Commit 3fcdab70 authored by Eliad Peller's avatar Eliad Peller Committed by Luciano Coelho

wl12xx: Use a dedicated fw for PLT

A special PLT firmware is used for calibration.

Add multiple fw support by introducing a new fw_type member,
representing the currently saved fw (the actual fw state
can be determined by wl->state).
Signed-off-by: default avatarGery Kahn <geryk@ti.com>
Signed-off-by: default avatarEliad Peller <eliad@wizery.com>
Signed-off-by: default avatarLuciano Coelho <coelho@ti.com>
parent f95f9aad
...@@ -113,7 +113,7 @@ static void wl1271_debugfs_update_stats(struct wl1271 *wl) ...@@ -113,7 +113,7 @@ static void wl1271_debugfs_update_stats(struct wl1271 *wl)
if (ret < 0) if (ret < 0)
goto out; goto out;
if (wl->state == WL1271_STATE_ON && if (wl->state == WL1271_STATE_ON && !wl->plt &&
time_after(jiffies, wl->stats.fw_stats_update + time_after(jiffies, wl->stats.fw_stats_update +
msecs_to_jiffies(WL1271_DEBUGFS_STATS_LIFETIME))) { msecs_to_jiffies(WL1271_DEBUGFS_STATS_LIFETIME))) {
wl1271_acx_statistics(wl, wl->stats.fw_stats); wl1271_acx_statistics(wl, wl->stats.fw_stats);
......
...@@ -993,16 +993,29 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) ...@@ -993,16 +993,29 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int wl1271_fetch_firmware(struct wl1271 *wl) static int wl12xx_fetch_firmware(struct wl1271 *wl, bool plt)
{ {
const struct firmware *fw; const struct firmware *fw;
const char *fw_name; const char *fw_name;
enum wl12xx_fw_type fw_type;
int ret; int ret;
if (wl->chip.id == CHIP_ID_1283_PG20) if (plt) {
fw_name = WL128X_FW_NAME; fw_type = WL12XX_FW_TYPE_PLT;
else if (wl->chip.id == CHIP_ID_1283_PG20)
fw_name = WL127X_FW_NAME; fw_name = WL128X_PLT_FW_NAME;
else
fw_name = WL127X_PLT_FW_NAME;
} else {
fw_type = WL12XX_FW_TYPE_NORMAL;
if (wl->chip.id == CHIP_ID_1283_PG20)
fw_name = WL128X_FW_NAME;
else
fw_name = WL127X_FW_NAME;
}
if (wl->fw_type == fw_type)
return 0;
wl1271_debug(DEBUG_BOOT, "booting firmware %s", fw_name); wl1271_debug(DEBUG_BOOT, "booting firmware %s", fw_name);
...@@ -1021,6 +1034,7 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) ...@@ -1021,6 +1034,7 @@ static int wl1271_fetch_firmware(struct wl1271 *wl)
} }
vfree(wl->fw); vfree(wl->fw);
wl->fw_type = WL12XX_FW_TYPE_NONE;
wl->fw_len = fw->size; wl->fw_len = fw->size;
wl->fw = vmalloc(wl->fw_len); wl->fw = vmalloc(wl->fw_len);
...@@ -1032,7 +1046,7 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) ...@@ -1032,7 +1046,7 @@ static int wl1271_fetch_firmware(struct wl1271 *wl)
memcpy(wl->fw, fw->data, wl->fw_len); memcpy(wl->fw, fw->data, wl->fw_len);
ret = 0; ret = 0;
wl->fw_type = fw_type;
out: out:
release_firmware(fw); release_firmware(fw);
...@@ -1160,7 +1174,7 @@ static void wl1271_recovery_work(struct work_struct *work) ...@@ -1160,7 +1174,7 @@ static void wl1271_recovery_work(struct work_struct *work)
mutex_lock(&wl->mutex); mutex_lock(&wl->mutex);
if (wl->state != WL1271_STATE_ON) if (wl->state != WL1271_STATE_ON || wl->plt)
goto out_unlock; goto out_unlock;
/* Avoid a recursive recovery */ /* Avoid a recursive recovery */
...@@ -1261,7 +1275,7 @@ static int wl12xx_set_power_on(struct wl1271 *wl) ...@@ -1261,7 +1275,7 @@ static int wl12xx_set_power_on(struct wl1271 *wl)
return ret; return ret;
} }
static int wl1271_chip_wakeup(struct wl1271 *wl) static int wl12xx_chip_wakeup(struct wl1271 *wl, bool plt)
{ {
int ret = 0; int ret = 0;
...@@ -1316,11 +1330,9 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) ...@@ -1316,11 +1330,9 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
goto out; goto out;
} }
if (wl->fw == NULL) { ret = wl12xx_fetch_firmware(wl, plt);
ret = wl1271_fetch_firmware(wl); if (ret < 0)
if (ret < 0) goto out;
goto out;
}
/* No NVS from netlink, try to get it from the filesystem */ /* No NVS from netlink, try to get it from the filesystem */
if (wl->nvs == NULL) { if (wl->nvs == NULL) {
...@@ -1352,7 +1364,7 @@ int wl1271_plt_start(struct wl1271 *wl) ...@@ -1352,7 +1364,7 @@ int wl1271_plt_start(struct wl1271 *wl)
while (retries) { while (retries) {
retries--; retries--;
ret = wl1271_chip_wakeup(wl); ret = wl12xx_chip_wakeup(wl, true);
if (ret < 0) if (ret < 0)
goto power_off; goto power_off;
...@@ -1364,7 +1376,8 @@ int wl1271_plt_start(struct wl1271 *wl) ...@@ -1364,7 +1376,8 @@ int wl1271_plt_start(struct wl1271 *wl)
if (ret < 0) if (ret < 0)
goto irq_disable; goto irq_disable;
wl->state = WL1271_STATE_PLT; wl->plt = true;
wl->state = WL1271_STATE_ON;
wl1271_notice("firmware booted in PLT mode (%s)", wl1271_notice("firmware booted in PLT mode (%s)",
wl->chip.fw_ver_str); wl->chip.fw_ver_str);
...@@ -1413,7 +1426,7 @@ int wl1271_plt_stop(struct wl1271 *wl) ...@@ -1413,7 +1426,7 @@ int wl1271_plt_stop(struct wl1271 *wl)
*/ */
wl1271_disable_interrupts(wl); wl1271_disable_interrupts(wl);
mutex_lock(&wl->mutex); mutex_lock(&wl->mutex);
if (wl->state != WL1271_STATE_PLT) { if (!wl->plt) {
mutex_unlock(&wl->mutex); mutex_unlock(&wl->mutex);
/* /*
...@@ -1440,6 +1453,7 @@ int wl1271_plt_stop(struct wl1271 *wl) ...@@ -1440,6 +1453,7 @@ int wl1271_plt_stop(struct wl1271 *wl)
wl1271_power_off(wl); wl1271_power_off(wl);
wl->flags = 0; wl->flags = 0;
wl->state = WL1271_STATE_OFF; wl->state = WL1271_STATE_OFF;
wl->plt = false;
wl->rx_counter = 0; wl->rx_counter = 0;
mutex_unlock(&wl->mutex); mutex_unlock(&wl->mutex);
...@@ -1995,7 +2009,7 @@ static bool wl12xx_init_fw(struct wl1271 *wl) ...@@ -1995,7 +2009,7 @@ static bool wl12xx_init_fw(struct wl1271 *wl)
while (retries) { while (retries) {
retries--; retries--;
ret = wl1271_chip_wakeup(wl); ret = wl12xx_chip_wakeup(wl, false);
if (ret < 0) if (ret < 0)
goto power_off; goto power_off;
...@@ -2098,6 +2112,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, ...@@ -2098,6 +2112,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
goto out; goto out;
} }
ret = wl12xx_init_vif_data(wl, vif); ret = wl12xx_init_vif_data(wl, vif);
if (ret < 0) if (ret < 0)
goto out; goto out;
...@@ -5009,7 +5024,7 @@ static int wl1271_register_hw(struct wl1271 *wl) ...@@ -5009,7 +5024,7 @@ static int wl1271_register_hw(struct wl1271 *wl)
static void wl1271_unregister_hw(struct wl1271 *wl) static void wl1271_unregister_hw(struct wl1271 *wl)
{ {
if (wl->state == WL1271_STATE_PLT) if (wl->plt)
wl1271_plt_stop(wl); wl1271_plt_stop(wl);
unregister_netdevice_notifier(&wl1271_dev_notifier); unregister_netdevice_notifier(&wl1271_dev_notifier);
...@@ -5186,6 +5201,7 @@ static struct ieee80211_hw *wl1271_alloc_hw(void) ...@@ -5186,6 +5201,7 @@ static struct ieee80211_hw *wl1271_alloc_hw(void)
spin_lock_init(&wl->wl_lock); spin_lock_init(&wl->wl_lock);
wl->state = WL1271_STATE_OFF; wl->state = WL1271_STATE_OFF;
wl->fw_type = WL12XX_FW_TYPE_NONE;
mutex_init(&wl->mutex); mutex_init(&wl->mutex);
/* Apply default driver configuration. */ /* Apply default driver configuration. */
...@@ -5253,6 +5269,7 @@ static int wl1271_free_hw(struct wl1271 *wl) ...@@ -5253,6 +5269,7 @@ static int wl1271_free_hw(struct wl1271 *wl)
vfree(wl->fw); vfree(wl->fw);
wl->fw = NULL; wl->fw = NULL;
wl->fw_type = WL12XX_FW_TYPE_NONE;
kfree(wl->nvs); kfree(wl->nvs);
wl->nvs = NULL; wl->nvs = NULL;
......
...@@ -113,7 +113,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, ...@@ -113,7 +113,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
* In PLT mode we seem to get frames and mac80211 warns about them, * In PLT mode we seem to get frames and mac80211 warns about them,
* workaround this by not retrieving them at all. * workaround this by not retrieving them at all.
*/ */
if (unlikely(wl->state == WL1271_STATE_PLT)) if (unlikely(wl->plt))
return -EINVAL; return -EINVAL;
/* the data read starts with the descriptor */ /* the data read starts with the descriptor */
......
...@@ -372,3 +372,5 @@ MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); ...@@ -372,3 +372,5 @@ MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
MODULE_FIRMWARE(WL127X_FW_NAME); MODULE_FIRMWARE(WL127X_FW_NAME);
MODULE_FIRMWARE(WL128X_FW_NAME); MODULE_FIRMWARE(WL128X_FW_NAME);
MODULE_FIRMWARE(WL127X_PLT_FW_NAME);
MODULE_FIRMWARE(WL128X_PLT_FW_NAME);
...@@ -435,4 +435,6 @@ MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); ...@@ -435,4 +435,6 @@ MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
MODULE_FIRMWARE(WL127X_FW_NAME); MODULE_FIRMWARE(WL127X_FW_NAME);
MODULE_FIRMWARE(WL128X_FW_NAME); MODULE_FIRMWARE(WL128X_FW_NAME);
MODULE_FIRMWARE(WL127X_PLT_FW_NAME);
MODULE_FIRMWARE(WL128X_PLT_FW_NAME);
MODULE_ALIAS("spi:wl1271"); MODULE_ALIAS("spi:wl1271");
...@@ -274,7 +274,7 @@ static int wl12xx_tm_cmd_get_mac(struct wl1271 *wl, struct nlattr *tb[]) ...@@ -274,7 +274,7 @@ static int wl12xx_tm_cmd_get_mac(struct wl1271 *wl, struct nlattr *tb[])
mutex_lock(&wl->mutex); mutex_lock(&wl->mutex);
if (wl->state != WL1271_STATE_PLT) { if (!wl->plt) {
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
......
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
#define WL127X_FW_NAME "ti-connectivity/wl127x-fw-4-sr.bin" #define WL127X_FW_NAME "ti-connectivity/wl127x-fw-4-sr.bin"
#define WL128X_FW_NAME "ti-connectivity/wl128x-fw-4-sr.bin" #define WL128X_FW_NAME "ti-connectivity/wl128x-fw-4-sr.bin"
#define WL127X_PLT_FW_NAME "ti-connectivity/wl127x-fw-4-plt.bin"
#define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-4-plt.bin"
/* /*
* wl127x and wl128x are using the same NVS file name. However, the * wl127x and wl128x are using the same NVS file name. However, the
...@@ -90,7 +92,12 @@ ...@@ -90,7 +92,12 @@
enum wl1271_state { enum wl1271_state {
WL1271_STATE_OFF, WL1271_STATE_OFF,
WL1271_STATE_ON, WL1271_STATE_ON,
WL1271_STATE_PLT, };
enum wl12xx_fw_type {
WL12XX_FW_TYPE_NONE,
WL12XX_FW_TYPE_NORMAL,
WL12XX_FW_TYPE_PLT,
}; };
enum wl1271_partition_type { enum wl1271_partition_type {
...@@ -294,6 +301,8 @@ struct wl1271 { ...@@ -294,6 +301,8 @@ struct wl1271 {
spinlock_t wl_lock; spinlock_t wl_lock;
enum wl1271_state state; enum wl1271_state state;
enum wl12xx_fw_type fw_type;
bool plt;
struct mutex mutex; struct mutex mutex;
unsigned long flags; unsigned long flags;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment