0001
0002
0003
0004
0005 #include <linux/module.h>
0006 #include <linux/ulpi/driver.h>
0007 #include <linux/ulpi/regs.h>
0008 #include <linux/clk.h>
0009 #include <linux/regulator/consumer.h>
0010 #include <linux/of_device.h>
0011 #include <linux/phy/phy.h>
0012 #include <linux/reset.h>
0013 #include <linux/extcon.h>
0014 #include <linux/notifier.h>
0015
0016 #define ULPI_PWR_CLK_MNG_REG 0x88
0017 # define ULPI_PWR_OTG_COMP_DISABLE BIT(0)
0018
0019 #define ULPI_MISC_A 0x96
0020 # define ULPI_MISC_A_VBUSVLDEXTSEL BIT(1)
0021 # define ULPI_MISC_A_VBUSVLDEXT BIT(0)
0022
0023
0024 struct ulpi_seq {
0025 u8 addr;
0026 u8 val;
0027 };
0028
0029 struct qcom_usb_hs_phy {
0030 struct ulpi *ulpi;
0031 struct phy *phy;
0032 struct clk *ref_clk;
0033 struct clk *sleep_clk;
0034 struct regulator *v1p8;
0035 struct regulator *v3p3;
0036 struct reset_control *reset;
0037 struct ulpi_seq *init_seq;
0038 struct extcon_dev *vbus_edev;
0039 struct notifier_block vbus_notify;
0040 };
0041
0042 static int qcom_usb_hs_phy_set_mode(struct phy *phy,
0043 enum phy_mode mode, int submode)
0044 {
0045 struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy);
0046 u8 addr;
0047 int ret;
0048
0049 if (!uphy->vbus_edev) {
0050 u8 val = 0;
0051
0052 switch (mode) {
0053 case PHY_MODE_USB_OTG:
0054 case PHY_MODE_USB_HOST:
0055 val |= ULPI_INT_IDGRD;
0056 fallthrough;
0057 case PHY_MODE_USB_DEVICE:
0058 val |= ULPI_INT_SESS_VALID;
0059 break;
0060 default:
0061 break;
0062 }
0063
0064 ret = ulpi_write(uphy->ulpi, ULPI_USB_INT_EN_RISE, val);
0065 if (ret)
0066 return ret;
0067 ret = ulpi_write(uphy->ulpi, ULPI_USB_INT_EN_FALL, val);
0068 } else {
0069 switch (mode) {
0070 case PHY_MODE_USB_OTG:
0071 case PHY_MODE_USB_DEVICE:
0072 addr = ULPI_SET(ULPI_MISC_A);
0073 break;
0074 case PHY_MODE_USB_HOST:
0075 addr = ULPI_CLR(ULPI_MISC_A);
0076 break;
0077 default:
0078 return -EINVAL;
0079 }
0080
0081 ret = ulpi_write(uphy->ulpi, ULPI_SET(ULPI_PWR_CLK_MNG_REG),
0082 ULPI_PWR_OTG_COMP_DISABLE);
0083 if (ret)
0084 return ret;
0085 ret = ulpi_write(uphy->ulpi, addr, ULPI_MISC_A_VBUSVLDEXTSEL);
0086 }
0087
0088 return ret;
0089 }
0090
0091 static int
0092 qcom_usb_hs_phy_vbus_notifier(struct notifier_block *nb, unsigned long event,
0093 void *ptr)
0094 {
0095 struct qcom_usb_hs_phy *uphy;
0096 u8 addr;
0097
0098 uphy = container_of(nb, struct qcom_usb_hs_phy, vbus_notify);
0099
0100 if (event)
0101 addr = ULPI_SET(ULPI_MISC_A);
0102 else
0103 addr = ULPI_CLR(ULPI_MISC_A);
0104
0105 return ulpi_write(uphy->ulpi, addr, ULPI_MISC_A_VBUSVLDEXT);
0106 }
0107
0108 static int qcom_usb_hs_phy_power_on(struct phy *phy)
0109 {
0110 struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy);
0111 struct ulpi *ulpi = uphy->ulpi;
0112 const struct ulpi_seq *seq;
0113 int ret, state;
0114
0115 ret = clk_prepare_enable(uphy->ref_clk);
0116 if (ret)
0117 return ret;
0118
0119 ret = clk_prepare_enable(uphy->sleep_clk);
0120 if (ret)
0121 goto err_sleep;
0122
0123 ret = regulator_set_load(uphy->v1p8, 50000);
0124 if (ret < 0)
0125 goto err_1p8;
0126
0127 ret = regulator_enable(uphy->v1p8);
0128 if (ret)
0129 goto err_1p8;
0130
0131 ret = regulator_set_voltage_triplet(uphy->v3p3, 3050000, 3300000,
0132 3300000);
0133 if (ret)
0134 goto err_3p3;
0135
0136 ret = regulator_set_load(uphy->v3p3, 50000);
0137 if (ret < 0)
0138 goto err_3p3;
0139
0140 ret = regulator_enable(uphy->v3p3);
0141 if (ret)
0142 goto err_3p3;
0143
0144 for (seq = uphy->init_seq; seq->addr; seq++) {
0145 ret = ulpi_write(ulpi, ULPI_EXT_VENDOR_SPECIFIC + seq->addr,
0146 seq->val);
0147 if (ret)
0148 goto err_ulpi;
0149 }
0150
0151 if (uphy->reset) {
0152 ret = reset_control_reset(uphy->reset);
0153 if (ret)
0154 goto err_ulpi;
0155 }
0156
0157 if (uphy->vbus_edev) {
0158 state = extcon_get_state(uphy->vbus_edev, EXTCON_USB);
0159
0160 qcom_usb_hs_phy_vbus_notifier(&uphy->vbus_notify, state,
0161 uphy->vbus_edev);
0162 ret = extcon_register_notifier(uphy->vbus_edev, EXTCON_USB,
0163 &uphy->vbus_notify);
0164 if (ret)
0165 goto err_ulpi;
0166 }
0167
0168 return 0;
0169 err_ulpi:
0170 regulator_disable(uphy->v3p3);
0171 err_3p3:
0172 regulator_disable(uphy->v1p8);
0173 err_1p8:
0174 clk_disable_unprepare(uphy->sleep_clk);
0175 err_sleep:
0176 clk_disable_unprepare(uphy->ref_clk);
0177 return ret;
0178 }
0179
0180 static int qcom_usb_hs_phy_power_off(struct phy *phy)
0181 {
0182 struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy);
0183
0184 if (uphy->vbus_edev)
0185 extcon_unregister_notifier(uphy->vbus_edev, EXTCON_USB,
0186 &uphy->vbus_notify);
0187 regulator_disable(uphy->v3p3);
0188 regulator_disable(uphy->v1p8);
0189 clk_disable_unprepare(uphy->sleep_clk);
0190 clk_disable_unprepare(uphy->ref_clk);
0191
0192 return 0;
0193 }
0194
0195 static const struct phy_ops qcom_usb_hs_phy_ops = {
0196 .power_on = qcom_usb_hs_phy_power_on,
0197 .power_off = qcom_usb_hs_phy_power_off,
0198 .set_mode = qcom_usb_hs_phy_set_mode,
0199 .owner = THIS_MODULE,
0200 };
0201
0202 static int qcom_usb_hs_phy_probe(struct ulpi *ulpi)
0203 {
0204 struct qcom_usb_hs_phy *uphy;
0205 struct phy_provider *p;
0206 struct clk *clk;
0207 struct regulator *reg;
0208 struct reset_control *reset;
0209 int size;
0210 int ret;
0211
0212 uphy = devm_kzalloc(&ulpi->dev, sizeof(*uphy), GFP_KERNEL);
0213 if (!uphy)
0214 return -ENOMEM;
0215 ulpi_set_drvdata(ulpi, uphy);
0216 uphy->ulpi = ulpi;
0217
0218 size = of_property_count_u8_elems(ulpi->dev.of_node, "qcom,init-seq");
0219 if (size < 0)
0220 size = 0;
0221 uphy->init_seq = devm_kmalloc_array(&ulpi->dev, (size / 2) + 1,
0222 sizeof(*uphy->init_seq), GFP_KERNEL);
0223 if (!uphy->init_seq)
0224 return -ENOMEM;
0225 ret = of_property_read_u8_array(ulpi->dev.of_node, "qcom,init-seq",
0226 (u8 *)uphy->init_seq, size);
0227 if (ret && size)
0228 return ret;
0229
0230 uphy->init_seq[size / 2].addr = uphy->init_seq[size / 2].val = 0;
0231
0232 uphy->ref_clk = clk = devm_clk_get(&ulpi->dev, "ref");
0233 if (IS_ERR(clk))
0234 return PTR_ERR(clk);
0235
0236 uphy->sleep_clk = clk = devm_clk_get(&ulpi->dev, "sleep");
0237 if (IS_ERR(clk))
0238 return PTR_ERR(clk);
0239
0240 uphy->v1p8 = reg = devm_regulator_get(&ulpi->dev, "v1p8");
0241 if (IS_ERR(reg))
0242 return PTR_ERR(reg);
0243
0244 uphy->v3p3 = reg = devm_regulator_get(&ulpi->dev, "v3p3");
0245 if (IS_ERR(reg))
0246 return PTR_ERR(reg);
0247
0248 uphy->reset = reset = devm_reset_control_get(&ulpi->dev, "por");
0249 if (IS_ERR(reset)) {
0250 if (PTR_ERR(reset) == -EPROBE_DEFER)
0251 return PTR_ERR(reset);
0252 uphy->reset = NULL;
0253 }
0254
0255 uphy->phy = devm_phy_create(&ulpi->dev, ulpi->dev.of_node,
0256 &qcom_usb_hs_phy_ops);
0257 if (IS_ERR(uphy->phy))
0258 return PTR_ERR(uphy->phy);
0259
0260 uphy->vbus_edev = extcon_get_edev_by_phandle(&ulpi->dev, 0);
0261 if (IS_ERR(uphy->vbus_edev)) {
0262 if (PTR_ERR(uphy->vbus_edev) != -ENODEV)
0263 return PTR_ERR(uphy->vbus_edev);
0264 uphy->vbus_edev = NULL;
0265 }
0266
0267 uphy->vbus_notify.notifier_call = qcom_usb_hs_phy_vbus_notifier;
0268 phy_set_drvdata(uphy->phy, uphy);
0269
0270 p = devm_of_phy_provider_register(&ulpi->dev, of_phy_simple_xlate);
0271 return PTR_ERR_OR_ZERO(p);
0272 }
0273
0274 static const struct of_device_id qcom_usb_hs_phy_match[] = {
0275 { .compatible = "qcom,usb-hs-phy", },
0276 { }
0277 };
0278 MODULE_DEVICE_TABLE(of, qcom_usb_hs_phy_match);
0279
0280 static struct ulpi_driver qcom_usb_hs_phy_driver = {
0281 .probe = qcom_usb_hs_phy_probe,
0282 .driver = {
0283 .name = "qcom_usb_hs_phy",
0284 .of_match_table = qcom_usb_hs_phy_match,
0285 },
0286 };
0287 module_ulpi_driver(qcom_usb_hs_phy_driver);
0288
0289 MODULE_DESCRIPTION("Qualcomm USB HS phy");
0290 MODULE_LICENSE("GPL v2");