boot.c 20.2 KB
Newer Older
L
Luciano Coelho 已提交
1 2 3
/*
 * This file is part of wl1271
 *
4
 * Copyright (C) 2008-2010 Nokia Corporation
L
Luciano Coelho 已提交
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 *
 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

24
#include <linux/slab.h>
25
#include <linux/wl12xx.h>
26
#include <linux/export.h>
L
Luciano Coelho 已提交
27

28
#include "debug.h"
S
Shahar Levi 已提交
29 30 31 32
#include "acx.h"
#include "boot.h"
#include "io.h"
#include "event.h"
33
#include "rx.h"
L
Luciano Coelho 已提交
34

35 36 37 38 39 40
/*
 * TODO: this is here just for now, it will be removed when we move
 * the top_reg stuff to wl12xx
 */
#include "../wl12xx/reg.h"

L
Luciano Coelho 已提交
41 42 43 44 45
static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
{
	u32 cpu_ctrl;

	/* 10.5.0 run the firmware (I) */
46
	cpu_ctrl = wlcore_read_reg(wl, REG_ECPU_CONTROL);
L
Luciano Coelho 已提交
47 48 49

	/* 10.5.1 run the firmware (II) */
	cpu_ctrl |= flag;
50
	wlcore_write_reg(wl, REG_ECPU_CONTROL, cpu_ctrl);
L
Luciano Coelho 已提交
51 52
}

53 54 55 56 57
static unsigned int wl12xx_get_fw_ver_quirks(struct wl1271 *wl)
{
	unsigned int quirks = 0;
	unsigned int *fw_ver = wl->chip.fw_ver;

58 59 60 61 62 63 64 65 66
	/* Only new station firmwares support routing fw logs to the host */
	if ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) &&
	    (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_FWLOG_STA_MIN))
		quirks |= WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED;

	/* This feature is not yet supported for AP mode */
	if (fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP)
		quirks |= WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED;

67 68 69
	return quirks;
}

L
Levi, Shahar 已提交
70 71 72 73 74 75 76 77 78 79 80 81 82 83
static void wl1271_parse_fw_ver(struct wl1271 *wl)
{
	int ret;

	ret = sscanf(wl->chip.fw_ver_str + 4, "%u.%u.%u.%u.%u",
		     &wl->chip.fw_ver[0], &wl->chip.fw_ver[1],
		     &wl->chip.fw_ver[2], &wl->chip.fw_ver[3],
		     &wl->chip.fw_ver[4]);

	if (ret != 5) {
		wl1271_warning("fw version incorrect value");
		memset(wl->chip.fw_ver, 0, sizeof(wl->chip.fw_ver));
		return;
	}
84 85 86

	/* Check if any quirks are needed with older fw versions */
	wl->quirks |= wl12xx_get_fw_ver_quirks(wl);
L
Levi, Shahar 已提交
87 88
}

L
Luciano Coelho 已提交
89 90
static void wl1271_boot_fw_version(struct wl1271 *wl)
{
91
	struct wl1271_static_data *static_data;
L
Luciano Coelho 已提交
92

93 94 95 96 97 98 99
	static_data = kmalloc(sizeof(*static_data), GFP_DMA);
	if (!static_data) {
		__WARN();
		return;
	}

	wl1271_read(wl, wl->cmd_box_addr, static_data, sizeof(*static_data),
T
Teemu Paasikivi 已提交
100
		    false);
L
Luciano Coelho 已提交
101

102
	strncpy(wl->chip.fw_ver_str, static_data->fw_version,
L
Levi, Shahar 已提交
103
		sizeof(wl->chip.fw_ver_str));
L
Luciano Coelho 已提交
104

105 106
	kfree(static_data);

L
Luciano Coelho 已提交
107
	/* make sure the string is NULL-terminated */
L
Levi, Shahar 已提交
108 109 110
	wl->chip.fw_ver_str[sizeof(wl->chip.fw_ver_str) - 1] = '\0';

	wl1271_parse_fw_ver(wl);
L
Luciano Coelho 已提交
111 112 113 114 115
}

