usb: renesas_usbhs: add autonomy mode
Current renesas_usbhs was designed to save power when USB is not connected.
And it assumed platform uses callback to notify connection/disconnection
by external interrupt.
But some SuperH / platform board doesn't have such feature.
This patch adds autonomy mode which detect USB connection/disconnection
by internal interrupt.
But power will be always ON when autonomy mode is selected.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c
index 9a75a456..34e68e0 100644
--- a/drivers/usb/renesas_usbhs/common.c
+++ b/drivers/usb/renesas_usbhs/common.c
@@ -21,6 +21,14 @@
#include <linux/sysfs.h>
#include "./common.h"
+#define USBHSF_RUNTIME_PWCTRL (1 << 0)
+
+/* status */
+#define usbhsc_flags_init(p) do {(p)->flags = 0; } while (0)
+#define usbhsc_flags_set(p, b) ((p)->flags |= (b))
+#define usbhsc_flags_clr(p, b) ((p)->flags &= ~(b))
+#define usbhsc_flags_has(p, b) ((p)->flags & (b))
+
/*
* platform call back
*
@@ -203,7 +211,8 @@
dev_dbg(&pdev->dev, "%s enable\n", __func__);
/* power on */
- usbhsc_power_ctrl(priv, enable);
+ if (usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL))
+ usbhsc_power_ctrl(priv, enable);
/* module start */
usbhs_mod_call(priv, start, priv);
@@ -215,7 +224,8 @@
usbhs_mod_call(priv, stop, priv);
/* power off */
- usbhsc_power_ctrl(priv, enable);
+ if (usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL))
+ usbhsc_power_ctrl(priv, enable);
usbhs_mod_change(priv, -1);
@@ -252,8 +262,7 @@
/* check platform information */
if (!info ||
- !info->platform_callback.get_id ||
- !info->platform_callback.get_vbus) {
+ !info->platform_callback.get_id) {
dev_err(&pdev->dev, "no platform information\n");
return -EINVAL;
}
@@ -296,6 +305,11 @@
priv->dparam->pipe_size = ARRAY_SIZE(usbhsc_default_pipe_type);
}
+ /* FIXME */
+ /* runtime power control ? */
+ if (priv->pfunc->get_vbus)
+ usbhsc_flags_set(priv, USBHSF_RUNTIME_PWCTRL);
+
/*
* priv settings
*/
@@ -338,10 +352,16 @@
/* reset phy for connection */
usbhs_platform_call(priv, phy_reset, pdev);
+ /* power control */
+ pm_runtime_enable(&pdev->dev);
+ if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) {
+ usbhsc_power_ctrl(priv, 1);
+ usbhs_mod_autonomy_mode(priv);
+ }
+
/*
* manual call notify_hotplug for cold plug
*/
- pm_runtime_enable(&pdev->dev);
ret = usbhsc_drvcllbck_notify_hotplug(pdev);
if (ret < 0)
goto probe_end_call_remove;
@@ -376,9 +396,11 @@
dfunc->notify_hotplug = NULL;
- pm_runtime_disable(&pdev->dev);
+ /* power off */
+ if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL))
+ usbhsc_power_ctrl(priv, 0);
- usbhsc_bus_ctrl(priv, 0);
+ pm_runtime_disable(&pdev->dev);
usbhs_platform_call(priv, hardware_exit, pdev);
usbhs_pipe_remove(priv);