linux/drivers/usb/host/ohci-omap.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-1.0+
   2/*
   3 * OHCI HCD (Host Controller Driver) for USB.
   4 *
   5 * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
   6 * (C) Copyright 2000-2005 David Brownell
   7 * (C) Copyright 2002 Hewlett-Packard Company
   8 *
   9 * OMAP Bus Glue
  10 *
  11 * Modified for OMAP by Tony Lindgren <tony@atomide.com>
  12 * Based on the 2.4 OMAP OHCI driver originally done by MontaVista Software Inc.
  13 * and on ohci-sa1111.c by Christopher Hoover <ch@hpl.hp.com>
  14 *
  15 * This file is licenced under the GPL.
  16 */
  17
  18#include <linux/clk.h>
  19#include <linux/dma-mapping.h>
  20#include <linux/err.h>
  21#include <linux/gpio.h>
  22#include <linux/io.h>
  23#include <linux/jiffies.h>
  24#include <linux/kernel.h>
  25#include <linux/module.h>
  26#include <linux/usb/otg.h>
  27#include <linux/platform_device.h>
  28#include <linux/signal.h>
  29#include <linux/usb.h>
  30#include <linux/usb/hcd.h>
  31
  32#include "ohci.h"
  33
  34#include <asm/io.h>
  35#include <asm/mach-types.h>
  36
  37#include <mach/mux.h>
  38
  39#include <mach/hardware.h>
  40#include <mach/usb.h>
  41
  42
  43/* OMAP-1510 OHCI has its own MMU for DMA */
  44#define OMAP1510_LB_MEMSIZE     32      /* Should be same as SDRAM size */
  45#define OMAP1510_LB_CLOCK_DIV   0xfffec10c
  46#define OMAP1510_LB_MMU_CTL     0xfffec208
  47#define OMAP1510_LB_MMU_LCK     0xfffec224
  48#define OMAP1510_LB_MMU_LD_TLB  0xfffec228
  49#define OMAP1510_LB_MMU_CAM_H   0xfffec22c
  50#define OMAP1510_LB_MMU_CAM_L   0xfffec230
  51#define OMAP1510_LB_MMU_RAM_H   0xfffec234
  52#define OMAP1510_LB_MMU_RAM_L   0xfffec238
  53
  54#define DRIVER_DESC "OHCI OMAP driver"
  55
  56#ifdef CONFIG_TPS65010
  57#include <linux/mfd/tps65010.h>
  58#else
  59
  60#define LOW     0
  61#define HIGH    1
  62
  63#define GPIO1   1
  64
  65static inline int tps65010_set_gpio_out_value(unsigned gpio, unsigned value)
  66{
  67        return 0;
  68}
  69
  70#endif
  71
  72static struct clk *usb_host_ck;
  73static struct clk *usb_dc_ck;
  74
  75static const char hcd_name[] = "ohci-omap";
  76static struct hc_driver __read_mostly ohci_omap_hc_driver;
  77
  78static void omap_ohci_clock_power(int on)
  79{
  80        if (on) {
  81                clk_enable(usb_dc_ck);
  82                clk_enable(usb_host_ck);
  83                /* guesstimate for T5 == 1x 32K clock + APLL lock time */
  84                udelay(100);
  85        } else {
  86                clk_disable(usb_host_ck);
  87                clk_disable(usb_dc_ck);
  88        }
  89}
  90
  91/*
  92 * Board specific gang-switched transceiver power on/off.
  93 * NOTE:  OSK supplies power from DC, not battery.
  94 */
  95static int omap_ohci_transceiver_power(int on)
  96{
  97        if (on) {
  98                if (machine_is_omap_innovator() && cpu_is_omap1510())
  99                        __raw_writeb(__raw_readb(INNOVATOR_FPGA_CAM_USB_CONTROL)
 100                                | ((1 << 5/*usb1*/) | (1 << 3/*usb2*/)),
 101                               INNOVATOR_FPGA_CAM_USB_CONTROL);
 102                else if (machine_is_omap_osk())
 103                        tps65010_set_gpio_out_value(GPIO1, LOW);
 104        } else {
 105                if (machine_is_omap_innovator() && cpu_is_omap1510())
 106                        __raw_writeb(__raw_readb(INNOVATOR_FPGA_CAM_USB_CONTROL)
 107                                & ~((1 << 5/*usb1*/) | (1 << 3/*usb2*/)),
 108                               INNOVATOR_FPGA_CAM_USB_CONTROL);
 109                else if (machine_is_omap_osk())
 110                        tps65010_set_gpio_out_value(GPIO1, HIGH);
 111        }
 112
 113        return 0;
 114}
 115
 116#ifdef CONFIG_ARCH_OMAP15XX
 117/*
 118 * OMAP-1510 specific Local Bus clock on/off
 119 */
 120static int omap_1510_local_bus_power(int on)
 121{
 122        if (on) {
 123                omap_writel((1 << 1) | (1 << 0), OMAP1510_LB_MMU_CTL);
 124                udelay(200);
 125        } else {
 126                omap_writel(0, OMAP1510_LB_MMU_CTL);
 127        }
 128
 129        return 0;
 130}
 131
 132/*
 133 * OMAP-1510 specific Local Bus initialization
 134 * NOTE: This assumes 32MB memory size in OMAP1510LB_MEMSIZE.
 135 *       See also arch/mach-omap/memory.h for __virt_to_dma() and
 136 *       __dma_to_virt() which need to match with the physical
 137 *       Local Bus address below.
 138 */
 139static int omap_1510_local_bus_init(void)
 140{
 141        unsigned int tlb;
 142        unsigned long lbaddr, physaddr;
 143
 144        omap_writel((omap_readl(OMAP1510_LB_CLOCK_DIV) & 0xfffffff8) | 0x4,
 145               OMAP1510_LB_CLOCK_DIV);
 146
 147        /* Configure the Local Bus MMU table */
 148        for (tlb = 0; tlb < OMAP1510_LB_MEMSIZE; tlb++) {
 149                lbaddr = tlb * 0x00100000 + OMAP1510_LB_OFFSET;
 150                physaddr = tlb * 0x00100000 + PHYS_OFFSET;
 151                omap_writel((lbaddr & 0x0fffffff) >> 22, OMAP1510_LB_MMU_CAM_H);
 152                omap_writel(((lbaddr & 0x003ffc00) >> 6) | 0xc,
 153                       OMAP1510_LB_MMU_CAM_L);
 154                omap_writel(physaddr >> 16, OMAP1510_LB_MMU_RAM_H);
 155                omap_writel((physaddr & 0x0000fc00) | 0x300, OMAP1510_LB_MMU_RAM_L);
 156                omap_writel(tlb << 4, OMAP1510_LB_MMU_LCK);
 157                omap_writel(0x1, OMAP1510_LB_MMU_LD_TLB);
 158        }
 159
 160        /* Enable the walking table */
 161        omap_writel(omap_readl(OMAP1510_LB_MMU_CTL) | (1 << 3), OMAP1510_LB_MMU_CTL);
 162        udelay(200);
 163
 164        return 0;
 165}
 166#else
 167#define omap_1510_local_bus_power(x)    {}
 168#define omap_1510_local_bus_init()      {}
 169#endif
 170
 171#ifdef  CONFIG_USB_OTG
 172
 173static void start_hnp(struct ohci_hcd *ohci)
 174{
 175        struct usb_hcd *hcd = ohci_to_hcd(ohci);
 176        const unsigned  port = hcd->self.otg_port - 1;
 177        unsigned long   flags;
 178        u32 l;
 179
 180        otg_start_hnp(hcd->usb_phy->otg);
 181
 182        local_irq_save(flags);
 183        hcd->usb_phy->otg->state = OTG_STATE_A_SUSPEND;
 184        writel (RH_PS_PSS, &ohci->regs->roothub.portstatus [port]);
 185        l = omap_readl(OTG_CTRL);
 186        l &= ~OTG_A_BUSREQ;
 187        omap_writel(l, OTG_CTRL);
 188        local_irq_restore(flags);
 189}
 190
 191#endif
 192
 193/*-------------------------------------------------------------------------*/
 194
 195static int ohci_omap_reset(struct usb_hcd *hcd)
 196{
 197        struct ohci_hcd         *ohci = hcd_to_ohci(hcd);
 198        struct omap_usb_config  *config = dev_get_platdata(hcd->self.controller);
 199        int                     need_transceiver = (config->otg != 0);
 200        int                     ret;
 201
 202        dev_dbg(hcd->self.controller, "starting USB Controller\n");
 203
 204        if (config->otg) {
 205                hcd->self.otg_port = config->otg;
 206                /* default/minimum OTG power budget:  8 mA */
 207                hcd->power_budget = 8;
 208        }
 209
 210        /* boards can use OTG transceivers in non-OTG modes */
 211        need_transceiver = need_transceiver
 212                        || machine_is_omap_h2() || machine_is_omap_h3();
 213
 214        /* XXX OMAP16xx only */
 215        if (config->ocpi_enable)
 216                config->ocpi_enable();
 217
 218#ifdef  CONFIG_USB_OTG
 219        if (need_transceiver) {
 220                hcd->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2);
 221                if (!IS_ERR_OR_NULL(hcd->usb_phy)) {
 222                        int     status = otg_set_host(hcd->usb_phy->otg,
 223                                                &ohci_to_hcd(ohci)->self);
 224                        dev_dbg(hcd->self.controller, "init %s phy, status %d\n",
 225                                        hcd->usb_phy->label, status);
 226                        if (status) {
 227                                usb_put_phy(hcd->usb_phy);
 228                                return status;
 229                        }
 230                } else {
 231                        return -EPROBE_DEFER;
 232                }
 233                hcd->skip_phy_initialization = 1;
 234                ohci->start_hnp = start_hnp;
 235        }
 236#endif
 237
 238        omap_ohci_clock_power(1);
 239
 240        if (cpu_is_omap15xx()) {
 241                omap_1510_local_bus_power(1);
 242                omap_1510_local_bus_init();
 243        }
 244
 245        ret = ohci_setup(hcd);
 246        if (ret < 0)
 247                return ret;
 248
 249        if (config->otg || config->rwc) {
 250                ohci->hc_control = OHCI_CTRL_RWC;
 251                writel(OHCI_CTRL_RWC, &ohci->regs->control);
 252        }
 253
 254        /* board-specific power switching and overcurrent support */
 255        if (machine_is_omap_osk() || machine_is_omap_innovator()) {
 256                u32     rh = roothub_a (ohci);
 257
 258                /* power switching (ganged by default) */
 259                rh &= ~RH_A_NPS;
 260
 261                /* TPS2045 switch for internal transceiver (port 1) */
 262                if (machine_is_omap_osk()) {
 263                        ohci_to_hcd(ohci)->power_budget = 250;
 264
 265                        rh &= ~RH_A_NOCP;
 266
 267                        /* gpio9 for overcurrent detction */
 268                        omap_cfg_reg(W8_1610_GPIO9);
 269                        gpio_request(9, "OHCI overcurrent");
 270                        gpio_direction_input(9);
 271
 272                        /* for paranoia's sake:  disable USB.PUEN */
 273                        omap_cfg_reg(W4_USB_HIGHZ);
 274                }
 275                ohci_writel(ohci, rh, &ohci->regs->roothub.a);
 276                ohci->flags &= ~OHCI_QUIRK_HUB_POWER;
 277        } else if (machine_is_nokia770()) {
 278                /* We require a self-powered hub, which should have
 279                 * plenty of power. */
 280                ohci_to_hcd(ohci)->power_budget = 0;
 281        }
 282
 283        /* FIXME hub_wq hub requests should manage power switching */
 284        omap_ohci_transceiver_power(1);
 285
 286        /* board init will have already handled HMC and mux setup.
 287         * any external transceiver should already be initialized
 288         * too, so all configured ports use the right signaling now.
 289         */
 290
 291        return 0;
 292}
 293
 294/*-------------------------------------------------------------------------*/
 295
 296/**
 297 * ohci_hcd_omap_probe - initialize OMAP-based HCDs
 298 * Context: !in_interrupt()
 299 *
 300 * Allocates basic resources for this USB host controller, and
 301 * then invokes the start() method for the HCD associated with it
 302 * through the hotplug entry's driver_data.
 303 */
 304static int ohci_hcd_omap_probe(struct platform_device *pdev)
 305{
 306        int retval, irq;
 307        struct usb_hcd *hcd = 0;
 308
 309        if (pdev->num_resources != 2) {
 310                dev_err(&pdev->dev, "invalid num_resources: %i\n",
 311                       pdev->num_resources);
 312                return -ENODEV;
 313        }
 314
 315        if (pdev->resource[0].flags != IORESOURCE_MEM
 316                        || pdev->resource[1].flags != IORESOURCE_IRQ) {
 317                dev_err(&pdev->dev, "invalid resource type\n");
 318                return -ENODEV;
 319        }
 320
 321        usb_host_ck = clk_get(&pdev->dev, "usb_hhc_ck");
 322        if (IS_ERR(usb_host_ck))
 323                return PTR_ERR(usb_host_ck);
 324
 325        if (!cpu_is_omap15xx())
 326                usb_dc_ck = clk_get(&pdev->dev, "usb_dc_ck");
 327        else
 328                usb_dc_ck = clk_get(&pdev->dev, "lb_ck");
 329
 330        if (IS_ERR(usb_dc_ck)) {
 331                clk_put(usb_host_ck);
 332                return PTR_ERR(usb_dc_ck);
 333        }
 334
 335
 336        hcd = usb_create_hcd(&ohci_omap_hc_driver, &pdev->dev,
 337                        dev_name(&pdev->dev));
 338        if (!hcd) {
 339                retval = -ENOMEM;
 340                goto err0;
 341        }
 342        hcd->rsrc_start = pdev->resource[0].start;
 343        hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
 344
 345        if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
 346                dev_dbg(&pdev->dev, "request_mem_region failed\n");
 347                retval = -EBUSY;
 348                goto err1;
 349        }
 350
 351        hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
 352        if (!hcd->regs) {
 353                dev_err(&pdev->dev, "can't ioremap OHCI HCD\n");
 354                retval = -ENOMEM;
 355                goto err2;
 356        }
 357
 358        irq = platform_get_irq(pdev, 0);
 359        if (irq < 0) {
 360                retval = -ENXIO;
 361                goto err3;
 362        }
 363        retval = usb_add_hcd(hcd, irq, 0);
 364        if (retval)
 365                goto err3;
 366
 367        device_wakeup_enable(hcd->self.controller);
 368        return 0;
 369err3:
 370        iounmap(hcd->regs);
 371err2:
 372        release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 373err1:
 374        usb_put_hcd(hcd);
 375err0:
 376        clk_put(usb_dc_ck);
 377        clk_put(usb_host_ck);
 378        return retval;
 379}
 380
 381
 382/* may be called with controller, bus, and devices active */
 383
 384/**
 385 * ohci_hcd_omap_remove - shutdown processing for OMAP-based HCDs
 386 * @dev: USB Host Controller being removed
 387 * Context: !in_interrupt()
 388 *
 389 * Reverses the effect of ohci_hcd_omap_probe(), first invoking
 390 * the HCD's stop() method.  It is always called from a thread
 391 * context, normally "rmmod", "apmd", or something similar.
 392 */
 393static int ohci_hcd_omap_remove(struct platform_device *pdev)
 394{
 395        struct usb_hcd  *hcd = platform_get_drvdata(pdev);
 396
 397        dev_dbg(hcd->self.controller, "stopping USB Controller\n");
 398        usb_remove_hcd(hcd);
 399        omap_ohci_clock_power(0);
 400        if (!IS_ERR_OR_NULL(hcd->usb_phy)) {
 401                (void) otg_set_host(hcd->usb_phy->otg, 0);
 402                usb_put_phy(hcd->usb_phy);
 403        }
 404        if (machine_is_omap_osk())
 405                gpio_free(9);
 406        iounmap(hcd->regs);
 407        release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 408        usb_put_hcd(hcd);
 409        clk_put(usb_dc_ck);
 410        clk_put(usb_host_ck);
 411        return 0;
 412}
 413
 414/*-------------------------------------------------------------------------*/
 415
 416#ifdef  CONFIG_PM
 417
 418static int ohci_omap_suspend(struct platform_device *pdev, pm_message_t message)
 419{
 420        struct usb_hcd *hcd = platform_get_drvdata(pdev);
 421        struct ohci_hcd *ohci = hcd_to_ohci(hcd);
 422        bool do_wakeup = device_may_wakeup(&pdev->dev);
 423        int ret;
 424
 425        if (time_before(jiffies, ohci->next_statechange))
 426                msleep(5);
 427        ohci->next_statechange = jiffies;
 428
 429        ret = ohci_suspend(hcd, do_wakeup);
 430        if (ret)
 431                return ret;
 432
 433        omap_ohci_clock_power(0);
 434        return ret;
 435}
 436
 437static int ohci_omap_resume(struct platform_device *dev)
 438{
 439        struct usb_hcd  *hcd = platform_get_drvdata(dev);
 440        struct ohci_hcd *ohci = hcd_to_ohci(hcd);
 441
 442        if (time_before(jiffies, ohci->next_statechange))
 443                msleep(5);
 444        ohci->next_statechange = jiffies;
 445
 446        omap_ohci_clock_power(1);
 447        ohci_resume(hcd, false);
 448        return 0;
 449}
 450
 451#endif
 452
 453/*-------------------------------------------------------------------------*/
 454
 455/*
 456 * Driver definition to register with the OMAP bus
 457 */
 458static struct platform_driver ohci_hcd_omap_driver = {
 459        .probe          = ohci_hcd_omap_probe,
 460        .remove         = ohci_hcd_omap_remove,
 461        .shutdown       = usb_hcd_platform_shutdown,
 462#ifdef  CONFIG_PM
 463        .suspend        = ohci_omap_suspend,
 464        .resume         = ohci_omap_resume,
 465#endif
 466        .driver         = {
 467                .name   = "ohci",
 468        },
 469};
 470
 471static const struct ohci_driver_overrides omap_overrides __initconst = {
 472        .product_desc   = "OMAP OHCI",
 473        .reset          = ohci_omap_reset
 474};
 475
 476static int __init ohci_omap_init(void)
 477{
 478        if (usb_disabled())
 479                return -ENODEV;
 480
 481        pr_info("%s: " DRIVER_DESC "\n", hcd_name);
 482
 483        ohci_init_driver(&ohci_omap_hc_driver, &omap_overrides);
 484        return platform_driver_register(&ohci_hcd_omap_driver);
 485}
 486module_init(ohci_omap_init);
 487
 488static void __exit ohci_omap_cleanup(void)
 489{
 490        platform_driver_unregister(&ohci_hcd_omap_driver);
 491}
 492module_exit(ohci_omap_cleanup);
 493
 494MODULE_DESCRIPTION(DRIVER_DESC);
 495MODULE_ALIAS("platform:ohci");
 496MODULE_LICENSE("GPL");
 497