static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
					     size_t fw_data_len, u32 dest)
{
116
	struct wlcore_partition_set partition;
L
Luciano Coelho 已提交
117
	int addr, chunk_num, partition_limit;
118
	u8 *p, *chunk;
L
Luciano Coelho 已提交
119 120 121 122 123

	/* whal_FwCtrl_LoadFwImageSm() */

	wl1271_debug(DEBUG_BOOT, "starting firmware upload");

124 125
	wl1271_debug(DEBUG_BOOT, "fw_data_len %zd chunk_size %d",
		     fw_data_len, CHUNK_SIZE);
L
Luciano Coelho 已提交
126 127 128 129 130 131

	if ((fw_data_len % 4) != 0) {
		wl1271_error("firmware length not multiple of four");
		return -EIO;
	}

132
	chunk = kmalloc(CHUNK_SIZE, GFP_KERNEL);
133
	if (!chunk) {
134 135 136 137
		wl1271_error("allocation for firmware upload chunk failed");
		return -ENOMEM;
	}

138
	memcpy(&partition, &wl->ptable[PART_DOWN], sizeof(partition));
139
	partition.mem.start = dest;
140
	wlcore_set_partition(wl, &partition);
L
Luciano Coelho 已提交
141 142 143

	/* 10.1 set partition limit and chunk num */
	chunk_num = 0;
144
	partition_limit = wl->ptable[PART_DOWN].mem.size;
L
Luciano Coelho 已提交
145 146 147 148 149 150 151

	while (chunk_num < fw_data_len / CHUNK_SIZE) {
		/* 10.2 update partition, if needed */
		addr = dest + (chunk_num + 2) * CHUNK_SIZE;
		if (addr > partition_limit) {
			addr = dest + chunk_num * CHUNK_SIZE;
			partition_limit = chunk_num * CHUNK_SIZE +
152
				wl->ptable[PART_DOWN].mem.size;
153
			partition.mem.start = addr;
154
			wlcore_set_partition(wl, &partition);
L
Luciano Coelho 已提交
155 156 157 158 159
		}

		/* 10.3 upload the chunk */
		addr = dest + chunk_num * CHUNK_SIZE;
		p = buf + chunk_num * CHUNK_SIZE;
160
		memcpy(chunk, p, CHUNK_SIZE);
L
Luciano Coelho 已提交
161 162
		wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x",
			     p, addr);
T
Teemu Paasikivi 已提交
163
		wl1271_write(wl, addr, chunk, CHUNK_SIZE, false);
L
Luciano Coelho 已提交
164 165 166 167 168 169 170

		chunk_num++;
	}

	/* 10.4 upload the last chunk */
	addr = dest + chunk_num * CHUNK_SIZE;
	p = buf + chunk_num * CHUNK_SIZE;
171
	memcpy(chunk, p, fw_data_len % CHUNK_SIZE);
172
	wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x",
L
Luciano Coelho 已提交
173
		     fw_data_len % CHUNK_SIZE, p, addr);
T
Teemu Paasikivi 已提交
174
	wl1271_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false);
L
Luciano Coelho 已提交
175

176
	kfree(chunk);
L
Luciano Coelho 已提交
177 178 179 180 181 182
	return 0;
}

static int wl1271_boot_upload_firmware(struct wl1271 *wl)
{
	u32 chunks, addr, len;
183
	int ret = 0;
L
Luciano Coelho 已提交
184 185 186
	u8 *fw;

	fw = wl->fw;
L
Luciano Coelho 已提交
187
	chunks = be32_to_cpup((__be32 *) fw);
L
Luciano Coelho 已提交
188 189 190 191 192
	fw += sizeof(u32);

	wl1271_debug(DEBUG_BOOT, "firmware chunks to be uploaded: %u", chunks);

	while (chunks--) {
L
Luciano Coelho 已提交
193
		addr = be32_to_cpup((__be32 *) fw);
L
Luciano Coelho 已提交
194
		fw += sizeof(u32);
L
Luciano Coelho 已提交
195
		len = be32_to_cpup((__be32 *) fw);
L
Luciano Coelho 已提交
196 197 198 199 200 201 202 203
		fw += sizeof(u32);

		if (len > 300000) {
			wl1271_info("firmware chunk too long: %u", len);
			return -EINVAL;
		}
		wl1271_debug(DEBUG_BOOT, "chunk %d addr 0x%x len %u",
			     chunks, addr, len);
204 205 206
		ret = wl1271_boot_upload_firmware_chunk(wl, fw, len, addr);
		if (ret != 0)
			break;
L
Luciano Coelho 已提交
207 208 209
		fw += len;
	}

210
	return ret;
L
Luciano Coelho 已提交
211 212 213 214 215 216 217
}

