diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2014-11-25 06:28:46 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-11-25 12:19:28 -0500 |
commit | 2193dda5eec60373c7a061c129c6ab9d658f78e9 (patch) | |
tree | c474b5df7c45575c22ec35be3f9f1f6574272530 | |
parent | f910b6cba27af4c5e1b0de1225a268448c2e82be (diff) |
USB: host: Remove ehci-octeon and ohci-octeon drivers
Remove special-purpose octeon drivers and instead use ehci-platform
and ohci-platform as suggested with
http://marc.info/?l=linux-mips&m=140139694721623&w=2
[andreas.herrmann:
fixed compile error]
Cc: David Daney <david.daney@cavium.com>
Cc: Alex Smith <alex.smith@imgtec.com>
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Andreas Herrmann <andreas.herrmann@caviumnetworks.com>
Acked-by: Ralf Baechle <ralf@linux-mips.org>
Tested-by: Aaro Koskinen <aaro.koskinen@iki.fi>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | arch/mips/cavium-octeon/octeon-platform.c | 274 | ||||
-rw-r--r-- | arch/mips/configs/cavium_octeon_defconfig | 3 | ||||
-rw-r--r-- | drivers/usb/host/Kconfig | 18 | ||||
-rw-r--r-- | drivers/usb/host/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 5 | ||||
-rw-r--r-- | drivers/usb/host/ehci-octeon.c | 182 | ||||
-rw-r--r-- | drivers/usb/host/octeon2-common.c | 200 | ||||
-rw-r--r-- | drivers/usb/host/ohci-hcd.c | 5 | ||||
-rw-r--r-- | drivers/usb/host/ohci-octeon.c | 196 |
9 files changed, 285 insertions, 599 deletions
diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c index 6df0f4d8f197..b67ddf0f8bcd 100644 --- a/arch/mips/cavium-octeon/octeon-platform.c +++ b/arch/mips/cavium-octeon/octeon-platform.c | |||
@@ -7,22 +7,27 @@ | |||
7 | * Copyright (C) 2008 Wind River Systems | 7 | * Copyright (C) 2008 Wind River Systems |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/delay.h> | ||
10 | #include <linux/init.h> | 11 | #include <linux/init.h> |
11 | #include <linux/irq.h> | 12 | #include <linux/irq.h> |
12 | #include <linux/i2c.h> | 13 | #include <linux/i2c.h> |
13 | #include <linux/usb.h> | 14 | #include <linux/usb.h> |
14 | #include <linux/dma-mapping.h> | 15 | #include <linux/dma-mapping.h> |
15 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/mutex.h> | ||
16 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
17 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
18 | #include <linux/of_platform.h> | 20 | #include <linux/of_platform.h> |
19 | #include <linux/of_fdt.h> | 21 | #include <linux/of_fdt.h> |
20 | #include <linux/libfdt.h> | 22 | #include <linux/libfdt.h> |
23 | #include <linux/usb/ehci_pdriver.h> | ||
24 | #include <linux/usb/ohci_pdriver.h> | ||
21 | 25 | ||
22 | #include <asm/octeon/octeon.h> | 26 | #include <asm/octeon/octeon.h> |
23 | #include <asm/octeon/cvmx-rnm-defs.h> | 27 | #include <asm/octeon/cvmx-rnm-defs.h> |
24 | #include <asm/octeon/cvmx-helper.h> | 28 | #include <asm/octeon/cvmx-helper.h> |
25 | #include <asm/octeon/cvmx-helper-board.h> | 29 | #include <asm/octeon/cvmx-helper-board.h> |
30 | #include <asm/octeon/cvmx-uctlx-defs.h> | ||
26 | 31 | ||
27 | /* Octeon Random Number Generator. */ | 32 | /* Octeon Random Number Generator. */ |
28 | static int __init octeon_rng_device_init(void) | 33 | static int __init octeon_rng_device_init(void) |
@@ -68,6 +73,229 @@ device_initcall(octeon_rng_device_init); | |||
68 | 73 | ||
69 | #ifdef CONFIG_USB | 74 | #ifdef CONFIG_USB |
70 | 75 | ||
76 | static DEFINE_MUTEX(octeon2_usb_clocks_mutex); | ||
77 | |||
78 | static int octeon2_usb_clock_start_cnt; | ||
79 | |||
80 | static void octeon2_usb_clocks_start(void) | ||
81 | { | ||
82 | u64 div; | ||
83 | union cvmx_uctlx_if_ena if_ena; | ||
84 | union cvmx_uctlx_clk_rst_ctl clk_rst_ctl; | ||
85 | union cvmx_uctlx_uphy_ctl_status uphy_ctl_status; | ||
86 | union cvmx_uctlx_uphy_portx_ctl_status port_ctl_status; | ||
87 | int i; | ||
88 | unsigned long io_clk_64_to_ns; | ||
89 | |||
90 | |||
91 | mutex_lock(&octeon2_usb_clocks_mutex); | ||
92 | |||
93 | octeon2_usb_clock_start_cnt++; | ||
94 | if (octeon2_usb_clock_start_cnt != 1) | ||
95 | goto exit; | ||
96 | |||
97 | io_clk_64_to_ns = 64000000000ull / octeon_get_io_clock_rate(); | ||
98 | |||
99 | /* | ||
100 | * Step 1: Wait for voltages stable. That surely happened | ||
101 | * before starting the kernel. | ||
102 | * | ||
103 | * Step 2: Enable SCLK of UCTL by writing UCTL0_IF_ENA[EN] = 1 | ||
104 | */ | ||
105 | if_ena.u64 = 0; | ||
106 | if_ena.s.en = 1; | ||
107 | cvmx_write_csr(CVMX_UCTLX_IF_ENA(0), if_ena.u64); | ||
108 | |||
109 | /* Step 3: Configure the reference clock, PHY, and HCLK */ | ||
110 | clk_rst_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_CLK_RST_CTL(0)); | ||
111 | |||
112 | /* | ||
113 | * If the UCTL looks like it has already been started, skip | ||
114 | * the initialization, otherwise bus errors are obtained. | ||
115 | */ | ||
116 | if (clk_rst_ctl.s.hrst) | ||
117 | goto end_clock; | ||
118 | /* 3a */ | ||
119 | clk_rst_ctl.s.p_por = 1; | ||
120 | clk_rst_ctl.s.hrst = 0; | ||
121 | clk_rst_ctl.s.p_prst = 0; | ||
122 | clk_rst_ctl.s.h_clkdiv_rst = 0; | ||
123 | clk_rst_ctl.s.o_clkdiv_rst = 0; | ||
124 | clk_rst_ctl.s.h_clkdiv_en = 0; | ||
125 | clk_rst_ctl.s.o_clkdiv_en = 0; | ||
126 | cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); | ||
127 | |||
128 | /* 3b */ | ||
129 | /* 12MHz crystal. */ | ||
130 | clk_rst_ctl.s.p_refclk_sel = 0; | ||
131 | clk_rst_ctl.s.p_refclk_div = 0; | ||
132 | cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); | ||
133 | |||
134 | /* 3c */ | ||
135 | div = octeon_get_io_clock_rate() / 130000000ull; | ||
136 | |||
137 | switch (div) { | ||
138 | case 0: | ||
139 | div = 1; | ||
140 | break; | ||
141 | case 1: | ||
142 | case 2: | ||
143 | case 3: | ||
144 | case 4: | ||
145 | break; | ||
146 | case 5: | ||
147 | div = 4; | ||
148 | break; | ||
149 | case 6: | ||
150 | case 7: | ||
151 | div = 6; | ||
152 | break; | ||
153 | case 8: | ||
154 | case 9: | ||
155 | case 10: | ||
156 | case 11: | ||
157 | div = 8; | ||
158 | break; | ||
159 | default: | ||
160 | div = 12; | ||
161 | break; | ||
162 | } | ||
163 | clk_rst_ctl.s.h_div = div; | ||
164 | cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); | ||
165 | /* Read it back, */ | ||
166 | clk_rst_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_CLK_RST_CTL(0)); | ||
167 | clk_rst_ctl.s.h_clkdiv_en = 1; | ||
168 | cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); | ||
169 | /* 3d */ | ||
170 | clk_rst_ctl.s.h_clkdiv_rst = 1; | ||
171 | cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); | ||
172 | |||
173 | /* 3e: delay 64 io clocks */ | ||
174 | ndelay(io_clk_64_to_ns); | ||
175 | |||
176 | /* | ||
177 | * Step 4: Program the power-on reset field in the UCTL | ||
178 | * clock-reset-control register. | ||
179 | */ | ||
180 | clk_rst_ctl.s.p_por = 0; | ||
181 | cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); | ||
182 | |||
183 | /* Step 5: Wait 1 ms for the PHY clock to start. */ | ||
184 | mdelay(1); | ||
185 | |||
186 | /* | ||
187 | * Step 6: Program the reset input from automatic test | ||
188 | * equipment field in the UPHY CSR | ||
189 | */ | ||
190 | uphy_ctl_status.u64 = cvmx_read_csr(CVMX_UCTLX_UPHY_CTL_STATUS(0)); | ||
191 | uphy_ctl_status.s.ate_reset = 1; | ||
192 | cvmx_write_csr(CVMX_UCTLX_UPHY_CTL_STATUS(0), uphy_ctl_status.u64); | ||
193 | |||
194 | /* Step 7: Wait for at least 10ns. */ | ||
195 | ndelay(10); | ||
196 | |||
197 | /* Step 8: Clear the ATE_RESET field in the UPHY CSR. */ | ||
198 | uphy_ctl_status.s.ate_reset = 0; | ||
199 | cvmx_write_csr(CVMX_UCTLX_UPHY_CTL_STATUS(0), uphy_ctl_status.u64); | ||
200 | |||
201 | /* | ||
202 | * Step 9: Wait for at least 20ns for UPHY to output PHY clock | ||
203 | * signals and OHCI_CLK48 | ||
204 | */ | ||
205 | ndelay(20); | ||
206 | |||
207 | /* Step 10: Configure the OHCI_CLK48 and OHCI_CLK12 clocks. */ | ||
208 | /* 10a */ | ||
209 | clk_rst_ctl.s.o_clkdiv_rst = 1; | ||
210 | cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); | ||
211 | |||
212 | /* 10b */ | ||
213 | clk_rst_ctl.s.o_clkdiv_en = 1; | ||
214 | cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); | ||
215 | |||
216 | /* 10c */ | ||
217 | ndelay(io_clk_64_to_ns); | ||
218 | |||
219 | /* | ||
220 | * Step 11: Program the PHY reset field: | ||
221 | * UCTL0_CLK_RST_CTL[P_PRST] = 1 | ||
222 | */ | ||
223 | clk_rst_ctl.s.p_prst = 1; | ||
224 | cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); | ||
225 | |||
226 | /* Step 12: Wait 1 uS. */ | ||
227 | udelay(1); | ||
228 | |||
229 | /* Step 13: Program the HRESET_N field: UCTL0_CLK_RST_CTL[HRST] = 1 */ | ||
230 | clk_rst_ctl.s.hrst = 1; | ||
231 | cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); | ||
232 | |||
233 | end_clock: | ||
234 | /* Now we can set some other registers. */ | ||
235 | |||
236 | for (i = 0; i <= 1; i++) { | ||
237 | port_ctl_status.u64 = | ||
238 | cvmx_read_csr(CVMX_UCTLX_UPHY_PORTX_CTL_STATUS(i, 0)); | ||
239 | /* Set txvreftune to 15 to obtain compliant 'eye' diagram. */ | ||
240 | port_ctl_status.s.txvreftune = 15; | ||
241 | port_ctl_status.s.txrisetune = 1; | ||
242 | port_ctl_status.s.txpreemphasistune = 1; | ||
243 | cvmx_write_csr(CVMX_UCTLX_UPHY_PORTX_CTL_STATUS(i, 0), | ||
244 | port_ctl_status.u64); | ||
245 | } | ||
246 | |||
247 | /* Set uSOF cycle period to 60,000 bits. */ | ||
248 | cvmx_write_csr(CVMX_UCTLX_EHCI_FLA(0), 0x20ull); | ||
249 | exit: | ||
250 | mutex_unlock(&octeon2_usb_clocks_mutex); | ||
251 | } | ||
252 | |||
253 | static void octeon2_usb_clocks_stop(void) | ||
254 | { | ||
255 | mutex_lock(&octeon2_usb_clocks_mutex); | ||
256 | octeon2_usb_clock_start_cnt--; | ||
257 | mutex_unlock(&octeon2_usb_clocks_mutex); | ||
258 | } | ||
259 | |||
260 | static int octeon_ehci_power_on(struct platform_device *pdev) | ||
261 | { | ||
262 | octeon2_usb_clocks_start(); | ||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | static void octeon_ehci_power_off(struct platform_device *pdev) | ||
267 | { | ||
268 | octeon2_usb_clocks_stop(); | ||
269 | } | ||
270 | |||
271 | static struct usb_ehci_pdata octeon_ehci_pdata = { | ||
272 | /* Octeon EHCI matches CPU endianness. */ | ||
273 | #ifdef __BIG_ENDIAN | ||
274 | .big_endian_mmio = 1, | ||
275 | #endif | ||
276 | .power_on = octeon_ehci_power_on, | ||
277 | .power_off = octeon_ehci_power_off, | ||
278 | }; | ||
279 | |||
280 | static void __init octeon_ehci_hw_start(void) | ||
281 | { | ||
282 | union cvmx_uctlx_ehci_ctl ehci_ctl; | ||
283 | |||
284 | octeon2_usb_clocks_start(); | ||
285 | |||
286 | ehci_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_EHCI_CTL(0)); | ||
287 | /* Use 64-bit addressing. */ | ||
288 | ehci_ctl.s.ehci_64b_addr_en = 1; | ||
289 | ehci_ctl.s.l2c_addr_msb = 0; | ||
290 | ehci_ctl.s.l2c_buff_emod = 1; /* Byte swapped. */ | ||
291 | ehci_ctl.s.l2c_desc_emod = 1; /* Byte swapped. */ | ||
292 | cvmx_write_csr(CVMX_UCTLX_EHCI_CTL(0), ehci_ctl.u64); | ||
293 | |||
294 | octeon2_usb_clocks_stop(); | ||
295 | } | ||
296 | |||
297 | static u64 octeon_ehci_dma_mask = DMA_BIT_MASK(64); | ||
298 | |||
71 | static int __init octeon_ehci_device_init(void) | 299 | static int __init octeon_ehci_device_init(void) |
72 | { | 300 | { |
73 | struct platform_device *pd; | 301 | struct platform_device *pd; |
@@ -88,7 +316,7 @@ static int __init octeon_ehci_device_init(void) | |||
88 | if (octeon_is_simulation() || usb_disabled()) | 316 | if (octeon_is_simulation() || usb_disabled()) |
89 | return 0; /* No USB in the simulator. */ | 317 | return 0; /* No USB in the simulator. */ |
90 | 318 | ||
91 | pd = platform_device_alloc("octeon-ehci", 0); | 319 | pd = platform_device_alloc("ehci-platform", 0); |
92 | if (!pd) { | 320 | if (!pd) { |
93 | ret = -ENOMEM; | 321 | ret = -ENOMEM; |
94 | goto out; | 322 | goto out; |
@@ -105,6 +333,10 @@ static int __init octeon_ehci_device_init(void) | |||
105 | if (ret) | 333 | if (ret) |
106 | goto fail; | 334 | goto fail; |
107 | 335 | ||
336 | pd->dev.dma_mask = &octeon_ehci_dma_mask; | ||
337 | pd->dev.platform_data = &octeon_ehci_pdata; | ||
338 | octeon_ehci_hw_start(); | ||
339 | |||
108 | ret = platform_device_add(pd); | 340 | ret = platform_device_add(pd); |
109 | if (ret) | 341 | if (ret) |
110 | goto fail; | 342 | goto fail; |
@@ -117,6 +349,41 @@ out: | |||
117 | } | 349 | } |
118 | device_initcall(octeon_ehci_device_init); | 350 | device_initcall(octeon_ehci_device_init); |
119 | 351 | ||
352 | static int octeon_ohci_power_on(struct platform_device *pdev) | ||
353 | { | ||
354 | octeon2_usb_clocks_start(); | ||
355 | return 0; | ||
356 | } | ||
357 | |||
358 | static void octeon_ohci_power_off(struct platform_device *pdev) | ||
359 | { | ||
360 | octeon2_usb_clocks_stop(); | ||
361 | } | ||
362 | |||
363 | static struct usb_ohci_pdata octeon_ohci_pdata = { | ||
364 | /* Octeon OHCI matches CPU endianness. */ | ||
365 | #ifdef __BIG_ENDIAN | ||
366 | .big_endian_mmio = 1, | ||
367 | #endif | ||
368 | .power_on = octeon_ohci_power_on, | ||
369 | .power_off = octeon_ohci_power_off, | ||
370 | }; | ||
371 | |||
372 | static void __init octeon_ohci_hw_start(void) | ||
373 | { | ||
374 | union cvmx_uctlx_ohci_ctl ohci_ctl; | ||
375 | |||
376 | octeon2_usb_clocks_start(); | ||
377 | |||
378 | ohci_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_OHCI_CTL(0)); | ||
379 | ohci_ctl.s.l2c_addr_msb = 0; | ||
380 | ohci_ctl.s.l2c_buff_emod = 1; /* Byte swapped. */ | ||
381 | ohci_ctl.s.l2c_desc_emod = 1; /* Byte swapped. */ | ||
382 | cvmx_write_csr(CVMX_UCTLX_OHCI_CTL(0), ohci_ctl.u64); | ||
383 | |||
384 | octeon2_usb_clocks_stop(); | ||
385 | } | ||
386 | |||
120 | static int __init octeon_ohci_device_init(void) | 387 | static int __init octeon_ohci_device_init(void) |
121 | { | 388 | { |
122 | struct platform_device *pd; | 389 | struct platform_device *pd; |
@@ -137,7 +404,7 @@ static int __init octeon_ohci_device_init(void) | |||
137 | if (octeon_is_simulation() || usb_disabled()) | 404 | if (octeon_is_simulation() || usb_disabled()) |
138 | return 0; /* No USB in the simulator. */ | 405 | return 0; /* No USB in the simulator. */ |
139 | 406 | ||
140 | pd = platform_device_alloc("octeon-ohci", 0); | 407 | pd = platform_device_alloc("ohci-platform", 0); |
141 | if (!pd) { | 408 | if (!pd) { |
142 | ret = -ENOMEM; | 409 | ret = -ENOMEM; |
143 | goto out; | 410 | goto out; |
@@ -154,6 +421,9 @@ static int __init octeon_ohci_device_init(void) | |||
154 | if (ret) | 421 | if (ret) |
155 | goto fail; | 422 | goto fail; |
156 | 423 | ||
424 | pd->dev.platform_data = &octeon_ohci_pdata; | ||
425 | octeon_ohci_hw_start(); | ||
426 | |||
157 | ret = platform_device_add(pd); | 427 | ret = platform_device_add(pd); |
158 | if (ret) | 428 | if (ret) |
159 | goto fail; | 429 | goto fail; |
diff --git a/arch/mips/configs/cavium_octeon_defconfig b/arch/mips/configs/cavium_octeon_defconfig index b2476a1c4aaa..e57058d4ec22 100644 --- a/arch/mips/configs/cavium_octeon_defconfig +++ b/arch/mips/configs/cavium_octeon_defconfig | |||
@@ -120,6 +120,9 @@ CONFIG_SPI_OCTEON=y | |||
120 | # CONFIG_HWMON is not set | 120 | # CONFIG_HWMON is not set |
121 | CONFIG_WATCHDOG=y | 121 | CONFIG_WATCHDOG=y |
122 | # CONFIG_USB_SUPPORT is not set | 122 | # CONFIG_USB_SUPPORT is not set |
123 | CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y | ||
124 | CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y | ||
125 | CONFIG_USB_OHCI_LITTLE_ENDIAN=y | ||
123 | CONFIG_RTC_CLASS=y | 126 | CONFIG_RTC_CLASS=y |
124 | CONFIG_RTC_DRV_DS1307=y | 127 | CONFIG_RTC_DRV_DS1307=y |
125 | CONFIG_STAGING=y | 128 | CONFIG_STAGING=y |
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index a3ca1375dd52..fafc628480e0 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig | |||
@@ -292,11 +292,15 @@ config USB_EHCI_HCD_PLATFORM | |||
292 | If unsure, say N. | 292 | If unsure, say N. |
293 | 293 | ||
294 | config USB_OCTEON_EHCI | 294 | config USB_OCTEON_EHCI |
295 | bool "Octeon on-chip EHCI support" | 295 | bool "Octeon on-chip EHCI support (DEPRECATED)" |
296 | depends on CAVIUM_OCTEON_SOC | 296 | depends on CAVIUM_OCTEON_SOC |
297 | default n | 297 | default n |
298 | select USB_EHCI_BIG_ENDIAN_MMIO | 298 | select USB_EHCI_BIG_ENDIAN_MMIO |
299 | select USB_EHCI_HCD_PLATFORM | ||
299 | help | 300 | help |
301 | This option is deprecated now and the driver was removed, use | ||
302 | USB_EHCI_HCD_PLATFORM instead. | ||
303 | |||
300 | Enable support for the Octeon II SOC's on-chip EHCI | 304 | Enable support for the Octeon II SOC's on-chip EHCI |
301 | controller. It is needed for high-speed (480Mbit/sec) | 305 | controller. It is needed for high-speed (480Mbit/sec) |
302 | USB 2.0 device support. All CN6XXX based chips with USB are | 306 | USB 2.0 device support. All CN6XXX based chips with USB are |
@@ -575,12 +579,16 @@ config USB_OHCI_HCD_PLATFORM | |||
575 | If unsure, say N. | 579 | If unsure, say N. |
576 | 580 | ||
577 | config USB_OCTEON_OHCI | 581 | config USB_OCTEON_OHCI |
578 | bool "Octeon on-chip OHCI support" | 582 | bool "Octeon on-chip OHCI support (DEPRECATED)" |
579 | depends on CAVIUM_OCTEON_SOC | 583 | depends on CAVIUM_OCTEON_SOC |
580 | default USB_OCTEON_EHCI | 584 | default USB_OCTEON_EHCI |
581 | select USB_OHCI_BIG_ENDIAN_MMIO | 585 | select USB_OHCI_BIG_ENDIAN_MMIO |
582 | select USB_OHCI_LITTLE_ENDIAN | 586 | select USB_OHCI_LITTLE_ENDIAN |
587 | select USB_OHCI_HCD_PLATFORM | ||
583 | help | 588 | help |
589 | This option is deprecated now and the driver was removed, use | ||
590 | USB_OHCI_HCD_PLATFORM instead. | ||
591 | |||
584 | Enable support for the Octeon II SOC's on-chip OHCI | 592 | Enable support for the Octeon II SOC's on-chip OHCI |
585 | controller. It is needed for low-speed USB 1.0 device | 593 | controller. It is needed for low-speed USB 1.0 device |
586 | support. All CN6XXX based chips with USB are supported. | 594 | support. All CN6XXX based chips with USB are supported. |
@@ -754,12 +762,6 @@ config USB_IMX21_HCD | |||
754 | To compile this driver as a module, choose M here: the | 762 | To compile this driver as a module, choose M here: the |
755 | module will be called "imx21-hcd". | 763 | module will be called "imx21-hcd". |
756 | 764 | ||
757 | |||
758 | |||
759 | config USB_OCTEON2_COMMON | ||
760 | bool | ||
761 | default y if USB_OCTEON_EHCI || USB_OCTEON_OHCI | ||
762 | |||
763 | config USB_HCD_BCMA | 765 | config USB_HCD_BCMA |
764 | tristate "BCMA usb host driver" | 766 | tristate "BCMA usb host driver" |
765 | depends on BCMA | 767 | depends on BCMA |
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 348c24321562..d6216a493bab 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile | |||
@@ -73,7 +73,6 @@ obj-$(CONFIG_USB_ISP1760_HCD) += isp1760.o | |||
73 | obj-$(CONFIG_USB_HWA_HCD) += hwa-hc.o | 73 | obj-$(CONFIG_USB_HWA_HCD) += hwa-hc.o |
74 | obj-$(CONFIG_USB_IMX21_HCD) += imx21-hcd.o | 74 | obj-$(CONFIG_USB_IMX21_HCD) += imx21-hcd.o |
75 | obj-$(CONFIG_USB_FSL_MPH_DR_OF) += fsl-mph-dr-of.o | 75 | obj-$(CONFIG_USB_FSL_MPH_DR_OF) += fsl-mph-dr-of.o |
76 | obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o | ||
77 | obj-$(CONFIG_USB_HCD_BCMA) += bcma-hcd.o | 76 | obj-$(CONFIG_USB_HCD_BCMA) += bcma-hcd.o |
78 | obj-$(CONFIG_USB_HCD_SSB) += ssb-hcd.o | 77 | obj-$(CONFIG_USB_HCD_SSB) += ssb-hcd.o |
79 | obj-$(CONFIG_USB_FUSBH200_HCD) += fusbh200-hcd.o | 78 | obj-$(CONFIG_USB_FUSBH200_HCD) += fusbh200-hcd.o |
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index df75b8e7d157..38bfeedae1d0 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -1275,11 +1275,6 @@ MODULE_LICENSE ("GPL"); | |||
1275 | #define XILINX_OF_PLATFORM_DRIVER ehci_hcd_xilinx_of_driver | 1275 | #define XILINX_OF_PLATFORM_DRIVER ehci_hcd_xilinx_of_driver |
1276 | #endif | 1276 | #endif |
1277 | 1277 | ||
1278 | #ifdef CONFIG_USB_OCTEON_EHCI | ||
1279 | #include "ehci-octeon.c" | ||
1280 | #define PLATFORM_DRIVER ehci_octeon_driver | ||
1281 | #endif | ||
1282 | |||
1283 | #ifdef CONFIG_TILE_USB | 1278 | #ifdef CONFIG_TILE_USB |
1284 | #include "ehci-tilegx.c" | 1279 | #include "ehci-tilegx.c" |
1285 | #define PLATFORM_DRIVER ehci_hcd_tilegx_driver | 1280 | #define PLATFORM_DRIVER ehci_hcd_tilegx_driver |
diff --git a/drivers/usb/host/ehci-octeon.c b/drivers/usb/host/ehci-octeon.c deleted file mode 100644 index 2d0c4bcba579..000000000000 --- a/drivers/usb/host/ehci-octeon.c +++ /dev/null | |||
@@ -1,182 +0,0 @@ | |||
1 | /* | ||
2 | * EHCI HCD glue for Cavium Octeon II SOCs. | ||
3 | * | ||
4 | * Loosely based on ehci-au1xxx.c | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of the GNU General Public | ||
7 | * License. See the file "COPYING" in the main directory of this archive | ||
8 | * for more details. | ||
9 | * | ||
10 | * Copyright (C) 2010 Cavium Networks | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/platform_device.h> | ||
15 | |||
16 | #include <asm/octeon/octeon.h> | ||
17 | #include <asm/octeon/cvmx-uctlx-defs.h> | ||
18 | |||
19 | #define OCTEON_EHCI_HCD_NAME "octeon-ehci" | ||
20 | |||
21 | /* Common clock init code. */ | ||
22 | void octeon2_usb_clocks_start(void); | ||
23 | void octeon2_usb_clocks_stop(void); | ||
24 | |||
25 | static void ehci_octeon_start(void) | ||
26 | { | ||
27 | union cvmx_uctlx_ehci_ctl ehci_ctl; | ||
28 | |||
29 | octeon2_usb_clocks_start(); | ||
30 | |||
31 | ehci_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_EHCI_CTL(0)); | ||
32 | /* Use 64-bit addressing. */ | ||
33 | ehci_ctl.s.ehci_64b_addr_en = 1; | ||
34 | ehci_ctl.s.l2c_addr_msb = 0; | ||
35 | ehci_ctl.s.l2c_buff_emod = 1; /* Byte swapped. */ | ||
36 | ehci_ctl.s.l2c_desc_emod = 1; /* Byte swapped. */ | ||
37 | cvmx_write_csr(CVMX_UCTLX_EHCI_CTL(0), ehci_ctl.u64); | ||
38 | } | ||
39 | |||
40 | static void ehci_octeon_stop(void) | ||
41 | { | ||
42 | octeon2_usb_clocks_stop(); | ||
43 | } | ||
44 | |||
45 | static const struct hc_driver ehci_octeon_hc_driver = { | ||
46 | .description = hcd_name, | ||
47 | .product_desc = "Octeon EHCI", | ||
48 | .hcd_priv_size = sizeof(struct ehci_hcd), | ||
49 | |||
50 | /* | ||
51 | * generic hardware linkage | ||
52 | */ | ||
53 | .irq = ehci_irq, | ||
54 | .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, | ||
55 | |||
56 | /* | ||
57 | * basic lifecycle operations | ||
58 | */ | ||
59 | .reset = ehci_setup, | ||
60 | .start = ehci_run, | ||
61 | .stop = ehci_stop, | ||
62 | .shutdown = ehci_shutdown, | ||
63 | |||
64 | /* | ||
65 | * managing i/o requests and associated device resources | ||
66 | */ | ||
67 | .urb_enqueue = ehci_urb_enqueue, | ||
68 | .urb_dequeue = ehci_urb_dequeue, | ||
69 | .endpoint_disable = ehci_endpoint_disable, | ||
70 | .endpoint_reset = ehci_endpoint_reset, | ||
71 | |||
72 | /* | ||
73 | * scheduling support | ||
74 | */ | ||
75 | .get_frame_number = ehci_get_frame, | ||
76 | |||
77 | /* | ||
78 | * root hub support | ||
79 | */ | ||
80 | .hub_status_data = ehci_hub_status_data, | ||
81 | .hub_control = ehci_hub_control, | ||
82 | .bus_suspend = ehci_bus_suspend, | ||
83 | .bus_resume = ehci_bus_resume, | ||
84 | .relinquish_port = ehci_relinquish_port, | ||
85 | .port_handed_over = ehci_port_handed_over, | ||
86 | |||
87 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
88 | }; | ||
89 | |||
90 | static u64 ehci_octeon_dma_mask = DMA_BIT_MASK(64); | ||
91 | |||
92 | static int ehci_octeon_drv_probe(struct platform_device *pdev) | ||
93 | { | ||
94 | struct usb_hcd *hcd; | ||
95 | struct ehci_hcd *ehci; | ||
96 | struct resource *res_mem; | ||
97 | int irq; | ||
98 | int ret; | ||
99 | |||
100 | if (usb_disabled()) | ||
101 | return -ENODEV; | ||
102 | |||
103 | irq = platform_get_irq(pdev, 0); | ||
104 | if (irq < 0) { | ||
105 | dev_err(&pdev->dev, "No irq assigned\n"); | ||
106 | return -ENODEV; | ||
107 | } | ||
108 | |||
109 | /* | ||
110 | * We can DMA from anywhere. But the descriptors must be in | ||
111 | * the lower 4GB. | ||
112 | */ | ||
113 | pdev->dev.dma_mask = &ehci_octeon_dma_mask; | ||
114 | ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); | ||
115 | if (ret) | ||
116 | return ret; | ||
117 | |||
118 | hcd = usb_create_hcd(&ehci_octeon_hc_driver, &pdev->dev, "octeon"); | ||
119 | if (!hcd) | ||
120 | return -ENOMEM; | ||
121 | |||
122 | res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
123 | hcd->regs = devm_ioremap_resource(&pdev->dev, res_mem); | ||
124 | if (IS_ERR(hcd->regs)) { | ||
125 | ret = PTR_ERR(hcd->regs); | ||
126 | goto err1; | ||
127 | } | ||
128 | hcd->rsrc_start = res_mem->start; | ||
129 | hcd->rsrc_len = resource_size(res_mem); | ||
130 | |||
131 | ehci_octeon_start(); | ||
132 | |||
133 | ehci = hcd_to_ehci(hcd); | ||
134 | |||
135 | /* Octeon EHCI matches CPU endianness. */ | ||
136 | #ifdef __BIG_ENDIAN | ||
137 | ehci->big_endian_mmio = 1; | ||
138 | #endif | ||
139 | |||
140 | ehci->caps = hcd->regs; | ||
141 | |||
142 | ret = usb_add_hcd(hcd, irq, IRQF_SHARED); | ||
143 | if (ret) { | ||
144 | dev_dbg(&pdev->dev, "failed to add hcd with err %d\n", ret); | ||
145 | goto err2; | ||
146 | } | ||
147 | device_wakeup_enable(hcd->self.controller); | ||
148 | |||
149 | platform_set_drvdata(pdev, hcd); | ||
150 | |||
151 | return 0; | ||
152 | err2: | ||
153 | ehci_octeon_stop(); | ||
154 | |||
155 | err1: | ||
156 | usb_put_hcd(hcd); | ||
157 | return ret; | ||
158 | } | ||
159 | |||
160 | static int ehci_octeon_drv_remove(struct platform_device *pdev) | ||
161 | { | ||
162 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
163 | |||
164 | usb_remove_hcd(hcd); | ||
165 | |||
166 | ehci_octeon_stop(); | ||
167 | usb_put_hcd(hcd); | ||
168 | |||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | static struct platform_driver ehci_octeon_driver = { | ||
173 | .probe = ehci_octeon_drv_probe, | ||
174 | .remove = ehci_octeon_drv_remove, | ||
175 | .shutdown = usb_hcd_platform_shutdown, | ||
176 | .driver = { | ||
177 | .name = OCTEON_EHCI_HCD_NAME, | ||
178 | .owner = THIS_MODULE, | ||
179 | } | ||
180 | }; | ||
181 | |||
182 | MODULE_ALIAS("platform:" OCTEON_EHCI_HCD_NAME); | ||
diff --git a/drivers/usb/host/octeon2-common.c b/drivers/usb/host/octeon2-common.c deleted file mode 100644 index d9df423f3d12..000000000000 --- a/drivers/usb/host/octeon2-common.c +++ /dev/null | |||
@@ -1,200 +0,0 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2010, 2011 Cavium Networks | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/mutex.h> | ||
11 | #include <linux/delay.h> | ||
12 | |||
13 | #include <asm/octeon/octeon.h> | ||
14 | #include <asm/octeon/cvmx-uctlx-defs.h> | ||
15 | |||
16 | static DEFINE_MUTEX(octeon2_usb_clocks_mutex); | ||
17 | |||
18 | static int octeon2_usb_clock_start_cnt; | ||
19 | |||
20 | void octeon2_usb_clocks_start(void) | ||
21 | { | ||
22 | u64 div; | ||
23 | union cvmx_uctlx_if_ena if_ena; | ||
24 | union cvmx_uctlx_clk_rst_ctl clk_rst_ctl; | ||
25 | union cvmx_uctlx_uphy_ctl_status uphy_ctl_status; | ||
26 | union cvmx_uctlx_uphy_portx_ctl_status port_ctl_status; | ||
27 | int i; | ||
28 | unsigned long io_clk_64_to_ns; | ||
29 | |||
30 | |||
31 | mutex_lock(&octeon2_usb_clocks_mutex); | ||
32 | |||
33 | octeon2_usb_clock_start_cnt++; | ||
34 | if (octeon2_usb_clock_start_cnt != 1) | ||
35 | goto exit; | ||
36 | |||
37 | io_clk_64_to_ns = 64000000000ull / octeon_get_io_clock_rate(); | ||
38 | |||
39 | /* | ||
40 | * Step 1: Wait for voltages stable. That surely happened | ||
41 | * before starting the kernel. | ||
42 | * | ||
43 | * Step 2: Enable SCLK of UCTL by writing UCTL0_IF_ENA[EN] = 1 | ||
44 | */ | ||
45 | if_ena.u64 = 0; | ||
46 | if_ena.s.en = 1; | ||
47 | cvmx_write_csr(CVMX_UCTLX_IF_ENA(0), if_ena.u64); | ||
48 | |||
49 | /* Step 3: Configure the reference clock, PHY, and HCLK */ | ||
50 | clk_rst_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_CLK_RST_CTL(0)); | ||
51 | |||
52 | /* | ||
53 | * If the UCTL looks like it has already been started, skip | ||
54 | * the initialization, otherwise bus errors are obtained. | ||
55 | */ | ||
56 | if (clk_rst_ctl.s.hrst) | ||
57 | goto end_clock; | ||
58 | /* 3a */ | ||
59 | clk_rst_ctl.s.p_por = 1; | ||
60 | clk_rst_ctl.s.hrst = 0; | ||
61 | clk_rst_ctl.s.p_prst = 0; | ||
62 | clk_rst_ctl.s.h_clkdiv_rst = 0; | ||
63 | clk_rst_ctl.s.o_clkdiv_rst = 0; | ||
64 | clk_rst_ctl.s.h_clkdiv_en = 0; | ||
65 | clk_rst_ctl.s.o_clkdiv_en = 0; | ||
66 | cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); | ||
67 | |||
68 | /* 3b */ | ||
69 | /* 12MHz crystal. */ | ||
70 | clk_rst_ctl.s.p_refclk_sel = 0; | ||
71 | clk_rst_ctl.s.p_refclk_div = 0; | ||
72 | cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); | ||
73 | |||
74 | /* 3c */ | ||
75 | div = octeon_get_io_clock_rate() / 130000000ull; | ||
76 | |||
77 | switch (div) { | ||
78 | case 0: | ||
79 | div = 1; | ||
80 | break; | ||
81 | case 1: | ||
82 | case 2: | ||
83 | case 3: | ||
84 | case 4: | ||
85 | break; | ||
86 | case 5: | ||
87 | div = 4; | ||
88 | break; | ||
89 | case 6: | ||
90 | case 7: | ||
91 | div = 6; | ||
92 | break; | ||
93 | case 8: | ||
94 | case 9: | ||
95 | case 10: | ||
96 | case 11: | ||
97 | div = 8; | ||
98 | break; | ||
99 | default: | ||
100 | div = 12; | ||
101 | break; | ||
102 | } | ||
103 | clk_rst_ctl.s.h_div = div; | ||
104 | cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); | ||
105 | /* Read it back, */ | ||
106 | clk_rst_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_CLK_RST_CTL(0)); | ||
107 | clk_rst_ctl.s.h_clkdiv_en = 1; | ||
108 | cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); | ||
109 | /* 3d */ | ||
110 | clk_rst_ctl.s.h_clkdiv_rst = 1; | ||
111 | cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); | ||
112 | |||
113 | /* 3e: delay 64 io clocks */ | ||
114 | ndelay(io_clk_64_to_ns); | ||
115 | |||
116 | /* | ||
117 | * Step 4: Program the power-on reset field in the UCTL | ||
118 | * clock-reset-control register. | ||
119 | */ | ||
120 | clk_rst_ctl.s.p_por = 0; | ||
121 | cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); | ||
122 | |||
123 | /* Step 5: Wait 1 ms for the PHY clock to start. */ | ||
124 | mdelay(1); | ||
125 | |||
126 | /* | ||
127 | * Step 6: Program the reset input from automatic test | ||
128 | * equipment field in the UPHY CSR | ||
129 | */ | ||
130 | uphy_ctl_status.u64 = cvmx_read_csr(CVMX_UCTLX_UPHY_CTL_STATUS(0)); | ||
131 | uphy_ctl_status.s.ate_reset = 1; | ||
132 | cvmx_write_csr(CVMX_UCTLX_UPHY_CTL_STATUS(0), uphy_ctl_status.u64); | ||
133 | |||
134 | /* Step 7: Wait for at least 10ns. */ | ||
135 | ndelay(10); | ||
136 | |||
137 | /* Step 8: Clear the ATE_RESET field in the UPHY CSR. */ | ||
138 | uphy_ctl_status.s.ate_reset = 0; | ||
139 | cvmx_write_csr(CVMX_UCTLX_UPHY_CTL_STATUS(0), uphy_ctl_status.u64); | ||
140 | |||
141 | /* | ||
142 | * Step 9: Wait for at least 20ns for UPHY to output PHY clock | ||
143 | * signals and OHCI_CLK48 | ||
144 | */ | ||
145 | ndelay(20); | ||
146 | |||
147 | /* Step 10: Configure the OHCI_CLK48 and OHCI_CLK12 clocks. */ | ||
148 | /* 10a */ | ||
149 | clk_rst_ctl.s.o_clkdiv_rst = 1; | ||
150 | cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); | ||
151 | |||
152 | /* 10b */ | ||
153 | clk_rst_ctl.s.o_clkdiv_en = 1; | ||
154 | cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); | ||
155 | |||
156 | /* 10c */ | ||
157 | ndelay(io_clk_64_to_ns); | ||
158 | |||
159 | /* | ||
160 | * Step 11: Program the PHY reset field: | ||
161 | * UCTL0_CLK_RST_CTL[P_PRST] = 1 | ||
162 | */ | ||
163 | clk_rst_ctl.s.p_prst = 1; | ||
164 | cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); | ||
165 | |||
166 | /* Step 12: Wait 1 uS. */ | ||
167 | udelay(1); | ||
168 | |||
169 | /* Step 13: Program the HRESET_N field: UCTL0_CLK_RST_CTL[HRST] = 1 */ | ||
170 | clk_rst_ctl.s.hrst = 1; | ||
171 | cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); | ||
172 | |||
173 | end_clock: | ||
174 | /* Now we can set some other registers. */ | ||
175 | |||
176 | for (i = 0; i <= 1; i++) { | ||
177 | port_ctl_status.u64 = | ||
178 | cvmx_read_csr(CVMX_UCTLX_UPHY_PORTX_CTL_STATUS(i, 0)); | ||
179 | /* Set txvreftune to 15 to obtain compliant 'eye' diagram. */ | ||
180 | port_ctl_status.s.txvreftune = 15; | ||
181 | port_ctl_status.s.txrisetune = 1; | ||
182 | port_ctl_status.s.txpreemphasistune = 1; | ||
183 | cvmx_write_csr(CVMX_UCTLX_UPHY_PORTX_CTL_STATUS(i, 0), | ||
184 | port_ctl_status.u64); | ||
185 | } | ||
186 | |||
187 | /* Set uSOF cycle period to 60,000 bits. */ | ||
188 | cvmx_write_csr(CVMX_UCTLX_EHCI_FLA(0), 0x20ull); | ||
189 | exit: | ||
190 | mutex_unlock(&octeon2_usb_clocks_mutex); | ||
191 | } | ||
192 | EXPORT_SYMBOL(octeon2_usb_clocks_start); | ||
193 | |||
194 | void octeon2_usb_clocks_stop(void) | ||
195 | { | ||
196 | mutex_lock(&octeon2_usb_clocks_mutex); | ||
197 | octeon2_usb_clock_start_cnt--; | ||
198 | mutex_unlock(&octeon2_usb_clocks_mutex); | ||
199 | } | ||
200 | EXPORT_SYMBOL(octeon2_usb_clocks_stop); | ||
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index d664edabf14e..1dab9dfbca6a 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c | |||
@@ -1249,11 +1249,6 @@ MODULE_LICENSE ("GPL"); | |||
1249 | #define PLATFORM_DRIVER ohci_hcd_jz4740_driver | 1249 | #define PLATFORM_DRIVER ohci_hcd_jz4740_driver |
1250 | #endif | 1250 | #endif |
1251 | 1251 | ||
1252 | #ifdef CONFIG_USB_OCTEON_OHCI | ||
1253 | #include "ohci-octeon.c" | ||
1254 | #define PLATFORM_DRIVER ohci_octeon_driver | ||
1255 | #endif | ||
1256 | |||
1257 | #ifdef CONFIG_TILE_USB | 1252 | #ifdef CONFIG_TILE_USB |
1258 | #include "ohci-tilegx.c" | 1253 | #include "ohci-tilegx.c" |
1259 | #define PLATFORM_DRIVER ohci_hcd_tilegx_driver | 1254 | #define PLATFORM_DRIVER ohci_hcd_tilegx_driver |
diff --git a/drivers/usb/host/ohci-octeon.c b/drivers/usb/host/ohci-octeon.c deleted file mode 100644 index 20d861b6192f..000000000000 --- a/drivers/usb/host/ohci-octeon.c +++ /dev/null | |||
@@ -1,196 +0,0 @@ | |||
1 | /* | ||
2 | * EHCI HCD glue for Cavium Octeon II SOCs. | ||
3 | * | ||
4 | * Loosely based on ehci-au1xxx.c | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of the GNU General Public | ||
7 | * License. See the file "COPYING" in the main directory of this archive | ||
8 | * for more details. | ||
9 | * | ||
10 | * Copyright (C) 2010 Cavium Networks | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/platform_device.h> | ||
15 | |||
16 | #include <asm/octeon/octeon.h> | ||
17 | #include <asm/octeon/cvmx-uctlx-defs.h> | ||
18 | |||
19 | #define OCTEON_OHCI_HCD_NAME "octeon-ohci" | ||
20 | |||
21 | /* Common clock init code. */ | ||
22 | void octeon2_usb_clocks_start(void); | ||
23 | void octeon2_usb_clocks_stop(void); | ||
24 | |||
25 | static void ohci_octeon_hw_start(void) | ||
26 | { | ||
27 | union cvmx_uctlx_ohci_ctl ohci_ctl; | ||
28 | |||
29 | octeon2_usb_clocks_start(); | ||
30 | |||
31 | ohci_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_OHCI_CTL(0)); | ||
32 | ohci_ctl.s.l2c_addr_msb = 0; | ||
33 | ohci_ctl.s.l2c_buff_emod = 1; /* Byte swapped. */ | ||
34 | ohci_ctl.s.l2c_desc_emod = 1; /* Byte swapped. */ | ||
35 | cvmx_write_csr(CVMX_UCTLX_OHCI_CTL(0), ohci_ctl.u64); | ||
36 | |||
37 | } | ||
38 | |||
39 | static void ohci_octeon_hw_stop(void) | ||
40 | { | ||
41 | /* Undo ohci_octeon_start() */ | ||
42 | octeon2_usb_clocks_stop(); | ||
43 | } | ||
44 | |||
45 | static int ohci_octeon_start(struct usb_hcd *hcd) | ||
46 | { | ||
47 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); | ||
48 | int ret; | ||
49 | |||
50 | ret = ohci_init(ohci); | ||
51 | |||
52 | if (ret < 0) | ||
53 | return ret; | ||
54 | |||
55 | ret = ohci_run(ohci); | ||
56 | |||
57 | if (ret < 0) { | ||
58 | ohci_err(ohci, "can't start %s", hcd->self.bus_name); | ||
59 | ohci_stop(hcd); | ||
60 | return ret; | ||
61 | } | ||
62 | |||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | static const struct hc_driver ohci_octeon_hc_driver = { | ||
67 | .description = hcd_name, | ||
68 | .product_desc = "Octeon OHCI", | ||
69 | .hcd_priv_size = sizeof(struct ohci_hcd), | ||
70 | |||
71 | /* | ||
72 | * generic hardware linkage | ||
73 | */ | ||
74 | .irq = ohci_irq, | ||
75 | .flags = HCD_USB11 | HCD_MEMORY, | ||
76 | |||
77 | /* | ||
78 | * basic lifecycle operations | ||
79 | */ | ||
80 | .start = ohci_octeon_start, | ||
81 | .stop = ohci_stop, | ||
82 | .shutdown = ohci_shutdown, | ||
83 | |||
84 | /* | ||
85 | * managing i/o requests and associated device resources | ||
86 | */ | ||
87 | .urb_enqueue = ohci_urb_enqueue, | ||
88 | .urb_dequeue = ohci_urb_dequeue, | ||
89 | .endpoint_disable = ohci_endpoint_disable, | ||
90 | |||
91 | /* | ||
92 | * scheduling support | ||
93 | */ | ||
94 | .get_frame_number = ohci_get_frame, | ||
95 | |||
96 | /* | ||
97 | * root hub support | ||
98 | */ | ||
99 | .hub_status_data = ohci_hub_status_data, | ||
100 | .hub_control = ohci_hub_control, | ||
101 | |||
102 | .start_port_reset = ohci_start_port_reset, | ||
103 | }; | ||
104 | |||
105 | static int ohci_octeon_drv_probe(struct platform_device *pdev) | ||
106 | { | ||
107 | struct usb_hcd *hcd; | ||
108 | struct ohci_hcd *ohci; | ||
109 | void *reg_base; | ||
110 | struct resource *res_mem; | ||
111 | int irq; | ||
112 | int ret; | ||
113 | |||
114 | if (usb_disabled()) | ||
115 | return -ENODEV; | ||
116 | |||
117 | irq = platform_get_irq(pdev, 0); | ||
118 | if (irq < 0) { | ||
119 | dev_err(&pdev->dev, "No irq assigned\n"); | ||
120 | return -ENODEV; | ||
121 | } | ||
122 | |||
123 | /* Ohci is a 32-bit device. */ | ||
124 | ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); | ||
125 | if (ret) | ||
126 | return ret; | ||
127 | |||
128 | hcd = usb_create_hcd(&ohci_octeon_hc_driver, &pdev->dev, "octeon"); | ||
129 | if (!hcd) | ||
130 | return -ENOMEM; | ||
131 | |||
132 | res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
133 | reg_base = devm_ioremap_resource(&pdev->dev, res_mem); | ||
134 | if (IS_ERR(reg_base)) { | ||
135 | ret = PTR_ERR(reg_base); | ||
136 | goto err1; | ||
137 | } | ||
138 | hcd->rsrc_start = res_mem->start; | ||
139 | hcd->rsrc_len = resource_size(res_mem); | ||
140 | |||
141 | ohci_octeon_hw_start(); | ||
142 | |||
143 | hcd->regs = reg_base; | ||
144 | |||
145 | ohci = hcd_to_ohci(hcd); | ||
146 | |||
147 | /* Octeon OHCI matches CPU endianness. */ | ||
148 | #ifdef __BIG_ENDIAN | ||
149 | ohci->flags |= OHCI_QUIRK_BE_MMIO; | ||
150 | #endif | ||
151 | |||
152 | ohci_hcd_init(ohci); | ||
153 | |||
154 | ret = usb_add_hcd(hcd, irq, IRQF_SHARED); | ||
155 | if (ret) { | ||
156 | dev_dbg(&pdev->dev, "failed to add hcd with err %d\n", ret); | ||
157 | goto err2; | ||
158 | } | ||
159 | |||
160 | device_wakeup_enable(hcd->self.controller); | ||
161 | |||
162 | platform_set_drvdata(pdev, hcd); | ||
163 | |||
164 | return 0; | ||
165 | |||
166 | err2: | ||
167 | ohci_octeon_hw_stop(); | ||
168 | |||
169 | err1: | ||
170 | usb_put_hcd(hcd); | ||
171 | return ret; | ||
172 | } | ||
173 | |||
174 | static int ohci_octeon_drv_remove(struct platform_device *pdev) | ||
175 | { | ||
176 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
177 | |||
178 | usb_remove_hcd(hcd); | ||
179 | |||
180 | ohci_octeon_hw_stop(); | ||
181 | usb_put_hcd(hcd); | ||
182 | |||
183 | return 0; | ||
184 | } | ||
185 | |||
186 | static struct platform_driver ohci_octeon_driver = { | ||
187 | .probe = ohci_octeon_drv_probe, | ||
188 | .remove = ohci_octeon_drv_remove, | ||
189 | .shutdown = usb_hcd_platform_shutdown, | ||
190 | .driver = { | ||
191 | .name = OCTEON_OHCI_HCD_NAME, | ||
192 | .owner = THIS_MODULE, | ||
193 | } | ||
194 | }; | ||
195 | |||
196 | MODULE_ALIAS("platform:" OCTEON_OHCI_HCD_NAME); | ||