aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget
diff options
context:
space:
mode:
authorAnatolij Gustschin <agust@denx.de>2011-04-18 16:01:58 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-05-02 19:59:37 -0400
commit2ea6698d7b9266da53044dddc5f6743adf097fb5 (patch)
tree73dc8d286faf7c6cc25a18843825d796c0138f5b /drivers/usb/gadget
parent09ba0def9aefc16c1c8a6d166f024c9d704f0ab0 (diff)
USB: fsl_udc_core: support device mode of MPC5121E DR USB Controller
Extend the FSL UDC driver to support MPC5121E DR USB Controller operation in device mode. Add MPC5121E specific init/uninit at probe and remove and isolate system interface register accesses when running on MPC5121E SoC, as these registers are not available on this platform. This patch relies on previous patch for supporting big endian registers and descriptors access in the FSL UDC driver. Additionally support endpoint FIFO status operation by providing appropriate callback in endpoint ops structure. Also flush cache for the req buffer used for GetStatus reply. Without this, the correct reply to an endpoint GetStatus is written to 'req', but doesn't make it out to the USB bus since the buffer hasn't been flushed. This would cause the USBCV Halt Endpoint test to fail (according to changelog in Freescale LTIB driver code). Signed-off-by: Anatolij Gustschin <agust@denx.de> Cc: Li Yang <leoli@freescale.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r--drivers/usb/gadget/fsl_udc_core.c141
-rw-r--r--drivers/usb/gadget/fsl_usb2_udc.h2
2 files changed, 112 insertions, 31 deletions
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index b101b7e9c9b6..28b3a9f25f3b 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -6,7 +6,7 @@
6 * 6 *
7 * Description: 7 * Description:
8 * Freescale high-speed USB SOC DR module device controller driver. 8 * Freescale high-speed USB SOC DR module device controller driver.
9 * This can be found on MPC8349E/MPC8313E cpus. 9 * This can be found on MPC8349E/MPC8313E/MPC5121E cpus.
10 * The driver is previously named as mpc_udc. Based on bare board 10 * The driver is previously named as mpc_udc. Based on bare board
11 * code from Dave Liu and Shlomi Gridish. 11 * code from Dave Liu and Shlomi Gridish.
12 * 12 *
@@ -45,6 +45,7 @@
45#include <asm/system.h> 45#include <asm/system.h>
46#include <asm/unaligned.h> 46#include <asm/unaligned.h>
47#include <asm/dma.h> 47#include <asm/dma.h>
48#include <asm/cacheflush.h>
48 49
49#include "fsl_usb2_udc.h" 50#include "fsl_usb2_udc.h"
50 51
@@ -278,9 +279,12 @@ static int dr_controller_setup(struct fsl_udc *udc)
278 279
279 /* Set the controller as device mode */ 280 /* Set the controller as device mode */
280 tmp = fsl_readl(&dr_regs->usbmode); 281 tmp = fsl_readl(&dr_regs->usbmode);
282 tmp &= ~USB_MODE_CTRL_MODE_MASK; /* clear mode bits */
281 tmp |= USB_MODE_CTRL_MODE_DEVICE; 283 tmp |= USB_MODE_CTRL_MODE_DEVICE;
282 /* Disable Setup Lockout */ 284 /* Disable Setup Lockout */
283 tmp |= USB_MODE_SETUP_LOCK_OFF; 285 tmp |= USB_MODE_SETUP_LOCK_OFF;
286 if (udc->pdata->es)
287 tmp |= USB_MODE_ES;
284 fsl_writel(tmp, &dr_regs->usbmode); 288 fsl_writel(tmp, &dr_regs->usbmode);
285 289
286 /* Clear the setup status */ 290 /* Clear the setup status */
@@ -296,20 +300,24 @@ static int dr_controller_setup(struct fsl_udc *udc)
296 300
297 /* Config control enable i/o output, cpu endian register */ 301 /* Config control enable i/o output, cpu endian register */
298#ifndef CONFIG_ARCH_MXC 302#ifndef CONFIG_ARCH_MXC
299 ctrl = __raw_readl(&usb_sys_regs->control); 303 if (udc->pdata->have_sysif_regs) {
300 ctrl |= USB_CTRL_IOENB; 304 ctrl = __raw_readl(&usb_sys_regs->control);
301 __raw_writel(ctrl, &usb_sys_regs->control); 305 ctrl |= USB_CTRL_IOENB;
306 __raw_writel(ctrl, &usb_sys_regs->control);
307 }
302#endif 308#endif
303 309
304#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) 310#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
305 /* Turn on cache snooping hardware, since some PowerPC platforms 311 /* Turn on cache snooping hardware, since some PowerPC platforms
306 * wholly rely on hardware to deal with cache coherent. */ 312 * wholly rely on hardware to deal with cache coherent. */
307 313
308 /* Setup Snooping for all the 4GB space */ 314 if (udc->pdata->have_sysif_regs) {
309 tmp = SNOOP_SIZE_2GB; /* starts from 0x0, size 2G */ 315 /* Setup Snooping for all the 4GB space */
310 __raw_writel(tmp, &usb_sys_regs->snoop1); 316 tmp = SNOOP_SIZE_2GB; /* starts from 0x0, size 2G */
311 tmp |= 0x80000000; /* starts from 0x8000000, size 2G */ 317 __raw_writel(tmp, &usb_sys_regs->snoop1);
312 __raw_writel(tmp, &usb_sys_regs->snoop2); 318 tmp |= 0x80000000; /* starts from 0x8000000, size 2G */
319 __raw_writel(tmp, &usb_sys_regs->snoop2);
320 }
313#endif 321#endif
314 322
315 return 0; 323 return 0;
@@ -1014,6 +1022,36 @@ out:
1014 return status; 1022 return status;
1015} 1023}
1016 1024
1025static int fsl_ep_fifo_status(struct usb_ep *_ep)
1026{
1027 struct fsl_ep *ep;
1028 struct fsl_udc *udc;
1029 int size = 0;
1030 u32 bitmask;
1031 struct ep_queue_head *d_qh;
1032
1033 ep = container_of(_ep, struct fsl_ep, ep);
1034 if (!_ep || (!ep->desc && ep_index(ep) != 0))
1035 return -ENODEV;
1036
1037 udc = (struct fsl_udc *)ep->udc;
1038
1039 if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN)
1040 return -ESHUTDOWN;
1041
1042 d_qh = &ep->udc->ep_qh[ep_index(ep) * 2 + ep_is_in(ep)];
1043
1044 bitmask = (ep_is_in(ep)) ? (1 << (ep_index(ep) + 16)) :
1045 (1 << (ep_index(ep)));
1046
1047 if (fsl_readl(&dr_regs->endptstatus) & bitmask)
1048 size = (d_qh->size_ioc_int_sts & DTD_PACKET_SIZE)
1049 >> DTD_LENGTH_BIT_POS;
1050
1051 pr_debug("%s %u\n", __func__, size);
1052 return size;
1053}
1054
1017static void fsl_ep_fifo_flush(struct usb_ep *_ep) 1055static void fsl_ep_fifo_flush(struct usb_ep *_ep)
1018{ 1056{
1019 struct fsl_ep *ep; 1057 struct fsl_ep *ep;
@@ -1066,6 +1104,7 @@ static struct usb_ep_ops fsl_ep_ops = {
1066 .dequeue = fsl_ep_dequeue, 1104 .dequeue = fsl_ep_dequeue,
1067 1105
1068 .set_halt = fsl_ep_set_halt, 1106 .set_halt = fsl_ep_set_halt,
1107 .fifo_status = fsl_ep_fifo_status,
1069 .fifo_flush = fsl_ep_fifo_flush, /* flush fifo */ 1108 .fifo_flush = fsl_ep_fifo_flush, /* flush fifo */
1070}; 1109};
1071 1110
@@ -1280,6 +1319,10 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,
1280 req = udc->status_req; 1319 req = udc->status_req;
1281 /* Fill in the reqest structure */ 1320 /* Fill in the reqest structure */
1282 *((u16 *) req->req.buf) = cpu_to_le16(tmp); 1321 *((u16 *) req->req.buf) = cpu_to_le16(tmp);
1322
1323 /* flush cache for the req buffer */
1324 flush_dcache_range((u32)req->req.buf, (u32)req->req.buf + 8);
1325
1283 req->ep = ep; 1326 req->ep = ep;
1284 req->req.length = 2; 1327 req->req.length = 2;
1285 req->req.status = -EINPROGRESS; 1328 req->req.status = -EINPROGRESS;
@@ -1332,6 +1375,7 @@ static void setup_received_irq(struct fsl_udc *udc,
1332 /* Status phase from udc */ 1375 /* Status phase from udc */
1333 { 1376 {
1334 int rc = -EOPNOTSUPP; 1377 int rc = -EOPNOTSUPP;
1378 u16 ptc = 0;
1335 1379
1336 if ((setup->bRequestType & (USB_RECIP_MASK | USB_TYPE_MASK)) 1380 if ((setup->bRequestType & (USB_RECIP_MASK | USB_TYPE_MASK))
1337 == (USB_RECIP_ENDPOINT | USB_TYPE_STANDARD)) { 1381 == (USB_RECIP_ENDPOINT | USB_TYPE_STANDARD)) {
@@ -1353,17 +1397,19 @@ static void setup_received_irq(struct fsl_udc *udc,
1353 | USB_TYPE_STANDARD)) { 1397 | USB_TYPE_STANDARD)) {
1354 /* Note: The driver has not include OTG support yet. 1398 /* Note: The driver has not include OTG support yet.
1355 * This will be set when OTG support is added */ 1399 * This will be set when OTG support is added */
1356 if (!gadget_is_otg(&udc->gadget)) 1400 if (wValue == USB_DEVICE_TEST_MODE)
1357 break; 1401 ptc = wIndex >> 8;
1358 else if (setup->bRequest == USB_DEVICE_B_HNP_ENABLE) 1402 else if (gadget_is_otg(&udc->gadget)) {
1359 udc->gadget.b_hnp_enable = 1; 1403 if (setup->bRequest ==
1360 else if (setup->bRequest == USB_DEVICE_A_HNP_SUPPORT) 1404 USB_DEVICE_B_HNP_ENABLE)
1361 udc->gadget.a_hnp_support = 1; 1405 udc->gadget.b_hnp_enable = 1;
1362 else if (setup->bRequest == 1406 else if (setup->bRequest ==
1363 USB_DEVICE_A_ALT_HNP_SUPPORT) 1407 USB_DEVICE_A_HNP_SUPPORT)
1364 udc->gadget.a_alt_hnp_support = 1; 1408 udc->gadget.a_hnp_support = 1;
1365 else 1409 else if (setup->bRequest ==
1366 break; 1410 USB_DEVICE_A_ALT_HNP_SUPPORT)
1411 udc->gadget.a_alt_hnp_support = 1;
1412 }
1367 rc = 0; 1413 rc = 0;
1368 } else 1414 } else
1369 break; 1415 break;
@@ -1372,6 +1418,15 @@ static void setup_received_irq(struct fsl_udc *udc,
1372 if (ep0_prime_status(udc, EP_DIR_IN)) 1418 if (ep0_prime_status(udc, EP_DIR_IN))
1373 ep0stall(udc); 1419 ep0stall(udc);
1374 } 1420 }
1421 if (ptc) {
1422 u32 tmp;
1423
1424 mdelay(10);
1425 tmp = fsl_readl(&dr_regs->portsc1) | (ptc << 16);
1426 fsl_writel(tmp, &dr_regs->portsc1);
1427 printk(KERN_INFO "udc: switch to test mode %d.\n", ptc);
1428 }
1429
1375 return; 1430 return;
1376 } 1431 }
1377 1432
@@ -2106,16 +2161,18 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count,
2106 next += t; 2161 next += t;
2107 2162
2108#ifndef CONFIG_ARCH_MXC 2163#ifndef CONFIG_ARCH_MXC
2109 tmp_reg = usb_sys_regs->snoop1; 2164 if (udc->pdata->have_sysif_regs) {
2110 t = scnprintf(next, size, "Snoop1 Reg : = [0x%x]\n\n", tmp_reg); 2165 tmp_reg = usb_sys_regs->snoop1;
2111 size -= t; 2166 t = scnprintf(next, size, "Snoop1 Reg : = [0x%x]\n\n", tmp_reg);
2112 next += t; 2167 size -= t;
2168 next += t;
2113 2169
2114 tmp_reg = usb_sys_regs->control; 2170 tmp_reg = usb_sys_regs->control;
2115 t = scnprintf(next, size, "General Control Reg : = [0x%x]\n\n", 2171 t = scnprintf(next, size, "General Control Reg : = [0x%x]\n\n",
2116 tmp_reg); 2172 tmp_reg);
2117 size -= t; 2173 size -= t;
2118 next += t; 2174 next += t;
2175 }
2119#endif 2176#endif
2120 2177
2121 /* ------fsl_udc, fsl_ep, fsl_request structure information ----- */ 2178 /* ------fsl_udc, fsl_ep, fsl_request structure information ----- */
@@ -2336,6 +2393,17 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
2336 goto err_release_mem_region; 2393 goto err_release_mem_region;
2337 } 2394 }
2338 2395
2396 pdata->regs = (void *)dr_regs;
2397
2398 /*
2399 * do platform specific init: check the clock, grab/config pins, etc.
2400 */
2401 if (pdata->init && pdata->init(pdev)) {
2402 ret = -ENODEV;
2403 goto err_iounmap_noclk;
2404 }
2405
2406 /* Set accessors only after pdata->init() ! */
2339 if (pdata->big_endian_mmio) { 2407 if (pdata->big_endian_mmio) {
2340 _fsl_readl = _fsl_readl_be; 2408 _fsl_readl = _fsl_readl_be;
2341 _fsl_writel = _fsl_writel_be; 2409 _fsl_writel = _fsl_writel_be;
@@ -2345,8 +2413,9 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
2345 } 2413 }
2346 2414
2347#ifndef CONFIG_ARCH_MXC 2415#ifndef CONFIG_ARCH_MXC
2348 usb_sys_regs = (struct usb_sys_interface *) 2416 if (pdata->have_sysif_regs)
2349 ((u32)dr_regs + USB_DR_SYS_OFFSET); 2417 usb_sys_regs = (struct usb_sys_interface *)
2418 ((u32)dr_regs + USB_DR_SYS_OFFSET);
2350#endif 2419#endif
2351 2420
2352 /* Initialize USB clocks */ 2421 /* Initialize USB clocks */
@@ -2446,6 +2515,8 @@ err_unregister:
2446err_free_irq: 2515err_free_irq:
2447 free_irq(udc_controller->irq, udc_controller); 2516 free_irq(udc_controller->irq, udc_controller);
2448err_iounmap: 2517err_iounmap:
2518 if (pdata->exit)
2519 pdata->exit(pdev);
2449 fsl_udc_clk_release(); 2520 fsl_udc_clk_release();
2450err_iounmap_noclk: 2521err_iounmap_noclk:
2451 iounmap(dr_regs); 2522 iounmap(dr_regs);
@@ -2463,6 +2534,7 @@ err_kfree:
2463static int __exit fsl_udc_remove(struct platform_device *pdev) 2534static int __exit fsl_udc_remove(struct platform_device *pdev)
2464{ 2535{
2465 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 2536 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2537 struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
2466 2538
2467 DECLARE_COMPLETION(done); 2539 DECLARE_COMPLETION(done);
2468 2540
@@ -2489,6 +2561,13 @@ static int __exit fsl_udc_remove(struct platform_device *pdev)
2489 /* free udc --wait for the release() finished */ 2561 /* free udc --wait for the release() finished */
2490 wait_for_completion(&done); 2562 wait_for_completion(&done);
2491 2563
2564 /*
2565 * do platform specific un-initialization:
2566 * release iomux pins, etc.
2567 */
2568 if (pdata->exit)
2569 pdata->exit(pdev);
2570
2492 return 0; 2571 return 0;
2493} 2572}
2494 2573
diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h
index 24efba93cef5..5647cc21b84c 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.h
+++ b/drivers/usb/gadget/fsl_usb2_udc.h
@@ -275,7 +275,9 @@ struct usb_sys_interface {
275#define USB_MODE_CTRL_MODE_IDLE 0x00000000 275#define USB_MODE_CTRL_MODE_IDLE 0x00000000
276#define USB_MODE_CTRL_MODE_DEVICE 0x00000002 276#define USB_MODE_CTRL_MODE_DEVICE 0x00000002
277#define USB_MODE_CTRL_MODE_HOST 0x00000003 277#define USB_MODE_CTRL_MODE_HOST 0x00000003
278#define USB_MODE_CTRL_MODE_MASK 0x00000003
278#define USB_MODE_CTRL_MODE_RSV 0x00000001 279#define USB_MODE_CTRL_MODE_RSV 0x00000001
280#define USB_MODE_ES 0x00000004 /* Endian Select */
279#define USB_MODE_SETUP_LOCK_OFF 0x00000008 281#define USB_MODE_SETUP_LOCK_OFF 0x00000008
280#define USB_MODE_STREAM_DISABLE 0x00000010 282#define USB_MODE_STREAM_DISABLE 0x00000010
281/* Endpoint Flush Register */ 283/* Endpoint Flush Register */