diff options
author | Sergei Shtylyov <sergei.shtylyov@cogentembedded.com> | 2013-06-08 16:36:05 -0400 |
---|---|---|
committer | Simon Horman <horms+renesas@verge.net.au> | 2013-06-11 03:11:20 -0400 |
commit | 02474a41e6180521a2b9b30b84888670e290dba0 (patch) | |
tree | 45abf58f6de1ce997d95373859b428acb59bd496 | |
parent | 54407f190c8d542572a9547ba5460d811810b6e4 (diff) |
ARM: shmobile: r8a7778: add USB support
Add USB clock and EHCI, OHCI, and USB PHY platform devices for R8A7778 SoC; add
a function to register PHY device with board-specific platform data and register
EHCI and OHCI platfrom devices from the init_late() board method.
Also, don't forget to enable CONFIG_ARCH_HAS_[EO]HCI options for R8A7778 SoC in
Kconfig...
The patch has been tested on the BOCK-W board.
Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
-rw-r--r-- | arch/arm/mach-shmobile/Kconfig | 2 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/clock-r8a7778.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/include/mach/r8a7778.h | 3 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/setup-r8a7778.c | 108 |
4 files changed, 117 insertions, 0 deletions
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 5414402938a5..757c4e97375f 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig | |||
@@ -41,6 +41,8 @@ config ARCH_R8A7778 | |||
41 | select CPU_V7 | 41 | select CPU_V7 |
42 | select SH_CLK_CPG | 42 | select SH_CLK_CPG |
43 | select ARM_GIC | 43 | select ARM_GIC |
44 | select USB_ARCH_HAS_EHCI | ||
45 | select USB_ARCH_HAS_OHCI | ||
44 | 46 | ||
45 | config ARCH_R8A7779 | 47 | config ARCH_R8A7779 |
46 | bool "R-Car H1 (R8A77790)" | 48 | bool "R-Car H1 (R8A77790)" |
diff --git a/arch/arm/mach-shmobile/clock-r8a7778.c b/arch/arm/mach-shmobile/clock-r8a7778.c index b251e4d0924d..696d206adc3f 100644 --- a/arch/arm/mach-shmobile/clock-r8a7778.c +++ b/arch/arm/mach-shmobile/clock-r8a7778.c | |||
@@ -105,6 +105,7 @@ static struct clk *main_clks[] = { | |||
105 | enum { | 105 | enum { |
106 | MSTP323, MSTP322, MSTP321, | 106 | MSTP323, MSTP322, MSTP321, |
107 | MSTP114, | 107 | MSTP114, |
108 | MSTP100, | ||
108 | MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021, | 109 | MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021, |
109 | MSTP016, MSTP015, | 110 | MSTP016, MSTP015, |
110 | MSTP_NR }; | 111 | MSTP_NR }; |
@@ -114,6 +115,7 @@ static struct clk mstp_clks[MSTP_NR] = { | |||
114 | [MSTP322] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 22, 0), /* SDHI1 */ | 115 | [MSTP322] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 22, 0), /* SDHI1 */ |
115 | [MSTP321] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 21, 0), /* SDHI2 */ | 116 | [MSTP321] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 21, 0), /* SDHI2 */ |
116 | [MSTP114] = SH_CLK_MSTP32(&p_clk, MSTPCR1, 14, 0), /* Ether */ | 117 | [MSTP114] = SH_CLK_MSTP32(&p_clk, MSTPCR1, 14, 0), /* Ether */ |
118 | [MSTP100] = SH_CLK_MSTP32(&p_clk, MSTPCR1, 0, 0), /* USB0/1 */ | ||
117 | [MSTP026] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 26, 0), /* SCIF0 */ | 119 | [MSTP026] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 26, 0), /* SCIF0 */ |
118 | [MSTP025] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 25, 0), /* SCIF1 */ | 120 | [MSTP025] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 25, 0), /* SCIF1 */ |
119 | [MSTP024] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 24, 0), /* SCIF2 */ | 121 | [MSTP024] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 24, 0), /* SCIF2 */ |
@@ -130,6 +132,8 @@ static struct clk_lookup lookups[] = { | |||
130 | CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP322]), /* SDHI1 */ | 132 | CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP322]), /* SDHI1 */ |
131 | CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP321]), /* SDHI2 */ | 133 | CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP321]), /* SDHI2 */ |
132 | CLKDEV_DEV_ID("sh-eth", &mstp_clks[MSTP114]), /* Ether */ | 134 | CLKDEV_DEV_ID("sh-eth", &mstp_clks[MSTP114]), /* Ether */ |
135 | CLKDEV_DEV_ID("ehci-platform", &mstp_clks[MSTP100]), /* USB EHCI port0/1 */ | ||
136 | CLKDEV_DEV_ID("ohci-platform", &mstp_clks[MSTP100]), /* USB OHCI port0/1 */ | ||
133 | CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP026]), /* SCIF0 */ | 137 | CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP026]), /* SCIF0 */ |
134 | CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP025]), /* SCIF1 */ | 138 | CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP025]), /* SCIF1 */ |
135 | CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP024]), /* SCIF2 */ | 139 | CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP024]), /* SCIF2 */ |
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7778.h b/arch/arm/mach-shmobile/include/mach/r8a7778.h index ae65b459483f..1d4207cc0b04 100644 --- a/arch/arm/mach-shmobile/include/mach/r8a7778.h +++ b/arch/arm/mach-shmobile/include/mach/r8a7778.h | |||
@@ -20,10 +20,13 @@ | |||
20 | 20 | ||
21 | #include <linux/mmc/sh_mobile_sdhi.h> | 21 | #include <linux/mmc/sh_mobile_sdhi.h> |
22 | #include <linux/sh_eth.h> | 22 | #include <linux/sh_eth.h> |
23 | #include <linux/platform_data/usb-rcar-phy.h> | ||
23 | 24 | ||
24 | extern void r8a7778_add_standard_devices(void); | 25 | extern void r8a7778_add_standard_devices(void); |
25 | extern void r8a7778_add_standard_devices_dt(void); | 26 | extern void r8a7778_add_standard_devices_dt(void); |
26 | extern void r8a7778_add_ether_device(struct sh_eth_plat_data *pdata); | 27 | extern void r8a7778_add_ether_device(struct sh_eth_plat_data *pdata); |
28 | extern void r8a7778_add_usb_phy_device(struct rcar_phy_platform_data *pdata); | ||
29 | extern void r8a7778_init_late(void); | ||
27 | extern void r8a7778_init_delay(void); | 30 | extern void r8a7778_init_delay(void); |
28 | extern void r8a7778_init_irq(void); | 31 | extern void r8a7778_init_irq(void); |
29 | extern void r8a7778_init_irq_dt(void); | 32 | extern void r8a7778_init_irq_dt(void); |
diff --git a/arch/arm/mach-shmobile/setup-r8a7778.c b/arch/arm/mach-shmobile/setup-r8a7778.c index 1b9b7f2a5016..f84885a71f6f 100644 --- a/arch/arm/mach-shmobile/setup-r8a7778.c +++ b/arch/arm/mach-shmobile/setup-r8a7778.c | |||
@@ -30,6 +30,12 @@ | |||
30 | #include <linux/irqchip.h> | 30 | #include <linux/irqchip.h> |
31 | #include <linux/serial_sci.h> | 31 | #include <linux/serial_sci.h> |
32 | #include <linux/sh_timer.h> | 32 | #include <linux/sh_timer.h> |
33 | #include <linux/pm_runtime.h> | ||
34 | #include <linux/usb/phy.h> | ||
35 | #include <linux/usb/hcd.h> | ||
36 | #include <linux/usb/ehci_pdriver.h> | ||
37 | #include <linux/usb/ohci_pdriver.h> | ||
38 | #include <linux/dma-mapping.h> | ||
33 | #include <mach/irqs.h> | 39 | #include <mach/irqs.h> |
34 | #include <mach/r8a7778.h> | 40 | #include <mach/r8a7778.h> |
35 | #include <mach/common.h> | 41 | #include <mach/common.h> |
@@ -89,6 +95,99 @@ static struct sh_timer_config sh_tmu1_platform_data = { | |||
89 | &sh_tmu##idx##_platform_data, \ | 95 | &sh_tmu##idx##_platform_data, \ |
90 | sizeof(sh_tmu##idx##_platform_data)) | 96 | sizeof(sh_tmu##idx##_platform_data)) |
91 | 97 | ||
98 | /* USB PHY */ | ||
99 | static struct resource usb_phy_resources[] __initdata = { | ||
100 | DEFINE_RES_MEM(0xffe70800, 0x100), | ||
101 | DEFINE_RES_MEM(0xffe76000, 0x100), | ||
102 | }; | ||
103 | |||
104 | void __init r8a7778_add_usb_phy_device(struct rcar_phy_platform_data *pdata) | ||
105 | { | ||
106 | platform_device_register_resndata(&platform_bus, "rcar_usb_phy", -1, | ||
107 | usb_phy_resources, | ||
108 | ARRAY_SIZE(usb_phy_resources), | ||
109 | pdata, sizeof(*pdata)); | ||
110 | } | ||
111 | |||
112 | /* USB */ | ||
113 | static struct usb_phy *phy; | ||
114 | |||
115 | static int usb_power_on(struct platform_device *pdev) | ||
116 | { | ||
117 | if (IS_ERR(phy)) | ||
118 | return PTR_ERR(phy); | ||
119 | |||
120 | pm_runtime_enable(&pdev->dev); | ||
121 | pm_runtime_get_sync(&pdev->dev); | ||
122 | |||
123 | usb_phy_init(phy); | ||
124 | |||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | static void usb_power_off(struct platform_device *pdev) | ||
129 | { | ||
130 | if (IS_ERR(phy)) | ||
131 | return; | ||
132 | |||
133 | usb_phy_shutdown(phy); | ||
134 | |||
135 | pm_runtime_put_sync(&pdev->dev); | ||
136 | pm_runtime_disable(&pdev->dev); | ||
137 | } | ||
138 | |||
139 | static int ehci_init_internal_buffer(struct usb_hcd *hcd) | ||
140 | { | ||
141 | /* | ||
142 | * Below are recommended values from the datasheet; | ||
143 | * see [USB :: Setting of EHCI Internal Buffer]. | ||
144 | */ | ||
145 | /* EHCI IP internal buffer setting */ | ||
146 | iowrite32(0x00ff0040, hcd->regs + 0x0094); | ||
147 | /* EHCI IP internal buffer enable */ | ||
148 | iowrite32(0x00000001, hcd->regs + 0x009C); | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static struct usb_ehci_pdata ehci_pdata __initdata = { | ||
154 | .power_on = usb_power_on, | ||
155 | .power_off = usb_power_off, | ||
156 | .power_suspend = usb_power_off, | ||
157 | .pre_setup = ehci_init_internal_buffer, | ||
158 | }; | ||
159 | |||
160 | static struct resource ehci_resources[] __initdata = { | ||
161 | DEFINE_RES_MEM(0xffe70000, 0x400), | ||
162 | DEFINE_RES_IRQ(gic_iid(0x4c)), | ||
163 | }; | ||
164 | |||
165 | static struct usb_ohci_pdata ohci_pdata __initdata = { | ||
166 | .power_on = usb_power_on, | ||
167 | .power_off = usb_power_off, | ||
168 | .power_suspend = usb_power_off, | ||
169 | }; | ||
170 | |||
171 | static struct resource ohci_resources[] __initdata = { | ||
172 | DEFINE_RES_MEM(0xffe70400, 0x400), | ||
173 | DEFINE_RES_IRQ(gic_iid(0x4c)), | ||
174 | }; | ||
175 | |||
176 | #define USB_PLATFORM_INFO(hci) \ | ||
177 | static struct platform_device_info hci##_info __initdata = { \ | ||
178 | .parent = &platform_bus, \ | ||
179 | .name = #hci "-platform", \ | ||
180 | .id = -1, \ | ||
181 | .res = hci##_resources, \ | ||
182 | .num_res = ARRAY_SIZE(hci##_resources), \ | ||
183 | .data = &hci##_pdata, \ | ||
184 | .size_data = sizeof(hci##_pdata), \ | ||
185 | .dma_mask = DMA_BIT_MASK(32), \ | ||
186 | } | ||
187 | |||
188 | USB_PLATFORM_INFO(ehci); | ||
189 | USB_PLATFORM_INFO(ohci); | ||
190 | |||
92 | /* Ether */ | 191 | /* Ether */ |
93 | static struct resource ether_resources[] = { | 192 | static struct resource ether_resources[] = { |
94 | DEFINE_RES_MEM(0xfde00000, 0x400), | 193 | DEFINE_RES_MEM(0xfde00000, 0x400), |
@@ -197,6 +296,14 @@ void __init r8a7778_add_standard_devices(void) | |||
197 | r8a7778_register_tmu(1); | 296 | r8a7778_register_tmu(1); |
198 | } | 297 | } |
199 | 298 | ||
299 | void __init r8a7778_init_late(void) | ||
300 | { | ||
301 | phy = usb_get_phy(USB_PHY_TYPE_USB2); | ||
302 | |||
303 | platform_device_register_full(&ehci_info); | ||
304 | platform_device_register_full(&ohci_info); | ||
305 | } | ||
306 | |||
200 | static struct renesas_intc_irqpin_config irqpin_platform_data = { | 307 | static struct renesas_intc_irqpin_config irqpin_platform_data = { |
201 | .irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */ | 308 | .irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */ |
202 | .sense_bitfield_width = 2, | 309 | .sense_bitfield_width = 2, |
@@ -310,6 +417,7 @@ DT_MACHINE_START(R8A7778_DT, "Generic R8A7778 (Flattened Device Tree)") | |||
310 | .init_machine = r8a7778_add_standard_devices_dt, | 417 | .init_machine = r8a7778_add_standard_devices_dt, |
311 | .init_time = shmobile_timer_init, | 418 | .init_time = shmobile_timer_init, |
312 | .dt_compat = r8a7778_compat_dt, | 419 | .dt_compat = r8a7778_compat_dt, |
420 | .init_late = r8a7778_init_late, | ||
313 | MACHINE_END | 421 | MACHINE_END |
314 | 422 | ||
315 | #endif /* CONFIG_USE_OF */ | 423 | #endif /* CONFIG_USE_OF */ |