Lines Matching +full:wakeup +full:- +full:method
1 // SPDX-License-Identifier: GPL-1.0+
6 * Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
11 * Based on ohci-omap.c
17 #include <linux/dma-mapping.h>
29 #include <soc/at91/atmel-sfr.h>
39 ((struct ohci_at91_priv *)hcd_to_ohci(h)->priv)
56 bool wakeup; /* Saved wake-up state for resume */ member
63 static const char hcd_name[] = "ohci-atmel";
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, ®s->control); in at91_start_hc()
120 dev_dbg(&pdev->dev, "stop\n"); in at91_stop_hc()
134 /*-------------------------------------------------------------------------*/
142 regmap = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr"); in at91_dt_syscon_sfr()
144 regmap = syscon_regmap_lookup_by_compatible("microchip,sam9x60-sfr"); in at91_dt_syscon_sfr()
157 * usb_hcd_at91_probe - initialize AT91-based HCDs
164 * then invokes the start() method for the HCD associated with it
175 struct device *dev = &pdev->dev; in usb_hcd_at91_probe()
187 return -ENOMEM; in usb_hcd_at91_probe()
191 hcd->regs = devm_ioremap_resource(dev, res); in usb_hcd_at91_probe()
192 if (IS_ERR(hcd->regs)) { in usb_hcd_at91_probe()
193 retval = PTR_ERR(hcd->regs); in usb_hcd_at91_probe()
196 hcd->rsrc_start = res->start; in usb_hcd_at91_probe()
197 hcd->rsrc_len = resource_size(res); in usb_hcd_at91_probe()
199 ohci_at91->iclk = devm_clk_get(dev, "ohci_clk"); in usb_hcd_at91_probe()
200 if (IS_ERR(ohci_at91->iclk)) { in usb_hcd_at91_probe()
202 retval = PTR_ERR(ohci_at91->iclk); in usb_hcd_at91_probe()
205 ohci_at91->fclk = devm_clk_get(dev, "uhpck"); in usb_hcd_at91_probe()
206 if (IS_ERR(ohci_at91->fclk)) { in usb_hcd_at91_probe()
208 retval = PTR_ERR(ohci_at91->fclk); in usb_hcd_at91_probe()
211 ohci_at91->hclk = devm_clk_get(dev, "hclk"); in usb_hcd_at91_probe()
212 if (IS_ERR(ohci_at91->hclk)) { in usb_hcd_at91_probe()
214 retval = PTR_ERR(ohci_at91->hclk); in usb_hcd_at91_probe()
218 ohci_at91->sfr_regmap = at91_dt_syscon_sfr(); in usb_hcd_at91_probe()
219 if (!ohci_at91->sfr_regmap) in usb_hcd_at91_probe()
222 board = hcd->self.controller->platform_data; in usb_hcd_at91_probe()
224 ohci->num_ports = board->ports; in usb_hcd_at91_probe()
231 ohci->hc_control = OHCI_CTRL_RWC; in usb_hcd_at91_probe()
235 device_wakeup_enable(hcd->self.controller); in usb_hcd_at91_probe()
251 * usb_hcd_at91_remove - shutdown processing for AT91-based HCDs
258 * the HCD's stop() method. It is always called from a thread
269 /*-------------------------------------------------------------------------*/
275 gpiod_set_value(pdata->vbus_pin[port], enable); in ohci_at91_usb_set_power()
281 return -EINVAL; in ohci_at91_usb_get_power()
283 return gpiod_get_value(pdata->vbus_pin[port]); in ohci_at91_usb_get_power()
287 * Update the status data from the hub with the over-current indicator change.
291 struct at91_usbh_data *pdata = hcd->self.controller->platform_data; in ohci_at91_hub_status_data()
296 if (pdata->overcurrent_changed[port]) { in ohci_at91_hub_status_data()
334 struct at91_usbh_data *pdata = dev_get_platdata(hcd->self.controller); in ohci_at91_hub_control()
337 int ret = -EINVAL; in ohci_at91_hub_control()
340 dev_dbg(hcd->self.controller, in ohci_at91_hub_control()
344 wIndex--; in ohci_at91_hub_control()
350 dev_dbg(hcd->self.controller, "SetPortFeat: POWER\n"); in ohci_at91_hub_control()
359 dev_dbg(hcd->self.controller, "SetPortFeat: SUSPEND\n"); in ohci_at91_hub_control()
360 if (valid_port(wIndex) && ohci_at91->sfr_regmap) { in ohci_at91_hub_control()
361 ohci_at91_port_suspend(ohci_at91->sfr_regmap, in ohci_at91_hub_control()
372 dev_dbg(hcd->self.controller, in ohci_at91_hub_control()
376 pdata->overcurrent_changed[wIndex] = 0; in ohci_at91_hub_control()
377 pdata->overcurrent_status[wIndex] = 0; in ohci_at91_hub_control()
383 dev_dbg(hcd->self.controller, in ohci_at91_hub_control()
387 pdata->overcurrent_status[wIndex] = 0; in ohci_at91_hub_control()
392 dev_dbg(hcd->self.controller, in ohci_at91_hub_control()
402 dev_dbg(hcd->self.controller, "ClearPortFeature: SUSPEND\n"); in ohci_at91_hub_control()
403 if (valid_port(wIndex) && ohci_at91->sfr_regmap) { in ohci_at91_hub_control()
404 ohci_at91_port_suspend(ohci_at91->sfr_regmap, in ohci_at91_hub_control()
424 dev_dbg(hcd->self.controller, "wHubCharacteristics 0x%04x\n", in ohci_at91_hub_control()
425 desc->wHubCharacteristics); in ohci_at91_hub_control()
427 /* remove the old configurations for power-switching, and in ohci_at91_hub_control()
428 * over-current protection, and insert our new configuration in ohci_at91_hub_control()
431 desc->wHubCharacteristics &= ~cpu_to_le16(HUB_CHAR_LPSM); in ohci_at91_hub_control()
432 desc->wHubCharacteristics |= in ohci_at91_hub_control()
435 if (pdata->overcurrent_supported) { in ohci_at91_hub_control()
436 desc->wHubCharacteristics &= ~cpu_to_le16(HUB_CHAR_OCPM); in ohci_at91_hub_control()
437 desc->wHubCharacteristics |= in ohci_at91_hub_control()
441 dev_dbg(hcd->self.controller, "wHubCharacteristics after 0x%04x\n", in ohci_at91_hub_control()
442 desc->wHubCharacteristics); in ohci_at91_hub_control()
449 dev_dbg(hcd->self.controller, "GetPortStatus(%d)\n", wIndex); in ohci_at91_hub_control()
455 if (pdata->overcurrent_changed[wIndex]) in ohci_at91_hub_control()
458 if (pdata->overcurrent_status[wIndex]) in ohci_at91_hub_control()
467 /*-------------------------------------------------------------------------*/
472 struct at91_usbh_data *pdata = dev_get_platdata(&pdev->dev); in ohci_hcd_at91_overcurrent_irq()
475 /* From the GPIO notifying the over-current situation, find in ohci_hcd_at91_overcurrent_irq()
478 if (gpiod_to_irq(pdata->overcurrent_pin[port]) == irq) in ohci_hcd_at91_overcurrent_irq()
483 dev_err(& pdev->dev, "overcurrent interrupt from unknown GPIO\n"); in ohci_hcd_at91_overcurrent_irq()
487 val = gpiod_get_value(pdata->overcurrent_pin[port]); in ohci_hcd_at91_overcurrent_irq()
489 /* When notified of an over-current situation, disable power in ohci_hcd_at91_overcurrent_irq()
491 over-current. */ in ohci_hcd_at91_overcurrent_irq()
494 pdata->overcurrent_status[port] = 1; in ohci_hcd_at91_overcurrent_irq()
495 pdata->overcurrent_changed[port] = 1; in ohci_hcd_at91_overcurrent_irq()
498 dev_dbg(& pdev->dev, "overcurrent situation %s\n", in ohci_hcd_at91_overcurrent_irq()
505 { .compatible = "atmel,at91rm9200-ohci" },
511 /*-------------------------------------------------------------------------*/
515 struct device_node *np = pdev->dev.of_node; in ohci_hcd_at91_drv_probe()
522 /* Right now device-tree probed devices don't get dma_mask set. in ohci_hcd_at91_drv_probe()
526 ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); in ohci_hcd_at91_drv_probe()
530 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); in ohci_hcd_at91_drv_probe()
532 return -ENOMEM; in ohci_hcd_at91_drv_probe()
534 pdev->dev.platform_data = pdata; in ohci_hcd_at91_drv_probe()
536 if (!of_property_read_u32(np, "num-ports", &ports)) in ohci_hcd_at91_drv_probe()
537 pdata->ports = ports; in ohci_hcd_at91_drv_probe()
540 if (i >= pdata->ports) in ohci_hcd_at91_drv_probe()
543 pdata->vbus_pin[i] = in ohci_hcd_at91_drv_probe()
544 devm_gpiod_get_index_optional(&pdev->dev, "atmel,vbus", in ohci_hcd_at91_drv_probe()
546 if (IS_ERR(pdata->vbus_pin[i])) { in ohci_hcd_at91_drv_probe()
547 err = PTR_ERR(pdata->vbus_pin[i]); in ohci_hcd_at91_drv_probe()
548 dev_err(&pdev->dev, "unable to claim gpio \"vbus\": %d\n", err); in ohci_hcd_at91_drv_probe()
554 if (i >= pdata->ports) in ohci_hcd_at91_drv_probe()
557 pdata->overcurrent_pin[i] = in ohci_hcd_at91_drv_probe()
558 devm_gpiod_get_index_optional(&pdev->dev, "atmel,oc", in ohci_hcd_at91_drv_probe()
560 if (!pdata->overcurrent_pin[i]) in ohci_hcd_at91_drv_probe()
562 if (IS_ERR(pdata->overcurrent_pin[i])) { in ohci_hcd_at91_drv_probe()
563 err = PTR_ERR(pdata->overcurrent_pin[i]); in ohci_hcd_at91_drv_probe()
564 dev_err(&pdev->dev, "unable to claim gpio \"overcurrent\": %d\n", err); in ohci_hcd_at91_drv_probe()
568 ret = devm_request_irq(&pdev->dev, in ohci_hcd_at91_drv_probe()
569 gpiod_to_irq(pdata->overcurrent_pin[i]), in ohci_hcd_at91_drv_probe()
574 dev_info(&pdev->dev, "failed to request gpio \"overcurrent\" IRQ\n"); in ohci_hcd_at91_drv_probe()
577 device_init_wakeup(&pdev->dev, 1); in ohci_hcd_at91_drv_probe()
583 struct at91_usbh_data *pdata = dev_get_platdata(&pdev->dev); in ohci_hcd_at91_drv_remove()
591 device_init_wakeup(&pdev->dev, 0); in ohci_hcd_at91_drv_remove()
605 * Disable wakeup if we are going to sleep with slow clock mode in ohci_hcd_at91_drv_suspend()
608 ohci_at91->wakeup = device_may_wakeup(dev) in ohci_hcd_at91_drv_suspend()
611 if (ohci_at91->wakeup) in ohci_hcd_at91_drv_suspend()
612 enable_irq_wake(hcd->irq); in ohci_hcd_at91_drv_suspend()
614 ret = ohci_suspend(hcd, ohci_at91->wakeup); in ohci_hcd_at91_drv_suspend()
616 if (ohci_at91->wakeup) in ohci_hcd_at91_drv_suspend()
617 disable_irq_wake(hcd->irq); in ohci_hcd_at91_drv_suspend()
622 * reconnect, or wakeup without the 48 MHz clock active. so for in ohci_hcd_at91_drv_suspend()
627 if (!ohci_at91->wakeup) { in ohci_hcd_at91_drv_suspend()
628 ohci->rh_state = OHCI_RH_HALTED; in ohci_hcd_at91_drv_suspend()
631 (void) ohci_readl (ohci, &ohci->regs->control); in ohci_hcd_at91_drv_suspend()
633 ohci_at91_port_suspend(ohci_at91->sfr_regmap, 1); in ohci_hcd_at91_drv_suspend()
636 ohci_at91_port_suspend(ohci_at91->sfr_regmap, 1); in ohci_hcd_at91_drv_suspend()
648 ohci_at91_port_suspend(ohci_at91->sfr_regmap, 0); in ohci_hcd_at91_drv_resume()
650 if (ohci_at91->wakeup) in ohci_hcd_at91_drv_resume()
651 disable_irq_wake(hcd->irq); in ohci_hcd_at91_drv_resume()
677 return -ENODEV; in ohci_at91_init()
683 * The Atmel HW has some unusual quirks, which require Atmel-specific in ohci_at91_init()