greybus: arche-apb-ctrl: Introduce ara,init-disable property for APB
authorVaibhav Hiremath <vaibhav.hiremath@linaro.org>
Fri, 12 Feb 2016 20:34:14 +0000 (02:04 +0530)
committerGreg Kroah-Hartman <gregkh@google.com>
Mon, 15 Feb 2016 21:18:40 +0000 (13:18 -0800)
New DT property "ara,init-disable" will allow user to disable
APB1 or APB2 during boot and enable it only when needed through
command prompt via sysfs interface.

 - To disable APB2 during boot, specify "ara,init-disable" property in
   respective APB node.

 - How to check the state
   # cat /sys/devices/arche_platform.*/apb*/state

   It should be 'off', if 'ara,init-disable' enabled in DT.

 - During runtime if user/developer desired to enable APB2 (strictly and
   only for development purpose) then respective APB can be enabled
   through,

   # echo active > /sys/devices/arche_platform.*/apb*/state

Note:
  - If APB device is in 'off,disabled' state, then no state transitions
    are permitted.
  - User/developer must first activate APB device

    # echo active > /sys/devices/arche_platform.*/apb*/state

    This will clear the 'init-disable' flag and allow state transition
    from here onwards.
    Note that, 'off,disabled' is only indicative state and is only
    applicable during init/boot.

Testing Done: Tested on EVT1.2 and DB3.5 platform

Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
drivers/staging/greybus/arche-apb-ctrl.c

index e4fd34ddf46519e25f0edf0f08c4571577a487c6..04ba8365f7bfd2b95c29c79a67aea110b2a1b28c 100644 (file)
@@ -32,6 +32,7 @@ struct arche_apb_ctrl_drvdata {
        int pwrdn_gpio;
 
        enum arche_platform_state state;
+       bool init_disabled;
 
        struct regulator *vcore;
        struct regulator *vio;
@@ -77,6 +78,9 @@ static int apb_ctrl_coldboot_seq(struct platform_device *pdev)
        struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev);
        int ret;
 
+       if (apb->init_disabled)
+               return 0;
+
        /* Hold APB in reset state */
        assert_reset(apb->resetn_gpio);
 
@@ -119,6 +123,9 @@ static int apb_ctrl_fw_flashing_seq(struct platform_device *pdev)
        struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev);
        int ret;
 
+       if (apb->init_disabled)
+               return 0;
+
        ret = regulator_enable(apb->vcore);
        if (ret) {
                dev_err(dev, "failed to enable core regulator\n");
@@ -142,6 +149,9 @@ static int apb_ctrl_standby_boot_seq(struct platform_device *pdev)
 {
        struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev);
 
+       if (apb->init_disabled)
+               return 0;
+
        /* If it is in OFF state, then we do not want to change the state */
        if (apb->state == ARCHE_PLATFORM_STATE_OFF)
                return 0;
@@ -163,6 +173,9 @@ static void apb_ctrl_poweroff_seq(struct platform_device *pdev)
 {
        struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev);
 
+       if (apb->init_disabled)
+               return;
+
        /* disable the clock */
        if (gpio_is_valid(apb->clk_en_gpio))
                gpio_set_value(apb->clk_en_gpio, 0);
@@ -186,6 +199,7 @@ static ssize_t state_store(struct device *dev,
        struct platform_device *pdev = to_platform_device(dev);
        struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev);
        int ret = 0;
+       bool is_disabled;
 
        if (sysfs_streq(buf, "off")) {
                if (apb->state == ARCHE_PLATFORM_STATE_OFF)
@@ -197,7 +211,11 @@ static ssize_t state_store(struct device *dev,
                        return count;
 
                apb_ctrl_poweroff_seq(pdev);
+               is_disabled = apb->init_disabled;
+               apb->init_disabled = false;
                ret = apb_ctrl_coldboot_seq(pdev);
+               if (ret)
+                       apb->init_disabled = is_disabled;
        } else if (sysfs_streq(buf, "standby")) {
                if (apb->state == ARCHE_PLATFORM_STATE_STANDBY)
                        return count;
@@ -226,7 +244,8 @@ static ssize_t state_show(struct device *dev,
 
        switch (apb->state) {
        case ARCHE_PLATFORM_STATE_OFF:
-               return sprintf(buf, "off\n");
+               return sprintf(buf, "off%s\n",
+                               apb->init_disabled ? ",disabled" : "");
        case ARCHE_PLATFORM_STATE_ACTIVE:
                return sprintf(buf, "active\n");
        case ARCHE_PLATFORM_STATE_STANDBY:
@@ -346,6 +365,9 @@ int arche_apb_ctrl_probe(struct platform_device *pdev)
 
        /* Initially set APB to OFF state */
        apb->state = ARCHE_PLATFORM_STATE_OFF;
+       /* Check whether device needs to be enabled on boot */
+       if (of_property_read_bool(pdev->dev.of_node, "ara,init-disable"))
+               apb->init_disabled = true;
 
        platform_set_drvdata(pdev, apb);