diff options
author | Alex Shi <alex.shi@linaro.org> | 2015-11-16 10:57:25 +0800 |
---|---|---|
committer | Alex Shi <alex.shi@linaro.org> | 2015-11-16 10:57:25 +0800 |
commit | 29ed9e09b5173c3bbc9999c1ecebd9823c09857c (patch) | |
tree | 7a2fd309af6abf1a3c610e28b658e7ecfd630189 /arch | |
parent | 82c795655f6297b9efdcee2643ff937e1849ad83 (diff) | |
parent | 9b42b559544c7ad3d246b6ad4c1125a74d02136a (diff) |
Merge remote-tracking branch 'origin/v3.18/topic/pcie/master' into linux-linaro-lsk-v3.18
Conflicts solution:
/* Using the latest version dts', that is except the serial
* port definition in juno.dts, others keep the pcie/master
* version.
*/
arch/arm64/boot/dts/arm/Makefile
arch/arm64/boot/dts/arm/juno-clocks.dtsi
arch/arm64/boot/dts/arm/juno.dts
Diffstat (limited to 'arch')
94 files changed, 1496 insertions, 466 deletions
diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c index 076c35cd6cde..f249000a65ac 100644 --- a/arch/alpha/kernel/pci.c +++ b/arch/alpha/kernel/pci.c @@ -334,6 +334,8 @@ common_init_pci(void) bus = pci_scan_root_bus(NULL, next_busno, alpha_mv.pci_ops, hose, &resources); + if (!bus) + continue; hose->bus = bus; hose->need_domain_info = need_domain_info; next_busno = bus->busn_res.end + 1; @@ -349,6 +351,11 @@ common_init_pci(void) pci_assign_unassigned_resources(); pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq); + for (hose = hose_head; hose; hose = hose->next) { + bus = hose->bus; + if (bus) + pci_bus_add_devices(bus); + } } diff --git a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c index 837c0fa58317..700686d04869 100644 --- a/arch/alpha/kernel/sys_nautilus.c +++ b/arch/alpha/kernel/sys_nautilus.c @@ -207,6 +207,9 @@ nautilus_init_pci(void) /* Scan our single hose. */ bus = pci_scan_bus(0, alpha_mv.pci_ops, hose); + if (!bus) + return; + hose->bus = bus; pcibios_claim_one_bus(bus); @@ -253,6 +256,7 @@ nautilus_init_pci(void) for the root bus, so just clear it. */ bus->self = NULL; pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq); + pci_bus_add_devices(bus); } /* diff --git a/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi index d3c0bf5c84e3..b5756c21ea1d 100644 --- a/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi +++ b/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi @@ -282,7 +282,6 @@ }; &ssi1 { - fsl,mode = "i2s-slave"; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi index cade1bdc97e9..86f03c1b147c 100644 --- a/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi +++ b/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi @@ -287,7 +287,6 @@ }; &ssi1 { - fsl,mode = "i2s-slave"; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi index cf13239a1619..4a8d97f47759 100644 --- a/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi +++ b/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi @@ -376,12 +376,10 @@ }; &ssi1 { - fsl,mode = "i2s-slave"; status = "okay"; }; &ssi2 { - fsl,mode = "i2s-slave"; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi b/arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi index 584721264121..585b4f6986c1 100644 --- a/arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi +++ b/arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi @@ -9,17 +9,103 @@ * http://www.gnu.org/copyleft/gpl.html */ +#include <dt-bindings/sound/fsl-imx-audmux.h> + / { chosen { linux,stdout-path = &uart4; }; + + regulators { + sound_1v8: regulator@2 { + compatible = "regulator-fixed"; + reg = <2>; + regulator-name = "i2s-audio-1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + sound_3v3: regulator@3 { + compatible = "regulator-fixed"; + reg = <3>; + regulator-name = "i2s-audio-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + }; + + tlv320_mclk: oscillator { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <19200000>; + clock-output-names = "tlv320-mclk"; + }; + + sound { + compatible = "simple-audio-card"; + simple-audio-card,name = "OnboardTLV320AIC3007"; + simple-audio-card,format = "i2s"; + simple-audio-card,bitclock-master = <&dailink_master>; + simple-audio-card,frame-master = <&dailink_master>; + simple-audio-card,widgets = + "Microphone", "Mic Jack", + "Line", "Line In", + "Line", "Line Out", + "Speaker", "Speaker", + "Headphone", "Headphone Jack"; + simple-audio-card,routing = + "Line Out", "LLOUT", + "Line Out", "RLOUT", + "Speaker", "SPOP", + "Speaker", "SPOM", + "Headphone Jack", "HPLOUT", + "Headphone Jack", "HPROUT", + "MIC3L", "Mic Jack", + "MIC3R", "Mic Jack", + "Mic Jack", "Mic Bias", + "LINE1L", "Line In", + "LINE1R", "Line In"; + + simple-audio-card,cpu { + sound-dai = <&ssi2>; + }; + + dailink_master: simple-audio-card,codec { + sound-dai = <&codec>; + clocks = <&tlv320_mclk>; + }; + }; + }; -&fec { +&audmux { status = "okay"; + + ssi2 { + fsl,audmux-port = <1>; + fsl,port-config = < + (IMX_AUDMUX_V2_PTCR_TFSDIR | + IMX_AUDMUX_V2_PTCR_TFSEL(4) | + IMX_AUDMUX_V2_PTCR_TCLKDIR | + IMX_AUDMUX_V2_PTCR_TCSEL(4)) + IMX_AUDMUX_V2_PDCR_RXDSEL(4) + >; + }; + + pins5 { + fsl,audmux-port = <4>; + fsl,port-config = < + 0x00000000 + IMX_AUDMUX_V2_PDCR_RXDSEL(1) + >; + }; }; -&gpmi { +&can1 { + status = "okay"; +}; + +&fec { status = "okay"; }; @@ -28,14 +114,18 @@ }; &i2c2 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_i2c2>; - clock-frequency = <100000>; status = "okay"; - tlv320@18 { - compatible = "ti,tlv320aic3x"; + codec: tlv320@18 { + compatible = "ti,tlv320aic3007"; + #sound-dai-cells = <0>; reg = <0x18>; + ai3x-micbias-vg = <2>; + + AVDD-supply = <&sound_3v3>; + IOVDD-supply = <&sound_3v3>; + DRVDD-supply = <&sound_3v3>; + DVDD-supply = <&sound_1v8>; }; stmpe@41 { @@ -55,9 +145,14 @@ }; &i2c3 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_i2c3>; - clock-frequency = <100000>; + status = "okay"; +}; + +&pcie { + status = "okay"; +}; + +&ssi2 { status = "okay"; }; @@ -84,19 +179,3 @@ &usdhc3 { status = "okay"; }; - -&iomuxc { - pinctrl_i2c2: i2c2grp { - fsl,pins = < - MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1 - MX6QDL_PAD_EIM_D16__I2C2_SDA 0x4001b8b1 - >; - }; - - pinctrl_i2c3: i2c3grp { - fsl,pins = < - MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1 - MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1 - >; - }; -}; diff --git a/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi b/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi index 413569752422..1ce6133b67f5 100644 --- a/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi +++ b/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi @@ -60,6 +60,18 @@ }; }; +&audmux { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audmux>; + status = "disabled"; +}; + +&can1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan1>; + status = "disabled"; +}; + &ecspi3 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_ecspi3>; @@ -74,6 +86,22 @@ }; }; +&fec { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet>; + phy-mode = "rgmii"; + phy-reset-gpios = <&gpio3 23 GPIO_ACTIVE_LOW>; + phy-supply = <&vdd_eth_io_reg>; + status = "disabled"; +}; + +&gpmi { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpmi_nand>; + nand-on-flash-bbt; + status = "okay"; +}; + &i2c1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c1>; @@ -87,8 +115,8 @@ pmic@58 { compatible = "dlg,da9063"; reg = <0x58>; - interrupt-parent = <&gpio4>; - interrupts = <17 0x8>; /* active-low GPIO4_17 */ + interrupt-parent = <&gpio2>; + interrupts = <9 0x8>; /* active-low GPIO2_9 */ regulators { vddcore_reg: bcore1 { @@ -164,6 +192,18 @@ }; }; +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c2>; + clock-frequency = <100000>; +}; + +&i2c3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c3>; + clock-frequency = <100000>; +}; + &iomuxc { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_hog>; @@ -173,7 +213,7 @@ fsl,pins = < MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x80000000 MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24 0x80000000 /* SPI NOR chipselect */ - MX6QDL_PAD_DI0_PIN15__GPIO4_IO17 0x80000000 /* PMIC interrupt */ + MX6QDL_PAD_SD4_DAT1__GPIO2_IO09 0x80000000 /* PMIC interrupt */ MX6QDL_PAD_ENET_TXD0__GPIO1_IO30 0x80000000 /* Green LED */ MX6QDL_PAD_EIM_EB3__GPIO2_IO31 0x80000000 /* Red LED */ >; @@ -208,6 +248,13 @@ >; }; + pinctrl_flexcan1: flexcan1grp { + fsl,pins = < + MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x1b0b0 + MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x1b0b0 + >; + }; + pinctrl_gpmi_nand: gpminandgrp { fsl,pins = < MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1 @@ -237,6 +284,24 @@ >; }; + pinctrl_i2c2: i2c2grp { + fsl,pins = < + MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1 + MX6QDL_PAD_EIM_D16__I2C2_SDA 0x4001b8b1 + >; + }; + + pinctrl_i2c3: i2c3grp { + fsl,pins = < + MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1 + MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1 + >; + }; + + pinctrl_pcie: pciegrp { + fsl,pins = <MX6QDL_PAD_DI0_PIN15__GPIO4_IO17 0x80000000>; + }; + pinctrl_uart3: uart3grp { fsl,pins = < MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1 @@ -295,22 +360,22 @@ MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000 >; }; - }; -}; -&fec { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_enet>; - phy-mode = "rgmii"; - phy-reset-gpios = <&gpio3 23 GPIO_ACTIVE_LOW>; - phy-supply = <&vdd_eth_io_reg>; - status = "disabled"; + pinctrl_audmux: audmuxgrp { + fsl,pins = < + MX6QDL_PAD_DISP0_DAT16__AUD5_TXC 0x130b0 + MX6QDL_PAD_DISP0_DAT17__AUD5_TXD 0x110b0 + MX6QDL_PAD_DISP0_DAT18__AUD5_TXFS 0x130b0 + MX6QDL_PAD_DISP0_DAT19__AUD5_RXD 0x130b0 + >; + }; + }; }; -&gpmi { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_gpmi_nand>; - nand-on-flash-bbt; +&pcie { + pinctrl-name = "default"; + pinctrl-0 = <&pinctrl_pcie>; + reset-gpio = <&gpio4 17 0>; status = "disabled"; }; diff --git a/arch/arm/boot/dts/imx6qdl-rex.dtsi b/arch/arm/boot/dts/imx6qdl-rex.dtsi index 4b5e8c87e53f..394a4ace351a 100644 --- a/arch/arm/boot/dts/imx6qdl-rex.dtsi +++ b/arch/arm/boot/dts/imx6qdl-rex.dtsi @@ -306,7 +306,6 @@ }; &ssi1 { - fsl,mode = "i2s-slave"; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi index b57e554dba4e..0565921877ab 100644 --- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi +++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi @@ -109,10 +109,8 @@ "Headphone Jack", "HPOUTR", "Ext Spk", "SPKOUTL", "Ext Spk", "SPKOUTR", - "MICBIAS", "AMIC", - "IN3R", "MICBIAS", - "DMIC", "MICBIAS", - "DMICDAT", "DMIC"; + "AMIC", "MICBIAS", + "IN3R", "AMIC"; mux-int-port = <2>; mux-ext-port = <3>; }; @@ -181,7 +179,7 @@ codec: wm8962@1a { compatible = "wlf,wm8962"; reg = <0x1a>; - clocks = <&clks 201>; + clocks = <&clks IMX6QDL_CLK_CKO>; DCVDD-supply = <®_audio>; DBVDD-supply = <®_audio>; AVDD-supply = <®_audio>; diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi index 9596ed5867e6..39abef10a7bc 100644 --- a/arch/arm/boot/dts/imx6qdl.dtsi +++ b/arch/arm/boot/dts/imx6qdl.dtsi @@ -53,6 +53,7 @@ interrupt-controller; reg = <0x00a01000 0x1000>, <0x00a00100 0x100>; + interrupt-parent = <&intc>; }; clocks { @@ -82,7 +83,7 @@ #address-cells = <1>; #size-cells = <1>; compatible = "simple-bus"; - interrupt-parent = <&intc>; + interrupt-parent = <&gpc>; ranges; dma_apbh: dma-apbh@00110000 { @@ -122,6 +123,7 @@ compatible = "arm,cortex-a9-twd-timer"; reg = <0x00a00600 0x20>; interrupts = <1 13 0xf01>; + interrupt-parent = <&intc>; clocks = <&clks IMX6QDL_CLK_TWD>; }; @@ -151,10 +153,10 @@ interrupt-names = "msi"; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 0x7>; - interrupt-map = <0 0 0 1 &intc GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>, - <0 0 0 2 &intc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>, - <0 0 0 3 &intc GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>, - <0 0 0 4 &intc GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>; + interrupt-map = <0 0 0 1 &gpc GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &gpc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &gpc GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &gpc GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clks IMX6QDL_CLK_PCIE_AXI>, <&clks IMX6QDL_CLK_LVDS1_GATE>, <&clks IMX6QDL_CLK_PCIE_REF_125M>; @@ -680,8 +682,11 @@ gpc: gpc@020dc000 { compatible = "fsl,imx6q-gpc"; reg = <0x020dc000 0x4000>; + interrupt-controller; + #interrupt-cells = <3>; interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>, <0 90 IRQ_TYPE_LEVEL_HIGH>; + interrupt-parent = <&intc>; }; gpr: iomuxc-gpr@020e0000 { diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi index dfd83e6d8087..960a66930cc5 100644 --- a/arch/arm/boot/dts/imx6sl.dtsi +++ b/arch/arm/boot/dts/imx6sl.dtsi @@ -72,6 +72,7 @@ interrupt-controller; reg = <0x00a01000 0x1000>, <0x00a00100 0x100>; + interrupt-parent = <&intc>; }; clocks { @@ -95,7 +96,7 @@ #address-cells = <1>; #size-cells = <1>; compatible = "simple-bus"; - interrupt-parent = <&intc>; + interrupt-parent = <&gpc>; ranges; ocram: sram@00900000 { @@ -597,7 +598,10 @@ gpc: gpc@020dc000 { compatible = "fsl,imx6sl-gpc", "fsl,imx6q-gpc"; reg = <0x020dc000 0x4000>; + interrupt-controller; + #interrupt-cells = <3>; interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>; + interrupt-parent = <&intc>; }; gpr: iomuxc-gpr@020e0000 { diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi index f3e88c03b1e4..22c9fc0fbc9e 100644 --- a/arch/arm/boot/dts/imx6sx.dtsi +++ b/arch/arm/boot/dts/imx6sx.dtsi @@ -88,6 +88,7 @@ interrupt-controller; reg = <0x00a01000 0x1000>, <0x00a00100 0x100>; + interrupt-parent = <&intc>; }; clocks { @@ -131,7 +132,7 @@ #address-cells = <1>; #size-cells = <1>; compatible = "simple-bus"; - interrupt-parent = <&intc>; + interrupt-parent = <&gpc>; ranges; pmu { @@ -694,7 +695,10 @@ gpc: gpc@020dc000 { compatible = "fsl,imx6sx-gpc", "fsl,imx6q-gpc"; reg = <0x020dc000 0x4000>; + interrupt-controller; + #interrupt-cells = <3>; interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>; + interrupt-parent = <&intc>; }; iomuxc: iomuxc@020e0000 { diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index 85738b200023..f3c0d953f6a2 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h @@ -121,12 +121,14 @@ static inline unsigned long dma_max_pfn(struct device *dev) } #define dma_max_pfn(dev) dma_max_pfn(dev) -static inline int set_arch_dma_coherent_ops(struct device *dev) +static inline void arch_setup_dma_ops(struct device *dev, u64 dma_base, + u64 size, struct iommu_ops *iommu, + bool coherent) { - set_dma_ops(dev, &arm_coherent_dma_ops); - return 0; + if (coherent) + set_dma_ops(dev, &arm_coherent_dma_ops); } -#define set_arch_dma_coherent_ops(dev) set_arch_dma_coherent_ops(dev) +#define arch_setup_dma_ops arch_setup_dma_ops static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) { diff --git a/arch/arm/include/asm/mach/pci.h b/arch/arm/include/asm/mach/pci.h index 7fc42784becb..8292b5f81e23 100644 --- a/arch/arm/include/asm/mach/pci.h +++ b/arch/arm/include/asm/mach/pci.h @@ -22,6 +22,9 @@ struct hw_pci { #ifdef CONFIG_PCI_DOMAINS int domain; #endif +#ifdef CONFIG_PCI_MSI + struct msi_controller *msi_ctrl; +#endif struct pci_ops *ops; int nr_controllers; void **private_data; @@ -36,8 +39,6 @@ struct hw_pci { resource_size_t start, resource_size_t size, resource_size_t align); - void (*add_bus)(struct pci_bus *bus); - void (*remove_bus)(struct pci_bus *bus); }; /* @@ -47,6 +48,9 @@ struct pci_sys_data { #ifdef CONFIG_PCI_DOMAINS int domain; #endif +#ifdef CONFIG_PCI_MSI + struct msi_controller *msi_ctrl; +#endif struct list_head node; int busnr; /* primary bus number */ u64 mem_offset; /* bus->cpu memory mapping offset */ @@ -65,8 +69,6 @@ struct pci_sys_data { resource_size_t start, resource_size_t size, resource_size_t align); - void (*add_bus)(struct pci_bus *bus); - void (*remove_bus)(struct pci_bus *bus); void *private_data; /* platform controller private data */ }; diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index 17a26c17f7f5..daaff73bc776 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -18,6 +18,15 @@ static int debug_pci; +#ifdef CONFIG_PCI_MSI +struct msi_controller *pcibios_msi_controller(struct pci_dev *dev) +{ + struct pci_sys_data *sysdata = dev->bus->sysdata; + + return sysdata->msi_ctrl; +} +#endif + /* * We can't use pci_get_device() here since we are * called from interrupt context. @@ -360,20 +369,6 @@ void pcibios_fixup_bus(struct pci_bus *bus) } EXPORT_SYMBOL(pcibios_fixup_bus); -void pcibios_add_bus(struct pci_bus *bus) -{ - struct pci_sys_data *sys = bus->sysdata; - if (sys->add_bus) - sys->add_bus(bus); -} - -void pcibios_remove_bus(struct pci_bus *bus) -{ - struct pci_sys_data *sys = bus->sysdata; - if (sys->remove_bus) - sys->remove_bus(bus); -} - /* * Swizzle the device pin each time we cross a bridge. If a platform does * not provide a swizzle function, we perform the standard PCI swizzling. @@ -471,12 +466,13 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw, #ifdef CONFIG_PCI_DOMAINS sys->domain = hw->domain; #endif +#ifdef CONFIG_PCI_MSI + sys->msi_ctrl = hw->msi_ctrl; +#endif sys->busnr = busnr; sys->swizzle = hw->swizzle; sys->map_irq = hw->map_irq; sys->align_resource = hw->align_resource; - sys->add_bus = hw->add_bus; - sys->remove_bus = hw->remove_bus; INIT_LIST_HEAD(&sys->resources); if (hw->private_data) diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 11b2957f792b..5d4017351b7b 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -50,6 +50,7 @@ config HAVE_IMX_ANATOP config HAVE_IMX_GPC bool + select PM_GENERIC_DOMAINS if PM config HAVE_IMX_MMDC bool diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index 6e4fcd8339cd..e5fa5eeeea52 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -32,8 +32,7 @@ ifeq ($(CONFIG_CPU_IDLE),y) obj-$(CONFIG_SOC_IMX5) += cpuidle-imx5.o obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o obj-$(CONFIG_SOC_IMX6SL) += cpuidle-imx6sl.o -# i.MX6SX reuses i.MX6Q cpuidle driver -obj-$(CONFIG_SOC_IMX6SX) += cpuidle-imx6q.o +obj-$(CONFIG_SOC_IMX6SX) += cpuidle-imx6sx.o endif ifdef CONFIG_SND_IMX_SOC diff --git a/arch/arm/mach-imx/clk-pllv3.c b/arch/arm/mach-imx/clk-pllv3.c index 57de74da0acf..0ad6e5442fd8 100644 --- a/arch/arm/mach-imx/clk-pllv3.c +++ b/arch/arm/mach-imx/clk-pllv3.c @@ -69,7 +69,6 @@ static int clk_pllv3_prepare(struct clk_hw *hw) { struct clk_pllv3 *pll = to_clk_pllv3(hw); u32 val; - int ret; val = readl_relaxed(pll->base); if (pll->powerup_set) @@ -78,11 +77,7 @@ static int clk_pllv3_prepare(struct clk_hw *hw) val &= ~BM_PLL_POWER; writel_relaxed(val, pll->base); - ret = clk_pllv3_wait_lock(pll); - if (ret) - return ret; - - return 0; + return clk_pllv3_wait_lock(pll); } static void clk_pllv3_unprepare(struct clk_hw *hw) diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index 1dabf435c592..f71339522156 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -61,7 +61,6 @@ struct platform_device *mxc_register_gpio(char *name, int id, void mxc_set_cpu_type(unsigned int type); void mxc_restart(enum reboot_mode, const char *); void mxc_arch_reset_init(void __iomem *); -void mxc_arch_reset_init_dt(void); int mx51_revision(void); int mx53_revision(void); void imx_set_aips(void __iomem *); @@ -71,6 +70,11 @@ void imx_set_soc_revision(unsigned int rev); unsigned int imx_get_soc_revision(void); void imx_init_revision_from_anatop(void); struct device *imx_soc_device_init(void); +void imx6_enable_rbc(bool enable); +void imx_gpc_check_dt(void); +void imx_gpc_set_arm_power_in_lpm(bool power_off); +void imx_gpc_set_arm_power_up_timing(u32 sw2iso, u32 sw); +void imx_gpc_set_arm_power_down_timing(u32 sw2iso, u32 sw); enum mxc_cpu_pwr_mode { WAIT_CLOCKED, /* wfi only */ @@ -103,13 +107,12 @@ static inline void imx_scu_map_io(void) {} static inline void imx_smp_prepare(void) {} #endif void imx_src_init(void); -void imx_gpc_init(void); void imx_gpc_pre_suspend(bool arm_power_off); void imx_gpc_post_resume(void); void imx_gpc_mask_all(void); void imx_gpc_restore_all(void); -void imx_gpc_irq_mask(struct irq_data *d); -void imx_gpc_irq_unmask(struct irq_data *d); +void imx_gpc_hwirq_mask(unsigned int hwirq); +void imx_gpc_hwirq_unmask(unsigned int hwirq); void imx_anatop_init(void); void imx_anatop_pre_suspend(void); void imx_anatop_post_resume(void); diff --git a/arch/arm/mach-imx/cpuidle-imx6sx.c b/arch/arm/mach-imx/cpuidle-imx6sx.c new file mode 100644 index 000000000000..d8a9f219e028 --- /dev/null +++ b/arch/arm/mach-imx/cpuidle-imx6sx.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2014 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 version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/cpuidle.h> +#include <linux/cpu_pm.h> +#include <linux/module.h> +#include <asm/cpuidle.h> +#include <asm/proc-fns.h> +#include <asm/suspend.h> + +#include "common.h" +#include "cpuidle.h" + +static int imx6sx_idle_finish(unsigned long val) +{ + cpu_do_idle(); + + return 0; +} + +static int imx6sx_enter_wait(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) +{ + imx6q_set_lpm(WAIT_UNCLOCKED); + + switch (index) { + case 1: + cpu_do_idle(); + break; + case 2: + imx6_enable_rbc(true); + imx_gpc_set_arm_power_in_lpm(true); + imx_set_cpu_jump(0, v7_cpu_resume); + /* Need to notify there is a cpu pm operation. */ + cpu_pm_enter(); + cpu_cluster_pm_enter(); + + cpu_suspend(0, imx6sx_idle_finish); + + cpu_cluster_pm_exit(); + cpu_pm_exit(); + imx_gpc_set_arm_power_in_lpm(false); + imx6_enable_rbc(false); + break; + default: + break; + } + + imx6q_set_lpm(WAIT_CLOCKED); + + return index; +} + +static struct cpuidle_driver imx6sx_cpuidle_driver = { + .name = "imx6sx_cpuidle", + .owner = THIS_MODULE, + .states = { + /* WFI */ + ARM_CPUIDLE_WFI_STATE, + /* WAIT */ + { + .exit_latency = 50, + .target_residency = 75, + .flags = CPUIDLE_FLAG_TIME_VALID | + CPUIDLE_FLAG_TIMER_STOP, + .enter = imx6sx_enter_wait, + .name = "WAIT", + .desc = "Clock off", + }, + /* WAIT + ARM power off */ + { + /* + * ARM gating 31us * 5 + RBC clear 65us + * and some margin for SW execution, here set it + * to 300us. + */ + .exit_latency = 300, + .target_residency = 500, + .flags = CPUIDLE_FLAG_TIME_VALID, + .enter = imx6sx_enter_wait, + .name = "LOW-POWER-IDLE", + .desc = "ARM power off", + }, + }, + .state_count = 3, + .safe_state_index = 0, +}; + +int __init imx6sx_cpuidle_init(void) +{ + imx6_enable_rbc(false); + /* + * set ARM power up/down timing to the fastest, + * sw2iso and sw can be set to one 32K cycle = 31us + * except for power up sw2iso which need to be + * larger than LDO ramp up time. + */ + imx_gpc_set_arm_power_up_timing(2, 1); + imx_gpc_set_arm_power_down_timing(1, 1); + + return cpuidle_register(&imx6sx_cpuidle_driver, NULL); +} diff --git a/arch/arm/mach-imx/cpuidle.h b/arch/arm/mach-imx/cpuidle.h index 24e33670417c..f9140128ba05 100644 --- a/arch/arm/mach-imx/cpuidle.h +++ b/arch/arm/mach-imx/cpuidle.h @@ -14,6 +14,7 @@ extern int imx5_cpuidle_init(void); extern int imx6q_cpuidle_init(void); extern int imx6sl_cpuidle_init(void); +extern int imx6sx_cpuidle_init(void); #else static inline int imx5_cpuidle_init(void) { @@ -27,4 +28,8 @@ static inline int imx6sl_cpuidle_init(void) { return 0; } +static inline int imx6sx_cpuidle_init(void) +{ + return 0; +} #endif diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c index 82ea74e68482..bbf015056221 100644 --- a/arch/arm/mach-imx/gpc.c +++ b/arch/arm/mach-imx/gpc.c @@ -10,23 +10,67 @@ * http://www.gnu.org/copyleft/gpl.html */ +#include <linux/clk.h> +#include <linux/delay.h> #include <linux/io.h> #include <linux/irq.h> #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_irq.h> +#include <linux/platform_device.h> +#include <linux/pm_domain.h> +#include <linux/regulator/consumer.h> #include <linux/irqchip/arm-gic.h> #include "common.h" +#include "hardware.h" +#define GPC_CNTR 0x000 #define GPC_IMR1 0x008 +#define GPC_PGC_GPU_PDN 0x260 +#define GPC_PGC_GPU_PUPSCR 0x264 +#define GPC_PGC_GPU_PDNSCR 0x268 #define GPC_PGC_CPU_PDN 0x2a0 +#define GPC_PGC_CPU_PUPSCR 0x2a4 +#define GPC_PGC_CPU_PDNSCR 0x2a8 +#define GPC_PGC_SW2ISO_SHIFT 0x8 +#define GPC_PGC_SW_SHIFT 0x0 #define IMR_NUM 4 +#define GPC_MAX_IRQS (IMR_NUM * 32) + +#define GPU_VPU_PUP_REQ BIT(1) +#define GPU_VPU_PDN_REQ BIT(0) + +#define GPC_CLK_MAX 6 + +struct pu_domain { + struct generic_pm_domain base; + struct regulator *reg; + struct clk *clk[GPC_CLK_MAX]; + int num_clks; +}; static void __iomem *gpc_base; static u32 gpc_wake_irqs[IMR_NUM]; static u32 gpc_saved_imrs[IMR_NUM]; +void imx_gpc_set_arm_power_up_timing(u32 sw2iso, u32 sw) +{ + writel_relaxed((sw2iso << GPC_PGC_SW2ISO_SHIFT) | + (sw << GPC_PGC_SW_SHIFT), gpc_base + GPC_PGC_CPU_PUPSCR); +} + +void imx_gpc_set_arm_power_down_timing(u32 sw2iso, u32 sw) +{ + writel_relaxed((sw2iso << GPC_PGC_SW2ISO_SHIFT) | + (sw << GPC_PGC_SW_SHIFT), gpc_base + GPC_PGC_CPU_PDNSCR); +} + +void imx_gpc_set_arm_power_in_lpm(bool power_off) +{ + writel_relaxed(power_off, gpc_base + GPC_PGC_CPU_PDN); +} + void imx_gpc_pre_suspend(bool arm_power_off) { void __iomem *reg_imr1 = gpc_base + GPC_IMR1; @@ -34,7 +78,7 @@ void imx_gpc_pre_suspend(bool arm_power_off) /* Tell GPC to power off ARM core when suspend */ if (arm_power_off) - writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN); + imx_gpc_set_arm_power_in_lpm(arm_power_off); for (i = 0; i < IMR_NUM; i++) { gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4); @@ -48,7 +92,7 @@ void imx_gpc_post_resume(void) int i; /* Keep ARM core powered on for other low-power modes */ - writel_relaxed(0x0, gpc_base + GPC_PGC_CPU_PDN); + imx_gpc_set_arm_power_in_lpm(false); for (i = 0; i < IMR_NUM; i++) writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4); @@ -56,17 +100,17 @@ void imx_gpc_post_resume(void) static int imx_gpc_irq_set_wake(struct irq_data *d, unsigned int on) { - unsigned int idx = d->irq / 32 - 1; + unsigned int idx = d->hwirq / 32; u32 mask; - /* Sanity check for SPI irq */ - if (d->irq < 32) - return -EINVAL; - - mask = 1 << d->irq % 32; + mask = 1 << d->hwirq % 32; gpc_wake_irqs[idx] = on ? gpc_wake_irqs[idx] | mask : gpc_wake_irqs[idx] & ~mask; + /* + * Do *not* call into the parent, as the GIC doesn't have any + * wake-up facility... + */ return 0; } @@ -91,51 +135,349 @@ void imx_gpc_restore_all(void) writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4); } -void imx_gpc_irq_unmask(struct irq_data *d) +void imx_gpc_hwirq_unmask(unsigned int hwirq) { void __iomem *reg; u32 val; - /* Sanity check for SPI irq */ - if (d->irq < 32) - return; - - reg = gpc_base + GPC_IMR1 + (d->irq / 32 - 1) * 4; + reg = gpc_base + GPC_IMR1 + hwirq / 32 * 4; val = readl_relaxed(reg); - val &= ~(1 << d->irq % 32); + val &= ~(1 << hwirq % 32); writel_relaxed(val, reg); } -void imx_gpc_irq_mask(struct irq_data *d) +void imx_gpc_hwirq_mask(unsigned int hwirq) { void __iomem *reg; u32 val; - /* Sanity check for SPI irq */ - if (d->irq < 32) - return; - - reg = gpc_base + GPC_IMR1 + (d->irq / 32 - 1) * 4; + reg = gpc_base + GPC_IMR1 + hwirq / 32 * 4; val = readl_relaxed(reg); - val |= 1 << (d->irq % 32); + val |= 1 << (hwirq % 32); writel_relaxed(val, reg); } -void __init imx_gpc_init(void) +static void imx_gpc_irq_unmask(struct irq_data *d) { - struct device_node *np; + imx_gpc_hwirq_unmask(d->hwirq); + irq_chip_unmask_parent(d); +} + +static void imx_gpc_irq_mask(struct irq_data *d) +{ + imx_gpc_hwirq_mask(d->hwirq); + irq_chip_mask_parent(d); +} + +static struct irq_chip imx_gpc_chip = { + .name = "GPC", + .irq_eoi = irq_chip_eoi_parent, + .irq_mask = imx_gpc_irq_mask, + .irq_unmask = imx_gpc_irq_unmask, + .irq_retrigger = irq_chip_retrigger_hierarchy, + .irq_set_wake = imx_gpc_irq_set_wake, +#ifdef CONFIG_SMP + .irq_set_affinity = irq_chip_set_affinity_parent, +#endif +}; + +static int imx_gpc_domain_xlate(struct irq_domain *domain, + struct device_node *controller, + const u32 *intspec, + unsigned int intsize, + unsigned long *out_hwirq, + unsigned int *out_type) +{ + if (domain->of_node != controller) + return -EINVAL; /* Shouldn't happen, really... */ + if (intsize != 3) + return -EINVAL; /* Not GIC compliant */ + if (intspec[0] != 0) + return -EINVAL; /* No PPI should point to this domain */ + + *out_hwirq = intspec[1]; + *out_type = intspec[2]; + return 0; +} + +static int imx_gpc_domain_alloc(struct irq_domain *domain, + unsigned int irq, + unsigned int nr_irqs, void *data) +{ + struct of_phandle_args *args = data; + struct of_phandle_args parent_args; + irq_hw_number_t hwirq; int i; - np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc"); - gpc_base = of_iomap(np, 0); - WARN_ON(!gpc_base); + if (args->args_count != 3) + return -EINVAL; /* Not GIC compliant */ + if (args->args[0] != 0) + return -EINVAL; /* No PPI should point to this domain */ + + hwirq = args->args[1]; + if (hwirq >= GPC_MAX_IRQS) + return -EINVAL; /* Can't deal with this */ + + for (i = 0; i < nr_irqs; i++) + irq_domain_set_hwirq_and_chip(domain, irq + i, hwirq + i, + &imx_gpc_chip, NULL); + + parent_args = *args; + parent_args.np = domain->parent->of_node; + return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs, &parent_args); +} + +static struct irq_domain_ops imx_gpc_domain_ops = { + .xlate = imx_gpc_domain_xlate, + .alloc = imx_gpc_domain_alloc, + .free = irq_domain_free_irqs_common, +}; + +static int __init imx_gpc_init(struct device_node *node, + struct device_node *parent) +{ + struct irq_domain *parent_domain, *domain; + int i; + + if (!parent) { + pr_err("%s: no parent, giving up\n", node->full_name); + return -ENODEV; + } + + parent_domain = irq_find_host(parent); + if (!parent_domain) { + pr_err("%s: unable to obtain parent domain\n", node->full_name); + return -ENXIO; + } + + gpc_base = of_iomap(node, 0); + if (WARN_ON(!gpc_base)) + return -ENOMEM; + + domain = irq_domain_add_hierarchy(parent_domain, 0, GPC_MAX_IRQS, + node, &imx_gpc_domain_ops, + NULL); + if (!domain) { + iounmap(gpc_base); + return -ENOMEM; + } /* Initially mask all interrupts */ for (i = 0; i < IMR_NUM; i++) writel_relaxed(~0, gpc_base + GPC_IMR1 + i * 4); - /* Register GPC as the secondary interrupt controller behind GIC */ - gic_arch_extn.irq_mask = imx_gpc_irq_mask; - gic_arch_extn.irq_unmask = imx_gpc_irq_unmask; - gic_arch_extn.irq_set_wake = imx_gpc_irq_set_wake; + return 0; +} + +/* + * We cannot use the IRQCHIP_DECLARE macro that lives in + * drivers/irqchip, so we're forced to roll our own. Not very nice. + */ +OF_DECLARE_2(irqchip, imx_gpc, "fsl,imx6q-gpc", imx_gpc_init); + +void __init imx_gpc_check_dt(void) +{ + struct device_node *np; + + np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc"); + if (WARN_ON(!np)) + return; + + if (WARN_ON(!of_find_property(np, "interrupt-controller", NULL))) { + pr_warn("Outdated DT detected, suspend/resume will NOT work\n"); + + /* map GPC, so that at least CPUidle and WARs keep working */ + gpc_base = of_iomap(np, 0); + } +} + +#ifdef CONFIG_PM_GENERIC_DOMAINS + +static void _imx6q_pm_pu_power_off(struct generic_pm_domain *genpd) +{ + int iso, iso2sw; + u32 val; + + /* Read ISO and ISO2SW power down delays */ + val = readl_relaxed(gpc_base + GPC_PGC_GPU_PDNSCR); + iso = val & 0x3f; + iso2sw = (val >> 8) & 0x3f; + + /* Gate off PU domain when GPU/VPU when powered down */ + writel_relaxed(0x1, gpc_base + GPC_PGC_GPU_PDN); + + /* Request GPC to power down GPU/VPU */ + val = readl_relaxed(gpc_base + GPC_CNTR); + val |= GPU_VPU_PDN_REQ; + writel_relaxed(val, gpc_base + GPC_CNTR); + + /* Wait ISO + ISO2SW IPG clock cycles */ + ndelay((iso + iso2sw) * 1000 / 66); +} + +static int imx6q_pm_pu_power_off(struct generic_pm_domain *genpd) +{ + struct pu_domain *pu = container_of(genpd, struct pu_domain, base); + + _imx6q_pm_pu_power_off(genpd); + + if (pu->reg) + regulator_disable(pu->reg); + + return 0; +} + +static int imx6q_pm_pu_power_on(struct generic_pm_domain *genpd) +{ + struct pu_domain *pu = container_of(genpd, struct pu_domain, base); + int i, ret, sw, sw2iso; + u32 val; + + if (pu->reg) + ret = regulator_enable(pu->reg); + if (pu->reg && ret) { + pr_err("%s: failed to enable regulator: %d\n", __func__, ret); + return ret; + } + + /* Enable reset clocks for all devices in the PU domain */ + for (i = 0; i < pu->num_clks; i++) + clk_prepare_enable(pu->clk[i]); + + /* Gate off PU domain when GPU/VPU when powered down */ + writel_relaxed(0x1, gpc_base + GPC_PGC_GPU_PDN); + + /* Read ISO and ISO2SW power down delays */ + val = readl_relaxed(gpc_base + GPC_PGC_GPU_PUPSCR); + sw = val & 0x3f; + sw2iso = (val >> 8) & 0x3f; + + /* Request GPC to power up GPU/VPU */ + val = readl_relaxed(gpc_base + GPC_CNTR); + val |= GPU_VPU_PUP_REQ; + writel_relaxed(val, gpc_base + GPC_CNTR); + + /* Wait ISO + ISO2SW IPG clock cycles */ + ndelay((sw + sw2iso) * 1000 / 66); + + /* Disable reset clocks for all devices in the PU domain */ + for (i = 0; i < pu->num_clks; i++) + clk_disable_unprepare(pu->clk[i]); + + return 0; +} + +static struct generic_pm_domain imx6q_arm_domain = { + .name = "ARM", +}; + +static struct pu_domain imx6q_pu_domain = { + .base = { + .name = "PU", + .power_off = imx6q_pm_pu_power_off, + .power_on = imx6q_pm_pu_power_on, + .power_off_latency_ns = 25000, + .power_on_latency_ns = 2000000, + }, +}; + +static struct generic_pm_domain imx6sl_display_domain = { + .name = "DISPLAY", +}; + +static struct generic_pm_domain *imx_gpc_domains[] = { + &imx6q_arm_domain, + &imx6q_pu_domain.base, + &imx6sl_display_domain, +}; + +static struct genpd_onecell_data imx_gpc_onecell_data = { + .domains = imx_gpc_domains, + .num_domains = ARRAY_SIZE(imx_gpc_domains), +}; + +static int imx_gpc_genpd_init(struct device *dev, struct regulator *pu_reg) +{ + struct clk *clk; + bool is_off; + int i; + + imx6q_pu_domain.reg = pu_reg; + + for (i = 0; ; i++) { + clk = of_clk_get(dev->of_node, i); + if (IS_ERR(clk)) + break; + if (i >= GPC_CLK_MAX) { + dev_err(dev, "more than %d clocks\n", GPC_CLK_MAX); + goto clk_err; + } + imx6q_pu_domain.clk[i] = clk; + } + imx6q_pu_domain.num_clks = i; + + is_off = IS_ENABLED(CONFIG_PM); + if (is_off) { + _imx6q_pm_pu_power_off(&imx6q_pu_domain.base); + } else { + /* + * Enable power if compiled without CONFIG_PM in case the + * bootloader disabled it. + */ + imx6q_pm_pu_power_on(&imx6q_pu_domain.base); + } + + pm_genpd_init(&imx6q_pu_domain.base, NULL, is_off); + return of_genpd_add_provider_onecell(dev->of_node, + &imx_gpc_onecell_data); + +clk_err: + while (i--) + clk_put(imx6q_pu_domain.clk[i]); + return -EINVAL; +} + +#else +static inline int imx_gpc_genpd_init(struct device *dev, struct regulator *reg) +{ + return 0; +} +#endif /* CONFIG_PM_GENERIC_DOMAINS */ + +static int imx_gpc_probe(struct platform_device *pdev) +{ + struct regulator *pu_reg; + int ret; + + pu_reg = devm_regulator_get_optional(&pdev->dev, "pu"); + if (PTR_ERR(pu_reg) == -ENODEV) + pu_reg = NULL; + if (IS_ERR(pu_reg)) { + ret = PTR_ERR(pu_reg); + dev_err(&pdev->dev, "failed to get pu regulator: %d\n", ret); + return ret; + } + + return imx_gpc_genpd_init(&pdev->dev, pu_reg); +} + +static const struct of_device_id imx_gpc_dt_ids[] = { + { .compatible = "fsl,imx6q-gpc" }, + { .compatible = "fsl,imx6sl-gpc" }, + { } +}; + +static struct platform_driver imx_gpc_driver = { + .driver = { + .name = "imx-gpc", + .owner = THIS_MODULE, + .of_match_table = imx_gpc_dt_ids, + }, + .probe = imx_gpc_probe, +}; + +static int __init imx_pgc_init(void) +{ + return platform_driver_register(&imx_gpc_driver); } +subsys_initcall(imx_pgc_init); diff --git a/arch/arm/mach-imx/imx25-dt.c b/arch/arm/mach-imx/imx25-dt.c index cf8032bae277..25defbdb06c4 100644 --- a/arch/arm/mach-imx/imx25-dt.c +++ b/arch/arm/mach-imx/imx25-dt.c @@ -17,13 +17,6 @@ #include "common.h" #include "mx25.h" -static void __init imx25_dt_init(void) -{ - mxc_arch_reset_init_dt(); - - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); -} - static const char * const imx25_dt_board_compat[] __initconst = { "fsl,imx25", NULL @@ -33,7 +26,5 @@ DT_MACHINE_START(IMX25_DT, "Freescale i.MX25 (Device Tree Support)") .map_io = mx25_map_io, .init_early = imx25_init_early, .init_irq = mx25_init_irq, - .init_machine = imx25_dt_init, .dt_compat = imx25_dt_board_compat, - .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/imx27-dt.c b/arch/arm/mach-imx/imx27-dt.c index dc8f1a6f45f2..bd42d1bd10af 100644 --- a/arch/arm/mach-imx/imx27-dt.c +++ b/arch/arm/mach-imx/imx27-dt.c @@ -22,8 +22,6 @@ static void __init imx27_dt_init(void) { struct platform_device_info devinfo = { .name = "cpufreq-dt", }; - mxc_arch_reset_init_dt(); - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); platform_device_register_full(&devinfo); @@ -40,5 +38,4 @@ DT_MACHINE_START(IMX27_DT, "Freescale i.MX27 (Device Tree Support)") .init_irq = mx27_init_irq, .init_machine = imx27_dt_init, .dt_compat = imx27_dt_board_compat, - .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/imx31-dt.c b/arch/arm/mach-imx/imx31-dt.c index 418dbc82adc4..32100222a017 100644 --- a/arch/arm/mach-imx/imx31-dt.c +++ b/arch/arm/mach-imx/imx31-dt.c @@ -18,13 +18,6 @@ #include "common.h" #include "mx31.h" -static void __init imx31_dt_init(void) -{ - mxc_arch_reset_init_dt(); - - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); -} - static const char * const imx31_dt_board_compat[] __initconst = { "fsl,imx31", NULL @@ -40,7 +33,5 @@ DT_MACHINE_START(IMX31_DT, "Freescale i.MX31 (Device Tree Support)") .init_early = imx31_init_early, .init_irq = mx31_init_irq, .init_time = imx31_dt_timer_init, - .init_machine = imx31_dt_init, .dt_compat = imx31_dt_board_compat, - .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/imx35-dt.c b/arch/arm/mach-imx/imx35-dt.c index 584fbe105579..e9396037235d 100644 --- a/arch/arm/mach-imx/imx35-dt.c +++ b/arch/arm/mach-imx/imx35-dt.c @@ -20,14 +20,6 @@ #include "common.h" #include "mx35.h" -static void __init imx35_dt_init(void) -{ - mxc_arch_reset_init_dt(); - - of_platform_populate(NULL, of_default_bus_match_table, - NULL, NULL); -} - static void __init imx35_irq_init(void) { imx_init_l2cache(); @@ -43,7 +35,5 @@ DT_MACHINE_START(IMX35_DT, "Freescale i.MX35 (Device Tree Support)") .map_io = mx35_map_io, .init_early = imx35_init_early, .init_irq = imx35_irq_init, - .init_machine = imx35_dt_init, .dt_compat = imx35_dt_board_compat, - .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/iomux-imx31.c b/arch/arm/mach-imx/iomux-imx31.c index 1657fe64cd0f..d6a30753ca7c 100644 --- a/arch/arm/mach-imx/iomux-imx31.c +++ b/arch/arm/mach-imx/iomux-imx31.c @@ -44,9 +44,11 @@ static unsigned long mxc_pin_alloc_map[NB_PORTS * 32 / BITS_PER_LONG]; /* * set the mode for a IOMUX pin. */ -int mxc_iomux_mode(unsigned int pin_mode) +void mxc_iomux_mode(unsigned int pin_mode) { - u32 field, l, mode, ret = 0; + u32 field; + u32 l; + u32 mode; void __iomem *reg; reg = IOMUXSW_MUX_CTL + (pin_mode & IOMUX_REG_MASK); @@ -61,8 +63,6 @@ int mxc_iomux_mode(unsigned int pin_mode) __raw_writel(l, reg); spin_unlock(&gpio_mux_lock); - - return ret; } /* diff --git a/arch/arm/mach-imx/iomux-mx3.h b/arch/arm/mach-imx/iomux-mx3.h index f79f78a1c0ed..0a5adba61e0b 100644 --- a/arch/arm/mach-imx/iomux-mx3.h +++ b/arch/arm/mach-imx/iomux-mx3.h @@ -144,7 +144,7 @@ void mxc_iomux_set_gpr(enum iomux_gp_func, bool en); * It is called by the setup functions and should not be called directly anymore. * It is here visible for backward compatibility */ -int mxc_iomux_mode(unsigned int pin_mode); +void mxc_iomux_mode(unsigned int pin_mode); #define IOMUX_PADNUM_MASK 0x1ff #define IOMUX_GPIONUM_SHIFT 9 diff --git a/arch/arm/mach-imx/mach-imx50.c b/arch/arm/mach-imx/mach-imx50.c index b1e56a94a382..ecf58b9e974b 100644 --- a/arch/arm/mach-imx/mach-imx50.c +++ b/arch/arm/mach-imx/mach-imx50.c @@ -16,13 +16,6 @@ #include "common.h" -static void __init imx50_dt_init(void) -{ - mxc_arch_reset_init_dt(); - - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); -} - static const char * const imx50_dt_board_compat[] __initconst = { "fsl,imx50", NULL @@ -30,7 +23,5 @@ static const char * const imx50_dt_board_compat[] __initconst = { DT_MACHINE_START(IMX50_DT, "Freescale i.MX50 (Device Tree Support)") .init_irq = tzic_init_irq, - .init_machine = imx50_dt_init, .dt_compat = imx50_dt_board_compat, - .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-imx51.c b/arch/arm/mach-imx/mach-imx51.c index 2c5fcaf8675b..b015129e4045 100644 --- a/arch/arm/mach-imx/mach-imx51.c +++ b/arch/arm/mach-imx/mach-imx51.c @@ -53,7 +53,6 @@ static void __init imx51_dt_init(void) { struct platform_device_info devinfo = { .name = "cpufreq-dt", }; - mxc_arch_reset_init_dt(); imx51_ipu_mipi_setup(); imx_src_init(); @@ -78,5 +77,4 @@ DT_MACHINE_START(IMX51_DT, "Freescale i.MX51 (Device Tree Support)") .init_machine = imx51_dt_init, .init_late = imx51_init_late, .dt_compat = imx51_dt_board_compat, - .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-imx53.c b/arch/arm/mach-imx/mach-imx53.c index 03dd6ea13acc..18b5c5c136db 100644 --- a/arch/arm/mach-imx/mach-imx53.c +++ b/arch/arm/mach-imx/mach-imx53.c @@ -30,7 +30,6 @@ static void __init imx53_init_early(void) static void __init imx53_dt_init(void) { - mxc_arch_reset_init_dt(); imx_src_init(); of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); @@ -54,5 +53,4 @@ DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)") .init_machine = imx53_dt_init, .init_late = imx53_init_late, .dt_compat = imx53_dt_board_compat, - .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index d51c6e99a2e9..e21a693fc984 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -268,8 +268,6 @@ static void __init imx6q_init_machine(void) imx_print_silicon_rev(cpu_is_imx6dl() ? "i.MX6DL" : "i.MX6Q", imx_get_soc_revision()); - mxc_arch_reset_init_dt(); - parent = imx_soc_device_init(); if (parent == NULL) pr_warn("failed to initialize soc device\n"); @@ -331,7 +329,7 @@ static void __init imx6q_opp_check_speed_grading(struct device *cpu_dev) if (dev_pm_opp_disable(cpu_dev, 852000000)) pr_warn("failed to disable 852 MHz OPP\n"); } - + iounmap(base); put_node: of_node_put(np); } @@ -389,10 +387,10 @@ static void __init imx6q_map_io(void) static void __init imx6q_init_irq(void) { + imx_gpc_check_dt(); imx_init_revision_from_anatop(); imx_init_l2cache(); imx_src_init(); - imx_gpc_init(); irqchip_init(); } @@ -409,5 +407,4 @@ DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad/DualLite (Device Tree)") .init_machine = imx6q_init_machine, .init_late = imx6q_init_late, .dt_compat = imx6q_dt_compat, - .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-imx6sl.c b/arch/arm/mach-imx/mach-imx6sl.c index ed263a21d928..12a1b098fc6a 100644 --- a/arch/arm/mach-imx/mach-imx6sl.c +++ b/arch/arm/mach-imx/mach-imx6sl.c @@ -48,8 +48,6 @@ static void __init imx6sl_init_machine(void) { struct device *parent; - mxc_arch_reset_init_dt(); - parent = imx_soc_device_init(); if (parent == NULL) pr_warn("failed to initialize soc device\n"); @@ -63,10 +61,10 @@ static void __init imx6sl_init_machine(void) static void __init imx6sl_init_irq(void) { + imx_gpc_check_dt(); imx_init_revision_from_anatop(); imx_init_l2cache(); imx_src_init(); - imx_gpc_init(); irqchip_init(); } @@ -76,10 +74,8 @@ static const char * const imx6sl_dt_compat[] __initconst = { }; DT_MACHINE_START(IMX6SL, "Freescale i.MX6 SoloLite (Device Tree)") - .map_io = debug_ll_io_init, .init_irq = imx6sl_init_irq, .init_machine = imx6sl_init_machine, .init_late = imx6sl_init_late, .dt_compat = imx6sl_dt_compat, - .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-imx6sx.c b/arch/arm/mach-imx/mach-imx6sx.c index 3de3b7369aef..f17b7004c24b 100644 --- a/arch/arm/mach-imx/mach-imx6sx.c +++ b/arch/arm/mach-imx/mach-imx6sx.c @@ -8,40 +8,89 @@ #include <linux/irqchip.h> #include <linux/of_platform.h> +#include <linux/phy.h> +#include <linux/regmap.h> +#include <linux/mfd/syscon.h> +#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include "common.h" #include "cpuidle.h" +static int ar8031_phy_fixup(struct phy_device *dev) +{ + u16 val; + + /* Set RGMII IO voltage to 1.8V */ + phy_write(dev, 0x1d, 0x1f); + phy_write(dev, 0x1e, 0x8); + + /* introduce tx clock delay */ + phy_write(dev, 0x1d, 0x5); + val = phy_read(dev, 0x1e); + val |= 0x0100; + phy_write(dev, 0x1e, val); + + return 0; +} + +#define PHY_ID_AR8031 0x004dd074 +static void __init imx6sx_enet_phy_init(void) +{ + if (IS_BUILTIN(CONFIG_PHYLIB)) + phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffff, + ar8031_phy_fixup); +} + +static void __init imx6sx_enet_clk_sel(void) +{ + struct regmap *gpr; + + gpr = syscon_regmap_lookup_by_compatible("fsl,imx6sx-iomuxc-gpr"); + if (!IS_ERR(gpr)) { + regmap_update_bits(gpr, IOMUXC_GPR1, + IMX6SX_GPR1_FEC_CLOCK_MUX_SEL_MASK, 0); + regmap_update_bits(gpr, IOMUXC_GPR1, + IMX6SX_GPR1_FEC_CLOCK_PAD_DIR_MASK, 0); + } else { + pr_err("failed to find fsl,imx6sx-iomux-gpr regmap\n"); + } +} + +static inline void imx6sx_enet_init(void) +{ + imx6sx_enet_phy_init(); + imx6sx_enet_clk_sel(); +} + static void __init imx6sx_init_machine(void) { struct device *parent; - mxc_arch_reset_init_dt(); - parent = imx_soc_device_init(); if (parent == NULL) pr_warn("failed to initialize soc device\n"); of_platform_populate(NULL, of_default_bus_match_table, NULL, parent); + imx6sx_enet_init(); imx_anatop_init(); imx6sx_pm_init(); } static void __init imx6sx_init_irq(void) { + imx_gpc_check_dt(); imx_init_revision_from_anatop(); imx_init_l2cache(); imx_src_init(); - imx_gpc_init(); irqchip_init(); } static void __init imx6sx_init_late(void) { - imx6q_cpuidle_init(); + imx6sx_cpuidle_init(); if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ)) platform_device_register_simple("imx6q-cpufreq", -1, NULL, 0); @@ -53,10 +102,8 @@ static const char * const imx6sx_dt_compat[] __initconst = { }; DT_MACHINE_START(IMX6SX, "Freescale i.MX6 SoloX (Device Tree)") - .map_io = debug_ll_io_init, .init_irq = imx6sx_init_irq, .init_machine = imx6sx_init_machine, .dt_compat = imx6sx_dt_compat, .init_late = imx6sx_init_late, - .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/mach-vf610.c b/arch/arm/mach-imx/mach-vf610.c index ee7e57b752a7..c11ab6a1dc87 100644 --- a/arch/arm/mach-imx/mach-vf610.c +++ b/arch/arm/mach-imx/mach-vf610.c @@ -12,14 +12,6 @@ #include <asm/mach/arch.h> #include <asm/hardware/cache-l2x0.h> -#include "common.h" - -static void __init vf610_init_machine(void) -{ - mxc_arch_reset_init_dt(); - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); -} - static const char * const vf610_dt_compat[] __initconst = { "fsl,vf610", NULL, @@ -28,7 +20,5 @@ static const char * const vf610_dt_compat[] __initconst = { DT_MACHINE_START(VYBRID_VF610, "Freescale Vybrid VF610 (Device Tree)") .l2c_aux_val = 0, .l2c_aux_mask = ~0, - .init_machine = vf610_init_machine, .dt_compat = vf610_dt_compat, - .restart = mxc_restart, MACHINE_END diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c index 5c3af8f993d0..7ffdae68c9f0 100644 --- a/arch/arm/mach-imx/pm-imx6.c +++ b/arch/arm/mach-imx/pm-imx6.c @@ -209,7 +209,7 @@ void imx6q_set_int_mem_clk_lpm(bool enable) writel_relaxed(val, ccm_base + CGPR); } -static void imx6q_enable_rbc(bool enable) +void imx6_enable_rbc(bool enable) { u32 val; @@ -261,7 +261,6 @@ static void imx6q_enable_wb(bool enable) int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode) { - struct irq_data *iomuxc_irq_data = irq_get_irq_data(32); u32 val = readl_relaxed(ccm_base + CLPCR); val &= ~BM_CLPCR_LPM; @@ -315,10 +314,12 @@ int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode) * Low-Power mode. * 3) Software should mask IRQ #32 right after CCM Low-Power mode * is set (set bits 0-1 of CCM_CLPCR). + * + * Note that IRQ #32 is GIC SPI #0. */ - imx_gpc_irq_unmask(iomuxc_irq_data); + imx_gpc_hwirq_unmask(0); writel_relaxed(val, ccm_base + CLPCR); - imx_gpc_irq_mask(iomuxc_irq_data); + imx_gpc_hwirq_mask(0); return 0; } @@ -364,7 +365,7 @@ static int imx6q_pm_enter(suspend_state_t state) * RBC setting, so we do NOT need to do that here. */ if (!imx6_suspend_in_ocram_fn) - imx6q_enable_rbc(true); + imx6_enable_rbc(true); imx_gpc_pre_suspend(true); imx_anatop_pre_suspend(); imx_set_cpu_jump(0, v7_cpu_resume); @@ -374,7 +375,7 @@ static int imx6q_pm_enter(suspend_state_t state) imx_smp_prepare(); imx_anatop_post_resume(); imx_gpc_post_resume(); - imx6q_enable_rbc(false); + imx6_enable_rbc(false); imx6q_enable_wb(false); imx6q_set_int_mem_clk_lpm(true); imx6q_set_lpm(WAIT_CLOCKED); diff --git a/arch/arm/mach-imx/system.c b/arch/arm/mach-imx/system.c index d14c33fd6b03..51c35013b673 100644 --- a/arch/arm/mach-imx/system.c +++ b/arch/arm/mach-imx/system.c @@ -89,21 +89,6 @@ void __init mxc_arch_reset_init(void __iomem *base) clk_prepare(wdog_clk); } -void __init mxc_arch_reset_init_dt(void) -{ - struct device_node *np; - - np = of_find_compatible_node(NULL, NULL, "fsl,imx21-wdt"); - wdog_base = of_iomap(np, 0); - WARN_ON(!wdog_base); - - wdog_clk = of_clk_get(np, 0); - if (IS_ERR(wdog_clk)) - pr_warn("%s: failed to get wdog clock\n", __func__); - else - clk_prepare(wdog_clk); -} - #ifdef CONFIG_CACHE_L2X0 void __init imx_init_l2cache(void) { diff --git a/arch/arm/mach-iop13xx/msi.c b/arch/arm/mach-iop13xx/msi.c index e7730cf9c15d..9f89e76dfbb9 100644 --- a/arch/arm/mach-iop13xx/msi.c +++ b/arch/arm/mach-iop13xx/msi.c @@ -126,10 +126,10 @@ static void iop13xx_msi_nop(struct irq_data *d) static struct irq_chip iop13xx_msi_chip = { .name = "PCI-MSI", .irq_ack = iop13xx_msi_nop, - .irq_enable = unmask_msi_irq, - .irq_disable = mask_msi_irq, - .irq_mask = mask_msi_irq, - .irq_unmask = unmask_msi_irq, + .irq_enable = pci_msi_unmask_irq, + .irq_disable = pci_msi_mask_irq, + .irq_mask = pci_msi_mask_irq, + .irq_unmask = pci_msi_unmask_irq, }; int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) @@ -153,7 +153,7 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) id = iop13xx_cpu_id(); msg.data = (id << IOP13XX_MU_MIMR_CORE_SELECT) | (irq & 0x7f); - write_msi_msg(irq, &msg); + pci_write_msi_msg(irq, &msg); irq_set_chip_and_handler(irq, &iop13xx_msi_chip, handle_simple_irq); return 0; diff --git a/arch/arm/plat-orion/gpio.c b/arch/arm/plat-orion/gpio.c index e048f6198d68..14f6e647c739 100644 --- a/arch/arm/plat-orion/gpio.c +++ b/arch/arm/plat-orion/gpio.c @@ -505,9 +505,9 @@ static void orion_gpio_unmask_irq(struct irq_data *d) u32 mask = d->mask; irq_gc_lock(gc); - reg_val = irq_reg_readl(gc->reg_base + ct->regs.mask); + reg_val = irq_reg_readl(gc, ct->regs.mask); reg_val |= mask; - irq_reg_writel(reg_val, gc->reg_base + ct->regs.mask); + irq_reg_writel(gc, reg_val, ct->regs.mask); irq_gc_unlock(gc); } @@ -519,9 +519,9 @@ static void orion_gpio_mask_irq(struct irq_data *d) u32 reg_val; irq_gc_lock(gc); - reg_val = irq_reg_readl(gc->reg_base + ct->regs.mask); + reg_val = irq_reg_readl(gc, ct->regs.mask); reg_val &= ~mask; - irq_reg_writel(reg_val, gc->reg_base + ct->regs.mask); + irq_reg_writel(gc, reg_val, ct->regs.mask); irq_gc_unlock(gc); } diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 00b9c4870230..611a8e75ac38 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -13,7 +13,9 @@ config ARM64 select ARM_ARCH_TIMER select ARM_GIC select AUDIT_ARCH_COMPAT_GENERIC + select ARM_GIC_V2M if PCI_MSI select ARM_GIC_V3 + select ARM_GIC_V3_ITS if PCI_MSI select BUILDTIME_EXTABLE_SORT select CLONE_BACKWARDS select COMMON_CLK diff --git a/arch/arm64/boot/dts/arm/Makefile b/arch/arm64/boot/dts/arm/Makefile index 301a0dada1fe..c5c98b91514e 100644 --- a/arch/arm64/boot/dts/arm/Makefile +++ b/arch/arm64/boot/dts/arm/Makefile @@ -1,5 +1,5 @@ dtb-$(CONFIG_ARCH_VEXPRESS) += foundation-v8.dtb -dtb-$(CONFIG_ARCH_VEXPRESS) += juno.dtb +dtb-$(CONFIG_ARCH_VEXPRESS) += juno.dtb juno-r1.dtb dtb-$(CONFIG_ARCH_VEXPRESS) += rtsm_ve-aemv8a.dtb always := $(dtb-y) diff --git a/arch/arm64/boot/dts/arm/juno-base.dtsi b/arch/arm64/boot/dts/arm/juno-base.dtsi new file mode 100644 index 000000000000..e3ee96036eca --- /dev/null +++ b/arch/arm64/boot/dts/arm/juno-base.dtsi @@ -0,0 +1,154 @@ + /* + * Devices shared by all Juno boards + */ + + memtimer: timer@2a810000 { + compatible = "arm,armv7-timer-mem"; + reg = <0x0 0x2a810000 0x0 0x10000>; + clock-frequency = <50000000>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + status = "disabled"; + frame@2a830000 { + frame-number = <1>; + interrupts = <0 60 4>; + reg = <0x0 0x2a830000 0x0 0x10000>; + }; + }; + + gic: interrupt-controller@2c010000 { + compatible = "arm,gic-400", "arm,cortex-a15-gic"; + reg = <0x0 0x2c010000 0 0x1000>, + <0x0 0x2c02f000 0 0x2000>, + <0x0 0x2c04f000 0 0x2000>, + <0x0 0x2c06f000 0 0x2000>; + #address-cells = <2>; + #interrupt-cells = <3>; + #size-cells = <2>; + interrupt-controller; + interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_HIGH)>; + ranges = <0 0 0 0x2c1c0000 0 0x40000>; + v2m_0: v2m@0 { + compatible = "arm,gic-v2m-frame"; + msi-controller; + reg = <0 0 0 0x1000>; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>; + }; + + /include/ "juno-clocks.dtsi" + + dma@7ff00000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0x0 0x7ff00000 0 0x1000>; + #dma-cells = <1>; + #dma-channels = <8>; + #dma-requests = <32>; + interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&soc_faxiclk>; + clock-names = "apb_pclk"; + }; + + soc_uart0: uart@7ff80000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0 0x7ff80000 0x0 0x1000>; + interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&soc_uartclk>, <&soc_refclk100mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + i2c@7ffa0000 { + compatible = "snps,designware-i2c"; + reg = <0x0 0x7ffa0000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>; + clock-frequency = <400000>; + i2c-sda-hold-time-ns = <500>; + clocks = <&soc_smc50mhz>; + + dvi0: dvi-transmitter@70 { + compatible = "nxp,tda998x"; + reg = <0x70>; + }; + + dvi1: dvi-transmitter@71 { + compatible = "nxp,tda998x"; + reg = <0x71>; + }; + }; + + ohci@7ffb0000 { + compatible = "generic-ohci"; + reg = <0x0 0x7ffb0000 0x0 0x10000>; + interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&soc_usb48mhz>; + }; + + ehci@7ffc0000 { + compatible = "generic-ehci"; + reg = <0x0 0x7ffc0000 0x0 0x10000>; + interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&soc_usb48mhz>; + }; + + memory-controller@7ffd0000 { + compatible = "arm,pl354", "arm,primecell"; + reg = <0 0x7ffd0000 0 0x1000>; + interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&soc_smc50mhz>; + clock-names = "apb_pclk"; + }; + + memory@80000000 { + device_type = "memory"; + /* last 16MB of the first memory area is reserved for secure world use by firmware */ + reg = <0x00000000 0x80000000 0x0 0x7f000000>, + <0x00000008 0x80000000 0x1 0x80000000>; + }; + + smb { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0 0x08000000 0x04000000>, + <1 0 0 0x14000000 0x04000000>, + <2 0 0 0x18000000 0x04000000>, + <3 0 0 0x1c000000 0x04000000>, + <4 0 0 0x0c000000 0x04000000>, + <5 0 0 0x10000000 0x04000000>; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 15>; + interrupt-map = <0 0 0 &gic 0 0 0 68 IRQ_TYPE_LEVEL_HIGH>, + <0 0 1 &gic 0 0 0 69 IRQ_TYPE_LEVEL_HIGH>, + <0 0 2 &gic 0 0 0 70 IRQ_TYPE_LEVEL_HIGH>, + <0 0 3 &gic 0 0 0 160 IRQ_TYPE_LEVEL_HIGH>, + <0 0 4 &gic 0 0 0 161 IRQ_TYPE_LEVEL_HIGH>, + <0 0 5 &gic 0 0 0 162 IRQ_TYPE_LEVEL_HIGH>, + <0 0 6 &gic 0 0 0 163 IRQ_TYPE_LEVEL_HIGH>, + <0 0 7 &gic 0 0 0 164 IRQ_TYPE_LEVEL_HIGH>, + <0 0 8 &gic 0 0 0 165 IRQ_TYPE_LEVEL_HIGH>, + <0 0 9 &gic 0 0 0 166 IRQ_TYPE_LEVEL_HIGH>, + <0 0 10 &gic 0 0 0 167 IRQ_TYPE_LEVEL_HIGH>, + <0 0 11 &gic 0 0 0 168 IRQ_TYPE_LEVEL_HIGH>, + <0 0 12 &gic 0 0 0 169 IRQ_TYPE_LEVEL_HIGH>; + + /include/ "juno-motherboard.dtsi" + }; diff --git a/arch/arm64/boot/dts/arm/juno-clocks.dtsi b/arch/arm64/boot/dts/arm/juno-clocks.dtsi index c9b89efe0f56..25352ed943e6 100644 --- a/arch/arm64/boot/dts/arm/juno-clocks.dtsi +++ b/arch/arm64/boot/dts/arm/juno-clocks.dtsi @@ -36,9 +36,9 @@ clock-output-names = "apb_pclk"; }; - soc_faxiclk: refclk533mhz { + soc_faxiclk: refclk400mhz { compatible = "fixed-clock"; #clock-cells = <0>; - clock-frequency = <533000000>; + clock-frequency = <400000000>; clock-output-names = "faxi_clk"; }; diff --git a/arch/arm64/boot/dts/arm/juno-r1.dts b/arch/arm64/boot/dts/arm/juno-r1.dts new file mode 100644 index 000000000000..a25964d26bda --- /dev/null +++ b/arch/arm64/boot/dts/arm/juno-r1.dts @@ -0,0 +1,136 @@ +/* + * ARM Ltd. Juno Platform + * + * Copyright (c) 2015 ARM Ltd. + * + * This file is licensed under a dual GPLv2 or BSD license. + */ + +/dts-v1/; + +#include <dt-bindings/interrupt-controller/arm-gic.h> + +/ { + model = "ARM Juno development board (r1)"; + compatible = "arm,juno-r1", "arm,juno", "arm,vexpress"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &soc_uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + A57_0: cpu@0 { + compatible = "arm,cortex-a57","arm,armv8"; + reg = <0x0 0x0>; + device_type = "cpu"; + enable-method = "psci"; + next-level-cache = <&A57_L2>; + }; + + A57_1: cpu@1 { + compatible = "arm,cortex-a57","arm,armv8"; + reg = <0x0 0x1>; + device_type = "cpu"; + enable-method = "psci"; + next-level-cache = <&A57_L2>; + }; + + A53_0: cpu@100 { + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0 0x100>; + device_type = "cpu"; + enable-method = "psci"; + next-level-cache = <&A53_L2>; + }; + + A53_1: cpu@101 { + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0 0x101>; + device_type = "cpu"; + enable-method = "psci"; + next-level-cache = <&A53_L2>; + }; + + A53_2: cpu@102 { + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0 0x102>; + device_type = "cpu"; + enable-method = "psci"; + next-level-cache = <&A53_L2>; + }; + + A53_3: cpu@103 { + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x0 0x103>; + device_type = "cpu"; + enable-method = "psci"; + next-level-cache = <&A53_L2>; + }; + + A57_L2: l2-cache0 { + compatible = "cache"; + }; + + A53_L2: l2-cache1 { + compatible = "cache"; + }; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = <GIC_SPI 02 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 06 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>; + interrupt-affinity = <&A57_0>, + <&A57_1>, + <&A53_0>, + <&A53_1>, + <&A53_2>, + <&A53_3>; + }; + + #include "juno-base.dtsi" + + pcie-controller@40000000 { + compatible = "arm,juno-r1-pcie", "plda,xpressrich3-axi", "pci-host-ecam-generic"; + device_type = "pci"; + reg = <0 0x40000000 0 0x10000000>; /* ECAM config space */ + bus-range = <0 255>; + linux,pci-domain = <0>; + #address-cells = <3>; + #size-cells = <2>; + dma-coherent; + ranges = <0x01000000 0x00 0x5f800000 0x00 0x5f800000 0x0 0x00800000>, + <0x02000000 0x00 0x50000000 0x00 0x50000000 0x0 0x08000000>, + <0x42000000 0x40 0x00000000 0x40 0x00000000 0x1 0x00000000>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &gic 0 0 0 136 4>, + <0 0 0 2 &gic 0 0 0 137 4>, + <0 0 0 3 &gic 0 0 0 138 4>, + <0 0 0 4 &gic 0 0 0 139 4>; + msi-parent = <&v2m_0>; + }; +}; + +&memtimer { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/arm/juno.dts b/arch/arm64/boot/dts/arm/juno.dts index 5e9110a3353d..d7cbdd482a61 100644 --- a/arch/arm64/boot/dts/arm/juno.dts +++ b/arch/arm64/boot/dts/arm/juno.dts @@ -91,33 +91,6 @@ }; }; - memory@80000000 { - device_type = "memory"; - /* last 16MB of the first memory area is reserved for secure world use by firmware */ - reg = <0x00000000 0x80000000 0x0 0x7f000000>, - <0x00000008 0x80000000 0x1 0x80000000>; - }; - - gic: interrupt-controller@2c001000 { - compatible = "arm,gic-400", "arm,cortex-a15-gic"; - reg = <0x0 0x2c010000 0 0x1000>, - <0x0 0x2c02f000 0 0x2000>, - <0x0 0x2c04f000 0 0x2000>, - <0x0 0x2c06f000 0 0x2000>; - #address-cells = <0>; - #interrupt-cells = <3>; - interrupt-controller; - interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_HIGH)>; - }; - - timer { - compatible = "arm,armv8-timer"; - interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>, - <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>, - <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>, - <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>; - }; - pmu { compatible = "arm,armv8-pmuv3"; interrupts = <GIC_SPI 02 IRQ_TYPE_LEVEL_HIGH>, @@ -134,105 +107,5 @@ <&A53_3>; }; - /include/ "juno-clocks.dtsi" - - dma@7ff00000 { - compatible = "arm,pl330", "arm,primecell"; - reg = <0x0 0x7ff00000 0 0x1000>; - #dma-cells = <1>; - #dma-channels = <8>; - #dma-requests = <32>; - interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&soc_faxiclk>; - clock-names = "apb_pclk"; - }; - - soc_uart0: uart@7ff80000 { - compatible = "arm,pl011", "arm,primecell"; - reg = <0x0 0x7ff80000 0x0 0x1000>; - interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&soc_uartclk>, <&soc_refclk100mhz>; - clock-names = "uartclk", "apb_pclk"; - }; - - i2c@7ffa0000 { - compatible = "snps,designware-i2c"; - reg = <0x0 0x7ffa0000 0x0 0x1000>; - #address-cells = <1>; - #size-cells = <0>; - interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>; - clock-frequency = <400000>; - i2c-sda-hold-time-ns = <500>; - clocks = <&soc_smc50mhz>; - - dvi0: dvi-transmitter@70 { - compatible = "nxp,tda998x"; - reg = <0x70>; - }; - - dvi1: dvi-transmitter@71 { - compatible = "nxp,tda998x"; - reg = <0x71>; - }; - }; - - ohci@7ffb0000 { - compatible = "generic-ohci"; - reg = <0x0 0x7ffb0000 0x0 0x10000>; - interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&soc_usb48mhz>; - }; - - ehci@7ffc0000 { - compatible = "generic-ehci"; - reg = <0x0 0x7ffc0000 0x0 0x10000>; - interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&soc_usb48mhz>; - }; - - memory-controller@7ffd0000 { - compatible = "arm,pl354", "arm,primecell"; - reg = <0 0x7ffd0000 0 0x1000>; - interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&soc_smc50mhz>; - clock-names = "apb_pclk"; - }; - - smb { - compatible = "simple-bus"; - #address-cells = <2>; - #size-cells = <1>; - ranges = <0 0 0 0x08000000 0x04000000>, - <1 0 0 0x14000000 0x04000000>, - <2 0 0 0x18000000 0x04000000>, - <3 0 0 0x1c000000 0x04000000>, - <4 0 0 0x0c000000 0x04000000>, - <5 0 0 0x10000000 0x04000000>; - - #interrupt-cells = <1>; - interrupt-map-mask = <0 0 15>; - interrupt-map = <0 0 0 &gic 0 68 IRQ_TYPE_LEVEL_HIGH>, - <0 0 1 &gic 0 69 IRQ_TYPE_LEVEL_HIGH>, - <0 0 2 &gic 0 70 IRQ_TYPE_LEVEL_HIGH>, - <0 0 3 &gic 0 160 IRQ_TYPE_LEVEL_HIGH>, - <0 0 4 &gic 0 161 IRQ_TYPE_LEVEL_HIGH>, - <0 0 5 &gic 0 162 IRQ_TYPE_LEVEL_HIGH>, - <0 0 6 &gic 0 163 IRQ_TYPE_LEVEL_HIGH>, - <0 0 7 &gic 0 164 IRQ_TYPE_LEVEL_HIGH>, - <0 0 8 &gic 0 165 IRQ_TYPE_LEVEL_HIGH>, - <0 0 9 &gic 0 166 IRQ_TYPE_LEVEL_HIGH>, - <0 0 10 &gic 0 167 IRQ_TYPE_LEVEL_HIGH>, - <0 0 11 &gic 0 168 IRQ_TYPE_LEVEL_HIGH>, - <0 0 12 &gic 0 169 IRQ_TYPE_LEVEL_HIGH>; - - /include/ "juno-motherboard.dtsi" - }; + #include "juno-base.dtsi" }; diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index dd301be89ecc..6738cb24c058 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -37,6 +37,7 @@ CONFIG_ARCH_VEXPRESS=y CONFIG_ARCH_XGENE=y CONFIG_PCI=y CONFIG_PCI_MSI=y +CONFIG_PCI_HOST_GENERIC=y CONFIG_PCI_XGENE=y CONFIG_SMP=y CONFIG_PREEMPT=y diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild index dc770bd4f5a5..e315bd833c10 100644 --- a/arch/arm64/include/asm/Kbuild +++ b/arch/arm64/include/asm/Kbuild @@ -28,6 +28,7 @@ generic-y += local64.h generic-y += mcs_spinlock.h generic-y += mman.h generic-y += msgbuf.h +generic-y += msi.h generic-y += mutex.h generic-y += pci.h generic-y += pci-bridge.h diff --git a/arch/frv/mb93090-mb00/pci-vdk.c b/arch/frv/mb93090-mb00/pci-vdk.c index efa5d65b0007..34fb53700e91 100644 --- a/arch/frv/mb93090-mb00/pci-vdk.c +++ b/arch/frv/mb93090-mb00/pci-vdk.c @@ -316,6 +316,7 @@ void pcibios_fixup_bus(struct pci_bus *bus) int __init pcibios_init(void) { + struct pci_bus *bus; struct pci_ops *dir = NULL; LIST_HEAD(resources); @@ -383,12 +384,15 @@ int __init pcibios_init(void) printk("PCI: Probing PCI hardware\n"); pci_add_resource(&resources, &pci_ioport_resource); pci_add_resource(&resources, &pci_iomem_resource); - pci_scan_root_bus(NULL, 0, pci_root_ops, NULL, &resources); + bus = pci_scan_root_bus(NULL, 0, pci_root_ops, NULL, &resources); pcibios_irq_init(); pcibios_fixup_irqs(); pcibios_resource_survey(); + if (!bus) + return 0; + pci_bus_add_devices(bus); return 0; } diff --git a/arch/ia64/kernel/msi_ia64.c b/arch/ia64/kernel/msi_ia64.c index 8c3730c3c63d..8ae36ea177d3 100644 --- a/arch/ia64/kernel/msi_ia64.c +++ b/arch/ia64/kernel/msi_ia64.c @@ -35,7 +35,7 @@ static int ia64_set_msi_irq_affinity(struct irq_data *idata, data |= MSI_DATA_VECTOR(irq_to_vector(irq)); msg.data = data; - write_msi_msg(irq, &msg); + pci_write_msi_msg(irq, &msg); cpumask_copy(idata->affinity, cpumask_of(cpu)); return 0; @@ -71,7 +71,7 @@ int ia64_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) MSI_DATA_DELIVERY_FIXED | MSI_DATA_VECTOR(vector); - write_msi_msg(irq, &msg); + pci_write_msi_msg(irq, &msg); irq_set_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq); return 0; @@ -102,8 +102,8 @@ static int ia64_msi_retrigger_irq(struct irq_data *data) */ static struct irq_chip ia64_msi_chip = { .name = "PCI-MSI", - .irq_mask = mask_msi_irq, - .irq_unmask = unmask_msi_irq, + .irq_mask = pci_msi_mask_irq, + .irq_unmask = pci_msi_unmask_irq, .irq_ack = ia64_ack_msi_irq, #ifdef CONFIG_SMP .irq_set_affinity = ia64_set_msi_irq_affinity, diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index 0b5ce82d203d..1be65eb074ec 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c @@ -271,7 +271,9 @@ sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus) if (bus == NULL) { kfree(res); kfree(controller); + return; } + pci_bus_add_devices(bus); } /* diff --git a/arch/ia64/sn/kernel/msi_sn.c b/arch/ia64/sn/kernel/msi_sn.c index 446e7799928c..a0eb27b66d13 100644 --- a/arch/ia64/sn/kernel/msi_sn.c +++ b/arch/ia64/sn/kernel/msi_sn.c @@ -145,7 +145,7 @@ int sn_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *entry) msg.data = 0x100 + irq; irq_set_msi_desc(irq, entry); - write_msi_msg(irq, &msg); + pci_write_msi_msg(irq, &msg); irq_set_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq); return 0; @@ -205,7 +205,7 @@ static int sn_set_msi_irq_affinity(struct irq_data *data, msg.address_hi = (u32)(bus_addr >> 32); msg.address_lo = (u32)(bus_addr & 0x00000000ffffffff); - write_msi_msg(irq, &msg); + pci_write_msi_msg(irq, &msg); cpumask_copy(data->affinity, cpu_mask); return 0; @@ -228,8 +228,8 @@ static int sn_msi_retrigger_irq(struct irq_data *data) static struct irq_chip sn_msi_chip = { .name = "PCI-MSI", - .irq_mask = mask_msi_irq, - .irq_unmask = unmask_msi_irq, + .irq_mask = pci_msi_mask_irq, + .irq_unmask = pci_msi_unmask_irq, .irq_ack = sn_ack_msi_irq, #ifdef CONFIG_SMP .irq_set_affinity = sn_set_msi_irq_affinity, diff --git a/arch/m68k/coldfire/pci.c b/arch/m68k/coldfire/pci.c index df9679238b6d..821de928dc3f 100644 --- a/arch/m68k/coldfire/pci.c +++ b/arch/m68k/coldfire/pci.c @@ -313,12 +313,16 @@ static int __init mcf_pci_init(void) schedule_timeout(msecs_to_jiffies(200)); rootbus = pci_scan_bus(0, &mcf_pci_ops, NULL); + if (!rootbus) + return -ENODEV; + rootbus->resource[0] = &mcf_pci_io; rootbus->resource[1] = &mcf_pci_mem; pci_fixup_irqs(pci_common_swizzle, mcf_pci_map_irq); pci_bus_size_bridges(rootbus); pci_bus_assign_resources(rootbus); + pci_bus_add_devices(rootbus); return 0; } diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c index b30e41c0c033..a014e5b2e396 100644 --- a/arch/microblaze/pci/pci-common.c +++ b/arch/microblaze/pci/pci-common.c @@ -1371,6 +1371,10 @@ static int __init pcibios_init(void) /* Call common code to handle resource allocation */ pcibios_resource_survey(); + list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { + if (hose->bus) + pci_bus_add_devices(hose->bus); + } return 0; } diff --git a/arch/mips/pci/msi-octeon.c b/arch/mips/pci/msi-octeon.c index 63bbe07a1ccd..cffaaf4aae3c 100644 --- a/arch/mips/pci/msi-octeon.c +++ b/arch/mips/pci/msi-octeon.c @@ -178,7 +178,7 @@ msi_irq_allocated: pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control); irq_set_msi_desc(irq, desc); - write_msi_msg(irq, &msg); + pci_write_msi_msg(irq, &msg); return 0; } diff --git a/arch/mips/pci/msi-xlp.c b/arch/mips/pci/msi-xlp.c index f7ac3edda1b2..6a40f24c91b4 100644 --- a/arch/mips/pci/msi-xlp.c +++ b/arch/mips/pci/msi-xlp.c @@ -217,7 +217,7 @@ static void xlp_msix_mask_ack(struct irq_data *d) msixvec = nlm_irq_msixvec(d->irq); link = nlm_irq_msixlink(msixvec); - mask_msi_irq(d); + pci_msi_mask_irq(d); md = irq_data_get_irq_handler_data(d); /* Ack MSI on bridge */ @@ -239,10 +239,10 @@ static void xlp_msix_mask_ack(struct irq_data *d) static struct irq_chip xlp_msix_chip = { .name = "XLP-MSIX", - .irq_enable = unmask_msi_irq, - .irq_disable = mask_msi_irq, + .irq_enable = pci_msi_unmask_irq, + .irq_disable = pci_msi_mask_irq, .irq_mask_ack = xlp_msix_mask_ack, - .irq_unmask = unmask_msi_irq, + .irq_unmask = pci_msi_unmask_irq, }; void arch_teardown_msi_irq(unsigned int irq) @@ -345,7 +345,7 @@ static int xlp_setup_msi(uint64_t lnkbase, int node, int link, if (ret < 0) return ret; - write_msi_msg(xirq, &msg); + pci_write_msi_msg(xirq, &msg); return 0; } @@ -446,7 +446,7 @@ static int xlp_setup_msix(uint64_t lnkbase, int node, int link, if (ret < 0) return ret; - write_msi_msg(xirq, &msg); + pci_write_msi_msg(xirq, &msg); return 0; } diff --git a/arch/mips/pci/pci-xlr.c b/arch/mips/pci/pci-xlr.c index 0dde80332d3a..26d2dabef281 100644 --- a/arch/mips/pci/pci-xlr.c +++ b/arch/mips/pci/pci-xlr.c @@ -260,7 +260,7 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) if (ret < 0) return ret; - write_msi_msg(irq, &msg); + pci_write_msi_msg(irq, &msg); return 0; } #endif diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index 1bf60b127377..9eb54b557c9f 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c @@ -114,6 +114,7 @@ static void pcibios_scanbus(struct pci_controller *hose) pci_bus_size_bridges(bus); pci_bus_assign_resources(bus); } + pci_bus_add_devices(bus); } } diff --git a/arch/mn10300/unit-asb2305/pci.c b/arch/mn10300/unit-asb2305/pci.c index 6b4339f8c9c2..1d91c74b8d3f 100644 --- a/arch/mn10300/unit-asb2305/pci.c +++ b/arch/mn10300/unit-asb2305/pci.c @@ -347,6 +347,7 @@ static int __init pcibios_init(void) { resource_size_t io_offset, mem_offset; LIST_HEAD(resources); + struct pci_bus *bus; ioport_resource.start = 0xA0000000; ioport_resource.end = 0xDFFFFFFF; @@ -376,11 +377,14 @@ static int __init pcibios_init(void) pci_add_resource_offset(&resources, &pci_ioport_resource, io_offset); pci_add_resource_offset(&resources, &pci_iomem_resource, mem_offset); - pci_scan_root_bus(NULL, 0, &pci_direct_ampci, NULL, &resources); + bus = pci_scan_root_bus(NULL, 0, &pci_direct_ampci, NULL, &resources); + if (!bus) + return 0; pcibios_irq_init(); pcibios_fixup_irqs(); pcibios_resource_survey(); + pci_bus_add_devices(bus); return 0; } diff --git a/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c b/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c index ca3a062ed1b9..11090ab4bf59 100644 --- a/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c +++ b/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c @@ -123,7 +123,8 @@ cpld_pic_cascade(unsigned int irq, struct irq_desc *desc) } static int -cpld_pic_host_match(struct irq_domain *h, struct device_node *node) +cpld_pic_host_match(struct irq_domain *h, struct device_node *node, + enum irq_domain_bus_token bus_token) { return cpld_pic_node == node; } diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c index 862b32702d29..0883994df384 100644 --- a/arch/powerpc/platforms/cell/axon_msi.c +++ b/arch/powerpc/platforms/cell/axon_msi.c @@ -279,7 +279,7 @@ static int axon_msi_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) irq_set_msi_desc(virq, entry); msg.data = virq; - write_msi_msg(virq, &msg); + pci_write_msi_msg(virq, &msg); } return 0; @@ -301,9 +301,9 @@ static void axon_msi_teardown_msi_irqs(struct pci_dev *dev) } static struct irq_chip msic_irq_chip = { - .irq_mask = mask_msi_irq, - .irq_unmask = unmask_msi_irq, - .irq_shutdown = mask_msi_irq, + .irq_mask = pci_msi_mask_irq, + .irq_unmask = pci_msi_unmask_irq, + .irq_shutdown = pci_msi_mask_irq, .name = "AXON-MSI", }; diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 28e558d3316d..109d236ca492 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c @@ -222,7 +222,8 @@ void iic_request_IPIs(void) #endif /* CONFIG_SMP */ -static int iic_host_match(struct irq_domain *h, struct device_node *node) +static int iic_host_match(struct irq_domain *h, struct device_node *node, + enum irq_domain_bus_token bus_token) { return of_device_is_compatible(node, "IBM,CBEA-Internal-Interrupt-Controller"); diff --git a/arch/powerpc/platforms/embedded6xx/flipper-pic.c b/arch/powerpc/platforms/embedded6xx/flipper-pic.c index 4cde8e7da4b8..b7866e01483d 100644 --- a/arch/powerpc/platforms/embedded6xx/flipper-pic.c +++ b/arch/powerpc/platforms/embedded6xx/flipper-pic.c @@ -108,7 +108,8 @@ static int flipper_pic_map(struct irq_domain *h, unsigned int virq, return 0; } -static int flipper_pic_match(struct irq_domain *h, struct device_node *np) +static int flipper_pic_match(struct irq_domain *h, struct device_node *np, + enum irq_domain_bus_token bus_token) { return 1; } diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c index 4c24bf60d39d..246cab46bffe 100644 --- a/arch/powerpc/platforms/powermac/pic.c +++ b/arch/powerpc/platforms/powermac/pic.c @@ -268,7 +268,8 @@ static struct irqaction gatwick_cascade_action = { .name = "cascade", }; -static int pmac_pic_host_match(struct irq_domain *h, struct device_node *node) +static int pmac_pic_host_match(struct irq_domain *h, struct device_node *node, + enum irq_domain_bus_token bus_token) { /* We match all, we don't always have a node anyway */ return 1; diff --git a/arch/powerpc/platforms/powernv/opal-irqchip.c b/arch/powerpc/platforms/powernv/opal-irqchip.c new file mode 100644 index 000000000000..2c91ee7800b9 --- /dev/null +++ b/arch/powerpc/platforms/powernv/opal-irqchip.c @@ -0,0 +1,254 @@ +/* + * This file implements an irqchip for OPAL events. Whenever there is + * an interrupt that is handled by OPAL we get passed a list of events + * that Linux needs to do something about. These basically look like + * interrupts to Linux so we implement an irqchip to handle them. + * + * Copyright Alistair Popple, IBM Corporation 2014. + * + * 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/bitops.h> +#include <linux/irq.h> +#include <linux/irqchip.h> +#include <linux/irqdomain.h> +#include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/kthread.h> +#include <linux/delay.h> +#include <linux/slab.h> +#include <linux/irq_work.h> + +#include <asm/machdep.h> +#include <asm/opal.h> + +#include "powernv.h" + +/* Maximum number of events supported by OPAL firmware */ +#define MAX_NUM_EVENTS 64 + +struct opal_event_irqchip { + struct irq_chip irqchip; + struct irq_domain *domain; + unsigned long mask; +}; +static struct opal_event_irqchip opal_event_irqchip; + +static unsigned int opal_irq_count; +static unsigned int *opal_irqs; + +static void opal_handle_irq_work(struct irq_work *work); +static __be64 last_outstanding_events; +static struct irq_work opal_event_irq_work = { + .func = opal_handle_irq_work, +}; + +static void opal_event_mask(struct irq_data *d) +{ + clear_bit(d->hwirq, &opal_event_irqchip.mask); +} + +static void opal_event_unmask(struct irq_data *d) +{ + set_bit(d->hwirq, &opal_event_irqchip.mask); + + opal_poll_events(&last_outstanding_events); + if (last_outstanding_events & opal_event_irqchip.mask) + /* Need to retrigger the interrupt */ + irq_work_queue(&opal_event_irq_work); +} + +static int opal_event_set_type(struct irq_data *d, unsigned int flow_type) +{ + /* + * For now we only support level triggered events. The irq + * handler will be called continuously until the event has + * been cleared in OPAL. + */ + if (flow_type != IRQ_TYPE_LEVEL_HIGH) + return -EINVAL; + + return 0; +} + +static struct opal_event_irqchip opal_event_irqchip = { + .irqchip = { + .name = "OPAL EVT", + .irq_mask = opal_event_mask, + .irq_unmask = opal_event_unmask, + .irq_set_type = opal_event_set_type, + }, + .mask = 0, +}; + +static int opal_event_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hwirq) +{ + irq_set_chip_data(irq, &opal_event_irqchip); + irq_set_chip_and_handler(irq, &opal_event_irqchip.irqchip, + handle_level_irq); + + return 0; +} + +void opal_handle_events(uint64_t events) +{ + int virq, hwirq = 0; + u64 mask = opal_event_irqchip.mask; + + if (!in_irq() && (events & mask)) { + last_outstanding_events = events; + irq_work_queue(&opal_event_irq_work); + return; + } + + while (events & mask) { + hwirq = fls64(events) - 1; + if (BIT_ULL(hwirq) & mask) { + virq = irq_find_mapping(opal_event_irqchip.domain, + hwirq); + if (virq) + generic_handle_irq(virq); + } + events &= ~BIT_ULL(hwirq); + } +} + +static irqreturn_t opal_interrupt(int irq, void *data) +{ + __be64 events; + + opal_handle_interrupt(virq_to_hw(irq), &events); + opal_handle_events(be64_to_cpu(events)); + + return IRQ_HANDLED; +} + +static void opal_handle_irq_work(struct irq_work *work) +{ + opal_handle_events(be64_to_cpu(last_outstanding_events)); +} + +static int opal_event_match(struct irq_domain *h, struct device_node *node, + enum irq_domain_bus_token bus_token) +{ + return h->of_node == node; +} + +static int opal_event_xlate(struct irq_domain *h, struct device_node *np, + const u32 *intspec, unsigned int intsize, + irq_hw_number_t *out_hwirq, unsigned int *out_flags) +{ + *out_hwirq = intspec[0]; + *out_flags = IRQ_TYPE_LEVEL_HIGH; + + return 0; +} + +static const struct irq_domain_ops opal_event_domain_ops = { + .match = opal_event_match, + .map = opal_event_map, + .xlate = opal_event_xlate, +}; + +void opal_event_shutdown(void) +{ + unsigned int i; + + /* First free interrupts, which will also mask them */ + for (i = 0; i < opal_irq_count; i++) { + if (opal_irqs[i]) + free_irq(opal_irqs[i], NULL); + opal_irqs[i] = 0; + } +} + +int __init opal_event_init(void) +{ + struct device_node *dn, *opal_node; + const __be32 *irqs; + int i, irqlen, rc = 0; + + opal_node = of_find_node_by_path("/ibm,opal"); + if (!opal_node) { + pr_warn("opal: Node not found\n"); + return -ENODEV; + } + + /* If dn is NULL it means the domain won't be linked to a DT + * node so therefore irq_of_parse_and_map(...) wont work. But + * that shouldn't be problem because if we're running a + * version of skiboot that doesn't have the dn then the + * devices won't have the correct properties and will have to + * fall back to the legacy method (opal_event_request(...)) + * anyway. */ + dn = of_find_compatible_node(NULL, NULL, "ibm,opal-event"); + opal_event_irqchip.domain = irq_domain_add_linear(dn, MAX_NUM_EVENTS, + &opal_event_domain_ops, &opal_event_irqchip); + of_node_put(dn); + if (!opal_event_irqchip.domain) { + pr_warn("opal: Unable to create irq domain\n"); + rc = -ENOMEM; + goto out; + } + + /* Get interrupt property */ + irqs = of_get_property(opal_node, "opal-interrupts", &irqlen); + opal_irq_count = irqs ? (irqlen / 4) : 0; + pr_debug("Found %d interrupts reserved for OPAL\n", opal_irq_count); + + /* Install interrupt handlers */ + opal_irqs = kcalloc(opal_irq_count, sizeof(*opal_irqs), GFP_KERNEL); + for (i = 0; irqs && i < opal_irq_count; i++, irqs++) { + unsigned int irq, virq; + + /* Get hardware and virtual IRQ */ + irq = be32_to_cpup(irqs); + virq = irq_create_mapping(NULL, irq); + if (virq == NO_IRQ) { + pr_warn("Failed to map irq 0x%x\n", irq); + continue; + } + + /* Install interrupt handler */ + rc = request_irq(virq, opal_interrupt, 0, "opal", NULL); + if (rc) { + irq_dispose_mapping(virq); + pr_warn("Error %d requesting irq %d (0x%x)\n", + rc, virq, irq); + continue; + } + + /* Cache IRQ */ + opal_irqs[i] = virq; + } + +out: + of_node_put(opal_node); + return rc; +} +machine_arch_initcall(powernv, opal_event_init); + +/** + * opal_event_request(unsigned int opal_event_nr) - Request an event + * @opal_event_nr: the opal event number to request + * + * This routine can be used to find the linux virq number which can + * then be passed to request_irq to assign a handler for a particular + * opal event. This should only be used by legacy devices which don't + * have proper device tree bindings. Most devices should use + * irq_of_parse_and_map() instead. + */ +int opal_event_request(unsigned int opal_event_nr) +{ + if (WARN_ON_ONCE(!opal_event_irqchip.domain)) + return NO_IRQ; + + return irq_create_mapping(opal_event_irqchip.domain, opal_event_nr); +} +EXPORT_SYMBOL(opal_event_request); diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index 9ff55d59ac76..019991d574a0 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c @@ -90,7 +90,7 @@ static int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) return rc; } irq_set_msi_desc(virq, entry); - write_msi_msg(virq, &msg); + pci_write_msi_msg(virq, &msg); } return 0; } diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c index 5f3b23220b8e..df0c086d8197 100644 --- a/arch/powerpc/platforms/ps3/interrupt.c +++ b/arch/powerpc/platforms/ps3/interrupt.c @@ -678,7 +678,8 @@ static int ps3_host_map(struct irq_domain *h, unsigned int virq, return 0; } -static int ps3_host_match(struct irq_domain *h, struct device_node *np) +static int ps3_host_match(struct irq_domain *h, struct device_node *np, + enum irq_domain_bus_token bus_token) { /* Match all */ return 1; diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c index 8b909e94fd9a..691a154c286d 100644 --- a/arch/powerpc/platforms/pseries/msi.c +++ b/arch/powerpc/platforms/pseries/msi.c @@ -476,7 +476,7 @@ again: irq_set_msi_desc(virq, entry); /* Read config space back so we can restore after reset */ - __read_msi_msg(entry, &msg); + __pci_read_msi_msg(entry, &msg); entry->msg = msg; } diff --git a/arch/powerpc/sysdev/ehv_pic.c b/arch/powerpc/sysdev/ehv_pic.c index 2d20f10a4203..eca0b00794fa 100644 --- a/arch/powerpc/sysdev/ehv_pic.c +++ b/arch/powerpc/sysdev/ehv_pic.c @@ -177,7 +177,8 @@ unsigned int ehv_pic_get_irq(void) return irq_linear_revmap(global_ehv_pic->irqhost, irq); } -static int ehv_pic_host_match(struct irq_domain *h, struct device_node *node) +static int ehv_pic_host_match(struct irq_domain *h, struct device_node *node, + enum irq_domain_bus_token bus_token) { /* Exact match, unless ehv_pic node is NULL */ return h->of_node == NULL || h->of_node == node; diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c index ea6b3a1c79d8..f13282ca3ee9 100644 --- a/arch/powerpc/sysdev/fsl_msi.c +++ b/arch/powerpc/sysdev/fsl_msi.c @@ -82,8 +82,8 @@ static void fsl_msi_print_chip(struct irq_data *irqd, struct seq_file *p) static struct irq_chip fsl_msi_chip = { - .irq_mask = mask_msi_irq, - .irq_unmask = unmask_msi_irq, + .irq_mask = pci_msi_mask_irq, + .irq_unmask = pci_msi_unmask_irq, .irq_ack = fsl_msi_end_irq, .irq_print_chip = fsl_msi_print_chip, }; @@ -243,7 +243,7 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) irq_set_msi_desc(virq, entry); fsl_compose_msi_msg(pdev, hwirq, &msg, msi_data); - write_msi_msg(virq, &msg); + pci_write_msi_msg(virq, &msg); } return 0; diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c index 45598da0b321..8c3756cbc4f9 100644 --- a/arch/powerpc/sysdev/i8259.c +++ b/arch/powerpc/sysdev/i8259.c @@ -162,7 +162,8 @@ static struct resource pic_edgectrl_iores = { .flags = IORESOURCE_BUSY, }; -static int i8259_host_match(struct irq_domain *h, struct device_node *node) +static int i8259_host_match(struct irq_domain *h, struct device_node *node, + enum irq_domain_bus_token bus_token) { return h->of_node == NULL || h->of_node == node; } diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c index b50f97811c25..1b9b00f90388 100644 --- a/arch/powerpc/sysdev/ipic.c +++ b/arch/powerpc/sysdev/ipic.c @@ -672,7 +672,8 @@ static struct irq_chip ipic_edge_irq_chip = { .irq_set_type = ipic_set_irq_type, }; -static int ipic_host_match(struct irq_domain *h, struct device_node *node) +static int ipic_host_match(struct irq_domain *h, struct device_node *node, + enum irq_domain_bus_token bus_token) { /* Exact match, unless ipic node is NULL */ return h->of_node == NULL || h->of_node == node; diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 89cec0ed6a58..bf6f77e274b2 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -1009,7 +1009,8 @@ static struct irq_chip mpic_irq_ht_chip = { #endif /* CONFIG_MPIC_U3_HT_IRQS */ -static int mpic_host_match(struct irq_domain *h, struct device_node *node) +static int mpic_host_match(struct irq_domain *h, struct device_node *node, + enum irq_domain_bus_token bus_token) { /* Exact match, unless mpic node is NULL */ return h->of_node == NULL || h->of_node == node; diff --git a/arch/powerpc/sysdev/mpic_pasemi_msi.c b/arch/powerpc/sysdev/mpic_pasemi_msi.c index a6add4ae6c5a..5a4c4741cf14 100644 --- a/arch/powerpc/sysdev/mpic_pasemi_msi.c +++ b/arch/powerpc/sysdev/mpic_pasemi_msi.c @@ -42,7 +42,7 @@ static struct mpic *msi_mpic; static void mpic_pasemi_msi_mask_irq(struct irq_data *data) { pr_debug("mpic_pasemi_msi_mask_irq %d\n", data->irq); - mask_msi_irq(data); + pci_msi_mask_irq(data); mpic_mask_irq(data); } @@ -50,7 +50,7 @@ static void mpic_pasemi_msi_unmask_irq(struct irq_data *data) { pr_debug("mpic_pasemi_msi_unmask_irq %d\n", data->irq); mpic_unmask_irq(data); - unmask_msi_irq(data); + pci_msi_unmask_irq(data); } static struct irq_chip mpic_pasemi_msi_chip = { @@ -138,7 +138,7 @@ static int pasemi_msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) * register to generate MSI [512...1023] */ msg.data = hwirq-0x200; - write_msi_msg(virq, &msg); + pci_write_msi_msg(virq, &msg); } return 0; diff --git a/arch/powerpc/sysdev/mpic_u3msi.c b/arch/powerpc/sysdev/mpic_u3msi.c index db35a4073127..65880ccd3d36 100644 --- a/arch/powerpc/sysdev/mpic_u3msi.c +++ b/arch/powerpc/sysdev/mpic_u3msi.c @@ -25,14 +25,14 @@ static struct mpic *msi_mpic; static void mpic_u3msi_mask_irq(struct irq_data *data) { - mask_msi_irq(data); + pci_msi_mask_irq(data); mpic_mask_irq(data); } static void mpic_u3msi_unmask_irq(struct irq_data *data) { mpic_unmask_irq(data); - unmask_msi_irq(data); + pci_msi_unmask_irq(data); } static struct irq_chip mpic_u3msi_chip = { @@ -172,7 +172,7 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) printk("u3msi: allocated virq 0x%x (hw 0x%x) addr 0x%lx\n", virq, hwirq, (unsigned long)addr); msg.data = hwirq; - write_msi_msg(virq, &msg); + pci_write_msi_msg(virq, &msg); hwirq++; } diff --git a/arch/powerpc/sysdev/ppc4xx_hsta_msi.c b/arch/powerpc/sysdev/ppc4xx_hsta_msi.c index a6a4dbda9078..908105f835d1 100644 --- a/arch/powerpc/sysdev/ppc4xx_hsta_msi.c +++ b/arch/powerpc/sysdev/ppc4xx_hsta_msi.c @@ -85,7 +85,7 @@ static int hsta_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) msi_bitmap_free_hwirqs(&ppc4xx_hsta_msi.bmp, irq, 1); return -EINVAL; } - write_msi_msg(hwirq, &msg); + pci_write_msi_msg(hwirq, &msg); } return 0; diff --git a/arch/powerpc/sysdev/ppc4xx_msi.c b/arch/powerpc/sysdev/ppc4xx_msi.c index 85d9c1852d19..c6df3e205eab 100644 --- a/arch/powerpc/sysdev/ppc4xx_msi.c +++ b/arch/powerpc/sysdev/ppc4xx_msi.c @@ -116,7 +116,7 @@ static int ppc4xx_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) irq_set_msi_desc(virq, entry); msg.data = int_no; - write_msi_msg(virq, &msg); + pci_write_msi_msg(virq, &msg); } return 0; } diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c index b2b87c30e266..a433b3d40d18 100644 --- a/arch/powerpc/sysdev/qe_lib/qe_ic.c +++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c @@ -245,7 +245,8 @@ static struct irq_chip qe_ic_irq_chip = { .irq_mask_ack = qe_ic_mask_irq, }; -static int qe_ic_host_match(struct irq_domain *h, struct device_node *node) +static int qe_ic_host_match(struct irq_domain *h, struct device_node *node, + enum irq_domain_bus_token bus_token) { /* Exact match, unless qe_ic node is NULL */ return h->of_node == NULL || h->of_node == node; diff --git a/arch/powerpc/sysdev/xics/ics-opal.c b/arch/powerpc/sysdev/xics/ics-opal.c index 3c6ee1b64e5d..4ba554ec8eaf 100644 --- a/arch/powerpc/sysdev/xics/ics-opal.c +++ b/arch/powerpc/sysdev/xics/ics-opal.c @@ -73,7 +73,7 @@ static unsigned int ics_opal_startup(struct irq_data *d) * at that level, so we do it here by hand. */ if (d->msi_desc) - unmask_msi_irq(d); + pci_msi_unmask_irq(d); #endif /* unmask it */ diff --git a/arch/powerpc/sysdev/xics/ics-rtas.c b/arch/powerpc/sysdev/xics/ics-rtas.c index 936575d99c5c..bc81335b2cbc 100644 --- a/arch/powerpc/sysdev/xics/ics-rtas.c +++ b/arch/powerpc/sysdev/xics/ics-rtas.c @@ -76,7 +76,7 @@ static unsigned int ics_rtas_startup(struct irq_data *d) * at that level, so we do it here by hand. */ if (d->msi_desc) - unmask_msi_irq(d); + pci_msi_unmask_irq(d); #endif /* unmask it */ ics_rtas_unmask_irq(d); diff --git a/arch/powerpc/sysdev/xics/xics-common.c b/arch/powerpc/sysdev/xics/xics-common.c index fe0cca477164..13ab71690923 100644 --- a/arch/powerpc/sysdev/xics/xics-common.c +++ b/arch/powerpc/sysdev/xics/xics-common.c @@ -300,7 +300,8 @@ int xics_get_irq_server(unsigned int virq, const struct cpumask *cpumask, } #endif /* CONFIG_SMP */ -static int xics_host_match(struct irq_domain *h, struct device_node *node) +static int xics_host_match(struct irq_domain *h, struct device_node *node, + enum irq_domain_bus_token bus_token) { struct ics *ics; diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index 2fa7b14b9c08..dda4782fa1f4 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -50,8 +50,8 @@ static DEFINE_SPINLOCK(zpci_list_lock); static struct irq_chip zpci_irq_chip = { .name = "zPCI", - .irq_unmask = unmask_msi_irq, - .irq_mask = mask_msi_irq, + .irq_unmask = pci_msi_unmask_irq, + .irq_mask = pci_msi_mask_irq, }; static DECLARE_BITMAP(zpci_domain, ZPCI_NR_DEVICES); @@ -403,7 +403,7 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) msg.data = hwirq; msg.address_lo = zdev->msi_addr & 0xffffffff; msg.address_hi = zdev->msi_addr >> 32; - write_msi_msg(irq, &msg); + pci_write_msi_msg(irq, &msg); airq_iv_set_data(zdev->aibv, hwirq, irq); hwirq++; } @@ -448,9 +448,9 @@ void arch_teardown_msi_irqs(struct pci_dev *pdev) /* Release MSI interrupts */ list_for_each_entry(msi, &pdev->msi_list, list) { if (msi->msi_attrib.is_msix) - default_msix_mask_irq(msi, 1); + __pci_msix_desc_mask_irq(msi, 1); else - default_msi_mask_irq(msi, 1, 1); + __pci_msi_desc_mask_irq(msi, 1, 1); irq_set_msi_desc(msi->irq, NULL); irq_free_desc(msi->irq); msi->msg.address_lo = 0; @@ -755,8 +755,8 @@ static int zpci_scan_bus(struct zpci_dev *zdev) zpci_cleanup_bus_resources(zdev); return -EIO; } - zdev->bus->max_bus_speed = zdev->max_bus_speed; + pci_bus_add_devices(zdev->bus); return 0; } diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c index 1bc09ee7948f..efc10519916a 100644 --- a/arch/sh/drivers/pci/pci.c +++ b/arch/sh/drivers/pci/pci.c @@ -69,6 +69,7 @@ static void pcibios_scanbus(struct pci_channel *hose) pci_bus_size_bridges(bus); pci_bus_assign_resources(bus); + pci_bus_add_devices(bus); } else { pci_free_resource_list(&resources); } diff --git a/arch/sparc/kernel/leon_pci.c b/arch/sparc/kernel/leon_pci.c index 899b7203a4e4..297107679fdf 100644 --- a/arch/sparc/kernel/leon_pci.c +++ b/arch/sparc/kernel/leon_pci.c @@ -40,6 +40,7 @@ void leon_pci_init(struct platform_device *ofdev, struct leon_pci_info *info) /* Assign devices with resources */ pci_assign_unassigned_resources(); + pci_bus_add_devices(root_bus); } else { pci_free_resource_list(&resources); } diff --git a/arch/sparc/kernel/pci_msi.c b/arch/sparc/kernel/pci_msi.c index 580651af73f2..84e16d81a6d8 100644 --- a/arch/sparc/kernel/pci_msi.c +++ b/arch/sparc/kernel/pci_msi.c @@ -111,10 +111,10 @@ static void free_msi(struct pci_pbm_info *pbm, int msi_num) static struct irq_chip msi_irq = { .name = "PCI-MSI", - .irq_mask = mask_msi_irq, - .irq_unmask = unmask_msi_irq, - .irq_enable = unmask_msi_irq, - .irq_disable = mask_msi_irq, + .irq_mask = pci_msi_mask_irq, + .irq_unmask = pci_msi_unmask_irq, + .irq_enable = pci_msi_unmask_irq, + .irq_disable = pci_msi_mask_irq, /* XXX affinity XXX */ }; @@ -161,7 +161,7 @@ static int sparc64_setup_msi_irq(unsigned int *irq_p, msg.data = msi; irq_set_msi_desc(*irq_p, entry); - write_msi_msg(*irq_p, &msg); + pci_write_msi_msg(*irq_p, &msg); return 0; diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index 6cc78c213c01..24384e1dc33d 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -391,12 +391,16 @@ static void __init pcic_pbm_scan_bus(struct linux_pcic *pcic) struct linux_pbm_info *pbm = &pcic->pbm; pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno, &pcic_ops, pbm); + if (!pbm->pci_bus) + return; + #if 0 /* deadwood transplanted from sparc64 */ pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node); pci_record_assignments(pbm, pbm->pci_bus); pci_assign_unassigned(pbm, pbm->pci_bus); pci_fixup_irq(pbm, pbm->pci_bus); #endif + pci_bus_add_devices(pbm->pci_bus); } /* diff --git a/arch/tile/kernel/pci.c b/arch/tile/kernel/pci.c index 1f80a88c75a6..9503957f5d9e 100644 --- a/arch/tile/kernel/pci.c +++ b/arch/tile/kernel/pci.c @@ -339,6 +339,8 @@ int __init pcibios_init(void) struct pci_bus *next_bus; struct pci_dev *dev; + pci_bus_add_devices(root_bus); + list_for_each_entry(dev, &root_bus->devices, bus_list) { /* * Find the PCI host controller, ie. the 1st diff --git a/arch/tile/kernel/pci_gx.c b/arch/tile/kernel/pci_gx.c index e39f9c542807..be79d2894e73 100644 --- a/arch/tile/kernel/pci_gx.c +++ b/arch/tile/kernel/pci_gx.c @@ -1042,6 +1042,8 @@ int __init pcibios_init(void) alloc_mem_map_failed: break; } + + pci_bus_add_devices(root_bus); } return 0; @@ -1453,7 +1455,7 @@ static struct pci_ops tile_cfg_ops = { static unsigned int tilegx_msi_startup(struct irq_data *d) { if (d->msi_desc) - unmask_msi_irq(d); + pci_msi_unmask_irq(d); return 0; } @@ -1465,14 +1467,14 @@ static void tilegx_msi_ack(struct irq_data *d) static void tilegx_msi_mask(struct irq_data *d) { - mask_msi_irq(d); + pci_msi_mask_irq(d); __insn_mtspr(SPR_IPI_MASK_SET_K, 1UL << d->irq); } static void tilegx_msi_unmask(struct irq_data *d) { __insn_mtspr(SPR_IPI_MASK_RESET_K, 1UL << d->irq); - unmask_msi_irq(d); + pci_msi_unmask_irq(d); } static struct irq_chip tilegx_msi_chip = { @@ -1590,7 +1592,7 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) msg.address_hi = msi_addr >> 32; msg.address_lo = msi_addr & 0xffffffff; - write_msi_msg(irq, &msg); + pci_write_msi_msg(irq, &msg); irq_set_chip_and_handler(irq, &tilegx_msi_chip, handle_level_irq); irq_set_handler_data(irq, controller); diff --git a/arch/unicore32/kernel/pci.c b/arch/unicore32/kernel/pci.c index 374a055a8e6b..d45fa5f3e9c4 100644 --- a/arch/unicore32/kernel/pci.c +++ b/arch/unicore32/kernel/pci.c @@ -266,17 +266,10 @@ static int __init pci_common_init(void) pci_fixup_irqs(pci_common_swizzle, pci_puv3_map_irq); if (!pci_has_flag(PCI_PROBE_ONLY)) { - /* - * Size the bridge windows. - */ pci_bus_size_bridges(puv3_bus); - - /* - * Assign resources. - */ pci_bus_assign_resources(puv3_bus); } - + pci_bus_add_devices(puv3_bus); return 0; } subsys_initcall(pci_common_init); diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h index e45e4da96bf1..f58a9c7a3c86 100644 --- a/arch/x86/include/asm/x86_init.h +++ b/arch/x86/include/asm/x86_init.h @@ -172,7 +172,6 @@ struct x86_platform_ops { struct pci_dev; struct msi_msg; -struct msi_desc; struct x86_msi_ops { int (*setup_msi_irqs)(struct pci_dev *dev, int nvec, int type); @@ -183,8 +182,6 @@ struct x86_msi_ops { void (*teardown_msi_irqs)(struct pci_dev *dev); void (*restore_msi_irqs)(struct pci_dev *dev); int (*setup_hpet_msi)(unsigned int irq, unsigned int id); - u32 (*msi_mask_irq)(struct msi_desc *desc, u32 mask, u32 flag); - u32 (*msix_mask_irq)(struct msi_desc *desc, u32 flag); }; struct IO_APIC_route_entry; diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 1183d545da1e..7ffe0a2b870f 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -3158,7 +3158,7 @@ msi_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force) msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK; msg.address_lo |= MSI_ADDR_DEST_ID(dest); - __write_msi_msg(data->msi_desc, &msg); + __pci_write_msi_msg(data->msi_desc, &msg); return IRQ_SET_MASK_OK_NOCOPY; } @@ -3169,8 +3169,8 @@ msi_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force) */ static struct irq_chip msi_chip = { .name = "PCI-MSI", - .irq_unmask = unmask_msi_irq, - .irq_mask = mask_msi_irq, + .irq_unmask = pci_msi_unmask_irq, + .irq_mask = pci_msi_mask_irq, .irq_ack = ack_apic_edge, .irq_set_affinity = msi_set_affinity, .irq_retrigger = ioapic_retrigger_irq, @@ -3196,7 +3196,7 @@ int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, * MSI message denotes a contiguous group of IRQs, written for 0th IRQ. */ if (!irq_offset) - write_msi_msg(irq, &msg); + pci_write_msi_msg(irq, &msg); setup_remapped_irq(irq, irq_cfg(irq), chip); diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c index e48b674639cc..234b0722de53 100644 --- a/arch/x86/kernel/x86_init.c +++ b/arch/x86/kernel/x86_init.c @@ -116,8 +116,6 @@ struct x86_msi_ops x86_msi = { .teardown_msi_irqs = default_teardown_msi_irqs, .restore_msi_irqs = default_restore_msi_irqs, .setup_hpet_msi = default_setup_hpet_msi, - .msi_mask_irq = default_msi_mask_irq, - .msix_mask_irq = default_msix_mask_irq, }; /* MSI arch specific hooks */ @@ -140,14 +138,6 @@ void arch_restore_msi_irqs(struct pci_dev *dev) { x86_msi.restore_msi_irqs(dev); } -u32 arch_msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) -{ - return x86_msi.msi_mask_irq(desc, mask, flag); -} -u32 arch_msix_mask_irq(struct msi_desc *desc, u32 flag) -{ - return x86_msi.msix_mask_irq(desc, flag); -} #endif struct x86_io_apic_ops x86_io_apic_ops = { diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 2fb384724ebb..8fd6f44aee83 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -490,7 +490,9 @@ void pcibios_scan_root(int busnum) if (!bus) { pci_free_resource_list(&resources); kfree(sd); + return; } + pci_bus_add_devices(bus); } void __init pcibios_set_cache_line_size(void) diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index 6b3cf7c4e5c2..4f6844b9657d 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -229,7 +229,7 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) return 1; list_for_each_entry(msidesc, &dev->msi_list, list) { - __read_msi_msg(msidesc, &msg); + __pci_read_msi_msg(msidesc, &msg); pirq = MSI_ADDR_EXT_DEST_ID(msg.address_hi) | ((msg.address_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xff); if (msg.data != XEN_PIRQ_MSI_DATA || @@ -240,7 +240,7 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) goto error; } xen_msi_compose_msg(dev, pirq, &msg); - __write_msi_msg(msidesc, &msg); + __pci_write_msi_msg(msidesc, &msg); dev_dbg(&dev->dev, "xen: msi bound to pirq=%d\n", pirq); } else { dev_dbg(&dev->dev, @@ -394,14 +394,7 @@ static void xen_teardown_msi_irq(unsigned int irq) { xen_destroy_irq(irq); } -static u32 xen_nop_msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) -{ - return 0; -} -static u32 xen_nop_msix_mask_irq(struct msi_desc *desc, u32 flag) -{ - return 0; -} + #endif int __init pci_xen_init(void) @@ -425,8 +418,7 @@ int __init pci_xen_init(void) x86_msi.setup_msi_irqs = xen_setup_msi_irqs; x86_msi.teardown_msi_irq = xen_teardown_msi_irq; x86_msi.teardown_msi_irqs = xen_teardown_msi_irqs; - x86_msi.msi_mask_irq = xen_nop_msi_mask_irq; - x86_msi.msix_mask_irq = xen_nop_msix_mask_irq; + pci_msi_ignore_mask = 1; #endif return 0; } @@ -460,8 +452,7 @@ int __init pci_xen_initial_domain(void) x86_msi.setup_msi_irqs = xen_initdom_setup_msi_irqs; x86_msi.teardown_msi_irq = xen_teardown_msi_irq; x86_msi.restore_msi_irqs = xen_initdom_restore_msi_irqs; - x86_msi.msi_mask_irq = xen_nop_msi_mask_irq; - x86_msi.msix_mask_irq = xen_nop_msix_mask_irq; + pci_msi_ignore_mask = 1; #endif __acpi_register_gsi = acpi_register_gsi_xen; /* Pre-allocate legacy irqs */ diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c index 5b3403388d7f..b848cc3dc913 100644 --- a/arch/xtensa/kernel/pci.c +++ b/arch/xtensa/kernel/pci.c @@ -174,7 +174,7 @@ static int __init pcibios_init(void) struct pci_controller *pci_ctrl; struct list_head resources; struct pci_bus *bus; - int next_busno = 0; + int next_busno = 0, ret; printk("PCI: Probing PCI hardware\n"); @@ -185,14 +185,25 @@ static int __init pcibios_init(void) pci_controller_apertures(pci_ctrl, &resources); bus = pci_scan_root_bus(NULL, pci_ctrl->first_busno, pci_ctrl->ops, pci_ctrl, &resources); + if (!bus) + continue; + pci_ctrl->bus = bus; pci_ctrl->last_busno = bus->busn_res.end; if (next_busno <= pci_ctrl->last_busno) next_busno = pci_ctrl->last_busno+1; } pci_bus_count = next_busno; + ret = platform_pcibios_fixup(); + if (ret) + return ret; - return platform_pcibios_fixup(); + for (pci_ctrl = pci_ctrl_head; pci_ctrl; pci_ctrl = pci_ctrl->next) { + if (pci_ctrl->bus) + pci_bus_add_devices(pci_ctrl->bus); + } + + return 0; } subsys_initcall(pcibios_init); |