0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/clk.h>
0012 #include <linux/delay.h>
0013 #include <linux/io.h>
0014 #include <linux/kernel.h>
0015 #include <linux/module.h>
0016 #include <linux/of.h>
0017 #include <linux/of_address.h>
0018 #include <linux/of_device.h>
0019 #include <linux/iopoll.h>
0020 #include <linux/phy/phy.h>
0021 #include <linux/platform_device.h>
0022 #include <linux/mutex.h>
0023 #include <linux/mfd/syscon.h>
0024 #include <linux/regmap.h>
0025 #include <linux/regulator/consumer.h>
0026 #include <linux/soc/samsung/exynos-regs-pmu.h>
0027
0028
0029 #define EXYNOS5_FSEL_9MHZ6 0x0
0030 #define EXYNOS5_FSEL_10MHZ 0x1
0031 #define EXYNOS5_FSEL_12MHZ 0x2
0032 #define EXYNOS5_FSEL_19MHZ2 0x3
0033 #define EXYNOS5_FSEL_20MHZ 0x4
0034 #define EXYNOS5_FSEL_24MHZ 0x5
0035 #define EXYNOS5_FSEL_50MHZ 0x7
0036
0037
0038 #define EXYNOS5_DRD_LINKSYSTEM 0x04
0039
0040 #define LINKSYSTEM_FLADJ_MASK (0x3f << 1)
0041 #define LINKSYSTEM_FLADJ(_x) ((_x) << 1)
0042 #define LINKSYSTEM_XHCI_VERSION_CONTROL BIT(27)
0043
0044 #define EXYNOS5_DRD_PHYUTMI 0x08
0045
0046 #define PHYUTMI_OTGDISABLE BIT(6)
0047 #define PHYUTMI_FORCESUSPEND BIT(1)
0048 #define PHYUTMI_FORCESLEEP BIT(0)
0049
0050 #define EXYNOS5_DRD_PHYPIPE 0x0c
0051
0052 #define EXYNOS5_DRD_PHYCLKRST 0x10
0053
0054 #define PHYCLKRST_EN_UTMISUSPEND BIT(31)
0055
0056 #define PHYCLKRST_SSC_REFCLKSEL_MASK (0xff << 23)
0057 #define PHYCLKRST_SSC_REFCLKSEL(_x) ((_x) << 23)
0058
0059 #define PHYCLKRST_SSC_RANGE_MASK (0x03 << 21)
0060 #define PHYCLKRST_SSC_RANGE(_x) ((_x) << 21)
0061
0062 #define PHYCLKRST_SSC_EN BIT(20)
0063 #define PHYCLKRST_REF_SSP_EN BIT(19)
0064 #define PHYCLKRST_REF_CLKDIV2 BIT(18)
0065
0066 #define PHYCLKRST_MPLL_MULTIPLIER_MASK (0x7f << 11)
0067 #define PHYCLKRST_MPLL_MULTIPLIER_100MHZ_REF (0x19 << 11)
0068 #define PHYCLKRST_MPLL_MULTIPLIER_50M_REF (0x32 << 11)
0069 #define PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF (0x68 << 11)
0070 #define PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF (0x7d << 11)
0071 #define PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF (0x02 << 11)
0072
0073 #define PHYCLKRST_FSEL_UTMI_MASK (0x7 << 5)
0074 #define PHYCLKRST_FSEL_PIPE_MASK (0x7 << 8)
0075 #define PHYCLKRST_FSEL(_x) ((_x) << 5)
0076 #define PHYCLKRST_FSEL_PAD_100MHZ (0x27 << 5)
0077 #define PHYCLKRST_FSEL_PAD_24MHZ (0x2a << 5)
0078 #define PHYCLKRST_FSEL_PAD_20MHZ (0x31 << 5)
0079 #define PHYCLKRST_FSEL_PAD_19_2MHZ (0x38 << 5)
0080
0081 #define PHYCLKRST_RETENABLEN BIT(4)
0082
0083 #define PHYCLKRST_REFCLKSEL_MASK (0x03 << 2)
0084 #define PHYCLKRST_REFCLKSEL_PAD_REFCLK (0x2 << 2)
0085 #define PHYCLKRST_REFCLKSEL_EXT_REFCLK (0x3 << 2)
0086
0087 #define PHYCLKRST_PORTRESET BIT(1)
0088 #define PHYCLKRST_COMMONONN BIT(0)
0089
0090 #define EXYNOS5_DRD_PHYREG0 0x14
0091 #define PHYREG0_SSC_REF_CLK_SEL BIT(21)
0092 #define PHYREG0_SSC_RANGE BIT(20)
0093 #define PHYREG0_CR_WRITE BIT(19)
0094 #define PHYREG0_CR_READ BIT(18)
0095 #define PHYREG0_CR_DATA_IN(_x) ((_x) << 2)
0096 #define PHYREG0_CR_CAP_DATA BIT(1)
0097 #define PHYREG0_CR_CAP_ADDR BIT(0)
0098
0099 #define EXYNOS5_DRD_PHYREG1 0x18
0100 #define PHYREG1_CR_DATA_OUT(_x) ((_x) << 1)
0101 #define PHYREG1_CR_ACK BIT(0)
0102
0103 #define EXYNOS5_DRD_PHYPARAM0 0x1c
0104
0105 #define PHYPARAM0_REF_USE_PAD BIT(31)
0106 #define PHYPARAM0_REF_LOSLEVEL_MASK (0x1f << 26)
0107 #define PHYPARAM0_REF_LOSLEVEL (0x9 << 26)
0108
0109 #define EXYNOS5_DRD_PHYPARAM1 0x20
0110
0111 #define PHYPARAM1_PCS_TXDEEMPH_MASK (0x1f << 0)
0112 #define PHYPARAM1_PCS_TXDEEMPH (0x1c)
0113
0114 #define EXYNOS5_DRD_PHYTERM 0x24
0115
0116 #define EXYNOS5_DRD_PHYTEST 0x28
0117
0118 #define PHYTEST_POWERDOWN_SSP BIT(3)
0119 #define PHYTEST_POWERDOWN_HSP BIT(2)
0120
0121 #define EXYNOS5_DRD_PHYADP 0x2c
0122
0123 #define EXYNOS5_DRD_PHYUTMICLKSEL 0x30
0124
0125 #define PHYUTMICLKSEL_UTMI_CLKSEL BIT(2)
0126
0127 #define EXYNOS5_DRD_PHYRESUME 0x34
0128 #define EXYNOS5_DRD_LINKPORT 0x44
0129
0130
0131 #define EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN (0x15)
0132 #define LOSLEVEL_OVRD_IN_LOS_BIAS_5420 (0x5 << 13)
0133 #define LOSLEVEL_OVRD_IN_LOS_BIAS_DEFAULT (0x0 << 13)
0134 #define LOSLEVEL_OVRD_IN_EN (0x1 << 10)
0135 #define LOSLEVEL_OVRD_IN_LOS_LEVEL_DEFAULT (0x9 << 0)
0136
0137 #define EXYNOS5_DRD_PHYSS_TX_VBOOSTLEVEL_OVRD_IN (0x12)
0138 #define TX_VBOOSTLEVEL_OVRD_IN_VBOOST_5420 (0x5 << 13)
0139 #define TX_VBOOSTLEVEL_OVRD_IN_VBOOST_DEFAULT (0x4 << 13)
0140
0141 #define EXYNOS5_DRD_PHYSS_LANE0_TX_DEBUG (0x1010)
0142 #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_19M2_20M (0x4 << 4)
0143 #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_24M (0x8 << 4)
0144 #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_25M_26M (0x8 << 4)
0145 #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_48M_50M_52M (0x20 << 4)
0146 #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_62M5 (0x20 << 4)
0147 #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_96M_100M (0x40 << 4)
0148
0149 #define KHZ 1000
0150 #define MHZ (KHZ * KHZ)
0151
0152 enum exynos5_usbdrd_phy_id {
0153 EXYNOS5_DRDPHY_UTMI,
0154 EXYNOS5_DRDPHY_PIPE3,
0155 EXYNOS5_DRDPHYS_NUM,
0156 };
0157
0158 struct phy_usb_instance;
0159 struct exynos5_usbdrd_phy;
0160
0161 struct exynos5_usbdrd_phy_config {
0162 u32 id;
0163 void (*phy_isol)(struct phy_usb_instance *inst, u32 on);
0164 void (*phy_init)(struct exynos5_usbdrd_phy *phy_drd);
0165 unsigned int (*set_refclk)(struct phy_usb_instance *inst);
0166 };
0167
0168 struct exynos5_usbdrd_phy_drvdata {
0169 const struct exynos5_usbdrd_phy_config *phy_cfg;
0170 u32 pmu_offset_usbdrd0_phy;
0171 u32 pmu_offset_usbdrd1_phy;
0172 bool has_common_clk_gate;
0173 };
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193 struct exynos5_usbdrd_phy {
0194 struct device *dev;
0195 void __iomem *reg_phy;
0196 struct clk *clk;
0197 struct clk *pipeclk;
0198 struct clk *utmiclk;
0199 struct clk *itpclk;
0200 const struct exynos5_usbdrd_phy_drvdata *drv_data;
0201 struct phy_usb_instance {
0202 struct phy *phy;
0203 u32 index;
0204 struct regmap *reg_pmu;
0205 u32 pmu_offset;
0206 const struct exynos5_usbdrd_phy_config *phy_cfg;
0207 } phys[EXYNOS5_DRDPHYS_NUM];
0208 u32 extrefclk;
0209 struct clk *ref_clk;
0210 struct regulator *vbus;
0211 struct regulator *vbus_boost;
0212 };
0213
0214 static inline
0215 struct exynos5_usbdrd_phy *to_usbdrd_phy(struct phy_usb_instance *inst)
0216 {
0217 return container_of((inst), struct exynos5_usbdrd_phy,
0218 phys[(inst)->index]);
0219 }
0220
0221
0222
0223
0224
0225 static unsigned int exynos5_rate_to_clk(unsigned long rate, u32 *reg)
0226 {
0227
0228
0229 switch (rate) {
0230 case 9600 * KHZ:
0231 *reg = EXYNOS5_FSEL_9MHZ6;
0232 break;
0233 case 10 * MHZ:
0234 *reg = EXYNOS5_FSEL_10MHZ;
0235 break;
0236 case 12 * MHZ:
0237 *reg = EXYNOS5_FSEL_12MHZ;
0238 break;
0239 case 19200 * KHZ:
0240 *reg = EXYNOS5_FSEL_19MHZ2;
0241 break;
0242 case 20 * MHZ:
0243 *reg = EXYNOS5_FSEL_20MHZ;
0244 break;
0245 case 24 * MHZ:
0246 *reg = EXYNOS5_FSEL_24MHZ;
0247 break;
0248 case 50 * MHZ:
0249 *reg = EXYNOS5_FSEL_50MHZ;
0250 break;
0251 default:
0252 return -EINVAL;
0253 }
0254
0255 return 0;
0256 }
0257
0258 static void exynos5_usbdrd_phy_isol(struct phy_usb_instance *inst,
0259 unsigned int on)
0260 {
0261 unsigned int val;
0262
0263 if (!inst->reg_pmu)
0264 return;
0265
0266 val = on ? 0 : EXYNOS4_PHY_ENABLE;
0267
0268 regmap_update_bits(inst->reg_pmu, inst->pmu_offset,
0269 EXYNOS4_PHY_ENABLE, val);
0270 }
0271
0272
0273
0274
0275
0276
0277 static unsigned int
0278 exynos5_usbdrd_pipe3_set_refclk(struct phy_usb_instance *inst)
0279 {
0280 u32 reg;
0281 struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
0282
0283
0284 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
0285
0286
0287 reg &= ~PHYCLKRST_REFCLKSEL_MASK;
0288 reg |= PHYCLKRST_REFCLKSEL_EXT_REFCLK;
0289
0290
0291 reg &= ~PHYCLKRST_FSEL_PIPE_MASK |
0292 PHYCLKRST_MPLL_MULTIPLIER_MASK |
0293 PHYCLKRST_SSC_REFCLKSEL_MASK;
0294 switch (phy_drd->extrefclk) {
0295 case EXYNOS5_FSEL_50MHZ:
0296 reg |= (PHYCLKRST_MPLL_MULTIPLIER_50M_REF |
0297 PHYCLKRST_SSC_REFCLKSEL(0x00));
0298 break;
0299 case EXYNOS5_FSEL_24MHZ:
0300 reg |= (PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF |
0301 PHYCLKRST_SSC_REFCLKSEL(0x88));
0302 break;
0303 case EXYNOS5_FSEL_20MHZ:
0304 reg |= (PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF |
0305 PHYCLKRST_SSC_REFCLKSEL(0x00));
0306 break;
0307 case EXYNOS5_FSEL_19MHZ2:
0308 reg |= (PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF |
0309 PHYCLKRST_SSC_REFCLKSEL(0x88));
0310 break;
0311 default:
0312 dev_dbg(phy_drd->dev, "unsupported ref clk\n");
0313 break;
0314 }
0315
0316 return reg;
0317 }
0318
0319
0320
0321
0322
0323 static unsigned int
0324 exynos5_usbdrd_utmi_set_refclk(struct phy_usb_instance *inst)
0325 {
0326 u32 reg;
0327 struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
0328
0329
0330 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
0331
0332 reg &= ~PHYCLKRST_REFCLKSEL_MASK;
0333 reg |= PHYCLKRST_REFCLKSEL_EXT_REFCLK;
0334
0335 reg &= ~PHYCLKRST_FSEL_UTMI_MASK |
0336 PHYCLKRST_MPLL_MULTIPLIER_MASK |
0337 PHYCLKRST_SSC_REFCLKSEL_MASK;
0338 reg |= PHYCLKRST_FSEL(phy_drd->extrefclk);
0339
0340 return reg;
0341 }
0342
0343 static void exynos5_usbdrd_pipe3_init(struct exynos5_usbdrd_phy *phy_drd)
0344 {
0345 u32 reg;
0346
0347 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
0348
0349 reg &= ~PHYPARAM1_PCS_TXDEEMPH_MASK;
0350 reg |= PHYPARAM1_PCS_TXDEEMPH;
0351 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
0352
0353 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
0354 reg &= ~PHYTEST_POWERDOWN_SSP;
0355 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
0356 }
0357
0358 static void exynos5_usbdrd_utmi_init(struct exynos5_usbdrd_phy *phy_drd)
0359 {
0360 u32 reg;
0361
0362 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
0363
0364 reg &= ~PHYPARAM0_REF_LOSLEVEL_MASK;
0365 reg |= PHYPARAM0_REF_LOSLEVEL;
0366 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
0367
0368 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
0369
0370 reg &= ~PHYPARAM1_PCS_TXDEEMPH_MASK;
0371 reg |= PHYPARAM1_PCS_TXDEEMPH;
0372 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
0373
0374
0375 writel(PHYUTMI_OTGDISABLE, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMI);
0376
0377 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
0378 reg &= ~PHYTEST_POWERDOWN_HSP;
0379 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
0380 }
0381
0382 static int exynos5_usbdrd_phy_init(struct phy *phy)
0383 {
0384 int ret;
0385 u32 reg;
0386 struct phy_usb_instance *inst = phy_get_drvdata(phy);
0387 struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
0388
0389 ret = clk_prepare_enable(phy_drd->clk);
0390 if (ret)
0391 return ret;
0392
0393
0394 writel(0x0, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
0395 writel(0x0, phy_drd->reg_phy + EXYNOS5_DRD_PHYRESUME);
0396
0397
0398
0399
0400
0401 reg = LINKSYSTEM_XHCI_VERSION_CONTROL |
0402 LINKSYSTEM_FLADJ(0x20);
0403 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_LINKSYSTEM);
0404
0405 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
0406
0407 reg &= ~PHYPARAM0_REF_USE_PAD;
0408 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
0409
0410
0411 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMICLKSEL);
0412 reg |= PHYUTMICLKSEL_UTMI_CLKSEL;
0413 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMICLKSEL);
0414
0415
0416 inst->phy_cfg->phy_init(phy_drd);
0417
0418
0419 reg = inst->phy_cfg->set_refclk(inst);
0420
0421
0422 reg |= PHYCLKRST_RETENABLEN |
0423
0424 PHYCLKRST_REF_SSP_EN |
0425
0426 PHYCLKRST_SSC_EN |
0427
0428 PHYCLKRST_COMMONONN |
0429
0430 PHYCLKRST_PORTRESET;
0431
0432 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
0433
0434 udelay(10);
0435
0436 reg &= ~PHYCLKRST_PORTRESET;
0437 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
0438
0439 clk_disable_unprepare(phy_drd->clk);
0440
0441 return 0;
0442 }
0443
0444 static int exynos5_usbdrd_phy_exit(struct phy *phy)
0445 {
0446 int ret;
0447 u32 reg;
0448 struct phy_usb_instance *inst = phy_get_drvdata(phy);
0449 struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
0450
0451 ret = clk_prepare_enable(phy_drd->clk);
0452 if (ret)
0453 return ret;
0454
0455 reg = PHYUTMI_OTGDISABLE |
0456 PHYUTMI_FORCESUSPEND |
0457 PHYUTMI_FORCESLEEP;
0458 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMI);
0459
0460
0461 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
0462 reg &= ~(PHYCLKRST_REF_SSP_EN |
0463 PHYCLKRST_SSC_EN |
0464 PHYCLKRST_COMMONONN);
0465 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
0466
0467
0468 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
0469 reg |= PHYTEST_POWERDOWN_SSP |
0470 PHYTEST_POWERDOWN_HSP;
0471 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
0472
0473 clk_disable_unprepare(phy_drd->clk);
0474
0475 return 0;
0476 }
0477
0478 static int exynos5_usbdrd_phy_power_on(struct phy *phy)
0479 {
0480 int ret;
0481 struct phy_usb_instance *inst = phy_get_drvdata(phy);
0482 struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
0483
0484 dev_dbg(phy_drd->dev, "Request to power_on usbdrd_phy phy\n");
0485
0486 clk_prepare_enable(phy_drd->ref_clk);
0487 if (!phy_drd->drv_data->has_common_clk_gate) {
0488 clk_prepare_enable(phy_drd->pipeclk);
0489 clk_prepare_enable(phy_drd->utmiclk);
0490 clk_prepare_enable(phy_drd->itpclk);
0491 }
0492
0493
0494 if (phy_drd->vbus_boost) {
0495 ret = regulator_enable(phy_drd->vbus_boost);
0496 if (ret) {
0497 dev_err(phy_drd->dev,
0498 "Failed to enable VBUS boost supply\n");
0499 goto fail_vbus;
0500 }
0501 }
0502
0503 if (phy_drd->vbus) {
0504 ret = regulator_enable(phy_drd->vbus);
0505 if (ret) {
0506 dev_err(phy_drd->dev, "Failed to enable VBUS supply\n");
0507 goto fail_vbus_boost;
0508 }
0509 }
0510
0511
0512 inst->phy_cfg->phy_isol(inst, 0);
0513
0514 return 0;
0515
0516 fail_vbus_boost:
0517 if (phy_drd->vbus_boost)
0518 regulator_disable(phy_drd->vbus_boost);
0519
0520 fail_vbus:
0521 clk_disable_unprepare(phy_drd->ref_clk);
0522 if (!phy_drd->drv_data->has_common_clk_gate) {
0523 clk_disable_unprepare(phy_drd->itpclk);
0524 clk_disable_unprepare(phy_drd->utmiclk);
0525 clk_disable_unprepare(phy_drd->pipeclk);
0526 }
0527
0528 return ret;
0529 }
0530
0531 static int exynos5_usbdrd_phy_power_off(struct phy *phy)
0532 {
0533 struct phy_usb_instance *inst = phy_get_drvdata(phy);
0534 struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
0535
0536 dev_dbg(phy_drd->dev, "Request to power_off usbdrd_phy phy\n");
0537
0538
0539 inst->phy_cfg->phy_isol(inst, 1);
0540
0541
0542 if (phy_drd->vbus)
0543 regulator_disable(phy_drd->vbus);
0544 if (phy_drd->vbus_boost)
0545 regulator_disable(phy_drd->vbus_boost);
0546
0547 clk_disable_unprepare(phy_drd->ref_clk);
0548 if (!phy_drd->drv_data->has_common_clk_gate) {
0549 clk_disable_unprepare(phy_drd->itpclk);
0550 clk_disable_unprepare(phy_drd->pipeclk);
0551 clk_disable_unprepare(phy_drd->utmiclk);
0552 }
0553
0554 return 0;
0555 }
0556
0557 static int crport_handshake(struct exynos5_usbdrd_phy *phy_drd,
0558 u32 val, u32 cmd)
0559 {
0560 unsigned int result;
0561 int err;
0562
0563 writel(val | cmd, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
0564
0565 err = readl_poll_timeout(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1,
0566 result, (result & PHYREG1_CR_ACK), 1, 100);
0567 if (err == -ETIMEDOUT) {
0568 dev_err(phy_drd->dev, "CRPORT handshake timeout1 (0x%08x)\n", val);
0569 return err;
0570 }
0571
0572 writel(val, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
0573
0574 err = readl_poll_timeout(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1,
0575 result, !(result & PHYREG1_CR_ACK), 1, 100);
0576 if (err == -ETIMEDOUT) {
0577 dev_err(phy_drd->dev, "CRPORT handshake timeout2 (0x%08x)\n", val);
0578 return err;
0579 }
0580
0581 return 0;
0582 }
0583
0584 static int crport_ctrl_write(struct exynos5_usbdrd_phy *phy_drd,
0585 u32 addr, u32 data)
0586 {
0587 int ret;
0588
0589
0590 writel(PHYREG0_CR_DATA_IN(addr),
0591 phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
0592 ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(addr),
0593 PHYREG0_CR_CAP_ADDR);
0594 if (ret)
0595 return ret;
0596
0597
0598 writel(PHYREG0_CR_DATA_IN(data),
0599 phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
0600 ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(data),
0601 PHYREG0_CR_CAP_DATA);
0602 if (ret)
0603 return ret;
0604
0605 ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(data),
0606 PHYREG0_CR_WRITE);
0607
0608 return ret;
0609 }
0610
0611
0612
0613
0614
0615
0616 static int exynos5420_usbdrd_phy_calibrate(struct exynos5_usbdrd_phy *phy_drd)
0617 {
0618 unsigned int temp;
0619 int ret = 0;
0620
0621
0622
0623
0624
0625
0626
0627 temp = LOSLEVEL_OVRD_IN_LOS_BIAS_5420 |
0628 LOSLEVEL_OVRD_IN_EN |
0629 LOSLEVEL_OVRD_IN_LOS_LEVEL_DEFAULT;
0630 ret = crport_ctrl_write(phy_drd,
0631 EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN,
0632 temp);
0633 if (ret) {
0634 dev_err(phy_drd->dev,
0635 "Failed setting Loss-of-Signal level for SuperSpeed\n");
0636 return ret;
0637 }
0638
0639
0640
0641
0642
0643 temp = TX_VBOOSTLEVEL_OVRD_IN_VBOOST_5420;
0644 ret = crport_ctrl_write(phy_drd,
0645 EXYNOS5_DRD_PHYSS_TX_VBOOSTLEVEL_OVRD_IN,
0646 temp);
0647 if (ret) {
0648 dev_err(phy_drd->dev,
0649 "Failed setting Tx-Vboost-Level for SuperSpeed\n");
0650 return ret;
0651 }
0652
0653
0654
0655
0656
0657
0658
0659
0660
0661
0662 switch (phy_drd->extrefclk) {
0663 case EXYNOS5_FSEL_50MHZ:
0664 temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_48M_50M_52M;
0665 break;
0666 case EXYNOS5_FSEL_20MHZ:
0667 case EXYNOS5_FSEL_19MHZ2:
0668 temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_19M2_20M;
0669 break;
0670 case EXYNOS5_FSEL_24MHZ:
0671 default:
0672 temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_24M;
0673 break;
0674 }
0675
0676 ret = crport_ctrl_write(phy_drd,
0677 EXYNOS5_DRD_PHYSS_LANE0_TX_DEBUG,
0678 temp);
0679 if (ret)
0680 dev_err(phy_drd->dev,
0681 "Fail to set RxDet measurement time for SuperSpeed\n");
0682
0683 return ret;
0684 }
0685
0686 static struct phy *exynos5_usbdrd_phy_xlate(struct device *dev,
0687 struct of_phandle_args *args)
0688 {
0689 struct exynos5_usbdrd_phy *phy_drd = dev_get_drvdata(dev);
0690
0691 if (WARN_ON(args->args[0] >= EXYNOS5_DRDPHYS_NUM))
0692 return ERR_PTR(-ENODEV);
0693
0694 return phy_drd->phys[args->args[0]].phy;
0695 }
0696
0697 static int exynos5_usbdrd_phy_calibrate(struct phy *phy)
0698 {
0699 struct phy_usb_instance *inst = phy_get_drvdata(phy);
0700 struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
0701
0702 if (inst->phy_cfg->id == EXYNOS5_DRDPHY_UTMI)
0703 return exynos5420_usbdrd_phy_calibrate(phy_drd);
0704 return 0;
0705 }
0706
0707 static const struct phy_ops exynos5_usbdrd_phy_ops = {
0708 .init = exynos5_usbdrd_phy_init,
0709 .exit = exynos5_usbdrd_phy_exit,
0710 .power_on = exynos5_usbdrd_phy_power_on,
0711 .power_off = exynos5_usbdrd_phy_power_off,
0712 .calibrate = exynos5_usbdrd_phy_calibrate,
0713 .owner = THIS_MODULE,
0714 };
0715
0716 static int exynos5_usbdrd_phy_clk_handle(struct exynos5_usbdrd_phy *phy_drd)
0717 {
0718 unsigned long ref_rate;
0719 int ret;
0720
0721 phy_drd->clk = devm_clk_get(phy_drd->dev, "phy");
0722 if (IS_ERR(phy_drd->clk)) {
0723 dev_err(phy_drd->dev, "Failed to get phy clock\n");
0724 return PTR_ERR(phy_drd->clk);
0725 }
0726
0727 phy_drd->ref_clk = devm_clk_get(phy_drd->dev, "ref");
0728 if (IS_ERR(phy_drd->ref_clk)) {
0729 dev_err(phy_drd->dev, "Failed to get phy reference clock\n");
0730 return PTR_ERR(phy_drd->ref_clk);
0731 }
0732 ref_rate = clk_get_rate(phy_drd->ref_clk);
0733
0734 ret = exynos5_rate_to_clk(ref_rate, &phy_drd->extrefclk);
0735 if (ret) {
0736 dev_err(phy_drd->dev, "Clock rate (%ld) not supported\n",
0737 ref_rate);
0738 return ret;
0739 }
0740
0741 if (!phy_drd->drv_data->has_common_clk_gate) {
0742 phy_drd->pipeclk = devm_clk_get(phy_drd->dev, "phy_pipe");
0743 if (IS_ERR(phy_drd->pipeclk)) {
0744 dev_info(phy_drd->dev,
0745 "PIPE3 phy operational clock not specified\n");
0746 phy_drd->pipeclk = NULL;
0747 }
0748
0749 phy_drd->utmiclk = devm_clk_get(phy_drd->dev, "phy_utmi");
0750 if (IS_ERR(phy_drd->utmiclk)) {
0751 dev_info(phy_drd->dev,
0752 "UTMI phy operational clock not specified\n");
0753 phy_drd->utmiclk = NULL;
0754 }
0755
0756 phy_drd->itpclk = devm_clk_get(phy_drd->dev, "itp");
0757 if (IS_ERR(phy_drd->itpclk)) {
0758 dev_info(phy_drd->dev,
0759 "ITP clock from main OSC not specified\n");
0760 phy_drd->itpclk = NULL;
0761 }
0762 }
0763
0764 return 0;
0765 }
0766
0767 static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
0768 {
0769 .id = EXYNOS5_DRDPHY_UTMI,
0770 .phy_isol = exynos5_usbdrd_phy_isol,
0771 .phy_init = exynos5_usbdrd_utmi_init,
0772 .set_refclk = exynos5_usbdrd_utmi_set_refclk,
0773 },
0774 {
0775 .id = EXYNOS5_DRDPHY_PIPE3,
0776 .phy_isol = exynos5_usbdrd_phy_isol,
0777 .phy_init = exynos5_usbdrd_pipe3_init,
0778 .set_refclk = exynos5_usbdrd_pipe3_set_refclk,
0779 },
0780 };
0781
0782 static const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = {
0783 .phy_cfg = phy_cfg_exynos5,
0784 .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
0785 .pmu_offset_usbdrd1_phy = EXYNOS5420_USBDRD1_PHY_CONTROL,
0786 .has_common_clk_gate = true,
0787 };
0788
0789 static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = {
0790 .phy_cfg = phy_cfg_exynos5,
0791 .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
0792 .has_common_clk_gate = true,
0793 };
0794
0795 static const struct exynos5_usbdrd_phy_drvdata exynos5433_usbdrd_phy = {
0796 .phy_cfg = phy_cfg_exynos5,
0797 .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
0798 .pmu_offset_usbdrd1_phy = EXYNOS5433_USBHOST30_PHY_CONTROL,
0799 .has_common_clk_gate = false,
0800 };
0801
0802 static const struct exynos5_usbdrd_phy_drvdata exynos7_usbdrd_phy = {
0803 .phy_cfg = phy_cfg_exynos5,
0804 .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
0805 .has_common_clk_gate = false,
0806 };
0807
0808 static const struct of_device_id exynos5_usbdrd_phy_of_match[] = {
0809 {
0810 .compatible = "samsung,exynos5250-usbdrd-phy",
0811 .data = &exynos5250_usbdrd_phy
0812 }, {
0813 .compatible = "samsung,exynos5420-usbdrd-phy",
0814 .data = &exynos5420_usbdrd_phy
0815 }, {
0816 .compatible = "samsung,exynos5433-usbdrd-phy",
0817 .data = &exynos5433_usbdrd_phy
0818 }, {
0819 .compatible = "samsung,exynos7-usbdrd-phy",
0820 .data = &exynos7_usbdrd_phy
0821 },
0822 { },
0823 };
0824 MODULE_DEVICE_TABLE(of, exynos5_usbdrd_phy_of_match);
0825
0826 static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
0827 {
0828 struct device *dev = &pdev->dev;
0829 struct device_node *node = dev->of_node;
0830 struct exynos5_usbdrd_phy *phy_drd;
0831 struct phy_provider *phy_provider;
0832 const struct exynos5_usbdrd_phy_drvdata *drv_data;
0833 struct regmap *reg_pmu;
0834 u32 pmu_offset;
0835 int i, ret;
0836 int channel;
0837
0838 phy_drd = devm_kzalloc(dev, sizeof(*phy_drd), GFP_KERNEL);
0839 if (!phy_drd)
0840 return -ENOMEM;
0841
0842 dev_set_drvdata(dev, phy_drd);
0843 phy_drd->dev = dev;
0844
0845 phy_drd->reg_phy = devm_platform_ioremap_resource(pdev, 0);
0846 if (IS_ERR(phy_drd->reg_phy))
0847 return PTR_ERR(phy_drd->reg_phy);
0848
0849 drv_data = of_device_get_match_data(dev);
0850 if (!drv_data)
0851 return -EINVAL;
0852
0853 phy_drd->drv_data = drv_data;
0854
0855 ret = exynos5_usbdrd_phy_clk_handle(phy_drd);
0856 if (ret) {
0857 dev_err(dev, "Failed to initialize clocks\n");
0858 return ret;
0859 }
0860
0861 reg_pmu = syscon_regmap_lookup_by_phandle(dev->of_node,
0862 "samsung,pmu-syscon");
0863 if (IS_ERR(reg_pmu)) {
0864 dev_err(dev, "Failed to lookup PMU regmap\n");
0865 return PTR_ERR(reg_pmu);
0866 }
0867
0868
0869
0870
0871
0872
0873 channel = of_alias_get_id(node, "usbdrdphy");
0874 if (channel < 0)
0875 dev_dbg(dev, "Not a multi-controller usbdrd phy\n");
0876
0877 switch (channel) {
0878 case 1:
0879 pmu_offset = phy_drd->drv_data->pmu_offset_usbdrd1_phy;
0880 break;
0881 case 0:
0882 default:
0883 pmu_offset = phy_drd->drv_data->pmu_offset_usbdrd0_phy;
0884 break;
0885 }
0886
0887
0888 phy_drd->vbus = devm_regulator_get(dev, "vbus");
0889 if (IS_ERR(phy_drd->vbus)) {
0890 ret = PTR_ERR(phy_drd->vbus);
0891 if (ret == -EPROBE_DEFER)
0892 return ret;
0893
0894 dev_warn(dev, "Failed to get VBUS supply regulator\n");
0895 phy_drd->vbus = NULL;
0896 }
0897
0898 phy_drd->vbus_boost = devm_regulator_get(dev, "vbus-boost");
0899 if (IS_ERR(phy_drd->vbus_boost)) {
0900 ret = PTR_ERR(phy_drd->vbus_boost);
0901 if (ret == -EPROBE_DEFER)
0902 return ret;
0903
0904 dev_warn(dev, "Failed to get VBUS boost supply regulator\n");
0905 phy_drd->vbus_boost = NULL;
0906 }
0907
0908 dev_vdbg(dev, "Creating usbdrd_phy phy\n");
0909
0910 for (i = 0; i < EXYNOS5_DRDPHYS_NUM; i++) {
0911 struct phy *phy = devm_phy_create(dev, NULL,
0912 &exynos5_usbdrd_phy_ops);
0913 if (IS_ERR(phy)) {
0914 dev_err(dev, "Failed to create usbdrd_phy phy\n");
0915 return PTR_ERR(phy);
0916 }
0917
0918 phy_drd->phys[i].phy = phy;
0919 phy_drd->phys[i].index = i;
0920 phy_drd->phys[i].reg_pmu = reg_pmu;
0921 phy_drd->phys[i].pmu_offset = pmu_offset;
0922 phy_drd->phys[i].phy_cfg = &drv_data->phy_cfg[i];
0923 phy_set_drvdata(phy, &phy_drd->phys[i]);
0924 }
0925
0926 phy_provider = devm_of_phy_provider_register(dev,
0927 exynos5_usbdrd_phy_xlate);
0928 if (IS_ERR(phy_provider)) {
0929 dev_err(phy_drd->dev, "Failed to register phy provider\n");
0930 return PTR_ERR(phy_provider);
0931 }
0932
0933 return 0;
0934 }
0935
0936 static struct platform_driver exynos5_usb3drd_phy = {
0937 .probe = exynos5_usbdrd_phy_probe,
0938 .driver = {
0939 .of_match_table = exynos5_usbdrd_phy_of_match,
0940 .name = "exynos5_usb3drd_phy",
0941 .suppress_bind_attrs = true,
0942 }
0943 };
0944
0945 module_platform_driver(exynos5_usb3drd_phy);
0946 MODULE_DESCRIPTION("Samsung Exynos5 SoCs USB 3.0 DRD controller PHY driver");
0947 MODULE_AUTHOR("Vivek Gautam <gautam.vivek@samsung.com>");
0948 MODULE_LICENSE("GPL v2");
0949 MODULE_ALIAS("platform:exynos5_usb3drd_phy");