0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/kernel.h>
0012 #include <linux/mfd/syscon.h>
0013 #include <linux/module.h>
0014 #include <linux/phy/phy.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/regmap.h>
0017
0018 #define PERI_CRG_CLK_EN4 0x40
0019 #define PERI_CRG_CLK_DIS4 0x44
0020 #define GT_CLK_USB3OTG_REF BIT(0)
0021 #define GT_ACLK_USB3OTG BIT(1)
0022
0023 #define PERI_CRG_RSTEN4 0x90
0024 #define PERI_CRG_RSTDIS4 0x94
0025 #define IP_RST_USB3OTGPHY_POR BIT(3)
0026 #define IP_RST_USB3OTG BIT(5)
0027
0028 #define PERI_CRG_ISODIS 0x148
0029 #define USB_REFCLK_ISO_EN BIT(25)
0030
0031 #define PCTRL_PERI_CTRL3 0x10
0032 #define PCTRL_PERI_CTRL3_MSK_START 16
0033 #define USB_TCXO_EN BIT(1)
0034
0035 #define PCTRL_PERI_CTRL24 0x64
0036 #define SC_CLK_USB3PHY_3MUX1_SEL BIT(25)
0037
0038 #define USBOTG3_CTRL0 0x00
0039 #define SC_USB3PHY_ABB_GT_EN BIT(15)
0040
0041 #define USBOTG3_CTRL2 0x08
0042 #define USBOTG3CTRL2_POWERDOWN_HSP BIT(0)
0043 #define USBOTG3CTRL2_POWERDOWN_SSP BIT(1)
0044
0045 #define USBOTG3_CTRL3 0x0C
0046 #define USBOTG3_CTRL3_VBUSVLDEXT BIT(6)
0047 #define USBOTG3_CTRL3_VBUSVLDEXTSEL BIT(5)
0048
0049 #define USBOTG3_CTRL4 0x10
0050
0051 #define USBOTG3_CTRL7 0x1c
0052 #define REF_SSP_EN BIT(16)
0053
0054
0055 #define HI3660_USB_DEFAULT_PHY_PARAM 0x1c466e3
0056
0057 struct hi3660_priv {
0058 struct device *dev;
0059 struct regmap *peri_crg;
0060 struct regmap *pctrl;
0061 struct regmap *otg_bc;
0062 u32 eye_diagram_param;
0063 };
0064
0065 static int hi3660_phy_init(struct phy *phy)
0066 {
0067 struct hi3660_priv *priv = phy_get_drvdata(phy);
0068 u32 val, mask;
0069 int ret;
0070
0071
0072 ret = regmap_write(priv->peri_crg, PERI_CRG_ISODIS, USB_REFCLK_ISO_EN);
0073 if (ret)
0074 goto out;
0075
0076
0077 val = USB_TCXO_EN | (USB_TCXO_EN << PCTRL_PERI_CTRL3_MSK_START);
0078 ret = regmap_write(priv->pctrl, PCTRL_PERI_CTRL3, val);
0079 if (ret)
0080 goto out;
0081
0082
0083 val = IP_RST_USB3OTGPHY_POR | IP_RST_USB3OTG;
0084 ret = regmap_write(priv->peri_crg, PERI_CRG_RSTEN4, val);
0085 if (ret)
0086 goto out;
0087
0088
0089 val = SC_USB3PHY_ABB_GT_EN;
0090 mask = val;
0091 ret = regmap_update_bits(priv->otg_bc, USBOTG3_CTRL0, mask, val);
0092 if (ret)
0093 goto out;
0094
0095 val = REF_SSP_EN;
0096 mask = val;
0097 ret = regmap_update_bits(priv->otg_bc, USBOTG3_CTRL7, mask, val);
0098 if (ret)
0099 goto out;
0100
0101
0102 mask = USBOTG3CTRL2_POWERDOWN_HSP | USBOTG3CTRL2_POWERDOWN_SSP;
0103 ret = regmap_update_bits(priv->otg_bc, USBOTG3_CTRL2, mask, 0);
0104 if (ret)
0105 goto out;
0106
0107
0108 usleep_range(100, 120);
0109
0110
0111 val = IP_RST_USB3OTGPHY_POR | IP_RST_USB3OTG;
0112 ret = regmap_write(priv->peri_crg, PERI_CRG_RSTDIS4, val);
0113 if (ret)
0114 goto out;
0115
0116
0117 usleep_range(10000, 15000);
0118
0119
0120 val = USBOTG3_CTRL3_VBUSVLDEXT | USBOTG3_CTRL3_VBUSVLDEXTSEL;
0121 mask = val;
0122 ret = regmap_update_bits(priv->otg_bc, USBOTG3_CTRL3, mask, val);
0123 if (ret)
0124 goto out;
0125
0126
0127 usleep_range(100, 120);
0128
0129 ret = regmap_write(priv->otg_bc, USBOTG3_CTRL4,
0130 priv->eye_diagram_param);
0131 if (ret)
0132 goto out;
0133
0134 return 0;
0135 out:
0136 dev_err(priv->dev, "failed to init phy ret: %d\n", ret);
0137 return ret;
0138 }
0139
0140 static int hi3660_phy_exit(struct phy *phy)
0141 {
0142 struct hi3660_priv *priv = phy_get_drvdata(phy);
0143 u32 val;
0144 int ret;
0145
0146
0147 val = IP_RST_USB3OTGPHY_POR;
0148 ret = regmap_write(priv->peri_crg, PERI_CRG_RSTEN4, val);
0149 if (ret)
0150 goto out;
0151
0152
0153 val = USB_TCXO_EN << PCTRL_PERI_CTRL3_MSK_START;
0154 ret = regmap_write(priv->pctrl, PCTRL_PERI_CTRL3, val);
0155 if (ret)
0156 goto out;
0157
0158 return 0;
0159 out:
0160 dev_err(priv->dev, "failed to exit phy ret: %d\n", ret);
0161 return ret;
0162 }
0163
0164 static const struct phy_ops hi3660_phy_ops = {
0165 .init = hi3660_phy_init,
0166 .exit = hi3660_phy_exit,
0167 .owner = THIS_MODULE,
0168 };
0169
0170 static int hi3660_phy_probe(struct platform_device *pdev)
0171 {
0172 struct phy_provider *phy_provider;
0173 struct device *dev = &pdev->dev;
0174 struct phy *phy;
0175 struct hi3660_priv *priv;
0176
0177 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0178 if (!priv)
0179 return -ENOMEM;
0180
0181 priv->dev = dev;
0182 priv->peri_crg = syscon_regmap_lookup_by_phandle(dev->of_node,
0183 "hisilicon,pericrg-syscon");
0184 if (IS_ERR(priv->peri_crg)) {
0185 dev_err(dev, "no hisilicon,pericrg-syscon\n");
0186 return PTR_ERR(priv->peri_crg);
0187 }
0188
0189 priv->pctrl = syscon_regmap_lookup_by_phandle(dev->of_node,
0190 "hisilicon,pctrl-syscon");
0191 if (IS_ERR(priv->pctrl)) {
0192 dev_err(dev, "no hisilicon,pctrl-syscon\n");
0193 return PTR_ERR(priv->pctrl);
0194 }
0195
0196
0197 priv->otg_bc = syscon_node_to_regmap(dev->parent->of_node);
0198 if (IS_ERR(priv->otg_bc)) {
0199 dev_err(dev, "no hisilicon,usb3-otg-bc-syscon\n");
0200 return PTR_ERR(priv->otg_bc);
0201 }
0202
0203 if (of_property_read_u32(dev->of_node, "hisilicon,eye-diagram-param",
0204 &(priv->eye_diagram_param)))
0205 priv->eye_diagram_param = HI3660_USB_DEFAULT_PHY_PARAM;
0206
0207 phy = devm_phy_create(dev, NULL, &hi3660_phy_ops);
0208 if (IS_ERR(phy))
0209 return PTR_ERR(phy);
0210
0211 phy_set_drvdata(phy, priv);
0212 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
0213 return PTR_ERR_OR_ZERO(phy_provider);
0214 }
0215
0216 static const struct of_device_id hi3660_phy_of_match[] = {
0217 {.compatible = "hisilicon,hi3660-usb-phy",},
0218 { }
0219 };
0220 MODULE_DEVICE_TABLE(of, hi3660_phy_of_match);
0221
0222 static struct platform_driver hi3660_phy_driver = {
0223 .probe = hi3660_phy_probe,
0224 .driver = {
0225 .name = "hi3660-usb-phy",
0226 .of_match_table = hi3660_phy_of_match,
0227 }
0228 };
0229 module_platform_driver(hi3660_phy_driver);
0230
0231 MODULE_AUTHOR("Yu Chen <chenyu56@huawei.com>");
0232 MODULE_LICENSE("GPL v2");
0233 MODULE_DESCRIPTION("Hilisicon Hi3660 USB3 PHY Driver");