at86rf230: replace state change sleeps with hrtimer

This patch replace the state change timing relevant sleeps with
hrtimers. Currently the sleeps are done in the complete handler of
spi_async. The relation of doing the state change timing sleep with a
timer will get the sleep functionality out of spi_async complete handler
context.

Signed-off-by: Alexander Aring <alex.aring@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
This commit is contained in:
Alexander Aring 2015-03-09 13:56:10 +01:00 committed by Marcel Holtmann
parent e372174900
commit eb3b435ecd
1 changed files with 29 additions and 10 deletions

View File

@ -19,6 +19,7 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/hrtimer.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/gpio.h> #include <linux/gpio.h>
@ -64,6 +65,7 @@ struct at86rf230_state_change {
struct at86rf230_local *lp; struct at86rf230_local *lp;
int irq; int irq;
struct hrtimer timer;
struct spi_message msg; struct spi_message msg;
struct spi_transfer trx; struct spi_transfer trx;
u8 buf[AT86RF2XX_MAX_BUF]; u8 buf[AT86RF2XX_MAX_BUF];
@ -548,6 +550,19 @@ at86rf230_async_state_assert(void *context)
ctx->complete(context); ctx->complete(context);
} }
static enum hrtimer_restart at86rf230_async_state_timer(struct hrtimer *timer)
{
struct at86rf230_state_change *ctx =
container_of(timer, struct at86rf230_state_change, timer);
struct at86rf230_local *lp = ctx->lp;
at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx,
at86rf230_async_state_assert,
ctx->irq_enable);
return HRTIMER_NORESTART;
}
/* Do state change timing delay. */ /* Do state change timing delay. */
static void static void
at86rf230_async_state_delay(void *context) at86rf230_async_state_delay(void *context)
@ -556,6 +571,7 @@ at86rf230_async_state_delay(void *context)
struct at86rf230_local *lp = ctx->lp; struct at86rf230_local *lp = ctx->lp;
struct at86rf2xx_chip_data *c = lp->data; struct at86rf2xx_chip_data *c = lp->data;
bool force = false; bool force = false;
ktime_t tim;
/* The force state changes are will show as normal states in the /* The force state changes are will show as normal states in the
* state status subregister. We change the to_state to the * state status subregister. We change the to_state to the
@ -579,11 +595,10 @@ at86rf230_async_state_delay(void *context)
case STATE_TRX_OFF: case STATE_TRX_OFF:
switch (ctx->to_state) { switch (ctx->to_state) {
case STATE_RX_AACK_ON: case STATE_RX_AACK_ON:
usleep_range(c->t_off_to_aack, c->t_off_to_aack + 10); tim = ktime_set(0, c->t_off_to_aack * NSEC_PER_USEC);
goto change; goto change;
case STATE_TX_ON: case STATE_TX_ON:
usleep_range(c->t_off_to_tx_on, tim = ktime_set(0, c->t_off_to_tx_on * NSEC_PER_USEC);
c->t_off_to_tx_on + 10);
goto change; goto change;
default: default:
break; break;
@ -597,8 +612,8 @@ at86rf230_async_state_delay(void *context)
* to TX_ON. * to TX_ON.
*/ */
if (!force) { if (!force) {
usleep_range(c->t_frame + c->t_p_ack, tim = ktime_set(0, (c->t_frame + c->t_p_ack) *
c->t_frame + c->t_p_ack + 1000); NSEC_PER_USEC);
goto change; goto change;
} }
break; break;
@ -610,7 +625,7 @@ at86rf230_async_state_delay(void *context)
case STATE_P_ON: case STATE_P_ON:
switch (ctx->to_state) { switch (ctx->to_state) {
case STATE_TRX_OFF: case STATE_TRX_OFF:
usleep_range(c->t_reset_to_off, c->t_reset_to_off + 10); tim = ktime_set(0, c->t_reset_to_off * NSEC_PER_USEC);
goto change; goto change;
default: default:
break; break;
@ -621,12 +636,10 @@ at86rf230_async_state_delay(void *context)
} }
/* Default delay is 1us in the most cases */ /* Default delay is 1us in the most cases */
udelay(1); tim = ktime_set(0, NSEC_PER_USEC);
change: change:
at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx, hrtimer_start(&ctx->timer, tim, HRTIMER_MODE_REL);
at86rf230_async_state_assert,
ctx->irq_enable);
} }
static void static void
@ -1546,6 +1559,8 @@ at86rf230_setup_spi_messages(struct at86rf230_local *lp)
lp->state.trx.tx_buf = lp->state.buf; lp->state.trx.tx_buf = lp->state.buf;
lp->state.trx.rx_buf = lp->state.buf; lp->state.trx.rx_buf = lp->state.buf;
spi_message_add_tail(&lp->state.trx, &lp->state.msg); spi_message_add_tail(&lp->state.trx, &lp->state.msg);
hrtimer_init(&lp->state.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
lp->state.timer.function = at86rf230_async_state_timer;
lp->irq.lp = lp; lp->irq.lp = lp;
lp->irq.irq = lp->spi->irq; lp->irq.irq = lp->spi->irq;
@ -1555,6 +1570,8 @@ at86rf230_setup_spi_messages(struct at86rf230_local *lp)
lp->irq.trx.tx_buf = lp->irq.buf; lp->irq.trx.tx_buf = lp->irq.buf;
lp->irq.trx.rx_buf = lp->irq.buf; lp->irq.trx.rx_buf = lp->irq.buf;
spi_message_add_tail(&lp->irq.trx, &lp->irq.msg); spi_message_add_tail(&lp->irq.trx, &lp->irq.msg);
hrtimer_init(&lp->irq.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
lp->irq.timer.function = at86rf230_async_state_timer;
lp->tx.lp = lp; lp->tx.lp = lp;
lp->tx.irq = lp->spi->irq; lp->tx.irq = lp->spi->irq;
@ -1564,6 +1581,8 @@ at86rf230_setup_spi_messages(struct at86rf230_local *lp)
lp->tx.trx.tx_buf = lp->tx.buf; lp->tx.trx.tx_buf = lp->tx.buf;
lp->tx.trx.rx_buf = lp->tx.buf; lp->tx.trx.rx_buf = lp->tx.buf;
spi_message_add_tail(&lp->tx.trx, &lp->tx.msg); spi_message_add_tail(&lp->tx.trx, &lp->tx.msg);
hrtimer_init(&lp->tx.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
lp->tx.timer.function = at86rf230_async_state_timer;
} }
static int at86rf230_probe(struct spi_device *spi) static int at86rf230_probe(struct spi_device *spi)