/* Copyright Statement: * * This software/firmware and related documentation ("MediaTek Software") are * protected under relevant copyright laws. The information contained herein * is confidential and proprietary to MediaTek Inc. and/or its licensors. * Without the prior written permission of MediaTek inc. and/or its licensors, * any reproduction, modification, use or disclosure of MediaTek Software, * and information contained herein, in whole or in part, shall be strictly prohibited. */ /* MediaTek Inc. (C) 2015. All rights reserved. * * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. */ /***************************************************************************** * * Filename: * --------- * mt6582_auxadc.c * * Project: * -------- * Android_Software * * Description: * ------------ * This Module defines functions of mt6573 AUXADC * * Author: * ------- * James Lo * ****************************************************************************/ //#include //#include #include #include #include #include /////////////////////////////////////////////////////////////////////////////////////////// //// Define static int adc_auto_set =0; static int adc_rtp_set =1; static unsigned short mt_tpd_read_adc(unsigned short pos) { *(volatile unsigned short *)AUXADC_TP_ADDR = pos; *(volatile unsigned short *)AUXADC_TP_CON0 = 0x01; while (0x01 & *(volatile unsigned short *)AUXADC_TP_CON0) { ; } //wait for write finish return *(volatile unsigned short *)AUXADC_TP_DATA0; } static void mt_auxadc_disable_penirq(void) { //disable RTP if (adc_rtp_set) { adc_rtp_set = 0; *(volatile unsigned short *)AUXADC_CON_RTP = 1; } //Turn off PENIRQ detection circuit *(volatile unsigned short *)AUXADC_TP_CMD = 1; //run once touch function mt_tpd_read_adc(TP_CMD_ADDR_X); } //step1 check con3 if auxadc is busy //step2 clear bit //step3 read channle and make sure old ready bit ==0 //step4 set bit to trigger sample //step5 read channle and make sure ready bit ==1 //step6 read data /////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// //// Common API int IMM_GetOneChannelValue(int dwChannel, int data[4], int* rawdata) { unsigned int channel[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; int idle_count =0; int data_ready_count=0; // mutex_lock(&mutex_get_cali_value); /* in uboot no pms api if(enable_clock(MT65XX_PDN_PERI_AUXADC,"AUXADC")) { //dprintf(1,"hwEnableClock AUXADC !!!."); if(enable_clock(MT65XX_PDN_PERI_AUXADC,"AUXADC")) {dprintf(1,"hwEnableClock AUXADC failed.");} } */ if (dwChannel == PAD_AUX_XP)mt_auxadc_disable_penirq(); //step1 check con3 if auxadc is busy while ((*(volatile unsigned short *)AUXADC_CON2) & 0x01) { dprintf(1,"[adc_api]: wait for module idle\n"); udelay(10000); idle_count++; if (idle_count>30) { //wait for idle time out dprintf(1,"[adc_api]: wait for aux/adc idle time out\n"); return -1; } } // step2 clear bit if (0 == adc_auto_set) { //clear bit *(volatile unsigned short *)AUXADC_CON1 = *(volatile unsigned short *)AUXADC_CON1 & (~(1 << dwChannel)); } //step3 read channle and make sure old ready bit ==0 while ((*(volatile unsigned short *)(AUXADC_DAT0 + dwChannel * 0x04)) & (1<<12)) { dprintf(1,"[adc_api]: wait for channel[%d] ready bit clear\n",dwChannel); udelay(10000); data_ready_count++; if (data_ready_count>30) { //wait for idle time out dprintf(1,"[adc_api]: wait for channel[%d] ready bit clear time out\n",dwChannel); return -2; } } //step4 set bit to trigger sample if (0==adc_auto_set) { *(volatile unsigned short *)AUXADC_CON1 = *(volatile unsigned short *)AUXADC_CON1 | (1 << dwChannel); } //step5 read channle and make sure ready bit ==1 udelay(25);//we must dealay here for hw sample channel data while (0==((*(volatile unsigned short *)(AUXADC_DAT0 + dwChannel * 0x04)) & (1<<12))) { dprintf(1,"[adc_api]: wait for channel[%d] ready bit ==1\n",dwChannel); udelay(10000); data_ready_count++; if (data_ready_count>30) { //wait for idle time out dprintf(1,"[adc_api]: wait for channel[%d] data ready time out\n",dwChannel); return -3; } } ////step6 read data channel[dwChannel] = (*(volatile unsigned short *)(AUXADC_DAT0 + dwChannel * 0x04)) & 0x0FFF; if (rawdata) { *rawdata = channel[dwChannel]; } //dprintf(1,"[adc_api: imm mode raw data => channel[%d] = %d\n",dwChannel, channel[dwChannel]); //dprintf(1,"[adc_api]: imm mode => channel[%d] = %d.%d\n", dwChannel, (channel[dwChannel] * 250 / 4096 / 100), ((channel[dwChannel] * 250 / 4096) % 100)); data[0] = (channel[dwChannel] * 150 / 4096 / 100); data[1] = ((channel[dwChannel] * 150 / 4096) % 100); /* if(disable_clock(MT65XX_PDN_PERI_AUXADC,"AUXADC")) { dprintf(1,"hwEnableClock AUXADC failed."); } mutex_unlock(&mutex_get_cali_value); */ return 0; } // 1v == 1000000 uv // this function voltage Unit is uv int IMM_GetOneChannelValue_Cali(int Channel, int*voltage) { int ret = 0, data[4], rawvalue; ret = IMM_GetOneChannelValue( Channel, data, &rawvalue); if (ret) { ret = IMM_GetOneChannelValue( Channel, data, &rawvalue); if (ret) { dprintf(1,"[adc_api]:IMM_GetOneChannelValue_Cali get raw value error %d \n",ret); return -1; } } //*voltage = rawvalue*1500000 / 4096; *voltage = (int)((long long)rawvalue*1500000 / (long long)4096); //dprintf(1,"[adc_api]:IMM_GetOneChannelValue_Cali voltage= %d uv \n",*voltage); return 0; } static int IMM_auxadc_get_evrage_data(int times, int Channel) { int ret = 0, data[4], i, ret_value = 0, ret_temp = 0; i = times; while (i--) { ret_value = IMM_GetOneChannelValue(Channel, data, &ret_temp); ret += ret_temp; dprintf(1,"[auxadc_get_data(channel%d)]: ret_temp=%d, ret = %d.\n",Channel,ret_temp,ret_value); } ret = ret / times; return ret; } int auxadc_test(void ) { int i = 0, data[4] = {0,0,0,0}; int res =0; int rawdata=0; //int Voltiage_cali =0; for (i = 0; i < 16; i++) { //dprintf(1,"[adc_driver]: i=%d\n",i); res = IMM_GetOneChannelValue(i,data,&rawdata); if (res < 0) { dprintf(1,"[adc_lk]: get data error\n"); break; } else { dprintf(1,"[adc_lk]: channel[%d]raw =%d\n",i,rawdata); //dprintf(1,"[adc_lk]: channel[%d]=%d.%.02d \n",i,data[0],data[1]); } #if 0 res= IMM_GetOneChannelValue_Cali(i, &Voltiage_cali); if (res < 0) { dprintf(1,"[adc_driver]: get cali voltage error\n"); break; } else { dprintf(1,"[adc_driver]: channel[%d] cali_voltage =%d\n",i,Voltiage_cali); } #endif } return 0; } ///////////////////////////////////////////////////////////////////////////////////////////