phy-uniphier-ahci.c (13382B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * phy-uniphier-ahci.c - PHY driver for UniPhier AHCI controller 4 * Copyright 2016-2020, Socionext Inc. 5 * Author: Kunihiko Hayashi <hayashi.kunihiko@socionext.com> 6 */ 7 8#include <linux/bitfield.h> 9#include <linux/bitops.h> 10#include <linux/clk.h> 11#include <linux/iopoll.h> 12#include <linux/module.h> 13#include <linux/of.h> 14#include <linux/of_platform.h> 15#include <linux/phy/phy.h> 16#include <linux/platform_device.h> 17#include <linux/reset.h> 18 19struct uniphier_ahciphy_priv { 20 struct device *dev; 21 void __iomem *base; 22 struct clk *clk, *clk_parent, *clk_parent_gio; 23 struct reset_control *rst, *rst_parent, *rst_parent_gio; 24 struct reset_control *rst_pm, *rst_tx, *rst_rx; 25 const struct uniphier_ahciphy_soc_data *data; 26}; 27 28struct uniphier_ahciphy_soc_data { 29 int (*init)(struct uniphier_ahciphy_priv *priv); 30 int (*power_on)(struct uniphier_ahciphy_priv *priv); 31 int (*power_off)(struct uniphier_ahciphy_priv *priv); 32 bool is_legacy; 33 bool is_ready_high; 34 bool is_phy_clk; 35}; 36 37/* for Pro4 */ 38#define CKCTRL0 0x0 39#define CKCTRL0_CK_OFF BIT(9) 40#define CKCTRL0_NCY_MASK GENMASK(8, 4) 41#define CKCTRL0_NCY5_MASK GENMASK(3, 2) 42#define CKCTRL0_PRESCALE_MASK GENMASK(1, 0) 43#define CKCTRL1 0x4 44#define CKCTRL1_LOS_LVL_MASK GENMASK(20, 16) 45#define CKCTRL1_TX_LVL_MASK GENMASK(12, 8) 46#define RXTXCTRL 0x8 47#define RXTXCTRL_RX_EQ_VALL_MASK GENMASK(31, 29) 48#define RXTXCTRL_RX_DPLL_MODE_MASK GENMASK(28, 26) 49#define RXTXCTRL_TX_ATTEN_MASK GENMASK(14, 12) 50#define RXTXCTRL_TX_BOOST_MASK GENMASK(11, 8) 51#define RXTXCTRL_TX_EDGERATE_MASK GENMASK(3, 2) 52#define RXTXCTRL_TX_CKO_EN BIT(0) 53#define RSTPWR 0x30 54#define RSTPWR_RX_EN_VAL BIT(18) 55 56/* for PXs2/PXs3 */ 57#define CKCTRL 0x0 58#define CKCTRL_P0_READY BIT(15) 59#define CKCTRL_P0_RESET BIT(10) 60#define CKCTRL_REF_SSP_EN BIT(9) 61#define TXCTRL0 0x4 62#define TXCTRL0_AMP_G3_MASK GENMASK(22, 16) 63#define TXCTRL0_AMP_G2_MASK GENMASK(14, 8) 64#define TXCTRL0_AMP_G1_MASK GENMASK(6, 0) 65#define TXCTRL1 0x8 66#define TXCTRL1_DEEMPH_G3_MASK GENMASK(21, 16) 67#define TXCTRL1_DEEMPH_G2_MASK GENMASK(13, 8) 68#define TXCTRL1_DEEMPH_G1_MASK GENMASK(5, 0) 69#define RXCTRL 0xc 70#define RXCTRL_LOS_LVL_MASK GENMASK(20, 16) 71#define RXCTRL_LOS_BIAS_MASK GENMASK(10, 8) 72#define RXCTRL_RX_EQ_MASK GENMASK(2, 0) 73 74static int uniphier_ahciphy_pro4_init(struct uniphier_ahciphy_priv *priv) 75{ 76 u32 val; 77 78 /* set phy MPLL parameters */ 79 val = readl(priv->base + CKCTRL0); 80 val &= ~CKCTRL0_NCY_MASK; 81 val |= FIELD_PREP(CKCTRL0_NCY_MASK, 0x6); 82 val &= ~CKCTRL0_NCY5_MASK; 83 val |= FIELD_PREP(CKCTRL0_NCY5_MASK, 0x2); 84 val &= ~CKCTRL0_PRESCALE_MASK; 85 val |= FIELD_PREP(CKCTRL0_PRESCALE_MASK, 0x1); 86 writel(val, priv->base + CKCTRL0); 87 88 /* setup phy control parameters */ 89 val = readl(priv->base + CKCTRL1); 90 val &= ~CKCTRL1_LOS_LVL_MASK; 91 val |= FIELD_PREP(CKCTRL1_LOS_LVL_MASK, 0x10); 92 val &= ~CKCTRL1_TX_LVL_MASK; 93 val |= FIELD_PREP(CKCTRL1_TX_LVL_MASK, 0x06); 94 writel(val, priv->base + CKCTRL1); 95 96 val = readl(priv->base + RXTXCTRL); 97 val &= ~RXTXCTRL_RX_EQ_VALL_MASK; 98 val |= FIELD_PREP(RXTXCTRL_RX_EQ_VALL_MASK, 0x6); 99 val &= ~RXTXCTRL_RX_DPLL_MODE_MASK; 100 val |= FIELD_PREP(RXTXCTRL_RX_DPLL_MODE_MASK, 0x3); 101 val &= ~RXTXCTRL_TX_ATTEN_MASK; 102 val |= FIELD_PREP(RXTXCTRL_TX_ATTEN_MASK, 0x3); 103 val &= ~RXTXCTRL_TX_BOOST_MASK; 104 val |= FIELD_PREP(RXTXCTRL_TX_BOOST_MASK, 0x5); 105 val &= ~RXTXCTRL_TX_EDGERATE_MASK; 106 val |= FIELD_PREP(RXTXCTRL_TX_EDGERATE_MASK, 0x0); 107 writel(val, priv->base + RXTXCTRL); 108 109 return 0; 110} 111 112static int uniphier_ahciphy_pro4_power_on(struct uniphier_ahciphy_priv *priv) 113{ 114 u32 val; 115 int ret; 116 117 /* enable reference clock for phy */ 118 val = readl(priv->base + CKCTRL0); 119 val &= ~CKCTRL0_CK_OFF; 120 writel(val, priv->base + CKCTRL0); 121 122 /* enable TX clock */ 123 val = readl(priv->base + RXTXCTRL); 124 val |= RXTXCTRL_TX_CKO_EN; 125 writel(val, priv->base + RXTXCTRL); 126 127 /* wait until RX is ready */ 128 ret = readl_poll_timeout(priv->base + RSTPWR, val, 129 !(val & RSTPWR_RX_EN_VAL), 200, 2000); 130 if (ret) { 131 dev_err(priv->dev, "Failed to check whether Rx is ready\n"); 132 goto out_disable_clock; 133 } 134 135 /* release all reset */ 136 ret = reset_control_deassert(priv->rst_pm); 137 if (ret) { 138 dev_err(priv->dev, "Failed to release PM reset\n"); 139 goto out_disable_clock; 140 } 141 142 ret = reset_control_deassert(priv->rst_tx); 143 if (ret) { 144 dev_err(priv->dev, "Failed to release Tx reset\n"); 145 goto out_reset_pm_assert; 146 } 147 148 ret = reset_control_deassert(priv->rst_rx); 149 if (ret) { 150 dev_err(priv->dev, "Failed to release Rx reset\n"); 151 goto out_reset_tx_assert; 152 } 153 154 return 0; 155 156out_reset_tx_assert: 157 reset_control_assert(priv->rst_tx); 158out_reset_pm_assert: 159 reset_control_assert(priv->rst_pm); 160 161out_disable_clock: 162 /* disable TX clock */ 163 val = readl(priv->base + RXTXCTRL); 164 val &= ~RXTXCTRL_TX_CKO_EN; 165 writel(val, priv->base + RXTXCTRL); 166 167 /* disable reference clock for phy */ 168 val = readl(priv->base + CKCTRL0); 169 val |= CKCTRL0_CK_OFF; 170 writel(val, priv->base + CKCTRL0); 171 172 return ret; 173} 174 175static int uniphier_ahciphy_pro4_power_off(struct uniphier_ahciphy_priv *priv) 176{ 177 u32 val; 178 179 reset_control_assert(priv->rst_rx); 180 reset_control_assert(priv->rst_tx); 181 reset_control_assert(priv->rst_pm); 182 183 /* disable TX clock */ 184 val = readl(priv->base + RXTXCTRL); 185 val &= ~RXTXCTRL_TX_CKO_EN; 186 writel(val, priv->base + RXTXCTRL); 187 188 /* disable reference clock for phy */ 189 val = readl(priv->base + CKCTRL0); 190 val |= CKCTRL0_CK_OFF; 191 writel(val, priv->base + CKCTRL0); 192 193 return 0; 194} 195 196static void uniphier_ahciphy_pxs2_enable(struct uniphier_ahciphy_priv *priv, 197 bool enable) 198{ 199 u32 val; 200 201 val = readl(priv->base + CKCTRL); 202 203 if (enable) { 204 val |= CKCTRL_REF_SSP_EN; 205 writel(val, priv->base + CKCTRL); 206 val &= ~CKCTRL_P0_RESET; 207 writel(val, priv->base + CKCTRL); 208 } else { 209 val |= CKCTRL_P0_RESET; 210 writel(val, priv->base + CKCTRL); 211 val &= ~CKCTRL_REF_SSP_EN; 212 writel(val, priv->base + CKCTRL); 213 } 214} 215 216static int uniphier_ahciphy_pxs2_power_on(struct uniphier_ahciphy_priv *priv) 217{ 218 int ret; 219 u32 val; 220 221 uniphier_ahciphy_pxs2_enable(priv, true); 222 223 /* wait until PLL is ready */ 224 if (priv->data->is_ready_high) 225 ret = readl_poll_timeout(priv->base + CKCTRL, val, 226 (val & CKCTRL_P0_READY), 200, 400); 227 else 228 ret = readl_poll_timeout(priv->base + CKCTRL, val, 229 !(val & CKCTRL_P0_READY), 200, 400); 230 if (ret) { 231 dev_err(priv->dev, "Failed to check whether PHY PLL is ready\n"); 232 uniphier_ahciphy_pxs2_enable(priv, false); 233 } 234 235 return ret; 236} 237 238static int uniphier_ahciphy_pxs2_power_off(struct uniphier_ahciphy_priv *priv) 239{ 240 uniphier_ahciphy_pxs2_enable(priv, false); 241 242 return 0; 243} 244 245static int uniphier_ahciphy_pxs3_init(struct uniphier_ahciphy_priv *priv) 246{ 247 int i; 248 u32 val; 249 250 /* setup port parameter */ 251 val = readl(priv->base + TXCTRL0); 252 val &= ~TXCTRL0_AMP_G3_MASK; 253 val |= FIELD_PREP(TXCTRL0_AMP_G3_MASK, 0x73); 254 val &= ~TXCTRL0_AMP_G2_MASK; 255 val |= FIELD_PREP(TXCTRL0_AMP_G2_MASK, 0x46); 256 val &= ~TXCTRL0_AMP_G1_MASK; 257 val |= FIELD_PREP(TXCTRL0_AMP_G1_MASK, 0x42); 258 writel(val, priv->base + TXCTRL0); 259 260 val = readl(priv->base + TXCTRL1); 261 val &= ~TXCTRL1_DEEMPH_G3_MASK; 262 val |= FIELD_PREP(TXCTRL1_DEEMPH_G3_MASK, 0x23); 263 val &= ~TXCTRL1_DEEMPH_G2_MASK; 264 val |= FIELD_PREP(TXCTRL1_DEEMPH_G2_MASK, 0x05); 265 val &= ~TXCTRL1_DEEMPH_G1_MASK; 266 val |= FIELD_PREP(TXCTRL1_DEEMPH_G1_MASK, 0x05); 267 268 val = readl(priv->base + RXCTRL); 269 val &= ~RXCTRL_LOS_LVL_MASK; 270 val |= FIELD_PREP(RXCTRL_LOS_LVL_MASK, 0x9); 271 val &= ~RXCTRL_LOS_BIAS_MASK; 272 val |= FIELD_PREP(RXCTRL_LOS_BIAS_MASK, 0x2); 273 val &= ~RXCTRL_RX_EQ_MASK; 274 val |= FIELD_PREP(RXCTRL_RX_EQ_MASK, 0x1); 275 276 /* dummy read 25 times to make a wait time for the phy to stabilize */ 277 for (i = 0; i < 25; i++) 278 readl(priv->base + CKCTRL); 279 280 return 0; 281} 282 283static int uniphier_ahciphy_init(struct phy *phy) 284{ 285 struct uniphier_ahciphy_priv *priv = phy_get_drvdata(phy); 286 int ret; 287 288 ret = clk_prepare_enable(priv->clk_parent_gio); 289 if (ret) 290 return ret; 291 292 ret = clk_prepare_enable(priv->clk_parent); 293 if (ret) 294 goto out_clk_gio_disable; 295 296 ret = reset_control_deassert(priv->rst_parent_gio); 297 if (ret) 298 goto out_clk_disable; 299 300 ret = reset_control_deassert(priv->rst_parent); 301 if (ret) 302 goto out_rst_gio_assert; 303 304 if (priv->data->init) { 305 ret = priv->data->init(priv); 306 if (ret) 307 goto out_rst_assert; 308 } 309 310 return 0; 311 312out_rst_assert: 313 reset_control_assert(priv->rst_parent); 314out_rst_gio_assert: 315 reset_control_assert(priv->rst_parent_gio); 316out_clk_disable: 317 clk_disable_unprepare(priv->clk_parent); 318out_clk_gio_disable: 319 clk_disable_unprepare(priv->clk_parent_gio); 320 321 return ret; 322} 323 324static int uniphier_ahciphy_exit(struct phy *phy) 325{ 326 struct uniphier_ahciphy_priv *priv = phy_get_drvdata(phy); 327 328 reset_control_assert(priv->rst_parent); 329 reset_control_assert(priv->rst_parent_gio); 330 clk_disable_unprepare(priv->clk_parent); 331 clk_disable_unprepare(priv->clk_parent_gio); 332 333 return 0; 334} 335 336static int uniphier_ahciphy_power_on(struct phy *phy) 337{ 338 struct uniphier_ahciphy_priv *priv = phy_get_drvdata(phy); 339 int ret = 0; 340 341 ret = clk_prepare_enable(priv->clk); 342 if (ret) 343 return ret; 344 345 ret = reset_control_deassert(priv->rst); 346 if (ret) 347 goto out_clk_disable; 348 349 if (priv->data->power_on) { 350 ret = priv->data->power_on(priv); 351 if (ret) 352 goto out_reset_assert; 353 } 354 355 return 0; 356 357out_reset_assert: 358 reset_control_assert(priv->rst); 359out_clk_disable: 360 clk_disable_unprepare(priv->clk); 361 362 return ret; 363} 364 365static int uniphier_ahciphy_power_off(struct phy *phy) 366{ 367 struct uniphier_ahciphy_priv *priv = phy_get_drvdata(phy); 368 int ret = 0; 369 370 if (priv->data->power_off) 371 ret = priv->data->power_off(priv); 372 373 reset_control_assert(priv->rst); 374 clk_disable_unprepare(priv->clk); 375 376 return ret; 377} 378 379static const struct phy_ops uniphier_ahciphy_ops = { 380 .init = uniphier_ahciphy_init, 381 .exit = uniphier_ahciphy_exit, 382 .power_on = uniphier_ahciphy_power_on, 383 .power_off = uniphier_ahciphy_power_off, 384 .owner = THIS_MODULE, 385}; 386 387static int uniphier_ahciphy_probe(struct platform_device *pdev) 388{ 389 struct device *dev = &pdev->dev; 390 struct uniphier_ahciphy_priv *priv; 391 struct phy *phy; 392 struct phy_provider *phy_provider; 393 394 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 395 if (!priv) 396 return -ENOMEM; 397 398 priv->dev = dev; 399 priv->data = of_device_get_match_data(dev); 400 if (WARN_ON(!priv->data)) 401 return -EINVAL; 402 403 priv->base = devm_platform_ioremap_resource(pdev, 0); 404 if (IS_ERR(priv->base)) 405 return PTR_ERR(priv->base); 406 407 priv->clk_parent = devm_clk_get(dev, "link"); 408 if (IS_ERR(priv->clk_parent)) 409 return PTR_ERR(priv->clk_parent); 410 411 if (priv->data->is_phy_clk) { 412 priv->clk = devm_clk_get(dev, "phy"); 413 if (IS_ERR(priv->clk)) 414 return PTR_ERR(priv->clk); 415 } 416 417 priv->rst_parent = devm_reset_control_get_shared(dev, "link"); 418 if (IS_ERR(priv->rst_parent)) 419 return PTR_ERR(priv->rst_parent); 420 421 priv->rst = devm_reset_control_get_shared(dev, "phy"); 422 if (IS_ERR(priv->rst)) 423 return PTR_ERR(priv->rst); 424 425 if (priv->data->is_legacy) { 426 priv->clk_parent_gio = devm_clk_get(dev, "gio"); 427 if (IS_ERR(priv->clk_parent_gio)) 428 return PTR_ERR(priv->clk_parent_gio); 429 priv->rst_parent_gio = 430 devm_reset_control_get_shared(dev, "gio"); 431 if (IS_ERR(priv->rst_parent_gio)) 432 return PTR_ERR(priv->rst_parent_gio); 433 434 priv->rst_pm = devm_reset_control_get_shared(dev, "pm"); 435 if (IS_ERR(priv->rst_pm)) 436 return PTR_ERR(priv->rst_pm); 437 438 priv->rst_tx = devm_reset_control_get_shared(dev, "tx"); 439 if (IS_ERR(priv->rst_tx)) 440 return PTR_ERR(priv->rst_tx); 441 442 priv->rst_rx = devm_reset_control_get_shared(dev, "rx"); 443 if (IS_ERR(priv->rst_rx)) 444 return PTR_ERR(priv->rst_rx); 445 } 446 447 phy = devm_phy_create(dev, dev->of_node, &uniphier_ahciphy_ops); 448 if (IS_ERR(phy)) { 449 dev_err(dev, "failed to create phy\n"); 450 return PTR_ERR(phy); 451 } 452 453 phy_set_drvdata(phy, priv); 454 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 455 if (IS_ERR(phy_provider)) 456 return PTR_ERR(phy_provider); 457 458 return 0; 459} 460 461static const struct uniphier_ahciphy_soc_data uniphier_pro4_data = { 462 .init = uniphier_ahciphy_pro4_init, 463 .power_on = uniphier_ahciphy_pro4_power_on, 464 .power_off = uniphier_ahciphy_pro4_power_off, 465 .is_legacy = true, 466 .is_phy_clk = false, 467}; 468 469static const struct uniphier_ahciphy_soc_data uniphier_pxs2_data = { 470 .power_on = uniphier_ahciphy_pxs2_power_on, 471 .power_off = uniphier_ahciphy_pxs2_power_off, 472 .is_legacy = false, 473 .is_ready_high = false, 474 .is_phy_clk = false, 475}; 476 477static const struct uniphier_ahciphy_soc_data uniphier_pxs3_data = { 478 .init = uniphier_ahciphy_pxs3_init, 479 .power_on = uniphier_ahciphy_pxs2_power_on, 480 .power_off = uniphier_ahciphy_pxs2_power_off, 481 .is_legacy = false, 482 .is_ready_high = true, 483 .is_phy_clk = true, 484}; 485 486static const struct of_device_id uniphier_ahciphy_match[] = { 487 { 488 .compatible = "socionext,uniphier-pro4-ahci-phy", 489 .data = &uniphier_pro4_data, 490 }, 491 { 492 .compatible = "socionext,uniphier-pxs2-ahci-phy", 493 .data = &uniphier_pxs2_data, 494 }, 495 { 496 .compatible = "socionext,uniphier-pxs3-ahci-phy", 497 .data = &uniphier_pxs3_data, 498 }, 499 { /* Sentinel */ }, 500}; 501MODULE_DEVICE_TABLE(of, uniphier_ahciphy_match); 502 503static struct platform_driver uniphier_ahciphy_driver = { 504 .probe = uniphier_ahciphy_probe, 505 .driver = { 506 .name = "uniphier-ahci-phy", 507 .of_match_table = uniphier_ahciphy_match, 508 }, 509}; 510module_platform_driver(uniphier_ahciphy_driver); 511 512MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>"); 513MODULE_DESCRIPTION("UniPhier PHY driver for AHCI controller"); 514MODULE_LICENSE("GPL v2");