^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Battery charger driver for Dialog Semiconductor DA9030
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2008 Compulab, Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Mike Rapoport <mike@compulab.co.il>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/power_supply.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/mfd/da903x.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/debugfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/notifier.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define DA9030_FAULT_LOG 0x0a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define DA9030_FAULT_LOG_OVER_TEMP (1 << 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define DA9030_FAULT_LOG_VBAT_OVER (1 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define DA9030_CHARGE_CONTROL 0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define DA9030_CHRG_CHARGER_ENABLE (1 << 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define DA9030_ADC_MAN_CONTROL 0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define DA9030_ADC_TBATREF_ENABLE (1 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define DA9030_ADC_LDO_INT_ENABLE (1 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define DA9030_ADC_AUTO_CONTROL 0x31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define DA9030_ADC_TBAT_ENABLE (1 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define DA9030_ADC_VBAT_IN_TXON (1 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define DA9030_ADC_VCH_ENABLE (1 << 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define DA9030_ADC_ICH_ENABLE (1 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define DA9030_ADC_VBAT_ENABLE (1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define DA9030_ADC_AUTO_SLEEP_ENABLE (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define DA9030_VBATMON 0x32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define DA9030_VBATMONTXON 0x33
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define DA9030_TBATHIGHP 0x34
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define DA9030_TBATHIGHN 0x35
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define DA9030_TBATLOW 0x36
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define DA9030_VBAT_RES 0x41
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define DA9030_VBATMIN_RES 0x42
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define DA9030_VBATMINTXON_RES 0x43
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define DA9030_ICHMAX_RES 0x44
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define DA9030_ICHMIN_RES 0x45
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define DA9030_ICHAVERAGE_RES 0x46
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define DA9030_VCHMAX_RES 0x47
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define DA9030_VCHMIN_RES 0x48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define DA9030_TBAT_RES 0x49
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct da9030_adc_res {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) uint8_t vbat_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) uint8_t vbatmin_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) uint8_t vbatmintxon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) uint8_t ichmax_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) uint8_t ichmin_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) uint8_t ichaverage_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) uint8_t vchmax_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) uint8_t vchmin_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) uint8_t tbat_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) uint8_t adc_in4_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) uint8_t adc_in5_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct da9030_battery_thresholds {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) int tbat_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) int tbat_high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) int tbat_restart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) int vbat_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) int vbat_crit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) int vbat_charge_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) int vbat_charge_stop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) int vbat_charge_restart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) int vcharge_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) int vcharge_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) struct da9030_charger {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct power_supply *psy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct power_supply_desc psy_desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct device *master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct da9030_adc_res adc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct delayed_work work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) unsigned int interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct power_supply_info *battery_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct da9030_battery_thresholds thresholds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) unsigned int charge_milliamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) unsigned int charge_millivolt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /* charger status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) bool chdet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) uint8_t fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) int mA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) int mV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) bool is_on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) struct notifier_block nb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /* platform callbacks for battery low and critical events */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) void (*battery_low)(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) void (*battery_critical)(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct dentry *debug_file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static inline int da9030_reg_to_mV(int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return ((reg * 2650) >> 8) + 2650;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static inline int da9030_millivolt_to_reg(int mV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return ((mV - 2650) << 8) / 2650;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static inline int da9030_reg_to_mA(int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return ((reg * 24000) >> 8) / 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #ifdef CONFIG_DEBUG_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static int bat_debug_show(struct seq_file *s, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct da9030_charger *charger = s->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) seq_printf(s, "charger is %s\n", charger->is_on ? "on" : "off");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (charger->chdet) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) seq_printf(s, "iset = %dmA, vset = %dmV\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) charger->mA, charger->mV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) seq_printf(s, "vbat_res = %d (%dmV)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) charger->adc.vbat_res,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) da9030_reg_to_mV(charger->adc.vbat_res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) seq_printf(s, "vbatmin_res = %d (%dmV)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) charger->adc.vbatmin_res,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) da9030_reg_to_mV(charger->adc.vbatmin_res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) seq_printf(s, "vbatmintxon = %d (%dmV)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) charger->adc.vbatmintxon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) da9030_reg_to_mV(charger->adc.vbatmintxon));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) seq_printf(s, "ichmax_res = %d (%dmA)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) charger->adc.ichmax_res,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) da9030_reg_to_mV(charger->adc.ichmax_res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) seq_printf(s, "ichmin_res = %d (%dmA)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) charger->adc.ichmin_res,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) da9030_reg_to_mA(charger->adc.ichmin_res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) seq_printf(s, "ichaverage_res = %d (%dmA)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) charger->adc.ichaverage_res,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) da9030_reg_to_mA(charger->adc.ichaverage_res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) seq_printf(s, "vchmax_res = %d (%dmV)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) charger->adc.vchmax_res,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) da9030_reg_to_mA(charger->adc.vchmax_res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) seq_printf(s, "vchmin_res = %d (%dmV)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) charger->adc.vchmin_res,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) da9030_reg_to_mV(charger->adc.vchmin_res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) DEFINE_SHOW_ATTRIBUTE(bat_debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) static struct dentry *da9030_bat_create_debugfs(struct da9030_charger *charger)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) charger->debug_file = debugfs_create_file("charger", 0666, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) charger, &bat_debug_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) return charger->debug_file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static void da9030_bat_remove_debugfs(struct da9030_charger *charger)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) debugfs_remove(charger->debug_file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) static inline struct dentry *da9030_bat_create_debugfs(struct da9030_charger *charger)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) static inline void da9030_bat_remove_debugfs(struct da9030_charger *charger)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) static inline void da9030_read_adc(struct da9030_charger *charger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) struct da9030_adc_res *adc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) da903x_reads(charger->master, DA9030_VBAT_RES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) sizeof(*adc), (uint8_t *)adc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) static void da9030_charger_update_state(struct da9030_charger *charger)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) uint8_t val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) da903x_read(charger->master, DA9030_CHARGE_CONTROL, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) charger->is_on = (val & DA9030_CHRG_CHARGER_ENABLE) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) charger->mA = ((val >> 3) & 0xf) * 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) charger->mV = (val & 0x7) * 50 + 4000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) da9030_read_adc(charger, &charger->adc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) da903x_read(charger->master, DA9030_FAULT_LOG, &charger->fault);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) charger->chdet = da903x_query_status(charger->master,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) DA9030_STATUS_CHDET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static void da9030_set_charge(struct da9030_charger *charger, int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) uint8_t val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) val = DA9030_CHRG_CHARGER_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) val |= (charger->charge_milliamp / 100) << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) val |= (charger->charge_millivolt - 4000) / 50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) charger->is_on = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) charger->is_on = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) da903x_write(charger->master, DA9030_CHARGE_CONTROL, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) power_supply_changed(charger->psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) static void da9030_charger_check_state(struct da9030_charger *charger)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) da9030_charger_update_state(charger);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) /* we wake or boot with external power on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (!charger->is_on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if ((charger->chdet) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) (charger->adc.vbat_res <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) charger->thresholds.vbat_charge_start)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) da9030_set_charge(charger, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) /* Charger has been pulled out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (!charger->chdet) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) da9030_set_charge(charger, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (charger->adc.vbat_res >=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) charger->thresholds.vbat_charge_stop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) da9030_set_charge(charger, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) da903x_write(charger->master, DA9030_VBATMON,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) charger->thresholds.vbat_charge_restart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) } else if (charger->adc.vbat_res >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) charger->thresholds.vbat_low) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) /* we are charging and passed LOW_THRESH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) so upate DA9030 VBAT threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) da903x_write(charger->master, DA9030_VBATMON,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) charger->thresholds.vbat_low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (charger->adc.vchmax_res > charger->thresholds.vcharge_max ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) charger->adc.vchmin_res < charger->thresholds.vcharge_min ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) /* Tempreture readings are negative */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) charger->adc.tbat_res < charger->thresholds.tbat_high ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) charger->adc.tbat_res > charger->thresholds.tbat_low) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) /* disable charger */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) da9030_set_charge(charger, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) static void da9030_charging_monitor(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) struct da9030_charger *charger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) charger = container_of(work, struct da9030_charger, work.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) da9030_charger_check_state(charger);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /* reschedule for the next time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) schedule_delayed_work(&charger->work, charger->interval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) static enum power_supply_property da9030_battery_props[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) POWER_SUPPLY_PROP_MODEL_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) POWER_SUPPLY_PROP_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) POWER_SUPPLY_PROP_HEALTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) POWER_SUPPLY_PROP_TECHNOLOGY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) POWER_SUPPLY_PROP_VOLTAGE_NOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) POWER_SUPPLY_PROP_CURRENT_AVG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static void da9030_battery_check_status(struct da9030_charger *charger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) union power_supply_propval *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) if (charger->chdet) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (charger->is_on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) val->intval = POWER_SUPPLY_STATUS_CHARGING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) static void da9030_battery_check_health(struct da9030_charger *charger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) union power_supply_propval *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (charger->fault & DA9030_FAULT_LOG_OVER_TEMP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) else if (charger->fault & DA9030_FAULT_LOG_VBAT_OVER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) val->intval = POWER_SUPPLY_HEALTH_GOOD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) static int da9030_battery_get_property(struct power_supply *psy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) enum power_supply_property psp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) union power_supply_propval *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) struct da9030_charger *charger = power_supply_get_drvdata(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) switch (psp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) case POWER_SUPPLY_PROP_STATUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) da9030_battery_check_status(charger, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) case POWER_SUPPLY_PROP_HEALTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) da9030_battery_check_health(charger, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) case POWER_SUPPLY_PROP_TECHNOLOGY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) val->intval = charger->battery_info->technology;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) val->intval = charger->battery_info->voltage_max_design;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) val->intval = charger->battery_info->voltage_min_design;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) case POWER_SUPPLY_PROP_VOLTAGE_NOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) val->intval = da9030_reg_to_mV(charger->adc.vbat_res) * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) case POWER_SUPPLY_PROP_CURRENT_AVG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) val->intval =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) da9030_reg_to_mA(charger->adc.ichaverage_res) * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) case POWER_SUPPLY_PROP_MODEL_NAME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) val->strval = charger->battery_info->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) static void da9030_battery_vbat_event(struct da9030_charger *charger)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) da9030_read_adc(charger, &charger->adc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (charger->is_on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (charger->adc.vbat_res < charger->thresholds.vbat_low) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) /* set VBAT threshold for critical */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) da903x_write(charger->master, DA9030_VBATMON,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) charger->thresholds.vbat_crit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (charger->battery_low)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) charger->battery_low();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) } else if (charger->adc.vbat_res <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) charger->thresholds.vbat_crit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) /* notify the system of battery critical */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (charger->battery_critical)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) charger->battery_critical();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) static int da9030_battery_event(struct notifier_block *nb, unsigned long event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) struct da9030_charger *charger =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) container_of(nb, struct da9030_charger, nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) switch (event) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) case DA9030_EVENT_CHDET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) cancel_delayed_work_sync(&charger->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) schedule_work(&charger->work.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) case DA9030_EVENT_VBATMON:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) da9030_battery_vbat_event(charger);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) case DA9030_EVENT_CHIOVER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) case DA9030_EVENT_TBAT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) da9030_set_charge(charger, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) static void da9030_battery_convert_thresholds(struct da9030_charger *charger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) struct da9030_battery_info *pdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) charger->thresholds.tbat_low = pdata->tbat_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) charger->thresholds.tbat_high = pdata->tbat_high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) charger->thresholds.tbat_restart = pdata->tbat_restart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) charger->thresholds.vbat_low =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) da9030_millivolt_to_reg(pdata->vbat_low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) charger->thresholds.vbat_crit =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) da9030_millivolt_to_reg(pdata->vbat_crit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) charger->thresholds.vbat_charge_start =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) da9030_millivolt_to_reg(pdata->vbat_charge_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) charger->thresholds.vbat_charge_stop =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) da9030_millivolt_to_reg(pdata->vbat_charge_stop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) charger->thresholds.vbat_charge_restart =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) da9030_millivolt_to_reg(pdata->vbat_charge_restart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) charger->thresholds.vcharge_min =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) da9030_millivolt_to_reg(pdata->vcharge_min);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) charger->thresholds.vcharge_max =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) da9030_millivolt_to_reg(pdata->vcharge_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) static void da9030_battery_setup_psy(struct da9030_charger *charger)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) struct power_supply_desc *psy_desc = &charger->psy_desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) struct power_supply_info *info = charger->battery_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) psy_desc->name = info->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) psy_desc->use_for_apm = info->use_for_apm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) psy_desc->type = POWER_SUPPLY_TYPE_BATTERY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) psy_desc->get_property = da9030_battery_get_property;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) psy_desc->properties = da9030_battery_props;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) psy_desc->num_properties = ARRAY_SIZE(da9030_battery_props);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) static int da9030_battery_charger_init(struct da9030_charger *charger)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) char v[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) v[0] = v[1] = charger->thresholds.vbat_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) v[2] = charger->thresholds.tbat_high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) v[3] = charger->thresholds.tbat_restart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) v[4] = charger->thresholds.tbat_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) ret = da903x_writes(charger->master, DA9030_VBATMON, 5, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) * Enable reference voltage supply for ADC from the LDO_INTERNAL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) * regulator. Must be set before ADC measurements can be made.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) ret = da903x_write(charger->master, DA9030_ADC_MAN_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) DA9030_ADC_LDO_INT_ENABLE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) DA9030_ADC_TBATREF_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) /* enable auto ADC measuremnts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) return da903x_write(charger->master, DA9030_ADC_AUTO_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) DA9030_ADC_TBAT_ENABLE | DA9030_ADC_VBAT_IN_TXON |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) DA9030_ADC_VCH_ENABLE | DA9030_ADC_ICH_ENABLE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) DA9030_ADC_VBAT_ENABLE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) DA9030_ADC_AUTO_SLEEP_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) static int da9030_battery_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) struct da9030_charger *charger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) struct power_supply_config psy_cfg = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) struct da9030_battery_info *pdata = pdev->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (pdata == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) if (pdata->charge_milliamp >= 1500 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) pdata->charge_millivolt < 4000 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) pdata->charge_millivolt > 4350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) charger = devm_kzalloc(&pdev->dev, sizeof(*charger), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if (charger == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) charger->master = pdev->dev.parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) /* 10 seconds between monitor runs unless platform defines other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) interval */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) charger->interval = msecs_to_jiffies(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) (pdata->batmon_interval ? : 10) * 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) charger->charge_milliamp = pdata->charge_milliamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) charger->charge_millivolt = pdata->charge_millivolt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) charger->battery_info = pdata->battery_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) charger->battery_low = pdata->battery_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) charger->battery_critical = pdata->battery_critical;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) da9030_battery_convert_thresholds(charger, pdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) ret = da9030_battery_charger_init(charger);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) goto err_charger_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) INIT_DELAYED_WORK(&charger->work, da9030_charging_monitor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) schedule_delayed_work(&charger->work, charger->interval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) charger->nb.notifier_call = da9030_battery_event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) ret = da903x_register_notifier(charger->master, &charger->nb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) DA9030_EVENT_CHDET |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) DA9030_EVENT_VBATMON |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) DA9030_EVENT_CHIOVER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) DA9030_EVENT_TBAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) goto err_notifier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) da9030_battery_setup_psy(charger);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) psy_cfg.drv_data = charger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) charger->psy = power_supply_register(&pdev->dev, &charger->psy_desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) &psy_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) if (IS_ERR(charger->psy)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) ret = PTR_ERR(charger->psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) goto err_ps_register;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) charger->debug_file = da9030_bat_create_debugfs(charger);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) platform_set_drvdata(pdev, charger);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) err_ps_register:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) da903x_unregister_notifier(charger->master, &charger->nb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) DA9030_EVENT_CHDET | DA9030_EVENT_VBATMON |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) DA9030_EVENT_CHIOVER | DA9030_EVENT_TBAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) err_notifier:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) cancel_delayed_work(&charger->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) err_charger_init:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) static int da9030_battery_remove(struct platform_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) struct da9030_charger *charger = platform_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) da9030_bat_remove_debugfs(charger);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) da903x_unregister_notifier(charger->master, &charger->nb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) DA9030_EVENT_CHDET | DA9030_EVENT_VBATMON |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) DA9030_EVENT_CHIOVER | DA9030_EVENT_TBAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) cancel_delayed_work_sync(&charger->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) da9030_set_charge(charger, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) power_supply_unregister(charger->psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) static struct platform_driver da903x_battery_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) .name = "da903x-battery",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) .probe = da9030_battery_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) .remove = da9030_battery_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) module_platform_driver(da903x_battery_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) MODULE_DESCRIPTION("DA9030 battery charger driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) MODULE_AUTHOR("Mike Rapoport, CompuLab");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) MODULE_LICENSE("GPL");