linux/drivers/phy/intel/phy-intel-keembay-emmc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Intel Keem Bay eMMC PHY driver
   4 * Copyright (C) 2020 Intel Corporation
   5 */
   6
   7#include <linux/bitfield.h>
   8#include <linux/clk.h>
   9#include <linux/delay.h>
  10#include <linux/mfd/syscon.h>
  11#include <linux/module.h>
  12#include <linux/of.h>
  13#include <linux/of_address.h>
  14#include <linux/phy/phy.h>
  15#include <linux/platform_device.h>
  16#include <linux/regmap.h>
  17
  18/* eMMC/SD/SDIO core/phy configuration registers */
  19#define PHY_CFG_0               0x24
  20#define  SEL_DLY_TXCLK_MASK     BIT(29)
  21#define  OTAP_DLY_ENA_MASK      BIT(27)
  22#define  OTAP_DLY_SEL_MASK      GENMASK(26, 23)
  23#define  DLL_EN_MASK            BIT(10)
  24#define  PWR_DOWN_MASK          BIT(0)
  25
  26#define PHY_CFG_2               0x2c
  27#define  SEL_FREQ_MASK          GENMASK(12, 10)
  28
  29#define PHY_STAT                0x40
  30#define  CAL_DONE_MASK          BIT(6)
  31#define  IS_CALDONE(x)          ((x) & CAL_DONE_MASK)
  32#define  DLL_RDY_MASK           BIT(5)
  33#define  IS_DLLRDY(x)           ((x) & DLL_RDY_MASK)
  34
  35/* From ACS_eMMC51_16nFFC_RO1100_Userguide_v1p0.pdf p17 */
  36#define FREQSEL_200M_170M       0x0
  37#define FREQSEL_170M_140M       0x1
  38#define FREQSEL_140M_110M       0x2
  39#define FREQSEL_110M_80M        0x3
  40#define FREQSEL_80M_50M         0x4
  41
  42struct keembay_emmc_phy {
  43        struct regmap *syscfg;
  44        struct clk *emmcclk;
  45};
  46
  47static const struct regmap_config keembay_regmap_config = {
  48        .reg_bits = 32,
  49        .val_bits = 32,
  50        .reg_stride = 4,
  51};
  52
  53static int keembay_emmc_phy_power(struct phy *phy, bool on_off)
  54{
  55        struct keembay_emmc_phy *priv = phy_get_drvdata(phy);
  56        unsigned int caldone;
  57        unsigned int dllrdy;
  58        unsigned int freqsel;
  59        unsigned int mhz;
  60        int ret;
  61
  62        /*
  63         * Keep phyctrl_pdb and phyctrl_endll low to allow
  64         * initialization of CALIO state M/C DFFs
  65         */
  66        ret = regmap_update_bits(priv->syscfg, PHY_CFG_0, PWR_DOWN_MASK,
  67                                 FIELD_PREP(PWR_DOWN_MASK, 0));
  68        if (ret) {
  69                dev_err(&phy->dev, "CALIO power down bar failed: %d\n", ret);
  70                return ret;
  71        }
  72
  73        ret = regmap_update_bits(priv->syscfg, PHY_CFG_0, DLL_EN_MASK,
  74                                 FIELD_PREP(DLL_EN_MASK, 0));
  75        if (ret) {
  76                dev_err(&phy->dev, "turn off the dll failed: %d\n", ret);
  77                return ret;
  78        }
  79
  80        /* Already finish power off above */
  81        if (!on_off)
  82                return 0;
  83
  84        mhz = DIV_ROUND_CLOSEST(clk_get_rate(priv->emmcclk), 1000000);
  85        if (mhz <= 200 && mhz >= 170)
  86                freqsel = FREQSEL_200M_170M;
  87        else if (mhz <= 170 && mhz >= 140)
  88                freqsel = FREQSEL_170M_140M;
  89        else if (mhz <= 140 && mhz >= 110)
  90                freqsel = FREQSEL_140M_110M;
  91        else if (mhz <= 110 && mhz >= 80)
  92                freqsel = FREQSEL_110M_80M;
  93        else if (mhz <= 80 && mhz >= 50)
  94                freqsel = FREQSEL_80M_50M;
  95        else
  96                freqsel = 0x0;
  97
  98        /* Check for EMMC clock rate*/
  99        if (mhz > 175)
 100                dev_warn(&phy->dev, "Unsupported rate: %d MHz\n", mhz);
 101
 102        /*
 103         * According to the user manual, calpad calibration
 104         * cycle takes more than 2us without the minimal recommended
 105         * value, so we may need a little margin here
 106         */
 107        udelay(5);
 108
 109        ret = regmap_update_bits(priv->syscfg, PHY_CFG_0, PWR_DOWN_MASK,
 110                                 FIELD_PREP(PWR_DOWN_MASK, 1));
 111        if (ret) {
 112                dev_err(&phy->dev, "CALIO power down bar failed: %d\n", ret);
 113                return ret;
 114        }
 115
 116        /*
 117         * According to the user manual, it asks driver to wait 5us for
 118         * calpad busy trimming. However it is documented that this value is
 119         * PVT(A.K.A. process, voltage and temperature) relevant, so some
 120         * failure cases are found which indicates we should be more tolerant
 121         * to calpad busy trimming.
 122         */
 123        ret = regmap_read_poll_timeout(priv->syscfg, PHY_STAT,
 124                                       caldone, IS_CALDONE(caldone),
 125                                       0, 50);
 126        if (ret) {
 127                dev_err(&phy->dev, "caldone failed, ret=%d\n", ret);
 128                return ret;
 129        }
 130
 131        /* Set the frequency of the DLL operation */
 132        ret = regmap_update_bits(priv->syscfg, PHY_CFG_2, SEL_FREQ_MASK,
 133                                 FIELD_PREP(SEL_FREQ_MASK, freqsel));
 134        if (ret) {
 135                dev_err(&phy->dev, "set the frequency of dll failed:%d\n", ret);
 136                return ret;
 137        }
 138
 139        /* Turn on the DLL */
 140        ret = regmap_update_bits(priv->syscfg, PHY_CFG_0, DLL_EN_MASK,
 141                                 FIELD_PREP(DLL_EN_MASK, 1));
 142        if (ret) {
 143                dev_err(&phy->dev, "turn on the dll failed: %d\n", ret);
 144                return ret;
 145        }
 146
 147        /*
 148         * We turned on the DLL even though the rate was 0 because we the
 149         * clock might be turned on later.  ...but we can't wait for the DLL
 150         * to lock when the rate is 0 because it will never lock with no
 151         * input clock.
 152         *
 153         * Technically we should be checking the lock later when the clock
 154         * is turned on, but for now we won't.
 155         */
 156        if (mhz == 0)
 157                return 0;
 158
 159        /*
 160         * After enabling analog DLL circuits docs say that we need 10.2 us if
 161         * our source clock is at 50 MHz and that lock time scales linearly
 162         * with clock speed. If we are powering on the PHY and the card clock
 163         * is super slow (like 100kHz) this could take as long as 5.1 ms as
 164         * per the math: 10.2 us * (50000000 Hz / 100000 Hz) => 5.1 ms
 165         * hopefully we won't be running at 100 kHz, but we should still make
 166         * sure we wait long enough.
 167         *
 168         * NOTE: There appear to be corner cases where the DLL seems to take
 169         * extra long to lock for reasons that aren't understood. In some
 170         * extreme cases we've seen it take up to over 10ms (!). We'll be
 171         * generous and give it 50ms.
 172         */
 173        ret = regmap_read_poll_timeout(priv->syscfg, PHY_STAT,
 174                                       dllrdy, IS_DLLRDY(dllrdy),
 175                                       0, 50 * USEC_PER_MSEC);
 176        if (ret)
 177                dev_err(&phy->dev, "dllrdy failed, ret=%d\n", ret);
 178
 179        return ret;
 180}
 181
 182static int keembay_emmc_phy_init(struct phy *phy)
 183{
 184        struct keembay_emmc_phy *priv = phy_get_drvdata(phy);
 185
 186        /*
 187         * We purposely get the clock here and not in probe to avoid the
 188         * circular dependency problem. We expect:
 189         * - PHY driver to probe
 190         * - SDHCI driver to start probe
 191         * - SDHCI driver to register it's clock
 192         * - SDHCI driver to get the PHY
 193         * - SDHCI driver to init the PHY
 194         *
 195         * The clock is optional, so upon any error just return it like
 196         * any other error to user.
 197         */
 198        priv->emmcclk = clk_get_optional(&phy->dev, "emmcclk");
 199
 200        return PTR_ERR_OR_ZERO(priv->emmcclk);
 201}
 202
 203static int keembay_emmc_phy_exit(struct phy *phy)
 204{
 205        struct keembay_emmc_phy *priv = phy_get_drvdata(phy);
 206
 207        clk_put(priv->emmcclk);
 208
 209        return 0;
 210};
 211
 212static int keembay_emmc_phy_power_on(struct phy *phy)
 213{
 214        struct keembay_emmc_phy *priv = phy_get_drvdata(phy);
 215        int ret;
 216
 217        /* Delay chain based txclk: enable */
 218        ret = regmap_update_bits(priv->syscfg, PHY_CFG_0, SEL_DLY_TXCLK_MASK,
 219                                 FIELD_PREP(SEL_DLY_TXCLK_MASK, 1));
 220        if (ret) {
 221                dev_err(&phy->dev, "ERROR: delay chain txclk set: %d\n", ret);
 222                return ret;
 223        }
 224
 225        /* Output tap delay: enable */
 226        ret = regmap_update_bits(priv->syscfg, PHY_CFG_0, OTAP_DLY_ENA_MASK,
 227                                 FIELD_PREP(OTAP_DLY_ENA_MASK, 1));
 228        if (ret) {
 229                dev_err(&phy->dev, "ERROR: output tap delay set: %d\n", ret);
 230                return ret;
 231        }
 232
 233        /* Output tap delay */
 234        ret = regmap_update_bits(priv->syscfg, PHY_CFG_0, OTAP_DLY_SEL_MASK,
 235                                 FIELD_PREP(OTAP_DLY_SEL_MASK, 2));
 236        if (ret) {
 237                dev_err(&phy->dev, "ERROR: output tap delay select: %d\n", ret);
 238                return ret;
 239        }
 240
 241        /* Power up eMMC phy analog blocks */
 242        return keembay_emmc_phy_power(phy, true);
 243}
 244
 245static int keembay_emmc_phy_power_off(struct phy *phy)
 246{
 247        /* Power down eMMC phy analog blocks */
 248        return keembay_emmc_phy_power(phy, false);
 249}
 250
 251static const struct phy_ops ops = {
 252        .init           = keembay_emmc_phy_init,
 253        .exit           = keembay_emmc_phy_exit,
 254        .power_on       = keembay_emmc_phy_power_on,
 255        .power_off      = keembay_emmc_phy_power_off,
 256        .owner          = THIS_MODULE,
 257};
 258
 259static int keembay_emmc_phy_probe(struct platform_device *pdev)
 260{
 261        struct device *dev = &pdev->dev;
 262        struct device_node *np = dev->of_node;
 263        struct keembay_emmc_phy *priv;
 264        struct phy *generic_phy;
 265        struct phy_provider *phy_provider;
 266        void __iomem *base;
 267
 268        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 269        if (!priv)
 270                return -ENOMEM;
 271
 272        base = devm_platform_ioremap_resource(pdev, 0);
 273        if (IS_ERR(base))
 274                return PTR_ERR(base);
 275
 276        priv->syscfg = devm_regmap_init_mmio(dev, base, &keembay_regmap_config);
 277        if (IS_ERR(priv->syscfg))
 278                return PTR_ERR(priv->syscfg);
 279
 280        generic_phy = devm_phy_create(dev, np, &ops);
 281        if (IS_ERR(generic_phy))
 282                return dev_err_probe(dev, PTR_ERR(generic_phy),
 283                                     "failed to create PHY\n");
 284
 285        phy_set_drvdata(generic_phy, priv);
 286        phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
 287
 288        return PTR_ERR_OR_ZERO(phy_provider);
 289}
 290
 291static const struct of_device_id keembay_emmc_phy_dt_ids[] = {
 292        { .compatible = "intel,keembay-emmc-phy" },
 293        {}
 294};
 295MODULE_DEVICE_TABLE(of, keembay_emmc_phy_dt_ids);
 296
 297static struct platform_driver keembay_emmc_phy_driver = {
 298        .probe          = keembay_emmc_phy_probe,
 299        .driver         = {
 300                .name   = "keembay-emmc-phy",
 301                .of_match_table = keembay_emmc_phy_dt_ids,
 302        },
 303};
 304module_platform_driver(keembay_emmc_phy_driver);
 305
 306MODULE_AUTHOR("Wan Ahmad Zainie <wan.ahmad.zainie.wan.mohamad@intel.com>");
 307MODULE_DESCRIPTION("Intel Keem Bay eMMC PHY driver");
 308MODULE_LICENSE("GPL v2");
 309