All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv7 0/4] USB: gadget: atmel_usba_udc: PM driver improvements
@ 2015-02-12 17:54 Sylvain Rochet
  2015-02-12 17:54 ` [PATCHv7 1/4] USB: gadget: atmel_usba_udc: Fixed vbus_prev initial state Sylvain Rochet
                   ` (4 more replies)
  0 siblings, 5 replies; 11+ messages in thread
From: Sylvain Rochet @ 2015-02-12 17:54 UTC (permalink / raw)
  To: linux-arm-kernel

Start clocks on rising edge of the Vbus signal, stop clocks on falling
edge of the Vbus signal.

Add suspend/resume with wakeup support.

Changes since v6:
  * Removed single IRQ edge support, which was used to wake up only on 
    device connection. We don't have yet a clean solution to handle IRQ
    controller with (at91sam9x5) and without (at91rm9200) single edge 
    support. Rework PATCH v6 4/5 removed, we don't need this one anymore.

Changes since v5:
  * Some boards does not support configuring a GPIO interrupt on a specific
    edge (rising only or falling only). As suggested added a config boolean
    to distinguish between boards with and without support
  * Added a missing mutex_lock()/unlock() in usba_udc_suspend(), we need to
    protect usba_stop() because usba_start() and usba_stop() can still
    be called by Vbus IRQ handler.
  * Rebased the full series on linux-next
  * Patch cleaning with the help of checkpatch.pl

Changes since v4:
  * Now using IRQ_NOAUTOEN flag to remove the unused check for
    udc->driver is not NULL in the Vbus IRQ.
  * Reworked the start/stop of clocks on Vbus edges to prepare for
    suspend/resume support, factorised start and stop procedures
  * New patch, suspend/resume for USBA with wakeup support

Changes since v3:
  * Added stable tag for the first patch
  * As suggested, removed the unused check for udc->driver is NULL in
    Vbus IRQ by requesting IRQ after udc->driver is set and by releasing
    IRQ before udc->driver is cleared
  * Rebased the core patch of this series against the just explained changes

Changes since v2:
  * Use spin_lock_irqsave/unlock_irqrestore instead of spin_lock/unlock in
    threaded interrupt because we are not in irq context anymore
  * Removed useless and probably harmful IRQF_NO_SUSPEND from
    devm_request_threaded_irq() flags

Changes since v1:
  * Using a threaded irq and mutex instead of spinclock as suggested
  * Moved a silently fixed bug in a separate patch (1/2)

Sylvain Rochet (4):
  USB: gadget: atmel_usba_udc: Fixed vbus_prev initial state
  USB: gadget: atmel_usba_udc: Request an auto disabled Vbus signal IRQ
    instead of an auto enabled IRQ request followed by IRQ disable
  USB: gadget: atmel_usba_udc: Start clocks on rising edge of the Vbus
    signal, stop clocks on falling edge of the Vbus signal
  USB: gadget: atmel_usba_udc: Add suspend/resume with wakeup support

 drivers/usb/gadget/udc/atmel_usba_udc.c | 208 ++++++++++++++++++++++++--------
 drivers/usb/gadget/udc/atmel_usba_udc.h |   4 +
 2 files changed, 159 insertions(+), 53 deletions(-)

-- 
2.1.4

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCHv7 1/4] USB: gadget: atmel_usba_udc: Fixed vbus_prev initial state
  2015-02-12 17:54 [PATCHv7 0/4] USB: gadget: atmel_usba_udc: PM driver improvements Sylvain Rochet
@ 2015-02-12 17:54 ` Sylvain Rochet
  2015-02-12 17:54 ` [PATCHv7 2/4] USB: gadget: atmel_usba_udc: Request an auto disabled Vbus signal IRQ instead of an auto enabled IRQ request followed by IRQ disable Sylvain Rochet
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 11+ messages in thread
From: Sylvain Rochet @ 2015-02-12 17:54 UTC (permalink / raw)
  To: linux-arm-kernel

If vbus gpio is high at init, we should set vbus_prev to true
accordingly to the current vbus state. Without that, we skip the first
vbus interrupt because the saved vbus state is not consistent.

Signed-off-by: Sylvain Rochet <sylvain.rochet@finsecur.com>
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Acked-by: Boris Brezillon <boris.brezillon@free-electrons.com>
---
 drivers/usb/gadget/udc/atmel_usba_udc.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c
