Lines Matching +full:control +full:- +full:parent

1 // SPDX-License-Identifier: GPL-2.0+
18 #include <linux/phy/phy-sun4i-usb.h>
95 if (!test_bit(SUNXI_MUSB_FL_ENABLED, &glue->flags)) in sunxi_musb_work()
98 if (test_and_clear_bit(SUNXI_MUSB_FL_HOSTMODE_PEND, &glue->flags)) { in sunxi_musb_work()
99 struct musb *musb = glue->musb; in sunxi_musb_work()
103 spin_lock_irqsave(&musb->lock, flags); in sunxi_musb_work()
105 devctl = readb(musb->mregs + SUNXI_MUSB_DEVCTL); in sunxi_musb_work()
106 if (test_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags)) { in sunxi_musb_work()
107 set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags); in sunxi_musb_work()
108 musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; in sunxi_musb_work()
112 clear_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags); in sunxi_musb_work()
113 musb->xceiv->otg->state = OTG_STATE_B_IDLE; in sunxi_musb_work()
117 writeb(devctl, musb->mregs + SUNXI_MUSB_DEVCTL); in sunxi_musb_work()
119 spin_unlock_irqrestore(&musb->lock, flags); in sunxi_musb_work()
122 vbus_on = test_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags); in sunxi_musb_work()
123 phy_on = test_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags); in sunxi_musb_work()
127 phy_power_on(glue->phy); in sunxi_musb_work()
128 set_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags); in sunxi_musb_work()
130 phy_power_off(glue->phy); in sunxi_musb_work()
131 clear_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags); in sunxi_musb_work()
135 if (test_and_clear_bit(SUNXI_MUSB_FL_PHY_MODE_PEND, &glue->flags)) in sunxi_musb_work()
136 phy_set_mode(glue->phy, glue->phy_mode); in sunxi_musb_work()
141 struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent); in sunxi_musb_set_vbus()
144 set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags); in sunxi_musb_set_vbus()
145 musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; in sunxi_musb_set_vbus()
147 clear_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags); in sunxi_musb_set_vbus()
150 schedule_work(&glue->work); in sunxi_musb_set_vbus()
155 struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent); in sunxi_musb_pre_root_reset_end()
157 sun4i_usb_phy_set_squelch_detect(glue->phy, false); in sunxi_musb_pre_root_reset_end()
162 struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent); in sunxi_musb_post_root_reset_end()
164 sun4i_usb_phy_set_squelch_detect(glue->phy, true); in sunxi_musb_post_root_reset_end()
172 spin_lock_irqsave(&musb->lock, flags); in sunxi_musb_interrupt()
174 musb->int_usb = readb(musb->mregs + SUNXI_MUSB_INTRUSB); in sunxi_musb_interrupt()
175 if (musb->int_usb) in sunxi_musb_interrupt()
176 writeb(musb->int_usb, musb->mregs + SUNXI_MUSB_INTRUSB); in sunxi_musb_interrupt()
178 if ((musb->int_usb & MUSB_INTR_RESET) && !is_host_active(musb)) { in sunxi_musb_interrupt()
180 musb_ep_select(musb->mregs, 0); in sunxi_musb_interrupt()
181 musb_writeb(musb->mregs, MUSB_FADDR, 0); in sunxi_musb_interrupt()
184 musb->int_tx = readw(musb->mregs + SUNXI_MUSB_INTRTX); in sunxi_musb_interrupt()
185 if (musb->int_tx) in sunxi_musb_interrupt()
186 writew(musb->int_tx, musb->mregs + SUNXI_MUSB_INTRTX); in sunxi_musb_interrupt()
188 musb->int_rx = readw(musb->mregs + SUNXI_MUSB_INTRRX); in sunxi_musb_interrupt()
189 if (musb->int_rx) in sunxi_musb_interrupt()
190 writew(musb->int_rx, musb->mregs + SUNXI_MUSB_INTRRX); in sunxi_musb_interrupt()
194 spin_unlock_irqrestore(&musb->lock, flags); in sunxi_musb_interrupt()
205 set_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags); in sunxi_musb_host_notifier()
207 clear_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags); in sunxi_musb_host_notifier()
209 set_bit(SUNXI_MUSB_FL_HOSTMODE_PEND, &glue->flags); in sunxi_musb_host_notifier()
210 schedule_work(&glue->work); in sunxi_musb_host_notifier()
217 struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent); in sunxi_musb_init()
221 musb->phy = glue->phy; in sunxi_musb_init()
222 musb->xceiv = glue->xceiv; in sunxi_musb_init()
224 if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags)) { in sunxi_musb_init()
225 ret = sunxi_sram_claim(musb->controller->parent); in sunxi_musb_init()
230 ret = clk_prepare_enable(glue->clk); in sunxi_musb_init()
234 if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags)) { in sunxi_musb_init()
235 ret = reset_control_deassert(glue->rst); in sunxi_musb_init()
240 writeb(SUNXI_MUSB_VEND0_PIO_MODE, musb->mregs + SUNXI_MUSB_VEND0); in sunxi_musb_init()
243 ret = devm_extcon_register_notifier(glue->dev, glue->extcon, in sunxi_musb_init()
244 EXTCON_USB_HOST, &glue->host_nb); in sunxi_musb_init()
248 ret = phy_init(glue->phy); in sunxi_musb_init()
252 musb->isr = sunxi_musb_interrupt; in sunxi_musb_init()
254 /* Stop the musb-core from doing runtime pm (not supported on sunxi) */ in sunxi_musb_init()
255 pm_runtime_get(musb->controller); in sunxi_musb_init()
260 if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags)) in sunxi_musb_init()
261 reset_control_assert(glue->rst); in sunxi_musb_init()
263 clk_disable_unprepare(glue->clk); in sunxi_musb_init()
265 if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags)) in sunxi_musb_init()
266 sunxi_sram_release(musb->controller->parent); in sunxi_musb_init()
272 struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent); in sunxi_musb_exit()
274 pm_runtime_put(musb->controller); in sunxi_musb_exit()
276 cancel_work_sync(&glue->work); in sunxi_musb_exit()
277 if (test_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags)) in sunxi_musb_exit()
278 phy_power_off(glue->phy); in sunxi_musb_exit()
280 phy_exit(glue->phy); in sunxi_musb_exit()
282 if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags)) in sunxi_musb_exit()
283 reset_control_assert(glue->rst); in sunxi_musb_exit()
285 clk_disable_unprepare(glue->clk); in sunxi_musb_exit()
286 if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags)) in sunxi_musb_exit()
287 sunxi_sram_release(musb->controller->parent); in sunxi_musb_exit()
289 devm_usb_put_phy(glue->dev, glue->xceiv); in sunxi_musb_exit()
296 struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent); in sunxi_musb_enable()
298 glue->musb = musb; in sunxi_musb_enable()
301 if (test_and_set_bit(SUNXI_MUSB_FL_ENABLED, &glue->flags)) in sunxi_musb_enable()
304 schedule_work(&glue->work); in sunxi_musb_enable()
309 struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent); in sunxi_musb_disable()
311 clear_bit(SUNXI_MUSB_FL_ENABLED, &glue->flags); in sunxi_musb_disable()
326 struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent); in sunxi_musb_set_mode()
340 dev_err(musb->controller->parent, in sunxi_musb_set_mode()
342 return -EINVAL; in sunxi_musb_set_mode()
345 if (glue->phy_mode == new_mode) in sunxi_musb_set_mode()
348 if (musb->port_mode != MUSB_OTG) { in sunxi_musb_set_mode()
349 dev_err(musb->controller->parent, in sunxi_musb_set_mode()
351 return -EINVAL; in sunxi_musb_set_mode()
354 if (musb->port1_status & USB_PORT_STAT_ENABLE) in sunxi_musb_set_mode()
361 glue->phy_mode = new_mode; in sunxi_musb_set_mode()
362 set_bit(SUNXI_MUSB_FL_PHY_MODE_PEND, &glue->flags); in sunxi_musb_set_mode()
363 schedule_work(&glue->work); in sunxi_musb_set_mode()
370 struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent); in sunxi_musb_recover()
373 * Schedule a phy_set_mode with the current glue->phy_mode value, in sunxi_musb_recover()
376 set_bit(SUNXI_MUSB_FL_PHY_MODE_PEND, &glue->flags); in sunxi_musb_recover()
377 schedule_work(&glue->work); in sunxi_musb_recover()
384 * 0x00 - 0x17 fifo regs, 1 long per fifo
385 * 0x40 - 0x57 generic control regs (power - frame)
386 * 0x80 - 0x8f ep control regs (addressed through hw_ep->regs, indexed)
387 * 0x90 - 0x97 fifo control regs (indexed)
388 * 0x98 - 0x9f multipoint / busctl regs (indexed)
414 if (addr == sunxi_musb->mregs) { in sunxi_musb_readb()
415 /* generic control or fifo control reg access */ in sunxi_musb_readb()
436 glue = dev_get_drvdata(sunxi_musb->controller->parent); in sunxi_musb_readb()
439 &glue->flags)) in sunxi_musb_readb()
453 dev_err(sunxi_musb->controller->parent, in sunxi_musb_readb()
457 } else if (addr == (sunxi_musb->mregs + 0x80)) { in sunxi_musb_readb()
458 /* ep control reg access */ in sunxi_musb_readb()
465 dev_err(sunxi_musb->controller->parent, in sunxi_musb_readb()
467 (int)(addr - sunxi_musb->mregs)); in sunxi_musb_readb()
473 if (addr == sunxi_musb->mregs) { in sunxi_musb_writeb()
474 /* generic control or fifo control reg access */ in sunxi_musb_writeb()
488 dev_warn(sunxi_musb->controller->parent, in sunxi_musb_writeb()
489 "sunxi-musb does not have testmode\n"); in sunxi_musb_writeb()
507 dev_err(sunxi_musb->controller->parent, in sunxi_musb_writeb()
511 } else if (addr == (sunxi_musb->mregs + 0x80)) { in sunxi_musb_writeb()
512 /* ep control reg access */ in sunxi_musb_writeb()
518 dev_err(sunxi_musb->controller->parent, in sunxi_musb_writeb()
520 (int)(addr - sunxi_musb->mregs)); in sunxi_musb_writeb()
525 if (addr == sunxi_musb->mregs) { in sunxi_musb_readw()
526 /* generic control or fifo control reg access */ in sunxi_musb_readw()
545 dev_err(sunxi_musb->controller->parent, in sunxi_musb_readw()
549 } else if (addr == (sunxi_musb->mregs + 0x80)) { in sunxi_musb_readw()
550 /* ep control reg access */ in sunxi_musb_readw()
554 dev_err(sunxi_musb->controller->parent, in sunxi_musb_readw()
556 (int)(addr - sunxi_musb->mregs)); in sunxi_musb_readw()
562 if (addr == sunxi_musb->mregs) { in sunxi_musb_writew()
563 /* generic control or fifo control reg access */ in sunxi_musb_writew()
580 dev_err(sunxi_musb->controller->parent, in sunxi_musb_writew()
584 } else if (addr == (sunxi_musb->mregs + 0x80)) { in sunxi_musb_writew()
585 /* ep control reg access */ in sunxi_musb_writew()
589 dev_err(sunxi_musb->controller->parent, in sunxi_musb_writew()
591 (int)(addr - sunxi_musb->mregs)); in sunxi_musb_writew()
671 struct device_node *np = pdev->dev.of_node; in sunxi_musb_probe()
675 dev_err(&pdev->dev, "Error no device tree node found\n"); in sunxi_musb_probe()
676 return -EINVAL; in sunxi_musb_probe()
679 glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL); in sunxi_musb_probe()
681 return -ENOMEM; in sunxi_musb_probe()
684 switch (usb_get_dr_mode(&pdev->dev)) { in sunxi_musb_probe()
688 glue->phy_mode = PHY_MODE_USB_HOST; in sunxi_musb_probe()
694 glue->phy_mode = PHY_MODE_USB_DEVICE; in sunxi_musb_probe()
700 glue->phy_mode = PHY_MODE_USB_OTG; in sunxi_musb_probe()
704 dev_err(&pdev->dev, "Invalid or missing 'dr_mode' property\n"); in sunxi_musb_probe()
705 return -EINVAL; in sunxi_musb_probe()
708 if (!of_device_is_compatible(np, "allwinner,sun8i-h3-musb")) in sunxi_musb_probe()
713 glue->dev = &pdev->dev; in sunxi_musb_probe()
714 INIT_WORK(&glue->work, sunxi_musb_work); in sunxi_musb_probe()
715 glue->host_nb.notifier_call = sunxi_musb_host_notifier; in sunxi_musb_probe()
717 if (of_device_is_compatible(np, "allwinner,sun4i-a10-musb")) in sunxi_musb_probe()
718 set_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags); in sunxi_musb_probe()
720 if (of_device_is_compatible(np, "allwinner,sun6i-a31-musb")) in sunxi_musb_probe()
721 set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags); in sunxi_musb_probe()
723 if (of_device_is_compatible(np, "allwinner,sun8i-a33-musb") || in sunxi_musb_probe()
724 of_device_is_compatible(np, "allwinner,sun8i-h3-musb")) { in sunxi_musb_probe()
725 set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags); in sunxi_musb_probe()
726 set_bit(SUNXI_MUSB_FL_NO_CONFIGDATA, &glue->flags); in sunxi_musb_probe()
729 glue->clk = devm_clk_get(&pdev->dev, NULL); in sunxi_musb_probe()
730 if (IS_ERR(glue->clk)) { in sunxi_musb_probe()
731 dev_err(&pdev->dev, "Error getting clock: %ld\n", in sunxi_musb_probe()
732 PTR_ERR(glue->clk)); in sunxi_musb_probe()
733 return PTR_ERR(glue->clk); in sunxi_musb_probe()
736 if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags)) { in sunxi_musb_probe()
737 glue->rst = devm_reset_control_get(&pdev->dev, NULL); in sunxi_musb_probe()
738 if (IS_ERR(glue->rst)) { in sunxi_musb_probe()
739 if (PTR_ERR(glue->rst) == -EPROBE_DEFER) in sunxi_musb_probe()
740 return -EPROBE_DEFER; in sunxi_musb_probe()
741 dev_err(&pdev->dev, "Error getting reset %ld\n", in sunxi_musb_probe()
742 PTR_ERR(glue->rst)); in sunxi_musb_probe()
743 return PTR_ERR(glue->rst); in sunxi_musb_probe()
747 glue->extcon = extcon_get_edev_by_phandle(&pdev->dev, 0); in sunxi_musb_probe()
748 if (IS_ERR(glue->extcon)) { in sunxi_musb_probe()
749 if (PTR_ERR(glue->extcon) == -EPROBE_DEFER) in sunxi_musb_probe()
750 return -EPROBE_DEFER; in sunxi_musb_probe()
751 dev_err(&pdev->dev, "Invalid or missing extcon\n"); in sunxi_musb_probe()
752 return PTR_ERR(glue->extcon); in sunxi_musb_probe()
755 glue->phy = devm_phy_get(&pdev->dev, "usb"); in sunxi_musb_probe()
756 if (IS_ERR(glue->phy)) { in sunxi_musb_probe()
757 if (PTR_ERR(glue->phy) == -EPROBE_DEFER) in sunxi_musb_probe()
758 return -EPROBE_DEFER; in sunxi_musb_probe()
759 dev_err(&pdev->dev, "Error getting phy %ld\n", in sunxi_musb_probe()
760 PTR_ERR(glue->phy)); in sunxi_musb_probe()
761 return PTR_ERR(glue->phy); in sunxi_musb_probe()
764 glue->usb_phy = usb_phy_generic_register(); in sunxi_musb_probe()
765 if (IS_ERR(glue->usb_phy)) { in sunxi_musb_probe()
766 dev_err(&pdev->dev, "Error registering usb-phy %ld\n", in sunxi_musb_probe()
767 PTR_ERR(glue->usb_phy)); in sunxi_musb_probe()
768 return PTR_ERR(glue->usb_phy); in sunxi_musb_probe()
771 glue->xceiv = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); in sunxi_musb_probe()
772 if (IS_ERR(glue->xceiv)) { in sunxi_musb_probe()
773 ret = PTR_ERR(glue->xceiv); in sunxi_musb_probe()
774 dev_err(&pdev->dev, "Error getting usb-phy %d\n", ret); in sunxi_musb_probe()
781 pinfo.name = "musb-hdrc"; in sunxi_musb_probe()
783 pinfo.parent = &pdev->dev; in sunxi_musb_probe()
784 pinfo.fwnode = of_fwnode_handle(pdev->dev.of_node); in sunxi_musb_probe()
786 pinfo.res = pdev->resource; in sunxi_musb_probe()
787 pinfo.num_res = pdev->num_resources; in sunxi_musb_probe()
791 glue->musb_pdev = platform_device_register_full(&pinfo); in sunxi_musb_probe()
792 if (IS_ERR(glue->musb_pdev)) { in sunxi_musb_probe()
793 ret = PTR_ERR(glue->musb_pdev); in sunxi_musb_probe()
794 dev_err(&pdev->dev, "Error registering musb dev: %d\n", ret); in sunxi_musb_probe()
801 usb_phy_generic_unregister(glue->usb_phy); in sunxi_musb_probe()
808 struct platform_device *usb_phy = glue->usb_phy; in sunxi_musb_remove()
810 platform_device_unregister(glue->musb_pdev); in sunxi_musb_remove()
817 { .compatible = "allwinner,sun4i-a10-musb", },
818 { .compatible = "allwinner,sun6i-a31-musb", },
819 { .compatible = "allwinner,sun8i-a33-musb", },
820 { .compatible = "allwinner,sun8i-h3-musb", },
829 .name = "musb-sunxi",