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>       /* IRQF_DISABLED */
  18#include <linux/jiffies.h>
  19#include <linux/platform_device.h>
  20#include <linux/clk.h>
  21#include <linux/gpio.h>
  22
  23#include <mach/hardware.h>
  24#include <asm/io.h>
  25#include <asm/mach-types.h>
  26
  27#include <mach/mux.h>
  28#include <mach/irqs.h>
  29#include <mach/fpga.h>
  30#include <mach/usb.h>
  31
  32
  33/* OMAP-1510 OHCI has its own MMU for DMA */
  34#define OMAP1510_LB_MEMSIZE     32      /* Should be same as SDRAM size */
  35#define OMAP1510_LB_CLOCK_DIV   0xfffec10c
  36#define OMAP1510_LB_MMU_CTL     0xfffec208
  37#define OMAP1510_LB_MMU_LCK     0xfffec224
  38#define OMAP1510_LB_MMU_LD_TLB  0xfffec228
  39#define OMAP1510_LB_MMU_CAM_H   0xfffec22c
  40#define OMAP1510_LB_MMU_CAM_L   0xfffec230
  41#define OMAP1510_LB_MMU_RAM_H   0xfffec234
  42#define OMAP1510_LB_MMU_RAM_L   0xfffec238
  43
  44
  45#ifndef CONFIG_ARCH_OMAP
  46#error "This file is OMAP bus glue.  CONFIG_OMAP must be defined."
  47#endif
  48
  49#ifdef CONFIG_TPS65010
  50#include <linux/i2c/tps65010.h>
  51#else
  52
  53#define LOW     0
  54#define HIGH    1
  55
  56#define GPIO1   1
  57
  58static inline int tps65010_set_gpio_out_value(unsigned gpio, unsigned value)
  59{
  60        return 0;
  61}
  62
  63#endif
  64
  65extern int usb_disabled(void);
  66extern int ocpi_enable(void);
  67
  68static struct clk *usb_host_ck;
  69static struct clk *usb_dc_ck;
  70static int host_enabled;
  71static int host_initialized;
  72
  73static void omap_ohci_clock_power(int on)
  74{
  75        if (on) {
  76                clk_enable(usb_dc_ck);
  77                clk_enable(usb_host_ck);
  78                /* guesstimate for T5 == 1x 32K clock + APLL lock time */
  79                udelay(100);
  80        } else {
  81                clk_disable(usb_host_ck);
  82                clk_disable(usb_dc_ck);
  83        }
  84}
  85
  86/*
  87 * Board specific gang-switched transceiver power on/off.
  88 * NOTE:  OSK supplies power from DC, not battery.
  89 */
  90static int omap_ohci_transceiver_power(int on)
  91{
  92        if (on) {
  93                if (machine_is_omap_innovator() && cpu_is_omap1510())
  94                        fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL)
  95                                | ((1 << 5/*usb1*/) | (1 << 3/*usb2*/)),
  96                               INNOVATOR_FPGA_CAM_USB_CONTROL);
  97                else if (machine_is_omap_osk())
  98                        tps65010_set_gpio_out_value(GPIO1, LOW);
  99        } else {
 100                if (machine_is_omap_innovator() && cpu_is_omap1510())
 101                        fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL)
 102                                & ~((1 << 5/*usb1*/) | (1 << 3/*usb2*/)),
 103                               INNOVATOR_FPGA_CAM_USB_CONTROL);
 104                else if (machine_is_omap_osk())
 105                        tps65010_set_gpio_out_value(GPIO1, HIGH);
 106        }
 107
 108        return 0;
 109}
 110
 111#ifdef CONFIG_ARCH_OMAP15XX
 112/*
 113 * OMAP-1510 specific Local Bus clock on/off
 114 */
 115static int omap_1510_local_bus_power(int on)
 116{
 117        if (on) {
 118                omap_writel((1 << 1) | (1 << 0), OMAP1510_LB_MMU_CTL);
 119                udelay(200);
 120        } else {
 121                omap_writel(0, OMAP1510_LB_MMU_CTL);
 122        }
 123
 124        return 0;
 125}
 126
 127/*
 128 * OMAP-1510 specific Local Bus initialization
 129 * NOTE: This assumes 32MB memory size in OMAP1510LB_MEMSIZE.
 130 *       See also arch/mach-omap/memory.h for __virt_to_dma() and
 131 *       __dma_to_virt() which need to match with the physical
 132 *       Local Bus address below.
 133 */
 134static int omap_1510_local_bus_init(void)
 135{
 136        unsigned int tlb;
 137        unsigned long lbaddr, physaddr;
 138
 139        omap_writel((omap_readl(OMAP1510_LB_CLOCK_DIV) & 0xfffffff8) | 0x4,
 140               OMAP1510_LB_CLOCK_DIV);
 141
 142        /* Configure the Local Bus MMU table */
 143        for (tlb = 0; tlb < OMAP1510_LB_MEMSIZE; tlb++) {
 144                lbaddr = tlb * 0x00100000 + OMAP1510_LB_OFFSET;
 145                physaddr = tlb * 0x00100000 + PHYS_OFFSET;
 146                omap_writel((lbaddr & 0x0fffffff) >> 22, OMAP1510_LB_MMU_CAM_H);
 147                omap_writel(((lbaddr & 0x003ffc00) >> 6) | 0xc,
 148                       OMAP1510_LB_MMU_CAM_L);
 149                omap_writel(physaddr >> 16, OMAP1510_LB_MMU_RAM_H);
 150                omap_writel((physaddr & 0x0000fc00) | 0x300, OMAP1510_LB_MMU_RAM_L);
 151                omap_writel(tlb << 4, OMAP1510_LB_MMU_LCK);
 152                omap_writel(0x1, OMAP1510_LB_MMU_LD_TLB);
 153        }
 154
 155        /* Enable the walking table */
 156        omap_writel(omap_readl(OMAP1510_LB_MMU_CTL) | (1 << 3), OMAP1510_LB_MMU_CTL);
 157        udelay(200);
 158
 159        return 0;
 160}
 161#else
 162#define omap_1510_local_bus_power(x)    {}
 163#define omap_1510_local_bus_init()      {}
 164#endif
 165
 166#ifdef  CONFIG_USB_OTG
 167
 168static void start_hnp(struct ohci_hcd *ohci)
 169{
 170        const unsigned  port = ohci_to_hcd(ohci)->self.otg_port - 1;
 171        unsigned long   flags;
 172        u32 l;
 173
 174        otg_start_hnp(ohci->transceiver);
 175
 176        local_irq_save(flags);
 177        ohci->transceiver->state = OTG_STATE_A_SUSPEND;
 178        writel (RH_PS_PSS, &ohci->regs->roothub.portstatus [port]);
 179        l = omap_readl(OTG_CTRL);
 180        l &= ~OTG_A_BUSREQ;
 181        omap_writel(l, OTG_CTRL);
 182        local_irq_restore(flags);
 183}
 184
 185#endif
 186
 187/*-------------------------------------------------------------------------*/
 188
 189static int ohci_omap_init(struct usb_hcd *hcd)
 190{
 191        struct ohci_hcd         *ohci = hcd_to_ohci(hcd);
 192        struct omap_usb_config  *config = hcd->self.controller->platform_data;
 193        int                     need_transceiver = (config->otg != 0);
 194        int                     ret;
 195
 196        dev_dbg(hcd->self.controller, "starting USB Controller\n");
 197
 198        if (config->otg) {
 199                ohci_to_hcd(ohci)->self.otg_port = config->otg;
 200                /* default/minimum OTG power budget:  8 mA */
 201                ohci_to_hcd(ohci)->power_budget = 8;
 202        }
 203
 204        /* boards can use OTG transceivers in non-OTG modes */
 205        need_transceiver = need_transceiver
 206                        || machine_is_omap_h2() || machine_is_omap_h3();
 207
 208        if (cpu_is_omap16xx())
 209                ocpi_enable();
 210
 211#ifdef  CONFIG_USB_OTG
 212        if (need_transceiver) {
 213                ohci->transceiver = otg_get_transceiver();
 214                if (ohci->transceiver) {
 215                        int     status = otg_set_host(ohci->transceiver,
 216                                                &ohci_to_hcd(ohci)->self);
 217                        dev_dbg(hcd->self.controller, "init %s transceiver, status %d\n",
 218                                        ohci->transceiver->label, status);
 219                        if (status) {
 220                                if (ohci->transceiver)
 221                                        put_device(ohci->transceiver->dev);
 222                                return status;
 223                        }
 224                } else {
 225                        dev_err(hcd->self.controller, "can't find transceiver\n");
 226                        return -ENODEV;
 227                }
 228                ohci->start_hnp = start_hnp;
 229        }
 230#endif
 231
 232        omap_ohci_clock_power(1);
 233
 234        if (cpu_is_omap15xx()) {
 235                omap_1510_local_bus_power(1);
 236                omap_1510_local_bus_init();
 237        }
 238
 239        if ((ret = ohci_init(ohci)) < 0)
 240                return ret;
 241
 242        /* board-specific power switching and overcurrent support */
 243        if (machine_is_omap_osk() || machine_is_omap_innovator()) {
 244                u32     rh = roothub_a (ohci);
 245
 246                /* power switching (ganged by default) */
 247                rh &= ~RH_A_NPS;
 248
 249                /* TPS2045 switch for internal transceiver (port 1) */
 250                if (machine_is_omap_osk()) {
 251                        ohci_to_hcd(ohci)->power_budget = 250;
 252
 253                        rh &= ~RH_A_NOCP;
 254
 255                        /* gpio9 for overcurrent detction */
 256                        omap_cfg_reg(W8_1610_GPIO9);
 257                        gpio_request(9, "OHCI overcurrent");
 258                        gpio_direction_input(9);
 259
 260                        /* for paranoia's sake:  disable USB.PUEN */
 261                        omap_cfg_reg(W4_USB_HIGHZ);
 262                }
 263                ohci_writel(ohci, rh, &ohci->regs->roothub.a);
 264                ohci->flags &= ~OHCI_QUIRK_HUB_POWER;
 265        } else if (machine_is_nokia770()) {
 266                /* We require a self-powered hub, which should have
 267                 * plenty of power. */
 268                ohci_to_hcd(ohci)->power_budget = 0;
 269        }
 270
 271        /* FIXME khubd hub requests should manage power switching */
 272        omap_ohci_transceiver_power(1);
 273
 274        /* board init will have already handled HMC and mux setup.
 275         * any external transceiver should already be initialized
 276         * too, so all configured ports use the right signaling now.
 277         */
 278
 279        return 0;
 280}
 281
 282static void ohci_omap_stop(struct usb_hcd *hcd)
 283{
 284        dev_dbg(hcd->self.controller, "stopping USB Controller\n");
 285        ohci_stop(hcd);
 286        omap_ohci_clock_power(0);
 287}
 288
 289
 290/*-------------------------------------------------------------------------*/
 291
 292/**
 293 * usb_hcd_omap_probe - initialize OMAP-based HCDs
 294 * Context: !in_interrupt()
 295 *
 296 * Allocates basic resources for this USB host controller, and
 297 * then invokes the start() method for the HCD associated with it
 298 * through the hotplug entry's driver_data.
 299 */
 300static int usb_hcd_omap_probe (const struct hc_driver *driver,
 301                          struct platform_device *pdev)
 302{
 303        int retval, irq;
 304        struct usb_hcd *hcd = 0;
 305        struct ohci_hcd *ohci;
 306
 307        if (pdev->num_resources != 2) {
 308                printk(KERN_ERR "hcd probe: invalid num_resources: %i\n",
 309                       pdev->num_resources);
 310                return -ENODEV;
 311        }
 312
 313        if (pdev->resource[0].flags != IORESOURCE_MEM
 314                        || pdev->resource[1].flags != IORESOURCE_IRQ) {
 315                printk(KERN_ERR "hcd probe: invalid resource type\n");
 316                return -ENODEV;
 317        }
 318
 319        usb_host_ck = clk_get(&pdev->dev, "usb_hhc_ck");
 320        if (IS_ERR(usb_host_ck))
 321                return PTR_ERR(usb_host_ck);
 322
 323        if (!cpu_is_omap15xx())
 324                usb_dc_ck = clk_get(&pdev->dev, "usb_dc_ck");
 325        else
 326                usb_dc_ck = clk_get(&pdev->dev, "lb_ck");
 327
 328        if (IS_ERR(usb_dc_ck)) {
 329                clk_put(usb_host_ck);
 330                return PTR_ERR(usb_dc_ck);
 331        }
 332
 333
 334        hcd = usb_create_hcd (driver, &pdev->dev, dev_name(&pdev->dev));
 335        if (!hcd) {
 336                retval = -ENOMEM;
 337                goto err0;
 338        }
 339        hcd->rsrc_start = pdev->resource[0].start;
 340        hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
 341
 342        if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
 343                dev_dbg(&pdev->dev, "request_mem_region failed\n");
 344                retval = -EBUSY;
 345                goto err1;
 346        }
 347
 348        hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
 349        if (!hcd->regs) {
 350                dev_err(&pdev->dev, "can't ioremap OHCI HCD\n");
 351                retval = -ENOMEM;
 352                goto err2;
 353        }
 354
 355        ohci = hcd_to_ohci(hcd);
 356        ohci_hcd_init(ohci);
 357
 358        host_initialized = 0;
 359        host_enabled = 1;
 360
 361        irq = platform_get_irq(pdev, 0);
 362        if (irq < 0) {
 363                retval = -ENXIO;
 364                goto err3;
 365        }
 366        retval = usb_add_hcd(hcd, irq, IRQF_DISABLED);
 367        if (retval)
 368                goto err3;
 369
 370        host_initialized = 1;
 371
 372        if (!host_enabled)
 373                omap_ohci_clock_power(0);
 374
 375        return 0;
 376err3:
 377        iounmap(hcd->regs);
 378err2:
 379        release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 380err1:
 381        usb_put_hcd(hcd);
 382err0:
 383        clk_put(usb_dc_ck);
 384        clk_put(usb_host_ck);
 385        return retval;
 386}
 387
 388
 389/* may be called with controller, bus, and devices active */
 390
 391/**
 392 * usb_hcd_omap_remove - shutdown processing for OMAP-based HCDs
 393 * @dev: USB Host Controller being removed
 394 * Context: !in_interrupt()
 395 *
 396 * Reverses the effect of usb_hcd_omap_probe(), first invoking
 397 * the HCD's stop() method.  It is always called from a thread
 398 * context, normally "rmmod", "apmd", or something similar.
 399 */
 400static inline void
 401usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev)
 402{
 403        struct ohci_hcd         *ohci = hcd_to_ohci (hcd);
 404
 405        usb_remove_hcd(hcd);
 406        if (ohci->transceiver) {
 407                (void) otg_set_host(ohci->transceiver, 0);
 408                put_device(ohci->transceiver->dev);
 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        platform_set_drvdata(dev, NULL);
 502
 503        return 0;
 504}
 505
 506/*-------------------------------------------------------------------------*/
 507
 508#ifdef  CONFIG_PM
 509
 510static int ohci_omap_suspend(struct platform_device *dev, pm_message_t message)
 511{
 512        struct ohci_hcd *ohci = hcd_to_ohci(platform_get_drvdata(dev));
 513
 514        if (time_before(jiffies, ohci->next_statechange))
 515                msleep(5);
 516        ohci->next_statechange = jiffies;
 517
 518        omap_ohci_clock_power(0);
 519        ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
 520        return 0;
 521}
 522
 523static int ohci_omap_resume(struct platform_device *dev)
 524{
 525        struct usb_hcd  *hcd = platform_get_drvdata(dev);
 526        struct ohci_hcd *ohci = hcd_to_ohci(hcd);
 527
 528        if (time_before(jiffies, ohci->next_statechange))
 529                msleep(5);
 530        ohci->next_statechange = jiffies;
 531
 532        omap_ohci_clock_power(1);
 533        ohci_finish_controller_resume(hcd);
 534        return 0;
 535}
 536
 537#endif
 538
 539/*-------------------------------------------------------------------------*/
 540
 541/*
 542 * Driver definition to register with the OMAP bus
 543 */
 544static struct platform_driver ohci_hcd_omap_driver = {
 545        .probe          = ohci_hcd_omap_drv_probe,
 546        .remove         = ohci_hcd_omap_drv_remove,
 547        .shutdown       = usb_hcd_platform_shutdown,
 548#ifdef  CONFIG_PM
 549        .suspend        = ohci_omap_suspend,
 550        .resume         = ohci_omap_resume,
 551#endif
 552        .driver         = {
 553                .owner  = THIS_MODULE,
 554                .name   = "ohci",
 555        },
 556};
 557
 558MODULE_ALIAS("platform:ohci");
 559