]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: cw1200: Convert to GPIO descriptors
authorLinus Walleij <linus.walleij@linaro.org>
Wed, 31 Jan 2024 22:37:25 +0000 (23:37 +0100)
committerKalle Valo <kvalo@kernel.org>
Mon, 5 Feb 2024 18:17:10 +0000 (20:17 +0200)
The CW1200 uses two GPIOs to control the powerup and reset
pins, get these from GPIO descriptors instead of being passed
as platform data from boardfiles.

The RESET line will need to be marked as active low as we will
let gpiolib handle the polarity inversion.

The SDIO case is a bit special since the "card" need to be
powered up before it gets detected on the SDIO bus and
properly probed. Fix this by using board-specific GPIOs
assigned to device "NULL".

There are currently no in-tree users.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://msgid.link/20240131-descriptors-wireless-v1-6-e1c7c5d68746@linaro.org
drivers/net/wireless/st/cw1200/cw1200_sdio.c
drivers/net/wireless/st/cw1200/cw1200_spi.c
include/linux/platform_data/net-cw1200.h

index 4c30b5772ce0fea4efbab998f8dcdb2798c12aa9..00c4731d8f8efd86ae4ef85d948d324f13f99c2c 100644 (file)
@@ -8,7 +8,7 @@
 
 #include <linux/module.h>
 #include <linux/interrupt.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/delay.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/sdio_func.h>
@@ -178,12 +178,15 @@ static int cw1200_sdio_irq_unsubscribe(struct hwbus_priv *self)
        return ret;
 }
 