static int wl1271_boot_upload_nvs(struct wl1271 *wl)
{
	size_t nvs_len, burst_len;
	int i;
	u32 dest_addr, val;
218
	u8 *nvs_ptr, *nvs_aligned;
L
Luciano Coelho 已提交
219

220
	if (wl->nvs == NULL)
L
Luciano Coelho 已提交
221 222
		return -ENODEV;

223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
	if (wl->chip.id == CHIP_ID_1283_PG20) {
		struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs;

		if (wl->nvs_len == sizeof(struct wl128x_nvs_file)) {
			if (nvs->general_params.dual_mode_select)
				wl->enable_11a = true;
		} else {
			wl1271_error("nvs size is not as expected: %zu != %zu",
				     wl->nvs_len,
				     sizeof(struct wl128x_nvs_file));
			kfree(wl->nvs);
			wl->nvs = NULL;
			wl->nvs_len = 0;
			return -EILSEQ;
		}
238

239 240 241 242 243 244 245 246 247 248 249 250 251 252
		/* only the first part of the NVS needs to be uploaded */
		nvs_len = sizeof(nvs->nvs);
		nvs_ptr = (u8 *)nvs->nvs;

	} else {
		struct wl1271_nvs_file *nvs =
			(struct wl1271_nvs_file *)wl->nvs;
		/*
		 * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz
		 * band configurations) can be removed when those NVS files stop
		 * floating around.
		 */
		if (wl->nvs_len == sizeof(struct wl1271_nvs_file) ||
		    wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) {
253
			if (nvs->general_params.dual_mode_select)
254 255
				wl->enable_11a = true;
		}
256

257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
		if (wl->nvs_len != sizeof(struct wl1271_nvs_file) &&
		    (wl->nvs_len != WL1271_INI_LEGACY_NVS_FILE_SIZE ||
		     wl->enable_11a)) {
			wl1271_error("nvs size is not as expected: %zu != %zu",
				wl->nvs_len, sizeof(struct wl1271_nvs_file));
			kfree(wl->nvs);
			wl->nvs = NULL;
			wl->nvs_len = 0;
			return -EILSEQ;
		}

		/* only the first part of the NVS needs to be uploaded */
		nvs_len = sizeof(nvs->nvs);
		nvs_ptr = (u8 *) nvs->nvs;
	}
L
Luciano Coelho 已提交
272

273
	/* update current MAC address to NVS */
274 275 276 277 278 279
	nvs_ptr[11] = wl->addresses[0].addr[0];
	nvs_ptr[10] = wl->addresses[0].addr[1];
	nvs_ptr[6] = wl->addresses[0].addr[2];
	nvs_ptr[5] = wl->addresses[0].addr[3];
	nvs_ptr[4] = wl->addresses[0].addr[4];
	nvs_ptr[3] = wl->addresses[0].addr[5];
280

L
Luciano Coelho 已提交
281 282 283 284 285 286 287 288 289 290 291 292 293 294
	/*
	 * Layout before the actual NVS tables:
	 * 1 byte : burst length.
	 * 2 bytes: destination address.
	 * n bytes: data to burst copy.
	 *
	 * This is ended by a 0 length, then the NVS tables.
	 */

	/* FIXME: Do we need to check here whether the LSB is 1? */
	while (nvs_ptr[0]) {
		burst_len = nvs_ptr[0];
		dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8));

295 296
		/*
		 * Due to our new wl1271_translate_reg_addr function,
297 298
		 * we need to add the register partition start address
		 * to the destination
299
		 */
300
		dest_addr += wl->curr_part.reg.start;
