diff options
Diffstat (limited to 'drivers/usb/chipidea/core.c')
| -rw-r--r-- | drivers/usb/chipidea/core.c | 70 |
1 files changed, 64 insertions, 6 deletions
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 15e03b308f8a..1083585fad00 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c | |||
| @@ -56,6 +56,7 @@ | |||
| 56 | #include <linux/init.h> | 56 | #include <linux/init.h> |
| 57 | #include <linux/platform_device.h> | 57 | #include <linux/platform_device.h> |
| 58 | #include <linux/module.h> | 58 | #include <linux/module.h> |
| 59 | #include <linux/idr.h> | ||
| 59 | #include <linux/interrupt.h> | 60 | #include <linux/interrupt.h> |
| 60 | #include <linux/io.h> | 61 | #include <linux/io.h> |
| 61 | #include <linux/irq.h> | 62 | #include <linux/irq.h> |
| @@ -179,7 +180,7 @@ static int hw_device_init(struct ci13xxx *ci, void __iomem *base) | |||
| 179 | ci->hw_bank.abs = base; | 180 | ci->hw_bank.abs = base; |
| 180 | 181 | ||
| 181 | ci->hw_bank.cap = ci->hw_bank.abs; | 182 | ci->hw_bank.cap = ci->hw_bank.abs; |
| 182 | ci->hw_bank.cap += ci->udc_driver->capoffset; | 183 | ci->hw_bank.cap += ci->platdata->capoffset; |
| 183 | ci->hw_bank.op = ci->hw_bank.cap + ioread8(ci->hw_bank.cap); | 184 | ci->hw_bank.op = ci->hw_bank.cap + ioread8(ci->hw_bank.cap); |
| 184 | 185 | ||
| 185 | hw_alloc_regmap(ci, false); | 186 | hw_alloc_regmap(ci, false); |
| @@ -227,11 +228,11 @@ int hw_device_reset(struct ci13xxx *ci, u32 mode) | |||
| 227 | udelay(10); /* not RTOS friendly */ | 228 | udelay(10); /* not RTOS friendly */ |
| 228 | 229 | ||
| 229 | 230 | ||
| 230 | if (ci->udc_driver->notify_event) | 231 | if (ci->platdata->notify_event) |
| 231 | ci->udc_driver->notify_event(ci, | 232 | ci->platdata->notify_event(ci, |
| 232 | CI13XXX_CONTROLLER_RESET_EVENT); | 233 | CI13XXX_CONTROLLER_RESET_EVENT); |
| 233 | 234 | ||
| 234 | if (ci->udc_driver->flags & CI13XXX_DISABLE_STREAMING) | 235 | if (ci->platdata->flags & CI13XXX_DISABLE_STREAMING) |
| 235 | hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS); | 236 | hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS); |
| 236 | 237 | ||
| 237 | /* USBMODE should be configured step by step */ | 238 | /* USBMODE should be configured step by step */ |
| @@ -332,6 +333,59 @@ static irqreturn_t ci_irq(int irq, void *data) | |||
| 332 | return ci->role == CI_ROLE_END ? ret : ci_role(ci)->irq(ci); | 333 | return ci->role == CI_ROLE_END ? ret : ci_role(ci)->irq(ci); |
| 333 | } | 334 | } |
| 334 | 335 | ||
| 336 | static DEFINE_IDA(ci_ida); | ||
| 337 | |||
| 338 | struct platform_device *ci13xxx_add_device(struct device *dev, | ||
| 339 | struct resource *res, int nres, | ||
| 340 | struct ci13xxx_platform_data *platdata) | ||
| 341 | { | ||
| 342 | struct platform_device *pdev; | ||
| 343 | int id, ret; | ||
| 344 | |||
| 345 | id = ida_simple_get(&ci_ida, 0, 0, GFP_KERNEL); | ||
| 346 | if (id < 0) | ||
| 347 | return ERR_PTR(id); | ||
| 348 | |||
| 349 | pdev = platform_device_alloc("ci_hdrc", id); | ||
| 350 | if (!pdev) { | ||
| 351 | ret = -ENOMEM; | ||
| 352 | goto put_id; | ||
| 353 | } | ||
| 354 | |||
| 355 | pdev->dev.parent = dev; | ||
| 356 | pdev->dev.dma_mask = dev->dma_mask; | ||
| 357 | pdev->dev.dma_parms = dev->dma_parms; | ||
| 358 | dma_set_coherent_mask(&pdev->dev, dev->coherent_dma_mask); | ||
| 359 | |||
| 360 | ret = platform_device_add_resources(pdev, res, nres); | ||
| 361 | if (ret) | ||
| 362 | goto err; | ||
| 363 | |||
| 364 | ret = platform_device_add_data(pdev, platdata, sizeof(*platdata)); | ||
| 365 | if (ret) | ||
| 366 | goto err; | ||
| 367 | |||
| 368 | ret = platform_device_add(pdev); | ||
| 369 | if (ret) | ||
| 370 | goto err; | ||
| 371 | |||
| 372 | return pdev; | ||
| 373 | |||
| 374 | err: | ||
| 375 | platform_device_put(pdev); | ||
| 376 | put_id: | ||
| 377 | ida_simple_remove(&ci_ida, id); | ||
| 378 | return ERR_PTR(ret); | ||
| 379 | } | ||
| 380 | EXPORT_SYMBOL_GPL(ci13xxx_add_device); | ||
| 381 | |||
| 382 | void ci13xxx_remove_device(struct platform_device *pdev) | ||
| 383 | { | ||
| 384 | platform_device_unregister(pdev); | ||
| 385 | ida_simple_remove(&ci_ida, pdev->id); | ||
| 386 | } | ||
| 387 | EXPORT_SYMBOL_GPL(ci13xxx_remove_device); | ||
| 388 | |||
| 335 | static int __devinit ci_hdrc_probe(struct platform_device *pdev) | 389 | static int __devinit ci_hdrc_probe(struct platform_device *pdev) |
| 336 | { | 390 | { |
| 337 | struct device *dev = &pdev->dev; | 391 | struct device *dev = &pdev->dev; |
| @@ -364,7 +418,11 @@ static int __devinit ci_hdrc_probe(struct platform_device *pdev) | |||
| 364 | } | 418 | } |
| 365 | 419 | ||
| 366 | ci->dev = dev; | 420 | ci->dev = dev; |
| 367 | ci->udc_driver = dev->platform_data; | 421 | ci->platdata = dev->platform_data; |
| 422 | if (ci->platdata->phy) | ||
| 423 | ci->transceiver = ci->platdata->phy; | ||
| 424 | else | ||
| 425 | ci->global_phy = true; | ||
| 368 | 426 | ||
| 369 | ret = hw_device_init(ci, base); | 427 | ret = hw_device_init(ci, base); |
| 370 | if (ret < 0) { | 428 | if (ret < 0) { |
| @@ -419,7 +477,7 @@ static int __devinit ci_hdrc_probe(struct platform_device *pdev) | |||
| 419 | } | 477 | } |
| 420 | 478 | ||
| 421 | platform_set_drvdata(pdev, ci); | 479 | platform_set_drvdata(pdev, ci); |
| 422 | ret = request_irq(ci->irq, ci_irq, IRQF_SHARED, ci->udc_driver->name, | 480 | ret = request_irq(ci->irq, ci_irq, IRQF_SHARED, ci->platdata->name, |
| 423 | ci); | 481 | ci); |
| 424 | if (ret) | 482 | if (ret) |
| 425 | goto stop; | 483 | goto stop; |
