Commit 288cb34e authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-v6.12' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply

Pull power supply and reset updates from Sebastian Reichel:
 "Power-supply core:
   - introduce power_supply_show_enum_with_available() helper
   - change usb_types from an array into a bitmask
   - fix early usage of power_supply_property_is_writeable() resulting
     in sysfs files not being writable
   - fix missing temp1_max_alarm attribute in power-supply's hwmon
     devices

  Drivers:
   - max1720x: expose nvmem device
   - brcmstb: cleanup driver to use latest APIs
   - max77693: expose input and charging current limit
   - max17042_battery: fix state of charge reading for devices without
     current sensing
   - axp20x_battery: add AXP717 support
   - axp20x_battery: fix min/max voltage properties
   - axp20x_usb_power: add AXP717 support
   - axp20x_usb_power: add DT based input current limit

  Documentation updates

  Misc minor cleanups and fixes"

* tag 'for-v6.12' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply: (38 commits)
  power: supply: hwmon: Fix missing temp1_max_alarm attribute
  power: supply: Drop use_cnt check from power_supply_property_is_writeable()
  power: supply: ab8500: Constify struct kobj_type
  power: supply: max1720x: fix a double free on error in probe()
  power: supply: axp20x_battery: add support for AXP717
  power: supply: axp20x_usb_power: Add support for AXP717
  dt-bindings: power: supply: axp20x: Add AXP717 compatible
  dt-bindings: power: supply: axp20x: Add AXP717 compatible
  power: supply: axp20x_usb_power: Fix spelling mistake "reqested" -> "requested"
  power: supply: Change usb_types from an array into a bitmask
  power: supply: sysfs: Move power_supply_show_enum_with_available() up
  power: supply: sysfs: Add power_supply_show_enum_with_available() helper
  power: supply: rt9467-charger: Remove "usb_type" property write support
  power: supply: ucs1002: Adjust ucs1002_set_usb_type() to accept string values
  power: supply: "usb_type" property may be written to
  power: supply: max1720x: add read support for nvmem
  mfd: axp20x: Add ADC, BAT, and USB cells for AXP717
  power: supply: core: constify psy_tzd_ops
  power: reset: brcmstb: Do not go into infinite loop if reset fails
  power: reset: brcmstb: Use devm_register_sys_off_handler()
  ...
