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
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Mon, 08 Aug 2022 11:05:16 +0100
From:   Yassine Oudjana <yassine.oudjana@...il.com>
To:     Krzysztof Kozlowski <krzysztof.kozlowski@...aro.org>
Cc:     Sebastian Reichel <sre@...nel.org>,
        Rob Herring <robh+dt@...nel.org>,
        Krzysztof Kozlowski <krzysztof.kozlowski+dt@...aro.org>,
        Andy Gross <agross@...nel.org>,
        Bjorn Andersson <bjorn.andersson@...aro.org>,
        Yassine Oudjana <y.oudjana@...tonmail.com>,
        Alejandro Tafalla <atafalla@...on.com>,
        Konrad Dybcio <konrad.dybcio@...ainline.org>,
        linux-pm@...r.kernel.org, linux-arm-msm@...r.kernel.org,
        devicetree@...r.kernel.org, phone-devel@...r.kernel.org,
        linux-kernel@...r.kernel.org
Subject: Re: [PATCH 8/8] power: supply: Add driver for Qualcomm SMBCHG


On Mon, Aug 8 2022 at 11:55:02 +03:00:00, Krzysztof Kozlowski 
<krzysztof.kozlowski@...aro.org> wrote:
> On 08/08/2022 10:34, Yassine Oudjana wrote:
>>  From: Yassine Oudjana <y.oudjana@...tonmail.com>
>> 
>>  Add a driver for the switch-mode battery charger found on
>>  PMICs such as PMI8994. This block is referred to in the vendor
>>  kernel[1] as smbcharger or SMBCHG. It has USB and DC inputs,
>>  and can generate VBUS for USB OTG with a boost regulator.
>>  It supports Qualcomm Quick Charge 2.0, and can operate along
>>  with a parallel charger (SMB1357, or SMB1351 for added Quick
>>  Charge 3.0 support) for improved efficiency at higher currents.
>> 
>>  At the moment, this driver supports charging off of the USB input
>>  at 5V with input current limit up to 3A. It also includes support
>>  for operating the OTG boost regulator as well as extcon
>>  functionality, reporting states of USB and USB_HOST with VBUS and
>>  charge port types.
>> 
>>  Co-developed-by: Alejandro Tafalla <atafalla@...on.com>
>>  Signed-off-by: Alejandro Tafalla <atafalla@...on.com>
>>  Signed-off-by: Yassine Oudjana <y.oudjana@...tonmail.com>
>> 
>>  [1] 
>> https://github.com/android-linux-stable/msm-3.18/blob/kernel.lnx.3.18.r34-rel/drivers/power/qpnp-smbcharger.c
>>  ---
>>   MAINTAINERS                        |    2 +
>>   drivers/power/supply/Kconfig       |   11 +
>>   drivers/power/supply/Makefile      |    1 +
>>   drivers/power/supply/qcom-smbchg.c | 1664 
>> ++++++++++++++++++++++++++++
>>   drivers/power/supply/qcom-smbchg.h |  428 +++++++
>>   5 files changed, 2106 insertions(+)
>>   create mode 100644 drivers/power/supply/qcom-smbchg.c
>>   create mode 100644 drivers/power/supply/qcom-smbchg.h
>> 
>>  diff --git a/MAINTAINERS b/MAINTAINERS
>>  index f6cf3a27d132..9b8693050890 100644
>>  --- a/MAINTAINERS
>>  +++ b/MAINTAINERS
>>  @@ -16964,6 +16964,8 @@ L:	linux-pm@...r.kernel.org
>>   L:	linux-arm-msm@...r.kernel.org
>>   S:	Maintained
>>   F:	Documentation/devicetree/bindings/power/supply/qcom,smbchg.yaml
>>  +F:	drivers/power/supply/qcom-smbchg.c
>>  +F:	drivers/power/supply/qcom-smbchg.h
>> 
>>   QUALCOMM TSENS THERMAL DRIVER
>>   M:	Amit Kucheria <amitk@...nel.org>
>>  diff --git a/drivers/power/supply/Kconfig 
>> b/drivers/power/supply/Kconfig
>>  index 1aa8323ad9f6..246bfc118d9f 100644
>>  --- a/drivers/power/supply/Kconfig
>>  +++ b/drivers/power/supply/Kconfig
>>  @@ -633,6 +633,17 @@ config CHARGER_QCOM_SMBB
>>   	  documentation for more detail.  The base name for this driver is
>>   	  'pm8941_charger'.
>> 
>>  +config CHARGER_QCOM_SMBCHG
>>  +	tristate "Qualcomm Switch-Mode Battery Charger"
> 
> As I mentioned in cover letter, this should be either squashed into
> Caleb's work, merged into some common part or kept separate but with
> clear explaining why it cannot be merged.
> 
> Some incomplete review follows:
> 
>>  +	depends on MFD_SPMI_PMIC || COMPILE_TEST
>>  +	depends on OF
>>  +	depends on EXTCON
>>  +	depends on REGULATOR
>>  +	select QCOM_PMIC_SEC_WRITE
>>  +	help
>>  +	  Say Y to include support for the Switch-Mode Battery Charger 
>> block
>>  +	  found in Qualcomm PMICs such as PMI8994.
>>  +
>>   config CHARGER_BQ2415X
>>   	tristate "TI BQ2415x battery charger driver"
>>   	depends on I2C
>>  diff --git a/drivers/power/supply/Makefile 
>> b/drivers/power/supply/Makefile
>>  index 7f02f36aea55..7c2c037cd8b1 100644
>>  --- a/drivers/power/supply/Makefile
>>  +++ b/drivers/power/supply/Makefile
>>  @@ -83,6 +83,7 @@ obj-$(CONFIG_CHARGER_MAX8998)	+= max8998_charger.o
>>   obj-$(CONFIG_CHARGER_MP2629)	+= mp2629_charger.o
>>   obj-$(CONFIG_CHARGER_MT6360)	+= mt6360_charger.o
>>   obj-$(CONFIG_CHARGER_QCOM_SMBB)	+= qcom_smbb.o
>>  +obj-$(CONFIG_CHARGER_QCOM_SMBCHG)	+= qcom-smbchg.o
>>   obj-$(CONFIG_CHARGER_BQ2415X)	+= bq2415x_charger.o
>>   obj-$(CONFIG_CHARGER_BQ24190)	+= bq24190_charger.o
>>   obj-$(CONFIG_CHARGER_BQ24257)	+= bq24257_charger.o
>>  diff --git a/drivers/power/supply/qcom-smbchg.c 
>> b/drivers/power/supply/qcom-smbchg.c
>>  new file mode 100644
>>  index 000000000000..23a9667953c9
>>  --- /dev/null
>>  +++ b/drivers/power/supply/qcom-smbchg.c
>>  @@ -0,0 +1,1664 @@
>>  +// SPDX-License-Identifier: GPL-2.0-only
> 
> Several things look like based from original sources, so please retain
> original copyright.

