diff options
66 files changed, 900 insertions, 174 deletions
diff --git a/Documentation/powerpc/dts-bindings/fsl/83xx-512x-pci.txt b/Documentation/powerpc/dts-bindings/fsl/83xx-512x-pci.txt new file mode 100644 index 0000000..35a4653 --- /dev/null +++ b/Documentation/powerpc/dts-bindings/fsl/83xx-512x-pci.txt @@ -0,0 +1,40 @@ +* Freescale 83xx and 512x PCI bridges + +Freescale 83xx and 512x SOCs include the same pci bridge core. + +83xx/512x specific notes: +- reg: should contain two address length tuples + The first is for the internal pci bridge registers + The second is for the pci config space access registers + +Example (MPC8313ERDB) + pci0: pci@e0008500 { + cell-index = <1>; + interrupt-map-mask = <0xf800 0x0 0x0 0x7>; + interrupt-map = < + /* IDSEL 0x0E -mini PCI */ + 0x7000 0x0 0x0 0x1 &ipic 18 0x8 + 0x7000 0x0 0x0 0x2 &ipic 18 0x8 + 0x7000 0x0 0x0 0x3 &ipic 18 0x8 + 0x7000 0x0 0x0 0x4 &ipic 18 0x8 + + /* IDSEL 0x0F - PCI slot */ + 0x7800 0x0 0x0 0x1 &ipic 17 0x8 + 0x7800 0x0 0x0 0x2 &ipic 18 0x8 + 0x7800 0x0 0x0 0x3 &ipic 17 0x8 + 0x7800 0x0 0x0 0x4 &ipic 18 0x8>; + interrupt-parent = <&ipic>; + interrupts = <66 0x8>; + bus-range = <0x0 0x0>; + ranges = <0x02000000 0x0 0x90000000 0x90000000 0x0 0x10000000 + 0x42000000 0x0 0x80000000 0x80000000 0x0 0x10000000 + 0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>; + clock-frequency = <66666666>; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + reg = <0xe0008500 0x100 /* internal registers */ + 0xe0008300 0x8>; /* config space access registers */ + compatible = "fsl,mpc8349-pci"; + device_type = "pci"; + }; diff --git a/Documentation/powerpc/dts-bindings/fsl/dma.txt b/Documentation/powerpc/dts-bindings/fsl/dma.txt index 86826df..cc45311 100644 --- a/Documentation/powerpc/dts-bindings/fsl/dma.txt +++ b/Documentation/powerpc/dts-bindings/fsl/dma.txt @@ -20,7 +20,7 @@ Required properties: - compatible : compatible list, contains 2 entries, first is "fsl,CHIP-dma-channel", where CHIP is the processor (mpc8349, mpc8350, etc.) and the second is - "fsl,elo-dma-channel" + "fsl,elo-dma-channel". However, see note below. - reg : <registers mapping for channel> - cell-index : dma channel index starts at 0. @@ -82,7 +82,7 @@ Required properties: - compatible : compatible list, contains 2 entries, first is "fsl,CHIP-dma-channel", where CHIP is the processor (mpc8540, mpc8560, etc.) and the second is - "fsl,eloplus-dma-channel" + "fsl,eloplus-dma-channel". However, see note below. - cell-index : dma channel index starts at 0. - reg : <registers mapping for channel> - interrupts : <interrupt mapping for DMA channel IRQ> @@ -125,3 +125,12 @@ Example: interrupts = <17 2>; }; }; + +Note on DMA channel compatible properties: The compatible property must say +"fsl,elo-dma-channel" or "fsl,eloplus-dma-channel" to be used by the Elo DMA +driver (fsldma). Any DMA channel used by fsldma cannot be used by another +DMA driver, such as the SSI sound drivers for the MPC8610. Therefore, any DMA +channel that should be used for another driver should not use +"fsl,elo-dma-channel" or "fsl,eloplus-dma-channel". For the SSI drivers, for +example, the compatible property should be "fsl,ssi-dma-channel". See ssi.txt +for more information. diff --git a/Documentation/powerpc/dts-bindings/fsl/ssi.txt b/Documentation/powerpc/dts-bindings/fsl/ssi.txt index 5d98413..a2d9639 100644 --- a/Documentation/powerpc/dts-bindings/fsl/ssi.txt +++ b/Documentation/powerpc/dts-bindings/fsl/ssi.txt @@ -24,12 +24,12 @@ Required properties: "rj-master" - r.j., SSI is clock master "ac97-slave" - AC97 mode, SSI is clock slave "ac97-master" - AC97 mode, SSI is clock master -- fsl,playback-dma: phandle to a DMA node for the DMA channel to use for - playback of audio. This is typically dictated by SOC - design. See the notes below. -- fsl,capture-dma: phandle to a DMA node for the DMA channel to use for - capture (recording) of audio. This is typically dictated - by SOC design. See the notes below. +- fsl,playback-dma: phandle to a node for the DMA channel to use for + playback of audio. This is typically dictated by SOC + design. See the notes below. +- fsl,capture-dma: phandle to a node for the DMA channel to use for + capture (recording) of audio. This is typically dictated + by SOC design. See the notes below. Optional properties: - codec-handle : phandle to a 'codec' node that defines an audio @@ -51,3 +51,11 @@ playback and DMA channel 1 for capture. SSI2 must use DMA channel 2 for playback and DMA channel 3 for capture. The developer can choose which DMA controller to use, but the channels themselves are hard-wired. The purpose of these two properties is to represent this hardware design. + +The device tree nodes for the DMA channels that are referenced by +"fsl,playback-dma" and "fsl,capture-dma" must be marked as compatible with +"fsl,ssi-dma-channel". The SOC-specific compatible string (e.g. +"fsl,mpc8610-dma-channel") can remain. If these nodes are left as +"fsl,elo-dma-channel" or "fsl,eloplus-dma-channel", then the generic Elo DMA +drivers (fsldma) will attempt to use them, and it will conflict with the +sound drivers. diff --git a/arch/powerpc/boot/dts/gef_sbc610.dts b/arch/powerpc/boot/dts/gef_sbc610.dts index 80b79e4..6ed6083 100644 --- a/arch/powerpc/boot/dts/gef_sbc610.dts +++ b/arch/powerpc/boot/dts/gef_sbc610.dts @@ -67,6 +67,39 @@ reg = <0x0 0x40000000>; // set by uboot }; + localbus@fef05000 { + #address-cells = <2>; + #size-cells = <1>; + compatible = "fsl,mpc8641-localbus", "simple-bus"; + reg = <0xf8005000 0x1000>; + interrupts = <19 2>; + interrupt-parent = <&mpic>; + + ranges = <0 0 0xff000000 0x01000000 // 16MB Boot flash + 1 0 0xe8000000 0x08000000 // Paged Flash 0 + 2 0 0xe0000000 0x08000000 // Paged Flash 1 + 3 0 0xfc100000 0x00020000 // NVRAM + 4 0 0xfc000000 0x00008000 // FPGA + 5 0 0xfc008000 0x00008000 // AFIX FPGA + 6 0 0xfd000000 0x00800000 // IO FPGA (8-bit) + 7 0 0xfd800000 0x00800000>; // IO FPGA (32-bit) + + fpga@4,0 { + compatible = "gef,fpga-regs"; + reg = <0x4 0x0 0x40>; + }; + gef_pic: pic@4,4000 { + #interrupt-cells = <1>; + interrupt-controller; + compatible = "gef,fpga-pic"; + reg = <0x4 0x4000 0x20>; + interrupts = <0x8 + 0x9>; + interrupt-parent = <&mpic>; + + }; + }; + soc@fef00000 { #address-cells = <1>; #size-cells = <1>; @@ -150,13 +183,13 @@ reg = <0x24520 0x20>; phy0: ethernet-phy@0 { - interrupt-parent = <&mpic>; - interrupts = <0x0 0x1>; + interrupt-parent = <&gef_pic>; + interrupts = <0x9 0x4>; reg = <1>; }; phy2: ethernet-phy@2 { - interrupt-parent = <&mpic>; - interrupts = <0x0 0x1>; + interrupt-parent = <&gef_pic>; + interrupts = <0x8 0x4>; reg = <3>; }; }; diff --git a/arch/powerpc/boot/dts/mpc5121ads.dts b/arch/powerpc/boot/dts/mpc5121ads.dts index 1f9036c..c2b8dbf 100644 --- a/arch/powerpc/boot/dts/mpc5121ads.dts +++ b/arch/powerpc/boot/dts/mpc5121ads.dts @@ -403,7 +403,8 @@ #interrupt-cells = <1>; #size-cells = <2>; #address-cells = <3>; - reg = <0x80008500 0x100>; + reg = <0x80008500 0x100 /* internal registers */ + 0x80008300 0x8>; /* config space access registers */ compatible = "fsl,mpc5121-pci"; device_type = "pci"; }; diff --git a/arch/powerpc/boot/dts/mpc8313erdb.dts b/arch/powerpc/boot/dts/mpc8313erdb.dts index 5390855..747f276 100644 --- a/arch/powerpc/boot/dts/mpc8313erdb.dts +++ b/arch/powerpc/boot/dts/mpc8313erdb.dts @@ -363,7 +363,8 @@ #interrupt-cells = <1>; #size-cells = <2>; #address-cells = <3>; - reg = <0xe0008500 0x100>; + reg = <0xe0008500 0x100 /* internal registers */ + 0xe0008300 0x8>; /* config space access registers */ compatible = "fsl,mpc8349-pci"; device_type = "pci"; }; diff --git a/arch/powerpc/boot/dts/mpc8315erdb.dts b/arch/powerpc/boot/dts/mpc8315erdb.dts index 94c9b41..7449e54 100644 --- a/arch/powerpc/boot/dts/mpc8315erdb.dts +++ b/arch/powerpc/boot/dts/mpc8315erdb.dts @@ -318,7 +318,8 @@ #interrupt-cells = <1>; #size-cells = <2>; #address-cells = <3>; - reg = <0xe0008500 0x100>; + reg = <0xe0008500 0x100 /* internal registers */ + 0xe0008300 0x8>; /* config space access registers */ compatible = "fsl,mpc8349-pci"; device_type = "pci"; }; diff --git a/arch/powerpc/boot/dts/mpc832x_mds.dts b/arch/powerpc/boot/dts/mpc832x_mds.dts index 015808a..e4cc176 100644 --- a/arch/powerpc/boot/dts/mpc832x_mds.dts +++ b/arch/powerpc/boot/dts/mpc832x_mds.dts @@ -423,7 +423,8 @@ #interrupt-cells = <1>; #size-cells = <2>; #address-cells = <3>; - reg = <0xe0008500 0x100>; + reg = <0xe0008500 0x100 /* internal registers */ + 0xe0008300 0x8>; /* config space access registers */ compatible = "fsl,mpc8349-pci"; device_type = "pci"; }; diff --git a/arch/powerpc/boot/dts/mpc832x_rdb.dts b/arch/powerpc/boot/dts/mpc832x_rdb.dts index b5b0ec2..226ff06 100644 --- a/arch/powerpc/boot/dts/mpc832x_rdb.dts +++ b/arch/powerpc/boot/dts/mpc832x_rdb.dts @@ -331,7 +331,8 @@ #interrupt-cells = <1>; #size-cells = <2>; #address-cells = <3>; - reg = <0xe0008500 0x100>; + reg = <0xe0008500 0x100 /* internal registers */ + 0xe0008300 0x8>; /* config space access registers */ compatible = "fsl,mpc8349-pci"; device_type = "pci"; }; diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts index 1327a61..5cedf37 100644 --- a/arch/powerpc/boot/dts/mpc8349emitx.dts +++ b/arch/powerpc/boot/dts/mpc8349emitx.dts @@ -254,7 +254,8 @@ #interrupt-cells = <1>; #size-cells = <2>; #address-cells = <3>; - reg = <0xe0008500 0x100>; + reg = <0xe0008500 0x100 /* internal registers */ + 0xe0008300 0x8>; /* config space access registers */ compatible = "fsl,mpc8349-pci"; device_type = "pci"; }; @@ -280,7 +281,8 @@ #interrupt-cells = <1>; #size-cells = <2>; #address-cells = <3>; - reg = <0xe0008600 0x100>; + reg = <0xe0008600 0x100 /* internal registers */ + 0xe0008380 0x8>; /* config space access registers */ compatible = "fsl,mpc8349-pci"; device_type = "pci"; }; diff --git a/arch/powerpc/boot/dts/mpc8349emitxgp.dts b/arch/powerpc/boot/dts/mpc8349emitxgp.dts index f70d3a0..81ae1d3 100644 --- a/arch/powerpc/boot/dts/mpc8349emitxgp.dts +++ b/arch/powerpc/boot/dts/mpc8349emitxgp.dts @@ -228,7 +228,8 @@ #interrupt-cells = <1>; #size-cells = <2>; #address-cells = <3>; - reg = <0xe0008600 0x100>; + reg = <0xe0008600 0x100 /* internal registers */ + 0xe0008380 0x8>; /* config space access registers */ compatible = "fsl,mpc8349-pci"; device_type = "pci"; }; diff --git a/arch/powerpc/boot/dts/mpc834x_mds.dts b/arch/powerpc/boot/dts/mpc834x_mds.dts index e29739e..04bfde3 100644 --- a/arch/powerpc/boot/dts/mpc834x_mds.dts +++ b/arch/powerpc/boot/dts/mpc834x_mds.dts @@ -315,7 +315,8 @@ #interrupt-cells = <1>; #size-cells = <2>; #address-cells = <3>; - reg = <0xe0008500 0x100>; + reg = <0xe0008500 0x100 /* internal registers */ + 0xe0008300 0x8>; /* config space access registers */ compatible = "fsl,mpc8349-pci"; device_type = "pci"; }; @@ -376,7 +377,8 @@ #interrupt-cells = <1>; #size-cells = <2>; #address-cells = <3>; - reg = <0xe0008600 0x100>; + reg = <0xe0008600 0x100 /* internal registers */ + 0xe0008380 0x8>; /* config space access registers */ compatible = "fsl,mpc8349-pci"; device_type = "pci"; }; diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts index 49aec71..66a12d2 100644 --- a/arch/powerpc/boot/dts/mpc836x_mds.dts +++ b/arch/powerpc/boot/dts/mpc836x_mds.dts @@ -426,7 +426,8 @@ #interrupt-cells = <1>; #size-cells = <2>; #address-cells = <3>; - reg = <0xe0008500 0x100>; + reg = <0xe0008500 0x100 /* internal registers */ + 0xe0008300 0x8>; /* config space access registers */ compatible = "fsl,mpc8349-pci"; device_type = "pci"; }; diff --git a/arch/powerpc/boot/dts/mpc836x_rdk.dts b/arch/powerpc/boot/dts/mpc836x_rdk.dts index 69c9bd2..decadf3 100644 --- a/arch/powerpc/boot/dts/mpc836x_rdk.dts +++ b/arch/powerpc/boot/dts/mpc836x_rdk.dts @@ -387,6 +387,18 @@ device-width = <1>; }; + upm@1,0 { + compatible = "fsl,upm-nand"; + reg = <1 0 1>; + fsl,upm-addr-offset = <16>; + fsl,upm-cmd-offset = <8>; + gpios = <&qe_pio_e 18 0>; + + flash { + compatible = "stm,nand512-a"; + }; + }; + display@2,0 { device_type = "display"; compatible = "fujitsu,MB86277", "fujitsu,mint"; @@ -409,7 +421,8 @@ #interrupt-cells = <1>; device_type = "pci"; compatible = "fsl,mpc8360-pci", "fsl,mpc8349-pci"; - reg = <0xe0008500 0x100>; + reg = <0xe0008500 0x100 /* internal registers */ + 0xe0008300 0x8>; /* config space access registers */ ranges = <0x02000000 0 0x90000000 0x90000000 0 0x10000000 0x42000000 0 0x80000000 0x80000000 0 0x10000000 0x01000000 0 0xe0300000 0xe0300000 0 0x00100000>; diff --git a/arch/powerpc/boot/dts/mpc8377_mds.dts b/arch/powerpc/boot/dts/mpc8377_mds.dts index 78f0f11..0484561 100644 --- a/arch/powerpc/boot/dts/mpc8377_mds.dts +++ b/arch/powerpc/boot/dts/mpc8377_mds.dts @@ -136,6 +136,13 @@ interrupts = <14 0x8>; interrupt-parent = <&ipic>; dfsrr; + + rtc@68 { + compatible = "dallas,ds1374"; + reg = <0x68>; + interrupts = <19 0x8>; + interrupt-parent = <&ipic>; + }; }; i2c@3100 { @@ -378,7 +385,8 @@ #interrupt-cells = <1>; #size-cells = <2>; #address-cells = <3>; - reg = <0xe0008500 0x100>; + reg = <0xe0008500 0x100 /* internal registers */ + 0xe0008300 0x8>; /* config space access registers */ compatible = "fsl,mpc8349-pci"; device_type = "pci"; }; diff --git a/arch/powerpc/boot/dts/mpc8377_rdb.dts b/arch/powerpc/boot/dts/mpc8377_rdb.dts index d46327e..53191ba 100644 --- a/arch/powerpc/boot/dts/mpc8377_rdb.dts +++ b/arch/powerpc/boot/dts/mpc8377_rdb.dts @@ -319,7 +319,8 @@ #interrupt-cells = <1>; #size-cells = <2>; #address-cells = <3>; - reg = <0xe0008500 0x100>; + reg = <0xe0008500 0x100 /* internal registers */ + 0xe0008300 0x8>; /* config space access registers */ compatible = "fsl,mpc8349-pci"; device_type = "pci"; }; diff --git a/arch/powerpc/boot/dts/mpc8378_mds.dts b/arch/powerpc/boot/dts/mpc8378_mds.dts index c44f30f..67a08d2 100644 --- a/arch/powerpc/boot/dts/mpc8378_mds.dts +++ b/arch/powerpc/boot/dts/mpc8378_mds.dts @@ -136,6 +136,13 @@ interrupts = <14 0x8>; interrupt-parent = <&ipic>; dfsrr; + + rtc@68 { + compatible = "dallas,ds1374"; + reg = <0x68>; + interrupts = <19 0x8>; + interrupt-parent = <&ipic>; + }; }; i2c@3100 { @@ -364,7 +371,8 @@ #interrupt-cells = <1>; #size-cells = <2>; #address-cells = <3>; - reg = <0xe0008500 0x100>; + reg = <0xe0008500 0x100 /* internal registers */ + 0xe0008300 0x8>; /* config space access registers */ compatible = "fsl,mpc8349-pci"; device_type = "pci"; }; diff --git a/arch/powerpc/boot/dts/mpc8378_rdb.dts b/arch/powerpc/boot/dts/mpc8378_rdb.dts index b3e3bd7..4a09153 100644 --- a/arch/powerpc/boot/dts/mpc8378_rdb.dts +++ b/arch/powerpc/boot/dts/mpc8378_rdb.dts @@ -305,7 +305,8 @@ #interrupt-cells = <1>; #size-cells = <2>; #address-cells = <3>; - reg = <0xe0008500 0x100>; + reg = <0xe0008500 0x100 /* internal registers */ + 0xe0008300 0x8>; /* config space access registers */ compatible = "fsl,mpc8349-pci"; device_type = "pci"; }; diff --git a/arch/powerpc/boot/dts/mpc8379_mds.dts b/arch/powerpc/boot/dts/mpc8379_mds.dts index 653ed47..323370a 100644 --- a/arch/powerpc/boot/dts/mpc8379_mds.dts +++ b/arch/powerpc/boot/dts/mpc8379_mds.dts @@ -136,6 +136,13 @@ interrupts = <14 0x8>; interrupt-parent = <&ipic>; dfsrr; + + rtc@68 { + compatible = "dallas,ds1374"; + reg = <0x68>; + interrupts = <19 0x8>; + interrupt-parent = <&ipic>; + }; }; i2c@3100 { @@ -392,7 +399,8 @@ #interrupt-cells = <1>; #size-cells = <2>; #address-cells = <3>; - reg = <0xe0008500 0x100>; + reg = <0xe0008500 0x100 /* internal registers */ + 0xe0008300 0x8>; /* config space access registers */ compatible = "fsl,mpc8349-pci"; device_type = "pci"; }; diff --git a/arch/powerpc/boot/dts/mpc8379_rdb.dts b/arch/powerpc/boot/dts/mpc8379_rdb.dts index 123c8df..bbd884a 100644 --- a/arch/powerpc/boot/dts/mpc8379_rdb.dts +++ b/arch/powerpc/boot/dts/mpc8379_rdb.dts @@ -333,7 +333,8 @@ #interrupt-cells = <1>; #size-cells = <2>; #address-cells = <3>; - reg = <0xe0008500 0x100>; + reg = <0xe0008500 0x100 /* internal registers */ + 0xe0008300 0x8>; /* config space access registers */ compatible = "fsl,mpc8349-pci"; device_type = "pci"; }; diff --git a/arch/powerpc/boot/dts/mpc8536ds.dts b/arch/powerpc/boot/dts/mpc8536ds.dts index 1505d68..93fdd99 100644 --- a/arch/powerpc/boot/dts/mpc8536ds.dts +++ b/arch/powerpc/boot/dts/mpc8536ds.dts @@ -91,6 +91,8 @@ rtc@68 { compatible = "dallas,ds3232"; reg = <0x68>; + interrupts = <0 0x1>; + interrupt-parent = <&mpic>; }; }; diff --git a/arch/powerpc/boot/dts/mpc8610_hpcd.dts b/arch/powerpc/boot/dts/mpc8610_hpcd.dts index 0f3a36e..3f4c610 100644 --- a/arch/powerpc/boot/dts/mpc8610_hpcd.dts +++ b/arch/powerpc/boot/dts/mpc8610_hpcd.dts @@ -237,7 +237,7 @@ dma00: dma-channel@0 { compatible = "fsl,mpc8610-dma-channel", - "fsl,eloplus-dma-channel"; + "fsl,ssi-dma-channel"; cell-index = <0>; reg = <0x0 0x80>; interrupt-parent = <&mpic>; @@ -245,7 +245,7 @@ }; dma01: dma-channel@1 { compatible = "fsl,mpc8610-dma-channel", - "fsl,eloplus-dma-channel"; + "fsl,ssi-dma-channel"; cell-index = <1>; reg = <0x80 0x80>; interrupt-parent = <&mpic>; diff --git a/arch/powerpc/boot/dts/sbc8349.dts b/arch/powerpc/boot/dts/sbc8349.dts index c7f411f..0f941f3 100644 --- a/arch/powerpc/boot/dts/sbc8349.dts +++ b/arch/powerpc/boot/dts/sbc8349.dts @@ -272,7 +272,8 @@ #interrupt-cells = <1>; #size-cells = <2>; #address-cells = <3>; - reg = <0xe0008500 0x100>; + reg = <0xe0008500 0x100 /* internal registers */ + 0xe0008300 0x8>; /* config space access registers */ compatible = "fsl,mpc8349-pci"; device_type = "pci"; }; diff --git a/arch/powerpc/configs/83xx/asp8347_defconfig b/arch/powerpc/configs/83xx/asp8347_defconfig index 6638f5a..0b1fa20f 100644 --- a/arch/powerpc/configs/83xx/asp8347_defconfig +++ b/arch/powerpc/configs/83xx/asp8347_defconfig @@ -164,6 +164,8 @@ CONFIG_CLASSIC_RCU=y # CONFIG_PPC_MULTIPLATFORM=y CONFIG_CLASSIC32=y +# CONFIG_PPC_CHRP is not set +# CONFIG_PPC_PMAC is not set # CONFIG_MPC5121_ADS is not set # CONFIG_MPC5121_GENERIC is not set # CONFIG_PPC_MPC52xx is not set diff --git a/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig b/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig index df125f3..b7eae2b 100644 --- a/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig +++ b/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig @@ -163,6 +163,8 @@ CONFIG_CLASSIC_RCU=y # CONFIG_PPC_MULTIPLATFORM=y CONFIG_CLASSIC32=y +# CONFIG_PPC_CHRP is not set +# CONFIG_PPC_PMAC is not set # CONFIG_MPC5121_ADS is not set # CONFIG_MPC5121_GENERIC is not set # CONFIG_PPC_MPC52xx is not set diff --git a/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig b/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig index 6e0e08c..b0a27a6 100644 --- a/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig +++ b/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig @@ -163,6 +163,8 @@ CONFIG_CLASSIC_RCU=y # CONFIG_PPC_MULTIPLATFORM=y CONFIG_CLASSIC32=y +# CONFIG_PPC_CHRP is not set +# CONFIG_PPC_PMAC is not set # CONFIG_MPC5121_ADS is not set # CONFIG_MPC5121_GENERIC is not set # CONFIG_PPC_MPC52xx is not set diff --git a/arch/powerpc/configs/83xx/mpc832x_mds_defconfig b/arch/powerpc/configs/83xx/mpc832x_mds_defconfig index d6e204a..ad825bc 100644 --- a/arch/powerpc/configs/83xx/mpc832x_mds_defconfig +++ b/arch/powerpc/configs/83xx/mpc832x_mds_defconfig @@ -163,6 +163,8 @@ CONFIG_CLASSIC_RCU=y # CONFIG_PPC_MULTIPLATFORM=y CONFIG_CLASSIC32=y +# CONFIG_PPC_CHRP is not set +# CONFIG_PPC_PMAC is not set # CONFIG_MPC5121_ADS is not set # CONFIG_MPC5121_GENERIC is not set # CONFIG_PPC_MPC52xx is not set diff --git a/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig b/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig index 1f3d343..3826750 100644 --- a/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig +++ b/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig @@ -163,6 +163,8 @@ CONFIG_CLASSIC_RCU=y # CONFIG_PPC_MULTIPLATFORM=y CONFIG_CLASSIC32=y +# CONFIG_PPC_CHRP is not set +# CONFIG_PPC_PMAC is not set # CONFIG_MPC5121_ADS is not set # CONFIG_MPC5121_GENERIC is not set # CONFIG_PPC_MPC52xx is not set diff --git a/arch/powerpc/configs/83xx/mpc834x_itx_defconfig b/arch/powerpc/configs/83xx/mpc834x_itx_defconfig index 4686c21..90aab34 100644 --- a/arch/powerpc/configs/83xx/mpc834x_itx_defconfig +++ b/arch/powerpc/configs/83xx/mpc834x_itx_defconfig @@ -163,6 +163,8 @@ CONFIG_CLASSIC_RCU=y # CONFIG_PPC_MULTIPLATFORM=y CONFIG_CLASSIC32=y +# CONFIG_PPC_CHRP is not set +# CONFIG_PPC_PMAC is not set # CONFIG_MPC5121_ADS is not set # CONFIG_MPC5121_GENERIC is not set # CONFIG_PPC_MPC52xx is not set diff --git a/arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig b/arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig index f11c25e..7458a24 100644 --- a/arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig +++ b/arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig @@ -163,6 +163,8 @@ CONFIG_CLASSIC_RCU=y # CONFIG_PPC_MULTIPLATFORM=y CONFIG_CLASSIC32=y +# CONFIG_PPC_CHRP is not set +# CONFIG_PPC_PMAC is not set # CONFIG_MPC5121_ADS is not set # CONFIG_MPC5121_GENERIC is not set # CONFIG_PPC_MPC52xx is not set diff --git a/arch/powerpc/configs/83xx/mpc834x_mds_defconfig b/arch/powerpc/configs/83xx/mpc834x_mds_defconfig index ffe4b2e..1a92798 100644 --- a/arch/powerpc/configs/83xx/mpc834x_mds_defconfig +++ b/arch/powerpc/configs/83xx/mpc834x_mds_defconfig @@ -163,6 +163,8 @@ CONFIG_CLASSIC_RCU=y # CONFIG_PPC_MULTIPLATFORM=y CONFIG_CLASSIC32=y +# CONFIG_PPC_CHRP is not set +# CONFIG_PPC_PMAC is not set # CONFIG_MPC5121_ADS is not set # CONFIG_MPC5121_GENERIC is not set # CONFIG_PPC_MPC52xx is not set diff --git a/arch/powerpc/configs/83xx/mpc836x_mds_defconfig b/arch/powerpc/configs/83xx/mpc836x_mds_defconfig index 71445e3..03d8ced 100644 --- a/arch/powerpc/configs/83xx/mpc836x_mds_defconfig +++ b/arch/powerpc/configs/83xx/mpc836x_mds_defconfig @@ -163,6 +163,8 @@ CONFIG_CLASSIC_RCU=y # CONFIG_PPC_MULTIPLATFORM=y CONFIG_CLASSIC32=y +# CONFIG_PPC_CHRP is not set +# CONFIG_PPC_PMAC is not set # CONFIG_MPC5121_ADS is not set # CONFIG_MPC5121_GENERIC is not set # CONFIG_PPC_MPC52xx is not set diff --git a/arch/powerpc/configs/83xx/mpc836x_rdk_defconfig b/arch/powerpc/configs/83xx/mpc836x_rdk_defconfig index 58486cc..cdf8417 100644 --- a/arch/powerpc/configs/83xx/mpc836x_rdk_defconfig +++ b/arch/powerpc/configs/83xx/mpc836x_rdk_defconfig @@ -164,6 +164,8 @@ CONFIG_CLASSIC_RCU=y # CONFIG_PPC_MULTIPLATFORM=y CONFIG_CLASSIC32=y +# CONFIG_PPC_CHRP is not set +# CONFIG_PPC_PMAC is not set # CONFIG_MPC5121_ADS is not set # CONFIG_MPC5121_GENERIC is not set # CONFIG_PPC_MPC52xx is not set diff --git a/arch/powerpc/configs/83xx/mpc837x_mds_defconfig b/arch/powerpc/configs/83xx/mpc837x_mds_defconfig index 0171e21..97e02d7 100644 --- a/arch/powerpc/configs/83xx/mpc837x_mds_defconfig +++ b/arch/powerpc/configs/83xx/mpc837x_mds_defconfig @@ -164,6 +164,8 @@ CONFIG_CLASSIC_RCU=y # CONFIG_PPC_MULTIPLATFORM=y CONFIG_CLASSIC32=y +# CONFIG_PPC_CHRP is not set +# CONFIG_PPC_PMAC is not set # CONFIG_MPC5121_ADS is not set # CONFIG_MPC5121_GENERIC is not set # CONFIG_PPC_MPC52xx is not set diff --git a/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig b/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig index d6b383b..5ac3305 100644 --- a/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig +++ b/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig @@ -164,6 +164,8 @@ CONFIG_CLASSIC_RCU=y # CONFIG_PPC_MULTIPLATFORM=y CONFIG_CLASSIC32=y +# CONFIG_PPC_CHRP is not set +# CONFIG_PPC_PMAC is not set # CONFIG_MPC5121_ADS is not set # CONFIG_MPC5121_GENERIC is not set # CONFIG_PPC_MPC52xx is not set diff --git a/arch/powerpc/configs/83xx/sbc834x_defconfig b/arch/powerpc/configs/83xx/sbc834x_defconfig index b8dd17b..c359cc2 100644 --- a/arch/powerpc/configs/83xx/sbc834x_defconfig +++ b/arch/powerpc/configs/83xx/sbc834x_defconfig @@ -162,6 +162,8 @@ CONFIG_CLASSIC_RCU=y # CONFIG_PPC_MULTIPLATFORM=y CONFIG_CLASSIC32=y +# CONFIG_PPC_CHRP is not set +# CONFIG_PPC_PMAC is not set # CONFIG_MPC5121_ADS is not set # CONFIG_MPC5121_GENERIC is not set # CONFIG_PPC_MPC52xx is not set diff --git a/arch/powerpc/configs/86xx/gef_sbc610_defconfig b/arch/powerpc/configs/86xx/gef_sbc610_defconfig index f589489..312d7af 100644 --- a/arch/powerpc/configs/86xx/gef_sbc610_defconfig +++ b/arch/powerpc/configs/86xx/gef_sbc610_defconfig @@ -156,7 +156,10 @@ CONFIG_CLASSIC_RCU=y # # Platform support # -# CONFIG_PPC_MULTIPLATFORM is not set +CONFIG_PPC_MULTIPLATFORM=y +CONFIG_CLASSIC32=y +# CONFIG_PPC_CHRP is not set +# CONFIG_PPC_PMAC is not set # CONFIG_PPC_82xx is not set # CONFIG_PPC_83xx is not set CONFIG_PPC_86xx=y diff --git a/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig b/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig index 14116a8..c98c6ee 100644 --- a/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig +++ b/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig @@ -165,6 +165,8 @@ CONFIG_CLASSIC_RCU=y # CONFIG_PPC_MULTIPLATFORM=y CONFIG_CLASSIC32=y +# CONFIG_PPC_CHRP is not set +# CONFIG_PPC_PMAC is not set # CONFIG_MPC5121_ADS is not set # CONFIG_MPC5121_GENERIC is not set # CONFIG_PPC_MPC52xx is not set diff --git a/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig b/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig index 07e369d..444ddf9 100644 --- a/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig +++ b/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig @@ -167,6 +167,8 @@ CONFIG_CLASSIC_RCU=y # CONFIG_PPC_MULTIPLATFORM=y CONFIG_CLASSIC32=y +# CONFIG_PPC_CHRP is not set +# CONFIG_PPC_PMAC is not set # CONFIG_MPC5121_ADS is not set # CONFIG_MPC5121_GENERIC is not set # CONFIG_PPC_MPC52xx is not set diff --git a/arch/powerpc/configs/86xx/sbc8641d_defconfig b/arch/powerpc/configs/86xx/sbc8641d_defconfig index 3326303..d900f8f 100644 --- a/arch/powerpc/configs/86xx/sbc8641d_defconfig +++ b/arch/powerpc/configs/86xx/sbc8641d_defconfig @@ -166,6 +166,8 @@ CONFIG_CLASSIC_RCU=y # CONFIG_PPC_MULTIPLATFORM=y CONFIG_CLASSIC32=y +# CONFIG_PPC_CHRP is not set +# CONFIG_PPC_PMAC is not set # CONFIG_MPC5121_ADS is not set # CONFIG_MPC5121_GENERIC is not set # CONFIG_PPC_MPC52xx is not set diff --git a/arch/powerpc/configs/ep8248e_defconfig b/arch/powerpc/configs/ep8248e_defconfig index a63cd05..cd691f7 100644 --- a/arch/powerpc/configs/ep8248e_defconfig +++ b/arch/powerpc/configs/ep8248e_defconfig @@ -150,6 +150,8 @@ CONFIG_CLASSIC_RCU=y # CONFIG_PPC_MULTIPLATFORM=y CONFIG_CLASSIC32=y +# CONFIG_PPC_CHRP is not set +# CONFIG_PPC_PMAC is not set # CONFIG_MPC5121_ADS is not set # CONFIG_MPC5121_GENERIC is not set # CONFIG_PPC_MPC52xx is not set diff --git a/arch/powerpc/configs/mpc8272_ads_defconfig b/arch/powerpc/configs/mpc8272_ads_defconfig index ddbca3e..ff6f7c4 100644 --- a/arch/powerpc/configs/mpc8272_ads_defconfig +++ b/arch/powerpc/configs/mpc8272_ads_defconfig @@ -151,6 +151,8 @@ CONFIG_CLASSIC_RCU=y # CONFIG_PPC_MULTIPLATFORM=y CONFIG_CLASSIC32=y +# CONFIG_PPC_CHRP is not set +# CONFIG_PPC_PMAC is not set # CONFIG_MPC5121_ADS is not set # CONFIG_MPC5121_GENERIC is not set # CONFIG_PPC_MPC52xx is not set diff --git a/arch/powerpc/configs/mpc83xx_defconfig b/arch/powerpc/configs/mpc83xx_defconfig index 994a4e7..991c9bd 100644 --- a/arch/powerpc/configs/mpc83xx_defconfig +++ b/arch/powerpc/configs/mpc83xx_defconfig @@ -166,6 +166,8 @@ CONFIG_CLASSIC_RCU=y # CONFIG_PPC_MULTIPLATFORM=y CONFIG_CLASSIC32=y +# CONFIG_PPC_CHRP is not set +# CONFIG_PPC_PMAC is not set # CONFIG_MPC5121_ADS is not set # CONFIG_MPC5121_GENERIC is not set # CONFIG_PPC_MPC52xx is not set diff --git a/arch/powerpc/configs/pq2fads_defconfig b/arch/powerpc/configs/pq2fads_defconfig index e687cc0..7e17862 100644 --- a/arch/powerpc/configs/pq2fads_defconfig +++ b/arch/powerpc/configs/pq2fads_defconfig @@ -152,6 +152,8 @@ CONFIG_CLASSIC_RCU=y # CONFIG_PPC_MULTIPLATFORM=y CONFIG_CLASSIC32=y +# CONFIG_PPC_CHRP is not set +# CONFIG_PPC_PMAC is not set # CONFIG_MPC5121_ADS is not set # CONFIG_MPC5121_GENERIC is not set # CONFIG_PPC_MPC52xx is not set diff --git a/arch/powerpc/include/asm/fsl_lbc.h b/arch/powerpc/include/asm/fsl_lbc.h index 303f548..63a4f77 100644 --- a/arch/powerpc/include/asm/fsl_lbc.h +++ b/arch/powerpc/include/asm/fsl_lbc.h @@ -23,9 +23,9 @@ #ifndef __ASM_FSL_LBC_H #define __ASM_FSL_LBC_H +#include <linux/compiler.h> #include <linux/types.h> -#include <linux/spinlock.h> -#include <asm/io.h> +#include <linux/io.h> struct fsl_lbc_bank { __be32 br; /**< Base Register */ @@ -227,9 +227,6 @@ struct fsl_lbc_regs { u8 res8[0xF00]; }; -extern struct fsl_lbc_regs __iomem *fsl_lbc_regs; -extern spinlock_t fsl_lbc_lock; - /* * FSL UPM routines */ @@ -268,44 +265,7 @@ static inline void fsl_upm_end_pattern(struct fsl_upm *upm) cpu_relax(); } -/** - * fsl_upm_run_pattern - actually run an UPM pattern - * @upm: pointer to the fsl_upm structure obtained via fsl_upm_find - * @io_base: remapped pointer to where memory access should happen - * @mar: MAR register content during pattern execution - * - * This function triggers dummy write to the memory specified by the io_base, - * thus UPM pattern actually executed. Note that mar usage depends on the - * pre-programmed AMX bits in the UPM RAM. - */ -static inline int fsl_upm_run_pattern(struct fsl_upm *upm, - void __iomem *io_base, u32 mar) -{ - int ret = 0; - unsigned long flags; - - spin_lock_irqsave(&fsl_lbc_lock, flags); - - out_be32(&fsl_lbc_regs->mar, mar << (32 - upm->width)); - - switch (upm->width) { - case 8: - out_8(io_base, 0x0); - break; - case 16: - out_be16(io_base, 0x0); - break; - case 32: - out_be32(io_base, 0x0); - break; - default: - ret = -EINVAL; - break; - } - - spin_unlock_irqrestore(&fsl_lbc_lock, flags); - - return ret; -} +extern int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, + u32 mar); #endif /* __ASM_FSL_LBC_H */ diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index 18c0093..590304c 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S @@ -656,10 +656,6 @@ interrupt_base: bne 2f /* Bail if permission mismach */ -#ifdef CONFIG_PTE_64BIT - lwz r13,0(r12) -#endif - /* Jump to common TLB load point */ b finish_tlb_load diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index 174b77e..a848c63 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c @@ -54,11 +54,12 @@ LIST_HEAD(hose_list); static int pci_bus_count; static void -fixup_hide_host_resource_fsl(struct pci_dev* dev) +fixup_hide_host_resource_fsl(struct pci_dev *dev) { int i, class = dev->class >> 8; - if ((class == PCI_CLASS_PROCESSOR_POWERPC) && + if ((class == PCI_CLASS_PROCESSOR_POWERPC || + class == PCI_CLASS_BRIDGE_OTHER) && (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) && (dev->bus->parent == NULL)) { for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig index c62f893..326852c 100644 --- a/arch/powerpc/platforms/512x/Kconfig +++ b/arch/powerpc/platforms/512x/Kconfig @@ -3,6 +3,8 @@ config PPC_MPC512x select FSL_SOC select IPIC select PPC_CLOCK + select PPC_PCI_CHOICE + select FSL_PCI if PCI config PPC_MPC5121 bool diff --git a/arch/powerpc/platforms/512x/mpc5121_ads.c b/arch/powerpc/platforms/512x/mpc5121_ads.c index 5ebf693..441abc4 100644 --- a/arch/powerpc/platforms/512x/mpc5121_ads.c +++ b/arch/powerpc/platforms/512x/mpc5121_ads.c @@ -22,16 +22,26 @@ #include <asm/prom.h> #include <asm/time.h> +#include <sysdev/fsl_pci.h> + #include "mpc512x.h" #include "mpc5121_ads.h" static void __init mpc5121_ads_setup_arch(void) { +#ifdef CONFIG_PCI + struct device_node *np; +#endif printk(KERN_INFO "MPC5121 ADS board from Freescale Semiconductor\n"); /* * cpld regs are needed early */ mpc5121_ads_cpld_map(); + +#ifdef CONFIG_PCI + for_each_compatible_node(np, "pci", "fsl,mpc5121-pci") + mpc83xx_add_bridge(np); +#endif } static void __init mpc5121_ads_init_IRQ(void) diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig index 6159c5d..83c664a 100644 --- a/arch/powerpc/platforms/83xx/Kconfig +++ b/arch/powerpc/platforms/83xx/Kconfig @@ -19,7 +19,6 @@ config MPC831x_RDB config MPC832x_MDS bool "Freescale MPC832x MDS" select DEFAULT_UIMAGE - select QUICC_ENGINE select PPC_MPC832x help This option enables support for the MPC832x MDS evaluation board. @@ -27,7 +26,6 @@ config MPC832x_MDS config MPC832x_RDB bool "Freescale MPC832x RDB" select DEFAULT_UIMAGE - select QUICC_ENGINE select PPC_MPC832x help This option enables support for the MPC8323 RDB board. @@ -57,15 +55,12 @@ config MPC834x_ITX config MPC836x_MDS bool "Freescale MPC836x MDS" select DEFAULT_UIMAGE - select QUICC_ENGINE help This option enables support for the MPC836x MDS Processor Board. config MPC836x_RDK bool "Freescale/Logic MPC836x RDK" select DEFAULT_UIMAGE - select QUICC_ENGINE - select QE_GPIO select FSL_GTM select FSL_LBC help diff --git a/arch/powerpc/platforms/83xx/mpc837x_mds.c b/arch/powerpc/platforms/83xx/mpc837x_mds.c index be62de2..8bb13c8 100644 --- a/arch/powerpc/platforms/83xx/mpc837x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc837x_mds.c @@ -85,8 +85,14 @@ static void __init mpc837x_mds_setup_arch(void) ppc_md.progress("mpc837x_mds_setup_arch()", 0); #ifdef CONFIG_PCI - for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") + for_each_compatible_node(np, "pci", "fsl,mpc8349-pci") { + if (!of_device_is_available(np)) { + pr_warning("%s: disabled by the firmware.\n", + np->full_name); + continue; + } mpc83xx_add_bridge(np); + } #endif mpc837xmds_usb_cfg(); } diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index 291675b..b79dc71 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig @@ -33,7 +33,6 @@ config MPC85xx_CDS config MPC85xx_MDS bool "Freescale MPC85xx MDS" select DEFAULT_UIMAGE - select QUICC_ENGINE select PHYLIB help This option enables support for the MPC85xx MDS board diff --git a/arch/powerpc/platforms/86xx/Makefile b/arch/powerpc/platforms/86xx/Makefile index cb9fc8f..4a56ff6 100644 --- a/arch/powerpc/platforms/86xx/Makefile +++ b/arch/powerpc/platforms/86xx/Makefile @@ -7,4 +7,4 @@ obj-$(CONFIG_SMP) += mpc86xx_smp.o obj-$(CONFIG_MPC8641_HPCN) += mpc86xx_hpcn.o obj-$(CONFIG_SBC8641D) += sbc8641d.o obj-$(CONFIG_MPC8610_HPCD) += mpc8610_hpcd.o -obj-$(CONFIG_GEF_SBC610) += gef_sbc610.o +obj-$(CONFIG_GEF_SBC610) += gef_sbc610.o gef_pic.o diff --git a/arch/powerpc/platforms/86xx/gef_pic.c b/arch/powerpc/platforms/86xx/gef_pic.c new file mode 100644 index 0000000..50d0a2b --- /dev/null +++ b/arch/powerpc/platforms/86xx/gef_pic.c @@ -0,0 +1,258 @@ +/* + * Interrupt handling for GE Fanuc's FPGA based PIC + * + * Author: Martyn Welch <martyn.welch@gefanuc.com> + * + * 2008 (c) GE Fanuc Intelligent Platforms Embedded Systems, Inc. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include <linux/stddef.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <linux/spinlock.h> + +#include <asm/byteorder.h> +#include <asm/io.h> +#include <asm/prom.h> +#include <asm/irq.h> + +#include "gef_pic.h" + +#define DEBUG +#undef DEBUG + +#ifdef DEBUG +#define DBG(fmt...) do { printk(KERN_DEBUG "gef_pic: " fmt); } while (0) +#else +#define DBG(fmt...) do { } while (0) +#endif + +#define GEF_PIC_NUM_IRQS 32 + +/* Interrupt Controller Interface Registers */ +#define GEF_PIC_INTR_STATUS 0x0000 + +#define GEF_PIC_INTR_MASK(cpu) (0x0010 + (0x4 * cpu)) +#define GEF_PIC_CPU0_INTR_MASK GEF_PIC_INTR_MASK(0) +#define GEF_PIC_CPU1_INTR_MASK GEF_PIC_INTR_MASK(1) + +#define GEF_PIC_MCP_MASK(cpu) (0x0018 + (0x4 * cpu)) +#define GEF_PIC_CPU0_MCP_MASK GEF_PIC_MCP_MASK(0) +#define GEF_PIC_CPU1_MCP_MASK GEF_PIC_MCP_MASK(1) + +#define gef_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq) + + +static DEFINE_SPINLOCK(gef_pic_lock); + +static void __iomem *gef_pic_irq_reg_base; +static struct irq_host *gef_pic_irq_host; +static int gef_pic_cascade_irq; + +/* + * Interrupt Controller Handling + * + * The interrupt controller handles interrupts for most on board interrupts, + * apart from PCI interrupts. For example on SBC610: + * + * 17:31 RO Reserved + * 16 RO PCI Express Doorbell 3 Status + * 15 RO PCI Express Doorbell 2 Status + * 14 RO PCI Express Doorbell 1 Status + * 13 RO PCI Express Doorbell 0 Status + * 12 RO Real Time Clock Interrupt Status + * 11 RO Temperature Interrupt Status + * 10 RO Temperature Critical Interrupt Status + * 9 RO Ethernet PHY1 Interrupt Status + * 8 RO Ethernet PHY3 Interrupt Status + * 7 RO PEX8548 Interrupt Status + * 6 RO Reserved + * 5 RO Watchdog 0 Interrupt Status + * 4 RO Watchdog 1 Interrupt Status + * 3 RO AXIS Message FIFO A Interrupt Status + * 2 RO AXIS Message FIFO B Interrupt Status + * 1 RO AXIS Message FIFO C Interrupt Status + * 0 RO AXIS Message FIFO D Interrupt Status + * + * Interrupts can be forwarded to one of two output lines. Nothing + * clever is done, so if the masks are incorrectly set, a single input + * interrupt could generate interrupts on both output lines! + * + * The dual lines are there to allow the chained interrupts to be easily + * passed into two different cores. We currently do not use this functionality + * in this driver. + * + * Controller can also be configured to generate Machine checks (MCP), again on + * two lines, to be attached to two different cores. It is suggested that these + * should be masked out. + */ + +void gef_pic_cascade(unsigned int irq, struct irq_desc *desc) +{ + unsigned int cascade_irq; + + /* + * See if we actually have an interrupt, call generic handling code if + * we do. + */ + cascade_irq = gef_pic_get_irq(); + + if (cascade_irq != NO_IRQ) + generic_handle_irq(cascade_irq); + + desc->chip->eoi(irq); + +} + +static void gef_pic_mask(unsigned int virq) +{ + unsigned long flags; + unsigned int hwirq; + u32 mask; + + hwirq = gef_irq_to_hw(virq); + + spin_lock_irqsave(&gef_pic_lock, flags); + mask = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0)); + mask &= ~(1 << hwirq); + out_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0), mask); + spin_unlock_irqrestore(&gef_pic_lock, flags); +} + +static void gef_pic_mask_ack(unsigned int virq) +{ + /* Don't think we actually have to do anything to ack an interrupt, + * we just need to clear down the devices interrupt and it will go away + */ + gef_pic_mask(virq); +} + +static void gef_pic_unmask(unsigned int virq) +{ + unsigned long flags; + unsigned int hwirq; + u32 mask; + + hwirq = gef_irq_to_hw(virq); + + spin_lock_irqsave(&gef_pic_lock, flags); + mask = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0)); + mask |= (1 << hwirq); + out_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0), mask); + spin_unlock_irqrestore(&gef_pic_lock, flags); +} + +static struct irq_chip gef_pic_chip = { + .typename = "gefp", + .mask = gef_pic_mask, + .mask_ack = gef_pic_mask_ack, + .unmask = gef_pic_unmask, +}; + + +/* When an interrupt is being configured, this call allows some flexibilty + * in deciding which irq_chip structure is used + */ +static int gef_pic_host_map(struct irq_host *h, unsigned int virq, + irq_hw_number_t hwirq) +{ + /* All interrupts are LEVEL sensitive */ + get_irq_desc(virq)->status |= IRQ_LEVEL; + set_irq_chip_and_handler(virq, &gef_pic_chip, handle_level_irq); + + return 0; +} + +static int gef_pic_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) +{ + + *out_hwirq = intspec[0]; + if (intsize > 1) + *out_flags = intspec[1]; + else + *out_flags = IRQ_TYPE_LEVEL_HIGH; + + return 0; +} + +static struct irq_host_ops gef_pic_host_ops = { + .map = gef_pic_host_map, + .xlate = gef_pic_host_xlate, +}; + + +/* + * Initialisation of PIC, this should be called in BSP + */ +void __init gef_pic_init(struct device_node *np) +{ + unsigned long flags; + + /* Map the devices registers into memory */ + gef_pic_irq_reg_base = of_iomap(np, 0); + + spin_lock_irqsave(&gef_pic_lock, flags); + + /* Initialise everything as masked. */ + out_be32(gef_pic_irq_reg_base + GEF_PIC_CPU0_INTR_MASK, 0); + out_be32(gef_pic_irq_reg_base + GEF_PIC_CPU1_INTR_MASK, 0); + + out_be32(gef_pic_irq_reg_base + GEF_PIC_CPU0_MCP_MASK, 0); + out_be32(gef_pic_irq_reg_base + GEF_PIC_CPU1_MCP_MASK, 0); + + spin_unlock_irqrestore(&gef_pic_lock, flags); + + /* Map controller */ + gef_pic_cascade_irq = irq_of_parse_and_map(np, 0); + if (gef_pic_cascade_irq == NO_IRQ) { + printk(KERN_ERR "SBC610: failed to map cascade interrupt"); + return; + } + + /* Setup an irq_host structure */ + gef_pic_irq_host = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, + GEF_PIC_NUM_IRQS, + &gef_pic_host_ops, NO_IRQ); + if (gef_pic_irq_host == NULL) + return; + + /* Chain with parent controller */ + set_irq_chained_handler(gef_pic_cascade_irq, gef_pic_cascade); +} + +/* + * This is called when we receive an interrupt with apparently comes from this + * chip - check, returning the highest interrupt generated or return NO_IRQ + */ +unsigned int gef_pic_get_irq(void) +{ + u32 cause, mask, active; + unsigned int virq = NO_IRQ; + int hwirq; + + cause = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_STATUS); + + mask = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0)); + + active = cause & mask; + + if (active) { + for (hwirq = GEF_PIC_NUM_IRQS - 1; hwirq > -1; hwirq--) { + if (active & (0x1 << hwirq)) + break; + } + virq = irq_linear_revmap(gef_pic_irq_host, + (irq_hw_number_t)hwirq); + } + + return virq; +} + diff --git a/arch/powerpc/platforms/86xx/gef_pic.h b/arch/powerpc/platforms/86xx/gef_pic.h new file mode 100644 index 0000000..6149916 --- /dev/null +++ b/arch/powerpc/platforms/86xx/gef_pic.h @@ -0,0 +1,11 @@ +#ifndef __GEF_PIC_H__ +#define __GEF_PIC_H__ + +#include <linux/init.h> + +void gef_pic_cascade(unsigned int, struct irq_desc *); +unsigned int gef_pic_get_irq(void); +void gef_pic_init(struct device_node *); + +#endif /* __GEF_PIC_H__ */ + diff --git a/arch/powerpc/platforms/86xx/gef_sbc610.c b/arch/powerpc/platforms/86xx/gef_sbc610.c index ee21500..821c45f 100644 --- a/arch/powerpc/platforms/86xx/gef_sbc610.c +++ b/arch/powerpc/platforms/86xx/gef_sbc610.c @@ -39,6 +39,7 @@ #include <sysdev/fsl_soc.h> #include "mpc86xx.h" +#include "gef_pic.h" #undef DEBUG @@ -48,8 +49,31 @@ #define DBG (fmt...) do { } while (0) #endif +void __iomem *sbc610_regs; + +static void __init gef_sbc610_init_irq(void) +{ + struct device_node *cascade_node = NULL; + + mpc86xx_init_irq(); + + /* + * There is a simple interrupt handler in the main FPGA, this needs + * to be cascaded into the MPIC + */ + cascade_node = of_find_compatible_node(NULL, NULL, "gef,fpga-pic"); + if (!cascade_node) { + printk(KERN_WARNING "SBC610: No FPGA PIC\n"); + return; + } + + gef_pic_init(cascade_node); + of_node_put(cascade_node); +} + static void __init gef_sbc610_setup_arch(void) { + struct device_node *regs; #ifdef CONFIG_PCI struct device_node *np; @@ -63,8 +87,43 @@ static void __init gef_sbc610_setup_arch(void) #ifdef CONFIG_SMP mpc86xx_smp_init(); #endif + + /* Remap basic board registers */ + regs = of_find_compatible_node(NULL, NULL, "gef,fpga-regs"); + if (regs) { + sbc610_regs = of_iomap(regs, 0); + if (sbc610_regs == NULL) + printk(KERN_WARNING "Unable to map board registers\n"); + of_node_put(regs); + } +} + +/* Return the PCB revision */ +static unsigned int gef_sbc610_get_pcb_rev(void) +{ + unsigned int reg; + + reg = ioread32(sbc610_regs); + return (reg >> 8) & 0xff; +} + +/* Return the board (software) revision */ +static unsigned int gef_sbc610_get_board_rev(void) +{ + unsigned int reg; + + reg = ioread32(sbc610_regs); + return (reg >> 16) & 0xff; } +/* Return the FPGA revision */ +static unsigned int gef_sbc610_get_fpga_rev(void) +{ + unsigned int reg; + + reg = ioread32(sbc610_regs); + return (reg >> 24) & 0xf; +} static void gef_sbc610_show_cpuinfo(struct seq_file *m) { @@ -73,6 +132,10 @@ static void gef_sbc610_show_cpuinfo(struct seq_file *m) seq_printf(m, "Vendor\t\t: GE Fanuc Intelligent Platforms\n"); + seq_printf(m, "Revision\t: %u%c\n", gef_sbc610_get_pcb_rev(), + ('A' + gef_sbc610_get_board_rev() - 1)); + seq_printf(m, "FPGA Revision\t: %u\n", gef_sbc610_get_fpga_rev()); + seq_printf(m, "SVR\t\t: 0x%x\n", svid); seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); } @@ -145,7 +208,7 @@ define_machine(gef_sbc610) { .name = "GE Fanuc SBC610", .probe = gef_sbc610_probe, .setup_arch = gef_sbc610_setup_arch, - .init_IRQ = mpc86xx_init_irq, + .init_IRQ = gef_sbc610_init_irq, .show_cpuinfo = gef_sbc610_show_cpuinfo, .get_irq = mpic_get_irq, .restart = fsl_rstcr_restart, diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c index 5eedb71..e8d54ac 100644 --- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c +++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c @@ -238,7 +238,6 @@ static void __init mpc86xx_hpcd_setup_arch(void) } #endif #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) - preallocate_diu_videomemory(); diu_ops.get_pixel_format = mpc8610hpcd_get_pixel_format; diu_ops.set_gamma_table = mpc8610hpcd_set_gamma_table; diu_ops.set_monitor_port = mpc8610hpcd_set_monitor_port; diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index 9578c45..47e956c 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig @@ -239,7 +239,8 @@ config TAU_AVERAGE If in doubt, say N here. config QUICC_ENGINE - bool + bool "Freescale QUICC Engine (QE) Support" + depends on FSL_SOC select PPC_LIB_RHEAP select CRC32 help @@ -248,6 +249,15 @@ config QUICC_ENGINE Selecting this option means that you wish to build a kernel for a machine with a QE coprocessor. +config QE_GPIO + bool "QE GPIO support" + depends on QUICC_ENGINE + select GENERIC_GPIO + select ARCH_REQUIRE_GPIOLIB + help + Say Y here if you're going to use hardware that connects to the + QE GPIOs. + config CPM2 bool "Enable support for the CPM2 (Communications Processor Module)" depends on MPC85xx || 8260 diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c index 422c8fa..0494ee5 100644 --- a/arch/powerpc/sysdev/fsl_lbc.c +++ b/arch/powerpc/sysdev/fsl_lbc.c @@ -11,14 +11,19 @@ * (at your option) any later version. */ +#include <linux/init.h> +#include <linux/module.h> #include <linux/kernel.h> +#include <linux/compiler.h> +#include <linux/spinlock.h> +#include <linux/types.h> +#include <linux/io.h> #include <linux/of.h> +#include <asm/prom.h> #include <asm/fsl_lbc.h> -spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock); - -struct fsl_lbc_regs __iomem *fsl_lbc_regs; -EXPORT_SYMBOL(fsl_lbc_regs); +static spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock); +static struct fsl_lbc_regs __iomem *fsl_lbc_regs; static char __initdata *compat_lbc[] = { "fsl,pq2-localbus", @@ -127,3 +132,43 @@ int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm) return 0; } EXPORT_SYMBOL(fsl_upm_find); + +/** + * fsl_upm_run_pattern - actually run an UPM pattern + * @upm: pointer to the fsl_upm structure obtained via fsl_upm_find + * @io_base: remapped pointer to where memory access should happen + * @mar: MAR register content during pattern execution + * + * This function triggers dummy write to the memory specified by the io_base, + * thus UPM pattern actually executed. Note that mar usage depends on the + * pre-programmed AMX bits in the UPM RAM. + */ +int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar) +{ + int ret = 0; + unsigned long flags; + + spin_lock_irqsave(&fsl_lbc_lock, flags); + + out_be32(&fsl_lbc_regs->mar, mar << (32 - upm->width)); + + switch (upm->width) { + case 8: + out_8(io_base, 0x0); + break; + case 16: + out_be16(io_base, 0x0); + break; + case 32: + out_be32(io_base, 0x0); + break; + default: + ret = -EINVAL; + break; + } + + spin_unlock_irqrestore(&fsl_lbc_lock, flags); + + return ret; +} +EXPORT_SYMBOL(fsl_upm_run_pattern); diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 61e6d77..5b264eb 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -1,7 +1,7 @@ /* - * MPC85xx/86xx PCI/PCIE support routing. + * MPC83xx/85xx/86xx PCI/PCIE support routing. * - * Copyright 2007 Freescale Semiconductor, Inc + * Copyright 2007,2008 Freescale Semiconductor, Inc * * Initial author: Xianghua Xiao <x.xiao@freescale.com> * Recode: ZHANG WEI <wei.zhang@freescale.com> @@ -251,20 +251,47 @@ DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641D, quirk_fsl_pcie_header); DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8610, quirk_fsl_pcie_header); #endif /* CONFIG_PPC_85xx || CONFIG_PPC_86xx */ -#if defined(CONFIG_PPC_83xx) +#if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x) int __init mpc83xx_add_bridge(struct device_node *dev) { int len; struct pci_controller *hose; - struct resource rsrc; + struct resource rsrc_reg; + struct resource rsrc_cfg; const int *bus_range; - int primary = 1, has_address = 0; - phys_addr_t immr = get_immrbase(); + int primary; pr_debug("Adding PCI host bridge %s\n", dev->full_name); /* Fetch host bridge registers address */ - has_address = (of_address_to_resource(dev, 0, &rsrc) == 0); + if (of_address_to_resource(dev, 0, &rsrc_reg)) { + printk(KERN_WARNING "Can't get pci register base!\n"); + return -ENOMEM; + } + + memset(&rsrc_cfg, 0, sizeof(rsrc_cfg)); + + if (of_address_to_resource(dev, 1, &rsrc_cfg)) { + printk(KERN_WARNING + "No pci config register base in dev tree, " + "using default\n"); + /* + * MPC83xx supports up to two host controllers + * one at 0x8500 has config space registers at 0x8300 + * one at 0x8600 has config space registers at 0x8380 + */ + if ((rsrc_reg.start & 0xfffff) == 0x8500) + rsrc_cfg.start = (rsrc_reg.start & 0xfff00000) + 0x8300; + else if ((rsrc_reg.start & 0xfffff) == 0x8600) + rsrc_cfg.start = (rsrc_reg.start & 0xfff00000) + 0x8380; + } + /* + * Controller at offset 0x8500 is primary + */ + if ((rsrc_reg.start & 0xfffff) == 0x8500) + primary = 1; + else + primary = 0; /* Get bus range if any */ bus_range = of_get_property(dev, "bus-range", &len); @@ -281,22 +308,11 @@ int __init mpc83xx_add_bridge(struct device_node *dev) hose->first_busno = bus_range ? bus_range[0] : 0; hose->last_busno = bus_range ? bus_range[1] : 0xff; - /* MPC83xx supports up to two host controllers one at 0x8500 from immrbar - * the other at 0x8600, we consider the 0x8500 the primary controller - */ - /* PCI 1 */ - if ((rsrc.start & 0xfffff) == 0x8500) { - setup_indirect_pci(hose, immr + 0x8300, immr + 0x8304, 0); - } - /* PCI 2 */ - if ((rsrc.start & 0xfffff) == 0x8600) { - setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384, 0); - primary = 0; - } + setup_indirect_pci(hose, rsrc_cfg.start, rsrc_cfg.start + 4, 0); - printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%016llx. " + printk(KERN_INFO "Found FSL PCI host bridge at 0x%016llx. " "Firmware bus number: %d->%d\n", - (unsigned long long)rsrc.start, hose->first_busno, + (unsigned long long)rsrc_reg.start, hose->first_busno, hose->last_busno); pr_debug(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n", diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index eeb0700..01b884b 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c @@ -720,42 +720,6 @@ void fsl_rstcr_restart(char *cmd) #endif #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) -struct platform_diu_data_ops diu_ops = { - .diu_size = 1280 * 1024 * 4, /* default one 1280x1024 buffer */ -}; +struct platform_diu_data_ops diu_ops; EXPORT_SYMBOL(diu_ops); - -int __init preallocate_diu_videomemory(void) -{ - pr_debug("diu_size=%lu\n", diu_ops.diu_size); - - diu_ops.diu_mem = __alloc_bootmem(diu_ops.diu_size, 8, 0); - if (!diu_ops.diu_mem) { - printk(KERN_ERR "fsl-diu: cannot allocate %lu bytes\n", - diu_ops.diu_size); - return -ENOMEM; - } - - pr_debug("diu_mem=%p\n", diu_ops.diu_mem); - - rh_init(&diu_ops.diu_rh_info, 4096, ARRAY_SIZE(diu_ops.diu_rh_block), - diu_ops.diu_rh_block); - return rh_attach_region(&diu_ops.diu_rh_info, - (unsigned long) diu_ops.diu_mem, - diu_ops.diu_size); -} - -static int __init early_parse_diufb(char *p) -{ - if (!p) - return 1; - - diu_ops.diu_size = _ALIGN_UP(memparse(p, &p), 8); - - pr_debug("diu_size=%lu\n", diu_ops.diu_size); - - return 0; -} -early_param("diufb", early_parse_diufb); - #endif diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h index 0242998..60f7f22 100644 --- a/arch/powerpc/sysdev/fsl_soc.h +++ b/arch/powerpc/sysdev/fsl_soc.h @@ -20,14 +20,7 @@ extern int fsl_spi_init(struct spi_board_info *board_infos, extern void fsl_rstcr_restart(char *cmd); #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) -#include <linux/bootmem.h> -#include <asm/rheap.h> struct platform_diu_data_ops { - rh_block_t diu_rh_block[16]; - rh_info_t diu_rh_info; - unsigned long diu_size; - void *diu_mem; - unsigned int (*get_pixel_format) (unsigned int bits_per_pixel, int monitor_port); void (*set_gamma_table) (int monitor_port, char *gamma_table_base); @@ -38,7 +31,6 @@ struct platform_diu_data_ops { }; extern struct platform_diu_data_ops diu_ops; -int __init preallocate_diu_videomemory(void); #endif #endif diff --git a/arch/powerpc/sysdev/qe_lib/Kconfig b/arch/powerpc/sysdev/qe_lib/Kconfig index 1ce5464..76ffbc4 100644 --- a/arch/powerpc/sysdev/qe_lib/Kconfig +++ b/arch/powerpc/sysdev/qe_lib/Kconfig @@ -24,12 +24,3 @@ config QE_USB bool help QE USB Host Controller support - -config QE_GPIO - bool "QE GPIO support" - depends on QUICC_ENGINE - select GENERIC_GPIO - select ARCH_REQUIRE_GPIOLIB - help - Say Y here if you're going to use hardware that connects to the - QE GPIOs. diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig index a95cb94..1735682 100644 --- a/drivers/i2c/chips/Kconfig +++ b/drivers/i2c/chips/Kconfig @@ -172,4 +172,15 @@ config MENELAUS and other features that are often used in portable devices like cell phones and PDAs. +config MCU_MPC8349EMITX + tristate "MPC8349E-mITX MCU driver" + depends on I2C && PPC_83xx + select GENERIC_GPIO + select ARCH_REQUIRE_GPIOLIB + help + Say Y here to enable soft power-off functionality on the Freescale + boards with the MPC8349E-mITX-compatible MCU chips. This driver will + also register MCU GPIOs with the generic GPIO API, so you'll able + to use MCU pins as GPIOs. + endmenu diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile index 39e3e69..ca520fa 100644 --- a/drivers/i2c/chips/Makefile +++ b/drivers/i2c/chips/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o obj-$(CONFIG_TPS65010) += tps65010.o obj-$(CONFIG_MENELAUS) += menelaus.o obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o +obj-$(CONFIG_MCU_MPC8349EMITX) += mcu_mpc8349emitx.o ifeq ($(CONFIG_I2C_DEBUG_CHIP),y) EXTRA_CFLAGS += -DDEBUG diff --git a/drivers/i2c/chips/mcu_mpc8349emitx.c b/drivers/i2c/chips/mcu_mpc8349emitx.c new file mode 100644 index 0000000..82a9bcb --- /dev/null +++ b/drivers/i2c/chips/mcu_mpc8349emitx.c @@ -0,0 +1,209 @@ +/* + * Power Management and GPIO expander driver for MPC8349E-mITX-compatible MCU + * + * Copyright (c) 2008 MontaVista Software, Inc. + * + * Author: Anton Vorontsov <avorontsov@ru.mvista.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. + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/device.h> +#include <linux/mutex.h> +#include <linux/i2c.h> +#include <linux/gpio.h> +#include <linux/of.h> +#include <linux/of_gpio.h> +#include <asm/prom.h> +#include <asm/machdep.h> + +/* + * I don't have specifications for the MCU firmware, I found this register + * and bits positions by the trial&error method. + */ +#define MCU_REG_CTRL 0x20 +#define MCU_CTRL_POFF 0x40 + +#define MCU_NUM_GPIO 2 + +struct mcu { + struct mutex lock; + struct device_node *np; + struct i2c_client *client; + struct of_gpio_chip of_gc; + u8 reg_ctrl; +}; + +static struct mcu *glob_mcu; + +static void mcu_power_off(void) +{ + struct mcu *mcu = glob_mcu; + + pr_info("Sending power-off request to the MCU...\n"); + mutex_lock(&mcu->lock); + i2c_smbus_write_byte_data(glob_mcu->client, MCU_REG_CTRL, + mcu->reg_ctrl | MCU_CTRL_POFF); + mutex_unlock(&mcu->lock); +} + +static void mcu_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) +{ + struct of_gpio_chip *of_gc = to_of_gpio_chip(gc); + struct mcu *mcu = container_of(of_gc, struct mcu, of_gc); + u8 bit = 1 << (4 + gpio); + + mutex_lock(&mcu->lock); + if (val) + mcu->reg_ctrl &= ~bit; + else + mcu->reg_ctrl |= bit; + + i2c_smbus_write_byte_data(mcu->client, MCU_REG_CTRL, mcu->reg_ctrl); + mutex_unlock(&mcu->lock); +} + +static int mcu_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) +{ + mcu_gpio_set(gc, gpio, val); + return 0; +} + +static int mcu_gpiochip_add(struct mcu *mcu) +{ + struct device_node *np; + struct of_gpio_chip *of_gc = &mcu->of_gc; + struct gpio_chip *gc = &of_gc->gc; + int ret; + + np = of_find_compatible_node(NULL, NULL, "fsl,mcu-mpc8349emitx"); + if (!np) + return -ENODEV; + + gc->owner = THIS_MODULE; + gc->label = np->full_name; + gc->can_sleep = 1; + gc->ngpio = MCU_NUM_GPIO; + gc->base = -1; + gc->set = mcu_gpio_set; + gc->direction_output = mcu_gpio_dir_out; + of_gc->gpio_cells = 2; + of_gc->xlate = of_gpio_simple_xlate; + + np->data = of_gc; + mcu->np = np; + + /* + * We don't want to lose the node, its ->data and ->full_name... + * So, if succeeded, we don't put the node here. + */ + ret = gpiochip_add(gc); + if (ret) + of_node_put(np); + return ret; +} + +static int mcu_gpiochip_remove(struct mcu *mcu) +{ + int ret; + + ret = gpiochip_remove(&mcu->of_gc.gc); + if (ret) + return ret; + of_node_put(mcu->np); + + return 0; +} + +static int __devinit mcu_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct mcu *mcu; + int ret; + + mcu = kzalloc(sizeof(*mcu), GFP_KERNEL); + if (!mcu) + return -ENOMEM; + + mutex_init(&mcu->lock); + mcu->client = client; + i2c_set_clientdata(client, mcu); + + ret = i2c_smbus_read_byte_data(mcu->client, MCU_REG_CTRL); + if (ret < 0) + goto err; + mcu->reg_ctrl = ret; + + ret = mcu_gpiochip_add(mcu); + if (ret) + goto err; + + /* XXX: this is potentially racy, but there is no lock for ppc_md */ + if (!ppc_md.power_off) { + glob_mcu = mcu; + ppc_md.power_off = mcu_power_off; + dev_info(&client->dev, "will provide power-off service\n"); + } + + return 0; +err: + kfree(mcu); + return ret; +} + +static int __devexit mcu_remove(struct i2c_client *client) +{ + struct mcu *mcu = i2c_get_clientdata(client); + int ret; + + if (glob_mcu == mcu) { + ppc_md.power_off = NULL; + glob_mcu = NULL; + } + + ret = mcu_gpiochip_remove(mcu); + if (ret) + return ret; + i2c_set_clientdata(client, NULL); + kfree(mcu); + return 0; +} + +static const struct i2c_device_id mcu_ids[] = { + { "mcu-mpc8349emitx", }, + {}, +}; +MODULE_DEVICE_TABLE(i2c, mcu_ids); + +static struct i2c_driver mcu_driver = { + .driver = { + .name = "mcu-mpc8349emitx", + .owner = THIS_MODULE, + }, + .probe = mcu_probe, + .remove = __devexit_p(mcu_remove), + .id_table = mcu_ids, +}; + +static int __init mcu_init(void) +{ + return i2c_add_driver(&mcu_driver); +} +module_init(mcu_init); + +static void __exit mcu_exit(void) +{ + i2c_del_driver(&mcu_driver); +} +module_exit(mcu_exit); + +MODULE_DESCRIPTION("Power Management and GPIO expander driver for " + "MPC8349E-mITX-compatible MCU"); +MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>"); +MODULE_LICENSE("GPL"); |