All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH bluetooth-next 0/3] at86rf230: state delay over hrtimer and calibration
@ 2015-03-09 12:56 Alexander Aring
  2015-03-09 12:56 ` [PATCH bluetooth-next 1/3] at86rf230: replace state change sleeps with hrtimer Alexander Aring
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Alexander Aring @ 2015-03-09 12:56 UTC (permalink / raw)
  To: linux-wpan; +Cc: kernel, Alexander Aring

Hi,

this patch series contains for doing the state delay via hrtimer and introduce
the transceiver calibration by doing a TRX_OFF -> TX_ON state before transmit
and transceiver leaves 5 minutes in PLL state.

- Alex

Alexander Aring (3):
  at86rf230: replace state change sleeps with hrtimer
  at86rf230: add support for calibration timeout
  at86rf230: fix volatile regmap registers

 drivers/net/ieee802154/at86rf230.c | 113 +++++++++++++++++++++++++++++--------
 1 file changed, 89 insertions(+), 24 deletions(-)

-- 
2.3.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH bluetooth-next 1/3] at86rf230: replace state change sleeps with hrtimer
  2015-03-09 12:56 [PATCH bluetooth-next 0/3] at86rf230: state delay over hrtimer and calibration Alexander Aring
@ 2015-03-09 12:56 ` Alexander Aring
  2015-03-09 12:56 ` [PATCH bluetooth-next 2/3] at86rf230: add support for calibration timeout Alexander Aring
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Alexander Aring @ 2015-03-09 12:56 UTC (permalink / raw)
  To: linux-wpan; +Cc: kernel, Alexander Aring

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>
---
 drivers/net/ieee802154/at86rf230.c | 39 ++++++++++++++++++++++++++++----------
 1 file changed, 29 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index 088fa68..cdcd152 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -19,6 +19,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/hrtimer.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/gpio.h>
@@ -64,6 +65,7 @@ struct at86rf230_state_change {
 	struct at86rf230_local *lp;
 	int irq;
 
+	struct hrtimer timer;
 	struct spi_message msg;
 	struct spi_transfer trx;
 	u8 buf[AT86RF2XX_MAX_BUF];
@@ -548,6 +550,19 @@ done:
 		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. */
 static void
 at86rf230_async_state_delay(void *context)
@@ -556,6 +571,7 @@ at86rf230_async_state_delay(void *context)
 	struct at86rf230_local *lp = ctx->lp;
 	struct at86rf2xx_chip_data *c = lp->data;
 	bool force = false;
+	ktime_t tim;
 
 	/* The force state changes are will show as normal states in 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:
 		switch (ctx->to_state) {
 		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;
 		case STATE_TX_ON:
-			usleep_range(c->t_off_to_tx_on,
-				     c->t_off_to_tx_on + 10);
+			tim = ktime_set(0, c->t_off_to_tx_on * NSEC_PER_USEC);
 			goto change;
 		default:
 			break;
@@ -597,8 +612,8 @@ at86rf230_async_state_delay(void *context)
 			 * to TX_ON.
 			 */
 			if (!force) {
-				usleep_range(c->t_frame + c->t_p_ack,
-					     c->t_frame + c->t_p_ack + 1000);
+				tim = ktime_set(0, (c->t_frame + c->t_p_ack) *
+						   NSEC_PER_USEC);
 				goto change;
 			}
 			break;
@@ -610,7 +625,7 @@ at86rf230_async_state_delay(void *context)
 	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);
+			tim = ktime_set(0, c->t_reset_to_off * NSEC_PER_USEC);
 			goto change;
 		default:
 			break;
@@ -621,12 +636,10 @@ at86rf230_async_state_delay(void *context)
 	}
 
 	/* Default delay is 1us in the most cases */
-	udelay(1);
+	tim = ktime_set(0, NSEC_PER_USEC);
 
 change:
-	at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx,
-				 at86rf230_async_state_assert,
-				 ctx->irq_enable);
+	hrtimer_start(&ctx->timer, tim, HRTIMER_MODE_REL);
 }
 
 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.rx_buf = lp->state.buf;
 	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.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.rx_buf = lp->irq.buf;
 	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.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.rx_buf = lp->tx.buf;
 	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)
-- 
2.3.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH bluetooth-next 2/3] at86rf230: add support for calibration timeout
  2015-03-09 12:56 [PATCH bluetooth-next 0/3] at86rf230: state delay over hrtimer and calibration Alexander Aring
  2015-03-09 12:56 ` [PATCH bluetooth-next 1/3] at86rf230: replace state change sleeps with hrtimer Alexander Aring
