Commit a10c9c71 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull power supply and reset changes from Sebastian Reichel:
 "Core:
   - Nothing

  Drivers:
   - at91-reset: cleanups, proper handling for sam9x60
   - sc27xx, charger-manager: allow building as module
   - sc27xx: add support to read current charge capacity
   - axp288: more quirks for weird hardware
   - misc fixes"

* tag 'for-v5.7' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply: (26 commits)
  power: reset: sc27xx: Allow the SC27XX poweroff driver building into a module
  power: reset: sc27xx: Change to use cpu_down()
  power: reset: sc27xx: Power off the external subsystems' connection
  power: twl4030: Use scnprintf() for avoiding potential buffer overflow
  power: supply: bq27xxx_battery: Silence deferred-probe error
  power: reset: at91-reset: handle nrst async for sam9x60
  power: reset: at91-reset: get rid of at91_reset_data
  power: reset: at91-reset: keep only one reset function
  power: reset: at91-reset: make at91sam9g45_restart() generic
  power: reset: at91-reset: introduce ramc_lpr to struct at91_reset
  power: reset: at91-reset: use r4 as tmp argument
  power: reset: at91-reset: introduce args member in at91_reset_data
  power: reset: at91-reset: introduce struct at91_reset_data
  power: reset: at91-reset: devm_kzalloc() for at91_reset data structure
  power: reset: at91-reset: pass rstc base address to at91_reset_status()
  power: reset: at91-reset: convert reset in pointer to struct at91_reset
  power: reset: at91-reset: add notifier block to struct at91_reset
  power: reset: at91-reset: add sclk to struct at91_reset
  power: reset: at91-reset: add ramc_base[] to struct at91_reset
  power: reset: at91-reset: introduce struct at91_reset
  ...
parents c48b0722 f78c55e3
......@@ -248,7 +248,7 @@ config SYSCON_REBOOT_MODE
action according to the mode.
config POWER_RESET_SC27XX
bool "Spreadtrum SC27xx PMIC power-off driver"
tristate "Spreadtrum SC27xx PMIC power-off driver"
depends on MFD_SC27XX_PMIC || COMPILE_TEST
help
This driver supports powering off a system through
......
......@@ -35,6 +35,7 @@
#define AT91_RSTC_MR 0x08 /* Reset Controller Mode Register */
#define AT91_RSTC_URSTEN BIT(0) /* User Reset Enable */
#define AT91_RSTC_URSTASYNC BIT(2) /* User Reset Asynchronous Control */
#define AT91_RSTC_URSTIEN BIT(4) /* User Reset Interrupt Enable */
#define AT91_RSTC_ERSTL GENMASK(11, 8) /* External Reset Length */
......@@ -49,105 +50,63 @@ enum reset_type {
RESET_TYPE_ULP2 = 8,
};
static void __iomem *at91_ramc_base[2], *at91_rstc_base;
static struct clk *sclk;
struct at91_reset {
void __iomem *rstc_base;
void __iomem *ramc_base[2];
struct clk *sclk;
struct notifier_block nb;
u32 args;
u32 ramc_lpr;
};
/*
* unless the SDRAM is cleanly shutdown before we hit the
* reset register it can be left driving the data bus and
* killing the chance of a subsequent boot from NAND
*/
static int at91sam9260_restart(struct notifier_block *this, unsigned long mode,
void *cmd)
static int at91_reset(struct notifier_block *this, unsigned long mode,
void *cmd)
{
asm volatile(
/* Align to cache lines */
".balign 32\n\t"
/* Disable SDRAM accesses */
"str %2, [%0, #" __stringify(AT91_SDRAMC_TR) "]\n\t"
/* Power down SDRAM */
"str %3, [%0, #" __stringify(AT91_SDRAMC_LPR) "]\n\t"
/* Reset CPU */
"str %4, [%1, #" __stringify(AT91_RSTC_CR) "]\n\t"
"b .\n\t"
:
: "r" (at91_ramc_base[0]),
"r" (at91_rstc_base),
"r" (1),
"r" cpu_to_le32(AT91_SDRAMC_LPCB_POWER_DOWN),
"r" cpu_to_le32(AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST));
struct at91_reset *reset = container_of(this, struct at91_reset, nb);
return NOTIFY_DONE;
}
static int at91sam9g45_restart(struct notifier_block *this, unsigned long mode,
void *cmd)
{
asm volatile(
/*
* Test wether we have a second RAM controller to care
* about.
*
* First, test that we can dereference the virtual address.
*/
"cmp %1, #0\n\t"
"beq 1f\n\t"
/* Then, test that the RAM controller is enabled */
"ldr r0, [%1]\n\t"
"cmp r0, #0\n\t"
/* Align to cache lines */
".balign 32\n\t"
/* Disable SDRAM0 accesses */
"1: str %3, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
" tst %0, #0\n\t"
" beq 1f\n\t"
" str %3, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
/* Power down SDRAM0 */
" str %4, [%0, #" __stringify(AT91_DDRSDRC_LPR) "]\n\t"
" str %4, [%0, %6]\n\t"
/* Disable SDRAM1 accesses */
"1: tst %1, #0\n\t"
" beq 2f\n\t"
" strne %3, [%1, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
/* Power down SDRAM1 */
" strne %4, [%1, #" __stringify(AT91_DDRSDRC_LPR) "]\n\t"
" strne %4, [%1, %6]\n\t"
/* Reset CPU */
" str %5, [%2, #" __stringify(AT91_RSTC_CR) "]\n\t"
"2: str %5, [%2, #" __stringify(AT91_RSTC_CR) "]\n\t"
" b .\n\t"
:
: "r" (at91_ramc_base[0]),
"r" (at91_ramc_base[1]),
"r" (at91_rstc_base),
: "r" (reset->ramc_base[0]),
"r" (reset->ramc_base[1]),
"r" (reset->rstc_base),
"r" (1),
"r" cpu_to_le32(AT91_DDRSDRC_LPCB_POWER_DOWN),
"r" cpu_to_le32(AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST)
: "r0");
return NOTIFY_DONE;
}
static int sama5d3_restart(struct notifier_block *this, unsigned long mode,
void *cmd)
{
writel(AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST,
at91_rstc_base);
"r" (reset->args),
"r" (reset->ramc_lpr)
: "r4");
return NOTIFY_DONE;
}
static int samx7_restart(struct notifier_block *this, unsigned long mode,
void *cmd)
{
writel(AT91_RSTC_KEY | AT91_RSTC_PROCRST, at91_rstc_base);
return NOTIFY_DONE;
}
static void __init at91_reset_status(struct platform_device *pdev)
static void __init at91_reset_status(struct platform_device *pdev,
void __iomem *base)
{
const char *reason;
u32 reg = readl(at91_rstc_base + AT91_RSTC_SR);
u32 reg = readl(base + AT91_RSTC_SR);
switch ((reg & AT91_RSTC_RSTTYP) >> 8) {
case RESET_TYPE_GENERAL:
......@@ -183,42 +142,68 @@ static void __init at91_reset_status(struct platform_device *pdev)
}
static const struct of_device_id at91_ramc_of_match[] = {
{ .compatible = "atmel,at91sam9260-sdramc", },
{ .compatible = "atmel,at91sam9g45-ddramc", },
{
.compatible = "atmel,at91sam9260-sdramc",
.data = (void *)AT91_SDRAMC_LPR,
},
{
.compatible = "atmel,at91sam9g45-ddramc",
.data = (void *)AT91_DDRSDRC_LPR,
},
{ /* sentinel */ }
};
static const struct of_device_id at91_reset_of_match[] = {
{ .compatible = "atmel,at91sam9260-rstc", .data = at91sam9260_restart },
{ .compatible = "atmel,at91sam9g45-rstc", .data = at91sam9g45_restart },
{ .compatible = "atmel,sama5d3-rstc", .data = sama5d3_restart },
{ .compatible = "atmel,samx7-rstc", .data = samx7_restart },
{ .compatible = "microchip,sam9x60-rstc", .data = samx7_restart },
{
.compatible = "atmel,at91sam9260-rstc",
.data = (void *)(AT91_RSTC_KEY | AT91_RSTC_PERRST |
AT91_RSTC_PROCRST),
},
{
.compatible = "atmel,at91sam9g45-rstc",
.data = (void *)(AT91_RSTC_KEY | AT91_RSTC_PERRST |
AT91_RSTC_PROCRST)
},
{
.compatible = "atmel,sama5d3-rstc",
.data = (void *)(AT91_RSTC_KEY | AT91_RSTC_PERRST |
AT91_RSTC_PROCRST)
},
{
.compatible = "atmel,samx7-rstc",
.data = (void *)(AT91_RSTC_KEY | AT91_RSTC_PROCRST)
},
{
.compatible = "microchip,sam9x60-rstc",
.data = (void *)(AT91_RSTC_KEY | AT91_RSTC_PROCRST)
},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, at91_reset_of_match);
static struct notifier_block at91_restart_nb = {
.priority = 192,
};
static int __init at91_reset_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
struct at91_reset *reset;
struct device_node *np;
int ret, idx = 0;
at91_rstc_base = of_iomap(pdev->dev.of_node, 0);
if (!at91_rstc_base) {
reset = devm_kzalloc(&pdev->dev, sizeof(*reset), GFP_KERNEL);
if (!reset)
return -ENOMEM;
reset->rstc_base = of_iomap(pdev->dev.of_node, 0);
if (!reset->rstc_base) {
dev_err(&pdev->dev, "Could not map reset controller address\n");
return -ENODEV;
}
if (!of_device_is_compatible(pdev->dev.of_node, "atmel,sama5d3-rstc")) {
/* we need to shutdown the ddr controller, so get ramc base */
for_each_matching_node(np, at91_ramc_of_match) {
at91_ramc_base[idx] = of_iomap(np, 0);
if (!at91_ramc_base[idx]) {
for_each_matching_node_and_match(np, at91_ramc_of_match, &match) {
reset->ramc_lpr = (u32)match->data;
reset->ramc_base[idx] = of_iomap(np, 0);
if (!reset->ramc_base[idx]) {
dev_err(&pdev->dev, "Could not map ram controller address\n");
of_node_put(np);
return -ENODEV;
......@@ -228,33 +213,46 @@ static int __init at91_reset_probe(struct platform_device *pdev)
}
match = of_match_node(at91_reset_of_match, pdev->dev.of_node);
at91_restart_nb.notifier_call = match->data;
reset->nb.notifier_call = at91_reset;
reset->nb.priority = 192;
reset->args = (u32)match->data;
sclk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(sclk))
return PTR_ERR(sclk);
reset->sclk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(reset->sclk))
return PTR_ERR(reset->sclk);
ret = clk_prepare_enable(sclk);
ret = clk_prepare_enable(reset->sclk);
if (ret) {
dev_err(&pdev->dev, "Could not enable slow clock\n");
return ret;
}
ret = register_restart_handler(&at91_restart_nb);
platform_set_drvdata(pdev, reset);
if (of_device_is_compatible(pdev->dev.of_node, "microchip,sam9x60-rstc")) {
u32 val = readl(reset->rstc_base + AT91_RSTC_MR);
writel(AT91_RSTC_KEY | AT91_RSTC_URSTASYNC | val,
reset->rstc_base + AT91_RSTC_MR);
}
ret = register_restart_handler(&reset->nb);
if (ret) {
clk_disable_unprepare(sclk);
clk_disable_unprepare(reset->sclk);
return ret;
}
at91_reset_status(pdev);
at91_reset_status(pdev, reset->rstc_base);
return 0;
}
static int __exit at91_reset_remove(struct platform_device *pdev)
{
unregister_restart_handler(&at91_restart_nb);
clk_disable_unprepare(sclk);
struct at91_reset *reset = platform_get_drvdata(pdev);
unregister_restart_handler(&reset->nb);
clk_disable_unprepare(reset->sclk);
return 0;
}
......
......@@ -6,6 +6,7 @@
#include <linux/cpu.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/regmap.h>
......@@ -13,6 +14,8 @@
#define SC27XX_PWR_PD_HW 0xc2c
#define SC27XX_PWR_OFF_EN BIT(0)
#define SC27XX_SLP_CTRL 0xdf0
#define SC27XX_LDO_XTL_EN BIT(3)
static struct regmap *regmap;
......@@ -27,10 +30,13 @@ static struct regmap *regmap;
*/
static void sc27xx_poweroff_shutdown(void)
{
#ifdef CONFIG_PM_SLEEP_SMP
int cpu = smp_processor_id();
#ifdef CONFIG_HOTPLUG_CPU
int cpu;
freeze_secondary_cpus(cpu);
for_each_online_cpu(cpu) {
if (cpu != smp_processor_id())
remove_cpu(cpu);
}
#endif
}
......@@ -40,6 +46,9 @@ static struct syscore_ops poweroff_syscore_ops = {
static void sc27xx_poweroff_do_poweroff(void)
{
/* Disable the external subsys connection's power firstly */
regmap_write(regmap, SC27XX_SLP_CTRL, SC27XX_LDO_XTL_EN);
regmap_write(regmap, SC27XX_PWR_PD_HW, SC27XX_PWR_OFF_EN);
}
......@@ -63,4 +72,8 @@ static struct platform_driver sc27xx_poweroff_driver = {
.name = "sc27xx-poweroff",
},
};
builtin_platform_driver(sc27xx_poweroff_driver);
module_platform_driver(sc27xx_poweroff_driver);
MODULE_DESCRIPTION("Power off driver for SC27XX PMIC Device");
MODULE_AUTHOR("Baolin Wang <baolin.wang@unisoc.com>");
MODULE_LICENSE("GPL v2");
......@@ -480,7 +480,7 @@ config CHARGER_GPIO
called gpio-charger.
config CHARGER_MANAGER
bool "Battery charger manager for multiple chargers"
tristate "Battery charger manager for multiple chargers"
depends on REGULATOR
select EXTCON
help
......
......@@ -404,7 +404,7 @@ static void ab8500_enable_disable_sw_fallback(struct ab8500_charger *di,
}
/**
* ab8500_power_supply_changed - a wrapper with local extentions for
* ab8500_power_supply_changed - a wrapper with local extensions for
* power_supply_changed
* @di: pointer to the ab8500_charger structure
* @psy: pointer to power_supply_that have changed.
......@@ -683,7 +683,7 @@ static int ab8500_charger_max_usb_curr(struct ab8500_charger *di,
/*
* Platform only supports USB 2.0.
* This means that charging current from USB source
* is maximum 500 mA. Every occurence of USB_STAT_*_HOST_*
* is maximum 500 mA. Every occurrence of USB_STAT_*_HOST_*
* should set USB_CH_IP_CUR_LVL_0P5.
*/
......@@ -1379,13 +1379,13 @@ static int ab8500_charger_ac_en(struct ux500_charger *charger,
/*
* Due to a bug in AB8500, BTEMP_HIGH/LOW interrupts
* will be triggered everytime we enable the VDD ADC supply.
* will be triggered every time we enable the VDD ADC supply.
* This will turn off charging for a short while.
* It can be avoided by having the supply on when
* there is a charger enabled. Normally the VDD ADC supply
* is enabled everytime a GPADC conversion is triggered. We will
* force it to be enabled from this driver to have
* the GPADC module independant of the AB8500 chargers
* is enabled every time a GPADC conversion is triggered.
* We will force it to be enabled from this driver to have
* the GPADC module independent of the AB8500 chargers
*/
if (!di->vddadc_en_ac) {
ret = regulator_enable(di->regu);
......@@ -1455,7 +1455,7 @@ static int ab8500_charger_ac_en(struct ux500_charger *charger,
if (is_ab8500_1p1_or_earlier(di->parent)) {
/*
* For ABB revision 1.0 and 1.1 there is a bug in the
* watchdog logic. That means we have to continously
* watchdog logic. That means we have to continuously
* kick the charger watchdog even when no charger is
* connected. This is only valid once the AC charger
* has been enabled. This is a bug that is not handled
......@@ -1552,13 +1552,13 @@ static int ab8500_charger_usb_en(struct ux500_charger *charger,
/*
* Due to a bug in AB8500, BTEMP_HIGH/LOW interrupts
* will be triggered everytime we enable the VDD ADC supply.
* will be triggered every time we enable the VDD ADC supply.
* This will turn off charging for a short while.
* It can be avoided by having the supply on when
* there is a charger enabled. Normally the VDD ADC supply
* is enabled everytime a GPADC conversion is triggered. We will
* force it to be enabled from this driver to have
* the GPADC module independant of the AB8500 chargers
* is enabled every time a GPADC conversion is triggered.
* We will force it to be enabled from this driver to have
* the GPADC module independent of the AB8500 chargers
*/
if (!di->vddadc_en_usb) {
ret = regulator_enable(di->regu);
......@@ -1582,7 +1582,10 @@ static int ab8500_charger_usb_en(struct ux500_charger *charger,
return -ENXIO;
}
/* ChVoltLevel: max voltage upto which battery can be charged */
/*
* ChVoltLevel: max voltage up to which battery can be
* charged
*/
ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER,
AB8500_CH_VOLT_LVL_REG, (u8) volt_index);
if (ret) {
......@@ -2014,7 +2017,7 @@ static void ab8500_charger_check_hw_failure_work(struct work_struct *work)
* Work queue function for kicking the charger watchdog.
*
* For ABB revision 1.0 and 1.1 there is a bug in the watchdog
* logic. That means we have to continously kick the charger
* logic. That means we have to continuously kick the charger
* watchdog even when no charger is connected. This is only
* valid once the AC charger has been enabled. This is
* a bug that is not handled by the algorithm and the
......@@ -2262,7 +2265,7 @@ static void ab8500_charger_usb_link_status_work(struct work_struct *work)
* Some chargers that breaks the USB spec is
* identified as invalid by AB8500 and it refuse
* to start the charging process. but by jumping
* thru a few hoops it can be forced to start.
* through a few hoops it can be forced to start.
*/
if (is_ab8500(di->parent))
ret = abx500_get_register_interruptible(di->dev, AB8500_USB,
......@@ -3214,7 +3217,7 @@ static int ab8500_charger_resume(struct platform_device *pdev)
/*
* For ABB revision 1.0 and 1.1 there is a bug in the watchdog
* logic. That means we have to continously kick the charger
* logic. That means we have to continuously kick the charger
* watchdog even when no charger is connected. This is only
* valid once the AC charger has been enabled. This is
* a bug that is not handled by the algorithm and the
......@@ -3483,7 +3486,7 @@ static int ab8500_charger_probe(struct platform_device *pdev)
/*
* For ABB revision 1.0 and 1.1 there is a bug in the watchdog
* logic. That means we have to continously kick the charger
* logic. That means we have to continuously kick the charger
* watchdog even when no charger is connected. This is only
* valid once the AC charger has been enabled. This is
* a bug that is not handled by the algorithm and the
......
......@@ -21,6 +21,7 @@
#include <linux/property.h>
#include <linux/mfd/axp20x.h>
#include <linux/extcon.h>
#include <linux/dmi.h>
#define PS_STAT_VBUS_TRIGGER BIT(0)
#define PS_STAT_BAT_CHRG_DIR BIT(2)
......@@ -545,6 +546,49 @@ static irqreturn_t axp288_charger_irq_thread_handler(int irq, void *dev)
return IRQ_HANDLED;
}
/*
* The HP Pavilion x2 10 series comes in a number of variants:
* Bay Trail SoC + AXP288 PMIC, DMI_BOARD_NAME: "815D"
* Cherry Trail SoC + AXP288 PMIC, DMI_BOARD_NAME: "813E"
* Cherry Trail SoC + TI PMIC, DMI_BOARD_NAME: "827C" or "82F4"
*
* The variants with the AXP288 PMIC are all kinds of special:
*
* 1. All variants use a Type-C connector which the AXP288 does not support, so
* when using a Type-C charger it is not recognized. Unlike most AXP288 devices,
* this model actually has mostly working ACPI AC / Battery code, the ACPI code
* "solves" this by simply setting the input_current_limit to 3A.
* There are still some issues with the ACPI code, so we use this native driver,
* and to solve the charging not working (500mA is not enough) issue we hardcode
* the 3A input_current_limit like the ACPI code does.
*
* 2. If no charger is connected the machine boots with the vbus-path disabled.
* Normally this is done when a 5V boost converter is active to avoid the PMIC
* trying to charge from the 5V boost converter's output. This is done when
* an OTG host cable is inserted and the ID pin on the micro-B receptacle is
* pulled low and the ID pin has an ACPI event handler associated with it
* which re-enables the vbus-path when the ID pin is pulled high when the
* OTG host cable is removed. The Type-C connector has no ID pin, there is
* no ID pin handler and there appears to be no 5V boost converter, so we
* end up not charging because the vbus-path is disabled, until we unplug
* the charger which automatically clears the vbus-path disable bit and then
* on the second plug-in of the adapter we start charging. To solve the not
* charging on first charger plugin we unconditionally enable the vbus-path at
* probe on this model, which is safe since there is no 5V boost converter.
*/
static const struct dmi_system_id axp288_hp_x2_dmi_ids[] = {
{
/*
* Bay Trail model has "Hewlett-Packard" as sys_vendor, Cherry
* Trail model has "HP", so we only match on product_name.
*/
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"),
},
},
{} /* Terminating entry */
};
static void axp288_charger_extcon_evt_worker(struct work_struct *work)
{
struct axp288_chrg_info *info =
......@@ -568,7 +612,11 @@ static void axp288_charger_extcon_evt_worker(struct work_struct *work)
}
/* Determine cable/charger type */
if (extcon_get_state(edev, EXTCON_CHG_USB_SDP) > 0) {
if (dmi_check_system(axp288_hp_x2_dmi_ids)) {
/* See comment above axp288_hp_x2_dmi_ids declaration */
dev_dbg(&info->pdev->dev, "HP X2 with Type-C, setting inlmt to 3A\n");
current_limit = 3000000;
} else if (extcon_get_state(edev, EXTCON_CHG_USB_SDP) > 0) {
dev_dbg(&info->pdev->dev, "USB SDP charger is connected\n");
current_limit = 500000;
} else if (extcon_get_state(edev, EXTCON_CHG_USB_CDP) > 0) {
......@@ -685,6 +733,13 @@ static int charger_init_hw_regs(struct axp288_chrg_info *info)
return ret;
}
if (dmi_check_system(axp288_hp_x2_dmi_ids)) {
/* See comment above axp288_hp_x2_dmi_ids declaration */
ret = axp288_charger_vbus_path_select(info, true);
if (ret < 0)
return ret;
}
/* Read current charge voltage and current limit */
ret = regmap_read(info->regmap, AXP20X_CHRG_CTRL1, &val);
if (ret < 0) {
......
......@@ -706,14 +706,14 @@ static const struct dmi_system_id axp288_fuel_gauge_blacklist[] = {
{
/* Intel Cherry Trail Compute Stick, Windows version */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
DMI_MATCH(DMI_SYS_VENDOR, "Intel"),
DMI_MATCH(DMI_PRODUCT_NAME, "STK1AW32SC"),
},
},
{
/* Intel Cherry Trail Compute Stick, version without an OS */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
DMI_MATCH(DMI_SYS_VENDOR, "Intel"),
DMI_MATCH(DMI_PRODUCT_NAME, "STK1A32SC"),
},
},
......
......@@ -1885,7 +1885,10 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
di->bat = power_supply_register_no_ws(di->dev, psy_desc, &psy_cfg);
if (IS_ERR(di->bat)) {
dev_err(di->dev, "failed to register battery\n");
if (PTR_ERR(di->bat) == -EPROBE_DEFER)
dev_dbg(di->dev, "failed to register battery, deferring probe\n");
else
dev_err(di->dev, "failed to register battery\n");
return PTR_ERR(di->bat);
}
......
......@@ -148,7 +148,8 @@ static int ingenic_battery_probe(struct platform_device *pdev)
bat->battery = devm_power_supply_register(dev, desc, &psy_cfg);
if (IS_ERR(bat->battery)) {
dev_err(dev, "Unable to register battery\n");
if (PTR_ERR(bat->battery) != -EPROBE_DEFER)
dev_err(dev, "Unable to register battery\n");
return PTR_ERR(bat->battery);
}
......
......@@ -614,6 +614,17 @@ static int sc27xx_fgu_get_property(struct power_supply *psy,
val->intval = data->total_cap * 1000;
break;
case POWER_SUPPLY_PROP_CHARGE_NOW:
ret = sc27xx_fgu_get_clbcnt(data, &value);
if (ret)
goto error;
value = DIV_ROUND_CLOSEST(value * 10,
36 * SC27XX_FGU_SAMPLE_HZ);
val->intval = sc27xx_fgu_adc_to_current(data, value);
break;
default:
ret = -EINVAL;
break;
......@@ -682,6 +693,7 @@ static enum power_supply_property sc27xx_fgu_props[] = {
POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
POWER_SUPPLY_PROP_CALIBRATE,
POWER_SUPPLY_PROP_CHARGE_NOW
};
static const struct power_supply_desc sc27xx_fgu_desc = {
......
......@@ -726,10 +726,10 @@ twl4030_bci_mode_show(struct device *dev,
for (i = 0; i < ARRAY_SIZE(modes); i++)
if (mode == i)
len += snprintf(buf+len, PAGE_SIZE-len,
len += scnprintf(buf+len, PAGE_SIZE-len,
"[%s] ", modes[i]);
else
len += snprintf(buf+len, PAGE_SIZE-len,
len += scnprintf(buf+len, PAGE_SIZE-len,
"%s ", modes[i]);
buf[len-1] = '\n';
return len;
......
......@@ -248,7 +248,7 @@ struct charger_manager {
u64 charging_end_time;
};
#ifdef CONFIG_CHARGER_MANAGER
#if IS_ENABLED(CONFIG_CHARGER_MANAGER)
extern void cm_notify_event(struct power_supply *psy,
enum cm_event_types type, char *msg);
#else
......
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