index d79cb35..e63c6fc 100644
--- a/drivers/usb/gadget/udc/atmel_usba_udc.c
+++ b/drivers/usb/gadget/udc/atmel_usba_udc.c
@@ -1811,6 +1811,8 @@ static int atmel_usba_start(struct usb_gadget *gadget,
 		toggle_bias(udc, 1);
 		usba_writel(udc, CTRL, USBA_ENABLE_MASK);
 		usba_int_enb_set(udc, USBA_END_OF_RESET);
+
+		udc->vbus_prev = 1;
 	}
 	spin_unlock_irqrestore(&udc->lock, flags);
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCHv7 2/4] USB: gadget: atmel_usba_udc: Request an auto disabled Vbus signal IRQ instead of an auto enabled IRQ request followed by IRQ disable
  2015-02-12 17:54 [PATCHv7 0/4] USB: gadget: atmel_usba_udc: PM driver improvements Sylvain Rochet
  2015-02-12 17:54 ` [PATCHv7 1/4] USB: gadget: atmel_usba_udc: Fixed vbus_prev initial state Sylvain Rochet
@ 2015-02-12 17:54 ` Sylvain Rochet
  2015-03-10 21:12   ` Felipe Balbi
  2015-02-12 17:54 ` [PATCHv7 3/4] USB: gadget: atmel_usba_udc: Start clocks on rising edge of the Vbus signal, stop clocks on falling edge of the Vbus signal Sylvain Rochet
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 11+ messages in thread
From: Sylvain Rochet @ 2015-02-12 17:54 UTC (permalink / raw)
  To: linux-arm-kernel

Vbus IRQ handler needs a started UDC driver to work because it uses
udc->driver, which is set by the UDC start handler. The previous way
chosen was to return from interrupt if udc->driver is NULL using a
spinlock around the check.

We now request an auto disabled (IRQ_NOAUTOEN) Vbus signal IRQ instead
of an auto enabled IRQ followed by disable_irq(). This way we remove the
very small timeslot of enabled IRQ which existed previously between
request() and disable(). We don't need anymore to check if udc->driver
is NULL in IRQ handler.

Signed-off-by: Sylvain Rochet <sylvain.rochet@finsecur.com>
Suggested-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Acked-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
 drivers/usb/gadget/udc/atmel_usba_udc.c | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c
index e63c6fc..bbbd5f1 100644
--- a/drivers/usb/gadget/udc/atmel_usba_udc.c
+++ b/drivers/usb/gadget/udc/atmel_usba_udc.c
@@ -1749,10 +1749,6 @@ static irqreturn_t usba_vbus_irq(int irq, void *devid)
 
 	spin_lock(&udc->lock);
 
