Lines Matching +full:mpfs +full:- +full:musb

1 // SPDX-License-Identifier: GPL-2.0
3 * PolarFire SoC (MPFS) MUSB Glue Layer
5 * Copyright (c) 2020-2022 Microchip Corporation. All rights reserved.
11 #include <linux/dma-mapping.h>
27 struct platform_device *musb; member
52 static void mpfs_musb_set_vbus(struct musb *musb, int is_on) in mpfs_musb_set_vbus() argument
61 devctl = musb_readb(musb->mregs, MUSB_DEVCTL); in mpfs_musb_set_vbus()
64 musb->is_active = 1; in mpfs_musb_set_vbus()
65 musb->xceiv->otg->default_a = 1; in mpfs_musb_set_vbus()
66 musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; in mpfs_musb_set_vbus()
68 MUSB_HST_MODE(musb); in mpfs_musb_set_vbus()
70 musb->is_active = 0; in mpfs_musb_set_vbus()
73 * NOTE: skipping A_WAIT_VFALL -> A_IDLE and in mpfs_musb_set_vbus()
76 musb->xceiv->otg->default_a = 0; in mpfs_musb_set_vbus()
77 musb->xceiv->otg->state = OTG_STATE_B_IDLE; in mpfs_musb_set_vbus()
80 MUSB_DEV_MODE(musb); in mpfs_musb_set_vbus()
83 musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); in mpfs_musb_set_vbus()
85 dev_dbg(musb->controller, "VBUS %s, devctl %02x\n", in mpfs_musb_set_vbus()
86 usb_otg_state_string(musb->xceiv->otg->state), in mpfs_musb_set_vbus()
87 musb_readb(musb->mregs, MUSB_DEVCTL)); in mpfs_musb_set_vbus()
94 struct musb *musb = from_timer(musb, t, dev_timer); in otg_timer() local
95 void __iomem *mregs = musb->mregs; in otg_timer()
100 * We poll because PolarFire SoC won't expose several OTG-critical in otg_timer()
104 dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl, in otg_timer()
105 usb_otg_state_string(musb->xceiv->otg->state)); in otg_timer()
107 spin_lock_irqsave(&musb->lock, flags); in otg_timer()
108 switch (musb->xceiv->otg->state) { in otg_timer()
111 musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); in otg_timer()
113 devctl = musb_readb(musb->mregs, MUSB_DEVCTL); in otg_timer()
115 musb->xceiv->otg->state = OTG_STATE_B_IDLE; in otg_timer()
116 MUSB_DEV_MODE(musb); in otg_timer()
117 mod_timer(&musb->dev_timer, jiffies + POLL_SECONDS * HZ); in otg_timer()
119 musb->xceiv->otg->state = OTG_STATE_A_IDLE; in otg_timer()
120 MUSB_HST_MODE(musb); in otg_timer()
125 mod_timer(&musb->dev_timer, jiffies + POLL_SECONDS * HZ); in otg_timer()
128 musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; in otg_timer()
132 * There's no ID-changed IRQ, so we have no good way to tell in otg_timer()
133 * when to switch to the A-Default state machine (by setting in otg_timer()
138 * grounded and we're now in the A-Default state machine. in otg_timer()
146 mod_timer(&musb->dev_timer, jiffies + POLL_SECONDS * HZ); in otg_timer()
148 musb->xceiv->otg->state = OTG_STATE_A_IDLE; in otg_timer()
153 spin_unlock_irqrestore(&musb->lock, flags); in otg_timer()
156 static void __maybe_unused mpfs_musb_try_idle(struct musb *musb, unsigned long timeout) in mpfs_musb_try_idle() argument
164 if (musb->is_active || (musb->a_wait_bcon == 0 && in mpfs_musb_try_idle()
165 musb->xceiv->otg->state == OTG_STATE_A_WAIT_BCON)) { in mpfs_musb_try_idle()
166 dev_dbg(musb->controller, "%s active, deleting timer\n", in mpfs_musb_try_idle()
167 usb_otg_state_string(musb->xceiv->otg->state)); in mpfs_musb_try_idle()
168 del_timer(&musb->dev_timer); in mpfs_musb_try_idle()
173 if (time_after(last_timer, timeout) && timer_pending(&musb->dev_timer)) { in mpfs_musb_try_idle()
174 dev_dbg(musb->controller, "Longer idle timer already pending, ignoring...\n"); in mpfs_musb_try_idle()
179 dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n", in mpfs_musb_try_idle()
180 usb_otg_state_string(musb->xceiv->otg->state), in mpfs_musb_try_idle()
181 jiffies_to_msecs(timeout - jiffies)); in mpfs_musb_try_idle()
182 mod_timer(&musb->dev_timer, timeout); in mpfs_musb_try_idle()
189 struct musb *musb = __hci; in mpfs_musb_interrupt() local
191 spin_lock_irqsave(&musb->lock, flags); in mpfs_musb_interrupt()
193 musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB); in mpfs_musb_interrupt()
194 musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX); in mpfs_musb_interrupt()
195 musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX); in mpfs_musb_interrupt()
197 if (musb->int_usb || musb->int_tx || musb->int_rx) { in mpfs_musb_interrupt()
198 musb_writeb(musb->mregs, MUSB_INTRUSB, musb->int_usb); in mpfs_musb_interrupt()
199 musb_writew(musb->mregs, MUSB_INTRTX, musb->int_tx); in mpfs_musb_interrupt()
200 musb_writew(musb->mregs, MUSB_INTRRX, musb->int_rx); in mpfs_musb_interrupt()
201 ret = musb_interrupt(musb); in mpfs_musb_interrupt()
205 if (musb->xceiv->otg->state == OTG_STATE_B_IDLE) in mpfs_musb_interrupt()
206 mod_timer(&musb->dev_timer, jiffies + POLL_SECONDS * HZ); in mpfs_musb_interrupt()
208 spin_unlock_irqrestore(&musb->lock, flags); in mpfs_musb_interrupt()
213 static int mpfs_musb_init(struct musb *musb) in mpfs_musb_init() argument
215 struct device *dev = musb->controller; in mpfs_musb_init()
217 musb->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); in mpfs_musb_init()
218 if (IS_ERR(musb->xceiv)) { in mpfs_musb_init()
220 return PTR_ERR(musb->xceiv); in mpfs_musb_init()
223 timer_setup(&musb->dev_timer, otg_timer, 0); in mpfs_musb_init()
225 musb->dyn_fifo = true; in mpfs_musb_init()
226 musb->isr = mpfs_musb_interrupt; in mpfs_musb_init()
228 musb_platform_set_vbus(musb, 1); in mpfs_musb_init()
233 static int mpfs_musb_exit(struct musb *musb) in mpfs_musb_exit() argument
235 del_timer_sync(&musb->dev_timer); in mpfs_musb_exit()
257 struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev); in mpfs_probe()
260 struct device *dev = &pdev->dev; in mpfs_probe()
266 return -ENOMEM; in mpfs_probe()
268 musb_pdev = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO); in mpfs_probe()
270 dev_err(dev, "failed to allocate musb device\n"); in mpfs_probe()
271 return -ENOMEM; in mpfs_probe()
274 clk = devm_clk_get(&pdev->dev, NULL); in mpfs_probe()
276 dev_err(&pdev->dev, "failed to get clock\n"); in mpfs_probe()
283 dev_err(&pdev->dev, "failed to enable clock\n"); in mpfs_probe()
287 musb_pdev->dev.parent = dev; in mpfs_probe()
288 musb_pdev->dev.coherent_dma_mask = DMA_BIT_MASK(39); in mpfs_probe()
289 musb_pdev->dev.dma_mask = &musb_pdev->dev.coherent_dma_mask; in mpfs_probe()
290 device_set_of_node_from_dev(&musb_pdev->dev, dev); in mpfs_probe()
292 glue->dev = dev; in mpfs_probe()
293 glue->musb = musb_pdev; in mpfs_probe()
294 glue->clk = clk; in mpfs_probe()
298 ret = -ENOMEM; in mpfs_probe()
302 pdata->config = &mpfs_musb_hdrc_config; in mpfs_probe()
303 pdata->platform_ops = &mpfs_ops; in mpfs_probe()
305 pdata->extvbus = device_property_read_bool(dev, "microchip,ext-vbus-drv"); in mpfs_probe()
307 pdata->mode = usb_get_dr_mode(dev); in mpfs_probe()
308 if (pdata->mode == USB_DR_MODE_UNKNOWN) { in mpfs_probe()
310 pdata->mode = USB_DR_MODE_OTG; in mpfs_probe()
313 glue->phy = usb_phy_generic_register(); in mpfs_probe()
314 if (IS_ERR(glue->phy)) { in mpfs_probe()
315 dev_err(dev, "failed to register usb-phy %ld\n", in mpfs_probe()
316 PTR_ERR(glue->phy)); in mpfs_probe()
317 ret = PTR_ERR(glue->phy); in mpfs_probe()
323 ret = platform_device_add_resources(musb_pdev, pdev->resource, pdev->num_resources); in mpfs_probe()
337 dev_err(dev, "failed to register musb device\n"); in mpfs_probe()
341 dev_info(&pdev->dev, "Registered MPFS MUSB driver\n"); in mpfs_probe()
348 usb_phy_generic_unregister(glue->phy); in mpfs_probe()
357 clk_disable_unprepare(glue->clk); in mpfs_remove()
358 platform_device_unregister(glue->musb); in mpfs_remove()
364 { .compatible = "microchip,mpfs-musb" },
374 .name = "mpfs-musb",
381 MODULE_DESCRIPTION("PolarFire SoC MUSB Glue Layer");