staging: wfx: add infrastructure for new driver
authorJérôme Pouiller <jerome.pouiller@silabs.com>
Thu, 19 Sep 2019 14:25:36 +0000 (14:25 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 4 Oct 2019 08:26:51 +0000 (10:26 +0200)
Instantiate build infrastructure WFx driver. This driver provides support
for Wifi chipset Silicon Labs WF200 and further:

   https://www.silabs.com/documents/public/data-sheets/wf200-datasheet.pdf

This chip support SPI and SDIO bus.

SDIO interface has two particularities:
    1. Some parameters may be useful for end user (I will talk about
       gpio_wakeup later).
    2. The SDIO VID and PID of WF200 are 0000:0001 which are too much
       generic to rely on.

So, current code checks VID/PID and looks for a node in DT (since WF200
targets embedded platforms, I don't think it is a problem to rely on
DT). DT can also be used to define to parameters for driver. Currently,
if no node is found, a warning is emitted, but it could be changed in
error.

Signed-off-by: Jérôme Pouiller <jerome.pouiller@silabs.com>
Link: https://lore.kernel.org/r/20190919142527.31797-2-Jerome.Pouiller@silabs.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
12 files changed:
MAINTAINERS
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/wfx/Documentation/devicetree/bindings/net/wireless/siliabs,wfx.txt [new file with mode: 0644]
drivers/staging/wfx/Kconfig [new file with mode: 0644]
drivers/staging/wfx/Makefile [new file with mode: 0644]
drivers/staging/wfx/TODO [new file with mode: 0644]
drivers/staging/wfx/bus.h [new file with mode: 0644]
drivers/staging/wfx/bus_sdio.c [new file with mode: 0644]
drivers/staging/wfx/bus_spi.c [new file with mode: 0644]
drivers/staging/wfx/main.c [new file with mode: 0644]
drivers/staging/wfx/wfx_version.h [new file with mode: 0644]

index 296de2b..8f5b484 100644 (file)
@@ -14802,6 +14802,11 @@ S:     Maintained
 F:     drivers/input/touchscreen/silead.c
 F:     drivers/platform/x86/touchscreen_dmi.c
 
+SILICON LABS WIRELESS DRIVERS (for WFxxx series)
+M:     Jérôme Pouiller <jerome.pouiller@silabs.com>
+S:     Supported
+F:     drivers/staging/wfx/
+
 SILICON MOTION SM712 FRAME BUFFER DRIVER
 M:     Sudip Mukherjee <sudipm.mukherjee@gmail.com>
 M:     Teddy Wang <teddy.wang@siliconmotion.com>
index 6f1fa4c..a490141 100644 (file)
@@ -125,4 +125,6 @@ source "drivers/staging/exfat/Kconfig"
 
 source "drivers/staging/qlge/Kconfig"
 
+source "drivers/staging/wfx/Kconfig"
+
 endif # STAGING
index a90f9b3..4cb548a 100644 (file)
@@ -53,3 +53,4 @@ obj-$(CONFIG_UWB)             += uwb/
 obj-$(CONFIG_USB_WUSB)         += wusbcore/
 obj-$(CONFIG_EXFAT_FS)         += exfat/
 obj-$(CONFIG_QLGE)             += qlge/
+obj-$(CONFIG_WFX)              += wfx/
diff --git a/drivers/staging/wfx/Documentation/devicetree/bindings/net/wireless/siliabs,wfx.txt b/drivers/staging/wfx/Documentation/devicetree/bindings/net/wireless/siliabs,wfx.txt
new file mode 100644 (file)
index 0000000..15965c9
--- /dev/null
@@ -0,0 +1,97 @@
+The WFxxx chip series can be connected via SPI or via SDIO.
+
+SPI
+---
+
+You have to declare the WFxxx chip in your device tree.
+
+Required properties:
+ - compatible: Should be "silabs,wfx-spi"
+ - reg: Chip select address of device
+ - spi-max-frequency: Maximum SPI clocking speed of device in Hz
+ - interrupts-extended: Should contain interrupt line (interrupt-parent +
+   interrupt can also been used). Trigger should be `IRQ_TYPE_EDGE_RISING`.
+
+Optional properties:
+ - reset-gpios: phandle of gpio that will be used to reset chip during probe.
+   Without this property, you may encounter issues with warm boot.
+
+Please consult Documentation/devicetree/bindings/spi/spi-bus.txt for optional
+SPI connection related properties,
+
+Example:
+
+&spi1 {
+       wfx {
+               compatible = "silabs,wfx-spi";
+               pinctrl-names = "default";
+               pinctrl-0 = <&wfx_irq &wfx_gpios>;
+               interrupts-extended = <&gpio 16 IRQ_TYPE_EDGE_RISING>;
+               wakeup-gpios = <&gpio 12 GPIO_ACTIVE_HIGH>;
+               reset-gpios = <&gpio 13 GPIO_ACTIVE_HIGH>;
+               reg = <0>;
+               spi-max-frequency = <42000000>;
+       };
+};
+
+
+SDIO
+----
+
+The driver is able to detect a WFxxx chip on SDIO bus by matching its Vendor ID
+and Product ID. However, driver will only provide limited features in this
+case. Thus declaring WFxxx chip in device tree is strongly recommended (and may
+become mandatory in the future).
+
+Required properties:
+ - compatible: Should be "silabs,wfx-sdio"
+ - reg: Should be 1
+
+In addition, it is recommended to declare a mmc-pwrseq on SDIO host above WFx.
+Without it, you may encounter issues with warm boot. mmc-pwrseq should be
+compatible with mmc-pwrseq-simple. Please consult
+Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt for more
+information.
+
+Example:
+
+/ {
+       wfx_pwrseq: wfx_pwrseq {
+               compatible = "mmc-pwrseq-simple";
+               pinctrl-names = "default";
+               pinctrl-0 = <&wfx_reset>;
+               reset-gpios = <&gpio 13 GPIO_ACTIVE_LOW>;
+       };
+};
+
+&mmc1 {
+       mmc-pwrseq = <&wfx_pwrseq>;
+       #address-size = <1>;
+       #size = <0>;
+
+       mmc@1 {
+               compatible = "silabs,wfx-sdio";
+               reg = <1>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&wfx_wakeup>;
+               wakeup-gpios = <&gpio 12 GPIO_ACTIVE_HIGH>;
+       };
+};
+
+Note that #address-size and #size shoud already be defined in node mmc1, but it
+is rarely the case.
+
+Common properties
+-----------------
+
+Some properties are recognized either by SPI and SDIO versions:
+ - wakeup-gpios: phandle of gpio that will be used to wake-up chip. Without
+   this property, driver will disable most of power saving features.
+ - config-file: Use an alternative file as PDS. Default is `wf200.pds`. Only
+   necessary for development/debug purpose.
+ - slk_key: String representing hexdecimal value of secure link key to use.
+   Must contains 64 hexadecimal digits. Not supported in current version.
+
+WFx driver also supports `mac-address` and `local-mac-address` as described in
+Documentation/devicetree/binding/net/ethernet.txt
+
diff --git a/drivers/staging/wfx/Kconfig b/drivers/staging/wfx/Kconfig
new file mode 100644 (file)
index 0000000..9b8a1c7
--- /dev/null
@@ -0,0 +1,7 @@
+config WFX
+       tristate "Silicon Labs wireless chips WF200 and further"
+       depends on MAC80211
+       depends on (SPI || MMC)
+       help
+         This is a driver for Silicons Labs WFxxx series (WF200 and further)
+         chipsets. This chip can be found on SPI or SDIO buses.
diff --git a/drivers/staging/wfx/Makefile b/drivers/staging/wfx/Makefile
new file mode 100644 (file)
index 0000000..74939a5
--- /dev/null
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0
+
+wfx-y := \
+       main.o
+wfx-$(CONFIG_SPI) += bus_spi.o
+wfx-$(subst m,y,$(CONFIG_MMC)) += bus_sdio.o
+
+obj-$(CONFIG_WFX) += wfx.o
diff --git a/drivers/staging/wfx/TODO b/drivers/staging/wfx/TODO
new file mode 100644 (file)
index 0000000..be990e8
--- /dev/null
@@ -0,0 +1,20 @@
+This is a list of things that need to be done to get this driver out of the
+staging directory.
+
+  - wfx_version.h is still there in order to ensure synchronization with github.
+    It can be dropped as soon as development is entirely in kernel
+
+  - I have to take a decision about secure link support. I can:
+      - drop completely
+      - keep it in an external patch (my preferred option)
+      - replace call to mbedtls with kernel crypto API (necessitate a
+        bunch of work)
+      - pull mbedtls in kernel (non-realistic)
+
+  - mac80211 interface does not (yet) have expected quality to be placed
+    outside of staging:
+      - Some processings are redundant with mac80211 ones
+      - Many members from wfx_dev/wfx_vif can be retrieved from mac80211
+        structures
+      - Some functions are too complex
+      - ...
diff --git a/drivers/staging/wfx/bus.h b/drivers/staging/wfx/bus.h
new file mode 100644 (file)
index 0000000..8ce871a
--- /dev/null
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Common bus abstraction layer.
+ *
+ * Copyright (c) 2017-2018, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ */
+#ifndef WFX_BUS_H
+#define WFX_BUS_H
+
+#include <linux/mmc/sdio_func.h>
+#include <linux/spi/spi.h>
+
+extern struct sdio_driver wfx_sdio_driver;
+extern struct spi_driver wfx_spi_driver;
+
+#endif
diff --git a/drivers/staging/wfx/bus_sdio.c b/drivers/staging/wfx/bus_sdio.c
new file mode 100644 (file)
index 0000000..4b26c99
--- /dev/null
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * SDIO interface.
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ */
+#include <linux/module.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/card.h>
+#include <linux/of_irq.h>
+
+#include "bus.h"
+
+static const struct of_device_id wfx_sdio_of_match[];
+static int wfx_sdio_probe(struct sdio_func *func,
+                         const struct sdio_device_id *id)
+{
+       struct device_node *np = func->dev.of_node;
+
+       if (func->num != 1) {
+               dev_err(&func->dev, "SDIO function number is %d while it should always be 1 (unsupported chip?)\n", func->num);
+               return -ENODEV;
+       }
+
+       if (np) {
+               if (!of_match_node(wfx_sdio_of_match, np)) {
+                       dev_warn(&func->dev, "no compatible device found in DT\n");
+                       return -ENODEV;
+               }
+       } else {
+               dev_warn(&func->dev, "device is not declared in DT, features will be limited\n");
+               // FIXME: ignore VID/PID and only rely on device tree
+               // return -ENODEV;
+       }
+       return -EIO; // FIXME: not yet supported
+}
+
+static void wfx_sdio_remove(struct sdio_func *func)
+{
+}
+
+#define SDIO_VENDOR_ID_SILABS        0x0000
+#define SDIO_DEVICE_ID_SILABS_WF200  0x1000
+static const struct sdio_device_id wfx_sdio_ids[] = {
+       { SDIO_DEVICE(SDIO_VENDOR_ID_SILABS, SDIO_DEVICE_ID_SILABS_WF200) },
+       // FIXME: ignore VID/PID and only rely on device tree
+       // { SDIO_DEVICE(SDIO_ANY_ID, SDIO_ANY_ID) },
+       { },
+};
+MODULE_DEVICE_TABLE(sdio, wfx_sdio_ids);
+
+#ifdef CONFIG_OF
+static const struct of_device_id wfx_sdio_of_match[] = {
+       { .compatible = "silabs,wfx-sdio" },
+       { },
+};
+MODULE_DEVICE_TABLE(of, wfx_sdio_of_match);
+#endif
+
+struct sdio_driver wfx_sdio_driver = {
+       .name = "wfx-sdio",
+       .id_table = wfx_sdio_ids,
+       .probe = wfx_sdio_probe,
+       .remove = wfx_sdio_remove,
+       .drv = {
+               .owner = THIS_MODULE,
+               .of_match_table = of_match_ptr(wfx_sdio_of_match),
+       }
+};
diff --git a/drivers/staging/wfx/bus_spi.c b/drivers/staging/wfx/bus_spi.c
new file mode 100644 (file)
index 0000000..574b60f
--- /dev/null
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * SPI interface.
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2011, Sagrad Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ */
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/of.h>
+
+#include "bus.h"
+
+static int wfx_spi_probe(struct spi_device *func)
+{
+       return -EIO;
+}
+
+/* Disconnect Function to be called by SPI stack when device is disconnected */
+static int wfx_spi_disconnect(struct spi_device *func)
+{
+       return 0;
+}
+
+/*
+ * For dynamic driver binding, kernel does not use OF to match driver. It only
+ * use modalias and modalias is a copy of 'compatible' DT node with vendor
+ * stripped.
+ */
+static const struct spi_device_id wfx_spi_id[] = {
+       { "wfx-spi", 0 },
+       { },
+};
+MODULE_DEVICE_TABLE(spi, wfx_spi_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id wfx_spi_of_match[] = {
+       { .compatible = "silabs,wfx-spi" },
+       { },
+};
+MODULE_DEVICE_TABLE(of, wfx_spi_of_match);
+#endif
+
+struct spi_driver wfx_spi_driver = {
+       .driver = {
+               .name = "wfx-spi",
+               .of_match_table = of_match_ptr(wfx_spi_of_match),
+       },
+       .id_table = wfx_spi_id,
+       .probe = wfx_spi_probe,
+       .remove = wfx_spi_disconnect,
+};
diff --git a/drivers/staging/wfx/main.c b/drivers/staging/wfx/main.c
new file mode 100644 (file)
index 0000000..cd69f95
--- /dev/null
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Device probe and register.
+ *
+ * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ * Copyright (c) 2008, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (c) 2007-2009, Christian Lamparter <chunkeey@web.de>
+ * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
+ * Copyright (c) 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
+ */
+#include <linux/module.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/spi/spi.h>
+#include <linux/etherdevice.h>
+
+#include "bus.h"
+#include "wfx_version.h"
+
+MODULE_DESCRIPTION("Silicon Labs 802.11 Wireless LAN driver for WFx");
+MODULE_AUTHOR("Jérôme Pouiller <jerome.pouiller@silabs.com>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(WFX_LABEL);
+
+static int __init wfx_core_init(void)
+{
+       int ret = 0;
+
+       pr_info("wfx: Silicon Labs " WFX_LABEL "\n");
+
+       if (IS_ENABLED(CONFIG_SPI))
+               ret = spi_register_driver(&wfx_spi_driver);
+       if (IS_ENABLED(CONFIG_MMC) && !ret)
+               ret = sdio_register_driver(&wfx_sdio_driver);
+       return ret;
+}
+module_init(wfx_core_init);
+
+static void __exit wfx_core_exit(void)
+{
+       if (IS_ENABLED(CONFIG_MMC))
+               sdio_unregister_driver(&wfx_sdio_driver);
+       if (IS_ENABLED(CONFIG_SPI))
+               spi_unregister_driver(&wfx_spi_driver);
+}
+module_exit(wfx_core_exit);
diff --git a/drivers/staging/wfx/wfx_version.h b/drivers/staging/wfx/wfx_version.h
new file mode 100644 (file)
index 0000000..6e7f302
--- /dev/null
@@ -0,0 +1,3 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT! */
+#define WFX_LABEL "2.3.1"