/*
 * This file is part of wl1251
 *
 * Copyright (C) 2008 Nokia Corporation
 *
 * 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
 *
 */

#include <linux/slab.h>

#include "reg.h"
#include "boot.h"
#include "io.h"
#include "spi.h"
#include "event.h"
#include "acx.h"

void wl1251_boot_target_enable_interrupts(struct wl1251 *wl)
{
	wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask));
	wl1251_reg_write32(wl, HI_CFG, HI_CFG_DEF_VAL);
}

int wl1251_boot_soft_reset(struct wl1251 *wl)
{
	unsigned long timeout;
	u32 boot_data;

	/* perform soft reset */
	wl1251_reg_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT);

	/* SOFT_RESET is self clearing */
	timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME);
	while (1) {
		boot_data = wl1251_reg_read32(wl, ACX_REG_SLV_SOFT_RESET);
		wl1251_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 */
			wl1251_error("soft reset timeout");
			return -1;
		}

		udelay(SOFT_RESET_STALL_TIME);
	}

	/* disable Rx/Tx */
	wl1251_reg_write32(wl, ENABLE, 0x0);

	/* disable auto calibration on start*/
	wl1251_reg_write32(wl, SPARE_A2, 0xffff);

	return 0;
}

int wl1251_boot_init_seq(struct wl1251 *wl)
{
	u32 scr_pad6, init_data, tmp, elp_cmd, ref_freq;

	/*
	 * col #1: INTEGER_DIVIDER
	 * col #2: FRACTIONAL_DIVIDER
	 * col #3: ATTN_BB
	 * col #4: ALPHA_BB
	 * col #5: STOP_TIME_BB
	 * col #6: BB_PLL_LOOP_FILTER
	 */
	static const u32 LUT[REF_FREQ_NUM][LUT_PARAM_NUM] = {

		{   83, 87381,  0xB, 5, 0xF00,  3}, /* REF_FREQ_19_2*/
		{   61, 141154, 0xB, 5, 0x1450, 2}, /* REF_FREQ_26_0*/
		{   41, 174763, 0xC, 6, 0x2D00, 1}, /* REF_FREQ_38_4*/
		{   40, 0,      0xC, 6, 0x2EE0, 1}, /* REF_FREQ_40_0*/
		{   47, 162280, 0xC, 6, 0x2760, 1}  /* REF_FREQ_33_6        */
	};

	/* read NVS params */
	scr_pad6 = wl1251_reg_read32(wl, SCR_PAD6);
	wl1251_debug(DEBUG_BOOT, "scr_pad6 0x%x", scr_pad6);

	/* read ELP_CMD */
	elp_cmd = wl1251_reg_read32(wl, ELP_CMD);
	wl1251_debug(DEBUG_BOOT, "elp_cmd 0x%x", elp_cmd);

	/* set the BB calibration time to be 300 usec (PLL_CAL_TIME) */
	ref_freq = scr_pad6 & 0x000000FF;
	wl1251_debug(DEBUG_BOOT, "ref_freq 0x%x", ref_freq);

	wl1251_reg_write32(wl, PLL_CAL_TIME, 0x9);

	/*
	 * PG 1.2: set the clock buffer time to be 210 usec (CLK_BUF_TIME)
	 */
	wl1251_reg_write32(wl, CLK_BUF_TIME, 0x6);

	/*
	 * set the clock detect feature to work in the restart wu procedure
	 * (ELP_CFG_MODE[14]) and Select the clock source type
	 * (ELP_CFG_MODE[13:12])
	 */
	tmp = ((scr_pad6 & 0x0000FF00) << 4) | 0x00004000;
	wl1251_reg_write32(wl, ELP_CFG_MODE, tmp);

	/* PG 1.2: enable the BB PLL fix. Enable the PLL_LIMP_CLK_EN_CMD */
	elp_cmd |= 0x00000040;
	wl1251_reg_write32(wl, ELP_CMD, elp_cmd);

	/* PG 1.2: Set the BB PLL stable time to be 1000usec
	 * (PLL_STABLE_TIME) */
	wl1251_reg_write32(wl, CFG_PLL_SYNC_CNT, 0x20);

	/* PG 1.2: read clock request time */
	init_data = wl1251_reg_read32(wl, CLK_REQ_TIME);

	/*
	 * PG 1.2: set the clock request time to be ref_clk_settling_time -
	 * 1ms = 4ms
	 */
	if (init_data > 0x21)
		tmp = init_data - 0x21;
	else
		tmp = 0;
	wl1251_reg_write32(wl, CLK_REQ_TIME, tmp);

	/* set BB PLL configurations in RF AFE */
	wl1251_reg_write32(wl, 0x003058cc, 0x4B5);

	/* set RF_AFE_REG_5 */
	wl1251_reg_write32(wl, 0x003058d4, 0x50);

	/* set RF_AFE_CTRL_REG_2 */
	wl1251_reg_write32(wl, 0x00305948, 0x11c001);

	/*
	 * change RF PLL and BB PLL divider for VCO clock and adjust VCO
	 * bais current(RF_AFE_REG_13)
	 */
	wl1251_reg_write32(wl, 0x003058f4, 0x1e);

	/* set BB PLL configurations */
	tmp = LUT[ref_freq][LUT_PARAM_INTEGER_DIVIDER] | 0x00017000;
	wl1251_reg_write32(wl, 0x00305840, tmp);

	/* set fractional divider according to Appendix C-BB PLL
	 * Calculations
	 */
	tmp = LUT[ref_freq][LUT_PARAM_FRACTIONAL_DIVIDER];
	wl1251_reg_write32(wl, 0x00305844, tmp);

	/* set the initial data for the sigma delta */
	wl1251_reg_write32(wl, 0x00305848, 0x3039);

	/*
	 * set the accumulator attenuation value, calibration loop1
	 * (alpha), calibration loop2 (beta), calibration loop3 (gamma) and
	 * the VCO gain
	 */
	tmp = (LUT[ref_freq][LUT_PARAM_ATTN_BB] << 16) |
		(LUT[ref_freq][LUT_PARAM_ALPHA_BB] << 12) | 0x1;
	wl1251_reg_write32(wl, 0x00305854, tmp);

	/*
	 * set the calibration stop time after holdoff time expires and set
	 * settling time HOLD_OFF_TIME_BB
	 */
	tmp = LUT[ref_freq][LUT_PARAM_STOP_TIME_BB] | 0x000A0000;
	wl1251_reg_write32(wl, 0x00305858, tmp);

	/*
	 * set BB PLL Loop filter capacitor3- BB_C3[2:0] and set BB PLL
	 * constant leakage current to linearize PFD to 0uA -
	 * BB_ILOOPF[7:3]
	 */
	tmp = LUT[ref_freq][LUT_PARAM_BB_PLL_LOOP_FILTER] | 0x00000030;
	wl1251_reg_write32(wl, 0x003058f8, tmp);

	/*
	 * set regulator output voltage for n divider to
	 * 1.35-BB_REFDIV[1:0], set charge pump current- BB_CPGAIN[4:2],
	 * set BB PLL Loop filter capacitor2- BB_C2[7:5], set gain of BB
	 * PLL auto-call to normal mode- BB_CALGAIN_3DB[8]
	 */
	wl1251_reg_write32(wl, 0x003058f0, 0x29);

	/* enable restart wakeup sequence (ELP_CMD[0]) */
	wl1251_reg_write32(wl, ELP_CMD, elp_cmd | 0x1);

	/* restart sequence completed */
	udelay(2000);

	return 0;
}

