Skip to content

Commit 2ea6698

Browse files
vdsaogregkh
authored andcommitted
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 <[email protected]> Cc: Li Yang <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 09ba0de commit 2ea6698

File tree

2 files changed

+112
-31
lines changed

2 files changed

+112
-31
lines changed

drivers/usb/gadget/fsl_udc_core.c

Lines changed: 110 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
* Description:
88
* 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.
1010
* The driver is previously named as mpc_udc. Based on bare board
1111
* code from Dave Liu and Shlomi Gridish.
1212
*
@@ -45,6 +45,7 @@
4545
#include <asm/system.h>
4646
#include <asm/unaligned.h>
4747
#include <asm/dma.h>
48+
#include <asm/cacheflush.h>
4849

4950
#include "fsl_usb2_udc.h"
5051

@@ -278,9 +279,12 @@ static int dr_controller_setup(struct fsl_udc *udc)
278279

279280
/* Set the controller as device mode */
280281
tmp = fsl_readl(&dr_regs->usbmode);
282+
tmp &= ~USB_MODE_CTRL_MODE_MASK; /* clear mode bits */
281283
tmp |= USB_MODE_CTRL_MODE_DEVICE;
282284
/* Disable Setup Lockout */
283285
tmp |= USB_MODE_SETUP_LOCK_OFF;
286+
if (udc->pdata->es)
287+
tmp |= USB_MODE_ES;
284288
fsl_writel(tmp, &dr_regs->usbmode);
285289

286290
/* Clear the setup status */
@@ -296,20 +300,24 @@ static int dr_controller_setup(struct fsl_udc *udc)
296300

297301
/* Config control enable i/o output, cpu endian register */
298302
#ifndef CONFIG_ARCH_MXC
299-
ctrl = __raw_readl(&usb_sys_regs->control);
300-
ctrl |= USB_CTRL_IOENB;
301-
__raw_writel(ctrl, &usb_sys_regs->control);
303+
if (udc->pdata->have_sysif_regs) {
304+
ctrl = __raw_readl(&usb_sys_regs->control);
305+
ctrl |= USB_CTRL_IOENB;
306+
__raw_writel(ctrl, &usb_sys_regs->control);
307+
}
302308
#endif
303309

304310
#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
305311
/* Turn on cache snooping hardware, since some PowerPC platforms
306312
* wholly rely on hardware to deal with cache coherent. */
307313

308-
/* Setup Snooping for all the 4GB space */
309-
tmp = SNOOP_SIZE_2GB; /* starts from 0x0, size 2G */
310-
__raw_writel(tmp, &usb_sys_regs->snoop1);
311-
tmp |= 0x80000000; /* starts from 0x8000000, size 2G */
312-
__raw_writel(tmp, &usb_sys_regs->snoop2);
314+
if (udc->pdata->have_sysif_regs) {
315+
/* Setup Snooping for all the 4GB space */
316+
tmp = SNOOP_SIZE_2GB; /* starts from 0x0, size 2G */
317+
__raw_writel(tmp, &usb_sys_regs->snoop1);
318+
tmp |= 0x80000000; /* starts from 0x8000000, size 2G */
319+
__raw_writel(tmp, &usb_sys_regs->snoop2);
320+
}
313321
#endif
314322

315323
return 0;
@@ -1014,6 +1022,36 @@ static int fsl_ep_set_halt(struct usb_ep *_ep, int value)
10141022
return status;
10151023
}
10161024

