forked from Minki/linux
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: [POWERPC] Fix return value from memcpy [POWERPC] iseries: Define insw et al. so libata/ide will compile [POWERPC] Fix irq enable/disable in smp_generic_take_timebase [POWERPC] Fix problem with time not advancing on 32-bit platforms [POWERPC] Restore copyright notice in arch/powerpc/kernel/fpu.S [POWERPC] Fix up ibm_architecture_vec definition [POWERPC] Make OF irq map code detect more error cases [POWERPC] Support for "weird" MPICs and fixup mpc7448_hpc2 [POWERPC] Fix MPIC sense codes in documentation [POWERPC] Fix performance regression in IRQ radix tree locking [POWERPC] Add mpc7448hpc2 device tree source file [POWERPC] Add MPC8349E MDS device tree source file to arch/powerpc/boot/dts [POWERPC] modify mpc83xx platforms to use new IRQ layer [POWERPC] Adapt ipic driver to new host_ops interface, add set_irq_type to set IRQ sense [POWERPC] back up old school ipic.[hc] to arch/ppc [POWERPC] Use mpc8641hpcn PIC base address from dev tree. [POWERPC] Allow MPC8641 HPCN to build with CONFIG_PCI disabled too. [POWERPC] Fix powerpc 44x_mmu build [POWERPC] Remove flush_dcache_all export
This commit is contained in:
commit
4c15343167
@ -1136,10 +1136,10 @@ Sense and level information should be encoded as follows:
|
||||
Devices connected to openPIC-compatible controllers should encode
|
||||
sense and polarity as follows:
|
||||
|
||||
0 = high to low edge sensitive type enabled
|
||||
0 = low to high edge sensitive type enabled
|
||||
1 = active low level sensitive type enabled
|
||||
2 = low to high edge sensitive type enabled
|
||||
3 = active high level sensitive type enabled
|
||||
2 = active high level sensitive type enabled
|
||||
3 = high to low edge sensitive type enabled
|
||||
|
||||
ISA PIC interrupt controllers should adhere to the ISA PIC
|
||||
encodings listed below:
|
||||
|
@ -354,6 +354,7 @@ endchoice
|
||||
config PPC_PSERIES
|
||||
depends on PPC_MULTIPLATFORM && PPC64
|
||||
bool "IBM pSeries & new (POWER5-based) iSeries"
|
||||
select MPIC
|
||||
select PPC_I8259
|
||||
select PPC_RTAS
|
||||
select RTAS_ERROR_LOGGING
|
||||
@ -363,6 +364,7 @@ config PPC_PSERIES
|
||||
config PPC_CHRP
|
||||
bool "Common Hardware Reference Platform (CHRP) based machines"
|
||||
depends on PPC_MULTIPLATFORM && PPC32
|
||||
select MPIC
|
||||
select PPC_I8259
|
||||
select PPC_INDIRECT_PCI
|
||||
select PPC_RTAS
|
||||
@ -373,6 +375,7 @@ config PPC_CHRP
|
||||
config PPC_PMAC
|
||||
bool "Apple PowerMac based machines"
|
||||
depends on PPC_MULTIPLATFORM
|
||||
select MPIC
|
||||
select PPC_INDIRECT_PCI if PPC32
|
||||
select PPC_MPC106 if PPC32
|
||||
default y
|
||||
@ -380,6 +383,7 @@ config PPC_PMAC
|
||||
config PPC_PMAC64
|
||||
bool
|
||||
depends on PPC_PMAC && POWER4
|
||||
select MPIC
|
||||
select U3_DART
|
||||
select MPIC_BROKEN_U3
|
||||
select GENERIC_TBSYNC
|
||||
@ -389,6 +393,7 @@ config PPC_PMAC64
|
||||
config PPC_PREP
|
||||
bool "PowerPC Reference Platform (PReP) based machines"
|
||||
depends on PPC_MULTIPLATFORM && PPC32 && BROKEN
|
||||
select MPIC
|
||||
select PPC_I8259
|
||||
select PPC_INDIRECT_PCI
|
||||
select PPC_UDBG_16550
|
||||
@ -397,6 +402,7 @@ config PPC_PREP
|
||||
config PPC_MAPLE
|
||||
depends on PPC_MULTIPLATFORM && PPC64
|
||||
bool "Maple 970FX Evaluation Board"
|
||||
select MPIC
|
||||
select U3_DART
|
||||
select MPIC_BROKEN_U3
|
||||
select GENERIC_TBSYNC
|
||||
@ -439,12 +445,6 @@ config U3_DART
|
||||
depends on PPC_MULTIPLATFORM && PPC64
|
||||
default n
|
||||
|
||||
config MPIC
|
||||
depends on PPC_PSERIES || PPC_PMAC || PPC_MAPLE || PPC_CHRP \
|
||||
|| MPC7448HPC2
|
||||
bool
|
||||
default y
|
||||
|
||||
config PPC_RTAS
|
||||
bool
|
||||
default n
|
||||
@ -812,6 +812,14 @@ config GENERIC_ISA_DMA
|
||||
depends on PPC64 || POWER4 || 6xx && !CPM2
|
||||
default y
|
||||
|
||||
config MPIC
|
||||
bool
|
||||
default n
|
||||
|
||||
config MPIC_WEIRD
|
||||
bool
|
||||
default n
|
||||
|
||||
config PPC_I8259
|
||||
bool
|
||||
default n
|
||||
|
190
arch/powerpc/boot/dts/mpc7448hpc2.dts
Normal file
190
arch/powerpc/boot/dts/mpc7448hpc2.dts
Normal file
@ -0,0 +1,190 @@
|
||||
/*
|
||||
* MPC7448HPC2 (Taiga) board Device Tree Source
|
||||
*
|
||||
* Copyright 2006 Freescale Semiconductor Inc.
|
||||
* 2006 Roy Zang <Roy Zang at freescale.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.
|
||||
*/
|
||||
|
||||
|
||||
/ {
|
||||
model = "mpc7448hpc2";
|
||||
compatible = "mpc74xx";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
linux,phandle = <100>;
|
||||
|
||||
cpus {
|
||||
#cpus = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells =<0>;
|
||||
linux,phandle = <200>;
|
||||
|
||||
PowerPC,7448@0 {
|
||||
device_type = "cpu";
|
||||
reg = <0>;
|
||||
d-cache-line-size = <20>; // 32 bytes
|
||||
i-cache-line-size = <20>; // 32 bytes
|
||||
d-cache-size = <8000>; // L1, 32K bytes
|
||||
i-cache-size = <8000>; // L1, 32K bytes
|
||||
timebase-frequency = <0>; // 33 MHz, from uboot
|
||||
clock-frequency = <0>; // From U-Boot
|
||||
bus-frequency = <0>; // From U-Boot
|
||||
32-bit;
|
||||
linux,phandle = <201>;
|
||||
linux,boot-cpu;
|
||||
};
|
||||
};
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
linux,phandle = <300>;
|
||||
reg = <00000000 20000000 // DDR2 512M at 0
|
||||
>;
|
||||
};
|
||||
|
||||
tsi108@c0000000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
#interrupt-cells = <2>;
|
||||
device_type = "tsi-bridge";
|
||||
ranges = <00000000 c0000000 00010000>;
|
||||
reg = <c0000000 00010000>;
|
||||
bus-frequency = <0>;
|
||||
|
||||
i2c@7000 {
|
||||
interrupt-parent = <7400>;
|
||||
interrupts = <E 0>;
|
||||
reg = <7000 400>;
|
||||
device_type = "i2c";
|
||||
compatible = "tsi-i2c";
|
||||
};
|
||||
|
||||
mdio@6000 {
|
||||
device_type = "mdio";
|
||||
compatible = "tsi-ethernet";
|
||||
|
||||
ethernet-phy@6000 {
|
||||
linux,phandle = <6000>;
|
||||
interrupt-parent = <7400>;
|
||||
interrupts = <2 1>;
|
||||
reg = <6000 50>;
|
||||
phy-id = <8>;
|
||||
device_type = "ethernet-phy";
|
||||
};
|
||||
|
||||
ethernet-phy@6400 {
|
||||
linux,phandle = <6400>;
|
||||
interrupt-parent = <7400>;
|
||||
interrupts = <2 1>;
|
||||
reg = <6000 50>;
|
||||
phy-id = <9>;
|
||||
device_type = "ethernet-phy";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
ethernet@6200 {
|
||||
#size-cells = <0>;
|
||||
device_type = "network";
|
||||
model = "TSI-ETH";
|
||||
compatible = "tsi-ethernet";
|
||||
reg = <6000 200>;
|
||||
address = [ 00 06 D2 00 00 01 ];
|
||||
interrupts = <10 2>;
|
||||
interrupt-parent = <7400>;
|
||||
phy-handle = <6000>;
|
||||
};
|
||||
|
||||
ethernet@6600 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
device_type = "network";
|
||||
model = "TSI-ETH";
|
||||
compatible = "tsi-ethernet";
|
||||
reg = <6400 200>;
|
||||
address = [ 00 06 D2 00 00 02 ];
|
||||
interrupts = <11 2>;
|
||||
interrupt-parent = <7400>;
|
||||
phy-handle = <6400>;
|
||||
};
|
||||
|
||||
serial@7808 {
|
||||
device_type = "serial";
|
||||
compatible = "ns16550";
|
||||
reg = <7808 200>;
|
||||
clock-frequency = <3f6b5a00>;
|
||||
interrupts = <c 0>;
|
||||
interrupt-parent = <7400>;
|
||||
};
|
||||
|
||||
serial@7c08 {
|
||||
device_type = "serial";
|
||||
compatible = "ns16550";
|
||||
reg = <7c08 200>;
|
||||
clock-frequency = <3f6b5a00>;
|
||||
interrupts = <d 0>;
|
||||
interrupt-parent = <7400>;
|
||||
};
|
||||
|
||||
pic@7400 {
|
||||
linux,phandle = <7400>;
|
||||
clock-frequency = <0>;
|
||||
interrupt-controller;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <2>;
|
||||
reg = <7400 400>;
|
||||
built-in;
|
||||
compatible = "chrp,open-pic";
|
||||
device_type = "open-pic";
|
||||
big-endian;
|
||||
};
|
||||
pci@1000 {
|
||||
compatible = "tsi10x";
|
||||
device_type = "pci";
|
||||
linux,phandle = <1000>;
|
||||
#interrupt-cells = <1>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
reg = <1000 1000>;
|
||||
bus-range = <0 0>;
|
||||
ranges = <02000000 0 e0000000 e0000000 0 1A000000
|
||||
01000000 0 00000000 fa000000 0 00010000>;
|
||||
clock-frequency = <7f28154>;
|
||||
interrupt-parent = <7400>;
|
||||
interrupts = <17 2>;
|
||||
interrupt-map-mask = <f800 0 0 7>;
|
||||
interrupt-map = <
|
||||
|
||||
/* IDSEL 0x11 */
|
||||
0800 0 0 1 7400 24 0
|
||||
0800 0 0 2 7400 25 0
|
||||
0800 0 0 3 7400 26 0
|
||||
0800 0 0 4 7400 27 0
|
||||
|
||||
/* IDSEL 0x12 */
|
||||
1000 0 0 1 7400 25 0
|
||||
1000 0 0 2 7400 26 0
|
||||
1000 0 0 3 7400 27 0
|
||||
1000 0 0 4 7400 24 0
|
||||
|
||||
/* IDSEL 0x13 */
|
||||
1800 0 0 1 7400 26 0
|
||||
1800 0 0 2 7400 27 0
|
||||
1800 0 0 3 7400 24 0
|
||||
1800 0 0 4 7400 25 0
|
||||
|
||||
/* IDSEL 0x14 */
|
||||
2000 0 0 1 7400 27 0
|
||||
2000 0 0 2 7400 24 0
|
||||
2000 0 0 3 7400 25 0
|
||||
2000 0 0 4 7400 26 0
|
||||
>;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
328
arch/powerpc/boot/dts/mpc8349emds.dts
Normal file
328
arch/powerpc/boot/dts/mpc8349emds.dts
Normal file
@ -0,0 +1,328 @@
|
||||
/*
|
||||
* MPC8349E MDS Device Tree Source
|
||||
*
|
||||
* Copyright 2005, 2006 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
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
/ {
|
||||
model = "MPC8349EMDS";
|
||||
compatible = "MPC834xMDS";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
cpus {
|
||||
#cpus = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
PowerPC,8349@0 {
|
||||
device_type = "cpu";
|
||||
reg = <0>;
|
||||
d-cache-line-size = <20>; // 32 bytes
|
||||
i-cache-line-size = <20>; // 32 bytes
|
||||
d-cache-size = <8000>; // L1, 32K
|
||||
i-cache-size = <8000>; // L1, 32K
|
||||
timebase-frequency = <0>; // from bootloader
|
||||
bus-frequency = <0>; // from bootloader
|
||||
clock-frequency = <0>; // from bootloader
|
||||
32-bit;
|
||||
};
|
||||
};
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
reg = <00000000 10000000>; // 256MB at 0
|
||||
};
|
||||
|
||||
soc8349@e0000000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
#interrupt-cells = <2>;
|
||||
device_type = "soc";
|
||||
ranges = <0 e0000000 00100000>;
|
||||
reg = <e0000000 00000200>;
|
||||
bus-frequency = <0>;
|
||||
|
||||
wdt@200 {
|
||||
device_type = "watchdog";
|
||||
compatible = "mpc83xx_wdt";
|
||||
reg = <200 100>;
|
||||
};
|
||||
|
||||
i2c@3000 {
|
||||
device_type = "i2c";
|
||||
compatible = "fsl-i2c";
|
||||
reg = <3000 100>;
|
||||
interrupts = <e 8>;
|
||||
interrupt-parent = <700>;
|
||||
dfsrr;
|
||||
};
|
||||
|
||||
i2c@3100 {
|
||||
device_type = "i2c";
|
||||
compatible = "fsl-i2c";
|
||||
reg = <3100 100>;
|
||||
interrupts = <f 8>;
|
||||
interrupt-parent = <700>;
|
||||
dfsrr;
|
||||
};
|
||||
|
||||
spi@7000 {
|
||||
device_type = "spi";
|
||||
compatible = "mpc83xx_spi";
|
||||
reg = <7000 1000>;
|
||||
interrupts = <10 8>;
|
||||
interrupt-parent = <700>;
|
||||
mode = <0>;
|
||||
};
|
||||
|
||||
/* phy type (ULPI or SERIAL) are only types supportted for MPH */
|
||||
/* port = 0 or 1 */
|
||||
usb@22000 {
|
||||
device_type = "usb";
|
||||
compatible = "fsl-usb2-mph";
|
||||
reg = <22000 1000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
interrupt-parent = <700>;
|
||||
interrupts = <27 2>;
|
||||
phy_type = "ulpi";
|
||||
port1;
|
||||
};
|
||||
/* phy type (ULPI, UTMI, UTMI_WIDE, SERIAL) */
|
||||
usb@23000 {
|
||||
device_type = "usb";
|
||||
compatible = "fsl-usb2-dr";
|
||||
reg = <23000 1000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
interrupt-parent = <700>;
|
||||
interrupts = <26 2>;
|
||||
phy_type = "ulpi";
|
||||
};
|
||||
|
||||
mdio@24520 {
|
||||
device_type = "mdio";
|
||||
compatible = "gianfar";
|
||||
reg = <24520 20>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
linux,phandle = <24520>;
|
||||
ethernet-phy@0 {
|
||||
linux,phandle = <2452000>;
|
||||
interrupt-parent = <700>;
|
||||
interrupts = <11 2>;
|
||||
reg = <0>;
|
||||
device_type = "ethernet-phy";
|
||||
};
|
||||
ethernet-phy@1 {
|
||||
linux,phandle = <2452001>;
|
||||
interrupt-parent = <700>;
|
||||
interrupts = <12 2>;
|
||||
reg = <1>;
|
||||
device_type = "ethernet-phy";
|
||||
};
|
||||
};
|
||||
|
||||
ethernet@24000 {
|
||||
device_type = "network";
|
||||
model = "TSEC";
|
||||
compatible = "gianfar";
|
||||
reg = <24000 1000>;
|
||||
address = [ 00 00 00 00 00 00 ];
|
||||
local-mac-address = [ 00 00 00 00 00 00 ];
|
||||
interrupts = <20 8 21 8 22 8>;
|
||||
interrupt-parent = <700>;
|
||||
phy-handle = <2452000>;
|
||||
};
|
||||
|
||||
ethernet@25000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
device_type = "network";
|
||||
model = "TSEC";
|
||||
compatible = "gianfar";
|
||||
reg = <25000 1000>;
|
||||
address = [ 00 00 00 00 00 00 ];
|
||||
local-mac-address = [ 00 00 00 00 00 00 ];
|
||||
interrupts = <23 8 24 8 25 8>;
|
||||
interrupt-parent = <700>;
|
||||
phy-handle = <2452001>;
|
||||
};
|
||||
|
||||
serial@4500 {
|
||||
device_type = "serial";
|
||||
compatible = "ns16550";
|
||||
reg = <4500 100>;
|
||||
clock-frequency = <0>;
|
||||
interrupts = <9 8>;
|
||||
interrupt-parent = <700>;
|
||||
};
|
||||
|
||||
serial@4600 {
|
||||
device_type = "serial";
|
||||
compatible = "ns16550";
|
||||
reg = <4600 100>;
|
||||
clock-frequency = <0>;
|
||||
interrupts = <a 8>;
|
||||
interrupt-parent = <700>;
|
||||
};
|
||||
|
||||
pci@8500 {
|
||||
interrupt-map-mask = <f800 0 0 7>;
|
||||
interrupt-map = <
|
||||
|
||||
/* IDSEL 0x11 */
|
||||
8800 0 0 1 700 14 8
|
||||
8800 0 0 2 700 15 8
|
||||
8800 0 0 3 700 16 8
|
||||
8800 0 0 4 700 17 8
|
||||
|
||||
/* IDSEL 0x12 */
|
||||
9000 0 0 1 700 16 8
|
||||
9000 0 0 2 700 17 8
|
||||
9000 0 0 3 700 14 8
|
||||
9000 0 0 4 700 15 8
|
||||
|
||||
/* IDSEL 0x13 */
|
||||
9800 0 0 1 700 17 8
|
||||
9800 0 0 2 700 14 8
|
||||
9800 0 0 3 700 15 8
|
||||
9800 0 0 4 700 16 8
|
||||
|
||||
/* IDSEL 0x15 */
|
||||
a800 0 0 1 700 14 8
|
||||
a800 0 0 2 700 15 8
|
||||
a800 0 0 3 700 16 8
|
||||
a800 0 0 4 700 17 8
|
||||
|
||||
/* IDSEL 0x16 */
|
||||
b000 0 0 1 700 17 8
|
||||
b000 0 0 2 700 14 8
|
||||
b000 0 0 3 700 15 8
|
||||
b000 0 0 4 700 16 8
|
||||
|
||||
/* IDSEL 0x17 */
|
||||
b800 0 0 1 700 16 8
|
||||
b800 0 0 2 700 17 8
|
||||
b800 0 0 3 700 14 8
|
||||
b800 0 0 4 700 15 8
|
||||
|
||||
/* IDSEL 0x18 */
|
||||
b000 0 0 1 700 15 8
|
||||
b000 0 0 2 700 16 8
|
||||
b000 0 0 3 700 17 8
|
||||
b000 0 0 4 700 14 8>;
|
||||
interrupt-parent = <700>;
|
||||
interrupts = <42 8>;
|
||||
bus-range = <0 0>;
|
||||
ranges = <02000000 0 a0000000 a0000000 0 10000000
|
||||
42000000 0 80000000 80000000 0 10000000
|
||||
01000000 0 00000000 e2000000 0 00100000>;
|
||||
clock-frequency = <3f940aa>;
|
||||
#interrupt-cells = <1>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
reg = <8500 100>;
|
||||
compatible = "83xx";
|
||||
device_type = "pci";
|
||||
};
|
||||
|
||||
pci@8600 {
|
||||
interrupt-map-mask = <f800 0 0 7>;
|
||||
interrupt-map = <
|
||||
|
||||
/* IDSEL 0x11 */
|
||||
8800 0 0 1 700 14 8
|
||||
8800 0 0 2 700 15 8
|
||||
8800 0 0 3 700 16 8
|
||||
8800 0 0 4 700 17 8
|
||||
|
||||
/* IDSEL 0x12 */
|
||||
9000 0 0 1 700 16 8
|
||||
9000 0 0 2 700 17 8
|
||||
9000 0 0 3 700 14 8
|
||||
9000 0 0 4 700 15 8
|
||||
|
||||
/* IDSEL 0x13 */
|
||||
9800 0 0 1 700 17 8
|
||||
9800 0 0 2 700 14 8
|
||||
9800 0 0 3 700 15 8
|
||||
9800 0 0 4 700 16 8
|
||||
|
||||
/* IDSEL 0x15 */
|
||||
a800 0 0 1 700 14 8
|
||||
a800 0 0 2 700 15 8
|
||||
a800 0 0 3 700 16 8
|
||||
a800 0 0 4 700 17 8
|
||||
|
||||
/* IDSEL 0x16 */
|
||||
b000 0 0 1 700 17 8
|
||||
b000 0 0 2 700 14 8
|
||||
b000 0 0 3 700 15 8
|
||||
b000 0 0 4 700 16 8
|
||||
|
||||
/* IDSEL 0x17 */
|
||||
b800 0 0 1 700 16 8
|
||||
b800 0 0 2 700 17 8
|
||||
b800 0 0 3 700 14 8
|
||||
b800 0 0 4 700 15 8
|
||||
|
||||
/* IDSEL 0x18 */
|
||||
b000 0 0 1 700 15 8
|
||||
b000 0 0 2 700 16 8
|
||||
b000 0 0 3 700 17 8
|
||||
b000 0 0 4 700 14 8>;
|
||||
interrupt-parent = <700>;
|
||||
interrupts = <42 8>;
|
||||
bus-range = <0 0>;
|
||||
ranges = <02000000 0 b0000000 b0000000 0 10000000
|
||||
42000000 0 90000000 90000000 0 10000000
|
||||
01000000 0 00000000 e2100000 0 00100000>;
|
||||
clock-frequency = <3f940aa>;
|
||||
#interrupt-cells = <1>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
reg = <8600 100>;
|
||||
compatible = "83xx";
|
||||
device_type = "pci";
|
||||
};
|
||||
|
||||
/* May need to remove if on a part without crypto engine */
|
||||
crypto@30000 {
|
||||
device_type = "crypto";
|
||||
model = "SEC2";
|
||||
compatible = "talitos";
|
||||
reg = <30000 10000>;
|
||||
interrupts = <b 8>;
|
||||
interrupt-parent = <700>;
|
||||
num-channels = <4>;
|
||||
channel-fifo-len = <18>;
|
||||
exec-units-mask = <0000007e>;
|
||||
/* desc mask is for rev2.0,
|
||||
* we need runtime fixup for >2.0 */
|
||||
descriptor-types-mask = <01010ebf>;
|
||||
};
|
||||
|
||||
/* IPIC
|
||||
* interrupts cell = <intr #, sense>
|
||||
* sense values match linux IORESOURCE_IRQ_* defines:
|
||||
* sense == 8: Level, low assertion
|
||||
* sense == 2: Edge, high-to-low change
|
||||
*/
|
||||
pic@700 {
|
||||
linux,phandle = <700>;
|
||||
interrupt-controller;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <2>;
|
||||
reg = <700 100>;
|
||||
built-in;
|
||||
device_type = "ipic";
|
||||
};
|
||||
};
|
||||
};
|
@ -2,6 +2,11 @@
|
||||
* FPU support code, moved here from head.S so that it can be used
|
||||
* by chips which use other head-whatever.S files.
|
||||
*
|
||||
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
|
||||
* Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
|
||||
* Copyright (C) 1996 Paul Mackerras.
|
||||
* Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
|
||||
*
|
||||
* 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
|
||||
|
@ -322,7 +322,8 @@ EXPORT_SYMBOL(do_softirq);
|
||||
|
||||
static LIST_HEAD(irq_hosts);
|
||||
static spinlock_t irq_big_lock = SPIN_LOCK_UNLOCKED;
|
||||
|
||||
static DEFINE_PER_CPU(unsigned int, irq_radix_reader);
|
||||
static unsigned int irq_radix_writer;
|
||||
struct irq_map_entry irq_map[NR_IRQS];
|
||||
static unsigned int irq_virq_count = NR_IRQS;
|
||||
static struct irq_host *irq_default_host;
|
||||
@ -455,6 +456,58 @@ void irq_set_virq_count(unsigned int count)
|
||||
irq_virq_count = count;
|
||||
}
|
||||
|
||||
/* radix tree not lockless safe ! we use a brlock-type mecanism
|
||||
* for now, until we can use a lockless radix tree
|
||||
*/
|
||||
static void irq_radix_wrlock(unsigned long *flags)
|
||||
{
|
||||
unsigned int cpu, ok;
|
||||
|
||||
spin_lock_irqsave(&irq_big_lock, *flags);
|
||||
irq_radix_writer = 1;
|
||||
smp_mb();
|
||||
do {
|
||||
barrier();
|
||||
ok = 1;
|
||||
for_each_possible_cpu(cpu) {
|
||||
if (per_cpu(irq_radix_reader, cpu)) {
|
||||
ok = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ok)
|
||||
cpu_relax();
|
||||
} while(!ok);
|
||||
}
|
||||
|
||||
static void irq_radix_wrunlock(unsigned long flags)
|
||||
{
|
||||
smp_wmb();
|
||||
irq_radix_writer = 0;
|
||||
spin_unlock_irqrestore(&irq_big_lock, flags);
|
||||
}
|
||||
|
||||
static void irq_radix_rdlock(unsigned long *flags)
|
||||
{
|
||||
local_irq_save(*flags);
|
||||
__get_cpu_var(irq_radix_reader) = 1;
|
||||
smp_mb();
|
||||
if (likely(irq_radix_writer == 0))
|
||||
return;
|
||||
__get_cpu_var(irq_radix_reader) = 0;
|
||||
smp_wmb();
|
||||
spin_lock(&irq_big_lock);
|
||||
__get_cpu_var(irq_radix_reader) = 1;
|
||||
spin_unlock(&irq_big_lock);
|
||||
}
|
||||
|
||||
static void irq_radix_rdunlock(unsigned long flags)
|
||||
{
|
||||
__get_cpu_var(irq_radix_reader) = 0;
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
|
||||
unsigned int irq_create_mapping(struct irq_host *host,
|
||||
irq_hw_number_t hwirq)
|
||||
{
|
||||
@ -604,13 +657,9 @@ void irq_dispose_mapping(unsigned int virq)
|
||||
/* Check if radix tree allocated yet */
|
||||
if (host->revmap_data.tree.gfp_mask == 0)
|
||||
break;
|
||||
/* XXX radix tree not safe ! remove lock whem it becomes safe
|
||||
* and use some RCU sync to make sure everything is ok before we
|
||||
* can re-use that map entry
|
||||
*/
|
||||
spin_lock_irqsave(&irq_big_lock, flags);
|
||||
irq_radix_wrlock(&flags);
|
||||
radix_tree_delete(&host->revmap_data.tree, hwirq);
|
||||
spin_unlock_irqrestore(&irq_big_lock, flags);
|
||||
irq_radix_wrunlock(flags);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -677,25 +726,24 @@ unsigned int irq_radix_revmap(struct irq_host *host,
|
||||
if (tree->gfp_mask == 0)
|
||||
return irq_find_mapping(host, hwirq);
|
||||
|
||||
/* XXX Current radix trees are NOT SMP safe !!! Remove that lock
|
||||
* when that is fixed (when Nick's patch gets in
|
||||
*/
|
||||
spin_lock_irqsave(&irq_big_lock, flags);
|
||||
|
||||
/* Now try to resolve */
|
||||
irq_radix_rdlock(&flags);
|
||||
ptr = radix_tree_lookup(tree, hwirq);
|
||||
irq_radix_rdunlock(flags);
|
||||
|
||||
/* Found it, return */
|
||||
if (ptr) {
|
||||
virq = ptr - irq_map;
|
||||
goto bail;
|
||||
return virq;
|
||||
}
|
||||
|
||||
/* If not there, try to insert it */
|
||||
virq = irq_find_mapping(host, hwirq);
|
||||
if (virq != NO_IRQ)
|
||||
if (virq != NO_IRQ) {
|
||||
irq_radix_wrlock(&flags);
|
||||
radix_tree_insert(tree, hwirq, &irq_map[virq]);
|
||||
bail:
|
||||
spin_unlock_irqrestore(&irq_big_lock, flags);
|
||||
irq_radix_wrunlock(flags);
|
||||
}
|
||||
return virq;
|
||||
}
|
||||
|
||||
@ -806,12 +854,12 @@ static int irq_late_init(void)
|
||||
struct irq_host *h;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&irq_big_lock, flags);
|
||||
irq_radix_wrlock(&flags);
|
||||
list_for_each_entry(h, &irq_hosts, link) {
|
||||
if (h->revmap_type == IRQ_HOST_MAP_TREE)
|
||||
INIT_RADIX_TREE(&h->revmap_data.tree, GFP_ATOMIC);
|
||||
}
|
||||
spin_unlock_irqrestore(&irq_big_lock, flags);
|
||||
irq_radix_wrunlock(flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1289,6 +1289,9 @@ int pci_read_irq_line(struct pci_dev *pci_dev)
|
||||
|
||||
DBG("Try to map irq for %s...\n", pci_name(pci_dev));
|
||||
|
||||
#ifdef DEBUG
|
||||
memset(&oirq, 0xff, sizeof(oirq));
|
||||
#endif
|
||||
/* Try to get a mapping from the device-tree */
|
||||
if (of_irq_map_pci(pci_dev, &oirq)) {
|
||||
u8 line, pin;
|
||||
@ -1314,8 +1317,9 @@ int pci_read_irq_line(struct pci_dev *pci_dev)
|
||||
if (virq != NO_IRQ)
|
||||
set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
|
||||
} else {
|
||||
DBG(" -> got one, spec %d cells (0x%08x...) on %s\n",
|
||||
oirq.size, oirq.specifier[0], oirq.controller->full_name);
|
||||
DBG(" -> got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
|
||||
oirq.size, oirq.specifier[0], oirq.specifier[1],
|
||||
oirq.controller->full_name);
|
||||
|
||||
virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
|
||||
oirq.size);
|
||||
@ -1324,6 +1328,9 @@ int pci_read_irq_line(struct pci_dev *pci_dev)
|
||||
DBG(" -> failed to map !\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
DBG(" -> mapped to linux irq %d\n", virq);
|
||||
|
||||
pci_dev->irq = virq;
|
||||
pci_write_config_byte(pci_dev, PCI_INTERRUPT_LINE, virq);
|
||||
|
||||
|
@ -126,10 +126,6 @@ EXPORT_SYMBOL(pci_bus_mem_base_phys);
|
||||
EXPORT_SYMBOL(pci_bus_to_hose);
|
||||
#endif /* CONFIG_PCI */
|
||||
|
||||
#ifdef CONFIG_NOT_COHERENT_CACHE
|
||||
EXPORT_SYMBOL(flush_dcache_all);
|
||||
#endif
|
||||
|
||||
EXPORT_SYMBOL(start_thread);
|
||||
EXPORT_SYMBOL(kernel_thread);
|
||||
|
||||
|
@ -646,13 +646,13 @@ static unsigned char ibm_architecture_vec[] = {
|
||||
5 - 1, /* 5 option vectors */
|
||||
|
||||
/* option vector 1: processor architectures supported */
|
||||
3 - 1, /* length */
|
||||
3 - 2, /* length */
|
||||
0, /* don't ignore, don't halt */
|
||||
OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 |
|
||||
OV1_PPC_2_04 | OV1_PPC_2_05,
|
||||
|
||||
/* option vector 2: Open Firmware options supported */
|
||||
34 - 1, /* length */
|
||||
34 - 2, /* length */
|
||||
OV2_REAL_MODE,
|
||||
0, 0,
|
||||
W(0xffffffff), /* real_base */
|
||||
@ -666,16 +666,16 @@ static unsigned char ibm_architecture_vec[] = {
|
||||
48, /* max log_2(hash table size) */
|
||||
|
||||
/* option vector 3: processor options supported */
|
||||
3 - 1, /* length */
|
||||
3 - 2, /* length */
|
||||
0, /* don't ignore, don't halt */
|
||||
OV3_FP | OV3_VMX,
|
||||
|
||||
/* option vector 4: IBM PAPR implementation */
|
||||
2 - 1, /* length */
|
||||
2 - 2, /* length */
|
||||
0, /* don't halt */
|
||||
|
||||
/* option vector 5: PAPR/OF options */
|
||||
3 - 1, /* length */
|
||||
3 - 2, /* length */
|
||||
0, /* don't ignore, don't halt */
|
||||
OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES,
|
||||
};
|
||||
|
@ -639,14 +639,17 @@ void of_irq_map_init(unsigned int flags)
|
||||
|
||||
}
|
||||
|
||||
int of_irq_map_raw(struct device_node *parent, u32 *intspec, u32 *addr,
|
||||
struct of_irq *out_irq)
|
||||
int of_irq_map_raw(struct device_node *parent, u32 *intspec, u32 ointsize,
|
||||
u32 *addr, struct of_irq *out_irq)
|
||||
{
|
||||
struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL;
|
||||
u32 *tmp, *imap, *imask;
|
||||
u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0;
|
||||
int imaplen, match, i;
|
||||
|
||||
DBG("of_irq_map_raw: par=%s,intspec=[0x%08x 0x%08x...],ointsize=%d\n",
|
||||
parent->full_name, intspec[0], intspec[1], ointsize);
|
||||
|
||||
ipar = of_node_get(parent);
|
||||
|
||||
/* First get the #interrupt-cells property of the current cursor
|
||||
@ -670,6 +673,9 @@ int of_irq_map_raw(struct device_node *parent, u32 *intspec, u32 *addr,
|
||||
|
||||
DBG("of_irq_map_raw: ipar=%s, size=%d\n", ipar->full_name, intsize);
|
||||
|
||||
if (ointsize != intsize)
|
||||
return -EINVAL;
|
||||
|
||||
/* Look for this #address-cells. We have to implement the old linux
|
||||
* trick of looking for the parent here as some device-trees rely on it
|
||||
*/
|
||||
@ -875,12 +881,15 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq
|
||||
}
|
||||
intsize = *tmp;
|
||||
|
||||
DBG(" intsize=%d intlen=%d\n", intsize, intlen);
|
||||
|
||||
/* Check index */
|
||||
if ((index + 1) * intsize > intlen)
|
||||
return -EINVAL;
|
||||
|
||||
/* Get new specifier and map it */
|
||||
res = of_irq_map_raw(p, intspec + index * intsize, addr, out_irq);
|
||||
res = of_irq_map_raw(p, intspec + index * intsize, intsize,
|
||||
addr, out_irq);
|
||||
of_node_put(p);
|
||||
return res;
|
||||
}
|
||||
@ -965,7 +974,7 @@ int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
|
||||
laddr[0] = (pdev->bus->number << 16)
|
||||
| (pdev->devfn << 8);
|
||||
laddr[1] = laddr[2] = 0;
|
||||
return of_irq_map_raw(ppnode, &lspec, laddr, out_irq);
|
||||
return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_irq_map_pci);
|
||||
#endif /* CONFIG_PCI */
|
||||
|
@ -45,8 +45,9 @@ void __devinit smp_generic_take_timebase(void)
|
||||
{
|
||||
int cmd;
|
||||
u64 tb;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_disable();
|
||||
local_irq_save(flags);
|
||||
while (!running)
|
||||
barrier();
|
||||
rmb();
|
||||
@ -70,7 +71,7 @@ void __devinit smp_generic_take_timebase(void)
|
||||
set_tb(tb >> 32, tb & 0xfffffffful);
|
||||
enter_contest(tbsync->mark, -1);
|
||||
}
|
||||
local_irq_enable();
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static int __devinit start_contest(int cmd, long offset, int num)
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
.align 7
|
||||
_GLOBAL(memcpy)
|
||||
std r3,48(r1) /* save destination pointer for return value */
|
||||
mtcrf 0x01,r5
|
||||
cmpldi cr1,r5,16
|
||||
neg r6,r3 # LS 3 bits = # bytes to 8-byte dest bdry
|
||||
@ -38,7 +39,7 @@ _GLOBAL(memcpy)
|
||||
stdu r9,16(r3)
|
||||
bdnz 1b
|
||||
3: std r8,8(r3)
|
||||
beqlr
|
||||
beq 3f
|
||||
addi r3,r3,16
|
||||
ld r9,8(r4)
|
||||
.Ldo_tail:
|
||||
@ -53,7 +54,8 @@ _GLOBAL(memcpy)
|
||||
2: bf cr7*4+3,3f
|
||||
rotldi r9,r9,8
|
||||
stb r9,0(r3)
|
||||
3: blr
|
||||
3: ld r3,48(r1) /* return dest pointer */
|
||||
blr
|
||||
|
||||
.Lsrc_unaligned:
|
||||
srdi r6,r5,3
|
||||
@ -115,7 +117,7 @@ _GLOBAL(memcpy)
|
||||
5: srd r12,r9,r11
|
||||
or r12,r8,r12
|
||||
std r12,24(r3)
|
||||
beqlr
|
||||
beq 4f
|
||||
cmpwi cr1,r5,8
|
||||
addi r3,r3,32
|
||||
sld r9,r9,r10
|
||||
@ -167,4 +169,5 @@ _GLOBAL(memcpy)
|
||||
3: bf cr7*4+3,4f
|
||||
lbz r0,0(r4)
|
||||
stb r0,0(r3)
|
||||
4: blr
|
||||
4: ld r3,48(r1) /* return dest pointer */
|
||||
blr
|
||||
|
@ -103,7 +103,7 @@ unsigned long __init mmu_mapin_ram(void)
|
||||
|
||||
/* Determine number of entries necessary to cover lowmem */
|
||||
pinned_tlbs = (unsigned int)
|
||||
(_ALIGN(total_lowmem, PPC44x_PIN_SIZE) >> PPC44x_PIN_SHIFT);
|
||||
(_ALIGN(total_lowmem, PPC_PIN_SIZE) >> PPC44x_PIN_SHIFT);
|
||||
|
||||
/* Write upper watermark to save location */
|
||||
tlb_44x_hwater = PPC44x_LOW_SLOT - pinned_tlbs;
|
||||
@ -111,7 +111,7 @@ unsigned long __init mmu_mapin_ram(void)
|
||||
/* If necessary, set additional pinned TLBs */
|
||||
if (pinned_tlbs > 1)
|
||||
for (i = (PPC44x_LOW_SLOT-(pinned_tlbs-1)); i < PPC44x_LOW_SLOT; i++) {
|
||||
unsigned int phys_addr = (PPC44x_LOW_SLOT-i) * PPC44x_PIN_SIZE;
|
||||
unsigned int phys_addr = (PPC44x_LOW_SLOT-i) * PPC_PIN_SIZE;
|
||||
ppc44x_pin_tlb(i, phys_addr+PAGE_OFFSET, phys_addr);
|
||||
}
|
||||
|
||||
|
@ -46,26 +46,6 @@ unsigned long isa_io_base = 0;
|
||||
unsigned long isa_mem_base = 0;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
static int
|
||||
mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
|
||||
{
|
||||
static char pci_irq_table[][4] =
|
||||
/*
|
||||
* PCI IDSEL/INTPIN->INTLINE
|
||||
* A B C D
|
||||
*/
|
||||
{
|
||||
{PIRQB, PIRQC, PIRQD, PIRQA}, /* idsel 0x0e */
|
||||
{PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x0f */
|
||||
{PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x10 */
|
||||
};
|
||||
|
||||
const long min_idsel = 0x0e, max_idsel = 0x10, irqs_per_slot = 4;
|
||||
return PCI_IRQ_TABLE_LOOKUP;
|
||||
}
|
||||
#endif /* CONFIG_PCI */
|
||||
|
||||
/* ************************************************************************
|
||||
*
|
||||
* Setup the architecture
|
||||
@ -92,8 +72,6 @@ static void __init mpc834x_itx_setup_arch(void)
|
||||
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
|
||||
add_bridge(np);
|
||||
|
||||
ppc_md.pci_swizzle = common_swizzle;
|
||||
ppc_md.pci_map_irq = mpc83xx_map_irq;
|
||||
ppc_md.pci_exclude_device = mpc83xx_exclude_device;
|
||||
#endif
|
||||
|
||||
@ -106,25 +84,13 @@ static void __init mpc834x_itx_setup_arch(void)
|
||||
|
||||
void __init mpc834x_itx_init_IRQ(void)
|
||||
{
|
||||
u8 senses[8] = {
|
||||
0, /* EXT 0 */
|
||||
IRQ_SENSE_LEVEL, /* EXT 1 */
|
||||
IRQ_SENSE_LEVEL, /* EXT 2 */
|
||||
0, /* EXT 3 */
|
||||
#ifdef CONFIG_PCI
|
||||
IRQ_SENSE_LEVEL, /* EXT 4 */
|
||||
IRQ_SENSE_LEVEL, /* EXT 5 */
|
||||
IRQ_SENSE_LEVEL, /* EXT 6 */
|
||||
IRQ_SENSE_LEVEL, /* EXT 7 */
|
||||
#else
|
||||
0, /* EXT 4 */
|
||||
0, /* EXT 5 */
|
||||
0, /* EXT 6 */
|
||||
0, /* EXT 7 */
|
||||
#endif
|
||||
};
|
||||
struct device_node *np;
|
||||
|
||||
ipic_init(get_immrbase() + 0x00700, 0, 0, senses, 8);
|
||||
np = of_find_node_by_type(NULL, "ipic");
|
||||
if (!np)
|
||||
return;
|
||||
|
||||
ipic_init(np, 0);
|
||||
|
||||
/* Initialize the default interrupt mapping priorities,
|
||||
* in case the boot rom changed something on us.
|
||||
@ -153,4 +119,7 @@ define_machine(mpc834x_itx) {
|
||||
.time_init = mpc83xx_time_init,
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
.progress = udbg_progress,
|
||||
#ifdef CONFIG_PCI
|
||||
.pcibios_fixup = mpc83xx_pcibios_fixup,
|
||||
#endif
|
||||
};
|
||||
|
@ -43,33 +43,6 @@ unsigned long isa_io_base = 0;
|
||||
unsigned long isa_mem_base = 0;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
static int
|
||||
mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
|
||||
{
|
||||
static char pci_irq_table[][4] =
|
||||
/*
|
||||
* PCI IDSEL/INTPIN->INTLINE
|
||||
* A B C D
|
||||
*/
|
||||
{
|
||||
{PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x11 */
|
||||
{PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x12 */
|
||||
{PIRQD, PIRQA, PIRQB, PIRQC}, /* idsel 0x13 */
|
||||
{0, 0, 0, 0},
|
||||
{PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x15 */
|
||||
{PIRQD, PIRQA, PIRQB, PIRQC}, /* idsel 0x16 */
|
||||
{PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x17 */
|
||||
{PIRQB, PIRQC, PIRQD, PIRQA}, /* idsel 0x18 */
|
||||
{0, 0, 0, 0}, /* idsel 0x19 */
|
||||
{0, 0, 0, 0}, /* idsel 0x20 */
|
||||
};
|
||||
|
||||
const long min_idsel = 0x11, max_idsel = 0x20, irqs_per_slot = 4;
|
||||
return PCI_IRQ_TABLE_LOOKUP;
|
||||
}
|
||||
#endif /* CONFIG_PCI */
|
||||
|
||||
/* ************************************************************************
|
||||
*
|
||||
* Setup the architecture
|
||||
@ -96,8 +69,6 @@ static void __init mpc834x_sys_setup_arch(void)
|
||||
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
|
||||
add_bridge(np);
|
||||
|
||||
ppc_md.pci_swizzle = common_swizzle;
|
||||
ppc_md.pci_map_irq = mpc83xx_map_irq;
|
||||
ppc_md.pci_exclude_device = mpc83xx_exclude_device;
|
||||
#endif
|
||||
|
||||
@ -110,25 +81,13 @@ static void __init mpc834x_sys_setup_arch(void)
|
||||
|
||||
void __init mpc834x_sys_init_IRQ(void)
|
||||
{
|
||||
u8 senses[8] = {
|
||||
0, /* EXT 0 */
|
||||
IRQ_SENSE_LEVEL, /* EXT 1 */
|
||||
IRQ_SENSE_LEVEL, /* EXT 2 */
|
||||
0, /* EXT 3 */
|
||||
#ifdef CONFIG_PCI
|
||||
IRQ_SENSE_LEVEL, /* EXT 4 */
|
||||
IRQ_SENSE_LEVEL, /* EXT 5 */
|
||||
IRQ_SENSE_LEVEL, /* EXT 6 */
|
||||
IRQ_SENSE_LEVEL, /* EXT 7 */
|
||||
#else
|
||||
0, /* EXT 4 */
|
||||
0, /* EXT 5 */
|
||||
0, /* EXT 6 */
|
||||
0, /* EXT 7 */
|
||||
#endif
|
||||
};
|
||||
struct device_node *np;
|
||||
|
||||
ipic_init(get_immrbase() + 0x00700, 0, 0, senses, 8);
|
||||
np = of_find_node_by_type(NULL, "ipic");
|
||||
if (!np)
|
||||
return;
|
||||
|
||||
ipic_init(np, 0);
|
||||
|
||||
/* Initialize the default interrupt mapping priorities,
|
||||
* in case the boot rom changed something on us.
|
||||
@ -178,4 +137,7 @@ define_machine(mpc834x_sys) {
|
||||
.time_init = mpc83xx_time_init,
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
.progress = udbg_progress,
|
||||
#ifdef CONFIG_PCI
|
||||
.pcibios_fixup = mpc83xx_pcibios_fixup,
|
||||
#endif
|
||||
};
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
extern int add_bridge(struct device_node *dev);
|
||||
extern int mpc83xx_exclude_device(u_char bus, u_char devfn);
|
||||
extern void mpc83xx_pcibios_fixup(void);
|
||||
extern void mpc83xx_restart(char *cmd);
|
||||
extern long mpc83xx_time_init(void);
|
||||
|
||||
|
@ -45,6 +45,15 @@ int mpc83xx_exclude_device(u_char bus, u_char devfn)
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
void __init mpc83xx_pcibios_fixup(void)
|
||||
{
|
||||
struct pci_dev *dev = NULL;
|
||||
|
||||
/* map all the PCI irqs */
|
||||
for_each_pci_dev(dev)
|
||||
pci_read_irq_line(dev);
|
||||
}
|
||||
|
||||
int __init add_bridge(struct device_node *dev)
|
||||
{
|
||||
int len;
|
||||
|
@ -52,6 +52,7 @@ unsigned long pci_dram_offset = 0;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
@ -60,40 +61,43 @@ static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc,
|
||||
generic_handle_irq(cascade_irq, regs);
|
||||
desc->chip->eoi(irq);
|
||||
}
|
||||
#endif /* CONFIG_PCI */
|
||||
|
||||
void __init
|
||||
mpc86xx_hpcn_init_irq(void)
|
||||
{
|
||||
struct mpic *mpic1;
|
||||
struct device_node *np, *cascade_node = NULL;
|
||||
struct device_node *np;
|
||||
struct resource res;
|
||||
#ifdef CONFIG_PCI
|
||||
struct device_node *cascade_node = NULL;
|
||||
int cascade_irq;
|
||||
phys_addr_t openpic_paddr;
|
||||
#endif
|
||||
|
||||
/* Determine PIC address. */
|
||||
np = of_find_node_by_type(NULL, "open-pic");
|
||||
if (np == NULL)
|
||||
return;
|
||||
|
||||
/* Determine the Physical Address of the OpenPIC regs */
|
||||
openpic_paddr = get_immrbase() + MPC86xx_OPENPIC_OFFSET;
|
||||
of_address_to_resource(np, 0, &res);
|
||||
|
||||
/* Alloc mpic structure and per isu has 16 INT entries. */
|
||||
mpic1 = mpic_alloc(np, openpic_paddr,
|
||||
mpic1 = mpic_alloc(np, res.start,
|
||||
MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
|
||||
16, NR_IRQS - 4,
|
||||
" MPIC ");
|
||||
BUG_ON(mpic1 == NULL);
|
||||
|
||||
mpic_assign_isu(mpic1, 0, openpic_paddr + 0x10000);
|
||||
mpic_assign_isu(mpic1, 0, res.start + 0x10000);
|
||||
|
||||
/* 48 Internal Interrupts */
|
||||
mpic_assign_isu(mpic1, 1, openpic_paddr + 0x10200);
|
||||
mpic_assign_isu(mpic1, 2, openpic_paddr + 0x10400);
|
||||
mpic_assign_isu(mpic1, 3, openpic_paddr + 0x10600);
|
||||
mpic_assign_isu(mpic1, 1, res.start + 0x10200);
|
||||
mpic_assign_isu(mpic1, 2, res.start + 0x10400);
|
||||
mpic_assign_isu(mpic1, 3, res.start + 0x10600);
|
||||
|
||||
/* 16 External interrupts
|
||||
* Moving them from [0 - 15] to [64 - 79]
|
||||
*/
|
||||
mpic_assign_isu(mpic1, 4, openpic_paddr + 0x10000);
|
||||
mpic_assign_isu(mpic1, 4, res.start + 0x10000);
|
||||
|
||||
mpic_init(mpic1);
|
||||
|
||||
|
@ -188,7 +188,8 @@ int __init add_bridge(struct device_node *dev)
|
||||
|
||||
printk(KERN_INFO "Found MPC86xx PCIE host bridge at 0x%08lx. "
|
||||
"Firmware bus number: %d->%d\n",
|
||||
rsrc.start, hose->first_busno, hose->last_busno);
|
||||
(unsigned long) rsrc.start,
|
||||
hose->first_busno, hose->last_busno);
|
||||
|
||||
DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n",
|
||||
hose, hose->cfg_addr, hose->cfg_data);
|
||||
|
@ -80,6 +80,7 @@ config MPC7448HPC2
|
||||
select DEFAULT_UIMAGE
|
||||
select PPC_UDBG_16550
|
||||
select MPIC
|
||||
select MPIC_WEIRD
|
||||
help
|
||||
Select MPC7448HPC2 if configuring for Freescale MPC7448HPC2 (Taiga)
|
||||
platform
|
||||
|
@ -215,7 +215,7 @@ static void __init mpc7448_hpc2_init_IRQ(void)
|
||||
|
||||
mpic = mpic_alloc(tsi_pic, mpic_paddr,
|
||||
MPIC_PRIMARY | MPIC_BIG_ENDIAN | MPIC_WANTS_RESET |
|
||||
MPIC_SPV_EOI | MPIC_MOD_ID(MPIC_ID_TSI108),
|
||||
MPIC_SPV_EOI | MPIC_NO_PTHROU_DIS | MPIC_REGSET_TSI108,
|
||||
0, /* num_sources used */
|
||||
0, /* num_sources used */
|
||||
"Tsi108_PIC");
|
||||
|
@ -9,11 +9,11 @@ obj-$(CONFIG_BOOKE) += dcr.o
|
||||
obj-$(CONFIG_40x) += dcr.o
|
||||
obj-$(CONFIG_U3_DART) += dart_iommu.o
|
||||
obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
|
||||
obj-$(CONFIG_PPC_83xx) += ipic.o
|
||||
obj-$(CONFIG_FSL_SOC) += fsl_soc.o
|
||||
obj-$(CONFIG_PPC_TODC) += todc.o
|
||||
obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
|
||||
|
||||
ifeq ($(CONFIG_PPC_MERGE),y)
|
||||
obj-$(CONFIG_PPC_I8259) += i8259.o
|
||||
endif
|
||||
obj-$(CONFIG_PPC_83xx) += ipic.o
|
||||
endif
|
||||
|
@ -19,15 +19,18 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/sysdev.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/ipic.h>
|
||||
#include <asm/mpc83xx.h>
|
||||
|
||||
#include "ipic.h"
|
||||
|
||||
static struct ipic p_ipic;
|
||||
static struct ipic * primary_ipic;
|
||||
static DEFINE_SPINLOCK(ipic_lock);
|
||||
|
||||
static struct ipic_info ipic_info[] = {
|
||||
[9] = {
|
||||
@ -373,74 +376,220 @@ static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32
|
||||
out_be32(base + (reg >> 2), value);
|
||||
}
|
||||
|
||||
static inline struct ipic * ipic_from_irq(unsigned int irq)
|
||||
static inline struct ipic * ipic_from_irq(unsigned int virq)
|
||||
{
|
||||
return primary_ipic;
|
||||
}
|
||||
|
||||
static void ipic_enable_irq(unsigned int irq)
|
||||
#define ipic_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq)
|
||||
|
||||
static void ipic_unmask_irq(unsigned int virq)
|
||||
{
|
||||
struct ipic *ipic = ipic_from_irq(irq);
|
||||
unsigned int src = irq - ipic->irq_offset;
|
||||
struct ipic *ipic = ipic_from_irq(virq);
|
||||
unsigned int src = ipic_irq_to_hw(virq);
|
||||
unsigned long flags;
|
||||
u32 temp;
|
||||
|
||||
spin_lock_irqsave(&ipic_lock, flags);
|
||||
|
||||
temp = ipic_read(ipic->regs, ipic_info[src].mask);
|
||||
temp |= (1 << (31 - ipic_info[src].bit));
|
||||
ipic_write(ipic->regs, ipic_info[src].mask, temp);
|
||||
|
||||
spin_unlock_irqrestore(&ipic_lock, flags);
|
||||
}
|
||||
|
||||
static void ipic_disable_irq(unsigned int irq)
|
||||
static void ipic_mask_irq(unsigned int virq)
|
||||
{
|
||||
struct ipic *ipic = ipic_from_irq(irq);
|
||||
unsigned int src = irq - ipic->irq_offset;
|
||||
struct ipic *ipic = ipic_from_irq(virq);
|
||||
unsigned int src = ipic_irq_to_hw(virq);
|
||||
unsigned long flags;
|
||||
u32 temp;
|
||||
|
||||
spin_lock_irqsave(&ipic_lock, flags);
|
||||
|
||||
temp = ipic_read(ipic->regs, ipic_info[src].mask);
|
||||
temp &= ~(1 << (31 - ipic_info[src].bit));
|
||||
ipic_write(ipic->regs, ipic_info[src].mask, temp);
|
||||
|
||||
spin_unlock_irqrestore(&ipic_lock, flags);
|
||||
}
|
||||
|
||||
static void ipic_disable_irq_and_ack(unsigned int irq)
|
||||
static void ipic_ack_irq(unsigned int virq)
|
||||
{
|
||||
struct ipic *ipic = ipic_from_irq(irq);
|
||||
unsigned int src = irq - ipic->irq_offset;
|
||||
struct ipic *ipic = ipic_from_irq(virq);
|
||||
unsigned int src = ipic_irq_to_hw(virq);
|
||||
unsigned long flags;
|
||||
u32 temp;
|
||||
|
||||
ipic_disable_irq(irq);
|
||||
spin_lock_irqsave(&ipic_lock, flags);
|
||||
|
||||
temp = ipic_read(ipic->regs, ipic_info[src].pend);
|
||||
temp |= (1 << (31 - ipic_info[src].bit));
|
||||
ipic_write(ipic->regs, ipic_info[src].pend, temp);
|
||||
|
||||
spin_unlock_irqrestore(&ipic_lock, flags);
|
||||
}
|
||||
|
||||
static void ipic_end_irq(unsigned int irq)
|
||||
static void ipic_mask_irq_and_ack(unsigned int virq)
|
||||
{
|
||||
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
|
||||
ipic_enable_irq(irq);
|
||||
struct ipic *ipic = ipic_from_irq(virq);
|
||||
unsigned int src = ipic_irq_to_hw(virq);
|
||||
unsigned long flags;
|
||||
u32 temp;
|
||||
|
||||
spin_lock_irqsave(&ipic_lock, flags);
|
||||
|
||||
temp = ipic_read(ipic->regs, ipic_info[src].mask);
|
||||
temp &= ~(1 << (31 - ipic_info[src].bit));
|
||||
ipic_write(ipic->regs, ipic_info[src].mask, temp);
|
||||
|
||||
temp = ipic_read(ipic->regs, ipic_info[src].pend);
|
||||
temp |= (1 << (31 - ipic_info[src].bit));
|
||||
ipic_write(ipic->regs, ipic_info[src].pend, temp);
|
||||
|
||||
spin_unlock_irqrestore(&ipic_lock, flags);
|
||||
}
|
||||
|
||||
struct hw_interrupt_type ipic = {
|
||||
.typename = " IPIC ",
|
||||
.enable = ipic_enable_irq,
|
||||
.disable = ipic_disable_irq,
|
||||
.ack = ipic_disable_irq_and_ack,
|
||||
.end = ipic_end_irq,
|
||||
static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type)
|
||||
{
|
||||
struct ipic *ipic = ipic_from_irq(virq);
|
||||
unsigned int src = ipic_irq_to_hw(virq);
|
||||
struct irq_desc *desc = get_irq_desc(virq);
|
||||
unsigned int vold, vnew, edibit;
|
||||
|
||||
if (flow_type == IRQ_TYPE_NONE)
|
||||
flow_type = IRQ_TYPE_LEVEL_LOW;
|
||||
|
||||
/* ipic supports only low assertion and high-to-low change senses
|
||||
*/
|
||||
if (!(flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))) {
|
||||
printk(KERN_ERR "ipic: sense type 0x%x not supported\n",
|
||||
flow_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
|
||||
desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
|
||||
if (flow_type & IRQ_TYPE_LEVEL_LOW) {
|
||||
desc->status |= IRQ_LEVEL;
|
||||
set_irq_handler(virq, handle_level_irq);
|
||||
} else {
|
||||
set_irq_handler(virq, handle_edge_irq);
|
||||
}
|
||||
|
||||
/* only EXT IRQ senses are programmable on ipic
|
||||
* internal IRQ senses are LEVEL_LOW
|
||||
*/
|
||||
if (src == IPIC_IRQ_EXT0)
|
||||
edibit = 15;
|
||||
else
|
||||
if (src >= IPIC_IRQ_EXT1 && src <= IPIC_IRQ_EXT7)
|
||||
edibit = (14 - (src - IPIC_IRQ_EXT1));
|
||||
else
|
||||
return (flow_type & IRQ_TYPE_LEVEL_LOW) ? 0 : -EINVAL;
|
||||
|
||||
vold = ipic_read(ipic->regs, IPIC_SECNR);
|
||||
if ((flow_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_FALLING) {
|
||||
vnew = vold | (1 << edibit);
|
||||
} else {
|
||||
vnew = vold & ~(1 << edibit);
|
||||
}
|
||||
if (vold != vnew)
|
||||
ipic_write(ipic->regs, IPIC_SECNR, vnew);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_chip ipic_irq_chip = {
|
||||
.typename = " 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,
|
||||
};
|
||||
|
||||
void __init ipic_init(phys_addr_t phys_addr,
|
||||
unsigned int flags,
|
||||
unsigned int irq_offset,
|
||||
unsigned char *senses,
|
||||
unsigned int senses_count)
|
||||
static int ipic_host_match(struct irq_host *h, struct device_node *node)
|
||||
{
|
||||
u32 i, temp = 0;
|
||||
struct ipic *ipic = h->host_data;
|
||||
|
||||
primary_ipic = &p_ipic;
|
||||
primary_ipic->regs = ioremap(phys_addr, MPC83xx_IPIC_SIZE);
|
||||
/* Exact match, unless ipic node is NULL */
|
||||
return ipic->of_node == NULL || ipic->of_node == node;
|
||||
}
|
||||
|
||||
primary_ipic->irq_offset = irq_offset;
|
||||
static int ipic_host_map(struct irq_host *h, unsigned int virq,
|
||||
irq_hw_number_t hw)
|
||||
{
|
||||
struct ipic *ipic = h->host_data;
|
||||
struct irq_chip *chip;
|
||||
|
||||
ipic_write(primary_ipic->regs, IPIC_SICNR, 0x0);
|
||||
/* Default chip */
|
||||
chip = &ipic->hc_irq;
|
||||
|
||||
set_irq_chip_data(virq, ipic);
|
||||
set_irq_chip_and_handler(virq, chip, handle_level_irq);
|
||||
|
||||
/* Set default irq type */
|
||||
set_irq_type(virq, IRQ_TYPE_NONE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ipic_host_xlate(struct irq_host *h, struct device_node *ct,
|
||||
u32 *intspec, unsigned int intsize,
|
||||
irq_hw_number_t *out_hwirq, unsigned int *out_flags)
|
||||
|
||||
{
|
||||
/* interrupt sense values coming from the device tree equal either
|
||||
* LEVEL_LOW (low assertion) or EDGE_FALLING (high-to-low change)
|
||||
*/
|
||||
*out_hwirq = intspec[0];
|
||||
if (intsize > 1)
|
||||
*out_flags = intspec[1];
|
||||
else
|
||||
*out_flags = IRQ_TYPE_NONE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_host_ops ipic_host_ops = {
|
||||
.match = ipic_host_match,
|
||||
.map = ipic_host_map,
|
||||
.xlate = ipic_host_xlate,
|
||||
};
|
||||
|
||||
void __init ipic_init(struct device_node *node,
|
||||
unsigned int flags)
|
||||
{
|
||||
struct ipic *ipic;
|
||||
struct resource res;
|
||||
u32 temp = 0, ret;
|
||||
|
||||
ipic = alloc_bootmem(sizeof(struct ipic));
|
||||
if (ipic == NULL)
|
||||
return;
|
||||
|
||||
memset(ipic, 0, sizeof(struct ipic));
|
||||
ipic->of_node = node ? of_node_get(node) : NULL;
|
||||
|
||||
ipic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR,
|
||||
NR_IPIC_INTS,
|
||||
&ipic_host_ops, 0);
|
||||
if (ipic->irqhost == NULL) {
|
||||
of_node_put(node);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = of_address_to_resource(node, 0, &res);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
ipic->regs = ioremap(res.start, res.end - res.start + 1);
|
||||
|
||||
ipic->irqhost->host_data = ipic;
|
||||
ipic->hc_irq = ipic_irq_chip;
|
||||
|
||||
/* init hw */
|
||||
ipic_write(ipic->regs, IPIC_SICNR, 0x0);
|
||||
|
||||
/* default priority scheme is grouped. If spread mode is required
|
||||
* configure SICFR accordingly */
|
||||
@ -453,49 +602,35 @@ void __init ipic_init(phys_addr_t phys_addr,
|
||||
if (flags & IPIC_SPREADMODE_MIX_B)
|
||||
temp |= SICFR_MPSB;
|
||||
|
||||
ipic_write(primary_ipic->regs, IPIC_SICNR, temp);
|
||||
ipic_write(ipic->regs, IPIC_SICNR, temp);
|
||||
|
||||
/* handle MCP route */
|
||||
temp = 0;
|
||||
if (flags & IPIC_DISABLE_MCP_OUT)
|
||||
temp = SERCR_MCPR;
|
||||
ipic_write(primary_ipic->regs, IPIC_SERCR, temp);
|
||||
ipic_write(ipic->regs, IPIC_SERCR, temp);
|
||||
|
||||
/* handle routing of IRQ0 to MCP */
|
||||
temp = ipic_read(primary_ipic->regs, IPIC_SEMSR);
|
||||
temp = ipic_read(ipic->regs, IPIC_SEMSR);
|
||||
|
||||
if (flags & IPIC_IRQ0_MCP)
|
||||
temp |= SEMSR_SIRQ0;
|
||||
else
|
||||
temp &= ~SEMSR_SIRQ0;
|
||||
|
||||
ipic_write(primary_ipic->regs, IPIC_SEMSR, temp);
|
||||
ipic_write(ipic->regs, IPIC_SEMSR, temp);
|
||||
|
||||
for (i = 0 ; i < NR_IPIC_INTS ; i++) {
|
||||
irq_desc[i+irq_offset].chip = &ipic;
|
||||
irq_desc[i+irq_offset].status = IRQ_LEVEL;
|
||||
}
|
||||
primary_ipic = ipic;
|
||||
irq_set_default_host(primary_ipic->irqhost);
|
||||
|
||||
temp = 0;
|
||||
for (i = 0 ; i < senses_count ; i++) {
|
||||
if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) {
|
||||
temp |= 1 << (15 - i);
|
||||
if (i != 0)
|
||||
irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0;
|
||||
else
|
||||
irq_desc[irq_offset + MPC83xx_IRQ_EXT0].status = 0;
|
||||
}
|
||||
}
|
||||
ipic_write(primary_ipic->regs, IPIC_SECNR, temp);
|
||||
|
||||
printk ("IPIC (%d IRQ sources, %d External IRQs) at %p\n", NR_IPIC_INTS,
|
||||
senses_count, primary_ipic->regs);
|
||||
printk ("IPIC (%d IRQ sources) at %p\n", NR_IPIC_INTS,
|
||||
primary_ipic->regs);
|
||||
}
|
||||
|
||||
int ipic_set_priority(unsigned int irq, unsigned int priority)
|
||||
int ipic_set_priority(unsigned int virq, unsigned int priority)
|
||||
{
|
||||
struct ipic *ipic = ipic_from_irq(irq);
|
||||
unsigned int src = irq - ipic->irq_offset;
|
||||
struct ipic *ipic = ipic_from_irq(virq);
|
||||
unsigned int src = ipic_irq_to_hw(virq);
|
||||
u32 temp;
|
||||
|
||||
if (priority > 7)
|
||||
@ -520,10 +655,10 @@ int ipic_set_priority(unsigned int irq, unsigned int priority)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ipic_set_highest_priority(unsigned int irq)
|
||||
void ipic_set_highest_priority(unsigned int virq)
|
||||
{
|
||||
struct ipic *ipic = ipic_from_irq(irq);
|
||||
unsigned int src = irq - ipic->irq_offset;
|
||||
struct ipic *ipic = ipic_from_irq(virq);
|
||||
unsigned int src = ipic_irq_to_hw(virq);
|
||||
u32 temp;
|
||||
|
||||
temp = ipic_read(ipic->regs, IPIC_SICFR);
|
||||
@ -537,37 +672,10 @@ void ipic_set_highest_priority(unsigned int irq)
|
||||
|
||||
void ipic_set_default_priority(void)
|
||||
{
|
||||
ipic_set_priority(MPC83xx_IRQ_TSEC1_TX, 0);
|
||||
ipic_set_priority(MPC83xx_IRQ_TSEC1_RX, 1);
|
||||
ipic_set_priority(MPC83xx_IRQ_TSEC1_ERROR, 2);
|
||||
ipic_set_priority(MPC83xx_IRQ_TSEC2_TX, 3);
|
||||
ipic_set_priority(MPC83xx_IRQ_TSEC2_RX, 4);
|
||||
ipic_set_priority(MPC83xx_IRQ_TSEC2_ERROR, 5);
|
||||
ipic_set_priority(MPC83xx_IRQ_USB2_DR, 6);
|
||||
ipic_set_priority(MPC83xx_IRQ_USB2_MPH, 7);
|
||||
|
||||
ipic_set_priority(MPC83xx_IRQ_UART1, 0);
|
||||
ipic_set_priority(MPC83xx_IRQ_UART2, 1);
|
||||
ipic_set_priority(MPC83xx_IRQ_SEC2, 2);
|
||||
ipic_set_priority(MPC83xx_IRQ_IIC1, 5);
|
||||
ipic_set_priority(MPC83xx_IRQ_IIC2, 6);
|
||||
ipic_set_priority(MPC83xx_IRQ_SPI, 7);
|
||||
ipic_set_priority(MPC83xx_IRQ_RTC_SEC, 0);
|
||||
ipic_set_priority(MPC83xx_IRQ_PIT, 1);
|
||||
ipic_set_priority(MPC83xx_IRQ_PCI1, 2);
|
||||
ipic_set_priority(MPC83xx_IRQ_PCI2, 3);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT0, 4);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT1, 5);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT2, 6);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT3, 7);
|
||||
ipic_set_priority(MPC83xx_IRQ_RTC_ALR, 0);
|
||||
ipic_set_priority(MPC83xx_IRQ_MU, 1);
|
||||
ipic_set_priority(MPC83xx_IRQ_SBA, 2);
|
||||
ipic_set_priority(MPC83xx_IRQ_DMA, 3);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT4, 4);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT5, 5);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT6, 6);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT7, 7);
|
||||
ipic_write(primary_ipic->regs, IPIC_SIPRR_A, IPIC_SIPRR_A_DEFAULT);
|
||||
ipic_write(primary_ipic->regs, IPIC_SIPRR_D, IPIC_SIPRR_D_DEFAULT);
|
||||
ipic_write(primary_ipic->regs, IPIC_SMPRR_A, IPIC_SMPRR_A_DEFAULT);
|
||||
ipic_write(primary_ipic->regs, IPIC_SMPRR_B, IPIC_SMPRR_B_DEFAULT);
|
||||
}
|
||||
|
||||
void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq)
|
||||
@ -600,17 +708,20 @@ void ipic_clear_mcp_status(u32 mask)
|
||||
ipic_write(primary_ipic->regs, IPIC_SERMR, mask);
|
||||
}
|
||||
|
||||
/* Return an interrupt vector or -1 if no interrupt is pending. */
|
||||
int ipic_get_irq(struct pt_regs *regs)
|
||||
/* Return an interrupt vector or NO_IRQ if no interrupt is pending. */
|
||||
unsigned int ipic_get_irq(struct pt_regs *regs)
|
||||
{
|
||||
int irq;
|
||||
|
||||
irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & 0x7f;
|
||||
BUG_ON(primary_ipic == NULL);
|
||||
|
||||
#define IPIC_SIVCR_VECTOR_MASK 0x7f
|
||||
irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & IPIC_SIVCR_VECTOR_MASK;
|
||||
|
||||
if (irq == 0) /* 0 --> no irq is pending */
|
||||
irq = -1;
|
||||
return NO_IRQ;
|
||||
|
||||
return irq;
|
||||
return irq_linear_revmap(primary_ipic->irqhost, irq);
|
||||
}
|
||||
|
||||
static struct sysdev_class ipic_sysclass = {
|
||||
|
@ -15,7 +15,18 @@
|
||||
|
||||
#include <asm/ipic.h>
|
||||
|
||||
#define MPC83xx_IPIC_SIZE (0x00100)
|
||||
#define NR_IPIC_INTS 128
|
||||
|
||||
/* External IRQS */
|
||||
#define IPIC_IRQ_EXT0 48
|
||||
#define IPIC_IRQ_EXT1 17
|
||||
#define IPIC_IRQ_EXT7 23
|
||||
|
||||
/* Default Priority Registers */
|
||||
#define IPIC_SIPRR_A_DEFAULT 0x05309770
|
||||
#define IPIC_SIPRR_D_DEFAULT 0x05309770
|
||||
#define IPIC_SMPRR_A_DEFAULT 0x05309770
|
||||
#define IPIC_SMPRR_B_DEFAULT 0x05309770
|
||||
|
||||
/* System Global Interrupt Configuration Register */
|
||||
#define SICFR_IPSA 0x00010000
|
||||
@ -31,7 +42,15 @@
|
||||
|
||||
struct ipic {
|
||||
volatile u32 __iomem *regs;
|
||||
unsigned int irq_offset;
|
||||
|
||||
/* The remapper for this IPIC */
|
||||
struct irq_host *irqhost;
|
||||
|
||||
/* The "linux" controller struct */
|
||||
struct irq_chip hc_irq;
|
||||
|
||||
/* The device node of the interrupt controller */
|
||||
struct device_node *of_node;
|
||||
};
|
||||
|
||||
struct ipic_info {
|
||||
|
@ -54,6 +54,94 @@ static DEFINE_SPINLOCK(mpic_lock);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MPIC_WEIRD
|
||||
static u32 mpic_infos[][MPIC_IDX_END] = {
|
||||
[0] = { /* Original OpenPIC compatible MPIC */
|
||||
MPIC_GREG_BASE,
|
||||
MPIC_GREG_FEATURE_0,
|
||||
MPIC_GREG_GLOBAL_CONF_0,
|
||||
MPIC_GREG_VENDOR_ID,
|
||||
MPIC_GREG_IPI_VECTOR_PRI_0,
|
||||
MPIC_GREG_IPI_STRIDE,
|
||||
MPIC_GREG_SPURIOUS,
|
||||
MPIC_GREG_TIMER_FREQ,
|
||||
|
||||
MPIC_TIMER_BASE,
|
||||
MPIC_TIMER_STRIDE,
|
||||
MPIC_TIMER_CURRENT_CNT,
|
||||
MPIC_TIMER_BASE_CNT,
|
||||
MPIC_TIMER_VECTOR_PRI,
|
||||
MPIC_TIMER_DESTINATION,
|
||||
|
||||
MPIC_CPU_BASE,
|
||||
MPIC_CPU_STRIDE,
|
||||
MPIC_CPU_IPI_DISPATCH_0,
|
||||
MPIC_CPU_IPI_DISPATCH_STRIDE,
|
||||
MPIC_CPU_CURRENT_TASK_PRI,
|
||||
MPIC_CPU_WHOAMI,
|
||||
MPIC_CPU_INTACK,
|
||||
MPIC_CPU_EOI,
|
||||
|
||||
MPIC_IRQ_BASE,
|
||||
MPIC_IRQ_STRIDE,
|
||||
MPIC_IRQ_VECTOR_PRI,
|
||||
MPIC_VECPRI_VECTOR_MASK,
|
||||
MPIC_VECPRI_POLARITY_POSITIVE,
|
||||
MPIC_VECPRI_POLARITY_NEGATIVE,
|
||||
MPIC_VECPRI_SENSE_LEVEL,
|
||||
MPIC_VECPRI_SENSE_EDGE,
|
||||
MPIC_VECPRI_POLARITY_MASK,
|
||||
MPIC_VECPRI_SENSE_MASK,
|
||||
MPIC_IRQ_DESTINATION
|
||||
},
|
||||
[1] = { /* Tsi108/109 PIC */
|
||||
TSI108_GREG_BASE,
|
||||
TSI108_GREG_FEATURE_0,
|
||||
TSI108_GREG_GLOBAL_CONF_0,
|
||||
TSI108_GREG_VENDOR_ID,
|
||||
TSI108_GREG_IPI_VECTOR_PRI_0,
|
||||
TSI108_GREG_IPI_STRIDE,
|
||||
TSI108_GREG_SPURIOUS,
|
||||
TSI108_GREG_TIMER_FREQ,
|
||||
|
||||
TSI108_TIMER_BASE,
|
||||
TSI108_TIMER_STRIDE,
|
||||
TSI108_TIMER_CURRENT_CNT,
|
||||
TSI108_TIMER_BASE_CNT,
|
||||
TSI108_TIMER_VECTOR_PRI,
|
||||
TSI108_TIMER_DESTINATION,
|
||||
|
||||
TSI108_CPU_BASE,
|
||||
TSI108_CPU_STRIDE,
|
||||
TSI108_CPU_IPI_DISPATCH_0,
|
||||
TSI108_CPU_IPI_DISPATCH_STRIDE,
|
||||
TSI108_CPU_CURRENT_TASK_PRI,
|
||||
TSI108_CPU_WHOAMI,
|
||||
TSI108_CPU_INTACK,
|
||||
TSI108_CPU_EOI,
|
||||
|
||||
TSI108_IRQ_BASE,
|
||||
TSI108_IRQ_STRIDE,
|
||||
TSI108_IRQ_VECTOR_PRI,
|
||||
TSI108_VECPRI_VECTOR_MASK,
|
||||
TSI108_VECPRI_POLARITY_POSITIVE,
|
||||
TSI108_VECPRI_POLARITY_NEGATIVE,
|
||||
TSI108_VECPRI_SENSE_LEVEL,
|
||||
TSI108_VECPRI_SENSE_EDGE,
|
||||
TSI108_VECPRI_POLARITY_MASK,
|
||||
TSI108_VECPRI_SENSE_MASK,
|
||||
TSI108_IRQ_DESTINATION
|
||||
},
|
||||
};
|
||||
|
||||
#define MPIC_INFO(name) mpic->hw_set[MPIC_IDX_##name]
|
||||
|
||||
#else /* CONFIG_MPIC_WEIRD */
|
||||
|
||||
#define MPIC_INFO(name) MPIC_##name
|
||||
|
||||
#endif /* CONFIG_MPIC_WEIRD */
|
||||
|
||||
/*
|
||||
* Register accessor functions
|
||||
*/
|
||||
@ -80,7 +168,8 @@ static inline void _mpic_write(unsigned int be, volatile u32 __iomem *base,
|
||||
static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi)
|
||||
{
|
||||
unsigned int be = (mpic->flags & MPIC_BIG_ENDIAN) != 0;
|
||||
unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10);
|
||||
unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) +
|
||||
(ipi * MPIC_INFO(GREG_IPI_STRIDE));
|
||||
|
||||
if (mpic->flags & MPIC_BROKEN_IPI)
|
||||
be = !be;
|
||||
@ -89,7 +178,8 @@ static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi)
|
||||
|
||||
static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 value)
|
||||
{
|
||||
unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10);
|
||||
unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) +
|
||||
(ipi * MPIC_INFO(GREG_IPI_STRIDE));
|
||||
|
||||
_mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->gregs, offset, value);
|
||||
}
|
||||
@ -120,7 +210,7 @@ static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, unsigne
|
||||
unsigned int idx = src_no & mpic->isu_mask;
|
||||
|
||||
return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu],
|
||||
reg + (idx * MPIC_IRQ_STRIDE));
|
||||
reg + (idx * MPIC_INFO(IRQ_STRIDE)));
|
||||
}
|
||||
|
||||
static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no,
|
||||
@ -130,7 +220,7 @@ static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no,
|
||||
unsigned int idx = src_no & mpic->isu_mask;
|
||||
|
||||
_mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu],
|
||||
reg + (idx * MPIC_IRQ_STRIDE), value);
|
||||
reg + (idx * MPIC_INFO(IRQ_STRIDE)), value);
|
||||
}
|
||||
|
||||
#define mpic_read(b,r) _mpic_read(mpic->flags & MPIC_BIG_ENDIAN,(b),(r))
|
||||
@ -156,8 +246,8 @@ static void __init mpic_test_broken_ipi(struct mpic *mpic)
|
||||
{
|
||||
u32 r;
|
||||
|
||||
mpic_write(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0, MPIC_VECPRI_MASK);
|
||||
r = mpic_read(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0);
|
||||
mpic_write(mpic->gregs, MPIC_INFO(GREG_IPI_VECTOR_PRI_0), MPIC_VECPRI_MASK);
|
||||
r = mpic_read(mpic->gregs, MPIC_INFO(GREG_IPI_VECTOR_PRI_0));
|
||||
|
||||
if (r == le32_to_cpu(MPIC_VECPRI_MASK)) {
|
||||
printk(KERN_INFO "mpic: Detected reversed IPI registers\n");
|
||||
@ -394,8 +484,8 @@ static inline struct mpic * mpic_from_irq(unsigned int irq)
|
||||
/* Send an EOI */
|
||||
static inline void mpic_eoi(struct mpic *mpic)
|
||||
{
|
||||
mpic_cpu_write(MPIC_CPU_EOI, 0);
|
||||
(void)mpic_cpu_read(MPIC_CPU_WHOAMI);
|
||||
mpic_cpu_write(MPIC_INFO(CPU_EOI), 0);
|
||||
(void)mpic_cpu_read(MPIC_INFO(CPU_WHOAMI));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
@ -419,8 +509,8 @@ static void mpic_unmask_irq(unsigned int irq)
|
||||
|
||||
DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src);
|
||||
|
||||
mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
|
||||
mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) &
|
||||
mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
|
||||
mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) &
|
||||
~MPIC_VECPRI_MASK);
|
||||
/* make sure mask gets to controller before we return to user */
|
||||
do {
|
||||
@ -428,7 +518,7 @@ static void mpic_unmask_irq(unsigned int irq)
|
||||
printk(KERN_ERR "mpic_enable_irq timeout\n");
|
||||
break;
|
||||
}
|
||||
} while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK);
|
||||
} while(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK);
|
||||
}
|
||||
|
||||
static void mpic_mask_irq(unsigned int irq)
|
||||
@ -439,8 +529,8 @@ static void mpic_mask_irq(unsigned int irq)
|
||||
|
||||
DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src);
|
||||
|
||||
mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
|
||||
mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) |
|
||||
mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
|
||||
mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) |
|
||||
MPIC_VECPRI_MASK);
|
||||
|
||||
/* make sure mask gets to controller before we return to user */
|
||||
@ -449,7 +539,7 @@ static void mpic_mask_irq(unsigned int irq)
|
||||
printk(KERN_ERR "mpic_enable_irq timeout\n");
|
||||
break;
|
||||
}
|
||||
} while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK));
|
||||
} while(!(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK));
|
||||
}
|
||||
|
||||
static void mpic_end_irq(unsigned int irq)
|
||||
@ -560,24 +650,28 @@ static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask)
|
||||
|
||||
cpus_and(tmp, cpumask, cpu_online_map);
|
||||
|
||||
mpic_irq_write(src, MPIC_IRQ_DESTINATION,
|
||||
mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION),
|
||||
mpic_physmask(cpus_addr(tmp)[0]));
|
||||
}
|
||||
|
||||
static unsigned int mpic_type_to_vecpri(unsigned int type)
|
||||
static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type)
|
||||
{
|
||||
/* Now convert sense value */
|
||||
switch(type & IRQ_TYPE_SENSE_MASK) {
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
return MPIC_VECPRI_SENSE_EDGE | MPIC_VECPRI_POLARITY_POSITIVE;
|
||||
return MPIC_INFO(VECPRI_SENSE_EDGE) |
|
||||
MPIC_INFO(VECPRI_POLARITY_POSITIVE);
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
return MPIC_VECPRI_SENSE_EDGE | MPIC_VECPRI_POLARITY_NEGATIVE;
|
||||
return MPIC_INFO(VECPRI_SENSE_EDGE) |
|
||||
MPIC_INFO(VECPRI_POLARITY_NEGATIVE);
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
return MPIC_VECPRI_SENSE_LEVEL | MPIC_VECPRI_POLARITY_POSITIVE;
|
||||
return MPIC_INFO(VECPRI_SENSE_LEVEL) |
|
||||
MPIC_INFO(VECPRI_POLARITY_POSITIVE);
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
default:
|
||||
return MPIC_VECPRI_SENSE_LEVEL | MPIC_VECPRI_POLARITY_NEGATIVE;
|
||||
return MPIC_INFO(VECPRI_SENSE_LEVEL) |
|
||||
MPIC_INFO(VECPRI_POLARITY_NEGATIVE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -609,13 +703,14 @@ static int mpic_set_irq_type(unsigned int virq, unsigned int flow_type)
|
||||
vecpri = MPIC_VECPRI_POLARITY_POSITIVE |
|
||||
MPIC_VECPRI_SENSE_EDGE;
|
||||
else
|
||||
vecpri = mpic_type_to_vecpri(flow_type);
|
||||
vecpri = mpic_type_to_vecpri(mpic, flow_type);
|
||||
|
||||
vold = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI);
|
||||
vnew = vold & ~(MPIC_VECPRI_POLARITY_MASK | MPIC_VECPRI_SENSE_MASK);
|
||||
vold = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI));
|
||||
vnew = vold & ~(MPIC_INFO(VECPRI_POLARITY_MASK) |
|
||||
MPIC_INFO(VECPRI_SENSE_MASK));
|
||||
vnew |= vecpri;
|
||||
if (vold != vnew)
|
||||
mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI, vnew);
|
||||
mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vnew);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -798,17 +893,22 @@ struct mpic * __init mpic_alloc(struct device_node *node,
|
||||
mpic->irq_count = irq_count;
|
||||
mpic->num_sources = 0; /* so far */
|
||||
|
||||
#ifdef CONFIG_MPIC_WEIRD
|
||||
mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)];
|
||||
#endif
|
||||
|
||||
/* Map the global registers */
|
||||
mpic->gregs = ioremap(phys_addr + MPIC_GREG_BASE, 0x1000);
|
||||
mpic->tmregs = mpic->gregs + ((MPIC_TIMER_BASE - MPIC_GREG_BASE) >> 2);
|
||||
mpic->gregs = ioremap(phys_addr + MPIC_INFO(GREG_BASE), 0x1000);
|
||||
mpic->tmregs = mpic->gregs +
|
||||
((MPIC_INFO(TIMER_BASE) - MPIC_INFO(GREG_BASE)) >> 2);
|
||||
BUG_ON(mpic->gregs == NULL);
|
||||
|
||||
/* Reset */
|
||||
if (flags & MPIC_WANTS_RESET) {
|
||||
mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0,
|
||||
mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
|
||||
mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
|
||||
mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
|
||||
| MPIC_GREG_GCONF_RESET);
|
||||
while( mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
|
||||
while( mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
|
||||
& MPIC_GREG_GCONF_RESET)
|
||||
mb();
|
||||
}
|
||||
@ -817,7 +917,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
|
||||
* MPICs, num sources as well. On ISU MPICs, sources are counted
|
||||
* as ISUs are added
|
||||
*/
|
||||
reg = mpic_read(mpic->gregs, MPIC_GREG_FEATURE_0);
|
||||
reg = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0));
|
||||
mpic->num_cpus = ((reg & MPIC_GREG_FEATURE_LAST_CPU_MASK)
|
||||
>> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1;
|
||||
if (isu_size == 0)
|
||||
@ -826,16 +926,16 @@ struct mpic * __init mpic_alloc(struct device_node *node,
|
||||
|
||||
/* Map the per-CPU registers */
|
||||
for (i = 0; i < mpic->num_cpus; i++) {
|
||||
mpic->cpuregs[i] = ioremap(phys_addr + MPIC_CPU_BASE +
|
||||
i * MPIC_CPU_STRIDE, 0x1000);
|
||||
mpic->cpuregs[i] = ioremap(phys_addr + MPIC_INFO(CPU_BASE) +
|
||||
i * MPIC_INFO(CPU_STRIDE), 0x1000);
|
||||
BUG_ON(mpic->cpuregs[i] == NULL);
|
||||
}
|
||||
|
||||
/* Initialize main ISU if none provided */
|
||||
if (mpic->isu_size == 0) {
|
||||
mpic->isu_size = mpic->num_sources;
|
||||
mpic->isus[0] = ioremap(phys_addr + MPIC_IRQ_BASE,
|
||||
MPIC_IRQ_STRIDE * mpic->isu_size);
|
||||
mpic->isus[0] = ioremap(phys_addr + MPIC_INFO(IRQ_BASE),
|
||||
MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
|
||||
BUG_ON(mpic->isus[0] == NULL);
|
||||
}
|
||||
mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1);
|
||||
@ -879,7 +979,8 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
|
||||
|
||||
BUG_ON(isu_num >= MPIC_MAX_ISU);
|
||||
|
||||
mpic->isus[isu_num] = ioremap(phys_addr, MPIC_IRQ_STRIDE * mpic->isu_size);
|
||||
mpic->isus[isu_num] = ioremap(phys_addr,
|
||||
MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
|
||||
if ((isu_first + mpic->isu_size) > mpic->num_sources)
|
||||
mpic->num_sources = isu_first + mpic->isu_size;
|
||||
}
|
||||
@ -904,14 +1005,16 @@ void __init mpic_init(struct mpic *mpic)
|
||||
printk(KERN_INFO "mpic: Initializing for %d sources\n", mpic->num_sources);
|
||||
|
||||
/* Set current processor priority to max */
|
||||
mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf);
|
||||
mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0xf);
|
||||
|
||||
/* Initialize timers: just disable them all */
|
||||
for (i = 0; i < 4; i++) {
|
||||
mpic_write(mpic->tmregs,
|
||||
i * MPIC_TIMER_STRIDE + MPIC_TIMER_DESTINATION, 0);
|
||||
i * MPIC_INFO(TIMER_STRIDE) +
|
||||
MPIC_INFO(TIMER_DESTINATION), 0);
|
||||
mpic_write(mpic->tmregs,
|
||||
i * MPIC_TIMER_STRIDE + MPIC_TIMER_VECTOR_PRI,
|
||||
i * MPIC_INFO(TIMER_STRIDE) +
|
||||
MPIC_INFO(TIMER_VECTOR_PRI),
|
||||
MPIC_VECPRI_MASK |
|
||||
(MPIC_VEC_TIMER_0 + i));
|
||||
}
|
||||
@ -940,21 +1043,22 @@ void __init mpic_init(struct mpic *mpic)
|
||||
(8 << MPIC_VECPRI_PRIORITY_SHIFT);
|
||||
|
||||
/* init hw */
|
||||
mpic_irq_write(i, MPIC_IRQ_VECTOR_PRI, vecpri);
|
||||
mpic_irq_write(i, MPIC_IRQ_DESTINATION,
|
||||
mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
|
||||
mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION),
|
||||
1 << hard_smp_processor_id());
|
||||
}
|
||||
|
||||
/* Init spurrious vector */
|
||||
mpic_write(mpic->gregs, MPIC_GREG_SPURIOUS, MPIC_VEC_SPURRIOUS);
|
||||
mpic_write(mpic->gregs, MPIC_INFO(GREG_SPURIOUS), MPIC_VEC_SPURRIOUS);
|
||||
|
||||
/* Disable 8259 passthrough */
|
||||
mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0,
|
||||
mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
|
||||
| MPIC_GREG_GCONF_8259_PTHROU_DIS);
|
||||
/* Disable 8259 passthrough, if supported */
|
||||
if (!(mpic->flags & MPIC_NO_PTHROU_DIS))
|
||||
mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
|
||||
mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
|
||||
| MPIC_GREG_GCONF_8259_PTHROU_DIS);
|
||||
|
||||
/* Set current processor priority to 0 */
|
||||
mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0);
|
||||
mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0);
|
||||
}
|
||||
|
||||
void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio)
|
||||
@ -997,9 +1101,9 @@ void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
|
||||
mpic_ipi_write(src - MPIC_VEC_IPI_0,
|
||||
reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
|
||||
} else {
|
||||
reg = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI)
|
||||
reg = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI))
|
||||
& ~MPIC_VECPRI_PRIORITY_MASK;
|
||||
mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
|
||||
mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
|
||||
reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
|
||||
}
|
||||
spin_unlock_irqrestore(&mpic_lock, flags);
|
||||
@ -1017,7 +1121,7 @@ unsigned int mpic_irq_get_priority(unsigned int irq)
|
||||
if (is_ipi)
|
||||
reg = mpic_ipi_read(src = MPIC_VEC_IPI_0);
|
||||
else
|
||||
reg = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI);
|
||||
reg = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI));
|
||||
spin_unlock_irqrestore(&mpic_lock, flags);
|
||||
return (reg & MPIC_VECPRI_PRIORITY_MASK) >> MPIC_VECPRI_PRIORITY_SHIFT;
|
||||
}
|
||||
@ -1043,12 +1147,12 @@ void mpic_setup_this_cpu(void)
|
||||
*/
|
||||
if (distribute_irqs) {
|
||||
for (i = 0; i < mpic->num_sources ; i++)
|
||||
mpic_irq_write(i, MPIC_IRQ_DESTINATION,
|
||||
mpic_irq_read(i, MPIC_IRQ_DESTINATION) | msk);
|
||||
mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION),
|
||||
mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION)) | msk);
|
||||
}
|
||||
|
||||
/* Set current processor priority to 0 */
|
||||
mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0);
|
||||
mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0);
|
||||
|
||||
spin_unlock_irqrestore(&mpic_lock, flags);
|
||||
#endif /* CONFIG_SMP */
|
||||
@ -1058,7 +1162,7 @@ int mpic_cpu_get_priority(void)
|
||||
{
|
||||
struct mpic *mpic = mpic_primary;
|
||||
|
||||
return mpic_cpu_read(MPIC_CPU_CURRENT_TASK_PRI);
|
||||
return mpic_cpu_read(MPIC_INFO(CPU_CURRENT_TASK_PRI));
|
||||
}
|
||||
|
||||
void mpic_cpu_set_priority(int prio)
|
||||
@ -1066,7 +1170,7 @@ void mpic_cpu_set_priority(int prio)
|
||||
struct mpic *mpic = mpic_primary;
|
||||
|
||||
prio &= MPIC_CPU_TASKPRI_MASK;
|
||||
mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, prio);
|
||||
mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), prio);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1088,11 +1192,11 @@ void mpic_teardown_this_cpu(int secondary)
|
||||
|
||||
/* let the mpic know we don't want intrs. */
|
||||
for (i = 0; i < mpic->num_sources ; i++)
|
||||
mpic_irq_write(i, MPIC_IRQ_DESTINATION,
|
||||
mpic_irq_read(i, MPIC_IRQ_DESTINATION) & ~msk);
|
||||
mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION),
|
||||
mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION)) & ~msk);
|
||||
|
||||
/* Set current processor priority to max */
|
||||
mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf);
|
||||
mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0xf);
|
||||
|
||||
spin_unlock_irqrestore(&mpic_lock, flags);
|
||||
}
|
||||
@ -1108,7 +1212,8 @@ void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask)
|
||||
DBG("%s: send_ipi(ipi_no: %d)\n", mpic->name, ipi_no);
|
||||
#endif
|
||||
|
||||
mpic_cpu_write(MPIC_CPU_IPI_DISPATCH_0 + ipi_no * 0x10,
|
||||
mpic_cpu_write(MPIC_INFO(CPU_IPI_DISPATCH_0) +
|
||||
ipi_no * MPIC_INFO(CPU_IPI_DISPATCH_STRIDE),
|
||||
mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0]));
|
||||
}
|
||||
|
||||
@ -1116,7 +1221,7 @@ unsigned int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs)
|
||||
{
|
||||
u32 src;
|
||||
|
||||
src = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK;
|
||||
src = mpic_cpu_read(MPIC_INFO(CPU_INTACK)) & MPIC_INFO(VECPRI_VECTOR_MASK);
|
||||
#ifdef DEBUG_LOW
|
||||
DBG("%s: get_one_irq(): %d\n", mpic->name, src);
|
||||
#endif
|
||||
|
@ -47,8 +47,9 @@ void __devinit
|
||||
smp_generic_take_timebase( void )
|
||||
{
|
||||
int cmd, tbl, tbu;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_disable();
|
||||
local_irq_save(flags);
|
||||
while( !running )
|
||||
;
|
||||
rmb();
|
||||
@ -64,7 +65,7 @@ smp_generic_take_timebase( void )
|
||||
tbu = tbsync->tbu;
|
||||
tbsync->ack = 0;
|
||||
if( cmd == kExit )
|
||||
return;
|
||||
break;
|
||||
|
||||
if( cmd == kSetAndTest ) {
|
||||
while( tbsync->handshake )
|
||||
@ -77,7 +78,7 @@ smp_generic_take_timebase( void )
|
||||
}
|
||||
enter_contest( tbsync->mark, -1 );
|
||||
}
|
||||
local_irq_enable();
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static int __devinit
|
||||
|
@ -93,7 +93,7 @@ obj-$(CONFIG_PCI) += pci_auto.o
|
||||
endif
|
||||
obj-$(CONFIG_RAPIDIO) += ppc85xx_rio.o
|
||||
obj-$(CONFIG_83xx) += ppc83xx_setup.o ppc_sys.o \
|
||||
mpc83xx_sys.o mpc83xx_devices.o
|
||||
mpc83xx_sys.o mpc83xx_devices.o ipic.o
|
||||
ifeq ($(CONFIG_83xx),y)
|
||||
obj-$(CONFIG_PCI) += pci_auto.o
|
||||
endif
|
||||
|
646
arch/ppc/syslib/ipic.c
Normal file
646
arch/ppc/syslib/ipic.c
Normal file
@ -0,0 +1,646 @@
|
||||
/*
|
||||
* include/asm-ppc/ipic.c
|
||||
*
|
||||
* IPIC routines implementations.
|
||||
*
|
||||
* Copyright 2005 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
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/sysdev.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/ipic.h>
|
||||
#include <asm/mpc83xx.h>
|
||||
|
||||
#include "ipic.h"
|
||||
|
||||
static struct ipic p_ipic;
|
||||
static struct ipic * primary_ipic;
|
||||
|
||||
static struct ipic_info ipic_info[] = {
|
||||
[9] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_H,
|
||||
.prio = IPIC_SIPRR_D,
|
||||
.force = IPIC_SIFCR_H,
|
||||
.bit = 24,
|
||||
.prio_mask = 0,
|
||||
},
|
||||
[10] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_H,
|
||||
.prio = IPIC_SIPRR_D,
|
||||
.force = IPIC_SIFCR_H,
|
||||
.bit = 25,
|
||||
.prio_mask = 1,
|
||||
},
|
||||
[11] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_H,
|
||||
.prio = IPIC_SIPRR_D,
|
||||
.force = IPIC_SIFCR_H,
|
||||
.bit = 26,
|
||||
.prio_mask = 2,
|
||||
},
|
||||
[14] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_H,
|
||||
.prio = IPIC_SIPRR_D,
|
||||
.force = IPIC_SIFCR_H,
|
||||
.bit = 29,
|
||||
.prio_mask = 5,
|
||||
},
|
||||
[15] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_H,
|
||||
.prio = IPIC_SIPRR_D,
|
||||
.force = IPIC_SIFCR_H,
|
||||
.bit = 30,
|
||||
.prio_mask = 6,
|
||||
},
|
||||
[16] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_H,
|
||||
.prio = IPIC_SIPRR_D,
|
||||
.force = IPIC_SIFCR_H,
|
||||
.bit = 31,
|
||||
.prio_mask = 7,
|
||||
},
|
||||
[17] = {
|
||||
.pend = IPIC_SEPNR,
|
||||
.mask = IPIC_SEMSR,
|
||||
.prio = IPIC_SMPRR_A,
|
||||
.force = IPIC_SEFCR,
|
||||
.bit = 1,
|
||||
.prio_mask = 5,
|
||||
},
|
||||
[18] = {
|
||||
.pend = IPIC_SEPNR,
|
||||
.mask = IPIC_SEMSR,
|
||||
.prio = IPIC_SMPRR_A,
|
||||
.force = IPIC_SEFCR,
|
||||
.bit = 2,
|
||||
.prio_mask = 6,
|
||||
},
|
||||
[19] = {
|
||||
.pend = IPIC_SEPNR,
|
||||
.mask = IPIC_SEMSR,
|
||||
.prio = IPIC_SMPRR_A,
|
||||
.force = IPIC_SEFCR,
|
||||
.bit = 3,
|
||||
.prio_mask = 7,
|
||||
},
|
||||
[20] = {
|
||||
.pend = IPIC_SEPNR,
|
||||
.mask = IPIC_SEMSR,
|
||||
.prio = IPIC_SMPRR_B,
|
||||
.force = IPIC_SEFCR,
|
||||
.bit = 4,
|
||||
.prio_mask = 4,
|
||||
},
|
||||
[21] = {
|
||||
.pend = IPIC_SEPNR,
|
||||
.mask = IPIC_SEMSR,
|
||||
.prio = IPIC_SMPRR_B,
|
||||
.force = IPIC_SEFCR,
|
||||
.bit = 5,
|
||||
.prio_mask = 5,
|
||||
},
|
||||
[22] = {
|
||||
.pend = IPIC_SEPNR,
|
||||
.mask = IPIC_SEMSR,
|
||||
.prio = IPIC_SMPRR_B,
|
||||
.force = IPIC_SEFCR,
|
||||
.bit = 6,
|
||||
.prio_mask = 6,
|
||||
},
|
||||
[23] = {
|
||||
.pend = IPIC_SEPNR,
|
||||
.mask = IPIC_SEMSR,
|
||||
.prio = IPIC_SMPRR_B,
|
||||
.force = IPIC_SEFCR,
|
||||
.bit = 7,
|
||||
.prio_mask = 7,
|
||||
},
|
||||
[32] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_H,
|
||||
.prio = IPIC_SIPRR_A,
|
||||
.force = IPIC_SIFCR_H,
|
||||
.bit = 0,
|
||||
.prio_mask = 0,
|
||||
},
|
||||
[33] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_H,
|
||||
.prio = IPIC_SIPRR_A,
|
||||
.force = IPIC_SIFCR_H,
|
||||
.bit = 1,
|
||||
.prio_mask = 1,
|
||||
},
|
||||
[34] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_H,
|
||||
.prio = IPIC_SIPRR_A,
|
||||
.force = IPIC_SIFCR_H,
|
||||
.bit = 2,
|
||||
.prio_mask = 2,
|
||||
},
|
||||
[35] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_H,
|
||||
.prio = IPIC_SIPRR_A,
|
||||
.force = IPIC_SIFCR_H,
|
||||
.bit = 3,
|
||||
.prio_mask = 3,
|
||||
},
|
||||
[36] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_H,
|
||||
.prio = IPIC_SIPRR_A,
|
||||
.force = IPIC_SIFCR_H,
|
||||
.bit = 4,
|
||||
.prio_mask = 4,
|
||||
},
|
||||
[37] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_H,
|
||||
.prio = IPIC_SIPRR_A,
|
||||
.force = IPIC_SIFCR_H,
|
||||
.bit = 5,
|
||||
.prio_mask = 5,
|
||||
},
|
||||
[38] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_H,
|
||||
.prio = IPIC_SIPRR_A,
|
||||
.force = IPIC_SIFCR_H,
|
||||
.bit = 6,
|
||||
.prio_mask = 6,
|
||||
},
|
||||
[39] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_H,
|
||||
.prio = IPIC_SIPRR_A,
|
||||
.force = IPIC_SIFCR_H,
|
||||
.bit = 7,
|
||||
.prio_mask = 7,
|
||||
},
|
||||
[48] = {
|
||||
.pend = IPIC_SEPNR,
|
||||
.mask = IPIC_SEMSR,
|
||||
.prio = IPIC_SMPRR_A,
|
||||
.force = IPIC_SEFCR,
|
||||
.bit = 0,
|
||||
.prio_mask = 4,
|
||||
},
|
||||
[64] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = IPIC_SMPRR_A,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 0,
|
||||
.prio_mask = 0,
|
||||
},
|
||||
[65] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = IPIC_SMPRR_A,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 1,
|
||||
.prio_mask = 1,
|
||||
},
|
||||
[66] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = IPIC_SMPRR_A,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 2,
|
||||
.prio_mask = 2,
|
||||
},
|
||||
[67] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = IPIC_SMPRR_A,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 3,
|
||||
.prio_mask = 3,
|
||||
},
|
||||
[68] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = IPIC_SMPRR_B,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 4,
|
||||
.prio_mask = 0,
|
||||
},
|
||||
[69] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = IPIC_SMPRR_B,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 5,
|
||||
.prio_mask = 1,
|
||||
},
|
||||
[70] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = IPIC_SMPRR_B,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 6,
|
||||
.prio_mask = 2,
|
||||
},
|
||||
[71] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = IPIC_SMPRR_B,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 7,
|
||||
.prio_mask = 3,
|
||||
},
|
||||
[72] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = 0,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 8,
|
||||
},
|
||||
[73] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = 0,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 9,
|
||||
},
|
||||
[74] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = 0,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 10,
|
||||
},
|
||||
[75] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = 0,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 11,
|
||||
},
|
||||
[76] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = 0,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 12,
|
||||
},
|
||||
[77] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = 0,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 13,
|
||||
},
|
||||
[78] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = 0,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 14,
|
||||
},
|
||||
[79] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = 0,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 15,
|
||||
},
|
||||
[80] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = 0,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 16,
|
||||
},
|
||||
[84] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = 0,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 20,
|
||||
},
|
||||
[85] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = 0,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 21,
|
||||
},
|
||||
[90] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = 0,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 26,
|
||||
},
|
||||
[91] = {
|
||||
.pend = IPIC_SIPNR_H,
|
||||
.mask = IPIC_SIMSR_L,
|
||||
.prio = 0,
|
||||
.force = IPIC_SIFCR_L,
|
||||
.bit = 27,
|
||||
},
|
||||
};
|
||||
|
||||
static inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg)
|
||||
{
|
||||
return in_be32(base + (reg >> 2));
|
||||
}
|
||||
|
||||
static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value)
|
||||
{
|
||||
out_be32(base + (reg >> 2), value);
|
||||
}
|
||||
|
||||
static inline struct ipic * ipic_from_irq(unsigned int irq)
|
||||
{
|
||||
return primary_ipic;
|
||||
}
|
||||
|
||||
static void ipic_enable_irq(unsigned int irq)
|
||||
{
|
||||
struct ipic *ipic = ipic_from_irq(irq);
|
||||
unsigned int src = irq - ipic->irq_offset;
|
||||
u32 temp;
|
||||
|
||||
temp = ipic_read(ipic->regs, ipic_info[src].mask);
|
||||
temp |= (1 << (31 - ipic_info[src].bit));
|
||||
ipic_write(ipic->regs, ipic_info[src].mask, temp);
|
||||
}
|
||||
|
||||
static void ipic_disable_irq(unsigned int irq)
|
||||
{
|
||||
struct ipic *ipic = ipic_from_irq(irq);
|
||||
unsigned int src = irq - ipic->irq_offset;
|
||||
u32 temp;
|
||||
|
||||
temp = ipic_read(ipic->regs, ipic_info[src].mask);
|
||||
temp &= ~(1 << (31 - ipic_info[src].bit));
|
||||
ipic_write(ipic->regs, ipic_info[src].mask, temp);
|
||||
}
|
||||
|
||||
static void ipic_disable_irq_and_ack(unsigned int irq)
|
||||
{
|
||||
struct ipic *ipic = ipic_from_irq(irq);
|
||||
unsigned int src = irq - ipic->irq_offset;
|
||||
u32 temp;
|
||||
|
||||
ipic_disable_irq(irq);
|
||||
|
||||
temp = ipic_read(ipic->regs, ipic_info[src].pend);
|
||||
temp |= (1 << (31 - ipic_info[src].bit));
|
||||
ipic_write(ipic->regs, ipic_info[src].pend, temp);
|
||||
}
|
||||
|
||||
static void ipic_end_irq(unsigned int irq)
|
||||
{
|
||||
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
|
||||
ipic_enable_irq(irq);
|
||||
}
|
||||
|
||||
struct hw_interrupt_type ipic = {
|
||||
.typename = " IPIC ",
|
||||
.enable = ipic_enable_irq,
|
||||
.disable = ipic_disable_irq,
|
||||
.ack = ipic_disable_irq_and_ack,
|
||||
.end = ipic_end_irq,
|
||||
};
|
||||
|
||||
void __init ipic_init(phys_addr_t phys_addr,
|
||||
unsigned int flags,
|
||||
unsigned int irq_offset,
|
||||
unsigned char *senses,
|
||||
unsigned int senses_count)
|
||||
{
|
||||
u32 i, temp = 0;
|
||||
|
||||
primary_ipic = &p_ipic;
|
||||
primary_ipic->regs = ioremap(phys_addr, MPC83xx_IPIC_SIZE);
|
||||
|
||||
primary_ipic->irq_offset = irq_offset;
|
||||
|
||||
ipic_write(primary_ipic->regs, IPIC_SICNR, 0x0);
|
||||
|
||||
/* default priority scheme is grouped. If spread mode is required
|
||||
* configure SICFR accordingly */
|
||||
if (flags & IPIC_SPREADMODE_GRP_A)
|
||||
temp |= SICFR_IPSA;
|
||||
if (flags & IPIC_SPREADMODE_GRP_D)
|
||||
temp |= SICFR_IPSD;
|
||||
if (flags & IPIC_SPREADMODE_MIX_A)
|
||||
temp |= SICFR_MPSA;
|
||||
if (flags & IPIC_SPREADMODE_MIX_B)
|
||||
temp |= SICFR_MPSB;
|
||||
|
||||
ipic_write(primary_ipic->regs, IPIC_SICNR, temp);
|
||||
|
||||
/* handle MCP route */
|
||||
temp = 0;
|
||||
if (flags & IPIC_DISABLE_MCP_OUT)
|
||||
temp = SERCR_MCPR;
|
||||
ipic_write(primary_ipic->regs, IPIC_SERCR, temp);
|
||||
|
||||
/* handle routing of IRQ0 to MCP */
|
||||
temp = ipic_read(primary_ipic->regs, IPIC_SEMSR);
|
||||
|
||||
if (flags & IPIC_IRQ0_MCP)
|
||||
temp |= SEMSR_SIRQ0;
|
||||
else
|
||||
temp &= ~SEMSR_SIRQ0;
|
||||
|
||||
ipic_write(primary_ipic->regs, IPIC_SEMSR, temp);
|
||||
|
||||
for (i = 0 ; i < NR_IPIC_INTS ; i++) {
|
||||
irq_desc[i+irq_offset].chip = &ipic;
|
||||
irq_desc[i+irq_offset].status = IRQ_LEVEL;
|
||||
}
|
||||
|
||||
temp = 0;
|
||||
for (i = 0 ; i < senses_count ; i++) {
|
||||
if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) {
|
||||
temp |= 1 << (15 - i);
|
||||
if (i != 0)
|
||||
irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0;
|
||||
else
|
||||
irq_desc[irq_offset + MPC83xx_IRQ_EXT0].status = 0;
|
||||
}
|
||||
}
|
||||
ipic_write(primary_ipic->regs, IPIC_SECNR, temp);
|
||||
|
||||
printk ("IPIC (%d IRQ sources, %d External IRQs) at %p\n", NR_IPIC_INTS,
|
||||
senses_count, primary_ipic->regs);
|
||||
}
|
||||
|
||||
int ipic_set_priority(unsigned int irq, unsigned int priority)
|
||||
{
|
||||
struct ipic *ipic = ipic_from_irq(irq);
|
||||
unsigned int src = irq - ipic->irq_offset;
|
||||
u32 temp;
|
||||
|
||||
if (priority > 7)
|
||||
return -EINVAL;
|
||||
if (src > 127)
|
||||
return -EINVAL;
|
||||
if (ipic_info[src].prio == 0)
|
||||
return -EINVAL;
|
||||
|
||||
temp = ipic_read(ipic->regs, ipic_info[src].prio);
|
||||
|
||||
if (priority < 4) {
|
||||
temp &= ~(0x7 << (20 + (3 - priority) * 3));
|
||||
temp |= ipic_info[src].prio_mask << (20 + (3 - priority) * 3);
|
||||
} else {
|
||||
temp &= ~(0x7 << (4 + (7 - priority) * 3));
|
||||
temp |= ipic_info[src].prio_mask << (4 + (7 - priority) * 3);
|
||||
}
|
||||
|
||||
ipic_write(ipic->regs, ipic_info[src].prio, temp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ipic_set_highest_priority(unsigned int irq)
|
||||
{
|
||||
struct ipic *ipic = ipic_from_irq(irq);
|
||||
unsigned int src = irq - ipic->irq_offset;
|
||||
u32 temp;
|
||||
|
||||
temp = ipic_read(ipic->regs, IPIC_SICFR);
|
||||
|
||||
/* clear and set HPI */
|
||||
temp &= 0x7f000000;
|
||||
temp |= (src & 0x7f) << 24;
|
||||
|
||||
ipic_write(ipic->regs, IPIC_SICFR, temp);
|
||||
}
|
||||
|
||||
void ipic_set_default_priority(void)
|
||||
{
|
||||
ipic_set_priority(MPC83xx_IRQ_TSEC1_TX, 0);
|
||||
ipic_set_priority(MPC83xx_IRQ_TSEC1_RX, 1);
|
||||
ipic_set_priority(MPC83xx_IRQ_TSEC1_ERROR, 2);
|
||||
ipic_set_priority(MPC83xx_IRQ_TSEC2_TX, 3);
|
||||
ipic_set_priority(MPC83xx_IRQ_TSEC2_RX, 4);
|
||||
ipic_set_priority(MPC83xx_IRQ_TSEC2_ERROR, 5);
|
||||
ipic_set_priority(MPC83xx_IRQ_USB2_DR, 6);
|
||||
ipic_set_priority(MPC83xx_IRQ_USB2_MPH, 7);
|
||||
|
||||
ipic_set_priority(MPC83xx_IRQ_UART1, 0);
|
||||
ipic_set_priority(MPC83xx_IRQ_UART2, 1);
|
||||
ipic_set_priority(MPC83xx_IRQ_SEC2, 2);
|
||||
ipic_set_priority(MPC83xx_IRQ_IIC1, 5);
|
||||
ipic_set_priority(MPC83xx_IRQ_IIC2, 6);
|
||||
ipic_set_priority(MPC83xx_IRQ_SPI, 7);
|
||||
ipic_set_priority(MPC83xx_IRQ_RTC_SEC, 0);
|
||||
ipic_set_priority(MPC83xx_IRQ_PIT, 1);
|
||||
ipic_set_priority(MPC83xx_IRQ_PCI1, 2);
|
||||
ipic_set_priority(MPC83xx_IRQ_PCI2, 3);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT0, 4);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT1, 5);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT2, 6);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT3, 7);
|
||||
ipic_set_priority(MPC83xx_IRQ_RTC_ALR, 0);
|
||||
ipic_set_priority(MPC83xx_IRQ_MU, 1);
|
||||
ipic_set_priority(MPC83xx_IRQ_SBA, 2);
|
||||
ipic_set_priority(MPC83xx_IRQ_DMA, 3);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT4, 4);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT5, 5);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT6, 6);
|
||||
ipic_set_priority(MPC83xx_IRQ_EXT7, 7);
|
||||
}
|
||||
|
||||
void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq)
|
||||
{
|
||||
struct ipic *ipic = primary_ipic;
|
||||
u32 temp;
|
||||
|
||||
temp = ipic_read(ipic->regs, IPIC_SERMR);
|
||||
temp |= (1 << (31 - mcp_irq));
|
||||
ipic_write(ipic->regs, IPIC_SERMR, temp);
|
||||
}
|
||||
|
||||
void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq)
|
||||
{
|
||||
struct ipic *ipic = primary_ipic;
|
||||
u32 temp;
|
||||
|
||||
temp = ipic_read(ipic->regs, IPIC_SERMR);
|
||||
temp &= (1 << (31 - mcp_irq));
|
||||
ipic_write(ipic->regs, IPIC_SERMR, temp);
|
||||
}
|
||||
|
||||
u32 ipic_get_mcp_status(void)
|
||||
{
|
||||
return ipic_read(primary_ipic->regs, IPIC_SERMR);
|
||||
}
|
||||
|
||||
void ipic_clear_mcp_status(u32 mask)
|
||||
{
|
||||
ipic_write(primary_ipic->regs, IPIC_SERMR, mask);
|
||||
}
|
||||
|
||||
/* Return an interrupt vector or -1 if no interrupt is pending. */
|
||||
int ipic_get_irq(struct pt_regs *regs)
|
||||
{
|
||||
int irq;
|
||||
|
||||
irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & 0x7f;
|
||||
|
||||
if (irq == 0) /* 0 --> no irq is pending */
|
||||
irq = -1;
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
static struct sysdev_class ipic_sysclass = {
|
||||
set_kset_name("ipic"),
|
||||
};
|
||||
|
||||
static struct sys_device device_ipic = {
|
||||
.id = 0,
|
||||
.cls = &ipic_sysclass,
|
||||
};
|
||||
|
||||
static int __init init_ipic_sysfs(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (!primary_ipic->regs)
|
||||
return -ENODEV;
|
||||
printk(KERN_DEBUG "Registering ipic with sysfs...\n");
|
||||
|
||||
rc = sysdev_class_register(&ipic_sysclass);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "Failed registering ipic sys class\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
rc = sysdev_register(&device_ipic);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "Failed registering ipic sys device\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
subsys_initcall(init_ipic_sysfs);
|
47
arch/ppc/syslib/ipic.h
Normal file
47
arch/ppc/syslib/ipic.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* IPIC private definitions and structure.
|
||||
*
|
||||
* Maintainer: Kumar Gala <galak@kernel.crashing.org>
|
||||
*
|
||||
* Copyright 2005 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
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
#ifndef __IPIC_H__
|
||||
#define __IPIC_H__
|
||||
|
||||
#include <asm/ipic.h>
|
||||
|
||||
#define MPC83xx_IPIC_SIZE (0x00100)
|
||||
|
||||
/* System Global Interrupt Configuration Register */
|
||||
#define SICFR_IPSA 0x00010000
|
||||
#define SICFR_IPSD 0x00080000
|
||||
#define SICFR_MPSA 0x00200000
|
||||
#define SICFR_MPSB 0x00400000
|
||||
|
||||
/* System External Interrupt Mask Register */
|
||||
#define SEMSR_SIRQ0 0x00008000
|
||||
|
||||
/* System Error Control Register */
|
||||
#define SERCR_MCPR 0x00000001
|
||||
|
||||
struct ipic {
|
||||
volatile u32 __iomem *regs;
|
||||
unsigned int irq_offset;
|
||||
};
|
||||
|
||||
struct ipic_info {
|
||||
u8 pend; /* pending register offset from base */
|
||||
u8 mask; /* mask register offset from base */
|
||||
u8 prio; /* priority register offset from base */
|
||||
u8 force; /* force register offset from base */
|
||||
u8 bit; /* register bit position (as per doc)
|
||||
bit mask = 1 << (31 - bit) */
|
||||
u8 prio_mask; /* priority mask value */
|
||||
};
|
||||
|
||||
#endif /* __IPIC_H__ */
|
@ -72,6 +72,9 @@ extern unsigned long pci_io_base;
|
||||
* Neither do the standard versions now, these are just here
|
||||
* for older code.
|
||||
*/
|
||||
#define insb(port, buf, ns) _insb((u8 __iomem *)((port)+pci_io_base), (buf), (ns))
|
||||
#define insw(port, buf, ns) _insw_ns((u8 __iomem *)((port)+pci_io_base), (buf), (ns))
|
||||
#define insl(port, buf, nl) _insl_ns((u8 __iomem *)((port)+pci_io_base), (buf), (nl))
|
||||
#define insw_ns(port, buf, ns) _insw_ns((u16 __iomem *)((port)+pci_io_base), (buf), (ns))
|
||||
#define insl_ns(port, buf, nl) _insl_ns((u32 __iomem *)((port)+pci_io_base), (buf), (nl))
|
||||
#else
|
||||
@ -137,12 +140,12 @@ static inline void __raw_writeq(unsigned long v, volatile void __iomem *addr)
|
||||
#define insw_ns(port, buf, ns) eeh_insw_ns((port), (buf), (ns))
|
||||
#define insl_ns(port, buf, nl) eeh_insl_ns((port), (buf), (nl))
|
||||
|
||||
#endif
|
||||
|
||||
#define outsb(port, buf, ns) _outsb((u8 __iomem *)((port)+pci_io_base), (buf), (ns))
|
||||
#define outsw(port, buf, ns) _outsw_ns((u16 __iomem *)((port)+pci_io_base), (buf), (ns))
|
||||
#define outsl(port, buf, nl) _outsl_ns((u32 __iomem *)((port)+pci_io_base), (buf), (nl))
|
||||
|
||||
#endif
|
||||
|
||||
#define readb_relaxed(addr) readb(addr)
|
||||
#define readw_relaxed(addr) readw(addr)
|
||||
#define readl_relaxed(addr) readl(addr)
|
||||
|
@ -69,9 +69,6 @@ enum ipic_mcp_irq {
|
||||
IPIC_MCP_MU = 7,
|
||||
};
|
||||
|
||||
extern void ipic_init(phys_addr_t phys_addr, unsigned int flags,
|
||||
unsigned int irq_offset,
|
||||
unsigned char *senses, unsigned int senses_count);
|
||||
extern int ipic_set_priority(unsigned int irq, unsigned int priority);
|
||||
extern void ipic_set_highest_priority(unsigned int irq);
|
||||
extern void ipic_set_default_priority(void);
|
||||
@ -79,7 +76,16 @@ extern void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq);
|
||||
extern void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq);
|
||||
extern u32 ipic_get_mcp_status(void);
|
||||
extern void ipic_clear_mcp_status(u32 mask);
|
||||
|
||||
#ifdef CONFIG_PPC_MERGE
|
||||
extern void ipic_init(struct device_node *node, unsigned int flags);
|
||||
extern unsigned int ipic_get_irq(struct pt_regs *regs);
|
||||
#else
|
||||
extern void ipic_init(phys_addr_t phys_addr, unsigned int flags,
|
||||
unsigned int irq_offset,
|
||||
unsigned char *senses, unsigned int senses_count);
|
||||
extern int ipic_get_irq(struct pt_regs *regs);
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_IPIC_H__ */
|
||||
#endif /* __KERNEL__ */
|
||||
|
@ -23,8 +23,6 @@
|
||||
#define _ISA_MEM_BASE isa_mem_base
|
||||
#ifdef CONFIG_PCI
|
||||
#define PCI_DRAM_OFFSET pci_dram_offset
|
||||
#else
|
||||
#define PCI_DRAM_OFFSET 0
|
||||
#endif
|
||||
|
||||
#define CPU0_BOOT_RELEASE 0x01000000
|
||||
@ -33,7 +31,6 @@
|
||||
#define MCM_PORT_CONFIG_OFFSET 0x1010
|
||||
|
||||
/* Offset from CCSRBAR */
|
||||
#define MPC86xx_OPENPIC_OFFSET (0x40000)
|
||||
#define MPC86xx_MCM_OFFSET (0x00000)
|
||||
#define MPC86xx_MCM_SIZE (0x02000)
|
||||
|
||||
|
@ -41,6 +41,7 @@
|
||||
#define MPIC_GREG_IPI_VECTOR_PRI_1 0x000b0
|
||||
#define MPIC_GREG_IPI_VECTOR_PRI_2 0x000c0
|
||||
#define MPIC_GREG_IPI_VECTOR_PRI_3 0x000d0
|
||||
#define MPIC_GREG_IPI_STRIDE 0x10
|
||||
#define MPIC_GREG_SPURIOUS 0x000e0
|
||||
#define MPIC_GREG_TIMER_FREQ 0x000f0
|
||||
|
||||
@ -68,6 +69,7 @@
|
||||
#define MPIC_CPU_IPI_DISPATCH_1 0x00050
|
||||
#define MPIC_CPU_IPI_DISPATCH_2 0x00060
|
||||
#define MPIC_CPU_IPI_DISPATCH_3 0x00070
|
||||
#define MPIC_CPU_IPI_DISPATCH_STRIDE 0x00010
|
||||
#define MPIC_CPU_CURRENT_TASK_PRI 0x00080
|
||||
#define MPIC_CPU_TASKPRI_MASK 0x0000000f
|
||||
#define MPIC_CPU_WHOAMI 0x00090
|
||||
@ -114,6 +116,103 @@
|
||||
#define MPIC_VEC_TIMER_1 248
|
||||
#define MPIC_VEC_TIMER_0 247
|
||||
|
||||
/*
|
||||
* Tsi108 implementation of MPIC has many differences from the original one
|
||||
*/
|
||||
|
||||
/*
|
||||
* Global registers
|
||||
*/
|
||||
|
||||
#define TSI108_GREG_BASE 0x00000
|
||||
#define TSI108_GREG_FEATURE_0 0x00000
|
||||
#define TSI108_GREG_GLOBAL_CONF_0 0x00004
|
||||
#define TSI108_GREG_VENDOR_ID 0x0000c
|
||||
#define TSI108_GREG_IPI_VECTOR_PRI_0 0x00204 /* Doorbell 0 */
|
||||
#define TSI108_GREG_IPI_STRIDE 0x0c
|
||||
#define TSI108_GREG_SPURIOUS 0x00010
|
||||
#define TSI108_GREG_TIMER_FREQ 0x00014
|
||||
|
||||
/*
|
||||
* Timer registers
|
||||
*/
|
||||
#define TSI108_TIMER_BASE 0x0030
|
||||
#define TSI108_TIMER_STRIDE 0x10
|
||||
#define TSI108_TIMER_CURRENT_CNT 0x00000
|
||||
#define TSI108_TIMER_BASE_CNT 0x00004
|
||||
#define TSI108_TIMER_VECTOR_PRI 0x00008
|
||||
#define TSI108_TIMER_DESTINATION 0x0000c
|
||||
|
||||
/*
|
||||
* Per-Processor registers
|
||||
*/
|
||||
#define TSI108_CPU_BASE 0x00300
|
||||
#define TSI108_CPU_STRIDE 0x00040
|
||||
#define TSI108_CPU_IPI_DISPATCH_0 0x00200
|
||||
#define TSI108_CPU_IPI_DISPATCH_STRIDE 0x00000
|
||||
#define TSI108_CPU_CURRENT_TASK_PRI 0x00000
|
||||
#define TSI108_CPU_WHOAMI 0xffffffff
|
||||
#define TSI108_CPU_INTACK 0x00004
|
||||
#define TSI108_CPU_EOI 0x00008
|
||||
|
||||
/*
|
||||
* Per-source registers
|
||||
*/
|
||||
#define TSI108_IRQ_BASE 0x00100
|
||||
#define TSI108_IRQ_STRIDE 0x00008
|
||||
#define TSI108_IRQ_VECTOR_PRI 0x00000
|
||||
#define TSI108_VECPRI_VECTOR_MASK 0x000000ff
|
||||
#define TSI108_VECPRI_POLARITY_POSITIVE 0x01000000
|
||||
#define TSI108_VECPRI_POLARITY_NEGATIVE 0x00000000
|
||||
#define TSI108_VECPRI_SENSE_LEVEL 0x02000000
|
||||
#define TSI108_VECPRI_SENSE_EDGE 0x00000000
|
||||
#define TSI108_VECPRI_POLARITY_MASK 0x01000000
|
||||
#define TSI108_VECPRI_SENSE_MASK 0x02000000
|
||||
#define TSI108_IRQ_DESTINATION 0x00004
|
||||
|
||||
/* weird mpic register indices and mask bits in the HW info array */
|
||||
enum {
|
||||
MPIC_IDX_GREG_BASE = 0,
|
||||
MPIC_IDX_GREG_FEATURE_0,
|
||||
MPIC_IDX_GREG_GLOBAL_CONF_0,
|
||||
MPIC_IDX_GREG_VENDOR_ID,
|
||||
MPIC_IDX_GREG_IPI_VECTOR_PRI_0,
|
||||
MPIC_IDX_GREG_IPI_STRIDE,
|
||||
MPIC_IDX_GREG_SPURIOUS,
|
||||
MPIC_IDX_GREG_TIMER_FREQ,
|
||||
|
||||
MPIC_IDX_TIMER_BASE,
|
||||
MPIC_IDX_TIMER_STRIDE,
|
||||
MPIC_IDX_TIMER_CURRENT_CNT,
|
||||
MPIC_IDX_TIMER_BASE_CNT,
|
||||
MPIC_IDX_TIMER_VECTOR_PRI,
|
||||
MPIC_IDX_TIMER_DESTINATION,
|
||||
|
||||
MPIC_IDX_CPU_BASE,
|
||||
MPIC_IDX_CPU_STRIDE,
|
||||
MPIC_IDX_CPU_IPI_DISPATCH_0,
|
||||
MPIC_IDX_CPU_IPI_DISPATCH_STRIDE,
|
||||
MPIC_IDX_CPU_CURRENT_TASK_PRI,
|
||||
MPIC_IDX_CPU_WHOAMI,
|
||||
MPIC_IDX_CPU_INTACK,
|
||||
MPIC_IDX_CPU_EOI,
|
||||
|
||||
MPIC_IDX_IRQ_BASE,
|
||||
MPIC_IDX_IRQ_STRIDE,
|
||||
MPIC_IDX_IRQ_VECTOR_PRI,
|
||||
|
||||
MPIC_IDX_VECPRI_VECTOR_MASK,
|
||||
MPIC_IDX_VECPRI_POLARITY_POSITIVE,
|
||||
MPIC_IDX_VECPRI_POLARITY_NEGATIVE,
|
||||
MPIC_IDX_VECPRI_SENSE_LEVEL,
|
||||
MPIC_IDX_VECPRI_SENSE_EDGE,
|
||||
MPIC_IDX_VECPRI_POLARITY_MASK,
|
||||
MPIC_IDX_VECPRI_SENSE_MASK,
|
||||
MPIC_IDX_IRQ_DESTINATION,
|
||||
MPIC_IDX_END
|
||||
};
|
||||
|
||||
|
||||
#ifdef CONFIG_MPIC_BROKEN_U3
|
||||
/* Fixup table entry */
|
||||
struct mpic_irq_fixup
|
||||
@ -171,15 +270,29 @@ struct mpic
|
||||
volatile u32 __iomem *cpuregs[MPIC_MAX_CPUS];
|
||||
volatile u32 __iomem *isus[MPIC_MAX_ISU];
|
||||
|
||||
#ifdef CONFIG_MPIC_WEIRD
|
||||
/* Pointer to HW info array */
|
||||
u32 *hw_set;
|
||||
#endif
|
||||
|
||||
/* link */
|
||||
struct mpic *next;
|
||||
};
|
||||
|
||||
/*
|
||||
* MPIC flags (passed to mpic_alloc)
|
||||
*
|
||||
* The top 4 bits contain an MPIC bhw id that is used to index the
|
||||
* register offsets and some masks when CONFIG_MPIC_WEIRD is set.
|
||||
* Note setting any ID (leaving those bits to 0) means standard MPIC
|
||||
*/
|
||||
|
||||
/* This is the primary controller, only that one has IPIs and
|
||||
* has afinity control. A non-primary MPIC always uses CPU0
|
||||
* registers only
|
||||
*/
|
||||
#define MPIC_PRIMARY 0x00000001
|
||||
|
||||
/* Set this for a big-endian MPIC */
|
||||
#define MPIC_BIG_ENDIAN 0x00000002
|
||||
/* Broken U3 MPIC */
|
||||
@ -188,6 +301,18 @@ struct mpic
|
||||
#define MPIC_BROKEN_IPI 0x00000008
|
||||
/* MPIC wants a reset */
|
||||
#define MPIC_WANTS_RESET 0x00000010
|
||||
/* Spurious vector requires EOI */
|
||||
#define MPIC_SPV_EOI 0x00000020
|
||||
/* No passthrough disable */
|
||||
#define MPIC_NO_PTHROU_DIS 0x00000040
|
||||
|
||||
/* MPIC HW modification ID */
|
||||
#define MPIC_REGSET_MASK 0xf0000000
|
||||
#define MPIC_REGSET(val) (((val) & 0xf ) << 28)
|
||||
#define MPIC_GET_REGSET(flags) (((flags) >> 28) & 0xf)
|
||||
|
||||
#define MPIC_REGSET_STANDARD MPIC_REGSET(0) /* Original MPIC */
|
||||
#define MPIC_REGSET_TSI108 MPIC_REGSET(1) /* Tsi108/109 PIC */
|
||||
|
||||
/* Allocate the controller structure and setup the linux irq descs
|
||||
* for the range if interrupts passed in. No HW initialization is
|
||||
|
@ -276,6 +276,7 @@ extern void of_irq_map_init(unsigned int flags);
|
||||
* of_irq_map_raw - Low level interrupt tree parsing
|
||||
* @parent: the device interrupt parent
|
||||
* @intspec: interrupt specifier ("interrupts" property of the device)
|
||||
* @ointsize: size of the passed in interrupt specifier
|
||||
* @addr: address specifier (start of "reg" property of the device)
|
||||
* @out_irq: structure of_irq filled by this function
|
||||
*
|
||||
@ -288,7 +289,8 @@ extern void of_irq_map_init(unsigned int flags);
|
||||
*
|
||||
*/
|
||||
|
||||
extern int of_irq_map_raw(struct device_node *parent, u32 *intspec, u32 *addr,
|
||||
extern int of_irq_map_raw(struct device_node *parent, u32 *intspec,
|
||||
u32 ointsize, u32 *addr,
|
||||
struct of_irq *out_irq);
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user