Do I replace the existing copyright here with the original one, just 
add it, or mention that this driver is based on downstream sources 
(maybe putting a link as well) then add it?

> 
>>  +/*
>>  + * Power supply driver for Qualcomm PMIC switch-mode battery 
>> charger
>>  + *
>>  + * Copyright (c) 2021 Yassine Oudjana <y.oudjana@...tonmail.com>
>>  + * Copyright (c) 2021 Alejandro Tafalla <atafalla@...on.com>
>>  + */
>>  +
>>  +#include <asm/unaligned.h>
>>  +#include <linux/errno.h>
>>  +#include <linux/extcon-provider.h>
>>  +#include <linux/kernel.h>
>>  +#include <linux/module.h>
>>  +#include <linux/of.h>
>>  +#include <linux/of_device.h>
>>  +#include <linux/of_irq.h>
>>  +#include <linux/interrupt.h>
>>  +#include <linux/platform_device.h>
>>  +#include <linux/power_supply.h>
>>  +#include <linux/regmap.h>
>>  +#include <linux/slab.h>
>>  +#include <linux/reboot.h>
>>  +#include <linux/regulator/driver.h>
>>  +#include <linux/util_macros.h>
>>  +#include <soc/qcom/pmic-sec-write.h>
>>  +
>>  +#include "qcom-smbchg.h"
>>  +
> 
> 
> (...)
> 
>>  +/**
>>  + * @brief smbchg_otg_enable() - Enable OTG regulator
>>  + *
>>  + * @param rdev Pointer to regulator_dev
>>  + * @return 0 on success, -errno on failure
>>  + */
>>  +static int smbchg_otg_enable(struct regulator_dev *rdev)
>>  +{
>>  +	struct smbchg_chip *chip = rdev_get_drvdata(rdev);
>>  +	int ret;
>>  +
>>  +	dev_dbg(chip->dev, "Enabling OTG VBUS regulator");
>>  +
>>  +	ret = regmap_update_bits(chip->regmap,
>>  +				 chip->base + SMBCHG_BAT_IF_CMD_CHG, OTG_EN_BIT,
>>  +				 OTG_EN_BIT);
>>  +	if (ret)
>>  +		dev_err(chip->dev, "Failed to enable OTG regulator: %pe\n",
>>  +			ERR_PTR(ret));
>>  +
>>  +	return ret;
>>  +}
>>  +
>>  +/**
>>  + * @brief smbchg_otg_disable() - Disable OTG regulator
>>  + *
>>  + * @param rdev Pointer to regulator_dev
>>  + * @return 0 on success, -errno on failure
>>  + */
>>  +static int smbchg_otg_disable(struct regulator_dev *rdev)
>>  +{
>>  +	struct smbchg_chip *chip = rdev_get_drvdata(rdev);
>>  +	int ret;
>>  +
>>  +	dev_dbg(chip->dev, "Disabling OTG VBUS regulator");
> 
> Here and in other places - no dbg messages replacing tracing. We have
> tracing for that.

Will look into it.

> 
>>  +
>>  +	ret = regmap_update_bits(chip->regmap,
>>  +				 chip->base + SMBCHG_BAT_IF_CMD_CHG, OTG_EN_BIT,
>>  +				 0);
>>  +	if (ret) {
>>  +		dev_err(chip->dev, "Failed to disable OTG regulator: %pe\n",
>>  +			ERR_PTR(ret));
>>  +		return ret;
>>  +	}
>>  +
>>  +	return 0;
>>  +}
>>  +
> 
> (...)
> 
>>  +static irqreturn_t smbchg_handle_charger_error(int irq, void *data)
>>  +{
>>  +	struct smbchg_chip *chip = data;
>>  +
>>  +	dev_err(chip->dev, "Charger error");
>>  +
>>  +	power_supply_changed(chip->usb_psy);
>>  +
>>  +	return IRQ_HANDLED;
>>  +}
>>  +
>>  +static irqreturn_t smbchg_handle_p2f(int irq, void *data)
>>  +{
>>  +	struct smbchg_chip *chip = data;
>>  +
>>  +	dev_dbg(chip->dev, "Fast charging threshold reached");
>>  +
>>  +	power_supply_changed(chip->usb_psy);
>>  +
>>  +	return IRQ_HANDLED;
> 
> Several interrupts which are exactly the same... no, use one interrupt
> handler for all such cases. Anyway I have some doubts about these 20 
> or
> more separate interrupt lines...

This was to allow for printing different debug messages. I believe 
there are interrupt status registers that can be used instead, so I 
might try to use them to find out the specific event in a single 
handler while adding tracing.

> 
>>  +}
>>  +
>>  +static irqreturn_t smbchg_handle_rechg(int irq, void *data)
>>  +{
>>  +	struct smbchg_chip *chip = data;
>>  +
>>  +	dev_dbg(chip->dev, "Recharge threshold reached");
>>  +
>>  +	/* Auto-recharge is enabled, nothing to do here */
>>  +	return IRQ_HANDLED;
>>  +}
>>  +
>>  +static irqreturn_t smbchg_handle_taper(int irq, void *data)
>>  +{
>>  +	struct smbchg_chip *chip = data;
>>  +
>>  +	dev_dbg(chip->dev, "Taper charging threshold reached");
>>  +
>>  +	power_supply_changed(chip->usb_psy);
>>  +
>>  +	return IRQ_HANDLED;
>>  +}
>>  +
>>  +static irqreturn_t smbchg_handle_tcc(int irq, void *data)
>>  +{
>>  +	struct smbchg_chip *chip = data;
>>  +
>>  +	dev_dbg(chip->dev, "Termination current reached");
>>  +
>>  +	power_supply_changed(chip->usb_psy);
>>  +
>>  +	return IRQ_HANDLED;
>>  +}
>>  +
>>  +static irqreturn_t smbchg_handle_batt_temp(int irq, void *data)
>>  +{
>>  +	struct smbchg_chip *chip = data;
>>  +
>>  +	power_supply_changed(chip->usb_psy);
>>  +
>>  +	return IRQ_HANDLED;
>>  +}
> 
> (...)
> 
>>  +
>>  +const struct smbchg_irq smbchg_irqs[] = {
> 
> You mix everywhere functions with static variables. All variables -
> except platform_driver related go to the beginning of the file.

They were grouped based on their topic (interrupt handling, power 
supply properties, ...). Will rearrange them.

> 
>>  +	{ "chg-error", smbchg_handle_charger_error },
>>  +	{ "chg-inhibit", NULL },
>>  +	{ "chg-prechg-sft", NULL },
>>  +	{ "chg-complete-chg-sft", NULL },
>>  +	{ "chg-p2f-thr", smbchg_handle_p2f },
>>  +	{ "chg-rechg-thr", smbchg_handle_rechg },
>>  +	{ "chg-taper-thr", smbchg_handle_taper },
>>  +	{ "chg-tcc-thr", smbchg_handle_tcc },
>>  +	{ "batt-hot", smbchg_handle_batt_temp },
>>  +	{ "batt-warm", smbchg_handle_batt_temp },
>>  +	{ "batt-cold", smbchg_handle_batt_temp },
>>  +	{ "batt-cool", smbchg_handle_batt_temp },
>>  +	{ "batt-ov", NULL },
>>  +	{ "batt-low", NULL },
>>  +	{ "batt-missing", smbchg_handle_batt_presence },
>>  +	{ "batt-term-missing", NULL },
>>  +	{ "usbin-uv", NULL },
>>  +	{ "usbin-ov", NULL },
>>  +	{ "usbin-src-det", smbchg_handle_usb_source_detect },
>>  +	{ "usbid-change", smbchg_handle_usbid_change },
>>  +	{ "otg-fail", smbchg_handle_otg_fail },
>>  +	{ "otg-oc", smbchg_handle_otg_oc },
>>  +	{ "aicl-done", smbchg_handle_aicl_done },
>>  +	{ "dcin-uv", NULL },
>>  +	{ "dcin-ov", NULL },
>>  +	{ "power-ok", NULL },
>>  +	{ "temp-shutdown", smbchg_handle_temp_shutdown },
>>  +	{ "wdog-timeout", NULL },
>>  +	{ "flash-fail", NULL },
>>  +	{ "otst2", NULL },
>>  +	{ "otst3", NULL },
>>  +};
>>  +
>>  +/**
> 
> (...)
> 
>>  +
>>  +static int smbchg_probe(struct platform_device *pdev)
>>  +{
>>  +	struct smbchg_chip *chip;
>>  +	struct regulator_config config = {};
>>  +	struct power_supply_config supply_config = {};
>>  +	int i, irq, ret;
>>  +
>>  +	chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
>>  +	if (!chip)
>>  +		return -ENOMEM;
>>  +
>>  +	chip->dev = &pdev->dev;
>>  +
>>  +	chip->regmap = dev_get_regmap(chip->dev->parent, NULL);
>>  +	if (!chip->regmap) {
>>  +		dev_err(chip->dev, "Failed to get regmap\n");
>>  +		return -ENODEV;
>>  +	}
>>  +
>>  +	ret = of_property_read_u32(chip->dev->of_node, "reg", 
>> &chip->base);
> 
> First: device_xxx

Okay.

> Second: what if address is bigger than u32? Shouldn't this be
> of_read_number or something similar in device_xxx API?

The address wouldn't exceed sizeof(u16). Actually now I think I 
should've used property_read_u16 instead. I couldn't find a device_* 
equivalent of of_read_number (or at least not a direct one), are you 
sure it exists?

> 
>>  +	if (ret) {
>>  +		dev_err(chip->dev, "Failed to get base address: %pe\n",
>>  +			ERR_PTR(ret));
>>  +		return ret;
>>  +	}
>>  +
>>  +	spin_lock_init(&chip->sec_access_lock);
>>  +	INIT_WORK(&chip->otg_reset_work, smbchg_otg_reset_worker);
>>  +
>>  +	/* Initialize OTG regulator */
>>  +	chip->otg_rdesc.id = -1;
>>  +	chip->otg_rdesc.name = "otg-vbus";
>>  +	chip->otg_rdesc.ops = &smbchg_otg_ops;
>>  +	chip->otg_rdesc.owner = THIS_MODULE;
>>  +	chip->otg_rdesc.type = REGULATOR_VOLTAGE;
>>  +	chip->otg_rdesc.of_match = "otg-vbus";
>>  +
>>  +	config.dev = chip->dev;
>>  +	config.driver_data = chip;
>>  +
>>  +	chip->otg_reg =
>>  +		devm_regulator_register(chip->dev, &chip->otg_rdesc, &config);
> 
> This wrapping is difficult to read.

