0001
0002
0003
0004
0005
0006
0007 #include <linux/bitfield.h>
0008 #include <linux/clk.h>
0009 #include <linux/delay.h>
0010 #include <linux/mfd/syscon.h>
0011 #include <linux/module.h>
0012 #include <linux/of.h>
0013 #include <linux/of_address.h>
0014 #include <linux/phy/phy.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/regmap.h>
0017
0018
0019 #define PHY_CFG_0 0x24
0020 #define SEL_DLY_TXCLK_MASK BIT(29)
0021 #define OTAP_DLY_ENA_MASK BIT(27)
0022 #define OTAP_DLY_SEL_MASK GENMASK(26, 23)
0023 #define DLL_EN_MASK BIT(10)
0024 #define PWR_DOWN_MASK BIT(0)
0025
0026 #define PHY_CFG_2 0x2c
0027 #define SEL_FREQ_MASK GENMASK(12, 10)
0028
0029 #define PHY_STAT 0x40
0030 #define CAL_DONE_MASK BIT(6)
0031 #define IS_CALDONE(x) ((x) & CAL_DONE_MASK)
0032 #define DLL_RDY_MASK BIT(5)
0033 #define IS_DLLRDY(x) ((x) & DLL_RDY_MASK)
0034
0035
0036 #define FREQSEL_200M_170M 0x0
0037 #define FREQSEL_170M_140M 0x1
0038 #define FREQSEL_140M_110M 0x2
0039 #define FREQSEL_110M_80M 0x3
0040 #define FREQSEL_80M_50M 0x4
0041
0042 struct keembay_emmc_phy {
0043 struct regmap *syscfg;
0044 struct clk *emmcclk;
0045 };
0046
0047 static const struct regmap_config keembay_regmap_config = {
0048 .reg_bits = 32,
0049 .val_bits = 32,
0050 .reg_stride = 4,
0051 };
0052
0053 static int keembay_emmc_phy_power(struct phy *phy, bool on_off)
0054 {
0055 struct keembay_emmc_phy *priv = phy_get_drvdata(phy);
0056 unsigned int caldone;
0057 unsigned int dllrdy;
0058 unsigned int freqsel;
0059 unsigned int mhz;
0060 int ret;
0061
0062
0063
0064
0065
0066 ret = regmap_update_bits(priv->syscfg, PHY_CFG_0, PWR_DOWN_MASK,
0067 FIELD_PREP(PWR_DOWN_MASK, 0));
0068 if (ret) {
0069 dev_err(&phy->dev, "CALIO power down bar failed: %d\n", ret);
0070 return ret;
0071 }
0072
0073 ret = regmap_update_bits(priv->syscfg, PHY_CFG_0, DLL_EN_MASK,
0074 FIELD_PREP(DLL_EN_MASK, 0));
0075 if (ret) {
0076 dev_err(&phy->dev, "turn off the dll failed: %d\n", ret);
0077 return ret;
0078 }
0079
0080
0081 if (!on_off)
0082 return 0;
0083
0084 mhz = DIV_ROUND_CLOSEST(clk_get_rate(priv->emmcclk), 1000000);
0085 if (mhz <= 200 && mhz >= 170)
0086 freqsel = FREQSEL_200M_170M;
0087 else if (mhz <= 170 && mhz >= 140)
0088 freqsel = FREQSEL_170M_140M;
0089 else if (mhz <= 140 && mhz >= 110)
0090 freqsel = FREQSEL_140M_110M;
0091 else if (mhz <= 110 && mhz >= 80)
0092 freqsel = FREQSEL_110M_80M;
0093 else if (mhz <= 80 && mhz >= 50)
0094 freqsel = FREQSEL_80M_50M;
0095 else
0096 freqsel = 0x0;
0097
0098
0099 if (mhz > 175)
0100 dev_warn(&phy->dev, "Unsupported rate: %d MHz\n", mhz);
0101
0102
0103
0104
0105
0106
0107 udelay(5);
0108
0109 ret = regmap_update_bits(priv->syscfg, PHY_CFG_0, PWR_DOWN_MASK,
0110 FIELD_PREP(PWR_DOWN_MASK, 1));
0111 if (ret) {
0112 dev_err(&phy->dev, "CALIO power down bar failed: %d\n", ret);
0113 return ret;
0114 }
0115
0116
0117
0118
0119
0120
0121
0122
0123 ret = regmap_read_poll_timeout(priv->syscfg, PHY_STAT,
0124 caldone, IS_CALDONE(caldone),
0125 0, 50);
0126 if (ret) {
0127 dev_err(&phy->dev, "caldone failed, ret=%d\n", ret);
0128 return ret;
0129 }
0130
0131
0132 ret = regmap_update_bits(priv->syscfg, PHY_CFG_2, SEL_FREQ_MASK,
0133 FIELD_PREP(SEL_FREQ_MASK, freqsel));
0134 if (ret) {
0135 dev_err(&phy->dev, "set the frequency of dll failed:%d\n", ret);
0136 return ret;
0137 }
0138
0139
0140 ret = regmap_update_bits(priv->syscfg, PHY_CFG_0, DLL_EN_MASK,
0141 FIELD_PREP(DLL_EN_MASK, 1));
0142 if (ret) {
0143 dev_err(&phy->dev, "turn on the dll failed: %d\n", ret);
0144 return ret;
0145 }
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156 if (mhz == 0)
0157 return 0;
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173 ret = regmap_read_poll_timeout(priv->syscfg, PHY_STAT,
0174 dllrdy, IS_DLLRDY(dllrdy),
0175 0, 50 * USEC_PER_MSEC);
0176 if (ret)
0177 dev_err(&phy->dev, "dllrdy failed, ret=%d\n", ret);
0178
0179 return ret;
0180 }
0181
0182 static int keembay_emmc_phy_init(struct phy *phy)
0183 {
0184 struct keembay_emmc_phy *priv = phy_get_drvdata(phy);
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198 priv->emmcclk = clk_get_optional(&phy->dev, "emmcclk");
0199
0200 return PTR_ERR_OR_ZERO(priv->emmcclk);
0201 }
0202
0203 static int keembay_emmc_phy_exit(struct phy *phy)
0204 {
0205 struct keembay_emmc_phy *priv = phy_get_drvdata(phy);
0206
0207 clk_put(priv->emmcclk);
0208
0209 return 0;
0210 };
0211
0212 static int keembay_emmc_phy_power_on(struct phy *phy)
0213 {
0214 struct keembay_emmc_phy *priv = phy_get_drvdata(phy);
0215 int ret;
0216
0217
0218 ret = regmap_update_bits(priv->syscfg, PHY_CFG_0, SEL_DLY_TXCLK_MASK,
0219 FIELD_PREP(SEL_DLY_TXCLK_MASK, 1));
0220 if (ret) {
0221 dev_err(&phy->dev, "ERROR: delay chain txclk set: %d\n", ret);
0222 return ret;
0223 }
0224
0225
0226 ret = regmap_update_bits(priv->syscfg, PHY_CFG_0, OTAP_DLY_ENA_MASK,
0227 FIELD_PREP(OTAP_DLY_ENA_MASK, 1));
0228 if (ret) {
0229 dev_err(&phy->dev, "ERROR: output tap delay set: %d\n", ret);
0230 return ret;
0231 }
0232
0233
0234 ret = regmap_update_bits(priv->syscfg, PHY_CFG_0, OTAP_DLY_SEL_MASK,
0235 FIELD_PREP(OTAP_DLY_SEL_MASK, 2));
0236 if (ret) {
0237 dev_err(&phy->dev, "ERROR: output tap delay select: %d\n", ret);
0238 return ret;
0239 }
0240
0241
0242 return keembay_emmc_phy_power(phy, true);
0243 }
0244
0245 static int keembay_emmc_phy_power_off(struct phy *phy)
0246 {
0247
0248 return keembay_emmc_phy_power(phy, false);
0249 }
0250
0251 static const struct phy_ops ops = {
0252 .init = keembay_emmc_phy_init,
0253 .exit = keembay_emmc_phy_exit,
0254 .power_on = keembay_emmc_phy_power_on,
0255 .power_off = keembay_emmc_phy_power_off,
0256 .owner = THIS_MODULE,
0257 };
0258
0259 static int keembay_emmc_phy_probe(struct platform_device *pdev)
0260 {
0261 struct device *dev = &pdev->dev;
0262 struct device_node *np = dev->of_node;
0263 struct keembay_emmc_phy *priv;
0264 struct phy *generic_phy;
0265 struct phy_provider *phy_provider;
0266 void __iomem *base;
0267
0268 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0269 if (!priv)
0270 return -ENOMEM;
0271
0272 base = devm_platform_ioremap_resource(pdev, 0);
0273 if (IS_ERR(base))
0274 return PTR_ERR(base);
0275
0276 priv->syscfg = devm_regmap_init_mmio(dev, base, &keembay_regmap_config);
0277 if (IS_ERR(priv->syscfg))
0278 return PTR_ERR(priv->syscfg);
0279
0280 generic_phy = devm_phy_create(dev, np, &ops);
0281 if (IS_ERR(generic_phy))
0282 return dev_err_probe(dev, PTR_ERR(generic_phy),
0283 "failed to create PHY\n");
0284
0285 phy_set_drvdata(generic_phy, priv);
0286 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
0287
0288 return PTR_ERR_OR_ZERO(phy_provider);
0289 }
0290
0291 static const struct of_device_id keembay_emmc_phy_dt_ids[] = {
0292 { .compatible = "intel,keembay-emmc-phy" },
0293 {}
0294 };
0295 MODULE_DEVICE_TABLE(of, keembay_emmc_phy_dt_ids);
0296
0297 static struct platform_driver keembay_emmc_phy_driver = {
0298 .probe = keembay_emmc_phy_probe,
0299 .driver = {
0300 .name = "keembay-emmc-phy",
0301 .of_match_table = keembay_emmc_phy_dt_ids,
0302 },
0303 };
0304 module_platform_driver(keembay_emmc_phy_driver);
0305
0306 MODULE_AUTHOR("Wan Ahmad Zainie <wan.ahmad.zainie.wan.mohamad@intel.com>");
0307 MODULE_DESCRIPTION("Intel Keem Bay eMMC PHY driver");
0308 MODULE_LICENSE("GPL v2");