/*
 * rtl8712_efuse.c
 *
 * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
 * Linux device driver for RTL8192SU
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA
 *
 * Modifications for inclusion into the Linux staging tree are
 * Copyright(c) 2010 Larry Finger. All rights reserved.
 *
 * Contact information:
 * WLAN FAE <wlanfae@realtek.com>.
 * Larry Finger <Larry.Finger@lwfinger.net>
 *
 ******************************************************************************/

#define _RTL8712_EFUSE_C_

#include "osdep_service.h"
#include "drv_types.h"
#include "rtl8712_efuse.h"

/* reserve 3 bytes for HW stop read */
static int efuse_available_max_size = EFUSE_MAX_SIZE - 3 /*0x1FD*/;

static void efuse_reg_ctrl(struct _adapter *padapter, u8 bPowerOn)
{
	u8 tmpu8 = 0;

	if (true == bPowerOn) {
		/* -----------------e-fuse pwr & clk reg ctrl ---------------
		 * Enable LDOE25 Macro Block
		 */
		tmpu8 = r8712_read8(padapter, EFUSE_TEST + 3);
		tmpu8 |= 0x80;
		r8712_write8(padapter, EFUSE_TEST + 3, tmpu8);
		msleep(20); /* for some platform , need some delay time */
		/* Change Efuse Clock for write action to 40MHZ */
		r8712_write8(padapter, EFUSE_CLK_CTRL, 0x03);
		msleep(20); /* for some platform , need some delay time */
	} else {
		/* -----------------e-fuse pwr & clk reg ctrl -----------------
		 * Disable LDOE25 Macro Block
		 */
		tmpu8 = r8712_read8(padapter, EFUSE_TEST + 3);
		tmpu8 &= 0x7F;
		r8712_write8(padapter, EFUSE_TEST + 3, tmpu8);
		/* Change Efuse Clock for write action to 500K */
		r8712_write8(padapter, EFUSE_CLK_CTRL, 0x02);
	}
}

/*
 * Before write E-Fuse, this function must be called.
 */
u8 r8712_efuse_reg_init(struct _adapter *padapter)
{
	return true;
}

void r8712_efuse_reg_uninit(struct _adapter *padapter)
{
	efuse_reg_ctrl(padapter, false);
}

static u8 efuse_one_byte_read(struct _adapter *padapter, u16 addr, u8 *data)
{
	u8 tmpidx = 0, bResult;

	/* -----------------e-fuse reg ctrl --------------------------------- */
	r8712_write8(padapter, EFUSE_CTRL+1, (u8)(addr&0xFF)); /* address */
	r8712_write8(padapter, EFUSE_CTRL+2, ((u8)((addr>>8)&0x03)) |
	       (r8712_read8(padapter, EFUSE_CTRL+2)&0xFC));
	r8712_write8(padapter, EFUSE_CTRL+3, 0x72); /* read cmd */
	/* wait for complete */
	while (!(0x80 & r8712_read8(padapter, EFUSE_CTRL+3)) && (tmpidx < 100))
		tmpidx++;
	if (tmpidx < 100) {
		*data = r8712_read8(padapter, EFUSE_CTRL);
		bResult = true;
	} else {
		*data = 0xff;
		bResult = false;
	}
	return bResult;
}

static u8 efuse_one_byte_write(struct _adapter *padapter, u16 addr, u8 data)
{
	u8 tmpidx = 0, bResult;

	/* -----------------e-fuse reg ctrl -------------------------------- */
	r8712_write8(padapter, EFUSE_CTRL+1, (u8)(addr&0xFF)); /* address */
	r8712_write8(padapter, EFUSE_CTRL+2, ((u8)((addr>>8)&0x03)) |
	       (r8712_read8(padapter, EFUSE_CTRL+2)&0xFC));
	r8712_write8(padapter, EFUSE_CTRL, data); /* data */
	r8712_write8(padapter, EFUSE_CTRL+3, 0xF2); /* write cmd */
	/* wait for complete */
	while ((0x80 &  r8712_read8(padapter, EFUSE_CTRL+3)) && (tmpidx < 100))
		tmpidx++;
	if (tmpidx < 100)
		bResult = true;
	else
		bResult = false;
	return bResult;
}

