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