diff options
-rw-r--r-- | drivers/net/ieee802154/at86rf230.c | 88 |
1 files changed, 68 insertions, 20 deletions
diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index 6b31f4708122..b839bbd4ff69 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c @@ -90,6 +90,7 @@ struct at86rf230_local { struct at86rf2xx_chip_data *data; struct regmap *regmap; int slp_tr; + bool sleep; struct completion state_complete; struct at86rf230_state_change state; @@ -114,18 +115,66 @@ at86rf230_async_state_change(struct at86rf230_local *lp, const u8 state, void (*complete)(void *context), const bool irq_enable); +static inline void +at86rf230_sleep(struct at86rf230_local *lp) +{ + if (gpio_is_valid(lp->slp_tr)) { + gpio_set_value(lp->slp_tr, 1); + usleep_range(lp->data->t_off_to_sleep, + lp->data->t_off_to_sleep + 10); + lp->sleep = true; + } +} + +static inline void +at86rf230_awake(struct at86rf230_local *lp) +{ + if (gpio_is_valid(lp->slp_tr)) { + gpio_set_value(lp->slp_tr, 0); + usleep_range(lp->data->t_sleep_to_off, + lp->data->t_sleep_to_off + 100); + lp->sleep = false; + } +} + static inline int __at86rf230_write(struct at86rf230_local *lp, unsigned int addr, unsigned int data) { - return regmap_write(lp->regmap, addr, data); + bool sleep = lp->sleep; + int ret; + + /* awake for register setting if sleep */ + if (sleep) + at86rf230_awake(lp); + + ret = regmap_write(lp->regmap, addr, data); + + /* sleep again if was sleeping */ + if (sleep) + at86rf230_sleep(lp); + + return ret; } static inline int __at86rf230_read(struct at86rf230_local *lp, unsigned int addr, unsigned int *data) { - return regmap_read(lp->regmap, addr, data); + bool sleep = lp->sleep; + int ret; + + /* awake for register setting if sleep */ + if (sleep) + at86rf230_awake(lp); + + ret = regmap_read(lp->regmap, addr, data); + + /* sleep again if was sleeping */ + if (sleep) + at86rf230_sleep(lp); + + return ret; } static inline int @@ -147,7 +196,20 @@ at86rf230_write_subreg(struct at86rf230_local *lp, unsigned int addr, unsigned int mask, unsigned int shift, unsigned int data) { - return regmap_update_bits(lp->regmap, addr, mask, data << shift); + bool sleep = lp->sleep; + int ret; + + /* awake for register setting if sleep */ + if (sleep) + at86rf230_awake(lp); + + ret = regmap_update_bits(lp->regmap, addr, mask, data << shift); + + /* sleep again if was sleeping */ + if (sleep) + at86rf230_sleep(lp); + + return ret; } static inline void @@ -873,12 +935,7 @@ at86rf230_start(struct ieee802154_hw *hw) { struct at86rf230_local *lp = hw->priv; - if (gpio_is_valid(lp->slp_tr)) { - gpio_set_value(lp->slp_tr, 0); - usleep_range(lp->data->t_sleep_to_off, - lp->data->t_sleep_to_off + 100); - } - + at86rf230_awake(lp); enable_irq(lp->spi->irq); return at86rf230_sync_state_change(hw->priv, STATE_RX_AACK_ON); @@ -892,12 +949,7 @@ at86rf230_stop(struct ieee802154_hw *hw) at86rf230_sync_state_change(hw->priv, STATE_FORCE_TRX_OFF); disable_irq(lp->spi->irq); - - if (gpio_is_valid(lp->slp_tr)) { - gpio_set_value(lp->slp_tr, 1); - usleep_range(lp->data->t_off_to_sleep, - lp->data->t_off_to_sleep + 10); - } + at86rf230_sleep(lp); } static int @@ -1672,11 +1724,7 @@ static int at86rf230_probe(struct spi_device *spi) disable_irq(spi->irq); /* going into sleep by default */ - if (gpio_is_valid(slp_tr)) { - gpio_set_value(slp_tr, 1); - usleep_range(lp->data->t_off_to_sleep, - lp->data->t_off_to_sleep + 10); - } + at86rf230_sleep(lp); rc = ieee802154_register_hw(lp->hw); if (rc) |