@ 2015-03-09 12:56 ` Alexander Aring
  2015-03-09 12:56 ` [PATCH bluetooth-next 3/3] at86rf230: fix volatile regmap registers Alexander Aring
  2015-03-14 16:13 ` [PATCH bluetooth-next 0/3] at86rf230: state delay over hrtimer and calibration Marcel Holtmann
  3 siblings, 0 replies; 5+ messages in thread
From: Alexander Aring @ 2015-03-09 12:56 UTC (permalink / raw)
  To: linux-wpan
  Cc: kernel, Alexander Aring, Phoebe Buckheister, Werner Almesberger

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>
---
 drivers/net/ieee802154/at86rf230.c | 72 ++++++++++++++++++++++++++++++--------
 1 file changed, 58 insertions(+), 14 deletions(-)

diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index cdcd152..3b81c62 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -20,6 +20,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/hrtimer.h>
+#include <linux/jiffies.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/gpio.h>
@@ -60,6 +61,8 @@ struct at86rf2xx_chip_data {
  * We assume the max_frame_retries (7) value of 802.15.4 here.
  */
 #define AT86RF2XX_MAX_TX_RETRIES	7
+/* We use the recommended 5 minutes timeout to recalibrate */
+#define AT86RF2XX_CAL_LOOP_TIMEOUT	(5 * 60 * HZ)
 
 struct at86rf230_state_change {
 	struct at86rf230_local *lp;
@@ -90,6 +93,7 @@ struct at86rf230_local {
 	struct at86rf230_state_change irq;
 
 	bool tx_aret;
+	unsigned long cal_timeout;
 	s8 max_frame_retries;
 	bool is_tx;
 	/* spinlock for is_tx protection */
@@ -491,6 +495,14 @@ at86rf230_async_read_reg(struct at86rf230_local *lp, const u8 reg,
 	}
 }
 
+static inline u8 at86rf230_state_to_force(u8 state)
+{
+	if (state == STATE_TX_ON)
+		return STATE_FORCE_TX_ON;
+	else
+		return STATE_FORCE_TRX_OFF;
+}
+
 static void
 at86rf230_async_state_assert(void *context)
 {
@@ -527,11 +539,12 @@ at86rf230_async_state_assert(void *context)
 			 * higher or equal than AT86RF2XX_MAX_TX_RETRIES we
 			 * will do a force change.
 			 */
-			if (ctx->to_state == STATE_TX_ON) {
-				u8 state = STATE_TX_ON;
+			if (ctx->to_state == STATE_TX_ON ||
+			    ctx->to_state == STATE_TRX_OFF) {
+				u8 state = ctx->to_state;
 
 				if (lp->tx_retry >= AT86RF2XX_MAX_TX_RETRIES)
-					state = STATE_FORCE_TX_ON;
+					state = at86rf230_state_to_force(state);
 				lp->tx_retry++;
 
 				at86rf230_async_state_change(lp, ctx, state,
@@ -599,6 +612,11 @@ at86rf230_async_state_delay(void *context)
 			goto change;
 		case STATE_TX_ON:
 			tim = ktime_set(0, c->t_off_to_tx_on * NSEC_PER_USEC);
+			/* state change from TRX_OFF to TX_ON to do a
+			 * calibration, we need to reset the timeout for the
+			 * next one.
+			 */
+			lp->cal_timeout = jiffies + AT86RF2XX_CAL_LOOP_TIMEOUT;
 			goto change;
 		default:
 			break;
@@ -606,10 +624,11 @@ at86rf230_async_state_delay(void *context)
 		break;
 	case STATE_BUSY_RX_AACK:
 		switch (ctx->to_state) {
+		case STATE_TRX_OFF:
 		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.
+			 * to TX_ON or TRX_OFF.
 			 */
 			if (!force) {
 				tim = ktime_set(0, (c->t_frame + c->t_p_ack) *
@@ -969,25 +988,45 @@ at86rf230_xmit_tx_on(void *context)
 				     at86rf230_write_frame, false);
 }
 
-static int
-at86rf230_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
+static void
+at86rf230_xmit_start(void *context)
 {
-	struct at86rf230_local *lp = hw->priv;
-	struct at86rf230_state_change *ctx = &lp->tx;
-
-	void (*tx_complete)(void *context) = at86rf230_write_frame;
-
-	lp->tx_skb = skb;
+	struct at86rf230_state_change *ctx = context;
+	struct at86rf230_local *lp = ctx->lp;
 
 	/* In ARET mode we need to go into STATE_TX_ARET_ON after we
 	 * are in STATE_TX_ON. The pfad differs here, so we change
 	 * the complete handler.
 	 */
 	if (lp->tx_aret)
-		tx_complete = at86rf230_xmit_tx_on;
+		at86rf230_async_state_change(lp, ctx, STATE_TX_ON,
+					     at86rf230_xmit_tx_on, false);
+	else
+		at86rf230_async_state_change(lp, ctx, STATE_TX_ON,
+					     at86rf230_write_frame, false);
+}
+
+static int
+at86rf230_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
+{
+	struct at86rf230_local *lp = hw->priv;
+	struct at86rf230_state_change *ctx = &lp->tx;
 
+	lp->tx_skb = skb;
 	lp->tx_retry = 0;
-	at86rf230_async_state_change(lp, ctx, STATE_TX_ON, tx_complete, false);
+
+	/* After 5 minutes in PLL and the same frequency we run again the
+	 * calibration loops which is recommended by at86rf2xx datasheets.
+	 *
+	 * The calibration is initiate by a state change from TRX_OFF
+	 * to TX_ON, the lp->cal_timeout should be reinit by state_delay
+	 * function then to start in the next 5 minutes.
+	 */
+	if (time_is_before_jiffies(lp->cal_timeout))
+		at86rf230_async_state_change(lp, ctx, STATE_TRX_OFF,
+					     at86rf230_xmit_start, false);
+	else
+		at86rf230_xmit_start(ctx);
 
 	return 0;
 }
@@ -1003,6 +1042,9 @@ at86rf230_ed(struct ieee802154_hw *hw, u8 *level)
 static int
 at86rf230_start(struct ieee802154_hw *hw)
 {
+	struct at86rf230_local *lp = hw->priv;
+
+	lp->cal_timeout = jiffies + AT86RF2XX_CAL_LOOP_TIMEOUT;
 	return at86rf230_sync_state_change(hw->priv, STATE_RX_AACK_ON);
 }
 
@@ -1083,6 +1125,8 @@ at86rf230_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
 	/* Wait for PLL */
 	usleep_range(lp->data->t_channel_switch,
 		     lp->data->t_channel_switch + 10);
+
+	lp->cal_timeout = jiffies + AT86RF2XX_CAL_LOOP_TIMEOUT;
 	return rc;
 }
 
-- 
2.3.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH bluetooth-next 3/3] at86rf230: fix volatile regmap registers
  2015-03-09 12:56 [PATCH bluetooth-next 0/3] at86rf230: state delay over hrtimer and calibration Alexander Aring
  2015-03-09 12:56 ` [PATCH bluetooth-next 1/3] at86rf230: replace state change sleeps with hrtimer Alexander Aring
  2015-03-09 12:56 ` [PATCH bluetooth-next 2/3] at86rf230: add support for calibration timeout Alexander Aring
@ 2015-03-09 12:56 ` Alexander Aring
  2015-03-14 16:13 ` [PATCH bluetooth-next 0/3] at86rf230: state delay over hrtimer and calibration Marcel Holtmann
  3 siblings, 0 replies; 5+ messages in thread
From: Alexander Aring @ 2015-03-09 12:56 UTC (permalink / raw)
  To: linux-wpan; +Cc: kernel, Alexander Aring

These registers are also changed by transceiver and should be volatile
for right accessing via regmap debugfs.

Signed-off-by: Alexander Aring <alex.aring@gmail.com>
---
 drivers/net/ieee802154/at86rf230.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index 3b81c62..51b88fd 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -421,6 +421,8 @@ at86rf230_reg_volatile(struct device *dev, unsigned int reg)
 	case RG_PHY_ED_LEVEL:
 	case RG_IRQ_STATUS:
 	case RG_VREG_CTRL:
+	case RG_PLL_CF:
+	case RG_PLL_DCU:
 		return true;
 	default:
 		return false;
-- 
2.3.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH bluetooth-next 0/3] at86rf230: state delay over hrtimer and calibration
  2015-03-09 12:56 [PATCH bluetooth-next 0/3] at86rf230: state delay over hrtimer and calibration Alexander Aring
                   ` (2 preceding siblings ...)
  2015-03-09 12:56 ` [PATCH bluetooth-next 3/3] at86rf230: fix volatile regmap registers Alexander Aring
@ 2015-03-14 16:13 ` Marcel Holtmann
  3 siblings, 0 replies; 5+ messages in thread