parents bfbb9632 e50a57d1
......@@ -377,17 +377,33 @@ What: /sys/class/power_supply/<supply_name>/charge_type
Date: July 2009
Contact: linux-pm@vger.kernel.org
Description:
Represents the type of charging currently being applied to the
battery. "Trickle", "Fast", and "Standard" all mean different
charging speeds. "Adaptive" means that the charger uses some
algorithm to adjust the charge rate dynamically, without
any user configuration required. "Custom" means that the charger
uses the charge_control_* properties as configuration for some
different algorithm. "Long Life" means the charger reduces its
charging rate in order to prolong the battery health. "Bypass"
means the charger bypasses the charging path around the
integrated converter allowing for a "smart" wall adaptor to
perform the power conversion externally.
Select the charging algorithm to use for a battery.
Standard:
Fully charge the battery at a moderate rate.
Fast:
Quickly charge the battery using fast-charge
technology. This is typically harder on the battery
than standard charging and may lower its lifespan.
Trickle:
Users who primarily operate the system while
plugged into an external power source can extend
battery life with this mode. Vendor tooling may
call this "Primarily AC Use".
Adaptive:
Automatically optimize battery charge rate based
on typical usage pattern.
Custom:
Use the charge_control_* properties to determine
when to start and stop charging. Advanced users
can use this to drastically extend battery life.
Long Life:
The charger reduces its charging rate in order to
prolong the battery health.
Bypass:
The charger bypasses the charging path around the
integrated converter allowing for a "smart" wall
adaptor to perform the power conversion externally.
Access: Read, Write
......@@ -592,7 +608,12 @@ Description:
the supply, for example it can show if USB-PD capable source
is attached.
Access: Read-Only
Access: For power-supplies which consume USB power such
as battery charger chips, this indicates the type of
the connected USB power source and is Read-Only.
For power-supplies which act as a USB power-source such as
e.g. the UCS1002 USB Port Power Controller this is writable.
Valid values:
"Unknown", "SDP", "DCP", "CDP", "ACA", "C", "PD",
......
......@@ -27,6 +27,9 @@ properties:
battery-detect-gpios:
maxItems: 1
interrupts:
maxItems: 1
io-channels:
items:
- description: Battery Temperature ADC
......@@ -53,6 +56,7 @@ required:
- compatible
- reg
- battery-detect-gpios
- interrupts
- io-channels
- io-channel-names
- nvmem-cells
......@@ -88,6 +92,8 @@ examples:
compatible = "sprd,sc2731-fgu";
reg = <0xa00>;
battery-detect-gpios = <&pmic_eic 9 GPIO_ACTIVE_HIGH>;
interrupt-parent = <&sc2731_pmic>;
interrupts = <4>;
io-channels = <&pmic_adc 5>, <&pmic_adc 14>;
io-channel-names = "bat-temp", "charge-vol";
nvmem-cells = <&fgu_calib>;
......
......@@ -23,11 +23,18 @@ properties:
- const: x-powers,axp202-battery-power-supply
- const: x-powers,axp209-battery-power-supply
- const: x-powers,axp221-battery-power-supply
- const: x-powers,axp717-battery-power-supply
- items:
- const: x-powers,axp803-battery-power-supply
- const: x-powers,axp813-battery-power-supply
- const: x-powers,axp813-battery-power-supply
monitored-battery:
description:
Specifies the phandle of an optional simple-battery connected to
this gauge.
$ref: /schemas/types.yaml#/definitions/phandle
required:
- compatible
......
......@@ -15,9 +15,6 @@ maintainers:
- Chen-Yu Tsai <wens@csie.org>
- Sebastian Reichel <sre@kernel.org>
allOf:
- $ref: power-supply.yaml#
properties:
compatible:
oneOf:
......@@ -26,13 +23,82 @@ properties:
- x-powers,axp202-usb-power-supply
- x-powers,axp221-usb-power-supply
- x-powers,axp223-usb-power-supply
- x-powers,axp717-usb-power-supply
- x-powers,axp813-usb-power-supply
- items:
- const: x-powers,axp803-usb-power-supply
- const: x-powers,axp813-usb-power-supply
input-current-limit-microamp:
description:
Optional value to clamp the maximum input current limit to for
the device. If omitted, the programmed value from the EFUSE will
be used.
minimum: 100000
maximum: 4000000
required:
- compatible
allOf:
- $ref: power-supply.yaml#
- if:
properties:
compatible:
contains:
enum:
- x-powers,axp192-usb-power-supply
then:
properties:
input-current-limit-microamp:
enum: [100000, 500000]
- if:
properties:
compatible:
contains:
enum:
- x-powers,axp202-usb-power-supply
- x-powers,axp223-usb-power-supply
then:
properties:
input-current-limit-microamp:
enum: [100000, 500000, 900000]
- if:
properties:
compatible:
contains:
enum:
- x-powers,axp221-usb-power-supply
then:
properties:
input-current-limit-microamp:
enum: [500000, 900000]
- if:
properties:
compatible:
contains:
enum:
- x-powers,axp717-usb-power-supply
then:
properties:
input-current-limit-microamp:
description: Maximum input current in increments of 50000 uA.
minimum: 100000
maximum: 3250000
- if:
properties:
compatible:
contains:
enum:
- x-powers,axp813-usb-power-supply
then:
properties:
input-current-limit-microamp:
enum: [100000, 500000, 900000, 1500000, 2000000, 2500000,
3000000, 3500000, 4000000]
additionalProperties: false
......@@ -461,14 +461,6 @@ static int cht_wc_extcon_psy_get_prop(struct power_supply *psy,
return 0;
}
static const enum power_supply_usb_type cht_wc_extcon_psy_usb_types[] = {
POWER_SUPPLY_USB_TYPE_SDP,
POWER_SUPPLY_USB_TYPE_CDP,
POWER_SUPPLY_USB_TYPE_DCP,
POWER_SUPPLY_USB_TYPE_ACA,
POWER_SUPPLY_USB_TYPE_UNKNOWN,
};
static const enum power_supply_property cht_wc_extcon_psy_props[] = {
POWER_SUPPLY_PROP_USB_TYPE,
POWER_SUPPLY_PROP_ONLINE,
......@@ -477,8 +469,11 @@ static const enum power_supply_property cht_wc_extcon_psy_props[] = {
static const struct power_supply_desc cht_wc_extcon_psy_desc = {
.name = "cht_wcove_pwrsrc",
.type = POWER_SUPPLY_TYPE_USB,
.usb_types = cht_wc_extcon_psy_usb_types,
.num_usb_types = ARRAY_SIZE(cht_wc_extcon_psy_usb_types),
.usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |
BIT(POWER_SUPPLY_USB_TYPE_CDP) |
BIT(POWER_SUPPLY_USB_TYPE_DCP) |
BIT(POWER_SUPPLY_USB_TYPE_ACA) |
BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
.properties = cht_wc_extcon_psy_props,
.num_properties = ARRAY_SIZE(cht_wc_extcon_psy_props),
.get_property = cht_wc_extcon_psy_get_prop,
......
......@@ -209,15 +209,23 @@ static const struct regmap_access_table axp313a_volatile_table = {
};
static const struct regmap_range axp717_writeable_ranges[] = {
regmap_reg_range(AXP717_MODULE_EN_CONTROL_2, AXP717_MODULE_EN_CONTROL_2),
regmap_reg_range(AXP717_BOOST_CONTROL, AXP717_BOOST_CONTROL),
regmap_reg_range(AXP717_PMU_FAULT, AXP717_MODULE_EN_CONTROL_1),
regmap_reg_range(AXP717_MIN_SYS_V_CONTROL, AXP717_BOOST_CONTROL),
regmap_reg_range(AXP717_VSYS_V_POWEROFF, AXP717_VSYS_V_POWEROFF),
regmap_reg_range(AXP717_IRQ0_EN, AXP717_IRQ4_EN),
regmap_reg_range(AXP717_IRQ0_STATE, AXP717_IRQ4_STATE),
regmap_reg_range(AXP717_ICC_CHG_SET, AXP717_CV_CHG_SET),
regmap_reg_range(AXP717_DCDC_OUTPUT_CONTROL, AXP717_CPUSLDO_CONTROL),
regmap_reg_range(AXP717_ADC_CH_EN_CONTROL, AXP717_ADC_CH_EN_CONTROL),
regmap_reg_range(AXP717_ADC_DATA_SEL, AXP717_ADC_DATA_SEL),
};
static const struct regmap_range axp717_volatile_ranges[] = {
regmap_reg_range(AXP717_ON_INDICATE, AXP717_PMU_FAULT),
regmap_reg_range(AXP717_IRQ0_STATE, AXP717_IRQ4_STATE),
regmap_reg_range(AXP717_BATT_PERCENT_DATA, AXP717_BATT_PERCENT_DATA),
regmap_reg_range(AXP717_BATT_V_H, AXP717_BATT_CHRG_I_L),
regmap_reg_range(AXP717_ADC_DATA_H, AXP717_ADC_DATA_L),
};
static const struct regmap_access_table axp717_writeable_table = {
......@@ -310,6 +318,12 @@ static const struct resource axp22x_usb_power_supply_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"),
};
static const struct resource axp717_usb_power_supply_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP717_IRQ_VBUS_OVER_V, "VBUS_OVER_V"),
DEFINE_RES_IRQ_NAMED(AXP717_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN"),
DEFINE_RES_IRQ_NAMED(AXP717_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"),
};
/* AXP803 and AXP813/AXP818 share the same interrupts */
static const struct resource axp803_usb_power_supply_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP803_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN"),
......@@ -424,7 +438,7 @@ static const struct regmap_config axp717_regmap_config = {
.val_bits = 8,
.wr_table = &axp717_writeable_table,
.volatile_table = &axp717_volatile_table,
.max_register = AXP717_CPUSLDO_CONTROL,
.max_register = AXP717_ADC_DATA_L,
.cache_type = REGCACHE_MAPLE,
};
......@@ -1026,6 +1040,13 @@ static struct mfd_cell axp313a_cells[] = {
static struct mfd_cell axp717_cells[] = {
MFD_CELL_NAME("axp20x-regulator"),
MFD_CELL_RES("axp20x-pek", axp717_pek_resources),
MFD_CELL_OF("axp717-adc",
NULL, NULL, 0, 0, "x-powers,axp717-adc"),
MFD_CELL_OF("axp20x-usb-power-supply",
axp717_usb_power_supply_resources, NULL, 0, 0,
"x-powers,axp717-usb-power-supply"),
MFD_CELL_OF("axp20x-battery-power-supply",
NULL, NULL, 0, 0, "x-powers,axp717-battery-power-supply"),
};
static const struct resource axp288_adc_resources[] = {
......
......@@ -411,12 +411,6 @@ static int tusb1210_psy_get_prop(struct power_supply *psy,
return 0;
}
static const enum power_supply_usb_type tusb1210_psy_usb_types[] = {
POWER_SUPPLY_USB_TYPE_SDP,
POWER_SUPPLY_USB_TYPE_DCP,
POWER_SUPPLY_USB_TYPE_UNKNOWN,
};
static const enum power_supply_property tusb1210_psy_props[] = {
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_USB_TYPE,
......@@ -426,8 +420,9 @@ static const enum power_supply_property tusb1210_psy_props[] = {
static const struct power_supply_desc tusb1210_psy_desc = {
.name = "tusb1211-charger-detect",
.type = POWER_SUPPLY_TYPE_USB,
.usb_types = tusb1210_psy_usb_types,
.num_usb_types = ARRAY_SIZE(tusb1210_psy_usb_types),
.usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |
BIT(POWER_SUPPLY_USB_TYPE_DCP) |
BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
.properties = tusb1210_psy_props,
.num_properties = ARRAY_SIZE(tusb1210_psy_props),
.get_property = tusb1210_psy_get_prop,
......
......@@ -18,9 +18,6 @@
#include <linux/smp.h>
#include <linux/mfd/syscon.h>
#define RESET_SOURCE_ENABLE_REG 1
#define SW_MASTER_RESET_REG 2
static struct regmap *regmap;
static u32 rst_src_en;
static u32 sw_mstr_rst;
......@@ -32,8 +29,7 @@ struct reset_reg_mask {
static const struct reset_reg_mask *reset_masks;
static int brcmstb_restart_handler(struct notifier_block *this,
unsigned long mode, void *cmd)
static int brcmstb_restart_handler(struct sys_off_data *data)
{
int rc;
u32 tmp;
......@@ -62,17 +58,9 @@ static int brcmstb_restart_handler(struct notifier_block *this,
return NOTIFY_DONE;
}
while (1)
;
return NOTIFY_DONE;
}
static struct notifier_block brcmstb_restart_nb = {
.notifier_call = brcmstb_restart_handler,
.priority = 128,
};
static const struct reset_reg_mask reset_bits_40nm = {
.rst_src_en_mask = BIT(0),
.sw_mstr_rst_mask = BIT(0),
......@@ -83,46 +71,28 @@ static const struct reset_reg_mask reset_bits_65nm = {
.sw_mstr_rst_mask = BIT(31),
};
static const struct of_device_id of_match[] = {
{ .compatible = "brcm,brcmstb-reboot", .data = &reset_bits_40nm },
{ .compatible = "brcm,bcm7038-reboot", .data = &reset_bits_65nm },
{},
};
static int brcmstb_reboot_probe(struct platform_device *pdev)
{
int rc;
struct device_node *np = pdev->dev.of_node;
const struct of_device_id *of_id;
unsigned int args[2];
of_id = of_match_node(of_match, np);
if (!of_id) {
pr_err("failed to look up compatible string\n");
reset_masks = device_get_match_data(&pdev->dev);
if (!reset_masks) {
pr_err("failed to get match data\n");
return -EINVAL;
}
reset_masks = of_id->data;
regmap = syscon_regmap_lookup_by_phandle(np, "syscon");
regmap = syscon_regmap_lookup_by_phandle_args(np, "syscon", ARRAY_SIZE(args), args);
if (IS_ERR(regmap)) {
pr_err("failed to get syscon phandle\n");
return -EINVAL;
}
rst_src_en = args[0];
sw_mstr_rst = args[1];
rc = of_property_read_u32_index(np, "syscon", RESET_SOURCE_ENABLE_REG,
&rst_src_en);
if (rc) {
pr_err("can't get rst_src_en offset (%d)\n", rc);
return -EINVAL;
}
rc = of_property_read_u32_index(np, "syscon", SW_MASTER_RESET_REG,
&sw_mstr_rst);
if (rc) {
pr_err("can't get sw_mstr_rst offset (%d)\n", rc);
return -EINVAL;
}
rc = register_restart_handler(&brcmstb_restart_nb);
rc = devm_register_sys_off_handler(&pdev->dev, SYS_OFF_MODE_RESTART,
128, brcmstb_restart_handler, NULL);
if (rc)
dev_err(&pdev->dev,
"cannot register restart handler (err=%d)\n", rc);
......@@ -130,6 +100,12 @@ static int brcmstb_reboot_probe(struct platform_device *pdev)
return rc;
}
static const struct of_device_id of_match[] = {
{ .compatible = "brcm,brcmstb-reboot", .data = &reset_bits_40nm },
{ .compatible = "brcm,bcm7038-reboot", .data = &reset_bits_65nm },
{},
};
static struct platform_driver brcmstb_reboot_driver = {
.probe = brcmstb_reboot_probe,
.driver = {
......@@ -140,7 +116,6 @@ static struct platform_driver brcmstb_reboot_driver = {
static int __init brcmstb_reboot_init(void)
{
return platform_driver_probe(&brcmstb_reboot_driver,
brcmstb_reboot_probe);
return platform_driver_register(&brcmstb_reboot_driver);
}
subsys_initcall(brcmstb_reboot_init);
......@@ -18,7 +18,6 @@
struct pwr_mlxbf {
struct work_struct reboot_work;
struct work_struct shutdown_work;
const char *hid;
};
......@@ -27,22 +26,17 @@ static void pwr_mlxbf_reboot_work(struct work_struct *work)
acpi_bus_generate_netlink_event("button/reboot.*", "Reboot Button", 0x80, 1);
}
static void pwr_mlxbf_shutdown_work(struct work_struct *work)
{
acpi_bus_generate_netlink_event("button/power.*", "Power Button", 0x80, 1);
}
static irqreturn_t pwr_mlxbf_irq(int irq, void *ptr)
{
const char *rst_pwr_hid = "MLNXBF24";
const char *low_pwr_hid = "MLNXBF29";
const char *shutdown_hid = "MLNXBF29";
struct pwr_mlxbf *priv = ptr;
if (!strncmp(priv->hid, rst_pwr_hid, 8))
schedule_work(&priv->reboot_work);
if (!strncmp(priv->hid, low_pwr_hid, 8))
schedule_work(&priv->shutdown_work);
if (!strncmp(priv->hid, shutdown_hid, 8))
orderly_poweroff(true);
return IRQ_HANDLED;
}
......@@ -70,10 +64,6 @@ static int pwr_mlxbf_probe(struct platform_device *pdev)
if (irq < 0)
return dev_err_probe(dev, irq, "Error getting %s irq.\n", priv->hid);
err = devm_work_autocancel(dev, &priv->shutdown_work, pwr_mlxbf_shutdown_work);
if (err)
return err;
err = devm_work_autocancel(dev, &priv->reboot_work, pwr_mlxbf_reboot_work);
if (err)
return err;
......
......@@ -2531,7 +2531,7 @@ static struct attribute *ab8500_fg_attrs[] = {
};
ATTRIBUTE_GROUPS(ab8500_fg);
static struct kobj_type ab8500_fg_ktype = {
static const struct kobj_type ab8500_fg_ktype = {
.sysfs_ops = &ab8500_fg_sysfs_ops,
.default_groups = ab8500_fg_groups,
};
......
......@@ -17,6 +17,7 @@
* GNU General Public License for more details.
*/
#include <linux/bitfield.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
......@@ -32,9 +33,19 @@
#include <linux/mfd/axp20x.h>
#define AXP20X_PWR_STATUS_BAT_CHARGING BIT(2)
#define AXP717_PWR_STATUS_MASK GENMASK(6, 5)
#define AXP717_PWR_STATUS_BAT_STANDBY 0
#define AXP717_PWR_STATUS_BAT_CHRG 1
#define AXP717_PWR_STATUS_BAT_DISCHRG 2
#define AXP20X_PWR_OP_BATT_PRESENT BIT(5)
#define AXP20X_PWR_OP_BATT_ACTIVATED BIT(3)
#define AXP717_PWR_OP_BATT_PRESENT BIT(3)
#define AXP717_BATT_PMU_FAULT_MASK GENMASK(2, 0)
#define AXP717_BATT_UVLO_2_5V BIT(2)
#define AXP717_BATT_OVER_TEMP BIT(1)
#define AXP717_BATT_UNDER_TEMP BIT(0)
#define AXP209_FG_PERCENT GENMASK(6, 0)
#define AXP22X_FG_VALID BIT(7)
......@@ -49,20 +60,51 @@
#define AXP22X_CHRG_CTRL1_TGT_4_22V (1 << 5)
#define AXP22X_CHRG_CTRL1_TGT_4_24V (3 << 5)
#define AXP717_CHRG_ENABLE BIT(1)
#define AXP717_CHRG_CV_VOLT_MASK GENMASK(2, 0)
#define AXP717_CHRG_CV_4_0V 0
#define AXP717_CHRG_CV_4_1V 1
#define AXP717_CHRG_CV_4_2V 2
#define AXP717_CHRG_CV_4_35V 3
#define AXP717_CHRG_CV_4_4V 4
/* Values 5 and 6 reserved. */
#define AXP717_CHRG_CV_5_0V 7
#define AXP813_CHRG_CTRL1_TGT_4_35V (3 << 5)
#define AXP20X_CHRG_CTRL1_TGT_CURR GENMASK(3, 0)
#define AXP717_ICC_CHARGER_LIM_MASK GENMASK(5, 0)
#define AXP717_ITERM_CHG_LIM_MASK GENMASK(3, 0)
#define AXP717_ITERM_CC_STEP 64000
#define AXP20X_V_OFF_MASK GENMASK(2, 0)
#define AXP717_V_OFF_MASK GENMASK(6, 4)
#define AXP717_BAT_VMIN_MIN_UV 2600000
#define AXP717_BAT_VMIN_MAX_UV 3300000
#define AXP717_BAT_VMIN_STEP 100000
#define AXP717_BAT_CV_MIN_UV 4000000
#define AXP717_BAT_CV_MAX_UV 5000000
#define AXP717_BAT_CC_MIN_UA 0
#define AXP717_BAT_CC_MAX_UA 3008000
struct axp20x_batt_ps;
struct axp_data {
int ccc_scale;
int ccc_offset;
unsigned int ccc_reg;
unsigned int ccc_mask;
bool has_fg_valid;
const struct power_supply_desc *bat_ps_desc;
int (*get_max_voltage)(struct axp20x_batt_ps *batt, int *val);
int (*set_max_voltage)(struct axp20x_batt_ps *batt, int val);
int (*cfg_iio_chan)(struct platform_device *pdev,
struct axp20x_batt_ps *axp_batt);
void (*set_bat_info)(struct platform_device *pdev,
struct axp20x_batt_ps *axp_batt,
struct power_supply_battery_info *info);
};
struct axp20x_batt_ps {
......@@ -135,6 +177,39 @@ static int axp22x_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt,
return 0;
}
static int axp717_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt,
int *val)
{
int ret, reg;
ret = regmap_read(axp20x_batt->regmap, AXP717_CV_CHG_SET, &reg);
if (ret)
return ret;
switch (reg & AXP717_CHRG_CV_VOLT_MASK) {
case AXP717_CHRG_CV_4_0V:
*val = 4000000;
return 0;
case AXP717_CHRG_CV_4_1V:
*val = 4100000;
return 0;
case AXP717_CHRG_CV_4_2V:
*val = 4200000;
return 0;
case AXP717_CHRG_CV_4_35V:
*val = 4350000;
return 0;
case AXP717_CHRG_CV_4_4V:
*val = 4400000;
return 0;
case AXP717_CHRG_CV_5_0V:
*val = 5000000;
return 0;
default:
return -EINVAL;
}
}
static int axp813_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt,
int *val)
{
......@@ -180,6 +255,21 @@ static int axp20x_get_constant_charge_current(struct axp20x_batt_ps *axp,
return 0;
}
static int axp717_get_constant_charge_current(struct axp20x_batt_ps *axp,
int *val)
{
int ret;
ret = regmap_read(axp->regmap, AXP717_ICC_CHG_SET, val);
if (ret)
return ret;
*val = FIELD_GET(AXP717_ICC_CHARGER_LIM_MASK, *val) *
axp->data->ccc_scale;
return 0;
}
static int axp20x_battery_get_prop(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
......@@ -303,11 +393,11 @@ static int axp20x_battery_get_prop(struct power_supply *psy,
val->intval = reg & AXP209_FG_PERCENT;
break;
case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
case POWER_SUPPLY_PROP_VOLTAGE_MAX:
return axp20x_batt->data->get_max_voltage(axp20x_batt,
&val->intval);
case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
case POWER_SUPPLY_PROP_VOLTAGE_MIN:
ret = regmap_read(axp20x_batt->regmap, AXP20X_V_OFF, &reg);
if (ret)
return ret;
......@@ -332,6 +422,171 @@ static int axp20x_battery_get_prop(struct power_supply *psy,
return 0;
}
static int axp717_battery_get_prop(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
{
struct axp20x_batt_ps *axp20x_batt = power_supply_get_drvdata(psy);
int ret = 0, reg;
switch (psp) {
case POWER_SUPPLY_PROP_PRESENT:
case POWER_SUPPLY_PROP_ONLINE:
ret = regmap_read(axp20x_batt->regmap, AXP717_ON_INDICATE,
&reg);
if (ret)
return ret;
val->intval = FIELD_GET(AXP717_PWR_OP_BATT_PRESENT, reg);
return 0;
case POWER_SUPPLY_PROP_STATUS:
ret = regmap_read(axp20x_batt->regmap, AXP717_PMU_STATUS_2,
&reg);
if (ret)
return ret;
switch (FIELD_GET(AXP717_PWR_STATUS_MASK, reg)) {
case AXP717_PWR_STATUS_BAT_STANDBY:
val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
return 0;
case AXP717_PWR_STATUS_BAT_CHRG:
val->intval = POWER_SUPPLY_STATUS_CHARGING;
return 0;
case AXP717_PWR_STATUS_BAT_DISCHRG:
val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
return 0;
default:
val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
return 0;
}
/*
* If a fault is detected it must also be cleared; if the
* condition persists it should reappear (This is an
* assumption, it's actually not documented). A restart was
* not sufficient to clear the bit in testing despite the
* register listed as POR.
*/
case POWER_SUPPLY_PROP_HEALTH:
ret = regmap_read(axp20x_batt->regmap, AXP717_PMU_FAULT,
&reg);
if (ret)
return ret;
switch (reg & AXP717_BATT_PMU_FAULT_MASK) {
case AXP717_BATT_UVLO_2_5V:
val->intval = POWER_SUPPLY_HEALTH_DEAD;
regmap_update_bits(axp20x_batt->regmap,
AXP717_PMU_FAULT,
AXP717_BATT_UVLO_2_5V,
AXP717_BATT_UVLO_2_5V);
return 0;
case AXP717_BATT_OVER_TEMP:
val->intval = POWER_SUPPLY_HEALTH_HOT;
regmap_update_bits(axp20x_batt->regmap,
AXP717_PMU_FAULT,
AXP717_BATT_OVER_TEMP,
AXP717_BATT_OVER_TEMP);
return 0;
case AXP717_BATT_UNDER_TEMP:
val->intval = POWER_SUPPLY_HEALTH_COLD;
regmap_update_bits(axp20x_batt->regmap,
AXP717_PMU_FAULT,
AXP717_BATT_UNDER_TEMP,
AXP717_BATT_UNDER_TEMP);
return 0;
default:
val->intval = POWER_SUPPLY_HEALTH_GOOD;
return 0;
}
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
ret = axp717_get_constant_charge_current(axp20x_batt,
&val->intval);
if (ret)
return ret;
return 0;
case POWER_SUPPLY_PROP_CURRENT_NOW:
/*
* The offset of this value is currently unknown and is
* not documented in the datasheet. Based on
* observation it's assumed to be somewhere around
* 450ma. I will leave the value raw for now.
*/
ret = iio_read_channel_processed(axp20x_batt->batt_chrg_i, &val->intval);
if (ret)
return ret;
/* IIO framework gives mA but Power Supply framework gives uA */
val->intval *= 1000;
return 0;
case POWER_SUPPLY_PROP_CAPACITY:
ret = regmap_read(axp20x_batt->regmap, AXP717_ON_INDICATE,
&reg);
if (ret)
return ret;
if (!FIELD_GET(AXP717_PWR_OP_BATT_PRESENT, reg))
return -ENODEV;
ret = regmap_read(axp20x_batt->regmap,
AXP717_BATT_PERCENT_DATA, &reg);
if (ret)
return ret;
/*
* Fuel Gauge data takes 7 bits but the stored value seems to be
* directly the raw percentage without any scaling to 7 bits.
*/
val->intval = reg & AXP209_FG_PERCENT;
return 0;
case POWER_SUPPLY_PROP_VOLTAGE_MAX:
return axp20x_batt->data->get_max_voltage(axp20x_batt,
&val->intval);
case POWER_SUPPLY_PROP_VOLTAGE_MIN:
ret = regmap_read(axp20x_batt->regmap,
AXP717_VSYS_V_POWEROFF, &reg);
if (ret)
return ret;
val->intval = AXP717_BAT_VMIN_MIN_UV + AXP717_BAT_VMIN_STEP *
(reg & AXP717_V_OFF_MASK);
return 0;
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
ret = iio_read_channel_processed(axp20x_batt->batt_v,
&val->intval);
if (ret)
return ret;
/* IIO framework gives mV but Power Supply framework gives uV */
val->intval *= 1000;
return 0;
case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
ret = regmap_read(axp20x_batt->regmap,
AXP717_ITERM_CHG_SET, &reg);
if (ret)
return ret;
val->intval = (reg & AXP717_ITERM_CHG_LIM_MASK) * AXP717_ITERM_CC_STEP;
return 0;
default:
return -EINVAL;
}
}
static int axp22x_battery_set_max_voltage(struct axp20x_batt_ps *axp20x_batt,
int val)
{
......@@ -388,6 +643,35 @@ static int axp20x_battery_set_max_voltage(struct axp20x_batt_ps *axp20x_batt,
AXP20X_CHRG_CTRL1_TGT_VOLT, val);
}
static int axp717_battery_set_max_voltage(struct axp20x_batt_ps *axp20x_batt,
int val)
{
switch (val) {
case 4000000:
val = AXP717_CHRG_CV_4_0V;
break;
case 4100000:
val = AXP717_CHRG_CV_4_1V;
break;
case 4200000:
val = AXP717_CHRG_CV_4_2V;
break;
default:
/*
* AXP717 can go up to 4.35, 4.4, and 5.0 volts which
* seem too high for lithium batteries, so do not allow.
*/
return -EINVAL;
}
return regmap_update_bits(axp20x_batt->regmap,
AXP717_CV_CHG_SET,
AXP717_CHRG_CV_VOLT_MASK, val);
}
static int axp20x_set_constant_charge_current(struct axp20x_batt_ps *axp_batt,
int charge_current)
{
......@@ -404,6 +688,24 @@ static int axp20x_set_constant_charge_current(struct axp20x_batt_ps *axp_batt,
AXP20X_CHRG_CTRL1_TGT_CURR, charge_current);
}
static int axp717_set_constant_charge_current(struct axp20x_batt_ps *axp,
int charge_current)
{
int val;
if (charge_current > axp->max_ccc)
return -EINVAL;
if (charge_current > AXP717_BAT_CC_MAX_UA || charge_current < 0)
return -EINVAL;
val = (charge_current - axp->data->ccc_offset) /
axp->data->ccc_scale;
return regmap_update_bits(axp->regmap, AXP717_ICC_CHG_SET,
AXP717_ICC_CHARGER_LIM_MASK, val);
}
static int axp20x_set_max_constant_charge_current(struct axp20x_batt_ps *axp,
int charge_current)
{
......@@ -448,6 +750,19 @@ static int axp20x_set_voltage_min_design(struct axp20x_batt_ps *axp_batt,
AXP20X_V_OFF_MASK, val1);
}
static int axp717_set_voltage_min_design(struct axp20x_batt_ps *axp_batt,
int min_voltage)
{
int val1 = (min_voltage - AXP717_BAT_VMIN_MIN_UV) / AXP717_BAT_VMIN_STEP;
if (val1 < 0 || val1 > AXP717_V_OFF_MASK)
return -EINVAL;
return regmap_update_bits(axp_batt->regmap,
AXP717_VSYS_V_POWEROFF,
AXP717_V_OFF_MASK, val1);
}
static int axp20x_battery_set_prop(struct power_supply *psy,
enum power_supply_property psp,
const union power_supply_propval *val)
......@@ -455,10 +770,10 @@ static int axp20x_battery_set_prop(struct power_supply *psy,
struct axp20x_batt_ps *axp20x_batt = power_supply_get_drvdata(psy);
switch (psp) {
case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
case POWER_SUPPLY_PROP_VOLTAGE_MIN:
return axp20x_set_voltage_min_design(axp20x_batt, val->intval);
case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
case POWER_SUPPLY_PROP_VOLTAGE_MAX:
return axp20x_batt->data->set_max_voltage(axp20x_batt, val->intval);
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
......@@ -484,6 +799,42 @@ static int axp20x_battery_set_prop(struct power_supply *psy,
}
}
static int axp717_battery_set_prop(struct power_supply *psy,
enum power_supply_property psp,
const union power_supply_propval *val)
{
struct axp20x_batt_ps *axp20x_batt = power_supply_get_drvdata(psy);
switch (psp) {
case POWER_SUPPLY_PROP_VOLTAGE_MIN:
return axp717_set_voltage_min_design(axp20x_batt, val->intval);
case POWER_SUPPLY_PROP_VOLTAGE_MAX:
return axp20x_batt->data->set_max_voltage(axp20x_batt, val->intval);
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
return axp717_set_constant_charge_current(axp20x_batt,
val->intval);
case POWER_SUPPLY_PROP_STATUS:
switch (val->intval) {
case POWER_SUPPLY_STATUS_CHARGING:
return regmap_update_bits(axp20x_batt->regmap,
AXP717_MODULE_EN_CONTROL_2,
AXP717_CHRG_ENABLE,
AXP717_CHRG_ENABLE);
case POWER_SUPPLY_STATUS_DISCHARGING:
case POWER_SUPPLY_STATUS_NOT_CHARGING:
return regmap_update_bits(axp20x_batt->regmap,
AXP717_MODULE_EN_CONTROL_2,
AXP717_CHRG_ENABLE, 0);
}
return -EINVAL;
default:
return -EINVAL;
}
}
static enum power_supply_property axp20x_battery_props[] = {
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_ONLINE,
......@@ -493,22 +844,45 @@ static enum power_supply_property axp20x_battery_props[] = {
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
POWER_SUPPLY_PROP_HEALTH,
POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
POWER_SUPPLY_PROP_VOLTAGE_MAX,
POWER_SUPPLY_PROP_VOLTAGE_MIN,
POWER_SUPPLY_PROP_CAPACITY,
};
static enum power_supply_property axp717_battery_props[] = {
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_CURRENT_NOW,
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
POWER_SUPPLY_PROP_HEALTH,
POWER_SUPPLY_PROP_VOLTAGE_MAX,
POWER_SUPPLY_PROP_VOLTAGE_MIN,
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT,
};
static int axp20x_battery_prop_writeable(struct power_supply *psy,
enum power_supply_property psp)
{
return psp == POWER_SUPPLY_PROP_STATUS ||
psp == POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN ||
psp == POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN ||
psp == POWER_SUPPLY_PROP_VOLTAGE_MIN ||
psp == POWER_SUPPLY_PROP_VOLTAGE_MAX ||
psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT ||
psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX;
}
static const struct power_supply_desc axp20x_batt_ps_desc = {
static int axp717_battery_prop_writeable(struct power_supply *psy,
enum power_supply_property psp)
{
return psp == POWER_SUPPLY_PROP_STATUS ||
psp == POWER_SUPPLY_PROP_VOLTAGE_MIN ||
psp == POWER_SUPPLY_PROP_VOLTAGE_MAX ||
psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX;
}
static const struct power_supply_desc axp209_batt_ps_desc = {
.name = "axp20x-battery",
.type = POWER_SUPPLY_TYPE_BATTERY,
.properties = axp20x_battery_props,
......@@ -518,27 +892,163 @@ static const struct power_supply_desc axp20x_batt_ps_desc = {
.set_property = axp20x_battery_set_prop,
};
static const struct power_supply_desc axp717_batt_ps_desc = {
.name = "axp20x-battery",
.type = POWER_SUPPLY_TYPE_BATTERY,
.properties = axp717_battery_props,
.num_properties = ARRAY_SIZE(axp717_battery_props),
.property_is_writeable = axp717_battery_prop_writeable,
.get_property = axp717_battery_get_prop,
.set_property = axp717_battery_set_prop,
};
static int axp209_bat_cfg_iio_channels(struct platform_device *pdev,
struct axp20x_batt_ps *axp_batt)
{
axp_batt->batt_v = devm_iio_channel_get(&pdev->dev, "batt_v");
if (IS_ERR(axp_batt->batt_v)) {
if (PTR_ERR(axp_batt->batt_v) == -ENODEV)
return -EPROBE_DEFER;
return PTR_ERR(axp_batt->batt_v);
}
axp_batt->batt_chrg_i = devm_iio_channel_get(&pdev->dev,
"batt_chrg_i");
if (IS_ERR(axp_batt->batt_chrg_i)) {
if (PTR_ERR(axp_batt->batt_chrg_i) == -ENODEV)
return -EPROBE_DEFER;
return PTR_ERR(axp_batt->batt_chrg_i);
}
axp_batt->batt_dischrg_i = devm_iio_channel_get(&pdev->dev,
"batt_dischrg_i");
if (IS_ERR(axp_batt->batt_dischrg_i)) {
if (PTR_ERR(axp_batt->batt_dischrg_i) == -ENODEV)
return -EPROBE_DEFER;
return PTR_ERR(axp_batt->batt_dischrg_i);
}
return 0;
}
static int axp717_bat_cfg_iio_channels(struct platform_device *pdev,
struct axp20x_batt_ps *axp_batt)
{
axp_batt->batt_v = devm_iio_channel_get(&pdev->dev, "batt_v");
if (IS_ERR(axp_batt->batt_v)) {
if (PTR_ERR(axp_batt->batt_v) == -ENODEV)
return -EPROBE_DEFER;
return PTR_ERR(axp_batt->batt_v);
}
axp_batt->batt_chrg_i = devm_iio_channel_get(&pdev->dev,
"batt_chrg_i");
if (IS_ERR(axp_batt->batt_chrg_i)) {
if (PTR_ERR(axp_batt->batt_chrg_i) == -ENODEV)
return -EPROBE_DEFER;
return PTR_ERR(axp_batt->batt_chrg_i);
}
return 0;
}
static void axp209_set_battery_info(struct platform_device *pdev,
struct axp20x_batt_ps *axp_batt,
struct power_supply_battery_info *info)
{
int vmin = info->voltage_min_design_uv;
int ccc = info->constant_charge_current_max_ua;
if (vmin > 0 && axp20x_set_voltage_min_design(axp_batt, vmin))
dev_err(&pdev->dev,
"couldn't set voltage_min_design\n");
/* Set max to unverified value to be able to set CCC */
axp_batt->max_ccc = ccc;
if (ccc <= 0 || axp20x_set_constant_charge_current(axp_batt, ccc)) {
dev_err(&pdev->dev,
"couldn't set ccc from DT: fallback to min value\n");
ccc = 300000;
axp_batt->max_ccc = ccc;
axp20x_set_constant_charge_current(axp_batt, ccc);
}
}
static void axp717_set_battery_info(struct platform_device *pdev,
struct axp20x_batt_ps *axp_batt,
struct power_supply_battery_info *info)
{
int vmin = info->voltage_min_design_uv;
int vmax = info->voltage_max_design_uv;
int ccc = info->constant_charge_current_max_ua;
int val;
if (vmin > 0 && axp717_set_voltage_min_design(axp_batt, vmin))
dev_err(&pdev->dev,
"couldn't set voltage_min_design\n");
if (vmax > 0 && axp717_battery_set_max_voltage(axp_batt, vmax))
dev_err(&pdev->dev,
"couldn't set voltage_max_design\n");
axp717_get_constant_charge_current(axp_batt, &val);
axp_batt->max_ccc = ccc;
if (ccc <= 0 || axp717_set_constant_charge_current(axp_batt, ccc)) {
dev_err(&pdev->dev,
"couldn't set ccc from DT: current ccc is %d\n",
val);
}
}
static const struct axp_data axp209_data = {
.ccc_scale = 100000,
.ccc_offset = 300000,
.ccc_reg = AXP20X_CHRG_CTRL1,
.ccc_mask = AXP20X_CHRG_CTRL1_TGT_CURR,
.bat_ps_desc = &axp209_batt_ps_desc,
.get_max_voltage = axp20x_battery_get_max_voltage,
.set_max_voltage = axp20x_battery_set_max_voltage,
.cfg_iio_chan = axp209_bat_cfg_iio_channels,
.set_bat_info = axp209_set_battery_info,
};
static const struct axp_data axp221_data = {
.ccc_scale = 150000,
.ccc_offset = 300000,
.ccc_reg = AXP20X_CHRG_CTRL1,
.ccc_mask = AXP20X_CHRG_CTRL1_TGT_CURR,
.has_fg_valid = true,
.bat_ps_desc = &axp209_batt_ps_desc,
.get_max_voltage = axp22x_battery_get_max_voltage,
.set_max_voltage = axp22x_battery_set_max_voltage,
.cfg_iio_chan = axp209_bat_cfg_iio_channels,
.set_bat_info = axp209_set_battery_info,
};
static const struct axp_data axp717_data = {
.ccc_scale = 64000,
.ccc_offset = 0,
.ccc_reg = AXP717_ICC_CHG_SET,
.ccc_mask = AXP717_ICC_CHARGER_LIM_MASK,
.bat_ps_desc = &axp717_batt_ps_desc,
.get_max_voltage = axp717_battery_get_max_voltage,
.set_max_voltage = axp717_battery_set_max_voltage,
.cfg_iio_chan = axp717_bat_cfg_iio_channels,
.set_bat_info = axp717_set_battery_info,
};
static const struct axp_data axp813_data = {
.ccc_scale = 200000,
.ccc_offset = 200000,
.ccc_reg = AXP20X_CHRG_CTRL1,
.ccc_mask = AXP20X_CHRG_CTRL1_TGT_CURR,
.has_fg_valid = true,
.bat_ps_desc = &axp209_batt_ps_desc,
.get_max_voltage = axp813_battery_get_max_voltage,
.set_max_voltage = axp20x_battery_set_max_voltage,
.cfg_iio_chan = axp209_bat_cfg_iio_channels,
.set_bat_info = axp209_set_battery_info,
};
static const struct of_device_id axp20x_battery_ps_id[] = {
......@@ -548,6 +1058,9 @@ static const struct of_device_id axp20x_battery_ps_id[] = {
}, {
.compatible = "x-powers,axp221-battery-power-supply",
.data = (void *)&axp221_data,
}, {
.compatible = "x-powers,axp717-battery-power-supply",
.data = (void *)&axp717_data,
}, {
.compatible = "x-powers,axp813-battery-power-supply",
.data = (void *)&axp813_data,
......@@ -561,6 +1074,7 @@ static int axp20x_power_probe(struct platform_device *pdev)
struct power_supply_config psy_cfg = {};
struct power_supply_battery_info *info;
struct device *dev = &pdev->dev;
int ret;
if (!of_device_is_available(pdev->dev.of_node))
return -ENODEV;
......@@ -572,29 +1086,6 @@ static int axp20x_power_probe(struct platform_device *pdev)
axp20x_batt->dev = &pdev->dev;
axp20x_batt->batt_v = devm_iio_channel_get(&pdev->dev, "batt_v");
if (IS_ERR(axp20x_batt->batt_v)) {
if (PTR_ERR(axp20x_batt->batt_v) == -ENODEV)
return -EPROBE_DEFER;
return PTR_ERR(axp20x_batt->batt_v);
}
axp20x_batt->batt_chrg_i = devm_iio_channel_get(&pdev->dev,
"batt_chrg_i");
if (IS_ERR(axp20x_batt->batt_chrg_i)) {
if (PTR_ERR(axp20x_batt->batt_chrg_i) == -ENODEV)
return -EPROBE_DEFER;
return PTR_ERR(axp20x_batt->batt_chrg_i);
}
axp20x_batt->batt_dischrg_i = devm_iio_channel_get(&pdev->dev,
"batt_dischrg_i");
if (IS_ERR(axp20x_batt->batt_dischrg_i)) {
if (PTR_ERR(axp20x_batt->batt_dischrg_i) == -ENODEV)
return -EPROBE_DEFER;
return PTR_ERR(axp20x_batt->batt_dischrg_i);
}
axp20x_batt->regmap = dev_get_regmap(pdev->dev.parent, NULL);
platform_set_drvdata(pdev, axp20x_batt);
......@@ -603,8 +1094,12 @@ static int axp20x_power_probe(struct platform_device *pdev)
axp20x_batt->data = (struct axp_data *)of_device_get_match_data(dev);
ret = axp20x_batt->data->cfg_iio_chan(pdev, axp20x_batt);
if (ret)
return ret;
axp20x_batt->batt = devm_power_supply_register(&pdev->dev,
&axp20x_batt_ps_desc,
axp20x_batt->data->bat_ps_desc,
&psy_cfg);
if (IS_ERR(axp20x_batt->batt)) {
dev_err(&pdev->dev, "failed to register power supply: %ld\n",
......@@ -613,33 +1108,15 @@ static int axp20x_power_probe(struct platform_device *pdev)
}
if (!power_supply_get_battery_info(axp20x_batt->batt, &info)) {
int vmin = info->voltage_min_design_uv;
int ccc = info->constant_charge_current_max_ua;
if (vmin > 0 && axp20x_set_voltage_min_design(axp20x_batt,
vmin))
dev_err(&pdev->dev,
"couldn't set voltage_min_design\n");
/* Set max to unverified value to be able to set CCC */
axp20x_batt->max_ccc = ccc;
if (ccc <= 0 || axp20x_set_constant_charge_current(axp20x_batt,
ccc)) {
dev_err(&pdev->dev,
"couldn't set constant charge current from DT: fallback to minimum value\n");
ccc = 300000;
axp20x_batt->max_ccc = ccc;
axp20x_set_constant_charge_current(axp20x_batt, ccc);
}
axp20x_batt->data->set_bat_info(pdev, axp20x_batt, info);
power_supply_put_battery_info(axp20x_batt->batt, info);
}
/*
* Update max CCC to a valid value if battery info is present or set it
* to current register value by default.
*/
axp20x_get_constant_charge_current(axp20x_batt,
&axp20x_batt->max_ccc);
axp20x_get_constant_charge_current(axp20x_batt, &axp20x_batt->max_ccc);
return 0;
}
......
......@@ -30,8 +30,13 @@
#define AXP20X_PWR_STATUS_VBUS_PRESENT BIT(5)
#define AXP20X_PWR_STATUS_VBUS_USED BIT(4)
#define AXP717_PWR_STATUS_VBUS_GOOD BIT(5)
#define AXP20X_USB_STATUS_VBUS_VALID BIT(2)
#define AXP717_PMU_FAULT_VBUS BIT(5)
#define AXP717_PMU_FAULT_VSYS BIT(3)
#define AXP20X_VBUS_VHOLD_uV(b) (4000000 + (((b) >> 3) & 7) * 100000)
#define AXP20X_VBUS_VHOLD_MASK GENMASK(5, 3)
#define AXP20X_VBUS_VHOLD_OFFSET 3
......@@ -39,12 +44,20 @@
#define AXP20X_ADC_EN1_VBUS_CURR BIT(2)
#define AXP20X_ADC_EN1_VBUS_VOLT BIT(3)
#define AXP717_INPUT_VOL_LIMIT_MASK GENMASK(3, 0)
#define AXP717_INPUT_CUR_LIMIT_MASK GENMASK(5, 0)
#define AXP717_ADC_DATA_MASK GENMASK(14, 0)
#define AXP717_ADC_EN_VBUS_VOLT BIT(2)
/*
* Note do not raise the debounce time, we must report Vusb high within
* 100ms otherwise we get Vbus errors in musb.
*/
#define DEBOUNCE_TIME msecs_to_jiffies(50)
struct axp20x_usb_power;
struct axp_data {
const struct power_supply_desc *power_desc;
const char * const *irq_names;
......@@ -58,6 +71,10 @@ struct axp_data {
struct reg_field usb_bc_det_fld;
struct reg_field vbus_disable_bit;
bool vbus_needs_polling: 1;
void (*axp20x_read_vbus)(struct work_struct *work);
int (*axp20x_cfg_iio_chan)(struct platform_device *pdev,
struct axp20x_usb_power *power);
int (*axp20x_cfg_adc_reg)(struct axp20x_usb_power *power);
};
struct axp20x_usb_power {
......@@ -74,6 +91,7 @@ struct axp20x_usb_power {
struct iio_channel *vbus_v;
struct iio_channel *vbus_i;
struct delayed_work vbus_detect;
int max_input_cur;
unsigned int old_status;
unsigned int online;
unsigned int num_irqs;
......@@ -136,6 +154,24 @@ static void axp20x_usb_power_poll_vbus(struct work_struct *work)
mod_delayed_work(system_power_efficient_wq, &power->vbus_detect, DEBOUNCE_TIME);
}
static void axp717_usb_power_poll_vbus(struct work_struct *work)
{
struct axp20x_usb_power *power =
container_of(work, struct axp20x_usb_power, vbus_detect.work);
unsigned int val;
int ret;
ret = regmap_read(power->regmap, AXP717_ON_INDICATE, &val);
if (ret)
return;
val &= AXP717_PWR_STATUS_VBUS_GOOD;
if (val != power->old_status)
power_supply_changed(power->supply);
power->old_status = val;
}
static int axp20x_get_usb_type(struct axp20x_usb_power *power,
union power_supply_propval *val)
{
......@@ -281,6 +317,91 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
return 0;
}
static int axp717_usb_power_get_property(struct power_supply *psy,
enum power_supply_property psp, union power_supply_propval *val)
{
struct axp20x_usb_power *power = power_supply_get_drvdata(psy);
unsigned int v;
int ret;
switch (psp) {
case POWER_SUPPLY_PROP_HEALTH:
val->intval = POWER_SUPPLY_HEALTH_GOOD;
ret = regmap_read(power->regmap, AXP717_ON_INDICATE, &v);
if (ret)
return ret;
if (!(v & AXP717_PWR_STATUS_VBUS_GOOD))
val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;
ret = regmap_read(power->regmap, AXP717_PMU_FAULT_VBUS, &v);
if (ret)
return ret;
v &= (AXP717_PMU_FAULT_VBUS | AXP717_PMU_FAULT_VSYS);
if (v) {
val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
regmap_write(power->regmap, AXP717_PMU_FAULT_VBUS, v);
}
break;
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
ret = regmap_read(power->regmap, AXP717_INPUT_CUR_LIMIT_CTRL, &v);
if (ret)
return ret;
/* 50ma step size with 100ma offset. */
v &= AXP717_INPUT_CUR_LIMIT_MASK;
val->intval = (v * 50000) + 100000;
break;
case POWER_SUPPLY_PROP_ONLINE:
case POWER_SUPPLY_PROP_PRESENT:
ret = regmap_read(power->regmap, AXP717_ON_INDICATE, &v);
if (ret)
return ret;
val->intval = !!(v & AXP717_PWR_STATUS_VBUS_GOOD);
break;
case POWER_SUPPLY_PROP_USB_TYPE:
return axp20x_get_usb_type(power, val);
case POWER_SUPPLY_PROP_VOLTAGE_MIN:
ret = regmap_read(power->regmap, AXP717_INPUT_VOL_LIMIT_CTRL, &v);
if (ret)
return ret;
/* 80mv step size with 3.88v offset. */
v &= AXP717_INPUT_VOL_LIMIT_MASK;
val->intval = (v * 80000) + 3880000;
break;
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
if (IS_ENABLED(CONFIG_AXP20X_ADC)) {
ret = iio_read_channel_processed(power->vbus_v,
&val->intval);
if (ret)
return ret;
/*
* IIO framework gives mV but Power Supply framework
* gives uV.
*/
val->intval *= 1000;
return 0;
}
ret = axp20x_read_variable_width(power->regmap,
AXP717_VBUS_V_H, 16);
if (ret < 0)
return ret;
val->intval = (ret % AXP717_ADC_DATA_MASK) * 1000;
break;
default:
return -EINVAL;
}
return 0;
}
static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,
int intval)
{
......@@ -307,6 +428,22 @@ static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,
return -EINVAL;
}
static int axp717_usb_power_set_voltage_min(struct axp20x_usb_power *power,
int intval)
{
int val;
/* Minimum value of 3.88v and maximum of 5.08v. */
if (intval < 3880000 || intval > 5080000)
return -EINVAL;
/* step size of 80ma with 3.88v offset. */
val = (intval - 3880000) / 80000;
return regmap_update_bits(power->regmap,
AXP717_INPUT_VOL_LIMIT_CTRL,
AXP717_INPUT_VOL_LIMIT_MASK, val);
}
static int axp20x_usb_power_set_input_current_limit(struct axp20x_usb_power *power,
int intval)
{
......@@ -317,6 +454,13 @@ static int axp20x_usb_power_set_input_current_limit(struct axp20x_usb_power *pow
if (intval == -1)
return -EINVAL;
if (power->max_input_cur && (intval > power->max_input_cur)) {
dev_warn(power->dev,
"requested current %d clamped to max current %d\n",
intval, power->max_input_cur);
intval = power->max_input_cur;
}
/*
* BC1.2 detection can cause a race condition if we try to set a current
* limit while it's in progress. When it finishes it will overwrite the
......@@ -340,6 +484,29 @@ static int axp20x_usb_power_set_input_current_limit(struct axp20x_usb_power *pow
return regmap_field_write(power->curr_lim_fld, reg);
}
static int axp717_usb_power_set_input_current_limit(struct axp20x_usb_power *power,
int intval)
{
int tmp;
/* Minimum value of 100mA and maximum value of 3.25A*/
if (intval < 100000 || intval > 3250000)
return -EINVAL;
if (power->max_input_cur && (intval > power->max_input_cur)) {
dev_warn(power->dev,
"reqested current %d clamped to max current %d\n",
intval, power->max_input_cur);
intval = power->max_input_cur;
}
/* Minimum value of 100mA with step size of 50mA. */
tmp = (intval - 100000) / 50000;
return regmap_update_bits(power->regmap,
AXP717_INPUT_CUR_LIMIT_CTRL,
AXP717_INPUT_CUR_LIMIT_MASK, tmp);
}
static int axp20x_usb_power_set_property(struct power_supply *psy,
enum power_supply_property psp,
const union power_supply_propval *val)
......@@ -362,6 +529,24 @@ static int axp20x_usb_power_set_property(struct power_supply *psy,
default:
return -EINVAL;
}
}
static int axp717_usb_power_set_property(struct power_supply *psy,
enum power_supply_property psp,
const union power_supply_propval *val)
{
struct axp20x_usb_power *power = power_supply_get_drvdata(psy);
switch (psp) {
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
return axp717_usb_power_set_input_current_limit(power, val->intval);
case POWER_SUPPLY_PROP_VOLTAGE_MIN:
return axp717_usb_power_set_voltage_min(power, val->intval);
default:
return -EINVAL;
}
return -EINVAL;
}
......@@ -385,6 +570,64 @@ static int axp20x_usb_power_prop_writeable(struct power_supply *psy,
psp == POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT;
}
static int axp717_usb_power_prop_writeable(struct power_supply *psy,
enum power_supply_property psp)
{
return psp == POWER_SUPPLY_PROP_VOLTAGE_MIN ||
psp == POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT;
}
static int axp20x_configure_iio_channels(struct platform_device *pdev,
struct axp20x_usb_power *power)
{
power->vbus_v = devm_iio_channel_get(&pdev->dev, "vbus_v");
if (IS_ERR(power->vbus_v)) {
if (PTR_ERR(power->vbus_v) == -ENODEV)
return -EPROBE_DEFER;
return PTR_ERR(power->vbus_v);
}
power->vbus_i = devm_iio_channel_get(&pdev->dev, "vbus_i");
if (IS_ERR(power->vbus_i)) {
if (PTR_ERR(power->vbus_i) == -ENODEV)
return -EPROBE_DEFER;
return PTR_ERR(power->vbus_i);
}
return 0;
}
static int axp717_configure_iio_channels(struct platform_device *pdev,
struct axp20x_usb_power *power)
{
power->vbus_v = devm_iio_channel_get(&pdev->dev, "vbus_v");
if (IS_ERR(power->vbus_v)) {
if (PTR_ERR(power->vbus_v) == -ENODEV)
return -EPROBE_DEFER;
return PTR_ERR(power->vbus_v);
}
return 0;
}
static int axp20x_configure_adc_registers(struct axp20x_usb_power *power)
{
/* Enable vbus voltage and current measurement */
return regmap_update_bits(power->regmap, AXP20X_ADC_EN1,
AXP20X_ADC_EN1_VBUS_CURR |
AXP20X_ADC_EN1_VBUS_VOLT,
AXP20X_ADC_EN1_VBUS_CURR |
AXP20X_ADC_EN1_VBUS_VOLT);
}
static int axp717_configure_adc_registers(struct axp20x_usb_power *power)
{
/* Enable vbus voltage measurement */
return regmap_update_bits(power->regmap, AXP717_ADC_CH_EN_CONTROL,
AXP717_ADC_EN_VBUS_VOLT,
AXP717_ADC_EN_VBUS_VOLT);
}
static enum power_supply_property axp20x_usb_power_properties[] = {
POWER_SUPPLY_PROP_HEALTH,
POWER_SUPPLY_PROP_PRESENT,
......@@ -403,6 +646,16 @@ static enum power_supply_property axp22x_usb_power_properties[] = {
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
};
static enum power_supply_property axp717_usb_power_properties[] = {
POWER_SUPPLY_PROP_HEALTH,
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_USB_TYPE,
POWER_SUPPLY_PROP_VOLTAGE_MIN,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
};
static enum power_supply_property axp813_usb_power_properties[] = {
POWER_SUPPLY_PROP_HEALTH,
POWER_SUPPLY_PROP_PRESENT,
......@@ -412,13 +665,6 @@ static enum power_supply_property axp813_usb_power_properties[] = {
POWER_SUPPLY_PROP_USB_TYPE,
};
static enum power_supply_usb_type axp813_usb_types[] = {
POWER_SUPPLY_USB_TYPE_SDP,
POWER_SUPPLY_USB_TYPE_DCP,
POWER_SUPPLY_USB_TYPE_CDP,
POWER_SUPPLY_USB_TYPE_UNKNOWN,
};
static const struct power_supply_desc axp20x_usb_power_desc = {
.name = "axp20x-usb",
.type = POWER_SUPPLY_TYPE_USB,
......@@ -439,6 +685,20 @@ static const struct power_supply_desc axp22x_usb_power_desc = {
.set_property = axp20x_usb_power_set_property,
};
static const struct power_supply_desc axp717_usb_power_desc = {
.name = "axp20x-usb",
.type = POWER_SUPPLY_TYPE_USB,
.properties = axp717_usb_power_properties,
.num_properties = ARRAY_SIZE(axp717_usb_power_properties),
.property_is_writeable = axp717_usb_power_prop_writeable,
.get_property = axp717_usb_power_get_property,
.set_property = axp717_usb_power_set_property,
.usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |
BIT(POWER_SUPPLY_USB_TYPE_CDP) |
BIT(POWER_SUPPLY_USB_TYPE_DCP) |
BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
};
static const struct power_supply_desc axp813_usb_power_desc = {
.name = "axp20x-usb",
.type = POWER_SUPPLY_TYPE_USB,
......@@ -447,8 +707,10 @@ static const struct power_supply_desc axp813_usb_power_desc = {
.property_is_writeable = axp20x_usb_power_prop_writeable,
.get_property = axp20x_usb_power_get_property,
.set_property = axp20x_usb_power_set_property,
.usb_types = axp813_usb_types,
.num_usb_types = ARRAY_SIZE(axp813_usb_types),
.usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |
BIT(POWER_SUPPLY_USB_TYPE_CDP) |
BIT(POWER_SUPPLY_USB_TYPE_DCP) |
BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
};
static const char * const axp20x_irq_names[] = {
......@@ -463,6 +725,12 @@ static const char * const axp22x_irq_names[] = {
"VBUS_REMOVAL",
};
static const char * const axp717_irq_names[] = {
"VBUS_PLUGIN",
"VBUS_REMOVAL",
"VBUS_OVER_V",
};
static int axp192_usb_curr_lim_table[] = {
-1,
-1,
......@@ -505,6 +773,9 @@ static const struct axp_data axp192_data = {
.curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
.vbus_valid_bit = REG_FIELD(AXP192_USB_OTG_STATUS, 2, 2),
.vbus_mon_bit = REG_FIELD(AXP20X_VBUS_MON, 3, 3),
.axp20x_read_vbus = &axp20x_usb_power_poll_vbus,
.axp20x_cfg_iio_chan = axp20x_configure_iio_channels,
.axp20x_cfg_adc_reg = axp20x_configure_adc_registers,
};
static const struct axp_data axp202_data = {
......@@ -516,6 +787,9 @@ static const struct axp_data axp202_data = {
.curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
.vbus_valid_bit = REG_FIELD(AXP20X_USB_OTG_STATUS, 2, 2),
.vbus_mon_bit = REG_FIELD(AXP20X_VBUS_MON, 3, 3),
.axp20x_read_vbus = &axp20x_usb_power_poll_vbus,
.axp20x_cfg_iio_chan = axp20x_configure_iio_channels,
.axp20x_cfg_adc_reg = axp20x_configure_adc_registers,
};
static const struct axp_data axp221_data = {
......@@ -526,6 +800,9 @@ static const struct axp_data axp221_data = {
.curr_lim_table_size = ARRAY_SIZE(axp221_usb_curr_lim_table),
.curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
.vbus_needs_polling = true,
.axp20x_read_vbus = &axp20x_usb_power_poll_vbus,
.axp20x_cfg_iio_chan = axp20x_configure_iio_channels,
.axp20x_cfg_adc_reg = axp20x_configure_adc_registers,
};
static const struct axp_data axp223_data = {
......@@ -536,6 +813,23 @@ static const struct axp_data axp223_data = {
.curr_lim_table_size = ARRAY_SIZE(axp20x_usb_curr_lim_table),
.curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
.vbus_needs_polling = true,
.axp20x_read_vbus = &axp20x_usb_power_poll_vbus,
.axp20x_cfg_iio_chan = axp20x_configure_iio_channels,
.axp20x_cfg_adc_reg = axp20x_configure_adc_registers,
};
static const struct axp_data axp717_data = {
.power_desc = &axp717_usb_power_desc,
.irq_names = axp717_irq_names,
.num_irq_names = ARRAY_SIZE(axp717_irq_names),
.curr_lim_fld = REG_FIELD(AXP717_INPUT_CUR_LIMIT_CTRL, 0, 5),
.usb_bc_en_bit = REG_FIELD(AXP717_MODULE_EN_CONTROL_1, 4, 4),
.usb_bc_det_fld = REG_FIELD(AXP717_BC_DETECT, 5, 7),
.vbus_mon_bit = REG_FIELD(AXP717_ADC_CH_EN_CONTROL, 2, 2),
.vbus_needs_polling = false,
.axp20x_read_vbus = &axp717_usb_power_poll_vbus,
.axp20x_cfg_iio_chan = axp717_configure_iio_channels,
.axp20x_cfg_adc_reg = axp717_configure_adc_registers,
};
static const struct axp_data axp813_data = {
......@@ -549,6 +843,9 @@ static const struct axp_data axp813_data = {
.usb_bc_det_fld = REG_FIELD(AXP288_BC_DET_STAT, 5, 7),
.vbus_disable_bit = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 7, 7),
.vbus_needs_polling = true,
.axp20x_read_vbus = &axp20x_usb_power_poll_vbus,
.axp20x_cfg_iio_chan = axp20x_configure_iio_channels,
.axp20x_cfg_adc_reg = axp20x_configure_adc_registers,
};
#ifdef CONFIG_PM_SLEEP
......@@ -590,36 +887,6 @@ static int axp20x_usb_power_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(axp20x_usb_power_pm_ops, axp20x_usb_power_suspend,
axp20x_usb_power_resume);
static int configure_iio_channels(struct platform_device *pdev,
struct axp20x_usb_power *power)
{
power->vbus_v = devm_iio_channel_get(&pdev->dev, "vbus_v");
if (IS_ERR(power->vbus_v)) {
if (PTR_ERR(power->vbus_v) == -ENODEV)
return -EPROBE_DEFER;
return PTR_ERR(power->vbus_v);
}
power->vbus_i = devm_iio_channel_get(&pdev->dev, "vbus_i");
if (IS_ERR(power->vbus_i)) {
if (PTR_ERR(power->vbus_i) == -ENODEV)
return -EPROBE_DEFER;
return PTR_ERR(power->vbus_i);
}
return 0;
}
static int configure_adc_registers(struct axp20x_usb_power *power)
{
/* Enable vbus voltage and current measurement */
return regmap_update_bits(power->regmap, AXP20X_ADC_EN1,
AXP20X_ADC_EN1_VBUS_CURR |
AXP20X_ADC_EN1_VBUS_VOLT,
AXP20X_ADC_EN1_VBUS_CURR |
AXP20X_ADC_EN1_VBUS_VOLT);
}
static int axp20x_regmap_field_alloc_optional(struct device *dev,
struct regmap *regmap,
struct reg_field fdesc,
......@@ -640,6 +907,18 @@ static int axp20x_regmap_field_alloc_optional(struct device *dev,
return 0;
}
/* Optionally allow users to specify a maximum charging current. */
static void axp20x_usb_power_parse_dt(struct device *dev,
struct axp20x_usb_power *power)
{
int ret;
ret = device_property_read_u32(dev, "input-current-limit-microamp",
&power->max_input_cur);
if (ret)
dev_dbg(dev, "%s() no input-current-limit specified\n", __func__);
}
static int axp20x_usb_power_probe(struct platform_device *pdev)
{
struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
......@@ -676,6 +955,8 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
if (IS_ERR(power->curr_lim_fld))
return PTR_ERR(power->curr_lim_fld);
axp20x_usb_power_parse_dt(&pdev->dev, power);
ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap,
axp_data->vbus_valid_bit,
&power->vbus_valid_bit);
......@@ -707,7 +988,7 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
return ret;
ret = devm_delayed_work_autocancel(&pdev->dev, &power->vbus_detect,
axp20x_usb_power_poll_vbus);
axp_data->axp20x_read_vbus);
if (ret)
return ret;
......@@ -718,9 +999,9 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
return ret;
if (IS_ENABLED(CONFIG_AXP20X_ADC))
ret = configure_iio_channels(pdev, power);
ret = axp_data->axp20x_cfg_iio_chan(pdev, power);
else
ret = configure_adc_registers(power);
ret = axp_data->axp20x_cfg_adc_reg(power);
if (ret)
return ret;
......@@ -778,6 +1059,9 @@ static const struct of_device_id axp20x_usb_power_match[] = {
}, {
.compatible = "x-powers,axp223-usb-power-supply",
.data = &axp223_data,
}, {
.compatible = "x-powers,axp717-usb-power-supply",
.data = &axp717_data,
}, {
.compatible = "x-powers,axp813-usb-power-supply",
.data = &axp813_data,
......
......@@ -334,14 +334,6 @@ static const int bq25618_619_ichg_values[] = {
1290000, 1360000, 1430000, 1500000
};
static enum power_supply_usb_type bq256xx_usb_type[] = {
POWER_SUPPLY_USB_TYPE_SDP,
POWER_SUPPLY_USB_TYPE_CDP,
POWER_SUPPLY_USB_TYPE_DCP,
POWER_SUPPLY_USB_TYPE_UNKNOWN,
POWER_SUPPLY_USB_TYPE_ACA,
};
static int bq256xx_array_parse(int array_size, int val, const int array[])
{
int i = 0;
......@@ -1252,8 +1244,11 @@ static int bq256xx_property_is_writeable(struct power_supply *psy,
static const struct power_supply_desc bq256xx_power_supply_desc = {
.name = "bq256xx-charger",
.type = POWER_SUPPLY_TYPE_USB,
.usb_types = bq256xx_usb_type,
.num_usb_types = ARRAY_SIZE(bq256xx_usb_type),
.usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |
BIT(POWER_SUPPLY_USB_TYPE_CDP) |
BIT(POWER_SUPPLY_USB_TYPE_DCP) |
BIT(POWER_SUPPLY_USB_TYPE_ACA) |
BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
.properties = bq256xx_power_supply_props,
.num_properties = ARRAY_SIZE(bq256xx_power_supply_props),
.get_property = bq256xx_get_charger_property,
......
......@@ -904,7 +904,7 @@ static int cpcap_charger_probe(struct platform_device *pdev)
psy_cfg.of_node = pdev->dev.of_node;
psy_cfg.drv_data = ddata;
psy_cfg.supplied_to = cpcap_charger_supplied_to;
psy_cfg.num_supplicants = ARRAY_SIZE(cpcap_charger_supplied_to),
psy_cfg.num_supplicants = ARRAY_SIZE(cpcap_charger_supplied_to);
ddata->usb = devm_power_supply_register(ddata->dev,
&cpcap_charger_usb_desc,
......
......@@ -73,17 +73,6 @@ static enum power_supply_property cros_usbpd_dedicated_charger_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_NOW,
};
static enum power_supply_usb_type cros_usbpd_charger_usb_types[] = {
POWER_SUPPLY_USB_TYPE_UNKNOWN,
POWER_SUPPLY_USB_TYPE_SDP,
POWER_SUPPLY_USB_TYPE_DCP,
POWER_SUPPLY_USB_TYPE_CDP,
POWER_SUPPLY_USB_TYPE_C,
POWER_SUPPLY_USB_TYPE_PD,
POWER_SUPPLY_USB_TYPE_PD_DRP,
POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID
};
/* Input voltage/current limit in mV/mA. Default to none. */
static u16 input_voltage_limit = EC_POWER_LIMIT_NONE;
static u16 input_current_limit = EC_POWER_LIMIT_NONE;
......@@ -643,9 +632,14 @@ static int cros_usbpd_charger_probe(struct platform_device *pd)
psy_desc->properties = cros_usbpd_charger_props;
psy_desc->num_properties =
ARRAY_SIZE(cros_usbpd_charger_props);
psy_desc->usb_types = cros_usbpd_charger_usb_types;
psy_desc->num_usb_types =
ARRAY_SIZE(cros_usbpd_charger_usb_types);
psy_desc->usb_types = BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN) |
BIT(POWER_SUPPLY_USB_TYPE_SDP) |
BIT(POWER_SUPPLY_USB_TYPE_DCP) |
BIT(POWER_SUPPLY_USB_TYPE_CDP) |
BIT(POWER_SUPPLY_USB_TYPE_C) |
BIT(POWER_SUPPLY_USB_TYPE_PD) |
BIT(POWER_SUPPLY_USB_TYPE_PD_DRP) |
BIT(POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID);
}
psy_desc->name = port->name;
......
......@@ -353,15 +353,10 @@ static enum power_supply_property yoga_c630_psy_adpt_properties[] = {
POWER_SUPPLY_PROP_USB_TYPE,
};
static const enum power_supply_usb_type yoga_c630_psy_adpt_usb_type[] = {
POWER_SUPPLY_USB_TYPE_C,
};
static const struct power_supply_desc yoga_c630_psy_adpt_psy_desc = {
.name = "yoga-c630-adapter",
.type = POWER_SUPPLY_TYPE_USB,
.usb_types = yoga_c630_psy_adpt_usb_type,
.num_usb_types = ARRAY_SIZE(yoga_c630_psy_adpt_usb_type),
.usb_types = BIT(POWER_SUPPLY_USB_TYPE_C),
.properties = yoga_c630_psy_adpt_properties,
.num_properties = ARRAY_SIZE(yoga_c630_psy_adpt_properties),
.get_property = yoga_c630_psy_adpt_get_property,
......
......@@ -853,7 +853,10 @@ static void max17042_set_soc_threshold(struct max17042_chip *chip, u16 off)
/* program interrupt thresholds such that we should
* get interrupt for every 'off' perc change in the soc
*/
if (chip->pdata->enable_current_sense)
regmap_read(map, MAX17042_RepSOC, &soc);
else
regmap_read(map, MAX17042_VFSOC, &soc);
soc >>= 8;
soc_tr = (soc + off) << 8;
if (off < soc)
......
......@@ -10,13 +10,16 @@
#include <linux/bitfield.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/nvmem-provider.h>
#include <linux/power_supply.h>
#include <linux/regmap.h>
#include <asm/unaligned.h>
/* Nonvolatile registers */
#define MAX1720X_NXTABLE0 0x80
#define MAX1720X_NRSENSE 0xCF /* RSense in 10^-5 Ohm */
#define MAX1720X_NDEVICE_NAME4 0xDF
/* ModelGauge m5 */
#define MAX172XX_STATUS 0x00 /* Status */
......@@ -46,6 +49,8 @@ static const char *const max17205_model = "MAX17205";
struct max1720x_device_info {
struct regmap *regmap;
struct regmap *regmap_nv;
struct i2c_client *ancillary;
int rsense;
};
......@@ -106,6 +111,134 @@ static const struct regmap_config max1720x_regmap_cfg = {
.cache_type = REGCACHE_RBTREE,
};
static const struct regmap_range max1720x_nvmem_allow[] = {
regmap_reg_range(MAX1720X_NXTABLE0, MAX1720X_NDEVICE_NAME4),
};
static const struct regmap_range max1720x_nvmem_deny[] = {
regmap_reg_range(0x00, 0x7F),
regmap_reg_range(0xE0, 0xFF),
};
static const struct regmap_access_table max1720x_nvmem_regs = {
.yes_ranges = max1720x_nvmem_allow,
.n_yes_ranges = ARRAY_SIZE(max1720x_nvmem_allow),
.no_ranges = max1720x_nvmem_deny,
.n_no_ranges = ARRAY_SIZE(max1720x_nvmem_deny),
};
static const struct regmap_config max1720x_nvmem_regmap_cfg = {
.reg_bits = 8,
.val_bits = 16,
.max_register = MAX1720X_NDEVICE_NAME4,
.val_format_endian = REGMAP_ENDIAN_LITTLE,
.rd_table = &max1720x_nvmem_regs,
};
static const struct nvmem_cell_info max1720x_nvmem_cells[] = {
{ .name = "nXTable0", .offset = 0, .bytes = 2, },
{ .name = "nXTable1", .offset = 2, .bytes = 2, },
{ .name = "nXTable2", .offset = 4, .bytes = 2, },
{ .name = "nXTable3", .offset = 6, .bytes = 2, },
{ .name = "nXTable4", .offset = 8, .bytes = 2, },
{ .name = "nXTable5", .offset = 10, .bytes = 2, },
{ .name = "nXTable6", .offset = 12, .bytes = 2, },
{ .name = "nXTable7", .offset = 14, .bytes = 2, },
{ .name = "nXTable8", .offset = 16, .bytes = 2, },
{ .name = "nXTable9", .offset = 18, .bytes = 2, },
{ .name = "nXTable10", .offset = 20, .bytes = 2, },
{ .name = "nXTable11", .offset = 22, .bytes = 2, },
{ .name = "nUser18C", .offset = 24, .bytes = 2, },
{ .name = "nUser18D", .offset = 26, .bytes = 2, },
{ .name = "nODSCTh", .offset = 28, .bytes = 2, },
{ .name = "nODSCCfg", .offset = 30, .bytes = 2, },
{ .name = "nOCVTable0", .offset = 32, .bytes = 2, },
{ .name = "nOCVTable1", .offset = 34, .bytes = 2, },
{ .name = "nOCVTable2", .offset = 36, .bytes = 2, },
{ .name = "nOCVTable3", .offset = 38, .bytes = 2, },
{ .name = "nOCVTable4", .offset = 40, .bytes = 2, },
{ .name = "nOCVTable5", .offset = 42, .bytes = 2, },
{ .name = "nOCVTable6", .offset = 44, .bytes = 2, },
{ .name = "nOCVTable7", .offset = 46, .bytes = 2, },
{ .name = "nOCVTable8", .offset = 48, .bytes = 2, },
{ .name = "nOCVTable9", .offset = 50, .bytes = 2, },
{ .name = "nOCVTable10", .offset = 52, .bytes = 2, },
{ .name = "nOCVTable11", .offset = 54, .bytes = 2, },
{ .name = "nIChgTerm", .offset = 56, .bytes = 2, },
{ .name = "nFilterCfg", .offset = 58, .bytes = 2, },
{ .name = "nVEmpty", .offset = 60, .bytes = 2, },
{ .name = "nLearnCfg", .offset = 62, .bytes = 2, },
{ .name = "nQRTable00", .offset = 64, .bytes = 2, },
{ .name = "nQRTable10", .offset = 66, .bytes = 2, },
{ .name = "nQRTable20", .offset = 68, .bytes = 2, },
{ .name = "nQRTable30", .offset = 70, .bytes = 2, },
{ .name = "nCycles", .offset = 72, .bytes = 2, },
{ .name = "nFullCapNom", .offset = 74, .bytes = 2, },
{ .name = "nRComp0", .offset = 76, .bytes = 2, },
{ .name = "nTempCo", .offset = 78, .bytes = 2, },
{ .name = "nIAvgEmpty", .offset = 80, .bytes = 2, },
{ .name = "nFullCapRep", .offset = 82, .bytes = 2, },
{ .name = "nVoltTemp", .offset = 84, .bytes = 2, },
{ .name = "nMaxMinCurr", .offset = 86, .bytes = 2, },
{ .name = "nMaxMinVolt", .offset = 88, .bytes = 2, },
{ .name = "nMaxMinTemp", .offset = 90, .bytes = 2, },
{ .name = "nSOC", .offset = 92, .bytes = 2, },
{ .name = "nTimerH", .offset = 94, .bytes = 2, },
{ .name = "nConfig", .offset = 96, .bytes = 2, },
{ .name = "nRippleCfg", .offset = 98, .bytes = 2, },
{ .name = "nMiscCfg", .offset = 100, .bytes = 2, },
{ .name = "nDesignCap", .offset = 102, .bytes = 2, },
{ .name = "nHibCfg", .offset = 104, .bytes = 2, },
{ .name = "nPackCfg", .offset = 106, .bytes = 2, },
{ .name = "nRelaxCfg", .offset = 108, .bytes = 2, },
{ .name = "nConvgCfg", .offset = 110, .bytes = 2, },
{ .name = "nNVCfg0", .offset = 112, .bytes = 2, },
{ .name = "nNVCfg1", .offset = 114, .bytes = 2, },
{ .name = "nNVCfg2", .offset = 116, .bytes = 2, },
{ .name = "nSBSCfg", .offset = 118, .bytes = 2, },
{ .name = "nROMID0", .offset = 120, .bytes = 2, },
{ .name = "nROMID1", .offset = 122, .bytes = 2, },
{ .name = "nROMID2", .offset = 124, .bytes = 2, },
{ .name = "nROMID3", .offset = 126, .bytes = 2, },
{ .name = "nVAlrtTh", .offset = 128, .bytes = 2, },
{ .name = "nTAlrtTh", .offset = 130, .bytes = 2, },
{ .name = "nSAlrtTh", .offset = 132, .bytes = 2, },
{ .name = "nIAlrtTh", .offset = 134, .bytes = 2, },
{ .name = "nUser1C4", .offset = 136, .bytes = 2, },
{ .name = "nUser1C5", .offset = 138, .bytes = 2, },
{ .name = "nFullSOCThr", .offset = 140, .bytes = 2, },
{ .name = "nTTFCfg", .offset = 142, .bytes = 2, },
{ .name = "nCGain", .offset = 144, .bytes = 2, },
{ .name = "nTCurve", .offset = 146, .bytes = 2, },
{ .name = "nTGain", .offset = 148, .bytes = 2, },
{ .name = "nTOff", .offset = 150, .bytes = 2, },
{ .name = "nManfctrName0", .offset = 152, .bytes = 2, },
{ .name = "nManfctrName1", .offset = 154, .bytes = 2, },
{ .name = "nManfctrName2", .offset = 156, .bytes = 2, },
{ .name = "nRSense", .offset = 158, .bytes = 2, },
{ .name = "nUser1D0", .offset = 160, .bytes = 2, },
{ .name = "nUser1D1", .offset = 162, .bytes = 2, },
{ .name = "nAgeFcCfg", .offset = 164, .bytes = 2, },
{ .name = "nDesignVoltage", .offset = 166, .bytes = 2, },
{ .name = "nUser1D4", .offset = 168, .bytes = 2, },
{ .name = "nRFastVShdn", .offset = 170, .bytes = 2, },
{ .name = "nManfctrDate", .offset = 172, .bytes = 2, },
{ .name = "nFirstUsed", .offset = 174, .bytes = 2, },
{ .name = "nSerialNumber0", .offset = 176, .bytes = 2, },
{ .name = "nSerialNumber1", .offset = 178, .bytes = 2, },
{ .name = "nSerialNumber2", .offset = 180, .bytes = 2, },
{ .name = "nDeviceName0", .offset = 182, .bytes = 2, },
{ .name = "nDeviceName1", .offset = 184, .bytes = 2, },
{ .name = "nDeviceName2", .offset = 186, .bytes = 2, },
{ .name = "nDeviceName3", .offset = 188, .bytes = 2, },
{ .name = "nDeviceName4", .offset = 190, .bytes = 2, },
};
static const enum power_supply_property max1720x_battery_props[] = {
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_CAPACITY,
......@@ -249,30 +382,80 @@ static int max1720x_battery_get_property(struct power_supply *psy,
return ret;
}
static int max1720x_probe_sense_resistor(struct i2c_client *client,
static
int max1720x_nvmem_reg_read(void *priv, unsigned int off, void *val, size_t len)
{
struct max1720x_device_info *info = priv;
unsigned int reg = MAX1720X_NXTABLE0 + (off / 2);
return regmap_bulk_read(info->regmap_nv, reg, val, len / 2);
}
static void max1720x_unregister_ancillary(void *data)
{
struct max1720x_device_info *info = data;
i2c_unregister_device(info->ancillary);
}
static int max1720x_probe_nvmem(struct i2c_client *client,
struct max1720x_device_info *info)
{
struct device *dev = &client->dev;
struct i2c_client *ancillary;
struct nvmem_config nvmem_config = {
.dev = dev,
.name = "max1720x_nvmem",
.cells = max1720x_nvmem_cells,
.ncells = ARRAY_SIZE(max1720x_nvmem_cells),
.read_only = true,
.root_only = true,
.reg_read = max1720x_nvmem_reg_read,
.size = ARRAY_SIZE(max1720x_nvmem_cells) * 2,
.word_size = 2,
.stride = 2,
.priv = info,
};
struct nvmem_device *nvmem;
unsigned int val;
int ret;
ancillary = i2c_new_ancillary_device(client, "nvmem", 0xb);
if (IS_ERR(ancillary)) {
info->ancillary = i2c_new_ancillary_device(client, "nvmem", 0xb);
if (IS_ERR(info->ancillary)) {
dev_err(dev, "Failed to initialize ancillary i2c device\n");
return PTR_ERR(ancillary);
return PTR_ERR(info->ancillary);
}
ret = devm_add_action_or_reset(dev, max1720x_unregister_ancillary, info);
if (ret) {
dev_err(dev, "Failed to add unregister callback\n");
return ret;
}
info->regmap_nv = devm_regmap_init_i2c(info->ancillary,
&max1720x_nvmem_regmap_cfg);
if (IS_ERR(info->regmap_nv)) {
dev_err(dev, "regmap initialization of nvmem failed\n");
return PTR_ERR(info->regmap_nv);
}
ret = i2c_smbus_read_word_data(ancillary, MAX1720X_NRSENSE);
i2c_unregister_device(ancillary);
if (ret < 0)
ret = regmap_read(info->regmap_nv, MAX1720X_NRSENSE, &val);
if (ret < 0) {
dev_err(dev, "Failed to read sense resistor value\n");
return ret;
}
info->rsense = ret;
info->rsense = val;
if (!info->rsense) {
dev_warn(dev, "RSense not calibrated, set 10 mOhms!\n");
info->rsense = 1000; /* in regs in 10^-5 */
}
nvmem = devm_nvmem_register(dev, &nvmem_config);
if (IS_ERR(nvmem)) {
dev_err(dev, "Could not register nvmem!");
return PTR_ERR(nvmem);
}
return 0;
}
......@@ -299,15 +482,15 @@ static int max1720x_probe(struct i2c_client *client)
psy_cfg.drv_data = info;
psy_cfg.fwnode = dev_fwnode(dev);
i2c_set_clientdata(client, info);
info->regmap = devm_regmap_init_i2c(client, &max1720x_regmap_cfg);
if (IS_ERR(info->regmap))
return dev_err_probe(dev, PTR_ERR(info->regmap),
"regmap initialization failed\n");
ret = max1720x_probe_sense_resistor(client, info);
ret = max1720x_probe_nvmem(client, info);
if (ret)
return dev_err_probe(dev, ret,
"Failed to read sense resistor value\n");
return dev_err_probe(dev, ret, "Failed to probe nvmem\n");
bat = devm_power_supply_register(dev, &max1720x_bat_desc, &psy_cfg);
if (IS_ERR(bat))
......
......@@ -197,12 +197,58 @@ static int max77693_get_online(struct regmap *regmap, int *val)
return 0;
}
/*
* There are *two* current limit registers:
* - CHGIN limit, which limits the input current from the external charger;
* - Fast charge current limit, which limits the current going to the battery.
*/
static int max77693_get_input_current_limit(struct regmap *regmap, int *val)
{
unsigned int data;
int ret;
ret = regmap_read(regmap, MAX77693_CHG_REG_CHG_CNFG_09, &data);
if (ret < 0)
return ret;
data &= CHG_CNFG_09_CHGIN_ILIM_MASK;
data >>= CHG_CNFG_09_CHGIN_ILIM_SHIFT;
if (data <= 0x03)
/* The first four values (0x00..0x03) are 60mA */
*val = 60000;
else
*val = data * 20000; /* 20mA steps */
return 0;
}
static int max77693_get_fast_charge_current(struct regmap *regmap, int *val)
{
unsigned int data;
int ret;
ret = regmap_read(regmap, MAX77693_CHG_REG_CHG_CNFG_02, &data);
if (ret < 0)
return ret;
data &= CHG_CNFG_02_CC_MASK;
data >>= CHG_CNFG_02_CC_SHIFT;
*val = data * 33300; /* 33.3mA steps */
return 0;
}
static enum power_supply_property max77693_charger_props[] = {
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_CHARGE_TYPE,
POWER_SUPPLY_PROP_HEALTH,
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
POWER_SUPPLY_PROP_MODEL_NAME,
POWER_SUPPLY_PROP_MANUFACTURER,
};
......@@ -231,6 +277,12 @@ static int max77693_charger_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_ONLINE:
ret = max77693_get_online(regmap, &val->intval);
break;
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
ret = max77693_get_input_current_limit(regmap, &val->intval);
break;
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
ret = max77693_get_fast_charge_current(regmap, &val->intval);
break;
case POWER_SUPPLY_PROP_MODEL_NAME:
val->strval = max77693_charger_model;
break;
......
......@@ -191,6 +191,7 @@ static const struct platform_device_id max8998_battery_id[] = {
{ "max8998-battery", TYPE_MAX8998 },
{ }
};
MODULE_DEVICE_TABLE(platform, max8998_battery_id);
static struct platform_driver max8998_battery_driver = {
.driver = {
......
......@@ -94,14 +94,6 @@ struct mp2629_prop {
int shift;
};
static enum power_supply_usb_type mp2629_usb_types[] = {
POWER_SUPPLY_USB_TYPE_SDP,
POWER_SUPPLY_USB_TYPE_DCP,
POWER_SUPPLY_USB_TYPE_CDP,
POWER_SUPPLY_USB_TYPE_PD_DRP,
POWER_SUPPLY_USB_TYPE_UNKNOWN
};
static enum power_supply_property mp2629_charger_usb_props[] = {
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_USB_TYPE,
......@@ -487,8 +479,11 @@ static irqreturn_t mp2629_irq_handler(int irq, void *dev_id)
static const struct power_supply_desc mp2629_usb_desc = {
.name = "mp2629_usb",
.type = POWER_SUPPLY_TYPE_USB,
.usb_types = mp2629_usb_types,
.num_usb_types = ARRAY_SIZE(mp2629_usb_types),
.usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |
BIT(POWER_SUPPLY_USB_TYPE_CDP) |
BIT(POWER_SUPPLY_USB_TYPE_DCP) |
BIT(POWER_SUPPLY_USB_TYPE_PD_DRP) |
BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
.properties = mp2629_charger_usb_props,
.num_properties = ARRAY_SIZE(mp2629_charger_usb_props),
.get_property = mp2629_charger_usb_get_prop,
......
......@@ -154,13 +154,6 @@ enum mt6360_pmu_chg_type {
MT6360_CHG_TYPE_MAX,
};
static enum power_supply_usb_type mt6360_charger_usb_types[] = {
POWER_SUPPLY_USB_TYPE_UNKNOWN,
POWER_SUPPLY_USB_TYPE_SDP,
POWER_SUPPLY_USB_TYPE_DCP,
POWER_SUPPLY_USB_TYPE_CDP,
};
static int mt6360_get_chrdet_ext_stat(struct mt6360_chg_info *mci,
bool *pwr_rdy)
{
......@@ -574,8 +567,10 @@ static const struct power_supply_desc mt6360_charger_desc = {
.get_property = mt6360_charger_get_property,
.set_property = mt6360_charger_set_property,
.property_is_writeable = mt6360_charger_property_is_writeable,
.usb_types = mt6360_charger_usb_types,
.num_usb_types = ARRAY_SIZE(mt6360_charger_usb_types),
.usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |
BIT(POWER_SUPPLY_USB_TYPE_CDP) |
BIT(POWER_SUPPLY_USB_TYPE_DCP) |
BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
};
static const struct regulator_ops mt6360_chg_otg_ops = {
......
......@@ -624,13 +624,6 @@ static enum power_supply_property mt6370_chg_properties[] = {
POWER_SUPPLY_PROP_USB_TYPE,
};
static enum power_supply_usb_type mt6370_chg_usb_types[] = {
POWER_SUPPLY_USB_TYPE_UNKNOWN,
POWER_SUPPLY_USB_TYPE_SDP,
POWER_SUPPLY_USB_TYPE_CDP,
POWER_SUPPLY_USB_TYPE_DCP,
};
static const struct power_supply_desc mt6370_chg_psy_desc = {
.name = "mt6370-charger",
.type = POWER_SUPPLY_TYPE_USB,
......@@ -639,8 +632,10 @@ static const struct power_supply_desc mt6370_chg_psy_desc = {
.get_property = mt6370_chg_get_property,
.set_property = mt6370_chg_set_property,
.property_is_writeable = mt6370_chg_property_is_writeable,
.usb_types = mt6370_chg_usb_types,
.num_usb_types = ARRAY_SIZE(mt6370_chg_usb_types),
.usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |
BIT(POWER_SUPPLY_USB_TYPE_CDP) |
BIT(POWER_SUPPLY_USB_TYPE_DCP) |
BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
};
static const struct regulator_ops mt6370_chg_otg_ops = {
......
......@@ -9,6 +9,7 @@
* Modified: 2004, Oct Szabolcs Gyurko
*/
#include <linux/cleanup.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/init.h>
......@@ -756,10 +757,10 @@ int power_supply_get_battery_info(struct power_supply *psy,
for (index = 0; index < len; index++) {
struct power_supply_battery_ocv_table *table;
char *propname;
int i, tab_len, size;
propname = kasprintf(GFP_KERNEL, "ocv-capacity-table-%d", index);
char *propname __free(kfree) = kasprintf(GFP_KERNEL, "ocv-capacity-table-%d",
index);
if (!propname) {
power_supply_put_battery_info(psy, info);
err = -ENOMEM;
......@@ -768,13 +769,11 @@ int power_supply_get_battery_info(struct power_supply *psy,
list = of_get_property(battery_np, propname, &size);
if (!list || !size) {
dev_err(&psy->dev, "failed to get %s\n", propname);
kfree(propname);
power_supply_put_battery_info(psy, info);
err = -EINVAL;
goto out_put_node;
}
kfree(propname);
tab_len = size / (2 * sizeof(__be32));
info->ocv_table_size[index] = tab_len;
......@@ -1232,11 +1231,7 @@ EXPORT_SYMBOL_GPL(power_supply_set_property);
int power_supply_property_is_writeable(struct power_supply *psy,
enum power_supply_property psp)
{
if (atomic_read(&psy->use_cnt) <= 0 ||
!psy->desc->property_is_writeable)
return -ENODEV;
return psy->desc->property_is_writeable(psy, psp);
return psy->desc->property_is_writeable && psy->desc->property_is_writeable(psy, psp);
}
EXPORT_SYMBOL_GPL(power_supply_property_is_writeable);
......@@ -1296,7 +1291,7 @@ static int power_supply_read_temp(struct thermal_zone_device *tzd,
return ret;
}
static struct thermal_zone_device_ops psy_tzd_ops = {
static const struct thermal_zone_device_ops psy_tzd_ops = {
.get_temp = power_supply_read_temp,
};
......@@ -1361,10 +1356,6 @@ __power_supply_register(struct device *parent,
pr_warn("%s: Expected proper parent device for '%s'\n",
__func__, desc->name);
if (psy_has_property(desc, POWER_SUPPLY_PROP_USB_TYPE) &&
(!desc->usb_types || !desc->num_usb_types))
return ERR_PTR(-EINVAL);
psy = kzalloc(sizeof(*psy), GFP_KERNEL);
if (!psy)
return ERR_PTR(-ENOMEM);
......
......@@ -318,7 +318,8 @@ static const struct hwmon_channel_info * const power_supply_hwmon_info[] = {
HWMON_T_INPUT |
HWMON_T_MAX |
HWMON_T_MIN |
HWMON_T_MIN_ALARM,
HWMON_T_MIN_ALARM |
HWMON_T_MAX_ALARM,
HWMON_T_LABEL |
HWMON_T_INPUT |
......
......@@ -209,7 +209,7 @@ static struct power_supply_attr power_supply_attrs[] = {
POWER_SUPPLY_ATTR(TIME_TO_FULL_NOW),
POWER_SUPPLY_ATTR(TIME_TO_FULL_AVG),
POWER_SUPPLY_ENUM_ATTR(TYPE),
POWER_SUPPLY_ATTR(USB_TYPE),
POWER_SUPPLY_ENUM_ATTR(USB_TYPE),
POWER_SUPPLY_ENUM_ATTR(SCOPE),
POWER_SUPPLY_ATTR(PRECHARGE_CURRENT),
POWER_SUPPLY_ATTR(CHARGE_TERM_CURRENT),
......@@ -237,31 +237,28 @@ static enum power_supply_property dev_attr_psp(struct device_attribute *attr)
return to_ps_attr(attr) - power_supply_attrs;
}
static ssize_t power_supply_show_usb_type(struct device *dev,
const struct power_supply_desc *desc,
union power_supply_propval *value,
char *buf)
static ssize_t power_supply_show_enum_with_available(
struct device *dev, const char * const labels[], int label_count,
unsigned int available_values, int value, char *buf)
{
enum power_supply_usb_type usb_type;
bool match = false, available, active;
ssize_t count = 0;
bool match = false;
int i;
for (i = 0; i < desc->num_usb_types; ++i) {
usb_type = desc->usb_types[i];
for (i = 0; i < label_count; i++) {
available = available_values & BIT(i);
active = i == value;
if (value->intval == usb_type) {
count += sysfs_emit_at(buf, count, "[%s] ",
POWER_SUPPLY_USB_TYPE_TEXT[usb_type]);
if (available && active) {
count += sysfs_emit_at(buf, count, "[%s] ", labels[i]);
match = true;
} else {
count += sysfs_emit_at(buf, count, "%s ",
POWER_SUPPLY_USB_TYPE_TEXT[usb_type]);
} else if (available) {
count += sysfs_emit_at(buf, count, "%s ", labels[i]);
}
}
if (!match) {
dev_warn(dev, "driver reporting unsupported connected type\n");
dev_warn(dev, "driver reporting unavailable enum value %d\n", value);
return -EINVAL;
}
......@@ -300,8 +297,10 @@ static ssize_t power_supply_show_property(struct device *dev,
switch (psp) {
case POWER_SUPPLY_PROP_USB_TYPE:
ret = power_supply_show_usb_type(dev, psy->desc,
&value, buf);
ret = power_supply_show_enum_with_available(
dev, POWER_SUPPLY_USB_TYPE_TEXT,
ARRAY_SIZE(POWER_SUPPLY_USB_TYPE_TEXT),
psy->desc->usb_types, value.intval, buf);
break;
case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR:
ret = power_supply_charge_behaviour_show(dev, psy->desc->charge_behaviours,
......@@ -523,33 +522,10 @@ ssize_t power_supply_charge_behaviour_show(struct device *dev,
enum power_supply_charge_behaviour current_behaviour,
char *buf)
{
bool match = false, available, active;
ssize_t count = 0;
int i;
for (i = 0; i < ARRAY_SIZE(POWER_SUPPLY_CHARGE_BEHAVIOUR_TEXT); i++) {
available = available_behaviours & BIT(i);
active = i == current_behaviour;
if (available && active) {
count += sysfs_emit_at(buf, count, "[%s] ",
POWER_SUPPLY_CHARGE_BEHAVIOUR_TEXT[i]);
match = true;
} else if (available) {
count += sysfs_emit_at(buf, count, "%s ",
POWER_SUPPLY_CHARGE_BEHAVIOUR_TEXT[i]);
}
}
if (!match) {
dev_warn(dev, "driver reporting unsupported charge behaviour\n");
return -EINVAL;
}
if (count)
buf[count - 1] = '\n';
return count;
return power_supply_show_enum_with_available(
dev, POWER_SUPPLY_CHARGE_BEHAVIOUR_TEXT,
ARRAY_SIZE(POWER_SUPPLY_CHARGE_BEHAVIOUR_TEXT),
available_behaviours, current_behaviour, buf);
}
EXPORT_SYMBOL_GPL(power_supply_charge_behaviour_show);
......
......@@ -786,19 +786,6 @@ static int qcom_battmgr_usb_get_property(struct power_supply *psy,
return 0;
}
static const enum power_supply_usb_type usb_psy_supported_types[] = {
POWER_SUPPLY_USB_TYPE_UNKNOWN,
POWER_SUPPLY_USB_TYPE_SDP,
POWER_SUPPLY_USB_TYPE_DCP,
POWER_SUPPLY_USB_TYPE_CDP,
POWER_SUPPLY_USB_TYPE_ACA,
POWER_SUPPLY_USB_TYPE_C,
POWER_SUPPLY_USB_TYPE_PD,
POWER_SUPPLY_USB_TYPE_PD_DRP,
POWER_SUPPLY_USB_TYPE_PD_PPS,
POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID,
};
static const enum power_supply_property sc8280xp_usb_props[] = {
POWER_SUPPLY_PROP_ONLINE,
};
......@@ -809,8 +796,16 @@ static const struct power_supply_desc sc8280xp_usb_psy_desc = {
.properties = sc8280xp_usb_props,
.num_properties = ARRAY_SIZE(sc8280xp_usb_props),
.get_property = qcom_battmgr_usb_get_property,
.usb_types = usb_psy_supported_types,
.num_usb_types = ARRAY_SIZE(usb_psy_supported_types),
.usb_types = BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN) |
BIT(POWER_SUPPLY_USB_TYPE_SDP) |
BIT(POWER_SUPPLY_USB_TYPE_DCP) |
BIT(POWER_SUPPLY_USB_TYPE_CDP) |
BIT(POWER_SUPPLY_USB_TYPE_ACA) |
BIT(POWER_SUPPLY_USB_TYPE_C) |
BIT(POWER_SUPPLY_USB_TYPE_PD) |
BIT(POWER_SUPPLY_USB_TYPE_PD_DRP) |
BIT(POWER_SUPPLY_USB_TYPE_PD_PPS) |
BIT(POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID),
};
static const enum power_supply_property sm8350_usb_props[] = {
......@@ -829,8 +824,16 @@ static const struct power_supply_desc sm8350_usb_psy_desc = {
.properties = sm8350_usb_props,
.num_properties = ARRAY_SIZE(sm8350_usb_props),
.get_property = qcom_battmgr_usb_get_property,
.usb_types = usb_psy_supported_types,
.num_usb_types = ARRAY_SIZE(usb_psy_supported_types),
.usb_types = BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN) |
BIT(POWER_SUPPLY_USB_TYPE_SDP) |
BIT(POWER_SUPPLY_USB_TYPE_DCP) |
BIT(POWER_SUPPLY_USB_TYPE_CDP) |
BIT(POWER_SUPPLY_USB_TYPE_ACA) |
BIT(POWER_SUPPLY_USB_TYPE_C) |
BIT(POWER_SUPPLY_USB_TYPE_PD) |
BIT(POWER_SUPPLY_USB_TYPE_PD_DRP) |
BIT(POWER_SUPPLY_USB_TYPE_PD_PPS) |
BIT(POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID),
};
static const u8 sm8350_wls_prop_map[] = {
......
......@@ -411,13 +411,6 @@ static enum power_supply_property smb2_properties[] = {
POWER_SUPPLY_PROP_USB_TYPE,
};
static enum power_supply_usb_type smb2_usb_types[] = {
POWER_SUPPLY_USB_TYPE_UNKNOWN,
POWER_SUPPLY_USB_TYPE_SDP,
POWER_SUPPLY_USB_TYPE_DCP,
POWER_SUPPLY_USB_TYPE_CDP,
};
static int smb2_get_prop_usb_online(struct smb2_chip *chip, int *val)
{
unsigned int stat;
......@@ -775,8 +768,10 @@ static irqreturn_t smb2_handle_wdog_bark(int irq, void *data)
static const struct power_supply_desc smb2_psy_desc = {
.name = "pmi8998_charger",
.type = POWER_SUPPLY_TYPE_USB,
.usb_types = smb2_usb_types,
.num_usb_types = ARRAY_SIZE(smb2_usb_types),
.usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |
BIT(POWER_SUPPLY_USB_TYPE_CDP) |
BIT(POWER_SUPPLY_USB_TYPE_DCP) |
BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
.properties = smb2_properties,
.num_properties = ARRAY_SIZE(smb2_properties),
.get_property = smb2_get_property,
......
......@@ -673,11 +673,6 @@ static enum power_supply_property rk817_chg_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_AVG,
};
static enum power_supply_usb_type rk817_usb_type[] = {
POWER_SUPPLY_USB_TYPE_DCP,
POWER_SUPPLY_USB_TYPE_UNKNOWN,
};
static const struct power_supply_desc rk817_bat_desc = {
.name = "rk817-battery",
.type = POWER_SUPPLY_TYPE_BATTERY,
......@@ -689,8 +684,8 @@ static const struct power_supply_desc rk817_bat_desc = {
static const struct power_supply_desc rk817_chg_desc = {
.name = "rk817-charger",
.type = POWER_SUPPLY_TYPE_USB,
.usb_types = rk817_usb_type,
.num_usb_types = ARRAY_SIZE(rk817_usb_type),
.usb_types = BIT(POWER_SUPPLY_USB_TYPE_DCP) |
BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
.properties = rk817_chg_props,
.num_properties = ARRAY_SIZE(rk817_chg_props),
.get_property = rk817_chg_get_prop,
......
......@@ -70,13 +70,6 @@ struct rn5t618_power_info {
int irq;
};
static enum power_supply_usb_type rn5t618_usb_types[] = {
POWER_SUPPLY_USB_TYPE_SDP,
POWER_SUPPLY_USB_TYPE_DCP,
POWER_SUPPLY_USB_TYPE_CDP,
POWER_SUPPLY_USB_TYPE_UNKNOWN
};
static enum power_supply_property rn5t618_usb_props[] = {
/* input current limit is not very accurate */
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
......@@ -681,8 +674,10 @@ static const struct power_supply_desc rn5t618_adp_desc = {
static const struct power_supply_desc rn5t618_usb_desc = {
.name = "rn5t618-usb",
.type = POWER_SUPPLY_TYPE_USB,
.usb_types = rn5t618_usb_types,
.num_usb_types = ARRAY_SIZE(rn5t618_usb_types),
.usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |
BIT(POWER_SUPPLY_USB_TYPE_CDP) |
BIT(POWER_SUPPLY_USB_TYPE_DCP) |
BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
.properties = rn5t618_usb_props,
.num_properties = ARRAY_SIZE(rn5t618_usb_props),
.get_property = rn5t618_usb_get_property,
......
......@@ -630,13 +630,6 @@ static int rt9467_psy_set_ieoc(struct rt9467_chg_data *data, int microamp)
return ret;
}
static const enum power_supply_usb_type rt9467_chg_usb_types[] = {
POWER_SUPPLY_USB_TYPE_UNKNOWN,
POWER_SUPPLY_USB_TYPE_SDP,
POWER_SUPPLY_USB_TYPE_DCP,
POWER_SUPPLY_USB_TYPE_CDP,
};
static const enum power_supply_property rt9467_chg_properties[] = {
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_ONLINE,
......@@ -745,8 +738,6 @@ static int rt9467_psy_set_property(struct power_supply *psy,
RT9467_RANGE_IPREC, val->intval);
case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
return rt9467_psy_set_ieoc(data, val->intval);
case POWER_SUPPLY_PROP_USB_TYPE:
return regmap_field_write(data->rm_field[F_USBCHGEN], val->intval);
default:
return -EINVAL;
}
......@@ -764,7 +755,6 @@ static int rt9467_chg_prop_is_writeable(struct power_supply *psy,
case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT:
case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
case POWER_SUPPLY_PROP_USB_TYPE:
return 1;
default:
return 0;
......@@ -774,8 +764,10 @@ static int rt9467_chg_prop_is_writeable(struct power_supply *psy,
static const struct power_supply_desc rt9467_chg_psy_desc = {
.name = "rt9467-charger",
.type = POWER_SUPPLY_TYPE_USB,
.usb_types = rt9467_chg_usb_types,
.num_usb_types = ARRAY_SIZE(rt9467_chg_usb_types),
.usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |
BIT(POWER_SUPPLY_USB_TYPE_CDP) |
BIT(POWER_SUPPLY_USB_TYPE_DCP) |
BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
.properties = rt9467_chg_properties,
.num_properties = ARRAY_SIZE(rt9467_chg_properties),
.property_is_writeable = rt9467_chg_prop_is_writeable,
......
......@@ -333,14 +333,6 @@ static enum power_supply_property rt9471_charger_properties[] = {
POWER_SUPPLY_PROP_MANUFACTURER,
};
static enum power_supply_usb_type rt9471_charger_usb_types[] = {
POWER_SUPPLY_USB_TYPE_UNKNOWN,
POWER_SUPPLY_USB_TYPE_SDP,
POWER_SUPPLY_USB_TYPE_DCP,
POWER_SUPPLY_USB_TYPE_CDP,
POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID,
};
static int rt9471_charger_property_is_writeable(struct power_supply *psy,
enum power_supply_property psp)
{
......@@ -726,8 +718,11 @@ static int rt9471_register_psy(struct rt9471_chip *chip)
desc->name = psy_name;
desc->type = POWER_SUPPLY_TYPE_USB;
desc->usb_types = rt9471_charger_usb_types;
desc->num_usb_types = ARRAY_SIZE(rt9471_charger_usb_types);
desc->usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |
BIT(POWER_SUPPLY_USB_TYPE_CDP) |
BIT(POWER_SUPPLY_USB_TYPE_DCP) |
BIT(POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID) |
BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN);
desc->properties = rt9471_charger_properties;
desc->num_properties = ARRAY_SIZE(rt9471_charger_properties);
desc->get_property = rt9471_charger_get_property;
......
......@@ -363,7 +363,7 @@ static int twl4030_charger_update_current(struct twl4030_bci *bci)
if (status < 0)
return status;
cur_reg |= oldreg << 8;
if (reg != oldreg) {
if (reg != cur_reg) {
/* disable write protection for one write access for
* BCIIREF */
status = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0xE7,
......
......@@ -296,22 +296,17 @@ static int ucs1002_set_max_current(struct ucs1002_info *info, u32 val)
return 0;
}
static enum power_supply_usb_type ucs1002_usb_types[] = {
POWER_SUPPLY_USB_TYPE_PD,
POWER_SUPPLY_USB_TYPE_SDP,
POWER_SUPPLY_USB_TYPE_DCP,
POWER_SUPPLY_USB_TYPE_CDP,
POWER_SUPPLY_USB_TYPE_UNKNOWN,
};
static int ucs1002_set_usb_type(struct ucs1002_info *info, int val)
{
unsigned int mode;
if (val < 0 || val >= ARRAY_SIZE(ucs1002_usb_types))
return -EINVAL;
switch (ucs1002_usb_types[val]) {
switch (val) {
/*
* POWER_SUPPLY_USB_TYPE_UNKNOWN == 0, map this to dedicated for
* userspace API compatibility with older versions of this driver
* which mapped 0 to dedicated.
*/
case POWER_SUPPLY_USB_TYPE_UNKNOWN:
case POWER_SUPPLY_USB_TYPE_PD:
mode = V_SET_ACTIVE_MODE_DEDICATED;
break;
......@@ -428,8 +423,11 @@ static int ucs1002_property_is_writeable(struct power_supply *psy,
static const struct power_supply_desc ucs1002_charger_desc = {
.name = "ucs1002",
.type = POWER_SUPPLY_TYPE_USB,
.usb_types = ucs1002_usb_types,
.num_usb_types = ARRAY_SIZE(ucs1002_usb_types),
.usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |
BIT(POWER_SUPPLY_USB_TYPE_CDP) |
BIT(POWER_SUPPLY_USB_TYPE_DCP) |
BIT(POWER_SUPPLY_USB_TYPE_PD) |
BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
.get_property = ucs1002_get_property,
.set_property = ucs1002_set_property,
.property_is_writeable = ucs1002_property_is_writeable,
......
......@@ -1339,12 +1339,6 @@ static void anx7411_get_gpio_irq(struct anx7411_data *ctx)
dev_err(dev, "failed to get GPIO IRQ\n");
}
static enum power_supply_usb_type anx7411_psy_usb_types[] = {
POWER_SUPPLY_USB_TYPE_C,
POWER_SUPPLY_USB_TYPE_PD,
POWER_SUPPLY_USB_TYPE_PD_PPS,
};
static enum power_supply_property anx7411_psy_props[] = {
POWER_SUPPLY_PROP_USB_TYPE,
POWER_SUPPLY_PROP_ONLINE,
......@@ -1422,8 +1416,9 @@ static int anx7411_psy_register(struct anx7411_data *ctx)
psy_desc->name = psy_name;
psy_desc->type = POWER_SUPPLY_TYPE_USB;
psy_desc->usb_types = anx7411_psy_usb_types;
psy_desc->num_usb_types = ARRAY_SIZE(anx7411_psy_usb_types);
psy_desc->usb_types = BIT(POWER_SUPPLY_USB_TYPE_C) |
BIT(POWER_SUPPLY_USB_TYPE_PD) |
BIT(POWER_SUPPLY_USB_TYPE_PD_PPS);
psy_desc->properties = anx7411_psy_props;
psy_desc->num_properties = ARRAY_SIZE(anx7411_psy_props);
......
......@@ -109,12 +109,6 @@ struct rt1719_data {
u16 conn_stat;
};
static const enum power_supply_usb_type rt1719_psy_usb_types[] = {
POWER_SUPPLY_USB_TYPE_C,
POWER_SUPPLY_USB_TYPE_PD,
POWER_SUPPLY_USB_TYPE_PD_PPS
};
static const enum power_supply_property rt1719_psy_properties[] = {
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_USB_TYPE,
......@@ -572,8 +566,9 @@ static int devm_rt1719_psy_register(struct rt1719_data *data)
data->psy_desc.name = psy_name;
data->psy_desc.type = POWER_SUPPLY_TYPE_USB;
data->psy_desc.usb_types = rt1719_psy_usb_types;
data->psy_desc.num_usb_types = ARRAY_SIZE(rt1719_psy_usb_types);
data->psy_desc.usb_types = BIT(POWER_SUPPLY_USB_TYPE_C) |
BIT(POWER_SUPPLY_USB_TYPE_PD) |
BIT(POWER_SUPPLY_USB_TYPE_PD_PPS);
data->psy_desc.properties = rt1719_psy_properties;
data->psy_desc.num_properties = ARRAY_SIZE(rt1719_psy_properties);
data->psy_desc.get_property = rt1719_psy_get_property;
......
......@@ -7483,12 +7483,6 @@ static int tcpm_psy_prop_writeable(struct power_supply *psy,
}
}
static enum power_supply_usb_type tcpm_psy_usb_types[] = {
POWER_SUPPLY_USB_TYPE_C,
POWER_SUPPLY_USB_TYPE_PD,
POWER_SUPPLY_USB_TYPE_PD_PPS,
};
static const char *tcpm_psy_name_prefix = "tcpm-source-psy-";
static int devm_tcpm_psy_register(struct tcpm_port *port)
......@@ -7509,8 +7503,9 @@ static int devm_tcpm_psy_register(struct tcpm_port *port)
port_dev_name);
port->psy_desc.name = psy_name;
port->psy_desc.type = POWER_SUPPLY_TYPE_USB;
port->psy_desc.usb_types = tcpm_psy_usb_types;
port->psy_desc.num_usb_types = ARRAY_SIZE(tcpm_psy_usb_types);
port->psy_desc.usb_types = BIT(POWER_SUPPLY_USB_TYPE_C) |
BIT(POWER_SUPPLY_USB_TYPE_PD) |
BIT(POWER_SUPPLY_USB_TYPE_PD_PPS);
port->psy_desc.properties = tcpm_psy_props;
port->psy_desc.num_properties = ARRAY_SIZE(tcpm_psy_props);
port->psy_desc.get_property = tcpm_psy_get_prop;
......
......@@ -150,11 +150,6 @@ static enum power_supply_property tps6598x_psy_props[] = {
POWER_SUPPLY_PROP_ONLINE,
};
static enum power_supply_usb_type tps6598x_psy_usb_types[] = {
POWER_SUPPLY_USB_TYPE_C,
POWER_SUPPLY_USB_TYPE_PD,
};
static const char *tps6598x_psy_name_prefix = "tps6598x-source-psy-";
/*
......@@ -827,8 +822,8 @@ static int devm_tps6598_psy_register(struct tps6598x *tps)
tps->psy_desc.name = psy_name;
tps->psy_desc.type = POWER_SUPPLY_TYPE_USB;
tps->psy_desc.usb_types = tps6598x_psy_usb_types;
tps->psy_desc.num_usb_types = ARRAY_SIZE(tps6598x_psy_usb_types);
tps->psy_desc.usb_types = BIT(POWER_SUPPLY_USB_TYPE_C) |
BIT(POWER_SUPPLY_USB_TYPE_PD);
tps->psy_desc.properties = tps6598x_psy_props;
tps->psy_desc.num_properties = ARRAY_SIZE(tps6598x_psy_props);
tps->psy_desc.get_property = tps6598x_psy_get_prop;
......
......@@ -254,12 +254,6 @@ static int ucsi_psy_get_prop(struct power_supply *psy,
}
}
static enum power_supply_usb_type ucsi_psy_usb_types[] = {
POWER_SUPPLY_USB_TYPE_C,
POWER_SUPPLY_USB_TYPE_PD,
POWER_SUPPLY_USB_TYPE_PD_PPS,
};
int ucsi_register_port_psy(struct ucsi_connector *con)
{
struct power_supply_config psy_cfg = {};
......@@ -276,8 +270,9 @@ int ucsi_register_port_psy(struct ucsi_connector *con)
con->psy_desc.name = psy_name;
con->psy_desc.type = POWER_SUPPLY_TYPE_USB;
con->psy_desc.usb_types = ucsi_psy_usb_types;
con->psy_desc.num_usb_types = ARRAY_SIZE(ucsi_psy_usb_types);
con->psy_desc.usb_types = BIT(POWER_SUPPLY_USB_TYPE_C) |
BIT(POWER_SUPPLY_USB_TYPE_PD) |
BIT(POWER_SUPPLY_USB_TYPE_PD_PPS);
con->psy_desc.properties = ucsi_psy_props;
con->psy_desc.num_properties = ARRAY_SIZE(ucsi_psy_props);
con->psy_desc.get_property = ucsi_psy_get_prop;
......
......@@ -115,8 +115,16 @@ enum axp20x_variants {
#define AXP313A_IRQ_STATE 0x21
#define AXP717_ON_INDICATE 0x00
#define AXP717_PMU_STATUS_2 0x01
#define AXP717_BC_DETECT 0x05
#define AXP717_PMU_FAULT 0x08
#define AXP717_MODULE_EN_CONTROL_1 0x0b
#define AXP717_MIN_SYS_V_CONTROL 0x15
#define AXP717_INPUT_VOL_LIMIT_CTRL 0x16
#define AXP717_INPUT_CUR_LIMIT_CTRL 0x17
#define AXP717_MODULE_EN_CONTROL_2 0x19
#define AXP717_BOOST_CONTROL 0x1e
#define AXP717_VSYS_V_POWEROFF 0x24
#define AXP717_IRQ0_EN 0x40
#define AXP717_IRQ1_EN 0x41
#define AXP717_IRQ2_EN 0x42
......@@ -127,6 +135,9 @@ enum axp20x_variants {
#define AXP717_IRQ2_STATE 0x4a
#define AXP717_IRQ3_STATE 0x4b
#define AXP717_IRQ4_STATE 0x4c
#define AXP717_ICC_CHG_SET 0x62
#define AXP717_ITERM_CHG_SET 0x63
#define AXP717_CV_CHG_SET 0x64
#define AXP717_DCDC_OUTPUT_CONTROL 0x80
#define AXP717_DCDC1_CONTROL 0x83
#define AXP717_DCDC2_CONTROL 0x84
......@@ -147,6 +158,19 @@ enum axp20x_variants {
#define AXP717_CLDO3_CONTROL 0x9d
#define AXP717_CLDO4_CONTROL 0x9e
#define AXP717_CPUSLDO_CONTROL 0x9f
#define AXP717_BATT_PERCENT_DATA 0xa4
#define AXP717_ADC_CH_EN_CONTROL 0xc0
#define AXP717_BATT_V_H 0xc4
#define AXP717_BATT_V_L 0xc5
#define AXP717_VBUS_V_H 0xc6
#define AXP717_VBUS_V_L 0xc7
#define AXP717_VSYS_V_H 0xc8
#define AXP717_VSYS_V_L 0xc9
#define AXP717_BATT_CHRG_I_H 0xca
#define AXP717_BATT_CHRG_I_L 0xcb
#define AXP717_ADC_DATA_SEL 0xcd
#define AXP717_ADC_DATA_H 0xce
#define AXP717_ADC_DATA_L 0xcf
#define AXP806_STARTUP_SRC 0x00
#define AXP806_CHIP_ID 0x03
......
......@@ -217,6 +217,10 @@ enum max77693_charger_battery_state {
#define CHG_CNFG_01_CHGRSTRT_MASK (0x3 << CHG_CNFG_01_CHGRSTRT_SHIFT)
#define CHG_CNFG_01_PQEN_MAKS BIT(CHG_CNFG_01_PQEN_SHIFT)
/* MAX77693_CHG_REG_CHG_CNFG_02 register */
#define CHG_CNFG_02_CC_SHIFT 0
#define CHG_CNFG_02_CC_MASK 0x3F
/* MAX77693_CHG_REG_CHG_CNFG_03 register */
#define CHG_CNFG_03_TOITH_SHIFT 0
#define CHG_CNFG_03_TOTIME_SHIFT 3
......@@ -244,6 +248,7 @@ enum max77693_charger_battery_state {
#define CHG_CNFG_12_VCHGINREG_MASK (0x3 << CHG_CNFG_12_VCHGINREG_SHIFT)
/* MAX77693 CHG_CNFG_09 Register */
#define CHG_CNFG_09_CHGIN_ILIM_SHIFT 0
#define CHG_CNFG_09_CHGIN_ILIM_MASK 0x7F
/* MAX77693 CHG_CTRL Register */
......
......@@ -243,8 +243,7 @@ struct power_supply_desc {
const char *name;
enum power_supply_type type;
u8 charge_behaviours;
const enum power_supply_usb_type *usb_types;
size_t num_usb_types;
u32 usb_types;
const enum power_supply_property *properties;
size_t num_properties;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment