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