]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
greybus: hd: arche-platform: implement greybus shutdown
authorDavid Lin <dtwlin@google.com>
Wed, 13 Jul 2016 00:41:21 +0000 (17:41 -0700)
committerGreg Kroah-Hartman <gregkh@google.com>
Fri, 15 Jul 2016 22:58:52 +0000 (07:58 +0900)
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>
drivers/staging/greybus/arche-apb-ctrl.c
drivers/staging/greybus/arche-platform.c
drivers/staging/greybus/core.c
drivers/staging/greybus/hd.c
drivers/staging/greybus/hd.h

index fce6a187ecfea650a4da89e4a1c87a2743e4ffdb..cae56fc0a6e554310e105692434f7a33277bdd28 100644 (file)
@@ -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,
index 31c952454cff3b82055f8821eab4c620b6a07b47..af784204973f467b66bbaf1f7bf2cc919a8e57cd 100644 (file)
@@ -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,
index 53d9ba151aeb1326bf442a5084f001c9e6e935d9..2c94bbb1748fb2cd904db24e19f79160ee4f50ba 100644 (file)
@@ -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)
index 8ef849a8300ffb2b92458099e000f33dc0f964ce..185ae3fa10fd6f99357380cf6907cea0b98469b1 100644 (file)
@@ -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);
index d5d8c67551f2820cc40e151272addf95b0d74ac4..6ea5e28d9eb9d88f420e45574e40ce55661bf819 100644 (file)
@@ -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);