From 2923c58eb5acb019e6781dc05662b896e14339f6 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Sat, 13 Feb 2016 02:04:07 +0530 Subject: [PATCH] greybus: arche_platform: Add sysfs to allow user to change state This patch introduces sysfs interface for the user space to enable operational state change of the driver. Currently, driver supports, 'off', 'active' and 'standby' Note that, driver doesn't do anything for standby state as of today. To see the current state # cat /sys/devices/arche_platform.*/state And to change the state # echo [off/active/standby] > /sys/devices/arche_platform.*/state Testing Done: Tested on EVT1.2 and DB3.5 platform. Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/arche-platform.c | 56 ++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index b2f3919f7cb3..1dd2b08225c4 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -148,6 +148,55 @@ static void arche_platform_poweroff_seq(struct arche_platform_drvdata *arche_pda arche_pdata->state = ARCHE_PLATFORM_STATE_OFF; } +static ssize_t state_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct platform_device *pdev = to_platform_device(dev); + struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev); + int ret = 0; + + if (sysfs_streq(buf, "off")) { + if (arche_pdata->state == ARCHE_PLATFORM_STATE_OFF) + return count; + + arche_platform_poweroff_seq(arche_pdata); + } else if (sysfs_streq(buf, "active")) { + if (arche_pdata->state == ARCHE_PLATFORM_STATE_ACTIVE) + return count; + + ret = arche_platform_coldboot_seq(arche_pdata); + } else if (sysfs_streq(buf, "standby")) { + if (arche_pdata->state == ARCHE_PLATFORM_STATE_STANDBY) + return count; + + dev_warn(arche_pdata->dev, "standby state not supported\n"); + } else { + dev_err(arche_pdata->dev, "unknown state\n"); + ret = -EINVAL; + } + + return ret ? ret : count; +} + +static ssize_t state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct arche_platform_drvdata *arche_pdata = dev_get_drvdata(dev); + + switch (arche_pdata->state) { + case ARCHE_PLATFORM_STATE_OFF: + return sprintf(buf, "off\n"); + case ARCHE_PLATFORM_STATE_ACTIVE: + return sprintf(buf, "active\n"); + case ARCHE_PLATFORM_STATE_STANDBY: + return sprintf(buf, "standby\n"); + default: + return sprintf(buf, "unknown state\n"); + } +} + +static DEVICE_ATTR_RW(state); + static int arche_platform_probe(struct platform_device *pdev) { struct arche_platform_drvdata *arche_pdata; @@ -248,6 +297,12 @@ static int arche_platform_probe(struct platform_device *pdev) INIT_DELAYED_WORK(&arche_pdata->delayed_work, svc_delayed_work); schedule_delayed_work(&arche_pdata->delayed_work, msecs_to_jiffies(2000)); + ret = device_create_file(dev, &dev_attr_state); + if (ret) { + dev_err(dev, "failed to create state file in sysfs\n"); + return ret; + } + ret = arche_platform_coldboot_seq(arche_pdata); if (ret) { dev_err(dev, "Failed to cold boot svc %d\n", ret); @@ -273,6 +328,7 @@ static int arche_platform_remove(struct platform_device *pdev) { struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev); + device_remove_file(&pdev->dev, &dev_attr_state); cancel_delayed_work_sync(&arche_pdata->delayed_work); device_for_each_child(&pdev->dev, NULL, arche_remove_child); arche_platform_poweroff_seq(arche_pdata); -- 2.39.5