root/drivers/usb/musb/omap2430.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. omap2430_musb_set_vbus
  2. omap2430_low_level_exit
  3. omap2430_low_level_init
  4. omap2430_musb_mailbox
  5. omap_musb_set_mailbox
  6. omap_musb_mailbox_work
  7. omap2430_musb_interrupt
  8. omap2430_musb_init
  9. omap2430_musb_enable
  10. omap2430_musb_disable
  11. omap2430_musb_exit
  12. omap2430_probe
  13. omap2430_remove
  14. omap2430_runtime_suspend
  15. omap2430_runtime_resume

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright (C) 2005-2007 by Texas Instruments
   4  * Some code has been taken from tusb6010.c
   5  * Copyrights for that are attributable to:
   6  * Copyright (C) 2006 Nokia Corporation
   7  * Tony Lindgren <tony@atomide.com>
   8  *
   9  * This file is part of the Inventra Controller Driver for Linux.
  10  */
  11 #include <linux/module.h>
  12 #include <linux/kernel.h>
  13 #include <linux/sched.h>
  14 #include <linux/init.h>
  15 #include <linux/list.h>
  16 #include <linux/io.h>
  17 #include <linux/of.h>
  18 #include <linux/platform_device.h>
  19 #include <linux/dma-mapping.h>
  20 #include <linux/pm_runtime.h>
  21 #include <linux/err.h>
  22 #include <linux/delay.h>
  23 #include <linux/usb/musb.h>
  24 #include <linux/phy/omap_control_phy.h>
  25 #include <linux/of_platform.h>
  26 
  27 #include "musb_core.h"
  28 #include "omap2430.h"
  29 
  30 struct omap2430_glue {
  31         struct device           *dev;
  32         struct platform_device  *musb;
  33         enum musb_vbus_id_status status;
  34         struct work_struct      omap_musb_mailbox_work;
  35         struct device           *control_otghs;
  36 };
  37 #define glue_to_musb(g)         platform_get_drvdata(g->musb)
  38 
  39 static struct omap2430_glue     *_glue;
  40 
  41 static void omap2430_musb_set_vbus(struct musb *musb, int is_on)
  42 {
  43         struct usb_otg  *otg = musb->xceiv->otg;
  44         u8              devctl;
  45         unsigned long timeout = jiffies + msecs_to_jiffies(1000);
  46         /* HDRC controls CPEN, but beware current surges during device
  47          * connect.  They can trigger transient overcurrent conditions
  48          * that must be ignored.
  49          */
  50 
  51         devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
  52 
  53         if (is_on) {
  54                 if (musb->xceiv->otg->state == OTG_STATE_A_IDLE) {
  55                         int loops = 100;
  56                         /* start the session */
  57                         devctl |= MUSB_DEVCTL_SESSION;
  58                         musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
  59                         /*
  60                          * Wait for the musb to set as A device to enable the
  61                          * VBUS
  62                          */
  63                         while (musb_readb(musb->mregs, MUSB_DEVCTL) &
  64                                MUSB_DEVCTL_BDEVICE) {
  65 
  66                                 mdelay(5);
  67                                 cpu_relax();
  68 
  69                                 if (time_after(jiffies, timeout)
  70                                     || loops-- <= 0) {
  71                                         dev_err(musb->controller,
  72                                         "configured as A device timeout");
  73                                         break;
  74                                 }
  75                         }
  76 
  77                         otg_set_vbus(otg, 1);
  78                 } else {
  79                         musb->is_active = 1;
  80                         musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
  81                         devctl |= MUSB_DEVCTL_SESSION;
  82                         MUSB_HST_MODE(musb);
  83                 }
  84         } else {
  85                 musb->is_active = 0;
  86 
  87                 /* NOTE:  we're skipping A_WAIT_VFALL -> A_IDLE and
  88                  * jumping right to B_IDLE...
  89                  */
  90 
  91                 musb->xceiv->otg->state = OTG_STATE_B_IDLE;
  92                 devctl &= ~MUSB_DEVCTL_SESSION;
  93 
  94                 MUSB_DEV_MODE(musb);
  95         }
  96         musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
  97 
  98         dev_dbg(musb->controller, "VBUS %s, devctl %02x "
  99                 /* otg %3x conf %08x prcm %08x */ "\n",
 100                 usb_otg_state_string(musb->xceiv->otg->state),
 101                 musb_readb(musb->mregs, MUSB_DEVCTL));
 102 }
 103 
 104 static inline void omap2430_low_level_exit(struct musb *musb)
 105 {
 106         u32 l;
 107 
 108         /* in any role */
 109         l = musb_readl(musb->mregs, OTG_FORCESTDBY);
 110         l |= ENABLEFORCE;       /* enable MSTANDBY */
 111         musb_writel(musb->mregs, OTG_FORCESTDBY, l);
 112 }
 113 
 114 static inline void omap2430_low_level_init(struct musb *musb)
 115 {
 116         u32 l;
 117 
 118         l = musb_readl(musb->mregs, OTG_FORCESTDBY);
 119         l &= ~ENABLEFORCE;      /* disable MSTANDBY */
 120         musb_writel(musb->mregs, OTG_FORCESTDBY, l);
 121 }
 122 
 123 static int omap2430_musb_mailbox(enum musb_vbus_id_status status)
 124 {
 125         struct omap2430_glue    *glue = _glue;
 126 
 127         if (!glue) {
 128                 pr_err("%s: musb core is not yet initialized\n", __func__);
 129                 return -EPROBE_DEFER;
 130         }
 131         glue->status = status;
 132 
 133         if (!glue_to_musb(glue)) {
 134                 pr_err("%s: musb core is not yet ready\n", __func__);
 135                 return -EPROBE_DEFER;
 136         }
 137 
 138         schedule_work(&glue->omap_musb_mailbox_work);
 139 
 140         return 0;
 141 }
 142 
 143 static void omap_musb_set_mailbox(struct omap2430_glue *glue)
 144 {
 145         struct musb *musb = glue_to_musb(glue);
 146         struct musb_hdrc_platform_data *pdata =
 147                 dev_get_platdata(musb->controller);
 148         struct omap_musb_board_data *data = pdata->board_data;
 149 
 150         pm_runtime_get_sync(musb->controller);
 151         switch (glue->status) {
 152         case MUSB_ID_GROUND:
 153                 dev_dbg(musb->controller, "ID GND\n");
 154 
 155                 musb->xceiv->otg->state = OTG_STATE_A_IDLE;
 156                 musb->xceiv->last_event = USB_EVENT_ID;
 157                 if (musb->gadget_driver) {
 158                         omap_control_usb_set_mode(glue->control_otghs,
 159                                 USB_MODE_HOST);
 160                         omap2430_musb_set_vbus(musb, 1);
 161                 }
 162                 break;
 163 
 164         case MUSB_VBUS_VALID:
 165                 dev_dbg(musb->controller, "VBUS Connect\n");
 166 
 167                 musb->xceiv->otg->state = OTG_STATE_B_IDLE;
 168                 musb->xceiv->last_event = USB_EVENT_VBUS;
 169                 omap_control_usb_set_mode(glue->control_otghs, USB_MODE_DEVICE);
 170                 break;
 171 
 172         case MUSB_ID_FLOAT:
 173         case MUSB_VBUS_OFF:
 174                 dev_dbg(musb->controller, "VBUS Disconnect\n");
 175 
 176                 musb->xceiv->last_event = USB_EVENT_NONE;
 177                 if (musb->gadget_driver)
 178                         omap2430_musb_set_vbus(musb, 0);
 179 
 180                 if (data->interface_type == MUSB_INTERFACE_UTMI)
 181                         otg_set_vbus(musb->xceiv->otg, 0);
 182 
 183                 omap_control_usb_set_mode(glue->control_otghs,
 184                         USB_MODE_DISCONNECT);
 185                 break;
 186         default:
 187                 dev_dbg(musb->controller, "ID float\n");
 188         }
 189         pm_runtime_mark_last_busy(musb->controller);
 190         pm_runtime_put_autosuspend(musb->controller);
 191         atomic_notifier_call_chain(&musb->xceiv->notifier,
 192                         musb->xceiv->last_event, NULL);
 193 }
 194 
 195 
 196 static void omap_musb_mailbox_work(struct work_struct *mailbox_work)
 197 {
 198         struct omap2430_glue *glue = container_of(mailbox_work,
 199                                 struct omap2430_glue, omap_musb_mailbox_work);
 200 
 201         omap_musb_set_mailbox(glue);
 202 }
 203 
 204 static irqreturn_t omap2430_musb_interrupt(int irq, void *__hci)
 205 {
 206         unsigned long   flags;
 207         irqreturn_t     retval = IRQ_NONE;
 208         struct musb     *musb = __hci;
 209 
 210         spin_lock_irqsave(&musb->lock, flags);
 211 
 212         musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
 213         musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
 214         musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
 215 
 216         if (musb->int_usb || musb->int_tx || musb->int_rx)
 217                 retval = musb_interrupt(musb);
 218 
 219         spin_unlock_irqrestore(&musb->lock, flags);
 220 
 221         return retval;
 222 }
 223 
 224 static int omap2430_musb_init(struct musb *musb)
 225 {
 226         u32 l;
 227         int status = 0;
 228         struct device *dev = musb->controller;
 229         struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
 230         struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
 231         struct omap_musb_board_data *data = plat->board_data;
 232 
 233         /* We require some kind of external transceiver, hooked
 234          * up through ULPI.  TWL4030-family PMICs include one,
 235          * which needs a driver, drivers aren't always needed.
 236          */
 237         musb->phy = devm_phy_get(dev->parent, "usb2-phy");
 238 
 239         /* We can't totally remove musb->xceiv as of now because
 240          * musb core uses xceiv.state and xceiv.otg. Once we have
 241          * a separate state machine to handle otg, these can be moved
 242          * out of xceiv and then we can start using the generic PHY
 243          * framework
 244          */
 245         musb->xceiv = devm_usb_get_phy_by_phandle(dev->parent, "usb-phy", 0);
 246 
 247         if (IS_ERR(musb->xceiv)) {
 248                 status = PTR_ERR(musb->xceiv);
 249 
 250                 if (status == -ENXIO)
 251                         return status;
 252 
 253                 dev_dbg(dev, "HS USB OTG: no transceiver configured\n");
 254                 return -EPROBE_DEFER;
 255         }
 256 
 257         if (IS_ERR(musb->phy)) {
 258                 dev_err(dev, "HS USB OTG: no PHY configured\n");
 259                 return PTR_ERR(musb->phy);
 260         }
 261         musb->isr = omap2430_musb_interrupt;
 262         phy_init(musb->phy);
 263         phy_power_on(musb->phy);
 264 
 265         l = musb_readl(musb->mregs, OTG_INTERFSEL);
 266 
 267         if (data->interface_type == MUSB_INTERFACE_UTMI) {
 268                 /* OMAP4 uses Internal PHY GS70 which uses UTMI interface */
 269                 l &= ~ULPI_12PIN;       /* Disable ULPI */
 270                 l |= UTMI_8BIT;         /* Enable UTMI  */
 271         } else {
 272                 l |= ULPI_12PIN;
 273         }
 274 
 275         musb_writel(musb->mregs, OTG_INTERFSEL, l);
 276 
 277         dev_dbg(dev, "HS USB OTG: revision 0x%x, sysconfig 0x%02x, "
 278                         "sysstatus 0x%x, intrfsel 0x%x, simenable  0x%x\n",
 279                         musb_readl(musb->mregs, OTG_REVISION),
 280                         musb_readl(musb->mregs, OTG_SYSCONFIG),
 281                         musb_readl(musb->mregs, OTG_SYSSTATUS),
 282                         musb_readl(musb->mregs, OTG_INTERFSEL),
 283                         musb_readl(musb->mregs, OTG_SIMENABLE));
 284 
 285         if (glue->status != MUSB_UNKNOWN)
 286                 omap_musb_set_mailbox(glue);
 287 
 288         return 0;
 289 }
 290 
 291 static void omap2430_musb_enable(struct musb *musb)
 292 {
 293         u8              devctl;
 294         unsigned long timeout = jiffies + msecs_to_jiffies(1000);
 295         struct device *dev = musb->controller;
 296         struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
 297         struct musb_hdrc_platform_data *pdata = dev_get_platdata(dev);
 298         struct omap_musb_board_data *data = pdata->board_data;
 299 
 300 
 301         switch (glue->status) {
 302 
 303         case MUSB_ID_GROUND:
 304                 omap_control_usb_set_mode(glue->control_otghs, USB_MODE_HOST);
 305                 if (data->interface_type != MUSB_INTERFACE_UTMI)
 306                         break;
 307                 devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
 308                 /* start the session */
 309                 devctl |= MUSB_DEVCTL_SESSION;
 310                 musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
 311                 while (musb_readb(musb->mregs, MUSB_DEVCTL) &
 312                                 MUSB_DEVCTL_BDEVICE) {
 313                         cpu_relax();
 314 
 315                         if (time_after(jiffies, timeout)) {
 316                                 dev_err(dev, "configured as A device timeout");
 317                                 break;
 318                         }
 319                 }
 320                 break;
 321 
 322         case MUSB_VBUS_VALID:
 323                 omap_control_usb_set_mode(glue->control_otghs, USB_MODE_DEVICE);
 324                 break;
 325 
 326         default:
 327                 break;
 328         }
 329 }
 330 
 331 static void omap2430_musb_disable(struct musb *musb)
 332 {
 333         struct device *dev = musb->controller;
 334         struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
 335 
 336         if (glue->status != MUSB_UNKNOWN)
 337                 omap_control_usb_set_mode(glue->control_otghs,
 338                         USB_MODE_DISCONNECT);
 339 }
 340 
 341 static int omap2430_musb_exit(struct musb *musb)
 342 {
 343         struct device *dev = musb->controller;
 344         struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
 345 
 346         omap2430_low_level_exit(musb);
 347         phy_power_off(musb->phy);
 348         phy_exit(musb->phy);
 349         musb->phy = NULL;
 350         cancel_work_sync(&glue->omap_musb_mailbox_work);
 351 
 352         return 0;
 353 }
 354 
 355 static const struct musb_platform_ops omap2430_ops = {
 356         .quirks         = MUSB_DMA_INVENTRA,
 357 #ifdef CONFIG_USB_INVENTRA_DMA
 358         .dma_init       = musbhs_dma_controller_create,
 359         .dma_exit       = musbhs_dma_controller_destroy,
 360 #endif
 361         .init           = omap2430_musb_init,
 362         .exit           = omap2430_musb_exit,
 363 
 364         .enable         = omap2430_musb_enable,
 365         .disable        = omap2430_musb_disable,
 366 
 367         .phy_callback   = omap2430_musb_mailbox,
 368 };
 369 
 370 static u64 omap2430_dmamask = DMA_BIT_MASK(32);
 371 
 372 static int omap2430_probe(struct platform_device *pdev)
 373 {
 374         struct resource                 musb_resources[3];
 375         struct musb_hdrc_platform_data  *pdata = dev_get_platdata(&pdev->dev);
 376         struct omap_musb_board_data     *data;
 377         struct platform_device          *musb;
 378         struct omap2430_glue            *glue;
 379         struct device_node              *np = pdev->dev.of_node;
 380         struct musb_hdrc_config         *config;
 381         struct device_node              *control_node;
 382         struct platform_device          *control_pdev;
 383         int                             ret = -ENOMEM, val;
 384 
 385         if (!np)
 386                 return -ENODEV;
 387 
 388         glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
 389         if (!glue)
 390                 goto err0;
 391 
 392         musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
 393         if (!musb) {
 394                 dev_err(&pdev->dev, "failed to allocate musb device\n");
 395                 goto err0;
 396         }
 397 
 398         musb->dev.parent                = &pdev->dev;
 399         musb->dev.dma_mask              = &omap2430_dmamask;
 400         musb->dev.coherent_dma_mask     = omap2430_dmamask;
 401 
 402         glue->dev                       = &pdev->dev;
 403         glue->musb                      = musb;
 404         glue->status                    = MUSB_UNKNOWN;
 405         glue->control_otghs = ERR_PTR(-ENODEV);
 406 
 407         pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 408         if (!pdata)
 409                 goto err2;
 410 
 411         data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
 412         if (!data)
 413                 goto err2;
 414 
 415         config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);
 416         if (!config)
 417                 goto err2;
 418 
 419         of_property_read_u32(np, "mode", (u32 *)&pdata->mode);
 420         of_property_read_u32(np, "interface-type",
 421                         (u32 *)&data->interface_type);
 422         of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps);
 423         of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits);
 424         of_property_read_u32(np, "power", (u32 *)&pdata->power);
 425 
 426         ret = of_property_read_u32(np, "multipoint", &val);
 427         if (!ret && val)
 428                 config->multipoint = true;
 429 
 430         pdata->board_data       = data;
 431         pdata->config           = config;
 432 
 433         control_node = of_parse_phandle(np, "ctrl-module", 0);
 434         if (control_node) {
 435                 control_pdev = of_find_device_by_node(control_node);
 436                 if (!control_pdev) {
 437                         dev_err(&pdev->dev, "Failed to get control device\n");
 438                         ret = -EINVAL;
 439                         goto err2;
 440                 }
 441                 glue->control_otghs = &control_pdev->dev;
 442         }
 443 
 444         pdata->platform_ops             = &omap2430_ops;
 445 
 446         platform_set_drvdata(pdev, glue);
 447 
 448         /*
 449          * REVISIT if we ever have two instances of the wrapper, we will be
 450          * in big trouble
 451          */
 452         _glue   = glue;
 453 
 454         INIT_WORK(&glue->omap_musb_mailbox_work, omap_musb_mailbox_work);
 455 
 456         memset(musb_resources, 0x00, sizeof(*musb_resources) *
 457                         ARRAY_SIZE(musb_resources));
 458 
 459         musb_resources[0].name = pdev->resource[0].name;
 460         musb_resources[0].start = pdev->resource[0].start;
 461         musb_resources[0].end = pdev->resource[0].end;
 462         musb_resources[0].flags = pdev->resource[0].flags;
 463 
 464         musb_resources[1].name = pdev->resource[1].name;
 465         musb_resources[1].start = pdev->resource[1].start;
 466         musb_resources[1].end = pdev->resource[1].end;
 467         musb_resources[1].flags = pdev->resource[1].flags;
 468 
 469         musb_resources[2].name = pdev->resource[2].name;
 470         musb_resources[2].start = pdev->resource[2].start;
 471         musb_resources[2].end = pdev->resource[2].end;
 472         musb_resources[2].flags = pdev->resource[2].flags;
 473 
 474         ret = platform_device_add_resources(musb, musb_resources,
 475                         ARRAY_SIZE(musb_resources));
 476         if (ret) {
 477                 dev_err(&pdev->dev, "failed to add resources\n");
 478                 goto err2;
 479         }
 480 
 481         ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
 482         if (ret) {
 483                 dev_err(&pdev->dev, "failed to add platform_data\n");
 484                 goto err2;
 485         }
 486 
 487         pm_runtime_enable(glue->dev);
 488 
 489         ret = platform_device_add(musb);
 490         if (ret) {
 491                 dev_err(&pdev->dev, "failed to register musb device\n");
 492                 goto err3;
 493         }
 494 
 495         return 0;
 496 
 497 err3:
 498         pm_runtime_disable(glue->dev);
 499 
 500 err2:
 501         platform_device_put(musb);
 502 
 503 err0:
 504         return ret;
 505 }
 506 
 507 static int omap2430_remove(struct platform_device *pdev)
 508 {
 509         struct omap2430_glue *glue = platform_get_drvdata(pdev);
 510 
 511         platform_device_unregister(glue->musb);
 512         pm_runtime_disable(glue->dev);
 513 
 514         return 0;
 515 }
 516 
 517 #ifdef CONFIG_PM
 518 
 519 static int omap2430_runtime_suspend(struct device *dev)
 520 {
 521         struct omap2430_glue            *glue = dev_get_drvdata(dev);
 522         struct musb                     *musb = glue_to_musb(glue);
 523 
 524         if (!musb)
 525                 return 0;
 526 
 527         musb->context.otg_interfsel = musb_readl(musb->mregs,
 528                                                  OTG_INTERFSEL);
 529 
 530         omap2430_low_level_exit(musb);
 531 
 532         phy_power_off(musb->phy);
 533         phy_exit(musb->phy);
 534 
 535         return 0;
 536 }
 537 
 538 static int omap2430_runtime_resume(struct device *dev)
 539 {
 540         struct omap2430_glue            *glue = dev_get_drvdata(dev);
 541         struct musb                     *musb = glue_to_musb(glue);
 542 
 543         if (!musb)
 544                 return 0;
 545 
 546         phy_init(musb->phy);
 547         phy_power_on(musb->phy);
 548 
 549         omap2430_low_level_init(musb);
 550         musb_writel(musb->mregs, OTG_INTERFSEL,
 551                     musb->context.otg_interfsel);
 552 
 553         return 0;
 554 }
 555 
 556 static const struct dev_pm_ops omap2430_pm_ops = {
 557         .runtime_suspend = omap2430_runtime_suspend,
 558         .runtime_resume = omap2430_runtime_resume,
 559 };
 560 
 561 #define DEV_PM_OPS      (&omap2430_pm_ops)
 562 #else
 563 #define DEV_PM_OPS      NULL
 564 #endif
 565 
 566 #ifdef CONFIG_OF
 567 static const struct of_device_id omap2430_id_table[] = {
 568         {
 569                 .compatible = "ti,omap4-musb"
 570         },
 571         {
 572                 .compatible = "ti,omap3-musb"
 573         },
 574         {},
 575 };
 576 MODULE_DEVICE_TABLE(of, omap2430_id_table);
 577 #endif
 578 
 579 static struct platform_driver omap2430_driver = {
 580         .probe          = omap2430_probe,
 581         .remove         = omap2430_remove,
 582         .driver         = {
 583                 .name   = "musb-omap2430",
 584                 .pm     = DEV_PM_OPS,
 585                 .of_match_table = of_match_ptr(omap2430_id_table),
 586         },
 587 };
 588 
 589 module_platform_driver(omap2430_driver);
 590 
 591 MODULE_DESCRIPTION("OMAP2PLUS MUSB Glue Layer");
 592 MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
 593 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */