int axp_gpio_get_io(int gpio, int *io_state) { uint8_t val; if (!axp) { printk("[AXP] driver has not ready now, wait...\n"); return -ENODEV; } switch (gpio) { case 0: axp_read(&axp->dev, AXP20_GPIO0_CFG, &val); return check_io012(gpio, val & 0x07, io_state); case 1: axp_read(&axp->dev, AXP20_GPIO1_CFG, &val); return check_io012(gpio, val & 0x07, io_state); case 2: axp_read(&axp->dev, AXP20_GPIO2_CFG, &val); return check_io012(gpio, val & 0x07, io_state); case 3: axp_read(&axp->dev, AXP20_GPIO3_CFG, &val); val &= 0x04; if (val == 0x0) { *io_state = 1; } else { *io_state = 0; } break; default: return -ENXIO; } return 0; }
int axp_charger_set_usbcur_limit(int usbcur_limit) { uint8_t val; if ((usbcur_limit < 0 || usbcur_limit > 900) && (usbcur_limit != -1)) { printf("wrong current limit:%d\n", usbcur_limit); } axp_read(AXP20_CHARGE_VBUS, &val); val &= ~0x03; switch (usbcur_limit) { case -1: case 0: val |= 0x3; // Max break; case 100: val |= 0x2; break; case 500: val |= 0x1; break; case 900: val |= 0x0; break; default: printf("usbcur_limit=%d, not in 0,100,500,900. please check!\n", usbcur_limit); return -1; break; } axp_write(AXP20_CHARGE_VBUS, val); axp_read(AXP20_CHARGE_VBUS, &val); printf("[AXP_PMU]%s,AXP20_CHARGE_VBUS:0x%x\n", __func__, val); return 0; }
/* axp driver porting interface */ static int axp_gpio_get_data(int gpio) { uint8_t ret; struct axp_dev *axp = NULL; #ifdef CONFIG_AW_AXP22 axp = axp_dev_lookup(AXP22); #elif defined(CONFIG_AW_AXP81X) axp = axp_dev_lookup(AXP81X); #endif if (NULL == axp) { printk("%s: axp data is null\n", __func__); return -ENXIO; } switch(gpio){ case 0:axp_read(axp->dev,AXP_GPIO01_STATE,&ret);ret &= 0x10;ret = ret>>4;break; case 1:axp_read(axp->dev,AXP_GPIO01_STATE,&ret);ret &= 0x20;ret = ret>>5;break; case 2:printk("This IO is not an input,no return value!");return -ENXIO; case 3:printk("This IO is not an input,no return value!");return -ENXIO; case 4:printk("This IO is not an input,no return value!");return -ENXIO; case 5:printk("This IO is not an input,no return value!");return -ENXIO; default:return -ENXIO; } return ret; }
void axp81x_power_off(int power_start) { uint8_t val; struct axp_dev *axp; axp = axp_dev_lookup(AXP81X); if (NULL == axp) { printk("%s: axp data is null\n", __func__); return; } if(axp81x_config.pmu_pwroff_vol >= 2600 && axp81x_config.pmu_pwroff_vol <= 3300){ if (axp81x_config.pmu_pwroff_vol > 3200){ val = 0x7; }else if (axp81x_config.pmu_pwroff_vol > 3100){ val = 0x6; }else if (axp81x_config.pmu_pwroff_vol > 3000){ val = 0x5; }else if (axp81x_config.pmu_pwroff_vol > 2900){ val = 0x4; }else if (axp81x_config.pmu_pwroff_vol > 2800){ val = 0x3; }else if (axp81x_config.pmu_pwroff_vol > 2700){ val = 0x2; }else if (axp81x_config.pmu_pwroff_vol > 2600){ val = 0x1; }else val = 0x0; axp_update(axp->dev, AXP81X_VOFF_SET, val, 0x7); } val = 0xff; printk("[axp] send power-off command!\n"); mdelay(20); if(axp81x_config.power_start != 1){ axp_read(axp->dev, AXP81X_STATUS, &val); if(val & 0xF0){ axp_read(axp->dev, AXP81X_MODE_CHGSTATUS, &val); if(val & 0x20) { printk("[axp] set flag!\n"); axp_read(axp->dev, AXP81X_BUFFERC, &val); if (0x0d != val) axp_write(axp->dev, AXP81X_BUFFERC, 0x0f); mdelay(20); printk("[axp] reboot!\n"); machine_restart(NULL); printk("[axp] warning!!! arch can't ,reboot, maybe some error happend!\n"); } } } axp_read(axp->dev, AXP81X_BUFFERC, &val); if (0x0d != val) axp_write(axp->dev, AXP81X_BUFFERC, 0x00); mdelay(20); axp_set_bits(axp->dev, AXP81X_OFF_CTL, 0x80); mdelay(20); printk("[axp] warning!!! axp can't power-off, maybe some error happend!\n"); }
static int axp_pmx_get(int gpio) { struct axp_dev *axp = NULL; uint8_t data; #ifdef CONFIG_AW_AXP22 axp = axp_dev_lookup(AXP22); #elif defined(CONFIG_AW_AXP81X) axp = axp_dev_lookup(AXP81X); #endif if (NULL == axp) { printk("%s: %d axp data is null\n", __func__, __LINE__); return -ENXIO; } switch(gpio){ case 0: axp_read(axp->dev, AXP_GPIO0_CFG, &data); if (0 == (data & 0x06)) return 1; else if (0x02 == (data & 0x07)) return 0; else return -ENXIO; case 1: axp_read(axp->dev, AXP_GPIO1_CFG, &data); if (0 == (data & 0x06)) return 1; else if (0x02 == (data & 0x07)) return 0; else return -ENXIO; case 2: return 1; case 3: axp_read(axp->dev, AXP_GPIO3_CFG, &data); if (0 == (data & 0x08)) return 1; else return 0; case 4: axp_read(axp->dev, AXP_GPIO4_CFG, &data); if (0 == (data & 0x10)) return 1; else return 0; case 5: return 1; default:return -ENXIO; } return -ENXIO; }
static int axp_get_rdc(struct axp_charger *charger) { uint8_t val[3]; unsigned int i,temp,pre_temp; int averPreVol = 0, averPreCur = 0,averNextVol = 0,averNextCur = 0; //axp_reads(charger->master,AXP18_DATA_BUFFER1,2,val); axp_read(charger->master,AXP18_DATA_BUFFER1,val); axp_read(charger->master,AXP18_DATA_BUFFER2,val+1); pre_temp = (((val[0] & 0x7F) << 8 ) + val[1]); printk("%d:pre_temp = %d\n",__LINE__,pre_temp); if( charger->is_on){ for(i = 0; i< AXP18_RDC_COUNT; i++){ axp_charger_update(charger); averPreVol += charger->vbat; averPreCur += charger->ibat; msleep(50); } averPreVol /= AXP18_RDC_COUNT; averPreCur /= AXP18_RDC_COUNT; axp_clr_bits(charger->master,AXP18_CHARGE_CONTROL2,0x80); msleep(500); for(i = 0; i< AXP18_RDC_COUNT; i++){ axp_charger_update(charger); averNextVol += charger->vbat; averNextCur += charger->ibat; msleep(50); } averNextVol /= AXP18_RDC_COUNT; averNextVol /= AXP18_RDC_COUNT; axp_set_bits(charger->master,AXP18_CHARGE_CONTROL2,0x80); msleep(500); if(ABS(averPreCur - averNextCur) > 200){ temp = 1000 * ABS(averPreVol - averNextVol) / ABS(averPreCur); if((temp < 5) || (temp > 5000)){ return pre_temp; } else { temp += pre_temp; temp >>= 1; val[0] = ((temp & 0xFF00) | 0x8000) >> 8; val[1] = AXP18_DATA_BUFFER2; val[2] = temp & 0x00FF; axp_writes(charger->master,AXP18_DATA_BUFFER1,3,val ); return temp; } } else return pre_temp;
static inline void axp_read_adc(struct axp_charger *charger, struct axp_adc_res *adc) { uint8_t tmp; //axp_reads(charger->master, AXP18_VBAT_RES,sizeof(*adc), (uint8_t *)adc);//axp18 can't support muti-reads axp_read(charger->master,AXP18_VBAT_RES,&tmp); adc->vbat_res = tmp; axp_read(charger->master,AXP18_IBAT_RES,&tmp); adc->ibat_res = tmp; axp_read(charger->master,AXP18_VAC_RES,&tmp); adc->vac_res = tmp; axp_read(charger->master,AXP18_IAC_RES,&tmp); adc->iac_res = tmp; }
static int axp_battery_adc_set(struct axp_charger *charger) { int ret ; uint8_t val; /*enable adc and set adc */ val= AXP19_ADC_BATVOL_ENABLE | AXP19_ADC_BATCUR_ENABLE | AXP19_ADC_DCINCUR_ENABLE | AXP19_ADC_DCINVOL_ENABLE | AXP19_ADC_USBVOL_ENABLE | AXP19_ADC_USBCUR_ENABLE; ret = axp_write(charger->master, AXP19_ADC_CONTROL1, val); if (ret) return ret; ret = axp_read(charger->master, AXP19_ADC_CONTROL3, &val); switch (charger->sample_time/25){ case 1: val &= ~(3 << 6);break; case 2: val &= ~(3 << 6);val |= 1 << 6;break; case 4: val &= ~(3 << 6);val |= 2 << 6;break; case 8: val |= 3 << 6;break; default: break; } ret = axp_write(charger->master, AXP19_ADC_CONTROL3, val); if (ret) return ret; return 0; }
static void board_pmu_init(void) { struct aml_pmu_driver *driver = aml_pmu_get_driver(); if (driver && driver->pmu_init) { driver->pmu_init(); } #ifdef CONFIG_AW_AXP20 // todo add your platform needed init code here #ifdef CONFIG_AML_AXP202 uint8_t tmp; uint8_t reg_val; uint8_t axp_ts_current=0x3; //TS pin output current: 00:20uA£»01:40uA;10:60uA;11:80uA #endif #ifdef CONFIG_AML_AXP202 #define LTF_CHARGE_REG 0x38 #define HTF_CHARGE_REG 0x39 //#define LTF_DISCHARGE_REG 0x3c //#define HTF_DISCHARGE_REG 0x3d #define TS_CURRENT_REG 0x84 axp_read(TS_CURRENT_REG, ®_val); tmp = axp_ts_current << 4; reg_val &= ~(3<<4); //reg_val &= 0xcf; reg_val |= tmp; reg_val &= ~(3<<0); reg_val |= 0x1; //TS pin:charge output current axp_write(TS_CURRENT_REG,reg_val); //set TS pin output current axp_write(LTF_CHARGE_REG,0xDB); //set battery low temperature threshold,T=0 axp_write(HTF_CHARGE_REG,0x48); //set battery high temperature threshold,T=70 #endif #endif }
static int axp_battery_first_init(struct axp_charger *charger) { int ret; uint8_t val; axp_set_charge(charger); ret = axp_battery_adc_set(charger); if(ret) return ret; ret = axp_read(charger->master, AXP81X_ADC_CONTROL4, &val); spin_lock(&charger->charger_lock); switch ((val >> 4) & 0x03) { case 0: charger->sample_time = 100; break; case 1: charger->sample_time = 200; break; case 2: charger->sample_time = 400; break; case 3: charger->sample_time = 800; break; default: break; } spin_unlock(&charger->charger_lock); return ret; }
int axp_set_charging_current(int current) { uint8_t reg_val = 0; if (current > 1800 * 1000 || current < 0) { printf("%s, wrong charge current seting:%d\n", __func__, current); return -1; } if (current > 100) { current = current / 1000; } else { current = (current * board_battery_para.pmu_battery_cap) / 100 + 100; } if (current > 1600) { current = 1600; } axp_read(POWER20_CHARGE1, ®_val); if(current == 0) { reg_val &= 0x7f; axp_write(POWER20_CHARGE1, reg_val); printf("%s: set charge current to %d Reg value %x!\n",__FUNCTION__, current, reg_val); } else { reg_val &= 0xf0; reg_val |= ((current-300)/100); axp_write(POWER20_CHARGE1, reg_val); printf("%s: set charge current to %d Reg value %x!\n",__FUNCTION__, current, reg_val); } return 0; }
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); }
static ssize_t workmode_show(struct device *dev, struct device_attribute *attr, char *buf) { struct regulator_dev *rdev = dev_get_drvdata(dev); struct axp_regulator_info *info = rdev_get_drvdata(rdev); struct device *axp_dev = to_axp_dev(rdev); int ret; uint8_t val; ret = axp_read(axp_dev, AXP20_BUCKMODE, &val); if (ret) return sprintf(buf, "IO ERROR\n"); if(info->desc.id == AXP20_ID_DCDC2){ switch (val & 0x04) { case 0:return sprintf(buf, "AUTO\n"); case 4:return sprintf(buf, "PWM\n"); default:return sprintf(buf, "UNKNOWN\n"); } } else if(info->desc.id == AXP20_ID_DCDC3){ switch (val & 0x02) { case 0:return sprintf(buf, "AUTO\n"); case 2:return sprintf(buf, "PWM\n"); default:return sprintf(buf, "UNKNOWN\n"); } } else return sprintf(buf, "IO ID ERROR\n"); }
int axp_gpio_get_io(int gpio, int *io_state) { uint8_t val; if (!axp) { WARN_ON_ONCE("axp gpio used without AXP"); return -ENODEV; } switch(gpio) { case 0: axp_read(&axp->dev,AXP20_GPIO0_CFG,&val);val &= 0x07; if(val < 0x02) *io_state = 1; else if (val == 0x02) *io_state = 0; else return -EIO; break; case 1: axp_read(&axp->dev,AXP20_GPIO1_CFG,&val);val &= 0x07; if(val < 0x02) *io_state = 1; else if (val == 0x02) *io_state = 0; else return -EIO; break; case 2: axp_read(&axp->dev,AXP20_GPIO2_CFG,&val);val &= 0x07; if(val == 0x0) *io_state = 1; else if (val == 0x02) *io_state = 0; else return -EIO; break; case 3: axp_read(&axp->dev,AXP20_GPIO3_CFG,&val);val &= 0x04; if(val == 0x0) *io_state = 1; else *io_state = 0; break; default:return -ENXIO; } return 0; }
int axp_gpio_get_io(int gpio, int *io_state) { uint8_t val; switch(gpio) { case 0: axp_read(&axp->dev,AXP19_GPIO0_CFG,&val);val &= 0x07; if(val == 0x00) *io_state = 1; else if (val == 0x01) *io_state = 0; else return -EIO; break; case 1: axp_read(&axp->dev,AXP19_GPIO1_CFG,&val);val &= 0x07; if(val < 0x00) *io_state = 1; else if (val == 0x01) *io_state = 0; else return -EIO; break; case 2: axp_read(&axp->dev,AXP19_GPIO2_CFG,&val);val &= 0x07; if(val == 0x0) *io_state = 1; else if (val == 0x01) *io_state = 0; else return -EIO; break; case 3: axp_read(&axp->dev,AXP19_GPIO34_CFG,&val);val &= 0x03; if(val == 0x1) *io_state = 1; else if(val == 0x2) *io_state = 0; else return -EIO; break; case 4: axp_read(&axp->dev,AXP19_GPIO34_CFG,&val);val &= 0x0C; if(val == 0x4) *io_state = 1; else if(val == 0x8) *io_state = 0; else return -EIO; break; case 5: axp_read(&axp->dev,AXP19_GPIO5_CFG,&val);val &= 0x40; *io_state = val >> 6; break; case 6: axp_read(&axp->dev,AXP19_GPIO67_CFG1,&val);*io_state = (val & 0x40)?0:1;break; case 7: axp_read(&axp->dev,AXP19_GPIO67_CFG1,&val);*io_state = (val & 0x04)?0:1;break; default:return -ENXIO; } return 0; }
int axp_read_bat_cap(void) { int bat_cap; uint8_t tmp; axp_read(axp_charger->master, AXP_CAP,&tmp); bat_cap = (int) (tmp & 0x7F); return bat_cap; }
int axp202_charger_online(void) { uint8_t val; axp_read(AXP20_CHARGE_STATUS, &val); if (val & ((1<<7) | (1<<5))) { return 1; } else { return 0; } }
static void axp_charger_update_state(struct axp_charger *charger) { uint8_t val,tmp; axp_read(charger->master, AXP18_CHARGE_STATUS, &val); charger->is_on = (val & AXP18_IN_CHARGE) ? 1 : 0; axp_read(charger->master,AXP18_FAULT_LOG1,&charger->fault); axp_read(charger->master, AXP18_FAULT_LOG2, &val); charger->is_finish = (val & AXP18_FINISH_CHARGE) ? 1 : 0; tmp = val & 0x22; val = tmp >> 5 | tmp << 5; charger->fault |= val; axp_read(charger->master, AXP18_STATUS, &val); charger->bat_det = (val & AXP18_STATUS_BATEN) ? 1 : 0; charger->ac_det = (val & AXP18_STATUS_DCIEN) ? 1 : 0; charger->usb_det = (val & AXP18_STATUS_USBEN) ? 1 : 0; charger->ext_valid = (val & AXP18_STATUS_EXTVA) ? 1 : 0; }
int axp_gpio_get_value(int gpio, int *value) { int io_state; int ret; uint8_t val; ret = axp_gpio_get_io(gpio,&io_state); if(ret) return ret; if(io_state){ switch(gpio) { case 0:ret = axp_read(&axp->dev,AXP20_GPIO0_CFG,&val);*value = val & 0x01;break; case 1:ret =axp_read(&axp->dev,AXP20_GPIO1_CFG,&val);*value = val & 0x01;break; case 2:ret = 0; *value = 0;break; case 3:ret = axp_read(&axp->dev,AXP20_GPIO3_CFG,&val);val &= 0x02;*value = val>>1;break; default:return -ENXIO; } } else{ switch(gpio)
int axp_battery_calibrate_init(void) { uint8_t val; axp_read(0x01, &val); if (!(val & 0x20)) { terminal_print(0, 35, "ERROR, NO battery is connected to system\n"); return 0; } axp_read(0x30, &val); val |= 0x03; axp_write(0x30, val); axp_read(0x84, &val); val &= ~0xc0; val |= 0x80; axp_write(0x84, val); // set ADC sample rate to 100KHz axp_write(0x82, 0xff); // open all ADC axp_write(0x31, 0x03); // shutdown when battery voltage < 2.9V axp_write(0x33, 0xc8); // set charge current to 1.1A axp_write(0xb8, 0x20); // clear coulomb counter axp_write(0xb8, 0x80); // start coulomb counter return 1; }
static void axp_set_charge(struct axp_charger *charger) { uint8_t val,tmp; val = 0x00; if(charger->chgvol < 4200) val &= ~(3 << 5); else if (charger->chgvol<4360){ val &= ~(3 << 5); val |= 1 << 6; } else val |= 3 << 5; if(charger->limit_on) val |= ((charger->chgcur - 100) / 200) | (1 << 3); else val |= ((charger->chgcur - 100) / 200) ; val &= 0x7F; val |= charger->chgen << 7; axp_read(charger->master, AXP18_CHARGE_CONTROL2, &tmp); tmp &= 0x3C; if(charger->chgpretime < 30) charger->chgpretime = 30; if(charger->chgcsttime < 420) charger->chgcsttime = 420; tmp |= ((charger->chgpretime - 30) / 10) << 6 \ | (charger->chgcsttime - 420) / 60; axp_write(charger->master, AXP18_CHARGE_CONTROL1, val); axp_write(charger->master, AXP18_CHARGE_CONTROL2, tmp); axp_read(charger->master, AXP18_CHARGE_STATUS, &val); if(charger ->chgend == 10) val &= ~(1 << 6); else val |= 1 << 6; axp_write(charger->master, AXP18_CHARGE_STATUS, val); }
static int axp_is_enabled(struct regulator_dev *rdev) { struct axp_regulator_info *info = rdev_get_drvdata(rdev); struct device *axp_dev = to_axp_dev(rdev); uint8_t reg_val; int ret; ret = axp_read(axp_dev, info->enable_reg, ®_val); if (ret) return ret; return !!(reg_val & (1 << info->enable_bit)); }
static ssize_t frequency_show(struct device *dev, struct device_attribute *attr, char *buf) { struct regulator_dev *rdev = dev_get_drvdata(dev); struct device *axp_dev = to_axp_dev(rdev); int ret; uint8_t val; ret = axp_read(axp_dev, AXP18_BUCKFREQ, &val); if (ret) return ret; ret = val & 0x0F; return sprintf(buf, "%d\n",(ret*75 + 750)); }
static inline int is_ac_online(void) { uint8_t val; axp_read(&axp->dev,0x00, &val); if(val & ((1<<7) | (1<<5))) { return 1; } else { return 0; } }
static int axp_ldoio0_is_enabled(struct regulator_dev *rdev) { struct axp_regulator_info *info = rdev_get_drvdata(rdev); struct device *axp_dev = to_axp_dev(rdev); uint8_t reg_val; int ret; ret = axp_read(axp_dev, info->enable_reg, ®_val); if (ret) return ret; return (((reg_val &= 0x07)== 0x03)?1:0); }
int axp_usb_det(void) { uint8_t ret = 0; if(axp_charger == NULL || axp_charger->master == NULL) { return ret; } axp_read(axp_charger->master,AXP_CHARGE_STATUS,&ret); if(ret & 0x10)/*usb or usb adapter can be used*/ return 1; else/*no usb or usb adapter*/ return 0; }
int axp_gpio_get_value(int gpio, int *value) { int io_state; int ret; uint8_t val; if (!axp) { printk("[AXP] driver has not ready now, wait...\n"); return -ENODEV; } ret = axp_gpio_get_io(gpio,&io_state); if(ret) return ret; if(io_state){ switch (gpio) { case 0:ret = axp_read(&axp->dev, AXP20_GPIO0_CFG, &val);*value = val & 0x01;break; case 1:ret = axp_read(&axp->dev, AXP20_GPIO1_CFG, &val);*value = val & 0x01;break; case 2:ret = axp_read(&axp->dev, AXP20_GPIO2_CFG, &val);*value = val & 0x01;break; case 3:ret = axp_read(&axp->dev, AXP20_GPIO3_CFG, &val);val &= 0x02;*value = val>>1;break; default: return -ENXIO; } } else { switch (gpio) {
static int axp_get_freq(void) { int ret = 25; uint8_t temp; axp_read(AXP20_ADC_CONTROL3, &temp); temp &= 0xc0; switch(temp >> 6){ case 0: ret = 25; break; case 1: ret = 50; break; case 2: ret = 100;break; case 3: ret = 200;break; default:break; } return ret; }
static int axp_get_voltage(struct regulator_dev *rdev) { struct axp_regulator_info *info = rdev_get_drvdata(rdev); struct device *axp_dev = to_axp_dev(rdev); uint8_t val, mask; int ret; ret = axp_read(axp_dev, info->vol_reg, &val); if (ret) return ret; mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; val = (val & mask) >> info->vol_shift; return info->min_uV + info->step_uV * val; }
static int axp_get_aldo12_voltage(struct regulator_dev *rdev) { struct axp_regulator_info *info = rdev_get_drvdata(rdev); struct device *axp_dev = to_axp_dev(rdev); uint8_t val, mask; int ret; ret = axp_read(axp_dev, info->vol_reg, &val); if (ret) return ret; mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; val = (val & mask) >> info->vol_shift; ret = axp15_aldo12_data[val]*1000; return ret; }