wifi: wilc1000: validate chip id during bus probe
authorDavid Mosberger-Tang <davidm@egauge.net>
Mon, 12 Feb 2024 20:22:30 +0000 (20:22 +0000)
committerKalle Valo <kvalo@kernel.org>
Thu, 15 Feb 2024 11:09:16 +0000 (13:09 +0200)
Previously, the driver created a net device (typically wlan0) as soon
as the module was loaded.  This commit changes the driver to follow
normal Linux convention of creating the net device only when bus
probing detects a supported chip.

Signed-off-by: David Mosberger-Tang <davidm@egauge.net>
Tested-By: Alexis Lothoré <alexis.lothore@bootlin.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://msgid.link/20240212202057.3468714-1-davidm@egauge.net
drivers/net/wireless/microchip/wilc1000/spi.c
drivers/net/wireless/microchip/wilc1000/wlan.c
drivers/net/wireless/microchip/wilc1000/wlan.h

index c92ee4b73a744d31610ce63143acba11330fd83c..3c4451535c8a494019fef97128cacfe8b3d79583 100644 (file)
@@ -42,7 +42,7 @@ MODULE_PARM_DESC(enable_crc16,
 #define WILC_SPI_RSP_HDR_EXTRA_DATA    8
 
 struct wilc_spi {
-       bool isinit;            /* true if SPI protocol has been configured */
+       bool isinit;            /* true if wilc_spi_init was successful */
        bool probing_crc;       /* true if we're probing chip's CRC config */
        bool crc7_enabled;      /* true if crc7 is currently enabled */
        bool crc16_enabled;     /* true if crc16 is currently enabled */
@@ -55,6 +55,8 @@ struct wilc_spi {
 static const struct wilc_hif_func wilc_hif_spi;
 
 static int wilc_spi_reset(struct wilc *wilc);
+static int wilc_spi_configure_bus_protocol(struct wilc *wilc);
+static int wilc_validate_chipid(struct wilc *wilc);
 
 /********************************************
  *
@@ -232,8 +234,27 @@ static int wilc_bus_probe(struct spi_device *spi)
        }
        clk_prepare_enable(wilc->rtc_clk);
 
+       dev_info(&spi->dev, "Selected CRC config: crc7=%s, crc16=%s\n",
+                enable_crc7 ? "on" : "off", enable_crc16 ? "on" : "off");
+
+       /* we need power to configure the bus protocol and to read the chip id: */
+
+       wilc_wlan_power(wilc, true);
+
+       ret = wilc_spi_configure_bus_protocol(wilc);
+       if (ret)
+               goto power_down;
+
+       ret = wilc_validate_chipid(wilc);
+       if (ret)
+               goto power_down;
+
+       wilc_wlan_power(wilc, false);
        return 0;
 
+power_down:
+       clk_disable_unprepare(wilc->rtc_clk);
+       wilc_wlan_power(wilc, false);
 netdev_cleanup:
        wilc_netdev_cleanup(wilc);
 free:
@@ -1102,26 +1123,34 @@ static int wilc_spi_deinit(struct wilc *wilc)
 
 static int wilc_spi_init(struct wilc *wilc, bool resume)
 {
-       struct spi_device *spi = to_spi_device(wilc->dev);
        struct wilc_spi *spi_priv = wilc->bus_data;
-       u32 reg;
-       u32 chipid;
-       int ret, i;
+       int ret;
 
        if (spi_priv->isinit) {
                /* Confirm we can read chipid register without error: */
-               ret = wilc_spi_read_reg(wilc, WILC_CHIPID, &chipid);
-               if (ret == 0)
+               if (wilc_validate_chipid(wilc) == 0)
                        return 0;
-
-               dev_err(&spi->dev, "Fail cmd read chip id...\n");
        }
 
        wilc_wlan_power(wilc, true);
 
-       /*
-        * configure protocol
-        */
+       ret = wilc_spi_configure_bus_protocol(wilc);
+       if (ret) {
+               wilc_wlan_power(wilc, false);
+               return ret;
+       }
+
+       spi_priv->isinit = true;
+
+       return 0;
+}
+
+static int wilc_spi_configure_bus_protocol(struct wilc *wilc)
+{
+       struct spi_device *spi = to_spi_device(wilc->dev);
+       struct wilc_spi *spi_priv = wilc->bus_data;
+       u32 reg;
+       int ret, i;
 
        /*
         * Infer the CRC settings that are currently in effect.  This
@@ -1173,6 +1202,15 @@ static int wilc_spi_init(struct wilc *wilc, bool resume)
 
        spi_priv->probing_crc = false;
 
+       return 0;
+}
+
+static int wilc_validate_chipid(struct wilc *wilc)
+{
+       struct spi_device *spi = to_spi_device(wilc->dev);
+       u32 chipid;
+       int ret;
+
        /*
         * make sure can read chip id without protocol error
         */
@@ -1181,9 +1219,10 @@ static int wilc_spi_init(struct wilc *wilc, bool resume)
                dev_err(&spi->dev, "Fail cmd read chip id...\n");
                return ret;
        }
-
-       spi_priv->isinit = true;
-
+       if (!is_wilc1000(chipid)) {
+               dev_err(&spi->dev, "Unknown chip id 0x%x\n", chipid);
+               return -ENODEV;
+       }
        return 0;
 }
 
index 6b2f2269ddf82f3f789f13bcca0d53ec7b4f21cd..68be233c36cefba0ef279a86f63fcfcd2f2d3d1f 100644 (file)
 
 #define WAKE_UP_TRIAL_RETRY            10000
 
-static inline bool is_wilc1000(u32 id)
-{
-       return (id & (~WILC_CHIP_REV_FIELD)) == WILC_1000_BASE_ID;
-}
-
 static inline void acquire_bus(struct wilc *wilc, enum bus_acquire acquire)
 {
        mutex_lock(&wilc->hif_cs);
index f02775f7e41fe86c71a31364acf76b09b1fa19c3..54643d8fef04e45f834ff207131730be60b8812b 100644 (file)
@@ -409,6 +409,11 @@ struct wilc_cfg_rsp {
 
 struct wilc_vif;
 
+static inline bool is_wilc1000(u32 id)
+{
+       return (id & (~WILC_CHIP_REV_FIELD)) == WILC_1000_BASE_ID;
+}
+
 int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer,
                                u32 buffer_size);
 int wilc_wlan_start(struct wilc *wilc);