static void wl1251_boot_set_ecpu_ctrl(struct wl1251 *wl, u32 flag)
{
	u32 cpu_ctrl;

	/* 10.5.0 run the firmware (I) */
	cpu_ctrl = wl1251_reg_read32(wl, ACX_REG_ECPU_CONTROL);

	/* 10.5.1 run the firmware (II) */
	cpu_ctrl &= ~flag;
	wl1251_reg_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
}

int wl1251_boot_run_firmware(struct wl1251 *wl)
{
	int loop, ret;
	u32 chip_id, acx_intr;

	wl1251_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT);

	chip_id = wl1251_reg_read32(wl, CHIP_ID_B);

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

	if (chip_id != wl->chip_id) {
		wl1251_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);
		acx_intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);

		if (acx_intr == 0xffffffff) {
			wl1251_error("error reading hardware complete "
				     "init indication");
			return -EIO;
		}
		/* check that ACX_INTR_INIT_COMPLETE is enabled */
		else if (acx_intr & WL1251_ACX_INTR_INIT_COMPLETE) {
			wl1251_reg_write32(wl, ACX_REG_INTERRUPT_ACK,
					   WL1251_ACX_INTR_INIT_COMPLETE);
			break;
		}
	}

	if (loop > INIT_LOOP) {
		wl1251_error("timeout waiting for the hardware to "
			     "complete initialization");
		return -EIO;
	}

	/* get hardware config command mail box */
	wl->cmd_box_addr = wl1251_reg_read32(wl, REG_COMMAND_MAILBOX_PTR);

	/* get hardware config event mail box */
	wl->event_box_addr = wl1251_reg_read32(wl, REG_EVENT_MAILBOX_PTR);

	/* set the working partition to its "running" mode offset */
	wl1251_set_partition(wl, WL1251_PART_WORK_MEM_START,
			     WL1251_PART_WORK_MEM_SIZE,
			     WL1251_PART_WORK_REG_START,
			     WL1251_PART_WORK_REG_SIZE);

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

	wl1251_acx_fw_version(wl, wl->fw_ver, sizeof(wl->fw_ver));

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

	/* enable gpio interrupts */
	wl1251_enable_interrupts(wl);

	/* Enable target's interrupts */
	wl->intr_mask = WL1251_ACX_INTR_RX0_DATA |
		WL1251_ACX_INTR_RX1_DATA |
		WL1251_ACX_INTR_TX_RESULT |
		WL1251_ACX_INTR_EVENT_A |
		WL1251_ACX_INTR_EVENT_B |
		WL1251_ACX_INTR_INIT_COMPLETE;
	wl1251_boot_target_enable_interrupts(wl);

	wl->event_mask = SCAN_COMPLETE_EVENT_ID | BSS_LOSE_EVENT_ID |
		SYNCHRONIZATION_TIMEOUT_EVENT_ID |
		ROAMING_TRIGGER_LOW_RSSI_EVENT_ID |
		ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID |
		REGAINED_BSS_EVENT_ID | BT_PTA_SENSE_EVENT_ID |
		BT_PTA_PREDICTION_EVENT_ID | JOIN_EVENT_COMPLETE_ID |
		PS_REPORT_EVENT_ID;

	ret = wl1251_event_unmask(wl);
	if (ret < 0) {
		wl1251_error("EVENT mask setting failed");
		return ret;
	}

	wl1251_event_mbox_config(wl);

	/* firmware startup completed */
	return 0;
}

