Skip to content

Commit dce481e

Browse files
alexaringholtmann
authored andcommitted
at86rf230: add support for calibration timeout
This patch adds a handling for calibration if we are 5 minutes in PLL state. I first tried to implement the calibration functionality in TX_ON state via register values CF_START and DCU_START, but this occurs a one second delay at each calibration time. An another solution to start a calibration is to switch from TRX_OFF state into TX_ON, then a calibration is done automatically by transceiver. This method will be used in this patch, after each transmit of a frame we check with jiffies if the PLL is set 5 minutes without doing a TRX_OFF->(TX_ON || RX_AACK_ON) or channel switch. The worst case would be a transceiver in receiving mode only, but this is under normal operation very unlikely. Signed-off-by: Alexander Aring <[email protected]> Cc: Phoebe Buckheister <[email protected]> Cc: Werner Almesberger <[email protected]> Signed-off-by: Marcel Holtmann <[email protected]>
1 parent eb3b435 commit dce481e

File tree

1 file changed

+58
-14
lines changed

1 file changed

+58
-14
lines changed

drivers/net/ieee802154/at86rf230.c

Lines changed: 58 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <linux/kernel.h>
2121
#include <linux/module.h>
2222
#include <linux/hrtimer.h>
23+
#include <linux/jiffies.h>
2324
#include <linux/interrupt.h>
2425
#include <linux/irq.h>
2526
#include <linux/gpio.h>
@@ -60,6 +61,8 @@ struct at86rf2xx_chip_data {
6061
* We assume the max_frame_retries (7) value of 802.15.4 here.
6162
*/
6263
#define AT86RF2XX_MAX_TX_RETRIES 7
64+
/* We use the recommended 5 minutes timeout to recalibrate */
65+
#define AT86RF2XX_CAL_LOOP_TIMEOUT (5 * 60 * HZ)
6366

6467
struct at86rf230_state_change {
6568
struct at86rf230_local *lp;
@@ -90,6 +93,7 @@ struct at86rf230_local {
9093
struct at86rf230_state_change irq;
9194

9295
bool tx_aret;
96+
unsigned long cal_timeout;
9397
s8 max_frame_retries;
9498
bool is_tx;
9599
/* spinlock for is_tx protection */
@@ -491,6 +495,14 @@ at86rf230_async_read_reg(struct at86rf230_local *lp, const u8 reg,
491495
}
492496
}
493497

498+
static inline u8 at86rf230_state_to_force(u8 state)
499+
{
500+
if (state == STATE_TX_ON)
501+
return STATE_FORCE_TX_ON;
502+
else
503+
return STATE_FORCE_TRX_OFF;
504+
}
505+
494506
static void
495507
at86rf230_async_state_assert(void *context)
496508
{
@@ -527,11 +539,12 @@ at86rf230_async_state_assert(void *context)
527539
* higher or equal than AT86RF2XX_MAX_TX_RETRIES we
528540
* will do a force change.
529541
*/
530-
if (ctx->to_state == STATE_TX_ON) {
531-
u8 state = STATE_TX_ON;
542+
if (ctx->to_state == STATE_TX_ON ||
543+
ctx->to_state == STATE_TRX_OFF) {
544+
u8 state = ctx->to_state;
532545

533546
if (lp->tx_retry >= AT86RF2XX_MAX_TX_RETRIES)
534-
state = STATE_FORCE_TX_ON;
547+
state = at86rf230_state_to_force(state);
535548
lp->tx_retry++;
536549

537550
at86rf230_async_state_change(lp, ctx, state,
@@ -599,17 +612,23 @@ at86rf230_async_state_delay(void *context)
599612
goto change;
600613
case STATE_TX_ON:
601614
tim = ktime_set(0, c->t_off_to_tx_on * NSEC_PER_USEC);
615+
/* state change from TRX_OFF to TX_ON to do a
616+
* calibration, we need to reset the timeout for the
617+
* next one.
618+
*/
619+
lp->cal_timeout = jiffies + AT86RF2XX_CAL_LOOP_TIMEOUT;
602620
goto change;
603621
default:
604622
break;
605623
}
606624
break;
607625
case STATE_BUSY_RX_AACK:
608626
switch (ctx->to_state) {
627+
case STATE_TRX_OFF:
609628
case STATE_TX_ON:
610629
/* Wait for worst case receiving time if we
611630
* didn't make a force change from BUSY_RX_AACK
612-
* to TX_ON.
631+
* to TX_ON or TRX_OFF.
613632
*/
614633
if (!force) {
615634
tim = ktime_set(0, (c->t_frame + c->t_p_ack) *
@@ -969,25 +988,45 @@ at86rf230_xmit_tx_on(void *context)
969988
at86rf230_write_frame, false);
970989
}
971990

972-
static int
973-
at86rf230_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
991+
static void
992+
at86rf230_xmit_start(void *context)
974993
{
975-
struct at86rf230_local *lp = hw->priv;
976-
struct at86rf230_state_change *ctx = &lp->tx;
977-
978-
void (*tx_complete)(void *context) = at86rf230_write_frame;
979-
980-
lp->tx_skb = skb;
994+
struct at86rf230_state_change *ctx = context;
995+
struct at86rf230_local *lp = ctx->lp;
981996

982997
/* In ARET mode we need to go into STATE_TX_ARET_ON after we
983998
* are in STATE_TX_ON. The pfad differs here, so we change
984999
* the complete handler.
9851000
*/
9861001
if (lp->tx_aret)
987-
tx_complete = at86rf230_xmit_tx_on;
1002+
at86rf230_async_state_change(lp, ctx, STATE_TX_ON,
1003+
at86rf230_xmit_tx_on, false);
1004+
else
1005+
at86rf230_async_state_change(lp, ctx, STATE_TX_ON,
1006+
at86rf230_write_frame, false);
1007+
}
1008+
1009+
static int
1010+
at86rf230_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
1011+
{
1012+
struct at86rf230_local *lp = hw->priv;
1013+
struct at86rf230_state_change *ctx = &lp->tx;
9881014

1015+
lp->tx_skb = skb;
9891016
lp->tx_retry = 0;
990-
at86rf230_async_state_change(lp, ctx, STATE_TX_ON, tx_complete, false);
1017+
1018+
/* After 5 minutes in PLL and the same frequency we run again the
1019+
* calibration loops which is recommended by at86rf2xx datasheets.
1020+
*
1021+
* The calibration is initiate by a state change from TRX_OFF
1022+
* to TX_ON, the lp->cal_timeout should be reinit by state_delay
1023+
* function then to start in the next 5 minutes.
1024+
*/
1025+
if (time_is_before_jiffies(lp->cal_timeout))
1026+
at86rf230_async_state_change(lp, ctx, STATE_TRX_OFF,
1027+
at86rf230_xmit_start, false);
1028+
else
1029+
at86rf230_xmit_start(ctx);
9911030

9921031
return 0;
9931032
}
@@ -1003,6 +1042,9 @@ at86rf230_ed(struct ieee802154_hw *hw, u8 *level)
10031042
static int
10041043
at86rf230_start(struct ieee802154_hw *hw)
10051044
{
1045+
struct at86rf230_local *lp = hw->priv;
1046+
1047+
lp->cal_timeout = jiffies + AT86RF2XX_CAL_LOOP_TIMEOUT;
10061048
return at86rf230_sync_state_change(hw->priv, STATE_RX_AACK_ON);
10071049
}
10081050

@@ -1083,6 +1125,8 @@ at86rf230_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
10831125
/* Wait for PLL */
10841126
usleep_range(lp->data->t_channel_switch,
10851127
lp->data->t_channel_switch + 10);
1128+
1129+
lp->cal_timeout = jiffies + AT86RF2XX_CAL_LOOP_TIMEOUT;
10861130
return rc;
10871131
}
10881132

0 commit comments

Comments
 (0)