[RFC 1/3] at86rf230: add support for platform-specific reset function

Werner Almesberger werner at almesberger.net
Mon Apr 29 20:15:22 EDT 2013


Some platforms may not connect the /RST line directly to a GPIO, or they
may not connect it at all and instead use power cycling to reset the
transceiver.

An example of the latter type is the ATBEN board on the Ben NanoNote.

This patch adds support for a platform-specific reset function to the
AT86RF230/1 driver. If the platform provides a reset function, "rstn"
is ignored and no GPIO is allocated for it.
---
 drivers/net/ieee802154/at86rf230.c |   45 +++++++++++++++++++++++++------------
 include/linux/spi/at86rf230.h      |    9 ++++++-
 2 files changed, 39 insertions(+), 15 deletions(-)

diff --git a/include/linux/spi/at86rf230.h b/include/linux/spi/at86rf230.h
index aa327a8..9fd1b29 100644
--- a/include/linux/spi/at86rf230.h
+++ b/include/linux/spi/at86rf230.h
@@ -23,7 +23,7 @@
 #define AT86RF230_H
 
 struct at86rf230_platform_data {
-	int rstn;
+	int rstn;	/* only used if "reset" (below) is NULL */
 	int slp_tr;
 	int dig2;
 
@@ -40,6 +40,13 @@ struct at86rf230_platform_data {
 	 * of the device to high active (the default value).
 	 */
 	int irq_type;
+
+	/* Platform-specific transceiver reset function, e.g., to use
+	 * power cycling instead of the reset line. If "reset" is NULL,
+	 * the driver resets the transceiver through the "rstn" GPIO.
+	 */
+	void (*reset)(void *reset_data);
+	void *reset_data;
 };
 
 #endif
diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index 6f10b49..7fa32f2 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -834,6 +834,21 @@ static void at86rf230_fill_data(struct spi_device *spi)
 	lp->dig2 = pdata->dig2;
 }
 
+static void at86rf230_reset(struct at86rf230_local *lp)
+{
+	struct at86rf230_platform_data *pdata = lp->spi->dev.platform_data;
+
+	if (pdata->reset) {
+		pdata->reset(pdata->reset_data);
+	} else {
+		msleep(1);
+		gpio_set_value(lp->rstn, 0);
+		msleep(1);
+		gpio_set_value(lp->rstn, 1);
+	}
+	msleep(1);
+}
+
 static int at86rf230_probe(struct spi_device *spi)
 {
 	struct at86rf230_platform_data *pdata;
@@ -888,9 +903,11 @@ static int at86rf230_probe(struct spi_device *spi)
 
 	at86rf230_fill_data(spi);
 
-	rc = gpio_request(lp->rstn, "rstn");
-	if (rc)
-		goto err_rstn;
+	if (!pdata->reset) {
+		rc = gpio_request(lp->rstn, "rstn");
+		if (rc)
+			goto err_rstn;
+	}
 
 	if (gpio_is_valid(lp->slp_tr)) {
 		rc = gpio_request(lp->slp_tr, "slp_tr");
@@ -898,9 +915,11 @@ static int at86rf230_probe(struct spi_device *spi)
 			goto err_slp_tr;
 	}
 
-	rc = gpio_direction_output(lp->rstn, 1);
-	if (rc)
-		goto err_gpio_dir;
+	if (!pdata->reset) {
+		rc = gpio_direction_output(lp->rstn, 1);
+		if (rc)
+			goto err_gpio_dir;
+	}
 
 	if (gpio_is_valid(lp->slp_tr)) {
 		rc = gpio_direction_output(lp->slp_tr, 0);
@@ -908,12 +927,7 @@ static int at86rf230_probe(struct spi_device *spi)
 			goto err_gpio_dir;
 	}
 
-	/* Reset */
-	msleep(1);
-	gpio_set_value(lp->rstn, 0);
-	msleep(1);
-	gpio_set_value(lp->rstn, 1);
-	msleep(1);
+	at86rf230_reset(lp);
 
 	rc = at86rf230_read_subreg(lp, SR_MAN_ID_0, &man_id_0);
 	if (rc)
@@ -985,7 +999,8 @@ err_gpio_dir:
 	if (gpio_is_valid(lp->slp_tr))
 		gpio_free(lp->slp_tr);
 err_slp_tr:
-	gpio_free(lp->rstn);
+	if (!pdata->reset)
+		gpio_free(lp->rstn);
 err_rstn:
 	spi_set_drvdata(spi, NULL);
 	mutex_destroy(&lp->bmux);
@@ -995,6 +1010,7 @@ err_rstn:
 
 static int at86rf230_remove(struct spi_device *spi)
 {
+	struct at86rf230_platform_data *pdata = spi->dev.platform_data;
 	struct at86rf230_local *lp = spi_get_drvdata(spi);
 
 	ieee802154_unregister_device(lp->dev);
@@ -1004,7 +1020,8 @@ static int at86rf230_remove(struct spi_device *spi)
 
 	if (gpio_is_valid(lp->slp_tr))
 		gpio_free(lp->slp_tr);
-	gpio_free(lp->rstn);
+	if (!pdata->reset)
+		gpio_free(lp->rstn);
 
 	spi_set_drvdata(spi, NULL);
 	mutex_destroy(&lp->bmux);



More information about the discussion mailing list


interactive