#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

static int adc_type; /*1:12bit; 0:10bit*/
unsigned int channel = 0xffff;
unsigned int keycode;

int get_adc_sample_gxbb(int ch);

static void aml_set_reg32_bits(volatile unsigned int *_reg,
		const unsigned int _value,
		const unsigned int _start,
		const unsigned int _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 unsigned int *_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 unsigned int *_reg,
		const unsigned int _value)
{
	writel( _value, (volatile unsigned int *)_reg );
};

static unsigned int aml_read_reg32(volatile unsigned int *_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);
		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, 0x9388000a);

	if (adc_type)
		aml_set_reg32_bits(P_AO_SAR_ADC_REG3, 0x1, 27, 1);

	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);

	saradc_power_control(1);
}

int saradc_value_trim(int val)
{
	int tmp;

	switch (get_cpu_family_id()) {
		case MESON_CPU_MAJOR_ID_GXL:
		case MESON_CPU_MAJOR_ID_GXM:
		case MESON_CPU_MAJOR_ID_TXL:
			tmp = val * 3072 / 2764;
			return (tmp < 1024) ? tmp : 1023;
			break;

		default:
			return val;
			break;
	}
}

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 saradc_value_trim(value);
}

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

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

	if (channel == 0xffff) {
		channel = CONFIG_ADC_POWER_KEY_CHAN;
		keycode = CONFIG_ADC_POWER_KEY_VAL;
	}

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

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