Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
[sfrench/cifs-2.6.git] / drivers / usb / chipidea / ci_hdrc_msm.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2010, Code Aurora Forum. All rights reserved. */
3
4 #include <linux/module.h>
5 #include <linux/platform_device.h>
6 #include <linux/pm_runtime.h>
7 #include <linux/usb/chipidea.h>
8 #include <linux/clk.h>
9 #include <linux/reset.h>
10 #include <linux/mfd/syscon.h>
11 #include <linux/regmap.h>
12 #include <linux/io.h>
13 #include <linux/reset-controller.h>
14 #include <linux/extcon.h>
15 #include <linux/of.h>
16
17 #include "ci.h"
18
19 #define HS_PHY_AHB_MODE                 0x0098
20
21 #define HS_PHY_GENCONFIG                0x009c
22 #define HS_PHY_TXFIFO_IDLE_FORCE_DIS    BIT(4)
23
24 #define HS_PHY_GENCONFIG_2              0x00a0
25 #define HS_PHY_SESS_VLD_CTRL_EN         BIT(7)
26 #define HS_PHY_ULPI_TX_PKT_EN_CLR_FIX   BIT(19)
27
28 #define HSPHY_SESS_VLD_CTRL             BIT(25)
29
30 /* Vendor base starts at 0x200 beyond CI base */
31 #define HS_PHY_CTRL                     0x0040
32 #define HS_PHY_SEC_CTRL                 0x0078
33 #define HS_PHY_DIG_CLAMP_N              BIT(16)
34 #define HS_PHY_POR_ASSERT               BIT(0)
35
36 struct ci_hdrc_msm {
37         struct platform_device *ci;
38         struct clk *core_clk;
39         struct clk *iface_clk;
40         struct clk *fs_clk;
41         struct ci_hdrc_platform_data pdata;
42         struct reset_controller_dev rcdev;
43         bool secondary_phy;
44         bool hsic;
45         void __iomem *base;
46 };
47
48 static int
49 ci_hdrc_msm_por_reset(struct reset_controller_dev *r, unsigned long id)
50 {
51         struct ci_hdrc_msm *ci_msm = container_of(r, struct ci_hdrc_msm, rcdev);
52         void __iomem *addr = ci_msm->base;
53         u32 val;
54
55         if (id)
56                 addr += HS_PHY_SEC_CTRL;
57         else
58                 addr += HS_PHY_CTRL;
59
60         val = readl_relaxed(addr);
61         val |= HS_PHY_POR_ASSERT;
62         writel(val, addr);
63         /*
64          * wait for minimum 10 microseconds as suggested by manual.
65          * Use a slightly larger value since the exact value didn't
66          * work 100% of the time.
67          */
68         udelay(12);
69         val &= ~HS_PHY_POR_ASSERT;
70         writel(val, addr);
71
72         return 0;
73 }
74
75 static const struct reset_control_ops ci_hdrc_msm_reset_ops = {
76         .reset = ci_hdrc_msm_por_reset,
77 };
78
79 static int ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
80 {
81         struct device *dev = ci->dev->parent;
82         struct ci_hdrc_msm *msm_ci = dev_get_drvdata(dev);
83         int ret;
84
85         switch (event) {
86         case CI_HDRC_CONTROLLER_RESET_EVENT:
87                 dev_dbg(dev, "CI_HDRC_CONTROLLER_RESET_EVENT received\n");
88
89                 hw_phymode_configure(ci);
90                 if (msm_ci->secondary_phy) {
91                         u32 val = readl_relaxed(msm_ci->base + HS_PHY_SEC_CTRL);
92                         val |= HS_PHY_DIG_CLAMP_N;
93                         writel_relaxed(val, msm_ci->base + HS_PHY_SEC_CTRL);
94                 }
95
96                 ret = phy_init(ci->phy);
97                 if (ret)
98                         return ret;
99
100                 ret = phy_power_on(ci->phy);
101                 if (ret) {
102                         phy_exit(ci->phy);
103                         return ret;
104                 }
105
106                 /* use AHB transactor, allow posted data writes */
107                 hw_write_id_reg(ci, HS_PHY_AHB_MODE, 0xffffffff, 0x8);
108
109                 /* workaround for rx buffer collision issue */
110                 hw_write_id_reg(ci, HS_PHY_GENCONFIG,
111                                 HS_PHY_TXFIFO_IDLE_FORCE_DIS, 0);
112
113                 if (!msm_ci->hsic)
114                         hw_write_id_reg(ci, HS_PHY_GENCONFIG_2,
115                                         HS_PHY_ULPI_TX_PKT_EN_CLR_FIX, 0);
116
117                 if (!IS_ERR(ci->platdata->vbus_extcon.edev)) {
118                         hw_write_id_reg(ci, HS_PHY_GENCONFIG_2,
119                                         HS_PHY_SESS_VLD_CTRL_EN,
120                                         HS_PHY_SESS_VLD_CTRL_EN);
121                         hw_write(ci, OP_USBCMD, HSPHY_SESS_VLD_CTRL,
122                                  HSPHY_SESS_VLD_CTRL);
123
124                 }
125                 break;
126         case CI_HDRC_CONTROLLER_STOPPED_EVENT:
127                 dev_dbg(dev, "CI_HDRC_CONTROLLER_STOPPED_EVENT received\n");
128                 phy_power_off(ci->phy);
129                 phy_exit(ci->phy);
130                 break;
131         default:
132                 dev_dbg(dev, "unknown ci_hdrc event\n");
133                 break;
134         }
135
136         return 0;
137 }
138
139 static int ci_hdrc_msm_mux_phy(struct ci_hdrc_msm *ci,
140                                struct platform_device *pdev)
141 {
142         struct regmap *regmap;
143         struct device *dev = &pdev->dev;
144         struct of_phandle_args args;
145         u32 val;
146         int ret;
147
148         ret = of_parse_phandle_with_fixed_args(dev->of_node, "phy-select", 2, 0,
149                                                &args);
150         if (ret)
151                 return 0;
152
153         regmap = syscon_node_to_regmap(args.np);
154         of_node_put(args.np);
155         if (IS_ERR(regmap))
156                 return PTR_ERR(regmap);
157
158         ret = regmap_write(regmap, args.args[0], args.args[1]);
159         if (ret)
160                 return ret;
161
162         ci->secondary_phy = !!args.args[1];
163         if (ci->secondary_phy) {
164                 val = readl_relaxed(ci->base + HS_PHY_SEC_CTRL);
165                 val |= HS_PHY_DIG_CLAMP_N;
166                 writel_relaxed(val, ci->base + HS_PHY_SEC_CTRL);
167         }
168
169         return 0;
170 }
171
172 static int ci_hdrc_msm_probe(struct platform_device *pdev)
173 {
174         struct ci_hdrc_msm *ci;
175         struct platform_device *plat_ci;
176         struct clk *clk;
177         struct reset_control *reset;
178         struct resource *res;
179         int ret;
180         struct device_node *ulpi_node, *phy_node;
181
182         dev_dbg(&pdev->dev, "ci_hdrc_msm_probe\n");
183
184         ci = devm_kzalloc(&pdev->dev, sizeof(*ci), GFP_KERNEL);
185         if (!ci)
186                 return -ENOMEM;
187         platform_set_drvdata(pdev, ci);
188
189         ci->pdata.name = "ci_hdrc_msm";
190         ci->pdata.capoffset = DEF_CAPOFFSET;
191         ci->pdata.flags = CI_HDRC_REGS_SHARED | CI_HDRC_DISABLE_STREAMING |
192                           CI_HDRC_OVERRIDE_AHB_BURST |
193                           CI_HDRC_OVERRIDE_PHY_CONTROL;
194         ci->pdata.notify_event = ci_hdrc_msm_notify_event;
195
196         reset = devm_reset_control_get(&pdev->dev, "core");
197         if (IS_ERR(reset))
198                 return PTR_ERR(reset);
199
200         ci->core_clk = clk = devm_clk_get(&pdev->dev, "core");
201         if (IS_ERR(clk))
202                 return PTR_ERR(clk);
203
204         ci->iface_clk = clk = devm_clk_get(&pdev->dev, "iface");
205         if (IS_ERR(clk))
206                 return PTR_ERR(clk);
207
208         ci->fs_clk = clk = devm_clk_get(&pdev->dev, "fs");
209         if (IS_ERR(clk)) {
210                 if (PTR_ERR(clk) == -EPROBE_DEFER)
211                         return -EPROBE_DEFER;
212                 ci->fs_clk = NULL;
213         }
214
215         res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
216         ci->base = devm_ioremap_resource(&pdev->dev, res);
217         if (IS_ERR(ci->base))
218                 return PTR_ERR(ci->base);
219
220         ci->rcdev.owner = THIS_MODULE;
221         ci->rcdev.ops = &ci_hdrc_msm_reset_ops;
222         ci->rcdev.of_node = pdev->dev.of_node;
223         ci->rcdev.nr_resets = 2;
224         ret = reset_controller_register(&ci->rcdev);
225         if (ret)
226                 return ret;
227
228         ret = clk_prepare_enable(ci->fs_clk);
229         if (ret)
230                 goto err_fs;
231
232         reset_control_assert(reset);
233         usleep_range(10000, 12000);
234         reset_control_deassert(reset);
235
236         clk_disable_unprepare(ci->fs_clk);
237
238         ret = clk_prepare_enable(ci->core_clk);
239         if (ret)
240                 goto err_fs;
241
242         ret = clk_prepare_enable(ci->iface_clk);
243         if (ret)
244                 goto err_iface;
245
246         ret = ci_hdrc_msm_mux_phy(ci, pdev);
247         if (ret)
248                 goto err_mux;
249
250         ulpi_node = of_get_child_by_name(pdev->dev.of_node, "ulpi");
251         if (ulpi_node) {
252                 phy_node = of_get_next_available_child(ulpi_node, NULL);
253                 ci->hsic = of_device_is_compatible(phy_node, "qcom,usb-hsic-phy");
254                 of_node_put(phy_node);
255         }
256         of_node_put(ulpi_node);
257
258         plat_ci = ci_hdrc_add_device(&pdev->dev, pdev->resource,
259                                      pdev->num_resources, &ci->pdata);
260         if (IS_ERR(plat_ci)) {
261                 ret = PTR_ERR(plat_ci);
262                 if (ret != -EPROBE_DEFER)
263                         dev_err(&pdev->dev, "ci_hdrc_add_device failed!\n");
264                 goto err_mux;
265         }
266
267         ci->ci = plat_ci;
268
269         pm_runtime_set_active(&pdev->dev);
270         pm_runtime_no_callbacks(&pdev->dev);
271         pm_runtime_enable(&pdev->dev);
272
273         return 0;
274
275 err_mux:
276         clk_disable_unprepare(ci->iface_clk);
277 err_iface:
278         clk_disable_unprepare(ci->core_clk);
279 err_fs:
280         reset_controller_unregister(&ci->rcdev);
281         return ret;
282 }
283
284 static int ci_hdrc_msm_remove(struct platform_device *pdev)
285 {
286         struct ci_hdrc_msm *ci = platform_get_drvdata(pdev);
287
288         pm_runtime_disable(&pdev->dev);
289         ci_hdrc_remove_device(ci->ci);
290         clk_disable_unprepare(ci->iface_clk);
291         clk_disable_unprepare(ci->core_clk);
292         reset_controller_unregister(&ci->rcdev);
293
294         return 0;
295 }
296
297 static const struct of_device_id msm_ci_dt_match[] = {
298         { .compatible = "qcom,ci-hdrc", },
299         { }
300 };
301 MODULE_DEVICE_TABLE(of, msm_ci_dt_match);
302
303 static struct platform_driver ci_hdrc_msm_driver = {
304         .probe = ci_hdrc_msm_probe,
305         .remove = ci_hdrc_msm_remove,
306         .driver = {
307                 .name = "msm_hsusb",
308                 .of_match_table = msm_ci_dt_match,
309         },
310 };
311
312 module_platform_driver(ci_hdrc_msm_driver);
313
314 MODULE_ALIAS("platform:msm_hsusb");
315 MODULE_ALIAS("platform:ci13xxx_msm");
316 MODULE_LICENSE("GPL v2");