xref: /openbmc/linux/drivers/net/wireless/ti/wlcore/boot.c (revision 90f59ee4)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * This file is part of wl1271
4  *
5  * Copyright (C) 2008-2010 Nokia Corporation
6  *
7  * Contact: Luciano Coelho <luciano.coelho@nokia.com>
8  */
9 
10 #include <linux/slab.h>
11 #include <linux/export.h>
12 
13 #include "debug.h"
14 #include "acx.h"
15 #include "boot.h"
16 #include "io.h"
17 #include "event.h"
18 #include "rx.h"
19 #include "hw_ops.h"
20 
21 static int wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
22 {
23 	u32 cpu_ctrl;
24 	int ret;
25 
26 	/* 10.5.0 run the firmware (I) */
27 	ret = wlcore_read_reg(wl, REG_ECPU_CONTROL, &cpu_ctrl);
28 	if (ret < 0)
29 		goto out;
30 
31 	/* 10.5.1 run the firmware (II) */
32 	cpu_ctrl |= flag;
33 	ret = wlcore_write_reg(wl, REG_ECPU_CONTROL, cpu_ctrl);
34 
35 out:
36 	return ret;
37 }
38 
39 static int wlcore_boot_parse_fw_ver(struct wl1271 *wl,
40 				    struct wl1271_static_data *static_data)
41 {
42 	int ret;
43 
44 	strncpy(wl->chip.fw_ver_str, static_data->fw_version,
45 		sizeof(wl->chip.fw_ver_str));
46 
47 	/* make sure the string is NULL-terminated */
48 	wl->chip.fw_ver_str[sizeof(wl->chip.fw_ver_str) - 1] = '\0';
49 
50 	ret = sscanf(wl->chip.fw_ver_str + 4, "%u.%u.%u.%u.%u",
51 		     &wl->chip.fw_ver[0], &wl->chip.fw_ver[1],
52 		     &wl->chip.fw_ver[2], &wl->chip.fw_ver[3],
53 		     &wl->chip.fw_ver[4]);
54 
55 	if (ret != 5) {
56 		wl1271_warning("fw version incorrect value");
57 		memset(wl->chip.fw_ver, 0, sizeof(wl->chip.fw_ver));
58 		ret = -EINVAL;
59 		goto out;
60 	}
61 
62 	ret = wlcore_identify_fw(wl);
63 	if (ret < 0)
64 		goto out;
65 out:
66 	return ret;
67 }
68 
69 static int wlcore_validate_fw_ver(struct wl1271 *wl)
70 {
71 	unsigned int *fw_ver = wl->chip.fw_ver;
72 	unsigned int *min_ver = (wl->fw_type == WL12XX_FW_TYPE_MULTI) ?
73 		wl->min_mr_fw_ver : wl->min_sr_fw_ver;
74 	char min_fw_str[32] = "";
75 	int off = 0;
76 	int i;
77 
78 	/* the chip must be exactly equal */
79 	if ((min_ver[FW_VER_CHIP] != WLCORE_FW_VER_IGNORE) &&
80 	    (min_ver[FW_VER_CHIP] != fw_ver[FW_VER_CHIP]))
81 		goto fail;
82 
83 	/* the firmware type must be equal */
84 	if ((min_ver[FW_VER_IF_TYPE] != WLCORE_FW_VER_IGNORE) &&
85 	    (min_ver[FW_VER_IF_TYPE] != fw_ver[FW_VER_IF_TYPE]))
86 		goto fail;
87 
88 	/* the project number must be equal */
89 	if ((min_ver[FW_VER_SUBTYPE] != WLCORE_FW_VER_IGNORE) &&
90 	    (min_ver[FW_VER_SUBTYPE] != fw_ver[FW_VER_SUBTYPE]))
91 		goto fail;
92 
93 	/* the API version must be greater or equal */
94 	if ((min_ver[FW_VER_MAJOR] != WLCORE_FW_VER_IGNORE) &&
95 		 (min_ver[FW_VER_MAJOR] > fw_ver[FW_VER_MAJOR]))
96 		goto fail;
97 
98 	/* if the API version is equal... */
99 	if (((min_ver[FW_VER_MAJOR] == WLCORE_FW_VER_IGNORE) ||
100 	     (min_ver[FW_VER_MAJOR] == fw_ver[FW_VER_MAJOR])) &&
101 	    /* ...the minor must be greater or equal */
102 	    ((min_ver[FW_VER_MINOR] != WLCORE_FW_VER_IGNORE) &&
103 	     (min_ver[FW_VER_MINOR] > fw_ver[FW_VER_MINOR])))
104 		goto fail;
105 
106 	return 0;
107 
108 fail:
109 	for (i = 0; i < NUM_FW_VER && off < sizeof(min_fw_str); i++)
110 		if (min_ver[i] == WLCORE_FW_VER_IGNORE)
111 			off += snprintf(min_fw_str + off,
112 					sizeof(min_fw_str) - off,
113 					"*.");
114 		else
115 			off += snprintf(min_fw_str + off,
116 					sizeof(min_fw_str) - off,
117 					"%u.", min_ver[i]);
118 
119 	wl1271_error("Your WiFi FW version (%u.%u.%u.%u.%u) is invalid.\n"
120 		     "Please use at least FW %s\n"
121 		     "You can get the latest firmwares at:\n"
122 		     "git://git.ti.com/wilink8-wlan/wl18xx_fw.git",
123 		     fw_ver[FW_VER_CHIP], fw_ver[FW_VER_IF_TYPE],
124 		     fw_ver[FW_VER_MAJOR], fw_ver[FW_VER_SUBTYPE],
125 		     fw_ver[FW_VER_MINOR], min_fw_str);
126 	return -EINVAL;
127 }
128 
129 static int wlcore_boot_static_data(struct wl1271 *wl)
130 {
131 	struct wl1271_static_data *static_data;
132 	size_t len = sizeof(*static_data) + wl->static_data_priv_len;
133 	int ret;
134 
135 	static_data = kmalloc(len, GFP_KERNEL);
136 	if (!static_data) {
137 		ret = -ENOMEM;
138 		goto out;
139 	}
140 
141 	ret = wlcore_read(wl, wl->cmd_box_addr, static_data, len, false);
142 	if (ret < 0)
143 		goto out_free;
144 
145 	ret = wlcore_boot_parse_fw_ver(wl, static_data);
146 	if (ret < 0)
147 		goto out_free;
148 
149 	ret = wlcore_validate_fw_ver(wl);
150 	if (ret < 0)
151 		goto out_free;
152 
153 	ret = wlcore_handle_static_data(wl, static_data);
154 	if (ret < 0)
155 		goto out_free;
156 
157 out_free:
158 	kfree(static_data);
159 out:
160 	return ret;
161 }
162 
163 static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
164 					     size_t fw_data_len, u32 dest)
165 {
166 	struct wlcore_partition_set partition;
167 	int addr, chunk_num, partition_limit;
168 	u8 *p, *chunk;
169 	int ret;
170 
171 	/* whal_FwCtrl_LoadFwImageSm() */
172 
173 	wl1271_debug(DEBUG_BOOT, "starting firmware upload");
174 
175 	wl1271_debug(DEBUG_BOOT, "fw_data_len %zd chunk_size %d",
176 		     fw_data_len, CHUNK_SIZE);
177 
178 	if ((fw_data_len % 4) != 0) {
179 		wl1271_error("firmware length not multiple of four");
180 		return -EIO;
181 	}
182 
183 	chunk = kmalloc(CHUNK_SIZE, GFP_KERNEL);
184 	if (!chunk) {
185 		wl1271_error("allocation for firmware upload chunk failed");
186 		return -ENOMEM;
187 	}
188 
189 	memcpy(&partition, &wl->ptable[PART_DOWN], sizeof(partition));
190 	partition.mem.start = dest;
191 	ret = wlcore_set_partition(wl, &partition);
192 	if (ret < 0)
193 		goto out;
194 
195 	/* 10.1 set partition limit and chunk num */
196 	chunk_num = 0;
197 	partition_limit = wl->ptable[PART_DOWN].mem.size;
198 
199 	while (chunk_num < fw_data_len / CHUNK_SIZE) {
200 		/* 10.2 update partition, if needed */
201 		addr = dest + (chunk_num + 2) * CHUNK_SIZE;
202 		if (addr > partition_limit) {
203 			addr = dest + chunk_num * CHUNK_SIZE;
204 			partition_limit = chunk_num * CHUNK_SIZE +
205 				wl->ptable[PART_DOWN].mem.size;
206 			partition.mem.start = addr;
207 			ret = wlcore_set_partition(wl, &partition);
208 			if (ret < 0)
209 				goto out;
210 		}
211 
212 		/* 10.3 upload the chunk */
213 		addr = dest + chunk_num * CHUNK_SIZE;
214 		p = buf + chunk_num * CHUNK_SIZE;
215 		memcpy(chunk, p, CHUNK_SIZE);
216 		wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x",
217 			     p, addr);
218 		ret = wlcore_write(wl, addr, chunk, CHUNK_SIZE, false);
219 		if (ret < 0)
220 			goto out;
221 
222 		chunk_num++;
223 	}
224 
225 	/* 10.4 upload the last chunk */
226 	addr = dest + chunk_num * CHUNK_SIZE;
227 	p = buf + chunk_num * CHUNK_SIZE;
228 	memcpy(chunk, p, fw_data_len % CHUNK_SIZE);
229 	wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x",
230 		     fw_data_len % CHUNK_SIZE, p, addr);
231 	ret = wlcore_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false);
232 
233 out:
234 	kfree(chunk);
235 	return ret;
236 }
237 
238 int wlcore_boot_upload_firmware(struct wl1271 *wl)
239 {
240 	u32 chunks, addr, len;
241 	int ret = 0;
242 	u8 *fw;
243 
244 	fw = wl->fw;
245 	chunks = be32_to_cpup((__be32 *) fw);
246 	fw += sizeof(u32);
247 
248 	wl1271_debug(DEBUG_BOOT, "firmware chunks to be uploaded: %u", chunks);
249 
250 	while (chunks--) {
251 		addr = be32_to_cpup((__be32 *) fw);
252 		fw += sizeof(u32);
253 		len = be32_to_cpup((__be32 *) fw);
254 		fw += sizeof(u32);
255 
256 		if (len > 300000) {
257 			wl1271_info("firmware chunk too long: %u", len);
258 			return -EINVAL;
259 		}
260 		wl1271_debug(DEBUG_BOOT, "chunk %d addr 0x%x len %u",
261 			     chunks, addr, len);
262 		ret = wl1271_boot_upload_firmware_chunk(wl, fw, len, addr);
263 		if (ret != 0)
264 			break;
265 		fw += len;
266 	}
267 
268 	return ret;
269 }
270 EXPORT_SYMBOL_GPL(wlcore_boot_upload_firmware);
271 
272 int wlcore_boot_upload_nvs(struct wl1271 *wl)
273 {
274 	struct platform_device *pdev = wl->pdev;
275 	struct wlcore_platdev_data *pdev_data = dev_get_platdata(&pdev->dev);
276 	const char *nvs_name = "unknown";
277 	size_t nvs_len, burst_len;
278 	int i;
279 	u32 dest_addr, val;
280 	u8 *nvs_ptr, *nvs_aligned;
281 	int ret;
282 
283 	if (wl->nvs == NULL) {
284 		wl1271_error("NVS file is needed during boot");
285 		return -ENODEV;
286 	}
287 
288 	if (pdev_data && pdev_data->family)
289 		nvs_name = pdev_data->family->nvs_name;
290 
291 	if (wl->quirks & WLCORE_QUIRK_LEGACY_NVS) {
292 		struct wl1271_nvs_file *nvs =
293 			(struct wl1271_nvs_file *)wl->nvs;
294 		/*
295 		 * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz
296 		 * band configurations) can be removed when those NVS files stop
297 		 * floating around.
298 		 */
299 		if (wl->nvs_len == sizeof(struct wl1271_nvs_file) ||
300 		    wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) {
301 			if (nvs->general_params.dual_mode_select)
302 				wl->enable_11a = true;
303 		}
304 
305 		if (wl->nvs_len != sizeof(struct wl1271_nvs_file) &&
306 		    (wl->nvs_len != WL1271_INI_LEGACY_NVS_FILE_SIZE ||
307 		     wl->enable_11a)) {
308 			wl1271_error("%s size is not as expected: %zu != %zu",
309 				     nvs_name, wl->nvs_len,
310 				     sizeof(struct wl1271_nvs_file));
311 			kfree(wl->nvs);
312 			wl->nvs = NULL;
313 			wl->nvs_len = 0;
314 			return -EILSEQ;
315 		}
316 
317 		/* only the first part of the NVS needs to be uploaded */
318 		nvs_len = sizeof(nvs->nvs);
319 		nvs_ptr = (u8 *) nvs->nvs;
320 	} else {
321 		struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs;
322 
323 		if (wl->nvs_len == sizeof(struct wl128x_nvs_file)) {
324 			if (nvs->general_params.dual_mode_select)
325 				wl->enable_11a = true;
326 		} else {
327 			wl1271_error("%s size is not as expected: %zu != %zu",
328 				     nvs_name, wl->nvs_len,
329 				     sizeof(struct wl128x_nvs_file));
330 			kfree(wl->nvs);
331 			wl->nvs = NULL;
332 			wl->nvs_len = 0;
333 			return -EILSEQ;
334 		}
335 
336 		/* only the first part of the NVS needs to be uploaded */
337 		nvs_len = sizeof(nvs->nvs);
338 		nvs_ptr = (u8 *)nvs->nvs;
339 	}
340 
341 	/* update current MAC address to NVS */
342 	nvs_ptr[11] = wl->addresses[0].addr[0];
343 	nvs_ptr[10] = wl->addresses[0].addr[1];
344 	nvs_ptr[6] = wl->addresses[0].addr[2];
345 	nvs_ptr[5] = wl->addresses[0].addr[3];
346 	nvs_ptr[4] = wl->addresses[0].addr[4];
347 	nvs_ptr[3] = wl->addresses[0].addr[5];
348 
349 	/*
350 	 * Layout before the actual NVS tables:
351 	 * 1 byte : burst length.
352 	 * 2 bytes: destination address.
353 	 * n bytes: data to burst copy.
354 	 *
355 	 * This is ended by a 0 length, then the NVS tables.
356 	 */
357 
358 	/* FIXME: Do we need to check here whether the LSB is 1? */
359 	while (nvs_ptr[0]) {
360 		burst_len = nvs_ptr[0];
361 		dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8));
362 
363 		/*
364 		 * Due to our new wl1271_translate_reg_addr function,
365 		 * we need to add the register partition start address
366 		 * to the destination
367 		 */
368 		dest_addr += wl->curr_part.reg.start;
369 
370 		/* We move our pointer to the data */
371 		nvs_ptr += 3;
372 
373 		for (i = 0; i < burst_len; i++) {
374 			if (nvs_ptr + 3 >= (u8 *) wl->nvs + nvs_len)
375 				goto out_badnvs;
376 
377 			val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
378 			       | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));
379 
380 			wl1271_debug(DEBUG_BOOT,
381 				     "nvs burst write 0x%x: 0x%x",
382 				     dest_addr, val);
383 			ret = wlcore_write32(wl, dest_addr, val);
384 			if (ret < 0)
385 				return ret;
386 
387 			nvs_ptr += 4;
388 			dest_addr += 4;
389 		}
390 
391 		if (nvs_ptr >= (u8 *) wl->nvs + nvs_len)
392 			goto out_badnvs;
393 	}
394 
395 	/*
396 	 * We've reached the first zero length, the first NVS table
397 	 * is located at an aligned offset which is at least 7 bytes further.
398 	 * NOTE: The wl->nvs->nvs element must be first, in order to
399 	 * simplify the casting, we assume it is at the beginning of
400 	 * the wl->nvs structure.
401 	 */
402 	nvs_ptr = (u8 *)wl->nvs +
403 			ALIGN(nvs_ptr - (u8 *)wl->nvs + 7, 4);
404 
405 	if (nvs_ptr >= (u8 *) wl->nvs + nvs_len)
406 		goto out_badnvs;
407 
408 	nvs_len -= nvs_ptr - (u8 *)wl->nvs;
409 
410 	/* Now we must set the partition correctly */
411 	ret = wlcore_set_partition(wl, &wl->ptable[PART_WORK]);
412 	if (ret < 0)
413 		return ret;
414 
415 	/* Copy the NVS tables to a new block to ensure alignment */
416 	nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL);
417 	if (!nvs_aligned)
418 		return -ENOMEM;
419 
420 	/* And finally we upload the NVS tables */
421 	ret = wlcore_write_data(wl, REG_CMD_MBOX_ADDRESS, nvs_aligned, nvs_len,
422 				false);
423 
424 	kfree(nvs_aligned);
425 	return ret;
426 
427 out_badnvs:
428 	wl1271_error("nvs data is malformed");
429 	return -EILSEQ;
430 }
431 EXPORT_SYMBOL_GPL(wlcore_boot_upload_nvs);
432 
433 int wlcore_boot_run_firmware(struct wl1271 *wl)
434 {
435 	int loop, ret;
436 	u32 chip_id, intr;
437 
438 	/* Make sure we have the boot partition */
439 	ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
440 	if (ret < 0)
441 		return ret;
442 
443 	ret = wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT);
444 	if (ret < 0)
445 		return ret;
446 
447 	ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &chip_id);
448 	if (ret < 0)
449 		return ret;
450 
451 	wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id);
452 
453 	if (chip_id != wl->chip.id) {
454 		wl1271_error("chip id doesn't match after firmware boot");
455 		return -EIO;
456 	}
457 
458 	/* wait for init to complete */
459 	loop = 0;
460 	while (loop++ < INIT_LOOP) {
461 		udelay(INIT_LOOP_DELAY);
462 		ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &intr);
463 		if (ret < 0)
464 			return ret;
465 
466 		if (intr == 0xffffffff) {
467 			wl1271_error("error reading hardware complete "
468 				     "init indication");
469 			return -EIO;
470 		}
471 		/* check that ACX_INTR_INIT_COMPLETE is enabled */
472 		else if (intr & WL1271_ACX_INTR_INIT_COMPLETE) {
473 			ret = wlcore_write_reg(wl, REG_INTERRUPT_ACK,
474 					       WL1271_ACX_INTR_INIT_COMPLETE);
475 			if (ret < 0)
476 				return ret;
477 			break;
478 		}
479 	}
480 
481 	if (loop > INIT_LOOP) {
482 		wl1271_error("timeout waiting for the hardware to "
483 			     "complete initialization");
484 		return -EIO;
485 	}
486 
487 	/* get hardware config command mail box */
488 	ret = wlcore_read_reg(wl, REG_COMMAND_MAILBOX_PTR, &wl->cmd_box_addr);
489 	if (ret < 0)
490 		return ret;
491 
492 	wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x", wl->cmd_box_addr);
493 
494 	/* get hardware config event mail box */
495 	ret = wlcore_read_reg(wl, REG_EVENT_MAILBOX_PTR, &wl->mbox_ptr[0]);
496 	if (ret < 0)
497 		return ret;
498 
499 	wl->mbox_ptr[1] = wl->mbox_ptr[0] + wl->mbox_size;
500 
501 	wl1271_debug(DEBUG_MAILBOX, "MBOX ptrs: 0x%x 0x%x",
502 		     wl->mbox_ptr[0], wl->mbox_ptr[1]);
503 
504 	ret = wlcore_boot_static_data(wl);
505 	if (ret < 0) {
506 		wl1271_error("error getting static data");
507 		return ret;
508 	}
509 
510 	/*
511 	 * in case of full asynchronous mode the firmware event must be
512 	 * ready to receive event from the command mailbox
513 	 */
514 
515 	/* unmask required mbox events  */
516 	ret = wl1271_event_unmask(wl);
517 	if (ret < 0) {
518 		wl1271_error("EVENT mask setting failed");
519 		return ret;
520 	}
521 
522 	/* set the working partition to its "running" mode offset */
523 	ret = wlcore_set_partition(wl, &wl->ptable[PART_WORK]);
524 
525 	/* firmware startup completed */
526 	return ret;
527 }
528 EXPORT_SYMBOL_GPL(wlcore_boot_run_firmware);
529