aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSergei Shtylyov <sergei.shtylyov@cogentembedded.com>2013-06-08 16:36:05 -0400
committerSimon Horman <horms+renesas@verge.net.au>2013-06-11 03:11:20 -0400
commit02474a41e6180521a2b9b30b84888670e290dba0 (patch)
tree45abf58f6de1ce997d95373859b428acb59bd496
parent54407f190c8d542572a9547ba5460d811810b6e4 (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/Kconfig2
-rw-r--r--arch/arm/mach-shmobile/clock-r8a7778.c4
-rw-r--r--arch/arm/mach-shmobile/include/mach/r8a7778.h3
-rw-r--r--arch/arm/mach-shmobile/setup-r8a7778.c108
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
45config ARCH_R8A7779 47config 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[] = {
105enum { 105enum {
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
24extern void r8a7778_add_standard_devices(void); 25extern void r8a7778_add_standard_devices(void);
25extern void r8a7778_add_standard_devices_dt(void); 26extern void r8a7778_add_standard_devices_dt(void);
26extern void r8a7778_add_ether_device(struct sh_eth_plat_data *pdata); 27extern void r8a7778_add_ether_device(struct sh_eth_plat_data *pdata);
28extern void r8a7778_add_usb_phy_device(struct rcar_phy_platform_data *pdata);
29extern void r8a7778_init_late(void);
27extern void r8a7778_init_delay(void); 30extern void r8a7778_init_delay(void);
28extern void r8a7778_init_irq(void); 31extern void r8a7778_init_irq(void);
29extern void r8a7778_init_irq_dt(void); 32extern 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 */
99static struct resource usb_phy_resources[] __initdata = {
100 DEFINE_RES_MEM(0xffe70800, 0x100),
101 DEFINE_RES_MEM(0xffe76000, 0x100),
102};
103
104void __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 */
113static struct usb_phy *phy;
114
115static 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
128static 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
139static 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
153static 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
160static struct resource ehci_resources[] __initdata = {
161 DEFINE_RES_MEM(0xffe70000, 0x400),
162 DEFINE_RES_IRQ(gic_iid(0x4c)),
163};
164
165static 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
171static 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) \
177static 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
188USB_PLATFORM_INFO(ehci);
189USB_PLATFORM_INFO(ohci);
190
92/* Ether */ 191/* Ether */
93static struct resource ether_resources[] = { 192static 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
299void __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
200static struct renesas_intc_irqpin_config irqpin_platform_data = { 307static 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,
313MACHINE_END 421MACHINE_END
314 422
315#endif /* CONFIG_USE_OF */ 423#endif /* CONFIG_USE_OF */