^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Generic battery driver code using IIO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2012, Anish Kumar <anish198519851985@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * based on jz4740-battery.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * based on s3c_adc_battery.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * License. See the file COPYING in the main directory of this archive for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/power_supply.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/gpio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/jiffies.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/iio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/iio/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/power/generic-adc-battery.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define JITTER_DEFAULT 10 /* hope 10ms is enough */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) enum gab_chan_type {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) GAB_VOLTAGE = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) GAB_CURRENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) GAB_POWER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) GAB_MAX_CHAN_TYPE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * gab_chan_name suggests the standard channel names for commonly used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * channel types.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static const char *const gab_chan_name[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) [GAB_VOLTAGE] = "voltage",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) [GAB_CURRENT] = "current",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) [GAB_POWER] = "power",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct gab {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct power_supply *psy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct power_supply_desc psy_desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct iio_channel *channel[GAB_MAX_CHAN_TYPE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct gab_platform_data *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct delayed_work bat_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) int level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) bool cable_plugged;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static struct gab *to_generic_bat(struct power_supply *psy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return power_supply_get_drvdata(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static void gab_ext_power_changed(struct power_supply *psy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct gab *adc_bat = to_generic_bat(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) schedule_delayed_work(&adc_bat->bat_work, msecs_to_jiffies(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static const enum power_supply_property gab_props[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) POWER_SUPPLY_PROP_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) POWER_SUPPLY_PROP_CHARGE_NOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) POWER_SUPPLY_PROP_VOLTAGE_NOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) POWER_SUPPLY_PROP_CURRENT_NOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) POWER_SUPPLY_PROP_TECHNOLOGY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) POWER_SUPPLY_PROP_MODEL_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * This properties are set based on the received platform data and this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * should correspond one-to-one with enum chan_type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static const enum power_supply_property gab_dyn_props[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) POWER_SUPPLY_PROP_VOLTAGE_NOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) POWER_SUPPLY_PROP_CURRENT_NOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) POWER_SUPPLY_PROP_POWER_NOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static bool gab_charge_finished(struct gab *adc_bat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct gab_platform_data *pdata = adc_bat->pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) bool ret = gpio_get_value(pdata->gpio_charge_finished);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) bool inv = pdata->gpio_inverted;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (!gpio_is_valid(pdata->gpio_charge_finished))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return ret ^ inv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static int gab_get_status(struct gab *adc_bat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct gab_platform_data *pdata = adc_bat->pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct power_supply_info *bat_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) bat_info = &pdata->battery_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (adc_bat->level == bat_info->charge_full_design)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return POWER_SUPPLY_STATUS_FULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return adc_bat->status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static enum gab_chan_type gab_prop_to_chan(enum power_supply_property psp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) switch (psp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) case POWER_SUPPLY_PROP_POWER_NOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return GAB_POWER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) case POWER_SUPPLY_PROP_VOLTAGE_NOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return GAB_VOLTAGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) case POWER_SUPPLY_PROP_CURRENT_NOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return GAB_CURRENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) return GAB_POWER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) static int read_channel(struct gab *adc_bat, enum power_supply_property psp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) int *result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) int chan_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) chan_index = gab_prop_to_chan(psp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) ret = iio_read_channel_processed(adc_bat->channel[chan_index],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) pr_err("read channel error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static int gab_get_property(struct power_supply *psy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) enum power_supply_property psp, union power_supply_propval *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) struct gab *adc_bat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) struct gab_platform_data *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) struct power_supply_info *bat_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) int result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) adc_bat = to_generic_bat(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (!adc_bat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) dev_err(&psy->dev, "no battery infos ?!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) pdata = adc_bat->pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) bat_info = &pdata->battery_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) switch (psp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) case POWER_SUPPLY_PROP_STATUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) val->intval = gab_get_status(adc_bat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) case POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) val->intval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) case POWER_SUPPLY_PROP_CHARGE_NOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) val->intval = pdata->cal_charge(result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) case POWER_SUPPLY_PROP_VOLTAGE_NOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) case POWER_SUPPLY_PROP_CURRENT_NOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) case POWER_SUPPLY_PROP_POWER_NOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) ret = read_channel(adc_bat, psp, &result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) val->intval = result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) case POWER_SUPPLY_PROP_TECHNOLOGY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) val->intval = bat_info->technology;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) val->intval = bat_info->voltage_min_design;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) val->intval = bat_info->voltage_max_design;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) val->intval = bat_info->charge_full_design;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) case POWER_SUPPLY_PROP_MODEL_NAME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) val->strval = bat_info->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) static void gab_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) struct gab *adc_bat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) struct delayed_work *delayed_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) bool is_plugged;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) delayed_work = to_delayed_work(work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) adc_bat = container_of(delayed_work, struct gab, bat_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) status = adc_bat->status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) is_plugged = power_supply_am_i_supplied(adc_bat->psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) adc_bat->cable_plugged = is_plugged;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if (!is_plugged)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) adc_bat->status = POWER_SUPPLY_STATUS_DISCHARGING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) else if (gab_charge_finished(adc_bat))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) adc_bat->status = POWER_SUPPLY_STATUS_NOT_CHARGING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) adc_bat->status = POWER_SUPPLY_STATUS_CHARGING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (status != adc_bat->status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) power_supply_changed(adc_bat->psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) static irqreturn_t gab_charged(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) struct gab *adc_bat = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) struct gab_platform_data *pdata = adc_bat->pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) int delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) delay = pdata->jitter_delay ? pdata->jitter_delay : JITTER_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) schedule_delayed_work(&adc_bat->bat_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) msecs_to_jiffies(delay));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) static int gab_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) struct gab *adc_bat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) struct power_supply_desc *psy_desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) struct power_supply_config psy_cfg = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) struct gab_platform_data *pdata = pdev->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) enum power_supply_property *properties;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) int chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) int index = ARRAY_SIZE(gab_props);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) bool any = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) adc_bat = devm_kzalloc(&pdev->dev, sizeof(*adc_bat), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (!adc_bat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) dev_err(&pdev->dev, "failed to allocate memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) psy_cfg.drv_data = adc_bat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) psy_desc = &adc_bat->psy_desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) psy_desc->name = pdata->battery_info.name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) /* bootup default values for the battery */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) adc_bat->cable_plugged = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) adc_bat->status = POWER_SUPPLY_STATUS_DISCHARGING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) psy_desc->type = POWER_SUPPLY_TYPE_BATTERY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) psy_desc->get_property = gab_get_property;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) psy_desc->external_power_changed = gab_ext_power_changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) adc_bat->pdata = pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) * copying the static properties and allocating extra memory for holding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) * the extra configurable properties received from platform data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) properties = kcalloc(ARRAY_SIZE(gab_props) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) ARRAY_SIZE(gab_chan_name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) sizeof(*properties),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (!properties) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) goto first_mem_fail;
^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) memcpy(properties, gab_props, sizeof(gab_props));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) * getting channel from iio and copying the battery properties
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) * based on the channel supported by consumer device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) for (chan = 0; chan < ARRAY_SIZE(gab_chan_name); chan++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) adc_bat->channel[chan] = iio_channel_get(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) gab_chan_name[chan]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if (IS_ERR(adc_bat->channel[chan])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) ret = PTR_ERR(adc_bat->channel[chan]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) adc_bat->channel[chan] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) /* copying properties for supported channels only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) int index2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) for (index2 = 0; index2 < index; index2++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (properties[index2] == gab_dyn_props[chan])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) break; /* already known */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (index2 == index) /* really new */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) properties[index++] = gab_dyn_props[chan];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) any = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) /* none of the channels are supported so let's bail out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (!any) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) goto second_mem_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) * Total number of properties is equal to static properties
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) * plus the dynamic properties.Some properties may not be set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) * as come channels may be not be supported by the device.So
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) * we need to take care of that.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) psy_desc->properties = properties;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) psy_desc->num_properties = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) adc_bat->psy = power_supply_register(&pdev->dev, psy_desc, &psy_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (IS_ERR(adc_bat->psy)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) ret = PTR_ERR(adc_bat->psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) goto err_reg_fail;
^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) INIT_DELAYED_WORK(&adc_bat->bat_work, gab_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (gpio_is_valid(pdata->gpio_charge_finished)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) ret = gpio_request(pdata->gpio_charge_finished, "charged");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) goto gpio_req_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) irq = gpio_to_irq(pdata->gpio_charge_finished);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) ret = request_any_context_irq(irq, gab_charged,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) "battery charged", adc_bat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) goto err_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) platform_set_drvdata(pdev, adc_bat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) /* Schedule timer to check current status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) schedule_delayed_work(&adc_bat->bat_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) msecs_to_jiffies(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) err_gpio:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) gpio_free(pdata->gpio_charge_finished);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) gpio_req_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) power_supply_unregister(adc_bat->psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) err_reg_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) for (chan = 0; chan < ARRAY_SIZE(gab_chan_name); chan++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (adc_bat->channel[chan])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) iio_channel_release(adc_bat->channel[chan]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) second_mem_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) kfree(properties);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) first_mem_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) static int gab_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) int chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) struct gab *adc_bat = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) struct gab_platform_data *pdata = adc_bat->pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) power_supply_unregister(adc_bat->psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (gpio_is_valid(pdata->gpio_charge_finished)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) free_irq(gpio_to_irq(pdata->gpio_charge_finished), adc_bat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) gpio_free(pdata->gpio_charge_finished);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) for (chan = 0; chan < ARRAY_SIZE(gab_chan_name); chan++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (adc_bat->channel[chan])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) iio_channel_release(adc_bat->channel[chan]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) kfree(adc_bat->psy_desc.properties);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) cancel_delayed_work_sync(&adc_bat->bat_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) static int __maybe_unused gab_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) struct gab *adc_bat = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) cancel_delayed_work_sync(&adc_bat->bat_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) adc_bat->status = POWER_SUPPLY_STATUS_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) static int __maybe_unused gab_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) struct gab *adc_bat = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) struct gab_platform_data *pdata = adc_bat->pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) int delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) delay = pdata->jitter_delay ? pdata->jitter_delay : JITTER_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) /* Schedule timer to check current status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) schedule_delayed_work(&adc_bat->bat_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) msecs_to_jiffies(delay));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) static SIMPLE_DEV_PM_OPS(gab_pm_ops, gab_suspend, gab_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) static struct platform_driver gab_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) .name = "generic-adc-battery",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) .pm = &gab_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) .probe = gab_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) .remove = gab_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) module_platform_driver(gab_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) MODULE_AUTHOR("anish kumar <anish198519851985@gmail.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) MODULE_DESCRIPTION("generic battery driver using IIO");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) MODULE_LICENSE("GPL");