2 * Intel Wireless Multicomm 3200 WiFi driver
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
39 #include <linux/kernel.h>
40 #include <linux/firmware.h>
50 static const char fw_barker
[] = "*WESTOPFORNOONE*";
53 * @op_code: Op code we're looking for.
54 * @index: There can be several instances of the same opcode within
55 * the firmware. Index specifies which one we're looking for.
57 static int iwm_fw_op_offset(struct iwm_priv
*iwm
, const struct firmware
*fw
,
58 u16 op_code
, u32 index
)
60 int offset
= -EINVAL
, fw_offset
;
63 struct iwm_fw_hdr_rec
*rec
;
68 /* We first need to look for the firmware barker */
69 if (memcmp(fw_ptr
, fw_barker
, IWM_HDR_BARKER_LEN
)) {
70 IWM_ERR(iwm
, "No barker string in this FW\n");
74 if (fw
->size
< IWM_HDR_LEN
) {
75 IWM_ERR(iwm
, "FW is too small (%zu)\n", fw
->size
);
79 fw_offset
+= IWM_HDR_BARKER_LEN
;
81 while (fw_offset
< fw
->size
) {
82 rec
= (struct iwm_fw_hdr_rec
*)(fw_ptr
+ fw_offset
);
84 IWM_DBG_FW(iwm
, DBG
, "FW: op_code: 0x%x, len: %d @ 0x%x\n",
85 rec
->op_code
, rec
->len
, fw_offset
);
87 if (rec
->op_code
== IWM_HDR_REC_OP_INVALID
) {
88 IWM_DBG_FW(iwm
, DBG
, "Reached INVALID op code\n");
92 if (rec
->op_code
== op_code
) {
93 if (op_index
== index
) {
94 fw_offset
+= sizeof(struct iwm_fw_hdr_rec
);
101 fw_offset
+= sizeof(struct iwm_fw_hdr_rec
) + rec
->len
;
108 static int iwm_load_firmware_chunk(struct iwm_priv
*iwm
,
109 const struct firmware
*fw
,
110 struct iwm_fw_img_desc
*img_desc
)
112 struct iwm_udma_nonwifi_cmd target_cmd
;
117 IWM_DBG_FW(iwm
, INFO
, "Loading FW chunk: %d bytes @ 0x%x\n",
118 img_desc
->length
, img_desc
->address
);
120 target_cmd
.opcode
= UMAC_HDI_OUT_OPCODE_WRITE
;
121 target_cmd
.handle_by_hw
= 1;
126 chunk_size
= img_desc
->length
;
127 chunk_ptr
= fw
->data
+ img_desc
->offset
;
129 while (chunk_size
> 0) {
132 tmp_chunk_size
= min_t(u32
, chunk_size
,
133 IWM_MAX_NONWIFI_CMD_BUFF_SIZE
);
135 target_cmd
.addr
= cpu_to_le32(img_desc
->address
+
136 (chunk_ptr
- fw
->data
- img_desc
->offset
));
137 target_cmd
.op1_sz
= cpu_to_le32(tmp_chunk_size
);
139 IWM_DBG_FW(iwm
, DBG
, "\t%d bytes @ 0x%x\n",
140 tmp_chunk_size
, target_cmd
.addr
);
142 ret
= iwm_hal_send_target_cmd(iwm
, &target_cmd
, chunk_ptr
);
144 IWM_ERR(iwm
, "Couldn't load FW chunk\n");
148 chunk_size
-= tmp_chunk_size
;
149 chunk_ptr
+= tmp_chunk_size
;
155 * To load a fw image to the target, we basically go through the
156 * fw, looking for OP_MEM_DESC records. Once we found one, we
157 * pass it to iwm_load_firmware_chunk().
158 * The OP_MEM_DESC records contain the actuall memory chunk to be
159 * sent, but also the destination address.
161 static int iwm_load_img(struct iwm_priv
*iwm
, const char *img_name
)
163 const struct firmware
*fw
;
164 struct iwm_fw_img_desc
*img_desc
;
165 struct iwm_fw_img_ver
*ver
;
166 int ret
= 0, fw_offset
;
167 u32 opcode_idx
= 0, build_date
;
170 ret
= request_firmware(&fw
, img_name
, iwm_to_dev(iwm
));
172 IWM_ERR(iwm
, "Request firmware failed");
176 IWM_DBG_FW(iwm
, INFO
, "Start to load FW %s\n", img_name
);
179 fw_offset
= iwm_fw_op_offset(iwm
, fw
,
180 IWM_HDR_REC_OP_MEM_DESC
,
185 img_desc
= (struct iwm_fw_img_desc
*)(fw
->data
+ fw_offset
);
186 ret
= iwm_load_firmware_chunk(iwm
, fw
, img_desc
);
192 /* Read firmware version */
193 fw_offset
= iwm_fw_op_offset(iwm
, fw
, IWM_HDR_REC_OP_SW_VER
, 0);
197 ver
= (struct iwm_fw_img_ver
*)(fw
->data
+ fw_offset
);
200 fw_offset
= iwm_fw_op_offset(iwm
, fw
, IWM_HDR_REC_OP_BUILD_TAG
, 0);
204 build_tag
= (char *)(fw
->data
+ fw_offset
);
206 /* Read build date */
207 fw_offset
= iwm_fw_op_offset(iwm
, fw
, IWM_HDR_REC_OP_BUILD_DATE
, 0);
211 build_date
= *(u32
*)(fw
->data
+ fw_offset
);
213 IWM_INFO(iwm
, "%s:\n", img_name
);
214 IWM_INFO(iwm
, "\tVersion: %02X.%02X\n", ver
->major
, ver
->minor
);
215 IWM_INFO(iwm
, "\tBuild tag: %s\n", build_tag
);
216 IWM_INFO(iwm
, "\tBuild date: %x-%x-%x\n",
217 IWM_BUILD_YEAR(build_date
), IWM_BUILD_MONTH(build_date
),
218 IWM_BUILD_DAY(build_date
));
222 release_firmware(fw
);
227 static int iwm_load_umac(struct iwm_priv
*iwm
)
229 struct iwm_udma_nonwifi_cmd target_cmd
;
232 ret
= iwm_load_img(iwm
, iwm
->bus_ops
->umac_name
);
236 /* We've loaded the UMAC, we can tell the target to jump there */
237 target_cmd
.opcode
= UMAC_HDI_OUT_OPCODE_JUMP
;
238 target_cmd
.addr
= cpu_to_le32(UMAC_MU_FW_INST_DATA_12_ADDR
);
239 target_cmd
.op1_sz
= 0;
241 target_cmd
.handle_by_hw
= 0;
242 target_cmd
.resp
= 1 ;
245 ret
= iwm_hal_send_target_cmd(iwm
, &target_cmd
, NULL
);
247 IWM_ERR(iwm
, "Couldn't send JMP command\n");
252 static int iwm_load_lmac(struct iwm_priv
*iwm
, const char *img_name
)
256 ret
= iwm_load_img(iwm
, img_name
);
260 return iwm_send_umac_reset(iwm
,
261 cpu_to_le32(UMAC_RST_CTRL_FLG_LARC_CLK_EN
), 0);
264 static int iwm_init_calib(struct iwm_priv
*iwm
, unsigned long cfg_bitmap
,
265 unsigned long expected_bitmap
, u8 rx_iq_cmd
)
267 /* Read RX IQ calibration result from EEPROM */
268 if (test_bit(rx_iq_cmd
, &cfg_bitmap
)) {
269 iwm_store_rxiq_calib_result(iwm
);
270 set_bit(PHY_CALIBRATE_RX_IQ_CMD
, &iwm
->calib_done_map
);
273 iwm_send_prio_table(iwm
);
274 iwm_send_init_calib_cfg(iwm
, cfg_bitmap
);
276 while (iwm
->calib_done_map
!= expected_bitmap
) {
277 if (iwm_notif_handle(iwm
, CALIBRATION_RES_NOTIFICATION
,
278 IWM_SRC_LMAC
, WAIT_NOTIF_TIMEOUT
)) {
279 IWM_DBG_FW(iwm
, DBG
, "Initial calibration timeout\n");
283 IWM_DBG_FW(iwm
, DBG
, "Got calibration result. calib_done_map: "
284 "0x%lx, expected calibrations: 0x%lx\n",
285 iwm
->calib_done_map
, expected_bitmap
);
292 * We currently have to load 3 FWs:
293 * 1) The UMAC (Upper MAC).
294 * 2) The calibration LMAC (Lower MAC).
295 * We then send the calibration init command, so that the device can
296 * run a first calibration round.
297 * 3) The operational LMAC, which replaces the calibration one when it's
298 * done with the first calibration round.
300 * Once those 3 FWs have been loaded, we send the periodic calibration
301 * command, and then the device is available for regular 802.11 operations.
303 int iwm_load_fw(struct iwm_priv
*iwm
)
305 unsigned long init_calib_map
, periodic_calib_map
;
306 unsigned long expected_calib_map
;
309 /* We first start downloading the UMAC */
310 ret
= iwm_load_umac(iwm
);
312 IWM_ERR(iwm
, "UMAC loading failed\n");
316 /* Handle UMAC_ALIVE notification */
317 ret
= iwm_notif_handle(iwm
, UMAC_NOTIFY_OPCODE_ALIVE
, IWM_SRC_UMAC
,
320 IWM_ERR(iwm
, "Handle UMAC_ALIVE failed: %d\n", ret
);
324 /* UMAC is alive, we can download the calibration LMAC */
325 ret
= iwm_load_lmac(iwm
, iwm
->bus_ops
->calib_lmac_name
);
327 IWM_ERR(iwm
, "Calibration LMAC loading failed\n");
331 /* Handle UMAC_INIT_COMPLETE notification */
332 ret
= iwm_notif_handle(iwm
, UMAC_NOTIFY_OPCODE_INIT_COMPLETE
,
333 IWM_SRC_UMAC
, WAIT_NOTIF_TIMEOUT
);
335 IWM_ERR(iwm
, "Handle INIT_COMPLETE failed for calibration "
340 /* Read EEPROM data */
341 ret
= iwm_eeprom_init(iwm
);
343 IWM_ERR(iwm
, "Couldn't init eeprom array\n");
347 init_calib_map
= iwm
->conf
.calib_map
& IWM_CALIB_MAP_INIT_MSK
;
348 expected_calib_map
= iwm
->conf
.expected_calib_map
&
349 IWM_CALIB_MAP_INIT_MSK
;
350 periodic_calib_map
= IWM_CALIB_MAP_PER_LMAC(iwm
->conf
.calib_map
);
352 ret
= iwm_init_calib(iwm
, init_calib_map
, expected_calib_map
,
353 CALIB_CFG_RX_IQ_IDX
);
355 /* Let's try the old way */
356 ret
= iwm_init_calib(iwm
, expected_calib_map
,
358 PHY_CALIBRATE_RX_IQ_CMD
);
360 IWM_ERR(iwm
, "Calibration result timeout\n");
365 /* Handle LMAC CALIBRATION_COMPLETE notification */
366 ret
= iwm_notif_handle(iwm
, CALIBRATION_COMPLETE_NOTIFICATION
,
367 IWM_SRC_LMAC
, WAIT_NOTIF_TIMEOUT
);
369 IWM_ERR(iwm
, "Wait for CALIBRATION_COMPLETE timeout\n");
373 IWM_INFO(iwm
, "LMAC calibration done: 0x%lx\n", iwm
->calib_done_map
);
375 iwm_send_umac_reset(iwm
, cpu_to_le32(UMAC_RST_CTRL_FLG_LARC_RESET
), 1);
377 ret
= iwm_notif_handle(iwm
, UMAC_CMD_OPCODE_RESET
, IWM_SRC_UMAC
,
380 IWM_ERR(iwm
, "Wait for UMAC RESET timeout\n");
384 /* Download the operational LMAC */
385 ret
= iwm_load_lmac(iwm
, iwm
->bus_ops
->lmac_name
);
387 IWM_ERR(iwm
, "LMAC loading failed\n");
391 ret
= iwm_notif_handle(iwm
, UMAC_NOTIFY_OPCODE_INIT_COMPLETE
,
392 IWM_SRC_UMAC
, WAIT_NOTIF_TIMEOUT
);
394 IWM_ERR(iwm
, "Handle INIT_COMPLETE failed for LMAC: %d\n", ret
);
398 iwm_send_prio_table(iwm
);
399 iwm_send_calib_results(iwm
);
400 iwm_send_periodic_calib_cfg(iwm
, periodic_calib_map
);
405 iwm_eeprom_exit(iwm
);