[ reset{,_data} are now copied from platform_data to at86rf230_local ]

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 |   46 +++++++++++++++++++++++++------------
 include/linux/spi/at86rf230.h      |    9 ++++++-
 2 files changed, 40 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..22fe088 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -38,6 +38,8 @@
 struct at86rf230_local {
        struct spi_device *spi;
        int rstn, slp_tr, dig2;
+       void (*reset)(void *reset_data);
+       void *reset_data;
 
        u8 part;
        u8 vers;
@@ -832,6 +834,21 @@ static void at86rf230_fill_data(struct spi_device *spi)
        lp->rstn = pdata->rstn;
        lp->slp_tr = pdata->slp_tr;
        lp->dig2 = pdata->dig2;
+       lp->reset = pdata->reset;
+       lp->reset_data = pdata->reset_data;
+}
+
+static void at86rf230_reset(struct at86rf230_local *lp)
+{
+       if (lp->reset) {
+               lp->reset(lp->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)
@@ -888,9 +905,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 (!lp->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 +917,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 (!lp->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 +929,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 +1001,8 @@ err_gpio_dir:
        if (gpio_is_valid(lp->slp_tr))
                gpio_free(lp->slp_tr);
 err_slp_tr:
-       gpio_free(lp->rstn);
+       if (!lp->reset)
+               gpio_free(lp->rstn);
 err_rstn:
        spi_set_drvdata(spi, NULL);
        mutex_destroy(&lp->bmux);
@@ -1004,7 +1021,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 (!lp->reset)
+               gpio_free(lp->rstn);
 
        spi_set_drvdata(spi, NULL);
        mutex_destroy(&lp->bmux);

------------------------------------------------------------------------------
Learn Graph Databases - Download FREE O'Reilly Book
"Graph Databases" is the definitive new guide to graph databases and 
their applications. This 200-page book is written by three acclaimed 
leaders in the field. The early access version is available now. 
Download your free book today! http://p.sf.net/sfu/neotech_d2d_may
_______________________________________________
Linux-zigbee-devel mailing list
Linux-zigbee-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-zigbee-devel

Reply via email to