Загрузка данных
static int max17055_get_status(struct max17042_chip *chip, int *status)
{
int ret, avg_current;
u32 data, vcell_data, soc_data, curr_data;
int real_vcell, real_avg_curr, real_curr, real_soc;
/* Значения по умолчанию (fallbacks) на случай, если pdata пуст */
int dts_ichg_term_ma = 150;
int dts_vmax_mv = 4250;
/* 1. Проверяем физическое подключение внешнего источника питания */
ret = power_supply_am_i_supplied(chip->battery);
if (ret < 0) {
*status = POWER_SUPPLY_STATUS_UNKNOWN;
return 0;
}
if (ret == 0) {
*status = POWER_SUPPLY_STATUS_DISCHARGING;
/* Возвращаем заводской порог 95% при отключении кабеля */
if (chip->scale_synced) {
regmap_write(chip->regmap, MAX17047_FullSOCThr, 0x5F00);
chip->scale_synced = false;
}
return 0;
}
/* По умолчанию выставляем статус активной зарядки */
*status = POWER_SUPPLY_STATUS_CHARGING;
/* ДИНАМИЧЕСКИЙ СБОР ПАРАМЕТРОВ ТОКА ИЗ DTS */
if (chip->pdata && chip->pdata->ichg_term) {
if (chip->pdata->ichg_term > 5000)
dts_ichg_term_ma = chip->pdata->ichg_term / 1000; /* Перевод из мкА в мА */
else
dts_ichg_term_ma = chip->pdata->ichg_term;
}
/* Ток отсечки: значение DTS + 10 мА запаса на пульсации */
int current_trigger_threshold = dts_ichg_term_ma + 10;
/* ДИНАМИЧЕСКИЙ СБОР ПАРАМЕТРОВ НАПРЯЖЕНИЯ ИЗ DTS */
if (chip->pdata && chip->pdata->vmax > 0) {
/* Если vmax в pdata заполнено из свойства "maxim,over-volt" */
dts_vmax_mv = chip->pdata->vmax;
}
/* Порог детекции CV-плато: Максимум из DTS минус 40 мВ (например, 4250 - 40 = 4210 мВ) */
int voltage_cv_threshold = dts_vmax_mv - 40;
/* 2. Считываем физические параметры из регистров MAX17055 */
if (regmap_read(chip->regmap, MAX17042_VCELL, &vcell_data) < 0 ||
regmap_read(chip->regmap, MAX17042_AvgCurrent, &data) < 0 ||
regmap_read(chip->regmap, MAX17042_Current, &curr_data) < 0 ||
regmap_read(chip->regmap, MAX17042_RepSOC, &soc_data) < 0) {
return -EIO;
}
real_vcell = vcell_data * 78125 / 1000000; /* Напряжение в мВ */
real_avg_curr = sign_extend32(data, 15) * 1562500 / chip->pdata->r_sns; /* Средний ток в мА */
real_curr = sign_extend32(curr_data, 15) * 1562500 / chip->pdata->r_sns; /* Мгновенный ток в мА */
real_soc = soc_data >> 8; /* Текущее целое значение процентов */
/* Вывод лога для контроля параметров в dmesg */
printk("%s: VCELL=%d mV (Target CV>=%d), Current=%d mA, AvgCurrent=%d mA, RepSOC=%d%% (DTS Term=%d mA)\n",
__FUNCTION__, real_vcell, voltage_cv_threshold, real_curr, real_avg_curr, real_soc, dts_ichg_term_ma);
/* 3. ГАРАНТИРОВАННЫЙ ТРИГГЕР АДАПТАЦИИ ПОД ИЗНОС БАТАРЕИ */
if (real_vcell >= voltage_cv_threshold &&
real_avg_curr > 0 && real_avg_curr < current_trigger_threshold &&
real_curr > 0 && real_curr < current_trigger_threshold &&
real_soc >= 85 && !chip->scale_synced) {
/* Вычисляем адаптивный порог: текущий застрявший SOC минус 2% безопасности */
int target_soc_threshold = real_soc - 2;
if (target_soc_threshold > 95) target_soc_threshold = 95;
if (target_soc_threshold < 80) target_soc_threshold = 80;
u16 raw_thr_value = (target_soc_threshold << 8) & 0xFF00;
dev_info(&chip->client->dev,
"ModelGauge m5: Battery aging detected. Shifting FullSOCThr to %d%%\n",
target_soc_threshold);
/* Фиксируем скорректированный порог и взводим защелку */
regmap_write(chip->regmap, MAX17047_FullSOCThr, raw_thr_value);
chip->scale_synced = true;
}
/* 4. ПРОВЕРКА СТАТУСА FULL (АППАРАТНЫЙ ВАРИАНТ) */
ret = regmap_read(chip->regmap, MAX17042_STATUS, &data);
if (ret == 0 && (data & 0x0400)) {
printk("%s: !!! STATUS FULL FROM HARDWARE FQ BIT !!!\n", __FUNCTION__);
*status = POWER_SUPPLY_STATUS_FULL;
return 0;
}
/* 5. ПРОВЕРКА СТАТУСА FULL (ПРОГРАММНЫЙ ДУБЛЕР) */
if (*status == POWER_SUPPLY_STATUS_CHARGING && real_soc >= 100 &&
real_vcell >= voltage_cv_threshold &&
real_avg_curr > 0 && real_avg_curr < current_trigger_threshold &&
real_curr > 0 && real_curr < current_trigger_threshold) {
printk("%s: !!! SCALE REACHED 100%% AND CV PLATEAU. FORCING FULL STATUS !!!\n", __FUNCTION__);
*status = POWER_SUPPLY_STATUS_FULL;
return 0;
}
return 0;
}