static inline void axp_read_adc(struct axp_charger *charger, struct axp_adc_res *adc) { uint8_t tmp[8]; #ifdef CONFIG_AW_AXP19 axp_reads(charger->master,AXP_VACH_RES,8,tmp); adc->vac_res = ((uint16_t) tmp[0] << 8 )| tmp[1]; adc->iac_res = ((uint16_t) tmp[2] << 8 )| tmp[3]; adc->vusb_res = ((uint16_t) tmp[4] << 8 )| tmp[5]; adc->iusb_res = ((uint16_t) tmp[6] << 8 )| tmp[7]; #else adc->vac_res = 0; adc->iac_res = 0; adc->vusb_res = 0; adc->iusb_res = 0; axp_reads(charger->master,AXP_OCVBATH_RES,2,tmp); adc->ocvbat_res = ((uint16_t) tmp[0] << 8 )| tmp[1]; axp_reads(charger->master,AXP_VTS_RES,2,tmp); adc->ts_res = ((uint16_t) tmp[0] << 8 )| tmp[1]; #endif axp_reads(charger->master,AXP_VBATH_RES,6,tmp); adc->vbat_res = ((uint16_t) tmp[0] << 8 )| tmp[1]; adc->ichar_res = ((uint16_t) tmp[2] << 8 )| tmp[3]; adc->idischar_res = ((uint16_t) tmp[4] << 8 )| tmp[5]; }
static inline void axp_read_adc(struct axp_charger *charger, struct axp_adc_res *adc) { uint8_t tmp[8]; axp_reads(charger->master,AXP19_VACH_RES,8,tmp); adc->vac_res = ((uint16_t) tmp[0] << 8 )| tmp[1]; adc->iac_res = ((uint16_t) tmp[2] << 8 )| tmp[3]; adc->vusb_res = ((uint16_t) tmp[4] << 8 )| tmp[5]; adc->iusb_res = ((uint16_t) tmp[6] << 8 )| tmp[7]; axp_reads(charger->master,AXP19_VBATH_RES,6,tmp); adc->vbat_res = ((uint16_t) tmp[0] << 8 )| tmp[1]; adc->ichar_res = ((uint16_t) tmp[2] << 8 )| tmp[3]; adc->idischar_res = ((uint16_t) tmp[4] << 8 )| tmp[5]; }
static inline void axp_read_adc(struct axp_adc_res *adc) { uint8_t tmp[8]; axp_reads(AXP20_VACH_RES,8,tmp); adc->vac_res = ((uint16_t) tmp[0] << 4 )| (tmp[1] & 0x0f); adc->iac_res = ((uint16_t) tmp[2] << 4 )| (tmp[3] & 0x0f); adc->vusb_res = ((uint16_t) tmp[4] << 4 )| (tmp[5] & 0x0f); adc->iusb_res = ((uint16_t) tmp[6] << 4 )| (tmp[7] & 0x0f); axp_reads(AXP20_VBATH_RES,6,tmp); adc->vbat_res = ((uint16_t) tmp[0] << 4 )| (tmp[1] & 0x0f); adc->ichar_res = ((uint16_t) tmp[2] << 4 )| (tmp[3] & 0x0f); adc->idischar_res = ((uint16_t) tmp[4] << 5 )| (tmp[5] & 0x1f); }
void axp_charger_update_state(struct axp_charger *charger) { uint8_t val[2]; uint16_t tmp; axp_reads(charger->master,AXP_CHARGE_STATUS,2,val); tmp = (val[1] << 8 )+ val[0]; spin_lock(&charger->charger_lock); charger->is_on = (val[1] & AXP_IN_CHARGE) ? 1 : 0; charger->fault = val[1]; charger->bat_det = (tmp & AXP_STATUS_BATEN)?1:0; charger->ac_det = (tmp & AXP_STATUS_ACEN)?1:0; charger->usb_det = (tmp & AXP_STATUS_USBEN)?1:0; charger->ext_valid = (tmp & (AXP_STATUS_USBVA |AXP_STATUS_ACVA))?1:0; charger->in_short = (tmp& AXP_STATUS_ACUSBSH)?1:0; if(!charger->in_short) { charger->ac_valid = (tmp & AXP_STATUS_ACVA)?1:0; } charger->bat_current_direction = (tmp & AXP_STATUS_BATCURDIR)?1:0; charger->in_short = (tmp& AXP_STATUS_ACUSBSH)?1:0; charger->batery_active = (tmp & AXP_STATUS_BATINACT)?1:0; charger->int_over_temp = (tmp & AXP_STATUS_ICTEMOV)?1:0; spin_unlock(&charger->charger_lock); axp_read(charger->master,AXP_CHARGE_CONTROL1,val); spin_lock(&charger->charger_lock); charger->charge_on = ((val[0] >> 7) & 0x01); spin_unlock(&charger->charger_lock); }
void axp_charger_update(struct axp_charger *charger, const struct axp_config_info *axp_config) { uint16_t tmp; uint8_t val[2]; #ifdef CONFIG_AW_AXP19 #else int bat_temp_mv; #endif charger->adc = &adc; axp_read_adc(charger, &adc); tmp = charger->adc->vbat_res; spin_lock(&charger->charger_lock); charger->vbat = axp_vbat_to_mV(tmp); spin_unlock(&charger->charger_lock); //tmp = charger->adc->ichar_res + charger->adc->idischar_res; spin_lock(&charger->charger_lock); charger->ibat = ABS(axp_icharge_to_mA(charger->adc->ichar_res)-axp_ibat_to_mA(charger->adc->idischar_res)); tmp = 00;///qin charger->vac = axp_vdc_to_mV(tmp); tmp = 00; charger->iac = axp_iac_to_mA(tmp); tmp = 00; charger->vusb = axp_vdc_to_mV(tmp); tmp = 00; charger->iusb = axp_iusb_to_mA(tmp); spin_unlock(&charger->charger_lock); axp_reads(charger->master,AXP_INTTEMP,2,val); //DBG_PSY_MSG("TEMPERATURE:val1=0x%x,val2=0x%x\n",val[1],val[0]); tmp = (val[0] << 4 ) + (val[1] & 0x0F); #ifdef CONFIG_AW_AXP19 spin_lock(&charger->charger_lock); charger->ic_temp = (int) ((tmp - 1447)/10); charger->disvbat = charger->vbat; charger->disibat = axp_ibat_to_mA(charger->adc->idischar_res); spin_unlock(&charger->charger_lock); #else spin_lock(&charger->charger_lock); charger->ic_temp = (int) tmp *1063/10000 - 2667/10; charger->disvbat = charger->vbat; charger->disibat = axp_ibat_to_mA(charger->adc->idischar_res); spin_unlock(&charger->charger_lock); tmp = charger->adc->ocvbat_res; spin_lock(&charger->charger_lock); charger->ocv = axp_ocvbat_to_mV(tmp); spin_unlock(&charger->charger_lock); tmp = charger->adc->ts_res; bat_temp_mv = axp_vts_to_mV(tmp); spin_lock(&charger->charger_lock); charger->bat_temp = axp_vts_to_temp(bat_temp_mv, axp_config); spin_unlock(&charger->charger_lock); #endif }
/* 得到开路电压 */ static int axp_get_ocv(void) { int battery_ocv; uint8_t v[2]; axp_reads(AXP_OCV_BUFFER0, 2, v); battery_ocv = ((v[0] << 4) + (v[1] & 0x0f)) * 11 /10; DBG_PSY_MSG("battery_ocv = %d\n", battery_ocv); return battery_ocv; }
int axp_charger_get_charging_status(void) { axp_reads(0x00, 2, (uint8_t *)&status_reg); if (status_reg & (1 << 2)) { return 1; } else { return 0; } }
static int axp_get_rdc(struct axp_charger *charger) { uint8_t val[2]; unsigned int i,temp,pre_temp; int averPreVol = 0, averPreCur = 0,averNextVol = 0,averNextCur = 0; axp_reads(charger->master,AXP19_DATA_BUFFER2,2,val); pre_temp = (((val[0] & 0x07) << 8 ) + val[1]); if(!charger->bat_det){ return pre_temp; } if( charger->ext_valid){ for(i = 0; i< AXP19_RDC_COUNT; i++){ axp_charger_update(charger); averPreVol += charger->vbat; averPreCur += charger->ibat; msleep(200); } averPreVol /= AXP19_RDC_COUNT; averPreCur /= AXP19_RDC_COUNT; axp_clr_bits(charger->master,AXP20_CHARGE_CONTROL1,0x80); msleep(3000); for(i = 0; i< AXP19_RDC_COUNT; i++){ axp_charger_update(charger); averNextVol += charger->vbat; averNextCur += charger->ibat; msleep(200); } averNextVol /= AXP19_RDC_COUNT; averNextCur /= AXP19_RDC_COUNT; axp_set_bits(charger->master,AXP20_CHARGE_CONTROL1,0x80); if(ABS(averPreCur - averNextCur) > 200){ temp = 1000 * ABS(averPreVol - averNextVol) / ABS(averPreCur - averNextCur); if((temp < 5) || (temp > 5000)){ return pre_temp; } else { temp += pre_temp; temp >>= 1; axp_write(charger->master,AXP19_DATA_BUFFER2,((temp & 0xFF00) | 0x800) >> 8); axp_write(charger->master,AXP19_DATA_BUFFER3,temp & 0x00FF); return temp; } } else { return pre_temp;
int axp_update_calibrate(int charge) { uint8_t val[2]; struct axp_adc_res axp_adc; uint32_t tmp0, tmp1; coulomb = axp_get_coulomb(); ocv = axp_get_ocv(); axp_read_adc(&axp_adc); ibat = ABS(axp_ibat_to_mA(axp_adc.ichar_res)-axp_ibat_to_mA(axp_adc.idischar_res)); tmp0 = axp_adc.vbat_res; vbat_i = (tmp0 * 1100) / 1000; axp_reads(0xBA, 2, val); tmp1 = ((val[0] & 0x1F) << 8) | val[1]; rdc_r = (tmp1 * 10742) / 10000; if (charge) { return axp_calculate_rdc(); } return 0; }
static void axp_charger_update_state(struct axp_charger *charger) { uint8_t val[2]; uint16_t tmp; axp_reads(charger->master,AXP19_CHARGE_STATUS,2,val); tmp = (val[1] << 8 )+ val[0]; //printk("tmp = 0x%x\n",tmp); charger->is_on = (val[1] & AXP19_IN_CHARGE) ? 1 : 0; charger->fault = val[1]; charger->bat_det = (tmp & AXP19_STATUS_BATEN)?1:0; charger->ac_det = (tmp & AXP19_STATUS_ACEN)?1:0; charger->usb_det = (tmp & AXP19_STATUS_USBEN)?1:0; charger->usb_valid = (tmp & AXP19_STATUS_USBVA)?1:0; charger->ac_valid = (tmp & AXP19_STATUS_ACVA)?1:0; charger->ext_valid = charger->ac_valid | charger->usb_valid; charger->bat_current_direction = (tmp & AXP19_STATUS_BATCURDIR)?1:0; charger->in_short = (tmp& AXP19_STATUS_ACUSBSH)?1:0; charger->batery_active = (tmp & AXP19_STATUS_BATINACT)?1:0; charger->low_charge_current = (tmp & AXP19_STATUS_CHACURLOEXP)?1:0; charger->int_over_temp = (tmp & AXP19_STATUS_ICTEMOV)?1:0; }
static int axp_get_coulomb(void) { uint8_t temp[8]; uint64_t rValue1,rValue2,rValue; uint32_t Cur_CoulombCounter_tmp,m; axp_reads(POWER20_BAT_CHGCOULOMB3,8, temp); rValue1 = ((temp[0] << 24) + (temp[1] << 16) + (temp[2] << 8) + temp[3]); rValue2 = ((temp[4] << 24) + (temp[5] << 16) + (temp[6] << 8) + temp[7]); DBG_PSY_MSG("%s->%d - CHARGINGOULB:[0]=0x%x,[1]=0x%x,[2]=0x%x,[3]=0x%x\n",__FUNCTION__,__LINE__,temp[0],temp[1],temp[2],temp[3]); DBG_PSY_MSG("%s->%d - DISCHARGINGCLOUB:[4]=0x%x,[5]=0x%x,[6]=0x%x,[7]=0x%x\n",__FUNCTION__,__LINE__,temp[4],temp[5],temp[6],temp[7]); rValue = (ABS(rValue1 - rValue2)) * 4369; m = axp_get_freq() * 480; do_div(rValue,m); if(rValue1 >= rValue2) Cur_CoulombCounter_tmp = (int)rValue; else Cur_CoulombCounter_tmp = (int)(0 - rValue); DBG_PSY_MSG("Cur_CoulombCounter_tmp = %d\n",Cur_CoulombCounter_tmp); return Cur_CoulombCounter_tmp; //unit mAh }
int axp202_reads(int addr, unsigned char *buf, int count) { return axp_reads(addr, count, buf); }
static void axp_charging_monitor(struct work_struct *work) { struct axp_charger *charger; uint8_t val,temp_val[4]; int pre_rest_vol,pre_bat_curr_dir; unsigned long power_sply = 0; charger = container_of(work, struct axp_charger, work.work); pre_rest_vol = charger->rest_vol; pre_bat_curr_dir = charger->bat_current_direction; axp_charger_update_state(charger); axp_charger_update(charger, &axp81x_config); axp_read(charger->master, AXP81X_CAP,&val); spin_lock(&charger->charger_lock); charger->rest_vol = (int) (val & 0x7F); spin_unlock(&charger->charger_lock); if (axp_debug & DEBUG_SPLY) { DBG_PSY_MSG(DEBUG_SPLY, "charger->ic_temp = %d\n",charger->ic_temp); DBG_PSY_MSG(DEBUG_SPLY, "charger->bat_temp = %d\n",charger->bat_temp); DBG_PSY_MSG(DEBUG_SPLY, "charger->vbat = %d\n",charger->vbat); DBG_PSY_MSG(DEBUG_SPLY, "charger->ibat = %d\n",charger->ibat); DBG_PSY_MSG(DEBUG_SPLY, "charger->ocv = %d\n",charger->ocv); DBG_PSY_MSG(DEBUG_SPLY, "charger->disvbat = %d\n",charger->disvbat); DBG_PSY_MSG(DEBUG_SPLY, "charger->disibat = %d\n",charger->disibat); power_sply = charger->disvbat * charger->disibat; if (0 != power_sply) power_sply = power_sply/1000; DBG_PSY_MSG(DEBUG_SPLY, "power_sply = %ld mW\n",power_sply); DBG_PSY_MSG(DEBUG_SPLY, "charger->rest_vol = %d\n",charger->rest_vol); axp_reads(charger->master,0xba,2,temp_val); DBG_PSY_MSG(DEBUG_SPLY, "Axp Rdc = %d\n",(((temp_val[0] & 0x1f) <<8) + temp_val[1])*10742/10000); axp_reads(charger->master,0xe0,2,temp_val); DBG_PSY_MSG(DEBUG_SPLY, "Axp batt_max_cap = %d\n",(((temp_val[0] & 0x7f) <<8) + temp_val[1])*1456/1000); axp_reads(charger->master,0xe2,2,temp_val); DBG_PSY_MSG(DEBUG_SPLY, "Axp coulumb_counter = %d\n",(((temp_val[0] & 0x7f) <<8) + temp_val[1])*1456/1000); axp_read(charger->master,0xb8,temp_val); DBG_PSY_MSG(DEBUG_SPLY, "Axp REG_B8 = %x\n",temp_val[0]); axp_reads(charger->master,0xe4,2,temp_val); DBG_PSY_MSG(DEBUG_SPLY, "Axp OCV_percentage = %d\n",(temp_val[0] & 0x7f)); DBG_PSY_MSG(DEBUG_SPLY, "Axp Coulumb_percentage = %d\n",(temp_val[1] & 0x7f)); DBG_PSY_MSG(DEBUG_SPLY, "charger->is_on = %d\n",charger->is_on); DBG_PSY_MSG(DEBUG_SPLY, "charger->bat_current_direction = %d\n",charger->bat_current_direction); DBG_PSY_MSG(DEBUG_SPLY, "charger->charge_on = %d\n",charger->charge_on); DBG_PSY_MSG(DEBUG_SPLY, "charger->ext_valid = %d\n",charger->ext_valid); DBG_PSY_MSG(DEBUG_SPLY, "pmu_runtime_chgcur = %d\n",axp81x_config.pmu_runtime_chgcur); DBG_PSY_MSG(DEBUG_SPLY, "pmu_earlysuspend_chgcur = %d\n",axp81x_config.pmu_earlysuspend_chgcur); DBG_PSY_MSG(DEBUG_SPLY, "pmu_suspend_chgcur = %d\n",axp81x_config.pmu_suspend_chgcur); DBG_PSY_MSG(DEBUG_SPLY, "pmu_shutdown_chgcur = %d\n\n\n",axp81x_config.pmu_shutdown_chgcur); } /* if battery volume changed, inform uevent */ if((charger->rest_vol - pre_rest_vol) || (charger->bat_current_direction != pre_bat_curr_dir)){ axp_reads(charger->master,0xe2,2,temp_val); axp_reads(charger->master,0xe4,2,(temp_val+2)); DBG_PSY_MSG(DEBUG_SPLY, "battery vol change: %d->%d \n", pre_rest_vol, charger->rest_vol); DBG_PSY_MSG(DEBUG_SPLY, "for test %d %d %d %d %d %d\n",charger->vbat,charger->ocv,charger->ibat, (temp_val[2] & 0x7f),(temp_val[3] & 0x7f),(((temp_val[0] & 0x7f) <<8) + temp_val[1])*1456/1000); pre_rest_vol = charger->rest_vol; power_supply_changed(&charger->batt); } /* reschedule for the next time */ schedule_delayed_work(&charger->work, charger->interval); }