static int wl1251_boot_upload_firmware(struct wl1251 *wl)
{
	int addr, chunk_num, partition_limit;
	size_t fw_data_len, len;
	u8 *p, *buf;

	/* whal_FwCtrl_LoadFwImageSm() */

	wl1251_debug(DEBUG_BOOT, "chip id before fw upload: 0x%x",
		     wl1251_reg_read32(wl, CHIP_ID_B));

	/* 10.0 check firmware length and set partition */
	fw_data_len =  (wl->fw[4] << 24) | (wl->fw[5] << 16) |
		(wl->fw[6] << 8) | (wl->fw[7]);

	wl1251_debug(DEBUG_BOOT, "fw_data_len %zu chunk_size %d", fw_data_len,
		CHUNK_SIZE);

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

	buf = kmalloc(CHUNK_SIZE, GFP_KERNEL);
	if (!buf) {
		wl1251_error("allocation for firmware upload chunk failed");
		return -ENOMEM;
	}

	wl1251_set_partition(wl, WL1251_PART_DOWN_MEM_START,
			     WL1251_PART_DOWN_MEM_SIZE,
			     WL1251_PART_DOWN_REG_START,
			     WL1251_PART_DOWN_REG_SIZE);

	/* 10.1 set partition limit and chunk num */
	chunk_num = 0;
	partition_limit = WL1251_PART_DOWN_MEM_SIZE;

	while (chunk_num < fw_data_len / CHUNK_SIZE) {
		/* 10.2 update partition, if needed */
		addr = WL1251_PART_DOWN_MEM_START +
			(chunk_num + 2) * CHUNK_SIZE;
		if (addr > partition_limit) {
			addr = WL1251_PART_DOWN_MEM_START +
				chunk_num * CHUNK_SIZE;
			partition_limit = chunk_num * CHUNK_SIZE +
				WL1251_PART_DOWN_MEM_SIZE;
			wl1251_set_partition(wl,
					     addr,
					     WL1251_PART_DOWN_MEM_SIZE,
					     WL1251_PART_DOWN_REG_START,
					     WL1251_PART_DOWN_REG_SIZE);
		}

		/* 10.3 upload the chunk */
		addr = WL1251_PART_DOWN_MEM_START + chunk_num * CHUNK_SIZE;
		p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE;
		wl1251_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x",
			     p, addr);

		/* need to copy the chunk for dma */
		len = CHUNK_SIZE;
		memcpy(buf, p, len);
		wl1251_mem_write(wl, addr, buf, len);

		chunk_num++;
	}

	/* 10.4 upload the last chunk */
	addr = WL1251_PART_DOWN_MEM_START + chunk_num * CHUNK_SIZE;
	p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE;

	/* need to copy the chunk for dma */
	len = fw_data_len % CHUNK_SIZE;
	memcpy(buf, p, len);

	wl1251_debug(DEBUG_BOOT, "uploading fw last chunk (%zu B) 0x%p to 0x%x",
		     len, p, addr);
	wl1251_mem_write(wl, addr, buf, len);

	kfree(buf);

	return 0;
}

