lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Message-ID: <aEifg/+mIuVVm6El@lizhi-Precision-Tower-5810> Date: Tue, 10 Jun 2025 17:11:31 -0400 From: Frank Li <Frank.li@....com> To: Samuel Kayode <samuel.kayode@...oirfairelinux.com> Cc: Lee Jones <lee@...nel.org>, Rob Herring <robh@...nel.org>, Krzysztof Kozlowski <krzk+dt@...nel.org>, Conor Dooley <conor+dt@...nel.org>, Liam Girdwood <lgirdwood@...il.com>, Mark Brown <broonie@...nel.org>, Dmitry Torokhov <dmitry.torokhov@...il.com>, Sebastian Reichel <sre@...nel.org>, devicetree@...r.kernel.org, linux-kernel@...r.kernel.org, linux-input@...r.kernel.org, linux-pm@...r.kernel.org, Abel Vesa <abelvesa@...nel.org>, Abel Vesa <abelvesa@...ux.com>, Robin Gong <b38343@...escale.com>, Robin Gong <yibin.gong@....com>, Enric Balletbo i Serra <eballetbo@...il.com> Subject: Re: [PATCH v5 5/6] power: supply: pf1550: add battery charger support On Tue, Jun 10, 2025 at 03:47:33PM -0400, Samuel Kayode wrote: > Add support for the battery charger for pf1550 PMIC. > > Signed-off-by: Samuel Kayode <samuel.kayode@...oirfairelinux.com> > --- > v5: > - Drop lock for battery and charger delayed_work > - More conservative locking in vbus delayed_work > - Apply lock when setting power supply type during register initialization > v4: > - Finish handling of some interrupts in threaded irq handler > - Use platform_get_irq > v3: > - Use struct power_supply_get_battery_info to get constant charge > voltage if specified > - Use virqs mapped in MFD driver > v2: > - Address feedback from Enric Balletbo Serra > --- > drivers/power/supply/Kconfig | 11 + > drivers/power/supply/Makefile | 1 + > drivers/power/supply/pf1550-charger.c | 645 ++++++++++++++++++++++++++++++++++ > 3 files changed, 657 insertions(+) > > diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig > index 79ddb006e2dad6bf96b71ed570a37c006b5f9433..6d0c872edac1f45da314632e671af1aeda4c87b8 100644 > --- a/drivers/power/supply/Kconfig > +++ b/drivers/power/supply/Kconfig > @@ -471,6 +471,17 @@ config CHARGER_88PM860X > help > Say Y here to enable charger for Marvell 88PM860x chip. > > +config CHARGER_PF1550 > + tristate "NXP PF1550 battery charger driver" > + depends on MFD_PF1550 > + help > + Say Y to enable support for the NXP PF1550 battery charger. > + The device is a single cell Li-Ion/Li-Polymer battery charger for > + portable application. > + > + This driver can also be built as a module. If so, the module will be > + called pf1550-charger. > + > config BATTERY_RX51 > tristate "Nokia RX-51 (N900) battery driver" > depends on TWL4030_MADC > diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile > index 4f5f8e3507f80da02812f0d08c2d81ddff0a272f..7f68380099c59dab71b73120150612a23e16a745 100644 > --- a/drivers/power/supply/Makefile > +++ b/drivers/power/supply/Makefile > @@ -64,6 +64,7 @@ obj-$(CONFIG_CHARGER_RT9467) += rt9467-charger.o > obj-$(CONFIG_CHARGER_RT9471) += rt9471.o > obj-$(CONFIG_BATTERY_TWL4030_MADC) += twl4030_madc_battery.o > obj-$(CONFIG_CHARGER_88PM860X) += 88pm860x_charger.o > +obj-$(CONFIG_CHARGER_PF1550) += pf1550-charger.o > obj-$(CONFIG_BATTERY_RX51) += rx51_battery.o > obj-$(CONFIG_AB8500_BM) += ab8500_bmdata.o ab8500_charger.o ab8500_fg.o ab8500_btemp.o ab8500_chargalg.o > obj-$(CONFIG_CHARGER_CPCAP) += cpcap-charger.o > diff --git a/drivers/power/supply/pf1550-charger.c b/drivers/power/supply/pf1550-charger.c > new file mode 100644 > index 0000000000000000000000000000000000000000..04da5bd115657980c8eac462a9c33a42f6b94be7 > --- /dev/null > +++ b/drivers/power/supply/pf1550-charger.c > @@ -0,0 +1,645 @@ > +// SPDX-License-Identifier: GPL-2.0 > +// > +// pf1550_charger.c - charger driver for the PF1550 > +// > +// Copyright (C) 2016 Freescale Semiconductor, Inc. > +// Robin Gong <yibin.gong@...escale.com> > +// > +// Portions Copyright (c) 2025 Savoir-faire Linux Inc. > +// Samuel Kayode <samuel.kayode@...oirfairelinux.com> > +// > + > +#include <linux/interrupt.h> > +#include <linux/mfd/pf1550.h> > +#include <linux/module.h> > +#include <linux/platform_device.h> > +#include <linux/power_supply.h> > + > +#define PF1550_CHARGER_NAME "pf1550-charger" > +#define PF1550_DEFAULT_CONSTANT_VOLT 4200000 > +#define PF1550_DEFAULT_MIN_SYSTEM_VOLT 3500000 > +#define PF1550_DEFAULT_THERMAL_TEMP 75 > +#define PF1550_CHARGER_IRQ_NR 5 > + > +static const char *pf1550_charger_model = "PF1550"; > +static const char *pf1550_charger_manufacturer = "NXP"; > + > +struct pf1550_charger { > + struct device *dev; > + const struct pf1550_dev *pf1550; > + struct power_supply *charger; > + struct power_supply_desc psy_desc; > + struct delayed_work vbus_sense_work; > + struct delayed_work chg_sense_work; > + struct delayed_work bat_sense_work; > + struct mutex mutex; > + > + u32 constant_volt; > + u32 min_system_volt; > + u32 thermal_regulation_temp; > +}; > + ... > + > +static void pf1550_chg_vbus_work(struct work_struct *work) > +{ > + struct pf1550_charger *chg = container_of(to_delayed_work(work), > + struct pf1550_charger, > + vbus_sense_work); > + unsigned int data; > + bool psy_changed = false; > + > + if (!chg->charger) > + return; > + > + if (regmap_read(chg->pf1550->regmap, PF1550_CHARG_REG_VBUS_SNS, &data)) { > + dev_err(chg->dev, "Read VBUS_SNS error.\n"); > + return; > + } > + > + mutex_lock(&chg->mutex); > + > + if (data & PF1550_VBUS_UVLO) { > + chg->psy_desc.type = POWER_SUPPLY_TYPE_BATTERY; > + psy_changed = true; > + dev_dbg(chg->dev, "VBUS detached.\n"); > + } > + if (data & PF1550_VBUS_IN2SYS) > + dev_dbg(chg->dev, "VBUS_IN2SYS_SNS.\n"); > + if (data & PF1550_VBUS_OVLO) > + dev_dbg(chg->dev, "VBUS_OVLO_SNS.\n"); > + if (data & PF1550_VBUS_VALID) { > + chg->psy_desc.type = POWER_SUPPLY_TYPE_MAINS; > + psy_changed = true; > + dev_dbg(chg->dev, "VBUS attached.\n"); > + } > + > + mutex_unlock(&chg->mutex); not sure why need lock here, you just update chg->psy_desc.type? > + > + if (psy_changed) > + power_supply_changed(chg->charger); > +} > + > +static irqreturn_t pf1550_charger_irq_handler(int irq, void *data) > +{ > + struct pf1550_charger *chg = data; > + struct device *dev = chg->dev; > + struct platform_device *pdev = to_platform_device(dev); > + int i, irq_type = -1; > + > + for (i = 0; i < PF1550_CHARGER_IRQ_NR; i++) > + if (irq == platform_get_irq(pdev, i)) > + irq_type = i; > + > + switch (irq_type) { > + case PF1550_CHARG_IRQ_BAT2SOCI: > + dev_info(dev, "BAT to SYS Overcurrent interrupt.\n"); > + break; > + case PF1550_CHARG_IRQ_BATI: > + schedule_delayed_work(&chg->bat_sense_work, > + msecs_to_jiffies(10)); > + break; > + case PF1550_CHARG_IRQ_CHGI: > + schedule_delayed_work(&chg->chg_sense_work, > + msecs_to_jiffies(10)); > + break; > + case PF1550_CHARG_IRQ_VBUSI: > + schedule_delayed_work(&chg->vbus_sense_work, > + msecs_to_jiffies(10)); > + break; > + case PF1550_CHARG_IRQ_THMI: > + dev_info(dev, "Thermal interrupt.\n"); > + break; > + default: > + dev_err(dev, "unknown interrupt occurred.\n"); > + } > + > + return IRQ_HANDLED; > +} > + ... > + > +static int pf1550_charger_probe(struct platform_device *pdev) > +{ > + struct pf1550_charger *chg; > + struct power_supply_config psy_cfg = {}; > + const struct pf1550_dev *pf1550 = dev_get_drvdata(pdev->dev.parent); maintain reverise christmas tree order look little big better. > + int i, irq, ret; > + > + chg = devm_kzalloc(&pdev->dev, sizeof(*chg), GFP_KERNEL); > + if (!chg) > + return -ENOMEM; > + > + chg->dev = &pdev->dev; > + chg->pf1550 = pf1550; > + > + if (!chg->pf1550->regmap) > + return dev_err_probe(&pdev->dev, -ENODEV, > + "failed to get regmap\n"); > + > + platform_set_drvdata(pdev, chg); > + > + mutex_init(&chg->mutex); > + > + INIT_DELAYED_WORK(&chg->vbus_sense_work, pf1550_chg_vbus_work); > + INIT_DELAYED_WORK(&chg->chg_sense_work, pf1550_chg_chg_work); > + INIT_DELAYED_WORK(&chg->bat_sense_work, pf1550_chg_bat_work); > + > + for (i = 0; i < PF1550_CHARGER_IRQ_NR; i++) { > + irq = platform_get_irq(pdev, i); > + if (irq < 0) > + return irq; > + > + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, > + pf1550_charger_irq_handler, > + IRQF_NO_SUSPEND, > + "pf1550-charger", chg); > + if (ret) > + return dev_err_probe(&pdev->dev, ret, > + "failed irq request\n"); > + } > + > + psy_cfg.drv_data = chg; > + > + chg->psy_desc.name = PF1550_CHARGER_NAME; > + chg->psy_desc.type = POWER_SUPPLY_TYPE_BATTERY; > + chg->psy_desc.get_property = pf1550_charger_get_property; > + chg->psy_desc.properties = pf1550_charger_props; > + chg->psy_desc.num_properties = ARRAY_SIZE(pf1550_charger_props); > + > + chg->charger = devm_power_supply_register(&pdev->dev, &chg->psy_desc, > + &psy_cfg); > + if (IS_ERR(chg->charger)) > + return dev_err_probe(&pdev->dev, PTR_ERR(chg->charger), > + "failed: power supply register\n"); > + > + pf1550_dt_parse_dev_info(chg); > + > + ret = pf1550_reg_init(chg); > + > + return ret; return pf1550_reg_init(chg); Frank > +} > + > +static void pf1550_charger_remove(struct platform_device *pdev) > +{ > + struct pf1550_charger *chg = platform_get_drvdata(pdev); > + > + cancel_delayed_work_sync(&chg->bat_sense_work); > + cancel_delayed_work_sync(&chg->chg_sense_work); > + cancel_delayed_work_sync(&chg->vbus_sense_work); > +} > + > +static const struct platform_device_id pf1550_charger_id[] = { > + { "pf1550-charger", 0 }, > + { /* sentinel */ } > +}; > +MODULE_DEVICE_TABLE(platform, pf1550_charger_id); > + > +static struct platform_driver pf1550_charger_driver = { > + .driver = { > + .name = "pf1550-charger", > + }, > + .probe = pf1550_charger_probe, > + .remove = pf1550_charger_remove, > + .id_table = pf1550_charger_id, > +}; > +module_platform_driver(pf1550_charger_driver); > + > +MODULE_AUTHOR("Robin Gong <yibin.gong@...escale.com>"); > +MODULE_DESCRIPTION("PF1550 charger driver"); > +MODULE_LICENSE("GPL"); > > -- > 2.49.0 >
Powered by blists - more mailing lists