├── wilc ├── Makefile ├── microchip,wilc1000,spi.txt ├── wilc_wfi_cfgoperations.h ├── microchip,wilc1000,sdio.txt ├── wilc_wlan_cfg.h ├── wilc_debugfs.h ├── wilc_netdev.h ├── Kconfig ├── wilc_debugfs.c ├── sysfs.c ├── wilc_hif.h ├── wilc_wfi_netdevice.h ├── wilc_mon.c ├── wilc_wlan.h ├── wilc_wlan_cfg.c ├── wilc_bt.c ├── wilc_wlan_if.h ├── wilc_sdio.c └── wilc_spi.c └── README.md /wilc/Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0 2 | ccflags-y += -I$(src)/ -DWILC_ASIC_A0 -DWILC_DEBUGFS 3 | 4 | wilc-objs := wilc_wfi_cfgoperations.o wilc_netdev.o wilc_mon.o \ 5 | wilc_hif.o wilc_wlan_cfg.o wilc_debugfs.o \ 6 | wilc_wlan.o sysfs.o wilc_bt.o 7 | 8 | obj-$(CONFIG_WILC_SDIO) += wilc-sdio.o 9 | wilc-sdio-objs += $(wilc-objs) 10 | wilc-sdio-objs += wilc_sdio.o 11 | 12 | obj-$(CONFIG_WILC_SPI) += wilc-spi.o 13 | wilc-spi-objs += $(wilc-objs) 14 | wilc-spi-objs += wilc_spi.o 15 | -------------------------------------------------------------------------------- /wilc/microchip,wilc1000,spi.txt: -------------------------------------------------------------------------------- 1 | * Microchip WILC wireless SPI device 2 | 3 | The wilc1000 chips can be connected via SPI. This document describes 4 | the binding for the SPI connected module. 5 | 6 | Required properties: 7 | - compatible : Should be "microchip,wilc1000-spi" 8 | - spi-max-frequency : Maximum SPI clocking speed of device in Hz 9 | - reg : Chip select address of device 10 | - irq-gpios : Connect to a host IRQ 11 | - reset-gpios : Reset module GPIO 12 | - chip_en-gpios: : Chip enable GPIO 13 | 14 | Optional: 15 | - rtc_clk : Clock connected on the rtc clock line. Must be assigned 16 | a frequency with assigned-clocks property, and must be 17 | connected to a clock provider. 18 | 19 | Examples: 20 | 21 | spi1: spi@fc018000 { 22 | cs-gpios = <&pioB 21 0>; 23 | status = "okay"; 24 | 25 | wilc_spi@0 { 26 | compatible = "microchip,wilc1000", "microchip,wilc3000"; 27 | spi-max-frequency = <48000000>; 28 | reg = <0>; 29 | irq-gpios = <&pioC 27 0>; 30 | reset-gpios = <&pioB 28 0>; 31 | chip_en-gpios = <&pioC 30 0>; 32 | clocks = <&pck1>; 33 | clock-names = "rtc_clk"; 34 | assigned-clocks = <&pck1>; 35 | assigned-clock-rates = <32768>; 36 | status = "okay"; 37 | }; 38 | }; 39 | -------------------------------------------------------------------------------- /wilc/wilc_wfi_cfgoperations.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | /* 3 | * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. 4 | * All rights reserved. 5 | */ 6 | 7 | #ifndef NM_WFI_CFGOPERATIONS 8 | #define NM_WFI_CFGOPERATIONS 9 | #include "wilc_wfi_netdevice.h" 10 | 11 | struct wilc *wilc_create_wiphy(struct device *dev); 12 | void wilc_free_wiphy(struct net_device *net); 13 | void wilc_deinit_host_int(struct net_device *net); 14 | int wilc_init_host_int(struct net_device *net); 15 | void wilc_wfi_monitor_rx(struct net_device *mon_dev, u8 *buff, u32 size); 16 | void wilc_wfi_deinit_mon_interface(struct wilc *wl, bool rtnl_locked); 17 | struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl, 18 | const char *name, 19 | struct net_device *real_dev); 20 | void wilc_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev, 21 | u16 frame_type, bool reg); 22 | void wilc_sysfs_init(struct wilc *wilc); 23 | void wilc_sysfs_exit(void); 24 | int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type, 25 | const struct wilc_hif_func *ops); 26 | struct wilc_vif *wilc_get_vif_from_type(struct wilc *wl, int type); 27 | struct wilc_vif *wilc_get_wl_to_vif(struct wilc *wl); 28 | void wlan_deinit_locks(struct wilc *wl); 29 | #endif 30 | -------------------------------------------------------------------------------- /wilc/microchip,wilc1000,sdio.txt: -------------------------------------------------------------------------------- 1 | * Microchip WILC wireless SDIO device 2 | 3 | The wilc1000 chips can be connected via SDIO. The node is used to specifiy 4 | child node to the SDIO controller that connects the device to the system. 5 | 6 | Required properties: 7 | - compatible : Should be "microchip,wilc1000-sdio" 8 | - irq-gpios : Connect to a host IRQ 9 | - reset-gpios : Reset module GPIO 10 | - chip_en-gpios : Chip enable GPIO 11 | - reg : Slot ID used in the controller 12 | 13 | Optional: 14 | - bus-width : Number of data lines wired up the slot. Default 1 bit. 15 | - rtc_clk : Clock connected on the rtc clock line. Must be assigned 16 | a frequency with assigned-clocks property, and must be 17 | connected to a clock provider. 18 | 19 | Examples: 20 | mmc1: mmc@fc000000 { 21 | pinctrl-names = "default"; 22 | pinctrl-0 = <&pinctrl_mmc1_clk_cmd_dat0 &pinctrl_mmc1_dat1_3>; 23 | non-removable; 24 | vmmc-supply = <&vcc_mmc1_reg>; 25 | vqmmc-supply = <&vcc_3v3_reg>; 26 | status = "okay"; 27 | 28 | wilc_sdio@0 { 29 | compatible = "microchip,wilc1000", "microchip,wilc3000"; 30 | irq-gpios = <&pioC 27 0>; 31 | reset-gpios = <&pioB 28 0>; 32 | chip_en-gpios = <&pioC 30 0>; 33 | clocks = <&pck1>; 34 | clock-names = "rtc_clk"; 35 | assigned-clocks = <&pck1>; 36 | assigned-clock-rates = <32768>; 37 | status = "okay"; 38 | reg = <0>; 39 | bus-width = <4>; 40 | } 41 | }; 42 | } 43 | -------------------------------------------------------------------------------- /wilc/wilc_wlan_cfg.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | /* 3 | * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. 4 | * All rights reserved. 5 | */ 6 | 7 | #ifndef WILC_WLAN_CFG_H 8 | #define WILC_WLAN_CFG_H 9 | 10 | struct wilc_cfg_byte { 11 | u16 id; 12 | u8 val; 13 | }; 14 | 15 | struct wilc_cfg_hword { 16 | u16 id; 17 | u16 val; 18 | }; 19 | 20 | struct wilc_cfg_word { 21 | u32 id; 22 | u32 val; 23 | }; 24 | 25 | struct wilc_cfg_str { 26 | u16 id; 27 | u8 *str; 28 | }; 29 | 30 | struct wilc_cfg_bin { 31 | u16 id; 32 | u8 *bin; 33 | }; 34 | 35 | struct wilc_cfg_str_vals { 36 | u8 mac_address[7]; 37 | u8 firmware_version[129]; 38 | u8 assoc_rsp[256]; 39 | }; 40 | 41 | struct wilc_bin_vals { 42 | u8 antenna_param[5]; 43 | }; 44 | 45 | struct wilc_cfg { 46 | struct wilc_cfg_byte *b; 47 | struct wilc_cfg_hword *hw; 48 | struct wilc_cfg_word *w; 49 | struct wilc_cfg_str *s; 50 | struct wilc_cfg_str_vals *str_vals; 51 | struct wilc_cfg_bin *bin; 52 | struct wilc_bin_vals *bin_vals; 53 | }; 54 | 55 | struct wilc; 56 | int cfg_set_wid(struct wilc_vif *vif, u8 *frame, u32 offset, u16 id, u8 *buf, 57 | int size); 58 | int cfg_get_wid(u8 *frame, u32 offset, u16 id); 59 | int cfg_get_val(struct wilc *wl, u16 wid, u8 *buffer, u32 buffer_size); 60 | void cfg_indicate_rx(struct wilc *wilc, u8 *frame, int size, 61 | struct wilc_cfg_rsp *rsp); 62 | int cfg_init(struct wilc *wl); 63 | void cfg_deinit(struct wilc *wl); 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /wilc/wilc_debugfs.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | /* 3 | * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. 4 | * All rights reserved. 5 | */ 6 | 7 | #ifndef WILC_DEBUGFS_H 8 | #define WILC_DEBUGFS_H 9 | 10 | #include 11 | 12 | #define GENERIC_DBG BIT(0) 13 | #define HOSTAPD_DBG BIT(1) 14 | #define HOSTINF_DBG BIT(2) 15 | #define CORECONFIG_DBG BIT(3) 16 | #define CFG80211_DBG BIT(4) 17 | #define INT_DBG BIT(5) 18 | #define TX_DBG BIT(6) 19 | #define RX_DBG BIT(7) 20 | #define TCP_ENH BIT(8) 21 | #define INIT_DBG BIT(9) 22 | #define PWRDEV_DBG BIT(10) 23 | #define DBG_REGION_ALL (BIT(11)-1) 24 | 25 | extern atomic_t WILC_DEBUG_REGION; 26 | 27 | #define PRINT_D(netdev, region, format, ...) do { \ 28 | if (atomic_read(&WILC_DEBUG_REGION)&(region))\ 29 | netdev_dbg(netdev, "DBG [%s: %d] "format, __func__, __LINE__,\ 30 | ##__VA_ARGS__); } \ 31 | while (0) 32 | 33 | #define PRINT_INFO(netdev, region, format, ...) do { \ 34 | if (atomic_read(&WILC_DEBUG_REGION)&(region))\ 35 | netdev_info(netdev, "INFO [%s]"format, __func__, \ 36 | ##__VA_ARGS__); } \ 37 | while (0) 38 | 39 | #define PRINT_WRN(netdev, region, format, ...) do { \ 40 | if (atomic_read(&WILC_DEBUG_REGION)&(region))\ 41 | netdev_warn(netdev, "WRN [%s: %d]"format, __func__, __LINE__,\ 42 | ##__VA_ARGS__); } \ 43 | while (0) 44 | 45 | #define PRINT_ER(netdev, format, ...) netdev_err(netdev, "ERR [%s:%d] "format,\ 46 | __func__, __LINE__, ##__VA_ARGS__) 47 | 48 | int wilc_debugfs_init(void); 49 | void wilc_debugfs_remove(void); 50 | #endif /* WILC_DEBUGFS_H */ 51 | -------------------------------------------------------------------------------- /wilc/wilc_netdev.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | /* 3 | * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. 4 | * All rights reserved. 5 | */ 6 | 7 | #ifndef WILC_NETDEV_H 8 | #define WILC_NETDEV_H 9 | #include 10 | #include 11 | #include 12 | 13 | #include "wilc_wfi_netdevice.h" 14 | #include "wilc_wlan_if.h" 15 | 16 | extern int wait_for_recovery; 17 | 18 | struct net_device *wilc_get_if_netdev(struct wilc *wilc, uint8_t ifc); 19 | 20 | #if KERNEL_VERSION(3, 14, 0) > LINUX_VERSION_CODE 21 | static inline void ether_addr_copy(u8 *dst, const u8 *src) 22 | { 23 | #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) 24 | *(u32 *)dst = *(const u32 *)src; 25 | *(u16 *)(dst + 4) = *(const u16 *)(src + 4); 26 | #else 27 | u16 *a = (u16 *)dst; 28 | const u16 *b = (const u16 *)src; 29 | 30 | a[0] = b[0]; 31 | a[1] = b[1]; 32 | a[2] = b[2]; 33 | #endif 34 | } 35 | 36 | static inline bool ether_addr_equal_unaligned(const u8 *addr1, const u8 *addr2) 37 | { 38 | #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) 39 | return ether_addr_equal(addr1, addr2); 40 | #else 41 | return memcmp(addr1, addr2, ETH_ALEN) == 0; 42 | #endif 43 | } 44 | #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) */ 45 | 46 | #if KERNEL_VERSION(3, 12, 0) > LINUX_VERSION_CODE 47 | #define PTR_ERR_OR_ZERO(ptr) PTR_RET(ptr) 48 | #endif 49 | 50 | int wilc_bt_power_up(struct wilc *wilc, int source); 51 | int wilc_bt_power_down(struct wilc *wilc, int source); 52 | void wilc_wfi_monitor_rx(struct net_device *mon_dev, u8 *buff, u32 size); 53 | struct wilc_vif * 54 | wilc_netdev_ifc_init(struct wilc *wl, const char *name, int iftype, 55 | enum nl80211_iftype type, bool rtnl_locked); 56 | 57 | #endif /* WILC_NETDEV_H */ 58 | -------------------------------------------------------------------------------- /wilc/Kconfig: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0 2 | config WILC 3 | tristate 4 | 5 | config WLAN_VENDOR_MCHP 6 | bool "Microhip devices" 7 | default y 8 | help 9 | This adds support for WILC1000 & WILC3000 chips which support 10 | IEEE 802.11n WiFi. WILC3000 is a WiFi-BT combo chip. 11 | 12 | if WLAN_VENDOR_MCHP 13 | 14 | config WILC_SDIO 15 | tristate "WILC SDIO" 16 | depends on CFG80211 && INET && MMC 17 | select WILC 18 | help 19 | This module adds support for the SDIO interface of adapters using 20 | WILC1000 & WILC3000 chipset. The Atmel WILC1000 SDIO is a full speed interface. 21 | It meets SDIO card specification version 2.0. The interface supports 22 | the 1-bit/4-bit SD transfer mode at the clock range of 0-50 MHz. 23 | The host can use this interface to read and write from any register 24 | within the chip as well as configure the WILC1000 for data DMA. 25 | To use this interface, pin9 (SDIO_SPI_CFG) must be grounded. Select 26 | this if your platform is using the SDIO bus. 27 | WILC3000 additionally supports BT 4.0 and BLE modes. 28 | 29 | config WILC_SPI 30 | tristate "WILC SPI" 31 | depends on CFG80211 && INET && SPI 32 | select WILC 33 | help 34 | This module adds support for the SPI interface of adapters using 35 | WILC1000 & WILC3000 chipset. The Atmel WILC1000 has a Serial Peripheral 36 | Interface (SPI) that operates as a SPI slave. This SPI interface can 37 | be used for control and for serial I/O of 802.11 data. The SPI is a 38 | full-duplex slave synchronous serial interface that is available 39 | immediately following reset when pin 9 (SDIO_SPI_CFG) is tied to 40 | VDDIO. Select this if your platform is using the SPI bus. 41 | WILC3000 additionally supports BT 4.0 and BLE modes. 42 | 43 | config WILC_HW_OOB_INTR 44 | bool "WILC out of band interrupt" 45 | depends on WILC_SDIO 46 | default n 47 | help 48 | This option enables out-of-band interrupt support for the WILC1000 & 49 | WILC3000 chipset. This OOB interrupt is intended to provide a faster 50 | interrupt mechanism for SDIO host controllers that don't support SDIO 51 | interrupt. Select this option If the SDIO host controller in your 52 | platform doesn't support SDIO time devision interrupt. 53 | endif 54 | -------------------------------------------------------------------------------- /wilc/wilc_debugfs.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | /* 3 | * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. 4 | * All rights reserved. 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include "wilc_debugfs.h" 11 | 12 | atomic_t WILC_DEBUG_REGION = ATOMIC_INIT(INIT_DBG | GENERIC_DBG | 13 | CFG80211_DBG | HOSTAPD_DBG | 14 | PWRDEV_DBG); 15 | 16 | #if defined(WILC_DEBUGFS) 17 | static struct dentry *wilc_dir; 18 | 19 | static ssize_t wilc_debug_region_read(struct file *file, char __user *userbuf, 20 | size_t count, loff_t *ppos) 21 | { 22 | char buf[128]; 23 | int res = 0; 24 | 25 | /* only allow read from start */ 26 | if (*ppos > 0) 27 | return 0; 28 | 29 | res = scnprintf(buf, sizeof(buf), "Debug Region: (0x%08x)\n", 30 | atomic_read(&WILC_DEBUG_REGION)); 31 | 32 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); 33 | } 34 | 35 | static ssize_t wilc_debug_region_write(struct file *filp, 36 | const char __user *buf, size_t count, 37 | loff_t *ppos) 38 | { 39 | int flag = 0; 40 | int ret; 41 | 42 | ret = kstrtouint_from_user(buf, count, 16, &flag); 43 | if (ret) 44 | return ret; 45 | 46 | if (flag > DBG_REGION_ALL) { 47 | pr_err("%s, value (0x%08x) is out of range, stay previous flag (0x%08x)\n", 48 | __func__, flag, atomic_read(&WILC_DEBUG_REGION)); 49 | pr_err("allowed bits are 0 to 15\n"); 50 | return -EINVAL; 51 | } 52 | 53 | atomic_set(&WILC_DEBUG_REGION, (int)flag); 54 | 55 | pr_info("Debug region set to %x\n", atomic_read(&WILC_DEBUG_REGION)); 56 | 57 | return count; 58 | } 59 | 60 | #define FOPS(_open, _read, _write, _poll) { \ 61 | .owner = THIS_MODULE, \ 62 | .open = (_open), \ 63 | .read = (_read), \ 64 | .write = (_write), \ 65 | .poll = (_poll), \ 66 | } 67 | 68 | struct wilc_debugfs_info_t { 69 | const char *name; 70 | int perm; 71 | unsigned int data; 72 | const struct file_operations fops; 73 | }; 74 | 75 | static struct wilc_debugfs_info_t debugfs_info[] = { 76 | { 77 | "wilc_debug_region", 78 | 0666, 79 | 0, 80 | FOPS(NULL, wilc_debug_region_read, wilc_debug_region_write, 81 | NULL), 82 | }, 83 | }; 84 | 85 | int wilc_debugfs_init(void) 86 | { 87 | int i; 88 | struct wilc_debugfs_info_t *info; 89 | 90 | wilc_dir = debugfs_create_dir("wilc", NULL); 91 | if (wilc_dir == NULL) { 92 | pr_err("Error creating debugfs\n"); 93 | return -EFAULT; 94 | } 95 | for (i = 0; i < ARRAY_SIZE(debugfs_info); i++) { 96 | info = &debugfs_info[i]; 97 | debugfs_create_file(info->name, 98 | info->perm, 99 | wilc_dir, 100 | &info->data, 101 | &info->fops); 102 | } 103 | return 0; 104 | } 105 | 106 | void wilc_debugfs_remove(void) 107 | { 108 | debugfs_remove_recursive(wilc_dir); 109 | } 110 | 111 | #endif 112 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Microchip Embedded Wi-Fi® 2 | 3 | 4 |


