1 /* 2 * Samsung EXYNOS5 SoC series USB DRD PHY driver 3 * 4 * Phy provider for USB 3.0 DRD controller on Exynos5 SoC series 5 * 6 * Copyright (C) 2014 Samsung Electronics Co., Ltd. 7 * Author: Vivek Gautam <gautam.vivek@samsung.com> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 */ 13 14 #include <linux/clk.h> 15 #include <linux/delay.h> 16 #include <linux/io.h> 17 #include <linux/kernel.h> 18 #include <linux/module.h> 19 #include <linux/of.h> 20 #include <linux/of_address.h> 21 #include <linux/of_device.h> 22 #include <linux/phy/phy.h> 23 #include <linux/platform_device.h> 24 #include <linux/mutex.h> 25 #include <linux/mfd/syscon.h> 26 #include <linux/regmap.h> 27 #include <linux/regulator/consumer.h> 28 #include <linux/soc/samsung/exynos-regs-pmu.h> 29 30 /* Exynos USB PHY registers */ 31 #define EXYNOS5_FSEL_9MHZ6 0x0 32 #define EXYNOS5_FSEL_10MHZ 0x1 33 #define EXYNOS5_FSEL_12MHZ 0x2 34 #define EXYNOS5_FSEL_19MHZ2 0x3 35 #define EXYNOS5_FSEL_20MHZ 0x4 36 #define EXYNOS5_FSEL_24MHZ 0x5 37 #define EXYNOS5_FSEL_50MHZ 0x7 38 39 /* EXYNOS5: USB 3.0 DRD PHY registers */ 40 #define EXYNOS5_DRD_LINKSYSTEM 0x04 41 42 #define LINKSYSTEM_FLADJ_MASK (0x3f << 1) 43 #define LINKSYSTEM_FLADJ(_x) ((_x) << 1) 44 #define LINKSYSTEM_XHCI_VERSION_CONTROL BIT(27) 45 46 #define EXYNOS5_DRD_PHYUTMI 0x08 47 48 #define PHYUTMI_OTGDISABLE BIT(6) 49 #define PHYUTMI_FORCESUSPEND BIT(1) 50 #define PHYUTMI_FORCESLEEP BIT(0) 51 52 #define EXYNOS5_DRD_PHYPIPE 0x0c 53 54 #define EXYNOS5_DRD_PHYCLKRST 0x10 55 56 #define PHYCLKRST_EN_UTMISUSPEND BIT(31) 57 58 #define PHYCLKRST_SSC_REFCLKSEL_MASK (0xff << 23) 59 #define PHYCLKRST_SSC_REFCLKSEL(_x) ((_x) << 23) 60 61 #define PHYCLKRST_SSC_RANGE_MASK (0x03 << 21) 62 #define PHYCLKRST_SSC_RANGE(_x) ((_x) << 21) 63 64 #define PHYCLKRST_SSC_EN BIT(20) 65 #define PHYCLKRST_REF_SSP_EN BIT(19) 66 #define PHYCLKRST_REF_CLKDIV2 BIT(18) 67 68 #define PHYCLKRST_MPLL_MULTIPLIER_MASK (0x7f << 11) 69 #define PHYCLKRST_MPLL_MULTIPLIER_100MHZ_REF (0x19 << 11) 70 #define PHYCLKRST_MPLL_MULTIPLIER_50M_REF (0x32 << 11) 71 #define PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF (0x68 << 11) 72 #define PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF (0x7d << 11) 73 #define PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF (0x02 << 11) 74 75 #define PHYCLKRST_FSEL_UTMI_MASK (0x7 << 5) 76 #define PHYCLKRST_FSEL_PIPE_MASK (0x7 << 8) 77 #define PHYCLKRST_FSEL(_x) ((_x) << 5) 78 #define PHYCLKRST_FSEL_PAD_100MHZ (0x27 << 5) 79 #define PHYCLKRST_FSEL_PAD_24MHZ (0x2a << 5) 80 #define PHYCLKRST_FSEL_PAD_20MHZ (0x31 << 5) 81 #define PHYCLKRST_FSEL_PAD_19_2MHZ (0x38 << 5) 82 83 #define PHYCLKRST_RETENABLEN BIT(4) 84 85 #define PHYCLKRST_REFCLKSEL_MASK (0x03 << 2) 86 #define PHYCLKRST_REFCLKSEL_PAD_REFCLK (0x2 << 2) 87 #define PHYCLKRST_REFCLKSEL_EXT_REFCLK (0x3 << 2) 88 89 #define PHYCLKRST_PORTRESET BIT(1) 90 #define PHYCLKRST_COMMONONN BIT(0) 91 92 #define EXYNOS5_DRD_PHYREG0 0x14 93 #define PHYREG0_SSC_REF_CLK_SEL BIT(21) 94 #define PHYREG0_SSC_RANGE BIT(20) 95 #define PHYREG0_CR_WRITE BIT(19) 96 #define PHYREG0_CR_READ BIT(18) 97 #define PHYREG0_CR_DATA_IN(_x) ((_x) << 2) 98 #define PHYREG0_CR_CAP_DATA BIT(1) 99 #define PHYREG0_CR_CAP_ADDR BIT(0) 100 101 #define EXYNOS5_DRD_PHYREG1 0x18 102 #define PHYREG1_CR_DATA_OUT(_x) ((_x) << 1) 103 #define PHYREG1_CR_ACK BIT(0) 104 105 #define EXYNOS5_DRD_PHYPARAM0 0x1c 106 107 #define PHYPARAM0_REF_USE_PAD BIT(31) 108 #define PHYPARAM0_REF_LOSLEVEL_MASK (0x1f << 26) 109 #define PHYPARAM0_REF_LOSLEVEL (0x9 << 26) 110 111 #define EXYNOS5_DRD_PHYPARAM1 0x20 112 113 #define PHYPARAM1_PCS_TXDEEMPH_MASK (0x1f << 0) 114 #define PHYPARAM1_PCS_TXDEEMPH (0x1c) 115 116 #define EXYNOS5_DRD_PHYTERM 0x24 117 118 #define EXYNOS5_DRD_PHYTEST 0x28 119 120 #define PHYTEST_POWERDOWN_SSP BIT(3) 121 #define PHYTEST_POWERDOWN_HSP BIT(2) 122 123 #define EXYNOS5_DRD_PHYADP 0x2c 124 125 #define EXYNOS5_DRD_PHYUTMICLKSEL 0x30 126 127 #define PHYUTMICLKSEL_UTMI_CLKSEL BIT(2) 128 129 #define EXYNOS5_DRD_PHYRESUME 0x34 130 #define EXYNOS5_DRD_LINKPORT 0x44 131 132 /* USB 3.0 DRD PHY SS Function Control Reg; accessed by CR_PORT */ 133 #define EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN (0x15) 134 #define LOSLEVEL_OVRD_IN_LOS_BIAS_5420 (0x5 << 13) 135 #define LOSLEVEL_OVRD_IN_LOS_BIAS_DEFAULT (0x0 << 13) 136 #define LOSLEVEL_OVRD_IN_EN (0x1 << 10) 137 #define LOSLEVEL_OVRD_IN_LOS_LEVEL_DEFAULT (0x9 << 0) 138 139 #define EXYNOS5_DRD_PHYSS_TX_VBOOSTLEVEL_OVRD_IN (0x12) 140 #define TX_VBOOSTLEVEL_OVRD_IN_VBOOST_5420 (0x5 << 13) 141 #define TX_VBOOSTLEVEL_OVRD_IN_VBOOST_DEFAULT (0x4 << 13) 142 143 #define EXYNOS5_DRD_PHYSS_LANE0_TX_DEBUG (0x1010) 144 #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_19M2_20M (0x4 << 4) 145 #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_24M (0x8 << 4) 146 #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_25M_26M (0x8 << 4) 147 #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_48M_50M_52M (0x20 << 4) 148 #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_62M5 (0x20 << 4) 149 #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_96M_100M (0x40 << 4) 150 151 #define KHZ 1000 152 #define MHZ (KHZ * KHZ) 153 154 enum exynos5_usbdrd_phy_id { 155 EXYNOS5_DRDPHY_UTMI, 156 EXYNOS5_DRDPHY_PIPE3, 157 EXYNOS5_DRDPHYS_NUM, 158 }; 159 160 struct phy_usb_instance; 161 struct exynos5_usbdrd_phy; 162 163 struct exynos5_usbdrd_phy_config { 164 u32 id; 165 void (*phy_isol)(struct phy_usb_instance *inst, u32 on); 166 void (*phy_init)(struct exynos5_usbdrd_phy *phy_drd); 167 unsigned int (*set_refclk)(struct phy_usb_instance *inst); 168 }; 169 170 struct exynos5_usbdrd_phy_drvdata { 171 const struct exynos5_usbdrd_phy_config *phy_cfg; 172 u32 pmu_offset_usbdrd0_phy; 173 u32 pmu_offset_usbdrd1_phy; 174 bool has_common_clk_gate; 175 }; 176 177 /** 178 * struct exynos5_usbdrd_phy - driver data for USB 3.0 PHY 179 * @dev: pointer to device instance of this platform device 180 * @reg_phy: usb phy controller register memory base 181 * @clk: phy clock for register access 182 * @pipeclk: clock for pipe3 phy 183 * @utmiclk: clock for utmi+ phy 184 * @itpclk: clock for ITP generation 185 * @drv_data: pointer to SoC level driver data structure 186 * @phys[]: array for 'EXYNOS5_DRDPHYS_NUM' number of PHY 187 * instances each with its 'phy' and 'phy_cfg'. 188 * @extrefclk: frequency select settings when using 'separate 189 * reference clocks' for SS and HS operations 190 * @ref_clk: reference clock to PHY block from which PHY's 191 * operational clocks are derived 192 * vbus: VBUS regulator for phy 193 * vbus_boost: Boost regulator for VBUS present on few Exynos boards 194 */ 195 struct exynos5_usbdrd_phy { 196 struct device *dev; 197 void __iomem *reg_phy; 198 struct clk *clk; 199 struct clk *pipeclk; 200 struct clk *utmiclk; 201 struct clk *itpclk; 202 const struct exynos5_usbdrd_phy_drvdata *drv_data; 203 struct phy_usb_instance { 204 struct phy *phy; 205 u32 index; 206 struct regmap *reg_pmu; 207 u32 pmu_offset; 208 const struct exynos5_usbdrd_phy_config *phy_cfg; 209 } phys[EXYNOS5_DRDPHYS_NUM]; 210 u32 extrefclk; 211 struct clk *ref_clk; 212 struct regulator *vbus; 213 struct regulator *vbus_boost; 214 }; 215 216 static inline 217 struct exynos5_usbdrd_phy *to_usbdrd_phy(struct phy_usb_instance *inst) 218 { 219 return container_of((inst), struct exynos5_usbdrd_phy, 220 phys[(inst)->index]); 221 } 222 223 /* 224 * exynos5_rate_to_clk() converts the supplied clock rate to the value that 225 * can be written to the phy register. 226 */ 227 static unsigned int exynos5_rate_to_clk(unsigned long rate, u32 *reg) 228 { 229 /* EXYNOS5_FSEL_MASK */ 230 231 switch (rate) { 232 case 9600 * KHZ: 233 *reg = EXYNOS5_FSEL_9MHZ6; 234 break; 235 case 10 * MHZ: 236 *reg = EXYNOS5_FSEL_10MHZ; 237 break; 238 case 12 * MHZ: 239 *reg = EXYNOS5_FSEL_12MHZ; 240 break; 241 case 19200 * KHZ: 242 *reg = EXYNOS5_FSEL_19MHZ2; 243 break; 244 case 20 * MHZ: 245 *reg = EXYNOS5_FSEL_20MHZ; 246 break; 247 case 24 * MHZ: 248 *reg = EXYNOS5_FSEL_24MHZ; 249 break; 250 case 50 * MHZ: 251 *reg = EXYNOS5_FSEL_50MHZ; 252 break; 253 default: 254 return -EINVAL; 255 } 256 257 return 0; 258 } 259 260 static void exynos5_usbdrd_phy_isol(struct phy_usb_instance *inst, 261 unsigned int on) 262 { 263 unsigned int val; 264 265 if (!inst->reg_pmu) 266 return; 267 268 val = on ? 0 : EXYNOS4_PHY_ENABLE; 269 270 regmap_update_bits(inst->reg_pmu, inst->pmu_offset, 271 EXYNOS4_PHY_ENABLE, val); 272 } 273 274 /* 275 * Sets the pipe3 phy's clk as EXTREFCLK (XXTI) which is internal clock 276 * from clock core. Further sets multiplier values and spread spectrum 277 * clock settings for SuperSpeed operations. 278 */ 279 static unsigned int 280 exynos5_usbdrd_pipe3_set_refclk(struct phy_usb_instance *inst) 281 { 282 u32 reg; 283 struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst); 284 285 /* restore any previous reference clock settings */ 286 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST); 287 288 /* Use EXTREFCLK as ref clock */ 289 reg &= ~PHYCLKRST_REFCLKSEL_MASK; 290 reg |= PHYCLKRST_REFCLKSEL_EXT_REFCLK; 291 292 /* FSEL settings corresponding to reference clock */ 293 reg &= ~PHYCLKRST_FSEL_PIPE_MASK | 294 PHYCLKRST_MPLL_MULTIPLIER_MASK | 295 PHYCLKRST_SSC_REFCLKSEL_MASK; 296 switch (phy_drd->extrefclk) { 297 case EXYNOS5_FSEL_50MHZ: 298 reg |= (PHYCLKRST_MPLL_MULTIPLIER_50M_REF | 299 PHYCLKRST_SSC_REFCLKSEL(0x00)); 300 break; 301 case EXYNOS5_FSEL_24MHZ: 302 reg |= (PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF | 303 PHYCLKRST_SSC_REFCLKSEL(0x88)); 304 break; 305 case EXYNOS5_FSEL_20MHZ: 306 reg |= (PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF | 307 PHYCLKRST_SSC_REFCLKSEL(0x00)); 308 break; 309 case EXYNOS5_FSEL_19MHZ2: 310 reg |= (PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF | 311 PHYCLKRST_SSC_REFCLKSEL(0x88)); 312 break; 313 default: 314 dev_dbg(phy_drd->dev, "unsupported ref clk\n"); 315 break; 316 } 317 318 return reg; 319 } 320 321 /* 322 * Sets the utmi phy's clk as EXTREFCLK (XXTI) which is internal clock 323 * from clock core. Further sets the FSEL values for HighSpeed operations. 324 */ 325 static unsigned int 326 exynos5_usbdrd_utmi_set_refclk(struct phy_usb_instance *inst) 327 { 328 u32 reg; 329 struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst); 330 331 /* restore any previous reference clock settings */ 332 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST); 333 334 reg &= ~PHYCLKRST_REFCLKSEL_MASK; 335 reg |= PHYCLKRST_REFCLKSEL_EXT_REFCLK; 336 337 reg &= ~PHYCLKRST_FSEL_UTMI_MASK | 338 PHYCLKRST_MPLL_MULTIPLIER_MASK | 339 PHYCLKRST_SSC_REFCLKSEL_MASK; 340 reg |= PHYCLKRST_FSEL(phy_drd->extrefclk); 341 342 return reg; 343 } 344 345 static void exynos5_usbdrd_pipe3_init(struct exynos5_usbdrd_phy *phy_drd) 346 { 347 u32 reg; 348 349 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1); 350 /* Set Tx De-Emphasis level */ 351 reg &= ~PHYPARAM1_PCS_TXDEEMPH_MASK; 352 reg |= PHYPARAM1_PCS_TXDEEMPH; 353 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1); 354 355 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST); 356 reg &= ~PHYTEST_POWERDOWN_SSP; 357 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST); 358 } 359 360 static void exynos5_usbdrd_utmi_init(struct exynos5_usbdrd_phy *phy_drd) 361 { 362 u32 reg; 363 364 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0); 365 /* Set Loss-of-Signal Detector sensitivity */ 366 reg &= ~PHYPARAM0_REF_LOSLEVEL_MASK; 367 reg |= PHYPARAM0_REF_LOSLEVEL; 368 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0); 369 370 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1); 371 /* Set Tx De-Emphasis level */ 372 reg &= ~PHYPARAM1_PCS_TXDEEMPH_MASK; 373 reg |= PHYPARAM1_PCS_TXDEEMPH; 374 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1); 375 376 /* UTMI Power Control */ 377 writel(PHYUTMI_OTGDISABLE, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMI); 378 379 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST); 380 reg &= ~PHYTEST_POWERDOWN_HSP; 381 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST); 382 } 383 384 static int exynos5_usbdrd_phy_init(struct phy *phy) 385 { 386 int ret; 387 u32 reg; 388 struct phy_usb_instance *inst = phy_get_drvdata(phy); 389 struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst); 390 391 ret = clk_prepare_enable(phy_drd->clk); 392 if (ret) 393 return ret; 394 395 /* Reset USB 3.0 PHY */ 396 writel(0x0, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0); 397 writel(0x0, phy_drd->reg_phy + EXYNOS5_DRD_PHYRESUME); 398 399 /* 400 * Setting the Frame length Adj value[6:1] to default 0x20 401 * See xHCI 1.0 spec, 5.2.4 402 */ 403 reg = LINKSYSTEM_XHCI_VERSION_CONTROL | 404 LINKSYSTEM_FLADJ(0x20); 405 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_LINKSYSTEM); 406 407 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0); 408 /* Select PHY CLK source */ 409 reg &= ~PHYPARAM0_REF_USE_PAD; 410 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0); 411 412 /* This bit must be set for both HS and SS operations */ 413 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMICLKSEL); 414 reg |= PHYUTMICLKSEL_UTMI_CLKSEL; 415 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMICLKSEL); 416 417 /* UTMI or PIPE3 specific init */ 418 inst->phy_cfg->phy_init(phy_drd); 419 420 /* reference clock settings */ 421 reg = inst->phy_cfg->set_refclk(inst); 422 423 /* Digital power supply in normal operating mode */ 424 reg |= PHYCLKRST_RETENABLEN | 425 /* Enable ref clock for SS function */ 426 PHYCLKRST_REF_SSP_EN | 427 /* Enable spread spectrum */ 428 PHYCLKRST_SSC_EN | 429 /* Power down HS Bias and PLL blocks in suspend mode */ 430 PHYCLKRST_COMMONONN | 431 /* Reset the port */ 432 PHYCLKRST_PORTRESET; 433 434 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST); 435 436 udelay(10); 437 438 reg &= ~PHYCLKRST_PORTRESET; 439 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST); 440 441 clk_disable_unprepare(phy_drd->clk); 442 443 return 0; 444 } 445 446 static int exynos5_usbdrd_phy_exit(struct phy *phy) 447 { 448 int ret; 449 u32 reg; 450 struct phy_usb_instance *inst = phy_get_drvdata(phy); 451 struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst); 452 453 ret = clk_prepare_enable(phy_drd->clk); 454 if (ret) 455 return ret; 456 457 reg = PHYUTMI_OTGDISABLE | 458 PHYUTMI_FORCESUSPEND | 459 PHYUTMI_FORCESLEEP; 460 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMI); 461 462 /* Resetting the PHYCLKRST enable bits to reduce leakage current */ 463 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST); 464 reg &= ~(PHYCLKRST_REF_SSP_EN | 465 PHYCLKRST_SSC_EN | 466 PHYCLKRST_COMMONONN); 467 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST); 468 469 /* Control PHYTEST to remove leakage current */ 470 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST); 471 reg |= PHYTEST_POWERDOWN_SSP | 472 PHYTEST_POWERDOWN_HSP; 473 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST); 474 475 clk_disable_unprepare(phy_drd->clk); 476 477 return 0; 478 } 479 480 static int exynos5_usbdrd_phy_power_on(struct phy *phy) 481 { 482 int ret; 483 struct phy_usb_instance *inst = phy_get_drvdata(phy); 484 struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst); 485 486 dev_dbg(phy_drd->dev, "Request to power_on usbdrd_phy phy\n"); 487 488 clk_prepare_enable(phy_drd->ref_clk); 489 if (!phy_drd->drv_data->has_common_clk_gate) { 490 clk_prepare_enable(phy_drd->pipeclk); 491 clk_prepare_enable(phy_drd->utmiclk); 492 clk_prepare_enable(phy_drd->itpclk); 493 } 494 495 /* Enable VBUS supply */ 496 if (phy_drd->vbus_boost) { 497 ret = regulator_enable(phy_drd->vbus_boost); 498 if (ret) { 499 dev_err(phy_drd->dev, 500 "Failed to enable VBUS boost supply\n"); 501 goto fail_vbus; 502 } 503 } 504 505 if (phy_drd->vbus) { 506 ret = regulator_enable(phy_drd->vbus); 507 if (ret) { 508 dev_err(phy_drd->dev, "Failed to enable VBUS supply\n"); 509 goto fail_vbus_boost; 510 } 511 } 512 513 /* Power-on PHY*/ 514 inst->phy_cfg->phy_isol(inst, 0); 515 516 return 0; 517 518 fail_vbus_boost: 519 if (phy_drd->vbus_boost) 520 regulator_disable(phy_drd->vbus_boost); 521 522 fail_vbus: 523 clk_disable_unprepare(phy_drd->ref_clk); 524 if (!phy_drd->drv_data->has_common_clk_gate) { 525 clk_disable_unprepare(phy_drd->itpclk); 526 clk_disable_unprepare(phy_drd->utmiclk); 527 clk_disable_unprepare(phy_drd->pipeclk); 528 } 529 530 return ret; 531 } 532 533 static int exynos5_usbdrd_phy_power_off(struct phy *phy) 534 { 535 struct phy_usb_instance *inst = phy_get_drvdata(phy); 536 struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst); 537 538 dev_dbg(phy_drd->dev, "Request to power_off usbdrd_phy phy\n"); 539 540 /* Power-off the PHY */ 541 inst->phy_cfg->phy_isol(inst, 1); 542 543 /* Disable VBUS supply */ 544 if (phy_drd->vbus) 545 regulator_disable(phy_drd->vbus); 546 if (phy_drd->vbus_boost) 547 regulator_disable(phy_drd->vbus_boost); 548 549 clk_disable_unprepare(phy_drd->ref_clk); 550 if (!phy_drd->drv_data->has_common_clk_gate) { 551 clk_disable_unprepare(phy_drd->itpclk); 552 clk_disable_unprepare(phy_drd->pipeclk); 553 clk_disable_unprepare(phy_drd->utmiclk); 554 } 555 556 return 0; 557 } 558 559 static int crport_handshake(struct exynos5_usbdrd_phy *phy_drd, 560 u32 val, u32 cmd) 561 { 562 u32 usec = 100; 563 unsigned int result; 564 565 writel(val | cmd, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0); 566 567 do { 568 result = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1); 569 if (result & PHYREG1_CR_ACK) 570 break; 571 572 udelay(1); 573 } while (usec-- > 0); 574 575 if (!usec) { 576 dev_err(phy_drd->dev, 577 "CRPORT handshake timeout1 (0x%08x)\n", val); 578 return -ETIME; 579 } 580 581 usec = 100; 582 583 writel(val, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0); 584 585 do { 586 result = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1); 587 if (!(result & PHYREG1_CR_ACK)) 588 break; 589 590 udelay(1); 591 } while (usec-- > 0); 592 593 if (!usec) { 594 dev_err(phy_drd->dev, 595 "CRPORT handshake timeout2 (0x%08x)\n", val); 596 return -ETIME; 597 } 598 599 return 0; 600 } 601 602 static int crport_ctrl_write(struct exynos5_usbdrd_phy *phy_drd, 603 u32 addr, u32 data) 604 { 605 int ret; 606 607 /* Write Address */ 608 writel(PHYREG0_CR_DATA_IN(addr), 609 phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0); 610 ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(addr), 611 PHYREG0_CR_CAP_ADDR); 612 if (ret) 613 return ret; 614 615 /* Write Data */ 616 writel(PHYREG0_CR_DATA_IN(data), 617 phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0); 618 ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(data), 619 PHYREG0_CR_CAP_DATA); 620 if (ret) 621 return ret; 622 623 ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(data), 624 PHYREG0_CR_WRITE); 625 626 return ret; 627 } 628 629 /* 630 * Calibrate few PHY parameters using CR_PORT register to meet 631 * SuperSpeed requirements on Exynos5420 and Exynos5800 systems, 632 * which have 28nm USB 3.0 DRD PHY. 633 */ 634 static int exynos5420_usbdrd_phy_calibrate(struct exynos5_usbdrd_phy *phy_drd) 635 { 636 unsigned int temp; 637 int ret = 0; 638 639 /* 640 * Change los_bias to (0x5) for 28nm PHY from a 641 * default value (0x0); los_level is set as default 642 * (0x9) as also reflected in los_level[30:26] bits 643 * of PHYPARAM0 register. 644 */ 645 temp = LOSLEVEL_OVRD_IN_LOS_BIAS_5420 | 646 LOSLEVEL_OVRD_IN_EN | 647 LOSLEVEL_OVRD_IN_LOS_LEVEL_DEFAULT; 648 ret = crport_ctrl_write(phy_drd, 649 EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN, 650 temp); 651 if (ret) { 652 dev_err(phy_drd->dev, 653 "Failed setting Loss-of-Signal level for SuperSpeed\n"); 654 return ret; 655 } 656 657 /* 658 * Set tx_vboost_lvl to (0x5) for 28nm PHY Tuning, 659 * to raise Tx signal level from its default value of (0x4) 660 */ 661 temp = TX_VBOOSTLEVEL_OVRD_IN_VBOOST_5420; 662 ret = crport_ctrl_write(phy_drd, 663 EXYNOS5_DRD_PHYSS_TX_VBOOSTLEVEL_OVRD_IN, 664 temp); 665 if (ret) { 666 dev_err(phy_drd->dev, 667 "Failed setting Tx-Vboost-Level for SuperSpeed\n"); 668 return ret; 669 } 670 671 /* 672 * Set proper time to wait for RxDetect measurement, for 673 * desired reference clock of PHY, by tuning the CR_PORT 674 * register LANE0.TX_DEBUG which is internal to PHY. 675 * This fixes issue with few USB 3.0 devices, which are 676 * not detected (not even generate interrupts on the bus 677 * on insertion) without this change. 678 * e.g. Samsung SUM-TSB16S 3.0 USB drive. 679 */ 680 switch (phy_drd->extrefclk) { 681 case EXYNOS5_FSEL_50MHZ: 682 temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_48M_50M_52M; 683 break; 684 case EXYNOS5_FSEL_20MHZ: 685 case EXYNOS5_FSEL_19MHZ2: 686 temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_19M2_20M; 687 break; 688 case EXYNOS5_FSEL_24MHZ: 689 default: 690 temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_24M; 691 break; 692 } 693 694 ret = crport_ctrl_write(phy_drd, 695 EXYNOS5_DRD_PHYSS_LANE0_TX_DEBUG, 696 temp); 697 if (ret) 698 dev_err(phy_drd->dev, 699 "Fail to set RxDet measurement time for SuperSpeed\n"); 700 701 return ret; 702 } 703 704 static struct phy *exynos5_usbdrd_phy_xlate(struct device *dev, 705 struct of_phandle_args *args) 706 { 707 struct exynos5_usbdrd_phy *phy_drd = dev_get_drvdata(dev); 708 709 if (WARN_ON(args->args[0] >= EXYNOS5_DRDPHYS_NUM)) 710 return ERR_PTR(-ENODEV); 711 712 return phy_drd->phys[args->args[0]].phy; 713 } 714 715 static int exynos5_usbdrd_phy_calibrate(struct phy *phy) 716 { 717 struct phy_usb_instance *inst = phy_get_drvdata(phy); 718 struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst); 719 720 return exynos5420_usbdrd_phy_calibrate(phy_drd); 721 } 722 723 static const struct phy_ops exynos5_usbdrd_phy_ops = { 724 .init = exynos5_usbdrd_phy_init, 725 .exit = exynos5_usbdrd_phy_exit, 726 .power_on = exynos5_usbdrd_phy_power_on, 727 .power_off = exynos5_usbdrd_phy_power_off, 728 .calibrate = exynos5_usbdrd_phy_calibrate, 729 .owner = THIS_MODULE, 730 }; 731 732 static int exynos5_usbdrd_phy_clk_handle(struct exynos5_usbdrd_phy *phy_drd) 733 { 734 unsigned long ref_rate; 735 int ret; 736 737 phy_drd->clk = devm_clk_get(phy_drd->dev, "phy"); 738 if (IS_ERR(phy_drd->clk)) { 739 dev_err(phy_drd->dev, "Failed to get phy clock\n"); 740 return PTR_ERR(phy_drd->clk); 741 } 742 743 phy_drd->ref_clk = devm_clk_get(phy_drd->dev, "ref"); 744 if (IS_ERR(phy_drd->ref_clk)) { 745 dev_err(phy_drd->dev, "Failed to get phy reference clock\n"); 746 return PTR_ERR(phy_drd->ref_clk); 747 } 748 ref_rate = clk_get_rate(phy_drd->ref_clk); 749 750 ret = exynos5_rate_to_clk(ref_rate, &phy_drd->extrefclk); 751 if (ret) { 752 dev_err(phy_drd->dev, "Clock rate (%ld) not supported\n", 753 ref_rate); 754 return ret; 755 } 756 757 if (!phy_drd->drv_data->has_common_clk_gate) { 758 phy_drd->pipeclk = devm_clk_get(phy_drd->dev, "phy_pipe"); 759 if (IS_ERR(phy_drd->pipeclk)) { 760 dev_info(phy_drd->dev, 761 "PIPE3 phy operational clock not specified\n"); 762 phy_drd->pipeclk = NULL; 763 } 764 765 phy_drd->utmiclk = devm_clk_get(phy_drd->dev, "phy_utmi"); 766 if (IS_ERR(phy_drd->utmiclk)) { 767 dev_info(phy_drd->dev, 768 "UTMI phy operational clock not specified\n"); 769 phy_drd->utmiclk = NULL; 770 } 771 772 phy_drd->itpclk = devm_clk_get(phy_drd->dev, "itp"); 773 if (IS_ERR(phy_drd->itpclk)) { 774 dev_info(phy_drd->dev, 775 "ITP clock from main OSC not specified\n"); 776 phy_drd->itpclk = NULL; 777 } 778 } 779 780 return 0; 781 } 782 783 static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = { 784 { 785 .id = EXYNOS5_DRDPHY_UTMI, 786 .phy_isol = exynos5_usbdrd_phy_isol, 787 .phy_init = exynos5_usbdrd_utmi_init, 788 .set_refclk = exynos5_usbdrd_utmi_set_refclk, 789 }, 790 { 791 .id = EXYNOS5_DRDPHY_PIPE3, 792 .phy_isol = exynos5_usbdrd_phy_isol, 793 .phy_init = exynos5_usbdrd_pipe3_init, 794 .set_refclk = exynos5_usbdrd_pipe3_set_refclk, 795 }, 796 }; 797 798 static const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = { 799 .phy_cfg = phy_cfg_exynos5, 800 .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL, 801 .pmu_offset_usbdrd1_phy = EXYNOS5420_USBDRD1_PHY_CONTROL, 802 .has_common_clk_gate = true, 803 }; 804 805 static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = { 806 .phy_cfg = phy_cfg_exynos5, 807 .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL, 808 .has_common_clk_gate = true, 809 }; 810 811 static const struct exynos5_usbdrd_phy_drvdata exynos5433_usbdrd_phy = { 812 .phy_cfg = phy_cfg_exynos5, 813 .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL, 814 .pmu_offset_usbdrd1_phy = EXYNOS5433_USBHOST30_PHY_CONTROL, 815 .has_common_clk_gate = false, 816 }; 817 818 static const struct exynos5_usbdrd_phy_drvdata exynos7_usbdrd_phy = { 819 .phy_cfg = phy_cfg_exynos5, 820 .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL, 821 .has_common_clk_gate = false, 822 }; 823 824 static const struct of_device_id exynos5_usbdrd_phy_of_match[] = { 825 { 826 .compatible = "samsung,exynos5250-usbdrd-phy", 827 .data = &exynos5250_usbdrd_phy 828 }, { 829 .compatible = "samsung,exynos5420-usbdrd-phy", 830 .data = &exynos5420_usbdrd_phy 831 }, { 832 .compatible = "samsung,exynos5433-usbdrd-phy", 833 .data = &exynos5433_usbdrd_phy 834 }, { 835 .compatible = "samsung,exynos7-usbdrd-phy", 836 .data = &exynos7_usbdrd_phy 837 }, 838 { }, 839 }; 840 MODULE_DEVICE_TABLE(of, exynos5_usbdrd_phy_of_match); 841 842 static int exynos5_usbdrd_phy_probe(struct platform_device *pdev) 843 { 844 struct device *dev = &pdev->dev; 845 struct device_node *node = dev->of_node; 846 struct exynos5_usbdrd_phy *phy_drd; 847 struct phy_provider *phy_provider; 848 struct resource *res; 849 const struct exynos5_usbdrd_phy_drvdata *drv_data; 850 struct regmap *reg_pmu; 851 u32 pmu_offset; 852 int i, ret; 853 int channel; 854 855 phy_drd = devm_kzalloc(dev, sizeof(*phy_drd), GFP_KERNEL); 856 if (!phy_drd) 857 return -ENOMEM; 858 859 dev_set_drvdata(dev, phy_drd); 860 phy_drd->dev = dev; 861 862 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 863 phy_drd->reg_phy = devm_ioremap_resource(dev, res); 864 if (IS_ERR(phy_drd->reg_phy)) 865 return PTR_ERR(phy_drd->reg_phy); 866 867 drv_data = of_device_get_match_data(dev); 868 if (!drv_data) 869 return -EINVAL; 870 871 phy_drd->drv_data = drv_data; 872 873 ret = exynos5_usbdrd_phy_clk_handle(phy_drd); 874 if (ret) { 875 dev_err(dev, "Failed to initialize clocks\n"); 876 return ret; 877 } 878 879 reg_pmu = syscon_regmap_lookup_by_phandle(dev->of_node, 880 "samsung,pmu-syscon"); 881 if (IS_ERR(reg_pmu)) { 882 dev_err(dev, "Failed to lookup PMU regmap\n"); 883 return PTR_ERR(reg_pmu); 884 } 885 886 /* 887 * Exynos5420 SoC has multiple channels for USB 3.0 PHY, with 888 * each having separate power control registers. 889 * 'channel' facilitates to set such registers. 890 */ 891 channel = of_alias_get_id(node, "usbdrdphy"); 892 if (channel < 0) 893 dev_dbg(dev, "Not a multi-controller usbdrd phy\n"); 894 895 switch (channel) { 896 case 1: 897 pmu_offset = phy_drd->drv_data->pmu_offset_usbdrd1_phy; 898 break; 899 case 0: 900 default: 901 pmu_offset = phy_drd->drv_data->pmu_offset_usbdrd0_phy; 902 break; 903 } 904 905 /* Get Vbus regulators */ 906 phy_drd->vbus = devm_regulator_get(dev, "vbus"); 907 if (IS_ERR(phy_drd->vbus)) { 908 ret = PTR_ERR(phy_drd->vbus); 909 if (ret == -EPROBE_DEFER) 910 return ret; 911 912 dev_warn(dev, "Failed to get VBUS supply regulator\n"); 913 phy_drd->vbus = NULL; 914 } 915 916 phy_drd->vbus_boost = devm_regulator_get(dev, "vbus-boost"); 917 if (IS_ERR(phy_drd->vbus_boost)) { 918 ret = PTR_ERR(phy_drd->vbus_boost); 919 if (ret == -EPROBE_DEFER) 920 return ret; 921 922 dev_warn(dev, "Failed to get VBUS boost supply regulator\n"); 923 phy_drd->vbus_boost = NULL; 924 } 925 926 dev_vdbg(dev, "Creating usbdrd_phy phy\n"); 927 928 for (i = 0; i < EXYNOS5_DRDPHYS_NUM; i++) { 929 struct phy *phy = devm_phy_create(dev, NULL, 930 &exynos5_usbdrd_phy_ops); 931 if (IS_ERR(phy)) { 932 dev_err(dev, "Failed to create usbdrd_phy phy\n"); 933 return PTR_ERR(phy); 934 } 935 936 phy_drd->phys[i].phy = phy; 937 phy_drd->phys[i].index = i; 938 phy_drd->phys[i].reg_pmu = reg_pmu; 939 phy_drd->phys[i].pmu_offset = pmu_offset; 940 phy_drd->phys[i].phy_cfg = &drv_data->phy_cfg[i]; 941 phy_set_drvdata(phy, &phy_drd->phys[i]); 942 } 943 944 phy_provider = devm_of_phy_provider_register(dev, 945 exynos5_usbdrd_phy_xlate); 946 if (IS_ERR(phy_provider)) { 947 dev_err(phy_drd->dev, "Failed to register phy provider\n"); 948 return PTR_ERR(phy_provider); 949 } 950 951 return 0; 952 } 953 954 static struct platform_driver exynos5_usb3drd_phy = { 955 .probe = exynos5_usbdrd_phy_probe, 956 .driver = { 957 .of_match_table = exynos5_usbdrd_phy_of_match, 958 .name = "exynos5_usb3drd_phy", 959 } 960 }; 961 962 module_platform_driver(exynos5_usb3drd_phy); 963 MODULE_DESCRIPTION("Samsung EXYNOS5 SoCs USB 3.0 DRD controller PHY driver"); 964 MODULE_AUTHOR("Vivek Gautam <gautam.vivek@samsung.com>"); 965 MODULE_LICENSE("GPL v2"); 966 MODULE_ALIAS("platform:exynos5_usb3drd_phy"); 967