-	/* May happen if Vbus pin toggles during probe() */
-	if (!udc->driver)
-		goto out;
-
 	vbus = vbus_is_present(udc);
 	if (vbus != udc->vbus_prev) {
 		if (vbus) {
@@ -1773,7 +1769,6 @@ static irqreturn_t usba_vbus_irq(int irq, void *devid)
 		udc->vbus_prev = vbus;
 	}
 
-out:
 	spin_unlock(&udc->lock);
 
 	return IRQ_HANDLED;
@@ -2113,6 +2108,8 @@ static int usba_udc_probe(struct platform_device *pdev)
 
 	if (gpio_is_valid(udc->vbus_pin)) {
 		if (!devm_gpio_request(&pdev->dev, udc->vbus_pin, "atmel_usba_udc")) {
+			irq_set_status_flags(gpio_to_irq(udc->vbus_pin),
+					IRQ_NOAUTOEN);
 			ret = devm_request_irq(&pdev->dev,
 					gpio_to_irq(udc->vbus_pin),
 					usba_vbus_irq, 0,
@@ -2122,8 +2119,6 @@ static int usba_udc_probe(struct platform_device *pdev)
 				dev_warn(&udc->pdev->dev,
 					 "failed to request vbus irq; "
 					 "assuming always on\n");
-			} else {
-				disable_irq(gpio_to_irq(udc->vbus_pin));
 			}
 		} else {
 			/* gpio_request fail so use -EINVAL for gpio_is_valid */
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCHv7 3/4] USB: gadget: atmel_usba_udc: Start clocks on rising edge of the Vbus signal, stop clocks on falling edge of the Vbus signal
  2015-02-12 17:54 [PATCHv7 0/4] USB: gadget: atmel_usba_udc: PM driver improvements Sylvain Rochet
  2015-02-12 17:54 ` [PATCHv7 1/4] USB: gadget: atmel_usba_udc: Fixed vbus_prev initial state Sylvain Rochet
  2015-02-12 17:54 ` [PATCHv7 2/4] USB: gadget: atmel_usba_udc: Request an auto disabled Vbus signal IRQ instead of an auto enabled IRQ request followed by IRQ disable Sylvain Rochet
@ 2015-02-12 17:54 ` Sylvain Rochet
  2015-03-10 21:13   ` Felipe Balbi
  2015-02-12 17:54 ` [PATCHv7 4/4] USB: gadget: atmel_usba_udc: Add suspend/resume with wakeup support Sylvain Rochet
  2015-03-04 13:12 ` [PATCHv7 0/4] USB: gadget: atmel_usba_udc: PM driver improvements Nicolas Ferre
  4 siblings, 1 reply; 11+ messages in thread
From: Sylvain Rochet @ 2015-02-12 17:54 UTC (permalink / raw)
  To: linux-arm-kernel

If USB PLL is not necessary for other USB drivers (e.g. OHCI and EHCI)
we will reduce power consumption by switching off the USB PLL if no USB
Host is currently connected to this USB Device.

We are using Vbus GPIO signal to detect Host presence. If Vbus signal is
not available then the device stays continuously clocked.

Signed-off-by: Sylvain Rochet <sylvain.rochet@finsecur.com>
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Acked-by: Boris Brezillon <boris.brezillon@free-electrons.com>
---
 drivers/usb/gadget/udc/atmel_usba_udc.c | 144 +++++++++++++++++++++-----------
 drivers/usb/gadget/udc/atmel_usba_udc.h |   4 +
 2 files changed, 100 insertions(+), 48 deletions(-)

diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c
index bbbd5f1..999e2f2 100644
--- a/drivers/usb/gadget/udc/atmel_usba_udc.c
+++ b/drivers/usb/gadget/udc/atmel_usba_udc.c
@@ -1739,7 +1739,72 @@ static irqreturn_t usba_udc_irq(int irq, void *devid)
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t usba_vbus_irq(int irq, void *devid)
+static int start_clock(struct usba_udc *udc)
+{
+	int ret;
+
+	if (udc->clocked)
+		return 0;
+
+	ret = clk_prepare_enable(udc->pclk);
+	if (ret)
+		return ret;
+	ret = clk_prepare_enable(udc->hclk);
+	if (ret) {
+		clk_disable_unprepare(udc->pclk);
+		return ret;
+	}
+
+	udc->clocked = true;
+	return 0;
+}
+
+static void stop_clock(struct usba_udc *udc)
+{
+	if (!udc->clocked)
+		return;
+
+	clk_disable_unprepare(udc->hclk);
+	clk_disable_unprepare(udc->pclk);
+
+	udc->clocked = false;
+}
+
+static int usba_start(struct usba_udc *udc)
+{
+	unsigned long flags;
+	int ret;
+
+	ret = start_clock(udc);
+	if (ret)
+		return ret;
+
+	spin_lock_irqsave(&udc->lock, flags);
+	toggle_bias(udc, 1);
+	usba_writel(udc, CTRL, USBA_ENABLE_MASK);
+	usba_int_enb_set(udc, USBA_END_OF_RESET);
+	spin_unlock_irqrestore(&udc->lock, flags);
+
+	return 0;
+}
+
+static void usba_stop(struct usba_udc *udc)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&udc->lock, flags);
+	udc->gadget.speed = USB_SPEED_UNKNOWN;
+	reset_all_endpoints(udc);
+
+	/* This will also disable the DP pullup */
+	toggle_bias(udc, 0);
+	usba_writel(udc, CTRL, USBA_DISABLE_MASK);
+	spin_unlock_irqrestore(&udc->lock, flags);
+
+	stop_clock(udc);
+}
+
+static irqreturn_t usba_vbus_irq_thread(int irq, void *devid)
 {
 	struct usba_udc *udc = devid;
 	int vbus;
@@ -1747,30 +1812,22 @@ static irqreturn_t usba_vbus_irq(int irq, void *devid)
 	/* debounce */
 	udelay(10);
 
-	spin_lock(&udc->lock);
+	mutex_lock(&udc->vbus_mutex);
 
 	vbus = vbus_is_present(udc);
 	if (vbus != udc->vbus_prev) {
 		if (vbus) {
-			toggle_bias(udc, 1);
-			usba_writel(udc, CTRL, USBA_ENABLE_MASK);
-			usba_int_enb_set(udc, USBA_END_OF_RESET);
+			usba_start(udc);
 		} else {
-			udc->gadget.speed = USB_SPEED_UNKNOWN;
-			reset_all_endpoints(udc);
-			toggle_bias(udc, 0);
-			usba_writel(udc, CTRL, USBA_DISABLE_MASK);
-			if (udc->driver->disconnect) {
-				spin_unlock(&udc->lock);
+			usba_stop(udc);
+
+			if (udc->driver->disconnect)
 				udc->driver->disconnect(&udc->gadget);
-				spin_lock(&udc->lock);
-			}
 		}
 		udc->vbus_prev = vbus;
 	}
 
-	spin_unlock(&udc->lock);
-
+	mutex_unlock(&udc->vbus_mutex);
 	return IRQ_HANDLED;
 }
 
