blob: 75fe80734e485a309c51efc6ed181142fb947950 [file] [log] [blame]
#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 AML_ADC_SAMPLE_DEBUG 0
#define FLAG_BUSY_KERNEL (1<<14) /* for bl30 */
#define FLAG_BUSY_BL30 (1<<15) /* for bl30 */
#define PP_AO_SEC_SD_CFG8 (volatile unsigned int *)(0xc8100000 + (0x88 << 2))
#if 0 /*For Mbox Platform*/
#define GXBB_CLK_REG (volatile unsigned int *)0xc883c3d8
#define P_SAR_SAR_ADC_REG0 (volatile unsigned int *)0xc1108680
#define P_SAR_ADC_CHAN_LIST (volatile unsigned int *)0xc1108684
#define P_SAR_ADC_AVG_CNTL (volatile unsigned int *)0xc1108688
#define P_SAR_ADC_REG3 (volatile unsigned int *)0xc110868c
#define P_SAR_ADC_DELAY (volatile unsigned int *)0xc1108690
#define P_SAR_ADC_LAST_RD (volatile unsigned int *)0xc1108694
#define P_SAR_ADC_FIFO_RD (volatile unsigned int *)0xc1108698
#define P_SAR_ADC_AUX_SW (volatile unsigned int *)0xc110869c
#define P_SAR_ADC_CHAN_10_SW (volatile unsigned int *)0xc11086a0
#define P_SAR_ADC_DETECT_IDLE_SW (volatile unsigned int *)0xc11086a4
#define P_SAR_ADC_DELTA_10 (volatile unsigned int *)0xc11086a8
#define P_SAR_ADC_DELTA_11 (volatile unsigned int *)0xc11086aC
#else /*For TV Platform*/
#define GXBB_CLK_REG (volatile unsigned int *)0xc8100090
#define P_SAR_SAR_ADC_REG0 (volatile unsigned int *)0xc8100600
#define P_SAR_ADC_CHAN_LIST (volatile unsigned int *)0xc8100604
#define P_SAR_ADC_AVG_CNTL (volatile unsigned int *)0xc8100608
#define P_SAR_ADC_REG3 (volatile unsigned int *)0xc810060c
#define P_SAR_ADC_DELAY (volatile unsigned int *)0xc8100610
#define P_SAR_ADC_LAST_RD (volatile unsigned int *)0xc8100614
#define P_SAR_ADC_FIFO_RD (volatile unsigned int *)0xc8100618
#define P_SAR_ADC_AUX_SW (volatile unsigned int *)0xc810061c
#define P_SAR_ADC_CHAN_10_SW (volatile unsigned int *)0xc8100620
#define P_SAR_ADC_DETECT_IDLE_SW (volatile unsigned int *)0xc8100624
#define P_SAR_ADC_DELTA_10 (volatile unsigned int *)0xc8100628
#define P_SAR_ADC_DELTA_11 (volatile unsigned int *)0xc810062c
#define P_SAR_ADC_REG13 (volatile unsigned int *)0xc8100634
#endif
#define PP_SAR_ADC_REG0 P_SAR_SAR_ADC_REG0
#define PP_SAR_ADC_CHAN_LIST P_SAR_ADC_CHAN_LIST
#define PP_SAR_ADC_AVG_CNTL P_SAR_ADC_AVG_CNTL
#define PP_SAR_ADC_REG3 P_SAR_ADC_REG3
#define PP_SAR_ADC_DELAY P_SAR_ADC_DELAY
#define PP_SAR_ADC_LAST_RD P_SAR_ADC_LAST_RD
#define PP_SAR_ADC_FIFO_RD P_SAR_ADC_FIFO_RD
#define PP_SAR_ADC_AUX_SW P_SAR_ADC_AUX_SW
#define PP_SAR_ADC_CHAN_10_SW P_SAR_ADC_CHAN_10_SW
#define PP_SAR_ADC_DETECT_IDLE_SW P_SAR_ADC_DETECT_IDLE_SW
#define PP_SAR_ADC_DELTA_10 P_SAR_ADC_DELTA_10
#define PP_SAR_ADC_DELTA_11 P_SAR_ADC_DELTA_11
#define PP_SAR_ADC_REG13 P_SAR_ADC_REG13
#define set_bits aml_set_reg32_bits
#define get_bits aml_get_reg32_bits
#define set_reg aml_write_reg32
#define get_reg aml_read_reg32
static int adc_type; /*1:12bit; 0:10bit*/
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(PP_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(GXBB_CLK_REG,1,8,1);
else
aml_set_reg32_bits(PP_SAR_ADC_REG3,1,30,1);
} else {
if (get_cpu_family_id() >= MESON_CPU_MAJOR_ID_GXBB)
aml_set_reg32_bits(GXBB_CLK_REG,0,8,1);
else
aml_set_reg32_bits(PP_SAR_ADC_REG3,0,30,1);
}
}
static inline void saradc_power_control(int on)
{
if (on) {
aml_set_reg32_bits(PP_SAR_ADC_DELTA_11,1,13,1);
aml_set_reg32_bits(PP_SAR_ADC_DELTA_11,3,5,2);
aml_set_reg32_bits(PP_SAR_ADC_REG3,1,21,1);
_udelay(5);
saradc_clock_switch(1);
} else {
saradc_clock_switch(0);
aml_set_reg32_bits(PP_SAR_ADC_REG3,0,30,1);
/*aml_set_reg32_bits(PP_SAR_ADC_DELTA_11,0,13,1);*//* disable bandgap */
aml_set_reg32_bits(PP_SAR_ADC_DELTA_11,0,5,2);
}
}
/*
* 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) { /*bit0-bit7*/
val = val & 0xff;
aml_write_reg32(GXBB_CLK_REG, (0<<9) | (val << 0));
} else { /*bit10-bit15*/
val = val & 0x3f;
aml_set_reg32_bits(PP_SAR_ADC_REG3,val,10,5);
}
}
int get_adc_sample_gxbb(int ch);
static void saradc_internal_cal_12bit(void)
{
int val[5]/*, nominal[5] = {0, 1024, 2048, 3072, 4096}*/;
int i;
int abs_val = 4096;
unsigned int abs_num = 0;
unsigned int abs_tmp = 0;
/* set CAL_CNTL: 3/4 VDD*/
aml_set_reg32_bits(PP_SAR_ADC_REG3,3,23,3);
for (i = 0; i < 64; i++) {
aml_set_reg32_bits(PP_SAR_ADC_REG13,i,8,6);
_udelay(5);
val[0] = get_adc_sample_gxbb(7);
if (val[0] < 3050/4) {
abs_tmp = 3050/4 - val[0];
if (abs_tmp < abs_val) {
abs_val = abs_tmp;
abs_num = i;
}
}
}
aml_set_reg32_bits(PP_SAR_ADC_REG13,abs_num,8,6);
/*for (i=0;i<5;i++) {
aml_set_reg32_bits(PP_SAR_ADC_REG3,i,23,3);
_udelay(5);
val[0] = get_adc_sample_gxbb(7);
uart_put_hex(val[0], 32);
uart_puts("\n");
}*/
}
void saradc_enable(void)
{
static int init_times=0;
if (get_cpu_family_id() <= MESON_CPU_MAJOR_ID_GXTVBB)
adc_type = 0;
else
adc_type = 1;
set_reg(P_SAR_SAR_ADC_REG0, 0x84004040);
set_reg(PP_SAR_ADC_CHAN_LIST, 0);
/* REG2: all chanel set to 8-samples & median averaging mode */
set_reg(PP_SAR_ADC_AVG_CNTL, 0);
set_reg(PP_SAR_ADC_REG3, 0x9388000a);
aml_set_reg32_bits(PP_SAR_ADC_REG3,0x14,10,5);
/*gxl change vdd
set_reg(PP_SAR_ADC_REG13, );
gxl change sampling mode */
if (adc_type)
aml_set_reg32_bits(PP_SAR_ADC_REG3,0x1,27,1);
saradc_clock_set(20);
set_reg(PP_SAR_ADC_DELAY, 0x10a000a);
set_reg(PP_SAR_ADC_AUX_SW, 0x3eb1a0c);
set_reg(PP_SAR_ADC_CHAN_10_SW, 0x8c000c);
set_reg(PP_SAR_ADC_DETECT_IDLE_SW, 0xc000c);
#if AML_ADC_SAMPLE_DEBUG
printf("ADCREG reg0 =%x\n", get_reg(PP_SAR_ADC_REG0));
printf("ADCREG ch list =%x\n",get_reg(PP_SAR_ADC_CHAN_LIST));
printf("ADCREG avg =%x\n", get_reg(PP_SAR_ADC_AVG_CNTL));
printf("ADCREG reg3 =%x\n", get_reg(PP_SAR_ADC_REG3));
printf("ADCREG ch72 sw =%x\n",get_reg(PP_SAR_ADC_AUX_SW));
printf("ADCREG ch10 sw =%x\n",get_reg(PP_SAR_ADC_CHAN_10_SW));
printf("ADCREG detect&idle=%x\n",get_reg(PP_SAR_ADC_DETECT_IDLE_SW));
printf("ADCREG GXBB_CLK_REG=%x\n",get_reg(GXBB_CLK_REG));
#endif //AML_ADC_SAMPLE_DEBUG
saradc_power_control(1);
if (!init_times) {
init_times = 1;
saradc_internal_cal_12bit();
}
}
int get_adc_sample_gxbb(int ch)
{
int value=0;
int count=0;
int sum=0;
//static int nn=0;
//unsigned long flags;
count = 0;
while (aml_read_reg32(PP_SAR_ADC_DELAY) & FLAG_BUSY_BL30) {
_udelay(100);
if (++count > 100) {
//printf("bl30 busy error\n");
uart_puts(".bl30 busy error");
uart_puts("\n");
value = -1;
goto end1;
}
}
aml_set_reg32_bits(PP_SAR_ADC_DELAY,1,FLAG_BUSY_KERNEL,1);
/*
count = 0;
while (aml_get_reg32_bits(PP_SAR_ADC_REG0,21,5) && (count < 32)) {
value = aml_read_reg32(PP_SAR_ADC_FIFO_RD);
count++;
}
*/
aml_set_reg32_bits(PP_SAR_ADC_REG3,1,29,1);
set_reg(PP_SAR_ADC_CHAN_LIST, ch);
set_reg(PP_SAR_ADC_DETECT_IDLE_SW, (0xc000c | (ch<<23) | (ch<<7)));
aml_set_reg32_bits(PP_SAR_ADC_REG0, 1,0,1);
aml_set_reg32_bits(PP_SAR_ADC_REG0, 1,2,1);
count = 0;
do {
_udelay(10);
//nn=10000;
//while(nn--);
if (!(aml_read_reg32(P_SAR_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(PP_SAR_ADC_REG0,21,5) && (count < 32)) {
if (aml_get_reg32_bits(PP_SAR_ADC_REG0,26,1)) {
uart_puts("fifo_count, but fifo empty");
uart_puts("\n");
}
value = aml_read_reg32(PP_SAR_ADC_FIFO_RD);
if (((value>>12) & 0x07) == ch) {
value &= 0xffc;
value >>= 2;
sum += value;
count++;
} else {
uart_puts("chanel error");
uart_puts("\n");
}
}
if (!aml_get_reg32_bits(PP_SAR_ADC_REG0,26,1)) {
uart_puts("fifo_count=0, but fifo not empty");
uart_puts("\n");
}
if (!count) {
value = -1;
goto end;
}
value = sum / count;
end:
aml_set_reg32_bits(PP_SAR_ADC_REG0,1,14,1);
aml_set_reg32_bits(PP_SAR_ADC_REG0,0,0,1);
end1:
aml_set_reg32_bits(PP_SAR_ADC_REG3,0,29,1);
aml_set_reg32_bits(PP_SAR_ADC_DELAY,0,FLAG_BUSY_KERNEL,1);
return value;
}
int saradc_disable(void)
{
saradc_power_control(0);
return 0;
}
int check_adc_key_resume(void)
{
int value;
/*the sampling value of adc: 0-1023*/
value = get_adc_sample_gxbb(2);
if ((value >= 0) && (value <= 40))
return 1;
else
return 0;
}