2 * Copyright (c) 2010 Broadcom Corporation
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include <linux/kernel.h>
18 #include <linux/string.h>
19 #include <linux/netdevice.h>
20 #include <linux/module.h>
21 #include <linux/firmware.h>
22 #include <brcmu_wifi.h>
23 #include <brcmu_utils.h>
28 #include "fwil_types.h"
29 #include "tracepoint.h"
35 MODULE_AUTHOR("Broadcom Corporation");
36 MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
37 MODULE_LICENSE("Dual BSD/GPL");
39 #define BRCMF_DEFAULT_SCAN_CHANNEL_TIME 40
40 #define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40
42 /* default boost value for RSSI_DELTA in preferred join selection */
43 #define BRCMF_JOIN_PREF_RSSI_BOOST 8
45 #define BRCMF_DEFAULT_TXGLOM_SIZE 32 /* max tx frames in glom chain */
47 static int brcmf_sdiod_txglomsz
= BRCMF_DEFAULT_TXGLOM_SIZE
;
48 module_param_named(txglomsz
, brcmf_sdiod_txglomsz
, int, 0);
49 MODULE_PARM_DESC(txglomsz
, "Maximum tx packet chain size [SDIO]");
51 /* Debug level configuration. See debug.h for bits, sysfs modifiable */
53 module_param_named(debug
, brcmf_msg_level
, int, 0600);
54 MODULE_PARM_DESC(debug
, "Level of debug output");
56 static int brcmf_p2p_enable
;
57 module_param_named(p2pon
, brcmf_p2p_enable
, int, 0);
58 MODULE_PARM_DESC(p2pon
, "Enable legacy p2p management functionality");
60 static int brcmf_feature_disable
;
61 module_param_named(feature_disable
, brcmf_feature_disable
, int, 0);
62 MODULE_PARM_DESC(feature_disable
, "Disable features");
64 static char brcmf_firmware_path
[BRCMF_FW_ALTPATH_LEN
];
65 module_param_string(alternative_fw_path
, brcmf_firmware_path
,
66 BRCMF_FW_ALTPATH_LEN
, 0400);
67 MODULE_PARM_DESC(alternative_fw_path
, "Alternative firmware path");
69 static int brcmf_fcmode
;
70 module_param_named(fcmode
, brcmf_fcmode
, int, 0);
71 MODULE_PARM_DESC(fcmode
, "Mode of firmware signalled flow control");
73 static int brcmf_roamoff
;
74 module_param_named(roamoff
, brcmf_roamoff
, int, 0400);
75 MODULE_PARM_DESC(roamoff
, "Do not use internal roaming engine");
77 static int brcmf_iapp_enable
;
78 module_param_named(iapp
, brcmf_iapp_enable
, int, 0);
79 MODULE_PARM_DESC(iapp
, "Enable partial support for the obsoleted Inter-Access Point Protocol");
82 /* always succeed brcmf_bus_started() */
83 static int brcmf_ignore_probe_fail
;
84 module_param_named(ignore_probe_fail
, brcmf_ignore_probe_fail
, int, 0);
85 MODULE_PARM_DESC(ignore_probe_fail
, "always succeed probe for debugging");
88 static struct brcmfmac_platform_data
*brcmfmac_pdata
;
89 struct brcmf_mp_global_t brcmf_mp_global
;
91 void brcmf_c_set_joinpref_default(struct brcmf_if
*ifp
)
93 struct brcmf_join_pref_params join_pref_params
[2];
96 /* Setup join_pref to select target by RSSI (boost on 5GHz) */
97 join_pref_params
[0].type
= BRCMF_JOIN_PREF_RSSI_DELTA
;
98 join_pref_params
[0].len
= 2;
99 join_pref_params
[0].rssi_gain
= BRCMF_JOIN_PREF_RSSI_BOOST
;
100 join_pref_params
[0].band
= WLC_BAND_5G
;
102 join_pref_params
[1].type
= BRCMF_JOIN_PREF_RSSI
;
103 join_pref_params
[1].len
= 2;
104 join_pref_params
[1].rssi_gain
= 0;
105 join_pref_params
[1].band
= 0;
106 err
= brcmf_fil_iovar_data_set(ifp
, "join_pref", join_pref_params
,
107 sizeof(join_pref_params
));
109 brcmf_err("Set join_pref error (%d)\n", err
);
112 static int brcmf_c_download(struct brcmf_if
*ifp
, u16 flag
,
113 struct brcmf_dload_data_le
*dload_buf
,
118 flag
|= (DLOAD_HANDLER_VER
<< DLOAD_FLAG_VER_SHIFT
);
119 dload_buf
->flag
= cpu_to_le16(flag
);
120 dload_buf
->dload_type
= cpu_to_le16(DL_TYPE_CLM
);
121 dload_buf
->len
= cpu_to_le32(len
);
122 dload_buf
->crc
= cpu_to_le32(0);
123 len
= sizeof(*dload_buf
) + len
- 1;
125 err
= brcmf_fil_iovar_data_set(ifp
, "clmload", dload_buf
, len
);
130 static int brcmf_c_process_clm_blob(struct brcmf_if
*ifp
)
132 struct brcmf_bus
*bus
= ifp
->drvr
->bus_if
;
133 struct brcmf_dload_data_le
*chunk_buf
;
134 const struct firmware
*clm
= NULL
;
135 u8 clm_name
[BRCMF_FW_NAME_LEN
];
139 u16 dl_flag
= DL_BEGIN
;
143 brcmf_dbg(TRACE
, "Enter\n");
145 memset(clm_name
, 0, sizeof(clm_name
));
146 err
= brcmf_bus_get_fwname(bus
, ".clm_blob", clm_name
);
148 brcmf_err("get CLM blob file name failed (%d)\n", err
);
152 err
= firmware_request_nowarn(&clm
, clm_name
, bus
->dev
);
154 brcmf_info("no clm_blob available (err=%d), device may have limited channels available\n",
159 chunk_buf
= kzalloc(sizeof(*chunk_buf
) + MAX_CHUNK_LEN
- 1, GFP_KERNEL
);
168 if (datalen
> MAX_CHUNK_LEN
) {
169 chunk_len
= MAX_CHUNK_LEN
;
174 memcpy(chunk_buf
->data
, clm
->data
+ cumulative_len
, chunk_len
);
176 err
= brcmf_c_download(ifp
, dl_flag
, chunk_buf
, chunk_len
);
178 dl_flag
&= ~DL_BEGIN
;
180 cumulative_len
+= chunk_len
;
181 datalen
-= chunk_len
;
182 } while ((datalen
> 0) && (err
== 0));
185 brcmf_err("clmload (%zu byte file) failed (%d); ",
187 /* Retrieve clmload_status and print */
188 err
= brcmf_fil_iovar_int_get(ifp
, "clmload_status", &status
);
190 brcmf_err("get clmload_status failed (%d)\n", err
);
192 brcmf_dbg(INFO
, "clmload_status=%d\n", status
);
198 release_firmware(clm
);
202 int brcmf_c_preinit_dcmds(struct brcmf_if
*ifp
)
204 s8 eventmask
[BRCMF_EVENTING_MASK_LEN
];
205 u8 buf
[BRCMF_DCMD_SMLEN
];
206 struct brcmf_bus
*bus
;
207 struct brcmf_rev_info_le revinfo
;
208 struct brcmf_rev_info
*ri
;
213 /* retreive mac address */
214 err
= brcmf_fil_iovar_data_get(ifp
, "cur_etheraddr", ifp
->mac_addr
,
215 sizeof(ifp
->mac_addr
));
217 brcmf_err("Retreiving cur_etheraddr failed, %d\n", err
);
220 memcpy(ifp
->drvr
->wiphy
->perm_addr
, ifp
->drvr
->mac
, ETH_ALEN
);
221 memcpy(ifp
->drvr
->mac
, ifp
->mac_addr
, sizeof(ifp
->drvr
->mac
));
223 bus
= ifp
->drvr
->bus_if
;
224 ri
= &ifp
->drvr
->revinfo
;
226 err
= brcmf_fil_cmd_data_get(ifp
, BRCMF_C_GET_REVINFO
,
227 &revinfo
, sizeof(revinfo
));
229 brcmf_err("retrieving revision info failed, %d\n", err
);
230 strlcpy(ri
->chipname
, "UNKNOWN", sizeof(ri
->chipname
));
232 ri
->vendorid
= le32_to_cpu(revinfo
.vendorid
);
233 ri
->deviceid
= le32_to_cpu(revinfo
.deviceid
);
234 ri
->radiorev
= le32_to_cpu(revinfo
.radiorev
);
235 ri
->corerev
= le32_to_cpu(revinfo
.corerev
);
236 ri
->boardid
= le32_to_cpu(revinfo
.boardid
);
237 ri
->boardvendor
= le32_to_cpu(revinfo
.boardvendor
);
238 ri
->boardrev
= le32_to_cpu(revinfo
.boardrev
);
239 ri
->driverrev
= le32_to_cpu(revinfo
.driverrev
);
240 ri
->ucoderev
= le32_to_cpu(revinfo
.ucoderev
);
241 ri
->bus
= le32_to_cpu(revinfo
.bus
);
242 ri
->phytype
= le32_to_cpu(revinfo
.phytype
);
243 ri
->phyrev
= le32_to_cpu(revinfo
.phyrev
);
244 ri
->anarev
= le32_to_cpu(revinfo
.anarev
);
245 ri
->chippkg
= le32_to_cpu(revinfo
.chippkg
);
246 ri
->nvramrev
= le32_to_cpu(revinfo
.nvramrev
);
248 /* use revinfo if not known yet */
250 bus
->chip
= le32_to_cpu(revinfo
.chipnum
);
251 bus
->chiprev
= le32_to_cpu(revinfo
.chiprev
);
257 brcmf_chip_name(bus
->chip
, bus
->chiprev
,
258 ri
->chipname
, sizeof(ri
->chipname
));
260 /* Do any CLM downloading */
261 err
= brcmf_c_process_clm_blob(ifp
);
263 brcmf_err("download CLM blob file failed, %d\n", err
);
267 /* query for 'ver' to get version info from firmware */
268 memset(buf
, 0, sizeof(buf
));
270 err
= brcmf_fil_iovar_data_get(ifp
, "ver", buf
, sizeof(buf
));
272 brcmf_err("Retreiving version information failed, %d\n",
279 /* Print fw version info */
280 brcmf_info("Firmware: %s %s\n", ri
->chipname
, buf
);
282 /* locate firmware version number for ethtool */
283 ptr
= strrchr(buf
, ' ') + 1;
284 strlcpy(ifp
->drvr
->fwver
, ptr
, sizeof(ifp
->drvr
->fwver
));
286 /* Query for 'clmver' to get CLM version info from firmware */
287 memset(buf
, 0, sizeof(buf
));
288 err
= brcmf_fil_iovar_data_get(ifp
, "clmver", buf
, sizeof(buf
));
290 brcmf_dbg(TRACE
, "retrieving clmver failed, %d\n", err
);
292 clmver
= (char *)buf
;
293 /* store CLM version for adding it to revinfo debugfs file */
294 memcpy(ifp
->drvr
->clmver
, clmver
, sizeof(ifp
->drvr
->clmver
));
296 /* Replace all newline/linefeed characters with space
299 strreplace(clmver
, '\n', ' ');
301 brcmf_dbg(INFO
, "CLM version = %s\n", clmver
);
305 err
= brcmf_fil_iovar_int_set(ifp
, "mpc", 1);
307 brcmf_err("failed setting mpc\n");
311 brcmf_c_set_joinpref_default(ifp
);
313 /* Setup event_msgs, enable E_IF */
314 err
= brcmf_fil_iovar_data_get(ifp
, "event_msgs", eventmask
,
315 BRCMF_EVENTING_MASK_LEN
);
317 brcmf_err("Get event_msgs error (%d)\n", err
);
320 setbit(eventmask
, BRCMF_E_IF
);
321 err
= brcmf_fil_iovar_data_set(ifp
, "event_msgs", eventmask
,
322 BRCMF_EVENTING_MASK_LEN
);
324 brcmf_err("Set event_msgs error (%d)\n", err
);
328 /* Setup default scan channel time */
329 err
= brcmf_fil_cmd_int_set(ifp
, BRCMF_C_SET_SCAN_CHANNEL_TIME
,
330 BRCMF_DEFAULT_SCAN_CHANNEL_TIME
);
332 brcmf_err("BRCMF_C_SET_SCAN_CHANNEL_TIME error (%d)\n",
337 /* Setup default scan unassoc time */
338 err
= brcmf_fil_cmd_int_set(ifp
, BRCMF_C_SET_SCAN_UNASSOC_TIME
,
339 BRCMF_DEFAULT_SCAN_UNASSOC_TIME
);
341 brcmf_err("BRCMF_C_SET_SCAN_UNASSOC_TIME error (%d)\n",
346 /* Enable tx beamforming, errors can be ignored (not supported) */
347 (void)brcmf_fil_iovar_int_set(ifp
, "txbf", 1);
352 #ifndef CONFIG_BRCM_TRACING
353 void __brcmf_err(const char *func
, const char *fmt
, ...)
355 struct va_format vaf
;
362 pr_err("%s: %pV", func
, &vaf
);
368 #if defined(CONFIG_BRCM_TRACING) || defined(CONFIG_BRCMDBG)
369 void __brcmf_dbg(u32 level
, const char *func
, const char *fmt
, ...)
371 struct va_format vaf
= {
378 if (brcmf_msg_level
& level
)
379 pr_debug("%s %pV", func
, &vaf
);
380 trace_brcmf_dbg(level
, func
, &vaf
);
385 static void brcmf_mp_attach(void)
387 /* If module param firmware path is set then this will always be used,
388 * if not set then if available use the platform data version. To make
389 * sure it gets initialized at all, always copy the module param version
391 strlcpy(brcmf_mp_global
.firmware_path
, brcmf_firmware_path
,
392 BRCMF_FW_ALTPATH_LEN
);
393 if ((brcmfmac_pdata
) && (brcmfmac_pdata
->fw_alternative_path
) &&
394 (brcmf_mp_global
.firmware_path
[0] == '\0')) {
395 strlcpy(brcmf_mp_global
.firmware_path
,
396 brcmfmac_pdata
->fw_alternative_path
,
397 BRCMF_FW_ALTPATH_LEN
);
401 struct brcmf_mp_device
*brcmf_get_module_param(struct device
*dev
,
402 enum brcmf_bus_type bus_type
,
403 u32 chip
, u32 chiprev
)
405 struct brcmf_mp_device
*settings
;
406 struct brcmfmac_pd_device
*device_pd
;
410 brcmf_dbg(INFO
, "Enter, bus=%d, chip=%d, rev=%d\n", bus_type
, chip
,
412 settings
= kzalloc(sizeof(*settings
), GFP_ATOMIC
);
416 /* start by using the module paramaters */
417 settings
->p2p_enable
= !!brcmf_p2p_enable
;
418 settings
->feature_disable
= brcmf_feature_disable
;
419 settings
->fcmode
= brcmf_fcmode
;
420 settings
->roamoff
= !!brcmf_roamoff
;
421 settings
->iapp
= !!brcmf_iapp_enable
;
423 settings
->ignore_probe_fail
= !!brcmf_ignore_probe_fail
;
426 if (bus_type
== BRCMF_BUSTYPE_SDIO
)
427 settings
->bus
.sdio
.txglomsz
= brcmf_sdiod_txglomsz
;
429 /* See if there is any device specific platform data configured */
431 if (brcmfmac_pdata
) {
432 for (i
= 0; i
< brcmfmac_pdata
->device_count
; i
++) {
433 device_pd
= &brcmfmac_pdata
->devices
[i
];
434 if ((device_pd
->bus_type
== bus_type
) &&
435 (device_pd
->id
== chip
) &&
436 ((device_pd
->rev
== chiprev
) ||
437 (device_pd
->rev
== -1))) {
438 brcmf_dbg(INFO
, "Platform data for device found\n");
439 settings
->country_codes
=
440 device_pd
->country_codes
;
441 if (device_pd
->bus_type
== BRCMF_BUSTYPE_SDIO
)
442 memcpy(&settings
->bus
.sdio
,
443 &device_pd
->bus
.sdio
,
444 sizeof(settings
->bus
.sdio
));
451 /* No platform data for this device, try OF (Open Firwmare) */
452 brcmf_of_probe(dev
, bus_type
, settings
);
457 void brcmf_release_module_param(struct brcmf_mp_device
*module_param
)
462 static int __init
brcmf_common_pd_probe(struct platform_device
*pdev
)
464 brcmf_dbg(INFO
, "Enter\n");
466 brcmfmac_pdata
= dev_get_platdata(&pdev
->dev
);
468 if (brcmfmac_pdata
->power_on
)
469 brcmfmac_pdata
->power_on();
474 static int brcmf_common_pd_remove(struct platform_device
*pdev
)
476 brcmf_dbg(INFO
, "Enter\n");
478 if (brcmfmac_pdata
->power_off
)
479 brcmfmac_pdata
->power_off();
484 static struct platform_driver brcmf_pd
= {
485 .remove
= brcmf_common_pd_remove
,
487 .name
= BRCMFMAC_PDATA_NAME
,
491 static int __init
brcmfmac_module_init(void)
495 /* Get the platform data (if available) for our devices */
496 err
= platform_driver_probe(&brcmf_pd
, brcmf_common_pd_probe
);
498 brcmf_dbg(INFO
, "No platform data available.\n");
500 /* Initialize global module paramaters */
503 /* Continue the initialization by registering the different busses */
504 err
= brcmf_core_init();
507 platform_driver_unregister(&brcmf_pd
);
513 static void __exit
brcmfmac_module_exit(void)
517 platform_driver_unregister(&brcmf_pd
);
520 module_init(brcmfmac_module_init
);
521 module_exit(brcmfmac_module_exit
);