Загрузка данных
static int max17055_get_status(struct max17042_chip *chip, int *status)
{
int ret, avg_current;
u32 data, vcell_data, soc_data;
int real_vcell, real_avg_curr, real_soc;
/* 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% для следующего цикла нормальной зарядки
* и сбрасываем защелку конечного автомата. До этого момента (пока статус FULL
* и кабель подключен) порог удерживается заниженным, сохраняя стабильные 100%. */
if (chip->scale_synced) {
regmap_write(chip->regmap, MAX17047_FullSOCThr, 0x5F00); /* Возврат на 95% */
chip->scale_synced = false;
}
return 0;
}
/* По умолчанию выставляем статус активной зарядки */
*status = POWER_SUPPLY_STATUS_CHARGING;
/* 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_RepSOC, &soc_data) < 0) {
return -EIO;
}
real_vcell = vcell_data * 78125 / 1000000; /* Напряжение в мВ (примерно 4225 мВ) */
real_avg_curr = sign_extend32(data, 15) * 1562500 / chip->pdata->r_sns; /* Ток в мА */
real_soc = soc_data >> 8; /* Текущее целое значение отображаемых процентов */
/* Вывод лога для контроля параметров в dmesg */
printk("%s: VCELL=%d mV, AvgCurrent=%d mA, RepSOC=%d%%\n",
__FUNCTION__, real_vcell, real_avg_curr, real_soc);
/* 3. ГАРАНТИРОВАННЫЙ ТРИГГЕР АДАПТАЦИИ ПОД ИЗНОС БАТАРЕИ
* Срабатывает СТРОГО 1 РАЗ за сессию зарядки при выполнении 4-х условий:
* - Напряжение на банке вышло на стадию CV (>= 4.21В)
* - Средний ток честно упал ниже 195 мА (основной заряд завершен)
* - Батарея успела набрать хотя бы 85% емкости (защита от ложного срабатывания на пустом АКБ)
* - Коррекция в этом цикле еще не выполнялась (!chip->scale_synced)
*/
if (real_vcell >= 4210 && real_avg_curr > 0 && real_avg_curr < 195 && 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 (АППАРАТНЫЙ ВАРИАНТ)
* Читаем регистр STATUS (0x00) и проверяем 10-й бит FQ (маска 0x0400) */
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 (ПРОГРАММНЫЙ ДУБЛЕР)
* Защита от наводок чарджера и шумов земли. Если шкала благодаря нашей адаптации
* успешно дошла до 100%, напряжение стабильно на плато, а средний ток заряда
* находится в минимальных пределах, принудительно отдаем операционной системе статус FULL.
*/
if (*status == POWER_SUPPLY_STATUS_CHARGING && real_soc >= 100 && real_vcell >= 4210 && real_avg_curr > 0 && real_avg_curr < 195) {
printk("%s: !!! SCALE REACHED 100%% AND CV PLATEAU. FORCING FULL STATUS !!!\n", __FUNCTION__);
*status = POWER_SUPPLY_STATUS_FULL;
return 0;
}
return 0;
}