static u8 efuse_one_byte_rw(struct _adapter *padapter, u8 bRead, u16 addr,
			    u8 *data)
{
	u8 tmpidx = 0, tmpv8 = 0, bResult;

	/* -----------------e-fuse reg ctrl --------------------------------- */
	r8712_write8(padapter, EFUSE_CTRL+1, (u8)(addr&0xFF)); /* address */
	tmpv8 = ((u8)((addr >> 8) & 0x03)) |
		 (r8712_read8(padapter, EFUSE_CTRL + 2) & 0xFC);
	r8712_write8(padapter, EFUSE_CTRL+2, tmpv8);
	if (true == bRead) {
		r8712_write8(padapter, EFUSE_CTRL+3,  0x72); /* read cmd */
		while (!(0x80 & r8712_read8(padapter, EFUSE_CTRL+3)) &&
		       (tmpidx < 100))
			tmpidx++;
		if (tmpidx < 100) {
			*data = r8712_read8(padapter, EFUSE_CTRL);
			bResult = true;
		} else {
			*data = 0;
			bResult = false;
		}
	} else {
		r8712_write8(padapter, EFUSE_CTRL, *data); /* data */
		r8712_write8(padapter, EFUSE_CTRL+3, 0xF2); /* write cmd */
		while ((0x80 & r8712_read8(padapter, EFUSE_CTRL+3)) &&
		       (tmpidx < 100))
			tmpidx++;
		if (tmpidx < 100)
			bResult = true;
		else
			bResult = false;
	}
	return bResult;
}

static u8 efuse_is_empty(struct _adapter *padapter, u8 *empty)
{
	u8 value, ret = true;

	/* read one byte to check if E-Fuse is empty */
	if (efuse_one_byte_rw(padapter, true, 0, &value) == true) {
		if (0xFF == value)
			*empty = true;
		else
			*empty = false;
	} else
		ret = false;
	return ret;
}

void r8712_efuse_change_max_size(struct _adapter *padapter)
{
	u16 pre_pg_data_saddr = 0x1FB;
	u16 i;
	u16 pre_pg_data_size = 5;
	u8 pre_pg_data[5];

	for (i = 0; i < pre_pg_data_size; i++)
		efuse_one_byte_read(padapter, pre_pg_data_saddr + i,
				    &pre_pg_data[i]);
	if ((pre_pg_data[0] == 0x03) && (pre_pg_data[1] == 0x00) &&
	    (pre_pg_data[2] == 0x00) && (pre_pg_data[3] == 0x00) &&
	    (pre_pg_data[4] == 0x0C))
		efuse_available_max_size -= pre_pg_data_size;
}

int r8712_efuse_get_max_size(struct _adapter *padapter)
{
	return	efuse_available_max_size;
}

static u8 calculate_word_cnts(const u8 word_en)
{
	u8 word_cnts = 0;
	u8 word_idx;

	for (word_idx = 0; word_idx < PGPKG_MAX_WORDS; word_idx++)
		if (!(word_en & BIT(word_idx)))
			word_cnts++; /* 0 : write enable */
	return word_cnts;
}

static void pgpacket_copy_data(const u8 word_en, const u8 *sourdata,
			       u8 *targetdata)
{
	u8 tmpindex = 0;
	u8 word_idx, byte_idx;

	for (word_idx = 0; word_idx < PGPKG_MAX_WORDS; word_idx++) {
		if (!(word_en&BIT(word_idx))) {
			byte_idx = word_idx * 2;
			targetdata[byte_idx] = sourdata[tmpindex++];
			targetdata[byte_idx + 1] = sourdata[tmpindex++];
		}
	}
}

u16 r8712_efuse_get_current_size(struct _adapter *padapter)
{
	int bContinual = true;
	u16 efuse_addr = 0;
	u8 hoffset = 0, hworden = 0;
	u8 efuse_data, word_cnts = 0;

	while (bContinual && efuse_one_byte_read(padapter, efuse_addr,
	       &efuse_data) && (efuse_addr < efuse_available_max_size)) {
		if (efuse_data != 0xFF) {
			hoffset = (efuse_data >> 4) & 0x0F;
			hworden =  efuse_data & 0x0F;
			word_cnts = calculate_word_cnts(hworden);
			/* read next header */
			efuse_addr = efuse_addr + (word_cnts * 2) + 1;
		} else
			bContinual = false;
	}
	return efuse_addr;
}

u8 r8712_efuse_pg_packet_read(struct _adapter *padapter, u8 offset, u8 *data)
{
	u8 hoffset = 0, hworden = 0, word_cnts = 0;
	u16 efuse_addr = 0;
	u8 efuse_data;
	u8 tmpidx = 0;
	u8 tmpdata[PGPKT_DATA_SIZE];
	u8 ret = true;

	if (data == NULL)
		return false;
	if (offset > 0x0f)
		return false;
	memset(data, 0xFF, sizeof(u8)*PGPKT_DATA_SIZE);
	while (efuse_addr < efuse_available_max_size) {
		if (efuse_one_byte_read(padapter, efuse_addr, &efuse_data) ==
		    true) {
			if (efuse_data == 0xFF)
				break;
			hoffset = (efuse_data >> 4) & 0x0F;
			hworden =  efuse_data & 0x0F;
			word_cnts = calculate_word_cnts(hworden);
			if (hoffset == offset) {
				memset(tmpdata, 0xFF, PGPKT_DATA_SIZE);
				for (tmpidx = 0; tmpidx < word_cnts * 2;
				     tmpidx++) {
					if (efuse_one_byte_read(padapter,
					    efuse_addr+1+tmpidx, &efuse_data) ==
					     true) {
						tmpdata[tmpidx] = efuse_data;
					} else
						ret = false;
				}
				pgpacket_copy_data(hworden, tmpdata, data);
			}
			efuse_addr += 1 + (word_cnts*2);
		} else {
			ret = false;
			break;
		}
	}
	return ret;
}

static u8 fix_header(struct _adapter *padapter, u8 header, u16 header_addr)
{
	struct PGPKT_STRUCT pkt;
	u8 offset, word_en, value;
	u16 addr;
	int i;
	u8 ret = true;

	pkt.offset = GET_EFUSE_OFFSET(header);
	pkt.word_en = GET_EFUSE_WORD_EN(header);
	addr = header_addr + 1 + calculate_word_cnts(pkt.word_en) * 2;
	if (addr > efuse_available_max_size)
		return false;
	/* retrieve original data */
	addr = 0;
	while (addr < header_addr) {
		if (efuse_one_byte_read(padapter, addr++, &value) == false) {
			ret = false;
			break;
		}
		offset = GET_EFUSE_OFFSET(value);
		word_en = GET_EFUSE_WORD_EN(value);
		if (pkt.offset != offset) {
			addr += calculate_word_cnts(word_en)*2;
			continue;
		}
		for (i = 0; i < PGPKG_MAX_WORDS; i++) {
			if (BIT(i) & word_en) {
				if (BIT(i) & pkt.word_en) {
					if (efuse_one_byte_read(
							padapter, addr,
							&value) == true)
						pkt.data[i*2] = value;
					else
						return false;
					if (efuse_one_byte_read(
							padapter,
							addr + 1,
							&value) == true)
						pkt.data[i*2 + 1] =
							value;
					else
						return false;
				}
				addr += 2;
			}
		}
	}
	if (addr != header_addr)
		return false;
	addr++;
	/* fill original data */
	for (i = 0; i < PGPKG_MAX_WORDS; i++) {
		if (BIT(i) & pkt.word_en) {
			efuse_one_byte_write(padapter, addr, pkt.data[i*2]);
			efuse_one_byte_write(padapter, addr+1,
					pkt.data[i*2 + 1]);
			/* additional check */
			if (efuse_one_byte_read(padapter, addr, &value)
				== false)
				ret = false;
			else if (pkt.data[i*2] != value) {
				ret = false;
				if (0xFF == value) /* write again */
					efuse_one_byte_write(padapter, addr,
							pkt.data[i * 2]);
			}
			if (efuse_one_byte_read(padapter, addr+1, &value) ==
				false)
				ret = false;
			else if (pkt.data[i*2 + 1] != value) {
				ret = false;
				if (0xFF == value) /* write again */
					efuse_one_byte_write(padapter, addr+1,
							pkt.data[i*2 + 1]);
			}
		}
		addr += 2;
	}
	return ret;
}

