summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDavid Lin <dtwlin@google.com>2016-07-12 17:41:21 -0700
committerGreg Kroah-Hartman <gregkh@google.com>2016-07-16 07:58:52 +0900
commit1f77b363bef417e28d8556a11c9a82f3e6cf24f0 (patch)
tree6fc4cc15c512e32c7fa762015c2c5b11c0ac42a5 /drivers
parent47becc556d4e8dc5bcd370100edebd6ad749b702 (diff)
downloadop-kernel-dev-1f77b363bef417e28d8556a11c9a82f3e6cf24f0.zip
op-kernel-dev-1f77b363bef417e28d8556a11c9a82f3e6cf24f0.tar.gz
greybus: hd: arche-platform: implement greybus shutdown
Implement platform driver shutdown callback to perform proper greybus shutdown so that the userspace unipro_shutdown service that shuts down the APB/SVC abruptly can be removed. The shutdown callback in arche-platform will first remove SVC so that all the Interface can be Deactivated in a sequence according to the spec before powering off the APB: Before: -> Arche/APB power off -> SoC power off After this patch: -> HD shutdown -> SVC shutdown -> Module shutdown -> Interface shutdown -> Bundle shutdown -> Arche/APB power off -> SoC power off Testing Done: - Observe all Interfaces are deactivated in the log during shutdown - Measure power off current and make sure no regression Signed-off-by: David Lin <dtwlin@google.com> Reviewed-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/staging/greybus/arche-apb-ctrl.c6
-rw-r--r--drivers/staging/greybus/arche-platform.c10
-rw-r--r--drivers/staging/greybus/core.c11
-rw-r--r--drivers/staging/greybus/hd.c6
-rw-r--r--drivers/staging/greybus/hd.h1
5 files changed, 34 insertions, 0 deletions
diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c
index fce6a18..cae56fc 100644
--- a/drivers/staging/greybus/arche-apb-ctrl.c
+++ b/drivers/staging/greybus/arche-apb-ctrl.c
@@ -444,6 +444,11 @@ static int arche_apb_ctrl_resume(struct device *dev)
return 0;
}
+static void arche_apb_ctrl_shutdown(struct platform_device *pdev)
+{
+ apb_ctrl_poweroff(&pdev->dev);
+}
+
static SIMPLE_DEV_PM_OPS(arche_apb_ctrl_pm_ops, arche_apb_ctrl_suspend,
arche_apb_ctrl_resume);
@@ -455,6 +460,7 @@ static struct of_device_id arche_apb_ctrl_of_match[] = {
static struct platform_driver arche_apb_ctrl_device_driver = {
.probe = arche_apb_ctrl_probe,
.remove = arche_apb_ctrl_remove,
+ .shutdown = arche_apb_ctrl_shutdown,
.driver = {
.name = "arche-apb-ctrl",
.pm = &arche_apb_ctrl_pm_ops,
diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c
index 31c9524..af78420 100644
--- a/drivers/staging/greybus/arche-platform.c
+++ b/drivers/staging/greybus/arche-platform.c
@@ -770,6 +770,15 @@ static int arche_platform_resume(struct device *dev)
return 0;
}
+static void arche_platform_shutdown(struct platform_device *pdev)
+{
+ struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev);
+
+ arche_platform_poweroff_seq(arche_pdata);
+
+ usb3613_hub_mode_ctrl(false);
+}
+
static SIMPLE_DEV_PM_OPS(arche_platform_pm_ops,
arche_platform_suspend,
arche_platform_resume);
@@ -789,6 +798,7 @@ MODULE_DEVICE_TABLE(of, arche_combined_id);
static struct platform_driver arche_platform_device_driver = {
.probe = arche_platform_probe,
.remove = arche_platform_remove,
+ .shutdown = arche_platform_shutdown,
.driver = {
.name = "arche-platform-ctrl",
.pm = &arche_platform_pm_ops,
diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c
index 53d9ba1..2c94bbb 100644
--- a/drivers/staging/greybus/core.c
+++ b/drivers/staging/greybus/core.c
@@ -146,10 +146,21 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env)
return 0;
}
+static void greybus_shutdown(struct device *dev)
+{
+ if (is_gb_host_device(dev)) {
+ struct gb_host_device *hd;
+
+ hd = to_gb_host_device(dev);
+ gb_hd_shutdown(hd);
+ }
+}
+
struct bus_type greybus_bus_type = {
.name = "greybus",
.match = greybus_match_device,
.uevent = greybus_uevent,
+ .shutdown = greybus_shutdown,
};
static int greybus_probe(struct device *dev)
diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c
index 8ef849a..185ae3f 100644
--- a/drivers/staging/greybus/hd.c
+++ b/drivers/staging/greybus/hd.c
@@ -232,6 +232,12 @@ void gb_hd_del(struct gb_host_device *hd)
}
EXPORT_SYMBOL_GPL(gb_hd_del);
+void gb_hd_shutdown(struct gb_host_device *hd)
+{
+ gb_svc_del(hd->svc);
+}
+EXPORT_SYMBOL_GPL(gb_hd_shutdown);
+
void gb_hd_put(struct gb_host_device *hd)
{
put_device(&hd->dev);
diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h
index d5d8c67..6ea5e28 100644
--- a/drivers/staging/greybus/hd.h
+++ b/drivers/staging/greybus/hd.h
@@ -75,6 +75,7 @@ struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver,
size_t num_cports);
int gb_hd_add(struct gb_host_device *hd);
void gb_hd_del(struct gb_host_device *hd);
+void gb_hd_shutdown(struct gb_host_device *hd);
void gb_hd_put(struct gb_host_device *hd);
int gb_hd_output(struct gb_host_device *hd, void *req, u16 size, u8 cmd,
bool in_irq);
OpenPOWER on IntegriCloud