blob: 195a7ce0cd04c22b579a076e029a4b6b7edbfc0d [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Google Battery Management System
*
* Copyright 2020 Google, LLC
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __GBMS_POWER_SUPPLY_H__
#define __GBMS_POWER_SUPPLY_H__
#include <linux/power_supply.h>
enum {
GBMS_TAPER_CONTROL_OFF = 0,
GBMS_TAPER_CONTROL_ON,
};
/* Indicates USB Type-C CC connection status */
/* Deprecated */
enum power_supply_typec_mode {
POWER_SUPPLY_TYPEC_NONE,
/* Acting as source */
POWER_SUPPLY_TYPEC_SINK, /* Rd only */
POWER_SUPPLY_TYPEC_SINK_POWERED_CABLE, /* Rd/Ra */
POWER_SUPPLY_TYPEC_SINK_DEBUG_ACCESSORY,/* Rd/Rd */
POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER, /* Ra/Ra */
POWER_SUPPLY_TYPEC_POWERED_CABLE_ONLY, /* Ra only */
/* Acting as sink */
POWER_SUPPLY_TYPEC_SOURCE_DEFAULT, /* Rp default */
POWER_SUPPLY_TYPEC_SOURCE_MEDIUM, /* Rp 1.5A */
POWER_SUPPLY_TYPEC_SOURCE_HIGH, /* Rp 3A */
POWER_SUPPLY_TYPEC_DAM_DEFAULT, /* Rp-1.5A/Rp-3A */
POWER_SUPPLY_TYPEC_DAM_MEDIUM, /* Rp-Default/Rp-1.5A */
POWER_SUPPLY_TYPEC_DAM_HIGH, /* Rp-Default/Rp-3A */
/* Non Compliant */
POWER_SUPPLY_TYPEC_NON_COMPLIANT,
POWER_SUPPLY_TYPEC_RP_STD_STD, /* Rp-Default/Rp-Default */
POWER_SUPPLY_TYPEC_RP_MED_MED, /* Rp-1.5A/Rp-1.5A */
POWER_SUPPLY_TYPEC_RP_HIGH_HIGH, /* Rp-3A/Rp-3A */
};
/* Deprecated */
enum power_supply_typec_src_rp {
POWER_SUPPLY_TYPEC_SRC_RP_STD,
POWER_SUPPLY_TYPEC_SRC_RP_1P5A,
POWER_SUPPLY_TYPEC_SRC_RP_3A
};
/* Deprecated */
enum power_supply_typec_power_role {
POWER_SUPPLY_TYPEC_PR_NONE, /* CC lines in high-Z */
POWER_SUPPLY_TYPEC_PR_DUAL,
POWER_SUPPLY_TYPEC_PR_SINK,
POWER_SUPPLY_TYPEC_PR_SOURCE,
};
enum gbms_property {
/* I am not proud of this */
GBMS_PROP_LOCAL_EXTENSIONS = POWER_SUPPLY_PROP_SERIAL_NUMBER + 100,
GBMS_PROP_ADAPTER_DETAILS, /* GBMS Adapter Details */
GBMS_PROP_BATT_CE_CTRL, /* GBMS plugged (replace with GBMS_PROP_CHARGING_ENABLED) */
GBMS_PROP_CAPACITY_RAW, /* GBMS used for ssoc */
GBMS_PROP_CHARGING_ENABLED, /* GBMS cpm control */
GBMS_PROP_CHARGE_CHARGER_STATE, /* GBMS charge, need uint64 */
GBMS_PROP_CHARGE_DISABLE, /* GBMS disconnect */
GBMS_PROP_DEAD_BATTERY, /* GBMS during boot */
GBMS_PROP_INPUT_CURRENT_LIMITED, /* can be device prop */
GBMS_PROP_TAPER_CONTROL, /* GBMS DC, needs for last tier */
GBMS_PROP_HEALTH_ACT_IMPEDANCE, /* GBMS activation impedance, qualified */
GBMS_PROP_HEALTH_IMPEDANCE, /* GBMS impedance, qualified */
GBMS_PROP_RESISTANCE, /* GBMS battery resistance, unqualified */
GBMS_PROP_RESISTANCE_RAW, /* GBMS battery resistance, unqualified, u16 */
GBMS_PROP_RESISTANCE_AVG, /* GBMS google_resistance */
GBMS_PROP_BATTERY_AGE, /* GBMS time in field */
GBMS_PROP_CAPACITY_FADE_RATE, /* GBMS capaciy fade rate */
GBMS_PROP_CHARGE_FULL_ESTIMATE, /* GBMS google_capacity */
};
union gbms_propval {
union power_supply_propval prop;
int64_t int64val;
};
#define gbms_propval_int64val(psp) \
container_of(psp, union gbms_propval, prop)->int64val
static inline int gpsy_set_int64_prop(struct power_supply *psy,
enum gbms_property psp,
union gbms_propval val,
const char *prop_name)
{
int ret = 0;
if (!psy)
return -EINVAL;
pr_debug("set %s for '%s' to %lld\n", prop_name,
psy->desc->name, (long long)val.int64val);
ret = power_supply_set_property(psy, (enum power_supply_property)psp,
&val.prop);
if (ret < 0)
pr_err("failed to set %s for '%s', ret=%d\n",
prop_name, psy->desc->name, ret);
return ret;
}
#define GPSY_SET_INT64_PROP(psy, psp, val) \
gpsy_set_int64_prop(psy, psp, (union gbms_propval) \
{ .int64val = (int64_t)(val) }, #psp)
static inline int64_t gpsy_get_int64_prop(struct power_supply *psy,
enum gbms_property psp,
const char *prop_name,
int *err)
{
union gbms_propval val;
if (!psy) {
*err = -EINVAL;
return *err;
}
*err = power_supply_get_property(psy, (enum power_supply_property)psp,
&val.prop);
if (*err < 0) {
pr_err("failed to get %s from '%s', ret=%d\n",
prop_name, psy->desc->name, *err);
return *err;
}
pr_debug("get %s for '%s' => %lld\n", prop_name,
psy->desc->name, (long long)val.int64val);
return val.int64val;
}
#define GPSY_GET_INT64_PROP(psy, psp, err) \
gpsy_get_int64_prop(psy, psp, #psp, err)
/* GBMS properties -------------------------------------------------------- */
struct gbms_desc {
struct power_supply_desc psy_dsc;
bool forward;
/* bgms properties */
int (*get_property)(struct power_supply *psy, enum gbms_property psp,
union gbms_propval *val);
int (*set_property)(struct power_supply *psy, enum gbms_property psp,
const union gbms_propval *val);
int (*property_is_writeable)(struct power_supply *psy,
enum gbms_property psp);
};
extern int gbms_set_property(struct power_supply *psy, enum gbms_property psp,
const union gbms_propval *val);
extern int gbms_get_property(struct power_supply *psy, enum gbms_property psp,
union gbms_propval *val);
#endif /* __GBMS_POWER_SUPPLY_H__ */