/*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
* *
This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* *
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.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* *
Description:
*/

#define MESON_CPU_MAJOR_ID_GXBB		0x1F
#define MESON_CPU_MAJOR_ID_GXTVBB	0x20
#define MESON_CPU_MAJOR_ID_GXL		0x21
#define MESON_CPU_MAJOR_ID_GXM		0x22
#define MESON_CPU_MAJOR_ID_TXL		0x23
#define MESON_CPU_MAJOR_ID_TXLX		0x24
#define MESON_CPU_MAJOR_ID_G12A		0x28

static int adc_type; /*1:12bit; 0:10bit*/

static void aml_set_reg32_bits(volatile uint32_t *_reg,
		const uint32_t _value,
		const uint32_t _start,
		const uint32_t _len)
{
	writel(((readl((volatile unsigned int *)_reg) & \
		~(((1L << (_len) )-1) << (_start))) | \
		((unsigned)((_value) & ((1L<<(_len))-1)) << (_start))),
		(volatile void *)_reg );
}

static unsigned int aml_get_reg32_bits(volatile uint32_t *_reg,
		const unsigned int _start,
		const unsigned int _len)
{
	return	((readl((volatile unsigned int *)_reg) >> (_start)) & \
		((1L << (_len) ) - 1));
}

static void aml_write_reg32(volatile uint32_t *_reg,
		const uint32_t _value)
{
	writel(_value, (volatile unsigned int *)_reg );
};

static unsigned int aml_read_reg32(volatile uint32_t *_reg)
{
	return readl((volatile unsigned int *)_reg);
};

static int get_cpu_family_id(void)
{
	return ((aml_read_reg32(P_AO_SEC_SD_CFG8) >> 24) & 0xff);
}

/*
 * description: used to enable and disable the clock of the SARADC
 * onoff: 1: enable ; 0: disable
 */
static void saradc_clock_switch(int onoff)
{
/* if the famiy id of the cpu greater than or equal to MESON_CPU_MAJOR_ID_GXBB,
 * the clock switch from the clock tree register, otherwise from
 * the adc module register.
 */
	if (onoff) {
		if (get_cpu_family_id() >= MESON_CPU_MAJOR_ID_GXBB)
			aml_set_reg32_bits(P_AO_SAR_CLK, 1, 8, 1);
		else
			aml_set_reg32_bits(P_AO_SAR_ADC_REG3, 1, 30, 1);
	} else {
		if (get_cpu_family_id() >= MESON_CPU_MAJOR_ID_GXBB)
			aml_set_reg32_bits(P_AO_SAR_CLK, 0, 8, 1);
		else
			aml_set_reg32_bits(P_AO_SAR_ADC_REG3, 0, 30, 1);
	}
}
static inline void saradc_power_control(int on)
{
	if (on) {
		aml_set_reg32_bits(P_AO_SAR_ADC_REG11, 1, 13, 1);
		if (get_cpu_family_id() >= MESON_CPU_MAJOR_ID_G12A)
			aml_set_reg32_bits(P_AO_SAR_ADC_REG11, 0, 5, 2);
		else
			aml_set_reg32_bits(P_AO_SAR_ADC_REG11, 3, 5, 2);
		aml_set_reg32_bits(P_AO_SAR_ADC_REG3, 1, 21, 1);

		_udelay(5);

		saradc_clock_switch(1);
	}	else {
		saradc_clock_switch(0);
		aml_set_reg32_bits(P_AO_SAR_ADC_REG3, 0, 21, 1);
	}
}

/*
 * description: used to set the DIV of the clock
 */
static void saradc_clock_set(unsigned char val)
{
/* if the famiy id of the cpu greater than or equal to MESON_CPU_MAJOR_ID_GXBB,
 * the clock switch from the clock tree register, otherwise from
 * the adc module register.
 */
	if (get_cpu_family_id() >= MESON_CPU_MAJOR_ID_GXBB) {
		/*bit[0-7]: set clk div; bit[9-10]: select clk source*/
		aml_set_reg32_bits(P_AO_SAR_CLK, 0, 9, 2);
		aml_set_reg32_bits(P_AO_SAR_CLK, (val & 0xff), 0, 8);
	} else {
		/*bit10-bit15: set clk div*/
		aml_set_reg32_bits(P_AO_SAR_ADC_REG3, (val & 0x3f), 10, 6);
	}
}

