linux/drivers/mfd/omap-usb-host.c
<<
>>
Prefs
   1/**
   2 * omap-usb-host.c - The USBHS core driver for OMAP EHCI & OHCI
   3 *
   4 * Copyright (C) 2011-2013 Texas Instruments Incorporated - http://www.ti.com
   5 * Author: Keshava Munegowda <keshava_mgowda@ti.com>
   6 * Author: Roger Quadros <rogerq@ti.com>
   7 *
   8 * This program is free software: you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2  of
  10 * the License as published by the Free Software Foundation.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  19 */
  20#include <linux/kernel.h>
  21#include <linux/module.h>
  22#include <linux/types.h>
  23#include <linux/slab.h>
  24#include <linux/delay.h>
  25#include <linux/clk.h>
  26#include <linux/dma-mapping.h>
  27#include <linux/gpio.h>
  28#include <linux/platform_device.h>
  29#include <linux/platform_data/usb-omap.h>
  30#include <linux/pm_runtime.h>
  31#include <linux/of.h>
  32#include <linux/of_platform.h>
  33#include <linux/err.h>
  34
  35#include "omap-usb.h"
  36
  37#define USBHS_DRIVER_NAME       "usbhs_omap"
  38#define OMAP_EHCI_DEVICE        "ehci-omap"
  39#define OMAP_OHCI_DEVICE        "ohci-omap3"
  40
  41/* OMAP USBHOST Register addresses  */
  42
  43/* UHH Register Set */
  44#define OMAP_UHH_REVISION                               (0x00)
  45#define OMAP_UHH_SYSCONFIG                              (0x10)
  46#define OMAP_UHH_SYSCONFIG_MIDLEMODE                    (1 << 12)
  47#define OMAP_UHH_SYSCONFIG_CACTIVITY                    (1 << 8)
  48#define OMAP_UHH_SYSCONFIG_SIDLEMODE                    (1 << 3)
  49#define OMAP_UHH_SYSCONFIG_ENAWAKEUP                    (1 << 2)
  50#define OMAP_UHH_SYSCONFIG_SOFTRESET                    (1 << 1)
  51#define OMAP_UHH_SYSCONFIG_AUTOIDLE                     (1 << 0)
  52
  53#define OMAP_UHH_SYSSTATUS                              (0x14)
  54#define OMAP_UHH_HOSTCONFIG                             (0x40)
  55#define OMAP_UHH_HOSTCONFIG_ULPI_BYPASS                 (1 << 0)
  56#define OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS              (1 << 0)
  57#define OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS              (1 << 11)
  58#define OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS              (1 << 12)
  59#define OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN              (1 << 2)
  60#define OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN              (1 << 3)
  61#define OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN             (1 << 4)
  62#define OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN              (1 << 5)
  63#define OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS           (1 << 8)
  64#define OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS           (1 << 9)
  65#define OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS           (1 << 10)
  66#define OMAP4_UHH_HOSTCONFIG_APP_START_CLK              (1 << 31)
  67
  68/* OMAP4-specific defines */
  69#define OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR              (3 << 2)
  70#define OMAP4_UHH_SYSCONFIG_NOIDLE                      (1 << 2)
  71#define OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR             (3 << 4)
  72#define OMAP4_UHH_SYSCONFIG_NOSTDBY                     (1 << 4)
  73#define OMAP4_UHH_SYSCONFIG_SOFTRESET                   (1 << 0)
  74
  75#define OMAP4_P1_MODE_CLEAR                             (3 << 16)
  76#define OMAP4_P1_MODE_TLL                               (1 << 16)
  77#define OMAP4_P1_MODE_HSIC                              (3 << 16)
  78#define OMAP4_P2_MODE_CLEAR                             (3 << 18)
  79#define OMAP4_P2_MODE_TLL                               (1 << 18)
  80#define OMAP4_P2_MODE_HSIC                              (3 << 18)
  81
  82#define OMAP_UHH_DEBUG_CSR                              (0x44)
  83
  84/* Values of UHH_REVISION - Note: these are not given in the TRM */
  85#define OMAP_USBHS_REV1         0x00000010      /* OMAP3 */
  86#define OMAP_USBHS_REV2         0x50700100      /* OMAP4 */
  87
  88#define is_omap_usbhs_rev1(x)   (x->usbhs_rev == OMAP_USBHS_REV1)
  89#define is_omap_usbhs_rev2(x)   (x->usbhs_rev == OMAP_USBHS_REV2)
  90
  91#define is_ehci_phy_mode(x)     (x == OMAP_EHCI_PORT_MODE_PHY)
  92#define is_ehci_tll_mode(x)     (x == OMAP_EHCI_PORT_MODE_TLL)
  93#define is_ehci_hsic_mode(x)    (x == OMAP_EHCI_PORT_MODE_HSIC)
  94
  95
  96struct usbhs_hcd_omap {
  97        int                             nports;
  98        struct clk                      **utmi_clk;
  99        struct clk                      **hsic60m_clk;
 100        struct clk                      **hsic480m_clk;
 101
 102        struct clk                      *xclk60mhsp1_ck;
 103        struct clk                      *xclk60mhsp2_ck;
 104        struct clk                      *utmi_p1_gfclk;
 105        struct clk                      *utmi_p2_gfclk;
 106        struct clk                      *init_60m_fclk;
 107        struct clk                      *ehci_logic_fck;
 108
 109        void __iomem                    *uhh_base;
 110
 111        struct usbhs_omap_platform_data *pdata;
 112
 113        u32                             usbhs_rev;
 114};
 115/*-------------------------------------------------------------------------*/
 116
 117static const char usbhs_driver_name[] = USBHS_DRIVER_NAME;
 118static u64 usbhs_dmamask = DMA_BIT_MASK(32);
 119
 120/*-------------------------------------------------------------------------*/
 121
 122static inline void usbhs_write(void __iomem *base, u32 reg, u32 val)
 123{
 124        writel_relaxed(val, base + reg);
 125}
 126
 127static inline u32 usbhs_read(void __iomem *base, u32 reg)
 128{
 129        return readl_relaxed(base + reg);
 130}
 131
 132/*-------------------------------------------------------------------------*/
 133
 134/**
 135 * Map 'enum usbhs_omap_port_mode' found in <linux/platform_data/usb-omap.h>
 136 * to the device tree binding portN-mode found in
 137 * 'Documentation/devicetree/bindings/mfd/omap-usb-host.txt'
 138 */
 139static const char * const port_modes[] = {
 140        [OMAP_USBHS_PORT_MODE_UNUSED]   = "",
 141        [OMAP_EHCI_PORT_MODE_PHY]       = "ehci-phy",
 142        [OMAP_EHCI_PORT_MODE_TLL]       = "ehci-tll",
 143        [OMAP_EHCI_PORT_MODE_HSIC]      = "ehci-hsic",
 144        [OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0]   = "ohci-phy-6pin-datse0",
 145        [OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM]     = "ohci-phy-6pin-dpdm",
 146        [OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0]   = "ohci-phy-3pin-datse0",
 147        [OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM]     = "ohci-phy-4pin-dpdm",
 148        [OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0]   = "ohci-tll-6pin-datse0",
 149        [OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM]     = "ohci-tll-6pin-dpdm",
 150        [OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0]   = "ohci-tll-3pin-datse0",
 151        [OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM]     = "ohci-tll-4pin-dpdm",
 152        [OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0]   = "ohci-tll-2pin-datse0",
 153        [OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM]     = "ohci-tll-2pin-dpdm",
 154};
 155
 156/**
 157 * omap_usbhs_get_dt_port_mode - Get the 'enum usbhs_omap_port_mode'
 158 * from the port mode string.
 159 * @mode: The port mode string, usually obtained from device tree.
 160 *
 161 * The function returns the 'enum usbhs_omap_port_mode' that matches the
 162 * provided port mode string as per the port_modes table.
 163 * If no match is found it returns -ENODEV
 164 */
 165static int omap_usbhs_get_dt_port_mode(const char *mode)
 166{
 167        int i;
 168
 169        for (i = 0; i < ARRAY_SIZE(port_modes); i++) {
 170                if (!strcmp(mode, port_modes[i]))
 171                        return i;
 172        }
 173
 174        return -ENODEV;
 175}
 176
 177static struct platform_device *omap_usbhs_alloc_child(const char *name,
 178                        struct resource *res, int num_resources, void *pdata,
 179                        size_t pdata_size, struct device *dev)
 180{
 181        struct platform_device  *child;
 182        int                     ret;
 183
 184        child = platform_device_alloc(name, 0);
 185
 186        if (!child) {
 187                dev_err(dev, "platform_device_alloc %s failed\n", name);
 188                goto err_end;
 189        }
 190
 191        ret = platform_device_add_resources(child, res, num_resources);
 192        if (ret) {
 193                dev_err(dev, "platform_device_add_resources failed\n");
 194                goto err_alloc;
 195        }
 196
 197        ret = platform_device_add_data(child, pdata, pdata_size);
 198        if (ret) {
 199                dev_err(dev, "platform_device_add_data failed\n");
 200                goto err_alloc;
 201        }
 202
 203        child->dev.dma_mask             = &usbhs_dmamask;
 204        dma_set_coherent_mask(&child->dev, DMA_BIT_MASK(32));
 205        child->dev.parent               = dev;
 206
 207        ret = platform_device_add(child);
 208        if (ret) {
 209                dev_err(dev, "platform_device_add failed\n");
 210                goto err_alloc;
 211        }
 212
 213        return child;
 214
 215err_alloc:
 216        platform_device_put(child);
 217
 218err_end:
 219        return NULL;
 220}
 221
 222static int omap_usbhs_alloc_children(struct platform_device *pdev)
 223{
 224        struct device                           *dev = &pdev->dev;
 225        struct usbhs_omap_platform_data         *pdata = dev_get_platdata(dev);
 226        struct platform_device                  *ehci;
 227        struct platform_device                  *ohci;
 228        struct resource                         *res;
 229        struct resource                         resources[2];
 230        int                                     ret;
 231
 232        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ehci");
 233        if (!res) {
 234                dev_err(dev, "EHCI get resource IORESOURCE_MEM failed\n");
 235                ret = -ENODEV;
 236                goto err_end;
 237        }
 238        resources[0] = *res;
 239
 240        res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ehci-irq");
 241        if (!res) {
 242                dev_err(dev, " EHCI get resource IORESOURCE_IRQ failed\n");
 243                ret = -ENODEV;
 244                goto err_end;
 245        }
 246        resources[1] = *res;
 247
 248        ehci = omap_usbhs_alloc_child(OMAP_EHCI_DEVICE, resources, 2, pdata,
 249                sizeof(*pdata), dev);
 250
 251        if (!ehci) {
 252                dev_err(dev, "omap_usbhs_alloc_child failed\n");
 253                ret = -ENOMEM;
 254                goto err_end;
 255        }
 256
 257        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ohci");
 258        if (!res) {
 259                dev_err(dev, "OHCI get resource IORESOURCE_MEM failed\n");
 260                ret = -ENODEV;
 261                goto err_ehci;
 262        }
 263        resources[0] = *res;
 264
 265        res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ohci-irq");
 266        if (!res) {
 267                dev_err(dev, "OHCI get resource IORESOURCE_IRQ failed\n");
 268                ret = -ENODEV;
 269                goto err_ehci;
 270        }
 271        resources[1] = *res;
 272
 273        ohci = omap_usbhs_alloc_child(OMAP_OHCI_DEVICE, resources, 2, pdata,
 274                sizeof(*pdata), dev);
 275        if (!ohci) {
 276                dev_err(dev, "omap_usbhs_alloc_child failed\n");
 277                ret = -ENOMEM;
 278                goto err_ehci;
 279        }
 280
 281        return 0;
 282
 283err_ehci:
 284        platform_device_unregister(ehci);
 285
 286err_end:
 287        return ret;
 288}
 289
 290static bool is_ohci_port(enum usbhs_omap_port_mode pmode)
 291{
 292        switch (pmode) {
 293        case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
 294        case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
 295        case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
 296        case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
 297        case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
 298        case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
 299        case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
 300        case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
 301        case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
 302        case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
 303                return true;
 304
 305        default:
 306                return false;
 307        }
 308}
 309
 310static int usbhs_runtime_resume(struct device *dev)
 311{
 312        struct usbhs_hcd_omap           *omap = dev_get_drvdata(dev);
 313        struct usbhs_omap_platform_data *pdata = omap->pdata;
 314        int i, r;
 315
 316        dev_dbg(dev, "usbhs_runtime_resume\n");
 317
 318        omap_tll_enable(pdata);
 319
 320        if (!IS_ERR(omap->ehci_logic_fck))
 321                clk_prepare_enable(omap->ehci_logic_fck);
 322
 323        for (i = 0; i < omap->nports; i++) {
 324                switch (pdata->port_mode[i]) {
 325                case OMAP_EHCI_PORT_MODE_HSIC:
 326                        if (!IS_ERR(omap->hsic60m_clk[i])) {
 327                                r = clk_prepare_enable(omap->hsic60m_clk[i]);
 328                                if (r) {
 329                                        dev_err(dev,
 330                                         "Can't enable port %d hsic60m clk:%d\n",
 331                                         i, r);
 332                                }
 333                        }
 334
 335                        if (!IS_ERR(omap->hsic480m_clk[i])) {
 336                                r = clk_prepare_enable(omap->hsic480m_clk[i]);
 337                                if (r) {
 338                                        dev_err(dev,
 339                                         "Can't enable port %d hsic480m clk:%d\n",
 340                                         i, r);
 341                                }
 342                        }
 343                /* Fall through as HSIC mode needs utmi_clk */
 344
 345                case OMAP_EHCI_PORT_MODE_TLL:
 346                        if (!IS_ERR(omap->utmi_clk[i])) {
 347                                r = clk_prepare_enable(omap->utmi_clk[i]);
 348                                if (r) {
 349                                        dev_err(dev,
 350                                         "Can't enable port %d clk : %d\n",
 351                                         i, r);
 352                                }
 353                        }
 354                        break;
 355                default:
 356                        break;
 357                }
 358        }
 359
 360        return 0;
 361}
 362
 363static int usbhs_runtime_suspend(struct device *dev)
 364{
 365        struct usbhs_hcd_omap           *omap = dev_get_drvdata(dev);
 366        struct usbhs_omap_platform_data *pdata = omap->pdata;
 367        int i;
 368
 369        dev_dbg(dev, "usbhs_runtime_suspend\n");
 370
 371        for (i = 0; i < omap->nports; i++) {
 372                switch (pdata->port_mode[i]) {
 373                case OMAP_EHCI_PORT_MODE_HSIC:
 374                        if (!IS_ERR(omap->hsic60m_clk[i]))
 375                                clk_disable_unprepare(omap->hsic60m_clk[i]);
 376
 377                        if (!IS_ERR(omap->hsic480m_clk[i]))
 378                                clk_disable_unprepare(omap->hsic480m_clk[i]);
 379                /* Fall through as utmi_clks were used in HSIC mode */
 380
 381                case OMAP_EHCI_PORT_MODE_TLL:
 382                        if (!IS_ERR(omap->utmi_clk[i]))
 383                                clk_disable_unprepare(omap->utmi_clk[i]);
 384                        break;
 385                default:
 386                        break;
 387                }
 388        }
 389
 390        if (!IS_ERR(omap->ehci_logic_fck))
 391                clk_disable_unprepare(omap->ehci_logic_fck);
 392
 393        omap_tll_disable(pdata);
 394
 395        return 0;
 396}
 397
 398static unsigned omap_usbhs_rev1_hostconfig(struct usbhs_hcd_omap *omap,
 399                                                unsigned reg)
 400{
 401        struct usbhs_omap_platform_data *pdata = omap->pdata;
 402        int i;
 403
 404        for (i = 0; i < omap->nports; i++) {
 405                switch (pdata->port_mode[i]) {
 406                case OMAP_USBHS_PORT_MODE_UNUSED:
 407                        reg &= ~(OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS << i);
 408                        break;
 409                case OMAP_EHCI_PORT_MODE_PHY:
 410                        if (pdata->single_ulpi_bypass)
 411                                break;
 412
 413                        if (i == 0)
 414                                reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS;
 415                        else
 416                                reg &= ~(OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS
 417                                                                << (i-1));
 418                        break;
 419                default:
 420                        if (pdata->single_ulpi_bypass)
 421                                break;
 422
 423                        if (i == 0)
 424                                reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS;
 425                        else
 426                                reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS
 427                                                                << (i-1);
 428                        break;
 429                }
 430        }
 431
 432        if (pdata->single_ulpi_bypass) {
 433                /* bypass ULPI only if none of the ports use PHY mode */
 434                reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
 435
 436                for (i = 0; i < omap->nports; i++) {
 437                        if (is_ehci_phy_mode(pdata->port_mode[i])) {
 438                                reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
 439                                break;
 440                        }
 441                }
 442        }
 443
 444        return reg;
 445}
 446
 447static unsigned omap_usbhs_rev2_hostconfig(struct usbhs_hcd_omap *omap,
 448                                                unsigned reg)
 449{
 450        struct usbhs_omap_platform_data *pdata = omap->pdata;
 451        int i;
 452
 453        for (i = 0; i < omap->nports; i++) {
 454                /* Clear port mode fields for PHY mode */
 455                reg &= ~(OMAP4_P1_MODE_CLEAR << 2 * i);
 456
 457                if (is_ehci_tll_mode(pdata->port_mode[i]) ||
 458                                (is_ohci_port(pdata->port_mode[i])))
 459                        reg |= OMAP4_P1_MODE_TLL << 2 * i;
 460                else if (is_ehci_hsic_mode(pdata->port_mode[i]))
 461                        reg |= OMAP4_P1_MODE_HSIC << 2 * i;
 462        }
 463
 464        return reg;
 465}
 466
 467static void omap_usbhs_init(struct device *dev)
 468{
 469        struct usbhs_hcd_omap           *omap = dev_get_drvdata(dev);
 470        unsigned                        reg;
 471
 472        dev_dbg(dev, "starting TI HSUSB Controller\n");
 473
 474        pm_runtime_get_sync(dev);
 475
 476        reg = usbhs_read(omap->uhh_base, OMAP_UHH_HOSTCONFIG);
 477        /* setup ULPI bypass and burst configurations */
 478        reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN
 479                        | OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN
 480                        | OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN);
 481        reg |= OMAP4_UHH_HOSTCONFIG_APP_START_CLK;
 482        reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN;
 483
 484        switch (omap->usbhs_rev) {
 485        case OMAP_USBHS_REV1:
 486                reg = omap_usbhs_rev1_hostconfig(omap, reg);
 487                break;
 488
 489        case OMAP_USBHS_REV2:
 490                reg = omap_usbhs_rev2_hostconfig(omap, reg);
 491                break;
 492
 493        default:        /* newer revisions */
 494                reg = omap_usbhs_rev2_hostconfig(omap, reg);
 495                break;
 496        }
 497
 498        usbhs_write(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg);
 499        dev_dbg(dev, "UHH setup done, uhh_hostconfig=%x\n", reg);
 500
 501        pm_runtime_put_sync(dev);
 502}
 503
 504static int usbhs_omap_get_dt_pdata(struct device *dev,
 505                                        struct usbhs_omap_platform_data *pdata)
 506{
 507        int ret, i;
 508        struct device_node *node = dev->of_node;
 509
 510        ret = of_property_read_u32(node, "num-ports", &pdata->nports);
 511        if (ret)
 512                pdata->nports = 0;
 513
 514        if (pdata->nports > OMAP3_HS_USB_PORTS) {
 515                dev_warn(dev, "Too many num_ports <%d> in device tree. Max %d\n",
 516                                pdata->nports, OMAP3_HS_USB_PORTS);
 517                return -ENODEV;
 518        }
 519
 520        /* get port modes */
 521        for (i = 0; i < OMAP3_HS_USB_PORTS; i++) {
 522                char prop[11];
 523                const char *mode;
 524
 525                pdata->port_mode[i] = OMAP_USBHS_PORT_MODE_UNUSED;
 526
 527                snprintf(prop, sizeof(prop), "port%d-mode", i + 1);
 528                ret = of_property_read_string(node, prop, &mode);
 529                if (ret < 0)
 530                        continue;
 531
 532                ret = omap_usbhs_get_dt_port_mode(mode);
 533                if (ret < 0) {
 534                        dev_warn(dev, "Invalid port%d-mode \"%s\" in device tree\n",
 535                                        i, mode);
 536                        return -ENODEV;
 537                }
 538
 539                dev_dbg(dev, "port%d-mode: %s -> %d\n", i, mode, ret);
 540                pdata->port_mode[i] = ret;
 541        }
 542
 543        /* get flags */
 544        pdata->single_ulpi_bypass = of_property_read_bool(node,
 545                                                "single-ulpi-bypass");
 546
 547        return 0;
 548}
 549
 550static const struct of_device_id usbhs_child_match_table[] = {
 551        { .compatible = "ti,omap-ehci", },
 552        { .compatible = "ti,omap-ohci", },
 553        { }
 554};
 555
 556/**
 557 * usbhs_omap_probe - initialize TI-based HCDs
 558 *
 559 * Allocates basic resources for this USB host controller.
 560 */
 561static int usbhs_omap_probe(struct platform_device *pdev)
 562{
 563        struct device                   *dev =  &pdev->dev;
 564        struct usbhs_omap_platform_data *pdata = dev_get_platdata(dev);
 565        struct usbhs_hcd_omap           *omap;
 566        struct resource                 *res;
 567        int                             ret = 0;
 568        int                             i;
 569        bool                            need_logic_fck;
 570
 571        if (dev->of_node) {
 572                /* For DT boot we populate platform data from OF node */
 573                pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
 574                if (!pdata)
 575                        return -ENOMEM;
 576
 577                ret = usbhs_omap_get_dt_pdata(dev, pdata);
 578                if (ret)
 579                        return ret;
 580
 581                dev->platform_data = pdata;
 582        }
 583
 584        if (!pdata) {
 585                dev_err(dev, "Missing platform data\n");
 586                return -ENODEV;
 587        }
 588
 589        if (pdata->nports > OMAP3_HS_USB_PORTS) {
 590                dev_info(dev, "Too many num_ports <%d> in platform_data. Max %d\n",
 591                                pdata->nports, OMAP3_HS_USB_PORTS);
 592                return -ENODEV;
 593        }
 594
 595        omap = devm_kzalloc(dev, sizeof(*omap), GFP_KERNEL);
 596        if (!omap) {
 597                dev_err(dev, "Memory allocation failed\n");
 598                return -ENOMEM;
 599        }
 600
 601        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 602        omap->uhh_base = devm_ioremap_resource(dev, res);
 603        if (IS_ERR(omap->uhh_base))
 604                return PTR_ERR(omap->uhh_base);
 605
 606        omap->pdata = pdata;
 607
 608        /* Initialize the TLL subsystem */
 609        omap_tll_init(pdata);
 610
 611        pm_runtime_enable(dev);
 612
 613        platform_set_drvdata(pdev, omap);
 614        pm_runtime_get_sync(dev);
 615
 616        omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION);
 617
 618        /* we need to call runtime suspend before we update omap->nports
 619         * to prevent unbalanced clk_disable()
 620         */
 621        pm_runtime_put_sync(dev);
 622
 623        /*
 624         * If platform data contains nports then use that
 625         * else make out number of ports from USBHS revision
 626         */
 627        if (pdata->nports) {
 628                omap->nports = pdata->nports;
 629        } else {
 630                switch (omap->usbhs_rev) {
 631                case OMAP_USBHS_REV1:
 632                        omap->nports = 3;
 633                        break;
 634                case OMAP_USBHS_REV2:
 635                        omap->nports = 2;
 636                        break;
 637                default:
 638                        omap->nports = OMAP3_HS_USB_PORTS;
 639                        dev_dbg(dev,
 640                         "USB HOST Rev:0x%x not recognized, assuming %d ports\n",
 641                         omap->usbhs_rev, omap->nports);
 642                        break;
 643                }
 644                pdata->nports = omap->nports;
 645        }
 646
 647        i = sizeof(struct clk *) * omap->nports;
 648        omap->utmi_clk = devm_kzalloc(dev, i, GFP_KERNEL);
 649        omap->hsic480m_clk = devm_kzalloc(dev, i, GFP_KERNEL);
 650        omap->hsic60m_clk = devm_kzalloc(dev, i, GFP_KERNEL);
 651
 652        if (!omap->utmi_clk || !omap->hsic480m_clk || !omap->hsic60m_clk) {
 653                dev_err(dev, "Memory allocation failed\n");
 654                ret = -ENOMEM;
 655                goto err_mem;
 656        }
 657
 658        /* Set all clocks as invalid to begin with */
 659        omap->ehci_logic_fck = ERR_PTR(-ENODEV);
 660        omap->init_60m_fclk = ERR_PTR(-ENODEV);
 661        omap->utmi_p1_gfclk = ERR_PTR(-ENODEV);
 662        omap->utmi_p2_gfclk = ERR_PTR(-ENODEV);
 663        omap->xclk60mhsp1_ck = ERR_PTR(-ENODEV);
 664        omap->xclk60mhsp2_ck = ERR_PTR(-ENODEV);
 665
 666        for (i = 0; i < omap->nports; i++) {
 667                omap->utmi_clk[i] = ERR_PTR(-ENODEV);
 668                omap->hsic480m_clk[i] = ERR_PTR(-ENODEV);
 669                omap->hsic60m_clk[i] = ERR_PTR(-ENODEV);
 670        }
 671
 672        /* for OMAP3 i.e. USBHS REV1 */
 673        if (omap->usbhs_rev == OMAP_USBHS_REV1) {
 674                need_logic_fck = false;
 675                for (i = 0; i < omap->nports; i++) {
 676                        if (is_ehci_phy_mode(pdata->port_mode[i]) ||
 677                            is_ehci_tll_mode(pdata->port_mode[i]) ||
 678                            is_ehci_hsic_mode(pdata->port_mode[i]))
 679
 680                                need_logic_fck |= true;
 681                }
 682
 683                if (need_logic_fck) {
 684                        omap->ehci_logic_fck = devm_clk_get(dev,
 685                                                            "usbhost_120m_fck");
 686                        if (IS_ERR(omap->ehci_logic_fck)) {
 687                                ret = PTR_ERR(omap->ehci_logic_fck);
 688                                dev_err(dev, "usbhost_120m_fck failed:%d\n",
 689                                        ret);
 690                                goto err_mem;
 691                        }
 692                }
 693                goto initialize;
 694        }
 695
 696        /* for OMAP4+ i.e. USBHS REV2+ */
 697        omap->utmi_p1_gfclk = devm_clk_get(dev, "utmi_p1_gfclk");
 698        if (IS_ERR(omap->utmi_p1_gfclk)) {
 699                ret = PTR_ERR(omap->utmi_p1_gfclk);
 700                dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret);
 701                goto err_mem;
 702        }
 703
 704        omap->utmi_p2_gfclk = devm_clk_get(dev, "utmi_p2_gfclk");
 705        if (IS_ERR(omap->utmi_p2_gfclk)) {
 706                ret = PTR_ERR(omap->utmi_p2_gfclk);
 707                dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret);
 708                goto err_mem;
 709        }
 710
 711        omap->xclk60mhsp1_ck = devm_clk_get(dev, "refclk_60m_ext_p1");
 712        if (IS_ERR(omap->xclk60mhsp1_ck)) {
 713                ret = PTR_ERR(omap->xclk60mhsp1_ck);
 714                dev_err(dev, "refclk_60m_ext_p1 failed error:%d\n", ret);
 715                goto err_mem;
 716        }
 717
 718        omap->xclk60mhsp2_ck = devm_clk_get(dev, "refclk_60m_ext_p2");
 719        if (IS_ERR(omap->xclk60mhsp2_ck)) {
 720                ret = PTR_ERR(omap->xclk60mhsp2_ck);
 721                dev_err(dev, "refclk_60m_ext_p2 failed error:%d\n", ret);
 722                goto err_mem;
 723        }
 724
 725        omap->init_60m_fclk = devm_clk_get(dev, "refclk_60m_int");
 726        if (IS_ERR(omap->init_60m_fclk)) {
 727                ret = PTR_ERR(omap->init_60m_fclk);
 728                dev_err(dev, "refclk_60m_int failed error:%d\n", ret);
 729                goto err_mem;
 730        }
 731
 732        for (i = 0; i < omap->nports; i++) {
 733                char clkname[30];
 734
 735                /* clock names are indexed from 1*/
 736                snprintf(clkname, sizeof(clkname),
 737                                "usb_host_hs_utmi_p%d_clk", i + 1);
 738
 739                /* If a clock is not found we won't bail out as not all
 740                 * platforms have all clocks and we can function without
 741                 * them
 742                 */
 743                omap->utmi_clk[i] = devm_clk_get(dev, clkname);
 744                if (IS_ERR(omap->utmi_clk[i])) {
 745                        ret = PTR_ERR(omap->utmi_clk[i]);
 746                        dev_err(dev, "Failed to get clock : %s : %d\n",
 747                                clkname, ret);
 748                        goto err_mem;
 749                }
 750
 751                snprintf(clkname, sizeof(clkname),
 752                                "usb_host_hs_hsic480m_p%d_clk", i + 1);
 753                omap->hsic480m_clk[i] = devm_clk_get(dev, clkname);
 754                if (IS_ERR(omap->hsic480m_clk[i])) {
 755                        ret = PTR_ERR(omap->hsic480m_clk[i]);
 756                        dev_err(dev, "Failed to get clock : %s : %d\n",
 757                                clkname, ret);
 758                        goto err_mem;
 759                }
 760
 761                snprintf(clkname, sizeof(clkname),
 762                                "usb_host_hs_hsic60m_p%d_clk", i + 1);
 763                omap->hsic60m_clk[i] = devm_clk_get(dev, clkname);
 764                if (IS_ERR(omap->hsic60m_clk[i])) {
 765                        ret = PTR_ERR(omap->hsic60m_clk[i]);
 766                        dev_err(dev, "Failed to get clock : %s : %d\n",
 767                                clkname, ret);
 768                        goto err_mem;
 769                }
 770        }
 771
 772        if (is_ehci_phy_mode(pdata->port_mode[0])) {
 773                ret = clk_set_parent(omap->utmi_p1_gfclk,
 774                                        omap->xclk60mhsp1_ck);
 775                if (ret != 0) {
 776                        dev_err(dev, "xclk60mhsp1_ck set parent failed: %d\n",
 777                                ret);
 778                        goto err_mem;
 779                }
 780        } else if (is_ehci_tll_mode(pdata->port_mode[0])) {
 781                ret = clk_set_parent(omap->utmi_p1_gfclk,
 782                                        omap->init_60m_fclk);
 783                if (ret != 0) {
 784                        dev_err(dev, "P0 init_60m_fclk set parent failed: %d\n",
 785                                ret);
 786                        goto err_mem;
 787                }
 788        }
 789
 790        if (is_ehci_phy_mode(pdata->port_mode[1])) {
 791                ret = clk_set_parent(omap->utmi_p2_gfclk,
 792                                        omap->xclk60mhsp2_ck);
 793                if (ret != 0) {
 794                        dev_err(dev, "xclk60mhsp2_ck set parent failed: %d\n",
 795                                ret);
 796                        goto err_mem;
 797                }
 798        } else if (is_ehci_tll_mode(pdata->port_mode[1])) {
 799                ret = clk_set_parent(omap->utmi_p2_gfclk,
 800                                                omap->init_60m_fclk);
 801                if (ret != 0) {
 802                        dev_err(dev, "P1 init_60m_fclk set parent failed: %d\n",
 803                                ret);
 804                        goto err_mem;
 805                }
 806        }
 807
 808initialize:
 809        omap_usbhs_init(dev);
 810
 811        if (dev->of_node) {
 812                ret = of_platform_populate(dev->of_node,
 813                                usbhs_child_match_table, NULL, dev);
 814
 815                if (ret) {
 816                        dev_err(dev, "Failed to create DT children: %d\n", ret);
 817                        goto err_mem;
 818                }
 819
 820        } else {
 821                ret = omap_usbhs_alloc_children(pdev);
 822                if (ret) {
 823                        dev_err(dev, "omap_usbhs_alloc_children failed: %d\n",
 824                                                ret);
 825                        goto err_mem;
 826                }
 827        }
 828
 829        return 0;
 830
 831err_mem:
 832        pm_runtime_disable(dev);
 833
 834        return ret;
 835}
 836
 837static int usbhs_omap_remove_child(struct device *dev, void *data)
 838{
 839        dev_info(dev, "unregistering\n");
 840        platform_device_unregister(to_platform_device(dev));
 841        return 0;
 842}
 843
 844/**
 845 * usbhs_omap_remove - shutdown processing for UHH & TLL HCDs
 846 * @pdev: USB Host Controller being removed
 847 *
 848 * Reverses the effect of usbhs_omap_probe().
 849 */
 850static int usbhs_omap_remove(struct platform_device *pdev)
 851{
 852        pm_runtime_disable(&pdev->dev);
 853
 854        /* remove children */
 855        device_for_each_child(&pdev->dev, NULL, usbhs_omap_remove_child);
 856        return 0;
 857}
 858
 859static const struct dev_pm_ops usbhsomap_dev_pm_ops = {
 860        .runtime_suspend        = usbhs_runtime_suspend,
 861        .runtime_resume         = usbhs_runtime_resume,
 862};
 863
 864static const struct of_device_id usbhs_omap_dt_ids[] = {
 865        { .compatible = "ti,usbhs-host" },
 866        { }
 867};
 868
 869MODULE_DEVICE_TABLE(of, usbhs_omap_dt_ids);
 870
 871
 872static struct platform_driver usbhs_omap_driver = {
 873        .driver = {
 874                .name           = (char *)usbhs_driver_name,
 875                .pm             = &usbhsomap_dev_pm_ops,
 876                .of_match_table = usbhs_omap_dt_ids,
 877        },
 878        .remove         = usbhs_omap_remove,
 879};
 880
 881MODULE_AUTHOR("Keshava Munegowda <keshava_mgowda@ti.com>");
 882MODULE_AUTHOR("Roger Quadros <rogerq@ti.com>");
 883MODULE_ALIAS("platform:" USBHS_DRIVER_NAME);
 884MODULE_LICENSE("GPL v2");
 885MODULE_DESCRIPTION("usb host common core driver for omap EHCI and OHCI");
 886
 887static int __init omap_usbhs_drvinit(void)
 888{
 889        return platform_driver_probe(&usbhs_omap_driver, usbhs_omap_probe);
 890}
 891
 892/*
 893 * init before ehci and ohci drivers;
 894 * The usbhs core driver should be initialized much before
 895 * the omap ehci and ohci probe functions are called.
 896 * This usbhs core driver should be initialized after
 897 * usb tll driver
 898 */
 899fs_initcall_sync(omap_usbhs_drvinit);
 900
 901static void __exit omap_usbhs_drvexit(void)
 902{
 903        platform_driver_unregister(&usbhs_omap_driver);
 904}
 905module_exit(omap_usbhs_drvexit);
 906