This was done by clang-format. I don't mind changing it manually, but 
shouldn't it be conforming to the linux code style if it was done 
automatically following the .clang-format config file in the root of 
the kernel tree?

> 
>>  +	if (IS_ERR(chip->otg_reg)) {
>>  +		dev_err(chip->dev,
>>  +			"Failed to register OTG VBUS regulator: %pe\n",
>>  +			chip->otg_reg);
>>  +		return PTR_ERR(chip->otg_reg);
>>  +	}
>>  +
>>  +	chip->data = of_device_get_match_data(chip->dev);
>>  +
>>  +	supply_config.drv_data = chip;
>>  +	supply_config.of_node = pdev->dev.of_node;
>>  +	chip->usb_psy = devm_power_supply_register(
> 
> This wrapping is difficult to read.

Ditto.

> 
>>  +		chip->dev, &smbchg_usb_psy_desc, &supply_config);
>>  +	if (IS_ERR(chip->usb_psy)) {
>>  +		dev_err(chip->dev, "Failed to register USB power supply: %pe\n",
>>  +			chip->usb_psy);
>>  +		return PTR_ERR(chip->usb_psy);
>>  +	}
>>  +
>>  +	ret = power_supply_get_battery_info(chip->usb_psy, 
>> &chip->batt_info);
>>  +	if (ret) {
>>  +		dev_err(chip->dev, "Failed to get battery info: %pe\n",
>>  +			ERR_PTR(ret));
>>  +		return ret;
>>  +	}
>>  +
>>  +	if (chip->batt_info->voltage_max_design_uv == -EINVAL) {
>>  +		dev_err(chip->dev,
>>  +			"Battery info missing maximum design voltage\n");
>>  +		return -EINVAL;
>>  +	}
>>  +
>>  +	if (chip->batt_info->constant_charge_current_max_ua == -EINVAL) {
>>  +		dev_err(chip->dev,
>>  +			"Battery info missing maximum constant charge current\n");
>>  +		return -EINVAL;
>>  +	}
>>  +
>>  +	/* Initialize extcon */
>>  +	chip->edev = devm_extcon_dev_allocate(chip->dev, 
>> smbchg_extcon_cable);
>>  +	if (IS_ERR(chip->edev)) {
>>  +		dev_err(chip->dev, "Failed to allocate extcon device: %pe\n",
>>  +			chip->edev);
>>  +		return PTR_ERR(chip->edev);
>>  +	}
>>  +
>>  +	ret = devm_extcon_dev_register(chip->dev, chip->edev);
>>  +	if (ret) {
>>  +		dev_err(chip->dev, "Failed to register extcon device: %pe\n",
>>  +			ERR_PTR(ret));
>>  +		return ret;
>>  +	}
>>  +
>>  +	extcon_set_property_capability(chip->edev, EXTCON_USB,
>>  +				       EXTCON_PROP_USB_VBUS);
>>  +	extcon_set_property_capability(chip->edev, EXTCON_USB_HOST,
>>  +				       EXTCON_PROP_USB_VBUS);
>>  +
>>  +	/* Initialize charger */
>>  +	ret = smbchg_init(chip);
>>  +	if (ret)
>>  +		return ret;
>>  +
>>  +	/* Request IRQs */
>>  +	for (i = 0; i < ARRAY_SIZE(smbchg_irqs); ++i) {
>>  +		/* IRQ unused */
>>  +		if (!smbchg_irqs[i].handler)
>>  +			continue;
>>  +
>>  +		irq = of_irq_get_byname(pdev->dev.of_node, smbchg_irqs[i].name);
>>  +		if (irq < 0) {
>>  +			dev_err(chip->dev, "Failed to get %s IRQ: %pe\n",
>>  +				smbchg_irqs[i].name, ERR_PTR(irq));
>>  +			return irq;
>>  +		}
>>  +
>>  +		ret = devm_request_threaded_irq(chip->dev, irq, NULL,
>>  +						smbchg_irqs[i].handler,
>>  +						IRQF_ONESHOT,
>>  +						smbchg_irqs[i].name, chip);
>>  +		if (ret) {
>>  +			dev_err(chip->dev, "failed to request %s IRQ: %pe\n",
>>  +				smbchg_irqs[i].name, ERR_PTR(irq));
>>  +			return ret;
>>  +		}
>>  +	}
>>  +
>>  +	platform_set_drvdata(pdev, chip);
>>  +
>>  +	return 0;
>>  +}
>>  +
>>  +static int smbchg_remove(struct platform_device *pdev)
>>  +{
>>  +	struct smbchg_chip *chip = platform_get_drvdata(pdev);
>>  +
>>  +	smbchg_usb_enable(chip, false);
>>  +	smbchg_charging_enable(chip, false);
>>  +
>>  +	return 0;
>>  +}
>>  +
>>  +static const struct of_device_id smbchg_id_table[] = {
>>  +	{ .compatible = "qcom,pmi8994-smbchg", .data = 
>> &smbchg_pmi8994_data },
>>  +	{ .compatible = "qcom,pmi8996-smbchg", .data = 
>> &smbchg_pmi8996_data },
>>  +	{}
>>  +};
>>  +MODULE_DEVICE_TABLE(of, smbchg_id_table);
>>  +
>>  +static struct platform_driver smbchg_driver = {
>>  +	.probe = smbchg_probe,
>>  +	.remove = smbchg_remove,
>>  +	.driver = {
>>  +		.name = "qcom-smbchg",
>>  +		.of_match_table = smbchg_id_table,
>>  +	},
>>  +};
>>  +module_platform_driver(smbchg_driver);
>>  +
>>  +MODULE_AUTHOR("Yassine Oudjana <y.oudjana@...tonmail.com>");
>>  +MODULE_AUTHOR("Alejandro Tafalla <atafalla@...on.com>");
>>  +MODULE_DESCRIPTION("Qualcomm PMIC switch-mode battery charger 
>> driver");
>>  +MODULE_LICENSE("GPL");
>>  diff --git a/drivers/power/supply/qcom-smbchg.h 
>> b/drivers/power/supply/qcom-smbchg.h
>>  new file mode 100644
>>  index 000000000000..06445e10b4db
>>  --- /dev/null
>>  +++ b/drivers/power/supply/qcom-smbchg.h
>>  @@ -0,0 +1,428 @@
>>  +/* SPDX-License-Identifier: GPL-2.0-only */
>>  +
>>  +/* Registers */
>>  +/* CHGR */
>>  +#define SMBCHG_CHGR_FV_STS			0x00c
>>  +#define SMBCHG_CHGR_STS				0x00e
>>  +#define SMBCHG_CHGR_RT_STS			0x010
>>  +#define SMBCHG_CHGR_FCC_CFG			0x0f2
>>  +#define SMBCHG_CHGR_FCC_CMP_CFG			0x0f3
>>  +#define SMBCHG_CHGR_FV_CFG			0x0f4
>>  +#define SMBCHG_CHGR_FV_CMP			0x0f5
>>  +#define SMBCHG_CHGR_AFVC_CFG			0x0f6
>>  +#define SMBCHG_CHGR_CHG_INHIB_CFG		0x0f7
>>  +#define SMBCHG_CHGR_TCC_CFG			0x0f9
>>  +#define SMBCHG_CHGR_CCMP_CFG			0x0fa
>>  +#define SMBCHG_CHGR_CHGR_CFG1			0x0fb
>>  +#define SMBCHG_CHGR_CHGR_CFG2			0x0fc
>>  +#define SMBCHG_CHGR_SFT_CFG			0x0fd
>>  +#define SMBCHG_CHGR_CFG				0x0ff
>>  +
>>  +/* OTG */
>>  +#define SMBCHG_OTG_RT_STS			0x110
>>  +#define SMBCHG_OTG_OTG_CFG			0x1f1
>>  +#define SMBCHG_OTG_TRIM6			0x1f6
>>  +#define SMBCHG_OTG_LOW_PWR_OPTIONS		0x1ff
>>  +
>>  +/* BAT-IF */
>>  +#define SMBCHG_BAT_IF_BAT_PRES_STS		0x208
>>  +#define SMBCHG_BAT_IF_RT_STS			0x210
>>  +#define SMBCHG_BAT_IF_CMD_CHG			0x242
>>  +#define SMBCHG_BAT_IF_CMD_CHG_LED		0x243
>>  +#define SMBCHG_BAT_IF_BM_CFG			0x2f3
>>  +#define SMBCHG_BAT_IF_BAT_IF_TRIM7		0x2f7
>>  +#define SMBCHG_BAT_IF_BB_CLMP_SEL		0x2f8
>>  +#define SMBCHG_BAT_IF_ZIN_ICL_PT		0x2fc
>>  +#define SMBCHG_BAT_IF_ZIN_ICL_LV		0x2fd
>>  +#define SMBCHG_BAT_IF_ZIN_ICL_HV		0x2fe
>>  +
>>  +/* USB-CHGPTH */
>>  +#define SMBCHG_USB_CHGPTH_ICL_STS_1		0x307
>>  +#define SMBCHG_USB_CHGPTH_PWR_PATH		0x308
>>  +#define SMBCHG_USB_CHGPTH_ICL_STS_2		0x309
>>  +#define SMBCHG_USB_CHGPTH_RID_STS		0x30b
>>  +#define SMBCHG_USB_CHGPTH_USBIN_HVDCP_STS	0x30c
>>  +#define SMBCHG_USB_CHGPTH_INPUT_STS		0x30d
>>  +#define SMBCHG_USB_CHGPTH_USBID_MSB		0x30e
>>  +#define SMBCHG_USB_CHGPTH_RT_STS		0x310
>>  +#define SMBCHG_USB_CHGPTH_CMD_IL		0x340
>>  +#define SMBCHG_USB_CHGPTH_CMD_APSD		0x341
>>  +#define SMBCHG_USB_CHGPTH_CMD_HVDCP_1		0x342
>>  +#define SMBCHG_USB_CHGPTH_CMD_HVDCP_2		0x343
>>  +#define SMBCHG_USB_CHGPTH_USBIN_CHGR_CFG	0x3f1
>>  +#define SMBCHG_USB_CHGPTH_IL_CFG		0x3f2
>>  +#define SMBCHG_USB_CHGPTH_AICL_CFG		0x3f3
>>  +#define SMBCHG_USB_CHGPTH_CFG			0x3f4
>>  +#define SMBCHG_USB_CHGPTH_APSD_CFG		0x3f5
>>  +#define SMBCHG_USB_CHGPTH_TR_RID		0x3fa
>>  +#define SMBCHG_USB_CHGPTH_ICL_BUF_CONFIG	0x3fc
>>  +#define SMBCHG_USB_CHGPTH_TR_8OR32B		0x3fe
>>  +
>>  +/* DC-CHGPTH */
>>  +#define SMBCHG_DC_CHGPTH_RT_STS			0x410
>>  +#define SMBCHG_DC_CHGPTH_IL_CFG			0x4f2
>>  +#define SMBCHG_DC_CHGPTH_AICL_CFG		0x4f3
>>  +#define SMBCHG_DC_CHGPTH_AICL_WL_SEL_CFG	0x4f5
>>  +
>>  +/* MISC */
>>  +#define SMBCHG_MISC_REVISION1			0x600
>>  +#define SMBCHG_MISC_IDEV_STS			0x608
>>  +#define SMBCHG_MISC_RT_STS			0x610
>>  +#define SMBCHG_MISC_TEST			0x6e2
>>  +#define SMBCHG_MISC_NTC_VOUT_CFG		0x6f3
>>  +#define SMBCHG_MISC_TRIM_OPT_15_8		0x6f5
>>  +#define SMBCHG_MISC_TRIM_OPT_7_0		0x6f6
>>  +#define SMBCHG_MISC_TRIM_14			0x6fe
>>  +
>>  +/* Bits */
>>  +/* CHGR_STS bits */
>>  +#define CHG_TYPE_MASK			GENMASK(2, 1)
>>  +#define CHG_HOLD_OFF_BIT		BIT(3)\
>>  +
>>  +/* CHGR_FCC_CFG bits */
>>  +#define FCC_MASK			GENMASK(4, 0)
>>  +
>>  +/* CHGR_RT_STS bits */
>>  +#define CHG_INHIBIT_BIT			BIT(1)
>>  +#define CHG_COMP_SFT_BIT		BIT(3)
>>  +#define BAT_TCC_REACHED_BIT		BIT(7)
>>  +
>>  +/* CHGR_FV_CFG bits */
>>  +#define FV_MASK				GENMASK(5, 0)
>>  +
>>  +/* CHGR_TCC_CFG bits */
>>  +#define CHG_ITERM_MASK			GENMASK(2, 0)
>>  +
>>  +/* CHGR_CHGR_CFG1 bits */
>>  +#define RECHG_THRESHOLD_SRC_BIT		BIT(1)
>>  +#define TERM_I_SRC_BIT			BIT(2)
>>  +
>>  +/* CHGR_CHGR_CFG2 bits */
>>  +#define CHARGER_INHIBIT_BIT		BIT(0)
>>  +#define AUTO_RECHG_BIT			BIT(2)
>>  +#define I_TERM_BIT			BIT(3)
>>  +#define P2F_CHG_TRAN_BIT		BIT(5)
>>  +#define CHG_EN_POLARITY_BIT		BIT(6)
>>  +#define CHG_EN_SRC_BIT			BIT(7)
>>  +
>>  +/* CHGR_CFG bits */
>>  +#define RCHG_LVL_BIT			BIT(0)
>>  +
>>  +/* BAT_IF_CMD_CHG bits */
>>  +#define OTG_EN_BIT			BIT(0)
>>  +#define CHG_EN_BIT			BIT(1)
>>  +
>>  +/* BAT_IF_RT_STS bits */
>>  +#define HOT_BAT_HARD_BIT		BIT(0)
>>  +#define HOT_BAT_SOFT_BIT		BIT(1)
>>  +#define COLD_BAT_HARD_BIT		BIT(2)
>>  +#define COLD_BAT_SOFT_BIT		BIT(3)
>>  +#define BAT_OV_BIT			BIT(4)
>>  +#define BAT_LOW_BIT			BIT(5)
>>  +#define BAT_MISSING_BIT			BIT(6)
>>  +#define BAT_TERM_MISSING_BIT		BIT(7)
>>  +
>>  +/* USB_CHGPTH_ICL_STS_1 bits */
>>  +#define ICL_STS_MASK			GENMASK(4, 0)
>>  +#define AICL_STS_BIT			BIT(5)
>>  +#define AICL_SUSP_BIT			BIT(6)
>>  +
>>  +/* USB_CHGPTH_CFG bits */
>>  +#define USB51AC_CTRL			BIT(1)
>>  +#define USB51_COMMAND_POL		BIT(2)
>>  +#define CFG_USB3P0_SEL_BIT		BIT(7)
>>  +
>>  +/* USB_CHGPTH_RT_STS bits */
>>  +#define USBIN_OV_BIT			BIT(1)
>>  +#define USBIN_SRC_DET_BIT		BIT(2)
>>  +
>>  +/* USB_CHGPTH_RID_STS bits */
>>  +#define RID_MASK			GENMASK(3, 0)
>>  +
>>  +/* USB_CHGPTH_CMD_IL bits */
>>  +#define USBIN_MODE_HC_BIT		BIT(0)
>>  +#define USB51_MODE_BIT			BIT(1)
>>  +#define ICL_OVERRIDE_BIT		BIT(2)
>>  +#define USBIN_SUSPEND_BIT		BIT(4)
>>  +
>>  +/* USB_CHGPTH_IL_CFG bits */
>>  +#define USBIN_INPUT_MASK		GENMASK(4, 0)
>>  +
>>  +/* USB_CHGPTH_AICL_CFG bits */
>>  +#define USB_CHGPTH_AICL_EN		BIT(2)
>>  +
>>  +/* USB_CHGPTH_APSD_CFG bits */
>>  +#define USB_CHGPTH_APSD_EN		BIT(0)
>>  +
>>  +/* MISC_IDEV_STS bits */
>>  +#define FMB_STS_MASK			GENMASK(3, 0)
>>  +
>>  +/* MISC_TRIM_OPT_15_8 bits */
>>  +#define AICL_RERUN_MASK			GENMASK(5, 4)
>>  +#define AICL_RERUN_DC_BIT		BIT(4)
>>  +#define AICL_RERUN_USB_BIT		BIT(5)
>>  +
>>  +/* Values */
>>  +/* CHGR_STS values */
>>  +#define CHG_TYPE_SHIFT			1
>>  +#define BATT_NOT_CHG_VAL		0x0
>>  +#define BATT_PRE_CHG_VAL		0x1
>>  +#define BATT_FAST_CHG_VAL		0x2
>>  +#define BATT_TAPER_CHG_VAL		0x3
>>  +
>>  +/* CHGR_CHGR_CFG1 values */
>>  +#define	RCHG_SRC_ANA			0
>>  +#define RCHG_SRC_FG			BIT(1)
>>  +#define TERM_SRC_ANA			0
>>  +#define TERM_SRC_FG			BIT(2)
>>  +
>>  +/* CHGR_CHGR_CFG2 values */
>>  +#define CHG_INHIBIT_DIS			0
>>  +#define CHG_INHIBIT_EN			BIT(0)
>>  +#define AUTO_RCHG_EN			0
>>  +#define AUTO_RCHG_DIS			BIT(2)
>>  +#define CURRENT_TERM_EN			0
>>  +#define CURRENT_TERM_DIS		BIT(3)
>>  +#define PRE_FAST_AUTO			0
>>  +#define PRE_FAST_CMD			BIT(5)
>>  +#define CHG_EN_SRC_CMD			0
>>  +#define CHG_EN_SRC_PIN			BIT(7)
>>  +
>>  +/* CHGR_CFG values */
>>  +#define RCHG_THRESH_100MV		0
>>  +#define RCHG_THRESH_200MV		BIT(0)
>>  +
>>  +/* USB_CHGPTH_INPUT_STS values */
>>  +#define USBIN_9V			BIT(5)
>>  +#define USBIN_UNREG			BIT(4)
>>  +#define USBIN_LV			BIT(3)
>>  +
>>  +/* USB_CHGPTH_USBID_MSB values */
>>  +#define USBID_GND_THRESHOLD		0x495
>>  +
>>  +/* USB_CHGPTH_CFG values */
>>  +#define USB51_COMMAND_CONTROL		0
>>  +#define USB51_PIN_CONTROL		BIT(1)
>>  +#define USB51AC_COMMAND1_500		0
>>  +#define USB51AC_COMMAND1_100		BIT(2)
>>  +#define USB_2P0_SEL			0
>>  +#define USB_3P0_SEL			BIT(7)
>>  +
>>  +/* MISC_IDEV_STS values */
>>  +#define USB_TYPE_SDP_BIT		BIT(4)
>>  +#define USB_TYPE_OTHER_BIT		BIT(5)
>>  +#define USB_TYPE_DCP_BIT		BIT(6)
>>  +#define USB_TYPE_CDP_BIT		BIT(7)
>>  +
>>  +/* Constant parameters */
>>  +#define NUM_OTG_RESET_RETRIES		5
>>  +#define OTG_RESET_DELAY_MS		20
>>  +
>>  +/*
>>  + * These values can be indexed using a bitmask:
>>  + * 0: USB 2.0/3.0
>>  + * 1: Limited/full current
>>  + */
>>  +static const int smbchg_lc_ilim_options[] = {
>>  +	[0b00] = 100000,
>>  +	[0b01] = 150000,
>>  +	[0b10] = 500000,
>>  +	[0b11] = 900000
>>  +};
>>  +#define LC_ILIM_USB3_BIT		BIT(0)
>>  +#define LC_ILIM_FULL_CURRENT_BIT	BIT(1)
>>  +#define smbchg_lc_ilim(usb_3, full_current) 
>> smbchg_lc_ilim_options[usb_3 | full_current << 1]
>>  +
>>  +struct smbchg_chip {
>>  +	unsigned int base;
>>  +	struct device *dev;
>>  +	struct regmap *regmap;
>>  +
>>  +	struct power_supply_battery_info *batt_info;
>>  +	struct power_supply *usb_psy;
>>  +
>>  +	struct regulator_desc otg_rdesc;
>>  +	struct regulator_dev *otg_reg;
>>  +	int otg_resets;
>>  +
>>  +	struct extcon_dev *edev;
>>  +
>>  +	spinlock_t sec_access_lock;
>>  +	struct work_struct otg_reset_work;
>>  +
>>  +	const struct smbchg_data *data;
>>  +};
>>  +
>>  +struct smbchg_irq {
>>  +	const char *name;
>>  +	irq_handler_t handler;
>>  +};
>>  +
>>  +struct smbchg_data {
>>  +	const int *iterm_table;
>>  +	unsigned int iterm_table_len;
>>  +	const int *ilim_table;
>>  +	unsigned int ilim_table_len;
>>  +
>>  +	bool reset_otg_on_oc;
>>  +};
>>  +
>>  +static const int smbchg_fv_table[] = {
> 
> No static data in headers.

Understood.

> 
> Best regards,
> Krzysztof


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