u8 r8712_efuse_pg_packet_write(struct _adapter *padapter, const u8 offset,
			 const u8 word_en, const u8 *data)
{
	u8 pg_header = 0;
	u16 efuse_addr = 0, curr_size = 0;
	u8 efuse_data, target_word_cnts = 0;
	static int repeat_times;
	int sub_repeat;
	u8 bResult = true;

	/* check if E-Fuse Clock Enable and E-Fuse Clock is 40M */
	efuse_data = r8712_read8(padapter, EFUSE_CLK_CTRL);
	if (efuse_data != 0x03)
		return false;
	pg_header = MAKE_EFUSE_HEADER(offset, word_en);
	target_word_cnts = calculate_word_cnts(word_en);
	repeat_times = 0;
	efuse_addr = 0;
	while (efuse_addr < efuse_available_max_size) {
		curr_size = r8712_efuse_get_current_size(padapter);
		if ((curr_size + 1 + target_word_cnts * 2) >
		     efuse_available_max_size)
			return false; /*target_word_cnts + pg header(1 byte)*/
		efuse_addr = curr_size; /* current size is also the last addr*/
		efuse_one_byte_write(padapter, efuse_addr, pg_header); /*hdr*/
		sub_repeat = 0;
		/* check if what we read is what we write */
		while (efuse_one_byte_read(padapter, efuse_addr,
					   &efuse_data) == false) {
			if (++sub_repeat > _REPEAT_THRESHOLD_) {
				bResult = false; /* continue to blind write */
				break; /* continue to blind write */
			}
		}
		if ((sub_repeat > _REPEAT_THRESHOLD_) ||
		    (pg_header == efuse_data)) {
			/* write header ok OR can't check header(creep) */
			u8 i;

			/* go to next address */
			efuse_addr++;
			for (i = 0; i < target_word_cnts*2; i++) {
				efuse_one_byte_write(padapter,
						     efuse_addr + i,
						     *(data + i));
				if (efuse_one_byte_read(padapter,
				    efuse_addr + i, &efuse_data) == false)
					bResult = false;
				else if (*(data+i) != efuse_data) /* fail */
					bResult = false;
			}
			break;
		} else { /* write header fail */
			bResult = false;
			if (0xFF == efuse_data)
				return bResult; /* nothing damaged. */
			/* call rescue procedure */
			if (fix_header(padapter, efuse_data, efuse_addr) ==
			    false)
				return false; /* rescue fail */

			if (++repeat_times > _REPEAT_THRESHOLD_) /* fail */
				break;
			/* otherwise, take another risk... */
		}
	}
	return bResult;
}

u8 r8712_efuse_access(struct _adapter *padapter, u8 bRead, u16 start_addr,
		      u16 cnts, u8 *data)
{
	int i;
	u8 res = true;

	if (start_addr > EFUSE_MAX_SIZE)
		return false;
	if ((bRead == false) && ((start_addr + cnts) >
	   efuse_available_max_size))
		return false;
	if ((false == bRead) && (r8712_efuse_reg_init(padapter) == false))
		return false;
	/* -----------------e-fuse one byte read / write ---------------------*/
	for (i = 0; i < cnts; i++) {
		if ((start_addr + i) > EFUSE_MAX_SIZE) {
			res = false;
			break;
		}
		res = efuse_one_byte_rw(padapter, bRead, start_addr + i,
		      data + i);
		if ((false == bRead) && (false == res))
			break;
	}
	if (false == bRead)
		r8712_efuse_reg_uninit(padapter);
	return res;
}