L
Luciano Coelho 已提交
301 302 303 304 305

		/* We move our pointer to the data */
		nvs_ptr += 3;

		for (i = 0; i < burst_len; i++) {
306 307 308
			if (nvs_ptr + 3 >= (u8 *) wl->nvs + nvs_len)
				goto out_badnvs;

L
Luciano Coelho 已提交
309 310 311 312 313 314
			val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
			       | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));

			wl1271_debug(DEBUG_BOOT,
				     "nvs burst write 0x%x: 0x%x",
				     dest_addr, val);
T
Teemu Paasikivi 已提交
315
			wl1271_write32(wl, dest_addr, val);
L
Luciano Coelho 已提交
316 317 318 319

			nvs_ptr += 4;
			dest_addr += 4;
		}
320 321 322

		if (nvs_ptr >= (u8 *) wl->nvs + nvs_len)
			goto out_badnvs;
L
Luciano Coelho 已提交
323 324 325 326
	}

	/*
	 * We've reached the first zero length, the first NVS table
327
	 * is located at an aligned offset which is at least 7 bytes further.
328 329 330
	 * NOTE: The wl->nvs->nvs element must be first, in order to
	 * simplify the casting, we assume it is at the beginning of
	 * the wl->nvs structure.
L
Luciano Coelho 已提交
331
	 */
332 333
	nvs_ptr = (u8 *)wl->nvs +
			ALIGN(nvs_ptr - (u8 *)wl->nvs + 7, 4);
334 335 336 337

	if (nvs_ptr >= (u8 *) wl->nvs + nvs_len)
		goto out_badnvs;

338
	nvs_len -= nvs_ptr - (u8 *)wl->nvs;
L
Luciano Coelho 已提交
339 340

	/* Now we must set the partition correctly */
341
	wlcore_set_partition(wl, &wl->ptable[PART_WORK]);
L
Luciano Coelho 已提交
342 343

	/* Copy the NVS tables to a new block to ensure alignment */
344 345 346
	nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL);
	if (!nvs_aligned)
		return -ENOMEM;
L
Luciano Coelho 已提交
347 348

	/* And finally we upload the NVS tables */
349 350
	wlcore_write_data(wl, REG_CMD_MBOX_ADDRESS,
			  nvs_aligned, nvs_len, false);
L
Luciano Coelho 已提交
351 352 353

	kfree(nvs_aligned);
	return 0;
354 355 356 357

out_badnvs:
	wl1271_error("nvs data is malformed");
	return -EILSEQ;
L
Luciano Coelho 已提交
358 359 360 361
}

static void wl1271_boot_enable_interrupts(struct wl1271 *wl)
{
362
	wl1271_enable_interrupts(wl);
363 364 365
	wlcore_write_reg(wl, REG_INTERRUPT_MASK,
			 WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
	wl1271_write32(wl, WL12XX_HI_CFG, HI_CFG_DEF_VAL);
L
Luciano Coelho 已提交
366 367 368 369 370 371 372 373
}

static int wl1271_boot_soft_reset(struct wl1271 *wl)
{
	unsigned long timeout;
	u32 boot_data;

	/* perform soft reset */
374
	wl1271_write32(wl, WL12XX_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT);
L
Luciano Coelho 已提交
375 376 377 378

	/* SOFT_RESET is self clearing */
	timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME);
	while (1) {
379
		boot_data = wl1271_read32(wl, WL12XX_SLV_SOFT_RESET);
L
Luciano Coelho 已提交
380 381 382 383 384 385 386 387 388 389 390 391 392 393 394
		wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data);
		if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0)
			break;

		if (time_after(jiffies, timeout)) {
			/* 1.2 check pWhalBus->uSelfClearTime if the
			 * timeout was reached */
			wl1271_error("soft reset timeout");
			return -1;
		}

		udelay(SOFT_RESET_STALL_TIME);
	}

	/* disable Rx/Tx */
395
	wl1271_write32(wl, WL12XX_ENABLE, 0x0);
L
Luciano Coelho 已提交
396 397

	/* disable auto calibration on start*/
398
	wl1271_write32(wl, WL12XX_SPARE_A2, 0xffff);
L
Luciano Coelho 已提交
399 400 401 402 403 404 405

	return 0;
}

static int wl1271_boot_run_firmware(struct wl1271 *wl)
{
	int loop, ret;
406
	u32 chip_id, intr;
L
Luciano Coelho 已提交
407 408 409

	wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT);

