linux/arch/arm/mach-mmp/devices.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * linux/arch/arm/mach-mmp/devices.c
   4 */
   5
   6#include <linux/init.h>
   7#include <linux/platform_device.h>
   8#include <linux/dma-mapping.h>
   9#include <linux/delay.h>
  10
  11#include <asm/irq.h>
  12#include "irqs.h"
  13#include "devices.h"
  14#include "cputype.h"
  15#include "regs-usb.h"
  16
  17int __init pxa_register_device(struct pxa_device_desc *desc,
  18                                void *data, size_t size)
  19{
  20        struct platform_device *pdev;
  21        struct resource res[2 + MAX_RESOURCE_DMA];
  22        int i, ret = 0, nres = 0;
  23
  24        pdev = platform_device_alloc(desc->drv_name, desc->id);
  25        if (pdev == NULL)
  26                return -ENOMEM;
  27
  28        pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
  29
  30        memset(res, 0, sizeof(res));
  31
  32        if (desc->start != -1ul && desc->size > 0) {
  33                res[nres].start = desc->start;
  34                res[nres].end   = desc->start + desc->size - 1;
  35                res[nres].flags = IORESOURCE_MEM;
  36                nres++;
  37        }
  38
  39        if (desc->irq != NO_IRQ) {
  40                res[nres].start = desc->irq;
  41                res[nres].end   = desc->irq;
  42                res[nres].flags = IORESOURCE_IRQ;
  43                nres++;
  44        }
  45
  46        for (i = 0; i < MAX_RESOURCE_DMA; i++, nres++) {
  47                if (desc->dma[i] == 0)
  48                        break;
  49
  50                res[nres].start = desc->dma[i];
  51                res[nres].end   = desc->dma[i];
  52                res[nres].flags = IORESOURCE_DMA;
  53        }
  54
  55        ret = platform_device_add_resources(pdev, res, nres);
  56        if (ret) {
  57                platform_device_put(pdev);
  58                return ret;
  59        }
  60
  61        if (data && size) {
  62                ret = platform_device_add_data(pdev, data, size);
  63                if (ret) {
  64                        platform_device_put(pdev);
  65                        return ret;
  66                }
  67        }
  68
  69        return platform_device_add(pdev);
  70}
  71
  72#if IS_ENABLED(CONFIG_USB) || IS_ENABLED(CONFIG_USB_GADGET)
  73#if IS_ENABLED(CONFIG_USB_MV_UDC) || IS_ENABLED(CONFIG_USB_EHCI_MV)
  74#if IS_ENABLED(CONFIG_CPU_PXA910) || IS_ENABLED(CONFIG_CPU_PXA168)
  75
  76/*****************************************************************************
  77 * The registers read/write routines
  78 *****************************************************************************/
  79
  80static unsigned int u2o_get(void __iomem *base, unsigned int offset)
  81{
  82        return readl_relaxed(base + offset);
  83}
  84
  85static void u2o_set(void __iomem *base, unsigned int offset,
  86                unsigned int value)
  87{
  88        u32 reg;
  89
  90        reg = readl_relaxed(base + offset);
  91        reg |= value;
  92        writel_relaxed(reg, base + offset);
  93        readl_relaxed(base + offset);
  94}
  95
  96static void u2o_clear(void __iomem *base, unsigned int offset,
  97                unsigned int value)
  98{
  99        u32 reg;
 100
 101        reg = readl_relaxed(base + offset);
 102        reg &= ~value;
 103        writel_relaxed(reg, base + offset);
 104        readl_relaxed(base + offset);
 105}
 106
 107static void u2o_write(void __iomem *base, unsigned int offset,
 108                unsigned int value)
 109{
 110        writel_relaxed(value, base + offset);
 111        readl_relaxed(base + offset);
 112}
 113
 114
 115static DEFINE_MUTEX(phy_lock);
 116static int phy_init_cnt;
 117
 118static int usb_phy_init_internal(void __iomem *base)
 119{
 120        int loops;
 121
 122        pr_info("Init usb phy!!!\n");
 123
 124        /* Initialize the USB PHY power */
 125        if (cpu_is_pxa910()) {
 126                u2o_set(base, UTMI_CTRL, (1<<UTMI_CTRL_INPKT_DELAY_SOF_SHIFT)
 127                        | (1<<UTMI_CTRL_PU_REF_SHIFT));
 128        }
 129
 130        u2o_set(base, UTMI_CTRL, 1<<UTMI_CTRL_PLL_PWR_UP_SHIFT);
 131        u2o_set(base, UTMI_CTRL, 1<<UTMI_CTRL_PWR_UP_SHIFT);
 132
 133        /* UTMI_PLL settings */
 134        u2o_clear(base, UTMI_PLL, UTMI_PLL_PLLVDD18_MASK
 135                | UTMI_PLL_PLLVDD12_MASK | UTMI_PLL_PLLCALI12_MASK
 136                | UTMI_PLL_FBDIV_MASK | UTMI_PLL_REFDIV_MASK
 137                | UTMI_PLL_ICP_MASK | UTMI_PLL_KVCO_MASK);
 138
 139        u2o_set(base, UTMI_PLL, 0xee<<UTMI_PLL_FBDIV_SHIFT
 140                | 0xb<<UTMI_PLL_REFDIV_SHIFT | 3<<UTMI_PLL_PLLVDD18_SHIFT
 141                | 3<<UTMI_PLL_PLLVDD12_SHIFT | 3<<UTMI_PLL_PLLCALI12_SHIFT
 142                | 1<<UTMI_PLL_ICP_SHIFT | 3<<UTMI_PLL_KVCO_SHIFT);
 143
 144        /* UTMI_TX */
 145        u2o_clear(base, UTMI_TX, UTMI_TX_REG_EXT_FS_RCAL_EN_MASK
 146                | UTMI_TX_TXVDD12_MASK | UTMI_TX_CK60_PHSEL_MASK
 147                | UTMI_TX_IMPCAL_VTH_MASK | UTMI_TX_REG_EXT_FS_RCAL_MASK
 148                | UTMI_TX_AMP_MASK);
 149        u2o_set(base, UTMI_TX, 3<<UTMI_TX_TXVDD12_SHIFT
 150                | 4<<UTMI_TX_CK60_PHSEL_SHIFT | 4<<UTMI_TX_IMPCAL_VTH_SHIFT
 151                | 8<<UTMI_TX_REG_EXT_FS_RCAL_SHIFT | 3<<UTMI_TX_AMP_SHIFT);
 152
 153        /* UTMI_RX */
 154        u2o_clear(base, UTMI_RX, UTMI_RX_SQ_THRESH_MASK
 155                | UTMI_REG_SQ_LENGTH_MASK);
 156        u2o_set(base, UTMI_RX, 7<<UTMI_RX_SQ_THRESH_SHIFT
 157                | 2<<UTMI_REG_SQ_LENGTH_SHIFT);
 158
 159        /* UTMI_IVREF */
 160        if (cpu_is_pxa168())
 161                /* fixing Microsoft Altair board interface with NEC hub issue -
 162                 * Set UTMI_IVREF from 0x4a3 to 0x4bf */
 163                u2o_write(base, UTMI_IVREF, 0x4bf);
 164
 165        /* toggle VCOCAL_START bit of UTMI_PLL */
 166        udelay(200);
 167        u2o_set(base, UTMI_PLL, VCOCAL_START);
 168        udelay(40);
 169        u2o_clear(base, UTMI_PLL, VCOCAL_START);
 170
 171        /* toggle REG_RCAL_START bit of UTMI_TX */
 172        udelay(400);
 173        u2o_set(base, UTMI_TX, REG_RCAL_START);
 174        udelay(40);
 175        u2o_clear(base, UTMI_TX, REG_RCAL_START);
 176        udelay(400);
 177
 178        /* Make sure PHY PLL is ready */
 179        loops = 0;
 180        while ((u2o_get(base, UTMI_PLL) & PLL_READY) == 0) {
 181                mdelay(1);
 182                loops++;
 183                if (loops > 100) {
 184                        printk(KERN_WARNING "calibrate timeout, UTMI_PLL %x\n",
 185                                u2o_get(base, UTMI_PLL));
 186                        break;
 187                }
 188        }
 189
 190        if (cpu_is_pxa168()) {
 191                u2o_set(base, UTMI_RESERVE, 1 << 5);
 192                /* Turn on UTMI PHY OTG extension */
 193                u2o_write(base, UTMI_OTG_ADDON, 1);
 194        }
 195
 196        return 0;
 197}
 198
 199static int usb_phy_deinit_internal(void __iomem *base)
 200{
 201        pr_info("Deinit usb phy!!!\n");
 202
 203        if (cpu_is_pxa168())
 204                u2o_clear(base, UTMI_OTG_ADDON, UTMI_OTG_ADDON_OTG_ON);
 205
 206        u2o_clear(base, UTMI_CTRL, UTMI_CTRL_RXBUF_PDWN);
 207        u2o_clear(base, UTMI_CTRL, UTMI_CTRL_TXBUF_PDWN);
 208        u2o_clear(base, UTMI_CTRL, UTMI_CTRL_USB_CLK_EN);
 209        u2o_clear(base, UTMI_CTRL, 1<<UTMI_CTRL_PWR_UP_SHIFT);
 210        u2o_clear(base, UTMI_CTRL, 1<<UTMI_CTRL_PLL_PWR_UP_SHIFT);
 211
 212        return 0;
 213}
 214
 215int pxa_usb_phy_init(void __iomem *phy_reg)
 216{
 217        mutex_lock(&phy_lock);
 218        if (phy_init_cnt++ == 0)
 219                usb_phy_init_internal(phy_reg);
 220        mutex_unlock(&phy_lock);
 221        return 0;
 222}
 223
 224void pxa_usb_phy_deinit(void __iomem *phy_reg)
 225{
 226        WARN_ON(phy_init_cnt == 0);
 227
 228        mutex_lock(&phy_lock);
 229        if (--phy_init_cnt == 0)
 230                usb_phy_deinit_internal(phy_reg);
 231        mutex_unlock(&phy_lock);
 232}
 233#endif
 234#endif
 235#endif
 236
 237#if IS_ENABLED(CONFIG_USB_SUPPORT)
 238static u64 __maybe_unused usb_dma_mask = ~(u32)0;
 239
 240#if IS_ENABLED(CONFIG_PHY_PXA_USB)
 241struct resource pxa168_usb_phy_resources[] = {
 242        [0] = {
 243                .start  = PXA168_U2O_PHYBASE,
 244                .end    = PXA168_U2O_PHYBASE + USB_PHY_RANGE,
 245                .flags  = IORESOURCE_MEM,
 246        },
 247};
 248
 249struct platform_device pxa168_device_usb_phy = {
 250        .name           = "pxa-usb-phy",
 251        .id             = -1,
 252        .resource       = pxa168_usb_phy_resources,
 253        .num_resources  = ARRAY_SIZE(pxa168_usb_phy_resources),
 254        .dev            =  {
 255                .dma_mask       = &usb_dma_mask,
 256                .coherent_dma_mask = 0xffffffff,
 257        }
 258};
 259#endif /* CONFIG_PHY_PXA_USB */
 260
 261#if IS_ENABLED(CONFIG_USB_MV_UDC)
 262struct resource pxa168_u2o_resources[] = {
 263        /* regbase */
 264        [0] = {
 265                .start  = PXA168_U2O_REGBASE + U2x_CAPREGS_OFFSET,
 266                .end    = PXA168_U2O_REGBASE + USB_REG_RANGE,
 267                .flags  = IORESOURCE_MEM,
 268                .name   = "capregs",
 269        },
 270        /* phybase */
 271        [1] = {
 272                .start  = PXA168_U2O_PHYBASE,
 273                .end    = PXA168_U2O_PHYBASE + USB_PHY_RANGE,
 274                .flags  = IORESOURCE_MEM,
 275                .name   = "phyregs",
 276        },
 277        [2] = {
 278                .start  = IRQ_PXA168_USB1,
 279                .end    = IRQ_PXA168_USB1,
 280                .flags  = IORESOURCE_IRQ,
 281        },
 282};
 283
 284struct platform_device pxa168_device_u2o = {
 285        .name           = "mv-udc",
 286        .id             = -1,
 287        .resource       = pxa168_u2o_resources,
 288        .num_resources  = ARRAY_SIZE(pxa168_u2o_resources),
 289        .dev            =  {
 290                .dma_mask       = &usb_dma_mask,
 291                .coherent_dma_mask = 0xffffffff,
 292        }
 293};
 294#endif /* CONFIG_USB_MV_UDC */
 295
 296#if IS_ENABLED(CONFIG_USB_EHCI_MV_U2O)
 297struct resource pxa168_u2oehci_resources[] = {
 298        [0] = {
 299                .start  = PXA168_U2O_REGBASE,
 300                .end    = PXA168_U2O_REGBASE + USB_REG_RANGE,
 301                .flags  = IORESOURCE_MEM,
 302        },
 303        [1] = {
 304                .start  = IRQ_PXA168_USB1,
 305                .end    = IRQ_PXA168_USB1,
 306                .flags  = IORESOURCE_IRQ,
 307        },
 308};
 309
 310struct platform_device pxa168_device_u2oehci = {
 311        .name           = "pxa-u2oehci",
 312        .id             = -1,
 313        .dev            = {
 314                .dma_mask               = &usb_dma_mask,
 315                .coherent_dma_mask      = 0xffffffff,
 316        },
 317
 318        .num_resources  = ARRAY_SIZE(pxa168_u2oehci_resources),
 319        .resource       = pxa168_u2oehci_resources,
 320};
 321#endif
 322
 323#if IS_ENABLED(CONFIG_USB_MV_OTG)
 324struct resource pxa168_u2ootg_resources[] = {
 325        /* regbase */
 326        [0] = {
 327                .start  = PXA168_U2O_REGBASE + U2x_CAPREGS_OFFSET,
 328                .end    = PXA168_U2O_REGBASE + USB_REG_RANGE,
 329                .flags  = IORESOURCE_MEM,
 330                .name   = "capregs",
 331        },
 332        /* phybase */
 333        [1] = {
 334                .start  = PXA168_U2O_PHYBASE,
 335                .end    = PXA168_U2O_PHYBASE + USB_PHY_RANGE,
 336                .flags  = IORESOURCE_MEM,
 337                .name   = "phyregs",
 338        },
 339        [2] = {
 340                .start  = IRQ_PXA168_USB1,
 341                .end    = IRQ_PXA168_USB1,
 342                .flags  = IORESOURCE_IRQ,
 343        },
 344};
 345
 346struct platform_device pxa168_device_u2ootg = {
 347        .name           = "mv-otg",
 348        .id             = -1,
 349        .dev  = {
 350                .dma_mask          = &usb_dma_mask,
 351                .coherent_dma_mask = 0xffffffff,
 352        },
 353
 354        .num_resources  = ARRAY_SIZE(pxa168_u2ootg_resources),
 355        .resource      = pxa168_u2ootg_resources,
 356};
 357#endif /* CONFIG_USB_MV_OTG */
 358
 359#endif
 360