Pārlūkot izejas kodu

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>
David Lin 9 gadi atpakaļ
vecāks
revīzija
1f77b363be

+ 6 - 0
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,

+ 10 - 0
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,

+ 11 - 0
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)

+ 6 - 0
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);

+ 1 - 0
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);