static void at86rf230_irq_trx_end(void *context) { struct at86rf230_state_change *ctx = context; struct at86rf230_local *lp = ctx->lp; if (lp->is_tx) { lp->is_tx = 0; at86rf230_async_read_reg(lp, RG_TRX_STATE, ctx, at86rf230_tx_trac_check); } else { at86rf230_async_read_reg(lp, RG_TRX_STATE, ctx, at86rf230_rx_trac_check); } }
static void at86rf230_async_state_change_start(void *context) { struct at86rf230_state_change *ctx = context; struct at86rf230_local *lp = ctx->lp; u8 *buf = ctx->buf; const u8 trx_state = buf[1] & TRX_STATE_MASK; /* Check for "possible" STATE_TRANSITION_IN_PROGRESS */ if (trx_state == STATE_TRANSITION_IN_PROGRESS) { udelay(1); at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx, at86rf230_async_state_change_start); return; } /* Check if we already are in the state which we change in */ if (trx_state == ctx->to_state) { if (ctx->complete) ctx->complete(context); return; } /* Set current state to the context of state change */ ctx->from_state = trx_state; /* Going into the next step for a state change which do a timing * relevant delay. */ at86rf230_async_write_reg(lp, RG_TRX_STATE, ctx->to_state, ctx, at86rf230_async_state_delay); }
static void at86rf230_tx_trac_status(void *context) { struct at86rf230_state_change *ctx = context; struct at86rf230_local *lp = ctx->lp; at86rf230_async_read_reg(lp, RG_TRX_STATE, ctx, at86rf230_tx_trac_check, true); }
static void at86rf230_async_state_change(struct at86rf230_local *lp, struct at86rf230_state_change *ctx, const u8 state, void (*complete)(void *context)) { /* Initialization for the state change context */ ctx->to_state = state; ctx->complete = complete; at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx, at86rf230_async_state_change_start); }
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); return HRTIMER_NORESTART; }
static void at86rf230_irq_trx_end(struct at86rf230_local *lp) { if (lp->is_tx) { lp->is_tx = 0; at86rf230_async_state_change(lp, &lp->irq, STATE_FORCE_TX_ON, at86rf230_tx_trac_status, true); } else { at86rf230_async_read_reg(lp, RG_TRX_STATE, &lp->irq, at86rf230_rx_trac_check, true); } }
static void at86rf230_async_state_change_start(void *context) { struct at86rf230_state_change *ctx = context; struct at86rf230_local *lp = ctx->lp; u8 *buf = ctx->buf; const u8 trx_state = buf[1] & 0x1f; int rc; /* Check for "possible" STATE_TRANSITION_IN_PROGRESS */ if (trx_state == STATE_TRANSITION_IN_PROGRESS) { udelay(1); at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx, at86rf230_async_state_change_start, ctx->irq_enable); return; } /* Check if we already are in the state which we change in */ if (trx_state == ctx->to_state) { if (ctx->complete) ctx->complete(context); return; } /* Set current state to the context of state change */ ctx->from_state = trx_state; /* Going into the next step for a state change which do a timing * relevant delay. */ buf[0] = (RG_TRX_STATE & CMD_REG_MASK) | CMD_REG | CMD_WRITE; buf[1] = ctx->to_state; ctx->trx.len = 2; ctx->msg.complete = at86rf230_async_state_delay; rc = spi_async(lp->spi, &ctx->msg); if (rc) { if (ctx->irq_enable) enable_irq(lp->spi->irq); at86rf230_async_error(lp, ctx, rc); } }
static void at86rf230_irq_trx_end(struct at86rf230_local *lp) { spin_lock(&lp->lock); if (lp->is_tx) { lp->is_tx = 0; spin_unlock(&lp->lock); if (lp->tx_aret) at86rf230_async_state_change(lp, &lp->irq, STATE_FORCE_TX_ON, at86rf230_tx_trac_status, true); else at86rf230_async_state_change(lp, &lp->irq, STATE_RX_AACK_ON, at86rf230_tx_complete, true); } else { spin_unlock(&lp->lock); at86rf230_async_read_reg(lp, RG_TRX_STATE, &lp->irq, at86rf230_rx_trac_check, true); } }
/* Do state change timing delay. */ static void at86rf230_async_state_delay(void *context) { struct at86rf230_state_change *ctx = context; struct at86rf230_local *lp = ctx->lp; struct at86rf2xx_chip_data *c = lp->data; bool force = false; /* The force state changes are will show as normal states in the * state status subregister. We change the to_state to the * corresponding one and remember if it was a force change, this * differs if we do a state change from STATE_BUSY_RX_AACK. */ switch (ctx->to_state) { case STATE_FORCE_TX_ON: ctx->to_state = STATE_TX_ON; force = true; break; case STATE_FORCE_TRX_OFF: ctx->to_state = STATE_TRX_OFF; force = true; break; default: break; } switch (ctx->from_state) { case STATE_TRX_OFF: switch (ctx->to_state) { case STATE_RX_AACK_ON: usleep_range(c->t_off_to_aack, c->t_off_to_aack + 10); goto change; case STATE_TX_ON: usleep_range(c->t_off_to_tx_on, c->t_off_to_tx_on + 10); goto change; default: break; } break; case STATE_BUSY_RX_AACK: switch (ctx->to_state) { case STATE_TX_ON: /* Wait for worst case receiving time if we * didn't make a force change from BUSY_RX_AACK * to TX_ON. */ if (!force) { usleep_range(c->t_frame + c->t_p_ack, c->t_frame + c->t_p_ack + 1000); goto change; } break; default: break; } break; /* Default value, means RESET state */ case STATE_P_ON: switch (ctx->to_state) { case STATE_TRX_OFF: usleep_range(c->t_reset_to_off, c->t_reset_to_off + 10); goto change; default: break; } break; default: break; } /* Default delay is 1us in the most cases */ udelay(1); change: at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx, at86rf230_async_state_assert, ctx->irq_enable); }