init.c revision 0e71bb084adc4986b9a4be3581897f0ee703cbd5
12f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo/* 280301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valo * This file is part of wl1251 32f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo * 42f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo * Copyright (C) 2009 Nokia Corporation 52f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo * 62f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo * Contact: Kalle Valo <kalle.valo@nokia.com> 72f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo * 82f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo * This program is free software; you can redistribute it and/or 92f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo * modify it under the terms of the GNU General Public License 102f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo * version 2 as published by the Free Software Foundation. 112f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo * 122f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo * This program is distributed in the hope that it will be useful, but 132f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo * WITHOUT ANY WARRANTY; without even the implied warranty of 142f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 152f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo * General Public License for more details. 162f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo * 172f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo * You should have received a copy of the GNU General Public License 182f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo * along with this program; if not, write to the Free Software 192f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 202f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo * 02110-1301 USA 212f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo * 222f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo */ 232f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 242f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo#include <linux/kernel.h> 252f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo#include <linux/module.h> 262f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 27ef2f8d45771490de5b8373c25e983ee1e3aee9eaKalle Valo#include "wl1251_init.h" 282f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo#include "wl12xx_80211.h" 29ef2f8d45771490de5b8373c25e983ee1e3aee9eaKalle Valo#include "wl1251_acx.h" 30ef2f8d45771490de5b8373c25e983ee1e3aee9eaKalle Valo#include "wl1251_cmd.h" 310e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo#include "reg.h" 322f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 3380301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valoint wl1251_hw_init_hwenc_config(struct wl1251 *wl) 342f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo{ 352f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo int ret; 362f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 3780301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valo ret = wl1251_acx_feature_cfg(wl); 382f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo if (ret < 0) { 3980301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valo wl1251_warning("couldn't set feature config"); 402f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return ret; 412f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo } 422f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 4380301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valo ret = wl1251_acx_default_key(wl, wl->default_key); 442f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo if (ret < 0) { 4580301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valo wl1251_warning("couldn't set default key"); 462f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return ret; 472f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo } 482f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 492f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return 0; 502f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo} 512f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 5280301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valoint wl1251_hw_init_templates_config(struct wl1251 *wl) 532f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo{ 542f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo int ret; 552f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo u8 partial_vbm[PARTIAL_VBM_MAX]; 562f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 572f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo /* send empty templates for fw memory reservation */ 5880301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valo ret = wl1251_cmd_template_set(wl, CMD_PROBE_REQ, NULL, 592f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo sizeof(struct wl12xx_probe_req_template)); 602f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo if (ret < 0) 612f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return ret; 622f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 6380301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valo ret = wl1251_cmd_template_set(wl, CMD_NULL_DATA, NULL, 642f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo sizeof(struct wl12xx_null_data_template)); 652f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo if (ret < 0) 662f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return ret; 672f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 6880301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valo ret = wl1251_cmd_template_set(wl, CMD_PS_POLL, NULL, 692f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo sizeof(struct wl12xx_ps_poll_template)); 702f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo if (ret < 0) 712f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return ret; 722f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 7380301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valo ret = wl1251_cmd_template_set(wl, CMD_QOS_NULL_DATA, NULL, 742f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo sizeof 752f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo (struct wl12xx_qos_null_data_template)); 762f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo if (ret < 0) 772f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return ret; 782f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 7980301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valo ret = wl1251_cmd_template_set(wl, CMD_PROBE_RESP, NULL, 802f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo sizeof 812f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo (struct wl12xx_probe_resp_template)); 822f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo if (ret < 0) 832f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return ret; 842f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 8580301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valo ret = wl1251_cmd_template_set(wl, CMD_BEACON, NULL, 862f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo sizeof 872f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo (struct wl12xx_beacon_template)); 882f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo if (ret < 0) 892f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return ret; 902f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 912f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo /* tim templates, first reserve space then allocate an empty one */ 922f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo memset(partial_vbm, 0, PARTIAL_VBM_MAX); 9380301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valo ret = wl1251_cmd_vbm(wl, TIM_ELE_ID, partial_vbm, PARTIAL_VBM_MAX, 0); 942f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo if (ret < 0) 952f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return ret; 962f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 9780301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valo ret = wl1251_cmd_vbm(wl, TIM_ELE_ID, partial_vbm, 1, 0); 982f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo if (ret < 0) 992f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return ret; 1002f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 1012f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return 0; 1022f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo} 1032f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 10480301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valoint wl1251_hw_init_rx_config(struct wl1251 *wl, u32 config, u32 filter) 1052f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo{ 1062f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo int ret; 1072f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 10880301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valo ret = wl1251_acx_rx_msdu_life_time(wl, RX_MSDU_LIFETIME_DEF); 1092f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo if (ret < 0) 1102f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return ret; 1112f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 11280301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valo ret = wl1251_acx_rx_config(wl, config, filter); 1132f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo if (ret < 0) 1142f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return ret; 1152f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 1162f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return 0; 1172f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo} 1182f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 11980301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valoint wl1251_hw_init_phy_config(struct wl1251 *wl) 1202f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo{ 1212f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo int ret; 1222f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 12380301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valo ret = wl1251_acx_pd_threshold(wl); 1242f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo if (ret < 0) 1252f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return ret; 1262f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 12780301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valo ret = wl1251_acx_slot(wl, DEFAULT_SLOT_TIME); 1282f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo if (ret < 0) 1292f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return ret; 1302f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 13180301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valo ret = wl1251_acx_group_address_tbl(wl); 1322f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo if (ret < 0) 1332f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return ret; 1342f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 13580301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valo ret = wl1251_acx_service_period_timeout(wl); 1362f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo if (ret < 0) 1372f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return ret; 1382f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 13980301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valo ret = wl1251_acx_rts_threshold(wl, RTS_THRESHOLD_DEF); 1402f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo if (ret < 0) 1412f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return ret; 1422f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 1432f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return 0; 1442f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo} 1452f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 14680301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valoint wl1251_hw_init_beacon_filter(struct wl1251 *wl) 1472f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo{ 1482f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo int ret; 1492f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 15080301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valo ret = wl1251_acx_beacon_filter_opt(wl); 1512f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo if (ret < 0) 1522f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return ret; 1532f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 15480301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valo ret = wl1251_acx_beacon_filter_table(wl); 1552f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo if (ret < 0) 1562f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return ret; 1572f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 1582f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return 0; 1592f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo} 1602f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 16180301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valoint wl1251_hw_init_pta(struct wl1251 *wl) 1622f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo{ 1632f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo int ret; 1642f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 16580301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valo ret = wl1251_acx_sg_enable(wl); 1662f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo if (ret < 0) 1672f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return ret; 1682f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 16980301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valo ret = wl1251_acx_sg_cfg(wl); 1702f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo if (ret < 0) 1712f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return ret; 1722f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 1732f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return 0; 1742f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo} 1752f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 17680301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valoint wl1251_hw_init_energy_detection(struct wl1251 *wl) 1772f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo{ 1782f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo int ret; 1792f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 18080301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valo ret = wl1251_acx_cca_threshold(wl); 1812f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo if (ret < 0) 1822f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return ret; 1832f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 1842f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return 0; 1852f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo} 1862f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 18780301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valoint wl1251_hw_init_beacon_broadcast(struct wl1251 *wl) 1882f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo{ 1892f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo int ret; 1902f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 19180301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valo ret = wl1251_acx_bcn_dtim_options(wl); 1922f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo if (ret < 0) 1932f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return ret; 1942f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 1952f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo return 0; 1962f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo} 1972f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo 19880301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valoint wl1251_hw_init_power_auth(struct wl1251 *wl) 1992f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo{ 20080301cdcfe44e3533175be23d7d52a9fc8c3fdb0Kalle Valo return wl1251_acx_sleep_auth(wl, WL1251_PSM_CAM); 2012f01a1f58889fbfeb68b1bc1b52e4197f3333490Kalle Valo} 2020e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 2030e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valoint wl1251_hw_init_mem_config(struct wl1251 *wl) 2040e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo{ 2050e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo int ret; 2060e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 2070e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo ret = wl1251_acx_mem_cfg(wl); 2080e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo if (ret < 0) 2090e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo return ret; 2100e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 2110e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo wl->target_mem_map = kzalloc(sizeof(struct wl1251_acx_mem_map), 2120e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo GFP_KERNEL); 2130e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo if (!wl->target_mem_map) { 2140e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo wl1251_error("couldn't allocate target memory map"); 2150e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo return -ENOMEM; 2160e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo } 2170e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 2180e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo /* we now ask for the firmware built memory map */ 2190e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo ret = wl1251_acx_mem_map(wl, wl->target_mem_map, 2200e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo sizeof(struct wl1251_acx_mem_map)); 2210e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo if (ret < 0) { 2220e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo wl1251_error("couldn't retrieve firmware memory map"); 2230e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo kfree(wl->target_mem_map); 2240e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo wl->target_mem_map = NULL; 2250e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo return ret; 2260e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo } 2270e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 2280e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo return 0; 2290e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo} 2300e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 2310e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valostatic int wl1251_hw_init_txq_fill(u8 qid, 2320e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo struct acx_tx_queue_qos_config *config, 2330e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo u32 num_blocks) 2340e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo{ 2350e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo config->qid = qid; 2360e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 2370e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo switch (qid) { 2380e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo case QOS_AC_BE: 2390e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo config->high_threshold = 2400e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo (QOS_TX_HIGH_BE_DEF * num_blocks) / 100; 2410e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo config->low_threshold = 2420e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo (QOS_TX_LOW_BE_DEF * num_blocks) / 100; 2430e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo break; 2440e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo case QOS_AC_BK: 2450e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo config->high_threshold = 2460e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo (QOS_TX_HIGH_BK_DEF * num_blocks) / 100; 2470e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo config->low_threshold = 2480e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo (QOS_TX_LOW_BK_DEF * num_blocks) / 100; 2490e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo break; 2500e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo case QOS_AC_VI: 2510e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo config->high_threshold = 2520e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo (QOS_TX_HIGH_VI_DEF * num_blocks) / 100; 2530e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo config->low_threshold = 2540e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo (QOS_TX_LOW_VI_DEF * num_blocks) / 100; 2550e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo break; 2560e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo case QOS_AC_VO: 2570e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo config->high_threshold = 2580e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo (QOS_TX_HIGH_VO_DEF * num_blocks) / 100; 2590e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo config->low_threshold = 2600e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo (QOS_TX_LOW_VO_DEF * num_blocks) / 100; 2610e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo break; 2620e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo default: 2630e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo wl1251_error("Invalid TX queue id: %d", qid); 2640e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo return -EINVAL; 2650e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo } 2660e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 2670e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo return 0; 2680e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo} 2690e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 2700e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valostatic int wl1251_hw_init_tx_queue_config(struct wl1251 *wl) 2710e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo{ 2720e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo struct acx_tx_queue_qos_config *config; 2730e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo struct wl1251_acx_mem_map *wl_mem_map = wl->target_mem_map; 2740e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo int ret, i; 2750e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 2760e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo wl1251_debug(DEBUG_ACX, "acx tx queue config"); 2770e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 2780e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo config = kzalloc(sizeof(*config), GFP_KERNEL); 2790e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo if (!config) { 2800e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo ret = -ENOMEM; 2810e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo goto out; 2820e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo } 2830e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 2840e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo for (i = 0; i < MAX_NUM_OF_AC; i++) { 2850e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo ret = wl1251_hw_init_txq_fill(i, config, 2860e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo wl_mem_map->num_tx_mem_blocks); 2870e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo if (ret < 0) 2880e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo goto out; 2890e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 2900e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo ret = wl1251_cmd_configure(wl, ACX_TX_QUEUE_CFG, 2910e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo config, sizeof(*config)); 2920e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo if (ret < 0) 2930e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo goto out; 2940e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo } 2950e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 2960e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valoout: 2970e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo kfree(config); 2980e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo return ret; 2990e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo} 3000e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 3010e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valostatic int wl1251_hw_init_data_path_config(struct wl1251 *wl) 3020e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo{ 3030e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo int ret; 3040e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 3050e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo /* asking for the data path parameters */ 3060e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo wl->data_path = kzalloc(sizeof(struct acx_data_path_params_resp), 3070e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo GFP_KERNEL); 3080e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo if (!wl->data_path) { 3090e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo wl1251_error("Couldnt allocate data path parameters"); 3100e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo return -ENOMEM; 3110e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo } 3120e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 3130e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo ret = wl1251_acx_data_path_params(wl, wl->data_path); 3140e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo if (ret < 0) { 3150e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo kfree(wl->data_path); 3160e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo wl->data_path = NULL; 3170e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo return ret; 3180e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo } 3190e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 3200e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo return 0; 3210e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo} 3220e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 3230e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 3240e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valoint wl1251_hw_init(struct wl1251 *wl) 3250e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo{ 3260e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo struct wl1251_acx_mem_map *wl_mem_map; 3270e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo int ret; 3280e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 3290e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo ret = wl1251_hw_init_hwenc_config(wl); 3300e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo if (ret < 0) 3310e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo return ret; 3320e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 3330e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo /* Template settings */ 3340e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo ret = wl1251_hw_init_templates_config(wl); 3350e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo if (ret < 0) 3360e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo return ret; 3370e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 3380e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo /* Default memory configuration */ 3390e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo ret = wl1251_hw_init_mem_config(wl); 3400e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo if (ret < 0) 3410e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo return ret; 3420e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 3430e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo /* Default data path configuration */ 3440e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo ret = wl1251_hw_init_data_path_config(wl); 3450e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo if (ret < 0) 3460e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo goto out_free_memmap; 3470e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 3480e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo /* RX config */ 3490e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo ret = wl1251_hw_init_rx_config(wl, 3500e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo RX_CFG_PROMISCUOUS | RX_CFG_TSF, 3510e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo RX_FILTER_OPTION_DEF); 3520e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo /* RX_CONFIG_OPTION_ANY_DST_ANY_BSS, 3530e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo RX_FILTER_OPTION_FILTER_ALL); */ 3540e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo if (ret < 0) 3550e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo goto out_free_data_path; 3560e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 3570e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo /* TX queues config */ 3580e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo ret = wl1251_hw_init_tx_queue_config(wl); 3590e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo if (ret < 0) 3600e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo goto out_free_data_path; 3610e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 3620e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo /* PHY layer config */ 3630e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo ret = wl1251_hw_init_phy_config(wl); 3640e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo if (ret < 0) 3650e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo goto out_free_data_path; 3660e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 3670e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo /* Beacon filtering */ 3680e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo ret = wl1251_hw_init_beacon_filter(wl); 3690e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo if (ret < 0) 3700e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo goto out_free_data_path; 3710e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 3720e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo /* Bluetooth WLAN coexistence */ 3730e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo ret = wl1251_hw_init_pta(wl); 3740e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo if (ret < 0) 3750e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo goto out_free_data_path; 3760e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 3770e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo /* Energy detection */ 3780e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo ret = wl1251_hw_init_energy_detection(wl); 3790e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo if (ret < 0) 3800e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo goto out_free_data_path; 3810e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 3820e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo /* Beacons and boradcast settings */ 3830e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo ret = wl1251_hw_init_beacon_broadcast(wl); 3840e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo if (ret < 0) 3850e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo goto out_free_data_path; 3860e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 3870e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo /* Enable data path */ 3880e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo ret = wl1251_cmd_data_path(wl, wl->channel, 1); 3890e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo if (ret < 0) 3900e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo goto out_free_data_path; 3910e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 3920e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo /* Default power state */ 3930e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo ret = wl1251_hw_init_power_auth(wl); 3940e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo if (ret < 0) 3950e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo goto out_free_data_path; 3960e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 3970e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo wl_mem_map = wl->target_mem_map; 3980e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo wl1251_info("%d tx blocks at 0x%x, %d rx blocks at 0x%x", 3990e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo wl_mem_map->num_tx_mem_blocks, 4000e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo wl->data_path->tx_control_addr, 4010e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo wl_mem_map->num_rx_mem_blocks, 4020e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo wl->data_path->rx_control_addr); 4030e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 4040e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo return 0; 4050e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 4060e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo out_free_data_path: 4070e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo kfree(wl->data_path); 4080e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 4090e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo out_free_memmap: 4100e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo kfree(wl->target_mem_map); 4110e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo 4120e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo return ret; 4130e71bb084adc4986b9a4be3581897f0ee703cbd5Kalle Valo} 414