linux/arch/arm/mach-davinci/usb-da8xx.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * DA8xx USB
   4 */
   5#include <linux/clk.h>
   6#include <linux/delay.h>
   7#include <linux/dma-mapping.h>
   8#include <linux/init.h>
   9#include <linux/mfd/da8xx-cfgchip.h>
  10#include <linux/phy/phy.h>
  11#include <linux/platform_data/phy-da8xx-usb.h>
  12#include <linux/platform_data/usb-davinci.h>
  13#include <linux/platform_device.h>
  14#include <linux/usb/musb.h>
  15
  16#include <mach/clock.h>
  17#include <mach/common.h>
  18#include <mach/cputype.h>
  19#include <mach/da8xx.h>
  20#include <mach/irqs.h>
  21
  22#include "clock.h"
  23
  24#define DA8XX_USB0_BASE         0x01e00000
  25#define DA8XX_USB1_BASE         0x01e25000
  26
  27static struct clk *usb20_clk;
  28
  29static struct da8xx_usb_phy_platform_data da8xx_usb_phy_pdata;
  30
  31static struct platform_device da8xx_usb_phy = {
  32        .name           = "da8xx-usb-phy",
  33        .id             = -1,
  34        .dev            = {
  35                /*
  36                 * Setting init_name so that clock lookup will work in
  37                 * da8xx_register_usb11_phy_clk() even if this device is not
  38                 * registered yet.
  39                 */
  40                .init_name      = "da8xx-usb-phy",
  41                .platform_data  = &da8xx_usb_phy_pdata,
  42        },
  43};
  44
  45int __init da8xx_register_usb_phy(void)
  46{
  47        da8xx_usb_phy_pdata.cfgchip = da8xx_get_cfgchip();
  48
  49        return platform_device_register(&da8xx_usb_phy);
  50}
  51
  52static struct musb_hdrc_config musb_config = {
  53        .multipoint     = true,
  54        .num_eps        = 5,
  55        .ram_bits       = 10,
  56};
  57
  58static struct musb_hdrc_platform_data usb_data = {
  59        /* OTG requires a Mini-AB connector */
  60        .mode           = MUSB_OTG,
  61        .clock          = "usb20",
  62        .config         = &musb_config,
  63};
  64
  65static struct resource da8xx_usb20_resources[] = {
  66        {
  67                .start          = DA8XX_USB0_BASE,
  68                .end            = DA8XX_USB0_BASE + SZ_64K - 1,
  69                .flags          = IORESOURCE_MEM,
  70        },
  71        {
  72                .start          = IRQ_DA8XX_USB_INT,
  73                .flags          = IORESOURCE_IRQ,
  74                .name           = "mc",
  75        },
  76};
  77
  78static u64 usb_dmamask = DMA_BIT_MASK(32);
  79
  80static struct platform_device da8xx_usb20_dev = {
  81        .name           = "musb-da8xx",
  82        .id             = -1,
  83        .dev = {
  84                /*
  85                 * Setting init_name so that clock lookup will work in
  86                 * usb20_phy_clk_enable() even if this device is not registered.
  87                 */
  88                .init_name              = "musb-da8xx",
  89                .platform_data          = &usb_data,
  90                .dma_mask               = &usb_dmamask,
  91                .coherent_dma_mask      = DMA_BIT_MASK(32),
  92        },
  93        .resource       = da8xx_usb20_resources,
  94        .num_resources  = ARRAY_SIZE(da8xx_usb20_resources),
  95};
  96
  97int __init da8xx_register_usb20(unsigned int mA, unsigned int potpgt)
  98{
  99        usb_data.power  = mA > 510 ? 255 : mA / 2;
 100        usb_data.potpgt = (potpgt + 1) / 2;
 101
 102        return platform_device_register(&da8xx_usb20_dev);
 103}
 104
 105static struct resource da8xx_usb11_resources[] = {
 106        [0] = {
 107                .start  = DA8XX_USB1_BASE,
 108                .end    = DA8XX_USB1_BASE + SZ_4K - 1,
 109                .flags  = IORESOURCE_MEM,
 110        },
 111        [1] = {
 112                .start  = IRQ_DA8XX_IRQN,
 113                .end    = IRQ_DA8XX_IRQN,
 114                .flags  = IORESOURCE_IRQ,
 115        },
 116};
 117
 118static u64 da8xx_usb11_dma_mask = DMA_BIT_MASK(32);
 119
 120static struct platform_device da8xx_usb11_device = {
 121        .name           = "ohci-da8xx",
 122        .id             = -1,
 123        .dev = {
 124                .dma_mask               = &da8xx_usb11_dma_mask,
 125                .coherent_dma_mask      = DMA_BIT_MASK(32),
 126        },
 127        .num_resources  = ARRAY_SIZE(da8xx_usb11_resources),
 128        .resource       = da8xx_usb11_resources,
 129};
 130
 131int __init da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata)
 132{
 133        da8xx_usb11_device.dev.platform_data = pdata;
 134        return platform_device_register(&da8xx_usb11_device);
 135}
 136
 137static struct clk usb_refclkin = {
 138        .name           = "usb_refclkin",
 139        .set_rate       = davinci_simple_set_rate,
 140};
 141
 142static struct clk_lookup usb_refclkin_lookup =
 143        CLK(NULL, "usb_refclkin", &usb_refclkin);
 144
 145/**
 146 * da8xx_register_usb_refclkin - register USB_REFCLKIN clock
 147 *
 148 * @rate: The clock rate in Hz
 149 *
 150 * This clock is only needed if the board provides an external USB_REFCLKIN
 151 * signal, in which case it will be used as the parent of usb20_phy_clk and/or
 152 * usb11_phy_clk.
 153 */
 154int __init da8xx_register_usb_refclkin(int rate)
 155{
 156        int ret;
 157
 158        usb_refclkin.rate = rate;
 159        ret = clk_register(&usb_refclkin);
 160        if (ret)
 161                return ret;
 162
 163        clkdev_add(&usb_refclkin_lookup);
 164
 165        return 0;
 166}
 167
 168static void usb20_phy_clk_enable(struct clk *clk)
 169{
 170        u32 val;
 171        u32 timeout = 500000; /* 500 msec */
 172
 173        val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
 174
 175        /* The USB 2.O PLL requires that the USB 2.O PSC is enabled as well. */
 176        davinci_clk_enable(usb20_clk);
 177
 178        /*
 179         * Turn on the USB 2.0 PHY, but just the PLL, and not OTG. The USB 1.1
 180         * host may use the PLL clock without USB 2.0 OTG being used.
 181         */
 182        val &= ~(CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN);
 183        val |= CFGCHIP2_PHY_PLLON;
 184
 185        writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
 186
 187        while (--timeout) {
 188                val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
 189                if (val & CFGCHIP2_PHYCLKGD)
 190                        goto done;
 191                udelay(1);
 192        }
 193
 194        pr_err("Timeout waiting for USB 2.0 PHY clock good\n");
 195done:
 196        davinci_clk_disable(usb20_clk);
 197}
 198
 199static void usb20_phy_clk_disable(struct clk *clk)
 200{
 201        u32 val;
 202
 203        val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
 204        val |= CFGCHIP2_PHYPWRDN;
 205        writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
 206}
 207
 208static int usb20_phy_clk_set_parent(struct clk *clk, struct clk *parent)
 209{
 210        u32 val;
 211
 212        val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
 213
 214        /* Set the mux depending on the parent clock. */
 215        if (parent == &usb_refclkin) {
 216                val &= ~CFGCHIP2_USB2PHYCLKMUX;
 217        } else if (strcmp(parent->name, "pll0_aux_clk") == 0) {
 218                val |= CFGCHIP2_USB2PHYCLKMUX;
 219        } else {
 220                pr_err("Bad parent on USB 2.0 PHY clock\n");
 221                return -EINVAL;
 222        }
 223
 224        /* reference frequency also comes from parent clock */
 225        val &= ~CFGCHIP2_REFFREQ_MASK;
 226        switch (clk_get_rate(parent)) {
 227        case 12000000:
 228                val |= CFGCHIP2_REFFREQ_12MHZ;
 229                break;
 230        case 13000000:
 231                val |= CFGCHIP2_REFFREQ_13MHZ;
 232                break;
 233        case 19200000:
 234                val |= CFGCHIP2_REFFREQ_19_2MHZ;
 235                break;
 236        case 20000000:
 237                val |= CFGCHIP2_REFFREQ_20MHZ;
 238                break;
 239        case 24000000:
 240                val |= CFGCHIP2_REFFREQ_24MHZ;
 241                break;
 242        case 26000000:
 243                val |= CFGCHIP2_REFFREQ_26MHZ;
 244                break;
 245        case 38400000:
 246                val |= CFGCHIP2_REFFREQ_38_4MHZ;
 247                break;
 248        case 40000000:
 249                val |= CFGCHIP2_REFFREQ_40MHZ;
 250                break;
 251        case 48000000:
 252                val |= CFGCHIP2_REFFREQ_48MHZ;
 253                break;
 254        default:
 255                pr_err("Bad parent clock rate on USB 2.0 PHY clock\n");
 256                return -EINVAL;
 257        }
 258
 259        writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
 260
 261        return 0;
 262}
 263
 264static struct clk usb20_phy_clk = {
 265        .name           = "usb0_clk48",
 266        .clk_enable     = usb20_phy_clk_enable,
 267        .clk_disable    = usb20_phy_clk_disable,
 268        .set_parent     = usb20_phy_clk_set_parent,
 269};
 270
 271static struct clk_lookup usb20_phy_clk_lookup =
 272        CLK("da8xx-usb-phy", "usb0_clk48", &usb20_phy_clk);
 273
 274/**
 275 * da8xx_register_usb20_phy_clk - register USB0PHYCLKMUX clock
 276 *
 277 * @use_usb_refclkin: Selects the parent clock - either "usb_refclkin" if true
 278 *      or "pll0_aux" if false.
 279 */
 280int __init da8xx_register_usb20_phy_clk(bool use_usb_refclkin)
 281{
 282        struct clk *parent;
 283        int ret;
 284
 285        usb20_clk = clk_get(&da8xx_usb20_dev.dev, "usb20");
 286        ret = PTR_ERR_OR_ZERO(usb20_clk);
 287        if (ret)
 288                return ret;
 289
 290        parent = clk_get(NULL, use_usb_refclkin ? "usb_refclkin" : "pll0_aux");
 291        ret = PTR_ERR_OR_ZERO(parent);
 292        if (ret) {
 293                clk_put(usb20_clk);
 294                return ret;
 295        }
 296
 297        usb20_phy_clk.parent = parent;
 298        ret = clk_register(&usb20_phy_clk);
 299        if (!ret)
 300                clkdev_add(&usb20_phy_clk_lookup);
 301
 302        clk_put(parent);
 303
 304        return ret;
 305}
 306
 307static int usb11_phy_clk_set_parent(struct clk *clk, struct clk *parent)
 308{
 309        u32 val;
 310
 311        val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
 312
 313        /* Set the USB 1.1 PHY clock mux based on the parent clock. */
 314        if (parent == &usb20_phy_clk) {
 315                val &= ~CFGCHIP2_USB1PHYCLKMUX;
 316        } else if (parent == &usb_refclkin) {
 317                val |= CFGCHIP2_USB1PHYCLKMUX;
 318        } else {
 319                pr_err("Bad parent on USB 1.1 PHY clock\n");
 320                return -EINVAL;
 321        }
 322
 323        writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
 324
 325        return 0;
 326}
 327
 328static struct clk usb11_phy_clk = {
 329        .name           = "usb1_clk48",
 330        .set_parent     = usb11_phy_clk_set_parent,
 331};
 332
 333static struct clk_lookup usb11_phy_clk_lookup =
 334        CLK("da8xx-usb-phy", "usb1_clk48", &usb11_phy_clk);
 335
 336/**
 337 * da8xx_register_usb11_phy_clk - register USB1PHYCLKMUX clock
 338 *
 339 * @use_usb_refclkin: Selects the parent clock - either "usb_refclkin" if true
 340 *      or "usb0_clk48" if false.
 341 */
 342int __init da8xx_register_usb11_phy_clk(bool use_usb_refclkin)
 343{
 344        struct clk *parent;
 345        int ret = 0;
 346
 347        if (use_usb_refclkin)
 348                parent = clk_get(NULL, "usb_refclkin");
 349        else
 350                parent = clk_get(&da8xx_usb_phy.dev, "usb0_clk48");
 351        if (IS_ERR(parent))
 352                return PTR_ERR(parent);
 353
 354        usb11_phy_clk.parent = parent;
 355        ret = clk_register(&usb11_phy_clk);
 356        if (!ret)
 357                clkdev_add(&usb11_phy_clk_lookup);
 358
 359        clk_put(parent);
 360
 361        return ret;
 362}
 363