From 7b3115f265de1b669b757f3802b67c9a7f146223 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 2 Dec 2011 15:52:19 +0200 Subject: wl12xx/wlcore: rename wl12xx to wlcore Rename the wl12xx driver directory to wlcore as an initial step towards the split of the driver into wlcore and wl12xx. We just rename the directory first to keep git blame happy. Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/cmd.c | 1950 ++++++++++++++++++++++++++++++++++ 1 file changed, 1950 insertions(+) create mode 100644 drivers/net/wireless/ti/wlcore/cmd.c (limited to 'drivers/net/wireless/ti/wlcore/cmd.c') diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c new file mode 100644 index 00000000000..82cb90a4a99 --- /dev/null +++ b/drivers/net/wireless/ti/wlcore/cmd.c @@ -0,0 +1,1950 @@ +/* + * This file is part of wl1271 + * + * Copyright (C) 2009-2010 Nokia Corporation + * + * Contact: Luciano Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include +#include +#include +#include +#include +#include + +#include "wl12xx.h" +#include "debug.h" +#include "reg.h" +#include "io.h" +#include "acx.h" +#include "wl12xx_80211.h" +#include "cmd.h" +#include "event.h" +#include "tx.h" + +#define WL1271_CMD_FAST_POLL_COUNT 50 + +/* + * send command to firmware + * + * @wl: wl struct + * @id: command id + * @buf: buffer containing the command, must work with dma + * @len: length of the buffer + */ +int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, + size_t res_len) +{ + struct wl1271_cmd_header *cmd; + unsigned long timeout; + u32 intr; + int ret = 0; + u16 status; + u16 poll_count = 0; + + cmd = buf; + cmd->id = cpu_to_le16(id); + cmd->status = 0; + + WARN_ON(len % 4 != 0); + WARN_ON(test_bit(WL1271_FLAG_IN_ELP, &wl->flags)); + + wl1271_write(wl, wl->cmd_box_addr, buf, len, false); + + wl1271_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD); + + timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT); + + intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); + while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) { + if (time_after(jiffies, timeout)) { + wl1271_error("command complete timeout"); + ret = -ETIMEDOUT; + goto fail; + } + + poll_count++; + if (poll_count < WL1271_CMD_FAST_POLL_COUNT) + udelay(10); + else + msleep(1); + + intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); + } + + /* read back the status code of the command */ + if (res_len == 0) + res_len = sizeof(struct wl1271_cmd_header); + wl1271_read(wl, wl->cmd_box_addr, cmd, res_len, false); + + status = le16_to_cpu(cmd->status); + if (status != CMD_STATUS_SUCCESS) { + wl1271_error("command execute failure %d", status); + ret = -EIO; + goto fail; + } + + wl1271_write32(wl, ACX_REG_INTERRUPT_ACK, + WL1271_ACX_INTR_CMD_COMPLETE); + return 0; + +fail: + WARN_ON(1); + wl12xx_queue_recovery_work(wl); + return ret; +} + +int wl1271_cmd_general_parms(struct wl1271 *wl) +{ + struct wl1271_general_parms_cmd *gen_parms; + struct wl1271_ini_general_params *gp = + &((struct wl1271_nvs_file *)wl->nvs)->general_params; + bool answer = false; + int ret; + + if (!wl->nvs) + return -ENODEV; + + if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { + wl1271_warning("FEM index from INI out of bounds"); + return -EINVAL; + } + + gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); + if (!gen_parms) + return -ENOMEM; + + gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; + + memcpy(&gen_parms->general_params, gp, sizeof(*gp)); + + if (gp->tx_bip_fem_auto_detect) + answer = true; + + /* Override the REF CLK from the NVS with the one from platform data */ + gen_parms->general_params.ref_clock = wl->ref_clock; + + ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); + if (ret < 0) { + wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); + goto out; + } + + gp->tx_bip_fem_manufacturer = + gen_parms->general_params.tx_bip_fem_manufacturer; + + if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { + wl1271_warning("FEM index from FW out of bounds"); + ret = -EINVAL; + goto out; + } + + wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", + answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); + +out: + kfree(gen_parms); + return ret; +} + +int wl128x_cmd_general_parms(struct wl1271 *wl) +{ + struct wl128x_general_parms_cmd *gen_parms; + struct wl128x_ini_general_params *gp = + &((struct wl128x_nvs_file *)wl->nvs)->general_params; + bool answer = false; + int ret; + + if (!wl->nvs) + return -ENODEV; + + if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { + wl1271_warning("FEM index from ini out of bounds"); + return -EINVAL; + } + + gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); + if (!gen_parms) + return -ENOMEM; + + gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; + + memcpy(&gen_parms->general_params, gp, sizeof(*gp)); + + if (gp->tx_bip_fem_auto_detect) + answer = true; + + /* Replace REF and TCXO CLKs with the ones from platform data */ + gen_parms->general_params.ref_clock = wl->ref_clock; + gen_parms->general_params.tcxo_ref_clock = wl->tcxo_clock; + + ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); + if (ret < 0) { + wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); + goto out; + } + + gp->tx_bip_fem_manufacturer = + gen_parms->general_params.tx_bip_fem_manufacturer; + + if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { + wl1271_warning("FEM index from FW out of bounds"); + ret = -EINVAL; + goto out; + } + + wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", + answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); + +out: + kfree(gen_parms); + return ret; +} + +int wl1271_cmd_radio_parms(struct wl1271 *wl) +{ + struct wl1271_nvs_file *nvs = (struct wl1271_nvs_file *)wl->nvs; + struct wl1271_radio_parms_cmd *radio_parms; + struct wl1271_ini_general_params *gp = &nvs->general_params; + int ret; + + if (!wl->nvs) + return -ENODEV; + + radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL); + if (!radio_parms) + return -ENOMEM; + + radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; + + /* 2.4GHz parameters */ + memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2, + sizeof(struct wl1271_ini_band_params_2)); + memcpy(&radio_parms->dyn_params_2, + &nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params, + sizeof(struct wl1271_ini_fem_params_2)); + + /* 5GHz parameters */ + memcpy(&radio_parms->static_params_5, + &nvs->stat_radio_params_5, + sizeof(struct wl1271_ini_band_params_5)); + memcpy(&radio_parms->dyn_params_5, + &nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params, + sizeof(struct wl1271_ini_fem_params_5)); + + wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", + radio_parms, sizeof(*radio_parms)); + + ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0); + if (ret < 0) + wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed"); + + kfree(radio_parms); + return ret; +} + +int wl128x_cmd_radio_parms(struct wl1271 *wl) +{ + struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs; + struct wl128x_radio_parms_cmd *radio_parms; + struct wl128x_ini_general_params *gp = &nvs->general_params; + int ret; + + if (!wl->nvs) + return -ENODEV; + + radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL); + if (!radio_parms) + return -ENOMEM; + + radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; + + /* 2.4GHz parameters */ + memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2, + sizeof(struct wl128x_ini_band_params_2)); + memcpy(&radio_parms->dyn_params_2, + &nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params, + sizeof(struct wl128x_ini_fem_params_2)); + + /* 5GHz parameters */ + memcpy(&radio_parms->static_params_5, + &nvs->stat_radio_params_5, + sizeof(struct wl128x_ini_band_params_5)); + memcpy(&radio_parms->dyn_params_5, + &nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params, + sizeof(struct wl128x_ini_fem_params_5)); + + radio_parms->fem_vendor_and_options = nvs->fem_vendor_and_options; + + wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", + radio_parms, sizeof(*radio_parms)); + + ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0); + if (ret < 0) + wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed"); + + kfree(radio_parms); + return ret; +} + +int wl1271_cmd_ext_radio_parms(struct wl1271 *wl) +{ + struct wl1271_ext_radio_parms_cmd *ext_radio_parms; + struct conf_rf_settings *rf = &wl->conf.rf; + int ret; + + if (!wl->nvs) + return -ENODEV; + + ext_radio_parms = kzalloc(sizeof(*ext_radio_parms), GFP_KERNEL); + if (!ext_radio_parms) + return -ENOMEM; + + ext_radio_parms->test.id = TEST_CMD_INI_FILE_RF_EXTENDED_PARAM; + + memcpy(ext_radio_parms->tx_per_channel_power_compensation_2, + rf->tx_per_channel_power_compensation_2, + CONF_TX_PWR_COMPENSATION_LEN_2); + memcpy(ext_radio_parms->tx_per_channel_power_compensation_5, + rf->tx_per_channel_power_compensation_5, + CONF_TX_PWR_COMPENSATION_LEN_5); + + wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_EXT_RADIO_PARAM: ", + ext_radio_parms, sizeof(*ext_radio_parms)); + + ret = wl1271_cmd_test(wl, ext_radio_parms, sizeof(*ext_radio_parms), 0); + if (ret < 0) + wl1271_warning("TEST_CMD_INI_FILE_RF_EXTENDED_PARAM failed"); + + kfree(ext_radio_parms); + return ret; +} + +/* + * Poll the mailbox event field until any of the bits in the mask is set or a + * timeout occurs (WL1271_EVENT_TIMEOUT in msecs) + */ +static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, u32 mask) +{ + u32 *events_vector; + u32 event; + unsigned long timeout; + int ret = 0; + + events_vector = kmalloc(sizeof(*events_vector), GFP_DMA); + + timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT); + + do { + if (time_after(jiffies, timeout)) { + wl1271_debug(DEBUG_CMD, "timeout waiting for event %d", + (int)mask); + ret = -ETIMEDOUT; + goto out; + } + + msleep(1); + + /* read from both event fields */ + wl1271_read(wl, wl->mbox_ptr[0], events_vector, + sizeof(*events_vector), false); + event = *events_vector & mask; + wl1271_read(wl, wl->mbox_ptr[1], events_vector, + sizeof(*events_vector), false); + event |= *events_vector & mask; + } while (!event); + +out: + kfree(events_vector); + return ret; +} + +static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) +{ + int ret; + + ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask); + if (ret != 0) { + wl12xx_queue_recovery_work(wl); + return ret; + } + + return 0; +} + +int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 *addr, u8 role_type, + u8 *role_id) +{ + struct wl12xx_cmd_role_enable *cmd; + int ret; + + wl1271_debug(DEBUG_CMD, "cmd role enable"); + + if (WARN_ON(*role_id != WL12XX_INVALID_ROLE_ID)) + return -EBUSY; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + + /* get role id */ + cmd->role_id = find_first_zero_bit(wl->roles_map, WL12XX_MAX_ROLES); + if (cmd->role_id >= WL12XX_MAX_ROLES) { + ret = -EBUSY; + goto out_free; + } + + memcpy(cmd->mac_address, addr, ETH_ALEN); + cmd->role_type = role_type; + + ret = wl1271_cmd_send(wl, CMD_ROLE_ENABLE, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("failed to initiate cmd role enable"); + goto out_free; + } + + __set_bit(cmd->role_id, wl->roles_map); + *role_id = cmd->role_id; + +out_free: + kfree(cmd); + +out: + return ret; +} + +int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id) +{ + struct wl12xx_cmd_role_disable *cmd; + int ret; + + wl1271_debug(DEBUG_CMD, "cmd role disable"); + + if (WARN_ON(*role_id == WL12XX_INVALID_ROLE_ID)) + return -ENOENT; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + cmd->role_id = *role_id; + + ret = wl1271_cmd_send(wl, CMD_ROLE_DISABLE, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("failed to initiate cmd role disable"); + goto out_free; + } + + __clear_bit(*role_id, wl->roles_map); + *role_id = WL12XX_INVALID_ROLE_ID; + +out_free: + kfree(cmd); + +out: + return ret; +} + +int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid) +{ + unsigned long flags; + u8 link = find_first_zero_bit(wl->links_map, WL12XX_MAX_LINKS); + if (link >= WL12XX_MAX_LINKS) + return -EBUSY; + + /* these bits are used by op_tx */ + spin_lock_irqsave(&wl->wl_lock, flags); + __set_bit(link, wl->links_map); + __set_bit(link, wlvif->links_map); + spin_unlock_irqrestore(&wl->wl_lock, flags); + *hlid = link; + return 0; +} + +void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid) +{ + unsigned long flags; + + if (*hlid == WL12XX_INVALID_LINK_ID) + return; + + /* these bits are used by op_tx */ + spin_lock_irqsave(&wl->wl_lock, flags); + __clear_bit(*hlid, wl->links_map); + __clear_bit(*hlid, wlvif->links_map); + spin_unlock_irqrestore(&wl->wl_lock, flags); + + /* + * At this point op_tx() will not add more packets to the queues. We + * can purge them. + */ + wl1271_tx_reset_link_queues(wl, *hlid); + + *hlid = WL12XX_INVALID_LINK_ID; +} + +static int wl12xx_get_new_session_id(struct wl1271 *wl, + struct wl12xx_vif *wlvif) +{ + if (wlvif->session_counter >= SESSION_COUNTER_MAX) + wlvif->session_counter = 0; + + wlvif->session_counter++; + + return wlvif->session_counter; +} + +static int wl12xx_cmd_role_start_dev(struct wl1271 *wl, + struct wl12xx_vif *wlvif) +{ + struct wl12xx_cmd_role_start *cmd; + int ret; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + + wl1271_debug(DEBUG_CMD, "cmd role start dev %d", wlvif->dev_role_id); + + cmd->role_id = wlvif->dev_role_id; + if (wlvif->band == IEEE80211_BAND_5GHZ) + cmd->band = WL12XX_BAND_5GHZ; + cmd->channel = wlvif->channel; + + if (wlvif->dev_hlid == WL12XX_INVALID_LINK_ID) { + ret = wl12xx_allocate_link(wl, wlvif, &wlvif->dev_hlid); + if (ret) + goto out_free; + } + cmd->device.hlid = wlvif->dev_hlid; + cmd->device.session = wl12xx_get_new_session_id(wl, wlvif); + + wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d", + cmd->role_id, cmd->device.hlid, cmd->device.session); + + ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("failed to initiate cmd role enable"); + goto err_hlid; + } + + goto out_free; + +err_hlid: + /* clear links on error */ + wl12xx_free_link(wl, wlvif, &wlvif->dev_hlid); + +out_free: + kfree(cmd); + +out: + return ret; +} + +static int wl12xx_cmd_role_stop_dev(struct wl1271 *wl, + struct wl12xx_vif *wlvif) +{ + struct wl12xx_cmd_role_stop *cmd; + int ret; + + if (WARN_ON(wlvif->dev_hlid == WL12XX_INVALID_LINK_ID)) + return -EINVAL; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + + wl1271_debug(DEBUG_CMD, "cmd role stop dev"); + + cmd->role_id = wlvif->dev_role_id; + cmd->disc_type = DISCONNECT_IMMEDIATE; + cmd->reason = cpu_to_le16(WLAN_REASON_UNSPECIFIED); + + ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("failed to initiate cmd role stop"); + goto out_free; + } + + ret = wl1271_cmd_wait_for_event(wl, ROLE_STOP_COMPLETE_EVENT_ID); + if (ret < 0) { + wl1271_error("cmd role stop dev event completion error"); + goto out_free; + } + + wl12xx_free_link(wl, wlvif, &wlvif->dev_hlid); + +out_free: + kfree(cmd); + +out: + return ret; +} + +int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) +{ + struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); + struct wl12xx_cmd_role_start *cmd; + int ret; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + + wl1271_debug(DEBUG_CMD, "cmd role start sta %d", wlvif->role_id); + + cmd->role_id = wlvif->role_id; + if (wlvif->band == IEEE80211_BAND_5GHZ) + cmd->band = WL12XX_BAND_5GHZ; + cmd->channel = wlvif->channel; + cmd->sta.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set); + cmd->sta.beacon_interval = cpu_to_le16(wlvif->beacon_int); + cmd->sta.ssid_type = WL12XX_SSID_TYPE_ANY; + cmd->sta.ssid_len = wlvif->ssid_len; + memcpy(cmd->sta.ssid, wlvif->ssid, wlvif->ssid_len); + memcpy(cmd->sta.bssid, vif->bss_conf.bssid, ETH_ALEN); + cmd->sta.local_rates = cpu_to_le32(wlvif->rate_set); + + if (wlvif->sta.hlid == WL12XX_INVALID_LINK_ID) { + ret = wl12xx_allocate_link(wl, wlvif, &wlvif->sta.hlid); + if (ret) + goto out_free; + } + cmd->sta.hlid = wlvif->sta.hlid; + cmd->sta.session = wl12xx_get_new_session_id(wl, wlvif); + cmd->sta.remote_rates = cpu_to_le32(wlvif->rate_set); + + wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d " + "basic_rate_set: 0x%x, remote_rates: 0x%x", + wlvif->role_id, cmd->sta.hlid, cmd->sta.session, + wlvif->basic_rate_set, wlvif->rate_set); + + ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("failed to initiate cmd role start sta"); + goto err_hlid; + } + + goto out_free; + +err_hlid: + /* clear links on error. */ + wl12xx_free_link(wl, wlvif, &wlvif->sta.hlid); + +out_free: + kfree(cmd); + +out: + return ret; +} + +/* use this function to stop ibss as well */ +int wl12xx_cmd_role_stop_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) +{ + struct wl12xx_cmd_role_stop *cmd; + int ret; + + if (WARN_ON(wlvif->sta.hlid == WL12XX_INVALID_LINK_ID)) + return -EINVAL; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + + wl1271_debug(DEBUG_CMD, "cmd role stop sta %d", wlvif->role_id); + + cmd->role_id = wlvif->role_id; + cmd->disc_type = DISCONNECT_IMMEDIATE; + cmd->reason = cpu_to_le16(WLAN_REASON_UNSPECIFIED); + + ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("failed to initiate cmd role stop sta"); + goto out_free; + } + + wl12xx_free_link(wl, wlvif, &wlvif->sta.hlid); + +out_free: + kfree(cmd); + +out: + return ret; +} + +int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) +{ + struct wl12xx_cmd_role_start *cmd; + struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); + struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; + int ret; + + wl1271_debug(DEBUG_CMD, "cmd role start ap %d", wlvif->role_id); + + /* trying to use hidden SSID with an old hostapd version */ + if (wlvif->ssid_len == 0 && !bss_conf->hidden_ssid) { + wl1271_error("got a null SSID from beacon/bss"); + ret = -EINVAL; + goto out; + } + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + + ret = wl12xx_allocate_link(wl, wlvif, &wlvif->ap.global_hlid); + if (ret < 0) + goto out_free; + + ret = wl12xx_allocate_link(wl, wlvif, &wlvif->ap.bcast_hlid); + if (ret < 0) + goto out_free_global; + + cmd->role_id = wlvif->role_id; + cmd->ap.aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period); + cmd->ap.bss_index = WL1271_AP_BSS_INDEX; + cmd->ap.global_hlid = wlvif->ap.global_hlid; + cmd->ap.broadcast_hlid = wlvif->ap.bcast_hlid; + cmd->ap.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set); + cmd->ap.beacon_interval = cpu_to_le16(wlvif->beacon_int); + cmd->ap.dtim_interval = bss_conf->dtim_period; + cmd->ap.beacon_expiry = WL1271_AP_DEF_BEACON_EXP; + /* FIXME: Change when adding DFS */ + cmd->ap.reset_tsf = 1; /* By default reset AP TSF */ + cmd->channel = wlvif->channel; + + if (!bss_conf->hidden_ssid) { + /* take the SSID from the beacon for backward compatibility */ + cmd->ap.ssid_type = WL12XX_SSID_TYPE_PUBLIC; + cmd->ap.ssid_len = wlvif->ssid_len; + memcpy(cmd->ap.ssid, wlvif->ssid, wlvif->ssid_len); + } else { + cmd->ap.ssid_type = WL12XX_SSID_TYPE_HIDDEN; + cmd->ap.ssid_len = bss_conf->ssid_len; + memcpy(cmd->ap.ssid, bss_conf->ssid, bss_conf->ssid_len); + } + + cmd->ap.local_rates = cpu_to_le32(0xffffffff); + + switch (wlvif->band) { + case IEEE80211_BAND_2GHZ: + cmd->band = RADIO_BAND_2_4GHZ; + break; + case IEEE80211_BAND_5GHZ: + cmd->band = RADIO_BAND_5GHZ; + break; + default: + wl1271_warning("ap start - unknown band: %d", (int)wlvif->band); + cmd->band = RADIO_BAND_2_4GHZ; + break; + } + + ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("failed to initiate cmd role start ap"); + goto out_free_bcast; + } + + goto out_free; + +out_free_bcast: + wl12xx_free_link(wl, wlvif, &wlvif->ap.bcast_hlid); + +out_free_global: + wl12xx_free_link(wl, wlvif, &wlvif->ap.global_hlid); + +out_free: + kfree(cmd); + +out: + return ret; +} + +int wl12xx_cmd_role_stop_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) +{ + struct wl12xx_cmd_role_stop *cmd; + int ret; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + + wl1271_debug(DEBUG_CMD, "cmd role stop ap %d", wlvif->role_id); + + cmd->role_id = wlvif->role_id; + + ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("failed to initiate cmd role stop ap"); + goto out_free; + } + + wl12xx_free_link(wl, wlvif, &wlvif->ap.bcast_hlid); + wl12xx_free_link(wl, wlvif, &wlvif->ap.global_hlid); + +out_free: + kfree(cmd); + +out: + return ret; +} + +int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif) +{ + struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); + struct wl12xx_cmd_role_start *cmd; + struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; + int ret; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + + wl1271_debug(DEBUG_CMD, "cmd role start ibss %d", wlvif->role_id); + + cmd->role_id = wlvif->role_id; + if (wlvif->band == IEEE80211_BAND_5GHZ) + cmd->band = WL12XX_BAND_5GHZ; + cmd->channel = wlvif->channel; + cmd->ibss.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set); + cmd->ibss.beacon_interval = cpu_to_le16(wlvif->beacon_int); + cmd->ibss.dtim_interval = bss_conf->dtim_period; + cmd->ibss.ssid_type = WL12XX_SSID_TYPE_ANY; + cmd->ibss.ssid_len = wlvif->ssid_len; + memcpy(cmd->ibss.ssid, wlvif->ssid, wlvif->ssid_len); + memcpy(cmd->ibss.bssid, vif->bss_conf.bssid, ETH_ALEN); + cmd->sta.local_rates = cpu_to_le32(wlvif->rate_set); + + if (wlvif->sta.hlid == WL12XX_INVALID_LINK_ID) { + ret = wl12xx_allocate_link(wl, wlvif, &wlvif->sta.hlid); + if (ret) + goto out_free; + } + cmd->ibss.hlid = wlvif->sta.hlid; + cmd->ibss.remote_rates = cpu_to_le32(wlvif->rate_set); + + wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d " + "basic_rate_set: 0x%x, remote_rates: 0x%x", + wlvif->role_id, cmd->sta.hlid, cmd->sta.session, + wlvif->basic_rate_set, wlvif->rate_set); + + wl1271_debug(DEBUG_CMD, "vif->bss_conf.bssid = %pM", + vif->bss_conf.bssid); + + ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("failed to initiate cmd role enable"); + goto err_hlid; + } + + goto out_free; + +err_hlid: + /* clear links on error. */ + wl12xx_free_link(wl, wlvif, &wlvif->sta.hlid); + +out_free: + kfree(cmd); + +out: + return ret; +} + + +/** + * send test command to firmware + * + * @wl: wl struct + * @buf: buffer containing the command, with all headers, must work with dma + * @len: length of the buffer + * @answer: is answer needed + */ +int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer) +{ + int ret; + size_t res_len = 0; + + wl1271_debug(DEBUG_CMD, "cmd test"); + + if (answer) + res_len = buf_len; + + ret = wl1271_cmd_send(wl, CMD_TEST, buf, buf_len, res_len); + + if (ret < 0) { + wl1271_warning("TEST command failed"); + return ret; + } + + return ret; +} + +/** + * read acx from firmware + * + * @wl: wl struct + * @id: acx id + * @buf: buffer for the response, including all headers, must work with dma + * @len: length of buf + */ +int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len) +{ + struct acx_header *acx = buf; + int ret; + + wl1271_debug(DEBUG_CMD, "cmd interrogate"); + + acx->id = cpu_to_le16(id); + + /* payload length, does not include any headers */ + acx->len = cpu_to_le16(len - sizeof(*acx)); + + ret = wl1271_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx), len); + if (ret < 0) + wl1271_error("INTERROGATE command failed"); + + return ret; +} + +/** + * write acx value to firmware + * + * @wl: wl struct + * @id: acx id + * @buf: buffer containing acx, including all headers, must work with dma + * @len: length of buf + */ +int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len) +{ + struct acx_header *acx = buf; + int ret; + + wl1271_debug(DEBUG_CMD, "cmd configure (%d)", id); + + acx->id = cpu_to_le16(id); + + /* payload length, does not include any headers */ + acx->len = cpu_to_le16(len - sizeof(*acx)); + + ret = wl1271_cmd_send(wl, CMD_CONFIGURE, acx, len, 0); + if (ret < 0) { + wl1271_warning("CONFIGURE command NOK"); + return ret; + } + + return 0; +} + +int wl1271_cmd_data_path(struct wl1271 *wl, bool enable) +{ + struct cmd_enabledisable_path *cmd; + int ret; + u16 cmd_rx, cmd_tx; + + wl1271_debug(DEBUG_CMD, "cmd data path"); + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + + /* the channel here is only used for calibration, so hardcoded to 1 */ + cmd->channel = 1; + + if (enable) { + cmd_rx = CMD_ENABLE_RX; + cmd_tx = CMD_ENABLE_TX; + } else { + cmd_rx = CMD_DISABLE_RX; + cmd_tx = CMD_DISABLE_TX; + } + + ret = wl1271_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("rx %s cmd for channel %d failed", + enable ? "start" : "stop", cmd->channel); + goto out; + } + + wl1271_debug(DEBUG_BOOT, "rx %s cmd channel %d", + enable ? "start" : "stop", cmd->channel); + + ret = wl1271_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("tx %s cmd for channel %d failed", + enable ? "start" : "stop", cmd->channel); + goto out; + } + + wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d", + enable ? "start" : "stop", cmd->channel); + +out: + kfree(cmd); + return ret; +} + +int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, + u8 ps_mode, u16 auto_ps_timeout) +{ + struct wl1271_cmd_ps_params *ps_params = NULL; + int ret = 0; + + wl1271_debug(DEBUG_CMD, "cmd set ps mode"); + + ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL); + if (!ps_params) { + ret = -ENOMEM; + goto out; + } + + ps_params->role_id = wlvif->role_id; + ps_params->ps_mode = ps_mode; + ps_params->auto_ps_timeout = auto_ps_timeout; + + ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, + sizeof(*ps_params), 0); + if (ret < 0) { + wl1271_error("cmd set_ps_mode failed"); + goto out; + } + +out: + kfree(ps_params); + return ret; +} + +int wl1271_cmd_template_set(struct wl1271 *wl, u8 role_id, + u16 template_id, void *buf, size_t buf_len, + int index, u32 rates) +{ + struct wl1271_cmd_template_set *cmd; + int ret = 0; + + wl1271_debug(DEBUG_CMD, "cmd template_set %d (role %d)", + template_id, role_id); + + WARN_ON(buf_len > WL1271_CMD_TEMPL_MAX_SIZE); + buf_len = min_t(size_t, buf_len, WL1271_CMD_TEMPL_MAX_SIZE); + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + + /* during initialization wlvif is NULL */ + cmd->role_id = role_id; + cmd->len = cpu_to_le16(buf_len); + cmd->template_type = template_id; + cmd->enabled_rates = cpu_to_le32(rates); + cmd->short_retry_limit = wl->conf.tx.tmpl_short_retry_limit; + cmd->long_retry_limit = wl->conf.tx.tmpl_long_retry_limit; + cmd->index = index; + + if (buf) + memcpy(cmd->template_data, buf, buf_len); + + ret = wl1271_cmd_send(wl, CMD_SET_TEMPLATE, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_warning("cmd set_template failed: %d", ret); + goto out_free; + } + +out_free: + kfree(cmd); + +out: + return ret; +} + +int wl12xx_cmd_build_null_data(struct wl1271 *wl, struct wl12xx_vif *wlvif) +{ + struct sk_buff *skb = NULL; + int size; + void *ptr; + int ret = -ENOMEM; + + + if (wlvif->bss_type == BSS_TYPE_IBSS) { + size = sizeof(struct wl12xx_null_data_template); + ptr = NULL; + } else { + skb = ieee80211_nullfunc_get(wl->hw, + wl12xx_wlvif_to_vif(wlvif)); + if (!skb) + goto out; + size = skb->len; + ptr = skb->data; + } + + ret = wl1271_cmd_template_set(wl, wlvif->role_id, + CMD_TEMPL_NULL_DATA, ptr, size, 0, + wlvif->basic_rate); + +out: + dev_kfree_skb(skb); + if (ret) + wl1271_warning("cmd buld null data failed %d", ret); + + return ret; + +} + +int wl12xx_cmd_build_klv_null_data(struct wl1271 *wl, + struct wl12xx_vif *wlvif) +{ + struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); + struct sk_buff *skb = NULL; + int ret = -ENOMEM; + + skb = ieee80211_nullfunc_get(wl->hw, vif); + if (!skb) + goto out; + + ret = wl1271_cmd_template_set(wl, wlvif->role_id, CMD_TEMPL_KLV, + skb->data, skb->len, + CMD_TEMPL_KLV_IDX_NULL_DATA, + wlvif->basic_rate); + +out: + dev_kfree_skb(skb); + if (ret) + wl1271_warning("cmd build klv null data failed %d", ret); + + return ret; + +} + +int wl1271_cmd_build_ps_poll(struct wl1271 *wl, struct wl12xx_vif *wlvif, + u16 aid) +{ + struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); + struct sk_buff *skb; + int ret = 0; + + skb = ieee80211_pspoll_get(wl->hw, vif); + if (!skb) + goto out; + + ret = wl1271_cmd_template_set(wl, wlvif->role_id, + CMD_TEMPL_PS_POLL, skb->data, + skb->len, 0, wlvif->basic_rate_set); + +out: + dev_kfree_skb(skb); + return ret; +} + +int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, + u8 role_id, u8 band, + const u8 *ssid, size_t ssid_len, + const u8 *ie, size_t ie_len) +{ + struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); + struct sk_buff *skb; + int ret; + u32 rate; + + skb = ieee80211_probereq_get(wl->hw, vif, ssid, ssid_len, + ie, ie_len); + if (!skb) { + ret = -ENOMEM; + goto out; + } + + wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len); + + rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]); + if (band == IEEE80211_BAND_2GHZ) + ret = wl1271_cmd_template_set(wl, role_id, + CMD_TEMPL_CFG_PROBE_REQ_2_4, + skb->data, skb->len, 0, rate); + else + ret = wl1271_cmd_template_set(wl, role_id, + CMD_TEMPL_CFG_PROBE_REQ_5, + skb->data, skb->len, 0, rate); + +out: + dev_kfree_skb(skb); + return ret; +} + +struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, + struct wl12xx_vif *wlvif, + struct sk_buff *skb) +{ + struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); + int ret; + u32 rate; + + if (!skb) + skb = ieee80211_ap_probereq_get(wl->hw, vif); + if (!skb) + goto out; + + wl1271_dump(DEBUG_SCAN, "AP PROBE REQ: ", skb->data, skb->len); + + rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[wlvif->band]); + if (wlvif->band == IEEE80211_BAND_2GHZ) + ret = wl1271_cmd_template_set(wl, wlvif->role_id, + CMD_TEMPL_CFG_PROBE_REQ_2_4, + skb->data, skb->len, 0, rate); + else + ret = wl1271_cmd_template_set(wl, wlvif->role_id, + CMD_TEMPL_CFG_PROBE_REQ_5, + skb->data, skb->len, 0, rate); + + if (ret < 0) + wl1271_error("Unable to set ap probe request template."); + +out: + return skb; +} + +int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif) +{ + int ret, extra; + u16 fc; + struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); + struct sk_buff *skb; + struct wl12xx_arp_rsp_template *tmpl; + struct ieee80211_hdr_3addr *hdr; + struct arphdr *arp_hdr; + + skb = dev_alloc_skb(sizeof(*hdr) + sizeof(__le16) + sizeof(*tmpl) + + WL1271_EXTRA_SPACE_MAX); + if (!skb) { + wl1271_error("failed to allocate buffer for arp rsp template"); + return -ENOMEM; + } + + skb_reserve(skb, sizeof(*hdr) + WL1271_EXTRA_SPACE_MAX); + + tmpl = (struct wl12xx_arp_rsp_template *)skb_put(skb, sizeof(*tmpl)); + memset(tmpl, 0, sizeof(tmpl)); + + /* llc layer */ + memcpy(tmpl->llc_hdr, rfc1042_header, sizeof(rfc1042_header)); + tmpl->llc_type = cpu_to_be16(ETH_P_ARP); + + /* arp header */ + arp_hdr = &tmpl->arp_hdr; + arp_hdr->ar_hrd = cpu_to_be16(ARPHRD_ETHER); + arp_hdr->ar_pro = cpu_to_be16(ETH_P_IP); + arp_hdr->ar_hln = ETH_ALEN; + arp_hdr->ar_pln = 4; + arp_hdr->ar_op = cpu_to_be16(ARPOP_REPLY); + + /* arp payload */ + memcpy(tmpl->sender_hw, vif->addr, ETH_ALEN); + tmpl->sender_ip = wlvif->ip_addr; + + /* encryption space */ + switch (wlvif->encryption_type) { + case KEY_TKIP: + extra = WL1271_EXTRA_SPACE_TKIP; + break; + case KEY_AES: + extra = WL1271_EXTRA_SPACE_AES; + break; + case KEY_NONE: + case KEY_WEP: + case KEY_GEM: + extra = 0; + break; + default: + wl1271_warning("Unknown encryption type: %d", + wlvif->encryption_type); + ret = -EINVAL; + goto out; + } + + if (extra) { + u8 *space = skb_push(skb, extra); + memset(space, 0, extra); + } + + /* QoS header - BE */ + if (wlvif->sta.qos) + memset(skb_push(skb, sizeof(__le16)), 0, sizeof(__le16)); + + /* mac80211 header */ + hdr = (struct ieee80211_hdr_3addr *)skb_push(skb, sizeof(*hdr)); + memset(hdr, 0, sizeof(hdr)); + fc = IEEE80211_FTYPE_DATA | IEEE80211_FCTL_TODS; + if (wlvif->sta.qos) + fc |= IEEE80211_STYPE_QOS_DATA; + else + fc |= IEEE80211_STYPE_DATA; + if (wlvif->encryption_type != KEY_NONE) + fc |= IEEE80211_FCTL_PROTECTED; + + hdr->frame_control = cpu_to_le16(fc); + memcpy(hdr->addr1, vif->bss_conf.bssid, ETH_ALEN); + memcpy(hdr->addr2, vif->addr, ETH_ALEN); + memset(hdr->addr3, 0xff, ETH_ALEN); + + ret = wl1271_cmd_template_set(wl, wlvif->role_id, CMD_TEMPL_ARP_RSP, + skb->data, skb->len, 0, + wlvif->basic_rate); +out: + dev_kfree_skb(skb); + return ret; +} + +int wl1271_build_qos_null_data(struct wl1271 *wl, struct ieee80211_vif *vif) +{ + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); + struct ieee80211_qos_hdr template; + + memset(&template, 0, sizeof(template)); + + memcpy(template.addr1, vif->bss_conf.bssid, ETH_ALEN); + memcpy(template.addr2, vif->addr, ETH_ALEN); + memcpy(template.addr3, vif->bss_conf.bssid, ETH_ALEN); + + template.frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | + IEEE80211_STYPE_QOS_NULLFUNC | + IEEE80211_FCTL_TODS); + + /* FIXME: not sure what priority to use here */ + template.qos_ctrl = cpu_to_le16(0); + + return wl1271_cmd_template_set(wl, wlvif->role_id, + CMD_TEMPL_QOS_NULL_DATA, &template, + sizeof(template), 0, + wlvif->basic_rate); +} + +int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid) +{ + struct wl1271_cmd_set_keys *cmd; + int ret = 0; + + wl1271_debug(DEBUG_CMD, "cmd set_default_wep_key %d", id); + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + + cmd->hlid = hlid; + cmd->key_id = id; + cmd->lid_key_type = WEP_DEFAULT_LID_TYPE; + cmd->key_action = cpu_to_le16(KEY_SET_ID); + cmd->key_type = KEY_WEP; + + ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_warning("cmd set_default_wep_key failed: %d", ret); + goto out; + } + +out: + kfree(cmd); + + return ret; +} + +int wl1271_cmd_set_sta_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, + u16 action, u8 id, u8 key_type, + u8 key_size, const u8 *key, const u8 *addr, + u32 tx_seq_32, u16 tx_seq_16) +{ + struct wl1271_cmd_set_keys *cmd; + int ret = 0; + + /* hlid might have already been deleted */ + if (wlvif->sta.hlid == WL12XX_INVALID_LINK_ID) + return 0; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + + cmd->hlid = wlvif->sta.hlid; + + if (key_type == KEY_WEP) + cmd->lid_key_type = WEP_DEFAULT_LID_TYPE; + else if (is_broadcast_ether_addr(addr)) + cmd->lid_key_type = BROADCAST_LID_TYPE; + else + cmd->lid_key_type = UNICAST_LID_TYPE; + + cmd->key_action = cpu_to_le16(action); + cmd->key_size = key_size; + cmd->key_type = key_type; + + cmd->ac_seq_num16[0] = cpu_to_le16(tx_seq_16); + cmd->ac_seq_num32[0] = cpu_to_le32(tx_seq_32); + + cmd->key_id = id; + + if (key_type == KEY_TKIP) { + /* + * We get the key in the following form: + * TKIP (16 bytes) - TX MIC (8 bytes) - RX MIC (8 bytes) + * but the target is expecting: + * TKIP - RX MIC - TX MIC + */ + memcpy(cmd->key, key, 16); + memcpy(cmd->key + 16, key + 24, 8); + memcpy(cmd->key + 24, key + 16, 8); + + } else { + memcpy(cmd->key, key, key_size); + } + + wl1271_dump(DEBUG_CRYPT, "TARGET KEY: ", cmd, sizeof(*cmd)); + + ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_warning("could not set keys"); + goto out; + } + +out: + kfree(cmd); + + return ret; +} + +/* + * TODO: merge with sta/ibss into 1 set_key function. + * note there are slight diffs + */ +int wl1271_cmd_set_ap_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, + u16 action, u8 id, u8 key_type, + u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, + u16 tx_seq_16) +{ + struct wl1271_cmd_set_keys *cmd; + int ret = 0; + u8 lid_type; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + if (hlid == wlvif->ap.bcast_hlid) { + if (key_type == KEY_WEP) + lid_type = WEP_DEFAULT_LID_TYPE; + else + lid_type = BROADCAST_LID_TYPE; + } else { + lid_type = UNICAST_LID_TYPE; + } + + wl1271_debug(DEBUG_CRYPT, "ap key action: %d id: %d lid: %d type: %d" + " hlid: %d", (int)action, (int)id, (int)lid_type, + (int)key_type, (int)hlid); + + cmd->lid_key_type = lid_type; + cmd->hlid = hlid; + cmd->key_action = cpu_to_le16(action); + cmd->key_size = key_size; + cmd->key_type = key_type; + cmd->key_id = id; + cmd->ac_seq_num16[0] = cpu_to_le16(tx_seq_16); + cmd->ac_seq_num32[0] = cpu_to_le32(tx_seq_32); + + if (key_type == KEY_TKIP) { + /* + * We get the key in the following form: + * TKIP (16 bytes) - TX MIC (8 bytes) - RX MIC (8 bytes) + * but the target is expecting: + * TKIP - RX MIC - TX MIC + */ + memcpy(cmd->key, key, 16); + memcpy(cmd->key + 16, key + 24, 8); + memcpy(cmd->key + 24, key + 16, 8); + } else { + memcpy(cmd->key, key, key_size); + } + + wl1271_dump(DEBUG_CRYPT, "TARGET AP KEY: ", cmd, sizeof(*cmd)); + + ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_warning("could not set ap keys"); + goto out; + } + +out: + kfree(cmd); + return ret; +} + +int wl12xx_cmd_set_peer_state(struct wl1271 *wl, u8 hlid) +{ + struct wl12xx_cmd_set_peer_state *cmd; + int ret = 0; + + wl1271_debug(DEBUG_CMD, "cmd set peer state (hlid=%d)", hlid); + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + + cmd->hlid = hlid; + cmd->state = WL1271_CMD_STA_STATE_CONNECTED; + + ret = wl1271_cmd_send(wl, CMD_SET_PEER_STATE, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("failed to send set peer state command"); + goto out_free; + } + +out_free: + kfree(cmd); + +out: + return ret; +} + +int wl12xx_cmd_add_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif, + struct ieee80211_sta *sta, u8 hlid) +{ + struct wl12xx_cmd_add_peer *cmd; + int i, ret; + u32 sta_rates; + + wl1271_debug(DEBUG_CMD, "cmd add peer %d", (int)hlid); + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + + memcpy(cmd->addr, sta->addr, ETH_ALEN); + cmd->bss_index = WL1271_AP_BSS_INDEX; + cmd->aid = sta->aid; + cmd->hlid = hlid; + cmd->sp_len = sta->max_sp; + cmd->wmm = sta->wme ? 1 : 0; + + for (i = 0; i < NUM_ACCESS_CATEGORIES_COPY; i++) + if (sta->wme && (sta->uapsd_queues & BIT(i))) + cmd->psd_type[i] = WL1271_PSD_UPSD_TRIGGER; + else + cmd->psd_type[i] = WL1271_PSD_LEGACY; + + sta_rates = sta->supp_rates[wlvif->band]; + if (sta->ht_cap.ht_supported) + sta_rates |= sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET; + + cmd->supported_rates = + cpu_to_le32(wl1271_tx_enabled_rates_get(wl, sta_rates, + wlvif->band)); + + wl1271_debug(DEBUG_CMD, "new peer rates=0x%x queues=0x%x", + cmd->supported_rates, sta->uapsd_queues); + + ret = wl1271_cmd_send(wl, CMD_ADD_PEER, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("failed to initiate cmd add peer"); + goto out_free; + } + +out_free: + kfree(cmd); + +out: + return ret; +} + +int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid) +{ + struct wl12xx_cmd_remove_peer *cmd; + int ret; + + wl1271_debug(DEBUG_CMD, "cmd remove peer %d", (int)hlid); + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + + cmd->hlid = hlid; + /* We never send a deauth, mac80211 is in charge of this */ + cmd->reason_opcode = 0; + cmd->send_deauth_flag = 0; + + ret = wl1271_cmd_send(wl, CMD_REMOVE_PEER, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("failed to initiate cmd remove peer"); + goto out_free; + } + + /* + * We are ok with a timeout here. The event is sometimes not sent + * due to a firmware bug. + */ + wl1271_cmd_wait_for_event_or_timeout(wl, + PEER_REMOVE_COMPLETE_EVENT_ID); + +out_free: + kfree(cmd); + +out: + return ret; +} + +int wl12xx_cmd_config_fwlog(struct wl1271 *wl) +{ + struct wl12xx_cmd_config_fwlog *cmd; + int ret = 0; + + wl1271_debug(DEBUG_CMD, "cmd config firmware logger"); + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + + cmd->logger_mode = wl->conf.fwlog.mode; + cmd->log_severity = wl->conf.fwlog.severity; + cmd->timestamp = wl->conf.fwlog.timestamp; + cmd->output = wl->conf.fwlog.output; + cmd->threshold = wl->conf.fwlog.threshold; + + ret = wl1271_cmd_send(wl, CMD_CONFIG_FWLOGGER, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("failed to send config firmware logger command"); + goto out_free; + } + +out_free: + kfree(cmd); + +out: + return ret; +} + +int wl12xx_cmd_start_fwlog(struct wl1271 *wl) +{ + struct wl12xx_cmd_start_fwlog *cmd; + int ret = 0; + + wl1271_debug(DEBUG_CMD, "cmd start firmware logger"); + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + + ret = wl1271_cmd_send(wl, CMD_START_FWLOGGER, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("failed to send start firmware logger command"); + goto out_free; + } + +out_free: + kfree(cmd); + +out: + return ret; +} + +int wl12xx_cmd_stop_fwlog(struct wl1271 *wl) +{ + struct wl12xx_cmd_stop_fwlog *cmd; + int ret = 0; + + wl1271_debug(DEBUG_CMD, "cmd stop firmware logger"); + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + + ret = wl1271_cmd_send(wl, CMD_STOP_FWLOGGER, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("failed to send stop firmware logger command"); + goto out_free; + } + +out_free: + kfree(cmd); + +out: + return ret; +} + +static int wl12xx_cmd_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, + u8 role_id) +{ + struct wl12xx_cmd_roc *cmd; + int ret = 0; + + wl1271_debug(DEBUG_CMD, "cmd roc %d (%d)", wlvif->channel, role_id); + + if (WARN_ON(role_id == WL12XX_INVALID_ROLE_ID)) + return -EINVAL; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + + cmd->role_id = role_id; + cmd->channel = wlvif->channel; + switch (wlvif->band) { + case IEEE80211_BAND_2GHZ: + cmd->band = RADIO_BAND_2_4GHZ; + break; + case IEEE80211_BAND_5GHZ: + cmd->band = RADIO_BAND_5GHZ; + break; + default: + wl1271_error("roc - unknown band: %d", (int)wlvif->band); + ret = -EINVAL; + goto out_free; + } + + + ret = wl1271_cmd_send(wl, CMD_REMAIN_ON_CHANNEL, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("failed to send ROC command"); + goto out_free; + } + +out_free: + kfree(cmd); + +out: + return ret; +} + +static int wl12xx_cmd_croc(struct wl1271 *wl, u8 role_id) +{ + struct wl12xx_cmd_croc *cmd; + int ret = 0; + + wl1271_debug(DEBUG_CMD, "cmd croc (%d)", role_id); + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + cmd->role_id = role_id; + + ret = wl1271_cmd_send(wl, CMD_CANCEL_REMAIN_ON_CHANNEL, cmd, + sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("failed to send ROC command"); + goto out_free; + } + +out_free: + kfree(cmd); + +out: + return ret; +} + +int wl12xx_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 role_id) +{ + int ret = 0; + + if (WARN_ON(test_bit(role_id, wl->roc_map))) + return 0; + + ret = wl12xx_cmd_roc(wl, wlvif, role_id); + if (ret < 0) + goto out; + + ret = wl1271_cmd_wait_for_event(wl, + REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID); + if (ret < 0) { + wl1271_error("cmd roc event completion error"); + goto out; + } + + __set_bit(role_id, wl->roc_map); +out: + return ret; +} + +int wl12xx_croc(struct wl1271 *wl, u8 role_id) +{ + int ret = 0; + + if (WARN_ON(!test_bit(role_id, wl->roc_map))) + return 0; + + ret = wl12xx_cmd_croc(wl, role_id); + if (ret < 0) + goto out; + + __clear_bit(role_id, wl->roc_map); + + /* + * Rearm the tx watchdog when removing the last ROC. This prevents + * recoveries due to just finished ROCs - when Tx hasn't yet had + * a chance to get out. + */ + if (find_first_bit(wl->roc_map, WL12XX_MAX_ROLES) >= WL12XX_MAX_ROLES) + wl12xx_rearm_tx_watchdog_locked(wl); +out: + return ret; +} + +int wl12xx_cmd_channel_switch(struct wl1271 *wl, + struct wl12xx_vif *wlvif, + struct ieee80211_channel_switch *ch_switch) +{ + struct wl12xx_cmd_channel_switch *cmd; + int ret; + + wl1271_debug(DEBUG_ACX, "cmd channel switch"); + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + + cmd->role_id = wlvif->role_id; + cmd->channel = ch_switch->channel->hw_value; + cmd->switch_time = ch_switch->count; + cmd->stop_tx = ch_switch->block_tx; + + /* FIXME: control from mac80211 in the future */ + cmd->post_switch_tx_disable = 0; /* Enable TX on the target channel */ + + ret = wl1271_cmd_send(wl, CMD_CHANNEL_SWITCH, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("failed to send channel switch command"); + goto out_free; + } + +out_free: + kfree(cmd); + +out: + return ret; +} + +int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl) +{ + struct wl12xx_cmd_stop_channel_switch *cmd; + int ret; + + wl1271_debug(DEBUG_ACX, "cmd stop channel switch"); + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) { + ret = -ENOMEM; + goto out; + } + + ret = wl1271_cmd_send(wl, CMD_STOP_CHANNEL_SWICTH, cmd, sizeof(*cmd), 0); + if (ret < 0) { + wl1271_error("failed to stop channel switch command"); + goto out_free; + } + +out_free: + kfree(cmd); + +out: + return ret; +} + +/* start dev role and roc on its channel */ +int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) +{ + int ret; + + if (WARN_ON(!(wlvif->bss_type == BSS_TYPE_STA_BSS || + wlvif->bss_type == BSS_TYPE_IBSS))) + return -EINVAL; + + ret = wl12xx_cmd_role_start_dev(wl, wlvif); + if (ret < 0) + goto out; + + ret = wl12xx_roc(wl, wlvif, wlvif->dev_role_id); + if (ret < 0) + goto out_stop; + + return 0; + +out_stop: + wl12xx_cmd_role_stop_dev(wl, wlvif); +out: + return ret; +} + +/* croc dev hlid, and stop the role */ +int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) +{ + int ret; + + if (WARN_ON(!(wlvif->bss_type == BSS_TYPE_STA_BSS || + wlvif->bss_type == BSS_TYPE_IBSS))) + return -EINVAL; + + /* flush all pending packets */ + wl1271_tx_work_locked(wl); + + if (test_bit(wlvif->dev_role_id, wl->roc_map)) { + ret = wl12xx_croc(wl, wlvif->dev_role_id); + if (ret < 0) + goto out; + } + + ret = wl12xx_cmd_role_stop_dev(wl, wlvif); + if (ret < 0) + goto out; +out: + return ret; +} -- cgit v1.2.3-70-g09d2 From c31be25a7144ebc9b7a22128909bac7654d4c46b Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Mon, 21 Nov 2011 19:25:24 +0200 Subject: wl12xx/wlcore: move wl1271 struct to wlcore and add ops In order to add chip-specific operations and prepare for future elements that need to be set by the lower driver, move the wl1271 structure to the wlcore.h file and add an empty placeholder for the operations structure. Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wl12xx/main.c | 4 + drivers/net/wireless/ti/wlcore/acx.c | 2 +- drivers/net/wireless/ti/wlcore/acx.h | 2 +- drivers/net/wireless/ti/wlcore/boot.h | 2 +- drivers/net/wireless/ti/wlcore/cmd.c | 2 +- drivers/net/wireless/ti/wlcore/cmd.h | 2 +- drivers/net/wireless/ti/wlcore/debugfs.c | 2 +- drivers/net/wireless/ti/wlcore/debugfs.h | 2 +- drivers/net/wireless/ti/wlcore/event.c | 2 +- drivers/net/wireless/ti/wlcore/init.h | 2 +- drivers/net/wireless/ti/wlcore/io.c | 2 +- drivers/net/wireless/ti/wlcore/main.c | 7 +- drivers/net/wireless/ti/wlcore/ps.h | 2 +- drivers/net/wireless/ti/wlcore/rx.c | 2 +- drivers/net/wireless/ti/wlcore/scan.c | 2 +- drivers/net/wireless/ti/wlcore/scan.h | 2 +- drivers/net/wireless/ti/wlcore/sdio.c | 2 +- drivers/net/wireless/ti/wlcore/spi.c | 2 +- drivers/net/wireless/ti/wlcore/testmode.c | 2 +- drivers/net/wireless/ti/wlcore/tx.c | 2 +- drivers/net/wireless/ti/wlcore/wl12xx.h | 211 ---------------------------- drivers/net/wireless/ti/wlcore/wlcore.h | 219 ++++++++++++++++++++++++++++++ 22 files changed, 247 insertions(+), 230 deletions(-) (limited to 'drivers/net/wireless/ti/wlcore/cmd.c') diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index c4fc93f5718..0d30150a3de 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c @@ -27,6 +27,9 @@ #include "../wlcore/wlcore.h" #include "../wlcore/debug.h" +static struct wlcore_ops wl12xx_ops = { +}; + static int __devinit wl12xx_probe(struct platform_device *pdev) { struct wl1271 *wl; @@ -39,6 +42,7 @@ static int __devinit wl12xx_probe(struct platform_device *pdev) } wl = hw->priv; + wl->ops = &wl12xx_ops; return wlcore_probe(wl, pdev); } diff --git a/drivers/net/wireless/ti/wlcore/acx.c b/drivers/net/wireless/ti/wlcore/acx.c index bc96db0683a..43cc6a2dae1 100644 --- a/drivers/net/wireless/ti/wlcore/acx.c +++ b/drivers/net/wireless/ti/wlcore/acx.c @@ -28,7 +28,7 @@ #include #include -#include "wl12xx.h" +#include "wlcore.h" #include "debug.h" #include "wl12xx_80211.h" #include "reg.h" diff --git a/drivers/net/wireless/ti/wlcore/acx.h b/drivers/net/wireless/ti/wlcore/acx.h index a28fc044034..e24511a0461 100644 --- a/drivers/net/wireless/ti/wlcore/acx.h +++ b/drivers/net/wireless/ti/wlcore/acx.h @@ -25,7 +25,7 @@ #ifndef __ACX_H__ #define __ACX_H__ -#include "wl12xx.h" +#include "wlcore.h" #include "cmd.h" /************************************************************************* diff --git a/drivers/net/wireless/ti/wlcore/boot.h b/drivers/net/wireless/ti/wlcore/boot.h index c3adc09f403..a39e0e2a0c2 100644 --- a/drivers/net/wireless/ti/wlcore/boot.h +++ b/drivers/net/wireless/ti/wlcore/boot.h @@ -24,7 +24,7 @@ #ifndef __BOOT_H__ #define __BOOT_H__ -#include "wl12xx.h" +#include "wlcore.h" int wl1271_boot(struct wl1271 *wl); int wl1271_load_firmware(struct wl1271 *wl); diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index 82cb90a4a99..68e686f25af 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c @@ -28,7 +28,7 @@ #include #include -#include "wl12xx.h" +#include "wlcore.h" #include "debug.h" #include "reg.h" #include "io.h" diff --git a/drivers/net/wireless/ti/wlcore/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h index de217d92516..58d2a8b5c8d 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.h +++ b/drivers/net/wireless/ti/wlcore/cmd.h @@ -25,7 +25,7 @@ #ifndef __CMD_H__ #define __CMD_H__ -#include "wl12xx.h" +#include "wlcore.h" struct acx_header; diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c index e1cf7276596..02e4255ed7a 100644 --- a/drivers/net/wireless/ti/wlcore/debugfs.c +++ b/drivers/net/wireless/ti/wlcore/debugfs.c @@ -26,7 +26,7 @@ #include #include -#include "wl12xx.h" +#include "wlcore.h" #include "debug.h" #include "acx.h" #include "ps.h" diff --git a/drivers/net/wireless/ti/wlcore/debugfs.h b/drivers/net/wireless/ti/wlcore/debugfs.h index 254c5b292cf..a8d3aef011f 100644 --- a/drivers/net/wireless/ti/wlcore/debugfs.h +++ b/drivers/net/wireless/ti/wlcore/debugfs.h @@ -24,7 +24,7 @@ #ifndef __DEBUGFS_H__ #define __DEBUGFS_H__ -#include "wl12xx.h" +#include "wlcore.h" int wl1271_debugfs_init(struct wl1271 *wl); void wl1271_debugfs_exit(struct wl1271 *wl); diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c index 96f06a89c2a..8d79af964b8 100644 --- a/drivers/net/wireless/ti/wlcore/event.c +++ b/drivers/net/wireless/ti/wlcore/event.c @@ -21,7 +21,7 @@ * */ -#include "wl12xx.h" +#include "wlcore.h" #include "debug.h" #include "reg.h" #include "io.h" diff --git a/drivers/net/wireless/ti/wlcore/init.h b/drivers/net/wireless/ti/wlcore/init.h index 2da0f404ef6..a45fbfddec1 100644 --- a/drivers/net/wireless/ti/wlcore/init.h +++ b/drivers/net/wireless/ti/wlcore/init.h @@ -24,7 +24,7 @@ #ifndef __INIT_H__ #define __INIT_H__ -#include "wl12xx.h" +#include "wlcore.h" int wl1271_hw_init_power_auth(struct wl1271 *wl); int wl1271_init_templates_config(struct wl1271 *wl); diff --git a/drivers/net/wireless/ti/wlcore/io.c b/drivers/net/wireless/ti/wlcore/io.c index c574a3b31e3..b0701fb9dbd 100644 --- a/drivers/net/wireless/ti/wlcore/io.c +++ b/drivers/net/wireless/ti/wlcore/io.c @@ -26,7 +26,7 @@ #include #include -#include "wl12xx.h" +#include "wlcore.h" #include "debug.h" #include "wl12xx_80211.h" #include "io.h" diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 3cbc774f105..194a8b00de1 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -35,7 +35,7 @@ #include #include -#include "wl12xx.h" +#include "wlcore.h" #include "debug.h" #include "wl12xx_80211.h" #include "reg.h" @@ -5485,6 +5485,11 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) unsigned long irqflags; int ret; + if (!wl->ops) { + ret = -EINVAL; + goto out_free_hw; + } + wl->irq = platform_get_irq(pdev, 0); wl->ref_clock = pdata->board_ref_clock; wl->tcxo_clock = pdata->board_tcxo_clock; diff --git a/drivers/net/wireless/ti/wlcore/ps.h b/drivers/net/wireless/ti/wlcore/ps.h index 5f19d4fbbf2..de4f9da8ed2 100644 --- a/drivers/net/wireless/ti/wlcore/ps.h +++ b/drivers/net/wireless/ti/wlcore/ps.h @@ -24,7 +24,7 @@ #ifndef __PS_H__ #define __PS_H__ -#include "wl12xx.h" +#include "wlcore.h" #include "acx.h" int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, diff --git a/drivers/net/wireless/ti/wlcore/rx.c b/drivers/net/wireless/ti/wlcore/rx.c index cfa6071704c..4fc37f9f38a 100644 --- a/drivers/net/wireless/ti/wlcore/rx.c +++ b/drivers/net/wireless/ti/wlcore/rx.c @@ -24,7 +24,7 @@ #include #include -#include "wl12xx.h" +#include "wlcore.h" #include "debug.h" #include "acx.h" #include "reg.h" diff --git a/drivers/net/wireless/ti/wlcore/scan.c b/drivers/net/wireless/ti/wlcore/scan.c index a57f333d07f..ade21a011c4 100644 --- a/drivers/net/wireless/ti/wlcore/scan.c +++ b/drivers/net/wireless/ti/wlcore/scan.c @@ -23,7 +23,7 @@ #include -#include "wl12xx.h" +#include "wlcore.h" #include "debug.h" #include "cmd.h" #include "scan.h" diff --git a/drivers/net/wireless/ti/wlcore/scan.h b/drivers/net/wireless/ti/wlcore/scan.h index 2b300f4d0be..81ee36ac207 100644 --- a/drivers/net/wireless/ti/wlcore/scan.h +++ b/drivers/net/wireless/ti/wlcore/scan.h @@ -24,7 +24,7 @@ #ifndef __SCAN_H__ #define __SCAN_H__ -#include "wl12xx.h" +#include "wlcore.h" int wl1271_scan(struct wl1271 *wl, struct ieee80211_vif *vif, const u8 *ssid, size_t ssid_len, diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c index 4b3c32774ba..e407acf124d 100644 --- a/drivers/net/wireless/ti/wlcore/sdio.c +++ b/drivers/net/wireless/ti/wlcore/sdio.c @@ -33,7 +33,7 @@ #include #include -#include "wl12xx.h" +#include "wlcore.h" #include "wl12xx_80211.h" #include "io.h" diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c index 2fc18a8dcce..9eeb3941297 100644 --- a/drivers/net/wireless/ti/wlcore/spi.c +++ b/drivers/net/wireless/ti/wlcore/spi.c @@ -30,7 +30,7 @@ #include #include -#include "wl12xx.h" +#include "wlcore.h" #include "wl12xx_80211.h" #include "io.h" diff --git a/drivers/net/wireless/ti/wlcore/testmode.c b/drivers/net/wireless/ti/wlcore/testmode.c index 1e93bb9c024..2ea40131e64 100644 --- a/drivers/net/wireless/ti/wlcore/testmode.c +++ b/drivers/net/wireless/ti/wlcore/testmode.c @@ -25,7 +25,7 @@ #include #include -#include "wl12xx.h" +#include "wlcore.h" #include "debug.h" #include "acx.h" #include "reg.h" diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c index 43ae49143d6..83cb83cdc10 100644 --- a/drivers/net/wireless/ti/wlcore/tx.c +++ b/drivers/net/wireless/ti/wlcore/tx.c @@ -25,7 +25,7 @@ #include #include -#include "wl12xx.h" +#include "wlcore.h" #include "debug.h" #include "io.h" #include "reg.h" diff --git a/drivers/net/wireless/ti/wlcore/wl12xx.h b/drivers/net/wireless/ti/wlcore/wl12xx.h index 82802d1c078..37b2d64b5b5 100644 --- a/drivers/net/wireless/ti/wlcore/wl12xx.h +++ b/drivers/net/wireless/ti/wlcore/wl12xx.h @@ -34,7 +34,6 @@ #include "conf.h" #include "ini.h" -#include "event.h" #define WL127X_FW_NAME_MULTI "ti-connectivity/wl127x-fw-4-mr.bin" #define WL127X_FW_NAME_SINGLE "ti-connectivity/wl127x-fw-4-sr.bin" @@ -293,216 +292,6 @@ struct wl1271_link { u8 ba_bitmap; }; -struct wl1271 { - struct ieee80211_hw *hw; - bool mac80211_registered; - - struct device *dev; - - void *if_priv; - - struct wl1271_if_operations *if_ops; - - void (*set_power)(bool enable); - int irq; - int ref_clock; - - spinlock_t wl_lock; - - enum wl1271_state state; - enum wl12xx_fw_type fw_type; - bool plt; - u8 last_vif_count; - struct mutex mutex; - - unsigned long flags; - - struct wl1271_partition_set part; - - struct wl1271_chip chip; - - int cmd_box_addr; - int event_box_addr; - - u8 *fw; - size_t fw_len; - void *nvs; - size_t nvs_len; - - s8 hw_pg_ver; - - /* address read from the fuse ROM */ - u32 fuse_oui_addr; - u32 fuse_nic_addr; - - /* we have up to 2 MAC addresses */ - struct mac_address addresses[2]; - int channel; - u8 system_hlid; - - unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)]; - unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)]; - unsigned long roc_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)]; - unsigned long rate_policies_map[ - BITS_TO_LONGS(WL12XX_MAX_RATE_POLICIES)]; - - struct list_head wlvif_list; - - u8 sta_count; - u8 ap_count; - - struct wl1271_acx_mem_map *target_mem_map; - - /* Accounting for allocated / available TX blocks on HW */ - u32 tx_blocks_freed; - u32 tx_blocks_available; - u32 tx_allocated_blocks; - u32 tx_results_count; - - /* amount of spare TX blocks to use */ - u32 tx_spare_blocks; - - /* Accounting for allocated / available Tx packets in HW */ - u32 tx_pkts_freed[NUM_TX_QUEUES]; - u32 tx_allocated_pkts[NUM_TX_QUEUES]; - - /* Transmitted TX packets counter for chipset interface */ - u32 tx_packets_count; - - /* Time-offset between host and chipset clocks */ - s64 time_offset; - - /* Frames scheduled for transmission, not handled yet */ - int tx_queue_count[NUM_TX_QUEUES]; - long stopped_queues_map; - - /* Frames received, not handled yet by mac80211 */ - struct sk_buff_head deferred_rx_queue; - - /* Frames sent, not returned yet to mac80211 */ - struct sk_buff_head deferred_tx_queue; - - struct work_struct tx_work; - struct workqueue_struct *freezable_wq; - - /* Pending TX frames */ - unsigned long tx_frames_map[BITS_TO_LONGS(ACX_TX_DESCRIPTORS)]; - struct sk_buff *tx_frames[ACX_TX_DESCRIPTORS]; - int tx_frames_cnt; - - /* FW Rx counter */ - u32 rx_counter; - - /* Rx memory pool address */ - struct wl1271_rx_mem_pool_addr rx_mem_pool_addr; - - /* Intermediate buffer, used for packet aggregation */ - u8 *aggr_buf; - - /* Reusable dummy packet template */ - struct sk_buff *dummy_packet; - - /* Network stack work */ - struct work_struct netstack_work; - - /* FW log buffer */ - u8 *fwlog; - - /* Number of valid bytes in the FW log buffer */ - ssize_t fwlog_size; - - /* Sysfs FW log entry readers wait queue */ - wait_queue_head_t fwlog_waitq; - - /* Hardware recovery work */ - struct work_struct recovery_work; - - struct event_mailbox *mbox; - - /* The mbox event mask */ - u32 event_mask; - - /* Mailbox pointers */ - u32 mbox_ptr[2]; - - /* Are we currently scanning */ - struct ieee80211_vif *scan_vif; - struct wl1271_scan scan; - struct delayed_work scan_complete_work; - - bool sched_scanning; - - /* The current band */ - enum ieee80211_band band; - - struct completion *elp_compl; - struct delayed_work elp_work; - - /* in dBm */ - int power_level; - - struct wl1271_stats stats; - - __le32 buffer_32; - u32 buffer_cmd; - u32 buffer_busyword[WL1271_BUSY_WORD_CNT]; - - struct wl12xx_fw_status *fw_status; - struct wl1271_tx_hw_res_if *tx_res_if; - - /* Current chipset configuration */ - struct conf_drv_settings conf; - - bool sg_enabled; - - bool enable_11a; - - /* Most recently reported noise in dBm */ - s8 noise; - - /* bands supported by this instance of wl12xx */ - struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; - - int tcxo_clock; - - /* - * wowlan trigger was configured during suspend. - * (currently, only "ANY" trigger is supported) - */ - bool wow_enabled; - bool irq_wake_enabled; - - /* - * AP-mode - links indexed by HLID. The global and broadcast links - * are always active. - */ - struct wl1271_link links[WL12XX_MAX_LINKS]; - - /* AP-mode - a bitmap of links currently in PS mode according to FW */ - u32 ap_fw_ps_map; - - /* AP-mode - a bitmap of links currently in PS mode in mac80211 */ - unsigned long ap_ps_map; - - /* Quirks of specific hardware revisions */ - unsigned int quirks; - - /* Platform limitations */ - unsigned int platform_quirks; - - /* number of currently active RX BA sessions */ - int ba_rx_session_count; - - /* AP-mode - number of currently connected stations */ - int active_sta_count; - - /* last wlvif we transmitted from */ - struct wl12xx_vif *last_wlvif; - - /* work to fire when Tx is stuck */ - struct delayed_work tx_watchdog_work; -}; - struct wl1271_station { u8 hlid; }; diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index 4cabf971da5..0bcc6adcbc1 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h @@ -22,7 +22,226 @@ #ifndef __WLCORE_H__ #define __WLCORE_H__ +#include + #include "wl12xx.h" +#include "event.h" + +struct wlcore_ops { +}; + +struct wl1271 { + struct ieee80211_hw *hw; + bool mac80211_registered; + + struct device *dev; + + void *if_priv; + + struct wl1271_if_operations *if_ops; + + void (*set_power)(bool enable); + int irq; + int ref_clock; + + spinlock_t wl_lock; + + enum wl1271_state state; + enum wl12xx_fw_type fw_type; + bool plt; + u8 last_vif_count; + struct mutex mutex; + + unsigned long flags; + + struct wl1271_partition_set part; + + struct wl1271_chip chip; + + int cmd_box_addr; + int event_box_addr; + + u8 *fw; + size_t fw_len; + void *nvs; + size_t nvs_len; + + s8 hw_pg_ver; + + /* address read from the fuse ROM */ + u32 fuse_oui_addr; + u32 fuse_nic_addr; + + /* we have up to 2 MAC addresses */ + struct mac_address addresses[2]; + int channel; + u8 system_hlid; + + unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)]; + unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)]; + unsigned long roc_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)]; + unsigned long rate_policies_map[ + BITS_TO_LONGS(WL12XX_MAX_RATE_POLICIES)]; + + struct list_head wlvif_list; + + u8 sta_count; + u8 ap_count; + + struct wl1271_acx_mem_map *target_mem_map; + + /* Accounting for allocated / available TX blocks on HW */ + u32 tx_blocks_freed; + u32 tx_blocks_available; + u32 tx_allocated_blocks; + u32 tx_results_count; + + /* amount of spare TX blocks to use */ + u32 tx_spare_blocks; + + /* Accounting for allocated / available Tx packets in HW */ + u32 tx_pkts_freed[NUM_TX_QUEUES]; + u32 tx_allocated_pkts[NUM_TX_QUEUES]; + + /* Transmitted TX packets counter for chipset interface */ + u32 tx_packets_count; + + /* Time-offset between host and chipset clocks */ + s64 time_offset; + + /* Frames scheduled for transmission, not handled yet */ + int tx_queue_count[NUM_TX_QUEUES]; + long stopped_queues_map; + + /* Frames received, not handled yet by mac80211 */ + struct sk_buff_head deferred_rx_queue; + + /* Frames sent, not returned yet to mac80211 */ + struct sk_buff_head deferred_tx_queue; + + struct work_struct tx_work; + struct workqueue_struct *freezable_wq; + + /* Pending TX frames */ + unsigned long tx_frames_map[BITS_TO_LONGS(ACX_TX_DESCRIPTORS)]; + struct sk_buff *tx_frames[ACX_TX_DESCRIPTORS]; + int tx_frames_cnt; + + /* FW Rx counter */ + u32 rx_counter; + + /* Rx memory pool address */ + struct wl1271_rx_mem_pool_addr rx_mem_pool_addr; + + /* Intermediate buffer, used for packet aggregation */ + u8 *aggr_buf; + + /* Reusable dummy packet template */ + struct sk_buff *dummy_packet; + + /* Network stack work */ + struct work_struct netstack_work; + + /* FW log buffer */ + u8 *fwlog; + + /* Number of valid bytes in the FW log buffer */ + ssize_t fwlog_size; + + /* Sysfs FW log entry readers wait queue */ + wait_queue_head_t fwlog_waitq; + + /* Hardware recovery work */ + struct work_struct recovery_work; + + /* Pointer that holds DMA-friendly block for the mailbox */ + struct event_mailbox *mbox; + + /* The mbox event mask */ + u32 event_mask; + + /* Mailbox pointers */ + u32 mbox_ptr[2]; + + /* Are we currently scanning */ + struct ieee80211_vif *scan_vif; + struct wl1271_scan scan; + struct delayed_work scan_complete_work; + + bool sched_scanning; + + /* The current band */ + enum ieee80211_band band; + + struct completion *elp_compl; + struct delayed_work elp_work; + + /* in dBm */ + int power_level; + + struct wl1271_stats stats; + + __le32 buffer_32; + u32 buffer_cmd; + u32 buffer_busyword[WL1271_BUSY_WORD_CNT]; + + struct wl12xx_fw_status *fw_status; + struct wl1271_tx_hw_res_if *tx_res_if; + + /* Current chipset configuration */ + struct conf_drv_settings conf; + + bool sg_enabled; + + bool enable_11a; + + /* Most recently reported noise in dBm */ + s8 noise; + + /* bands supported by this instance of wl12xx */ + struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; + + int tcxo_clock; + + /* + * wowlan trigger was configured during suspend. + * (currently, only "ANY" trigger is supported) + */ + bool wow_enabled; + bool irq_wake_enabled; + + /* + * AP-mode - links indexed by HLID. The global and broadcast links + * are always active. + */ + struct wl1271_link links[WL12XX_MAX_LINKS]; + + /* AP-mode - a bitmap of links currently in PS mode according to FW */ + u32 ap_fw_ps_map; + + /* AP-mode - a bitmap of links currently in PS mode in mac80211 */ + unsigned long ap_ps_map; + + /* Quirks of specific hardware revisions */ + unsigned int quirks; + + /* Platform limitations */ + unsigned int platform_quirks; + + /* number of currently active RX BA sessions */ + int ba_rx_session_count; + + /* AP-mode - number of currently connected stations */ + int active_sta_count; + + /* last wlvif we transmitted from */ + struct wl12xx_vif *last_wlvif; + + /* work to fire when Tx is stuck */ + struct delayed_work tx_watchdog_work; + + struct wlcore_ops *ops; +}; int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev); int __devexit wlcore_remove(struct platform_device *pdev); -- cgit v1.2.3-70-g09d2 From 00782136b4d6e2316e0a2a55f3b1fba160e9576e Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Tue, 29 Nov 2011 13:38:37 +0200 Subject: wlcore/wl12xx: implement chip-specific register tables Add register tables support in wlcore, add some new IO functions to read and write to chip-specific register and data addresses. Move some common register values from wl12xx to wlcore and add the registers table to wl12xx. Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wl12xx/main.c | 43 ++- drivers/net/wireless/ti/wl12xx/reg.h | 551 +++++++++++++++++++++++++++++ drivers/net/wireless/ti/wlcore/acx.c | 1 - drivers/net/wireless/ti/wlcore/boot.c | 71 ++-- drivers/net/wireless/ti/wlcore/boot.h | 67 ---- drivers/net/wireless/ti/wlcore/cmd.c | 26 +- drivers/net/wireless/ti/wlcore/cmd.h | 14 +- drivers/net/wireless/ti/wlcore/conf.h | 1 - drivers/net/wireless/ti/wlcore/event.c | 5 +- drivers/net/wireless/ti/wlcore/init.c | 1 - drivers/net/wireless/ti/wlcore/io.c | 29 +- drivers/net/wireless/ti/wlcore/io.h | 36 +- drivers/net/wireless/ti/wlcore/main.c | 35 +- drivers/net/wireless/ti/wlcore/ps.c | 5 +- drivers/net/wireless/ti/wlcore/reg.h | 555 ------------------------------ drivers/net/wireless/ti/wlcore/rx.c | 20 +- drivers/net/wireless/ti/wlcore/sdio.c | 4 +- drivers/net/wireless/ti/wlcore/spi.c | 2 - drivers/net/wireless/ti/wlcore/testmode.c | 1 - drivers/net/wireless/ti/wlcore/tx.c | 17 +- drivers/net/wireless/ti/wlcore/wlcore.h | 107 ++++++ 21 files changed, 852 insertions(+), 739 deletions(-) create mode 100644 drivers/net/wireless/ti/wl12xx/reg.h delete mode 100644 drivers/net/wireless/ti/wlcore/reg.h (limited to 'drivers/net/wireless/ti/wlcore/cmd.c') diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index 0d3ed7d7893..ea8480c1fae 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c @@ -27,7 +27,7 @@ #include "../wlcore/wlcore.h" #include "../wlcore/debug.h" -#include "../wlcore/reg.h" +#include "reg.h" static struct wlcore_ops wl12xx_ops = { }; @@ -52,6 +52,26 @@ static struct wlcore_partition_set wl12xx_ptable[PART_TABLE_LEN] = { }, }, + [PART_BOOT] = { /* in wl12xx we can use a mix of work and down + * partition here */ + .mem = { + .start = 0x00040000, + .size = 0x00014fc0 + }, + .reg = { + .start = REGISTERS_BASE, + .size = 0x00008800 + }, + .mem2 = { + .start = 0x00000000, + .size = 0x00000000 + }, + .mem3 = { + .start = 0x00000000, + .size = 0x00000000 + }, + }, + [PART_WORK] = { .mem = { .start = 0x00040000, @@ -91,6 +111,26 @@ static struct wlcore_partition_set wl12xx_ptable[PART_TABLE_LEN] = { } }; +static const int wl12xx_rtable[REG_TABLE_LEN] = { + [REG_ECPU_CONTROL] = WL12XX_REG_ECPU_CONTROL, + [REG_INTERRUPT_NO_CLEAR] = WL12XX_REG_INTERRUPT_NO_CLEAR, + [REG_INTERRUPT_ACK] = WL12XX_REG_INTERRUPT_ACK, + [REG_COMMAND_MAILBOX_PTR] = WL12XX_REG_COMMAND_MAILBOX_PTR, + [REG_EVENT_MAILBOX_PTR] = WL12XX_REG_EVENT_MAILBOX_PTR, + [REG_INTERRUPT_TRIG] = WL12XX_REG_INTERRUPT_TRIG, + [REG_INTERRUPT_MASK] = WL12XX_REG_INTERRUPT_MASK, + [REG_PC_ON_RECOVERY] = WL12XX_SCR_PAD4, + [REG_CHIP_ID_B] = WL12XX_CHIP_ID_B, + [REG_CMD_MBOX_ADDRESS] = WL12XX_CMD_MBOX_ADDRESS, + + /* data access memory addresses, used with partition translation */ + [REG_SLV_MEM_DATA] = WL1271_SLV_MEM_DATA, + [REG_SLV_REG_DATA] = WL1271_SLV_REG_DATA, + + /* raw data access memory addresses */ + [REG_RAW_FW_STATUS_ADDR] = FW_STATUS_ADDR, +}; + static int __devinit wl12xx_probe(struct platform_device *pdev) { struct wl1271 *wl; @@ -105,6 +145,7 @@ static int __devinit wl12xx_probe(struct platform_device *pdev) wl = hw->priv; wl->ops = &wl12xx_ops; wl->ptable = wl12xx_ptable; + wl->rtable = wl12xx_rtable; return wlcore_probe(wl, pdev); } diff --git a/drivers/net/wireless/ti/wl12xx/reg.h b/drivers/net/wireless/ti/wl12xx/reg.h new file mode 100644 index 00000000000..c6a47436475 --- /dev/null +++ b/drivers/net/wireless/ti/wl12xx/reg.h @@ -0,0 +1,551 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 1998-2009 Texas Instruments. All rights reserved. + * Copyright (C) 2009 Nokia Corporation + * + * Contact: Luciano Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __REG_H__ +#define __REG_H__ + +#include + +#define REGISTERS_BASE 0x00300000 +#define DRPW_BASE 0x00310000 + +#define REGISTERS_DOWN_SIZE 0x00008800 +#define REGISTERS_WORK_SIZE 0x0000b000 + +#define FW_STATUS_ADDR (0x14FC0 + 0xA000) + +/*=============================================== + Host Software Reset - 32bit RW + ------------------------------------------ + [31:1] Reserved + 0 SOFT_RESET Soft Reset - When this bit is set, + it holds the Wlan hardware in a soft reset state. + This reset disables all MAC and baseband processor + clocks except the CardBus/PCI interface clock. + It also initializes all MAC state machines except + the host interface. It does not reload the + contents of the EEPROM. When this bit is cleared + (not self-clearing), the Wlan hardware + exits the software reset state. +===============================================*/ +#define WL12XX_SLV_SOFT_RESET (REGISTERS_BASE + 0x0000) + +#define WL1271_SLV_REG_DATA (REGISTERS_BASE + 0x0008) +#define WL1271_SLV_REG_ADATA (REGISTERS_BASE + 0x000c) +#define WL1271_SLV_MEM_DATA (REGISTERS_BASE + 0x0018) + +#define WL12XX_REG_INTERRUPT_TRIG (REGISTERS_BASE + 0x0474) +#define WL12XX_REG_INTERRUPT_TRIG_H (REGISTERS_BASE + 0x0478) + +/*============================================= + Host Interrupt Mask Register - 32bit (RW) + ------------------------------------------ + Setting a bit in this register masks the + corresponding interrupt to the host. + 0 - RX0 - Rx first dubble buffer Data Interrupt + 1 - TXD - Tx Data Interrupt + 2 - TXXFR - Tx Transfer Interrupt + 3 - RX1 - Rx second dubble buffer Data Interrupt + 4 - RXXFR - Rx Transfer Interrupt + 5 - EVENT_A - Event Mailbox interrupt + 6 - EVENT_B - Event Mailbox interrupt + 7 - WNONHST - Wake On Host Interrupt + 8 - TRACE_A - Debug Trace interrupt + 9 - TRACE_B - Debug Trace interrupt + 10 - CDCMP - Command Complete Interrupt + 11 - + 12 - + 13 - + 14 - ICOMP - Initialization Complete Interrupt + 16 - SG SE - Soft Gemini - Sense enable interrupt + 17 - SG SD - Soft Gemini - Sense disable interrupt + 18 - - + 19 - - + 20 - - + 21- - + Default: 0x0001 +*==============================================*/ +#define WL12XX_REG_INTERRUPT_MASK (REGISTERS_BASE + 0x04DC) + +/*============================================= + Host Interrupt Mask Set 16bit, (Write only) + ------------------------------------------ + Setting a bit in this register sets + the corresponding bin in ACX_HINT_MASK register + without effecting the mask + state of other bits (0 = no effect). +==============================================*/ +#define ACX_REG_HINT_MASK_SET (REGISTERS_BASE + 0x04E0) + +/*============================================= + Host Interrupt Mask Clear 16bit,(Write only) + ------------------------------------------ + Setting a bit in this register clears + the corresponding bin in ACX_HINT_MASK register + without effecting the mask + state of other bits (0 = no effect). +=============================================*/ +#define ACX_REG_HINT_MASK_CLR (REGISTERS_BASE + 0x04E4) + +/*============================================= + Host Interrupt Status Nondestructive Read + 16bit,(Read only) + ------------------------------------------ + The host can read this register to determine + which interrupts are active. + Reading this register doesn't + effect its content. +=============================================*/ +#define WL12XX_REG_INTERRUPT_NO_CLEAR (REGISTERS_BASE + 0x04E8) + +/*============================================= + Host Interrupt Status Clear on Read Register + 16bit,(Read only) + ------------------------------------------ + The host can read this register to determine + which interrupts are active. + Reading this register clears it, + thus making all interrupts inactive. +==============================================*/ +#define ACX_REG_INTERRUPT_CLEAR (REGISTERS_BASE + 0x04F8) + +/*============================================= + Host Interrupt Acknowledge Register + 16bit,(Write only) + ------------------------------------------ + The host can set individual bits in this + register to clear (acknowledge) the corresp. + interrupt status bits in the HINT_STS_CLR and + HINT_STS_ND registers, thus making the + assotiated interrupt inactive. (0-no effect) +==============================================*/ +#define WL12XX_REG_INTERRUPT_ACK (REGISTERS_BASE + 0x04F0) + +#define WL12XX_REG_RX_DRIVER_COUNTER (REGISTERS_BASE + 0x0538) + +/* Device Configuration registers*/ +#define SOR_CFG (REGISTERS_BASE + 0x0800) + +/* Embedded ARM CPU Control */ + +/*=============================================== + Halt eCPU - 32bit RW + ------------------------------------------ + 0 HALT_ECPU Halt Embedded CPU - This bit is the + compliment of bit 1 (MDATA2) in the SOR_CFG register. + During a hardware reset, this bit holds + the inverse of MDATA2. + When downloading firmware from the host, + set this bit (pull down MDATA2). + The host clears this bit after downloading the firmware into + zero-wait-state SSRAM. + When loading firmware from Flash, clear this bit (pull up MDATA2) + so that the eCPU can run the bootloader code in Flash + HALT_ECPU eCPU State + -------------------- + 1 halt eCPU + 0 enable eCPU + ===============================================*/ +#define WL12XX_REG_ECPU_CONTROL (REGISTERS_BASE + 0x0804) + +#define WL12XX_HI_CFG (REGISTERS_BASE + 0x0808) + +/*=============================================== + EEPROM Burst Read Start - 32bit RW + ------------------------------------------ + [31:1] Reserved + 0 ACX_EE_START - EEPROM Burst Read Start 0 + Setting this bit starts a burst read from + the external EEPROM. + If this bit is set (after reset) before an EEPROM read/write, + the burst read starts at EEPROM address 0. + Otherwise, it starts at the address + following the address of the previous access. + TheWlan hardware hardware clears this bit automatically. + + Default: 0x00000000 +*================================================*/ +#define ACX_REG_EE_START (REGISTERS_BASE + 0x080C) + +#define WL12XX_OCP_POR_CTR (REGISTERS_BASE + 0x09B4) +#define WL12XX_OCP_DATA_WRITE (REGISTERS_BASE + 0x09B8) +#define WL12XX_OCP_DATA_READ (REGISTERS_BASE + 0x09BC) +#define WL12XX_OCP_CMD (REGISTERS_BASE + 0x09C0) + +#define WL12XX_HOST_WR_ACCESS (REGISTERS_BASE + 0x09F8) + +#define WL12XX_CHIP_ID_B (REGISTERS_BASE + 0x5674) + +#define WL12XX_ENABLE (REGISTERS_BASE + 0x5450) + +/* Power Management registers */ +#define WL12XX_ELP_CFG_MODE (REGISTERS_BASE + 0x5804) +#define WL12XX_ELP_CMD (REGISTERS_BASE + 0x5808) +#define WL12XX_PLL_CAL_TIME (REGISTERS_BASE + 0x5810) +#define WL12XX_CLK_REQ_TIME (REGISTERS_BASE + 0x5814) +#define WL12XX_CLK_BUF_TIME (REGISTERS_BASE + 0x5818) + +#define WL12XX_CFG_PLL_SYNC_CNT (REGISTERS_BASE + 0x5820) + +/* Scratch Pad registers*/ +#define WL12XX_SCR_PAD0 (REGISTERS_BASE + 0x5608) +#define WL12XX_SCR_PAD1 (REGISTERS_BASE + 0x560C) +#define WL12XX_SCR_PAD2 (REGISTERS_BASE + 0x5610) +#define WL12XX_SCR_PAD3 (REGISTERS_BASE + 0x5614) +#define WL12XX_SCR_PAD4 (REGISTERS_BASE + 0x5618) +#define WL12XX_SCR_PAD4_SET (REGISTERS_BASE + 0x561C) +#define WL12XX_SCR_PAD4_CLR (REGISTERS_BASE + 0x5620) +#define WL12XX_SCR_PAD5 (REGISTERS_BASE + 0x5624) +#define WL12XX_SCR_PAD5_SET (REGISTERS_BASE + 0x5628) +#define WL12XX_SCR_PAD5_CLR (REGISTERS_BASE + 0x562C) +#define WL12XX_SCR_PAD6 (REGISTERS_BASE + 0x5630) +#define WL12XX_SCR_PAD7 (REGISTERS_BASE + 0x5634) +#define WL12XX_SCR_PAD8 (REGISTERS_BASE + 0x5638) +#define WL12XX_SCR_PAD9 (REGISTERS_BASE + 0x563C) + +/* Spare registers*/ +#define WL12XX_SPARE_A1 (REGISTERS_BASE + 0x0994) +#define WL12XX_SPARE_A2 (REGISTERS_BASE + 0x0998) +#define WL12XX_SPARE_A3 (REGISTERS_BASE + 0x099C) +#define WL12XX_SPARE_A4 (REGISTERS_BASE + 0x09A0) +#define WL12XX_SPARE_A5 (REGISTERS_BASE + 0x09A4) +#define WL12XX_SPARE_A6 (REGISTERS_BASE + 0x09A8) +#define WL12XX_SPARE_A7 (REGISTERS_BASE + 0x09AC) +#define WL12XX_SPARE_A8 (REGISTERS_BASE + 0x09B0) +#define WL12XX_SPARE_B1 (REGISTERS_BASE + 0x5420) +#define WL12XX_SPARE_B2 (REGISTERS_BASE + 0x5424) +#define WL12XX_SPARE_B3 (REGISTERS_BASE + 0x5428) +#define WL12XX_SPARE_B4 (REGISTERS_BASE + 0x542C) +#define WL12XX_SPARE_B5 (REGISTERS_BASE + 0x5430) +#define WL12XX_SPARE_B6 (REGISTERS_BASE + 0x5434) +#define WL12XX_SPARE_B7 (REGISTERS_BASE + 0x5438) +#define WL12XX_SPARE_B8 (REGISTERS_BASE + 0x543C) + +#define WL12XX_PLL_PARAMETERS (REGISTERS_BASE + 0x6040) +#define WL12XX_WU_COUNTER_PAUSE (REGISTERS_BASE + 0x6008) +#define WL12XX_WELP_ARM_COMMAND (REGISTERS_BASE + 0x6100) +#define WL12XX_DRPW_SCRATCH_START (DRPW_BASE + 0x002C) + +#define WL12XX_CMD_MBOX_ADDRESS 0x407B4 + +#define ACX_REG_EEPROM_START_BIT BIT(1) + +/* Command/Information Mailbox Pointers */ + +/*=============================================== + Command Mailbox Pointer - 32bit RW + ------------------------------------------ + This register holds the start address of + the command mailbox located in the Wlan hardware memory. + The host must read this pointer after a reset to + find the location of the command mailbox. + The Wlan hardware initializes the command mailbox + pointer with the default address of the command mailbox. + The command mailbox pointer is not valid until after + the host receives the Init Complete interrupt from + the Wlan hardware. + ===============================================*/ +#define WL12XX_REG_COMMAND_MAILBOX_PTR (WL12XX_SCR_PAD0) + +/*=============================================== + Information Mailbox Pointer - 32bit RW + ------------------------------------------ + This register holds the start address of + the information mailbox located in the Wlan hardware memory. + The host must read this pointer after a reset to find + the location of the information mailbox. + The Wlan hardware initializes the information mailbox pointer + with the default address of the information mailbox. + The information mailbox pointer is not valid + until after the host receives the Init Complete interrupt from + the Wlan hardware. + ===============================================*/ +#define WL12XX_REG_EVENT_MAILBOX_PTR (WL12XX_SCR_PAD1) + +/*=============================================== + EEPROM Read/Write Request 32bit RW + ------------------------------------------ + 1 EE_READ - EEPROM Read Request 1 - Setting this bit + loads a single byte of data into the EE_DATA + register from the EEPROM location specified in + the EE_ADDR register. + The Wlan hardware hardware clears this bit automatically. + EE_DATA is valid when this bit is cleared. + + 0 EE_WRITE - EEPROM Write Request - Setting this bit + writes a single byte of data from the EE_DATA register into the + EEPROM location specified in the EE_ADDR register. + The Wlan hardware hardware clears this bit automatically. +*===============================================*/ +#define ACX_EE_CTL_REG EE_CTL +#define EE_WRITE 0x00000001ul +#define EE_READ 0x00000002ul + +/*=============================================== + EEPROM Address - 32bit RW + ------------------------------------------ + This register specifies the address + within the EEPROM from/to which to read/write data. + ===============================================*/ +#define ACX_EE_ADDR_REG EE_ADDR + +/*=============================================== + EEPROM Data - 32bit RW + ------------------------------------------ + This register either holds the read 8 bits of + data from the EEPROM or the write data + to be written to the EEPROM. + ===============================================*/ +#define ACX_EE_DATA_REG EE_DATA + +/*=============================================== + EEPROM Base Address - 32bit RW + ------------------------------------------ + This register holds the upper nine bits + [23:15] of the 24-bit Wlan hardware memory + address for burst reads from EEPROM accesses. + The EEPROM provides the lower 15 bits of this address. + The MSB of the address from the EEPROM is ignored. + ===============================================*/ +#define ACX_EE_CFG EE_CFG + +/*=============================================== + GPIO Output Values -32bit, RW + ------------------------------------------ + [31:16] Reserved + [15: 0] Specify the output values (at the output driver inputs) for + GPIO[15:0], respectively. + ===============================================*/ +#define ACX_GPIO_OUT_REG GPIO_OUT +#define ACX_MAX_GPIO_LINES 15 + +/*=============================================== + Contention window -32bit, RW + ------------------------------------------ + [31:26] Reserved + [25:16] Max (0x3ff) + [15:07] Reserved + [06:00] Current contention window value - default is 0x1F + ===============================================*/ +#define ACX_CONT_WIND_CFG_REG CONT_WIND_CFG +#define ACX_CONT_WIND_MIN_MASK 0x0000007f +#define ACX_CONT_WIND_MAX 0x03ff0000 + +#define REF_FREQ_19_2 0 +#define REF_FREQ_26_0 1 +#define REF_FREQ_38_4 2 +#define REF_FREQ_40_0 3 +#define REF_FREQ_33_6 4 +#define REF_FREQ_NUM 5 + +#define LUT_PARAM_INTEGER_DIVIDER 0 +#define LUT_PARAM_FRACTIONAL_DIVIDER 1 +#define LUT_PARAM_ATTN_BB 2 +#define LUT_PARAM_ALPHA_BB 3 +#define LUT_PARAM_STOP_TIME_BB 4 +#define LUT_PARAM_BB_PLL_LOOP_FILTER 5 +#define LUT_PARAM_NUM 6 + +#define WL12XX_EEPROMLESS_IND (WL12XX_SCR_PAD4) +#define USE_EEPROM 0 +#define NVS_DATA_BUNDARY_ALIGNMENT 4 + +/* Firmware image header size */ +#define FW_HDR_SIZE 8 + +/****************************************************************************** + + CHANNELS, BAND & REG DOMAINS definitions + +******************************************************************************/ + +#define SHORT_PREAMBLE_BIT BIT(0) /* CCK or Barker depending on the rate */ +#define OFDM_RATE_BIT BIT(6) +#define PBCC_RATE_BIT BIT(7) + +enum { + CCK_LONG = 0, + CCK_SHORT = SHORT_PREAMBLE_BIT, + PBCC_LONG = PBCC_RATE_BIT, + PBCC_SHORT = PBCC_RATE_BIT | SHORT_PREAMBLE_BIT, + OFDM = OFDM_RATE_BIT +}; + +/****************************************************************************** + +Transmit-Descriptor RATE-SET field definitions... + +Define a new "Rate-Set" for TX path that incorporates the +Rate & Modulation info into a single 16-bit field. + +TxdRateSet_t: +b15 - Indicates Preamble type (1=SHORT, 0=LONG). + Notes: + Must be LONG (0) for 1Mbps rate. + Does not apply (set to 0) for RevG-OFDM rates. +b14 - Indicates PBCC encoding (1=PBCC, 0=not). + Notes: + Does not apply (set to 0) for rates 1 and 2 Mbps. + Does not apply (set to 0) for RevG-OFDM rates. +b13 - Unused (set to 0). +b12-b0 - Supported Rate indicator bits as defined below. + +******************************************************************************/ + +#define OCP_CMD_LOOP 32 +#define OCP_CMD_WRITE 0x1 +#define OCP_CMD_READ 0x2 +#define OCP_READY_MASK BIT(18) +#define OCP_STATUS_MASK (BIT(16) | BIT(17)) +#define OCP_STATUS_NO_RESP 0x00000 +#define OCP_STATUS_OK 0x10000 +#define OCP_STATUS_REQ_FAILED 0x20000 +#define OCP_STATUS_RESP_ERROR 0x30000 + +#define OCP_REG_POLARITY 0x0064 +#define OCP_REG_CLK_TYPE 0x0448 +#define OCP_REG_CLK_POLARITY 0x0cb2 +#define OCP_REG_CLK_PULL 0x0cb4 + +#define WL127X_REG_FUSE_DATA_2_1 0x050a +#define WL128X_REG_FUSE_DATA_2_1 0x2152 +#define PG_VER_MASK 0x3c +#define PG_VER_OFFSET 2 + +#define PG_MAJOR_VER_MASK 0x3 +#define PG_MAJOR_VER_OFFSET 0x0 +#define PG_MINOR_VER_MASK 0xc +#define PG_MINOR_VER_OFFSET 0x2 + +#define POLARITY_LOW BIT(1) +#define NO_PULL (BIT(14) | BIT(15)) + +#define FREF_CLK_TYPE_BITS 0xfffffe7f +#define CLK_REQ_PRCM 0x100 +#define FREF_CLK_POLARITY_BITS 0xfffff8ff +#define CLK_REQ_OUTN_SEL 0x700 + +#define WU_COUNTER_PAUSE_VAL 0x3FF +#define WELP_ARM_COMMAND_VAL 0x4 + +/* PLL configuration algorithm for wl128x */ +#define SYS_CLK_CFG_REG 0x2200 +/* Bit[0] - 0-TCXO, 1-FREF */ +#define MCS_PLL_CLK_SEL_FREF BIT(0) +/* Bit[3:2] - 01-TCXO, 10-FREF */ +#define WL_CLK_REQ_TYPE_FREF BIT(3) +#define WL_CLK_REQ_TYPE_PG2 (BIT(3) | BIT(2)) +/* Bit[4] - 0-TCXO, 1-FREF */ +#define PRCM_CM_EN_MUX_WLAN_FREF BIT(4) + +#define TCXO_ILOAD_INT_REG 0x2264 +#define TCXO_CLK_DETECT_REG 0x2266 + +#define TCXO_DET_FAILED BIT(4) + +#define FREF_ILOAD_INT_REG 0x2084 +#define FREF_CLK_DETECT_REG 0x2086 +#define FREF_CLK_DETECT_FAIL BIT(4) + +/* Use this reg for masking during driver access */ +#define WL_SPARE_REG 0x2320 +#define WL_SPARE_VAL BIT(2) +/* Bit[6:5:3] - mask wl write SYS_CLK_CFG[8:5:2:4] */ +#define WL_SPARE_MASK_8526 (BIT(6) | BIT(5) | BIT(3)) + +#define PLL_LOCK_COUNTERS_REG 0xD8C +#define PLL_LOCK_COUNTERS_COEX 0x0F +#define PLL_LOCK_COUNTERS_MCS 0xF0 +#define MCS_PLL_OVERRIDE_REG 0xD90 +#define MCS_PLL_CONFIG_REG 0xD92 +#define MCS_SEL_IN_FREQ_MASK 0x0070 +#define MCS_SEL_IN_FREQ_SHIFT 4 +#define MCS_PLL_CONFIG_REG_VAL 0x73 +#define MCS_PLL_ENABLE_HP (BIT(0) | BIT(1)) + +#define MCS_PLL_M_REG 0xD94 +#define MCS_PLL_N_REG 0xD96 +#define MCS_PLL_M_REG_VAL 0xC8 +#define MCS_PLL_N_REG_VAL 0x07 + +#define SDIO_IO_DS 0xd14 + +/* SDIO/wSPI DS configuration values */ +enum { + HCI_IO_DS_8MA = 0, + HCI_IO_DS_4MA = 1, /* default */ + HCI_IO_DS_6MA = 2, + HCI_IO_DS_2MA = 3, +}; + +/* end PLL configuration algorithm for wl128x */ + +/*=============================================== + HI_CFG Interface Configuration Register Values + ------------------------------------------ + ===============================================*/ +#define HI_CFG_UART_ENABLE 0x00000004 +#define HI_CFG_RST232_ENABLE 0x00000008 +#define HI_CFG_CLOCK_REQ_SELECT 0x00000010 +#define HI_CFG_HOST_INT_ENABLE 0x00000020 +#define HI_CFG_VLYNQ_OUTPUT_ENABLE 0x00000040 +#define HI_CFG_HOST_INT_ACTIVE_LOW 0x00000080 +#define HI_CFG_UART_TX_OUT_GPIO_15 0x00000100 +#define HI_CFG_UART_TX_OUT_GPIO_14 0x00000200 +#define HI_CFG_UART_TX_OUT_GPIO_7 0x00000400 + +#define HI_CFG_DEF_VAL \ + (HI_CFG_UART_ENABLE | \ + HI_CFG_RST232_ENABLE | \ + HI_CFG_CLOCK_REQ_SELECT | \ + HI_CFG_HOST_INT_ENABLE) + +#define WL127X_REG_FUSE_DATA_2_1 0x050a +#define WL128X_REG_FUSE_DATA_2_1 0x2152 +#define PG_VER_MASK 0x3c +#define PG_VER_OFFSET 2 + +#define WL127X_PG_MAJOR_VER_MASK 0x3 +#define WL127X_PG_MAJOR_VER_OFFSET 0x0 +#define WL127X_PG_MINOR_VER_MASK 0xc +#define WL127X_PG_MINOR_VER_OFFSET 0x2 + +#define WL128X_PG_MAJOR_VER_MASK 0xc +#define WL128X_PG_MAJOR_VER_OFFSET 0x2 +#define WL128X_PG_MINOR_VER_MASK 0x3 +#define WL128X_PG_MINOR_VER_OFFSET 0x0 + +#define WL127X_PG_GET_MAJOR(pg_ver) ((pg_ver & WL127X_PG_MAJOR_VER_MASK) >> \ + WL127X_PG_MAJOR_VER_OFFSET) +#define WL127X_PG_GET_MINOR(pg_ver) ((pg_ver & WL127X_PG_MINOR_VER_MASK) >> \ + WL127X_PG_MINOR_VER_OFFSET) +#define WL128X_PG_GET_MAJOR(pg_ver) ((pg_ver & WL128X_PG_MAJOR_VER_MASK) >> \ + WL128X_PG_MAJOR_VER_OFFSET) +#define WL128X_PG_GET_MINOR(pg_ver) ((pg_ver & WL128X_PG_MINOR_VER_MASK) >> \ + WL128X_PG_MINOR_VER_OFFSET) + +#define WL12XX_REG_FUSE_BD_ADDR_1 0x00310eb4 +#define WL12XX_REG_FUSE_BD_ADDR_2 0x00310eb8 + +#endif diff --git a/drivers/net/wireless/ti/wlcore/acx.c b/drivers/net/wireless/ti/wlcore/acx.c index 43cc6a2dae1..cba8af2a398 100644 --- a/drivers/net/wireless/ti/wlcore/acx.c +++ b/drivers/net/wireless/ti/wlcore/acx.c @@ -31,7 +31,6 @@ #include "wlcore.h" #include "debug.h" #include "wl12xx_80211.h" -#include "reg.h" #include "ps.h" int wl1271_acx_wake_up_conditions(struct wl1271 *wl, struct wl12xx_vif *wlvif, diff --git a/drivers/net/wireless/ti/wlcore/boot.c b/drivers/net/wireless/ti/wlcore/boot.c index da37c59552b..69409ecfb0b 100644 --- a/drivers/net/wireless/ti/wlcore/boot.c +++ b/drivers/net/wireless/ti/wlcore/boot.c @@ -27,22 +27,27 @@ #include "debug.h" #include "acx.h" -#include "reg.h" #include "boot.h" #include "io.h" #include "event.h" #include "rx.h" +/* + * TODO: this is here just for now, it will be removed when we move + * the top_reg stuff to wl12xx + */ +#include "../wl12xx/reg.h" + static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag) { u32 cpu_ctrl; /* 10.5.0 run the firmware (I) */ - cpu_ctrl = wl1271_read32(wl, ACX_REG_ECPU_CONTROL); + cpu_ctrl = wlcore_read_reg(wl, REG_ECPU_CONTROL); /* 10.5.1 run the firmware (II) */ cpu_ctrl |= flag; - wl1271_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl); + wlcore_write_reg(wl, REG_ECPU_CONTROL, cpu_ctrl); } static unsigned int wl12xx_get_fw_ver_quirks(struct wl1271 *wl) @@ -289,9 +294,10 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) /* * Due to our new wl1271_translate_reg_addr function, - * we need to add the REGISTER_BASE to the destination + * we need to add the register partition start address + * to the destination */ - dest_addr += REGISTERS_BASE; + dest_addr += wl->curr_part.reg.start; /* We move our pointer to the data */ nvs_ptr += 3; @@ -340,7 +346,8 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) return -ENOMEM; /* And finally we upload the NVS tables */ - wl1271_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, false); + wlcore_write_data(wl, REG_CMD_MBOX_ADDRESS, + nvs_aligned, nvs_len, false); kfree(nvs_aligned); return 0; @@ -353,9 +360,9 @@ out_badnvs: static void wl1271_boot_enable_interrupts(struct wl1271 *wl) { wl1271_enable_interrupts(wl); - wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, - WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); - wl1271_write32(wl, HI_CFG, HI_CFG_DEF_VAL); + wlcore_write_reg(wl, REG_INTERRUPT_MASK, + WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); + wl1271_write32(wl, WL12XX_HI_CFG, HI_CFG_DEF_VAL); } static int wl1271_boot_soft_reset(struct wl1271 *wl) @@ -364,12 +371,12 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl) u32 boot_data; /* perform soft reset */ - wl1271_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT); + wl1271_write32(wl, WL12XX_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT); /* SOFT_RESET is self clearing */ timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME); while (1) { - boot_data = wl1271_read32(wl, ACX_REG_SLV_SOFT_RESET); + boot_data = wl1271_read32(wl, WL12XX_SLV_SOFT_RESET); wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data); if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0) break; @@ -385,10 +392,10 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl) } /* disable Rx/Tx */ - wl1271_write32(wl, ENABLE, 0x0); + wl1271_write32(wl, WL12XX_ENABLE, 0x0); /* disable auto calibration on start*/ - wl1271_write32(wl, SPARE_A2, 0xffff); + wl1271_write32(wl, WL12XX_SPARE_A2, 0xffff); return 0; } @@ -400,7 +407,7 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); - chip_id = wl1271_read32(wl, CHIP_ID_B); + chip_id = wlcore_read_reg(wl, REG_CHIP_ID_B); wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id); @@ -413,7 +420,7 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) loop = 0; while (loop++ < INIT_LOOP) { udelay(INIT_LOOP_DELAY); - intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); + intr = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR); if (intr == 0xffffffff) { wl1271_error("error reading hardware complete " @@ -422,8 +429,8 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) } /* check that ACX_INTR_INIT_COMPLETE is enabled */ else if (intr & WL1271_ACX_INTR_INIT_COMPLETE) { - wl1271_write32(wl, ACX_REG_INTERRUPT_ACK, - WL1271_ACX_INTR_INIT_COMPLETE); + wlcore_write_reg(wl, REG_INTERRUPT_ACK, + WL1271_ACX_INTR_INIT_COMPLETE); break; } } @@ -435,10 +442,10 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) } /* get hardware config command mail box */ - wl->cmd_box_addr = wl1271_read32(wl, REG_COMMAND_MAILBOX_PTR); + wl->cmd_box_addr = wlcore_read_reg(wl, REG_COMMAND_MAILBOX_PTR); /* get hardware config event mail box */ - wl->event_box_addr = wl1271_read32(wl, REG_EVENT_MAILBOX_PTR); + wl->event_box_addr = wlcore_read_reg(wl, REG_EVENT_MAILBOX_PTR); /* set the working partition to its "running" mode offset */ wlcore_set_partition(wl, &wl->ptable[PART_WORK]); @@ -668,15 +675,15 @@ static int wl127x_boot_clk(struct wl1271 *wl) wl1271_top_reg_write(wl, OCP_REG_CLK_POLARITY, val); } - wl1271_write32(wl, PLL_PARAMETERS, clk); + wl1271_write32(wl, WL12XX_PLL_PARAMETERS, clk); - pause = wl1271_read32(wl, PLL_PARAMETERS); + pause = wl1271_read32(wl, WL12XX_PLL_PARAMETERS); wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause); pause &= ~(WU_COUNTER_PAUSE_VAL); pause |= WU_COUNTER_PAUSE_VAL; - wl1271_write32(wl, WU_COUNTER_PAUSE, pause); + wl1271_write32(wl, WL12XX_WU_COUNTER_PAUSE, pause); return 0; } @@ -699,7 +706,7 @@ int wl1271_load_firmware(struct wl1271 *wl) } /* Continue the ELP wake up sequence */ - wl1271_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); + wl1271_write32(wl, WL12XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); udelay(500); wlcore_set_partition(wl, &wl->ptable[PART_DRPW]); @@ -708,8 +715,7 @@ int wl1271_load_firmware(struct wl1271 *wl) to be used by DRPw FW. The RTRIM value will be added by the FW before taking DRPw out of reset */ - wl1271_debug(DEBUG_BOOT, "DRPW_SCRATCH_START %08x", DRPW_SCRATCH_START); - clk = wl1271_read32(wl, DRPW_SCRATCH_START); + clk = wl1271_read32(wl, WL12XX_DRPW_SCRATCH_START); wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); @@ -719,12 +725,12 @@ int wl1271_load_firmware(struct wl1271 *wl) clk |= (wl->ref_clock << 1) << 4; } - wl1271_write32(wl, DRPW_SCRATCH_START, clk); + wl1271_write32(wl, WL12XX_DRPW_SCRATCH_START, clk); wlcore_set_partition(wl, &wl->ptable[PART_WORK]); /* Disable interrupts */ - wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); + wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); ret = wl1271_boot_soft_reset(wl); if (ret < 0) @@ -739,20 +745,20 @@ int wl1271_load_firmware(struct wl1271 *wl) * ACX_EEPROMLESS_IND_REG */ wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG"); - wl1271_write32(wl, ACX_EEPROMLESS_IND_REG, ACX_EEPROMLESS_IND_REG); + wl1271_write32(wl, WL12XX_EEPROMLESS_IND, WL12XX_EEPROMLESS_IND); - tmp = wl1271_read32(wl, CHIP_ID_B); + tmp = wlcore_read_reg(wl, REG_CHIP_ID_B); wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); /* 6. read the EEPROM parameters */ - tmp = wl1271_read32(wl, SCR_PAD2); + tmp = wl1271_read32(wl, WL12XX_SCR_PAD2); /* WL1271: The reference driver skips steps 7 to 10 (jumps directly * to upload_fw) */ if (wl->chip.id == CHIP_ID_1283_PG20) - wl1271_top_reg_write(wl, SDIO_IO_DS, wl->conf.hci_io_ds); + wl1271_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA); ret = wl1271_boot_upload_firmware(wl); if (ret < 0) @@ -781,8 +787,7 @@ int wl1271_boot(struct wl1271 *wl) if (ret < 0) goto out; - wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, - WL1271_ACX_ALL_EVENTS_VECTOR); + wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_ALL_EVENTS_VECTOR); /* Enable firmware interrupts now */ wl1271_boot_enable_interrupts(wl); diff --git a/drivers/net/wireless/ti/wlcore/boot.h b/drivers/net/wireless/ti/wlcore/boot.h index a39e0e2a0c2..842ae3fdd87 100644 --- a/drivers/net/wireless/ti/wlcore/boot.h +++ b/drivers/net/wireless/ti/wlcore/boot.h @@ -50,71 +50,4 @@ struct wl1271_static_data { #define WU_COUNTER_PAUSE_VAL 0x3FF #define WELP_ARM_COMMAND_VAL 0x4 -#define OCP_REG_POLARITY 0x0064 -#define OCP_REG_CLK_TYPE 0x0448 -#define OCP_REG_CLK_POLARITY 0x0cb2 -#define OCP_REG_CLK_PULL 0x0cb4 - -#define CMD_MBOX_ADDRESS 0x407B4 - -#define POLARITY_LOW BIT(1) -#define NO_PULL (BIT(14) | BIT(15)) - -#define FREF_CLK_TYPE_BITS 0xfffffe7f -#define CLK_REQ_PRCM 0x100 -#define FREF_CLK_POLARITY_BITS 0xfffff8ff -#define CLK_REQ_OUTN_SEL 0x700 - -/* PLL configuration algorithm for wl128x */ -#define SYS_CLK_CFG_REG 0x2200 -/* Bit[0] - 0-TCXO, 1-FREF */ -#define MCS_PLL_CLK_SEL_FREF BIT(0) -/* Bit[3:2] - 01-TCXO, 10-FREF */ -#define WL_CLK_REQ_TYPE_FREF BIT(3) -#define WL_CLK_REQ_TYPE_PG2 (BIT(3) | BIT(2)) -/* Bit[4] - 0-TCXO, 1-FREF */ -#define PRCM_CM_EN_MUX_WLAN_FREF BIT(4) - -#define TCXO_ILOAD_INT_REG 0x2264 -#define TCXO_CLK_DETECT_REG 0x2266 - -#define TCXO_DET_FAILED BIT(4) - -#define FREF_ILOAD_INT_REG 0x2084 -#define FREF_CLK_DETECT_REG 0x2086 -#define FREF_CLK_DETECT_FAIL BIT(4) - -/* Use this reg for masking during driver access */ -#define WL_SPARE_REG 0x2320 -#define WL_SPARE_VAL BIT(2) -/* Bit[6:5:3] - mask wl write SYS_CLK_CFG[8:5:2:4] */ -#define WL_SPARE_MASK_8526 (BIT(6) | BIT(5) | BIT(3)) - -#define PLL_LOCK_COUNTERS_REG 0xD8C -#define PLL_LOCK_COUNTERS_COEX 0x0F -#define PLL_LOCK_COUNTERS_MCS 0xF0 -#define MCS_PLL_OVERRIDE_REG 0xD90 -#define MCS_PLL_CONFIG_REG 0xD92 -#define MCS_SEL_IN_FREQ_MASK 0x0070 -#define MCS_SEL_IN_FREQ_SHIFT 4 -#define MCS_PLL_CONFIG_REG_VAL 0x73 -#define MCS_PLL_ENABLE_HP (BIT(0) | BIT(1)) - -#define MCS_PLL_M_REG 0xD94 -#define MCS_PLL_N_REG 0xD96 -#define MCS_PLL_M_REG_VAL 0xC8 -#define MCS_PLL_N_REG_VAL 0x07 - -#define SDIO_IO_DS 0xd14 - -/* SDIO/wSPI DS configuration values */ -enum { - HCI_IO_DS_8MA = 0, - HCI_IO_DS_4MA = 1, /* default */ - HCI_IO_DS_6MA = 2, - HCI_IO_DS_2MA = 3, -}; - -/* end PLL configuration algorithm for wl128x */ - #endif diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index 68e686f25af..3ec86e96f5c 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c @@ -30,7 +30,6 @@ #include "wlcore.h" #include "debug.h" -#include "reg.h" #include "io.h" #include "acx.h" #include "wl12xx_80211.h" @@ -67,11 +66,11 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, wl1271_write(wl, wl->cmd_box_addr, buf, len, false); - wl1271_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD); + wlcore_write_reg(wl, REG_INTERRUPT_TRIG, INTR_TRIG_CMD); timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT); - intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); + intr = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR); while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) { if (time_after(jiffies, timeout)) { wl1271_error("command complete timeout"); @@ -85,7 +84,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, else msleep(1); - intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); + intr = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR); } /* read back the status code of the command */ @@ -100,8 +99,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, goto fail; } - wl1271_write32(wl, ACX_REG_INTERRUPT_ACK, - WL1271_ACX_INTR_CMD_COMPLETE); + wlcore_write_reg(wl, REG_INTERRUPT_ACK, WL1271_ACX_INTR_CMD_COMPLETE); return 0; fail: @@ -529,7 +527,7 @@ static int wl12xx_cmd_role_start_dev(struct wl1271 *wl, cmd->role_id = wlvif->dev_role_id; if (wlvif->band == IEEE80211_BAND_5GHZ) - cmd->band = WL12XX_BAND_5GHZ; + cmd->band = WLCORE_BAND_5GHZ; cmd->channel = wlvif->channel; if (wlvif->dev_hlid == WL12XX_INVALID_LINK_ID) { @@ -620,7 +618,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) cmd->role_id = wlvif->role_id; if (wlvif->band == IEEE80211_BAND_5GHZ) - cmd->band = WL12XX_BAND_5GHZ; + cmd->band = WLCORE_BAND_5GHZ; cmd->channel = wlvif->channel; cmd->sta.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set); cmd->sta.beacon_interval = cpu_to_le16(wlvif->beacon_int); @@ -757,14 +755,14 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) switch (wlvif->band) { case IEEE80211_BAND_2GHZ: - cmd->band = RADIO_BAND_2_4GHZ; + cmd->band = WLCORE_BAND_2_4GHZ; break; case IEEE80211_BAND_5GHZ: - cmd->band = RADIO_BAND_5GHZ; + cmd->band = WLCORE_BAND_5GHZ; break; default: wl1271_warning("ap start - unknown band: %d", (int)wlvif->band); - cmd->band = RADIO_BAND_2_4GHZ; + cmd->band = WLCORE_BAND_2_4GHZ; break; } @@ -837,7 +835,7 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif) cmd->role_id = wlvif->role_id; if (wlvif->band == IEEE80211_BAND_5GHZ) - cmd->band = WL12XX_BAND_5GHZ; + cmd->band = WLCORE_BAND_5GHZ; cmd->channel = wlvif->channel; cmd->ibss.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set); cmd->ibss.beacon_interval = cpu_to_le16(wlvif->beacon_int); @@ -1737,10 +1735,10 @@ static int wl12xx_cmd_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, cmd->channel = wlvif->channel; switch (wlvif->band) { case IEEE80211_BAND_2GHZ: - cmd->band = RADIO_BAND_2_4GHZ; + cmd->band = WLCORE_BAND_2_4GHZ; break; case IEEE80211_BAND_5GHZ: - cmd->band = RADIO_BAND_5GHZ; + cmd->band = WLCORE_BAND_5GHZ; break; default: wl1271_error("roc - unknown band: %d", (int)wlvif->band); diff --git a/drivers/net/wireless/ti/wlcore/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h index 58d2a8b5c8d..cd1eb2eef90 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.h +++ b/drivers/net/wireless/ti/wlcore/cmd.h @@ -262,13 +262,13 @@ struct wl12xx_cmd_role_disable { u8 padding[3]; } __packed; -enum wl12xx_band { - WL12XX_BAND_2_4GHZ = 0, - WL12XX_BAND_5GHZ = 1, - WL12XX_BAND_JAPAN_4_9_GHZ = 2, - WL12XX_BAND_DEFAULT = WL12XX_BAND_2_4GHZ, - WL12XX_BAND_INVALID = 0x7E, - WL12XX_BAND_MAX_RADIO = 0x7F, +enum wlcore_band { + WLCORE_BAND_2_4GHZ = 0, + WLCORE_BAND_5GHZ = 1, + WLCORE_BAND_JAPAN_4_9_GHZ = 2, + WLCORE_BAND_DEFAULT = WLCORE_BAND_2_4GHZ, + WLCORE_BAND_INVALID = 0x7E, + WLCORE_BAND_MAX_RADIO = 0x7F, }; struct wl12xx_cmd_role_start { diff --git a/drivers/net/wireless/ti/wlcore/conf.h b/drivers/net/wireless/ti/wlcore/conf.h index 5d2a9e004c7..3bdb1bea2db 100644 --- a/drivers/net/wireless/ti/wlcore/conf.h +++ b/drivers/net/wireless/ti/wlcore/conf.h @@ -1320,7 +1320,6 @@ struct conf_drv_settings { struct conf_fwlog fwlog; struct conf_rate_policy_settings rate; struct conf_hangover_settings hangover; - u8 hci_io_ds; }; #endif diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c index 8d79af964b8..078cb012fcc 100644 --- a/drivers/net/wireless/ti/wlcore/event.c +++ b/drivers/net/wireless/ti/wlcore/event.c @@ -23,7 +23,6 @@ #include "wlcore.h" #include "debug.h" -#include "reg.h" #include "io.h" #include "event.h" #include "ps.h" @@ -281,7 +280,7 @@ int wl1271_event_unmask(struct wl1271 *wl) void wl1271_event_mbox_config(struct wl1271 *wl) { - wl->mbox_ptr[0] = wl1271_read32(wl, REG_EVENT_MAILBOX_PTR); + wl->mbox_ptr[0] = wlcore_read_reg(wl, REG_EVENT_MAILBOX_PTR); wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox); wl1271_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x", @@ -307,7 +306,7 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num) return ret; /* then we let the firmware know it can go on...*/ - wl1271_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK); + wlcore_write_reg(wl, REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK); return 0; } diff --git a/drivers/net/wireless/ti/wlcore/init.c b/drivers/net/wireless/ti/wlcore/init.c index 203fbebf09e..f3b606798f1 100644 --- a/drivers/net/wireless/ti/wlcore/init.c +++ b/drivers/net/wireless/ti/wlcore/init.c @@ -30,7 +30,6 @@ #include "wl12xx_80211.h" #include "acx.h" #include "cmd.h" -#include "reg.h" #include "tx.h" #include "io.h" diff --git a/drivers/net/wireless/ti/wlcore/io.c b/drivers/net/wireless/ti/wlcore/io.c index 65c562c40f8..30c60e3e73f 100644 --- a/drivers/net/wireless/ti/wlcore/io.c +++ b/drivers/net/wireless/ti/wlcore/io.c @@ -32,18 +32,11 @@ #include "io.h" #include "tx.h" -#define OCP_CMD_LOOP 32 - -#define OCP_CMD_WRITE 0x1 -#define OCP_CMD_READ 0x2 - -#define OCP_READY_MASK BIT(18) -#define OCP_STATUS_MASK (BIT(16) | BIT(17)) - -#define OCP_STATUS_NO_RESP 0x00000 -#define OCP_STATUS_OK 0x10000 -#define OCP_STATUS_REQ_FAILED 0x20000 -#define OCP_STATUS_RESP_ERROR 0x30000 +/* + * TODO: this is here just for now, it will be removed when we move + * the top_reg stuff to wl12xx + */ +#include "../wl12xx/reg.h" bool wl1271_set_block_size(struct wl1271 *wl) { @@ -187,13 +180,13 @@ void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val) { /* write address >> 1 + 0x30000 to OCP_POR_CTR */ addr = (addr >> 1) + 0x30000; - wl1271_write32(wl, OCP_POR_CTR, addr); + wl1271_write32(wl, WL12XX_OCP_POR_CTR, addr); /* write value to OCP_POR_WDATA */ - wl1271_write32(wl, OCP_DATA_WRITE, val); + wl1271_write32(wl, WL12XX_OCP_DATA_WRITE, val); /* write 1 to OCP_CMD */ - wl1271_write32(wl, OCP_CMD, OCP_CMD_WRITE); + wl1271_write32(wl, WL12XX_OCP_CMD, OCP_CMD_WRITE); } u16 wl1271_top_reg_read(struct wl1271 *wl, int addr) @@ -203,14 +196,14 @@ u16 wl1271_top_reg_read(struct wl1271 *wl, int addr) /* write address >> 1 + 0x30000 to OCP_POR_CTR */ addr = (addr >> 1) + 0x30000; - wl1271_write32(wl, OCP_POR_CTR, addr); + wl1271_write32(wl, WL12XX_OCP_POR_CTR, addr); /* write 2 to OCP_CMD */ - wl1271_write32(wl, OCP_CMD, OCP_CMD_READ); + wl1271_write32(wl, WL12XX_OCP_CMD, OCP_CMD_READ); /* poll for data ready */ do { - val = wl1271_read32(wl, OCP_DATA_READ); + val = wl1271_read32(wl, WL12XX_OCP_DATA_READ); } while (!(val & OCP_READY_MASK) && --timeout); if (!timeout) { diff --git a/drivers/net/wireless/ti/wlcore/io.h b/drivers/net/wireless/ti/wlcore/io.h index 495ab335b46..c5ca3c83631 100644 --- a/drivers/net/wireless/ti/wlcore/io.h +++ b/drivers/net/wireless/ti/wlcore/io.h @@ -26,7 +26,6 @@ #define __IO_H__ #include -#include "reg.h" #define HW_ACCESS_MEMORY_MAX_RANGE 0x1FFC0 @@ -65,6 +64,18 @@ static inline void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf, wl->if_ops->read(wl->dev, addr, buf, len, fixed); } +static inline void wlcore_raw_read_data(struct wl1271 *wl, int reg, void *buf, + size_t len, bool fixed) +{ + wl1271_raw_read(wl, wl->rtable[reg], buf, len, fixed); +} + +static inline void wlcore_raw_write_data(struct wl1271 *wl, int reg, void *buf, + size_t len, bool fixed) +{ + wl1271_raw_write(wl, wl->rtable[reg], buf, len, fixed); +} + static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr) { wl1271_raw_read(wl, addr, &wl->buffer_32, @@ -100,6 +111,18 @@ static inline void wl1271_write(struct wl1271 *wl, int addr, void *buf, wl1271_raw_write(wl, physical, buf, len, fixed); } +static inline void wlcore_write_data(struct wl1271 *wl, int reg, void *buf, + size_t len, bool fixed) +{ + wl1271_write(wl, wl->rtable[reg], buf, len, fixed); +} + +static inline void wlcore_read_data(struct wl1271 *wl, int reg, void *buf, + size_t len, bool fixed) +{ + wl1271_read(wl, wl->rtable[reg], buf, len, fixed); +} + static inline void wl1271_read_hwaddr(struct wl1271 *wl, int hwaddr, void *buf, size_t len, bool fixed) { @@ -124,6 +147,17 @@ static inline void wl1271_write32(struct wl1271 *wl, int addr, u32 val) wl1271_raw_write32(wl, wlcore_translate_addr(wl, addr), val); } +static inline u32 wlcore_read_reg(struct wl1271 *wl, int reg) +{ + return wl1271_raw_read32(wl, + wlcore_translate_addr(wl, wl->rtable[reg])); +} + +static inline void wlcore_write_reg(struct wl1271 *wl, int reg, u32 val) +{ + wl1271_raw_write32(wl, wlcore_translate_addr(wl, wl->rtable[reg]), val); +} + static inline void wl1271_power_off(struct wl1271 *wl) { wl->if_ops->power(wl->dev, false); diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 30d47b239ab..d3fde0ac03c 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -38,7 +38,6 @@ #include "wlcore.h" #include "debug.h" #include "wl12xx_80211.h" -#include "reg.h" #include "io.h" #include "event.h" #include "tx.h" @@ -51,6 +50,9 @@ #include "testmode.h" #include "scan.h" +/* TODO: remove this once the FUSE definitions are separated */ +#include "../wl12xx/reg.h" + #define WL1271_BOOT_RETRIES 3 static struct conf_drv_settings default_conf = { @@ -354,7 +356,6 @@ static struct conf_drv_settings default_conf = { .output = WL12XX_FWLOG_OUTPUT_HOST, .threshold = 0, }, - .hci_io_ds = HCI_IO_DS_6MA, .rate = { .rate_retry_score = 32000, .per_add = 8192, @@ -796,7 +797,8 @@ static void wl12xx_fw_status(struct wl1271 *wl, int avail, freed_blocks; int i; - wl1271_raw_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false); + wlcore_raw_read_data(wl, REG_RAW_FW_STATUS_ADDR, status, + sizeof(*status), false); wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " "drv_rx_counter = %d, tx_results_counter = %d)", @@ -1246,7 +1248,8 @@ static void wl1271_recovery_work(struct work_struct *work) wl12xx_read_fwlog_panic(wl); wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x", - wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4)); + wl->chip.fw_ver_str, + wlcore_read_reg(wl, REG_PC_ON_RECOVERY)); BUG_ON(bug_on_recovery && !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)); @@ -1297,10 +1300,7 @@ out_unlock: static void wl1271_fw_wakeup(struct wl1271 *wl) { - u32 elp_reg; - - elp_reg = ELPCTRL_WAKE_UP; - wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg); + wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP); } static int wl1271_setup(struct wl1271 *wl) @@ -1330,7 +1330,7 @@ static int wl12xx_set_power_on(struct wl1271 *wl) wl1271_io_reset(wl); wl1271_io_init(wl); - wlcore_set_partition(wl, &wl->ptable[PART_DOWN]); + wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); /* ELP module wake up */ wl1271_fw_wakeup(wl); @@ -5107,22 +5107,25 @@ static int wl12xx_get_hw_info(struct wl1271 *wl) if (ret < 0) goto out; - wl->chip.id = wl1271_read32(wl, CHIP_ID_B); + wl->chip.id = wlcore_read_reg(wl, REG_CHIP_ID_B); + + wl->fuse_oui_addr = 0; + wl->fuse_nic_addr = 0; + /* TODO: properly detect PG ver and read MAC addr in other families */ if (wl->chip.id == CHIP_ID_1283_PG20) die_info = wl1271_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1); - else + else if (wl->chip.id < CHIP_ID_1283_PG20) die_info = wl1271_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1); + else + goto skip_mac; wl->hw_pg_ver = (s8) (die_info & PG_VER_MASK) >> PG_VER_OFFSET; - if (!wl12xx_mac_in_fuse(wl)) { - wl->fuse_oui_addr = 0; - wl->fuse_nic_addr = 0; - } else { + if (wl12xx_mac_in_fuse(wl)) wl12xx_get_fuse_mac(wl); - } +skip_mac: wl1271_power_off(wl); out: return ret; diff --git a/drivers/net/wireless/ti/wlcore/ps.c b/drivers/net/wireless/ti/wlcore/ps.c index 78f598b4f97..cfeb114843e 100644 --- a/drivers/net/wireless/ti/wlcore/ps.c +++ b/drivers/net/wireless/ti/wlcore/ps.c @@ -21,7 +21,6 @@ * */ -#include "reg.h" #include "ps.h" #include "io.h" #include "tx.h" @@ -62,7 +61,7 @@ void wl1271_elp_work(struct work_struct *work) } wl1271_debug(DEBUG_PSM, "chip to elp"); - wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); + wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_SLEEP); set_bit(WL1271_FLAG_IN_ELP, &wl->flags); out: @@ -125,7 +124,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl) wl->elp_compl = &compl; spin_unlock_irqrestore(&wl->wl_lock, flags); - wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP); + wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP); if (!pending) { ret = wait_for_completion_timeout( diff --git a/drivers/net/wireless/ti/wlcore/reg.h b/drivers/net/wireless/ti/wlcore/reg.h deleted file mode 100644 index 340db324bc2..00000000000 --- a/drivers/net/wireless/ti/wlcore/reg.h +++ /dev/null @@ -1,555 +0,0 @@ -/* - * This file is part of wl12xx - * - * Copyright (C) 1998-2009 Texas Instruments. All rights reserved. - * Copyright (C) 2009 Nokia Corporation - * - * Contact: Luciano Coelho - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __REG_H__ -#define __REG_H__ - -#include - -#define REGISTERS_BASE 0x00300000 -#define DRPW_BASE 0x00310000 - -#define REGISTERS_DOWN_SIZE 0x00008800 -#define REGISTERS_WORK_SIZE 0x0000b000 - -#define HW_ACCESS_ELP_CTRL_REG_ADDR 0x1FFFC -#define FW_STATUS_ADDR (0x14FC0 + 0xA000) - -/* ELP register commands */ -#define ELPCTRL_WAKE_UP 0x1 -#define ELPCTRL_WAKE_UP_WLAN_READY 0x5 -#define ELPCTRL_SLEEP 0x0 -/* ELP WLAN_READY bit */ -#define ELPCTRL_WLAN_READY 0x2 - -/*=============================================== - Host Software Reset - 32bit RW - ------------------------------------------ - [31:1] Reserved - 0 SOFT_RESET Soft Reset - When this bit is set, - it holds the Wlan hardware in a soft reset state. - This reset disables all MAC and baseband processor - clocks except the CardBus/PCI interface clock. - It also initializes all MAC state machines except - the host interface. It does not reload the - contents of the EEPROM. When this bit is cleared - (not self-clearing), the Wlan hardware - exits the software reset state. -===============================================*/ -#define ACX_REG_SLV_SOFT_RESET (REGISTERS_BASE + 0x0000) - -#define WL1271_SLV_REG_DATA (REGISTERS_BASE + 0x0008) -#define WL1271_SLV_REG_ADATA (REGISTERS_BASE + 0x000c) -#define WL1271_SLV_MEM_DATA (REGISTERS_BASE + 0x0018) - -#define ACX_REG_INTERRUPT_TRIG (REGISTERS_BASE + 0x0474) -#define ACX_REG_INTERRUPT_TRIG_H (REGISTERS_BASE + 0x0478) - -/*============================================= - Host Interrupt Mask Register - 32bit (RW) - ------------------------------------------ - Setting a bit in this register masks the - corresponding interrupt to the host. - 0 - RX0 - Rx first dubble buffer Data Interrupt - 1 - TXD - Tx Data Interrupt - 2 - TXXFR - Tx Transfer Interrupt - 3 - RX1 - Rx second dubble buffer Data Interrupt - 4 - RXXFR - Rx Transfer Interrupt - 5 - EVENT_A - Event Mailbox interrupt - 6 - EVENT_B - Event Mailbox interrupt - 7 - WNONHST - Wake On Host Interrupt - 8 - TRACE_A - Debug Trace interrupt - 9 - TRACE_B - Debug Trace interrupt - 10 - CDCMP - Command Complete Interrupt - 11 - - 12 - - 13 - - 14 - ICOMP - Initialization Complete Interrupt - 16 - SG SE - Soft Gemini - Sense enable interrupt - 17 - SG SD - Soft Gemini - Sense disable interrupt - 18 - - - 19 - - - 20 - - - 21- - - Default: 0x0001 -*==============================================*/ -#define ACX_REG_INTERRUPT_MASK (REGISTERS_BASE + 0x04DC) - -/*============================================= - Host Interrupt Mask Set 16bit, (Write only) - ------------------------------------------ - Setting a bit in this register sets - the corresponding bin in ACX_HINT_MASK register - without effecting the mask - state of other bits (0 = no effect). -==============================================*/ -#define ACX_REG_HINT_MASK_SET (REGISTERS_BASE + 0x04E0) - -/*============================================= - Host Interrupt Mask Clear 16bit,(Write only) - ------------------------------------------ - Setting a bit in this register clears - the corresponding bin in ACX_HINT_MASK register - without effecting the mask - state of other bits (0 = no effect). -=============================================*/ -#define ACX_REG_HINT_MASK_CLR (REGISTERS_BASE + 0x04E4) - -/*============================================= - Host Interrupt Status Nondestructive Read - 16bit,(Read only) - ------------------------------------------ - The host can read this register to determine - which interrupts are active. - Reading this register doesn't - effect its content. -=============================================*/ -#define ACX_REG_INTERRUPT_NO_CLEAR (REGISTERS_BASE + 0x04E8) - -/*============================================= - Host Interrupt Status Clear on Read Register - 16bit,(Read only) - ------------------------------------------ - The host can read this register to determine - which interrupts are active. - Reading this register clears it, - thus making all interrupts inactive. -==============================================*/ -#define ACX_REG_INTERRUPT_CLEAR (REGISTERS_BASE + 0x04F8) - -/*============================================= - Host Interrupt Acknowledge Register - 16bit,(Write only) - ------------------------------------------ - The host can set individual bits in this - register to clear (acknowledge) the corresp. - interrupt status bits in the HINT_STS_CLR and - HINT_STS_ND registers, thus making the - assotiated interrupt inactive. (0-no effect) -==============================================*/ -#define ACX_REG_INTERRUPT_ACK (REGISTERS_BASE + 0x04F0) - -#define RX_DRIVER_COUNTER_ADDRESS (REGISTERS_BASE + 0x0538) - -/* Device Configuration registers*/ -#define SOR_CFG (REGISTERS_BASE + 0x0800) - -/* Embedded ARM CPU Control */ - -/*=============================================== - Halt eCPU - 32bit RW - ------------------------------------------ - 0 HALT_ECPU Halt Embedded CPU - This bit is the - compliment of bit 1 (MDATA2) in the SOR_CFG register. - During a hardware reset, this bit holds - the inverse of MDATA2. - When downloading firmware from the host, - set this bit (pull down MDATA2). - The host clears this bit after downloading the firmware into - zero-wait-state SSRAM. - When loading firmware from Flash, clear this bit (pull up MDATA2) - so that the eCPU can run the bootloader code in Flash - HALT_ECPU eCPU State - -------------------- - 1 halt eCPU - 0 enable eCPU - ===============================================*/ -#define ACX_REG_ECPU_CONTROL (REGISTERS_BASE + 0x0804) - -#define HI_CFG (REGISTERS_BASE + 0x0808) - -/*=============================================== - EEPROM Burst Read Start - 32bit RW - ------------------------------------------ - [31:1] Reserved - 0 ACX_EE_START - EEPROM Burst Read Start 0 - Setting this bit starts a burst read from - the external EEPROM. - If this bit is set (after reset) before an EEPROM read/write, - the burst read starts at EEPROM address 0. - Otherwise, it starts at the address - following the address of the previous access. - TheWlan hardware hardware clears this bit automatically. - - Default: 0x00000000 -*================================================*/ -#define ACX_REG_EE_START (REGISTERS_BASE + 0x080C) - -#define OCP_POR_CTR (REGISTERS_BASE + 0x09B4) -#define OCP_DATA_WRITE (REGISTERS_BASE + 0x09B8) -#define OCP_DATA_READ (REGISTERS_BASE + 0x09BC) -#define OCP_CMD (REGISTERS_BASE + 0x09C0) - -#define WL1271_HOST_WR_ACCESS (REGISTERS_BASE + 0x09F8) - -#define CHIP_ID_B (REGISTERS_BASE + 0x5674) - -#define CHIP_ID_1271_PG10 (0x4030101) -#define CHIP_ID_1271_PG20 (0x4030111) -#define CHIP_ID_1283_PG10 (0x05030101) -#define CHIP_ID_1283_PG20 (0x05030111) - -#define ENABLE (REGISTERS_BASE + 0x5450) - -/* Power Management registers */ -#define ELP_CFG_MODE (REGISTERS_BASE + 0x5804) -#define ELP_CMD (REGISTERS_BASE + 0x5808) -#define PLL_CAL_TIME (REGISTERS_BASE + 0x5810) -#define CLK_REQ_TIME (REGISTERS_BASE + 0x5814) -#define CLK_BUF_TIME (REGISTERS_BASE + 0x5818) - -#define CFG_PLL_SYNC_CNT (REGISTERS_BASE + 0x5820) - -/* Scratch Pad registers*/ -#define SCR_PAD0 (REGISTERS_BASE + 0x5608) -#define SCR_PAD1 (REGISTERS_BASE + 0x560C) -#define SCR_PAD2 (REGISTERS_BASE + 0x5610) -#define SCR_PAD3 (REGISTERS_BASE + 0x5614) -#define SCR_PAD4 (REGISTERS_BASE + 0x5618) -#define SCR_PAD4_SET (REGISTERS_BASE + 0x561C) -#define SCR_PAD4_CLR (REGISTERS_BASE + 0x5620) -#define SCR_PAD5 (REGISTERS_BASE + 0x5624) -#define SCR_PAD5_SET (REGISTERS_BASE + 0x5628) -#define SCR_PAD5_CLR (REGISTERS_BASE + 0x562C) -#define SCR_PAD6 (REGISTERS_BASE + 0x5630) -#define SCR_PAD7 (REGISTERS_BASE + 0x5634) -#define SCR_PAD8 (REGISTERS_BASE + 0x5638) -#define SCR_PAD9 (REGISTERS_BASE + 0x563C) - -/* Spare registers*/ -#define SPARE_A1 (REGISTERS_BASE + 0x0994) -#define SPARE_A2 (REGISTERS_BASE + 0x0998) -#define SPARE_A3 (REGISTERS_BASE + 0x099C) -#define SPARE_A4 (REGISTERS_BASE + 0x09A0) -#define SPARE_A5 (REGISTERS_BASE + 0x09A4) -#define SPARE_A6 (REGISTERS_BASE + 0x09A8) -#define SPARE_A7 (REGISTERS_BASE + 0x09AC) -#define SPARE_A8 (REGISTERS_BASE + 0x09B0) -#define SPARE_B1 (REGISTERS_BASE + 0x5420) -#define SPARE_B2 (REGISTERS_BASE + 0x5424) -#define SPARE_B3 (REGISTERS_BASE + 0x5428) -#define SPARE_B4 (REGISTERS_BASE + 0x542C) -#define SPARE_B5 (REGISTERS_BASE + 0x5430) -#define SPARE_B6 (REGISTERS_BASE + 0x5434) -#define SPARE_B7 (REGISTERS_BASE + 0x5438) -#define SPARE_B8 (REGISTERS_BASE + 0x543C) - -#define PLL_PARAMETERS (REGISTERS_BASE + 0x6040) -#define WU_COUNTER_PAUSE (REGISTERS_BASE + 0x6008) -#define WELP_ARM_COMMAND (REGISTERS_BASE + 0x6100) -#define DRPW_SCRATCH_START (DRPW_BASE + 0x002C) - - -#define ACX_SLV_SOFT_RESET_BIT BIT(1) -#define ACX_REG_EEPROM_START_BIT BIT(1) - -/* Command/Information Mailbox Pointers */ - -/*=============================================== - Command Mailbox Pointer - 32bit RW - ------------------------------------------ - This register holds the start address of - the command mailbox located in the Wlan hardware memory. - The host must read this pointer after a reset to - find the location of the command mailbox. - The Wlan hardware initializes the command mailbox - pointer with the default address of the command mailbox. - The command mailbox pointer is not valid until after - the host receives the Init Complete interrupt from - the Wlan hardware. - ===============================================*/ -#define REG_COMMAND_MAILBOX_PTR (SCR_PAD0) - -/*=============================================== - Information Mailbox Pointer - 32bit RW - ------------------------------------------ - This register holds the start address of - the information mailbox located in the Wlan hardware memory. - The host must read this pointer after a reset to find - the location of the information mailbox. - The Wlan hardware initializes the information mailbox pointer - with the default address of the information mailbox. - The information mailbox pointer is not valid - until after the host receives the Init Complete interrupt from - the Wlan hardware. - ===============================================*/ -#define REG_EVENT_MAILBOX_PTR (SCR_PAD1) - -/*=============================================== - EEPROM Read/Write Request 32bit RW - ------------------------------------------ - 1 EE_READ - EEPROM Read Request 1 - Setting this bit - loads a single byte of data into the EE_DATA - register from the EEPROM location specified in - the EE_ADDR register. - The Wlan hardware hardware clears this bit automatically. - EE_DATA is valid when this bit is cleared. - - 0 EE_WRITE - EEPROM Write Request - Setting this bit - writes a single byte of data from the EE_DATA register into the - EEPROM location specified in the EE_ADDR register. - The Wlan hardware hardware clears this bit automatically. -*===============================================*/ -#define ACX_EE_CTL_REG EE_CTL -#define EE_WRITE 0x00000001ul -#define EE_READ 0x00000002ul - -/*=============================================== - EEPROM Address - 32bit RW - ------------------------------------------ - This register specifies the address - within the EEPROM from/to which to read/write data. - ===============================================*/ -#define ACX_EE_ADDR_REG EE_ADDR - -/*=============================================== - EEPROM Data - 32bit RW - ------------------------------------------ - This register either holds the read 8 bits of - data from the EEPROM or the write data - to be written to the EEPROM. - ===============================================*/ -#define ACX_EE_DATA_REG EE_DATA - -/*=============================================== - EEPROM Base Address - 32bit RW - ------------------------------------------ - This register holds the upper nine bits - [23:15] of the 24-bit Wlan hardware memory - address for burst reads from EEPROM accesses. - The EEPROM provides the lower 15 bits of this address. - The MSB of the address from the EEPROM is ignored. - ===============================================*/ -#define ACX_EE_CFG EE_CFG - -/*=============================================== - GPIO Output Values -32bit, RW - ------------------------------------------ - [31:16] Reserved - [15: 0] Specify the output values (at the output driver inputs) for - GPIO[15:0], respectively. - ===============================================*/ -#define ACX_GPIO_OUT_REG GPIO_OUT -#define ACX_MAX_GPIO_LINES 15 - -/*=============================================== - Contention window -32bit, RW - ------------------------------------------ - [31:26] Reserved - [25:16] Max (0x3ff) - [15:07] Reserved - [06:00] Current contention window value - default is 0x1F - ===============================================*/ -#define ACX_CONT_WIND_CFG_REG CONT_WIND_CFG -#define ACX_CONT_WIND_MIN_MASK 0x0000007f -#define ACX_CONT_WIND_MAX 0x03ff0000 - -/*=============================================== - HI_CFG Interface Configuration Register Values - ------------------------------------------ - ===============================================*/ -#define HI_CFG_UART_ENABLE 0x00000004 -#define HI_CFG_RST232_ENABLE 0x00000008 -#define HI_CFG_CLOCK_REQ_SELECT 0x00000010 -#define HI_CFG_HOST_INT_ENABLE 0x00000020 -#define HI_CFG_VLYNQ_OUTPUT_ENABLE 0x00000040 -#define HI_CFG_HOST_INT_ACTIVE_LOW 0x00000080 -#define HI_CFG_UART_TX_OUT_GPIO_15 0x00000100 -#define HI_CFG_UART_TX_OUT_GPIO_14 0x00000200 -#define HI_CFG_UART_TX_OUT_GPIO_7 0x00000400 - -#define HI_CFG_DEF_VAL \ - (HI_CFG_UART_ENABLE | \ - HI_CFG_RST232_ENABLE | \ - HI_CFG_CLOCK_REQ_SELECT | \ - HI_CFG_HOST_INT_ENABLE) - -#define REF_FREQ_19_2 0 -#define REF_FREQ_26_0 1 -#define REF_FREQ_38_4 2 -#define REF_FREQ_40_0 3 -#define REF_FREQ_33_6 4 -#define REF_FREQ_NUM 5 - -#define LUT_PARAM_INTEGER_DIVIDER 0 -#define LUT_PARAM_FRACTIONAL_DIVIDER 1 -#define LUT_PARAM_ATTN_BB 2 -#define LUT_PARAM_ALPHA_BB 3 -#define LUT_PARAM_STOP_TIME_BB 4 -#define LUT_PARAM_BB_PLL_LOOP_FILTER 5 -#define LUT_PARAM_NUM 6 - -#define ACX_EEPROMLESS_IND_REG (SCR_PAD4) -#define USE_EEPROM 0 -#define SOFT_RESET_MAX_TIME 1000000 -#define SOFT_RESET_STALL_TIME 1000 -#define NVS_DATA_BUNDARY_ALIGNMENT 4 - - -/* Firmware image load chunk size */ -#define CHUNK_SIZE 16384 - -/* Firmware image header size */ -#define FW_HDR_SIZE 8 - -#define ECPU_CONTROL_HALT 0x00000101 - - -/****************************************************************************** - - CHANNELS, BAND & REG DOMAINS definitions - -******************************************************************************/ - - -enum { - RADIO_BAND_2_4GHZ = 0, /* 2.4 Ghz band */ - RADIO_BAND_5GHZ = 1, /* 5 Ghz band */ - RADIO_BAND_JAPAN_4_9_GHZ = 2, - DEFAULT_BAND = RADIO_BAND_2_4GHZ, - INVALID_BAND = 0xFE, - MAX_RADIO_BANDS = 0xFF -}; - -#define SHORT_PREAMBLE_BIT BIT(0) /* CCK or Barker depending on the rate */ -#define OFDM_RATE_BIT BIT(6) -#define PBCC_RATE_BIT BIT(7) - -enum { - CCK_LONG = 0, - CCK_SHORT = SHORT_PREAMBLE_BIT, - PBCC_LONG = PBCC_RATE_BIT, - PBCC_SHORT = PBCC_RATE_BIT | SHORT_PREAMBLE_BIT, - OFDM = OFDM_RATE_BIT -}; - -/****************************************************************************** - -Transmit-Descriptor RATE-SET field definitions... - -Define a new "Rate-Set" for TX path that incorporates the -Rate & Modulation info into a single 16-bit field. - -TxdRateSet_t: -b15 - Indicates Preamble type (1=SHORT, 0=LONG). - Notes: - Must be LONG (0) for 1Mbps rate. - Does not apply (set to 0) for RevG-OFDM rates. -b14 - Indicates PBCC encoding (1=PBCC, 0=not). - Notes: - Does not apply (set to 0) for rates 1 and 2 Mbps. - Does not apply (set to 0) for RevG-OFDM rates. -b13 - Unused (set to 0). -b12-b0 - Supported Rate indicator bits as defined below. - -******************************************************************************/ - - -/************************************************************************* - - Interrupt Trigger Register (Host -> WiLink) - -**************************************************************************/ - -/* Hardware to Embedded CPU Interrupts - first 32-bit register set */ - -/* - * Host Command Interrupt. Setting this bit masks - * the interrupt that the host issues to inform - * the FW that it has sent a command - * to the Wlan hardware Command Mailbox. - */ -#define INTR_TRIG_CMD BIT(0) - -/* - * Host Event Acknowlegde Interrupt. The host - * sets this bit to acknowledge that it received - * the unsolicited information from the event - * mailbox. - */ -#define INTR_TRIG_EVENT_ACK BIT(1) - -/* - * The host sets this bit to inform the Wlan - * FW that a TX packet is in the XFER - * Buffer #0. - */ -#define INTR_TRIG_TX_PROC0 BIT(2) - -/* - * The host sets this bit to inform the FW - * that it read a packet from RX XFER - * Buffer #0. - */ -#define INTR_TRIG_RX_PROC0 BIT(3) - -#define INTR_TRIG_DEBUG_ACK BIT(4) - -#define INTR_TRIG_STATE_CHANGED BIT(5) - - -/* Hardware to Embedded CPU Interrupts - second 32-bit register set */ - -/* - * The host sets this bit to inform the FW - * that it read a packet from RX XFER - * Buffer #1. - */ -#define INTR_TRIG_RX_PROC1 BIT(17) - -/* - * The host sets this bit to inform the Wlan - * hardware that a TX packet is in the XFER - * Buffer #1. - */ -#define INTR_TRIG_TX_PROC1 BIT(18) - -#define WL127X_REG_FUSE_DATA_2_1 0x050a -#define WL128X_REG_FUSE_DATA_2_1 0x2152 -#define PG_VER_MASK 0x3c -#define PG_VER_OFFSET 2 - -#define WL127X_PG_MAJOR_VER_MASK 0x3 -#define WL127X_PG_MAJOR_VER_OFFSET 0x0 -#define WL127X_PG_MINOR_VER_MASK 0xc -#define WL127X_PG_MINOR_VER_OFFSET 0x2 - -#define WL128X_PG_MAJOR_VER_MASK 0xc -#define WL128X_PG_MAJOR_VER_OFFSET 0x2 -#define WL128X_PG_MINOR_VER_MASK 0x3 -#define WL128X_PG_MINOR_VER_OFFSET 0x0 - -#define WL127X_PG_GET_MAJOR(pg_ver) ((pg_ver & WL127X_PG_MAJOR_VER_MASK) >> \ - WL127X_PG_MAJOR_VER_OFFSET) -#define WL127X_PG_GET_MINOR(pg_ver) ((pg_ver & WL127X_PG_MINOR_VER_MASK) >> \ - WL127X_PG_MINOR_VER_OFFSET) -#define WL128X_PG_GET_MAJOR(pg_ver) ((pg_ver & WL128X_PG_MAJOR_VER_MASK) >> \ - WL128X_PG_MAJOR_VER_OFFSET) -#define WL128X_PG_GET_MINOR(pg_ver) ((pg_ver & WL128X_PG_MINOR_VER_MASK) >> \ - WL128X_PG_MINOR_VER_OFFSET) - -#define WL12XX_REG_FUSE_BD_ADDR_1 0x00310eb4 -#define WL12XX_REG_FUSE_BD_ADDR_2 0x00310eb8 - -#endif diff --git a/drivers/net/wireless/ti/wlcore/rx.c b/drivers/net/wireless/ti/wlcore/rx.c index 4fc37f9f38a..d7fab4626a1 100644 --- a/drivers/net/wireless/ti/wlcore/rx.c +++ b/drivers/net/wireless/ti/wlcore/rx.c @@ -27,11 +27,16 @@ #include "wlcore.h" #include "debug.h" #include "acx.h" -#include "reg.h" #include "rx.h" #include "tx.h" #include "io.h" +/* + * TODO: this is here just for now, it must be removed when the data + * operations are in place. + */ +#include "../wl12xx/reg.h" + static u8 wl12xx_rx_get_mem_block(struct wl12xx_fw_status *status, u32 drv_rx_counter) { @@ -231,14 +236,14 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) wl->rx_mem_pool_addr.addr_extra = wl->rx_mem_pool_addr.addr + 4; - wl1271_write(wl, WL1271_SLV_REG_DATA, - &wl->rx_mem_pool_addr, - sizeof(wl->rx_mem_pool_addr), false); + wlcore_write_data(wl, REG_SLV_REG_DATA, + &wl->rx_mem_pool_addr, + sizeof(wl->rx_mem_pool_addr), false); } /* Read all available packets at once */ - wl1271_read(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf, - buf_size, true); + wlcore_read_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, + buf_size, true); /* Split data into separate packets */ pkt_offset = 0; @@ -278,7 +283,8 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) * for older hardware revisions */ if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION) - wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); + wl1271_write32(wl, WL12XX_REG_RX_DRIVER_COUNTER, + wl->rx_counter); wl12xx_rearm_rx_streaming(wl, active_hlids); } diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c index e407acf124d..0a72347cfc4 100644 --- a/drivers/net/wireless/ti/wlcore/sdio.c +++ b/drivers/net/wireless/ti/wlcore/sdio.c @@ -76,7 +76,7 @@ static void wl12xx_sdio_raw_read(struct device *child, int addr, void *buf, sdio_claim_host(func); - if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { + if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG)) { ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret); dev_dbg(child->parent, "sdio read 52 addr 0x%x, byte 0x%02x\n", addr, ((u8 *)buf)[0]); @@ -105,7 +105,7 @@ static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf, sdio_claim_host(func); - if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { + if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG)) { sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret); dev_dbg(child->parent, "sdio write 52 addr 0x%x, byte 0x%02x\n", addr, ((u8 *)buf)[0]); diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c index 9eeb3941297..553cd3cbb98 100644 --- a/drivers/net/wireless/ti/wlcore/spi.c +++ b/drivers/net/wireless/ti/wlcore/spi.c @@ -34,8 +34,6 @@ #include "wl12xx_80211.h" #include "io.h" -#include "reg.h" - #define WSPI_CMD_READ 0x40000000 #define WSPI_CMD_WRITE 0x00000000 #define WSPI_CMD_FIXED 0x20000000 diff --git a/drivers/net/wireless/ti/wlcore/testmode.c b/drivers/net/wireless/ti/wlcore/testmode.c index 2ea40131e64..9cda706e4e3 100644 --- a/drivers/net/wireless/ti/wlcore/testmode.c +++ b/drivers/net/wireless/ti/wlcore/testmode.c @@ -28,7 +28,6 @@ #include "wlcore.h" #include "debug.h" #include "acx.h" -#include "reg.h" #include "ps.h" #include "io.h" diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c index 83cb83cdc10..4e90c07d1ab 100644 --- a/drivers/net/wireless/ti/wlcore/tx.c +++ b/drivers/net/wireless/ti/wlcore/tx.c @@ -28,11 +28,16 @@ #include "wlcore.h" #include "debug.h" #include "io.h" -#include "reg.h" #include "ps.h" #include "tx.h" #include "event.h" +/* + * TODO: this is here just for now, it must be removed when the data + * operations are in place. + */ +#include "../wl12xx/reg.h" + static int wl1271_set_default_wep_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 id) { @@ -718,8 +723,8 @@ void wl1271_tx_work_locked(struct wl1271 *wl) * Flush buffer and try again. */ wl1271_skb_queue_head(wl, wlvif, skb); - wl1271_write(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf, - buf_offset, true); + wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, + buf_offset, true); sent_packets = true; buf_offset = 0; continue; @@ -753,8 +758,8 @@ void wl1271_tx_work_locked(struct wl1271 *wl) out_ack: if (buf_offset) { - wl1271_write(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf, - buf_offset, true); + wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, + buf_offset, true); sent_packets = true; } if (sent_packets) { @@ -763,7 +768,7 @@ out_ack: * required for older hardware revisions */ if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION) - wl1271_write32(wl, WL1271_HOST_WR_ACCESS, + wl1271_write32(wl, WL12XX_HOST_WR_ACCESS, wl->tx_packets_count); wl1271_handle_tx_low_watermark(wl); diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index 84f05a4d3cd..f11e5c6de51 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h @@ -53,6 +53,29 @@ struct wlcore_partition_set { struct wlcore_partition mem3; }; +enum wlcore_registers { + /* register addresses, used with partition translation */ + REG_ECPU_CONTROL, + REG_INTERRUPT_NO_CLEAR, + REG_INTERRUPT_ACK, + REG_COMMAND_MAILBOX_PTR, + REG_EVENT_MAILBOX_PTR, + REG_INTERRUPT_TRIG, + REG_INTERRUPT_MASK, + REG_PC_ON_RECOVERY, + REG_CHIP_ID_B, + REG_CMD_MBOX_ADDRESS, + + /* data access memory addresses, used with partition translation */ + REG_SLV_MEM_DATA, + REG_SLV_REG_DATA, + + /* raw data access memory addresses */ + REG_RAW_FW_STATUS_ADDR, + + REG_TABLE_LEN, +}; + struct wl1271 { struct ieee80211_hw *hw; bool mac80211_registered; @@ -266,6 +289,8 @@ struct wl1271 { struct wlcore_ops *ops; /* pointer to the lower driver partition table */ const struct wlcore_partition_set *ptable; + /* pointer to the lower driver register table */ + const int *rtable; }; int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev); @@ -273,5 +298,87 @@ int __devexit wlcore_remove(struct platform_device *pdev); struct ieee80211_hw *wlcore_alloc_hw(void); int wlcore_free_hw(struct wl1271 *wl); +/* Firmware image load chunk size */ +#define CHUNK_SIZE 16384 + +/* TODO: move to the lower drivers when all usages are abstracted */ +#define CHIP_ID_1271_PG10 (0x4030101) +#define CHIP_ID_1271_PG20 (0x4030111) +#define CHIP_ID_1283_PG10 (0x05030101) +#define CHIP_ID_1283_PG20 (0x05030111) + +/* TODO: move all these common registers and values elsewhere */ +#define HW_ACCESS_ELP_CTRL_REG 0x1FFFC + +/* ELP register commands */ +#define ELPCTRL_WAKE_UP 0x1 +#define ELPCTRL_WAKE_UP_WLAN_READY 0x5 +#define ELPCTRL_SLEEP 0x0 +/* ELP WLAN_READY bit */ +#define ELPCTRL_WLAN_READY 0x2 + +/************************************************************************* + + Interrupt Trigger Register (Host -> WiLink) + +**************************************************************************/ + +/* Hardware to Embedded CPU Interrupts - first 32-bit register set */ + +/* + * Host Command Interrupt. Setting this bit masks + * the interrupt that the host issues to inform + * the FW that it has sent a command + * to the Wlan hardware Command Mailbox. + */ +#define INTR_TRIG_CMD BIT(0) + +/* + * Host Event Acknowlegde Interrupt. The host + * sets this bit to acknowledge that it received + * the unsolicited information from the event + * mailbox. + */ +#define INTR_TRIG_EVENT_ACK BIT(1) + +/* + * The host sets this bit to inform the Wlan + * FW that a TX packet is in the XFER + * Buffer #0. + */ +#define INTR_TRIG_TX_PROC0 BIT(2) + +/* + * The host sets this bit to inform the FW + * that it read a packet from RX XFER + * Buffer #0. + */ +#define INTR_TRIG_RX_PROC0 BIT(3) + +#define INTR_TRIG_DEBUG_ACK BIT(4) + +#define INTR_TRIG_STATE_CHANGED BIT(5) + +/* Hardware to Embedded CPU Interrupts - second 32-bit register set */ + +/* + * The host sets this bit to inform the FW + * that it read a packet from RX XFER + * Buffer #1. + */ +#define INTR_TRIG_RX_PROC1 BIT(17) + +/* + * The host sets this bit to inform the Wlan + * hardware that a TX packet is in the XFER + * Buffer #1. + */ +#define INTR_TRIG_TX_PROC1 BIT(18) + +#define ACX_SLV_SOFT_RESET_BIT BIT(1) +#define SOFT_RESET_MAX_TIME 1000000 +#define SOFT_RESET_STALL_TIME 1000 + +#define ECPU_CONTROL_HALT 0x00000101 #endif /* __WLCORE_H__ */ -- cgit v1.2.3-70-g09d2 From f16ff75872b04fa6c779367ae24146c8a1729f2e Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Wed, 11 Apr 2012 10:15:46 +0300 Subject: wlcore/wl12xx: add command trigger and event ack operations Different chips may use different bits in the interrupt trigger register. Add operations to handle these differences. Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wl12xx/main.c | 12 ++++++++++++ drivers/net/wireless/ti/wl12xx/reg.h | 16 ++++++++++++++++ drivers/net/wireless/ti/wlcore/cmd.c | 6 +++++- drivers/net/wireless/ti/wlcore/event.c | 7 +++++-- drivers/net/wireless/ti/wlcore/wlcore.h | 18 ++---------------- 5 files changed, 40 insertions(+), 19 deletions(-) (limited to 'drivers/net/wireless/ti/wlcore/cmd.c') diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index cef2884b37c..8d82203d3da 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c @@ -571,6 +571,16 @@ out: return ret; } +static void wl12xx_trigger_cmd(struct wl1271 *wl) +{ + wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_CMD); +} + +static void wl12xx_ack_event(struct wl1271 *wl) +{ + wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_EVENT_ACK); +} + static bool wl12xx_mac_in_fuse(struct wl1271 *wl) { bool supported = false; @@ -637,6 +647,8 @@ static void wl12xx_get_mac(struct wl1271 *wl) static struct wlcore_ops wl12xx_ops = { .identify_chip = wl12xx_identify_chip, .boot = wl12xx_boot, + .trigger_cmd = wl12xx_trigger_cmd, + .ack_event = wl12xx_ack_event, .get_pg_ver = wl12xx_get_pg_ver, .get_mac = wl12xx_get_mac, }; diff --git a/drivers/net/wireless/ti/wl12xx/reg.h b/drivers/net/wireless/ti/wl12xx/reg.h index 003041bdb5f..79ede02e258 100644 --- a/drivers/net/wireless/ti/wl12xx/reg.h +++ b/drivers/net/wireless/ti/wl12xx/reg.h @@ -490,6 +490,22 @@ enum { /* end PLL configuration algorithm for wl128x */ +/* + * Host Command Interrupt. Setting this bit masks + * the interrupt that the host issues to inform + * the FW that it has sent a command + * to the Wlan hardware Command Mailbox. + */ +#define WL12XX_INTR_TRIG_CMD BIT(0) + +/* + * Host Event Acknowlegde Interrupt. The host + * sets this bit to acknowledge that it received + * the unsolicited information from the event + * mailbox. + */ +#define WL12XX_INTR_TRIG_EVENT_ACK BIT(1) + /*=============================================== HI_CFG Interface Configuration Register Values ------------------------------------------ diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index 3ec86e96f5c..e80f674e77c 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c @@ -66,7 +66,11 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, wl1271_write(wl, wl->cmd_box_addr, buf, len, false); - wlcore_write_reg(wl, REG_INTERRUPT_TRIG, INTR_TRIG_CMD); + /* + * TODO: we just need this because one bit is in a different + * place. Is there any better way? + */ + wl->ops->trigger_cmd(wl); timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT); diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c index 078cb012fcc..e3f572cbdf9 100644 --- a/drivers/net/wireless/ti/wlcore/event.c +++ b/drivers/net/wireless/ti/wlcore/event.c @@ -305,8 +305,11 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num) if (ret < 0) return ret; - /* then we let the firmware know it can go on...*/ - wlcore_write_reg(wl, REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK); + /* + * TODO: we just need this because one bit is in a different + * place. Is there any better way? + */ + wl->ops->ack_event(wl); return 0; } diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index 38d1ed2967c..76c27dd93c2 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h @@ -30,6 +30,8 @@ struct wlcore_ops { int (*identify_chip)(struct wl1271 *wl); int (*boot)(struct wl1271 *wl); + void (*trigger_cmd)(struct wl1271 *wl); + void (*ack_event)(struct wl1271 *wl); s8 (*get_pg_ver)(struct wl1271 *wl); void (*get_mac)(struct wl1271 *wl); }; @@ -344,22 +346,6 @@ int wlcore_free_hw(struct wl1271 *wl); /* Hardware to Embedded CPU Interrupts - first 32-bit register set */ -/* - * Host Command Interrupt. Setting this bit masks - * the interrupt that the host issues to inform - * the FW that it has sent a command - * to the Wlan hardware Command Mailbox. - */ -#define INTR_TRIG_CMD BIT(0) - -/* - * Host Event Acknowlegde Interrupt. The host - * sets this bit to acknowledge that it received - * the unsolicited information from the event - * mailbox. - */ -#define INTR_TRIG_EVENT_ACK BIT(1) - /* * The host sets this bit to inform the Wlan * FW that a TX packet is in the XFER -- cgit v1.2.3-70-g09d2 From 9d68d1eea7fb4d05b5bd037da6a66329d640b2f1 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 2 Dec 2011 00:47:45 +0200 Subject: wlcore/wl12xx: add hw_init operation Move all the wl12xx-specific hw initialization procedures into a new hw_init op. Move some commands and ACX functions to wl12xx. Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wl12xx/Makefile | 2 +- drivers/net/wireless/ti/wl12xx/acx.c | 53 +++++++ drivers/net/wireless/ti/wl12xx/acx.h | 36 +++++ drivers/net/wireless/ti/wl12xx/cmd.c | 252 ++++++++++++++++++++++++++++++++ drivers/net/wireless/ti/wl12xx/cmd.h | 110 ++++++++++++++ drivers/net/wireless/ti/wl12xx/main.c | 40 +++++ drivers/net/wireless/ti/wlcore/acx.c | 26 ---- drivers/net/wireless/ti/wlcore/acx.h | 8 +- drivers/net/wireless/ti/wlcore/cmd.c | 228 +---------------------------- drivers/net/wireless/ti/wlcore/cmd.h | 82 ----------- drivers/net/wireless/ti/wlcore/init.c | 43 +----- drivers/net/wireless/ti/wlcore/main.c | 23 +-- drivers/net/wireless/ti/wlcore/wlcore.h | 1 + 13 files changed, 499 insertions(+), 405 deletions(-) create mode 100644 drivers/net/wireless/ti/wl12xx/acx.c create mode 100644 drivers/net/wireless/ti/wl12xx/acx.h create mode 100644 drivers/net/wireless/ti/wl12xx/cmd.c create mode 100644 drivers/net/wireless/ti/wl12xx/cmd.h (limited to 'drivers/net/wireless/ti/wlcore/cmd.c') diff --git a/drivers/net/wireless/ti/wl12xx/Makefile b/drivers/net/wireless/ti/wl12xx/Makefile index 1df22d55943..87f64b14db3 100644 --- a/drivers/net/wireless/ti/wl12xx/Makefile +++ b/drivers/net/wireless/ti/wl12xx/Makefile @@ -1,3 +1,3 @@ -wl12xx-objs = main.o +wl12xx-objs = main.o cmd.o acx.o obj-$(CONFIG_WL12XX) += wl12xx.o diff --git a/drivers/net/wireless/ti/wl12xx/acx.c b/drivers/net/wireless/ti/wl12xx/acx.c new file mode 100644 index 00000000000..bea06b2d7bf --- /dev/null +++ b/drivers/net/wireless/ti/wl12xx/acx.c @@ -0,0 +1,53 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 2008-2009 Nokia Corporation + * Copyright (C) 2011 Texas Instruments Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include "../wlcore/cmd.h" +#include "../wlcore/debug.h" +#include "../wlcore/acx.h" + +#include "acx.h" + +int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap) +{ + struct wl1271_acx_host_config_bitmap *bitmap_conf; + int ret; + + bitmap_conf = kzalloc(sizeof(*bitmap_conf), GFP_KERNEL); + if (!bitmap_conf) { + ret = -ENOMEM; + goto out; + } + + bitmap_conf->host_cfg_bitmap = cpu_to_le32(host_cfg_bitmap); + + ret = wl1271_cmd_configure(wl, ACX_HOST_IF_CFG_BITMAP, + bitmap_conf, sizeof(*bitmap_conf)); + if (ret < 0) { + wl1271_warning("wl1271 bitmap config opt failed: %d", ret); + goto out; + } + +out: + kfree(bitmap_conf); + + return ret; +} diff --git a/drivers/net/wireless/ti/wl12xx/acx.h b/drivers/net/wireless/ti/wl12xx/acx.h new file mode 100644 index 00000000000..d1f5aba0afc --- /dev/null +++ b/drivers/net/wireless/ti/wl12xx/acx.h @@ -0,0 +1,36 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 1998-2009, 2011 Texas Instruments. All rights reserved. + * Copyright (C) 2008-2010 Nokia Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __WL12XX_ACX_H__ +#define __WL12XX_ACX_H__ + +#include "../wlcore/wlcore.h" + +struct wl1271_acx_host_config_bitmap { + struct acx_header header; + + __le32 host_cfg_bitmap; +} __packed; + +int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap); + +#endif /* __WL12XX_ACX_H__ */ diff --git a/drivers/net/wireless/ti/wl12xx/cmd.c b/drivers/net/wireless/ti/wl12xx/cmd.c new file mode 100644 index 00000000000..e46512d185a --- /dev/null +++ b/drivers/net/wireless/ti/wl12xx/cmd.c @@ -0,0 +1,252 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 2009-2010 Nokia Corporation + * Copyright (C) 2011 Texas Instruments Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include "../wlcore/cmd.h" +#include "../wlcore/debug.h" + +#include "cmd.h" + +int wl1271_cmd_ext_radio_parms(struct wl1271 *wl) +{ + struct wl1271_ext_radio_parms_cmd *ext_radio_parms; + struct conf_rf_settings *rf = &wl->conf.rf; + int ret; + + if (!wl->nvs) + return -ENODEV; + + ext_radio_parms = kzalloc(sizeof(*ext_radio_parms), GFP_KERNEL); + if (!ext_radio_parms) + return -ENOMEM; + + ext_radio_parms->test.id = TEST_CMD_INI_FILE_RF_EXTENDED_PARAM; + + memcpy(ext_radio_parms->tx_per_channel_power_compensation_2, + rf->tx_per_channel_power_compensation_2, + CONF_TX_PWR_COMPENSATION_LEN_2); + memcpy(ext_radio_parms->tx_per_channel_power_compensation_5, + rf->tx_per_channel_power_compensation_5, + CONF_TX_PWR_COMPENSATION_LEN_5); + + wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_EXT_RADIO_PARAM: ", + ext_radio_parms, sizeof(*ext_radio_parms)); + + ret = wl1271_cmd_test(wl, ext_radio_parms, sizeof(*ext_radio_parms), 0); + if (ret < 0) + wl1271_warning("TEST_CMD_INI_FILE_RF_EXTENDED_PARAM failed"); + + kfree(ext_radio_parms); + return ret; +} + +int wl1271_cmd_general_parms(struct wl1271 *wl) +{ + struct wl1271_general_parms_cmd *gen_parms; + struct wl1271_ini_general_params *gp = + &((struct wl1271_nvs_file *)wl->nvs)->general_params; + bool answer = false; + int ret; + + if (!wl->nvs) + return -ENODEV; + + if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { + wl1271_warning("FEM index from INI out of bounds"); + return -EINVAL; + } + + gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); + if (!gen_parms) + return -ENOMEM; + + gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; + + memcpy(&gen_parms->general_params, gp, sizeof(*gp)); + + if (gp->tx_bip_fem_auto_detect) + answer = true; + + /* Override the REF CLK from the NVS with the one from platform data */ + gen_parms->general_params.ref_clock = wl->ref_clock; + + ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); + if (ret < 0) { + wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); + goto out; + } + + gp->tx_bip_fem_manufacturer = + gen_parms->general_params.tx_bip_fem_manufacturer; + + if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { + wl1271_warning("FEM index from FW out of bounds"); + ret = -EINVAL; + goto out; + } + + wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", + answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); + +out: + kfree(gen_parms); + return ret; +} + +int wl128x_cmd_general_parms(struct wl1271 *wl) +{ + struct wl128x_general_parms_cmd *gen_parms; + struct wl128x_ini_general_params *gp = + &((struct wl128x_nvs_file *)wl->nvs)->general_params; + bool answer = false; + int ret; + + if (!wl->nvs) + return -ENODEV; + + if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { + wl1271_warning("FEM index from ini out of bounds"); + return -EINVAL; + } + + gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); + if (!gen_parms) + return -ENOMEM; + + gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; + + memcpy(&gen_parms->general_params, gp, sizeof(*gp)); + + if (gp->tx_bip_fem_auto_detect) + answer = true; + + /* Replace REF and TCXO CLKs with the ones from platform data */ + gen_parms->general_params.ref_clock = wl->ref_clock; + gen_parms->general_params.tcxo_ref_clock = wl->tcxo_clock; + + ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); + if (ret < 0) { + wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); + goto out; + } + + gp->tx_bip_fem_manufacturer = + gen_parms->general_params.tx_bip_fem_manufacturer; + + if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { + wl1271_warning("FEM index from FW out of bounds"); + ret = -EINVAL; + goto out; + } + + wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", + answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); + +out: + kfree(gen_parms); + return ret; +} + +int wl1271_cmd_radio_parms(struct wl1271 *wl) +{ + struct wl1271_nvs_file *nvs = (struct wl1271_nvs_file *)wl->nvs; + struct wl1271_radio_parms_cmd *radio_parms; + struct wl1271_ini_general_params *gp = &nvs->general_params; + int ret; + + if (!wl->nvs) + return -ENODEV; + + radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL); + if (!radio_parms) + return -ENOMEM; + + radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; + + /* 2.4GHz parameters */ + memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2, + sizeof(struct wl1271_ini_band_params_2)); + memcpy(&radio_parms->dyn_params_2, + &nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params, + sizeof(struct wl1271_ini_fem_params_2)); + + /* 5GHz parameters */ + memcpy(&radio_parms->static_params_5, + &nvs->stat_radio_params_5, + sizeof(struct wl1271_ini_band_params_5)); + memcpy(&radio_parms->dyn_params_5, + &nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params, + sizeof(struct wl1271_ini_fem_params_5)); + + wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", + radio_parms, sizeof(*radio_parms)); + + ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0); + if (ret < 0) + wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed"); + + kfree(radio_parms); + return ret; +} + +int wl128x_cmd_radio_parms(struct wl1271 *wl) +{ + struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs; + struct wl128x_radio_parms_cmd *radio_parms; + struct wl128x_ini_general_params *gp = &nvs->general_params; + int ret; + + if (!wl->nvs) + return -ENODEV; + + radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL); + if (!radio_parms) + return -ENOMEM; + + radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; + + /* 2.4GHz parameters */ + memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2, + sizeof(struct wl128x_ini_band_params_2)); + memcpy(&radio_parms->dyn_params_2, + &nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params, + sizeof(struct wl128x_ini_fem_params_2)); + + /* 5GHz parameters */ + memcpy(&radio_parms->static_params_5, + &nvs->stat_radio_params_5, + sizeof(struct wl128x_ini_band_params_5)); + memcpy(&radio_parms->dyn_params_5, + &nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params, + sizeof(struct wl128x_ini_fem_params_5)); + + radio_parms->fem_vendor_and_options = nvs->fem_vendor_and_options; + + wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", + radio_parms, sizeof(*radio_parms)); + + ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0); + if (ret < 0) + wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed"); + + kfree(radio_parms); + return ret; +} diff --git a/drivers/net/wireless/ti/wl12xx/cmd.h b/drivers/net/wireless/ti/wl12xx/cmd.h new file mode 100644 index 00000000000..ff458302ab0 --- /dev/null +++ b/drivers/net/wireless/ti/wl12xx/cmd.h @@ -0,0 +1,110 @@ +/* + * This file is part of wl12xx + * + * Copyright (C) 1998-2009, 2011 Texas Instruments. All rights reserved. + * Copyright (C) 2009 Nokia Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __WL12XX_CMD_H__ +#define __WL12XX_CMD_H__ + +#define TEST_CMD_INI_FILE_RADIO_PARAM 0x19 +#define TEST_CMD_INI_FILE_GENERAL_PARAM 0x1E + +struct wl1271_general_parms_cmd { + struct wl1271_cmd_header header; + + struct wl1271_cmd_test_header test; + + struct wl1271_ini_general_params general_params; + + u8 sr_debug_table[WL1271_INI_MAX_SMART_REFLEX_PARAM]; + u8 sr_sen_n_p; + u8 sr_sen_n_p_gain; + u8 sr_sen_nrn; + u8 sr_sen_prn; + u8 padding[3]; +} __packed; + +struct wl128x_general_parms_cmd { + struct wl1271_cmd_header header; + + struct wl1271_cmd_test_header test; + + struct wl128x_ini_general_params general_params; + + u8 sr_debug_table[WL1271_INI_MAX_SMART_REFLEX_PARAM]; + u8 sr_sen_n_p; + u8 sr_sen_n_p_gain; + u8 sr_sen_nrn; + u8 sr_sen_prn; + u8 padding[3]; +} __packed; + +struct wl1271_radio_parms_cmd { + struct wl1271_cmd_header header; + + struct wl1271_cmd_test_header test; + + /* Static radio parameters */ + struct wl1271_ini_band_params_2 static_params_2; + struct wl1271_ini_band_params_5 static_params_5; + + /* Dynamic radio parameters */ + struct wl1271_ini_fem_params_2 dyn_params_2; + u8 padding2; + struct wl1271_ini_fem_params_5 dyn_params_5; + u8 padding3[2]; +} __packed; + +struct wl128x_radio_parms_cmd { + struct wl1271_cmd_header header; + + struct wl1271_cmd_test_header test; + + /* Static radio parameters */ + struct wl128x_ini_band_params_2 static_params_2; + struct wl128x_ini_band_params_5 static_params_5; + + u8 fem_vendor_and_options; + + /* Dynamic radio parameters */ + struct wl128x_ini_fem_params_2 dyn_params_2; + u8 padding2; + struct wl128x_ini_fem_params_5 dyn_params_5; +} __packed; + +#define TEST_CMD_INI_FILE_RF_EXTENDED_PARAM 0x26 + +struct wl1271_ext_radio_parms_cmd { + struct wl1271_cmd_header header; + + struct wl1271_cmd_test_header test; + + u8 tx_per_channel_power_compensation_2[CONF_TX_PWR_COMPENSATION_LEN_2]; + u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5]; + u8 padding[3]; +} __packed; + +int wl1271_cmd_general_parms(struct wl1271 *wl); +int wl128x_cmd_general_parms(struct wl1271 *wl); +int wl1271_cmd_radio_parms(struct wl1271 *wl); +int wl128x_cmd_radio_parms(struct wl1271 *wl); +int wl1271_cmd_ext_radio_parms(struct wl1271 *wl); + +#endif /* __WL12XX_CMD_H__ */ diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index 00ecd2ad495..9b2f40cd58d 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c @@ -36,6 +36,8 @@ #include "../wlcore/boot.h" #include "reg.h" +#include "cmd.h" +#include "acx.h" #define WL12XX_TX_HW_BLOCK_SPARE_DEFAULT 1 #define WL12XX_TX_HW_BLOCK_GEM_SPARE 2 @@ -800,6 +802,43 @@ static void wl12xx_tx_delayed_compl(struct wl1271 *wl) wl1271_tx_complete(wl); } +static int wl12xx_hw_init(struct wl1271 *wl) +{ + int ret; + + if (wl->chip.id == CHIP_ID_1283_PG20) { + u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE; + + ret = wl128x_cmd_general_parms(wl); + if (ret < 0) + goto out; + ret = wl128x_cmd_radio_parms(wl); + if (ret < 0) + goto out; + + if (wl->quirks & WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN) + /* Enable SDIO padding */ + host_cfg_bitmap |= HOST_IF_CFG_TX_PAD_TO_SDIO_BLK; + + /* Must be before wl1271_acx_init_mem_config() */ + ret = wl1271_acx_host_if_cfg_bitmap(wl, host_cfg_bitmap); + if (ret < 0) + goto out; + } else { + ret = wl1271_cmd_general_parms(wl); + if (ret < 0) + goto out; + ret = wl1271_cmd_radio_parms(wl); + if (ret < 0) + goto out; + ret = wl1271_cmd_ext_radio_parms(wl); + if (ret < 0) + goto out; + } +out: + return ret; +} + static bool wl12xx_mac_in_fuse(struct wl1271 *wl) { bool supported = false; @@ -875,6 +914,7 @@ static struct wlcore_ops wl12xx_ops = { .get_rx_packet_len = wl12xx_get_rx_packet_len, .tx_immediate_compl = NULL, .tx_delayed_compl = wl12xx_tx_delayed_compl, + .hw_init = wl12xx_hw_init, .get_pg_ver = wl12xx_get_pg_ver, .get_mac = wl12xx_get_mac, }; diff --git a/drivers/net/wireless/ti/wlcore/acx.c b/drivers/net/wireless/ti/wlcore/acx.c index c811f75fc8d..01dba462e52 100644 --- a/drivers/net/wireless/ti/wlcore/acx.c +++ b/drivers/net/wireless/ti/wlcore/acx.c @@ -997,32 +997,6 @@ out: return ret; } -int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap) -{ - struct wl1271_acx_host_config_bitmap *bitmap_conf; - int ret; - - bitmap_conf = kzalloc(sizeof(*bitmap_conf), GFP_KERNEL); - if (!bitmap_conf) { - ret = -ENOMEM; - goto out; - } - - bitmap_conf->host_cfg_bitmap = cpu_to_le32(host_cfg_bitmap); - - ret = wl1271_cmd_configure(wl, ACX_HOST_IF_CFG_BITMAP, - bitmap_conf, sizeof(*bitmap_conf)); - if (ret < 0) { - wl1271_warning("wl1271 bitmap config opt failed: %d", ret); - goto out; - } - -out: - kfree(bitmap_conf); - - return ret; -} - int wl1271_acx_init_mem_config(struct wl1271 *wl) { int ret; diff --git a/drivers/net/wireless/ti/wlcore/acx.h b/drivers/net/wireless/ti/wlcore/acx.h index e24511a0461..b2f88831b7a 100644 --- a/drivers/net/wireless/ti/wlcore/acx.h +++ b/drivers/net/wireless/ti/wlcore/acx.h @@ -824,16 +824,11 @@ struct wl1271_acx_keep_alive_config { __le32 period; } __packed; +/* TODO: maybe this needs to be moved somewhere else? */ #define HOST_IF_CFG_RX_FIFO_ENABLE BIT(0) #define HOST_IF_CFG_TX_EXTRA_BLKS_SWAP BIT(1) #define HOST_IF_CFG_TX_PAD_TO_SDIO_BLK BIT(3) -struct wl1271_acx_host_config_bitmap { - struct acx_header header; - - __le32 host_cfg_bitmap; -} __packed; - enum { WL1271_ACX_TRIG_TYPE_LEVEL = 0, WL1271_ACX_TRIG_TYPE_EDGE, @@ -1274,7 +1269,6 @@ int wl1271_acx_frag_threshold(struct wl1271 *wl, u32 frag_threshold); int wl1271_acx_tx_config_options(struct wl1271 *wl); int wl12xx_acx_mem_cfg(struct wl1271 *wl); int wl1271_acx_init_mem_config(struct wl1271 *wl); -int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap); int wl1271_acx_init_rx_interrupt(struct wl1271 *wl); int wl1271_acx_smart_reflex(struct wl1271 *wl); int wl1271_acx_bet_enable(struct wl1271 *wl, struct wl12xx_vif *wlvif, diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index e80f674e77c..8407590cf6c 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c @@ -112,232 +112,6 @@ fail: return ret; } -int wl1271_cmd_general_parms(struct wl1271 *wl) -{ - struct wl1271_general_parms_cmd *gen_parms; - struct wl1271_ini_general_params *gp = - &((struct wl1271_nvs_file *)wl->nvs)->general_params; - bool answer = false; - int ret; - - if (!wl->nvs) - return -ENODEV; - - if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { - wl1271_warning("FEM index from INI out of bounds"); - return -EINVAL; - } - - gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); - if (!gen_parms) - return -ENOMEM; - - gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; - - memcpy(&gen_parms->general_params, gp, sizeof(*gp)); - - if (gp->tx_bip_fem_auto_detect) - answer = true; - - /* Override the REF CLK from the NVS with the one from platform data */ - gen_parms->general_params.ref_clock = wl->ref_clock; - - ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); - if (ret < 0) { - wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); - goto out; - } - - gp->tx_bip_fem_manufacturer = - gen_parms->general_params.tx_bip_fem_manufacturer; - - if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { - wl1271_warning("FEM index from FW out of bounds"); - ret = -EINVAL; - goto out; - } - - wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", - answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); - -out: - kfree(gen_parms); - return ret; -} - -int wl128x_cmd_general_parms(struct wl1271 *wl) -{ - struct wl128x_general_parms_cmd *gen_parms; - struct wl128x_ini_general_params *gp = - &((struct wl128x_nvs_file *)wl->nvs)->general_params; - bool answer = false; - int ret; - - if (!wl->nvs) - return -ENODEV; - - if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { - wl1271_warning("FEM index from ini out of bounds"); - return -EINVAL; - } - - gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); - if (!gen_parms) - return -ENOMEM; - - gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; - - memcpy(&gen_parms->general_params, gp, sizeof(*gp)); - - if (gp->tx_bip_fem_auto_detect) - answer = true; - - /* Replace REF and TCXO CLKs with the ones from platform data */ - gen_parms->general_params.ref_clock = wl->ref_clock; - gen_parms->general_params.tcxo_ref_clock = wl->tcxo_clock; - - ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); - if (ret < 0) { - wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); - goto out; - } - - gp->tx_bip_fem_manufacturer = - gen_parms->general_params.tx_bip_fem_manufacturer; - - if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { - wl1271_warning("FEM index from FW out of bounds"); - ret = -EINVAL; - goto out; - } - - wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", - answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); - -out: - kfree(gen_parms); - return ret; -} - -int wl1271_cmd_radio_parms(struct wl1271 *wl) -{ - struct wl1271_nvs_file *nvs = (struct wl1271_nvs_file *)wl->nvs; - struct wl1271_radio_parms_cmd *radio_parms; - struct wl1271_ini_general_params *gp = &nvs->general_params; - int ret; - - if (!wl->nvs) - return -ENODEV; - - radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL); - if (!radio_parms) - return -ENOMEM; - - radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; - - /* 2.4GHz parameters */ - memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2, - sizeof(struct wl1271_ini_band_params_2)); - memcpy(&radio_parms->dyn_params_2, - &nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params, - sizeof(struct wl1271_ini_fem_params_2)); - - /* 5GHz parameters */ - memcpy(&radio_parms->static_params_5, - &nvs->stat_radio_params_5, - sizeof(struct wl1271_ini_band_params_5)); - memcpy(&radio_parms->dyn_params_5, - &nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params, - sizeof(struct wl1271_ini_fem_params_5)); - - wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", - radio_parms, sizeof(*radio_parms)); - - ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0); - if (ret < 0) - wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed"); - - kfree(radio_parms); - return ret; -} - -int wl128x_cmd_radio_parms(struct wl1271 *wl) -{ - struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs; - struct wl128x_radio_parms_cmd *radio_parms; - struct wl128x_ini_general_params *gp = &nvs->general_params; - int ret; - - if (!wl->nvs) - return -ENODEV; - - radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL); - if (!radio_parms) - return -ENOMEM; - - radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; - - /* 2.4GHz parameters */ - memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2, - sizeof(struct wl128x_ini_band_params_2)); - memcpy(&radio_parms->dyn_params_2, - &nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params, - sizeof(struct wl128x_ini_fem_params_2)); - - /* 5GHz parameters */ - memcpy(&radio_parms->static_params_5, - &nvs->stat_radio_params_5, - sizeof(struct wl128x_ini_band_params_5)); - memcpy(&radio_parms->dyn_params_5, - &nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params, - sizeof(struct wl128x_ini_fem_params_5)); - - radio_parms->fem_vendor_and_options = nvs->fem_vendor_and_options; - - wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", - radio_parms, sizeof(*radio_parms)); - - ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0); - if (ret < 0) - wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed"); - - kfree(radio_parms); - return ret; -} - -int wl1271_cmd_ext_radio_parms(struct wl1271 *wl) -{ - struct wl1271_ext_radio_parms_cmd *ext_radio_parms; - struct conf_rf_settings *rf = &wl->conf.rf; - int ret; - - if (!wl->nvs) - return -ENODEV; - - ext_radio_parms = kzalloc(sizeof(*ext_radio_parms), GFP_KERNEL); - if (!ext_radio_parms) - return -ENOMEM; - - ext_radio_parms->test.id = TEST_CMD_INI_FILE_RF_EXTENDED_PARAM; - - memcpy(ext_radio_parms->tx_per_channel_power_compensation_2, - rf->tx_per_channel_power_compensation_2, - CONF_TX_PWR_COMPENSATION_LEN_2); - memcpy(ext_radio_parms->tx_per_channel_power_compensation_5, - rf->tx_per_channel_power_compensation_5, - CONF_TX_PWR_COMPENSATION_LEN_5); - - wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_EXT_RADIO_PARAM: ", - ext_radio_parms, sizeof(*ext_radio_parms)); - - ret = wl1271_cmd_test(wl, ext_radio_parms, sizeof(*ext_radio_parms), 0); - if (ret < 0) - wl1271_warning("TEST_CMD_INI_FILE_RF_EXTENDED_PARAM failed"); - - kfree(ext_radio_parms); - return ret; -} - /* * Poll the mailbox event field until any of the bits in the mask is set or a * timeout occurs (WL1271_EVENT_TIMEOUT in msecs) @@ -913,6 +687,7 @@ int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer) return ret; } +EXPORT_SYMBOL_GPL(wl1271_cmd_test); /** * read acx from firmware @@ -969,6 +744,7 @@ int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len) return 0; } +EXPORT_SYMBOL_GPL(wl1271_cmd_configure); int wl1271_cmd_data_path(struct wl1271 *wl, bool enable) { diff --git a/drivers/net/wireless/ti/wlcore/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h index cd1eb2eef90..a46ae07cb77 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.h +++ b/drivers/net/wireless/ti/wlcore/cmd.h @@ -31,11 +31,6 @@ struct acx_header; int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, size_t res_len); -int wl1271_cmd_general_parms(struct wl1271 *wl); -int wl128x_cmd_general_parms(struct wl1271 *wl); -int wl1271_cmd_radio_parms(struct wl1271 *wl); -int wl128x_cmd_radio_parms(struct wl1271 *wl); -int wl1271_cmd_ext_radio_parms(struct wl1271 *wl); int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 *addr, u8 role_type, u8 *role_id); int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id); @@ -494,83 +489,6 @@ enum wl1271_channel_tune_bands { #define WL1271_PD_REFERENCE_POINT_BAND_B_G 0 -#define TEST_CMD_INI_FILE_RADIO_PARAM 0x19 -#define TEST_CMD_INI_FILE_GENERAL_PARAM 0x1E -#define TEST_CMD_INI_FILE_RF_EXTENDED_PARAM 0x26 - -struct wl1271_general_parms_cmd { - struct wl1271_cmd_header header; - - struct wl1271_cmd_test_header test; - - struct wl1271_ini_general_params general_params; - - u8 sr_debug_table[WL1271_INI_MAX_SMART_REFLEX_PARAM]; - u8 sr_sen_n_p; - u8 sr_sen_n_p_gain; - u8 sr_sen_nrn; - u8 sr_sen_prn; - u8 padding[3]; -} __packed; - -struct wl128x_general_parms_cmd { - struct wl1271_cmd_header header; - - struct wl1271_cmd_test_header test; - - struct wl128x_ini_general_params general_params; - - u8 sr_debug_table[WL1271_INI_MAX_SMART_REFLEX_PARAM]; - u8 sr_sen_n_p; - u8 sr_sen_n_p_gain; - u8 sr_sen_nrn; - u8 sr_sen_prn; - u8 padding[3]; -} __packed; - -struct wl1271_radio_parms_cmd { - struct wl1271_cmd_header header; - - struct wl1271_cmd_test_header test; - - /* Static radio parameters */ - struct wl1271_ini_band_params_2 static_params_2; - struct wl1271_ini_band_params_5 static_params_5; - - /* Dynamic radio parameters */ - struct wl1271_ini_fem_params_2 dyn_params_2; - u8 padding2; - struct wl1271_ini_fem_params_5 dyn_params_5; - u8 padding3[2]; -} __packed; - -struct wl128x_radio_parms_cmd { - struct wl1271_cmd_header header; - - struct wl1271_cmd_test_header test; - - /* Static radio parameters */ - struct wl128x_ini_band_params_2 static_params_2; - struct wl128x_ini_band_params_5 static_params_5; - - u8 fem_vendor_and_options; - - /* Dynamic radio parameters */ - struct wl128x_ini_fem_params_2 dyn_params_2; - u8 padding2; - struct wl128x_ini_fem_params_5 dyn_params_5; -} __packed; - -struct wl1271_ext_radio_parms_cmd { - struct wl1271_cmd_header header; - - struct wl1271_cmd_test_header test; - - u8 tx_per_channel_power_compensation_2[CONF_TX_PWR_COMPENSATION_LEN_2]; - u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5]; - u8 padding[3]; -} __packed; - /* * There are three types of disconnections: * diff --git a/drivers/net/wireless/ti/wlcore/init.c b/drivers/net/wireless/ti/wlcore/init.c index c332da2f1cb..afe4f753f70 100644 --- a/drivers/net/wireless/ti/wlcore/init.c +++ b/drivers/net/wireless/ti/wlcore/init.c @@ -493,26 +493,6 @@ static int wl1271_set_ba_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif) return wl12xx_acx_set_ba_initiator_policy(wl, wlvif); } -int wl1271_chip_specific_init(struct wl1271 *wl) -{ - int ret = 0; - - if (wl->chip.id == CHIP_ID_1283_PG20) { - u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE; - - if (wl->quirks & WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN) - /* Enable SDIO padding */ - host_cfg_bitmap |= HOST_IF_CFG_TX_PAD_TO_SDIO_BLK; - - /* Must be before wl1271_acx_init_mem_config() */ - ret = wl1271_acx_host_if_cfg_bitmap(wl, host_cfg_bitmap); - if (ret < 0) - goto out; - } -out: - return ret; -} - /* vif-specifc initialization */ static int wl12xx_init_sta_role(struct wl1271 *wl, struct wl12xx_vif *wlvif) { @@ -665,27 +645,8 @@ int wl1271_hw_init(struct wl1271 *wl) { int ret; - if (wl->chip.id == CHIP_ID_1283_PG20) { - ret = wl128x_cmd_general_parms(wl); - if (ret < 0) - return ret; - ret = wl128x_cmd_radio_parms(wl); - if (ret < 0) - return ret; - } else { - ret = wl1271_cmd_general_parms(wl); - if (ret < 0) - return ret; - ret = wl1271_cmd_radio_parms(wl); - if (ret < 0) - return ret; - ret = wl1271_cmd_ext_radio_parms(wl); - if (ret < 0) - return ret; - } - - /* Chip-specific init */ - ret = wl1271_chip_specific_init(wl); + /* Chip-specific hw init */ + ret = wl->ops->hw_init(wl); if (ret < 0) return ret; diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 83be5be32ff..6a98013329d 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -672,28 +672,7 @@ static int wl1271_plt_init(struct wl1271 *wl) { int ret; - if (wl->chip.id == CHIP_ID_1283_PG20) - ret = wl128x_cmd_general_parms(wl); - else - ret = wl1271_cmd_general_parms(wl); - if (ret < 0) - return ret; - - if (wl->chip.id == CHIP_ID_1283_PG20) - ret = wl128x_cmd_radio_parms(wl); - else - ret = wl1271_cmd_radio_parms(wl); - if (ret < 0) - return ret; - - if (wl->chip.id != CHIP_ID_1283_PG20) { - ret = wl1271_cmd_ext_radio_parms(wl); - if (ret < 0) - return ret; - } - - /* Chip-specific initializations */ - ret = wl1271_chip_specific_init(wl); + ret = wl->ops->hw_init(wl); if (ret < 0) return ret; diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index db7ad71a11e..91ccd1e3638 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h @@ -53,6 +53,7 @@ struct wlcore_ops { u32 data_len); void (*tx_delayed_compl)(struct wl1271 *wl); void (*tx_immediate_compl)(struct wl1271 *wl); + int (*hw_init)(struct wl1271 *wl); s8 (*get_pg_ver)(struct wl1271 *wl); void (*get_mac)(struct wl1271 *wl); }; -- cgit v1.2.3-70-g09d2 From 5d10b1957d4dd7b5f854a224fb30cc564405d4d9 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Tue, 13 Dec 2011 12:27:22 +0200 Subject: wlcore/wl12xx: expand functionality of cmd_trigger HW op Change the cmd_trigger op to include the write of the command buffer. Also, instead of letting the lower driver access the cmd_box_addr element directly, we now pass the address in the trigger_cmd operation, so it doesn't have to be exported. Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wl12xx/main.c | 4 +++- drivers/net/wireless/ti/wlcore/cmd.c | 2 +- drivers/net/wireless/ti/wlcore/wlcore.h | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless/ti/wlcore/cmd.c') diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index 564ca914bfc..083e1d8be17 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c @@ -707,8 +707,10 @@ out: return ret; } -static void wl12xx_trigger_cmd(struct wl1271 *wl) +static void wl12xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr, + void *buf, size_t len) { + wl1271_write(wl, cmd_box_addr, buf, len, false); wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_CMD); } diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index 8407590cf6c..5c4716c6f04 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c @@ -70,7 +70,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, * TODO: we just need this because one bit is in a different * place. Is there any better way? */ - wl->ops->trigger_cmd(wl); + wl->ops->trigger_cmd(wl, wl->cmd_box_addr, buf, len); timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT); diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index 7e2881d3886..83f1d7cfd78 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h @@ -37,7 +37,8 @@ enum wl_rx_buf_align; struct wlcore_ops { int (*identify_chip)(struct wl1271 *wl); int (*boot)(struct wl1271 *wl); - void (*trigger_cmd)(struct wl1271 *wl); + void (*trigger_cmd)(struct wl1271 *wl, int cmd_box_addr, + void *buf, size_t len); void (*ack_event)(struct wl1271 *wl); u32 (*calc_tx_blocks)(struct wl1271 *wl, u32 len, u32 spare_blks); void (*set_tx_desc_blocks)(struct wl1271 *wl, -- cgit v1.2.3-70-g09d2