u8 r8712_efuse_map_read(struct _adapter *padapter, u16 addr, u16 cnts, u8 *data)
{
	u8 offset, ret = true;
	u8 pktdata[PGPKT_DATA_SIZE];
	int i, idx;

	if ((addr + cnts) > EFUSE_MAP_MAX_SIZE)
		return false;
	if ((efuse_is_empty(padapter, &offset) == true) && (offset ==
	     true)) {
		for (i = 0; i < cnts; i++)
			data[i] = 0xFF;
		return ret;
	}
	offset = (addr >> 3) & 0xF;
	ret = r8712_efuse_pg_packet_read(padapter, offset, pktdata);
	i = addr & 0x7;	/* pktdata index */
	idx = 0;	/* data index */

	do {
		for (; i < PGPKT_DATA_SIZE; i++) {
			data[idx++] = pktdata[i];
			if (idx == cnts)
				return ret;
		}
		offset++;
		if (!r8712_efuse_pg_packet_read(padapter, offset, pktdata))
			ret = false;
		i = 0;
	} while (1);
	return ret;
}

u8 r8712_efuse_map_write(struct _adapter *padapter, u16 addr, u16 cnts,
			 u8 *data)
{
	u8 offset, word_en, empty;
	u8 pktdata[PGPKT_DATA_SIZE], newdata[PGPKT_DATA_SIZE];
	int i, j, idx;

	if ((addr + cnts) > EFUSE_MAP_MAX_SIZE)
		return false;
	/* check if E-Fuse Clock Enable and E-Fuse Clock is 40M */
	empty = r8712_read8(padapter, EFUSE_CLK_CTRL);
	if (empty != 0x03)
		return false;
	if (efuse_is_empty(padapter, &empty) == true) {
		if (true == empty)
			memset(pktdata, 0xFF, PGPKT_DATA_SIZE);
	} else
		return false;
	offset = (addr >> 3) & 0xF;
	if (empty == false)
		if (!r8712_efuse_pg_packet_read(padapter, offset, pktdata))
			return false;
	word_en = 0xF;
	memset(newdata, 0xFF, PGPKT_DATA_SIZE);
	i = addr & 0x7;	/* pktdata index */
	j = 0;		/* newdata index */
	idx = 0;	/* data index */

	if (i & 0x1) {
		/*  odd start */
		if (data[idx] != pktdata[i]) {
			word_en &= ~BIT(i >> 1);
			newdata[j++] = pktdata[i - 1];
			newdata[j++] = data[idx];
		}
		i++;
		idx++;
	}
	do {
		for (; i < PGPKT_DATA_SIZE; i += 2) {
			if ((cnts - idx) == 1) {
				if (data[idx] != pktdata[i]) {
					word_en &= ~BIT(i >> 1);
					newdata[j++] = data[idx];
					newdata[j++] = pktdata[1 + 1];
				}
				idx++;
				break;
			} else {
				if ((data[idx] != pktdata[i]) || (data[idx+1] !=
				     pktdata[i+1])) {
					word_en &= ~BIT(i >> 1);
					newdata[j++] = data[idx];
					newdata[j++] = data[idx + 1];
				}
				idx += 2;
			}
			if (idx == cnts)
				break;
		}

		if (word_en != 0xF)
			if (r8712_efuse_pg_packet_write(padapter, offset,
			    word_en, newdata) == false)
				return false;
		if (idx == cnts)
			break;
		offset++;
		if (empty == false)
			if (!r8712_efuse_pg_packet_read(padapter, offset,
			    pktdata))
				return false;
		i = 0;
		j = 0;
		word_en = 0xF;
		memset(newdata, 0xFF, PGPKT_DATA_SIZE);
	} while (1);

	return true;
}
