0001
0002
0003
0004
0005
0006
0007 #include <linux/delay.h>
0008 #include <linux/io.h>
0009 #include <linux/module.h>
0010 #include <linux/phy/phy.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/soc/mmp/cputype.h>
0013
0014 #define USB2_PLL_REG0 0x4
0015 #define USB2_PLL_REG1 0x8
0016 #define USB2_TX_REG0 0x10
0017 #define USB2_TX_REG1 0x14
0018 #define USB2_TX_REG2 0x18
0019 #define USB2_RX_REG0 0x20
0020 #define USB2_RX_REG1 0x24
0021 #define USB2_RX_REG2 0x28
0022 #define USB2_ANA_REG0 0x30
0023 #define USB2_ANA_REG1 0x34
0024 #define USB2_ANA_REG2 0x38
0025 #define USB2_DIG_REG0 0x3C
0026 #define USB2_DIG_REG1 0x40
0027 #define USB2_DIG_REG2 0x44
0028 #define USB2_DIG_REG3 0x48
0029 #define USB2_TEST_REG0 0x4C
0030 #define USB2_TEST_REG1 0x50
0031 #define USB2_TEST_REG2 0x54
0032 #define USB2_CHARGER_REG0 0x58
0033 #define USB2_OTG_REG0 0x5C
0034 #define USB2_PHY_MON0 0x60
0035 #define USB2_RESETVE_REG0 0x64
0036 #define USB2_ICID_REG0 0x78
0037 #define USB2_ICID_REG1 0x7C
0038
0039
0040
0041
0042 #define USB2_PLL_FBDIV_SHIFT_MMP3 0
0043 #define USB2_PLL_FBDIV_MASK_MMP3 (0xFF << 0)
0044
0045 #define USB2_PLL_REFDIV_SHIFT_MMP3 8
0046 #define USB2_PLL_REFDIV_MASK_MMP3 (0xF << 8)
0047
0048 #define USB2_PLL_VDD12_SHIFT_MMP3 12
0049 #define USB2_PLL_VDD18_SHIFT_MMP3 14
0050
0051
0052 #define USB2_PLL_FBDIV_SHIFT_MMP3_B0 0
0053 #define USB2_PLL_REFDIV_SHIFT_MMP3_B0 9
0054 #define USB2_PLL_VDD18_SHIFT_MMP3_B0 14
0055 #define USB2_PLL_FBDIV_MASK_MMP3_B0 0x01FF
0056 #define USB2_PLL_REFDIV_MASK_MMP3_B0 0x3E00
0057
0058 #define USB2_PLL_CAL12_SHIFT_MMP3 0
0059 #define USB2_PLL_CALI12_MASK_MMP3 (0x3 << 0)
0060
0061 #define USB2_PLL_VCOCAL_START_SHIFT_MMP3 2
0062
0063 #define USB2_PLL_KVCO_SHIFT_MMP3 4
0064 #define USB2_PLL_KVCO_MASK_MMP3 (0x7<<4)
0065
0066 #define USB2_PLL_ICP_SHIFT_MMP3 8
0067 #define USB2_PLL_ICP_MASK_MMP3 (0x7<<8)
0068
0069 #define USB2_PLL_LOCK_BYPASS_SHIFT_MMP3 12
0070
0071 #define USB2_PLL_PU_PLL_SHIFT_MMP3 13
0072 #define USB2_PLL_PU_PLL_MASK (0x1 << 13)
0073
0074 #define USB2_PLL_READY_MASK_MMP3 (0x1 << 15)
0075
0076
0077 #define USB2_TX_IMPCAL_VTH_SHIFT_MMP3 8
0078 #define USB2_TX_IMPCAL_VTH_MASK_MMP3 (0x7 << 8)
0079
0080 #define USB2_TX_RCAL_START_SHIFT_MMP3 13
0081
0082
0083 #define USB2_TX_CK60_PHSEL_SHIFT_MMP3 0
0084 #define USB2_TX_CK60_PHSEL_MASK_MMP3 (0xf << 0)
0085
0086 #define USB2_TX_AMP_SHIFT_MMP3 4
0087 #define USB2_TX_AMP_MASK_MMP3 (0x7 << 4)
0088
0089 #define USB2_TX_VDD12_SHIFT_MMP3 8
0090 #define USB2_TX_VDD12_MASK_MMP3 (0x3 << 8)
0091
0092
0093 #define USB2_TX_DRV_SLEWRATE_SHIFT 10
0094
0095
0096 #define USB2_RX_SQ_THRESH_SHIFT_MMP3 4
0097 #define USB2_RX_SQ_THRESH_MASK_MMP3 (0xf << 4)
0098
0099 #define USB2_RX_SQ_LENGTH_SHIFT_MMP3 10
0100 #define USB2_RX_SQ_LENGTH_MASK_MMP3 (0x3 << 10)
0101
0102
0103 #define USB2_ANA_PU_ANA_SHIFT_MMP3 14
0104
0105
0106 #define USB2_OTG_PU_OTG_SHIFT_MMP3 3
0107
0108 struct mmp3_usb_phy {
0109 struct phy *phy;
0110 void __iomem *base;
0111 };
0112
0113 static unsigned int u2o_get(void __iomem *base, unsigned int offset)
0114 {
0115 return readl_relaxed(base + offset);
0116 }
0117
0118 static void u2o_set(void __iomem *base, unsigned int offset,
0119 unsigned int value)
0120 {
0121 u32 reg;
0122
0123 reg = readl_relaxed(base + offset);
0124 reg |= value;
0125 writel_relaxed(reg, base + offset);
0126 readl_relaxed(base + offset);
0127 }
0128
0129 static void u2o_clear(void __iomem *base, unsigned int offset,
0130 unsigned int value)
0131 {
0132 u32 reg;
0133
0134 reg = readl_relaxed(base + offset);
0135 reg &= ~value;
0136 writel_relaxed(reg, base + offset);
0137 readl_relaxed(base + offset);
0138 }
0139
0140 static int mmp3_usb_phy_init(struct phy *phy)
0141 {
0142 struct mmp3_usb_phy *mmp3_usb_phy = phy_get_drvdata(phy);
0143 void __iomem *base = mmp3_usb_phy->base;
0144
0145 if (cpu_is_mmp3_a0()) {
0146 u2o_clear(base, USB2_PLL_REG0, (USB2_PLL_FBDIV_MASK_MMP3
0147 | USB2_PLL_REFDIV_MASK_MMP3));
0148 u2o_set(base, USB2_PLL_REG0,
0149 0xd << USB2_PLL_REFDIV_SHIFT_MMP3
0150 | 0xf0 << USB2_PLL_FBDIV_SHIFT_MMP3);
0151 } else if (cpu_is_mmp3_b0()) {
0152 u2o_clear(base, USB2_PLL_REG0, USB2_PLL_REFDIV_MASK_MMP3_B0
0153 | USB2_PLL_FBDIV_MASK_MMP3_B0);
0154 u2o_set(base, USB2_PLL_REG0,
0155 0xd << USB2_PLL_REFDIV_SHIFT_MMP3_B0
0156 | 0xf0 << USB2_PLL_FBDIV_SHIFT_MMP3_B0);
0157 } else {
0158 dev_err(&phy->dev, "unsupported silicon revision\n");
0159 return -ENODEV;
0160 }
0161
0162 u2o_clear(base, USB2_PLL_REG1, USB2_PLL_PU_PLL_MASK
0163 | USB2_PLL_ICP_MASK_MMP3
0164 | USB2_PLL_KVCO_MASK_MMP3
0165 | USB2_PLL_CALI12_MASK_MMP3);
0166 u2o_set(base, USB2_PLL_REG1, 1 << USB2_PLL_PU_PLL_SHIFT_MMP3
0167 | 1 << USB2_PLL_LOCK_BYPASS_SHIFT_MMP3
0168 | 3 << USB2_PLL_ICP_SHIFT_MMP3
0169 | 3 << USB2_PLL_KVCO_SHIFT_MMP3
0170 | 3 << USB2_PLL_CAL12_SHIFT_MMP3);
0171
0172 u2o_clear(base, USB2_TX_REG0, USB2_TX_IMPCAL_VTH_MASK_MMP3);
0173 u2o_set(base, USB2_TX_REG0, 2 << USB2_TX_IMPCAL_VTH_SHIFT_MMP3);
0174
0175 u2o_clear(base, USB2_TX_REG1, USB2_TX_VDD12_MASK_MMP3
0176 | USB2_TX_AMP_MASK_MMP3
0177 | USB2_TX_CK60_PHSEL_MASK_MMP3);
0178 u2o_set(base, USB2_TX_REG1, 3 << USB2_TX_VDD12_SHIFT_MMP3
0179 | 4 << USB2_TX_AMP_SHIFT_MMP3
0180 | 4 << USB2_TX_CK60_PHSEL_SHIFT_MMP3);
0181
0182 u2o_clear(base, USB2_TX_REG2, 3 << USB2_TX_DRV_SLEWRATE_SHIFT);
0183 u2o_set(base, USB2_TX_REG2, 2 << USB2_TX_DRV_SLEWRATE_SHIFT);
0184
0185 u2o_clear(base, USB2_RX_REG0, USB2_RX_SQ_THRESH_MASK_MMP3);
0186 u2o_set(base, USB2_RX_REG0, 0xa << USB2_RX_SQ_THRESH_SHIFT_MMP3);
0187
0188 u2o_set(base, USB2_ANA_REG1, 0x1 << USB2_ANA_PU_ANA_SHIFT_MMP3);
0189
0190 u2o_set(base, USB2_OTG_REG0, 0x1 << USB2_OTG_PU_OTG_SHIFT_MMP3);
0191
0192 return 0;
0193 }
0194
0195 static int mmp3_usb_phy_calibrate(struct phy *phy)
0196 {
0197 struct mmp3_usb_phy *mmp3_usb_phy = phy_get_drvdata(phy);
0198 void __iomem *base = mmp3_usb_phy->base;
0199 int loops;
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213 udelay(200);
0214 u2o_set(base, USB2_PLL_REG1, 1 << USB2_PLL_VCOCAL_START_SHIFT_MMP3);
0215 udelay(400);
0216 u2o_set(base, USB2_TX_REG0, 1 << USB2_TX_RCAL_START_SHIFT_MMP3);
0217 udelay(40);
0218 u2o_clear(base, USB2_TX_REG0, 1 << USB2_TX_RCAL_START_SHIFT_MMP3);
0219 udelay(400);
0220
0221 loops = 0;
0222 while ((u2o_get(base, USB2_PLL_REG1) & USB2_PLL_READY_MASK_MMP3) == 0) {
0223 mdelay(1);
0224 loops++;
0225 if (loops > 100) {
0226 dev_err(&phy->dev, "PLL_READY not set after 100mS.\n");
0227 return -ETIMEDOUT;
0228 }
0229 }
0230
0231 return 0;
0232 }
0233
0234 static const struct phy_ops mmp3_usb_phy_ops = {
0235 .init = mmp3_usb_phy_init,
0236 .calibrate = mmp3_usb_phy_calibrate,
0237 .owner = THIS_MODULE,
0238 };
0239
0240 static const struct of_device_id mmp3_usb_phy_of_match[] = {
0241 { .compatible = "marvell,mmp3-usb-phy", },
0242 { },
0243 };
0244 MODULE_DEVICE_TABLE(of, mmp3_usb_phy_of_match);
0245
0246 static int mmp3_usb_phy_probe(struct platform_device *pdev)
0247 {
0248 struct device *dev = &pdev->dev;
0249 struct mmp3_usb_phy *mmp3_usb_phy;
0250 struct phy_provider *provider;
0251
0252 mmp3_usb_phy = devm_kzalloc(dev, sizeof(*mmp3_usb_phy), GFP_KERNEL);
0253 if (!mmp3_usb_phy)
0254 return -ENOMEM;
0255
0256 mmp3_usb_phy->base = devm_platform_ioremap_resource(pdev, 0);
0257 if (IS_ERR(mmp3_usb_phy->base)) {
0258 dev_err(dev, "failed to remap PHY regs\n");
0259 return PTR_ERR(mmp3_usb_phy->base);
0260 }
0261
0262 mmp3_usb_phy->phy = devm_phy_create(dev, NULL, &mmp3_usb_phy_ops);
0263 if (IS_ERR(mmp3_usb_phy->phy)) {
0264 dev_err(dev, "failed to create PHY\n");
0265 return PTR_ERR(mmp3_usb_phy->phy);
0266 }
0267
0268 phy_set_drvdata(mmp3_usb_phy->phy, mmp3_usb_phy);
0269 provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
0270 if (IS_ERR(provider)) {
0271 dev_err(dev, "failed to register PHY provider\n");
0272 return PTR_ERR(provider);
0273 }
0274
0275 return 0;
0276 }
0277
0278 static struct platform_driver mmp3_usb_phy_driver = {
0279 .probe = mmp3_usb_phy_probe,
0280 .driver = {
0281 .name = "mmp3-usb-phy",
0282 .of_match_table = mmp3_usb_phy_of_match,
0283 },
0284 };
0285 module_platform_driver(mmp3_usb_phy_driver);
0286
0287 MODULE_AUTHOR("Lubomir Rintel <lkundrak@v3.sk>");
0288 MODULE_DESCRIPTION("Marvell MMP3 USB PHY Driver");
0289 MODULE_LICENSE("GPL v2");