0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/bitfield.h>
0009 #include <linux/bitops.h>
0010 #include <linux/clk.h>
0011 #include <linux/iopoll.h>
0012 #include <linux/module.h>
0013 #include <linux/of.h>
0014 #include <linux/of_platform.h>
0015 #include <linux/phy/phy.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/reset.h>
0018
0019 struct uniphier_ahciphy_priv {
0020 struct device *dev;
0021 void __iomem *base;
0022 struct clk *clk, *clk_parent, *clk_parent_gio;
0023 struct reset_control *rst, *rst_parent, *rst_parent_gio;
0024 struct reset_control *rst_pm, *rst_tx, *rst_rx;
0025 const struct uniphier_ahciphy_soc_data *data;
0026 };
0027
0028 struct uniphier_ahciphy_soc_data {
0029 int (*init)(struct uniphier_ahciphy_priv *priv);
0030 int (*power_on)(struct uniphier_ahciphy_priv *priv);
0031 int (*power_off)(struct uniphier_ahciphy_priv *priv);
0032 bool is_legacy;
0033 bool is_ready_high;
0034 bool is_phy_clk;
0035 };
0036
0037
0038 #define CKCTRL0 0x0
0039 #define CKCTRL0_CK_OFF BIT(9)
0040 #define CKCTRL0_NCY_MASK GENMASK(8, 4)
0041 #define CKCTRL0_NCY5_MASK GENMASK(3, 2)
0042 #define CKCTRL0_PRESCALE_MASK GENMASK(1, 0)
0043 #define CKCTRL1 0x4
0044 #define CKCTRL1_LOS_LVL_MASK GENMASK(20, 16)
0045 #define CKCTRL1_TX_LVL_MASK GENMASK(12, 8)
0046 #define RXTXCTRL 0x8
0047 #define RXTXCTRL_RX_EQ_VALL_MASK GENMASK(31, 29)
0048 #define RXTXCTRL_RX_DPLL_MODE_MASK GENMASK(28, 26)
0049 #define RXTXCTRL_TX_ATTEN_MASK GENMASK(14, 12)
0050 #define RXTXCTRL_TX_BOOST_MASK GENMASK(11, 8)
0051 #define RXTXCTRL_TX_EDGERATE_MASK GENMASK(3, 2)
0052 #define RXTXCTRL_TX_CKO_EN BIT(0)
0053 #define RSTPWR 0x30
0054 #define RSTPWR_RX_EN_VAL BIT(18)
0055
0056
0057 #define CKCTRL 0x0
0058 #define CKCTRL_P0_READY BIT(15)
0059 #define CKCTRL_P0_RESET BIT(10)
0060 #define CKCTRL_REF_SSP_EN BIT(9)
0061 #define TXCTRL0 0x4
0062 #define TXCTRL0_AMP_G3_MASK GENMASK(22, 16)
0063 #define TXCTRL0_AMP_G2_MASK GENMASK(14, 8)
0064 #define TXCTRL0_AMP_G1_MASK GENMASK(6, 0)
0065 #define TXCTRL1 0x8
0066 #define TXCTRL1_DEEMPH_G3_MASK GENMASK(21, 16)
0067 #define TXCTRL1_DEEMPH_G2_MASK GENMASK(13, 8)
0068 #define TXCTRL1_DEEMPH_G1_MASK GENMASK(5, 0)
0069 #define RXCTRL 0xc
0070 #define RXCTRL_LOS_LVL_MASK GENMASK(20, 16)
0071 #define RXCTRL_LOS_BIAS_MASK GENMASK(10, 8)
0072 #define RXCTRL_RX_EQ_MASK GENMASK(2, 0)
0073
0074 static int uniphier_ahciphy_pro4_init(struct uniphier_ahciphy_priv *priv)
0075 {
0076 u32 val;
0077
0078
0079 val = readl(priv->base + CKCTRL0);
0080 val &= ~CKCTRL0_NCY_MASK;
0081 val |= FIELD_PREP(CKCTRL0_NCY_MASK, 0x6);
0082 val &= ~CKCTRL0_NCY5_MASK;
0083 val |= FIELD_PREP(CKCTRL0_NCY5_MASK, 0x2);
0084 val &= ~CKCTRL0_PRESCALE_MASK;
0085 val |= FIELD_PREP(CKCTRL0_PRESCALE_MASK, 0x1);
0086 writel(val, priv->base + CKCTRL0);
0087
0088
0089 val = readl(priv->base + CKCTRL1);
0090 val &= ~CKCTRL1_LOS_LVL_MASK;
0091 val |= FIELD_PREP(CKCTRL1_LOS_LVL_MASK, 0x10);
0092 val &= ~CKCTRL1_TX_LVL_MASK;
0093 val |= FIELD_PREP(CKCTRL1_TX_LVL_MASK, 0x06);
0094 writel(val, priv->base + CKCTRL1);
0095
0096 val = readl(priv->base + RXTXCTRL);
0097 val &= ~RXTXCTRL_RX_EQ_VALL_MASK;
0098 val |= FIELD_PREP(RXTXCTRL_RX_EQ_VALL_MASK, 0x6);
0099 val &= ~RXTXCTRL_RX_DPLL_MODE_MASK;
0100 val |= FIELD_PREP(RXTXCTRL_RX_DPLL_MODE_MASK, 0x3);
0101 val &= ~RXTXCTRL_TX_ATTEN_MASK;
0102 val |= FIELD_PREP(RXTXCTRL_TX_ATTEN_MASK, 0x3);
0103 val &= ~RXTXCTRL_TX_BOOST_MASK;
0104 val |= FIELD_PREP(RXTXCTRL_TX_BOOST_MASK, 0x5);
0105 val &= ~RXTXCTRL_TX_EDGERATE_MASK;
0106 val |= FIELD_PREP(RXTXCTRL_TX_EDGERATE_MASK, 0x0);
0107 writel(val, priv->base + RXTXCTRL);
0108
0109 return 0;
0110 }
0111
0112 static int uniphier_ahciphy_pro4_power_on(struct uniphier_ahciphy_priv *priv)
0113 {
0114 u32 val;
0115 int ret;
0116
0117
0118 val = readl(priv->base + CKCTRL0);
0119 val &= ~CKCTRL0_CK_OFF;
0120 writel(val, priv->base + CKCTRL0);
0121
0122
0123 val = readl(priv->base + RXTXCTRL);
0124 val |= RXTXCTRL_TX_CKO_EN;
0125 writel(val, priv->base + RXTXCTRL);
0126
0127
0128 ret = readl_poll_timeout(priv->base + RSTPWR, val,
0129 !(val & RSTPWR_RX_EN_VAL), 200, 2000);
0130 if (ret) {
0131 dev_err(priv->dev, "Failed to check whether Rx is ready\n");
0132 goto out_disable_clock;
0133 }
0134
0135
0136 ret = reset_control_deassert(priv->rst_pm);
0137 if (ret) {
0138 dev_err(priv->dev, "Failed to release PM reset\n");
0139 goto out_disable_clock;
0140 }
0141
0142 ret = reset_control_deassert(priv->rst_tx);
0143 if (ret) {
0144 dev_err(priv->dev, "Failed to release Tx reset\n");
0145 goto out_reset_pm_assert;
0146 }
0147
0148 ret = reset_control_deassert(priv->rst_rx);
0149 if (ret) {
0150 dev_err(priv->dev, "Failed to release Rx reset\n");
0151 goto out_reset_tx_assert;
0152 }
0153
0154 return 0;
0155
0156 out_reset_tx_assert:
0157 reset_control_assert(priv->rst_tx);
0158 out_reset_pm_assert:
0159 reset_control_assert(priv->rst_pm);
0160
0161 out_disable_clock:
0162
0163 val = readl(priv->base + RXTXCTRL);
0164 val &= ~RXTXCTRL_TX_CKO_EN;
0165 writel(val, priv->base + RXTXCTRL);
0166
0167
0168 val = readl(priv->base + CKCTRL0);
0169 val |= CKCTRL0_CK_OFF;
0170 writel(val, priv->base + CKCTRL0);
0171
0172 return ret;
0173 }
0174
0175 static int uniphier_ahciphy_pro4_power_off(struct uniphier_ahciphy_priv *priv)
0176 {
0177 u32 val;
0178
0179 reset_control_assert(priv->rst_rx);
0180 reset_control_assert(priv->rst_tx);
0181 reset_control_assert(priv->rst_pm);
0182
0183
0184 val = readl(priv->base + RXTXCTRL);
0185 val &= ~RXTXCTRL_TX_CKO_EN;
0186 writel(val, priv->base + RXTXCTRL);
0187
0188
0189 val = readl(priv->base + CKCTRL0);
0190 val |= CKCTRL0_CK_OFF;
0191 writel(val, priv->base + CKCTRL0);
0192
0193 return 0;
0194 }
0195
0196 static void uniphier_ahciphy_pxs2_enable(struct uniphier_ahciphy_priv *priv,
0197 bool enable)
0198 {
0199 u32 val;
0200
0201 val = readl(priv->base + CKCTRL);
0202
0203 if (enable) {
0204 val |= CKCTRL_REF_SSP_EN;
0205 writel(val, priv->base + CKCTRL);
0206 val &= ~CKCTRL_P0_RESET;
0207 writel(val, priv->base + CKCTRL);
0208 } else {
0209 val |= CKCTRL_P0_RESET;
0210 writel(val, priv->base + CKCTRL);
0211 val &= ~CKCTRL_REF_SSP_EN;
0212 writel(val, priv->base + CKCTRL);
0213 }
0214 }
0215
0216 static int uniphier_ahciphy_pxs2_power_on(struct uniphier_ahciphy_priv *priv)
0217 {
0218 int ret;
0219 u32 val;
0220
0221 uniphier_ahciphy_pxs2_enable(priv, true);
0222
0223
0224 if (priv->data->is_ready_high)
0225 ret = readl_poll_timeout(priv->base + CKCTRL, val,
0226 (val & CKCTRL_P0_READY), 200, 400);
0227 else
0228 ret = readl_poll_timeout(priv->base + CKCTRL, val,
0229 !(val & CKCTRL_P0_READY), 200, 400);
0230 if (ret) {
0231 dev_err(priv->dev, "Failed to check whether PHY PLL is ready\n");
0232 uniphier_ahciphy_pxs2_enable(priv, false);
0233 }
0234
0235 return ret;
0236 }
0237
0238 static int uniphier_ahciphy_pxs2_power_off(struct uniphier_ahciphy_priv *priv)
0239 {
0240 uniphier_ahciphy_pxs2_enable(priv, false);
0241
0242 return 0;
0243 }
0244
0245 static int uniphier_ahciphy_pxs3_init(struct uniphier_ahciphy_priv *priv)
0246 {
0247 int i;
0248 u32 val;
0249
0250
0251 val = readl(priv->base + TXCTRL0);
0252 val &= ~TXCTRL0_AMP_G3_MASK;
0253 val |= FIELD_PREP(TXCTRL0_AMP_G3_MASK, 0x73);
0254 val &= ~TXCTRL0_AMP_G2_MASK;
0255 val |= FIELD_PREP(TXCTRL0_AMP_G2_MASK, 0x46);
0256 val &= ~TXCTRL0_AMP_G1_MASK;
0257 val |= FIELD_PREP(TXCTRL0_AMP_G1_MASK, 0x42);
0258 writel(val, priv->base + TXCTRL0);
0259
0260 val = readl(priv->base + TXCTRL1);
0261 val &= ~TXCTRL1_DEEMPH_G3_MASK;
0262 val |= FIELD_PREP(TXCTRL1_DEEMPH_G3_MASK, 0x23);
0263 val &= ~TXCTRL1_DEEMPH_G2_MASK;
0264 val |= FIELD_PREP(TXCTRL1_DEEMPH_G2_MASK, 0x05);
0265 val &= ~TXCTRL1_DEEMPH_G1_MASK;
0266 val |= FIELD_PREP(TXCTRL1_DEEMPH_G1_MASK, 0x05);
0267
0268 val = readl(priv->base + RXCTRL);
0269 val &= ~RXCTRL_LOS_LVL_MASK;
0270 val |= FIELD_PREP(RXCTRL_LOS_LVL_MASK, 0x9);
0271 val &= ~RXCTRL_LOS_BIAS_MASK;
0272 val |= FIELD_PREP(RXCTRL_LOS_BIAS_MASK, 0x2);
0273 val &= ~RXCTRL_RX_EQ_MASK;
0274 val |= FIELD_PREP(RXCTRL_RX_EQ_MASK, 0x1);
0275
0276
0277 for (i = 0; i < 25; i++)
0278 readl(priv->base + CKCTRL);
0279
0280 return 0;
0281 }
0282
0283 static int uniphier_ahciphy_init(struct phy *phy)
0284 {
0285 struct uniphier_ahciphy_priv *priv = phy_get_drvdata(phy);
0286 int ret;
0287
0288 ret = clk_prepare_enable(priv->clk_parent_gio);
0289 if (ret)
0290 return ret;
0291
0292 ret = clk_prepare_enable(priv->clk_parent);
0293 if (ret)
0294 goto out_clk_gio_disable;
0295
0296 ret = reset_control_deassert(priv->rst_parent_gio);
0297 if (ret)
0298 goto out_clk_disable;
0299
0300 ret = reset_control_deassert(priv->rst_parent);
0301 if (ret)
0302 goto out_rst_gio_assert;
0303
0304 if (priv->data->init) {
0305 ret = priv->data->init(priv);
0306 if (ret)
0307 goto out_rst_assert;
0308 }
0309
0310 return 0;
0311
0312 out_rst_assert:
0313 reset_control_assert(priv->rst_parent);
0314 out_rst_gio_assert:
0315 reset_control_assert(priv->rst_parent_gio);
0316 out_clk_disable:
0317 clk_disable_unprepare(priv->clk_parent);
0318 out_clk_gio_disable:
0319 clk_disable_unprepare(priv->clk_parent_gio);
0320
0321 return ret;
0322 }
0323
0324 static int uniphier_ahciphy_exit(struct phy *phy)
0325 {
0326 struct uniphier_ahciphy_priv *priv = phy_get_drvdata(phy);
0327
0328 reset_control_assert(priv->rst_parent);
0329 reset_control_assert(priv->rst_parent_gio);
0330 clk_disable_unprepare(priv->clk_parent);
0331 clk_disable_unprepare(priv->clk_parent_gio);
0332
0333 return 0;
0334 }
0335
0336 static int uniphier_ahciphy_power_on(struct phy *phy)
0337 {
0338 struct uniphier_ahciphy_priv *priv = phy_get_drvdata(phy);
0339 int ret = 0;
0340
0341 ret = clk_prepare_enable(priv->clk);
0342 if (ret)
0343 return ret;
0344
0345 ret = reset_control_deassert(priv->rst);
0346 if (ret)
0347 goto out_clk_disable;
0348
0349 if (priv->data->power_on) {
0350 ret = priv->data->power_on(priv);
0351 if (ret)
0352 goto out_reset_assert;
0353 }
0354
0355 return 0;
0356
0357 out_reset_assert:
0358 reset_control_assert(priv->rst);
0359 out_clk_disable:
0360 clk_disable_unprepare(priv->clk);
0361
0362 return ret;
0363 }
0364
0365 static int uniphier_ahciphy_power_off(struct phy *phy)
0366 {
0367 struct uniphier_ahciphy_priv *priv = phy_get_drvdata(phy);
0368 int ret = 0;
0369
0370 if (priv->data->power_off)
0371 ret = priv->data->power_off(priv);
0372
0373 reset_control_assert(priv->rst);
0374 clk_disable_unprepare(priv->clk);
0375
0376 return ret;
0377 }
0378
0379 static const struct phy_ops uniphier_ahciphy_ops = {
0380 .init = uniphier_ahciphy_init,
0381 .exit = uniphier_ahciphy_exit,
0382 .power_on = uniphier_ahciphy_power_on,
0383 .power_off = uniphier_ahciphy_power_off,
0384 .owner = THIS_MODULE,
0385 };
0386
0387 static int uniphier_ahciphy_probe(struct platform_device *pdev)
0388 {
0389 struct device *dev = &pdev->dev;
0390 struct uniphier_ahciphy_priv *priv;
0391 struct phy *phy;
0392 struct phy_provider *phy_provider;
0393
0394 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0395 if (!priv)
0396 return -ENOMEM;
0397
0398 priv->dev = dev;
0399 priv->data = of_device_get_match_data(dev);
0400 if (WARN_ON(!priv->data))
0401 return -EINVAL;
0402
0403 priv->base = devm_platform_ioremap_resource(pdev, 0);
0404 if (IS_ERR(priv->base))
0405 return PTR_ERR(priv->base);
0406
0407 priv->clk_parent = devm_clk_get(dev, "link");
0408 if (IS_ERR(priv->clk_parent))
0409 return PTR_ERR(priv->clk_parent);
0410
0411 if (priv->data->is_phy_clk) {
0412 priv->clk = devm_clk_get(dev, "phy");
0413 if (IS_ERR(priv->clk))
0414 return PTR_ERR(priv->clk);
0415 }
0416
0417 priv->rst_parent = devm_reset_control_get_shared(dev, "link");
0418 if (IS_ERR(priv->rst_parent))
0419 return PTR_ERR(priv->rst_parent);
0420
0421 priv->rst = devm_reset_control_get_shared(dev, "phy");
0422 if (IS_ERR(priv->rst))
0423 return PTR_ERR(priv->rst);
0424
0425 if (priv->data->is_legacy) {
0426 priv->clk_parent_gio = devm_clk_get(dev, "gio");
0427 if (IS_ERR(priv->clk_parent_gio))
0428 return PTR_ERR(priv->clk_parent_gio);
0429 priv->rst_parent_gio =
0430 devm_reset_control_get_shared(dev, "gio");
0431 if (IS_ERR(priv->rst_parent_gio))
0432 return PTR_ERR(priv->rst_parent_gio);
0433
0434 priv->rst_pm = devm_reset_control_get_shared(dev, "pm");
0435 if (IS_ERR(priv->rst_pm))
0436 return PTR_ERR(priv->rst_pm);
0437
0438 priv->rst_tx = devm_reset_control_get_shared(dev, "tx");
0439 if (IS_ERR(priv->rst_tx))
0440 return PTR_ERR(priv->rst_tx);
0441
0442 priv->rst_rx = devm_reset_control_get_shared(dev, "rx");
0443 if (IS_ERR(priv->rst_rx))
0444 return PTR_ERR(priv->rst_rx);
0445 }
0446
0447 phy = devm_phy_create(dev, dev->of_node, &uniphier_ahciphy_ops);
0448 if (IS_ERR(phy)) {
0449 dev_err(dev, "failed to create phy\n");
0450 return PTR_ERR(phy);
0451 }
0452
0453 phy_set_drvdata(phy, priv);
0454 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
0455 if (IS_ERR(phy_provider))
0456 return PTR_ERR(phy_provider);
0457
0458 return 0;
0459 }
0460
0461 static const struct uniphier_ahciphy_soc_data uniphier_pro4_data = {
0462 .init = uniphier_ahciphy_pro4_init,
0463 .power_on = uniphier_ahciphy_pro4_power_on,
0464 .power_off = uniphier_ahciphy_pro4_power_off,
0465 .is_legacy = true,
0466 .is_phy_clk = false,
0467 };
0468
0469 static const struct uniphier_ahciphy_soc_data uniphier_pxs2_data = {
0470 .power_on = uniphier_ahciphy_pxs2_power_on,
0471 .power_off = uniphier_ahciphy_pxs2_power_off,
0472 .is_legacy = false,
0473 .is_ready_high = false,
0474 .is_phy_clk = false,
0475 };
0476
0477 static const struct uniphier_ahciphy_soc_data uniphier_pxs3_data = {
0478 .init = uniphier_ahciphy_pxs3_init,
0479 .power_on = uniphier_ahciphy_pxs2_power_on,
0480 .power_off = uniphier_ahciphy_pxs2_power_off,
0481 .is_legacy = false,
0482 .is_ready_high = true,
0483 .is_phy_clk = true,
0484 };
0485
0486 static const struct of_device_id uniphier_ahciphy_match[] = {
0487 {
0488 .compatible = "socionext,uniphier-pro4-ahci-phy",
0489 .data = &uniphier_pro4_data,
0490 },
0491 {
0492 .compatible = "socionext,uniphier-pxs2-ahci-phy",
0493 .data = &uniphier_pxs2_data,
0494 },
0495 {
0496 .compatible = "socionext,uniphier-pxs3-ahci-phy",
0497 .data = &uniphier_pxs3_data,
0498 },
0499 { },
0500 };
0501 MODULE_DEVICE_TABLE(of, uniphier_ahciphy_match);
0502
0503 static struct platform_driver uniphier_ahciphy_driver = {
0504 .probe = uniphier_ahciphy_probe,
0505 .driver = {
0506 .name = "uniphier-ahci-phy",
0507 .of_match_table = uniphier_ahciphy_match,
0508 },
0509 };
0510 module_platform_driver(uniphier_ahciphy_driver);
0511
0512 MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>");
0513 MODULE_DESCRIPTION("UniPhier PHY driver for AHCI controller");
0514 MODULE_LICENSE("GPL v2");