diff options
26 files changed, 1393 insertions, 440 deletions
diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/r8a7779.dtsi new file mode 100644 index 000000000000..fe5c6f213271 --- /dev/null +++ b/arch/arm/boot/dts/r8a7779.dtsi | |||
| @@ -0,0 +1,98 @@ | |||
| 1 | /* | ||
| 2 | * Device Tree Source for Renesas r8a7779 | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Renesas Solutions Corp. | ||
| 5 | * Copyright (C) 2013 Simon Horman | ||
| 6 | * | ||
| 7 | * This file is licensed under the terms of the GNU General Public License | ||
| 8 | * version 2. This program is licensed "as is" without any warranty of any | ||
| 9 | * kind, whether express or implied. | ||
| 10 | */ | ||
| 11 | |||
| 12 | /include/ "skeleton.dtsi" | ||
| 13 | |||
| 14 | / { | ||
| 15 | compatible = "renesas,r8a7779"; | ||
| 16 | |||
| 17 | cpus { | ||
| 18 | #address-cells = <1>; | ||
| 19 | #size-cells = <0>; | ||
| 20 | |||
| 21 | cpu@0 { | ||
| 22 | device_type = "cpu"; | ||
| 23 | compatible = "arm,cortex-a9"; | ||
| 24 | reg = <0>; | ||
| 25 | }; | ||
| 26 | cpu@1 { | ||
| 27 | device_type = "cpu"; | ||
| 28 | compatible = "arm,cortex-a9"; | ||
| 29 | reg = <1>; | ||
| 30 | }; | ||
| 31 | cpu@2 { | ||
| 32 | device_type = "cpu"; | ||
| 33 | compatible = "arm,cortex-a9"; | ||
| 34 | reg = <2>; | ||
| 35 | }; | ||
| 36 | cpu@3 { | ||
| 37 | device_type = "cpu"; | ||
| 38 | compatible = "arm,cortex-a9"; | ||
| 39 | reg = <3>; | ||
| 40 | }; | ||
| 41 | }; | ||
| 42 | |||
| 43 | gic: interrupt-controller@f0001000 { | ||
| 44 | compatible = "arm,cortex-a9-gic"; | ||
| 45 | #interrupt-cells = <3>; | ||
| 46 | interrupt-controller; | ||
| 47 | reg = <0xf0001000 0x1000>, | ||
| 48 | <0xf0000100 0x100>; | ||
| 49 | }; | ||
| 50 | |||
| 51 | i2c0: i2c@0xffc70000 { | ||
| 52 | #address-cells = <1>; | ||
| 53 | #size-cells = <0>; | ||
| 54 | compatible = "renesas,rmobile-iic"; | ||
| 55 | reg = <0xffc70000 0x1000>; | ||
| 56 | interrupt-parent = <&gic>; | ||
| 57 | interrupts = <0 79 0x4>; | ||
| 58 | }; | ||
| 59 | |||
| 60 | i2c1: i2c@0xffc71000 { | ||
| 61 | #address-cells = <1>; | ||
| 62 | #size-cells = <0>; | ||
| 63 | compatible = "renesas,rmobile-iic"; | ||
| 64 | reg = <0xffc71000 0x1000>; | ||
| 65 | interrupt-parent = <&gic>; | ||
| 66 | interrupts = <0 82 0x4>; | ||
| 67 | }; | ||
| 68 | |||
| 69 | i2c2: i2c@0xffc72000 { | ||
| 70 | #address-cells = <1>; | ||
| 71 | #size-cells = <0>; | ||
| 72 | compatible = "renesas,rmobile-iic"; | ||
| 73 | reg = <0xffc72000 0x1000>; | ||
| 74 | interrupt-parent = <&gic>; | ||
| 75 | interrupts = <0 80 0x4>; | ||
| 76 | }; | ||
| 77 | |||
| 78 | i2c3: i2c@0xffc73000 { | ||
| 79 | #address-cells = <1>; | ||
| 80 | #size-cells = <0>; | ||
| 81 | compatible = "renesas,rmobile-iic"; | ||
| 82 | reg = <0xffc73000 0x1000>; | ||
| 83 | interrupt-parent = <&gic>; | ||
| 84 | interrupts = <0 81 0x4>; | ||
| 85 | }; | ||
| 86 | |||
| 87 | thermal@ffc48000 { | ||
| 88 | compatible = "renesas,rcar-thermal"; | ||
| 89 | reg = <0xffc48000 0x38>; | ||
| 90 | }; | ||
| 91 | |||
| 92 | sata: sata@fc600000 { | ||
| 93 | compatible = "renesas,rcar-sata"; | ||
| 94 | reg = <0xfc600000 0x2000>; | ||
| 95 | interrupt-parent = <&gic>; | ||
| 96 | interrupts = <0 100 0x4>; | ||
| 97 | }; | ||
| 98 | }; | ||
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 9255546e7bf6..75d413c004b6 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig | |||
| @@ -16,6 +16,7 @@ config ARCH_SH73A0 | |||
| 16 | select CPU_V7 | 16 | select CPU_V7 |
| 17 | select I2C | 17 | select I2C |
| 18 | select SH_CLK_CPG | 18 | select SH_CLK_CPG |
| 19 | select RENESAS_INTC_IRQPIN | ||
| 19 | 20 | ||
| 20 | config ARCH_R8A7740 | 21 | config ARCH_R8A7740 |
| 21 | bool "R-Mobile A1 (R8A77400)" | 22 | bool "R-Mobile A1 (R8A77400)" |
| @@ -31,6 +32,7 @@ config ARCH_R8A7779 | |||
| 31 | select SH_CLK_CPG | 32 | select SH_CLK_CPG |
| 32 | select USB_ARCH_HAS_EHCI | 33 | select USB_ARCH_HAS_EHCI |
| 33 | select USB_ARCH_HAS_OHCI | 34 | select USB_ARCH_HAS_OHCI |
| 35 | select RENESAS_INTC_IRQPIN | ||
| 34 | 36 | ||
| 35 | config ARCH_EMEV2 | 37 | config ARCH_EMEV2 |
| 36 | bool "Emma Mobile EV2" | 38 | bool "Emma Mobile EV2" |
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index e1fac57514b9..b646ff4d742a 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile | |||
| @@ -14,10 +14,9 @@ obj-$(CONFIG_ARCH_EMEV2) += setup-emev2.o clock-emev2.o | |||
| 14 | 14 | ||
| 15 | # SMP objects | 15 | # SMP objects |
| 16 | smp-y := platsmp.o headsmp.o | 16 | smp-y := platsmp.o headsmp.o |
| 17 | smp-$(CONFIG_HOTPLUG_CPU) += hotplug.o | 17 | smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o headsmp-scu.o |
| 18 | smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o headsmp-sh73a0.o | 18 | smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o headsmp-scu.o |
| 19 | smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o | 19 | smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o headsmp-scu.o |
| 20 | smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o | ||
| 21 | 20 | ||
| 22 | # IRQ objects | 21 | # IRQ objects |
| 23 | obj-$(CONFIG_ARCH_SH7372) += entry-intc.o | 22 | obj-$(CONFIG_ARCH_SH7372) += entry-intc.o |
diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c index 7f3a6b7e7b7c..d34d12ae496b 100644 --- a/arch/arm/mach-shmobile/board-kzm9g.c +++ b/arch/arm/mach-shmobile/board-kzm9g.c | |||
| @@ -81,7 +81,7 @@ static struct resource smsc9221_resources[] = { | |||
| 81 | .flags = IORESOURCE_MEM, | 81 | .flags = IORESOURCE_MEM, |
| 82 | }, | 82 | }, |
| 83 | [1] = { | 83 | [1] = { |
| 84 | .start = intcs_evt2irq(0x260), /* IRQ3 */ | 84 | .start = irq_pin(3), /* IRQ3 */ |
| 85 | .flags = IORESOURCE_IRQ, | 85 | .flags = IORESOURCE_IRQ, |
| 86 | }, | 86 | }, |
| 87 | }; | 87 | }; |
| @@ -115,7 +115,7 @@ static struct resource usb_resources[] = { | |||
| 115 | .flags = IORESOURCE_MEM, | 115 | .flags = IORESOURCE_MEM, |
| 116 | }, | 116 | }, |
| 117 | [1] = { | 117 | [1] = { |
| 118 | .start = intcs_evt2irq(0x220), /* IRQ1 */ | 118 | .start = irq_pin(1), /* IRQ1 */ |
| 119 | .flags = IORESOURCE_IRQ, | 119 | .flags = IORESOURCE_IRQ, |
| 120 | }, | 120 | }, |
| 121 | }; | 121 | }; |
| @@ -138,7 +138,7 @@ struct usbhs_private { | |||
| 138 | struct renesas_usbhs_platform_info info; | 138 | struct renesas_usbhs_platform_info info; |
| 139 | }; | 139 | }; |
| 140 | 140 | ||
| 141 | #define IRQ15 intcs_evt2irq(0x03e0) | 141 | #define IRQ15 irq_pin(15) |
| 142 | #define USB_PHY_MODE (1 << 4) | 142 | #define USB_PHY_MODE (1 << 4) |
| 143 | #define USB_PHY_INT_EN ((1 << 3) | (1 << 2)) | 143 | #define USB_PHY_INT_EN ((1 << 3) | (1 << 2)) |
| 144 | #define USB_PHY_ON (1 << 1) | 144 | #define USB_PHY_ON (1 << 1) |
| @@ -563,25 +563,25 @@ static struct i2c_board_info i2c0_devices[] = { | |||
| 563 | }, | 563 | }, |
| 564 | { | 564 | { |
| 565 | I2C_BOARD_INFO("ak8975", 0x0c), | 565 | I2C_BOARD_INFO("ak8975", 0x0c), |
| 566 | .irq = intcs_evt2irq(0x3380), /* IRQ28 */ | 566 | .irq = irq_pin(28), /* IRQ28 */ |
| 567 | }, | 567 | }, |
| 568 | { | 568 | { |
| 569 | I2C_BOARD_INFO("adxl34x", 0x1d), | 569 | I2C_BOARD_INFO("adxl34x", 0x1d), |
| 570 | .irq = intcs_evt2irq(0x3340), /* IRQ26 */ | 570 | .irq = irq_pin(26), /* IRQ26 */ |
| 571 | }, | 571 | }, |
| 572 | }; | 572 | }; |
| 573 | 573 | ||
| 574 | static struct i2c_board_info i2c1_devices[] = { | 574 | static struct i2c_board_info i2c1_devices[] = { |
| 575 | { | 575 | { |
| 576 | I2C_BOARD_INFO("st1232-ts", 0x55), | 576 | I2C_BOARD_INFO("st1232-ts", 0x55), |
| 577 | .irq = intcs_evt2irq(0x300), /* IRQ8 */ | 577 | .irq = irq_pin(8), /* IRQ8 */ |
| 578 | }, | 578 | }, |
| 579 | }; | 579 | }; |
| 580 | 580 | ||
| 581 | static struct i2c_board_info i2c3_devices[] = { | 581 | static struct i2c_board_info i2c3_devices[] = { |
| 582 | { | 582 | { |
| 583 | I2C_BOARD_INFO("pcf8575", 0x20), | 583 | I2C_BOARD_INFO("pcf8575", 0x20), |
| 584 | .irq = intcs_evt2irq(0x3260), /* IRQ19 */ | 584 | .irq = irq_pin(19), /* IRQ19 */ |
| 585 | .platform_data = &pcf8575_pdata, | 585 | .platform_data = &pcf8575_pdata, |
| 586 | }, | 586 | }, |
| 587 | }; | 587 | }; |
diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c index 19ce885a3b43..1feb9a2286a8 100644 --- a/arch/arm/mach-shmobile/clock-r8a7740.c +++ b/arch/arm/mach-shmobile/clock-r8a7740.c | |||
| @@ -593,29 +593,42 @@ static struct clk_lookup lookups[] = { | |||
| 593 | CLKDEV_DEV_ID("sh_mobile_ceu.1", &mstp_clks[MSTP128]), | 593 | CLKDEV_DEV_ID("sh_mobile_ceu.1", &mstp_clks[MSTP128]), |
| 594 | 594 | ||
| 595 | CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), | 595 | CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), |
| 596 | CLKDEV_DEV_ID("e6c80000.sci", &mstp_clks[MSTP200]), | ||
| 596 | CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), | 597 | CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), |
| 598 | CLKDEV_DEV_ID("e6c70000.sci", &mstp_clks[MSTP201]), | ||
| 597 | CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP202]), | 599 | CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP202]), |
| 600 | CLKDEV_DEV_ID("e6c60000.sci", &mstp_clks[MSTP202]), | ||
| 598 | CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]), | 601 | CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]), |
| 602 | CLKDEV_DEV_ID("e6c50000.sci", &mstp_clks[MSTP203]), | ||
| 599 | CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), | 603 | CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), |
| 604 | CLKDEV_DEV_ID("e6c40000.sci", &mstp_clks[MSTP204]), | ||
| 600 | CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP206]), | 605 | CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP206]), |
| 606 | CLKDEV_DEV_ID("e6c30000.sci", &mstp_clks[MSTP206]), | ||
| 601 | CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]), | 607 | CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]), |
| 608 | CLKDEV_DEV_ID("e6cb0000.sci", &mstp_clks[MSTP207]), | ||
| 602 | CLKDEV_DEV_ID("sh-dma-engine.3", &mstp_clks[MSTP214]), | 609 | CLKDEV_DEV_ID("sh-dma-engine.3", &mstp_clks[MSTP214]), |
| 603 | CLKDEV_DEV_ID("sh-dma-engine.2", &mstp_clks[MSTP216]), | 610 | CLKDEV_DEV_ID("sh-dma-engine.2", &mstp_clks[MSTP216]), |
| 604 | CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[MSTP217]), | 611 | CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[MSTP217]), |
| 605 | CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]), | 612 | CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]), |
| 606 | CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP222]), | 613 | CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP222]), |
| 614 | CLKDEV_DEV_ID("e6cd0000.sci", &mstp_clks[MSTP222]), | ||
| 607 | CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP230]), | 615 | CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP230]), |
| 616 | CLKDEV_DEV_ID("e6cc0000.sci", &mstp_clks[MSTP230]), | ||
| 608 | 617 | ||
| 609 | CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), | 618 | CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), |
| 610 | CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), | 619 | CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), |
| 611 | CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), | 620 | CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), |
| 612 | CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP320]), | 621 | CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP320]), |
| 613 | CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), | 622 | CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), |
| 623 | CLKDEV_DEV_ID("e6850000.sdhi", &mstp_clks[MSTP314]), | ||
| 614 | CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), | 624 | CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), |
| 625 | CLKDEV_DEV_ID("e6860000.sdhi", &mstp_clks[MSTP313]), | ||
| 615 | CLKDEV_DEV_ID("sh_mmcif", &mstp_clks[MSTP312]), | 626 | CLKDEV_DEV_ID("sh_mmcif", &mstp_clks[MSTP312]), |
| 627 | CLKDEV_DEV_ID("e6bd0000.mmcif", &mstp_clks[MSTP312]), | ||
| 616 | CLKDEV_DEV_ID("sh-eth", &mstp_clks[MSTP309]), | 628 | CLKDEV_DEV_ID("sh-eth", &mstp_clks[MSTP309]), |
| 617 | 629 | ||
| 618 | CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP415]), | 630 | CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP415]), |
| 631 | CLKDEV_DEV_ID("e6870000.sdhi", &mstp_clks[MSTP415]), | ||
| 619 | 632 | ||
| 620 | /* ICK */ | 633 | /* ICK */ |
| 621 | CLKDEV_ICK_ID("host", "renesas_usbhs", &mstp_clks[MSTP416]), | 634 | CLKDEV_ICK_ID("host", "renesas_usbhs", &mstp_clks[MSTP416]), |
diff --git a/arch/arm/mach-shmobile/clock-r8a7779.c b/arch/arm/mach-shmobile/clock-r8a7779.c index 1db36537255c..d9edeaf66007 100644 --- a/arch/arm/mach-shmobile/clock-r8a7779.c +++ b/arch/arm/mach-shmobile/clock-r8a7779.c | |||
| @@ -87,7 +87,8 @@ static struct clk div4_clks[DIV4_NR] = { | |||
| 87 | }; | 87 | }; |
| 88 | 88 | ||
| 89 | enum { MSTP323, MSTP322, MSTP321, MSTP320, | 89 | enum { MSTP323, MSTP322, MSTP321, MSTP320, |
| 90 | MSTP101, MSTP100, | 90 | MSTP115, |
| 91 | MSTP103, MSTP101, MSTP100, | ||
| 91 | MSTP030, | 92 | MSTP030, |
| 92 | MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021, | 93 | MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021, |
| 93 | MSTP016, MSTP015, MSTP014, | 94 | MSTP016, MSTP015, MSTP014, |
| @@ -99,6 +100,8 @@ static struct clk mstp_clks[MSTP_NR] = { | |||
| 99 | [MSTP322] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 22, 0), /* SDHI1 */ | 100 | [MSTP322] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 22, 0), /* SDHI1 */ |
| 100 | [MSTP321] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 21, 0), /* SDHI2 */ | 101 | [MSTP321] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 21, 0), /* SDHI2 */ |
| 101 | [MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 20, 0), /* SDHI3 */ | 102 | [MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 20, 0), /* SDHI3 */ |
| 103 | [MSTP115] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 15, 0), /* SATA */ | ||
| 104 | [MSTP103] = SH_CLK_MSTP32(&div4_clks[DIV4_S], MSTPCR1, 3, 0), /* DU */ | ||
| 102 | [MSTP101] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 1, 0), /* USB2 */ | 105 | [MSTP101] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 1, 0), /* USB2 */ |
| 103 | [MSTP100] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 0, 0), /* USB0/1 */ | 106 | [MSTP100] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 0, 0), /* USB0/1 */ |
| 104 | [MSTP030] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 30, 0), /* I2C0 */ | 107 | [MSTP030] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 30, 0), /* I2C0 */ |
| @@ -156,6 +159,8 @@ static struct clk_lookup lookups[] = { | |||
| 156 | CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]), | 159 | CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]), |
| 157 | 160 | ||
| 158 | /* MSTP32 clocks */ | 161 | /* MSTP32 clocks */ |
| 162 | CLKDEV_DEV_ID("sata_rcar", &mstp_clks[MSTP115]), /* SATA */ | ||
| 163 | CLKDEV_DEV_ID("fc600000.sata", &mstp_clks[MSTP115]), /* SATA w/DT */ | ||
| 159 | CLKDEV_DEV_ID("ehci-platform.1", &mstp_clks[MSTP101]), /* USB EHCI port2 */ | 164 | CLKDEV_DEV_ID("ehci-platform.1", &mstp_clks[MSTP101]), /* USB EHCI port2 */ |
| 160 | CLKDEV_DEV_ID("ohci-platform.1", &mstp_clks[MSTP101]), /* USB OHCI port2 */ | 165 | CLKDEV_DEV_ID("ohci-platform.1", &mstp_clks[MSTP101]), /* USB OHCI port2 */ |
| 161 | CLKDEV_DEV_ID("ehci-platform.0", &mstp_clks[MSTP100]), /* USB EHCI port0/1 */ | 166 | CLKDEV_DEV_ID("ehci-platform.0", &mstp_clks[MSTP100]), /* USB EHCI port0/1 */ |
| @@ -180,6 +185,7 @@ static struct clk_lookup lookups[] = { | |||
| 180 | CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP322]), /* SDHI1 */ | 185 | CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP322]), /* SDHI1 */ |
| 181 | CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP321]), /* SDHI2 */ | 186 | CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP321]), /* SDHI2 */ |
| 182 | CLKDEV_DEV_ID("sh_mobile_sdhi.3", &mstp_clks[MSTP320]), /* SDHI3 */ | 187 | CLKDEV_DEV_ID("sh_mobile_sdhi.3", &mstp_clks[MSTP320]), /* SDHI3 */ |
| 188 | CLKDEV_DEV_ID("rcar-du.0", &mstp_clks[MSTP103]), /* DU */ | ||
| 183 | }; | 189 | }; |
| 184 | 190 | ||
| 185 | void __init r8a7779_clock_init(void) | 191 | void __init r8a7779_clock_init(void) |
diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c index afa5423a0f93..71843dd39e16 100644 --- a/arch/arm/mach-shmobile/clock-sh73a0.c +++ b/arch/arm/mach-shmobile/clock-sh73a0.c | |||
| @@ -265,12 +265,12 @@ enum { DIV4_I, DIV4_ZG, DIV4_M3, DIV4_B, DIV4_M1, DIV4_M2, | |||
| 265 | 265 | ||
| 266 | static struct clk div4_clks[DIV4_NR] = { | 266 | static struct clk div4_clks[DIV4_NR] = { |
| 267 | [DIV4_I] = DIV4(FRQCRA, 20, 0xdff, CLK_ENABLE_ON_INIT), | 267 | [DIV4_I] = DIV4(FRQCRA, 20, 0xdff, CLK_ENABLE_ON_INIT), |
| 268 | [DIV4_ZG] = DIV4(FRQCRA, 16, 0xd7f, CLK_ENABLE_ON_INIT), | 268 | [DIV4_ZG] = SH_CLK_DIV4(&pll0_clk, FRQCRA, 16, 0xd7f, CLK_ENABLE_ON_INIT), |
| 269 | [DIV4_M3] = DIV4(FRQCRA, 12, 0x1dff, CLK_ENABLE_ON_INIT), | 269 | [DIV4_M3] = DIV4(FRQCRA, 12, 0x1dff, CLK_ENABLE_ON_INIT), |
| 270 | [DIV4_B] = DIV4(FRQCRA, 8, 0xdff, CLK_ENABLE_ON_INIT), | 270 | [DIV4_B] = DIV4(FRQCRA, 8, 0xdff, CLK_ENABLE_ON_INIT), |
| 271 | [DIV4_M1] = DIV4(FRQCRA, 4, 0x1dff, 0), | 271 | [DIV4_M1] = DIV4(FRQCRA, 4, 0x1dff, 0), |
| 272 | [DIV4_M2] = DIV4(FRQCRA, 0, 0x1dff, 0), | 272 | [DIV4_M2] = DIV4(FRQCRA, 0, 0x1dff, 0), |
| 273 | [DIV4_Z] = DIV4(FRQCRB, 24, 0x97f, 0), | 273 | [DIV4_Z] = SH_CLK_DIV4(&pll0_clk, FRQCRB, 24, 0x97f, 0), |
| 274 | [DIV4_ZTR] = DIV4(FRQCRB, 20, 0xdff, 0), | 274 | [DIV4_ZTR] = DIV4(FRQCRB, 20, 0xdff, 0), |
| 275 | [DIV4_ZT] = DIV4(FRQCRB, 16, 0xdff, 0), | 275 | [DIV4_ZT] = DIV4(FRQCRB, 16, 0xdff, 0), |
| 276 | [DIV4_ZX] = DIV4(FRQCRB, 12, 0xdff, 0), | 276 | [DIV4_ZX] = DIV4(FRQCRB, 12, 0xdff, 0), |
| @@ -581,10 +581,13 @@ static struct clk_lookup lookups[] = { | |||
| 581 | CLKDEV_DEV_ID("e6822000.i2c", &mstp_clks[MSTP323]), /* I2C1 */ | 581 | CLKDEV_DEV_ID("e6822000.i2c", &mstp_clks[MSTP323]), /* I2C1 */ |
| 582 | CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP322]), /* USB */ | 582 | CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP322]), /* USB */ |
| 583 | CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */ | 583 | CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */ |
| 584 | CLKDEV_DEV_ID("ee100000.sdhi", &mstp_clks[MSTP314]), /* SDHI0 */ | ||
| 584 | CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */ | 585 | CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */ |
| 586 | CLKDEV_DEV_ID("ee120000.sdhi", &mstp_clks[MSTP313]), /* SDHI1 */ | ||
| 585 | CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMCIF0 */ | 587 | CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMCIF0 */ |
| 586 | CLKDEV_DEV_ID("e6bd0000.mmcif", &mstp_clks[MSTP312]), /* MMCIF0 */ | 588 | CLKDEV_DEV_ID("e6bd0000.mmcif", &mstp_clks[MSTP312]), /* MMCIF0 */ |
| 587 | CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP311]), /* SDHI2 */ | 589 | CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP311]), /* SDHI2 */ |
| 590 | CLKDEV_DEV_ID("ee140000.sdhi", &mstp_clks[MSTP311]), /* SDHI2 */ | ||
| 588 | CLKDEV_DEV_ID("leds-renesas-tpu.12", &mstp_clks[MSTP303]), /* TPU1 */ | 591 | CLKDEV_DEV_ID("leds-renesas-tpu.12", &mstp_clks[MSTP303]), /* TPU1 */ |
| 589 | CLKDEV_DEV_ID("leds-renesas-tpu.21", &mstp_clks[MSTP302]), /* TPU2 */ | 592 | CLKDEV_DEV_ID("leds-renesas-tpu.21", &mstp_clks[MSTP302]), /* TPU2 */ |
| 590 | CLKDEV_DEV_ID("leds-renesas-tpu.30", &mstp_clks[MSTP301]), /* TPU3 */ | 593 | CLKDEV_DEV_ID("leds-renesas-tpu.30", &mstp_clks[MSTP301]), /* TPU3 */ |
diff --git a/arch/arm/mach-shmobile/headsmp-sh73a0.S b/arch/arm/mach-shmobile/headsmp-scu.S index bec4c0d9b713..7d113f898e7f 100644 --- a/arch/arm/mach-shmobile/headsmp-sh73a0.S +++ b/arch/arm/mach-shmobile/headsmp-scu.S | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * SMP support for SoC sh73a0 | 2 | * Shared SCU setup for mach-shmobile |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2012 Bastian Hecht | 4 | * Copyright (C) 2012 Bastian Hecht |
| 5 | * | 5 | * |
| @@ -35,11 +35,12 @@ | |||
| 35 | * the physical address as the MMU is still turned off. | 35 | * the physical address as the MMU is still turned off. |
| 36 | */ | 36 | */ |
| 37 | .align 12 | 37 | .align 12 |
| 38 | ENTRY(sh73a0_secondary_vector) | 38 | ENTRY(shmobile_secondary_vector_scu) |
| 39 | mrc p15, 0, r0, c0, c0, 5 @ read MIPDR | 39 | mrc p15, 0, r0, c0, c0, 5 @ read MIPDR |
| 40 | and r0, r0, #3 @ mask out cpu ID | 40 | and r0, r0, #3 @ mask out cpu ID |
| 41 | lsl r0, r0, #3 @ we will shift by cpu_id * 8 bits | 41 | lsl r0, r0, #3 @ we will shift by cpu_id * 8 bits |
| 42 | mov r1, #0xf0000000 @ SCU base address | 42 | ldr r1, 2f |
| 43 | ldr r1, [r1] @ SCU base address | ||
| 43 | ldr r2, [r1, #8] @ SCU Power Status Register | 44 | ldr r2, [r1, #8] @ SCU Power Status Register |
| 44 | mov r3, #3 | 45 | mov r3, #3 |
| 45 | bic r2, r2, r3, lsl r0 @ Clear bits of our CPU (Run Mode) | 46 | bic r2, r2, r3, lsl r0 @ Clear bits of our CPU (Run Mode) |
| @@ -47,4 +48,10 @@ ENTRY(sh73a0_secondary_vector) | |||
| 47 | 48 | ||
| 48 | ldr pc, 1f | 49 | ldr pc, 1f |
| 49 | 1: .long shmobile_invalidate_start - PAGE_OFFSET + PLAT_PHYS_OFFSET | 50 | 1: .long shmobile_invalidate_start - PAGE_OFFSET + PLAT_PHYS_OFFSET |
| 50 | ENDPROC(sh73a0_secondary_vector) | 51 | 2: .long shmobile_scu_base - PAGE_OFFSET + PLAT_PHYS_OFFSET |
| 52 | ENDPROC(shmobile_secondary_vector_scu) | ||
| 53 | |||
| 54 | .text | ||
| 55 | .globl shmobile_scu_base | ||
| 56 | shmobile_scu_base: | ||
| 57 | .space 4 | ||
diff --git a/arch/arm/mach-shmobile/hotplug.c b/arch/arm/mach-shmobile/hotplug.c deleted file mode 100644 index a1524e3367b0..000000000000 --- a/arch/arm/mach-shmobile/hotplug.c +++ /dev/null | |||
| @@ -1,68 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * SMP support for R-Mobile / SH-Mobile | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Magnus Damm | ||
| 5 | * | ||
| 6 | * Based on realview, Copyright (C) 2002 ARM Ltd, All Rights Reserved | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/errno.h> | ||
| 14 | #include <linux/smp.h> | ||
| 15 | #include <linux/cpumask.h> | ||
| 16 | #include <linux/delay.h> | ||
| 17 | #include <linux/of.h> | ||
| 18 | #include <mach/common.h> | ||
| 19 | #include <mach/r8a7779.h> | ||
| 20 | #include <mach/emev2.h> | ||
| 21 | #include <asm/cacheflush.h> | ||
| 22 | #include <asm/mach-types.h> | ||
| 23 | |||
| 24 | static cpumask_t dead_cpus; | ||
| 25 | |||
| 26 | void shmobile_cpu_die(unsigned int cpu) | ||
| 27 | { | ||
| 28 | /* hardware shutdown code running on the CPU that is being offlined */ | ||
| 29 | flush_cache_all(); | ||
| 30 | dsb(); | ||
| 31 | |||
| 32 | /* notify platform_cpu_kill() that hardware shutdown is finished */ | ||
| 33 | cpumask_set_cpu(cpu, &dead_cpus); | ||
| 34 | |||
| 35 | /* wait for SoC code in platform_cpu_kill() to shut off CPU core | ||
| 36 | * power. CPU bring up starts from the reset vector. | ||
| 37 | */ | ||
| 38 | while (1) { | ||
| 39 | /* | ||
| 40 | * here's the WFI | ||
| 41 | */ | ||
| 42 | asm(".word 0xe320f003\n" | ||
| 43 | : | ||
| 44 | : | ||
| 45 | : "memory", "cc"); | ||
| 46 | } | ||
| 47 | } | ||
| 48 | |||
| 49 | int shmobile_cpu_disable(unsigned int cpu) | ||
| 50 | { | ||
| 51 | cpumask_clear_cpu(cpu, &dead_cpus); | ||
| 52 | /* | ||
| 53 | * we don't allow CPU 0 to be shutdown (it is still too special | ||
| 54 | * e.g. clock tick interrupts) | ||
| 55 | */ | ||
| 56 | return cpu == 0 ? -EPERM : 0; | ||
| 57 | } | ||
| 58 | |||
| 59 | int shmobile_cpu_disable_any(unsigned int cpu) | ||
| 60 | { | ||
| 61 | cpumask_clear_cpu(cpu, &dead_cpus); | ||
| 62 | return 0; | ||
| 63 | } | ||
| 64 | |||
| 65 | int shmobile_cpu_is_dead(unsigned int cpu) | ||
| 66 | { | ||
| 67 | return cpumask_test_cpu(cpu, &dead_cpus); | ||
| 68 | } | ||
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h index e48606d8a2be..03f73def2fc6 100644 --- a/arch/arm/mach-shmobile/include/mach/common.h +++ b/arch/arm/mach-shmobile/include/mach/common.h | |||
| @@ -8,6 +8,7 @@ extern void shmobile_setup_delay(unsigned int max_cpu_core_mhz, | |||
| 8 | struct twd_local_timer; | 8 | struct twd_local_timer; |
| 9 | extern void shmobile_setup_console(void); | 9 | extern void shmobile_setup_console(void); |
| 10 | extern void shmobile_secondary_vector(void); | 10 | extern void shmobile_secondary_vector(void); |
| 11 | extern void shmobile_secondary_vector_scu(void); | ||
| 11 | struct clk; | 12 | struct clk; |
| 12 | extern int shmobile_clk_init(void); | 13 | extern int shmobile_clk_init(void); |
| 13 | extern void shmobile_handle_irq_intc(struct pt_regs *); | 14 | extern void shmobile_handle_irq_intc(struct pt_regs *); |
| @@ -33,23 +34,23 @@ extern int sh7372_do_idle_sysc(unsigned long sleep_mode); | |||
| 33 | extern struct clk sh7372_extal1_clk; | 34 | extern struct clk sh7372_extal1_clk; |
| 34 | extern struct clk sh7372_extal2_clk; | 35 | extern struct clk sh7372_extal2_clk; |
| 35 | 36 | ||
| 37 | extern void sh73a0_init_delay(void); | ||
| 36 | extern void sh73a0_init_irq(void); | 38 | extern void sh73a0_init_irq(void); |
| 37 | extern void sh73a0_init_irq_dt(void); | 39 | extern void sh73a0_init_irq_dt(void); |
| 38 | extern void sh73a0_map_io(void); | 40 | extern void sh73a0_map_io(void); |
| 39 | extern void sh73a0_earlytimer_init(void); | 41 | extern void sh73a0_earlytimer_init(void); |
| 40 | extern void sh73a0_add_early_devices(void); | 42 | extern void sh73a0_add_early_devices(void); |
| 41 | extern void sh73a0_add_early_devices_dt(void); | ||
| 42 | extern void sh73a0_add_standard_devices(void); | 43 | extern void sh73a0_add_standard_devices(void); |
| 43 | extern void sh73a0_add_standard_devices_dt(void); | 44 | extern void sh73a0_add_standard_devices_dt(void); |
| 44 | extern void sh73a0_clock_init(void); | 45 | extern void sh73a0_clock_init(void); |
| 45 | extern void sh73a0_pinmux_init(void); | 46 | extern void sh73a0_pinmux_init(void); |
| 46 | extern void sh73a0_pm_init(void); | 47 | extern void sh73a0_pm_init(void); |
| 47 | extern void sh73a0_secondary_vector(void); | ||
| 48 | extern struct clk sh73a0_extal1_clk; | 48 | extern struct clk sh73a0_extal1_clk; |
| 49 | extern struct clk sh73a0_extal2_clk; | 49 | extern struct clk sh73a0_extal2_clk; |
| 50 | extern struct clk sh73a0_extcki_clk; | 50 | extern struct clk sh73a0_extcki_clk; |
| 51 | extern struct clk sh73a0_extalr_clk; | 51 | extern struct clk sh73a0_extalr_clk; |
| 52 | 52 | ||
| 53 | extern void r8a7740_meram_workaround(void); | ||
| 53 | extern void r8a7740_init_irq(void); | 54 | extern void r8a7740_init_irq(void); |
| 54 | extern void r8a7740_map_io(void); | 55 | extern void r8a7740_map_io(void); |
| 55 | extern void r8a7740_add_early_devices(void); | 56 | extern void r8a7740_add_early_devices(void); |
| @@ -58,16 +59,18 @@ extern void r8a7740_clock_init(u8 md_ck); | |||
| 58 | extern void r8a7740_pinmux_init(void); | 59 | extern void r8a7740_pinmux_init(void); |
| 59 | extern void r8a7740_pm_init(void); | 60 | extern void r8a7740_pm_init(void); |
| 60 | 61 | ||
| 62 | extern void r8a7779_init_delay(void); | ||
| 61 | extern void r8a7779_init_irq(void); | 63 | extern void r8a7779_init_irq(void); |
| 64 | extern void r8a7779_init_irq_extpin(int irlm); | ||
| 65 | extern void r8a7779_init_irq_dt(void); | ||
| 62 | extern void r8a7779_map_io(void); | 66 | extern void r8a7779_map_io(void); |
| 63 | extern void r8a7779_earlytimer_init(void); | 67 | extern void r8a7779_earlytimer_init(void); |
| 64 | extern void r8a7779_add_early_devices(void); | 68 | extern void r8a7779_add_early_devices(void); |
| 65 | extern void r8a7779_add_standard_devices(void); | 69 | extern void r8a7779_add_standard_devices(void); |
| 70 | extern void r8a7779_add_standard_devices_dt(void); | ||
| 66 | extern void r8a7779_clock_init(void); | 71 | extern void r8a7779_clock_init(void); |
| 67 | extern void r8a7779_pinmux_init(void); | 72 | extern void r8a7779_pinmux_init(void); |
| 68 | extern void r8a7779_pm_init(void); | 73 | extern void r8a7779_pm_init(void); |
| 69 | extern void r8a7740_meram_workaround(void); | ||
| 70 | |||
| 71 | extern void r8a7779_register_twd(void); | 74 | extern void r8a7779_register_twd(void); |
| 72 | 75 | ||
| 73 | #ifdef CONFIG_SUSPEND | 76 | #ifdef CONFIG_SUSPEND |
| @@ -82,16 +85,7 @@ int shmobile_cpuidle_init(void); | |||
| 82 | static inline int shmobile_cpuidle_init(void) { return 0; } | 85 | static inline int shmobile_cpuidle_init(void) { return 0; } |
| 83 | #endif | 86 | #endif |
| 84 | 87 | ||
| 85 | extern void shmobile_cpu_die(unsigned int cpu); | 88 | extern void __iomem *shmobile_scu_base; |
| 86 | extern int shmobile_cpu_disable(unsigned int cpu); | ||
| 87 | extern int shmobile_cpu_disable_any(unsigned int cpu); | ||
| 88 | |||
| 89 | #ifdef CONFIG_HOTPLUG_CPU | ||
| 90 | extern int shmobile_cpu_is_dead(unsigned int cpu); | ||
| 91 | #else | ||
| 92 | static inline int shmobile_cpu_is_dead(unsigned int cpu) { return 1; } | ||
| 93 | #endif | ||
| 94 | |||
| 95 | extern void shmobile_smp_init_cpus(unsigned int ncores); | 89 | extern void shmobile_smp_init_cpus(unsigned int ncores); |
| 96 | 90 | ||
| 97 | static inline void __init shmobile_init_late(void) | 91 | static inline void __init shmobile_init_late(void) |
diff --git a/arch/arm/mach-shmobile/include/mach/irqs.h b/arch/arm/mach-shmobile/include/mach/irqs.h index 06a5da3c3050..b2074e2acb15 100644 --- a/arch/arm/mach-shmobile/include/mach/irqs.h +++ b/arch/arm/mach-shmobile/include/mach/irqs.h | |||
| @@ -5,10 +5,15 @@ | |||
| 5 | 5 | ||
| 6 | /* GIC */ | 6 | /* GIC */ |
| 7 | #define gic_spi(nr) ((nr) + 32) | 7 | #define gic_spi(nr) ((nr) + 32) |
| 8 | #define gic_iid(nr) (nr) /* ICCIAR / interrupt ID */ | ||
| 8 | 9 | ||
| 9 | /* INTCS */ | 10 | /* INTCS */ |
| 10 | #define INTCS_VECT_BASE 0x3400 | 11 | #define INTCS_VECT_BASE 0x3400 |
| 11 | #define INTCS_VECT(n, vect) INTC_VECT((n), INTCS_VECT_BASE + (vect)) | 12 | #define INTCS_VECT(n, vect) INTC_VECT((n), INTCS_VECT_BASE + (vect)) |
| 12 | #define intcs_evt2irq(evt) evt2irq(INTCS_VECT_BASE + (evt)) | 13 | #define intcs_evt2irq(evt) evt2irq(INTCS_VECT_BASE + (evt)) |
| 13 | 14 | ||
| 15 | /* External IRQ pins */ | ||
| 16 | #define IRQPIN_BASE 2000 | ||
| 17 | #define irq_pin(nr) ((nr) + IRQPIN_BASE) | ||
| 18 | |||
| 14 | #endif /* __ASM_MACH_IRQS_H */ | 19 | #endif /* __ASM_MACH_IRQS_H */ |
diff --git a/arch/arm/mach-shmobile/intc-r8a7779.c b/arch/arm/mach-shmobile/intc-r8a7779.c index 8807c27f71f9..b86dc8908724 100644 --- a/arch/arm/mach-shmobile/intc-r8a7779.c +++ b/arch/arm/mach-shmobile/intc-r8a7779.c | |||
| @@ -19,12 +19,16 @@ | |||
| 19 | */ | 19 | */ |
| 20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
| 21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
| 22 | #include <linux/platform_device.h> | ||
| 22 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
| 23 | #include <linux/irq.h> | 24 | #include <linux/irq.h> |
| 24 | #include <linux/io.h> | 25 | #include <linux/io.h> |
| 25 | #include <linux/irqchip/arm-gic.h> | 26 | #include <linux/irqchip/arm-gic.h> |
| 27 | #include <linux/platform_data/irq-renesas-intc-irqpin.h> | ||
| 28 | #include <linux/irqchip.h> | ||
| 26 | #include <mach/common.h> | 29 | #include <mach/common.h> |
| 27 | #include <mach/intc.h> | 30 | #include <mach/intc.h> |
| 31 | #include <mach/irqs.h> | ||
| 28 | #include <mach/r8a7779.h> | 32 | #include <mach/r8a7779.h> |
| 29 | #include <asm/mach-types.h> | 33 | #include <asm/mach-types.h> |
| 30 | #include <asm/mach/arch.h> | 34 | #include <asm/mach/arch.h> |
| @@ -38,18 +42,61 @@ | |||
| 38 | #define INT2NTSR0 IOMEM(0xfe700060) | 42 | #define INT2NTSR0 IOMEM(0xfe700060) |
| 39 | #define INT2NTSR1 IOMEM(0xfe700064) | 43 | #define INT2NTSR1 IOMEM(0xfe700064) |
| 40 | 44 | ||
| 45 | static struct renesas_intc_irqpin_config irqpin0_platform_data = { | ||
| 46 | .irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */ | ||
| 47 | .sense_bitfield_width = 2, | ||
| 48 | }; | ||
| 49 | |||
| 50 | static struct resource irqpin0_resources[] = { | ||
| 51 | DEFINE_RES_MEM(0xfe78001c, 4), /* ICR1 */ | ||
| 52 | DEFINE_RES_MEM(0xfe780010, 4), /* INTPRI */ | ||
| 53 | DEFINE_RES_MEM(0xfe780024, 4), /* INTREQ */ | ||
| 54 | DEFINE_RES_MEM(0xfe780044, 4), /* INTMSK0 */ | ||
| 55 | DEFINE_RES_MEM(0xfe780064, 4), /* INTMSKCLR0 */ | ||
| 56 | DEFINE_RES_IRQ(gic_spi(27)), /* IRQ0 */ | ||
| 57 | DEFINE_RES_IRQ(gic_spi(28)), /* IRQ1 */ | ||
| 58 | DEFINE_RES_IRQ(gic_spi(29)), /* IRQ2 */ | ||
| 59 | DEFINE_RES_IRQ(gic_spi(30)), /* IRQ3 */ | ||
| 60 | }; | ||
| 61 | |||
| 62 | static struct platform_device irqpin0_device = { | ||
| 63 | .name = "renesas_intc_irqpin", | ||
| 64 | .id = 0, | ||
| 65 | .resource = irqpin0_resources, | ||
| 66 | .num_resources = ARRAY_SIZE(irqpin0_resources), | ||
| 67 | .dev = { | ||
| 68 | .platform_data = &irqpin0_platform_data, | ||
| 69 | }, | ||
| 70 | }; | ||
| 71 | |||
| 72 | void __init r8a7779_init_irq_extpin(int irlm) | ||
| 73 | { | ||
| 74 | void __iomem *icr0 = ioremap_nocache(0xfe780000, PAGE_SIZE); | ||
| 75 | unsigned long tmp; | ||
| 76 | |||
| 77 | if (icr0) { | ||
| 78 | tmp = ioread32(icr0); | ||
| 79 | if (irlm) | ||
| 80 | tmp |= 1 << 23; /* IRQ0 -> IRQ3 as individual pins */ | ||
| 81 | else | ||
| 82 | tmp &= ~(1 << 23); /* IRL mode - not supported */ | ||
| 83 | tmp |= (1 << 21); /* LVLMODE = 1 */ | ||
| 84 | iowrite32(tmp, icr0); | ||
| 85 | iounmap(icr0); | ||
| 86 | |||
| 87 | if (irlm) | ||
| 88 | platform_device_register(&irqpin0_device); | ||
| 89 | } else | ||
| 90 | pr_warn("r8a7779: unable to setup external irq pin mode\n"); | ||
| 91 | } | ||
| 92 | |||
| 41 | static int r8a7779_set_wake(struct irq_data *data, unsigned int on) | 93 | static int r8a7779_set_wake(struct irq_data *data, unsigned int on) |
| 42 | { | 94 | { |
| 43 | return 0; /* always allow wakeup */ | 95 | return 0; /* always allow wakeup */ |
| 44 | } | 96 | } |
| 45 | 97 | ||
| 46 | void __init r8a7779_init_irq(void) | 98 | static void __init r8a7779_init_irq_common(void) |
| 47 | { | 99 | { |
| 48 | void __iomem *gic_dist_base = IOMEM(0xf0001000); | ||
| 49 | void __iomem *gic_cpu_base = IOMEM(0xf0000100); | ||
| 50 | |||
| 51 | /* use GIC to handle interrupts */ | ||
| 52 | gic_init(0, 29, gic_dist_base, gic_cpu_base); | ||
| 53 | gic_arch_extn.irq_set_wake = r8a7779_set_wake; | 100 | gic_arch_extn.irq_set_wake = r8a7779_set_wake; |
| 54 | 101 | ||
| 55 | /* route all interrupts to ARM */ | 102 | /* route all interrupts to ARM */ |
| @@ -63,3 +110,22 @@ void __init r8a7779_init_irq(void) | |||
| 63 | __raw_writel(0xbffffffc, INT2SMSKCR3); | 110 | __raw_writel(0xbffffffc, INT2SMSKCR3); |
| 64 | __raw_writel(0x003fee3f, INT2SMSKCR4); | 111 | __raw_writel(0x003fee3f, INT2SMSKCR4); |
| 65 | } | 112 | } |
| 113 | |||
| 114 | void __init r8a7779_init_irq(void) | ||
| 115 | { | ||
| 116 | void __iomem *gic_dist_base = IOMEM(0xf0001000); | ||
| 117 | void __iomem *gic_cpu_base = IOMEM(0xf0000100); | ||
| 118 | |||
| 119 | /* use GIC to handle interrupts */ | ||
| 120 | gic_init(0, 29, gic_dist_base, gic_cpu_base); | ||
| 121 | |||
| 122 | r8a7779_init_irq_common(); | ||
| 123 | } | ||
| 124 | |||
| 125 | #ifdef CONFIG_OF | ||
| 126 | void __init r8a7779_init_irq_dt(void) | ||
| 127 | { | ||
| 128 | irqchip_init(); | ||
| 129 | r8a7779_init_irq_common(); | ||
| 130 | } | ||
| 131 | #endif | ||
diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c index 91faba666d46..19a26f4579b3 100644 --- a/arch/arm/mach-shmobile/intc-sh73a0.c +++ b/arch/arm/mach-shmobile/intc-sh73a0.c | |||
| @@ -260,108 +260,6 @@ static int sh73a0_set_wake(struct irq_data *data, unsigned int on) | |||
| 260 | return 0; /* always allow wakeup */ | 260 | return 0; /* always allow wakeup */ |
| 261 | } | 261 | } |
| 262 | 262 | ||
| 263 | #define RELOC_BASE 0x1200 | ||
| 264 | |||
| 265 | /* INTCA IRQ pins at INTCS + RELOC_BASE to make space for GIC+INTC handling */ | ||
| 266 | #define INTCS_VECT_RELOC(n, vect) INTCS_VECT((n), (vect) + RELOC_BASE) | ||
| 267 | |||
| 268 | INTC_IRQ_PINS_32(intca_irq_pins, 0xe6900000, | ||
| 269 | INTCS_VECT_RELOC, "sh73a0-intca-irq-pins"); | ||
| 270 | |||
| 271 | static int to_gic_irq(struct irq_data *data) | ||
| 272 | { | ||
| 273 | unsigned int vect = irq2evt(data->irq) - INTCS_VECT_BASE; | ||
| 274 | |||
| 275 | if (vect >= 0x3200) | ||
| 276 | vect -= 0x3000; | ||
| 277 | else | ||
| 278 | vect -= 0x0200; | ||
| 279 | |||
| 280 | return gic_spi((vect >> 5) + 1); | ||
| 281 | } | ||
| 282 | |||
| 283 | static int to_intca_reloc_irq(struct irq_data *data) | ||
| 284 | { | ||
| 285 | return data->irq + (RELOC_BASE >> 5); | ||
| 286 | } | ||
| 287 | |||
| 288 | #define irq_cb(cb, irq) irq_get_chip(irq)->cb(irq_get_irq_data(irq)) | ||
| 289 | #define irq_cbp(cb, irq, p...) irq_get_chip(irq)->cb(irq_get_irq_data(irq), p) | ||
| 290 | |||
| 291 | static void intca_gic_enable(struct irq_data *data) | ||
| 292 | { | ||
| 293 | irq_cb(irq_unmask, to_intca_reloc_irq(data)); | ||
| 294 | irq_cb(irq_unmask, to_gic_irq(data)); | ||
| 295 | } | ||
| 296 | |||
| 297 | static void intca_gic_disable(struct irq_data *data) | ||
| 298 | { | ||
| 299 | irq_cb(irq_mask, to_gic_irq(data)); | ||
| 300 | irq_cb(irq_mask, to_intca_reloc_irq(data)); | ||
| 301 | } | ||
| 302 | |||
| 303 | static void intca_gic_mask_ack(struct irq_data *data) | ||
| 304 | { | ||
| 305 | irq_cb(irq_mask, to_gic_irq(data)); | ||
| 306 | irq_cb(irq_mask_ack, to_intca_reloc_irq(data)); | ||
| 307 | } | ||
| 308 | |||
| 309 | static void intca_gic_eoi(struct irq_data *data) | ||
| 310 | { | ||
| 311 | irq_cb(irq_eoi, to_gic_irq(data)); | ||
| 312 | } | ||
| 313 | |||
| 314 | static int intca_gic_set_type(struct irq_data *data, unsigned int type) | ||
| 315 | { | ||
| 316 | return irq_cbp(irq_set_type, to_intca_reloc_irq(data), type); | ||
| 317 | } | ||
| 318 | |||
| 319 | #ifdef CONFIG_SMP | ||
| 320 | static int intca_gic_set_affinity(struct irq_data *data, | ||
| 321 | const struct cpumask *cpumask, | ||
| 322 | bool force) | ||
| 323 | { | ||
| 324 | return irq_cbp(irq_set_affinity, to_gic_irq(data), cpumask, force); | ||
| 325 | } | ||
| 326 | #endif | ||
| 327 | |||
| 328 | struct irq_chip intca_gic_irq_chip = { | ||
| 329 | .name = "INTCA-GIC", | ||
| 330 | .irq_mask = intca_gic_disable, | ||
| 331 | .irq_unmask = intca_gic_enable, | ||
| 332 | .irq_mask_ack = intca_gic_mask_ack, | ||
| 333 | .irq_eoi = intca_gic_eoi, | ||
| 334 | .irq_enable = intca_gic_enable, | ||
| 335 | .irq_disable = intca_gic_disable, | ||
| 336 | .irq_shutdown = intca_gic_disable, | ||
| 337 | .irq_set_type = intca_gic_set_type, | ||
| 338 | .irq_set_wake = sh73a0_set_wake, | ||
| 339 | #ifdef CONFIG_SMP | ||
| 340 | .irq_set_affinity = intca_gic_set_affinity, | ||
| 341 | #endif | ||
| 342 | }; | ||
| 343 | |||
| 344 | static int to_intc_vect(int irq) | ||
| 345 | { | ||
| 346 | unsigned int irq_pin = irq - gic_spi(1); | ||
| 347 | unsigned int offs; | ||
| 348 | |||
| 349 | if (irq_pin < 16) | ||
| 350 | offs = 0x0200; | ||
| 351 | else | ||
| 352 | offs = 0x3000; | ||
| 353 | |||
| 354 | return offs + (irq_pin << 5); | ||
| 355 | } | ||
| 356 | |||
| 357 | static irqreturn_t sh73a0_irq_pin_demux(int irq, void *dev_id) | ||
| 358 | { | ||
| 359 | generic_handle_irq(intcs_evt2irq(to_intc_vect(irq))); | ||
| 360 | return IRQ_HANDLED; | ||
| 361 | } | ||
| 362 | |||
| 363 | static struct irqaction sh73a0_irq_pin_cascade[32]; | ||
| 364 | |||
| 365 | #define PINTER0_PHYS 0xe69000a0 | 263 | #define PINTER0_PHYS 0xe69000a0 |
| 366 | #define PINTER1_PHYS 0xe69000a4 | 264 | #define PINTER1_PHYS 0xe69000a4 |
| 367 | #define PINTER0_VIRT IOMEM(0xe69000a0) | 265 | #define PINTER0_VIRT IOMEM(0xe69000a0) |
| @@ -422,13 +320,11 @@ void __init sh73a0_init_irq(void) | |||
| 422 | void __iomem *gic_dist_base = IOMEM(0xf0001000); | 320 | void __iomem *gic_dist_base = IOMEM(0xf0001000); |
| 423 | void __iomem *gic_cpu_base = IOMEM(0xf0000100); | 321 | void __iomem *gic_cpu_base = IOMEM(0xf0000100); |
| 424 | void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE); | 322 | void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE); |
| 425 | int k, n; | ||
| 426 | 323 | ||
| 427 | gic_init(0, 29, gic_dist_base, gic_cpu_base); | 324 | gic_init(0, 29, gic_dist_base, gic_cpu_base); |
| 428 | gic_arch_extn.irq_set_wake = sh73a0_set_wake; | 325 | gic_arch_extn.irq_set_wake = sh73a0_set_wake; |
| 429 | 326 | ||
| 430 | register_intc_controller(&intcs_desc); | 327 | register_intc_controller(&intcs_desc); |
| 431 | register_intc_controller(&intca_irq_pins_desc); | ||
| 432 | register_intc_controller(&intc_pint0_desc); | 328 | register_intc_controller(&intc_pint0_desc); |
| 433 | register_intc_controller(&intc_pint1_desc); | 329 | register_intc_controller(&intc_pint1_desc); |
| 434 | 330 | ||
| @@ -438,19 +334,6 @@ void __init sh73a0_init_irq(void) | |||
| 438 | sh73a0_intcs_cascade.dev_id = intevtsa; | 334 | sh73a0_intcs_cascade.dev_id = intevtsa; |
| 439 | setup_irq(gic_spi(50), &sh73a0_intcs_cascade); | 335 | setup_irq(gic_spi(50), &sh73a0_intcs_cascade); |
| 440 | 336 | ||
| 441 | /* IRQ pins require special handling through INTCA and GIC */ | ||
| 442 | for (k = 0; k < 32; k++) { | ||
| 443 | sh73a0_irq_pin_cascade[k].name = "INTCA-GIC cascade"; | ||
| 444 | sh73a0_irq_pin_cascade[k].handler = sh73a0_irq_pin_demux; | ||
| 445 | setup_irq(gic_spi(1 + k), &sh73a0_irq_pin_cascade[k]); | ||
| 446 | |||
| 447 | n = intcs_evt2irq(to_intc_vect(gic_spi(1 + k))); | ||
| 448 | WARN_ON(irq_alloc_desc_at(n, numa_node_id()) != n); | ||
| 449 | irq_set_chip_and_handler_name(n, &intca_gic_irq_chip, | ||
| 450 | handle_level_irq, "level"); | ||
| 451 | set_irq_flags(n, IRQF_VALID); /* yuck */ | ||
| 452 | } | ||
| 453 | |||
| 454 | /* PINT pins are sanely tied to the GIC as SPI */ | 337 | /* PINT pins are sanely tied to the GIC as SPI */ |
| 455 | sh73a0_pint0_cascade.name = "PINT0 cascade"; | 338 | sh73a0_pint0_cascade.name = "PINT0 cascade"; |
| 456 | sh73a0_pint0_cascade.handler = sh73a0_pint0_demux; | 339 | sh73a0_pint0_cascade.handler = sh73a0_pint0_demux; |
| @@ -460,11 +343,3 @@ void __init sh73a0_init_irq(void) | |||
| 460 | sh73a0_pint1_cascade.handler = sh73a0_pint1_demux; | 343 | sh73a0_pint1_cascade.handler = sh73a0_pint1_demux; |
| 461 | setup_irq(gic_spi(34), &sh73a0_pint1_cascade); | 344 | setup_irq(gic_spi(34), &sh73a0_pint1_cascade); |
| 462 | } | 345 | } |
| 463 | |||
| 464 | #ifdef CONFIG_OF | ||
| 465 | void __init sh73a0_init_irq_dt(void) | ||
| 466 | { | ||
| 467 | irqchip_init(); | ||
| 468 | gic_arch_extn.irq_set_wake = sh73a0_set_wake; | ||
| 469 | } | ||
| 470 | #endif | ||
diff --git a/arch/arm/mach-shmobile/setup-emev2.c b/arch/arm/mach-shmobile/setup-emev2.c index 47662a581c0a..e4545c152722 100644 --- a/arch/arm/mach-shmobile/setup-emev2.c +++ b/arch/arm/mach-shmobile/setup-emev2.c | |||
| @@ -404,7 +404,7 @@ void __init emev2_add_standard_devices(void) | |||
| 404 | ARRAY_SIZE(emev2_late_devices)); | 404 | ARRAY_SIZE(emev2_late_devices)); |
| 405 | } | 405 | } |
| 406 | 406 | ||
| 407 | void __init emev2_init_delay(void) | 407 | static void __init emev2_init_delay(void) |
| 408 | { | 408 | { |
| 409 | shmobile_setup_delay(533, 1, 3); /* Cortex-A9 @ 533MHz */ | 409 | shmobile_setup_delay(533, 1, 3); /* Cortex-A9 @ 533MHz */ |
| 410 | } | 410 | } |
| @@ -439,7 +439,7 @@ static const struct of_dev_auxdata emev2_auxdata_lookup[] __initconst = { | |||
| 439 | { } | 439 | { } |
| 440 | }; | 440 | }; |
| 441 | 441 | ||
| 442 | void __init emev2_add_standard_devices_dt(void) | 442 | static void __init emev2_add_standard_devices_dt(void) |
| 443 | { | 443 | { |
| 444 | of_platform_populate(NULL, of_default_bus_match_table, | 444 | of_platform_populate(NULL, of_default_bus_match_table, |
| 445 | emev2_auxdata_lookup, NULL); | 445 | emev2_auxdata_lookup, NULL); |
diff --git a/arch/arm/mach-shmobile/setup-r8a7779.c b/arch/arm/mach-shmobile/setup-r8a7779.c index c54ff9b29fe5..042df35e71a0 100644 --- a/arch/arm/mach-shmobile/setup-r8a7779.c +++ b/arch/arm/mach-shmobile/setup-r8a7779.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
| 22 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
| 23 | #include <linux/irq.h> | 23 | #include <linux/irq.h> |
| 24 | #include <linux/of_platform.h> | ||
| 24 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
| 25 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
| 26 | #include <linux/input.h> | 27 | #include <linux/input.h> |
| @@ -28,6 +29,7 @@ | |||
| 28 | #include <linux/serial_sci.h> | 29 | #include <linux/serial_sci.h> |
| 29 | #include <linux/sh_intc.h> | 30 | #include <linux/sh_intc.h> |
| 30 | #include <linux/sh_timer.h> | 31 | #include <linux/sh_timer.h> |
| 32 | #include <linux/dma-mapping.h> | ||
| 31 | #include <mach/hardware.h> | 33 | #include <mach/hardware.h> |
| 32 | #include <mach/irqs.h> | 34 | #include <mach/irqs.h> |
| 33 | #include <mach/r8a7779.h> | 35 | #include <mach/r8a7779.h> |
| @@ -91,7 +93,7 @@ static struct plat_sci_port scif0_platform_data = { | |||
| 91 | .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1, | 93 | .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1, |
| 92 | .scbrr_algo_id = SCBRR_ALGO_2, | 94 | .scbrr_algo_id = SCBRR_ALGO_2, |
| 93 | .type = PORT_SCIF, | 95 | .type = PORT_SCIF, |
| 94 | .irqs = SCIx_IRQ_MUXED(gic_spi(88)), | 96 | .irqs = SCIx_IRQ_MUXED(gic_iid(0x78)), |
| 95 | }; | 97 | }; |
| 96 | 98 | ||
| 97 | static struct platform_device scif0_device = { | 99 | static struct platform_device scif0_device = { |
| @@ -108,7 +110,7 @@ static struct plat_sci_port scif1_platform_data = { | |||
| 108 | .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1, | 110 | .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1, |
| 109 | .scbrr_algo_id = SCBRR_ALGO_2, | 111 | .scbrr_algo_id = SCBRR_ALGO_2, |
| 110 | .type = PORT_SCIF, | 112 | .type = PORT_SCIF, |
| 111 | .irqs = SCIx_IRQ_MUXED(gic_spi(89)), | 113 | .irqs = SCIx_IRQ_MUXED(gic_iid(0x79)), |
| 112 | }; | 114 | }; |
| 113 | 115 | ||
| 114 | static struct platform_device scif1_device = { | 116 | static struct platform_device scif1_device = { |
| @@ -125,7 +127,7 @@ static struct plat_sci_port scif2_platform_data = { | |||
| 125 | .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1, | 127 | .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1, |
| 126 | .scbrr_algo_id = SCBRR_ALGO_2, | 128 | .scbrr_algo_id = SCBRR_ALGO_2, |
| 127 | .type = PORT_SCIF, | 129 | .type = PORT_SCIF, |
| 128 | .irqs = SCIx_IRQ_MUXED(gic_spi(90)), | 130 | .irqs = SCIx_IRQ_MUXED(gic_iid(0x7a)), |
| 129 | }; | 131 | }; |
| 130 | 132 | ||
| 131 | static struct platform_device scif2_device = { | 133 | static struct platform_device scif2_device = { |
| @@ -142,7 +144,7 @@ static struct plat_sci_port scif3_platform_data = { | |||
| 142 | .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1, | 144 | .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1, |
| 143 | .scbrr_algo_id = SCBRR_ALGO_2, | 145 | .scbrr_algo_id = SCBRR_ALGO_2, |
| 144 | .type = PORT_SCIF, | 146 | .type = PORT_SCIF, |
| 145 | .irqs = SCIx_IRQ_MUXED(gic_spi(91)), | 147 | .irqs = SCIx_IRQ_MUXED(gic_iid(0x7b)), |
| 146 | }; | 148 | }; |
| 147 | 149 | ||
| 148 | static struct platform_device scif3_device = { | 150 | static struct platform_device scif3_device = { |
| @@ -159,7 +161,7 @@ static struct plat_sci_port scif4_platform_data = { | |||
| 159 | .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1, | 161 | .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1, |
| 160 | .scbrr_algo_id = SCBRR_ALGO_2, | 162 | .scbrr_algo_id = SCBRR_ALGO_2, |
| 161 | .type = PORT_SCIF, | 163 | .type = PORT_SCIF, |
| 162 | .irqs = SCIx_IRQ_MUXED(gic_spi(92)), | 164 | .irqs = SCIx_IRQ_MUXED(gic_iid(0x7c)), |
| 163 | }; | 165 | }; |
| 164 | 166 | ||
| 165 | static struct platform_device scif4_device = { | 167 | static struct platform_device scif4_device = { |
| @@ -176,7 +178,7 @@ static struct plat_sci_port scif5_platform_data = { | |||
| 176 | .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1, | 178 | .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1, |
| 177 | .scbrr_algo_id = SCBRR_ALGO_2, | 179 | .scbrr_algo_id = SCBRR_ALGO_2, |
| 178 | .type = PORT_SCIF, | 180 | .type = PORT_SCIF, |
| 179 | .irqs = SCIx_IRQ_MUXED(gic_spi(93)), | 181 | .irqs = SCIx_IRQ_MUXED(gic_iid(0x7d)), |
| 180 | }; | 182 | }; |
| 181 | 183 | ||
| 182 | static struct platform_device scif5_device = { | 184 | static struct platform_device scif5_device = { |
| @@ -203,7 +205,7 @@ static struct resource tmu00_resources[] = { | |||
| 203 | .flags = IORESOURCE_MEM, | 205 | .flags = IORESOURCE_MEM, |
| 204 | }, | 206 | }, |
| 205 | [1] = { | 207 | [1] = { |
| 206 | .start = gic_spi(32), | 208 | .start = gic_iid(0x40), |
| 207 | .flags = IORESOURCE_IRQ, | 209 | .flags = IORESOURCE_IRQ, |
| 208 | }, | 210 | }, |
| 209 | }; | 211 | }; |
| @@ -233,7 +235,7 @@ static struct resource tmu01_resources[] = { | |||
| 233 | .flags = IORESOURCE_MEM, | 235 | .flags = IORESOURCE_MEM, |
| 234 | }, | 236 | }, |
| 235 | [1] = { | 237 | [1] = { |
| 236 | .start = gic_spi(33), | 238 | .start = gic_iid(0x41), |
| 237 | .flags = IORESOURCE_IRQ, | 239 | .flags = IORESOURCE_IRQ, |
| 238 | }, | 240 | }, |
| 239 | }; | 241 | }; |
| @@ -255,7 +257,7 @@ static struct resource rcar_i2c0_res[] = { | |||
| 255 | .end = 0xffc70fff, | 257 | .end = 0xffc70fff, |
| 256 | .flags = IORESOURCE_MEM, | 258 | .flags = IORESOURCE_MEM, |
| 257 | }, { | 259 | }, { |
| 258 | .start = gic_spi(79), | 260 | .start = gic_iid(0x6f), |
| 259 | .flags = IORESOURCE_IRQ, | 261 | .flags = IORESOURCE_IRQ, |
| 260 | }, | 262 | }, |
| 261 | }; | 263 | }; |
| @@ -273,7 +275,7 @@ static struct resource rcar_i2c1_res[] = { | |||
| 273 | .end = 0xffc71fff, | 275 | .end = 0xffc71fff, |
| 274 | .flags = IORESOURCE_MEM, | 276 | .flags = IORESOURCE_MEM, |
| 275 | }, { | 277 | }, { |
| 276 | .start = gic_spi(82), | 278 | .start = gic_iid(0x72), |
| 277 | .flags = IORESOURCE_IRQ, | 279 | .flags = IORESOURCE_IRQ, |
| 278 | }, | 280 | }, |
| 279 | }; | 281 | }; |
| @@ -291,7 +293,7 @@ static struct resource rcar_i2c2_res[] = { | |||
| 291 | .end = 0xffc72fff, | 293 | .end = 0xffc72fff, |
| 292 | .flags = IORESOURCE_MEM, | 294 | .flags = IORESOURCE_MEM, |
| 293 | }, { | 295 | }, { |
| 294 | .start = gic_spi(80), | 296 | .start = gic_iid(0x70), |
| 295 | .flags = IORESOURCE_IRQ, | 297 | .flags = IORESOURCE_IRQ, |
| 296 | }, | 298 | }, |
| 297 | }; | 299 | }; |
| @@ -309,7 +311,7 @@ static struct resource rcar_i2c3_res[] = { | |||
| 309 | .end = 0xffc73fff, | 311 | .end = 0xffc73fff, |
| 310 | .flags = IORESOURCE_MEM, | 312 | .flags = IORESOURCE_MEM, |
| 311 | }, { | 313 | }, { |
| 312 | .start = gic_spi(81), | 314 | .start = gic_iid(0x71), |
| 313 | .flags = IORESOURCE_IRQ, | 315 | .flags = IORESOURCE_IRQ, |
| 314 | }, | 316 | }, |
| 315 | }; | 317 | }; |
| @@ -321,7 +323,31 @@ static struct platform_device i2c3_device = { | |||
| 321 | .num_resources = ARRAY_SIZE(rcar_i2c3_res), | 323 | .num_resources = ARRAY_SIZE(rcar_i2c3_res), |
| 322 | }; | 324 | }; |
| 323 | 325 | ||
| 324 | static struct platform_device *r8a7779_early_devices[] __initdata = { | 326 | static struct resource sata_resources[] = { |
| 327 | [0] = { | ||
| 328 | .name = "rcar-sata", | ||
| 329 | .start = 0xfc600000, | ||
| 330 | .end = 0xfc601fff, | ||
| 331 | .flags = IORESOURCE_MEM, | ||
| 332 | }, | ||
| 333 | [1] = { | ||
| 334 | .start = gic_iid(0x84), | ||
| 335 | .flags = IORESOURCE_IRQ, | ||
| 336 | }, | ||
| 337 | }; | ||
| 338 | |||
| 339 | static struct platform_device sata_device = { | ||
| 340 | .name = "sata_rcar", | ||
| 341 | .id = -1, | ||
| 342 | .resource = sata_resources, | ||
| 343 | .num_resources = ARRAY_SIZE(sata_resources), | ||
| 344 | .dev = { | ||
| 345 | .dma_mask = &sata_device.dev.coherent_dma_mask, | ||
| 346 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
| 347 | }, | ||
| 348 | }; | ||
| 349 | |||
| 350 | static struct platform_device *r8a7779_devices_dt[] __initdata = { | ||
| 325 | &scif0_device, | 351 | &scif0_device, |
| 326 | &scif1_device, | 352 | &scif1_device, |
| 327 | &scif2_device, | 353 | &scif2_device, |
| @@ -330,13 +356,14 @@ static struct platform_device *r8a7779_early_devices[] __initdata = { | |||
| 330 | &scif5_device, | 356 | &scif5_device, |
| 331 | &tmu00_device, | 357 | &tmu00_device, |
| 332 | &tmu01_device, | 358 | &tmu01_device, |
| 359 | }; | ||
| 360 | |||
| 361 | static struct platform_device *r8a7779_late_devices[] __initdata = { | ||
| 333 | &i2c0_device, | 362 | &i2c0_device, |
| 334 | &i2c1_device, | 363 | &i2c1_device, |
| 335 | &i2c2_device, | 364 | &i2c2_device, |
| 336 | &i2c3_device, | 365 | &i2c3_device, |
| 337 | }; | 366 | &sata_device, |
| 338 | |||
| 339 | static struct platform_device *r8a7779_late_devices[] __initdata = { | ||
| 340 | }; | 367 | }; |
| 341 | 368 | ||
| 342 | void __init r8a7779_add_standard_devices(void) | 369 | void __init r8a7779_add_standard_devices(void) |
| @@ -349,8 +376,8 @@ void __init r8a7779_add_standard_devices(void) | |||
| 349 | 376 | ||
| 350 | r8a7779_init_pm_domains(); | 377 | r8a7779_init_pm_domains(); |
| 351 | 378 | ||
| 352 | platform_add_devices(r8a7779_early_devices, | 379 | platform_add_devices(r8a7779_devices_dt, |
| 353 | ARRAY_SIZE(r8a7779_early_devices)); | 380 | ARRAY_SIZE(r8a7779_devices_dt)); |
| 354 | platform_add_devices(r8a7779_late_devices, | 381 | platform_add_devices(r8a7779_late_devices, |
| 355 | ARRAY_SIZE(r8a7779_late_devices)); | 382 | ARRAY_SIZE(r8a7779_late_devices)); |
| 356 | } | 383 | } |
| @@ -367,8 +394,8 @@ void __init r8a7779_earlytimer_init(void) | |||
| 367 | 394 | ||
| 368 | void __init r8a7779_add_early_devices(void) | 395 | void __init r8a7779_add_early_devices(void) |
| 369 | { | 396 | { |
| 370 | early_platform_add_devices(r8a7779_early_devices, | 397 | early_platform_add_devices(r8a7779_devices_dt, |
| 371 | ARRAY_SIZE(r8a7779_early_devices)); | 398 | ARRAY_SIZE(r8a7779_devices_dt)); |
| 372 | 399 | ||
| 373 | /* Early serial console setup is not included here due to | 400 | /* Early serial console setup is not included here due to |
| 374 | * memory map collisions. The SCIF serial ports in r8a7779 | 401 | * memory map collisions. The SCIF serial ports in r8a7779 |
| @@ -386,3 +413,40 @@ void __init r8a7779_add_early_devices(void) | |||
| 386 | * command line in case of the marzen board. | 413 | * command line in case of the marzen board. |
| 387 | */ | 414 | */ |
| 388 | } | 415 | } |
| 416 | |||
| 417 | #ifdef CONFIG_USE_OF | ||
| 418 | void __init r8a7779_init_delay(void) | ||
| 419 | { | ||
| 420 | shmobile_setup_delay(1000, 2, 4); /* Cortex-A9 @ 1000MHz */ | ||
| 421 | } | ||
| 422 | |||
| 423 | static const struct of_dev_auxdata r8a7779_auxdata_lookup[] __initconst = { | ||
| 424 | {}, | ||
| 425 | }; | ||
| 426 | |||
| 427 | void __init r8a7779_add_standard_devices_dt(void) | ||
| 428 | { | ||
| 429 | /* clocks are setup late during boot in the case of DT */ | ||
| 430 | r8a7779_clock_init(); | ||
| 431 | |||
| 432 | platform_add_devices(r8a7779_devices_dt, | ||
| 433 | ARRAY_SIZE(r8a7779_devices_dt)); | ||
| 434 | of_platform_populate(NULL, of_default_bus_match_table, | ||
| 435 | r8a7779_auxdata_lookup, NULL); | ||
| 436 | } | ||
| 437 | |||
| 438 | static const char *r8a7779_compat_dt[] __initdata = { | ||
| 439 | "renesas,r8a7779", | ||
| 440 | NULL, | ||
| 441 | }; | ||
| 442 | |||
| 443 | DT_MACHINE_START(R8A7779_DT, "Generic R8A7779 (Flattened Device Tree)") | ||
| 444 | .map_io = r8a7779_map_io, | ||
| 445 | .init_early = r8a7779_init_delay, | ||
| 446 | .nr_irqs = NR_IRQS_LEGACY, | ||
| 447 | .init_irq = r8a7779_init_irq_dt, | ||
| 448 | .init_machine = r8a7779_add_standard_devices_dt, | ||
| 449 | .init_time = shmobile_timer_init, | ||
| 450 | .dt_compat = r8a7779_compat_dt, | ||
| 451 | MACHINE_END | ||
| 452 | #endif /* CONFIG_USE_OF */ | ||
diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c index bdab575f88bc..e8cd93a5c550 100644 --- a/arch/arm/mach-shmobile/setup-sh73a0.c +++ b/arch/arm/mach-shmobile/setup-sh73a0.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
| 23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
| 24 | #include <linux/irq.h> | 24 | #include <linux/irq.h> |
| 25 | #include <linux/irqchip.h> | ||
| 25 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
| 26 | #include <linux/of_platform.h> | 27 | #include <linux/of_platform.h> |
| 27 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
| @@ -32,6 +33,7 @@ | |||
| 32 | #include <linux/sh_intc.h> | 33 | #include <linux/sh_intc.h> |
| 33 | #include <linux/sh_timer.h> | 34 | #include <linux/sh_timer.h> |
| 34 | #include <linux/platform_data/sh_ipmmu.h> | 35 | #include <linux/platform_data/sh_ipmmu.h> |
| 36 | #include <linux/platform_data/irq-renesas-intc-irqpin.h> | ||
| 35 | #include <mach/dma-register.h> | 37 | #include <mach/dma-register.h> |
| 36 | #include <mach/hardware.h> | 38 | #include <mach/hardware.h> |
| 37 | #include <mach/irqs.h> | 39 | #include <mach/irqs.h> |
| @@ -810,7 +812,128 @@ static struct platform_device ipmmu_device = { | |||
| 810 | .num_resources = ARRAY_SIZE(ipmmu_resources), | 812 | .num_resources = ARRAY_SIZE(ipmmu_resources), |
| 811 | }; | 813 | }; |
| 812 | 814 | ||
| 813 | static struct platform_device *sh73a0_early_devices_dt[] __initdata = { | 815 | static struct renesas_intc_irqpin_config irqpin0_platform_data = { |
| 816 | .irq_base = irq_pin(0), /* IRQ0 -> IRQ7 */ | ||
| 817 | }; | ||
| 818 | |||
| 819 | static struct resource irqpin0_resources[] = { | ||
| 820 | DEFINE_RES_MEM(0xe6900000, 4), /* ICR1A */ | ||
| 821 | DEFINE_RES_MEM(0xe6900010, 4), /* INTPRI00A */ | ||
| 822 | DEFINE_RES_MEM(0xe6900020, 1), /* INTREQ00A */ | ||
| 823 | DEFINE_RES_MEM(0xe6900040, 1), /* INTMSK00A */ | ||
| 824 | DEFINE_RES_MEM(0xe6900060, 1), /* INTMSKCLR00A */ | ||
| 825 | DEFINE_RES_IRQ(gic_spi(1)), /* IRQ0 */ | ||
| 826 | DEFINE_RES_IRQ(gic_spi(2)), /* IRQ1 */ | ||
| 827 | DEFINE_RES_IRQ(gic_spi(3)), /* IRQ2 */ | ||
| 828 | DEFINE_RES_IRQ(gic_spi(4)), /* IRQ3 */ | ||
| 829 | DEFINE_RES_IRQ(gic_spi(5)), /* IRQ4 */ | ||
| 830 | DEFINE_RES_IRQ(gic_spi(6)), /* IRQ5 */ | ||
| 831 | DEFINE_RES_IRQ(gic_spi(7)), /* IRQ6 */ | ||
| 832 | DEFINE_RES_IRQ(gic_spi(8)), /* IRQ7 */ | ||
| 833 | }; | ||
| 834 | |||
| 835 | static struct platform_device irqpin0_device = { | ||
| 836 | .name = "renesas_intc_irqpin", | ||
| 837 | .id = 0, | ||
| 838 | .resource = irqpin0_resources, | ||
| 839 | .num_resources = ARRAY_SIZE(irqpin0_resources), | ||
| 840 | .dev = { | ||
| 841 | .platform_data = &irqpin0_platform_data, | ||
| 842 | }, | ||
| 843 | }; | ||
| 844 | |||
| 845 | static struct renesas_intc_irqpin_config irqpin1_platform_data = { | ||
| 846 | .irq_base = irq_pin(8), /* IRQ8 -> IRQ15 */ | ||
| 847 | .control_parent = true, /* Disable spurious IRQ10 */ | ||
| 848 | }; | ||
| 849 | |||
| 850 | static struct resource irqpin1_resources[] = { | ||
| 851 | DEFINE_RES_MEM(0xe6900004, 4), /* ICR2A */ | ||
| 852 | DEFINE_RES_MEM(0xe6900014, 4), /* INTPRI10A */ | ||
| 853 | DEFINE_RES_MEM(0xe6900024, 1), /* INTREQ10A */ | ||
| 854 | DEFINE_RES_MEM(0xe6900044, 1), /* INTMSK10A */ | ||
| 855 | DEFINE_RES_MEM(0xe6900064, 1), /* INTMSKCLR10A */ | ||
| 856 | DEFINE_RES_IRQ(gic_spi(9)), /* IRQ8 */ | ||
| 857 | DEFINE_RES_IRQ(gic_spi(10)), /* IRQ9 */ | ||
| 858 | DEFINE_RES_IRQ(gic_spi(11)), /* IRQ10 */ | ||
| 859 | DEFINE_RES_IRQ(gic_spi(12)), /* IRQ11 */ | ||
| 860 | DEFINE_RES_IRQ(gic_spi(13)), /* IRQ12 */ | ||
| 861 | DEFINE_RES_IRQ(gic_spi(14)), /* IRQ13 */ | ||
| 862 | DEFINE_RES_IRQ(gic_spi(15)), /* IRQ14 */ | ||
| 863 | DEFINE_RES_IRQ(gic_spi(16)), /* IRQ15 */ | ||
| 864 | }; | ||
| 865 | |||
| 866 | static struct platform_device irqpin1_device = { | ||
| 867 | .name = "renesas_intc_irqpin", | ||
| 868 | .id = 1, | ||
| 869 | .resource = irqpin1_resources, | ||
| 870 | .num_resources = ARRAY_SIZE(irqpin1_resources), | ||
| 871 | .dev = { | ||
| 872 | .platform_data = &irqpin1_platform_data, | ||
| 873 | }, | ||
| 874 | }; | ||
| 875 | |||
| 876 | static struct renesas_intc_irqpin_config irqpin2_platform_data = { | ||
| 877 | .irq_base = irq_pin(16), /* IRQ16 -> IRQ23 */ | ||
| 878 | }; | ||
| 879 | |||
| 880 | static struct resource irqpin2_resources[] = { | ||
| 881 | DEFINE_RES_MEM(0xe6900008, 4), /* ICR3A */ | ||
| 882 | DEFINE_RES_MEM(0xe6900018, 4), /* INTPRI20A */ | ||
| 883 | DEFINE_RES_MEM(0xe6900028, 1), /* INTREQ20A */ | ||
| 884 | DEFINE_RES_MEM(0xe6900048, 1), /* INTMSK20A */ | ||
| 885 | DEFINE_RES_MEM(0xe6900068, 1), /* INTMSKCLR20A */ | ||
| 886 | DEFINE_RES_IRQ(gic_spi(17)), /* IRQ16 */ | ||
| 887 | DEFINE_RES_IRQ(gic_spi(18)), /* IRQ17 */ | ||
| 888 | DEFINE_RES_IRQ(gic_spi(19)), /* IRQ18 */ | ||
| 889 | DEFINE_RES_IRQ(gic_spi(20)), /* IRQ19 */ | ||
| 890 | DEFINE_RES_IRQ(gic_spi(21)), /* IRQ20 */ | ||
| 891 | DEFINE_RES_IRQ(gic_spi(22)), /* IRQ21 */ | ||
| 892 | DEFINE_RES_IRQ(gic_spi(23)), /* IRQ22 */ | ||
| 893 | DEFINE_RES_IRQ(gic_spi(24)), /* IRQ23 */ | ||
| 894 | }; | ||
| 895 | |||
| 896 | static struct platform_device irqpin2_device = { | ||
| 897 | .name = "renesas_intc_irqpin", | ||
| 898 | .id = 2, | ||
| 899 | .resource = irqpin2_resources, | ||
| 900 | .num_resources = ARRAY_SIZE(irqpin2_resources), | ||
| 901 | .dev = { | ||
| 902 | .platform_data = &irqpin2_platform_data, | ||
| 903 | }, | ||
| 904 | }; | ||
| 905 | |||
| 906 | static struct renesas_intc_irqpin_config irqpin3_platform_data = { | ||
| 907 | .irq_base = irq_pin(24), /* IRQ24 -> IRQ31 */ | ||
| 908 | }; | ||
| 909 | |||
| 910 | static struct resource irqpin3_resources[] = { | ||
| 911 | DEFINE_RES_MEM(0xe690000c, 4), /* ICR4A */ | ||
| 912 | DEFINE_RES_MEM(0xe690001c, 4), /* INTPRI30A */ | ||
| 913 | DEFINE_RES_MEM(0xe690002c, 1), /* INTREQ30A */ | ||
| 914 | DEFINE_RES_MEM(0xe690004c, 1), /* INTMSK30A */ | ||
| 915 | DEFINE_RES_MEM(0xe690006c, 1), /* INTMSKCLR30A */ | ||
| 916 | DEFINE_RES_IRQ(gic_spi(25)), /* IRQ24 */ | ||
| 917 | DEFINE_RES_IRQ(gic_spi(26)), /* IRQ25 */ | ||
| 918 | DEFINE_RES_IRQ(gic_spi(27)), /* IRQ26 */ | ||
| 919 | DEFINE_RES_IRQ(gic_spi(28)), /* IRQ27 */ | ||
| 920 | DEFINE_RES_IRQ(gic_spi(29)), /* IRQ28 */ | ||
| 921 | DEFINE_RES_IRQ(gic_spi(30)), /* IRQ29 */ | ||
| 922 | DEFINE_RES_IRQ(gic_spi(31)), /* IRQ30 */ | ||
| 923 | DEFINE_RES_IRQ(gic_spi(32)), /* IRQ31 */ | ||
| 924 | }; | ||
| 925 | |||
| 926 | static struct platform_device irqpin3_device = { | ||
| 927 | .name = "renesas_intc_irqpin", | ||
| 928 | .id = 3, | ||
| 929 | .resource = irqpin3_resources, | ||
| 930 | .num_resources = ARRAY_SIZE(irqpin3_resources), | ||
| 931 | .dev = { | ||
| 932 | .platform_data = &irqpin3_platform_data, | ||
| 933 | }, | ||
| 934 | }; | ||
| 935 | |||
| 936 | static struct platform_device *sh73a0_devices_dt[] __initdata = { | ||
| 814 | &scif0_device, | 937 | &scif0_device, |
| 815 | &scif1_device, | 938 | &scif1_device, |
| 816 | &scif2_device, | 939 | &scif2_device, |
| @@ -838,6 +961,10 @@ static struct platform_device *sh73a0_late_devices[] __initdata = { | |||
| 838 | &dma0_device, | 961 | &dma0_device, |
| 839 | &mpdma0_device, | 962 | &mpdma0_device, |
| 840 | &pmu_device, | 963 | &pmu_device, |
| 964 | &irqpin0_device, | ||
| 965 | &irqpin1_device, | ||
| 966 | &irqpin2_device, | ||
| 967 | &irqpin3_device, | ||
| 841 | }; | 968 | }; |
| 842 | 969 | ||
| 843 | #define SRCR2 IOMEM(0xe61580b0) | 970 | #define SRCR2 IOMEM(0xe61580b0) |
| @@ -847,8 +974,8 @@ void __init sh73a0_add_standard_devices(void) | |||
| 847 | /* Clear software reset bit on SY-DMAC module */ | 974 | /* Clear software reset bit on SY-DMAC module */ |
| 848 | __raw_writel(__raw_readl(SRCR2) & ~(1 << 18), SRCR2); | 975 | __raw_writel(__raw_readl(SRCR2) & ~(1 << 18), SRCR2); |
| 849 | 976 | ||
| 850 | platform_add_devices(sh73a0_early_devices_dt, | 977 | platform_add_devices(sh73a0_devices_dt, |
| 851 | ARRAY_SIZE(sh73a0_early_devices_dt)); | 978 | ARRAY_SIZE(sh73a0_devices_dt)); |
| 852 | platform_add_devices(sh73a0_early_devices, | 979 | platform_add_devices(sh73a0_early_devices, |
| 853 | ARRAY_SIZE(sh73a0_early_devices)); | 980 | ARRAY_SIZE(sh73a0_early_devices)); |
| 854 | platform_add_devices(sh73a0_late_devices, | 981 | platform_add_devices(sh73a0_late_devices, |
| @@ -867,8 +994,8 @@ void __init sh73a0_earlytimer_init(void) | |||
| 867 | 994 | ||
| 868 | void __init sh73a0_add_early_devices(void) | 995 | void __init sh73a0_add_early_devices(void) |
| 869 | { | 996 | { |
| 870 | early_platform_add_devices(sh73a0_early_devices_dt, | 997 | early_platform_add_devices(sh73a0_devices_dt, |
| 871 | ARRAY_SIZE(sh73a0_early_devices_dt)); | 998 | ARRAY_SIZE(sh73a0_devices_dt)); |
| 872 | early_platform_add_devices(sh73a0_early_devices, | 999 | early_platform_add_devices(sh73a0_early_devices, |
| 873 | ARRAY_SIZE(sh73a0_early_devices)); | 1000 | ARRAY_SIZE(sh73a0_early_devices)); |
| 874 | 1001 | ||
| @@ -878,23 +1005,9 @@ void __init sh73a0_add_early_devices(void) | |||
| 878 | 1005 | ||
| 879 | #ifdef CONFIG_USE_OF | 1006 | #ifdef CONFIG_USE_OF |
| 880 | 1007 | ||
| 881 | /* Please note that the clock initialisation shcheme used in | 1008 | void __init sh73a0_init_delay(void) |
| 882 | * sh73a0_add_early_devices_dt() and sh73a0_add_standard_devices_dt() | ||
| 883 | * does not work with SMP as there is a yet to be resolved lock-up in | ||
| 884 | * workqueue initialisation. | ||
| 885 | * | ||
| 886 | * CONFIG_SMP should be disabled when using this code. | ||
| 887 | */ | ||
| 888 | |||
| 889 | void __init sh73a0_add_early_devices_dt(void) | ||
| 890 | { | 1009 | { |
| 891 | shmobile_setup_delay(1196, 44, 46); /* Cortex-A9 @ 1196MHz */ | 1010 | shmobile_setup_delay(1196, 44, 46); /* Cortex-A9 @ 1196MHz */ |
| 892 | |||
| 893 | early_platform_add_devices(sh73a0_early_devices_dt, | ||
| 894 | ARRAY_SIZE(sh73a0_early_devices_dt)); | ||
| 895 | |||
| 896 | /* setup early console here as well */ | ||
| 897 | shmobile_setup_console(); | ||
| 898 | } | 1011 | } |
| 899 | 1012 | ||
| 900 | static const struct of_dev_auxdata sh73a0_auxdata_lookup[] __initconst = { | 1013 | static const struct of_dev_auxdata sh73a0_auxdata_lookup[] __initconst = { |
| @@ -906,8 +1019,8 @@ void __init sh73a0_add_standard_devices_dt(void) | |||
| 906 | /* clocks are setup late during boot in the case of DT */ | 1019 | /* clocks are setup late during boot in the case of DT */ |
| 907 | sh73a0_clock_init(); | 1020 | sh73a0_clock_init(); |
| 908 | 1021 | ||
| 909 | platform_add_devices(sh73a0_early_devices_dt, | 1022 | platform_add_devices(sh73a0_devices_dt, |
| 910 | ARRAY_SIZE(sh73a0_early_devices_dt)); | 1023 | ARRAY_SIZE(sh73a0_devices_dt)); |
| 911 | of_platform_populate(NULL, of_default_bus_match_table, | 1024 | of_platform_populate(NULL, of_default_bus_match_table, |
| 912 | sh73a0_auxdata_lookup, NULL); | 1025 | sh73a0_auxdata_lookup, NULL); |
| 913 | } | 1026 | } |
| @@ -918,10 +1031,11 @@ static const char *sh73a0_boards_compat_dt[] __initdata = { | |||
| 918 | }; | 1031 | }; |
| 919 | 1032 | ||
| 920 | DT_MACHINE_START(SH73A0_DT, "Generic SH73A0 (Flattened Device Tree)") | 1033 | DT_MACHINE_START(SH73A0_DT, "Generic SH73A0 (Flattened Device Tree)") |
| 1034 | .smp = smp_ops(sh73a0_smp_ops), | ||
| 921 | .map_io = sh73a0_map_io, | 1035 | .map_io = sh73a0_map_io, |
| 922 | .init_early = sh73a0_add_early_devices_dt, | 1036 | .init_early = sh73a0_init_delay, |
| 923 | .nr_irqs = NR_IRQS_LEGACY, | 1037 | .nr_irqs = NR_IRQS_LEGACY, |
| 924 | .init_irq = sh73a0_init_irq_dt, | 1038 | .init_irq = irqchip_init, |
| 925 | .init_machine = sh73a0_add_standard_devices_dt, | 1039 | .init_machine = sh73a0_add_standard_devices_dt, |
| 926 | .init_time = shmobile_timer_init, | 1040 | .init_time = shmobile_timer_init, |
| 927 | .dt_compat = sh73a0_boards_compat_dt, | 1041 | .dt_compat = sh73a0_boards_compat_dt, |
diff --git a/arch/arm/mach-shmobile/smp-emev2.c b/arch/arm/mach-shmobile/smp-emev2.c index 953eb1f9388d..8225c16b371b 100644 --- a/arch/arm/mach-shmobile/smp-emev2.c +++ b/arch/arm/mach-shmobile/smp-emev2.c | |||
| @@ -28,63 +28,9 @@ | |||
| 28 | #include <mach/emev2.h> | 28 | #include <mach/emev2.h> |
| 29 | #include <asm/smp_plat.h> | 29 | #include <asm/smp_plat.h> |
| 30 | #include <asm/smp_scu.h> | 30 | #include <asm/smp_scu.h> |
| 31 | #include <asm/cacheflush.h> | ||
| 32 | 31 | ||
| 33 | #define EMEV2_SCU_BASE 0x1e000000 | 32 | #define EMEV2_SCU_BASE 0x1e000000 |
| 34 | 33 | ||
| 35 | static DEFINE_SPINLOCK(scu_lock); | ||
| 36 | static void __iomem *scu_base; | ||
| 37 | |||
| 38 | static void modify_scu_cpu_psr(unsigned long set, unsigned long clr) | ||
| 39 | { | ||
| 40 | unsigned long tmp; | ||
| 41 | |||
| 42 | /* we assume this code is running on a different cpu | ||
| 43 | * than the one that is changing coherency setting */ | ||
| 44 | spin_lock(&scu_lock); | ||
| 45 | tmp = readl(scu_base + 8); | ||
| 46 | tmp &= ~clr; | ||
| 47 | tmp |= set; | ||
| 48 | writel(tmp, scu_base + 8); | ||
| 49 | spin_unlock(&scu_lock); | ||
| 50 | |||
| 51 | } | ||
| 52 | |||
| 53 | static unsigned int __init emev2_get_core_count(void) | ||
| 54 | { | ||
| 55 | if (!scu_base) { | ||
| 56 | scu_base = ioremap(EMEV2_SCU_BASE, PAGE_SIZE); | ||
| 57 | emev2_clock_init(); /* need ioremapped SMU */ | ||
| 58 | } | ||
| 59 | |||
| 60 | WARN_ON_ONCE(!scu_base); | ||
| 61 | |||
| 62 | return scu_base ? scu_get_core_count(scu_base) : 1; | ||
| 63 | } | ||
| 64 | |||
| 65 | static int emev2_platform_cpu_kill(unsigned int cpu) | ||
| 66 | { | ||
| 67 | return 0; /* not supported yet */ | ||
| 68 | } | ||
| 69 | |||
| 70 | static int __maybe_unused emev2_cpu_kill(unsigned int cpu) | ||
| 71 | { | ||
| 72 | int k; | ||
| 73 | |||
| 74 | /* this function is running on another CPU than the offline target, | ||
| 75 | * here we need wait for shutdown code in platform_cpu_die() to | ||
| 76 | * finish before asking SoC-specific code to power off the CPU core. | ||
| 77 | */ | ||
| 78 | for (k = 0; k < 1000; k++) { | ||
| 79 | if (shmobile_cpu_is_dead(cpu)) | ||
| 80 | return emev2_platform_cpu_kill(cpu); | ||
| 81 | mdelay(1); | ||
| 82 | } | ||
| 83 | |||
| 84 | return 0; | ||
| 85 | } | ||
| 86 | |||
| 87 | |||
| 88 | static void __cpuinit emev2_secondary_init(unsigned int cpu) | 34 | static void __cpuinit emev2_secondary_init(unsigned int cpu) |
| 89 | { | 35 | { |
| 90 | gic_secondary_init(0); | 36 | gic_secondary_init(0); |
| @@ -92,31 +38,30 @@ static void __cpuinit emev2_secondary_init(unsigned int cpu) | |||
| 92 | 38 | ||
| 93 | static int __cpuinit emev2_boot_secondary(unsigned int cpu, struct task_struct *idle) | 39 | static int __cpuinit emev2_boot_secondary(unsigned int cpu, struct task_struct *idle) |
| 94 | { | 40 | { |
| 95 | cpu = cpu_logical_map(cpu); | 41 | arch_send_wakeup_ipi_mask(cpumask_of(cpu_logical_map(cpu))); |
| 96 | |||
| 97 | /* enable cache coherency */ | ||
| 98 | modify_scu_cpu_psr(0, 3 << (cpu * 8)); | ||
| 99 | |||
| 100 | /* Tell ROM loader about our vector (in headsmp.S) */ | ||
| 101 | emev2_set_boot_vector(__pa(shmobile_secondary_vector)); | ||
| 102 | |||
| 103 | arch_send_wakeup_ipi_mask(cpumask_of(cpu)); | ||
| 104 | return 0; | 42 | return 0; |
| 105 | } | 43 | } |
| 106 | 44 | ||
| 107 | static void __init emev2_smp_prepare_cpus(unsigned int max_cpus) | 45 | static void __init emev2_smp_prepare_cpus(unsigned int max_cpus) |
| 108 | { | 46 | { |
| 109 | int cpu = cpu_logical_map(0); | 47 | scu_enable(shmobile_scu_base); |
| 110 | 48 | ||
| 111 | scu_enable(scu_base); | 49 | /* Tell ROM loader about our vector (in headsmp-scu.S) */ |
| 50 | emev2_set_boot_vector(__pa(shmobile_secondary_vector_scu)); | ||
| 112 | 51 | ||
| 113 | /* enable cache coherency on CPU0 */ | 52 | /* enable cache coherency on booting CPU */ |
| 114 | modify_scu_cpu_psr(0, 3 << (cpu * 8)); | 53 | scu_power_mode(shmobile_scu_base, SCU_PM_NORMAL); |
| 115 | } | 54 | } |
| 116 | 55 | ||
| 117 | static void __init emev2_smp_init_cpus(void) | 56 | static void __init emev2_smp_init_cpus(void) |
| 118 | { | 57 | { |
| 119 | unsigned int ncores = emev2_get_core_count(); | 58 | unsigned int ncores; |
| 59 | |||
| 60 | /* setup EMEV2 specific SCU base */ | ||
| 61 | shmobile_scu_base = ioremap(EMEV2_SCU_BASE, PAGE_SIZE); | ||
| 62 | emev2_clock_init(); /* need ioremapped SMU */ | ||
| 63 | |||
| 64 | ncores = shmobile_scu_base ? scu_get_core_count(shmobile_scu_base) : 1; | ||
| 120 | 65 | ||
| 121 | shmobile_smp_init_cpus(ncores); | 66 | shmobile_smp_init_cpus(ncores); |
| 122 | } | 67 | } |
| @@ -126,9 +71,4 @@ struct smp_operations emev2_smp_ops __initdata = { | |||
| 126 | .smp_prepare_cpus = emev2_smp_prepare_cpus, | 71 | .smp_prepare_cpus = emev2_smp_prepare_cpus, |
| 127 | .smp_secondary_init = emev2_secondary_init, | 72 | .smp_secondary_init = emev2_secondary_init, |
| 128 | .smp_boot_secondary = emev2_boot_secondary, | 73 | .smp_boot_secondary = emev2_boot_secondary, |
| 129 | #ifdef CONFIG_HOTPLUG_CPU | ||
| 130 | .cpu_kill = emev2_cpu_kill, | ||
| 131 | .cpu_die = shmobile_cpu_die, | ||
| 132 | .cpu_disable = shmobile_cpu_disable, | ||
| 133 | #endif | ||
| 134 | }; | 74 | }; |
diff --git a/arch/arm/mach-shmobile/smp-r8a7779.c b/arch/arm/mach-shmobile/smp-r8a7779.c index 3a4acf23edcf..ea4535a5c4e2 100644 --- a/arch/arm/mach-shmobile/smp-r8a7779.c +++ b/arch/arm/mach-shmobile/smp-r8a7779.c | |||
| @@ -26,11 +26,13 @@ | |||
| 26 | #include <linux/irqchip/arm-gic.h> | 26 | #include <linux/irqchip/arm-gic.h> |
| 27 | #include <mach/common.h> | 27 | #include <mach/common.h> |
| 28 | #include <mach/r8a7779.h> | 28 | #include <mach/r8a7779.h> |
| 29 | #include <asm/cacheflush.h> | ||
| 29 | #include <asm/smp_plat.h> | 30 | #include <asm/smp_plat.h> |
| 30 | #include <asm/smp_scu.h> | 31 | #include <asm/smp_scu.h> |
| 31 | #include <asm/smp_twd.h> | 32 | #include <asm/smp_twd.h> |
| 32 | 33 | ||
| 33 | #define AVECR IOMEM(0xfe700040) | 34 | #define AVECR IOMEM(0xfe700040) |
| 35 | #define R8A7779_SCU_BASE 0xf0000000 | ||
| 34 | 36 | ||
| 35 | static struct r8a7779_pm_ch r8a7779_ch_cpu1 = { | 37 | static struct r8a7779_pm_ch r8a7779_ch_cpu1 = { |
| 36 | .chan_offs = 0x40, /* PWRSR0 .. PWRER0 */ | 38 | .chan_offs = 0x40, /* PWRSR0 .. PWRER0 */ |
| @@ -56,44 +58,14 @@ static struct r8a7779_pm_ch *r8a7779_ch_cpu[4] = { | |||
| 56 | [3] = &r8a7779_ch_cpu3, | 58 | [3] = &r8a7779_ch_cpu3, |
| 57 | }; | 59 | }; |
| 58 | 60 | ||
| 59 | static void __iomem *scu_base_addr(void) | ||
| 60 | { | ||
| 61 | return (void __iomem *)0xf0000000; | ||
| 62 | } | ||
| 63 | |||
| 64 | static DEFINE_SPINLOCK(scu_lock); | ||
| 65 | static unsigned long tmp; | ||
| 66 | |||
| 67 | #ifdef CONFIG_HAVE_ARM_TWD | 61 | #ifdef CONFIG_HAVE_ARM_TWD |
| 68 | static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29); | 62 | static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, R8A7779_SCU_BASE + 0x600, 29); |
| 69 | |||
| 70 | void __init r8a7779_register_twd(void) | 63 | void __init r8a7779_register_twd(void) |
| 71 | { | 64 | { |
| 72 | twd_local_timer_register(&twd_local_timer); | 65 | twd_local_timer_register(&twd_local_timer); |
| 73 | } | 66 | } |
| 74 | #endif | 67 | #endif |
| 75 | 68 | ||
| 76 | static void modify_scu_cpu_psr(unsigned long set, unsigned long clr) | ||
| 77 | { | ||
| 78 | void __iomem *scu_base = scu_base_addr(); | ||
| 79 | |||
| 80 | spin_lock(&scu_lock); | ||
| 81 | tmp = __raw_readl(scu_base + 8); | ||
| 82 | tmp &= ~clr; | ||
| 83 | tmp |= set; | ||
| 84 | spin_unlock(&scu_lock); | ||
| 85 | |||
| 86 | /* disable cache coherency after releasing the lock */ | ||
| 87 | __raw_writel(tmp, scu_base + 8); | ||
| 88 | } | ||
| 89 | |||
| 90 | static unsigned int __init r8a7779_get_core_count(void) | ||
| 91 | { | ||
| 92 | void __iomem *scu_base = scu_base_addr(); | ||
| 93 | |||
| 94 | return scu_get_core_count(scu_base); | ||
| 95 | } | ||
| 96 | |||
| 97 | static int r8a7779_platform_cpu_kill(unsigned int cpu) | 69 | static int r8a7779_platform_cpu_kill(unsigned int cpu) |
| 98 | { | 70 | { |
| 99 | struct r8a7779_pm_ch *ch = NULL; | 71 | struct r8a7779_pm_ch *ch = NULL; |
| @@ -101,9 +73,6 @@ static int r8a7779_platform_cpu_kill(unsigned int cpu) | |||
| 101 | 73 | ||
| 102 | cpu = cpu_logical_map(cpu); | 74 | cpu = cpu_logical_map(cpu); |
| 103 | 75 | ||
| 104 | /* disable cache coherency */ | ||
| 105 | modify_scu_cpu_psr(3 << (cpu * 8), 0); | ||
| 106 | |||
| 107 | if (cpu < ARRAY_SIZE(r8a7779_ch_cpu)) | 76 | if (cpu < ARRAY_SIZE(r8a7779_ch_cpu)) |
| 108 | ch = r8a7779_ch_cpu[cpu]; | 77 | ch = r8a7779_ch_cpu[cpu]; |
| 109 | 78 | ||
| @@ -113,25 +82,6 @@ static int r8a7779_platform_cpu_kill(unsigned int cpu) | |||
| 113 | return ret ? ret : 1; | 82 | return ret ? ret : 1; |
| 114 | } | 83 | } |
| 115 | 84 | ||
| 116 | static int __maybe_unused r8a7779_cpu_kill(unsigned int cpu) | ||
| 117 | { | ||
| 118 | int k; | ||
| 119 | |||
| 120 | /* this function is running on another CPU than the offline target, | ||
| 121 | * here we need wait for shutdown code in platform_cpu_die() to | ||
| 122 | * finish before asking SoC-specific code to power off the CPU core. | ||
| 123 | */ | ||
| 124 | for (k = 0; k < 1000; k++) { | ||
| 125 | if (shmobile_cpu_is_dead(cpu)) | ||
| 126 | return r8a7779_platform_cpu_kill(cpu); | ||
| 127 | |||
| 128 | mdelay(1); | ||
| 129 | } | ||
| 130 | |||
| 131 | return 0; | ||
| 132 | } | ||
| 133 | |||
| 134 | |||
| 135 | static void __cpuinit r8a7779_secondary_init(unsigned int cpu) | 85 | static void __cpuinit r8a7779_secondary_init(unsigned int cpu) |
| 136 | { | 86 | { |
| 137 | gic_secondary_init(0); | 87 | gic_secondary_init(0); |
| @@ -144,9 +94,6 @@ static int __cpuinit r8a7779_boot_secondary(unsigned int cpu, struct task_struct | |||
| 144 | 94 | ||
| 145 | cpu = cpu_logical_map(cpu); | 95 | cpu = cpu_logical_map(cpu); |
| 146 | 96 | ||
| 147 | /* enable cache coherency */ | ||
| 148 | modify_scu_cpu_psr(0, 3 << (cpu * 8)); | ||
| 149 | |||
| 150 | if (cpu < ARRAY_SIZE(r8a7779_ch_cpu)) | 97 | if (cpu < ARRAY_SIZE(r8a7779_ch_cpu)) |
| 151 | ch = r8a7779_ch_cpu[cpu]; | 98 | ch = r8a7779_ch_cpu[cpu]; |
| 152 | 99 | ||
| @@ -158,15 +105,13 @@ static int __cpuinit r8a7779_boot_secondary(unsigned int cpu, struct task_struct | |||
| 158 | 105 | ||
| 159 | static void __init r8a7779_smp_prepare_cpus(unsigned int max_cpus) | 106 | static void __init r8a7779_smp_prepare_cpus(unsigned int max_cpus) |
| 160 | { | 107 | { |
| 161 | int cpu = cpu_logical_map(0); | 108 | scu_enable(shmobile_scu_base); |
| 162 | 109 | ||
| 163 | scu_enable(scu_base_addr()); | 110 | /* Map the reset vector (in headsmp-scu.S) */ |
| 111 | __raw_writel(__pa(shmobile_secondary_vector_scu), AVECR); | ||
| 164 | 112 | ||
| 165 | /* Map the reset vector (in headsmp.S) */ | 113 | /* enable cache coherency on booting CPU */ |
| 166 | __raw_writel(__pa(shmobile_secondary_vector), AVECR); | 114 | scu_power_mode(shmobile_scu_base, SCU_PM_NORMAL); |
| 167 | |||
| 168 | /* enable cache coherency on CPU0 */ | ||
| 169 | modify_scu_cpu_psr(0, 3 << (cpu * 8)); | ||
| 170 | 115 | ||
| 171 | r8a7779_pm_init(); | 116 | r8a7779_pm_init(); |
| 172 | 117 | ||
| @@ -178,10 +123,60 @@ static void __init r8a7779_smp_prepare_cpus(unsigned int max_cpus) | |||
| 178 | 123 | ||
| 179 | static void __init r8a7779_smp_init_cpus(void) | 124 | static void __init r8a7779_smp_init_cpus(void) |
| 180 | { | 125 | { |
| 181 | unsigned int ncores = r8a7779_get_core_count(); | 126 | /* setup r8a7779 specific SCU base */ |
| 127 | shmobile_scu_base = IOMEM(R8A7779_SCU_BASE); | ||
| 128 | |||
| 129 | shmobile_smp_init_cpus(scu_get_core_count(shmobile_scu_base)); | ||
| 130 | } | ||
| 182 | 131 | ||
| 183 | shmobile_smp_init_cpus(ncores); | 132 | #ifdef CONFIG_HOTPLUG_CPU |
| 133 | static int r8a7779_scu_psr_core_disabled(int cpu) | ||
| 134 | { | ||
| 135 | unsigned long mask = 3 << (cpu * 8); | ||
| 136 | |||
| 137 | if ((__raw_readl(shmobile_scu_base + 8) & mask) == mask) | ||
| 138 | return 1; | ||
| 139 | |||
| 140 | return 0; | ||
| 141 | } | ||
| 142 | |||
| 143 | static int r8a7779_cpu_kill(unsigned int cpu) | ||
| 144 | { | ||
| 145 | int k; | ||
| 146 | |||
| 147 | /* this function is running on another CPU than the offline target, | ||
| 148 | * here we need wait for shutdown code in platform_cpu_die() to | ||
| 149 | * finish before asking SoC-specific code to power off the CPU core. | ||
| 150 | */ | ||
| 151 | for (k = 0; k < 1000; k++) { | ||
| 152 | if (r8a7779_scu_psr_core_disabled(cpu)) | ||
| 153 | return r8a7779_platform_cpu_kill(cpu); | ||
| 154 | |||
| 155 | mdelay(1); | ||
| 156 | } | ||
| 157 | |||
| 158 | return 0; | ||
| 159 | } | ||
| 160 | |||
| 161 | static void r8a7779_cpu_die(unsigned int cpu) | ||
| 162 | { | ||
| 163 | dsb(); | ||
| 164 | flush_cache_all(); | ||
| 165 | |||
| 166 | /* disable cache coherency */ | ||
| 167 | scu_power_mode(shmobile_scu_base, SCU_PM_POWEROFF); | ||
| 168 | |||
| 169 | /* Endless loop until power off from r8a7779_cpu_kill() */ | ||
| 170 | while (1) | ||
| 171 | cpu_do_idle(); | ||
| 172 | } | ||
| 173 | |||
| 174 | static int r8a7779_cpu_disable(unsigned int cpu) | ||
| 175 | { | ||
| 176 | /* only CPU1->3 have power domains, do not allow hotplug of CPU0 */ | ||
| 177 | return cpu == 0 ? -EPERM : 0; | ||
| 184 | } | 178 | } |
| 179 | #endif /* CONFIG_HOTPLUG_CPU */ | ||
| 185 | 180 | ||
| 186 | struct smp_operations r8a7779_smp_ops __initdata = { | 181 | struct smp_operations r8a7779_smp_ops __initdata = { |
| 187 | .smp_init_cpus = r8a7779_smp_init_cpus, | 182 | .smp_init_cpus = r8a7779_smp_init_cpus, |
| @@ -190,7 +185,7 @@ struct smp_operations r8a7779_smp_ops __initdata = { | |||
| 190 | .smp_boot_secondary = r8a7779_boot_secondary, | 185 | .smp_boot_secondary = r8a7779_boot_secondary, |
| 191 | #ifdef CONFIG_HOTPLUG_CPU | 186 | #ifdef CONFIG_HOTPLUG_CPU |
| 192 | .cpu_kill = r8a7779_cpu_kill, | 187 | .cpu_kill = r8a7779_cpu_kill, |
| 193 | .cpu_die = shmobile_cpu_die, | 188 | .cpu_die = r8a7779_cpu_die, |
| 194 | .cpu_disable = shmobile_cpu_disable, | 189 | .cpu_disable = r8a7779_cpu_disable, |
| 195 | #endif | 190 | #endif |
| 196 | }; | 191 | }; |
diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c index acb46a94ccdf..5ae502b16437 100644 --- a/arch/arm/mach-shmobile/smp-sh73a0.c +++ b/arch/arm/mach-shmobile/smp-sh73a0.c | |||
| @@ -39,26 +39,16 @@ | |||
| 39 | 39 | ||
| 40 | #define PSTR_SHUTDOWN_MODE 3 | 40 | #define PSTR_SHUTDOWN_MODE 3 |
| 41 | 41 | ||
| 42 | static void __iomem *scu_base_addr(void) | 42 | #define SH73A0_SCU_BASE 0xf0000000 |
| 43 | { | ||
| 44 | return (void __iomem *)0xf0000000; | ||
| 45 | } | ||
| 46 | 43 | ||
| 47 | #ifdef CONFIG_HAVE_ARM_TWD | 44 | #ifdef CONFIG_HAVE_ARM_TWD |
| 48 | static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29); | 45 | static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, SH73A0_SCU_BASE + 0x600, 29); |
| 49 | void __init sh73a0_register_twd(void) | 46 | void __init sh73a0_register_twd(void) |
| 50 | { | 47 | { |
| 51 | twd_local_timer_register(&twd_local_timer); | 48 | twd_local_timer_register(&twd_local_timer); |
| 52 | } | 49 | } |
| 53 | #endif | 50 | #endif |
| 54 | 51 | ||
| 55 | static unsigned int __init sh73a0_get_core_count(void) | ||
| 56 | { | ||
| 57 | void __iomem *scu_base = scu_base_addr(); | ||
| 58 | |||
| 59 | return scu_get_core_count(scu_base); | ||
| 60 | } | ||
| 61 | |||
| 62 | static void __cpuinit sh73a0_secondary_init(unsigned int cpu) | 52 | static void __cpuinit sh73a0_secondary_init(unsigned int cpu) |
| 63 | { | 53 | { |
| 64 | gic_secondary_init(0); | 54 | gic_secondary_init(0); |
| @@ -78,21 +68,22 @@ static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct | |||
| 78 | 68 | ||
| 79 | static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus) | 69 | static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus) |
| 80 | { | 70 | { |
| 81 | scu_enable(scu_base_addr()); | 71 | scu_enable(shmobile_scu_base); |
| 82 | 72 | ||
| 83 | /* Map the reset vector (in headsmp-sh73a0.S) */ | 73 | /* Map the reset vector (in headsmp-scu.S) */ |
| 84 | __raw_writel(0, APARMBAREA); /* 4k */ | 74 | __raw_writel(0, APARMBAREA); /* 4k */ |
| 85 | __raw_writel(__pa(sh73a0_secondary_vector), SBAR); | 75 | __raw_writel(__pa(shmobile_secondary_vector_scu), SBAR); |
| 86 | 76 | ||
| 87 | /* enable cache coherency on booting CPU */ | 77 | /* enable cache coherency on booting CPU */ |
| 88 | scu_power_mode(scu_base_addr(), SCU_PM_NORMAL); | 78 | scu_power_mode(shmobile_scu_base, SCU_PM_NORMAL); |
| 89 | } | 79 | } |
| 90 | 80 | ||
| 91 | static void __init sh73a0_smp_init_cpus(void) | 81 | static void __init sh73a0_smp_init_cpus(void) |
| 92 | { | 82 | { |
| 93 | unsigned int ncores = sh73a0_get_core_count(); | 83 | /* setup sh73a0 specific SCU base */ |
| 84 | shmobile_scu_base = IOMEM(SH73A0_SCU_BASE); | ||
| 94 | 85 | ||
| 95 | shmobile_smp_init_cpus(ncores); | 86 | shmobile_smp_init_cpus(scu_get_core_count(shmobile_scu_base)); |
| 96 | } | 87 | } |
| 97 | 88 | ||
| 98 | #ifdef CONFIG_HOTPLUG_CPU | 89 | #ifdef CONFIG_HOTPLUG_CPU |
| @@ -128,11 +119,16 @@ static void sh73a0_cpu_die(unsigned int cpu) | |||
| 128 | flush_cache_all(); | 119 | flush_cache_all(); |
| 129 | 120 | ||
| 130 | /* Set power off mode. This takes the CPU out of the MP cluster */ | 121 | /* Set power off mode. This takes the CPU out of the MP cluster */ |
| 131 | scu_power_mode(scu_base_addr(), SCU_PM_POWEROFF); | 122 | scu_power_mode(shmobile_scu_base, SCU_PM_POWEROFF); |
| 132 | 123 | ||
| 133 | /* Enter shutdown mode */ | 124 | /* Enter shutdown mode */ |
| 134 | cpu_do_idle(); | 125 | cpu_do_idle(); |
| 135 | } | 126 | } |
| 127 | |||
| 128 | static int sh73a0_cpu_disable(unsigned int cpu) | ||
| 129 | { | ||
| 130 | return 0; /* CPU0 and CPU1 supported */ | ||
| 131 | } | ||
| 136 | #endif /* CONFIG_HOTPLUG_CPU */ | 132 | #endif /* CONFIG_HOTPLUG_CPU */ |
| 137 | 133 | ||
| 138 | struct smp_operations sh73a0_smp_ops __initdata = { | 134 | struct smp_operations sh73a0_smp_ops __initdata = { |
| @@ -143,6 +139,6 @@ struct smp_operations sh73a0_smp_ops __initdata = { | |||
| 143 | #ifdef CONFIG_HOTPLUG_CPU | 139 | #ifdef CONFIG_HOTPLUG_CPU |
| 144 | .cpu_kill = sh73a0_cpu_kill, | 140 | .cpu_kill = sh73a0_cpu_kill, |
| 145 | .cpu_die = sh73a0_cpu_die, | 141 | .cpu_die = sh73a0_cpu_die, |
| 146 | .cpu_disable = shmobile_cpu_disable_any, | 142 | .cpu_disable = sh73a0_cpu_disable, |
| 147 | #endif | 143 | #endif |
| 148 | }; | 144 | }; |
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index a350969e5efe..4a33351c25dc 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig | |||
| @@ -25,6 +25,14 @@ config ARM_VIC_NR | |||
| 25 | The maximum number of VICs available in the system, for | 25 | The maximum number of VICs available in the system, for |
| 26 | power management. | 26 | power management. |
| 27 | 27 | ||
| 28 | config RENESAS_INTC_IRQPIN | ||
| 29 | bool | ||
| 30 | select IRQ_DOMAIN | ||
| 31 | |||
| 32 | config RENESAS_IRQC | ||
| 33 | bool | ||
| 34 | select IRQ_DOMAIN | ||
| 35 | |||
| 28 | config VERSATILE_FPGA_IRQ | 36 | config VERSATILE_FPGA_IRQ |
| 29 | bool | 37 | bool |
| 30 | select IRQ_DOMAIN | 38 | select IRQ_DOMAIN |
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 98e3b87bdf1b..e41ceb9bec22 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile | |||
| @@ -8,4 +8,6 @@ obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi.o | |||
| 8 | obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o | 8 | obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o |
| 9 | obj-$(CONFIG_ARM_GIC) += irq-gic.o | 9 | obj-$(CONFIG_ARM_GIC) += irq-gic.o |
| 10 | obj-$(CONFIG_ARM_VIC) += irq-vic.o | 10 | obj-$(CONFIG_ARM_VIC) += irq-vic.o |
| 11 | obj-$(CONFIG_RENESAS_INTC_IRQPIN) += irq-renesas-intc-irqpin.o | ||
| 12 | obj-$(CONFIG_RENESAS_IRQC) += irq-renesas-irqc.o | ||
| 11 | obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o | 13 | obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o |
diff --git a/drivers/irqchip/irq-renesas-intc-irqpin.c b/drivers/irqchip/irq-renesas-intc-irqpin.c new file mode 100644 index 000000000000..fd5dabc2235d --- /dev/null +++ b/drivers/irqchip/irq-renesas-intc-irqpin.c | |||
| @@ -0,0 +1,471 @@ | |||
| 1 | /* | ||
| 2 | * Renesas INTC External IRQ Pin Driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Magnus Damm | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/init.h> | ||
| 21 | #include <linux/platform_device.h> | ||
| 22 | #include <linux/spinlock.h> | ||
| 23 | #include <linux/interrupt.h> | ||
| 24 | #include <linux/ioport.h> | ||
| 25 | #include <linux/io.h> | ||
| 26 | #include <linux/irq.h> | ||
| 27 | #include <linux/irqdomain.h> | ||
| 28 | #include <linux/err.h> | ||
| 29 | #include <linux/slab.h> | ||
| 30 | #include <linux/module.h> | ||
| 31 | #include <linux/platform_data/irq-renesas-intc-irqpin.h> | ||
| 32 | |||
| 33 | #define INTC_IRQPIN_MAX 8 /* maximum 8 interrupts per driver instance */ | ||
| 34 | |||
| 35 | #define INTC_IRQPIN_REG_SENSE 0 /* ICRn */ | ||
| 36 | #define INTC_IRQPIN_REG_PRIO 1 /* INTPRInn */ | ||
| 37 | #define INTC_IRQPIN_REG_SOURCE 2 /* INTREQnn */ | ||
| 38 | #define INTC_IRQPIN_REG_MASK 3 /* INTMSKnn */ | ||
| 39 | #define INTC_IRQPIN_REG_CLEAR 4 /* INTMSKCLRnn */ | ||
| 40 | #define INTC_IRQPIN_REG_NR 5 | ||
| 41 | |||
| 42 | /* INTC external IRQ PIN hardware register access: | ||
| 43 | * | ||
| 44 | * SENSE is read-write 32-bit with 2-bits or 4-bits per IRQ (*) | ||
| 45 | * PRIO is read-write 32-bit with 4-bits per IRQ (**) | ||
| 46 | * SOURCE is read-only 32-bit or 8-bit with 1-bit per IRQ (***) | ||
| 47 | * MASK is write-only 32-bit or 8-bit with 1-bit per IRQ (***) | ||
| 48 | * CLEAR is write-only 32-bit or 8-bit with 1-bit per IRQ (***) | ||
| 49 | * | ||
| 50 | * (*) May be accessed by more than one driver instance - lock needed | ||
| 51 | * (**) Read-modify-write access by one driver instance - lock needed | ||
| 52 | * (***) Accessed by one driver instance only - no locking needed | ||
| 53 | */ | ||
| 54 | |||
| 55 | struct intc_irqpin_iomem { | ||
| 56 | void __iomem *iomem; | ||
| 57 | unsigned long (*read)(void __iomem *iomem); | ||
| 58 | void (*write)(void __iomem *iomem, unsigned long data); | ||
| 59 | int width; | ||
| 60 | }; | ||
| 61 | |||
| 62 | struct intc_irqpin_irq { | ||
| 63 | int hw_irq; | ||
| 64 | int requested_irq; | ||
| 65 | int domain_irq; | ||
| 66 | struct intc_irqpin_priv *p; | ||
| 67 | }; | ||
| 68 | |||
| 69 | struct intc_irqpin_priv { | ||
| 70 | struct intc_irqpin_iomem iomem[INTC_IRQPIN_REG_NR]; | ||
| 71 | struct intc_irqpin_irq irq[INTC_IRQPIN_MAX]; | ||
| 72 | struct renesas_intc_irqpin_config config; | ||
| 73 | unsigned int number_of_irqs; | ||
| 74 | struct platform_device *pdev; | ||
| 75 | struct irq_chip irq_chip; | ||
| 76 | struct irq_domain *irq_domain; | ||
| 77 | }; | ||
| 78 | |||
| 79 | static unsigned long intc_irqpin_read32(void __iomem *iomem) | ||
| 80 | { | ||
| 81 | return ioread32(iomem); | ||
| 82 | } | ||
| 83 | |||
| 84 | static unsigned long intc_irqpin_read8(void __iomem *iomem) | ||
| 85 | { | ||
| 86 | return ioread8(iomem); | ||
| 87 | } | ||
| 88 | |||
| 89 | static void intc_irqpin_write32(void __iomem *iomem, unsigned long data) | ||
| 90 | { | ||
| 91 | iowrite32(data, iomem); | ||
| 92 | } | ||
| 93 | |||
| 94 | static void intc_irqpin_write8(void __iomem *iomem, unsigned long data) | ||
| 95 | { | ||
| 96 | iowrite8(data, iomem); | ||
| 97 | } | ||
| 98 | |||
| 99 | static inline unsigned long intc_irqpin_read(struct intc_irqpin_priv *p, | ||
| 100 | int reg) | ||
| 101 | { | ||
| 102 | struct intc_irqpin_iomem *i = &p->iomem[reg]; | ||
| 103 | |||
| 104 | return i->read(i->iomem); | ||
| 105 | } | ||
| 106 | |||
| 107 | static inline void intc_irqpin_write(struct intc_irqpin_priv *p, | ||
| 108 | int reg, unsigned long data) | ||
| 109 | { | ||
| 110 | struct intc_irqpin_iomem *i = &p->iomem[reg]; | ||
| 111 | |||
| 112 | i->write(i->iomem, data); | ||
| 113 | } | ||
| 114 | |||
| 115 | static inline unsigned long intc_irqpin_hwirq_mask(struct intc_irqpin_priv *p, | ||
| 116 | int reg, int hw_irq) | ||
| 117 | { | ||
| 118 | return BIT((p->iomem[reg].width - 1) - hw_irq); | ||
| 119 | } | ||
| 120 | |||
| 121 | static inline void intc_irqpin_irq_write_hwirq(struct intc_irqpin_priv *p, | ||
| 122 | int reg, int hw_irq) | ||
| 123 | { | ||
| 124 | intc_irqpin_write(p, reg, intc_irqpin_hwirq_mask(p, reg, hw_irq)); | ||
| 125 | } | ||
| 126 | |||
| 127 | static DEFINE_RAW_SPINLOCK(intc_irqpin_lock); /* only used by slow path */ | ||
| 128 | |||
| 129 | static void intc_irqpin_read_modify_write(struct intc_irqpin_priv *p, | ||
| 130 | int reg, int shift, | ||
| 131 | int width, int value) | ||
| 132 | { | ||
| 133 | unsigned long flags; | ||
| 134 | unsigned long tmp; | ||
| 135 | |||
| 136 | raw_spin_lock_irqsave(&intc_irqpin_lock, flags); | ||
| 137 | |||
| 138 | tmp = intc_irqpin_read(p, reg); | ||
| 139 | tmp &= ~(((1 << width) - 1) << shift); | ||
| 140 | tmp |= value << shift; | ||
| 141 | intc_irqpin_write(p, reg, tmp); | ||
| 142 | |||
| 143 | raw_spin_unlock_irqrestore(&intc_irqpin_lock, flags); | ||
| 144 | } | ||
| 145 | |||
| 146 | static void intc_irqpin_mask_unmask_prio(struct intc_irqpin_priv *p, | ||
| 147 | int irq, int do_mask) | ||
| 148 | { | ||
| 149 | int bitfield_width = 4; /* PRIO assumed to have fixed bitfield width */ | ||
| 150 | int shift = (7 - irq) * bitfield_width; /* PRIO assumed to be 32-bit */ | ||
| 151 | |||
| 152 | intc_irqpin_read_modify_write(p, INTC_IRQPIN_REG_PRIO, | ||
| 153 | shift, bitfield_width, | ||
| 154 | do_mask ? 0 : (1 << bitfield_width) - 1); | ||
| 155 | } | ||
| 156 | |||
| 157 | static int intc_irqpin_set_sense(struct intc_irqpin_priv *p, int irq, int value) | ||
| 158 | { | ||
| 159 | int bitfield_width = p->config.sense_bitfield_width; | ||
| 160 | int shift = (7 - irq) * bitfield_width; /* SENSE assumed to be 32-bit */ | ||
| 161 | |||
| 162 | dev_dbg(&p->pdev->dev, "sense irq = %d, mode = %d\n", irq, value); | ||
| 163 | |||
| 164 | if (value >= (1 << bitfield_width)) | ||
| 165 | return -EINVAL; | ||
| 166 | |||
| 167 | intc_irqpin_read_modify_write(p, INTC_IRQPIN_REG_SENSE, shift, | ||
| 168 | bitfield_width, value); | ||
| 169 | return 0; | ||
| 170 | } | ||
| 171 | |||
| 172 | static void intc_irqpin_dbg(struct intc_irqpin_irq *i, char *str) | ||
| 173 | { | ||
| 174 | dev_dbg(&i->p->pdev->dev, "%s (%d:%d:%d)\n", | ||
| 175 | str, i->requested_irq, i->hw_irq, i->domain_irq); | ||
| 176 | } | ||
| 177 | |||
| 178 | static void intc_irqpin_irq_enable(struct irq_data *d) | ||
| 179 | { | ||
| 180 | struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d); | ||
| 181 | int hw_irq = irqd_to_hwirq(d); | ||
| 182 | |||
| 183 | intc_irqpin_dbg(&p->irq[hw_irq], "enable"); | ||
| 184 | intc_irqpin_irq_write_hwirq(p, INTC_IRQPIN_REG_CLEAR, hw_irq); | ||
| 185 | } | ||
| 186 | |||
| 187 | static void intc_irqpin_irq_disable(struct irq_data *d) | ||
| 188 | { | ||
| 189 | struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d); | ||
| 190 | int hw_irq = irqd_to_hwirq(d); | ||
| 191 | |||
| 192 | intc_irqpin_dbg(&p->irq[hw_irq], "disable"); | ||
| 193 | intc_irqpin_irq_write_hwirq(p, INTC_IRQPIN_REG_MASK, hw_irq); | ||
| 194 | } | ||
| 195 | |||
| 196 | static void intc_irqpin_irq_enable_force(struct irq_data *d) | ||
| 197 | { | ||
| 198 | struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d); | ||
| 199 | int irq = p->irq[irqd_to_hwirq(d)].requested_irq; | ||
| 200 | |||
| 201 | intc_irqpin_irq_enable(d); | ||
| 202 | |||
| 203 | /* enable interrupt through parent interrupt controller, | ||
| 204 | * assumes non-shared interrupt with 1:1 mapping | ||
| 205 | * needed for busted IRQs on some SoCs like sh73a0 | ||
| 206 | */ | ||
| 207 | irq_get_chip(irq)->irq_unmask(irq_get_irq_data(irq)); | ||
| 208 | } | ||
| 209 | |||
| 210 | static void intc_irqpin_irq_disable_force(struct irq_data *d) | ||
| 211 | { | ||
| 212 | struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d); | ||
| 213 | int irq = p->irq[irqd_to_hwirq(d)].requested_irq; | ||
| 214 | |||
| 215 | /* disable interrupt through parent interrupt controller, | ||
| 216 | * assumes non-shared interrupt with 1:1 mapping | ||
| 217 | * needed for busted IRQs on some SoCs like sh73a0 | ||
| 218 | */ | ||
| 219 | irq_get_chip(irq)->irq_mask(irq_get_irq_data(irq)); | ||
| 220 | intc_irqpin_irq_disable(d); | ||
| 221 | } | ||
| 222 | |||
| 223 | #define INTC_IRQ_SENSE_VALID 0x10 | ||
| 224 | #define INTC_IRQ_SENSE(x) (x + INTC_IRQ_SENSE_VALID) | ||
| 225 | |||
| 226 | static unsigned char intc_irqpin_sense[IRQ_TYPE_SENSE_MASK + 1] = { | ||
| 227 | [IRQ_TYPE_EDGE_FALLING] = INTC_IRQ_SENSE(0x00), | ||
| 228 | [IRQ_TYPE_EDGE_RISING] = INTC_IRQ_SENSE(0x01), | ||
| 229 | [IRQ_TYPE_LEVEL_LOW] = INTC_IRQ_SENSE(0x02), | ||
| 230 | [IRQ_TYPE_LEVEL_HIGH] = INTC_IRQ_SENSE(0x03), | ||
| 231 | [IRQ_TYPE_EDGE_BOTH] = INTC_IRQ_SENSE(0x04), | ||
| 232 | }; | ||
| 233 | |||
| 234 | static int intc_irqpin_irq_set_type(struct irq_data *d, unsigned int type) | ||
| 235 | { | ||
| 236 | unsigned char value = intc_irqpin_sense[type & IRQ_TYPE_SENSE_MASK]; | ||
| 237 | struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d); | ||
| 238 | |||
| 239 | if (!(value & INTC_IRQ_SENSE_VALID)) | ||
| 240 | return -EINVAL; | ||
| 241 | |||
| 242 | return intc_irqpin_set_sense(p, irqd_to_hwirq(d), | ||
| 243 | value ^ INTC_IRQ_SENSE_VALID); | ||
| 244 | } | ||
| 245 | |||
| 246 | static irqreturn_t intc_irqpin_irq_handler(int irq, void *dev_id) | ||
| 247 | { | ||
| 248 | struct intc_irqpin_irq *i = dev_id; | ||
| 249 | struct intc_irqpin_priv *p = i->p; | ||
| 250 | unsigned long bit; | ||
| 251 | |||
| 252 | intc_irqpin_dbg(i, "demux1"); | ||
| 253 | bit = intc_irqpin_hwirq_mask(p, INTC_IRQPIN_REG_SOURCE, i->hw_irq); | ||
| 254 | |||
| 255 | if (intc_irqpin_read(p, INTC_IRQPIN_REG_SOURCE) & bit) { | ||
| 256 | intc_irqpin_write(p, INTC_IRQPIN_REG_SOURCE, ~bit); | ||
| 257 | intc_irqpin_dbg(i, "demux2"); | ||
| 258 | generic_handle_irq(i->domain_irq); | ||
| 259 | return IRQ_HANDLED; | ||
| 260 | } | ||
| 261 | return IRQ_NONE; | ||
| 262 | } | ||
| 263 | |||
| 264 | static int intc_irqpin_irq_domain_map(struct irq_domain *h, unsigned int virq, | ||
| 265 | irq_hw_number_t hw) | ||
| 266 | { | ||
| 267 | struct intc_irqpin_priv *p = h->host_data; | ||
| 268 | |||
| 269 | p->irq[hw].domain_irq = virq; | ||
| 270 | p->irq[hw].hw_irq = hw; | ||
| 271 | |||
| 272 | intc_irqpin_dbg(&p->irq[hw], "map"); | ||
| 273 | irq_set_chip_data(virq, h->host_data); | ||
| 274 | irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq); | ||
| 275 | set_irq_flags(virq, IRQF_VALID); /* kill me now */ | ||
| 276 | return 0; | ||
| 277 | } | ||
| 278 | |||
| 279 | static struct irq_domain_ops intc_irqpin_irq_domain_ops = { | ||
| 280 | .map = intc_irqpin_irq_domain_map, | ||
| 281 | .xlate = irq_domain_xlate_twocell, | ||
| 282 | }; | ||
| 283 | |||
| 284 | static int intc_irqpin_probe(struct platform_device *pdev) | ||
| 285 | { | ||
| 286 | struct renesas_intc_irqpin_config *pdata = pdev->dev.platform_data; | ||
| 287 | struct intc_irqpin_priv *p; | ||
| 288 | struct intc_irqpin_iomem *i; | ||
| 289 | struct resource *io[INTC_IRQPIN_REG_NR]; | ||
| 290 | struct resource *irq; | ||
| 291 | struct irq_chip *irq_chip; | ||
| 292 | void (*enable_fn)(struct irq_data *d); | ||
| 293 | void (*disable_fn)(struct irq_data *d); | ||
| 294 | const char *name = dev_name(&pdev->dev); | ||
| 295 | int ret; | ||
| 296 | int k; | ||
| 297 | |||
| 298 | p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); | ||
| 299 | if (!p) { | ||
| 300 | dev_err(&pdev->dev, "failed to allocate driver data\n"); | ||
| 301 | ret = -ENOMEM; | ||
| 302 | goto err0; | ||
| 303 | } | ||
| 304 | |||
| 305 | /* deal with driver instance configuration */ | ||
| 306 | if (pdata) | ||
| 307 | memcpy(&p->config, pdata, sizeof(*pdata)); | ||
| 308 | if (!p->config.sense_bitfield_width) | ||
| 309 | p->config.sense_bitfield_width = 4; /* default to 4 bits */ | ||
| 310 | |||
| 311 | p->pdev = pdev; | ||
| 312 | platform_set_drvdata(pdev, p); | ||
| 313 | |||
| 314 | /* get hold of manadatory IOMEM */ | ||
| 315 | for (k = 0; k < INTC_IRQPIN_REG_NR; k++) { | ||
| 316 | io[k] = platform_get_resource(pdev, IORESOURCE_MEM, k); | ||
| 317 | if (!io[k]) { | ||
| 318 | dev_err(&pdev->dev, "not enough IOMEM resources\n"); | ||
| 319 | ret = -EINVAL; | ||
| 320 | goto err0; | ||
| 321 | } | ||
| 322 | } | ||
| 323 | |||
| 324 | /* allow any number of IRQs between 1 and INTC_IRQPIN_MAX */ | ||
| 325 | for (k = 0; k < INTC_IRQPIN_MAX; k++) { | ||
| 326 | irq = platform_get_resource(pdev, IORESOURCE_IRQ, k); | ||
| 327 | if (!irq) | ||
| 328 | break; | ||
| 329 | |||
| 330 | p->irq[k].p = p; | ||
| 331 | p->irq[k].requested_irq = irq->start; | ||
| 332 | } | ||
| 333 | |||
| 334 | p->number_of_irqs = k; | ||
| 335 | if (p->number_of_irqs < 1) { | ||
| 336 | dev_err(&pdev->dev, "not enough IRQ resources\n"); | ||
| 337 | ret = -EINVAL; | ||
| 338 | goto err0; | ||
| 339 | } | ||
| 340 | |||
| 341 | /* ioremap IOMEM and setup read/write callbacks */ | ||
| 342 | for (k = 0; k < INTC_IRQPIN_REG_NR; k++) { | ||
| 343 | i = &p->iomem[k]; | ||
| 344 | |||
| 345 | switch (resource_size(io[k])) { | ||
| 346 | case 1: | ||
| 347 | i->width = 8; | ||
| 348 | i->read = intc_irqpin_read8; | ||
| 349 | i->write = intc_irqpin_write8; | ||
| 350 | break; | ||
| 351 | case 4: | ||
| 352 | i->width = 32; | ||
| 353 | i->read = intc_irqpin_read32; | ||
| 354 | i->write = intc_irqpin_write32; | ||
| 355 | break; | ||
| 356 | default: | ||
| 357 | dev_err(&pdev->dev, "IOMEM size mismatch\n"); | ||
| 358 | ret = -EINVAL; | ||
| 359 | goto err0; | ||
| 360 | } | ||
| 361 | |||
| 362 | i->iomem = devm_ioremap_nocache(&pdev->dev, io[k]->start, | ||
| 363 | resource_size(io[k])); | ||
| 364 | if (!i->iomem) { | ||
| 365 | dev_err(&pdev->dev, "failed to remap IOMEM\n"); | ||
| 366 | ret = -ENXIO; | ||
| 367 | goto err0; | ||
| 368 | } | ||
| 369 | } | ||
| 370 | |||
| 371 | /* mask all interrupts using priority */ | ||
| 372 | for (k = 0; k < p->number_of_irqs; k++) | ||
| 373 | intc_irqpin_mask_unmask_prio(p, k, 1); | ||
| 374 | |||
| 375 | /* use more severe masking method if requested */ | ||
| 376 | if (p->config.control_parent) { | ||
| 377 | enable_fn = intc_irqpin_irq_enable_force; | ||
| 378 | disable_fn = intc_irqpin_irq_disable_force; | ||
| 379 | } else { | ||
| 380 | enable_fn = intc_irqpin_irq_enable; | ||
| 381 | disable_fn = intc_irqpin_irq_disable; | ||
| 382 | } | ||
| 383 | |||
| 384 | irq_chip = &p->irq_chip; | ||
| 385 | irq_chip->name = name; | ||
| 386 | irq_chip->irq_mask = disable_fn; | ||
| 387 | irq_chip->irq_unmask = enable_fn; | ||
| 388 | irq_chip->irq_enable = enable_fn; | ||
| 389 | irq_chip->irq_disable = disable_fn; | ||
| 390 | irq_chip->irq_set_type = intc_irqpin_irq_set_type; | ||
| 391 | irq_chip->flags = IRQCHIP_SKIP_SET_WAKE; | ||
| 392 | |||
| 393 | p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, | ||
| 394 | p->number_of_irqs, | ||
| 395 | p->config.irq_base, | ||
| 396 | &intc_irqpin_irq_domain_ops, p); | ||
| 397 | if (!p->irq_domain) { | ||
| 398 | ret = -ENXIO; | ||
| 399 | dev_err(&pdev->dev, "cannot initialize irq domain\n"); | ||
| 400 | goto err0; | ||
| 401 | } | ||
| 402 | |||
| 403 | /* request and set priority on interrupts one by one */ | ||
| 404 | for (k = 0; k < p->number_of_irqs; k++) { | ||
| 405 | if (devm_request_irq(&pdev->dev, p->irq[k].requested_irq, | ||
| 406 | intc_irqpin_irq_handler, | ||
| 407 | 0, name, &p->irq[k])) { | ||
| 408 | dev_err(&pdev->dev, "failed to request low IRQ\n"); | ||
| 409 | ret = -ENOENT; | ||
| 410 | goto err1; | ||
| 411 | } | ||
| 412 | intc_irqpin_mask_unmask_prio(p, k, 0); | ||
| 413 | } | ||
| 414 | |||
| 415 | dev_info(&pdev->dev, "driving %d irqs\n", p->number_of_irqs); | ||
| 416 | |||
| 417 | /* warn in case of mismatch if irq base is specified */ | ||
| 418 | if (p->config.irq_base) { | ||
| 419 | if (p->config.irq_base != p->irq[0].domain_irq) | ||
| 420 | dev_warn(&pdev->dev, "irq base mismatch (%d/%d)\n", | ||
| 421 | p->config.irq_base, p->irq[0].domain_irq); | ||
| 422 | } | ||
| 423 | |||
| 424 | return 0; | ||
| 425 | |||
| 426 | err1: | ||
| 427 | irq_domain_remove(p->irq_domain); | ||
| 428 | err0: | ||
| 429 | return ret; | ||
| 430 | } | ||
| 431 | |||
| 432 | static int intc_irqpin_remove(struct platform_device *pdev) | ||
| 433 | { | ||
| 434 | struct intc_irqpin_priv *p = platform_get_drvdata(pdev); | ||
| 435 | |||
| 436 | irq_domain_remove(p->irq_domain); | ||
| 437 | |||
| 438 | return 0; | ||
| 439 | } | ||
| 440 | |||
| 441 | static const struct of_device_id intc_irqpin_dt_ids[] = { | ||
| 442 | { .compatible = "renesas,intc-irqpin", }, | ||
| 443 | {}, | ||
| 444 | }; | ||
| 445 | MODULE_DEVICE_TABLE(of, intc_irqpin_dt_ids); | ||
| 446 | |||
| 447 | static struct platform_driver intc_irqpin_device_driver = { | ||
| 448 | .probe = intc_irqpin_probe, | ||
| 449 | .remove = intc_irqpin_remove, | ||
| 450 | .driver = { | ||
| 451 | .name = "renesas_intc_irqpin", | ||
| 452 | .of_match_table = intc_irqpin_dt_ids, | ||
| 453 | .owner = THIS_MODULE, | ||
| 454 | } | ||
| 455 | }; | ||
| 456 | |||
| 457 | static int __init intc_irqpin_init(void) | ||
| 458 | { | ||
| 459 | return platform_driver_register(&intc_irqpin_device_driver); | ||
| 460 | } | ||
| 461 | postcore_initcall(intc_irqpin_init); | ||
| 462 | |||
| 463 | static void __exit intc_irqpin_exit(void) | ||
| 464 | { | ||
| 465 | platform_driver_unregister(&intc_irqpin_device_driver); | ||
| 466 | } | ||
| 467 | module_exit(intc_irqpin_exit); | ||
| 468 | |||
| 469 | MODULE_AUTHOR("Magnus Damm"); | ||
| 470 | MODULE_DESCRIPTION("Renesas INTC External IRQ Pin Driver"); | ||
| 471 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/irqchip/irq-renesas-irqc.c b/drivers/irqchip/irq-renesas-irqc.c new file mode 100644 index 000000000000..927bff373aac --- /dev/null +++ b/drivers/irqchip/irq-renesas-irqc.c | |||
| @@ -0,0 +1,307 @@ | |||
| 1 | /* | ||
| 2 | * Renesas IRQC Driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Magnus Damm | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/init.h> | ||
| 21 | #include <linux/platform_device.h> | ||
| 22 | #include <linux/spinlock.h> | ||
| 23 | #include <linux/interrupt.h> | ||
| 24 | #include <linux/ioport.h> | ||
| 25 | #include <linux/io.h> | ||
| 26 | #include <linux/irq.h> | ||
| 27 | #include <linux/irqdomain.h> | ||
| 28 | #include <linux/err.h> | ||
| 29 | #include <linux/slab.h> | ||
| 30 | #include <linux/module.h> | ||
| 31 | #include <linux/platform_data/irq-renesas-irqc.h> | ||
| 32 | |||
| 33 | #define IRQC_IRQ_MAX 32 /* maximum 32 interrupts per driver instance */ | ||
| 34 | |||
| 35 | #define IRQC_REQ_STS 0x00 | ||
| 36 | #define IRQC_EN_STS 0x04 | ||
| 37 | #define IRQC_EN_SET 0x08 | ||
| 38 | #define IRQC_INT_CPU_BASE(n) (0x000 + ((n) * 0x10)) | ||
| 39 | #define DETECT_STATUS 0x100 | ||
| 40 | #define IRQC_CONFIG(n) (0x180 + ((n) * 0x04)) | ||
| 41 | |||
| 42 | struct irqc_irq { | ||
| 43 | int hw_irq; | ||
| 44 | int requested_irq; | ||
| 45 | int domain_irq; | ||
| 46 | struct irqc_priv *p; | ||
| 47 | }; | ||
| 48 | |||
| 49 | struct irqc_priv { | ||
| 50 | void __iomem *iomem; | ||
| 51 | void __iomem *cpu_int_base; | ||
| 52 | struct irqc_irq irq[IRQC_IRQ_MAX]; | ||
| 53 | struct renesas_irqc_config config; | ||
| 54 | unsigned int number_of_irqs; | ||
| 55 | struct platform_device *pdev; | ||
| 56 | struct irq_chip irq_chip; | ||
| 57 | struct irq_domain *irq_domain; | ||
| 58 | }; | ||
| 59 | |||
| 60 | static void irqc_dbg(struct irqc_irq *i, char *str) | ||
| 61 | { | ||
| 62 | dev_dbg(&i->p->pdev->dev, "%s (%d:%d:%d)\n", | ||
| 63 | str, i->requested_irq, i->hw_irq, i->domain_irq); | ||
| 64 | } | ||
| 65 | |||
| 66 | static void irqc_irq_enable(struct irq_data *d) | ||
| 67 | { | ||
| 68 | struct irqc_priv *p = irq_data_get_irq_chip_data(d); | ||
| 69 | int hw_irq = irqd_to_hwirq(d); | ||
| 70 | |||
| 71 | irqc_dbg(&p->irq[hw_irq], "enable"); | ||
| 72 | iowrite32(BIT(hw_irq), p->cpu_int_base + IRQC_EN_SET); | ||
| 73 | } | ||
| 74 | |||
| 75 | static void irqc_irq_disable(struct irq_data *d) | ||
| 76 | { | ||
| 77 | struct irqc_priv *p = irq_data_get_irq_chip_data(d); | ||
| 78 | int hw_irq = irqd_to_hwirq(d); | ||
| 79 | |||
| 80 | irqc_dbg(&p->irq[hw_irq], "disable"); | ||
| 81 | iowrite32(BIT(hw_irq), p->cpu_int_base + IRQC_EN_STS); | ||
| 82 | } | ||
| 83 | |||
| 84 | #define INTC_IRQ_SENSE_VALID 0x10 | ||
| 85 | #define INTC_IRQ_SENSE(x) (x + INTC_IRQ_SENSE_VALID) | ||
| 86 | |||
| 87 | static unsigned char irqc_sense[IRQ_TYPE_SENSE_MASK + 1] = { | ||
| 88 | [IRQ_TYPE_LEVEL_LOW] = INTC_IRQ_SENSE(0x01), | ||
| 89 | [IRQ_TYPE_LEVEL_HIGH] = INTC_IRQ_SENSE(0x02), | ||
| 90 | [IRQ_TYPE_EDGE_FALLING] = INTC_IRQ_SENSE(0x04), /* Synchronous */ | ||
| 91 | [IRQ_TYPE_EDGE_RISING] = INTC_IRQ_SENSE(0x08), /* Synchronous */ | ||
| 92 | [IRQ_TYPE_EDGE_BOTH] = INTC_IRQ_SENSE(0x0c), /* Synchronous */ | ||
| 93 | }; | ||
| 94 | |||
| 95 | static int irqc_irq_set_type(struct irq_data *d, unsigned int type) | ||
| 96 | { | ||
| 97 | struct irqc_priv *p = irq_data_get_irq_chip_data(d); | ||
| 98 | int hw_irq = irqd_to_hwirq(d); | ||
| 99 | unsigned char value = irqc_sense[type & IRQ_TYPE_SENSE_MASK]; | ||
| 100 | unsigned long tmp; | ||
| 101 | |||
| 102 | irqc_dbg(&p->irq[hw_irq], "sense"); | ||
| 103 | |||
| 104 | if (!(value & INTC_IRQ_SENSE_VALID)) | ||
| 105 | return -EINVAL; | ||
| 106 | |||
| 107 | tmp = ioread32(p->iomem + IRQC_CONFIG(hw_irq)); | ||
| 108 | tmp &= ~0x3f; | ||
| 109 | tmp |= value ^ INTC_IRQ_SENSE_VALID; | ||
| 110 | iowrite32(tmp, p->iomem + IRQC_CONFIG(hw_irq)); | ||
| 111 | return 0; | ||
| 112 | } | ||
| 113 | |||
| 114 | static irqreturn_t irqc_irq_handler(int irq, void *dev_id) | ||
| 115 | { | ||
| 116 | struct irqc_irq *i = dev_id; | ||
| 117 | struct irqc_priv *p = i->p; | ||
| 118 | unsigned long bit = BIT(i->hw_irq); | ||
| 119 | |||
| 120 | irqc_dbg(i, "demux1"); | ||
| 121 | |||
| 122 | if (ioread32(p->iomem + DETECT_STATUS) & bit) { | ||
| 123 | iowrite32(bit, p->iomem + DETECT_STATUS); | ||
| 124 | irqc_dbg(i, "demux2"); | ||
| 125 | generic_handle_irq(i->domain_irq); | ||
| 126 | return IRQ_HANDLED; | ||
| 127 | } | ||
| 128 | return IRQ_NONE; | ||
| 129 | } | ||
| 130 | |||
| 131 | static int irqc_irq_domain_map(struct irq_domain *h, unsigned int virq, | ||
| 132 | irq_hw_number_t hw) | ||
| 133 | { | ||
| 134 | struct irqc_priv *p = h->host_data; | ||
| 135 | |||
| 136 | p->irq[hw].domain_irq = virq; | ||
| 137 | p->irq[hw].hw_irq = hw; | ||
| 138 | |||
| 139 | irqc_dbg(&p->irq[hw], "map"); | ||
| 140 | irq_set_chip_data(virq, h->host_data); | ||
| 141 | irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq); | ||
| 142 | set_irq_flags(virq, IRQF_VALID); /* kill me now */ | ||
| 143 | return 0; | ||
| 144 | } | ||
| 145 | |||
| 146 | static struct irq_domain_ops irqc_irq_domain_ops = { | ||
| 147 | .map = irqc_irq_domain_map, | ||
| 148 | .xlate = irq_domain_xlate_twocell, | ||
| 149 | }; | ||
| 150 | |||
| 151 | static int irqc_probe(struct platform_device *pdev) | ||
| 152 | { | ||
| 153 | struct renesas_irqc_config *pdata = pdev->dev.platform_data; | ||
| 154 | struct irqc_priv *p; | ||
| 155 | struct resource *io; | ||
| 156 | struct resource *irq; | ||
| 157 | struct irq_chip *irq_chip; | ||
| 158 | const char *name = dev_name(&pdev->dev); | ||
| 159 | int ret; | ||
| 160 | int k; | ||
| 161 | |||
| 162 | p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
| 163 | if (!p) { | ||
| 164 | dev_err(&pdev->dev, "failed to allocate driver data\n"); | ||
| 165 | ret = -ENOMEM; | ||
| 166 | goto err0; | ||
| 167 | } | ||
| 168 | |||
| 169 | /* deal with driver instance configuration */ | ||
| 170 | if (pdata) | ||
| 171 | memcpy(&p->config, pdata, sizeof(*pdata)); | ||
| 172 | |||
| 173 | p->pdev = pdev; | ||
| 174 | platform_set_drvdata(pdev, p); | ||
| 175 | |||
| 176 | /* get hold of manadatory IOMEM */ | ||
| 177 | io = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 178 | if (!io) { | ||
| 179 | dev_err(&pdev->dev, "not enough IOMEM resources\n"); | ||
| 180 | ret = -EINVAL; | ||
| 181 | goto err1; | ||
| 182 | } | ||
| 183 | |||
| 184 | /* allow any number of IRQs between 1 and IRQC_IRQ_MAX */ | ||
| 185 | for (k = 0; k < IRQC_IRQ_MAX; k++) { | ||
| 186 | irq = platform_get_resource(pdev, IORESOURCE_IRQ, k); | ||
| 187 | if (!irq) | ||
| 188 | break; | ||
| 189 | |||
| 190 | p->irq[k].p = p; | ||
| 191 | p->irq[k].requested_irq = irq->start; | ||
| 192 | } | ||
| 193 | |||
| 194 | p->number_of_irqs = k; | ||
| 195 | if (p->number_of_irqs < 1) { | ||
| 196 | dev_err(&pdev->dev, "not enough IRQ resources\n"); | ||
| 197 | ret = -EINVAL; | ||
| 198 | goto err1; | ||
| 199 | } | ||
| 200 | |||
| 201 | /* ioremap IOMEM and setup read/write callbacks */ | ||
| 202 | p->iomem = ioremap_nocache(io->start, resource_size(io)); | ||
| 203 | if (!p->iomem) { | ||
| 204 | dev_err(&pdev->dev, "failed to remap IOMEM\n"); | ||
| 205 | ret = -ENXIO; | ||
| 206 | goto err2; | ||
| 207 | } | ||
| 208 | |||
| 209 | p->cpu_int_base = p->iomem + IRQC_INT_CPU_BASE(0); /* SYS-SPI */ | ||
| 210 | |||
| 211 | irq_chip = &p->irq_chip; | ||
| 212 | irq_chip->name = name; | ||
| 213 | irq_chip->irq_mask = irqc_irq_disable; | ||
| 214 | irq_chip->irq_unmask = irqc_irq_enable; | ||
| 215 | irq_chip->irq_enable = irqc_irq_enable; | ||
| 216 | irq_chip->irq_disable = irqc_irq_disable; | ||
| 217 | irq_chip->irq_set_type = irqc_irq_set_type; | ||
| 218 | irq_chip->flags = IRQCHIP_SKIP_SET_WAKE; | ||
| 219 | |||
| 220 | p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, | ||
| 221 | p->number_of_irqs, | ||
| 222 | p->config.irq_base, | ||
| 223 | &irqc_irq_domain_ops, p); | ||
| 224 | if (!p->irq_domain) { | ||
| 225 | ret = -ENXIO; | ||
| 226 | dev_err(&pdev->dev, "cannot initialize irq domain\n"); | ||
| 227 | goto err2; | ||
| 228 | } | ||
| 229 | |||
| 230 | /* request interrupts one by one */ | ||
| 231 | for (k = 0; k < p->number_of_irqs; k++) { | ||
| 232 | if (request_irq(p->irq[k].requested_irq, irqc_irq_handler, | ||
| 233 | 0, name, &p->irq[k])) { | ||
| 234 | dev_err(&pdev->dev, "failed to request IRQ\n"); | ||
| 235 | ret = -ENOENT; | ||
| 236 | goto err3; | ||
| 237 | } | ||
| 238 | } | ||
| 239 | |||
| 240 | dev_info(&pdev->dev, "driving %d irqs\n", p->number_of_irqs); | ||
| 241 | |||
| 242 | /* warn in case of mismatch if irq base is specified */ | ||
| 243 | if (p->config.irq_base) { | ||
| 244 | if (p->config.irq_base != p->irq[0].domain_irq) | ||
| 245 | dev_warn(&pdev->dev, "irq base mismatch (%d/%d)\n", | ||
| 246 | p->config.irq_base, p->irq[0].domain_irq); | ||
| 247 | } | ||
| 248 | |||
| 249 | return 0; | ||
| 250 | err3: | ||
| 251 | for (; k >= 0; k--) | ||
| 252 | free_irq(p->irq[k - 1].requested_irq, &p->irq[k - 1]); | ||
| 253 | |||
| 254 | irq_domain_remove(p->irq_domain); | ||
| 255 | err2: | ||
| 256 | iounmap(p->iomem); | ||
| 257 | err1: | ||
| 258 | kfree(p); | ||
| 259 | err0: | ||
| 260 | return ret; | ||
| 261 | } | ||
| 262 | |||
| 263 | static int irqc_remove(struct platform_device *pdev) | ||
| 264 | { | ||
| 265 | struct irqc_priv *p = platform_get_drvdata(pdev); | ||
| 266 | int k; | ||
| 267 | |||
| 268 | for (k = 0; k < p->number_of_irqs; k++) | ||
| 269 | free_irq(p->irq[k].requested_irq, &p->irq[k]); | ||
| 270 | |||
| 271 | irq_domain_remove(p->irq_domain); | ||
| 272 | iounmap(p->iomem); | ||
| 273 | kfree(p); | ||
| 274 | return 0; | ||
| 275 | } | ||
| 276 | |||
| 277 | static const struct of_device_id irqc_dt_ids[] = { | ||
| 278 | { .compatible = "renesas,irqc", }, | ||
| 279 | {}, | ||
| 280 | }; | ||
| 281 | MODULE_DEVICE_TABLE(of, irqc_dt_ids); | ||
| 282 | |||
| 283 | static struct platform_driver irqc_device_driver = { | ||
| 284 | .probe = irqc_probe, | ||
| 285 | .remove = irqc_remove, | ||
| 286 | .driver = { | ||
| 287 | .name = "renesas_irqc", | ||
| 288 | .of_match_table = irqc_dt_ids, | ||
| 289 | .owner = THIS_MODULE, | ||
| 290 | } | ||
| 291 | }; | ||
| 292 | |||
| 293 | static int __init irqc_init(void) | ||
| 294 | { | ||
| 295 | return platform_driver_register(&irqc_device_driver); | ||
| 296 | } | ||
| 297 | postcore_initcall(irqc_init); | ||
| 298 | |||
| 299 | static void __exit irqc_exit(void) | ||
| 300 | { | ||
| 301 | platform_driver_unregister(&irqc_device_driver); | ||
| 302 | } | ||
| 303 | module_exit(irqc_exit); | ||
| 304 | |||
| 305 | MODULE_AUTHOR("Magnus Damm"); | ||
| 306 | MODULE_DESCRIPTION("Renesas IRQC Driver"); | ||
| 307 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c index 709008e94124..6f15c03077a0 100644 --- a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c +++ b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c | |||
| @@ -2733,9 +2733,9 @@ static struct pinmux_data_reg pinmux_data_regs[] = { | |||
| 2733 | { }, | 2733 | { }, |
| 2734 | }; | 2734 | }; |
| 2735 | 2735 | ||
| 2736 | /* IRQ pins through INTCS with IRQ0->15 from 0x200 and IRQ16-31 from 0x3200 */ | 2736 | /* External IRQ pins mapped at IRQPIN_BASE */ |
| 2737 | #define EXT_IRQ16L(n) intcs_evt2irq(0x200 + ((n) << 5)) | 2737 | #define EXT_IRQ16L(n) irq_pin(n) |
| 2738 | #define EXT_IRQ16H(n) intcs_evt2irq(0x3200 + ((n - 16) << 5)) | 2738 | #define EXT_IRQ16H(n) irq_pin(n) |
| 2739 | 2739 | ||
| 2740 | static struct pinmux_irq pinmux_irqs[] = { | 2740 | static struct pinmux_irq pinmux_irqs[] = { |
| 2741 | PINMUX_IRQ(EXT_IRQ16H(19), PORT9_FN0), | 2741 | PINMUX_IRQ(EXT_IRQ16H(19), PORT9_FN0), |
diff --git a/include/linux/platform_data/irq-renesas-intc-irqpin.h b/include/linux/platform_data/irq-renesas-intc-irqpin.h new file mode 100644 index 000000000000..e4cb911066a6 --- /dev/null +++ b/include/linux/platform_data/irq-renesas-intc-irqpin.h | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | /* | ||
| 2 | * Renesas INTC External IRQ Pin Driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Magnus Damm | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 18 | */ | ||
| 19 | |||
| 20 | #ifndef __IRQ_RENESAS_INTC_IRQPIN_H__ | ||
| 21 | #define __IRQ_RENESAS_INTC_IRQPIN_H__ | ||
| 22 | |||
| 23 | struct renesas_intc_irqpin_config { | ||
| 24 | unsigned int sense_bitfield_width; | ||
| 25 | unsigned int irq_base; | ||
| 26 | bool control_parent; | ||
| 27 | }; | ||
| 28 | |||
| 29 | #endif /* __IRQ_RENESAS_INTC_IRQPIN_H__ */ | ||
diff --git a/include/linux/platform_data/irq-renesas-irqc.h b/include/linux/platform_data/irq-renesas-irqc.h new file mode 100644 index 000000000000..3ae17b3e00ed --- /dev/null +++ b/include/linux/platform_data/irq-renesas-irqc.h | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | /* | ||
| 2 | * Renesas IRQC Driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Magnus Damm | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 18 | */ | ||
| 19 | |||
| 20 | #ifndef __IRQ_RENESAS_IRQC_H__ | ||
| 21 | #define __IRQ_RENESAS_IRQC_H__ | ||
| 22 | |||
| 23 | struct renesas_irqc_config { | ||
| 24 | unsigned int irq_base; | ||
| 25 | }; | ||
| 26 | |||
| 27 | #endif /* __IRQ_RENESAS_IRQC_H__ */ | ||
