The mrf24j40 requires a high on the RESET pin, otherwise it will reset itself over and over. With this patch the driver will ensure that a GPIO (if connected) will be set to high during device initialization. Details: - set reset to high on driver probe - make pin configurable via device tree (overlay) - similar to the at86rf233 driver - update devicetree documentation Signed-off-by: smlng <s@xxxxxxxx> --- .../bindings/net/ieee802154/mrf24j40.txt | 4 ++ drivers/net/ieee802154/mrf24j40.c | 59 ++++++++++++++++++++-- include/linux/spi/mrf24j40.h | 9 ++++ 3 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 include/linux/spi/mrf24j40.h diff --git a/Documentation/devicetree/bindings/net/ieee802154/mrf24j40.txt b/Documentation/devicetree/bindings/net/ieee802154/mrf24j40.txt index a4ed2efb5b73..2fabba041e48 100644 --- a/Documentation/devicetree/bindings/net/ieee802154/mrf24j40.txt +++ b/Documentation/devicetree/bindings/net/ieee802154/mrf24j40.txt @@ -9,6 +9,10 @@ Required properties: - reg: the chipselect index - interrupts: the interrupt generated by the device. +Optional properties: + - reset-gpio: GPIO spec for the rstn pin + - wake-gpio: GPIO spec for the wake pin + Example: mrf24j40ma@0 { diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index 7b131f8e4093..275b54d6bad3 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -16,9 +16,11 @@ */ #include <linux/spi/spi.h> +#include <linux/spi/mrf24j40.h> #include <linux/interrupt.h> #include <linux/module.h> #include <linux/regmap.h> +#include <linux/of_gpio.h> #include <linux/ieee802154.h> #include <linux/irq.h> #include <net/cfg802154.h> @@ -1276,16 +1278,67 @@ static void mrf24j40_phy_setup(struct mrf24j40 *devrec) } } +static int +mrf24j40_get_pdata(struct spi_device *spi, int *rstn, int *wake) +{ + struct mrf24j40_platform_data *pdata = spi->dev.platform_data; + + if (!IS_ENABLED(CONFIG_OF) || !spi->dev.of_node) { + if (!pdata) + return -ENOENT; + + *rstn = pdata->rstn; + *wake = pdata->wake; + return 0; + } + + *rstn = of_get_named_gpio(spi->dev.of_node, "reset-gpio", 0); + *wake = of_get_named_gpio(spi->dev.of_node, "wake-gpio", 0); + return 0; +} + static int mrf24j40_probe(struct spi_device *spi) { int ret = -ENOMEM, irq_type; + int rc, rstn, wake; struct ieee802154_hw *hw; struct mrf24j40 *devrec; - dev_info(&spi->dev, "probe(). IRQ: %d\n", spi->irq); + if (!spi->irq) { + dev_err(&spi->dev, "no IRQ specified\n"); + return -EINVAL; + } - /* Register with the 802154 subsystem */ + rc = mrf24j40_get_pdata(spi, &rstn, &wake); + if (rc < 0) { + dev_err(&spi->dev, "failed to parse platform_data: %d\n", rc); + return rc; + } + + if (gpio_is_valid(rstn)) { + rc = devm_gpio_request_one(&spi->dev, rstn, + GPIOF_OUT_INIT_HIGH, "rstn"); + if (rc) + return rc; + } + if (gpio_is_valid(wake)) { + rc = devm_gpio_request_one(&spi->dev, wake, + GPIOF_OUT_INIT_LOW, "wake"); + if (rc) + return rc; + } + + /* Reset */ + if (gpio_is_valid(rstn)) { + udelay(1); + gpio_set_value(rstn, 0); + udelay(1); + gpio_set_value(rstn, 1); + usleep_range(120, 240); + } + + /* Register with the 802154 subsystem */ hw = ieee802154_alloc_hw(sizeof(*devrec), &mrf24j40_ops); if (!hw) goto err_ret; @@ -1350,7 +1403,7 @@ static int mrf24j40_probe(struct spi_device *spi) goto err_register_device; } - dev_dbg(printdev(devrec), "registered mrf24j40\n"); + dev_info(printdev(devrec), "registered mrf24j40\n"); ret = ieee802154_register_hw(devrec->hw); if (ret) goto err_register_device; diff --git a/include/linux/spi/mrf24j40.h b/include/linux/spi/mrf24j40.h new file mode 100644 index 000000000000..60810194cae9 --- /dev/null +++ b/include/linux/spi/mrf24j40.h @@ -0,0 +1,9 @@ +#ifndef _SPI_MRF24J40_H +#define _SPI_MRF24J40_H + +struct mrf24j40_platform_data { + int rstn; + int wake; +}; + +#endif /* _SPI_MRF24J40_H */ -- 2.10.2 -- To unsubscribe from this list: send the line "unsubscribe linux-wpan" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html