0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/clk.h>
0010 #include <linux/delay.h>
0011 #include <linux/io.h>
0012 #include <linux/iopoll.h>
0013 #include <linux/module.h>
0014 #include <linux/of.h>
0015 #include <linux/phy/phy.h>
0016 #include <linux/platform_device.h>
0017
0018
0019 #define CTRL_CFG_0 0x00
0020 #define CTRL_CFG_1 0x04
0021 #define CTRL_PRESET_0 0x08
0022 #define CTRL_PRESET_1 0x0c
0023 #define CTRL_PRESET_2 0x10
0024 #define CTRL_PRESET_3 0x14
0025 #define CTRL_PRESET_4 0x18
0026 #define CTRL_CFG_2 0x1c
0027 #define CTRL_CFG_3 0x20
0028 #define PHY_CFG_0 0x24
0029 #define PHY_CFG_1 0x28
0030 #define PHY_CFG_2 0x2c
0031 #define PHYBIST_CTRL 0x30
0032 #define SDHC_STAT3 0x34
0033 #define PHY_STAT 0x38
0034 #define PHYBIST_STAT_0 0x3c
0035 #define PHYBIST_STAT_1 0x40
0036 #define EMMC_AXI 0x44
0037
0038
0039 #define CTRL_PRESET3_MASK GENMASK(31, 0)
0040 #define CTRL_PRESET3_SHIFT 0
0041
0042
0043 #define SUPPORT_HS_MASK BIT(26)
0044 #define SUPPORT_HS_SHIFT 26
0045
0046 #define SUPPORT_8B_MASK BIT(24)
0047 #define SUPPORT_8B_SHIFT 24
0048
0049
0050 #define SUPPORT_SDR50_MASK BIT(28)
0051 #define SUPPORT_SDR50_SHIFT 28
0052 #define SLOT_TYPE_MASK GENMASK(27, 26)
0053 #define SLOT_TYPE_OFFSET 26
0054 #define SUPPORT_64B_MASK BIT(24)
0055 #define SUPPORT_64B_SHIFT 24
0056 #define SUPPORT_HS400_MASK BIT(2)
0057 #define SUPPORT_HS400_SHIFT 2
0058 #define SUPPORT_DDR50_MASK BIT(1)
0059 #define SUPPORT_DDR50_SHIFT 1
0060 #define SUPPORT_SDR104_MASK BIT(0)
0061 #define SUPPORT_SDR104_SHIFT 0
0062
0063
0064 #define SEL_DLY_TXCLK_MASK BIT(29)
0065 #define SEL_DLY_TXCLK_SHIFT 29
0066 #define SEL_DLY_RXCLK_MASK BIT(28)
0067 #define SEL_DLY_RXCLK_SHIFT 28
0068
0069 #define OTAP_DLY_ENA_MASK BIT(27)
0070 #define OTAP_DLY_ENA_SHIFT 27
0071 #define OTAP_DLY_SEL_MASK GENMASK(26, 23)
0072 #define OTAP_DLY_SEL_SHIFT 23
0073 #define ITAP_CHG_WIN_MASK BIT(22)
0074 #define ITAP_CHG_WIN_SHIFT 22
0075 #define ITAP_DLY_ENA_MASK BIT(21)
0076 #define ITAP_DLY_ENA_SHIFT 21
0077 #define ITAP_DLY_SEL_MASK GENMASK(20, 16)
0078 #define ITAP_DLY_SEL_SHIFT 16
0079 #define RET_ENB_MASK BIT(15)
0080 #define RET_ENB_SHIFT 15
0081 #define RET_EN_MASK BIT(14)
0082 #define RET_EN_SHIFT 14
0083 #define DLL_IFF_MASK GENMASK(13, 11)
0084 #define DLL_IFF_SHIFT 11
0085 #define DLL_EN_MASK BIT(10)
0086 #define DLL_EN_SHIFT 10
0087 #define DLL_TRIM_ICP_MASK GENMASK(9, 6)
0088 #define DLL_TRIM_ICP_SHIFT 6
0089 #define RETRIM_EN_MASK BIT(5)
0090 #define RETRIM_EN_SHIFT 5
0091 #define RETRIM_MASK BIT(4)
0092 #define RETRIM_SHIFT 4
0093 #define DR_TY_MASK GENMASK(3, 1)
0094 #define DR_TY_SHIFT 1
0095 #define PWR_DOWN_MASK BIT(0)
0096 #define PWR_DOWN_SHIFT 0
0097
0098
0099 #define REN_DAT_MASK GENMASK(19, 12)
0100 #define REN_DAT_SHIFT 12
0101 #define REN_CMD_MASK BIT(11)
0102 #define REN_CMD_SHIFT 11
0103 #define REN_STRB_MASK BIT(10)
0104 #define REN_STRB_SHIFT 10
0105 #define PU_STRB_MASK BIT(20)
0106 #define PU_STRB_SHIFT 20
0107
0108
0109 #define CLKBUF_MASK GENMASK(24, 21)
0110 #define CLKBUF_SHIFT 21
0111 #define SEL_STRB_MASK GENMASK(20, 13)
0112 #define SEL_STRB_SHIFT 13
0113 #define SEL_FREQ_MASK GENMASK(12, 10)
0114 #define SEL_FREQ_SHIFT 10
0115
0116
0117 #define CAL_DONE BIT(6)
0118 #define DLL_RDY BIT(5)
0119
0120 #define OTAP_DLY 0x0
0121 #define ITAP_DLY 0x0
0122 #define STRB 0x33
0123
0124
0125 #define FREQSEL_200M_170M 0x0
0126 #define FREQSEL_170M_140M 0x1
0127 #define FREQSEL_140M_110M 0x2
0128 #define FREQSEL_110M_80M 0x3
0129 #define FREQSEL_80M_50M 0x4
0130 #define FREQSEL_275M_250M 0x5
0131 #define FREQSEL_250M_225M 0x6
0132 #define FREQSEL_225M_200M 0x7
0133
0134
0135 #define PHY_UNINITIALIZED 0
0136 #define PHY_INITIALIZED 1
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148 struct thunderbay_emmc_phy {
0149 void __iomem *reg_base;
0150 struct clk *emmcclk;
0151 int phy_power_sts;
0152 };
0153
0154 static inline void update_reg(struct thunderbay_emmc_phy *tbh_phy, u32 offset,
0155 u32 mask, u32 shift, u32 val)
0156 {
0157 u32 tmp;
0158
0159 tmp = readl(tbh_phy->reg_base + offset);
0160 tmp &= ~mask;
0161 tmp |= val << shift;
0162 writel(tmp, tbh_phy->reg_base + offset);
0163 }
0164
0165 static int thunderbay_emmc_phy_power(struct phy *phy, bool power_on)
0166 {
0167 struct thunderbay_emmc_phy *tbh_phy = phy_get_drvdata(phy);
0168 unsigned int freqsel = FREQSEL_200M_170M;
0169 unsigned long rate;
0170 static int lock;
0171 u32 val;
0172 int ret;
0173
0174
0175 rate = clk_get_rate(tbh_phy->emmcclk);
0176 switch (rate) {
0177 case 200000000:
0178
0179 update_reg(tbh_phy, PHY_CFG_0, DLL_EN_MASK, DLL_EN_SHIFT, 0x0);
0180 break;
0181
0182
0183 case 50000000 ... 52000000:
0184 case 400000:
0185 default:
0186 break;
0187 }
0188
0189 if (!power_on)
0190 return 0;
0191
0192 rate = clk_get_rate(tbh_phy->emmcclk);
0193 switch (rate) {
0194 case 170000001 ... 200000000:
0195 freqsel = FREQSEL_200M_170M;
0196 break;
0197
0198 case 140000001 ... 170000000:
0199 freqsel = FREQSEL_170M_140M;
0200 break;
0201
0202 case 110000001 ... 140000000:
0203 freqsel = FREQSEL_140M_110M;
0204 break;
0205
0206 case 80000001 ... 110000000:
0207 freqsel = FREQSEL_110M_80M;
0208 break;
0209
0210 case 50000000 ... 80000000:
0211 freqsel = FREQSEL_80M_50M;
0212 break;
0213
0214 case 250000001 ... 275000000:
0215 freqsel = FREQSEL_275M_250M;
0216 break;
0217
0218 case 225000001 ... 250000000:
0219 freqsel = FREQSEL_250M_225M;
0220 break;
0221
0222 case 200000001 ... 225000000:
0223 freqsel = FREQSEL_225M_200M;
0224 break;
0225 default:
0226 break;
0227 }
0228
0229 if (rate > 200000000)
0230 dev_warn(&phy->dev, "Unsupported rate: %lu\n", rate);
0231
0232 udelay(5);
0233
0234 if (lock == 0) {
0235
0236 update_reg(tbh_phy, PHY_CFG_0, PWR_DOWN_MASK,
0237 PWR_DOWN_SHIFT, 0x1);
0238 lock = 1;
0239
0240
0241
0242
0243
0244
0245
0246 ret = readl_poll_timeout(tbh_phy->reg_base + PHY_STAT,
0247 val, (val & CAL_DONE), 10, 50);
0248 if (ret) {
0249 dev_err(&phy->dev, "caldone failed, ret=%d\n", ret);
0250 return ret;
0251 }
0252 }
0253 rate = clk_get_rate(tbh_phy->emmcclk);
0254 switch (rate) {
0255 case 200000000:
0256
0257 update_reg(tbh_phy, PHY_CFG_2, SEL_FREQ_MASK, SEL_FREQ_SHIFT, freqsel);
0258
0259
0260 update_reg(tbh_phy, PHY_CFG_0, DLL_EN_MASK, DLL_EN_SHIFT, 0x1);
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276 ret = readl_poll_timeout(tbh_phy->reg_base + PHY_STAT,
0277 val, (val & DLL_RDY), 10, 50 * USEC_PER_MSEC);
0278 if (ret) {
0279 dev_err(&phy->dev, "dllrdy failed, ret=%d\n", ret);
0280 return ret;
0281 }
0282 break;
0283
0284 default:
0285 break;
0286 }
0287 return 0;
0288 }
0289
0290 static int thunderbay_emmc_phy_init(struct phy *phy)
0291 {
0292 struct thunderbay_emmc_phy *tbh_phy = phy_get_drvdata(phy);
0293
0294 tbh_phy->emmcclk = clk_get(&phy->dev, "emmcclk");
0295
0296 return PTR_ERR_OR_ZERO(tbh_phy->emmcclk);
0297 }
0298
0299 static int thunderbay_emmc_phy_exit(struct phy *phy)
0300 {
0301 struct thunderbay_emmc_phy *tbh_phy = phy_get_drvdata(phy);
0302
0303 clk_put(tbh_phy->emmcclk);
0304
0305 return 0;
0306 }
0307
0308 static int thunderbay_emmc_phy_power_on(struct phy *phy)
0309 {
0310 struct thunderbay_emmc_phy *tbh_phy = phy_get_drvdata(phy);
0311 unsigned long rate;
0312
0313
0314 update_reg(tbh_phy, CTRL_CFG_0,
0315 SUPPORT_HS_MASK, SUPPORT_HS_SHIFT, 0x1);
0316 update_reg(tbh_phy, CTRL_CFG_0,
0317 SUPPORT_8B_MASK, SUPPORT_8B_SHIFT, 0x1);
0318 update_reg(tbh_phy, CTRL_CFG_1,
0319 SUPPORT_SDR50_MASK, SUPPORT_SDR50_SHIFT, 0x1);
0320 update_reg(tbh_phy, CTRL_CFG_1,
0321 SUPPORT_DDR50_MASK, SUPPORT_DDR50_SHIFT, 0x1);
0322 update_reg(tbh_phy, CTRL_CFG_1,
0323 SUPPORT_SDR104_MASK, SUPPORT_SDR104_SHIFT, 0x1);
0324 update_reg(tbh_phy, CTRL_CFG_1,
0325 SUPPORT_HS400_MASK, SUPPORT_HS400_SHIFT, 0x1);
0326 update_reg(tbh_phy, CTRL_CFG_1,
0327 SUPPORT_64B_MASK, SUPPORT_64B_SHIFT, 0x1);
0328
0329 if (tbh_phy->phy_power_sts == PHY_UNINITIALIZED) {
0330
0331 update_reg(tbh_phy, PHY_CFG_0, SEL_DLY_TXCLK_MASK, SEL_DLY_TXCLK_SHIFT, 0x1);
0332 update_reg(tbh_phy, PHY_CFG_0, SEL_DLY_RXCLK_MASK, SEL_DLY_RXCLK_SHIFT, 0x1);
0333 update_reg(tbh_phy, PHY_CFG_0, ITAP_DLY_ENA_MASK, ITAP_DLY_ENA_SHIFT, 0x0);
0334 update_reg(tbh_phy, PHY_CFG_0, ITAP_DLY_SEL_MASK, ITAP_DLY_SEL_SHIFT, 0x0);
0335 update_reg(tbh_phy, PHY_CFG_0, OTAP_DLY_ENA_MASK, OTAP_DLY_ENA_SHIFT, 0x0);
0336 update_reg(tbh_phy, PHY_CFG_0, OTAP_DLY_SEL_MASK, OTAP_DLY_SEL_SHIFT, 0);
0337 update_reg(tbh_phy, PHY_CFG_0, DLL_TRIM_ICP_MASK, DLL_TRIM_ICP_SHIFT, 0);
0338 update_reg(tbh_phy, PHY_CFG_0, DR_TY_MASK, DR_TY_SHIFT, 0x1);
0339
0340 } else if (tbh_phy->phy_power_sts == PHY_INITIALIZED) {
0341
0342 rate = clk_get_rate(tbh_phy->emmcclk);
0343 switch (rate) {
0344 case 200000000:
0345 update_reg(tbh_phy, PHY_CFG_0, SEL_DLY_TXCLK_MASK,
0346 SEL_DLY_TXCLK_SHIFT, 0x0);
0347 update_reg(tbh_phy, PHY_CFG_0, SEL_DLY_RXCLK_MASK,
0348 SEL_DLY_RXCLK_SHIFT, 0x0);
0349 update_reg(tbh_phy, PHY_CFG_0, ITAP_DLY_ENA_MASK,
0350 ITAP_DLY_ENA_SHIFT, 0x0);
0351 update_reg(tbh_phy, PHY_CFG_0, ITAP_DLY_SEL_MASK,
0352 ITAP_DLY_SEL_SHIFT, 0x0);
0353 update_reg(tbh_phy, PHY_CFG_0, OTAP_DLY_ENA_MASK,
0354 OTAP_DLY_ENA_SHIFT, 0x1);
0355 update_reg(tbh_phy, PHY_CFG_0, OTAP_DLY_SEL_MASK,
0356 OTAP_DLY_SEL_SHIFT, 2);
0357 update_reg(tbh_phy, PHY_CFG_0, DLL_TRIM_ICP_MASK,
0358 DLL_TRIM_ICP_SHIFT, 0x8);
0359 update_reg(tbh_phy, PHY_CFG_0, DR_TY_MASK,
0360 DR_TY_SHIFT, 0x1);
0361
0362 update_reg(tbh_phy, PHY_CFG_2, SEL_STRB_MASK,
0363 SEL_STRB_SHIFT, STRB);
0364 break;
0365
0366 case 50000000 ... 52000000:
0367
0368 update_reg(tbh_phy, PHY_CFG_0, SEL_DLY_TXCLK_MASK,
0369 SEL_DLY_TXCLK_SHIFT, 0x1);
0370 update_reg(tbh_phy, PHY_CFG_0, SEL_DLY_RXCLK_MASK,
0371 SEL_DLY_RXCLK_SHIFT, 0x1);
0372 update_reg(tbh_phy, PHY_CFG_0, ITAP_DLY_ENA_MASK,
0373 ITAP_DLY_ENA_SHIFT, 0x0);
0374 update_reg(tbh_phy, PHY_CFG_0, ITAP_DLY_SEL_MASK,
0375 ITAP_DLY_SEL_SHIFT, 0x0);
0376 update_reg(tbh_phy, PHY_CFG_0, OTAP_DLY_ENA_MASK,
0377 OTAP_DLY_ENA_SHIFT, 0x1);
0378 update_reg(tbh_phy, PHY_CFG_0, OTAP_DLY_SEL_MASK,
0379 OTAP_DLY_SEL_SHIFT, 4);
0380 update_reg(tbh_phy, PHY_CFG_0, DLL_TRIM_ICP_MASK,
0381 DLL_TRIM_ICP_SHIFT, 0x8);
0382 update_reg(tbh_phy, PHY_CFG_0,
0383 DR_TY_MASK, DR_TY_SHIFT, 0x1);
0384 break;
0385
0386 case 400000:
0387 update_reg(tbh_phy, PHY_CFG_0, SEL_DLY_TXCLK_MASK,
0388 SEL_DLY_TXCLK_SHIFT, 0x1);
0389 update_reg(tbh_phy, PHY_CFG_0, SEL_DLY_RXCLK_MASK,
0390 SEL_DLY_RXCLK_SHIFT, 0x1);
0391 update_reg(tbh_phy, PHY_CFG_0, ITAP_DLY_ENA_MASK,
0392 ITAP_DLY_ENA_SHIFT, 0x0);
0393 update_reg(tbh_phy, PHY_CFG_0, ITAP_DLY_SEL_MASK,
0394 ITAP_DLY_SEL_SHIFT, 0x0);
0395 update_reg(tbh_phy, PHY_CFG_0, OTAP_DLY_ENA_MASK,
0396 OTAP_DLY_ENA_SHIFT, 0x0);
0397 update_reg(tbh_phy, PHY_CFG_0, OTAP_DLY_SEL_MASK,
0398 OTAP_DLY_SEL_SHIFT, 0);
0399 update_reg(tbh_phy, PHY_CFG_0, DLL_TRIM_ICP_MASK,
0400 DLL_TRIM_ICP_SHIFT, 0);
0401 update_reg(tbh_phy, PHY_CFG_0, DR_TY_MASK, DR_TY_SHIFT, 0x1);
0402 break;
0403
0404 default:
0405 update_reg(tbh_phy, PHY_CFG_0, SEL_DLY_TXCLK_MASK,
0406 SEL_DLY_TXCLK_SHIFT, 0x1);
0407 update_reg(tbh_phy, PHY_CFG_0, SEL_DLY_RXCLK_MASK,
0408 SEL_DLY_RXCLK_SHIFT, 0x1);
0409 update_reg(tbh_phy, PHY_CFG_0, ITAP_DLY_ENA_MASK,
0410 ITAP_DLY_ENA_SHIFT, 0x0);
0411 update_reg(tbh_phy, PHY_CFG_0, ITAP_DLY_SEL_MASK,
0412 ITAP_DLY_SEL_SHIFT, 0x0);
0413 update_reg(tbh_phy, PHY_CFG_0, OTAP_DLY_ENA_MASK,
0414 OTAP_DLY_ENA_SHIFT, 0x1);
0415 update_reg(tbh_phy, PHY_CFG_0, OTAP_DLY_SEL_MASK,
0416 OTAP_DLY_SEL_SHIFT, 2);
0417 update_reg(tbh_phy, PHY_CFG_0, DLL_TRIM_ICP_MASK,
0418 DLL_TRIM_ICP_SHIFT, 0x8);
0419 update_reg(tbh_phy, PHY_CFG_0, DR_TY_MASK,
0420 DR_TY_SHIFT, 0x1);
0421 break;
0422 }
0423
0424 tbh_phy->phy_power_sts = PHY_UNINITIALIZED;
0425 }
0426
0427 update_reg(tbh_phy, PHY_CFG_0, RETRIM_EN_MASK, RETRIM_EN_SHIFT, 0x1);
0428 update_reg(tbh_phy, PHY_CFG_0, RETRIM_MASK, RETRIM_SHIFT, 0x0);
0429
0430 return thunderbay_emmc_phy_power(phy, 1);
0431 }
0432
0433 static int thunderbay_emmc_phy_power_off(struct phy *phy)
0434 {
0435 struct thunderbay_emmc_phy *tbh_phy = phy_get_drvdata(phy);
0436
0437 tbh_phy->phy_power_sts = PHY_INITIALIZED;
0438
0439 return thunderbay_emmc_phy_power(phy, 0);
0440 }
0441
0442 static const struct phy_ops thunderbay_emmc_phy_ops = {
0443 .init = thunderbay_emmc_phy_init,
0444 .exit = thunderbay_emmc_phy_exit,
0445 .power_on = thunderbay_emmc_phy_power_on,
0446 .power_off = thunderbay_emmc_phy_power_off,
0447 .owner = THIS_MODULE,
0448 };
0449
0450 static const struct of_device_id thunderbay_emmc_phy_of_match[] = {
0451 { .compatible = "intel,thunderbay-emmc-phy",
0452 (void *)&thunderbay_emmc_phy_ops },
0453 {}
0454 };
0455 MODULE_DEVICE_TABLE(of, thunderbay_emmc_phy_of_match);
0456
0457 static int thunderbay_emmc_phy_probe(struct platform_device *pdev)
0458 {
0459 struct thunderbay_emmc_phy *tbh_phy;
0460 struct phy_provider *phy_provider;
0461 struct device *dev = &pdev->dev;
0462 const struct of_device_id *id;
0463 struct phy *generic_phy;
0464 struct resource *res;
0465
0466 if (!dev->of_node)
0467 return -ENODEV;
0468
0469 tbh_phy = devm_kzalloc(dev, sizeof(*tbh_phy), GFP_KERNEL);
0470 if (!tbh_phy)
0471 return -ENOMEM;
0472
0473 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0474 tbh_phy->reg_base = devm_ioremap_resource(&pdev->dev, res);
0475 if (IS_ERR(tbh_phy->reg_base))
0476 return PTR_ERR(tbh_phy->reg_base);
0477
0478 tbh_phy->phy_power_sts = PHY_UNINITIALIZED;
0479 id = of_match_node(thunderbay_emmc_phy_of_match, pdev->dev.of_node);
0480 if (!id) {
0481 dev_err(dev, "failed to get match_node\n");
0482 return -EINVAL;
0483 }
0484
0485 generic_phy = devm_phy_create(dev, dev->of_node, id->data);
0486 if (IS_ERR(generic_phy)) {
0487 dev_err(dev, "failed to create PHY\n");
0488 return PTR_ERR(generic_phy);
0489 }
0490
0491 phy_set_drvdata(generic_phy, tbh_phy);
0492 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
0493
0494 return PTR_ERR_OR_ZERO(phy_provider);
0495 }
0496
0497 static struct platform_driver thunderbay_emmc_phy_driver = {
0498 .probe = thunderbay_emmc_phy_probe,
0499 .driver = {
0500 .name = "thunderbay-emmc-phy",
0501 .of_match_table = thunderbay_emmc_phy_of_match,
0502 },
0503 };
0504 module_platform_driver(thunderbay_emmc_phy_driver);
0505
0506 MODULE_AUTHOR("Nandhini S <nandhini.srikandan@intel.com>");
0507 MODULE_AUTHOR("Rashmi A <rashmi.a@intel.com>");
0508 MODULE_DESCRIPTION("Intel Thunder Bay eMMC PHY driver");
0509 MODULE_LICENSE("GPL v2");