linux/drivers/phy/phy-exynos5250-usb2.c
<<
>>
Prefs
   1/*
   2 * Samsung SoC USB 1.1/2.0 PHY driver - Exynos 5250 support
   3 *
   4 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
   5 * Author: Kamil Debski <k.debski@samsung.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 as
   9 * published by the Free Software Foundation.
  10 */
  11
  12#include <linux/delay.h>
  13#include <linux/io.h>
  14#include <linux/phy/phy.h>
  15#include <linux/regmap.h>
  16#include "phy-samsung-usb2.h"
  17
  18/* Exynos USB PHY registers */
  19#define EXYNOS_5250_REFCLKSEL_CRYSTAL   0x0
  20#define EXYNOS_5250_REFCLKSEL_XO        0x1
  21#define EXYNOS_5250_REFCLKSEL_CLKCORE   0x2
  22
  23#define EXYNOS_5250_FSEL_9MHZ6          0x0
  24#define EXYNOS_5250_FSEL_10MHZ          0x1
  25#define EXYNOS_5250_FSEL_12MHZ          0x2
  26#define EXYNOS_5250_FSEL_19MHZ2         0x3
  27#define EXYNOS_5250_FSEL_20MHZ          0x4
  28#define EXYNOS_5250_FSEL_24MHZ          0x5
  29#define EXYNOS_5250_FSEL_50MHZ          0x7
  30
  31/* Normal host */
  32#define EXYNOS_5250_HOSTPHYCTRL0                        0x0
  33
  34#define EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL            BIT(31)
  35#define EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_SHIFT        19
  36#define EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_MASK \
  37                (0x3 << EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_SHIFT)
  38#define EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT             16
  39#define EXYNOS_5250_HOSTPHYCTRL0_FSEL_MASK \
  40                (0x7 << EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT)
  41#define EXYNOS_5250_HOSTPHYCTRL0_TESTBURNIN             BIT(11)
  42#define EXYNOS_5250_HOSTPHYCTRL0_RETENABLE              BIT(10)
  43#define EXYNOS_5250_HOSTPHYCTRL0_COMMON_ON_N            BIT(9)
  44#define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_MASK         (0x3 << 7)
  45#define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_DUAL         (0x0 << 7)
  46#define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_ID0          (0x1 << 7)
  47#define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_ANALOGTEST   (0x2 << 7)
  48#define EXYNOS_5250_HOSTPHYCTRL0_SIDDQ                  BIT(6)
  49#define EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP             BIT(5)
  50#define EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND           BIT(4)
  51#define EXYNOS_5250_HOSTPHYCTRL0_WORDINTERFACE          BIT(3)
  52#define EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST              BIT(2)
  53#define EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST              BIT(1)
  54#define EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST               BIT(0)
  55
  56/* HSIC0 & HSIC1 */
  57#define EXYNOS_5250_HSICPHYCTRL1                        0x10
  58#define EXYNOS_5250_HSICPHYCTRL2                        0x20
  59
  60#define EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_MASK         (0x3 << 23)
  61#define EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT      (0x2 << 23)
  62#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_MASK         (0x7f << 16)
  63#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12           (0x24 << 16)
  64#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_15           (0x1c << 16)
  65#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_16           (0x1a << 16)
  66#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_19_2         (0x15 << 16)
  67#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_20           (0x14 << 16)
  68#define EXYNOS_5250_HSICPHYCTRLX_SIDDQ                  BIT(6)
  69#define EXYNOS_5250_HSICPHYCTRLX_FORCESLEEP             BIT(5)
  70#define EXYNOS_5250_HSICPHYCTRLX_FORCESUSPEND           BIT(4)
  71#define EXYNOS_5250_HSICPHYCTRLX_WORDINTERFACE          BIT(3)
  72#define EXYNOS_5250_HSICPHYCTRLX_UTMISWRST              BIT(2)
  73#define EXYNOS_5250_HSICPHYCTRLX_PHYSWRST               BIT(0)
  74
  75/* EHCI control */
  76#define EXYNOS_5250_HOSTEHCICTRL                        0x30
  77#define EXYNOS_5250_HOSTEHCICTRL_ENAINCRXALIGN          BIT(29)
  78#define EXYNOS_5250_HOSTEHCICTRL_ENAINCR4               BIT(28)
  79#define EXYNOS_5250_HOSTEHCICTRL_ENAINCR8               BIT(27)
  80#define EXYNOS_5250_HOSTEHCICTRL_ENAINCR16              BIT(26)
  81#define EXYNOS_5250_HOSTEHCICTRL_AUTOPPDONOVRCUREN      BIT(25)
  82#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT        19
  83#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_MASK \
  84                (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT)
  85#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_SHIFT        13
  86#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_MASK \
  87                (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_SHIFT)
  88#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL2_SHIFT        7
  89#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_MASK \
  90                (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT)
  91#define EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_SHIFT     1
  92#define EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_MASK \
  93                (0x1 << EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_SHIFT)
  94#define EXYNOS_5250_HOSTEHCICTRL_SIMULATIONMODE         BIT(0)
  95
  96/* OHCI control */
  97#define EXYNOS_5250_HOSTOHCICTRL                        0x34
  98#define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_SHIFT      1
  99#define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_MASK \
 100                (0x3ff << EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_SHIFT)
 101#define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVALEN          BIT(0)
 102
 103/* USBOTG */
 104#define EXYNOS_5250_USBOTGSYS                           0x38
 105#define EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET          BIT(14)
 106#define EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG          BIT(13)
 107#define EXYNOS_5250_USBOTGSYS_PHY_SW_RST                BIT(12)
 108#define EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT           9
 109#define EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK \
 110                (0x3 << EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT)
 111#define EXYNOS_5250_USBOTGSYS_ID_PULLUP                 BIT(8)
 112#define EXYNOS_5250_USBOTGSYS_COMMON_ON                 BIT(7)
 113#define EXYNOS_5250_USBOTGSYS_FSEL_SHIFT                4
 114#define EXYNOS_5250_USBOTGSYS_FSEL_MASK \
 115                (0x3 << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT)
 116#define EXYNOS_5250_USBOTGSYS_FORCE_SLEEP               BIT(3)
 117#define EXYNOS_5250_USBOTGSYS_OTGDISABLE                BIT(2)
 118#define EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG                BIT(1)
 119#define EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND             BIT(0)
 120
 121/* Isolation, configured in the power management unit */
 122#define EXYNOS_5250_USB_ISOL_OTG_OFFSET         0x704
 123#define EXYNOS_5250_USB_ISOL_OTG                BIT(0)
 124#define EXYNOS_5250_USB_ISOL_HOST_OFFSET        0x708
 125#define EXYNOS_5250_USB_ISOL_HOST               BIT(0)
 126
 127/* Mode swtich register */
 128#define EXYNOS_5250_MODE_SWITCH_OFFSET          0x230
 129#define EXYNOS_5250_MODE_SWITCH_MASK            1
 130#define EXYNOS_5250_MODE_SWITCH_DEVICE          0
 131#define EXYNOS_5250_MODE_SWITCH_HOST            1
 132
 133enum exynos4x12_phy_id {
 134        EXYNOS5250_DEVICE,
 135        EXYNOS5250_HOST,
 136        EXYNOS5250_HSIC0,
 137        EXYNOS5250_HSIC1,
 138        EXYNOS5250_NUM_PHYS,
 139};
 140
 141/*
 142 * exynos5250_rate_to_clk() converts the supplied clock rate to the value that
 143 * can be written to the phy register.
 144 */
 145static int exynos5250_rate_to_clk(unsigned long rate, u32 *reg)
 146{
 147        /* EXYNOS_5250_FSEL_MASK */
 148
 149        switch (rate) {
 150        case 9600 * KHZ:
 151                *reg = EXYNOS_5250_FSEL_9MHZ6;
 152                break;
 153        case 10 * MHZ:
 154                *reg = EXYNOS_5250_FSEL_10MHZ;
 155                break;
 156        case 12 * MHZ:
 157                *reg = EXYNOS_5250_FSEL_12MHZ;
 158                break;
 159        case 19200 * KHZ:
 160                *reg = EXYNOS_5250_FSEL_19MHZ2;
 161                break;
 162        case 20 * MHZ:
 163                *reg = EXYNOS_5250_FSEL_20MHZ;
 164                break;
 165        case 24 * MHZ:
 166                *reg = EXYNOS_5250_FSEL_24MHZ;
 167                break;
 168        case 50 * MHZ:
 169                *reg = EXYNOS_5250_FSEL_50MHZ;
 170                break;
 171        default:
 172                return -EINVAL;
 173        }
 174
 175        return 0;
 176}
 177
 178static void exynos5250_isol(struct samsung_usb2_phy_instance *inst, bool on)
 179{
 180        struct samsung_usb2_phy_driver *drv = inst->drv;
 181        u32 offset;
 182        u32 mask;
 183
 184        switch (inst->cfg->id) {
 185        case EXYNOS5250_DEVICE:
 186                offset = EXYNOS_5250_USB_ISOL_OTG_OFFSET;
 187                mask = EXYNOS_5250_USB_ISOL_OTG;
 188                break;
 189        case EXYNOS5250_HOST:
 190                offset = EXYNOS_5250_USB_ISOL_HOST_OFFSET;
 191                mask = EXYNOS_5250_USB_ISOL_HOST;
 192                break;
 193        default:
 194                return;
 195        };
 196
 197        regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask);
 198}
 199
 200static int exynos5250_power_on(struct samsung_usb2_phy_instance *inst)
 201{
 202        struct samsung_usb2_phy_driver *drv = inst->drv;
 203        u32 ctrl0;
 204        u32 otg;
 205        u32 ehci;
 206        u32 ohci;
 207        u32 hsic;
 208
 209        switch (inst->cfg->id) {
 210        case EXYNOS5250_DEVICE:
 211                regmap_update_bits(drv->reg_sys,
 212                                   EXYNOS_5250_MODE_SWITCH_OFFSET,
 213                                   EXYNOS_5250_MODE_SWITCH_MASK,
 214                                   EXYNOS_5250_MODE_SWITCH_DEVICE);
 215
 216                /* OTG configuration */
 217                otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS);
 218                /* The clock */
 219                otg &= ~EXYNOS_5250_USBOTGSYS_FSEL_MASK;
 220                otg |= drv->ref_reg_val << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT;
 221                /* Reset */
 222                otg &= ~(EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND |
 223                        EXYNOS_5250_USBOTGSYS_FORCE_SLEEP |
 224                        EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG);
 225                otg |=  EXYNOS_5250_USBOTGSYS_PHY_SW_RST |
 226                        EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET |
 227                        EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |
 228                        EXYNOS_5250_USBOTGSYS_OTGDISABLE;
 229                /* Ref clock */
 230                otg &=  ~EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK;
 231                otg |=  EXYNOS_5250_REFCLKSEL_CLKCORE <<
 232                                        EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT;
 233                writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);
 234                udelay(100);
 235                otg &= ~(EXYNOS_5250_USBOTGSYS_PHY_SW_RST |
 236                        EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |
 237                        EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET |
 238                        EXYNOS_5250_USBOTGSYS_OTGDISABLE);
 239                writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);
 240
 241
 242                break;
 243        case EXYNOS5250_HOST:
 244        case EXYNOS5250_HSIC0:
 245        case EXYNOS5250_HSIC1:
 246                /* Host registers configuration */
 247                ctrl0 = readl(drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
 248                /* The clock */
 249                ctrl0 &= ~EXYNOS_5250_HOSTPHYCTRL0_FSEL_MASK;
 250                ctrl0 |= drv->ref_reg_val <<
 251                                        EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT;
 252
 253                /* Reset */
 254                ctrl0 &=        ~(EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST |
 255                                EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL |
 256                                EXYNOS_5250_HOSTPHYCTRL0_SIDDQ |
 257                                EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND |
 258                                EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP);
 259                ctrl0 |=        EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST |
 260                                EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST |
 261                                EXYNOS_5250_HOSTPHYCTRL0_COMMON_ON_N;
 262                writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
 263                udelay(10);
 264                ctrl0 &=        ~(EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST |
 265                                EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST);
 266                writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
 267
 268                /* OTG configuration */
 269                otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS);
 270                /* The clock */
 271                otg &= ~EXYNOS_5250_USBOTGSYS_FSEL_MASK;
 272                otg |= drv->ref_reg_val << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT;
 273                /* Reset */
 274                otg &= ~(EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND |
 275                        EXYNOS_5250_USBOTGSYS_FORCE_SLEEP |
 276                        EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG);
 277                otg |=  EXYNOS_5250_USBOTGSYS_PHY_SW_RST |
 278                        EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET |
 279                        EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |
 280                        EXYNOS_5250_USBOTGSYS_OTGDISABLE;
 281                /* Ref clock */
 282                otg &=  ~EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK;
 283                otg |=  EXYNOS_5250_REFCLKSEL_CLKCORE <<
 284                                        EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT;
 285                writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);
 286                udelay(10);
 287                otg &= ~(EXYNOS_5250_USBOTGSYS_PHY_SW_RST |
 288                        EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |
 289                        EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET);
 290
 291                /* HSIC phy configuration */
 292                hsic = (EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12 |
 293                                EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT |
 294                                EXYNOS_5250_HSICPHYCTRLX_PHYSWRST);
 295                writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1);
 296                writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2);
 297                udelay(10);
 298                hsic &= ~EXYNOS_5250_HSICPHYCTRLX_PHYSWRST;
 299                writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1);
 300                writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2);
 301                /* The following delay is necessary for the reset sequence to be
 302                 * completed */
 303                udelay(80);
 304
 305                /* Enable EHCI DMA burst */
 306                ehci = readl(drv->reg_phy + EXYNOS_5250_HOSTEHCICTRL);
 307                ehci |= EXYNOS_5250_HOSTEHCICTRL_ENAINCRXALIGN |
 308                        EXYNOS_5250_HOSTEHCICTRL_ENAINCR4 |
 309                        EXYNOS_5250_HOSTEHCICTRL_ENAINCR8 |
 310                        EXYNOS_5250_HOSTEHCICTRL_ENAINCR16;
 311                writel(ehci, drv->reg_phy + EXYNOS_5250_HOSTEHCICTRL);
 312
 313                /* OHCI settings */
 314                ohci = readl(drv->reg_phy + EXYNOS_5250_HOSTOHCICTRL);
 315                /* Following code is based on the old driver */
 316                ohci |= 0x1 << 3;
 317                writel(ohci, drv->reg_phy + EXYNOS_5250_HOSTOHCICTRL);
 318
 319                break;
 320        }
 321        exynos5250_isol(inst, 0);
 322
 323        return 0;
 324}
 325
 326static int exynos5250_power_off(struct samsung_usb2_phy_instance *inst)
 327{
 328        struct samsung_usb2_phy_driver *drv = inst->drv;
 329        u32 ctrl0;
 330        u32 otg;
 331        u32 hsic;
 332
 333        exynos5250_isol(inst, 1);
 334
 335        switch (inst->cfg->id) {
 336        case EXYNOS5250_DEVICE:
 337                otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS);
 338                otg |= (EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND |
 339                        EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG |
 340                        EXYNOS_5250_USBOTGSYS_FORCE_SLEEP);
 341                writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);
 342                break;
 343        case EXYNOS5250_HOST:
 344                ctrl0 = readl(drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
 345                ctrl0 |= (EXYNOS_5250_HOSTPHYCTRL0_SIDDQ |
 346                                EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND |
 347                                EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP |
 348                                EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST |
 349                                EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL);
 350                writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
 351                break;
 352        case EXYNOS5250_HSIC0:
 353        case EXYNOS5250_HSIC1:
 354                hsic = (EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12 |
 355                                EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT |
 356                                EXYNOS_5250_HSICPHYCTRLX_SIDDQ |
 357                                EXYNOS_5250_HSICPHYCTRLX_FORCESLEEP |
 358                                EXYNOS_5250_HSICPHYCTRLX_FORCESUSPEND
 359                                );
 360                writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1);
 361                writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2);
 362                break;
 363        }
 364
 365        return 0;
 366}
 367
 368
 369static const struct samsung_usb2_common_phy exynos5250_phys[] = {
 370        {
 371                .label          = "device",
 372                .id             = EXYNOS5250_DEVICE,
 373                .power_on       = exynos5250_power_on,
 374                .power_off      = exynos5250_power_off,
 375        },
 376        {
 377                .label          = "host",
 378                .id             = EXYNOS5250_HOST,
 379                .power_on       = exynos5250_power_on,
 380                .power_off      = exynos5250_power_off,
 381        },
 382        {
 383                .label          = "hsic0",
 384                .id             = EXYNOS5250_HSIC0,
 385                .power_on       = exynos5250_power_on,
 386                .power_off      = exynos5250_power_off,
 387        },
 388        {
 389                .label          = "hsic1",
 390                .id             = EXYNOS5250_HSIC1,
 391                .power_on       = exynos5250_power_on,
 392                .power_off      = exynos5250_power_off,
 393        },
 394};
 395
 396const struct samsung_usb2_phy_config exynos5250_usb2_phy_config = {
 397        .has_mode_switch        = 1,
 398        .num_phys               = EXYNOS5250_NUM_PHYS,
 399        .phys                   = exynos5250_phys,
 400        .rate_to_clk            = exynos5250_rate_to_clk,
 401};
 402