Search Linux Wireless

[PATCH] wifi: wilc1000: validate chip id during bus probe

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxx>
---
V2 -> V3: Add missing forward declarations, actually :-(

 drivers/net/wireless/microchip/wilc1000/spi.c | 133 ++++++++++++------
 .../net/wireless/microchip/wilc1000/wlan.h    |   1 +
 2 files changed, 90 insertions(+), 44 deletions(-)

diff --git a/drivers/net/wireless/microchip/wilc1000/spi.c b/drivers/net/wireless/microchip/wilc1000/spi.c
index 77b4cdff73c3..dd6935dc1bc9 100644
--- a/drivers/net/wireless/microchip/wilc1000/spi.c
+++ b/drivers/net/wireless/microchip/wilc1000/spi.c
@@ -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,6 +234,22 @@ static int wilc_bus_probe(struct spi_device *spi)
 	}
 	clk_prepare_enable(wilc->rtc_clk);
 
+	/* 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 == 0)
+		ret = wilc_validate_chipid(wilc);
+
+	wilc_wlan_power(wilc, false);
+
+	if (ret) {
+		ret = -ENODEV;
+		goto netdev_cleanup;
+	}
+
 	return 0;
 
 netdev_cleanup:
@@ -1074,58 +1092,43 @@ static int wilc_spi_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size)
  *
  ********************************************/
 
-static int wilc_spi_reset(struct wilc *wilc)
+static const char *
+strbool(bool val)
 {
-	struct spi_device *spi = to_spi_device(wilc->dev);
-	struct wilc_spi *spi_priv = wilc->bus_data;
-	int result;
-
-	result = wilc_spi_special_cmd(wilc, CMD_RESET);
-	if (result && !spi_priv->probing_crc)
-		dev_err(&spi->dev, "Failed cmd reset\n");
-
-	return result;
-}
-
-static bool wilc_spi_is_init(struct wilc *wilc)
-{
-	struct wilc_spi *spi_priv = wilc->bus_data;
-
-	return spi_priv->isinit;
+	return val ? "on" : "off";
 }
 
-static int wilc_spi_deinit(struct wilc *wilc)
+static int wilc_validate_chipid(struct wilc *wilc)
 {
-	struct wilc_spi *spi_priv = wilc->bus_data;
+	struct spi_device *spi = to_spi_device(wilc->dev);
+	u32 chipid, base_id;
+	int ret;
 
-	spi_priv->isinit = false;
-	wilc_wlan_power(wilc, false);
+	/*
+	 * make sure can read chip id without protocol error
+	 */
+	ret = wilc_spi_read_reg(wilc, WILC_CHIPID, &chipid);
+	if (ret) {
+		dev_err(&spi->dev, "Fail cmd read chip id...\n");
+		return ret;
+	}
+	base_id = chipid & ~WILC_CHIP_REV_FIELD;
+	if (base_id != WILC_1000_BASE_ID && base_id != WILC_3000_BASE_ID) {
+		dev_err(&spi->dev, "Unknown chip id 0x%x\n", chipid);
+		return ret;
+	}
+	dev_info(&spi->dev, "Detected chip id 0x%x (crc7=%s, crc16=%s)\n",
+		 chipid, strbool(enable_crc7), strbool(enable_crc16));
 	return 0;
 }
 
-static int wilc_spi_init(struct wilc *wilc, bool resume)
+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;
-	u32 chipid;
 	int ret, i;
 
-	if (spi_priv->isinit) {
-		/* Confirm we can read chipid register without error: */
-		ret = wilc_spi_read_reg(wilc, WILC_CHIPID, &chipid);
-		if (ret == 0)
-			return 0;
-
-		dev_err(&spi->dev, "Fail cmd read chip id...\n");
-	}
-
-	wilc_wlan_power(wilc, true);
-
-	/*
-	 * configure protocol
-	 */
-
 	/*
 	 * Infer the CRC settings that are currently in effect.  This
 	 * is necessary because we can't be sure that the chip has
@@ -1176,12 +1179,54 @@ static int wilc_spi_init(struct wilc *wilc, bool resume)
 
 	spi_priv->probing_crc = false;
 
-	/*
-	 * make sure can read chip id without protocol error
-	 */
-	ret = wilc_spi_read_reg(wilc, WILC_CHIPID, &chipid);
+	return 0;
+}
+
+static int wilc_spi_reset(struct wilc *wilc)
+{
+	struct spi_device *spi = to_spi_device(wilc->dev);
+	struct wilc_spi *spi_priv = wilc->bus_data;
+	int result;
+
+	result = wilc_spi_special_cmd(wilc, CMD_RESET);
+	if (result && !spi_priv->probing_crc)
+		dev_err(&spi->dev, "Failed cmd reset\n");
+
+	return result;
+}
+
+static bool wilc_spi_is_init(struct wilc *wilc)
+{
+	struct wilc_spi *spi_priv = wilc->bus_data;
+
+	return spi_priv->isinit;
+}
+
+static int wilc_spi_deinit(struct wilc *wilc)
+{
+	struct wilc_spi *spi_priv = wilc->bus_data;
+
+	spi_priv->isinit = false;
+	wilc_wlan_power(wilc, false);
+	return 0;
+}
+
+static int wilc_spi_init(struct wilc *wilc, bool resume)
+{
+	struct wilc_spi *spi_priv = wilc->bus_data;
+	int ret;
+
+	if (spi_priv->isinit) {
+		/* Confirm we can read chipid register without error: */
+		if (wilc_validate_chipid(wilc) == 0)
+			return 0;
+	}
+
+	wilc_wlan_power(wilc, true);
+
+	ret = wilc_spi_configure_bus_protocol(wilc);
 	if (ret) {
-		dev_err(&spi->dev, "Fail cmd read chip id...\n");
+		wilc_wlan_power(wilc, false);
 		return ret;
 	}
 
diff --git a/drivers/net/wireless/microchip/wilc1000/wlan.h b/drivers/net/wireless/microchip/wilc1000/wlan.h
index a72cd5cac81d..43dda9f0d9ca 100644
--- a/drivers/net/wireless/microchip/wilc1000/wlan.h
+++ b/drivers/net/wireless/microchip/wilc1000/wlan.h
@@ -182,6 +182,7 @@
 #define WILC_CORTUS_BOOT_FROM_IRAM	0x71
 
 #define WILC_1000_BASE_ID		0x100000
+#define WILC_3000_BASE_ID		0x300000
 
 #define WILC_1000_BASE_ID_2A		0x1002A0
 #define WILC_1000_BASE_ID_2A_REV1	(WILC_1000_BASE_ID_2A + 1)
-- 
2.34.1





[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux