Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (62 commits) powerpc/85xx: Fix signedness bug in cache-sram powerpc/fsl: 85xx: document cache sram bindings powerpc/fsl: define binding for fsl mpic interrupt controllers powerpc/fsl_msi: Handle msi-available-ranges better drivers/serial/ucc_uart.c: Add of_node_put to avoid memory leak powerpc/85xx: Fix SPE float to integer conversion failure powerpc/85xx: Update sata controller compatible for p1022ds board ATA: Add FSL sata v2 controller support powerpc/mpc8xxx_gpio: simplify searching for 'fsl, qoriq-gpio' compatiable powerpc/8xx: remove obsolete mgsuvd board powerpc/82xx: rename and update mgcoge board support powerpc/83xx: rename and update kmeter1 powerpc/85xx: Workaroudn e500 CPU erratum A005 powerpc/fsl_pci: Add support for FSL PCIe controllers v2.x powerpc/85xx: Fix writing to spin table 'cpu-release-addr' on ppc64e powerpc/pseries: Disable MSI using new interface if possible powerpc: Enable GENERIC_HARDIRQS_NO_DEPRECATED. powerpc: core irq_data conversion. powerpc: sysdev/xilinx_intc irq_data conversion. powerpc: sysdev/uic irq_data conversion. ... Fix up conflicts in arch/powerpc/sysdev/fsl_msi.c (due to getting rid of of_platform_driver in arch/powerpc)
This commit is contained in:
commit
0a95d92c00
|
@ -0,0 +1,20 @@
|
|||
* Freescale PQ3 and QorIQ based Cache SRAM
|
||||
|
||||
Freescale's mpc85xx and some QorIQ platforms provide an
|
||||
option of configuring a part of (or full) cache memory
|
||||
as SRAM. This cache SRAM representation in the device
|
||||
tree should be done as under:-
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : should be "fsl,p2020-cache-sram"
|
||||
- fsl,cache-sram-ctlr-handle : points to the L2 controller
|
||||
- reg : offset and length of the cache-sram.
|
||||
|
||||
Example:
|
||||
|
||||
cache-sram@fff00000 {
|
||||
fsl,cache-sram-ctlr-handle = <&L2>;
|
||||
reg = <0 0xfff00000 0 0x10000>;
|
||||
compatible = "fsl,p2020-cache-sram";
|
||||
};
|
|
@ -1,42 +1,211 @@
|
|||
* OpenPIC and its interrupt numbers on Freescale's e500/e600 cores
|
||||
=====================================================================
|
||||
Freescale MPIC Interrupt Controller Node
|
||||
Copyright (C) 2010,2011 Freescale Semiconductor Inc.
|
||||
=====================================================================
|
||||
|
||||
The OpenPIC specification does not specify which interrupt source has to
|
||||
become which interrupt number. This is up to the software implementation
|
||||
of the interrupt controller. The only requirement is that every
|
||||
interrupt source has to have an unique interrupt number / vector number.
|
||||
To accomplish this the current implementation assigns the number zero to
|
||||
the first source, the number one to the second source and so on until
|
||||
all interrupt sources have their unique number.
|
||||
Usually the assigned vector number equals the interrupt number mentioned
|
||||
in the documentation for a given core / CPU. This is however not true
|
||||
for the e500 cores (MPC85XX CPUs) where the documentation distinguishes
|
||||
between internal and external interrupt sources and starts counting at
|
||||
zero for both of them.
|
||||
The Freescale MPIC interrupt controller is found on all PowerQUICC
|
||||
and QorIQ processors and is compatible with the Open PIC. The
|
||||
notable difference from Open PIC binding is the addition of 2
|
||||
additional cells in the interrupt specifier defining interrupt type
|
||||
information.
|
||||
|
||||
So what to write for external interrupt source X or internal interrupt
|
||||
source Y into the device tree? Here is an example:
|
||||
PROPERTIES
|
||||
|
||||
The memory map for the interrupt controller in the MPC8544[0] shows,
|
||||
that the first interrupt source starts at 0x5_0000 (PIC Register Address
|
||||
Map-Interrupt Source Configuration Registers). This source becomes the
|
||||
number zero therefore:
|
||||
External interrupt 0 = interrupt number 0
|
||||
External interrupt 1 = interrupt number 1
|
||||
External interrupt 2 = interrupt number 2
|
||||
...
|
||||
Every interrupt number allocates 0x20 bytes register space. So to get
|
||||
its number it is sufficient to shift the lower 16bits to right by five.
|
||||
So for the external interrupt 10 we have:
|
||||
0x0140 >> 5 = 10
|
||||
- compatible
|
||||
Usage: required
|
||||
Value type: <string>
|
||||
Definition: Shall include "fsl,mpic". Freescale MPIC
|
||||
controllers compatible with this binding have Block
|
||||
Revision Registers BRR1 and BRR2 at offset 0x0 and
|
||||
0x10 in the MPIC.
|
||||
|
||||
After the external sources, the internal sources follow. The in core I2C
|
||||
controller on the MPC8544 for instance has the internal source number
|
||||
27. Oo obtain its interrupt number we take the lower 16bits of its memory
|
||||
address (0x5_0560) and shift it right:
|
||||
0x0560 >> 5 = 43
|
||||
- reg
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: A standard property. Specifies the physical
|
||||
offset and length of the device's registers within the
|
||||
CCSR address space.
|
||||
|
||||
Therefore the I2C device node for the MPC8544 CPU has to have the
|
||||
interrupt number 43 specified in the device tree.
|
||||
- interrupt-controller
|
||||
Usage: required
|
||||
Value type: <empty>
|
||||
Definition: Specifies that this node is an interrupt
|
||||
controller
|
||||
|
||||
[0] MPC8544E PowerQUICCTM III, Integrated Host Processor Family Reference Manual
|
||||
MPC8544ERM Rev. 1 10/2007
|
||||
- #interrupt-cells
|
||||
Usage: required
|
||||
Value type: <u32>
|
||||
Definition: Shall be 2 or 4. A value of 2 means that interrupt
|
||||
specifiers do not contain the interrupt-type or type-specific
|
||||
information cells.
|
||||
|
||||
- #address-cells
|
||||
Usage: required
|
||||
Value type: <u32>
|
||||
Definition: Shall be 0.
|
||||
|
||||
- pic-no-reset
|
||||
Usage: optional
|
||||
Value type: <empty>
|
||||
Definition: The presence of this property specifies that the
|
||||
MPIC must not be reset by the client program, and that
|
||||
the boot program has initialized all interrupt source
|
||||
configuration registers to a sane state-- masked or
|
||||
directed at other cores. This ensures that the client
|
||||
program will not receive interrupts for sources not belonging
|
||||
to the client. The presence of this property also mandates
|
||||
that any initialization related to interrupt sources shall
|
||||
be limited to sources explicitly referenced in the device tree.
|
||||
|
||||
INTERRUPT SPECIFIER DEFINITION
|
||||
|
||||
Interrupt specifiers consists of 4 cells encoded as
|
||||
follows:
|
||||
|
||||
<1st-cell> interrupt-number
|
||||
|
||||
Identifies the interrupt source. The meaning
|
||||
depends on the type of interrupt.
|
||||
|
||||
Note: If the interrupt-type cell is undefined
|
||||
(i.e. #interrupt-cells = 2), this cell
|
||||
should be interpreted the same as for
|
||||
interrupt-type 0-- i.e. an external or
|
||||
normal SoC device interrupt.
|
||||
|
||||
<2nd-cell> level-sense information, encoded as follows:
|
||||
0 = low-to-high edge triggered
|
||||
1 = active low level-sensitive
|
||||
2 = active high level-sensitive
|
||||
3 = high-to-low edge triggered
|
||||
|
||||
<3rd-cell> interrupt-type
|
||||
|
||||
The following types are supported:
|
||||
|
||||
0 = external or normal SoC device interrupt
|
||||
|
||||
The interrupt-number cell contains
|
||||
the SoC device interrupt number. The
|
||||
type-specific cell is undefined. The
|
||||
interrupt-number is derived from the
|
||||
MPIC a block of registers referred to as
|
||||
the "Interrupt Source Configuration Registers".
|
||||
Each source has 32-bytes of registers
|
||||
(vector/priority and destination) in this
|
||||
region. So interrupt 0 is at offset 0x0,
|
||||
interrupt 1 is at offset 0x20, and so on.
|
||||
|
||||
1 = error interrupt
|
||||
|
||||
The interrupt-number cell contains
|
||||
the SoC device interrupt number for
|
||||
the error interrupt. The type-specific
|
||||
cell identifies the specific error
|
||||
interrupt number.
|
||||
|
||||
2 = MPIC inter-processor interrupt (IPI)
|
||||
|
||||
The interrupt-number cell identifies
|
||||
the MPIC IPI number. The type-specific
|
||||
cell is undefined.
|
||||
|
||||
3 = MPIC timer interrupt
|
||||
|
||||
The interrupt-number cell identifies
|
||||
the MPIC timer number. The type-specific
|
||||
cell is undefined.
|
||||
|
||||
<4th-cell> type-specific information
|
||||
|
||||
The type-specific cell is encoded as follows:
|
||||
|
||||
- For interrupt-type 1 (error interrupt),
|
||||
the type-specific cell contains the
|
||||
bit number of the error interrupt in the
|
||||
Error Interrupt Summary Register.
|
||||
|
||||
EXAMPLE 1
|
||||
/*
|
||||
* mpic interrupt controller with 4 cells per specifier
|
||||
*/
|
||||
mpic: pic@40000 {
|
||||
compatible = "fsl,mpic";
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <4>;
|
||||
#address-cells = <0>;
|
||||
reg = <0x40000 0x40000>;
|
||||
};
|
||||
|
||||
EXAMPLE 2
|
||||
/*
|
||||
* The MPC8544 I2C controller node has an internal
|
||||
* interrupt number of 27. As per the reference manual
|
||||
* this corresponds to interrupt source configuration
|
||||
* registers at 0x5_0560.
|
||||
*
|
||||
* The interrupt source configuration registers begin
|
||||
* at 0x5_0000.
|
||||
*
|
||||
* To compute the interrupt specifier interrupt number
|
||||
*
|
||||
* 0x560 >> 5 = 43
|
||||
*
|
||||
* The interrupt source configuration registers begin
|
||||
* at 0x5_0000, and so the i2c vector/priority registers
|
||||
* are at 0x5_0560.
|
||||
*/
|
||||
i2c@3000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cell-index = <0>;
|
||||
compatible = "fsl-i2c";
|
||||
reg = <0x3000 0x100>;
|
||||
interrupts = <43 2>;
|
||||
interrupt-parent = <&mpic>;
|
||||
dfsrr;
|
||||
};
|
||||
|
||||
|
||||
EXAMPLE 3
|
||||
/*
|
||||
* Definition of a node defining the 4
|
||||
* MPIC IPI interrupts. Note the interrupt
|
||||
* type of 2.
|
||||
*/
|
||||
ipi@410a0 {
|
||||
compatible = "fsl,mpic-ipi";
|
||||
reg = <0x40040 0x10>;
|
||||
interrupts = <0 0 2 0
|
||||
1 0 2 0
|
||||
2 0 2 0
|
||||
3 0 2 0>;
|
||||
};
|
||||
|
||||
EXAMPLE 4
|
||||
/*
|
||||
* Definition of a node defining the MPIC
|
||||
* global timers. Note the interrupt
|
||||
* type of 3.
|
||||
*/
|
||||
timer0: timer@41100 {
|
||||
compatible = "fsl,mpic-global-timer";
|
||||
reg = <0x41100 0x100>;
|
||||
interrupts = <0 0 3 0
|
||||
1 0 3 0
|
||||
2 0 3 0
|
||||
3 0 3 0>;
|
||||
};
|
||||
|
||||
EXAMPLE 5
|
||||
/*
|
||||
* Definition of an error interrupt (interupt type 1).
|
||||
* SoC interrupt number is 16 and the specific error
|
||||
* interrupt bit in the error interrupt summary register
|
||||
* is 23.
|
||||
*/
|
||||
memory-controller@8000 {
|
||||
compatible = "fsl,p4080-memory-controller";
|
||||
reg = <0x8000 0x1000>;
|
||||
interrupts = <16 2 1 23>;
|
||||
};
|
||||
|
|
|
@ -5,14 +5,21 @@ Required properties:
|
|||
first is "fsl,CHIP-msi", where CHIP is the processor(mpc8610, mpc8572,
|
||||
etc.) and the second is "fsl,mpic-msi" or "fsl,ipic-msi" depending on
|
||||
the parent type.
|
||||
|
||||
- reg : should contain the address and the length of the shared message
|
||||
interrupt register set.
|
||||
|
||||
- msi-available-ranges: use <start count> style section to define which
|
||||
msi interrupt can be used in the 256 msi interrupts. This property is
|
||||
optional, without this, all the 256 MSI interrupts can be used.
|
||||
Each available range must begin and end on a multiple of 32 (i.e.
|
||||
no splitting an individual MSI register or the associated PIC interrupt).
|
||||
|
||||
- interrupts : each one of the interrupts here is one entry per 32 MSIs,
|
||||
and routed to the host interrupt controller. the interrupts should
|
||||
be set as edge sensitive.
|
||||
be set as edge sensitive. If msi-available-ranges is present, only
|
||||
the interrupts that correspond to available ranges shall be present.
|
||||
|
||||
- interrupt-parent: the phandle for the interrupt controller
|
||||
that services interrupts for this device. for 83xx cpu, the interrupts
|
||||
are routed to IPIC, and for 85xx/86xx cpu the interrupts are routed
|
||||
|
|
|
@ -626,6 +626,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
|||
disable= [IPV6]
|
||||
See Documentation/networking/ipv6.txt.
|
||||
|
||||
disable_ddw [PPC/PSERIES]
|
||||
Disable Dynamic DMA Window support. Use this if
|
||||
to workaround buggy firmware.
|
||||
|
||||
disable_ipv6= [IPV6]
|
||||
See Documentation/networking/ipv6.txt.
|
||||
|
||||
|
|
|
@ -134,6 +134,7 @@ config PPC
|
|||
select HAVE_GENERIC_HARDIRQS
|
||||
select HAVE_SPARSE_IRQ
|
||||
select IRQ_PER_CPU
|
||||
select GENERIC_HARDIRQS_NO_DEPRECATED
|
||||
|
||||
config EARLY_PRINTK
|
||||
bool
|
||||
|
|
|
@ -172,6 +172,19 @@
|
|||
interrupts = <0x1e 4>;
|
||||
};
|
||||
|
||||
USBOTG0: usbotg@bff80000 {
|
||||
compatible = "amcc,dwc-otg";
|
||||
reg = <0x4 0xbff80000 0x10000>;
|
||||
interrupt-parent = <&USBOTG0>;
|
||||
#interrupt-cells = <1>;
|
||||
#address-cells = <0>;
|
||||
#size-cells = <0>;
|
||||
interrupts = <0x0 0x1 0x2>;
|
||||
interrupt-map = </* USB-OTG */ 0x0 &UIC2 0x1c 0x4
|
||||
/* HIGH-POWER */ 0x1 &UIC1 0x1a 0x8
|
||||
/* DMA */ 0x2 &UIC0 0xc 0x4>;
|
||||
};
|
||||
|
||||
SATA0: sata@bffd1000 {
|
||||
compatible = "amcc,sata-460ex";
|
||||
reg = <4 0xbffd1000 0x800 4 0xbffd0800 0x400>;
|
||||
|
@ -233,6 +246,11 @@
|
|||
};
|
||||
};
|
||||
|
||||
cpld@2,0 {
|
||||
compatible = "amcc,ppc460ex-bcsr";
|
||||
reg = <2 0x0 0x9>;
|
||||
};
|
||||
|
||||
ndfc@3,0 {
|
||||
compatible = "ibm,ndfc";
|
||||
reg = <0x00000003 0x00000000 0x00002000>;
|
||||
|
@ -307,6 +325,12 @@
|
|||
interrupts = <0x3 0x4>;
|
||||
};
|
||||
|
||||
GPIO0: gpio@ef600b00 {
|
||||
compatible = "ibm,ppc4xx-gpio";
|
||||
reg = <0xef600b00 0x00000048>;
|
||||
gpio-controller;
|
||||
};
|
||||
|
||||
ZMII0: emac-zmii@ef600d00 {
|
||||
compatible = "ibm,zmii-460ex", "ibm,zmii";
|
||||
reg = <0xef600d00 0x0000000c>;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Keymile KMETER1 Device Tree Source
|
||||
*
|
||||
* 2008 DENX Software Engineering GmbH
|
||||
* 2008-2011 DENX Software Engineering GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
|
@ -70,11 +70,11 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cell-index = <0>;
|
||||
compatible = "fsl-i2c";
|
||||
compatible = "fsl,mpc8313-i2c","fsl-i2c";
|
||||
reg = <0x3000 0x100>;
|
||||
interrupts = <14 0x8>;
|
||||
interrupt-parent = <&ipic>;
|
||||
dfsrr;
|
||||
clock-frequency = <400000>;
|
||||
};
|
||||
|
||||
serial0: serial@4500 {
|
||||
|
@ -137,6 +137,13 @@
|
|||
compatible = "fsl,mpc8360-par_io";
|
||||
num-ports = <7>;
|
||||
|
||||
qe_pio_c: gpio-controller@30 {
|
||||
#gpio-cells = <2>;
|
||||
compatible = "fsl,mpc8360-qe-pario-bank",
|
||||
"fsl,mpc8323-qe-pario-bank";
|
||||
reg = <0x1430 0x18>;
|
||||
gpio-controller;
|
||||
};
|
||||
pio_ucc1: ucc_pin@0 {
|
||||
reg = <0>;
|
||||
|
||||
|
@ -472,7 +479,17 @@
|
|||
#address-cells = <0>;
|
||||
#interrupt-cells = <1>;
|
||||
reg = <0x80 0x80>;
|
||||
interrupts = <32 8 33 8>;
|
||||
big-endian;
|
||||
interrupts = <
|
||||
32 0x8
|
||||
33 0x8
|
||||
34 0x8
|
||||
35 0x8
|
||||
40 0x8
|
||||
41 0x8
|
||||
42 0x8
|
||||
43 0x8
|
||||
>;
|
||||
interrupt-parent = <&ipic>;
|
||||
};
|
||||
};
|
||||
|
@ -484,43 +501,31 @@
|
|||
compatible = "fsl,mpc8360-localbus", "fsl,pq2pro-localbus",
|
||||
"simple-bus";
|
||||
reg = <0xe0005000 0xd8>;
|
||||
ranges = <0 0 0xf0000000 0x04000000>; /* Filled in by U-Boot */
|
||||
ranges = <0 0 0xf0000000 0x04000000 /* LB 0 */
|
||||
1 0 0xe8000000 0x01000000 /* LB 1 */
|
||||
3 0 0xa0000000 0x10000000>; /* LB 3 */
|
||||
|
||||
flash@f0000000,0 {
|
||||
flash@0,0 {
|
||||
compatible = "cfi-flash";
|
||||
/*
|
||||
* The Intel P30 chip has 2 non-identical chips on
|
||||
* one die, so we need to define 2 separate regions
|
||||
* that are scanned by physmap_of independantly.
|
||||
*/
|
||||
reg = <0 0x00000000 0x02000000
|
||||
0 0x02000000 0x02000000>; /* Filled in by U-Boot */
|
||||
bank-width = <2>;
|
||||
reg = <0 0 0x04000000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
partition@0 {
|
||||
bank-width = <2>;
|
||||
partition@0 { /* 768KB */
|
||||
label = "u-boot";
|
||||
reg = <0 0x40000>;
|
||||
reg = <0 0xC0000>;
|
||||
};
|
||||
partition@40000 {
|
||||
partition@c0000 { /* 128KB */
|
||||
label = "env";
|
||||
reg = <0x40000 0x40000>;
|
||||
reg = <0xC0000 0x20000>;
|
||||
};
|
||||
partition@80000 {
|
||||
label = "dtb";
|
||||
reg = <0x80000 0x20000>;
|
||||
partition@e0000 { /* 128KB */
|
||||
label = "envred";
|
||||
reg = <0xE0000 0x20000>;
|
||||
};
|
||||
partition@a0000 {
|
||||
label = "kernel";
|
||||
reg = <0xa0000 0x300000>;
|
||||
};
|
||||
partition@3a0000 {
|
||||
label = "ramdisk";
|
||||
reg = <0x3a0000 0x800000>;
|
||||
};
|
||||
partition@ba0000 {
|
||||
label = "user";
|
||||
reg = <0xba0000 0x3460000>;
|
||||
partition@100000 { /* 64512KB */
|
||||
label = "ubi0";
|
||||
reg = <0x100000 0x3F00000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
/dts-v1/;
|
||||
/ {
|
||||
model = "MGCOGE";
|
||||
compatible = "keymile,mgcoge";
|
||||
compatible = "keymile,km82xx";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
|
@ -48,8 +48,10 @@
|
|||
reg = <0xf0010100 0x40>;
|
||||
|
||||
ranges = <0 0 0xfe000000 0x00400000
|
||||
5 0 0x50000000 0x20000000
|
||||
>; /* Filled in by U-Boot */
|
||||
1 0 0x30000000 0x00010000
|
||||
2 0 0x40000000 0x00010000
|
||||
5 0 0x50000000 0x04000000
|
||||
>;
|
||||
|
||||
flash@0,0 {
|
||||
compatible = "cfi-flash";
|
||||
|
@ -60,36 +62,32 @@
|
|||
device-width = <1>;
|
||||
partition@0 {
|
||||
label = "u-boot";
|
||||
reg = <0 0x40000>;
|
||||
reg = <0x00000 0xC0000>;
|
||||
};
|
||||
partition@40000 {
|
||||
partition@1 {
|
||||
label = "env";
|
||||
reg = <0x40000 0x20000>;
|
||||
reg = <0xC0000 0x20000>;
|
||||
};
|
||||
partition@60000 {
|
||||
label = "kernel";
|
||||
reg = <0x60000 0x220000>;
|
||||
partition@2 {
|
||||
label = "envred";
|
||||
reg = <0xE0000 0x20000>;
|
||||
};
|
||||
partition@280000 {
|
||||
label = "dtb";
|
||||
reg = <0x280000 0x20000>;
|
||||
partition@3 {
|
||||
label = "free";
|
||||
reg = <0x100000 0x300000>;
|
||||
};
|
||||
};
|
||||
|
||||
flash@5,0 {
|
||||
compatible = "cfi-flash";
|
||||
reg = <5 0x0 0x2000000>;
|
||||
reg = <5 0x00000000 0x02000000
|
||||
5 0x02000000 0x02000000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
bank-width = <2>;
|
||||
device-width = <2>;
|
||||
partition@0 {
|
||||
label = "ramdisk";
|
||||
reg = <0 0x7a0000>;
|
||||
};
|
||||
partition@7a0000 {
|
||||
label = "user";
|
||||
reg = <0x7a0000 0x1860000>;
|
||||
partition@app { /* 64 MBytes */
|
||||
label = "ubi0";
|
||||
reg = <0x00000000 0x04000000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -217,6 +215,13 @@
|
|||
};
|
||||
};
|
||||
|
||||
cpm2_pio_c: gpio-controller@10d40 {
|
||||
#gpio-cells = <2>;
|
||||
compatible = "fsl,cpm2-pario-bank";
|
||||
reg = <0x10d40 0x14>;
|
||||
gpio-controller;
|
||||
};
|
||||
|
||||
PIC: interrupt-controller@10c00 {
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-controller;
|
||||
|
|
|
@ -1,163 +0,0 @@
|
|||
/*
|
||||
* MGSUVD Device Tree Source
|
||||
*
|
||||
* Copyright 2008 DENX Software Engineering GmbH
|
||||
* Heiko Schocher <hs@denx.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/ {
|
||||
model = "MGSUVD";
|
||||
compatible = "keymile,mgsuvd";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
PowerPC,852@0 {
|
||||
device_type = "cpu";
|
||||
reg = <0>;
|
||||
d-cache-line-size = <16>;
|
||||
i-cache-line-size = <16>;
|
||||
d-cache-size = <8192>;
|
||||
i-cache-size = <8192>;
|
||||
timebase-frequency = <0>; /* Filled in by u-boot */
|
||||
bus-frequency = <0>; /* Filled in by u-boot */
|
||||
clock-frequency = <0>; /* Filled in by u-boot */
|
||||
interrupts = <15 2>; /* decrementer interrupt */
|
||||
interrupt-parent = <&PIC>;
|
||||
};
|
||||
};
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
reg = <00000000 0x4000000>; /* Filled in by u-boot */
|
||||
};
|
||||
|
||||
localbus@fff00100 {
|
||||
compatible = "fsl,mpc852-localbus", "fsl,pq1-localbus", "simple-bus";
|
||||
#address-cells = <2>;
|
||||
#size-cells = <1>;
|
||||
reg = <0xfff00100 0x40>;
|
||||
|
||||
ranges = <0 0 0xf0000000 0x01000000>; /* Filled in by u-boot */
|
||||
|
||||
flash@0,0 {
|
||||
compatible = "cfi-flash";
|
||||
reg = <0 0 0x1000000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
bank-width = <1>;
|
||||
device-width = <1>;
|
||||
partition@0 {
|
||||
label = "u-boot";
|
||||
reg = <0 0x80000>;
|
||||
};
|
||||
partition@80000 {
|
||||
label = "env";
|
||||
reg = <0x80000 0x20000>;
|
||||
};
|
||||
partition@a0000 {
|
||||
label = "kernel";
|
||||
reg = <0xa0000 0x1e0000>;
|
||||
};
|
||||
partition@280000 {
|
||||
label = "dtb";
|
||||
reg = <0x280000 0x20000>;
|
||||
};
|
||||
partition@2a0000 {
|
||||
label = "root";
|
||||
reg = <0x2a0000 0x500000>;
|
||||
};
|
||||
partition@7a0000 {
|
||||
label = "user";
|
||||
reg = <0x7a0000 0x860000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
soc@fff00000 {
|
||||
compatible = "fsl,mpc852", "fsl,pq1-soc", "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
device_type = "soc";
|
||||
ranges = <0 0xfff00000 0x00004000>;
|
||||
|
||||
PIC: interrupt-controller@0 {
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
reg = <0 24>;
|
||||
compatible = "fsl,mpc852-pic", "fsl,pq1-pic";
|
||||
};
|
||||
|
||||
cpm@9c0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "fsl,mpc852-cpm", "fsl,cpm1", "simple-bus";
|
||||
interrupts = <0>; /* cpm error interrupt */
|
||||
interrupt-parent = <&CPM_PIC>;
|
||||
reg = <0x9c0 10>;
|
||||
ranges;
|
||||
|
||||
muram@2000 {
|
||||
compatible = "fsl,cpm-muram";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0 0x2000 0x2000>;
|
||||
|
||||
data@0 {
|
||||
compatible = "fsl,cpm-muram-data";
|
||||
reg = <0x800 0x1800>;
|
||||
};
|
||||
};
|
||||
|
||||
brg@9f0 {
|
||||
compatible = "fsl,mpc852-brg",
|
||||
"fsl,cpm1-brg",
|
||||
"fsl,cpm-brg";
|
||||
reg = <0x9f0 0x10>;
|
||||
clock-frequency = <0>; /* Filled in by u-boot */
|
||||
};
|
||||
|
||||
CPM_PIC: interrupt-controller@930 {
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
interrupts = <5 2 0 2>;
|
||||
interrupt-parent = <&PIC>;
|
||||
reg = <0x930 0x20>;
|
||||
compatible = "fsl,cpm1-pic";
|
||||
};
|
||||
|
||||
/* MON-1 */
|
||||
serial@a80 {
|
||||
device_type = "serial";
|
||||
compatible = "fsl,cpm1-smc-uart";
|
||||
reg = <0xa80 0x10 0x3fc0 0x40>;
|
||||
interrupts = <4>;
|
||||
interrupt-parent = <&CPM_PIC>;
|
||||
fsl,cpm-brg = <1>;
|
||||
fsl,cpm-command = <0x0090>;
|
||||
current-speed = <0>; /* Filled in by u-boot */
|
||||
};
|
||||
|
||||
ethernet@a40 {
|
||||
device_type = "network";
|
||||
compatible = "fsl,mpc866-scc-enet",
|
||||
"fsl,cpm1-scc-enet";
|
||||
reg = <0xa40 0x18 0x3e00 0x100>;
|
||||
local-mac-address = [ 00 00 00 00 00 00 ]; /* Filled in by u-boot */
|
||||
interrupts = <28>;
|
||||
interrupt-parent = <&CPM_PIC>;
|
||||
fsl,cpm-command = <0x80>;
|
||||
fixed-link = <0 0 10 0 0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -475,14 +475,14 @@
|
|||
};
|
||||
|
||||
sata@18000 {
|
||||
compatible = "fsl,mpc8536-sata", "fsl,pq-sata";
|
||||
compatible = "fsl,p1022-sata", "fsl,pq-sata-v2";
|
||||
reg = <0x18000 0x1000>;
|
||||
cell-index = <1>;
|
||||
interrupts = <74 0x2>;
|
||||
};
|
||||
|
||||
sata@19000 {
|
||||
compatible = "fsl,mpc8536-sata", "fsl,pq-sata";
|
||||
compatible = "fsl,p1022-sata", "fsl,pq-sata-v2";
|
||||
reg = <0x19000 0x1000>;
|
||||
cell-index = <2>;
|
||||
interrupts = <41 0x2>;
|
||||
|
|
|
@ -2,6 +2,7 @@ CONFIG_EXPERIMENTAL=y
|
|||
# CONFIG_SWAP is not set
|
||||
CONFIG_SYSVIPC=y
|
||||
CONFIG_POSIX_MQUEUE=y
|
||||
CONFIG_SPARSE_IRQ=y
|
||||
CONFIG_LOG_BUF_SHIFT=14
|
||||
CONFIG_EXPERT=y
|
||||
# CONFIG_HOTPLUG is not set
|
||||
|
@ -18,7 +19,6 @@ CONFIG_KMETER1=y
|
|||
CONFIG_NO_HZ=y
|
||||
CONFIG_HIGH_RES_TIMERS=y
|
||||
CONFIG_PREEMPT=y
|
||||
CONFIG_SPARSE_IRQ=y
|
||||
# CONFIG_SECCOMP is not set
|
||||
CONFIG_NET=y
|
||||
CONFIG_PACKET=y
|
||||
|
@ -37,7 +37,6 @@ CONFIG_MTD=y
|
|||
CONFIG_MTD_CONCAT=y
|
||||
CONFIG_MTD_PARTITIONS=y
|
||||
CONFIG_MTD_CMDLINE_PARTS=y
|
||||
CONFIG_MTD_OF_PARTS=y
|
||||
CONFIG_MTD_CHAR=y
|
||||
CONFIG_MTD_BLOCK=y
|
||||
CONFIG_MTD_CFI=y
|
||||
|
@ -49,13 +48,12 @@ CONFIG_MTD_UBI=y
|
|||
CONFIG_MTD_UBI_GLUEBI=y
|
||||
CONFIG_MTD_UBI_DEBUG=y
|
||||
CONFIG_PROC_DEVICETREE=y
|
||||
# CONFIG_MISC_DEVICES is not set
|
||||
CONFIG_NETDEVICES=y
|
||||
CONFIG_DUMMY=y
|
||||
CONFIG_TUN=y
|
||||
CONFIG_MII=y
|
||||
CONFIG_MARVELL_PHY=y
|
||||
CONFIG_NET_ETHERNET=y
|
||||
CONFIG_MII=y
|
||||
CONFIG_UCC_GETH=y
|
||||
# CONFIG_NETDEV_10000 is not set
|
||||
CONFIG_WAN=y
|
||||
|
@ -77,7 +75,6 @@ CONFIG_I2C_MPC=y
|
|||
# CONFIG_USB_SUPPORT is not set
|
||||
CONFIG_UIO=y
|
||||
# CONFIG_DNOTIFY is not set
|
||||
CONFIG_INOTIFY=y
|
||||
CONFIG_TMPFS=y
|
||||
CONFIG_JFFS2_FS=y
|
||||
CONFIG_NFS_FS=y
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
CONFIG_SYSVIPC=y
|
||||
CONFIG_SPARSE_IRQ=y
|
||||
CONFIG_IKCONFIG=y
|
||||
CONFIG_IKCONFIG_PROC=y
|
||||
CONFIG_LOG_BUF_SHIFT=14
|
||||
|
@ -10,7 +11,6 @@ CONFIG_SLAB=y
|
|||
CONFIG_PPC_82xx=y
|
||||
CONFIG_MGCOGE=y
|
||||
CONFIG_BINFMT_MISC=y
|
||||
CONFIG_SPARSE_IRQ=y
|
||||
# CONFIG_SECCOMP is not set
|
||||
CONFIG_NET=y
|
||||
CONFIG_PACKET=y
|
||||
|
@ -30,7 +30,6 @@ CONFIG_MTD=y
|
|||
CONFIG_MTD_CONCAT=y
|
||||
CONFIG_MTD_PARTITIONS=y
|
||||
CONFIG_MTD_CMDLINE_PARTS=y
|
||||
CONFIG_MTD_OF_PARTS=y
|
||||
CONFIG_MTD_CHAR=y
|
||||
CONFIG_MTD_BLKDEVS=y
|
||||
CONFIG_MTD_CFI=y
|
||||
|
@ -43,7 +42,6 @@ CONFIG_MTD_PHYSMAP_OF=y
|
|||
CONFIG_PROC_DEVICETREE=y
|
||||
CONFIG_BLK_DEV_LOOP=y
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
# CONFIG_MISC_DEVICES is not set
|
||||
# CONFIG_MACINTOSH_DRIVERS is not set
|
||||
CONFIG_NETDEVICES=y
|
||||
CONFIG_FIXED_PHY=y
|
||||
|
@ -67,7 +65,6 @@ CONFIG_EXT2_FS=y
|
|||
CONFIG_EXT3_FS=y
|
||||
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
|
||||
# CONFIG_EXT3_FS_XATTR is not set
|
||||
CONFIG_INOTIFY=y
|
||||
CONFIG_AUTOFS4_FS=y
|
||||
CONFIG_PROC_KCORE=y
|
||||
CONFIG_TMPFS=y
|
||||
|
@ -88,13 +85,9 @@ CONFIG_DEBUG_FS=y
|
|||
CONFIG_DEBUG_KERNEL=y
|
||||
# CONFIG_SCHED_DEBUG is not set
|
||||
CONFIG_DEBUG_INFO=y
|
||||
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
|
||||
CONFIG_SYSCTL_SYSCALL_CHECK=y
|
||||
CONFIG_BDI_SWITCH=y
|
||||
CONFIG_CRYPTO_CBC=y
|
||||
CONFIG_CRYPTO_ECB=y
|
||||
CONFIG_CRYPTO_PCBC=y
|
||||
CONFIG_CRYPTO_MD5=y
|
||||
CONFIG_CRYPTO_DES=y
|
||||
# CONFIG_CRYPTO_ANSI_CPRNG is not set
|
||||
# CONFIG_CRYPTO_HW is not set
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
CONFIG_PPC_8xx=y
|
||||
CONFIG_EXPERIMENTAL=y
|
||||
# CONFIG_SWAP is not set
|
||||
CONFIG_SYSVIPC=y
|
||||
CONFIG_BLK_DEV_INITRD=y
|
||||
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
|
||||
CONFIG_EXPERT=y
|
||||
# CONFIG_SYSCTL_SYSCALL is not set
|
||||
# CONFIG_HOTPLUG is not set
|
||||
# CONFIG_BUG is not set
|
||||
# CONFIG_BASE_FULL is not set
|
||||
# CONFIG_EPOLL is not set
|
||||
# CONFIG_VM_EVENT_COUNTERS is not set
|
||||
CONFIG_SLAB=y
|
||||
# CONFIG_BLK_DEV_BSG is not set
|
||||
CONFIG_PPC_MGSUVD=y
|
||||
CONFIG_8xx_COPYBACK=y
|
||||
CONFIG_8xx_CPU6=y
|
||||
CONFIG_I2C_SPI_SMC1_UCODE_PATCH=y
|
||||
CONFIG_HZ_1000=y
|
||||
CONFIG_MATH_EMULATION=y
|
||||
CONFIG_SPARSE_IRQ=y
|
||||
# CONFIG_SECCOMP is not set
|
||||
CONFIG_NET=y
|
||||
CONFIG_PACKET=y
|
||||
CONFIG_UNIX=y
|
||||
CONFIG_INET=y
|
||||
CONFIG_IP_MULTICAST=y
|
||||
CONFIG_IP_PNP=y
|
||||
CONFIG_SYN_COOKIES=y
|
||||
# CONFIG_INET_LRO is not set
|
||||
# CONFIG_IPV6 is not set
|
||||
CONFIG_MTD=y
|
||||
CONFIG_MTD_PARTITIONS=y
|
||||
CONFIG_MTD_CMDLINE_PARTS=y
|
||||
CONFIG_MTD_OF_PARTS=y
|
||||
CONFIG_MTD_CHAR=y
|
||||
CONFIG_MTD_BLOCK=y
|
||||
CONFIG_MTD_CFI=y
|
||||
CONFIG_MTD_CFI_ADV_OPTIONS=y
|
||||
CONFIG_MTD_CFI_GEOMETRY=y
|
||||
# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
|
||||
CONFIG_MTD_CFI_INTELEXT=y
|
||||
CONFIG_MTD_CFI_AMDSTD=y
|
||||
CONFIG_MTD_CFI_STAA=y
|
||||
CONFIG_MTD_PHYSMAP_OF=y
|
||||
CONFIG_BLK_DEV_LOOP=y
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
# CONFIG_MISC_DEVICES is not set
|
||||
CONFIG_NETDEVICES=y
|
||||
CONFIG_FIXED_PHY=y
|
||||
CONFIG_NET_ETHERNET=y
|
||||
CONFIG_FS_ENET=y
|
||||
# CONFIG_FS_ENET_HAS_FEC is not set
|
||||
# CONFIG_NETDEV_1000 is not set
|
||||
# CONFIG_NETDEV_10000 is not set
|
||||
# CONFIG_INPUT is not set
|
||||
# CONFIG_SERIO is not set
|
||||
# CONFIG_VT is not set
|
||||
CONFIG_SERIAL_CPM=y
|
||||
CONFIG_SERIAL_CPM_CONSOLE=y
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
CONFIG_GEN_RTC=y
|
||||
# CONFIG_HWMON is not set
|
||||
# CONFIG_USB_SUPPORT is not set
|
||||
CONFIG_EXT2_FS=y
|
||||
CONFIG_EXT2_FS_XATTR=y
|
||||
CONFIG_EXT3_FS=y
|
||||
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
|
||||
CONFIG_INOTIFY=y
|
||||
CONFIG_TMPFS=y
|
||||
CONFIG_JFFS2_FS=y
|
||||
CONFIG_CRAMFS=y
|
||||
CONFIG_NFS_FS=y
|
||||
CONFIG_NFS_V3=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_PARTITION_ADVANCED=y
|
||||
CONFIG_CRC_CCITT=y
|
||||
CONFIG_DEBUG_FS=y
|
||||
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
|
||||
# CONFIG_CRYPTO_ANSI_CPRNG is not set
|
|
@ -154,6 +154,7 @@ extern const char *powerpc_base_platform;
|
|||
#define CPU_FTR_NAP_DISABLE_L2_PR ASM_CONST(0x0000000000002000)
|
||||
#define CPU_FTR_DUAL_PLL_750FX ASM_CONST(0x0000000000004000)
|
||||
#define CPU_FTR_NO_DPM ASM_CONST(0x0000000000008000)
|
||||
#define CPU_FTR_476_DD2 ASM_CONST(0x0000000000010000)
|
||||
#define CPU_FTR_NEED_COHERENT ASM_CONST(0x0000000000020000)
|
||||
#define CPU_FTR_NO_BTIC ASM_CONST(0x0000000000040000)
|
||||
#define CPU_FTR_NODSISRALIGN ASM_CONST(0x0000000000100000)
|
||||
|
@ -465,7 +466,7 @@ enum {
|
|||
CPU_FTRS_44X | CPU_FTRS_440x6 |
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_47x
|
||||
CPU_FTRS_47X |
|
||||
CPU_FTRS_47X | CPU_FTR_476_DD2 |
|
||||
#endif
|
||||
#ifdef CONFIG_E200
|
||||
CPU_FTRS_E200 |
|
||||
|
|
|
@ -141,6 +141,8 @@ static inline bool arch_irqs_disabled(void)
|
|||
|
||||
#endif /* CONFIG_PPC64 */
|
||||
|
||||
#define ARCH_IRQ_INIT_FLAGS IRQ_NOREQUEST
|
||||
|
||||
/*
|
||||
* interrupt-retrigger: should we handle this via lost interrupts and IPIs
|
||||
* or should we not care like we do now ? --BenH.
|
||||
|
|
|
@ -467,11 +467,11 @@ extern void mpic_request_ipis(void);
|
|||
void smp_mpic_message_pass(int target, int msg);
|
||||
|
||||
/* Unmask a specific virq */
|
||||
extern void mpic_unmask_irq(unsigned int irq);
|
||||
extern void mpic_unmask_irq(struct irq_data *d);
|
||||
/* Mask a specific virq */
|
||||
extern void mpic_mask_irq(unsigned int irq);
|
||||
extern void mpic_mask_irq(struct irq_data *d);
|
||||
/* EOI a specific virq */
|
||||
extern void mpic_end_irq(unsigned int irq);
|
||||
extern void mpic_end_irq(struct irq_data *d);
|
||||
|
||||
/* Fetch interrupt from a given mpic */
|
||||
extern unsigned int mpic_get_one_irq(struct mpic *mpic);
|
||||
|
|
|
@ -51,7 +51,8 @@ static inline int mmio_nvram_init(void)
|
|||
extern int __init nvram_scan_partitions(void);
|
||||
extern loff_t nvram_create_partition(const char *name, int sig,
|
||||
int req_size, int min_size);
|
||||
extern int nvram_remove_partition(const char *name, int sig);
|
||||
extern int nvram_remove_partition(const char *name, int sig,
|
||||
const char *exceptions[]);
|
||||
extern int nvram_get_partition_size(loff_t data_index);
|
||||
extern loff_t nvram_find_partition(const char *name, int sig, int *out_size);
|
||||
|
||||
|
|
|
@ -170,6 +170,7 @@ extern int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long addre
|
|||
#define pgprot_cached_wthru(prot) (__pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL) | \
|
||||
_PAGE_COHERENT | _PAGE_WRITETHRU))
|
||||
|
||||
#define pgprot_writecombine pgprot_noncached_wc
|
||||
|
||||
struct file;
|
||||
extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
|
||||
|
|
|
@ -81,7 +81,7 @@ int qe_ic_set_high_priority(unsigned int virq, unsigned int priority, int high);
|
|||
static inline void qe_ic_cascade_low_ipic(unsigned int irq,
|
||||
struct irq_desc *desc)
|
||||
{
|
||||
struct qe_ic *qe_ic = desc->handler_data;
|
||||
struct qe_ic *qe_ic = get_irq_desc_data(desc);
|
||||
unsigned int cascade_irq = qe_ic_get_low_irq(qe_ic);
|
||||
|
||||
if (cascade_irq != NO_IRQ)
|
||||
|
@ -91,7 +91,7 @@ static inline void qe_ic_cascade_low_ipic(unsigned int irq,
|
|||
static inline void qe_ic_cascade_high_ipic(unsigned int irq,
|
||||
struct irq_desc *desc)
|
||||
{
|
||||
struct qe_ic *qe_ic = desc->handler_data;
|
||||
struct qe_ic *qe_ic = get_irq_desc_data(desc);
|
||||
unsigned int cascade_irq = qe_ic_get_high_irq(qe_ic);
|
||||
|
||||
if (cascade_irq != NO_IRQ)
|
||||
|
@ -101,32 +101,35 @@ static inline void qe_ic_cascade_high_ipic(unsigned int irq,
|
|||
static inline void qe_ic_cascade_low_mpic(unsigned int irq,
|
||||
struct irq_desc *desc)
|
||||
{
|
||||
struct qe_ic *qe_ic = desc->handler_data;
|
||||
struct qe_ic *qe_ic = get_irq_desc_data(desc);
|
||||
unsigned int cascade_irq = qe_ic_get_low_irq(qe_ic);
|
||||
struct irq_chip *chip = get_irq_desc_chip(desc);
|
||||
|
||||
if (cascade_irq != NO_IRQ)
|
||||
generic_handle_irq(cascade_irq);
|
||||
|
||||
desc->chip->eoi(irq);
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
}
|
||||
|
||||
static inline void qe_ic_cascade_high_mpic(unsigned int irq,
|
||||
struct irq_desc *desc)
|
||||
{
|
||||
struct qe_ic *qe_ic = desc->handler_data;
|
||||
struct qe_ic *qe_ic = get_irq_desc_data(desc);
|
||||
unsigned int cascade_irq = qe_ic_get_high_irq(qe_ic);
|
||||
struct irq_chip *chip = get_irq_desc_chip(desc);
|
||||
|
||||
if (cascade_irq != NO_IRQ)
|
||||
generic_handle_irq(cascade_irq);
|
||||
|
||||
desc->chip->eoi(irq);
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
}
|
||||
|
||||
static inline void qe_ic_cascade_muxed_mpic(unsigned int irq,
|
||||
struct irq_desc *desc)
|
||||
{
|
||||
struct qe_ic *qe_ic = desc->handler_data;
|
||||
struct qe_ic *qe_ic = get_irq_desc_data(desc);
|
||||
unsigned int cascade_irq;
|
||||
struct irq_chip *chip = get_irq_desc_chip(desc);
|
||||
|
||||
cascade_irq = qe_ic_get_high_irq(qe_ic);
|
||||
if (cascade_irq == NO_IRQ)
|
||||
|
@ -135,7 +138,7 @@ static inline void qe_ic_cascade_muxed_mpic(unsigned int irq,
|
|||
if (cascade_irq != NO_IRQ)
|
||||
generic_handle_irq(cascade_irq);
|
||||
|
||||
desc->chip->eoi(irq);
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
}
|
||||
|
||||
#endif /* _ASM_POWERPC_QE_IC_H */
|
||||
|
|
|
@ -170,6 +170,16 @@
|
|||
#define SPEFSCR_FRMC 0x00000003 /* Embedded FP rounding mode control */
|
||||
|
||||
/* Special Purpose Registers (SPRNs)*/
|
||||
|
||||
#ifdef CONFIG_40x
|
||||
#define SPRN_PID 0x3B1 /* Process ID */
|
||||
#else
|
||||
#define SPRN_PID 0x030 /* Process ID */
|
||||
#ifdef CONFIG_BOOKE
|
||||
#define SPRN_PID0 SPRN_PID/* Process ID Register 0 */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define SPRN_CTR 0x009 /* Count Register */
|
||||
#define SPRN_DSCR 0x11
|
||||
#define SPRN_CTRLF 0x088
|
||||
|
@ -852,6 +862,8 @@
|
|||
#define PVR_7450 0x80000000
|
||||
#define PVR_8540 0x80200000
|
||||
#define PVR_8560 0x80200000
|
||||
#define PVR_VER_E500V1 0x8020
|
||||
#define PVR_VER_E500V2 0x8021
|
||||
/*
|
||||
* For the 8xx processors, all of them report the same PVR family for
|
||||
* the PowerPC core. The various versions of these processors must be
|
||||
|
|
|
@ -150,8 +150,6 @@
|
|||
* or IBM 40x.
|
||||
*/
|
||||
#ifdef CONFIG_BOOKE
|
||||
#define SPRN_PID 0x030 /* Process ID */
|
||||
#define SPRN_PID0 SPRN_PID/* Process ID Register 0 */
|
||||
#define SPRN_CSRR0 0x03A /* Critical Save and Restore Register 0 */
|
||||
#define SPRN_CSRR1 0x03B /* Critical Save and Restore Register 1 */
|
||||
#define SPRN_DEAR 0x03D /* Data Error Address Register */
|
||||
|
@ -168,7 +166,6 @@
|
|||
#define SPRN_TCR 0x154 /* Timer Control Register */
|
||||
#endif /* Book E */
|
||||
#ifdef CONFIG_40x
|
||||
#define SPRN_PID 0x3B1 /* Process ID */
|
||||
#define SPRN_DBCR1 0x3BD /* Debug Control Register 1 */
|
||||
#define SPRN_ESR 0x3D4 /* Exception Syndrome Register */
|
||||
#define SPRN_DEAR 0x3D5 /* Data Error Address Register */
|
||||
|
|
|
@ -1811,11 +1811,11 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
|||
.machine_check = machine_check_440A,
|
||||
.platform = "ppc440",
|
||||
},
|
||||
{ /* 476 core */
|
||||
.pvr_mask = 0xffff0000,
|
||||
.pvr_value = 0x11a50000,
|
||||
{ /* 476 DD2 core */
|
||||
.pvr_mask = 0xffffffff,
|
||||
.pvr_value = 0x11a52080,
|
||||
.cpu_name = "476",
|
||||
.cpu_features = CPU_FTRS_47X,
|
||||
.cpu_features = CPU_FTRS_47X | CPU_FTR_476_DD2,
|
||||
.cpu_user_features = COMMON_USER_BOOKE |
|
||||
PPC_FEATURE_HAS_FPU,
|
||||
.mmu_features = MMU_FTR_TYPE_47x |
|
||||
|
@ -1839,6 +1839,20 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
|||
.machine_check = machine_check_47x,
|
||||
.platform = "ppc470",
|
||||
},
|
||||
{ /* 476 others */
|
||||
.pvr_mask = 0xffff0000,
|
||||
.pvr_value = 0x11a50000,
|
||||
.cpu_name = "476",
|
||||
.cpu_features = CPU_FTRS_47X,
|
||||
.cpu_user_features = COMMON_USER_BOOKE |
|
||||
PPC_FEATURE_HAS_FPU,
|
||||
.mmu_features = MMU_FTR_TYPE_47x |
|
||||
MMU_FTR_USE_TLBIVAX_BCAST | MMU_FTR_LOCK_BCAST_INVAL,
|
||||
.icache_bsize = 32,
|
||||
.dcache_bsize = 128,
|
||||
.machine_check = machine_check_47x,
|
||||
.platform = "ppc470",
|
||||
},
|
||||
{ /* default match */
|
||||
.pvr_mask = 0x00000000,
|
||||
.pvr_value = 0x00000000,
|
||||
|
|
|
@ -237,6 +237,7 @@ int show_interrupts(struct seq_file *p, void *v)
|
|||
int i = *(loff_t *) v, j, prec;
|
||||
struct irqaction *action;
|
||||
struct irq_desc *desc;
|
||||
struct irq_chip *chip;
|
||||
|
||||
if (i > nr_irqs)
|
||||
return 0;
|
||||
|
@ -270,8 +271,9 @@ int show_interrupts(struct seq_file *p, void *v)
|
|||
for_each_online_cpu(j)
|
||||
seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
|
||||
|
||||
if (desc->chip)
|
||||
seq_printf(p, " %-16s", desc->chip->name);
|
||||
chip = get_irq_desc_chip(desc);
|
||||
if (chip)
|
||||
seq_printf(p, " %-16s", chip->name);
|
||||
else
|
||||
seq_printf(p, " %-16s", "None");
|
||||
seq_printf(p, " %-8s", (desc->status & IRQ_LEVEL) ? "Level" : "Edge");
|
||||
|
@ -313,6 +315,8 @@ void fixup_irqs(const struct cpumask *map)
|
|||
alloc_cpumask_var(&mask, GFP_KERNEL);
|
||||
|
||||
for_each_irq(irq) {
|
||||
struct irq_chip *chip;
|
||||
|
||||
desc = irq_to_desc(irq);
|
||||
if (!desc)
|
||||
continue;
|
||||
|
@ -320,13 +324,15 @@ void fixup_irqs(const struct cpumask *map)
|
|||
if (desc->status & IRQ_PER_CPU)
|
||||
continue;
|
||||
|
||||
cpumask_and(mask, desc->affinity, map);
|
||||
chip = get_irq_desc_chip(desc);
|
||||
|
||||
cpumask_and(mask, desc->irq_data.affinity, map);
|
||||
if (cpumask_any(mask) >= nr_cpu_ids) {
|
||||
printk("Breaking affinity for irq %i\n", irq);
|
||||
cpumask_copy(mask, map);
|
||||
}
|
||||
if (desc->chip->set_affinity)
|
||||
desc->chip->set_affinity(irq, mask);
|
||||
if (chip->irq_set_affinity)
|
||||
chip->irq_set_affinity(&desc->irq_data, mask, true);
|
||||
else if (desc->action && !(warned++))
|
||||
printk("Cannot set affinity for irq %i\n", irq);
|
||||
}
|
||||
|
@ -678,16 +684,15 @@ void irq_set_virq_count(unsigned int count)
|
|||
static int irq_setup_virq(struct irq_host *host, unsigned int virq,
|
||||
irq_hw_number_t hwirq)
|
||||
{
|
||||
struct irq_desc *desc;
|
||||
int res;
|
||||
|
||||
desc = irq_to_desc_alloc_node(virq, 0);
|
||||
if (!desc) {
|
||||
res = irq_alloc_desc_at(virq, 0);
|
||||
if (res != virq) {
|
||||
pr_debug("irq: -> allocating desc failed\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Clear IRQ_NOREQUEST flag */
|
||||
desc->status &= ~IRQ_NOREQUEST;
|
||||
irq_clear_status_flags(virq, IRQ_NOREQUEST);
|
||||
|
||||
/* map it */
|
||||
smp_wmb();
|
||||
|
@ -696,11 +701,13 @@ static int irq_setup_virq(struct irq_host *host, unsigned int virq,
|
|||
|
||||
if (host->ops->map(host, virq, hwirq)) {
|
||||
pr_debug("irq: -> mapping failed, freeing\n");
|
||||
goto error;
|
||||
goto errdesc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
errdesc:
|
||||
irq_free_descs(virq, 1);
|
||||
error:
|
||||
irq_free_virt(virq, 1);
|
||||
return -1;
|
||||
|
@ -879,9 +886,9 @@ void irq_dispose_mapping(unsigned int virq)
|
|||
smp_mb();
|
||||
irq_map[virq].hwirq = host->inval_irq;
|
||||
|
||||
/* Set some flags */
|
||||
irq_to_desc(virq)->status |= IRQ_NOREQUEST;
|
||||
irq_set_status_flags(virq, IRQ_NOREQUEST);
|
||||
|
||||
irq_free_descs(virq, 1);
|
||||
/* Free it */
|
||||
irq_free_virt(virq, 1);
|
||||
}
|
||||
|
@ -1074,21 +1081,6 @@ void irq_free_virt(unsigned int virq, unsigned int count)
|
|||
|
||||
int arch_early_irq_init(void)
|
||||
{
|
||||
struct irq_desc *desc;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NR_IRQS; i++) {
|
||||
desc = irq_to_desc(i);
|
||||
if (desc)
|
||||
desc->status |= IRQ_NOREQUEST;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arch_init_chip_data(struct irq_desc *desc, int node)
|
||||
{
|
||||
desc->status |= IRQ_NOREQUEST;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1159,11 +1151,14 @@ static int virq_debug_show(struct seq_file *m, void *private)
|
|||
raw_spin_lock_irqsave(&desc->lock, flags);
|
||||
|
||||
if (desc->action && desc->action->handler) {
|
||||
struct irq_chip *chip;
|
||||
|
||||
seq_printf(m, "%5d ", i);
|
||||
seq_printf(m, "0x%05lx ", virq_to_hw(i));
|
||||
|
||||
if (desc->chip && desc->chip->name)
|
||||
p = desc->chip->name;
|
||||
chip = get_irq_desc_chip(desc);
|
||||
if (chip && chip->name)
|
||||
p = chip->name;
|
||||
else
|
||||
p = none;
|
||||
seq_printf(m, "%-15s ", p);
|
||||
|
|
|
@ -26,20 +26,23 @@ void machine_kexec_mask_interrupts(void) {
|
|||
|
||||
for_each_irq(i) {
|
||||
struct irq_desc *desc = irq_to_desc(i);
|
||||
struct irq_chip *chip;
|
||||
|
||||
if (!desc || !desc->chip)
|
||||
if (!desc)
|
||||
continue;
|
||||
|
||||
if (desc->chip->eoi &&
|
||||
desc->status & IRQ_INPROGRESS)
|
||||
desc->chip->eoi(i);
|
||||
chip = get_irq_desc_chip(desc);
|
||||
if (!chip)
|
||||
continue;
|
||||
|
||||
if (desc->chip->mask)
|
||||
desc->chip->mask(i);
|
||||
if (chip->irq_eoi && desc->status & IRQ_INPROGRESS)
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
|
||||
if (desc->chip->disable &&
|
||||
!(desc->status & IRQ_DISABLED))
|
||||
desc->chip->disable(i);
|
||||
if (chip->irq_mask)
|
||||
chip->irq_mask(&desc->irq_data);
|
||||
|
||||
if (chip->irq_disable && !(desc->status & IRQ_DISABLED))
|
||||
chip->irq_disable(&desc->irq_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -237,22 +237,45 @@ static unsigned char __init nvram_checksum(struct nvram_header *p)
|
|||
return c_sum;
|
||||
}
|
||||
|
||||
/*
|
||||
* Per the criteria passed via nvram_remove_partition(), should this
|
||||
* partition be removed? 1=remove, 0=keep
|
||||
*/
|
||||
static int nvram_can_remove_partition(struct nvram_partition *part,
|
||||
const char *name, int sig, const char *exceptions[])
|
||||
{
|
||||
if (part->header.signature != sig)
|
||||
return 0;
|
||||
if (name) {
|
||||
if (strncmp(name, part->header.name, 12))
|
||||
return 0;
|
||||
} else if (exceptions) {
|
||||
const char **except;
|
||||
for (except = exceptions; *except; except++) {
|
||||
if (!strncmp(*except, part->header.name, 12))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* nvram_remove_partition - Remove one or more partitions in nvram
|
||||
* @name: name of the partition to remove, or NULL for a
|
||||
* signature only match
|
||||
* @sig: signature of the partition(s) to remove
|
||||
* @exceptions: When removing all partitions with a matching signature,
|
||||
* leave these alone.
|
||||
*/
|
||||
|
||||
int __init nvram_remove_partition(const char *name, int sig)
|
||||
int __init nvram_remove_partition(const char *name, int sig,
|
||||
const char *exceptions[])
|
||||
{
|
||||
struct nvram_partition *part, *prev, *tmp;
|
||||
int rc;
|
||||
|
||||
list_for_each_entry(part, &nvram_partitions, partition) {
|
||||
if (part->header.signature != sig)
|
||||
continue;
|
||||
if (name && strncmp(name, part->header.name, 12))
|
||||
if (!nvram_can_remove_partition(part, name, sig, exceptions))
|
||||
continue;
|
||||
|
||||
/* Make partition a free partition */
|
||||
|
|
|
@ -97,7 +97,7 @@ static void __init move_device_tree(void)
|
|||
start = __pa(initial_boot_params);
|
||||
size = be32_to_cpu(initial_boot_params->totalsize);
|
||||
|
||||
if ((memory_limit && (start + size) > memory_limit) ||
|
||||
if ((memory_limit && (start + size) > PHYSICAL_START + memory_limit) ||
|
||||
overlaps_crashkernel(start, size)) {
|
||||
p = __va(memblock_alloc(size, PAGE_SIZE));
|
||||
memcpy(p, initial_boot_params, size);
|
||||
|
|
|
@ -412,7 +412,8 @@ static void rtas_event_scan(struct work_struct *w)
|
|||
|
||||
get_online_cpus();
|
||||
|
||||
cpu = cpumask_next(smp_processor_id(), cpu_online_mask);
|
||||
/* raw_ OK because just using CPU as starting point. */
|
||||
cpu = cpumask_next(raw_smp_processor_id(), cpu_online_mask);
|
||||
if (cpu >= nr_cpu_ids) {
|
||||
cpu = cpumask_first(cpu_online_mask);
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* arch/powerpc/math-emu/math_efp.c
|
||||
*
|
||||
* Copyright (C) 2006-2008 Freescale Semiconductor, Inc. All rights reserved.
|
||||
* Copyright (C) 2006-2008, 2010 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* Author: Ebony Zhu, <ebony.zhu@freescale.com>
|
||||
* Yu Liu, <yu.liu@freescale.com>
|
||||
|
@ -104,6 +104,8 @@
|
|||
#define FP_EX_MASK (FP_EX_INEXACT | FP_EX_INVALID | FP_EX_DIVZERO | \
|
||||
FP_EX_UNDERFLOW | FP_EX_OVERFLOW)
|
||||
|
||||
static int have_e500_cpu_a005_erratum;
|
||||
|
||||
union dw_union {
|
||||
u64 dp[1];
|
||||
u32 wp[2];
|
||||
|
@ -320,7 +322,8 @@ int do_spe_mathemu(struct pt_regs *regs)
|
|||
} else {
|
||||
_FP_ROUND_ZERO(1, SB);
|
||||
}
|
||||
FP_TO_INT_S(vc.wp[1], SB, 32, ((func & 0x3) != 0));
|
||||
FP_TO_INT_S(vc.wp[1], SB, 32,
|
||||
(((func & 0x3) != 0) || SB_s));
|
||||
goto update_regs;
|
||||
|
||||
default:
|
||||
|
@ -458,7 +461,8 @@ cmp_s:
|
|||
} else {
|
||||
_FP_ROUND_ZERO(2, DB);
|
||||
}
|
||||
FP_TO_INT_D(vc.wp[1], DB, 32, ((func & 0x3) != 0));
|
||||
FP_TO_INT_D(vc.wp[1], DB, 32,
|
||||
(((func & 0x3) != 0) || DB_s));
|
||||
goto update_regs;
|
||||
|
||||
default:
|
||||
|
@ -589,8 +593,10 @@ cmp_d:
|
|||
_FP_ROUND_ZERO(1, SB0);
|
||||
_FP_ROUND_ZERO(1, SB1);
|
||||
}
|
||||
FP_TO_INT_S(vc.wp[0], SB0, 32, ((func & 0x3) != 0));
|
||||
FP_TO_INT_S(vc.wp[1], SB1, 32, ((func & 0x3) != 0));
|
||||
FP_TO_INT_S(vc.wp[0], SB0, 32,
|
||||
(((func & 0x3) != 0) || SB0_s));
|
||||
FP_TO_INT_S(vc.wp[1], SB1, 32,
|
||||
(((func & 0x3) != 0) || SB1_s));
|
||||
goto update_regs;
|
||||
|
||||
default:
|
||||
|
@ -652,6 +658,15 @@ update_regs:
|
|||
return 0;
|
||||
|
||||
illegal:
|
||||
if (have_e500_cpu_a005_erratum) {
|
||||
/* according to e500 cpu a005 erratum, reissue efp inst */
|
||||
regs->nip -= 4;
|
||||
#ifdef DEBUG
|
||||
printk(KERN_DEBUG "re-issue efp inst: %08lx\n", speinsn);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
printk(KERN_ERR "\nOoops! IEEE-754 compliance handler encountered un-supported instruction.\ninst code: %08lx\n", speinsn);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
@ -718,3 +733,43 @@ int speround_handler(struct pt_regs *regs)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init spe_mathemu_init(void)
|
||||
{
|
||||
u32 pvr, maj, min;
|
||||
|
||||
pvr = mfspr(SPRN_PVR);
|
||||
|
||||
if ((PVR_VER(pvr) == PVR_VER_E500V1) ||
|
||||
(PVR_VER(pvr) == PVR_VER_E500V2)) {
|
||||
maj = PVR_MAJ(pvr);
|
||||
min = PVR_MIN(pvr);
|
||||
|
||||
/*
|
||||
* E500 revision below 1.1, 2.3, 3.1, 4.1, 5.1
|
||||
* need cpu a005 errata workaround
|
||||
*/
|
||||
switch (maj) {
|
||||
case 1:
|
||||
if (min < 1)
|
||||
have_e500_cpu_a005_erratum = 1;
|
||||
break;
|
||||
case 2:
|
||||
if (min < 3)
|
||||
have_e500_cpu_a005_erratum = 1;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
if (min < 1)
|
||||
have_e500_cpu_a005_erratum = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_init(spe_mathemu_init);
|
||||
|
|
|
@ -148,7 +148,7 @@ void __init MMU_init(void)
|
|||
lowmem_end_addr = memstart_addr + total_lowmem;
|
||||
#ifndef CONFIG_HIGHMEM
|
||||
total_memory = total_lowmem;
|
||||
memblock_enforce_memory_limit(lowmem_end_addr);
|
||||
memblock_enforce_memory_limit(total_lowmem);
|
||||
memblock_analyze();
|
||||
#endif /* CONFIG_HIGHMEM */
|
||||
}
|
||||
|
|
|
@ -189,6 +189,13 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_47x)
|
|||
blr
|
||||
|
||||
#ifdef CONFIG_PPC_47x
|
||||
|
||||
/*
|
||||
* 47x variant of icbt
|
||||
*/
|
||||
# define ICBT(CT,RA,RB) \
|
||||
.long 0x7c00002c | ((CT) << 21) | ((RA) << 16) | ((RB) << 11)
|
||||
|
||||
/*
|
||||
* _tlbivax_bcast is only on 47x. We don't bother doing a runtime
|
||||
* check though, it will blow up soon enough if we mistakenly try
|
||||
|
@ -206,9 +213,37 @@ _GLOBAL(_tlbivax_bcast)
|
|||
isync
|
||||
eieio
|
||||
tlbsync
|
||||
BEGIN_FTR_SECTION
|
||||
b 1f
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_476_DD2)
|
||||
sync
|
||||
wrtee r10
|
||||
blr
|
||||
/*
|
||||
* DD2 HW could hang if in instruction fetch happens before msync completes.
|
||||
* Touch enough instruction cache lines to ensure cache hits
|
||||
*/
|
||||
1: mflr r9
|
||||
bl 2f
|
||||
2: mflr r6
|
||||
li r7,32
|
||||
ICBT(0,r6,r7) /* touch next cache line */
|
||||
add r6,r6,r7
|
||||
ICBT(0,r6,r7) /* touch next cache line */
|
||||
add r6,r6,r7
|
||||
ICBT(0,r6,r7) /* touch next cache line */
|
||||
sync
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
mtlr r9
|
||||
wrtee r10
|
||||
blr
|
||||
#endif /* CONFIG_PPC_47x */
|
||||
|
||||
#elif defined(CONFIG_FSL_BOOKE)
|
||||
|
|
|
@ -4,4 +4,8 @@
|
|||
extern u8 as1_readb(volatile u8 __iomem *addr);
|
||||
extern void as1_writeb(u8 data, volatile u8 __iomem *addr);
|
||||
|
||||
#define GPIO0_OSRH 0xC
|
||||
#define GPIO0_TSRH 0x14
|
||||
#define GPIO0_ISR1H 0x34
|
||||
|
||||
#endif /* __POWERPC_PLATFORMS_44X_44X_H */
|
||||
|
|
|
@ -115,7 +115,6 @@ config CANYONLANDS
|
|||
bool "Canyonlands"
|
||||
depends on 44x
|
||||
default n
|
||||
select PPC44x_SIMPLE
|
||||
select 460EX
|
||||
select PCI
|
||||
select PPC4xx_PCI_EXPRESS
|
||||
|
|
|
@ -9,3 +9,4 @@ obj-$(CONFIG_WARP) += warp.o
|
|||
obj-$(CONFIG_XILINX_VIRTEX_5_FXT) += virtex.o
|
||||
obj-$(CONFIG_XILINX_ML510) += virtex_ml510.o
|
||||
obj-$(CONFIG_ISS4xx) += iss4xx.o
|
||||
obj-$(CONFIG_CANYONLANDS)+= canyonlands.o
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* This contain platform specific code for APM PPC460EX based Canyonlands
|
||||
* board.
|
||||
*
|
||||
* Copyright (c) 2010, Applied Micro Circuits Corporation
|
||||
* Author: Rupjyoti Sarmah <rsarmah@apm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/pci-bridge.h>
|
||||
#include <asm/ppc4xx.h>
|
||||
#include <asm/udbg.h>
|
||||
#include <asm/uic.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/delay.h>
|
||||
#include "44x.h"
|
||||
|
||||
#define BCSR_USB_EN 0x11
|
||||
|
||||
static __initdata struct of_device_id ppc460ex_of_bus[] = {
|
||||
{ .compatible = "ibm,plb4", },
|
||||
{ .compatible = "ibm,opb", },
|
||||
{ .compatible = "ibm,ebc", },
|
||||
{ .compatible = "simple-bus", },
|
||||
{},
|
||||
};
|
||||
|
||||
static int __init ppc460ex_device_probe(void)
|
||||
{
|
||||
of_platform_bus_probe(NULL, ppc460ex_of_bus, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
machine_device_initcall(canyonlands, ppc460ex_device_probe);
|
||||
|
||||
/* Using this code only for the Canyonlands board. */
|
||||
|
||||
static int __init ppc460ex_probe(void)
|
||||
{
|
||||
unsigned long root = of_get_flat_dt_root();
|
||||
if (of_flat_dt_is_compatible(root, "amcc,canyonlands")) {
|
||||
ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* USB PHY fixup code on Canyonlands kit. */
|
||||
|
||||
static int __init ppc460ex_canyonlands_fixup(void)
|
||||
{
|
||||
u8 __iomem *bcsr ;
|
||||
void __iomem *vaddr;
|
||||
struct device_node *np;
|
||||
int ret = 0;
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "amcc,ppc460ex-bcsr");
|
||||
if (!np) {
|
||||
printk(KERN_ERR "failed did not find amcc, ppc460ex bcsr node\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
bcsr = of_iomap(np, 0);
|
||||
of_node_put(np);
|
||||
|
||||
if (!bcsr) {
|
||||
printk(KERN_CRIT "Could not remap bcsr\n");
|
||||
ret = -ENODEV;
|
||||
goto err_bcsr;
|
||||
}
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "ibm,ppc4xx-gpio");
|
||||
if (!np) {
|
||||
printk(KERN_ERR "failed did not find ibm,ppc4xx-gpio node\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
vaddr = of_iomap(np, 0);
|
||||
of_node_put(np);
|
||||
|
||||
if (!vaddr) {
|
||||
printk(KERN_CRIT "Could not get gpio node address\n");
|
||||
ret = -ENODEV;
|
||||
goto err_gpio;
|
||||
}
|
||||
/* Disable USB, through the BCSR7 bits */
|
||||
setbits8(&bcsr[7], BCSR_USB_EN);
|
||||
|
||||
/* Wait for a while after reset */
|
||||
msleep(100);
|
||||
|
||||
/* Enable USB here */
|
||||
clrbits8(&bcsr[7], BCSR_USB_EN);
|
||||
|
||||
/*
|
||||
* Configure multiplexed gpio16 and gpio19 as alternate1 output
|
||||
* source after USB reset. In this configuration gpio16 will be
|
||||
* USB2HStop and gpio19 will be USB2DStop. For more details refer to
|
||||
* table 34-7 of PPC460EX user manual.
|
||||
*/
|
||||
setbits32((vaddr + GPIO0_OSRH), 0x42000000);
|
||||
setbits32((vaddr + GPIO0_TSRH), 0x42000000);
|
||||
err_gpio:
|
||||
iounmap(vaddr);
|
||||
err_bcsr:
|
||||
iounmap(bcsr);
|
||||
return ret;
|
||||
}
|
||||
machine_device_initcall(canyonlands, ppc460ex_canyonlands_fixup);
|
||||
define_machine(canyonlands) {
|
||||
.name = "Canyonlands",
|
||||
.probe = ppc460ex_probe,
|
||||
.progress = udbg_progress,
|
||||
.init_IRQ = uic_init_tree,
|
||||
.get_irq = uic_get_irq,
|
||||
.restart = ppc4xx_reset_system,
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
};
|
|
@ -53,7 +53,6 @@ static char *board[] __initdata = {
|
|||
"amcc,arches",
|
||||
"amcc,bamboo",
|
||||
"amcc,bluestone",
|
||||
"amcc,canyonlands",
|
||||
"amcc,glacier",
|
||||
"ibm,ebony",
|
||||
"amcc,eiger",
|
||||
|
|
|
@ -59,9 +59,9 @@ irq_to_pic_bit(unsigned int irq)
|
|||
}
|
||||
|
||||
static void
|
||||
cpld_mask_irq(unsigned int irq)
|
||||
cpld_mask_irq(struct irq_data *d)
|
||||
{
|
||||
unsigned int cpld_irq = (unsigned int)irq_map[irq].hwirq;
|
||||
unsigned int cpld_irq = (unsigned int)irq_map[d->irq].hwirq;
|
||||
void __iomem *pic_mask = irq_to_pic_mask(cpld_irq);
|
||||
|
||||
out_8(pic_mask,
|
||||
|
@ -69,9 +69,9 @@ cpld_mask_irq(unsigned int irq)
|
|||
}
|
||||
|
||||
static void
|
||||
cpld_unmask_irq(unsigned int irq)
|
||||
cpld_unmask_irq(struct irq_data *d)
|
||||
{
|
||||
unsigned int cpld_irq = (unsigned int)irq_map[irq].hwirq;
|
||||
unsigned int cpld_irq = (unsigned int)irq_map[d->irq].hwirq;
|
||||
void __iomem *pic_mask = irq_to_pic_mask(cpld_irq);
|
||||
|
||||
out_8(pic_mask,
|
||||
|
@ -80,9 +80,9 @@ cpld_unmask_irq(unsigned int irq)
|
|||
|
||||
static struct irq_chip cpld_pic = {
|
||||
.name = "CPLD PIC",
|
||||
.mask = cpld_mask_irq,
|
||||
.ack = cpld_mask_irq,
|
||||
.unmask = cpld_unmask_irq,
|
||||
.irq_mask = cpld_mask_irq,
|
||||
.irq_ack = cpld_mask_irq,
|
||||
.irq_unmask = cpld_unmask_irq,
|
||||
};
|
||||
|
||||
static int
|
||||
|
|
|
@ -49,45 +49,46 @@ struct media5200_irq {
|
|||
};
|
||||
struct media5200_irq media5200_irq;
|
||||
|
||||
static void media5200_irq_unmask(unsigned int virq)
|
||||
static void media5200_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
||||
spin_lock_irqsave(&media5200_irq.lock, flags);
|
||||
val = in_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE);
|
||||
val |= 1 << (MEDIA5200_IRQ_SHIFT + irq_map[virq].hwirq);
|
||||
val |= 1 << (MEDIA5200_IRQ_SHIFT + irq_map[d->irq].hwirq);
|
||||
out_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE, val);
|
||||
spin_unlock_irqrestore(&media5200_irq.lock, flags);
|
||||
}
|
||||
|
||||
static void media5200_irq_mask(unsigned int virq)
|
||||
static void media5200_irq_mask(struct irq_data *d)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
||||
spin_lock_irqsave(&media5200_irq.lock, flags);
|
||||
val = in_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE);
|
||||
val &= ~(1 << (MEDIA5200_IRQ_SHIFT + irq_map[virq].hwirq));
|
||||
val &= ~(1 << (MEDIA5200_IRQ_SHIFT + irq_map[d->irq].hwirq));
|
||||
out_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE, val);
|
||||
spin_unlock_irqrestore(&media5200_irq.lock, flags);
|
||||
}
|
||||
|
||||
static struct irq_chip media5200_irq_chip = {
|
||||
.name = "Media5200 FPGA",
|
||||
.unmask = media5200_irq_unmask,
|
||||
.mask = media5200_irq_mask,
|
||||
.mask_ack = media5200_irq_mask,
|
||||
.irq_unmask = media5200_irq_unmask,
|
||||
.irq_mask = media5200_irq_mask,
|
||||
.irq_mask_ack = media5200_irq_mask,
|
||||
};
|
||||
|
||||
void media5200_irq_cascade(unsigned int virq, struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = get_irq_desc_chip(desc);
|
||||
int sub_virq, val;
|
||||
u32 status, enable;
|
||||
|
||||
/* Mask off the cascaded IRQ */
|
||||
raw_spin_lock(&desc->lock);
|
||||
desc->chip->mask(virq);
|
||||
chip->irq_mask(&desc->irq_data);
|
||||
raw_spin_unlock(&desc->lock);
|
||||
|
||||
/* Ask the FPGA for IRQ status. If 'val' is 0, then no irqs
|
||||
|
@ -105,9 +106,9 @@ void media5200_irq_cascade(unsigned int virq, struct irq_desc *desc)
|
|||
|
||||
/* Processing done; can reenable the cascade now */
|
||||
raw_spin_lock(&desc->lock);
|
||||
desc->chip->ack(virq);
|
||||
chip->irq_ack(&desc->irq_data);
|
||||
if (!(desc->status & IRQ_DISABLED))
|
||||
desc->chip->unmask(virq);
|
||||
chip->irq_unmask(&desc->irq_data);
|
||||
raw_spin_unlock(&desc->lock);
|
||||
}
|
||||
|
||||
|
|
|
@ -135,9 +135,9 @@ DEFINE_MUTEX(mpc52xx_gpt_list_mutex);
|
|||
* Cascaded interrupt controller hooks
|
||||
*/
|
||||
|
||||
static void mpc52xx_gpt_irq_unmask(unsigned int virq)
|
||||
static void mpc52xx_gpt_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
struct mpc52xx_gpt_priv *gpt = get_irq_chip_data(virq);
|
||||
struct mpc52xx_gpt_priv *gpt = irq_data_get_irq_chip_data(d);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&gpt->lock, flags);
|
||||
|
@ -145,9 +145,9 @@ static void mpc52xx_gpt_irq_unmask(unsigned int virq)
|
|||
spin_unlock_irqrestore(&gpt->lock, flags);
|
||||
}
|
||||
|
||||
static void mpc52xx_gpt_irq_mask(unsigned int virq)
|
||||
static void mpc52xx_gpt_irq_mask(struct irq_data *d)
|
||||
{
|
||||
struct mpc52xx_gpt_priv *gpt = get_irq_chip_data(virq);
|
||||
struct mpc52xx_gpt_priv *gpt = irq_data_get_irq_chip_data(d);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&gpt->lock, flags);
|
||||
|
@ -155,20 +155,20 @@ static void mpc52xx_gpt_irq_mask(unsigned int virq)
|
|||
spin_unlock_irqrestore(&gpt->lock, flags);
|
||||
}
|
||||
|
||||
static void mpc52xx_gpt_irq_ack(unsigned int virq)
|
||||
static void mpc52xx_gpt_irq_ack(struct irq_data *d)
|
||||
{
|
||||
struct mpc52xx_gpt_priv *gpt = get_irq_chip_data(virq);
|
||||
struct mpc52xx_gpt_priv *gpt = irq_data_get_irq_chip_data(d);
|
||||
|
||||
out_be32(&gpt->regs->status, MPC52xx_GPT_STATUS_IRQMASK);
|
||||
}
|
||||
|
||||
static int mpc52xx_gpt_irq_set_type(unsigned int virq, unsigned int flow_type)
|
||||
static int mpc52xx_gpt_irq_set_type(struct irq_data *d, unsigned int flow_type)
|
||||
{
|
||||
struct mpc52xx_gpt_priv *gpt = get_irq_chip_data(virq);
|
||||
struct mpc52xx_gpt_priv *gpt = irq_data_get_irq_chip_data(d);
|
||||
unsigned long flags;
|
||||
u32 reg;
|
||||
|
||||
dev_dbg(gpt->dev, "%s: virq=%i type=%x\n", __func__, virq, flow_type);
|
||||
dev_dbg(gpt->dev, "%s: virq=%i type=%x\n", __func__, d->irq, flow_type);
|
||||
|
||||
spin_lock_irqsave(&gpt->lock, flags);
|
||||
reg = in_be32(&gpt->regs->mode) & ~MPC52xx_GPT_MODE_ICT_MASK;
|
||||
|
@ -184,10 +184,10 @@ static int mpc52xx_gpt_irq_set_type(unsigned int virq, unsigned int flow_type)
|
|||
|
||||
static struct irq_chip mpc52xx_gpt_irq_chip = {
|
||||
.name = "MPC52xx GPT",
|
||||
.unmask = mpc52xx_gpt_irq_unmask,
|
||||
.mask = mpc52xx_gpt_irq_mask,
|
||||
.ack = mpc52xx_gpt_irq_ack,
|
||||
.set_type = mpc52xx_gpt_irq_set_type,
|
||||
.irq_unmask = mpc52xx_gpt_irq_unmask,
|
||||
.irq_mask = mpc52xx_gpt_irq_mask,
|
||||
.irq_ack = mpc52xx_gpt_irq_ack,
|
||||
.irq_set_type = mpc52xx_gpt_irq_set_type,
|
||||
};
|
||||
|
||||
void mpc52xx_gpt_irq_cascade(unsigned int virq, struct irq_desc *desc)
|
||||
|
|
|
@ -155,47 +155,47 @@ static inline void io_be_clrbit(u32 __iomem *addr, int bitno)
|
|||
/*
|
||||
* IRQ[0-3] interrupt irq_chip
|
||||
*/
|
||||
static void mpc52xx_extirq_mask(unsigned int virq)
|
||||
static void mpc52xx_extirq_mask(struct irq_data *d)
|
||||
{
|
||||
int irq;
|
||||
int l2irq;
|
||||
|
||||
irq = irq_map[virq].hwirq;
|
||||
irq = irq_map[d->irq].hwirq;
|
||||
l2irq = irq & MPC52xx_IRQ_L2_MASK;
|
||||
|
||||
io_be_clrbit(&intr->ctrl, 11 - l2irq);
|
||||
}
|
||||
|
||||
static void mpc52xx_extirq_unmask(unsigned int virq)
|
||||
static void mpc52xx_extirq_unmask(struct irq_data *d)
|
||||
{
|
||||
int irq;
|
||||
int l2irq;
|
||||
|
||||
irq = irq_map[virq].hwirq;
|
||||
irq = irq_map[d->irq].hwirq;
|
||||
l2irq = irq & MPC52xx_IRQ_L2_MASK;
|
||||
|
||||
io_be_setbit(&intr->ctrl, 11 - l2irq);
|
||||
}
|
||||
|
||||
static void mpc52xx_extirq_ack(unsigned int virq)
|
||||
static void mpc52xx_extirq_ack(struct irq_data *d)
|
||||
{
|
||||
int irq;
|
||||
int l2irq;
|
||||
|
||||
irq = irq_map[virq].hwirq;
|
||||
irq = irq_map[d->irq].hwirq;
|
||||
l2irq = irq & MPC52xx_IRQ_L2_MASK;
|
||||
|
||||
io_be_setbit(&intr->ctrl, 27-l2irq);
|
||||
}
|
||||
|
||||
static int mpc52xx_extirq_set_type(unsigned int virq, unsigned int flow_type)
|
||||
static int mpc52xx_extirq_set_type(struct irq_data *d, unsigned int flow_type)
|
||||
{
|
||||
u32 ctrl_reg, type;
|
||||
int irq;
|
||||
int l2irq;
|
||||
void *handler = handle_level_irq;
|
||||
|
||||
irq = irq_map[virq].hwirq;
|
||||
irq = irq_map[d->irq].hwirq;
|
||||
l2irq = irq & MPC52xx_IRQ_L2_MASK;
|
||||
|
||||
pr_debug("%s: irq=%x. l2=%d flow_type=%d\n", __func__, irq, l2irq, flow_type);
|
||||
|
@ -214,44 +214,44 @@ static int mpc52xx_extirq_set_type(unsigned int virq, unsigned int flow_type)
|
|||
ctrl_reg |= (type << (22 - (l2irq * 2)));
|
||||
out_be32(&intr->ctrl, ctrl_reg);
|
||||
|
||||
__set_irq_handler_unlocked(virq, handler);
|
||||
__set_irq_handler_unlocked(d->irq, handler);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_chip mpc52xx_extirq_irqchip = {
|
||||
.name = "MPC52xx External",
|
||||
.mask = mpc52xx_extirq_mask,
|
||||
.unmask = mpc52xx_extirq_unmask,
|
||||
.ack = mpc52xx_extirq_ack,
|
||||
.set_type = mpc52xx_extirq_set_type,
|
||||
.irq_mask = mpc52xx_extirq_mask,
|
||||
.irq_unmask = mpc52xx_extirq_unmask,
|
||||
.irq_ack = mpc52xx_extirq_ack,
|
||||
.irq_set_type = mpc52xx_extirq_set_type,
|
||||
};
|
||||
|
||||
/*
|
||||
* Main interrupt irq_chip
|
||||
*/
|
||||
static int mpc52xx_null_set_type(unsigned int virq, unsigned int flow_type)
|
||||
static int mpc52xx_null_set_type(struct irq_data *d, unsigned int flow_type)
|
||||
{
|
||||
return 0; /* Do nothing so that the sense mask will get updated */
|
||||
}
|
||||
|
||||
static void mpc52xx_main_mask(unsigned int virq)
|
||||
static void mpc52xx_main_mask(struct irq_data *d)
|
||||
{
|
||||
int irq;
|
||||
int l2irq;
|
||||
|
||||
irq = irq_map[virq].hwirq;
|
||||
irq = irq_map[d->irq].hwirq;
|
||||
l2irq = irq & MPC52xx_IRQ_L2_MASK;
|
||||
|
||||
io_be_setbit(&intr->main_mask, 16 - l2irq);
|
||||
}
|
||||
|
||||
static void mpc52xx_main_unmask(unsigned int virq)
|
||||
static void mpc52xx_main_unmask(struct irq_data *d)
|
||||
{
|
||||
int irq;
|
||||
int l2irq;
|
||||
|
||||
irq = irq_map[virq].hwirq;
|
||||
irq = irq_map[d->irq].hwirq;
|
||||
l2irq = irq & MPC52xx_IRQ_L2_MASK;
|
||||
|
||||
io_be_clrbit(&intr->main_mask, 16 - l2irq);
|
||||
|
@ -259,32 +259,32 @@ static void mpc52xx_main_unmask(unsigned int virq)
|
|||
|
||||
static struct irq_chip mpc52xx_main_irqchip = {
|
||||
.name = "MPC52xx Main",
|
||||
.mask = mpc52xx_main_mask,
|
||||
.mask_ack = mpc52xx_main_mask,
|
||||
.unmask = mpc52xx_main_unmask,
|
||||
.set_type = mpc52xx_null_set_type,
|
||||
.irq_mask = mpc52xx_main_mask,
|
||||
.irq_mask_ack = mpc52xx_main_mask,
|
||||
.irq_unmask = mpc52xx_main_unmask,
|
||||
.irq_set_type = mpc52xx_null_set_type,
|
||||
};
|
||||
|
||||
/*
|
||||
* Peripherals interrupt irq_chip
|
||||
*/
|
||||
static void mpc52xx_periph_mask(unsigned int virq)
|
||||
static void mpc52xx_periph_mask(struct irq_data *d)
|
||||
{
|
||||
int irq;
|
||||
int l2irq;
|
||||
|
||||
irq = irq_map[virq].hwirq;
|
||||
irq = irq_map[d->irq].hwirq;
|
||||
l2irq = irq & MPC52xx_IRQ_L2_MASK;
|
||||
|
||||
io_be_setbit(&intr->per_mask, 31 - l2irq);
|
||||
}
|
||||
|
||||
static void mpc52xx_periph_unmask(unsigned int virq)
|
||||
static void mpc52xx_periph_unmask(struct irq_data *d)
|
||||
{
|
||||
int irq;
|
||||
int l2irq;
|
||||
|
||||
irq = irq_map[virq].hwirq;
|
||||
irq = irq_map[d->irq].hwirq;
|
||||
l2irq = irq & MPC52xx_IRQ_L2_MASK;
|
||||
|
||||
io_be_clrbit(&intr->per_mask, 31 - l2irq);
|
||||
|
@ -292,43 +292,43 @@ static void mpc52xx_periph_unmask(unsigned int virq)
|
|||
|
||||
static struct irq_chip mpc52xx_periph_irqchip = {
|
||||
.name = "MPC52xx Peripherals",
|
||||
.mask = mpc52xx_periph_mask,
|
||||
.mask_ack = mpc52xx_periph_mask,
|
||||
.unmask = mpc52xx_periph_unmask,
|
||||
.set_type = mpc52xx_null_set_type,
|
||||
.irq_mask = mpc52xx_periph_mask,
|
||||
.irq_mask_ack = mpc52xx_periph_mask,
|
||||
.irq_unmask = mpc52xx_periph_unmask,
|
||||
.irq_set_type = mpc52xx_null_set_type,
|
||||
};
|
||||
|
||||
/*
|
||||
* SDMA interrupt irq_chip
|
||||
*/
|
||||
static void mpc52xx_sdma_mask(unsigned int virq)
|
||||
static void mpc52xx_sdma_mask(struct irq_data *d)
|
||||
{
|
||||
int irq;
|
||||
int l2irq;
|
||||
|
||||
irq = irq_map[virq].hwirq;
|
||||
irq = irq_map[d->irq].hwirq;
|
||||
l2irq = irq & MPC52xx_IRQ_L2_MASK;
|
||||
|
||||
io_be_setbit(&sdma->IntMask, l2irq);
|
||||
}
|
||||
|
||||
static void mpc52xx_sdma_unmask(unsigned int virq)
|
||||
static void mpc52xx_sdma_unmask(struct irq_data *d)
|
||||
{
|
||||
int irq;
|
||||
int l2irq;
|
||||
|
||||
irq = irq_map[virq].hwirq;
|
||||
irq = irq_map[d->irq].hwirq;
|
||||
l2irq = irq & MPC52xx_IRQ_L2_MASK;
|
||||
|
||||
io_be_clrbit(&sdma->IntMask, l2irq);
|
||||
}
|
||||
|
||||
static void mpc52xx_sdma_ack(unsigned int virq)
|
||||
static void mpc52xx_sdma_ack(struct irq_data *d)
|
||||
{
|
||||
int irq;
|
||||
int l2irq;
|
||||
|
||||
irq = irq_map[virq].hwirq;
|
||||
irq = irq_map[d->irq].hwirq;
|
||||
l2irq = irq & MPC52xx_IRQ_L2_MASK;
|
||||
|
||||
out_be32(&sdma->IntPend, 1 << l2irq);
|
||||
|
@ -336,10 +336,10 @@ static void mpc52xx_sdma_ack(unsigned int virq)
|
|||
|
||||
static struct irq_chip mpc52xx_sdma_irqchip = {
|
||||
.name = "MPC52xx SDMA",
|
||||
.mask = mpc52xx_sdma_mask,
|
||||
.unmask = mpc52xx_sdma_unmask,
|
||||
.ack = mpc52xx_sdma_ack,
|
||||
.set_type = mpc52xx_null_set_type,
|
||||
.irq_mask = mpc52xx_sdma_mask,
|
||||
.irq_unmask = mpc52xx_sdma_unmask,
|
||||
.irq_ack = mpc52xx_sdma_ack,
|
||||
.irq_set_type = mpc52xx_null_set_type,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,4 +6,4 @@ obj-$(CONFIG_CPM2) += pq2.o
|
|||
obj-$(CONFIG_PQ2_ADS_PCI_PIC) += pq2ads-pci-pic.o
|
||||
obj-$(CONFIG_PQ2FADS) += pq2fads.o
|
||||
obj-$(CONFIG_EP8248E) += ep8248e.o
|
||||
obj-$(CONFIG_MGCOGE) += mgcoge.o
|
||||
obj-$(CONFIG_MGCOGE) += km82xx.o
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Keymile mgcoge support
|
||||
* Copyright 2008 DENX Software Engineering GmbH
|
||||
* Keymile km82xx support
|
||||
* Copyright 2008-2011 DENX Software Engineering GmbH
|
||||
* Author: Heiko Schocher <hs@denx.de>
|
||||
*
|
||||
* based on code from:
|
||||
|
@ -31,9 +31,10 @@
|
|||
|
||||
#include "pq2.h"
|
||||
|
||||
static void __init mgcoge_pic_init(void)
|
||||
static void __init km82xx_pic_init(void)
|
||||
{
|
||||
struct device_node *np = of_find_compatible_node(NULL, NULL, "fsl,pq2-pic");
|
||||
struct device_node *np = of_find_compatible_node(NULL, NULL,
|
||||
"fsl,pq2-pic");
|
||||
if (!np) {
|
||||
printk(KERN_ERR "PIC init: can not find cpm-pic node\n");
|
||||
return;
|
||||
|
@ -47,12 +48,18 @@ struct cpm_pin {
|
|||
int port, pin, flags;
|
||||
};
|
||||
|
||||
static __initdata struct cpm_pin mgcoge_pins[] = {
|
||||
static __initdata struct cpm_pin km82xx_pins[] = {
|
||||
|
||||
/* SMC2 */
|
||||
{0, 8, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
|
||||
{0, 9, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
|
||||
|
||||
/* SCC1 */
|
||||
{2, 21, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
|
||||
{2, 15, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
|
||||
{3, 31, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
|
||||
{3, 30, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
|
||||
|
||||
/* SCC4 */
|
||||
{2, 25, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
|
||||
{2, 24, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
|
||||
|
@ -107,30 +114,49 @@ static __initdata struct cpm_pin mgcoge_pins[] = {
|
|||
{3, 14, CPM_PIN_INPUT | CPM_PIN_SECONDARY | CPM_PIN_OPENDRAIN},
|
||||
{3, 15, CPM_PIN_INPUT | CPM_PIN_SECONDARY | CPM_PIN_OPENDRAIN},
|
||||
#endif
|
||||
|
||||
/* USB */
|
||||
{0, 10, CPM_PIN_OUTPUT | CPM_PIN_GPIO}, /* FULL_SPEED */
|
||||
{0, 11, CPM_PIN_OUTPUT | CPM_PIN_GPIO}, /*/SLAVE */
|
||||
{2, 10, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, /* RXN */
|
||||
{2, 11, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, /* RXP */
|
||||
{2, 20, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, /* /OE */
|
||||
{2, 27, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, /* RXCLK */
|
||||
{3, 23, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, /* TXP */
|
||||
{3, 24, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, /* TXN */
|
||||
{3, 25, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, /* RXD */
|
||||
};
|
||||
|
||||
static void __init init_ioports(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mgcoge_pins); i++) {
|
||||
const struct cpm_pin *pin = &mgcoge_pins[i];
|
||||
for (i = 0; i < ARRAY_SIZE(km82xx_pins); i++) {
|
||||
const struct cpm_pin *pin = &km82xx_pins[i];
|
||||
cpm2_set_pin(pin->port, pin->pin, pin->flags);
|
||||
}
|
||||
|
||||
cpm2_smc_clk_setup(CPM_CLK_SMC2, CPM_BRG8);
|
||||
cpm2_clk_setup(CPM_CLK_SCC1, CPM_CLK11, CPM_CLK_RX);
|
||||
cpm2_clk_setup(CPM_CLK_SCC1, CPM_CLK11, CPM_CLK_TX);
|
||||
cpm2_clk_setup(CPM_CLK_SCC3, CPM_CLK5, CPM_CLK_RTX);
|
||||
cpm2_clk_setup(CPM_CLK_SCC4, CPM_CLK7, CPM_CLK_RX);
|
||||
cpm2_clk_setup(CPM_CLK_SCC4, CPM_CLK8, CPM_CLK_TX);
|
||||
cpm2_clk_setup(CPM_CLK_FCC1, CPM_CLK10, CPM_CLK_RX);
|
||||
cpm2_clk_setup(CPM_CLK_FCC1, CPM_CLK9, CPM_CLK_TX);
|
||||
cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK13, CPM_CLK_RX);
|
||||
cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK14, CPM_CLK_TX);
|
||||
|
||||
/* Force USB FULL SPEED bit to '1' */
|
||||
setbits32(&cpm2_immr->im_ioport.iop_pdata, 1 << (31 - 10));
|
||||
/* clear USB_SLAVE */
|
||||
clrbits32(&cpm2_immr->im_ioport.iop_pdata, 1 << (31 - 11));
|
||||
}
|
||||
|
||||
static void __init mgcoge_setup_arch(void)
|
||||
static void __init km82xx_setup_arch(void)
|
||||
{
|
||||
if (ppc_md.progress)
|
||||
ppc_md.progress("mgcoge_setup_arch()", 0);
|
||||
ppc_md.progress("km82xx_setup_arch()", 0);
|
||||
|
||||
cpm2_reset();
|
||||
|
||||
|
@ -142,7 +168,7 @@ static void __init mgcoge_setup_arch(void)
|
|||
init_ioports();
|
||||
|
||||
if (ppc_md.progress)
|
||||
ppc_md.progress("mgcoge_setup_arch(), finish", 0);
|
||||
ppc_md.progress("km82xx_setup_arch(), finish", 0);
|
||||
}
|
||||
|
||||
static __initdata struct of_device_id of_bus_ids[] = {
|
||||
|
@ -156,23 +182,23 @@ static int __init declare_of_platform_devices(void)
|
|||
|
||||
return 0;
|
||||
}
|
||||
machine_device_initcall(mgcoge, declare_of_platform_devices);
|
||||
machine_device_initcall(km82xx, declare_of_platform_devices);
|
||||
|
||||
/*
|
||||
* Called very early, device-tree isn't unflattened
|
||||
*/
|
||||
static int __init mgcoge_probe(void)
|
||||
static int __init km82xx_probe(void)
|
||||
{
|
||||
unsigned long root = of_get_flat_dt_root();
|
||||
return of_flat_dt_is_compatible(root, "keymile,mgcoge");
|
||||
return of_flat_dt_is_compatible(root, "keymile,km82xx");
|
||||
}
|
||||
|
||||
define_machine(mgcoge)
|
||||
define_machine(km82xx)
|
||||
{
|
||||
.name = "Keymile MGCOGE",
|
||||
.probe = mgcoge_probe,
|
||||
.setup_arch = mgcoge_setup_arch,
|
||||
.init_IRQ = mgcoge_pic_init,
|
||||
.name = "Keymile km82xx",
|
||||
.probe = km82xx_probe,
|
||||
.setup_arch = km82xx_setup_arch,
|
||||
.init_IRQ = km82xx_pic_init,
|
||||
.get_irq = cpm2_get_irq,
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
.restart = pq2_restart,
|
|
@ -39,10 +39,10 @@ struct pq2ads_pci_pic {
|
|||
|
||||
#define NUM_IRQS 32
|
||||
|
||||
static void pq2ads_pci_mask_irq(unsigned int virq)
|
||||
static void pq2ads_pci_mask_irq(struct irq_data *d)
|
||||
{
|
||||
struct pq2ads_pci_pic *priv = get_irq_chip_data(virq);
|
||||
int irq = NUM_IRQS - virq_to_hw(virq) - 1;
|
||||
struct pq2ads_pci_pic *priv = irq_data_get_irq_chip_data(d);
|
||||
int irq = NUM_IRQS - virq_to_hw(d->irq) - 1;
|
||||
|
||||
if (irq != -1) {
|
||||
unsigned long flags;
|
||||
|
@ -55,10 +55,10 @@ static void pq2ads_pci_mask_irq(unsigned int virq)
|
|||
}
|
||||
}
|
||||
|
||||
static void pq2ads_pci_unmask_irq(unsigned int virq)
|
||||
static void pq2ads_pci_unmask_irq(struct irq_data *d)
|
||||
{
|
||||
struct pq2ads_pci_pic *priv = get_irq_chip_data(virq);
|
||||
int irq = NUM_IRQS - virq_to_hw(virq) - 1;
|
||||
struct pq2ads_pci_pic *priv = irq_data_get_irq_chip_data(d);
|
||||
int irq = NUM_IRQS - virq_to_hw(d->irq) - 1;
|
||||
|
||||
if (irq != -1) {
|
||||
unsigned long flags;
|
||||
|
@ -71,18 +71,17 @@ static void pq2ads_pci_unmask_irq(unsigned int virq)
|
|||
|
||||
static struct irq_chip pq2ads_pci_ic = {
|
||||
.name = "PQ2 ADS PCI",
|
||||
.end = pq2ads_pci_unmask_irq,
|
||||
.mask = pq2ads_pci_mask_irq,
|
||||
.mask_ack = pq2ads_pci_mask_irq,
|
||||
.ack = pq2ads_pci_mask_irq,
|
||||
.unmask = pq2ads_pci_unmask_irq,
|
||||
.enable = pq2ads_pci_unmask_irq,
|
||||
.disable = pq2ads_pci_mask_irq
|
||||
.irq_mask = pq2ads_pci_mask_irq,
|
||||
.irq_mask_ack = pq2ads_pci_mask_irq,
|
||||
.irq_ack = pq2ads_pci_mask_irq,
|
||||
.irq_unmask = pq2ads_pci_unmask_irq,
|
||||
.irq_enable = pq2ads_pci_unmask_irq,
|
||||
.irq_disable = pq2ads_pci_mask_irq
|
||||
};
|
||||
|
||||
static void pq2ads_pci_irq_demux(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct pq2ads_pci_pic *priv = desc->handler_data;
|
||||
struct pq2ads_pci_pic *priv = get_irq_desc_data(desc);
|
||||
u32 stat, mask, pend;
|
||||
int bit;
|
||||
|
||||
|
|
|
@ -16,4 +16,4 @@ obj-$(CONFIG_MPC837x_MDS) += mpc837x_mds.o
|
|||
obj-$(CONFIG_SBC834x) += sbc834x.o
|
||||
obj-$(CONFIG_MPC837x_RDB) += mpc837x_rdb.o
|
||||
obj-$(CONFIG_ASP834x) += asp834x.o
|
||||
obj-$(CONFIG_KMETER1) += kmeter1.o
|
||||
obj-$(CONFIG_KMETER1) += km83xx.o
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2008 DENX Software Engineering GmbH
|
||||
* Copyright 2008-2011 DENX Software Engineering GmbH
|
||||
* Author: Heiko Schocher <hs@denx.de>
|
||||
*
|
||||
* Description:
|
||||
|
@ -49,12 +49,12 @@
|
|||
* Setup the architecture
|
||||
*
|
||||
*/
|
||||
static void __init kmeter1_setup_arch(void)
|
||||
static void __init mpc83xx_km_setup_arch(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
if (ppc_md.progress)
|
||||
ppc_md.progress("kmeter1_setup_arch()", 0);
|
||||
ppc_md.progress("kmpbec83xx_setup_arch()", 0);
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
|
||||
|
@ -69,6 +69,9 @@ static void __init kmeter1_setup_arch(void)
|
|||
par_io_init(np);
|
||||
of_node_put(np);
|
||||
|
||||
for_each_node_by_name(np, "spi")
|
||||
par_io_of_config(np);
|
||||
|
||||
for (np = NULL; (np = of_find_node_by_name(np, "ucc")) != NULL;)
|
||||
par_io_of_config(np);
|
||||
}
|
||||
|
@ -119,7 +122,7 @@ static void __init kmeter1_setup_arch(void)
|
|||
#endif /* CONFIG_QUICC_ENGINE */
|
||||
}
|
||||
|
||||
static struct of_device_id kmeter_ids[] = {
|
||||
static struct of_device_id kmpbec83xx_ids[] = {
|
||||
{ .type = "soc", },
|
||||
{ .compatible = "soc", },
|
||||
{ .compatible = "simple-bus", },
|
||||
|
@ -131,13 +134,13 @@ static struct of_device_id kmeter_ids[] = {
|
|||
static int __init kmeter_declare_of_platform_devices(void)
|
||||
{
|
||||
/* Publish the QE devices */
|
||||
of_platform_bus_probe(NULL, kmeter_ids, NULL);
|
||||
of_platform_bus_probe(NULL, kmpbec83xx_ids, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
machine_device_initcall(kmeter1, kmeter_declare_of_platform_devices);
|
||||
machine_device_initcall(mpc83xx_km, kmeter_declare_of_platform_devices);
|
||||
|
||||
static void __init kmeter1_init_IRQ(void)
|
||||
static void __init mpc83xx_km_init_IRQ(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
|
@ -168,21 +171,34 @@ static void __init kmeter1_init_IRQ(void)
|
|||
#endif /* CONFIG_QUICC_ENGINE */
|
||||
}
|
||||
|
||||
/* list of the supported boards */
|
||||
static char *board[] __initdata = {
|
||||
"Keymile,KMETER1",
|
||||
"Keymile,kmpbec8321",
|
||||
NULL
|
||||
};
|
||||
|
||||
/*
|
||||
* Called very early, MMU is off, device-tree isn't unflattened
|
||||
*/
|
||||
static int __init kmeter1_probe(void)
|
||||
static int __init mpc83xx_km_probe(void)
|
||||
{
|
||||
unsigned long root = of_get_flat_dt_root();
|
||||
unsigned long node = of_get_flat_dt_root();
|
||||
int i = 0;
|
||||
|
||||
return of_flat_dt_is_compatible(root, "keymile,KMETER1");
|
||||
while (board[i]) {
|
||||
if (of_flat_dt_is_compatible(node, board[i]))
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
return (board[i] != NULL);
|
||||
}
|
||||
|
||||
define_machine(kmeter1) {
|
||||
.name = "KMETER1",
|
||||
.probe = kmeter1_probe,
|
||||
.setup_arch = kmeter1_setup_arch,
|
||||
.init_IRQ = kmeter1_init_IRQ,
|
||||
define_machine(mpc83xx_km) {
|
||||
.name = "mpc83xx-km-platform",
|
||||
.probe = mpc83xx_km_probe,
|
||||
.setup_arch = mpc83xx_km_setup_arch,
|
||||
.init_IRQ = mpc83xx_km_init_IRQ,
|
||||
.get_irq = ipic_get_irq,
|
||||
.restart = mpc83xx_restart,
|
||||
.time_init = mpc83xx_time_init,
|
|
@ -56,12 +56,13 @@ static void machine_restart(char *cmd)
|
|||
|
||||
static void cpm2_cascade(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = get_irq_desc_chip(desc);
|
||||
int cascade_irq;
|
||||
|
||||
while ((cascade_irq = cpm2_get_irq()) >= 0)
|
||||
generic_handle_irq(cascade_irq);
|
||||
|
||||
desc->chip->eoi(irq);
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
}
|
||||
|
||||
static void __init ksi8560_pic_init(void)
|
||||
|
|
|
@ -50,12 +50,13 @@ static int mpc85xx_exclude_device(struct pci_controller *hose,
|
|||
|
||||
static void cpm2_cascade(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = get_irq_desc_chip(desc);
|
||||
int cascade_irq;
|
||||
|
||||
while ((cascade_irq = cpm2_get_irq()) >= 0)
|
||||
generic_handle_irq(cascade_irq);
|
||||
|
||||
desc->chip->eoi(irq);
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_CPM2 */
|
||||
|
|
|
@ -47,12 +47,13 @@
|
|||
#ifdef CONFIG_PPC_I8259
|
||||
static void mpc85xx_8259_cascade(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = get_irq_desc_chip(desc);
|
||||
unsigned int cascade_irq = i8259_irq();
|
||||
|
||||
if (cascade_irq != NO_IRQ) {
|
||||
generic_handle_irq(cascade_irq);
|
||||
}
|
||||
desc->chip->eoi(irq);
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
}
|
||||
#endif /* CONFIG_PPC_I8259 */
|
||||
|
||||
|
|
|
@ -41,12 +41,13 @@
|
|||
|
||||
static void cpm2_cascade(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = get_irq_desc_chip(desc);
|
||||
int cascade_irq;
|
||||
|
||||
while ((cascade_irq = cpm2_get_irq()) >= 0)
|
||||
generic_handle_irq(cascade_irq);
|
||||
|
||||
desc->chip->eoi(irq);
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_CPM2 */
|
||||
|
|
|
@ -91,10 +91,14 @@ smp_85xx_kick_cpu(int nr)
|
|||
while ((__secondary_hold_acknowledge != nr) && (++n < 1000))
|
||||
mdelay(1);
|
||||
#else
|
||||
smp_generic_kick_cpu(nr);
|
||||
|
||||
out_be64((u64 *)(bptr_vaddr + BOOT_ENTRY_ADDR_UPPER),
|
||||
__pa((u64)*((unsigned long long *) generic_secondary_smp_init)));
|
||||
|
||||
smp_generic_kick_cpu(nr);
|
||||
if (!ioremappable)
|
||||
flush_dcache_range((ulong)bptr_vaddr,
|
||||
(ulong)(bptr_vaddr + SIZE_BOOT_ENTRY));
|
||||
#endif
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
|
|
@ -93,6 +93,7 @@ static inline unsigned int socrates_fpga_pic_get_irq(unsigned int irq)
|
|||
|
||||
void socrates_fpga_pic_cascade(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = get_irq_desc_chip(desc);
|
||||
unsigned int cascade_irq;
|
||||
|
||||
/*
|
||||
|
@ -103,17 +104,16 @@ void socrates_fpga_pic_cascade(unsigned int irq, struct irq_desc *desc)
|
|||
|
||||
if (cascade_irq != NO_IRQ)
|
||||
generic_handle_irq(cascade_irq);
|
||||
desc->chip->eoi(irq);
|
||||
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
}
|
||||
|
||||
static void socrates_fpga_pic_ack(unsigned int virq)
|
||||
static void socrates_fpga_pic_ack(struct irq_data *d)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int hwirq, irq_line;
|
||||
uint32_t mask;
|
||||
|
||||
hwirq = socrates_fpga_irq_to_hw(virq);
|
||||
hwirq = socrates_fpga_irq_to_hw(d->irq);
|
||||
|
||||
irq_line = fpga_irqs[hwirq].irq_line;
|
||||
raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
|
||||
|
@ -124,14 +124,14 @@ static void socrates_fpga_pic_ack(unsigned int virq)
|
|||
raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
|
||||
}
|
||||
|
||||
static void socrates_fpga_pic_mask(unsigned int virq)
|
||||
static void socrates_fpga_pic_mask(struct irq_data *d)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int hwirq;
|
||||
int irq_line;
|
||||
u32 mask;
|
||||
|
||||
hwirq = socrates_fpga_irq_to_hw(virq);
|
||||
hwirq = socrates_fpga_irq_to_hw(d->irq);
|
||||
|
||||
irq_line = fpga_irqs[hwirq].irq_line;
|
||||
raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
|
||||
|
@ -142,14 +142,14 @@ static void socrates_fpga_pic_mask(unsigned int virq)
|
|||
raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
|
||||
}
|
||||
|
||||
static void socrates_fpga_pic_mask_ack(unsigned int virq)
|
||||
static void socrates_fpga_pic_mask_ack(struct irq_data *d)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int hwirq;
|
||||
int irq_line;
|
||||
u32 mask;
|
||||
|
||||
hwirq = socrates_fpga_irq_to_hw(virq);
|
||||
hwirq = socrates_fpga_irq_to_hw(d->irq);
|
||||
|
||||
irq_line = fpga_irqs[hwirq].irq_line;
|
||||
raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
|
||||
|
@ -161,14 +161,14 @@ static void socrates_fpga_pic_mask_ack(unsigned int virq)
|
|||
raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
|
||||
}
|
||||
|
||||
static void socrates_fpga_pic_unmask(unsigned int virq)
|
||||
static void socrates_fpga_pic_unmask(struct irq_data *d)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int hwirq;
|
||||
int irq_line;
|
||||
u32 mask;
|
||||
|
||||
hwirq = socrates_fpga_irq_to_hw(virq);
|
||||
hwirq = socrates_fpga_irq_to_hw(d->irq);
|
||||
|
||||
irq_line = fpga_irqs[hwirq].irq_line;
|
||||
raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
|
||||
|
@ -179,14 +179,14 @@ static void socrates_fpga_pic_unmask(unsigned int virq)
|
|||
raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
|
||||
}
|
||||
|
||||
static void socrates_fpga_pic_eoi(unsigned int virq)
|
||||
static void socrates_fpga_pic_eoi(struct irq_data *d)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int hwirq;
|
||||
int irq_line;
|
||||
u32 mask;
|
||||
|
||||
hwirq = socrates_fpga_irq_to_hw(virq);
|
||||
hwirq = socrates_fpga_irq_to_hw(d->irq);
|
||||
|
||||
irq_line = fpga_irqs[hwirq].irq_line;
|
||||
raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
|
||||
|
@ -197,7 +197,7 @@ static void socrates_fpga_pic_eoi(unsigned int virq)
|
|||
raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
|
||||
}
|
||||
|
||||
static int socrates_fpga_pic_set_type(unsigned int virq,
|
||||
static int socrates_fpga_pic_set_type(struct irq_data *d,
|
||||
unsigned int flow_type)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
@ -205,7 +205,7 @@ static int socrates_fpga_pic_set_type(unsigned int virq,
|
|||
int polarity;
|
||||
u32 mask;
|
||||
|
||||
hwirq = socrates_fpga_irq_to_hw(virq);
|
||||
hwirq = socrates_fpga_irq_to_hw(d->irq);
|
||||
|
||||
if (fpga_irqs[hwirq].type != IRQ_TYPE_NONE)
|
||||
return -EINVAL;
|
||||
|
@ -233,12 +233,12 @@ static int socrates_fpga_pic_set_type(unsigned int virq,
|
|||
|
||||
static struct irq_chip socrates_fpga_pic_chip = {
|
||||
.name = "FPGA-PIC",
|
||||
.ack = socrates_fpga_pic_ack,
|
||||
.mask = socrates_fpga_pic_mask,
|
||||
.mask_ack = socrates_fpga_pic_mask_ack,
|
||||
.unmask = socrates_fpga_pic_unmask,
|
||||
.eoi = socrates_fpga_pic_eoi,
|
||||
.set_type = socrates_fpga_pic_set_type,
|
||||
.irq_ack = socrates_fpga_pic_ack,
|
||||
.irq_mask = socrates_fpga_pic_mask,
|
||||
.irq_mask_ack = socrates_fpga_pic_mask_ack,
|
||||
.irq_unmask = socrates_fpga_pic_unmask,
|
||||
.irq_eoi = socrates_fpga_pic_eoi,
|
||||
.irq_set_type = socrates_fpga_pic_set_type,
|
||||
};
|
||||
|
||||
static int socrates_fpga_pic_host_map(struct irq_host *h, unsigned int virq,
|
||||
|
|
|
@ -46,12 +46,13 @@
|
|||
|
||||
static void cpm2_cascade(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = get_irq_desc_chip(desc);
|
||||
int cascade_irq;
|
||||
|
||||
while ((cascade_irq = cpm2_get_irq()) >= 0)
|
||||
generic_handle_irq(cascade_irq);
|
||||
|
||||
desc->chip->eoi(irq);
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
}
|
||||
#endif /* CONFIG_CPM2 */
|
||||
|
||||
|
|
|
@ -44,12 +44,13 @@
|
|||
|
||||
static void cpm2_cascade(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = get_irq_desc_chip(desc);
|
||||
int cascade_irq;
|
||||
|
||||
while ((cascade_irq = cpm2_get_irq()) >= 0)
|
||||
generic_handle_irq(cascade_irq);
|
||||
|
||||
desc->chip->eoi(irq);
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
}
|
||||
#endif /* CONFIG_CPM2 */
|
||||
|
||||
|
|
|
@ -95,6 +95,7 @@ static int gef_pic_cascade_irq;
|
|||
|
||||
void gef_pic_cascade(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = get_irq_desc_chip(desc);
|
||||
unsigned int cascade_irq;
|
||||
|
||||
/*
|
||||
|
@ -106,17 +107,16 @@ void gef_pic_cascade(unsigned int irq, struct irq_desc *desc)
|
|||
if (cascade_irq != NO_IRQ)
|
||||
generic_handle_irq(cascade_irq);
|
||||
|
||||
desc->chip->eoi(irq);
|
||||
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
}
|
||||
|
||||
static void gef_pic_mask(unsigned int virq)
|
||||
static void gef_pic_mask(struct irq_data *d)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int hwirq;
|
||||
u32 mask;
|
||||
|
||||
hwirq = gef_irq_to_hw(virq);
|
||||
hwirq = gef_irq_to_hw(d->irq);
|
||||
|
||||
raw_spin_lock_irqsave(&gef_pic_lock, flags);
|
||||
mask = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0));
|
||||
|
@ -125,21 +125,21 @@ static void gef_pic_mask(unsigned int virq)
|
|||
raw_spin_unlock_irqrestore(&gef_pic_lock, flags);
|
||||
}
|
||||
|
||||
static void gef_pic_mask_ack(unsigned int virq)
|
||||
static void gef_pic_mask_ack(struct irq_data *d)
|
||||
{
|
||||
/* Don't think we actually have to do anything to ack an interrupt,
|
||||
* we just need to clear down the devices interrupt and it will go away
|
||||
*/
|
||||
gef_pic_mask(virq);
|
||||
gef_pic_mask(d);
|
||||
}
|
||||
|
||||
static void gef_pic_unmask(unsigned int virq)
|
||||
static void gef_pic_unmask(struct irq_data *d)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int hwirq;
|
||||
u32 mask;
|
||||
|
||||
hwirq = gef_irq_to_hw(virq);
|
||||
hwirq = gef_irq_to_hw(d->irq);
|
||||
|
||||
raw_spin_lock_irqsave(&gef_pic_lock, flags);
|
||||
mask = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0));
|
||||
|
@ -150,9 +150,9 @@ static void gef_pic_unmask(unsigned int virq)
|
|||
|
||||
static struct irq_chip gef_pic_chip = {
|
||||
.name = "gefp",
|
||||
.mask = gef_pic_mask,
|
||||
.mask_ack = gef_pic_mask_ack,
|
||||
.unmask = gef_pic_unmask,
|
||||
.irq_mask = gef_pic_mask,
|
||||
.irq_mask_ack = gef_pic_mask_ack,
|
||||
.irq_unmask = gef_pic_unmask,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -19,10 +19,13 @@
|
|||
#ifdef CONFIG_PPC_I8259
|
||||
static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = get_irq_desc_chip(desc);
|
||||
unsigned int cascade_irq = i8259_irq();
|
||||
|
||||
if (cascade_irq != NO_IRQ)
|
||||
generic_handle_irq(cascade_irq);
|
||||
desc->chip->eoi(irq);
|
||||
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
}
|
||||
#endif /* CONFIG_PPC_I8259 */
|
||||
|
||||
|
|
|
@ -49,12 +49,6 @@ config PPC_ADDER875
|
|||
This enables support for the Analogue & Micro Adder 875
|
||||
board.
|
||||
|
||||
config PPC_MGSUVD
|
||||
bool "MGSUVD"
|
||||
select CPM1
|
||||
help
|
||||
This enables support for the Keymile MGSUVD board.
|
||||
|
||||
config TQM8XX
|
||||
bool "TQM8XX"
|
||||
select CPM1
|
||||
|
|
|
@ -6,5 +6,4 @@ obj-$(CONFIG_MPC885ADS) += mpc885ads_setup.o
|
|||
obj-$(CONFIG_MPC86XADS) += mpc86xads_setup.o
|
||||
obj-$(CONFIG_PPC_EP88XC) += ep88xc.o
|
||||
obj-$(CONFIG_PPC_ADDER875) += adder875.o
|
||||
obj-$(CONFIG_PPC_MGSUVD) += mgsuvd.o
|
||||
obj-$(CONFIG_TQM8XX) += tqm8xx_setup.o
|
||||
|
|
|
@ -218,15 +218,20 @@ void mpc8xx_restart(char *cmd)
|
|||
|
||||
static void cpm_cascade(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip;
|
||||
int cascade_irq;
|
||||
|
||||
if ((cascade_irq = cpm_get_irq()) >= 0) {
|
||||
struct irq_desc *cdesc = irq_to_desc(cascade_irq);
|
||||
|
||||
generic_handle_irq(cascade_irq);
|
||||
cdesc->chip->eoi(cascade_irq);
|
||||
|
||||
chip = get_irq_desc_chip(cdesc);
|
||||
chip->irq_eoi(&cdesc->irq_data);
|
||||
}
|
||||
desc->chip->eoi(irq);
|
||||
|
||||
chip = get_irq_desc_chip(desc);
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
}
|
||||
|
||||
/* Initialize the internal interrupt controllers. The number of
|
||||
|
|
|
@ -1,92 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Platform setup for the Keymile mgsuvd board
|
||||
*
|
||||
* Heiko Schocher <hs@denx.de>
|
||||
*
|
||||
* Copyright 2008 DENX Software Engineering GmbH
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public License
|
||||
* version 2. This program is licensed "as is" without any warranty of any
|
||||
* kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/cpm1.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/fs_pd.h>
|
||||
|
||||
#include "mpc8xx.h"
|
||||
|
||||
struct cpm_pin {
|
||||
int port, pin, flags;
|
||||
};
|
||||
|
||||
static __initdata struct cpm_pin mgsuvd_pins[] = {
|
||||
/* SMC1 */
|
||||
{CPM_PORTB, 24, CPM_PIN_INPUT}, /* RX */
|
||||
{CPM_PORTB, 25, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* TX */
|
||||
|
||||
/* SCC3 */
|
||||
{CPM_PORTA, 10, CPM_PIN_INPUT},
|
||||
{CPM_PORTA, 11, CPM_PIN_INPUT},
|
||||
{CPM_PORTA, 3, CPM_PIN_INPUT},
|
||||
{CPM_PORTA, 2, CPM_PIN_INPUT},
|
||||
{CPM_PORTC, 13, CPM_PIN_INPUT},
|
||||
};
|
||||
|
||||
static void __init init_ioports(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mgsuvd_pins); i++) {
|
||||
struct cpm_pin *pin = &mgsuvd_pins[i];
|
||||
cpm1_set_pin(pin->port, pin->pin, pin->flags);
|
||||
}
|
||||
|
||||
setbits16(&mpc8xx_immr->im_ioport.iop_pcso, 0x300);
|
||||
cpm1_clk_setup(CPM_CLK_SCC3, CPM_CLK5, CPM_CLK_RX);
|
||||
cpm1_clk_setup(CPM_CLK_SCC3, CPM_CLK6, CPM_CLK_TX);
|
||||
cpm1_clk_setup(CPM_CLK_SMC1, CPM_BRG1, CPM_CLK_RTX);
|
||||
}
|
||||
|
||||
static void __init mgsuvd_setup_arch(void)
|
||||
{
|
||||
cpm_reset();
|
||||
init_ioports();
|
||||
}
|
||||
|
||||
static __initdata struct of_device_id of_bus_ids[] = {
|
||||
{ .compatible = "simple-bus" },
|
||||
{},
|
||||
};
|
||||
|
||||
static int __init declare_of_platform_devices(void)
|
||||
{
|
||||
of_platform_bus_probe(NULL, of_bus_ids, NULL);
|
||||
return 0;
|
||||
}
|
||||
machine_device_initcall(mgsuvd, declare_of_platform_devices);
|
||||
|
||||
static int __init mgsuvd_probe(void)
|
||||
{
|
||||
unsigned long root = of_get_flat_dt_root();
|
||||
return of_flat_dt_is_compatible(root, "keymile,mgsuvd");
|
||||
}
|
||||
|
||||
define_machine(mgsuvd) {
|
||||
.name = "MGSUVD",
|
||||
.probe = mgsuvd_probe,
|
||||
.setup_arch = mgsuvd_setup_arch,
|
||||
.init_IRQ = mpc8xx_pics_init,
|
||||
.get_irq = mpc8xx_get_irq,
|
||||
.restart = mpc8xx_restart,
|
||||
.calibrate_decr = mpc8xx_calibrate_decr,
|
||||
.set_rtc_time = mpc8xx_set_rtc_time,
|
||||
.get_rtc_time = mpc8xx_get_rtc_time,
|
||||
};
|
|
@ -93,6 +93,7 @@ static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val)
|
|||
|
||||
static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = get_irq_desc_chip(desc);
|
||||
struct axon_msic *msic = get_irq_data(irq);
|
||||
u32 write_offset, msi;
|
||||
int idx;
|
||||
|
@ -145,7 +146,7 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
|
|||
msic->read_offset &= MSIC_FIFO_SIZE_MASK;
|
||||
}
|
||||
|
||||
desc->chip->eoi(irq);
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
}
|
||||
|
||||
static struct axon_msic *find_msi_translator(struct pci_dev *dev)
|
||||
|
|
|
@ -61,59 +61,59 @@ static inline void beatic_update_irq_mask(unsigned int irq_plug)
|
|||
panic("Failed to set mask IRQ!");
|
||||
}
|
||||
|
||||
static void beatic_mask_irq(unsigned int irq_plug)
|
||||
static void beatic_mask_irq(struct irq_data *d)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
raw_spin_lock_irqsave(&beatic_irq_mask_lock, flags);
|
||||
beatic_irq_mask_enable[irq_plug/64] &= ~(1UL << (63 - (irq_plug%64)));
|
||||
beatic_update_irq_mask(irq_plug);
|
||||
beatic_irq_mask_enable[d->irq/64] &= ~(1UL << (63 - (d->irq%64)));
|
||||
beatic_update_irq_mask(d->irq);
|
||||
raw_spin_unlock_irqrestore(&beatic_irq_mask_lock, flags);
|
||||
}
|
||||
|
||||
static void beatic_unmask_irq(unsigned int irq_plug)
|
||||
static void beatic_unmask_irq(struct irq_data *d)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
raw_spin_lock_irqsave(&beatic_irq_mask_lock, flags);
|
||||
beatic_irq_mask_enable[irq_plug/64] |= 1UL << (63 - (irq_plug%64));
|
||||
beatic_update_irq_mask(irq_plug);
|
||||
beatic_irq_mask_enable[d->irq/64] |= 1UL << (63 - (d->irq%64));
|
||||
beatic_update_irq_mask(d->irq);
|
||||
raw_spin_unlock_irqrestore(&beatic_irq_mask_lock, flags);
|
||||
}
|
||||
|
||||
static void beatic_ack_irq(unsigned int irq_plug)
|
||||
static void beatic_ack_irq(struct irq_data *d)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
raw_spin_lock_irqsave(&beatic_irq_mask_lock, flags);
|
||||
beatic_irq_mask_ack[irq_plug/64] &= ~(1UL << (63 - (irq_plug%64)));
|
||||
beatic_update_irq_mask(irq_plug);
|
||||
beatic_irq_mask_ack[d->irq/64] &= ~(1UL << (63 - (d->irq%64)));
|
||||
beatic_update_irq_mask(d->irq);
|
||||
raw_spin_unlock_irqrestore(&beatic_irq_mask_lock, flags);
|
||||
}
|
||||
|
||||
static void beatic_end_irq(unsigned int irq_plug)
|
||||
static void beatic_end_irq(struct irq_data *d)
|
||||
{
|
||||
s64 err;
|
||||
unsigned long flags;
|
||||
|
||||
err = beat_downcount_of_interrupt(irq_plug);
|
||||
err = beat_downcount_of_interrupt(d->irq);
|
||||
if (err != 0) {
|
||||
if ((err & 0xFFFFFFFF) != 0xFFFFFFF5) /* -11: wrong state */
|
||||
panic("Failed to downcount IRQ! Error = %16llx", err);
|
||||
|
||||
printk(KERN_ERR "IRQ over-downcounted, plug %d\n", irq_plug);
|
||||
printk(KERN_ERR "IRQ over-downcounted, plug %d\n", d->irq);
|
||||
}
|
||||
raw_spin_lock_irqsave(&beatic_irq_mask_lock, flags);
|
||||
beatic_irq_mask_ack[irq_plug/64] |= 1UL << (63 - (irq_plug%64));
|
||||
beatic_update_irq_mask(irq_plug);
|
||||
beatic_irq_mask_ack[d->irq/64] |= 1UL << (63 - (d->irq%64));
|
||||
beatic_update_irq_mask(d->irq);
|
||||
raw_spin_unlock_irqrestore(&beatic_irq_mask_lock, flags);
|
||||
}
|
||||
|
||||
static struct irq_chip beatic_pic = {
|
||||
.name = "CELL-BEAT",
|
||||
.unmask = beatic_unmask_irq,
|
||||
.mask = beatic_mask_irq,
|
||||
.eoi = beatic_end_irq,
|
||||
.irq_unmask = beatic_unmask_irq,
|
||||
.irq_mask = beatic_mask_irq,
|
||||
.irq_eoi = beatic_end_irq,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -232,7 +232,7 @@ unsigned int beatic_get_irq(void)
|
|||
|
||||
ret = beatic_get_irq_plug();
|
||||
if (ret != NO_IRQ)
|
||||
beatic_ack_irq(ret);
|
||||
beatic_ack_irq(irq_get_irq_data(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -72,15 +72,15 @@ static irq_hw_number_t iic_pending_to_hwnum(struct cbe_iic_pending_bits bits)
|
|||
return (node << IIC_IRQ_NODE_SHIFT) | (class << 4) | unit;
|
||||
}
|
||||
|
||||
static void iic_mask(unsigned int irq)
|
||||
static void iic_mask(struct irq_data *d)
|
||||
{
|
||||
}
|
||||
|
||||
static void iic_unmask(unsigned int irq)
|
||||
static void iic_unmask(struct irq_data *d)
|
||||
{
|
||||
}
|
||||
|
||||
static void iic_eoi(unsigned int irq)
|
||||
static void iic_eoi(struct irq_data *d)
|
||||
{
|
||||
struct iic *iic = &__get_cpu_var(cpu_iic);
|
||||
out_be64(&iic->regs->prio, iic->eoi_stack[--iic->eoi_ptr]);
|
||||
|
@ -89,19 +89,21 @@ static void iic_eoi(unsigned int irq)
|
|||
|
||||
static struct irq_chip iic_chip = {
|
||||
.name = "CELL-IIC",
|
||||
.mask = iic_mask,
|
||||
.unmask = iic_unmask,
|
||||
.eoi = iic_eoi,
|
||||
.irq_mask = iic_mask,
|
||||
.irq_unmask = iic_unmask,
|
||||
.irq_eoi = iic_eoi,
|
||||
};
|
||||
|
||||
|
||||
static void iic_ioexc_eoi(unsigned int irq)
|
||||
static void iic_ioexc_eoi(struct irq_data *d)
|
||||
{
|
||||
}
|
||||
|
||||
static void iic_ioexc_cascade(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct cbe_iic_regs __iomem *node_iic = (void __iomem *)desc->handler_data;
|
||||
struct irq_chip *chip = get_irq_desc_chip(desc);
|
||||
struct cbe_iic_regs __iomem *node_iic =
|
||||
(void __iomem *)get_irq_desc_data(desc);
|
||||
unsigned int base = (irq & 0xffffff00) | IIC_IRQ_TYPE_IOEXC;
|
||||
unsigned long bits, ack;
|
||||
int cascade;
|
||||
|
@ -128,15 +130,15 @@ static void iic_ioexc_cascade(unsigned int irq, struct irq_desc *desc)
|
|||
if (ack)
|
||||
out_be64(&node_iic->iic_is, ack);
|
||||
}
|
||||
desc->chip->eoi(irq);
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
}
|
||||
|
||||
|
||||
static struct irq_chip iic_ioexc_chip = {
|
||||
.name = "CELL-IOEX",
|
||||
.mask = iic_mask,
|
||||
.unmask = iic_unmask,
|
||||
.eoi = iic_ioexc_eoi,
|
||||
.irq_mask = iic_mask,
|
||||
.irq_unmask = iic_unmask,
|
||||
.irq_eoi = iic_ioexc_eoi,
|
||||
};
|
||||
|
||||
/* Get an IRQ number from the pending state register of the IIC */
|
||||
|
@ -237,6 +239,8 @@ extern int noirqdebug;
|
|||
|
||||
static void handle_iic_irq(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = get_irq_desc_chip(desc);
|
||||
|
||||
raw_spin_lock(&desc->lock);
|
||||
|
||||
desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
|
||||
|
@ -275,7 +279,7 @@ static void handle_iic_irq(unsigned int irq, struct irq_desc *desc)
|
|||
|
||||
desc->status &= ~IRQ_INPROGRESS;
|
||||
out_eoi:
|
||||
desc->chip->eoi(irq);
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
raw_spin_unlock(&desc->lock);
|
||||
}
|
||||
|
||||
|
|
|
@ -187,13 +187,15 @@ machine_subsys_initcall(cell, cell_publish_devices);
|
|||
|
||||
static void cell_mpic_cascade(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct mpic *mpic = desc->handler_data;
|
||||
struct irq_chip *chip = get_irq_desc_chip(desc);
|
||||
struct mpic *mpic = get_irq_desc_data(desc);
|
||||
unsigned int virq;
|
||||
|
||||
virq = mpic_get_one_irq(mpic);
|
||||
if (virq != NO_IRQ)
|
||||
generic_handle_irq(virq);
|
||||
desc->chip->eoi(irq);
|
||||
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
}
|
||||
|
||||
static void __init mpic_init_IRQ(void)
|
||||
|
|
|
@ -79,30 +79,30 @@ static void __iomem *spider_get_irq_config(struct spider_pic *pic,
|
|||
return pic->regs + TIR_CFGA + 8 * src;
|
||||
}
|
||||
|
||||
static void spider_unmask_irq(unsigned int virq)
|
||||
static void spider_unmask_irq(struct irq_data *d)
|
||||
{
|
||||
struct spider_pic *pic = spider_virq_to_pic(virq);
|
||||
void __iomem *cfg = spider_get_irq_config(pic, irq_map[virq].hwirq);
|
||||
struct spider_pic *pic = spider_virq_to_pic(d->irq);
|
||||
void __iomem *cfg = spider_get_irq_config(pic, irq_map[d->irq].hwirq);
|
||||
|
||||
out_be32(cfg, in_be32(cfg) | 0x30000000u);
|
||||
}
|
||||
|
||||
static void spider_mask_irq(unsigned int virq)
|
||||
static void spider_mask_irq(struct irq_data *d)
|
||||
{
|
||||
struct spider_pic *pic = spider_virq_to_pic(virq);
|
||||
void __iomem *cfg = spider_get_irq_config(pic, irq_map[virq].hwirq);
|
||||
struct spider_pic *pic = spider_virq_to_pic(d->irq);
|
||||
void __iomem *cfg = spider_get_irq_config(pic, irq_map[d->irq].hwirq);
|
||||
|
||||
out_be32(cfg, in_be32(cfg) & ~0x30000000u);
|
||||
}
|
||||
|
||||
static void spider_ack_irq(unsigned int virq)
|
||||
static void spider_ack_irq(struct irq_data *d)
|
||||
{
|
||||
struct spider_pic *pic = spider_virq_to_pic(virq);
|
||||
unsigned int src = irq_map[virq].hwirq;
|
||||
struct spider_pic *pic = spider_virq_to_pic(d->irq);
|
||||
unsigned int src = irq_map[d->irq].hwirq;
|
||||
|
||||
/* Reset edge detection logic if necessary
|
||||
*/
|
||||
if (irq_to_desc(virq)->status & IRQ_LEVEL)
|
||||
if (irq_to_desc(d->irq)->status & IRQ_LEVEL)
|
||||
return;
|
||||
|
||||
/* Only interrupts 47 to 50 can be set to edge */
|
||||
|
@ -113,13 +113,13 @@ static void spider_ack_irq(unsigned int virq)
|
|||
out_be32(pic->regs + TIR_EDC, 0x100 | (src & 0xf));
|
||||
}
|
||||
|
||||
static int spider_set_irq_type(unsigned int virq, unsigned int type)
|
||||
static int spider_set_irq_type(struct irq_data *d, unsigned int type)
|
||||
{
|
||||
unsigned int sense = type & IRQ_TYPE_SENSE_MASK;
|
||||
struct spider_pic *pic = spider_virq_to_pic(virq);
|
||||
unsigned int hw = irq_map[virq].hwirq;
|
||||
struct spider_pic *pic = spider_virq_to_pic(d->irq);
|
||||
unsigned int hw = irq_map[d->irq].hwirq;
|
||||
void __iomem *cfg = spider_get_irq_config(pic, hw);
|
||||
struct irq_desc *desc = irq_to_desc(virq);
|
||||
struct irq_desc *desc = irq_to_desc(d->irq);
|
||||
u32 old_mask;
|
||||
u32 ic;
|
||||
|
||||
|
@ -169,10 +169,10 @@ static int spider_set_irq_type(unsigned int virq, unsigned int type)
|
|||
|
||||
static struct irq_chip spider_pic = {
|
||||
.name = "SPIDER",
|
||||
.unmask = spider_unmask_irq,
|
||||
.mask = spider_mask_irq,
|
||||
.ack = spider_ack_irq,
|
||||
.set_type = spider_set_irq_type,
|
||||
.irq_unmask = spider_unmask_irq,
|
||||
.irq_mask = spider_mask_irq,
|
||||
.irq_ack = spider_ack_irq,
|
||||
.irq_set_type = spider_set_irq_type,
|
||||
};
|
||||
|
||||
static int spider_host_map(struct irq_host *h, unsigned int virq,
|
||||
|
@ -207,7 +207,8 @@ static struct irq_host_ops spider_host_ops = {
|
|||
|
||||
static void spider_irq_cascade(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct spider_pic *pic = desc->handler_data;
|
||||
struct irq_chip *chip = get_irq_desc_chip(desc);
|
||||
struct spider_pic *pic = get_irq_desc_data(desc);
|
||||
unsigned int cs, virq;
|
||||
|
||||
cs = in_be32(pic->regs + TIR_CS) >> 24;
|
||||
|
@ -215,9 +216,11 @@ static void spider_irq_cascade(unsigned int irq, struct irq_desc *desc)
|
|||
virq = NO_IRQ;
|
||||
else
|
||||
virq = irq_linear_revmap(pic->host, cs);
|
||||
|
||||
if (virq != NO_IRQ)
|
||||
generic_handle_irq(virq);
|
||||
desc->chip->eoi(irq);
|
||||
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
}
|
||||
|
||||
/* For hooking up the cascace we have a problem. Our device-tree is
|
||||
|
|
|
@ -365,10 +365,13 @@ void __init chrp_setup_arch(void)
|
|||
|
||||
static void chrp_8259_cascade(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = get_irq_desc_chip(desc);
|
||||
unsigned int cascade_irq = i8259_irq();
|
||||
|
||||
if (cascade_irq != NO_IRQ)
|
||||
generic_handle_irq(cascade_irq);
|
||||
desc->chip->eoi(irq);
|
||||
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -46,10 +46,10 @@
|
|||
*
|
||||
*/
|
||||
|
||||
static void flipper_pic_mask_and_ack(unsigned int virq)
|
||||
static void flipper_pic_mask_and_ack(struct irq_data *d)
|
||||
{
|
||||
int irq = virq_to_hw(virq);
|
||||
void __iomem *io_base = get_irq_chip_data(virq);
|
||||
int irq = virq_to_hw(d->irq);
|
||||
void __iomem *io_base = irq_data_get_irq_chip_data(d);
|
||||
u32 mask = 1 << irq;
|
||||
|
||||
clrbits32(io_base + FLIPPER_IMR, mask);
|
||||
|
@ -57,27 +57,27 @@ static void flipper_pic_mask_and_ack(unsigned int virq)
|
|||
out_be32(io_base + FLIPPER_ICR, mask);
|
||||
}
|
||||
|
||||
static void flipper_pic_ack(unsigned int virq)
|
||||
static void flipper_pic_ack(struct irq_data *d)
|
||||
{
|
||||
int irq = virq_to_hw(virq);
|
||||
void __iomem *io_base = get_irq_chip_data(virq);
|
||||
int irq = virq_to_hw(d->irq);
|
||||
void __iomem *io_base = irq_data_get_irq_chip_data(d);
|
||||
|
||||
/* this is at least needed for RSW */
|
||||
out_be32(io_base + FLIPPER_ICR, 1 << irq);
|
||||
}
|
||||
|
||||
static void flipper_pic_mask(unsigned int virq)
|
||||
static void flipper_pic_mask(struct irq_data *d)
|
||||
{
|
||||
int irq = virq_to_hw(virq);
|
||||
void __iomem *io_base = get_irq_chip_data(virq);
|
||||
int irq = virq_to_hw(d->irq);
|
||||
void __iomem *io_base = irq_data_get_irq_chip_data(d);
|
||||
|
||||
clrbits32(io_base + FLIPPER_IMR, 1 << irq);
|
||||
}
|
||||
|
||||
static void flipper_pic_unmask(unsigned int virq)
|
||||
static void flipper_pic_unmask(struct irq_data *d)
|
||||
{
|
||||
int irq = virq_to_hw(virq);
|
||||
void __iomem *io_base = get_irq_chip_data(virq);
|
||||
int irq = virq_to_hw(d->irq);
|
||||
void __iomem *io_base = irq_data_get_irq_chip_data(d);
|
||||
|
||||
setbits32(io_base + FLIPPER_IMR, 1 << irq);
|
||||
}
|
||||
|
@ -85,10 +85,10 @@ static void flipper_pic_unmask(unsigned int virq)
|
|||
|
||||
static struct irq_chip flipper_pic = {
|
||||
.name = "flipper-pic",
|
||||
.ack = flipper_pic_ack,
|
||||
.mask_ack = flipper_pic_mask_and_ack,
|
||||
.mask = flipper_pic_mask,
|
||||
.unmask = flipper_pic_unmask,
|
||||
.irq_ack = flipper_pic_ack,
|
||||
.irq_mask_ack = flipper_pic_mask_and_ack,
|
||||
.irq_mask = flipper_pic_mask,
|
||||
.irq_unmask = flipper_pic_unmask,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -41,36 +41,36 @@
|
|||
*
|
||||
*/
|
||||
|
||||
static void hlwd_pic_mask_and_ack(unsigned int virq)
|
||||
static void hlwd_pic_mask_and_ack(struct irq_data *d)
|
||||
{
|
||||
int irq = virq_to_hw(virq);
|
||||
void __iomem *io_base = get_irq_chip_data(virq);
|
||||
int irq = virq_to_hw(d->irq);
|
||||
void __iomem *io_base = irq_data_get_irq_chip_data(d);
|
||||
u32 mask = 1 << irq;
|
||||
|
||||
clrbits32(io_base + HW_BROADWAY_IMR, mask);
|
||||
out_be32(io_base + HW_BROADWAY_ICR, mask);
|
||||
}
|
||||
|
||||
static void hlwd_pic_ack(unsigned int virq)
|
||||
static void hlwd_pic_ack(struct irq_data *d)
|
||||
{
|
||||
int irq = virq_to_hw(virq);
|
||||
void __iomem *io_base = get_irq_chip_data(virq);
|
||||
int irq = virq_to_hw(d->irq);
|
||||
void __iomem *io_base = irq_data_get_irq_chip_data(d);
|
||||
|
||||
out_be32(io_base + HW_BROADWAY_ICR, 1 << irq);
|
||||
}
|
||||
|
||||
static void hlwd_pic_mask(unsigned int virq)
|
||||
static void hlwd_pic_mask(struct irq_data *d)
|
||||
{
|
||||
int irq = virq_to_hw(virq);
|
||||
void __iomem *io_base = get_irq_chip_data(virq);
|
||||
int irq = virq_to_hw(d->irq);
|
||||
void __iomem *io_base = irq_data_get_irq_chip_data(d);
|
||||
|
||||
clrbits32(io_base + HW_BROADWAY_IMR, 1 << irq);
|
||||
}
|
||||
|
||||
static void hlwd_pic_unmask(unsigned int virq)
|
||||
static void hlwd_pic_unmask(struct irq_data *d)
|
||||
{
|
||||
int irq = virq_to_hw(virq);
|
||||
void __iomem *io_base = get_irq_chip_data(virq);
|
||||
int irq = virq_to_hw(d->irq);
|
||||
void __iomem *io_base = irq_data_get_irq_chip_data(d);
|
||||
|
||||
setbits32(io_base + HW_BROADWAY_IMR, 1 << irq);
|
||||
}
|
||||
|
@ -78,10 +78,10 @@ static void hlwd_pic_unmask(unsigned int virq)
|
|||
|
||||
static struct irq_chip hlwd_pic = {
|
||||
.name = "hlwd-pic",
|
||||
.ack = hlwd_pic_ack,
|
||||
.mask_ack = hlwd_pic_mask_and_ack,
|
||||
.mask = hlwd_pic_mask,
|
||||
.unmask = hlwd_pic_unmask,
|
||||
.irq_ack = hlwd_pic_ack,
|
||||
.irq_mask_ack = hlwd_pic_mask_and_ack,
|
||||
.irq_mask = hlwd_pic_mask,
|
||||
.irq_unmask = hlwd_pic_unmask,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -129,11 +129,12 @@ static unsigned int __hlwd_pic_get_irq(struct irq_host *h)
|
|||
static void hlwd_pic_irq_cascade(unsigned int cascade_virq,
|
||||
struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = get_irq_desc_chip(desc);
|
||||
struct irq_host *irq_host = get_irq_data(cascade_virq);
|
||||
unsigned int virq;
|
||||
|
||||
raw_spin_lock(&desc->lock);
|
||||
desc->chip->mask(cascade_virq); /* IRQ_LEVEL */
|
||||
chip->irq_mask(&desc->irq_data); /* IRQ_LEVEL */
|
||||
raw_spin_unlock(&desc->lock);
|
||||
|
||||
virq = __hlwd_pic_get_irq(irq_host);
|
||||
|
@ -143,9 +144,9 @@ static void hlwd_pic_irq_cascade(unsigned int cascade_virq,
|
|||
pr_err("spurious interrupt!\n");
|
||||
|
||||
raw_spin_lock(&desc->lock);
|
||||
desc->chip->ack(cascade_virq); /* IRQ_LEVEL */
|
||||
if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
|
||||
desc->chip->unmask(cascade_virq);
|
||||
chip->irq_ack(&desc->irq_data); /* IRQ_LEVEL */
|
||||
if (!(desc->status & IRQ_DISABLED) && chip->irq_unmask)
|
||||
chip->irq_unmask(&desc->irq_data);
|
||||
raw_spin_unlock(&desc->lock);
|
||||
}
|
||||
|
||||
|
|
|
@ -167,11 +167,11 @@ static void pci_event_handler(struct HvLpEvent *event)
|
|||
* This will be called by device drivers (via enable_IRQ)
|
||||
* to enable INTA in the bridge interrupt status register.
|
||||
*/
|
||||
static void iseries_enable_IRQ(unsigned int irq)
|
||||
static void iseries_enable_IRQ(struct irq_data *d)
|
||||
{
|
||||
u32 bus, dev_id, function, mask;
|
||||
const u32 sub_bus = 0;
|
||||
unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
|
||||
unsigned int rirq = (unsigned int)irq_map[d->irq].hwirq;
|
||||
|
||||
/* The IRQ has already been locked by the caller */
|
||||
bus = REAL_IRQ_TO_BUS(rirq);
|
||||
|
@ -184,23 +184,23 @@ static void iseries_enable_IRQ(unsigned int irq)
|
|||
}
|
||||
|
||||
/* This is called by iseries_activate_IRQs */
|
||||
static unsigned int iseries_startup_IRQ(unsigned int irq)
|
||||
static unsigned int iseries_startup_IRQ(struct irq_data *d)
|
||||
{
|
||||
u32 bus, dev_id, function, mask;
|
||||
const u32 sub_bus = 0;
|
||||
unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
|
||||
unsigned int rirq = (unsigned int)irq_map[d->irq].hwirq;
|
||||
|
||||
bus = REAL_IRQ_TO_BUS(rirq);
|
||||
function = REAL_IRQ_TO_FUNC(rirq);
|
||||
dev_id = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
|
||||
|
||||
/* Link the IRQ number to the bridge */
|
||||
HvCallXm_connectBusUnit(bus, sub_bus, dev_id, irq);
|
||||
HvCallXm_connectBusUnit(bus, sub_bus, dev_id, d->irq);
|
||||
|
||||
/* Unmask bridge interrupts in the FISR */
|
||||
mask = 0x01010000 << function;
|
||||
HvCallPci_unmaskFisr(bus, sub_bus, dev_id, mask);
|
||||
iseries_enable_IRQ(irq);
|
||||
iseries_enable_IRQ(d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -215,21 +215,26 @@ void __init iSeries_activate_IRQs()
|
|||
|
||||
for_each_irq (irq) {
|
||||
struct irq_desc *desc = irq_to_desc(irq);
|
||||
struct irq_chip *chip;
|
||||
|
||||
if (desc && desc->chip && desc->chip->startup) {
|
||||
if (!desc)
|
||||
continue;
|
||||
|
||||
chip = get_irq_desc_chip(desc);
|
||||
if (chip && chip->irq_startup) {
|
||||
raw_spin_lock_irqsave(&desc->lock, flags);
|
||||
desc->chip->startup(irq);
|
||||
chip->irq_startup(&desc->irq_data);
|
||||
raw_spin_unlock_irqrestore(&desc->lock, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* this is not called anywhere currently */
|
||||
static void iseries_shutdown_IRQ(unsigned int irq)
|
||||
static void iseries_shutdown_IRQ(struct irq_data *d)
|
||||
{
|
||||
u32 bus, dev_id, function, mask;
|
||||
const u32 sub_bus = 0;
|
||||
unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
|
||||
unsigned int rirq = (unsigned int)irq_map[d->irq].hwirq;
|
||||
|
||||
/* irq should be locked by the caller */
|
||||
bus = REAL_IRQ_TO_BUS(rirq);
|
||||
|
@ -248,11 +253,11 @@ static void iseries_shutdown_IRQ(unsigned int irq)
|
|||
* This will be called by device drivers (via disable_IRQ)
|
||||
* to disable INTA in the bridge interrupt status register.
|
||||
*/
|
||||
static void iseries_disable_IRQ(unsigned int irq)
|
||||
static void iseries_disable_IRQ(struct irq_data *d)
|
||||
{
|
||||
u32 bus, dev_id, function, mask;
|
||||
const u32 sub_bus = 0;
|
||||
unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
|
||||
unsigned int rirq = (unsigned int)irq_map[d->irq].hwirq;
|
||||
|
||||
/* The IRQ has already been locked by the caller */
|
||||
bus = REAL_IRQ_TO_BUS(rirq);
|
||||
|
@ -264,9 +269,9 @@ static void iseries_disable_IRQ(unsigned int irq)
|
|||
HvCallPci_maskInterrupts(bus, sub_bus, dev_id, mask);
|
||||
}
|
||||
|
||||
static void iseries_end_IRQ(unsigned int irq)
|
||||
static void iseries_end_IRQ(struct irq_data *d)
|
||||
{
|
||||
unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
|
||||
unsigned int rirq = (unsigned int)irq_map[d->irq].hwirq;
|
||||
|
||||
HvCallPci_eoi(REAL_IRQ_TO_BUS(rirq), REAL_IRQ_TO_SUBBUS(rirq),
|
||||
(REAL_IRQ_TO_IDSEL(rirq) << 4) + REAL_IRQ_TO_FUNC(rirq));
|
||||
|
@ -274,11 +279,11 @@ static void iseries_end_IRQ(unsigned int irq)
|
|||
|
||||
static struct irq_chip iseries_pic = {
|
||||
.name = "iSeries",
|
||||
.startup = iseries_startup_IRQ,
|
||||
.shutdown = iseries_shutdown_IRQ,
|
||||
.unmask = iseries_enable_IRQ,
|
||||
.mask = iseries_disable_IRQ,
|
||||
.eoi = iseries_end_IRQ
|
||||
.irq_startup = iseries_startup_IRQ,
|
||||
.irq_shutdown = iseries_shutdown_IRQ,
|
||||
.irq_unmask = iseries_enable_IRQ,
|
||||
.irq_mask = iseries_disable_IRQ,
|
||||
.irq_eoi = iseries_end_IRQ
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -240,7 +240,7 @@ static __init void pas_init_IRQ(void)
|
|||
nmi_virq = irq_create_mapping(NULL, *nmiprop);
|
||||
mpic_irq_set_priority(nmi_virq, 15);
|
||||
set_irq_type(nmi_virq, IRQ_TYPE_EDGE_RISING);
|
||||
mpic_unmask_irq(nmi_virq);
|
||||
mpic_unmask_irq(irq_get_irq_data(nmi_virq));
|
||||
}
|
||||
|
||||
of_node_put(mpic_node);
|
||||
|
@ -266,7 +266,7 @@ static int pas_machine_check_handler(struct pt_regs *regs)
|
|||
if (nmi_virq != NO_IRQ && mpic_get_mcirq() == nmi_virq) {
|
||||
printk(KERN_ERR "NMI delivered\n");
|
||||
debugger(regs);
|
||||
mpic_end_irq(nmi_virq);
|
||||
mpic_end_irq(irq_get_irq_data(nmi_virq));
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
|
@ -82,9 +82,9 @@ static void __pmac_retrigger(unsigned int irq_nr)
|
|||
}
|
||||
}
|
||||
|
||||
static void pmac_mask_and_ack_irq(unsigned int virq)
|
||||
static void pmac_mask_and_ack_irq(struct irq_data *d)
|
||||
{
|
||||
unsigned int src = irq_map[virq].hwirq;
|
||||
unsigned int src = irq_map[d->irq].hwirq;
|
||||
unsigned long bit = 1UL << (src & 0x1f);
|
||||
int i = src >> 5;
|
||||
unsigned long flags;
|
||||
|
@ -104,9 +104,9 @@ static void pmac_mask_and_ack_irq(unsigned int virq)
|
|||
raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);
|
||||
}
|
||||
|
||||
static void pmac_ack_irq(unsigned int virq)
|
||||
static void pmac_ack_irq(struct irq_data *d)
|
||||
{
|
||||
unsigned int src = irq_map[virq].hwirq;
|
||||
unsigned int src = irq_map[d->irq].hwirq;
|
||||
unsigned long bit = 1UL << (src & 0x1f);
|
||||
int i = src >> 5;
|
||||
unsigned long flags;
|
||||
|
@ -149,15 +149,15 @@ static void __pmac_set_irq_mask(unsigned int irq_nr, int nokicklost)
|
|||
/* When an irq gets requested for the first client, if it's an
|
||||
* edge interrupt, we clear any previous one on the controller
|
||||
*/
|
||||
static unsigned int pmac_startup_irq(unsigned int virq)
|
||||
static unsigned int pmac_startup_irq(struct irq_data *d)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int src = irq_map[virq].hwirq;
|
||||
unsigned int src = irq_map[d->irq].hwirq;
|
||||
unsigned long bit = 1UL << (src & 0x1f);
|
||||
int i = src >> 5;
|
||||
|
||||
raw_spin_lock_irqsave(&pmac_pic_lock, flags);
|
||||
if ((irq_to_desc(virq)->status & IRQ_LEVEL) == 0)
|
||||
if ((irq_to_desc(d->irq)->status & IRQ_LEVEL) == 0)
|
||||
out_le32(&pmac_irq_hw[i]->ack, bit);
|
||||
__set_bit(src, ppc_cached_irq_mask);
|
||||
__pmac_set_irq_mask(src, 0);
|
||||
|
@ -166,10 +166,10 @@ static unsigned int pmac_startup_irq(unsigned int virq)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void pmac_mask_irq(unsigned int virq)
|
||||
static void pmac_mask_irq(struct irq_data *d)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int src = irq_map[virq].hwirq;
|
||||
unsigned int src = irq_map[d->irq].hwirq;
|
||||
|
||||
raw_spin_lock_irqsave(&pmac_pic_lock, flags);
|
||||
__clear_bit(src, ppc_cached_irq_mask);
|
||||
|
@ -177,10 +177,10 @@ static void pmac_mask_irq(unsigned int virq)
|
|||
raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);
|
||||
}
|
||||
|
||||
static void pmac_unmask_irq(unsigned int virq)
|
||||
static void pmac_unmask_irq(struct irq_data *d)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int src = irq_map[virq].hwirq;
|
||||
unsigned int src = irq_map[d->irq].hwirq;
|
||||
|
||||
raw_spin_lock_irqsave(&pmac_pic_lock, flags);
|
||||
__set_bit(src, ppc_cached_irq_mask);
|
||||
|
@ -188,24 +188,24 @@ static void pmac_unmask_irq(unsigned int virq)
|
|||
raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);
|
||||
}
|
||||
|
||||
static int pmac_retrigger(unsigned int virq)
|
||||
static int pmac_retrigger(struct irq_data *d)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
raw_spin_lock_irqsave(&pmac_pic_lock, flags);
|
||||
__pmac_retrigger(irq_map[virq].hwirq);
|
||||
__pmac_retrigger(irq_map[d->irq].hwirq);
|
||||
raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct irq_chip pmac_pic = {
|
||||
.name = "PMAC-PIC",
|
||||
.startup = pmac_startup_irq,
|
||||
.mask = pmac_mask_irq,
|
||||
.ack = pmac_ack_irq,
|
||||
.mask_ack = pmac_mask_and_ack_irq,
|
||||
.unmask = pmac_unmask_irq,
|
||||
.retrigger = pmac_retrigger,
|
||||
.irq_startup = pmac_startup_irq,
|
||||
.irq_mask = pmac_mask_irq,
|
||||
.irq_ack = pmac_ack_irq,
|
||||
.irq_mask_ack = pmac_mask_and_ack_irq,
|
||||
.irq_unmask = pmac_unmask_irq,
|
||||
.irq_retrigger = pmac_retrigger,
|
||||
};
|
||||
|
||||
static irqreturn_t gatwick_action(int cpl, void *dev_id)
|
||||
|
@ -472,12 +472,14 @@ int of_irq_map_oldworld(struct device_node *device, int index,
|
|||
|
||||
static void pmac_u3_cascade(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct mpic *mpic = desc->handler_data;
|
||||
|
||||
struct irq_chip *chip = get_irq_desc_chip(desc);
|
||||
struct mpic *mpic = get_irq_desc_data(desc);
|
||||
unsigned int cascade_irq = mpic_get_one_irq(mpic);
|
||||
|
||||
if (cascade_irq != NO_IRQ)
|
||||
generic_handle_irq(cascade_irq);
|
||||
desc->chip->eoi(irq);
|
||||
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
}
|
||||
|
||||
static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic)
|
||||
|
@ -707,7 +709,7 @@ static int pmacpic_resume(struct sys_device *sysdev)
|
|||
mb();
|
||||
for (i = 0; i < max_real_irqs; ++i)
|
||||
if (test_bit(i, sleep_save_mask))
|
||||
pmac_unmask_irq(i);
|
||||
pmac_unmask_irq(irq_get_irq_data(i));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -99,16 +99,16 @@ static DEFINE_PER_CPU(struct ps3_private, ps3_private);
|
|||
* Sets ps3_bmp.mask and calls lv1_did_update_interrupt_mask().
|
||||
*/
|
||||
|
||||
static void ps3_chip_mask(unsigned int virq)
|
||||
static void ps3_chip_mask(struct irq_data *d)
|
||||
{
|
||||
struct ps3_private *pd = get_irq_chip_data(virq);
|
||||
struct ps3_private *pd = irq_data_get_irq_chip_data(d);
|
||||
unsigned long flags;
|
||||
|
||||
pr_debug("%s:%d: thread_id %llu, virq %d\n", __func__, __LINE__,
|
||||
pd->thread_id, virq);
|
||||
pd->thread_id, d->irq);
|
||||
|
||||
local_irq_save(flags);
|
||||
clear_bit(63 - virq, &pd->bmp.mask);
|
||||
clear_bit(63 - d->irq, &pd->bmp.mask);
|
||||
lv1_did_update_interrupt_mask(pd->ppe_id, pd->thread_id);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
@ -120,16 +120,16 @@ static void ps3_chip_mask(unsigned int virq)
|
|||
* Clears ps3_bmp.mask and calls lv1_did_update_interrupt_mask().
|
||||
*/
|
||||
|
||||
static void ps3_chip_unmask(unsigned int virq)
|
||||
static void ps3_chip_unmask(struct irq_data *d)
|
||||
{
|
||||
struct ps3_private *pd = get_irq_chip_data(virq);
|
||||
struct ps3_private *pd = irq_data_get_irq_chip_data(d);
|
||||
unsigned long flags;
|
||||
|
||||
pr_debug("%s:%d: thread_id %llu, virq %d\n", __func__, __LINE__,
|
||||
pd->thread_id, virq);
|
||||
pd->thread_id, d->irq);
|
||||
|
||||
local_irq_save(flags);
|
||||
set_bit(63 - virq, &pd->bmp.mask);
|
||||
set_bit(63 - d->irq, &pd->bmp.mask);
|
||||
lv1_did_update_interrupt_mask(pd->ppe_id, pd->thread_id);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
@ -141,10 +141,10 @@ static void ps3_chip_unmask(unsigned int virq)
|
|||
* Calls lv1_end_of_interrupt_ext().
|
||||
*/
|
||||
|
||||
static void ps3_chip_eoi(unsigned int virq)
|
||||
static void ps3_chip_eoi(struct irq_data *d)
|
||||
{
|
||||
const struct ps3_private *pd = get_irq_chip_data(virq);
|
||||
lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, virq);
|
||||
const struct ps3_private *pd = irq_data_get_irq_chip_data(d);
|
||||
lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, d->irq);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -153,9 +153,9 @@ static void ps3_chip_eoi(unsigned int virq)
|
|||
|
||||
static struct irq_chip ps3_irq_chip = {
|
||||
.name = "ps3",
|
||||
.mask = ps3_chip_mask,
|
||||
.unmask = ps3_chip_unmask,
|
||||
.eoi = ps3_chip_eoi,
|
||||
.irq_mask = ps3_chip_mask,
|
||||
.irq_unmask = ps3_chip_unmask,
|
||||
.irq_eoi = ps3_chip_eoi,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -202,7 +202,7 @@ static int ps3_virq_setup(enum ps3_cpu_binding cpu, unsigned long outlet,
|
|||
goto fail_set;
|
||||
}
|
||||
|
||||
ps3_chip_mask(*virq);
|
||||
ps3_chip_mask(irq_get_irq_data(*virq));
|
||||
|
||||
return result;
|
||||
|
||||
|
@ -296,7 +296,7 @@ int ps3_irq_plug_destroy(unsigned int virq)
|
|||
pr_debug("%s:%d: ppe_id %llu, thread_id %llu, virq %u\n", __func__,
|
||||
__LINE__, pd->ppe_id, pd->thread_id, virq);
|
||||
|
||||
ps3_chip_mask(virq);
|
||||
ps3_chip_mask(irq_get_irq_data(virq));
|
||||
|
||||
result = lv1_disconnect_irq_plug_ext(pd->ppe_id, pd->thread_id, virq);
|
||||
|
||||
|
@ -357,7 +357,7 @@ int ps3_event_receive_port_destroy(unsigned int virq)
|
|||
|
||||
pr_debug(" -> %s:%d virq %u\n", __func__, __LINE__, virq);
|
||||
|
||||
ps3_chip_mask(virq);
|
||||
ps3_chip_mask(irq_get_irq_data(virq));
|
||||
|
||||
result = lv1_destruct_event_receive_port(virq_to_hw(virq));
|
||||
|
||||
|
@ -492,7 +492,7 @@ int ps3_io_irq_destroy(unsigned int virq)
|
|||
int result;
|
||||
unsigned long outlet = virq_to_hw(virq);
|
||||
|
||||
ps3_chip_mask(virq);
|
||||
ps3_chip_mask(irq_get_irq_data(virq));
|
||||
|
||||
/*
|
||||
* lv1_destruct_io_irq_outlet() will destroy the IRQ plug,
|
||||
|
@ -553,7 +553,7 @@ int ps3_vuart_irq_destroy(unsigned int virq)
|
|||
{
|
||||
int result;
|
||||
|
||||
ps3_chip_mask(virq);
|
||||
ps3_chip_mask(irq_get_irq_data(virq));
|
||||
result = lv1_deconfigure_virtual_uart_irq();
|
||||
|
||||
if (result) {
|
||||
|
@ -605,7 +605,7 @@ int ps3_spe_irq_destroy(unsigned int virq)
|
|||
{
|
||||
int result;
|
||||
|
||||
ps3_chip_mask(virq);
|
||||
ps3_chip_mask(irq_get_irq_data(virq));
|
||||
|
||||
result = ps3_irq_plug_destroy(virq);
|
||||
BUG_ON(result);
|
||||
|
|
|
@ -508,12 +508,7 @@ static int cmm_memory_isolate_cb(struct notifier_block *self,
|
|||
if (action == MEM_ISOLATE_COUNT)
|
||||
ret = cmm_count_pages(arg);
|
||||
|
||||
if (ret)
|
||||
ret = notifier_from_errno(ret);
|
||||
else
|
||||
ret = NOTIFY_OK;
|
||||
|
||||
return ret;
|
||||
return notifier_from_errno(ret);
|
||||
}
|
||||
|
||||
static struct notifier_block cmm_mem_isolate_nb = {
|
||||
|
@ -635,12 +630,7 @@ static int cmm_memory_cb(struct notifier_block *self,
|
|||
break;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
ret = notifier_from_errno(ret);
|
||||
else
|
||||
ret = NOTIFY_OK;
|
||||
|
||||
return ret;
|
||||
return notifier_from_errno(ret);
|
||||
}
|
||||
|
||||
static struct notifier_block cmm_mem_nb = {
|
||||
|
|
|
@ -876,7 +876,7 @@ void eeh_restore_bars(struct pci_dn *pdn)
|
|||
*
|
||||
* Save the values of the device bars. Unlike the restore
|
||||
* routine, this routine is *not* recursive. This is because
|
||||
* PCI devices are added individuallly; but, for the restore,
|
||||
* PCI devices are added individually; but, for the restore,
|
||||
* an entire slot is reset at a time.
|
||||
*/
|
||||
static void eeh_save_bars(struct pci_dn *pdn)
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/crash_dump.h>
|
||||
#include <linux/memory.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/rtas.h>
|
||||
|
@ -45,6 +46,7 @@
|
|||
#include <asm/tce.h>
|
||||
#include <asm/ppc-pci.h>
|
||||
#include <asm/udbg.h>
|
||||
#include <asm/mmzone.h>
|
||||
|
||||
#include "plpar_wrappers.h"
|
||||
|
||||
|
@ -270,6 +272,152 @@ static unsigned long tce_get_pSeriesLP(struct iommu_table *tbl, long tcenum)
|
|||
return tce_ret;
|
||||
}
|
||||
|
||||
/* this is compatable with cells for the device tree property */
|
||||
struct dynamic_dma_window_prop {
|
||||
__be32 liobn; /* tce table number */
|
||||
__be64 dma_base; /* address hi,lo */
|
||||
__be32 tce_shift; /* ilog2(tce_page_size) */
|
||||
__be32 window_shift; /* ilog2(tce_window_size) */
|
||||
};
|
||||
|
||||
struct direct_window {
|
||||
struct device_node *device;
|
||||
const struct dynamic_dma_window_prop *prop;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
/* Dynamic DMA Window support */
|
||||
struct ddw_query_response {
|
||||
u32 windows_available;
|
||||
u32 largest_available_block;
|
||||
u32 page_size;
|
||||
u32 migration_capable;
|
||||
};
|
||||
|
||||
struct ddw_create_response {
|
||||
u32 liobn;
|
||||
u32 addr_hi;
|
||||
u32 addr_lo;
|
||||
};
|
||||
|
||||
static LIST_HEAD(direct_window_list);
|
||||
/* prevents races between memory on/offline and window creation */
|
||||
static DEFINE_SPINLOCK(direct_window_list_lock);
|
||||
/* protects initializing window twice for same device */
|
||||
static DEFINE_MUTEX(direct_window_init_mutex);
|
||||
#define DIRECT64_PROPNAME "linux,direct64-ddr-window-info"
|
||||
|
||||
static int tce_clearrange_multi_pSeriesLP(unsigned long start_pfn,
|
||||
unsigned long num_pfn, const void *arg)
|
||||
{
|
||||
const struct dynamic_dma_window_prop *maprange = arg;
|
||||
int rc;
|
||||
u64 tce_size, num_tce, dma_offset, next;
|
||||
u32 tce_shift;
|
||||
long limit;
|
||||
|
||||
tce_shift = be32_to_cpu(maprange->tce_shift);
|
||||
tce_size = 1ULL << tce_shift;
|
||||
next = start_pfn << PAGE_SHIFT;
|
||||
num_tce = num_pfn << PAGE_SHIFT;
|
||||
|
||||
/* round back to the beginning of the tce page size */
|
||||
num_tce += next & (tce_size - 1);
|
||||
next &= ~(tce_size - 1);
|
||||
|
||||
/* covert to number of tces */
|
||||
num_tce |= tce_size - 1;
|
||||
num_tce >>= tce_shift;
|
||||
|
||||
do {
|
||||
/*
|
||||
* Set up the page with TCE data, looping through and setting
|
||||
* the values.
|
||||
*/
|
||||
limit = min_t(long, num_tce, 512);
|
||||
dma_offset = next + be64_to_cpu(maprange->dma_base);
|
||||
|
||||
rc = plpar_tce_stuff((u64)be32_to_cpu(maprange->liobn),
|
||||
dma_offset,
|
||||
0, limit);
|
||||
num_tce -= limit;
|
||||
} while (num_tce > 0 && !rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int tce_setrange_multi_pSeriesLP(unsigned long start_pfn,
|
||||
unsigned long num_pfn, const void *arg)
|
||||
{
|
||||
const struct dynamic_dma_window_prop *maprange = arg;
|
||||
u64 *tcep, tce_size, num_tce, dma_offset, next, proto_tce, liobn;
|
||||
u32 tce_shift;
|
||||
u64 rc = 0;
|
||||
long l, limit;
|
||||
|
||||
local_irq_disable(); /* to protect tcep and the page behind it */
|
||||
tcep = __get_cpu_var(tce_page);
|
||||
|
||||
if (!tcep) {
|
||||
tcep = (u64 *)__get_free_page(GFP_ATOMIC);
|
||||
if (!tcep) {
|
||||
local_irq_enable();
|
||||
return -ENOMEM;
|
||||
}
|
||||
__get_cpu_var(tce_page) = tcep;
|
||||
}
|
||||
|
||||
proto_tce = TCE_PCI_READ | TCE_PCI_WRITE;
|
||||
|
||||
liobn = (u64)be32_to_cpu(maprange->liobn);
|
||||
tce_shift = be32_to_cpu(maprange->tce_shift);
|
||||
tce_size = 1ULL << tce_shift;
|
||||
next = start_pfn << PAGE_SHIFT;
|
||||
num_tce = num_pfn << PAGE_SHIFT;
|
||||
|
||||
/* round back to the beginning of the tce page size */
|
||||
num_tce += next & (tce_size - 1);
|
||||
next &= ~(tce_size - 1);
|
||||
|
||||
/* covert to number of tces */
|
||||
num_tce |= tce_size - 1;
|
||||
num_tce >>= tce_shift;
|
||||
|
||||
/* We can map max one pageful of TCEs at a time */
|
||||
do {
|
||||
/*
|
||||
* Set up the page with TCE data, looping through and setting
|
||||
* the values.
|
||||
*/
|
||||
limit = min_t(long, num_tce, 4096/TCE_ENTRY_SIZE);
|
||||
dma_offset = next + be64_to_cpu(maprange->dma_base);
|
||||
|
||||
for (l = 0; l < limit; l++) {
|
||||
tcep[l] = proto_tce | next;
|
||||
next += tce_size;
|
||||
}
|
||||
|
||||
rc = plpar_tce_put_indirect(liobn,
|
||||
dma_offset,
|
||||
(u64)virt_to_abs(tcep),
|
||||
limit);
|
||||
|
||||
num_tce -= limit;
|
||||
} while (num_tce > 0 && !rc);
|
||||
|
||||
/* error cleanup: caller will clear whole range */
|
||||
|
||||
local_irq_enable();
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int tce_setrange_multi_pSeriesLP_walk(unsigned long start_pfn,
|
||||
unsigned long num_pfn, void *arg)
|
||||
{
|
||||
return tce_setrange_multi_pSeriesLP(start_pfn, num_pfn, arg);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
static void iommu_table_setparms(struct pci_controller *phb,
|
||||
struct device_node *dn,
|
||||
|
@ -495,6 +643,329 @@ static void pci_dma_dev_setup_pSeries(struct pci_dev *dev)
|
|||
pci_name(dev));
|
||||
}
|
||||
|
||||
static int __read_mostly disable_ddw;
|
||||
|
||||
static int __init disable_ddw_setup(char *str)
|
||||
{
|
||||
disable_ddw = 1;
|
||||
printk(KERN_INFO "ppc iommu: disabling ddw.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
early_param("disable_ddw", disable_ddw_setup);
|
||||
|
||||
static void remove_ddw(struct device_node *np)
|
||||
{
|
||||
struct dynamic_dma_window_prop *dwp;
|
||||
struct property *win64;
|
||||
const u32 *ddr_avail;
|
||||
u64 liobn;
|
||||
int len, ret;
|
||||
|
||||
ddr_avail = of_get_property(np, "ibm,ddw-applicable", &len);
|
||||
win64 = of_find_property(np, DIRECT64_PROPNAME, NULL);
|
||||
if (!win64 || !ddr_avail || len < 3 * sizeof(u32))
|
||||
return;
|
||||
|
||||
dwp = win64->value;
|
||||
liobn = (u64)be32_to_cpu(dwp->liobn);
|
||||
|
||||
/* clear the whole window, note the arg is in kernel pages */
|
||||
ret = tce_clearrange_multi_pSeriesLP(0,
|
||||
1ULL << (be32_to_cpu(dwp->window_shift) - PAGE_SHIFT), dwp);
|
||||
if (ret)
|
||||
pr_warning("%s failed to clear tces in window.\n",
|
||||
np->full_name);
|
||||
else
|
||||
pr_debug("%s successfully cleared tces in window.\n",
|
||||
np->full_name);
|
||||
|
||||
ret = rtas_call(ddr_avail[2], 1, 1, NULL, liobn);
|
||||
if (ret)
|
||||
pr_warning("%s: failed to remove direct window: rtas returned "
|
||||
"%d to ibm,remove-pe-dma-window(%x) %llx\n",
|
||||
np->full_name, ret, ddr_avail[2], liobn);
|
||||
else
|
||||
pr_debug("%s: successfully removed direct window: rtas returned "
|
||||
"%d to ibm,remove-pe-dma-window(%x) %llx\n",
|
||||
np->full_name, ret, ddr_avail[2], liobn);
|
||||
}
|
||||
|
||||
|
||||
static int dupe_ddw_if_already_created(struct pci_dev *dev, struct device_node *pdn)
|
||||
{
|
||||
struct device_node *dn;
|
||||
struct pci_dn *pcidn;
|
||||
struct direct_window *window;
|
||||
const struct dynamic_dma_window_prop *direct64;
|
||||
u64 dma_addr = 0;
|
||||
|
||||
dn = pci_device_to_OF_node(dev);
|
||||
pcidn = PCI_DN(dn);
|
||||
spin_lock(&direct_window_list_lock);
|
||||
/* check if we already created a window and dupe that config if so */
|
||||
list_for_each_entry(window, &direct_window_list, list) {
|
||||
if (window->device == pdn) {
|
||||
direct64 = window->prop;
|
||||
dma_addr = direct64->dma_base;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock(&direct_window_list_lock);
|
||||
|
||||
return dma_addr;
|
||||
}
|
||||
|
||||
static u64 dupe_ddw_if_kexec(struct pci_dev *dev, struct device_node *pdn)
|
||||
{
|
||||
struct device_node *dn;
|
||||
struct pci_dn *pcidn;
|
||||
int len;
|
||||
struct direct_window *window;
|
||||
const struct dynamic_dma_window_prop *direct64;
|
||||
u64 dma_addr = 0;
|
||||
|
||||
dn = pci_device_to_OF_node(dev);
|
||||
pcidn = PCI_DN(dn);
|
||||
direct64 = of_get_property(pdn, DIRECT64_PROPNAME, &len);
|
||||
if (direct64) {
|
||||
window = kzalloc(sizeof(*window), GFP_KERNEL);
|
||||
if (!window) {
|
||||
remove_ddw(pdn);
|
||||
} else {
|
||||
window->device = pdn;
|
||||
window->prop = direct64;
|
||||
spin_lock(&direct_window_list_lock);
|
||||
list_add(&window->list, &direct_window_list);
|
||||
spin_unlock(&direct_window_list_lock);
|
||||
dma_addr = direct64->dma_base;
|
||||
}
|
||||
}
|
||||
|
||||
return dma_addr;
|
||||
}
|
||||
|
||||
static int query_ddw(struct pci_dev *dev, const u32 *ddr_avail,
|
||||
struct ddw_query_response *query)
|
||||
{
|
||||
struct device_node *dn;
|
||||
struct pci_dn *pcidn;
|
||||
u32 cfg_addr;
|
||||
u64 buid;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Get the config address and phb buid of the PE window.
|
||||
* Rely on eeh to retrieve this for us.
|
||||
* Retrieve them from the pci device, not the node with the
|
||||
* dma-window property
|
||||
*/
|
||||
dn = pci_device_to_OF_node(dev);
|
||||
pcidn = PCI_DN(dn);
|
||||
cfg_addr = pcidn->eeh_config_addr;
|
||||
if (pcidn->eeh_pe_config_addr)
|
||||
cfg_addr = pcidn->eeh_pe_config_addr;
|
||||
buid = pcidn->phb->buid;
|
||||
ret = rtas_call(ddr_avail[0], 3, 5, (u32 *)query,
|
||||
cfg_addr, BUID_HI(buid), BUID_LO(buid));
|
||||
dev_info(&dev->dev, "ibm,query-pe-dma-windows(%x) %x %x %x"
|
||||
" returned %d\n", ddr_avail[0], cfg_addr, BUID_HI(buid),
|
||||
BUID_LO(buid), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int create_ddw(struct pci_dev *dev, const u32 *ddr_avail,
|
||||
struct ddw_create_response *create, int page_shift,
|
||||
int window_shift)
|
||||
{
|
||||
struct device_node *dn;
|
||||
struct pci_dn *pcidn;
|
||||
u32 cfg_addr;
|
||||
u64 buid;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Get the config address and phb buid of the PE window.
|
||||
* Rely on eeh to retrieve this for us.
|
||||
* Retrieve them from the pci device, not the node with the
|
||||
* dma-window property
|
||||
*/
|
||||
dn = pci_device_to_OF_node(dev);
|
||||
pcidn = PCI_DN(dn);
|
||||
cfg_addr = pcidn->eeh_config_addr;
|
||||
if (pcidn->eeh_pe_config_addr)
|
||||
cfg_addr = pcidn->eeh_pe_config_addr;
|
||||
buid = pcidn->phb->buid;
|
||||
|
||||
do {
|
||||
/* extra outputs are LIOBN and dma-addr (hi, lo) */
|
||||
ret = rtas_call(ddr_avail[1], 5, 4, (u32 *)create, cfg_addr,
|
||||
BUID_HI(buid), BUID_LO(buid), page_shift, window_shift);
|
||||
} while (rtas_busy_delay(ret));
|
||||
dev_info(&dev->dev,
|
||||
"ibm,create-pe-dma-window(%x) %x %x %x %x %x returned %d "
|
||||
"(liobn = 0x%x starting addr = %x %x)\n", ddr_avail[1],
|
||||
cfg_addr, BUID_HI(buid), BUID_LO(buid), page_shift,
|
||||
window_shift, ret, create->liobn, create->addr_hi, create->addr_lo);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the PE supports dynamic dma windows, and there is space for a table
|
||||
* that can map all pages in a linear offset, then setup such a table,
|
||||
* and record the dma-offset in the struct device.
|
||||
*
|
||||
* dev: the pci device we are checking
|
||||
* pdn: the parent pe node with the ibm,dma_window property
|
||||
* Future: also check if we can remap the base window for our base page size
|
||||
*
|
||||
* returns the dma offset for use by dma_set_mask
|
||||
*/
|
||||
static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
|
||||
{
|
||||
int len, ret;
|
||||
struct ddw_query_response query;
|
||||
struct ddw_create_response create;
|
||||
int page_shift;
|
||||
u64 dma_addr, max_addr;
|
||||
struct device_node *dn;
|
||||
const u32 *uninitialized_var(ddr_avail);
|
||||
struct direct_window *window;
|
||||
struct property *uninitialized_var(win64);
|
||||
struct dynamic_dma_window_prop *ddwprop;
|
||||
|
||||
mutex_lock(&direct_window_init_mutex);
|
||||
|
||||
dma_addr = dupe_ddw_if_already_created(dev, pdn);
|
||||
if (dma_addr != 0)
|
||||
goto out_unlock;
|
||||
|
||||
dma_addr = dupe_ddw_if_kexec(dev, pdn);
|
||||
if (dma_addr != 0)
|
||||
goto out_unlock;
|
||||
|
||||
/*
|
||||
* the ibm,ddw-applicable property holds the tokens for:
|
||||
* ibm,query-pe-dma-window
|
||||
* ibm,create-pe-dma-window
|
||||
* ibm,remove-pe-dma-window
|
||||
* for the given node in that order.
|
||||
* the property is actually in the parent, not the PE
|
||||
*/
|
||||
ddr_avail = of_get_property(pdn, "ibm,ddw-applicable", &len);
|
||||
if (!ddr_avail || len < 3 * sizeof(u32))
|
||||
goto out_unlock;
|
||||
|
||||
/*
|
||||
* Query if there is a second window of size to map the
|
||||
* whole partition. Query returns number of windows, largest
|
||||
* block assigned to PE (partition endpoint), and two bitmasks
|
||||
* of page sizes: supported and supported for migrate-dma.
|
||||
*/
|
||||
dn = pci_device_to_OF_node(dev);
|
||||
ret = query_ddw(dev, ddr_avail, &query);
|
||||
if (ret != 0)
|
||||
goto out_unlock;
|
||||
|
||||
if (query.windows_available == 0) {
|
||||
/*
|
||||
* no additional windows are available for this device.
|
||||
* We might be able to reallocate the existing window,
|
||||
* trading in for a larger page size.
|
||||
*/
|
||||
dev_dbg(&dev->dev, "no free dynamic windows");
|
||||
goto out_unlock;
|
||||
}
|
||||
if (query.page_size & 4) {
|
||||
page_shift = 24; /* 16MB */
|
||||
} else if (query.page_size & 2) {
|
||||
page_shift = 16; /* 64kB */
|
||||
} else if (query.page_size & 1) {
|
||||
page_shift = 12; /* 4kB */
|
||||
} else {
|
||||
dev_dbg(&dev->dev, "no supported direct page size in mask %x",
|
||||
query.page_size);
|
||||
goto out_unlock;
|
||||
}
|
||||
/* verify the window * number of ptes will map the partition */
|
||||
/* check largest block * page size > max memory hotplug addr */
|
||||
max_addr = memory_hotplug_max();
|
||||
if (query.largest_available_block < (max_addr >> page_shift)) {
|
||||
dev_dbg(&dev->dev, "can't map partiton max 0x%llx with %u "
|
||||
"%llu-sized pages\n", max_addr, query.largest_available_block,
|
||||
1ULL << page_shift);
|
||||
goto out_unlock;
|
||||
}
|
||||
len = order_base_2(max_addr);
|
||||
win64 = kzalloc(sizeof(struct property), GFP_KERNEL);
|
||||
if (!win64) {
|
||||
dev_info(&dev->dev,
|
||||
"couldn't allocate property for 64bit dma window\n");
|
||||
goto out_unlock;
|
||||
}
|
||||
win64->name = kstrdup(DIRECT64_PROPNAME, GFP_KERNEL);
|
||||
win64->value = ddwprop = kmalloc(sizeof(*ddwprop), GFP_KERNEL);
|
||||
if (!win64->name || !win64->value) {
|
||||
dev_info(&dev->dev,
|
||||
"couldn't allocate property name and value\n");
|
||||
goto out_free_prop;
|
||||
}
|
||||
|
||||
ret = create_ddw(dev, ddr_avail, &create, page_shift, len);
|
||||
if (ret != 0)
|
||||
goto out_free_prop;
|
||||
|
||||
ddwprop->liobn = cpu_to_be32(create.liobn);
|
||||
ddwprop->dma_base = cpu_to_be64(of_read_number(&create.addr_hi, 2));
|
||||
ddwprop->tce_shift = cpu_to_be32(page_shift);
|
||||
ddwprop->window_shift = cpu_to_be32(len);
|
||||
|
||||
dev_dbg(&dev->dev, "created tce table LIOBN 0x%x for %s\n",
|
||||
create.liobn, dn->full_name);
|
||||
|
||||
window = kzalloc(sizeof(*window), GFP_KERNEL);
|
||||
if (!window)
|
||||
goto out_clear_window;
|
||||
|
||||
ret = walk_system_ram_range(0, memblock_end_of_DRAM() >> PAGE_SHIFT,
|
||||
win64->value, tce_setrange_multi_pSeriesLP_walk);
|
||||
if (ret) {
|
||||
dev_info(&dev->dev, "failed to map direct window for %s: %d\n",
|
||||
dn->full_name, ret);
|
||||
goto out_clear_window;
|
||||
}
|
||||
|
||||
ret = prom_add_property(pdn, win64);
|
||||
if (ret) {
|
||||
dev_err(&dev->dev, "unable to add dma window property for %s: %d",
|
||||
pdn->full_name, ret);
|
||||
goto out_clear_window;
|
||||
}
|
||||
|
||||
window->device = pdn;
|
||||
window->prop = ddwprop;
|
||||
spin_lock(&direct_window_list_lock);
|
||||
list_add(&window->list, &direct_window_list);
|
||||
spin_unlock(&direct_window_list_lock);
|
||||
|
||||
dma_addr = of_read_number(&create.addr_hi, 2);
|
||||
goto out_unlock;
|
||||
|
||||
out_clear_window:
|
||||
remove_ddw(pdn);
|
||||
|
||||
out_free_prop:
|
||||
kfree(win64->name);
|
||||
kfree(win64->value);
|
||||
kfree(win64);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&direct_window_init_mutex);
|
||||
return dma_addr;
|
||||
}
|
||||
|
||||
static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
|
||||
{
|
||||
struct device_node *pdn, *dn;
|
||||
|
@ -541,23 +1012,137 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
|
|||
|
||||
set_iommu_table_base(&dev->dev, pci->iommu_table);
|
||||
}
|
||||
|
||||
static int dma_set_mask_pSeriesLP(struct device *dev, u64 dma_mask)
|
||||
{
|
||||
bool ddw_enabled = false;
|
||||
struct device_node *pdn, *dn;
|
||||
struct pci_dev *pdev;
|
||||
const void *dma_window = NULL;
|
||||
u64 dma_offset;
|
||||
|
||||
if (!dev->dma_mask || !dma_supported(dev, dma_mask))
|
||||
return -EIO;
|
||||
|
||||
/* only attempt to use a new window if 64-bit DMA is requested */
|
||||
if (!disable_ddw && dma_mask == DMA_BIT_MASK(64)) {
|
||||
pdev = to_pci_dev(dev);
|
||||
|
||||
dn = pci_device_to_OF_node(pdev);
|
||||
dev_dbg(dev, "node is %s\n", dn->full_name);
|
||||
|
||||
/*
|
||||
* the device tree might contain the dma-window properties
|
||||
* per-device and not neccesarily for the bus. So we need to
|
||||
* search upwards in the tree until we either hit a dma-window
|
||||
* property, OR find a parent with a table already allocated.
|
||||
*/
|
||||
for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table;
|
||||
pdn = pdn->parent) {
|
||||
dma_window = of_get_property(pdn, "ibm,dma-window", NULL);
|
||||
if (dma_window)
|
||||
break;
|
||||
}
|
||||
if (pdn && PCI_DN(pdn)) {
|
||||
dma_offset = enable_ddw(pdev, pdn);
|
||||
if (dma_offset != 0) {
|
||||
dev_info(dev, "Using 64-bit direct DMA at offset %llx\n", dma_offset);
|
||||
set_dma_offset(dev, dma_offset);
|
||||
set_dma_ops(dev, &dma_direct_ops);
|
||||
ddw_enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* fall-through to iommu ops */
|
||||
if (!ddw_enabled) {
|
||||
dev_info(dev, "Using 32-bit DMA via iommu\n");
|
||||
set_dma_ops(dev, &dma_iommu_ops);
|
||||
}
|
||||
|
||||
*dev->dma_mask = dma_mask;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* CONFIG_PCI */
|
||||
#define pci_dma_bus_setup_pSeries NULL
|
||||
#define pci_dma_dev_setup_pSeries NULL
|
||||
#define pci_dma_bus_setup_pSeriesLP NULL
|
||||
#define pci_dma_dev_setup_pSeriesLP NULL
|
||||
#define dma_set_mask_pSeriesLP NULL
|
||||
#endif /* !CONFIG_PCI */
|
||||
|
||||
static int iommu_mem_notifier(struct notifier_block *nb, unsigned long action,
|
||||
void *data)
|
||||
{
|
||||
struct direct_window *window;
|
||||
struct memory_notify *arg = data;
|
||||
int ret = 0;
|
||||
|
||||
switch (action) {
|
||||
case MEM_GOING_ONLINE:
|
||||
spin_lock(&direct_window_list_lock);
|
||||
list_for_each_entry(window, &direct_window_list, list) {
|
||||
ret |= tce_setrange_multi_pSeriesLP(arg->start_pfn,
|
||||
arg->nr_pages, window->prop);
|
||||
/* XXX log error */
|
||||
}
|
||||
spin_unlock(&direct_window_list_lock);
|
||||
break;
|
||||
case MEM_CANCEL_ONLINE:
|
||||
case MEM_OFFLINE:
|
||||
spin_lock(&direct_window_list_lock);
|
||||
list_for_each_entry(window, &direct_window_list, list) {
|
||||
ret |= tce_clearrange_multi_pSeriesLP(arg->start_pfn,
|
||||
arg->nr_pages, window->prop);
|
||||
/* XXX log error */
|
||||
}
|
||||
spin_unlock(&direct_window_list_lock);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (ret && action != MEM_CANCEL_ONLINE)
|
||||
return NOTIFY_BAD;
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static struct notifier_block iommu_mem_nb = {
|
||||
.notifier_call = iommu_mem_notifier,
|
||||
};
|
||||
|
||||
static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node)
|
||||
{
|
||||
int err = NOTIFY_OK;
|
||||
struct device_node *np = node;
|
||||
struct pci_dn *pci = PCI_DN(np);
|
||||
struct direct_window *window;
|
||||
|
||||
switch (action) {
|
||||
case PSERIES_RECONFIG_REMOVE:
|
||||
if (pci && pci->iommu_table)
|
||||
iommu_free_table(pci->iommu_table, np->full_name);
|
||||
|
||||
spin_lock(&direct_window_list_lock);
|
||||
list_for_each_entry(window, &direct_window_list, list) {
|
||||
if (window->device == np) {
|
||||
list_del(&window->list);
|
||||
kfree(window);
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock(&direct_window_list_lock);
|
||||
|
||||
/*
|
||||
* Because the notifier runs after isolation of the
|
||||
* slot, we are guaranteed any DMA window has already
|
||||
* been revoked and the TCEs have been marked invalid,
|
||||
* so we don't need a call to remove_ddw(np). However,
|
||||
* if an additional notifier action is added before the
|
||||
* isolate call, we should update this code for
|
||||
* completeness with such a call.
|
||||
*/
|
||||
break;
|
||||
default:
|
||||
err = NOTIFY_DONE;
|
||||
|
@ -587,6 +1172,7 @@ void iommu_init_early_pSeries(void)
|
|||
ppc_md.tce_get = tce_get_pSeriesLP;
|
||||
ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pSeriesLP;
|
||||
ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_pSeriesLP;
|
||||
ppc_md.dma_set_mask = dma_set_mask_pSeriesLP;
|
||||
} else {
|
||||
ppc_md.tce_build = tce_build_pSeries;
|
||||
ppc_md.tce_free = tce_free_pSeries;
|
||||
|
@ -597,6 +1183,7 @@ void iommu_init_early_pSeries(void)
|
|||
|
||||
|
||||
pSeries_reconfig_notifier_register(&iommu_reconfig_nb);
|
||||
register_memory_notifier(&iommu_mem_nb);
|
||||
|
||||
set_pci_dma_ops(&dma_iommu_ops);
|
||||
}
|
||||
|
|
|
@ -93,8 +93,18 @@ static void rtas_disable_msi(struct pci_dev *pdev)
|
|||
if (!pdn)
|
||||
return;
|
||||
|
||||
if (rtas_change_msi(pdn, RTAS_CHANGE_FN, 0) != 0)
|
||||
pr_debug("rtas_msi: Setting MSIs to 0 failed!\n");
|
||||
/*
|
||||
* disabling MSI with the explicit interface also disables MSI-X
|
||||
*/
|
||||
if (rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, 0) != 0) {
|
||||
/*
|
||||
* may have failed because explicit interface is not
|
||||
* present
|
||||
*/
|
||||
if (rtas_change_msi(pdn, RTAS_CHANGE_FN, 0) != 0) {
|
||||
pr_debug("rtas_msi: Setting MSIs to 0 failed!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int rtas_query_irq_number(struct pci_dn *pdn, int offset)
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kmsg_dump.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/nvram.h>
|
||||
#include <asm/rtas.h>
|
||||
|
@ -30,17 +32,54 @@ static int nvram_fetch, nvram_store;
|
|||
static char nvram_buf[NVRW_CNT]; /* assume this is in the first 4GB */
|
||||
static DEFINE_SPINLOCK(nvram_lock);
|
||||
|
||||
static long nvram_error_log_index = -1;
|
||||
static long nvram_error_log_size = 0;
|
||||
|
||||
struct err_log_info {
|
||||
int error_type;
|
||||
unsigned int seq_num;
|
||||
};
|
||||
#define NVRAM_MAX_REQ 2079
|
||||
#define NVRAM_MIN_REQ 1055
|
||||
|
||||
#define NVRAM_LOG_PART_NAME "ibm,rtas-log"
|
||||
struct nvram_os_partition {
|
||||
const char *name;
|
||||
int req_size; /* desired size, in bytes */
|
||||
int min_size; /* minimum acceptable size (0 means req_size) */
|
||||
long size; /* size of data portion (excluding err_log_info) */
|
||||
long index; /* offset of data portion of partition */
|
||||
};
|
||||
|
||||
static struct nvram_os_partition rtas_log_partition = {
|
||||
.name = "ibm,rtas-log",
|
||||
.req_size = 2079,
|
||||
.min_size = 1055,
|
||||
.index = -1
|
||||
};
|
||||
|
||||
static struct nvram_os_partition oops_log_partition = {
|
||||
.name = "lnx,oops-log",
|
||||
.req_size = 4000,
|
||||
.min_size = 2000,
|
||||
.index = -1
|
||||
};
|
||||
|
||||
static const char *pseries_nvram_os_partitions[] = {
|
||||
"ibm,rtas-log",
|
||||
"lnx,oops-log",
|
||||
NULL
|
||||
};
|
||||
|
||||
static void oops_to_nvram(struct kmsg_dumper *dumper,
|
||||
enum kmsg_dump_reason reason,
|
||||
const char *old_msgs, unsigned long old_len,
|
||||
const char *new_msgs, unsigned long new_len);
|
||||
|
||||
static struct kmsg_dumper nvram_kmsg_dumper = {
|
||||
.dump = oops_to_nvram
|
||||
};
|
||||
|
||||
/* See clobbering_unread_rtas_event() */
|
||||
#define NVRAM_RTAS_READ_TIMEOUT 5 /* seconds */
|
||||
static unsigned long last_unread_rtas_event; /* timestamp */
|
||||
|
||||
/* We preallocate oops_buf during init to avoid kmalloc during oops/panic. */
|
||||
static char *oops_buf;
|
||||
|
||||
static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
|
||||
{
|
||||
|
@ -134,7 +173,7 @@ static ssize_t pSeries_nvram_get_size(void)
|
|||
}
|
||||
|
||||
|
||||
/* nvram_write_error_log
|
||||
/* nvram_write_os_partition, nvram_write_error_log
|
||||
*
|
||||
* We need to buffer the error logs into nvram to ensure that we have
|
||||
* the failure information to decode. If we have a severe error there
|
||||
|
@ -156,48 +195,58 @@ static ssize_t pSeries_nvram_get_size(void)
|
|||
* The 'data' section would look like (in bytes):
|
||||
* +--------------+------------+-----------------------------------+
|
||||
* | event_logged | sequence # | error log |
|
||||
* |0 3|4 7|8 nvram_error_log_size-1|
|
||||
* |0 3|4 7|8 error_log_size-1|
|
||||
* +--------------+------------+-----------------------------------+
|
||||
*
|
||||
* event_logged: 0 if event has not been logged to syslog, 1 if it has
|
||||
* sequence #: The unique sequence # for each event. (until it wraps)
|
||||
* error log: The error log from event_scan
|
||||
*/
|
||||
int nvram_write_error_log(char * buff, int length,
|
||||
unsigned int err_type, unsigned int error_log_cnt)
|
||||
int nvram_write_os_partition(struct nvram_os_partition *part, char * buff,
|
||||
int length, unsigned int err_type, unsigned int error_log_cnt)
|
||||
{
|
||||
int rc;
|
||||
loff_t tmp_index;
|
||||
struct err_log_info info;
|
||||
|
||||
if (nvram_error_log_index == -1) {
|
||||
if (part->index == -1) {
|
||||
return -ESPIPE;
|
||||
}
|
||||
|
||||
if (length > nvram_error_log_size) {
|
||||
length = nvram_error_log_size;
|
||||
if (length > part->size) {
|
||||
length = part->size;
|
||||
}
|
||||
|
||||
info.error_type = err_type;
|
||||
info.seq_num = error_log_cnt;
|
||||
|
||||
tmp_index = nvram_error_log_index;
|
||||
tmp_index = part->index;
|
||||
|
||||
rc = ppc_md.nvram_write((char *)&info, sizeof(struct err_log_info), &tmp_index);
|
||||
if (rc <= 0) {
|
||||
printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc);
|
||||
pr_err("%s: Failed nvram_write (%d)\n", __FUNCTION__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = ppc_md.nvram_write(buff, length, &tmp_index);
|
||||
if (rc <= 0) {
|
||||
printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc);
|
||||
pr_err("%s: Failed nvram_write (%d)\n", __FUNCTION__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nvram_write_error_log(char * buff, int length,
|
||||
unsigned int err_type, unsigned int error_log_cnt)
|
||||
{
|
||||
int rc = nvram_write_os_partition(&rtas_log_partition, buff, length,
|
||||
err_type, error_log_cnt);
|
||||
if (!rc)
|
||||
last_unread_rtas_event = get_seconds();
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* nvram_read_error_log
|
||||
*
|
||||
* Reads nvram for error log for at most 'length'
|
||||
|
@ -209,13 +258,13 @@ int nvram_read_error_log(char * buff, int length,
|
|||
loff_t tmp_index;
|
||||
struct err_log_info info;
|
||||
|
||||
if (nvram_error_log_index == -1)
|
||||
if (rtas_log_partition.index == -1)
|
||||
return -1;
|
||||
|
||||
if (length > nvram_error_log_size)
|
||||
length = nvram_error_log_size;
|
||||
if (length > rtas_log_partition.size)
|
||||
length = rtas_log_partition.size;
|
||||
|
||||
tmp_index = nvram_error_log_index;
|
||||
tmp_index = rtas_log_partition.index;
|
||||
|
||||
rc = ppc_md.nvram_read((char *)&info, sizeof(struct err_log_info), &tmp_index);
|
||||
if (rc <= 0) {
|
||||
|
@ -244,37 +293,40 @@ int nvram_clear_error_log(void)
|
|||
int clear_word = ERR_FLAG_ALREADY_LOGGED;
|
||||
int rc;
|
||||
|
||||
if (nvram_error_log_index == -1)
|
||||
if (rtas_log_partition.index == -1)
|
||||
return -1;
|
||||
|
||||
tmp_index = nvram_error_log_index;
|
||||
tmp_index = rtas_log_partition.index;
|
||||
|
||||
rc = ppc_md.nvram_write((char *)&clear_word, sizeof(int), &tmp_index);
|
||||
if (rc <= 0) {
|
||||
printk(KERN_ERR "nvram_clear_error_log: Failed nvram_write (%d)\n", rc);
|
||||
return rc;
|
||||
}
|
||||
last_unread_rtas_event = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* pseries_nvram_init_log_partition
|
||||
/* pseries_nvram_init_os_partition
|
||||
*
|
||||
* This will setup the partition we need for buffering the
|
||||
* error logs and cleanup partitions if needed.
|
||||
* This sets up a partition with an "OS" signature.
|
||||
*
|
||||
* The general strategy is the following:
|
||||
* 1.) If there is log partition large enough then use it.
|
||||
* 2.) If there is none large enough, search
|
||||
* for a free partition that is large enough.
|
||||
* 3.) If there is not a free partition large enough remove
|
||||
* _all_ OS partitions and consolidate the space.
|
||||
* 4.) Will first try getting a chunk that will satisfy the maximum
|
||||
* error log size (NVRAM_MAX_REQ).
|
||||
* 5.) If the max chunk cannot be allocated then try finding a chunk
|
||||
* that will satisfy the minum needed (NVRAM_MIN_REQ).
|
||||
* 1.) If a partition with the indicated name already exists...
|
||||
* - If it's large enough, use it.
|
||||
* - Otherwise, recycle it and keep going.
|
||||
* 2.) Search for a free partition that is large enough.
|
||||
* 3.) If there's not a free partition large enough, recycle any obsolete
|
||||
* OS partitions and try again.
|
||||
* 4.) Will first try getting a chunk that will satisfy the requested size.
|
||||
* 5.) If a chunk of the requested size cannot be allocated, then try finding
|
||||
* a chunk that will satisfy the minum needed.
|
||||
*
|
||||
* Returns 0 on success, else -1.
|
||||
*/
|
||||
static int __init pseries_nvram_init_log_partition(void)
|
||||
static int __init pseries_nvram_init_os_partition(struct nvram_os_partition
|
||||
*part)
|
||||
{
|
||||
loff_t p;
|
||||
int size;
|
||||
|
@ -282,47 +334,76 @@ static int __init pseries_nvram_init_log_partition(void)
|
|||
/* Scan nvram for partitions */
|
||||
nvram_scan_partitions();
|
||||
|
||||
/* Lookg for ours */
|
||||
p = nvram_find_partition(NVRAM_LOG_PART_NAME, NVRAM_SIG_OS, &size);
|
||||
/* Look for ours */
|
||||
p = nvram_find_partition(part->name, NVRAM_SIG_OS, &size);
|
||||
|
||||
/* Found one but too small, remove it */
|
||||
if (p && size < NVRAM_MIN_REQ) {
|
||||
pr_info("nvram: Found too small "NVRAM_LOG_PART_NAME" partition"
|
||||
",removing it...");
|
||||
nvram_remove_partition(NVRAM_LOG_PART_NAME, NVRAM_SIG_OS);
|
||||
if (p && size < part->min_size) {
|
||||
pr_info("nvram: Found too small %s partition,"
|
||||
" removing it...\n", part->name);
|
||||
nvram_remove_partition(part->name, NVRAM_SIG_OS, NULL);
|
||||
p = 0;
|
||||
}
|
||||
|
||||
/* Create one if we didn't find */
|
||||
if (!p) {
|
||||
p = nvram_create_partition(NVRAM_LOG_PART_NAME, NVRAM_SIG_OS,
|
||||
NVRAM_MAX_REQ, NVRAM_MIN_REQ);
|
||||
/* No room for it, try to get rid of any OS partition
|
||||
* and try again
|
||||
*/
|
||||
p = nvram_create_partition(part->name, NVRAM_SIG_OS,
|
||||
part->req_size, part->min_size);
|
||||
if (p == -ENOSPC) {
|
||||
pr_info("nvram: No room to create "NVRAM_LOG_PART_NAME
|
||||
" partition, deleting all OS partitions...");
|
||||
nvram_remove_partition(NULL, NVRAM_SIG_OS);
|
||||
p = nvram_create_partition(NVRAM_LOG_PART_NAME,
|
||||
NVRAM_SIG_OS, NVRAM_MAX_REQ,
|
||||
NVRAM_MIN_REQ);
|
||||
pr_info("nvram: No room to create %s partition, "
|
||||
"deleting any obsolete OS partitions...\n",
|
||||
part->name);
|
||||
nvram_remove_partition(NULL, NVRAM_SIG_OS,
|
||||
pseries_nvram_os_partitions);
|
||||
p = nvram_create_partition(part->name, NVRAM_SIG_OS,
|
||||
part->req_size, part->min_size);
|
||||
}
|
||||
}
|
||||
|
||||
if (p <= 0) {
|
||||
pr_err("nvram: Failed to find or create "NVRAM_LOG_PART_NAME
|
||||
" partition, err %d\n", (int)p);
|
||||
return 0;
|
||||
pr_err("nvram: Failed to find or create %s"
|
||||
" partition, err %d\n", part->name, (int)p);
|
||||
return -1;
|
||||
}
|
||||
|
||||
nvram_error_log_index = p;
|
||||
nvram_error_log_size = nvram_get_partition_size(p) -
|
||||
sizeof(struct err_log_info);
|
||||
part->index = p;
|
||||
part->size = nvram_get_partition_size(p) - sizeof(struct err_log_info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
machine_arch_initcall(pseries, pseries_nvram_init_log_partition);
|
||||
|
||||
static void __init nvram_init_oops_partition(int rtas_partition_exists)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = pseries_nvram_init_os_partition(&oops_log_partition);
|
||||
if (rc != 0) {
|
||||
if (!rtas_partition_exists)
|
||||
return;
|
||||
pr_notice("nvram: Using %s partition to log both"
|
||||
" RTAS errors and oops/panic reports\n",
|
||||
rtas_log_partition.name);
|
||||
memcpy(&oops_log_partition, &rtas_log_partition,
|
||||
sizeof(rtas_log_partition));
|
||||
}
|
||||
oops_buf = kmalloc(oops_log_partition.size, GFP_KERNEL);
|
||||
rc = kmsg_dump_register(&nvram_kmsg_dumper);
|
||||
if (rc != 0) {
|
||||
pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc);
|
||||
kfree(oops_buf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static int __init pseries_nvram_init_log_partitions(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = pseries_nvram_init_os_partition(&rtas_log_partition);
|
||||
nvram_init_oops_partition(rc == 0);
|
||||
return 0;
|
||||
}
|
||||
machine_arch_initcall(pseries, pseries_nvram_init_log_partitions);
|
||||
|
||||
int __init pSeries_nvram_init(void)
|
||||
{
|
||||
|
@ -353,3 +434,59 @@ int __init pSeries_nvram_init(void)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to capture the last capture_len bytes of the printk buffer. Return
|
||||
* the amount actually captured.
|
||||
*/
|
||||
static size_t capture_last_msgs(const char *old_msgs, size_t old_len,
|
||||
const char *new_msgs, size_t new_len,
|
||||
char *captured, size_t capture_len)
|
||||
{
|
||||
if (new_len >= capture_len) {
|
||||
memcpy(captured, new_msgs + (new_len - capture_len),
|
||||
capture_len);
|
||||
return capture_len;
|
||||
} else {
|
||||
/* Grab the end of old_msgs. */
|
||||
size_t old_tail_len = min(old_len, capture_len - new_len);
|
||||
memcpy(captured, old_msgs + (old_len - old_tail_len),
|
||||
old_tail_len);
|
||||
memcpy(captured + old_tail_len, new_msgs, new_len);
|
||||
return old_tail_len + new_len;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Are we using the ibm,rtas-log for oops/panic reports? And if so,
|
||||
* would logging this oops/panic overwrite an RTAS event that rtas_errd
|
||||
* hasn't had a chance to read and process? Return 1 if so, else 0.
|
||||
*
|
||||
* We assume that if rtas_errd hasn't read the RTAS event in
|
||||
* NVRAM_RTAS_READ_TIMEOUT seconds, it's probably not going to.
|
||||
*/
|
||||
static int clobbering_unread_rtas_event(void)
|
||||
{
|
||||
return (oops_log_partition.index == rtas_log_partition.index
|
||||
&& last_unread_rtas_event
|
||||
&& get_seconds() - last_unread_rtas_event <=
|
||||
NVRAM_RTAS_READ_TIMEOUT);
|
||||
}
|
||||
|
||||
/* our kmsg_dump callback */
|
||||
static void oops_to_nvram(struct kmsg_dumper *dumper,
|
||||
enum kmsg_dump_reason reason,
|
||||
const char *old_msgs, unsigned long old_len,
|
||||
const char *new_msgs, unsigned long new_len)
|
||||
{
|
||||
static unsigned int oops_count = 0;
|
||||
size_t text_len;
|
||||
|
||||
if (clobbering_unread_rtas_event())
|
||||
return;
|
||||
|
||||
text_len = capture_last_msgs(old_msgs, old_len, new_msgs, new_len,
|
||||
oops_buf, oops_log_partition.size);
|
||||
(void) nvram_write_os_partition(&oops_log_partition, oops_buf,
|
||||
(int) text_len, ERR_TYPE_KERNEL_PANIC, ++oops_count);
|
||||
}
|
||||
|
|
|
@ -114,10 +114,13 @@ static void __init fwnmi_init(void)
|
|||
|
||||
static void pseries_8259_cascade(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = get_irq_desc_chip(desc);
|
||||
unsigned int cascade_irq = i8259_irq();
|
||||
|
||||
if (cascade_irq != NO_IRQ)
|
||||
generic_handle_irq(cascade_irq);
|
||||
desc->chip->eoi(irq);
|
||||
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
}
|
||||
|
||||
static void __init pseries_setup_i8259_cascade(void)
|
||||
|
|
|
@ -202,20 +202,20 @@ static int get_irq_server(unsigned int virq, const struct cpumask *cpumask,
|
|||
#define get_irq_server(virq, cpumask, strict_check) (default_server)
|
||||
#endif
|
||||
|
||||
static void xics_unmask_irq(unsigned int virq)
|
||||
static void xics_unmask_irq(struct irq_data *d)
|
||||
{
|
||||
unsigned int irq;
|
||||
int call_status;
|
||||
int server;
|
||||
|
||||
pr_devel("xics: unmask virq %d\n", virq);
|
||||
pr_devel("xics: unmask virq %d\n", d->irq);
|
||||
|
||||
irq = (unsigned int)irq_map[virq].hwirq;
|
||||
irq = (unsigned int)irq_map[d->irq].hwirq;
|
||||
pr_devel(" -> map to hwirq 0x%x\n", irq);
|
||||
if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
|
||||
return;
|
||||
|
||||
server = get_irq_server(virq, irq_to_desc(virq)->affinity, 0);
|
||||
server = get_irq_server(d->irq, d->affinity, 0);
|
||||
|
||||
call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server,
|
||||
DEFAULT_PRIORITY);
|
||||
|
@ -235,61 +235,61 @@ static void xics_unmask_irq(unsigned int virq)
|
|||
}
|
||||
}
|
||||
|
||||
static unsigned int xics_startup(unsigned int virq)
|
||||
static unsigned int xics_startup(struct irq_data *d)
|
||||
{
|
||||
/*
|
||||
* The generic MSI code returns with the interrupt disabled on the
|
||||
* card, using the MSI mask bits. Firmware doesn't appear to unmask
|
||||
* at that level, so we do it here by hand.
|
||||
*/
|
||||
if (irq_to_desc(virq)->msi_desc)
|
||||
unmask_msi_irq(irq_get_irq_data(virq));
|
||||
if (d->msi_desc)
|
||||
unmask_msi_irq(d);
|
||||
|
||||
/* unmask it */
|
||||
xics_unmask_irq(virq);
|
||||
xics_unmask_irq(d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void xics_mask_real_irq(unsigned int irq)
|
||||
static void xics_mask_real_irq(struct irq_data *d)
|
||||
{
|
||||
int call_status;
|
||||
|
||||
if (irq == XICS_IPI)
|
||||
if (d->irq == XICS_IPI)
|
||||
return;
|
||||
|
||||
call_status = rtas_call(ibm_int_off, 1, 1, NULL, irq);
|
||||
call_status = rtas_call(ibm_int_off, 1, 1, NULL, d->irq);
|
||||
if (call_status != 0) {
|
||||
printk(KERN_ERR "%s: ibm_int_off irq=%u returned %d\n",
|
||||
__func__, irq, call_status);
|
||||
__func__, d->irq, call_status);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Have to set XIVE to 0xff to be able to remove a slot */
|
||||
call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq,
|
||||
call_status = rtas_call(ibm_set_xive, 3, 1, NULL, d->irq,
|
||||
default_server, 0xff);
|
||||
if (call_status != 0) {
|
||||
printk(KERN_ERR "%s: ibm_set_xive(0xff) irq=%u returned %d\n",
|
||||
__func__, irq, call_status);
|
||||
__func__, d->irq, call_status);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void xics_mask_irq(unsigned int virq)
|
||||
static void xics_mask_irq(struct irq_data *d)
|
||||
{
|
||||
unsigned int irq;
|
||||
|
||||
pr_devel("xics: mask virq %d\n", virq);
|
||||
pr_devel("xics: mask virq %d\n", d->irq);
|
||||
|
||||
irq = (unsigned int)irq_map[virq].hwirq;
|
||||
irq = (unsigned int)irq_map[d->irq].hwirq;
|
||||
if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
|
||||
return;
|
||||
xics_mask_real_irq(irq);
|
||||
xics_mask_real_irq(d);
|
||||
}
|
||||
|
||||
static void xics_mask_unknown_vec(unsigned int vec)
|
||||
{
|
||||
printk(KERN_ERR "Interrupt %u (real) is invalid, disabling it.\n", vec);
|
||||
xics_mask_real_irq(vec);
|
||||
xics_mask_real_irq(irq_get_irq_data(vec));
|
||||
}
|
||||
|
||||
static inline unsigned int xics_xirr_vector(unsigned int xirr)
|
||||
|
@ -371,30 +371,31 @@ static unsigned char pop_cppr(void)
|
|||
return os_cppr->stack[--os_cppr->index];
|
||||
}
|
||||
|
||||
static void xics_eoi_direct(unsigned int virq)
|
||||
static void xics_eoi_direct(struct irq_data *d)
|
||||
{
|
||||
unsigned int irq = (unsigned int)irq_map[virq].hwirq;
|
||||
unsigned int irq = (unsigned int)irq_map[d->irq].hwirq;
|
||||
|
||||
iosync();
|
||||
direct_xirr_info_set((pop_cppr() << 24) | irq);
|
||||
}
|
||||
|
||||
static void xics_eoi_lpar(unsigned int virq)
|
||||
static void xics_eoi_lpar(struct irq_data *d)
|
||||
{
|
||||
unsigned int irq = (unsigned int)irq_map[virq].hwirq;
|
||||
unsigned int irq = (unsigned int)irq_map[d->irq].hwirq;
|
||||
|
||||
iosync();
|
||||
lpar_xirr_info_set((pop_cppr() << 24) | irq);
|
||||
}
|
||||
|
||||
static int xics_set_affinity(unsigned int virq, const struct cpumask *cpumask)
|
||||
static int
|
||||
xics_set_affinity(struct irq_data *d, const struct cpumask *cpumask, bool force)
|
||||
{
|
||||
unsigned int irq;
|
||||
int status;
|
||||
int xics_status[2];
|
||||
int irq_server;
|
||||
|
||||
irq = (unsigned int)irq_map[virq].hwirq;
|
||||
irq = (unsigned int)irq_map[d->irq].hwirq;
|
||||
if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
|
||||
return -1;
|
||||
|
||||
|
@ -406,13 +407,13 @@ static int xics_set_affinity(unsigned int virq, const struct cpumask *cpumask)
|
|||
return -1;
|
||||
}
|
||||
|
||||
irq_server = get_irq_server(virq, cpumask, 1);
|
||||
irq_server = get_irq_server(d->irq, cpumask, 1);
|
||||
if (irq_server == -1) {
|
||||
char cpulist[128];
|
||||
cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask);
|
||||
printk(KERN_WARNING
|
||||
"%s: No online cpus in the mask %s for irq %d\n",
|
||||
__func__, cpulist, virq);
|
||||
__func__, cpulist, d->irq);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -430,20 +431,20 @@ static int xics_set_affinity(unsigned int virq, const struct cpumask *cpumask)
|
|||
|
||||
static struct irq_chip xics_pic_direct = {
|
||||
.name = "XICS",
|
||||
.startup = xics_startup,
|
||||
.mask = xics_mask_irq,
|
||||
.unmask = xics_unmask_irq,
|
||||
.eoi = xics_eoi_direct,
|
||||
.set_affinity = xics_set_affinity
|
||||
.irq_startup = xics_startup,
|
||||
.irq_mask = xics_mask_irq,
|
||||
.irq_unmask = xics_unmask_irq,
|
||||
.irq_eoi = xics_eoi_direct,
|
||||
.irq_set_affinity = xics_set_affinity
|
||||
};
|
||||
|
||||
static struct irq_chip xics_pic_lpar = {
|
||||
.name = "XICS",
|
||||
.startup = xics_startup,
|
||||
.mask = xics_mask_irq,
|
||||
.unmask = xics_unmask_irq,
|
||||
.eoi = xics_eoi_lpar,
|
||||
.set_affinity = xics_set_affinity
|
||||
.irq_startup = xics_startup,
|
||||
.irq_mask = xics_mask_irq,
|
||||
.irq_unmask = xics_unmask_irq,
|
||||
.irq_eoi = xics_eoi_lpar,
|
||||
.irq_set_affinity = xics_set_affinity
|
||||
};
|
||||
|
||||
|
||||
|
@ -890,6 +891,7 @@ void xics_migrate_irqs_away(void)
|
|||
|
||||
for_each_irq(virq) {
|
||||
struct irq_desc *desc;
|
||||
struct irq_chip *chip;
|
||||
int xics_status[2];
|
||||
int status;
|
||||
unsigned long flags;
|
||||
|
@ -903,12 +905,15 @@ void xics_migrate_irqs_away(void)
|
|||
/* We need to get IPIs still. */
|
||||
if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
|
||||
continue;
|
||||
|
||||
desc = irq_to_desc(virq);
|
||||
|
||||
/* We only need to migrate enabled IRQS */
|
||||
if (desc == NULL || desc->chip == NULL
|
||||
|| desc->action == NULL
|
||||
|| desc->chip->set_affinity == NULL)
|
||||
if (desc == NULL || desc->action == NULL)
|
||||
continue;
|
||||
|
||||
chip = get_irq_desc_chip(desc);
|
||||
if (chip == NULL || chip->irq_set_affinity == NULL)
|
||||
continue;
|
||||
|
||||
raw_spin_lock_irqsave(&desc->lock, flags);
|
||||
|
@ -934,8 +939,8 @@ void xics_migrate_irqs_away(void)
|
|||
virq, cpu);
|
||||
|
||||
/* Reset affinity to all cpus */
|
||||
cpumask_setall(irq_to_desc(virq)->affinity);
|
||||
desc->chip->set_affinity(virq, cpu_all_mask);
|
||||
cpumask_setall(desc->irq_data.affinity);
|
||||
chip->irq_set_affinity(&desc->irq_data, cpu_all_mask, true);
|
||||
unlock:
|
||||
raw_spin_unlock_irqrestore(&desc->lock, flags);
|
||||
}
|
||||
|
|
|
@ -56,32 +56,32 @@ static cpic8xx_t __iomem *cpic_reg;
|
|||
|
||||
static struct irq_host *cpm_pic_host;
|
||||
|
||||
static void cpm_mask_irq(unsigned int irq)
|
||||
static void cpm_mask_irq(struct irq_data *d)
|
||||
{
|
||||
unsigned int cpm_vec = (unsigned int)irq_map[irq].hwirq;
|
||||
unsigned int cpm_vec = (unsigned int)irq_map[d->irq].hwirq;
|
||||
|
||||
clrbits32(&cpic_reg->cpic_cimr, (1 << cpm_vec));
|
||||
}
|
||||
|
||||
static void cpm_unmask_irq(unsigned int irq)
|
||||
static void cpm_unmask_irq(struct irq_data *d)
|
||||
{
|
||||
unsigned int cpm_vec = (unsigned int)irq_map[irq].hwirq;
|
||||
unsigned int cpm_vec = (unsigned int)irq_map[d->irq].hwirq;
|
||||
|
||||
setbits32(&cpic_reg->cpic_cimr, (1 << cpm_vec));
|
||||
}
|
||||
|
||||
static void cpm_end_irq(unsigned int irq)
|
||||
static void cpm_end_irq(struct irq_data *d)
|
||||
{
|
||||
unsigned int cpm_vec = (unsigned int)irq_map[irq].hwirq;
|
||||
unsigned int cpm_vec = (unsigned int)irq_map[d->irq].hwirq;
|
||||
|
||||
out_be32(&cpic_reg->cpic_cisr, (1 << cpm_vec));
|
||||
}
|
||||
|
||||
static struct irq_chip cpm_pic = {
|
||||
.name = "CPM PIC",
|
||||
.mask = cpm_mask_irq,
|
||||
.unmask = cpm_unmask_irq,
|
||||
.eoi = cpm_end_irq,
|
||||
.irq_mask = cpm_mask_irq,
|
||||
.irq_unmask = cpm_unmask_irq,
|
||||
.irq_eoi = cpm_end_irq,
|
||||
};
|
||||
|
||||
int cpm_get_irq(void)
|
||||
|
|
|
@ -78,10 +78,10 @@ static const u_char irq_to_siubit[] = {
|
|||
24, 25, 26, 27, 28, 29, 30, 31,
|
||||
};
|
||||
|
||||
static void cpm2_mask_irq(unsigned int virq)
|
||||
static void cpm2_mask_irq(struct irq_data *d)
|
||||
{
|
||||
int bit, word;
|
||||
unsigned int irq_nr = virq_to_hw(virq);
|
||||
unsigned int irq_nr = virq_to_hw(d->irq);
|
||||
|
||||
bit = irq_to_siubit[irq_nr];
|
||||
word = irq_to_siureg[irq_nr];
|
||||
|
@ -90,10 +90,10 @@ static void cpm2_mask_irq(unsigned int virq)
|
|||
out_be32(&cpm2_intctl->ic_simrh + word, ppc_cached_irq_mask[word]);
|
||||
}
|
||||
|
||||
static void cpm2_unmask_irq(unsigned int virq)
|
||||
static void cpm2_unmask_irq(struct irq_data *d)
|
||||
{
|
||||
int bit, word;
|
||||
unsigned int irq_nr = virq_to_hw(virq);
|
||||
unsigned int irq_nr = virq_to_hw(d->irq);
|
||||
|
||||
bit = irq_to_siubit[irq_nr];
|
||||
word = irq_to_siureg[irq_nr];
|
||||
|
@ -102,10 +102,10 @@ static void cpm2_unmask_irq(unsigned int virq)
|
|||
out_be32(&cpm2_intctl->ic_simrh + word, ppc_cached_irq_mask[word]);
|
||||
}
|
||||
|
||||
static void cpm2_ack(unsigned int virq)
|
||||
static void cpm2_ack(struct irq_data *d)
|
||||
{
|
||||
int bit, word;
|
||||
unsigned int irq_nr = virq_to_hw(virq);
|
||||
unsigned int irq_nr = virq_to_hw(d->irq);
|
||||
|
||||
bit = irq_to_siubit[irq_nr];
|
||||
word = irq_to_siureg[irq_nr];
|
||||
|
@ -113,11 +113,11 @@ static void cpm2_ack(unsigned int virq)
|
|||
out_be32(&cpm2_intctl->ic_sipnrh + word, 1 << bit);
|
||||
}
|
||||
|
||||
static void cpm2_end_irq(unsigned int virq)
|
||||
static void cpm2_end_irq(struct irq_data *d)
|
||||
{
|
||||
struct irq_desc *desc;
|
||||
int bit, word;
|
||||
unsigned int irq_nr = virq_to_hw(virq);
|
||||
unsigned int irq_nr = virq_to_hw(d->irq);
|
||||
|
||||
desc = irq_to_desc(irq_nr);
|
||||
if (!(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))
|
||||
|
@ -137,10 +137,10 @@ static void cpm2_end_irq(unsigned int virq)
|
|||
}
|
||||
}
|
||||
|
||||
static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type)
|
||||
static int cpm2_set_irq_type(struct irq_data *d, unsigned int flow_type)
|
||||
{
|
||||
unsigned int src = virq_to_hw(virq);
|
||||
struct irq_desc *desc = irq_to_desc(virq);
|
||||
unsigned int src = virq_to_hw(d->irq);
|
||||
struct irq_desc *desc = irq_to_desc(d->irq);
|
||||
unsigned int vold, vnew, edibit;
|
||||
|
||||
/* Port C interrupts are either IRQ_TYPE_EDGE_FALLING or
|
||||
|
@ -199,11 +199,11 @@ err_sense:
|
|||
|
||||
static struct irq_chip cpm2_pic = {
|
||||
.name = "CPM2 SIU",
|
||||
.mask = cpm2_mask_irq,
|
||||
.unmask = cpm2_unmask_irq,
|
||||
.ack = cpm2_ack,
|
||||
.eoi = cpm2_end_irq,
|
||||
.set_type = cpm2_set_irq_type,
|
||||
.irq_mask = cpm2_mask_irq,
|
||||
.irq_unmask = cpm2_unmask_irq,
|
||||
.irq_ack = cpm2_ack,
|
||||
.irq_eoi = cpm2_end_irq,
|
||||
.irq_set_type = cpm2_set_irq_type,
|
||||
};
|
||||
|
||||
unsigned int cpm2_get_irq(void)
|
||||
|
|
|
@ -93,14 +93,14 @@ static int __devinit mpc85xx_l2ctlr_of_probe(struct platform_device *dev)
|
|||
l2cache_size = *prop;
|
||||
|
||||
sram_params.sram_size = get_cache_sram_size();
|
||||
if (sram_params.sram_size <= 0) {
|
||||
if ((int)sram_params.sram_size <= 0) {
|
||||
dev_err(&dev->dev,
|
||||
"Entire L2 as cache, Aborting Cache-SRAM stuff\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sram_params.sram_offset = get_cache_sram_offset();
|
||||
if (sram_params.sram_offset <= 0) {
|
||||
if ((int64_t)sram_params.sram_offset <= 0) {
|
||||
dev_err(&dev->dev,
|
||||
"Entire L2 as cache, provide a valid sram offset\n");
|
||||
return -EINVAL;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2007-2010 Freescale Semiconductor, Inc.
|
||||
* Copyright (C) 2007-2011 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* Author: Tony Li <tony.li@freescale.com>
|
||||
* Jason Jin <Jason.jin@freescale.com>
|
||||
|
@ -47,14 +47,14 @@ static inline u32 fsl_msi_read(u32 __iomem *base, unsigned int reg)
|
|||
* We do not need this actually. The MSIR register has been read once
|
||||
* in the cascade interrupt. So, this MSI interrupt has been acked
|
||||
*/
|
||||
static void fsl_msi_end_irq(unsigned int virq)
|
||||
static void fsl_msi_end_irq(struct irq_data *d)
|
||||
{
|
||||
}
|
||||
|
||||
static struct irq_chip fsl_msi_chip = {
|
||||
.irq_mask = mask_msi_irq,
|
||||
.irq_unmask = unmask_msi_irq,
|
||||
.ack = fsl_msi_end_irq,
|
||||
.irq_ack = fsl_msi_end_irq,
|
||||
.name = "FSL-MSI",
|
||||
};
|
||||
|
||||
|
@ -183,6 +183,7 @@ out_free:
|
|||
|
||||
static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = get_irq_desc_chip(desc);
|
||||
unsigned int cascade_irq;
|
||||
struct fsl_msi *msi_data;
|
||||
int msir_index = -1;
|
||||
|
@ -196,11 +197,11 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
|
|||
|
||||
raw_spin_lock(&desc->lock);
|
||||
if ((msi_data->feature & FSL_PIC_IP_MASK) == FSL_PIC_IP_IPIC) {
|
||||
if (desc->chip->mask_ack)
|
||||
desc->chip->mask_ack(irq);
|
||||
if (chip->irq_mask_ack)
|
||||
chip->irq_mask_ack(&desc->irq_data);
|
||||
else {
|
||||
desc->chip->mask(irq);
|
||||
desc->chip->ack(irq);
|
||||
chip->irq_mask(&desc->irq_data);
|
||||
chip->irq_ack(&desc->irq_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -238,11 +239,11 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
|
|||
|
||||
switch (msi_data->feature & FSL_PIC_IP_MASK) {
|
||||
case FSL_PIC_IP_MPIC:
|
||||
desc->chip->eoi(irq);
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
break;
|
||||
case FSL_PIC_IP_IPIC:
|
||||
if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
|
||||
desc->chip->unmask(irq);
|
||||
if (!(desc->status & IRQ_DISABLED) && chip->irq_unmask)
|
||||
chip->irq_unmask(&desc->irq_data);
|
||||
break;
|
||||
}
|
||||
unlock:
|
||||
|
@ -273,18 +274,46 @@ static int fsl_of_msi_remove(struct platform_device *ofdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit fsl_msi_setup_hwirq(struct fsl_msi *msi,
|
||||
struct platform_device *dev,
|
||||
int offset, int irq_index)
|
||||
{
|
||||
struct fsl_msi_cascade_data *cascade_data = NULL;
|
||||
int virt_msir;
|
||||
|
||||
virt_msir = irq_of_parse_and_map(dev->dev.of_node, irq_index);
|
||||
if (virt_msir == NO_IRQ) {
|
||||
dev_err(&dev->dev, "%s: Cannot translate IRQ index %d\n",
|
||||
__func__, irq_index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cascade_data = kzalloc(sizeof(struct fsl_msi_cascade_data), GFP_KERNEL);
|
||||
if (!cascade_data) {
|
||||
dev_err(&dev->dev, "No memory for MSI cascade data\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
msi->msi_virqs[irq_index] = virt_msir;
|
||||
cascade_data->index = offset + irq_index;
|
||||
cascade_data->msi_data = msi;
|
||||
set_irq_data(virt_msir, cascade_data);
|
||||
set_irq_chained_handler(virt_msir, fsl_msi_cascade);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit fsl_of_msi_probe(struct platform_device *dev)
|
||||
{
|
||||
struct fsl_msi *msi;
|
||||
struct resource res;
|
||||
int err, i, count;
|
||||
int err, i, j, irq_index, count;
|
||||
int rc;
|
||||
int virt_msir;
|
||||
const u32 *p;
|
||||
struct fsl_msi_feature *features;
|
||||
struct fsl_msi_cascade_data *cascade_data = NULL;
|
||||
int len;
|
||||
u32 offset;
|
||||
static const u32 all_avail[] = { 0, NR_MSI_IRQS };
|
||||
|
||||
if (!dev->dev.of_match)
|
||||
return -EINVAL;
|
||||
|
@ -335,42 +364,34 @@ static int __devinit fsl_of_msi_probe(struct platform_device *dev)
|
|||
goto error_out;
|
||||
}
|
||||
|
||||
p = of_get_property(dev->dev.of_node, "interrupts", &count);
|
||||
if (!p) {
|
||||
dev_err(&dev->dev, "no interrupts property found on %s\n",
|
||||
dev->dev.of_node->full_name);
|
||||
err = -ENODEV;
|
||||
goto error_out;
|
||||
}
|
||||
if (count % 8 != 0) {
|
||||
dev_err(&dev->dev, "Malformed interrupts property on %s\n",
|
||||
dev->dev.of_node->full_name);
|
||||
p = of_get_property(dev->dev.of_node, "msi-available-ranges", &len);
|
||||
if (p && len % (2 * sizeof(u32)) != 0) {
|
||||
dev_err(&dev->dev, "%s: Malformed msi-available-ranges property\n",
|
||||
__func__);
|
||||
err = -EINVAL;
|
||||
goto error_out;
|
||||
}
|
||||
offset = 0;
|
||||
p = of_get_property(dev->dev.of_node, "msi-available-ranges", &len);
|
||||
if (p)
|
||||
offset = *p / IRQS_PER_MSI_REG;
|
||||
|
||||
count /= sizeof(u32);
|
||||
for (i = 0; i < min(count / 2, NR_MSI_REG); i++) {
|
||||
virt_msir = irq_of_parse_and_map(dev->dev.of_node, i);
|
||||
if (virt_msir != NO_IRQ) {
|
||||
cascade_data = kzalloc(
|
||||
sizeof(struct fsl_msi_cascade_data),
|
||||
GFP_KERNEL);
|
||||
if (!cascade_data) {
|
||||
dev_err(&dev->dev,
|
||||
"No memory for MSI cascade data\n");
|
||||
err = -ENOMEM;
|
||||
if (!p)
|
||||
p = all_avail;
|
||||
|
||||
for (irq_index = 0, i = 0; i < len / (2 * sizeof(u32)); i++) {
|
||||
if (p[i * 2] % IRQS_PER_MSI_REG ||
|
||||
p[i * 2 + 1] % IRQS_PER_MSI_REG) {
|
||||
printk(KERN_WARNING "%s: %s: msi available range of %u at %u is not IRQ-aligned\n",
|
||||
__func__, dev->dev.of_node->full_name,
|
||||
p[i * 2 + 1], p[i * 2]);
|
||||
err = -EINVAL;
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
offset = p[i * 2] / IRQS_PER_MSI_REG;
|
||||
count = p[i * 2 + 1] / IRQS_PER_MSI_REG;
|
||||
|
||||
for (j = 0; j < count; j++, irq_index++) {
|
||||
err = fsl_msi_setup_hwirq(msi, dev, offset, irq_index);
|
||||
if (err)
|
||||
goto error_out;
|
||||
}
|
||||
msi->msi_virqs[i] = virt_msir;
|
||||
cascade_data->index = i + offset;
|
||||
cascade_data->msi_data = msi;
|
||||
set_irq_data(virt_msir, (void *)cascade_data);
|
||||
set_irq_chained_handler(virt_msir, fsl_msi_cascade);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* MPC83xx/85xx/86xx PCI/PCIE support routing.
|
||||
*
|
||||
* Copyright 2007-2010 Freescale Semiconductor, Inc.
|
||||
* Copyright 2007-2011 Freescale Semiconductor, Inc.
|
||||
* Copyright 2008-2009 MontaVista Software, Inc.
|
||||
*
|
||||
* Initial author: Xianghua Xiao <x.xiao@freescale.com>
|
||||
|
@ -99,7 +99,7 @@ static void __init setup_pci_atmu(struct pci_controller *hose,
|
|||
struct resource *rsrc)
|
||||
{
|
||||
struct ccsr_pci __iomem *pci;
|
||||
int i, j, n, mem_log, win_idx = 2;
|
||||
int i, j, n, mem_log, win_idx = 3, start_idx = 1, end_idx = 4;
|
||||
u64 mem, sz, paddr_hi = 0;
|
||||
u64 paddr_lo = ULLONG_MAX;
|
||||
u32 pcicsrbar = 0, pcicsrbar_sz;
|
||||
|
@ -109,6 +109,13 @@ static void __init setup_pci_atmu(struct pci_controller *hose,
|
|||
|
||||
pr_debug("PCI memory map start 0x%016llx, size 0x%016llx\n",
|
||||
(u64)rsrc->start, (u64)rsrc->end - (u64)rsrc->start + 1);
|
||||
|
||||
if (of_device_is_compatible(hose->dn, "fsl,qoriq-pcie-v2.2")) {
|
||||
win_idx = 2;
|
||||
start_idx = 0;
|
||||
end_idx = 3;
|
||||
}
|
||||
|
||||
pci = ioremap(rsrc->start, rsrc->end - rsrc->start + 1);
|
||||
if (!pci) {
|
||||
dev_err(hose->parent, "Unable to map ATMU registers\n");
|
||||
|
@ -118,7 +125,7 @@ static void __init setup_pci_atmu(struct pci_controller *hose,
|
|||
/* Disable all windows (except powar0 since it's ignored) */
|
||||
for(i = 1; i < 5; i++)
|
||||
out_be32(&pci->pow[i].powar, 0);
|
||||
for(i = 0; i < 3; i++)
|
||||
for (i = start_idx; i < end_idx; i++)
|
||||
out_be32(&pci->piw[i].piwar, 0);
|
||||
|
||||
/* Setup outbound MEM window */
|
||||
|
@ -204,7 +211,7 @@ static void __init setup_pci_atmu(struct pci_controller *hose,
|
|||
mem_log++;
|
||||
}
|
||||
|
||||
piwar |= (mem_log - 1);
|
||||
piwar |= ((mem_log - 1) & PIWAR_SZ_MASK);
|
||||
|
||||
/* Setup inbound memory window */
|
||||
out_be32(&pci->piw[win_idx].pitar, 0x00000000);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* MPC85xx/86xx PCI Express structure define
|
||||
*
|
||||
* Copyright 2007 Freescale Semiconductor, Inc
|
||||
* Copyright 2007,2011 Freescale Semiconductor, Inc
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
|
@ -21,6 +21,7 @@
|
|||
#define PIWAR_TGI_LOCAL 0x00f00000 /* target - local memory */
|
||||
#define PIWAR_READ_SNOOP 0x00050000
|
||||
#define PIWAR_WRITE_SNOOP 0x00005000
|
||||
#define PIWAR_SZ_MASK 0x0000003f
|
||||
|
||||
/* PCI/PCI Express outbound window reg */
|
||||
struct pci_outbound_window_regs {
|
||||
|
@ -49,7 +50,9 @@ struct ccsr_pci {
|
|||
__be32 int_ack; /* 0x.008 - PCI Interrupt Acknowledge Register */
|
||||
__be32 pex_otb_cpl_tor; /* 0x.00c - PCIE Outbound completion timeout register */
|
||||
__be32 pex_conf_tor; /* 0x.010 - PCIE configuration timeout register */
|
||||
u8 res2[12];
|
||||
__be32 pex_config; /* 0x.014 - PCIE CONFIG Register */
|
||||
__be32 pex_int_status; /* 0x.018 - PCIE interrupt status */
|
||||
u8 res2[4];
|
||||
__be32 pex_pme_mes_dr; /* 0x.020 - PCIE PME and message detect register */
|
||||
__be32 pex_pme_mes_disr; /* 0x.024 - PCIE PME and message disable register */
|
||||
__be32 pex_pme_mes_ier; /* 0x.028 - PCIE PME and message interrupt enable register */
|
||||
|
@ -62,14 +65,14 @@ struct ccsr_pci {
|
|||
* in all of the other outbound windows.
|
||||
*/
|
||||
struct pci_outbound_window_regs pow[5];
|
||||
|
||||
u8 res14[256];
|
||||
|
||||
/* PCI/PCI Express inbound window 3-1
|
||||
u8 res14[96];
|
||||
struct pci_inbound_window_regs pmit; /* 0xd00 - 0xd9c Inbound MSI */
|
||||
u8 res6[96];
|
||||
/* PCI/PCI Express inbound window 3-0
|
||||
* inbound window 1 supports only a 32-bit base address and does not
|
||||
* define an inbound window base extended address register.
|
||||
*/
|
||||
struct pci_inbound_window_regs piw[3];
|
||||
struct pci_inbound_window_regs piw[4];
|
||||
|
||||
__be32 pex_err_dr; /* 0x.e00 - PCI/PCIE error detect register */
|
||||
u8 res21[4];
|
||||
|
|
|
@ -78,19 +78,19 @@ unsigned int i8259_irq(void)
|
|||
return irq;
|
||||
}
|
||||
|
||||
static void i8259_mask_and_ack_irq(unsigned int irq_nr)
|
||||
static void i8259_mask_and_ack_irq(struct irq_data *d)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
raw_spin_lock_irqsave(&i8259_lock, flags);
|
||||
if (irq_nr > 7) {
|
||||
cached_A1 |= 1 << (irq_nr-8);
|
||||
if (d->irq > 7) {
|
||||
cached_A1 |= 1 << (d->irq-8);
|
||||
inb(0xA1); /* DUMMY */
|
||||
outb(cached_A1, 0xA1);
|
||||
outb(0x20, 0xA0); /* Non-specific EOI */
|
||||
outb(0x20, 0x20); /* Non-specific EOI to cascade */
|
||||
} else {
|
||||
cached_21 |= 1 << irq_nr;
|
||||
cached_21 |= 1 << d->irq;
|
||||
inb(0x21); /* DUMMY */
|
||||
outb(cached_21, 0x21);
|
||||
outb(0x20, 0x20); /* Non-specific EOI */
|
||||
|
@ -104,42 +104,42 @@ static void i8259_set_irq_mask(int irq_nr)
|
|||
outb(cached_21,0x21);
|
||||
}
|
||||
|
||||
static void i8259_mask_irq(unsigned int irq_nr)
|
||||
static void i8259_mask_irq(struct irq_data *d)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
pr_debug("i8259_mask_irq(%d)\n", irq_nr);
|
||||
pr_debug("i8259_mask_irq(%d)\n", d->irq);
|
||||
|
||||
raw_spin_lock_irqsave(&i8259_lock, flags);
|
||||
if (irq_nr < 8)
|
||||
cached_21 |= 1 << irq_nr;
|
||||
if (d->irq < 8)
|
||||
cached_21 |= 1 << d->irq;
|
||||
else
|
||||
cached_A1 |= 1 << (irq_nr-8);
|
||||
i8259_set_irq_mask(irq_nr);
|
||||
cached_A1 |= 1 << (d->irq-8);
|
||||
i8259_set_irq_mask(d->irq);
|
||||
raw_spin_unlock_irqrestore(&i8259_lock, flags);
|
||||
}
|
||||
|
||||
static void i8259_unmask_irq(unsigned int irq_nr)
|
||||
static void i8259_unmask_irq(struct irq_data *d)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
pr_debug("i8259_unmask_irq(%d)\n", irq_nr);
|
||||
pr_debug("i8259_unmask_irq(%d)\n", d->irq);
|
||||
|
||||
raw_spin_lock_irqsave(&i8259_lock, flags);
|
||||
if (irq_nr < 8)
|
||||
cached_21 &= ~(1 << irq_nr);
|
||||
if (d->irq < 8)
|
||||
cached_21 &= ~(1 << d->irq);
|
||||
else
|
||||
cached_A1 &= ~(1 << (irq_nr-8));
|
||||
i8259_set_irq_mask(irq_nr);
|
||||
cached_A1 &= ~(1 << (d->irq-8));
|
||||
i8259_set_irq_mask(d->irq);
|
||||
raw_spin_unlock_irqrestore(&i8259_lock, flags);
|
||||
}
|
||||
|
||||
static struct irq_chip i8259_pic = {
|
||||
.name = "i8259",
|
||||
.mask = i8259_mask_irq,
|
||||
.disable = i8259_mask_irq,
|
||||
.unmask = i8259_unmask_irq,
|
||||
.mask_ack = i8259_mask_and_ack_irq,
|
||||
.irq_mask = i8259_mask_irq,
|
||||
.irq_disable = i8259_mask_irq,
|
||||
.irq_unmask = i8259_unmask_irq,
|
||||
.irq_mask_ack = i8259_mask_and_ack_irq,
|
||||
};
|
||||
|
||||
static struct resource pic1_iores = {
|
||||
|
@ -188,7 +188,7 @@ static int i8259_host_map(struct irq_host *h, unsigned int virq,
|
|||
static void i8259_host_unmap(struct irq_host *h, unsigned int virq)
|
||||
{
|
||||
/* Make sure irq is masked in hardware */
|
||||
i8259_mask_irq(virq);
|
||||
i8259_mask_irq(irq_get_irq_data(virq));
|
||||
|
||||
/* remove chip and handler */
|
||||
set_irq_chip_and_handler(virq, NULL, NULL);
|
||||
|
|
|
@ -523,10 +523,10 @@ static inline struct ipic * ipic_from_irq(unsigned int virq)
|
|||
|
||||
#define ipic_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq)
|
||||
|
||||
static void ipic_unmask_irq(unsigned int virq)
|
||||
static void ipic_unmask_irq(struct irq_data *d)
|
||||
{
|
||||
struct ipic *ipic = ipic_from_irq(virq);
|
||||
unsigned int src = ipic_irq_to_hw(virq);
|
||||
struct ipic *ipic = ipic_from_irq(d->irq);
|
||||
unsigned int src = ipic_irq_to_hw(d->irq);
|
||||
unsigned long flags;
|
||||
u32 temp;
|
||||
|
||||
|
@ -539,10 +539,10 @@ static void ipic_unmask_irq(unsigned int virq)
|
|||
raw_spin_unlock_irqrestore(&ipic_lock, flags);
|
||||
}
|
||||
|
||||
static void ipic_mask_irq(unsigned int virq)
|
||||
static void ipic_mask_irq(struct irq_data *d)
|
||||
{
|
||||
struct ipic *ipic = ipic_from_irq(virq);
|
||||
unsigned int src = ipic_irq_to_hw(virq);
|
||||
struct ipic *ipic = ipic_from_irq(d->irq);
|
||||
unsigned int src = ipic_irq_to_hw(d->irq);
|
||||
unsigned long flags;
|
||||
u32 temp;
|
||||
|
||||
|
@ -559,10 +559,10 @@ static void ipic_mask_irq(unsigned int virq)
|
|||
raw_spin_unlock_irqrestore(&ipic_lock, flags);
|
||||
}
|
||||
|
||||
static void ipic_ack_irq(unsigned int virq)
|
||||
static void ipic_ack_irq(struct irq_data *d)
|
||||
{
|
||||
struct ipic *ipic = ipic_from_irq(virq);
|
||||
unsigned int src = ipic_irq_to_hw(virq);
|
||||
struct ipic *ipic = ipic_from_irq(d->irq);
|
||||
unsigned int src = ipic_irq_to_hw(d->irq);
|
||||
unsigned long flags;
|
||||
u32 temp;
|
||||
|
||||
|
@ -578,10 +578,10 @@ static void ipic_ack_irq(unsigned int virq)
|
|||
raw_spin_unlock_irqrestore(&ipic_lock, flags);
|
||||
}
|
||||
|
||||
static void ipic_mask_irq_and_ack(unsigned int virq)
|
||||
static void ipic_mask_irq_and_ack(struct irq_data *d)
|
||||
{
|
||||
struct ipic *ipic = ipic_from_irq(virq);
|
||||
unsigned int src = ipic_irq_to_hw(virq);
|
||||
struct ipic *ipic = ipic_from_irq(d->irq);
|
||||
unsigned int src = ipic_irq_to_hw(d->irq);
|
||||
unsigned long flags;
|
||||
u32 temp;
|
||||
|
||||
|
@ -601,11 +601,11 @@ static void ipic_mask_irq_and_ack(unsigned int virq)
|
|||
raw_spin_unlock_irqrestore(&ipic_lock, flags);
|
||||
}
|
||||
|
||||
static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type)
|
||||
static int ipic_set_irq_type(struct irq_data *d, unsigned int flow_type)
|
||||
{
|
||||
struct ipic *ipic = ipic_from_irq(virq);
|
||||
unsigned int src = ipic_irq_to_hw(virq);
|
||||
struct irq_desc *desc = irq_to_desc(virq);
|
||||
struct ipic *ipic = ipic_from_irq(d->irq);
|
||||
unsigned int src = ipic_irq_to_hw(d->irq);
|
||||
struct irq_desc *desc = irq_to_desc(d->irq);
|
||||
unsigned int vold, vnew, edibit;
|
||||
|
||||
if (flow_type == IRQ_TYPE_NONE)
|
||||
|
@ -630,10 +630,10 @@ static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type)
|
|||
if (flow_type & IRQ_TYPE_LEVEL_LOW) {
|
||||
desc->status |= IRQ_LEVEL;
|
||||
desc->handle_irq = handle_level_irq;
|
||||
desc->chip = &ipic_level_irq_chip;
|
||||
desc->irq_data.chip = &ipic_level_irq_chip;
|
||||
} else {
|
||||
desc->handle_irq = handle_edge_irq;
|
||||
desc->chip = &ipic_edge_irq_chip;
|
||||
desc->irq_data.chip = &ipic_edge_irq_chip;
|
||||
}
|
||||
|
||||
/* only EXT IRQ senses are programmable on ipic
|
||||
|
@ -661,19 +661,19 @@ static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type)
|
|||
/* level interrupts and edge interrupts have different ack operations */
|
||||
static struct irq_chip ipic_level_irq_chip = {
|
||||
.name = "IPIC",
|
||||
.unmask = ipic_unmask_irq,
|
||||
.mask = ipic_mask_irq,
|
||||
.mask_ack = ipic_mask_irq,
|
||||
.set_type = ipic_set_irq_type,
|
||||
.irq_unmask = ipic_unmask_irq,
|
||||
.irq_mask = ipic_mask_irq,
|
||||
.irq_mask_ack = ipic_mask_irq,
|
||||
.irq_set_type = ipic_set_irq_type,
|
||||
};
|
||||
|
||||
static struct irq_chip ipic_edge_irq_chip = {
|
||||
.name = "IPIC",
|
||||
.unmask = ipic_unmask_irq,
|
||||
.mask = ipic_mask_irq,
|
||||
.mask_ack = ipic_mask_irq_and_ack,
|
||||
.ack = ipic_ack_irq,
|
||||
.set_type = ipic_set_irq_type,
|
||||
.irq_unmask = ipic_unmask_irq,
|
||||
.irq_mask = ipic_mask_irq,
|
||||
.irq_mask_ack = ipic_mask_irq_and_ack,
|
||||
.irq_ack = ipic_ack_irq,
|
||||
.irq_set_type = ipic_set_irq_type,
|
||||
};
|
||||
|
||||
static int ipic_host_match(struct irq_host *h, struct device_node *node)
|
||||
|
|
|
@ -25,10 +25,10 @@ static sysconf8xx_t __iomem *siu_reg;
|
|||
|
||||
int cpm_get_irq(struct pt_regs *regs);
|
||||
|
||||
static void mpc8xx_unmask_irq(unsigned int virq)
|
||||
static void mpc8xx_unmask_irq(struct irq_data *d)
|
||||
{
|
||||
int bit, word;
|
||||
unsigned int irq_nr = (unsigned int)irq_map[virq].hwirq;
|
||||
unsigned int irq_nr = (unsigned int)irq_map[d->irq].hwirq;
|
||||
|
||||
bit = irq_nr & 0x1f;
|
||||
word = irq_nr >> 5;
|
||||
|
@ -37,10 +37,10 @@ static void mpc8xx_unmask_irq(unsigned int virq)
|
|||
out_be32(&siu_reg->sc_simask, ppc_cached_irq_mask[word]);
|
||||
}
|
||||
|
||||
static void mpc8xx_mask_irq(unsigned int virq)
|
||||
static void mpc8xx_mask_irq(struct irq_data *d)
|
||||
{
|
||||
int bit, word;
|
||||
unsigned int irq_nr = (unsigned int)irq_map[virq].hwirq;
|
||||
unsigned int irq_nr = (unsigned int)irq_map[d->irq].hwirq;
|
||||
|
||||
bit = irq_nr & 0x1f;
|
||||
word = irq_nr >> 5;
|
||||
|
@ -49,19 +49,19 @@ static void mpc8xx_mask_irq(unsigned int virq)
|
|||
out_be32(&siu_reg->sc_simask, ppc_cached_irq_mask[word]);
|
||||
}
|
||||
|
||||
static void mpc8xx_ack(unsigned int virq)
|
||||
static void mpc8xx_ack(struct irq_data *d)
|
||||
{
|
||||
int bit;
|
||||
unsigned int irq_nr = (unsigned int)irq_map[virq].hwirq;
|
||||
unsigned int irq_nr = (unsigned int)irq_map[d->irq].hwirq;
|
||||
|
||||
bit = irq_nr & 0x1f;
|
||||
out_be32(&siu_reg->sc_sipend, 1 << (31-bit));
|
||||
}
|
||||
|
||||
static void mpc8xx_end_irq(unsigned int virq)
|
||||
static void mpc8xx_end_irq(struct irq_data *d)
|
||||
{
|
||||
int bit, word;
|
||||
unsigned int irq_nr = (unsigned int)irq_map[virq].hwirq;
|
||||
unsigned int irq_nr = (unsigned int)irq_map[d->irq].hwirq;
|
||||
|
||||
bit = irq_nr & 0x1f;
|
||||
word = irq_nr >> 5;
|
||||
|
@ -70,9 +70,9 @@ static void mpc8xx_end_irq(unsigned int virq)
|
|||
out_be32(&siu_reg->sc_simask, ppc_cached_irq_mask[word]);
|
||||
}
|
||||
|
||||
static int mpc8xx_set_irq_type(unsigned int virq, unsigned int flow_type)
|
||||
static int mpc8xx_set_irq_type(struct irq_data *d, unsigned int flow_type)
|
||||
{
|
||||
struct irq_desc *desc = irq_to_desc(virq);
|
||||
struct irq_desc *desc = irq_to_desc(d->irq);
|
||||
|
||||
desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
|
||||
desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
|
||||
|
@ -80,7 +80,7 @@ static int mpc8xx_set_irq_type(unsigned int virq, unsigned int flow_type)
|
|||
desc->status |= IRQ_LEVEL;
|
||||
|
||||
if (flow_type & IRQ_TYPE_EDGE_FALLING) {
|
||||
irq_hw_number_t hw = (unsigned int)irq_map[virq].hwirq;
|
||||
irq_hw_number_t hw = (unsigned int)irq_map[d->irq].hwirq;
|
||||
unsigned int siel = in_be32(&siu_reg->sc_siel);
|
||||
|
||||
/* only external IRQ senses are programmable */
|
||||
|
@ -95,11 +95,11 @@ static int mpc8xx_set_irq_type(unsigned int virq, unsigned int flow_type)
|
|||
|
||||
static struct irq_chip mpc8xx_pic = {
|
||||
.name = "MPC8XX SIU",
|
||||
.unmask = mpc8xx_unmask_irq,
|
||||
.mask = mpc8xx_mask_irq,
|
||||
.ack = mpc8xx_ack,
|
||||
.eoi = mpc8xx_end_irq,
|
||||
.set_type = mpc8xx_set_irq_type,
|
||||
.irq_unmask = mpc8xx_unmask_irq,
|
||||
.irq_mask = mpc8xx_mask_irq,
|
||||
.irq_ack = mpc8xx_ack,
|
||||
.irq_eoi = mpc8xx_end_irq,
|
||||
.irq_set_type = mpc8xx_set_irq_type,
|
||||
};
|
||||
|
||||
unsigned int mpc8xx_get_irq(void)
|
||||
|
|
|
@ -155,43 +155,43 @@ static void mpc8xxx_gpio_irq_cascade(unsigned int irq, struct irq_desc *desc)
|
|||
32 - ffs(mask)));
|
||||
}
|
||||
|
||||
static void mpc8xxx_irq_unmask(unsigned int virq)
|
||||
static void mpc8xxx_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_chip_data(virq);
|
||||
struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
|
||||
struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
|
||||
|
||||
setbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(virq_to_hw(virq)));
|
||||
setbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(virq_to_hw(d->irq)));
|
||||
|
||||
spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
|
||||
}
|
||||
|
||||
static void mpc8xxx_irq_mask(unsigned int virq)
|
||||
static void mpc8xxx_irq_mask(struct irq_data *d)
|
||||
{
|
||||
struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_chip_data(virq);
|
||||
struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
|
||||
struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
|
||||
|
||||
clrbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(virq_to_hw(virq)));
|
||||
clrbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(virq_to_hw(d->irq)));
|
||||
|
||||
spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
|
||||
}
|
||||
|
||||
static void mpc8xxx_irq_ack(unsigned int virq)
|
||||
static void mpc8xxx_irq_ack(struct irq_data *d)
|
||||
{
|
||||
struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_chip_data(virq);
|
||||
struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
|
||||
struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
|
||||
|
||||
out_be32(mm->regs + GPIO_IER, mpc8xxx_gpio2mask(virq_to_hw(virq)));
|
||||
out_be32(mm->regs + GPIO_IER, mpc8xxx_gpio2mask(virq_to_hw(d->irq)));
|
||||
}
|
||||
|
||||
static int mpc8xxx_irq_set_type(unsigned int virq, unsigned int flow_type)
|
||||
static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
|
||||
{
|
||||
struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_chip_data(virq);
|
||||
struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
|
||||
struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
|
||||
unsigned long flags;
|
||||
|
||||
|
@ -199,14 +199,14 @@ static int mpc8xxx_irq_set_type(unsigned int virq, unsigned int flow_type)
|
|||
case IRQ_TYPE_EDGE_FALLING:
|
||||
spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
|
||||
setbits32(mm->regs + GPIO_ICR,
|
||||
mpc8xxx_gpio2mask(virq_to_hw(virq)));
|
||||
mpc8xxx_gpio2mask(virq_to_hw(d->irq)));
|
||||
spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
|
||||
break;
|
||||
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
|
||||
clrbits32(mm->regs + GPIO_ICR,
|
||||
mpc8xxx_gpio2mask(virq_to_hw(virq)));
|
||||
mpc8xxx_gpio2mask(virq_to_hw(d->irq)));
|
||||
spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
|
||||
break;
|
||||
|
||||
|
@ -217,11 +217,11 @@ static int mpc8xxx_irq_set_type(unsigned int virq, unsigned int flow_type)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mpc512x_irq_set_type(unsigned int virq, unsigned int flow_type)
|
||||
static int mpc512x_irq_set_type(struct irq_data *d, unsigned int flow_type)
|
||||
{
|
||||
struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_chip_data(virq);
|
||||
struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
|
||||
struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
|
||||
unsigned long gpio = virq_to_hw(virq);
|
||||
unsigned long gpio = virq_to_hw(d->irq);
|
||||
void __iomem *reg;
|
||||
unsigned int shift;
|
||||
unsigned long flags;
|
||||
|
@ -264,10 +264,10 @@ static int mpc512x_irq_set_type(unsigned int virq, unsigned int flow_type)
|
|||
|
||||
static struct irq_chip mpc8xxx_irq_chip = {
|
||||
.name = "mpc8xxx-gpio",
|
||||
.unmask = mpc8xxx_irq_unmask,
|
||||
.mask = mpc8xxx_irq_mask,
|
||||
.ack = mpc8xxx_irq_ack,
|
||||
.set_type = mpc8xxx_irq_set_type,
|
||||
.irq_unmask = mpc8xxx_irq_unmask,
|
||||
.irq_mask = mpc8xxx_irq_mask,
|
||||
.irq_ack = mpc8xxx_irq_ack,
|
||||
.irq_set_type = mpc8xxx_irq_set_type,
|
||||
};
|
||||
|
||||
static int mpc8xxx_gpio_irq_map(struct irq_host *h, unsigned int virq,
|
||||
|
@ -276,7 +276,7 @@ static int mpc8xxx_gpio_irq_map(struct irq_host *h, unsigned int virq,
|
|||
struct mpc8xxx_gpio_chip *mpc8xxx_gc = h->host_data;
|
||||
|
||||
if (mpc8xxx_gc->of_dev_id_data)
|
||||
mpc8xxx_irq_chip.set_type = mpc8xxx_gc->of_dev_id_data;
|
||||
mpc8xxx_irq_chip.irq_set_type = mpc8xxx_gc->of_dev_id_data;
|
||||
|
||||
set_irq_chip_data(virq, h->host_data);
|
||||
set_irq_chip_and_handler(virq, &mpc8xxx_irq_chip, handle_level_irq);
|
||||
|
@ -310,6 +310,7 @@ static struct of_device_id mpc8xxx_gpio_ids[] __initdata = {
|
|||
{ .compatible = "fsl,mpc8572-gpio", },
|
||||
{ .compatible = "fsl,mpc8610-gpio", },
|
||||
{ .compatible = "fsl,mpc5121-gpio", .data = mpc512x_irq_set_type, },
|
||||
{ .compatible = "fsl,qoriq-gpio", },
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -389,9 +390,6 @@ static int __init mpc8xxx_add_gpiochips(void)
|
|||
for_each_matching_node(np, mpc8xxx_gpio_ids)
|
||||
mpc8xxx_add_controller(np);
|
||||
|
||||
for_each_compatible_node(np, NULL, "fsl,qoriq-gpio")
|
||||
mpc8xxx_add_controller(np);
|
||||
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(mpc8xxx_add_gpiochips);
|
||||
|
|
|
@ -611,7 +611,7 @@ static struct mpic *mpic_find(unsigned int irq)
|
|||
if (irq < NUM_ISA_INTERRUPTS)
|
||||
return NULL;
|
||||
|
||||
return irq_to_desc(irq)->chip_data;
|
||||
return get_irq_chip_data(irq);
|
||||
}
|
||||
|
||||
/* Determine if the linux irq is an IPI */
|
||||
|
@ -636,16 +636,22 @@ static inline u32 mpic_physmask(u32 cpumask)
|
|||
|
||||
#ifdef CONFIG_SMP
|
||||
/* Get the mpic structure from the IPI number */
|
||||
static inline struct mpic * mpic_from_ipi(unsigned int ipi)
|
||||
static inline struct mpic * mpic_from_ipi(struct irq_data *d)
|
||||
{
|
||||
return irq_to_desc(ipi)->chip_data;
|
||||
return irq_data_get_irq_chip_data(d);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get the mpic structure from the irq number */
|
||||
static inline struct mpic * mpic_from_irq(unsigned int irq)
|
||||
{
|
||||
return irq_to_desc(irq)->chip_data;
|
||||
return get_irq_chip_data(irq);
|
||||
}
|
||||
|
||||
/* Get the mpic structure from the irq data */
|
||||
static inline struct mpic * mpic_from_irq_data(struct irq_data *d)
|
||||
{
|
||||
return irq_data_get_irq_chip_data(d);
|
||||
}
|
||||
|
||||
/* Send an EOI */
|
||||
|
@ -660,13 +666,13 @@ static inline void mpic_eoi(struct mpic *mpic)
|
|||
*/
|
||||
|
||||
|
||||
void mpic_unmask_irq(unsigned int irq)
|
||||
void mpic_unmask_irq(struct irq_data *d)
|
||||
{
|
||||
unsigned int loops = 100000;
|
||||
struct mpic *mpic = mpic_from_irq(irq);
|
||||
unsigned int src = mpic_irq_to_hw(irq);
|
||||
struct mpic *mpic = mpic_from_irq_data(d);
|
||||
unsigned int src = mpic_irq_to_hw(d->irq);
|
||||
|
||||
DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src);
|
||||
DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, d->irq, src);
|
||||
|
||||
mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
|
||||
mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) &
|
||||
|
@ -681,13 +687,13 @@ void mpic_unmask_irq(unsigned int irq)
|
|||
} while(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK);
|
||||
}
|
||||
|
||||
void mpic_mask_irq(unsigned int irq)
|
||||
void mpic_mask_irq(struct irq_data *d)
|
||||
{
|
||||
unsigned int loops = 100000;
|
||||
struct mpic *mpic = mpic_from_irq(irq);
|
||||
unsigned int src = mpic_irq_to_hw(irq);
|
||||
struct mpic *mpic = mpic_from_irq_data(d);
|
||||
unsigned int src = mpic_irq_to_hw(d->irq);
|
||||
|
||||
DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src);
|
||||
DBG("%s: disable_irq: %d (src %d)\n", mpic->name, d->irq, src);
|
||||
|
||||
mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
|
||||
mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) |
|
||||
|
@ -703,12 +709,12 @@ void mpic_mask_irq(unsigned int irq)
|
|||
} while(!(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK));
|
||||
}
|
||||
|
||||
void mpic_end_irq(unsigned int irq)
|
||||
void mpic_end_irq(struct irq_data *d)
|
||||
{
|
||||
struct mpic *mpic = mpic_from_irq(irq);
|
||||
struct mpic *mpic = mpic_from_irq_data(d);
|
||||
|
||||
#ifdef DEBUG_IRQ
|
||||
DBG("%s: end_irq: %d\n", mpic->name, irq);
|
||||
DBG("%s: end_irq: %d\n", mpic->name, d->irq);
|
||||
#endif
|
||||
/* We always EOI on end_irq() even for edge interrupts since that
|
||||
* should only lower the priority, the MPIC should have properly
|
||||
|
@ -720,51 +726,51 @@ void mpic_end_irq(unsigned int irq)
|
|||
|
||||
#ifdef CONFIG_MPIC_U3_HT_IRQS
|
||||
|
||||
static void mpic_unmask_ht_irq(unsigned int irq)
|
||||
static void mpic_unmask_ht_irq(struct irq_data *d)
|
||||
{
|
||||
struct mpic *mpic = mpic_from_irq(irq);
|
||||
unsigned int src = mpic_irq_to_hw(irq);
|
||||
struct mpic *mpic = mpic_from_irq_data(d);
|
||||
unsigned int src = mpic_irq_to_hw(d->irq);
|
||||
|
||||
mpic_unmask_irq(irq);
|
||||
mpic_unmask_irq(d);
|
||||
|
||||
if (irq_to_desc(irq)->status & IRQ_LEVEL)
|
||||
if (irq_to_desc(d->irq)->status & IRQ_LEVEL)
|
||||
mpic_ht_end_irq(mpic, src);
|
||||
}
|
||||
|
||||
static unsigned int mpic_startup_ht_irq(unsigned int irq)
|
||||
static unsigned int mpic_startup_ht_irq(struct irq_data *d)
|
||||
{
|
||||
struct mpic *mpic = mpic_from_irq(irq);
|
||||
unsigned int src = mpic_irq_to_hw(irq);
|
||||
struct mpic *mpic = mpic_from_irq_data(d);
|
||||
unsigned int src = mpic_irq_to_hw(d->irq);
|
||||
|
||||
mpic_unmask_irq(irq);
|
||||
mpic_startup_ht_interrupt(mpic, src, irq_to_desc(irq)->status);
|
||||
mpic_unmask_irq(d);
|
||||
mpic_startup_ht_interrupt(mpic, src, irq_to_desc(d->irq)->status);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mpic_shutdown_ht_irq(unsigned int irq)
|
||||
static void mpic_shutdown_ht_irq(struct irq_data *d)
|
||||
{
|
||||
struct mpic *mpic = mpic_from_irq(irq);
|
||||
unsigned int src = mpic_irq_to_hw(irq);
|
||||
struct mpic *mpic = mpic_from_irq_data(d);
|
||||
unsigned int src = mpic_irq_to_hw(d->irq);
|
||||
|
||||
mpic_shutdown_ht_interrupt(mpic, src, irq_to_desc(irq)->status);
|
||||
mpic_mask_irq(irq);
|
||||
mpic_shutdown_ht_interrupt(mpic, src, irq_to_desc(d->irq)->status);
|
||||
mpic_mask_irq(d);
|
||||
}
|
||||
|
||||
static void mpic_end_ht_irq(unsigned int irq)
|
||||
static void mpic_end_ht_irq(struct irq_data *d)
|
||||
{
|
||||
struct mpic *mpic = mpic_from_irq(irq);
|
||||
unsigned int src = mpic_irq_to_hw(irq);
|
||||
struct mpic *mpic = mpic_from_irq_data(d);
|
||||
unsigned int src = mpic_irq_to_hw(d->irq);
|
||||
|
||||
#ifdef DEBUG_IRQ
|
||||
DBG("%s: end_irq: %d\n", mpic->name, irq);
|
||||
DBG("%s: end_irq: %d\n", mpic->name, d->irq);
|
||||
#endif
|
||||
/* We always EOI on end_irq() even for edge interrupts since that
|
||||
* should only lower the priority, the MPIC should have properly
|
||||
* latched another edge interrupt coming in anyway
|
||||
*/
|
||||
|
||||
if (irq_to_desc(irq)->status & IRQ_LEVEL)
|
||||
if (irq_to_desc(d->irq)->status & IRQ_LEVEL)
|
||||
mpic_ht_end_irq(mpic, src);
|
||||
mpic_eoi(mpic);
|
||||
}
|
||||
|
@ -772,23 +778,23 @@ static void mpic_end_ht_irq(unsigned int irq)
|
|||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
static void mpic_unmask_ipi(unsigned int irq)
|
||||
static void mpic_unmask_ipi(struct irq_data *d)
|
||||
{
|
||||
struct mpic *mpic = mpic_from_ipi(irq);
|
||||
unsigned int src = mpic_irq_to_hw(irq) - mpic->ipi_vecs[0];
|
||||
struct mpic *mpic = mpic_from_ipi(d);
|
||||
unsigned int src = mpic_irq_to_hw(d->irq) - mpic->ipi_vecs[0];
|
||||
|
||||
DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, irq, src);
|
||||
DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, d->irq, src);
|
||||
mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK);
|
||||
}
|
||||
|
||||
static void mpic_mask_ipi(unsigned int irq)
|
||||
static void mpic_mask_ipi(struct irq_data *d)
|
||||
{
|
||||
/* NEVER disable an IPI... that's just plain wrong! */
|
||||
}
|
||||
|
||||
static void mpic_end_ipi(unsigned int irq)
|
||||
static void mpic_end_ipi(struct irq_data *d)
|
||||
{
|
||||
struct mpic *mpic = mpic_from_ipi(irq);
|
||||
struct mpic *mpic = mpic_from_ipi(d);
|
||||
|
||||
/*
|
||||
* IPIs are marked IRQ_PER_CPU. This has the side effect of
|
||||
|
@ -802,10 +808,11 @@ static void mpic_end_ipi(unsigned int irq)
|
|||
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
int mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
|
||||
int mpic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
|
||||
bool force)
|
||||
{
|
||||
struct mpic *mpic = mpic_from_irq(irq);
|
||||
unsigned int src = mpic_irq_to_hw(irq);
|
||||
struct mpic *mpic = mpic_from_irq_data(d);
|
||||
unsigned int src = mpic_irq_to_hw(d->irq);
|
||||
|
||||
if (mpic->flags & MPIC_SINGLE_DEST_CPU) {
|
||||
int cpuid = irq_choose_cpu(cpumask);
|
||||
|
@ -848,15 +855,15 @@ static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type)
|
|||
}
|
||||
}
|
||||
|
||||
int mpic_set_irq_type(unsigned int virq, unsigned int flow_type)
|
||||
int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type)
|
||||
{
|
||||
struct mpic *mpic = mpic_from_irq(virq);
|
||||
unsigned int src = mpic_irq_to_hw(virq);
|
||||
struct irq_desc *desc = irq_to_desc(virq);
|
||||
struct mpic *mpic = mpic_from_irq_data(d);
|
||||
unsigned int src = mpic_irq_to_hw(d->irq);
|
||||
struct irq_desc *desc = irq_to_desc(d->irq);
|
||||
unsigned int vecpri, vold, vnew;
|
||||
|
||||
DBG("mpic: set_irq_type(mpic:@%p,virq:%d,src:0x%x,type:0x%x)\n",
|
||||
mpic, virq, src, flow_type);
|
||||
mpic, d->irq, src, flow_type);
|
||||
|
||||
if (src >= mpic->irq_count)
|
||||
return -EINVAL;
|
||||
|
@ -907,28 +914,28 @@ void mpic_set_vector(unsigned int virq, unsigned int vector)
|
|||
}
|
||||
|
||||
static struct irq_chip mpic_irq_chip = {
|
||||
.mask = mpic_mask_irq,
|
||||
.unmask = mpic_unmask_irq,
|
||||
.eoi = mpic_end_irq,
|
||||
.set_type = mpic_set_irq_type,
|
||||
.irq_mask = mpic_mask_irq,
|
||||
.irq_unmask = mpic_unmask_irq,
|
||||
.irq_eoi = mpic_end_irq,
|
||||
.irq_set_type = mpic_set_irq_type,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static struct irq_chip mpic_ipi_chip = {
|
||||
.mask = mpic_mask_ipi,
|
||||
.unmask = mpic_unmask_ipi,
|
||||
.eoi = mpic_end_ipi,
|
||||
.irq_mask = mpic_mask_ipi,
|
||||
.irq_unmask = mpic_unmask_ipi,
|
||||
.irq_eoi = mpic_end_ipi,
|
||||
};
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
#ifdef CONFIG_MPIC_U3_HT_IRQS
|
||||
static struct irq_chip mpic_irq_ht_chip = {
|
||||
.startup = mpic_startup_ht_irq,
|
||||
.shutdown = mpic_shutdown_ht_irq,
|
||||
.mask = mpic_mask_irq,
|
||||
.unmask = mpic_unmask_ht_irq,
|
||||
.eoi = mpic_end_ht_irq,
|
||||
.set_type = mpic_set_irq_type,
|
||||
.irq_startup = mpic_startup_ht_irq,
|
||||
.irq_shutdown = mpic_shutdown_ht_irq,
|
||||
.irq_mask = mpic_mask_irq,
|
||||
.irq_unmask = mpic_unmask_ht_irq,
|
||||
.irq_eoi = mpic_end_ht_irq,
|
||||
.irq_set_type = mpic_set_irq_type,
|
||||
};
|
||||
#endif /* CONFIG_MPIC_U3_HT_IRQS */
|
||||
|
||||
|
@ -1060,12 +1067,12 @@ struct mpic * __init mpic_alloc(struct device_node *node,
|
|||
mpic->hc_irq = mpic_irq_chip;
|
||||
mpic->hc_irq.name = name;
|
||||
if (flags & MPIC_PRIMARY)
|
||||
mpic->hc_irq.set_affinity = mpic_set_affinity;
|
||||
mpic->hc_irq.irq_set_affinity = mpic_set_affinity;
|
||||
#ifdef CONFIG_MPIC_U3_HT_IRQS
|
||||
mpic->hc_ht_irq = mpic_irq_ht_chip;
|
||||
mpic->hc_ht_irq.name = name;
|
||||
if (flags & MPIC_PRIMARY)
|
||||
mpic->hc_ht_irq.set_affinity = mpic_set_affinity;
|
||||
mpic->hc_ht_irq.irq_set_affinity = mpic_set_affinity;
|
||||
#endif /* CONFIG_MPIC_U3_HT_IRQS */
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
|
|
@ -34,9 +34,10 @@ static inline int mpic_pasemi_msi_init(struct mpic *mpic)
|
|||
}
|
||||
#endif
|
||||
|
||||
extern int mpic_set_irq_type(unsigned int virq, unsigned int flow_type);
|
||||
extern int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type);
|
||||
extern void mpic_set_vector(unsigned int virq, unsigned int vector);
|
||||
extern int mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask);
|
||||
extern int mpic_set_affinity(struct irq_data *d,
|
||||
const struct cpumask *cpumask, bool force);
|
||||
extern void mpic_reset_core(int cpu);
|
||||
|
||||
#endif /* _POWERPC_SYSDEV_MPIC_H */
|
||||
|
|
|
@ -43,24 +43,24 @@ static void mpic_pasemi_msi_mask_irq(struct irq_data *data)
|
|||
{
|
||||
pr_debug("mpic_pasemi_msi_mask_irq %d\n", data->irq);
|
||||
mask_msi_irq(data);
|
||||
mpic_mask_irq(data->irq);
|
||||
mpic_mask_irq(data);
|
||||
}
|
||||
|
||||
static void mpic_pasemi_msi_unmask_irq(struct irq_data *data)
|
||||
{
|
||||
pr_debug("mpic_pasemi_msi_unmask_irq %d\n", data->irq);
|
||||
mpic_unmask_irq(data->irq);
|
||||
mpic_unmask_irq(data);
|
||||
unmask_msi_irq(data);
|
||||
}
|
||||
|
||||
static struct irq_chip mpic_pasemi_msi_chip = {
|
||||
.irq_shutdown = mpic_pasemi_msi_mask_irq,
|
||||
.irq_mask = mpic_pasemi_msi_mask_irq,
|
||||
.irq_unmask = mpic_pasemi_msi_unmask_irq,
|
||||
.eoi = mpic_end_irq,
|
||||
.set_type = mpic_set_irq_type,
|
||||
.set_affinity = mpic_set_affinity,
|
||||
.name = "PASEMI-MSI",
|
||||
.irq_shutdown = mpic_pasemi_msi_mask_irq,
|
||||
.irq_mask = mpic_pasemi_msi_mask_irq,
|
||||
.irq_unmask = mpic_pasemi_msi_unmask_irq,
|
||||
.irq_eoi = mpic_end_irq,
|
||||
.irq_set_type = mpic_set_irq_type,
|
||||
.irq_set_affinity = mpic_set_affinity,
|
||||
.name = "PASEMI-MSI",
|
||||
};
|
||||
|
||||
static int pasemi_msi_check_device(struct pci_dev *pdev, int nvec, int type)
|
||||
|
|
|
@ -26,23 +26,23 @@ static struct mpic *msi_mpic;
|
|||
static void mpic_u3msi_mask_irq(struct irq_data *data)
|
||||
{
|
||||
mask_msi_irq(data);
|
||||
mpic_mask_irq(data->irq);
|
||||
mpic_mask_irq(data);
|
||||
}
|
||||
|
||||
static void mpic_u3msi_unmask_irq(struct irq_data *data)
|
||||
{
|
||||
mpic_unmask_irq(data->irq);
|
||||
mpic_unmask_irq(data);
|
||||
unmask_msi_irq(data);
|
||||
}
|
||||
|
||||
static struct irq_chip mpic_u3msi_chip = {
|
||||
.irq_shutdown = mpic_u3msi_mask_irq,
|
||||
.irq_mask = mpic_u3msi_mask_irq,
|
||||
.irq_unmask = mpic_u3msi_unmask_irq,
|
||||
.eoi = mpic_end_irq,
|
||||
.set_type = mpic_set_irq_type,
|
||||
.set_affinity = mpic_set_affinity,
|
||||
.name = "MPIC-U3MSI",
|
||||
.irq_shutdown = mpic_u3msi_mask_irq,
|
||||
.irq_mask = mpic_u3msi_mask_irq,
|
||||
.irq_unmask = mpic_u3msi_unmask_irq,
|
||||
.irq_eoi = mpic_end_irq,
|
||||
.irq_set_type = mpic_set_irq_type,
|
||||
.irq_set_affinity = mpic_set_affinity,
|
||||
.name = "MPIC-U3MSI",
|
||||
};
|
||||
|
||||
static u64 read_ht_magic_addr(struct pci_dev *pdev, unsigned int pos)
|
||||
|
|
|
@ -346,7 +346,7 @@ static int __init mv64x60_i2c_device_setup(struct device_node *np, int id)
|
|||
if (prop)
|
||||
pdata.freq_m = *prop;
|
||||
|
||||
pdata.freq_m = 3; /* default */
|
||||
pdata.freq_n = 3; /* default */
|
||||
prop = of_get_property(np, "freq_n", NULL);
|
||||
if (prop)
|
||||
pdata.freq_n = *prop;
|
||||
|
|
|
@ -76,9 +76,9 @@ static struct irq_host *mv64x60_irq_host;
|
|||
* mv64x60_chip_low functions
|
||||
*/
|
||||
|
||||
static void mv64x60_mask_low(unsigned int virq)
|
||||
static void mv64x60_mask_low(struct irq_data *d)
|
||||
{
|
||||
int level2 = irq_map[virq].hwirq & MV64x60_LEVEL2_MASK;
|
||||
int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&mv64x60_lock, flags);
|
||||
|
@ -89,9 +89,9 @@ static void mv64x60_mask_low(unsigned int virq)
|
|||
(void)in_le32(mv64x60_irq_reg_base + MV64X60_IC_CPU0_INTR_MASK_LO);
|
||||
}
|
||||
|
||||
static void mv64x60_unmask_low(unsigned int virq)
|
||||
static void mv64x60_unmask_low(struct irq_data *d)
|
||||
{
|
||||
int level2 = irq_map[virq].hwirq & MV64x60_LEVEL2_MASK;
|
||||
int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&mv64x60_lock, flags);
|
||||
|
@ -104,18 +104,18 @@ static void mv64x60_unmask_low(unsigned int virq)
|
|||
|
||||
static struct irq_chip mv64x60_chip_low = {
|
||||
.name = "mv64x60_low",
|
||||
.mask = mv64x60_mask_low,
|
||||
.mask_ack = mv64x60_mask_low,
|
||||
.unmask = mv64x60_unmask_low,
|
||||
.irq_mask = mv64x60_mask_low,
|
||||
.irq_mask_ack = mv64x60_mask_low,
|
||||
.irq_unmask = mv64x60_unmask_low,
|
||||
};
|
||||
|
||||
/*
|
||||
* mv64x60_chip_high functions
|
||||
*/
|
||||
|
||||
static void mv64x60_mask_high(unsigned int virq)
|
||||
static void mv64x60_mask_high(struct irq_data *d)
|
||||
{
|
||||
int level2 = irq_map[virq].hwirq & MV64x60_LEVEL2_MASK;
|
||||
int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&mv64x60_lock, flags);
|
||||
|
@ -126,9 +126,9 @@ static void mv64x60_mask_high(unsigned int virq)
|
|||
(void)in_le32(mv64x60_irq_reg_base + MV64X60_IC_CPU0_INTR_MASK_HI);
|
||||
}
|
||||
|
||||
static void mv64x60_unmask_high(unsigned int virq)
|
||||
static void mv64x60_unmask_high(struct irq_data *d)
|
||||
{
|
||||
int level2 = irq_map[virq].hwirq & MV64x60_LEVEL2_MASK;
|
||||
int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&mv64x60_lock, flags);
|
||||
|
@ -141,18 +141,18 @@ static void mv64x60_unmask_high(unsigned int virq)
|
|||
|
||||
static struct irq_chip mv64x60_chip_high = {
|
||||
.name = "mv64x60_high",
|
||||
.mask = mv64x60_mask_high,
|
||||
.mask_ack = mv64x60_mask_high,
|
||||
.unmask = mv64x60_unmask_high,
|
||||
.irq_mask = mv64x60_mask_high,
|
||||
.irq_mask_ack = mv64x60_mask_high,
|
||||
.irq_unmask = mv64x60_unmask_high,
|
||||
};
|
||||
|
||||
/*
|
||||
* mv64x60_chip_gpp functions
|
||||
*/
|
||||
|
||||
static void mv64x60_mask_gpp(unsigned int virq)
|
||||
static void mv64x60_mask_gpp(struct irq_data *d)
|
||||
{
|
||||
int level2 = irq_map[virq].hwirq & MV64x60_LEVEL2_MASK;
|
||||
int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&mv64x60_lock, flags);
|
||||
|
@ -163,9 +163,9 @@ static void mv64x60_mask_gpp(unsigned int virq)
|
|||
(void)in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_INTR_MASK);
|
||||
}
|
||||
|
||||
static void mv64x60_mask_ack_gpp(unsigned int virq)
|
||||
static void mv64x60_mask_ack_gpp(struct irq_data *d)
|
||||
{
|
||||
int level2 = irq_map[virq].hwirq & MV64x60_LEVEL2_MASK;
|
||||
int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&mv64x60_lock, flags);
|
||||
|
@ -178,9 +178,9 @@ static void mv64x60_mask_ack_gpp(unsigned int virq)
|
|||
(void)in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_INTR_CAUSE);
|
||||
}
|
||||
|
||||
static void mv64x60_unmask_gpp(unsigned int virq)
|
||||
static void mv64x60_unmask_gpp(struct irq_data *d)
|
||||
{
|
||||
int level2 = irq_map[virq].hwirq & MV64x60_LEVEL2_MASK;
|
||||
int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&mv64x60_lock, flags);
|
||||
|
@ -193,9 +193,9 @@ static void mv64x60_unmask_gpp(unsigned int virq)
|
|||
|
||||
static struct irq_chip mv64x60_chip_gpp = {
|
||||
.name = "mv64x60_gpp",
|
||||
.mask = mv64x60_mask_gpp,
|
||||
.mask_ack = mv64x60_mask_ack_gpp,
|
||||
.unmask = mv64x60_unmask_gpp,
|
||||
.irq_mask = mv64x60_mask_gpp,
|
||||
.irq_mask_ack = mv64x60_mask_ack_gpp,
|
||||
.irq_unmask = mv64x60_unmask_gpp,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -189,15 +189,20 @@ static inline void qe_ic_write(volatile __be32 __iomem * base, unsigned int reg
|
|||
|
||||
static inline struct qe_ic *qe_ic_from_irq(unsigned int virq)
|
||||
{
|
||||
return irq_to_desc(virq)->chip_data;
|
||||
return get_irq_chip_data(virq);
|
||||
}
|
||||
|
||||
static inline struct qe_ic *qe_ic_from_irq_data(struct irq_data *d)
|
||||
{
|
||||
return irq_data_get_irq_chip_data(d);
|
||||
}
|
||||
|
||||
#define virq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq)
|
||||
|
||||
static void qe_ic_unmask_irq(unsigned int virq)
|
||||
static void qe_ic_unmask_irq(struct irq_data *d)
|
||||
{
|
||||
struct qe_ic *qe_ic = qe_ic_from_irq(virq);
|
||||
unsigned int src = virq_to_hw(virq);
|
||||
struct qe_ic *qe_ic = qe_ic_from_irq_data(d);
|
||||
unsigned int src = virq_to_hw(d->irq);
|
||||
unsigned long flags;
|
||||
u32 temp;
|
||||
|
||||
|
@ -210,10 +215,10 @@ static void qe_ic_unmask_irq(unsigned int virq)
|
|||
raw_spin_unlock_irqrestore(&qe_ic_lock, flags);
|
||||
}
|
||||
|
||||
static void qe_ic_mask_irq(unsigned int virq)
|
||||
static void qe_ic_mask_irq(struct irq_data *d)
|
||||
{
|
||||
struct qe_ic *qe_ic = qe_ic_from_irq(virq);
|
||||
unsigned int src = virq_to_hw(virq);
|
||||
struct qe_ic *qe_ic = qe_ic_from_irq_data(d);
|
||||
unsigned int src = virq_to_hw(d->irq);
|
||||
unsigned long flags;
|
||||
u32 temp;
|
||||
|
||||
|
@ -238,9 +243,9 @@ static void qe_ic_mask_irq(unsigned int virq)
|
|||
|
||||
static struct irq_chip qe_ic_irq_chip = {
|
||||
.name = "QEIC",
|
||||
.unmask = qe_ic_unmask_irq,
|
||||
.mask = qe_ic_mask_irq,
|
||||
.mask_ack = qe_ic_mask_irq,
|
||||
.irq_unmask = qe_ic_unmask_irq,
|
||||
.irq_mask = qe_ic_mask_irq,
|
||||
.irq_mask_ack = qe_ic_mask_irq,
|
||||
};
|
||||
|
||||
static int qe_ic_host_match(struct irq_host *h, struct device_node *node)
|
||||
|
|
|
@ -343,24 +343,9 @@ static inline unsigned int get_pci_source(void)
|
|||
* Linux descriptor level callbacks
|
||||
*/
|
||||
|
||||
static void tsi108_pci_irq_enable(u_int irq)
|
||||
static void tsi108_pci_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
tsi108_pci_int_unmask(irq);
|
||||
}
|
||||
|
||||
static void tsi108_pci_irq_disable(u_int irq)
|
||||
{
|
||||
tsi108_pci_int_mask(irq);
|
||||
}
|
||||
|
||||
static void tsi108_pci_irq_ack(u_int irq)
|
||||
{
|
||||
tsi108_pci_int_mask(irq);
|
||||
}
|
||||
|
||||
static void tsi108_pci_irq_end(u_int irq)
|
||||
{
|
||||
tsi108_pci_int_unmask(irq);
|
||||
tsi108_pci_int_unmask(d->irq);
|
||||
|
||||
/* Enable interrupts from PCI block */
|
||||
tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE,
|
||||
|
@ -370,16 +355,25 @@ static void tsi108_pci_irq_end(u_int irq)
|
|||
mb();
|
||||
}
|
||||
|
||||
static void tsi108_pci_irq_mask(struct irq_data *d)
|
||||
{
|
||||
tsi108_pci_int_mask(d->irq);
|
||||
}
|
||||
|
||||
static void tsi108_pci_irq_ack(struct irq_data *d)
|
||||
{
|
||||
tsi108_pci_int_mask(d->irq);
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupt controller descriptor for cascaded PCI interrupt controller.
|
||||
*/
|
||||
|
||||
static struct irq_chip tsi108_pci_irq = {
|
||||
.name = "tsi108_PCI_int",
|
||||
.mask = tsi108_pci_irq_disable,
|
||||
.ack = tsi108_pci_irq_ack,
|
||||
.end = tsi108_pci_irq_end,
|
||||
.unmask = tsi108_pci_irq_enable,
|
||||
.irq_mask = tsi108_pci_irq_mask,
|
||||
.irq_ack = tsi108_pci_irq_ack,
|
||||
.irq_unmask = tsi108_pci_irq_unmask,
|
||||
};
|
||||
|
||||
static int pci_irq_host_xlate(struct irq_host *h, struct device_node *ct,
|
||||
|
@ -437,8 +431,11 @@ void __init tsi108_pci_int_init(struct device_node *node)
|
|||
|
||||
void tsi108_irq_cascade(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = get_irq_desc_chip(desc);
|
||||
unsigned int cascade_irq = get_pci_source();
|
||||
|
||||
if (cascade_irq != NO_IRQ)
|
||||
generic_handle_irq(cascade_irq);
|
||||
desc->chip->eoi(irq);
|
||||
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
}
|
||||
|
|
|
@ -55,11 +55,11 @@ struct uic {
|
|||
struct irq_host *irqhost;
|
||||
};
|
||||
|
||||
static void uic_unmask_irq(unsigned int virq)
|
||||
static void uic_unmask_irq(struct irq_data *d)
|
||||
{
|
||||
struct irq_desc *desc = irq_to_desc(virq);
|
||||
struct uic *uic = get_irq_chip_data(virq);
|
||||
unsigned int src = uic_irq_to_hw(virq);
|
||||
struct irq_desc *desc = irq_to_desc(d->irq);
|
||||
struct uic *uic = irq_data_get_irq_chip_data(d);
|
||||
unsigned int src = uic_irq_to_hw(d->irq);
|
||||
unsigned long flags;
|
||||
u32 er, sr;
|
||||
|
||||
|
@ -74,10 +74,10 @@ static void uic_unmask_irq(unsigned int virq)
|
|||
spin_unlock_irqrestore(&uic->lock, flags);
|
||||
}
|
||||
|
||||
static void uic_mask_irq(unsigned int virq)
|
||||
static void uic_mask_irq(struct irq_data *d)
|
||||
{
|
||||
struct uic *uic = get_irq_chip_data(virq);
|
||||
unsigned int src = uic_irq_to_hw(virq);
|
||||
struct uic *uic = irq_data_get_irq_chip_data(d);
|
||||
unsigned int src = uic_irq_to_hw(d->irq);
|
||||
unsigned long flags;
|
||||
u32 er;
|
||||
|
||||
|
@ -88,10 +88,10 @@ static void uic_mask_irq(unsigned int virq)
|
|||
spin_unlock_irqrestore(&uic->lock, flags);
|
||||
}
|
||||
|
||||
static void uic_ack_irq(unsigned int virq)
|
||||
static void uic_ack_irq(struct irq_data *d)
|
||||
{
|
||||
struct uic *uic = get_irq_chip_data(virq);
|
||||
unsigned int src = uic_irq_to_hw(virq);
|
||||
struct uic *uic = irq_data_get_irq_chip_data(d);
|
||||
unsigned int src = uic_irq_to_hw(d->irq);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&uic->lock, flags);
|
||||
|
@ -99,11 +99,11 @@ static void uic_ack_irq(unsigned int virq)
|
|||
spin_unlock_irqrestore(&uic->lock, flags);
|
||||
}
|
||||
|
||||
static void uic_mask_ack_irq(unsigned int virq)
|
||||
static void uic_mask_ack_irq(struct irq_data *d)
|
||||
{
|
||||
struct irq_desc *desc = irq_to_desc(virq);
|
||||
struct uic *uic = get_irq_chip_data(virq);
|
||||
unsigned int src = uic_irq_to_hw(virq);
|
||||
struct irq_desc *desc = irq_to_desc(d->irq);
|
||||
struct uic *uic = irq_data_get_irq_chip_data(d);
|
||||
unsigned int src = uic_irq_to_hw(d->irq);
|
||||
unsigned long flags;
|
||||
u32 er, sr;
|
||||
|
||||
|
@ -125,18 +125,18 @@ static void uic_mask_ack_irq(unsigned int virq)
|
|||
spin_unlock_irqrestore(&uic->lock, flags);
|
||||
}
|
||||
|
||||
static int uic_set_irq_type(unsigned int virq, unsigned int flow_type)
|
||||
static int uic_set_irq_type(struct irq_data *d, unsigned int flow_type)
|
||||
{
|
||||
struct uic *uic = get_irq_chip_data(virq);
|
||||
unsigned int src = uic_irq_to_hw(virq);
|
||||
struct irq_desc *desc = irq_to_desc(virq);
|
||||
struct uic *uic = irq_data_get_irq_chip_data(d);
|
||||
unsigned int src = uic_irq_to_hw(d->irq);
|
||||
struct irq_desc *desc = irq_to_desc(d->irq);
|
||||
unsigned long flags;
|
||||
int trigger, polarity;
|
||||
u32 tr, pr, mask;
|
||||
|
||||
switch (flow_type & IRQ_TYPE_SENSE_MASK) {
|
||||
case IRQ_TYPE_NONE:
|
||||
uic_mask_irq(virq);
|
||||
uic_mask_irq(d);
|
||||
return 0;
|
||||
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
|
@ -178,11 +178,11 @@ static int uic_set_irq_type(unsigned int virq, unsigned int flow_type)
|
|||
|
||||
static struct irq_chip uic_irq_chip = {
|
||||
.name = "UIC",
|
||||
.unmask = uic_unmask_irq,
|
||||
.mask = uic_mask_irq,
|
||||
.mask_ack = uic_mask_ack_irq,
|
||||
.ack = uic_ack_irq,
|
||||
.set_type = uic_set_irq_type,
|
||||
.irq_unmask = uic_unmask_irq,
|
||||
.irq_mask = uic_mask_irq,
|
||||
.irq_mask_ack = uic_mask_ack_irq,
|
||||
.irq_ack = uic_ack_irq,
|
||||
.irq_set_type = uic_set_irq_type,
|
||||
};
|
||||
|
||||
static int uic_host_map(struct irq_host *h, unsigned int virq,
|
||||
|
@ -220,6 +220,7 @@ static struct irq_host_ops uic_host_ops = {
|
|||
|
||||
void uic_irq_cascade(unsigned int virq, struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = get_irq_desc_chip(desc);
|
||||
struct uic *uic = get_irq_data(virq);
|
||||
u32 msr;
|
||||
int src;
|
||||
|
@ -227,9 +228,9 @@ void uic_irq_cascade(unsigned int virq, struct irq_desc *desc)
|
|||
|
||||
raw_spin_lock(&desc->lock);
|
||||
if (desc->status & IRQ_LEVEL)
|
||||
desc->chip->mask(virq);
|
||||
chip->irq_mask(&desc->irq_data);
|
||||
else
|
||||
desc->chip->mask_ack(virq);
|
||||
chip->irq_mask_ack(&desc->irq_data);
|
||||
raw_spin_unlock(&desc->lock);
|
||||
|
||||
msr = mfdcr(uic->dcrbase + UIC_MSR);
|
||||
|
@ -244,9 +245,9 @@ void uic_irq_cascade(unsigned int virq, struct irq_desc *desc)
|
|||
uic_irq_ret:
|
||||
raw_spin_lock(&desc->lock);
|
||||
if (desc->status & IRQ_LEVEL)
|
||||
desc->chip->ack(virq);
|
||||
if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
|
||||
desc->chip->unmask(virq);
|
||||
chip->irq_ack(&desc->irq_data);
|
||||
if (!(desc->status & IRQ_DISABLED) && chip->irq_unmask)
|
||||
chip->irq_unmask(&desc->irq_data);
|
||||
raw_spin_unlock(&desc->lock);
|
||||
}
|
||||
|
||||
|
|
|
@ -69,17 +69,17 @@ static unsigned char xilinx_intc_map_senses[] = {
|
|||
*
|
||||
* IRQ Chip common (across level and edge) operations
|
||||
*/
|
||||
static void xilinx_intc_mask(unsigned int virq)
|
||||
static void xilinx_intc_mask(struct irq_data *d)
|
||||
{
|
||||
int irq = virq_to_hw(virq);
|
||||
void * regs = get_irq_chip_data(virq);
|
||||
int irq = virq_to_hw(d->irq);
|
||||
void * regs = irq_data_get_irq_chip_data(d);
|
||||
pr_debug("mask: %d\n", irq);
|
||||
out_be32(regs + XINTC_CIE, 1 << irq);
|
||||
}
|
||||
|
||||
static int xilinx_intc_set_type(unsigned int virq, unsigned int flow_type)
|
||||
static int xilinx_intc_set_type(struct irq_data *d, unsigned int flow_type)
|
||||
{
|
||||
struct irq_desc *desc = irq_to_desc(virq);
|
||||
struct irq_desc *desc = irq_to_desc(d->irq);
|
||||
|
||||
desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
|
||||
desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
|
||||
|
@ -91,10 +91,10 @@ static int xilinx_intc_set_type(unsigned int virq, unsigned int flow_type)
|
|||
/*
|
||||
* IRQ Chip level operations
|
||||
*/
|
||||
static void xilinx_intc_level_unmask(unsigned int virq)
|
||||
static void xilinx_intc_level_unmask(struct irq_data *d)
|
||||
{
|
||||
int irq = virq_to_hw(virq);
|
||||
void * regs = get_irq_chip_data(virq);
|
||||
int irq = virq_to_hw(d->irq);
|
||||
void * regs = irq_data_get_irq_chip_data(d);
|
||||
pr_debug("unmask: %d\n", irq);
|
||||
out_be32(regs + XINTC_SIE, 1 << irq);
|
||||
|
||||
|
@ -107,37 +107,37 @@ static void xilinx_intc_level_unmask(unsigned int virq)
|
|||
|
||||
static struct irq_chip xilinx_intc_level_irqchip = {
|
||||
.name = "Xilinx Level INTC",
|
||||
.mask = xilinx_intc_mask,
|
||||
.mask_ack = xilinx_intc_mask,
|
||||
.unmask = xilinx_intc_level_unmask,
|
||||
.set_type = xilinx_intc_set_type,
|
||||
.irq_mask = xilinx_intc_mask,
|
||||
.irq_mask_ack = xilinx_intc_mask,
|
||||
.irq_unmask = xilinx_intc_level_unmask,
|
||||
.irq_set_type = xilinx_intc_set_type,
|
||||
};
|
||||
|
||||
/*
|
||||
* IRQ Chip edge operations
|
||||
*/
|
||||
static void xilinx_intc_edge_unmask(unsigned int virq)
|
||||
static void xilinx_intc_edge_unmask(struct irq_data *d)
|
||||
{
|
||||
int irq = virq_to_hw(virq);
|
||||
void *regs = get_irq_chip_data(virq);
|
||||
int irq = virq_to_hw(d->irq);
|
||||
void *regs = irq_data_get_irq_chip_data(d);
|
||||
pr_debug("unmask: %d\n", irq);
|
||||
out_be32(regs + XINTC_SIE, 1 << irq);
|
||||
}
|
||||
|
||||
static void xilinx_intc_edge_ack(unsigned int virq)
|
||||
static void xilinx_intc_edge_ack(struct irq_data *d)
|
||||
{
|
||||
int irq = virq_to_hw(virq);
|
||||
void * regs = get_irq_chip_data(virq);
|
||||
int irq = virq_to_hw(d->irq);
|
||||
void * regs = irq_data_get_irq_chip_data(d);
|
||||
pr_debug("ack: %d\n", irq);
|
||||
out_be32(regs + XINTC_IAR, 1 << irq);
|
||||
}
|
||||
|
||||
static struct irq_chip xilinx_intc_edge_irqchip = {
|
||||
.name = "Xilinx Edge INTC",
|
||||
.mask = xilinx_intc_mask,
|
||||
.unmask = xilinx_intc_edge_unmask,
|
||||
.ack = xilinx_intc_edge_ack,
|
||||
.set_type = xilinx_intc_set_type,
|
||||
.irq_mask = xilinx_intc_mask,
|
||||
.irq_unmask = xilinx_intc_edge_unmask,
|
||||
.irq_ack = xilinx_intc_edge_ack,
|
||||
.irq_set_type = xilinx_intc_set_type,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -229,12 +229,14 @@ int xilinx_intc_get_irq(void)
|
|||
*/
|
||||
static void xilinx_i8259_cascade(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = get_irq_desc_chip(desc);
|
||||
unsigned int cascade_irq = i8259_irq();
|
||||
|
||||
if (cascade_irq)
|
||||
generic_handle_irq(cascade_irq);
|
||||
|
||||
/* Let xilinx_intc end the interrupt */
|
||||
desc->chip->unmask(irq);
|
||||
chip->irq_unmask(&desc->irq_data);
|
||||
}
|
||||
|
||||
static void __init xilinx_i8259_setup_cascade(void)
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* Author: Ashish Kalra <ashish.kalra@freescale.com>
|
||||
* Li Yang <leoli@freescale.com>
|
||||
*
|
||||
* Copyright (c) 2006-2007 Freescale Semiconductor, Inc.
|
||||
* Copyright (c) 2006-2007, 2011 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
|
@ -157,7 +157,8 @@ enum {
|
|||
IE_ON_SINGL_DEVICE_ERR | IE_ON_CMD_COMPLETE,
|
||||
|
||||
EXT_INDIRECT_SEG_PRD_FLAG = (1 << 31),
|
||||
DATA_SNOOP_ENABLE = (1 << 22),
|
||||
DATA_SNOOP_ENABLE_V1 = (1 << 22),
|
||||
DATA_SNOOP_ENABLE_V2 = (1 << 28),
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -260,6 +261,7 @@ struct sata_fsl_host_priv {
|
|||
void __iomem *ssr_base;
|
||||
void __iomem *csr_base;
|
||||
int irq;
|
||||
int data_snoop;
|
||||
};
|
||||
|
||||
static inline unsigned int sata_fsl_tag(unsigned int tag,
|
||||
|
@ -312,7 +314,8 @@ static void sata_fsl_setup_cmd_hdr_entry(struct sata_fsl_port_priv *pp,
|
|||
}
|
||||
|
||||
static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc,
|
||||
u32 *ttl, dma_addr_t cmd_desc_paddr)
|
||||
u32 *ttl, dma_addr_t cmd_desc_paddr,
|
||||
int data_snoop)
|
||||
{
|
||||
struct scatterlist *sg;
|
||||
unsigned int num_prde = 0;
|
||||
|
@ -362,8 +365,7 @@ static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc,
|
|||
|
||||
ttl_dwords += sg_len;
|
||||
prd->dba = cpu_to_le32(sg_addr);
|
||||
prd->ddc_and_ext =
|
||||
cpu_to_le32(DATA_SNOOP_ENABLE | (sg_len & ~0x03));
|
||||
prd->ddc_and_ext = cpu_to_le32(data_snoop | (sg_len & ~0x03));
|
||||
|
||||
VPRINTK("sg_fill, ttl=%d, dba=0x%x, ddc=0x%x\n",
|
||||
ttl_dwords, prd->dba, prd->ddc_and_ext);
|
||||
|
@ -378,7 +380,7 @@ static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc,
|
|||
/* set indirect extension flag along with indirect ext. size */
|
||||
prd_ptr_to_indirect_ext->ddc_and_ext =
|
||||
cpu_to_le32((EXT_INDIRECT_SEG_PRD_FLAG |
|
||||
DATA_SNOOP_ENABLE |
|
||||
data_snoop |
|
||||
(indirect_ext_segment_sz & ~0x03)));
|
||||
}
|
||||
|
||||
|
@ -421,7 +423,8 @@ static void sata_fsl_qc_prep(struct ata_queued_cmd *qc)
|
|||
|
||||
if (qc->flags & ATA_QCFLAG_DMAMAP)
|
||||
num_prde = sata_fsl_fill_sg(qc, (void *)cd,
|
||||
&ttl_dwords, cd_paddr);
|
||||
&ttl_dwords, cd_paddr,
|
||||
host_priv->data_snoop);
|
||||
|
||||
if (qc->tf.protocol == ATA_PROT_NCQ)
|
||||
desc_info |= FPDMA_QUEUED_CMD;
|
||||
|
@ -1349,6 +1352,11 @@ static int sata_fsl_probe(struct platform_device *ofdev)
|
|||
}
|
||||
host_priv->irq = irq;
|
||||
|
||||
if (of_device_is_compatible(ofdev->dev.of_node, "fsl,pq-sata-v2"))
|
||||
host_priv->data_snoop = DATA_SNOOP_ENABLE_V2;
|
||||
else
|
||||
host_priv->data_snoop = DATA_SNOOP_ENABLE_V1;
|
||||
|
||||
/* allocate host structure */
|
||||
host = ata_host_alloc_pinfo(&ofdev->dev, ppi, SATA_FSL_MAX_PORTS);
|
||||
|
||||
|
@ -1431,6 +1439,9 @@ static struct of_device_id fsl_sata_match[] = {
|
|||
{
|
||||
.compatible = "fsl,pq-sata",
|
||||
},
|
||||
{
|
||||
.compatible = "fsl,pq-sata-v2",
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
|
@ -283,7 +283,7 @@ static void __devinit rackmeter_init_cpu_sniffer(struct rackmeter *rm)
|
|||
}
|
||||
}
|
||||
|
||||
static void __devexit rackmeter_stop_cpu_sniffer(struct rackmeter *rm)
|
||||
static void rackmeter_stop_cpu_sniffer(struct rackmeter *rm)
|
||||
{
|
||||
cancel_delayed_work_sync(&rm->cpu[0].sniffer);
|
||||
cancel_delayed_work_sync(&rm->cpu[1].sniffer);
|
||||
|
|
|
@ -309,6 +309,7 @@ struct hvcs_struct {
|
|||
|
||||
static LIST_HEAD(hvcs_structs);
|
||||
static DEFINE_SPINLOCK(hvcs_structs_lock);
|
||||
static DEFINE_MUTEX(hvcs_init_mutex);
|
||||
|
||||
static void hvcs_unthrottle(struct tty_struct *tty);
|
||||
static void hvcs_throttle(struct tty_struct *tty);
|
||||
|
@ -340,6 +341,7 @@ static int __devinit hvcs_probe(struct vio_dev *dev,
|
|||
static int __devexit hvcs_remove(struct vio_dev *dev);
|
||||
static int __init hvcs_module_init(void);
|
||||
static void __exit hvcs_module_exit(void);
|
||||
static int __devinit hvcs_initialize(void);
|
||||
|
||||
#define HVCS_SCHED_READ 0x00000001
|
||||
#define HVCS_QUICK_READ 0x00000002
|
||||
|
@ -762,7 +764,7 @@ static int __devinit hvcs_probe(
|
|||
const struct vio_device_id *id)
|
||||
{
|
||||
struct hvcs_struct *hvcsd;
|
||||
int index;
|
||||
int index, rc;
|
||||
int retval;
|
||||
|
||||
if (!dev || !id) {
|
||||
|
@ -770,6 +772,13 @@ static int __devinit hvcs_probe(
|
|||
return -EPERM;
|
||||
}
|
||||
|
||||
/* Make sure we are properly initialized */
|
||||
rc = hvcs_initialize();
|
||||
if (rc) {
|
||||
pr_err("HVCS: Failed to initialize core driver.\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* early to avoid cleanup on failure */
|
||||
index = hvcs_get_index();
|
||||
if (index < 0) {
|
||||
|
@ -1464,12 +1473,15 @@ static void hvcs_free_index_list(void)
|
|||
hvcs_index_count = 0;
|
||||
}
|
||||
|
||||
static int __init hvcs_module_init(void)
|
||||
static int __devinit hvcs_initialize(void)
|
||||
{
|
||||
int rc;
|
||||
int num_ttys_to_alloc;
|
||||
int rc, num_ttys_to_alloc;
|
||||
|
||||
printk(KERN_INFO "Initializing %s\n", hvcs_driver_string);
|
||||
mutex_lock(&hvcs_init_mutex);
|
||||
if (hvcs_task) {
|
||||
mutex_unlock(&hvcs_init_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Has the user specified an overload with an insmod param? */
|
||||
if (hvcs_parm_num_devs <= 0 ||
|
||||
|
@ -1528,35 +1540,13 @@ static int __init hvcs_module_init(void)
|
|||
|
||||
hvcs_task = kthread_run(khvcsd, NULL, "khvcsd");
|
||||
if (IS_ERR(hvcs_task)) {
|
||||
printk(KERN_ERR "HVCS: khvcsd creation failed. Driver not loaded.\n");
|
||||
printk(KERN_ERR "HVCS: khvcsd creation failed.\n");
|
||||
rc = -EIO;
|
||||
goto kthread_fail;
|
||||
}
|
||||
|
||||
rc = vio_register_driver(&hvcs_vio_driver);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "HVCS: can't register vio driver\n");
|
||||
goto vio_fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* This needs to be done AFTER the vio_register_driver() call or else
|
||||
* the kobjects won't be initialized properly.
|
||||
*/
|
||||
rc = driver_create_file(&(hvcs_vio_driver.driver), &driver_attr_rescan);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "HVCS: sysfs attr create failed\n");
|
||||
goto attr_fail;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "HVCS: driver module inserted.\n");
|
||||
|
||||
mutex_unlock(&hvcs_init_mutex);
|
||||
return 0;
|
||||
|
||||
attr_fail:
|
||||
vio_unregister_driver(&hvcs_vio_driver);
|
||||
vio_fail:
|
||||
kthread_stop(hvcs_task);
|
||||
kthread_fail:
|
||||
kfree(hvcs_pi_buff);
|
||||
buff_alloc_fail:
|
||||
|
@ -1566,15 +1556,39 @@ register_fail:
|
|||
index_fail:
|
||||
put_tty_driver(hvcs_tty_driver);
|
||||
hvcs_tty_driver = NULL;
|
||||
mutex_unlock(&hvcs_init_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __init hvcs_module_init(void)
|
||||
{
|
||||
int rc = vio_register_driver(&hvcs_vio_driver);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "HVCS: can't register vio driver\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
pr_info("HVCS: Driver registered.\n");
|
||||
|
||||
/* This needs to be done AFTER the vio_register_driver() call or else
|
||||
* the kobjects won't be initialized properly.
|
||||
*/
|
||||
rc = driver_create_file(&(hvcs_vio_driver.driver), &driver_attr_rescan);
|
||||
if (rc)
|
||||
pr_warning(KERN_ERR "HVCS: Failed to create rescan file (err %d)\n", rc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit hvcs_module_exit(void)
|
||||
{
|
||||
/*
|
||||
* This driver receives hvcs_remove callbacks for each device upon
|
||||
* module removal.
|
||||
*/
|
||||
vio_unregister_driver(&hvcs_vio_driver);
|
||||
if (!hvcs_task)
|
||||
return;
|
||||
|
||||
/*
|
||||
* This synchronous operation will wake the khvcsd kthread if it is
|
||||
|
@ -1589,8 +1603,6 @@ static void __exit hvcs_module_exit(void)
|
|||
|
||||
driver_remove_file(&hvcs_vio_driver.driver, &driver_attr_rescan);
|
||||
|
||||
vio_unregister_driver(&hvcs_vio_driver);
|
||||
|
||||
tty_unregister_driver(hvcs_tty_driver);
|
||||
|
||||
hvcs_free_index_list();
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue