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