0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/init.h>
0009 #include <linux/kernel.h>
0010 #include <linux/module.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/mfd/syscon.h>
0013 #include <linux/of.h>
0014 #include <linux/of_device.h>
0015 #include <linux/pm_runtime.h>
0016 #include <linux/clk.h>
0017 #include <linux/regmap.h>
0018 #include <linux/pinctrl/consumer.h>
0019
0020
0021 #define USBSS_PID 0x0
0022 #define USBSS_OVERCURRENT_CTRL 0x4
0023 #define USBSS_PHY_CONFIG 0x8
0024 #define USBSS_PHY_TEST 0xc
0025 #define USBSS_CORE_STAT 0x14
0026 #define USBSS_HOST_VBUS_CTRL 0x18
0027 #define USBSS_MODE_CONTROL 0x1c
0028 #define USBSS_WAKEUP_CONFIG 0x30
0029 #define USBSS_WAKEUP_STAT 0x34
0030 #define USBSS_OVERRIDE_CONFIG 0x38
0031 #define USBSS_IRQ_MISC_STATUS_RAW 0x430
0032 #define USBSS_IRQ_MISC_STATUS 0x434
0033 #define USBSS_IRQ_MISC_ENABLE_SET 0x438
0034 #define USBSS_IRQ_MISC_ENABLE_CLR 0x43c
0035 #define USBSS_IRQ_MISC_EOI 0x440
0036 #define USBSS_INTR_TEST 0x490
0037 #define USBSS_VBUS_FILTER 0x614
0038 #define USBSS_VBUS_STAT 0x618
0039 #define USBSS_DEBUG_CFG 0x708
0040 #define USBSS_DEBUG_DATA 0x70c
0041 #define USBSS_HOST_HUB_CTRL 0x714
0042
0043
0044 #define USBSS_PHY_VBUS_SEL_MASK GENMASK(2, 1)
0045 #define USBSS_PHY_VBUS_SEL_SHIFT 1
0046 #define USBSS_PHY_LANE_REVERSE BIT(0)
0047
0048
0049 #define USBSS_MODE_VALID BIT(0)
0050
0051
0052 #define USBSS_WAKEUP_CFG_OVERCURRENT_EN BIT(3)
0053 #define USBSS_WAKEUP_CFG_LINESTATE_EN BIT(2)
0054 #define USBSS_WAKEUP_CFG_SESSVALID_EN BIT(1)
0055 #define USBSS_WAKEUP_CFG_VBUSVALID_EN BIT(0)
0056
0057
0058 #define USBSS_WAKEUP_STAT_OVERCURRENT BIT(4)
0059 #define USBSS_WAKEUP_STAT_LINESTATE BIT(3)
0060 #define USBSS_WAKEUP_STAT_SESSVALID BIT(2)
0061 #define USBSS_WAKEUP_STAT_VBUSVALID BIT(1)
0062 #define USBSS_WAKEUP_STAT_CLR BIT(0)
0063
0064
0065 #define USBSS_IRQ_MISC_RAW_VBUSVALID BIT(22)
0066 #define USBSS_IRQ_MISC_RAW_SESSVALID BIT(20)
0067
0068
0069 #define USBSS_IRQ_MISC_VBUSVALID BIT(22)
0070 #define USBSS_IRQ_MISC_SESSVALID BIT(20)
0071
0072
0073 #define USBSS_IRQ_MISC_ENABLE_SET_VBUSVALID BIT(22)
0074 #define USBSS_IRQ_MISC_ENABLE_SET_SESSVALID BIT(20)
0075
0076
0077 #define USBSS_IRQ_MISC_ENABLE_CLR_VBUSVALID BIT(22)
0078 #define USBSS_IRQ_MISC_ENABLE_CLR_SESSVALID BIT(20)
0079
0080
0081 #define USBSS_IRQ_MISC_EOI_VECTOR BIT(0)
0082
0083
0084 #define USBSS_VBUS_STAT_SESSVALID BIT(2)
0085 #define USBSS_VBUS_STAT_VBUSVALID BIT(0)
0086
0087
0088 #define PHY_PLL_REFCLK_MASK GENMASK(3, 0)
0089
0090 #define DWC3_AM62_AUTOSUSPEND_DELAY 100
0091
0092 struct dwc3_data {
0093 struct device *dev;
0094 void __iomem *usbss;
0095 struct clk *usb2_refclk;
0096 int rate_code;
0097 struct regmap *syscon;
0098 unsigned int offset;
0099 unsigned int vbus_divider;
0100 };
0101
0102 static const int dwc3_ti_rate_table[] = {
0103 9600,
0104 10000,
0105 12000,
0106 19200,
0107 20000,
0108 24000,
0109 25000,
0110 26000,
0111 38400,
0112 40000,
0113 58000,
0114 50000,
0115 52000,
0116 };
0117
0118 static inline u32 dwc3_ti_readl(struct dwc3_data *data, u32 offset)
0119 {
0120 return readl((data->usbss) + offset);
0121 }
0122
0123 static inline void dwc3_ti_writel(struct dwc3_data *data, u32 offset, u32 value)
0124 {
0125 writel(value, (data->usbss) + offset);
0126 }
0127
0128 static int phy_syscon_pll_refclk(struct dwc3_data *data)
0129 {
0130 struct device *dev = data->dev;
0131 struct device_node *node = dev->of_node;
0132 struct of_phandle_args args;
0133 struct regmap *syscon;
0134 int ret;
0135
0136 syscon = syscon_regmap_lookup_by_phandle(node, "ti,syscon-phy-pll-refclk");
0137 if (IS_ERR(syscon)) {
0138 dev_err(dev, "unable to get ti,syscon-phy-pll-refclk regmap\n");
0139 return PTR_ERR(syscon);
0140 }
0141
0142 data->syscon = syscon;
0143
0144 ret = of_parse_phandle_with_fixed_args(node, "ti,syscon-phy-pll-refclk", 1,
0145 0, &args);
0146 if (ret)
0147 return ret;
0148
0149 data->offset = args.args[0];
0150
0151 ret = regmap_update_bits(data->syscon, data->offset, PHY_PLL_REFCLK_MASK, data->rate_code);
0152 if (ret) {
0153 dev_err(dev, "failed to set phy pll reference clock rate\n");
0154 return ret;
0155 }
0156
0157 return 0;
0158 }
0159
0160 static int dwc3_ti_probe(struct platform_device *pdev)
0161 {
0162 struct device *dev = &pdev->dev;
0163 struct device_node *node = pdev->dev.of_node;
0164 struct dwc3_data *data;
0165 int i, ret;
0166 unsigned long rate;
0167 u32 reg;
0168
0169 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
0170 if (!data)
0171 return -ENOMEM;
0172
0173 data->dev = dev;
0174 platform_set_drvdata(pdev, data);
0175
0176 data->usbss = devm_platform_ioremap_resource(pdev, 0);
0177 if (IS_ERR(data->usbss)) {
0178 dev_err(dev, "can't map IOMEM resource\n");
0179 return PTR_ERR(data->usbss);
0180 }
0181
0182 data->usb2_refclk = devm_clk_get(dev, "ref");
0183 if (IS_ERR(data->usb2_refclk)) {
0184 dev_err(dev, "can't get usb2_refclk\n");
0185 return PTR_ERR(data->usb2_refclk);
0186 }
0187
0188
0189 rate = clk_get_rate(data->usb2_refclk);
0190 rate /= 1000;
0191 for (i = 0; i < ARRAY_SIZE(dwc3_ti_rate_table); i++) {
0192 if (dwc3_ti_rate_table[i] == rate)
0193 break;
0194 }
0195
0196 if (i == ARRAY_SIZE(dwc3_ti_rate_table)) {
0197 dev_err(dev, "unsupported usb2_refclk rate: %lu KHz\n", rate);
0198 return -EINVAL;
0199 }
0200
0201 data->rate_code = i;
0202
0203
0204 ret = phy_syscon_pll_refclk(data);
0205 if (ret)
0206 return ret;
0207
0208
0209 data->vbus_divider = device_property_read_bool(dev, "ti,vbus-divider");
0210 reg = dwc3_ti_readl(data, USBSS_PHY_CONFIG);
0211 if (data->vbus_divider)
0212 reg |= 1 << USBSS_PHY_VBUS_SEL_SHIFT;
0213
0214 dwc3_ti_writel(data, USBSS_PHY_CONFIG, reg);
0215
0216 pm_runtime_set_active(dev);
0217 pm_runtime_enable(dev);
0218
0219
0220
0221 pm_suspend_ignore_children(dev, false);
0222 clk_prepare_enable(data->usb2_refclk);
0223 pm_runtime_get_noresume(dev);
0224
0225 ret = of_platform_populate(node, NULL, NULL, dev);
0226 if (ret) {
0227 dev_err(dev, "failed to create dwc3 core: %d\n", ret);
0228 goto err_pm_disable;
0229 }
0230
0231
0232 reg = dwc3_ti_readl(data, USBSS_MODE_CONTROL);
0233 reg |= USBSS_MODE_VALID;
0234 dwc3_ti_writel(data, USBSS_MODE_CONTROL, reg);
0235
0236
0237 pm_runtime_set_autosuspend_delay(dev, DWC3_AM62_AUTOSUSPEND_DELAY);
0238 pm_runtime_use_autosuspend(dev);
0239 pm_runtime_mark_last_busy(dev);
0240 pm_runtime_put_autosuspend(dev);
0241 return 0;
0242
0243 err_pm_disable:
0244 clk_disable_unprepare(data->usb2_refclk);
0245 pm_runtime_disable(dev);
0246 pm_runtime_set_suspended(dev);
0247 return ret;
0248 }
0249
0250 static int dwc3_ti_remove_core(struct device *dev, void *c)
0251 {
0252 struct platform_device *pdev = to_platform_device(dev);
0253
0254 platform_device_unregister(pdev);
0255 return 0;
0256 }
0257
0258 static int dwc3_ti_remove(struct platform_device *pdev)
0259 {
0260 struct device *dev = &pdev->dev;
0261 struct dwc3_data *data = platform_get_drvdata(pdev);
0262 u32 reg;
0263
0264 device_for_each_child(dev, NULL, dwc3_ti_remove_core);
0265
0266
0267 reg = dwc3_ti_readl(data, USBSS_MODE_CONTROL);
0268 reg &= ~USBSS_MODE_VALID;
0269 dwc3_ti_writel(data, USBSS_MODE_CONTROL, reg);
0270
0271 pm_runtime_put_sync(dev);
0272 clk_disable_unprepare(data->usb2_refclk);
0273 pm_runtime_disable(dev);
0274 pm_runtime_set_suspended(dev);
0275
0276 platform_set_drvdata(pdev, NULL);
0277 return 0;
0278 }
0279
0280 #ifdef CONFIG_PM
0281 static int dwc3_ti_suspend_common(struct device *dev)
0282 {
0283 struct dwc3_data *data = dev_get_drvdata(dev);
0284
0285 clk_disable_unprepare(data->usb2_refclk);
0286
0287 return 0;
0288 }
0289
0290 static int dwc3_ti_resume_common(struct device *dev)
0291 {
0292 struct dwc3_data *data = dev_get_drvdata(dev);
0293
0294 clk_prepare_enable(data->usb2_refclk);
0295
0296 return 0;
0297 }
0298
0299 static UNIVERSAL_DEV_PM_OPS(dwc3_ti_pm_ops, dwc3_ti_suspend_common,
0300 dwc3_ti_resume_common, NULL);
0301
0302 #define DEV_PM_OPS (&dwc3_ti_pm_ops)
0303 #else
0304 #define DEV_PM_OPS NULL
0305 #endif
0306
0307 static const struct of_device_id dwc3_ti_of_match[] = {
0308 { .compatible = "ti,am62-usb"},
0309 {},
0310 };
0311 MODULE_DEVICE_TABLE(of, dwc3_ti_of_match);
0312
0313 static struct platform_driver dwc3_ti_driver = {
0314 .probe = dwc3_ti_probe,
0315 .remove = dwc3_ti_remove,
0316 .driver = {
0317 .name = "dwc3-am62",
0318 .pm = DEV_PM_OPS,
0319 .of_match_table = dwc3_ti_of_match,
0320 },
0321 };
0322
0323 module_platform_driver(dwc3_ti_driver);
0324
0325 MODULE_ALIAS("platform:dwc3-am62");
0326 MODULE_AUTHOR("Aswath Govindraju <a-govindraju@ti.com>");
0327 MODULE_LICENSE("GPL");
0328 MODULE_DESCRIPTION("DesignWare USB3 TI Glue Layer");