Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Copyright 2017-2020,2022 NXP
0004  */
0005 
0006 #include <linux/bitfield.h>
0007 #include <linux/bits.h>
0008 #include <linux/clk.h>
0009 #include <linux/mfd/syscon.h>
0010 #include <linux/module.h>
0011 #include <linux/of.h>
0012 #include <linux/phy/phy.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/pm_runtime.h>
0015 #include <linux/regmap.h>
0016 #include <linux/units.h>
0017 
0018 #define REG_SET     0x4
0019 #define REG_CLR     0x8
0020 
0021 #define PHY_CTRL    0x0
0022 #define  M_MASK     GENMASK(18, 17)
0023 #define  M(n)       FIELD_PREP(M_MASK, (n))
0024 #define  CCM_MASK   GENMASK(16, 14)
0025 #define  CCM(n)     FIELD_PREP(CCM_MASK, (n))
0026 #define  CA_MASK    GENMASK(13, 11)
0027 #define  CA(n)      FIELD_PREP(CA_MASK, (n))
0028 #define  TST_MASK   GENMASK(10, 5)
0029 #define  TST(n)     FIELD_PREP(TST_MASK, (n))
0030 #define  CH_EN(id)  BIT(3 + (id))
0031 #define  NB     BIT(2)
0032 #define  RFB        BIT(1)
0033 #define  PD     BIT(0)
0034 
0035 /* Power On Reset(POR) value */
0036 #define  CTRL_RESET_VAL (M(0x0) | CCM(0x4) | CA(0x4) | TST(0x25))
0037 
0038 /* PHY initialization value and mask */
0039 #define  CTRL_INIT_MASK (M_MASK | CCM_MASK | CA_MASK | TST_MASK | NB | RFB)
0040 #define  CTRL_INIT_VAL  (M(0x0) | CCM(0x5) | CA(0x4) | TST(0x25) | RFB)
0041 
0042 #define PHY_STATUS  0x10
0043 #define  LOCK       BIT(0)
0044 
0045 #define PHY_NUM     2
0046 
0047 #define MIN_CLKIN_FREQ  (25 * MEGA)
0048 #define MAX_CLKIN_FREQ  (165 * MEGA)
0049 
0050 #define PLL_LOCK_SLEEP      10
0051 #define PLL_LOCK_TIMEOUT    1000
0052 
0053 struct mixel_lvds_phy {
0054     struct phy *phy;
0055     struct phy_configure_opts_lvds cfg;
0056     unsigned int id;
0057 };
0058 
0059 struct mixel_lvds_phy_priv {
0060     struct regmap *regmap;
0061     struct mutex lock;  /* protect remap access and cfg of our own */
0062     struct clk *phy_ref_clk;
0063     struct mixel_lvds_phy *phys[PHY_NUM];
0064 };
0065 
0066 static int mixel_lvds_phy_init(struct phy *phy)
0067 {
0068     struct mixel_lvds_phy_priv *priv = dev_get_drvdata(phy->dev.parent);
0069 
0070     mutex_lock(&priv->lock);
0071     regmap_update_bits(priv->regmap,
0072                PHY_CTRL, CTRL_INIT_MASK, CTRL_INIT_VAL);
0073     mutex_unlock(&priv->lock);
0074 
0075     return 0;
0076 }
0077 
0078 static int mixel_lvds_phy_power_on(struct phy *phy)
0079 {
0080     struct mixel_lvds_phy_priv *priv = dev_get_drvdata(phy->dev.parent);
0081     struct mixel_lvds_phy *lvds_phy = phy_get_drvdata(phy);
0082     struct mixel_lvds_phy *companion = priv->phys[lvds_phy->id ^ 1];
0083     struct phy_configure_opts_lvds *cfg = &lvds_phy->cfg;
0084     u32 val = 0;
0085     u32 locked;
0086     int ret;
0087 
0088     /* The master PHY would power on the slave PHY. */
0089     if (cfg->is_slave)
0090         return 0;
0091 
0092     ret = clk_prepare_enable(priv->phy_ref_clk);
0093     if (ret < 0) {
0094         dev_err(&phy->dev,
0095             "failed to enable PHY reference clock: %d\n", ret);
0096         return ret;
0097     }
0098 
0099     mutex_lock(&priv->lock);
0100     if (cfg->bits_per_lane_and_dclk_cycle == 7) {
0101         if (cfg->differential_clk_rate < 44000000)
0102             val |= M(0x2);
0103         else if (cfg->differential_clk_rate < 90000000)
0104             val |= M(0x1);
0105         else
0106             val |= M(0x0);
0107     } else {
0108         val = NB;
0109 
0110         if (cfg->differential_clk_rate < 32000000)
0111             val |= M(0x2);
0112         else if (cfg->differential_clk_rate < 63000000)
0113             val |= M(0x1);
0114         else
0115             val |= M(0x0);
0116     }
0117     regmap_update_bits(priv->regmap, PHY_CTRL, M_MASK | NB, val);
0118 
0119     /*
0120      * Enable two channels synchronously,
0121      * if the companion PHY is a slave PHY.
0122      */
0123     if (companion->cfg.is_slave)
0124         val = CH_EN(0) | CH_EN(1);
0125     else
0126         val = CH_EN(lvds_phy->id);
0127     regmap_write(priv->regmap, PHY_CTRL + REG_SET, val);
0128 
0129     ret = regmap_read_poll_timeout(priv->regmap, PHY_STATUS, locked,
0130                        locked, PLL_LOCK_SLEEP,
0131                        PLL_LOCK_TIMEOUT);
0132     if (ret < 0) {
0133         dev_err(&phy->dev, "failed to get PHY lock: %d\n", ret);
0134         clk_disable_unprepare(priv->phy_ref_clk);
0135     }
0136     mutex_unlock(&priv->lock);
0137 
0138     return ret;
0139 }
0140 
0141 static int mixel_lvds_phy_power_off(struct phy *phy)
0142 {
0143     struct mixel_lvds_phy_priv *priv = dev_get_drvdata(phy->dev.parent);
0144     struct mixel_lvds_phy *lvds_phy = phy_get_drvdata(phy);
0145     struct mixel_lvds_phy *companion = priv->phys[lvds_phy->id ^ 1];
0146     struct phy_configure_opts_lvds *cfg = &lvds_phy->cfg;
0147 
0148     /* The master PHY would power off the slave PHY. */
0149     if (cfg->is_slave)
0150         return 0;
0151 
0152     mutex_lock(&priv->lock);
0153     if (companion->cfg.is_slave)
0154         regmap_write(priv->regmap, PHY_CTRL + REG_CLR,
0155                  CH_EN(0) | CH_EN(1));
0156     else
0157         regmap_write(priv->regmap, PHY_CTRL + REG_CLR,
0158                  CH_EN(lvds_phy->id));
0159     mutex_unlock(&priv->lock);
0160 
0161     clk_disable_unprepare(priv->phy_ref_clk);
0162 
0163     return 0;
0164 }
0165 
0166 static int mixel_lvds_phy_configure(struct phy *phy,
0167                     union phy_configure_opts *opts)
0168 {
0169     struct mixel_lvds_phy_priv *priv = dev_get_drvdata(phy->dev.parent);
0170     struct phy_configure_opts_lvds *cfg = &opts->lvds;
0171     int ret;
0172 
0173     ret = clk_set_rate(priv->phy_ref_clk, cfg->differential_clk_rate);
0174     if (ret)
0175         dev_err(&phy->dev, "failed to set PHY reference clock rate(%lu): %d\n",
0176             cfg->differential_clk_rate, ret);
0177 
0178     return ret;
0179 }
0180 
0181 /* Assume the master PHY's configuration set is cached first. */
0182 static int mixel_lvds_phy_check_slave(struct phy *slave_phy)
0183 {
0184     struct device *dev = &slave_phy->dev;
0185     struct mixel_lvds_phy_priv *priv = dev_get_drvdata(dev->parent);
0186     struct mixel_lvds_phy *slv = phy_get_drvdata(slave_phy);
0187     struct mixel_lvds_phy *mst = priv->phys[slv->id ^ 1];
0188     struct phy_configure_opts_lvds *mst_cfg = &mst->cfg;
0189     struct phy_configure_opts_lvds *slv_cfg = &slv->cfg;
0190 
0191     if (mst_cfg->bits_per_lane_and_dclk_cycle !=
0192         slv_cfg->bits_per_lane_and_dclk_cycle) {
0193         dev_err(dev, "number bits mismatch(mst: %u vs slv: %u)\n",
0194             mst_cfg->bits_per_lane_and_dclk_cycle,
0195             slv_cfg->bits_per_lane_and_dclk_cycle);
0196         return -EINVAL;
0197     }
0198 
0199     if (mst_cfg->differential_clk_rate !=
0200         slv_cfg->differential_clk_rate) {
0201         dev_err(dev, "dclk rate mismatch(mst: %lu vs slv: %lu)\n",
0202             mst_cfg->differential_clk_rate,
0203             slv_cfg->differential_clk_rate);
0204         return -EINVAL;
0205     }
0206 
0207     if (mst_cfg->lanes != slv_cfg->lanes) {
0208         dev_err(dev, "lanes mismatch(mst: %u vs slv: %u)\n",
0209             mst_cfg->lanes, slv_cfg->lanes);
0210         return -EINVAL;
0211     }
0212 
0213     if (mst_cfg->is_slave == slv_cfg->is_slave) {
0214         dev_err(dev, "master PHY is not found\n");
0215         return -EINVAL;
0216     }
0217 
0218     return 0;
0219 }
0220 
0221 static int mixel_lvds_phy_validate(struct phy *phy, enum phy_mode mode,
0222                    int submode, union phy_configure_opts *opts)
0223 {
0224     struct mixel_lvds_phy_priv *priv = dev_get_drvdata(phy->dev.parent);
0225     struct mixel_lvds_phy *lvds_phy = phy_get_drvdata(phy);
0226     struct phy_configure_opts_lvds *cfg = &opts->lvds;
0227     int ret = 0;
0228 
0229     if (mode != PHY_MODE_LVDS) {
0230         dev_err(&phy->dev, "invalid PHY mode(%d)\n", mode);
0231         return -EINVAL;
0232     }
0233 
0234     if (cfg->bits_per_lane_and_dclk_cycle != 7 &&
0235         cfg->bits_per_lane_and_dclk_cycle != 10) {
0236         dev_err(&phy->dev, "invalid bits per data lane(%u)\n",
0237             cfg->bits_per_lane_and_dclk_cycle);
0238         return -EINVAL;
0239     }
0240 
0241     if (cfg->lanes != 4 && cfg->lanes != 3) {
0242         dev_err(&phy->dev, "invalid data lanes(%u)\n", cfg->lanes);
0243         return -EINVAL;
0244     }
0245 
0246     if (cfg->differential_clk_rate < MIN_CLKIN_FREQ ||
0247         cfg->differential_clk_rate > MAX_CLKIN_FREQ) {
0248         dev_err(&phy->dev, "invalid differential clock rate(%lu)\n",
0249             cfg->differential_clk_rate);
0250         return -EINVAL;
0251     }
0252 
0253     mutex_lock(&priv->lock);
0254     /* cache configuration set of our own for check */
0255     memcpy(&lvds_phy->cfg, cfg, sizeof(*cfg));
0256 
0257     if (cfg->is_slave) {
0258         ret = mixel_lvds_phy_check_slave(phy);
0259         if (ret)
0260             dev_err(&phy->dev, "failed to check slave PHY: %d\n", ret);
0261     }
0262     mutex_unlock(&priv->lock);
0263 
0264     return ret;
0265 }
0266 
0267 static const struct phy_ops mixel_lvds_phy_ops = {
0268     .init = mixel_lvds_phy_init,
0269     .power_on = mixel_lvds_phy_power_on,
0270     .power_off = mixel_lvds_phy_power_off,
0271     .configure = mixel_lvds_phy_configure,
0272     .validate = mixel_lvds_phy_validate,
0273     .owner = THIS_MODULE,
0274 };
0275 
0276 static int mixel_lvds_phy_reset(struct device *dev)
0277 {
0278     struct mixel_lvds_phy_priv *priv = dev_get_drvdata(dev);
0279     int ret;
0280 
0281     ret = pm_runtime_resume_and_get(dev);
0282     if (ret < 0) {
0283         dev_err(dev, "failed to get PM runtime: %d\n", ret);
0284         return ret;
0285     }
0286 
0287     regmap_write(priv->regmap, PHY_CTRL, CTRL_RESET_VAL);
0288 
0289     ret = pm_runtime_put(dev);
0290     if (ret < 0)
0291         dev_err(dev, "failed to put PM runtime: %d\n", ret);
0292 
0293     return ret;
0294 }
0295 
0296 static struct phy *mixel_lvds_phy_xlate(struct device *dev,
0297                     struct of_phandle_args *args)
0298 {
0299     struct mixel_lvds_phy_priv *priv = dev_get_drvdata(dev);
0300     unsigned int phy_id;
0301 
0302     if (args->args_count != 1) {
0303         dev_err(dev,
0304             "invalid argument number(%d) for 'phys' property\n",
0305             args->args_count);
0306         return ERR_PTR(-EINVAL);
0307     }
0308 
0309     phy_id = args->args[0];
0310 
0311     if (phy_id >= PHY_NUM) {
0312         dev_err(dev, "invalid PHY index(%d)\n", phy_id);
0313         return ERR_PTR(-ENODEV);
0314     }
0315 
0316     return priv->phys[phy_id]->phy;
0317 }
0318 
0319 static int mixel_lvds_phy_probe(struct platform_device *pdev)
0320 {
0321     struct device *dev = &pdev->dev;
0322     struct phy_provider *phy_provider;
0323     struct mixel_lvds_phy_priv *priv;
0324     struct mixel_lvds_phy *lvds_phy;
0325     struct phy *phy;
0326     int i;
0327     int ret;
0328 
0329     if (!dev->of_node)
0330         return -ENODEV;
0331 
0332     priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0333     if (!priv)
0334         return -ENOMEM;
0335 
0336     priv->regmap = syscon_node_to_regmap(dev->of_node->parent);
0337     if (IS_ERR(priv->regmap))
0338         return dev_err_probe(dev, PTR_ERR(priv->regmap),
0339                      "failed to get regmap\n");
0340 
0341     priv->phy_ref_clk = devm_clk_get(dev, NULL);
0342     if (IS_ERR(priv->phy_ref_clk))
0343         return dev_err_probe(dev, PTR_ERR(priv->phy_ref_clk),
0344                      "failed to get PHY reference clock\n");
0345 
0346     mutex_init(&priv->lock);
0347 
0348     dev_set_drvdata(dev, priv);
0349 
0350     pm_runtime_enable(dev);
0351 
0352     ret = mixel_lvds_phy_reset(dev);
0353     if (ret) {
0354         dev_err(dev, "failed to do POR reset: %d\n", ret);
0355         return ret;
0356     }
0357 
0358     for (i = 0; i < PHY_NUM; i++) {
0359         lvds_phy = devm_kzalloc(dev, sizeof(*lvds_phy), GFP_KERNEL);
0360         if (!lvds_phy) {
0361             ret = -ENOMEM;
0362             goto err;
0363         }
0364 
0365         phy = devm_phy_create(dev, NULL, &mixel_lvds_phy_ops);
0366         if (IS_ERR(phy)) {
0367             ret = PTR_ERR(phy);
0368             dev_err(dev, "failed to create PHY for channel%d: %d\n",
0369                 i, ret);
0370             goto err;
0371         }
0372 
0373         lvds_phy->phy = phy;
0374         lvds_phy->id = i;
0375         priv->phys[i] = lvds_phy;
0376 
0377         phy_set_drvdata(phy, lvds_phy);
0378     }
0379 
0380     phy_provider = devm_of_phy_provider_register(dev, mixel_lvds_phy_xlate);
0381     if (IS_ERR(phy_provider)) {
0382         ret = PTR_ERR(phy_provider);
0383         dev_err(dev, "failed to register PHY provider: %d\n", ret);
0384         goto err;
0385     }
0386 
0387     return 0;
0388 err:
0389     pm_runtime_disable(dev);
0390 
0391     return ret;
0392 }
0393 
0394 static int mixel_lvds_phy_remove(struct platform_device *pdev)
0395 {
0396     pm_runtime_disable(&pdev->dev);
0397 
0398     return 0;
0399 }
0400 
0401 static int __maybe_unused mixel_lvds_phy_runtime_suspend(struct device *dev)
0402 {
0403     struct mixel_lvds_phy_priv *priv = dev_get_drvdata(dev);
0404 
0405     /* power down */
0406     mutex_lock(&priv->lock);
0407     regmap_write(priv->regmap, PHY_CTRL + REG_SET, PD);
0408     mutex_unlock(&priv->lock);
0409 
0410     return 0;
0411 }
0412 
0413 static int __maybe_unused mixel_lvds_phy_runtime_resume(struct device *dev)
0414 {
0415     struct mixel_lvds_phy_priv *priv = dev_get_drvdata(dev);
0416 
0417     /* power up + control initialization */
0418     mutex_lock(&priv->lock);
0419     regmap_update_bits(priv->regmap, PHY_CTRL,
0420                CTRL_INIT_MASK | PD, CTRL_INIT_VAL);
0421     mutex_unlock(&priv->lock);
0422 
0423     return 0;
0424 }
0425 
0426 static const struct dev_pm_ops mixel_lvds_phy_pm_ops = {
0427     SET_RUNTIME_PM_OPS(mixel_lvds_phy_runtime_suspend,
0428                mixel_lvds_phy_runtime_resume, NULL)
0429 };
0430 
0431 static const struct of_device_id mixel_lvds_phy_of_match[] = {
0432     { .compatible = "fsl,imx8qm-lvds-phy" },
0433     { /* sentinel */ }
0434 };
0435 MODULE_DEVICE_TABLE(of, mixel_lvds_phy_of_match);
0436 
0437 static struct platform_driver mixel_lvds_phy_driver = {
0438     .probe  = mixel_lvds_phy_probe,
0439     .remove = mixel_lvds_phy_remove,
0440     .driver = {
0441         .pm = &mixel_lvds_phy_pm_ops,
0442         .name = "mixel-lvds-phy",
0443         .of_match_table = mixel_lvds_phy_of_match,
0444     }
0445 };
0446 module_platform_driver(mixel_lvds_phy_driver);
0447 
0448 MODULE_DESCRIPTION("Mixel LVDS PHY driver");
0449 MODULE_AUTHOR("Liu Ying <victor.liu@nxp.com>");
0450 MODULE_LICENSE("GPL");