Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2014, The Linux Foundation. All rights reserved.
0004  */
0005 
0006 #include <linux/io.h>
0007 #include <linux/iopoll.h>
0008 #include <linux/kernel.h>
0009 #include <linux/module.h>
0010 #include <linux/of.h>
0011 #include <linux/time.h>
0012 #include <linux/delay.h>
0013 #include <linux/clk.h>
0014 #include <linux/slab.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/phy/phy.h>
0017 
0018 /* PHY registers */
0019 #define UNIPHY_PLL_REFCLK_CFG       0x000
0020 #define UNIPHY_PLL_PWRGEN_CFG       0x014
0021 #define UNIPHY_PLL_GLB_CFG      0x020
0022 #define UNIPHY_PLL_SDM_CFG0     0x038
0023 #define UNIPHY_PLL_SDM_CFG1     0x03C
0024 #define UNIPHY_PLL_SDM_CFG2     0x040
0025 #define UNIPHY_PLL_SDM_CFG3     0x044
0026 #define UNIPHY_PLL_SDM_CFG4     0x048
0027 #define UNIPHY_PLL_SSC_CFG0     0x04C
0028 #define UNIPHY_PLL_SSC_CFG1     0x050
0029 #define UNIPHY_PLL_SSC_CFG2     0x054
0030 #define UNIPHY_PLL_SSC_CFG3     0x058
0031 #define UNIPHY_PLL_LKDET_CFG0       0x05C
0032 #define UNIPHY_PLL_LKDET_CFG1       0x060
0033 #define UNIPHY_PLL_LKDET_CFG2       0x064
0034 #define UNIPHY_PLL_CAL_CFG0     0x06C
0035 #define UNIPHY_PLL_CAL_CFG8     0x08C
0036 #define UNIPHY_PLL_CAL_CFG9     0x090
0037 #define UNIPHY_PLL_CAL_CFG10        0x094
0038 #define UNIPHY_PLL_CAL_CFG11        0x098
0039 #define UNIPHY_PLL_STATUS       0x0C0
0040 
0041 #define SATA_PHY_SER_CTRL       0x100
0042 #define SATA_PHY_TX_DRIV_CTRL0      0x104
0043 #define SATA_PHY_TX_DRIV_CTRL1      0x108
0044 #define SATA_PHY_TX_IMCAL0      0x11C
0045 #define SATA_PHY_TX_IMCAL2      0x124
0046 #define SATA_PHY_RX_IMCAL0      0x128
0047 #define SATA_PHY_EQUAL          0x13C
0048 #define SATA_PHY_OOB_TERM       0x144
0049 #define SATA_PHY_CDR_CTRL0      0x148
0050 #define SATA_PHY_CDR_CTRL1      0x14C
0051 #define SATA_PHY_CDR_CTRL2      0x150
0052 #define SATA_PHY_CDR_CTRL3      0x154
0053 #define SATA_PHY_PI_CTRL0       0x168
0054 #define SATA_PHY_POW_DWN_CTRL0      0x180
0055 #define SATA_PHY_POW_DWN_CTRL1      0x184
0056 #define SATA_PHY_TX_DATA_CTRL       0x188
0057 #define SATA_PHY_ALIGNP         0x1A4
0058 #define SATA_PHY_TX_IMCAL_STAT      0x1E4
0059 #define SATA_PHY_RX_IMCAL_STAT      0x1E8
0060 
0061 #define UNIPHY_PLL_LOCK     BIT(0)
0062 #define SATA_PHY_TX_CAL     BIT(0)
0063 #define SATA_PHY_RX_CAL     BIT(0)
0064 
0065 /* default timeout set to 1 sec */
0066 #define TIMEOUT_MS      10000
0067 #define DELAY_INTERVAL_US   100
0068 
0069 struct qcom_apq8064_sata_phy {
0070     void __iomem *mmio;
0071     struct clk *cfg_clk;
0072     struct device *dev;
0073 };
0074 
0075 /* Helper function to do poll and timeout */
0076 static int poll_timeout(void __iomem *addr, u32 mask)
0077 {
0078     u32 val;
0079 
0080     return readl_relaxed_poll_timeout(addr, val, (val & mask),
0081                     DELAY_INTERVAL_US, TIMEOUT_MS * 1000);
0082 }
0083 
0084 static int qcom_apq8064_sata_phy_init(struct phy *generic_phy)
0085 {
0086     struct qcom_apq8064_sata_phy *phy = phy_get_drvdata(generic_phy);
0087     void __iomem *base = phy->mmio;
0088     int ret = 0;
0089 
0090     /* SATA phy initialization */
0091     writel_relaxed(0x01, base + SATA_PHY_SER_CTRL);
0092     writel_relaxed(0xB1, base + SATA_PHY_POW_DWN_CTRL0);
0093     /* Make sure the power down happens before power up */
0094     mb();
0095     usleep_range(10, 60);
0096 
0097     writel_relaxed(0x01, base + SATA_PHY_POW_DWN_CTRL0);
0098     writel_relaxed(0x3E, base + SATA_PHY_POW_DWN_CTRL1);
0099     writel_relaxed(0x01, base + SATA_PHY_RX_IMCAL0);
0100     writel_relaxed(0x01, base + SATA_PHY_TX_IMCAL0);
0101     writel_relaxed(0x02, base + SATA_PHY_TX_IMCAL2);
0102 
0103     /* Write UNIPHYPLL registers to configure PLL */
0104     writel_relaxed(0x04, base + UNIPHY_PLL_REFCLK_CFG);
0105     writel_relaxed(0x00, base + UNIPHY_PLL_PWRGEN_CFG);
0106 
0107     writel_relaxed(0x0A, base + UNIPHY_PLL_CAL_CFG0);
0108     writel_relaxed(0xF3, base + UNIPHY_PLL_CAL_CFG8);
0109     writel_relaxed(0x01, base + UNIPHY_PLL_CAL_CFG9);
0110     writel_relaxed(0xED, base + UNIPHY_PLL_CAL_CFG10);
0111     writel_relaxed(0x02, base + UNIPHY_PLL_CAL_CFG11);
0112 
0113     writel_relaxed(0x36, base + UNIPHY_PLL_SDM_CFG0);
0114     writel_relaxed(0x0D, base + UNIPHY_PLL_SDM_CFG1);
0115     writel_relaxed(0xA3, base + UNIPHY_PLL_SDM_CFG2);
0116     writel_relaxed(0xF0, base + UNIPHY_PLL_SDM_CFG3);
0117     writel_relaxed(0x00, base + UNIPHY_PLL_SDM_CFG4);
0118 
0119     writel_relaxed(0x19, base + UNIPHY_PLL_SSC_CFG0);
0120     writel_relaxed(0xE1, base + UNIPHY_PLL_SSC_CFG1);
0121     writel_relaxed(0x00, base + UNIPHY_PLL_SSC_CFG2);
0122     writel_relaxed(0x11, base + UNIPHY_PLL_SSC_CFG3);
0123 
0124     writel_relaxed(0x04, base + UNIPHY_PLL_LKDET_CFG0);
0125     writel_relaxed(0xFF, base + UNIPHY_PLL_LKDET_CFG1);
0126 
0127     writel_relaxed(0x02, base + UNIPHY_PLL_GLB_CFG);
0128     /* make sure global config LDO power down happens before power up */
0129     mb();
0130 
0131     writel_relaxed(0x03, base + UNIPHY_PLL_GLB_CFG);
0132     writel_relaxed(0x05, base + UNIPHY_PLL_LKDET_CFG2);
0133 
0134     /* PLL Lock wait */
0135     ret = poll_timeout(base + UNIPHY_PLL_STATUS, UNIPHY_PLL_LOCK);
0136     if (ret) {
0137         dev_err(phy->dev, "poll timeout UNIPHY_PLL_STATUS\n");
0138         return ret;
0139     }
0140 
0141     /* TX Calibration */
0142     ret = poll_timeout(base + SATA_PHY_TX_IMCAL_STAT, SATA_PHY_TX_CAL);
0143     if (ret) {
0144         dev_err(phy->dev, "poll timeout SATA_PHY_TX_IMCAL_STAT\n");
0145         return ret;
0146     }
0147 
0148     /* RX Calibration */
0149     ret = poll_timeout(base + SATA_PHY_RX_IMCAL_STAT, SATA_PHY_RX_CAL);
0150     if (ret) {
0151         dev_err(phy->dev, "poll timeout SATA_PHY_RX_IMCAL_STAT\n");
0152         return ret;
0153     }
0154 
0155     /* SATA phy calibrated succesfully, power up to functional mode */
0156     writel_relaxed(0x3E, base + SATA_PHY_POW_DWN_CTRL1);
0157     writel_relaxed(0x01, base + SATA_PHY_RX_IMCAL0);
0158     writel_relaxed(0x01, base + SATA_PHY_TX_IMCAL0);
0159 
0160     writel_relaxed(0x00, base + SATA_PHY_POW_DWN_CTRL1);
0161     writel_relaxed(0x59, base + SATA_PHY_CDR_CTRL0);
0162     writel_relaxed(0x04, base + SATA_PHY_CDR_CTRL1);
0163     writel_relaxed(0x00, base + SATA_PHY_CDR_CTRL2);
0164     writel_relaxed(0x00, base + SATA_PHY_PI_CTRL0);
0165     writel_relaxed(0x00, base + SATA_PHY_CDR_CTRL3);
0166     writel_relaxed(0x01, base + SATA_PHY_POW_DWN_CTRL0);
0167 
0168     writel_relaxed(0x11, base + SATA_PHY_TX_DATA_CTRL);
0169     writel_relaxed(0x43, base + SATA_PHY_ALIGNP);
0170     writel_relaxed(0x04, base + SATA_PHY_OOB_TERM);
0171 
0172     writel_relaxed(0x01, base + SATA_PHY_EQUAL);
0173     writel_relaxed(0x09, base + SATA_PHY_TX_DRIV_CTRL0);
0174     writel_relaxed(0x09, base + SATA_PHY_TX_DRIV_CTRL1);
0175 
0176     return 0;
0177 }
0178 
0179 static int qcom_apq8064_sata_phy_exit(struct phy *generic_phy)
0180 {
0181     struct qcom_apq8064_sata_phy *phy = phy_get_drvdata(generic_phy);
0182     void __iomem *base = phy->mmio;
0183 
0184     /* Power down PHY */
0185     writel_relaxed(0xF8, base + SATA_PHY_POW_DWN_CTRL0);
0186     writel_relaxed(0xFE, base + SATA_PHY_POW_DWN_CTRL1);
0187 
0188     /* Power down PLL block */
0189     writel_relaxed(0x00, base + UNIPHY_PLL_GLB_CFG);
0190 
0191     return 0;
0192 }
0193 
0194 static const struct phy_ops qcom_apq8064_sata_phy_ops = {
0195     .init       = qcom_apq8064_sata_phy_init,
0196     .exit       = qcom_apq8064_sata_phy_exit,
0197     .owner      = THIS_MODULE,
0198 };
0199 
0200 static int qcom_apq8064_sata_phy_probe(struct platform_device *pdev)
0201 {
0202     struct qcom_apq8064_sata_phy *phy;
0203     struct device *dev = &pdev->dev;
0204     struct phy_provider *phy_provider;
0205     struct phy *generic_phy;
0206     int ret;
0207 
0208     phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
0209     if (!phy)
0210         return -ENOMEM;
0211 
0212     phy->mmio = devm_platform_ioremap_resource(pdev, 0);
0213     if (IS_ERR(phy->mmio))
0214         return PTR_ERR(phy->mmio);
0215 
0216     generic_phy = devm_phy_create(dev, NULL, &qcom_apq8064_sata_phy_ops);
0217     if (IS_ERR(generic_phy)) {
0218         dev_err(dev, "%s: failed to create phy\n", __func__);
0219         return PTR_ERR(generic_phy);
0220     }
0221 
0222     phy->dev = dev;
0223     phy_set_drvdata(generic_phy, phy);
0224     platform_set_drvdata(pdev, phy);
0225 
0226     phy->cfg_clk = devm_clk_get(dev, "cfg");
0227     if (IS_ERR(phy->cfg_clk)) {
0228         dev_err(dev, "Failed to get sata cfg clock\n");
0229         return PTR_ERR(phy->cfg_clk);
0230     }
0231 
0232     ret = clk_prepare_enable(phy->cfg_clk);
0233     if (ret)
0234         return ret;
0235 
0236     phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
0237     if (IS_ERR(phy_provider)) {
0238         clk_disable_unprepare(phy->cfg_clk);
0239         dev_err(dev, "%s: failed to register phy\n", __func__);
0240         return PTR_ERR(phy_provider);
0241     }
0242 
0243     return 0;
0244 }
0245 
0246 static int qcom_apq8064_sata_phy_remove(struct platform_device *pdev)
0247 {
0248     struct qcom_apq8064_sata_phy *phy = platform_get_drvdata(pdev);
0249 
0250     clk_disable_unprepare(phy->cfg_clk);
0251 
0252     return 0;
0253 }
0254 
0255 static const struct of_device_id qcom_apq8064_sata_phy_of_match[] = {
0256     { .compatible = "qcom,apq8064-sata-phy" },
0257     { },
0258 };
0259 MODULE_DEVICE_TABLE(of, qcom_apq8064_sata_phy_of_match);
0260 
0261 static struct platform_driver qcom_apq8064_sata_phy_driver = {
0262     .probe  = qcom_apq8064_sata_phy_probe,
0263     .remove = qcom_apq8064_sata_phy_remove,
0264     .driver = {
0265         .name   = "qcom-apq8064-sata-phy",
0266         .of_match_table = qcom_apq8064_sata_phy_of_match,
0267     }
0268 };
0269 module_platform_driver(qcom_apq8064_sata_phy_driver);
0270 
0271 MODULE_DESCRIPTION("QCOM apq8064 SATA PHY driver");
0272 MODULE_LICENSE("GPL v2");