Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / net / wireless / ti / wl12xx / cmd.c
1 /*
2  * This file is part of wl12xx
3  *
4  * Copyright (C) 2009-2010 Nokia Corporation
5  * Copyright (C) 2011 Texas Instruments Inc.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * version 2 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19  * 02110-1301 USA
20  *
21  */
22
23 #include "../wlcore/cmd.h"
24 #include "../wlcore/debug.h"
25
26 #include "wl12xx.h"
27 #include "cmd.h"
28
29 int wl1271_cmd_ext_radio_parms(struct wl1271 *wl)
30 {
31         struct wl1271_ext_radio_parms_cmd *ext_radio_parms;
32         struct wl12xx_priv *priv = wl->priv;
33         struct wl12xx_conf_rf *rf = &priv->conf.rf;
34         int ret;
35
36         if (!wl->nvs)
37                 return -ENODEV;
38
39         ext_radio_parms = kzalloc(sizeof(*ext_radio_parms), GFP_KERNEL);
40         if (!ext_radio_parms)
41                 return -ENOMEM;
42
43         ext_radio_parms->test.id = TEST_CMD_INI_FILE_RF_EXTENDED_PARAM;
44
45         memcpy(ext_radio_parms->tx_per_channel_power_compensation_2,
46                rf->tx_per_channel_power_compensation_2,
47                CONF_TX_PWR_COMPENSATION_LEN_2);
48         memcpy(ext_radio_parms->tx_per_channel_power_compensation_5,
49                rf->tx_per_channel_power_compensation_5,
50                CONF_TX_PWR_COMPENSATION_LEN_5);
51
52         wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_EXT_RADIO_PARAM: ",
53                     ext_radio_parms, sizeof(*ext_radio_parms));
54
55         ret = wl1271_cmd_test(wl, ext_radio_parms, sizeof(*ext_radio_parms), 0);
56         if (ret < 0)
57                 wl1271_warning("TEST_CMD_INI_FILE_RF_EXTENDED_PARAM failed");
58
59         kfree(ext_radio_parms);
60         return ret;
61 }
62
63 int wl1271_cmd_general_parms(struct wl1271 *wl)
64 {
65         struct wl1271_general_parms_cmd *gen_parms;
66         struct wl1271_ini_general_params *gp =
67                 &((struct wl1271_nvs_file *)wl->nvs)->general_params;
68         struct wl12xx_priv *priv = wl->priv;
69         bool answer = false;
70         int ret;
71
72         if (!wl->nvs)
73                 return -ENODEV;
74
75         if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
76                 wl1271_warning("FEM index from INI out of bounds");
77                 return -EINVAL;
78         }
79
80         gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL);
81         if (!gen_parms)
82                 return -ENOMEM;
83
84         gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM;
85
86         memcpy(&gen_parms->general_params, gp, sizeof(*gp));
87
88         /* If we started in PLT FEM_DETECT mode, force auto detect */
89         if (wl->plt_mode == PLT_FEM_DETECT)
90                 gen_parms->general_params.tx_bip_fem_auto_detect = true;
91
92         if (gen_parms->general_params.tx_bip_fem_auto_detect)
93                 answer = true;
94
95         /* Override the REF CLK from the NVS with the one from platform data */
96         gen_parms->general_params.ref_clock = priv->ref_clock;
97
98         ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer);
99         if (ret < 0) {
100                 wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed");
101                 goto out;
102         }
103
104         gp->tx_bip_fem_manufacturer =
105                 gen_parms->general_params.tx_bip_fem_manufacturer;
106
107         if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
108                 wl1271_warning("FEM index from FW out of bounds");
109                 ret = -EINVAL;
110                 goto out;
111         }
112
113         /* If we are in calibrator based fem auto detect - save fem nr */
114         if (wl->plt_mode == PLT_FEM_DETECT)
115                 wl->fem_manuf = gp->tx_bip_fem_manufacturer;
116
117         wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n",
118                 answer == false ?
119                         "manual" :
120                 wl->plt_mode == PLT_FEM_DETECT ?
121                         "calibrator_fem_detect" :
122                         "auto",
123                 gp->tx_bip_fem_manufacturer);
124
125 out:
126         kfree(gen_parms);
127         return ret;
128 }
129
130 int wl128x_cmd_general_parms(struct wl1271 *wl)
131 {
132         struct wl128x_general_parms_cmd *gen_parms;
133         struct wl128x_ini_general_params *gp =
134                 &((struct wl128x_nvs_file *)wl->nvs)->general_params;
135         struct wl12xx_priv *priv = wl->priv;
136         bool answer = false;
137         int ret;
138
139         if (!wl->nvs)
140                 return -ENODEV;
141
142         if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
143                 wl1271_warning("FEM index from ini out of bounds");
144                 return -EINVAL;
145         }
146
147         gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL);
148         if (!gen_parms)
149                 return -ENOMEM;
150
151         gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM;
152
153         memcpy(&gen_parms->general_params, gp, sizeof(*gp));
154
155         /* If we started in PLT FEM_DETECT mode, force auto detect */
156         if (wl->plt_mode == PLT_FEM_DETECT)
157                 gen_parms->general_params.tx_bip_fem_auto_detect = true;
158
159         if (gen_parms->general_params.tx_bip_fem_auto_detect)
160                 answer = true;
161
162         /* Replace REF and TCXO CLKs with the ones from platform data */
163         gen_parms->general_params.ref_clock = priv->ref_clock;
164         gen_parms->general_params.tcxo_ref_clock = priv->tcxo_clock;
165
166         ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer);
167         if (ret < 0) {
168                 wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed");
169                 goto out;
170         }
171
172         gp->tx_bip_fem_manufacturer =
173                 gen_parms->general_params.tx_bip_fem_manufacturer;
174
175         if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
176                 wl1271_warning("FEM index from FW out of bounds");
177                 ret = -EINVAL;
178                 goto out;
179         }
180
181         /* If we are in calibrator based fem auto detect - save fem nr */
182         if (wl->plt_mode == PLT_FEM_DETECT)
183                 wl->fem_manuf = gp->tx_bip_fem_manufacturer;
184
185         wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n",
186                 answer == false ?
187                         "manual" :
188                 wl->plt_mode == PLT_FEM_DETECT ?
189                         "calibrator_fem_detect" :
190                         "auto",
191                 gp->tx_bip_fem_manufacturer);
192
193 out:
194         kfree(gen_parms);
195         return ret;
196 }
197
198 int wl1271_cmd_radio_parms(struct wl1271 *wl)
199 {
200         struct wl1271_nvs_file *nvs = (struct wl1271_nvs_file *)wl->nvs;
201         struct wl1271_radio_parms_cmd *radio_parms;
202         struct wl1271_ini_general_params *gp = &nvs->general_params;
203         int ret, fem_idx;
204
205         if (!wl->nvs)
206                 return -ENODEV;
207
208         radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL);
209         if (!radio_parms)
210                 return -ENOMEM;
211
212         radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM;
213
214         fem_idx = WL12XX_FEM_TO_NVS_ENTRY(gp->tx_bip_fem_manufacturer);
215
216         /* 2.4GHz parameters */
217         memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2,
218                sizeof(struct wl1271_ini_band_params_2));
219         memcpy(&radio_parms->dyn_params_2,
220                &nvs->dyn_radio_params_2[fem_idx].params,
221                sizeof(struct wl1271_ini_fem_params_2));
222
223         /* 5GHz parameters */
224         memcpy(&radio_parms->static_params_5,
225                &nvs->stat_radio_params_5,
226                sizeof(struct wl1271_ini_band_params_5));
227         memcpy(&radio_parms->dyn_params_5,
228                &nvs->dyn_radio_params_5[fem_idx].params,
229                sizeof(struct wl1271_ini_fem_params_5));
230
231         wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ",
232                     radio_parms, sizeof(*radio_parms));
233
234         ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0);
235         if (ret < 0)
236                 wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed");
237
238         kfree(radio_parms);
239         return ret;
240 }
241
242 int wl128x_cmd_radio_parms(struct wl1271 *wl)
243 {
244         struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs;
245         struct wl128x_radio_parms_cmd *radio_parms;
246         struct wl128x_ini_general_params *gp = &nvs->general_params;
247         int ret, fem_idx;
248
249         if (!wl->nvs)
250                 return -ENODEV;
251
252         radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL);
253         if (!radio_parms)
254                 return -ENOMEM;
255
256         radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM;
257
258         fem_idx = WL12XX_FEM_TO_NVS_ENTRY(gp->tx_bip_fem_manufacturer);
259
260         /* 2.4GHz parameters */
261         memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2,
262                sizeof(struct wl128x_ini_band_params_2));
263         memcpy(&radio_parms->dyn_params_2,
264                &nvs->dyn_radio_params_2[fem_idx].params,
265                sizeof(struct wl128x_ini_fem_params_2));
266
267         /* 5GHz parameters */
268         memcpy(&radio_parms->static_params_5,
269                &nvs->stat_radio_params_5,
270                sizeof(struct wl128x_ini_band_params_5));
271         memcpy(&radio_parms->dyn_params_5,
272                &nvs->dyn_radio_params_5[fem_idx].params,
273                sizeof(struct wl128x_ini_fem_params_5));
274
275         radio_parms->fem_vendor_and_options = nvs->fem_vendor_and_options;
276
277         wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ",
278                     radio_parms, sizeof(*radio_parms));
279
280         ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0);
281         if (ret < 0)
282                 wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed");
283
284         kfree(radio_parms);
285         return ret;
286 }
287
288 int wl12xx_cmd_channel_switch(struct wl1271 *wl,
289                               struct wl12xx_vif *wlvif,
290                               struct ieee80211_channel_switch *ch_switch)
291 {
292         struct wl12xx_cmd_channel_switch *cmd;
293         int ret;
294
295         wl1271_debug(DEBUG_ACX, "cmd channel switch");
296
297         cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
298         if (!cmd) {
299                 ret = -ENOMEM;
300                 goto out;
301         }
302
303         cmd->role_id = wlvif->role_id;
304         cmd->channel = ch_switch->chandef.chan->hw_value;
305         cmd->switch_time = ch_switch->count;
306         cmd->stop_tx = ch_switch->block_tx;
307
308         /* FIXME: control from mac80211 in the future */
309         /* Enable TX on the target channel */
310         cmd->post_switch_tx_disable = 0;
311
312         ret = wl1271_cmd_send(wl, CMD_CHANNEL_SWITCH, cmd, sizeof(*cmd), 0);
313         if (ret < 0) {
314                 wl1271_error("failed to send channel switch command");
315                 goto out_free;
316         }
317
318 out_free:
319         kfree(cmd);
320
321 out:
322         return ret;
323 }