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/phy/phy.h> 22#include <linux/platform_device.h> 23#include <linux/mutex.h> 24#include <linux/mfd/syscon.h> 25#include <linux/mfd/syscon/exynos5-pmu.h> 26#include <linux/regmap.h> 27#include <linux/regulator/consumer.h> 28 29/* Exynos USB PHY registers */ 30#define EXYNOS5_FSEL_9MHZ6 0x0 31#define EXYNOS5_FSEL_10MHZ 0x1 32#define EXYNOS5_FSEL_12MHZ 0x2 33#define EXYNOS5_FSEL_19MHZ2 0x3 34#define EXYNOS5_FSEL_20MHZ 0x4 35#define EXYNOS5_FSEL_24MHZ 0x5 36#define EXYNOS5_FSEL_50MHZ 0x7 37 38/* EXYNOS5: USB 3.0 DRD PHY registers */ 39#define EXYNOS5_DRD_LINKSYSTEM 0x04 40 41#define LINKSYSTEM_FLADJ_MASK (0x3f << 1) 42#define LINKSYSTEM_FLADJ(_x) ((_x) << 1) 43#define LINKSYSTEM_XHCI_VERSION_CONTROL BIT(27) 44 45#define EXYNOS5_DRD_PHYUTMI 0x08 46 47#define PHYUTMI_OTGDISABLE BIT(6) 48#define PHYUTMI_FORCESUSPEND BIT(1) 49#define PHYUTMI_FORCESLEEP BIT(0) 50 51#define EXYNOS5_DRD_PHYPIPE 0x0c 52 53#define EXYNOS5_DRD_PHYCLKRST 0x10 54 55#define PHYCLKRST_EN_UTMISUSPEND BIT(31) 56 57#define PHYCLKRST_SSC_REFCLKSEL_MASK (0xff << 23) 58#define PHYCLKRST_SSC_REFCLKSEL(_x) ((_x) << 23) 59 60#define PHYCLKRST_SSC_RANGE_MASK (0x03 << 21) 61#define PHYCLKRST_SSC_RANGE(_x) ((_x) << 21) 62 63#define PHYCLKRST_SSC_EN BIT(20) 64#define PHYCLKRST_REF_SSP_EN BIT(19) 65#define PHYCLKRST_REF_CLKDIV2 BIT(18) 66 67#define PHYCLKRST_MPLL_MULTIPLIER_MASK (0x7f << 11) 68#define PHYCLKRST_MPLL_MULTIPLIER_100MHZ_REF (0x19 << 11) 69#define PHYCLKRST_MPLL_MULTIPLIER_50M_REF (0x32 << 11) 70#define PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF (0x68 << 11) 71#define PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF (0x7d << 11) 72#define PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF (0x02 << 11) 73 74#define PHYCLKRST_FSEL_UTMI_MASK (0x7 << 5) 75#define PHYCLKRST_FSEL_PIPE_MASK (0x7 << 8) 76#define PHYCLKRST_FSEL(_x) ((_x) << 5) 77#define PHYCLKRST_FSEL_PAD_100MHZ (0x27 << 5) 78#define PHYCLKRST_FSEL_PAD_24MHZ (0x2a << 5) 79#define PHYCLKRST_FSEL_PAD_20MHZ (0x31 << 5) 80#define PHYCLKRST_FSEL_PAD_19_2MHZ (0x38 << 5) 81 82#define PHYCLKRST_RETENABLEN BIT(4) 83 84#define PHYCLKRST_REFCLKSEL_MASK (0x03 << 2) 85#define PHYCLKRST_REFCLKSEL_PAD_REFCLK (0x2 << 2) 86#define PHYCLKRST_REFCLKSEL_EXT_REFCLK (0x3 << 2) 87 88#define PHYCLKRST_PORTRESET BIT(1) 89#define PHYCLKRST_COMMONONN BIT(0) 90 91#define EXYNOS5_DRD_PHYREG0 0x14 92#define EXYNOS5_DRD_PHYREG1 0x18 93 94#define EXYNOS5_DRD_PHYPARAM0 0x1c 95 96#define PHYPARAM0_REF_USE_PAD BIT(31) 97#define PHYPARAM0_REF_LOSLEVEL_MASK (0x1f << 26) 98#define PHYPARAM0_REF_LOSLEVEL (0x9 << 26) 99 100#define EXYNOS5_DRD_PHYPARAM1 0x20 101 102#define PHYPARAM1_PCS_TXDEEMPH_MASK (0x1f << 0) 103#define PHYPARAM1_PCS_TXDEEMPH (0x1c) 104 105#define EXYNOS5_DRD_PHYTERM 0x24 106 107#define EXYNOS5_DRD_PHYTEST 0x28 108 109#define PHYTEST_POWERDOWN_SSP BIT(3) 110#define PHYTEST_POWERDOWN_HSP BIT(2) 111 112#define EXYNOS5_DRD_PHYADP 0x2c 113 114#define EXYNOS5_DRD_PHYUTMICLKSEL 0x30 115 116#define PHYUTMICLKSEL_UTMI_CLKSEL BIT(2) 117 118#define EXYNOS5_DRD_PHYRESUME 0x34 119#define EXYNOS5_DRD_LINKPORT 0x44 120 121#define KHZ 1000 122#define MHZ (KHZ * KHZ) 123 124enum exynos5_usbdrd_phy_id { 125 EXYNOS5_DRDPHY_UTMI, 126 EXYNOS5_DRDPHY_PIPE3, 127 EXYNOS5_DRDPHYS_NUM, 128}; 129 130struct phy_usb_instance; 131struct exynos5_usbdrd_phy; 132 133struct exynos5_usbdrd_phy_config { 134 u32 id; 135 void (*phy_isol)(struct phy_usb_instance *inst, u32 on); 136 void (*phy_init)(struct exynos5_usbdrd_phy *phy_drd); 137 unsigned int (*set_refclk)(struct phy_usb_instance *inst); 138}; 139 140struct exynos5_usbdrd_phy_drvdata { 141 const struct exynos5_usbdrd_phy_config *phy_cfg; 142 u32 pmu_offset_usbdrd0_phy; 143 u32 pmu_offset_usbdrd1_phy; 144 bool has_common_clk_gate; 145}; 146 147/** 148 * struct exynos5_usbdrd_phy - driver data for USB 3.0 PHY 149 * @dev: pointer to device instance of this platform device 150 * @reg_phy: usb phy controller register memory base 151 * @clk: phy clock for register access 152 * @pipeclk: clock for pipe3 phy 153 * @utmiclk: clock for utmi+ phy 154 * @itpclk: clock for ITP generation 155 * @drv_data: pointer to SoC level driver data structure 156 * @phys[]: array for 'EXYNOS5_DRDPHYS_NUM' number of PHY 157 * instances each with its 'phy' and 'phy_cfg'. 158 * @extrefclk: frequency select settings when using 'separate 159 * reference clocks' for SS and HS operations 160 * @ref_clk: reference clock to PHY block from which PHY's 161 * operational clocks are derived 162 * vbus: VBUS regulator for phy 163 * vbus_boost: Boost regulator for VBUS present on few Exynos boards 164 */ 165struct exynos5_usbdrd_phy { 166 struct device *dev; 167 void __iomem *reg_phy; 168 struct clk *clk; 169 struct clk *pipeclk; 170 struct clk *utmiclk; 171 struct clk *itpclk; 172 const struct exynos5_usbdrd_phy_drvdata *drv_data; 173 struct phy_usb_instance { 174 struct phy *phy; 175 u32 index; 176 struct regmap *reg_pmu; 177 u32 pmu_offset; 178 const struct exynos5_usbdrd_phy_config *phy_cfg; 179 } phys[EXYNOS5_DRDPHYS_NUM]; 180 u32 extrefclk; 181 struct clk *ref_clk; 182 struct regulator *vbus; 183 struct regulator *vbus_boost; 184}; 185 186static inline 187struct exynos5_usbdrd_phy *to_usbdrd_phy(struct phy_usb_instance *inst) 188{ 189 return container_of((inst), struct exynos5_usbdrd_phy, 190 phys[(inst)->index]); 191} 192 193/* 194 * exynos5_rate_to_clk() converts the supplied clock rate to the value that 195 * can be written to the phy register. 196 */ 197static unsigned int exynos5_rate_to_clk(unsigned long rate, u32 *reg) 198{ 199 /* EXYNOS5_FSEL_MASK */ 200 201 switch (rate) { 202 case 9600 * KHZ: 203 *reg = EXYNOS5_FSEL_9MHZ6; 204 break; 205 case 10 * MHZ: 206 *reg = EXYNOS5_FSEL_10MHZ; 207 break; 208 case 12 * MHZ: 209 *reg = EXYNOS5_FSEL_12MHZ; 210 break; 211 case 19200 * KHZ: 212 *reg = EXYNOS5_FSEL_19MHZ2; 213 break; 214 case 20 * MHZ: 215 *reg = EXYNOS5_FSEL_20MHZ; 216 break; 217 case 24 * MHZ: 218 *reg = EXYNOS5_FSEL_24MHZ; 219 break; 220 case 50 * MHZ: 221 *reg = EXYNOS5_FSEL_50MHZ; 222 break; 223 default: 224 return -EINVAL; 225 } 226 227 return 0; 228} 229 230static void exynos5_usbdrd_phy_isol(struct phy_usb_instance *inst, 231 unsigned int on) 232{ 233 unsigned int val; 234 235 if (!inst->reg_pmu) 236 return; 237 238 val = on ? 0 : EXYNOS5_PHY_ENABLE; 239 240 regmap_update_bits(inst->reg_pmu, inst->pmu_offset, 241 EXYNOS5_PHY_ENABLE, val); 242} 243 244/* 245 * Sets the pipe3 phy's clk as EXTREFCLK (XXTI) which is internal clock 246 * from clock core. Further sets multiplier values and spread spectrum 247 * clock settings for SuperSpeed operations. 248 */ 249static unsigned int 250exynos5_usbdrd_pipe3_set_refclk(struct phy_usb_instance *inst) 251{ 252 static u32 reg; 253 struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst); 254 255 /* restore any previous reference clock settings */ 256 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST); 257 258 /* Use EXTREFCLK as ref clock */ 259 reg &= ~PHYCLKRST_REFCLKSEL_MASK; 260 reg |= PHYCLKRST_REFCLKSEL_EXT_REFCLK; 261 262 /* FSEL settings corresponding to reference clock */ 263 reg &= ~PHYCLKRST_FSEL_PIPE_MASK | 264 PHYCLKRST_MPLL_MULTIPLIER_MASK | 265 PHYCLKRST_SSC_REFCLKSEL_MASK; 266 switch (phy_drd->extrefclk) { 267 case EXYNOS5_FSEL_50MHZ: 268 reg |= (PHYCLKRST_MPLL_MULTIPLIER_50M_REF | 269 PHYCLKRST_SSC_REFCLKSEL(0x00)); 270 break; 271 case EXYNOS5_FSEL_24MHZ: 272 reg |= (PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF | 273 PHYCLKRST_SSC_REFCLKSEL(0x88)); 274 break; 275 case EXYNOS5_FSEL_20MHZ: 276 reg |= (PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF | 277 PHYCLKRST_SSC_REFCLKSEL(0x00)); 278 break; 279 case EXYNOS5_FSEL_19MHZ2: 280 reg |= (PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF | 281 PHYCLKRST_SSC_REFCLKSEL(0x88)); 282 break; 283 default: 284 dev_dbg(phy_drd->dev, "unsupported ref clk\n"); 285 break; 286 } 287 288 return reg; 289} 290 291/* 292 * Sets the utmi phy's clk as EXTREFCLK (XXTI) which is internal clock 293 * from clock core. Further sets the FSEL values for HighSpeed operations. 294 */ 295static unsigned int 296exynos5_usbdrd_utmi_set_refclk(struct phy_usb_instance *inst) 297{ 298 static u32 reg; 299 struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst); 300 301 /* restore any previous reference clock settings */ 302 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST); 303 304 reg &= ~PHYCLKRST_REFCLKSEL_MASK; 305 reg |= PHYCLKRST_REFCLKSEL_EXT_REFCLK; 306 307 reg &= ~PHYCLKRST_FSEL_UTMI_MASK | 308 PHYCLKRST_MPLL_MULTIPLIER_MASK | 309 PHYCLKRST_SSC_REFCLKSEL_MASK; 310 reg |= PHYCLKRST_FSEL(phy_drd->extrefclk); 311 312 return reg; 313} 314 315static void exynos5_usbdrd_pipe3_init(struct exynos5_usbdrd_phy *phy_drd) 316{ 317 u32 reg; 318 319 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1); 320 /* Set Tx De-Emphasis level */ 321 reg &= ~PHYPARAM1_PCS_TXDEEMPH_MASK; 322 reg |= PHYPARAM1_PCS_TXDEEMPH; 323 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1); 324 325 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST); 326 reg &= ~PHYTEST_POWERDOWN_SSP; 327 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST); 328} 329 330static void exynos5_usbdrd_utmi_init(struct exynos5_usbdrd_phy *phy_drd) 331{ 332 u32 reg; 333 334 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0); 335 /* Set Loss-of-Signal Detector sensitivity */ 336 reg &= ~PHYPARAM0_REF_LOSLEVEL_MASK; 337 reg |= PHYPARAM0_REF_LOSLEVEL; 338 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0); 339 340 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1); 341 /* Set Tx De-Emphasis level */ 342 reg &= ~PHYPARAM1_PCS_TXDEEMPH_MASK; 343 reg |= PHYPARAM1_PCS_TXDEEMPH; 344 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1); 345 346 /* UTMI Power Control */ 347 writel(PHYUTMI_OTGDISABLE, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMI); 348 349 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST); 350 reg &= ~PHYTEST_POWERDOWN_HSP; 351 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST); 352} 353 354static int exynos5_usbdrd_phy_init(struct phy *phy) 355{ 356 int ret; 357 u32 reg; 358 struct phy_usb_instance *inst = phy_get_drvdata(phy); 359 struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst); 360 361 ret = clk_prepare_enable(phy_drd->clk); 362 if (ret) 363 return ret; 364 365 /* Reset USB 3.0 PHY */ 366 writel(0x0, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0); 367 writel(0x0, phy_drd->reg_phy + EXYNOS5_DRD_PHYRESUME); 368 369 /* 370 * Setting the Frame length Adj value[6:1] to default 0x20 371 * See xHCI 1.0 spec, 5.2.4 372 */ 373 reg = LINKSYSTEM_XHCI_VERSION_CONTROL | 374 LINKSYSTEM_FLADJ(0x20); 375 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_LINKSYSTEM); 376 377 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0); 378 /* Select PHY CLK source */ 379 reg &= ~PHYPARAM0_REF_USE_PAD; 380 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0); 381 382 /* This bit must be set for both HS and SS operations */ 383 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMICLKSEL); 384 reg |= PHYUTMICLKSEL_UTMI_CLKSEL; 385 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMICLKSEL); 386 387 /* UTMI or PIPE3 specific init */ 388 inst->phy_cfg->phy_init(phy_drd); 389 390 /* reference clock settings */ 391 reg = inst->phy_cfg->set_refclk(inst); 392 393 /* Digital power supply in normal operating mode */ 394 reg |= PHYCLKRST_RETENABLEN | 395 /* Enable ref clock for SS function */ 396 PHYCLKRST_REF_SSP_EN | 397 /* Enable spread spectrum */ 398 PHYCLKRST_SSC_EN | 399 /* Power down HS Bias and PLL blocks in suspend mode */ 400 PHYCLKRST_COMMONONN | 401 /* Reset the port */ 402 PHYCLKRST_PORTRESET; 403 404 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST); 405 406 udelay(10); 407 408 reg &= ~PHYCLKRST_PORTRESET; 409 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST); 410 411 clk_disable_unprepare(phy_drd->clk); 412 413 return 0; 414} 415 416static int exynos5_usbdrd_phy_exit(struct phy *phy) 417{ 418 int ret; 419 u32 reg; 420 struct phy_usb_instance *inst = phy_get_drvdata(phy); 421 struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst); 422 423 ret = clk_prepare_enable(phy_drd->clk); 424 if (ret) 425 return ret; 426 427 reg = PHYUTMI_OTGDISABLE | 428 PHYUTMI_FORCESUSPEND | 429 PHYUTMI_FORCESLEEP; 430 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMI); 431 432 /* Resetting the PHYCLKRST enable bits to reduce leakage current */ 433 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST); 434 reg &= ~(PHYCLKRST_REF_SSP_EN | 435 PHYCLKRST_SSC_EN | 436 PHYCLKRST_COMMONONN); 437 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST); 438 439 /* Control PHYTEST to remove leakage current */ 440 reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST); 441 reg |= PHYTEST_POWERDOWN_SSP | 442 PHYTEST_POWERDOWN_HSP; 443 writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST); 444 445 clk_disable_unprepare(phy_drd->clk); 446 447 return 0; 448} 449 450static int exynos5_usbdrd_phy_power_on(struct phy *phy) 451{ 452 int ret; 453 struct phy_usb_instance *inst = phy_get_drvdata(phy); 454 struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst); 455 456 dev_dbg(phy_drd->dev, "Request to power_on usbdrd_phy phy\n"); 457 458 clk_prepare_enable(phy_drd->ref_clk); 459 if (!phy_drd->drv_data->has_common_clk_gate) { 460 clk_prepare_enable(phy_drd->pipeclk); 461 clk_prepare_enable(phy_drd->utmiclk); 462 clk_prepare_enable(phy_drd->itpclk); 463 } 464 465 /* Enable VBUS supply */ 466 if (phy_drd->vbus_boost) { 467 ret = regulator_enable(phy_drd->vbus_boost); 468 if (ret) { 469 dev_err(phy_drd->dev, 470 "Failed to enable VBUS boost supply\n"); 471 goto fail_vbus; 472 } 473 } 474 475 if (phy_drd->vbus) { 476 ret = regulator_enable(phy_drd->vbus); 477 if (ret) { 478 dev_err(phy_drd->dev, "Failed to enable VBUS supply\n"); 479 goto fail_vbus_boost; 480 } 481 } 482 483 /* Power-on PHY*/ 484 inst->phy_cfg->phy_isol(inst, 0); 485 486 return 0; 487 488fail_vbus_boost: 489 if (phy_drd->vbus_boost) 490 regulator_disable(phy_drd->vbus_boost); 491 492fail_vbus: 493 clk_disable_unprepare(phy_drd->ref_clk); 494 if (!phy_drd->drv_data->has_common_clk_gate) { 495 clk_disable_unprepare(phy_drd->itpclk); 496 clk_disable_unprepare(phy_drd->utmiclk); 497 clk_disable_unprepare(phy_drd->pipeclk); 498 } 499 500 return ret; 501} 502 503static int exynos5_usbdrd_phy_power_off(struct phy *phy) 504{ 505 struct phy_usb_instance *inst = phy_get_drvdata(phy); 506 struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst); 507 508 dev_dbg(phy_drd->dev, "Request to power_off usbdrd_phy phy\n"); 509 510 /* Power-off the PHY */ 511 inst->phy_cfg->phy_isol(inst, 1); 512 513 /* Disable VBUS supply */ 514 if (phy_drd->vbus) 515 regulator_disable(phy_drd->vbus); 516 if (phy_drd->vbus_boost) 517 regulator_disable(phy_drd->vbus_boost); 518 519 clk_disable_unprepare(phy_drd->ref_clk); 520 if (!phy_drd->drv_data->has_common_clk_gate) { 521 clk_disable_unprepare(phy_drd->itpclk); 522 clk_disable_unprepare(phy_drd->pipeclk); 523 clk_disable_unprepare(phy_drd->utmiclk); 524 } 525 526 return 0; 527} 528 529static struct phy *exynos5_usbdrd_phy_xlate(struct device *dev, 530 struct of_phandle_args *args) 531{ 532 struct exynos5_usbdrd_phy *phy_drd = dev_get_drvdata(dev); 533 534 if (WARN_ON(args->args[0] >= EXYNOS5_DRDPHYS_NUM)) 535 return ERR_PTR(-ENODEV); 536 537 return phy_drd->phys[args->args[0]].phy; 538} 539 540static struct phy_ops exynos5_usbdrd_phy_ops = { 541 .init = exynos5_usbdrd_phy_init, 542 .exit = exynos5_usbdrd_phy_exit, 543 .power_on = exynos5_usbdrd_phy_power_on, 544 .power_off = exynos5_usbdrd_phy_power_off, 545 .owner = THIS_MODULE, 546}; 547 548static int exynos5_usbdrd_phy_clk_handle(struct exynos5_usbdrd_phy *phy_drd) 549{ 550 unsigned long ref_rate; 551 int ret; 552 553 phy_drd->clk = devm_clk_get(phy_drd->dev, "phy"); 554 if (IS_ERR(phy_drd->clk)) { 555 dev_err(phy_drd->dev, "Failed to get phy clock\n"); 556 return PTR_ERR(phy_drd->clk); 557 } 558 559 phy_drd->ref_clk = devm_clk_get(phy_drd->dev, "ref"); 560 if (IS_ERR(phy_drd->ref_clk)) { 561 dev_err(phy_drd->dev, "Failed to get phy reference clock\n"); 562 return PTR_ERR(phy_drd->ref_clk); 563 } 564 ref_rate = clk_get_rate(phy_drd->ref_clk); 565 566 ret = exynos5_rate_to_clk(ref_rate, &phy_drd->extrefclk); 567 if (ret) { 568 dev_err(phy_drd->dev, "Clock rate (%ld) not supported\n", 569 ref_rate); 570 return ret; 571 } 572 573 if (!phy_drd->drv_data->has_common_clk_gate) { 574 phy_drd->pipeclk = devm_clk_get(phy_drd->dev, "phy_pipe"); 575 if (IS_ERR(phy_drd->pipeclk)) { 576 dev_info(phy_drd->dev, 577 "PIPE3 phy operational clock not specified\n"); 578 phy_drd->pipeclk = NULL; 579 } 580 581 phy_drd->utmiclk = devm_clk_get(phy_drd->dev, "phy_utmi"); 582 if (IS_ERR(phy_drd->utmiclk)) { 583 dev_info(phy_drd->dev, 584 "UTMI phy operational clock not specified\n"); 585 phy_drd->utmiclk = NULL; 586 } 587 588 phy_drd->itpclk = devm_clk_get(phy_drd->dev, "itp"); 589 if (IS_ERR(phy_drd->itpclk)) { 590 dev_info(phy_drd->dev, 591 "ITP clock from main OSC not specified\n"); 592 phy_drd->itpclk = NULL; 593 } 594 } 595 596 return 0; 597} 598 599static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = { 600 { 601 .id = EXYNOS5_DRDPHY_UTMI, 602 .phy_isol = exynos5_usbdrd_phy_isol, 603 .phy_init = exynos5_usbdrd_utmi_init, 604 .set_refclk = exynos5_usbdrd_utmi_set_refclk, 605 }, 606 { 607 .id = EXYNOS5_DRDPHY_PIPE3, 608 .phy_isol = exynos5_usbdrd_phy_isol, 609 .phy_init = exynos5_usbdrd_pipe3_init, 610 .set_refclk = exynos5_usbdrd_pipe3_set_refclk, 611 }, 612}; 613 614static const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = { 615 .phy_cfg = phy_cfg_exynos5, 616 .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL, 617 .pmu_offset_usbdrd1_phy = EXYNOS5420_USBDRD1_PHY_CONTROL, 618 .has_common_clk_gate = true, 619}; 620 621static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = { 622 .phy_cfg = phy_cfg_exynos5, 623 .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL, 624 .has_common_clk_gate = true, 625}; 626 627static const struct exynos5_usbdrd_phy_drvdata exynos5433_usbdrd_phy = { 628 .phy_cfg = phy_cfg_exynos5, 629 .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL, 630 .pmu_offset_usbdrd1_phy = EXYNOS5433_USBHOST30_PHY_CONTROL, 631 .has_common_clk_gate = false, 632}; 633 634static const struct exynos5_usbdrd_phy_drvdata exynos7_usbdrd_phy = { 635 .phy_cfg = phy_cfg_exynos5, 636 .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL, 637 .has_common_clk_gate = false, 638}; 639 640static const struct of_device_id exynos5_usbdrd_phy_of_match[] = { 641 { 642 .compatible = "samsung,exynos5250-usbdrd-phy", 643 .data = &exynos5250_usbdrd_phy 644 }, { 645 .compatible = "samsung,exynos5420-usbdrd-phy", 646 .data = &exynos5420_usbdrd_phy 647 }, { 648 .compatible = "samsung,exynos5433-usbdrd-phy", 649 .data = &exynos5433_usbdrd_phy 650 }, { 651 .compatible = "samsung,exynos7-usbdrd-phy", 652 .data = &exynos7_usbdrd_phy 653 }, 654 { }, 655}; 656MODULE_DEVICE_TABLE(of, exynos5_usbdrd_phy_of_match); 657 658static int exynos5_usbdrd_phy_probe(struct platform_device *pdev) 659{ 660 struct device *dev = &pdev->dev; 661 struct device_node *node = dev->of_node; 662 struct exynos5_usbdrd_phy *phy_drd; 663 struct phy_provider *phy_provider; 664 struct resource *res; 665 const struct of_device_id *match; 666 const struct exynos5_usbdrd_phy_drvdata *drv_data; 667 struct regmap *reg_pmu; 668 u32 pmu_offset; 669 int i, ret; 670 int channel; 671 672 phy_drd = devm_kzalloc(dev, sizeof(*phy_drd), GFP_KERNEL); 673 if (!phy_drd) 674 return -ENOMEM; 675 676 dev_set_drvdata(dev, phy_drd); 677 phy_drd->dev = dev; 678 679 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 680 phy_drd->reg_phy = devm_ioremap_resource(dev, res); 681 if (IS_ERR(phy_drd->reg_phy)) 682 return PTR_ERR(phy_drd->reg_phy); 683 684 match = of_match_node(exynos5_usbdrd_phy_of_match, pdev->dev.of_node); 685 686 drv_data = match->data; 687 phy_drd->drv_data = drv_data; 688 689 ret = exynos5_usbdrd_phy_clk_handle(phy_drd); 690 if (ret) { 691 dev_err(dev, "Failed to initialize clocks\n"); 692 return ret; 693 } 694 695 reg_pmu = syscon_regmap_lookup_by_phandle(dev->of_node, 696 "samsung,pmu-syscon"); 697 if (IS_ERR(reg_pmu)) { 698 dev_err(dev, "Failed to lookup PMU regmap\n"); 699 return PTR_ERR(reg_pmu); 700 } 701 702 /* 703 * Exynos5420 SoC has multiple channels for USB 3.0 PHY, with 704 * each having separate power control registers. 705 * 'channel' facilitates to set such registers. 706 */ 707 channel = of_alias_get_id(node, "usbdrdphy"); 708 if (channel < 0) 709 dev_dbg(dev, "Not a multi-controller usbdrd phy\n"); 710 711 switch (channel) { 712 case 1: 713 pmu_offset = phy_drd->drv_data->pmu_offset_usbdrd1_phy; 714 break; 715 case 0: 716 default: 717 pmu_offset = phy_drd->drv_data->pmu_offset_usbdrd0_phy; 718 break; 719 } 720 721 /* Get Vbus regulators */ 722 phy_drd->vbus = devm_regulator_get(dev, "vbus"); 723 if (IS_ERR(phy_drd->vbus)) { 724 ret = PTR_ERR(phy_drd->vbus); 725 if (ret == -EPROBE_DEFER) 726 return ret; 727 728 dev_warn(dev, "Failed to get VBUS supply regulator\n"); 729 phy_drd->vbus = NULL; 730 } 731 732 phy_drd->vbus_boost = devm_regulator_get(dev, "vbus-boost"); 733 if (IS_ERR(phy_drd->vbus_boost)) { 734 ret = PTR_ERR(phy_drd->vbus_boost); 735 if (ret == -EPROBE_DEFER) 736 return ret; 737 738 dev_warn(dev, "Failed to get VBUS boost supply regulator\n"); 739 phy_drd->vbus_boost = NULL; 740 } 741 742 dev_vdbg(dev, "Creating usbdrd_phy phy\n"); 743 744 for (i = 0; i < EXYNOS5_DRDPHYS_NUM; i++) { 745 struct phy *phy = devm_phy_create(dev, NULL, 746 &exynos5_usbdrd_phy_ops); 747 if (IS_ERR(phy)) { 748 dev_err(dev, "Failed to create usbdrd_phy phy\n"); 749 return PTR_ERR(phy); 750 } 751 752 phy_drd->phys[i].phy = phy; 753 phy_drd->phys[i].index = i; 754 phy_drd->phys[i].reg_pmu = reg_pmu; 755 phy_drd->phys[i].pmu_offset = pmu_offset; 756 phy_drd->phys[i].phy_cfg = &drv_data->phy_cfg[i]; 757 phy_set_drvdata(phy, &phy_drd->phys[i]); 758 } 759 760 phy_provider = devm_of_phy_provider_register(dev, 761 exynos5_usbdrd_phy_xlate); 762 if (IS_ERR(phy_provider)) { 763 dev_err(phy_drd->dev, "Failed to register phy provider\n"); 764 return PTR_ERR(phy_provider); 765 } 766 767 return 0; 768} 769 770static struct platform_driver exynos5_usb3drd_phy = { 771 .probe = exynos5_usbdrd_phy_probe, 772 .driver = { 773 .of_match_table = exynos5_usbdrd_phy_of_match, 774 .name = "exynos5_usb3drd_phy", 775 } 776}; 777 778module_platform_driver(exynos5_usb3drd_phy); 779MODULE_DESCRIPTION("Samsung EXYNOS5 SoCs USB 3.0 DRD controller PHY driver"); 780MODULE_AUTHOR("Vivek Gautam <gautam.vivek@samsung.com>"); 781MODULE_LICENSE("GPL v2"); 782MODULE_ALIAS("platform:exynos5_usb3drd_phy"); 783