Lines Matching +full:retain +full:- +full:state +full:- +full:shutdown
1 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
3 * platform.c - DesignWare HS OTG Controller platform driver
10 * 1. Redistributions of source code must retain the above copyright
16 * 3. The names of the above-listed copyright holders may not be used
43 #include <linux/dma-mapping.h>
48 #include <linux/platform_data/s3c-hsotg.h>
69 * ------------------------------
71 * HST DEV any : ---
74 * DEV HST any : ---
86 hsotg->dr_mode = usb_get_dr_mode(hsotg->dev); in dwc2_get_dr_mode()
87 if (hsotg->dr_mode == USB_DR_MODE_UNKNOWN) in dwc2_get_dr_mode()
88 hsotg->dr_mode = USB_DR_MODE_OTG; in dwc2_get_dr_mode()
90 mode = hsotg->dr_mode; in dwc2_get_dr_mode()
94 dev_err(hsotg->dev, in dwc2_get_dr_mode()
96 return -EINVAL; in dwc2_get_dr_mode()
101 dev_err(hsotg->dev, in dwc2_get_dr_mode()
103 return -EINVAL; in dwc2_get_dr_mode()
113 if (mode != hsotg->dr_mode) { in dwc2_get_dr_mode()
114 dev_warn(hsotg->dev, in dwc2_get_dr_mode()
118 hsotg->dr_mode = mode; in dwc2_get_dr_mode()
128 regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies); in __dwc2_disable_regulators()
133 struct platform_device *pdev = to_platform_device(hsotg->dev); in __dwc2_lowlevel_hw_enable()
136 ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies), in __dwc2_lowlevel_hw_enable()
137 hsotg->supplies); in __dwc2_lowlevel_hw_enable()
141 ret = devm_add_action_or_reset(&pdev->dev, in __dwc2_lowlevel_hw_enable()
146 if (hsotg->clk) { in __dwc2_lowlevel_hw_enable()
147 ret = clk_prepare_enable(hsotg->clk); in __dwc2_lowlevel_hw_enable()
152 if (hsotg->uphy) { in __dwc2_lowlevel_hw_enable()
153 ret = usb_phy_init(hsotg->uphy); in __dwc2_lowlevel_hw_enable()
154 } else if (hsotg->plat && hsotg->plat->phy_init) { in __dwc2_lowlevel_hw_enable()
155 ret = hsotg->plat->phy_init(pdev, hsotg->plat->phy_type); in __dwc2_lowlevel_hw_enable()
157 ret = phy_power_on(hsotg->phy); in __dwc2_lowlevel_hw_enable()
159 ret = phy_init(hsotg->phy); in __dwc2_lowlevel_hw_enable()
166 * dwc2_lowlevel_hw_enable - enable platform lowlevel hw resources
167 * @hsotg: The driver state
170 * low-level USB platform resources (phy, clock, regulators)
177 hsotg->ll_hw_enabled = true; in dwc2_lowlevel_hw_enable()
183 struct platform_device *pdev = to_platform_device(hsotg->dev); in __dwc2_lowlevel_hw_disable()
186 if (hsotg->uphy) { in __dwc2_lowlevel_hw_disable()
187 usb_phy_shutdown(hsotg->uphy); in __dwc2_lowlevel_hw_disable()
188 } else if (hsotg->plat && hsotg->plat->phy_exit) { in __dwc2_lowlevel_hw_disable()
189 ret = hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type); in __dwc2_lowlevel_hw_disable()
191 ret = phy_exit(hsotg->phy); in __dwc2_lowlevel_hw_disable()
193 ret = phy_power_off(hsotg->phy); in __dwc2_lowlevel_hw_disable()
198 if (hsotg->clk) in __dwc2_lowlevel_hw_disable()
199 clk_disable_unprepare(hsotg->clk); in __dwc2_lowlevel_hw_disable()
205 * dwc2_lowlevel_hw_disable - disable platform lowlevel hw resources
206 * @hsotg: The driver state
209 * low-level USB platform resources (phy, clock, regulators)
216 hsotg->ll_hw_enabled = false; in dwc2_lowlevel_hw_disable()
224 hsotg->reset = devm_reset_control_get_optional(hsotg->dev, "dwc2"); in dwc2_lowlevel_hw_init()
225 if (IS_ERR(hsotg->reset)) { in dwc2_lowlevel_hw_init()
226 ret = PTR_ERR(hsotg->reset); in dwc2_lowlevel_hw_init()
227 dev_err(hsotg->dev, "error getting reset control %d\n", ret); in dwc2_lowlevel_hw_init()
231 reset_control_deassert(hsotg->reset); in dwc2_lowlevel_hw_init()
233 hsotg->reset_ecc = devm_reset_control_get_optional(hsotg->dev, "dwc2-ecc"); in dwc2_lowlevel_hw_init()
234 if (IS_ERR(hsotg->reset_ecc)) { in dwc2_lowlevel_hw_init()
235 ret = PTR_ERR(hsotg->reset_ecc); in dwc2_lowlevel_hw_init()
236 dev_err(hsotg->dev, "error getting reset control for ecc %d\n", ret); in dwc2_lowlevel_hw_init()
240 reset_control_deassert(hsotg->reset_ecc); in dwc2_lowlevel_hw_init()
246 hsotg->phy = devm_phy_get(hsotg->dev, "usb2-phy"); in dwc2_lowlevel_hw_init()
247 if (IS_ERR(hsotg->phy)) { in dwc2_lowlevel_hw_init()
248 ret = PTR_ERR(hsotg->phy); in dwc2_lowlevel_hw_init()
250 case -ENODEV: in dwc2_lowlevel_hw_init()
251 case -ENOSYS: in dwc2_lowlevel_hw_init()
252 hsotg->phy = NULL; in dwc2_lowlevel_hw_init()
254 case -EPROBE_DEFER: in dwc2_lowlevel_hw_init()
257 dev_err(hsotg->dev, "error getting phy %d\n", ret); in dwc2_lowlevel_hw_init()
262 if (!hsotg->phy) { in dwc2_lowlevel_hw_init()
263 hsotg->uphy = devm_usb_get_phy(hsotg->dev, USB_PHY_TYPE_USB2); in dwc2_lowlevel_hw_init()
264 if (IS_ERR(hsotg->uphy)) { in dwc2_lowlevel_hw_init()
265 ret = PTR_ERR(hsotg->uphy); in dwc2_lowlevel_hw_init()
267 case -ENODEV: in dwc2_lowlevel_hw_init()
268 case -ENXIO: in dwc2_lowlevel_hw_init()
269 hsotg->uphy = NULL; in dwc2_lowlevel_hw_init()
271 case -EPROBE_DEFER: in dwc2_lowlevel_hw_init()
274 dev_err(hsotg->dev, "error getting usb phy %d\n", in dwc2_lowlevel_hw_init()
281 hsotg->plat = dev_get_platdata(hsotg->dev); in dwc2_lowlevel_hw_init()
284 hsotg->clk = devm_clk_get_optional(hsotg->dev, "otg"); in dwc2_lowlevel_hw_init()
285 if (IS_ERR(hsotg->clk)) { in dwc2_lowlevel_hw_init()
286 dev_err(hsotg->dev, "cannot get otg clock\n"); in dwc2_lowlevel_hw_init()
287 return PTR_ERR(hsotg->clk); in dwc2_lowlevel_hw_init()
291 for (i = 0; i < ARRAY_SIZE(hsotg->supplies); i++) in dwc2_lowlevel_hw_init()
292 hsotg->supplies[i].supply = dwc2_hsotg_supply_names[i]; in dwc2_lowlevel_hw_init()
294 ret = devm_regulator_bulk_get(hsotg->dev, ARRAY_SIZE(hsotg->supplies), in dwc2_lowlevel_hw_init()
295 hsotg->supplies); in dwc2_lowlevel_hw_init()
297 if (ret != -EPROBE_DEFER) in dwc2_lowlevel_hw_init()
298 dev_err(hsotg->dev, "failed to request supplies: %d\n", in dwc2_lowlevel_hw_init()
306 * dwc2_driver_remove() - Called when the DWC_otg core is unregistered with the
321 if (hsotg->hcd_enabled) in dwc2_driver_remove()
323 if (hsotg->gadget_enabled) in dwc2_driver_remove()
328 if (hsotg->params.activate_stm_id_vb_detection) in dwc2_driver_remove()
329 regulator_disable(hsotg->usb33d); in dwc2_driver_remove()
331 if (hsotg->ll_hw_enabled) in dwc2_driver_remove()
334 reset_control_assert(hsotg->reset); in dwc2_driver_remove()
335 reset_control_assert(hsotg->reset_ecc); in dwc2_driver_remove()
341 * dwc2_driver_shutdown() - Called on device shutdown
348 * at shutdown-time which may bring the system clock below the threshold
349 * of being able to handle the dwc2 interrupts. Disabling dwc2-irqs
357 synchronize_irq(hsotg->irq); in dwc2_driver_shutdown()
361 * dwc2_check_core_endianness() - Returns true if core and AHB have
369 snpsid = ioread32(hsotg->regs + GSNPSID); in dwc2_check_core_endianness()
385 struct dwc2_hw_params *hw = &hsotg->hw_params; in dwc2_check_core_version()
393 hw->snpsid = dwc2_readl(hsotg, GSNPSID); in dwc2_check_core_version()
394 if ((hw->snpsid & GSNPSID_ID_MASK) != DWC2_OTG_ID && in dwc2_check_core_version()
395 (hw->snpsid & GSNPSID_ID_MASK) != DWC2_FS_IOT_ID && in dwc2_check_core_version()
396 (hw->snpsid & GSNPSID_ID_MASK) != DWC2_HS_IOT_ID) { in dwc2_check_core_version()
397 dev_err(hsotg->dev, "Bad value for GSNPSID: 0x%08x\n", in dwc2_check_core_version()
398 hw->snpsid); in dwc2_check_core_version()
399 return -ENODEV; in dwc2_check_core_version()
402 dev_dbg(hsotg->dev, "Core Release: %1x.%1x%1x%1x (snpsid=%x)\n", in dwc2_check_core_version()
403 hw->snpsid >> 12 & 0xf, hw->snpsid >> 8 & 0xf, in dwc2_check_core_version()
404 hw->snpsid >> 4 & 0xf, hw->snpsid & 0xf, hw->snpsid); in dwc2_check_core_version()
409 * dwc2_driver_probe() - Called when the DWC_otg core is bound to the DWC_otg
426 hsotg = devm_kzalloc(&dev->dev, sizeof(*hsotg), GFP_KERNEL); in dwc2_driver_probe()
428 return -ENOMEM; in dwc2_driver_probe()
430 hsotg->dev = &dev->dev; in dwc2_driver_probe()
435 if (!dev->dev.dma_mask) in dwc2_driver_probe()
436 dev->dev.dma_mask = &dev->dev.coherent_dma_mask; in dwc2_driver_probe()
437 retval = dma_set_coherent_mask(&dev->dev, DMA_BIT_MASK(32)); in dwc2_driver_probe()
439 dev_err(&dev->dev, "can't set coherent DMA mask: %d\n", retval); in dwc2_driver_probe()
443 hsotg->regs = devm_platform_get_and_ioremap_resource(dev, 0, &res); in dwc2_driver_probe()
444 if (IS_ERR(hsotg->regs)) in dwc2_driver_probe()
445 return PTR_ERR(hsotg->regs); in dwc2_driver_probe()
447 dev_dbg(&dev->dev, "mapped PA %08lx to VA %p\n", in dwc2_driver_probe()
448 (unsigned long)res->start, hsotg->regs); in dwc2_driver_probe()
454 spin_lock_init(&hsotg->lock); in dwc2_driver_probe()
456 hsotg->irq = platform_get_irq(dev, 0); in dwc2_driver_probe()
457 if (hsotg->irq < 0) in dwc2_driver_probe()
458 return hsotg->irq; in dwc2_driver_probe()
460 dev_dbg(hsotg->dev, "registering common handler for irq%d\n", in dwc2_driver_probe()
461 hsotg->irq); in dwc2_driver_probe()
462 retval = devm_request_irq(hsotg->dev, hsotg->irq, in dwc2_driver_probe()
464 dev_name(hsotg->dev), hsotg); in dwc2_driver_probe()
468 hsotg->vbus_supply = devm_regulator_get_optional(hsotg->dev, "vbus"); in dwc2_driver_probe()
469 if (IS_ERR(hsotg->vbus_supply)) { in dwc2_driver_probe()
470 retval = PTR_ERR(hsotg->vbus_supply); in dwc2_driver_probe()
471 hsotg->vbus_supply = NULL; in dwc2_driver_probe()
472 if (retval != -ENODEV) in dwc2_driver_probe()
480 hsotg->needs_byte_swap = dwc2_check_core_endianness(hsotg); in dwc2_driver_probe()
486 hsotg->need_phy_for_wake = in dwc2_driver_probe()
487 of_property_read_bool(dev->dev.of_node, in dwc2_driver_probe()
488 "snps,need-phy-for-wake"); in dwc2_driver_probe()
499 * Reset before dwc2_get_hwparams() then it could get power-on real in dwc2_driver_probe()
522 if (hsotg->params.activate_stm_id_vb_detection) { in dwc2_driver_probe()
525 hsotg->usb33d = devm_regulator_get(hsotg->dev, "usb33d"); in dwc2_driver_probe()
526 if (IS_ERR(hsotg->usb33d)) { in dwc2_driver_probe()
527 retval = PTR_ERR(hsotg->usb33d); in dwc2_driver_probe()
528 if (retval != -EPROBE_DEFER) in dwc2_driver_probe()
529 dev_err(hsotg->dev, in dwc2_driver_probe()
534 retval = regulator_enable(hsotg->usb33d); in dwc2_driver_probe()
536 dev_err(hsotg->dev, in dwc2_driver_probe()
549 if (retval != -EPROBE_DEFER) in dwc2_driver_probe()
550 dev_err(hsotg->dev, "failed to initialize dual-role\n"); in dwc2_driver_probe()
554 if (hsotg->dr_mode != USB_DR_MODE_HOST) { in dwc2_driver_probe()
558 hsotg->gadget_enabled = 1; in dwc2_driver_probe()
566 if (hsotg->need_phy_for_wake) in dwc2_driver_probe()
567 device_set_wakeup_capable(&dev->dev, true); in dwc2_driver_probe()
569 hsotg->reset_phy_on_wake = in dwc2_driver_probe()
570 of_property_read_bool(dev->dev.of_node, in dwc2_driver_probe()
571 "snps,reset-phy-on-wake"); in dwc2_driver_probe()
572 if (hsotg->reset_phy_on_wake && !hsotg->phy) { in dwc2_driver_probe()
573 dev_warn(hsotg->dev, in dwc2_driver_probe()
574 "Quirk reset-phy-on-wake only supports generic PHYs\n"); in dwc2_driver_probe()
575 hsotg->reset_phy_on_wake = false; in dwc2_driver_probe()
578 if (hsotg->dr_mode != USB_DR_MODE_PERIPHERAL) { in dwc2_driver_probe()
581 if (hsotg->gadget_enabled) in dwc2_driver_probe()
585 hsotg->hcd_enabled = 1; in dwc2_driver_probe()
589 hsotg->hibernated = 0; in dwc2_driver_probe()
594 if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL) in dwc2_driver_probe()
600 if (hsotg->gadget_enabled) { in dwc2_driver_probe()
601 retval = usb_add_gadget_udc(hsotg->dev, &hsotg->gadget); in dwc2_driver_probe()
603 hsotg->gadget.udc = NULL; in dwc2_driver_probe()
615 if (hsotg->hcd_enabled) in dwc2_driver_probe()
622 if (hsotg->params.activate_stm_id_vb_detection) in dwc2_driver_probe()
623 regulator_disable(hsotg->usb33d); in dwc2_driver_probe()
625 if (hsotg->dr_mode != USB_DR_MODE_PERIPHERAL) in dwc2_driver_probe()
641 if (dwc2->params.activate_stm_id_vb_detection) { in dwc2_suspend()
651 spin_lock_irqsave(&dwc2->lock, flags); in dwc2_suspend()
662 spin_unlock_irqrestore(&dwc2->lock, flags); in dwc2_suspend()
669 regulator_disable(dwc2->usb33d); in dwc2_suspend()
672 if (dwc2->ll_hw_enabled && in dwc2_suspend()
675 dwc2->phy_off_for_suspend = true; in dwc2_suspend()
686 if (dwc2->phy_off_for_suspend && dwc2->ll_hw_enabled) { in dwc2_resume()
691 dwc2->phy_off_for_suspend = false; in dwc2_resume()
693 if (dwc2->params.activate_stm_id_vb_detection) { in dwc2_resume()
697 ret = regulator_enable(dwc2->usb33d); in dwc2_resume()
709 spin_lock_irqsave(&dwc2->lock, flags); in dwc2_resume()
715 spin_unlock_irqrestore(&dwc2->lock, flags); in dwc2_resume()
741 .shutdown = dwc2_driver_shutdown,