From: Marcel Holtmann @ 2015-03-14 16:13 UTC (permalink / raw)
  To: Alexander Aring; +Cc: linux-wpan, kernel

Hi Alex,

> this patch series contains for doing the state delay via hrtimer and introduce
> the transceiver calibration by doing a TRX_OFF -> TX_ON state before transmit
> and transceiver leaves 5 minutes in PLL state.
> 
> - Alex
> 
> Alexander Aring (3):
>  at86rf230: replace state change sleeps with hrtimer
>  at86rf230: add support for calibration timeout
>  at86rf230: fix volatile regmap registers
> 
> drivers/net/ieee802154/at86rf230.c | 113 +++++++++++++++++++++++++++++--------
> 1 file changed, 89 insertions(+), 24 deletions(-)

all 3 patches have been applied to bluetooth-next tree.

Regards

Marcel


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2015-03-14 16:13 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-09 12:56 [PATCH bluetooth-next 0/3] at86rf230: state delay over hrtimer and calibration Alexander Aring
2015-03-09 12:56 ` [PATCH bluetooth-next 1/3] at86rf230: replace state change sleeps with hrtimer Alexander Aring
2015-03-09 12:56 ` [PATCH bluetooth-next 2/3] at86rf230: add support for calibration timeout Alexander Aring
2015-03-09 12:56 ` [PATCH bluetooth-next 3/3] at86rf230: fix volatile regmap registers Alexander Aring
2015-03-14 16:13 ` [PATCH bluetooth-next 0/3] at86rf230: state delay over hrtimer and calibration Marcel Holtmann

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.