5 | 6 | Microcip Embedded Wi-Fi® is a family of self-contained, low power and certified modules bringing wireless internet connectivity. 7 | 8 | **[ATWILC1000](http://www.microchip.com/wwwproducts/en/ATWILC1000)** is IEEE 802.11 b/g/n/ IOT link controller utilizing highly optimized 802.11 and provides mulitple peripheral interfaces like SPI, and SDIO. 9 | 10 | **[ATWILC3000](http://www.microchip.com/wwwproducts/en/ATWILC3000)** is IEEE 802.11 b/g/n/BT4.0 IOT link controller utilizing highly optimized 802.11-Bluetooth coexistence protocol and provides mulitple peripheral interfaces like UART, SPI, and SDIO. 11 | 12 | This is the unified driver source for wilc1000 & wilc3000 chipsets. 13 | 14 | Refer to the [Wi-Fi Link Controller Linux User Guide](http://ww1.microchip.com/downloads/en/DeviceDoc/ATWILC1000-ATWILC3000-Wi-Fi-Link-Controller-Linux-User-Guide-DS70005328C.pdf) for information on how to use the wireless devices on linux and the [Wi-Fi Link Controller Linux Release Notes](http://ww1.microchip.com/downloads/en/DeviceDoc/Wi-Fi%20Link%20Controller%20Linux%20Driver%20Release%20Notes%20v15.2.pdf) for the latest release notes and revision history. 15 | 16 | For more information on Microchip Embedded Wi-Fi®, visit [Microchip Embedded Wi-Fi®](http://www.microchip.com/design-centers/wireless-connectivity/embedded-wi-fi). 17 | 18 |

ATWILC Features

19 | 20 | The ATWILC module supports the following features. 21 |
    22 |
  1. Wi-Fi Station (STA) 23 |
      24 |
    • IEEE 802.11 b/g/n
    • 25 |
    • Open, Wired Equivalent Privacy (WEP), Wi-Fi Protected Access (WPA)/WPA2 personal and 26 | WPA/WPA2 enterprise security
    • 27 |
    28 |
  2. 29 |
  3. Wi-Fi Access Point (AP) 30 |
      31 |
    • IEEE 802.11 b/g/n
    • 32 |
    • Open, WEP, WPA/WPA2 personal and WPA/WPA2 enterprise security
    • 33 |
    • Supports eight stations
    • 34 |
  4. 35 |
  5. Wi-Fi Protected Setup (WPS) 36 |
      37 |
    • PBC
    • 38 |
    • PIN code
    • 39 |
    40 |
  6. 41 |
  7. Wi-Fi direct 42 |
      43 |
    • P2P Client
    • 44 |
    • P2P GO
    • 45 |
    46 |
  8. 47 |
  9. Concurrent modes 48 |
      49 |
    • STA-STA
    • 50 |
    • STA-AP
    • 51 |
    • STA-P2 Client
    • 52 |
    • STA-P2P GO
    • 53 |
    • AP-P2P Client
    • 54 |
    55 |
  10. 56 |
  11. Antenna diversity control for Wi-Fi 57 |
  12. 58 |
  13. Bluetooth (ATWILC3000 only) 59 |
      60 |
    • Bluetooth Low Energy (BLE) 4.0 support
    • 61 |
    • Modes of operation: Central and peripheral support
    • 62 |
    • Number of Connections: Supports seven clients
    • 63 |
    • Adaptive frequency hopping
    • 64 |
    • Coexistence with Wi-Fi
    • 65 |
    66 |
  14. 67 |
  15. Power save 68 |
      69 |
    • Beacon monitoring mode
    • 70 |
    • Low-power mode when disconnected
    • 71 |
    • Host suspend support
    • 72 |
    • Wake-up host on wireless LAN events
    • 73 |
    74 |
  16. 75 |
  17. RF version number 01.1 76 |
  18. 77 | Note: RF version number format is xx.y, where xx: "Major" and y: "Minor". 78 | Changes in Major number requires re-tests and possibly re-certification. 79 |
80 | -------------------------------------------------------------------------------- /wilc/sysfs.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | /* 3 | * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. 4 | * All rights reserved. 5 | */ 6 | 7 | #include 8 | #include "wilc_wfi_cfgoperations.h" 9 | 10 | static struct kobject *wilc_kobj; 11 | static int device_created; 12 | static struct wilc *wl; 13 | 14 | static ssize_t wilc_sysfs_show(struct kobject *kobj, 15 | struct kobj_attribute *attr, char *buf) 16 | { 17 | int attr_val = -1; 18 | 19 | if (strcmp(attr->attr.name, "p2p_mode") == 0) 20 | attr_val = wl->attr_sysfs.p2p_mode; 21 | if (strcmp(attr->attr.name, "ant_swtch_mode") == 0) 22 | attr_val = wl->attr_sysfs.ant_swtch_mode; 23 | else if (strcmp(attr->attr.name, "antenna1") == 0) 24 | attr_val = wl->attr_sysfs.antenna1; 25 | else if (strcmp(attr->attr.name, "antenna2") == 0) 26 | attr_val = wl->attr_sysfs.antenna2; 27 | 28 | return sprintf(buf, "%d\n", attr_val); 29 | } 30 | 31 | static ssize_t wilc_sysfs_store(struct kobject *kobj, 32 | struct kobj_attribute *attr, const char *buf, 33 | size_t count) 34 | { 35 | int attr_val; 36 | 37 | if (kstrtoint(buf, 10, &attr_val)) 38 | pr_err("Failed to convert p2p_mode string"); 39 | if (strcmp(attr->attr.name, "p2p_mode") == 0) { 40 | wl->attr_sysfs.p2p_mode = (attr_val?1:0); 41 | } else if (strcmp(attr->attr.name, "ant_swtch_mode") == 0) { 42 | if (attr_val > ANT_SWTCH_DUAL_GPIO_CTRL) 43 | pr_err("Valid antenna switch modes:\n1-Single Antenna, 2-Dual Antenna\n"); 44 | else 45 | wl->attr_sysfs.ant_swtch_mode = attr_val; 46 | } else if (strcmp(attr->attr.name, "antenna1") == 0) { 47 | wl->attr_sysfs.antenna1 = attr_val; 48 | } else if (strcmp(attr->attr.name, "antenna2") == 0) { 49 | wl->attr_sysfs.antenna2 = attr_val; 50 | } 51 | 52 | return count; 53 | } 54 | 55 | static struct kobj_attribute p2p_mode_attr = 56 | __ATTR(p2p_mode, 0664, wilc_sysfs_show, wilc_sysfs_store); 57 | 58 | static struct kobj_attribute ant_swtch_mode_attr = 59 | __ATTR(ant_swtch_mode, 0664, wilc_sysfs_show, wilc_sysfs_store); 60 | 61 | static struct kobj_attribute ant_swtch_antenna1_attr = 62 | __ATTR(antenna1, 0664, wilc_sysfs_show, wilc_sysfs_store); 63 | 64 | static struct kobj_attribute ant_swtch_antenna2_attr = 65 | __ATTR(antenna2, 0664, wilc_sysfs_show, wilc_sysfs_store); 66 | 67 | 68 | static struct attribute *wilc_attrs[] = { 69 | &p2p_mode_attr.attr, 70 | &ant_swtch_mode_attr.attr, 71 | &ant_swtch_antenna1_attr.attr, 72 | &ant_swtch_antenna2_attr.attr, 73 | NULL 74 | }; 75 | 76 | static struct attribute_group attr_group = { 77 | .attrs = wilc_attrs, 78 | }; 79 | 80 | void wilc_sysfs_init(struct wilc *wilc) 81 | { 82 | int retval; 83 | 84 | if (device_created) 85 | return; 86 | 87 | wilc_kobj = kobject_create_and_add("wilc", NULL); 88 | if (!wilc_kobj) { 89 | retval = -ENOMEM; 90 | return; 91 | } 92 | 93 | retval = sysfs_create_group(wilc_kobj, &attr_group); 94 | device_created = 1; 95 | wl = wilc; 96 | /* By default p2p mode is Group Owner */ 97 | wl->attr_sysfs.p2p_mode = 1; 98 | wl->attr_sysfs.ant_swtch_mode = ANT_SWTCH_INVALID_GPIO_CTRL; 99 | wl->attr_sysfs.antenna1 = 0xFF; 100 | wl->attr_sysfs.antenna2 = 0xFF; 101 | } 102 | 103 | void wilc_sysfs_exit(void) 104 | { 105 | device_created = 0; 106 | sysfs_remove_group(wilc_kobj, &attr_group); 107 | kobject_put(wilc_kobj); 108 | } 109 | -------------------------------------------------------------------------------- /wilc/wilc_hif.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | /* 3 | * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. 4 | * All rights reserved. 5 | */ 6 | 7 | #ifndef HOST_INT_H 8 | #define HOST_INT_H 9 | #include 10 | #include "wilc_wlan_if.h" 11 | 12 | enum { 13 | WILC_IDLE_MODE = 0x0, 14 | WILC_AP_MODE = 0x1, 15 | WILC_STATION_MODE = 0x2, 16 | WILC_GO_MODE = 0x3, 17 | WILC_CLIENT_MODE = 0x4, 18 | WILC_MONITOR_MODE = 0x5 19 | }; 20 | 21 | #define WILC_MAX_NUM_STA 9 22 | #define WILC_MAX_NUM_SCANNED_CH 14 23 | #define WILC_MAX_NUM_PROBED_SSID 10 24 | 25 | #define WILC_TX_MIC_KEY_LEN 8 26 | #define WILC_RX_MIC_KEY_LEN 8 27 | 28 | #define WILC_MAX_NUM_PMKIDS 16 29 | #define WILC_ADD_STA_LENGTH 40 30 | #define WILC_NUM_CONCURRENT_IFC 2 31 | 32 | enum { 33 | WILC_SET_CFG = 0, 34 | WILC_GET_CFG 35 | }; 36 | 37 | #define WILC_MAX_ASSOC_RESP_FRAME_SIZE 256 38 | extern uint32_t cfg_packet_timeout; 39 | 40 | struct assoc_resp { 41 | __le16 capab_info; 42 | __le16 status_code; 43 | __le16 aid; 44 | } __packed; 45 | 46 | struct rf_info { 47 | u8 link_speed; 48 | s8 rssi; 49 | u32 tx_cnt; 50 | u32 rx_cnt; 51 | u32 tx_fail_cnt; 52 | }; 53 | 54 | enum host_if_state { 55 | HOST_IF_IDLE = 0, 56 | HOST_IF_SCANNING = 1, 57 | HOST_IF_CONNECTING = 2, 58 | HOST_IF_WAITING_CONN_RESP = 3, 59 | HOST_IF_CONNECTED = 4, 60 | HOST_IF_P2P_LISTEN = 5, 61 | HOST_IF_FORCE_32BIT = 0xFFFFFFFF 62 | }; 63 | 64 | struct wilc_pmkid { 65 | u8 bssid[ETH_ALEN]; 66 | u8 pmkid[WLAN_PMKID_LEN]; 67 | } __packed; 68 | 69 | struct wilc_pmkid_attr { 70 | u8 numpmkid; 71 | struct wilc_pmkid pmkidlist[WILC_MAX_NUM_PMKIDS]; 72 | } __packed; 73 | 74 | struct cfg_param_attr { 75 | u32 flag; 76 | u16 short_retry_limit; 77 | u16 long_retry_limit; 78 | u16 frag_threshold; 79 | u16 rts_threshold; 80 | }; 81 | 82 | enum cfg_param { 83 | WILC_CFG_PARAM_RETRY_SHORT = BIT(0), 84 | WILC_CFG_PARAM_RETRY_LONG = BIT(1), 85 | WILC_CFG_PARAM_FRAG_THRESHOLD = BIT(2), 86 | WILC_CFG_PARAM_RTS_THRESHOLD = BIT(3) 87 | }; 88 | 89 | enum scan_event { 90 | SCAN_EVENT_NETWORK_FOUND = 0, 91 | SCAN_EVENT_DONE = 1, 92 | SCAN_EVENT_ABORTED = 2, 93 | SCAN_EVENT_FORCE_32BIT = 0xFFFFFFFF 94 | }; 95 | 96 | enum conn_event { 97 | EVENT_CONN_RESP = 0, 98 | EVENT_DISCONN_NOTIF = 1, 99 | EVENT_FORCE_32BIT = 0xFFFFFFFF 100 | }; 101 | 102 | enum { 103 | WILC_HIF_SDIO = 0, 104 | WILC_HIF_SPI = BIT(0), 105 | WILC_HIF_SDIO_GPIO_IRQ = BIT(1) 106 | }; 107 | 108 | enum { 109 | WILC_MAC_STATUS_INIT = -1, 110 | WILC_MAC_STATUS_DISCONNECTED = 0, 111 | WILC_MAC_STATUS_CONNECTED = 1 112 | }; 113 | 114 | struct wilc_rcvd_net_info { 115 | s8 rssi; 116 | u8 ch; 117 | u16 frame_len; 118 | struct ieee80211_mgmt *mgmt; 119 | }; 120 | 121 | typedef void (*wilc_remain_on_chan_ready)(void *); 122 | 123 | struct wilc_user_scan_req { 124 | void (*scan_result)(enum scan_event evt, 125 | struct wilc_rcvd_net_info *info, void *priv); 126 | void *arg; 127 | u32 ch_cnt; 128 | }; 129 | 130 | struct wilc_conn_info { 131 | u8 bssid[ETH_ALEN]; 132 | u8 security; 133 | enum authtype auth_type; 134 | u8 ch; 135 | u8 *req_ies; 136 | size_t req_ies_len; 137 | u8 *resp_ies; 138 | u16 resp_ies_len; 139 | u16 status; 140 | void (*conn_result)(enum conn_event evt, u8 status, void *priv); 141 | void *arg; 142 | void *param; 143 | }; 144 | 145 | struct wilc_remain_ch { 146 | u16 ch; 147 | u32 duration; 148 | void (*expired)(void *priv, u64 cookie); 149 | void *arg; 150 | u64 cookie; 151 | }; 152 | 153 | struct host_if_drv { 154 | struct wilc_user_scan_req usr_scan_req; 155 | struct wilc_conn_info conn_info; 156 | struct wilc_remain_ch remain_on_ch; 157 | u64 p2p_timeout; 158 | 159 | enum host_if_state hif_state; 160 | 161 | u8 assoc_bssid[ETH_ALEN]; 162 | struct completion comp_test_key_block; 163 | struct completion comp_test_disconn_block; 164 | struct completion comp_get_rssi; 165 | struct completion comp_inactive_time; 166 | 167 | struct timer_list scan_timer; 168 | struct wilc_vif *scan_timer_vif; 169 | 170 | struct timer_list connect_timer; 171 | struct wilc_vif *connect_timer_vif; 172 | 173 | struct timer_list remain_on_ch_timer; 174 | struct wilc_vif *remain_on_ch_timer_vif; 175 | 176 | bool ifc_up; 177 | u8 assoc_resp[WILC_MAX_ASSOC_RESP_FRAME_SIZE]; 178 | }; 179 | 180 | struct wilc_vif; 181 | 182 | signed int wilc_send_buffered_eap(struct wilc_vif *vif, 183 | void (*deliver_to_stack)(struct wilc_vif *, 184 | u8 *, u32, u32, u8), 185 | void (*eap_buf_param)(void *), u8 *buff, 186 | unsigned int size, unsigned int pkt_offset, 187 | void *user_arg); 188 | int wilc_remove_wep_key(struct wilc_vif *vif, u8 index); 189 | int wilc_set_wep_default_keyid(struct wilc_vif *vif, u8 index); 190 | int wilc_add_wep_key_bss_sta(struct wilc_vif *vif, const u8 *key, u8 len, 191 | u8 index); 192 | int wilc_add_wep_key_bss_ap(struct wilc_vif *vif, const u8 *key, u8 len, 193 | u8 index, u8 mode, enum authtype auth_type); 194 | int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len, 195 | const u8 *mac_addr, const u8 *rx_mic, const u8 *tx_mic, 196 | u8 mode, u8 cipher_mode, u8 index); 197 | s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, 198 | u32 *out_val); 199 | int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, 200 | u8 index, u32 key_rsc_len, const u8 *key_rsc, 201 | const u8 *rx_mic, const u8 *tx_mic, u8 mode, 202 | u8 cipher_mode); 203 | int wilc_set_pmkid_info(struct wilc_vif *vif, struct wilc_pmkid_attr *pmkid); 204 | int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr); 205 | int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr); 206 | int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ies, 207 | size_t ies_len); 208 | int wilc_disconnect(struct wilc_vif *vif); 209 | int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); 210 | int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level); 211 | int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, 212 | u8 *ch_freq_list, u8 ch_list_len, 213 | void (*scan_result_fn)(enum scan_event, 214 | struct wilc_rcvd_net_info *, void *), 215 | void *user_arg, struct cfg80211_scan_request *request); 216 | int wilc_hif_set_cfg(struct wilc_vif *vif, 217 | struct cfg_param_attr *cfg_param); 218 | int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler); 219 | int wilc_deinit(struct wilc_vif *vif); 220 | int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, 221 | struct cfg80211_beacon_data *params); 222 | int wilc_del_beacon(struct wilc_vif *vif); 223 | int wilc_add_station(struct wilc_vif *vif, const u8 *mac, 224 | struct station_parameters *params); 225 | int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]); 226 | int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr); 227 | int wilc_edit_station(struct wilc_vif *vif, const u8 *mac, 228 | struct station_parameters *params); 229 | int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout); 230 | int wilc_setup_multicast_filter(struct wilc_vif *vif, u32 enabled, u32 count, 231 | u8 *mc_list); 232 | int wilc_remain_on_channel(struct wilc_vif *vif, u64 cookie, 233 | u32 duration, u16 chan, 234 | void (*expired)(void *, u64), void *user_arg); 235 | int wilc_listen_state_expired(struct wilc_vif *vif, u64 cookie); 236 | void wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg); 237 | int wilc_set_operation_mode(struct wilc_vif *vif, int index, u8 mode, 238 | u8 ifc_id); 239 | int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats); 240 | int wilc_get_vif_idx(struct wilc_vif *vif); 241 | int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power); 242 | int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power); 243 | /*0 select antenna 1 , 2 select antenna mode , 2 allow the firmware to choose 244 | * the best antenna 245 | */ 246 | int wilc_set_antenna(struct wilc_vif *vif, u8 mode); 247 | 248 | void wilc_set_wowlan_trigger(struct wilc_vif *vif, u8 wowlan_trigger); 249 | 250 | extern u8 wilc_initialized; 251 | s32 handle_scan_done(struct wilc_vif *vif, enum scan_event evt); 252 | void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length); 253 | void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length); 254 | void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length); 255 | void *wilc_parse_join_bss_param(struct cfg80211_bss *bss, 256 | struct cfg80211_crypto_settings *crypto); 257 | void handle_connect_cancel(struct wilc_vif *vif); 258 | #endif 259 | -------------------------------------------------------------------------------- /wilc/wilc_wfi_netdevice.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | /* 3 | * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. 4 | * All rights reserved. 5 | */ 6 | 7 | #ifndef WILC_WFI_NETDEVICE 8 | #define WILC_WFI_NETDEVICE 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #if KERNEL_VERSION(3, 13, 0) < LINUX_VERSION_CODE 17 | #include 18 | #else 19 | #include 20 | #include 21 | #endif 22 | 23 | #include "wilc_hif.h" 24 | #include "wilc_wlan.h" 25 | #include "wilc_wlan_cfg.h" 26 | 27 | #define FLOW_CTRL_LOW_THRESHLD 128 28 | #define FLOW_CTRL_UP_THRESHLD 256 29 | 30 | #define WILC_MAX_NUM_PMKIDS 16 31 | #define PMKID_FOUND 1 32 | #define NUM_STA_ASSOCIATED 8 33 | 34 | #define NUM_REG_FRAME 2 35 | 36 | #define TCP_ACK_FILTER_LINK_SPEED_THRESH 54 37 | #define DEFAULT_LINK_SPEED 72 38 | 39 | #define GET_PKT_OFFSET(a) (((a) >> 22) & 0x1ff) 40 | 41 | #define ANT_SWTCH_INVALID_GPIO_CTRL 0 42 | #define ANT_SWTCH_SNGL_GPIO_CTRL 1 43 | #define ANT_SWTCH_DUAL_GPIO_CTRL 2 44 | 45 | struct wilc_wfi_stats { 46 | unsigned long rx_packets; 47 | unsigned long tx_packets; 48 | unsigned long rx_bytes; 49 | unsigned long tx_bytes; 50 | u64 rx_time; 51 | u64 tx_time; 52 | }; 53 | 54 | struct wilc_wfi_key { 55 | u8 *key; 56 | u8 *seq; 57 | int key_len; 58 | int seq_len; 59 | u32 cipher; 60 | }; 61 | 62 | struct wilc_wfi_wep_key { 63 | u8 *key; 64 | u8 key_len; 65 | u8 key_idx; 66 | }; 67 | 68 | struct sta_info { 69 | u8 sta_associated_bss[WILC_MAX_NUM_STA][ETH_ALEN]; 70 | }; 71 | 72 | /*Parameters needed for host interface for remaining on channel*/ 73 | struct wilc_wfi_p2p_listen_params { 74 | struct ieee80211_channel *listen_ch; 75 | u32 listen_duration; 76 | u64 listen_cookie; 77 | }; 78 | 79 | /* Struct to buffer eapol 1/4 frame */ 80 | struct wilc_buffered_eap { 81 | unsigned int size; 82 | unsigned int pkt_offset; 83 | u8 *buff; 84 | }; 85 | 86 | struct wilc_p2p_var { 87 | u8 local_random; 88 | u8 recv_random; 89 | bool is_wilc_ie; 90 | }; 91 | 92 | static const u32 wilc_cipher_suites[] = { 93 | WLAN_CIPHER_SUITE_WEP40, 94 | WLAN_CIPHER_SUITE_WEP104, 95 | WLAN_CIPHER_SUITE_TKIP, 96 | WLAN_CIPHER_SUITE_CCMP, 97 | WLAN_CIPHER_SUITE_AES_CMAC 98 | }; 99 | 100 | #if KERNEL_VERSION(4, 7, 0) > LINUX_VERSION_CODE 101 | #define CHAN2G(_channel, _freq, _flags) { \ 102 | .band = IEEE80211_BAND_2GHZ, \ 103 | .center_freq = (_freq), \ 104 | .hw_value = (_channel), \ 105 | .flags = (_flags), \ 106 | .max_antenna_gain = 0, \ 107 | .max_power = 30, \ 108 | } 109 | #else 110 | #define CHAN2G(_channel, _freq, _flags) { \ 111 | .band = NL80211_BAND_2GHZ, \ 112 | .center_freq = (_freq), \ 113 | .hw_value = (_channel), \ 114 | .flags = (_flags), \ 115 | .max_antenna_gain = 0, \ 116 | .max_power = 30, \ 117 | } 118 | #endif 119 | 120 | static const struct ieee80211_channel wilc_2ghz_channels[] = { 121 | CHAN2G(1, 2412, 0), 122 | CHAN2G(2, 2417, 0), 123 | CHAN2G(3, 2422, 0), 124 | CHAN2G(4, 2427, 0), 125 | CHAN2G(5, 2432, 0), 126 | CHAN2G(6, 2437, 0), 127 | CHAN2G(7, 2442, 0), 128 | CHAN2G(8, 2447, 0), 129 | CHAN2G(9, 2452, 0), 130 | CHAN2G(10, 2457, 0), 131 | CHAN2G(11, 2462, 0), 132 | CHAN2G(12, 2467, 0), 133 | CHAN2G(13, 2472, 0), 134 | CHAN2G(14, 2484, 0) 135 | }; 136 | 137 | #define RATETAB_ENT(_rate, _hw_value, _flags) { \ 138 | .bitrate = (_rate), \ 139 | .hw_value = (_hw_value), \ 140 | .flags = (_flags), \ 141 | } 142 | 143 | static struct ieee80211_rate wilc_bitrates[] = { 144 | RATETAB_ENT(10, 0, 0), 145 | RATETAB_ENT(20, 1, 0), 146 | RATETAB_ENT(55, 2, 0), 147 | RATETAB_ENT(110, 3, 0), 148 | RATETAB_ENT(60, 9, 0), 149 | RATETAB_ENT(90, 6, 0), 150 | RATETAB_ENT(120, 7, 0), 151 | RATETAB_ENT(180, 8, 0), 152 | RATETAB_ENT(240, 9, 0), 153 | RATETAB_ENT(360, 10, 0), 154 | RATETAB_ENT(480, 11, 0), 155 | RATETAB_ENT(540, 12, 0) 156 | }; 157 | 158 | struct wilc_priv { 159 | struct wireless_dev wdev; 160 | struct cfg80211_scan_request *scan_req; 161 | struct wilc_wfi_p2p_listen_params remain_on_ch_params; 162 | u64 tx_cookie; 163 | bool cfg_scanning; 164 | u8 associated_bss[ETH_ALEN]; 165 | struct sta_info assoc_stainfo; 166 | struct sk_buff *skb; 167 | struct net_device *dev; //TODO:need to remove it 168 | struct host_if_drv *hif_drv; 169 | struct wilc_pmkid_attr pmkid_list; 170 | u8 wep_key[4][WLAN_KEY_LEN_WEP104]; 171 | u8 wep_key_len[4]; 172 | /* The real interface that the monitor is on */ 173 | struct net_device *real_ndev; 174 | struct wilc_wfi_key *wilc_gtk[WILC_MAX_NUM_STA]; 175 | struct wilc_wfi_key *wilc_ptk[WILC_MAX_NUM_STA]; 176 | u8 wilc_groupkey; 177 | 178 | struct mutex scan_req_lock; 179 | 180 | struct wilc_buffered_eap *buffered_eap; 181 | 182 | struct timer_list eap_buff_timer; 183 | int scanned_cnt; 184 | struct wilc_p2p_var p2p; 185 | u64 inc_roc_cookie; 186 | }; 187 | 188 | struct frame_reg { 189 | u16 type; 190 | bool reg; 191 | }; 192 | 193 | #define MAX_TCP_SESSION 25 194 | #define MAX_PENDING_ACKS 256 195 | 196 | struct ack_session_info { 197 | u32 seq_num; 198 | u32 bigger_ack_num; 199 | u16 src_port; 200 | u16 dst_port; 201 | u16 status; 202 | }; 203 | 204 | struct pending_acks { 205 | u32 ack_num; 206 | u32 session_index; 207 | struct txq_entry_t *txqe; 208 | }; 209 | 210 | struct tcp_ack_filter { 211 | struct ack_session_info ack_session_info[2 * MAX_TCP_SESSION]; 212 | struct pending_acks pending_acks[MAX_PENDING_ACKS]; 213 | u32 pending_base; 214 | u32 tcp_session; 215 | u32 pending_acks_idx; 216 | bool enabled; 217 | }; 218 | 219 | struct sysfs_attr_group { 220 | bool p2p_mode; 221 | u8 ant_swtch_mode; 222 | u8 antenna1; 223 | u8 antenna2; 224 | }; 225 | 226 | struct wilc_vif { 227 | u8 idx; 228 | u8 iftype; 229 | int monitor_flag; 230 | int mac_opened; 231 | struct frame_reg frame_reg[NUM_REG_FRAME]; 232 | struct net_device_stats netstats; 233 | struct wilc *wilc; 234 | u8 bssid[ETH_ALEN]; 235 | struct host_if_drv *hif_drv; 236 | struct net_device *ndev; 237 | 238 | struct rf_info periodic_stats; 239 | struct timer_list periodic_rssi; 240 | struct tcp_ack_filter ack_filter; 241 | bool connecting; 242 | struct wilc_priv priv; 243 | struct list_head list; 244 | u8 restart; 245 | bool p2p_listen_state; 246 | struct cfg80211_bss *bss; 247 | }; 248 | 249 | struct wilc { 250 | struct wiphy *wiphy; 251 | const struct wilc_hif_func *hif_func; 252 | int io_type; 253 | s8 mac_status; 254 | #if KERNEL_VERSION(3, 13, 0) < LINUX_VERSION_CODE 255 | struct gpio_desc *gpio_irq; 256 | #else 257 | int gpio_irq; 258 | #endif 259 | struct clk *rtc_clk; 260 | bool initialized; 261 | int dev_irq_num; 262 | int close; 263 | u8 vif_num; 264 | struct list_head vif_list; 265 | struct srcu_struct srcu; 266 | /*protect vif list queue*/ 267 | struct mutex vif_mutex; 268 | u8 open_ifcs; 269 | /*protect head of transmit queue*/ 270 | struct mutex txq_add_to_head_cs; 271 | /*protect txq_entry_t transmit queue*/ 272 | spinlock_t txq_spinlock; 273 | /*protect rxq_entry_t receiver queue*/ 274 | struct mutex rxq_cs; 275 | /* lock to protect hif access */ 276 | struct mutex hif_cs; 277 | 278 | struct completion cfg_event; 279 | struct completion sync_event; 280 | struct completion txq_event; 281 | struct completion txq_thread_started; 282 | struct completion debug_thread_started; 283 | struct task_struct *txq_thread; 284 | struct task_struct *debug_thread; 285 | 286 | int quit; 287 | /* lock to protect issue of wid command to fw */ 288 | struct mutex cfg_cmd_lock; 289 | struct wilc_cfg_frame cfg_frame; 290 | u32 cfg_frame_offset; 291 | u8 cfg_seq_no; 292 | 293 | u8 *rx_buffer; 294 | u32 rx_buffer_offset; 295 | u8 *tx_buffer; 296 | 297 | struct txq_handle txq[NQUEUES]; 298 | int txq_entries; 299 | 300 | struct rxq_entry_t rxq_head; 301 | 302 | const struct firmware *firmware; 303 | 304 | struct device *dev; 305 | struct device *dt_dev; 306 | 307 | enum wilc_chip_type chip; 308 | 309 | uint8_t power_status[DEV_MAX]; 310 | uint8_t keep_awake[DEV_MAX]; 311 | struct mutex cs; 312 | struct workqueue_struct *hif_workqueue; 313 | 314 | struct wilc_cfg cfg; 315 | void *bus_data; 316 | struct net_device *monitor_dev; 317 | /* deinit lock */ 318 | struct mutex deinit_lock; 319 | u8 sta_ch; 320 | u8 op_ch; 321 | struct sysfs_attr_group attr_sysfs; 322 | struct ieee80211_channel channels[ARRAY_SIZE(wilc_2ghz_channels)]; 323 | struct ieee80211_rate bitrates[ARRAY_SIZE(wilc_bitrates)]; 324 | struct ieee80211_supported_band band; 325 | u32 cipher_suites[ARRAY_SIZE(wilc_cipher_suites)]; 326 | }; 327 | 328 | struct wilc_wfi_mon_priv { 329 | struct net_device *real_ndev; 330 | }; 331 | 332 | void wilc_frmw_to_host(struct wilc_vif *vif, u8 *buff, u32 size, 333 | u32 pkt_offset, u8 status); 334 | void wilc_mac_indicate(struct wilc *wilc); 335 | void wilc_netdev_cleanup(struct wilc *wilc); 336 | void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size); 337 | void wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid, u8 mode); 338 | 339 | #endif 340 | -------------------------------------------------------------------------------- /wilc/wilc_mon.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | /* 3 | * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. 4 | * All rights reserved. 5 | */ 6 | 7 | #include 8 | 9 | #include "wilc_netdev.h" 10 | #include "wilc_wfi_cfgoperations.h" 11 | 12 | struct wfi_rtap_hdr { 13 | struct ieee80211_radiotap_header hdr; 14 | u8 rate; 15 | } __packed; 16 | 17 | struct wfi_rtap_cb_hdr { 18 | struct ieee80211_radiotap_header hdr; 19 | u8 rate; 20 | u8 dump; 21 | u16 tx_flags; 22 | } __packed; 23 | 24 | #define TX_RADIOTAP_PRESENT ((1 << IEEE80211_RADIOTAP_RATE) | \ 25 | (1 << IEEE80211_RADIOTAP_TX_FLAGS)) 26 | 27 | void wilc_wfi_handle_monitor_rx(struct wilc *wilc, u8 *buff, u32 size) 28 | { 29 | struct wilc_vif *vif = 0; 30 | struct sk_buff *skb = NULL; 31 | struct wfi_rtap_hdr *hdr; 32 | 33 | vif = wilc_get_vif_from_type(wilc, WILC_MONITOR_MODE); 34 | if (!vif) { 35 | PRINT_D(vif->ndev, HOSTAPD_DBG, "Monitor interface not up\n"); 36 | return; 37 | } 38 | 39 | skb = dev_alloc_skb(size + sizeof(*hdr)); 40 | if (!skb) { 41 | PRINT_D(vif->ndev, HOSTAPD_DBG, 42 | "Monitor if: No memory to allocate skb"); 43 | return; 44 | } 45 | #if KERNEL_VERSION(4, 13, 0) <= LINUX_VERSION_CODE 46 | skb_put_data(skb, buff, size); 47 | hdr = skb_push(skb, sizeof(*hdr)); 48 | #else 49 | memcpy(skb_put(skb, size), buff, size); 50 | hdr = (struct wfi_rtap_hdr *)skb_push(skb, sizeof(*hdr)); 51 | #endif 52 | memset(hdr, 0, sizeof(*hdr)); 53 | hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */ 54 | hdr->hdr.it_len = cpu_to_le16(sizeof(*hdr)); 55 | PRINT_D(vif->ndev, HOSTAPD_DBG, 56 | "Radiotap len %d\n", hdr->hdr.it_len); 57 | hdr->hdr.it_present = cpu_to_le32 58 | (1 << IEEE80211_RADIOTAP_RATE); /* | */ 59 | PRINT_D(vif->ndev, HOSTAPD_DBG, "Presentflags %d\n", 60 | hdr->hdr.it_present); 61 | hdr->rate = 5; /* txrate->bitrate / 5; */ 62 | skb->dev = vif->ndev; 63 | skb_reset_mac_header(skb); 64 | skb->ip_summed = CHECKSUM_UNNECESSARY; 65 | skb->pkt_type = PACKET_OTHERHOST; 66 | skb->protocol = htons(ETH_P_802_2); 67 | memset(skb->cb, 0, sizeof(skb->cb)); 68 | netif_rx(skb); 69 | } 70 | 71 | void wilc_wfi_monitor_rx(struct net_device *mon_dev, u8 *buff, u32 size) 72 | { 73 | u32 header, pkt_offset; 74 | struct sk_buff *skb = NULL; 75 | struct wfi_rtap_hdr *hdr; 76 | struct wfi_rtap_cb_hdr *cb_hdr; 77 | 78 | if (!mon_dev) 79 | return; 80 | 81 | if (!netif_running(mon_dev)) { 82 | PRINT_D(mon_dev, HOSTAPD_DBG, 83 | "Monitor interface already RUNNING\n"); 84 | return; 85 | } 86 | 87 | /* Get WILC header */ 88 | header = get_unaligned_le32(buff - HOST_HDR_OFFSET); 89 | /* 90 | * The packet offset field contain info about what type of management 91 | * the frame we are dealing with and ack status 92 | */ 93 | pkt_offset = GET_PKT_OFFSET(header); 94 | 95 | if (pkt_offset & IS_MANAGMEMENT_CALLBACK) { 96 | /* hostapd callback mgmt frame */ 97 | 98 | skb = dev_alloc_skb(size + sizeof(*cb_hdr)); 99 | if (!skb) { 100 | PRINT_D(mon_dev, HOSTAPD_DBG, 101 | "Monitor if : No memory to allocate skb"); 102 | return; 103 | } 104 | #if KERNEL_VERSION(4, 13, 0) <= LINUX_VERSION_CODE 105 | skb_put_data(skb, buff, size); 106 | 107 | cb_hdr = skb_push(skb, sizeof(*cb_hdr)); 108 | #else 109 | memcpy(skb_put(skb, size), buff, size); 110 | cb_hdr = (struct wfi_rtap_cb_hdr *)skb_push(skb, 111 | sizeof(*cb_hdr)); 112 | #endif 113 | memset(cb_hdr, 0, sizeof(*cb_hdr)); 114 | 115 | cb_hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */ 116 | 117 | cb_hdr->hdr.it_len = cpu_to_le16(sizeof(*cb_hdr)); 118 | 119 | cb_hdr->hdr.it_present = cpu_to_le32(TX_RADIOTAP_PRESENT); 120 | 121 | cb_hdr->rate = 5; 122 | 123 | if (pkt_offset & IS_MGMT_STATUS_SUCCES) { 124 | /* success */ 125 | cb_hdr->tx_flags = IEEE80211_RADIOTAP_F_TX_RTS; 126 | } else { 127 | cb_hdr->tx_flags = IEEE80211_RADIOTAP_F_TX_FAIL; 128 | } 129 | 130 | } else { 131 | skb = dev_alloc_skb(size + sizeof(*hdr)); 132 | 133 | if (!skb) { 134 | PRINT_D(mon_dev, HOSTAPD_DBG, 135 | "Monitor if : No memory to allocate skb"); 136 | return; 137 | } 138 | #if KERNEL_VERSION(4, 13, 0) <= LINUX_VERSION_CODE 139 | skb_put_data(skb, buff, size); 140 | hdr = skb_push(skb, sizeof(*hdr)); 141 | #else 142 | memcpy(skb_put(skb, size), buff, size); 143 | hdr = (struct wfi_rtap_hdr *)skb_push(skb, 144 | sizeof(*hdr)); 145 | #endif 146 | memset(hdr, 0, sizeof(*hdr)); 147 | hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */ 148 | hdr->hdr.it_len = cpu_to_le16(sizeof(*hdr)); 149 | PRINT_D(mon_dev, HOSTAPD_DBG, 150 | "Radiotap len %d\n", hdr->hdr.it_len); 151 | hdr->hdr.it_present = cpu_to_le32 152 | (1 << IEEE80211_RADIOTAP_RATE); /* | */ 153 | PRINT_D(mon_dev, HOSTAPD_DBG, "Presentflags %d\n", 154 | hdr->hdr.it_present); 155 | hdr->rate = 5; 156 | } 157 | 158 | skb->dev = mon_dev; 159 | skb_reset_mac_header(skb); 160 | skb->ip_summed = CHECKSUM_UNNECESSARY; 161 | skb->pkt_type = PACKET_OTHERHOST; 162 | skb->protocol = htons(ETH_P_802_2); 163 | memset(skb->cb, 0, sizeof(skb->cb)); 164 | 165 | netif_rx(skb); 166 | } 167 | 168 | struct tx_complete_mon_data { 169 | int size; 170 | void *buff; 171 | }; 172 | 173 | static void mgmt_tx_complete(void *priv, int status) 174 | { 175 | struct tx_complete_mon_data *pv_data = priv; 176 | u8 *buf = pv_data->buff; 177 | 178 | if (status == 1) { 179 | if (buf[0] == 0x10 || buf[0] == 0xb0) 180 | pr_info("Packet sent Size = %d Add = %p.\n", 181 | pv_data->size, pv_data->buff); 182 | } else { 183 | pr_info("Couldn't send packet Size = %d Add = %p.\n", 184 | pv_data->size, pv_data->buff); 185 | } 186 | /* 187 | * in case of fully hosting mode, the freeing will be done 188 | * in response to the cfg packet 189 | */ 190 | kfree(pv_data->buff); 191 | 192 | kfree(pv_data); 193 | } 194 | 195 | static int mon_mgmt_tx(struct net_device *dev, const u8 *buf, size_t len) 196 | { 197 | struct tx_complete_mon_data *mgmt_tx = NULL; 198 | 199 | if (!dev) { 200 | PRINT_ER(dev, "ERROR: dev == NULL\n"); 201 | return -EFAULT; 202 | } 203 | 204 | netif_stop_queue(dev); 205 | mgmt_tx = kmalloc(sizeof(*mgmt_tx), GFP_ATOMIC); 206 | if (!mgmt_tx) { 207 | PRINT_ER(dev, 208 | "Failed to allocate memory for mgmt_tx structure\n"); 209 | return -ENOMEM; 210 | } 211 | 212 | mgmt_tx->buff = kmemdup(buf, len, GFP_ATOMIC); 213 | if (!mgmt_tx->buff) { 214 | kfree(mgmt_tx); 215 | return -ENOMEM; 216 | } 217 | 218 | mgmt_tx->size = len; 219 | 220 | txq_add_mgmt_pkt(dev, mgmt_tx, mgmt_tx->buff, mgmt_tx->size, 221 | mgmt_tx_complete); 222 | 223 | netif_wake_queue(dev); 224 | return 0; 225 | } 226 | 227 | static netdev_tx_t wilc_wfi_mon_xmit(struct sk_buff *skb, 228 | struct net_device *dev) 229 | { 230 | u32 rtap_len, ret = 0; 231 | struct wilc_wfi_mon_priv *mon_priv; 232 | u8 srcadd[ETH_ALEN]; 233 | u8 bssid[ETH_ALEN]; 234 | 235 | mon_priv = netdev_priv(dev); 236 | if (!mon_priv) { 237 | PRINT_ER(dev, "Monitor interface private structure is NULL\n"); 238 | return -EFAULT; 239 | } 240 | rtap_len = ieee80211_get_radiotap_len(skb->data); 241 | if (skb->len < rtap_len) { 242 | PRINT_ER(dev, "Error in radiotap header\n"); 243 | return -1; 244 | } 245 | 246 | skb_pull(skb, rtap_len); 247 | 248 | skb->dev = mon_priv->real_ndev; 249 | 250 | PRINT_D(dev, HOSTAPD_DBG, "Skipping the radiotap header\n"); 251 | PRINT_D(dev, HOSTAPD_DBG, "SKB netdevice name = %s\n", skb->dev->name); 252 | PRINT_D(dev, HOSTAPD_DBG, "MONITOR real dev name = %s\n", 253 | mon_priv->real_ndev->name); 254 | ether_addr_copy(srcadd, &skb->data[10]); 255 | ether_addr_copy(bssid, &skb->data[16]); 256 | /* 257 | * Identify if data or mgmt packet, if source address and bssid 258 | * fields are equal send it to mgmt frames handler 259 | */ 260 | if (!(memcmp(srcadd, bssid, 6))) { 261 | ret = mon_mgmt_tx(mon_priv->real_ndev, skb->data, skb->len); 262 | if (ret) 263 | PRINT_ER(dev, "fail to mgmt tx\n"); 264 | dev_kfree_skb(skb); 265 | } else { 266 | ret = wilc_mac_xmit(skb, mon_priv->real_ndev); 267 | } 268 | 269 | return ret; 270 | } 271 | 272 | static const struct net_device_ops wilc_wfi_netdev_ops = { 273 | .ndo_start_xmit = wilc_wfi_mon_xmit, 274 | 275 | }; 276 | 277 | struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl, 278 | const char *name, 279 | struct net_device *real_dev) 280 | { 281 | struct wilc_wfi_mon_priv *priv; 282 | 283 | /*If monitor interface is already initialized, return it*/ 284 | if (wl->monitor_dev) 285 | return wl->monitor_dev; 286 | 287 | wl->monitor_dev = alloc_etherdev(sizeof(struct wilc_wfi_mon_priv)); 288 | if (!wl->monitor_dev) { 289 | PRINT_ER(real_dev, "failed to allocate memory\n"); 290 | return NULL; 291 | } 292 | wl->monitor_dev->type = ARPHRD_IEEE80211_RADIOTAP; 293 | strncpy(wl->monitor_dev->name, name, IFNAMSIZ); 294 | wl->monitor_dev->name[IFNAMSIZ - 1] = 0; 295 | wl->monitor_dev->netdev_ops = &wilc_wfi_netdev_ops; 296 | #if KERNEL_VERSION(4, 11, 9) <= LINUX_VERSION_CODE 297 | wl->monitor_dev->needs_free_netdev = true; 298 | #else 299 | wl->monitor_dev->destructor = free_netdev; 300 | #endif 301 | if (register_netdevice(wl->monitor_dev)) { 302 | PRINT_ER(real_dev, "register_netdevice failed\n"); 303 | return NULL; 304 | } 305 | priv = netdev_priv(wl->monitor_dev); 306 | if (!priv) { 307 | PRINT_ER(real_dev, "private structure is NULL\n"); 308 | return NULL; 309 | } 310 | 311 | priv->real_ndev = real_dev; 312 | 313 | return wl->monitor_dev; 314 | } 315 | 316 | void wilc_wfi_deinit_mon_interface(struct wilc *wl, bool rtnl_locked) 317 | { 318 | if (!wl->monitor_dev) 319 | return; 320 | 321 | PRINT_INFO(wl->monitor_dev, HOSTAPD_DBG, 322 | "In Deinit monitor interface\n"); 323 | PRINT_INFO(wl->monitor_dev, HOSTAPD_DBG, "Unregister monitor netdev\n"); 324 | if (rtnl_locked) 325 | unregister_netdevice(wl->monitor_dev); 326 | else 327 | unregister_netdev(wl->monitor_dev); 328 | PRINT_INFO(wl->monitor_dev, HOSTAPD_DBG, 329 | "Deinit monitor interface done\n"); 330 | wl->monitor_dev = NULL; 331 | } 332 | -------------------------------------------------------------------------------- /wilc/wilc_wlan.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | /* 3 | * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. 4 | * All rights reserved. 5 | */ 6 | 7 | #ifndef WILC_WLAN_H 8 | #define WILC_WLAN_H 9 | 10 | #include 11 | #include 12 | 13 | static inline bool is_wilc1000(u32 id) 14 | { 15 | return (id & 0xfffff000) == 0x100000; 16 | } 17 | 18 | static inline bool is_wilc3000(u32 id) 19 | { 20 | return (id & 0xfffff000) == 0x300000; 21 | } 22 | 23 | /******************************************** 24 | * 25 | * Mac eth header length 26 | * 27 | ********************************************/ 28 | #define MAX_MAC_HDR_LEN 26 /* QOS_MAC_HDR_LEN */ 29 | #define SUB_MSDU_HEADER_LENGTH 14 30 | #define SNAP_HDR_LEN 8 31 | #define ETHERNET_HDR_LEN 14 32 | #define WORD_ALIGNMENT_PAD 0 33 | 34 | #define ETH_ETHERNET_HDR_OFFSET (MAX_MAC_HDR_LEN + \ 35 | SUB_MSDU_HEADER_LENGTH + \ 36 | SNAP_HDR_LEN - \ 37 | ETHERNET_HDR_LEN + \ 38 | WORD_ALIGNMENT_PAD) 39 | 40 | #define HOST_HDR_OFFSET 4 41 | #define ETHERNET_HDR_LEN 14 42 | #define IP_HDR_LEN 20 43 | #define IP_HDR_OFFSET ETHERNET_HDR_LEN 44 | #define UDP_HDR_OFFSET (IP_HDR_LEN + IP_HDR_OFFSET) 45 | #define UDP_HDR_LEN 8 46 | #define UDP_DATA_OFFSET (UDP_HDR_OFFSET + UDP_HDR_LEN) 47 | #define ETH_CONFIG_PKT_HDR_LEN UDP_DATA_OFFSET 48 | 49 | #define ETH_CONFIG_PKT_HDR_OFFSET (ETH_ETHERNET_HDR_OFFSET + \ 50 | ETH_CONFIG_PKT_HDR_LEN) 51 | #define PKT_STATUS_NEW 0 52 | #define PKT_STATUS_BUFFERED 1 53 | 54 | /******************************************** 55 | * 56 | * Register Defines 57 | * 58 | ********************************************/ 59 | #define WILC_PERIPH_REG_BASE 0x1000 60 | #define WILC_CHIPID WILC_PERIPH_REG_BASE 61 | #define WILC_GLB_RESET_0 (WILC_PERIPH_REG_BASE + 0x400) 62 | #define WILC_PIN_MUX_0 (WILC_PERIPH_REG_BASE + 0x408) 63 | #define WILC_HOST_TX_CTRL (WILC_PERIPH_REG_BASE + 0x6c) 64 | #define WILC_HOST_RX_CTRL_0 (WILC_PERIPH_REG_BASE + 0x70) 65 | #define WILC_HOST_RX_CTRL_1 (WILC_PERIPH_REG_BASE + 0x74) 66 | #define WILC_HOST_VMM_CTL (WILC_PERIPH_REG_BASE + 0x78) 67 | #define WILC_HOST_RX_CTRL (WILC_PERIPH_REG_BASE + 0x80) 68 | #define WILC_HOST_RX_EXTRA_SIZE (WILC_PERIPH_REG_BASE + 0x84) 69 | #define WILC_HOST_TX_CTRL_1 (WILC_PERIPH_REG_BASE + 0x88) 70 | #define WILC_INTERRUPT_CORTUS_0 (WILC_PERIPH_REG_BASE + 0xa8) 71 | #define WILC_MISC (WILC_PERIPH_REG_BASE + 0x428) 72 | #define WILC_INTR_REG_BASE (WILC_PERIPH_REG_BASE + 0xa00) 73 | #define WILC_INTR_ENABLE WILC_INTR_REG_BASE 74 | #define WILC_INTR2_ENABLE (WILC_INTR_REG_BASE + 4) 75 | 76 | #define WILC_INTR_POLARITY (WILC_INTR_REG_BASE + 0x10) 77 | #define WILC_INTR_TYPE (WILC_INTR_REG_BASE + 0x20) 78 | #define WILC_INTR_CLEAR (WILC_INTR_REG_BASE + 0x30) 79 | #define WILC_INTR_STATUS (WILC_INTR_REG_BASE + 0x40) 80 | 81 | #define WILC_VMM_TBL_SIZE 64 82 | #define WILC_VMM_TX_TBL_BASE 0x150400 83 | #define WILC_VMM_RX_TBL_BASE 0x150500 84 | 85 | #define WILC_VMM_BASE 0x150000 86 | #define WILC_VMM_CORE_CTL WILC_VMM_BASE 87 | #define WILC_VMM_TBL_CTL (WILC_VMM_BASE + 0x4) 88 | #define WILC_VMM_TBL_ENTRY (WILC_VMM_BASE + 0x8) 89 | #define WILC_VMM_TBL0_SIZE (WILC_VMM_BASE + 0xc) 90 | #define WILC_VMM_TO_HOST_SIZE (WILC_VMM_BASE + 0x10) 91 | #define WILC_VMM_CORE_CFG (WILC_VMM_BASE + 0x14) 92 | #define WILC_VMM_TBL_ACTIVE (WILC_VMM_BASE + 040) 93 | #define WILC_VMM_TBL_STATUS (WILC_VMM_BASE + 0x44) 94 | 95 | #define WILC_SPI_REG_BASE 0xe800 96 | #define WILC_SPI_CTL WILC_SPI_REG_BASE 97 | #define WILC_SPI_MASTER_DMA_ADDR (WILC_SPI_REG_BASE + 0x4) 98 | #define WILC_SPI_MASTER_DMA_COUNT (WILC_SPI_REG_BASE + 0x8) 99 | #define WILC_SPI_SLAVE_DMA_ADDR (WILC_SPI_REG_BASE + 0xc) 100 | #define WILC_SPI_SLAVE_DMA_COUNT (WILC_SPI_REG_BASE + 0x10) 101 | #define WILC_SPI_TX_MODE (WILC_SPI_REG_BASE + 0x20) 102 | #define WILC_SPI_PROTOCOL_CONFIG (WILC_SPI_REG_BASE + 0x24) 103 | #define WILC_SPI_INTR_CTL (WILC_SPI_REG_BASE + 0x2c) 104 | 105 | #define WILC_SPI_PROTOCOL_OFFSET (WILC_SPI_PROTOCOL_CONFIG - \ 106 | WILC_SPI_REG_BASE) 107 | 108 | #define WILC_AHB_DATA_MEM_BASE 0x30000 109 | #define WILC_AHB_SHARE_MEM_BASE 0xd0000 110 | 111 | #define VMM_TBL_RX_SHADOW_BASE WILC_AHB_SHARE_MEM_BASE 112 | #define VMM_TBL_RX_SHADOW_SIZE 256 113 | 114 | #define WILC_FW_HOST_COMM 0x13c0 115 | #define WILC_GP_REG_0 0x149c 116 | #define WILC_GP_REG_1 0x14a0 117 | 118 | #define WILC_COEXIST_CTL 0x161E00 119 | #define GLOBAL_MODE_CONTROL 0x1614 120 | #define PWR_SEQ_MISC_CTRL 0x3008 121 | #define COE_AUTO_PS_ON_NULL_PKT 0x160468 122 | #define COE_AUTO_PS_OFF_NULL_PKT 0x16046C 123 | #define CCA_CTL_2 (0x160EF4) 124 | #define CCA_CTL_7 (0x160F08) 125 | 126 | #define WILC_HAVE_SDIO_IRQ_GPIO BIT(0) 127 | #define WILC_HAVE_SLEEP_CLK_SRC_RTC BIT(2) 128 | #define WILC_HAVE_SLEEP_CLK_SRC_XO BIT(3) 129 | 130 | /******************************************** 131 | * 132 | * Wlan Defines 133 | * 134 | ********************************************/ 135 | #define WILC_CFG_PKT 1 136 | #define WILC_NET_PKT 0 137 | #define WILC_MGMT_PKT 2 138 | 139 | #define WILC_CFG_SET 1 140 | #define WILC_CFG_QUERY 0 141 | 142 | #define WILC_CFG_RSP 1 143 | #define WILC_CFG_RSP_STATUS 2 144 | #define WILC_CFG_RSP_SCAN 3 145 | #define WILC_ABORT_REQ_BIT BIT(31) 146 | 147 | #define WILC_RX_BUFF_SIZE (96 * 1024) 148 | #define WILC_TX_BUFF_SIZE (64 * 1024) 149 | 150 | #define MODALIAS "WILC_SPI" 151 | #define GPIO_NUM 0x5B 152 | #define GPIO_NUM_CHIP_EN 94 153 | #define GPIO_NUM_RESET 60 154 | 155 | #define NQUEUES 4 156 | #define VO_AC_COUNT_POS 25 157 | #define VO_AC_ACM_STAT_POS 24 158 | #define VI_AC_COUNT_POS 17 159 | #define VI_AC_ACM_STAT_POS 16 160 | #define BE_AC_COUNT_POS 9 161 | #define BE_AC_ACM_STAT_POS 8 162 | #define BK_AC_COUNT_POS 2 163 | #define BK_AC_ACM_STAT_POS 1 164 | #define AC_BUFFER_SIZE 1000 165 | /*******************************************/ 166 | /* E0 and later Interrupt flags. */ 167 | /*******************************************/ 168 | /*******************************************/ 169 | /* E0 and later Interrupt flags. */ 170 | /* IRQ Status word */ 171 | /* 15:0 = DMA count in words. */ 172 | /* 16: INT0 flag */ 173 | /* 17: INT1 flag */ 174 | /* 18: INT2 flag */ 175 | /* 19: INT3 flag */ 176 | /* 20: INT4 flag */ 177 | /* 21: INT5 flag */ 178 | /*******************************************/ 179 | #define IRG_FLAGS_OFFSET 16 180 | #define IRQ_DMA_WD_CNT_MASK ((1ul << IRG_FLAGS_OFFSET) - 1) 181 | #define INT_0 BIT(IRG_FLAGS_OFFSET) 182 | #define INT_1 BIT(IRG_FLAGS_OFFSET + 1) 183 | #define INT_2 BIT(IRG_FLAGS_OFFSET + 2) 184 | #define INT_3 BIT(IRG_FLAGS_OFFSET + 3) 185 | #define INT_4 BIT(IRG_FLAGS_OFFSET + 4) 186 | #define MAX_NUM_INT 5 187 | 188 | /*******************************************/ 189 | /* E0 and later Interrupt flags. */ 190 | /* IRQ Clear word */ 191 | /* 0: Clear INT0 */ 192 | /* 1: Clear INT1 */ 193 | /* 2: Clear INT2 */ 194 | /* 3: Clear INT3 */ 195 | /* 4: Clear INT4 */ 196 | /* 5: Clear INT5 */ 197 | /* 6: Select VMM table 1 */ 198 | /* 7: Select VMM table 2 */ 199 | /* 8: Enable VMM */ 200 | /*******************************************/ 201 | #define CLR_INT0 BIT(0) 202 | #define CLR_INT1 BIT(1) 203 | #define CLR_INT2 BIT(2) 204 | #define CLR_INT3 BIT(3) 205 | #define CLR_INT4 BIT(4) 206 | #define CLR_INT5 BIT(5) 207 | #define SEL_VMM_TBL0 BIT(6) 208 | #define SEL_VMM_TBL1 BIT(7) 209 | #define EN_VMM BIT(8) 210 | 211 | #define DATA_INT_EXT INT_0 212 | #define ALL_INT_EXT (DATA_INT_EXT) 213 | #define NUM_INT_EXT 1 214 | 215 | #define DATA_INT_CLR CLR_INT0 216 | 217 | #define ENABLE_RX_VMM (SEL_VMM_TBL1 | EN_VMM) 218 | #define ENABLE_TX_VMM (SEL_VMM_TBL0 | EN_VMM) 219 | /*time for expiring the completion of cfg packets*/ 220 | #define WILC_CFG_PKTS_TIMEOUT msecs_to_jiffies(3000) 221 | 222 | #define IS_MANAGMEMENT 0x100 223 | #define IS_MANAGMEMENT_CALLBACK 0x080 224 | #define IS_MGMT_STATUS_SUCCES 0x040 225 | #define IS_MON_PKT 0x020 226 | 227 | /******************************************** 228 | * 229 | * Tx/Rx Queue Structure 230 | * 231 | ********************************************/ 232 | 233 | enum ip_pkt_priority { 234 | AC_VO_Q = 0, 235 | AC_VI_Q = 1, 236 | AC_BE_Q = 2, 237 | AC_BK_Q = 3 238 | }; 239 | 240 | struct txq_entry_t { 241 | struct list_head list; 242 | int type; 243 | u8 q_num; 244 | int ack_idx; 245 | u8 *buffer; 246 | int buffer_size; 247 | void *priv; 248 | int status; 249 | struct wilc_vif *vif; 250 | void (*tx_complete_func)(void *priv, int status); 251 | }; 252 | 253 | struct txq_handle { 254 | struct txq_entry_t txq_head; 255 | u16 count; 256 | u8 acm; 257 | }; 258 | 259 | struct rxq_entry_t { 260 | struct list_head list; 261 | u8 *buffer; 262 | int buffer_size; 263 | }; 264 | 265 | enum wilc_chip_type { 266 | WILC_1000, 267 | WILC_3000, 268 | }; 269 | 270 | /******************************************** 271 | * 272 | * Host IF Structure 273 | * 274 | ********************************************/ 275 | struct wilc; 276 | struct wilc_hif_func { 277 | int (*hif_init)(struct wilc *wilc, bool resume); 278 | int (*hif_deinit)(struct wilc *wilc); 279 | int (*hif_read_reg)(struct wilc *wilc, u32 addr, u32 *data); 280 | int (*hif_write_reg)(struct wilc *wilc, u32 addr, u32 data); 281 | int (*hif_block_rx)(struct wilc *wilc, u32 addr, u8 *buf, u32 size); 282 | int (*hif_block_tx)(struct wilc *wilc, u32 addr, u8 *buf, u32 size); 283 | int (*hif_read_int)(struct wilc *wilc, u32 *int_status); 284 | int (*hif_clear_int_ext)(struct wilc *wilc, u32 val); 285 | int (*hif_read_size)(struct wilc *wilc, u32 *size); 286 | int (*hif_block_tx_ext)(struct wilc *wilc, u32 addr, u8 *buf, u32 size); 287 | int (*hif_block_rx_ext)(struct wilc *wilc, u32 addr, u8 *buf, u32 size); 288 | int (*hif_sync_ext)(struct wilc *wilc, int nint); 289 | int (*enable_interrupt)(struct wilc *nic); 290 | void (*disable_interrupt)(struct wilc *nic); 291 | int (*hif_reset)(struct wilc *wilc); 292 | bool (*hif_is_init)(struct wilc *wilc); 293 | }; 294 | 295 | #define WILC_MAX_CFG_FRAME_SIZE 1468 296 | 297 | struct tx_complete_data { 298 | int size; 299 | void *buff; 300 | struct sk_buff *skb; 301 | struct wilc_vif *vif; 302 | }; 303 | 304 | struct wilc_cfg_cmd_hdr { 305 | u8 cmd_type; 306 | u8 seq_no; 307 | __le16 total_len; 308 | __le32 driver_handler; 309 | }; 310 | 311 | struct wilc_cfg_frame { 312 | struct wilc_cfg_cmd_hdr hdr; 313 | u8 frame[WILC_MAX_CFG_FRAME_SIZE]; 314 | }; 315 | 316 | struct wilc_cfg_rsp { 317 | u8 type; 318 | u8 seq_no; 319 | }; 320 | 321 | struct wilc; 322 | struct wilc_vif; 323 | 324 | int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, 325 | u32 buffer_size); 326 | int wilc_wlan_start(struct wilc *wilc); 327 | int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif); 328 | int txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer, 329 | u32 buffer_size, 330 | void (*tx_complete_fn)(void *, int)); 331 | int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count); 332 | void wilc_handle_isr(struct wilc *wilc); 333 | void wilc_wlan_cleanup(struct net_device *dev); 334 | int cfg_set(struct wilc_vif *vif, int start, u16 wid, u8 *buffer, 335 | u32 buffer_size, int commit, u32 drv_handler); 336 | int cfg_get(struct wilc_vif *vif, int start, u16 wid, int commit, 337 | u32 drv_handler); 338 | int txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer, 339 | u32 buffer_size, 340 | void (*tx_complete_fn)(void *, int)); 341 | 342 | void wilc_enable_tcp_ack_filter(struct wilc_vif *vif, bool value); 343 | netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *dev); 344 | 345 | bool wilc_wfi_p2p_rx(struct wilc_vif *vif, u8 *buff, u32 size); 346 | void host_wakeup_notify(struct wilc *wilc, int source); 347 | void host_sleep_notify(struct wilc *wilc, int source); 348 | void chip_allow_sleep(struct wilc *wilc, int source); 349 | void chip_wakeup(struct wilc *wilc, int source); 350 | int wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids, 351 | u32 count); 352 | int wilc_wlan_power_on_sequence(struct wilc *wilc); 353 | int wilc_wlan_power_off_sequence(struct wilc *wilc); 354 | 355 | void wilc_bt_init(struct wilc *wilc); 356 | void wilc_bt_deinit(void); 357 | #if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE 358 | void eap_buff_timeout(struct timer_list *t); 359 | #else 360 | void eap_buff_timeout(unsigned long user); 361 | #endif 362 | void acquire_bus(struct wilc *wilc, enum bus_acquire acquire, int source); 363 | void release_bus(struct wilc *wilc, enum bus_release release, int source); 364 | int wilc_wlan_init(struct net_device *dev); 365 | u32 wilc_get_chipid(struct wilc *wilc, bool update); 366 | void wilc_wfi_handle_monitor_rx(struct wilc *wilc, u8 *buff, u32 size); 367 | #endif 368 | -------------------------------------------------------------------------------- /wilc/wilc_wlan_cfg.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | /* 3 | * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. 4 | * All rights reserved. 5 | */ 6 | 7 | #include "wilc_wlan_if.h" 8 | #include "wilc_wlan.h" 9 | #include "wilc_wlan_cfg.h" 10 | #include "wilc_wfi_netdevice.h" 11 | #include "wilc_wfi_cfgoperations.h" 12 | 13 | enum cfg_cmd_type { 14 | CFG_BYTE_CMD = 0, 15 | CFG_HWORD_CMD = 1, 16 | CFG_WORD_CMD = 2, 17 | CFG_STR_CMD = 3, 18 | CFG_BIN_CMD = 4 19 | }; 20 | 21 | static struct wilc_cfg_byte g_cfg_byte[] = { 22 | {WID_STATUS, 0}, 23 | {WID_RSSI, 0}, 24 | {WID_LINKSPEED, 0}, 25 | {WID_TX_POWER, 0}, 26 | {WID_WOWLAN_TRIGGER, 0}, 27 | {WID_NIL, 0} 28 | }; 29 | 30 | static struct wilc_cfg_hword g_cfg_hword[] = { 31 | {WID_NIL, 0} 32 | }; 33 | 34 | static struct wilc_cfg_word g_cfg_word[] = { 35 | {WID_FAILED_COUNT, 0}, 36 | {WID_RECEIVED_FRAGMENT_COUNT, 0}, 37 | {WID_SUCCESS_FRAME_COUNT, 0}, 38 | {WID_GET_INACTIVE_TIME, 0}, 39 | {WID_NIL, 0} 40 | 41 | }; 42 | 43 | static struct wilc_cfg_str g_cfg_str[] = { 44 | {WID_FIRMWARE_VERSION, NULL}, 45 | {WID_MAC_ADDR, NULL}, 46 | {WID_ASSOC_RES_INFO, NULL}, 47 | {WID_NIL, NULL} 48 | }; 49 | 50 | static struct wilc_cfg_bin g_cfg_bin[] = { 51 | {WID_ANTENNA_SELECTION, NULL}, 52 | {WID_NIL, NULL} 53 | }; 54 | 55 | /******************************************** 56 | * 57 | * Configuration Functions 58 | * 59 | ********************************************/ 60 | 61 | static int wilc_wlan_cfg_set_byte(u8 *frame, u32 offset, u16 id, u8 val8) 62 | { 63 | 64 | if ((offset + 4) >= WILC_MAX_CFG_FRAME_SIZE) 65 | return 0; 66 | 67 | put_unaligned_le16(id, &frame[offset]); 68 | put_unaligned_le16(1, &frame[offset + 2]); 69 | frame[offset + 4] = val8; 70 | return 5; 71 | } 72 | 73 | static int wilc_wlan_cfg_set_hword(u8 *frame, u32 offset, u16 id, u16 val16) 74 | { 75 | if ((offset + 5) >= WILC_MAX_CFG_FRAME_SIZE) 76 | return 0; 77 | 78 | put_unaligned_le16(id, &frame[offset]); 79 | put_unaligned_le16(2, &frame[offset + 2]); 80 | put_unaligned_le16(val16, &frame[offset + 4]); 81 | return 6; 82 | } 83 | 84 | static int wilc_wlan_cfg_set_word(u8 *frame, u32 offset, u16 id, u32 val32) 85 | { 86 | if ((offset + 7) >= WILC_MAX_CFG_FRAME_SIZE) 87 | return 0; 88 | 89 | put_unaligned_le16(id, &frame[offset]); 90 | put_unaligned_le16(4, &frame[offset + 2]); 91 | put_unaligned_le32(val32, &frame[offset + 4]); 92 | return 8; 93 | } 94 | 95 | static int wilc_wlan_cfg_set_str(u8 *frame, u32 offset, u16 id, u8 *str, 96 | u32 size) 97 | { 98 | if ((offset + size + 4) >= WILC_MAX_CFG_FRAME_SIZE) 99 | return 0; 100 | 101 | put_unaligned_le16(id, &frame[offset]); 102 | put_unaligned_le16(size, &frame[offset + 2]); 103 | 104 | if (str && size != 0) 105 | memcpy(&frame[offset + 4], str, size); 106 | 107 | return (size + 4); 108 | } 109 | 110 | static int wilc_wlan_cfg_set_bin(u8 *frame, u32 offset, u16 id, u8 *b, u32 size) 111 | { 112 | u32 i; 113 | u8 checksum = 0; 114 | 115 | if ((offset + size + 5) >= WILC_MAX_CFG_FRAME_SIZE) 116 | return 0; 117 | 118 | put_unaligned_le16(id, &frame[offset]); 119 | put_unaligned_le16(size, &frame[offset + 2]); 120 | 121 | if ((b) && size != 0) { 122 | memcpy(&frame[offset + 4], b, size); 123 | for (i = 0; i < size; i++) 124 | checksum += frame[offset + i + 4]; 125 | } 126 | 127 | frame[offset + size + 4] = checksum; 128 | return (size + 5); 129 | } 130 | 131 | /******************************************** 132 | * 133 | * Configuration Response Functions 134 | * 135 | ********************************************/ 136 | 137 | #define GET_WID_TYPE(wid) (((wid) >> 12) & 0x7) 138 | static void wilc_wlan_parse_response_frame(struct wilc *wl, u8 *info, 139 | int size) 140 | { 141 | u16 wid; 142 | u32 len = 0, i = 0; 143 | 144 | while (size > 0) { 145 | i = 0; 146 | wid = get_unaligned_le16(info); 147 | 148 | switch (GET_WID_TYPE(wid)) { 149 | case WID_CHAR: 150 | do { 151 | if (wl->cfg.b[i].id == WID_NIL) 152 | break; 153 | 154 | if (wl->cfg.b[i].id == wid) { 155 | wl->cfg.b[i].val = info[4]; 156 | break; 157 | } 158 | i++; 159 | } while (1); 160 | len = 3; 161 | break; 162 | 163 | case WID_SHORT: 164 | do { 165 | struct wilc_cfg_hword *hw = &wl->cfg.hw[i]; 166 | 167 | if (hw->id == WID_NIL) 168 | break; 169 | 170 | if (hw->id == wid) { 171 | hw->val = get_unaligned_le16(&info[4]); 172 | break; 173 | } 174 | i++; 175 | } while (1); 176 | len = 4; 177 | break; 178 | 179 | case WID_INT: 180 | do { 181 | struct wilc_cfg_word *w = &wl->cfg.w[i]; 182 | 183 | if (w->id == WID_NIL) 184 | break; 185 | 186 | if (w->id == wid) { 187 | w->val = get_unaligned_le32(&info[4]); 188 | break; 189 | } 190 | i++; 191 | } while (1); 192 | len = 6; 193 | break; 194 | 195 | case WID_STR: 196 | do { 197 | if (wl->cfg.s[i].id == WID_NIL) 198 | break; 199 | 200 | if (wl->cfg.s[i].id == wid) { 201 | memcpy(wl->cfg.s[i].str, &info[2], 202 | (2+((info[3] << 8) | info[2]))); 203 | break; 204 | } 205 | i++; 206 | } while (1); 207 | len = 2+((info[3] << 8) | info[2]); 208 | break; 209 | case WID_BIN_DATA: 210 | do { 211 | u16 length = (info[3] << 8) | info[2]; 212 | u8 checksum = 0; 213 | int j = 0; 214 | 215 | if (wl->cfg.bin[i].id == WID_NIL) 216 | break; 217 | 218 | if (wl->cfg.bin[i].id != wid) { 219 | i++; 220 | continue; 221 | } 222 | 223 | /* 224 | * Compute the Checksum of received 225 | * data field 226 | */ 227 | for (j = 0; j < length; j++) 228 | checksum += info[4 + j]; 229 | /* 230 | * Verify the checksum of recieved BIN 231 | * DATA 232 | */ 233 | if (checksum != info[4 + length]) { 234 | pr_err("%s: Checksum Failed\n", 235 | __func__); 236 | return; 237 | } 238 | 239 | memcpy(wl->cfg.bin[i].bin, &info[2], length+2); 240 | /* 241 | * value length + data length + 242 | * checksum 243 | */ 244 | len = 2 + length + 1; 245 | break; 246 | 247 | } while (1); 248 | break; 249 | default: 250 | break; 251 | } 252 | size -= (2 + len); 253 | info += (2 + len); 254 | } 255 | } 256 | 257 | static void wilc_wlan_parse_info_frame(struct wilc *wl, u8 *info) 258 | { 259 | u32 wid, len; 260 | 261 | wid = get_unaligned_le16(info); 262 | 263 | len = info[2]; 264 | 265 | if (len == 1 && wid == WID_STATUS) { 266 | int i = 0; 267 | 268 | do { 269 | if (wl->cfg.b[i].id == WID_NIL) 270 | break; 271 | 272 | if (wl->cfg.b[i].id == wid) { 273 | wl->cfg.b[i].val = info[3]; 274 | break; 275 | } 276 | i++; 277 | } while (1); 278 | } 279 | } 280 | 281 | /******************************************** 282 | * 283 | * Configuration Exported Functions 284 | * 285 | ********************************************/ 286 | 287 | int cfg_set_wid(struct wilc_vif *vif, u8 *frame, u32 offset, u16 id, u8 *buf, 288 | int size) 289 | { 290 | u8 type = (id >> 12) & 0xf; 291 | int ret = 0; 292 | 293 | switch (type) { 294 | case CFG_BYTE_CMD: 295 | if (size >= 1) 296 | ret = wilc_wlan_cfg_set_byte(frame, offset, id, *buf); 297 | break; 298 | 299 | case CFG_HWORD_CMD: 300 | if (size >= 2) 301 | ret = wilc_wlan_cfg_set_hword(frame, offset, id, 302 | *((u16 *)buf)); 303 | break; 304 | 305 | case CFG_WORD_CMD: 306 | if (size >= 4) 307 | ret = wilc_wlan_cfg_set_word(frame, offset, id, 308 | *((u32 *)buf)); 309 | break; 310 | 311 | case CFG_STR_CMD: 312 | ret = wilc_wlan_cfg_set_str(frame, offset, id, buf, size); 313 | break; 314 | 315 | case CFG_BIN_CMD: 316 | ret = wilc_wlan_cfg_set_bin(frame, offset, id, buf, size); 317 | break; 318 | default: 319 | PRINT_ER(vif->ndev, "illegal id\n"); 320 | } 321 | 322 | return ret; 323 | } 324 | 325 | int cfg_get_wid(u8 *frame, u32 offset, u16 id) 326 | { 327 | if ((offset + 2) >= WILC_MAX_CFG_FRAME_SIZE) 328 | return 0; 329 | 330 | put_unaligned_le16(id, &frame[offset]); 331 | return 2; 332 | } 333 | 334 | int cfg_get_val(struct wilc *wl, u16 wid, u8 *buffer, u32 buffer_size) 335 | { 336 | u32 type = (wid >> 12) & 0xf; 337 | int i, ret = 0; 338 | 339 | i = 0; 340 | if (type == CFG_BYTE_CMD) { 341 | do { 342 | if (wl->cfg.b[i].id == WID_NIL) 343 | break; 344 | 345 | if (wl->cfg.b[i].id == wid) { 346 | memcpy(buffer, &wl->cfg.b[i].val, 1); 347 | ret = 1; 348 | break; 349 | } 350 | i++; 351 | } while (1); 352 | } else if (type == CFG_HWORD_CMD) { 353 | do { 354 | if (wl->cfg.hw[i].id == WID_NIL) 355 | break; 356 | 357 | if (wl->cfg.hw[i].id == wid) { 358 | memcpy(buffer, &wl->cfg.hw[i].val, 2); 359 | ret = 2; 360 | break; 361 | } 362 | i++; 363 | } while (1); 364 | } else if (type == CFG_WORD_CMD) { 365 | do { 366 | if (wl->cfg.w[i].id == WID_NIL) 367 | break; 368 | 369 | if (wl->cfg.w[i].id == wid) { 370 | memcpy(buffer, &wl->cfg.w[i].val, 4); 371 | ret = 4; 372 | break; 373 | } 374 | i++; 375 | } while (1); 376 | } else if (type == CFG_STR_CMD) { 377 | do { 378 | u32 id = wl->cfg.s[i].id; 379 | 380 | if (id == WID_NIL) 381 | break; 382 | 383 | if (id == wid) { 384 | u16 size = get_unaligned_le16(wl->cfg.s[i].str); 385 | 386 | if (buffer_size >= size) { 387 | memcpy(buffer, &wl->cfg.s[i].str[2], 388 | size); 389 | ret = size; 390 | } 391 | break; 392 | } 393 | i++; 394 | } while (1); 395 | } else if (type == CFG_BIN_CMD) { /* binary command */ 396 | do { 397 | if (wl->cfg.bin[i].id == WID_NIL) 398 | break; 399 | 400 | if (wl->cfg.bin[i].id == wid) { 401 | uint32_t size = wl->cfg.bin[i].bin[0] | 402 | (wl->cfg.bin[i].bin[1]<<8); 403 | if (buffer_size >= size) { 404 | memcpy(buffer, &wl->cfg.bin[i].bin[2], 405 | size); 406 | ret = size; 407 | } 408 | break; 409 | } 410 | i++; 411 | } while (1); 412 | } else { 413 | pr_err("[CFG]: illegal type (%08x)\n", wid); 414 | } 415 | 416 | return ret; 417 | } 418 | 419 | void cfg_indicate_rx(struct wilc *wilc, u8 *frame, int size, 420 | struct wilc_cfg_rsp *rsp) 421 | { 422 | u8 msg_type; 423 | u8 msg_id; 424 | 425 | msg_type = frame[0]; 426 | msg_id = frame[1]; /* seq no */ 427 | frame += 4; 428 | size -= 4; 429 | rsp->type = 0; 430 | 431 | /* 432 | * The valid types of response messages are 433 | * 'R' (Response), 434 | * 'I' (Information), and 435 | * 'N' (Network Information) 436 | */ 437 | 438 | switch (msg_type) { 439 | case 'R': 440 | wilc_wlan_parse_response_frame(wilc, frame, size); 441 | rsp->type = WILC_CFG_RSP; 442 | rsp->seq_no = msg_id; 443 | break; 444 | 445 | case 'I': 446 | wilc_wlan_parse_info_frame(wilc, frame); 447 | rsp->type = WILC_CFG_RSP_STATUS; 448 | rsp->seq_no = msg_id; 449 | /*call host interface info parse as well*/ 450 | pr_info("%s: Info message received\n", __func__); 451 | wilc_gnrl_async_info_received(wilc, frame - 4, size + 4); 452 | break; 453 | 454 | case 'N': 455 | wilc_network_info_received(wilc, frame - 4, size + 4); 456 | break; 457 | 458 | case 'S': 459 | pr_info("%s: Scan Notification Received\n", __func__); 460 | wilc_scan_complete_received(wilc, frame - 4, size + 4); 461 | break; 462 | 463 | default: 464 | pr_err("%s: Receive unknown message %d-%d-%d-%d-%d-%d-%d-%d\n", 465 | __func__, frame[0], frame[1], frame[2], frame[3], 466 | frame[4], frame[5], frame[6], frame[7]); 467 | rsp->seq_no = msg_id; 468 | break; 469 | } 470 | } 471 | 472 | int cfg_init(struct wilc *wl) 473 | { 474 | struct wilc_cfg_str_vals *str_vals; 475 | struct wilc_bin_vals *bin_vals; 476 | int i = 0; 477 | 478 | wl->cfg.b = kmemdup(g_cfg_byte, sizeof(g_cfg_byte), GFP_KERNEL); 479 | if (!wl->cfg.b) 480 | return -ENOMEM; 481 | 482 | wl->cfg.hw = kmemdup(g_cfg_hword, sizeof(g_cfg_hword), GFP_KERNEL); 483 | if (!wl->cfg.hw) 484 | goto out_b; 485 | 486 | wl->cfg.w = kmemdup(g_cfg_word, sizeof(g_cfg_word), GFP_KERNEL); 487 | if (!wl->cfg.w) 488 | goto out_hw; 489 | 490 | wl->cfg.s = kmemdup(g_cfg_str, sizeof(g_cfg_str), GFP_KERNEL); 491 | if (!wl->cfg.s) 492 | goto out_w; 493 | 494 | str_vals = kzalloc(sizeof(*str_vals), GFP_KERNEL); 495 | if (!str_vals) 496 | goto out_s; 497 | 498 | wl->cfg.bin = kmemdup(g_cfg_bin, sizeof(g_cfg_bin), GFP_KERNEL); 499 | if (!wl->cfg.bin) 500 | goto out_str_val; 501 | 502 | bin_vals = kzalloc(sizeof(*bin_vals), GFP_KERNEL); 503 | if (!bin_vals) 504 | goto out_bin; 505 | 506 | /* store the string cfg parameters */ 507 | wl->cfg.str_vals = str_vals; 508 | wl->cfg.s[i].id = WID_FIRMWARE_VERSION; 509 | wl->cfg.s[i].str = str_vals->firmware_version; 510 | i++; 511 | wl->cfg.s[i].id = WID_MAC_ADDR; 512 | wl->cfg.s[i].str = str_vals->mac_address; 513 | i++; 514 | wl->cfg.s[i].id = WID_ASSOC_RES_INFO; 515 | wl->cfg.s[i].str = str_vals->assoc_rsp; 516 | i++; 517 | wl->cfg.s[i].id = WID_NIL; 518 | wl->cfg.s[i].str = NULL; 519 | 520 | /* store the bin parameters */ 521 | i = 0; 522 | wl->cfg.bin[i].id = WID_ANTENNA_SELECTION; 523 | wl->cfg.bin[i].bin = bin_vals->antenna_param; 524 | i++; 525 | 526 | wl->cfg.bin[i].id = WID_NIL; 527 | wl->cfg.bin[i].bin = NULL; 528 | 529 | return 0; 530 | 531 | out_bin: 532 | kfree(wl->cfg.bin); 533 | out_str_val: 534 | kfree(str_vals); 535 | out_s: 536 | kfree(wl->cfg.s); 537 | out_w: 538 | kfree(wl->cfg.w); 539 | out_hw: 540 | kfree(wl->cfg.hw); 541 | out_b: 542 | kfree(wl->cfg.b); 543 | return -ENOMEM; 544 | } 545 | 546 | void cfg_deinit(struct wilc *wl) 547 | { 548 | kfree(wl->cfg.b); 549 | kfree(wl->cfg.hw); 550 | kfree(wl->cfg.w); 551 | kfree(wl->cfg.s); 552 | kfree(wl->cfg.str_vals); 553 | kfree(wl->cfg.bin); 554 | kfree(wl->cfg.bin_vals); 555 | } 556 | 557 | -------------------------------------------------------------------------------- /wilc/wilc_bt.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | /* 3 | * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. 4 | * All rights reserved. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "wilc_wfi_netdevice.h" 22 | 23 | static struct wilc *wilc_bt; 24 | static dev_t chc_dev_no; /* Global variable for the first device number */ 25 | static struct cdev str_chc_dev; /* Global variable for the character */ 26 | struct device *dev; 27 | static struct class *chc_dev_class; /* Global variable for the device class */ 28 | static bool device_created; 29 | int bt_init_done; 30 | 31 | typedef void (wilc_cmd_handler)(char *); 32 | 33 | static void handle_cmd_bt_enable(char *param); 34 | static void handle_cmd_pwr_up(char *param); 35 | static void handle_cmd_pwr_down(char *param); 36 | static void handle_cmd_chip_wake_up(char *param); 37 | static void handle_cmd_chip_allow_sleep(char *param); 38 | static void handle_cmd_download_fw(char *param); 39 | static void handle_cmd_cca_thrshld(char *param); 40 | 41 | static void wilc_bt_firmware_download(struct wilc *); 42 | static void wilc_bt_start(struct wilc *); 43 | static int wilc_bt_dev_open(struct inode *i, struct file *f); 44 | static int wilc_bt_dev_close(struct inode *i, struct file *f); 45 | static ssize_t wilc_bt_dev_read(struct file *f, char __user *buf, size_t len, 46 | loff_t *off); 47 | static ssize_t wilc_bt_dev_write(struct file *f, const char __user *buff, 48 | size_t len, loff_t *off); 49 | 50 | static const struct file_operations pugs_fops = { 51 | .owner = THIS_MODULE, 52 | .open = wilc_bt_dev_open, 53 | .release = wilc_bt_dev_close, 54 | .read = wilc_bt_dev_read, 55 | .write = wilc_bt_dev_write 56 | }; 57 | 58 | struct cmd_entry { 59 | const char *str; 60 | wilc_cmd_handler *wilc_handle_cmd; 61 | }; 62 | 63 | static const struct cmd_entry cmd_table[] = { 64 | {"BT_DOWNLOAD_FW", handle_cmd_download_fw}, 65 | {"BT_POWER_UP", handle_cmd_pwr_up}, 66 | {"BT_POWER_DOWN", handle_cmd_pwr_down}, 67 | {"BT_FW_CHIP_WAKEUP", handle_cmd_chip_wake_up}, 68 | {"BT_FW_CHIP_ALLOW_SLEEP", handle_cmd_chip_allow_sleep}, 69 | {"BT_ENABLE", handle_cmd_bt_enable}, 70 | {"CCA_THRESHOLD", handle_cmd_cca_thrshld}, 71 | /* Keep the NULL handler at the end of the table */ 72 | {(const char *)NULL, NULL}, 73 | }; 74 | 75 | static int wilc_bt_dev_open(struct inode *i, struct file *f) 76 | { 77 | pr_info("at_pwr_dev: open()\n"); 78 | return 0; 79 | } 80 | 81 | static int wilc_bt_dev_close(struct inode *i, struct file *f) 82 | { 83 | pr_info("at_pwr_dev: close()\n"); 84 | return 0; 85 | } 86 | 87 | static ssize_t wilc_bt_dev_read(struct file *f, char __user *buf, size_t len, 88 | loff_t *off) 89 | { 90 | pr_debug("at_pwr_dev: read()\n"); 91 | return 0; 92 | } 93 | 94 | static ssize_t wilc_bt_dev_write(struct file *f, const char __user *buff, 95 | size_t len, loff_t *off) 96 | { 97 | struct cmd_entry *cmd; 98 | char *usr_str; 99 | 100 | 101 | if (len == 0) { 102 | pr_debug("received invalid size <=0: %d\n", len); 103 | return len; 104 | } 105 | 106 | usr_str = kmalloc(len, GFP_KERNEL); 107 | 108 | if (copy_from_user(usr_str, buff, len)) 109 | return -EIO; 110 | 111 | pr_debug("received %s, len %d\n", usr_str, len); 112 | // call the appropriate command handler 113 | cmd = (struct cmd_entry *)cmd_table; 114 | while (cmd->wilc_handle_cmd != NULL) { 115 | if (strncmp(cmd->str, usr_str, strlen(cmd->str)) == 0) { 116 | pr_debug("param len: %d, string: %s\n", 117 | len - strlen(cmd->str), usr_str); 118 | cmd->wilc_handle_cmd(usr_str + strlen(cmd->str)); 119 | break; 120 | } 121 | cmd++; 122 | } 123 | 124 | kfree(usr_str); 125 | return len; 126 | } 127 | 128 | static void wilc_bt_create_device(void) 129 | { 130 | int ret = 0; 131 | 132 | if (device_created) 133 | return; 134 | 135 | ret = alloc_chrdev_region(&chc_dev_no, 0, 1, "atmel"); 136 | if (ret < 0) 137 | return; 138 | chc_dev_class = class_create(THIS_MODULE, "atmel"); 139 | if (IS_ERR(chc_dev_class)) { 140 | unregister_chrdev_region(chc_dev_no, 1); 141 | return; 142 | } 143 | dev = device_create(chc_dev_class, NULL, chc_dev_no, NULL, 144 | "wilc_bt"); 145 | if (IS_ERR(dev)) { 146 | class_destroy(chc_dev_class); 147 | unregister_chrdev_region(chc_dev_no, 1); 148 | return; 149 | } 150 | 151 | cdev_init(&str_chc_dev, &pugs_fops); 152 | ret = cdev_add(&str_chc_dev, chc_dev_no, 1); 153 | if (ret < 0) { 154 | device_destroy(chc_dev_class, chc_dev_no); 155 | class_destroy(chc_dev_class); 156 | unregister_chrdev_region(chc_dev_no, 1); 157 | return; 158 | } 159 | mutex_init(&wilc_bt->cs); 160 | device_created = 1; 161 | } 162 | 163 | static void handle_cmd_cca_thrshld(char *param) 164 | { 165 | int carrier_thrshld, noise_thrshld; 166 | unsigned int carr_thrshld_frac, noise_thrshld_frac, carr_thrshld_int, 167 | noise_thrshld_int, reg; 168 | 169 | if (param == NULL) { 170 | pr_err("Invalid parameter\n"); 171 | return; 172 | } 173 | 174 | if (sscanf(param, " %d %d", &noise_thrshld, &carrier_thrshld) != 2) { 175 | pr_err("Failed to parse input parameters. Usage:\n"); 176 | pr_err("echo CCA_THRESHOLD NOISE_THRESHOLD CARRIER_THRESHOLD > /dev/at_pwr_dev\n"); 177 | pr_err("where threshold values are in dB * 10\n"); 178 | pr_err("e.g. echo CCA_THRESHOLD -625 -826 > /dev/at_pwr_dev to set thresholds to -62.5 and -82.6\n\n"); 179 | return; 180 | } 181 | 182 | pr_info("Changing CCA noise threshold to %d and carrier thresholds to %d\n", 183 | noise_thrshld, carrier_thrshld); 184 | 185 | carr_thrshld_int = carrier_thrshld/10; 186 | if (carrier_thrshld < 0) 187 | carr_thrshld_frac = (carr_thrshld_int * 10) - carrier_thrshld; 188 | else 189 | carr_thrshld_frac = carrier_thrshld - (carr_thrshld_int * 10); 190 | 191 | noise_thrshld_int = noise_thrshld/10; 192 | if (noise_thrshld < 0) 193 | noise_thrshld_frac = (noise_thrshld_int * 10) - noise_thrshld; 194 | else 195 | noise_thrshld_frac = noise_thrshld - (noise_thrshld_int * 10); 196 | 197 | wilc_bt->hif_func->hif_read_reg(wilc_bt, CCA_CTL_2, ®); 198 | reg &= ~(0x7FF0000); 199 | reg |= ((noise_thrshld_frac & 0x7) | ((noise_thrshld_int & 0x1FF) 200 | << 3)) << 16; 201 | wilc_bt->hif_func->hif_write_reg(wilc_bt, CCA_CTL_2, reg); 202 | 203 | wilc_bt->hif_func->hif_read_reg(wilc_bt, CCA_CTL_7, ®); 204 | reg &= ~(0x7FF0000); 205 | reg |= ((carr_thrshld_frac & 0x7) | ((carr_thrshld_int & 0x1FF) << 3)) 206 | << 16; 207 | wilc_bt->hif_func->hif_write_reg(wilc_bt, CCA_CTL_7, reg); 208 | } 209 | 210 | int wilc_bt_power_down(struct wilc *wilc, int source) 211 | { 212 | const struct wilc_hif_func *hif_func = wilc->hif_func; 213 | int ret; 214 | 215 | if (source == DEV_BT) { 216 | u32 reg; 217 | 218 | pr_info("AT PWR: bt_power_down\n"); 219 | 220 | /* Adjust coexistence module. This should be done from the FW 221 | * in the future 222 | */ 223 | acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP, DEV_BT); 224 | 225 | ret = hif_func->hif_read_reg(wilc, GLOBAL_MODE_CONTROL, 226 | ®); 227 | if (!ret) { 228 | pr_err("[wilc start]: fail read reg %x\n", 229 | GLOBAL_MODE_CONTROL); 230 | release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_BT); 231 | return ret; 232 | } 233 | /* Clear BT mode*/ 234 | reg &= ~BIT(1); 235 | ret = hif_func->hif_write_reg(wilc, GLOBAL_MODE_CONTROL, 236 | reg); 237 | if (!ret) { 238 | pr_err("[wilc start]: fail write reg %x\n", 239 | GLOBAL_MODE_CONTROL); 240 | release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_BT); 241 | return ret; 242 | } 243 | 244 | 245 | /*TicketId1115*/ 246 | /*Disable awake coex null frames*/ 247 | ret = hif_func->hif_read_reg(wilc, COE_AUTO_PS_ON_NULL_PKT, 248 | ®); 249 | if (!ret) { 250 | pr_err("[wilc start]: fail read reg %x\n", 251 | COE_AUTO_PS_ON_NULL_PKT); 252 | release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_BT); 253 | return ret; 254 | } 255 | reg &= ~BIT(30); 256 | ret = hif_func->hif_write_reg(wilc, COE_AUTO_PS_ON_NULL_PKT, 257 | reg); 258 | if (!ret) { 259 | pr_err("[wilc start]: fail write reg %x\n", 260 | COE_AUTO_PS_ON_NULL_PKT); 261 | release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_BT); 262 | return ret; 263 | } 264 | 265 | /*TicketId1115*/ 266 | /*Disable doze coex null frames*/ 267 | ret = hif_func->hif_read_reg(wilc, COE_AUTO_PS_OFF_NULL_PKT, 268 | ®); 269 | if (!ret) { 270 | pr_err("[wilc start]: fail read reg %x\n", 271 | COE_AUTO_PS_OFF_NULL_PKT); 272 | release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_BT); 273 | return ret; 274 | } 275 | reg &= ~BIT(30); 276 | ret = hif_func->hif_write_reg(wilc, COE_AUTO_PS_OFF_NULL_PKT, 277 | reg); 278 | if (!ret) { 279 | pr_err("[wilc start]: fail write reg %x\n", 280 | COE_AUTO_PS_OFF_NULL_PKT); 281 | release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_BT); 282 | return ret; 283 | } 284 | // Disable BT wakeup 285 | ret = hif_func->hif_read_reg(wilc, PWR_SEQ_MISC_CTRL, 286 | ®); 287 | if (!ret) { 288 | pr_err("[wilc start]: fail read reg %x\n", 289 | PWR_SEQ_MISC_CTRL); 290 | release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_BT); 291 | return ret; 292 | } 293 | reg &= ~BIT(29); 294 | ret = hif_func->hif_write_reg(wilc, PWR_SEQ_MISC_CTRL, 295 | reg); 296 | if (!ret) { 297 | pr_err("[wilc start]: fail write reg %x\n", 298 | PWR_SEQ_MISC_CTRL); 299 | release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_BT); 300 | return ret; 301 | } 302 | 303 | release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_BT); 304 | 305 | bt_init_done = 0; 306 | } 307 | 308 | mutex_lock(&wilc->cs); 309 | 310 | pr_info("source: %s, current bus status Wifi: %d, BT: %d\n", 311 | (source == DEV_WIFI ? "Wifi" : "BT"), 312 | wilc->power_status[DEV_WIFI], 313 | wilc->power_status[DEV_BT]); 314 | 315 | if (wilc->power_status[source] == false) { 316 | pr_err("power down request for already powered down source %s\n", 317 | (source == DEV_WIFI ? "Wifi" : "BT")); 318 | } else if (((source == DEV_WIFI) && 319 | (wilc->power_status[DEV_BT] == true)) || 320 | ((source == DEV_BT) && 321 | (wilc->power_status[DEV_WIFI] == true))) { 322 | pr_warn("Another device is preventing power down. request source is %s\n", 323 | (source == DEV_WIFI ? "Wifi" : "BT")); 324 | } else { 325 | ret = wilc_wlan_power_off_sequence(wilc); 326 | if (ret) { 327 | mutex_unlock(&wilc->cs); 328 | return ret; 329 | } 330 | } 331 | wilc->power_status[source] = false; 332 | 333 | mutex_unlock(&wilc->cs); 334 | 335 | return 0; 336 | } 337 | 338 | int wilc_bt_power_up(struct wilc *wilc, int source) 339 | { 340 | int count = 0; 341 | int ret; 342 | int reg; 343 | const struct wilc_hif_func *hif_func = wilc->hif_func; 344 | 345 | mutex_lock(&wilc->cs); 346 | 347 | pr_debug("source: %s, current bus status Wifi: %d, BT: %d\n", 348 | (source == DEV_WIFI ? "Wifi" : "BT"), 349 | wilc->power_status[DEV_WIFI], 350 | wilc->power_status[DEV_BT]); 351 | 352 | if (wilc->power_status[source] == true) { 353 | pr_err("power up request for already powered up source %s\n", 354 | (source == DEV_WIFI ? "Wifi" : "BT")); 355 | } else { 356 | /*Bug 215*/ 357 | /*Avoid overlapping between BT and Wifi intialization*/ 358 | if (wilc->power_status[DEV_WIFI] == true) { 359 | while (!wilc->initialized) { 360 | msleep(100); 361 | if (++count > 20) { 362 | pr_warn("Wifi initialize timeout\n"); 363 | break; 364 | } 365 | } 366 | } else if (wilc->power_status[DEV_BT] == true) { 367 | while (!bt_init_done) { 368 | msleep(200); 369 | if (++count > 30) { 370 | pr_warn("BT initialize timeout\n"); 371 | break; 372 | } 373 | } 374 | /* An additional wait to give BT firmware time to do 375 | * CPLL update as the time measured since the start of 376 | * BT Fw till the end of function "rf_nmi_init_tuner" 377 | * was 71.2 ms 378 | */ 379 | msleep(100); 380 | } 381 | } 382 | 383 | if ((wilc->power_status[DEV_WIFI] == true) || 384 | (wilc->power_status[DEV_BT] == true)) { 385 | pr_info("Device already up. request source is %s\n", 386 | (source == DEV_WIFI ? "Wifi" : "BT")); 387 | } else { 388 | pr_info("WILC POWER UP\n"); 389 | } 390 | wilc->power_status[source] = true; 391 | mutex_unlock(&wilc->cs); 392 | 393 | if (source == DEV_BT) { 394 | /*TicketId1092*/ 395 | /*If WiFi is off, force BT*/ 396 | if (wilc->power_status[DEV_WIFI] == false) { 397 | acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP, DEV_BT); 398 | 399 | /*TicketId1115*/ 400 | /*Disable awake coex null frames*/ 401 | ret = hif_func->hif_read_reg(wilc, 402 | COE_AUTO_PS_ON_NULL_PKT, 403 | ®); 404 | if (!ret) { 405 | pr_err("[wilc start]: fail read reg %x\n", 406 | COE_AUTO_PS_ON_NULL_PKT); 407 | goto fail; 408 | } 409 | reg &= ~BIT(30); 410 | ret = hif_func->hif_write_reg(wilc, 411 | COE_AUTO_PS_ON_NULL_PKT, 412 | reg); 413 | if (!ret) { 414 | pr_err("[wilc start]: fail write reg %x\n", 415 | COE_AUTO_PS_ON_NULL_PKT); 416 | goto fail; 417 | } 418 | 419 | /*TicketId1115*/ 420 | /*Disable doze coex null frames*/ 421 | ret = hif_func->hif_read_reg(wilc, 422 | COE_AUTO_PS_OFF_NULL_PKT, 423 | ®); 424 | if (!ret) { 425 | pr_err("[wilc start]: fail read reg %x\n", 426 | COE_AUTO_PS_OFF_NULL_PKT); 427 | goto fail; 428 | } 429 | reg &= ~BIT(30); 430 | ret = hif_func->hif_write_reg(wilc, 431 | COE_AUTO_PS_OFF_NULL_PKT, 432 | reg); 433 | if (!ret) { 434 | pr_err("[wilc start]: fail write reg %x\n", 435 | COE_AUTO_PS_OFF_NULL_PKT); 436 | goto fail; 437 | } 438 | 439 | release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_BT); 440 | } 441 | 442 | // Enable BT wakeup 443 | acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP, DEV_BT); 444 | 445 | ret = hif_func->hif_read_reg(wilc, PWR_SEQ_MISC_CTRL, 446 | ®); 447 | if (!ret) { 448 | pr_err("[wilc start]: fail read reg %x ...\n", 449 | PWR_SEQ_MISC_CTRL); 450 | goto fail; 451 | } 452 | reg |= BIT(29); 453 | ret = hif_func->hif_write_reg(wilc, PWR_SEQ_MISC_CTRL, 454 | reg); 455 | if (!ret) { 456 | pr_err("[wilc start]: fail write reg %x ...\n", 457 | PWR_SEQ_MISC_CTRL); 458 | goto fail; 459 | } 460 | 461 | release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_BT); 462 | } 463 | 464 | return 0; 465 | 466 | fail: 467 | release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_BT); 468 | wilc_bt_power_down(wilc, DEV_BT); 469 | return ret; 470 | } 471 | 472 | static void wilc_bt_firmware_download(struct wilc *wilc) 473 | { 474 | u32 offset; 475 | u32 addr, size, size2, blksz; 476 | u8 *dma_buffer; 477 | const struct firmware *wilc_bt_firmware; 478 | const u8 *buffer; 479 | size_t buffer_size; 480 | int ret = 0; 481 | u32 reg; 482 | const struct wilc_hif_func *hif_func; 483 | 484 | hif_func = wilc->hif_func; 485 | 486 | pr_info("Bluetooth firmware: %s\n", FW_WILC3000_BLE); 487 | if (request_firmware(&wilc_bt_firmware, FW_WILC3000_BLE, dev) != 0) { 488 | pr_err("%s - firmare not available. Skip!\n", FW_WILC3000_BLE); 489 | ret = -1; 490 | goto fail_1; 491 | } 492 | 493 | buffer = wilc_bt_firmware->data; 494 | buffer_size = (size_t)wilc_bt_firmware->size; 495 | if (buffer_size <= 0) { 496 | pr_err("Firmware size = 0!\n"); 497 | ret = -1; 498 | goto fail_1; 499 | } 500 | 501 | acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP, DEV_BT); 502 | 503 | ret = hif_func->hif_write_reg(wilc, 0x4f0000, 0x71); 504 | if (!ret) { 505 | pr_err("[wilc start]: fail write reg 0x4f0000 ...\n"); 506 | release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_BT); 507 | goto fail_1; 508 | } 509 | 510 | /* 511 | * Avoid booting from BT boot ROM. Make sure that Drive IRQN 512 | * [SDIO platform] or SD_DAT3 [SPI platform] to ?1? 513 | */ 514 | /* Set cortus reset register to register control. */ 515 | ret = hif_func->hif_read_reg(wilc, 0x3b0090, ®); 516 | if (!ret) { 517 | pr_err("[wilc start]: fail read reg 0x3b0090 ...\n"); 518 | release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_BT); 519 | goto fail_1; 520 | } 521 | 522 | reg |= (1 << 0); 523 | ret = hif_func->hif_write_reg(wilc, 0x3b0090, reg); 524 | if (!ret) { 525 | pr_err("[wilc start]: fail write reg 0x3b0090 ...\n"); 526 | release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_BT); 527 | goto fail_1; 528 | } 529 | 530 | hif_func->hif_read_reg(wilc, 0x3B0400, ®); 531 | 532 | if (reg & (1ul << 2)) { 533 | reg &= ~(1ul << 2); 534 | } else { 535 | reg |= (1ul << 2); 536 | hif_func->hif_write_reg(wilc, 0x3B0400, reg); 537 | reg &= ~(1ul << 2); 538 | } 539 | hif_func->hif_write_reg(wilc, 0x3B0400, reg); 540 | 541 | release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_BT); 542 | 543 | /* blocks of sizes > 512 causes the wifi to hang! */ 544 | blksz = (1ul << 9); 545 | /* Allocate a DMA coherent buffer. */ 546 | dma_buffer = kmalloc(blksz, GFP_KERNEL); 547 | if (dma_buffer == NULL) { 548 | ret = -5; 549 | pr_err("Can't allocate buffer for BT firmware download IO error\n"); 550 | goto fail_1; 551 | } 552 | pr_info("Downloading BT firmware size = %d ...\n", buffer_size); 553 | 554 | offset = 0; 555 | addr = 0x400000; 556 | size = buffer_size; 557 | addr = cpu_to_le32(addr); 558 | size = cpu_to_le32(size); 559 | offset = 0; 560 | 561 | while (((int)size) && (offset < buffer_size)) { 562 | if (size <= blksz) 563 | size2 = size; 564 | else 565 | size2 = blksz; 566 | 567 | /* Copy firmware into a DMA coherent buffer */ 568 | memcpy(dma_buffer, &buffer[offset], size2); 569 | 570 | acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP, DEV_BT); 571 | 572 | ret = hif_func->hif_block_tx(wilc, addr, dma_buffer, size2); 573 | 574 | release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_BT); 575 | 576 | if (!ret) 577 | break; 578 | 579 | addr += size2; 580 | offset += size2; 581 | size -= size2; 582 | } 583 | 584 | if (!ret) { 585 | ret = -5; 586 | pr_err("Can't download BT firmware IO error\n"); 587 | goto fail; 588 | } 589 | 590 | fail: 591 | kfree(dma_buffer); 592 | fail_1: 593 | pr_debug("Freeing BT FW buffer ...\n"); 594 | pr_debug("Releasing BT firmware\n"); 595 | release_firmware(wilc_bt_firmware); 596 | } 597 | 598 | static void wilc_bt_start(struct wilc *wilc) 599 | { 600 | u32 val32 = 0; 601 | 602 | acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP, DEV_BT); 603 | 604 | pr_info("Starting BT firmware\n"); 605 | /* 606 | * Write the firmware download complete magic value 0x10ADD09E at 607 | * location 0xFFFF000C (Cortus map) or C000C (AHB map). 608 | * This will let the boot-rom code execute from RAM. 609 | */ 610 | wilc->hif_func->hif_write_reg(wilc, 0x4F000c, 0x10add09e); 611 | 612 | wilc->hif_func->hif_read_reg(wilc, 0x3B0400, &val32); 613 | val32 &= ~((1ul << 2) | (1ul << 3)); 614 | wilc->hif_func->hif_write_reg(wilc, 0x3B0400, val32); 615 | 616 | msleep(100); 617 | 618 | val32 |= ((1ul << 2) | (1ul << 3)); 619 | 620 | wilc->hif_func->hif_write_reg(wilc, 0x3B0400, val32); 621 | 622 | pr_info("BT Start Succeeded\n"); 623 | 624 | release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP, DEV_BT); 625 | } 626 | 627 | static void handle_cmd_pwr_up(char *param) 628 | { 629 | pr_info("AT PWR: bt_power_up\n"); 630 | bt_init_done = 0; 631 | 632 | if (!wilc_bt->initialized && !wilc_bt->hif_func->hif_is_init(wilc_bt)) { 633 | acquire_bus(wilc_bt, WILC_BUS_ACQUIRE_ONLY, DEV_BT); 634 | if (!wilc_bt->hif_func->hif_init(wilc_bt, false)) { 635 | release_bus(wilc_bt, WILC_BUS_RELEASE_ONLY, DEV_BT); 636 | return; 637 | } 638 | release_bus(wilc_bt, WILC_BUS_RELEASE_ONLY, DEV_BT); 639 | } 640 | 641 | wilc_bt_power_up(wilc_bt, DEV_BT); 642 | } 643 | 644 | static void handle_cmd_pwr_down(char *param) 645 | { 646 | wilc_bt_power_down(wilc_bt, DEV_BT); 647 | } 648 | 649 | static void handle_cmd_chip_wake_up(char *param) 650 | { 651 | chip_wakeup(wilc_bt, DEV_BT); 652 | } 653 | 654 | static void handle_cmd_chip_allow_sleep(char *param) 655 | { 656 | bt_init_done = 1; 657 | chip_allow_sleep(wilc_bt, DEV_BT); 658 | } 659 | 660 | static void handle_cmd_download_fw(char *param) 661 | { 662 | pr_info("AT PWR: bt_download_fw\n"); 663 | 664 | wilc_bt_firmware_download(wilc_bt); 665 | wilc_bt_start(wilc_bt); 666 | } 667 | 668 | static void handle_cmd_bt_enable(char *param) 669 | { 670 | wilc_bt_power_up(wilc_bt, DEV_BT); 671 | wilc_bt_firmware_download(wilc_bt); 672 | wilc_bt_start(wilc_bt); 673 | } 674 | 675 | void wilc_bt_init(struct wilc *wilc) 676 | { 677 | wilc_bt = wilc; 678 | pr_debug("at_pwr_dev: init\n"); 679 | wilc_bt_create_device(); 680 | } 681 | 682 | void wilc_bt_deinit(void) 683 | { 684 | pr_info("at_pwr_dev: deinit\n"); 685 | 686 | if (&wilc_bt->cs != NULL) 687 | mutex_destroy(&wilc_bt->cs); 688 | 689 | cdev_del(&str_chc_dev); 690 | device_created = 0; 691 | device_destroy(chc_dev_class, chc_dev_no); 692 | class_destroy(chc_dev_class); 693 | unregister_chrdev_region(chc_dev_no, 1); 694 | pr_info("at_pwr_dev: unregistered\n"); 695 | } 696 | -------------------------------------------------------------------------------- /wilc/wilc_wlan_if.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | /* 3 | * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. 4 | * All rights reserved. 5 | */ 6 | 7 | #ifndef WILC_WLAN_IF_H 8 | #define WILC_WLAN_IF_H 9 | 10 | #include 11 | #include "wilc_debugfs.h" 12 | 13 | /******************************************** 14 | * 15 | * Host Interface Defines 16 | * 17 | ********************************************/ 18 | 19 | #define FW_WILC1000_WIFi "mchp/wilc1000_wifi_firmware.bin" 20 | #define FW_WILC3000_WIFI "mchp/wilc3000_wifi_firmware.bin" 21 | #define FW_WILC3000_BLE "mchp/wilc3000_ble_firmware.bin" 22 | 23 | enum bss_types { 24 | WILC_FW_BSS_TYPE_INFRA = 0, 25 | WILC_FW_BSS_TYPE_INDEPENDENT, 26 | WILC_FW_BSS_TYPE_AP, 27 | }; 28 | 29 | enum { 30 | WILC_FW_OPER_MODE_B_ONLY = 0, /* 1, 2 M, otherwise 5, 11 M */ 31 | WILC_FW_OPER_MODE_G_ONLY, /* 6,12,24 otherwise 9,18,36,48,54 */ 32 | WILC_FW_OPER_MODE_G_MIXED_11B_1, /* 1,2,5.5,11 otherwise all on */ 33 | WILC_FW_OPER_MODE_G_MIXED_11B_2, /* 1,2,5,11,6,12,24 otherwise all on */ 34 | }; 35 | 36 | enum { 37 | WILC_FW_PREAMBLE_SHORT = 0, /* Short Preamble */ 38 | WILC_FW_PREAMBLE_LONG = 1, /* Long Preamble */ 39 | WILC_FW_PREAMBLE_AUTO = 2, /* Auto Preamble Selection */ 40 | }; 41 | 42 | #define DEV_WIFI 0 43 | #define DEV_BT 1 44 | #define DEV_MAX 2 45 | 46 | enum { 47 | WILC_FW_PASSIVE_SCAN = 0, 48 | WILC_FW_ACTIVE_SCAN = 1, 49 | }; 50 | 51 | enum { 52 | WILC_FW_NO_POWERSAVE = 0, 53 | WILC_FW_MIN_FAST_PS = 1, 54 | WILC_FW_MAX_FAST_PS = 2, 55 | WILC_FW_MIN_PSPOLL_PS = 3, 56 | WILC_FW_MAX_PSPOLL_PS = 4 57 | }; 58 | 59 | enum bus_acquire { 60 | WILC_BUS_ACQUIRE_ONLY = 0, 61 | WILC_BUS_ACQUIRE_AND_WAKEUP = 1, 62 | }; 63 | 64 | enum bus_release { 65 | WILC_BUS_RELEASE_ONLY = 0, 66 | WILC_BUS_RELEASE_ALLOW_SLEEP = 1, 67 | }; 68 | 69 | enum { 70 | WILC_FW_NO_ENCRYPT = 0, 71 | WILC_FW_ENCRYPT_ENABLED = BIT(0), 72 | WILC_FW_WEP = BIT(1), 73 | WILC_FW_WEP_EXTENDED = BIT(2), 74 | WILC_FW_WPA = BIT(3), 75 | WILC_FW_WPA2 = BIT(4), 76 | WILC_FW_AES = BIT(5), 77 | WILC_FW_TKIP = BIT(6) 78 | }; 79 | 80 | enum { 81 | WILC_FW_SEC_NO = WILC_FW_NO_ENCRYPT, 82 | WILC_FW_SEC_WEP = WILC_FW_WEP | WILC_FW_ENCRYPT_ENABLED, 83 | WILC_FW_SEC_WEP_EXTENDED = WILC_FW_WEP_EXTENDED | WILC_FW_SEC_WEP, 84 | WILC_FW_SEC_WPA = WILC_FW_WPA | WILC_FW_ENCRYPT_ENABLED, 85 | WILC_FW_SEC_WPA_AES = WILC_FW_AES | WILC_FW_SEC_WPA, 86 | WILC_FW_SEC_WPA_TKIP = WILC_FW_TKIP | WILC_FW_SEC_WPA, 87 | WILC_FW_SEC_WPA2 = WILC_FW_WPA2 | WILC_FW_ENCRYPT_ENABLED, 88 | WILC_FW_SEC_WPA2_AES = WILC_FW_AES | WILC_FW_SEC_WPA2, 89 | WILC_FW_SEC_WPA2_TKIP = WILC_FW_TKIP | WILC_FW_SEC_WPA2 90 | }; 91 | 92 | enum authtype { 93 | WILC_FW_AUTH_OPEN_SYSTEM = 1, 94 | WILC_FW_AUTH_SHARED_KEY = 2, 95 | WILC_FW_AUTH_ANY = 3, 96 | WILC_FW_AUTH_IEEE8021 = 5 97 | }; 98 | 99 | enum site_survey { 100 | WILC_FW_SITE_SURVEY_1CH = 0, 101 | WILC_FW_SITE_SURVEY_ALL_CH = 1, 102 | WILC_FW_SITE_SURVEY_OFF = 2 103 | }; 104 | 105 | enum { 106 | WILC_FW_ACK_POLICY_NORMAL = 0, 107 | WILC_FW_ACK_NO_POLICY, 108 | }; 109 | 110 | enum { 111 | WILC_FW_REKEY_POLICY_DISABLE = 1, 112 | WILC_FW_REKEY_POLICY_TIME_BASE, 113 | WILC_FW_REKEY_POLICY_PKT_BASE, 114 | WILC_FW_REKEY_POLICY_TIME_PKT_BASE 115 | }; 116 | 117 | enum { 118 | WILC_FW_FILTER_NO = 0x00, 119 | WILC_FW_FILTER_AP_ONLY = 0x01, 120 | WILC_FW_FILTER_STA_ONLY = 0x02 121 | }; 122 | 123 | enum { 124 | WILC_FW_11N_PROT_AUTO = 0, /* Auto */ 125 | WILC_FW_11N_NO_PROT, /* Do not use any protection */ 126 | WILC_FW_11N_PROT_ERP, /* Protect all ERP frame exchanges */ 127 | WILC_FW_11N_PROT_HT, /* Protect all HT frame exchanges */ 128 | WILC_FW_11N_PROT_GF /* Protect all GF frame exchanges */ 129 | }; 130 | 131 | enum { 132 | WILC_FW_ERP_PROT_SELF_CTS, 133 | WILC_FW_ERP_PROT_RTS_CTS, 134 | }; 135 | 136 | enum { 137 | WILC_FW_11N_OP_MODE_HT_MIXED = 1, 138 | WILC_FW_11N_OP_MODE_HT_ONLY_20MHZ, 139 | WILC_FW_11N_OP_MODE_HT_ONLY_20_40MHZ, 140 | }; 141 | 142 | enum { 143 | WILC_FW_OBBS_NONHT_NO_DETECT = 0, 144 | WILC_FW_OBBS_NONHT_DETECT_ONLY = 1, 145 | WILC_FW_OBBS_NONHT_DETECT_PROTECT = 2, 146 | WILC_FW_OBBS_NONHT_DETECT_PROTECT_REPORT = 3, 147 | }; 148 | 149 | enum { 150 | WILC_FW_HT_PROT_RTS_CTS_NONHT = 0, /* RTS-CTS at non-HT rate */ 151 | WILC_FW_HT_PROT_FIRST_FRAME_NONHT, /* First frame at non-HT rate */ 152 | WILC_FW_HT_PROT_LSIG_TXOP, /* LSIG TXOP Protection */ 153 | WILC_FW_HT_PROT_FIRST_FRAME_MIXED, /* First frame at Mixed format */ 154 | }; 155 | 156 | enum { 157 | WILC_FW_SMPS_MODE_STATIC = 1, 158 | WILC_FW_SMPS_MODE_DYNAMIC = 2, 159 | WILC_FW_SMPS_MODE_MIMO = 3, /* power save disable */ 160 | }; 161 | 162 | enum { 163 | WILC_FW_TX_RATE_AUTO = 0, 164 | WILC_FW_TX_RATE_MBPS_1 = 1, 165 | WILC_FW_TX_RATE_MBPS_2 = 2, 166 | WILC_FW_TX_RATE_MBPS_5_5 = 5, 167 | WILC_FW_TX_RATE_MBPS_11 = 11, 168 | WILC_FW_TX_RATE_MBPS_6 = 6, 169 | WILC_FW_TX_RATE_MBPS_9 = 9, 170 | WILC_FW_TX_RATE_MBPS_12 = 12, 171 | WILC_FW_TX_RATE_MBPS_18 = 18, 172 | WILC_FW_TX_RATE_MBPS_24 = 24, 173 | WILC_FW_TX_RATE_MBPS_36 = 36, 174 | WILC_FW_TX_RATE_MBPS_48 = 48, 175 | WILC_FW_TX_RATE_MBPS_54 = 54 176 | }; 177 | 178 | enum { 179 | WILC_FW_DEFAULT_SCAN = 0, 180 | WILC_FW_USER_SCAN = BIT(0), 181 | WILC_FW_OBSS_PERIODIC_SCAN = BIT(1), 182 | WILC_FW_OBSS_ONETIME_SCAN = BIT(2) 183 | }; 184 | 185 | enum { 186 | WILC_FW_ACTION_FRM_IDX = 0, 187 | WILC_FW_PROBE_REQ_IDX = 1 188 | }; 189 | 190 | enum wid_type { 191 | WID_CHAR = 0, 192 | WID_SHORT = 1, 193 | WID_INT = 2, 194 | WID_STR = 3, 195 | WID_BIN_DATA = 4, 196 | WID_BIN = 5, 197 | }; 198 | 199 | enum { 200 | ANTENNA1 = 0, 201 | ANTENNA2 = 1, 202 | DIVERSITY = 2, 203 | NUM_ANT_MODE 204 | }; 205 | 206 | struct wid { 207 | u16 id; 208 | enum wid_type type; 209 | s32 size; 210 | s8 *val; 211 | }; 212 | 213 | enum { 214 | WID_NIL = 0xffff, 215 | 216 | /* 217 | * BSS Type 218 | * ----------------------------------------------------------- 219 | * Configuration : Infrastructure Independent Access Point 220 | * Values to set : 0 1 2 221 | * ----------------------------------------------------------- 222 | */ 223 | WID_BSS_TYPE = 0x0000, 224 | 225 | /* 226 | * Transmit Rate 227 | * ----------------------------------------------------------- 228 | * Configuration : 1 2 5.5 11 6 9 12 18 24 36 48 54 229 | * Values to set : 1 2 5 11 6 9 12 18 24 36 48 54 230 | * ----------------------------------------------------------- 231 | */ 232 | WID_CURRENT_TX_RATE = 0x0001, 233 | 234 | /* 235 | * Channel 236 | * ----------------------------------------------------------- 237 | * Configuration(g) : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 238 | * Values to set : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 239 | * ----------------------------------------------------------- 240 | */ 241 | WID_CURRENT_CHANNEL = 0x0002, 242 | 243 | /* 244 | * Preamble 245 | * ----------------------------------------------------------- 246 | * Configuration : short long Auto 247 | * Values to set : 0 1 2 248 | * ----------------------------------------------------------- 249 | */ 250 | WID_PREAMBLE = 0x0003, 251 | 252 | /* 253 | * 11g operating mode (ignored if 11g not present) 254 | * ----------------------------------------------------------- 255 | * Configuration : HighPerf Compat(RSet #1) Compat(RSet #2) 256 | * Values to set : 1 2 3 257 | * ----------------------------------------------------------- 258 | */ 259 | WID_11G_OPERATING_MODE = 0x0004, 260 | 261 | /* 262 | * Mac status (response only) 263 | * ----------------------------------------------------------- 264 | * Configuration : disconnect connect 265 | * Values to get : 0 1 266 | * ----------------------------------------------------------- 267 | */ 268 | WID_STATUS = 0x0005, 269 | 270 | /* 271 | * Scan type 272 | * ----------------------------------------------------------- 273 | * Configuration : Passive Scanning Active Scanning 274 | * Values to set : 0 1 275 | * ----------------------------------------------------------- 276 | */ 277 | WID_SCAN_TYPE = 0x0007, 278 | 279 | /* 280 | * Key Id (WEP default key Id) 281 | * ----------------------------------------------------------- 282 | * Configuration : Any value between 0 to 3 283 | * Values to set : Same value. Default is 0 284 | * ----------------------------------------------------------- 285 | */ 286 | WID_KEY_ID = 0x0009, 287 | 288 | /* 289 | * QoS Enable 290 | * ----------------------------------------------------------- 291 | * Configuration : QoS Disable WMM Enable 292 | * Values to set : 0 1 293 | * ----------------------------------------------------------- 294 | */ 295 | WID_QOS_ENABLE = 0x000A, 296 | 297 | /* 298 | * Power Management 299 | * ----------------------------------------------------------- 300 | * Configuration : NO_POWERSAVE MIN_POWERSAVE MAX_POWERSAVE 301 | * Values to set : 0 1 2 302 | * ----------------------------------------------------------- 303 | */ 304 | WID_POWER_MANAGEMENT = 0x000B, 305 | 306 | /* 307 | * WEP/802 11I Configuration 308 | * ----------------------------------------------------------- 309 | * Configuration:Disable WP40 WP104 WPA-AES WPA-TKIP RSN-AES RSN-TKIP 310 | * Values (0x) : 00 03 07 29 49 31 51 311 | * Configuration:WPA-AES+TKIP RSN-AES+TKIP 312 | * Values (0x) : 69 71 313 | * ----------------------------------------------------------- 314 | */ 315 | WID_11I_MODE = 0x000C, 316 | 317 | /* 318 | * WEP Configuration: Used in BSS STA mode only when WEP is enabled 319 | * ----------------------------------------------------------- 320 | * Configuration : Open System Shared Key Any Type | 802.1x Auth 321 | * Values (0x) : 01 02 03 | BIT2 322 | * ----------------------------------------------------------- 323 | */ 324 | WID_AUTH_TYPE = 0x000D, 325 | 326 | /* 327 | * Site Survey Type 328 | * ----------------------------------------------------------- 329 | * Configuration : Values to set 330 | * Survey 1 Channel : 0 331 | * survey all Channels : 1 332 | * Disable Site Survey : 2 333 | * ----------------------------------------------------------- 334 | */ 335 | WID_SITE_SURVEY = 0x000E, 336 | 337 | /* 338 | * Listen Interval 339 | * ----------------------------------------------------------- 340 | * Configuration : Any value between 1 to 255 341 | * Values to set : Same value. Default is 3 342 | * ----------------------------------------------------------- 343 | */ 344 | WID_LISTEN_INTERVAL = 0x000F, 345 | 346 | /* 347 | * DTIM Period 348 | * ----------------------------------------------------------- 349 | * Configuration : Any value between 1 to 255 350 | * Values to set : Same value. Default is 3 351 | * ----------------------------------------------------------- 352 | */ 353 | WID_DTIM_PERIOD = 0x0010, 354 | 355 | /* 356 | * ACK Policy 357 | * ----------------------------------------------------------- 358 | * Configuration : Normal Ack No Ack 359 | * Values to set : 0 1 360 | * ----------------------------------------------------------- 361 | */ 362 | WID_ACK_POLICY = 0x0011, 363 | 364 | /* 365 | * Reset MAC (Set only) 366 | * ----------------------------------------------------------- 367 | * Configuration : Don't Reset Reset No Request 368 | * Values to set : 0 1 2 369 | * ----------------------------------------------------------- 370 | */ 371 | WID_RESET = 0x0012, 372 | 373 | /* 374 | * Broadcast SSID Option: Setting this will adhere to "" SSID element 375 | * ----------------------------------------------------------- 376 | * Configuration : Enable Disable 377 | * Values to set : 1 0 378 | * ----------------------------------------------------------- 379 | */ 380 | WID_BCAST_SSID = 0x0015, 381 | 382 | /* 383 | * Disconnect (Station) 384 | * ----------------------------------------------------------- 385 | * Configuration : Association ID 386 | * Values to set : Association ID 387 | * ----------------------------------------------------------- 388 | */ 389 | WID_DISCONNECT = 0x0016, 390 | 391 | /* 392 | * 11a Tx Power Level 393 | * ----------------------------------------------------------- 394 | * Configuration : Sets TX Power (Higher the value greater the power) 395 | * Values to set : Any value between 0 and 63 (inclusive Default 48) 396 | * ----------------------------------------------------------- 397 | */ 398 | WID_TX_POWER_LEVEL_11A = 0x0018, 399 | 400 | /* 401 | * Group Key Update Policy Selection 402 | * ----------------------------------------------------------- 403 | * Configuration : Disabled timeBased packetBased timePacketBased 404 | * Values to set : 1 2 3 4 405 | * ----------------------------------------------------------- 406 | */ 407 | WID_REKEY_POLICY = 0x0019, 408 | 409 | /* 410 | * Allow Short Slot 411 | * ----------------------------------------------------------- 412 | * Configuration : Disallow Short Slot Allow Short Slot 413 | * (Enable Only Long Slot) (Enable Short Slot if applicable) 414 | * Values to set : 0 1 415 | * ----------------------------------------------------------- 416 | */ 417 | WID_SHORT_SLOT_ALLOWED = 0x001A, 418 | 419 | WID_PHY_ACTIVE_REG = 0x001B, 420 | 421 | /* 422 | * 11b Tx Power Level 423 | * ----------------------------------------------------------- 424 | * Configuration : Sets TX Power (Higher the value greater the power) 425 | * Values to set : Any value between 0 and 63 (inclusive Default 48) 426 | * ----------------------------------------------------------- 427 | */ 428 | WID_TX_POWER_LEVEL_11B = 0x001D, 429 | 430 | /* 431 | * Scan Request 432 | * ----------------------------------------------------------- 433 | * Configuration : Request default scan 434 | * Values to set : 0 435 | * ----------------------------------------------------------- 436 | */ 437 | WID_START_SCAN_REQ = 0x001E, 438 | 439 | /* 440 | * Rssi (get only) 441 | * ----------------------------------------------------------- 442 | * Configuration : 443 | * Values to get : Rssi value 444 | * ----------------------------------------------------------- 445 | */ 446 | WID_RSSI = 0x001F, 447 | 448 | /* 449 | * Join Request 450 | * ----------------------------------------------------------- 451 | * Configuration : Request to join 452 | * Values to set : index of scan result 453 | * ----------------------------------------------------------- 454 | */ 455 | WID_JOIN_REQ = 0x0020, 456 | 457 | WID_LINKSPEED = 0x0026, 458 | 459 | /* 460 | * Enable User Control of TX Power 461 | * ----------------------------------------------------------- 462 | * Configuration : Disable Enable 463 | * Values to set : 0 1 464 | * ----------------------------------------------------------- 465 | */ 466 | WID_USER_CONTROL_ON_TX_POWER = 0x0027, 467 | 468 | WID_MEMORY_ACCESS_8BIT = 0x0029, 469 | 470 | /* 471 | * Enable Auto RX Sensitivity feature 472 | * ----------------------------------------------------------- 473 | * Configuration : Disable Enable 474 | * Values to set : 0 1 475 | * ----------------------------------------------------------- 476 | */ 477 | WID_AUTO_RX_SENSITIVITY = 0x0032, 478 | 479 | /* 480 | * Receive Buffer Based Ack 481 | * ----------------------------------------------------------- 482 | * Configuration : Disable Enable 483 | * Values to set : 0 1 484 | * ----------------------------------------------------------- 485 | */ 486 | WID_DATAFLOW_CONTROL = 0x0033, 487 | 488 | /* 489 | * Scan Filter 490 | * ----------------------------------------------------------- 491 | * Configuration : Class No filter AP only Station Only 492 | * Values to set : 0 1 2 493 | * Configuration : Priority High Rssi Low Rssi Detect 494 | * Values to set : 0 0x4 0x0 495 | * Configuration : Channel filter off filter on 496 | * Values to set : 0 0x10 497 | * ----------------------------------------------------------- 498 | */ 499 | WID_SCAN_FILTER = 0x0036, 500 | 501 | /* 502 | * Link Loss Threshold (measure in the beacon period) 503 | * ----------------------------------------------------------- 504 | * Configuration : Any value between 10 and 254(Set to 255 disable) 505 | * Values to set : Same value. Default is 10 506 | * ----------------------------------------------------------- 507 | */ 508 | WID_LINK_LOSS_THRESHOLD = 0x0037, 509 | 510 | WID_ABORT_RUNNING_SCAN = 0x003E, 511 | 512 | /* NMAC Character WID list */ 513 | WID_WPS_START = 0x0043, 514 | 515 | /* 516 | * Protection mode for MAC 517 | * ----------------------------------------------------------- 518 | * Configuration : Auto No protection ERP HT GF 519 | * Values to set : 0 1 2 3 4 520 | * ----------------------------------------------------------- 521 | */ 522 | WID_11N_PROT_MECH = 0x0080, 523 | 524 | /* 525 | * ERP Protection type for MAC 526 | * ----------------------------------------------------------- 527 | * Configuration : Self-CTS RTS-CTS 528 | * Values to set : 0 1 529 | * ----------------------------------------------------------- 530 | */ 531 | WID_11N_ERP_PROT_TYPE = 0x0081, 532 | 533 | /* 534 | * HT Option Enable 535 | * ----------------------------------------------------------- 536 | * Configuration : HT Enable HT Disable 537 | * Values to set : 1 0 538 | * ----------------------------------------------------------- 539 | */ 540 | WID_11N_ENABLE = 0x0082, 541 | 542 | /* 543 | * 11n Operating mode (Note that 11g operating mode will also be 544 | * used in addition to this, if this is set to HT Mixed mode) 545 | * ----------------------------------------------------------- 546 | * Configuration : HT Mixed HT Only-20MHz HT Only-20/40MHz 547 | * Values to set : 1 2 3 548 | * ----------------------------------------------------------- 549 | */ 550 | WID_11N_OPERATING_MODE = 0x0083, 551 | 552 | /* 553 | * 11n OBSS non-HT STA Detection flag 554 | * ----------------------------------------------------------- 555 | * Configuration : Do not detect 556 | * Values to set : 0 557 | * Configuration : Detect, do not protect or report 558 | * Values to set : 1 559 | * Configuration : Detect, protect and do not report 560 | * Values to set : 2 561 | * Configuration : Detect, protect and report to other BSS 562 | * Values to set : 3 563 | * ----------------------------------------------------------- 564 | */ 565 | WID_11N_OBSS_NONHT_DETECTION = 0x0084, 566 | 567 | /* 568 | * 11n HT Protection Type 569 | * ----------------------------------------------------------- 570 | * Configuration : RTS-CTS First Frame Exchange at non-HT-rate 571 | * Values to set : 0 1 572 | * Configuration : LSIG TXOP First Frame Exchange in Mixed Fmt 573 | * Values to set : 2 3 574 | * ----------------------------------------------------------- 575 | */ 576 | WID_11N_HT_PROT_TYPE = 0x0085, 577 | 578 | /* 579 | * 11n RIFS Protection Enable Flag 580 | * ----------------------------------------------------------- 581 | * Configuration : Disable Enable 582 | * Values to set : 0 1 583 | * ----------------------------------------------------------- 584 | */ 585 | WID_11N_RIFS_PROT_ENABLE = 0x0086, 586 | 587 | /* 588 | * SMPS Mode 589 | * ----------------------------------------------------------- 590 | * Configuration : Static Dynamic MIMO (Power Save Disabled) 591 | * Values to set : 1 2 3 592 | * ----------------------------------------------------------- 593 | */ 594 | WID_11N_SMPS_MODE = 0x0087, 595 | 596 | /* 597 | * Current transmit MCS 598 | * ----------------------------------------------------------- 599 | * Configuration : MCS Index for data rate 600 | * Values to set : 0 to 7 601 | * ----------------------------------------------------------- 602 | */ 603 | WID_11N_CURRENT_TX_MCS = 0x0088, 604 | 605 | WID_11N_PRINT_STATS = 0x0089, 606 | 607 | /* 608 | * 11n Short GI Enable Flag 609 | * ----------------------------------------------------------- 610 | * Configuration : Disable Enable 611 | * Values to set : 0 1 612 | * ----------------------------------------------------------- 613 | */ 614 | WID_11N_SHORT_GI_ENABLE = 0x008D, 615 | 616 | /* 617 | * 11n RIFS Enable Flag 618 | * ----------------------------------------------------------- 619 | * Configuration : Disable Enable 620 | * Values to set : 0 1 621 | * ----------------------------------------------------------- 622 | */ 623 | WID_RIFS_MODE = 0x0094, 624 | 625 | /* 626 | * TX Abort Feature 627 | * ----------------------------------------------------------- 628 | * Configuration : Disable Self CTS Enable Self CTS 629 | * Values to set : 0 1 630 | * Configuration : Disable TX Abort Enable TX Abort 631 | * Values to set : 2 3 632 | * Configuration : Enable HW TX Abort Enable SW TX Abort 633 | * Values to set : 4 5 634 | * ----------------------------------------------------------- 635 | */ 636 | WID_TX_ABORT_CONFIG = 0x00A1, 637 | 638 | WID_REG_TSSI_11B_VALUE = 0x00A6, 639 | WID_REG_TSSI_11G_VALUE = 0x00A7, 640 | WID_REG_TSSI_11N_VALUE = 0x00A8, 641 | WID_TX_CALIBRATION = 0x00A9, 642 | WID_DSCR_TSSI_11B_VALUE = 0x00AA, 643 | WID_DSCR_TSSI_11G_VALUE = 0x00AB, 644 | WID_DSCR_TSSI_11N_VALUE = 0x00AC, 645 | 646 | /* 647 | * Immediate Block-Ack Support 648 | * ----------------------------------------------------------- 649 | * Configuration : Disable Enable 650 | * Values to set : 0 1 651 | * ----------------------------------------------------------- 652 | */ 653 | WID_11N_IMMEDIATE_BA_ENABLED = 0x00AF, 654 | 655 | /* 656 | * TXOP Disable Flag 657 | * ----------------------------------------------------------- 658 | * Configuration : Disable Enable 659 | * Values to set : 1 0 660 | * ----------------------------------------------------------- 661 | */ 662 | WID_11N_TXOP_PROT_DISABLE = 0x00B0, 663 | 664 | WID_TX_POWER_LEVEL_11N = 0x00B1, 665 | 666 | /* Custom Character WID list */ 667 | /* SCAN Complete notification WID*/ 668 | WID_SCAN_COMPLETE = 0x00C9, 669 | 670 | WID_DEL_BEACON = 0x00CA, 671 | 672 | WID_LOG_TERMINAL_SWITCH = 0x00CD, 673 | WID_TX_POWER = 0x00CE, 674 | WID_WOWLAN_TRIGGER = 0X00CF, 675 | /* EMAC Short WID list */ 676 | /* RTS Threshold */ 677 | /* 678 | * ----------------------------------------------------------- 679 | * Configuration : Any value between 256 to 2347 680 | * Values to set : Same value. Default is 2347 681 | * ----------------------------------------------------------- 682 | */ 683 | WID_RTS_THRESHOLD = 0x1000, 684 | 685 | /* 686 | * Fragmentation Threshold 687 | * ----------------------------------------------------------- 688 | * Configuration : Any value between 256 to 2346 689 | * Values to set : Same value. Default is 2346 690 | * ----------------------------------------------------------- 691 | */ 692 | WID_FRAG_THRESHOLD = 0x1001, 693 | 694 | WID_SHORT_RETRY_LIMIT = 0x1002, 695 | WID_LONG_RETRY_LIMIT = 0x1003, 696 | WID_BEACON_INTERVAL = 0x1006, 697 | WID_MEMORY_ACCESS_16BIT = 0x1008, 698 | WID_PASSIVE_SCAN_TIME = 0x100D, 699 | WID_JOIN_START_TIMEOUT = 0x100F, 700 | WID_ASOC_TIMEOUT = 0x1011, 701 | WID_11I_PROTOCOL_TIMEOUT = 0x1012, 702 | WID_EAPOL_RESPONSE_TIMEOUT = 0x1013, 703 | 704 | /* NMAC Short WID list */ 705 | WID_11N_SIG_QUAL_VAL = 0x1085, 706 | WID_CCA_THRESHOLD = 0x1087, 707 | 708 | /* Custom Short WID list */ 709 | 710 | /* EMAC Integer WID list */ 711 | WID_FAILED_COUNT = 0x2000, 712 | WID_RETRY_COUNT = 0x2001, 713 | WID_MULTIPLE_RETRY_COUNT = 0x2002, 714 | WID_FRAME_DUPLICATE_COUNT = 0x2003, 715 | WID_ACK_FAILURE_COUNT = 0x2004, 716 | WID_RECEIVED_FRAGMENT_COUNT = 0x2005, 717 | WID_MCAST_RECEIVED_FRAME_COUNT = 0x2006, 718 | WID_FCS_ERROR_COUNT = 0x2007, 719 | WID_SUCCESS_FRAME_COUNT = 0x2008, 720 | WID_HUT_TX_COUNT = 0x200A, 721 | WID_TX_FRAGMENT_COUNT = 0x200B, 722 | WID_TX_MULTICAST_FRAME_COUNT = 0x200C, 723 | WID_RTS_SUCCESS_COUNT = 0x200D, 724 | WID_RTS_FAILURE_COUNT = 0x200E, 725 | WID_WEP_UNDECRYPTABLE_COUNT = 0x200F, 726 | WID_REKEY_PERIOD = 0x2010, 727 | WID_REKEY_PACKET_COUNT = 0x2011, 728 | WID_1X_SERV_ADDR = 0x2012, 729 | WID_STACK_IP_ADDR = 0x2013, 730 | WID_STACK_NETMASK_ADDR = 0x2014, 731 | WID_HW_RX_COUNT = 0x2015, 732 | WID_MEMORY_ADDRESS = 0x201E, 733 | WID_MEMORY_ACCESS_32BIT = 0x201F, 734 | 735 | /* NMAC Integer WID list */ 736 | /* Custom Integer WID list */ 737 | WID_GET_INACTIVE_TIME = 0x2084, 738 | /* EMAC String WID list */ 739 | WID_SSID = 0x3000, 740 | WID_FIRMWARE_VERSION = 0x3001, 741 | WID_OPERATIONAL_RATE_SET = 0x3002, 742 | WID_BSSID = 0x3003, 743 | WID_WEP_KEY_VALUE = 0x3004, 744 | WID_11I_PSK = 0x3008, 745 | WID_11E_P_ACTION_REQ = 0x3009, 746 | WID_1X_KEY = 0x300A, 747 | WID_HARDWARE_VERSION = 0x300B, 748 | WID_MAC_ADDR = 0x300C, 749 | WID_HUT_DEST_ADDR = 0x300D, 750 | WID_PHY_VERSION = 0x300F, 751 | WID_SUPP_USERNAME = 0x3010, 752 | WID_SUPP_PASSWORD = 0x3011, 753 | WID_SITE_SURVEY_RESULTS = 0x3012, 754 | WID_RX_POWER_LEVEL = 0x3013, 755 | WID_SET_STA_MAC_INACTIVE_TIME = 0x3017, 756 | WID_ADD_WEP_KEY = 0x3019, 757 | WID_REMOVE_WEP_KEY = 0x301A, 758 | WID_ADD_PTK = 0x301B, 759 | WID_ADD_RX_GTK = 0x301C, 760 | WID_ADD_TX_GTK = 0x301D, 761 | WID_REMOVE_KEY = 0x301E, 762 | WID_ASSOC_REQ_INFO = 0x301F, 763 | WID_ASSOC_RES_INFO = 0x3020, 764 | WID_MANUFACTURER = 0x3026, /*Added for CAPI tool */ 765 | WID_MODEL_NAME = 0x3027, /*Added for CAPI tool */ 766 | WID_MODEL_NUM = 0x3028, /*Added for CAPI tool */ 767 | WID_DEVICE_NAME = 0x3029, /*Added for CAPI tool */ 768 | 769 | /* NMAC String WID list */ 770 | WID_SET_OPERATION_MODE = 0x3079, 771 | WID_11N_P_ACTION_REQ = 0x3080, 772 | WID_HUT_TEST_ID = 0x3081, 773 | WID_PMKID_INFO = 0x3082, 774 | WID_FIRMWARE_INFO = 0x3083, 775 | WID_REGISTER_FRAME = 0x3084, 776 | WID_DEL_ALL_STA = 0x3085, 777 | WID_REMAIN_ON_CHAN = 0x3996, 778 | WID_SSID_PROBE_REQ = 0x3997, 779 | WID_JOIN_REQ_EXTENDED = 0x3998, 780 | 781 | WID_IP_ADDRESS = 0x3999, 782 | 783 | /* Custom String WID list */ 784 | 785 | /* EMAC Binary WID list */ 786 | WID_UAPSD_CONFIG = 0x4001, 787 | WID_UAPSD_STATUS = 0x4002, 788 | WID_WMM_AP_AC_PARAMS = 0x4003, 789 | WID_WMM_STA_AC_PARAMS = 0x4004, 790 | WID_NETWORK_INFO = 0x4005, 791 | WID_STA_JOIN_INFO = 0x4006, 792 | WID_CONNECTED_STA_LIST = 0x4007, 793 | 794 | /* NMAC Binary WID list */ 795 | WID_11N_AUTORATE_TABLE = 0x4080, 796 | 797 | WID_SCAN_CHANNEL_LIST = 0x4084, 798 | 799 | WID_INFO_ELEMENT_PROBE = 0x4085, 800 | WID_INFO_ELEMENT_ASSOCIATE = 0x4086, 801 | WID_ADD_STA = 0X4087, 802 | WID_REMOVE_STA = 0X4088, 803 | WID_EDIT_STA = 0X4089, 804 | WID_ADD_BEACON = 0x408a, 805 | 806 | WID_SETUP_MULTICAST_FILTER = 0x408b, 807 | 808 | WID_ANTENNA_SELECTION = 0x408c, 809 | /* Miscellaneous WIDs */ 810 | WID_ALL = 0x7FFE, 811 | WID_MAX = 0xFFFF 812 | }; 813 | 814 | struct wilc; 815 | 816 | #endif 817 | -------------------------------------------------------------------------------- /wilc/wilc_sdio.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | /* 3 | * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. 4 | * All rights reserved. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "wilc_wfi_netdevice.h" 15 | #include "wilc_wlan.h" 16 | #include "wilc_wfi_cfgoperations.h" 17 | #include "wilc_netdev.h" 18 | 19 | enum sdio_host_lock { 20 | WILC_SDIO_HOST_NO_TAKEN = 0, 21 | WILC_SDIO_HOST_IRQ_TAKEN = 1, 22 | WILC_SDIO_HOST_DIS_TAKEN = 2, 23 | }; 24 | 25 | static enum sdio_host_lock sdio_intr_lock = WILC_SDIO_HOST_NO_TAKEN; 26 | static wait_queue_head_t sdio_intr_waitqueue; 27 | 28 | #define SDIO_MODALIAS "wilc_sdio" 29 | 30 | #define SDIO_VENDOR_ID_WILC 0x0296 31 | #define SDIO_DEVICE_ID_WILC 0x5347 32 | 33 | static const struct sdio_device_id wilc_sdio_ids[] = { 34 | { SDIO_DEVICE(SDIO_VENDOR_ID_WILC, SDIO_DEVICE_ID_WILC) }, 35 | { }, 36 | }; 37 | 38 | #define WILC_SDIO_BLOCK_SIZE 512 39 | 40 | struct wilc_sdio { 41 | bool irq_gpio; 42 | u32 block_size; 43 | int nint; 44 | bool is_init; 45 | struct wilc *wl; 46 | }; 47 | 48 | struct sdio_cmd52 { 49 | u32 read_write: 1; 50 | u32 function: 3; 51 | u32 raw: 1; 52 | u32 address: 17; 53 | u32 data: 8; 54 | }; 55 | 56 | struct sdio_cmd53 { 57 | u32 read_write: 1; 58 | u32 function: 3; 59 | u32 block_mode: 1; 60 | u32 increment: 1; 61 | u32 address: 17; 62 | u32 count: 9; 63 | u8 *buffer; 64 | u32 block_size; 65 | }; 66 | 67 | static const struct wilc_hif_func wilc_hif_sdio; 68 | 69 | static void wilc_sdio_interrupt(struct sdio_func *func) 70 | { 71 | if (sdio_intr_lock == WILC_SDIO_HOST_DIS_TAKEN) 72 | return; 73 | sdio_intr_lock = WILC_SDIO_HOST_IRQ_TAKEN; 74 | sdio_release_host(func); 75 | wilc_handle_isr(sdio_get_drvdata(func)); 76 | sdio_claim_host(func); 77 | sdio_intr_lock = WILC_SDIO_HOST_NO_TAKEN; 78 | wake_up_interruptible(&sdio_intr_waitqueue); 79 | } 80 | 81 | static int wilc_sdio_cmd52(struct wilc *wilc, struct sdio_cmd52 *cmd) 82 | { 83 | struct sdio_func *func = container_of(wilc->dev, struct sdio_func, dev); 84 | int ret; 85 | u8 data; 86 | 87 | sdio_claim_host(func); 88 | 89 | func->num = cmd->function; 90 | if (cmd->read_write) { /* write */ 91 | if (cmd->raw) { 92 | sdio_writeb(func, cmd->data, cmd->address, &ret); 93 | data = sdio_readb(func, cmd->address, &ret); 94 | cmd->data = data; 95 | } else { 96 | sdio_writeb(func, cmd->data, cmd->address, &ret); 97 | } 98 | } else { /* read */ 99 | data = sdio_readb(func, cmd->address, &ret); 100 | cmd->data = data; 101 | } 102 | 103 | sdio_release_host(func); 104 | 105 | if (ret) 106 | dev_err(&func->dev, "%s..failed, err(%d)\n", __func__, ret); 107 | return ret; 108 | } 109 | 110 | static int wilc_sdio_cmd53(struct wilc *wilc, struct sdio_cmd53 *cmd) 111 | { 112 | struct sdio_func *func = container_of(wilc->dev, struct sdio_func, dev); 113 | int size, ret; 114 | 115 | sdio_claim_host(func); 116 | 117 | func->num = cmd->function; 118 | func->cur_blksize = cmd->block_size; 119 | if (cmd->block_mode) 120 | size = cmd->count * cmd->block_size; 121 | else 122 | size = cmd->count; 123 | 124 | if (cmd->read_write) { /* write */ 125 | ret = sdio_memcpy_toio(func, cmd->address, 126 | (void *)cmd->buffer, size); 127 | } else { /* read */ 128 | ret = sdio_memcpy_fromio(func, (void *)cmd->buffer, 129 | cmd->address, size); 130 | } 131 | 132 | sdio_release_host(func); 133 | 134 | if (ret) 135 | dev_err(&func->dev, "%s..failed, err(%d)\n", __func__, ret); 136 | 137 | return ret; 138 | } 139 | 140 | static int wilc_sdio_probe(struct sdio_func *func, 141 | const struct sdio_device_id *id) 142 | { 143 | struct wilc *wilc; 144 | int ret, io_type; 145 | static bool init_power; 146 | struct wilc_sdio *sdio_priv; 147 | 148 | sdio_priv = kzalloc(sizeof(*sdio_priv), GFP_KERNEL); 149 | if (!sdio_priv) 150 | return -ENOMEM; 151 | 152 | if (IS_ENABLED(CONFIG_WILC_HW_OOB_INTR)) 153 | io_type = WILC_HIF_SDIO_GPIO_IRQ; 154 | else 155 | io_type = WILC_HIF_SDIO; 156 | dev_dbg(&func->dev, "Initializing netdev\n"); 157 | ret = wilc_cfg80211_init(&wilc, &func->dev, io_type, &wilc_hif_sdio); 158 | if (ret) { 159 | dev_err(&func->dev, "Couldn't initialize netdev\n"); 160 | kfree(sdio_priv); 161 | return ret; 162 | } 163 | sdio_set_drvdata(func, wilc); 164 | wilc->bus_data = sdio_priv; 165 | wilc->dev = &func->dev; 166 | wilc->dt_dev = &func->card->dev; 167 | sdio_priv->wl = wilc; 168 | 169 | wilc->rtc_clk = devm_clk_get(&func->card->dev, "rtc_clk"); 170 | if (PTR_ERR_OR_ZERO(wilc->rtc_clk) == -EPROBE_DEFER) 171 | return -EPROBE_DEFER; 172 | else if (!IS_ERR(wilc->rtc_clk)) 173 | clk_prepare_enable(wilc->rtc_clk); 174 | 175 | if (!init_power) { 176 | ret = wilc_wlan_power_on_sequence(wilc); 177 | if (ret) { 178 | wilc_netdev_cleanup(wilc); 179 | kfree(sdio_priv); 180 | return ret; 181 | } 182 | init_power = 1; 183 | } 184 | 185 | wilc_bt_init(wilc); 186 | 187 | dev_info(&func->dev, "Driver Initializing success\n"); 188 | return 0; 189 | } 190 | 191 | static void wilc_sdio_remove(struct sdio_func *func) 192 | { 193 | struct wilc *wilc = sdio_get_drvdata(func); 194 | 195 | if (!IS_ERR(wilc->rtc_clk)) 196 | clk_disable_unprepare(wilc->rtc_clk); 197 | 198 | wilc_netdev_cleanup(wilc); 199 | wilc_bt_deinit(); 200 | } 201 | 202 | static int wilc_sdio_reset(struct wilc *wilc) 203 | { 204 | struct sdio_cmd52 cmd; 205 | int ret; 206 | struct sdio_func *func = dev_to_sdio_func(wilc->dev); 207 | 208 | dev_info(&func->dev, "De Init SDIO\n"); 209 | 210 | cmd.read_write = 1; 211 | cmd.function = 0; 212 | cmd.raw = 0; 213 | cmd.address = 0x6; 214 | cmd.data = 0x8; 215 | ret = wilc_sdio_cmd52(wilc, &cmd); 216 | if (ret) 217 | dev_err(&func->dev, "Fail cmd 52, reset cmd\n"); 218 | return ret; 219 | } 220 | 221 | static bool wilc_sdio_is_init(struct wilc *wilc) 222 | { 223 | struct wilc_sdio *sdio_priv = wilc->bus_data; 224 | 225 | return sdio_priv->is_init; 226 | } 227 | 228 | static int wilc_sdio_suspend(struct device *dev) 229 | { 230 | struct sdio_func *func = dev_to_sdio_func(dev); 231 | struct wilc *wilc = sdio_get_drvdata(func); 232 | int ret; 233 | 234 | dev_info(&func->dev, "sdio suspend\n"); 235 | mutex_lock(&wilc->hif_cs); 236 | 237 | chip_wakeup(wilc, 0); 238 | 239 | if (mutex_is_locked(&wilc->hif_cs)) 240 | mutex_unlock(&wilc->hif_cs); 241 | 242 | host_sleep_notify(wilc, 0); 243 | chip_allow_sleep(wilc, 0); 244 | 245 | mutex_lock(&wilc->hif_cs); 246 | 247 | ret = wilc_sdio_reset(wilc); 248 | 249 | return 0; 250 | } 251 | 252 | static int wilc_sdio_enable_interrupt(struct wilc *dev) 253 | { 254 | struct sdio_func *func = container_of(dev->dev, struct sdio_func, dev); 255 | int ret = 0; 256 | 257 | sdio_intr_lock = WILC_SDIO_HOST_NO_TAKEN; 258 | 259 | sdio_claim_host(func); 260 | ret = sdio_claim_irq(func, wilc_sdio_interrupt); 261 | sdio_release_host(func); 262 | 263 | if (ret < 0) { 264 | dev_err(&func->dev, "can't claim sdio_irq, err(%d)\n", ret); 265 | ret = -EIO; 266 | } 267 | return ret; 268 | } 269 | 270 | static void wilc_sdio_disable_interrupt(struct wilc *dev) 271 | { 272 | struct sdio_func *func = container_of(dev->dev, struct sdio_func, dev); 273 | int ret; 274 | 275 | dev_info(&func->dev, "%s\n", __func__); 276 | 277 | if (sdio_intr_lock == WILC_SDIO_HOST_IRQ_TAKEN) 278 | wait_event_interruptible(sdio_intr_waitqueue, 279 | sdio_intr_lock == WILC_SDIO_HOST_NO_TAKEN); 280 | sdio_intr_lock = WILC_SDIO_HOST_DIS_TAKEN; 281 | 282 | sdio_claim_host(func); 283 | ret = sdio_release_irq(func); 284 | if (ret < 0) 285 | dev_err(&func->dev, "can't release sdio_irq, err(%d)\n", ret); 286 | sdio_release_host(func); 287 | sdio_intr_lock = WILC_SDIO_HOST_NO_TAKEN; 288 | } 289 | 290 | /******************************************** 291 | * 292 | * Function 0 293 | * 294 | ********************************************/ 295 | 296 | static int wilc_sdio_set_func0_csa_address(struct wilc *wilc, u32 adr) 297 | { 298 | struct sdio_func *func = dev_to_sdio_func(wilc->dev); 299 | struct sdio_cmd52 cmd; 300 | int ret; 301 | 302 | /** 303 | * Review: BIG ENDIAN 304 | **/ 305 | cmd.read_write = 1; 306 | cmd.function = 0; 307 | cmd.raw = 0; 308 | cmd.address = 0x10c; 309 | cmd.data = (u8)adr; 310 | ret = wilc_sdio_cmd52(wilc, &cmd); 311 | if (ret) { 312 | dev_err(&func->dev, "Failed cmd52, set 0x10c data...\n"); 313 | goto fail; 314 | } 315 | 316 | cmd.address = 0x10d; 317 | cmd.data = (u8)(adr >> 8); 318 | ret = wilc_sdio_cmd52(wilc, &cmd); 319 | if (ret) { 320 | dev_err(&func->dev, "Failed cmd52, set 0x10d data...\n"); 321 | goto fail; 322 | } 323 | 324 | cmd.address = 0x10e; 325 | cmd.data = (u8)(adr >> 16); 326 | ret = wilc_sdio_cmd52(wilc, &cmd); 327 | if (ret) { 328 | dev_err(&func->dev, "Failed cmd52, set 0x10e data...\n"); 329 | goto fail; 330 | } 331 | 332 | return 1; 333 | fail: 334 | return 0; 335 | } 336 | 337 | static int wilc_sdio_set_func0_block_size(struct wilc *wilc, u32 block_size) 338 | { 339 | struct sdio_func *func = dev_to_sdio_func(wilc->dev); 340 | struct sdio_cmd52 cmd; 341 | int ret; 342 | 343 | cmd.read_write = 1; 344 | cmd.function = 0; 345 | cmd.raw = 0; 346 | cmd.address = 0x10; 347 | cmd.data = (u8)block_size; 348 | ret = wilc_sdio_cmd52(wilc, &cmd); 349 | if (ret) { 350 | dev_err(&func->dev, "Failed cmd52, set 0x10 data...\n"); 351 | goto fail; 352 | } 353 | 354 | cmd.address = 0x11; 355 | cmd.data = (u8)(block_size >> 8); 356 | ret = wilc_sdio_cmd52(wilc, &cmd); 357 | if (ret) { 358 | dev_err(&func->dev, "Failed cmd52, set 0x11 data...\n"); 359 | goto fail; 360 | } 361 | 362 | return 1; 363 | fail: 364 | return 0; 365 | } 366 | 367 | /******************************************** 368 | * 369 | * Function 1 370 | * 371 | ********************************************/ 372 | 373 | static int wilc_sdio_set_func1_block_size(struct wilc *wilc, u32 block_size) 374 | { 375 | struct sdio_func *func = dev_to_sdio_func(wilc->dev); 376 | struct sdio_cmd52 cmd; 377 | int ret; 378 | 379 | cmd.read_write = 1; 380 | cmd.function = 0; 381 | cmd.raw = 0; 382 | cmd.address = 0x110; 383 | cmd.data = (u8)block_size; 384 | ret = wilc_sdio_cmd52(wilc, &cmd); 385 | if (ret) { 386 | dev_err(&func->dev, "Failed cmd52, set 0x110 data...\n"); 387 | goto fail; 388 | } 389 | cmd.address = 0x111; 390 | cmd.data = (u8)(block_size >> 8); 391 | ret = wilc_sdio_cmd52(wilc, &cmd); 392 | if (ret) { 393 | dev_err(&func->dev, "Failed cmd52, set 0x111 data...\n"); 394 | goto fail; 395 | } 396 | 397 | return 1; 398 | fail: 399 | return 0; 400 | } 401 | 402 | /******************************************** 403 | * 404 | * Sdio interfaces 405 | * 406 | ********************************************/ 407 | static int wilc_sdio_write_reg(struct wilc *wilc, u32 addr, u32 data) 408 | { 409 | struct sdio_func *func = dev_to_sdio_func(wilc->dev); 410 | struct wilc_sdio *sdio_priv = wilc->bus_data; 411 | int ret; 412 | 413 | cpu_to_le32s(&data); 414 | 415 | if (addr >= 0xf0 && addr <= 0xff) { 416 | struct sdio_cmd52 cmd; 417 | 418 | cmd.read_write = 1; 419 | cmd.function = 0; 420 | cmd.raw = 0; 421 | cmd.address = addr; 422 | cmd.data = data; 423 | ret = wilc_sdio_cmd52(wilc, &cmd); 424 | if (ret) { 425 | dev_err(&func->dev, 426 | "Failed cmd 52, write reg %08x ...\n", addr); 427 | goto fail; 428 | } 429 | } else { 430 | struct sdio_cmd53 cmd; 431 | 432 | /** 433 | * set the AHB address 434 | **/ 435 | if (!wilc_sdio_set_func0_csa_address(wilc, addr)) 436 | goto fail; 437 | 438 | cmd.read_write = 1; 439 | cmd.function = 0; 440 | cmd.address = 0x10f; 441 | cmd.block_mode = 0; 442 | cmd.increment = 1; 443 | cmd.count = 4; 444 | cmd.buffer = (u8 *)&data; 445 | cmd.block_size = sdio_priv->block_size; 446 | ret = wilc_sdio_cmd53(wilc, &cmd); 447 | if (ret) { 448 | dev_err(&func->dev, 449 | "Failed cmd53, write reg (%08x)...\n", addr); 450 | goto fail; 451 | } 452 | } 453 | 454 | return 1; 455 | 456 | fail: 457 | 458 | return 0; 459 | } 460 | 461 | static int wilc_sdio_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size) 462 | { 463 | struct sdio_func *func = dev_to_sdio_func(wilc->dev); 464 | struct wilc_sdio *sdio_priv = wilc->bus_data; 465 | u32 block_size = sdio_priv->block_size; 466 | struct sdio_cmd53 cmd; 467 | int nblk, nleft, ret; 468 | 469 | cmd.read_write = 1; 470 | if (addr > 0) { 471 | /** 472 | * has to be word aligned... 473 | **/ 474 | if (size & 0x3) { 475 | size += 4; 476 | size &= ~0x3; 477 | } 478 | 479 | /** 480 | * func 0 access 481 | **/ 482 | cmd.function = 0; 483 | cmd.address = 0x10f; 484 | } else { 485 | /** 486 | * has to be word aligned... 487 | **/ 488 | if (size & 0x3) { 489 | size += 4; 490 | size &= ~0x3; 491 | } 492 | 493 | /** 494 | * func 1 access 495 | **/ 496 | cmd.function = 1; 497 | cmd.address = 0; 498 | } 499 | 500 | nblk = size / block_size; 501 | nleft = size % block_size; 502 | 503 | if (nblk > 0) { 504 | cmd.block_mode = 1; 505 | cmd.increment = 1; 506 | cmd.count = nblk; 507 | cmd.buffer = buf; 508 | cmd.block_size = block_size; 509 | if (addr > 0) { 510 | if (!wilc_sdio_set_func0_csa_address(wilc, addr)) 511 | goto fail; 512 | } 513 | ret = wilc_sdio_cmd53(wilc, &cmd); 514 | if (ret) { 515 | dev_err(&func->dev, 516 | "Failed cmd53 [%x], block send...\n", addr); 517 | goto fail; 518 | } 519 | if (addr > 0) 520 | addr += nblk * block_size; 521 | buf += nblk * block_size; 522 | } 523 | 524 | if (nleft > 0) { 525 | cmd.block_mode = 0; 526 | cmd.increment = 1; 527 | cmd.count = nleft; 528 | cmd.buffer = buf; 529 | 530 | cmd.block_size = block_size; 531 | 532 | if (addr > 0) { 533 | if (!wilc_sdio_set_func0_csa_address(wilc, addr)) 534 | goto fail; 535 | } 536 | ret = wilc_sdio_cmd53(wilc, &cmd); 537 | if (ret) { 538 | dev_err(&func->dev, 539 | "Failed cmd53 [%x], bytes send...\n", addr); 540 | goto fail; 541 | } 542 | } 543 | 544 | return 1; 545 | 546 | fail: 547 | 548 | return 0; 549 | } 550 | 551 | static int wilc_sdio_read_reg(struct wilc *wilc, u32 addr, u32 *data) 552 | { 553 | struct sdio_func *func = dev_to_sdio_func(wilc->dev); 554 | struct wilc_sdio *sdio_priv = wilc->bus_data; 555 | int ret; 556 | 557 | if (addr >= 0xf0 && addr <= 0xff) { 558 | struct sdio_cmd52 cmd; 559 | 560 | cmd.read_write = 0; 561 | cmd.function = 0; 562 | cmd.raw = 0; 563 | cmd.address = addr; 564 | ret = wilc_sdio_cmd52(wilc, &cmd); 565 | if (ret) { 566 | dev_err(&func->dev, 567 | "Failed cmd 52, read reg (%08x) ...\n", addr); 568 | goto fail; 569 | } 570 | *data = cmd.data; 571 | } else { 572 | struct sdio_cmd53 cmd; 573 | 574 | if (!wilc_sdio_set_func0_csa_address(wilc, addr)) 575 | goto fail; 576 | 577 | cmd.read_write = 0; 578 | cmd.function = 0; 579 | cmd.address = 0x10f; 580 | cmd.block_mode = 0; 581 | cmd.increment = 1; 582 | cmd.count = 4; 583 | cmd.buffer = (u8 *)data; 584 | 585 | cmd.block_size = sdio_priv->block_size; 586 | ret = wilc_sdio_cmd53(wilc, &cmd); 587 | if (ret) { 588 | dev_err(&func->dev, 589 | "Failed cmd53, read reg (%08x)...\n", addr); 590 | goto fail; 591 | } 592 | } 593 | 594 | le32_to_cpus(data); 595 | 596 | return 1; 597 | 598 | fail: 599 | 600 | return 0; 601 | } 602 | 603 | static int wilc_sdio_read(struct wilc *wilc, u32 addr, u8 *buf, u32 size) 604 | { 605 | struct sdio_func *func = dev_to_sdio_func(wilc->dev); 606 | struct wilc_sdio *sdio_priv = wilc->bus_data; 607 | u32 block_size = sdio_priv->block_size; 608 | struct sdio_cmd53 cmd; 609 | int nblk, nleft, ret; 610 | 611 | cmd.read_write = 0; 612 | if (addr > 0) { 613 | /** 614 | * has to be word aligned... 615 | **/ 616 | if (size & 0x3) { 617 | size += 4; 618 | size &= ~0x3; 619 | } 620 | 621 | /** 622 | * func 0 access 623 | **/ 624 | cmd.function = 0; 625 | cmd.address = 0x10f; 626 | } else { 627 | /** 628 | * has to be word aligned... 629 | **/ 630 | if (size & 0x3) { 631 | size += 4; 632 | size &= ~0x3; 633 | } 634 | 635 | /** 636 | * func 1 access 637 | **/ 638 | cmd.function = 1; 639 | cmd.address = 0; 640 | } 641 | 642 | nblk = size / block_size; 643 | nleft = size % block_size; 644 | 645 | if (nblk > 0) { 646 | cmd.block_mode = 1; 647 | cmd.increment = 1; 648 | cmd.count = nblk; 649 | cmd.buffer = buf; 650 | cmd.block_size = block_size; 651 | if (addr > 0) { 652 | if (!wilc_sdio_set_func0_csa_address(wilc, addr)) 653 | goto fail; 654 | } 655 | ret = wilc_sdio_cmd53(wilc, &cmd); 656 | if (ret) { 657 | dev_err(&func->dev, 658 | "Failed cmd53 [%x], block read...\n", addr); 659 | goto fail; 660 | } 661 | if (addr > 0) 662 | addr += nblk * block_size; 663 | buf += nblk * block_size; 664 | } /* if (nblk > 0) */ 665 | 666 | if (nleft > 0) { 667 | cmd.block_mode = 0; 668 | cmd.increment = 1; 669 | cmd.count = nleft; 670 | cmd.buffer = buf; 671 | 672 | cmd.block_size = block_size; 673 | 674 | if (addr > 0) { 675 | if (!wilc_sdio_set_func0_csa_address(wilc, addr)) 676 | goto fail; 677 | } 678 | ret = wilc_sdio_cmd53(wilc, &cmd); 679 | if (ret) { 680 | dev_err(&func->dev, 681 | "Failed cmd53 [%x], bytes read...\n", addr); 682 | goto fail; 683 | } 684 | } 685 | 686 | return 1; 687 | 688 | fail: 689 | 690 | return 0; 691 | } 692 | 693 | /******************************************** 694 | * 695 | * Bus interfaces 696 | * 697 | ********************************************/ 698 | 699 | static int wilc_sdio_deinit(struct wilc *wilc) 700 | { 701 | struct wilc_sdio *sdio_priv = wilc->bus_data; 702 | 703 | sdio_priv->is_init = false; 704 | 705 | return 1; 706 | } 707 | 708 | static int wilc_sdio_init(struct wilc *wilc, bool resume) 709 | { 710 | struct sdio_func *func = dev_to_sdio_func(wilc->dev); 711 | struct wilc_sdio *sdio_priv = wilc->bus_data; 712 | struct sdio_cmd52 cmd; 713 | int loop, ret; 714 | u32 chipid; 715 | 716 | dev_info(&func->dev, "SDIO speed: %d\n", 717 | func->card->host->ios.clock); 718 | 719 | /* Patch for sdio interrupt latency issue */ 720 | pm_runtime_get_sync(mmc_dev(func->card->host)); 721 | 722 | init_waitqueue_head(&sdio_intr_waitqueue); 723 | sdio_priv->irq_gpio = (wilc->io_type == WILC_HIF_SDIO_GPIO_IRQ); 724 | 725 | /** 726 | * function 0 csa enable 727 | **/ 728 | cmd.read_write = 1; 729 | cmd.function = 0; 730 | cmd.raw = 1; 731 | cmd.address = 0x100; 732 | cmd.data = 0x80; 733 | ret = wilc_sdio_cmd52(wilc, &cmd); 734 | if (ret) { 735 | dev_err(&func->dev, "Fail cmd 52, enable csa...\n"); 736 | goto fail; 737 | } 738 | 739 | /** 740 | * function 0 block size 741 | **/ 742 | if (!wilc_sdio_set_func0_block_size(wilc, WILC_SDIO_BLOCK_SIZE)) { 743 | dev_err(&func->dev, "Fail cmd 52, set func 0 block size...\n"); 744 | goto fail; 745 | } 746 | sdio_priv->block_size = WILC_SDIO_BLOCK_SIZE; 747 | 748 | /** 749 | * enable func1 IO 750 | **/ 751 | cmd.read_write = 1; 752 | cmd.function = 0; 753 | cmd.raw = 1; 754 | cmd.address = 0x2; 755 | cmd.data = 0x2; 756 | ret = wilc_sdio_cmd52(wilc, &cmd); 757 | if (ret) { 758 | dev_err(&func->dev, 759 | "Fail cmd 52, set IOE register...\n"); 760 | goto fail; 761 | } 762 | 763 | /** 764 | * make sure func 1 is up 765 | **/ 766 | cmd.read_write = 0; 767 | cmd.function = 0; 768 | cmd.raw = 0; 769 | cmd.address = 0x3; 770 | loop = 3; 771 | do { 772 | cmd.data = 0; 773 | ret = wilc_sdio_cmd52(wilc, &cmd); 774 | if (ret) { 775 | dev_err(&func->dev, 776 | "Fail cmd 52, get IOR register...\n"); 777 | goto fail; 778 | } 779 | if (cmd.data == 0x2) 780 | break; 781 | } while (loop--); 782 | 783 | if (loop <= 0) { 784 | dev_err(&func->dev, "Fail func 1 is not ready...\n"); 785 | goto fail; 786 | } 787 | 788 | /** 789 | * func 1 is ready, set func 1 block size 790 | **/ 791 | if (!wilc_sdio_set_func1_block_size(wilc, WILC_SDIO_BLOCK_SIZE)) { 792 | dev_err(&func->dev, "Fail set func 1 block size...\n"); 793 | goto fail; 794 | } 795 | 796 | /** 797 | * func 1 interrupt enable 798 | **/ 799 | cmd.read_write = 1; 800 | cmd.function = 0; 801 | cmd.raw = 1; 802 | cmd.address = 0x4; 803 | cmd.data = 0x3; 804 | ret = wilc_sdio_cmd52(wilc, &cmd); 805 | if (ret) { 806 | dev_err(&func->dev, "Fail cmd 52, set IEN register...\n"); 807 | goto fail; 808 | } 809 | 810 | /** 811 | * make sure can read back chip id correctly 812 | **/ 813 | if (!resume) { 814 | chipid = wilc_get_chipid(wilc, true); 815 | if (is_wilc3000(chipid)) { 816 | wilc->chip = WILC_3000; 817 | } else if (is_wilc1000(chipid)) { 818 | wilc->chip = WILC_1000; 819 | } else { 820 | dev_err(&func->dev, "Unsupported chipid: %x\n", chipid); 821 | goto fail; 822 | } 823 | dev_info(&func->dev, "chipid %08x\n", chipid); 824 | } 825 | 826 | sdio_priv->is_init = true; 827 | 828 | return 1; 829 | 830 | fail: 831 | 832 | return 0; 833 | } 834 | 835 | static int wilc_sdio_read_size(struct wilc *wilc, u32 *size) 836 | { 837 | u32 tmp; 838 | struct sdio_cmd52 cmd; 839 | 840 | /** 841 | * Read DMA count in words 842 | **/ 843 | cmd.read_write = 0; 844 | cmd.function = 0; 845 | cmd.raw = 0; 846 | cmd.address = 0xf2; 847 | cmd.data = 0; 848 | wilc_sdio_cmd52(wilc, &cmd); 849 | tmp = cmd.data; 850 | 851 | cmd.address = 0xf3; 852 | cmd.data = 0; 853 | wilc_sdio_cmd52(wilc, &cmd); 854 | tmp |= (cmd.data << 8); 855 | 856 | *size = tmp; 857 | return 1; 858 | } 859 | 860 | static int wilc_sdio_read_int(struct wilc *wilc, u32 *int_status) 861 | { 862 | struct sdio_func *func = dev_to_sdio_func(wilc->dev); 863 | struct wilc_sdio *sdio_priv = wilc->bus_data; 864 | u32 tmp; 865 | struct sdio_cmd52 cmd; 866 | u32 irq_flags; 867 | int i; 868 | 869 | if (sdio_priv->irq_gpio) { 870 | wilc_sdio_read_size(wilc, &tmp); 871 | 872 | cmd.read_write = 0; 873 | cmd.function = 1; 874 | cmd.raw = 0; 875 | cmd.data = 0; 876 | if (wilc->chip == WILC_1000) { 877 | cmd.address = 0xf7; 878 | wilc_sdio_cmd52(wilc, &cmd); 879 | irq_flags = cmd.data & 0x1f; 880 | } else { 881 | cmd.address = 0xfe; 882 | wilc_sdio_cmd52(wilc, &cmd); 883 | irq_flags = cmd.data & 0x0f; 884 | } 885 | tmp |= ((irq_flags >> 0) << IRG_FLAGS_OFFSET); 886 | 887 | *int_status = tmp; 888 | } else { 889 | wilc_sdio_read_size(wilc, &tmp); 890 | cmd.read_write = 0; 891 | cmd.function = 1; 892 | cmd.address = 0x04; 893 | cmd.data = 0; 894 | wilc_sdio_cmd52(wilc, &cmd); 895 | 896 | if (cmd.data & BIT(0)) 897 | tmp |= INT_0; 898 | if (cmd.data & BIT(2)) 899 | tmp |= INT_1; 900 | if (cmd.data & BIT(3)) 901 | tmp |= INT_2; 902 | if (cmd.data & BIT(4)) 903 | tmp |= INT_3; 904 | if (cmd.data & BIT(5)) 905 | tmp |= INT_4; 906 | 907 | for (i = sdio_priv->nint; i < MAX_NUM_INT; i++) { 908 | if ((tmp >> (IRG_FLAGS_OFFSET + i)) & 0x1) { 909 | dev_err(&func->dev, 910 | "Unexpected interrupt (1) : tmp=%x, data=%x\n", 911 | tmp, cmd.data); 912 | break; 913 | } 914 | } 915 | 916 | *int_status = tmp; 917 | 918 | } 919 | 920 | return 1; 921 | } 922 | 923 | static int wilc_sdio_clear_int_ext(struct wilc *wilc, u32 val) 924 | { 925 | struct sdio_func *func = dev_to_sdio_func(wilc->dev); 926 | struct wilc_sdio *sdio_priv = wilc->bus_data; 927 | int ret; 928 | u32 reg = 0; 929 | 930 | if (wilc->chip == WILC_1000) { 931 | if (sdio_priv->irq_gpio) 932 | reg = val & (BIT(MAX_NUM_INT) - 1); 933 | 934 | /* select VMM table 0 */ 935 | if (val & SEL_VMM_TBL0) 936 | reg |= BIT(5); 937 | /* select VMM table 1 */ 938 | if (val & SEL_VMM_TBL1) 939 | reg |= BIT(6); 940 | /* enable VMM */ 941 | if (val & EN_VMM) 942 | reg |= BIT(7); 943 | if (reg) { 944 | struct sdio_cmd52 cmd; 945 | 946 | cmd.read_write = 1; 947 | cmd.function = 0; 948 | cmd.raw = 0; 949 | cmd.address = 0xf8; 950 | cmd.data = reg; 951 | 952 | ret = wilc_sdio_cmd52(wilc, &cmd); 953 | if (ret) { 954 | dev_err(&func->dev, 955 | "Failed cmd52, set 0xf8 data (%d) ...\n", 956 | __LINE__); 957 | goto fail; 958 | } 959 | } 960 | } else { 961 | if (sdio_priv->irq_gpio) { 962 | reg = val & (BIT(MAX_NUM_INT) - 1); 963 | if (reg) { 964 | struct sdio_cmd52 cmd; 965 | 966 | cmd.read_write = 1; 967 | cmd.function = 0; 968 | cmd.raw = 0; 969 | cmd.address = 0xfe; 970 | cmd.data = reg; 971 | 972 | ret = wilc_sdio_cmd52(wilc, &cmd); 973 | if (ret) { 974 | dev_err(&func->dev, 975 | "Failed cmd52, set 0xf8 data (%d) ...\n", 976 | __LINE__); 977 | goto fail; 978 | } 979 | } 980 | } 981 | /* select VMM table 0 */ 982 | if (val & SEL_VMM_TBL0) 983 | reg |= BIT(0); 984 | /* select VMM table 1 */ 985 | if (val & SEL_VMM_TBL1) 986 | reg |= BIT(1); 987 | /* enable VMM */ 988 | if (val & EN_VMM) 989 | reg |= BIT(2); 990 | 991 | if (reg) { 992 | struct sdio_cmd52 cmd; 993 | 994 | cmd.read_write = 1; 995 | cmd.function = 0; 996 | cmd.raw = 0; 997 | cmd.address = 0xf1; 998 | cmd.data = reg; 999 | 1000 | ret = wilc_sdio_cmd52(wilc, &cmd); 1001 | if (ret) { 1002 | dev_err(&func->dev, 1003 | "Failed cmd52, set 0xf6 data (%d) ...\n", 1004 | __LINE__); 1005 | goto fail; 1006 | } 1007 | } 1008 | } 1009 | 1010 | return 1; 1011 | fail: 1012 | return 0; 1013 | } 1014 | 1015 | static int wilc_sdio_sync_ext(struct wilc *wilc, int nint) 1016 | { 1017 | struct sdio_func *func = dev_to_sdio_func(wilc->dev); 1018 | struct wilc_sdio *sdio_priv = wilc->bus_data; 1019 | u32 reg; 1020 | int ret, i; 1021 | 1022 | if (nint > MAX_NUM_INT) { 1023 | dev_err(&func->dev, "Too many interrupts %d\n", nint); 1024 | return 0; 1025 | } 1026 | 1027 | sdio_priv->nint = nint; 1028 | 1029 | /* WILC3000 only. Was removed in WILC1000 on revision 6200. 1030 | * Might be related to suspend/resume 1031 | */ 1032 | if (wilc->chip == WILC_3000) { 1033 | /** 1034 | * Disable power sequencer 1035 | **/ 1036 | if (!wilc_sdio_read_reg(wilc, WILC_MISC, ®)) { 1037 | dev_err(&func->dev, "Failed read misc reg\n"); 1038 | return 0; 1039 | } 1040 | reg &= ~BIT(8); 1041 | if (!wilc_sdio_write_reg(wilc, WILC_MISC, reg)) { 1042 | dev_err(&func->dev, "Failed write misc reg\n"); 1043 | return 0; 1044 | } 1045 | } 1046 | 1047 | if (sdio_priv->irq_gpio) { 1048 | /** 1049 | * interrupt pin mux select 1050 | **/ 1051 | ret = wilc_sdio_read_reg(wilc, WILC_PIN_MUX_0, ®); 1052 | if (!ret) { 1053 | dev_err(&func->dev, "Failed read reg (%08x)...\n", 1054 | WILC_PIN_MUX_0); 1055 | return 0; 1056 | } 1057 | reg |= BIT(8); 1058 | ret = wilc_sdio_write_reg(wilc, WILC_PIN_MUX_0, reg); 1059 | if (!ret) { 1060 | dev_err(&func->dev, "Failed write reg (%08x)...\n", 1061 | WILC_PIN_MUX_0); 1062 | return 0; 1063 | } 1064 | 1065 | /** 1066 | * interrupt enable 1067 | **/ 1068 | ret = wilc_sdio_read_reg(wilc, WILC_INTR_ENABLE, ®); 1069 | if (!ret) { 1070 | dev_err(&func->dev, "Failed read reg (%08x)...\n", 1071 | WILC_INTR_ENABLE); 1072 | return 0; 1073 | } 1074 | 1075 | for (i = 0; (i < 5) && (nint > 0); i++, nint--) 1076 | reg |= BIT((27 + i)); 1077 | ret = wilc_sdio_write_reg(wilc, WILC_INTR_ENABLE, reg); 1078 | if (!ret) { 1079 | dev_err(&func->dev, "Failed write reg (%08x)...\n", 1080 | WILC_INTR_ENABLE); 1081 | return 0; 1082 | } 1083 | if (nint) { 1084 | ret = wilc_sdio_read_reg(wilc, WILC_INTR2_ENABLE, ®); 1085 | if (!ret) { 1086 | dev_err(&func->dev, 1087 | "Failed read reg (%08x)...\n", 1088 | WILC_INTR2_ENABLE); 1089 | return 0; 1090 | } 1091 | 1092 | for (i = 0; (i < 3) && (nint > 0); i++, nint--) 1093 | reg |= BIT(i); 1094 | 1095 | ret = wilc_sdio_write_reg(wilc, WILC_INTR2_ENABLE, reg); 1096 | if (!ret) { 1097 | dev_err(&func->dev, 1098 | "Failed write reg (%08x)...\n", 1099 | WILC_INTR2_ENABLE); 1100 | return 0; 1101 | } 1102 | } 1103 | } 1104 | return 1; 1105 | } 1106 | 1107 | /* Global sdio HIF function table */ 1108 | static const struct wilc_hif_func wilc_hif_sdio = { 1109 | .hif_init = wilc_sdio_init, 1110 | .hif_deinit = wilc_sdio_deinit, 1111 | .hif_read_reg = wilc_sdio_read_reg, 1112 | .hif_write_reg = wilc_sdio_write_reg, 1113 | .hif_block_rx = wilc_sdio_read, 1114 | .hif_block_tx = wilc_sdio_write, 1115 | .hif_read_int = wilc_sdio_read_int, 1116 | .hif_clear_int_ext = wilc_sdio_clear_int_ext, 1117 | .hif_read_size = wilc_sdio_read_size, 1118 | .hif_block_tx_ext = wilc_sdio_write, 1119 | .hif_block_rx_ext = wilc_sdio_read, 1120 | .hif_sync_ext = wilc_sdio_sync_ext, 1121 | .enable_interrupt = wilc_sdio_enable_interrupt, 1122 | .disable_interrupt = wilc_sdio_disable_interrupt, 1123 | .hif_reset = wilc_sdio_reset, 1124 | .hif_is_init = wilc_sdio_is_init, 1125 | }; 1126 | 1127 | static int wilc_sdio_resume(struct device *dev) 1128 | { 1129 | struct sdio_func *func = dev_to_sdio_func(dev); 1130 | struct wilc *wilc = sdio_get_drvdata(func); 1131 | 1132 | dev_info(&func->dev, "sdio resume\n"); 1133 | chip_wakeup(wilc, 0); 1134 | wilc_sdio_init(wilc, true); 1135 | 1136 | if (mutex_is_locked(&wilc->hif_cs)) 1137 | mutex_unlock(&wilc->hif_cs); 1138 | 1139 | host_wakeup_notify(wilc, 0); 1140 | 1141 | mutex_lock(&wilc->hif_cs); 1142 | 1143 | chip_allow_sleep(wilc, 0); 1144 | 1145 | if (mutex_is_locked(&wilc->hif_cs)) 1146 | mutex_unlock(&wilc->hif_cs); 1147 | 1148 | return 0; 1149 | } 1150 | 1151 | static const struct of_device_id wilc_of_match[] = { 1152 | { .compatible = "microchip,wilc1000", }, 1153 | { .compatible = "microchip,wilc3000", }, 1154 | { /* sentinel */} 1155 | }; 1156 | MODULE_DEVICE_TABLE(of, wilc_of_match); 1157 | 1158 | static const struct dev_pm_ops wilc_sdio_pm_ops = { 1159 | .suspend = wilc_sdio_suspend, 1160 | .resume = wilc_sdio_resume, 1161 | }; 1162 | 1163 | static struct sdio_driver wilc_sdio_driver = { 1164 | .name = SDIO_MODALIAS, 1165 | .id_table = wilc_sdio_ids, 1166 | .probe = wilc_sdio_probe, 1167 | .remove = wilc_sdio_remove, 1168 | .drv = { 1169 | .pm = &wilc_sdio_pm_ops, 1170 | .of_match_table = wilc_of_match, 1171 | } 1172 | }; 1173 | module_driver(wilc_sdio_driver, 1174 | sdio_register_driver, 1175 | sdio_unregister_driver); 1176 | MODULE_LICENSE("GPL"); 1177 | MODULE_VERSION("15.3"); 1178 | 1179 | -------------------------------------------------------------------------------- /wilc/wilc_spi.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | /* 3 | * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. 4 | * All rights reserved. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "wilc_wfi_netdevice.h" 12 | #include "wilc_wfi_cfgoperations.h" 13 | #include "wilc_netdev.h" 14 | 15 | struct wilc_spi { 16 | int crc_off; 17 | int nint; 18 | bool is_init; 19 | }; 20 | 21 | static const struct wilc_hif_func wilc_hif_spi; 22 | 23 | static int wilc_spi_rx(struct wilc *wilc, u8 *rb, u32 rlen); 24 | static int wilc_spi_reset(struct wilc *wilc); 25 | 26 | /******************************************** 27 | * 28 | * Crc7 29 | * 30 | ********************************************/ 31 | 32 | static const u8 crc7_syndrome_table[256] = { 33 | 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 34 | 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77, 35 | 0x19, 0x10, 0x0b, 0x02, 0x3d, 0x34, 0x2f, 0x26, 36 | 0x51, 0x58, 0x43, 0x4a, 0x75, 0x7c, 0x67, 0x6e, 37 | 0x32, 0x3b, 0x20, 0x29, 0x16, 0x1f, 0x04, 0x0d, 38 | 0x7a, 0x73, 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45, 39 | 0x2b, 0x22, 0x39, 0x30, 0x0f, 0x06, 0x1d, 0x14, 40 | 0x63, 0x6a, 0x71, 0x78, 0x47, 0x4e, 0x55, 0x5c, 41 | 0x64, 0x6d, 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b, 42 | 0x2c, 0x25, 0x3e, 0x37, 0x08, 0x01, 0x1a, 0x13, 43 | 0x7d, 0x74, 0x6f, 0x66, 0x59, 0x50, 0x4b, 0x42, 44 | 0x35, 0x3c, 0x27, 0x2e, 0x11, 0x18, 0x03, 0x0a, 45 | 0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69, 46 | 0x1e, 0x17, 0x0c, 0x05, 0x3a, 0x33, 0x28, 0x21, 47 | 0x4f, 0x46, 0x5d, 0x54, 0x6b, 0x62, 0x79, 0x70, 48 | 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31, 0x38, 49 | 0x41, 0x48, 0x53, 0x5a, 0x65, 0x6c, 0x77, 0x7e, 50 | 0x09, 0x00, 0x1b, 0x12, 0x2d, 0x24, 0x3f, 0x36, 51 | 0x58, 0x51, 0x4a, 0x43, 0x7c, 0x75, 0x6e, 0x67, 52 | 0x10, 0x19, 0x02, 0x0b, 0x34, 0x3d, 0x26, 0x2f, 53 | 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, 54 | 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 55 | 0x6a, 0x63, 0x78, 0x71, 0x4e, 0x47, 0x5c, 0x55, 56 | 0x22, 0x2b, 0x30, 0x39, 0x06, 0x0f, 0x14, 0x1d, 57 | 0x25, 0x2c, 0x37, 0x3e, 0x01, 0x08, 0x13, 0x1a, 58 | 0x6d, 0x64, 0x7f, 0x76, 0x49, 0x40, 0x5b, 0x52, 59 | 0x3c, 0x35, 0x2e, 0x27, 0x18, 0x11, 0x0a, 0x03, 60 | 0x74, 0x7d, 0x66, 0x6f, 0x50, 0x59, 0x42, 0x4b, 61 | 0x17, 0x1e, 0x05, 0x0c, 0x33, 0x3a, 0x21, 0x28, 62 | 0x5f, 0x56, 0x4d, 0x44, 0x7b, 0x72, 0x69, 0x60, 63 | 0x0e, 0x07, 0x1c, 0x15, 0x2a, 0x23, 0x38, 0x31, 64 | 0x46, 0x4f, 0x54, 0x5d, 0x62, 0x6b, 0x70, 0x79 65 | }; 66 | 67 | static u8 crc7_byte(u8 crc, u8 data) 68 | { 69 | return crc7_syndrome_table[(crc << 1) ^ data]; 70 | } 71 | 72 | static u8 crc7(u8 crc, const u8 *buffer, u32 len) 73 | { 74 | while (len--) 75 | crc = crc7_byte(crc, *buffer++); 76 | return crc; 77 | } 78 | 79 | /******************************************** 80 | * 81 | * Spi protocol Function 82 | * 83 | ********************************************/ 84 | 85 | #define CMD_DMA_WRITE 0xc1 86 | #define CMD_DMA_READ 0xc2 87 | #define CMD_INTERNAL_WRITE 0xc3 88 | #define CMD_INTERNAL_READ 0xc4 89 | #define CMD_TERMINATE 0xc5 90 | #define CMD_REPEAT 0xc6 91 | #define CMD_DMA_EXT_WRITE 0xc7 92 | #define CMD_DMA_EXT_READ 0xc8 93 | #define CMD_SINGLE_WRITE 0xc9 94 | #define CMD_SINGLE_READ 0xca 95 | #define CMD_RESET 0xcf 96 | 97 | #define N_OK 1 98 | #define N_FAIL 0 99 | #define N_RESET -1 100 | #define N_RETRY -2 101 | 102 | #define SPI_RESP_RETRY_COUNT (10) 103 | #define SPI_RETRY_COUNT (10) 104 | #define DATA_PKT_SZ_256 256 105 | #define DATA_PKT_SZ_512 512 106 | #define DATA_PKT_SZ_1K 1024 107 | #define DATA_PKT_SZ_2K (2 * 1024) 108 | #define DATA_PKT_SZ_4K (4 * 1024) 109 | #define DATA_PKT_SZ_8K (8 * 1024) 110 | #define DATA_PKT_SZ DATA_PKT_SZ_8K 111 | 112 | #define USE_SPI_DMA 0 113 | 114 | static int wilc_bus_probe(struct spi_device *spi) 115 | { 116 | int ret; 117 | static bool init_power; 118 | struct wilc *wilc; 119 | struct device *dev = &spi->dev; 120 | struct wilc_spi *spi_priv; 121 | 122 | dev_info(&spi->dev, "spiModalias: %s, spiMax-Speed: %d\n", 123 | spi->modalias, spi->max_speed_hz); 124 | 125 | spi_priv = kzalloc(sizeof(*spi_priv), GFP_KERNEL); 126 | if (!spi_priv) 127 | return -ENOMEM; 128 | 129 | ret = wilc_cfg80211_init(&wilc, dev, WILC_HIF_SPI, &wilc_hif_spi); 130 | if (ret) { 131 | kfree(spi_priv); 132 | return ret; 133 | } 134 | 135 | spi_set_drvdata(spi, wilc); 136 | wilc->dev = &spi->dev; 137 | wilc->bus_data = spi_priv; 138 | wilc->dt_dev = &spi->dev; 139 | 140 | wilc->rtc_clk = devm_clk_get(&spi->dev, "rtc_clk"); 141 | if (PTR_ERR_OR_ZERO(wilc->rtc_clk) == -EPROBE_DEFER) 142 | return -EPROBE_DEFER; 143 | else if (!IS_ERR(wilc->rtc_clk)) 144 | clk_prepare_enable(wilc->rtc_clk); 145 | 146 | if (!init_power) { 147 | ret = wilc_wlan_power_on_sequence(wilc); 148 | if (ret) { 149 | wilc_netdev_cleanup(wilc); 150 | kfree(spi_priv); 151 | return ret; 152 | } 153 | init_power = 1; 154 | } 155 | 156 | wilc_bt_init(wilc); 157 | 158 | dev_info(dev, "WILC SPI probe success\n"); 159 | return 0; 160 | } 161 | 162 | static int wilc_bus_remove(struct spi_device *spi) 163 | { 164 | struct wilc *wilc = spi_get_drvdata(spi); 165 | 166 | if (!IS_ERR(wilc->rtc_clk)) 167 | clk_disable_unprepare(wilc->rtc_clk); 168 | 169 | wilc_netdev_cleanup(wilc); 170 | wilc_bt_deinit(); 171 | return 0; 172 | } 173 | 174 | static int wilc_spi_suspend(struct device *dev) 175 | { 176 | struct spi_device *spi = to_spi_device(dev); 177 | struct wilc *wilc = spi_get_drvdata(spi); 178 | 179 | dev_info(&spi->dev, "\n\n << SUSPEND >>\n\n"); 180 | mutex_lock(&wilc->hif_cs); 181 | chip_wakeup(wilc, 0); 182 | 183 | if (mutex_is_locked(&wilc->hif_cs)) 184 | mutex_unlock(&wilc->hif_cs); 185 | 186 | /*notify the chip that host will sleep*/ 187 | host_sleep_notify(wilc, 0); 188 | chip_allow_sleep(wilc, 0); 189 | mutex_lock(&wilc->hif_cs); 190 | 191 | return 0; 192 | } 193 | 194 | static int wilc_spi_resume(struct device *dev) 195 | { 196 | struct spi_device *spi = to_spi_device(dev); 197 | struct wilc *wilc = spi_get_drvdata(spi); 198 | 199 | dev_info(&spi->dev, "\n\n <>\n\n"); 200 | 201 | /*wake the chip to compelete the re-intialization*/ 202 | chip_wakeup(wilc, 0); 203 | 204 | if (mutex_is_locked(&wilc->hif_cs)) 205 | mutex_unlock(&wilc->hif_cs); 206 | 207 | host_wakeup_notify(wilc, 0); 208 | 209 | mutex_lock(&wilc->hif_cs); 210 | 211 | chip_allow_sleep(wilc, 0); 212 | 213 | if (mutex_is_locked(&wilc->hif_cs)) 214 | mutex_unlock(&wilc->hif_cs); 215 | 216 | return 0; 217 | } 218 | 219 | static const struct of_device_id wilc_of_match[] = { 220 | { .compatible = "microchip,wilc1000", }, 221 | { .compatible = "microchip,wilc3000", }, 222 | { /* sentinel */ } 223 | }; 224 | MODULE_DEVICE_TABLE(of, wilc_of_match); 225 | static const struct dev_pm_ops wilc_spi_pm_ops = { 226 | .suspend = wilc_spi_suspend, 227 | .resume = wilc_spi_resume, 228 | }; 229 | 230 | static struct spi_driver wilc_spi_driver = { 231 | .driver = { 232 | .name = MODALIAS, 233 | .of_match_table = wilc_of_match, 234 | .pm = &wilc_spi_pm_ops, 235 | }, 236 | .probe = wilc_bus_probe, 237 | .remove = wilc_bus_remove, 238 | }; 239 | module_spi_driver(wilc_spi_driver); 240 | MODULE_LICENSE("GPL"); 241 | MODULE_VERSION("15.3"); 242 | 243 | static int spi_data_rsp(struct wilc *wilc, u8 cmd) 244 | { 245 | struct spi_device *spi = to_spi_device(wilc->dev); 246 | struct wilc_spi *spi_priv = wilc->bus_data; 247 | u8 len; 248 | u8 rsp[3]; 249 | int result = N_OK; 250 | 251 | if (!spi_priv->crc_off) 252 | len = 2; 253 | else 254 | len = 3; 255 | 256 | if (wilc_spi_rx(wilc, &rsp[0], len)) { 257 | dev_err(&spi->dev, "Failed bus error...\n"); 258 | result = N_FAIL; 259 | goto fail; 260 | } 261 | 262 | if ((rsp[len-1] != 0) || (rsp[len-2] != 0xC3)) { 263 | dev_err(&spi->dev, "Failed data response read, %x %x %x\n", 264 | rsp[0], rsp[1], rsp[2]); 265 | result = N_FAIL; 266 | goto fail; 267 | } 268 | 269 | fail: 270 | return result; 271 | } 272 | 273 | static int wilc_spi_tx(struct wilc *wilc, u8 *b, u32 len) 274 | { 275 | struct spi_device *spi = to_spi_device(wilc->dev); 276 | int ret; 277 | struct spi_message msg; 278 | 279 | if (len > 0 && b) { 280 | struct spi_transfer tr = { 281 | .tx_buf = b, 282 | .len = len, 283 | .delay_usecs = 0, 284 | }; 285 | char *r_buffer = kzalloc(len, GFP_KERNEL); 286 | 287 | if (!r_buffer) 288 | return -ENOMEM; 289 | 290 | tr.rx_buf = r_buffer; 291 | dev_dbg(&spi->dev, "Request writing %d bytes\n", len); 292 | 293 | memset(&msg, 0, sizeof(msg)); 294 | spi_message_init(&msg); 295 | msg.spi = spi; 296 | msg.is_dma_mapped = USE_SPI_DMA; 297 | spi_message_add_tail(&tr, &msg); 298 | 299 | ret = spi_sync(spi, &msg); 300 | if (ret < 0) 301 | dev_err(&spi->dev, "SPI transaction failed\n"); 302 | 303 | kfree(r_buffer); 304 | } else { 305 | dev_err(&spi->dev, 306 | "can't write data with the following length: %d\n", 307 | len); 308 | ret = -EINVAL; 309 | } 310 | 311 | return ret; 312 | } 313 | 314 | static int wilc_spi_rx(struct wilc *wilc, u8 *rb, u32 rlen) 315 | { 316 | struct spi_device *spi = to_spi_device(wilc->dev); 317 | int ret; 318 | 319 | if (rlen > 0) { 320 | struct spi_message msg; 321 | struct spi_transfer tr = { 322 | .rx_buf = rb, 323 | .len = rlen, 324 | .delay_usecs = 0, 325 | 326 | }; 327 | char *t_buffer = kzalloc(rlen, GFP_KERNEL); 328 | 329 | if (!t_buffer) 330 | return -ENOMEM; 331 | 332 | tr.tx_buf = t_buffer; 333 | 334 | memset(&msg, 0, sizeof(msg)); 335 | spi_message_init(&msg); 336 | msg.spi = spi; 337 | msg.is_dma_mapped = USE_SPI_DMA; 338 | spi_message_add_tail(&tr, &msg); 339 | 340 | ret = spi_sync(spi, &msg); 341 | if (ret < 0) 342 | dev_err(&spi->dev, "SPI transaction failed\n"); 343 | kfree(t_buffer); 344 | } else { 345 | dev_err(&spi->dev, 346 | "can't read data with the following length: %u\n", 347 | rlen); 348 | ret = -EINVAL; 349 | } 350 | 351 | return ret; 352 | } 353 | 354 | static int wilc_spi_tx_rx(struct wilc *wilc, u8 *wb, u8 *rb, u32 rlen) 355 | { 356 | struct spi_device *spi = to_spi_device(wilc->dev); 357 | int ret; 358 | 359 | if (rlen > 0) { 360 | struct spi_message msg; 361 | struct spi_transfer tr = { 362 | .rx_buf = rb, 363 | .tx_buf = wb, 364 | .len = rlen, 365 | .bits_per_word = 8, 366 | .delay_usecs = 0, 367 | 368 | }; 369 | 370 | memset(&msg, 0, sizeof(msg)); 371 | spi_message_init(&msg); 372 | msg.spi = spi; 373 | msg.is_dma_mapped = USE_SPI_DMA; 374 | 375 | spi_message_add_tail(&tr, &msg); 376 | ret = spi_sync(spi, &msg); 377 | if (ret < 0) 378 | dev_err(&spi->dev, "SPI transaction failed\n"); 379 | } else { 380 | dev_err(&spi->dev, 381 | "can't read data with the following length: %u\n", 382 | rlen); 383 | ret = -EINVAL; 384 | } 385 | 386 | return ret; 387 | } 388 | 389 | static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, 390 | u8 clockless) 391 | { 392 | struct spi_device *spi = to_spi_device(wilc->dev); 393 | struct wilc_spi *spi_priv = wilc->bus_data; 394 | u8 wb[32], rb[32]; 395 | u8 wix, rix; 396 | u32 len2; 397 | u8 rsp; 398 | int len = 0; 399 | int result = N_OK; 400 | int retry; 401 | u8 crc[2]; 402 | 403 | wb[0] = cmd; 404 | switch (cmd) { 405 | case CMD_SINGLE_READ: /* single word (4 bytes) read */ 406 | wb[1] = (u8)(adr >> 16); 407 | wb[2] = (u8)(adr >> 8); 408 | wb[3] = (u8)adr; 409 | len = 5; 410 | break; 411 | 412 | case CMD_INTERNAL_READ: /* internal register read */ 413 | wb[1] = (u8)(adr >> 8); 414 | if (clockless == 1) 415 | wb[1] |= BIT(7); 416 | wb[2] = (u8)adr; 417 | wb[3] = 0x00; 418 | len = 5; 419 | break; 420 | 421 | case CMD_TERMINATE: 422 | wb[1] = 0x00; 423 | wb[2] = 0x00; 424 | wb[3] = 0x00; 425 | len = 5; 426 | break; 427 | 428 | case CMD_REPEAT: 429 | wb[1] = 0x00; 430 | wb[2] = 0x00; 431 | wb[3] = 0x00; 432 | len = 5; 433 | break; 434 | 435 | case CMD_RESET: 436 | wb[1] = 0xff; 437 | wb[2] = 0xff; 438 | wb[3] = 0xff; 439 | len = 5; 440 | break; 441 | 442 | case CMD_DMA_WRITE: /* dma write */ 443 | case CMD_DMA_READ: /* dma read */ 444 | wb[1] = (u8)(adr >> 16); 445 | wb[2] = (u8)(adr >> 8); 446 | wb[3] = (u8)adr; 447 | wb[4] = (u8)(sz >> 8); 448 | wb[5] = (u8)(sz); 449 | len = 7; 450 | break; 451 | 452 | case CMD_DMA_EXT_WRITE: /* dma extended write */ 453 | case CMD_DMA_EXT_READ: /* dma extended read */ 454 | wb[1] = (u8)(adr >> 16); 455 | wb[2] = (u8)(adr >> 8); 456 | wb[3] = (u8)adr; 457 | wb[4] = (u8)(sz >> 16); 458 | wb[5] = (u8)(sz >> 8); 459 | wb[6] = (u8)(sz); 460 | len = 8; 461 | break; 462 | 463 | case CMD_INTERNAL_WRITE: /* internal register write */ 464 | wb[1] = (u8)(adr >> 8); 465 | if (clockless == 1) 466 | wb[1] |= BIT(7); 467 | wb[2] = (u8)(adr); 468 | wb[3] = b[3]; 469 | wb[4] = b[2]; 470 | wb[5] = b[1]; 471 | wb[6] = b[0]; 472 | len = 8; 473 | break; 474 | 475 | case CMD_SINGLE_WRITE: /* single word write */ 476 | wb[1] = (u8)(adr >> 16); 477 | wb[2] = (u8)(adr >> 8); 478 | wb[3] = (u8)(adr); 479 | wb[4] = b[3]; 480 | wb[5] = b[2]; 481 | wb[6] = b[1]; 482 | wb[7] = b[0]; 483 | len = 9; 484 | break; 485 | 486 | default: 487 | result = N_FAIL; 488 | break; 489 | } 490 | 491 | if (result != N_OK) 492 | return result; 493 | 494 | if (!spi_priv->crc_off) 495 | wb[len - 1] = (crc7(0x7f, (const u8 *)&wb[0], len - 1)) << 1; 496 | else 497 | len -= 1; 498 | 499 | #define NUM_SKIP_BYTES (1) 500 | #define NUM_RSP_BYTES (2) 501 | #define NUM_DATA_HDR_BYTES (1) 502 | #define NUM_DATA_BYTES (4) 503 | #define NUM_CRC_BYTES (2) 504 | #define NUM_DUMMY_BYTES (3) 505 | if (cmd == CMD_RESET || 506 | cmd == CMD_TERMINATE || 507 | cmd == CMD_REPEAT) { 508 | len2 = len + (NUM_SKIP_BYTES + NUM_RSP_BYTES + NUM_DUMMY_BYTES); 509 | } else if (cmd == CMD_INTERNAL_READ || cmd == CMD_SINGLE_READ) { 510 | int tmp = NUM_RSP_BYTES + NUM_DATA_HDR_BYTES + NUM_DATA_BYTES 511 | + NUM_DUMMY_BYTES; 512 | if (!spi_priv->crc_off) 513 | len2 = len + tmp + NUM_CRC_BYTES; 514 | else 515 | len2 = len + tmp; 516 | } else { 517 | len2 = len + (NUM_RSP_BYTES + NUM_DUMMY_BYTES); 518 | } 519 | #undef NUM_DUMMY_BYTES 520 | 521 | if (len2 > ARRAY_SIZE(wb)) { 522 | dev_err(&spi->dev, "spi buffer size too small (%d) (%zu)\n", 523 | len2, ARRAY_SIZE(wb)); 524 | return N_FAIL; 525 | } 526 | /* zero spi write buffers. */ 527 | for (wix = len; wix < len2; wix++) 528 | wb[wix] = 0; 529 | rix = len; 530 | 531 | if (wilc_spi_tx_rx(wilc, wb, rb, len2)) { 532 | dev_err(&spi->dev, "Failed cmd write, bus error...\n"); 533 | return N_FAIL; 534 | } 535 | 536 | /* 537 | * Command/Control response 538 | */ 539 | if (cmd == CMD_RESET || cmd == CMD_TERMINATE || cmd == CMD_REPEAT) 540 | rix++; /* skip 1 byte */ 541 | 542 | rsp = rb[rix++]; 543 | 544 | /* 545 | * Clockless registers operations might return unexptected responses, 546 | * even if successful. 547 | */ 548 | if (rsp != cmd && !clockless) { 549 | dev_err(&spi->dev, 550 | "Failed cmd response, cmd (%02x), resp (%02x)\n", 551 | cmd, rsp); 552 | return N_FAIL; 553 | } 554 | 555 | /* 556 | * State response 557 | */ 558 | rsp = rb[rix++]; 559 | if (rsp != 0x00 && !clockless) { 560 | dev_err(&spi->dev, "Failed cmd state response state (%02x)\n", 561 | rsp); 562 | return N_FAIL; 563 | } 564 | 565 | if (cmd == CMD_INTERNAL_READ || cmd == CMD_SINGLE_READ || 566 | cmd == CMD_DMA_READ || cmd == CMD_DMA_EXT_READ) { 567 | /* 568 | * Data Respnose header 569 | */ 570 | retry = SPI_RESP_RETRY_COUNT; 571 | do { 572 | /* 573 | * ensure there is room in buffer later 574 | * to read data and crc 575 | */ 576 | if (rix < len2) { 577 | rsp = rb[rix++]; 578 | } else { 579 | retry = 0; 580 | break; 581 | } 582 | if (((rsp >> 4) & 0xf) == 0xf) 583 | break; 584 | } while (retry--); 585 | 586 | if (retry <= 0 && !clockless) { 587 | dev_err(&spi->dev, 588 | "Error, data read response (%02x)\n", rsp); 589 | return N_RESET; 590 | } 591 | } 592 | 593 | if (cmd == CMD_INTERNAL_READ || cmd == CMD_SINGLE_READ) { 594 | /* 595 | * Read bytes 596 | */ 597 | if ((rix + 3) < len2) { 598 | b[0] = rb[rix++]; 599 | b[1] = rb[rix++]; 600 | b[2] = rb[rix++]; 601 | b[3] = rb[rix++]; 602 | } else { 603 | dev_err(&spi->dev, 604 | "buffer overrun when reading data.\n"); 605 | return N_FAIL; 606 | } 607 | 608 | if (!spi_priv->crc_off) { 609 | /* 610 | * Read Crc 611 | */ 612 | if ((rix + 1) < len2) { 613 | crc[0] = rb[rix++]; 614 | crc[1] = rb[rix++]; 615 | } else { 616 | dev_err(&spi->dev, 617 | "buffer overrun when reading crc.\n"); 618 | return N_FAIL; 619 | } 620 | } 621 | } else if ((cmd == CMD_DMA_READ) || (cmd == CMD_DMA_EXT_READ)) { 622 | int ix; 623 | 624 | /* some data may be read in response to dummy bytes. */ 625 | for (ix = 0; (rix < len2) && (ix < sz); ) 626 | b[ix++] = rb[rix++]; 627 | 628 | sz -= ix; 629 | 630 | if (sz > 0) { 631 | int nbytes; 632 | 633 | if (sz <= (DATA_PKT_SZ - ix)) 634 | nbytes = sz; 635 | else 636 | nbytes = DATA_PKT_SZ - ix; 637 | 638 | /* 639 | * Read bytes 640 | */ 641 | if (wilc_spi_rx(wilc, &b[ix], nbytes)) { 642 | dev_err(&spi->dev, 643 | "Failed block read, bus err\n"); 644 | return N_FAIL; 645 | } 646 | 647 | /* 648 | * Read Crc 649 | */ 650 | if (!spi_priv->crc_off && wilc_spi_rx(wilc, crc, 2)) { 651 | dev_err(&spi->dev, 652 | "Failed block crc read, bus err\n"); 653 | return N_FAIL; 654 | } 655 | 656 | ix += nbytes; 657 | sz -= nbytes; 658 | } 659 | 660 | /* 661 | * if any data in left unread, 662 | * then read the rest using normal DMA code. 663 | */ 664 | while (sz > 0) { 665 | int nbytes; 666 | 667 | if (sz <= DATA_PKT_SZ) 668 | nbytes = sz; 669 | else 670 | nbytes = DATA_PKT_SZ; 671 | 672 | /* 673 | * read data response only on the next DMA cycles not 674 | * the first DMA since data response header is already 675 | * handled above for the first DMA. 676 | */ 677 | /* 678 | * Data Respnose header 679 | */ 680 | retry = SPI_RESP_RETRY_COUNT; 681 | do { 682 | if (wilc_spi_rx(wilc, &rsp, 1)) { 683 | dev_err(&spi->dev, 684 | "Failed resp read, bus err\n"); 685 | result = N_FAIL; 686 | break; 687 | } 688 | if (((rsp >> 4) & 0xf) == 0xf) 689 | break; 690 | } while (retry--); 691 | 692 | if (result == N_FAIL) 693 | break; 694 | 695 | /* 696 | * Read bytes 697 | */ 698 | if (wilc_spi_rx(wilc, &b[ix], nbytes)) { 699 | dev_err(&spi->dev, 700 | "Failed block read, bus err\n"); 701 | result = N_FAIL; 702 | break; 703 | } 704 | 705 | /* 706 | * Read Crc 707 | */ 708 | if (!spi_priv->crc_off && wilc_spi_rx(wilc, crc, 2)) { 709 | dev_err(&spi->dev, 710 | "Failed block crc read, bus err\n"); 711 | result = N_FAIL; 712 | break; 713 | } 714 | 715 | ix += nbytes; 716 | sz -= nbytes; 717 | } 718 | } 719 | return result; 720 | } 721 | 722 | static int spi_data_write(struct wilc *wilc, u8 *b, u32 sz) 723 | { 724 | struct spi_device *spi = to_spi_device(wilc->dev); 725 | struct wilc_spi *spi_priv = wilc->bus_data; 726 | int ix, nbytes; 727 | int result = 1; 728 | u8 cmd, order, crc[2] = {0}; 729 | 730 | /* 731 | * Data 732 | */ 733 | ix = 0; 734 | do { 735 | if (sz <= DATA_PKT_SZ) { 736 | nbytes = sz; 737 | order = 0x3; 738 | } else { 739 | nbytes = DATA_PKT_SZ; 740 | if (ix == 0) 741 | order = 0x1; 742 | else 743 | order = 0x02; 744 | } 745 | 746 | /* 747 | * Write command 748 | */ 749 | cmd = 0xf0; 750 | cmd |= order; 751 | 752 | if (wilc_spi_tx(wilc, &cmd, 1)) { 753 | dev_err(&spi->dev, 754 | "Failed data block cmd write, bus error...\n"); 755 | result = N_FAIL; 756 | break; 757 | } 758 | 759 | /* 760 | * Write data 761 | */ 762 | if (wilc_spi_tx(wilc, &b[ix], nbytes)) { 763 | dev_err(&spi->dev, 764 | "Failed data block write, bus error...\n"); 765 | result = N_FAIL; 766 | break; 767 | } 768 | 769 | /* 770 | * Write Crc 771 | */ 772 | if (!spi_priv->crc_off) { 773 | if (wilc_spi_tx(wilc, crc, 2)) { 774 | dev_err(&spi->dev, "Failed data block crc write, bus error...\n"); 775 | result = N_FAIL; 776 | break; 777 | } 778 | } 779 | 780 | /* 781 | * No need to wait for response 782 | */ 783 | ix += nbytes; 784 | sz -= nbytes; 785 | } while (sz); 786 | 787 | return result; 788 | } 789 | 790 | /******************************************** 791 | * 792 | * Spi Internal Read/Write Function 793 | * 794 | ********************************************/ 795 | 796 | static int spi_internal_write(struct wilc *wilc, u32 adr, u32 dat) 797 | { 798 | struct spi_device *spi = to_spi_device(wilc->dev); 799 | int result; 800 | u8 retry = SPI_RETRY_COUNT; 801 | 802 | retry: 803 | cpu_to_le32s(&dat); 804 | result = spi_cmd_complete(wilc, CMD_INTERNAL_WRITE, adr, (u8 *)&dat, 4, 805 | 0); 806 | if (result != N_OK) { 807 | dev_err(&spi->dev, "Failed internal write cmd...\n"); 808 | goto fail; 809 | } 810 | 811 | fail: 812 | if (result != N_OK) { 813 | usleep_range(1000, 1100); 814 | wilc_spi_reset(wilc); 815 | dev_err(&spi->dev, "Reset and retry %d %x\n", retry, adr); 816 | usleep_range(1000, 1100); 817 | retry--; 818 | if (retry) 819 | goto retry; 820 | } 821 | return result; 822 | } 823 | 824 | static int spi_internal_read(struct wilc *wilc, u32 adr, u32 *data) 825 | { 826 | struct spi_device *spi = to_spi_device(wilc->dev); 827 | int result = N_OK; 828 | u8 retry = SPI_RETRY_COUNT; 829 | 830 | retry: 831 | result = spi_cmd_complete(wilc, CMD_INTERNAL_READ, adr, (u8 *)data, 4, 832 | 0); 833 | if (result != N_OK) { 834 | dev_err(&spi->dev, "Failed internal read cmd...\n"); 835 | goto fail; 836 | } 837 | 838 | le32_to_cpus(data); 839 | 840 | fail: 841 | if (result != N_OK) { 842 | usleep_range(1000, 1100); 843 | wilc_spi_reset(wilc); 844 | dev_err(&spi->dev, "Reset and retry %d %x\n", retry, adr); 845 | usleep_range(1000, 1100); 846 | retry--; 847 | if (retry) 848 | goto retry; 849 | } 850 | return result; 851 | } 852 | 853 | /******************************************** 854 | * 855 | * Spi interfaces 856 | * 857 | ********************************************/ 858 | 859 | static int wilc_spi_write_reg(struct wilc *wilc, u32 addr, u32 data) 860 | { 861 | struct spi_device *spi = to_spi_device(wilc->dev); 862 | u8 retry = SPI_RETRY_COUNT; 863 | int result = N_OK; 864 | u8 cmd = CMD_SINGLE_WRITE; 865 | u8 clockless = 0; 866 | 867 | cpu_to_le32s(&data); 868 | _RETRY_: 869 | if (addr <= 0x30) { 870 | /* Clockless register */ 871 | cmd = CMD_INTERNAL_WRITE; 872 | clockless = 1; 873 | } else { 874 | cmd = CMD_SINGLE_WRITE; 875 | clockless = 0; 876 | } 877 | 878 | result = spi_cmd_complete(wilc, cmd, addr, (u8 *)&data, 4, clockless); 879 | if (result != N_OK) { 880 | dev_err(&spi->dev, "Failed cmd, write reg (%08x)...\n", addr); 881 | goto fail; 882 | } 883 | 884 | fail: 885 | if (result != N_OK) { 886 | usleep_range(1000, 1100); 887 | wilc_spi_reset(wilc); 888 | dev_err(&spi->dev, 889 | "Reset and retry %d %x %d\n", retry, addr, data); 890 | usleep_range(1000, 1100); 891 | retry--; 892 | if (retry) 893 | goto _RETRY_; 894 | } 895 | return result; 896 | } 897 | 898 | static int wilc_spi_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size) 899 | { 900 | struct spi_device *spi = to_spi_device(wilc->dev); 901 | int result; 902 | u8 retry = SPI_RETRY_COUNT; 903 | 904 | /* 905 | * has to be greated than 4 906 | */ 907 | if (size <= 4) 908 | return 0; 909 | 910 | retry: 911 | result = spi_cmd_complete(wilc, CMD_DMA_EXT_WRITE, addr, NULL, size, 0); 912 | if (result != N_OK) { 913 | dev_err(&spi->dev, 914 | "Failed cmd, write block (%08x)...\n", addr); 915 | goto fail; 916 | } 917 | 918 | /* 919 | * Data 920 | */ 921 | result = spi_data_write(wilc, buf, size); 922 | if (result != N_OK) { 923 | dev_err(&spi->dev, "Failed block data write...\n"); 924 | goto fail; 925 | } 926 | /* 927 | * Data RESP 928 | */ 929 | result = spi_data_rsp(wilc, CMD_DMA_EXT_WRITE); 930 | if (result != N_OK) { 931 | dev_err(&spi->dev, "Failed block data write...\n"); 932 | goto fail; 933 | } 934 | 935 | fail: 936 | if (result != N_OK) { 937 | usleep_range(1000, 1100); 938 | wilc_spi_reset(wilc); 939 | dev_err(&spi->dev, 940 | "Reset and retry %d %x %d\n", retry, addr, size); 941 | usleep_range(1000, 1100); 942 | retry--; 943 | if (retry) 944 | goto retry; 945 | } 946 | return result; 947 | } 948 | 949 | static int wilc_spi_read_reg(struct wilc *wilc, u32 addr, u32 *data) 950 | { 951 | struct spi_device *spi = to_spi_device(wilc->dev); 952 | u8 retry = SPI_RETRY_COUNT; 953 | int result = N_OK; 954 | u8 cmd = CMD_SINGLE_READ; 955 | u8 clockless = 0; 956 | 957 | retry: 958 | if (addr <= 0x30) { 959 | /* Clockless register */ 960 | cmd = CMD_INTERNAL_READ; 961 | clockless = 1; 962 | } else { 963 | cmd = CMD_SINGLE_READ; 964 | clockless = 0; 965 | } 966 | 967 | result = spi_cmd_complete(wilc, cmd, addr, (u8 *)data, 4, clockless); 968 | if (result != N_OK) { 969 | dev_err(&spi->dev, "Failed cmd, read reg (%08x)...\n", addr); 970 | goto fail; 971 | } 972 | 973 | le32_to_cpus(data); 974 | 975 | fail: 976 | if (result != N_OK) { 977 | usleep_range(1000, 1100); 978 | wilc_spi_reset(wilc); 979 | dev_warn(&spi->dev, "Reset and retry %d %x\n", retry, addr); 980 | usleep_range(1000, 1100); 981 | retry--; 982 | if (retry) 983 | goto retry; 984 | } 985 | return result; 986 | } 987 | 988 | static int wilc_spi_read(struct wilc *wilc, u32 addr, u8 *buf, u32 size) 989 | { 990 | struct spi_device *spi = to_spi_device(wilc->dev); 991 | int result; 992 | u8 retry = SPI_RETRY_COUNT; 993 | 994 | if (size <= 4) 995 | return 0; 996 | 997 | retry: 998 | result = spi_cmd_complete(wilc, CMD_DMA_EXT_READ, addr, buf, size, 0); 999 | if (result != N_OK) { 1000 | dev_err(&spi->dev, "Failed cmd, read block (%08x)...\n", addr); 1001 | goto fail; 1002 | } 1003 | 1004 | fail: 1005 | if (result != N_OK) { 1006 | usleep_range(1000, 1100); 1007 | wilc_spi_reset(wilc); 1008 | dev_warn(&spi->dev, "Reset and retry %d %x %d\n", retry, addr, 1009 | size); 1010 | usleep_range(1000, 1100); 1011 | retry--; 1012 | if (retry) 1013 | goto retry; 1014 | } 1015 | return result; 1016 | } 1017 | 1018 | /******************************************** 1019 | * 1020 | * Bus interfaces 1021 | * 1022 | ********************************************/ 1023 | 1024 | int wilc_spi_reset(struct wilc *wilc) 1025 | { 1026 | struct spi_device *spi = to_spi_device(wilc->dev); 1027 | int result = N_OK; 1028 | 1029 | result = spi_cmd_complete(wilc, CMD_RESET, 0, 0, 0, 0); 1030 | if (result != N_OK) { 1031 | dev_err(&spi->dev, "Failed cmd reset\n"); 1032 | return 0; 1033 | } 1034 | 1035 | return 1; 1036 | } 1037 | 1038 | static bool wilc_spi_is_init(struct wilc *wilc) 1039 | { 1040 | struct wilc_spi *spi_priv = wilc->bus_data; 1041 | 1042 | return spi_priv->is_init; 1043 | } 1044 | 1045 | static int wilc_spi_deinit(struct wilc *wilc) 1046 | { 1047 | struct wilc_spi *spi_priv = wilc->bus_data; 1048 | 1049 | /* 1050 | * TODO: 1051 | */ 1052 | spi_priv->is_init = false; 1053 | 1054 | return 1; 1055 | } 1056 | 1057 | static int wilc_spi_init(struct wilc *wilc, bool resume) 1058 | { 1059 | struct spi_device *spi = to_spi_device(wilc->dev); 1060 | struct wilc_spi *spi_priv = wilc->bus_data; 1061 | u32 reg; 1062 | u32 chipid; 1063 | 1064 | if (spi_priv->is_init) { 1065 | if (!wilc_spi_read_reg(wilc, 0x1000, &chipid)) { 1066 | dev_err(&spi->dev, "Fail cmd read chip id...\n"); 1067 | return 0; 1068 | } 1069 | return 1; 1070 | } 1071 | 1072 | /* 1073 | * configure protocol 1074 | */ 1075 | 1076 | /* 1077 | * TODO: We can remove the CRC trials if there is a definite 1078 | * way to reset 1079 | */ 1080 | /* the SPI to it's initial value. */ 1081 | if (!spi_internal_read(wilc, WILC_SPI_PROTOCOL_OFFSET, ®)) { 1082 | /* 1083 | * Read failed. Try with CRC off. This might happen when module 1084 | * is removed but chip isn't reset 1085 | */ 1086 | spi_priv->crc_off = 1; 1087 | dev_err(&spi->dev, 1088 | "Failed read with CRC on, retrying with CRC off\n"); 1089 | if (!spi_internal_read(wilc, WILC_SPI_PROTOCOL_OFFSET, ®)) { 1090 | /* 1091 | * Read failed with both CRC on and off, 1092 | * something went bad 1093 | */ 1094 | dev_err(&spi->dev, "Failed internal read protocol...\n"); 1095 | return 0; 1096 | } 1097 | } 1098 | if (spi_priv->crc_off == 0) { 1099 | reg &= ~0xc; /* disable crc checking */ 1100 | reg &= ~0x70; 1101 | reg |= (0x5 << 4); 1102 | if (!spi_internal_write(wilc, WILC_SPI_PROTOCOL_OFFSET, reg)) { 1103 | dev_err(&spi->dev, 1104 | "[wilc spi %d]: Failed internal write reg\n", 1105 | __LINE__); 1106 | return 0; 1107 | } 1108 | spi_priv->crc_off = 1; 1109 | } 1110 | 1111 | /* 1112 | * make sure can read back chip id correctly 1113 | */ 1114 | if (!wilc_spi_read_reg(wilc, 0x1000, &chipid)) { 1115 | dev_err(&spi->dev, "Fail cmd read chip id...\n"); 1116 | return 0; 1117 | } 1118 | 1119 | if (!resume) { 1120 | chipid = wilc_get_chipid(wilc, true); 1121 | if (is_wilc3000(chipid)) { 1122 | wilc->chip = WILC_3000; 1123 | goto pass; 1124 | } else if (is_wilc1000(chipid)) { 1125 | wilc->chip = WILC_1000; 1126 | goto pass; 1127 | } else { 1128 | dev_err(&spi->dev, "Unsupported chipid: %x\n", chipid); 1129 | goto fail; 1130 | } 1131 | dev_dbg(&spi->dev, "chipid %08x\n", chipid); 1132 | } 1133 | 1134 | pass: 1135 | spi_priv->is_init = true; 1136 | return 1; 1137 | 1138 | fail: 1139 | return 0; 1140 | } 1141 | 1142 | static int wilc_spi_read_size(struct wilc *wilc, u32 *size) 1143 | { 1144 | int ret; 1145 | 1146 | ret = spi_internal_read(wilc, 0xe840 - WILC_SPI_REG_BASE, 1147 | size); 1148 | *size = *size & IRQ_DMA_WD_CNT_MASK; 1149 | 1150 | return ret; 1151 | } 1152 | 1153 | static int wilc_spi_read_int(struct wilc *wilc, u32 *int_status) 1154 | { 1155 | return spi_internal_read(wilc, 0xe840 - WILC_SPI_REG_BASE, 1156 | int_status); 1157 | } 1158 | 1159 | static int wilc_spi_clear_int_ext(struct wilc *wilc, u32 val) 1160 | { 1161 | return spi_internal_write(wilc, 0xe844 - WILC_SPI_REG_BASE, val); 1162 | } 1163 | 1164 | static int wilc_spi_sync_ext(struct wilc *wilc, int nint) 1165 | { 1166 | struct spi_device *spi = to_spi_device(wilc->dev); 1167 | struct wilc_spi *spi_priv = wilc->bus_data; 1168 | u32 reg; 1169 | int ret, i; 1170 | 1171 | if (nint > MAX_NUM_INT) { 1172 | dev_err(&spi->dev, "Too many interrupts (%d)...\n", nint); 1173 | return 0; 1174 | } 1175 | 1176 | spi_priv->nint = nint; 1177 | 1178 | /* 1179 | * interrupt pin mux select 1180 | */ 1181 | ret = wilc_spi_read_reg(wilc, WILC_PIN_MUX_0, ®); 1182 | if (!ret) { 1183 | dev_err(&spi->dev, "Failed read reg (%08x)...\n", 1184 | WILC_PIN_MUX_0); 1185 | return 0; 1186 | } 1187 | reg |= BIT(8); 1188 | ret = wilc_spi_write_reg(wilc, WILC_PIN_MUX_0, reg); 1189 | if (!ret) { 1190 | dev_err(&spi->dev, "Failed write reg (%08x)...\n", 1191 | WILC_PIN_MUX_0); 1192 | return 0; 1193 | } 1194 | 1195 | /* 1196 | * interrupt enable 1197 | */ 1198 | ret = wilc_spi_read_reg(wilc, WILC_INTR_ENABLE, ®); 1199 | if (!ret) { 1200 | dev_err(&spi->dev, "Failed read reg (%08x)...\n", 1201 | WILC_INTR_ENABLE); 1202 | return 0; 1203 | } 1204 | 1205 | for (i = 0; (i < 5) && (nint > 0); i++, nint--) 1206 | reg |= (BIT((27 + i))); 1207 | 1208 | ret = wilc_spi_write_reg(wilc, WILC_INTR_ENABLE, reg); 1209 | if (!ret) { 1210 | dev_err(&spi->dev, "Failed write reg (%08x)...\n", 1211 | WILC_INTR_ENABLE); 1212 | return 0; 1213 | } 1214 | if (nint) { 1215 | ret = wilc_spi_read_reg(wilc, WILC_INTR2_ENABLE, ®); 1216 | if (!ret) { 1217 | dev_err(&spi->dev, "Failed read reg (%08x)...\n", 1218 | WILC_INTR2_ENABLE); 1219 | return 0; 1220 | } 1221 | 1222 | for (i = 0; (i < 3) && (nint > 0); i++, nint--) 1223 | reg |= BIT(i); 1224 | 1225 | ret = wilc_spi_write_reg(wilc, WILC_INTR2_ENABLE, reg); 1226 | if (!ret) { 1227 | dev_err(&spi->dev, "Failed write reg (%08x)...\n", 1228 | WILC_INTR2_ENABLE); 1229 | return 0; 1230 | } 1231 | } 1232 | 1233 | return 1; 1234 | } 1235 | 1236 | /* Global spi HIF function table */ 1237 | static const struct wilc_hif_func wilc_hif_spi = { 1238 | .hif_init = wilc_spi_init, 1239 | .hif_deinit = wilc_spi_deinit, 1240 | .hif_read_reg = wilc_spi_read_reg, 1241 | .hif_write_reg = wilc_spi_write_reg, 1242 | .hif_block_rx = wilc_spi_read, 1243 | .hif_block_tx = wilc_spi_write, 1244 | .hif_read_int = wilc_spi_read_int, 1245 | .hif_clear_int_ext = wilc_spi_clear_int_ext, 1246 | .hif_read_size = wilc_spi_read_size, 1247 | .hif_block_tx_ext = wilc_spi_write, 1248 | .hif_block_rx_ext = wilc_spi_read, 1249 | .hif_sync_ext = wilc_spi_sync_ext, 1250 | .hif_reset = wilc_spi_reset, 1251 | .hif_is_init = wilc_spi_is_init, 1252 | }; 1253 | --------------------------------------------------------------------------------