1025+
static 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+
10171055
static void fsl_ep_fifo_flush(struct usb_ep *_ep)
10181056
{
10191057
struct fsl_ep *ep;
@@ -1066,6 +1104,7 @@ static struct usb_ep_ops fsl_ep_ops = {
10661104
.dequeue = fsl_ep_dequeue,
10671105

10681106
.set_halt = fsl_ep_set_halt,
1107+
.fifo_status = fsl_ep_fifo_status,
10691108
.fifo_flush = fsl_ep_fifo_flush, /* flush fifo */
10701109
};
10711110

@@ -1280,6 +1319,10 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,
12801319
req = udc->status_req;
12811320
/* Fill in the reqest structure */
12821321
*((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+
12831326
req->ep = ep;
12841327
req->req.length = 2;
12851328
req->req.status = -EINPROGRESS;
@@ -1332,6 +1375,7 @@ static void setup_received_irq(struct fsl_udc *udc,
13321375
/* Status phase from udc */
13331376
{
13341377
int rc = -EOPNOTSUPP;
1378+
u16 ptc = 0;
13351379

13361380
if ((setup->bRequestType & (USB_RECIP_MASK | USB_TYPE_MASK))
13371381
== (USB_RECIP_ENDPOINT | USB_TYPE_STANDARD)) {
@@ -1353,17 +1397,19 @@ static void setup_received_irq(struct fsl_udc *udc,
13531397
| USB_TYPE_STANDARD)) {
13541398
/* Note: The driver has not include OTG support yet.
13551399
* This will be set when OTG support is added */
1356-
if (!gadget_is_otg(&udc->gadget))
1357-
break;
1358-
else if (setup->bRequest == USB_DEVICE_B_HNP_ENABLE)
1359-
udc->gadget.b_hnp_enable = 1;
1360-
else if (setup->bRequest == USB_DEVICE_A_HNP_SUPPORT)
1361-
udc->gadget.a_hnp_support = 1;
1362-
else if (setup->bRequest ==
1363-
USB_DEVICE_A_ALT_HNP_SUPPORT)
1364-
udc->gadget.a_alt_hnp_support = 1;
1365-
else
1366-
break;
1400+
if (wValue == USB_DEVICE_TEST_MODE)
1401+
ptc = wIndex >> 8;
1402+
else if (gadget_is_otg(&udc->gadget)) {
1403+
if (setup->bRequest ==
1404+
USB_DEVICE_B_HNP_ENABLE)
1405+
udc->gadget.b_hnp_enable = 1;
1406+
else if (setup->bRequest ==
1407+
USB_DEVICE_A_HNP_SUPPORT)
1408+
udc->gadget.a_hnp_support = 1;
1409+
else if (setup->bRequest ==
1410+
USB_DEVICE_A_ALT_HNP_SUPPORT)
1411+
udc->gadget.a_alt_hnp_support = 1;
1412+
}
13671413
rc = 0;
13681414
} else
13691415
break;
@@ -1372,6 +1418,15 @@ static void setup_received_irq(struct fsl_udc *udc,
13721418
if (ep0_prime_status(udc, EP_DIR_IN))
13731419
ep0stall(udc);
13741420
}
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+
13751430
return;
13761431
}
13771432

@@ -2106,16 +2161,18 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count,
21062161
next += t;
21072162

21082163
#ifndef CONFIG_ARCH_MXC
2109-
tmp_reg = usb_sys_regs->snoop1;
2110-
t = scnprintf(next, size, "Snoop1 Reg : = [0x%x]\n\n", tmp_reg);
2111-
size -= t;
2112-
next += t;
2164+
if (udc->pdata->have_sysif_regs) {
2165+
tmp_reg = usb_sys_regs->snoop1;
2166+
t = scnprintf(next, size, "Snoop1 Reg : = [0x%x]\n\n", tmp_reg);
2167+
size -= t;
2168+
next += t;
21132169

2114-
tmp_reg = usb_sys_regs->control;
2115-
t = scnprintf(next, size, "General Control Reg : = [0x%x]\n\n",
2116-
tmp_reg);
2117-
size -= t;
2118-
next += t;
2170+
tmp_reg = usb_sys_regs->control;
2171+
t = scnprintf(next, size, "General Control Reg : = [0x%x]\n\n",
2172+
tmp_reg);
2173+
size -= t;
2174+
next += t;
2175+
}
21192176
#endif
21202177

21212178
/* ------fsl_udc, fsl_ep, fsl_request structure information ----- */
@@ -2336,6 +2393,17 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
23362393
goto err_release_mem_region;
23372394
}
23382395

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() ! */
23392407
if (pdata->big_endian_mmio) {
23402408
_fsl_readl = _fsl_readl_be;
23412409
_fsl_writel = _fsl_writel_be;
@@ -2345,8 +2413,9 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
23452413
}
23462414

23472415
#ifndef CONFIG_ARCH_MXC
2348-
usb_sys_regs = (struct usb_sys_interface *)
2349-
((u32)dr_regs + USB_DR_SYS_OFFSET);
2416+
if (pdata->have_sysif_regs)
2417+
usb_sys_regs = (struct usb_sys_interface *)
2418+
((u32)dr_regs + USB_DR_SYS_OFFSET);
23502419
#endif
23512420

23522421
/* Initialize USB clocks */
@@ -2446,6 +2515,8 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
24462515
err_free_irq:
24472516
free_irq(udc_controller->irq, udc_controller);
24482517
err_iounmap:
2518+
if (pdata->exit)
2519+
pdata->exit(pdev);
24492520
fsl_udc_clk_release();
24502521
err_iounmap_noclk:
24512522
iounmap(dr_regs);
@@ -2463,6 +2534,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
24632534
static int __exit fsl_udc_remove(struct platform_device *pdev)
24642535
{
24652536
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2537+
struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
24662538

24672539
DECLARE_COMPLETION(done);
24682540

@@ -2489,6 +2561,13 @@ static int __exit fsl_udc_remove(struct platform_device *pdev)
24892561
/* free udc --wait for the release() finished */
24902562
wait_for_completion(&done);
24912563

2564+
/*
2565+
* do platform specific un-initialization:
2566+
* release iomux pins, etc.
2567+
*/
2568+
if (pdata->exit)
2569+
pdata->exit(pdev);
2570+
24922571
return 0;
24932572
}
24942573

drivers/usb/gadget/fsl_usb2_udc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,9 @@ struct usb_sys_interface {
275275
#define USB_MODE_CTRL_MODE_IDLE 0x00000000
276276
#define USB_MODE_CTRL_MODE_DEVICE 0x00000002
277277
#define USB_MODE_CTRL_MODE_HOST 0x00000003
278+
#define USB_MODE_CTRL_MODE_MASK 0x00000003
278279
#define USB_MODE_CTRL_MODE_RSV 0x00000001
280+
#define USB_MODE_ES 0x00000004 /* Endian Select */
279281
#define USB_MODE_SETUP_LOCK_OFF 0x00000008
280282
#define USB_MODE_STREAM_DISABLE 0x00000010
281283
/* Endpoint Flush Register */

0 commit comments

Comments
 (0)