Commit 4365831d authored by Li Yang's avatar Li Yang Committed by Greg Kroah-Hartman

USB: fsl_usb2_udc: Get max ep number from DCCPARAMS register

Currently the driver is expecting max ep number in platform
data which isn't passing this information.  This patch fix
the problem by reading it from DCCPARAMS(Device Controller
Capability Parameters) register.  The change also need some
reordering of the probe code.
Signed-off-by: default avatarLi Yang <leoli@freescale.com>
Signed-off-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 37b5453d
...@@ -2189,27 +2189,19 @@ static void fsl_udc_release(struct device *dev) ...@@ -2189,27 +2189,19 @@ static void fsl_udc_release(struct device *dev)
* init resource for globle controller * init resource for globle controller
* Return the udc handle on success or NULL on failure * Return the udc handle on success or NULL on failure
------------------------------------------------------------------*/ ------------------------------------------------------------------*/
static struct fsl_udc *__init struct_udc_setup(struct platform_device *pdev) static int __init struct_udc_setup(struct fsl_udc *udc,
struct platform_device *pdev)
{ {
struct fsl_udc *udc;
struct fsl_usb2_platform_data *pdata; struct fsl_usb2_platform_data *pdata;
size_t size; size_t size;
udc = kzalloc(sizeof(struct fsl_udc), GFP_KERNEL);
if (udc == NULL) {
ERR("malloc udc failed\n");
return NULL;
}
pdata = pdev->dev.platform_data; pdata = pdev->dev.platform_data;
udc->phy_mode = pdata->phy_mode; udc->phy_mode = pdata->phy_mode;
/* max_ep_nr is bidirectional ep number, max_ep doubles the number */
udc->max_ep = pdata->max_ep_nr * 2;
udc->eps = kzalloc(sizeof(struct fsl_ep) * udc->max_ep, GFP_KERNEL); udc->eps = kzalloc(sizeof(struct fsl_ep) * udc->max_ep, GFP_KERNEL);
if (!udc->eps) { if (!udc->eps) {
ERR("malloc fsl_ep failed\n"); ERR("malloc fsl_ep failed\n");
goto cleanup; return -1;
} }
/* initialized QHs, take care of alignment */ /* initialized QHs, take care of alignment */
...@@ -2225,7 +2217,7 @@ static struct fsl_udc *__init struct_udc_setup(struct platform_device *pdev) ...@@ -2225,7 +2217,7 @@ static struct fsl_udc *__init struct_udc_setup(struct platform_device *pdev)
if (!udc->ep_qh) { if (!udc->ep_qh) {
ERR("malloc QHs for udc failed\n"); ERR("malloc QHs for udc failed\n");
kfree(udc->eps); kfree(udc->eps);
goto cleanup; return -1;
} }
udc->ep_qh_size = size; udc->ep_qh_size = size;
...@@ -2244,11 +2236,7 @@ static struct fsl_udc *__init struct_udc_setup(struct platform_device *pdev) ...@@ -2244,11 +2236,7 @@ static struct fsl_udc *__init struct_udc_setup(struct platform_device *pdev)
udc->remote_wakeup = 0; /* default to 0 on reset */ udc->remote_wakeup = 0; /* default to 0 on reset */
spin_lock_init(&udc->lock); spin_lock_init(&udc->lock);
return udc; return 0;
cleanup:
kfree(udc);
return NULL;
} }
/*---------------------------------------------------------------- /*----------------------------------------------------------------
...@@ -2287,35 +2275,37 @@ static int __init struct_ep_setup(struct fsl_udc *udc, unsigned char index, ...@@ -2287,35 +2275,37 @@ static int __init struct_ep_setup(struct fsl_udc *udc, unsigned char index,
} }
/* Driver probe function /* Driver probe function
* all intialize operations implemented here except enabling usb_intr reg * all intialization operations implemented here except enabling usb_intr reg
* board setup should have been done in the platform code
*/ */
static int __init fsl_udc_probe(struct platform_device *pdev) static int __init fsl_udc_probe(struct platform_device *pdev)
{ {
struct resource *res; struct resource *res;
int ret = -ENODEV; int ret = -ENODEV;
unsigned int i; unsigned int i;
u32 dccparams;
if (strcmp(pdev->name, driver_name)) { if (strcmp(pdev->name, driver_name)) {
VDBG("Wrong device\n"); VDBG("Wrong device\n");
return -ENODEV; return -ENODEV;
} }
/* board setup should have been done in the platform code */ udc_controller = kzalloc(sizeof(struct fsl_udc), GFP_KERNEL);
if (udc_controller == NULL) {
/* Initialize the udc structure including QH member and other member */ ERR("malloc udc failed\n");
udc_controller = struct_udc_setup(pdev);
if (!udc_controller) {
VDBG("udc_controller is NULL \n");
return -ENOMEM; return -ENOMEM;
} }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) if (!res) {
kfree(udc_controller);
return -ENXIO; return -ENXIO;
}
if (!request_mem_region(res->start, res->end - res->start + 1, if (!request_mem_region(res->start, res->end - res->start + 1,
driver_name)) { driver_name)) {
ERR("request mem region for %s failed \n", pdev->name); ERR("request mem region for %s failed \n", pdev->name);
kfree(udc_controller);
return -EBUSY; return -EBUSY;
} }
...@@ -2328,6 +2318,17 @@ static int __init fsl_udc_probe(struct platform_device *pdev) ...@@ -2328,6 +2318,17 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
usb_sys_regs = (struct usb_sys_interface *) usb_sys_regs = (struct usb_sys_interface *)
((u32)dr_regs + USB_DR_SYS_OFFSET); ((u32)dr_regs + USB_DR_SYS_OFFSET);
/* Read Device Controller Capability Parameters register */
dccparams = fsl_readl(&dr_regs->dccparams);
if (!(dccparams & DCCPARAMS_DC)) {
ERR("This SOC doesn't support device role\n");
ret = -ENODEV;
goto err2;
}
/* Get max device endpoints */
/* DEN is bidirectional ep number, max_ep doubles the number */
udc_controller->max_ep = (dccparams & DCCPARAMS_DEN_MASK) * 2;
udc_controller->irq = platform_get_irq(pdev, 0); udc_controller->irq = platform_get_irq(pdev, 0);
if (!udc_controller->irq) { if (!udc_controller->irq) {
ret = -ENODEV; ret = -ENODEV;
...@@ -2342,6 +2343,13 @@ static int __init fsl_udc_probe(struct platform_device *pdev) ...@@ -2342,6 +2343,13 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
goto err2; goto err2;
} }
/* Initialize the udc structure including QH member and other member */
if (struct_udc_setup(udc_controller, pdev)) {
ERR("Can't initialize udc data structure\n");
ret = -ENOMEM;
goto err3;
}
/* initialize usb hw reg except for regs for EP, /* initialize usb hw reg except for regs for EP,
* leave usbintr reg untouched */ * leave usbintr reg untouched */
dr_controller_setup(udc_controller); dr_controller_setup(udc_controller);
...@@ -2403,6 +2411,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev) ...@@ -2403,6 +2411,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
iounmap(dr_regs); iounmap(dr_regs);
err1: err1:
release_mem_region(res->start, res->end - res->start + 1); release_mem_region(res->start, res->end - res->start + 1);
kfree(udc_controller);
return ret; return ret;
} }
......
...@@ -101,6 +101,10 @@ struct usb_sys_interface { ...@@ -101,6 +101,10 @@ struct usb_sys_interface {
#define WAIT_FOR_OUT_STATUS 3 #define WAIT_FOR_OUT_STATUS 3
#define DATA_STATE_RECV 4 #define DATA_STATE_RECV 4
/* Device Controller Capability Parameter register */
#define DCCPARAMS_DC 0x00000080
#define DCCPARAMS_DEN_MASK 0x0000001f
/* Frame Index Register Bit Masks */ /* Frame Index Register Bit Masks */
#define USB_FRINDEX_MASKS 0x3fff #define USB_FRINDEX_MASKS 0x3fff
/* USB CMD Register Bit Masks */ /* USB CMD Register Bit Masks */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment