Lines Matching +full:self +full:- +full:power

1 // SPDX-License-Identifier: GPL-1.0+
6 * Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
11 * Based on ohci-omap.c
16 #include <linux/arm-smccc.h>
18 #include <linux/dma-mapping.h>
30 #include <soc/at91/atmel-sfr.h>
40 ((struct ohci_at91_priv *)hcd_to_ohci(h)->priv)
57 bool wakeup; /* Saved wake-up state for resume */
71 /*-------------------------------------------------------------------------*/
75 if (ohci_at91->clocked) in at91_start_clock()
78 clk_set_rate(ohci_at91->fclk, 48000000); in at91_start_clock()
79 clk_prepare_enable(ohci_at91->hclk); in at91_start_clock()
80 clk_prepare_enable(ohci_at91->iclk); in at91_start_clock()
81 clk_prepare_enable(ohci_at91->fclk); in at91_start_clock()
82 ohci_at91->clocked = true; in at91_start_clock()
87 if (!ohci_at91->clocked) in at91_stop_clock()
90 clk_disable_unprepare(ohci_at91->fclk); in at91_stop_clock()
91 clk_disable_unprepare(ohci_at91->iclk); in at91_stop_clock()
92 clk_disable_unprepare(ohci_at91->hclk); in at91_stop_clock()
93 ohci_at91->clocked = false; in at91_stop_clock()
99 struct ohci_regs __iomem *regs = hcd->regs; in at91_start_hc()
102 dev_dbg(&pdev->dev, "start\n"); in at91_start_hc()
112 writel(0, &regs->control); in at91_start_hc()
120 dev_dbg(&pdev->dev, "stop\n"); in at91_stop_hc()
134 /*-------------------------------------------------------------------------*/
142 if (!dev->of_node) in at91_dt_suspend_smc()
145 if (of_property_read_u32(dev->of_node, "microchip,suspend-smc-id", &suspend_smc_id)) in at91_dt_suspend_smc()
155 regmap = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr"); in at91_dt_syscon_sfr()
157 regmap = syscon_regmap_lookup_by_compatible("microchip,sam9x60-sfr"); in at91_dt_syscon_sfr()
170 * usb_hcd_at91_probe - initialize AT91-based HCDs
188 struct device *dev = &pdev->dev; in usb_hcd_at91_probe()
198 return -ENOMEM; in usb_hcd_at91_probe()
201 hcd->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); in usb_hcd_at91_probe()
202 if (IS_ERR(hcd->regs)) { in usb_hcd_at91_probe()
203 retval = PTR_ERR(hcd->regs); in usb_hcd_at91_probe()
206 hcd->rsrc_start = res->start; in usb_hcd_at91_probe()
207 hcd->rsrc_len = resource_size(res); in usb_hcd_at91_probe()
209 ohci_at91->iclk = devm_clk_get(dev, "ohci_clk"); in usb_hcd_at91_probe()
210 if (IS_ERR(ohci_at91->iclk)) { in usb_hcd_at91_probe()
212 retval = PTR_ERR(ohci_at91->iclk); in usb_hcd_at91_probe()
215 ohci_at91->fclk = devm_clk_get(dev, "uhpck"); in usb_hcd_at91_probe()
216 if (IS_ERR(ohci_at91->fclk)) { in usb_hcd_at91_probe()
218 retval = PTR_ERR(ohci_at91->fclk); in usb_hcd_at91_probe()
221 ohci_at91->hclk = devm_clk_get(dev, "hclk"); in usb_hcd_at91_probe()
222 if (IS_ERR(ohci_at91->hclk)) { in usb_hcd_at91_probe()
224 retval = PTR_ERR(ohci_at91->hclk); in usb_hcd_at91_probe()
228 ohci_at91->suspend_smc_id = at91_dt_suspend_smc(dev); in usb_hcd_at91_probe()
229 if (!ohci_at91->suspend_smc_id) { in usb_hcd_at91_probe()
231 ohci_at91->sfr_regmap = at91_dt_syscon_sfr(); in usb_hcd_at91_probe()
232 if (!ohci_at91->sfr_regmap) in usb_hcd_at91_probe()
236 board = hcd->self.controller->platform_data; in usb_hcd_at91_probe()
238 ohci->num_ports = board->ports; in usb_hcd_at91_probe()
245 ohci->hc_control = OHCI_CTRL_RWC; in usb_hcd_at91_probe()
249 device_wakeup_enable(hcd->self.controller); in usb_hcd_at91_probe()
265 * usb_hcd_at91_remove - shutdown processing for AT91-based HCDs
283 /*-------------------------------------------------------------------------*/
289 gpiod_set_value(pdata->vbus_pin[port], enable); in ohci_at91_usb_set_power()
295 return -EINVAL; in ohci_at91_usb_get_power()
297 return gpiod_get_value(pdata->vbus_pin[port]); in ohci_at91_usb_get_power()
301 * Update the status data from the hub with the over-current indicator change.
305 struct at91_usbh_data *pdata = hcd->self.controller->platform_data; in ohci_at91_hub_status_data()
310 if (pdata->overcurrent_changed[port]) { in ohci_at91_hub_status_data()
322 struct regmap *regmap = ohci_at91->sfr_regmap; in ohci_at91_port_suspend()
326 if (ohci_at91->suspend_smc_id) { in ohci_at91_port_suspend()
329 arm_smccc_smc(ohci_at91->suspend_smc_id, set, 0, 0, 0, 0, 0, 0, &res); in ohci_at91_port_suspend()
331 return -EINVAL; in ohci_at91_port_suspend()
354 struct at91_usbh_data *pdata = dev_get_platdata(hcd->self.controller); in ohci_at91_hub_control()
357 int ret = -EINVAL; in ohci_at91_hub_control()
360 dev_dbg(hcd->self.controller, in ohci_at91_hub_control()
364 wIndex--; in ohci_at91_hub_control()
370 dev_dbg(hcd->self.controller, "SetPortFeat: POWER\n"); in ohci_at91_hub_control()
379 dev_dbg(hcd->self.controller, "SetPortFeat: SUSPEND\n"); in ohci_at91_hub_control()
391 dev_dbg(hcd->self.controller, in ohci_at91_hub_control()
395 pdata->overcurrent_changed[wIndex] = 0; in ohci_at91_hub_control()
396 pdata->overcurrent_status[wIndex] = 0; in ohci_at91_hub_control()
402 dev_dbg(hcd->self.controller, in ohci_at91_hub_control()
406 pdata->overcurrent_status[wIndex] = 0; in ohci_at91_hub_control()
411 dev_dbg(hcd->self.controller, in ohci_at91_hub_control()
412 "ClearPortFeature: POWER\n"); in ohci_at91_hub_control()
421 dev_dbg(hcd->self.controller, "ClearPortFeature: SUSPEND\n"); in ohci_at91_hub_control()
442 dev_dbg(hcd->self.controller, "wHubCharacteristics 0x%04x\n", in ohci_at91_hub_control()
443 desc->wHubCharacteristics); in ohci_at91_hub_control()
445 /* remove the old configurations for power-switching, and in ohci_at91_hub_control()
446 * over-current protection, and insert our new configuration in ohci_at91_hub_control()
449 desc->wHubCharacteristics &= ~cpu_to_le16(HUB_CHAR_LPSM); in ohci_at91_hub_control()
450 desc->wHubCharacteristics |= in ohci_at91_hub_control()
453 if (pdata->overcurrent_supported) { in ohci_at91_hub_control()
454 desc->wHubCharacteristics &= ~cpu_to_le16(HUB_CHAR_OCPM); in ohci_at91_hub_control()
455 desc->wHubCharacteristics |= in ohci_at91_hub_control()
459 dev_dbg(hcd->self.controller, "wHubCharacteristics after 0x%04x\n", in ohci_at91_hub_control()
460 desc->wHubCharacteristics); in ohci_at91_hub_control()
467 dev_dbg(hcd->self.controller, "GetPortStatus(%d)\n", wIndex); in ohci_at91_hub_control()
473 if (pdata->overcurrent_changed[wIndex]) in ohci_at91_hub_control()
476 if (pdata->overcurrent_status[wIndex]) in ohci_at91_hub_control()
485 /*-------------------------------------------------------------------------*/
490 struct at91_usbh_data *pdata = dev_get_platdata(&pdev->dev); in ohci_hcd_at91_overcurrent_irq()
493 /* From the GPIO notifying the over-current situation, find in ohci_hcd_at91_overcurrent_irq()
496 if (gpiod_to_irq(pdata->overcurrent_pin[port]) == irq) in ohci_hcd_at91_overcurrent_irq()
501 dev_err(& pdev->dev, "overcurrent interrupt from unknown GPIO\n"); in ohci_hcd_at91_overcurrent_irq()
505 val = gpiod_get_value(pdata->overcurrent_pin[port]); in ohci_hcd_at91_overcurrent_irq()
507 /* When notified of an over-current situation, disable power in ohci_hcd_at91_overcurrent_irq()
509 over-current. */ in ohci_hcd_at91_overcurrent_irq()
512 pdata->overcurrent_status[port] = 1; in ohci_hcd_at91_overcurrent_irq()
513 pdata->overcurrent_changed[port] = 1; in ohci_hcd_at91_overcurrent_irq()
516 dev_dbg(& pdev->dev, "overcurrent situation %s\n", in ohci_hcd_at91_overcurrent_irq()
523 { .compatible = "atmel,at91rm9200-ohci" },
529 /*-------------------------------------------------------------------------*/
533 struct device_node *np = pdev->dev.of_node; in ohci_hcd_at91_drv_probe()
540 /* Right now device-tree probed devices don't get dma_mask set. in ohci_hcd_at91_drv_probe()
544 ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); in ohci_hcd_at91_drv_probe()
548 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); in ohci_hcd_at91_drv_probe()
550 return -ENOMEM; in ohci_hcd_at91_drv_probe()
552 pdev->dev.platform_data = pdata; in ohci_hcd_at91_drv_probe()
554 if (!of_property_read_u32(np, "num-ports", &ports)) in ohci_hcd_at91_drv_probe()
555 pdata->ports = ports; in ohci_hcd_at91_drv_probe()
558 if (i >= pdata->ports) in ohci_hcd_at91_drv_probe()
561 pdata->vbus_pin[i] = in ohci_hcd_at91_drv_probe()
562 devm_gpiod_get_index_optional(&pdev->dev, "atmel,vbus", in ohci_hcd_at91_drv_probe()
564 if (IS_ERR(pdata->vbus_pin[i])) { in ohci_hcd_at91_drv_probe()
565 err = PTR_ERR(pdata->vbus_pin[i]); in ohci_hcd_at91_drv_probe()
566 dev_err(&pdev->dev, "unable to claim gpio \"vbus\": %d\n", err); in ohci_hcd_at91_drv_probe()
572 if (i >= pdata->ports) in ohci_hcd_at91_drv_probe()
575 pdata->overcurrent_pin[i] = in ohci_hcd_at91_drv_probe()
576 devm_gpiod_get_index_optional(&pdev->dev, "atmel,oc", in ohci_hcd_at91_drv_probe()
578 if (!pdata->overcurrent_pin[i]) in ohci_hcd_at91_drv_probe()
580 if (IS_ERR(pdata->overcurrent_pin[i])) { in ohci_hcd_at91_drv_probe()
581 err = PTR_ERR(pdata->overcurrent_pin[i]); in ohci_hcd_at91_drv_probe()
582 dev_err(&pdev->dev, "unable to claim gpio \"overcurrent\": %d\n", err); in ohci_hcd_at91_drv_probe()
586 ret = devm_request_irq(&pdev->dev, in ohci_hcd_at91_drv_probe()
587 gpiod_to_irq(pdata->overcurrent_pin[i]), in ohci_hcd_at91_drv_probe()
592 dev_info(&pdev->dev, "failed to request gpio \"overcurrent\" IRQ\n"); in ohci_hcd_at91_drv_probe()
595 device_init_wakeup(&pdev->dev, 1); in ohci_hcd_at91_drv_probe()
601 struct at91_usbh_data *pdata = dev_get_platdata(&pdev->dev); in ohci_hcd_at91_drv_remove()
609 device_init_wakeup(&pdev->dev, 0); in ohci_hcd_at91_drv_remove()
625 ohci_at91->wakeup = device_may_wakeup(dev) in ohci_hcd_at91_drv_suspend()
628 if (ohci_at91->wakeup) in ohci_hcd_at91_drv_suspend()
629 enable_irq_wake(hcd->irq); in ohci_hcd_at91_drv_suspend()
631 ret = ohci_suspend(hcd, ohci_at91->wakeup); in ohci_hcd_at91_drv_suspend()
633 if (ohci_at91->wakeup) in ohci_hcd_at91_drv_suspend()
634 disable_irq_wake(hcd->irq); in ohci_hcd_at91_drv_suspend()
644 if (!ohci_at91->wakeup) { in ohci_hcd_at91_drv_suspend()
645 ohci->rh_state = OHCI_RH_HALTED; in ohci_hcd_at91_drv_suspend()
648 (void) ohci_readl (ohci, &ohci->regs->control); in ohci_hcd_at91_drv_suspend()
667 if (ohci_at91->wakeup) in ohci_hcd_at91_drv_resume()
668 disable_irq_wake(hcd->irq); in ohci_hcd_at91_drv_resume()
675 * that is, if ohci_at91->wakeup is clear. Tell ohci_resume() in ohci_hcd_at91_drv_resume()
678 ohci_resume(hcd, !ohci_at91->wakeup); in ohci_hcd_at91_drv_resume()
700 return -ENODEV; in ohci_at91_init()
705 * The Atmel HW has some unusual quirks, which require Atmel-specific in ohci_at91_init()