linux/arch/arm/mach-omap1/usb.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Platform level USB initialization for FS USB OTG controller on omap1
   4 *
   5 * Copyright (C) 2004 Texas Instruments, Inc.
   6 */
   7
   8#include <linux/module.h>
   9#include <linux/kernel.h>
  10#include <linux/init.h>
  11#include <linux/platform_device.h>
  12#include <linux/io.h>
  13
  14#include <asm/irq.h>
  15
  16#include <mach/mux.h>
  17
  18#include <mach/usb.h>
  19
  20#include "common.h"
  21
  22/* These routines should handle the standard chip-specific modes
  23 * for usb0/1/2 ports, covering basic mux and transceiver setup.
  24 *
  25 * Some board-*.c files will need to set up additional mux options,
  26 * like for suspend handling, vbus sensing, GPIOs, and the D+ pullup.
  27 */
  28
  29/* TESTED ON:
  30 *  - 1611B H2 (with usb1 mini-AB) using standard Mini-B or OTG cables
  31 *  - 5912 OSK OHCI (with usb0 standard-A), standard A-to-B cables
  32 *  - 5912 OSK UDC, with *nonstandard* A-to-A cable
  33 *  - 1510 Innovator UDC with bundled usb0 cable
  34 *  - 1510 Innovator OHCI with bundled usb1/usb2 cable
  35 *  - 1510 Innovator OHCI with custom usb0 cable, feeding 5V VBUS
  36 *  - 1710 custom development board using alternate pin group
  37 *  - 1710 H3 (with usb1 mini-AB) using standard Mini-B or OTG cables
  38 */
  39
  40#define INT_USB_IRQ_GEN         IH2_BASE + 20
  41#define INT_USB_IRQ_NISO        IH2_BASE + 30
  42#define INT_USB_IRQ_ISO         IH2_BASE + 29
  43#define INT_USB_IRQ_HGEN        INT_USB_HHC_1
  44#define INT_USB_IRQ_OTG         IH2_BASE + 8
  45
  46#ifdef  CONFIG_ARCH_OMAP_OTG
  47
  48static void __init
  49omap_otg_init(struct omap_usb_config *config)
  50{
  51        u32             syscon;
  52        int             alt_pingroup = 0;
  53        u16             w;
  54
  55        /* NOTE:  no bus or clock setup (yet?) */
  56
  57        syscon = omap_readl(OTG_SYSCON_1) & 0xffff;
  58        if (!(syscon & OTG_RESET_DONE))
  59                pr_debug("USB resets not complete?\n");
  60
  61        //omap_writew(0, OTG_IRQ_EN);
  62
  63        /* pin muxing and transceiver pinouts */
  64        if (config->pins[0] > 2)        /* alt pingroup 2 */
  65                alt_pingroup = 1;
  66        syscon |= config->usb0_init(config->pins[0], is_usb0_device(config));
  67        syscon |= config->usb1_init(config->pins[1]);
  68        syscon |= config->usb2_init(config->pins[2], alt_pingroup);
  69        pr_debug("OTG_SYSCON_1 = %08x\n", omap_readl(OTG_SYSCON_1));
  70        omap_writel(syscon, OTG_SYSCON_1);
  71
  72        syscon = config->hmc_mode;
  73        syscon |= USBX_SYNCHRO | (4 << 16) /* B_ASE0_BRST */;
  74#ifdef  CONFIG_USB_OTG
  75        if (config->otg)
  76                syscon |= OTG_EN;
  77#endif
  78        pr_debug("USB_TRANSCEIVER_CTRL = %03x\n",
  79                 omap_readl(USB_TRANSCEIVER_CTRL));
  80        pr_debug("OTG_SYSCON_2 = %08x\n", omap_readl(OTG_SYSCON_2));
  81        omap_writel(syscon, OTG_SYSCON_2);
  82
  83        printk("USB: hmc %d", config->hmc_mode);
  84        if (!alt_pingroup)
  85                pr_cont(", usb2 alt %d wires", config->pins[2]);
  86        else if (config->pins[0])
  87                pr_cont(", usb0 %d wires%s", config->pins[0],
  88                        is_usb0_device(config) ? " (dev)" : "");
  89        if (config->pins[1])
  90                pr_cont(", usb1 %d wires", config->pins[1]);
  91        if (!alt_pingroup && config->pins[2])
  92                pr_cont(", usb2 %d wires", config->pins[2]);
  93        if (config->otg)
  94                pr_cont(", Mini-AB on usb%d", config->otg - 1);
  95        pr_cont("\n");
  96
  97        /* leave USB clocks/controllers off until needed */
  98        w = omap_readw(ULPD_SOFT_REQ);
  99        w &= ~SOFT_USB_CLK_REQ;
 100        omap_writew(w, ULPD_SOFT_REQ);
 101
 102        w = omap_readw(ULPD_CLOCK_CTRL);
 103        w &= ~USB_MCLK_EN;
 104        w |= DIS_USB_PVCI_CLK;
 105        omap_writew(w, ULPD_CLOCK_CTRL);
 106
 107        syscon = omap_readl(OTG_SYSCON_1);
 108        syscon |= HST_IDLE_EN|DEV_IDLE_EN|OTG_IDLE_EN;
 109
 110#if IS_ENABLED(CONFIG_USB_OMAP)
 111        if (config->otg || config->register_dev) {
 112                struct platform_device *udc_device = config->udc_device;
 113                int status;
 114
 115                syscon &= ~DEV_IDLE_EN;
 116                udc_device->dev.platform_data = config;
 117                status = platform_device_register(udc_device);
 118                if (status)
 119                        pr_debug("can't register UDC device, %d\n", status);
 120        }
 121#endif
 122
 123#if     IS_ENABLED(CONFIG_USB_OHCI_HCD)
 124        if (config->otg || config->register_host) {
 125                struct platform_device *ohci_device = config->ohci_device;
 126                int status;
 127
 128                syscon &= ~HST_IDLE_EN;
 129                ohci_device->dev.platform_data = config;
 130                status = platform_device_register(ohci_device);
 131                if (status)
 132                        pr_debug("can't register OHCI device, %d\n", status);
 133        }
 134#endif
 135
 136#ifdef  CONFIG_USB_OTG
 137        if (config->otg) {
 138                struct platform_device *otg_device = config->otg_device;
 139                int status;
 140
 141                syscon &= ~OTG_IDLE_EN;
 142                otg_device->dev.platform_data = config;
 143                status = platform_device_register(otg_device);
 144                if (status)
 145                        pr_debug("can't register OTG device, %d\n", status);
 146        }
 147#endif
 148        pr_debug("OTG_SYSCON_1 = %08x\n", omap_readl(OTG_SYSCON_1));
 149        omap_writel(syscon, OTG_SYSCON_1);
 150}
 151
 152#else
 153static void omap_otg_init(struct omap_usb_config *config) {}
 154#endif
 155
 156#if IS_ENABLED(CONFIG_USB_OMAP)
 157
 158static struct resource udc_resources[] = {
 159        /* order is significant! */
 160        {               /* registers */
 161                .start          = UDC_BASE,
 162                .end            = UDC_BASE + 0xff,
 163                .flags          = IORESOURCE_MEM,
 164        }, {            /* general IRQ */
 165                .start          = INT_USB_IRQ_GEN,
 166                .flags          = IORESOURCE_IRQ,
 167        }, {            /* PIO IRQ */
 168                .start          = INT_USB_IRQ_NISO,
 169                .flags          = IORESOURCE_IRQ,
 170        }, {            /* SOF IRQ */
 171                .start          = INT_USB_IRQ_ISO,
 172                .flags          = IORESOURCE_IRQ,
 173        },
 174};
 175
 176static u64 udc_dmamask = ~(u32)0;
 177
 178static struct platform_device udc_device = {
 179        .name           = "omap_udc",
 180        .id             = -1,
 181        .dev = {
 182                .dma_mask               = &udc_dmamask,
 183                .coherent_dma_mask      = 0xffffffff,
 184        },
 185        .num_resources  = ARRAY_SIZE(udc_resources),
 186        .resource       = udc_resources,
 187};
 188
 189static inline void udc_device_init(struct omap_usb_config *pdata)
 190{
 191        /* IRQ numbers for omap7xx */
 192        if(cpu_is_omap7xx()) {
 193                udc_resources[1].start = INT_7XX_USB_GENI;
 194                udc_resources[2].start = INT_7XX_USB_NON_ISO;
 195                udc_resources[3].start = INT_7XX_USB_ISO;
 196        }
 197        pdata->udc_device = &udc_device;
 198}
 199
 200#else
 201
 202static inline void udc_device_init(struct omap_usb_config *pdata)
 203{
 204}
 205
 206#endif
 207
 208#if     IS_ENABLED(CONFIG_USB_OHCI_HCD)
 209
 210/* The dmamask must be set for OHCI to work */
 211static u64 ohci_dmamask = ~(u32)0;
 212
 213static struct resource ohci_resources[] = {
 214        {
 215                .start  = OMAP_OHCI_BASE,
 216                .end    = OMAP_OHCI_BASE + 0xff,
 217                .flags  = IORESOURCE_MEM,
 218        },
 219        {
 220                .start  = INT_USB_IRQ_HGEN,
 221                .flags  = IORESOURCE_IRQ,
 222        },
 223};
 224
 225static struct platform_device ohci_device = {
 226        .name                   = "ohci",
 227        .id                     = -1,
 228        .dev = {
 229                .dma_mask               = &ohci_dmamask,
 230                .coherent_dma_mask      = 0xffffffff,
 231        },
 232        .num_resources  = ARRAY_SIZE(ohci_resources),
 233        .resource               = ohci_resources,
 234};
 235
 236static inline void ohci_device_init(struct omap_usb_config *pdata)
 237{
 238        if (cpu_is_omap7xx())
 239                ohci_resources[1].start = INT_7XX_USB_HHC_1;
 240        pdata->ohci_device = &ohci_device;
 241        pdata->ocpi_enable = &ocpi_enable;
 242}
 243
 244#else
 245
 246static inline void ohci_device_init(struct omap_usb_config *pdata)
 247{
 248}
 249
 250#endif
 251
 252#if     defined(CONFIG_USB_OTG) && defined(CONFIG_ARCH_OMAP_OTG)
 253
 254static struct resource otg_resources[] = {
 255        /* order is significant! */
 256        {
 257                .start          = OTG_BASE,
 258                .end            = OTG_BASE + 0xff,
 259                .flags          = IORESOURCE_MEM,
 260        }, {
 261                .start          = INT_USB_IRQ_OTG,
 262                .flags          = IORESOURCE_IRQ,
 263        },
 264};
 265
 266static struct platform_device otg_device = {
 267        .name           = "omap_otg",
 268        .id             = -1,
 269        .num_resources  = ARRAY_SIZE(otg_resources),
 270        .resource       = otg_resources,
 271};
 272
 273static inline void otg_device_init(struct omap_usb_config *pdata)
 274{
 275        if (cpu_is_omap7xx())
 276                otg_resources[1].start = INT_7XX_USB_OTG;
 277        pdata->otg_device = &otg_device;
 278}
 279
 280#else
 281
 282static inline void otg_device_init(struct omap_usb_config *pdata)
 283{
 284}
 285
 286#endif
 287
 288static u32 __init omap1_usb0_init(unsigned nwires, unsigned is_device)
 289{
 290        u32     syscon1 = 0;
 291
 292        if (nwires == 0) {
 293                if (!cpu_is_omap15xx()) {
 294                        u32 l;
 295
 296                        /* pulldown D+/D- */
 297                        l = omap_readl(USB_TRANSCEIVER_CTRL);
 298                        l &= ~(3 << 1);
 299                        omap_writel(l, USB_TRANSCEIVER_CTRL);
 300                }
 301                return 0;
 302        }
 303
 304        if (is_device) {
 305                if (cpu_is_omap7xx()) {
 306                        omap_cfg_reg(AA17_7XX_USB_DM);
 307                        omap_cfg_reg(W16_7XX_USB_PU_EN);
 308                        omap_cfg_reg(W17_7XX_USB_VBUSI);
 309                        omap_cfg_reg(W18_7XX_USB_DMCK_OUT);
 310                        omap_cfg_reg(W19_7XX_USB_DCRST);
 311                } else
 312                        omap_cfg_reg(W4_USB_PUEN);
 313        }
 314
 315        if (nwires == 2) {
 316                u32 l;
 317
 318                // omap_cfg_reg(P9_USB_DP);
 319                // omap_cfg_reg(R8_USB_DM);
 320
 321                if (cpu_is_omap15xx()) {
 322                        /* This works on 1510-Innovator */
 323                        return 0;
 324                }
 325
 326                /* NOTES:
 327                 *  - peripheral should configure VBUS detection!
 328                 *  - only peripherals may use the internal D+/D- pulldowns
 329                 *  - OTG support on this port not yet written
 330                 */
 331
 332                /* Don't do this for omap7xx -- it causes USB to not work correctly */
 333                if (!cpu_is_omap7xx()) {
 334                        l = omap_readl(USB_TRANSCEIVER_CTRL);
 335                        l &= ~(7 << 4);
 336                        if (!is_device)
 337                                l |= (3 << 1);
 338                        omap_writel(l, USB_TRANSCEIVER_CTRL);
 339                }
 340
 341                return 3 << 16;
 342        }
 343
 344        /* alternate pin config, external transceiver */
 345        if (cpu_is_omap15xx()) {
 346                printk(KERN_ERR "no usb0 alt pin config on 15xx\n");
 347                return 0;
 348        }
 349
 350        omap_cfg_reg(V6_USB0_TXD);
 351        omap_cfg_reg(W9_USB0_TXEN);
 352        omap_cfg_reg(W5_USB0_SE0);
 353        if (nwires != 3)
 354                omap_cfg_reg(Y5_USB0_RCV);
 355
 356        /* NOTE:  SPEED and SUSP aren't configured here.  OTG hosts
 357         * may be able to use I2C requests to set those bits along
 358         * with VBUS switching and overcurrent detection.
 359         */
 360
 361        if (nwires != 6) {
 362                u32 l;
 363
 364                l = omap_readl(USB_TRANSCEIVER_CTRL);
 365                l &= ~CONF_USB2_UNI_R;
 366                omap_writel(l, USB_TRANSCEIVER_CTRL);
 367        }
 368
 369        switch (nwires) {
 370        case 3:
 371                syscon1 = 2;
 372                break;
 373        case 4:
 374                syscon1 = 1;
 375                break;
 376        case 6:
 377                syscon1 = 3;
 378                {
 379                        u32 l;
 380
 381                        omap_cfg_reg(AA9_USB0_VP);
 382                        omap_cfg_reg(R9_USB0_VM);
 383                        l = omap_readl(USB_TRANSCEIVER_CTRL);
 384                        l |= CONF_USB2_UNI_R;
 385                        omap_writel(l, USB_TRANSCEIVER_CTRL);
 386                }
 387                break;
 388        default:
 389                printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
 390                        0, nwires);
 391        }
 392
 393        return syscon1 << 16;
 394}
 395
 396static u32 __init omap1_usb1_init(unsigned nwires)
 397{
 398        u32     syscon1 = 0;
 399
 400        if (!cpu_is_omap15xx() && nwires != 6) {
 401                u32 l;
 402
 403                l = omap_readl(USB_TRANSCEIVER_CTRL);
 404                l &= ~CONF_USB1_UNI_R;
 405                omap_writel(l, USB_TRANSCEIVER_CTRL);
 406        }
 407        if (nwires == 0)
 408                return 0;
 409
 410        /* external transceiver */
 411        omap_cfg_reg(USB1_TXD);
 412        omap_cfg_reg(USB1_TXEN);
 413        if (nwires != 3)
 414                omap_cfg_reg(USB1_RCV);
 415
 416        if (cpu_is_omap15xx()) {
 417                omap_cfg_reg(USB1_SEO);
 418                omap_cfg_reg(USB1_SPEED);
 419                // SUSP
 420        } else if (cpu_is_omap1610() || cpu_is_omap5912()) {
 421                omap_cfg_reg(W13_1610_USB1_SE0);
 422                omap_cfg_reg(R13_1610_USB1_SPEED);
 423                // SUSP
 424        } else if (cpu_is_omap1710()) {
 425                omap_cfg_reg(R13_1710_USB1_SE0);
 426                // SUSP
 427        } else {
 428                pr_debug("usb%d cpu unrecognized\n", 1);
 429                return 0;
 430        }
 431
 432        switch (nwires) {
 433        case 2:
 434                goto bad;
 435        case 3:
 436                syscon1 = 2;
 437                break;
 438        case 4:
 439                syscon1 = 1;
 440                break;
 441        case 6:
 442                syscon1 = 3;
 443                omap_cfg_reg(USB1_VP);
 444                omap_cfg_reg(USB1_VM);
 445                if (!cpu_is_omap15xx()) {
 446                        u32 l;
 447
 448                        l = omap_readl(USB_TRANSCEIVER_CTRL);
 449                        l |= CONF_USB1_UNI_R;
 450                        omap_writel(l, USB_TRANSCEIVER_CTRL);
 451                }
 452                break;
 453        default:
 454bad:
 455                printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
 456                        1, nwires);
 457        }
 458
 459        return syscon1 << 20;
 460}
 461
 462static u32 __init omap1_usb2_init(unsigned nwires, unsigned alt_pingroup)
 463{
 464        u32     syscon1 = 0;
 465
 466        /* NOTE omap1 erratum: must leave USB2_UNI_R set if usb0 in use */
 467        if (alt_pingroup || nwires == 0)
 468                return 0;
 469
 470        if (!cpu_is_omap15xx() && nwires != 6) {
 471                u32 l;
 472
 473                l = omap_readl(USB_TRANSCEIVER_CTRL);
 474                l &= ~CONF_USB2_UNI_R;
 475                omap_writel(l, USB_TRANSCEIVER_CTRL);
 476        }
 477
 478        /* external transceiver */
 479        if (cpu_is_omap15xx()) {
 480                omap_cfg_reg(USB2_TXD);
 481                omap_cfg_reg(USB2_TXEN);
 482                omap_cfg_reg(USB2_SEO);
 483                if (nwires != 3)
 484                        omap_cfg_reg(USB2_RCV);
 485                /* there is no USB2_SPEED */
 486        } else if (cpu_is_omap16xx()) {
 487                omap_cfg_reg(V6_USB2_TXD);
 488                omap_cfg_reg(W9_USB2_TXEN);
 489                omap_cfg_reg(W5_USB2_SE0);
 490                if (nwires != 3)
 491                        omap_cfg_reg(Y5_USB2_RCV);
 492                // FIXME omap_cfg_reg(USB2_SPEED);
 493        } else {
 494                pr_debug("usb%d cpu unrecognized\n", 1);
 495                return 0;
 496        }
 497
 498        // omap_cfg_reg(USB2_SUSP);
 499
 500        switch (nwires) {
 501        case 2:
 502                goto bad;
 503        case 3:
 504                syscon1 = 2;
 505                break;
 506        case 4:
 507                syscon1 = 1;
 508                break;
 509        case 5:
 510                goto bad;
 511        case 6:
 512                syscon1 = 3;
 513                if (cpu_is_omap15xx()) {
 514                        omap_cfg_reg(USB2_VP);
 515                        omap_cfg_reg(USB2_VM);
 516                } else {
 517                        u32 l;
 518
 519                        omap_cfg_reg(AA9_USB2_VP);
 520                        omap_cfg_reg(R9_USB2_VM);
 521                        l = omap_readl(USB_TRANSCEIVER_CTRL);
 522                        l |= CONF_USB2_UNI_R;
 523                        omap_writel(l, USB_TRANSCEIVER_CTRL);
 524                }
 525                break;
 526        default:
 527bad:
 528                printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
 529                        2, nwires);
 530        }
 531
 532        return syscon1 << 24;
 533}
 534
 535#ifdef  CONFIG_ARCH_OMAP15XX
 536
 537/* ULPD_DPLL_CTRL */
 538#define DPLL_IOB                (1 << 13)
 539#define DPLL_PLL_ENABLE         (1 << 4)
 540#define DPLL_LOCK               (1 << 0)
 541
 542/* ULPD_APLL_CTRL */
 543#define APLL_NDPLL_SWITCH       (1 << 0)
 544
 545static void __init omap_1510_usb_init(struct omap_usb_config *config)
 546{
 547        unsigned int val;
 548        u16 w;
 549
 550        config->usb0_init(config->pins[0], is_usb0_device(config));
 551        config->usb1_init(config->pins[1]);
 552        config->usb2_init(config->pins[2], 0);
 553
 554        val = omap_readl(MOD_CONF_CTRL_0) & ~(0x3f << 1);
 555        val |= (config->hmc_mode << 1);
 556        omap_writel(val, MOD_CONF_CTRL_0);
 557
 558        printk("USB: hmc %d", config->hmc_mode);
 559        if (config->pins[0])
 560                pr_cont(", usb0 %d wires%s", config->pins[0],
 561                        is_usb0_device(config) ? " (dev)" : "");
 562        if (config->pins[1])
 563                pr_cont(", usb1 %d wires", config->pins[1]);
 564        if (config->pins[2])
 565                pr_cont(", usb2 %d wires", config->pins[2]);
 566        pr_cont("\n");
 567
 568        /* use DPLL for 48 MHz function clock */
 569        pr_debug("APLL %04x DPLL %04x REQ %04x\n", omap_readw(ULPD_APLL_CTRL),
 570                        omap_readw(ULPD_DPLL_CTRL), omap_readw(ULPD_SOFT_REQ));
 571
 572        w = omap_readw(ULPD_APLL_CTRL);
 573        w &= ~APLL_NDPLL_SWITCH;
 574        omap_writew(w, ULPD_APLL_CTRL);
 575
 576        w = omap_readw(ULPD_DPLL_CTRL);
 577        w |= DPLL_IOB | DPLL_PLL_ENABLE;
 578        omap_writew(w, ULPD_DPLL_CTRL);
 579
 580        w = omap_readw(ULPD_SOFT_REQ);
 581        w |= SOFT_UDC_REQ | SOFT_DPLL_REQ;
 582        omap_writew(w, ULPD_SOFT_REQ);
 583
 584        while (!(omap_readw(ULPD_DPLL_CTRL) & DPLL_LOCK))
 585                cpu_relax();
 586
 587#if IS_ENABLED(CONFIG_USB_OMAP)
 588        if (config->register_dev) {
 589                int status;
 590
 591                udc_device.dev.platform_data = config;
 592                status = platform_device_register(&udc_device);
 593                if (status)
 594                        pr_debug("can't register UDC device, %d\n", status);
 595                /* udc driver gates 48MHz by D+ pullup */
 596        }
 597#endif
 598
 599#if     IS_ENABLED(CONFIG_USB_OHCI_HCD)
 600        if (config->register_host) {
 601                int status;
 602
 603                ohci_device.dev.platform_data = config;
 604                status = platform_device_register(&ohci_device);
 605                if (status)
 606                        pr_debug("can't register OHCI device, %d\n", status);
 607                /* hcd explicitly gates 48MHz */
 608        }
 609#endif
 610}
 611
 612#else
 613static inline void omap_1510_usb_init(struct omap_usb_config *config) {}
 614#endif
 615
 616void __init omap1_usb_init(struct omap_usb_config *_pdata)
 617{
 618        struct omap_usb_config *pdata;
 619
 620        pdata = kmemdup(_pdata, sizeof(*pdata), GFP_KERNEL);
 621        if (!pdata)
 622                return;
 623
 624        pdata->usb0_init = omap1_usb0_init;
 625        pdata->usb1_init = omap1_usb1_init;
 626        pdata->usb2_init = omap1_usb2_init;
 627        udc_device_init(pdata);
 628        ohci_device_init(pdata);
 629        otg_device_init(pdata);
 630
 631        if (cpu_is_omap7xx() || cpu_is_omap16xx())
 632                omap_otg_init(pdata);
 633        else if (cpu_is_omap15xx())
 634                omap_1510_usb_init(pdata);
 635        else
 636                printk(KERN_ERR "USB: No init for your chip yet\n");
 637}
 638