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>
This commit is contained in:
David Lin 2016-07-12 17:41:21 -07:00 committed by Greg Kroah-Hartman
parent 47becc556d
commit 1f77b363be
5 changed files with 34 additions and 0 deletions

View 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,

View 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,

View 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)

View 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);

View 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);