1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (C) 2010 ST-Ericsson AB
4*4882a593Smuzhiyun * Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Based on omap2430.c
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include <linux/module.h>
10*4882a593Smuzhiyun #include <linux/kernel.h>
11*4882a593Smuzhiyun #include <linux/clk.h>
12*4882a593Smuzhiyun #include <linux/err.h>
13*4882a593Smuzhiyun #include <linux/io.h>
14*4882a593Smuzhiyun #include <linux/of.h>
15*4882a593Smuzhiyun #include <linux/platform_device.h>
16*4882a593Smuzhiyun #include <linux/usb/musb-ux500.h>
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun #include "musb_core.h"
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun static const struct musb_hdrc_config ux500_musb_hdrc_config = {
21*4882a593Smuzhiyun .multipoint = true,
22*4882a593Smuzhiyun .dyn_fifo = true,
23*4882a593Smuzhiyun .num_eps = 16,
24*4882a593Smuzhiyun .ram_bits = 16,
25*4882a593Smuzhiyun };
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun struct ux500_glue {
28*4882a593Smuzhiyun struct device *dev;
29*4882a593Smuzhiyun struct platform_device *musb;
30*4882a593Smuzhiyun struct clk *clk;
31*4882a593Smuzhiyun };
32*4882a593Smuzhiyun #define glue_to_musb(g) platform_get_drvdata(g->musb)
33*4882a593Smuzhiyun
ux500_musb_set_vbus(struct musb * musb,int is_on)34*4882a593Smuzhiyun static void ux500_musb_set_vbus(struct musb *musb, int is_on)
35*4882a593Smuzhiyun {
36*4882a593Smuzhiyun u8 devctl;
37*4882a593Smuzhiyun unsigned long timeout = jiffies + msecs_to_jiffies(1000);
38*4882a593Smuzhiyun /* HDRC controls CPEN, but beware current surges during device
39*4882a593Smuzhiyun * connect. They can trigger transient overcurrent conditions
40*4882a593Smuzhiyun * that must be ignored.
41*4882a593Smuzhiyun */
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun if (is_on) {
46*4882a593Smuzhiyun if (musb->xceiv->otg->state == OTG_STATE_A_IDLE) {
47*4882a593Smuzhiyun /* start the session */
48*4882a593Smuzhiyun devctl |= MUSB_DEVCTL_SESSION;
49*4882a593Smuzhiyun musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
50*4882a593Smuzhiyun /*
51*4882a593Smuzhiyun * Wait for the musb to set as A device to enable the
52*4882a593Smuzhiyun * VBUS
53*4882a593Smuzhiyun */
54*4882a593Smuzhiyun while (musb_readb(musb->mregs, MUSB_DEVCTL) & 0x80) {
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun if (time_after(jiffies, timeout)) {
57*4882a593Smuzhiyun dev_err(musb->controller,
58*4882a593Smuzhiyun "configured as A device timeout");
59*4882a593Smuzhiyun break;
60*4882a593Smuzhiyun }
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun } else {
64*4882a593Smuzhiyun musb->is_active = 1;
65*4882a593Smuzhiyun musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
66*4882a593Smuzhiyun devctl |= MUSB_DEVCTL_SESSION;
67*4882a593Smuzhiyun MUSB_HST_MODE(musb);
68*4882a593Smuzhiyun }
69*4882a593Smuzhiyun } else {
70*4882a593Smuzhiyun musb->is_active = 0;
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun /* NOTE: we're skipping A_WAIT_VFALL -> A_IDLE and jumping
73*4882a593Smuzhiyun * right to B_IDLE...
74*4882a593Smuzhiyun */
75*4882a593Smuzhiyun devctl &= ~MUSB_DEVCTL_SESSION;
76*4882a593Smuzhiyun MUSB_DEV_MODE(musb);
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun /*
81*4882a593Smuzhiyun * Devctl values will be updated after vbus goes below
82*4882a593Smuzhiyun * session_valid. The time taken depends on the capacitance
83*4882a593Smuzhiyun * on VBUS line. The max discharge time can be upto 1 sec
84*4882a593Smuzhiyun * as per the spec. Typically on our platform, it is 200ms
85*4882a593Smuzhiyun */
86*4882a593Smuzhiyun if (!is_on)
87*4882a593Smuzhiyun mdelay(200);
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun dev_dbg(musb->controller, "VBUS %s, devctl %02x\n",
90*4882a593Smuzhiyun usb_otg_state_string(musb->xceiv->otg->state),
91*4882a593Smuzhiyun musb_readb(musb->mregs, MUSB_DEVCTL));
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun
musb_otg_notifications(struct notifier_block * nb,unsigned long event,void * unused)94*4882a593Smuzhiyun static int musb_otg_notifications(struct notifier_block *nb,
95*4882a593Smuzhiyun unsigned long event, void *unused)
96*4882a593Smuzhiyun {
97*4882a593Smuzhiyun struct musb *musb = container_of(nb, struct musb, nb);
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun dev_dbg(musb->controller, "musb_otg_notifications %ld %s\n",
100*4882a593Smuzhiyun event, usb_otg_state_string(musb->xceiv->otg->state));
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun switch (event) {
103*4882a593Smuzhiyun case UX500_MUSB_ID:
104*4882a593Smuzhiyun dev_dbg(musb->controller, "ID GND\n");
105*4882a593Smuzhiyun ux500_musb_set_vbus(musb, 1);
106*4882a593Smuzhiyun break;
107*4882a593Smuzhiyun case UX500_MUSB_VBUS:
108*4882a593Smuzhiyun dev_dbg(musb->controller, "VBUS Connect\n");
109*4882a593Smuzhiyun break;
110*4882a593Smuzhiyun case UX500_MUSB_NONE:
111*4882a593Smuzhiyun dev_dbg(musb->controller, "VBUS Disconnect\n");
112*4882a593Smuzhiyun if (is_host_active(musb))
113*4882a593Smuzhiyun ux500_musb_set_vbus(musb, 0);
114*4882a593Smuzhiyun else
115*4882a593Smuzhiyun musb->xceiv->otg->state = OTG_STATE_B_IDLE;
116*4882a593Smuzhiyun break;
117*4882a593Smuzhiyun default:
118*4882a593Smuzhiyun dev_dbg(musb->controller, "ID float\n");
119*4882a593Smuzhiyun return NOTIFY_DONE;
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun return NOTIFY_OK;
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun
ux500_musb_interrupt(int irq,void * __hci)124*4882a593Smuzhiyun static irqreturn_t ux500_musb_interrupt(int irq, void *__hci)
125*4882a593Smuzhiyun {
126*4882a593Smuzhiyun unsigned long flags;
127*4882a593Smuzhiyun irqreturn_t retval = IRQ_NONE;
128*4882a593Smuzhiyun struct musb *musb = __hci;
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun spin_lock_irqsave(&musb->lock, flags);
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
133*4882a593Smuzhiyun musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
134*4882a593Smuzhiyun musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun if (musb->int_usb || musb->int_tx || musb->int_rx)
137*4882a593Smuzhiyun retval = musb_interrupt(musb);
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun spin_unlock_irqrestore(&musb->lock, flags);
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun return retval;
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun
ux500_musb_init(struct musb * musb)144*4882a593Smuzhiyun static int ux500_musb_init(struct musb *musb)
145*4882a593Smuzhiyun {
146*4882a593Smuzhiyun int status;
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
149*4882a593Smuzhiyun if (IS_ERR_OR_NULL(musb->xceiv)) {
150*4882a593Smuzhiyun pr_err("HS USB OTG: no transceiver configured\n");
151*4882a593Smuzhiyun return -EPROBE_DEFER;
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun musb->nb.notifier_call = musb_otg_notifications;
155*4882a593Smuzhiyun status = usb_register_notifier(musb->xceiv, &musb->nb);
156*4882a593Smuzhiyun if (status < 0) {
157*4882a593Smuzhiyun dev_dbg(musb->controller, "notification register failed\n");
158*4882a593Smuzhiyun return status;
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun musb->isr = ux500_musb_interrupt;
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun return 0;
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun
ux500_musb_exit(struct musb * musb)166*4882a593Smuzhiyun static int ux500_musb_exit(struct musb *musb)
167*4882a593Smuzhiyun {
168*4882a593Smuzhiyun usb_unregister_notifier(musb->xceiv, &musb->nb);
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun usb_put_phy(musb->xceiv);
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun return 0;
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun static const struct musb_platform_ops ux500_ops = {
176*4882a593Smuzhiyun .quirks = MUSB_DMA_UX500 | MUSB_INDEXED_EP,
177*4882a593Smuzhiyun #ifdef CONFIG_USB_UX500_DMA
178*4882a593Smuzhiyun .dma_init = ux500_dma_controller_create,
179*4882a593Smuzhiyun .dma_exit = ux500_dma_controller_destroy,
180*4882a593Smuzhiyun #endif
181*4882a593Smuzhiyun .init = ux500_musb_init,
182*4882a593Smuzhiyun .exit = ux500_musb_exit,
183*4882a593Smuzhiyun .fifo_mode = 5,
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun .set_vbus = ux500_musb_set_vbus,
186*4882a593Smuzhiyun };
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun static struct musb_hdrc_platform_data *
ux500_of_probe(struct platform_device * pdev,struct device_node * np)189*4882a593Smuzhiyun ux500_of_probe(struct platform_device *pdev, struct device_node *np)
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun struct musb_hdrc_platform_data *pdata;
192*4882a593Smuzhiyun const char *mode;
193*4882a593Smuzhiyun int strlen;
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
196*4882a593Smuzhiyun if (!pdata)
197*4882a593Smuzhiyun return NULL;
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun mode = of_get_property(np, "dr_mode", &strlen);
200*4882a593Smuzhiyun if (!mode) {
201*4882a593Smuzhiyun dev_err(&pdev->dev, "No 'dr_mode' property found\n");
202*4882a593Smuzhiyun return NULL;
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun if (strlen > 0) {
206*4882a593Smuzhiyun if (!strcmp(mode, "host"))
207*4882a593Smuzhiyun pdata->mode = MUSB_HOST;
208*4882a593Smuzhiyun if (!strcmp(mode, "otg"))
209*4882a593Smuzhiyun pdata->mode = MUSB_OTG;
210*4882a593Smuzhiyun if (!strcmp(mode, "peripheral"))
211*4882a593Smuzhiyun pdata->mode = MUSB_PERIPHERAL;
212*4882a593Smuzhiyun }
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun return pdata;
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun
ux500_probe(struct platform_device * pdev)217*4882a593Smuzhiyun static int ux500_probe(struct platform_device *pdev)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun struct resource musb_resources[2];
220*4882a593Smuzhiyun struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev);
221*4882a593Smuzhiyun struct device_node *np = pdev->dev.of_node;
222*4882a593Smuzhiyun struct platform_device *musb;
223*4882a593Smuzhiyun struct ux500_glue *glue;
224*4882a593Smuzhiyun struct clk *clk;
225*4882a593Smuzhiyun int ret = -ENOMEM;
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun if (!pdata) {
228*4882a593Smuzhiyun if (np) {
229*4882a593Smuzhiyun pdata = ux500_of_probe(pdev, np);
230*4882a593Smuzhiyun if (!pdata)
231*4882a593Smuzhiyun goto err0;
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun pdev->dev.platform_data = pdata;
234*4882a593Smuzhiyun } else {
235*4882a593Smuzhiyun dev_err(&pdev->dev, "no pdata or device tree found\n");
236*4882a593Smuzhiyun goto err0;
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
241*4882a593Smuzhiyun if (!glue)
242*4882a593Smuzhiyun goto err0;
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
245*4882a593Smuzhiyun if (!musb) {
246*4882a593Smuzhiyun dev_err(&pdev->dev, "failed to allocate musb device\n");
247*4882a593Smuzhiyun goto err0;
248*4882a593Smuzhiyun }
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun clk = devm_clk_get(&pdev->dev, NULL);
251*4882a593Smuzhiyun if (IS_ERR(clk)) {
252*4882a593Smuzhiyun dev_err(&pdev->dev, "failed to get clock\n");
253*4882a593Smuzhiyun ret = PTR_ERR(clk);
254*4882a593Smuzhiyun goto err1;
255*4882a593Smuzhiyun }
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun ret = clk_prepare_enable(clk);
258*4882a593Smuzhiyun if (ret) {
259*4882a593Smuzhiyun dev_err(&pdev->dev, "failed to enable clock\n");
260*4882a593Smuzhiyun goto err1;
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun musb->dev.parent = &pdev->dev;
264*4882a593Smuzhiyun musb->dev.dma_mask = &pdev->dev.coherent_dma_mask;
265*4882a593Smuzhiyun musb->dev.coherent_dma_mask = pdev->dev.coherent_dma_mask;
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun glue->dev = &pdev->dev;
268*4882a593Smuzhiyun glue->musb = musb;
269*4882a593Smuzhiyun glue->clk = clk;
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun pdata->platform_ops = &ux500_ops;
272*4882a593Smuzhiyun pdata->config = &ux500_musb_hdrc_config;
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun platform_set_drvdata(pdev, glue);
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun memset(musb_resources, 0x00, sizeof(*musb_resources) *
277*4882a593Smuzhiyun ARRAY_SIZE(musb_resources));
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun musb_resources[0].name = pdev->resource[0].name;
280*4882a593Smuzhiyun musb_resources[0].start = pdev->resource[0].start;
281*4882a593Smuzhiyun musb_resources[0].end = pdev->resource[0].end;
282*4882a593Smuzhiyun musb_resources[0].flags = pdev->resource[0].flags;
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun musb_resources[1].name = pdev->resource[1].name;
285*4882a593Smuzhiyun musb_resources[1].start = pdev->resource[1].start;
286*4882a593Smuzhiyun musb_resources[1].end = pdev->resource[1].end;
287*4882a593Smuzhiyun musb_resources[1].flags = pdev->resource[1].flags;
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun ret = platform_device_add_resources(musb, musb_resources,
290*4882a593Smuzhiyun ARRAY_SIZE(musb_resources));
291*4882a593Smuzhiyun if (ret) {
292*4882a593Smuzhiyun dev_err(&pdev->dev, "failed to add resources\n");
293*4882a593Smuzhiyun goto err2;
294*4882a593Smuzhiyun }
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
297*4882a593Smuzhiyun if (ret) {
298*4882a593Smuzhiyun dev_err(&pdev->dev, "failed to add platform_data\n");
299*4882a593Smuzhiyun goto err2;
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun ret = platform_device_add(musb);
303*4882a593Smuzhiyun if (ret) {
304*4882a593Smuzhiyun dev_err(&pdev->dev, "failed to register musb device\n");
305*4882a593Smuzhiyun goto err2;
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun return 0;
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun err2:
311*4882a593Smuzhiyun clk_disable_unprepare(clk);
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun err1:
314*4882a593Smuzhiyun platform_device_put(musb);
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun err0:
317*4882a593Smuzhiyun return ret;
318*4882a593Smuzhiyun }
319*4882a593Smuzhiyun
ux500_remove(struct platform_device * pdev)320*4882a593Smuzhiyun static int ux500_remove(struct platform_device *pdev)
321*4882a593Smuzhiyun {
322*4882a593Smuzhiyun struct ux500_glue *glue = platform_get_drvdata(pdev);
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun platform_device_unregister(glue->musb);
325*4882a593Smuzhiyun clk_disable_unprepare(glue->clk);
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun return 0;
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
ux500_suspend(struct device * dev)331*4882a593Smuzhiyun static int ux500_suspend(struct device *dev)
332*4882a593Smuzhiyun {
333*4882a593Smuzhiyun struct ux500_glue *glue = dev_get_drvdata(dev);
334*4882a593Smuzhiyun struct musb *musb = glue_to_musb(glue);
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun if (musb)
337*4882a593Smuzhiyun usb_phy_set_suspend(musb->xceiv, 1);
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun clk_disable_unprepare(glue->clk);
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun return 0;
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun
ux500_resume(struct device * dev)344*4882a593Smuzhiyun static int ux500_resume(struct device *dev)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun struct ux500_glue *glue = dev_get_drvdata(dev);
347*4882a593Smuzhiyun struct musb *musb = glue_to_musb(glue);
348*4882a593Smuzhiyun int ret;
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun ret = clk_prepare_enable(glue->clk);
351*4882a593Smuzhiyun if (ret) {
352*4882a593Smuzhiyun dev_err(dev, "failed to enable clock\n");
353*4882a593Smuzhiyun return ret;
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun if (musb)
357*4882a593Smuzhiyun usb_phy_set_suspend(musb->xceiv, 0);
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun return 0;
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun #endif
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun static SIMPLE_DEV_PM_OPS(ux500_pm_ops, ux500_suspend, ux500_resume);
364*4882a593Smuzhiyun
365*4882a593Smuzhiyun static const struct of_device_id ux500_match[] = {
366*4882a593Smuzhiyun { .compatible = "stericsson,db8500-musb", },
367*4882a593Smuzhiyun {}
368*4882a593Smuzhiyun };
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, ux500_match);
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun static struct platform_driver ux500_driver = {
373*4882a593Smuzhiyun .probe = ux500_probe,
374*4882a593Smuzhiyun .remove = ux500_remove,
375*4882a593Smuzhiyun .driver = {
376*4882a593Smuzhiyun .name = "musb-ux500",
377*4882a593Smuzhiyun .pm = &ux500_pm_ops,
378*4882a593Smuzhiyun .of_match_table = ux500_match,
379*4882a593Smuzhiyun },
380*4882a593Smuzhiyun };
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun MODULE_DESCRIPTION("UX500 MUSB Glue Layer");
383*4882a593Smuzhiyun MODULE_AUTHOR("Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>");
384*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
385*4882a593Smuzhiyun module_platform_driver(ux500_driver);
386