@@ -1782,57 +1839,47 @@ static int atmel_usba_start(struct usb_gadget *gadget,
 	unsigned long flags;
 
 	spin_lock_irqsave(&udc->lock, flags);
-
 	udc->devstatus = 1 << USB_DEVICE_SELF_POWERED;
 	udc->driver = driver;
 	spin_unlock_irqrestore(&udc->lock, flags);
 
-	ret = clk_prepare_enable(udc->pclk);
-	if (ret)
-		return ret;
-	ret = clk_prepare_enable(udc->hclk);
-	if (ret) {
-		clk_disable_unprepare(udc->pclk);
-		return ret;
-	}
+	mutex_lock(&udc->vbus_mutex);
 
-	udc->vbus_prev = 0;
 	if (gpio_is_valid(udc->vbus_pin))
 		enable_irq(gpio_to_irq(udc->vbus_pin));
 
 	/* If Vbus is present, enable the controller and wait for reset */
-	spin_lock_irqsave(&udc->lock, flags);
-	if (vbus_is_present(udc) && udc->vbus_prev == 0) {
-		toggle_bias(udc, 1);
-		usba_writel(udc, CTRL, USBA_ENABLE_MASK);
-		usba_int_enb_set(udc, USBA_END_OF_RESET);
-
-		udc->vbus_prev = 1;
+	udc->vbus_prev = vbus_is_present(udc);
+	if (udc->vbus_prev) {
+		ret = usba_start(udc);
+		if (ret)
+			goto err;
 	}
-	spin_unlock_irqrestore(&udc->lock, flags);
 
+	mutex_unlock(&udc->vbus_mutex);
 	return 0;
+
+err:
+	if (gpio_is_valid(udc->vbus_pin))
+		disable_irq(gpio_to_irq(udc->vbus_pin));
+
+	mutex_unlock(&udc->vbus_mutex);
+
+	spin_lock_irqsave(&udc->lock, flags);
+	udc->devstatus &= ~(1 << USB_DEVICE_SELF_POWERED);
+	udc->driver = NULL;
+	spin_unlock_irqrestore(&udc->lock, flags);
+	return ret;
 }
 
 static int atmel_usba_stop(struct usb_gadget *gadget)
 {
 	struct usba_udc *udc = container_of(gadget, struct usba_udc, gadget);
-	unsigned long flags;
 
 	if (gpio_is_valid(udc->vbus_pin))
 		disable_irq(gpio_to_irq(udc->vbus_pin));
 
-	spin_lock_irqsave(&udc->lock, flags);
-	udc->gadget.speed = USB_SPEED_UNKNOWN;
-	reset_all_endpoints(udc);
-	spin_unlock_irqrestore(&udc->lock, flags);
-
-	/* This will also disable the DP pullup */
-	toggle_bias(udc, 0);
-	usba_writel(udc, CTRL, USBA_DISABLE_MASK);
-
-	clk_disable_unprepare(udc->hclk);
-	clk_disable_unprepare(udc->pclk);
+	usba_stop(udc);
 
 	udc->driver = NULL;
 
@@ -2054,6 +2101,7 @@ static int usba_udc_probe(struct platform_device *pdev)
 		return PTR_ERR(hclk);
 
 	spin_lock_init(&udc->lock);
+	mutex_init(&udc->vbus_mutex);
 	udc->pdev = pdev;
 	udc->pclk = pclk;
 	udc->hclk = hclk;
@@ -2110,9 +2158,9 @@ static int usba_udc_probe(struct platform_device *pdev)
 		if (!devm_gpio_request(&pdev->dev, udc->vbus_pin, "atmel_usba_udc")) {
 			irq_set_status_flags(gpio_to_irq(udc->vbus_pin),
 					IRQ_NOAUTOEN);
-			ret = devm_request_irq(&pdev->dev,
-					gpio_to_irq(udc->vbus_pin),
-					usba_vbus_irq, 0,
+			ret = devm_request_threaded_irq(&pdev->dev,
+					gpio_to_irq(udc->vbus_pin), NULL,
+					usba_vbus_irq_thread, IRQF_ONESHOT,
 					"atmel_usba_udc", udc);
 			if (ret) {
 				udc->vbus_pin = -ENODEV;
diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.h b/drivers/usb/gadget/udc/atmel_usba_udc.h
index 497cd18..085749a 100644
--- a/drivers/usb/gadget/udc/atmel_usba_udc.h
+++ b/drivers/usb/gadget/udc/atmel_usba_udc.h
@@ -313,6 +313,9 @@ struct usba_udc {
 	/* Protect hw registers from concurrent modifications */
 	spinlock_t lock;
 
+	/* Mutex to prevent concurrent start or stop */
+	struct mutex vbus_mutex;
+
 	void __iomem *regs;
 	void __iomem *fifo;
 
@@ -328,6 +331,7 @@ struct usba_udc {
 	struct clk *hclk;
 	struct usba_ep *usba_ep;
 	bool bias_pulse_needed;
+	bool clocked;
 
 	u16 devstatus;
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCHv7 4/4] USB: gadget: atmel_usba_udc: Add suspend/resume with wakeup support
  2015-02-12 17:54 [PATCHv7 0/4] USB: gadget: atmel_usba_udc: PM driver improvements Sylvain Rochet
                   ` (2 preceding siblings ...)
  2015-02-12 17:54 ` [PATCHv7 3/4] USB: gadget: atmel_usba_udc: Start clocks on rising edge of the Vbus signal, stop clocks on falling edge of the Vbus signal Sylvain Rochet
@ 2015-02-12 17:54 ` Sylvain Rochet
  2015-03-04 13:09   ` Nicolas Ferre
  2015-03-04 13:12 ` [PATCHv7 0/4] USB: gadget: atmel_usba_udc: PM driver improvements Nicolas Ferre
  4 siblings, 1 reply; 11+ messages in thread
From: Sylvain Rochet @ 2015-02-12 17:54 UTC (permalink / raw)
  To: linux-arm-kernel

This patch add suspend/resume with wakeup support for Atmel USBA.

On suspend: We stay continuously clocked if Vbus signal is not
available. If Vbus signal is available we set the Vbus signal as a wake
up source then we stop the USBA itself and all clocks used by USBA.

On resume: We recover clocks and USBA if we stopped them. If a device is
currently connected at resume time we enable the controller.

Signed-off-by: Sylvain Rochet <sylvain.rochet@finsecur.com>
Acked-by: Boris Brezillon <boris.brezillon@free-electrons.com>
---
 drivers/usb/gadget/udc/atmel_usba_udc.c | 57 +++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c
index 999e2f2..d019b6c 100644
--- a/drivers/usb/gadget/udc/atmel_usba_udc.c
+++ b/drivers/usb/gadget/udc/atmel_usba_udc.c
@@ -2177,6 +2177,7 @@ static int usba_udc_probe(struct platform_device *pdev)
 	ret = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
 	if (ret)
 		return ret;
+	device_init_wakeup(&pdev->dev, 1);
 
 	usba_init_debugfs(udc);
 	for (i = 1; i < udc->num_ep; i++)
@@ -2192,6 +2193,7 @@ static int __exit usba_udc_remove(struct platform_device *pdev)
 
 	udc = platform_get_drvdata(pdev);
 
+	device_init_wakeup(&pdev->dev, 0);
 	usb_del_gadget_udc(&udc->gadget);
 
 	for (i = 1; i < udc->num_ep; i++)
@@ -2201,10 +2203,65 @@ static int __exit usba_udc_remove(struct platform_device *pdev)
 	return 0;
 }
 
+#ifdef CONFIG_PM
+static int usba_udc_suspend(struct device *dev)
+{
+	struct usba_udc *udc = dev_get_drvdata(dev);
+
+	/* Not started */
+	if (!udc->driver)
+		return 0;
+
+	mutex_lock(&udc->vbus_mutex);
+
+	if (!device_may_wakeup(dev)) {
+		usba_stop(udc);
+		goto out;
+	}
+
+	/*
+	 * Device may wake up. We stay clocked if we failed
+	 * to request vbus irq, assuming always on.
+	 */
+	if (gpio_is_valid(udc->vbus_pin)) {
+		usba_stop(udc);
+		enable_irq_wake(gpio_to_irq(udc->vbus_pin));
+	}
+
+out:
+	mutex_unlock(&udc->vbus_mutex);
+	return 0;
+}
+
+static int usba_udc_resume(struct device *dev)
+{
+	struct usba_udc *udc = dev_get_drvdata(dev);
+
+	/* Not started */
+	if (!udc->driver)
+		return 0;
+
+	if (device_may_wakeup(dev) && gpio_is_valid(udc->vbus_pin))
+		disable_irq_wake(gpio_to_irq(udc->vbus_pin));
+
+	/* If Vbus is present, enable the controller and wait for reset */
+	mutex_lock(&udc->vbus_mutex);
+	udc->vbus_prev = vbus_is_present(udc);
+	if (udc->vbus_prev)
+		usba_start(udc);
+	mutex_unlock(&udc->vbus_mutex);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(usba_udc_pm_ops, usba_udc_suspend, usba_udc_resume);
+
 static struct platform_driver udc_driver = {
 	.remove		= __exit_p(usba_udc_remove),
 	.driver		= {
 		.name		= "atmel_usba_udc",
+		.pm		= &usba_udc_pm_ops,
 		.of_match_table	= of_match_ptr(atmel_udc_dt_ids),
 	},
 };
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCHv7 4/4] USB: gadget: atmel_usba_udc: Add suspend/resume with wakeup support
  2015-02-12 17:54 ` [PATCHv7 4/4] USB: gadget: atmel_usba_udc: Add suspend/resume with wakeup support Sylvain Rochet
@ 2015-03-04 13:09   ` Nicolas Ferre
  0 siblings, 0 replies; 11+ messages in thread
From: Nicolas Ferre @ 2015-03-04 13:09 UTC (permalink / raw)
  To: linux-arm-kernel

Le 12/02/2015 18:54, Sylvain Rochet a ?crit :
> This patch add suspend/resume with wakeup support for Atmel USBA.
> 
> On suspend: We stay continuously clocked if Vbus signal is not
> available. If Vbus signal is available we set the Vbus signal as a wake
> up source then we stop the USBA itself and all clocks used by USBA.
> 
> On resume: We recover clocks and USBA if we stopped them. If a device is
> currently connected at resume time we enable the controller.
> 
> Signed-off-by: Sylvain Rochet <sylvain.rochet@finsecur.com>
> Acked-by: Boris Brezillon <boris.brezillon@free-electrons.com>

Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>

> ---
>  drivers/usb/gadget/udc/atmel_usba_udc.c | 57 +++++++++++++++++++++++++++++++++
>  1 file changed, 57 insertions(+)
> 
> diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c
> index 999e2f2..d019b6c 100644
> --- a/drivers/usb/gadget/udc/atmel_usba_udc.c
> +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c
> @@ -2177,6 +2177,7 @@ static int usba_udc_probe(struct platform_device *pdev)
>  	ret = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
>  	if (ret)
>  		return ret;
> +	device_init_wakeup(&pdev->dev, 1);
>  
>  	usba_init_debugfs(udc);
>  	for (i = 1; i < udc->num_ep; i++)
> @@ -2192,6 +2193,7 @@ static int __exit usba_udc_remove(struct platform_device *pdev)
>  
>  	udc = platform_get_drvdata(pdev);
>  
> +	device_init_wakeup(&pdev->dev, 0);
>  	usb_del_gadget_udc(&udc->gadget);
>  
>  	for (i = 1; i < udc->num_ep; i++)
> @@ -2201,10 +2203,65 @@ static int __exit usba_udc_remove(struct platform_device *pdev)
>  	return 0;
>  }
>  
> +#ifdef CONFIG_PM
> +static int usba_udc_suspend(struct device *dev)
> +{
> +	struct usba_udc *udc = dev_get_drvdata(dev);
> +
> +	/* Not started */
> +	if (!udc->driver)
> +		return 0;
> +
> +	mutex_lock(&udc->vbus_mutex);
> +
> +	if (!device_may_wakeup(dev)) {
> +		usba_stop(udc);
> +		goto out;
> +	}
> +
> +	/*
> +	 * Device may wake up. We stay clocked if we failed
> +	 * to request vbus irq, assuming always on.
> +	 */
> +	if (gpio_is_valid(udc->vbus_pin)) {
> +		usba_stop(udc);
> +		enable_irq_wake(gpio_to_irq(udc->vbus_pin));
> +	}
> +
> +out:
> +	mutex_unlock(&udc->vbus_mutex);
> +	return 0;
> +}
> +
> +static int usba_udc_resume(struct device *dev)
> +{
> +	struct usba_udc *udc = dev_get_drvdata(dev);
> +
> +	/* Not started */
> +	if (!udc->driver)
> +		return 0;
> +
> +	if (device_may_wakeup(dev) && gpio_is_valid(udc->vbus_pin))
> +		disable_irq_wake(gpio_to_irq(udc->vbus_pin));
> +
> +	/* If Vbus is present, enable the controller and wait for reset */
> +	mutex_lock(&udc->vbus_mutex);
> +	udc->vbus_prev = vbus_is_present(udc);
> +	if (udc->vbus_prev)
> +		usba_start(udc);
> +	mutex_unlock(&udc->vbus_mutex);
> +
> +	return 0;
> +}
> +#endif
> +
> +static SIMPLE_DEV_PM_OPS(usba_udc_pm_ops, usba_udc_suspend, usba_udc_resume);
> +
>  static struct platform_driver udc_driver = {
>  	.remove		= __exit_p(usba_udc_remove),
>  	.driver		= {
>  		.name		= "atmel_usba_udc",
> +		.pm		= &usba_udc_pm_ops,
>  		.of_match_table	= of_match_ptr(atmel_udc_dt_ids),
>  	},
>  };
> 


-- 
Nicolas Ferre

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCHv7 0/4] USB: gadget: atmel_usba_udc: PM driver improvements
  2015-02-12 17:54 [PATCHv7 0/4] USB: gadget: atmel_usba_udc: PM driver improvements Sylvain Rochet
                   ` (3 preceding siblings ...)
  2015-02-12 17:54 ` [PATCHv7 4/4] USB: gadget: atmel_usba_udc: Add suspend/resume with wakeup support Sylvain Rochet
@ 2015-03-04 13:12 ` Nicolas Ferre
  2015-03-10 21:10   ` Felipe Balbi
  4 siblings, 1 reply; 11+ messages in thread
From: Nicolas Ferre @ 2015-03-04 13:12 UTC (permalink / raw)
  To: linux-arm-kernel

Le 12/02/2015 18:54, Sylvain Rochet a ?crit :
> Start clocks on rising edge of the Vbus signal, stop clocks on falling
> edge of the Vbus signal.
> 
> Add suspend/resume with wakeup support.

Hi Felipe,

I think this series by Sylvain is ready for inclusion. Are you able to
take it for the next cycle?

Thank, bye,


> Changes since v6:
>   * Removed single IRQ edge support, which was used to wake up only on 
>     device connection. We don't have yet a clean solution to handle IRQ
>     controller with (at91sam9x5) and without (at91rm9200) single edge 
>     support. Rework PATCH v6 4/5 removed, we don't need this one anymore.
> 
> Changes since v5:
>   * Some boards does not support configuring a GPIO interrupt on a specific
>     edge (rising only or falling only). As suggested added a config boolean
>     to distinguish between boards with and without support
>   * Added a missing mutex_lock()/unlock() in usba_udc_suspend(), we need to
>     protect usba_stop() because usba_start() and usba_stop() can still
>     be called by Vbus IRQ handler.
>   * Rebased the full series on linux-next
>   * Patch cleaning with the help of checkpatch.pl
> 
> Changes since v4:
>   * Now using IRQ_NOAUTOEN flag to remove the unused check for
>     udc->driver is not NULL in the Vbus IRQ.
>   * Reworked the start/stop of clocks on Vbus edges to prepare for
>     suspend/resume support, factorised start and stop procedures
>   * New patch, suspend/resume for USBA with wakeup support
> 
> Changes since v3:
>   * Added stable tag for the first patch
>   * As suggested, removed the unused check for udc->driver is NULL in
>     Vbus IRQ by requesting IRQ after udc->driver is set and by releasing
>     IRQ before udc->driver is cleared
>   * Rebased the core patch of this series against the just explained changes
> 
> Changes since v2:
>   * Use spin_lock_irqsave/unlock_irqrestore instead of spin_lock/unlock in
>     threaded interrupt because we are not in irq context anymore
>   * Removed useless and probably harmful IRQF_NO_SUSPEND from
>     devm_request_threaded_irq() flags
> 
> Changes since v1:
>   * Using a threaded irq and mutex instead of spinclock as suggested
>   * Moved a silently fixed bug in a separate patch (1/2)
> 
> Sylvain Rochet (4):
>   USB: gadget: atmel_usba_udc: Fixed vbus_prev initial state
>   USB: gadget: atmel_usba_udc: Request an auto disabled Vbus signal IRQ
>     instead of an auto enabled IRQ request followed by IRQ disable
>   USB: gadget: atmel_usba_udc: Start clocks on rising edge of the Vbus
>     signal, stop clocks on falling edge of the Vbus signal
>   USB: gadget: atmel_usba_udc: Add suspend/resume with wakeup support
> 
>  drivers/usb/gadget/udc/atmel_usba_udc.c | 208 ++++++++++++++++++++++++--------
>  drivers/usb/gadget/udc/atmel_usba_udc.h |   4 +
>  2 files changed, 159 insertions(+), 53 deletions(-)
> 


-- 
Nicolas Ferre

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCHv7 0/4] USB: gadget: atmel_usba_udc: PM driver improvements
  2015-03-04 13:12 ` [PATCHv7 0/4] USB: gadget: atmel_usba_udc: PM driver improvements Nicolas Ferre
@ 2015-03-10 21:10   ` Felipe Balbi
  0 siblings, 0 replies; 11+ messages in thread
From: Felipe Balbi @ 2015-03-10 21:10 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Mar 04, 2015 at 02:12:51PM +0100, Nicolas Ferre wrote:
> Le 12/02/2015 18:54, Sylvain Rochet a ?crit :
> > Start clocks on rising edge of the Vbus signal, stop clocks on falling
> > edge of the Vbus signal.
> > 
> > Add suspend/resume with wakeup support.
> 
> Hi Felipe,
> 
> I think this series by Sylvain is ready for inclusion. Are you able to
> take it for the next cycle?

taking it now. Thanks

-- 
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150310/67e4e2c5/attachment.sig>

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCHv7 2/4] USB: gadget: atmel_usba_udc: Request an auto disabled Vbus signal IRQ instead of an auto enabled IRQ request followed by IRQ disable
  2015-02-12 17:54 ` [PATCHv7 2/4] USB: gadget: atmel_usba_udc: Request an auto disabled Vbus signal IRQ instead of an auto enabled IRQ request followed by IRQ disable Sylvain Rochet
@ 2015-03-10 21:12   ` Felipe Balbi
  2015-03-11  9:50     ` Sylvain Rochet
  0 siblings, 1 reply; 11+ messages in thread
From: Felipe Balbi @ 2015-03-10 21:12 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

(dropping patch, my only context is subject line)

"USB: gadget: atmel_usba_udc: Request an auto disabled Vbus signal IRQ
instead of an auto enabled IRQ request followed by IRQ disable"

Holy crap, that's a pretty long patch *short* description. I'm trimming
it to:

"usb: gadget: atmel_usba_udc: Request an auto disabled Vbus signal IRQ"

cheers

-- 
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150310/34af36fe/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCHv7 3/4] USB: gadget: atmel_usba_udc: Start clocks on rising edge of the Vbus signal, stop clocks on falling edge of the Vbus signal
  2015-02-12 17:54 ` [PATCHv7 3/4] USB: gadget: atmel_usba_udc: Start clocks on rising edge of the Vbus signal, stop clocks on falling edge of the Vbus signal Sylvain Rochet
@ 2015-03-10 21:13   ` Felipe Balbi
  0 siblings, 0 replies; 11+ messages in thread
From: Felipe Balbi @ 2015-03-10 21:13 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

this one became:

"usb: gadget: atmel_usba_udc: condition clocks to vbus state"

cheers

-- 
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150310/ad04e4fc/attachment.sig>

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCHv7 2/4] USB: gadget: atmel_usba_udc: Request an auto disabled Vbus signal IRQ instead of an auto enabled IRQ request followed by IRQ disable
  2015-03-10 21:12   ` Felipe Balbi
@ 2015-03-11  9:50     ` Sylvain Rochet
  0 siblings, 0 replies; 11+ messages in thread
From: Sylvain Rochet @ 2015-03-11  9:50 UTC (permalink / raw)
  To: linux-arm-kernel

Hello Felipe,

On Tue, Mar 10, 2015 at 04:12:14PM -0500, Felipe Balbi wrote:
> Hi,
> 
> (dropping patch, my only context is subject line)
> 
> "USB: gadget: atmel_usba_udc: Request an auto disabled Vbus signal IRQ
> instead of an auto enabled IRQ request followed by IRQ disable"
> 
> Holy crap, that's a pretty long patch *short* description. I'm trimming
> it to:
> 
> "usb: gadget: atmel_usba_udc: Request an auto disabled Vbus signal IRQ"

I agree, lesson learned!, thanks for the heads up :)

Cheers,
Sylvain

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2015-03-11  9:50 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-12 17:54 [PATCHv7 0/4] USB: gadget: atmel_usba_udc: PM driver improvements Sylvain Rochet
2015-02-12 17:54 ` [PATCHv7 1/4] USB: gadget: atmel_usba_udc: Fixed vbus_prev initial state Sylvain Rochet
2015-02-12 17:54 ` [PATCHv7 2/4] USB: gadget: atmel_usba_udc: Request an auto disabled Vbus signal IRQ instead of an auto enabled IRQ request followed by IRQ disable Sylvain Rochet
2015-03-10 21:12   ` Felipe Balbi
2015-03-11  9:50     ` Sylvain Rochet
2015-02-12 17:54 ` [PATCHv7 3/4] USB: gadget: atmel_usba_udc: Start clocks on rising edge of the Vbus signal, stop clocks on falling edge of the Vbus signal Sylvain Rochet
2015-03-10 21:13   ` Felipe Balbi
2015-02-12 17:54 ` [PATCHv7 4/4] USB: gadget: atmel_usba_udc: Add suspend/resume with wakeup support Sylvain Rochet
2015-03-04 13:09   ` Nicolas Ferre
2015-03-04 13:12 ` [PATCHv7 0/4] USB: gadget: atmel_usba_udc: PM driver improvements Nicolas Ferre
2015-03-10 21:10   ` Felipe Balbi

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.