void saradc_enable(void)
{
	if (get_cpu_family_id() <= MESON_CPU_MAJOR_ID_GXTVBB)
		adc_type = 0;
	else
		adc_type = 1;

	aml_write_reg32(P_AO_SAR_ADC_REG0, 0x84004040);
	aml_write_reg32(P_AO_SAR_ADC_CHAN_LIST, 0);
	/* REG2: all chanel set to 8-samples & median averaging mode */
	aml_write_reg32(P_AO_SAR_ADC_AVG_CNTL, 0);
	aml_write_reg32(P_AO_SAR_ADC_REG3, 0x9b88000a);

	saradc_clock_set(20);

	aml_write_reg32(P_AO_SAR_ADC_DELAY, 0x10a000a);
	aml_write_reg32(P_AO_SAR_ADC_AUX_SW, 0x3eb1a0c);
	aml_write_reg32(P_AO_SAR_ADC_CHAN_10_SW, 0x8c000c);
	aml_write_reg32(P_AO_SAR_ADC_DETECT_IDLE_SW, 0xc000c);

	/* select the VDDA as Vref for txlx and later SoCs */
	aml_set_reg32_bits(P_AO_SAR_ADC_REG11, 1, 0, 1);

	/* REG11 bit[1] must be set to <1> for g12a and later SoCs */
	aml_set_reg32_bits(P_AO_SAR_ADC_REG11, 1, 1, 1);

	saradc_power_control(1);
}

int get_adc_sample_gxbb(int ch)
{
	int value=0;
	int count=0;
	int sum=0;

	aml_write_reg32(P_AO_SAR_ADC_CHAN_LIST, ch);
	aml_write_reg32(P_AO_SAR_ADC_DETECT_IDLE_SW, (0xc000c | (ch<<23) | (ch<<7)));
	aml_set_reg32_bits(P_AO_SAR_ADC_REG0, 1, 0, 1);
	aml_set_reg32_bits(P_AO_SAR_ADC_REG0, 1, 2, 1);

	count = 0;
	do {
		_udelay(10);
		if (!(aml_read_reg32(P_AO_SAR_ADC_REG0) & 0x70000000))
			break;
		else if (++count > 10000) {
			uart_puts("busy error");
			uart_puts("\n");
			value = -1;
			goto end;
		}
	} while (1);

	count = 0;
	sum = 0;
	while (aml_get_reg32_bits(P_AO_SAR_ADC_REG0, 21, 5) && (count < 32)) {
        value = aml_read_reg32(P_AO_SAR_ADC_FIFO_RD);
		if (((value >> 12) & 0x07) == ch) {
			value &= 0xffc;
			value >>= 2;
			sum += value;
			count++;
		} else {
			uart_puts("channel error");
			uart_puts("\n");
		}
	}
	if (!count) {
		value = -1;
		goto end;
	}
	value = sum / count;

end:
	aml_set_reg32_bits(P_AO_SAR_ADC_REG0, 1, 14, 1);
	aml_set_reg32_bits(P_AO_SAR_ADC_REG0, 0, 0, 1);

	return value;
}

int saradc_disable(void)
{
	saradc_power_control(0);
	return 0;
}

int check_adc_key_resume(void)
{
	int value;
	int min;
	int max;

	/*the sampling value of adc: 0-1023*/
	min = CONFIG_ADC_POWER_KEY_VAL - 40;
	if (min < 0)
		min = 0;
	max = CONFIG_ADC_POWER_KEY_VAL + 40;
	if (max > 1023)
		max = 1023;

	value = get_adc_sample_gxbb(CONFIG_ADC_POWER_KEY_CHAN);
	if ((value >= min) && (value <= max))
		return 1;
	else
		return 0;
}
