0001
0002
0003
0004
0005
0006
0007 #include <linux/bitfield.h>
0008 #include <linux/bits.h>
0009 #include <linux/clk.h>
0010 #include <linux/delay.h>
0011 #include <linux/mod_devicetable.h>
0012 #include <linux/module.h>
0013 #include <linux/phy/phy.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/regmap.h>
0016
0017
0018 #define USS_CPR_CLK_EN 0x00
0019 #define USS_CPR_CLK_SET 0x04
0020 #define USS_CPR_CLK_CLR 0x08
0021 #define USS_CPR_RST_EN 0x10
0022 #define USS_CPR_RST_SET 0x14
0023 #define USS_CPR_RST_CLR 0x18
0024
0025
0026 #define USS_CPR_PHY_TST BIT(6)
0027 #define USS_CPR_LOW_JIT BIT(5)
0028 #define USS_CPR_CORE BIT(4)
0029 #define USS_CPR_SUSPEND BIT(3)
0030 #define USS_CPR_ALT_REF BIT(2)
0031 #define USS_CPR_REF BIT(1)
0032 #define USS_CPR_SYS BIT(0)
0033 #define USS_CPR_MASK GENMASK(6, 0)
0034
0035
0036 #define USS_USB_CTRL_CFG0 0x10
0037 #define VCC_RESET_N_MASK BIT(31)
0038
0039 #define USS_USB_PHY_CFG0 0x30
0040 #define POR_MASK BIT(15)
0041 #define PHY_RESET_MASK BIT(14)
0042 #define PHY_REF_USE_PAD_MASK BIT(5)
0043
0044 #define USS_USB_PHY_CFG6 0x64
0045 #define PHY0_SRAM_EXT_LD_DONE_MASK BIT(23)
0046
0047 #define USS_USB_PARALLEL_IF_CTRL 0xa0
0048 #define USB_PHY_CR_PARA_SEL_MASK BIT(2)
0049
0050 #define USS_USB_TSET_SIGNALS_AND_GLOB 0xac
0051 #define USB_PHY_CR_PARA_CLK_EN_MASK BIT(7)
0052
0053 #define USS_USB_STATUS_REG 0xb8
0054 #define PHY0_SRAM_INIT_DONE_MASK BIT(3)
0055
0056 #define USS_USB_TIEOFFS_CONSTANTS_REG1 0xc0
0057 #define IDDQ_ENABLE_MASK BIT(10)
0058
0059 struct keembay_usb_phy {
0060 struct device *dev;
0061 struct regmap *regmap_cpr;
0062 struct regmap *regmap_slv;
0063 };
0064
0065 static const struct regmap_config keembay_regmap_config = {
0066 .reg_bits = 32,
0067 .val_bits = 32,
0068 .reg_stride = 4,
0069 .max_register = USS_USB_TIEOFFS_CONSTANTS_REG1,
0070 };
0071
0072 static int keembay_usb_clocks_on(struct keembay_usb_phy *priv)
0073 {
0074 int ret;
0075
0076 ret = regmap_update_bits(priv->regmap_cpr, USS_CPR_CLK_SET,
0077 USS_CPR_MASK, USS_CPR_MASK);
0078 if (ret) {
0079 dev_err(priv->dev, "error clock set: %d\n", ret);
0080 return ret;
0081 }
0082
0083 ret = regmap_update_bits(priv->regmap_cpr, USS_CPR_RST_SET,
0084 USS_CPR_MASK, USS_CPR_MASK);
0085 if (ret) {
0086 dev_err(priv->dev, "error reset set: %d\n", ret);
0087 return ret;
0088 }
0089
0090 ret = regmap_update_bits(priv->regmap_slv,
0091 USS_USB_TIEOFFS_CONSTANTS_REG1,
0092 IDDQ_ENABLE_MASK,
0093 FIELD_PREP(IDDQ_ENABLE_MASK, 0));
0094 if (ret) {
0095 dev_err(priv->dev, "error iddq disable: %d\n", ret);
0096 return ret;
0097 }
0098
0099
0100 usleep_range(30, 60);
0101
0102 ret = regmap_update_bits(priv->regmap_slv, USS_USB_PHY_CFG0,
0103 PHY_REF_USE_PAD_MASK,
0104 FIELD_PREP(PHY_REF_USE_PAD_MASK, 1));
0105 if (ret)
0106 dev_err(priv->dev, "error ref clock select: %d\n", ret);
0107
0108 return ret;
0109 }
0110
0111 static int keembay_usb_core_off(struct keembay_usb_phy *priv)
0112 {
0113 int ret;
0114
0115 ret = regmap_update_bits(priv->regmap_slv, USS_USB_CTRL_CFG0,
0116 VCC_RESET_N_MASK,
0117 FIELD_PREP(VCC_RESET_N_MASK, 0));
0118 if (ret)
0119 dev_err(priv->dev, "error core reset: %d\n", ret);
0120
0121 return ret;
0122 }
0123
0124 static int keembay_usb_core_on(struct keembay_usb_phy *priv)
0125 {
0126 int ret;
0127
0128 ret = regmap_update_bits(priv->regmap_slv, USS_USB_CTRL_CFG0,
0129 VCC_RESET_N_MASK,
0130 FIELD_PREP(VCC_RESET_N_MASK, 1));
0131 if (ret)
0132 dev_err(priv->dev, "error core on: %d\n", ret);
0133
0134 return ret;
0135 }
0136
0137 static int keembay_usb_phys_on(struct keembay_usb_phy *priv)
0138 {
0139 int ret;
0140
0141 ret = regmap_update_bits(priv->regmap_slv, USS_USB_PHY_CFG0,
0142 POR_MASK | PHY_RESET_MASK,
0143 FIELD_PREP(POR_MASK | PHY_RESET_MASK, 0));
0144 if (ret)
0145 dev_err(priv->dev, "error phys on: %d\n", ret);
0146
0147 return ret;
0148 }
0149
0150 static int keembay_usb_phy_init(struct phy *phy)
0151 {
0152 struct keembay_usb_phy *priv = phy_get_drvdata(phy);
0153 u32 val;
0154 int ret;
0155
0156 ret = keembay_usb_core_off(priv);
0157 if (ret)
0158 return ret;
0159
0160
0161
0162
0163
0164 usleep_range(20, 40);
0165
0166 ret = keembay_usb_phys_on(priv);
0167 if (ret)
0168 return ret;
0169
0170 ret = regmap_update_bits(priv->regmap_slv,
0171 USS_USB_TSET_SIGNALS_AND_GLOB,
0172 USB_PHY_CR_PARA_CLK_EN_MASK,
0173 FIELD_PREP(USB_PHY_CR_PARA_CLK_EN_MASK, 0));
0174 if (ret) {
0175 dev_err(priv->dev, "error cr clock disable: %d\n", ret);
0176 return ret;
0177 }
0178
0179
0180
0181
0182
0183 udelay(2);
0184
0185 ret = regmap_update_bits(priv->regmap_slv,
0186 USS_USB_PARALLEL_IF_CTRL,
0187 USB_PHY_CR_PARA_SEL_MASK,
0188 FIELD_PREP(USB_PHY_CR_PARA_SEL_MASK, 1));
0189 if (ret) {
0190 dev_err(priv->dev, "error cr select: %d\n", ret);
0191 return ret;
0192 }
0193
0194 ret = regmap_update_bits(priv->regmap_slv,
0195 USS_USB_TSET_SIGNALS_AND_GLOB,
0196 USB_PHY_CR_PARA_CLK_EN_MASK,
0197 FIELD_PREP(USB_PHY_CR_PARA_CLK_EN_MASK, 1));
0198 if (ret) {
0199 dev_err(priv->dev, "error cr clock enable: %d\n", ret);
0200 return ret;
0201 }
0202
0203 ret = regmap_read_poll_timeout(priv->regmap_slv, USS_USB_STATUS_REG,
0204 val, val & PHY0_SRAM_INIT_DONE_MASK,
0205 USEC_PER_MSEC, 10 * USEC_PER_MSEC);
0206 if (ret) {
0207 dev_err(priv->dev, "SRAM init not done: %d\n", ret);
0208 return ret;
0209 }
0210
0211 ret = regmap_update_bits(priv->regmap_slv, USS_USB_PHY_CFG6,
0212 PHY0_SRAM_EXT_LD_DONE_MASK,
0213 FIELD_PREP(PHY0_SRAM_EXT_LD_DONE_MASK, 1));
0214 if (ret) {
0215 dev_err(priv->dev, "error SRAM init done set: %d\n", ret);
0216 return ret;
0217 }
0218
0219
0220
0221
0222
0223 usleep_range(20, 40);
0224
0225 return keembay_usb_core_on(priv);
0226 }
0227
0228 static const struct phy_ops ops = {
0229 .init = keembay_usb_phy_init,
0230 .owner = THIS_MODULE,
0231 };
0232
0233 static int keembay_usb_phy_probe(struct platform_device *pdev)
0234 {
0235 struct device *dev = &pdev->dev;
0236 struct keembay_usb_phy *priv;
0237 struct phy *generic_phy;
0238 struct phy_provider *phy_provider;
0239 void __iomem *base;
0240 int ret;
0241
0242 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0243 if (!priv)
0244 return -ENOMEM;
0245
0246 base = devm_platform_ioremap_resource_byname(pdev, "cpr-apb-base");
0247 if (IS_ERR(base))
0248 return PTR_ERR(base);
0249
0250 priv->regmap_cpr = devm_regmap_init_mmio(dev, base,
0251 &keembay_regmap_config);
0252 if (IS_ERR(priv->regmap_cpr))
0253 return PTR_ERR(priv->regmap_cpr);
0254
0255 base = devm_platform_ioremap_resource_byname(pdev, "slv-apb-base");
0256 if (IS_ERR(base))
0257 return PTR_ERR(base);
0258
0259 priv->regmap_slv = devm_regmap_init_mmio(dev, base,
0260 &keembay_regmap_config);
0261 if (IS_ERR(priv->regmap_slv))
0262 return PTR_ERR(priv->regmap_slv);
0263
0264 generic_phy = devm_phy_create(dev, dev->of_node, &ops);
0265 if (IS_ERR(generic_phy))
0266 return dev_err_probe(dev, PTR_ERR(generic_phy),
0267 "failed to create PHY\n");
0268
0269 phy_set_drvdata(generic_phy, priv);
0270 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
0271 if (IS_ERR(phy_provider))
0272 return dev_err_probe(dev, PTR_ERR(phy_provider),
0273 "failed to register phy provider\n");
0274
0275
0276 ret = keembay_usb_clocks_on(priv);
0277 if (ret)
0278 return ret;
0279
0280
0281 return keembay_usb_core_on(priv);
0282 }
0283
0284 static const struct of_device_id keembay_usb_phy_dt_ids[] = {
0285 { .compatible = "intel,keembay-usb-phy" },
0286 {}
0287 };
0288 MODULE_DEVICE_TABLE(of, keembay_usb_phy_dt_ids);
0289
0290 static struct platform_driver keembay_usb_phy_driver = {
0291 .probe = keembay_usb_phy_probe,
0292 .driver = {
0293 .name = "keembay-usb-phy",
0294 .of_match_table = keembay_usb_phy_dt_ids,
0295 },
0296 };
0297 module_platform_driver(keembay_usb_phy_driver);
0298
0299 MODULE_AUTHOR("Wan Ahmad Zainie <wan.ahmad.zainie.wan.mohamad@intel.com>");
0300 MODULE_DESCRIPTION("Intel Keem Bay USB PHY driver");
0301 MODULE_LICENSE("GPL v2");