static int wl1251_boot_upload_nvs(struct wl1251 *wl)
{
	size_t nvs_len, nvs_bytes_written, burst_len;
	int nvs_start, i;
	u32 dest_addr, val;
	u8 *nvs_ptr, *nvs;

	nvs = wl->nvs;
	if (nvs == NULL)
		return -ENODEV;

	nvs_ptr = nvs;

	nvs_len = wl->nvs_len;
	nvs_start = wl->fw_len;

	/*
	 * 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.
	 */

	while (nvs_ptr[0]) {
		burst_len = nvs_ptr[0];
		dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8));

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

		for (i = 0; i < burst_len; i++) {
			val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
			       | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));

			wl1251_debug(DEBUG_BOOT,
				     "nvs burst write 0x%x: 0x%x",
				     dest_addr, val);
			wl1251_mem_write32(wl, dest_addr, val);

			nvs_ptr += 4;
			dest_addr += 4;
		}
	}

	/*
	 * We've reached the first zero length, the first NVS table
	 * is 7 bytes further.
	 */
	nvs_ptr += 7;
	nvs_len -= nvs_ptr - nvs;
	nvs_len = ALIGN(nvs_len, 4);

	/* Now we must set the partition correctly */
	wl1251_set_partition(wl, nvs_start,
			     WL1251_PART_DOWN_MEM_SIZE,
			     WL1251_PART_DOWN_REG_START,
			     WL1251_PART_DOWN_REG_SIZE);

	/* And finally we upload the NVS tables */
	nvs_bytes_written = 0;
	while (nvs_bytes_written < nvs_len) {
		val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
		       | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));

		wl1251_debug(DEBUG_BOOT,
			     "nvs write table 0x%x: 0x%x",
			     nvs_start, val);
		wl1251_mem_write32(wl, nvs_start, val);

		nvs_ptr += 4;
		nvs_bytes_written += 4;
		nvs_start += 4;
	}

	return 0;
}

int wl1251_boot(struct wl1251 *wl)
{
	int ret = 0, minor_minor_e2_ver;
	u32 tmp, boot_data;

	/* halt embedded ARM CPU while loading firmware */
	wl1251_reg_write32(wl, ACX_REG_ECPU_CONTROL, ECPU_CONTROL_HALT);

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

	/* 2. start processing NVS file */
	if (wl->use_eeprom) {
		wl1251_reg_write32(wl, ACX_REG_EE_START, START_EEPROM_MGR);
		/* Wait for EEPROM NVS burst read to complete */
		msleep(40);
		wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, USE_EEPROM);
	} else {
		ret = wl1251_boot_upload_nvs(wl);
		if (ret < 0)
			goto out;

		/* write firmware's last address (ie. it's length) to
		 * ACX_EEPROMLESS_IND_REG */
		wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, wl->fw_len);
	}

	/* 6. read the EEPROM parameters */
	tmp = wl1251_reg_read32(wl, SCR_PAD2);

	/* 7. read bootdata */
	wl->boot_attr.radio_type = (tmp & 0x0000FF00) >> 8;
	wl->boot_attr.major = (tmp & 0x00FF0000) >> 16;
	tmp = wl1251_reg_read32(wl, SCR_PAD3);

	/* 8. check bootdata and call restart sequence */
	wl->boot_attr.minor = (tmp & 0x00FF0000) >> 16;
	minor_minor_e2_ver = (tmp & 0xFF000000) >> 24;

	wl1251_debug(DEBUG_BOOT, "radioType 0x%x majorE2Ver 0x%x "
		     "minorE2Ver 0x%x minor_minor_e2_ver 0x%x",
		     wl->boot_attr.radio_type, wl->boot_attr.major,
		     wl->boot_attr.minor, minor_minor_e2_ver);

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

	/* 9. NVS processing done */
	boot_data = wl1251_reg_read32(wl, ACX_REG_ECPU_CONTROL);

	wl1251_debug(DEBUG_BOOT, "halt boot_data 0x%x", boot_data);

	/* 10. check that ECPU_CONTROL_HALT bits are set in
	 * pWhalBus->uBootData and start uploading firmware
	 */
	if ((boot_data & ECPU_CONTROL_HALT) == 0) {
		wl1251_error("boot failed, ECPU_CONTROL_HALT not set");
		ret = -EIO;
		goto out;
	}

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

	/* 10.5 start firmware */
	ret = wl1251_boot_run_firmware(wl);
	if (ret < 0)
		goto out;

out:
	return ret;
}
