0df241385b
* Add new Qualcomm PMI8998/PM660 SMB2 charger * bq256xx: support systems without thermistors * cros_pchg: fix peripheral device status after system resume * axp20x_usb_power: add support for AXP192 * qcom-pon: add support for pm8941 * at91-reset: prepare to expose reset reason to sysfs * switch all I2C drivers back to use .probe instead of .probe_new * convert some more DT bindings to YAML * misc. cleanups -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE72YNB0Y/i3JqeVQT2O7X88g7+poFAmSjPRsACgkQ2O7X88g7 +ppEgw//SzE/6dgc5e2OG+qtHb2vnjUrmoz9w0/sGZuTVFhnvZ4ofpEyOrRR8/kV rUT6dqEPh3p/tHIyiLdcAG2JyA3QZ3G8rekdIUOj++vWn4S97FQsqBxwL/46D0om c7S+SDrCo/XKnJvRIiC8a+0HzAsjVUdaWdvzkEovrF5MRS1HeX4GXadaW/c6pdxN NfOZBR2F+JXHlC/nmBtpmQCJvikooz6DPvZd6Tiv9dlywOHNO7NSlcueuuhSofYp /j7BAXq/V+jEynNTPnaBwnO5aA1XPMpC/nOo4HuHjJbrHoXCt5bMhabA9bIlaplN 9bilfxmqqfaMkpWQOhF8qmz+s496WELcmGqGBZXvNBgn/85qYTPxue4JVe1D7ldh TjvGUBZkVUwkce052BZrPZCUTYhlrTBJ/6xpuGeUrPa3C9ib8e9Wm6C13zI2vsJV EeVxgt79cNkdioZ0GfibQTg+bJ7oa8BtwWEk0UaC9jfaPQGfNum05FHRik1a+A7R vehaoIYiCCMaXuHSZoqqjEocdnxXQCNkViMuYNqhN5Bcb0YdlMF6r0T2fa4HND0Y CU8uCofqTc67/RazqCsIRHNXDi6cJOYmdnSc1q7pYCO9/KmoMdP0xIFPB2Mca7uI 2rMooSE77ssYGc1gOW9GWuMNEdvJXNufJJzr5LLdMbhIh0ecy04= =9vtE -----END PGP SIGNATURE----- Merge tag 'for-v6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply Pull power supply and reset updates from Sebastian Reichel: - Add new Qualcomm PMI8998/PM660 SMB2 charger - bq256xx: support systems without thermistors - cros_pchg: fix peripheral device status after system resume - axp20x_usb_power: add support for AXP192 - qcom-pon: add support for pm8941 - at91-reset: prepare to expose reset reason to sysfs - switch all I2C drivers back to use .probe instead of .probe_new - convert some more DT bindings to YAML - misc cleanups * tag 'for-v6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply: (28 commits) MAINTAINERS: add documentation file for Microchip SAMA5D2 shutdown controller dt-bindings: power: reset: atmel,sama5d2-shdwc: convert to yaml dt-bindings: power: reset: atmel,at91sam9260-shdwc: convert to yaml power: reset: at91-reset: change the power on reason prototype power: reset: qcom-pon: add support for pm8941-pon dt-bindings: power: reset: qcom-pon: define pm8941-pon power: supply: add Qualcomm PMI8998 SMB2 Charger driver dt-bindings: power: supply: qcom,pmi8998-charger: add bindings for smb2 driver power: supply: rt9467: Make charger-enable control as logic level power: supply: Switch i2c drivers back to use .probe() power: reset: add HAS_IOPORT dependencies dt-bindings: power: supply: axp20x: Add AXP192 compatible power: supply: axp20x_usb_power: Add support for AXP192 power: supply: axp20x_usb_power: Remove variant IDs from VBUS polling check power: supply: axp20x_usb_power: Use regmap field for VBUS disabling power: supply: axp20x_usb_power: Use regmap fields for USB BC feature power: supply: axp20x_usb_power: Use regmap fields for VBUS monitor feature power: supply: axp20x_usb_power: Simplify USB current limit handling power: supply: hwmon: constify pointers to hwmon_channel_info power: supply: twl4030_madc_battery: Refactor twl4030_madc_bat_ext_changed() ...
208 lines
5.2 KiB
C
208 lines
5.2 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* Fuel gauge driver for Richtek RT5033
|
|
*
|
|
* Copyright (C) 2014 Samsung Electronics, Co., Ltd.
|
|
* Author: Beomho Seo <beomho.seo@samsung.com>
|
|
*/
|
|
|
|
#include <linux/i2c.h>
|
|
#include <linux/module.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/power_supply.h>
|
|
#include <linux/regmap.h>
|
|
#include <linux/mfd/rt5033-private.h>
|
|
|
|
struct rt5033_battery {
|
|
struct i2c_client *client;
|
|
struct regmap *regmap;
|
|
struct power_supply *psy;
|
|
};
|
|
|
|
static int rt5033_battery_get_status(struct i2c_client *client)
|
|
{
|
|
struct rt5033_battery *battery = i2c_get_clientdata(client);
|
|
union power_supply_propval val;
|
|
int ret;
|
|
|
|
ret = power_supply_get_property_from_supplier(battery->psy,
|
|
POWER_SUPPLY_PROP_STATUS,
|
|
&val);
|
|
if (ret)
|
|
val.intval = POWER_SUPPLY_STATUS_UNKNOWN;
|
|
|
|
return val.intval;
|
|
}
|
|
|
|
static int rt5033_battery_get_capacity(struct i2c_client *client)
|
|
{
|
|
struct rt5033_battery *battery = i2c_get_clientdata(client);
|
|
u32 msb;
|
|
|
|
regmap_read(battery->regmap, RT5033_FUEL_REG_SOC_H, &msb);
|
|
|
|
return msb;
|
|
}
|
|
|
|
static int rt5033_battery_get_present(struct i2c_client *client)
|
|
{
|
|
struct rt5033_battery *battery = i2c_get_clientdata(client);
|
|
u32 val;
|
|
|
|
regmap_read(battery->regmap, RT5033_FUEL_REG_CONFIG_L, &val);
|
|
|
|
return (val & RT5033_FUEL_BAT_PRESENT) ? true : false;
|
|
}
|
|
|
|
static int rt5033_battery_get_watt_prop(struct i2c_client *client,
|
|
enum power_supply_property psp)
|
|
{
|
|
struct rt5033_battery *battery = i2c_get_clientdata(client);
|
|
unsigned int regh, regl;
|
|
int ret;
|
|
u32 msb, lsb;
|
|
|
|
switch (psp) {
|
|
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
|
|
regh = RT5033_FUEL_REG_VBAT_H;
|
|
regl = RT5033_FUEL_REG_VBAT_L;
|
|
break;
|
|
case POWER_SUPPLY_PROP_VOLTAGE_AVG:
|
|
regh = RT5033_FUEL_REG_AVG_VOLT_H;
|
|
regl = RT5033_FUEL_REG_AVG_VOLT_L;
|
|
break;
|
|
case POWER_SUPPLY_PROP_VOLTAGE_OCV:
|
|
regh = RT5033_FUEL_REG_OCV_H;
|
|
regl = RT5033_FUEL_REG_OCV_L;
|
|
break;
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
|
|
regmap_read(battery->regmap, regh, &msb);
|
|
regmap_read(battery->regmap, regl, &lsb);
|
|
|
|
ret = ((msb << 4) + (lsb >> 4)) * 1250;
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int rt5033_battery_get_property(struct power_supply *psy,
|
|
enum power_supply_property psp,
|
|
union power_supply_propval *val)
|
|
{
|
|
struct rt5033_battery *battery = power_supply_get_drvdata(psy);
|
|
|
|
switch (psp) {
|
|
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
|
|
case POWER_SUPPLY_PROP_VOLTAGE_AVG:
|
|
case POWER_SUPPLY_PROP_VOLTAGE_OCV:
|
|
val->intval = rt5033_battery_get_watt_prop(battery->client,
|
|
psp);
|
|
break;
|
|
case POWER_SUPPLY_PROP_PRESENT:
|
|
val->intval = rt5033_battery_get_present(battery->client);
|
|
break;
|
|
case POWER_SUPPLY_PROP_CAPACITY:
|
|
val->intval = rt5033_battery_get_capacity(battery->client);
|
|
break;
|
|
case POWER_SUPPLY_PROP_STATUS:
|
|
val->intval = rt5033_battery_get_status(battery->client);
|
|
break;
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static enum power_supply_property rt5033_battery_props[] = {
|
|
POWER_SUPPLY_PROP_VOLTAGE_NOW,
|
|
POWER_SUPPLY_PROP_VOLTAGE_AVG,
|
|
POWER_SUPPLY_PROP_VOLTAGE_OCV,
|
|
POWER_SUPPLY_PROP_PRESENT,
|
|
POWER_SUPPLY_PROP_CAPACITY,
|
|
POWER_SUPPLY_PROP_STATUS,
|
|
};
|
|
|
|
static const struct regmap_config rt5033_battery_regmap_config = {
|
|
.reg_bits = 8,
|
|
.val_bits = 8,
|
|
.max_register = RT5033_FUEL_REG_END,
|
|
};
|
|
|
|
static const struct power_supply_desc rt5033_battery_desc = {
|
|
.name = "rt5033-battery",
|
|
.type = POWER_SUPPLY_TYPE_BATTERY,
|
|
.get_property = rt5033_battery_get_property,
|
|
.properties = rt5033_battery_props,
|
|
.num_properties = ARRAY_SIZE(rt5033_battery_props),
|
|
};
|
|
|
|
static int rt5033_battery_probe(struct i2c_client *client)
|
|
{
|
|
struct i2c_adapter *adapter = client->adapter;
|
|
struct power_supply_config psy_cfg = {};
|
|
struct rt5033_battery *battery;
|
|
|
|
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
|
|
return -EIO;
|
|
|
|
battery = devm_kzalloc(&client->dev, sizeof(*battery), GFP_KERNEL);
|
|
if (!battery)
|
|
return -ENOMEM;
|
|
|
|
battery->client = client;
|
|
battery->regmap = devm_regmap_init_i2c(client,
|
|
&rt5033_battery_regmap_config);
|
|
if (IS_ERR(battery->regmap)) {
|
|
dev_err(&client->dev, "Failed to initialize regmap\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
i2c_set_clientdata(client, battery);
|
|
psy_cfg.of_node = client->dev.of_node;
|
|
psy_cfg.drv_data = battery;
|
|
|
|
battery->psy = power_supply_register(&client->dev,
|
|
&rt5033_battery_desc, &psy_cfg);
|
|
if (IS_ERR(battery->psy))
|
|
return dev_err_probe(&client->dev, PTR_ERR(battery->psy),
|
|
"Failed to register power supply\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void rt5033_battery_remove(struct i2c_client *client)
|
|
{
|
|
struct rt5033_battery *battery = i2c_get_clientdata(client);
|
|
|
|
power_supply_unregister(battery->psy);
|
|
}
|
|
|
|
static const struct i2c_device_id rt5033_battery_id[] = {
|
|
{ "rt5033-battery", },
|
|
{ }
|
|
};
|
|
MODULE_DEVICE_TABLE(i2c, rt5033_battery_id);
|
|
|
|
static const struct of_device_id rt5033_battery_of_match[] = {
|
|
{ .compatible = "richtek,rt5033-battery", },
|
|
{ }
|
|
};
|
|
MODULE_DEVICE_TABLE(of, rt5033_battery_of_match);
|
|
|
|
static struct i2c_driver rt5033_battery_driver = {
|
|
.driver = {
|
|
.name = "rt5033-battery",
|
|
.of_match_table = rt5033_battery_of_match,
|
|
},
|
|
.probe = rt5033_battery_probe,
|
|
.remove = rt5033_battery_remove,
|
|
.id_table = rt5033_battery_id,
|
|
};
|
|
module_i2c_driver(rt5033_battery_driver);
|
|
|
|
MODULE_DESCRIPTION("Richtek RT5033 fuel gauge driver");
|
|
MODULE_AUTHOR("Beomho Seo <beomho.seo@samsung.com>");
|
|
MODULE_LICENSE("GPL");
|