aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Aring <alex.aring@gmail.com>2015-03-09 08:56:11 -0400
committerMarcel Holtmann <marcel@holtmann.org>2015-03-14 12:11:31 -0400
commitdce481e63dc18ece7c86c607aa17b7c753fce0b7 (patch)
tree2a952d0cf786987a03e56fd7268c370e32dd4810
parenteb3b435ecdb84d05698db862ce316b3c682f9a95 (diff)
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 <alex.aring@gmail.com> Cc: Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de> Cc: Werner Almesberger <werner@almesberger.net> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r--drivers/net/ieee802154/at86rf230.c72
1 files changed, 58 insertions, 14 deletions
diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index 4030fa69f176..795106c23097 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -20,6 +20,7 @@
20#include <linux/kernel.h> 20#include <linux/kernel.h>
21#include <linux/module.h> 21#include <linux/module.h>
22#include <linux/hrtimer.h> 22#include <linux/hrtimer.h>
23#include <linux/jiffies.h>
23#include <linux/interrupt.h> 24#include <linux/interrupt.h>
24#include <linux/irq.h> 25#include <linux/irq.h>
25#include <linux/gpio.h> 26#include <linux/gpio.h>
@@ -60,6 +61,8 @@ struct at86rf2xx_chip_data {
60 * We assume the max_frame_retries (7) value of 802.15.4 here. 61 * We assume the max_frame_retries (7) value of 802.15.4 here.
61 */ 62 */
62#define AT86RF2XX_MAX_TX_RETRIES 7 63#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)
63 66
64struct at86rf230_state_change { 67struct at86rf230_state_change {
65 struct at86rf230_local *lp; 68 struct at86rf230_local *lp;
@@ -90,6 +93,7 @@ struct at86rf230_local {
90 struct at86rf230_state_change irq; 93 struct at86rf230_state_change irq;
91 94
92 bool tx_aret; 95 bool tx_aret;
96 unsigned long cal_timeout;
93 s8 max_frame_retries; 97 s8 max_frame_retries;
94 bool is_tx; 98 bool is_tx;
95 /* spinlock for is_tx protection */ 99 /* spinlock for is_tx protection */
@@ -491,6 +495,14 @@ at86rf230_async_read_reg(struct at86rf230_local *lp, const u8 reg,
491 } 495 }
492} 496}
493 497
498static 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
494static void 506static void
495at86rf230_async_state_assert(void *context) 507at86rf230_async_state_assert(void *context)
496{ 508{
@@ -527,11 +539,12 @@ at86rf230_async_state_assert(void *context)
527 * higher or equal than AT86RF2XX_MAX_TX_RETRIES we 539 * higher or equal than AT86RF2XX_MAX_TX_RETRIES we
528 * will do a force change. 540 * will do a force change.
529 */ 541 */
530 if (ctx->to_state == STATE_TX_ON) { 542 if (ctx->to_state == STATE_TX_ON ||
531 u8 state = STATE_TX_ON; 543 ctx->to_state == STATE_TRX_OFF) {
544 u8 state = ctx->to_state;
532 545
533 if (lp->tx_retry >= AT86RF2XX_MAX_TX_RETRIES) 546 if (lp->tx_retry >= AT86RF2XX_MAX_TX_RETRIES)
534 state = STATE_FORCE_TX_ON; 547 state = at86rf230_state_to_force(state);
535 lp->tx_retry++; 548 lp->tx_retry++;
536 549
537 at86rf230_async_state_change(lp, ctx, state, 550 at86rf230_async_state_change(lp, ctx, state,
@@ -599,6 +612,11 @@ at86rf230_async_state_delay(void *context)
599 goto change; 612 goto change;
600 case STATE_TX_ON: 613 case STATE_TX_ON:
601 tim = ktime_set(0, c->t_off_to_tx_on * NSEC_PER_USEC); 614 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;
602 goto change; 620 goto change;
603 default: 621 default:
604 break; 622 break;
@@ -606,10 +624,11 @@ at86rf230_async_state_delay(void *context)
606 break; 624 break;
607 case STATE_BUSY_RX_AACK: 625 case STATE_BUSY_RX_AACK:
608 switch (ctx->to_state) { 626 switch (ctx->to_state) {
627 case STATE_TRX_OFF:
609 case STATE_TX_ON: 628 case STATE_TX_ON:
610 /* Wait for worst case receiving time if we 629 /* Wait for worst case receiving time if we
611 * didn't make a force change from BUSY_RX_AACK 630 * didn't make a force change from BUSY_RX_AACK
612 * to TX_ON. 631 * to TX_ON or TRX_OFF.
613 */ 632 */
614 if (!force) { 633 if (!force) {
615 tim = ktime_set(0, (c->t_frame + c->t_p_ack) * 634 tim = ktime_set(0, (c->t_frame + c->t_p_ack) *
@@ -969,25 +988,45 @@ at86rf230_xmit_tx_on(void *context)
969 at86rf230_write_frame, false); 988 at86rf230_write_frame, false);
970} 989}
971 990
972static int 991static void
973at86rf230_xmit(struct ieee802154_hw *hw, struct sk_buff *skb) 992at86rf230_xmit_start(void *context)
974{ 993{
975 struct at86rf230_local *lp = hw->priv; 994 struct at86rf230_state_change *ctx = context;
976 struct at86rf230_state_change *ctx = &lp->tx; 995 struct at86rf230_local *lp = ctx->lp;
977
978 void (*tx_complete)(void *context) = at86rf230_write_frame;
979
980 lp->tx_skb = skb;
981 996
982 /* In ARET mode we need to go into STATE_TX_ARET_ON after we 997 /* In ARET mode we need to go into STATE_TX_ARET_ON after we
983 * are in STATE_TX_ON. The pfad differs here, so we change 998 * are in STATE_TX_ON. The pfad differs here, so we change
984 * the complete handler. 999 * the complete handler.
985 */ 1000 */
986 if (lp->tx_aret) 1001 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
1009static int
1010at86rf230_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;
988 1014
1015 lp->tx_skb = skb;
989 lp->tx_retry = 0; 1016 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);
991 1030
992 return 0; 1031 return 0;
993} 1032}
@@ -1003,6 +1042,9 @@ at86rf230_ed(struct ieee802154_hw *hw, u8 *level)
1003static int 1042static int
1004at86rf230_start(struct ieee802154_hw *hw) 1043at86rf230_start(struct ieee802154_hw *hw)
1005{ 1044{
1045 struct at86rf230_local *lp = hw->priv;
1046
1047 lp->cal_timeout = jiffies + AT86RF2XX_CAL_LOOP_TIMEOUT;
1006 return at86rf230_sync_state_change(hw->priv, STATE_RX_AACK_ON); 1048 return at86rf230_sync_state_change(hw->priv, STATE_RX_AACK_ON);
1007} 1049}
1008 1050
@@ -1083,6 +1125,8 @@ at86rf230_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
1083 /* Wait for PLL */ 1125 /* Wait for PLL */
1084 usleep_range(lp->data->t_channel_switch, 1126 usleep_range(lp->data->t_channel_switch,
1085 lp->data->t_channel_switch + 10); 1127 lp->data->t_channel_switch + 10);
1128
1129 lp->cal_timeout = jiffies + AT86RF2XX_CAL_LOOP_TIMEOUT;
1086 return rc; 1130 return rc;
1087} 1131}
1088 1132