410
	chip_id = wlcore_read_reg(wl, REG_CHIP_ID_B);
L
Luciano Coelho 已提交
411 412 413 414 415 416 417 418 419 420 421 422

	wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id);

	if (chip_id != wl->chip.id) {
		wl1271_error("chip id doesn't match after firmware boot");
		return -EIO;
	}

	/* wait for init to complete */
	loop = 0;
	while (loop++ < INIT_LOOP) {
		udelay(INIT_LOOP_DELAY);
423
		intr = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR);
L
Luciano Coelho 已提交
424

425
		if (intr == 0xffffffff) {
L
Luciano Coelho 已提交
426 427 428 429 430
			wl1271_error("error reading hardware complete "
				     "init indication");
			return -EIO;
		}
		/* check that ACX_INTR_INIT_COMPLETE is enabled */
431
		else if (intr & WL1271_ACX_INTR_INIT_COMPLETE) {
432 433
			wlcore_write_reg(wl, REG_INTERRUPT_ACK,
					 WL1271_ACX_INTR_INIT_COMPLETE);
L
Luciano Coelho 已提交
434 435 436 437
			break;
		}
	}

L
Luciano Coelho 已提交
438
	if (loop > INIT_LOOP) {
L
Luciano Coelho 已提交
439 440 441 442 443 444
		wl1271_error("timeout waiting for the hardware to "
			     "complete initialization");
		return -EIO;
	}

	/* get hardware config command mail box */
445
	wl->cmd_box_addr = wlcore_read_reg(wl, REG_COMMAND_MAILBOX_PTR);
L
Luciano Coelho 已提交
446 447

	/* get hardware config event mail box */
448
	wl->event_box_addr = wlcore_read_reg(wl, REG_EVENT_MAILBOX_PTR);
L
Luciano Coelho 已提交
449 450

	/* set the working partition to its "running" mode offset */
451
	wlcore_set_partition(wl, &wl->ptable[PART_WORK]);
L
Luciano Coelho 已提交
452 453 454 455 456 457 458 459 460 461 462

	wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x",
		     wl->cmd_box_addr, wl->event_box_addr);

	wl1271_boot_fw_version(wl);

	/*
	 * in case of full asynchronous mode the firmware event must be
	 * ready to receive event from the command mailbox
	 */

463 464
	/* unmask required mbox events  */
	wl->event_mask = BSS_LOSE_EVENT_ID |
465
		SCAN_COMPLETE_EVENT_ID |
466
		ROLE_STOP_COMPLETE_EVENT_ID |
467
		RSSI_SNR_TRIGGER_0_EVENT_ID |
468
		PSPOLL_DELIVERY_FAILURE_EVENT_ID |
469 470
		SOFT_GEMINI_SENSE_EVENT_ID |
		PERIODIC_SCAN_REPORT_EVENT_ID |
E
Eliad Peller 已提交
471 472 473 474 475 476
		PERIODIC_SCAN_COMPLETE_EVENT_ID |
		DUMMY_PACKET_EVENT_ID |
		PEER_REMOVE_COMPLETE_EVENT_ID |
		BA_SESSION_RX_CONSTRAINT_EVENT_ID |
		REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID |
		INACTIVE_STA_EVENT_ID |
477 478
		MAX_TX_RETRY_EVENT_ID |
		CHANNEL_SWITCH_COMPLETE_EVENT_ID;
479

L
Luciano Coelho 已提交
480 481 482 483 484 485 486 487 488 489 490 491 492 493
	ret = wl1271_event_unmask(wl);
	if (ret < 0) {
		wl1271_error("EVENT mask setting failed");
		return ret;
	}

	wl1271_event_mbox_config(wl);

	/* firmware startup completed */
	return 0;
}

static int wl1271_boot_write_irq_polarity(struct wl1271 *wl)
{
494
	u32 polarity;
L
Luciano Coelho 已提交
495

496
	polarity = wl1271_top_reg_read(wl, OCP_REG_POLARITY);
L
Luciano Coelho 已提交
497 498 499

	/* We use HIGH polarity, so unset the LOW bit */
	polarity &= ~POLARITY_LOW;
500
	wl1271_top_reg_write(wl, OCP_REG_POLARITY, polarity);
L
Luciano Coelho 已提交
501 502 503 504

	return 0;
}

