diff options
Diffstat (limited to 'drivers/usb/gadget/fsl_usb2_udc.c')
-rw-r--r-- | drivers/usb/gadget/fsl_usb2_udc.c | 99 |
1 files changed, 36 insertions, 63 deletions
diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c index 3ca2b3159f00..10b2b33b8698 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.c +++ b/drivers/usb/gadget/fsl_usb2_udc.c | |||
@@ -228,7 +228,7 @@ static int dr_controller_setup(struct fsl_udc *udc) | |||
228 | 228 | ||
229 | /* Config PHY interface */ | 229 | /* Config PHY interface */ |
230 | portctrl = fsl_readl(&dr_regs->portsc1); | 230 | portctrl = fsl_readl(&dr_regs->portsc1); |
231 | portctrl &= ~(PORTSCX_PHY_TYPE_SEL & PORTSCX_PORT_WIDTH); | 231 | portctrl &= ~(PORTSCX_PHY_TYPE_SEL | PORTSCX_PORT_WIDTH); |
232 | switch (udc->phy_mode) { | 232 | switch (udc->phy_mode) { |
233 | case FSL_USB2_PHY_ULPI: | 233 | case FSL_USB2_PHY_ULPI: |
234 | portctrl |= PORTSCX_PTS_ULPI; | 234 | portctrl |= PORTSCX_PTS_ULPI; |
@@ -601,39 +601,6 @@ static void fsl_free_request(struct usb_ep *_ep, struct usb_request *_req) | |||
601 | kfree(req); | 601 | kfree(req); |
602 | } | 602 | } |
603 | 603 | ||
604 | /*------------------------------------------------------------------ | ||
605 | * Allocate an I/O buffer | ||
606 | *---------------------------------------------------------------------*/ | ||
607 | static void *fsl_alloc_buffer(struct usb_ep *_ep, unsigned bytes, | ||
608 | dma_addr_t *dma, gfp_t gfp_flags) | ||
609 | { | ||
610 | struct fsl_ep *ep; | ||
611 | |||
612 | if (!_ep) | ||
613 | return NULL; | ||
614 | |||
615 | ep = container_of(_ep, struct fsl_ep, ep); | ||
616 | |||
617 | return dma_alloc_coherent(ep->udc->gadget.dev.parent, | ||
618 | bytes, dma, gfp_flags); | ||
619 | } | ||
620 | |||
621 | /*------------------------------------------------------------------ | ||
622 | * frees an i/o buffer | ||
623 | *---------------------------------------------------------------------*/ | ||
624 | static void fsl_free_buffer(struct usb_ep *_ep, void *buf, | ||
625 | dma_addr_t dma, unsigned bytes) | ||
626 | { | ||
627 | struct fsl_ep *ep; | ||
628 | |||
629 | if (!_ep) | ||
630 | return; | ||
631 | |||
632 | ep = container_of(_ep, struct fsl_ep, ep); | ||
633 | |||
634 | dma_free_coherent(ep->udc->gadget.dev.parent, bytes, buf, dma); | ||
635 | } | ||
636 | |||
637 | /*-------------------------------------------------------------------------*/ | 604 | /*-------------------------------------------------------------------------*/ |
638 | static int fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req) | 605 | static int fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req) |
639 | { | 606 | { |
@@ -1047,9 +1014,6 @@ static struct usb_ep_ops fsl_ep_ops = { | |||
1047 | .alloc_request = fsl_alloc_request, | 1014 | .alloc_request = fsl_alloc_request, |
1048 | .free_request = fsl_free_request, | 1015 | .free_request = fsl_free_request, |
1049 | 1016 | ||
1050 | .alloc_buffer = fsl_alloc_buffer, | ||
1051 | .free_buffer = fsl_free_buffer, | ||
1052 | |||
1053 | .queue = fsl_ep_queue, | 1017 | .queue = fsl_ep_queue, |
1054 | .dequeue = fsl_ep_dequeue, | 1018 | .dequeue = fsl_ep_dequeue, |
1055 | 1019 | ||
@@ -2189,27 +2153,19 @@ static void fsl_udc_release(struct device *dev) | |||
2189 | * init resource for globle controller | 2153 | * init resource for globle controller |
2190 | * Return the udc handle on success or NULL on failure | 2154 | * Return the udc handle on success or NULL on failure |
2191 | ------------------------------------------------------------------*/ | 2155 | ------------------------------------------------------------------*/ |
2192 | static struct fsl_udc *__init struct_udc_setup(struct platform_device *pdev) | 2156 | static int __init struct_udc_setup(struct fsl_udc *udc, |
2157 | struct platform_device *pdev) | ||
2193 | { | 2158 | { |
2194 | struct fsl_udc *udc; | ||
2195 | struct fsl_usb2_platform_data *pdata; | 2159 | struct fsl_usb2_platform_data *pdata; |
2196 | size_t size; | 2160 | size_t size; |
2197 | 2161 | ||
2198 | udc = kzalloc(sizeof(struct fsl_udc), GFP_KERNEL); | ||
2199 | if (udc == NULL) { | ||
2200 | ERR("malloc udc failed\n"); | ||
2201 | return NULL; | ||
2202 | } | ||
2203 | |||
2204 | pdata = pdev->dev.platform_data; | 2162 | pdata = pdev->dev.platform_data; |
2205 | udc->phy_mode = pdata->phy_mode; | 2163 | udc->phy_mode = pdata->phy_mode; |
2206 | /* max_ep_nr is bidirectional ep number, max_ep doubles the number */ | ||
2207 | udc->max_ep = pdata->max_ep_nr * 2; | ||
2208 | 2164 | ||
2209 | udc->eps = kzalloc(sizeof(struct fsl_ep) * udc->max_ep, GFP_KERNEL); | 2165 | udc->eps = kzalloc(sizeof(struct fsl_ep) * udc->max_ep, GFP_KERNEL); |
2210 | if (!udc->eps) { | 2166 | if (!udc->eps) { |
2211 | ERR("malloc fsl_ep failed\n"); | 2167 | ERR("malloc fsl_ep failed\n"); |
2212 | goto cleanup; | 2168 | return -1; |
2213 | } | 2169 | } |
2214 | 2170 | ||
2215 | /* initialized QHs, take care of alignment */ | 2171 | /* initialized QHs, take care of alignment */ |
@@ -2225,7 +2181,7 @@ static struct fsl_udc *__init struct_udc_setup(struct platform_device *pdev) | |||
2225 | if (!udc->ep_qh) { | 2181 | if (!udc->ep_qh) { |
2226 | ERR("malloc QHs for udc failed\n"); | 2182 | ERR("malloc QHs for udc failed\n"); |
2227 | kfree(udc->eps); | 2183 | kfree(udc->eps); |
2228 | goto cleanup; | 2184 | return -1; |
2229 | } | 2185 | } |
2230 | 2186 | ||
2231 | udc->ep_qh_size = size; | 2187 | udc->ep_qh_size = size; |
@@ -2244,11 +2200,7 @@ static struct fsl_udc *__init struct_udc_setup(struct platform_device *pdev) | |||
2244 | udc->remote_wakeup = 0; /* default to 0 on reset */ | 2200 | udc->remote_wakeup = 0; /* default to 0 on reset */ |
2245 | spin_lock_init(&udc->lock); | 2201 | spin_lock_init(&udc->lock); |
2246 | 2202 | ||
2247 | return udc; | 2203 | return 0; |
2248 | |||
2249 | cleanup: | ||
2250 | kfree(udc); | ||
2251 | return NULL; | ||
2252 | } | 2204 | } |
2253 | 2205 | ||
2254 | /*---------------------------------------------------------------- | 2206 | /*---------------------------------------------------------------- |
@@ -2287,35 +2239,37 @@ static int __init struct_ep_setup(struct fsl_udc *udc, unsigned char index, | |||
2287 | } | 2239 | } |
2288 | 2240 | ||
2289 | /* Driver probe function | 2241 | /* Driver probe function |
2290 | * all intialize operations implemented here except enabling usb_intr reg | 2242 | * all intialization operations implemented here except enabling usb_intr reg |
2243 | * board setup should have been done in the platform code | ||
2291 | */ | 2244 | */ |
2292 | static int __init fsl_udc_probe(struct platform_device *pdev) | 2245 | static int __init fsl_udc_probe(struct platform_device *pdev) |
2293 | { | 2246 | { |
2294 | struct resource *res; | 2247 | struct resource *res; |
2295 | int ret = -ENODEV; | 2248 | int ret = -ENODEV; |
2296 | unsigned int i; | 2249 | unsigned int i; |
2250 | u32 dccparams; | ||
2297 | 2251 | ||
2298 | if (strcmp(pdev->name, driver_name)) { | 2252 | if (strcmp(pdev->name, driver_name)) { |
2299 | VDBG("Wrong device\n"); | 2253 | VDBG("Wrong device\n"); |
2300 | return -ENODEV; | 2254 | return -ENODEV; |
2301 | } | 2255 | } |
2302 | 2256 | ||
2303 | /* board setup should have been done in the platform code */ | 2257 | udc_controller = kzalloc(sizeof(struct fsl_udc), GFP_KERNEL); |
2304 | 2258 | if (udc_controller == NULL) { | |
2305 | /* Initialize the udc structure including QH member and other member */ | 2259 | ERR("malloc udc failed\n"); |
2306 | udc_controller = struct_udc_setup(pdev); | ||
2307 | if (!udc_controller) { | ||
2308 | VDBG("udc_controller is NULL \n"); | ||
2309 | return -ENOMEM; | 2260 | return -ENOMEM; |
2310 | } | 2261 | } |
2311 | 2262 | ||
2312 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 2263 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
2313 | if (!res) | 2264 | if (!res) { |
2265 | kfree(udc_controller); | ||
2314 | return -ENXIO; | 2266 | return -ENXIO; |
2267 | } | ||
2315 | 2268 | ||
2316 | if (!request_mem_region(res->start, res->end - res->start + 1, | 2269 | if (!request_mem_region(res->start, res->end - res->start + 1, |
2317 | driver_name)) { | 2270 | driver_name)) { |
2318 | ERR("request mem region for %s failed \n", pdev->name); | 2271 | ERR("request mem region for %s failed \n", pdev->name); |
2272 | kfree(udc_controller); | ||
2319 | return -EBUSY; | 2273 | return -EBUSY; |
2320 | } | 2274 | } |
2321 | 2275 | ||
@@ -2328,13 +2282,24 @@ static int __init fsl_udc_probe(struct platform_device *pdev) | |||
2328 | usb_sys_regs = (struct usb_sys_interface *) | 2282 | usb_sys_regs = (struct usb_sys_interface *) |
2329 | ((u32)dr_regs + USB_DR_SYS_OFFSET); | 2283 | ((u32)dr_regs + USB_DR_SYS_OFFSET); |
2330 | 2284 | ||
2285 | /* Read Device Controller Capability Parameters register */ | ||
2286 | dccparams = fsl_readl(&dr_regs->dccparams); | ||
2287 | if (!(dccparams & DCCPARAMS_DC)) { | ||
2288 | ERR("This SOC doesn't support device role\n"); | ||
2289 | ret = -ENODEV; | ||
2290 | goto err2; | ||
2291 | } | ||
2292 | /* Get max device endpoints */ | ||
2293 | /* DEN is bidirectional ep number, max_ep doubles the number */ | ||
2294 | udc_controller->max_ep = (dccparams & DCCPARAMS_DEN_MASK) * 2; | ||
2295 | |||
2331 | udc_controller->irq = platform_get_irq(pdev, 0); | 2296 | udc_controller->irq = platform_get_irq(pdev, 0); |
2332 | if (!udc_controller->irq) { | 2297 | if (!udc_controller->irq) { |
2333 | ret = -ENODEV; | 2298 | ret = -ENODEV; |
2334 | goto err2; | 2299 | goto err2; |
2335 | } | 2300 | } |
2336 | 2301 | ||
2337 | ret = request_irq(udc_controller->irq, fsl_udc_irq, SA_SHIRQ, | 2302 | ret = request_irq(udc_controller->irq, fsl_udc_irq, IRQF_SHARED, |
2338 | driver_name, udc_controller); | 2303 | driver_name, udc_controller); |
2339 | if (ret != 0) { | 2304 | if (ret != 0) { |
2340 | ERR("cannot request irq %d err %d \n", | 2305 | ERR("cannot request irq %d err %d \n", |
@@ -2342,6 +2307,13 @@ static int __init fsl_udc_probe(struct platform_device *pdev) | |||
2342 | goto err2; | 2307 | goto err2; |
2343 | } | 2308 | } |
2344 | 2309 | ||
2310 | /* Initialize the udc structure including QH member and other member */ | ||
2311 | if (struct_udc_setup(udc_controller, pdev)) { | ||
2312 | ERR("Can't initialize udc data structure\n"); | ||
2313 | ret = -ENOMEM; | ||
2314 | goto err3; | ||
2315 | } | ||
2316 | |||
2345 | /* initialize usb hw reg except for regs for EP, | 2317 | /* initialize usb hw reg except for regs for EP, |
2346 | * leave usbintr reg untouched */ | 2318 | * leave usbintr reg untouched */ |
2347 | dr_controller_setup(udc_controller); | 2319 | dr_controller_setup(udc_controller); |
@@ -2403,6 +2375,7 @@ err2: | |||
2403 | iounmap(dr_regs); | 2375 | iounmap(dr_regs); |
2404 | err1: | 2376 | err1: |
2405 | release_mem_region(res->start, res->end - res->start + 1); | 2377 | release_mem_region(res->start, res->end - res->start + 1); |
2378 | kfree(udc_controller); | ||
2406 | return ret; | 2379 | return ret; |
2407 | } | 2380 | } |
2408 | 2381 | ||