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: Gery Kahn <geryk@ti.com> Signed-off-by: Eliad Peller <eliad@wizery.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
This commit is contained in:
parent
f95f9aad15
commit
3fcdab7066
7 changed files with 52 additions and 22 deletions
|
@ -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 @@ out:
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
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 @@ out:
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
*/
|
*/
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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,
|
||||||
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 @@ out:
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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,
|
||||||
* 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>");
|
||||||
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>");
|
||||||
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[])
|
||||||
|
|
||||||
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 @@
|
||||||
|
|
||||||
#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 @@
|
||||||
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 {
|
||||||
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;
|
||||||
|
|
Loading…
Add table
Reference in a new issue