505
static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl)
L
Luciano Coelho 已提交
506
{
507
	u16 spare_reg;
508

509 510 511 512 513 514
	/* Mask bits [2] & [8:4] in the sys_clk_cfg register */
	spare_reg = wl1271_top_reg_read(wl, WL_SPARE_REG);
	if (spare_reg == 0xFFFF)
		return -EFAULT;
	spare_reg |= (BIT(3) | BIT(5) | BIT(6));
	wl1271_top_reg_write(wl, WL_SPARE_REG, spare_reg);
515

516 517 518
	/* Enable FREF_CLK_REQ & mux MCS and coex PLLs to FREF */
	wl1271_top_reg_write(wl, SYS_CLK_CFG_REG,
			     WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF);
519

520 521
	/* Delay execution for 15msec, to let the HW settle */
	mdelay(15);
522

523 524
	return 0;
}
525

526 527 528 529 530 531 532
static bool wl128x_is_tcxo_valid(struct wl1271 *wl)
{
	u16 tcxo_detection;

	tcxo_detection = wl1271_top_reg_read(wl, TCXO_CLK_DETECT_REG);
	if (tcxo_detection & TCXO_DET_FAILED)
		return false;
533

534
	return true;
535 536
}

537
static bool wl128x_is_fref_valid(struct wl1271 *wl)
538
{
539
	u16 fref_detection;
540

541 542 543
	fref_detection = wl1271_top_reg_read(wl, FREF_CLK_DETECT_REG);
	if (fref_detection & FREF_CLK_DETECT_FAIL)
		return false;
544

545 546
	return true;
}
547

548 549 550 551 552
static int wl128x_manually_configure_mcs_pll(struct wl1271 *wl)
{
	wl1271_top_reg_write(wl, MCS_PLL_M_REG, MCS_PLL_M_REG_VAL);
	wl1271_top_reg_write(wl, MCS_PLL_N_REG, MCS_PLL_N_REG_VAL);
	wl1271_top_reg_write(wl, MCS_PLL_CONFIG_REG, MCS_PLL_CONFIG_REG_VAL);
553

554 555
	return 0;
}
556

557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583
static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk)
{
	u16 spare_reg;
	u16 pll_config;
	u8 input_freq;

	/* Mask bits [3:1] in the sys_clk_cfg register */
	spare_reg = wl1271_top_reg_read(wl, WL_SPARE_REG);
	if (spare_reg == 0xFFFF)
		return -EFAULT;
	spare_reg |= BIT(2);
	wl1271_top_reg_write(wl, WL_SPARE_REG, spare_reg);

	/* Handle special cases of the TCXO clock */
	if (wl->tcxo_clock == WL12XX_TCXOCLOCK_16_8 ||
	    wl->tcxo_clock == WL12XX_TCXOCLOCK_33_6)
		return wl128x_manually_configure_mcs_pll(wl);

	/* Set the input frequency according to the selected clock source */
	input_freq = (clk & 1) + 1;

	pll_config = wl1271_top_reg_read(wl, MCS_PLL_CONFIG_REG);
	if (pll_config == 0xFFFF)
		return -EFAULT;
	pll_config |= (input_freq << MCS_SEL_IN_FREQ_SHIFT);
	pll_config |= MCS_PLL_ENABLE_HP;
	wl1271_top_reg_write(wl, MCS_PLL_CONFIG_REG, pll_config);
584

585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604
	return 0;
}

/*
 * WL128x has two clocks input - TCXO and FREF.
 * TCXO is the main clock of the device, while FREF is used to sync
 * between the GPS and the cellular modem.
 * In cases where TCXO is 32.736MHz or 16.368MHz, the FREF will be used
 * as the WLAN/BT main clock.
 */
