* [PATCH v3 0/7] Add MAX77643/MAX77654/MAX77658/MAX77659 PMIC Support
@ 2023-05-08 13:10 Zeynep Arslanbenzer
2023-05-08 13:10 ` [PATCH v3 1/7] regulator: max77658: Add ADI MAX77643/54/58/59 Regulator Support Zeynep Arslanbenzer
` (6 more replies)
0 siblings, 7 replies; 22+ messages in thread
From: Zeynep Arslanbenzer @ 2023-05-08 13:10 UTC (permalink / raw)
To: lee, robh+dt, krzysztof.kozlowski+dt, sre, lgirdwood, broonie
Cc: Zeynep.Arslanbenzer, linux-kernel, devicetree, linux-pm
Changes in v3:
* Remove regulator adi,max77658-regulator.yaml
* Patch 1: "mfd: max77658: Add ADI MAX77643/54/58/59 MFD Support"
* Use MAX77643/54/58/59 instead of listing every device
* Move max77658_pmic_setup function body to probe function
* Remove dev from max77658_dev struct
* Fix error explanations
* Drop chip structure, use only id
* Fix the wrong indentations
* Patch 2: "dt-bindings: mfd: max77658: Add ADI MAX77658"
* Decrease the example count
* Patch 3: "power: supply: max77658: Add ADI MAX77658 Battery Support"
* Use default values to initialize SALRT min-max thresholds
* Patch 4: "dt-bindings: power: supply: max77658: Add ADI MAX77658 Battery"
* Fix syntax
* Remove SALRT properties from the device tree
* State monitored-battery as required
* Remove reg
* PATCH 5: "power: supply: max77658: Add ADI MAX77654/58/59 Charger Support"
* Use MAX77643/54/58/59 instead of listing every device
* Use sysfs entries for fast-charge-timer and topoff-timer
* Patch 6: "dt-bindings: power: supply: max77658: Add ADI MAX77654/58/59 Charger"
* Remove fast-charge-timer and topoff-timer properties from the device tree
* PATCH 7: "regulator: max77658: Add ADI MAX77643/54/58/59 Regulator Support"
* Use MAX77643/54/58/59 instead of listing every device
* Use only one entry id id_table
Changes in v2:
* Add MAX77643, MAX77654, MAX77658 device support
Zeynep Arslanbenzer (7):
regulator: max77658: Add ADI MAX77643/54/58/59 Regulator Support
dt-bindings: power: supply: max77658: Add ADI MAX77654/58/59 Charger
power: supply: max77658: Add ADI MAX77654/58/59 Charger Support
dt-bindings: power: supply: max77658: Add ADI MAX77658 Battery
power: supply: max77658: Add ADI MAX77658 Battery Support
dt-bindings: mfd: max77658: Add ADI MAX77658
mfd: max77658: Add ADI MAX77643/54/58/59 MFD Support
.../devicetree/bindings/mfd/adi,max77658.yaml | 160 ++++
.../power/supply/adi,max77658-battery.yaml | 47 +
.../power/supply/adi,max77658-charger.yaml | 53 ++
drivers/mfd/Kconfig | 13 +
drivers/mfd/Makefile | 1 +
drivers/mfd/max77658.c | 426 +++++++++
drivers/power/supply/Kconfig | 14 +
drivers/power/supply/Makefile | 2 +
drivers/power/supply/max77658-battery.c | 633 +++++++++++++
drivers/power/supply/max77658-charger.c | 844 ++++++++++++++++++
drivers/regulator/Kconfig | 8 +
drivers/regulator/Makefile | 1 +
drivers/regulator/max77658-regulator.c | 170 ++++
include/linux/mfd/max77658.h | 80 ++
14 files changed, 2452 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mfd/adi,max77658.yaml
create mode 100644 Documentation/devicetree/bindings/power/supply/adi,max77658-battery.yaml
create mode 100644 Documentation/devicetree/bindings/power/supply/adi,max77658-charger.yaml
create mode 100644 drivers/mfd/max77658.c
create mode 100644 drivers/power/supply/max77658-battery.c
create mode 100644 drivers/power/supply/max77658-charger.c
create mode 100644 drivers/regulator/max77658-regulator.c
create mode 100644 include/linux/mfd/max77658.h
--
2.25.1
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v3 1/7] regulator: max77658: Add ADI MAX77643/54/58/59 Regulator Support
2023-05-08 13:10 [PATCH v3 0/7] Add MAX77643/MAX77654/MAX77658/MAX77659 PMIC Support Zeynep Arslanbenzer
@ 2023-05-08 13:10 ` Zeynep Arslanbenzer
2023-05-08 13:10 ` [PATCH v3 2/7] dt-bindings: power: supply: max77658: Add ADI MAX77654/58/59 Charger Zeynep Arslanbenzer
` (5 subsequent siblings)
6 siblings, 0 replies; 22+ messages in thread
From: Zeynep Arslanbenzer @ 2023-05-08 13:10 UTC (permalink / raw)
To: lee, robh+dt, krzysztof.kozlowski+dt, sre, lgirdwood, broonie
Cc: Zeynep.Arslanbenzer, linux-kernel, devicetree, linux-pm, Nurettin Bolucu
Regulator driver for ADI MAX77643/54/58/59.
MAX77643/MAX77659 has 1 LDO regulator.
MAX77654/MAX77658 has two LDO regulators.
Signed-off-by: Nurettin Bolucu <Nurettin.Bolucu@analog.com>
Signed-off-by: Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
---
drivers/regulator/Kconfig | 8 ++
drivers/regulator/Makefile | 1 +
drivers/regulator/max77658-regulator.c | 170 +++++++++++++++++++++++++
3 files changed, 179 insertions(+)
create mode 100644 drivers/regulator/max77658-regulator.c
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 820c9a0788e5..aba32f8be1a5 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -573,6 +573,14 @@ config REGULATOR_MAX77650
Semiconductor. This device has a SIMO with three independent
power rails and an LDO.
+config REGULATOR_MAX77658
+ tristate "Analog Devices MAX77643/54/58/59 Regulator"
+ depends on MFD_MAX77658
+ help
+ Regulator driver for MAX77643/54/58/59 PMIC from Analog Devices.
+ This driver supports LDO regulators.
+ Say Y here to enable the regulator driver.
+
config REGULATOR_MAX8649
tristate "Maxim 8649 voltage regulator"
depends on I2C
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index b9f5eb35bf5f..14b5f9fd75bf 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -70,6 +70,7 @@ obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o
obj-$(CONFIG_REGULATOR_MAX597X) += max597x-regulator.o
obj-$(CONFIG_REGULATOR_MAX77620) += max77620-regulator.o
obj-$(CONFIG_REGULATOR_MAX77650) += max77650-regulator.o
+obj-$(CONFIG_REGULATOR_MAX77658) += max77658-regulator.o
obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o
obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o
obj-$(CONFIG_REGULATOR_MAX8893) += max8893.o
diff --git a/drivers/regulator/max77658-regulator.c b/drivers/regulator/max77658-regulator.c
new file mode 100644
index 000000000000..f8a98c79d5f0
--- /dev/null
+++ b/drivers/regulator/max77658-regulator.c
@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 Analog Devices, Inc.
+ * ADI regulator driver for the MAX77643/54/58/59
+ */
+
+#include <linux/mfd/max77658.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+
+#define MAX77658_REG_MAX 2
+#define MAX77658_LDO_VOLT_REG_MAX 0x7F
+#define MAX77658_LDO_VOLT_N_RANGE 0x80
+#define MAX77658_LDO_VOLT_STEP 25000
+#define MAX77658_LDO_VOLT_BASE 500000
+#define MAX77654_LDO_VOLT_BASE 800000
+
+#define MAX77658_REG_CNFG_LDO0_A 0x48
+#define MAX77658_REG_CNFG_LDO0_B 0x49
+
+#define MAX77654_REG_CNFG_LDO0_A 0x38
+#define MAX77654_REG_CNFG_LDO0_B 0x39
+
+#define MAX77658_REG_CNFG_LDO1_A 0x4A
+#define MAX77658_REG_CNFG_LDO1_B 0x4B
+
+#define MAX77654_REG_CNFG_LDO1_A 0x3A
+#define MAX77654_REG_CNFG_LDO1_B 0x3B
+
+#define MAX77658_BITS_CONFIG_LDOX_A_TV_LDO GENMASK(6, 0)
+#define MAX77658_BITS_CONFIG_LDOX_B_EN_LDO GENMASK(2, 0)
+
+/*
+ * 0.500 to 3.675V (25mV step)
+ */
+static const struct linear_range MAX77658_LDO_volts[] = {
+ REGULATOR_LINEAR_RANGE(MAX77658_LDO_VOLT_BASE, 0x00,
+ MAX77658_LDO_VOLT_REG_MAX,
+ MAX77658_LDO_VOLT_STEP),
+};
+
+/*
+ * 0.800 to 3.975V (25mV step)
+ */
+static const struct linear_range MAX77654_LDO_volts[] = {
+ REGULATOR_LINEAR_RANGE(MAX77654_LDO_VOLT_BASE, 0x00,
+ MAX77658_LDO_VOLT_REG_MAX,
+ MAX77658_LDO_VOLT_STEP),
+};
+
+static const struct regulator_ops max77658_LDO_ops = {
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_ascend,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+};
+
+#define REGULATOR_DESC_LDO(num, volts, vsel_r, vsel_m, enable_r, enable_m) { \
+ .name = "LDO"#num, \
+ .id = num, \
+ .of_match = of_match_ptr("LDO"#num), \
+ .regulators_node = of_match_ptr("regulators"), \
+ .ops = &max77658_LDO_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .linear_ranges = volts, \
+ .n_linear_ranges = MAX77658_LDO_VOLT_N_RANGE, \
+ .vsel_reg = vsel_r, \
+ .vsel_mask = vsel_m, \
+ .enable_reg = enable_r, \
+ .enable_mask = enable_m, \
+ .enable_val = 0x06, \
+ .disable_val = 0x04, \
+}
+
+static const struct regulator_desc max77643_ldo_desc[] = {
+ REGULATOR_DESC_LDO(0, MAX77658_LDO_volts, MAX77654_REG_CNFG_LDO0_A,
+ MAX77658_BITS_CONFIG_LDOX_A_TV_LDO,
+ MAX77654_REG_CNFG_LDO0_B,
+ MAX77658_BITS_CONFIG_LDOX_B_EN_LDO),
+};
+
+static const struct regulator_desc max77654_ldo_desc[] = {
+ REGULATOR_DESC_LDO(0, MAX77654_LDO_volts, MAX77654_REG_CNFG_LDO0_A,
+ MAX77658_BITS_CONFIG_LDOX_A_TV_LDO,
+ MAX77654_REG_CNFG_LDO0_B,
+ MAX77658_BITS_CONFIG_LDOX_B_EN_LDO),
+ REGULATOR_DESC_LDO(1, MAX77654_LDO_volts, MAX77654_REG_CNFG_LDO1_A,
+ MAX77658_BITS_CONFIG_LDOX_A_TV_LDO,
+ MAX77654_REG_CNFG_LDO1_B,
+ MAX77658_BITS_CONFIG_LDOX_B_EN_LDO),
+};
+
+static const struct regulator_desc max77658_ldo_desc[] = {
+ REGULATOR_DESC_LDO(0, MAX77658_LDO_volts, MAX77658_REG_CNFG_LDO0_A,
+ MAX77658_BITS_CONFIG_LDOX_A_TV_LDO,
+ MAX77658_REG_CNFG_LDO0_B,
+ MAX77658_BITS_CONFIG_LDOX_B_EN_LDO),
+ REGULATOR_DESC_LDO(1, MAX77658_LDO_volts, MAX77658_REG_CNFG_LDO1_A,
+ MAX77658_BITS_CONFIG_LDOX_A_TV_LDO,
+ MAX77658_REG_CNFG_LDO1_B,
+ MAX77658_BITS_CONFIG_LDOX_B_EN_LDO),
+};
+
+static int max77658_regulator_probe(struct platform_device *pdev)
+{
+ struct max77658_dev *max77658 = dev_get_drvdata(pdev->dev.parent);
+ const struct regulator_desc *regulators;
+ struct regulator_config config = {};
+ struct regulator_dev *rdev;
+ int n_regulators = 0;
+ int i;
+
+ switch (max77658->id) {
+ case ID_MAX77643:
+ case ID_MAX77659:
+ regulators = max77643_ldo_desc;
+ n_regulators = ARRAY_SIZE(max77643_ldo_desc);
+ break;
+ case ID_MAX77654:
+ regulators = max77654_ldo_desc;
+ n_regulators = ARRAY_SIZE(max77654_ldo_desc);
+ break;
+ case ID_MAX77658:
+ regulators = max77658_ldo_desc;
+ n_regulators = ARRAY_SIZE(max77658_ldo_desc);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ config.dev = pdev->dev.parent;
+
+ for (i = 0; i < n_regulators; i++) {
+ rdev = devm_regulator_register(&pdev->dev, ®ulators[i],
+ &config);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "Failed to register %s regulator\n",
+ regulators[i].name);
+ return PTR_ERR(rdev);
+ }
+ }
+
+ return 0;
+}
+
+static const struct platform_device_id max77658_regulator_id[] = {
+ { "max77658-regulator" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, max77658_regulator_id);
+
+static struct platform_driver max77658_regulator_driver = {
+ .driver = {
+ .name = "max77658-regulator",
+ },
+ .probe = max77658_regulator_probe,
+ .id_table = max77658_regulator_id,
+};
+
+module_platform_driver(max77658_regulator_driver);
+
+MODULE_DESCRIPTION("MAX77658 Regulator Driver");
+MODULE_AUTHOR("Nurettin.Bolucu@analog.com, Zeynep.Arslanbenzer@analog.com");
+MODULE_LICENSE("GPL");
--
2.25.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v3 2/7] dt-bindings: power: supply: max77658: Add ADI MAX77654/58/59 Charger
2023-05-08 13:10 [PATCH v3 0/7] Add MAX77643/MAX77654/MAX77658/MAX77659 PMIC Support Zeynep Arslanbenzer
2023-05-08 13:10 ` [PATCH v3 1/7] regulator: max77658: Add ADI MAX77643/54/58/59 Regulator Support Zeynep Arslanbenzer
@ 2023-05-08 13:10 ` Zeynep Arslanbenzer
2023-05-08 14:32 ` Krzysztof Kozlowski
2023-05-08 19:45 ` Krzysztof Kozlowski
2023-05-08 13:10 ` [PATCH v3 3/7] power: supply: max77658: Add ADI MAX77654/58/59 Charger Support Zeynep Arslanbenzer
` (4 subsequent siblings)
6 siblings, 2 replies; 22+ messages in thread
From: Zeynep Arslanbenzer @ 2023-05-08 13:10 UTC (permalink / raw)
To: lee, robh+dt, krzysztof.kozlowski+dt, sre, lgirdwood, broonie
Cc: Zeynep.Arslanbenzer, linux-kernel, devicetree, linux-pm, Nurettin Bolucu
Add ADI MAX77654/58/59 power supply devicetree document.
Signed-off-by: Nurettin Bolucu <Nurettin.Bolucu@analog.com>
Signed-off-by: Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
---
.../power/supply/adi,max77658-charger.yaml | 53 +++++++++++++++++++
1 file changed, 53 insertions(+)
create mode 100644 Documentation/devicetree/bindings/power/supply/adi,max77658-charger.yaml
diff --git a/Documentation/devicetree/bindings/power/supply/adi,max77658-charger.yaml b/Documentation/devicetree/bindings/power/supply/adi,max77658-charger.yaml
new file mode 100644
index 000000000000..1b487d82cdbf
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/supply/adi,max77658-charger.yaml
@@ -0,0 +1,53 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/power/supply/adi,max77658-charger.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Battery charger for MAX77658 PMICs family from ADI
+
+maintainers:
+ - Nurettin Bolucu <Nurettin.Bolucu@analog.com>
+ - Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
+
+description: |
+ This module is part of the MAX77658 MFD device. For more details
+ see Documentation/devicetree/bindings/mfd/adi,max77658.yaml.
+
+ The charger is represented as a sub-node of the PMIC node on the device tree.
+
+properties:
+ compatible:
+ enum:
+ - adi,max77654-charger
+ - adi,max77658-charger
+ - adi,max77659-charger
+
+ adi,input-current-limit-microamp:
+ description: Input current limit value.
+
+ monitored-battery:
+ description: >
+ This property must be a phandle to a node using the format described
+ in battery.yaml, with the following properties being required:
+ - constant-charge-current-max-microamp
+
+allOf:
+ - $ref: power-supply.yaml#
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - adi,max77659-charger
+
+ then:
+ properties:
+ adi,input-current-limit-microamp: false
+
+required:
+ - compatible
+
+additionalProperties: false
+
+...
--
2.25.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v3 3/7] power: supply: max77658: Add ADI MAX77654/58/59 Charger Support
2023-05-08 13:10 [PATCH v3 0/7] Add MAX77643/MAX77654/MAX77658/MAX77659 PMIC Support Zeynep Arslanbenzer
2023-05-08 13:10 ` [PATCH v3 1/7] regulator: max77658: Add ADI MAX77643/54/58/59 Regulator Support Zeynep Arslanbenzer
2023-05-08 13:10 ` [PATCH v3 2/7] dt-bindings: power: supply: max77658: Add ADI MAX77654/58/59 Charger Zeynep Arslanbenzer
@ 2023-05-08 13:10 ` Zeynep Arslanbenzer
2023-05-08 19:51 ` Krzysztof Kozlowski
2023-05-08 20:22 ` Krzysztof Kozlowski
2023-05-08 13:10 ` [PATCH v3 4/7] dt-bindings: power: supply: max77658: Add ADI MAX77658 Battery Zeynep Arslanbenzer
` (3 subsequent siblings)
6 siblings, 2 replies; 22+ messages in thread
From: Zeynep Arslanbenzer @ 2023-05-08 13:10 UTC (permalink / raw)
To: lee, robh+dt, krzysztof.kozlowski+dt, sre, lgirdwood, broonie
Cc: Zeynep.Arslanbenzer, linux-kernel, devicetree, linux-pm, Nurettin Bolucu
Charger driver for ADI MAX77654/58/59.
The MAX77654/58/59 charger is Smart Power Selector Li+/Li-Poly Charger.
Signed-off-by: Nurettin Bolucu <Nurettin.Bolucu@analog.com>
Signed-off-by: Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
---
drivers/power/supply/Kconfig | 7 +
drivers/power/supply/Makefile | 1 +
drivers/power/supply/max77658-charger.c | 844 ++++++++++++++++++++++++
3 files changed, 852 insertions(+)
create mode 100644 drivers/power/supply/max77658-charger.c
diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index 0bbfe6a7ce4d..4b68bbb1e2a8 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -565,6 +565,13 @@ config CHARGER_MAX77650
Say Y to enable support for the battery charger control of MAX77650
PMICs.
+config CHARGER_MAX77658
+ tristate "Analog Devices MAX77654/58/59 battery charger driver"
+ depends on MFD_MAX77658
+ help
+ Say Y to enable support for the battery charger control of
+ MAX77654/58/59 PMIC.
+
config CHARGER_MAX77693
tristate "Maxim MAX77693 battery charger driver"
depends on MFD_MAX77693
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index 0ee8653e882e..af4bd6e5969f 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_CHARGER_LTC4162L) += ltc4162-l-charger.o
obj-$(CONFIG_CHARGER_MAX14577) += max14577_charger.o
obj-$(CONFIG_CHARGER_DETECTOR_MAX14656) += max14656_charger_detector.o
obj-$(CONFIG_CHARGER_MAX77650) += max77650-charger.o
+obj-$(CONFIG_CHARGER_MAX77658) += max77658-charger.o
obj-$(CONFIG_CHARGER_MAX77693) += max77693_charger.o
obj-$(CONFIG_CHARGER_MAX77976) += max77976_charger.o
obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o
diff --git a/drivers/power/supply/max77658-charger.c b/drivers/power/supply/max77658-charger.c
new file mode 100644
index 000000000000..de37ebd1a756
--- /dev/null
+++ b/drivers/power/supply/max77658-charger.c
@@ -0,0 +1,844 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 Analog Devices, Inc.
+ * ADI charger driver for the MAX77654/58/59
+ */
+
+#include <linux/bitfield.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/max77658.h>
+#include <linux/module.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/regmap.h>
+
+#define MAX77659_CHG_IRQ_MAX 5
+
+/* Default value for fast charge timer, in hours */
+#define MAX77658_FAST_CHG_TIMER_DEFAULT 5
+/* Default value for topoff timer, in minutes */
+#define MAX77658_TOPOFF_TIMER_DEFAULT 30
+
+#define MAX77658_CHARGER_CURRENT_MAX 300000
+#define MAX77658_CHARGER_CURRENT_MIN 7500
+#define MAX77658_CHARGER_CURRENT_STEP 7500
+#define MAX77658_CNFG_B_ICHGIN_LIM_MAX 475000
+#define MAX77658_CNFG_B_ICHGIN_LIM_MIN 95000
+#define MAX77658_CNFG_B_ICHGIN_LIM_STEP 95000
+#define MAX77658_CNFG_B_ICHGIN_LIM_REG_MAX 4
+#define MAX77658_TOPOFF_TIMER_STEP 5
+
+#define MAX77658_REG_STAT_CHG_A 0x02
+#define MAX77658_REG_STAT_CHG_B 0x03
+#define MAX77658_REG_CNFG_CHG_A 0x20
+#define MAX77658_REG_CNFG_CHG_B 0x21
+#define MAX77658_REG_CNFG_CHG_C 0x22
+#define MAX77658_REG_CNFG_CHG_D 0x23
+#define MAX77658_REG_CNFG_CHG_E 0x24
+#define MAX77658_REG_CNFG_CHG_F 0x25
+#define MAX77658_REG_CNFG_CHG_G 0x26
+#define MAX77658_REG_CNFG_CHG_H 0x27
+#define MAX77658_REG_CNFG_CHG_I 0x28
+
+#define MAX77658_BIT_STAT_A_THM_DTLS GENMASK(2, 0)
+#define MAX77658_BIT_STAT_A_TJ_REG_STAT BIT(3)
+#define MAX77658_BIT_STAT_A_VSYSY_MIN_STAT BIT(4)
+#define MAX77658_BIT_STAT_A_ICHGIN_LIM_STAT BIT(5)
+#define MAX77658_BIT_STAT_A_VCHGIN_MIN_STAT BIT(6)
+#define MAX77658_BIT_STAT_B_CHG BIT(1)
+#define MAX77658_BIT_STAT_B_CHGIN_DTSL GENMASK(3, 2)
+#define MAX77658_BIT_STAT_B_CHG_DTLS GENMASK(7, 4)
+#define MAX77658_BIT_CNFG_B_CHG_EN BIT(0)
+#define MAX77658_BIT_CNFG_B_ICHGIN_LIM GENMASK(4, 2)
+#define MAX77658_BIT_CNFG_C_TOPOFFTIMER GENMASK(2, 0)
+#define MAX77658_BIT_CNFG_E_TFASTCHG GENMASK(1, 0)
+#define MAX77658_BIT_CNFG_E_CC GENMASK(7, 2)
+#define MAX77658_BIT_CNFG_G_CHG_CV GENMASK(7, 2)
+
+enum {
+ MAX77658_CHG_DTLS_OFF,
+ MAX77658_CHG_DTLS_PREQUAL,
+ MAX77658_CHG_DTLS_FASTCHARGE_CC,
+ MAX77658_CHG_DTLS_JEITA_FASTCHARGE_CC,
+ MAX77658_CHG_DTLS_FASTCHARGE_CV,
+ MAX77658_CHG_DTLS_JEITA_FASTCHARGE_CV,
+ MAX77658_CHG_DTLS_TOPOFF,
+ MAX77658_CHG_DTLS_JEITA_TOPOFF,
+ MAX77658_CHG_DTLS_DONE,
+ MAX77658_CHG_DTLS_JEITA_DONE,
+ MAX77658_CHG_DTLS_OFF_TIMER_FAULT,
+ MAX77658_CHG_DTLS_OFF_CHARGE_TIMER_FAULT,
+ MAX77658_CHG_DTLS_OFF_BATTERY_TEMP_FAULT,
+ MAX77658_CHG_DTLS_RESERVED_13,
+};
+
+enum {
+ MAX77658_CHG_IRQ_THM_I,
+ MAX77658_CHG_IRQ_CHG_I,
+ MAX77658_CHG_IRQ_CHGIN_I,
+ MAX77658_CHG_IRQ_TJ_REG_I,
+ MAX77658_CHG_IRQ_SYS_CTRL_I,
+ MAX77658_CHG_IRQ_CHGIN_CTRL_I,
+ MAX77658_CHG_IRQ_SYS_CNFG_I,
+ MAX77658_CHG_IRQ_MAX,
+};
+
+struct max77658_charger {
+ struct device *dev;
+ struct max77658_dev *max77658;
+ struct regmap *regmap;
+
+ struct power_supply *psy_chg;
+ struct power_supply_desc psy_chg_d;
+
+ int irq;
+ int irq_arr[MAX77658_CHG_IRQ_MAX];
+ int irq_mask;
+
+ struct delayed_work irq_work;
+
+ int present;
+ int health;
+ int status;
+ int charge_type;
+
+ unsigned int fast_charge_current_ua;
+ unsigned int input_current_limit_ua;
+};
+
+static int max77658_set_input_current_limit(struct max77658_charger *charger,
+ int input_current)
+{
+ u8 reg_data = 0;
+
+ input_current = clamp_val(input_current, MAX77658_CNFG_B_ICHGIN_LIM_MIN,
+ MAX77658_CNFG_B_ICHGIN_LIM_MAX);
+ if (charger->max77658->id == ID_MAX77658) {
+ reg_data = MAX77658_CNFG_B_ICHGIN_LIM_REG_MAX + 1
+ - DIV_ROUND_UP(input_current,
+ MAX77658_CNFG_B_ICHGIN_LIM_STEP);
+ } else {
+ reg_data = DIV_ROUND_UP(input_current,
+ MAX77658_CNFG_B_ICHGIN_LIM_STEP) - 1;
+ }
+
+ reg_data = FIELD_PREP(MAX77658_BIT_CNFG_B_ICHGIN_LIM, reg_data);
+ return regmap_update_bits(charger->regmap, MAX77658_REG_CNFG_CHG_B,
+ MAX77658_BIT_CNFG_B_ICHGIN_LIM, reg_data);
+}
+
+static int max77658_get_input_current_limit(struct max77658_charger *charger,
+ int *get_current)
+{
+ unsigned int reg_data = 0;
+ int ret;
+
+ ret = regmap_read(charger->regmap, MAX77658_REG_CNFG_CHG_B, ®_data);
+ if (ret)
+ return ret;
+
+ reg_data = FIELD_GET(MAX77658_BIT_CNFG_B_ICHGIN_LIM, reg_data);
+
+ if (charger->max77658->id == ID_MAX77658) {
+ *get_current = (MAX77658_CNFG_B_ICHGIN_LIM_REG_MAX + 1
+ - reg_data) * MAX77658_CNFG_B_ICHGIN_LIM_STEP;
+ } else {
+ *get_current = (reg_data + 1) * MAX77658_CNFG_B_ICHGIN_LIM_STEP;
+ }
+
+ return 0;
+}
+
+static int max77658_set_charge_current(struct max77658_charger *charger,
+ int fast_charge_current_ua)
+{
+ unsigned int reg_data;
+
+ fast_charge_current_ua = clamp_val(fast_charge_current_ua,
+ MAX77658_CHARGER_CURRENT_MIN,
+ MAX77658_CHARGER_CURRENT_MAX);
+ reg_data = fast_charge_current_ua / MAX77658_CHARGER_CURRENT_STEP - 1;
+ reg_data = FIELD_PREP(MAX77658_BIT_CNFG_E_CC, reg_data);
+
+ return regmap_update_bits(charger->regmap, MAX77658_REG_CNFG_CHG_E,
+ MAX77658_BIT_CNFG_E_CC, reg_data);
+}
+
+static int max77658_get_charge_current(struct max77658_charger *charger,
+ int *get_current)
+{
+ unsigned int reg_data, current_val;
+ int ret;
+
+ ret = regmap_read(charger->regmap, MAX77658_REG_CNFG_CHG_E, ®_data);
+ if (ret)
+ return ret;
+
+ reg_data = FIELD_GET(MAX77658_BIT_CNFG_E_CC, reg_data);
+ current_val = (reg_data + 1) * MAX77658_CHARGER_CURRENT_STEP;
+
+ *get_current = clamp_val(current_val, MAX77658_CHARGER_CURRENT_MIN,
+ MAX77658_CHARGER_CURRENT_MAX);
+
+ return 0;
+}
+
+static ssize_t max77658_device_attr_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count,
+ int (*fn)(struct max77658_charger *,
+ unsigned long))
+{
+ struct max77658_charger *charger = dev_get_drvdata(dev);
+ unsigned long val;
+ int ret;
+
+ ret = kstrtoul(buf, 10, &val);
+ if (ret)
+ return ret;
+
+ ret = fn(charger, val);
+ if (ret)
+ return ret;
+
+ return count;
+}
+
+static int max77658_set_topoff_timer(struct max77658_charger *charger,
+ unsigned long minutes)
+{
+ unsigned int reg_data;
+
+ minutes = clamp_val(minutes, 0, MAX77658_BIT_CNFG_C_TOPOFFTIMER
+ * MAX77658_TOPOFF_TIMER_STEP);
+ reg_data = FIELD_PREP(MAX77658_BIT_CNFG_C_TOPOFFTIMER,
+ minutes / MAX77658_TOPOFF_TIMER_STEP);
+
+ return regmap_update_bits(charger->regmap, MAX77658_REG_CNFG_CHG_C,
+ MAX77658_BIT_CNFG_C_TOPOFFTIMER, reg_data);
+}
+
+static ssize_t topoff_timer_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ return max77658_device_attr_store(dev, attr, buf, count,
+ max77658_set_topoff_timer);
+}
+
+static ssize_t topoff_timer_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct max77658_charger *charger = dev_get_drvdata(dev);
+ unsigned int reg_data, minutes;
+ int ret;
+
+ ret = regmap_read(charger->regmap, MAX77658_REG_CNFG_CHG_C,
+ ®_data);
+ if (ret)
+ return ret;
+
+ minutes = FIELD_GET(MAX77658_BIT_STAT_A_THM_DTLS, reg_data)
+ * MAX77658_TOPOFF_TIMER_STEP;
+
+ return scnprintf(buf, PAGE_SIZE, "%u\n", minutes);
+}
+
+static int max77658_set_fast_charge_timer(struct max77658_charger *charger,
+ unsigned long hours)
+{
+ unsigned int val;
+
+ if (hours == 0 || hours > 7)
+ val = 0x00;
+ else if (hours < 3)
+ val = 0x01;
+ else
+ val = DIV_ROUND_UP(hours - 1, 2);
+
+ return regmap_update_bits(charger->regmap, MAX77658_REG_CNFG_CHG_E,
+ MAX77658_BIT_CNFG_E_TFASTCHG, val);
+}
+
+static ssize_t fast_charge_timer_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ return max77658_device_attr_store(dev, attr, buf, count,
+ max77658_set_fast_charge_timer);
+}
+
+static ssize_t fast_charge_timer_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct max77658_charger *charger = dev_get_drvdata(dev);
+ unsigned int reg_data, hours;
+ int ret;
+
+ ret = regmap_read(charger->regmap, MAX77658_REG_CNFG_CHG_E,
+ ®_data);
+ if (ret)
+ return ret;
+
+ reg_data = FIELD_GET(MAX77658_BIT_CNFG_E_TFASTCHG, reg_data);
+
+ if (reg_data == 0)
+ hours = 0;
+ else
+ hours = reg_data * 2 + 1;
+
+ return scnprintf(buf, PAGE_SIZE, "%u\n", hours);
+}
+
+static DEVICE_ATTR_RW(fast_charge_timer);
+static DEVICE_ATTR_RW(topoff_timer);
+
+static int max77658_charger_initialize(struct max77658_charger *charger)
+{
+ int ret;
+
+ ret = max77658_set_charge_current(charger,
+ charger->fast_charge_current_ua);
+ if (ret)
+ return dev_err_probe(charger->dev, ret,
+ "Error in writing register CNFG_CHG_C\n");
+
+ ret = max77658_set_fast_charge_timer(charger,
+ MAX77658_FAST_CHG_TIMER_DEFAULT);
+ if (ret)
+ return dev_err_probe(charger->dev, ret,
+ "Error in writing register CNFG_CHG_E\n");
+
+ ret = max77658_set_topoff_timer(charger, MAX77658_TOPOFF_TIMER_DEFAULT);
+ if (ret)
+ return dev_err_probe(charger->dev, ret,
+ "Error in writing register CNFG_CHG_C\n");
+
+ if (charger->max77658->id == ID_MAX77659)
+ return 0;
+
+ return max77658_set_input_current_limit(charger,
+ charger->input_current_limit_ua);
+}
+
+static void max77658_charger_parse_dt(struct max77658_charger *charger)
+{
+ int ret;
+
+ ret = device_property_read_u32(charger->dev,
+ "adi,input-current-limit-microamp",
+ &charger->input_current_limit_ua);
+ if (ret) {
+ dev_dbg(charger->dev,
+ "Could not read input-current-limit DT property\n");
+ charger->input_current_limit_ua = 475000;
+ }
+}
+
+struct max77658_charger_status_map {
+ int health;
+ int status;
+ int charge_type;
+};
+
+#define STATUS_MAP(_MAX77658_CHG_DTLS, _health, _status, _charge_type) \
+ [MAX77658_CHG_DTLS_##_MAX77658_CHG_DTLS] = {\
+ .health = POWER_SUPPLY_HEALTH_##_health,\
+ .status = POWER_SUPPLY_STATUS_##_status,\
+ .charge_type = POWER_SUPPLY_CHARGE_TYPE_##_charge_type,\
+ }
+
+static struct max77658_charger_status_map max77658_charger_status_map[] = {
+ /* chg_details_xx, health, status, charge_type */
+ STATUS_MAP(OFF, UNKNOWN, NOT_CHARGING, NONE),
+ STATUS_MAP(PREQUAL, GOOD, CHARGING, TRICKLE),
+ STATUS_MAP(FASTCHARGE_CC, GOOD, CHARGING, FAST),
+ STATUS_MAP(JEITA_FASTCHARGE_CC, GOOD, CHARGING, FAST),
+ STATUS_MAP(FASTCHARGE_CV, GOOD, CHARGING, FAST),
+ STATUS_MAP(JEITA_FASTCHARGE_CV, GOOD, CHARGING, FAST),
+ STATUS_MAP(TOPOFF, GOOD, CHARGING, FAST),
+ STATUS_MAP(JEITA_TOPOFF, GOOD, CHARGING, FAST),
+ STATUS_MAP(DONE, GOOD, FULL, NONE),
+ STATUS_MAP(JEITA_DONE, GOOD, FULL, NONE),
+ STATUS_MAP(OFF_TIMER_FAULT, SAFETY_TIMER_EXPIRE, NOT_CHARGING, NONE),
+ STATUS_MAP(OFF_CHARGE_TIMER_FAULT, UNKNOWN, NOT_CHARGING, NONE),
+ STATUS_MAP(OFF_BATTERY_TEMP_FAULT, HOT, NOT_CHARGING, NONE),
+};
+
+static int max77658_charger_update(struct max77658_charger *charger)
+{
+ unsigned int stat_chg_b, chg_dtls;
+ int ret;
+
+ ret = regmap_read(charger->regmap, MAX77658_REG_STAT_CHG_B,
+ &stat_chg_b);
+ if (ret) {
+ charger->health = POWER_SUPPLY_HEALTH_UNKNOWN;
+ charger->status = POWER_SUPPLY_STATUS_UNKNOWN;
+ charger->charge_type = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
+ return ret;
+ }
+
+ charger->present = stat_chg_b & MAX77658_BIT_STAT_B_CHG;
+ if (!charger->present) {
+ charger->health = POWER_SUPPLY_HEALTH_UNKNOWN;
+ charger->status = POWER_SUPPLY_STATUS_DISCHARGING;
+ charger->charge_type = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
+ return 0;
+ }
+
+ chg_dtls = FIELD_GET(MAX77658_BIT_STAT_B_CHG_DTLS, stat_chg_b);
+
+ charger->health = max77658_charger_status_map[chg_dtls].health;
+ charger->status = max77658_charger_status_map[chg_dtls].status;
+ charger->charge_type =
+ max77658_charger_status_map[chg_dtls].charge_type;
+
+ return 0;
+}
+
+static enum power_supply_property max77658_charger_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_CHARGE_TYPE,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CURRENT_MAX
+};
+
+static enum power_supply_property max77659_charger_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_CHARGE_TYPE,
+ POWER_SUPPLY_PROP_CURRENT_NOW
+};
+
+static int max77658_property_is_writeable(struct power_supply *psy,
+ enum power_supply_property psp)
+{
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ case POWER_SUPPLY_PROP_CURRENT_MAX:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static int max77659_property_is_writeable(struct power_supply *psy,
+ enum power_supply_property psp)
+{
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static int max77658_charger_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct max77658_charger *charger = power_supply_get_drvdata(psy);
+ int ret;
+
+ ret = max77658_charger_update(charger);
+ if (ret)
+ return ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = charger->present;
+ break;
+ case POWER_SUPPLY_PROP_HEALTH:
+ val->intval = charger->health;
+ break;
+ case POWER_SUPPLY_PROP_STATUS:
+ val->intval = charger->status;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_TYPE:
+ val->intval = charger->charge_type;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ ret = max77658_get_charge_current(charger, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_MAX:
+ if (charger->max77658->id != ID_MAX77659) {
+ ret = max77658_get_input_current_limit(charger,
+ &val->intval);
+ } else {
+ ret = -EINVAL;
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int max77658_charger_set_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ const union power_supply_propval *val)
+{
+ struct max77658_charger *charger = power_supply_get_drvdata(psy);
+ int ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ ret = regmap_update_bits(charger->regmap,
+ MAX77658_REG_CNFG_CHG_B,
+ MAX77658_BIT_CNFG_B_CHG_EN,
+ !!val->intval);
+ if (ret)
+ return ret;
+
+ ret =
+ max77658_set_charge_current(charger,
+ charger->fast_charge_current_ua);
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ /* val->intval - uA */
+ ret = max77658_set_charge_current(charger, val->intval);
+ if (ret)
+ return ret;
+
+ charger->fast_charge_current_ua = val->intval;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_MAX:
+ if (charger->max77658->id == ID_MAX77659) {
+ ret = -EINVAL;
+ break;
+ }
+ ret = max77658_set_input_current_limit(charger, val->intval);
+ if (ret)
+ return ret;
+
+ charger->input_current_limit_ua = val->intval;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static void max77658_charger_irq_handler(struct max77658_charger *charger,
+ int irq)
+{
+ int chg_present, vchgin, ichgin;
+ unsigned int val, stat_chg_b;
+ int ret;
+
+ switch (irq) {
+ case MAX77658_CHG_IRQ_THM_I:
+ ret = regmap_read(charger->regmap, MAX77658_REG_STAT_CHG_A,
+ &val);
+ if (ret) {
+ dev_err(charger->dev, "Failed to read STAT_CHG_A\n");
+ return;
+ }
+
+ val = FIELD_GET(MAX77658_BIT_STAT_A_THM_DTLS, val);
+ dev_dbg(charger->dev, "CHG_INT_THM: thm_dtls = %02Xh\n", val);
+ break;
+
+ case MAX77658_CHG_IRQ_CHG_I:
+ ret = regmap_read(charger->regmap, MAX77658_REG_STAT_CHG_B,
+ &val);
+ if (ret) {
+ dev_err(charger->dev, "Failed to read STAT_CHG_B\n");
+ return;
+ }
+
+ val = FIELD_GET(MAX77658_BIT_STAT_B_CHG_DTLS, val);
+ dev_dbg(charger->dev,
+ "CHG_INT_CHG: MAX77658_CHG_DTLS = %02Xh\n", val);
+ break;
+
+ case MAX77658_CHG_IRQ_CHGIN_I:
+ ret = regmap_read(charger->regmap,
+ MAX77658_REG_STAT_CHG_B, &val);
+ if (ret) {
+ dev_err(charger->dev, "Failed to read STAT_CHG_B\n");
+ return;
+ }
+
+ val = FIELD_GET(MAX77658_BIT_STAT_B_CHG_DTLS, val);
+ dev_dbg(charger->dev,
+ "CHG_INT_CHG: MAX77658_CHG_DTLS = %02Xh\n", val);
+
+ ret = regmap_read(charger->regmap, MAX77658_REG_STAT_CHG_B,
+ &stat_chg_b);
+ if (ret) {
+ dev_err(charger->dev, "Failed to read STAT_CHG_B\n");
+ return;
+ }
+
+ chg_present = stat_chg_b & MAX77658_BIT_STAT_B_CHG;
+
+ regmap_update_bits(charger->regmap, MAX77658_REG_CNFG_CHG_B,
+ MAX77658_BIT_CNFG_B_CHG_EN, !!chg_present);
+ if (chg_present)
+ break;
+
+ max77658_set_charge_current(charger,
+ charger->fast_charge_current_ua);
+ break;
+
+ case MAX77658_CHG_IRQ_TJ_REG_I:
+ ret = regmap_read(charger->regmap, MAX77658_REG_STAT_CHG_A,
+ &val);
+ if (ret) {
+ dev_err(charger->dev, "Failed to read STAT_CHG_A\n");
+ return;
+ }
+
+ val = FIELD_GET(MAX77658_BIT_STAT_A_TJ_REG_STAT, val);
+ dev_dbg(charger->dev,
+ "CHG_INT_TJ_REG: tj_reg_stat = %02Xh\n", val);
+ dev_dbg(charger->dev,
+ "CHG_INT_TJ_REG: Die temperature %s Tj-reg\n",
+ val ? "has exceeded" : "has not exceeded");
+ break;
+
+ case MAX77658_CHG_IRQ_SYS_CTRL_I:
+ ret = regmap_read(charger->regmap, MAX77658_REG_STAT_CHG_A,
+ &val);
+ if (ret) {
+ dev_err(charger->dev, "Failed to read STAT_CHG_A\n");
+ return;
+ }
+
+ val = FIELD_GET(MAX77658_BIT_STAT_A_VSYSY_MIN_STAT, val);
+ dev_dbg(charger->dev,
+ "CHG_INT_SYS_CTRL: The minimum system voltage regulation loop %s\n",
+ val ? "has engaged" : "has not engaged");
+ break;
+
+ case MAX77658_CHG_IRQ_CHGIN_CTRL_I:
+ ret = regmap_read(charger->regmap, MAX77658_REG_STAT_CHG_A,
+ &val);
+ if (ret) {
+ dev_dbg(charger->dev, "Failed to read STAT_CHG_A\n");
+ return;
+ }
+
+ vchgin = FIELD_GET(MAX77658_BIT_STAT_A_VCHGIN_MIN_STAT, val);
+ dev_dbg(charger->dev, "CHG_INT_CHGIN: VCHGIN_MIN_STAT %s\n",
+ vchgin ? "has changed" : "has not changed");
+
+ ichgin = FIELD_GET(MAX77658_BIT_STAT_A_ICHGIN_LIM_STAT, val);
+ dev_dbg(charger->dev, "CHG_INT_CHGIN: ICHGIN_LIM_STAT %s\n",
+ ichgin ? "has changed" : "has not changed");
+ break;
+
+ case MAX77658_CHG_IRQ_SYS_CNFG_I:
+ ret = regmap_read(charger->regmap, MAX77658_REG_CNFG_CHG_G,
+ &val);
+ if (ret) {
+ dev_dbg(charger->dev, "Failed to read CNFG_CHG_G\n");
+ return;
+ }
+
+ val = FIELD_GET(MAX77658_BIT_CNFG_G_CHG_CV, val);
+ dev_dbg(charger->dev, "CHG_INT_SYS_CNFG: CHG_VC = %02Xh\n",
+ val);
+ break;
+
+ default:
+ break;
+ }
+
+ power_supply_changed(charger->psy_chg);
+}
+
+static irqreturn_t max77658_charger_isr(int irq, void *data)
+{
+ struct max77658_charger *charger = data;
+
+ charger->irq = irq;
+ max77658_charger_update(charger);
+ max77658_charger_irq_handler(charger,
+ charger->irq - charger->irq_arr[0]);
+
+ return IRQ_HANDLED;
+}
+
+static const char * const max77658_irq_descs[] = {
+ "charger-thm",
+ "charger-chg",
+ "charger-chgin",
+ "charger-tj-reg",
+ "charger-sys-ctrl",
+ "charger-chgin-ctrl",
+ "charger-sys-cnfg",
+};
+
+static int max77658_charger_probe(struct platform_device *pdev)
+{
+ struct max77658_dev *max77658 = dev_get_drvdata(pdev->dev.parent);
+ struct power_supply_config charger_cfg = {};
+ struct power_supply_battery_info *info;
+ struct max77658_charger *charger;
+ struct device *dev = &pdev->dev;
+ int i, n_irq, ret;
+
+ charger = devm_kzalloc(dev, sizeof(*charger), GFP_KERNEL);
+ if (!charger)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, charger);
+
+ charger->dev = dev;
+ charger->max77658 = max77658;
+ charger->regmap = dev_get_regmap(charger->dev->parent, NULL);
+
+ charger->psy_chg_d.get_property = max77658_charger_get_property;
+ charger->psy_chg_d.set_property = max77658_charger_set_property;
+ charger->psy_chg_d.type = POWER_SUPPLY_TYPE_USB;
+ charger_cfg.of_node = dev->of_node;
+ charger_cfg.drv_data = charger;
+
+ switch (max77658->id) {
+ case ID_MAX77654:
+ charger->psy_chg_d.properties = max77658_charger_props;
+ charger->psy_chg_d.num_properties =
+ ARRAY_SIZE(max77658_charger_props);
+ charger->psy_chg_d.name = "max77654-charger";
+ charger->psy_chg_d.property_is_writeable =
+ max77658_property_is_writeable;
+ n_irq = MAX77658_CHG_IRQ_MAX;
+ break;
+ case ID_MAX77658:
+ charger->psy_chg_d.properties = max77658_charger_props;
+ charger->psy_chg_d.num_properties =
+ ARRAY_SIZE(max77658_charger_props);
+ charger->psy_chg_d.name = "max77658-charger";
+ charger->psy_chg_d.property_is_writeable =
+ max77658_property_is_writeable;
+ n_irq = MAX77658_CHG_IRQ_MAX;
+ break;
+ case ID_MAX77659:
+ charger->psy_chg_d.properties = max77659_charger_props;
+ charger->psy_chg_d.num_properties =
+ ARRAY_SIZE(max77659_charger_props);
+ charger->psy_chg_d.name = "max77659-charger";
+ charger->psy_chg_d.property_is_writeable =
+ max77659_property_is_writeable;
+ n_irq = MAX77659_CHG_IRQ_MAX;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ charger->psy_chg = devm_power_supply_register(dev, &charger->psy_chg_d,
+ &charger_cfg);
+ if (IS_ERR(charger->psy_chg))
+ return dev_err_probe(dev, PTR_ERR(charger->psy_chg),
+ "Failed to register power supply\n");
+
+ charger->psy_chg->of_node = of_get_child_by_name(dev->parent->of_node,
+ "charger");
+
+ if (!charger->psy_chg->of_node)
+ dev_err(charger->dev,
+ "of_get_child_by_name\n");
+
+ ret = power_supply_get_battery_info(charger->psy_chg, &info);
+ if (ret) {
+ dev_err(charger->dev, "Unable to get charger info\n");
+ charger->fast_charge_current_ua = 15000;
+ } else {
+ charger->fast_charge_current_ua =
+ info->constant_charge_current_max_ua;
+ }
+
+ if (charger->max77658->id != ID_MAX77659)
+ max77658_charger_parse_dt(charger);
+
+ ret = max77658_charger_initialize(charger);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to initialize charger\n");
+
+ for (i = 0; i < n_irq; i++) {
+ charger->irq_arr[i] =
+ regmap_irq_get_virq(max77658->irqc_chg, i);
+
+ if (charger->irq_arr[i] < 0)
+ return dev_err_probe(dev, -EINVAL,
+ "Invalid IRQ for MAX77658_CHG_IRQ %d\n",
+ i);
+
+ ret = devm_request_threaded_irq(dev, charger->irq_arr[i],
+ NULL, max77658_charger_isr,
+ IRQF_TRIGGER_FALLING,
+ max77658_irq_descs[i], charger);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to request irq: %d\n",
+ charger->irq_arr[i]);
+ }
+
+ ret = device_create_file(dev, &dev_attr_fast_charge_timer);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to create fast charge timer sysfs entry\n");
+
+ ret = device_create_file(dev, &dev_attr_topoff_timer);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to create topoff timer sysfs entry\n");
+
+ return 0;
+}
+
+static int max77658_charger_remove(struct platform_device *pdev)
+{
+ device_remove_file(&pdev->dev, &dev_attr_topoff_timer);
+ device_remove_file(&pdev->dev, &dev_attr_fast_charge_timer);
+
+ return 0;
+}
+
+static const struct of_device_id max77658_charger_of_id[] = {
+ { .compatible = "adi,max77654-charger" },
+ { .compatible = "adi,max77658-charger" },
+ { .compatible = "adi,max77659-charger" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, max77658_charger_of_id);
+
+static const struct platform_device_id max77658_charger_id[] = {
+ { "max77654-charger" },
+ { "max77658-charger" },
+ { "max77659-charger" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, max77658_charger_id);
+
+static struct platform_driver max77658_charger_driver = {
+ .driver = {
+ .name = "max77658-charger",
+ .of_match_table = max77658_charger_of_id,
+ },
+ .probe = max77658_charger_probe,
+ .remove = max77658_charger_remove,
+ .id_table = max77658_charger_id,
+};
+
+module_platform_driver(max77658_charger_driver);
+
+MODULE_DESCRIPTION("MAX77658 Charger Driver");
+MODULE_AUTHOR("Nurettin.Bolucu@analog.com, Zeynep.Arslanbenzer@analog.com");
+MODULE_LICENSE("GPL");
--
2.25.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v3 4/7] dt-bindings: power: supply: max77658: Add ADI MAX77658 Battery
2023-05-08 13:10 [PATCH v3 0/7] Add MAX77643/MAX77654/MAX77658/MAX77659 PMIC Support Zeynep Arslanbenzer
` (2 preceding siblings ...)
2023-05-08 13:10 ` [PATCH v3 3/7] power: supply: max77658: Add ADI MAX77654/58/59 Charger Support Zeynep Arslanbenzer
@ 2023-05-08 13:10 ` Zeynep Arslanbenzer
2023-05-08 14:31 ` Krzysztof Kozlowski
2023-05-08 19:54 ` Krzysztof Kozlowski
2023-05-08 13:10 ` [PATCH v3 5/7] power: supply: max77658: Add ADI MAX77658 Battery Support Zeynep Arslanbenzer
` (2 subsequent siblings)
6 siblings, 2 replies; 22+ messages in thread
From: Zeynep Arslanbenzer @ 2023-05-08 13:10 UTC (permalink / raw)
To: lee, robh+dt, krzysztof.kozlowski+dt, sre, lgirdwood, broonie
Cc: Zeynep.Arslanbenzer, linux-kernel, devicetree, linux-pm, Nurettin Bolucu
Add ADI MAX77658 power supply devicetree document.
Signed-off-by: Nurettin Bolucu <Nurettin.Bolucu@analog.com>
Signed-off-by: Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
---
.../power/supply/adi,max77658-battery.yaml | 47 +++++++++++++++++++
1 file changed, 47 insertions(+)
create mode 100644 Documentation/devicetree/bindings/power/supply/adi,max77658-battery.yaml
diff --git a/Documentation/devicetree/bindings/power/supply/adi,max77658-battery.yaml b/Documentation/devicetree/bindings/power/supply/adi,max77658-battery.yaml
new file mode 100644
index 000000000000..112296d2b1f4
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/supply/adi,max77658-battery.yaml
@@ -0,0 +1,47 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/power/supply/adi,max77658-battery.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Battery for MAX77658 PMICs family from ADI
+
+maintainers:
+ - Nurettin Bolucu <Nurettin.Bolucu@analog.com>
+ - Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
+
+description: |
+ This module is part of the MAX77658 MFD device. For more details
+ see Documentation/devicetree/bindings/mfd/adi,max77658.yaml.
+
+ The fuel gauge is represented as a sub-node of the PMIC node on the device tree.
+
+properties:
+ compatible:
+ const: adi,max77658-battery
+
+ adi,valrt-min-microvolt:
+ description: alert when battery voltage is lower than this value
+
+ adi,valrt-max-microvolt:
+ description: alert when battery voltage is higher than this value
+
+ adi,ialrt-min-microamp:
+ description: alert when battery current is lower than this value
+
+ adi,ialrt-max-microamp:
+ description: alert when battery current is higher than this value
+
+ monitored-battery:
+ description: >
+ This property must be a phandle to a node using the format described
+ in battery.yaml, with the following properties being required:
+ - alert-celsius
+
+required:
+ - compatible
+ - monitored-battery
+
+additionalProperties: false
+
+...
--
2.25.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v3 5/7] power: supply: max77658: Add ADI MAX77658 Battery Support
2023-05-08 13:10 [PATCH v3 0/7] Add MAX77643/MAX77654/MAX77658/MAX77659 PMIC Support Zeynep Arslanbenzer
` (3 preceding siblings ...)
2023-05-08 13:10 ` [PATCH v3 4/7] dt-bindings: power: supply: max77658: Add ADI MAX77658 Battery Zeynep Arslanbenzer
@ 2023-05-08 13:10 ` Zeynep Arslanbenzer
2023-05-08 19:57 ` Krzysztof Kozlowski
2023-05-08 20:15 ` Krzysztof Kozlowski
2023-05-08 13:10 ` [PATCH v3 6/7] dt-bindings: mfd: max77658: Add ADI MAX77658 Zeynep Arslanbenzer
2023-05-08 13:10 ` [PATCH v3 7/7] mfd: max77658: Add ADI MAX77643/54/58/59 MFD Support Zeynep Arslanbenzer
6 siblings, 2 replies; 22+ messages in thread
From: Zeynep Arslanbenzer @ 2023-05-08 13:10 UTC (permalink / raw)
To: lee, robh+dt, krzysztof.kozlowski+dt, sre, lgirdwood, broonie
Cc: Zeynep.Arslanbenzer, linux-kernel, devicetree, linux-pm, Nurettin Bolucu
Battery driver for ADI MAX77658.
The MAX77658 is an ultra-low power fuel gauge which implements the Maxim ModelGauge m5 EZ algorithm.
Signed-off-by: Nurettin Bolucu <Nurettin.Bolucu@analog.com>
Signed-off-by: Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
---
drivers/power/supply/Kconfig | 7 +
drivers/power/supply/Makefile | 1 +
drivers/power/supply/max77658-battery.c | 633 ++++++++++++++++++++++++
3 files changed, 641 insertions(+)
create mode 100644 drivers/power/supply/max77658-battery.c
diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index 4b68bbb1e2a8..f9556f4b9e35 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -572,6 +572,13 @@ config CHARGER_MAX77658
Say Y to enable support for the battery charger control of
MAX77654/58/59 PMIC.
+config BATTERY_MAX77658
+ tristate "Analog Devices MAX77658 battery driver"
+ depends on MFD_MAX77658
+ help
+ Say Y to enable support for the battery control of
+ MAX77658 PMIC.
+
config CHARGER_MAX77693
tristate "Maxim MAX77693 battery charger driver"
depends on MFD_MAX77693
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index af4bd6e5969f..e5a425d333a7 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -77,6 +77,7 @@ obj-$(CONFIG_CHARGER_MAX14577) += max14577_charger.o
obj-$(CONFIG_CHARGER_DETECTOR_MAX14656) += max14656_charger_detector.o
obj-$(CONFIG_CHARGER_MAX77650) += max77650-charger.o
obj-$(CONFIG_CHARGER_MAX77658) += max77658-charger.o
+obj-$(CONFIG_BATTERY_MAX77658) += max77658-battery.o
obj-$(CONFIG_CHARGER_MAX77693) += max77693_charger.o
obj-$(CONFIG_CHARGER_MAX77976) += max77976_charger.o
obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o
diff --git a/drivers/power/supply/max77658-battery.c b/drivers/power/supply/max77658-battery.c
new file mode 100644
index 000000000000..4948ef227db1
--- /dev/null
+++ b/drivers/power/supply/max77658-battery.c
@@ -0,0 +1,633 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 Analog Devices, Inc.
+ * ADI battery driver for the MAX77658
+ */
+
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/mfd/max77658.h>
+#include <linux/module.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/regmap.h>
+
+/* Default value for SALRT min threshold, in percent */
+#define MAX77658_SALRT_MIN_DEFAULT 1
+/* Default value for SALRT max threshold, in percent */
+#define MAX77658_SALRT_MAX_DEFAULT 99
+
+#define MAX77658_IALRTTH_RESOLUTION 8567
+#define MAX77658_CURRENT_RESOLUTION 33487
+#define MAX77658_VOLTAGE_RESOLUTION 78125
+#define MAX77658_FG_DELAY 1000
+#define MAX77658_BATTERY_FULL 100
+#define MAX77658_BATTERY_LOW 40
+#define MAX77658_BATTERY_CRITICAL 10
+#define MAX77658_MAXMINVOLT_STEP 20000
+#define MAX77658_VALRTTH_STEP 20000
+#define MAX77658_VEMPTY_VE_STEP 10000
+#define MAX77658_POWER_STEP 17100
+
+#define MAX77658_REG_STATUS 0x00
+#define MAX77658_REG_VALRTTH 0x01
+#define MAX77658_REG_TALRTTH 0x02
+#define MAX77658_REG_SALRTTH 0x03
+#define MAX77658_REG_CONFIG 0x1D
+#define MAX77658_REG_DEVNAME 0x21
+#define MAX77658_REG_VEMPTY 0x3A
+#define MAX77658_REG_AVGPOWER 0xB3
+#define MAX77658_REG_IALRTTH 0xB4
+#define MAX77658_REG_CONFIG2 0xBB
+#define MAX77658_REG_TEMP 0x08
+#define MAX77658_REG_VCELL 0x09
+#define MAX77658_REG_CURRENT 0x0A
+#define MAX77658_REG_AVGCURRENT 0x0B
+#define MAX77658_REG_AVGVCELL 0x19
+#define MAX77658_REG_MAXMINTEMP 0x1A
+#define MAX77658_REG_MAXMINVOLT 0x1B
+#define MAX77658_REG_MAXMINCURR 0x1C
+#define MAX77658_REG_REPSOC 0x06
+#define MAX77658_REG_TTE 0x11
+#define MAX77658_REG_TTF 0x20
+
+#define MAX77658_BIT_STATUS_BR BIT(15)
+#define MAX77658_BIT_STATUS_SMX BIT(14)
+#define MAX77658_BIT_STATUS_TMX BIT(13)
+#define MAX77658_BIT_STATUS_VMX BIT(12)
+#define MAX77658_BIT_STATUS_BI BIT(11)
+#define MAX77658_BIT_STATUS_SMN BIT(10)
+#define MAX77658_BIT_STATUS_TMN BIT(9)
+#define MAX77658_BIT_STATUS_VMN BIT(8)
+#define MAX77658_BIT_STATUS_POR BIT(2)
+#define MAX77658_BIT_CONFIG_AEN BIT(2)
+#define MAX77658_BIT_SALRTTH_SMIN GENMASK(7, 0)
+#define MAX77658_BIT_SALRTTH_SMAX GENMASK(15, 8)
+#define MAX77658_BIT_TALRTTH_TMIN GENMASK(7, 0)
+#define MAX77658_BIT_TALRTTH_TMAX GENMASK(15, 8)
+#define MAX77658_BIT_IALRTTH_IMIN GENMASK(7, 0)
+#define MAX77658_BIT_IALRTTH_IMAX GENMASK(15, 8)
+#define MAX77658_BIT_MAXMINTEMP_MIN GENMASK(7, 0)
+#define MAX77658_BIT_MAXMINTEMP_MAX GENMASK(15, 8)
+#define MAX77658_BIT_MAXMINVOLT_MIN GENMASK(7, 0)
+#define MAX77658_BIT_MAXMINVOLT_MAX GENMASK(15, 8)
+#define MAX77658_BIT_VEMPTY_VE GENMASK(15, 7)
+
+struct max77658_fg {
+ struct device *dev;
+ struct max77658_dev *max77658;
+ struct regmap *regmap;
+
+ struct delayed_work work;
+ struct power_supply *battery;
+ struct power_supply_desc psy_batt_d;
+
+ int vcell;
+ int soc;
+ int health;
+ int capacity_level;
+
+ int lasttime_vcell;
+ int lasttime_soc;
+
+ int volt_min_uv;
+ int volt_max_uv;
+ int temp_alert_min;
+ int temp_alert_max;
+ int curr_max_ma;
+ int curr_min_ma;
+};
+
+static int max77658_fg_get_soc(struct max77658_fg *max77658_fg)
+{
+ unsigned int soc;
+ int ret;
+
+ ret = regmap_read(max77658_fg->regmap, MAX77658_REG_REPSOC, &soc);
+ if (ret < 0) {
+ dev_dbg(max77658_fg->dev, "Error in reading register REPSOC\n");
+ return ret;
+ }
+
+ max77658_fg->soc = (u16)(soc >> 8);
+
+ if (max77658_fg->soc > MAX77658_BATTERY_FULL) {
+ max77658_fg->soc = MAX77658_BATTERY_FULL;
+ max77658_fg->capacity_level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
+ max77658_fg->health = POWER_SUPPLY_HEALTH_GOOD;
+ } else if (max77658_fg->soc < MAX77658_BATTERY_CRITICAL) {
+ max77658_fg->health = POWER_SUPPLY_HEALTH_DEAD;
+ max77658_fg->capacity_level =
+ POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
+ } else if (max77658_fg->soc < MAX77658_BATTERY_LOW) {
+ max77658_fg->health = POWER_SUPPLY_HEALTH_DEAD;
+ max77658_fg->capacity_level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
+ } else {
+ max77658_fg->health = POWER_SUPPLY_HEALTH_GOOD;
+ max77658_fg->capacity_level =
+ POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
+ }
+
+ return 0;
+}
+
+static void max77658_stop_work(void *data)
+{
+ struct max77658_fg *max77658_fg = data;
+
+ cancel_delayed_work_sync(&max77658_fg->work);
+}
+
+static u16 max77658_raw_voltage_to_uv(unsigned int val)
+{
+ return (u16)val * MAX77658_VOLTAGE_RESOLUTION;
+}
+
+static void max77658_fg_work(struct work_struct *work)
+{
+ struct max77658_fg *max77658_fg;
+ unsigned int val;
+ int ret;
+
+ max77658_fg = container_of(work, struct max77658_fg, work.work);
+
+ ret = regmap_read(max77658_fg->regmap, MAX77658_REG_VCELL, &val);
+ if (ret < 0)
+ dev_err(max77658_fg->dev, "Error in reading register\n");
+ else
+ max77658_fg->vcell = max77658_raw_voltage_to_uv(val);
+
+ ret = max77658_fg_get_soc(max77658_fg);
+ if (ret < 0)
+ goto out;
+
+ if (max77658_fg->vcell != max77658_fg->lasttime_vcell ||
+ max77658_fg->soc != max77658_fg->lasttime_soc) {
+ max77658_fg->lasttime_vcell = max77658_fg->vcell;
+ max77658_fg->lasttime_soc = max77658_fg->soc;
+
+ power_supply_changed(max77658_fg->battery);
+ }
+
+out:
+ schedule_delayed_work(&max77658_fg->work, MAX77658_FG_DELAY);
+}
+
+static enum power_supply_property max77658_fg_battery_props[] = {
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_VOLTAGE_AVG,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+ POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN,
+ POWER_SUPPLY_PROP_CAPACITY_ALERT_MAX,
+ POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_TEMP_ALERT_MIN,
+ POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CURRENT_MAX,
+ POWER_SUPPLY_PROP_CURRENT_AVG,
+ POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
+ POWER_SUPPLY_PROP_TIME_TO_FULL_AVG,
+ POWER_SUPPLY_PROP_TEMP_MAX,
+ POWER_SUPPLY_PROP_TEMP_MIN,
+ POWER_SUPPLY_PROP_POWER_AVG
+};
+
+static int max77658_property_is_writeable(struct power_supply *psy,
+ enum power_supply_property psp)
+{
+ switch (psp) {
+ case POWER_SUPPLY_PROP_TEMP_ALERT_MIN:
+ case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
+ case POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN:
+ case POWER_SUPPLY_PROP_CAPACITY_ALERT_MAX:
+ case POWER_SUPPLY_PROP_TEMP_MAX:
+ case POWER_SUPPLY_PROP_TEMP_MIN:
+ return 1;
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static u16 max77658_raw_current_to_ua(unsigned int val)
+{
+ return sign_extend32(val, 15) * MAX77658_CURRENT_RESOLUTION / 1000000;
+}
+
+static int max77658_fg_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct max77658_fg *max77658_fg = power_supply_get_drvdata(psy);
+ unsigned int reg_val;
+ u8 field_val;
+ int ret = 0;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_CAPACITY:
+ val->intval = max77658_fg->soc;
+ break;
+ case POWER_SUPPLY_PROP_HEALTH:
+ val->intval = max77658_fg->health;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
+ val->intval = max77658_fg->capacity_level;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ val->intval = max77658_fg->vcell;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_AVG:
+ ret = regmap_read(max77658_fg->regmap, MAX77658_REG_AVGVCELL,
+ ®_val);
+ if (ret)
+ return ret;
+
+ val->intval = max77658_raw_voltage_to_uv(reg_val);
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+ ret = regmap_read(max77658_fg->regmap, MAX77658_REG_MAXMINVOLT,
+ ®_val);
+ if (ret)
+ return ret;
+
+ val->intval = FIELD_GET(MAX77658_BIT_MAXMINVOLT_MAX, reg_val)
+ * MAX77658_MAXMINVOLT_STEP;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN:
+ ret = regmap_read(max77658_fg->regmap, MAX77658_REG_MAXMINVOLT,
+ ®_val);
+ if (ret)
+ return ret;
+
+ val->intval = FIELD_GET(MAX77658_BIT_MAXMINVOLT_MIN, reg_val)
+ * MAX77658_MAXMINVOLT_STEP;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+ ret = regmap_read(max77658_fg->regmap, MAX77658_REG_VEMPTY,
+ ®_val);
+ if (ret)
+ return ret;
+
+ val->intval = FIELD_GET(MAX77658_BIT_VEMPTY_VE, reg_val)
+ * MAX77658_VEMPTY_VE_STEP;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN:
+ ret = regmap_read(max77658_fg->regmap, MAX77658_REG_SALRTTH,
+ ®_val);
+ if (ret)
+ return ret;
+
+ val->intval = FIELD_GET(MAX77658_BIT_SALRTTH_SMIN, reg_val);
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY_ALERT_MAX:
+ ret = regmap_read(max77658_fg->regmap, MAX77658_REG_SALRTTH,
+ ®_val);
+ if (ret)
+ return ret;
+
+ val->intval = FIELD_GET(MAX77658_BIT_SALRTTH_SMAX, reg_val);
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ ret = regmap_read(max77658_fg->regmap, MAX77658_REG_TEMP,
+ ®_val);
+ if (ret)
+ return ret;
+
+ val->intval = sign_extend32(reg_val, 15);
+ val->intval = val->intval >> 8;
+ break;
+ case POWER_SUPPLY_PROP_TEMP_ALERT_MIN:
+ ret = regmap_read(max77658_fg->regmap, MAX77658_REG_TALRTTH,
+ ®_val);
+ if (ret)
+ return ret;
+
+ val->intval = sign_extend32(reg_val & 0xff, 7);
+ break;
+ case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
+ ret = regmap_read(max77658_fg->regmap, MAX77658_REG_TALRTTH,
+ ®_val);
+ if (ret)
+ return ret;
+
+ val->intval = sign_extend32(reg_val >> 8, 7);
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ ret = regmap_read(max77658_fg->regmap, MAX77658_REG_CURRENT,
+ ®_val);
+ if (ret)
+ return ret;
+
+ val->intval = max77658_raw_current_to_ua(reg_val);
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_AVG:
+ ret = regmap_read(max77658_fg->regmap, MAX77658_REG_AVGCURRENT,
+ ®_val);
+ if (ret)
+ return ret;
+
+ val->intval = max77658_raw_current_to_ua(reg_val);
+ break;
+ case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
+ ret = regmap_read(max77658_fg->regmap, MAX77658_REG_TTE,
+ ®_val);
+ if (ret)
+ return ret;
+
+ val->intval = (reg_val * 45) >> 3;
+ break;
+ case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG:
+ ret = regmap_read(max77658_fg->regmap, MAX77658_REG_TTF,
+ ®_val);
+ if (ret)
+ return ret;
+
+ val->intval = (reg_val * 45) >> 3;
+ break;
+ case POWER_SUPPLY_PROP_TEMP_MIN:
+ ret = regmap_read(max77658_fg->regmap, MAX77658_REG_MAXMINTEMP,
+ ®_val);
+ if (ret)
+ return ret;
+
+ field_val = FIELD_GET(MAX77658_BIT_MAXMINTEMP_MIN, reg_val);
+ val->intval = sign_extend32(field_val, 7);
+ break;
+ case POWER_SUPPLY_PROP_TEMP_MAX:
+ ret = regmap_read(max77658_fg->regmap, MAX77658_REG_MAXMINTEMP,
+ ®_val);
+ if (ret)
+ return ret;
+
+ field_val = FIELD_GET(MAX77658_BIT_MAXMINTEMP_MAX, reg_val);
+ val->intval = sign_extend32(field_val, 7);
+
+ break;
+ case POWER_SUPPLY_PROP_POWER_AVG:
+ ret = regmap_read(max77658_fg->regmap, MAX77658_REG_AVGPOWER,
+ ®_val);
+ if (ret)
+ return ret;
+
+ val->intval = reg_val * MAX77658_POWER_STEP;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_MAX:
+ ret = regmap_read(max77658_fg->regmap, MAX77658_REG_MAXMINCURR,
+ ®_val);
+ if (ret)
+ return ret;
+
+ val->intval = FIELD_GET(MAX77658_BIT_MAXMINTEMP_MAX, reg_val)
+ * MAX77658_IALRTTH_RESOLUTION;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int max77658_fg_set_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ const union power_supply_propval *val)
+{
+ struct max77658_fg *max77658_fg = power_supply_get_drvdata(psy);
+ int ret = 0;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_TEMP_ALERT_MIN:
+ ret = regmap_update_bits(max77658_fg->regmap,
+ MAX77658_REG_TALRTTH,
+ MAX77658_BIT_TALRTTH_TMIN,
+ val->intval);
+ break;
+ case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
+ ret = regmap_update_bits(max77658_fg->regmap,
+ MAX77658_REG_TALRTTH,
+ MAX77658_BIT_TALRTTH_TMAX,
+ val->intval);
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN:
+ ret = regmap_update_bits(max77658_fg->regmap,
+ MAX77658_REG_SALRTTH,
+ MAX77658_BIT_SALRTTH_SMIN,
+ val->intval);
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY_ALERT_MAX:
+ ret = regmap_update_bits(max77658_fg->regmap,
+ MAX77658_REG_SALRTTH,
+ MAX77658_BIT_SALRTTH_SMAX,
+ val->intval);
+ break;
+ case POWER_SUPPLY_PROP_TEMP_MIN:
+ ret = regmap_update_bits(max77658_fg->regmap,
+ MAX77658_REG_MAXMINTEMP,
+ MAX77658_BIT_MAXMINTEMP_MIN,
+ val->intval);
+ break;
+ case POWER_SUPPLY_PROP_TEMP_MAX:
+ ret = regmap_update_bits(max77658_fg->regmap,
+ MAX77658_REG_MAXMINTEMP,
+ MAX77658_BIT_MAXMINTEMP_MAX,
+ val->intval);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int max77658_set_alert_thresholds(struct max77658_fg *max77658_fg)
+{
+ unsigned int val;
+ int ret;
+
+ val = (max77658_fg->volt_min_uv / MAX77658_VALRTTH_STEP);
+ val |= ((max77658_fg->volt_max_uv / MAX77658_VALRTTH_STEP) << 8);
+ ret = regmap_write(max77658_fg->regmap, MAX77658_REG_VALRTTH, val);
+ if (ret)
+ return dev_err_probe(max77658_fg->dev, ret,
+ "Error in writing register VALRTTH\n");
+
+ val = FIELD_PREP(MAX77658_BIT_TALRTTH_TMAX, max77658_fg->temp_alert_max)
+ | FIELD_PREP(MAX77658_BIT_TALRTTH_TMIN, max77658_fg->temp_alert_min);
+ ret = regmap_write(max77658_fg->regmap, MAX77658_REG_TALRTTH, val);
+ if (ret)
+ return dev_err_probe(max77658_fg->dev, ret,
+ "Error in writing register TALRTTH\n");
+
+ val = FIELD_PREP(MAX77658_BIT_SALRTTH_SMAX, MAX77658_SALRT_MAX_DEFAULT)
+ | FIELD_PREP(MAX77658_BIT_SALRTTH_SMIN, MAX77658_SALRT_MIN_DEFAULT);
+ ret = regmap_write(max77658_fg->regmap, MAX77658_REG_SALRTTH, val);
+ if (ret)
+ return dev_err_probe(max77658_fg->dev, ret,
+ "Error in writing register SALRTTH\n");
+
+ val = FIELD_PREP(MAX77658_BIT_IALRTTH_IMAX,
+ max77658_fg->curr_max_ma / MAX77658_IALRTTH_RESOLUTION)
+ | FIELD_PREP(MAX77658_BIT_IALRTTH_IMIN,
+ (max77658_fg->curr_min_ma / MAX77658_IALRTTH_RESOLUTION));
+
+ return regmap_write(max77658_fg->regmap, MAX77658_REG_IALRTTH, val);
+}
+
+static int max77658_fg_initialize(struct max77658_fg *max77658_fg)
+{
+ unsigned int reg;
+ int ret;
+
+ ret = max77658_set_alert_thresholds(max77658_fg);
+ if (ret)
+ return dev_err_probe(max77658_fg->dev, ret,
+ "Error in setting alert thresholds\n");
+
+ ret = regmap_read(max77658_fg->regmap, MAX77658_REG_STATUS, ®);
+ if (ret)
+ return dev_err_probe(max77658_fg->dev, ret,
+ "Error in reading register STATUS\n");
+
+ ret = regmap_write(max77658_fg->regmap, MAX77658_REG_STATUS,
+ reg & ~MAX77658_BIT_STATUS_POR);
+ if (ret)
+ return dev_err_probe(max77658_fg->dev, ret,
+ "Error in writing register STATUS\n");
+
+ schedule_delayed_work(&max77658_fg->work, MAX77658_FG_DELAY);
+ return 0;
+}
+
+static void max77658_fg_parse_dt(struct max77658_fg *max77658_fg)
+{
+ struct device *dev = max77658_fg->dev;
+ int ret;
+
+ ret = device_property_read_u32(dev, "adi,valrt-min-microvolt",
+ &max77658_fg->volt_min_uv);
+ if (ret) {
+ dev_dbg(dev,
+ "Could not read adi,valrt-min-microvolt DT property\n");
+ max77658_fg->volt_min_uv = 0;
+ }
+
+ ret = device_property_read_u32(dev, "adi,valrt-max-microvolt",
+ &max77658_fg->volt_max_uv);
+ if (ret) {
+ dev_dbg(dev,
+ "Could not read adi,valrt-max-microvolt DT property\n");
+ max77658_fg->volt_max_uv = 5100000;
+ }
+
+ ret = device_property_read_u32(dev, "adi,ialrt-min-microamp",
+ &max77658_fg->curr_min_ma);
+ if (ret) {
+ dev_dbg(dev,
+ "Could not read adi,ialrt-min-microamp DT property\n");
+ max77658_fg->curr_min_ma = MAX77658_IALRTTH_RESOLUTION * (-128);
+ }
+
+ ret = device_property_read_u32(dev, "adi,ialrt-max-microamp",
+ &max77658_fg->curr_max_ma);
+ if (ret) {
+ dev_dbg(dev,
+ "Could not read adi,ialrt-max-microamp DT property\n");
+ max77658_fg->curr_max_ma = MAX77658_IALRTTH_RESOLUTION * 127;
+ }
+}
+
+static int max77658_fg_probe(struct platform_device *pdev)
+{
+ struct max77658_dev *max77658 = dev_get_drvdata(pdev->dev.parent);
+ struct power_supply_battery_info *info;
+ struct power_supply_config fg_cfg = {};
+ struct device *dev = &pdev->dev;
+ struct max77658_fg *fg;
+ int ret = 0;
+
+ fg = devm_kzalloc(&pdev->dev, sizeof(*fg), GFP_KERNEL);
+ if (!fg)
+ return -ENOMEM;
+
+ fg->dev = &pdev->dev;
+ fg->regmap = max77658->regmap_fg;
+
+ fg->psy_batt_d.name = "max77658-battery";
+ fg->psy_batt_d.type = POWER_SUPPLY_TYPE_BATTERY;
+ fg->psy_batt_d.get_property = max77658_fg_get_property;
+ fg->psy_batt_d.set_property = max77658_fg_set_property;
+ fg->psy_batt_d.properties = max77658_fg_battery_props;
+ fg->psy_batt_d.property_is_writeable = max77658_property_is_writeable;
+ fg->psy_batt_d.num_properties = ARRAY_SIZE(max77658_fg_battery_props);
+ fg_cfg.drv_data = fg;
+
+ INIT_DELAYED_WORK(&fg->work, max77658_fg_work);
+ ret = devm_add_action(&pdev->dev, max77658_stop_work, fg);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "Error in setting delayed work\n");
+
+ fg->battery = devm_power_supply_register(dev, &fg->psy_batt_d,
+ &fg_cfg);
+ if (IS_ERR(fg->battery))
+ return dev_err_probe(&pdev->dev, PTR_ERR(fg->battery),
+ "Failed to register battery\n");
+
+ fg->battery->of_node = of_get_child_by_name(dev->parent->of_node,
+ "fuel-gauge");
+
+ if (!fg->battery->of_node)
+ dev_err(dev,
+ "of_get_child_by_name\n");
+
+ ret = power_supply_get_battery_info(fg->battery, &info);
+ if (ret) {
+ dev_err(fg->dev, "Unable to get battery info\n");
+ fg->temp_alert_min = info->temp_alert_min;
+ fg->temp_alert_max = info->temp_alert_max;
+ } else {
+ fg->temp_alert_min = -128;
+ fg->temp_alert_max = 127;
+ }
+
+ max77658_fg_parse_dt(fg);
+
+ ret = max77658_fg_initialize(fg);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Error in initializing fuel gauge\n");
+ return 0;
+}
+
+static const struct of_device_id max77658_battery_of_id[] = {
+ { .compatible = "adi,max77658-battery" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, max77658_battery_of_id);
+
+static const struct platform_device_id max77658_fg_id[] = {
+ { "max77658-battery", 0 },
+ { },
+};
+MODULE_DEVICE_TABLE(platform, max77658_fg_id);
+
+static struct platform_driver max77658_fg_driver = {
+ .driver = {
+ .name = "max77658-battery",
+ .of_match_table = max77658_battery_of_id,
+ },
+ .probe = max77658_fg_probe,
+ .id_table = max77658_fg_id,
+};
+
+module_platform_driver(max77658_fg_driver);
+
+MODULE_DESCRIPTION("MAX77658 Fuel Gauge Driver");
+MODULE_AUTHOR("Nurettin.Bolucu@analog.com, Zeynep.Arslanbenzer@analog.com");
+MODULE_LICENSE("GPL");
--
2.25.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v3 6/7] dt-bindings: mfd: max77658: Add ADI MAX77658
2023-05-08 13:10 [PATCH v3 0/7] Add MAX77643/MAX77654/MAX77658/MAX77659 PMIC Support Zeynep Arslanbenzer
` (4 preceding siblings ...)
2023-05-08 13:10 ` [PATCH v3 5/7] power: supply: max77658: Add ADI MAX77658 Battery Support Zeynep Arslanbenzer
@ 2023-05-08 13:10 ` Zeynep Arslanbenzer
2023-05-08 14:31 ` Krzysztof Kozlowski
2023-05-08 20:02 ` Krzysztof Kozlowski
2023-05-08 13:10 ` [PATCH v3 7/7] mfd: max77658: Add ADI MAX77643/54/58/59 MFD Support Zeynep Arslanbenzer
6 siblings, 2 replies; 22+ messages in thread
From: Zeynep Arslanbenzer @ 2023-05-08 13:10 UTC (permalink / raw)
To: lee, robh+dt, krzysztof.kozlowski+dt, sre, lgirdwood, broonie
Cc: Zeynep.Arslanbenzer, linux-kernel, devicetree, linux-pm, Nurettin Bolucu
Add ADI MAX77658 devicetree document.
Signed-off-by: Nurettin Bolucu <Nurettin.Bolucu@analog.com>
Signed-off-by: Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
---
.../devicetree/bindings/mfd/adi,max77658.yaml | 160 ++++++++++++++++++
1 file changed, 160 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mfd/adi,max77658.yaml
diff --git a/Documentation/devicetree/bindings/mfd/adi,max77658.yaml b/Documentation/devicetree/bindings/mfd/adi,max77658.yaml
new file mode 100644
index 000000000000..4d6d87cd4b52
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/adi,max77658.yaml
@@ -0,0 +1,160 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/adi,max77658.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MAX77643/54/58/59 PMIC from ADI
+
+maintainers:
+ - Nurettin Bolucu <Nurettin.Bolucu@analog.com>
+ - Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
+
+description: |
+ MAX77643, MAX77654, MAX77658 and MAX77659 devices are a family of ADI PMICs
+ providing battery charging and power supply solutions for
+ low-power applications.
+
+ MAX77643 is a Power Management IC with 1 LDO regulator.
+
+ MAX77654 is a Power Management IC with 2 LDO regulators and 1 charger.
+
+ MAX77658 is a Power Management IC with 2 LDO regulators, 1 charger
+ and 1 fuel gauge.
+
+ MAX77659 is a Power Management IC with 1 LDO regulator and 1 charger.
+
+properties:
+ compatible:
+ enum:
+ - adi,max77643
+ - adi,max77654
+ - adi,max77658
+ - adi,max77659
+
+ reg:
+ items:
+ - enum: [0x40, 0x48]
+
+ interrupts:
+ maxItems: 1
+
+ charger:
+ $ref: /schemas/power/supply/adi,max77658-charger.yaml
+
+ fuel-gauge:
+ $ref: /schemas/power/supply/adi,max77658-battery.yaml
+
+ regulators:
+ type: object
+
+ description:
+ The regulators is represented as a sub-node of the PMIC node on the device tree.
+
+ patternProperties:
+ "^LDO[01]$":
+ type: object
+ $ref: /schemas/regulator/regulator.yaml
+ additionalProperties: false
+ description:
+ LDO regulator
+
+ properties:
+ regulator-always-on: true
+ regulator-boot-on: true
+
+ additionalProperties: false
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - adi,max77643
+ - adi,max77654
+ - adi,max77658
+
+ then:
+ properties:
+ reg:
+ items:
+ - const: 0x48
+
+ else:
+ properties:
+ reg:
+ items:
+ - const: 0x40
+
+required:
+ - compatible
+ - reg
+ - interrupts
+
+additionalProperties: false
+
+examples:
+ - |
+ battery: battery-cell {
+ compatible = "simple-battery";
+ alert-celsius = <0 100>;
+ constant-charge-current-max-microamp = <15000>;
+ };
+ #include <dt-bindings/interrupt-controller/irq.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pmic@48 {
+ compatible = "adi,max77658";
+ reg = <0x48>;
+ interrupt-parent = <&gpio>;
+ interrupts = <16 IRQ_TYPE_EDGE_FALLING>;
+ charger {
+ compatible = "adi,max77658-charger";
+ monitored-battery = <&battery>;
+ adi,input-current-limit-microamp = <475000>;
+ };
+ regulators {
+ LDO0 {
+ regulator-boot-on;
+ regulator-always-on;
+ };
+ LDO1 {
+ regulator-boot-on;
+ regulator-always-on;
+ };
+ };
+ fuel-gauge {
+ compatible = "adi,max77658-battery";
+ monitored-battery = <&battery>;
+ adi,valrt-min-microvolt = <0>;
+ adi,valrt-max-microvolt = <5100000>;
+ adi,ialrt-min-microamp = <(-5000)>;
+ adi,ialrt-max-microamp = <5000>;
+ };
+ };
+ };
+
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pmic@40 {
+ compatible = "adi,max77659";
+ reg = <0x40>;
+ interrupt-parent = <&gpio>;
+ interrupts = <16 IRQ_TYPE_EDGE_FALLING>;
+ charger {
+ compatible = "adi,max77659-charger";
+ monitored-battery = <&battery>;
+ };
+ regulators {
+ LDO0 {
+ regulator-boot-on;
+ regulator-always-on;
+ };
+ };
+ };
+ };
--
2.25.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v3 7/7] mfd: max77658: Add ADI MAX77643/54/58/59 MFD Support
2023-05-08 13:10 [PATCH v3 0/7] Add MAX77643/MAX77654/MAX77658/MAX77659 PMIC Support Zeynep Arslanbenzer
` (5 preceding siblings ...)
2023-05-08 13:10 ` [PATCH v3 6/7] dt-bindings: mfd: max77658: Add ADI MAX77658 Zeynep Arslanbenzer
@ 2023-05-08 13:10 ` Zeynep Arslanbenzer
2023-05-08 20:09 ` Krzysztof Kozlowski
6 siblings, 1 reply; 22+ messages in thread
From: Zeynep Arslanbenzer @ 2023-05-08 13:10 UTC (permalink / raw)
To: lee, robh+dt, krzysztof.kozlowski+dt, sre, lgirdwood, broonie
Cc: Zeynep.Arslanbenzer, linux-kernel, devicetree, linux-pm, Nurettin Bolucu
MFD driver for MAX77643/54/58/59 to enable its sub
devices.
The MAX77643 is a multi-function devices. It includes
regulator.
The MAX77654 is a multi-function devices. It includes
regulator and charger.
The MAX77658 is a multi-function devices. It includes
regulator, charger and battery.
The MAX77659 is a multi-function devices. It includes
regulator and charger.
Signed-off-by: Nurettin Bolucu <Nurettin.Bolucu@analog.com>
Signed-off-by: Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
---
drivers/mfd/Kconfig | 13 ++
drivers/mfd/Makefile | 1 +
drivers/mfd/max77658.c | 426 +++++++++++++++++++++++++++++++++++
include/linux/mfd/max77658.h | 80 +++++++
4 files changed, 520 insertions(+)
create mode 100644 drivers/mfd/max77658.c
create mode 100644 include/linux/mfd/max77658.h
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 8b93856de432..aa1630a6d33a 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -821,6 +821,19 @@ config MFD_MAX77650
the following functionalities of the device: GPIO, regulator,
charger, LED, onkey.
+config MFD_MAX77658
+ tristate "Analog Devices MAX77643/54/58/59 PMIC Support"
+ depends on I2C
+ depends on OF
+ select MFD_CORE
+ select REGMAP_I2C
+ select REGMAP_IRQ
+ help
+ Say Y here to add support for Analog Devices MAX77643/54/58/59
+ Power Management ICs. This is the core driver for interacting
+ with the device. Additional drivers must be enabled in order to use the
+ regulator, charger, and battery functionalities of the device.
+
config MFD_MAX77686
tristate "Maxim Semiconductor MAX77686/802 PMIC Support"
depends on I2C
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 7ed3ef4a698c..f52aff45878f 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -163,6 +163,7 @@ obj-$(CONFIG_MFD_DA9150) += da9150-core.o
obj-$(CONFIG_MFD_MAX14577) += max14577.o
obj-$(CONFIG_MFD_MAX77620) += max77620.o
obj-$(CONFIG_MFD_MAX77650) += max77650.o
+obj-$(CONFIG_MFD_MAX77658) += max77658.o
obj-$(CONFIG_MFD_MAX77686) += max77686.o
obj-$(CONFIG_MFD_MAX77693) += max77693.o
obj-$(CONFIG_MFD_MAX77714) += max77714.o
diff --git a/drivers/mfd/max77658.c b/drivers/mfd/max77658.c
new file mode 100644
index 000000000000..2eab1133cdc8
--- /dev/null
+++ b/drivers/mfd/max77658.c
@@ -0,0 +1,426 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 Analog Devices, Inc.
+ * ADI driver for the MAX77643/54/58/59
+ */
+
+#include <linux/i2c.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/max77658.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+
+#define I2C_ADDR_FUEL_GAUGE (0x6C >> 1)
+
+static const struct regmap_config max77658_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+};
+
+static const struct regmap_config max77658_regmap_config_fg = {
+ .reg_bits = 8,
+ .val_bits = 16,
+ .cache_type = REGCACHE_NONE,
+ .val_format_endian = REGMAP_ENDIAN_LITTLE,
+};
+
+static const struct regmap_irq max77643_glbl0_irqs[] = {
+ { .mask = MAX77658_BIT_INT_GLBL0_GPIO0_F, },
+ { .mask = MAX77658_BIT_INT_GLBL0_GPIO0_R, },
+ { .mask = MAX77658_BIT_INT_GLBL0_EN_F, },
+ { .mask = MAX77658_BIT_INT_GLBL0_EN_R, },
+ { .mask = MAX77658_BIT_INT_GLBL0_TJAL1_R, },
+ { .mask = MAX77658_BIT_INT_GLBL0_TJAL2_R, },
+ { .mask = MAX77643_BIT_INT_GLBL0_DOD0_R, },
+};
+
+static const struct regmap_irq_chip max77643_glbl0_irq_chip = {
+ .name = "max77643_glbl0",
+ .status_base = MAX77658_REG_INT_GLBL0,
+ .mask_base = MAX77643_REG_INTM_GLBL0,
+ .num_regs = 1,
+ .irqs = max77643_glbl0_irqs,
+ .num_irqs = ARRAY_SIZE(max77643_glbl0_irqs),
+};
+
+static const struct regmap_irq max77658_glbl0_irqs[] = {
+ { .mask = MAX77658_BIT_INT_GLBL0_GPIO0_F, },
+ { .mask = MAX77658_BIT_INT_GLBL0_GPIO0_R, },
+ { .mask = MAX77658_BIT_INT_GLBL0_EN_F, },
+ { .mask = MAX77658_BIT_INT_GLBL0_EN_R, },
+ { .mask = MAX77658_BIT_INT_GLBL0_TJAL1_R, },
+ { .mask = MAX77658_BIT_INT_GLBL0_TJAL2_R, },
+ { .mask = MAX77658_BIT_INT_GLBL0_DOD1_R, },
+ { .mask = MAX77658_BIT_INT_GLBL0_DOD0_R, },
+};
+
+static const struct regmap_irq_chip max77654_glbl0_irq_chip = {
+ .name = "max77654_glbl0",
+ .status_base = MAX77658_REG_INT_GLBL0,
+ .mask_base = MAX77654_REG_INTM_GLBL0,
+ .num_regs = 1,
+ .irqs = max77658_glbl0_irqs,
+ .num_irqs = ARRAY_SIZE(max77658_glbl0_irqs),
+};
+
+static const struct regmap_irq_chip max77658_glbl0_irq_chip = {
+ .name = "max77658_glbl0",
+ .status_base = MAX77658_REG_INT_GLBL0,
+ .mask_base = MAX77658_REG_INTM_GLBL0,
+ .num_regs = 1,
+ .irqs = max77658_glbl0_irqs,
+ .num_irqs = ARRAY_SIZE(max77658_glbl0_irqs),
+};
+
+static const struct regmap_irq max77659_glbl0_irqs[] = {
+ { .mask = MAX77658_BIT_INT_GLBL0_GPIO0_F, },
+ { .mask = MAX77658_BIT_INT_GLBL0_GPIO0_R, },
+ { .mask = MAX77658_BIT_INT_GLBL0_EN_F, },
+ { .mask = MAX77658_BIT_INT_GLBL0_EN_R, },
+ { .mask = MAX77658_BIT_INT_GLBL0_TJAL1_R, },
+ { .mask = MAX77658_BIT_INT_GLBL0_TJAL2_R, },
+ { .mask = MAX77658_BIT_INT_GLBL0_DOD0_R, },
+};
+
+static const struct regmap_irq_chip max77659_glbl0_irq_chip = {
+ .name = "max77659_glbl0",
+ .status_base = MAX77658_REG_INT_GLBL0,
+ .mask_base = MAX77654_REG_INTM_GLBL0,
+ .num_regs = 1,
+ .irqs = max77659_glbl0_irqs,
+ .num_irqs = ARRAY_SIZE(max77659_glbl0_irqs),
+};
+
+static const struct regmap_irq max77643_glbl1_irqs[] = {
+ { .mask = MAX77658_BIT_INT_GLBL1_GPI1_F, },
+ { .mask = MAX77658_BIT_INT_GLBL1_GPI1_R, },
+ { .mask = MAX77658_BIT_INT_GLBL1_SBB0_F, },
+ { .mask = MAX77658_BIT_INT_GLBL1_SBB1_F, },
+ { .mask = MAX77658_BIT_INT_GLBL1_SBB2_F, },
+ { .mask = MAX77658_BIT_INT_GLBL1_LDO0_F, },
+};
+
+static const struct regmap_irq_chip max77643_glbl1_irq_chip = {
+ .name = "max77643_glbl1",
+ .status_base = MAX77658_REG_INT_GLBL1,
+ .mask_base = MAX77643_REG_INTM_GLBL1,
+ .num_regs = 1,
+ .irqs = max77643_glbl1_irqs,
+ .num_irqs = ARRAY_SIZE(max77643_glbl1_irqs),
+};
+
+static const struct regmap_irq max77654_glbl1_irqs[] = {
+ { .mask = MAX77658_BIT_INT_GLBL1_GPI1_F, },
+ { .mask = MAX77658_BIT_INT_GLBL1_GPI1_R, },
+ { .mask = MAX77654_BIT_INT_GLBL1_GPI2_F, },
+ { .mask = MAX77654_BIT_INT_GLBL1_GPI2_R, },
+ { .mask = MAX77654_BIT_INT_GLBL1_SBB_TO, },
+ { .mask = MAX77658_BIT_INT_GLBL1_LDO0_F, },
+ { .mask = MAX77658_BIT_INT_GLBL1_LDO1_F, },
+};
+
+static const struct regmap_irq_chip max77654_glbl1_irq_chip = {
+ .name = "max77654_glbl1",
+ .status_base = MAX77658_REG_INT_GLBL1,
+ .mask_base = MAX77654_REG_INTM_GLBL1,
+ .num_regs = 1,
+ .irqs = max77654_glbl1_irqs,
+ .num_irqs = ARRAY_SIZE(max77654_glbl1_irqs),
+};
+
+static const struct regmap_irq max77658_glbl1_irqs[] = {
+ { .mask = MAX77658_BIT_INT_GLBL1_GPI1_F, },
+ { .mask = MAX77658_BIT_INT_GLBL1_GPI1_R, },
+ { .mask = MAX77658_BIT_INT_GLBL1_SBB0_F, },
+ { .mask = MAX77658_BIT_INT_GLBL1_SBB1_F, },
+ { .mask = MAX77658_BIT_INT_GLBL1_SBB2_F, },
+ { .mask = MAX77658_BIT_INT_GLBL1_LDO0_F, },
+ { .mask = MAX77658_BIT_INT_GLBL1_LDO1_F, },
+};
+
+static const struct regmap_irq_chip max77658_glbl1_irq_chip = {
+ .name = "max77658_glbl1",
+ .status_base = MAX77658_REG_INT_GLBL1,
+ .mask_base = MAX77658_REG_INTM_GLBL1,
+ .num_regs = 1,
+ .irqs = max77658_glbl1_irqs,
+ .num_irqs = ARRAY_SIZE(max77658_glbl1_irqs),
+};
+
+static const struct regmap_irq max77659_glbl1_irqs[] = {
+ { .mask = MAX77658_BIT_INT_GLBL1_GPI1_F, },
+ { .mask = MAX77658_BIT_INT_GLBL1_GPI1_R, },
+ { .mask = MAX77659_BIT_INT_GLBL1_SBB_TO, },
+ { .mask = MAX77658_BIT_INT_GLBL1_LDO0_F, },
+};
+
+static const struct regmap_irq_chip max77659_glbl1_irq_chip = {
+ .name = "max77659_glbl1",
+ .status_base = MAX77658_REG_INT_GLBL1,
+ .mask_base = MAX77658_REG_INTM_GLBL1,
+ .num_regs = 1,
+ .irqs = max77659_glbl1_irqs,
+ .num_irqs = ARRAY_SIZE(max77659_glbl1_irqs),
+};
+
+static const struct regmap_irq max77658_chg_irqs[] = {
+ { .mask = MAX77658_BIT_INT_THM, },
+ { .mask = MAX77658_BIT_INT_CHG, },
+ { .mask = MAX77658_BIT_INT_CHGIN, },
+ { .mask = MAX77658_BIT_INT_TJ_REG, },
+ { .mask = MAX77658_BIT_INT_CHGIN_CTRL, },
+ { .mask = MAX77658_BIT_INT_SYS_CTRL, },
+ { .mask = MAX77658_BIT_INT_SYS_CNFG, },
+};
+
+static const struct regmap_irq_chip max77654_chg_irq_chip = {
+ .name = "max77654_chg",
+ .status_base = MAX77658_REG_INT_CHG,
+ .mask_base = MAX77658_REG_INTM_CHG,
+ .num_regs = 1,
+ .irqs = max77658_chg_irqs,
+ .num_irqs = ARRAY_SIZE(max77658_chg_irqs),
+};
+
+static const struct regmap_irq_chip max77658_chg_irq_chip = {
+ .name = "max77658_chg",
+ .status_base = MAX77658_REG_INT_CHG,
+ .mask_base = MAX77658_REG_INTM_CHG,
+ .num_regs = 1,
+ .irqs = max77658_chg_irqs,
+ .num_irqs = ARRAY_SIZE(max77658_chg_irqs),
+};
+
+static const struct regmap_irq max77659_chg_irqs[] = {
+ { .mask = MAX77658_BIT_INT_THM, },
+ { .mask = MAX77658_BIT_INT_CHG, },
+ { .mask = MAX77658_BIT_INT_CHGIN, },
+ { .mask = MAX77658_BIT_INT_TJ_REG, },
+ { .mask = MAX77659_BIT_INT_SYS_CTRL, },
+};
+
+static const struct regmap_irq_chip max77659_chg_irq_chip = {
+ .name = "max77659_chg",
+ .status_base = MAX77658_REG_INT_CHG,
+ .mask_base = MAX77658_REG_INTM_CHG,
+ .num_regs = 1,
+ .irqs = max77659_chg_irqs,
+ .num_irqs = ARRAY_SIZE(max77659_chg_irqs),
+};
+
+static const struct mfd_cell max77643_devs[] = {
+ MFD_CELL_NAME("max77658-regulator"),
+};
+
+static const struct mfd_cell max77654_devs[] = {
+ MFD_CELL_NAME("max77658-regulator"),
+ MFD_CELL_OF("max77654-charger", NULL, NULL, 0, 0,
+ "adi,max77654-charger"),
+};
+
+static const struct mfd_cell max77658_devs[] = {
+ MFD_CELL_NAME("max77658-regulator"),
+ MFD_CELL_OF("max77658-charger", NULL, NULL, 0, 0,
+ "adi,max77658-charger"),
+ MFD_CELL_OF("max77658-battery", NULL, NULL, 0, 0,
+ "adi,max77658-battery"),
+};
+
+static const struct mfd_cell max77659_devs[] = {
+ MFD_CELL_NAME("max77658-regulator"),
+ MFD_CELL_OF("max77659-charger", NULL, NULL, 0, 0,
+ "adi,max77659-charger"),
+};
+
+static int max77658_pmic_irq_init(struct device *dev)
+{
+ const struct regmap_irq_chip *glbl0_chip, *glbl1_chip, *chg_chip;
+ struct max77658_dev *max77658 = dev_get_drvdata(dev);
+ int ret, i;
+
+ switch (max77658->id) {
+ case ID_MAX77643:
+ glbl0_chip = &max77643_glbl0_irq_chip;
+ glbl1_chip = &max77643_glbl1_irq_chip;
+ break;
+ case ID_MAX77654:
+ glbl0_chip = &max77654_glbl0_irq_chip;
+ glbl1_chip = &max77654_glbl1_irq_chip;
+ chg_chip = &max77654_chg_irq_chip;
+ break;
+ case ID_MAX77658:
+ glbl0_chip = &max77658_glbl0_irq_chip;
+ glbl1_chip = &max77658_glbl1_irq_chip;
+ chg_chip = &max77658_chg_irq_chip;
+ break;
+ case ID_MAX77659:
+ glbl0_chip = &max77659_glbl0_irq_chip;
+ glbl1_chip = &max77659_glbl1_irq_chip;
+ chg_chip = &max77659_chg_irq_chip;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (i = 0; i < glbl0_chip->num_regs; i++) {
+ ret = regmap_update_bits(max77658->regmap,
+ glbl0_chip->mask_base,
+ (1 << glbl0_chip->irqs[i].reg_offset),
+ 1);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Unable to write Global0 Interrupt Masking register\n");
+ }
+
+ for (i = 0; i < glbl1_chip->num_regs; i++) {
+ ret = regmap_update_bits(max77658->regmap,
+ glbl1_chip->mask_base,
+ (1 << glbl1_chip->irqs[i].reg_offset),
+ 1);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Unable to write Global1 Interrupt Masking register\n");
+ }
+
+ if (max77658->id != ID_MAX77643) {
+ for (i = 0; i < chg_chip->num_regs; i++) {
+ ret = regmap_update_bits(max77658->regmap,
+ chg_chip->mask_base,
+ (1 <<
+ chg_chip->irqs[i].reg_offset),
+ 1);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Unable to write Charger Interrupt Masking register\n");
+ }
+
+ ret = devm_regmap_add_irq_chip(dev, max77658->regmap,
+ max77658->irq,
+ IRQF_ONESHOT | IRQF_SHARED, 0,
+ chg_chip, &max77658->irqc_chg);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to add charger IRQ chip\n");
+ }
+
+ ret = devm_regmap_add_irq_chip(dev, max77658->regmap, max77658->irq,
+ IRQF_ONESHOT | IRQF_SHARED, 0,
+ glbl0_chip, &max77658->irqc_glbl0);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to add global0 IRQ chip\n");
+
+ return devm_regmap_add_irq_chip(dev, max77658->regmap, max77658->irq,
+ IRQF_ONESHOT | IRQF_SHARED, 0,
+ glbl1_chip, &max77658->irqc_glbl1);
+}
+
+static int max77658_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct device *dev = &client->dev;
+ struct max77658_dev *max77658;
+ const struct mfd_cell *cells;
+ struct i2c_client *fuel;
+ int ret, n_devs;
+
+ max77658 = devm_kzalloc(dev, sizeof(*max77658), GFP_KERNEL);
+ if (!max77658)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, max77658);
+ max77658->irq = client->irq;
+
+ max77658->id = (enum max77658_ids)device_get_match_data(dev);
+ if (!max77658->id)
+ max77658->id = (enum max77658_ids)id->driver_data;
+
+ if (!max77658->id)
+ return -EINVAL;
+
+ max77658->regmap = devm_regmap_init_i2c(client,
+ &max77658_regmap_config);
+ if (IS_ERR(max77658->regmap))
+ return dev_err_probe(dev, PTR_ERR(max77658->regmap),
+ "Failed to initialize regmap\n");
+
+ fuel = i2c_new_dummy_device(client->adapter, I2C_ADDR_FUEL_GAUGE);
+ if (IS_ERR(fuel))
+ return dev_err_probe(dev, PTR_ERR(fuel),
+ "Failed to create I2C device[0x%Xh]\n",
+ I2C_ADDR_FUEL_GAUGE);
+
+ i2c_set_clientdata(fuel, max77658);
+
+ max77658->regmap_fg = devm_regmap_init_i2c(fuel,
+ &max77658_regmap_config_fg);
+ if (IS_ERR(max77658->regmap_fg))
+ return dev_err_probe(dev,
+ PTR_ERR(max77658->regmap_fg),
+ "Failed to initialize I2C device[0x%Xh]\n",
+ I2C_ADDR_FUEL_GAUGE);
+
+ ret = max77658_pmic_irq_init(dev);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "Failed to initialize IRQ\n");
+
+ switch (max77658->id) {
+ case ID_MAX77643:
+ cells = max77643_devs;
+ n_devs = ARRAY_SIZE(max77643_devs);
+ break;
+ case ID_MAX77654:
+ cells = max77654_devs;
+ n_devs = ARRAY_SIZE(max77654_devs);
+ break;
+ case ID_MAX77658:
+ cells = max77658_devs;
+ n_devs = ARRAY_SIZE(max77658_devs);
+ break;
+ case ID_MAX77659:
+ cells = max77659_devs;
+ n_devs = ARRAY_SIZE(max77659_devs);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = devm_mfd_add_devices(dev, -1, cells, n_devs, NULL, 0, NULL);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to add sub-devices\n");
+
+ return device_init_wakeup(dev, true);
+}
+
+static const struct of_device_id max77658_of_id[] = {
+ { .compatible = "adi,max77643", .data = (void *)ID_MAX77643 },
+ { .compatible = "adi,max77654", .data = (void *)ID_MAX77654 },
+ { .compatible = "adi,max77658", .data = (void *)ID_MAX77658 },
+ { .compatible = "adi,max77659", .data = (void *)ID_MAX77659 },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, max77658_of_id);
+
+static const struct i2c_device_id max77658_i2c_id[] = {
+ { "max77643", ID_MAX77643 },
+ { "max77654", ID_MAX77654 },
+ { "max77658", ID_MAX77658 },
+ { "max77659", ID_MAX77659 },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(i2c, max77658_i2c_id);
+
+static struct i2c_driver max77658_driver = {
+ .driver = {
+ .name = "max77658",
+ .of_match_table = max77658_of_id,
+ },
+ .probe = max77658_i2c_probe,
+ .id_table = max77658_i2c_id,
+};
+module_i2c_driver(max77658_driver);
+
+MODULE_DESCRIPTION("MAX77658 MFD Driver");
+MODULE_AUTHOR("Nurettin.Bolucu@analog.com, Zeynep.Arslanbenzer@analog.com");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/max77658.h b/include/linux/mfd/max77658.h
new file mode 100644
index 000000000000..a7860f76c61f
--- /dev/null
+++ b/include/linux/mfd/max77658.h
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef __MFD_MAX77658_H__
+#define __MFD_MAX77658_H__
+
+#include <linux/bits.h>
+
+#define MAX77658_REG_INT_GLBL0 0x00
+#define MAX77658_REG_INT_CHG 0x01
+#define MAX77658_REG_INT_GLBL1 0x04
+#define MAX77658_REG_INTM_CHG 0x07
+#define MAX77658_REG_INTM_GLBL0 0x08
+#define MAX77658_REG_INTM_GLBL1 0x09
+
+#define MAX77654_REG_INTM_GLBL1 0x08
+#define MAX77654_REG_INTM_GLBL0 0x09
+
+#define MAX77643_REG_INT_GLBL1 0x01
+#define MAX77643_REG_INTM_GLBL0 0x04
+#define MAX77643_REG_INTM_GLBL1 0x05
+
+#define MAX77658_BIT_INT_GLBL0_GPIO0_F BIT(0)
+#define MAX77658_BIT_INT_GLBL0_GPIO0_R BIT(1)
+#define MAX77658_BIT_INT_GLBL0_EN_F BIT(2)
+#define MAX77658_BIT_INT_GLBL0_EN_R BIT(3)
+#define MAX77658_BIT_INT_GLBL0_TJAL1_R BIT(4)
+#define MAX77658_BIT_INT_GLBL0_TJAL2_R BIT(5)
+#define MAX77658_BIT_INT_GLBL0_DOD1_R BIT(6)
+#define MAX77658_BIT_INT_GLBL0_DOD0_R BIT(7)
+
+#define MAX77643_BIT_INT_GLBL0_DOD0_R BIT(6)
+
+#define MAX77658_BIT_INT_GLBL1_GPI1_F BIT(0)
+#define MAX77658_BIT_INT_GLBL1_GPI1_R BIT(1)
+#define MAX77658_BIT_INT_GLBL1_SBB0_F BIT(2)
+#define MAX77658_BIT_INT_GLBL1_SBB1_F BIT(3)
+#define MAX77658_BIT_INT_GLBL1_SBB2_F BIT(4)
+#define MAX77658_BIT_INT_GLBL1_LDO0_F BIT(5)
+#define MAX77658_BIT_INT_GLBL1_LDO1_F BIT(6)
+
+#define MAX77659_BIT_INT_GLBL1_SBB_TO BIT(4)
+
+#define MAX77654_BIT_INT_GLBL1_GPI2_F BIT(2)
+#define MAX77654_BIT_INT_GLBL1_GPI2_R BIT(3)
+#define MAX77654_BIT_INT_GLBL1_SBB_TO BIT(4)
+
+#define MAX77658_BIT_INT_THM BIT(0)
+#define MAX77658_BIT_INT_CHG BIT(1)
+#define MAX77658_BIT_INT_CHGIN BIT(2)
+#define MAX77658_BIT_INT_TJ_REG BIT(3)
+#define MAX77658_BIT_INT_CHGIN_CTRL BIT(4)
+#define MAX77658_BIT_INT_SYS_CTRL BIT(5)
+#define MAX77658_BIT_INT_SYS_CNFG BIT(6)
+
+#define MAX77659_BIT_INT_SYS_CTRL BIT(4)
+
+enum max77658_ids {
+ ID_MAX77643 = 1,
+ ID_MAX77654,
+ ID_MAX77658,
+ ID_MAX77659
+};
+
+struct device;
+struct regmap;
+struct regmap_irq_chip_data;
+
+struct max77658_dev {
+ enum max77658_ids id;
+
+ int irq;
+ struct regmap_irq_chip_data *irqc_glbl0;
+ struct regmap_irq_chip_data *irqc_glbl1;
+ struct regmap_irq_chip_data *irqc_chg;
+
+ struct regmap *regmap;
+ struct regmap *regmap_fg;
+};
+
+#endif /* __MFD_MAX77658_H__ */
--
2.25.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [PATCH v3 4/7] dt-bindings: power: supply: max77658: Add ADI MAX77658 Battery
2023-05-08 13:10 ` [PATCH v3 4/7] dt-bindings: power: supply: max77658: Add ADI MAX77658 Battery Zeynep Arslanbenzer
@ 2023-05-08 14:31 ` Krzysztof Kozlowski
2023-05-08 19:54 ` Krzysztof Kozlowski
1 sibling, 0 replies; 22+ messages in thread
From: Krzysztof Kozlowski @ 2023-05-08 14:31 UTC (permalink / raw)
To: Zeynep Arslanbenzer
Cc: robh+dt, sre, Nurettin Bolucu, linux-pm, lee,
krzysztof.kozlowski+dt, devicetree, broonie, linux-kernel,
lgirdwood
On Mon, 08 May 2023 16:10:42 +0300, Zeynep Arslanbenzer wrote:
> Add ADI MAX77658 power supply devicetree document.
>
> Signed-off-by: Nurettin Bolucu <Nurettin.Bolucu@analog.com>
> Signed-off-by: Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
> ---
> .../power/supply/adi,max77658-battery.yaml | 47 +++++++++++++++++++
> 1 file changed, 47 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/power/supply/adi,max77658-battery.yaml
>
My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):
yamllint warnings/errors:
doc reference errors (make refcheckdocs):
Documentation/devicetree/bindings/power/supply/adi,max77658-battery.yaml: Documentation/devicetree/bindings/mfd/adi,max77658.yaml
See https://patchwork.ozlabs.org/patch/1778410
This check can fail if there are any dependencies. The base for a patch
series is generally the most recent rc1.
If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:
pip3 install dtschema --upgrade
Please check and re-submit.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 6/7] dt-bindings: mfd: max77658: Add ADI MAX77658
2023-05-08 13:10 ` [PATCH v3 6/7] dt-bindings: mfd: max77658: Add ADI MAX77658 Zeynep Arslanbenzer
@ 2023-05-08 14:31 ` Krzysztof Kozlowski
2023-05-08 20:02 ` Krzysztof Kozlowski
1 sibling, 0 replies; 22+ messages in thread
From: Krzysztof Kozlowski @ 2023-05-08 14:31 UTC (permalink / raw)
To: Zeynep Arslanbenzer
Cc: robh+dt, sre, broonie, krzysztof.kozlowski+dt, linux-kernel,
devicetree, Nurettin Bolucu, lee, linux-pm, lgirdwood
On Mon, 08 May 2023 16:10:44 +0300, Zeynep Arslanbenzer wrote:
> Add ADI MAX77658 devicetree document.
>
> Signed-off-by: Nurettin Bolucu <Nurettin.Bolucu@analog.com>
> Signed-off-by: Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
> ---
> .../devicetree/bindings/mfd/adi,max77658.yaml | 160 ++++++++++++++++++
> 1 file changed, 160 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/mfd/adi,max77658.yaml
>
My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):
yamllint warnings/errors:
dtschema/dtc warnings/errors:
./Documentation/devicetree/bindings/mfd/adi,max77658.yaml: Unable to find schema file matching $id: http://devicetree.org/schemas/power/supply/adi,max77658-charger.yaml
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/mfd/adi,max77658.example.dtb: pmic@48: charger: False schema does not allow {'compatible': ['adi,max77658-charger'], 'monitored-battery': [[2]], 'adi,input-current-limit-microamp': [[475000]]}
From schema: /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/mfd/adi,max77658.yaml
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/mfd/adi,max77658.example.dtb: pmic@48: fuel-gauge: False schema does not allow {'compatible': ['adi,max77658-battery'], 'monitored-battery': [[2]], 'adi,valrt-min-microvolt': [[0]], 'adi,valrt-max-microvolt': [[5100000]], 'adi,ialrt-min-microamp': [[4294962296]], 'adi,ialrt-max-microamp': [[5000]]}
From schema: /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/mfd/adi,max77658.yaml
Documentation/devicetree/bindings/mfd/adi,max77658.example.dtb: /example-0/i2c/pmic@48/charger: failed to match any schema with compatible: ['adi,max77658-charger']
Documentation/devicetree/bindings/mfd/adi,max77658.example.dtb: /example-0/i2c/pmic@48/fuel-gauge: failed to match any schema with compatible: ['adi,max77658-battery']
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/mfd/adi,max77658.example.dtb: pmic@40: charger: False schema does not allow {'compatible': ['adi,max77659-charger'], 'monitored-battery': [[2]]}
From schema: /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/mfd/adi,max77658.yaml
Documentation/devicetree/bindings/mfd/adi,max77658.example.dtb: /example-1/i2c/pmic@40/charger: failed to match any schema with compatible: ['adi,max77659-charger']
See https://patchwork.ozlabs.org/patch/1778414
This check can fail if there are any dependencies. The base for a patch
series is generally the most recent rc1.
If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:
pip3 install dtschema --upgrade
Please check and re-submit.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 2/7] dt-bindings: power: supply: max77658: Add ADI MAX77654/58/59 Charger
2023-05-08 13:10 ` [PATCH v3 2/7] dt-bindings: power: supply: max77658: Add ADI MAX77654/58/59 Charger Zeynep Arslanbenzer
@ 2023-05-08 14:32 ` Krzysztof Kozlowski
2023-05-08 14:36 ` Krzysztof Kozlowski
2023-05-08 19:45 ` Krzysztof Kozlowski
1 sibling, 1 reply; 22+ messages in thread
From: Krzysztof Kozlowski @ 2023-05-08 14:32 UTC (permalink / raw)
To: Zeynep Arslanbenzer
Cc: sre, Nurettin Bolucu, broonie, robh+dt, devicetree,
krzysztof.kozlowski+dt, lee, linux-pm, linux-kernel, lgirdwood
On Mon, 08 May 2023 16:10:40 +0300, Zeynep Arslanbenzer wrote:
> Add ADI MAX77654/58/59 power supply devicetree document.
>
> Signed-off-by: Nurettin Bolucu <Nurettin.Bolucu@analog.com>
> Signed-off-by: Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
> ---
> .../power/supply/adi,max77658-charger.yaml | 53 +++++++++++++++++++
> 1 file changed, 53 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/power/supply/adi,max77658-charger.yaml
>
My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):
yamllint warnings/errors:
doc reference errors (make refcheckdocs):
Documentation/devicetree/bindings/power/supply/adi,max77658-charger.yaml: Documentation/devicetree/bindings/mfd/adi,max77658.yaml
See https://patchwork.ozlabs.org/patch/1778407
This check can fail if there are any dependencies. The base for a patch
series is generally the most recent rc1.
If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:
pip3 install dtschema --upgrade
Please check and re-submit.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 2/7] dt-bindings: power: supply: max77658: Add ADI MAX77654/58/59 Charger
2023-05-08 14:32 ` Krzysztof Kozlowski
@ 2023-05-08 14:36 ` Krzysztof Kozlowski
0 siblings, 0 replies; 22+ messages in thread
From: Krzysztof Kozlowski @ 2023-05-08 14:36 UTC (permalink / raw)
To: Zeynep Arslanbenzer
Cc: sre, Nurettin Bolucu, broonie, robh+dt, devicetree,
krzysztof.kozlowski+dt, lee, linux-pm, linux-kernel, lgirdwood
On 08/05/2023 16:32, Krzysztof Kozlowski wrote:
> On Mon, 08 May 2023 16:10:40 +0300, Zeynep Arslanbenzer wrote:
>> Add ADI MAX77654/58/59 power supply devicetree document.
>>
>> Signed-off-by: Nurettin Bolucu <Nurettin.Bolucu@analog.com>
>> Signed-off-by: Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
>> ---
>> .../power/supply/adi,max77658-charger.yaml | 53 +++++++++++++++++++
>> 1 file changed, 53 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/power/supply/adi,max77658-charger.yaml
>>
>
> My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
> on your patch (DT_CHECKER_FLAGS is new in v5.13):
>
> yamllint warnings/errors:
>
> doc reference errors (make refcheckdocs):
> Documentation/devicetree/bindings/power/supply/adi,max77658-charger.yaml: Documentation/devicetree/bindings/mfd/adi,max77658.yaml
This can be ignored, there is a kind of circular dependency so it's fine.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 2/7] dt-bindings: power: supply: max77658: Add ADI MAX77654/58/59 Charger
2023-05-08 13:10 ` [PATCH v3 2/7] dt-bindings: power: supply: max77658: Add ADI MAX77654/58/59 Charger Zeynep Arslanbenzer
2023-05-08 14:32 ` Krzysztof Kozlowski
@ 2023-05-08 19:45 ` Krzysztof Kozlowski
2023-05-08 19:55 ` Krzysztof Kozlowski
1 sibling, 1 reply; 22+ messages in thread
From: Krzysztof Kozlowski @ 2023-05-08 19:45 UTC (permalink / raw)
To: Zeynep Arslanbenzer, lee, robh+dt, krzysztof.kozlowski+dt, sre,
lgirdwood, broonie
Cc: linux-kernel, devicetree, linux-pm, Nurettin Bolucu
On 08/05/2023 15:10, Zeynep Arslanbenzer wrote:
> Add ADI MAX77654/58/59 power supply devicetree document.
>
> Signed-off-by: Nurettin Bolucu <Nurettin.Bolucu@analog.com>
> Signed-off-by: Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
> ---
> .../power/supply/adi,max77658-charger.yaml | 53 +++++++++++++++++++
> 1 file changed, 53 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/power/supply/adi,max77658-charger.yaml
>
> diff --git a/Documentation/devicetree/bindings/power/supply/adi,max77658-charger.yaml b/Documentation/devicetree/bindings/power/supply/adi,max77658-charger.yaml
> new file mode 100644
> index 000000000000..1b487d82cdbf
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/power/supply/adi,max77658-charger.yaml
> @@ -0,0 +1,53 @@
> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/power/supply/adi,max77658-charger.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Battery charger for MAX77658 PMICs family from ADI
> +
> +maintainers:
> + - Nurettin Bolucu <Nurettin.Bolucu@analog.com>
> + - Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
> +
> +description: |
> + This module is part of the MAX77658 MFD device. For more details
> + see Documentation/devicetree/bindings/mfd/adi,max77658.yaml.
> +
> + The charger is represented as a sub-node of the PMIC node on the device tree.
> +
> +properties:
> + compatible:
> + enum:
> + - adi,max77654-charger
> + - adi,max77658-charger
> + - adi,max77659-charger
What are the differences between them? Driver suggests they are
compatible. Your match data is empty there.
> +
> + adi,input-current-limit-microamp:
> + description: Input current limit value.
Your description is an exact copy of property name. That's not helpful.
What do you limit? Total current? Charging current? Top-off current?
You have default value, why it is not here? minimum/maximum?
> +
> + monitored-battery:
> + description: >
> + This property must be a phandle to a node using the format described
> + in battery.yaml, with the following properties being required:
> + - constant-charge-current-max-microamp
> +
> +allOf:
> + - $ref: power-supply.yaml#
> + - if:
> + properties:
> + compatible:
> + contains:
> + enum:
> + - adi,max77659-charger
> +
> + then:
> + properties:
> + adi,input-current-limit-microamp: false
> +
> +required:
> + - compatible
> +
> +additionalProperties: false
> +
> +...
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 3/7] power: supply: max77658: Add ADI MAX77654/58/59 Charger Support
2023-05-08 13:10 ` [PATCH v3 3/7] power: supply: max77658: Add ADI MAX77654/58/59 Charger Support Zeynep Arslanbenzer
@ 2023-05-08 19:51 ` Krzysztof Kozlowski
2023-05-08 20:22 ` Krzysztof Kozlowski
1 sibling, 0 replies; 22+ messages in thread
From: Krzysztof Kozlowski @ 2023-05-08 19:51 UTC (permalink / raw)
To: Zeynep Arslanbenzer, lee, robh+dt, krzysztof.kozlowski+dt, sre,
lgirdwood, broonie
Cc: linux-kernel, devicetree, linux-pm, Nurettin Bolucu
On 08/05/2023 15:10, Zeynep Arslanbenzer wrote:
> Charger driver for ADI MAX77654/58/59.
>
> The MAX77654/58/59 charger is Smart Power Selector Li+/Li-Poly Charger.
>
> Signed-off-by: Nurettin Bolucu <Nurettin.Bolucu@analog.com>
> Signed-off-by: Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
> ---
> drivers/power/supply/Kconfig | 7 +
> drivers/power/supply/Makefile | 1 +
> drivers/power/supply/max77658-charger.c | 844 ++++++++++++++++++++++++
> 3 files changed, 852 insertions(+)
> create mode 100644 drivers/power/supply/max77658-charger.c
>
> +
> +static int max77658_charger_probe(struct platform_device *pdev)
> +{
> + struct max77658_dev *max77658 = dev_get_drvdata(pdev->dev.parent);
> + struct power_supply_config charger_cfg = {};
> + struct power_supply_battery_info *info;
> + struct max77658_charger *charger;
> + struct device *dev = &pdev->dev;
> + int i, n_irq, ret;
> +
> + charger = devm_kzalloc(dev, sizeof(*charger), GFP_KERNEL);
> + if (!charger)
> + return -ENOMEM;
> +
> + platform_set_drvdata(pdev, charger);
> +
> + charger->dev = dev;
> + charger->max77658 = max77658;
> + charger->regmap = dev_get_regmap(charger->dev->parent, NULL);
> +
> + charger->psy_chg_d.get_property = max77658_charger_get_property;
> + charger->psy_chg_d.set_property = max77658_charger_set_property;
> + charger->psy_chg_d.type = POWER_SUPPLY_TYPE_USB;
> + charger_cfg.of_node = dev->of_node;
So here you have charger of_node...
> + charger_cfg.drv_data = charger;
> +
> + switch (max77658->id) {
> + case ID_MAX77654:
This suggests your devices are not compatible...
> + charger->psy_chg_d.properties = max77658_charger_props;
> + charger->psy_chg_d.num_properties =
> + ARRAY_SIZE(max77658_charger_props);
> + charger->psy_chg_d.name = "max77654-charger";
> + charger->psy_chg_d.property_is_writeable =
> + max77658_property_is_writeable;
> + n_irq = MAX77658_CHG_IRQ_MAX;
> + break;
> + case ID_MAX77658:
> + charger->psy_chg_d.properties = max77658_charger_props;
> + charger->psy_chg_d.num_properties =
> + ARRAY_SIZE(max77658_charger_props);
> + charger->psy_chg_d.name = "max77658-charger";
> + charger->psy_chg_d.property_is_writeable =
> + max77658_property_is_writeable;
> + n_irq = MAX77658_CHG_IRQ_MAX;
> + break;
> + case ID_MAX77659:
> + charger->psy_chg_d.properties = max77659_charger_props;
> + charger->psy_chg_d.num_properties =
> + ARRAY_SIZE(max77659_charger_props);
> + charger->psy_chg_d.name = "max77659-charger";
> + charger->psy_chg_d.property_is_writeable =
> + max77659_property_is_writeable;
> + n_irq = MAX77659_CHG_IRQ_MAX;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + charger->psy_chg = devm_power_supply_register(dev, &charger->psy_chg_d,
> + &charger_cfg);
> + if (IS_ERR(charger->psy_chg))
> + return dev_err_probe(dev, PTR_ERR(charger->psy_chg),
> + "Failed to register power supply\n");
> +
> + charger->psy_chg->of_node = of_get_child_by_name(dev->parent->of_node,
> + "charger");
and here... this is confusing. Why do you get the child of a parent?
Isn't this exactly this node?
> +
> + if (!charger->psy_chg->of_node)
> + dev_err(charger->dev,
> + "of_get_child_by_name\n");
??? Not helpful error message and actually not helpful case.
Can this even happen?
Maybe you should just drop platform_device_id?
> +
> + ret = power_supply_get_battery_info(charger->psy_chg, &info);
> + if (ret) {
> + dev_err(charger->dev, "Unable to get charger info\n");
> + charger->fast_charge_current_ua = 15000;
> + } else {
> + charger->fast_charge_current_ua =
> + info->constant_charge_current_max_ua;
> + }
> +
> + if (charger->max77658->id != ID_MAX77659)
> + max77658_charger_parse_dt(charger);
> +
> + ret = max77658_charger_initialize(charger);
> + if (ret)
> + return dev_err_probe(dev, ret,
> + "Failed to initialize charger\n");
> +
> + for (i = 0; i < n_irq; i++) {
> + charger->irq_arr[i] =
> + regmap_irq_get_virq(max77658->irqc_chg, i);
> +
> + if (charger->irq_arr[i] < 0)
> + return dev_err_probe(dev, -EINVAL,
> + "Invalid IRQ for MAX77658_CHG_IRQ %d\n",
> + i);
> +
> + ret = devm_request_threaded_irq(dev, charger->irq_arr[i],
> + NULL, max77658_charger_isr,
> + IRQF_TRIGGER_FALLING,
> + max77658_irq_descs[i], charger);
> + if (ret)
> + return dev_err_probe(dev, ret,
> + "Failed to request irq: %d\n",
> + charger->irq_arr[i]);
> + }
> +
> + ret = device_create_file(dev, &dev_attr_fast_charge_timer);
Where the ABI documentation?
> + if (ret)
> + return dev_err_probe(dev, ret,
> + "Failed to create fast charge timer sysfs entry\n");
> +
> + ret = device_create_file(dev, &dev_attr_topoff_timer);
The same.
> + if (ret)
> + return dev_err_probe(dev, ret,
> + "Failed to create topoff timer sysfs entry\n");
> +
> + return 0;
> +}
> +
> +static int max77658_charger_remove(struct platform_device *pdev)
> +{
> + device_remove_file(&pdev->dev, &dev_attr_topoff_timer);
> + device_remove_file(&pdev->dev, &dev_attr_fast_charge_timer);
> +
> + return 0;
> +}
> +
> +static const struct of_device_id max77658_charger_of_id[] = {
> + { .compatible = "adi,max77654-charger" },
> + { .compatible = "adi,max77658-charger" },
> + { .compatible = "adi,max77659-charger" },
So they are compatible? If so, use one entry. If not, use driver data.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 4/7] dt-bindings: power: supply: max77658: Add ADI MAX77658 Battery
2023-05-08 13:10 ` [PATCH v3 4/7] dt-bindings: power: supply: max77658: Add ADI MAX77658 Battery Zeynep Arslanbenzer
2023-05-08 14:31 ` Krzysztof Kozlowski
@ 2023-05-08 19:54 ` Krzysztof Kozlowski
1 sibling, 0 replies; 22+ messages in thread
From: Krzysztof Kozlowski @ 2023-05-08 19:54 UTC (permalink / raw)
To: Zeynep Arslanbenzer, lee, robh+dt, krzysztof.kozlowski+dt, sre,
lgirdwood, broonie
Cc: linux-kernel, devicetree, linux-pm, Nurettin Bolucu
On 08/05/2023 15:10, Zeynep Arslanbenzer wrote:
> Add ADI MAX77658 power supply devicetree document.
>
> Signed-off-by: Nurettin Bolucu <Nurettin.Bolucu@analog.com>
> Signed-off-by: Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
> ---
> .../power/supply/adi,max77658-battery.yaml | 47 +++++++++++++++++++
> 1 file changed, 47 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/power/supply/adi,max77658-battery.yaml
>
> diff --git a/Documentation/devicetree/bindings/power/supply/adi,max77658-battery.yaml b/Documentation/devicetree/bindings/power/supply/adi,max77658-battery.yaml
> new file mode 100644
> index 000000000000..112296d2b1f4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/power/supply/adi,max77658-battery.yaml
> @@ -0,0 +1,47 @@
> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/power/supply/adi,max77658-battery.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Battery for MAX77658 PMICs family from ADI
> +
> +maintainers:
> + - Nurettin Bolucu <Nurettin.Bolucu@analog.com>
> + - Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
> +
> +description: |
> + This module is part of the MAX77658 MFD device. For more details
> + see Documentation/devicetree/bindings/mfd/adi,max77658.yaml.
> +
> + The fuel gauge is represented as a sub-node of the PMIC node on the device tree.
> +
> +properties:
> + compatible:
> + const: adi,max77658-battery
> +
> + adi,valrt-min-microvolt:
> + description: alert when battery voltage is lower than this value
> +
> + adi,valrt-max-microvolt:
> + description: alert when battery voltage is higher than this value
Use the same approach/solution as battery.yaml.
> +
> + adi,ialrt-min-microamp:
> + description: alert when battery current is lower than this value
> +
> + adi,ialrt-max-microamp:
> + description: alert when battery current is higher than this value
Also here.
> +
> + monitored-battery:
> + description: >
> + This property must be a phandle to a node using the format described
> + in battery.yaml, with the following properties being required:
> + - alert-celsius
> +
> +required:
> + - compatible
> + - monitored-battery
> +
> +additionalProperties: false
> +
> +...
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 2/7] dt-bindings: power: supply: max77658: Add ADI MAX77654/58/59 Charger
2023-05-08 19:45 ` Krzysztof Kozlowski
@ 2023-05-08 19:55 ` Krzysztof Kozlowski
0 siblings, 0 replies; 22+ messages in thread
From: Krzysztof Kozlowski @ 2023-05-08 19:55 UTC (permalink / raw)
To: Zeynep Arslanbenzer, lee, robh+dt, krzysztof.kozlowski+dt, sre,
lgirdwood, broonie
Cc: linux-kernel, devicetree, linux-pm, Nurettin Bolucu
On 08/05/2023 21:45, Krzysztof Kozlowski wrote:
> On 08/05/2023 15:10, Zeynep Arslanbenzer wrote:
>> Add ADI MAX77654/58/59 power supply devicetree document.
>>
>> Signed-off-by: Nurettin Bolucu <Nurettin.Bolucu@analog.com>
>> Signed-off-by: Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
>> ---
>> .../power/supply/adi,max77658-charger.yaml | 53 +++++++++++++++++++
>> 1 file changed, 53 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/power/supply/adi,max77658-charger.yaml
>>
>> diff --git a/Documentation/devicetree/bindings/power/supply/adi,max77658-charger.yaml b/Documentation/devicetree/bindings/power/supply/adi,max77658-charger.yaml
>> new file mode 100644
>> index 000000000000..1b487d82cdbf
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/power/supply/adi,max77658-charger.yaml
>> @@ -0,0 +1,53 @@
>> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/power/supply/adi,max77658-charger.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: Battery charger for MAX77658 PMICs family from ADI
>> +
>> +maintainers:
>> + - Nurettin Bolucu <Nurettin.Bolucu@analog.com>
>> + - Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
>> +
>> +description: |
>> + This module is part of the MAX77658 MFD device. For more details
>> + see Documentation/devicetree/bindings/mfd/adi,max77658.yaml.
>> +
>> + The charger is represented as a sub-node of the PMIC node on the device tree.
>> +
>> +properties:
>> + compatible:
>> + enum:
>> + - adi,max77654-charger
>> + - adi,max77658-charger
>> + - adi,max77659-charger
>
> What are the differences between them? Driver suggests they are
> compatible. Your match data is empty there.
>
>> +
>> + adi,input-current-limit-microamp:
>> + description: Input current limit value.
>
> Your description is an exact copy of property name. That's not helpful.
> What do you limit? Total current? Charging current? Top-off current?
>
> You have default value, why it is not here? minimum/maximum?
>
BTW, this is duplicating constant-charge-current-max-microamp. If it
has different meaning, you need to explain this in description, not just
say what property name is saying.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 5/7] power: supply: max77658: Add ADI MAX77658 Battery Support
2023-05-08 13:10 ` [PATCH v3 5/7] power: supply: max77658: Add ADI MAX77658 Battery Support Zeynep Arslanbenzer
@ 2023-05-08 19:57 ` Krzysztof Kozlowski
2023-05-08 20:15 ` Krzysztof Kozlowski
1 sibling, 0 replies; 22+ messages in thread
From: Krzysztof Kozlowski @ 2023-05-08 19:57 UTC (permalink / raw)
To: Zeynep Arslanbenzer, lee, robh+dt, krzysztof.kozlowski+dt, sre,
lgirdwood, broonie
Cc: linux-kernel, devicetree, linux-pm, Nurettin Bolucu
On 08/05/2023 15:10, Zeynep Arslanbenzer wrote:
> Battery driver for ADI MAX77658.
>
> The MAX77658 is an ultra-low power fuel gauge which implements the Maxim ModelGauge m5 EZ algorithm.
>
> Signed-off-by: Nurettin Bolucu <Nurettin.Bolucu@analog.com>
> Signed-off-by: Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
> ---
> drivers/power/supply/Kconfig | 7 +
> drivers/power/supply/Makefile | 1 +
> drivers/power/supply/max77658-battery.c | 633 ++++++++++++++++++++++++
> 3 files changed, 641 insertions(+)
> create mode 100644 drivers/power/supply/max77658-battery.c
>
> diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
> index 4b68bbb1e2a8..f9556f4b9e35 100644
> --- a/drivers/power/supply/Kconfig
> +++ b/drivers/power/supply/Kconfig
> @@ -572,6 +572,13 @@ config CHARGER_MAX77658
> Say Y to enable support for the battery charger control of
> MAX77654/58/59 PMIC.
>
> +config BATTERY_MAX77658
> + tristate "Analog Devices MAX77658 battery driver"
> + depends on MFD_MAX77658
> + help
> + Say Y to enable support for the battery control of
> + MAX77658 PMIC.
> +
> config CHARGER_MAX77693
> tristate "Maxim MAX77693 battery charger driver"
> depends on MFD_MAX77693
> diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
> index af4bd6e5969f..e5a425d333a7 100644
> --- a/drivers/power/supply/Makefile
> +++ b/drivers/power/supply/Makefile
> @@ -77,6 +77,7 @@ obj-$(CONFIG_CHARGER_MAX14577) += max14577_charger.o
> obj-$(CONFIG_CHARGER_DETECTOR_MAX14656) += max14656_charger_detector.o
> obj-$(CONFIG_CHARGER_MAX77650) += max77650-charger.o
> obj-$(CONFIG_CHARGER_MAX77658) += max77658-charger.o
> +obj-$(CONFIG_BATTERY_MAX77658) += max77658-battery.o
> obj-$(CONFIG_CHARGER_MAX77693) += max77693_charger.o
> obj-$(CONFIG_CHARGER_MAX77976) += max77976_charger.o
> obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o
> diff --git a/drivers/power/supply/max77658-battery.c b/drivers/power/supply/max77658-battery.c
> new file mode 100644
> index 000000000000..4948ef227db1
> --- /dev/null
> +++ b/drivers/power/supply/max77658-battery.c
> @@ -0,0 +1,633 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2023 Analog Devices, Inc.
> + * ADI battery driver for the MAX77658
> + */
> +
> +#include <linux/bitfield.h>
> +#include <linux/delay.h>
> +#include <linux/mfd/max77658.h>
> +#include <linux/module.h>
> +#include <linux/of_irq.h>
> +#include <linux/platform_device.h>
> +#include <linux/power_supply.h>
> +#include <linux/regmap.h>
> +
> +/* Default value for SALRT min threshold, in percent */
> +#define MAX77658_SALRT_MIN_DEFAULT 1
> +/* Default value for SALRT max threshold, in percent */
> +#define MAX77658_SALRT_MAX_DEFAULT 99
> +
> +#define MAX77658_IALRTTH_RESOLUTION 8567
> +#define MAX77658_CURRENT_RESOLUTION 33487
> +#define MAX77658_VOLTAGE_RESOLUTION 78125
> +#define MAX77658_FG_DELAY 1000
> +#define MAX77658_BATTERY_FULL 100
> +#define MAX77658_BATTERY_LOW 40
> +#define MAX77658_BATTERY_CRITICAL 10
> +#define MAX77658_MAXMINVOLT_STEP 20000
> +#define MAX77658_VALRTTH_STEP 20000
> +#define MAX77658_VEMPTY_VE_STEP 10000
> +#define MAX77658_POWER_STEP 17100
> +
> +#define MAX77658_REG_STATUS 0x00
> +#define MAX77658_REG_VALRTTH 0x01
> +#define MAX77658_REG_TALRTTH 0x02
> +#define MAX77658_REG_SALRTTH 0x03
> +#define MAX77658_REG_CONFIG 0x1D
> +#define MAX77658_REG_DEVNAME 0x21
> +#define MAX77658_REG_VEMPTY 0x3A
> +#define MAX77658_REG_AVGPOWER 0xB3
> +#define MAX77658_REG_IALRTTH 0xB4
> +#define MAX77658_REG_CONFIG2 0xBB
> +#define MAX77658_REG_TEMP 0x08
> +#define MAX77658_REG_VCELL 0x09
> +#define MAX77658_REG_CURRENT 0x0A
> +#define MAX77658_REG_AVGCURRENT 0x0B
> +#define MAX77658_REG_AVGVCELL 0x19
> +#define MAX77658_REG_MAXMINTEMP 0x1A
> +#define MAX77658_REG_MAXMINVOLT 0x1B
> +#define MAX77658_REG_MAXMINCURR 0x1C
> +#define MAX77658_REG_REPSOC 0x06
> +#define MAX77658_REG_TTE 0x11
> +#define MAX77658_REG_TTF 0x20
> +
> +#define MAX77658_BIT_STATUS_BR BIT(15)
> +#define MAX77658_BIT_STATUS_SMX BIT(14)
> +#define MAX77658_BIT_STATUS_TMX BIT(13)
> +#define MAX77658_BIT_STATUS_VMX BIT(12)
> +#define MAX77658_BIT_STATUS_BI BIT(11)
> +#define MAX77658_BIT_STATUS_SMN BIT(10)
> +#define MAX77658_BIT_STATUS_TMN BIT(9)
> +#define MAX77658_BIT_STATUS_VMN BIT(8)
> +#define MAX77658_BIT_STATUS_POR BIT(2)
> +#define MAX77658_BIT_CONFIG_AEN BIT(2)
Odd indentation
(...)
> +}
> +
> +static void max77658_fg_parse_dt(struct max77658_fg *max77658_fg)
> +{
> + struct device *dev = max77658_fg->dev;
> + int ret;
> +
> + ret = device_property_read_u32(dev, "adi,valrt-min-microvolt",
> + &max77658_fg->volt_min_uv);
> + if (ret) {
> + dev_dbg(dev,
> + "Could not read adi,valrt-min-microvolt DT property\n");
> + max77658_fg->volt_min_uv = 0;
So you have defaults? DT binding is missing them
> + }
> +
> + ret = device_property_read_u32(dev, "adi,valrt-max-microvolt",
> + &max77658_fg->volt_max_uv);
> + if (ret) {
> + dev_dbg(dev,
> + "Could not read adi,valrt-max-microvolt DT property\n");
> + max77658_fg->volt_max_uv = 5100000;
Ditto
> + }
> +
> + ret = device_property_read_u32(dev, "adi,ialrt-min-microamp",
> + &max77658_fg->curr_min_ma);
> + if (ret) {
> + dev_dbg(dev,
> + "Could not read adi,ialrt-min-microamp DT property\n");
> + max77658_fg->curr_min_ma = MAX77658_IALRTTH_RESOLUTION * (-128);
Ditto
> + }
> +
> + ret = device_property_read_u32(dev, "adi,ialrt-max-microamp",
> + &max77658_fg->curr_max_ma);
> + if (ret) {
> + dev_dbg(dev,
> + "Could not read adi,ialrt-max-microamp DT property\n");
> + max77658_fg->curr_max_ma = MAX77658_IALRTTH_RESOLUTION * 127;
Ditto
> + }
> +}
> +
> +static int max77658_fg_probe(struct platform_device *pdev)
> +{
> + struct max77658_dev *max77658 = dev_get_drvdata(pdev->dev.parent);
> + struct power_supply_battery_info *info;
> + struct power_supply_config fg_cfg = {};
> + struct device *dev = &pdev->dev;
> + struct max77658_fg *fg;
> + int ret = 0;
> +
> + fg = devm_kzalloc(&pdev->dev, sizeof(*fg), GFP_KERNEL);
> + if (!fg)
> + return -ENOMEM;
> +
> + fg->dev = &pdev->dev;
> + fg->regmap = max77658->regmap_fg;
> +
> + fg->psy_batt_d.name = "max77658-battery";
> + fg->psy_batt_d.type = POWER_SUPPLY_TYPE_BATTERY;
> + fg->psy_batt_d.get_property = max77658_fg_get_property;
> + fg->psy_batt_d.set_property = max77658_fg_set_property;
> + fg->psy_batt_d.properties = max77658_fg_battery_props;
> + fg->psy_batt_d.property_is_writeable = max77658_property_is_writeable;
> + fg->psy_batt_d.num_properties = ARRAY_SIZE(max77658_fg_battery_props);
> + fg_cfg.drv_data = fg;
> +
> + INIT_DELAYED_WORK(&fg->work, max77658_fg_work);
> + ret = devm_add_action(&pdev->dev, max77658_stop_work, fg);
> + if (ret)
> + return dev_err_probe(&pdev->dev, ret,
> + "Error in setting delayed work\n");
> +
> + fg->battery = devm_power_supply_register(dev, &fg->psy_batt_d,
> + &fg_cfg);
> + if (IS_ERR(fg->battery))
> + return dev_err_probe(&pdev->dev, PTR_ERR(fg->battery),
> + "Failed to register battery\n");
> +
> + fg->battery->of_node = of_get_child_by_name(dev->parent->of_node,
> + "fuel-gauge");
> +
> + if (!fg->battery->of_node)
> + dev_err(dev,
> + "of_get_child_by_name\n");
Same problems a previous patch...
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 6/7] dt-bindings: mfd: max77658: Add ADI MAX77658
2023-05-08 13:10 ` [PATCH v3 6/7] dt-bindings: mfd: max77658: Add ADI MAX77658 Zeynep Arslanbenzer
2023-05-08 14:31 ` Krzysztof Kozlowski
@ 2023-05-08 20:02 ` Krzysztof Kozlowski
1 sibling, 0 replies; 22+ messages in thread
From: Krzysztof Kozlowski @ 2023-05-08 20:02 UTC (permalink / raw)
To: Zeynep Arslanbenzer, lee, robh+dt, krzysztof.kozlowski+dt, sre,
lgirdwood, broonie
Cc: linux-kernel, devicetree, linux-pm, Nurettin Bolucu
On 08/05/2023 15:10, Zeynep Arslanbenzer wrote:
> Add ADI MAX77658 devicetree document.
>
> Signed-off-by: Nurettin Bolucu <Nurettin.Bolucu@analog.com>
> Signed-off-by: Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
> ---
> .../devicetree/bindings/mfd/adi,max77658.yaml | 160 ++++++++++++++++++
> 1 file changed, 160 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/mfd/adi,max77658.yaml
>
> diff --git a/Documentation/devicetree/bindings/mfd/adi,max77658.yaml b/Documentation/devicetree/bindings/mfd/adi,max77658.yaml
> new file mode 100644
> index 000000000000..4d6d87cd4b52
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/adi,max77658.yaml
> @@ -0,0 +1,160 @@
> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/mfd/adi,max77658.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: MAX77643/54/58/59 PMIC from ADI
> +
> +maintainers:
> + - Nurettin Bolucu <Nurettin.Bolucu@analog.com>
> + - Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
> +
> +description: |
> + MAX77643, MAX77654, MAX77658 and MAX77659 devices are a family of ADI PMICs
> + providing battery charging and power supply solutions for
> + low-power applications.
> +
> + MAX77643 is a Power Management IC with 1 LDO regulator.
> +
> + MAX77654 is a Power Management IC with 2 LDO regulators and 1 charger.
> +
> + MAX77658 is a Power Management IC with 2 LDO regulators, 1 charger
> + and 1 fuel gauge.
> +
> + MAX77659 is a Power Management IC with 1 LDO regulator and 1 charger.
> +
> +properties:
> + compatible:
> + enum:
> + - adi,max77643
> + - adi,max77654
> + - adi,max77658
> + - adi,max77659
> +
> + reg:
> + items:
> + - enum: [0x40, 0x48]
> +
> + interrupts:
> + maxItems: 1
> +
> + charger:
> + $ref: /schemas/power/supply/adi,max77658-charger.yaml
> +
> + fuel-gauge:
> + $ref: /schemas/power/supply/adi,max77658-battery.yaml
> +
> + regulators:
> + type: object
> +
> + description:
> + The regulators is represented as a sub-node of the PMIC node on the device tree.
> +
> + patternProperties:
> + "^LDO[01]$":
lowercase
> + type: object
> + $ref: /schemas/regulator/regulator.yaml
> + additionalProperties: false
> + description:
> + LDO regulator
> +
> + properties:
> + regulator-always-on: true
> + regulator-boot-on: true
Why nothing else is allowed? You have different voltages, so how can you
configure their constraints if you do not allow them to be configured?
Drop all properties and use unevaluatedProperties..
> +
> + additionalProperties: false
> +
> +allOf:
> + - if:
> + properties:
> + compatible:
> + contains:
> + enum:
> + - adi,max77643
> + - adi,max77654
> + - adi,max77658
> +
> + then:
> + properties:
> + reg:
> + items:
> + - const: 0x48
> +
> + else:
> + properties:
> + reg:
> + items:
> + - const: 0x40
- if:
...
then:
properties:
regulators:
properties:
LDO1: false
> +
> +required:
> + - compatible
> + - reg
> + - interrupts
Put required before allOf.
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + battery: battery-cell {
> + compatible = "simple-battery";
> + alert-celsius = <0 100>;
> + constant-charge-current-max-microamp = <15000>;
> + };
> + #include <dt-bindings/interrupt-controller/irq.h>
> + i2c {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + pmic@48 {
> + compatible = "adi,max77658";
> + reg = <0x48>;
> + interrupt-parent = <&gpio>;
> + interrupts = <16 IRQ_TYPE_EDGE_FALLING>;
> + charger {
> + compatible = "adi,max77658-charger";
> + monitored-battery = <&battery>;
> + adi,input-current-limit-microamp = <475000>;
> + };
> + regulators {
> + LDO0 {
> + regulator-boot-on;
> + regulator-always-on;
> + };
> + LDO1 {
> + regulator-boot-on;
> + regulator-always-on;
> + };
> + };
> + fuel-gauge {
> + compatible = "adi,max77658-battery";
> + monitored-battery = <&battery>;
> + adi,valrt-min-microvolt = <0>;
> + adi,valrt-max-microvolt = <5100000>;
> + adi,ialrt-min-microamp = <(-5000)>;
> + adi,ialrt-max-microamp = <5000>;
> + };
> + };
> + };
> +
> + - |
> + #include <dt-bindings/interrupt-controller/irq.h>
> + i2c {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + pmic@40 {
> + compatible = "adi,max77659";
> + reg = <0x40>;
> + interrupt-parent = <&gpio>;
> + interrupts = <16 IRQ_TYPE_EDGE_FALLING>;
> + charger {
> + compatible = "adi,max77659-charger";
> + monitored-battery = <&battery>;
> + };
> + regulators {
> + LDO0 {
> + regulator-boot-on;
> + regulator-always-on;
> + };
> + };
> + };
> + };
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 7/7] mfd: max77658: Add ADI MAX77643/54/58/59 MFD Support
2023-05-08 13:10 ` [PATCH v3 7/7] mfd: max77658: Add ADI MAX77643/54/58/59 MFD Support Zeynep Arslanbenzer
@ 2023-05-08 20:09 ` Krzysztof Kozlowski
0 siblings, 0 replies; 22+ messages in thread
From: Krzysztof Kozlowski @ 2023-05-08 20:09 UTC (permalink / raw)
To: Zeynep Arslanbenzer, lee, robh+dt, krzysztof.kozlowski+dt, sre,
lgirdwood, broonie
Cc: linux-kernel, devicetree, linux-pm, Nurettin Bolucu
On 08/05/2023 15:10, Zeynep Arslanbenzer wrote:
> MFD driver for MAX77643/54/58/59 to enable its sub
> devices.
>
> The MAX77643 is a multi-function devices. It includes
> regulator.
>
> The MAX77654 is a multi-function devices. It includes
> regulator and charger.
>
> The MAX77658 is a multi-function devices. It includes
> regulator, charger and battery.
>
> The MAX77659 is a multi-function devices. It includes
> regulator and charger.
>
> Signed-off-by: Nurettin Bolucu <Nurettin.Bolucu@analog.com>
> Signed-off-by: Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
> ---
> drivers/mfd/Kconfig | 13 ++
> drivers/mfd/Makefile | 1 +
> drivers/mfd/max77658.c | 426 +++++++++++++++++++++++++++++++++++
> include/linux/mfd/max77658.h | 80 +++++++
> 4 files changed, 520 insertions(+)
> create mode 100644 drivers/mfd/max77658.c
> create mode 100644 include/linux/mfd/max77658.h
>
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 8b93856de432..aa1630a6d33a 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -821,6 +821,19 @@ config MFD_MAX77650
> the following functionalities of the device: GPIO, regulator,
> charger, LED, onkey.
>
...
glbl1_chip, &max77658->irqc_glbl1);
> +}
> +
> +static int max77658_i2c_probe(struct i2c_client *client,
> + const struct i2c_device_id *id)
> +{
> + struct device *dev = &client->dev;
> + struct max77658_dev *max77658;
> + const struct mfd_cell *cells;
> + struct i2c_client *fuel;
> + int ret, n_devs;
> +
> + max77658 = devm_kzalloc(dev, sizeof(*max77658), GFP_KERNEL);
> + if (!max77658)
> + return -ENOMEM;
> +
> + i2c_set_clientdata(client, max77658);
> + max77658->irq = client->irq;
> +
> + max77658->id = (enum max77658_ids)device_get_match_data(dev);
Double space -> One space.
> + if (!max77658->id)
> + max77658->id = (enum max77658_ids)id->driver_data;
> +
> + if (!max77658->id)
> + return -EINVAL;
> +
> + max77658->regmap = devm_regmap_init_i2c(client,
> + &max77658_regmap_config);
> + if (IS_ERR(max77658->regmap))
> + return dev_err_probe(dev, PTR_ERR(max77658->regmap),
> + "Failed to initialize regmap\n");
> +
> + fuel = i2c_new_dummy_device(client->adapter, I2C_ADDR_FUEL_GAUGE);
> + if (IS_ERR(fuel))
> + return dev_err_probe(dev, PTR_ERR(fuel),
> + "Failed to create I2C device[0x%Xh]\n",
> + I2C_ADDR_FUEL_GAUGE);
Where do you free "fuel" instance?
> +
> + i2c_set_clientdata(fuel, max77658);
> +
> + max77658->regmap_fg = devm_regmap_init_i2c(fuel,
> + &max77658_regmap_config_fg);
> + if (IS_ERR(max77658->regmap_fg))
> + return dev_err_probe(dev,
> + PTR_ERR(max77658->regmap_fg),
> + "Failed to initialize I2C device[0x%Xh]\n",
> + I2C_ADDR_FUEL_GAUGE);
> +
> + ret = max77658_pmic_irq_init(dev);
> + if (ret < 0)
> + return dev_err_probe(dev, ret, "Failed to initialize IRQ\n");
> +
> + switch (max77658->id) {
> + case ID_MAX77643:
> + cells = max77643_devs;
> + n_devs = ARRAY_SIZE(max77643_devs);
> + break;
> + case ID_MAX77654:
> + cells = max77654_devs;
> + n_devs = ARRAY_SIZE(max77654_devs);
> + break;
> + case ID_MAX77658:
> + cells = max77658_devs;
> + n_devs = ARRAY_SIZE(max77658_devs);
> + break;
> + case ID_MAX77659:
> + cells = max77659_devs;
> + n_devs = ARRAY_SIZE(max77659_devs);
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + ret = devm_mfd_add_devices(dev, -1, cells, n_devs, NULL, 0, NULL);
> + if (ret)
> + return dev_err_probe(dev, ret, "Failed to add sub-devices\n");
> +
> + return device_init_wakeup(dev, true);
> +}
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 5/7] power: supply: max77658: Add ADI MAX77658 Battery Support
2023-05-08 13:10 ` [PATCH v3 5/7] power: supply: max77658: Add ADI MAX77658 Battery Support Zeynep Arslanbenzer
2023-05-08 19:57 ` Krzysztof Kozlowski
@ 2023-05-08 20:15 ` Krzysztof Kozlowski
1 sibling, 0 replies; 22+ messages in thread
From: Krzysztof Kozlowski @ 2023-05-08 20:15 UTC (permalink / raw)
To: Zeynep Arslanbenzer, lee, robh+dt, krzysztof.kozlowski+dt, sre,
lgirdwood, broonie
Cc: linux-kernel, devicetree, linux-pm, Nurettin Bolucu
On 08/05/2023 15:10, Zeynep Arslanbenzer wrote:
> Battery driver for ADI MAX77658.
>
> The MAX77658 is an ultra-low power fuel gauge which implements the Maxim ModelGauge m5 EZ algorithm.
>
> Signed-off-by: Nurettin Bolucu <Nurettin.Bolucu@analog.com>
> Signed-off-by: Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
> ---
> drivers/power/supply/Kconfig | 7 +
> drivers/power/supply/Makefile | 1 +
> drivers/power/supply/max77658-battery.c | 633 ++++++++++++++++++++++++
> 3 files changed, 641 insertions(+)
> create mode 100644 drivers/power/supply/max77658-battery.c
>
> diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
> index 4b68bbb1e2a8..f9556f4b9e35 100644
> --- a/drivers/power/supply/Kconfig
> +++ b/drivers/power/supply/Kconfig
> @@ -572,6 +572,13 @@ config CHARGER_MAX77658
> Say Y to enable support for the battery charger control of
> MAX77654/58/59 PMIC.
>
> +config BATTERY_MAX77658
> + tristate "Analog Devices MAX77658 battery driver"
> + depends on MFD_MAX77658
> + help
> + Say Y to enable support for the battery control of
> + MAX77658 PMIC.
> +
> config CHARGER_MAX77693
> tristate "Maxim MAX77693 battery charger driver"
> depends on MFD_MAX77693
> diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
> index af4bd6e5969f..e5a425d333a7 100644
> --- a/drivers/power/supply/Makefile
> +++ b/drivers/power/supply/Makefile
> @@ -77,6 +77,7 @@ obj-$(CONFIG_CHARGER_MAX14577) += max14577_charger.o
> obj-$(CONFIG_CHARGER_DETECTOR_MAX14656) += max14656_charger_detector.o
> obj-$(CONFIG_CHARGER_MAX77650) += max77650-charger.o
> obj-$(CONFIG_CHARGER_MAX77658) += max77658-charger.o
> +obj-$(CONFIG_BATTERY_MAX77658) += max77658-battery.o
> obj-$(CONFIG_CHARGER_MAX77693) += max77693_charger.o
> obj-$(CONFIG_CHARGER_MAX77976) += max77976_charger.o
> obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o
> diff --git a/drivers/power/supply/max77658-battery.c b/drivers/power/supply/max77658-battery.c
> new file mode 100644
> index 000000000000..4948ef227db1
> --- /dev/null
> +++ b/drivers/power/supply/max77658-battery.c
> @@ -0,0 +1,633 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2023 Analog Devices, Inc.
> + * ADI battery driver for the MAX77658
> + */
> +
> +#include <linux/bitfield.h>
> +#include <linux/delay.h>
> +#include <linux/mfd/max77658.h>
> +#include <linux/module.h>
> +#include <linux/of_irq.h>
> +#include <linux/platform_device.h>
> +#include <linux/power_supply.h>
> +#include <linux/regmap.h>
> +
> +/* Default value for SALRT min threshold, in percent */
> +#define MAX77658_SALRT_MIN_DEFAULT 1
> +/* Default value for SALRT max threshold, in percent */
> +#define MAX77658_SALRT_MAX_DEFAULT 99
> +
> +#define MAX77658_IALRTTH_RESOLUTION 8567
> +#define MAX77658_CURRENT_RESOLUTION 33487
> +#define MAX77658_VOLTAGE_RESOLUTION 78125
> +#define MAX77658_FG_DELAY 1000
> +#define MAX77658_BATTERY_FULL 100
> +#define MAX77658_BATTERY_LOW 40
> +#define MAX77658_BATTERY_CRITICAL 10
> +#define MAX77658_MAXMINVOLT_STEP 20000
> +#define MAX77658_VALRTTH_STEP 20000
> +#define MAX77658_VEMPTY_VE_STEP 10000
> +#define MAX77658_POWER_STEP 17100
> +
> +#define MAX77658_REG_STATUS 0x00
> +#define MAX77658_REG_VALRTTH 0x01
> +#define MAX77658_REG_TALRTTH 0x02
> +#define MAX77658_REG_SALRTTH 0x03
> +#define MAX77658_REG_CONFIG 0x1D
> +#define MAX77658_REG_DEVNAME 0x21
> +#define MAX77658_REG_VEMPTY 0x3A
> +#define MAX77658_REG_AVGPOWER 0xB3
> +#define MAX77658_REG_IALRTTH 0xB4
> +#define MAX77658_REG_CONFIG2 0xBB
> +#define MAX77658_REG_TEMP 0x08
> +#define MAX77658_REG_VCELL 0x09
> +#define MAX77658_REG_CURRENT 0x0A
> +#define MAX77658_REG_AVGCURRENT 0x0B
> +#define MAX77658_REG_AVGVCELL 0x19
> +#define MAX77658_REG_MAXMINTEMP 0x1A
> +#define MAX77658_REG_MAXMINVOLT 0x1B
> +#define MAX77658_REG_MAXMINCURR 0x1C
> +#define MAX77658_REG_REPSOC 0x06
> +#define MAX77658_REG_TTE 0x11
> +#define MAX77658_REG_TTF 0x20
This is max17055 or very close one. Don't duplicate drivers. Entire
driver should be merged to existing one, e.g. max17042.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 3/7] power: supply: max77658: Add ADI MAX77654/58/59 Charger Support
2023-05-08 13:10 ` [PATCH v3 3/7] power: supply: max77658: Add ADI MAX77654/58/59 Charger Support Zeynep Arslanbenzer
2023-05-08 19:51 ` Krzysztof Kozlowski
@ 2023-05-08 20:22 ` Krzysztof Kozlowski
2023-06-16 10:39 ` Arslanbenzer, Zeynep
1 sibling, 1 reply; 22+ messages in thread
From: Krzysztof Kozlowski @ 2023-05-08 20:22 UTC (permalink / raw)
To: Zeynep Arslanbenzer, lee, robh+dt, krzysztof.kozlowski+dt, sre,
lgirdwood, broonie
Cc: linux-kernel, devicetree, linux-pm, Nurettin Bolucu
On 08/05/2023 15:10, Zeynep Arslanbenzer wrote:
> Charger driver for ADI MAX77654/58/59.
>
> The MAX77654/58/59 charger is Smart Power Selector Li+/Li-Poly Charger.
>
> Signed-off-by: Nurettin Bolucu <Nurettin.Bolucu@analog.com>
> Signed-off-by: Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
> ---
> drivers/power/supply/Kconfig | 7 +
> drivers/power/supply/Makefile | 1 +
> drivers/power/supply/max77658-charger.c | 844 ++++++++++++++++++++++++
> 3 files changed, 852 insertions(+)
> create mode 100644 drivers/power/supply/max77658-charger.c
>
Actually, with small differences (register map differs by few offsets)
this is max77650 charger. Several fields are exactly the same.
Please merge it with existing drivers.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 22+ messages in thread
* RE: [PATCH v3 3/7] power: supply: max77658: Add ADI MAX77654/58/59 Charger Support
2023-05-08 20:22 ` Krzysztof Kozlowski
@ 2023-06-16 10:39 ` Arslanbenzer, Zeynep
0 siblings, 0 replies; 22+ messages in thread
From: Arslanbenzer, Zeynep @ 2023-06-16 10:39 UTC (permalink / raw)
To: Krzysztof Kozlowski, lee, robh+dt, krzysztof.kozlowski+dt, sre,
lgirdwood, broonie
Cc: linux-kernel, devicetree, linux-pm
On Mon, 8 May 2023 , Krzysztof Kozlowski wrote:
>On 08/05/2023 15:10, Zeynep Arslanbenzer wrote:
>> Charger driver for ADI MAX77654/58/59.
>>
>> The MAX77654/58/59 charger is Smart Power Selector Li+/Li-Poly Charger.
>>
>> Signed-off-by: Nurettin Bolucu <Nurettin.Bolucu@analog.com>
>> Signed-off-by: Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
>> ---
>> drivers/power/supply/Kconfig | 7 +
>> drivers/power/supply/Makefile | 1 +
>> drivers/power/supply/max77658-charger.c | 844
>> ++++++++++++++++++++++++
>> 3 files changed, 852 insertions(+)
>> create mode 100644 drivers/power/supply/max77658-charger.c
>>
>
>Actually, with small differences (register map differs by few offsets) this is max77650 charger. Several fields are exactly the same.
>
>Please merge it with existing drivers.
>
>Best regards,
>Krzysztof
Since max77650 is similar to devices supported by this patch set,
I guess I should merge the regulator and mfd drivers too with the existing max77650 drivers.
As I observed from other device drivers, adding a new device driver support to an existing driver
should not change the existing driver code too much. But as I want to add support for 4 extra devices to max77650 drivers,
It can cause changes to the already existing driver code. I just want to be sure before sending a new patch, sorry for the long explanation.
Would it be okay to change the existing code and make the code more generic to add new devices?
For example, the regulator max77650 driver was written for a single device and
the developer made the regulator definitions separately as follows.
static struct max77650_regulator_desc max77650_LDO_desc = {
.desc = {
.name = "ldo",
static struct max77650_regulator_desc max77650_SBB0_desc = {
.desc = {
.name = "sbb0",
static struct max77650_regulator_desc max77650_SBB1_desc = {
.desc = {
.name "sbb1",
I want to add support for 4 regulators devices. Each of them has multiple LDOs and SBBs. This means I need to
add almost 20 regulator_desc separately if I want to add support according to the existing driver code. Instead of this, I can
use macros as below but it causes changes in the existing driver (if I make max77650 regulator descriptions too using macros).
#define REGULATOR_DESC_LDO() {
#define REGULATOR_DESC_SBB() {
static const struct regulator_desc max77650_regulator_desc[] = {
REGULATOR_DESC_LDO(LDO),
REGULATOR_DESC_SBB(SBB0),
REGULATOR_DESC_SBB(SBB1),
REGULATOR_DESC_SBB(SBB2),
)
Similar problems occur on the mfd driver as well (irqs and mfd_cells).
Best regards,
Zeynep
^ permalink raw reply [flat|nested] 22+ messages in thread
end of thread, other threads:[~2023-06-16 12:55 UTC | newest]
Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-08 13:10 [PATCH v3 0/7] Add MAX77643/MAX77654/MAX77658/MAX77659 PMIC Support Zeynep Arslanbenzer
2023-05-08 13:10 ` [PATCH v3 1/7] regulator: max77658: Add ADI MAX77643/54/58/59 Regulator Support Zeynep Arslanbenzer
2023-05-08 13:10 ` [PATCH v3 2/7] dt-bindings: power: supply: max77658: Add ADI MAX77654/58/59 Charger Zeynep Arslanbenzer
2023-05-08 14:32 ` Krzysztof Kozlowski
2023-05-08 14:36 ` Krzysztof Kozlowski
2023-05-08 19:45 ` Krzysztof Kozlowski
2023-05-08 19:55 ` Krzysztof Kozlowski
2023-05-08 13:10 ` [PATCH v3 3/7] power: supply: max77658: Add ADI MAX77654/58/59 Charger Support Zeynep Arslanbenzer
2023-05-08 19:51 ` Krzysztof Kozlowski
2023-05-08 20:22 ` Krzysztof Kozlowski
2023-06-16 10:39 ` Arslanbenzer, Zeynep
2023-05-08 13:10 ` [PATCH v3 4/7] dt-bindings: power: supply: max77658: Add ADI MAX77658 Battery Zeynep Arslanbenzer
2023-05-08 14:31 ` Krzysztof Kozlowski
2023-05-08 19:54 ` Krzysztof Kozlowski
2023-05-08 13:10 ` [PATCH v3 5/7] power: supply: max77658: Add ADI MAX77658 Battery Support Zeynep Arslanbenzer
2023-05-08 19:57 ` Krzysztof Kozlowski
2023-05-08 20:15 ` Krzysztof Kozlowski
2023-05-08 13:10 ` [PATCH v3 6/7] dt-bindings: mfd: max77658: Add ADI MAX77658 Zeynep Arslanbenzer
2023-05-08 14:31 ` Krzysztof Kozlowski
2023-05-08 20:02 ` Krzysztof Kozlowski
2023-05-08 13:10 ` [PATCH v3 7/7] mfd: max77658: Add ADI MAX77643/54/58/59 MFD Support Zeynep Arslanbenzer
2023-05-08 20:09 ` Krzysztof Kozlowski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).