+/* Like the rest of the driver, this only supports one device per system */
+static struct gpio_desc *cw1200_reset;
+static struct gpio_desc *cw1200_powerup;
+
 static int cw1200_sdio_off(const struct cw1200_platform_data_sdio *pdata)
 {
-       if (pdata->reset) {
-               gpio_set_value(pdata->reset, 0);
+       if (cw1200_reset) {
+               gpiod_set_value(cw1200_reset, 0);
                msleep(30); /* Min is 2 * CLK32K cycles */
-               gpio_free(pdata->reset);
        }
 
        if (pdata->power_ctrl)
@@ -196,16 +199,21 @@ static int cw1200_sdio_off(const struct cw1200_platform_data_sdio *pdata)
 
 static int cw1200_sdio_on(const struct cw1200_platform_data_sdio *pdata)
 {
-       /* Ensure I/Os are pulled low */
-       if (pdata->reset) {
-               gpio_request(pdata->reset, "cw1200_wlan_reset");
-               gpio_direction_output(pdata->reset, 0);
+       /* Ensure I/Os are pulled low (reset is active low) */
+       cw1200_reset = devm_gpiod_get_optional(NULL, "reset", GPIOD_OUT_HIGH);
+       if (IS_ERR(cw1200_reset)) {
+               pr_err("could not get CW1200 SDIO reset GPIO\n");
+               return PTR_ERR(cw1200_reset);
        }
-       if (pdata->powerup) {
-               gpio_request(pdata->powerup, "cw1200_wlan_powerup");
-               gpio_direction_output(pdata->powerup, 0);
+       gpiod_set_consumer_name(cw1200_reset, "cw1200_wlan_reset");
+       cw1200_powerup = devm_gpiod_get_optional(NULL, "powerup", GPIOD_OUT_LOW);
+       if (IS_ERR(cw1200_powerup)) {
+               pr_err("could not get CW1200 SDIO powerup GPIO\n");
+               return PTR_ERR(cw1200_powerup);
        }
-       if (pdata->reset || pdata->powerup)
+       gpiod_set_consumer_name(cw1200_powerup, "cw1200_wlan_powerup");
+
+       if (cw1200_reset || cw1200_powerup)
                msleep(10); /* Settle time? */
 
        /* Enable 3v3 and 1v8 to hardware */
@@ -226,13 +234,13 @@ static int cw1200_sdio_on(const struct cw1200_platform_data_sdio *pdata)
        }
 
        /* Enable POWERUP signal */
-       if (pdata->powerup) {
-               gpio_set_value(pdata->powerup, 1);
+       if (cw1200_powerup) {
+               gpiod_set_value(cw1200_powerup, 1);
                msleep(250); /* or more..? */
        }
-       /* Enable RSTn signal */
-       if (pdata->reset) {
-               gpio_set_value(pdata->reset, 1);
+       /* Deassert RSTn signal, note active low */
+       if (cw1200_reset) {
+               gpiod_set_value(cw1200_reset, 0);
                msleep(50); /* Or more..? */
        }
        return 0;
index b27b57fc25bc0e7ad1453fab4d89d4c572c3f260..fb3aafcafe185eab4b3e669d834a7b56d8d596ec 100644 (file)
@@ -11,7 +11,7 @@
  */
 
 #include <linux/module.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
@@ -38,6 +38,8 @@ struct hwbus_priv {
        const struct cw1200_platform_data_spi *pdata;
        spinlock_t              lock; /* Serialize all bus operations */
        wait_queue_head_t       wq;
+       struct gpio_desc        *reset;
+       struct gpio_desc        *powerup;
        int claimed;
 };
 
@@ -269,12 +271,12 @@ static void cw1200_spi_irq_unsubscribe(struct hwbus_priv *self)
        free_irq(self->func->irq, self);
 }
 
-static int cw1200_spi_off(const struct cw1200_platform_data_spi *pdata)
+static int cw1200_spi_off(struct hwbus_priv *self, const struct cw1200_platform_data_spi *pdata)
 {
-       if (pdata->reset) {
-               gpio_set_value(pdata->reset, 0);
+       if (self->reset) {
+               /* Assert RESET, note active low */
+               gpiod_set_value(self->reset, 1);
                msleep(30); /* Min is 2 * CLK32K cycles */
-               gpio_free(pdata->reset);
        }
 
        if (pdata->power_ctrl)
@@ -285,18 +287,12 @@ static int cw1200_spi_off(const struct cw1200_platform_data_spi *pdata)
        return 0;
 }
 
-static int cw1200_spi_on(const struct cw1200_platform_data_spi *pdata)
+static int cw1200_spi_on(struct hwbus_priv *self, const struct cw1200_platform_data_spi *pdata)
 {
        /* Ensure I/Os are pulled low */
-       if (pdata->reset) {
-               gpio_request(pdata->reset, "cw1200_wlan_reset");
-               gpio_direction_output(pdata->reset, 0);
-       }
-       if (pdata->powerup) {
-               gpio_request(pdata->powerup, "cw1200_wlan_powerup");
-               gpio_direction_output(pdata->powerup, 0);
-       }
-       if (pdata->reset || pdata->powerup)
+       gpiod_direction_output(self->reset, 1); /* Active low */
+       gpiod_direction_output(self->powerup, 0);
+       if (self->reset || self->powerup)
                msleep(10); /* Settle time? */
 
        /* Enable 3v3 and 1v8 to hardware */
@@ -317,13 +313,13 @@ static int cw1200_spi_on(const struct cw1200_platform_data_spi *pdata)
        }
 
        /* Enable POWERUP signal */
-       if (pdata->powerup) {
-               gpio_set_value(pdata->powerup, 1);
+       if (self->powerup) {
+               gpiod_set_value(self->powerup, 1);
                msleep(250); /* or more..? */
        }
-       /* Enable RSTn signal */
-       if (pdata->reset) {
-               gpio_set_value(pdata->reset, 1);
+       /* Assert RSTn signal, note active low */
+       if (self->reset) {
+               gpiod_set_value(self->reset, 0);
                msleep(50); /* Or more..? */
        }
        return 0;
@@ -375,20 +371,33 @@ static int cw1200_spi_probe(struct spi_device *func)
                spi_get_chipselect(func, 0), func->mode, func->bits_per_word,
                func->max_speed_hz);
 
-       if (cw1200_spi_on(plat_data)) {
+       self = devm_kzalloc(&func->dev, sizeof(*self), GFP_KERNEL);
+       if (!self) {
+               pr_err("Can't allocate SPI hwbus_priv.");
+               return -ENOMEM;
+       }
+
+       /* Request reset asserted */
+       self->reset = devm_gpiod_get_optional(&func->dev, "reset", GPIOD_OUT_HIGH);
+       if (IS_ERR(self->reset))
+               return dev_err_probe(&func->dev, PTR_ERR(self->reset),
+                                    "could not get reset GPIO\n");
+       gpiod_set_consumer_name(self->reset, "cw1200_wlan_reset");
+
+       self->powerup = devm_gpiod_get_optional(&func->dev, "powerup", GPIOD_OUT_LOW);
+       if (IS_ERR(self->powerup))
+               return dev_err_probe(&func->dev, PTR_ERR(self->powerup),
+                                    "could not get powerup GPIO\n");
+       gpiod_set_consumer_name(self->reset, "cw1200_wlan_powerup");
+
+       if (cw1200_spi_on(self, plat_data)) {
                pr_err("spi_on() failed!\n");
-               return -1;
+               return -ENODEV;
        }
 
        if (spi_setup(func)) {
                pr_err("spi_setup() failed!\n");
-               return -1;
-       }
-
-       self = devm_kzalloc(&func->dev, sizeof(*self), GFP_KERNEL);
-       if (!self) {
-               pr_err("Can't allocate SPI hwbus_priv.");
-               return -ENOMEM;
+               return -ENODEV;
        }
 
        self->pdata = plat_data;
@@ -410,7 +419,7 @@ static int cw1200_spi_probe(struct spi_device *func)
 
        if (status) {
                cw1200_spi_irq_unsubscribe(self);
-               cw1200_spi_off(plat_data);
+               cw1200_spi_off(self, plat_data);
        }
 
        return status;
@@ -428,7 +437,7 @@ static void cw1200_spi_disconnect(struct spi_device *func)
                        self->core = NULL;
                }
        }
-       cw1200_spi_off(dev_get_platdata(&func->dev));
+       cw1200_spi_off(self, dev_get_platdata(&func->dev));
 }
 
 static int __maybe_unused cw1200_spi_suspend(struct device *dev)
index c510734405bbc3b99dba50249ad0f9c87001c2cf..89d0ec6f7d462b95f8c75b68496531e661666e32 100644 (file)
@@ -14,8 +14,6 @@ struct cw1200_platform_data_spi {
 
        /* All others are optional */
        bool have_5ghz;
-       int reset;                     /* GPIO to RSTn signal (0 disables) */
-       int powerup;                   /* GPIO to POWERUP signal (0 disables) */
        int (*power_ctrl)(const struct cw1200_platform_data_spi *pdata,
                          bool enable); /* Control 3v3 / 1v8 supply */
        int (*clk_ctrl)(const struct cw1200_platform_data_spi *pdata,
@@ -30,8 +28,6 @@ struct cw1200_platform_data_sdio {
        /* All others are optional */
        bool have_5ghz;
        bool no_nptb;       /* SDIO hardware does not support non-power-of-2-blocksizes */
-       int reset;          /* GPIO to RSTn signal (0 disables) */
-       int powerup;        /* GPIO to POWERUP signal (0 disables) */
        int irq;            /* IRQ line or 0 to use SDIO IRQ */
        int (*power_ctrl)(const struct cw1200_platform_data_sdio *pdata,
                          bool enable); /* Control 3v3 / 1v8 supply */