static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock)
{
	u16 sys_clk_cfg;

	/* For XTAL-only modes, FREF will be used after switching from TCXO */
	if (wl->ref_clock == WL12XX_REFCLOCK_26_XTAL ||
	    wl->ref_clock == WL12XX_REFCLOCK_38_XTAL) {
		if (!wl128x_switch_tcxo_to_fref(wl))
			return -EINVAL;
		goto fref_clk;
605 606
	}

607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635
	/* Query the HW, to determine which clock source we should use */
	sys_clk_cfg = wl1271_top_reg_read(wl, SYS_CLK_CFG_REG);
	if (sys_clk_cfg == 0xFFFF)
		return -EINVAL;
	if (sys_clk_cfg & PRCM_CM_EN_MUX_WLAN_FREF)
		goto fref_clk;

	/* If TCXO is either 32.736MHz or 16.368MHz, switch to FREF */
	if (wl->tcxo_clock == WL12XX_TCXOCLOCK_16_368 ||
	    wl->tcxo_clock == WL12XX_TCXOCLOCK_32_736) {
		if (!wl128x_switch_tcxo_to_fref(wl))
			return -EINVAL;
		goto fref_clk;
	}

	/* TCXO clock is selected */
	if (!wl128x_is_tcxo_valid(wl))
		return -EINVAL;
	*selected_clock = wl->tcxo_clock;
	goto config_mcs_pll;

fref_clk:
	/* FREF clock is selected */
	if (!wl128x_is_fref_valid(wl))
		return -EINVAL;
	*selected_clock = wl->ref_clock;

config_mcs_pll:
	return wl128x_configure_mcs_pll(wl, *selected_clock);
636 637 638 639 640 641
}

static int wl127x_boot_clk(struct wl1271 *wl)
{
	u32 pause;
	u32 clk;
L
Luciano Coelho 已提交
642

643
	if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3)
644
		wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION;
645

646 647 648
	if (wl->ref_clock == CONF_REF_CLK_19_2_E ||
	    wl->ref_clock == CONF_REF_CLK_38_4_E ||
	    wl->ref_clock == CONF_REF_CLK_38_4_M_XTAL)
J
Juuso Oikarinen 已提交
649
		/* ref clk: 19.2/38.4/38.4-XTAL */
L
Luciano Coelho 已提交
650
		clk = 0x3;
651 652
	else if (wl->ref_clock == CONF_REF_CLK_26_E ||
		 wl->ref_clock == CONF_REF_CLK_52_E)
L
Luciano Coelho 已提交
653 654
		/* ref clk: 26/52 */
		clk = 0x5;
655 656
	else
		return -EINVAL;
L
Luciano Coelho 已提交
657

658
	if (wl->ref_clock != CONF_REF_CLK_19_2_E) {
J
Juuso Oikarinen 已提交
659
		u16 val;
660
		/* Set clock type (open drain) */
J
Juuso Oikarinen 已提交
661 662 663
		val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE);
		val &= FREF_CLK_TYPE_BITS;
		wl1271_top_reg_write(wl, OCP_REG_CLK_TYPE, val);
664 665 666 667 668

		/* Set clock pull mode (no pull) */
		val = wl1271_top_reg_read(wl, OCP_REG_CLK_PULL);
		val |= NO_PULL;
		wl1271_top_reg_write(wl, OCP_REG_CLK_PULL, val);
J
Juuso Oikarinen 已提交
669 670 671 672 673 674 675 676 677
	} else {
		u16 val;
		/* Set clock polarity */
		val = wl1271_top_reg_read(wl, OCP_REG_CLK_POLARITY);
		val &= FREF_CLK_POLARITY_BITS;
		val |= CLK_REQ_OUTN_SEL;
		wl1271_top_reg_write(wl, OCP_REG_CLK_POLARITY, val);
	}

678
	wl1271_write32(wl, WL12XX_PLL_PARAMETERS, clk);
L
Luciano Coelho 已提交
679

680
	pause = wl1271_read32(wl, WL12XX_PLL_PARAMETERS);
L
Luciano Coelho 已提交
681 682 683

	wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause);

684
	pause &= ~(WU_COUNTER_PAUSE_VAL);
L
Luciano Coelho 已提交
685
	pause |= WU_COUNTER_PAUSE_VAL;
686
	wl1271_write32(wl, WL12XX_WU_COUNTER_PAUSE, pause);
L
Luciano Coelho 已提交
687

