diff options
author | Bryan O'Donoghue <bryan.odonoghue@linaro.org> | 2016-05-05 15:34:59 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@google.com> | 2016-05-05 13:49:02 -0700 |
commit | c4058b7926a44387b1d2480be0f209edb74e7f1c (patch) | |
tree | c664797ff67bb163f91eec6022183b127a9dc288 /drivers/staging/greybus/arche-platform.c | |
parent | greybus: arche-platform: Export fn to allow timesync driver to change the state (diff) | |
download | linux-dev-c4058b7926a44387b1d2480be0f209edb74e7f1c.tar.xz linux-dev-c4058b7926a44387b1d2480be0f209edb74e7f1c.zip |
greybus: arche-platform: Rework platform/wd-line state transition logic
This patch simplifies and improves the readability of the internal state
transition logic of arche platform driver state transition logic by:
1. Making a dedicated function to state-transition the platform code.
2. Condense the decision to swtich states down to a single switch
statement instead of four separate if/else clauses.
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Suggested-by: Alex Elder <elder@linaro.org>
Reviewed-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Diffstat (limited to 'drivers/staging/greybus/arche-platform.c')
-rw-r--r-- | drivers/staging/greybus/arche-platform.c | 73 |
1 files changed, 48 insertions, 25 deletions
diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 4eceec39ae99..83d823cf5232 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -63,6 +63,13 @@ struct arche_platform_drvdata { struct device *dev; }; +/* Requires calling context to hold arche_pdata->spinlock */ +static void arche_platform_set_state(struct arche_platform_drvdata *arche_pdata, + enum arche_platform_state state) +{ + arche_pdata->state = state; +} + /* * arche_platform_change_state: Change the operational state * @@ -122,22 +129,26 @@ int arche_platform_change_state(enum arche_platform_state state) goto exit; } - if (arche_pdata->state == ARCHE_PLATFORM_STATE_OFF || - arche_pdata->state == ARCHE_PLATFORM_STATE_STANDBY || - arche_pdata->state == ARCHE_PLATFORM_STATE_FW_FLASHING) { - dev_err(arche_pdata->dev, "busy, request to retry later\n"); - goto exit; - } - - if (state == ARCHE_PLATFORM_STATE_TIME_SYNC) { + switch (state) { + case ARCHE_PLATFORM_STATE_TIME_SYNC: disable_irq(arche_pdata->wake_detect_irq); - arche_pdata->state = ARCHE_PLATFORM_STATE_TIME_SYNC; - } else if (state == ARCHE_PLATFORM_STATE_ACTIVE) { - arche_pdata->state = ARCHE_PLATFORM_STATE_ACTIVE; + break; + case ARCHE_PLATFORM_STATE_ACTIVE: enable_irq(arche_pdata->wake_detect_irq); - } else { - dev_err(arche_pdata->dev, "invalid state transition request\n"); + break; + case ARCHE_PLATFORM_STATE_OFF: + case ARCHE_PLATFORM_STATE_STANDBY: + case ARCHE_PLATFORM_STATE_FW_FLASHING: + dev_err(arche_pdata->dev, "busy, request to retry later\n"); + goto exit; + default: + ret = -EINVAL; + dev_err(arche_pdata->dev, + "invalid state transition request\n"); + goto exit; } + arche_platform_set_state(arche_pdata, state); + ret = 0; exit: spin_unlock_irqrestore(&arche_pdata->wake_lock, flags); mutex_unlock(&arche_pdata->platform_state_mutex); @@ -146,6 +157,14 @@ exit: } EXPORT_SYMBOL_GPL(arche_platform_change_state); +/* Requires arche_pdata->wake_lock is held by calling context */ +static void arche_platform_set_wake_detect_state( + struct arche_platform_drvdata *arche_pdata, + enum svc_wakedetect_state state) +{ + arche_pdata->wake_detect_state = state; +} + static inline void svc_reset_onoff(unsigned int gpio, bool onoff) { gpio_set_value(gpio, onoff); @@ -208,7 +227,8 @@ static irqreturn_t arche_platform_wd_irq_thread(int irq, void *devid) return IRQ_HANDLED; } - arche_pdata->wake_detect_state = WD_STATE_COLDBOOT_START; + arche_platform_set_wake_detect_state(arche_pdata, + WD_STATE_COLDBOOT_START); spin_unlock_irqrestore(&arche_pdata->wake_lock, flags); /* It should complete power cycle, so first make sure it is poweroff */ @@ -222,7 +242,7 @@ static irqreturn_t arche_platform_wd_irq_thread(int irq, void *devid) dev_warn(arche_pdata->dev, "failed to control hub device\n"); spin_lock_irqsave(&arche_pdata->wake_lock, flags); - arche_pdata->wake_detect_state = WD_STATE_IDLE; + arche_platform_set_wake_detect_state(arche_pdata, WD_STATE_IDLE); spin_unlock_irqrestore(&arche_pdata->wake_lock, flags); return IRQ_HANDLED; @@ -247,13 +267,14 @@ static irqreturn_t arche_platform_wd_irq(int irq, void *devid) if (time_before(jiffies, arche_pdata->wake_detect_start + msecs_to_jiffies(WD_COLDBOOT_PULSE_WIDTH_MS))) { - arche_pdata->wake_detect_state = WD_STATE_IDLE; + arche_platform_set_wake_detect_state(arche_pdata, + WD_STATE_IDLE); } else { /* Check we are not in middle of irq thread already */ if (arche_pdata->wake_detect_state != WD_STATE_COLDBOOT_START) { - arche_pdata->wake_detect_state = - WD_STATE_COLDBOOT_TRIG; + arche_platform_set_wake_detect_state(arche_pdata, + WD_STATE_COLDBOOT_TRIG); spin_unlock_irqrestore( &arche_pdata->wake_lock, flags); @@ -270,7 +291,8 @@ static irqreturn_t arche_platform_wd_irq(int irq, void *devid) * it is meant for coldboot and set the flag. If wake/detect line stays low * beyond 30msec, then it is coldboot else fallback to standby boot. */ - arche_pdata->wake_detect_state = WD_STATE_BOOT_INIT; + arche_platform_set_wake_detect_state(arche_pdata, + WD_STATE_BOOT_INIT); } } @@ -308,7 +330,7 @@ static int arche_platform_coldboot_seq(struct arche_platform_drvdata *arche_pdat svc_reset_onoff(arche_pdata->svc_reset_gpio, !arche_pdata->is_reset_act_hi); - arche_pdata->state = ARCHE_PLATFORM_STATE_ACTIVE; + arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_ACTIVE); return 0; } @@ -332,7 +354,7 @@ static void arche_platform_fw_flashing_seq(struct arche_platform_drvdata *arche_ svc_reset_onoff(arche_pdata->svc_reset_gpio, !arche_pdata->is_reset_act_hi); - arche_pdata->state = ARCHE_PLATFORM_STATE_FW_FLASHING; + arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_FW_FLASHING); } @@ -353,7 +375,8 @@ static void arche_platform_poweroff_seq(struct arche_platform_drvdata *arche_pda gpio_direction_output(arche_pdata->wake_detect_gpio, 0); usleep_range(100, 200); spin_lock_irqsave(&arche_pdata->wake_lock, flags); - arche_pdata->wake_detect_state = WD_STATE_IDLE; + arche_platform_set_wake_detect_state(arche_pdata, + WD_STATE_IDLE); spin_unlock_irqrestore(&arche_pdata->wake_lock, flags); clk_disable_unprepare(arche_pdata->svc_ref_clk); @@ -363,7 +386,7 @@ static void arche_platform_poweroff_seq(struct arche_platform_drvdata *arche_pda svc_reset_onoff(arche_pdata->svc_reset_gpio, arche_pdata->is_reset_act_hi); - arche_pdata->state = ARCHE_PLATFORM_STATE_OFF; + arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_OFF); } static ssize_t state_store(struct device *dev, @@ -502,7 +525,7 @@ static int arche_platform_probe(struct platform_device *pdev) dev_err(dev, "failed to set svc-reset gpio dir:%d\n", ret); return ret; } - arche_pdata->state = ARCHE_PLATFORM_STATE_OFF; + arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_OFF); arche_pdata->svc_sysboot_gpio = of_get_named_gpio(np, "svc,sysboot-gpio", 0); @@ -567,7 +590,7 @@ static int arche_platform_probe(struct platform_device *pdev) } /* deassert wake detect */ gpio_direction_output(arche_pdata->wake_detect_gpio, 0); - arche_pdata->wake_detect_state = WD_STATE_IDLE; + arche_platform_set_wake_detect_state(arche_pdata, WD_STATE_IDLE); arche_pdata->dev = &pdev->dev; |