0001
0002
0003
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
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
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
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
0091 writel_relaxed(0x01, base + SATA_PHY_SER_CTRL);
0092 writel_relaxed(0xB1, base + SATA_PHY_POW_DWN_CTRL0);
0093
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
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
0129 mb();
0130
0131 writel_relaxed(0x03, base + UNIPHY_PLL_GLB_CFG);
0132 writel_relaxed(0x05, base + UNIPHY_PLL_LKDET_CFG2);
0133
0134
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
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
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
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
0185 writel_relaxed(0xF8, base + SATA_PHY_POW_DWN_CTRL0);
0186 writel_relaxed(0xFE, base + SATA_PHY_POW_DWN_CTRL1);
0187
0188
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");