0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/module.h>
0012 #include <linux/kernel.h>
0013 #include <linux/sched.h>
0014 #include <linux/init.h>
0015 #include <linux/list.h>
0016 #include <linux/io.h>
0017 #include <linux/of.h>
0018 #include <linux/platform_device.h>
0019 #include <linux/dma-mapping.h>
0020 #include <linux/pm_runtime.h>
0021 #include <linux/err.h>
0022 #include <linux/delay.h>
0023 #include <linux/usb/musb.h>
0024 #include <linux/phy/omap_control_phy.h>
0025 #include <linux/of_platform.h>
0026
0027 #include "musb_core.h"
0028 #include "omap2430.h"
0029
0030 struct omap2430_glue {
0031 struct device *dev;
0032 struct platform_device *musb;
0033 enum musb_vbus_id_status status;
0034 struct work_struct omap_musb_mailbox_work;
0035 struct device *control_otghs;
0036 unsigned int is_runtime_suspended:1;
0037 unsigned int needs_resume:1;
0038 unsigned int phy_suspended:1;
0039 };
0040 #define glue_to_musb(g) platform_get_drvdata(g->musb)
0041
0042 static struct omap2430_glue *_glue;
0043
0044 static inline void omap2430_low_level_exit(struct musb *musb)
0045 {
0046 u32 l;
0047
0048
0049 l = musb_readl(musb->mregs, OTG_FORCESTDBY);
0050 l |= ENABLEFORCE;
0051 musb_writel(musb->mregs, OTG_FORCESTDBY, l);
0052 }
0053
0054 static inline void omap2430_low_level_init(struct musb *musb)
0055 {
0056 u32 l;
0057
0058 l = musb_readl(musb->mregs, OTG_FORCESTDBY);
0059 l &= ~ENABLEFORCE;
0060 musb_writel(musb->mregs, OTG_FORCESTDBY, l);
0061 }
0062
0063 static int omap2430_musb_mailbox(enum musb_vbus_id_status status)
0064 {
0065 struct omap2430_glue *glue = _glue;
0066
0067 if (!glue) {
0068 pr_err("%s: musb core is not yet initialized\n", __func__);
0069 return -EPROBE_DEFER;
0070 }
0071 glue->status = status;
0072
0073 if (!glue_to_musb(glue)) {
0074 pr_err("%s: musb core is not yet ready\n", __func__);
0075 return -EPROBE_DEFER;
0076 }
0077
0078 schedule_work(&glue->omap_musb_mailbox_work);
0079
0080 return 0;
0081 }
0082
0083
0084
0085
0086
0087
0088
0089
0090 static void omap_musb_set_mailbox(struct omap2430_glue *glue)
0091 {
0092 struct musb *musb = glue_to_musb(glue);
0093 int error;
0094
0095 pm_runtime_get_sync(musb->controller);
0096
0097 dev_dbg(musb->controller, "VBUS %s, devctl %02x\n",
0098 usb_otg_state_string(musb->xceiv->otg->state),
0099 musb_readb(musb->mregs, MUSB_DEVCTL));
0100
0101 switch (glue->status) {
0102 case MUSB_ID_GROUND:
0103 dev_dbg(musb->controller, "ID GND\n");
0104 switch (musb->xceiv->otg->state) {
0105 case OTG_STATE_A_IDLE:
0106 error = musb_set_host(musb);
0107 if (error)
0108 break;
0109 musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
0110 fallthrough;
0111 case OTG_STATE_A_WAIT_VRISE:
0112 case OTG_STATE_A_WAIT_BCON:
0113 case OTG_STATE_A_HOST:
0114
0115
0116
0117
0118 otg_set_vbus(musb->xceiv->otg, 1);
0119 break;
0120 default:
0121 musb->xceiv->otg->state = OTG_STATE_A_IDLE;
0122 musb->xceiv->last_event = USB_EVENT_ID;
0123 if (musb->gadget_driver) {
0124 omap_control_usb_set_mode(glue->control_otghs,
0125 USB_MODE_HOST);
0126 otg_set_vbus(musb->xceiv->otg, 1);
0127 }
0128 break;
0129 }
0130 break;
0131
0132 case MUSB_VBUS_VALID:
0133 dev_dbg(musb->controller, "VBUS Connect\n");
0134
0135 musb->xceiv->otg->state = OTG_STATE_B_IDLE;
0136 musb->xceiv->last_event = USB_EVENT_VBUS;
0137 omap_control_usb_set_mode(glue->control_otghs, USB_MODE_DEVICE);
0138 break;
0139
0140 case MUSB_ID_FLOAT:
0141 case MUSB_VBUS_OFF:
0142 dev_dbg(musb->controller, "VBUS Disconnect\n");
0143
0144 musb->xceiv->last_event = USB_EVENT_NONE;
0145 musb_set_peripheral(musb);
0146 otg_set_vbus(musb->xceiv->otg, 0);
0147 omap_control_usb_set_mode(glue->control_otghs,
0148 USB_MODE_DISCONNECT);
0149 break;
0150 default:
0151 dev_dbg(musb->controller, "ID float\n");
0152 }
0153 pm_runtime_mark_last_busy(musb->controller);
0154 pm_runtime_put_autosuspend(musb->controller);
0155 atomic_notifier_call_chain(&musb->xceiv->notifier,
0156 musb->xceiv->last_event, NULL);
0157 }
0158
0159
0160 static void omap_musb_mailbox_work(struct work_struct *mailbox_work)
0161 {
0162 struct omap2430_glue *glue = container_of(mailbox_work,
0163 struct omap2430_glue, omap_musb_mailbox_work);
0164
0165 omap_musb_set_mailbox(glue);
0166 }
0167
0168 static irqreturn_t omap2430_musb_interrupt(int irq, void *__hci)
0169 {
0170 unsigned long flags;
0171 irqreturn_t retval = IRQ_NONE;
0172 struct musb *musb = __hci;
0173
0174 spin_lock_irqsave(&musb->lock, flags);
0175
0176 musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
0177 musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
0178 musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
0179
0180 if (musb->int_usb || musb->int_tx || musb->int_rx)
0181 retval = musb_interrupt(musb);
0182
0183 spin_unlock_irqrestore(&musb->lock, flags);
0184
0185 return retval;
0186 }
0187
0188 static int omap2430_musb_init(struct musb *musb)
0189 {
0190 u32 l;
0191 int status = 0;
0192 struct device *dev = musb->controller;
0193 struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
0194 struct omap_musb_board_data *data = plat->board_data;
0195
0196
0197
0198
0199
0200 musb->phy = devm_phy_get(dev->parent, "usb2-phy");
0201
0202
0203
0204
0205
0206
0207
0208 musb->xceiv = devm_usb_get_phy_by_phandle(dev->parent, "usb-phy", 0);
0209
0210 if (IS_ERR(musb->xceiv)) {
0211 status = PTR_ERR(musb->xceiv);
0212
0213 if (status == -ENXIO)
0214 return status;
0215
0216 dev_dbg(dev, "HS USB OTG: no transceiver configured\n");
0217 return -EPROBE_DEFER;
0218 }
0219
0220 if (IS_ERR(musb->phy)) {
0221 dev_err(dev, "HS USB OTG: no PHY configured\n");
0222 return PTR_ERR(musb->phy);
0223 }
0224 musb->isr = omap2430_musb_interrupt;
0225 phy_init(musb->phy);
0226 phy_power_on(musb->phy);
0227
0228 l = musb_readl(musb->mregs, OTG_INTERFSEL);
0229
0230 if (data->interface_type == MUSB_INTERFACE_UTMI) {
0231
0232 l &= ~ULPI_12PIN;
0233 l |= UTMI_8BIT;
0234 } else {
0235 l |= ULPI_12PIN;
0236 }
0237
0238 musb_writel(musb->mregs, OTG_INTERFSEL, l);
0239
0240 dev_dbg(dev, "HS USB OTG: revision 0x%x, sysconfig 0x%02x, "
0241 "sysstatus 0x%x, intrfsel 0x%x, simenable 0x%x\n",
0242 musb_readl(musb->mregs, OTG_REVISION),
0243 musb_readl(musb->mregs, OTG_SYSCONFIG),
0244 musb_readl(musb->mregs, OTG_SYSSTATUS),
0245 musb_readl(musb->mregs, OTG_INTERFSEL),
0246 musb_readl(musb->mregs, OTG_SIMENABLE));
0247
0248 return 0;
0249 }
0250
0251 static void omap2430_musb_enable(struct musb *musb)
0252 {
0253 struct device *dev = musb->controller;
0254 struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
0255
0256 if (glue->status == MUSB_UNKNOWN)
0257 glue->status = MUSB_VBUS_OFF;
0258 omap_musb_set_mailbox(glue);
0259 }
0260
0261 static void omap2430_musb_disable(struct musb *musb)
0262 {
0263 struct device *dev = musb->controller;
0264 struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
0265
0266 if (glue->status != MUSB_UNKNOWN)
0267 omap_control_usb_set_mode(glue->control_otghs,
0268 USB_MODE_DISCONNECT);
0269 }
0270
0271 static int omap2430_musb_exit(struct musb *musb)
0272 {
0273 struct device *dev = musb->controller;
0274 struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
0275
0276 omap2430_low_level_exit(musb);
0277 phy_power_off(musb->phy);
0278 phy_exit(musb->phy);
0279 musb->phy = NULL;
0280 cancel_work_sync(&glue->omap_musb_mailbox_work);
0281
0282 return 0;
0283 }
0284
0285 static const struct musb_platform_ops omap2430_ops = {
0286 .quirks = MUSB_DMA_INVENTRA,
0287 #ifdef CONFIG_USB_INVENTRA_DMA
0288 .dma_init = musbhs_dma_controller_create,
0289 .dma_exit = musbhs_dma_controller_destroy,
0290 #endif
0291 .init = omap2430_musb_init,
0292 .exit = omap2430_musb_exit,
0293
0294 .enable = omap2430_musb_enable,
0295 .disable = omap2430_musb_disable,
0296
0297 .phy_callback = omap2430_musb_mailbox,
0298 };
0299
0300 static u64 omap2430_dmamask = DMA_BIT_MASK(32);
0301
0302 static int omap2430_probe(struct platform_device *pdev)
0303 {
0304 struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev);
0305 struct omap_musb_board_data *data;
0306 struct platform_device *musb;
0307 struct omap2430_glue *glue;
0308 struct device_node *np = pdev->dev.of_node;
0309 struct musb_hdrc_config *config;
0310 struct device_node *control_node;
0311 struct platform_device *control_pdev;
0312 int ret = -ENOMEM, val;
0313
0314 if (!np)
0315 return -ENODEV;
0316
0317 glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
0318 if (!glue)
0319 goto err0;
0320
0321 musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
0322 if (!musb) {
0323 dev_err(&pdev->dev, "failed to allocate musb device\n");
0324 goto err0;
0325 }
0326
0327 musb->dev.parent = &pdev->dev;
0328 musb->dev.dma_mask = &omap2430_dmamask;
0329 musb->dev.coherent_dma_mask = omap2430_dmamask;
0330
0331 glue->dev = &pdev->dev;
0332 glue->musb = musb;
0333 glue->status = MUSB_UNKNOWN;
0334 glue->control_otghs = ERR_PTR(-ENODEV);
0335
0336 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
0337 if (!pdata)
0338 goto err2;
0339
0340 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
0341 if (!data)
0342 goto err2;
0343
0344 config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);
0345 if (!config)
0346 goto err2;
0347
0348 of_property_read_u32(np, "mode", (u32 *)&pdata->mode);
0349 of_property_read_u32(np, "interface-type",
0350 (u32 *)&data->interface_type);
0351 of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps);
0352 of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits);
0353 of_property_read_u32(np, "power", (u32 *)&pdata->power);
0354
0355 ret = of_property_read_u32(np, "multipoint", &val);
0356 if (!ret && val)
0357 config->multipoint = true;
0358
0359 pdata->board_data = data;
0360 pdata->config = config;
0361
0362 control_node = of_parse_phandle(np, "ctrl-module", 0);
0363 if (control_node) {
0364 control_pdev = of_find_device_by_node(control_node);
0365 of_node_put(control_node);
0366 if (!control_pdev) {
0367 dev_err(&pdev->dev, "Failed to get control device\n");
0368 ret = -EINVAL;
0369 goto err2;
0370 }
0371 glue->control_otghs = &control_pdev->dev;
0372 }
0373
0374 pdata->platform_ops = &omap2430_ops;
0375
0376 platform_set_drvdata(pdev, glue);
0377
0378
0379
0380
0381
0382 _glue = glue;
0383
0384 INIT_WORK(&glue->omap_musb_mailbox_work, omap_musb_mailbox_work);
0385
0386 ret = platform_device_add_resources(musb, pdev->resource, pdev->num_resources);
0387 if (ret) {
0388 dev_err(&pdev->dev, "failed to add resources\n");
0389 goto err2;
0390 }
0391
0392 ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
0393 if (ret) {
0394 dev_err(&pdev->dev, "failed to add platform_data\n");
0395 goto err2;
0396 }
0397
0398 pm_runtime_enable(glue->dev);
0399
0400 ret = platform_device_add(musb);
0401 if (ret) {
0402 dev_err(&pdev->dev, "failed to register musb device\n");
0403 goto err3;
0404 }
0405
0406 return 0;
0407
0408 err3:
0409 pm_runtime_disable(glue->dev);
0410
0411 err2:
0412 platform_device_put(musb);
0413
0414 err0:
0415 return ret;
0416 }
0417
0418 static int omap2430_remove(struct platform_device *pdev)
0419 {
0420 struct omap2430_glue *glue = platform_get_drvdata(pdev);
0421
0422 platform_device_unregister(glue->musb);
0423 pm_runtime_disable(glue->dev);
0424
0425 return 0;
0426 }
0427
0428 #ifdef CONFIG_PM
0429
0430 static int omap2430_runtime_suspend(struct device *dev)
0431 {
0432 struct omap2430_glue *glue = dev_get_drvdata(dev);
0433 struct musb *musb = glue_to_musb(glue);
0434
0435 if (!musb)
0436 return 0;
0437
0438 musb->context.otg_interfsel = musb_readl(musb->mregs,
0439 OTG_INTERFSEL);
0440
0441 omap2430_low_level_exit(musb);
0442
0443 if (!glue->phy_suspended) {
0444 phy_power_off(musb->phy);
0445 phy_exit(musb->phy);
0446 }
0447
0448 glue->is_runtime_suspended = 1;
0449
0450 return 0;
0451 }
0452
0453 static int omap2430_runtime_resume(struct device *dev)
0454 {
0455 struct omap2430_glue *glue = dev_get_drvdata(dev);
0456 struct musb *musb = glue_to_musb(glue);
0457
0458 if (!musb)
0459 return 0;
0460
0461 if (!glue->phy_suspended) {
0462 phy_init(musb->phy);
0463 phy_power_on(musb->phy);
0464 }
0465
0466 omap2430_low_level_init(musb);
0467 musb_writel(musb->mregs, OTG_INTERFSEL,
0468 musb->context.otg_interfsel);
0469
0470
0471 usleep_range(200000, 250000);
0472
0473 glue->is_runtime_suspended = 0;
0474
0475 return 0;
0476 }
0477
0478
0479 static int omap2430_suspend(struct device *dev)
0480 {
0481 struct omap2430_glue *glue = dev_get_drvdata(dev);
0482 struct musb *musb = glue_to_musb(glue);
0483
0484 phy_power_off(musb->phy);
0485 phy_exit(musb->phy);
0486 glue->phy_suspended = 1;
0487
0488 return 0;
0489 }
0490
0491
0492 static int omap2430_suspend_late(struct device *dev)
0493 {
0494 struct omap2430_glue *glue = dev_get_drvdata(dev);
0495
0496 if (glue->is_runtime_suspended)
0497 return 0;
0498
0499 glue->needs_resume = 1;
0500
0501 return omap2430_runtime_suspend(dev);
0502 }
0503
0504 static int omap2430_resume_early(struct device *dev)
0505 {
0506 struct omap2430_glue *glue = dev_get_drvdata(dev);
0507
0508 if (!glue->needs_resume)
0509 return 0;
0510
0511 glue->needs_resume = 0;
0512
0513 return omap2430_runtime_resume(dev);
0514 }
0515
0516 static int omap2430_resume(struct device *dev)
0517 {
0518 struct omap2430_glue *glue = dev_get_drvdata(dev);
0519 struct musb *musb = glue_to_musb(glue);
0520
0521 phy_init(musb->phy);
0522 phy_power_on(musb->phy);
0523 glue->phy_suspended = 0;
0524
0525 return 0;
0526 }
0527
0528 static const struct dev_pm_ops omap2430_pm_ops = {
0529 .runtime_suspend = omap2430_runtime_suspend,
0530 .runtime_resume = omap2430_runtime_resume,
0531 .suspend = omap2430_suspend,
0532 .suspend_late = omap2430_suspend_late,
0533 .resume_early = omap2430_resume_early,
0534 .resume = omap2430_resume,
0535 };
0536
0537 #define DEV_PM_OPS (&omap2430_pm_ops)
0538 #else
0539 #define DEV_PM_OPS NULL
0540 #endif
0541
0542 #ifdef CONFIG_OF
0543 static const struct of_device_id omap2430_id_table[] = {
0544 {
0545 .compatible = "ti,omap4-musb"
0546 },
0547 {
0548 .compatible = "ti,omap3-musb"
0549 },
0550 {},
0551 };
0552 MODULE_DEVICE_TABLE(of, omap2430_id_table);
0553 #endif
0554
0555 static struct platform_driver omap2430_driver = {
0556 .probe = omap2430_probe,
0557 .remove = omap2430_remove,
0558 .driver = {
0559 .name = "musb-omap2430",
0560 .pm = DEV_PM_OPS,
0561 .of_match_table = of_match_ptr(omap2430_id_table),
0562 },
0563 };
0564
0565 module_platform_driver(omap2430_driver);
0566
0567 MODULE_DESCRIPTION("OMAP2PLUS MUSB Glue Layer");
0568 MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
0569 MODULE_LICENSE("GPL v2");