diff options
Diffstat (limited to 'drivers/net/wireless/microchip/wilc1000')
-rw-r--r-- | drivers/net/wireless/microchip/wilc1000/cfg80211.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/microchip/wilc1000/hif.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/microchip/wilc1000/netdev.c | 28 | ||||
-rw-r--r-- | drivers/net/wireless/microchip/wilc1000/netdev.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/microchip/wilc1000/sdio.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/microchip/wilc1000/spi.c | 80 | ||||
-rw-r--r-- | drivers/net/wireless/microchip/wilc1000/wlan.c | 41 | ||||
-rw-r--r-- | drivers/net/wireless/microchip/wilc1000/wlan.h | 2 |
8 files changed, 117 insertions, 53 deletions
diff --git a/drivers/net/wireless/microchip/wilc1000/cfg80211.c b/drivers/net/wireless/microchip/wilc1000/cfg80211.c index dc4bfe7be378..8d8378bafd9b 100644 --- a/drivers/net/wireless/microchip/wilc1000/cfg80211.c +++ b/drivers/net/wireless/microchip/wilc1000/cfg80211.c @@ -1737,23 +1737,15 @@ int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type, INIT_LIST_HEAD(&wl->rxq_head.list); INIT_LIST_HEAD(&wl->vif_list); - wl->hif_workqueue = create_singlethread_workqueue("WILC_wq"); - if (!wl->hif_workqueue) { - ret = -ENOMEM; - goto free_cfg; - } vif = wilc_netdev_ifc_init(wl, "wlan%d", WILC_STATION_MODE, NL80211_IFTYPE_STATION, false); if (IS_ERR(vif)) { ret = PTR_ERR(vif); - goto free_hq; + goto free_cfg; } return 0; -free_hq: - destroy_workqueue(wl->hif_workqueue); - free_cfg: wilc_wlan_cfg_deinit(wl); diff --git a/drivers/net/wireless/microchip/wilc1000/hif.c b/drivers/net/wireless/microchip/wilc1000/hif.c index e69b9c7f3d31..71b44cfe0dfc 100644 --- a/drivers/net/wireless/microchip/wilc1000/hif.c +++ b/drivers/net/wireless/microchip/wilc1000/hif.c @@ -1312,7 +1312,7 @@ int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr) result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); if (result) - netdev_err(vif->ndev, "Failed to get mac address\n"); + netdev_err(vif->ndev, "Failed to set mac address\n"); return result; } @@ -1929,6 +1929,7 @@ int wilc_edit_station(struct wilc_vif *vif, const u8 *mac, int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout) { + struct wilc *wilc = vif->wilc; struct wid wid; int result; s8 power_mode; @@ -1944,6 +1945,8 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout) result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); if (result) netdev_err(vif->ndev, "Failed to send power management\n"); + else + wilc->power_save_mode = enabled; return result; } diff --git a/drivers/net/wireless/microchip/wilc1000/netdev.c b/drivers/net/wireless/microchip/wilc1000/netdev.c index 690572e01a2a..643bddaae32a 100644 --- a/drivers/net/wireless/microchip/wilc1000/netdev.c +++ b/drivers/net/wireless/microchip/wilc1000/netdev.c @@ -27,7 +27,7 @@ static irqreturn_t isr_uh_routine(int irq, void *user_data) struct wilc *wilc = user_data; if (wilc->close) { - pr_err("Can't handle UH interrupt"); + pr_err("Can't handle UH interrupt\n"); return IRQ_HANDLED; } return IRQ_WAKE_THREAD; @@ -56,7 +56,7 @@ static int init_irq(struct net_device *dev) ret = request_threaded_irq(wl->dev_irq_num, isr_uh_routine, isr_bh_routine, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - "WILC_IRQ", wl); + dev->name, wl); if (ret) { netdev_err(dev, "Failed to request IRQ [%d]\n", ret); return ret; @@ -468,7 +468,7 @@ static int wlan_initialize_threads(struct net_device *dev) struct wilc *wilc = vif->wilc; wilc->txq_thread = kthread_run(wilc_txq_task, (void *)wilc, - "K_TXQ_TASK"); + "%s-tx", dev->name); if (IS_ERR(wilc->txq_thread)) { netdev_err(dev, "couldn't create TXQ thread\n"); wilc->close = 0; @@ -574,6 +574,7 @@ static int wilc_mac_open(struct net_device *ndev) struct wilc *wl = vif->wilc; int ret = 0; struct mgmt_frame_regs mgmt_regs = {}; + u8 addr[ETH_ALEN] __aligned(2); if (!wl || !wl->dev) { netdev_err(ndev, "device not ready\n"); @@ -596,10 +597,9 @@ static int wilc_mac_open(struct net_device *ndev) vif->idx); if (is_valid_ether_addr(ndev->dev_addr)) { - wilc_set_mac_address(vif, ndev->dev_addr); + ether_addr_copy(addr, ndev->dev_addr); + wilc_set_mac_address(vif, addr); } else { - u8 addr[ETH_ALEN]; - wilc_get_mac_address(vif, addr); eth_hw_addr_set(ndev, addr); } @@ -905,7 +905,6 @@ void wilc_netdev_cleanup(struct wilc *wilc) wilc_wlan_cfg_deinit(wilc); wlan_deinit_locks(wilc); - kfree(wilc->bus_data); wiphy_unregister(wilc->wiphy); wiphy_free(wilc->wiphy); } @@ -962,8 +961,15 @@ struct wilc_vif *wilc_netdev_ifc_init(struct wilc *wl, const char *name, ret = register_netdev(ndev); if (ret) { - free_netdev(ndev); - return ERR_PTR(-EFAULT); + ret = -EFAULT; + goto error; + } + + wl->hif_workqueue = alloc_ordered_workqueue("%s-wq", WQ_MEM_RECLAIM, + ndev->name); + if (!wl->hif_workqueue) { + ret = -ENOMEM; + goto error; } ndev->needs_free_netdev = true; @@ -977,6 +983,10 @@ struct wilc_vif *wilc_netdev_ifc_init(struct wilc *wl, const char *name, synchronize_srcu(&wl->srcu); return vif; + + error: + free_netdev(ndev); + return ERR_PTR(ret); } MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/microchip/wilc1000/netdev.h b/drivers/net/wireless/microchip/wilc1000/netdev.h index b9a88b3e322f..a067274c2014 100644 --- a/drivers/net/wireless/microchip/wilc1000/netdev.h +++ b/drivers/net/wireless/microchip/wilc1000/netdev.h @@ -212,6 +212,8 @@ struct wilc { s8 mac_status; struct clk *rtc_clk; bool initialized; + u32 chipid; + bool power_save_mode; int dev_irq_num; int close; u8 vif_num; diff --git a/drivers/net/wireless/microchip/wilc1000/sdio.c b/drivers/net/wireless/microchip/wilc1000/sdio.c index 26ebf6664342..ec595dbd8959 100644 --- a/drivers/net/wireless/microchip/wilc1000/sdio.c +++ b/drivers/net/wireless/microchip/wilc1000/sdio.c @@ -167,9 +167,11 @@ free: static void wilc_sdio_remove(struct sdio_func *func) { struct wilc *wilc = sdio_get_drvdata(func); + struct wilc_sdio *sdio_priv = wilc->bus_data; clk_disable_unprepare(wilc->rtc_clk); wilc_netdev_cleanup(wilc); + kfree(sdio_priv); } static int wilc_sdio_reset(struct wilc *wilc) diff --git a/drivers/net/wireless/microchip/wilc1000/spi.c b/drivers/net/wireless/microchip/wilc1000/spi.c index 640850f989dd..2c2ed4b09efd 100644 --- a/drivers/net/wireless/microchip/wilc1000/spi.c +++ b/drivers/net/wireless/microchip/wilc1000/spi.c @@ -8,10 +8,13 @@ #include <linux/spi/spi.h> #include <linux/crc7.h> #include <linux/crc-itu-t.h> +#include <linux/gpio/consumer.h> #include "netdev.h" #include "cfg80211.h" +#define SPI_MODALIAS "wilc1000_spi" + static bool enable_crc7; /* protect SPI commands with CRC7 */ module_param(enable_crc7, bool, 0644); MODULE_PARM_DESC(enable_crc7, @@ -43,6 +46,10 @@ struct wilc_spi { bool probing_crc; /* true if we're probing chip's CRC config */ bool crc7_enabled; /* true if crc7 is currently enabled */ bool crc16_enabled; /* true if crc16 is currently enabled */ + struct wilc_gpios { + struct gpio_desc *enable; /* ENABLE GPIO or NULL */ + struct gpio_desc *reset; /* RESET GPIO or NULL */ + } gpios; }; static const struct wilc_hif_func wilc_hif_spi; @@ -99,8 +106,6 @@ static int wilc_spi_reset(struct wilc *wilc); #define DATA_PKT_LOG_SZ DATA_PKT_LOG_SZ_MAX #define DATA_PKT_SZ (1 << DATA_PKT_LOG_SZ) -#define USE_SPI_DMA 0 - #define WILC_SPI_COMMAND_STAT_SUCCESS 0 #define WILC_GET_RESP_HDR_START(h) (((h) >> 4) & 0xf) @@ -152,6 +157,50 @@ struct wilc_spi_special_cmd_rsp { u8 status; } __packed; +static int wilc_parse_gpios(struct wilc *wilc) +{ + struct spi_device *spi = to_spi_device(wilc->dev); + struct wilc_spi *spi_priv = wilc->bus_data; + struct wilc_gpios *gpios = &spi_priv->gpios; + + /* get ENABLE pin and deassert it (if it is defined): */ + gpios->enable = devm_gpiod_get_optional(&spi->dev, + "enable", GPIOD_OUT_LOW); + /* get RESET pin and assert it (if it is defined): */ + if (gpios->enable) { + /* if enable pin exists, reset must exist as well */ + gpios->reset = devm_gpiod_get(&spi->dev, + "reset", GPIOD_OUT_HIGH); + if (IS_ERR(gpios->reset)) { + dev_err(&spi->dev, "missing reset gpio.\n"); + return PTR_ERR(gpios->reset); + } + } else { + gpios->reset = devm_gpiod_get_optional(&spi->dev, + "reset", GPIOD_OUT_HIGH); + } + return 0; +} + +static void wilc_wlan_power(struct wilc *wilc, bool on) +{ + struct wilc_spi *spi_priv = wilc->bus_data; + struct wilc_gpios *gpios = &spi_priv->gpios; + + if (on) { + /* assert ENABLE: */ + gpiod_set_value(gpios->enable, 1); + mdelay(5); + /* deassert RESET: */ + gpiod_set_value(gpios->reset, 0); + } else { + /* assert RESET: */ + gpiod_set_value(gpios->reset, 1); + /* deassert ENABLE: */ + gpiod_set_value(gpios->enable, 0); + } +} + static int wilc_bus_probe(struct spi_device *spi) { int ret; @@ -171,6 +220,10 @@ static int wilc_bus_probe(struct spi_device *spi) wilc->bus_data = spi_priv; wilc->dev_irq_num = spi->irq; + ret = wilc_parse_gpios(wilc); + if (ret < 0) + goto netdev_cleanup; + wilc->rtc_clk = devm_clk_get_optional(&spi->dev, "rtc"); if (IS_ERR(wilc->rtc_clk)) { ret = PTR_ERR(wilc->rtc_clk); @@ -190,9 +243,11 @@ free: static int wilc_bus_remove(struct spi_device *spi) { struct wilc *wilc = spi_get_drvdata(spi); + struct wilc_spi *spi_priv = wilc->bus_data; clk_disable_unprepare(wilc->rtc_clk); wilc_netdev_cleanup(wilc); + kfree(spi_priv); return 0; } @@ -203,11 +258,18 @@ static const struct of_device_id wilc_of_match[] = { }; MODULE_DEVICE_TABLE(of, wilc_of_match); +static const struct spi_device_id wilc_spi_id[] = { + { "wilc1000", 0 }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(spi, wilc_spi_id); + static struct spi_driver wilc_spi_driver = { .driver = { - .name = MODALIAS, + .name = SPI_MODALIAS, .of_match_table = wilc_of_match, }, + .id_table = wilc_spi_id, .probe = wilc_bus_probe, .remove = wilc_bus_remove, }; @@ -240,7 +302,6 @@ static int wilc_spi_tx(struct wilc *wilc, u8 *b, u32 len) memset(&msg, 0, sizeof(msg)); spi_message_init(&msg); msg.spi = spi; - msg.is_dma_mapped = USE_SPI_DMA; spi_message_add_tail(&tr, &msg); ret = spi_sync(spi, &msg); @@ -284,7 +345,6 @@ static int wilc_spi_rx(struct wilc *wilc, u8 *rb, u32 rlen) memset(&msg, 0, sizeof(msg)); spi_message_init(&msg); msg.spi = spi; - msg.is_dma_mapped = USE_SPI_DMA; spi_message_add_tail(&tr, &msg); ret = spi_sync(spi, &msg); @@ -323,7 +383,6 @@ static int wilc_spi_tx_rx(struct wilc *wilc, u8 *wb, u8 *rb, u32 rlen) memset(&msg, 0, sizeof(msg)); spi_message_init(&msg); msg.spi = spi; - msg.is_dma_mapped = USE_SPI_DMA; spi_message_add_tail(&tr, &msg); ret = spi_sync(spi, &msg); @@ -977,9 +1036,10 @@ static int wilc_spi_reset(struct wilc *wilc) static int wilc_spi_deinit(struct wilc *wilc) { - /* - * TODO: - */ + struct wilc_spi *spi_priv = wilc->bus_data; + + spi_priv->isinit = false; + wilc_wlan_power(wilc, false); return 0; } @@ -1000,6 +1060,8 @@ static int wilc_spi_init(struct wilc *wilc, bool resume) dev_err(&spi->dev, "Fail cmd read chip id...\n"); } + wilc_wlan_power(wilc, true); + /* * configure protocol */ diff --git a/drivers/net/wireless/microchip/wilc1000/wlan.c b/drivers/net/wireless/microchip/wilc1000/wlan.c index ea81ef120fd1..fb5633a05fd5 100644 --- a/drivers/net/wireless/microchip/wilc1000/wlan.c +++ b/drivers/net/wireless/microchip/wilc1000/wlan.c @@ -20,13 +20,13 @@ static inline bool is_wilc1000(u32 id) static inline void acquire_bus(struct wilc *wilc, enum bus_acquire acquire) { mutex_lock(&wilc->hif_cs); - if (acquire == WILC_BUS_ACQUIRE_AND_WAKEUP) + if (acquire == WILC_BUS_ACQUIRE_AND_WAKEUP && wilc->power_save_mode) chip_wakeup(wilc); } static inline void release_bus(struct wilc *wilc, enum bus_release release) { - if (release == WILC_BUS_RELEASE_ALLOW_SLEEP) + if (release == WILC_BUS_RELEASE_ALLOW_SLEEP && wilc->power_save_mode) chip_allow_sleep(wilc); mutex_unlock(&wilc->hif_cs); } @@ -626,7 +626,6 @@ void chip_wakeup(struct wilc *wilc) u32 clk_status_val = 0, trials = 0; u32 wakeup_reg, wakeup_bit; u32 clk_status_reg, clk_status_bit; - u32 to_host_from_fw_reg, to_host_from_fw_bit; u32 from_host_to_fw_reg, from_host_to_fw_bit; const struct wilc_hif_func *hif_func = wilc->hif_func; @@ -637,8 +636,6 @@ void chip_wakeup(struct wilc *wilc) clk_status_bit = WILC_SDIO_CLK_STATUS_BIT; from_host_to_fw_reg = WILC_SDIO_HOST_TO_FW_REG; from_host_to_fw_bit = WILC_SDIO_HOST_TO_FW_BIT; - to_host_from_fw_reg = WILC_SDIO_FW_TO_HOST_REG; - to_host_from_fw_bit = WILC_SDIO_FW_TO_HOST_BIT; } else { wakeup_reg = WILC_SPI_WAKEUP_REG; wakeup_bit = WILC_SPI_WAKEUP_BIT; @@ -646,8 +643,6 @@ void chip_wakeup(struct wilc *wilc) clk_status_bit = WILC_SPI_CLK_STATUS_BIT; from_host_to_fw_reg = WILC_SPI_HOST_TO_FW_REG; from_host_to_fw_bit = WILC_SPI_HOST_TO_FW_BIT; - to_host_from_fw_reg = WILC_SPI_FW_TO_HOST_REG; - to_host_from_fw_bit = WILC_SPI_FW_TO_HOST_BIT; } /* indicate host wakeup */ @@ -1229,7 +1224,8 @@ int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif) ret = 0; release: - release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); + /* host comm is disabled - we can't issue sleep command anymore: */ + release_bus(wilc, WILC_BUS_RELEASE_ONLY); return ret; } @@ -1258,7 +1254,7 @@ void wilc_wlan_cleanup(struct net_device *dev) wilc->rx_buffer = NULL; kfree(wilc->tx_buffer); wilc->tx_buffer = NULL; - wilc->hif_func->hif_deinit(NULL); + wilc->hif_func->hif_deinit(wilc); } static int wilc_wlan_cfg_commit(struct wilc_vif *vif, int type, @@ -1447,31 +1443,30 @@ release: u32 wilc_get_chipid(struct wilc *wilc, bool update) { - static u32 chipid; - u32 tempchipid = 0; + u32 chipid = 0; u32 rfrevid = 0; - if (chipid == 0 || update) { - wilc->hif_func->hif_read_reg(wilc, WILC_CHIPID, &tempchipid); + if (wilc->chipid == 0 || update) { + wilc->hif_func->hif_read_reg(wilc, WILC_CHIPID, &chipid); wilc->hif_func->hif_read_reg(wilc, WILC_RF_REVISION_ID, &rfrevid); - if (!is_wilc1000(tempchipid)) { - chipid = 0; - return chipid; + if (!is_wilc1000(chipid)) { + wilc->chipid = 0; + return wilc->chipid; } - if (tempchipid == WILC_1000_BASE_ID_2A) { /* 0x1002A0 */ + if (chipid == WILC_1000_BASE_ID_2A) { /* 0x1002A0 */ if (rfrevid != 0x1) - tempchipid = WILC_1000_BASE_ID_2A_REV1; - } else if (tempchipid == WILC_1000_BASE_ID_2B) { /* 0x1002B0 */ + chipid = WILC_1000_BASE_ID_2A_REV1; + } else if (chipid == WILC_1000_BASE_ID_2B) { /* 0x1002B0 */ if (rfrevid == 0x4) - tempchipid = WILC_1000_BASE_ID_2B_REV1; + chipid = WILC_1000_BASE_ID_2B_REV1; else if (rfrevid != 0x3) - tempchipid = WILC_1000_BASE_ID_2B_REV2; + chipid = WILC_1000_BASE_ID_2B_REV2; } - chipid = tempchipid; + wilc->chipid = chipid; } - return chipid; + return wilc->chipid; } int wilc_wlan_init(struct net_device *dev) diff --git a/drivers/net/wireless/microchip/wilc1000/wlan.h b/drivers/net/wireless/microchip/wilc1000/wlan.h index 13fde636aa0e..eb7978166d73 100644 --- a/drivers/net/wireless/microchip/wilc1000/wlan.h +++ b/drivers/net/wireless/microchip/wilc1000/wlan.h @@ -213,8 +213,6 @@ #define WILC_RX_BUFF_SIZE (96 * 1024) #define WILC_TX_BUFF_SIZE (64 * 1024) -#define MODALIAS "WILC_SPI" - #define NQUEUES 4 #define AC_BUFFER_SIZE 1000 |