688 689 690 691 692 693 694 695
	return 0;
}

/* uploads NVS and firmware */
int wl1271_load_firmware(struct wl1271 *wl)
{
	int ret = 0;
	u32 tmp, clk;
696
	int selected_clock = -1;
697 698

	if (wl->chip.id == CHIP_ID_1283_PG20) {
699
		ret = wl128x_boot_clk(wl, &selected_clock);
700 701 702 703 704 705 706 707
		if (ret < 0)
			goto out;
	} else {
		ret = wl127x_boot_clk(wl);
		if (ret < 0)
			goto out;
	}

L
Luciano Coelho 已提交
708
	/* Continue the ELP wake up sequence */
709
	wl1271_write32(wl, WL12XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
L
Luciano Coelho 已提交
710 711
	udelay(500);

712
	wlcore_set_partition(wl, &wl->ptable[PART_DRPW]);
L
Luciano Coelho 已提交
713 714 715 716 717

	/* Read-modify-write DRPW_SCRATCH_START register (see next state)
	   to be used by DRPw FW. The RTRIM value will be added by the FW
	   before taking DRPw out of reset */

718
	clk = wl1271_read32(wl, WL12XX_DRPW_SCRATCH_START);
L
Luciano Coelho 已提交
719 720 721

	wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk);

722
	if (wl->chip.id == CHIP_ID_1283_PG20) {
723
		clk |= ((selected_clock & 0x3) << 1) << 4;
724 725 726 727
	} else {
		clk |= (wl->ref_clock << 1) << 4;
	}

728
	wl1271_write32(wl, WL12XX_DRPW_SCRATCH_START, clk);
L
Luciano Coelho 已提交
729

730
	wlcore_set_partition(wl, &wl->ptable[PART_WORK]);
L
Luciano Coelho 已提交
731 732

	/* Disable interrupts */
733
	wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
L
Luciano Coelho 已提交
734 735 736 737 738 739 740 741 742 743 744 745 746 747

	ret = wl1271_boot_soft_reset(wl);
	if (ret < 0)
		goto out;

	/* 2. start processing NVS file */
	ret = wl1271_boot_upload_nvs(wl);
	if (ret < 0)
		goto out;

	/* write firmware's last address (ie. it's length) to
	 * ACX_EEPROMLESS_IND_REG */
	wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG");

748
	wl1271_write32(wl, WL12XX_EEPROMLESS_IND, WL12XX_EEPROMLESS_IND);
L
Luciano Coelho 已提交
749

750
	tmp = wlcore_read_reg(wl, REG_CHIP_ID_B);
L
Luciano Coelho 已提交
751 752 753 754

	wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp);

	/* 6. read the EEPROM parameters */
755
	tmp = wl1271_read32(wl, WL12XX_SCR_PAD2);
L
Luciano Coelho 已提交
756 757 758 759

	/* WL1271: The reference driver skips steps 7 to 10 (jumps directly
	 * to upload_fw) */

760
	if (wl->chip.id == CHIP_ID_1283_PG20)
761
		wl1271_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA);
762

L
Luciano Coelho 已提交
763 764 765 766
	ret = wl1271_boot_upload_firmware(wl);
	if (ret < 0)
		goto out;

767 768 769 770 771 772 773 774 775 776 777 778 779 780
out:
	return ret;
}
EXPORT_SYMBOL_GPL(wl1271_load_firmware);

int wl1271_boot(struct wl1271 *wl)
{
	int ret;

	/* upload NVS and firmware */
	ret = wl1271_load_firmware(wl);
	if (ret)
		return ret;

L
Luciano Coelho 已提交
781 782 783 784 785
	/* 10.5 start firmware */
	ret = wl1271_boot_run_firmware(wl);
	if (ret < 0)
		goto out;

786 787 788 789
	ret = wl1271_boot_write_irq_polarity(wl);
	if (ret < 0)
		goto out;

790
	wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_ALL_EVENTS_VECTOR);
791

792 793 794
	/* Enable firmware interrupts now */
	wl1271_boot_enable_interrupts(wl);

L
Luciano Coelho 已提交
795 796 797 798 799
	wl1271_event_mbox_config(wl);

out:
	return ret;
}