All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/15] Add Intel Cherry Trail Whiskey Cove PMIC support
@ 2017-03-17  9:55 Hans de Goede
  2017-03-17  9:55 ` [PATCH 01/15] mfd: Add Cherry Trail Whiskey Cove PMIC driver Hans de Goede
                   ` (14 more replies)
  0 siblings, 15 replies; 90+ messages in thread
From: Hans de Goede @ 2017-03-17  9:55 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Wolfram Sang, Andy Shevchenko,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: Hans de Goede, linux-acpi, Takashi Iwai, linux-i2c, linux-kernel,
	linux-pm

Hi All,

Here is a patch-series adding support for the Intel Cherry Trail Whiskey
Cove PMIC. The first 2 patches have been send before and as such are
at v3 now, the rest is new. This series touches a lot of subsystems
(as usually is the case with mfd devices). I'm sending this as a single
series so that people can see how all the bits fit together.

Patches 1-13 do not have any interdependencies (other then runtime deps
which are not a problem for merging) and can be merged directly into
their resp. subsystems when they pass review.

Patch 14: power: supply: Add driver for Cherry Trail Whiskey Cove
PMIC Fuel Gauge, depends on the i2c-core changes from patches 11-13.

Patch 15: i2c-cht-wc: Add Intel Cherry Trail Whiskey Cove SMBUS
controller driver, depends on both the bq24190_charger patches as it
uses new bq24190_platform_data fields for the i2c_board_info->platform_data
for the i2c client it registers, as well as on patch 14 as it uses
the cht_wc_fg_get_property symbol that patch adds/exports.

Regards,

Hans

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [PATCH 01/15] mfd: Add Cherry Trail Whiskey Cove PMIC driver
  2017-03-17  9:55 [PATCH 00/15] Add Intel Cherry Trail Whiskey Cove PMIC support Hans de Goede
@ 2017-03-17  9:55 ` Hans de Goede
  2017-03-17 17:00   ` Andy Shevchenko
  2017-03-17  9:55 ` [PATCH 02/15] ACPI / PMIC: Add opregion driver for Intel CHT Whiskey Cove PMIC Hans de Goede
                   ` (13 subsequent siblings)
  14 siblings, 1 reply; 90+ messages in thread
From: Hans de Goede @ 2017-03-17  9:55 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Wolfram Sang, Andy Shevchenko,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: Hans de Goede, linux-acpi, Takashi Iwai, linux-i2c, linux-kernel,
	linux-pm, Bin Gao, Felipe Balbi

Add mfd driver for Intel CHT Whiskey Cove PMIC, based on various non
upstreamed CHT Whiskey Cove PMIC patches.

This is a somewhat minimal version which adds irqchip support and cells
for: ACPI PMIC opregion support, the i2c-controller driving the external
charger irc and the pwrsrc/extcon block.

Further cells can be added in the future if/when drivers are upstreamed
for them.

Cc: Bin Gao <bin.gao@intel.com>
Cc: Felipe Balbi <felipe.balbi@linux.intel.com>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
Changes in v2:
-Since this uses plain mfd and not the intel_soc_pmic stuff give it
 its own Kconfig and allow this to be built as a module
-Add missing #include <acpi/acpi_bus.h>
Changes in v3:
-Drop #include <acpi/acpi_bus.h> again, not the right fix for the build errors
-Error out when the upper byte of the register-address passed to the regmap
 functions is 0 rather then hardcoding an address in that case
-Various minor style tweaks / cleanups
-Move defines of regulator register addresses to intel_pmic_chtwc.c,
 it is the only place where they are used
-Drop now empty include/linux/mfd/intel_chtwc.h
-Rename intel_soc_pmic_chtwc.c to intel_cht_wc.c to match Kconfig option name
-Add irqchip support
-Add external charger cell
-Add pwrsrc cell
---
 drivers/mfd/Kconfig                |  11 ++
 drivers/mfd/Makefile               |   1 +
 drivers/mfd/intel_soc_pmic_chtwc.c | 243 +++++++++++++++++++++++++++++++++++++
 3 files changed, 255 insertions(+)
 create mode 100644 drivers/mfd/intel_soc_pmic_chtwc.c

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 55ecdfb..d427a10 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -437,6 +437,17 @@ config INTEL_SOC_PMIC
 	  thermal, charger and related power management functions
 	  on these systems.
 
+config INTEL_SOC_PMIC_CHTWC
+	tristate "Support for Intel Cherry Trail Whiskey Cove PMIC"
+	depends on ACPI
+	depends on I2C
+	select MFD_CORE
+	select REGMAP_I2C
+	select REGMAP_IRQ
+	help
+	  Select this option to enable support for the Intel Cherry Trail
+	  Whiskey Cove PMIC found on some Intel Cherry Trail systems.
+
 config MFD_INTEL_LPSS
 	tristate
 	select COMMON_CLK
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 31ce076..d2ca514 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -209,6 +209,7 @@ obj-$(CONFIG_MFD_SKY81452)	+= sky81452.o
 intel-soc-pmic-objs		:= intel_soc_pmic_core.o intel_soc_pmic_crc.o
 intel-soc-pmic-$(CONFIG_INTEL_PMC_IPC)	+= intel_soc_pmic_bxtwc.o
 obj-$(CONFIG_INTEL_SOC_PMIC)	+= intel-soc-pmic.o
+obj-$(CONFIG_INTEL_SOC_PMIC_CHTWC) += intel_soc_pmic_chtwc.o
 obj-$(CONFIG_MFD_MT6397)	+= mt6397-core.o
 
 obj-$(CONFIG_MFD_ALTERA_A10SR)	+= altera-a10sr.o
diff --git a/drivers/mfd/intel_soc_pmic_chtwc.c b/drivers/mfd/intel_soc_pmic_chtwc.c
new file mode 100644
index 0000000..449462a
--- /dev/null
+++ b/drivers/mfd/intel_soc_pmic_chtwc.c
@@ -0,0 +1,243 @@
+/*
+ * MFD core driver for Intel Cherrytrail Whiskey Cove PMIC
+ * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Based on various non upstream patches to support the CHT Whiskey Cove PMIC:
+ * Copyright (C) 2013-2015 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/acpi.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/intel_soc_pmic.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+/* PMIC device registers */
+#define REG_OFFSET_MASK		GENMASK(7, 0)
+#define REG_ADDR_MASK		GENMASK(15, 8)
+#define REG_ADDR_SHIFT		8
+
+#define CHT_WC_IRQLVL1		0x6e02
+#define CHT_WC_IRQLVL1_MASK	0x6e0e
+
+/* Whiskey Cove PMIC share same ACPI ID between different platforms */
+#define CHT_WC_HRV		3
+
+/* Level 1 IRQs (level 2 IRQs are handled in the child device drivers) */
+enum {
+	CHT_WC_PWRSRC_IRQ = 0,
+	CHT_WC_THRM_IRQ,
+	CHT_WC_BCU_IRQ,
+	CHT_WC_ADC_IRQ,
+	CHT_WC_EXT_CHGR_IRQ,
+	CHT_WC_GPIO_IRQ,
+	/* There is no irq 6 */
+	CHT_WC_CRIT_IRQ = 7,
+};
+
+static struct resource cht_wc_pwrsrc_resources[] = {
+	DEFINE_RES_IRQ(CHT_WC_PWRSRC_IRQ),
+};
+
+static struct resource cht_wc_ext_charger_resources[] = {
+	DEFINE_RES_IRQ(CHT_WC_EXT_CHGR_IRQ),
+};
+
+static struct mfd_cell cht_wc_dev[] = {
+	{
+		.name = "cht_wcove_pwrsrc",
+		.num_resources = ARRAY_SIZE(cht_wc_pwrsrc_resources),
+		.resources = cht_wc_pwrsrc_resources,
+	},
+	{
+		.name = "cht_wcove_ext_chgr",
+		.num_resources = ARRAY_SIZE(cht_wc_ext_charger_resources),
+		.resources = cht_wc_ext_charger_resources,
+	},
+	{
+		.name = "cht_wcove_region",
+	},
+};
+
+/*
+ * The CHT Whiskey Cove covers multiple i2c addresses, with a 1 byte
+ * register address space per i2c address, so we use 16 bit register
+ * addresses where the high 8 bits contain the i2c client address.
+ */
+static int cht_wc_byte_reg_read(void *context, unsigned int reg,
+				unsigned int *val)
+{
+	struct i2c_client *client = context;
+	int ret, orig_addr = client->addr;
+
+	if (!(reg & REG_ADDR_MASK)) {
+		dev_err(&client->dev, "Error i2c address not specified\n");
+		return -EINVAL;
+	}
+
+	client->addr = (reg & REG_ADDR_MASK) >> REG_ADDR_SHIFT;
+	ret = i2c_smbus_read_byte_data(client, reg & REG_OFFSET_MASK);
+	client->addr = orig_addr;
+
+	if (ret < 0)
+		return ret;
+
+	*val = ret;
+	return 0;
+}
+
+static int cht_wc_byte_reg_write(void *context, unsigned int reg,
+				 unsigned int val)
+{
+	struct i2c_client *client = context;
+	int ret, orig_addr = client->addr;
+
+	if (!(reg & REG_ADDR_MASK)) {
+		dev_err(&client->dev, "Error i2c address not specified\n");
+		return -EINVAL;
+	}
+
+	client->addr = (reg & REG_ADDR_MASK) >> REG_ADDR_SHIFT;
+	ret = i2c_smbus_write_byte_data(client, reg & REG_OFFSET_MASK, val);
+	client->addr = orig_addr;
+
+	return ret;
+}
+
+static const struct regmap_config cht_wc_regmap_cfg = {
+	.reg_bits = 16,
+	.val_bits = 8,
+	.reg_write = cht_wc_byte_reg_write,
+	.reg_read = cht_wc_byte_reg_read,
+};
+
+static const struct regmap_irq cht_wc_regmap_irqs[] = {
+	REGMAP_IRQ_REG(CHT_WC_PWRSRC_IRQ, 0, BIT(CHT_WC_PWRSRC_IRQ)),
+	REGMAP_IRQ_REG(CHT_WC_THRM_IRQ, 0, BIT(CHT_WC_THRM_IRQ)),
+	REGMAP_IRQ_REG(CHT_WC_BCU_IRQ, 0, BIT(CHT_WC_BCU_IRQ)),
+	REGMAP_IRQ_REG(CHT_WC_ADC_IRQ, 0, BIT(CHT_WC_ADC_IRQ)),
+	REGMAP_IRQ_REG(CHT_WC_EXT_CHGR_IRQ, 0, BIT(CHT_WC_EXT_CHGR_IRQ)),
+	REGMAP_IRQ_REG(CHT_WC_GPIO_IRQ, 0, BIT(CHT_WC_GPIO_IRQ)),
+	REGMAP_IRQ_REG(CHT_WC_CRIT_IRQ, 0, BIT(CHT_WC_CRIT_IRQ)),
+};
+
+static const struct regmap_irq_chip cht_wc_regmap_irq_chip = {
+	.name = "cht_wc_irq_chip",
+	.status_base = CHT_WC_IRQLVL1,
+	.mask_base = CHT_WC_IRQLVL1_MASK,
+	.irqs = cht_wc_regmap_irqs,
+	.num_irqs = ARRAY_SIZE(cht_wc_regmap_irqs),
+	.num_regs = 1,
+};
+
+static int cht_wc_probe(struct i2c_client *client,
+			const struct i2c_device_id *i2c_id)
+{
+	struct device *dev = &client->dev;
+	struct intel_soc_pmic *pmic;
+	acpi_status status;
+	unsigned long long hrv;
+	int ret;
+
+	status = acpi_evaluate_integer(ACPI_HANDLE(dev), "_HRV", NULL, &hrv);
+	if (ACPI_FAILURE(status)) {
+		dev_err(dev, "Failed to get PMIC hardware revision\n");
+		return -ENODEV;
+	}
+	if (hrv != CHT_WC_HRV) {
+		dev_err(dev, "Invalid PMIC hardware revision: %llu\n", hrv);
+		return -ENODEV;
+	}
+	if (client->irq < 0) {
+		dev_err(dev, "Invalid IRQ\n");
+		return -ENODEV;
+	}
+
+	pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);
+	if (!pmic)
+		return -ENOMEM;
+
+	pmic->irq = client->irq;
+	pmic->dev = dev;
+	i2c_set_clientdata(client, pmic);
+
+	pmic->regmap = devm_regmap_init(dev, NULL, client, &cht_wc_regmap_cfg);
+	if (IS_ERR(pmic->regmap))
+		return PTR_ERR(pmic->regmap);
+
+	ret = devm_regmap_add_irq_chip(dev, pmic->regmap, pmic->irq,
+				       IRQF_ONESHOT | IRQF_SHARED, 0,
+				       &cht_wc_regmap_irq_chip,
+				       &pmic->irq_chip_data);
+	if (ret)
+		return ret;
+
+	return devm_mfd_add_devices(dev, -1, cht_wc_dev, ARRAY_SIZE(cht_wc_dev),
+			NULL, 0, regmap_irq_get_domain(pmic->irq_chip_data));
+}
+
+static void cht_wc_shutdown(struct i2c_client *client)
+{
+	struct intel_soc_pmic *pmic = i2c_get_clientdata(client);
+
+	disable_irq(pmic->irq);
+}
+
+static int __maybe_unused cht_wc_suspend(struct device *dev)
+{
+	struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
+
+	disable_irq(pmic->irq);
+	return 0;
+}
+
+static int __maybe_unused cht_wc_resume(struct device *dev)
+{
+	struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
+
+	enable_irq(pmic->irq);
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(cht_wc_pm_ops, cht_wc_suspend, cht_wc_resume);
+
+static const struct i2c_device_id cht_wc_i2c_id[] = {
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, cht_wc_i2c_id);
+
+static const struct acpi_device_id cht_wc_acpi_ids[] = {
+	{ "INT34D3", },
+	{ }
+};
+MODULE_DEVICE_TABLE(acpi, cht_wc_acpi_ids);
+
+static struct i2c_driver cht_wc_driver = {
+	.driver	= {
+		.name	= "CHT Whiskey Cove PMIC",
+		.pm     = &cht_wc_pm_ops,
+		.acpi_match_table = ACPI_PTR(cht_wc_acpi_ids),
+	},
+	.probe = cht_wc_probe,
+	.shutdown = cht_wc_shutdown,
+	.id_table = cht_wc_i2c_id,
+};
+
+module_i2c_driver(cht_wc_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [PATCH 02/15] ACPI / PMIC: Add opregion driver for Intel CHT Whiskey Cove PMIC
  2017-03-17  9:55 [PATCH 00/15] Add Intel Cherry Trail Whiskey Cove PMIC support Hans de Goede
  2017-03-17  9:55 ` [PATCH 01/15] mfd: Add Cherry Trail Whiskey Cove PMIC driver Hans de Goede
@ 2017-03-17  9:55 ` Hans de Goede
  2017-03-17  9:55 ` [PATCH 03/15] extcon: cht-wc: Add Intel Cherry Trail Whiskey Cove PMIC extcon driver Hans de Goede
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 90+ messages in thread
From: Hans de Goede @ 2017-03-17  9:55 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Wolfram Sang, Andy Shevchenko,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: Hans de Goede, linux-acpi, Takashi Iwai, linux-i2c, linux-kernel,
	linux-pm, Bin Gao, Felipe Balbi

Add opregion driver for Intel CHT Whiskey Cove PMIC, based on various
non upstreamed CHT Whiskey Cove PMIC patches. This does not include
support for the Thermal opregion (DPTF) due to lacking documentation.

Cc: Bin Gao <bin.gao@intel.com>
Cc: Felipe Balbi <felipe.balbi@linux.intel.com>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
Changes in v2:
-s/WhiskeyCove/Whiskey Cove/
-Some minor style tweaks
-Allow building as module
Changes in v3:
-Drop filename from copyright header
-Simplify intel_cht_wc_pmic_update_power to 1 line
-Move defines of regulator register addresses to intel_pmic_chtwc.c,
 it is the only place where they are used
---
 drivers/acpi/Kconfig                 |   6 +
 drivers/acpi/Makefile                |   1 +
 drivers/acpi/pmic/intel_pmic_chtwc.c | 280 +++++++++++++++++++++++++++++++++++
 3 files changed, 287 insertions(+)
 create mode 100644 drivers/acpi/pmic/intel_pmic_chtwc.c

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 83e5f7e..e3c4ef0 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -516,6 +516,12 @@ config BXT_WC_PMIC_OPREGION
 	help
 	  This config adds ACPI operation region support for BXT WhiskeyCove PMIC.
 
+config CHT_WC_PMIC_OPREGION
+	tristate "ACPI operation region support for CHT Whiskey Cove PMIC"
+	depends on INTEL_SOC_PMIC_CHTWC
+	help
+	  This config adds ACPI operation region support for CHT Whiskey Cove PMIC.
+
 endif
 
 config ACPI_CONFIGFS
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index a391bbc..6f6b47f 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -102,6 +102,7 @@ obj-$(CONFIG_PMIC_OPREGION)	+= pmic/intel_pmic.o
 obj-$(CONFIG_CRC_PMIC_OPREGION) += pmic/intel_pmic_crc.o
 obj-$(CONFIG_XPOWER_PMIC_OPREGION) += pmic/intel_pmic_xpower.o
 obj-$(CONFIG_BXT_WC_PMIC_OPREGION) += pmic/intel_pmic_bxtwc.o
+obj-$(CONFIG_CHT_WC_PMIC_OPREGION) += pmic/intel_pmic_chtwc.o
 
 obj-$(CONFIG_ACPI_CONFIGFS)	+= acpi_configfs.o
 
diff --git a/drivers/acpi/pmic/intel_pmic_chtwc.c b/drivers/acpi/pmic/intel_pmic_chtwc.c
new file mode 100644
index 0000000..85636d7
--- /dev/null
+++ b/drivers/acpi/pmic/intel_pmic_chtwc.c
@@ -0,0 +1,280 @@
+/*
+ * Intel CHT Whiskey Cove PMIC operation region driver
+ * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Based on various non upstream patches to support the CHT Whiskey Cove PMIC:
+ * Copyright (C) 2013-2015 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/acpi.h>
+#include <linux/init.h>
+#include <linux/mfd/intel_soc_pmic.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include "intel_pmic.h"
+
+#define CHT_WC_V1P05A_CTRL		0x6e3b
+#define CHT_WC_V1P15_CTRL		0x6e3c
+#define CHT_WC_V1P05A_VSEL		0x6e3d
+#define CHT_WC_V1P15_VSEL		0x6e3e
+#define CHT_WC_V1P8A_CTRL		0x6e56
+#define CHT_WC_V1P8SX_CTRL		0x6e57
+#define CHT_WC_VDDQ_CTRL		0x6e58
+#define CHT_WC_V1P2A_CTRL		0x6e59
+#define CHT_WC_V1P2SX_CTRL		0x6e5a
+#define CHT_WC_V1P8A_VSEL		0x6e5b
+#define CHT_WC_VDDQ_VSEL		0x6e5c
+#define CHT_WC_V2P8SX_CTRL		0x6e5d
+#define CHT_WC_V3P3A_CTRL		0x6e5e
+#define CHT_WC_V3P3SD_CTRL		0x6e5f
+#define CHT_WC_VSDIO_CTRL		0x6e67
+#define CHT_WC_V3P3A_VSEL		0x6e68
+#define CHT_WC_VPROG1A_CTRL		0x6e90
+#define CHT_WC_VPROG1B_CTRL		0x6e91
+#define CHT_WC_VPROG1F_CTRL		0x6e95
+#define CHT_WC_VPROG2D_CTRL		0x6e99
+#define CHT_WC_VPROG3A_CTRL		0x6e9a
+#define CHT_WC_VPROG3B_CTRL		0x6e9b
+#define CHT_WC_VPROG4A_CTRL		0x6e9c
+#define CHT_WC_VPROG4B_CTRL		0x6e9d
+#define CHT_WC_VPROG4C_CTRL		0x6e9e
+#define CHT_WC_VPROG4D_CTRL		0x6e9f
+#define CHT_WC_VPROG5A_CTRL		0x6ea0
+#define CHT_WC_VPROG5B_CTRL		0x6ea1
+#define CHT_WC_VPROG6A_CTRL		0x6ea2
+#define CHT_WC_VPROG6B_CTRL		0x6ea3
+#define CHT_WC_VPROG1A_VSEL		0x6ec0
+#define CHT_WC_VPROG1B_VSEL		0x6ec1
+#define CHT_WC_V1P8SX_VSEL		0x6ec2
+#define CHT_WC_V1P2SX_VSEL		0x6ec3
+#define CHT_WC_V1P2A_VSEL		0x6ec4
+#define CHT_WC_VPROG1F_VSEL		0x6ec5
+#define CHT_WC_VSDIO_VSEL		0x6ec6
+#define CHT_WC_V2P8SX_VSEL		0x6ec7
+#define CHT_WC_V3P3SD_VSEL		0x6ec8
+#define CHT_WC_VPROG2D_VSEL		0x6ec9
+#define CHT_WC_VPROG3A_VSEL		0x6eca
+#define CHT_WC_VPROG3B_VSEL		0x6ecb
+#define CHT_WC_VPROG4A_VSEL		0x6ecc
+#define CHT_WC_VPROG4B_VSEL		0x6ecd
+#define CHT_WC_VPROG4C_VSEL		0x6ece
+#define CHT_WC_VPROG4D_VSEL		0x6ecf
+#define CHT_WC_VPROG5A_VSEL		0x6ed0
+#define CHT_WC_VPROG5B_VSEL		0x6ed1
+#define CHT_WC_VPROG6A_VSEL		0x6ed2
+#define CHT_WC_VPROG6B_VSEL		0x6ed3
+
+/*
+ * Regulator support is based on the non upstream patch:
+ * "regulator: whiskey_cove: implements Whiskey Cove pmic VRF support"
+ * https://github.com/intel-aero/meta-intel-aero/blob/master/recipes-kernel/linux/linux-yocto/0019-regulator-whiskey_cove-implements-WhiskeyCove-pmic-V.patch
+ */
+static struct pmic_table power_table[] = {
+	{
+		.address = 0x0,
+		.reg = CHT_WC_V1P8A_CTRL,
+		.bit = 0x01,
+	}, /* V18A */
+	{
+		.address = 0x04,
+		.reg = CHT_WC_V1P8SX_CTRL,
+		.bit = 0x07,
+	}, /* V18X */
+	{
+		.address = 0x08,
+		.reg = CHT_WC_VDDQ_CTRL,
+		.bit = 0x01,
+	}, /* VDDQ */
+	{
+		.address = 0x0c,
+		.reg = CHT_WC_V1P2A_CTRL,
+		.bit = 0x07,
+	}, /* V12A */
+	{
+		.address = 0x10,
+		.reg = CHT_WC_V1P2SX_CTRL,
+		.bit = 0x07,
+	}, /* V12X */
+	{
+		.address = 0x14,
+		.reg = CHT_WC_V2P8SX_CTRL,
+		.bit = 0x07,
+	}, /* V28X */
+	{
+		.address = 0x18,
+		.reg = CHT_WC_V3P3A_CTRL,
+		.bit = 0x01,
+	}, /* V33A */
+	{
+		.address = 0x1c,
+		.reg = CHT_WC_V3P3SD_CTRL,
+		.bit = 0x07,
+	}, /* V3SD */
+	{
+		.address = 0x20,
+		.reg = CHT_WC_VSDIO_CTRL,
+		.bit = 0x07,
+	}, /* VSD */
+/*	{
+		.address = 0x24,
+		.reg = ??,
+		.bit = ??,
+	}, ** VSW2 */
+/*	{
+		.address = 0x28,
+		.reg = ??,
+		.bit = ??,
+	}, ** VSW1 */
+/*	{
+		.address = 0x2c,
+		.reg = ??,
+		.bit = ??,
+	}, ** VUPY */
+/*	{
+		.address = 0x30,
+		.reg = ??,
+		.bit = ??,
+	}, ** VRSO */
+	{
+		.address = 0x34,
+		.reg = CHT_WC_VPROG1A_CTRL,
+		.bit = 0x07,
+	}, /* VP1A */
+	{
+		.address = 0x38,
+		.reg = CHT_WC_VPROG1B_CTRL,
+		.bit = 0x07,
+	}, /* VP1B */
+	{
+		.address = 0x3c,
+		.reg = CHT_WC_VPROG1F_CTRL,
+		.bit = 0x07,
+	}, /* VP1F */
+	{
+		.address = 0x40,
+		.reg = CHT_WC_VPROG2D_CTRL,
+		.bit = 0x07,
+	}, /* VP2D */
+	{
+		.address = 0x44,
+		.reg = CHT_WC_VPROG3A_CTRL,
+		.bit = 0x07,
+	}, /* VP3A */
+	{
+		.address = 0x48,
+		.reg = CHT_WC_VPROG3B_CTRL,
+		.bit = 0x07,
+	}, /* VP3B */
+	{
+		.address = 0x4c,
+		.reg = CHT_WC_VPROG4A_CTRL,
+		.bit = 0x07,
+	}, /* VP4A */
+	{
+		.address = 0x50,
+		.reg = CHT_WC_VPROG4B_CTRL,
+		.bit = 0x07,
+	}, /* VP4B */
+	{
+		.address = 0x54,
+		.reg = CHT_WC_VPROG4C_CTRL,
+		.bit = 0x07,
+	}, /* VP4C */
+	{
+		.address = 0x58,
+		.reg = CHT_WC_VPROG4D_CTRL,
+		.bit = 0x07,
+	}, /* VP4D */
+	{
+		.address = 0x5c,
+		.reg = CHT_WC_VPROG5A_CTRL,
+		.bit = 0x07,
+	}, /* VP5A */
+	{
+		.address = 0x60,
+		.reg = CHT_WC_VPROG5B_CTRL,
+		.bit = 0x07,
+	}, /* VP5B */
+	{
+		.address = 0x64,
+		.reg = CHT_WC_VPROG6A_CTRL,
+		.bit = 0x07,
+	}, /* VP6A */
+	{
+		.address = 0x68,
+		.reg = CHT_WC_VPROG6B_CTRL,
+		.bit = 0x07,
+	}, /* VP6B */
+/*	{
+		.address = 0x6c,
+		.reg = ??,
+		.bit = ??,
+	}  ** VP7A */
+};
+
+static int intel_cht_wc_pmic_get_power(struct regmap *regmap, int reg,
+		int bit, u64 *value)
+{
+	int data;
+
+	if (regmap_read(regmap, reg, &data))
+		return -EIO;
+
+	*value = (data & bit) ? 1 : 0;
+	return 0;
+}
+
+static int intel_cht_wc_pmic_update_power(struct regmap *regmap, int reg,
+		int bitmask, bool on)
+{
+	return regmap_update_bits(regmap, reg, bitmask, on ? 1 : 0);
+}
+
+/*
+ * The thermal table and ops are empty, we do not support the Thermal opregion
+ * (DPTF) due to lacking documentation.
+ */
+static struct intel_pmic_opregion_data intel_cht_wc_pmic_opregion_data = {
+	.get_power		= intel_cht_wc_pmic_get_power,
+	.update_power		= intel_cht_wc_pmic_update_power,
+	.power_table		= power_table,
+	.power_table_count	= ARRAY_SIZE(power_table),
+};
+
+static int intel_cht_wc_pmic_opregion_probe(struct platform_device *pdev)
+{
+	struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
+
+	return intel_pmic_install_opregion_handler(&pdev->dev,
+			ACPI_HANDLE(pdev->dev.parent),
+			pmic->regmap,
+			&intel_cht_wc_pmic_opregion_data);
+}
+
+static struct platform_device_id cht_wc_opregion_id_table[] = {
+	{ .name = "cht_wcove_region" },
+	{},
+};
+MODULE_DEVICE_TABLE(platform, cht_wc_opregion_id_table);
+
+static struct platform_driver intel_cht_wc_pmic_opregion_driver = {
+	.probe = intel_cht_wc_pmic_opregion_probe,
+	.driver = {
+		.name = "cht_whiskey_cove_pmic",
+	},
+	.id_table = cht_wc_opregion_id_table,
+};
+module_platform_driver(intel_cht_wc_pmic_opregion_driver);
+
+MODULE_DESCRIPTION("Intel CHT Whiskey Cove PMIC operation region driver");
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_LICENSE("GPL");
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [PATCH 03/15] extcon: cht-wc: Add Intel Cherry Trail Whiskey Cove PMIC extcon driver
  2017-03-17  9:55 [PATCH 00/15] Add Intel Cherry Trail Whiskey Cove PMIC support Hans de Goede
  2017-03-17  9:55 ` [PATCH 01/15] mfd: Add Cherry Trail Whiskey Cove PMIC driver Hans de Goede
  2017-03-17  9:55 ` [PATCH 02/15] ACPI / PMIC: Add opregion driver for Intel CHT Whiskey Cove PMIC Hans de Goede
@ 2017-03-17  9:55 ` Hans de Goede
  2017-03-17 17:18   ` Andy Shevchenko
  2017-03-20  1:33   ` Chanwoo Choi
  2017-03-17  9:55 ` [PATCH 04/15] power: supply: bq24190_charger: Add no_register_reset pdata flag Hans de Goede
                   ` (11 subsequent siblings)
  14 siblings, 2 replies; 90+ messages in thread
From: Hans de Goede @ 2017-03-17  9:55 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Wolfram Sang, Andy Shevchenko,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: Hans de Goede, linux-acpi, Takashi Iwai, linux-i2c, linux-kernel,
	linux-pm

Add a driver for charger detection / control on the Intel Cherrytrail
Whiskey Cove PMIC.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/extcon/Kconfig         |   7 +
 drivers/extcon/Makefile        |   1 +
 drivers/extcon/extcon-cht-wc.c | 356 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 364 insertions(+)
 create mode 100644 drivers/extcon/extcon-cht-wc.c

diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
index 96bbae5..4cace6b 100644
--- a/drivers/extcon/Kconfig
+++ b/drivers/extcon/Kconfig
@@ -52,6 +52,13 @@ config EXTCON_INTEL_INT3496
 	  This ACPI device is typically found on Intel Baytrail or Cherrytrail
 	  based tablets, or other Baytrail / Cherrytrail devices.
 
+config EXTCON_CHT_WC
+	tristate "Intel Cherrytrail Whiskey Cove PMIC extcon driver"
+	depends on INTEL_SOC_PMIC_CHTWC
+	help
+	  Say Y here to enable extcon support for charger detection / control
+	  on the Intel Cherrytrail Whiskey Cove PMIC.
+
 config EXTCON_MAX14577
 	tristate "Maxim MAX14577/77836 EXTCON Support"
 	depends on MFD_MAX14577
diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile
index 237ac3f..160f88b 100644
--- a/drivers/extcon/Makefile
+++ b/drivers/extcon/Makefile
@@ -7,6 +7,7 @@ extcon-core-objs		+= extcon.o devres.o
 obj-$(CONFIG_EXTCON_ADC_JACK)	+= extcon-adc-jack.o
 obj-$(CONFIG_EXTCON_ARIZONA)	+= extcon-arizona.o
 obj-$(CONFIG_EXTCON_AXP288)	+= extcon-axp288.o
+obj-$(CONFIG_EXTCON_CHT_WC)	+= extcon-cht-wc.o
 obj-$(CONFIG_EXTCON_GPIO)	+= extcon-gpio.o
 obj-$(CONFIG_EXTCON_INTEL_INT3496) += extcon-intel-int3496.o
 obj-$(CONFIG_EXTCON_MAX14577)	+= extcon-max14577.o
diff --git a/drivers/extcon/extcon-cht-wc.c b/drivers/extcon/extcon-cht-wc.c
new file mode 100644
index 0000000..896eee6
--- /dev/null
+++ b/drivers/extcon/extcon-cht-wc.c
@@ -0,0 +1,356 @@
+/*
+ * Extcon charger detection driver for Intel Cherrytrail Whiskey Cove PMIC
+ * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Based on various non upstream patches to support the CHT Whiskey Cove PMIC:
+ * Copyright (C) 2013-2015 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/extcon.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mfd/intel_soc_pmic.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#define CHT_WC_PWRSRC_IRQ		0x6e03
+#define CHT_WC_PWRSRC_IRQ_MASK		0x6e0f
+#define CHT_WC_PWRSRC_STS		0x6e1e
+#define CHT_WC_PWRSRC_VBUS		BIT(0)
+#define CHT_WC_PWRSRC_DC		BIT(1)
+#define CHT_WC_PWRSRC_BAT		BIT(2)
+#define CHT_WC_PWRSRC_ID_GND		BIT(3)
+#define CHT_WC_PWRSRC_ID_FLOAT		BIT(4)
+
+#define CHT_WC_PHYCTRL			0x5e07
+
+#define CHT_WC_CHGRCTRL0		0x5e16
+
+#define CHT_WC_CHGRCTRL0		0x5e16
+#define CHT_WC_CHGRCTRL0_CHGRRESET	BIT(0)
+#define CHT_WC_CHGRCTRL0_EMRGCHREN	BIT(1)
+#define CHT_WC_CHGRCTRL0_EXTCHRDIS	BIT(2)
+#define CHT_WC_CHGRCTRL0_SWCONTROL	BIT(3)
+#define CHT_WC_CHGRCTRL0_TTLCK_MASK	BIT(4)
+#define CHT_WC_CHGRCTRL0_CCSM_OFF_MASK	BIT(5)
+#define CHT_WC_CHGRCTRL0_DBPOFF_MASK	BIT(6)
+#define CHT_WC_CHGRCTRL0_WDT_NOKICK	BIT(7)
+
+#define CHT_WC_CHGRCTRL1		0x5e17
+
+#define CHT_WC_USBSRC			0x5e29
+#define CHT_WC_USBSRC_STS_MASK		GENMASK(1, 0)
+#define CHT_WC_USBSRC_STS_SUCCESS	2
+#define CHT_WC_USBSRC_STS_FAIL		3
+#define CHT_WC_USBSRC_TYPE_SHIFT	2
+#define CHT_WC_USBSRC_TYPE_MASK		GENMASK(5, 2)
+#define CHT_WC_USBSRC_TYPE_NONE		0
+#define CHT_WC_USBSRC_TYPE_SDP		1
+#define CHT_WC_USBSRC_TYPE_DCP		2
+#define CHT_WC_USBSRC_TYPE_CDP		3
+#define CHT_WC_USBSRC_TYPE_ACA		4
+#define CHT_WC_USBSRC_TYPE_SE1		5
+#define CHT_WC_USBSRC_TYPE_MHL		6
+#define CHT_WC_USBSRC_TYPE_FLOAT_DP_DN	7
+#define CHT_WC_USBSRC_TYPE_OTHER	8
+#define CHT_WC_USBSRC_TYPE_DCP_EXTPHY	9
+
+enum cht_wc_usb_id {
+	USB_ID_OTG,
+	USB_ID_GND,
+	USB_ID_FLOAT,
+	USB_RID_A,
+	USB_RID_B,
+	USB_RID_C,
+};
+
+/* Strings matching the cht_wc_usb_id enum labels */
+static const char * const usb_id_str[] = {
+	"otg", "gnd", "float", "rid_a", "rid_b", "rid_c" };
+
+enum cht_wc_mux_select {
+	MUX_SEL_PMIC = 0,
+	MUX_SEL_SOC,
+};
+
+static const unsigned int cht_wc_extcon_cables[] = {
+	EXTCON_USB,
+	EXTCON_USB_HOST,
+	EXTCON_CHG_USB_SDP,
+	EXTCON_CHG_USB_CDP,
+	EXTCON_CHG_USB_DCP,
+	EXTCON_NONE,
+};
+
+struct cht_wc_extcon_data {
+	struct device *dev;
+	struct regmap *regmap;
+	struct extcon_dev *edev;
+	unsigned int previous_cable;
+	int usb_id;
+};
+
+static int cht_wc_extcon_get_id(struct cht_wc_extcon_data *ext, int pwrsrc_sts)
+{
+	if (ext->usb_id)
+		return ext->usb_id;
+
+	if (pwrsrc_sts & CHT_WC_PWRSRC_ID_GND)
+		return USB_ID_GND;
+	if (pwrsrc_sts & CHT_WC_PWRSRC_ID_FLOAT)
+		return USB_ID_FLOAT;
+
+	/*
+	 * Once we have iio support for the gpadc we should read the USBID
+	 * gpadc channel here and determine ACA role based on that.
+	 */
+	return USB_ID_FLOAT;
+}
+
+static int cht_wc_extcon_get_charger(struct cht_wc_extcon_data *ext)
+{
+	int ret, usbsrc, status, retries = 5;
+
+	do {
+		ret = regmap_read(ext->regmap, CHT_WC_USBSRC, &usbsrc);
+		if (ret) {
+			dev_err(ext->dev, "Error reading usbsrc: %d\n", ret);
+			return ret;
+		}
+		status = usbsrc & CHT_WC_USBSRC_STS_MASK;
+		if (status == CHT_WC_USBSRC_STS_SUCCESS ||
+		    status == CHT_WC_USBSRC_STS_FAIL)
+			break;
+
+		msleep(200);
+	} while (retries--);
+
+	if (status != CHT_WC_USBSRC_STS_SUCCESS) {
+		if (status == CHT_WC_USBSRC_STS_FAIL)
+			dev_warn(ext->dev, "Could not detect charger type\n");
+		else
+			dev_warn(ext->dev, "Timeout detecting charger type\n");
+		return EXTCON_CHG_USB_SDP; /* Save fallback */
+	}
+
+	ret = (usbsrc & CHT_WC_USBSRC_TYPE_MASK) >> CHT_WC_USBSRC_TYPE_SHIFT;
+	switch (ret) {
+	default:
+		dev_warn(ext->dev, "Unhandled charger type %d\n", ret);
+		/* Fall through treat as SDP */
+	case CHT_WC_USBSRC_TYPE_SDP:
+	case CHT_WC_USBSRC_TYPE_FLOAT_DP_DN:
+	case CHT_WC_USBSRC_TYPE_OTHER:
+		return EXTCON_CHG_USB_SDP;
+	case CHT_WC_USBSRC_TYPE_CDP:
+		return EXTCON_CHG_USB_CDP;
+	case CHT_WC_USBSRC_TYPE_DCP:
+	case CHT_WC_USBSRC_TYPE_DCP_EXTPHY:
+	case CHT_WC_USBSRC_TYPE_MHL: /* MHL2+ delivers upto 2A, treat as DCP */
+		return EXTCON_CHG_USB_DCP;
+	case CHT_WC_USBSRC_TYPE_ACA:
+		return EXTCON_CHG_USB_ACA;
+	}
+}
+
+static void cht_wc_extcon_set_phymux(struct cht_wc_extcon_data *ext, u8 state)
+{
+	int ret;
+
+	ret = regmap_write(ext->regmap, CHT_WC_PHYCTRL, state);
+	if (ret)
+		dev_err(ext->dev, "Error writing phyctrl: %d\n", ret);
+}
+
+static void cht_wc_extcon_det_event(struct cht_wc_extcon_data *ext)
+{
+	int ret, pwrsrc_sts, id;
+	unsigned int cable = EXTCON_NONE;
+
+	ret = regmap_read(ext->regmap, CHT_WC_PWRSRC_STS, &pwrsrc_sts);
+	if (ret) {
+		dev_err(ext->dev, "Error reading pwrsrc status: %d\n", ret);
+		return;
+	}
+
+	id = cht_wc_extcon_get_id(ext, pwrsrc_sts);
+	if (id == USB_ID_GND) {
+		/* The 5v boost causes a false VBUS / SDP detect, skip */
+		goto charger_det_done;
+	}
+
+	/* Plugged into a host/charger or not connected? */
+	if (!(pwrsrc_sts & CHT_WC_PWRSRC_VBUS)) {
+		/* Route D+ and D- to PMIC for future charger detection */
+		cht_wc_extcon_set_phymux(ext, MUX_SEL_PMIC);
+		goto set_state;
+	}
+
+	ret = cht_wc_extcon_get_charger(ext);
+	if (ret >= 0)
+		cable = ret;
+
+charger_det_done:
+	/* Route D+ and D- to SoC for the host / gadget controller */
+	cht_wc_extcon_set_phymux(ext, MUX_SEL_SOC);
+
+set_state:
+	extcon_set_state_sync(ext->edev, cable, true);
+	extcon_set_state_sync(ext->edev, ext->previous_cable, false);
+	extcon_set_state_sync(ext->edev, EXTCON_USB_HOST,
+			      id == USB_ID_GND || id == USB_RID_A);
+	ext->previous_cable = cable;
+}
+
+static irqreturn_t cht_wc_extcon_isr(int irq, void *data)
+{
+	struct cht_wc_extcon_data *ext = data;
+	int ret, irqs;
+
+	ret = regmap_read(ext->regmap, CHT_WC_PWRSRC_IRQ, &irqs);
+	if (ret)
+		dev_err(ext->dev, "Error reading irqs: %d\n", ret);
+
+	cht_wc_extcon_det_event(ext);
+
+	ret = regmap_write(ext->regmap, CHT_WC_PWRSRC_IRQ, irqs);
+	if (ret)
+		dev_err(ext->dev, "Error writing irqs: %d\n", ret);
+
+	return IRQ_HANDLED;
+}
+
+/* usb_id sysfs attribute for debug / testing purposes */
+static ssize_t usb_id_show(struct device *dev, struct device_attribute *attr,
+			   char *buf)
+{
+	struct cht_wc_extcon_data *ext = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%s\n", usb_id_str[ext->usb_id]);
+}
+
+static ssize_t usb_id_store(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t n)
+{
+	struct cht_wc_extcon_data *ext = dev_get_drvdata(dev);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(usb_id_str); i++) {
+		if (sysfs_streq(buf, usb_id_str[i])) {
+			dev_info(ext->dev, "New usb_id %s\n", usb_id_str[i]);
+			ext->usb_id = i;
+			cht_wc_extcon_det_event(ext);
+			return n;
+		}
+	}
+
+	return -EINVAL;
+}
+
+static DEVICE_ATTR(usb_id, 0644, usb_id_show, usb_id_store);
+
+static int cht_wc_extcon_probe(struct platform_device *pdev)
+{
+	struct cht_wc_extcon_data *ext;
+	struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
+	int irq, ret;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	ext = devm_kzalloc(&pdev->dev, sizeof(*ext), GFP_KERNEL);
+	if (!ext)
+		return -ENOMEM;
+
+	ext->dev = &pdev->dev;
+	ext->regmap = pmic->regmap;
+	ext->previous_cable = EXTCON_NONE;
+
+	/* Initialize extcon device */
+	ext->edev = devm_extcon_dev_allocate(ext->dev, cht_wc_extcon_cables);
+	if (IS_ERR(ext->edev))
+		return PTR_ERR(ext->edev);
+
+	ret = regmap_update_bits(ext->regmap, CHT_WC_CHGRCTRL0,
+		 CHT_WC_CHGRCTRL0_SWCONTROL | CHT_WC_CHGRCTRL0_CCSM_OFF_MASK,
+		 CHT_WC_CHGRCTRL0_SWCONTROL | CHT_WC_CHGRCTRL0_CCSM_OFF_MASK);
+	if (ret) {
+		dev_err(ext->dev, "Error enabling sw control\n");
+		return ret;
+	}
+
+	/* Register extcon device */
+	ret = devm_extcon_dev_register(ext->dev, ext->edev);
+	if (ret) {
+		dev_err(ext->dev, "Failed to register extcon device\n");
+		return ret;
+	}
+
+	/* Route D+ and D- to PMIC for initial charger detection */
+	cht_wc_extcon_set_phymux(ext, MUX_SEL_PMIC);
+
+	/* Get initial state */
+	cht_wc_extcon_det_event(ext);
+
+	ret = devm_request_threaded_irq(ext->dev, irq, NULL, cht_wc_extcon_isr,
+					IRQF_ONESHOT, pdev->name, ext);
+	if (ret) {
+		dev_err(ext->dev, "Failed to request interrupt\n");
+		return ret;
+	}
+
+	/* Unmask irqs */
+	ret = regmap_write(ext->regmap, CHT_WC_PWRSRC_IRQ_MASK,
+			   (int)~(CHT_WC_PWRSRC_VBUS | CHT_WC_PWRSRC_ID_GND |
+				  CHT_WC_PWRSRC_ID_FLOAT));
+	if (ret) {
+		dev_err(ext->dev, "Error writing irq-mask: %d\n", ret);
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, ext);
+	device_create_file(ext->dev, &dev_attr_usb_id);
+
+	return 0;
+}
+
+static int cht_wc_extcon_remove(struct platform_device *pdev)
+{
+	struct cht_wc_extcon_data *ext = platform_get_drvdata(pdev);
+
+	device_remove_file(ext->dev, &dev_attr_usb_id);
+
+	return 0;
+}
+
+static const struct platform_device_id cht_wc_extcon_table[] = {
+	{ .name = "cht_wcove_pwrsrc" },
+	{},
+};
+MODULE_DEVICE_TABLE(platform, cht_wc_extcon_table);
+
+static struct platform_driver cht_wc_extcon_driver = {
+	.probe = cht_wc_extcon_probe,
+	.remove = cht_wc_extcon_remove,
+	.id_table = cht_wc_extcon_table,
+	.driver = {
+		.name = "cht_wcove_pwrsrc",
+	},
+};
+module_platform_driver(cht_wc_extcon_driver);
+
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_DESCRIPTION("Intel Cherrytrail Whiskey Cove PMIC extcon driver");
+MODULE_LICENSE("GPL v2");
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [PATCH 04/15] power: supply: bq24190_charger: Add no_register_reset pdata flag
  2017-03-17  9:55 [PATCH 00/15] Add Intel Cherry Trail Whiskey Cove PMIC support Hans de Goede
                   ` (2 preceding siblings ...)
  2017-03-17  9:55 ` [PATCH 03/15] extcon: cht-wc: Add Intel Cherry Trail Whiskey Cove PMIC extcon driver Hans de Goede
@ 2017-03-17  9:55 ` Hans de Goede
  2017-03-17 17:20   ` Andy Shevchenko
  2017-03-18  7:10   ` [04/15] " Liam Breck
  2017-03-17  9:55 ` [PATCH 05/15] power: supply: bq24190_charger: Limit charging voltage to 4.3V Hans de Goede
                   ` (10 subsequent siblings)
  14 siblings, 2 replies; 90+ messages in thread
From: Hans de Goede @ 2017-03-17  9:55 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Wolfram Sang, Andy Shevchenko,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: Hans de Goede, linux-acpi, Takashi Iwai, linux-i2c, linux-kernel,
	linux-pm

On some platforms the register have been setup with platform specific
values by the firmware and should not be reset.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/power/supply/bq24190_charger.c | 5 +++++
 include/linux/power/bq24190_charger.h  | 1 +
 2 files changed, 6 insertions(+)

diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
index a4f0849..c92a40e4 100644
--- a/drivers/power/supply/bq24190_charger.c
+++ b/drivers/power/supply/bq24190_charger.c
@@ -151,6 +151,7 @@ struct bq24190_dev_info {
 	struct device			*dev;
 	struct power_supply		*charger;
 	struct power_supply		*battery;
+	struct bq24190_platform_data	*pdata;
 	char				model_name[I2C_NAME_SIZE];
 	kernel_ulong_t			model;
 	unsigned int			gpio_int;
@@ -506,6 +507,9 @@ static int bq24190_register_reset(struct bq24190_dev_info *bdi)
 	int ret, limit = 100;
 	u8 v;
 
+	if (bdi->pdata && bdi->pdata->no_register_reset)
+		return 0;
+
 	/* Reset the registers */
 	ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
 			BQ24190_REG_POC_RESET_MASK,
@@ -1339,6 +1343,7 @@ static int bq24190_probe(struct i2c_client *client,
 	bdi->client = client;
 	bdi->dev = dev;
 	bdi->model = id->driver_data;
+	bdi->pdata = client->dev.platform_data;
 	strncpy(bdi->model_name, id->name, I2C_NAME_SIZE);
 	mutex_init(&bdi->f_reg_lock);
 	bdi->f_reg = 0;
diff --git a/include/linux/power/bq24190_charger.h b/include/linux/power/bq24190_charger.h
index 9f02837..cb49717 100644
--- a/include/linux/power/bq24190_charger.h
+++ b/include/linux/power/bq24190_charger.h
@@ -11,6 +11,7 @@
 
 struct bq24190_platform_data {
 	unsigned int	gpio_int;	/* GPIO pin that's connected to INT# */
+	bool no_register_reset;
 };
 
 #endif
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [PATCH 05/15] power: supply: bq24190_charger: Limit charging voltage to 4.3V
  2017-03-17  9:55 [PATCH 00/15] Add Intel Cherry Trail Whiskey Cove PMIC support Hans de Goede
                   ` (3 preceding siblings ...)
  2017-03-17  9:55 ` [PATCH 04/15] power: supply: bq24190_charger: Add no_register_reset pdata flag Hans de Goede
@ 2017-03-17  9:55 ` Hans de Goede
  2017-03-18  7:10   ` [05/15] " Liam Breck
  2017-03-17  9:55 ` [PATCH 06/15] power: supply: bq24190_charger: Use i2c-core irq-mapping code Hans de Goede
                   ` (9 subsequent siblings)
  14 siblings, 1 reply; 90+ messages in thread
From: Hans de Goede @ 2017-03-17  9:55 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Wolfram Sang, Andy Shevchenko,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: Hans de Goede, linux-acpi, Takashi Iwai, linux-i2c, linux-kernel,
	linux-pm

When the platform data asks us to not reset the charger to its default
values and instead trust the firmware set values check the charging
voltage and clamp it to 4.304V.

Some firmwares set really too high voltages, e.g. the GPD-win I've been
working on uses 4.384V. New LiHV (High Voltage) batteries may be charged
upto 4.35V but that significantly impacts their lifetime, limit charging
to 4.304V for safety and lifetime reasons.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/power/supply/bq24190_charger.c | 27 ++++++++++++++++++++++++---
 1 file changed, 24 insertions(+), 3 deletions(-)

diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
index c92a40e4..7bca8d0 100644
--- a/drivers/power/supply/bq24190_charger.c
+++ b/drivers/power/supply/bq24190_charger.c
@@ -504,11 +504,32 @@ static int bq24190_set_mode_host(struct bq24190_dev_info *bdi)
 
 static int bq24190_register_reset(struct bq24190_dev_info *bdi)
 {
-	int ret, limit = 100;
+	int ret, voltage, limit = 100;
 	u8 v;
 
-	if (bdi->pdata && bdi->pdata->no_register_reset)
-		return 0;
+	if (bdi->pdata && bdi->pdata->no_register_reset) {
+		/*
+		 * We've been asked to keep the firmware settings as is, but
+		 * some firmwares set really too high voltages (e.g. 4.384V).
+		 * New LiHV (High Voltage) batteries may be charged upto 4.35V
+		 * but that significantly impacts their lifetime, limit
+		 * charging to 4.304V for safety and lifetime reasons.
+		 */
+		ret = bq24190_get_field_val(bdi, BQ24190_REG_CVC,
+			BQ24190_REG_CVC_VREG_MASK, BQ24190_REG_CVC_VREG_SHIFT,
+			bq24190_cvc_vreg_values,
+			ARRAY_SIZE(bq24190_cvc_vreg_values), &voltage);
+		if (ret < 0)
+			return ret;
+
+		if (voltage <= 4304000)
+			return 0;
+
+		return bq24190_set_field_val(bdi, BQ24190_REG_CVC,
+			BQ24190_REG_CVC_VREG_MASK, BQ24190_REG_CVC_VREG_SHIFT,
+			bq24190_cvc_vreg_values,
+			ARRAY_SIZE(bq24190_cvc_vreg_values), 4304000);
+	}
 
 	/* Reset the registers */
 	ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [PATCH 06/15] power: supply: bq24190_charger: Use i2c-core irq-mapping code
  2017-03-17  9:55 [PATCH 00/15] Add Intel Cherry Trail Whiskey Cove PMIC support Hans de Goede
                   ` (4 preceding siblings ...)
  2017-03-17  9:55 ` [PATCH 05/15] power: supply: bq24190_charger: Limit charging voltage to 4.3V Hans de Goede
@ 2017-03-17  9:55 ` Hans de Goede
  2017-03-17 17:24   ` Andy Shevchenko
  2017-03-18  7:10   ` [06/15] " Liam Breck
  2017-03-17  9:55 ` [PATCH 07/15] power: supply: bq24190_charger: Add support for bq24192[i] Hans de Goede
                   ` (8 subsequent siblings)
  14 siblings, 2 replies; 90+ messages in thread
From: Hans de Goede @ 2017-03-17  9:55 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Wolfram Sang, Andy Shevchenko,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: Hans de Goede, linux-acpi, Takashi Iwai, linux-i2c, linux-kernel,
	linux-pm

The i2c-core already maps of irqs before calling the driver's probe
function and there are no in tree users of
bq24190_platform_data->gpio_int.

Remove the redundant custom irq-mapping code and just use client->irq.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/power/supply/bq24190_charger.c | 61 ++--------------------------------
 include/linux/power/bq24190_charger.h  |  1 -
 2 files changed, 2 insertions(+), 60 deletions(-)

diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
index 7bca8d0..9c4b171 100644
--- a/drivers/power/supply/bq24190_charger.c
+++ b/drivers/power/supply/bq24190_charger.c
@@ -154,8 +154,6 @@ struct bq24190_dev_info {
 	struct bq24190_platform_data	*pdata;
 	char				model_name[I2C_NAME_SIZE];
 	kernel_ulong_t			model;
-	unsigned int			gpio_int;
-	unsigned int			irq;
 	struct mutex			f_reg_lock;
 	u8				f_reg;
 	u8				ss_reg;
@@ -1296,56 +1294,11 @@ static int bq24190_hw_init(struct bq24190_dev_info *bdi)
 	return ret;
 }
 
-#ifdef CONFIG_OF
-static int bq24190_setup_dt(struct bq24190_dev_info *bdi)
-{
-	bdi->irq = irq_of_parse_and_map(bdi->dev->of_node, 0);
-	if (bdi->irq <= 0)
-		return -1;
-
-	return 0;
-}
-#else
-static int bq24190_setup_dt(struct bq24190_dev_info *bdi)
-{
-	return -1;
-}
-#endif
-
-static int bq24190_setup_pdata(struct bq24190_dev_info *bdi,
-		struct bq24190_platform_data *pdata)
-{
-	int ret;
-
-	if (!gpio_is_valid(pdata->gpio_int))
-		return -1;
-
-	ret = gpio_request(pdata->gpio_int, dev_name(bdi->dev));
-	if (ret < 0)
-		return -1;
-
-	ret = gpio_direction_input(pdata->gpio_int);
-	if (ret < 0)
-		goto out;
-
-	bdi->irq = gpio_to_irq(pdata->gpio_int);
-	if (!bdi->irq)
-		goto out;
-
-	bdi->gpio_int = pdata->gpio_int;
-	return 0;
-
-out:
-	gpio_free(pdata->gpio_int);
-	return -1;
-}
-
 static int bq24190_probe(struct i2c_client *client,
 		const struct i2c_device_id *id)
 {
 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
 	struct device *dev = &client->dev;
-	struct bq24190_platform_data *pdata = client->dev.platform_data;
 	struct power_supply_config charger_cfg = {}, battery_cfg = {};
 	struct bq24190_dev_info *bdi;
 	int ret;
@@ -1372,12 +1325,7 @@ static int bq24190_probe(struct i2c_client *client,
 
 	i2c_set_clientdata(client, bdi);
 
-	if (dev->of_node)
-		ret = bq24190_setup_dt(bdi);
-	else
-		ret = bq24190_setup_pdata(bdi, pdata);
-
-	if (ret) {
+	if (!client->irq) {
 		dev_err(dev, "Can't get irq info\n");
 		return -EINVAL;
 	}
@@ -1417,7 +1365,7 @@ static int bq24190_probe(struct i2c_client *client,
 		goto out3;
 	}
 
-	ret = devm_request_threaded_irq(dev, bdi->irq, NULL,
+	ret = devm_request_threaded_irq(dev, client->irq, NULL,
 			bq24190_irq_handler_thread,
 			IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
 			"bq24190-charger", bdi);
@@ -1439,8 +1387,6 @@ static int bq24190_probe(struct i2c_client *client,
 
 out1:
 	pm_runtime_disable(dev);
-	if (bdi->gpio_int)
-		gpio_free(bdi->gpio_int);
 	return ret;
 }
 
@@ -1457,9 +1403,6 @@ static int bq24190_remove(struct i2c_client *client)
 	power_supply_unregister(bdi->charger);
 	pm_runtime_disable(bdi->dev);
 
-	if (bdi->gpio_int)
-		gpio_free(bdi->gpio_int);
-
 	return 0;
 }
 
diff --git a/include/linux/power/bq24190_charger.h b/include/linux/power/bq24190_charger.h
index cb49717..8d918cb 100644
--- a/include/linux/power/bq24190_charger.h
+++ b/include/linux/power/bq24190_charger.h
@@ -10,7 +10,6 @@
 #define _BQ24190_CHARGER_H_
 
 struct bq24190_platform_data {
-	unsigned int	gpio_int;	/* GPIO pin that's connected to INT# */
 	bool no_register_reset;
 };
 
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [PATCH 07/15] power: supply: bq24190_charger: Add support for bq24192[i]
  2017-03-17  9:55 [PATCH 00/15] Add Intel Cherry Trail Whiskey Cove PMIC support Hans de Goede
                   ` (5 preceding siblings ...)
  2017-03-17  9:55 ` [PATCH 06/15] power: supply: bq24190_charger: Use i2c-core irq-mapping code Hans de Goede
@ 2017-03-17  9:55 ` Hans de Goede
  2017-03-18  7:10   ` [07/15] " Liam Breck
  2017-03-17  9:55 ` [PATCH 08/15] power: supply: bq24190_charger: Add support for external fuel gauge Hans de Goede
                   ` (7 subsequent siblings)
  14 siblings, 1 reply; 90+ messages in thread
From: Hans de Goede @ 2017-03-17  9:55 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Wolfram Sang, Andy Shevchenko,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: Hans de Goede, linux-acpi, Takashi Iwai, linux-i2c, linux-kernel,
	linux-pm

The bq24192 and bq24192i are mostly identical to the bq24190, TI even
published a single datasheet for all 3 of them. The difference
between the bq24190 and bq24192[i] is the way charger-type detection
is done, the bq24190 is to be directly connected to the USB a/b lines,
where as the the bq24192[i] has a gpio which should be driven high/low
externally depending on the type of charger connected, from a register
level access pov there is no difference.

The differences between the bq24192 and bq24192i are:
1) Lower default charge rate on the bq24192i
2) Pre-charge-current can be max 640 mA on the bq24192i

Since we do not provide an API for setting the pre-charge-current,
these differences can be ignored and we can simply use the existing
code as-is with the bq24192 and bq24192i.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/power/supply/bq24190_charger.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
index 9c4b171..9014dee 100644
--- a/drivers/power/supply/bq24190_charger.c
+++ b/drivers/power/supply/bq24190_charger.c
@@ -1275,7 +1275,14 @@ static int bq24190_hw_init(struct bq24190_dev_info *bdi)
 	if (ret < 0)
 		goto out;
 
-	if (v != bdi->model) {
+	switch (v) {
+	case BQ24190_REG_VPRS_PN_24190:
+	case BQ24190_REG_VPRS_PN_24192:
+	case BQ24190_REG_VPRS_PN_24192I:
+		bdi->model = v;
+		break;
+	default:
+		dev_err(bdi->dev, "Error unknown model: 0x%02x\n", v);
 		ret = -ENODEV;
 		goto out;
 	}
@@ -1316,7 +1323,6 @@ static int bq24190_probe(struct i2c_client *client,
 
 	bdi->client = client;
 	bdi->dev = dev;
-	bdi->model = id->driver_data;
 	bdi->pdata = client->dev.platform_data;
 	strncpy(bdi->model_name, id->name, I2C_NAME_SIZE);
 	mutex_init(&bdi->f_reg_lock);
@@ -1450,6 +1456,8 @@ static SIMPLE_DEV_PM_OPS(bq24190_pm_ops, bq24190_pm_suspend, bq24190_pm_resume);
  */
 static const struct i2c_device_id bq24190_i2c_ids[] = {
 	{ "bq24190", BQ24190_REG_VPRS_PN_24190 },
+	{ "bq24192", BQ24190_REG_VPRS_PN_24192 },
+	{ "bq24192i", BQ24190_REG_VPRS_PN_24192I },
 	{ },
 };
 MODULE_DEVICE_TABLE(i2c, bq24190_i2c_ids);
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [PATCH 08/15] power: supply: bq24190_charger: Add support for external fuel gauge
  2017-03-17  9:55 [PATCH 00/15] Add Intel Cherry Trail Whiskey Cove PMIC support Hans de Goede
                   ` (6 preceding siblings ...)
  2017-03-17  9:55 ` [PATCH 07/15] power: supply: bq24190_charger: Add support for bq24192[i] Hans de Goede
@ 2017-03-17  9:55 ` Hans de Goede
  2017-03-18  7:10   ` [08/15] " Liam Breck
  2017-03-17  9:55 ` [PATCH 09/15] power: supply: bq24190_charger: Add voltage_max_design prop to battery Hans de Goede
                   ` (6 subsequent siblings)
  14 siblings, 1 reply; 90+ messages in thread
From: Hans de Goede @ 2017-03-17  9:55 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Wolfram Sang, Andy Shevchenko,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: Hans de Goede, linux-acpi, Takashi Iwai, linux-i2c, linux-kernel,
	linux-pm

Some platforms with a bq24190_charger have an external fuel gauge which
makes it possible to reliably report battery (dis)charge state, at
support for this by adding an optional get_ext_bat_property callback
to the platform_data and using this if the platform provides it.

By convention the callback will return -ENXIO when it is not ready yet,
or the driver providing it has been unbound from its device. Since it
returns the same error when unbound it cannot return -EPROBE_DEFER
as that is not a valid errno.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/power/supply/bq24190_charger.c | 41 +++++++++++++++++++++++++++++++---
 include/linux/power/bq24190_charger.h  |  4 ++++
 2 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
index 9014dee..9fe69a5 100644
--- a/drivers/power/supply/bq24190_charger.c
+++ b/drivers/power/supply/bq24190_charger.c
@@ -1111,7 +1111,10 @@ static int bq24190_battery_get_property(struct power_supply *psy,
 		ret = 0;
 		break;
 	default:
-		ret = -ENODATA;
+		if (bdi->pdata && bdi->pdata->get_ext_bat_property)
+			ret = bdi->pdata->get_ext_bat_property(psp, val);
+		else
+			ret = -ENODATA;
 	}
 
 	pm_runtime_put_sync(bdi->dev);
@@ -1168,12 +1171,31 @@ static enum power_supply_property bq24190_battery_properties[] = {
 	POWER_SUPPLY_PROP_TECHNOLOGY,
 	POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
 	POWER_SUPPLY_PROP_SCOPE,
+	/* Begin of extended battery properties */
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_VOLTAGE_AVG,
+	POWER_SUPPLY_PROP_VOLTAGE_OCV,
+	POWER_SUPPLY_PROP_CURRENT_NOW,
+	POWER_SUPPLY_PROP_CURRENT_AVG,
+	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+	POWER_SUPPLY_PROP_CHARGE_FULL,
+	POWER_SUPPLY_PROP_CHARGE_NOW,
 };
 
 static const struct power_supply_desc bq24190_battery_desc = {
 	.name			= "bq24190-battery",
 	.type			= POWER_SUPPLY_TYPE_BATTERY,
 	.properties		= bq24190_battery_properties,
+	.num_properties		= 6,
+	.get_property		= bq24190_battery_get_property,
+	.set_property		= bq24190_battery_set_property,
+	.property_is_writeable	= bq24190_battery_property_is_writeable,
+};
+
+static const struct power_supply_desc bq24190_ext_battery_desc = {
+	.name			= "bq24190-battery",
+	.type			= POWER_SUPPLY_TYPE_BATTERY,
+	.properties		= bq24190_battery_properties,
 	.num_properties		= ARRAY_SIZE(bq24190_battery_properties),
 	.get_property		= bq24190_battery_get_property,
 	.set_property		= bq24190_battery_set_property,
@@ -1336,6 +1358,15 @@ static int bq24190_probe(struct i2c_client *client,
 		return -EINVAL;
 	}
 
+	if (bdi->pdata && bdi->pdata->get_ext_bat_property) {
+		union power_supply_propval val;
+
+		/* Check external fuel gauge is ready */
+		ret = bdi->pdata->get_ext_bat_property(0, &val);
+		if (ret == -ENXIO)
+			return -EPROBE_DEFER;
+	}
+
 	pm_runtime_enable(dev);
 	pm_runtime_resume(dev);
 
@@ -1357,8 +1388,12 @@ static int bq24190_probe(struct i2c_client *client,
 	}
 
 	battery_cfg.drv_data = bdi;
-	bdi->battery = power_supply_register(dev, &bq24190_battery_desc,
-						&battery_cfg);
+	if (bdi->pdata && bdi->pdata->get_ext_bat_property)
+		bdi->battery = power_supply_register(dev,
+				    &bq24190_ext_battery_desc, &battery_cfg);
+	else
+		bdi->battery = power_supply_register(dev,
+				    &bq24190_battery_desc, &battery_cfg);
 	if (IS_ERR(bdi->battery)) {
 		dev_err(dev, "Can't register battery\n");
 		ret = PTR_ERR(bdi->battery);
diff --git a/include/linux/power/bq24190_charger.h b/include/linux/power/bq24190_charger.h
index 8d918cb..02d248b 100644
--- a/include/linux/power/bq24190_charger.h
+++ b/include/linux/power/bq24190_charger.h
@@ -9,8 +9,12 @@
 #ifndef _BQ24190_CHARGER_H_
 #define _BQ24190_CHARGER_H_
 
+#include <linux/power_supply.h>
+
 struct bq24190_platform_data {
 	bool no_register_reset;
+	int (*get_ext_bat_property)(enum power_supply_property prop,
+				    union power_supply_propval *val);
 };
 
 #endif
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [PATCH 09/15] power: supply: bq24190_charger: Add voltage_max_design prop to battery
  2017-03-17  9:55 [PATCH 00/15] Add Intel Cherry Trail Whiskey Cove PMIC support Hans de Goede
                   ` (7 preceding siblings ...)
  2017-03-17  9:55 ` [PATCH 08/15] power: supply: bq24190_charger: Add support for external fuel gauge Hans de Goede
@ 2017-03-17  9:55 ` Hans de Goede
  2017-03-18  7:10   ` [09/15] " Liam Breck
  2017-03-20  5:12   ` [PATCH 09/15] " Sebastian Reichel
  2017-03-17  9:55 ` [PATCH 10/15] power: supply: bq24190_charger: Use extcon to determine ilimit, 5v boost Hans de Goede
                   ` (5 subsequent siblings)
  14 siblings, 2 replies; 90+ messages in thread
From: Hans de Goede @ 2017-03-17  9:55 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Wolfram Sang, Andy Shevchenko,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: Hans de Goede, linux-acpi, Takashi Iwai, linux-i2c, linux-kernel,
	linux-pm

When combined with an external fuel-gauge, upower needs voltage_max_design
as it internally does all its calculations in Watts and converts the
charge_foo properties from A to Watts by using voltage_max_design.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/power/supply/bq24190_charger.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
index 9fe69a5..82cb33d 100644
--- a/drivers/power/supply/bq24190_charger.c
+++ b/drivers/power/supply/bq24190_charger.c
@@ -1103,6 +1103,13 @@ static int bq24190_battery_get_property(struct power_supply *psy,
 		val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
 		ret = 0;
 		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+		/*
+		 * Report charger configured voltage as max design voltage,
+		 * not entirely correct, but userspace needs something here.
+		 */
+		ret = bq24190_charger_get_voltage(bdi, val);
+		break;
 	case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
 		ret = bq24190_battery_get_temp_alert_max(bdi, val);
 		break;
@@ -1169,6 +1176,7 @@ static enum power_supply_property bq24190_battery_properties[] = {
 	POWER_SUPPLY_PROP_HEALTH,
 	POWER_SUPPLY_PROP_ONLINE,
 	POWER_SUPPLY_PROP_TECHNOLOGY,
+	POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
 	POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
 	POWER_SUPPLY_PROP_SCOPE,
 	/* Begin of extended battery properties */
@@ -1186,7 +1194,7 @@ static const struct power_supply_desc bq24190_battery_desc = {
 	.name			= "bq24190-battery",
 	.type			= POWER_SUPPLY_TYPE_BATTERY,
 	.properties		= bq24190_battery_properties,
-	.num_properties		= 6,
+	.num_properties		= 7,
 	.get_property		= bq24190_battery_get_property,
 	.set_property		= bq24190_battery_set_property,
 	.property_is_writeable	= bq24190_battery_property_is_writeable,
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [PATCH 10/15] power: supply: bq24190_charger: Use extcon to determine ilimit, 5v boost
  2017-03-17  9:55 [PATCH 00/15] Add Intel Cherry Trail Whiskey Cove PMIC support Hans de Goede
                   ` (8 preceding siblings ...)
  2017-03-17  9:55 ` [PATCH 09/15] power: supply: bq24190_charger: Add voltage_max_design prop to battery Hans de Goede
@ 2017-03-17  9:55 ` Hans de Goede
  2017-03-17 17:33   ` Andy Shevchenko
                     ` (2 more replies)
  2017-03-17  9:55 ` [PATCH 11/15] i2c: core: Allow getting ACPI info by index Hans de Goede
                   ` (4 subsequent siblings)
  14 siblings, 3 replies; 90+ messages in thread
From: Hans de Goede @ 2017-03-17  9:55 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Wolfram Sang, Andy Shevchenko,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: Hans de Goede, linux-acpi, Takashi Iwai, linux-i2c, linux-kernel,
	linux-pm

Add support for monitoring an extcon device with SDP/CDP/DCP and HOST
cables and adjust ilimit and enable/disable the 5v boost converter
accordingly. This is necessary on systems where the PSEL pin is hardwired
high and ILIM needs to be set by software based on the detected charger
type.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/power/supply/Kconfig           |  1 +
 drivers/power/supply/bq24190_charger.c | 85 ++++++++++++++++++++++++++++++++++
 include/linux/power/bq24190_charger.h  |  1 +
 3 files changed, 87 insertions(+)

diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index f8b6e64..fd93110 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -442,6 +442,7 @@ config CHARGER_BQ2415X
 config CHARGER_BQ24190
 	tristate "TI BQ24190 battery charger driver"
 	depends on I2C
+	depends on EXTCON
 	depends on GPIOLIB || COMPILE_TEST
 	help
 	  Say Y to enable support for the TI BQ24190 battery charger.
diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
index 82cb33d..03990e2 100644
--- a/drivers/power/supply/bq24190_charger.c
+++ b/drivers/power/supply/bq24190_charger.c
@@ -11,10 +11,12 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <linux/extcon.h>
 #include <linux/of_irq.h>
 #include <linux/of_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/power_supply.h>
+#include <linux/workqueue.h>
 #include <linux/gpio.h>
 #include <linux/i2c.h>
 
@@ -39,6 +41,8 @@
 #define BQ24190_REG_POC_WDT_RESET_SHIFT		6
 #define BQ24190_REG_POC_CHG_CONFIG_MASK		(BIT(5) | BIT(4))
 #define BQ24190_REG_POC_CHG_CONFIG_SHIFT	4
+#define BQ24190_REG_POC_CHG_CONFIG_CHARGE	1
+#define BQ24190_REG_POC_CHG_CONFIG_OTG		2
 #define BQ24190_REG_POC_SYS_MIN_MASK		(BIT(3) | BIT(2) | BIT(1))
 #define BQ24190_REG_POC_SYS_MIN_SHIFT		1
 #define BQ24190_REG_POC_BOOST_LIM_MASK		BIT(0)
@@ -152,6 +156,9 @@ struct bq24190_dev_info {
 	struct power_supply		*charger;
 	struct power_supply		*battery;
 	struct bq24190_platform_data	*pdata;
+	struct extcon_dev		*extcon;
+	struct notifier_block		extcon_nb;
+	struct work_struct		extcon_work;
 	char				model_name[I2C_NAME_SIZE];
 	kernel_ulong_t			model;
 	struct mutex			f_reg_lock;
@@ -167,6 +174,11 @@ struct bq24190_dev_info {
  * number at that index in the array is the real-world value that it
  * represents.
  */
+
+/* REG00[2:0] (IINLIM) in uAh */
+static const int bq24190_iinlim_values[] = {
+	100000, 150000, 500000, 900000, 1200000, 1500000, 2000000, 3000000 };
+
 /* REG02[7:2] (ICHG) in uAh */
 static const int bq24190_ccc_ichg_values[] = {
 	 512000,  576000,  640000,  704000,  768000,  832000,  896000,  960000,
@@ -1290,6 +1302,61 @@ static irqreturn_t bq24190_irq_handler_thread(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
+static void bq24190_extcon_work(struct work_struct *work)
+{
+	struct bq24190_dev_info *bdi =
+		container_of(work, struct bq24190_dev_info, extcon_work);
+	int ret, iinlim = 0;
+
+	if (extcon_get_state(bdi->extcon, EXTCON_CHG_USB_SDP) == 1)
+		iinlim = 500000;
+	else if (extcon_get_state(bdi->extcon, EXTCON_CHG_USB_CDP) == 1 ||
+		 extcon_get_state(bdi->extcon, EXTCON_CHG_USB_ACA) == 1)
+		iinlim = 1500000;
+	else if (extcon_get_state(bdi->extcon, EXTCON_CHG_USB_DCP) == 1)
+		iinlim = 2000000;
+
+	if (iinlim) {
+		ret = bq24190_set_field_val(bdi, BQ24190_REG_ISC,
+				BQ24190_REG_ISC_IINLIM_MASK,
+				BQ24190_REG_ISC_IINLIM_SHIFT,
+				bq24190_iinlim_values,
+				ARRAY_SIZE(bq24190_iinlim_values),
+				iinlim);
+		if (ret)
+			dev_err(bdi->dev, "Can't set IINLIM: %d\n", ret);
+	}
+
+	/*
+	 * If no charger has been detected and host mode is requested, activate
+	 * the 5V boost converter, otherwise deactivate it.
+	 */
+	if (!iinlim && extcon_get_state(bdi->extcon, EXTCON_USB_HOST) == 1) {
+		ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
+					 BQ24190_REG_POC_CHG_CONFIG_MASK,
+					 BQ24190_REG_POC_CHG_CONFIG_SHIFT,
+					 BQ24190_REG_POC_CHG_CONFIG_OTG);
+	} else {
+		ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
+					 BQ24190_REG_POC_CHG_CONFIG_MASK,
+					 BQ24190_REG_POC_CHG_CONFIG_SHIFT,
+					 BQ24190_REG_POC_CHG_CONFIG_CHARGE);
+	}
+	if (ret)
+		dev_err(bdi->dev, "Can't set CHG_CONFIG: %d\n", ret);
+}
+
+static int bq24190_extcon_event(struct notifier_block *nb, unsigned long event,
+				void *param)
+{
+	struct bq24190_dev_info *bdi =
+		container_of(nb, struct bq24190_dev_info, extcon_nb);
+
+	schedule_work(&bdi->extcon_work);
+
+	return NOTIFY_OK;
+}
+
 static int bq24190_hw_init(struct bq24190_dev_info *bdi)
 {
 	u8 v;
@@ -1375,6 +1442,12 @@ static int bq24190_probe(struct i2c_client *client,
 			return -EPROBE_DEFER;
 	}
 
+	if (bdi->pdata && bdi->pdata->extcon_name) {
+		bdi->extcon = extcon_get_extcon_dev(bdi->pdata->extcon_name);
+		if (!bdi->extcon)
+			return -EPROBE_DEFER;
+	}
+
 	pm_runtime_enable(dev);
 	pm_runtime_resume(dev);
 
@@ -1423,6 +1496,18 @@ static int bq24190_probe(struct i2c_client *client,
 		goto out4;
 	}
 
+	if (bdi->extcon) {
+		INIT_WORK(&bdi->extcon_work, bq24190_extcon_work);
+		bdi->extcon_nb.notifier_call = bq24190_extcon_event;
+		ret = devm_extcon_register_notifier(dev, bdi->extcon, -1,
+						    &bdi->extcon_nb);
+		if (ret)
+			goto out4;
+
+		/* Sync initial cable state */
+		schedule_work(&bdi->extcon_work);
+	}
+
 	return 0;
 
 out4:
diff --git a/include/linux/power/bq24190_charger.h b/include/linux/power/bq24190_charger.h
index 02d248b..909c5b9 100644
--- a/include/linux/power/bq24190_charger.h
+++ b/include/linux/power/bq24190_charger.h
@@ -13,6 +13,7 @@
 
 struct bq24190_platform_data {
 	bool no_register_reset;
+	const char *extcon_name;
 	int (*get_ext_bat_property)(enum power_supply_property prop,
 				    union power_supply_propval *val);
 };
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [PATCH 11/15] i2c: core: Allow getting ACPI info by index
  2017-03-17  9:55 [PATCH 00/15] Add Intel Cherry Trail Whiskey Cove PMIC support Hans de Goede
                   ` (9 preceding siblings ...)
  2017-03-17  9:55 ` [PATCH 10/15] power: supply: bq24190_charger: Use extcon to determine ilimit, 5v boost Hans de Goede
@ 2017-03-17  9:55 ` Hans de Goede
  2017-03-17 17:35   ` Andy Shevchenko
  2017-03-17  9:55 ` [PATCH 12/15] i2c: core: Add new i2c_acpi_new_device helper function Hans de Goede
                   ` (3 subsequent siblings)
  14 siblings, 1 reply; 90+ messages in thread
From: Hans de Goede @ 2017-03-17  9:55 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Wolfram Sang, Andy Shevchenko,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: Hans de Goede, linux-acpi, Takashi Iwai, linux-i2c, linux-kernel,
	linux-pm

Modify struct i2c_acpi_lookup and i2c_acpi_fill_info() to allow
using them to get the info from a certain index in the ACPI-resource
list rather then taking the first I2cSerialBus resource.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/i2c/i2c-core.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index d2402bb..32b58fb 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -112,6 +112,8 @@ struct i2c_acpi_lookup {
 	acpi_handle adapter_handle;
 	acpi_handle device_handle;
 	acpi_handle search_handle;
+	int n;
+	int index;
 	u32 speed;
 	u32 min_speed;
 };
@@ -123,6 +125,9 @@ static int i2c_acpi_fill_info(struct acpi_resource *ares, void *data)
 	struct acpi_resource_i2c_serialbus *sb;
 	acpi_status status;
 
+	if (lookup->index != -1 && lookup->n++ != lookup->index)
+		return 1;
+
 	if (info->addr || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS)
 		return 1;
 
@@ -182,6 +187,7 @@ static int i2c_acpi_get_info(struct acpi_device *adev,
 
 	memset(&lookup, 0, sizeof(lookup));
 	lookup.info = info;
+	lookup.index = -1;
 
 	ret = i2c_acpi_do_lookup(adev, &lookup);
 	if (ret)
@@ -328,6 +334,7 @@ u32 i2c_acpi_find_bus_speed(struct device *dev)
 	lookup.search_handle = ACPI_HANDLE(dev);
 	lookup.min_speed = UINT_MAX;
 	lookup.info = &dummy;
+	lookup.index = -1;
 
 	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
 				     I2C_ACPI_MAX_SCAN_DEPTH,
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [PATCH 12/15] i2c: core: Add new i2c_acpi_new_device helper function
  2017-03-17  9:55 [PATCH 00/15] Add Intel Cherry Trail Whiskey Cove PMIC support Hans de Goede
                   ` (10 preceding siblings ...)
  2017-03-17  9:55 ` [PATCH 11/15] i2c: core: Allow getting ACPI info by index Hans de Goede
@ 2017-03-17  9:55 ` Hans de Goede
  2017-03-17 17:37   ` Andy Shevchenko
  2017-03-17  9:55 ` [PATCH 13/15] i2c: core: Allow drivers to specify index for irq to get from of / ACPI Hans de Goede
                   ` (2 subsequent siblings)
  14 siblings, 1 reply; 90+ messages in thread
From: Hans de Goede @ 2017-03-17  9:55 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Wolfram Sang, Andy Shevchenko,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: Hans de Goede, linux-acpi, Takashi Iwai, linux-i2c, linux-kernel,
	linux-pm

By default the i2c subsys creates an i2c-client for the first I2cSerialBus
resource of an acpi_device, but some acpi_devices have multiple
I2cSerialBus resources and the driver may need access to the others.

This commit adds a new i2c_acpi_new_device function which can be used by
drivers to create an i2c-client for any (other) I2cSerialBus resource of
an acpi_device.

Note that the other resources may even be on a different i2c bus, so just
retrieving the client address is not enough.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/i2c/i2c-core.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/i2c.h    |  5 +++++
 2 files changed, 53 insertions(+)

diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 32b58fb..fd45207 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -421,6 +421,54 @@ static int i2c_acpi_notify(struct notifier_block *nb, unsigned long value,
 static struct notifier_block i2c_acpi_notifier = {
 	.notifier_call = i2c_acpi_notify,
 };
+
+/**
+ * i2c_acpi_new_device - Create i2c client for the Nth acpi resource of dev
+ * @dev:     Device owning the acpi resources to get the client from
+ * @index:   Index of acpi resource to get
+ *
+ * By default the i2c subsys creates an i2c-client for the first I2cSerialBus
+ * resource of an acpi_device, but some acpi_devices have multiple
+ * I2cSerialBus resources and the driver may need access to the others.
+ * This function can be used by drivers to create an i2c-client for any
+ * resource of an acpi_device.
+ *
+ * Returns a pointer to the new i2c-client, or NULL if the resource or
+ * adapter were not found.
+ */
+struct i2c_client *i2c_acpi_new_device(struct device *dev, int index)
+{
+	struct i2c_acpi_lookup lookup;
+	struct i2c_board_info info;
+	struct i2c_adapter *adapter;
+	struct acpi_device *adev;
+	LIST_HEAD(resource_list);
+	int ret;
+
+	adev = ACPI_COMPANION(dev);
+	if (!adev)
+		return NULL;
+
+	memset(&info, 0, sizeof(info));
+	memset(&lookup, 0, sizeof(lookup));
+	lookup.info = &info;
+	lookup.device_handle = acpi_device_handle(adev);
+	lookup.index = index;
+
+	ret = acpi_dev_get_resources(adev, &resource_list,
+				     i2c_acpi_fill_info, &lookup);
+	acpi_dev_free_resource_list(&resource_list);
+
+	if (ret < 0 || !info.addr)
+		return NULL;
+
+	adapter = i2c_acpi_find_adapter_by_handle(lookup.adapter_handle);
+	if (!adapter)
+		return NULL;
+
+	return i2c_new_device(adapter, &info);
+}
+EXPORT_SYMBOL_GPL(i2c_acpi_new_device);
 #else /* CONFIG_ACPI */
 static inline void i2c_acpi_register_devices(struct i2c_adapter *adap) { }
 extern struct notifier_block i2c_acpi_notifier;
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 6b18352..369ebfa 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -824,11 +824,16 @@ static inline const struct of_device_id
 
 #if IS_ENABLED(CONFIG_ACPI)
 u32 i2c_acpi_find_bus_speed(struct device *dev);
+struct i2c_client *i2c_acpi_new_device(struct device *dev, int index);
 #else
 static inline u32 i2c_acpi_find_bus_speed(struct device *dev)
 {
 	return 0;
 }
+static inline struct i2c_client *i2c_acpi_new_device(struct device *d, int i)
+{
+	return NULL;
+}
 #endif /* CONFIG_ACPI */
 
 #endif /* _LINUX_I2C_H */
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [PATCH 13/15] i2c: core: Allow drivers to specify index for irq to get from of / ACPI
  2017-03-17  9:55 [PATCH 00/15] Add Intel Cherry Trail Whiskey Cove PMIC support Hans de Goede
                   ` (11 preceding siblings ...)
  2017-03-17  9:55 ` [PATCH 12/15] i2c: core: Add new i2c_acpi_new_device helper function Hans de Goede
@ 2017-03-17  9:55 ` Hans de Goede
  2017-03-17 17:41   ` Andy Shevchenko
  2017-03-20  8:55     ` kbuild test robot
  2017-03-17  9:55 ` [PATCH 14/15] power: supply: Add driver for Cherry Trail Whiskey Cove PMIC Fuel Gauge Hans de Goede
  2017-03-17  9:55 ` [PATCH 15/15] i2c-cht-wc: Add Intel Cherry Trail Whiskey Cove SMBUS controller driver Hans de Goede
  14 siblings, 2 replies; 90+ messages in thread
From: Hans de Goede @ 2017-03-17  9:55 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Wolfram Sang, Andy Shevchenko,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: Hans de Goede, linux-acpi, Takashi Iwai, linux-i2c, linux-kernel,
	linux-pm

Some of or ACPI declared / enumerated devices may have multiple irq
resources declared and the driver may want to use a different irq then
the one with index 0.

This commit adds a new irq_index field to struct i2c_driver and makes
the i2c-core pass this to of_irq_get / acpi_dev_gpio_irq_get.

This is esp. useful for ACPI declared devices where the irq with
index 0 may be entirely useless and cause i2c_device_probe to fail with
-EPROBE_DEFER.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
Changes in v2:
-Actually also use the irq_index for of interrupts
---
 drivers/i2c/i2c-core.c | 8 ++++++--
 include/linux/i2c.h    | 3 +++
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index fd45207..2457995 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -984,6 +984,8 @@ static int i2c_device_probe(struct device *dev)
 	if (!client)
 		return 0;
 
+	driver = to_i2c_driver(dev->driver);
+
 	if (!client->irq) {
 		int irq = -ENOENT;
 
@@ -993,9 +995,11 @@ static int i2c_device_probe(struct device *dev)
 		} else if (dev->of_node) {
 			irq = of_irq_get_byname(dev->of_node, "irq");
 			if (irq == -EINVAL || irq == -ENODATA)
-				irq = of_irq_get(dev->of_node, 0);
+				irq = of_irq_get(dev->of_node,
+						 driver->irq_index);
 		} else if (ACPI_COMPANION(dev)) {
-			irq = acpi_dev_gpio_irq_get(ACPI_COMPANION(dev), 0);
+			irq = acpi_dev_gpio_irq_get(ACPI_COMPANION(dev),
+						    driver->irq_index);
 		}
 		if (irq == -EPROBE_DEFER)
 			return irq;
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 369ebfa..a5ffe29 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -212,6 +212,9 @@ struct i2c_driver {
 	int (*detect)(struct i2c_client *, struct i2c_board_info *);
 	const unsigned short *address_list;
 	struct list_head clients;
+
+	/* IRQ index for retreiving irq from ACPI resources */
+	int irq_index;
 };
 #define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)
 
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [PATCH 14/15] power: supply: Add driver for Cherry Trail Whiskey Cove PMIC Fuel Gauge
  2017-03-17  9:55 [PATCH 00/15] Add Intel Cherry Trail Whiskey Cove PMIC support Hans de Goede
                   ` (12 preceding siblings ...)
  2017-03-17  9:55 ` [PATCH 13/15] i2c: core: Allow drivers to specify index for irq to get from of / ACPI Hans de Goede
@ 2017-03-17  9:55 ` Hans de Goede
  2017-03-17 17:58   ` Andy Shevchenko
  2017-03-20  5:07   ` Sebastian Reichel
  2017-03-17  9:55 ` [PATCH 15/15] i2c-cht-wc: Add Intel Cherry Trail Whiskey Cove SMBUS controller driver Hans de Goede
  14 siblings, 2 replies; 90+ messages in thread
From: Hans de Goede @ 2017-03-17  9:55 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Wolfram Sang, Andy Shevchenko,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: Hans de Goede, linux-acpi, Takashi Iwai, linux-i2c, linux-kernel,
	linux-pm

Add a driver for the Cherry Trail Whiskey Cove PMIC Fuel Gauge, note
the Cherry Trail Whiskey Cove PMIC Fuel Gauge block is purely a fuel gauge
and not a full battery controller. As such it offers a platform_data
callback for extra power_supply properties for the actual external-charger
ic driver and does not register a power_supply itself.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/power/supply/Kconfig             |   9 ++
 drivers/power/supply/Makefile            |   1 +
 drivers/power/supply/cht_wc_fuel_gauge.c | 209 +++++++++++++++++++++++++++++++
 include/linux/power/cht_wc_fuel_gauge.h  |  21 ++++
 4 files changed, 240 insertions(+)
 create mode 100644 drivers/power/supply/cht_wc_fuel_gauge.c
 create mode 100644 include/linux/power/cht_wc_fuel_gauge.h

diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index fd93110..34ebfca 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -538,4 +538,13 @@ config AXP20X_POWER
 	  This driver provides support for the power supply features of
 	  AXP20x PMIC.
 
+config CHT_WC_FUEL_GAUGE
+	tristate "Intel Cherry Trail Whiskey Cove PMIC Fuel Gauge"
+	depends on INTEL_SOC_PMIC_CHTWC
+	help
+	  This adds support for the battery fuel gauge found in the Intel
+	  Cherry Trail Whiskey Cove PMIC. This driver allows monitoring
+	  of the charge level of the battery on Intel Cherry Trail systems
+	  with a Whiskey Cove PMIC.
+
 endif # POWER_SUPPLY
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index 3789a2c..702e28a 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -74,3 +74,4 @@ obj-$(CONFIG_CHARGER_TPS65090)	+= tps65090-charger.o
 obj-$(CONFIG_CHARGER_TPS65217)	+= tps65217_charger.o
 obj-$(CONFIG_AXP288_FUEL_GAUGE) += axp288_fuel_gauge.o
 obj-$(CONFIG_AXP288_CHARGER)	+= axp288_charger.o
+obj-$(CONFIG_CHT_WC_FUEL_GAUGE)	+= cht_wc_fuel_gauge.o
diff --git a/drivers/power/supply/cht_wc_fuel_gauge.c b/drivers/power/supply/cht_wc_fuel_gauge.c
new file mode 100644
index 0000000..56f6e5a
--- /dev/null
+++ b/drivers/power/supply/cht_wc_fuel_gauge.c
@@ -0,0 +1,209 @@
+/*
+ * Intel CHT Whiskey Cove Fuel Gauge driver
+ * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Cherrytrail Whiskey Cove devices have 2 functional blocks which interact
+ * with the battery.
+ *
+ * 1) The fuel-gauge which is build into the Whiskey Cove PMIC, but has its
+ * own i2c bus and i2c client addresses separately from the rest of the PMIC.
+ * That block is what this driver is for.
+ *
+ * 2) An external charger IC, which is connected to the SMBUS controller
+ * which is part of the rest of the Whiskey Cove PMIC, mfd/intel_cht_wc.c
+ * registers a platform device for the SMBUS controller and
+ * i2c/busses/i2c-cht-wc.c contains the i2c-adapter driver for this.
+ *
+ * However we want to present this as a single power_supply device to
+ * userspace. So this driver offers a callback to get the fuel-gauge
+ * power_supply properties, which gets passed to the external charger
+ * driver via i2c_board_info when i2c-cht-wc.c calls i2c_new_device().
+ */
+
+#include <linux/acpi.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/intel_soc_pmic.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/power/cht_wc_fuel_gauge.h>
+#include <linux/slab.h>
+
+#define REG_CHARGE_NOW		0x05
+#define REG_VOLTAGE_NOW		0x09
+#define REG_CURRENT_NOW		0x0a
+#define REG_CURRENT_AVG		0x0b
+#define REG_CHARGE_FULL		0x10
+#define REG_CHARGE_DESIGN	0x18
+#define REG_VOLTAGE_AVG		0x19
+#define REG_VOLTAGE_OCV		0x1b /* Only updated during charging */
+
+#define CHT_WC_FG_PTYPE		4
+
+struct cht_wc_fg_data {
+	struct device *dev;
+	struct i2c_client *client;
+};
+
+static DEFINE_MUTEX(cht_wc_fg_mutex);
+static struct cht_wc_fg_data *cht_wc_fg;
+
+static int cht_wc_fg_read(struct cht_wc_fg_data *fg, u8 reg,
+			  union power_supply_propval *val, int scale,
+			  int sign_extend)
+{
+	int ret;
+
+	ret = i2c_smbus_read_word_data(fg->client, reg);
+	if (ret < 0)
+		return ret;
+
+	if (sign_extend)
+		ret = sign_extend32(ret, 15);
+
+	val->intval = ret * scale;
+
+	return 0;
+}
+
+int cht_wc_fg_get_property(enum power_supply_property prop,
+			   union power_supply_propval *val)
+{
+	int ret = 0;
+
+	mutex_lock(&cht_wc_fg_mutex);
+
+	if (!cht_wc_fg) {
+		ret = -ENXIO;
+		goto out_unlock;
+	}
+
+	switch (prop) {
+	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+		ret = cht_wc_fg_read(cht_wc_fg, REG_VOLTAGE_NOW, val, 75, 0);
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_AVG:
+		ret = cht_wc_fg_read(cht_wc_fg, REG_VOLTAGE_AVG, val, 75, 0);
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_OCV:
+		ret = cht_wc_fg_read(cht_wc_fg, REG_VOLTAGE_OCV, val, 75, 0);
+		break;
+	case POWER_SUPPLY_PROP_CURRENT_NOW:
+		ret = cht_wc_fg_read(cht_wc_fg, REG_CURRENT_NOW, val, 150, 1);
+		break;
+	case POWER_SUPPLY_PROP_CURRENT_AVG:
+		ret = cht_wc_fg_read(cht_wc_fg, REG_CURRENT_AVG, val, 150, 1);
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+		ret = cht_wc_fg_read(cht_wc_fg, REG_CHARGE_DESIGN, val, 500, 0);
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_FULL:
+		ret = cht_wc_fg_read(cht_wc_fg, REG_CHARGE_FULL, val, 500, 0);
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_NOW:
+		ret = cht_wc_fg_read(cht_wc_fg, REG_CHARGE_NOW, val, 500, 0);
+		break;
+	default:
+		ret = -ENODATA;
+	}
+out_unlock:
+	mutex_unlock(&cht_wc_fg_mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(cht_wc_fg_get_property);
+
+static int cht_wc_fg_probe(struct i2c_client *client,
+			const struct i2c_device_id *i2c_id)
+{
+	struct device *dev = &client->dev;
+	struct cht_wc_fg_data *fg;
+	acpi_status status;
+	unsigned long long ptyp;
+
+	fg = devm_kzalloc(dev, sizeof(*fg), GFP_KERNEL);
+	if (!fg)
+		return -ENOMEM;
+
+	status = acpi_evaluate_integer(ACPI_HANDLE(dev), "PTYP", NULL, &ptyp);
+	if (ACPI_FAILURE(status)) {
+		dev_err(dev, "Failed to get PTYPE\n");
+		return -ENODEV;
+	}
+
+	/*
+	 * The same ACPI HID is used with different PMICs check PTYP to
+	 * ensure that we are dealing with a Whiskey Cove PMIC.
+	 */
+	if (ptyp != CHT_WC_FG_PTYPE)
+		return -ENODEV;
+
+	fg->dev = dev;
+	/*
+	 * The current resource settings table for the fuel gauge contains
+	 * multiple i2c devices on 2 different i2c-busses. The one we actually
+	 * want is the second resource (index 1).
+	 */
+	fg->client = i2c_acpi_new_device(dev, 1);
+	if (!fg->client)
+		return -EPROBE_DEFER;
+
+	i2c_set_clientdata(client, fg);
+
+	mutex_lock(&cht_wc_fg_mutex);
+	cht_wc_fg = fg;
+	mutex_unlock(&cht_wc_fg_mutex);
+
+	return 0;
+}
+
+static int cht_wc_fg_remove(struct i2c_client *i2c)
+{
+	struct cht_wc_fg_data *fg = i2c_get_clientdata(i2c);
+
+	mutex_lock(&cht_wc_fg_mutex);
+	cht_wc_fg = NULL;
+	mutex_unlock(&cht_wc_fg_mutex);
+
+	i2c_unregister_device(fg->client);
+
+	return 0;
+}
+
+static const struct i2c_device_id cht_wc_fg_i2c_id[] = {
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, cht_wc_fg_i2c_id);
+
+static const struct acpi_device_id cht_wc_fg_acpi_ids[] = {
+	{ "INT33FE", },
+	{ }
+};
+MODULE_DEVICE_TABLE(acpi, cht_wc_fg_acpi_ids);
+
+static struct i2c_driver cht_wc_fg_driver = {
+	.driver	= {
+		.name	= "CHT Whiskey Cove PMIC Fuel Gauge",
+		.acpi_match_table = ACPI_PTR(cht_wc_fg_acpi_ids),
+	},
+	.probe = cht_wc_fg_probe,
+	.remove = cht_wc_fg_remove,
+	.id_table = cht_wc_fg_i2c_id,
+	.irq_index = 1,
+};
+
+module_i2c_driver(cht_wc_fg_driver);
+
+MODULE_DESCRIPTION("Intel CHT Whiskey Cove PMIC Fuel Gauge driver");
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/power/cht_wc_fuel_gauge.h b/include/linux/power/cht_wc_fuel_gauge.h
new file mode 100644
index 0000000..4b4e051
--- /dev/null
+++ b/include/linux/power/cht_wc_fuel_gauge.h
@@ -0,0 +1,21 @@
+/*
+ * Intel CHT Whiskey Cove Fuel Gauge driver
+ * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __CHT_WC_FUEL_GAUGE_H
+#define __CHT_WC_FUEL_GAUGE_H
+
+int cht_wc_fg_get_property(enum power_supply_property prop,
+			   union power_supply_propval *val);
+
+#endif
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [PATCH 15/15] i2c-cht-wc: Add Intel Cherry Trail Whiskey Cove SMBUS controller driver
  2017-03-17  9:55 [PATCH 00/15] Add Intel Cherry Trail Whiskey Cove PMIC support Hans de Goede
                   ` (13 preceding siblings ...)
  2017-03-17  9:55 ` [PATCH 14/15] power: supply: Add driver for Cherry Trail Whiskey Cove PMIC Fuel Gauge Hans de Goede
@ 2017-03-17  9:55 ` Hans de Goede
  2017-03-17 18:22   ` Andy Shevchenko
  14 siblings, 1 reply; 90+ messages in thread
From: Hans de Goede @ 2017-03-17  9:55 UTC (permalink / raw)
  To: Rafael J . Wysocki, Len Brown, Wolfram Sang, Andy Shevchenko,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: Hans de Goede, linux-acpi, Takashi Iwai, linux-i2c, linux-kernel,
	linux-pm

The Intel Cherry Trail Whiskey Cove PMIC has a builtin SMBUS controller
for talking to an external PMIC. Add a driver for this.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/i2c/busses/Kconfig      |   9 ++
 drivers/i2c/busses/Makefile     |   1 +
 drivers/i2c/busses/i2c-cht-wc.c | 338 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 348 insertions(+)
 create mode 100644 drivers/i2c/busses/i2c-cht-wc.c

diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 8adc0f1..19ddd82 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -187,6 +187,15 @@ config I2C_PIIX4
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-piix4.
 
+config I2C_CHT_WC
+	tristate "Intel Cherry Trail Whiskey Cove PMIC smbus controller"
+	depends on INTEL_SOC_PMIC_CHTWC
+	depends on CHT_WC_FUEL_GAUGE
+	help
+	  If you say yes to this option, support will be included for the
+	  SMBus controller found in the Intel Cherry Trail Whiskey Cove PMIC
+	  found on some Intel Cherry Trail systems.
+
 config I2C_NFORCE2
 	tristate "Nvidia nForce2, nForce3 and nForce4"
 	depends on PCI
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 30b6085..f6443fa 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_I2C_ALI15X3)	+= i2c-ali15x3.o
 obj-$(CONFIG_I2C_AMD756)	+= i2c-amd756.o
 obj-$(CONFIG_I2C_AMD756_S4882)	+= i2c-amd756-s4882.o
 obj-$(CONFIG_I2C_AMD8111)	+= i2c-amd8111.o
+obj-$(CONFIG_I2C_CHT_WC)	+= i2c-cht-wc.o
 obj-$(CONFIG_I2C_I801)		+= i2c-i801.o
 obj-$(CONFIG_I2C_ISCH)		+= i2c-isch.o
 obj-$(CONFIG_I2C_ISMT)		+= i2c-ismt.o
diff --git a/drivers/i2c/busses/i2c-cht-wc.c b/drivers/i2c/busses/i2c-cht-wc.c
new file mode 100644
index 0000000..70599f7
--- /dev/null
+++ b/drivers/i2c/busses/i2c-cht-wc.c
@@ -0,0 +1,338 @@
+/*
+ * Intel CHT Whiskey Cove PMIC I2C Master driver
+ * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Based on various non upstream patches to support the CHT Whiskey Cove PMIC:
+ * Copyright (C) 2011 - 2014 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/mfd/intel_soc_pmic.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/power/bq24190_charger.h>
+#include <linux/power/cht_wc_fuel_gauge.h>
+#include <linux/slab.h>
+
+#define CHT_WC_I2C_CTRL			0x5e24
+#define CHT_WC_I2C_CTRL_WR		BIT(0)
+#define CHT_WC_I2C_CTRL_RD		BIT(1)
+#define CHT_WC_I2C_CLIENT_ADDR		0x5e25
+#define CHT_WC_I2C_REG_OFFSET		0x5e26
+#define CHT_WC_I2C_WRDATA		0x5e27
+#define CHT_WC_I2C_RDDATA		0x5e28
+
+#define CHT_WC_EXTCHGRIRQ		0x6e0a
+#define CHT_WC_EXTCHGRIRQ_CLIENT_IRQ	BIT(0)
+#define CHT_WC_EXTCHGRIRQ_WRITE_IRQ	BIT(1)
+#define CHT_WC_EXTCHGRIRQ_READ_IRQ	BIT(2)
+#define CHT_WC_EXTCHGRIRQ_NACK_IRQ	BIT(3)
+#define CHT_WC_EXTCHGRIRQ_ADAP_IRQS	((u8)(BIT(1) | BIT(2) | BIT(3)))
+#define CHT_WC_EXTCHGRIRQ_MSK		0x6e17
+
+struct cht_wc_i2c_adap {
+	struct i2c_adapter adapter;
+	wait_queue_head_t wait;
+	struct irq_chip irqchip;
+	struct mutex irqchip_lock;
+	struct regmap *regmap;
+	struct irq_domain *irq_domain;
+	struct i2c_client *client;
+	int client_irq;
+	u8 irq_mask;
+	u8 old_irq_mask;
+	bool nack;
+	bool done;
+};
+
+static irqreturn_t cht_wc_i2c_adap_thread_handler(int id, void *data)
+{
+	struct cht_wc_i2c_adap *adap = data;
+	int ret, reg;
+
+	/* Read irqs */
+	ret = regmap_read(adap->regmap, CHT_WC_EXTCHGRIRQ, &reg);
+	if (ret) {
+		dev_err(&adap->adapter.dev, "Error reading extchgrirq reg\n");
+		return IRQ_NONE;
+	}
+
+	reg &= ~adap->irq_mask;
+
+	/*
+	 * Immediately ack irqs, so that if new irqs arrives while we're
+	 * handling the previous ones our irq will re-trigger when we're done.
+	 */
+	ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ, reg);
+	if (ret)
+		dev_err(&adap->adapter.dev, "Error writing extchgrirq reg\n");
+
+	/*
+	 * Do NOT use handle_nested_irq here, the client irq handler will
+	 * likely want to do i2c transfers and the i2c controller uses this
+	 * interrupt handler as well, so running the client irq handler from
+	 * this thread will cause things to lock up.
+	 */
+	if (reg & CHT_WC_EXTCHGRIRQ_CLIENT_IRQ) {
+		/*
+		 * generic_handle_irq expects local irqs to be disabled
+		 * as normally it is called from interrupt context.
+		 */
+		local_irq_disable();
+		generic_handle_irq(adap->client_irq);
+		local_irq_enable();
+	}
+
+	if (reg & CHT_WC_EXTCHGRIRQ_ADAP_IRQS) {
+		if (reg & CHT_WC_EXTCHGRIRQ_NACK_IRQ)
+			adap->nack = true;
+		adap->done = true;
+		wake_up(&adap->wait);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static u32 cht_wc_i2c_adap_master_func(struct i2c_adapter *adap)
+{
+	/* This i2c adapter only supports smbus byte transfers */
+	return I2C_FUNC_SMBUS_BYTE_DATA;
+}
+
+static int cht_wc_i2c_adap_smbus_xfer(struct i2c_adapter *_adap, u16 addr,
+				      unsigned short flags, char read_write,
+				      u8 command, int size,
+				      union i2c_smbus_data *data)
+{
+	struct cht_wc_i2c_adap *adap = i2c_get_adapdata(_adap);
+	int ret, reg;
+
+	adap->nack = false;
+	adap->done = false;
+
+	ret = regmap_write(adap->regmap, CHT_WC_I2C_CLIENT_ADDR, addr);
+	if (ret)
+		return ret;
+
+	if (read_write == I2C_SMBUS_WRITE) {
+		ret = regmap_write(adap->regmap, CHT_WC_I2C_WRDATA, data->byte);
+		if (ret)
+			return ret;
+	}
+
+	ret = regmap_write(adap->regmap, CHT_WC_I2C_REG_OFFSET, command);
+	if (ret)
+		return ret;
+
+	ret = regmap_write(adap->regmap, CHT_WC_I2C_CTRL,
+			   (read_write == I2C_SMBUS_WRITE) ?
+			   CHT_WC_I2C_CTRL_WR : CHT_WC_I2C_CTRL_RD);
+	if (ret)
+		return ret;
+
+	/* 3 second timeout, during cable plug the PMIC responds quite slow */
+	ret = wait_event_timeout(adap->wait, adap->done, HZ * 3);
+	if (ret == 0)
+		return -ETIMEDOUT;
+	if (adap->nack)
+		return -EIO;
+
+	if (read_write == I2C_SMBUS_READ) {
+		ret = regmap_read(adap->regmap, CHT_WC_I2C_RDDATA, &reg);
+		if (ret)
+			return ret;
+
+		data->byte = reg;
+	}
+
+	return 0;
+}
+
+static const struct i2c_algorithm cht_wc_i2c_adap_algo = {
+	.functionality = cht_wc_i2c_adap_master_func,
+	.smbus_xfer = cht_wc_i2c_adap_smbus_xfer,
+};
+
+/**** irqchip for the client connected to the extchgr i2c adapter ****/
+static void cht_wc_i2c_irq_lock(struct irq_data *data)
+{
+	struct cht_wc_i2c_adap *adap = irq_data_get_irq_chip_data(data);
+
+	mutex_lock(&adap->irqchip_lock);
+}
+
+static void cht_wc_i2c_irq_sync_unlock(struct irq_data *data)
+{
+	struct cht_wc_i2c_adap *adap = irq_data_get_irq_chip_data(data);
+	int ret;
+
+	if (adap->irq_mask != adap->old_irq_mask) {
+		ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ_MSK,
+				   adap->irq_mask);
+		if (ret == 0)
+			adap->old_irq_mask = adap->irq_mask;
+		else
+			dev_err(&adap->adapter.dev, "Error writing extchgrirq_msk\n");
+	}
+
+	mutex_unlock(&adap->irqchip_lock);
+}
+
+static void cht_wc_i2c_irq_enable(struct irq_data *data)
+{
+	struct cht_wc_i2c_adap *adap = irq_data_get_irq_chip_data(data);
+
+	adap->irq_mask &= ~CHT_WC_EXTCHGRIRQ_CLIENT_IRQ;
+}
+
+static void cht_wc_i2c_irq_disable(struct irq_data *data)
+{
+	struct cht_wc_i2c_adap *adap = irq_data_get_irq_chip_data(data);
+
+	adap->irq_mask |= CHT_WC_EXTCHGRIRQ_CLIENT_IRQ;
+}
+
+static const struct irq_chip cht_wc_i2c_irq_chip = {
+	.irq_bus_lock		= cht_wc_i2c_irq_lock,
+	.irq_bus_sync_unlock	= cht_wc_i2c_irq_sync_unlock,
+	.irq_disable		= cht_wc_i2c_irq_disable,
+	.irq_enable		= cht_wc_i2c_irq_enable,
+	.name			= "cht_wc_ext_chrg_irq_chip",
+};
+
+static const struct bq24190_platform_data bq24190_pdata = {
+	.no_register_reset = true,
+	.extcon_name = "cht_wcove_pwrsrc",
+	.get_ext_bat_property = cht_wc_fg_get_property,
+};
+
+static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev)
+{
+	struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
+	struct cht_wc_i2c_adap *adap;
+	struct i2c_board_info board_info = {
+		.type = "bq24190",
+		.addr = 0x6b,
+		.platform_data = (void *)&bq24190_pdata,
+	};
+	int ret, irq;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "Error missing irq resource\n");
+		return -EINVAL;
+	}
+
+	adap = devm_kzalloc(&pdev->dev, sizeof(*adap), GFP_KERNEL);
+	if (!adap)
+		return -ENOMEM;
+
+	init_waitqueue_head(&adap->wait);
+	mutex_init(&adap->irqchip_lock);
+	adap->irqchip = cht_wc_i2c_irq_chip;
+	adap->regmap = pmic->regmap;
+	adap->adapter.owner = THIS_MODULE;
+	adap->adapter.class = I2C_CLASS_HWMON;
+	adap->adapter.algo = &cht_wc_i2c_adap_algo;
+	strlcpy(adap->adapter.name, "PMIC I2C Adapter",
+		sizeof(adap->adapter.name));
+	adap->adapter.dev.parent = &pdev->dev;
+
+	/* Clear and activate i2c-adapter interrupts, disable client irq */
+	adap->old_irq_mask = adap->irq_mask = ~CHT_WC_EXTCHGRIRQ_ADAP_IRQS;
+	ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ, ~adap->irq_mask);
+	if (ret)
+		return ret;
+
+	ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ_MSK, adap->irq_mask);
+	if (ret)
+		return ret;
+
+	/* Alloc and register client irq */
+	adap->irq_domain = irq_domain_add_linear(pdev->dev.of_node, 1,
+						 &irq_domain_simple_ops, NULL);
+	if (!adap->irq_domain)
+		return -ENOMEM;
+
+	adap->client_irq = irq_create_mapping(adap->irq_domain, 0);
+	if (!adap->client_irq) {
+		ret = -ENOMEM;
+		goto remove_irq_domain;
+	}
+
+	irq_set_chip_data(adap->client_irq, adap);
+	irq_set_chip_and_handler(adap->client_irq, &adap->irqchip,
+				 handle_simple_irq);
+
+	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+					cht_wc_i2c_adap_thread_handler,
+					IRQF_ONESHOT, "PMIC I2C Adapter", adap);
+	if (ret)
+		goto remove_irq_domain;
+
+	i2c_set_adapdata(&adap->adapter, adap);
+	ret = i2c_add_adapter(&adap->adapter);
+	if (ret)
+		goto remove_irq_domain;
+
+	board_info.irq = adap->client_irq;
+	adap->client = i2c_new_device(&adap->adapter, &board_info);
+	if (!adap->client) {
+		ret = -ENOMEM;
+		goto del_adapter;
+	}
+
+	platform_set_drvdata(pdev, adap);
+	return 0;
+
+del_adapter:
+	i2c_del_adapter(&adap->adapter);
+remove_irq_domain:
+	irq_domain_remove(adap->irq_domain);
+	return ret;
+}
+
+static int cht_wc_i2c_adap_i2c_remove(struct platform_device *pdev)
+{
+	struct cht_wc_i2c_adap *adap = platform_get_drvdata(pdev);
+
+	i2c_unregister_device(adap->client);
+	i2c_del_adapter(&adap->adapter);
+	irq_domain_remove(adap->irq_domain);
+
+	return 0;
+}
+
+static struct platform_device_id cht_wc_i2c_adap_id_table[] = {
+	{ .name = "cht_wcove_ext_chgr" },
+	{},
+};
+MODULE_DEVICE_TABLE(platform, cht_wc_i2c_adap_id_table);
+
+struct platform_driver cht_wc_i2c_adap_driver = {
+	.probe = cht_wc_i2c_adap_i2c_probe,
+	.remove = cht_wc_i2c_adap_i2c_remove,
+	.driver = {
+		.name = "cht_wcove_ext_chgr",
+	},
+	.id_table = cht_wc_i2c_adap_id_table,
+};
+module_platform_driver(cht_wc_i2c_adap_driver);
+
+MODULE_DESCRIPTION("Intel CHT Whiskey Cove PMIC I2C Master driver");
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_LICENSE("GPL");
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* Re: [PATCH 01/15] mfd: Add Cherry Trail Whiskey Cove PMIC driver
  2017-03-17  9:55 ` [PATCH 01/15] mfd: Add Cherry Trail Whiskey Cove PMIC driver Hans de Goede
@ 2017-03-17 17:00   ` Andy Shevchenko
  2017-03-20 10:41     ` Lee Jones
  0 siblings, 1 reply; 90+ messages in thread
From: Andy Shevchenko @ 2017-03-17 17:00 UTC (permalink / raw)
  To: Hans de Goede, Rafael J . Wysocki, Len Brown, Wolfram Sang,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: linux-acpi, Takashi Iwai, linux-i2c, linux-kernel, linux-pm,
	Bin Gao, Felipe Balbi

On Fri, 2017-03-17 at 10:55 +0100, Hans de Goede wrote:
> Add mfd driver for Intel CHT Whiskey Cove PMIC, based on various non
> upstreamed CHT Whiskey Cove PMIC patches.
> 
> This is a somewhat minimal version which adds irqchip support and
> cells
> for: ACPI PMIC opregion support, the i2c-controller driving the
> external
> charger irc and the pwrsrc/extcon block.
> 
> Further cells can be added in the future if/when drivers are
> upstreamed
> for them.

Couple of minor comments, otherwise looks good to me:

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

> +/* Whiskey Cove PMIC share same ACPI ID between different platforms
> */
> +#define CHT_WC_HRV		3
> +
> +/* Level 1 IRQs (level 2 IRQs are handled in the child device
> drivers) */
> +enum {
> +	CHT_WC_PWRSRC_IRQ = 0,
> +	CHT_WC_THRM_IRQ,
> +	CHT_WC_BCU_IRQ,
> +	CHT_WC_ADC_IRQ,
> +	CHT_WC_EXT_CHGR_IRQ,
> +	CHT_WC_GPIO_IRQ,
> +	/* There is no irq 6 */
> +	CHT_WC_CRIT_IRQ = 7,

I would prefer explicit over implicit (adding = N to each line), but
this is minor.

> +};

> +	pmic->regmap = devm_regmap_init(dev, NULL, client,
> &cht_wc_regmap_cfg);
> +	if (IS_ERR(pmic->regmap))
> +		return PTR_ERR(pmic->regmap);
> +
> +	ret = devm_regmap_add_irq_chip(dev, pmic->regmap, pmic->irq,
> +				       IRQF_ONESHOT | IRQF_SHARED, 0,
> +				       &cht_wc_regmap_irq_chip,
> +				       &pmic->irq_chip_data);
> +	if (ret)
> +		return ret;
> +


> +	return devm_mfd_add_devices(dev, -1, cht_wc_dev,
> ARRAY_SIZE(cht_wc_dev),
> +			NULL, 0, regmap_irq_get_domain(pmic-
> >irq_chip_data));

PLATFORM_DEVID_NONE, please.

> +}

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH 03/15] extcon: cht-wc: Add Intel Cherry Trail Whiskey Cove PMIC extcon driver
  2017-03-17  9:55 ` [PATCH 03/15] extcon: cht-wc: Add Intel Cherry Trail Whiskey Cove PMIC extcon driver Hans de Goede
@ 2017-03-17 17:18   ` Andy Shevchenko
  2017-03-20 18:08     ` Hans de Goede
  2017-03-20  1:33   ` Chanwoo Choi
  1 sibling, 1 reply; 90+ messages in thread
From: Andy Shevchenko @ 2017-03-17 17:18 UTC (permalink / raw)
  To: Hans de Goede, Rafael J . Wysocki, Len Brown, Wolfram Sang,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: linux-acpi, Takashi Iwai, linux-i2c, linux-kernel, linux-pm,
	Felipe Balbi

On Fri, 2017-03-17 at 10:55 +0100, Hans de Goede wrote:
> Add a driver for charger detection / control on the Intel Cherrytrail
> Whiskey Cove PMIC.

+Cc: Felipe for some question(s) below.

>  drivers/extcon/extcon-cht-wc.c | 356 

I would use same pattern across drivers, i.e. "chtwc" (same for the rest
of the drivers in this series).

> +#define CHT_WC_PWRSRC_IRQ		0x6e03
> +#define CHT_WC_PWRSRC_IRQ_MASK		0x6e0f
> +#define CHT_WC_PWRSRC_STS		0x6e1e
> +#define CHT_WC_PWRSRC_VBUS		BIT(0)
> +#define CHT_WC_PWRSRC_DC		BIT(1)
> +#define CHT_WC_PWRSRC_BAT		BIT(2)
> +#define CHT_WC_PWRSRC_ID_GND		BIT(3)
> +#define CHT_WC_PWRSRC_ID_FLOAT		BIT(4)

Not obvious for which register those bit definitions are.
Also, keep them ordered by offset.

> +
> +#define CHT_WC_PHYCTRL			0x5e07
> +

> +#define CHT_WC_CHGRCTRL0		0x5e16

Dup!

> +
> +#define CHT_WC_CHGRCTRL0		0x5e16

> +static int cht_wc_extcon_get_charger(struct cht_wc_extcon_data *ext)
> +{
> +	int ret, usbsrc, status, retries = 5;
> +
> +	do {
> +		ret = regmap_read(ext->regmap, CHT_WC_USBSRC,
> &usbsrc);
> +		if (ret) {
> +			dev_err(ext->dev, "Error reading usbsrc:
> %d\n", ret);
> +			return ret;
> +		}
> +		status = usbsrc & CHT_WC_USBSRC_STS_MASK;
> +		if (status == CHT_WC_USBSRC_STS_SUCCESS ||
> +		    status == CHT_WC_USBSRC_STS_FAIL)
> +			break;
> +

> +		msleep(200);

Comment why and why so long?

> +	} while (retries--);

> +static void cht_wc_extcon_det_event(struct cht_wc_extcon_data *ext)

det -> detect ?


> 
+static irqreturn_t cht_wc_extcon_isr(int irq, void *data)
> +{
> +	struct cht_wc_extcon_data *ext = data;
> +	int ret, irqs;
> +
> +	ret = regmap_read(ext->regmap, CHT_WC_PWRSRC_IRQ, &irqs);
> +	if (ret)
> +		dev_err(ext->dev, "Error reading irqs: %d\n", ret);

Shouldn't we return IRQ_NONE here?
Perhaps comment is needed.

> +
> +	cht_wc_extcon_det_event(ext);
> +
> +	ret = regmap_write(ext->regmap, CHT_WC_PWRSRC_IRQ, irqs);
> +	if (ret)
> +		dev_err(ext->dev, "Error writing irqs: %d\n", ret);
> +
> +	return IRQ_HANDLED;
> +}
> +

> +/* usb_id sysfs attribute for debug / testing purposes */

Hmm... I would use debugfs for debug, otherwise it looks like it should
be framework (extcon) wide.

Perhaps Felipe can advise something here.

> +static int cht_wc_extcon_probe(struct platform_device *pdev)
> +{

> +	struct cht_wc_extcon_data *ext;
> +	struct intel_soc_pmic *pmic = dev_get_drvdata(pdev-
> >dev.parent);

Exchange them (assignment first).

> +	int irq, ret;
> +


> +	ret = devm_request_threaded_irq(ext->dev, irq, NULL,
> cht_wc_extcon_isr,
> +					IRQF_ONESHOT, pdev->name,
> ext);
> +	if (ret) {
> +		dev_err(ext->dev, "Failed to request interrupt\n");
> +		return ret;
> +	}
> +
> +	/* Unmask irqs */
> +	ret = regmap_write(ext->regmap, CHT_WC_PWRSRC_IRQ_MASK,
> +			   (int)~(CHT_WC_PWRSRC_VBUS | 

Hmm... Do you need explicit casting here?

> CHT_WC_PWRSRC_ID_GND |
> +				  CHT_WC_PWRSRC_ID_FLOAT));
> +	if (ret) {
> +		dev_err(ext->dev, "Error writing irq-mask: %d\n",
> ret);
> +		return ret;
> +	}

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH 04/15] power: supply: bq24190_charger: Add no_register_reset pdata flag
  2017-03-17  9:55 ` [PATCH 04/15] power: supply: bq24190_charger: Add no_register_reset pdata flag Hans de Goede
@ 2017-03-17 17:20   ` Andy Shevchenko
  2017-03-18  7:10   ` [04/15] " Liam Breck
  1 sibling, 0 replies; 90+ messages in thread
From: Andy Shevchenko @ 2017-03-17 17:20 UTC (permalink / raw)
  To: Hans de Goede, Rafael J . Wysocki, Len Brown, Wolfram Sang,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: linux-acpi, Takashi Iwai, linux-i2c, linux-kernel, linux-pm

On Fri, 2017-03-17 at 10:55 +0100, Hans de Goede wrote:
> On some platforms the register have been setup with platform specific
> values by the firmware and should not be reset.
> 

I would not extend platform data at all.
For GPIO we may use GPIO lookup tables, for the rest -- unified (built-
in) device properties API.

Consider to get rid of 
 include/linux/power/bq24190_charger.h
completely.

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH 06/15] power: supply: bq24190_charger: Use i2c-core irq-mapping code
  2017-03-17  9:55 ` [PATCH 06/15] power: supply: bq24190_charger: Use i2c-core irq-mapping code Hans de Goede
@ 2017-03-17 17:24   ` Andy Shevchenko
  2017-03-20  4:46     ` Sebastian Reichel
  2017-03-18  7:10   ` [06/15] " Liam Breck
  1 sibling, 1 reply; 90+ messages in thread
From: Andy Shevchenko @ 2017-03-17 17:24 UTC (permalink / raw)
  To: Hans de Goede, Rafael J . Wysocki, Len Brown, Wolfram Sang,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: linux-acpi, Takashi Iwai, linux-i2c, linux-kernel, linux-pm

On Fri, 2017-03-17 at 10:55 +0100, Hans de Goede wrote:
> The i2c-core already maps of irqs before calling the driver's probe
> function and there are no in tree users of
> bq24190_platform_data->gpio_int.
> 
> Remove the redundant custom irq-mapping code and just use client->irq.
> 

Nice! I did similar clean up to some other driver, so,

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

P.S. This should be first in the series against bq24190.

> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
>  drivers/power/supply/bq24190_charger.c | 61 ++-----------------------
> ---------
>  include/linux/power/bq24190_charger.h  |  1 -
>  2 files changed, 2 insertions(+), 60 deletions(-)
> 
> diff --git a/drivers/power/supply/bq24190_charger.c
> b/drivers/power/supply/bq24190_charger.c
> index 7bca8d0..9c4b171 100644
> --- a/drivers/power/supply/bq24190_charger.c
> +++ b/drivers/power/supply/bq24190_charger.c
> @@ -154,8 +154,6 @@ struct bq24190_dev_info {
>  	struct bq24190_platform_data	*pdata;
>  	char				model_name[I2C_NAME_SIZE]
> ;
>  	kernel_ulong_t			model;
> -	unsigned int			gpio_int;
> -	unsigned int			irq;
>  	struct mutex			f_reg_lock;
>  	u8				f_reg;
>  	u8				ss_reg;
> @@ -1296,56 +1294,11 @@ static int bq24190_hw_init(struct
> bq24190_dev_info *bdi)
>  	return ret;
>  }
>  
> -#ifdef CONFIG_OF
> -static int bq24190_setup_dt(struct bq24190_dev_info *bdi)
> -{
> -	bdi->irq = irq_of_parse_and_map(bdi->dev->of_node, 0);
> -	if (bdi->irq <= 0)
> -		return -1;
> -
> -	return 0;
> -}
> -#else
> -static int bq24190_setup_dt(struct bq24190_dev_info *bdi)
> -{
> -	return -1;
> -}
> -#endif
> -
> -static int bq24190_setup_pdata(struct bq24190_dev_info *bdi,
> -		struct bq24190_platform_data *pdata)
> -{
> -	int ret;
> -
> -	if (!gpio_is_valid(pdata->gpio_int))
> -		return -1;
> -
> -	ret = gpio_request(pdata->gpio_int, dev_name(bdi->dev));
> -	if (ret < 0)
> -		return -1;
> -
> -	ret = gpio_direction_input(pdata->gpio_int);
> -	if (ret < 0)
> -		goto out;
> -
> -	bdi->irq = gpio_to_irq(pdata->gpio_int);
> -	if (!bdi->irq)
> -		goto out;
> -
> -	bdi->gpio_int = pdata->gpio_int;
> -	return 0;
> -
> -out:
> -	gpio_free(pdata->gpio_int);
> -	return -1;
> -}
> -
>  static int bq24190_probe(struct i2c_client *client,
>  		const struct i2c_device_id *id)
>  {
>  	struct i2c_adapter *adapter = to_i2c_adapter(client-
> >dev.parent);
>  	struct device *dev = &client->dev;
> -	struct bq24190_platform_data *pdata = client-
> >dev.platform_data;
>  	struct power_supply_config charger_cfg = {}, battery_cfg =
> {};
>  	struct bq24190_dev_info *bdi;
>  	int ret;
> @@ -1372,12 +1325,7 @@ static int bq24190_probe(struct i2c_client
> *client,
>  
>  	i2c_set_clientdata(client, bdi);
>  
> -	if (dev->of_node)
> -		ret = bq24190_setup_dt(bdi);
> -	else
> -		ret = bq24190_setup_pdata(bdi, pdata);
> -
> -	if (ret) {
> +	if (!client->irq) {
>  		dev_err(dev, "Can't get irq info\n");
>  		return -EINVAL;
>  	}
> @@ -1417,7 +1365,7 @@ static int bq24190_probe(struct i2c_client
> *client,
>  		goto out3;
>  	}
>  
> -	ret = devm_request_threaded_irq(dev, bdi->irq, NULL,
> +	ret = devm_request_threaded_irq(dev, client->irq, NULL,
>  			bq24190_irq_handler_thread,
>  			IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
>  			"bq24190-charger", bdi);
> @@ -1439,8 +1387,6 @@ static int bq24190_probe(struct i2c_client
> *client,
>  
>  out1:
>  	pm_runtime_disable(dev);
> -	if (bdi->gpio_int)
> -		gpio_free(bdi->gpio_int);
>  	return ret;
>  }
>  
> @@ -1457,9 +1403,6 @@ static int bq24190_remove(struct i2c_client
> *client)
>  	power_supply_unregister(bdi->charger);
>  	pm_runtime_disable(bdi->dev);
>  
> -	if (bdi->gpio_int)
> -		gpio_free(bdi->gpio_int);
> -
>  	return 0;
>  }
>  
> diff --git a/include/linux/power/bq24190_charger.h
> b/include/linux/power/bq24190_charger.h
> index cb49717..8d918cb 100644
> --- a/include/linux/power/bq24190_charger.h
> +++ b/include/linux/power/bq24190_charger.h
> @@ -10,7 +10,6 @@
>  #define _BQ24190_CHARGER_H_
>  
>  struct bq24190_platform_data {
> -	unsigned int	gpio_int;	/* GPIO pin that's
> connected to INT# */
>  	bool no_register_reset;
>  };
>  

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH 10/15] power: supply: bq24190_charger: Use extcon to determine ilimit, 5v boost
  2017-03-17  9:55 ` [PATCH 10/15] power: supply: bq24190_charger: Use extcon to determine ilimit, 5v boost Hans de Goede
@ 2017-03-17 17:33   ` Andy Shevchenko
  2017-03-20 22:38     ` Hans de Goede
  2017-03-18  7:10   ` [10/15] " Liam Breck
  2017-03-20  4:52   ` [PATCH 10/15] " Sebastian Reichel
  2 siblings, 1 reply; 90+ messages in thread
From: Andy Shevchenko @ 2017-03-17 17:33 UTC (permalink / raw)
  To: Hans de Goede, Rafael J . Wysocki, Len Brown, Wolfram Sang,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: linux-acpi, Takashi Iwai, linux-i2c, linux-kernel, linux-pm

On Fri, 2017-03-17 at 10:55 +0100, Hans de Goede wrote:
> Add support for monitoring an extcon device with SDP/CDP/DCP and HOST
> cables and adjust ilimit and enable/disable the 5v boost converter
> accordingly. This is necessary on systems where the PSEL pin is
> hardwired
> high and ILIM needs to be set by software based on the detected
> charger
> type.
> 

>  config CHARGER_BQ24190
>  	tristate "TI BQ24190 battery charger driver"
>  	depends on I2C

> +	depends on EXTCON

I dunno what is preferred here, but if we would like to keep
compatibility with previous configurations "select" should be used over
"depends on".

> +static void bq24190_extcon_work(struct work_struct *work)
> +{
> +	struct bq24190_dev_info *bdi =
> +		container_of(work, struct bq24190_dev_info,
> extcon_work);
> +	int ret, iinlim = 0;
> +
> +	if (extcon_get_state(bdi->extcon, EXTCON_CHG_USB_SDP) == 1)
> +		iinlim = 500000;
> +	else if (extcon_get_state(bdi->extcon, EXTCON_CHG_USB_CDP) ==
> 1 ||
> +		 extcon_get_state(bdi->extcon, EXTCON_CHG_USB_ACA) ==
> 1)
> +		iinlim = 1500000;
> +	else if (extcon_get_state(bdi->extcon, EXTCON_CHG_USB_DCP) ==
> 1)
> +		iinlim = 2000000;
> +

> +	if (iinlim) {

Could be possible to call below unconditionally here (use 0)?

> +		ret = bq24190_set_field_val(bdi, BQ24190_REG_ISC,
> +				BQ24190_REG_ISC_IINLIM_MASK,
> +				BQ24190_REG_ISC_IINLIM_SHIFT,
> +				bq24190_iinlim_values,
> +				ARRAY_SIZE(bq24190_iinlim_values),
> +				iinlim);
> +		if (ret)
> +			dev_err(bdi->dev, "Can't set IINLIM: %d\n",
> ret);
> +	}

Perhaps make above as a helper?

In that case no need for "if (iinlim)" and perhaps switch-case might be
used instead of if-else-if (latter is up to you).

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH 11/15] i2c: core: Allow getting ACPI info by index
  2017-03-17  9:55 ` [PATCH 11/15] i2c: core: Allow getting ACPI info by index Hans de Goede
@ 2017-03-17 17:35   ` Andy Shevchenko
  0 siblings, 0 replies; 90+ messages in thread
From: Andy Shevchenko @ 2017-03-17 17:35 UTC (permalink / raw)
  To: Hans de Goede, Rafael J . Wysocki, Len Brown, Wolfram Sang,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: linux-acpi, Takashi Iwai, linux-i2c, linux-kernel, linux-pm,
	Jarkko Nikula

On Fri, 2017-03-17 at 10:55 +0100, Hans de Goede wrote:
> Modify struct i2c_acpi_lookup and i2c_acpi_fill_info() to allow
> using them to get the info from a certain index in the ACPI-resource
> list rather then taking the first I2cSerialBus resource.
> 

+Cc: Jarkko (our main I2C guy)

> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
>  drivers/i2c/i2c-core.c | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
> index d2402bb..32b58fb 100644
> --- a/drivers/i2c/i2c-core.c
> +++ b/drivers/i2c/i2c-core.c
> @@ -112,6 +112,8 @@ struct i2c_acpi_lookup {
>  	acpi_handle adapter_handle;
>  	acpi_handle device_handle;
>  	acpi_handle search_handle;
> +	int n;
> +	int index;
>  	u32 speed;
>  	u32 min_speed;
>  };
> @@ -123,6 +125,9 @@ static int i2c_acpi_fill_info(struct acpi_resource
> *ares, void *data)
>  	struct acpi_resource_i2c_serialbus *sb;
>  	acpi_status status;
>  
> +	if (lookup->index != -1 && lookup->n++ != lookup->index)
> +		return 1;
> +
>  	if (info->addr || ares->type !=
> ACPI_RESOURCE_TYPE_SERIAL_BUS)
>  		return 1;
>  
> @@ -182,6 +187,7 @@ static int i2c_acpi_get_info(struct acpi_device
> *adev,
>  
>  	memset(&lookup, 0, sizeof(lookup));
>  	lookup.info = info;
> +	lookup.index = -1;
>  
>  	ret = i2c_acpi_do_lookup(adev, &lookup);
>  	if (ret)
> @@ -328,6 +334,7 @@ u32 i2c_acpi_find_bus_speed(struct device *dev)
>  	lookup.search_handle = ACPI_HANDLE(dev);
>  	lookup.min_speed = UINT_MAX;
>  	lookup.info = &dummy;
> +	lookup.index = -1;
>  
>  	status = acpi_walk_namespace(ACPI_TYPE_DEVICE,
> ACPI_ROOT_OBJECT,
>  				     I2C_ACPI_MAX_SCAN_DEPTH,

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH 12/15] i2c: core: Add new i2c_acpi_new_device helper function
  2017-03-17  9:55 ` [PATCH 12/15] i2c: core: Add new i2c_acpi_new_device helper function Hans de Goede
@ 2017-03-17 17:37   ` Andy Shevchenko
  2017-03-22 15:59     ` Hans de Goede
  0 siblings, 1 reply; 90+ messages in thread
From: Andy Shevchenko @ 2017-03-17 17:37 UTC (permalink / raw)
  To: Hans de Goede, Rafael J . Wysocki, Len Brown, Wolfram Sang,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: linux-acpi, Takashi Iwai, linux-i2c, linux-kernel, linux-pm

On Fri, 2017-03-17 at 10:55 +0100, Hans de Goede wrote:
> By default the i2c subsys creates an i2c-client for the first
> I2cSerialBus
> resource of an acpi_device, but some acpi_devices have multiple
> I2cSerialBus resources and the driver may need access to the others.
> 
> This commit adds a new i2c_acpi_new_device function which can be used
> by
> drivers to create an i2c-client for any (other) I2cSerialBus resource
> of
> an acpi_device.
> 
> Note that the other resources may even be on a different i2c bus, so
> just
> retrieving the client address is not enough.
> 

Looks sane to me:

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

Nevertheless, one nit, can you update commit message with real excerpt
of DSDT?

> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
>  drivers/i2c/i2c-core.c | 48
> ++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/i2c.h    |  5 +++++
>  2 files changed, 53 insertions(+)
> 
> diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
> index 32b58fb..fd45207 100644
> --- a/drivers/i2c/i2c-core.c
> +++ b/drivers/i2c/i2c-core.c
> @@ -421,6 +421,54 @@ static int i2c_acpi_notify(struct notifier_block
> *nb, unsigned long value,
>  static struct notifier_block i2c_acpi_notifier = {
>  	.notifier_call = i2c_acpi_notify,
>  };
> +
> +/**
> + * i2c_acpi_new_device - Create i2c client for the Nth acpi resource
> of dev
> + * @dev:     Device owning the acpi resources to get the client from
> + * @index:   Index of acpi resource to get
> + *
> + * By default the i2c subsys creates an i2c-client for the first
> I2cSerialBus
> + * resource of an acpi_device, but some acpi_devices have multiple
> + * I2cSerialBus resources and the driver may need access to the
> others.
> + * This function can be used by drivers to create an i2c-client for
> any
> + * resource of an acpi_device.
> + *
> + * Returns a pointer to the new i2c-client, or NULL if the resource
> or
> + * adapter were not found.
> + */
> +struct i2c_client *i2c_acpi_new_device(struct device *dev, int index)
> +{
> +	struct i2c_acpi_lookup lookup;
> +	struct i2c_board_info info;
> +	struct i2c_adapter *adapter;
> +	struct acpi_device *adev;
> +	LIST_HEAD(resource_list);
> +	int ret;
> +
> +	adev = ACPI_COMPANION(dev);
> +	if (!adev)
> +		return NULL;
> +
> +	memset(&info, 0, sizeof(info));
> +	memset(&lookup, 0, sizeof(lookup));
> +	lookup.info = &info;
> +	lookup.device_handle = acpi_device_handle(adev);
> +	lookup.index = index;
> +
> +	ret = acpi_dev_get_resources(adev, &resource_list,
> +				     i2c_acpi_fill_info, &lookup);
> +	acpi_dev_free_resource_list(&resource_list);
> +
> +	if (ret < 0 || !info.addr)
> +		return NULL;
> +
> +	adapter =
> i2c_acpi_find_adapter_by_handle(lookup.adapter_handle);
> +	if (!adapter)
> +		return NULL;
> +
> +	return i2c_new_device(adapter, &info);
> +}
> +EXPORT_SYMBOL_GPL(i2c_acpi_new_device);
>  #else /* CONFIG_ACPI */
>  static inline void i2c_acpi_register_devices(struct i2c_adapter
> *adap) { }
>  extern struct notifier_block i2c_acpi_notifier;
> diff --git a/include/linux/i2c.h b/include/linux/i2c.h
> index 6b18352..369ebfa 100644
> --- a/include/linux/i2c.h
> +++ b/include/linux/i2c.h
> @@ -824,11 +824,16 @@ static inline const struct of_device_id
>  
>  #if IS_ENABLED(CONFIG_ACPI)
>  u32 i2c_acpi_find_bus_speed(struct device *dev);
> +struct i2c_client *i2c_acpi_new_device(struct device *dev, int
> index);
>  #else
>  static inline u32 i2c_acpi_find_bus_speed(struct device *dev)
>  {
>  	return 0;
>  }
> +static inline struct i2c_client *i2c_acpi_new_device(struct device
> *d, int i)
> +{
> +	return NULL;
> +}
>  #endif /* CONFIG_ACPI */
>  
>  #endif /* _LINUX_I2C_H */

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH 13/15] i2c: core: Allow drivers to specify index for irq to get from of / ACPI
  2017-03-17  9:55 ` [PATCH 13/15] i2c: core: Allow drivers to specify index for irq to get from of / ACPI Hans de Goede
@ 2017-03-17 17:41   ` Andy Shevchenko
  2017-03-20  8:55     ` kbuild test robot
  1 sibling, 0 replies; 90+ messages in thread
From: Andy Shevchenko @ 2017-03-17 17:41 UTC (permalink / raw)
  To: Hans de Goede, Rafael J . Wysocki, Len Brown, Wolfram Sang,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: linux-acpi, Takashi Iwai, linux-i2c, linux-kernel, linux-pm

On Fri, 2017-03-17 at 10:55 +0100, Hans de Goede wrote:
> Some of or ACPI declared / enumerated devices may have multiple irq
> resources declared and the driver may want to use a different irq then
> the one with index 0.
> 
> This commit adds a new irq_index field to struct i2c_driver and makes
> the i2c-core pass this to of_irq_get / acpi_dev_gpio_irq_get.
> 
> This is esp. useful for ACPI declared devices where the irq with
> index 0 may be entirely useless and cause i2c_device_probe to fail
> with
> -EPROBE_DEFER.

> --- a/include/linux/i2c.h
> +++ b/include/linux/i2c.h
> @@ -212,6 +212,9 @@ struct i2c_driver {
>  	int (*detect)(struct i2c_client *, struct i2c_board_info *);
>  	const unsigned short *address_list;
>  	struct list_head clients;
> +
> +	/* IRQ index for retreiving irq from ACPI resources */

We have kernel doc.

> +	int irq_index;

Not sure about name (would like it to be shorter, but Friday evening
doesn't allow to be creative).

>  };
>  #define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH 14/15] power: supply: Add driver for Cherry Trail Whiskey Cove PMIC Fuel Gauge
  2017-03-17  9:55 ` [PATCH 14/15] power: supply: Add driver for Cherry Trail Whiskey Cove PMIC Fuel Gauge Hans de Goede
@ 2017-03-17 17:58   ` Andy Shevchenko
  2017-03-22 17:03     ` Hans de Goede
  2017-03-20  5:07   ` Sebastian Reichel
  1 sibling, 1 reply; 90+ messages in thread
From: Andy Shevchenko @ 2017-03-17 17:58 UTC (permalink / raw)
  To: Hans de Goede, Rafael J . Wysocki, Len Brown, Wolfram Sang,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: linux-acpi, Takashi Iwai, linux-i2c, linux-kernel, linux-pm

On Fri, 2017-03-17 at 10:55 +0100, Hans de Goede wrote:
> Add a driver for the Cherry Trail Whiskey Cove PMIC Fuel Gauge, note
> the Cherry Trail Whiskey Cove PMIC Fuel Gauge block is purely a fuel
> gauge
> and not a full battery controller. As such it offers a platform_data
> callback for extra power_supply properties for the actual external-
> charger
> ic driver and does not register a power_supply itself.

ic -> IC

Can we move to something like built-in device properties for additional
properties instead of extending platform data?

> +config CHT_WC_FUEL_GAUGE

I would use similar pattern:

FUEL_GAUGE_INTEL_CHTWC (or FUEL_GAUGE_CHTWC, but this might be less
obvious about vendor)

> --- /dev/null
> +++ b/drivers/power/supply/cht_wc_fuel_gauge.c
> @@ -0,0 +1,209 @@
> +/*
> + * Intel CHT Whiskey Cove Fuel Gauge driver

CHT -> Cherry Trail 

> + *
> + * Cherrytrail Whiskey Cove devices have 2 functional blocks which
> interact
> + * with the battery.

Cherry Trail? 

> +#define REG_CHARGE_NOW		0x05
> +#define REG_VOLTAGE_NOW		0x09
> +#define REG_CURRENT_NOW		0x0a
> +#define REG_CURRENT_AVG		0x0b
> +#define REG_CHARGE_FULL		0x10
> +#define REG_CHARGE_DESIGN	0x18
> +#define REG_VOLTAGE_AVG		0x19

> +#define REG_VOLTAGE_OCV		0x1b /* Only updated during
> charging */

I think comment makes more sense where actual update is happening in the
code.

> +
> +static int cht_wc_fg_read(struct cht_wc_fg_data *fg, u8 reg,
> +			  union power_supply_propval *val, int scale,
> +			  int sign_extend)
> +{
> +	int ret;
> +
> +	ret = i2c_smbus_read_word_data(fg->client, reg);
> +	if (ret < 0)
> +		return ret;
> +
> +	if (sign_extend)
> +		ret = sign_extend32(ret, 15);

Magic?

> +
> +	val->intval = ret * scale;
> +
> +	return 0;
> +}


> +
> +int cht_wc_fg_get_property(enum power_supply_property prop,
> +			   union power_supply_propval *val)
> +{
> +	int ret = 0;

Sounds like redundant assignment...

> +
> +	mutex_lock(&cht_wc_fg_mutex);
> +
> 

> +	if (!cht_wc_fg) {
> +		ret = -ENXIO;
> +		goto out_unlock;
> +	}

...otherwise maybe

ret = cht_wc_fg ? 0 : -ENXIO;
if (ret)
 goto ...;

?

> +	default:
> +		ret = -ENODATA;
> +	}
> +out_unlock:
> +	mutex_unlock(&cht_wc_fg_mutex);
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(cht_wc_fg_get_property);

> +
> +static int cht_wc_fg_probe(struct i2c_client *client,
> +			const struct i2c_device_id *i2c_id)
> +{
> +	struct device *dev = &client->dev;
> +	struct cht_wc_fg_data *fg;
> +	acpi_status status;
> +	unsigned long long ptyp;

> +	status = acpi_evaluate_integer(ACPI_HANDLE(dev), "PTYP",
> NULL, &ptyp);
> +	if (ACPI_FAILURE(status)) {
> +		dev_err(dev, "Failed to get PTYPE\n");
> +		return -ENODEV;
> +	}
> +
> +	/*
> +	 * The same ACPI HID is used with different PMICs check PTYP
> to
> +	 * ensure that we are dealing with a Whiskey Cove PMIC.
> +	 */
> +	if (ptyp != CHT_WC_FG_PTYPE)
> +		return -ENODEV;

Logically I would split this part to be a main driver for device which
would use actual driver based on this, though I think it too much churn
for no benefit right now.

> +	mutex_lock(&cht_wc_fg_mutex);
> +	cht_wc_fg = fg;
> +	mutex_unlock(&cht_wc_fg_mutex);

It's pity we have no common storage of single possible present device
drivers in the kernel. I would use some kind of framework rather then
keeping all those global variables with locking. Perhaps radix / RB
tree.

> +
> +	return 0;
> +}

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH 15/15] i2c-cht-wc: Add Intel Cherry Trail Whiskey Cove SMBUS controller driver
  2017-03-17  9:55 ` [PATCH 15/15] i2c-cht-wc: Add Intel Cherry Trail Whiskey Cove SMBUS controller driver Hans de Goede
@ 2017-03-17 18:22   ` Andy Shevchenko
  2017-03-23 13:58     ` Hans de Goede
  0 siblings, 1 reply; 90+ messages in thread
From: Andy Shevchenko @ 2017-03-17 18:22 UTC (permalink / raw)
  To: Hans de Goede, Rafael J . Wysocki, Len Brown, Wolfram Sang,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: linux-acpi, Takashi Iwai, linux-i2c, linux-kernel, linux-pm

On Fri, 2017-03-17 at 10:55 +0100, Hans de Goede wrote:
> The Intel Cherry Trail Whiskey Cove PMIC has a builtin SMBUS
> controller
> for talking to an external PMIC. Add a driver for this.

Looking to all this mess we have with PMICs, perhaps some file under
Documentation to explain all those dependencies with nice ASCII flow
charts would be created.

>  drivers/i2c/busses/i2c-cht-wc.c | 338 

File name: i2c-chtwc.c

> +#include <linux/power/cht_wc_fuel_gauge.h>

Perhaps chtwc_fuel_gauge or intel_chtwc_fuel_gauge.h (see previous patch
for comment regarding naming).

> +#include <linux/slab.h>
> +
> +#define CHT_WC_I2C_CTRL			0x5e24
> +#define CHT_WC_I2C_CTRL_WR		BIT(0)
> +#define CHT_WC_I2C_CTRL_RD		BIT(1)
> +#define CHT_WC_I2C_CLIENT_ADDR		0x5e25
> +#define CHT_WC_I2C_REG_OFFSET		0x5e26
> +#define CHT_WC_I2C_WRDATA		0x5e27
> +#define CHT_WC_I2C_RDDATA		0x5e28
> +
> +#define CHT_WC_EXTCHGRIRQ		0x6e0a
> +#define CHT_WC_EXTCHGRIRQ_CLIENT_IRQ	BIT(0)
> +#define CHT_WC_EXTCHGRIRQ_WRITE_IRQ	BIT(1)
> +#define CHT_WC_EXTCHGRIRQ_READ_IRQ	BIT(2)
> +#define CHT_WC_EXTCHGRIRQ_NACK_IRQ	BIT(3)
> 

> +#define CHT_WC_EXTCHGRIRQ_ADAP_IRQS	((u8)(BIT(1) | BIT(2) |
> BIT(3)))

_IRQ_MASK ?

GENMASK() ?

> +#define CHT_WC_EXTCHGRIRQ_MSK		0x6e17

> +struct cht_wc_i2c_adap {
> +	struct i2c_adapter adapter;
> +	wait_queue_head_t wait;
> +	struct irq_chip irqchip;
> +	struct mutex irqchip_lock;
> +	struct regmap *regmap;
> +	struct irq_domain *irq_domain;
> +	struct i2c_client *client;
> +	int client_irq;
> +	u8 irq_mask;
> +	u8 old_irq_mask;
> +	bool nack;
> +	bool done;
> +};
> +
> +static irqreturn_t cht_wc_i2c_adap_thread_handler(int id, void *data)
> +{
> +	struct cht_wc_i2c_adap *adap = data;
> +	int ret, reg;
> +
> +	/* Read irqs */

IRQs

> +	ret = regmap_read(adap->regmap, CHT_WC_EXTCHGRIRQ, &reg);
> +	if (ret) {
> +		dev_err(&adap->adapter.dev, "Error reading extchgrirq
> reg\n");
> +		return IRQ_NONE;
> +	}
> +
> +	reg &= ~adap->irq_mask;
> +
> +	/*
> +	 * Immediately ack irqs, so that if new irqs arrives while
> we're
> +	 * handling the previous ones our irq will re-trigger when
> we're done.
> +	 */
> +	ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ, reg);
> +	if (ret)
> +		dev_err(&adap->adapter.dev, "Error writing extchgrirq
> reg\n");
> +
> +	/*
> +	 * Do NOT use handle_nested_irq here, the client irq handler
> will
> +	 * likely want to do i2c transfers and the i2c controller
> uses this
> +	 * interrupt handler as well, so running the client irq
> handler from
> +	 * this thread will cause things to lock up.
> +	 */
> +	if (reg & CHT_WC_EXTCHGRIRQ_CLIENT_IRQ) {
> +		/*
> +		 * generic_handle_irq expects local irqs to be
> disabled
> +		 * as normally it is called from interrupt context.
> +		 */
> +		local_irq_disable();
> +		generic_handle_irq(adap->client_irq);
> +		local_irq_enable();
> +	}
> +
> +	if (reg & CHT_WC_EXTCHGRIRQ_ADAP_IRQS) {

> +		if (reg & CHT_WC_EXTCHGRIRQ_NACK_IRQ)
> +			adap->nack = true;

adap->nack = !!(reg & ...);

> +		adap->done = true;
> +		wake_up(&adap->wait);
> +	}
> +
> +	return IRQ_HANDLED;
> +}

> +static u32 cht_wc_i2c_adap_master_func(struct i2c_adapter *adap)
> +{
> +	/* This i2c adapter only supports smbus byte transfers */

smbus -> SMBUS

> +	return I2C_FUNC_SMBUS_BYTE_DATA;
> +}
> +
> +static int cht_wc_i2c_adap_smbus_xfer(struct i2c_adapter *_adap, u16
> addr,
> +				      unsigned short flags, char
> read_write,
> +				      u8 command, int size,
> +				      union i2c_smbus_data *data)
> +{
> +	struct cht_wc_i2c_adap *adap = i2c_get_adapdata(_adap);
> +	int ret, reg;
> +

> +
> +	/* 3 second timeout, during cable plug the PMIC responds
> quite slow */
> +	ret = wait_event_timeout(adap->wait, adap->done, HZ * 3);

3 * HZ

> +	if (ret == 0)
> +		return -ETIMEDOUT;
> +	if (adap->nack)
> +		return -EIO;
> +
> +	if (read_write == I2C_SMBUS_READ) {
> +		ret = regmap_read(adap->regmap, CHT_WC_I2C_RDDATA,
> &reg);
> +		if (ret)
> +			return ret;
> +
> +		data->byte = reg;
> +	}
> +
> +	return 0;
> +}

> +/**** irqchip for the client connected to the extchgr i2c adapter
> ****/

Useless ?

> +static void cht_wc_i2c_irq_lock(struct irq_data *data)
> +{
> +	struct cht_wc_i2c_adap *adap =
> irq_data_get_irq_chip_data(data);
> +
> +	mutex_lock(&adap->irqchip_lock);
> +}
> +
> +static void cht_wc_i2c_irq_sync_unlock(struct irq_data *data)
> +{
> +	struct cht_wc_i2c_adap *adap =
> irq_data_get_irq_chip_data(data);
> +	int ret;
> +
> +	if (adap->irq_mask != adap->old_irq_mask) {
> +		ret = regmap_write(adap->regmap,
> CHT_WC_EXTCHGRIRQ_MSK,
> +				   adap->irq_mask);
> +		if (ret == 0)
> +			adap->old_irq_mask = adap->irq_mask;
> +		else
> +			dev_err(&adap->adapter.dev, "Error writing
> extchgrirq_msk\n");

extchgrirq_msk -> EXTCHGRIRQ_MSK ?
> +	}
> +
> +	mutex_unlock(&adap->irqchip_lock);
> +}


> +static const struct bq24190_platform_data bq24190_pdata = {
> +	.no_register_reset = true,
> +	.extcon_name = "cht_wcove_pwrsrc",
> +	.get_ext_bat_property = cht_wc_fg_get_property,
> +};
> +
> +static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev)
> +{
> +	struct intel_soc_pmic *pmic = dev_get_drvdata(pdev-
> >dev.parent);
> +	struct cht_wc_i2c_adap *adap;

> +	struct i2c_board_info board_info = {
> +		.type = "bq24190",
> +		.addr = 0x6b,
> +		.platform_data = (void *)&bq24190_pdata,
> +	};
> +	int ret, irq;
> +

> +	/* Clear and activate i2c-adapter interrupts, disable client
> irq */

irq -> IRQ

> +
> +	/* Alloc and register client irq */

Ditto.

> +	adap->irq_domain = irq_domain_add_linear(pdev->dev.of_node,
> 1,
> +						 &irq_domain_simple_o
> ps, NULL);

Can you use irq_domain_add_simple()?

And why do we need separate domain for one IRQ line?

> +	if (!adap->irq_domain)
> +		return -ENOMEM;
> +
> +	adap->client_irq = irq_create_mapping(adap->irq_domain, 0);
> +	if (!adap->client_irq) {
> +		ret = -ENOMEM;
> +		goto remove_irq_domain;
> +	}
> +
> +	irq_set_chip_data(adap->client_irq, adap);
> +	irq_set_chip_and_handler(adap->client_irq, &adap->irqchip,
> +				 handle_simple_irq);
> +

> +	board_info.irq = adap->client_irq;
> +	adap->client = i2c_new_device(&adap->adapter, &board_info);
> +	if (!adap->client) {
> +		ret = -ENOMEM;
> +		goto del_adapter;
> +	}

I would split this to some other module with board info.

Does it make sense?

By the way, doesn't ACPI have the charger IC node?

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [04/15] power: supply: bq24190_charger: Add no_register_reset pdata flag
  2017-03-17  9:55 ` [PATCH 04/15] power: supply: bq24190_charger: Add no_register_reset pdata flag Hans de Goede
  2017-03-17 17:20   ` Andy Shevchenko
@ 2017-03-18  7:10   ` Liam Breck
  2017-03-18 14:13     ` Hans de Goede
  1 sibling, 1 reply; 90+ messages in thread
From: Liam Breck @ 2017-03-18  7:10 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Andy Shevchenko, Sebastian Reichel, Tony Lindgren, linux-pm, Liam Breck

[dropped CC's not relevant to BQ24190; pls re-add anyone appropriate]

Hi Hans,

I am the de facto maintainer of BQ24190, with help from Tony. I contracted the original author to 
create the driver. I'm not aware of anyone else relying on it at present.

Pls rebase to -next (!) and post BQ24190 changes in a separate patchset. Reference any 
dependencies in other patchsets with Depends-on lines in patch descriptions linking to 
patchwork.kernel.org. If any dependency might be controversial, pls defer the BQ24190 patchset til 
controversy resolves.

You may be interested in these, which I will support in BQ24190 in near future:
https://patchwork.kernel.org/patch/9626487/
https://patchwork.kernel.org/patch/9626491/

Further comments below...

On Fri, 17 Mar 2017 10:55:16 +0100, Hans de Goede wrote:

> On some platforms the register have been setup with platform specific
> values by the firmware and should not be reset.

Pls describe this mysterious, meddling firmware. Who wrote it, when does it run, on what devices, 
etc? Include URLs to docs, etc. BTW it's not really "firmware" if it runs on the main cpu, IMO. 
A boot loader is not firmware.

We probably don't want to disable register_reset in all circumstances. Can you record the 
firmware's settings for charger? I suspect we should replay them in set_mode_host() -- to be 
renamed set_operating_params in forthcoming patchset.

What generates your platform_data objects?
Are you forced to use platform_data for some reason?

> Signed-off-by: Hans de Goede <hdegoede@redhat.com>

Add to all BQ24190 patches:
Cc: Liam Breck <kernel@networkimprov.net>
Cc: Tony Lindgren <tony@atomide.com>

Pls don't CC me on the related patchsets.

> ---
>  drivers/power/supply/bq24190_charger.c | 5 +++++
>  include/linux/power/bq24190_charger.h  | 1 +
>  2 files changed, 6 insertions(+)
> 
> diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
> index a4f0849..c92a40e4 100644
> --- a/drivers/power/supply/bq24190_charger.c
> +++ b/drivers/power/supply/bq24190_charger.c
> @@ -151,6 +151,7 @@ struct bq24190_dev_info {
>  	struct device			*dev;
>  	struct power_supply		*charger;
>  	struct power_supply		*battery;
> +	struct bq24190_platform_data	*pdata;

Use a register settings array/struct here, instead of platform-data. None of your other patches need 
to retain pdata.

>  	char				model_name[I2C_NAME_SIZE];
>  	kernel_ulong_t			model;
>  	unsigned int			gpio_int;
> @@ -506,6 +507,9 @@ static int bq24190_register_reset(struct bq24190_dev_info *bdi)
>  	int ret, limit = 100;
>  	u8 v;
>  
> +	if (bdi->pdata && bdi->pdata->no_register_reset)
> +		return 0;
> +
>  	/* Reset the registers */
>  	ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
>  			BQ24190_REG_POC_RESET_MASK,
> @@ -1339,6 +1343,7 @@ static int bq24190_probe(struct i2c_client *client,
>  	bdi->client = client;
>  	bdi->dev = dev;
>  	bdi->model = id->driver_data;
> +	bdi->pdata = client->dev.platform_data;
>  	strncpy(bdi->model_name, id->name, I2C_NAME_SIZE);
>  	mutex_init(&bdi->f_reg_lock);
>  	bdi->f_reg = 0;
> diff --git a/include/linux/power/bq24190_charger.h b/include/linux/power/bq24190_charger.h
> index 9f02837..cb49717 100644
> --- a/include/linux/power/bq24190_charger.h
> +++ b/include/linux/power/bq24190_charger.h
> @@ -11,6 +11,7 @@
>  
>  struct bq24190_platform_data {
>  	unsigned int	gpio_int;	/* GPIO pin that's connected to INT# */
> +	bool no_register_reset;
>  };
>  
>  #endif

Thanks,
Liam

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [05/15] power: supply: bq24190_charger: Limit charging voltage to 4.3V
  2017-03-17  9:55 ` [PATCH 05/15] power: supply: bq24190_charger: Limit charging voltage to 4.3V Hans de Goede
@ 2017-03-18  7:10   ` Liam Breck
  2017-03-18 14:24     ` Hans de Goede
  0 siblings, 1 reply; 90+ messages in thread
From: Liam Breck @ 2017-03-18  7:10 UTC (permalink / raw)
  To: Hans de Goede; +Cc: Andy Shevchenko, Sebastian Reichel, Tony Lindgren, linux-pm

On Fri, 17 Mar 2017 10:55:17 +0100, Hans de Goede wrote:

> When the platform data asks us to not reset the charger to its default
> values and instead trust the firmware set values check the charging
> voltage and clamp it to 4.304V.
> 
> Some firmwares set really too high voltages, e.g. the GPD-win I've been
> working on uses 4.384V. New LiHV (High Voltage) batteries may be charged
> upto 4.35V but that significantly impacts their lifetime, limit charging
> to 4.304V for safety and lifetime reasons.

See comments on patch 04; pls specify the offending firmwares and exactly how they 
misconfigure the charger. Include URLs to datasheets, etc.

> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
>  drivers/power/supply/bq24190_charger.c | 27 ++++++++++++++++++++++++---
>  1 file changed, 24 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
> index c92a40e4..7bca8d0 100644
> --- a/drivers/power/supply/bq24190_charger.c
> +++ b/drivers/power/supply/bq24190_charger.c
> @@ -504,11 +504,32 @@ static int bq24190_set_mode_host(struct bq24190_dev_info *bdi)
>  
>  static int bq24190_register_reset(struct bq24190_dev_info *bdi)
>  {
> -	int ret, limit = 100;
> +	int ret, voltage, limit = 100;
>  	u8 v;
>  
> -	if (bdi->pdata && bdi->pdata->no_register_reset)
> -		return 0;
> +	if (bdi->pdata && bdi->pdata->no_register_reset) {

See comments on patch 04. Invoke this in set_mode_host() using value from settings config.

> +		/*
> +		 * We've been asked to keep the firmware settings as is, but
> +		 * some firmwares set really too high voltages (e.g. 4.384V).
> +		 * New LiHV (High Voltage) batteries may be charged upto 4.35V
> +		 * but that significantly impacts their lifetime, limit
> +		 * charging to 4.304V for safety and lifetime reasons.
> +		 */

Docs which belong in external config.

> +		ret = bq24190_get_field_val(bdi, BQ24190_REG_CVC,
> +			BQ24190_REG_CVC_VREG_MASK, BQ24190_REG_CVC_VREG_SHIFT,
> +			bq24190_cvc_vreg_values,
> +			ARRAY_SIZE(bq24190_cvc_vreg_values), &voltage);
> +		if (ret < 0)
> +			return ret;
> +
> +		if (voltage <= 4304000)
> +			return 0;

The limit value should come from settings config.

> +		return bq24190_set_field_val(bdi, BQ24190_REG_CVC,
> +			BQ24190_REG_CVC_VREG_MASK, BQ24190_REG_CVC_VREG_SHIFT,
> +			bq24190_cvc_vreg_values,
> +			ARRAY_SIZE(bq24190_cvc_vreg_values), 4304000);
> +	}
>  
>  	/* Reset the registers */
>  	ret = bq24190_write_mask(bdi, BQ24190_REG_POC,

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [06/15] power: supply: bq24190_charger: Use i2c-core irq-mapping code
  2017-03-17  9:55 ` [PATCH 06/15] power: supply: bq24190_charger: Use i2c-core irq-mapping code Hans de Goede
  2017-03-17 17:24   ` Andy Shevchenko
@ 2017-03-18  7:10   ` Liam Breck
  2017-03-18 14:16     ` Hans de Goede
  1 sibling, 1 reply; 90+ messages in thread
From: Liam Breck @ 2017-03-18  7:10 UTC (permalink / raw)
  To: Hans de Goede; +Cc: Andy Shevchenko, Sebastian Reichel, Tony Lindgren, linux-pm

On Fri, 17 Mar 2017 10:55:18 +0100, Hans de Goede wrote:

> The i2c-core already maps of irqs before calling the driver's probe
> function and there are no in tree users of
> bq24190_platform_data->gpio_int.
> 
> Remove the redundant custom irq-mapping code and just use client->irq.
> 
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> ---
>  drivers/power/supply/bq24190_charger.c | 61 ++--------------------------------
>  include/linux/power/bq24190_charger.h  |  1 -
>  2 files changed, 2 insertions(+), 60 deletions(-)
> 
> diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
> index 7bca8d0..9c4b171 100644
> --- a/drivers/power/supply/bq24190_charger.c
> +++ b/drivers/power/supply/bq24190_charger.c
> @@ -154,8 +154,6 @@ struct bq24190_dev_info {
>  	struct bq24190_platform_data	*pdata;
>  	char				model_name[I2C_NAME_SIZE];
>  	kernel_ulong_t			model;
> -	unsigned int			gpio_int;
> -	unsigned int			irq;
>  	struct mutex			f_reg_lock;
>  	u8				f_reg;
>  	u8				ss_reg;
> @@ -1296,56 +1294,11 @@ static int bq24190_hw_init(struct bq24190_dev_info *bdi)
>  	return ret;
>  }
>  
> -#ifdef CONFIG_OF
> -static int bq24190_setup_dt(struct bq24190_dev_info *bdi)
> -{
> -	bdi->irq = irq_of_parse_and_map(bdi->dev->of_node, 0);
> -	if (bdi->irq <= 0)
> -		return -1;
> -
> -	return 0;
> -}
> -#else
> -static int bq24190_setup_dt(struct bq24190_dev_info *bdi)
> -{
> -	return -1;
> -}
> -#endif

I am adding a DT binding to this driver, using the above function. If it doesn't need the irq call, 
you can remove that. You may need to rebase on my patchset, coming next week.

> -static int bq24190_setup_pdata(struct bq24190_dev_info *bdi,
> -		struct bq24190_platform_data *pdata)
> -{
> -	int ret;
> -
> -	if (!gpio_is_valid(pdata->gpio_int))
> -		return -1;
> -
> -	ret = gpio_request(pdata->gpio_int, dev_name(bdi->dev));
> -	if (ret < 0)
> -		return -1;
> -
> -	ret = gpio_direction_input(pdata->gpio_int);
> -	if (ret < 0)
> -		goto out;
> -
> -	bdi->irq = gpio_to_irq(pdata->gpio_int);
> -	if (!bdi->irq)
> -		goto out;
> -
> -	bdi->gpio_int = pdata->gpio_int;
> -	return 0;
> -
> -out:
> -	gpio_free(pdata->gpio_int);
> -	return -1;
> -}
> -
>  static int bq24190_probe(struct i2c_client *client,
>  		const struct i2c_device_id *id)
>  {
>  	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
>  	struct device *dev = &client->dev;
> -	struct bq24190_platform_data *pdata = client->dev.platform_data;
>  	struct power_supply_config charger_cfg = {}, battery_cfg = {};
>  	struct bq24190_dev_info *bdi;
>  	int ret;
> @@ -1372,12 +1325,7 @@ static int bq24190_probe(struct i2c_client *client,
>  
>  	i2c_set_clientdata(client, bdi);
>  
> -	if (dev->of_node)
> -		ret = bq24190_setup_dt(bdi);

And keep the above, adding:
		if (ret < 0) return ret;

> -	else
> -		ret = bq24190_setup_pdata(bdi, pdata);
> -
> -	if (ret) {
> +	if (!client->irq) {
>  		dev_err(dev, "Can't get irq info\n");
>  		return -EINVAL;
>  	}
> @@ -1417,7 +1365,7 @@ static int bq24190_probe(struct i2c_client *client,
>  		goto out3;
>  	}
>  
> -	ret = devm_request_threaded_irq(dev, bdi->irq, NULL,
> +	ret = devm_request_threaded_irq(dev, client->irq, NULL,
>  			bq24190_irq_handler_thread,
>  			IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
>  			"bq24190-charger", bdi);
> @@ -1439,8 +1387,6 @@ static int bq24190_probe(struct i2c_client *client,
>  
>  out1:
>  	pm_runtime_disable(dev);
> -	if (bdi->gpio_int)
> -		gpio_free(bdi->gpio_int);
>  	return ret;
>  }
>  
> @@ -1457,9 +1403,6 @@ static int bq24190_remove(struct i2c_client *client)
>  	power_supply_unregister(bdi->charger);
>  	pm_runtime_disable(bdi->dev);
>  
> -	if (bdi->gpio_int)
> -		gpio_free(bdi->gpio_int);
> -
>  	return 0;
>  }
>  
> diff --git a/include/linux/power/bq24190_charger.h b/include/linux/power/bq24190_charger.h
> index cb49717..8d918cb 100644
> --- a/include/linux/power/bq24190_charger.h
> +++ b/include/linux/power/bq24190_charger.h
> @@ -10,7 +10,6 @@
>  #define _BQ24190_CHARGER_H_
>  
>  struct bq24190_platform_data {
> -	unsigned int	gpio_int;	/* GPIO pin that's connected to INT# */
>  	bool no_register_reset;
>  };
 

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [07/15] power: supply: bq24190_charger: Add support for bq24192[i]
  2017-03-17  9:55 ` [PATCH 07/15] power: supply: bq24190_charger: Add support for bq24192[i] Hans de Goede
@ 2017-03-18  7:10   ` Liam Breck
  2017-03-18 14:30     ` Hans de Goede
  0 siblings, 1 reply; 90+ messages in thread
From: Liam Breck @ 2017-03-18  7:10 UTC (permalink / raw)
  To: Hans de Goede; +Cc: Andy Shevchenko, Sebastian Reichel, Tony Lindgren, linux-pm

On Fri, 17 Mar 2017 10:55:19 +0100, Hans de Goede wrote:

> The bq24192 and bq24192i are mostly identical to the bq24190, TI even
> published a single datasheet for all 3 of them. The difference
> between the bq24190 and bq24192[i] is the way charger-type detection
> is done, the bq24190 is to be directly connected to the USB a/b lines,
> where as the the bq24192[i] has a gpio which should be driven high/low
> externally depending on the type of charger connected, from a register
> level access pov there is no difference.
> 
> The differences between the bq24192 and bq24192i are:
> 1) Lower default charge rate on the bq24192i
> 2) Pre-charge-current can be max 640 mA on the bq24192i
> 
> Since we do not provide an API for setting the pre-charge-current,
> these differences can be ignored and we can simply use the existing
> code as-is with the bq24192 and bq24192i.

FYI, coming patchset will set pre- and termination-charge current via DT.

> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
>  drivers/power/supply/bq24190_charger.c | 12 ++++++++++--
>  1 file changed, 10 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
> index 9c4b171..9014dee 100644
> --- a/drivers/power/supply/bq24190_charger.c
> +++ b/drivers/power/supply/bq24190_charger.c
> @@ -1275,7 +1275,14 @@ static int bq24190_hw_init(struct bq24190_dev_info *bdi)
>  	if (ret < 0)
>  		goto out;
>  
> -	if (v != bdi->model) {
> +	switch (v) {
> +	case BQ24190_REG_VPRS_PN_24190:
> +	case BQ24190_REG_VPRS_PN_24192:
> +	case BQ24190_REG_VPRS_PN_24192I:
> +		bdi->model = v;

We should set model in probe(). Doesn't the previous code still work?

> +		break;
> +	default:
> +		dev_err(bdi->dev, "Error unknown model: 0x%02x\n", v);

Feel free to add the error msg.

>  		ret = -ENODEV;
>  		goto out;
>  	}
> @@ -1316,7 +1323,6 @@ static int bq24190_probe(struct i2c_client *client,
>  
>  	bdi->client = client;
>  	bdi->dev = dev;
> -	bdi->model = id->driver_data;

Is driver_data no longer always correct?

>  	bdi->pdata = client->dev.platform_data;
>  	strncpy(bdi->model_name, id->name, I2C_NAME_SIZE);
>  	mutex_init(&bdi->f_reg_lock);
> @@ -1450,6 +1456,8 @@ static SIMPLE_DEV_PM_OPS(bq24190_pm_ops, bq24190_pm_suspend, bq24190_pm_resume);
>   */
>  static const struct i2c_device_id bq24190_i2c_ids[] = {
>  	{ "bq24190", BQ24190_REG_VPRS_PN_24190 },
> +	{ "bq24192", BQ24190_REG_VPRS_PN_24192 },
> +	{ "bq24192i", BQ24190_REG_VPRS_PN_24192I },

This may be the only essential change.

>  	{ },
>  };
>  MODULE_DEVICE_TABLE(i2c, bq24190_i2c_ids);

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [08/15] power: supply: bq24190_charger: Add support for external fuel gauge
  2017-03-17  9:55 ` [PATCH 08/15] power: supply: bq24190_charger: Add support for external fuel gauge Hans de Goede
@ 2017-03-18  7:10   ` Liam Breck
  2017-03-18 14:31     ` Hans de Goede
  0 siblings, 1 reply; 90+ messages in thread
From: Liam Breck @ 2017-03-18  7:10 UTC (permalink / raw)
  To: Hans de Goede; +Cc: Andy Shevchenko, Sebastian Reichel, Tony Lindgren, linux-pm

On Fri, 17 Mar 2017 10:55:20 +0100, Hans de Goede wrote:

> Some platforms with a bq24190_charger have an external fuel gauge which
> makes it possible to reliably report battery (dis)charge state, at
> support for this by adding an optional get_ext_bat_property callback
> to the platform_data and using this if the platform provides it.

Please do not pollute the charger with fuel-gauge functionality; use the gauge driver directly.

And calling into a mystery module with a pointer from platform-data is scary! St. Patrick's 
Day is wrong for this; try April Fool's or Halloween ;-)

> By convention the callback will return -ENXIO when it is not ready yet,
> or the driver providing it has been unbound from its device. Since it
> returns the same error when unbound it cannot return -EPROBE_DEFER
> as that is not a valid errno.
> 
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
>  drivers/power/supply/bq24190_charger.c | 41 +++++++++++++++++++++++++++++++---
>  include/linux/power/bq24190_charger.h  |  4 ++++
>  2 files changed, 42 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
> index 9014dee..9fe69a5 100644
> --- a/drivers/power/supply/bq24190_charger.c
> +++ b/drivers/power/supply/bq24190_charger.c
> @@ -1111,7 +1111,10 @@ static int bq24190_battery_get_property(struct power_supply *psy,
>  		ret = 0;
>  		break;
>  	default:
> -		ret = -ENODATA;
> +		if (bdi->pdata && bdi->pdata->get_ext_bat_property)
> +			ret = bdi->pdata->get_ext_bat_property(psp, val);
> +		else
> +			ret = -ENODATA;
>  	}
>  
>  	pm_runtime_put_sync(bdi->dev);
> @@ -1168,12 +1171,31 @@ static enum power_supply_property bq24190_battery_properties[] = {
>  	POWER_SUPPLY_PROP_TECHNOLOGY,
>  	POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
>  	POWER_SUPPLY_PROP_SCOPE,
> +	/* Begin of extended battery properties */
> +	POWER_SUPPLY_PROP_VOLTAGE_NOW,
> +	POWER_SUPPLY_PROP_VOLTAGE_AVG,
> +	POWER_SUPPLY_PROP_VOLTAGE_OCV,
> +	POWER_SUPPLY_PROP_CURRENT_NOW,
> +	POWER_SUPPLY_PROP_CURRENT_AVG,
> +	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
> +	POWER_SUPPLY_PROP_CHARGE_FULL,
> +	POWER_SUPPLY_PROP_CHARGE_NOW,
>  };
>  
>  static const struct power_supply_desc bq24190_battery_desc = {
>  	.name			= "bq24190-battery",
>  	.type			= POWER_SUPPLY_TYPE_BATTERY,
>  	.properties		= bq24190_battery_properties,
> +	.num_properties		= 6,
> +	.get_property		= bq24190_battery_get_property,
> +	.set_property		= bq24190_battery_set_property,
> +	.property_is_writeable	= bq24190_battery_property_is_writeable,
> +};
> +
> +static const struct power_supply_desc bq24190_ext_battery_desc = {
> +	.name			= "bq24190-battery",
> +	.type			= POWER_SUPPLY_TYPE_BATTERY,
> +	.properties		= bq24190_battery_properties,
>  	.num_properties		= ARRAY_SIZE(bq24190_battery_properties),
>  	.get_property		= bq24190_battery_get_property,
>  	.set_property		= bq24190_battery_set_property,
> @@ -1336,6 +1358,15 @@ static int bq24190_probe(struct i2c_client *client,
>  		return -EINVAL;
>  	}
>  
> +	if (bdi->pdata && bdi->pdata->get_ext_bat_property) {
> +		union power_supply_propval val;
> +
> +		/* Check external fuel gauge is ready */
> +		ret = bdi->pdata->get_ext_bat_property(0, &val);
> +		if (ret == -ENXIO)
> +			return -EPROBE_DEFER;
> +	}
> +
>  	pm_runtime_enable(dev);
>  	pm_runtime_resume(dev);
>  
> @@ -1357,8 +1388,12 @@ static int bq24190_probe(struct i2c_client *client,
>  	}
>  
>  	battery_cfg.drv_data = bdi;
> -	bdi->battery = power_supply_register(dev, &bq24190_battery_desc,
> -						&battery_cfg);
> +	if (bdi->pdata && bdi->pdata->get_ext_bat_property)
> +		bdi->battery = power_supply_register(dev,
> +				    &bq24190_ext_battery_desc, &battery_cfg);
> +	else
> +		bdi->battery = power_supply_register(dev,
> +				    &bq24190_battery_desc, &battery_cfg);
>  	if (IS_ERR(bdi->battery)) {
>  		dev_err(dev, "Can't register battery\n");
>  		ret = PTR_ERR(bdi->battery);
> diff --git a/include/linux/power/bq24190_charger.h b/include/linux/power/bq24190_charger.h
> index 8d918cb..02d248b 100644
> --- a/include/linux/power/bq24190_charger.h
> +++ b/include/linux/power/bq24190_charger.h
> @@ -9,8 +9,12 @@
>  #ifndef _BQ24190_CHARGER_H_
>  #define _BQ24190_CHARGER_H_
>  
> +#include <linux/power_supply.h>
> +
>  struct bq24190_platform_data {
>  	bool no_register_reset;
> +	int (*get_ext_bat_property)(enum power_supply_property prop,
> +				    union power_supply_propval *val);
>  };
>  
>  #endif

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [09/15] power: supply: bq24190_charger: Add voltage_max_design prop to battery
  2017-03-17  9:55 ` [PATCH 09/15] power: supply: bq24190_charger: Add voltage_max_design prop to battery Hans de Goede
@ 2017-03-18  7:10   ` Liam Breck
  2017-03-18 14:34     ` Hans de Goede
  2017-03-20  5:12   ` [PATCH 09/15] " Sebastian Reichel
  1 sibling, 1 reply; 90+ messages in thread
From: Liam Breck @ 2017-03-18  7:10 UTC (permalink / raw)
  To: Hans de Goede; +Cc: Andy Shevchenko, Sebastian Reichel, Tony Lindgren, linux-pm

On Fri, 17 Mar 2017 10:55:21 +0100, Hans de Goede wrote:

> When combined with an external fuel-gauge, upower needs voltage_max_design
> as it internally does all its calculations in Watts and converts the
> charge_foo properties from A to Watts by using voltage_max_design.

This is a battery characteristic which should be obtained from the fuel gauge (e.g. V at charge 
termination) or external battery config.

See also https://patchwork.kernel.org/patch/9626487/

> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
>  drivers/power/supply/bq24190_charger.c | 10 +++++++++-
>  1 file changed, 9 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
> index 9fe69a5..82cb33d 100644
> --- a/drivers/power/supply/bq24190_charger.c
> +++ b/drivers/power/supply/bq24190_charger.c
> @@ -1103,6 +1103,13 @@ static int bq24190_battery_get_property(struct power_supply *psy,
>  		val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
>  		ret = 0;
>  		break;
> +	case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
> +		/*
> +		 * Report charger configured voltage as max design voltage,
> +		 * not entirely correct, but userspace needs something here.
> +		 */
> +		ret = bq24190_charger_get_voltage(bdi, val);
> +		break;
>  	case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
>  		ret = bq24190_battery_get_temp_alert_max(bdi, val);
>  		break;
> @@ -1169,6 +1176,7 @@ static enum power_supply_property bq24190_battery_properties[] = {
>  	POWER_SUPPLY_PROP_HEALTH,
>  	POWER_SUPPLY_PROP_ONLINE,
>  	POWER_SUPPLY_PROP_TECHNOLOGY,
> +	POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
>  	POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
>  	POWER_SUPPLY_PROP_SCOPE,
>  	/* Begin of extended battery properties */
> @@ -1186,7 +1194,7 @@ static const struct power_supply_desc bq24190_battery_desc = {
>  	.name			= "bq24190-battery",
>  	.type			= POWER_SUPPLY_TYPE_BATTERY,
>  	.properties		= bq24190_battery_properties,
> -	.num_properties		= 6,
> +	.num_properties		= 7,
>  	.get_property		= bq24190_battery_get_property,
>  	.set_property		= bq24190_battery_set_property,
>  	.property_is_writeable	= bq24190_battery_property_is_writeable,

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [10/15] power: supply: bq24190_charger: Use extcon to determine ilimit, 5v boost
  2017-03-17  9:55 ` [PATCH 10/15] power: supply: bq24190_charger: Use extcon to determine ilimit, 5v boost Hans de Goede
  2017-03-17 17:33   ` Andy Shevchenko
@ 2017-03-18  7:10   ` Liam Breck
  2017-03-18 14:42     ` Hans de Goede
  2017-03-20  4:52   ` [PATCH 10/15] " Sebastian Reichel
  2 siblings, 1 reply; 90+ messages in thread
From: Liam Breck @ 2017-03-18  7:10 UTC (permalink / raw)
  To: Hans de Goede; +Cc: Andy Shevchenko, Sebastian Reichel, Tony Lindgren, linux-pm

Tony, question for you below...

On Fri, 17 Mar 2017 10:55:22 +0100, Hans de Goede wrote:

> Add support for monitoring an extcon device with SDP/CDP/DCP and HOST

insert: USB X.0

> cables and adjust ilimit and enable/disable the 5v boost converter
> accordingly. This is necessary on systems where the PSEL pin is hardwired
> high and ILIM needs to be set by software based on the detected charger
> type.

This description is rather thin for the extent of the changes. What specific systems 
require this? What drivers generate the event? Also provide URLs to docs/datasheets.

> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
>  drivers/power/supply/Kconfig           |  1 +
>  drivers/power/supply/bq24190_charger.c | 85 ++++++++++++++++++++++++++++++++++
>  include/linux/power/bq24190_charger.h  |  1 +
>  3 files changed, 87 insertions(+)
> 
> diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
> index f8b6e64..fd93110 100644
> --- a/drivers/power/supply/Kconfig
> +++ b/drivers/power/supply/Kconfig
> @@ -442,6 +442,7 @@ config CHARGER_BQ2415X
>  config CHARGER_BQ24190
>  	tristate "TI BQ24190 battery charger driver"
>  	depends on I2C
> +	depends on EXTCON
>  	depends on GPIOLIB || COMPILE_TEST
>  	help
>  	  Say Y to enable support for the TI BQ24190 battery charger.
> diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
> index 82cb33d..03990e2 100644
> --- a/drivers/power/supply/bq24190_charger.c
> +++ b/drivers/power/supply/bq24190_charger.c
> @@ -11,10 +11,12 @@
>  #include <linux/module.h>
>  #include <linux/interrupt.h>
>  #include <linux/delay.h>
> +#include <linux/extcon.h>
>  #include <linux/of_irq.h>
>  #include <linux/of_device.h>
>  #include <linux/pm_runtime.h>
>  #include <linux/power_supply.h>
> +#include <linux/workqueue.h>
>  #include <linux/gpio.h>
>  #include <linux/i2c.h>
>  
> @@ -39,6 +41,8 @@
>  #define BQ24190_REG_POC_WDT_RESET_SHIFT		6
>  #define BQ24190_REG_POC_CHG_CONFIG_MASK		(BIT(5) | BIT(4))
>  #define BQ24190_REG_POC_CHG_CONFIG_SHIFT	4
> +#define BQ24190_REG_POC_CHG_CONFIG_CHARGE	1
> +#define BQ24190_REG_POC_CHG_CONFIG_OTG		2
>  #define BQ24190_REG_POC_SYS_MIN_MASK		(BIT(3) | BIT(2) | BIT(1))
>  #define BQ24190_REG_POC_SYS_MIN_SHIFT		1
>  #define BQ24190_REG_POC_BOOST_LIM_MASK		BIT(0)
> @@ -152,6 +156,9 @@ struct bq24190_dev_info {
>  	struct power_supply		*charger;
>  	struct power_supply		*battery;
>  	struct bq24190_platform_data	*pdata;
> +	struct extcon_dev		*extcon;
> +	struct notifier_block		extcon_nb;
> +	struct work_struct		extcon_work;
>  	char				model_name[I2C_NAME_SIZE];
>  	kernel_ulong_t			model;
>  	struct mutex			f_reg_lock;
> @@ -167,6 +174,11 @@ struct bq24190_dev_info {
>   * number at that index in the array is the real-world value that it
>   * represents.
>   */
> +
> +/* REG00[2:0] (IINLIM) in uAh */
> +static const int bq24190_iinlim_values[] = {
> +	100000, 150000, 500000, 900000, 1200000, 1500000, 2000000, 3000000 };
> +
>  /* REG02[7:2] (ICHG) in uAh */
>  static const int bq24190_ccc_ichg_values[] = {
>  	 512000,  576000,  640000,  704000,  768000,  832000,  896000,  960000,
> @@ -1290,6 +1302,61 @@ static irqreturn_t bq24190_irq_handler_thread(int irq, void *data)
>  	return IRQ_HANDLED;
>  }
>  
> +static void bq24190_extcon_work(struct work_struct *work)
> +{

Does this need pm_runtime_get_sync(), etc?
(See linux-next patches to driver.)

> +	struct bq24190_dev_info *bdi =
> +		container_of(work, struct bq24190_dev_info, extcon_work);
> +	int ret, iinlim = 0;
> +
> +	if (extcon_get_state(bdi->extcon, EXTCON_CHG_USB_SDP) == 1)
> +		iinlim = 500000;
> +	else if (extcon_get_state(bdi->extcon, EXTCON_CHG_USB_CDP) == 1 ||
> +		 extcon_get_state(bdi->extcon, EXTCON_CHG_USB_ACA) == 1)
> +		iinlim = 1500000;
> +	else if (extcon_get_state(bdi->extcon, EXTCON_CHG_USB_DCP) == 1)
> +		iinlim = 2000000;
> +
> +	if (iinlim) {
> +		ret = bq24190_set_field_val(bdi, BQ24190_REG_ISC,
> +				BQ24190_REG_ISC_IINLIM_MASK,
> +				BQ24190_REG_ISC_IINLIM_SHIFT,
> +				bq24190_iinlim_values,
> +				ARRAY_SIZE(bq24190_iinlim_values),
> +				iinlim);
> +		if (ret)
> +			dev_err(bdi->dev, "Can't set IINLIM: %d\n", ret);
> +	}
> +
> +	/*
> +	 * If no charger has been detected and host mode is requested, activate
> +	 * the 5V boost converter, otherwise deactivate it.
> +	 */
> +	if (!iinlim && extcon_get_state(bdi->extcon, EXTCON_USB_HOST) == 1) {
> +		ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
> +					 BQ24190_REG_POC_CHG_CONFIG_MASK,
> +					 BQ24190_REG_POC_CHG_CONFIG_SHIFT,
> +					 BQ24190_REG_POC_CHG_CONFIG_OTG);
> +	} else {
> +		ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
> +					 BQ24190_REG_POC_CHG_CONFIG_MASK,
> +					 BQ24190_REG_POC_CHG_CONFIG_SHIFT,
> +					 BQ24190_REG_POC_CHG_CONFIG_CHARGE);
> +	}
> +	if (ret)
> +		dev_err(bdi->dev, "Can't set CHG_CONFIG: %d\n", ret);
> +}
> +
> +static int bq24190_extcon_event(struct notifier_block *nb, unsigned long event,
> +				void *param)
> +{
> +	struct bq24190_dev_info *bdi =
> +		container_of(nb, struct bq24190_dev_info, extcon_nb);
> +
> +	schedule_work(&bdi->extcon_work);
> +
> +	return NOTIFY_OK;
> +}
> +
>  static int bq24190_hw_init(struct bq24190_dev_info *bdi)
>  {
>  	u8 v;
> @@ -1375,6 +1442,12 @@ static int bq24190_probe(struct i2c_client *client,
>  			return -EPROBE_DEFER;
>  	}
>  
> +	if (bdi->pdata && bdi->pdata->extcon_name) {

Verify that extcon_name has an expected value?

> +		bdi->extcon = extcon_get_extcon_dev(bdi->pdata->extcon_name);
> +		if (!bdi->extcon)
> +			return -EPROBE_DEFER;

dev_info() a msg about this linkage, including info about the other side.

> +	}
> +
>  	pm_runtime_enable(dev);
>  	pm_runtime_resume(dev);
>  
> @@ -1423,6 +1496,18 @@ static int bq24190_probe(struct i2c_client *client,
>  		goto out4;
>  	}
>  
> +	if (bdi->extcon) {
> +		INIT_WORK(&bdi->extcon_work, bq24190_extcon_work);
> +		bdi->extcon_nb.notifier_call = bq24190_extcon_event;
> +		ret = devm_extcon_register_notifier(dev, bdi->extcon, -1,
> +						    &bdi->extcon_nb);
> +		if (ret)
> +			goto out4;
> +
> +		/* Sync initial cable state */
> +		schedule_work(&bdi->extcon_work);
> +	}
> +
>  	return 0;
>  
>  out4:
> diff --git a/include/linux/power/bq24190_charger.h b/include/linux/power/bq24190_charger.h
> index 02d248b..909c5b9 100644
> --- a/include/linux/power/bq24190_charger.h
> +++ b/include/linux/power/bq24190_charger.h
> @@ -13,6 +13,7 @@
>  
>  struct bq24190_platform_data {
>  	bool no_register_reset;
> +	const char *extcon_name;
>  	int (*get_ext_bat_property)(enum power_supply_property prop,
>  				    union power_supply_propval *val);
>  };

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [04/15] power: supply: bq24190_charger: Add no_register_reset pdata flag
  2017-03-18  7:10   ` [04/15] " Liam Breck
@ 2017-03-18 14:13     ` Hans de Goede
  2017-03-18 18:51       ` Liam Breck
  0 siblings, 1 reply; 90+ messages in thread
From: Hans de Goede @ 2017-03-18 14:13 UTC (permalink / raw)
  To: Liam Breck
  Cc: Andy Shevchenko, Sebastian Reichel, Tony Lindgren, linux-pm, Liam Breck

Hi,

On 18-03-17 08:10, Liam Breck wrote:
> [dropped CC's not relevant to BQ24190; pls re-add anyone appropriate]
>
> Hi Hans,
>
> I am the de facto maintainer of BQ24190, with help from Tony. I contracted the original author to
> create the driver. I'm not aware of anyone else relying on it at present.

Hi Liam, nice to meet you.

> Pls rebase to -next (!) and post BQ24190 changes in a separate patchset.

Ok, I will rebase these patches on top of
https://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply.git/log/?h=for-next

 > Reference any
> dependencies in other patchsets with Depends-on lines in patch descriptions linking to
> patchwork.kernel.org. If any dependency might be controversial, pls defer the BQ24190 patchset til
> controversy resolves.

There are no dependencies for the BQ24190 patches, they are a dependency for
some of the other changes but they can go upstream as is.

> You may be interested in these, which I will support in BQ24190 in near future:
> https://patchwork.kernel.org/patch/9626487/
> https://patchwork.kernel.org/patch/9626491/

Yeah those are not going to matter for the use-case I'm looking at.
I've a feeling you've only looked at the bq24190 patches and not the
rest of the set. There is a reason I posted these all together as I
mentioned in the cover-letter:

"I'm sending this as a single series so that people can see how all the bits
fit together."

Anyways I will try to clarify things by answering you questions /
responding to your remarks.

> Further comments below...
>
> On Fri, 17 Mar 2017 10:55:16 +0100, Hans de Goede wrote:
>
>> On some platforms the register have been setup with platform specific
>> values by the firmware and should not be reset.
>
> Pls describe this mysterious, meddling firmware. Who wrote it, when does it run, on what devices,
> etc? Include URLs to docs, etc. BTW it's not really "firmware" if it runs on the main cpu, IMO.
> A boot loader is not firmware.

So not all the world runs on ARM and not all devices using the
TI BQ24190 (and variants) use an ARM processor or devicetree
for that matter). Having worked on both ARM and x86 quite a bit
I've a feeling that you are approaching my patchset with somewhat
of an ARM focussed pov.

The primary device I'm trying to get battery/charger monitoring
working for is the GPDwin: http://www.gpd.hk/gpdwin.asp

Which is an Intel Cherrytrail using machine with an Intel
Cherrytrail Whiskey Cove PMIC.

The firmware I'm talking about here is the EFI system firmware
which boots the machine aka the BIOS.

> We probably don't want to disable register_reset in all circumstances. Can you record the
> firmware's settings for charger?

Yes after a (re)boot they are always reset to the same values.

> I suspect we should replay them in set_mode_host() -- to be
> renamed set_operating_params in forthcoming patchset.

That is not going to work, the Cherrytrail Whiskey Cove PMIC
is used on many different boards and there is no way to get
the info from the firmware other then reading it back from
the chip, hence the no_register_reset flag.

> What generates your platform_data objects?

The last patch in the patch-set shows this. The
Cherrytrail Whiskey Cove PMIC does charger type detection
and has a fuelgauge, but it does not contain a battery
charger itself. Instead it contains an i2c controller
to which an external charger chip, one of the
TI BQ24190 variants, gets connected.

The driver for this i2c-controller calls i2c_new_device
with i2c_board_info describing the BQ24190 charger
after calling i2c_add_adapter().

> Are you forced to use platform_data for some reason?

Since this is info being passed around inside the kernel
using platform_data is a hell of a lot simpler (and cleaner
no need to check types, etc on the receiving side) then
using device-properties. Device-properties are nice when
getting info from firmware, but this is not that.

Also one of the things passed is actually a function
pointer to a function to get extra power_supply_properties
from the fuel-gauge, and passing function pointers certainly
is not something which should be done through device-props.

>
>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>
> Add to all BQ24190 patches:
> Cc: Liam Breck <kernel@networkimprov.net>
> Cc: Tony Lindgren <tony@atomide.com>
>
> Pls don't CC me on the related patchsets.
>
>> ---
>>  drivers/power/supply/bq24190_charger.c | 5 +++++
>>  include/linux/power/bq24190_charger.h  | 1 +
>>  2 files changed, 6 insertions(+)
>>
>> diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
>> index a4f0849..c92a40e4 100644
>> --- a/drivers/power/supply/bq24190_charger.c
>> +++ b/drivers/power/supply/bq24190_charger.c
>> @@ -151,6 +151,7 @@ struct bq24190_dev_info {
>>  	struct device			*dev;
>>  	struct power_supply		*charger;
>>  	struct power_supply		*battery;
>> +	struct bq24190_platform_data	*pdata;
>
> Use a register settings array/struct here, instead of platform-data. None of your other patches need
> to retain pdata.

Sure I can make a 1:1 copy of each field in pdata here, but that
is just more lines of code for the same result.

>
>>  	char				model_name[I2C_NAME_SIZE];
>>  	kernel_ulong_t			model;
>>  	unsigned int			gpio_int;
>> @@ -506,6 +507,9 @@ static int bq24190_register_reset(struct bq24190_dev_info *bdi)
>>  	int ret, limit = 100;
>>  	u8 v;
>>
>> +	if (bdi->pdata && bdi->pdata->no_register_reset)
>> +		return 0;
>> +
>>  	/* Reset the registers */
>>  	ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
>>  			BQ24190_REG_POC_RESET_MASK,
>> @@ -1339,6 +1343,7 @@ static int bq24190_probe(struct i2c_client *client,
>>  	bdi->client = client;
>>  	bdi->dev = dev;
>>  	bdi->model = id->driver_data;
>> +	bdi->pdata = client->dev.platform_data;
>>  	strncpy(bdi->model_name, id->name, I2C_NAME_SIZE);
>>  	mutex_init(&bdi->f_reg_lock);
>>  	bdi->f_reg = 0;
>> diff --git a/include/linux/power/bq24190_charger.h b/include/linux/power/bq24190_charger.h
>> index 9f02837..cb49717 100644
>> --- a/include/linux/power/bq24190_charger.h
>> +++ b/include/linux/power/bq24190_charger.h
>> @@ -11,6 +11,7 @@
>>
>>  struct bq24190_platform_data {
>>  	unsigned int	gpio_int;	/* GPIO pin that's connected to INT# */
>> +	bool no_register_reset;
>>  };
>>
>>  #endif
>
> Thanks,
> Liam
>

Regards,

Hans

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [06/15] power: supply: bq24190_charger: Use i2c-core irq-mapping code
  2017-03-18  7:10   ` [06/15] " Liam Breck
@ 2017-03-18 14:16     ` Hans de Goede
  0 siblings, 0 replies; 90+ messages in thread
From: Hans de Goede @ 2017-03-18 14:16 UTC (permalink / raw)
  To: Liam Breck; +Cc: Andy Shevchenko, Sebastian Reichel, Tony Lindgren, linux-pm

Hi,

On 18-03-17 08:10, Liam Breck wrote:
> On Fri, 17 Mar 2017 10:55:18 +0100, Hans de Goede wrote:
>
>> The i2c-core already maps of irqs before calling the driver's probe
>> function and there are no in tree users of
>> bq24190_platform_data->gpio_int.
>>
>> Remove the redundant custom irq-mapping code and just use client->irq.
>>
>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
>> ---
>>  drivers/power/supply/bq24190_charger.c | 61 ++--------------------------------
>>  include/linux/power/bq24190_charger.h  |  1 -
>>  2 files changed, 2 insertions(+), 60 deletions(-)
>>
>> diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
>> index 7bca8d0..9c4b171 100644
>> --- a/drivers/power/supply/bq24190_charger.c
>> +++ b/drivers/power/supply/bq24190_charger.c
>> @@ -154,8 +154,6 @@ struct bq24190_dev_info {
>>  	struct bq24190_platform_data	*pdata;
>>  	char				model_name[I2C_NAME_SIZE];
>>  	kernel_ulong_t			model;
>> -	unsigned int			gpio_int;
>> -	unsigned int			irq;
>>  	struct mutex			f_reg_lock;
>>  	u8				f_reg;
>>  	u8				ss_reg;
>> @@ -1296,56 +1294,11 @@ static int bq24190_hw_init(struct bq24190_dev_info *bdi)
>>  	return ret;
>>  }
>>
>> -#ifdef CONFIG_OF
>> -static int bq24190_setup_dt(struct bq24190_dev_info *bdi)
>> -{
>> -	bdi->irq = irq_of_parse_and_map(bdi->dev->of_node, 0);
>> -	if (bdi->irq <= 0)
>> -		return -1;
>> -
>> -	return 0;
>> -}
>> -#else
>> -static int bq24190_setup_dt(struct bq24190_dev_info *bdi)
>> -{
>> -	return -1;
>> -}
>> -#endif
>
> I am adding a DT binding to this driver, using the above function. If it doesn't need the irq call,
> you can remove that. You may need to rebase on my patchset, coming next week.

The irq_of_parse_and_map() is already done by the i2c-core,
so yeah that can (and IMHO should) be removed. If you're adding
new functionality to bq24190_setup_dt() then keeping the function
around makes sense of course.

>
>> -static int bq24190_setup_pdata(struct bq24190_dev_info *bdi,
>> -		struct bq24190_platform_data *pdata)
>> -{
>> -	int ret;
>> -
>> -	if (!gpio_is_valid(pdata->gpio_int))
>> -		return -1;
>> -
>> -	ret = gpio_request(pdata->gpio_int, dev_name(bdi->dev));
>> -	if (ret < 0)
>> -		return -1;
>> -
>> -	ret = gpio_direction_input(pdata->gpio_int);
>> -	if (ret < 0)
>> -		goto out;
>> -
>> -	bdi->irq = gpio_to_irq(pdata->gpio_int);
>> -	if (!bdi->irq)
>> -		goto out;
>> -
>> -	bdi->gpio_int = pdata->gpio_int;
>> -	return 0;
>> -
>> -out:
>> -	gpio_free(pdata->gpio_int);
>> -	return -1;
>> -}
>> -
>>  static int bq24190_probe(struct i2c_client *client,
>>  		const struct i2c_device_id *id)
>>  {
>>  	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
>>  	struct device *dev = &client->dev;
>> -	struct bq24190_platform_data *pdata = client->dev.platform_data;
>>  	struct power_supply_config charger_cfg = {}, battery_cfg = {};
>>  	struct bq24190_dev_info *bdi;
>>  	int ret;
>> @@ -1372,12 +1325,7 @@ static int bq24190_probe(struct i2c_client *client,
>>
>>  	i2c_set_clientdata(client, bdi);
>>
>> -	if (dev->of_node)
>> -		ret = bq24190_setup_dt(bdi);
>
> And keep the above, adding:
> 		if (ret < 0) return ret;
>
>> -	else
>> -		ret = bq24190_setup_pdata(bdi, pdata);
>> -
>> -	if (ret) {
>> +	if (!client->irq) {
>>  		dev_err(dev, "Can't get irq info\n");
>>  		return -EINVAL;
>>  	}
>> @@ -1417,7 +1365,7 @@ static int bq24190_probe(struct i2c_client *client,
>>  		goto out3;
>>  	}
>>
>> -	ret = devm_request_threaded_irq(dev, bdi->irq, NULL,
>> +	ret = devm_request_threaded_irq(dev, client->irq, NULL,
>>  			bq24190_irq_handler_thread,
>>  			IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
>>  			"bq24190-charger", bdi);
>> @@ -1439,8 +1387,6 @@ static int bq24190_probe(struct i2c_client *client,
>>
>>  out1:
>>  	pm_runtime_disable(dev);
>> -	if (bdi->gpio_int)
>> -		gpio_free(bdi->gpio_int);
>>  	return ret;
>>  }
>>
>> @@ -1457,9 +1403,6 @@ static int bq24190_remove(struct i2c_client *client)
>>  	power_supply_unregister(bdi->charger);
>>  	pm_runtime_disable(bdi->dev);
>>
>> -	if (bdi->gpio_int)
>> -		gpio_free(bdi->gpio_int);
>> -
>>  	return 0;
>>  }
>>
>> diff --git a/include/linux/power/bq24190_charger.h b/include/linux/power/bq24190_charger.h
>> index cb49717..8d918cb 100644
>> --- a/include/linux/power/bq24190_charger.h
>> +++ b/include/linux/power/bq24190_charger.h
>> @@ -10,7 +10,6 @@
>>  #define _BQ24190_CHARGER_H_
>>
>>  struct bq24190_platform_data {
>> -	unsigned int	gpio_int;	/* GPIO pin that's connected to INT# */
>>  	bool no_register_reset;
>>  };
>
>

Regards,

Hans

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [05/15] power: supply: bq24190_charger: Limit charging voltage to 4.3V
  2017-03-18  7:10   ` [05/15] " Liam Breck
@ 2017-03-18 14:24     ` Hans de Goede
  2017-03-18 19:01       ` Liam Breck
  0 siblings, 1 reply; 90+ messages in thread
From: Hans de Goede @ 2017-03-18 14:24 UTC (permalink / raw)
  To: Liam Breck; +Cc: Andy Shevchenko, Sebastian Reichel, Tony Lindgren, linux-pm

Hi,

On 18-03-17 08:10, Liam Breck wrote:
> On Fri, 17 Mar 2017 10:55:17 +0100, Hans de Goede wrote:
>
>> When the platform data asks us to not reset the charger to its default
>> values and instead trust the firmware set values check the charging
>> voltage and clamp it to 4.304V.
>>
>> Some firmwares set really too high voltages, e.g. the GPD-win I've been
>> working on uses 4.384V. New LiHV (High Voltage) batteries may be charged
>> upto 4.35V but that significantly impacts their lifetime, limit charging
>> to 4.304V for safety and lifetime reasons.
>
> See comments on patch 04; pls specify the offending firmwares and exactly how they
> misconfigure the charger. Include URLs to datasheets, etc.

As mentioned this is a x86 machine, without any datasheets. I can add an URL to
the page describing the device. Also misconfiguring may be a bit of a strong
word, this is a LiHV battery so 4.384V is mostly fine, I would just rather
use a max charge voltage with slightly more margin.

>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>> ---
>>  drivers/power/supply/bq24190_charger.c | 27 ++++++++++++++++++++++++---
>>  1 file changed, 24 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
>> index c92a40e4..7bca8d0 100644
>> --- a/drivers/power/supply/bq24190_charger.c
>> +++ b/drivers/power/supply/bq24190_charger.c
>> @@ -504,11 +504,32 @@ static int bq24190_set_mode_host(struct bq24190_dev_info *bdi)
>>
>>  static int bq24190_register_reset(struct bq24190_dev_info *bdi)
>>  {
>> -	int ret, limit = 100;
>> +	int ret, voltage, limit = 100;
>>  	u8 v;
>>
>> -	if (bdi->pdata && bdi->pdata->no_register_reset)
>> -		return 0;
>> +	if (bdi->pdata && bdi->pdata->no_register_reset) {
>
> See comments on patch 04. Invoke this in set_mode_host() using value from settings config.

Again, this is x86, there is no settings config (or one that we can get too)
other then the one stored in the registers of the IC.

>
>> +		/*
>> +		 * We've been asked to keep the firmware settings as is, but
>> +		 * some firmwares set really too high voltages (e.g. 4.384V).
>> +		 * New LiHV (High Voltage) batteries may be charged upto 4.35V
>> +		 * but that significantly impacts their lifetime, limit
>> +		 * charging to 4.304V for safety and lifetime reasons.
>> +		 */
>
> Docs which belong in external config.

Again there is NO external config. The i2c-adapter driver which registers
the client (and passed in any config) is a generic driver for any board
using a Cherrytrail Whiskey Cove PMIC. All that the ACPI tables tell us
is that there is a Cherrytrail Whiskey Cove PMIC and matching fuel-gauge,
for anything else we are on our own.


>
>> +		ret = bq24190_get_field_val(bdi, BQ24190_REG_CVC,
>> +			BQ24190_REG_CVC_VREG_MASK, BQ24190_REG_CVC_VREG_SHIFT,
>> +			bq24190_cvc_vreg_values,
>> +			ARRAY_SIZE(bq24190_cvc_vreg_values), &voltage);
>> +		if (ret < 0)
>> +			return ret;
>> +
>> +		if (voltage <= 4304000)
>> +			return 0;
>
> The limit value should come from settings config.

See above.

>
>> +		return bq24190_set_field_val(bdi, BQ24190_REG_CVC,
>> +			BQ24190_REG_CVC_VREG_MASK, BQ24190_REG_CVC_VREG_SHIFT,
>> +			bq24190_cvc_vreg_values,
>> +			ARRAY_SIZE(bq24190_cvc_vreg_values), 4304000);
>> +	}
>>
>>  	/* Reset the registers */
>>  	ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
>

Regards,

Hans

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [07/15] power: supply: bq24190_charger: Add support for bq24192[i]
  2017-03-18  7:10   ` [07/15] " Liam Breck
@ 2017-03-18 14:30     ` Hans de Goede
  2017-03-18 19:10       ` Liam Breck
  0 siblings, 1 reply; 90+ messages in thread
From: Hans de Goede @ 2017-03-18 14:30 UTC (permalink / raw)
  To: Liam Breck; +Cc: Andy Shevchenko, Sebastian Reichel, Tony Lindgren, linux-pm

Hi,

On 18-03-17 08:10, Liam Breck wrote:
> On Fri, 17 Mar 2017 10:55:19 +0100, Hans de Goede wrote:
>
>> The bq24192 and bq24192i are mostly identical to the bq24190, TI even
>> published a single datasheet for all 3 of them. The difference
>> between the bq24190 and bq24192[i] is the way charger-type detection
>> is done, the bq24190 is to be directly connected to the USB a/b lines,
>> where as the the bq24192[i] has a gpio which should be driven high/low
>> externally depending on the type of charger connected, from a register
>> level access pov there is no difference.
>>
>> The differences between the bq24192 and bq24192i are:
>> 1) Lower default charge rate on the bq24192i
>> 2) Pre-charge-current can be max 640 mA on the bq24192i
>>
>> Since we do not provide an API for setting the pre-charge-current,
>> these differences can be ignored and we can simply use the existing
>> code as-is with the bq24192 and bq24192i.
>
> FYI, coming patchset will set pre- and termination-charge current via DT.

Ok, note that this again is something which we cannot do on x86,
so we need to retain the BIOS set values there. I assume this will
not be a problem since you will need to keep the driver working
with device-trees which do not specify this info, for compatibility
with existing devicetrees.


>
>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>> ---
>>  drivers/power/supply/bq24190_charger.c | 12 ++++++++++--
>>  1 file changed, 10 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
>> index 9c4b171..9014dee 100644
>> --- a/drivers/power/supply/bq24190_charger.c
>> +++ b/drivers/power/supply/bq24190_charger.c
>> @@ -1275,7 +1275,14 @@ static int bq24190_hw_init(struct bq24190_dev_info *bdi)
>>  	if (ret < 0)
>>  		goto out;
>>
>> -	if (v != bdi->model) {
>> +	switch (v) {
>> +	case BQ24190_REG_VPRS_PN_24190:
>> +	case BQ24190_REG_VPRS_PN_24192:
>> +	case BQ24190_REG_VPRS_PN_24192I:
>> +		bdi->model = v;
>
> We should set model in probe(). Doesn't the previous code still work?

On x86 we know we have a variant but not which variant, since the
driver supports all variants we can simply make the driver flexible
enough to handle all variants and be done with it.

>
>> +		break;
>> +	default:
>> +		dev_err(bdi->dev, "Error unknown model: 0x%02x\n", v);
>
> Feel free to add the error msg.
>
>>  		ret = -ENODEV;
>>  		goto out;
>>  	}
>> @@ -1316,7 +1323,6 @@ static int bq24190_probe(struct i2c_client *client,
>>
>>  	bdi->client = client;
>>  	bdi->dev = dev;
>> -	bdi->model = id->driver_data;
>
> Is driver_data no longer always correct?

See above, I was actually planning on dropping the
setting of driver_data from the ids tables, but I forgot.

>
>>  	bdi->pdata = client->dev.platform_data;
>>  	strncpy(bdi->model_name, id->name, I2C_NAME_SIZE);
>>  	mutex_init(&bdi->f_reg_lock);
>> @@ -1450,6 +1456,8 @@ static SIMPLE_DEV_PM_OPS(bq24190_pm_ops, bq24190_pm_suspend, bq24190_pm_resume);
>>   */
>>  static const struct i2c_device_id bq24190_i2c_ids[] = {
>>  	{ "bq24190", BQ24190_REG_VPRS_PN_24190 },
>> +	{ "bq24192", BQ24190_REG_VPRS_PN_24192 },
>> +	{ "bq24192i", BQ24190_REG_VPRS_PN_24192I },
>
> This may be the only essential change.

See above, actually this should have been:

static const struct i2c_device_id bq24190_i2c_ids[] = {
  	{ "bq24190" },
	{ "bq24192" },
	{ "bq24192i" },
	{ },
};

Or (also works for me): just:

static const struct i2c_device_id bq24190_i2c_ids[] = {
  	{ "bq24190" },
	{ },	
};

And use the same compatible for all variants as they are
all compatible anyways.

Regards,

Hans

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [08/15] power: supply: bq24190_charger: Add support for external fuel gauge
  2017-03-18  7:10   ` [08/15] " Liam Breck
@ 2017-03-18 14:31     ` Hans de Goede
  2017-03-18 19:18       ` Liam Breck
  0 siblings, 1 reply; 90+ messages in thread
From: Hans de Goede @ 2017-03-18 14:31 UTC (permalink / raw)
  To: Liam Breck; +Cc: Andy Shevchenko, Sebastian Reichel, Tony Lindgren, linux-pm

Hi,

On 18-03-17 08:10, Liam Breck wrote:
> On Fri, 17 Mar 2017 10:55:20 +0100, Hans de Goede wrote:
>
>> Some platforms with a bq24190_charger have an external fuel gauge which
>> makes it possible to reliably report battery (dis)charge state, at
>> support for this by adding an optional get_ext_bat_property callback
>> to the platform_data and using this if the platform provides it.
>
> Please do not pollute the charger with fuel-gauge functionality; use the gauge driver directly.

That is not how the userspace ABI works, the userspace ABI says one
battery one power_supply device, so we need to combine the data from
the 2 sources.

> And calling into a mystery module with a pointer from platform-data is scary! St. Patrick's
> Day is wrong for this; try April Fool's or Halloween ;-)

Since we control both the caller and the callee I fail to see how
this is scary in any way.

Regards,

Hans


>
>> By convention the callback will return -ENXIO when it is not ready yet,
>> or the driver providing it has been unbound from its device. Since it
>> returns the same error when unbound it cannot return -EPROBE_DEFER
>> as that is not a valid errno.
>>
>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>> ---
>>  drivers/power/supply/bq24190_charger.c | 41 +++++++++++++++++++++++++++++++---
>>  include/linux/power/bq24190_charger.h  |  4 ++++
>>  2 files changed, 42 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
>> index 9014dee..9fe69a5 100644
>> --- a/drivers/power/supply/bq24190_charger.c
>> +++ b/drivers/power/supply/bq24190_charger.c
>> @@ -1111,7 +1111,10 @@ static int bq24190_battery_get_property(struct power_supply *psy,
>>  		ret = 0;
>>  		break;
>>  	default:
>> -		ret = -ENODATA;
>> +		if (bdi->pdata && bdi->pdata->get_ext_bat_property)
>> +			ret = bdi->pdata->get_ext_bat_property(psp, val);
>> +		else
>> +			ret = -ENODATA;
>>  	}
>>
>>  	pm_runtime_put_sync(bdi->dev);
>> @@ -1168,12 +1171,31 @@ static enum power_supply_property bq24190_battery_properties[] = {
>>  	POWER_SUPPLY_PROP_TECHNOLOGY,
>>  	POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
>>  	POWER_SUPPLY_PROP_SCOPE,
>> +	/* Begin of extended battery properties */
>> +	POWER_SUPPLY_PROP_VOLTAGE_NOW,
>> +	POWER_SUPPLY_PROP_VOLTAGE_AVG,
>> +	POWER_SUPPLY_PROP_VOLTAGE_OCV,
>> +	POWER_SUPPLY_PROP_CURRENT_NOW,
>> +	POWER_SUPPLY_PROP_CURRENT_AVG,
>> +	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
>> +	POWER_SUPPLY_PROP_CHARGE_FULL,
>> +	POWER_SUPPLY_PROP_CHARGE_NOW,
>>  };
>>
>>  static const struct power_supply_desc bq24190_battery_desc = {
>>  	.name			= "bq24190-battery",
>>  	.type			= POWER_SUPPLY_TYPE_BATTERY,
>>  	.properties		= bq24190_battery_properties,
>> +	.num_properties		= 6,
>> +	.get_property		= bq24190_battery_get_property,
>> +	.set_property		= bq24190_battery_set_property,
>> +	.property_is_writeable	= bq24190_battery_property_is_writeable,
>> +};
>> +
>> +static const struct power_supply_desc bq24190_ext_battery_desc = {
>> +	.name			= "bq24190-battery",
>> +	.type			= POWER_SUPPLY_TYPE_BATTERY,
>> +	.properties		= bq24190_battery_properties,
>>  	.num_properties		= ARRAY_SIZE(bq24190_battery_properties),
>>  	.get_property		= bq24190_battery_get_property,
>>  	.set_property		= bq24190_battery_set_property,
>> @@ -1336,6 +1358,15 @@ static int bq24190_probe(struct i2c_client *client,
>>  		return -EINVAL;
>>  	}
>>
>> +	if (bdi->pdata && bdi->pdata->get_ext_bat_property) {
>> +		union power_supply_propval val;
>> +
>> +		/* Check external fuel gauge is ready */
>> +		ret = bdi->pdata->get_ext_bat_property(0, &val);
>> +		if (ret == -ENXIO)
>> +			return -EPROBE_DEFER;
>> +	}
>> +
>>  	pm_runtime_enable(dev);
>>  	pm_runtime_resume(dev);
>>
>> @@ -1357,8 +1388,12 @@ static int bq24190_probe(struct i2c_client *client,
>>  	}
>>
>>  	battery_cfg.drv_data = bdi;
>> -	bdi->battery = power_supply_register(dev, &bq24190_battery_desc,
>> -						&battery_cfg);
>> +	if (bdi->pdata && bdi->pdata->get_ext_bat_property)
>> +		bdi->battery = power_supply_register(dev,
>> +				    &bq24190_ext_battery_desc, &battery_cfg);
>> +	else
>> +		bdi->battery = power_supply_register(dev,
>> +				    &bq24190_battery_desc, &battery_cfg);
>>  	if (IS_ERR(bdi->battery)) {
>>  		dev_err(dev, "Can't register battery\n");
>>  		ret = PTR_ERR(bdi->battery);
>> diff --git a/include/linux/power/bq24190_charger.h b/include/linux/power/bq24190_charger.h
>> index 8d918cb..02d248b 100644
>> --- a/include/linux/power/bq24190_charger.h
>> +++ b/include/linux/power/bq24190_charger.h
>> @@ -9,8 +9,12 @@
>>  #ifndef _BQ24190_CHARGER_H_
>>  #define _BQ24190_CHARGER_H_
>>
>> +#include <linux/power_supply.h>
>> +
>>  struct bq24190_platform_data {
>>  	bool no_register_reset;
>> +	int (*get_ext_bat_property)(enum power_supply_property prop,
>> +				    union power_supply_propval *val);
>>  };
>>
>>  #endif
>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [09/15] power: supply: bq24190_charger: Add voltage_max_design prop to battery
  2017-03-18  7:10   ` [09/15] " Liam Breck
@ 2017-03-18 14:34     ` Hans de Goede
  2017-03-18 19:34       ` Liam Breck
  0 siblings, 1 reply; 90+ messages in thread
From: Hans de Goede @ 2017-03-18 14:34 UTC (permalink / raw)
  To: Liam Breck; +Cc: Andy Shevchenko, Sebastian Reichel, Tony Lindgren, linux-pm

Hi,

On 18-03-17 08:10, Liam Breck wrote:
> On Fri, 17 Mar 2017 10:55:21 +0100, Hans de Goede wrote:
>
>> When combined with an external fuel-gauge, upower needs voltage_max_design
>> as it internally does all its calculations in Watts and converts the
>> charge_foo properties from A to Watts by using voltage_max_design.
>
> This is a battery characteristic which should be obtained from the fuel gauge (e.g. V at charge
> termination)

V at charge termination is *exactly* what bq24190_charger_get_voltage()
returns. And the fuel-gauge only measures charging it does not control
it, so unless we had some nvram to store things in over time the fg
driver cannot no what "V at charge termination" will be, where as the
bq24190_charger code actually knows as it controls at which voltage
the charger switches from constant current to constant voltage mode.

> or external battery config.
>
> See also https://patchwork.kernel.org/patch/9626487/

There is no external battery config on x86.

Regards,

Hans

>
>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>> ---
>>  drivers/power/supply/bq24190_charger.c | 10 +++++++++-
>>  1 file changed, 9 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
>> index 9fe69a5..82cb33d 100644
>> --- a/drivers/power/supply/bq24190_charger.c
>> +++ b/drivers/power/supply/bq24190_charger.c
>> @@ -1103,6 +1103,13 @@ static int bq24190_battery_get_property(struct power_supply *psy,
>>  		val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
>>  		ret = 0;
>>  		break;
>> +	case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
>> +		/*
>> +		 * Report charger configured voltage as max design voltage,
>> +		 * not entirely correct, but userspace needs something here.
>> +		 */
>> +		ret = bq24190_charger_get_voltage(bdi, val);
>> +		break;
>>  	case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
>>  		ret = bq24190_battery_get_temp_alert_max(bdi, val);
>>  		break;
>> @@ -1169,6 +1176,7 @@ static enum power_supply_property bq24190_battery_properties[] = {
>>  	POWER_SUPPLY_PROP_HEALTH,
>>  	POWER_SUPPLY_PROP_ONLINE,
>>  	POWER_SUPPLY_PROP_TECHNOLOGY,
>> +	POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
>>  	POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
>>  	POWER_SUPPLY_PROP_SCOPE,
>>  	/* Begin of extended battery properties */
>> @@ -1186,7 +1194,7 @@ static const struct power_supply_desc bq24190_battery_desc = {
>>  	.name			= "bq24190-battery",
>>  	.type			= POWER_SUPPLY_TYPE_BATTERY,
>>  	.properties		= bq24190_battery_properties,
>> -	.num_properties		= 6,
>> +	.num_properties		= 7,
>>  	.get_property		= bq24190_battery_get_property,
>>  	.set_property		= bq24190_battery_set_property,
>>  	.property_is_writeable	= bq24190_battery_property_is_writeable,

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [10/15] power: supply: bq24190_charger: Use extcon to determine ilimit, 5v boost
  2017-03-18  7:10   ` [10/15] " Liam Breck
@ 2017-03-18 14:42     ` Hans de Goede
  2017-03-18 19:57       ` Liam Breck
  0 siblings, 1 reply; 90+ messages in thread
From: Hans de Goede @ 2017-03-18 14:42 UTC (permalink / raw)
  To: Liam Breck; +Cc: Andy Shevchenko, Sebastian Reichel, Tony Lindgren, linux-pm

Hi,

On 18-03-17 08:10, Liam Breck wrote:
> Tony, question for you below...
>
> On Fri, 17 Mar 2017 10:55:22 +0100, Hans de Goede wrote:
>
>> Add support for monitoring an extcon device with SDP/CDP/DCP and HOST
>
> insert: USB X.0
>
>> cables and adjust ilimit and enable/disable the 5v boost converter
>> accordingly. This is necessary on systems where the PSEL pin is hardwired
>> high and ILIM needs to be set by software based on the detected charger
>> type.
>
> This description is rather thin for the extent of the changes. What specific systems
> require this?

Systems which use a variant with a PSEL pin where the PSEL pin is hardwired
high.

> What drivers generate the event?

The driver which registers the extcon with the name "extcon_name"
the bq24190_charger driver really does not need to know more.
In the use-case we are talking about now the driver is
the new extcon-cht-wc.c driver which is part of the patch-set
as I initially posted it.

> Also provide URLs to docs/datasheets.

I've no access to docs / datasheets for the Whiskey Cove PMIC.



>
>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>> ---
>>  drivers/power/supply/Kconfig           |  1 +
>>  drivers/power/supply/bq24190_charger.c | 85 ++++++++++++++++++++++++++++++++++
>>  include/linux/power/bq24190_charger.h  |  1 +
>>  3 files changed, 87 insertions(+)
>>
>> diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
>> index f8b6e64..fd93110 100644
>> --- a/drivers/power/supply/Kconfig
>> +++ b/drivers/power/supply/Kconfig
>> @@ -442,6 +442,7 @@ config CHARGER_BQ2415X
>>  config CHARGER_BQ24190
>>  	tristate "TI BQ24190 battery charger driver"
>>  	depends on I2C
>> +	depends on EXTCON
>>  	depends on GPIOLIB || COMPILE_TEST
>>  	help
>>  	  Say Y to enable support for the TI BQ24190 battery charger.
>> diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
>> index 82cb33d..03990e2 100644
>> --- a/drivers/power/supply/bq24190_charger.c
>> +++ b/drivers/power/supply/bq24190_charger.c
>> @@ -11,10 +11,12 @@
>>  #include <linux/module.h>
>>  #include <linux/interrupt.h>
>>  #include <linux/delay.h>
>> +#include <linux/extcon.h>
>>  #include <linux/of_irq.h>
>>  #include <linux/of_device.h>
>>  #include <linux/pm_runtime.h>
>>  #include <linux/power_supply.h>
>> +#include <linux/workqueue.h>
>>  #include <linux/gpio.h>
>>  #include <linux/i2c.h>
>>
>> @@ -39,6 +41,8 @@
>>  #define BQ24190_REG_POC_WDT_RESET_SHIFT		6
>>  #define BQ24190_REG_POC_CHG_CONFIG_MASK		(BIT(5) | BIT(4))
>>  #define BQ24190_REG_POC_CHG_CONFIG_SHIFT	4
>> +#define BQ24190_REG_POC_CHG_CONFIG_CHARGE	1
>> +#define BQ24190_REG_POC_CHG_CONFIG_OTG		2
>>  #define BQ24190_REG_POC_SYS_MIN_MASK		(BIT(3) | BIT(2) | BIT(1))
>>  #define BQ24190_REG_POC_SYS_MIN_SHIFT		1
>>  #define BQ24190_REG_POC_BOOST_LIM_MASK		BIT(0)
>> @@ -152,6 +156,9 @@ struct bq24190_dev_info {
>>  	struct power_supply		*charger;
>>  	struct power_supply		*battery;
>>  	struct bq24190_platform_data	*pdata;
>> +	struct extcon_dev		*extcon;
>> +	struct notifier_block		extcon_nb;
>> +	struct work_struct		extcon_work;
>>  	char				model_name[I2C_NAME_SIZE];
>>  	kernel_ulong_t			model;
>>  	struct mutex			f_reg_lock;
>> @@ -167,6 +174,11 @@ struct bq24190_dev_info {
>>   * number at that index in the array is the real-world value that it
>>   * represents.
>>   */
>> +
>> +/* REG00[2:0] (IINLIM) in uAh */
>> +static const int bq24190_iinlim_values[] = {
>> +	100000, 150000, 500000, 900000, 1200000, 1500000, 2000000, 3000000 };
>> +
>>  /* REG02[7:2] (ICHG) in uAh */
>>  static const int bq24190_ccc_ichg_values[] = {
>>  	 512000,  576000,  640000,  704000,  768000,  832000,  896000,  960000,
>> @@ -1290,6 +1302,61 @@ static irqreturn_t bq24190_irq_handler_thread(int irq, void *data)
>>  	return IRQ_HANDLED;
>>  }
>>
>> +static void bq24190_extcon_work(struct work_struct *work)
>> +{
>
> Does this need pm_runtime_get_sync(), etc?
> (See linux-next patches to driver.)

Yes with runtime pm this will need to do a
pm_runtime_get_sync(bdi->Dev) before accessing
the device.



>
>> +	struct bq24190_dev_info *bdi =
>> +		container_of(work, struct bq24190_dev_info, extcon_work);
>> +	int ret, iinlim = 0;
>> +
>> +	if (extcon_get_state(bdi->extcon, EXTCON_CHG_USB_SDP) == 1)
>> +		iinlim = 500000;
>> +	else if (extcon_get_state(bdi->extcon, EXTCON_CHG_USB_CDP) == 1 ||
>> +		 extcon_get_state(bdi->extcon, EXTCON_CHG_USB_ACA) == 1)
>> +		iinlim = 1500000;
>> +	else if (extcon_get_state(bdi->extcon, EXTCON_CHG_USB_DCP) == 1)
>> +		iinlim = 2000000;
>> +
>> +	if (iinlim) {
>> +		ret = bq24190_set_field_val(bdi, BQ24190_REG_ISC,
>> +				BQ24190_REG_ISC_IINLIM_MASK,
>> +				BQ24190_REG_ISC_IINLIM_SHIFT,
>> +				bq24190_iinlim_values,
>> +				ARRAY_SIZE(bq24190_iinlim_values),
>> +				iinlim);
>> +		if (ret)
>> +			dev_err(bdi->dev, "Can't set IINLIM: %d\n", ret);
>> +	}
>> +
>> +	/*
>> +	 * If no charger has been detected and host mode is requested, activate
>> +	 * the 5V boost converter, otherwise deactivate it.
>> +	 */
>> +	if (!iinlim && extcon_get_state(bdi->extcon, EXTCON_USB_HOST) == 1) {
>> +		ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
>> +					 BQ24190_REG_POC_CHG_CONFIG_MASK,
>> +					 BQ24190_REG_POC_CHG_CONFIG_SHIFT,
>> +					 BQ24190_REG_POC_CHG_CONFIG_OTG);
>> +	} else {
>> +		ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
>> +					 BQ24190_REG_POC_CHG_CONFIG_MASK,
>> +					 BQ24190_REG_POC_CHG_CONFIG_SHIFT,
>> +					 BQ24190_REG_POC_CHG_CONFIG_CHARGE);
>> +	}
>> +	if (ret)
>> +		dev_err(bdi->dev, "Can't set CHG_CONFIG: %d\n", ret);
>> +}
>> +
>> +static int bq24190_extcon_event(struct notifier_block *nb, unsigned long event,
>> +				void *param)
>> +{
>> +	struct bq24190_dev_info *bdi =
>> +		container_of(nb, struct bq24190_dev_info, extcon_nb);
>> +
>> +	schedule_work(&bdi->extcon_work);
>> +
>> +	return NOTIFY_OK;
>> +}
>> +
>>  static int bq24190_hw_init(struct bq24190_dev_info *bdi)
>>  {
>>  	u8 v;
>> @@ -1375,6 +1442,12 @@ static int bq24190_probe(struct i2c_client *client,
>>  			return -EPROBE_DEFER;
>>  	}
>>
>> +	if (bdi->pdata && bdi->pdata->extcon_name) {
>
> Verify that extcon_name has an expected value?

The whole idea is that the bq24190 does not need to care about
which extcon driver it is told to use, just that it has to
use *a* extcon driver.

>
>> +		bdi->extcon = extcon_get_extcon_dev(bdi->pdata->extcon_name);
>> +		if (!bdi->extcon)
>> +			return -EPROBE_DEFER;
>
> dev_info() a msg about this linkage, including info about the other side.

dev_info on success I assume, not on PROBE_DEFER, otherwise we will
end up spamming the log quite a lot while modules are loading.



>
>> +	}
>> +
>>  	pm_runtime_enable(dev);
>>  	pm_runtime_resume(dev);
>>
>> @@ -1423,6 +1496,18 @@ static int bq24190_probe(struct i2c_client *client,
>>  		goto out4;
>>  	}
>>
>> +	if (bdi->extcon) {
>> +		INIT_WORK(&bdi->extcon_work, bq24190_extcon_work);
>> +		bdi->extcon_nb.notifier_call = bq24190_extcon_event;
>> +		ret = devm_extcon_register_notifier(dev, bdi->extcon, -1,
>> +						    &bdi->extcon_nb);
>> +		if (ret)
>> +			goto out4;
>> +
>> +		/* Sync initial cable state */
>> +		schedule_work(&bdi->extcon_work);
>> +	}
>> +
>>  	return 0;
>>
>>  out4:
>> diff --git a/include/linux/power/bq24190_charger.h b/include/linux/power/bq24190_charger.h
>> index 02d248b..909c5b9 100644
>> --- a/include/linux/power/bq24190_charger.h
>> +++ b/include/linux/power/bq24190_charger.h
>> @@ -13,6 +13,7 @@
>>
>>  struct bq24190_platform_data {
>>  	bool no_register_reset;
>> +	const char *extcon_name;
>>  	int (*get_ext_bat_property)(enum power_supply_property prop,
>>  				    union power_supply_propval *val);
>>  };
>

Regards,

Hans

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [04/15] power: supply: bq24190_charger: Add no_register_reset pdata flag
  2017-03-18 14:13     ` Hans de Goede
@ 2017-03-18 18:51       ` Liam Breck
  2017-03-18 22:51         ` Hans de Goede
  0 siblings, 1 reply; 90+ messages in thread
From: Liam Breck @ 2017-03-18 18:51 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Andy Shevchenko, Sebastian Reichel, Tony Lindgren, linux-pm, Liam Breck

On Sat, Mar 18, 2017 at 7:13 AM, Hans de Goede <hdegoede@redhat.com> wrote:
> Hi,
>
> On 18-03-17 08:10, Liam Breck wrote:
>>
>> [dropped CC's not relevant to BQ24190; pls re-add anyone appropriate]
>>
>> Hi Hans,
>>
>> I am the de facto maintainer of BQ24190, with help from Tony. I contracted
>> the original author to
>> create the driver. I'm not aware of anyone else relying on it at present.
>
>
> Hi Liam, nice to meet you.
>
>> Pls rebase to -next (!) and post BQ24190 changes in a separate patchset.
>
>
> Ok, I will rebase these patches on top of
> https://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply.git/log/?h=for-next

Yep.

>> Reference any
>>
>> dependencies in other patchsets with Depends-on lines in patch
>> descriptions linking to
>> patchwork.kernel.org. If any dependency might be controversial, pls defer
>> the BQ24190 patchset til
>> controversy resolves.
>
> There are no dependencies for the BQ24190 patches, they are a dependency for
> some of the other changes but they can go upstream as is.

The extcon driver elsewhere in patchset?

>> You may be interested in these, which I will support in BQ24190 in near
>> future:
>> https://patchwork.kernel.org/patch/9626487/
>> https://patchwork.kernel.org/patch/9626491/
>
>
> Yeah those are not going to matter for the use-case I'm looking at.
> I've a feeling you've only looked at the bq24190 patches and not the
> rest of the set. There is a reason I posted these all together as I
> mentioned in the cover-letter:
>
> "I'm sending this as a single series so that people can see how all the bits
> fit together."

Reading the entire patchset may be a lot to ask some folks, altho I
did. It's best to give relevant background in each patch description.

> Anyways I will try to clarify things by answering you questions /
> responding to your remarks.
>
>> Further comments below...
>>
>> On Fri, 17 Mar 2017 10:55:16 +0100, Hans de Goede wrote:
>>
>>> On some platforms the register have been setup with platform specific
>>> values by the firmware and should not be reset.
>>
>>
>> Pls describe this mysterious, meddling firmware. Who wrote it, when does
>> it run, on what devices,
>> etc? Include URLs to docs, etc. BTW it's not really "firmware" if it runs
>> on the main cpu, IMO.
>> A boot loader is not firmware.
>
>
> So not all the world runs on ARM and not all devices using the
> TI BQ24190 (and variants) use an ARM processor or devicetree
> for that matter). Having worked on both ARM and x86 quite a bit
> I've a feeling that you are approaching my patchset with somewhat
> of an ARM focussed pov.
>
> The primary device I'm trying to get battery/charger monitoring
> working for is the GPDwin: http://www.gpd.hk/gpdwin.asp
>
> Which is an Intel Cherrytrail using machine with an Intel
> Cherrytrail Whiskey Cove PMIC.
>
> The firmware I'm talking about here is the EFI system firmware
> which boots the machine aka the BIOS.

Mention all of the above in patch descriptions.

>> We probably don't want to disable register_reset in all circumstances. Can
>> you record the
>> firmware's settings for charger?
>
>
> Yes after a (re)boot they are always reset to the same values.

So record those settings in a platform_data field. That's your
external config in this case.

The driver does a register_reset on resume so it has a consistent
state with chip.

>> I suspect we should replay them in set_mode_host() -- to be
>> renamed set_operating_params in forthcoming patchset.
>
>
> That is not going to work, the Cherrytrail Whiskey Cove PMIC
> is used on many different boards and there is no way to get
> the info from the firmware other then reading it back from
> the chip, hence the no_register_reset flag.

This isn't about the PMIC. You need to know how boot code for a
certain device configures the charger. Encode that knowledge in
platform_data. Also have you asked the vendor for docs?

>> What generates your platform_data objects?
>
>
> The last patch in the patch-set shows this. The
> Cherrytrail Whiskey Cove PMIC does charger type detection
> and has a fuelgauge, but it does not contain a battery
> charger itself. Instead it contains an i2c controller
> to which an external charger chip, one of the
> TI BQ24190 variants, gets connected.

More useful background for patch descriptions :-)

Given that design, it sounds like the PMIC driver should be the point
of contact with userspace, and use sysfs
(/sys/class/power_supply/bq24190-charger/f_*) to get/set charger
stats. We can amend the driver to extend that feature. (Also a good
way to test chip knobs.)

Some TI fuel gauges also work this way - I2C link to external charger.

> The driver for this i2c-controller calls i2c_new_device
> with i2c_board_info describing the BQ24190 charger
> after calling i2c_add_adapter().
>
>> Are you forced to use platform_data for some reason?
>
>
> Since this is info being passed around inside the kernel
> using platform_data is a hell of a lot simpler (and cleaner
> no need to check types, etc on the receiving side) then
> using device-properties. Device-properties are nice when
> getting info from firmware, but this is not that.

OK

> Also one of the things passed is actually a function
> pointer to a function to get extra power_supply_properties
> from the fuel-gauge, and passing function pointers certainly
> is not something which should be done through device-props.
>
>>
>>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>>
>>
>> Add to all BQ24190 patches:
>> Cc: Liam Breck <kernel@networkimprov.net>
>> Cc: Tony Lindgren <tony@atomide.com>
>>
>> Pls don't CC me on the related patchsets.
>>
>>> ---
>>>  drivers/power/supply/bq24190_charger.c | 5 +++++
>>>  include/linux/power/bq24190_charger.h  | 1 +
>>>  2 files changed, 6 insertions(+)
>>>
>>> diff --git a/drivers/power/supply/bq24190_charger.c
>>> b/drivers/power/supply/bq24190_charger.c
>>> index a4f0849..c92a40e4 100644
>>> --- a/drivers/power/supply/bq24190_charger.c
>>> +++ b/drivers/power/supply/bq24190_charger.c
>>> @@ -151,6 +151,7 @@ struct bq24190_dev_info {
>>>         struct device                   *dev;
>>>         struct power_supply             *charger;
>>>         struct power_supply             *battery;
>>> +       struct bq24190_platform_data    *pdata;
>>
>>
>> Use a register settings array/struct here, instead of platform-data. None
>> of your other patches need
>> to retain pdata.
>
>
> Sure I can make a 1:1 copy of each field in pdata here, but that
> is just more lines of code for the same result.

I mean record the chip's UEFI-supplied state here. Currently
no_register_reset appears to be the only pdata field used after
probe()

>>
>>>         char                            model_name[I2C_NAME_SIZE];
>>>         kernel_ulong_t                  model;
>>>         unsigned int                    gpio_int;
>>> @@ -506,6 +507,9 @@ static int bq24190_register_reset(struct
>>> bq24190_dev_info *bdi)
>>>         int ret, limit = 100;
>>>         u8 v;
>>>
>>> +       if (bdi->pdata && bdi->pdata->no_register_reset)
>>> +               return 0;
>>> +
>>>         /* Reset the registers */
>>>         ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
>>>                         BQ24190_REG_POC_RESET_MASK,
>>> @@ -1339,6 +1343,7 @@ static int bq24190_probe(struct i2c_client *client,
>>>         bdi->client = client;
>>>         bdi->dev = dev;
>>>         bdi->model = id->driver_data;
>>> +       bdi->pdata = client->dev.platform_data;
>>>         strncpy(bdi->model_name, id->name, I2C_NAME_SIZE);
>>>         mutex_init(&bdi->f_reg_lock);
>>>         bdi->f_reg = 0;
>>> diff --git a/include/linux/power/bq24190_charger.h
>>> b/include/linux/power/bq24190_charger.h
>>> index 9f02837..cb49717 100644
>>> --- a/include/linux/power/bq24190_charger.h
>>> +++ b/include/linux/power/bq24190_charger.h
>>> @@ -11,6 +11,7 @@
>>>
>>>  struct bq24190_platform_data {
>>>         unsigned int    gpio_int;       /* GPIO pin that's connected to
>>> INT# */
>>> +       bool no_register_reset;
>>>  };
>>>
>>>  #endif
>>
>>
>> Thanks,
>> Liam
>>
>
> Regards,
>
> Hans

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [05/15] power: supply: bq24190_charger: Limit charging voltage to 4.3V
  2017-03-18 14:24     ` Hans de Goede
@ 2017-03-18 19:01       ` Liam Breck
  0 siblings, 0 replies; 90+ messages in thread
From: Liam Breck @ 2017-03-18 19:01 UTC (permalink / raw)
  To: Hans de Goede; +Cc: Andy Shevchenko, Sebastian Reichel, Tony Lindgren, linux-pm

On Sat, Mar 18, 2017 at 7:24 AM, Hans de Goede <hdegoede@redhat.com> wrote:
> Hi,
>
> On 18-03-17 08:10, Liam Breck wrote:
>>
>> On Fri, 17 Mar 2017 10:55:17 +0100, Hans de Goede wrote:
>>
>>> When the platform data asks us to not reset the charger to its default
>>> values and instead trust the firmware set values check the charging
>>> voltage and clamp it to 4.304V.
>>>
>>> Some firmwares set really too high voltages, e.g. the GPD-win I've been
>>> working on uses 4.384V. New LiHV (High Voltage) batteries may be charged
>>> upto 4.35V but that significantly impacts their lifetime, limit charging
>>> to 4.304V for safety and lifetime reasons.
>>
>>
>> See comments on patch 04; pls specify the offending firmwares and exactly
>> how they
>> misconfigure the charger. Include URLs to datasheets, etc.
>
>
> As mentioned this is a x86 machine, without any datasheets. I can add an URL
> to
> the page describing the device. Also misconfiguring may be a bit of a strong
> word, this is a LiHV battery so 4.384V is mostly fine, I would just rather
> use a max charge voltage with slightly more margin.

You can also ask for docs, and cut/paste sections, if not in Cantonese :-)

>>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>>> ---
>>>  drivers/power/supply/bq24190_charger.c | 27 ++++++++++++++++++++++++---
>>>  1 file changed, 24 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/power/supply/bq24190_charger.c
>>> b/drivers/power/supply/bq24190_charger.c
>>> index c92a40e4..7bca8d0 100644
>>> --- a/drivers/power/supply/bq24190_charger.c
>>> +++ b/drivers/power/supply/bq24190_charger.c
>>> @@ -504,11 +504,32 @@ static int bq24190_set_mode_host(struct
>>> bq24190_dev_info *bdi)
>>>
>>>  static int bq24190_register_reset(struct bq24190_dev_info *bdi)
>>>  {
>>> -       int ret, limit = 100;
>>> +       int ret, voltage, limit = 100;
>>>         u8 v;
>>>
>>> -       if (bdi->pdata && bdi->pdata->no_register_reset)
>>> -               return 0;
>>> +       if (bdi->pdata && bdi->pdata->no_register_reset) {
>>
>>
>> See comments on patch 04. Invoke this in set_mode_host() using value from
>> settings config.
>
>
> Again, this is x86, there is no settings config (or one that we can get too)
> other then the one stored in the registers of the IC.

Addressed on patch 04 discussion.

>>
>>> +               /*
>>> +                * We've been asked to keep the firmware settings as is,
>>> but
>>> +                * some firmwares set really too high voltages (e.g.
>>> 4.384V).
>>> +                * New LiHV (High Voltage) batteries may be charged upto
>>> 4.35V
>>> +                * but that significantly impacts their lifetime, limit
>>> +                * charging to 4.304V for safety and lifetime reasons.
>>> +                */
>>
>>
>> Docs which belong in external config.
>
>
> Again there is NO external config. The i2c-adapter driver which registers
> the client (and passed in any config) is a generic driver for any board
> using a Cherrytrail Whiskey Cove PMIC. All that the ACPI tables tell us
> is that there is a Cherrytrail Whiskey Cove PMIC and matching fuel-gauge,
> for anything else we are on our own.

External config is platform_data. Put this comment above your
platform_data instance. Include the limit value in it.

But first consider making the fuel-gauge the envoy to userspace as
discussed in patch 04.

>>
>>> +               ret = bq24190_get_field_val(bdi, BQ24190_REG_CVC,
>>> +                       BQ24190_REG_CVC_VREG_MASK,
>>> BQ24190_REG_CVC_VREG_SHIFT,
>>> +                       bq24190_cvc_vreg_values,
>>> +                       ARRAY_SIZE(bq24190_cvc_vreg_values), &voltage);
>>> +               if (ret < 0)
>>> +                       return ret;
>>> +
>>> +               if (voltage <= 4304000)
>>> +                       return 0;
>>
>>
>> The limit value should come from settings config.
>
>
> See above.
>
>>
>>> +               return bq24190_set_field_val(bdi, BQ24190_REG_CVC,
>>> +                       BQ24190_REG_CVC_VREG_MASK,
>>> BQ24190_REG_CVC_VREG_SHIFT,
>>> +                       bq24190_cvc_vreg_values,
>>> +                       ARRAY_SIZE(bq24190_cvc_vreg_values), 4304000);
>>> +       }
>>>
>>>         /* Reset the registers */
>>>         ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
>>
>>
>
> Regards,
>
> Hans

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [07/15] power: supply: bq24190_charger: Add support for bq24192[i]
  2017-03-18 14:30     ` Hans de Goede
@ 2017-03-18 19:10       ` Liam Breck
  2017-03-18 22:55         ` Hans de Goede
  0 siblings, 1 reply; 90+ messages in thread
From: Liam Breck @ 2017-03-18 19:10 UTC (permalink / raw)
  To: Hans de Goede; +Cc: Andy Shevchenko, Sebastian Reichel, Tony Lindgren, linux-pm

On Sat, Mar 18, 2017 at 7:30 AM, Hans de Goede <hdegoede@redhat.com> wrote:
> Hi,
>
> On 18-03-17 08:10, Liam Breck wrote:
>>
>> On Fri, 17 Mar 2017 10:55:19 +0100, Hans de Goede wrote:
>>
>>> The bq24192 and bq24192i are mostly identical to the bq24190, TI even
>>> published a single datasheet for all 3 of them. The difference
>>> between the bq24190 and bq24192[i] is the way charger-type detection
>>> is done, the bq24190 is to be directly connected to the USB a/b lines,
>>> where as the the bq24192[i] has a gpio which should be driven high/low
>>> externally depending on the type of charger connected, from a register
>>> level access pov there is no difference.
>>>
>>> The differences between the bq24192 and bq24192i are:
>>> 1) Lower default charge rate on the bq24192i
>>> 2) Pre-charge-current can be max 640 mA on the bq24192i
>>>
>>> Since we do not provide an API for setting the pre-charge-current,
>>> these differences can be ignored and we can simply use the existing
>>> code as-is with the bq24192 and bq24192i.
>>
>>
>> FYI, coming patchset will set pre- and termination-charge current via DT.
>
>
> Ok, note that this again is something which we cannot do on x86,
> so we need to retain the BIOS set values there. I assume this will
> not be a problem since you will need to keep the driver working
> with device-trees which do not specify this info, for compatibility
> with existing devicetrees.
>
>
>>
>>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>>> ---
>>>  drivers/power/supply/bq24190_charger.c | 12 ++++++++++--
>>>  1 file changed, 10 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/power/supply/bq24190_charger.c
>>> b/drivers/power/supply/bq24190_charger.c
>>> index 9c4b171..9014dee 100644
>>> --- a/drivers/power/supply/bq24190_charger.c
>>> +++ b/drivers/power/supply/bq24190_charger.c
>>> @@ -1275,7 +1275,14 @@ static int bq24190_hw_init(struct bq24190_dev_info
>>> *bdi)
>>>         if (ret < 0)
>>>                 goto out;
>>>
>>> -       if (v != bdi->model) {
>>> +       switch (v) {
>>> +       case BQ24190_REG_VPRS_PN_24190:
>>> +       case BQ24190_REG_VPRS_PN_24192:
>>> +       case BQ24190_REG_VPRS_PN_24192I:
>>> +               bdi->model = v;
>>
>>
>> We should set model in probe(). Doesn't the previous code still work?
>
>
> On x86 we know we have a variant but not which variant, since the
> driver supports all variants we can simply make the driver flexible
> enough to handle all variants and be done with it.

How do we know it supports all variants sufficiently?

>>
>>> +               break;
>>> +       default:
>>> +               dev_err(bdi->dev, "Error unknown model: 0x%02x\n", v);
>>
>>
>> Feel free to add the error msg.
>>
>>>                 ret = -ENODEV;
>>>                 goto out;
>>>         }
>>> @@ -1316,7 +1323,6 @@ static int bq24190_probe(struct i2c_client *client,
>>>
>>>         bdi->client = client;
>>>         bdi->dev = dev;
>>> -       bdi->model = id->driver_data;
>>
>>
>> Is driver_data no longer always correct?
>
>
> See above, I was actually planning on dropping the
> setting of driver_data from the ids tables, but I forgot.

I suspect we want a platform_data field and

bdi->model = pdata ? pdata->model : id->driver_data

>>
>>>         bdi->pdata = client->dev.platform_data;
>>>         strncpy(bdi->model_name, id->name, I2C_NAME_SIZE);
>>>         mutex_init(&bdi->f_reg_lock);
>>> @@ -1450,6 +1456,8 @@ static SIMPLE_DEV_PM_OPS(bq24190_pm_ops,
>>> bq24190_pm_suspend, bq24190_pm_resume);
>>>   */
>>>  static const struct i2c_device_id bq24190_i2c_ids[] = {
>>>         { "bq24190", BQ24190_REG_VPRS_PN_24190 },
>>> +       { "bq24192", BQ24190_REG_VPRS_PN_24192 },
>>> +       { "bq24192i", BQ24190_REG_VPRS_PN_24192I },
>>
>>
>> This may be the only essential change.
>
>
> See above, actually this should have been:
>
> static const struct i2c_device_id bq24190_i2c_ids[] = {
>         { "bq24190" },
>         { "bq24192" },
>         { "bq24192i" },
>         { },
> };
>
> Or (also works for me): just:
>
> static const struct i2c_device_id bq24190_i2c_ids[] = {
>         { "bq24190" },
>         { },
> };
>
> And use the same compatible for all variants as they are
> all compatible anyways.
>
> Regards,
>
> Hans

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [08/15] power: supply: bq24190_charger: Add support for external fuel gauge
  2017-03-18 14:31     ` Hans de Goede
@ 2017-03-18 19:18       ` Liam Breck
  2017-03-18 23:02         ` Hans de Goede
  0 siblings, 1 reply; 90+ messages in thread
From: Liam Breck @ 2017-03-18 19:18 UTC (permalink / raw)
  To: Hans de Goede; +Cc: Andy Shevchenko, Sebastian Reichel, Tony Lindgren, linux-pm

On Sat, Mar 18, 2017 at 7:31 AM, Hans de Goede <hdegoede@redhat.com> wrote:
> Hi,
>
> On 18-03-17 08:10, Liam Breck wrote:
>>
>> On Fri, 17 Mar 2017 10:55:20 +0100, Hans de Goede wrote:
>>
>>> Some platforms with a bq24190_charger have an external fuel gauge which
>>> makes it possible to reliably report battery (dis)charge state, at
>>> support for this by adding an optional get_ext_bat_property callback
>>> to the platform_data and using this if the platform provides it.
>>
>>
>> Please do not pollute the charger with fuel-gauge functionality; use the
>> gauge driver directly.
>
>
> That is not how the userspace ABI works, the userspace ABI says one
> battery one power_supply device, so we need to combine the data from
> the 2 sources.

Reference?

See patch 04 discussion about fuel-gauge as primary point of contact.

Another approach to consider: a pseudo-driver which uses sysfs or
callbacks into two actual drivers.

>> And calling into a mystery module with a pointer from platform-data is
>> scary! St. Patrick's
>> Day is wrong for this; try April Fool's or Halloween ;-)
>
>
> Since we control both the caller and the callee I fail to see how
> this is scary in any way.

This patch looks like a hack to me. Pls find another way.

> Regards,
>
> Hans
>
>
>
>>
>>> By convention the callback will return -ENXIO when it is not ready yet,
>>> or the driver providing it has been unbound from its device. Since it
>>> returns the same error when unbound it cannot return -EPROBE_DEFER
>>> as that is not a valid errno.
>>>
>>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>>> ---
>>>  drivers/power/supply/bq24190_charger.c | 41
>>> +++++++++++++++++++++++++++++++---
>>>  include/linux/power/bq24190_charger.h  |  4 ++++
>>>  2 files changed, 42 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/power/supply/bq24190_charger.c
>>> b/drivers/power/supply/bq24190_charger.c
>>> index 9014dee..9fe69a5 100644
>>> --- a/drivers/power/supply/bq24190_charger.c
>>> +++ b/drivers/power/supply/bq24190_charger.c
>>> @@ -1111,7 +1111,10 @@ static int bq24190_battery_get_property(struct
>>> power_supply *psy,
>>>                 ret = 0;
>>>                 break;
>>>         default:
>>> -               ret = -ENODATA;
>>> +               if (bdi->pdata && bdi->pdata->get_ext_bat_property)
>>> +                       ret = bdi->pdata->get_ext_bat_property(psp, val);
>>> +               else
>>> +                       ret = -ENODATA;
>>>         }
>>>
>>>         pm_runtime_put_sync(bdi->dev);
>>> @@ -1168,12 +1171,31 @@ static enum power_supply_property
>>> bq24190_battery_properties[] = {
>>>         POWER_SUPPLY_PROP_TECHNOLOGY,
>>>         POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
>>>         POWER_SUPPLY_PROP_SCOPE,
>>> +       /* Begin of extended battery properties */
>>> +       POWER_SUPPLY_PROP_VOLTAGE_NOW,
>>> +       POWER_SUPPLY_PROP_VOLTAGE_AVG,
>>> +       POWER_SUPPLY_PROP_VOLTAGE_OCV,
>>> +       POWER_SUPPLY_PROP_CURRENT_NOW,
>>> +       POWER_SUPPLY_PROP_CURRENT_AVG,
>>> +       POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
>>> +       POWER_SUPPLY_PROP_CHARGE_FULL,
>>> +       POWER_SUPPLY_PROP_CHARGE_NOW,
>>>  };
>>>
>>>  static const struct power_supply_desc bq24190_battery_desc = {
>>>         .name                   = "bq24190-battery",
>>>         .type                   = POWER_SUPPLY_TYPE_BATTERY,
>>>         .properties             = bq24190_battery_properties,
>>> +       .num_properties         = 6,
>>> +       .get_property           = bq24190_battery_get_property,
>>> +       .set_property           = bq24190_battery_set_property,
>>> +       .property_is_writeable  = bq24190_battery_property_is_writeable,
>>> +};
>>> +
>>> +static const struct power_supply_desc bq24190_ext_battery_desc = {
>>> +       .name                   = "bq24190-battery",
>>> +       .type                   = POWER_SUPPLY_TYPE_BATTERY,
>>> +       .properties             = bq24190_battery_properties,
>>>         .num_properties         = ARRAY_SIZE(bq24190_battery_properties),
>>>         .get_property           = bq24190_battery_get_property,
>>>         .set_property           = bq24190_battery_set_property,
>>> @@ -1336,6 +1358,15 @@ static int bq24190_probe(struct i2c_client
>>> *client,
>>>                 return -EINVAL;
>>>         }
>>>
>>> +       if (bdi->pdata && bdi->pdata->get_ext_bat_property) {
>>> +               union power_supply_propval val;
>>> +
>>> +               /* Check external fuel gauge is ready */
>>> +               ret = bdi->pdata->get_ext_bat_property(0, &val);
>>> +               if (ret == -ENXIO)
>>> +                       return -EPROBE_DEFER;
>>> +       }
>>> +
>>>         pm_runtime_enable(dev);
>>>         pm_runtime_resume(dev);
>>>
>>> @@ -1357,8 +1388,12 @@ static int bq24190_probe(struct i2c_client
>>> *client,
>>>         }
>>>
>>>         battery_cfg.drv_data = bdi;
>>> -       bdi->battery = power_supply_register(dev, &bq24190_battery_desc,
>>> -                                               &battery_cfg);
>>> +       if (bdi->pdata && bdi->pdata->get_ext_bat_property)
>>> +               bdi->battery = power_supply_register(dev,
>>> +                                   &bq24190_ext_battery_desc,
>>> &battery_cfg);
>>> +       else
>>> +               bdi->battery = power_supply_register(dev,
>>> +                                   &bq24190_battery_desc, &battery_cfg);
>>>         if (IS_ERR(bdi->battery)) {
>>>                 dev_err(dev, "Can't register battery\n");
>>>                 ret = PTR_ERR(bdi->battery);
>>> diff --git a/include/linux/power/bq24190_charger.h
>>> b/include/linux/power/bq24190_charger.h
>>> index 8d918cb..02d248b 100644
>>> --- a/include/linux/power/bq24190_charger.h
>>> +++ b/include/linux/power/bq24190_charger.h
>>> @@ -9,8 +9,12 @@
>>>  #ifndef _BQ24190_CHARGER_H_
>>>  #define _BQ24190_CHARGER_H_
>>>
>>> +#include <linux/power_supply.h>
>>> +
>>>  struct bq24190_platform_data {
>>>         bool no_register_reset;
>>> +       int (*get_ext_bat_property)(enum power_supply_property prop,
>>> +                                   union power_supply_propval *val);
>>>  };
>>>
>>>  #endif
>>
>>
>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [09/15] power: supply: bq24190_charger: Add voltage_max_design prop to battery
  2017-03-18 14:34     ` Hans de Goede
@ 2017-03-18 19:34       ` Liam Breck
  2017-03-18 23:10         ` Hans de Goede
  0 siblings, 1 reply; 90+ messages in thread
From: Liam Breck @ 2017-03-18 19:34 UTC (permalink / raw)
  To: Hans de Goede; +Cc: Andy Shevchenko, Sebastian Reichel, Tony Lindgren, linux-pm

On Sat, Mar 18, 2017 at 7:34 AM, Hans de Goede <hdegoede@redhat.com> wrote:
> Hi,
>
> On 18-03-17 08:10, Liam Breck wrote:
>>
>> On Fri, 17 Mar 2017 10:55:21 +0100, Hans de Goede wrote:
>>
>>> When combined with an external fuel-gauge, upower needs
>>> voltage_max_design
>>> as it internally does all its calculations in Watts and converts the
>>> charge_foo properties from A to Watts by using voltage_max_design.
>>
>>
>> This is a battery characteristic which should be obtained from the fuel
>> gauge (e.g. V at charge
>> termination)
>
>
> V at charge termination is *exactly* what bq24190_charger_get_voltage()
> returns. And the fuel-gauge only measures charging it does not control
> it, so unless we had some nvram to store things in over time the fg
> driver cannot no what "V at charge termination" will be, where as the
> bq24190_charger code actually knows as it controls at which voltage
> the charger switches from constant current to constant voltage mode.
>
>> or external battery config.
>>
>> See also https://patchwork.kernel.org/patch/9626487/
>
>
> There is no external battery config on x86.

ACPI? The battery data/config should really be used to set the charger
register in question.

charger/voltage_max already has this. Can you find a way to use that?

> Regards,
>
> Hans
>
>
>>
>>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>>> ---
>>>  drivers/power/supply/bq24190_charger.c | 10 +++++++++-
>>>  1 file changed, 9 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/power/supply/bq24190_charger.c
>>> b/drivers/power/supply/bq24190_charger.c
>>> index 9fe69a5..82cb33d 100644
>>> --- a/drivers/power/supply/bq24190_charger.c
>>> +++ b/drivers/power/supply/bq24190_charger.c
>>> @@ -1103,6 +1103,13 @@ static int bq24190_battery_get_property(struct
>>> power_supply *psy,
>>>                 val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
>>>                 ret = 0;
>>>                 break;
>>> +       case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
>>> +               /*
>>> +                * Report charger configured voltage as max design
>>> voltage,
>>> +                * not entirely correct, but userspace needs something
>>> here.
>>> +                */
>>> +               ret = bq24190_charger_get_voltage(bdi, val);
>>> +               break;
>>>         case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
>>>                 ret = bq24190_battery_get_temp_alert_max(bdi, val);
>>>                 break;
>>> @@ -1169,6 +1176,7 @@ static enum power_supply_property
>>> bq24190_battery_properties[] = {
>>>         POWER_SUPPLY_PROP_HEALTH,
>>>         POWER_SUPPLY_PROP_ONLINE,
>>>         POWER_SUPPLY_PROP_TECHNOLOGY,
>>> +       POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
>>>         POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
>>>         POWER_SUPPLY_PROP_SCOPE,
>>>         /* Begin of extended battery properties */
>>> @@ -1186,7 +1194,7 @@ static const struct power_supply_desc
>>> bq24190_battery_desc = {
>>>         .name                   = "bq24190-battery",
>>>         .type                   = POWER_SUPPLY_TYPE_BATTERY,
>>>         .properties             = bq24190_battery_properties,
>>> -       .num_properties         = 6,
>>> +       .num_properties         = 7,
>>>         .get_property           = bq24190_battery_get_property,
>>>         .set_property           = bq24190_battery_set_property,
>>>         .property_is_writeable  = bq24190_battery_property_is_writeable,

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [10/15] power: supply: bq24190_charger: Use extcon to determine ilimit, 5v boost
  2017-03-18 14:42     ` Hans de Goede
@ 2017-03-18 19:57       ` Liam Breck
  2017-03-18 23:11         ` Hans de Goede
  0 siblings, 1 reply; 90+ messages in thread
From: Liam Breck @ 2017-03-18 19:57 UTC (permalink / raw)
  To: Hans de Goede; +Cc: Andy Shevchenko, Sebastian Reichel, Tony Lindgren, linux-pm

On Sat, Mar 18, 2017 at 7:42 AM, Hans de Goede <hdegoede@redhat.com> wrote:
> Hi,
>
> On 18-03-17 08:10, Liam Breck wrote:
>>
>> Tony, question for you below...
>>
>> On Fri, 17 Mar 2017 10:55:22 +0100, Hans de Goede wrote:
>>
>>> Add support for monitoring an extcon device with SDP/CDP/DCP and HOST
>>
>>
>> insert: USB X.0
>>
>>> cables and adjust ilimit and enable/disable the 5v boost converter
>>> accordingly. This is necessary on systems where the PSEL pin is hardwired
>>> high and ILIM needs to be set by software based on the detected charger
>>> type.
>>
>>
>> This description is rather thin for the extent of the changes. What
>> specific systems
>> require this?
>
>
> Systems which use a variant with a PSEL pin where the PSEL pin is hardwired
> high.

I gathered that :-p  It's illuminating to include detailed background
in a patch description; please paint us a picture :-)

Also you can set IINLIM via sysfs, so consider doing this from the
PMIC driver, or pseudo-driver. I don't see that BQ24190 generally
needs to handle extcon events.

>> What drivers generate the event?
>
>
> The driver which registers the extcon with the name "extcon_name"
> the bq24190_charger driver really does not need to know more.
> In the use-case we are talking about now the driver is
> the new extcon-cht-wc.c driver which is part of the patch-set
> as I initially posted it.
>
>> Also provide URLs to docs/datasheets.
>
>
> I've no access to docs / datasheets for the Whiskey Cove PMIC.
>
>
>>
>>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>>> ---
>>>  drivers/power/supply/Kconfig           |  1 +
>>>  drivers/power/supply/bq24190_charger.c | 85
>>> ++++++++++++++++++++++++++++++++++
>>>  include/linux/power/bq24190_charger.h  |  1 +
>>>  3 files changed, 87 insertions(+)
>>>
>>> diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
>>> index f8b6e64..fd93110 100644
>>> --- a/drivers/power/supply/Kconfig
>>> +++ b/drivers/power/supply/Kconfig
>>> @@ -442,6 +442,7 @@ config CHARGER_BQ2415X
>>>  config CHARGER_BQ24190
>>>         tristate "TI BQ24190 battery charger driver"
>>>         depends on I2C
>>> +       depends on EXTCON
>>>         depends on GPIOLIB || COMPILE_TEST
>>>         help
>>>           Say Y to enable support for the TI BQ24190 battery charger.
>>> diff --git a/drivers/power/supply/bq24190_charger.c
>>> b/drivers/power/supply/bq24190_charger.c
>>> index 82cb33d..03990e2 100644
>>> --- a/drivers/power/supply/bq24190_charger.c
>>> +++ b/drivers/power/supply/bq24190_charger.c
>>> @@ -11,10 +11,12 @@
>>>  #include <linux/module.h>
>>>  #include <linux/interrupt.h>
>>>  #include <linux/delay.h>
>>> +#include <linux/extcon.h>
>>>  #include <linux/of_irq.h>
>>>  #include <linux/of_device.h>
>>>  #include <linux/pm_runtime.h>
>>>  #include <linux/power_supply.h>
>>> +#include <linux/workqueue.h>
>>>  #include <linux/gpio.h>
>>>  #include <linux/i2c.h>
>>>
>>> @@ -39,6 +41,8 @@
>>>  #define BQ24190_REG_POC_WDT_RESET_SHIFT                6
>>>  #define BQ24190_REG_POC_CHG_CONFIG_MASK                (BIT(5) | BIT(4))
>>>  #define BQ24190_REG_POC_CHG_CONFIG_SHIFT       4
>>> +#define BQ24190_REG_POC_CHG_CONFIG_CHARGE      1
>>> +#define BQ24190_REG_POC_CHG_CONFIG_OTG         2
>>>  #define BQ24190_REG_POC_SYS_MIN_MASK           (BIT(3) | BIT(2) |
>>> BIT(1))
>>>  #define BQ24190_REG_POC_SYS_MIN_SHIFT          1
>>>  #define BQ24190_REG_POC_BOOST_LIM_MASK         BIT(0)
>>> @@ -152,6 +156,9 @@ struct bq24190_dev_info {
>>>         struct power_supply             *charger;
>>>         struct power_supply             *battery;
>>>         struct bq24190_platform_data    *pdata;
>>> +       struct extcon_dev               *extcon;
>>> +       struct notifier_block           extcon_nb;
>>> +       struct work_struct              extcon_work;
>>>         char                            model_name[I2C_NAME_SIZE];
>>>         kernel_ulong_t                  model;
>>>         struct mutex                    f_reg_lock;
>>> @@ -167,6 +174,11 @@ struct bq24190_dev_info {
>>>   * number at that index in the array is the real-world value that it
>>>   * represents.
>>>   */
>>> +
>>> +/* REG00[2:0] (IINLIM) in uAh */
>>> +static const int bq24190_iinlim_values[] = {
>>> +       100000, 150000, 500000, 900000, 1200000, 1500000, 2000000,
>>> 3000000 };
>>> +
>>>  /* REG02[7:2] (ICHG) in uAh */
>>>  static const int bq24190_ccc_ichg_values[] = {
>>>          512000,  576000,  640000,  704000,  768000,  832000,  896000,
>>> 960000,
>>> @@ -1290,6 +1302,61 @@ static irqreturn_t bq24190_irq_handler_thread(int
>>> irq, void *data)
>>>         return IRQ_HANDLED;
>>>  }
>>>
>>> +static void bq24190_extcon_work(struct work_struct *work)
>>> +{
>>
>>
>> Does this need pm_runtime_get_sync(), etc?
>> (See linux-next patches to driver.)
>
>
> Yes with runtime pm this will need to do a
> pm_runtime_get_sync(bdi->Dev) before accessing
> the device.
>
>
>
>
>>
>>> +       struct bq24190_dev_info *bdi =
>>> +               container_of(work, struct bq24190_dev_info, extcon_work);
>>> +       int ret, iinlim = 0;
>>> +
>>> +       if (extcon_get_state(bdi->extcon, EXTCON_CHG_USB_SDP) == 1)
>>> +               iinlim = 500000;
>>> +       else if (extcon_get_state(bdi->extcon, EXTCON_CHG_USB_CDP) == 1
>>> ||
>>> +                extcon_get_state(bdi->extcon, EXTCON_CHG_USB_ACA) == 1)
>>> +               iinlim = 1500000;
>>> +       else if (extcon_get_state(bdi->extcon, EXTCON_CHG_USB_DCP) == 1)
>>> +               iinlim = 2000000;
>>> +
>>> +       if (iinlim) {
>>> +               ret = bq24190_set_field_val(bdi, BQ24190_REG_ISC,
>>> +                               BQ24190_REG_ISC_IINLIM_MASK,
>>> +                               BQ24190_REG_ISC_IINLIM_SHIFT,
>>> +                               bq24190_iinlim_values,
>>> +                               ARRAY_SIZE(bq24190_iinlim_values),
>>> +                               iinlim);
>>> +               if (ret)
>>> +                       dev_err(bdi->dev, "Can't set IINLIM: %d\n", ret);
>>> +       }
>>> +
>>> +       /*
>>> +        * If no charger has been detected and host mode is requested,
>>> activate
>>> +        * the 5V boost converter, otherwise deactivate it.
>>> +        */
>>> +       if (!iinlim && extcon_get_state(bdi->extcon, EXTCON_USB_HOST) ==
>>> 1) {
>>> +               ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
>>> +                                        BQ24190_REG_POC_CHG_CONFIG_MASK,
>>> +
>>> BQ24190_REG_POC_CHG_CONFIG_SHIFT,
>>> +                                        BQ24190_REG_POC_CHG_CONFIG_OTG);
>>> +       } else {
>>> +               ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
>>> +                                        BQ24190_REG_POC_CHG_CONFIG_MASK,
>>> +
>>> BQ24190_REG_POC_CHG_CONFIG_SHIFT,
>>> +
>>> BQ24190_REG_POC_CHG_CONFIG_CHARGE);
>>> +       }
>>> +       if (ret)
>>> +               dev_err(bdi->dev, "Can't set CHG_CONFIG: %d\n", ret);
>>> +}
>>> +
>>> +static int bq24190_extcon_event(struct notifier_block *nb, unsigned long
>>> event,
>>> +                               void *param)
>>> +{
>>> +       struct bq24190_dev_info *bdi =
>>> +               container_of(nb, struct bq24190_dev_info, extcon_nb);
>>> +
>>> +       schedule_work(&bdi->extcon_work);
>>> +
>>> +       return NOTIFY_OK;
>>> +}
>>> +
>>>  static int bq24190_hw_init(struct bq24190_dev_info *bdi)
>>>  {
>>>         u8 v;
>>> @@ -1375,6 +1442,12 @@ static int bq24190_probe(struct i2c_client
>>> *client,
>>>                         return -EPROBE_DEFER;
>>>         }
>>>
>>> +       if (bdi->pdata && bdi->pdata->extcon_name) {
>>
>>
>> Verify that extcon_name has an expected value?
>
>
> The whole idea is that the bq24190 does not need to care about
> which extcon driver it is told to use, just that it has to
> use *a* extcon driver.
>
>>
>>> +               bdi->extcon =
>>> extcon_get_extcon_dev(bdi->pdata->extcon_name);
>>> +               if (!bdi->extcon)
>>> +                       return -EPROBE_DEFER;
>>
>>
>> dev_info() a msg about this linkage, including info about the other side.
>
>
> dev_info on success I assume, not on PROBE_DEFER, otherwise we will
> end up spamming the log quite a lot while modules are loading.
>
>
>
>
>>
>>> +       }
>>> +
>>>         pm_runtime_enable(dev);
>>>         pm_runtime_resume(dev);
>>>
>>> @@ -1423,6 +1496,18 @@ static int bq24190_probe(struct i2c_client
>>> *client,
>>>                 goto out4;
>>>         }
>>>
>>> +       if (bdi->extcon) {
>>> +               INIT_WORK(&bdi->extcon_work, bq24190_extcon_work);
>>> +               bdi->extcon_nb.notifier_call = bq24190_extcon_event;
>>> +               ret = devm_extcon_register_notifier(dev, bdi->extcon, -1,
>>> +                                                   &bdi->extcon_nb);
>>> +               if (ret)
>>> +                       goto out4;
>>> +
>>> +               /* Sync initial cable state */
>>> +               schedule_work(&bdi->extcon_work);
>>> +       }
>>> +
>>>         return 0;
>>>
>>>  out4:
>>> diff --git a/include/linux/power/bq24190_charger.h
>>> b/include/linux/power/bq24190_charger.h
>>> index 02d248b..909c5b9 100644
>>> --- a/include/linux/power/bq24190_charger.h
>>> +++ b/include/linux/power/bq24190_charger.h
>>> @@ -13,6 +13,7 @@
>>>
>>>  struct bq24190_platform_data {
>>>         bool no_register_reset;
>>> +       const char *extcon_name;
>>>         int (*get_ext_bat_property)(enum power_supply_property prop,
>>>                                     union power_supply_propval *val);
>>>  };
>>
>>
>
> Regards,
>
> Hans

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [04/15] power: supply: bq24190_charger: Add no_register_reset pdata flag
  2017-03-18 18:51       ` Liam Breck
@ 2017-03-18 22:51         ` Hans de Goede
  2017-03-19  0:57           ` Liam Breck
  0 siblings, 1 reply; 90+ messages in thread
From: Hans de Goede @ 2017-03-18 22:51 UTC (permalink / raw)
  To: Liam Breck
  Cc: Andy Shevchenko, Sebastian Reichel, Tony Lindgren, linux-pm, Liam Breck

Hi,

On 18-03-17 19:51, Liam Breck wrote:
> On Sat, Mar 18, 2017 at 7:13 AM, Hans de Goede <hdegoede@redhat.com> wrote:
>> Hi,
>>
>> On 18-03-17 08:10, Liam Breck wrote:
>>>
>>> [dropped CC's not relevant to BQ24190; pls re-add anyone appropriate]
>>>
>>> Hi Hans,
>>>
>>> I am the de facto maintainer of BQ24190, with help from Tony. I contracted
>>> the original author to
>>> create the driver. I'm not aware of anyone else relying on it at present.
>>
>>
>> Hi Liam, nice to meet you.
>>
>>> Pls rebase to -next (!) and post BQ24190 changes in a separate patchset.
>>
>>
>> Ok, I will rebase these patches on top of
>> https://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply.git/log/?h=for-next
>
> Yep.
>
>>> Reference any
>>>
>>> dependencies in other patchsets with Depends-on lines in patch
>>> descriptions linking to
>>> patchwork.kernel.org. If any dependency might be controversial, pls defer
>>> the BQ24190 patchset til
>>> controversy resolves.
>>
>> There are no dependencies for the BQ24190 patches, they are a dependency for
>> some of the other changes but they can go upstream as is.
>
> The extcon driver elsewhere in patchset?

That is only a runtime dependency and only when the extcon_name is
set in the platform_data, the patches can be merged upstream without
this (no compile / linktime dependency). Even runtime things will
not explode if the extcon driver is not there and asked for in
platform data, the probe() function will then simply return -EPROBE_DEFER.

>
>>> You may be interested in these, which I will support in BQ24190 in near
>>> future:
>>> https://patchwork.kernel.org/patch/9626487/
>>> https://patchwork.kernel.org/patch/9626491/
>>
>>
>> Yeah those are not going to matter for the use-case I'm looking at.
>> I've a feeling you've only looked at the bq24190 patches and not the
>> rest of the set. There is a reason I posted these all together as I
>> mentioned in the cover-letter:
>>
>> "I'm sending this as a single series so that people can see how all the bits
>> fit together."
>
> Reading the entire patchset may be a lot to ask some folks, altho I
> did. It's best to give relevant background in each patch description.
>
>> Anyways I will try to clarify things by answering you questions /
>> responding to your remarks.
>>
>>> Further comments below...
>>>
>>> On Fri, 17 Mar 2017 10:55:16 +0100, Hans de Goede wrote:
>>>
>>>> On some platforms the register have been setup with platform specific
>>>> values by the firmware and should not be reset.
>>>
>>>
>>> Pls describe this mysterious, meddling firmware. Who wrote it, when does
>>> it run, on what devices,
>>> etc? Include URLs to docs, etc. BTW it's not really "firmware" if it runs
>>> on the main cpu, IMO.
>>> A boot loader is not firmware.
>>
>>
>> So not all the world runs on ARM and not all devices using the
>> TI BQ24190 (and variants) use an ARM processor or devicetree
>> for that matter). Having worked on both ARM and x86 quite a bit
>> I've a feeling that you are approaching my patchset with somewhat
>> of an ARM focussed pov.
>>
>> The primary device I'm trying to get battery/charger monitoring
>> working for is the GPDwin: http://www.gpd.hk/gpdwin.asp
>>
>> Which is an Intel Cherrytrail using machine with an Intel
>> Cherrytrail Whiskey Cove PMIC.
>>
>> The firmware I'm talking about here is the EFI system firmware
>> which boots the machine aka the BIOS.
>
> Mention all of the above in patch descriptions.
>
>>> We probably don't want to disable register_reset in all circumstances. Can
>>> you record the
>>> firmware's settings for charger?
>>
>>
>> Yes after a (re)boot they are always reset to the same values.
>
> So record those settings in a platform_data field. That's your
> external config in this case.

Assuming the platform_data has sane values like uA that means
re-implementing most of the bq24190 driver in the code filling
the platform data (to go from register values to uA) that does
not seem like a sane approach when a simple do not reset
flag suffices. Note also see below for another way to deal
with this.

> The driver does a register_reset on resume so it has a consistent
> state with chip.

That assumes someone may be mucking with the chip during
suspend which usually is not the case arguably this is a
bad idea in general since if the chip is programmed with
lower then reset charging limits it may now charge above
the limits until the limits are re-applied.

I really wonder what the reset is there for at all TBH,
are there any cases where this really is necessary ?
Maybe it would be best to just drop the reset altogether,
or make it opt in rather then opt out.

>
>>> I suspect we should replay them in set_mode_host() -- to be
>>> renamed set_operating_params in forthcoming patchset.
>>
>>
>> That is not going to work, the Cherrytrail Whiskey Cove PMIC
>> is used on many different boards and there is no way to get
>> the info from the firmware other then reading it back from
>> the chip, hence the no_register_reset flag.
>
> This isn't about the PMIC. You need to know how boot code for a
> certain device configures the charger. Encode that knowledge in
> platform_data.

Again that info is already there in the registers and as long
as we do not touch them we're fine. Also see above about
needing to reproduce almost all of the bq24190 driver to
actually fill in platform_data from the registers.

> Also have you asked the vendor for docs?

Yes I've asked both the manufacturer and the chip vendor (Intel)
for docs, but I've not gotten an answer from either.

>>> What generates your platform_data objects?
>>
>>
>> The last patch in the patch-set shows this. The
>> Cherrytrail Whiskey Cove PMIC does charger type detection
>> and has a fuelgauge, but it does not contain a battery
>> charger itself. Instead it contains an i2c controller
>> to which an external charger chip, one of the
>> TI BQ24190 variants, gets connected.
>
> More useful background for patch descriptions :-)

I can put this in the patch descriptions as example.
but the patches are intended to be generally useful in case
a similar external fuel gauge situation comes along, which
is why I left the details out of the commit messages.

> Given that design, it sounds like the PMIC driver should be the point
> of contact with userspace, and use sysfs
> (/sys/class/power_supply/bq24190-charger/f_*) to get/set charger
> stats. We can amend the driver to extend that feature. (Also a good
> way to test chip knobs.)

One driver poking into the sysfs files of another driver is
not a sane intra driver interface, also this will require
(again) duplicating much of the bq24190 driver for all the
power_supply properties which it already implement.

I really do not see what your objection is against the
"power: supply: bq24190_charger: Add support for external fuel gauge"
patch is, the changes to bq24190_charger.c are minimal it defines
a clean, clear and simple interface. Where as the go through sysfs
interface solution you are proposing is neither of these 3.

I would appreciate it if you would actually think along with
me in how we can make this all work together nicely, currently
I'm getting the feeling that you want to make as little changes
to the bq24190-charger code as possible, even if that means
adding 10 times as much code elsewhere, that is not an acceptable
solution IMHO.


>
> Some TI fuel gauges also work this way - I2C link to external charger.
>
>> The driver for this i2c-controller calls i2c_new_device
>> with i2c_board_info describing the BQ24190 charger
>> after calling i2c_add_adapter().
>>
>>> Are you forced to use platform_data for some reason?
>>
>>
>> Since this is info being passed around inside the kernel
>> using platform_data is a hell of a lot simpler (and cleaner
>> no need to check types, etc on the receiving side) then
>> using device-properties. Device-properties are nice when
>> getting info from firmware, but this is not that.
>
> OK
>
>> Also one of the things passed is actually a function
>> pointer to a function to get extra power_supply_properties
>> from the fuel-gauge, and passing function pointers certainly
>> is not something which should be done through device-props.
>>
>>>
>>>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>>>
>>>
>>> Add to all BQ24190 patches:
>>> Cc: Liam Breck <kernel@networkimprov.net>
>>> Cc: Tony Lindgren <tony@atomide.com>
>>>
>>> Pls don't CC me on the related patchsets.
>>>
>>>> ---
>>>>  drivers/power/supply/bq24190_charger.c | 5 +++++
>>>>  include/linux/power/bq24190_charger.h  | 1 +
>>>>  2 files changed, 6 insertions(+)
>>>>
>>>> diff --git a/drivers/power/supply/bq24190_charger.c
>>>> b/drivers/power/supply/bq24190_charger.c
>>>> index a4f0849..c92a40e4 100644
>>>> --- a/drivers/power/supply/bq24190_charger.c
>>>> +++ b/drivers/power/supply/bq24190_charger.c
>>>> @@ -151,6 +151,7 @@ struct bq24190_dev_info {
>>>>         struct device                   *dev;
>>>>         struct power_supply             *charger;
>>>>         struct power_supply             *battery;
>>>> +       struct bq24190_platform_data    *pdata;
>>>
>>>
>>> Use a register settings array/struct here, instead of platform-data. None
>>> of your other patches need
>>> to retain pdata.
>>
>>
>> Sure I can make a 1:1 copy of each field in pdata here, but that
>> is just more lines of code for the same result.
>
> I mean record the chip's UEFI-supplied state here.

Ok, so a flag get state from chip in platform_data would be
an acceptable solution to me as then I can re-use all the
code in bq24190_charger.c to go from register values to
uA (and uV).

> Currently
> no_register_reset appears to be the only pdata field used after
> probe()

The get_ext_bat_property callback also gets used after probe, but
that could be a separate variable in bq24190_dev_info.

Regards,

Hans

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [07/15] power: supply: bq24190_charger: Add support for bq24192[i]
  2017-03-18 19:10       ` Liam Breck
@ 2017-03-18 22:55         ` Hans de Goede
  0 siblings, 0 replies; 90+ messages in thread
From: Hans de Goede @ 2017-03-18 22:55 UTC (permalink / raw)
  To: Liam Breck; +Cc: Andy Shevchenko, Sebastian Reichel, Tony Lindgren, linux-pm

HI,

On 18-03-17 20:10, Liam Breck wrote:
> On Sat, Mar 18, 2017 at 7:30 AM, Hans de Goede <hdegoede@redhat.com> wrote:
>> Hi,
>>
>> On 18-03-17 08:10, Liam Breck wrote:
>>>
>>> On Fri, 17 Mar 2017 10:55:19 +0100, Hans de Goede wrote:
>>>
>>>> The bq24192 and bq24192i are mostly identical to the bq24190, TI even
>>>> published a single datasheet for all 3 of them. The difference
>>>> between the bq24190 and bq24192[i] is the way charger-type detection
>>>> is done, the bq24190 is to be directly connected to the USB a/b lines,
>>>> where as the the bq24192[i] has a gpio which should be driven high/low
>>>> externally depending on the type of charger connected, from a register
>>>> level access pov there is no difference.
>>>>
>>>> The differences between the bq24192 and bq24192i are:
>>>> 1) Lower default charge rate on the bq24192i
>>>> 2) Pre-charge-current can be max 640 mA on the bq24192i
>>>>
>>>> Since we do not provide an API for setting the pre-charge-current,
>>>> these differences can be ignored and we can simply use the existing
>>>> code as-is with the bq24192 and bq24192i.
>>>
>>>
>>> FYI, coming patchset will set pre- and termination-charge current via DT.
>>
>>
>> Ok, note that this again is something which we cannot do on x86,
>> so we need to retain the BIOS set values there. I assume this will
>> not be a problem since you will need to keep the driver working
>> with device-trees which do not specify this info, for compatibility
>> with existing devicetrees.
>>
>>
>>>
>>>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>>>> ---
>>>>  drivers/power/supply/bq24190_charger.c | 12 ++++++++++--
>>>>  1 file changed, 10 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/drivers/power/supply/bq24190_charger.c
>>>> b/drivers/power/supply/bq24190_charger.c
>>>> index 9c4b171..9014dee 100644
>>>> --- a/drivers/power/supply/bq24190_charger.c
>>>> +++ b/drivers/power/supply/bq24190_charger.c
>>>> @@ -1275,7 +1275,14 @@ static int bq24190_hw_init(struct bq24190_dev_info
>>>> *bdi)
>>>>         if (ret < 0)
>>>>                 goto out;
>>>>
>>>> -       if (v != bdi->model) {
>>>> +       switch (v) {
>>>> +       case BQ24190_REG_VPRS_PN_24190:
>>>> +       case BQ24190_REG_VPRS_PN_24192:
>>>> +       case BQ24190_REG_VPRS_PN_24192I:
>>>> +               bdi->model = v;
>>>
>>>
>>> We should set model in probe(). Doesn't the previous code still work?
>>
>>
>> On x86 we know we have a variant but not which variant, since the
>> driver supports all variants we can simply make the driver flexible
>> enough to handle all variants and be done with it.
>
> How do we know it supports all variants sufficiently?

I've compared all the datasheets (actually TI has all variants
in a single datasheet) and all the registers are the same with
the exception of the 24192I having a lower Pre-charge-current
maximum then the others.


>
>>>
>>>> +               break;
>>>> +       default:
>>>> +               dev_err(bdi->dev, "Error unknown model: 0x%02x\n", v);
>>>
>>>
>>> Feel free to add the error msg.
>>>
>>>>                 ret = -ENODEV;
>>>>                 goto out;
>>>>         }
>>>> @@ -1316,7 +1323,6 @@ static int bq24190_probe(struct i2c_client *client,
>>>>
>>>>         bdi->client = client;
>>>>         bdi->dev = dev;
>>>> -       bdi->model = id->driver_data;
>>>
>>>
>>> Is driver_data no longer always correct?
>>
>>
>> See above, I was actually planning on dropping the
>> setting of driver_data from the ids tables, but I forgot.
>
> I suspect we want a platform_data field and
>
> bdi->model = pdata ? pdata->model : id->driver_data

I want the pmic code to be generic, it does not know
which exact model it is dealing with, it can find that out,
but that would be duplicating code already present in
bq24190_charger.c

Regards,

Hans



>
>>>
>>>>         bdi->pdata = client->dev.platform_data;
>>>>         strncpy(bdi->model_name, id->name, I2C_NAME_SIZE);
>>>>         mutex_init(&bdi->f_reg_lock);
>>>> @@ -1450,6 +1456,8 @@ static SIMPLE_DEV_PM_OPS(bq24190_pm_ops,
>>>> bq24190_pm_suspend, bq24190_pm_resume);
>>>>   */
>>>>  static const struct i2c_device_id bq24190_i2c_ids[] = {
>>>>         { "bq24190", BQ24190_REG_VPRS_PN_24190 },
>>>> +       { "bq24192", BQ24190_REG_VPRS_PN_24192 },
>>>> +       { "bq24192i", BQ24190_REG_VPRS_PN_24192I },
>>>
>>>
>>> This may be the only essential change.
>>
>>
>> See above, actually this should have been:
>>
>> static const struct i2c_device_id bq24190_i2c_ids[] = {
>>         { "bq24190" },
>>         { "bq24192" },
>>         { "bq24192i" },
>>         { },
>> };
>>
>> Or (also works for me): just:
>>
>> static const struct i2c_device_id bq24190_i2c_ids[] = {
>>         { "bq24190" },
>>         { },
>> };
>>
>> And use the same compatible for all variants as they are
>> all compatible anyways.
>>
>> Regards,
>>
>> Hans

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [08/15] power: supply: bq24190_charger: Add support for external fuel gauge
  2017-03-18 19:18       ` Liam Breck
@ 2017-03-18 23:02         ` Hans de Goede
  2017-03-19  1:01           ` Liam Breck
  2017-03-19  3:52           ` Liam Breck
  0 siblings, 2 replies; 90+ messages in thread
From: Hans de Goede @ 2017-03-18 23:02 UTC (permalink / raw)
  To: Liam Breck; +Cc: Andy Shevchenko, Sebastian Reichel, Tony Lindgren, linux-pm

Hi,

On 18-03-17 20:18, Liam Breck wrote:
> On Sat, Mar 18, 2017 at 7:31 AM, Hans de Goede <hdegoede@redhat.com> wrote:
>> Hi,
>>
>> On 18-03-17 08:10, Liam Breck wrote:
>>>
>>> On Fri, 17 Mar 2017 10:55:20 +0100, Hans de Goede wrote:
>>>
>>>> Some platforms with a bq24190_charger have an external fuel gauge which
>>>> makes it possible to reliably report battery (dis)charge state, at
>>>> support for this by adding an optional get_ext_bat_property callback
>>>> to the platform_data and using this if the platform provides it.
>>>
>>>
>>> Please do not pollute the charger with fuel-gauge functionality; use the
>>> gauge driver directly.
>>
>>
>> That is not how the userspace ABI works, the userspace ABI says one
>> battery one power_supply device, so we need to combine the data from
>> the 2 sources.
>
> Reference?

This is just how things work, if you define 2 battery type power-supplies
upower will export battery info for 2 batteries to userspace and
battery panel applets will show 2 batteries (which is useful for
laptops which actually have 2 batteries like eg the Lenovo T440, X240, etc.
which have both an internal battery and a replace battery at the back.

>
> See patch 04 discussion about fuel-gauge as primary point of contact.
>
> Another approach to consider: a pseudo-driver which uses sysfs or
> callbacks into two actual drivers.

Already answered in the patch 04 discussion.

>>> And calling into a mystery module with a pointer from platform-data is
>>> scary! St. Patrick's
>>> Day is wrong for this; try April Fool's or Halloween ;-)
>>
>>
>> Since we control both the caller and the callee I fail to see how
>> this is scary in any way.
>
> This patch looks like a hack to me. Pls find another way.

Poking sysfs files from kernelspace is a much bugger hack, that +
the code duplication required in making the fuel-gauge the leading
driver really makes me believe this "hack" is the best solution.

Also keep in mind that the fuel-gauge has no status interrupt for
events like power getting plugged in charging being done, fault
interrupts, etc. So we would also need some way to tap into
the bq24190's interrupt from the fuel-gauge driver.

Anways lets continue this discussion in the patch 04 part
of the thread.

Regards,

Hans




>>>> By convention the callback will return -ENXIO when it is not ready yet,
>>>> or the driver providing it has been unbound from its device. Since it
>>>> returns the same error when unbound it cannot return -EPROBE_DEFER
>>>> as that is not a valid errno.
>>>>
>>>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>>>> ---
>>>>  drivers/power/supply/bq24190_charger.c | 41
>>>> +++++++++++++++++++++++++++++++---
>>>>  include/linux/power/bq24190_charger.h  |  4 ++++
>>>>  2 files changed, 42 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/drivers/power/supply/bq24190_charger.c
>>>> b/drivers/power/supply/bq24190_charger.c
>>>> index 9014dee..9fe69a5 100644
>>>> --- a/drivers/power/supply/bq24190_charger.c
>>>> +++ b/drivers/power/supply/bq24190_charger.c
>>>> @@ -1111,7 +1111,10 @@ static int bq24190_battery_get_property(struct
>>>> power_supply *psy,
>>>>                 ret = 0;
>>>>                 break;
>>>>         default:
>>>> -               ret = -ENODATA;
>>>> +               if (bdi->pdata && bdi->pdata->get_ext_bat_property)
>>>> +                       ret = bdi->pdata->get_ext_bat_property(psp, val);
>>>> +               else
>>>> +                       ret = -ENODATA;
>>>>         }
>>>>
>>>>         pm_runtime_put_sync(bdi->dev);
>>>> @@ -1168,12 +1171,31 @@ static enum power_supply_property
>>>> bq24190_battery_properties[] = {
>>>>         POWER_SUPPLY_PROP_TECHNOLOGY,
>>>>         POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
>>>>         POWER_SUPPLY_PROP_SCOPE,
>>>> +       /* Begin of extended battery properties */
>>>> +       POWER_SUPPLY_PROP_VOLTAGE_NOW,
>>>> +       POWER_SUPPLY_PROP_VOLTAGE_AVG,
>>>> +       POWER_SUPPLY_PROP_VOLTAGE_OCV,
>>>> +       POWER_SUPPLY_PROP_CURRENT_NOW,
>>>> +       POWER_SUPPLY_PROP_CURRENT_AVG,
>>>> +       POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
>>>> +       POWER_SUPPLY_PROP_CHARGE_FULL,
>>>> +       POWER_SUPPLY_PROP_CHARGE_NOW,
>>>>  };
>>>>
>>>>  static const struct power_supply_desc bq24190_battery_desc = {
>>>>         .name                   = "bq24190-battery",
>>>>         .type                   = POWER_SUPPLY_TYPE_BATTERY,
>>>>         .properties             = bq24190_battery_properties,
>>>> +       .num_properties         = 6,
>>>> +       .get_property           = bq24190_battery_get_property,
>>>> +       .set_property           = bq24190_battery_set_property,
>>>> +       .property_is_writeable  = bq24190_battery_property_is_writeable,
>>>> +};
>>>> +
>>>> +static const struct power_supply_desc bq24190_ext_battery_desc = {
>>>> +       .name                   = "bq24190-battery",
>>>> +       .type                   = POWER_SUPPLY_TYPE_BATTERY,
>>>> +       .properties             = bq24190_battery_properties,
>>>>         .num_properties         = ARRAY_SIZE(bq24190_battery_properties),
>>>>         .get_property           = bq24190_battery_get_property,
>>>>         .set_property           = bq24190_battery_set_property,
>>>> @@ -1336,6 +1358,15 @@ static int bq24190_probe(struct i2c_client
>>>> *client,
>>>>                 return -EINVAL;
>>>>         }
>>>>
>>>> +       if (bdi->pdata && bdi->pdata->get_ext_bat_property) {
>>>> +               union power_supply_propval val;
>>>> +
>>>> +               /* Check external fuel gauge is ready */
>>>> +               ret = bdi->pdata->get_ext_bat_property(0, &val);
>>>> +               if (ret == -ENXIO)
>>>> +                       return -EPROBE_DEFER;
>>>> +       }
>>>> +
>>>>         pm_runtime_enable(dev);
>>>>         pm_runtime_resume(dev);
>>>>
>>>> @@ -1357,8 +1388,12 @@ static int bq24190_probe(struct i2c_client
>>>> *client,
>>>>         }
>>>>
>>>>         battery_cfg.drv_data = bdi;
>>>> -       bdi->battery = power_supply_register(dev, &bq24190_battery_desc,
>>>> -                                               &battery_cfg);
>>>> +       if (bdi->pdata && bdi->pdata->get_ext_bat_property)
>>>> +               bdi->battery = power_supply_register(dev,
>>>> +                                   &bq24190_ext_battery_desc,
>>>> &battery_cfg);
>>>> +       else
>>>> +               bdi->battery = power_supply_register(dev,
>>>> +                                   &bq24190_battery_desc, &battery_cfg);
>>>>         if (IS_ERR(bdi->battery)) {
>>>>                 dev_err(dev, "Can't register battery\n");
>>>>                 ret = PTR_ERR(bdi->battery);
>>>> diff --git a/include/linux/power/bq24190_charger.h
>>>> b/include/linux/power/bq24190_charger.h
>>>> index 8d918cb..02d248b 100644
>>>> --- a/include/linux/power/bq24190_charger.h
>>>> +++ b/include/linux/power/bq24190_charger.h
>>>> @@ -9,8 +9,12 @@
>>>>  #ifndef _BQ24190_CHARGER_H_
>>>>  #define _BQ24190_CHARGER_H_
>>>>
>>>> +#include <linux/power_supply.h>
>>>> +
>>>>  struct bq24190_platform_data {
>>>>         bool no_register_reset;
>>>> +       int (*get_ext_bat_property)(enum power_supply_property prop,
>>>> +                                   union power_supply_propval *val);
>>>>  };
>>>>
>>>>  #endif
>>>
>>>
>>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [09/15] power: supply: bq24190_charger: Add voltage_max_design prop to battery
  2017-03-18 19:34       ` Liam Breck
@ 2017-03-18 23:10         ` Hans de Goede
  0 siblings, 0 replies; 90+ messages in thread
From: Hans de Goede @ 2017-03-18 23:10 UTC (permalink / raw)
  To: Liam Breck; +Cc: Andy Shevchenko, Sebastian Reichel, Tony Lindgren, linux-pm

Hi,

On 18-03-17 20:34, Liam Breck wrote:
> On Sat, Mar 18, 2017 at 7:34 AM, Hans de Goede <hdegoede@redhat.com> wrote:
>> Hi,
>>
>> On 18-03-17 08:10, Liam Breck wrote:
>>>
>>> On Fri, 17 Mar 2017 10:55:21 +0100, Hans de Goede wrote:
>>>
>>>> When combined with an external fuel-gauge, upower needs
>>>> voltage_max_design
>>>> as it internally does all its calculations in Watts and converts the
>>>> charge_foo properties from A to Watts by using voltage_max_design.
>>>
>>>
>>> This is a battery characteristic which should be obtained from the fuel
>>> gauge (e.g. V at charge
>>> termination)
>>
>>
>> V at charge termination is *exactly* what bq24190_charger_get_voltage()
>> returns. And the fuel-gauge only measures charging it does not control
>> it, so unless we had some nvram to store things in over time the fg
>> driver cannot no what "V at charge termination" will be, where as the
>> bq24190_charger code actually knows as it controls at which voltage
>> the charger switches from constant current to constant voltage mode.
>>
>>> or external battery config.
>>>
>>> See also https://patchwork.kernel.org/patch/9626487/
>>
>>
>> There is no external battery config on x86.
>
> ACPI?

Ideally yes, in practice no.

> The battery data/config should really be used to set the charger
> register in question.

Again the contents of the register is the config, but as mentioned
in the patch04 discussion I'm fine with adding a flag to read the
info from the registers, rather then just not touching the registers,
just as long as the going from register contents to "battery data"
is done in the bq24190_charger driver as that already has all the
lookup tables, etc.

> charger/voltage_max already has this. Can you find a way to use that?

Nope, upower will look at the battery/max_voltage attribute, so we
need it under the battery power_supply, we cannot just make up
new userspace ABI here.

Regards,

Hans



>>>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>>>> ---
>>>>  drivers/power/supply/bq24190_charger.c | 10 +++++++++-
>>>>  1 file changed, 9 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/drivers/power/supply/bq24190_charger.c
>>>> b/drivers/power/supply/bq24190_charger.c
>>>> index 9fe69a5..82cb33d 100644
>>>> --- a/drivers/power/supply/bq24190_charger.c
>>>> +++ b/drivers/power/supply/bq24190_charger.c
>>>> @@ -1103,6 +1103,13 @@ static int bq24190_battery_get_property(struct
>>>> power_supply *psy,
>>>>                 val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
>>>>                 ret = 0;
>>>>                 break;
>>>> +       case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
>>>> +               /*
>>>> +                * Report charger configured voltage as max design
>>>> voltage,
>>>> +                * not entirely correct, but userspace needs something
>>>> here.
>>>> +                */
>>>> +               ret = bq24190_charger_get_voltage(bdi, val);
>>>> +               break;
>>>>         case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
>>>>                 ret = bq24190_battery_get_temp_alert_max(bdi, val);
>>>>                 break;
>>>> @@ -1169,6 +1176,7 @@ static enum power_supply_property
>>>> bq24190_battery_properties[] = {
>>>>         POWER_SUPPLY_PROP_HEALTH,
>>>>         POWER_SUPPLY_PROP_ONLINE,
>>>>         POWER_SUPPLY_PROP_TECHNOLOGY,
>>>> +       POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
>>>>         POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
>>>>         POWER_SUPPLY_PROP_SCOPE,
>>>>         /* Begin of extended battery properties */
>>>> @@ -1186,7 +1194,7 @@ static const struct power_supply_desc
>>>> bq24190_battery_desc = {
>>>>         .name                   = "bq24190-battery",
>>>>         .type                   = POWER_SUPPLY_TYPE_BATTERY,
>>>>         .properties             = bq24190_battery_properties,
>>>> -       .num_properties         = 6,
>>>> +       .num_properties         = 7,
>>>>         .get_property           = bq24190_battery_get_property,
>>>>         .set_property           = bq24190_battery_set_property,
>>>>         .property_is_writeable  = bq24190_battery_property_is_writeable,

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [10/15] power: supply: bq24190_charger: Use extcon to determine ilimit, 5v boost
  2017-03-18 19:57       ` Liam Breck
@ 2017-03-18 23:11         ` Hans de Goede
  0 siblings, 0 replies; 90+ messages in thread
From: Hans de Goede @ 2017-03-18 23:11 UTC (permalink / raw)
  To: Liam Breck; +Cc: Andy Shevchenko, Sebastian Reichel, Tony Lindgren, linux-pm

Hi,

On 18-03-17 20:57, Liam Breck wrote:
> On Sat, Mar 18, 2017 at 7:42 AM, Hans de Goede <hdegoede@redhat.com> wrote:
>> Hi,
>>
>> On 18-03-17 08:10, Liam Breck wrote:
>>>
>>> Tony, question for you below...
>>>
>>> On Fri, 17 Mar 2017 10:55:22 +0100, Hans de Goede wrote:
>>>
>>>> Add support for monitoring an extcon device with SDP/CDP/DCP and HOST
>>>
>>>
>>> insert: USB X.0
>>>
>>>> cables and adjust ilimit and enable/disable the 5v boost converter
>>>> accordingly. This is necessary on systems where the PSEL pin is hardwired
>>>> high and ILIM needs to be set by software based on the detected charger
>>>> type.
>>>
>>>
>>> This description is rather thin for the extent of the changes. What
>>> specific systems
>>> require this?
>>
>>
>> Systems which use a variant with a PSEL pin where the PSEL pin is hardwired
>> high.
>
> I gathered that :-p  It's illuminating to include detailed background
> in a patch description; please paint us a picture :-)
>
> Also you can set IINLIM via sysfs, so consider doing this from the
> PMIC driver, or pseudo-driver.

sysfs is a userspace API not an in kernel API (there maybe some ways
around that but that is not a good idea in general).

Also if anything is a hack it is the entire BQ24190 sysfs interface
I understand is useful for driver debugging (although not that
useful as we also have i2cdump / i2cset / i2cget in userspace),
but it really belongs behind a DEBUG #ifdef.

> I don't see that BQ24190 generally needs to handle extcon events.

Yet charger drivers handling extcon events to determine how much
current they can draw is a design pattern we already see in use
in the kernel:

[hans@shalem linux]$ grep -l extcon drivers/power/supply/*.c
drivers/power/supply/axp288_charger.c
drivers/power/supply/bq24190_charger.c
drivers/power/supply/charger-manager.c
drivers/power/supply/qcom_smbb.c

Regards,

Hans


>
>>> What drivers generate the event?
>>
>>
>> The driver which registers the extcon with the name "extcon_name"
>> the bq24190_charger driver really does not need to know more.
>> In the use-case we are talking about now the driver is
>> the new extcon-cht-wc.c driver which is part of the patch-set
>> as I initially posted it.
>>
>>> Also provide URLs to docs/datasheets.
>>
>>
>> I've no access to docs / datasheets for the Whiskey Cove PMIC.
>>
>>
>>>
>>>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>>>> ---
>>>>  drivers/power/supply/Kconfig           |  1 +
>>>>  drivers/power/supply/bq24190_charger.c | 85
>>>> ++++++++++++++++++++++++++++++++++
>>>>  include/linux/power/bq24190_charger.h  |  1 +
>>>>  3 files changed, 87 insertions(+)
>>>>
>>>> diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
>>>> index f8b6e64..fd93110 100644
>>>> --- a/drivers/power/supply/Kconfig
>>>> +++ b/drivers/power/supply/Kconfig
>>>> @@ -442,6 +442,7 @@ config CHARGER_BQ2415X
>>>>  config CHARGER_BQ24190
>>>>         tristate "TI BQ24190 battery charger driver"
>>>>         depends on I2C
>>>> +       depends on EXTCON
>>>>         depends on GPIOLIB || COMPILE_TEST
>>>>         help
>>>>           Say Y to enable support for the TI BQ24190 battery charger.
>>>> diff --git a/drivers/power/supply/bq24190_charger.c
>>>> b/drivers/power/supply/bq24190_charger.c
>>>> index 82cb33d..03990e2 100644
>>>> --- a/drivers/power/supply/bq24190_charger.c
>>>> +++ b/drivers/power/supply/bq24190_charger.c
>>>> @@ -11,10 +11,12 @@
>>>>  #include <linux/module.h>
>>>>  #include <linux/interrupt.h>
>>>>  #include <linux/delay.h>
>>>> +#include <linux/extcon.h>
>>>>  #include <linux/of_irq.h>
>>>>  #include <linux/of_device.h>
>>>>  #include <linux/pm_runtime.h>
>>>>  #include <linux/power_supply.h>
>>>> +#include <linux/workqueue.h>
>>>>  #include <linux/gpio.h>
>>>>  #include <linux/i2c.h>
>>>>
>>>> @@ -39,6 +41,8 @@
>>>>  #define BQ24190_REG_POC_WDT_RESET_SHIFT                6
>>>>  #define BQ24190_REG_POC_CHG_CONFIG_MASK                (BIT(5) | BIT(4))
>>>>  #define BQ24190_REG_POC_CHG_CONFIG_SHIFT       4
>>>> +#define BQ24190_REG_POC_CHG_CONFIG_CHARGE      1
>>>> +#define BQ24190_REG_POC_CHG_CONFIG_OTG         2
>>>>  #define BQ24190_REG_POC_SYS_MIN_MASK           (BIT(3) | BIT(2) |
>>>> BIT(1))
>>>>  #define BQ24190_REG_POC_SYS_MIN_SHIFT          1
>>>>  #define BQ24190_REG_POC_BOOST_LIM_MASK         BIT(0)
>>>> @@ -152,6 +156,9 @@ struct bq24190_dev_info {
>>>>         struct power_supply             *charger;
>>>>         struct power_supply             *battery;
>>>>         struct bq24190_platform_data    *pdata;
>>>> +       struct extcon_dev               *extcon;
>>>> +       struct notifier_block           extcon_nb;
>>>> +       struct work_struct              extcon_work;
>>>>         char                            model_name[I2C_NAME_SIZE];
>>>>         kernel_ulong_t                  model;
>>>>         struct mutex                    f_reg_lock;
>>>> @@ -167,6 +174,11 @@ struct bq24190_dev_info {
>>>>   * number at that index in the array is the real-world value that it
>>>>   * represents.
>>>>   */
>>>> +
>>>> +/* REG00[2:0] (IINLIM) in uAh */
>>>> +static const int bq24190_iinlim_values[] = {
>>>> +       100000, 150000, 500000, 900000, 1200000, 1500000, 2000000,
>>>> 3000000 };
>>>> +
>>>>  /* REG02[7:2] (ICHG) in uAh */
>>>>  static const int bq24190_ccc_ichg_values[] = {
>>>>          512000,  576000,  640000,  704000,  768000,  832000,  896000,
>>>> 960000,
>>>> @@ -1290,6 +1302,61 @@ static irqreturn_t bq24190_irq_handler_thread(int
>>>> irq, void *data)
>>>>         return IRQ_HANDLED;
>>>>  }
>>>>
>>>> +static void bq24190_extcon_work(struct work_struct *work)
>>>> +{
>>>
>>>
>>> Does this need pm_runtime_get_sync(), etc?
>>> (See linux-next patches to driver.)
>>
>>
>> Yes with runtime pm this will need to do a
>> pm_runtime_get_sync(bdi->Dev) before accessing
>> the device.
>>
>>
>>
>>
>>>
>>>> +       struct bq24190_dev_info *bdi =
>>>> +               container_of(work, struct bq24190_dev_info, extcon_work);
>>>> +       int ret, iinlim = 0;
>>>> +
>>>> +       if (extcon_get_state(bdi->extcon, EXTCON_CHG_USB_SDP) == 1)
>>>> +               iinlim = 500000;
>>>> +       else if (extcon_get_state(bdi->extcon, EXTCON_CHG_USB_CDP) == 1
>>>> ||
>>>> +                extcon_get_state(bdi->extcon, EXTCON_CHG_USB_ACA) == 1)
>>>> +               iinlim = 1500000;
>>>> +       else if (extcon_get_state(bdi->extcon, EXTCON_CHG_USB_DCP) == 1)
>>>> +               iinlim = 2000000;
>>>> +
>>>> +       if (iinlim) {
>>>> +               ret = bq24190_set_field_val(bdi, BQ24190_REG_ISC,
>>>> +                               BQ24190_REG_ISC_IINLIM_MASK,
>>>> +                               BQ24190_REG_ISC_IINLIM_SHIFT,
>>>> +                               bq24190_iinlim_values,
>>>> +                               ARRAY_SIZE(bq24190_iinlim_values),
>>>> +                               iinlim);
>>>> +               if (ret)
>>>> +                       dev_err(bdi->dev, "Can't set IINLIM: %d\n", ret);
>>>> +       }
>>>> +
>>>> +       /*
>>>> +        * If no charger has been detected and host mode is requested,
>>>> activate
>>>> +        * the 5V boost converter, otherwise deactivate it.
>>>> +        */
>>>> +       if (!iinlim && extcon_get_state(bdi->extcon, EXTCON_USB_HOST) ==
>>>> 1) {
>>>> +               ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
>>>> +                                        BQ24190_REG_POC_CHG_CONFIG_MASK,
>>>> +
>>>> BQ24190_REG_POC_CHG_CONFIG_SHIFT,
>>>> +                                        BQ24190_REG_POC_CHG_CONFIG_OTG);
>>>> +       } else {
>>>> +               ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
>>>> +                                        BQ24190_REG_POC_CHG_CONFIG_MASK,
>>>> +
>>>> BQ24190_REG_POC_CHG_CONFIG_SHIFT,
>>>> +
>>>> BQ24190_REG_POC_CHG_CONFIG_CHARGE);
>>>> +       }
>>>> +       if (ret)
>>>> +               dev_err(bdi->dev, "Can't set CHG_CONFIG: %d\n", ret);
>>>> +}
>>>> +
>>>> +static int bq24190_extcon_event(struct notifier_block *nb, unsigned long
>>>> event,
>>>> +                               void *param)
>>>> +{
>>>> +       struct bq24190_dev_info *bdi =
>>>> +               container_of(nb, struct bq24190_dev_info, extcon_nb);
>>>> +
>>>> +       schedule_work(&bdi->extcon_work);
>>>> +
>>>> +       return NOTIFY_OK;
>>>> +}
>>>> +
>>>>  static int bq24190_hw_init(struct bq24190_dev_info *bdi)
>>>>  {
>>>>         u8 v;
>>>> @@ -1375,6 +1442,12 @@ static int bq24190_probe(struct i2c_client
>>>> *client,
>>>>                         return -EPROBE_DEFER;
>>>>         }
>>>>
>>>> +       if (bdi->pdata && bdi->pdata->extcon_name) {
>>>
>>>
>>> Verify that extcon_name has an expected value?
>>
>>
>> The whole idea is that the bq24190 does not need to care about
>> which extcon driver it is told to use, just that it has to
>> use *a* extcon driver.
>>
>>>
>>>> +               bdi->extcon =
>>>> extcon_get_extcon_dev(bdi->pdata->extcon_name);
>>>> +               if (!bdi->extcon)
>>>> +                       return -EPROBE_DEFER;
>>>
>>>
>>> dev_info() a msg about this linkage, including info about the other side.
>>
>>
>> dev_info on success I assume, not on PROBE_DEFER, otherwise we will
>> end up spamming the log quite a lot while modules are loading.
>>
>>
>>
>>
>>>
>>>> +       }
>>>> +
>>>>         pm_runtime_enable(dev);
>>>>         pm_runtime_resume(dev);
>>>>
>>>> @@ -1423,6 +1496,18 @@ static int bq24190_probe(struct i2c_client
>>>> *client,
>>>>                 goto out4;
>>>>         }
>>>>
>>>> +       if (bdi->extcon) {
>>>> +               INIT_WORK(&bdi->extcon_work, bq24190_extcon_work);
>>>> +               bdi->extcon_nb.notifier_call = bq24190_extcon_event;
>>>> +               ret = devm_extcon_register_notifier(dev, bdi->extcon, -1,
>>>> +                                                   &bdi->extcon_nb);
>>>> +               if (ret)
>>>> +                       goto out4;
>>>> +
>>>> +               /* Sync initial cable state */
>>>> +               schedule_work(&bdi->extcon_work);
>>>> +       }
>>>> +
>>>>         return 0;
>>>>
>>>>  out4:
>>>> diff --git a/include/linux/power/bq24190_charger.h
>>>> b/include/linux/power/bq24190_charger.h
>>>> index 02d248b..909c5b9 100644
>>>> --- a/include/linux/power/bq24190_charger.h
>>>> +++ b/include/linux/power/bq24190_charger.h
>>>> @@ -13,6 +13,7 @@
>>>>
>>>>  struct bq24190_platform_data {
>>>>         bool no_register_reset;
>>>> +       const char *extcon_name;
>>>>         int (*get_ext_bat_property)(enum power_supply_property prop,
>>>>                                     union power_supply_propval *val);
>>>>  };
>>>
>>>
>>
>> Regards,
>>
>> Hans

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [04/15] power: supply: bq24190_charger: Add no_register_reset pdata flag
  2017-03-18 22:51         ` Hans de Goede
@ 2017-03-19  0:57           ` Liam Breck
  2017-03-19  8:22             ` Hans de Goede
  2017-03-19 14:54             ` Andy Shevchenko
  0 siblings, 2 replies; 90+ messages in thread
From: Liam Breck @ 2017-03-19  0:57 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Andy Shevchenko, Sebastian Reichel, Tony Lindgren, linux-pm, Liam Breck

Hi Hans,

I realize you put a ton of work into this patchset. Pls know that I
want you to end up with a solution that both works for you, and makes
the charger driver more generally useful. All of my critique is
offered in good faith, and not meant as rejection. I genuinely regret
it if you feel otherwise.

Pls consider my feedback for a couple days; I put a lot of thought into it.

On Sat, Mar 18, 2017 at 3:51 PM, Hans de Goede <hdegoede@redhat.com> wrote:
> Hi,
>
> On 18-03-17 19:51, Liam Breck wrote:
>>
>> On Sat, Mar 18, 2017 at 7:13 AM, Hans de Goede <hdegoede@redhat.com>
>> wrote:
>>>
>>> Hi,
>>>
>>> On 18-03-17 08:10, Liam Breck wrote:
>>>>
>>>>
>>>> [dropped CC's not relevant to BQ24190; pls re-add anyone appropriate]
>>>>
>>>> Hi Hans,
>>>>
>>>> I am the de facto maintainer of BQ24190, with help from Tony. I
>>>> contracted
>>>> the original author to
>>>> create the driver. I'm not aware of anyone else relying on it at
>>>> present.
>>>
>>>
>>>
>>> Hi Liam, nice to meet you.
>>>
>>>> Pls rebase to -next (!) and post BQ24190 changes in a separate patchset.
>>>
>>>
>>>
>>> Ok, I will rebase these patches on top of
>>>
>>> https://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply.git/log/?h=for-next
>>
>>
>> Yep.
>>
>>>> Reference any
>>>>
>>>> dependencies in other patchsets with Depends-on lines in patch
>>>> descriptions linking to
>>>> patchwork.kernel.org. If any dependency might be controversial, pls
>>>> defer
>>>> the BQ24190 patchset til
>>>> controversy resolves.
>>>
>>>
>>> There are no dependencies for the BQ24190 patches, they are a dependency
>>> for
>>> some of the other changes but they can go upstream as is.
>>
>>
>> The extcon driver elsewhere in patchset?
>
>
> That is only a runtime dependency and only when the extcon_name is
> set in the platform_data, the patches can be merged upstream without
> this (no compile / linktime dependency). Even runtime things will
> not explode if the extcon driver is not there and asked for in
> platform data, the probe() function will then simply return -EPROBE_DEFER.
>
>
>>
>>>> You may be interested in these, which I will support in BQ24190 in near
>>>> future:
>>>> https://patchwork.kernel.org/patch/9626487/
>>>> https://patchwork.kernel.org/patch/9626491/
>>>
>>>
>>>
>>> Yeah those are not going to matter for the use-case I'm looking at.
>>> I've a feeling you've only looked at the bq24190 patches and not the
>>> rest of the set. There is a reason I posted these all together as I
>>> mentioned in the cover-letter:
>>>
>>> "I'm sending this as a single series so that people can see how all the
>>> bits
>>> fit together."
>>
>>
>> Reading the entire patchset may be a lot to ask some folks, altho I
>> did. It's best to give relevant background in each patch description.
>>
>>> Anyways I will try to clarify things by answering you questions /
>>> responding to your remarks.
>>>
>>>> Further comments below...
>>>>
>>>> On Fri, 17 Mar 2017 10:55:16 +0100, Hans de Goede wrote:
>>>>
>>>>> On some platforms the register have been setup with platform specific
>>>>> values by the firmware and should not be reset.
>>>>
>>>>
>>>>
>>>> Pls describe this mysterious, meddling firmware. Who wrote it, when does
>>>> it run, on what devices,
>>>> etc? Include URLs to docs, etc. BTW it's not really "firmware" if it
>>>> runs
>>>> on the main cpu, IMO.
>>>> A boot loader is not firmware.
>>>
>>>
>>>
>>> So not all the world runs on ARM and not all devices using the
>>> TI BQ24190 (and variants) use an ARM processor or devicetree
>>> for that matter). Having worked on both ARM and x86 quite a bit
>>> I've a feeling that you are approaching my patchset with somewhat
>>> of an ARM focussed pov.
>>>
>>> The primary device I'm trying to get battery/charger monitoring
>>> working for is the GPDwin: http://www.gpd.hk/gpdwin.asp
>>>
>>> Which is an Intel Cherrytrail using machine with an Intel
>>> Cherrytrail Whiskey Cove PMIC.
>>>
>>> The firmware I'm talking about here is the EFI system firmware
>>> which boots the machine aka the BIOS.
>>
>>
>> Mention all of the above in patch descriptions.
>>
>>>> We probably don't want to disable register_reset in all circumstances.
>>>> Can
>>>> you record the
>>>> firmware's settings for charger?
>>>
>>>
>>>
>>> Yes after a (re)boot they are always reset to the same values.
>>
>>
>> So record those settings in a platform_data field. That's your
>> external config in this case.
>
>
> Assuming the platform_data has sane values like uA that means
> re-implementing most of the bq24190 driver in the code filling
> the platform data (to go from register values to uA) that does
> not seem like a sane approach when a simple do not reset
> flag suffices. Note also see below for another way to deal
> with this.

I am suggesting you treat platform_data like a DT node: fill it with
board-specific params. Don't compute the params, read them manually
via /sys/class/...-charger/f_* and hard-code them for this board. That
gives you control over the charger config. You've already found that
you need that given the high voltage setting.

>> The driver does a register_reset on resume so it has a consistent
>> state with chip.
>
>
> That assumes someone may be mucking with the chip during
> suspend which usually is not the case arguably this is a
> bad idea in general since if the chip is programmed with
> lower then reset charging limits it may now charge above
> the limits until the limits are re-applied.
>
> I really wonder what the reset is there for at all TBH,
> are there any cases where this really is necessary ?
> Maybe it would be best to just drop the reset altogether,
> or make it opt in rather then opt out.

The reason is to put the driver back into autonomous mode while we're
asleep. Otherwise we run in host mode.

>>>> I suspect we should replay them in set_mode_host() -- to be
>>>> renamed set_operating_params in forthcoming patchset.
>>>
>>>
>>>
>>> That is not going to work, the Cherrytrail Whiskey Cove PMIC
>>> is used on many different boards and there is no way to get
>>> the info from the firmware other then reading it back from
>>> the chip, hence the no_register_reset flag.
>>
>>
>> This isn't about the PMIC. You need to know how boot code for a
>> certain device configures the charger. Encode that knowledge in
>> platform_data.
>
>
> Again that info is already there in the registers and as long
> as we do not touch them we're fine. Also see above about
> needing to reproduce almost all of the bq24190 driver to
> actually fill in platform_data from the registers.
>
>> Also have you asked the vendor for docs?
>
>
> Yes I've asked both the manufacturer and the chip vendor (Intel)
> for docs, but I've not gotten an answer from either.

Maybe someone at Redhat could make a formal request on your behalf?

>>>> What generates your platform_data objects?
>>>
>>>
>>>
>>> The last patch in the patch-set shows this. The
>>> Cherrytrail Whiskey Cove PMIC does charger type detection
>>> and has a fuelgauge, but it does not contain a battery
>>> charger itself. Instead it contains an i2c controller
>>> to which an external charger chip, one of the
>>> TI BQ24190 variants, gets connected.
>>
>>
>> More useful background for patch descriptions :-)
>
>
> I can put this in the patch descriptions as example.
> but the patches are intended to be generally useful in case
> a similar external fuel gauge situation comes along, which
> is why I left the details out of the commit messages.

Patches are even more generally useful with scenario-specific descriptions :-)

>> Given that design, it sounds like the PMIC driver should be the point
>> of contact with userspace, and use sysfs
>> (/sys/class/power_supply/bq24190-charger/f_*) to get/set charger
>> stats. We can amend the driver to extend that feature. (Also a good
>> way to test chip knobs.)
>
>
> One driver poking into the sysfs files of another driver is
> not a sane intra driver interface, also this will require
> (again) duplicating much of the bq24190 driver for all the
> power_supply properties which it already implement.

Then consider the pseudo-driver concept. That would be generally
useful for any charger/gauge pairing. Both drivers would provide
callbacks to it.

> I really do not see what your objection is against the
> "power: supply: bq24190_charger: Add support for external fuel gauge"
> patch is, the changes to bq24190_charger.c are minimal it defines
> a clean, clear and simple interface. Where as the go through sysfs
> interface solution you are proposing is neither of these 3.
>
> I would appreciate it if you would actually think along with
> me in how we can make this all work together nicely, currently
> I'm getting the feeling that you want to make as little changes
> to the bq24190-charger code as possible, even if that means
> adding 10 times as much code elsewhere, that is not an acceptable
> solution IMHO.

I question your multiplier, but more code is better if it's generally
useful. Three of these patches look like board-specific expedients to
me.

>>
>> Some TI fuel gauges also work this way - I2C link to external charger.
>>
>>> The driver for this i2c-controller calls i2c_new_device
>>> with i2c_board_info describing the BQ24190 charger
>>> after calling i2c_add_adapter().
>>>
>>>> Are you forced to use platform_data for some reason?
>>>
>>>
>>>
>>> Since this is info being passed around inside the kernel
>>> using platform_data is a hell of a lot simpler (and cleaner
>>> no need to check types, etc on the receiving side) then
>>> using device-properties. Device-properties are nice when
>>> getting info from firmware, but this is not that.
>>
>>
>> OK
>>
>>> Also one of the things passed is actually a function
>>> pointer to a function to get extra power_supply_properties
>>> from the fuel-gauge, and passing function pointers certainly
>>> is not something which should be done through device-props.
>>>
>>>>
>>>>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>>>>
>>>>
>>>>
>>>> Add to all BQ24190 patches:
>>>> Cc: Liam Breck <kernel@networkimprov.net>
>>>> Cc: Tony Lindgren <tony@atomide.com>
>>>>
>>>> Pls don't CC me on the related patchsets.
>>>>
>>>>> ---
>>>>>  drivers/power/supply/bq24190_charger.c | 5 +++++
>>>>>  include/linux/power/bq24190_charger.h  | 1 +
>>>>>  2 files changed, 6 insertions(+)
>>>>>
>>>>> diff --git a/drivers/power/supply/bq24190_charger.c
>>>>> b/drivers/power/supply/bq24190_charger.c
>>>>> index a4f0849..c92a40e4 100644
>>>>> --- a/drivers/power/supply/bq24190_charger.c
>>>>> +++ b/drivers/power/supply/bq24190_charger.c
>>>>> @@ -151,6 +151,7 @@ struct bq24190_dev_info {
>>>>>         struct device                   *dev;
>>>>>         struct power_supply             *charger;
>>>>>         struct power_supply             *battery;
>>>>> +       struct bq24190_platform_data    *pdata;
>>>>
>>>>
>>>>
>>>> Use a register settings array/struct here, instead of platform-data.
>>>> None
>>>> of your other patches need
>>>> to retain pdata.
>>>
>>>
>>>
>>> Sure I can make a 1:1 copy of each field in pdata here, but that
>>> is just more lines of code for the same result.
>>
>>
>> I mean record the chip's UEFI-supplied state here.
>
>
> Ok, so a flag get state from chip in platform_data would be
> an acceptable solution to me as then I can re-use all the
> code in bq24190_charger.c to go from register values to
> uA (and uV).

Yes, recording chip state in probe is an alternative to hard-coding
values in platform_data. But I think you should do the latter, so you
get a known charger config. Maybe a later version of the board has an
undesirable value.

>> Currently
>> no_register_reset appears to be the only pdata field used after
>> probe()
>
>
> The get_ext_bat_property callback also gets used after probe, but
> that could be a separate variable in bq24190_dev_info.

Um, well I already gave you my thoughts on this :-)

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [08/15] power: supply: bq24190_charger: Add support for external fuel gauge
  2017-03-18 23:02         ` Hans de Goede
@ 2017-03-19  1:01           ` Liam Breck
  2017-03-19  3:52           ` Liam Breck
  1 sibling, 0 replies; 90+ messages in thread
From: Liam Breck @ 2017-03-19  1:01 UTC (permalink / raw)
  To: Hans de Goede; +Cc: Andy Shevchenko, Sebastian Reichel, Tony Lindgren, linux-pm

On Sat, Mar 18, 2017 at 4:02 PM, Hans de Goede <hdegoede@redhat.com> wrote:
> Hi,
>
> On 18-03-17 20:18, Liam Breck wrote:
>>
>> On Sat, Mar 18, 2017 at 7:31 AM, Hans de Goede <hdegoede@redhat.com>
>> wrote:
>>>
>>> Hi,
>>>
>>> On 18-03-17 08:10, Liam Breck wrote:
>>>>
>>>>
>>>> On Fri, 17 Mar 2017 10:55:20 +0100, Hans de Goede wrote:
>>>>
>>>>> Some platforms with a bq24190_charger have an external fuel gauge which
>>>>> makes it possible to reliably report battery (dis)charge state, at
>>>>> support for this by adding an optional get_ext_bat_property callback
>>>>> to the platform_data and using this if the platform provides it.
>>>>
>>>>
>>>>
>>>> Please do not pollute the charger with fuel-gauge functionality; use the
>>>> gauge driver directly.
>>>
>>>
>>>
>>> That is not how the userspace ABI works, the userspace ABI says one
>>> battery one power_supply device, so we need to combine the data from
>>> the 2 sources.
>>
>>
>> Reference?
>
>
> This is just how things work, if you define 2 battery type power-supplies
> upower will export battery info for 2 batteries to userspace and
> battery panel applets will show 2 batteries (which is useful for
> laptops which actually have 2 batteries like eg the Lenovo T440, X240, etc.
> which have both an internal battery and a replace battery at the back.

You said ABI; are there docs?

>> See patch 04 discussion about fuel-gauge as primary point of contact.
>>
>> Another approach to consider: a pseudo-driver which uses sysfs or
>> callbacks into two actual drivers.
>
>
> Already answered in the patch 04 discussion.
>
>>>> And calling into a mystery module with a pointer from platform-data is
>>>> scary! St. Patrick's
>>>> Day is wrong for this; try April Fool's or Halloween ;-)
>>>
>>>
>>>
>>> Since we control both the caller and the callee I fail to see how
>>> this is scary in any way.
>>
>>
>> This patch looks like a hack to me. Pls find another way.
>
>
> Poking sysfs files from kernelspace is a much bugger hack, that +
> the code duplication required in making the fuel-gauge the leading
> driver really makes me believe this "hack" is the best solution.
>
> Also keep in mind that the fuel-gauge has no status interrupt for
> events like power getting plugged in charging being done, fault
> interrupts, etc. So we would also need some way to tap into
> the bq24190's interrupt from the fuel-gauge driver.
>
> Anways lets continue this discussion in the patch 04 part
> of the thread.
>
>
> Regards,
>
> Hans
>
>
>
>
>>>>> By convention the callback will return -ENXIO when it is not ready yet,
>>>>> or the driver providing it has been unbound from its device. Since it
>>>>> returns the same error when unbound it cannot return -EPROBE_DEFER
>>>>> as that is not a valid errno.
>>>>>
>>>>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>>>>> ---
>>>>>  drivers/power/supply/bq24190_charger.c | 41
>>>>> +++++++++++++++++++++++++++++++---
>>>>>  include/linux/power/bq24190_charger.h  |  4 ++++
>>>>>  2 files changed, 42 insertions(+), 3 deletions(-)
>>>>>
>>>>> diff --git a/drivers/power/supply/bq24190_charger.c
>>>>> b/drivers/power/supply/bq24190_charger.c
>>>>> index 9014dee..9fe69a5 100644
>>>>> --- a/drivers/power/supply/bq24190_charger.c
>>>>> +++ b/drivers/power/supply/bq24190_charger.c
>>>>> @@ -1111,7 +1111,10 @@ static int bq24190_battery_get_property(struct
>>>>> power_supply *psy,
>>>>>                 ret = 0;
>>>>>                 break;
>>>>>         default:
>>>>> -               ret = -ENODATA;
>>>>> +               if (bdi->pdata && bdi->pdata->get_ext_bat_property)
>>>>> +                       ret = bdi->pdata->get_ext_bat_property(psp,
>>>>> val);
>>>>> +               else
>>>>> +                       ret = -ENODATA;
>>>>>         }
>>>>>
>>>>>         pm_runtime_put_sync(bdi->dev);
>>>>> @@ -1168,12 +1171,31 @@ static enum power_supply_property
>>>>> bq24190_battery_properties[] = {
>>>>>         POWER_SUPPLY_PROP_TECHNOLOGY,
>>>>>         POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
>>>>>         POWER_SUPPLY_PROP_SCOPE,
>>>>> +       /* Begin of extended battery properties */
>>>>> +       POWER_SUPPLY_PROP_VOLTAGE_NOW,
>>>>> +       POWER_SUPPLY_PROP_VOLTAGE_AVG,
>>>>> +       POWER_SUPPLY_PROP_VOLTAGE_OCV,
>>>>> +       POWER_SUPPLY_PROP_CURRENT_NOW,
>>>>> +       POWER_SUPPLY_PROP_CURRENT_AVG,
>>>>> +       POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
>>>>> +       POWER_SUPPLY_PROP_CHARGE_FULL,
>>>>> +       POWER_SUPPLY_PROP_CHARGE_NOW,
>>>>>  };
>>>>>
>>>>>  static const struct power_supply_desc bq24190_battery_desc = {
>>>>>         .name                   = "bq24190-battery",
>>>>>         .type                   = POWER_SUPPLY_TYPE_BATTERY,
>>>>>         .properties             = bq24190_battery_properties,
>>>>> +       .num_properties         = 6,
>>>>> +       .get_property           = bq24190_battery_get_property,
>>>>> +       .set_property           = bq24190_battery_set_property,
>>>>> +       .property_is_writeable  =
>>>>> bq24190_battery_property_is_writeable,
>>>>> +};
>>>>> +
>>>>> +static const struct power_supply_desc bq24190_ext_battery_desc = {
>>>>> +       .name                   = "bq24190-battery",
>>>>> +       .type                   = POWER_SUPPLY_TYPE_BATTERY,
>>>>> +       .properties             = bq24190_battery_properties,
>>>>>         .num_properties         =
>>>>> ARRAY_SIZE(bq24190_battery_properties),
>>>>>         .get_property           = bq24190_battery_get_property,
>>>>>         .set_property           = bq24190_battery_set_property,
>>>>> @@ -1336,6 +1358,15 @@ static int bq24190_probe(struct i2c_client
>>>>> *client,
>>>>>                 return -EINVAL;
>>>>>         }
>>>>>
>>>>> +       if (bdi->pdata && bdi->pdata->get_ext_bat_property) {
>>>>> +               union power_supply_propval val;
>>>>> +
>>>>> +               /* Check external fuel gauge is ready */
>>>>> +               ret = bdi->pdata->get_ext_bat_property(0, &val);
>>>>> +               if (ret == -ENXIO)
>>>>> +                       return -EPROBE_DEFER;
>>>>> +       }
>>>>> +
>>>>>         pm_runtime_enable(dev);
>>>>>         pm_runtime_resume(dev);
>>>>>
>>>>> @@ -1357,8 +1388,12 @@ static int bq24190_probe(struct i2c_client
>>>>> *client,
>>>>>         }
>>>>>
>>>>>         battery_cfg.drv_data = bdi;
>>>>> -       bdi->battery = power_supply_register(dev,
>>>>> &bq24190_battery_desc,
>>>>> -                                               &battery_cfg);
>>>>> +       if (bdi->pdata && bdi->pdata->get_ext_bat_property)
>>>>> +               bdi->battery = power_supply_register(dev,
>>>>> +                                   &bq24190_ext_battery_desc,
>>>>> &battery_cfg);
>>>>> +       else
>>>>> +               bdi->battery = power_supply_register(dev,
>>>>> +                                   &bq24190_battery_desc,
>>>>> &battery_cfg);
>>>>>         if (IS_ERR(bdi->battery)) {
>>>>>                 dev_err(dev, "Can't register battery\n");
>>>>>                 ret = PTR_ERR(bdi->battery);
>>>>> diff --git a/include/linux/power/bq24190_charger.h
>>>>> b/include/linux/power/bq24190_charger.h
>>>>> index 8d918cb..02d248b 100644
>>>>> --- a/include/linux/power/bq24190_charger.h
>>>>> +++ b/include/linux/power/bq24190_charger.h
>>>>> @@ -9,8 +9,12 @@
>>>>>  #ifndef _BQ24190_CHARGER_H_
>>>>>  #define _BQ24190_CHARGER_H_
>>>>>
>>>>> +#include <linux/power_supply.h>
>>>>> +
>>>>>  struct bq24190_platform_data {
>>>>>         bool no_register_reset;
>>>>> +       int (*get_ext_bat_property)(enum power_supply_property prop,
>>>>> +                                   union power_supply_propval *val);
>>>>>  };
>>>>>
>>>>>  #endif
>>>>
>>>>
>>>>
>>>
>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [08/15] power: supply: bq24190_charger: Add support for external fuel gauge
  2017-03-18 23:02         ` Hans de Goede
  2017-03-19  1:01           ` Liam Breck
@ 2017-03-19  3:52           ` Liam Breck
  1 sibling, 0 replies; 90+ messages in thread
From: Liam Breck @ 2017-03-19  3:52 UTC (permalink / raw)
  To: Hans de Goede; +Cc: Andy Shevchenko, Sebastian Reichel, Tony Lindgren, linux-pm

On Sat, Mar 18, 2017 at 4:02 PM, Hans de Goede <hdegoede@redhat.com> wrote:
> Hi,
>
> On 18-03-17 20:18, Liam Breck wrote:
>>
>> On Sat, Mar 18, 2017 at 7:31 AM, Hans de Goede <hdegoede@redhat.com>
>> wrote:
>>>
>>> Hi,
>>>
>>> On 18-03-17 08:10, Liam Breck wrote:
>>>>
>>>>
>>>> On Fri, 17 Mar 2017 10:55:20 +0100, Hans de Goede wrote:
>>>>
>>>>> Some platforms with a bq24190_charger have an external fuel gauge which
>>>>> makes it possible to reliably report battery (dis)charge state, at
>>>>> support for this by adding an optional get_ext_bat_property callback
>>>>> to the platform_data and using this if the platform provides it.
>>>>
>>>>
>>>>
>>>> Please do not pollute the charger with fuel-gauge functionality; use the
>>>> gauge driver directly.
>>>
>>>
>>>
>>> That is not how the userspace ABI works, the userspace ABI says one
>>> battery one power_supply device, so we need to combine the data from
>>> the 2 sources.
>>
>>
>> Reference?
>
>
> This is just how things work, if you define 2 battery type power-supplies
> upower will export battery info for 2 batteries to userspace and
> battery panel applets will show 2 batteries (which is useful for
> laptops which actually have 2 batteries like eg the Lenovo T440, X240, etc.
> which have both an internal battery and a replace battery at the back.

Have you looked into patching upower? I'd say the de facto ABI is
separate charger and gauge devices...

>> See patch 04 discussion about fuel-gauge as primary point of contact.
>>
>> Another approach to consider: a pseudo-driver which uses sysfs or
>> callbacks into two actual drivers.
>
>
> Already answered in the patch 04 discussion.
>
>>>> And calling into a mystery module with a pointer from platform-data is
>>>> scary! St. Patrick's
>>>> Day is wrong for this; try April Fool's or Halloween ;-)
>>>
>>>
>>>
>>> Since we control both the caller and the callee I fail to see how
>>> this is scary in any way.
>>
>>
>> This patch looks like a hack to me. Pls find another way.
>
>
> Poking sysfs files from kernelspace is a much bugger hack, that +
> the code duplication required in making the fuel-gauge the leading
> driver really makes me believe this "hack" is the best solution.
>
> Also keep in mind that the fuel-gauge has no status interrupt for
> events like power getting plugged in charging being done, fault
> interrupts, etc. So we would also need some way to tap into
> the bq24190's interrupt from the fuel-gauge driver.
>
> Anways lets continue this discussion in the patch 04 part
> of the thread.
>
>
> Regards,
>
> Hans
>
>
>
>
>>>>> By convention the callback will return -ENXIO when it is not ready yet,
>>>>> or the driver providing it has been unbound from its device. Since it
>>>>> returns the same error when unbound it cannot return -EPROBE_DEFER
>>>>> as that is not a valid errno.
>>>>>
>>>>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>>>>> ---
>>>>>  drivers/power/supply/bq24190_charger.c | 41
>>>>> +++++++++++++++++++++++++++++++---
>>>>>  include/linux/power/bq24190_charger.h  |  4 ++++
>>>>>  2 files changed, 42 insertions(+), 3 deletions(-)
>>>>>
>>>>> diff --git a/drivers/power/supply/bq24190_charger.c
>>>>> b/drivers/power/supply/bq24190_charger.c
>>>>> index 9014dee..9fe69a5 100644
>>>>> --- a/drivers/power/supply/bq24190_charger.c
>>>>> +++ b/drivers/power/supply/bq24190_charger.c
>>>>> @@ -1111,7 +1111,10 @@ static int bq24190_battery_get_property(struct
>>>>> power_supply *psy,
>>>>>                 ret = 0;
>>>>>                 break;
>>>>>         default:
>>>>> -               ret = -ENODATA;
>>>>> +               if (bdi->pdata && bdi->pdata->get_ext_bat_property)
>>>>> +                       ret = bdi->pdata->get_ext_bat_property(psp,
>>>>> val);
>>>>> +               else
>>>>> +                       ret = -ENODATA;
>>>>>         }
>>>>>
>>>>>         pm_runtime_put_sync(bdi->dev);
>>>>> @@ -1168,12 +1171,31 @@ static enum power_supply_property
>>>>> bq24190_battery_properties[] = {
>>>>>         POWER_SUPPLY_PROP_TECHNOLOGY,
>>>>>         POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
>>>>>         POWER_SUPPLY_PROP_SCOPE,
>>>>> +       /* Begin of extended battery properties */
>>>>> +       POWER_SUPPLY_PROP_VOLTAGE_NOW,
>>>>> +       POWER_SUPPLY_PROP_VOLTAGE_AVG,
>>>>> +       POWER_SUPPLY_PROP_VOLTAGE_OCV,
>>>>> +       POWER_SUPPLY_PROP_CURRENT_NOW,
>>>>> +       POWER_SUPPLY_PROP_CURRENT_AVG,
>>>>> +       POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
>>>>> +       POWER_SUPPLY_PROP_CHARGE_FULL,
>>>>> +       POWER_SUPPLY_PROP_CHARGE_NOW,
>>>>>  };
>>>>>
>>>>>  static const struct power_supply_desc bq24190_battery_desc = {
>>>>>         .name                   = "bq24190-battery",
>>>>>         .type                   = POWER_SUPPLY_TYPE_BATTERY,
>>>>>         .properties             = bq24190_battery_properties,
>>>>> +       .num_properties         = 6,
>>>>> +       .get_property           = bq24190_battery_get_property,
>>>>> +       .set_property           = bq24190_battery_set_property,
>>>>> +       .property_is_writeable  =
>>>>> bq24190_battery_property_is_writeable,
>>>>> +};
>>>>> +
>>>>> +static const struct power_supply_desc bq24190_ext_battery_desc = {
>>>>> +       .name                   = "bq24190-battery",
>>>>> +       .type                   = POWER_SUPPLY_TYPE_BATTERY,
>>>>> +       .properties             = bq24190_battery_properties,
>>>>>         .num_properties         =
>>>>> ARRAY_SIZE(bq24190_battery_properties),
>>>>>         .get_property           = bq24190_battery_get_property,
>>>>>         .set_property           = bq24190_battery_set_property,
>>>>> @@ -1336,6 +1358,15 @@ static int bq24190_probe(struct i2c_client
>>>>> *client,
>>>>>                 return -EINVAL;
>>>>>         }
>>>>>
>>>>> +       if (bdi->pdata && bdi->pdata->get_ext_bat_property) {
>>>>> +               union power_supply_propval val;
>>>>> +
>>>>> +               /* Check external fuel gauge is ready */
>>>>> +               ret = bdi->pdata->get_ext_bat_property(0, &val);
>>>>> +               if (ret == -ENXIO)
>>>>> +                       return -EPROBE_DEFER;
>>>>> +       }
>>>>> +
>>>>>         pm_runtime_enable(dev);
>>>>>         pm_runtime_resume(dev);
>>>>>
>>>>> @@ -1357,8 +1388,12 @@ static int bq24190_probe(struct i2c_client
>>>>> *client,
>>>>>         }
>>>>>
>>>>>         battery_cfg.drv_data = bdi;
>>>>> -       bdi->battery = power_supply_register(dev,
>>>>> &bq24190_battery_desc,
>>>>> -                                               &battery_cfg);
>>>>> +       if (bdi->pdata && bdi->pdata->get_ext_bat_property)
>>>>> +               bdi->battery = power_supply_register(dev,
>>>>> +                                   &bq24190_ext_battery_desc,
>>>>> &battery_cfg);
>>>>> +       else
>>>>> +               bdi->battery = power_supply_register(dev,
>>>>> +                                   &bq24190_battery_desc,
>>>>> &battery_cfg);
>>>>>         if (IS_ERR(bdi->battery)) {
>>>>>                 dev_err(dev, "Can't register battery\n");
>>>>>                 ret = PTR_ERR(bdi->battery);
>>>>> diff --git a/include/linux/power/bq24190_charger.h
>>>>> b/include/linux/power/bq24190_charger.h
>>>>> index 8d918cb..02d248b 100644
>>>>> --- a/include/linux/power/bq24190_charger.h
>>>>> +++ b/include/linux/power/bq24190_charger.h
>>>>> @@ -9,8 +9,12 @@
>>>>>  #ifndef _BQ24190_CHARGER_H_
>>>>>  #define _BQ24190_CHARGER_H_
>>>>>
>>>>> +#include <linux/power_supply.h>
>>>>> +
>>>>>  struct bq24190_platform_data {
>>>>>         bool no_register_reset;
>>>>> +       int (*get_ext_bat_property)(enum power_supply_property prop,
>>>>> +                                   union power_supply_propval *val);
>>>>>  };
>>>>>
>>>>>  #endif
>>>>
>>>>
>>>>
>>>
>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [04/15] power: supply: bq24190_charger: Add no_register_reset pdata flag
  2017-03-19  0:57           ` Liam Breck
@ 2017-03-19  8:22             ` Hans de Goede
  2017-03-19  9:42               ` Hans de Goede
  2017-03-19 14:54             ` Andy Shevchenko
  1 sibling, 1 reply; 90+ messages in thread
From: Hans de Goede @ 2017-03-19  8:22 UTC (permalink / raw)
  To: Liam Breck
  Cc: Andy Shevchenko, Sebastian Reichel, Tony Lindgren, linux-pm, Liam Breck

Hi,

On 19-03-17 01:57, Liam Breck wrote:
> Hi Hans,
>
> I realize you put a ton of work into this patchset. Pls know that I
> want you to end up with a solution that both works for you, and makes
> the charger driver more generally useful. All of my critique is
> offered in good faith, and not meant as rejection. I genuinely regret
> it if you feel otherwise.

While we are being candid I'm a bit surprised about how you're claiming
maintainership / ownership of the bq24190_charger driver and are acting
as if you are *the* authority on it. MAINTAINERS seems to disagree
with you.

You seem to have started contributing to the kernel about 6 months ago
going from git logs. I'm an experienced FOSS developer with 10+ years
of upstream kernel involvement and 2000+ commits on my name.

As such I'm finding it difficult to accept your authority on this and
some of your questions like "Have you looked into patching upower"
certainly do not help here. We can not EVER NEVER change userspace
if an ABI is already in place and widely used. We can extend / add
new ABIs but we cannot just go and change what userspace can expect
of an existing ABI.

Also you do not seem to understand what being a good maintainer
involves. All I see you do is throwing up roadblocks without offering
*workable* alternatives. Being a good maintainer is not just about
saying no, it is far more about thinking with the contributor and
helping them to find a good solution. Being a maintainer is much
more of a role where you help others then where you get to dictate
them what to do.

 > Then consider the pseudo-driver concept. That would be generally
 > useful for any charger/gauge pairing. Both drivers would provide
 > callbacks to it.

So your rejecting a patch which adds 30 lines of code for some
vague generic pseudo-driver concept without offering any design
direction on what such a concept would look like and without taking
into account that so far this seems to be a one-of problem.

Usually the rule in the kernel is that we do not introduce generic
solutions until we've at least 2 or 3 use-cases for it, both so
that we understand the problem better and so that we are sure
this actually is a generic problem which is worth the effort of
writing a generic solution for. Doing a generic solution now,
when we do not even fully understand the problem space seems
like over-engineering to me. Note that this is an in kernel
interface so we can always fix it later if a generic solution
is called for. But right now you are asking me to write something
which I do not even know what it should look like, will likely
be 1000+ lines of code and a lot of work and all that to avoid a
simple 30 line patch, which I will gladly admit is not the prettiest
but really is not that ugly either.

> Pls consider my feedback for a couple days; I put a lot of thought into it.

Try looking at this form my pov, as I wrote your asking me to
write some 1000+ line generic solution for something which might
well be a one-of problem, while we've no idea what such a generic
solution should look like (esp. since we have only one real-world
example of the problem so far) and you're offering 0 design assistance
in the process, all to avoid a not pretty but very serviceable patch
adding 30 lines of code.

Before you reply to this I'm going to ask you the same as you're
asking me. Please let my carefully considered and worded reply sink
in a bit before answering.

>> Assuming the platform_data has sane values like uA that means
>> re-implementing most of the bq24190 driver in the code filling
>> the platform data (to go from register values to uA) that does
>> not seem like a sane approach when a simple do not reset
>> flag suffices. Note also see below for another way to deal
>> with this.
>
> I am suggesting you treat platform_data like a DT node: fill it with
> board-specific params. Don't compute the params, read them manually
> via /sys/class/...-charger/f_* and hard-code them for this board. That
> gives you control over the charger config. You've already found that
> you need that given the high voltage setting.

This is not going to work, I realize this is how things are
done on ARM, but there are likely at least a 100 designs with
this Cherry Trail Whiskey Cove + TI charger combo and on x86 people
expect to be able to just take a generic kernel from a distro and
have it work without first needing to write a dts (or some equivalent)
so we really need to extract the info from the BIOS, which in this
case means reading back the values from the registers since the BIOS
offers no other interface (that we know of) to get those params.

>>> The driver does a register_reset on resume so it has a consistent
>>> state with chip.
>>
>>
>> That assumes someone may be mucking with the chip during
>> suspend which usually is not the case arguably this is a
>> bad idea in general since if the chip is programmed with
>> lower then reset charging limits it may now charge above
>> the limits until the limits are re-applied.
>>
>> I really wonder what the reset is there for at all TBH,
>> are there any cases where this really is necessary ?
>> Maybe it would be best to just drop the reset altogether,
>> or make it opt in rather then opt out.
>
> The reason is to put the driver back into autonomous mode while we're
> asleep. Otherwise we run in host mode.

You do not need to do a reset for that you can just re-enable
the host activity watchdog, that would actually be a better
solution as then you keep the charging settings as is without
needing to re-apply them after the reset. Note that if you
re-apply the settings after reset you are also kicking the
charger back into host mode since any host-activity does
that, the only difference from before the reset is that the
watchdog is now running again, see the statemachine in 8.4.1
of the datasheet. You can get the same effect with a single
i2c write re-enabling the watchdog.

>> Yes I've asked both the manufacturer and the chip vendor (Intel)
>> for docs, but I've not gotten an answer from either.
>
> Maybe someone at Redhat could make a formal request on your behalf?

I've quite good contacts inside Intel myself and I've already
made such a request, but without any result.

>>> I mean record the chip's UEFI-supplied state here.
>>
>>
>> Ok, so a flag get state from chip in platform_data would be
>> an acceptable solution to me as then I can re-use all the
>> code in bq24190_charger.c to go from register values to
>> uA (and uV).
>
> Yes, recording chip state in probe is an alternative to hard-coding
> values in platform_data. But I think you should do the latter, so you
> get a known charger config. Maybe a later version of the board has an
> undesirable value.

As mentioned before there is no such thing as a "board specific config"
in x86, all x86 code is generic and should run on any x86 board.

Regards,

Hans

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [04/15] power: supply: bq24190_charger: Add no_register_reset pdata flag
  2017-03-19  8:22             ` Hans de Goede
@ 2017-03-19  9:42               ` Hans de Goede
  2017-03-20  5:27                 ` Sebastian Reichel
  0 siblings, 1 reply; 90+ messages in thread
From: Hans de Goede @ 2017-03-19  9:42 UTC (permalink / raw)
  To: Liam Breck
  Cc: Andy Shevchenko, Sebastian Reichel, Tony Lindgren, linux-pm, Liam Breck

Hi Liam,

On 19-03-17 09:22, Hans de Goede wrote:
> Hi,

<snip>

>> Then consider the pseudo-driver concept. That would be generally
>> useful for any charger/gauge pairing. Both drivers would provide
>> callbacks to it.
>
> So your rejecting a patch which adds 30 lines of code for some
> vague generic pseudo-driver concept without offering any design
> direction on what such a concept would look like and without taking
> into account that so far this seems to be a one-of problem.

I still think the pseudo-driver idea is a bad idea. Having 1 driver
which somehow combines things from 2 drivers without clear semantics
feels wrong.

As said before I think your suggested solution lacks any
design direction, I've been thinking about this a bit more and
I've come up with an alternative solution with clearly defined
goals and semantics.

We want one driver which is solidly in control of the charger
since getting that wrong is quite bad and we want to extend
the information it is exporting to userspace in the form of
power_supply properties with some extra info.

So taking that as a starting point and generalizing that,
I think that if we want we can make something more generic then
my original patch for this. My idea is to introduce something
called a power_supply_properties_provider, with an API
like this:

typedef int (*power_supply_properties_provider_get_property_t)(
	enum power_supply_property prop, union power_supply_propval *val,
	void *driver_data);

struct power_supply_properties_provider;

struct power_supply_properties_provider *
power_supply_properties_provider_register(
	const char *name,
	power_supply_properties_provider_get_property_t get_property,
	const enum power_supply_property *properties,
	size_t num_properties,
	void *driver_data);

void power_supply_properties_provider_unregister(
	struct power_supply_properties_provider *pspp);

struct power_supply_properties_provider *
	power_supply_properties_provider_get(const char *name);

void power_supply_properties_provider_put(
	struct power_supply_properties_provider *pspp);

int power_supply_properties_provider_merge_properties(
	struct power_supply_properties_provider *pspp,
	const enum power_supply_property *properties,
	size_t num_properties,
	enum power_supply_property **merged_properties_ret,
	size_t *merged_num_properties_ret);

int power_supply_properties_provider_get_property(
	struct power_supply_properties_provider *pspp,
	enum power_supply_property prop,
	union power_supply_propval *val);

So in this case the faul-gauge driver would call
power_supply_properties_provider_register() from probe and
power_supply_properties_provider_unregister() from remove.

The struct power_supply_properties_provider will be ref-counted
so that it will stick around after unregister in case any
consumers who have gotten a ref through
power_supply_properties_provider_get can still call
power_supply_properties_provider_get_property, which after
unregister will simply always return -ENXIO.

A driver wanting to use extra properties like bq24190_charger
will call power_supply_properties_provider_get (with a name
provided through platform_data), use a dynamically allocated
struct power_supply_desc and fill the properties of that
using power_supply_properties_provider_merge_properties
to merge its own properties with the
power_supply_properties_provider's properties and in its
get_property method have a default label which calls
power_supply_properties_provider_get_property.

This would still add quite a bit more code then my original
patch for what may very well end up being a one-of solution,
but I guess we may encounter this problem more often and
this will offer a nice generic and clean way for dealing
with adding extra info from other sources to a power_supply
driver, so I'm happy to turn this idea / design into working
code if people like this better then my original patch.

Liam, Sebastian what do you think of the above proposal?

Regards,

Hans

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [04/15] power: supply: bq24190_charger: Add no_register_reset pdata flag
  2017-03-19  0:57           ` Liam Breck
  2017-03-19  8:22             ` Hans de Goede
@ 2017-03-19 14:54             ` Andy Shevchenko
  2017-03-19 18:13               ` Hans de Goede
  1 sibling, 1 reply; 90+ messages in thread
From: Andy Shevchenko @ 2017-03-19 14:54 UTC (permalink / raw)
  To: Liam Breck, Hans de Goede
  Cc: Sebastian Reichel, Tony Lindgren, linux-pm, Liam Breck

On Sat, 2017-03-18 at 17:57 -0700, Liam Breck wrote:

>> Assuming the platform_data has sane values like uA that means
> > re-implementing most of the bq24190 driver in the code filling
> > the platform data (to go from register values to uA) that does
> > not seem like a sane approach when a simple do not reset
> > flag suffices. Note also see below for another way to deal
> > with this.
> 
> I am suggesting you treat platform_data like a DT node: fill it with
> board-specific params. Don't compute the params, read them manually
> via /sys/class/...-charger/f_* and hard-code them for this board. That
> gives you control over the charger config. You've already found that
> you need that given the high voltage setting.

Guys, did you see my mail regarding all these?

Repeating myself here:

"I would not extend platform data at all.
For GPIO we may use GPIO lookup tables, for the rest -- unified (built-
in) device properties API.

Consider to get rid of 
 include/linux/power/bq24190_charger.h
completely."

Do you consider that approach? If no, why not?

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [04/15] power: supply: bq24190_charger: Add no_register_reset pdata flag
  2017-03-19 14:54             ` Andy Shevchenko
@ 2017-03-19 18:13               ` Hans de Goede
  0 siblings, 0 replies; 90+ messages in thread
From: Hans de Goede @ 2017-03-19 18:13 UTC (permalink / raw)
  To: Andy Shevchenko, Liam Breck
  Cc: Sebastian Reichel, Tony Lindgren, linux-pm, Liam Breck

Hi Andy,

On 19-03-17 15:54, Andy Shevchenko wrote:
> On Sat, 2017-03-18 at 17:57 -0700, Liam Breck wrote:
>
>>> Assuming the platform_data has sane values like uA that means
>>> re-implementing most of the bq24190 driver in the code filling
>>> the platform data (to go from register values to uA) that does
>>> not seem like a sane approach when a simple do not reset
>>> flag suffices. Note also see below for another way to deal
>>> with this.
>>
>> I am suggesting you treat platform_data like a DT node: fill it with
>> board-specific params. Don't compute the params, read them manually
>> via /sys/class/...-charger/f_* and hard-code them for this board. That
>> gives you control over the charger config. You've already found that
>> you need that given the high voltage setting.
>
> Guys, did you see my mail regarding all these?

Yes I did, thank you for all the reviews! I still need to go
over them one by one. From the top of my head I agree with most of
your comments and will fix them for the next version.

One thing I disagree with is the cht_wc > chtwc rename you are
proposing for one Cherry Trail and Whiskey Cove are 2 different
words (4 if you look at spelling but 2 if you look at pronunciation,
so IMHO cht_wc is more readable other then that I see the suggested
rename as a lot of extra churn without any tangible benefits.

> Repeating myself here:
>
> "I would not extend platform data at all.
> For GPIO we may use GPIO lookup tables, for the rest -- unified (built-
> in) device properties API.
>
> Consider to get rid of
>  include/linux/power/bq24190_charger.h
> completely."
>
> Do you consider that approach? If no, why not?

Liam asked more or less the same question and I answered with:

"Since this is info being passed around inside the kernel
using platform_data is a hell of a lot simpler (and cleaner
no need to check types, etc on the receiving side) then
using device-properties. Device-properties are nice when
getting info from firmware, but this is not that.

Also one of the things passed is actually a function
pointer to a function to get extra power_supply_properties
from the fuel-gauge, and passing function pointers certainly
is not something which should be done through device-props."

Now the function pointer bit is possibly going away but
it still feels wrong to first pack some native C-type into
a device-prop and then needing to unpack it on the other
side using platform_data for passing things along which
are purely in kernel really is a lot easier.

Regards,

Hans

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH 03/15] extcon: cht-wc: Add Intel Cherry Trail Whiskey Cove PMIC extcon driver
  2017-03-17  9:55 ` [PATCH 03/15] extcon: cht-wc: Add Intel Cherry Trail Whiskey Cove PMIC extcon driver Hans de Goede
  2017-03-17 17:18   ` Andy Shevchenko
@ 2017-03-20  1:33   ` Chanwoo Choi
  2017-03-20 13:00     ` Andy Shevchenko
  2017-03-20 19:57     ` Hans de Goede
  1 sibling, 2 replies; 90+ messages in thread
From: Chanwoo Choi @ 2017-03-20  1:33 UTC (permalink / raw)
  To: Hans de Goede, Rafael J . Wysocki, Len Brown, Wolfram Sang,
	Andy Shevchenko, Lee Jones, Sebastian Reichel, MyungJoo Ham
  Cc: linux-acpi, Takashi Iwai, linux-i2c, linux-kernel, linux-pm

Hi,

On 2017년 03월 17일 18:55, Hans de Goede wrote:
> Add a driver for charger detection / control on the Intel Cherrytrail
> Whiskey Cove PMIC.
> 
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
>  drivers/extcon/Kconfig         |   7 +
>  drivers/extcon/Makefile        |   1 +
>  drivers/extcon/extcon-cht-wc.c | 356 +++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 364 insertions(+)
>  create mode 100644 drivers/extcon/extcon-cht-wc.c
> 
> diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
> index 96bbae5..4cace6b 100644
> --- a/drivers/extcon/Kconfig
> +++ b/drivers/extcon/Kconfig
> @@ -52,6 +52,13 @@ config EXTCON_INTEL_INT3496
>  	  This ACPI device is typically found on Intel Baytrail or Cherrytrail
>  	  based tablets, or other Baytrail / Cherrytrail devices.
>  
> +config EXTCON_CHT_WC

Need to reorder it alpabetically as the following Makefile.

> +	tristate "Intel Cherrytrail Whiskey Cove PMIC extcon driver"
> +	depends on INTEL_SOC_PMIC_CHTWC
> +	help
> +	  Say Y here to enable extcon support for charger detection / control
> +	  on the Intel Cherrytrail Whiskey Cove PMIC.
> +
>  config EXTCON_MAX14577
>  	tristate "Maxim MAX14577/77836 EXTCON Support"
>  	depends on MFD_MAX14577
> diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile
> index 237ac3f..160f88b 100644
> --- a/drivers/extcon/Makefile
> +++ b/drivers/extcon/Makefile
> @@ -7,6 +7,7 @@ extcon-core-objs		+= extcon.o devres.o
>  obj-$(CONFIG_EXTCON_ADC_JACK)	+= extcon-adc-jack.o
>  obj-$(CONFIG_EXTCON_ARIZONA)	+= extcon-arizona.o
>  obj-$(CONFIG_EXTCON_AXP288)	+= extcon-axp288.o
> +obj-$(CONFIG_EXTCON_CHT_WC)	+= extcon-cht-wc.o
>  obj-$(CONFIG_EXTCON_GPIO)	+= extcon-gpio.o
>  obj-$(CONFIG_EXTCON_INTEL_INT3496) += extcon-intel-int3496.o
>  obj-$(CONFIG_EXTCON_MAX14577)	+= extcon-max14577.o
> diff --git a/drivers/extcon/extcon-cht-wc.c b/drivers/extcon/extcon-cht-wc.c
> new file mode 100644
> index 0000000..896eee6
> --- /dev/null
> +++ b/drivers/extcon/extcon-cht-wc.c
> @@ -0,0 +1,356 @@
> +/*
> + * Extcon charger detection driver for Intel Cherrytrail Whiskey Cove PMIC
> + * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
> + *
> + * Based on various non upstream patches to support the CHT Whiskey Cove PMIC:

Maybe, you don't need to add ':' at the end of line.

> + * Copyright (C) 2013-2015 Intel Corporation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + */
> +
> +#include <linux/extcon.h>
> +#include <linux/interrupt.h>
> +#include <linux/kernel.h>
> +#include <linux/mfd/intel_soc_pmic.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/slab.h>
> +
> +#define CHT_WC_PWRSRC_IRQ		0x6e03
> +#define CHT_WC_PWRSRC_IRQ_MASK		0x6e0f
> +#define CHT_WC_PWRSRC_STS		0x6e1e
> +#define CHT_WC_PWRSRC_VBUS		BIT(0)
> +#define CHT_WC_PWRSRC_DC		BIT(1)
> +#define CHT_WC_PWRSRC_BAT		BIT(2)
> +#define CHT_WC_PWRSRC_ID_GND		BIT(3)
> +#define CHT_WC_PWRSRC_ID_FLOAT		BIT(4)
> +
> +#define CHT_WC_PHYCTRL			0x5e07
> +
> +#define CHT_WC_CHGRCTRL0		0x5e16
> +
> +#define CHT_WC_CHGRCTRL0		0x5e16
> +#define CHT_WC_CHGRCTRL0_CHGRRESET	BIT(0)
> +#define CHT_WC_CHGRCTRL0_EMRGCHREN	BIT(1)
> +#define CHT_WC_CHGRCTRL0_EXTCHRDIS	BIT(2)
> +#define CHT_WC_CHGRCTRL0_SWCONTROL	BIT(3)
> +#define CHT_WC_CHGRCTRL0_TTLCK_MASK	BIT(4)
> +#define CHT_WC_CHGRCTRL0_CCSM_OFF_MASK	BIT(5)
> +#define CHT_WC_CHGRCTRL0_DBPOFF_MASK	BIT(6)
> +#define CHT_WC_CHGRCTRL0_WDT_NOKICK	BIT(7)
> +
> +#define CHT_WC_CHGRCTRL1		0x5e17
> +
> +#define CHT_WC_USBSRC			0x5e29
> +#define CHT_WC_USBSRC_STS_MASK		GENMASK(1, 0)
> +#define CHT_WC_USBSRC_STS_SUCCESS	2
> +#define CHT_WC_USBSRC_STS_FAIL		3
> +#define CHT_WC_USBSRC_TYPE_SHIFT	2
> +#define CHT_WC_USBSRC_TYPE_MASK		GENMASK(5, 2)
> +#define CHT_WC_USBSRC_TYPE_NONE		0
> +#define CHT_WC_USBSRC_TYPE_SDP		1
> +#define CHT_WC_USBSRC_TYPE_DCP		2
> +#define CHT_WC_USBSRC_TYPE_CDP		3
> +#define CHT_WC_USBSRC_TYPE_ACA		4
> +#define CHT_WC_USBSRC_TYPE_SE1		5
> +#define CHT_WC_USBSRC_TYPE_MHL		6
> +#define CHT_WC_USBSRC_TYPE_FLOAT_DP_DN	7
> +#define CHT_WC_USBSRC_TYPE_OTHER	8
> +#define CHT_WC_USBSRC_TYPE_DCP_EXTPHY	9
> +
> +enum cht_wc_usb_id {
> +	USB_ID_OTG,
> +	USB_ID_GND,
> +	USB_ID_FLOAT,
> +	USB_RID_A,
> +	USB_RID_B,
> +	USB_RID_C,
> +};
> +
> +/* Strings matching the cht_wc_usb_id enum labels */
> +static const char * const usb_id_str[] = {
> +	"otg", "gnd", "float", "rid_a", "rid_b", "rid_c" };
> +
> +enum cht_wc_mux_select {
> +	MUX_SEL_PMIC = 0,
> +	MUX_SEL_SOC,
> +};
> +
> +static const unsigned int cht_wc_extcon_cables[] = {
> +	EXTCON_USB,
> +	EXTCON_USB_HOST,
> +	EXTCON_CHG_USB_SDP,
> +	EXTCON_CHG_USB_CDP,
> +	EXTCON_CHG_USB_DCP,
> +	EXTCON_NONE,
> +};
> +
> +struct cht_wc_extcon_data {
> +	struct device *dev;
> +	struct regmap *regmap;
> +	struct extcon_dev *edev;
> +	unsigned int previous_cable;
> +	int usb_id;
> +};
> +
> +static int cht_wc_extcon_get_id(struct cht_wc_extcon_data *ext, int pwrsrc_sts)
> +{
> +	if (ext->usb_id)
> +		return ext->usb_id;
> +
> +	if (pwrsrc_sts & CHT_WC_PWRSRC_ID_GND)
> +		return USB_ID_GND;
> +	if (pwrsrc_sts & CHT_WC_PWRSRC_ID_FLOAT)
> +		return USB_ID_FLOAT;
> +
> +	/*
> +	 * Once we have iio support for the gpadc we should read the USBID
> +	 * gpadc channel here and determine ACA role based on that.
> +	 */
> +	return USB_ID_FLOAT;
> +}
> +
> +static int cht_wc_extcon_get_charger(struct cht_wc_extcon_data *ext)
> +{
> +	int ret, usbsrc, status, retries = 5;

You have to define the constant for '5' because the name of constant
definition indicates what is meaning. So, maybe you will use the 'for' loope
instead of 'do..while'.

> +
> +	do {
> +		ret = regmap_read(ext->regmap, CHT_WC_USBSRC, &usbsrc);
> +		if (ret) {
> +			dev_err(ext->dev, "Error reading usbsrc: %d\n", ret);
> +			return ret;
> +		}

Need to add one blank line.

> +		status = usbsrc & CHT_WC_USBSRC_STS_MASK;
> +		if (status == CHT_WC_USBSRC_STS_SUCCESS ||
> +		    status == CHT_WC_USBSRC_STS_FAIL)
> +			break;
> +
> +		msleep(200);

You have to define the constant for '200' because the name of constant
definition indicates what is meaning.

> +	} while (retries--);
> +
> +	if (status != CHT_WC_USBSRC_STS_SUCCESS) {
> +		if (status == CHT_WC_USBSRC_STS_FAIL)
> +			dev_warn(ext->dev, "Could not detect charger type\n");
> +		else
> +			dev_warn(ext->dev, "Timeout detecting charger type\n");
> +		return EXTCON_CHG_USB_SDP; /* Save fallback */
> +	}
> +
> +	ret = (usbsrc & CHT_WC_USBSRC_TYPE_MASK) >> CHT_WC_USBSRC_TYPE_SHIFT;

'ret' is not proper indicates the meaning of 'CHT_WC_USBSRC_TYPE'.
You have to use the more correct local variable such as 'usbsrc_type'.

> +	switch (ret) {
> +	default:
> +		dev_warn(ext->dev, "Unhandled charger type %d\n", ret);
> +		/* Fall through treat as SDP */

Is it right? Why do you located the 'default' on the top in the switch?

> +	case CHT_WC_USBSRC_TYPE_SDP:
> +	case CHT_WC_USBSRC_TYPE_FLOAT_DP_DN:
> +	case CHT_WC_USBSRC_TYPE_OTHER:
> +		return EXTCON_CHG_USB_SDP;
> +	case CHT_WC_USBSRC_TYPE_CDP:
> +		return EXTCON_CHG_USB_CDP;
> +	case CHT_WC_USBSRC_TYPE_DCP:
> +	case CHT_WC_USBSRC_TYPE_DCP_EXTPHY:
> +	case CHT_WC_USBSRC_TYPE_MHL: /* MHL2+ delivers upto 2A, treat as DCP */
> +		return EXTCON_CHG_USB_DCP;
> +	case CHT_WC_USBSRC_TYPE_ACA:
> +		return EXTCON_CHG_USB_ACA;
> +	}
> +}
> +
> +static void cht_wc_extcon_set_phymux(struct cht_wc_extcon_data *ext, u8 state)
> +{
> +	int ret;
> +
> +	ret = regmap_write(ext->regmap, CHT_WC_PHYCTRL, state);
> +	if (ret)
> +		dev_err(ext->dev, "Error writing phyctrl: %d\n", ret);

This function is only called in the cht_wc_extcon_det_event().
Also, this funciton write only one register. It is too short.
So, you don't need to add the separate function.
You better to include this code in the cht_wc_extcon_det_event().

> +}
> +
> +static void cht_wc_extcon_det_event(struct cht_wc_extcon_data *ext)
> +{
> +	int ret, pwrsrc_sts, id;
> +	unsigned int cable = EXTCON_NONE;
> +
> +	ret = regmap_read(ext->regmap, CHT_WC_PWRSRC_STS, &pwrsrc_sts);
> +	if (ret) {
> +		dev_err(ext->dev, "Error reading pwrsrc status: %d\n", ret);
> +		return;
> +	}
> +
> +	id = cht_wc_extcon_get_id(ext, pwrsrc_sts);
> +	if (id == USB_ID_GND) {
> +		/* The 5v boost causes a false VBUS / SDP detect, skip */
> +		goto charger_det_done;
> +	}
> +
> +	/* Plugged into a host/charger or not connected? */
> +	if (!(pwrsrc_sts & CHT_WC_PWRSRC_VBUS)) {
> +		/* Route D+ and D- to PMIC for future charger detection */
> +		cht_wc_extcon_set_phymux(ext, MUX_SEL_PMIC);
> +		goto set_state;
> +	}

The cht_wc_extcon_get_id() and cht_wc_extcon_det_event() use the value
of CHT_WC_PWRSRC_STS register. So, I think you better to gather the 
code related to the CHT_WC_PWRSRC_STS for readability.
- First suggestion, remove the separate the cht_wc_extcon_get_id()
- Second suggestion, The code from regmap_read() to "!(pwrsrc_sts & CHT_WC_PWRSRC_VBUS)"
          move into the cht_wc_extcon_get_id().

In my opinion, I recommend that second way.

> +
> +	ret = cht_wc_extcon_get_charger(ext);
> +	if (ret >= 0)
> +		cable = ret;
> +
> +charger_det_done:
> +	/* Route D+ and D- to SoC for the host / gadget controller */

Minor comment.
You better to use '&' instead of '/' 

> +	cht_wc_extcon_set_phymux(ext, MUX_SEL_SOC);
> +
> +set_state:
> +	extcon_set_state_sync(ext->edev, cable, true);
> +	extcon_set_state_sync(ext->edev, ext->previous_cable, false);
> +	extcon_set_state_sync(ext->edev, EXTCON_USB_HOST,
> +			      id == USB_ID_GND || id == USB_RID_A);
> +	ext->previous_cable = cable;
> +}
> +
> +static irqreturn_t cht_wc_extcon_isr(int irq, void *data)
> +{
> +	struct cht_wc_extcon_data *ext = data;
> +	int ret, irqs;
> +
> +	ret = regmap_read(ext->regmap, CHT_WC_PWRSRC_IRQ, &irqs);
> +	if (ret)
> +		dev_err(ext->dev, "Error reading irqs: %d\n", ret);
> +
> +	cht_wc_extcon_det_event(ext);
> +
> +	ret = regmap_write(ext->regmap, CHT_WC_PWRSRC_IRQ, irqs);
> +	if (ret)
> +		dev_err(ext->dev, "Error writing irqs: %d\n", ret);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +/* usb_id sysfs attribute for debug / testing purposes */
> +static ssize_t usb_id_show(struct device *dev, struct device_attribute *attr,
> +			   char *buf)
> +{
> +	struct cht_wc_extcon_data *ext = dev_get_drvdata(dev);
> +
> +	return sprintf(buf, "%s\n", usb_id_str[ext->usb_id]);
> +}
> +
> +static ssize_t usb_id_store(struct device *dev, struct device_attribute *attr,
> +			    const char *buf, size_t n)
> +{
> +	struct cht_wc_extcon_data *ext = dev_get_drvdata(dev);
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(usb_id_str); i++) {
> +		if (sysfs_streq(buf, usb_id_str[i])) {
> +			dev_info(ext->dev, "New usb_id %s\n", usb_id_str[i]);
> +			ext->usb_id = i;
> +			cht_wc_extcon_det_event(ext);
> +			return n;
> +		}
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +static DEVICE_ATTR(usb_id, 0644, usb_id_show, usb_id_store);

I think it is not good to add specific sysfs for only this device driver.
The sysfs entry of framework must include the only common and standard interfarce
for all extcon device drivers. Because the sysfs entry affects the ABI interface.

So, It is not proper.

> +
> +static int cht_wc_extcon_probe(struct platform_device *pdev)
> +{
> +	struct cht_wc_extcon_data *ext;
> +	struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
> +	int irq, ret;
> +
> +	irq = platform_get_irq(pdev, 0);
> +	if (irq < 0)
> +		return irq;
> +
> +	ext = devm_kzalloc(&pdev->dev, sizeof(*ext), GFP_KERNEL);
> +	if (!ext)
> +		return -ENOMEM;
> +
> +	ext->dev = &pdev->dev;
> +	ext->regmap = pmic->regmap;
> +	ext->previous_cable = EXTCON_NONE;
> +
> +	/* Initialize extcon device */
> +	ext->edev = devm_extcon_dev_allocate(ext->dev, cht_wc_extcon_cables);
> +	if (IS_ERR(ext->edev))
> +		return PTR_ERR(ext->edev);
> +
> +	ret = regmap_update_bits(ext->regmap, CHT_WC_CHGRCTRL0,
> +		 CHT_WC_CHGRCTRL0_SWCONTROL | CHT_WC_CHGRCTRL0_CCSM_OFF_MASK,
> +		 CHT_WC_CHGRCTRL0_SWCONTROL | CHT_WC_CHGRCTRL0_CCSM_OFF_MASK);
> +	if (ret) {
> +		dev_err(ext->dev, "Error enabling sw control\n");
> +		return ret;
> +	}
> +
> +	/* Register extcon device */
> +	ret = devm_extcon_dev_register(ext->dev, ext->edev);
> +	if (ret) {
> +		dev_err(ext->dev, "Failed to register extcon device\n");
> +		return ret;
> +	}
> +
> +	/* Route D+ and D- to PMIC for initial charger detection */
> +	cht_wc_extcon_set_phymux(ext, MUX_SEL_PMIC);
> +
> +	/* Get initial state */
> +	cht_wc_extcon_det_event(ext);
> +
> +	ret = devm_request_threaded_irq(ext->dev, irq, NULL, cht_wc_extcon_isr,
> +					IRQF_ONESHOT, pdev->name, ext);
> +	if (ret) {
> +		dev_err(ext->dev, "Failed to request interrupt\n");
> +		return ret;
> +	}
> +
> +	/* Unmask irqs */
> +	ret = regmap_write(ext->regmap, CHT_WC_PWRSRC_IRQ_MASK,
> +			   (int)~(CHT_WC_PWRSRC_VBUS | CHT_WC_PWRSRC_ID_GND |
> +				  CHT_WC_PWRSRC_ID_FLOAT));
> +	if (ret) {
> +		dev_err(ext->dev, "Error writing irq-mask: %d\n", ret);

I prefer to use the consistent error log. In the probe function,
you use the 'Failed to ...' when error hanppen. So, You better
to use the consistent format for errr log as following:
	- "Failed to write the irq-mask: %d\n", ret);

I think it improve the readability of your device driver.

> +		return ret;
> +	}
> +
> +	platform_set_drvdata(pdev, ext);
> +	device_create_file(ext->dev, &dev_attr_usb_id);
> +
> +	return 0;


In the probe function, you touch the some register for initialization.
But, if error happen, the probe function don't restore the register value.
Is it ok? I think you need to handle the error case.

> +}
> +
> +static int cht_wc_extcon_remove(struct platform_device *pdev)
> +{
> +	struct cht_wc_extcon_data *ext = platform_get_drvdata(pdev);
> +
> +	device_remove_file(ext->dev, &dev_attr_usb_id);

Don't need it.

> +
> +	return 0;
> +}
> +
> +static const struct platform_device_id cht_wc_extcon_table[] = {
> +	{ .name = "cht_wcove_pwrsrc" },

You use the 'cht_wc' word instead of 'cht_wcove_pwrsrc'.
So, To maintain the consistency, you better to use the 'cht-wc' as the name.
- I prefer to use '-' instead of '_' in the name.
	.name ="cht-wc"

> +	{},
> +};
> +MODULE_DEVICE_TABLE(platform, cht_wc_extcon_table);
> +
> +static struct platform_driver cht_wc_extcon_driver = {
> +	.probe = cht_wc_extcon_probe,
> +	.remove = cht_wc_extcon_remove,
> +	.id_table = cht_wc_extcon_table,
> +	.driver = {
> +		.name = "cht_wcove_pwrsrc",
> +	},
> +};
> +module_platform_driver(cht_wc_extcon_driver);
> +
> +MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
> +MODULE_DESCRIPTION("Intel Cherrytrail Whiskey Cove PMIC extcon driver");

Minor comment.
You better to locate the MODULE_DESCRIPTION at the first line
and then MODULE_AUTHOR is at second line.

> +MODULE_LICENSE("GPL v2");
> 


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH 06/15] power: supply: bq24190_charger: Use i2c-core irq-mapping code
  2017-03-17 17:24   ` Andy Shevchenko
@ 2017-03-20  4:46     ` Sebastian Reichel
  0 siblings, 0 replies; 90+ messages in thread
From: Sebastian Reichel @ 2017-03-20  4:46 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Hans de Goede, Rafael J . Wysocki, Len Brown, Wolfram Sang,
	Lee Jones, MyungJoo Ham, Chanwoo Choi, linux-acpi, Takashi Iwai,
	linux-i2c, linux-kernel, linux-pm

[-- Attachment #1: Type: text/plain, Size: 4845 bytes --]

Hi,

On Fri, Mar 17, 2017 at 07:24:14PM +0200, Andy Shevchenko wrote:
> On Fri, 2017-03-17 at 10:55 +0100, Hans de Goede wrote:
> > The i2c-core already maps of irqs before calling the driver's probe
> > function and there are no in tree users of
> > bq24190_platform_data->gpio_int.
> > 
> > Remove the redundant custom irq-mapping code and just use client->irq.
> > 
> 
> Nice! I did similar clean up to some other driver, so,
> 
> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> 
> P.S. This should be first in the series against bq24190.

Right.

Acked-by: Sebastian Reichel <sre@kernel.org>

-- Sebastian

> > Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> > ---
> >  drivers/power/supply/bq24190_charger.c | 61 ++-----------------------
> > ---------
> >  include/linux/power/bq24190_charger.h  |  1 -
> >  2 files changed, 2 insertions(+), 60 deletions(-)
> > 
> > diff --git a/drivers/power/supply/bq24190_charger.c
> > b/drivers/power/supply/bq24190_charger.c
> > index 7bca8d0..9c4b171 100644
> > --- a/drivers/power/supply/bq24190_charger.c
> > +++ b/drivers/power/supply/bq24190_charger.c
> > @@ -154,8 +154,6 @@ struct bq24190_dev_info {
> >  	struct bq24190_platform_data	*pdata;
> >  	char				model_name[I2C_NAME_SIZE]
> > ;
> >  	kernel_ulong_t			model;
> > -	unsigned int			gpio_int;
> > -	unsigned int			irq;
> >  	struct mutex			f_reg_lock;
> >  	u8				f_reg;
> >  	u8				ss_reg;
> > @@ -1296,56 +1294,11 @@ static int bq24190_hw_init(struct
> > bq24190_dev_info *bdi)
> >  	return ret;
> >  }
> >  
> > -#ifdef CONFIG_OF
> > -static int bq24190_setup_dt(struct bq24190_dev_info *bdi)
> > -{
> > -	bdi->irq = irq_of_parse_and_map(bdi->dev->of_node, 0);
> > -	if (bdi->irq <= 0)
> > -		return -1;
> > -
> > -	return 0;
> > -}
> > -#else
> > -static int bq24190_setup_dt(struct bq24190_dev_info *bdi)
> > -{
> > -	return -1;
> > -}
> > -#endif
> > -
> > -static int bq24190_setup_pdata(struct bq24190_dev_info *bdi,
> > -		struct bq24190_platform_data *pdata)
> > -{
> > -	int ret;
> > -
> > -	if (!gpio_is_valid(pdata->gpio_int))
> > -		return -1;
> > -
> > -	ret = gpio_request(pdata->gpio_int, dev_name(bdi->dev));
> > -	if (ret < 0)
> > -		return -1;
> > -
> > -	ret = gpio_direction_input(pdata->gpio_int);
> > -	if (ret < 0)
> > -		goto out;
> > -
> > -	bdi->irq = gpio_to_irq(pdata->gpio_int);
> > -	if (!bdi->irq)
> > -		goto out;
> > -
> > -	bdi->gpio_int = pdata->gpio_int;
> > -	return 0;
> > -
> > -out:
> > -	gpio_free(pdata->gpio_int);
> > -	return -1;
> > -}
> > -
> >  static int bq24190_probe(struct i2c_client *client,
> >  		const struct i2c_device_id *id)
> >  {
> >  	struct i2c_adapter *adapter = to_i2c_adapter(client-
> > >dev.parent);
> >  	struct device *dev = &client->dev;
> > -	struct bq24190_platform_data *pdata = client-
> > >dev.platform_data;
> >  	struct power_supply_config charger_cfg = {}, battery_cfg =
> > {};
> >  	struct bq24190_dev_info *bdi;
> >  	int ret;
> > @@ -1372,12 +1325,7 @@ static int bq24190_probe(struct i2c_client
> > *client,
> >  
> >  	i2c_set_clientdata(client, bdi);
> >  
> > -	if (dev->of_node)
> > -		ret = bq24190_setup_dt(bdi);
> > -	else
> > -		ret = bq24190_setup_pdata(bdi, pdata);
> > -
> > -	if (ret) {
> > +	if (!client->irq) {
> >  		dev_err(dev, "Can't get irq info\n");
> >  		return -EINVAL;
> >  	}
> > @@ -1417,7 +1365,7 @@ static int bq24190_probe(struct i2c_client
> > *client,
> >  		goto out3;
> >  	}
> >  
> > -	ret = devm_request_threaded_irq(dev, bdi->irq, NULL,
> > +	ret = devm_request_threaded_irq(dev, client->irq, NULL,
> >  			bq24190_irq_handler_thread,
> >  			IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
> >  			"bq24190-charger", bdi);
> > @@ -1439,8 +1387,6 @@ static int bq24190_probe(struct i2c_client
> > *client,
> >  
> >  out1:
> >  	pm_runtime_disable(dev);
> > -	if (bdi->gpio_int)
> > -		gpio_free(bdi->gpio_int);
> >  	return ret;
> >  }
> >  
> > @@ -1457,9 +1403,6 @@ static int bq24190_remove(struct i2c_client
> > *client)
> >  	power_supply_unregister(bdi->charger);
> >  	pm_runtime_disable(bdi->dev);
> >  
> > -	if (bdi->gpio_int)
> > -		gpio_free(bdi->gpio_int);
> > -
> >  	return 0;
> >  }
> >  
> > diff --git a/include/linux/power/bq24190_charger.h
> > b/include/linux/power/bq24190_charger.h
> > index cb49717..8d918cb 100644
> > --- a/include/linux/power/bq24190_charger.h
> > +++ b/include/linux/power/bq24190_charger.h
> > @@ -10,7 +10,6 @@
> >  #define _BQ24190_CHARGER_H_
> >  
> >  struct bq24190_platform_data {
> > -	unsigned int	gpio_int;	/* GPIO pin that's
> > connected to INT# */
> >  	bool no_register_reset;
> >  };
> >  
> 
> -- 
> Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Intel Finland Oy

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH 10/15] power: supply: bq24190_charger: Use extcon to determine ilimit, 5v boost
  2017-03-17  9:55 ` [PATCH 10/15] power: supply: bq24190_charger: Use extcon to determine ilimit, 5v boost Hans de Goede
  2017-03-17 17:33   ` Andy Shevchenko
  2017-03-18  7:10   ` [10/15] " Liam Breck
@ 2017-03-20  4:52   ` Sebastian Reichel
  2 siblings, 0 replies; 90+ messages in thread
From: Sebastian Reichel @ 2017-03-20  4:52 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Rafael J . Wysocki, Len Brown, Wolfram Sang, Andy Shevchenko,
	Lee Jones, MyungJoo Ham, Chanwoo Choi, linux-acpi, Takashi Iwai,
	linux-i2c, linux-kernel, linux-pm

[-- Attachment #1: Type: text/plain, Size: 6503 bytes --]

Hi,

On Fri, Mar 17, 2017 at 10:55:22AM +0100, Hans de Goede wrote:
> Add support for monitoring an extcon device with SDP/CDP/DCP and HOST
> cables and adjust ilimit and enable/disable the 5v boost converter
> accordingly. This is necessary on systems where the PSEL pin is hardwired
> high and ILIM needs to be set by software based on the detected charger
> type.
> 
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>

Acked-By: Sebastian Reichel <sre@kernel.org>

-- Sebastian

> ---
>  drivers/power/supply/Kconfig           |  1 +
>  drivers/power/supply/bq24190_charger.c | 85 ++++++++++++++++++++++++++++++++++
>  include/linux/power/bq24190_charger.h  |  1 +
>  3 files changed, 87 insertions(+)
> 
> diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
> index f8b6e64..fd93110 100644
> --- a/drivers/power/supply/Kconfig
> +++ b/drivers/power/supply/Kconfig
> @@ -442,6 +442,7 @@ config CHARGER_BQ2415X
>  config CHARGER_BQ24190
>  	tristate "TI BQ24190 battery charger driver"
>  	depends on I2C
> +	depends on EXTCON
>  	depends on GPIOLIB || COMPILE_TEST
>  	help
>  	  Say Y to enable support for the TI BQ24190 battery charger.
> diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
> index 82cb33d..03990e2 100644
> --- a/drivers/power/supply/bq24190_charger.c
> +++ b/drivers/power/supply/bq24190_charger.c
> @@ -11,10 +11,12 @@
>  #include <linux/module.h>
>  #include <linux/interrupt.h>
>  #include <linux/delay.h>
> +#include <linux/extcon.h>
>  #include <linux/of_irq.h>
>  #include <linux/of_device.h>
>  #include <linux/pm_runtime.h>
>  #include <linux/power_supply.h>
> +#include <linux/workqueue.h>
>  #include <linux/gpio.h>
>  #include <linux/i2c.h>
>  
> @@ -39,6 +41,8 @@
>  #define BQ24190_REG_POC_WDT_RESET_SHIFT		6
>  #define BQ24190_REG_POC_CHG_CONFIG_MASK		(BIT(5) | BIT(4))
>  #define BQ24190_REG_POC_CHG_CONFIG_SHIFT	4
> +#define BQ24190_REG_POC_CHG_CONFIG_CHARGE	1
> +#define BQ24190_REG_POC_CHG_CONFIG_OTG		2
>  #define BQ24190_REG_POC_SYS_MIN_MASK		(BIT(3) | BIT(2) | BIT(1))
>  #define BQ24190_REG_POC_SYS_MIN_SHIFT		1
>  #define BQ24190_REG_POC_BOOST_LIM_MASK		BIT(0)
> @@ -152,6 +156,9 @@ struct bq24190_dev_info {
>  	struct power_supply		*charger;
>  	struct power_supply		*battery;
>  	struct bq24190_platform_data	*pdata;
> +	struct extcon_dev		*extcon;
> +	struct notifier_block		extcon_nb;
> +	struct work_struct		extcon_work;
>  	char				model_name[I2C_NAME_SIZE];
>  	kernel_ulong_t			model;
>  	struct mutex			f_reg_lock;
> @@ -167,6 +174,11 @@ struct bq24190_dev_info {
>   * number at that index in the array is the real-world value that it
>   * represents.
>   */
> +
> +/* REG00[2:0] (IINLIM) in uAh */
> +static const int bq24190_iinlim_values[] = {
> +	100000, 150000, 500000, 900000, 1200000, 1500000, 2000000, 3000000 };
> +
>  /* REG02[7:2] (ICHG) in uAh */
>  static const int bq24190_ccc_ichg_values[] = {
>  	 512000,  576000,  640000,  704000,  768000,  832000,  896000,  960000,
> @@ -1290,6 +1302,61 @@ static irqreturn_t bq24190_irq_handler_thread(int irq, void *data)
>  	return IRQ_HANDLED;
>  }
>  
> +static void bq24190_extcon_work(struct work_struct *work)
> +{
> +	struct bq24190_dev_info *bdi =
> +		container_of(work, struct bq24190_dev_info, extcon_work);
> +	int ret, iinlim = 0;
> +
> +	if (extcon_get_state(bdi->extcon, EXTCON_CHG_USB_SDP) == 1)
> +		iinlim = 500000;
> +	else if (extcon_get_state(bdi->extcon, EXTCON_CHG_USB_CDP) == 1 ||
> +		 extcon_get_state(bdi->extcon, EXTCON_CHG_USB_ACA) == 1)
> +		iinlim = 1500000;
> +	else if (extcon_get_state(bdi->extcon, EXTCON_CHG_USB_DCP) == 1)
> +		iinlim = 2000000;
> +
> +	if (iinlim) {
> +		ret = bq24190_set_field_val(bdi, BQ24190_REG_ISC,
> +				BQ24190_REG_ISC_IINLIM_MASK,
> +				BQ24190_REG_ISC_IINLIM_SHIFT,
> +				bq24190_iinlim_values,
> +				ARRAY_SIZE(bq24190_iinlim_values),
> +				iinlim);
> +		if (ret)
> +			dev_err(bdi->dev, "Can't set IINLIM: %d\n", ret);
> +	}
> +
> +	/*
> +	 * If no charger has been detected and host mode is requested, activate
> +	 * the 5V boost converter, otherwise deactivate it.
> +	 */
> +	if (!iinlim && extcon_get_state(bdi->extcon, EXTCON_USB_HOST) == 1) {
> +		ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
> +					 BQ24190_REG_POC_CHG_CONFIG_MASK,
> +					 BQ24190_REG_POC_CHG_CONFIG_SHIFT,
> +					 BQ24190_REG_POC_CHG_CONFIG_OTG);
> +	} else {
> +		ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
> +					 BQ24190_REG_POC_CHG_CONFIG_MASK,
> +					 BQ24190_REG_POC_CHG_CONFIG_SHIFT,
> +					 BQ24190_REG_POC_CHG_CONFIG_CHARGE);
> +	}
> +	if (ret)
> +		dev_err(bdi->dev, "Can't set CHG_CONFIG: %d\n", ret);
> +}
> +
> +static int bq24190_extcon_event(struct notifier_block *nb, unsigned long event,
> +				void *param)
> +{
> +	struct bq24190_dev_info *bdi =
> +		container_of(nb, struct bq24190_dev_info, extcon_nb);
> +
> +	schedule_work(&bdi->extcon_work);
> +
> +	return NOTIFY_OK;
> +}
> +
>  static int bq24190_hw_init(struct bq24190_dev_info *bdi)
>  {
>  	u8 v;
> @@ -1375,6 +1442,12 @@ static int bq24190_probe(struct i2c_client *client,
>  			return -EPROBE_DEFER;
>  	}
>  
> +	if (bdi->pdata && bdi->pdata->extcon_name) {
> +		bdi->extcon = extcon_get_extcon_dev(bdi->pdata->extcon_name);
> +		if (!bdi->extcon)
> +			return -EPROBE_DEFER;
> +	}
> +
>  	pm_runtime_enable(dev);
>  	pm_runtime_resume(dev);
>  
> @@ -1423,6 +1496,18 @@ static int bq24190_probe(struct i2c_client *client,
>  		goto out4;
>  	}
>  
> +	if (bdi->extcon) {
> +		INIT_WORK(&bdi->extcon_work, bq24190_extcon_work);
> +		bdi->extcon_nb.notifier_call = bq24190_extcon_event;
> +		ret = devm_extcon_register_notifier(dev, bdi->extcon, -1,
> +						    &bdi->extcon_nb);
> +		if (ret)
> +			goto out4;
> +
> +		/* Sync initial cable state */
> +		schedule_work(&bdi->extcon_work);
> +	}
> +
>  	return 0;
>  
>  out4:
> diff --git a/include/linux/power/bq24190_charger.h b/include/linux/power/bq24190_charger.h
> index 02d248b..909c5b9 100644
> --- a/include/linux/power/bq24190_charger.h
> +++ b/include/linux/power/bq24190_charger.h
> @@ -13,6 +13,7 @@
>  
>  struct bq24190_platform_data {
>  	bool no_register_reset;
> +	const char *extcon_name;
>  	int (*get_ext_bat_property)(enum power_supply_property prop,
>  				    union power_supply_propval *val);
>  };
> -- 
> 2.9.3
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH 14/15] power: supply: Add driver for Cherry Trail Whiskey Cove PMIC Fuel Gauge
  2017-03-17  9:55 ` [PATCH 14/15] power: supply: Add driver for Cherry Trail Whiskey Cove PMIC Fuel Gauge Hans de Goede
  2017-03-17 17:58   ` Andy Shevchenko
@ 2017-03-20  5:07   ` Sebastian Reichel
  1 sibling, 0 replies; 90+ messages in thread
From: Sebastian Reichel @ 2017-03-20  5:07 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Rafael J . Wysocki, Len Brown, Wolfram Sang, Andy Shevchenko,
	Lee Jones, MyungJoo Ham, Chanwoo Choi, linux-acpi, Takashi Iwai,
	linux-i2c, linux-kernel, linux-pm

[-- Attachment #1: Type: text/plain, Size: 10292 bytes --]

Hi,

On Fri, Mar 17, 2017 at 10:55:26AM +0100, Hans de Goede wrote:
> Add a driver for the Cherry Trail Whiskey Cove PMIC Fuel Gauge, note
> the Cherry Trail Whiskey Cove PMIC Fuel Gauge block is purely a fuel gauge
> and not a full battery controller. As such it offers a platform_data
> callback for extra power_supply properties for the actual external-charger
> ic driver and does not register a power_supply itself.
> 
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>

I think this should become a normal battery-type power-supply
driver. bq24190_charger driver should only expose a charger-type
power-supply device on your system (and probably most others, its
very rare, that systems have a programmable charger and no
fuel-gauge).

-- Sebastian

> ---
>  drivers/power/supply/Kconfig             |   9 ++
>  drivers/power/supply/Makefile            |   1 +
>  drivers/power/supply/cht_wc_fuel_gauge.c | 209 +++++++++++++++++++++++++++++++
>  include/linux/power/cht_wc_fuel_gauge.h  |  21 ++++
>  4 files changed, 240 insertions(+)
>  create mode 100644 drivers/power/supply/cht_wc_fuel_gauge.c
>  create mode 100644 include/linux/power/cht_wc_fuel_gauge.h
> 
> diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
> index fd93110..34ebfca 100644
> --- a/drivers/power/supply/Kconfig
> +++ b/drivers/power/supply/Kconfig
> @@ -538,4 +538,13 @@ config AXP20X_POWER
>  	  This driver provides support for the power supply features of
>  	  AXP20x PMIC.
>  
> +config CHT_WC_FUEL_GAUGE
> +	tristate "Intel Cherry Trail Whiskey Cove PMIC Fuel Gauge"
> +	depends on INTEL_SOC_PMIC_CHTWC
> +	help
> +	  This adds support for the battery fuel gauge found in the Intel
> +	  Cherry Trail Whiskey Cove PMIC. This driver allows monitoring
> +	  of the charge level of the battery on Intel Cherry Trail systems
> +	  with a Whiskey Cove PMIC.
> +
>  endif # POWER_SUPPLY
> diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
> index 3789a2c..702e28a 100644
> --- a/drivers/power/supply/Makefile
> +++ b/drivers/power/supply/Makefile
> @@ -74,3 +74,4 @@ obj-$(CONFIG_CHARGER_TPS65090)	+= tps65090-charger.o
>  obj-$(CONFIG_CHARGER_TPS65217)	+= tps65217_charger.o
>  obj-$(CONFIG_AXP288_FUEL_GAUGE) += axp288_fuel_gauge.o
>  obj-$(CONFIG_AXP288_CHARGER)	+= axp288_charger.o
> +obj-$(CONFIG_CHT_WC_FUEL_GAUGE)	+= cht_wc_fuel_gauge.o
> diff --git a/drivers/power/supply/cht_wc_fuel_gauge.c b/drivers/power/supply/cht_wc_fuel_gauge.c
> new file mode 100644
> index 0000000..56f6e5a
> --- /dev/null
> +++ b/drivers/power/supply/cht_wc_fuel_gauge.c
> @@ -0,0 +1,209 @@
> +/*
> + * Intel CHT Whiskey Cove Fuel Gauge driver
> + * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License version
> + * 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * Cherrytrail Whiskey Cove devices have 2 functional blocks which interact
> + * with the battery.
> + *
> + * 1) The fuel-gauge which is build into the Whiskey Cove PMIC, but has its
> + * own i2c bus and i2c client addresses separately from the rest of the PMIC.
> + * That block is what this driver is for.
> + *
> + * 2) An external charger IC, which is connected to the SMBUS controller
> + * which is part of the rest of the Whiskey Cove PMIC, mfd/intel_cht_wc.c
> + * registers a platform device for the SMBUS controller and
> + * i2c/busses/i2c-cht-wc.c contains the i2c-adapter driver for this.
> + *
> + * However we want to present this as a single power_supply device to
> + * userspace. So this driver offers a callback to get the fuel-gauge
> + * power_supply properties, which gets passed to the external charger
> + * driver via i2c_board_info when i2c-cht-wc.c calls i2c_new_device().
> + */
> +
> +#include <linux/acpi.h>
> +#include <linux/delay.h>
> +#include <linux/i2c.h>
> +#include <linux/interrupt.h>
> +#include <linux/mfd/intel_soc_pmic.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/power_supply.h>
> +#include <linux/power/cht_wc_fuel_gauge.h>
> +#include <linux/slab.h>
> +
> +#define REG_CHARGE_NOW		0x05
> +#define REG_VOLTAGE_NOW		0x09
> +#define REG_CURRENT_NOW		0x0a
> +#define REG_CURRENT_AVG		0x0b
> +#define REG_CHARGE_FULL		0x10
> +#define REG_CHARGE_DESIGN	0x18
> +#define REG_VOLTAGE_AVG		0x19
> +#define REG_VOLTAGE_OCV		0x1b /* Only updated during charging */
> +
> +#define CHT_WC_FG_PTYPE		4
> +
> +struct cht_wc_fg_data {
> +	struct device *dev;
> +	struct i2c_client *client;
> +};
> +
> +static DEFINE_MUTEX(cht_wc_fg_mutex);
> +static struct cht_wc_fg_data *cht_wc_fg;
> +
> +static int cht_wc_fg_read(struct cht_wc_fg_data *fg, u8 reg,
> +			  union power_supply_propval *val, int scale,
> +			  int sign_extend)
> +{
> +	int ret;
> +
> +	ret = i2c_smbus_read_word_data(fg->client, reg);
> +	if (ret < 0)
> +		return ret;
> +
> +	if (sign_extend)
> +		ret = sign_extend32(ret, 15);
> +
> +	val->intval = ret * scale;
> +
> +	return 0;
> +}
> +
> +int cht_wc_fg_get_property(enum power_supply_property prop,
> +			   union power_supply_propval *val)
> +{
> +	int ret = 0;
> +
> +	mutex_lock(&cht_wc_fg_mutex);
> +
> +	if (!cht_wc_fg) {
> +		ret = -ENXIO;
> +		goto out_unlock;
> +	}
> +
> +	switch (prop) {
> +	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
> +		ret = cht_wc_fg_read(cht_wc_fg, REG_VOLTAGE_NOW, val, 75, 0);
> +		break;
> +	case POWER_SUPPLY_PROP_VOLTAGE_AVG:
> +		ret = cht_wc_fg_read(cht_wc_fg, REG_VOLTAGE_AVG, val, 75, 0);
> +		break;
> +	case POWER_SUPPLY_PROP_VOLTAGE_OCV:
> +		ret = cht_wc_fg_read(cht_wc_fg, REG_VOLTAGE_OCV, val, 75, 0);
> +		break;
> +	case POWER_SUPPLY_PROP_CURRENT_NOW:
> +		ret = cht_wc_fg_read(cht_wc_fg, REG_CURRENT_NOW, val, 150, 1);
> +		break;
> +	case POWER_SUPPLY_PROP_CURRENT_AVG:
> +		ret = cht_wc_fg_read(cht_wc_fg, REG_CURRENT_AVG, val, 150, 1);
> +		break;
> +	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
> +		ret = cht_wc_fg_read(cht_wc_fg, REG_CHARGE_DESIGN, val, 500, 0);
> +		break;
> +	case POWER_SUPPLY_PROP_CHARGE_FULL:
> +		ret = cht_wc_fg_read(cht_wc_fg, REG_CHARGE_FULL, val, 500, 0);
> +		break;
> +	case POWER_SUPPLY_PROP_CHARGE_NOW:
> +		ret = cht_wc_fg_read(cht_wc_fg, REG_CHARGE_NOW, val, 500, 0);
> +		break;
> +	default:
> +		ret = -ENODATA;
> +	}
> +out_unlock:
> +	mutex_unlock(&cht_wc_fg_mutex);
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(cht_wc_fg_get_property);
> +
> +static int cht_wc_fg_probe(struct i2c_client *client,
> +			const struct i2c_device_id *i2c_id)
> +{
> +	struct device *dev = &client->dev;
> +	struct cht_wc_fg_data *fg;
> +	acpi_status status;
> +	unsigned long long ptyp;
> +
> +	fg = devm_kzalloc(dev, sizeof(*fg), GFP_KERNEL);
> +	if (!fg)
> +		return -ENOMEM;
> +
> +	status = acpi_evaluate_integer(ACPI_HANDLE(dev), "PTYP", NULL, &ptyp);
> +	if (ACPI_FAILURE(status)) {
> +		dev_err(dev, "Failed to get PTYPE\n");
> +		return -ENODEV;
> +	}
> +
> +	/*
> +	 * The same ACPI HID is used with different PMICs check PTYP to
> +	 * ensure that we are dealing with a Whiskey Cove PMIC.
> +	 */
> +	if (ptyp != CHT_WC_FG_PTYPE)
> +		return -ENODEV;
> +
> +	fg->dev = dev;
> +	/*
> +	 * The current resource settings table for the fuel gauge contains
> +	 * multiple i2c devices on 2 different i2c-busses. The one we actually
> +	 * want is the second resource (index 1).
> +	 */
> +	fg->client = i2c_acpi_new_device(dev, 1);
> +	if (!fg->client)
> +		return -EPROBE_DEFER;
> +
> +	i2c_set_clientdata(client, fg);
> +
> +	mutex_lock(&cht_wc_fg_mutex);
> +	cht_wc_fg = fg;
> +	mutex_unlock(&cht_wc_fg_mutex);
> +
> +	return 0;
> +}
> +
> +static int cht_wc_fg_remove(struct i2c_client *i2c)
> +{
> +	struct cht_wc_fg_data *fg = i2c_get_clientdata(i2c);
> +
> +	mutex_lock(&cht_wc_fg_mutex);
> +	cht_wc_fg = NULL;
> +	mutex_unlock(&cht_wc_fg_mutex);
> +
> +	i2c_unregister_device(fg->client);
> +
> +	return 0;
> +}
> +
> +static const struct i2c_device_id cht_wc_fg_i2c_id[] = {
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(i2c, cht_wc_fg_i2c_id);
> +
> +static const struct acpi_device_id cht_wc_fg_acpi_ids[] = {
> +	{ "INT33FE", },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(acpi, cht_wc_fg_acpi_ids);
> +
> +static struct i2c_driver cht_wc_fg_driver = {
> +	.driver	= {
> +		.name	= "CHT Whiskey Cove PMIC Fuel Gauge",
> +		.acpi_match_table = ACPI_PTR(cht_wc_fg_acpi_ids),
> +	},
> +	.probe = cht_wc_fg_probe,
> +	.remove = cht_wc_fg_remove,
> +	.id_table = cht_wc_fg_i2c_id,
> +	.irq_index = 1,
> +};
> +
> +module_i2c_driver(cht_wc_fg_driver);
> +
> +MODULE_DESCRIPTION("Intel CHT Whiskey Cove PMIC Fuel Gauge driver");
> +MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
> +MODULE_LICENSE("GPL");
> diff --git a/include/linux/power/cht_wc_fuel_gauge.h b/include/linux/power/cht_wc_fuel_gauge.h
> new file mode 100644
> index 0000000..4b4e051
> --- /dev/null
> +++ b/include/linux/power/cht_wc_fuel_gauge.h
> @@ -0,0 +1,21 @@
> +/*
> + * Intel CHT Whiskey Cove Fuel Gauge driver
> + * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License version
> + * 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __CHT_WC_FUEL_GAUGE_H
> +#define __CHT_WC_FUEL_GAUGE_H
> +
> +int cht_wc_fg_get_property(enum power_supply_property prop,
> +			   union power_supply_propval *val);
> +
> +#endif
> -- 
> 2.9.3
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH 09/15] power: supply: bq24190_charger: Add voltage_max_design prop to battery
  2017-03-17  9:55 ` [PATCH 09/15] power: supply: bq24190_charger: Add voltage_max_design prop to battery Hans de Goede
  2017-03-18  7:10   ` [09/15] " Liam Breck
@ 2017-03-20  5:12   ` Sebastian Reichel
  1 sibling, 0 replies; 90+ messages in thread
From: Sebastian Reichel @ 2017-03-20  5:12 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Rafael J . Wysocki, Len Brown, Wolfram Sang, Andy Shevchenko,
	Lee Jones, MyungJoo Ham, Chanwoo Choi, linux-acpi, Takashi Iwai,
	linux-i2c, linux-kernel, linux-pm

[-- Attachment #1: Type: text/plain, Size: 2380 bytes --]

Hi,

On Fri, Mar 17, 2017 at 10:55:21AM +0100, Hans de Goede wrote:
> When combined with an external fuel-gauge, upower needs voltage_max_design
> as it internally does all its calculations in Watts and converts the
> charge_foo properties from A to Watts by using voltage_max_design.
> 
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>

Assuming, that my comment on patch 14 works POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN
is required in the fuel-gauge driver instead. As far as I understand
it the charger voltage was too high for your device anyways, so that
you capped it at 4.3V. So I assume, that you can just provide it via
device properties.

-- Sebastian

>  drivers/power/supply/bq24190_charger.c | 10 +++++++++-
>  1 file changed, 9 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
> index 9fe69a5..82cb33d 100644
> --- a/drivers/power/supply/bq24190_charger.c
> +++ b/drivers/power/supply/bq24190_charger.c
> @@ -1103,6 +1103,13 @@ static int bq24190_battery_get_property(struct power_supply *psy,
>  		val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
>  		ret = 0;
>  		break;
> +	case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
> +		/*
> +		 * Report charger configured voltage as max design voltage,
> +		 * not entirely correct, but userspace needs something here.
> +		 */
> +		ret = bq24190_charger_get_voltage(bdi, val);
> +		break;
>  	case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
>  		ret = bq24190_battery_get_temp_alert_max(bdi, val);
>  		break;
> @@ -1169,6 +1176,7 @@ static enum power_supply_property bq24190_battery_properties[] = {
>  	POWER_SUPPLY_PROP_HEALTH,
>  	POWER_SUPPLY_PROP_ONLINE,
>  	POWER_SUPPLY_PROP_TECHNOLOGY,
> +	POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
>  	POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
>  	POWER_SUPPLY_PROP_SCOPE,
>  	/* Begin of extended battery properties */
> @@ -1186,7 +1194,7 @@ static const struct power_supply_desc bq24190_battery_desc = {
>  	.name			= "bq24190-battery",
>  	.type			= POWER_SUPPLY_TYPE_BATTERY,
>  	.properties		= bq24190_battery_properties,
> -	.num_properties		= 6,
> +	.num_properties		= 7,
>  	.get_property		= bq24190_battery_get_property,
>  	.set_property		= bq24190_battery_set_property,
>  	.property_is_writeable	= bq24190_battery_property_is_writeable,
> -- 
> 2.9.3
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [04/15] power: supply: bq24190_charger: Add no_register_reset pdata flag
  2017-03-19  9:42               ` Hans de Goede
@ 2017-03-20  5:27                 ` Sebastian Reichel
  2017-03-20 13:54                   ` Hans de Goede
  0 siblings, 1 reply; 90+ messages in thread
From: Sebastian Reichel @ 2017-03-20  5:27 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Liam Breck, Andy Shevchenko, Tony Lindgren, linux-pm, Liam Breck

[-- Attachment #1: Type: text/plain, Size: 4675 bytes --]

Hi,

On Sun, Mar 19, 2017 at 10:42:00AM +0100, Hans de Goede wrote:
> On 19-03-17 09:22, Hans de Goede wrote:
> > > Then consider the pseudo-driver concept. That would be generally
> > > useful for any charger/gauge pairing. Both drivers would provide
> > > callbacks to it.
> > 
> > So your rejecting a patch which adds 30 lines of code for some
> > vague generic pseudo-driver concept without offering any design
> > direction on what such a concept would look like and without taking
> > into account that so far this seems to be a one-of problem.
> 
> I still think the pseudo-driver idea is a bad idea. Having 1 driver
> which somehow combines things from 2 drivers without clear semantics
> feels wrong.

Apart from being ugly, that does not work anyways, how should the
drivers know when its ok to expose their info to userspace and when
its not.

> As said before I think your suggested solution lacks any
> design direction, I've been thinking about this a bit more and
> I've come up with an alternative solution with clearly defined
> goals and semantics.
> 
> We want one driver which is solidly in control of the charger
> since getting that wrong is quite bad and we want to extend
> the information it is exporting to userspace in the form of
> power_supply properties with some extra info.
> 
> So taking that as a starting point and generalizing that,
> I think that if we want we can make something more generic then
> my original patch for this. My idea is to introduce something
> called a power_supply_properties_provider, with an API
> like this:

Thanks for thinking about this. From what I can see it should
be enough to just avoid exposing a battery device at all in
the charger driver, though. It does not really provide useful
information anyways.

> typedef int (*power_supply_properties_provider_get_property_t)(
> 	enum power_supply_property prop, union power_supply_propval *val,
> 	void *driver_data);
> 
> struct power_supply_properties_provider;
> 
> struct power_supply_properties_provider *
> power_supply_properties_provider_register(
> 	const char *name,
> 	power_supply_properties_provider_get_property_t get_property,
> 	const enum power_supply_property *properties,
> 	size_t num_properties,
> 	void *driver_data);
> 
> void power_supply_properties_provider_unregister(
> 	struct power_supply_properties_provider *pspp);
> 
> struct power_supply_properties_provider *
> 	power_supply_properties_provider_get(const char *name);
> 
> void power_supply_properties_provider_put(
> 	struct power_supply_properties_provider *pspp);
> 
> int power_supply_properties_provider_merge_properties(
> 	struct power_supply_properties_provider *pspp,
> 	const enum power_supply_property *properties,
> 	size_t num_properties,
> 	enum power_supply_property **merged_properties_ret,
> 	size_t *merged_num_properties_ret);
> 
> int power_supply_properties_provider_get_property(
> 	struct power_supply_properties_provider *pspp,
> 	enum power_supply_property prop,
> 	union power_supply_propval *val);
> 
> So in this case the faul-gauge driver would call
> power_supply_properties_provider_register() from probe and
> power_supply_properties_provider_unregister() from remove.
> 
> The struct power_supply_properties_provider will be ref-counted
> so that it will stick around after unregister in case any
> consumers who have gotten a ref through
> power_supply_properties_provider_get can still call
> power_supply_properties_provider_get_property, which after
> unregister will simply always return -ENXIO.
> 
> A driver wanting to use extra properties like bq24190_charger
> will call power_supply_properties_provider_get (with a name
> provided through platform_data), use a dynamically allocated
> struct power_supply_desc and fill the properties of that
> using power_supply_properties_provider_merge_properties
> to merge its own properties with the
> power_supply_properties_provider's properties and in its
> get_property method have a default label which calls
> power_supply_properties_provider_get_property.
> 
> This would still add quite a bit more code then my original
> patch for what may very well end up being a one-of solution,
> but I guess we may encounter this problem more often and
> this will offer a nice generic and clean way for dealing
> with adding extra info from other sources to a power_supply
> driver, so I'm happy to turn this idea / design into working
> code if people like this better then my original patch.
> 
> Liam, Sebastian what do you think of the above proposal?
> 
> Regards,
> 
> Hans
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH 13/15] i2c: core: Allow drivers to specify index for irq to get from of / ACPI
  2017-03-17  9:55 ` [PATCH 13/15] i2c: core: Allow drivers to specify index for irq to get from of / ACPI Hans de Goede
@ 2017-03-20  8:55     ` kbuild test robot
  2017-03-20  8:55     ` kbuild test robot
  1 sibling, 0 replies; 90+ messages in thread
From: kbuild test robot @ 2017-03-20  8:55 UTC (permalink / raw)
  Cc: kbuild-all, Rafael J . Wysocki, Len Brown, Wolfram Sang,
	Andy Shevchenko, Lee Jones, Sebastian Reichel, MyungJoo Ham,
	Chanwoo Choi, Hans de Goede, linux-acpi, Takashi Iwai, linux-i2c,
	linux-kernel, linux-pm

[-- Attachment #1: Type: text/plain, Size: 10856 bytes --]

Hi Hans,

[auto build test WARNING on wsa/i2c/for-next]
[also build test WARNING on v4.11-rc3 next-20170310]
[cannot apply to battery/master]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Hans-de-Goede/Add-Intel-Cherry-Trail-Whiskey-Cove-PMIC-support/20170320-144648
base:   https://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git i2c/for-next
reproduce: make htmldocs

All warnings (new ones prefixed by >>):

   include/linux/init.h:1: warning: no structured comments found
   kernel/sched/core.c:2085: warning: No description found for parameter 'rf'
   kernel/sched/core.c:2085: warning: Excess function parameter 'cookie' description in 'try_to_wake_up_local'
   include/linux/kthread.h:26: warning: Excess function parameter '...' description in 'kthread_create'
   kernel/sys.c:1: warning: no structured comments found
   include/linux/device.h:969: warning: No description found for parameter 'dma_ops'
   drivers/dma-buf/seqno-fence.c:1: warning: no structured comments found
>> include/linux/i2c.h:219: warning: No description found for parameter 'irq_index'
   include/linux/iio/iio.h:597: warning: No description found for parameter 'trig_readonly'
   include/linux/iio/trigger.h:151: warning: No description found for parameter 'indio_dev'
   include/linux/iio/trigger.h:151: warning: No description found for parameter 'trig'
   include/linux/device.h:970: warning: No description found for parameter 'dma_ops'
   drivers/regulator/core.c:1467: warning: Excess function parameter 'ret' description in 'regulator_dev_lookup'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'open'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'preclose'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'postclose'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'lastclose'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'set_busid'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'irq_handler'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'irq_preinstall'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'irq_postinstall'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'irq_uninstall'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'debugfs_init'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'debugfs_cleanup'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'gem_open_object'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'gem_close_object'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'prime_handle_to_fd'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'prime_fd_to_handle'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'gem_prime_export'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'gem_prime_import'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'gem_prime_pin'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'gem_prime_unpin'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'gem_prime_res_obj'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'gem_prime_get_sg_table'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'gem_prime_import_sg_table'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'gem_prime_vmap'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'gem_prime_vunmap'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'gem_prime_mmap'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'gem_vm_ops'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'major'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'minor'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'patchlevel'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'name'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'desc'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'date'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'driver_features'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'ioctls'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'num_ioctls'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'fops'
   include/drm/drm_color_mgmt.h:1: warning: no structured comments found
   drivers/gpu/drm/drm_fb_cma_helper.c:557: warning: Excess function parameter 'num_crtc' description in 'drm_fbdev_cma_init'
   drivers/gpu/drm/drm_fb_cma_helper.c:558: warning: Excess function parameter 'num_crtc' description in 'drm_fbdev_cma_init'
   drivers/gpu/drm/i915/intel_lpe_audio.c:342: warning: No description found for parameter 'pipe'
   drivers/gpu/drm/i915/intel_lpe_audio.c:342: warning: No description found for parameter 'dp_output'
   drivers/gpu/drm/i915/intel_lpe_audio.c:342: warning: No description found for parameter 'link_rate'
   drivers/gpu/drm/i915/intel_lpe_audio.c:343: warning: No description found for parameter 'pipe'
   drivers/gpu/drm/i915/intel_lpe_audio.c:343: warning: No description found for parameter 'dp_output'
   drivers/gpu/drm/i915/intel_lpe_audio.c:343: warning: No description found for parameter 'link_rate'
   drivers/media/dvb-core/dvb_frontend.h:677: warning: No description found for parameter 'refcount'
   Documentation/core-api/assoc_array.rst:13: WARNING: Enumerated list ends without a blank line; unexpected unindent.
   Documentation/doc-guide/sphinx.rst:110: ERROR: Unknown target name: "sphinx c domain".
   kernel/sched/fair.c:7616: WARNING: Inline emphasis start-string without end-string.
   kernel/time/timer.c:1200: ERROR: Unexpected indentation.
   kernel/time/timer.c:1202: ERROR: Unexpected indentation.
   kernel/time/timer.c:1203: WARNING: Block quote ends without a blank line; unexpected unindent.
   include/linux/wait.h:122: WARNING: Block quote ends without a blank line; unexpected unindent.
   include/linux/wait.h:125: ERROR: Unexpected indentation.
   include/linux/wait.h:127: WARNING: Block quote ends without a blank line; unexpected unindent.
   kernel/time/hrtimer.c:990: WARNING: Block quote ends without a blank line; unexpected unindent.
   kernel/signal.c:322: WARNING: Inline literal start-string without end-string.
   include/linux/iio/iio.h:219: ERROR: Unexpected indentation.
   include/linux/iio/iio.h:220: WARNING: Block quote ends without a blank line; unexpected unindent.
   include/linux/iio/iio.h:226: WARNING: Definition list ends without a blank line; unexpected unindent.
   drivers/iio/industrialio-core.c:639: ERROR: Unknown target name: "iio_val".
   drivers/iio/industrialio-core.c:646: ERROR: Unknown target name: "iio_val".
   drivers/message/fusion/mptbase.c:5051: WARNING: Definition list ends without a blank line; unexpected unindent.
   drivers/tty/serial/serial_core.c:1898: WARNING: Definition list ends without a blank line; unexpected unindent.
   include/linux/regulator/driver.h:271: ERROR: Unknown target name: "regulator_regmap_x_voltage".
   include/linux/spi/spi.h:369: ERROR: Unexpected indentation.
   drivers/usb/core/message.c:478: ERROR: Unexpected indentation.
   drivers/usb/core/message.c:479: WARNING: Block quote ends without a blank line; unexpected unindent.
   Documentation/driver-api/usb.rst:623: ERROR: Unknown target name: "usb_type".
   Documentation/driver-api/usb.rst:623: ERROR: Unknown target name: "usb_dir".
   Documentation/driver-api/usb.rst:623: ERROR: Unknown target name: "usb_recip".
   Documentation/driver-api/usb.rst:689: ERROR: Unknown target name: "usbdevfs_urb_type".
   sound/soc/soc-core.c:2670: ERROR: Unknown target name: "snd_soc_daifmt".
   sound/core/jack.c:312: ERROR: Unknown target name: "snd_jack_btn".
   WARNING: dvipng command 'dvipng' cannot be run (needed for math display), check the imgmath_dvipng setting

vim +/irq_index +219 include/linux/i2c.h

^1da177e Linus Torvalds 2005-04-16  203  	/* a ioctl like command that can be used to perform specific functions
^1da177e Linus Torvalds 2005-04-16  204  	 * with the device.
^1da177e Linus Torvalds 2005-04-16  205  	 */
^1da177e Linus Torvalds 2005-04-16  206  	int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);
^1da177e Linus Torvalds 2005-04-16  207  
^1da177e Linus Torvalds 2005-04-16  208  	struct device_driver driver;
d2653e92 Jean Delvare   2008-04-29  209  	const struct i2c_device_id *id_table;
4735c98f Jean Delvare   2008-07-14  210  
4735c98f Jean Delvare   2008-07-14  211  	/* Device detection callback for automatic device creation */
310ec792 Jean Delvare   2009-12-14  212  	int (*detect)(struct i2c_client *, struct i2c_board_info *);
c3813d6a Jean Delvare   2009-12-14  213  	const unsigned short *address_list;
4735c98f Jean Delvare   2008-07-14  214  	struct list_head clients;
f55c71b4 Hans de Goede  2017-03-17  215  
f55c71b4 Hans de Goede  2017-03-17  216  	/* IRQ index for retreiving irq from ACPI resources */
f55c71b4 Hans de Goede  2017-03-17  217  	int irq_index;
^1da177e Linus Torvalds 2005-04-16  218  };
^1da177e Linus Torvalds 2005-04-16 @219  #define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)
^1da177e Linus Torvalds 2005-04-16  220  
2096b956 David Brownell 2007-05-01  221  /**
2096b956 David Brownell 2007-05-01  222   * struct i2c_client - represent an I2C slave device
d64f73be David Brownell 2007-07-12  223   * @flags: I2C_CLIENT_TEN indicates the device uses a ten bit chip address;
d64f73be David Brownell 2007-07-12  224   *	I2C_CLIENT_PEC indicates it uses SMBus Packet Error Checking
2096b956 David Brownell 2007-05-01  225   * @addr: Address used on the I2C bus connected to the parent adapter.
2096b956 David Brownell 2007-05-01  226   * @name: Indicates the type of the device, usually a chip name that's
2096b956 David Brownell 2007-05-01  227   *	generic enough to hide second-sourcing and compatible revisions.

:::::: The code at line 219 was first introduced by commit
:::::: 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 Linux-2.6.12-rc2

:::::: TO: Linus Torvalds <torvalds@ppc970.osdl.org>
:::::: CC: Linus Torvalds <torvalds@ppc970.osdl.org>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 6576 bytes --]

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH 13/15] i2c: core: Allow drivers to specify index for irq to get from of / ACPI
@ 2017-03-20  8:55     ` kbuild test robot
  0 siblings, 0 replies; 90+ messages in thread
From: kbuild test robot @ 2017-03-20  8:55 UTC (permalink / raw)
  To: Hans de Goede
  Cc: kbuild-all, Rafael J . Wysocki, Len Brown, Wolfram Sang,
	Andy Shevchenko, Lee Jones, Sebastian Reichel, MyungJoo Ham,
	Chanwoo Choi, Hans de Goede, linux-acpi, Takashi Iwai, linux-i2c,
	linux-kernel, linux-pm

[-- Attachment #1: Type: text/plain, Size: 10856 bytes --]

Hi Hans,

[auto build test WARNING on wsa/i2c/for-next]
[also build test WARNING on v4.11-rc3 next-20170310]
[cannot apply to battery/master]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Hans-de-Goede/Add-Intel-Cherry-Trail-Whiskey-Cove-PMIC-support/20170320-144648
base:   https://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git i2c/for-next
reproduce: make htmldocs

All warnings (new ones prefixed by >>):

   include/linux/init.h:1: warning: no structured comments found
   kernel/sched/core.c:2085: warning: No description found for parameter 'rf'
   kernel/sched/core.c:2085: warning: Excess function parameter 'cookie' description in 'try_to_wake_up_local'
   include/linux/kthread.h:26: warning: Excess function parameter '...' description in 'kthread_create'
   kernel/sys.c:1: warning: no structured comments found
   include/linux/device.h:969: warning: No description found for parameter 'dma_ops'
   drivers/dma-buf/seqno-fence.c:1: warning: no structured comments found
>> include/linux/i2c.h:219: warning: No description found for parameter 'irq_index'
   include/linux/iio/iio.h:597: warning: No description found for parameter 'trig_readonly'
   include/linux/iio/trigger.h:151: warning: No description found for parameter 'indio_dev'
   include/linux/iio/trigger.h:151: warning: No description found for parameter 'trig'
   include/linux/device.h:970: warning: No description found for parameter 'dma_ops'
   drivers/regulator/core.c:1467: warning: Excess function parameter 'ret' description in 'regulator_dev_lookup'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'open'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'preclose'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'postclose'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'lastclose'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'set_busid'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'irq_handler'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'irq_preinstall'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'irq_postinstall'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'irq_uninstall'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'debugfs_init'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'debugfs_cleanup'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'gem_open_object'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'gem_close_object'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'prime_handle_to_fd'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'prime_fd_to_handle'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'gem_prime_export'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'gem_prime_import'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'gem_prime_pin'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'gem_prime_unpin'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'gem_prime_res_obj'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'gem_prime_get_sg_table'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'gem_prime_import_sg_table'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'gem_prime_vmap'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'gem_prime_vunmap'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'gem_prime_mmap'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'gem_vm_ops'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'major'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'minor'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'patchlevel'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'name'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'desc'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'date'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'driver_features'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'ioctls'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'num_ioctls'
   include/drm/drm_drv.h:438: warning: No description found for parameter 'fops'
   include/drm/drm_color_mgmt.h:1: warning: no structured comments found
   drivers/gpu/drm/drm_fb_cma_helper.c:557: warning: Excess function parameter 'num_crtc' description in 'drm_fbdev_cma_init'
   drivers/gpu/drm/drm_fb_cma_helper.c:558: warning: Excess function parameter 'num_crtc' description in 'drm_fbdev_cma_init'
   drivers/gpu/drm/i915/intel_lpe_audio.c:342: warning: No description found for parameter 'pipe'
   drivers/gpu/drm/i915/intel_lpe_audio.c:342: warning: No description found for parameter 'dp_output'
   drivers/gpu/drm/i915/intel_lpe_audio.c:342: warning: No description found for parameter 'link_rate'
   drivers/gpu/drm/i915/intel_lpe_audio.c:343: warning: No description found for parameter 'pipe'
   drivers/gpu/drm/i915/intel_lpe_audio.c:343: warning: No description found for parameter 'dp_output'
   drivers/gpu/drm/i915/intel_lpe_audio.c:343: warning: No description found for parameter 'link_rate'
   drivers/media/dvb-core/dvb_frontend.h:677: warning: No description found for parameter 'refcount'
   Documentation/core-api/assoc_array.rst:13: WARNING: Enumerated list ends without a blank line; unexpected unindent.
   Documentation/doc-guide/sphinx.rst:110: ERROR: Unknown target name: "sphinx c domain".
   kernel/sched/fair.c:7616: WARNING: Inline emphasis start-string without end-string.
   kernel/time/timer.c:1200: ERROR: Unexpected indentation.
   kernel/time/timer.c:1202: ERROR: Unexpected indentation.
   kernel/time/timer.c:1203: WARNING: Block quote ends without a blank line; unexpected unindent.
   include/linux/wait.h:122: WARNING: Block quote ends without a blank line; unexpected unindent.
   include/linux/wait.h:125: ERROR: Unexpected indentation.
   include/linux/wait.h:127: WARNING: Block quote ends without a blank line; unexpected unindent.
   kernel/time/hrtimer.c:990: WARNING: Block quote ends without a blank line; unexpected unindent.
   kernel/signal.c:322: WARNING: Inline literal start-string without end-string.
   include/linux/iio/iio.h:219: ERROR: Unexpected indentation.
   include/linux/iio/iio.h:220: WARNING: Block quote ends without a blank line; unexpected unindent.
   include/linux/iio/iio.h:226: WARNING: Definition list ends without a blank line; unexpected unindent.
   drivers/iio/industrialio-core.c:639: ERROR: Unknown target name: "iio_val".
   drivers/iio/industrialio-core.c:646: ERROR: Unknown target name: "iio_val".
   drivers/message/fusion/mptbase.c:5051: WARNING: Definition list ends without a blank line; unexpected unindent.
   drivers/tty/serial/serial_core.c:1898: WARNING: Definition list ends without a blank line; unexpected unindent.
   include/linux/regulator/driver.h:271: ERROR: Unknown target name: "regulator_regmap_x_voltage".
   include/linux/spi/spi.h:369: ERROR: Unexpected indentation.
   drivers/usb/core/message.c:478: ERROR: Unexpected indentation.
   drivers/usb/core/message.c:479: WARNING: Block quote ends without a blank line; unexpected unindent.
   Documentation/driver-api/usb.rst:623: ERROR: Unknown target name: "usb_type".
   Documentation/driver-api/usb.rst:623: ERROR: Unknown target name: "usb_dir".
   Documentation/driver-api/usb.rst:623: ERROR: Unknown target name: "usb_recip".
   Documentation/driver-api/usb.rst:689: ERROR: Unknown target name: "usbdevfs_urb_type".
   sound/soc/soc-core.c:2670: ERROR: Unknown target name: "snd_soc_daifmt".
   sound/core/jack.c:312: ERROR: Unknown target name: "snd_jack_btn".
   WARNING: dvipng command 'dvipng' cannot be run (needed for math display), check the imgmath_dvipng setting

vim +/irq_index +219 include/linux/i2c.h

^1da177e Linus Torvalds 2005-04-16  203  	/* a ioctl like command that can be used to perform specific functions
^1da177e Linus Torvalds 2005-04-16  204  	 * with the device.
^1da177e Linus Torvalds 2005-04-16  205  	 */
^1da177e Linus Torvalds 2005-04-16  206  	int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);
^1da177e Linus Torvalds 2005-04-16  207  
^1da177e Linus Torvalds 2005-04-16  208  	struct device_driver driver;
d2653e92 Jean Delvare   2008-04-29  209  	const struct i2c_device_id *id_table;
4735c98f Jean Delvare   2008-07-14  210  
4735c98f Jean Delvare   2008-07-14  211  	/* Device detection callback for automatic device creation */
310ec792 Jean Delvare   2009-12-14  212  	int (*detect)(struct i2c_client *, struct i2c_board_info *);
c3813d6a Jean Delvare   2009-12-14  213  	const unsigned short *address_list;
4735c98f Jean Delvare   2008-07-14  214  	struct list_head clients;
f55c71b4 Hans de Goede  2017-03-17  215  
f55c71b4 Hans de Goede  2017-03-17  216  	/* IRQ index for retreiving irq from ACPI resources */
f55c71b4 Hans de Goede  2017-03-17  217  	int irq_index;
^1da177e Linus Torvalds 2005-04-16  218  };
^1da177e Linus Torvalds 2005-04-16 @219  #define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)
^1da177e Linus Torvalds 2005-04-16  220  
2096b956 David Brownell 2007-05-01  221  /**
2096b956 David Brownell 2007-05-01  222   * struct i2c_client - represent an I2C slave device
d64f73be David Brownell 2007-07-12  223   * @flags: I2C_CLIENT_TEN indicates the device uses a ten bit chip address;
d64f73be David Brownell 2007-07-12  224   *	I2C_CLIENT_PEC indicates it uses SMBus Packet Error Checking
2096b956 David Brownell 2007-05-01  225   * @addr: Address used on the I2C bus connected to the parent adapter.
2096b956 David Brownell 2007-05-01  226   * @name: Indicates the type of the device, usually a chip name that's
2096b956 David Brownell 2007-05-01  227   *	generic enough to hide second-sourcing and compatible revisions.

:::::: The code at line 219 was first introduced by commit
:::::: 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 Linux-2.6.12-rc2

:::::: TO: Linus Torvalds <torvalds@ppc970.osdl.org>
:::::: CC: Linus Torvalds <torvalds@ppc970.osdl.org>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 6576 bytes --]

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH 01/15] mfd: Add Cherry Trail Whiskey Cove PMIC driver
  2017-03-17 17:00   ` Andy Shevchenko
@ 2017-03-20 10:41     ` Lee Jones
  2017-03-20 12:55       ` Andy Shevchenko
  0 siblings, 1 reply; 90+ messages in thread
From: Lee Jones @ 2017-03-20 10:41 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Hans de Goede, Rafael J . Wysocki, Len Brown, Wolfram Sang,
	Sebastian Reichel, MyungJoo Ham, Chanwoo Choi, linux-acpi,
	Takashi Iwai, linux-i2c, linux-kernel, linux-pm, Bin Gao,
	Felipe Balbi

On Fri, 17 Mar 2017, Andy Shevchenko wrote:

> On Fri, 2017-03-17 at 10:55 +0100, Hans de Goede wrote:
> > Add mfd driver for Intel CHT Whiskey Cove PMIC, based on various non
> > upstreamed CHT Whiskey Cove PMIC patches.
> > 
> > This is a somewhat minimal version which adds irqchip support and
> > cells
> > for: ACPI PMIC opregion support, the i2c-controller driving the
> > external
> > charger irc and the pwrsrc/extcon block.
> > 
> > Further cells can be added in the future if/when drivers are
> > upstreamed
> > for them.
> 
> Couple of minor comments, otherwise looks good to me:
> 
> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> 
> > +/* Whiskey Cove PMIC share same ACPI ID between different platforms
> > */
> > +#define CHT_WC_HRV		3
> > +
> > +/* Level 1 IRQs (level 2 IRQs are handled in the child device
> > drivers) */
> > +enum {
> > +	CHT_WC_PWRSRC_IRQ = 0,
> > +	CHT_WC_THRM_IRQ,
> > +	CHT_WC_BCU_IRQ,
> > +	CHT_WC_ADC_IRQ,
> > +	CHT_WC_EXT_CHGR_IRQ,
> > +	CHT_WC_GPIO_IRQ,
> > +	/* There is no irq 6 */
> > +	CHT_WC_CRIT_IRQ = 7,
> 
> I would prefer explicit over implicit (adding = N to each line), but
> this is minor.

No need.  The C standard is clear on what is expected of enums.

[...]

> > +	return devm_mfd_add_devices(dev, -1, cht_wc_dev,
> > ARRAY_SIZE(cht_wc_dev),
> > +			NULL, 0, regmap_irq_get_domain(pmic-
> > >irq_chip_data));
> 
> PLATFORM_DEVID_NONE, please.

+1

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH 01/15] mfd: Add Cherry Trail Whiskey Cove PMIC driver
  2017-03-20 10:41     ` Lee Jones
@ 2017-03-20 12:55       ` Andy Shevchenko
  0 siblings, 0 replies; 90+ messages in thread
From: Andy Shevchenko @ 2017-03-20 12:55 UTC (permalink / raw)
  To: Lee Jones
  Cc: Hans de Goede, Rafael J . Wysocki, Len Brown, Wolfram Sang,
	Sebastian Reichel, MyungJoo Ham, Chanwoo Choi, linux-acpi,
	Takashi Iwai, linux-i2c, linux-kernel, linux-pm, Bin Gao,
	Felipe Balbi

On Mon, 2017-03-20 at 10:41 +0000, Lee Jones wrote:
> On Fri, 17 Mar 2017, Andy Shevchenko wrote:
> > On Fri, 2017-03-17 at 10:55 +0100, Hans de Goede wrote:

> > > +enum {
> > > +	CHT_WC_PWRSRC_IRQ = 0,
> > > +	CHT_WC_THRM_IRQ,
> > > +	CHT_WC_BCU_IRQ,
> > > +	CHT_WC_ADC_IRQ,
> > > +	CHT_WC_EXT_CHGR_IRQ,
> > > +	CHT_WC_GPIO_IRQ,
> > > +	/* There is no irq 6 */
> > > +	CHT_WC_CRIT_IRQ = 7,
> > 
> > I would prefer explicit over implicit (adding = N to each line), but
> > this is minor.
> 
> No need.  The C standard is clear on what is expected of enums.

I understand that, though I don't like gaps in enums. That's why I
prefer in such cases pure #define over enum (yes, I understand that enum
in many cases is better).

But this all matter of taste. So, I will not insist if it would be left
as it is now.

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH 03/15] extcon: cht-wc: Add Intel Cherry Trail Whiskey Cove PMIC extcon driver
  2017-03-20  1:33   ` Chanwoo Choi
@ 2017-03-20 13:00     ` Andy Shevchenko
  2017-03-21  3:54       ` Chanwoo Choi
  2017-03-20 19:57     ` Hans de Goede
  1 sibling, 1 reply; 90+ messages in thread
From: Andy Shevchenko @ 2017-03-20 13:00 UTC (permalink / raw)
  To: Chanwoo Choi, Hans de Goede, Rafael J . Wysocki, Len Brown,
	Wolfram Sang, Lee Jones, Sebastian Reichel, MyungJoo Ham
  Cc: linux-acpi, Takashi Iwai, linux-i2c, linux-kernel, linux-pm

On Mon, 2017-03-20 at 10:33 +0900, Chanwoo Choi wrote:
> On 2017년 03월 17일 18:55, Hans de Goede wrote:

> > +static const struct platform_device_id cht_wc_extcon_table[] = {
> > +	{ .name = "cht_wcove_pwrsrc" },
> 
> You use the 'cht_wc' word instead of 'cht_wcove_pwrsrc'.
> So, To maintain the consistency, you better to use the 'cht-wc' as the
> name.
> - I prefer to use '-' instead of '_' in the name.
> 	.name ="cht-wc"

I would keep as Hans did for the sake of consistency among all Whiskey
Cove device drivers (and predecessors like Crystal Cove).

I understand your point from extcon subsystem view, but PMICs like
Whiskey Cove are multi-functional devices, and thus naming across them
(same prefix in use to be precise) is better idea.

> 
> > +	{},
> > +};
> > +MODULE_DEVICE_TABLE(platform, cht_wc_extcon_table);

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [04/15] power: supply: bq24190_charger: Add no_register_reset pdata flag
  2017-03-20  5:27                 ` Sebastian Reichel
@ 2017-03-20 13:54                   ` Hans de Goede
  2017-03-20 17:04                     ` Hans de Goede
  0 siblings, 1 reply; 90+ messages in thread
From: Hans de Goede @ 2017-03-20 13:54 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: Liam Breck, Andy Shevchenko, Tony Lindgren, linux-pm, Liam Breck

Hi,

On 20-03-17 06:27, Sebastian Reichel wrote:
> Hi,
>
> On Sun, Mar 19, 2017 at 10:42:00AM +0100, Hans de Goede wrote:

<snip>

>> We want one driver which is solidly in control of the charger
>> since getting that wrong is quite bad and we want to extend
>> the information it is exporting to userspace in the form of
>> power_supply properties with some extra info.
>>
>> So taking that as a starting point and generalizing that,
>> I think that if we want we can make something more generic then
>> my original patch for this. My idea is to introduce something
>> called a power_supply_properties_provider, with an API
>> like this:
>
> Thanks for thinking about this. From what I can see it should
> be enough to just avoid exposing a battery device at all in
> the charger driver, though. It does not really provide useful
> information anyways.

Interesting suggestion, 2 remarks / questions:

1) Given that we do not want to break existing setups
which may depend on the existing battery interface on the bq24190
driver and add a flag to not register it, or are you suggesting
to simply remove it all together? Removing it all together would
be better from a maintenance pov. Liam, you indicated that you
are the main user of the bq24190 driver currently, do you need
the battery power_supply interface for your use case ?

2) Not using the battery interface of the bq24190 driver at all
means that the fuelgauge driver needs to grow some extra
properties, specifically it will need to start reporting status,
something which the bq24190 driver really has a better idea
of the the fuel gauge.

Note that I do not have documentation on the fuel-gauge (not even
an out of tree driver from android-x86). It is all based on dumping
registers every 5 minutes during a charge / discharge cycle and
then puzzling together which register is what. I'm quite confident
I've this all right, but this does make adding a status property
harder (might involve some heuristics instead of being able
to get the absolute truth from the charge ic itself).

As such I think the power_supply_properties_provider proposal I'm
doing might still be a good idea. Anyways I will dig through the
dumps I've some more to see if I can find a good way to get
charging status from the fuel gauge and get back to you when
I'm done with looking at the dumps.

Regards,

Hans





>
>> typedef int (*power_supply_properties_provider_get_property_t)(
>> 	enum power_supply_property prop, union power_supply_propval *val,
>> 	void *driver_data);
>>
>> struct power_supply_properties_provider;
>>
>> struct power_supply_properties_provider *
>> power_supply_properties_provider_register(
>> 	const char *name,
>> 	power_supply_properties_provider_get_property_t get_property,
>> 	const enum power_supply_property *properties,
>> 	size_t num_properties,
>> 	void *driver_data);
>>
>> void power_supply_properties_provider_unregister(
>> 	struct power_supply_properties_provider *pspp);
>>
>> struct power_supply_properties_provider *
>> 	power_supply_properties_provider_get(const char *name);
>>
>> void power_supply_properties_provider_put(
>> 	struct power_supply_properties_provider *pspp);
>>
>> int power_supply_properties_provider_merge_properties(
>> 	struct power_supply_properties_provider *pspp,
>> 	const enum power_supply_property *properties,
>> 	size_t num_properties,
>> 	enum power_supply_property **merged_properties_ret,
>> 	size_t *merged_num_properties_ret);
>>
>> int power_supply_properties_provider_get_property(
>> 	struct power_supply_properties_provider *pspp,
>> 	enum power_supply_property prop,
>> 	union power_supply_propval *val);
>>
>> So in this case the faul-gauge driver would call
>> power_supply_properties_provider_register() from probe and
>> power_supply_properties_provider_unregister() from remove.
>>
>> The struct power_supply_properties_provider will be ref-counted
>> so that it will stick around after unregister in case any
>> consumers who have gotten a ref through
>> power_supply_properties_provider_get can still call
>> power_supply_properties_provider_get_property, which after
>> unregister will simply always return -ENXIO.
>>
>> A driver wanting to use extra properties like bq24190_charger
>> will call power_supply_properties_provider_get (with a name
>> provided through platform_data), use a dynamically allocated
>> struct power_supply_desc and fill the properties of that
>> using power_supply_properties_provider_merge_properties
>> to merge its own properties with the
>> power_supply_properties_provider's properties and in its
>> get_property method have a default label which calls
>> power_supply_properties_provider_get_property.
>>
>> This would still add quite a bit more code then my original
>> patch for what may very well end up being a one-of solution,
>> but I guess we may encounter this problem more often and
>> this will offer a nice generic and clean way for dealing
>> with adding extra info from other sources to a power_supply
>> driver, so I'm happy to turn this idea / design into working
>> code if people like this better then my original patch.
>>
>> Liam, Sebastian what do you think of the above proposal?
>>
>> Regards,
>>
>> Hans
>>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [04/15] power: supply: bq24190_charger: Add no_register_reset pdata flag
  2017-03-20 13:54                   ` Hans de Goede
@ 2017-03-20 17:04                     ` Hans de Goede
  2017-03-20 17:51                       ` Liam Breck
  0 siblings, 1 reply; 90+ messages in thread
From: Hans de Goede @ 2017-03-20 17:04 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: Liam Breck, Andy Shevchenko, Tony Lindgren, linux-pm, Liam Breck

Hi,

On 20-03-17 14:54, Hans de Goede wrote:
> Hi,
>
> On 20-03-17 06:27, Sebastian Reichel wrote:
>> Hi,
>>
>> On Sun, Mar 19, 2017 at 10:42:00AM +0100, Hans de Goede wrote:
>
> <snip>
>
>>> We want one driver which is solidly in control of the charger
>>> since getting that wrong is quite bad and we want to extend
>>> the information it is exporting to userspace in the form of
>>> power_supply properties with some extra info.
>>>
>>> So taking that as a starting point and generalizing that,
>>> I think that if we want we can make something more generic then
>>> my original patch for this. My idea is to introduce something
>>> called a power_supply_properties_provider, with an API
>>> like this:
>>
>> Thanks for thinking about this. From what I can see it should
>> be enough to just avoid exposing a battery device at all in
>> the charger driver, though. It does not really provide useful
>> information anyways.
>
> Interesting suggestion, 2 remarks / questions:
>
> 1) Given that we do not want to break existing setups
> which may depend on the existing battery interface on the bq24190
> driver and add a flag to not register it, or are you suggesting
> to simply remove it all together? Removing it all together would
> be better from a maintenance pov. Liam, you indicated that you
> are the main user of the bq24190 driver currently, do you need
> the battery power_supply interface for your use case ?
>
> 2) Not using the battery interface of the bq24190 driver at all
> means that the fuelgauge driver needs to grow some extra
> properties, specifically it will need to start reporting status,
> something which the bq24190 driver really has a better idea
> of the the fuel gauge.
>
> Note that I do not have documentation on the fuel-gauge (not even
> an out of tree driver from android-x86). It is all based on dumping
> registers every 5 minutes during a charge / discharge cycle and
> then puzzling together which register is what. I'm quite confident
> I've this all right, but this does make adding a status property
> harder (might involve some heuristics instead of being able
> to get the absolute truth from the charge ic itself).
>
> As such I think the power_supply_properties_provider proposal I'm
> doing might still be a good idea. Anyways I will dig through the
> dumps I've some more to see if I can find a good way to get
> charging status from the fuel gauge and get back to you when
> I'm done with looking at the dumps.

Ok, it looks like this approach should work. Downside is that
the fuel-gauge does not get interrupts when changing state,
but I can use extcon to get power being plugged in / removed
which is the most important state change to immediately
notify userspace about.

I will rework the patch-set accordingly. For now I'm just
going to throw in a patch completely removing the battery
power_supply from the bq24190_charger driver. If that is a
problem then that one can be replaced by one using a device
property to enable/disable the battery power_supply device,
question if we are going for a property for this, what should
the default be ? I tend toward a default of off / no battery
interface unless requested but that may break compatibility
with some existing dt files + userspace expecting it to be
there ?

Regards,

Hans





>>> typedef int (*power_supply_properties_provider_get_property_t)(
>>>     enum power_supply_property prop, union power_supply_propval *val,
>>>     void *driver_data);
>>>
>>> struct power_supply_properties_provider;
>>>
>>> struct power_supply_properties_provider *
>>> power_supply_properties_provider_register(
>>>     const char *name,
>>>     power_supply_properties_provider_get_property_t get_property,
>>>     const enum power_supply_property *properties,
>>>     size_t num_properties,
>>>     void *driver_data);
>>>
>>> void power_supply_properties_provider_unregister(
>>>     struct power_supply_properties_provider *pspp);
>>>
>>> struct power_supply_properties_provider *
>>>     power_supply_properties_provider_get(const char *name);
>>>
>>> void power_supply_properties_provider_put(
>>>     struct power_supply_properties_provider *pspp);
>>>
>>> int power_supply_properties_provider_merge_properties(
>>>     struct power_supply_properties_provider *pspp,
>>>     const enum power_supply_property *properties,
>>>     size_t num_properties,
>>>     enum power_supply_property **merged_properties_ret,
>>>     size_t *merged_num_properties_ret);
>>>
>>> int power_supply_properties_provider_get_property(
>>>     struct power_supply_properties_provider *pspp,
>>>     enum power_supply_property prop,
>>>     union power_supply_propval *val);
>>>
>>> So in this case the faul-gauge driver would call
>>> power_supply_properties_provider_register() from probe and
>>> power_supply_properties_provider_unregister() from remove.
>>>
>>> The struct power_supply_properties_provider will be ref-counted
>>> so that it will stick around after unregister in case any
>>> consumers who have gotten a ref through
>>> power_supply_properties_provider_get can still call
>>> power_supply_properties_provider_get_property, which after
>>> unregister will simply always return -ENXIO.
>>>
>>> A driver wanting to use extra properties like bq24190_charger
>>> will call power_supply_properties_provider_get (with a name
>>> provided through platform_data), use a dynamically allocated
>>> struct power_supply_desc and fill the properties of that
>>> using power_supply_properties_provider_merge_properties
>>> to merge its own properties with the
>>> power_supply_properties_provider's properties and in its
>>> get_property method have a default label which calls
>>> power_supply_properties_provider_get_property.
>>>
>>> This would still add quite a bit more code then my original
>>> patch for what may very well end up being a one-of solution,
>>> but I guess we may encounter this problem more often and
>>> this will offer a nice generic and clean way for dealing
>>> with adding extra info from other sources to a power_supply
>>> driver, so I'm happy to turn this idea / design into working
>>> code if people like this better then my original patch.
>>>
>>> Liam, Sebastian what do you think of the above proposal?
>>>
>>> Regards,
>>>
>>> Hans
>>>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [04/15] power: supply: bq24190_charger: Add no_register_reset pdata flag
  2017-03-20 17:04                     ` Hans de Goede
@ 2017-03-20 17:51                       ` Liam Breck
  2017-03-20 18:01                         ` Hans de Goede
  0 siblings, 1 reply; 90+ messages in thread
From: Liam Breck @ 2017-03-20 17:51 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Sebastian Reichel, Andy Shevchenko, Tony Lindgren, linux-pm, Liam Breck

On Mon, Mar 20, 2017 at 10:04 AM, Hans de Goede <hdegoede@redhat.com> wrote:
> Hi,
>
>
> On 20-03-17 14:54, Hans de Goede wrote:
>>
>> Hi,
>>
>> On 20-03-17 06:27, Sebastian Reichel wrote:
>>>
>>> Hi,
>>>
>>> On Sun, Mar 19, 2017 at 10:42:00AM +0100, Hans de Goede wrote:
>>
>>
>> <snip>
>>
>>>> We want one driver which is solidly in control of the charger
>>>> since getting that wrong is quite bad and we want to extend
>>>> the information it is exporting to userspace in the form of
>>>> power_supply properties with some extra info.
>>>>
>>>> So taking that as a starting point and generalizing that,
>>>> I think that if we want we can make something more generic then
>>>> my original patch for this. My idea is to introduce something
>>>> called a power_supply_properties_provider, with an API
>>>> like this:
>>>
>>>
>>> Thanks for thinking about this. From what I can see it should
>>> be enough to just avoid exposing a battery device at all in
>>> the charger driver, though. It does not really provide useful
>>> information anyways.
>>
>>
>> Interesting suggestion, 2 remarks / questions:
>>
>> 1) Given that we do not want to break existing setups
>> which may depend on the existing battery interface on the bq24190
>> driver and add a flag to not register it, or are you suggesting
>> to simply remove it all together? Removing it all together would
>> be better from a maintenance pov. Liam, you indicated that you
>> are the main user of the bq24190 driver currently, do you need
>> the battery power_supply interface for your use case ?
>>
>> 2) Not using the battery interface of the bq24190 driver at all
>> means that the fuelgauge driver needs to grow some extra
>> properties, specifically it will need to start reporting status,
>> something which the bq24190 driver really has a better idea
>> of the the fuel gauge.

Our userspace looks at bq24190-battery & -charger. If your userspace
can work with /sys/class/power_supply/whisky_cove-battery/* can't you
leave .bq24190-battery as is?

bq24190-battery's properties could move to -charger, tho health &
online would have to change name, replace same in -charger, or be
dropped.

>> Note that I do not have documentation on the fuel-gauge (not even
>> an out of tree driver from android-x86). It is all based on dumping
>> registers every 5 minutes during a charge / discharge cycle and
>> then puzzling together which register is what. I'm quite confident
>> I've this all right, but this does make adding a status property
>> harder (might involve some heuristics instead of being able
>> to get the absolute truth from the charge ic itself).
>>
>> As such I think the power_supply_properties_provider proposal I'm
>> doing might still be a good idea. Anyways I will dig through the
>> dumps I've some more to see if I can find a good way to get
>> charging status from the fuel gauge and get back to you when
>> I'm done with looking at the dumps.
>
>
> Ok, it looks like this approach should work. Downside is that
> the fuel-gauge does not get interrupts when changing state,
> but I can use extcon to get power being plugged in / removed
> which is the most important state change to immediately
> notify userspace about.
>
> I will rework the patch-set accordingly. For now I'm just
> going to throw in a patch completely removing the battery
> power_supply from the bq24190_charger driver. If that is a
> problem then that one can be replaced by one using a device
> property to enable/disable the battery power_supply device,
> question if we are going for a property for this, what should
> the default be ? I tend toward a default of off / no battery
> interface unless requested but that may break compatibility
> with some existing dt files + userspace expecting it to be
> there ?
>
>
> Regards,
>
> Hans
>
>
>
>
>
>>>> typedef int (*power_supply_properties_provider_get_property_t)(
>>>>     enum power_supply_property prop, union power_supply_propval *val,
>>>>     void *driver_data);
>>>>
>>>> struct power_supply_properties_provider;
>>>>
>>>> struct power_supply_properties_provider *
>>>> power_supply_properties_provider_register(
>>>>     const char *name,
>>>>     power_supply_properties_provider_get_property_t get_property,
>>>>     const enum power_supply_property *properties,
>>>>     size_t num_properties,
>>>>     void *driver_data);
>>>>
>>>> void power_supply_properties_provider_unregister(
>>>>     struct power_supply_properties_provider *pspp);
>>>>
>>>> struct power_supply_properties_provider *
>>>>     power_supply_properties_provider_get(const char *name);
>>>>
>>>> void power_supply_properties_provider_put(
>>>>     struct power_supply_properties_provider *pspp);
>>>>
>>>> int power_supply_properties_provider_merge_properties(
>>>>     struct power_supply_properties_provider *pspp,
>>>>     const enum power_supply_property *properties,
>>>>     size_t num_properties,
>>>>     enum power_supply_property **merged_properties_ret,
>>>>     size_t *merged_num_properties_ret);
>>>>
>>>> int power_supply_properties_provider_get_property(
>>>>     struct power_supply_properties_provider *pspp,
>>>>     enum power_supply_property prop,
>>>>     union power_supply_propval *val);
>>>>
>>>> So in this case the faul-gauge driver would call
>>>> power_supply_properties_provider_register() from probe and
>>>> power_supply_properties_provider_unregister() from remove.
>>>>
>>>> The struct power_supply_properties_provider will be ref-counted
>>>> so that it will stick around after unregister in case any
>>>> consumers who have gotten a ref through
>>>> power_supply_properties_provider_get can still call
>>>> power_supply_properties_provider_get_property, which after
>>>> unregister will simply always return -ENXIO.
>>>>
>>>> A driver wanting to use extra properties like bq24190_charger
>>>> will call power_supply_properties_provider_get (with a name
>>>> provided through platform_data), use a dynamically allocated
>>>> struct power_supply_desc and fill the properties of that
>>>> using power_supply_properties_provider_merge_properties
>>>> to merge its own properties with the
>>>> power_supply_properties_provider's properties and in its
>>>> get_property method have a default label which calls
>>>> power_supply_properties_provider_get_property.
>>>>
>>>> This would still add quite a bit more code then my original
>>>> patch for what may very well end up being a one-of solution,
>>>> but I guess we may encounter this problem more often and
>>>> this will offer a nice generic and clean way for dealing
>>>> with adding extra info from other sources to a power_supply
>>>> driver, so I'm happy to turn this idea / design into working
>>>> code if people like this better then my original patch.
>>>>
>>>> Liam, Sebastian what do you think of the above proposal?
>>>>
>>>> Regards,
>>>>
>>>> Hans
>>>>
>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [04/15] power: supply: bq24190_charger: Add no_register_reset pdata flag
  2017-03-20 17:51                       ` Liam Breck
@ 2017-03-20 18:01                         ` Hans de Goede
  2017-03-20 18:19                           ` Liam Breck
  0 siblings, 1 reply; 90+ messages in thread
From: Hans de Goede @ 2017-03-20 18:01 UTC (permalink / raw)
  To: Liam Breck
  Cc: Sebastian Reichel, Andy Shevchenko, Tony Lindgren, linux-pm, Liam Breck

Hi,

On 20-03-17 18:51, Liam Breck wrote:
> On Mon, Mar 20, 2017 at 10:04 AM, Hans de Goede <hdegoede@redhat.com> wrote:
>> Hi,
>>
>>
>> On 20-03-17 14:54, Hans de Goede wrote:
>>>
>>> Hi,
>>>
>>> On 20-03-17 06:27, Sebastian Reichel wrote:
>>>>
>>>> Hi,
>>>>
>>>> On Sun, Mar 19, 2017 at 10:42:00AM +0100, Hans de Goede wrote:
>>>
>>>
>>> <snip>
>>>
>>>>> We want one driver which is solidly in control of the charger
>>>>> since getting that wrong is quite bad and we want to extend
>>>>> the information it is exporting to userspace in the form of
>>>>> power_supply properties with some extra info.
>>>>>
>>>>> So taking that as a starting point and generalizing that,
>>>>> I think that if we want we can make something more generic then
>>>>> my original patch for this. My idea is to introduce something
>>>>> called a power_supply_properties_provider, with an API
>>>>> like this:
>>>>
>>>>
>>>> Thanks for thinking about this. From what I can see it should
>>>> be enough to just avoid exposing a battery device at all in
>>>> the charger driver, though. It does not really provide useful
>>>> information anyways.
>>>
>>>
>>> Interesting suggestion, 2 remarks / questions:
>>>
>>> 1) Given that we do not want to break existing setups
>>> which may depend on the existing battery interface on the bq24190
>>> driver and add a flag to not register it, or are you suggesting
>>> to simply remove it all together? Removing it all together would
>>> be better from a maintenance pov. Liam, you indicated that you
>>> are the main user of the bq24190 driver currently, do you need
>>> the battery power_supply interface for your use case ?
>>>
>>> 2) Not using the battery interface of the bq24190 driver at all
>>> means that the fuelgauge driver needs to grow some extra
>>> properties, specifically it will need to start reporting status,
>>> something which the bq24190 driver really has a better idea
>>> of the the fuel gauge.
>
> Our userspace looks at bq24190-battery & -charger. If your userspace
> can work with /sys/class/power_supply/whisky_cove-battery/* can't you
> leave .bq24190-battery as is?

No, my userspace is a generic distro which uses upower, which as I
explained before will look at *all* battery type power_supply devices
and will consider each of them being a separate battery. There *must*
be only one battery type power_supply per physical battery, that is
simply how the userspace ABI works.

> bq24190-battery's properties could move to -charger, tho health &
> online would have to change name, replace same in -charger, or be
> dropped.

That is one option, I can also simply make the registration dependent
on a device-property, then you do not need to change your userspace.

In that case I would prefer for the behavior to be to not register
the battery power_supply device unless the boolean device(tree)-property
named "linux,register-battery-power-supply" is present. But if you
need things to keep working the same with older dtb files which
will not contain that property, we can also go for:
"linux,disable-battery-power-supply"

Regards,

Hans

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH 03/15] extcon: cht-wc: Add Intel Cherry Trail Whiskey Cove PMIC extcon driver
  2017-03-17 17:18   ` Andy Shevchenko
@ 2017-03-20 18:08     ` Hans de Goede
  0 siblings, 0 replies; 90+ messages in thread
From: Hans de Goede @ 2017-03-20 18:08 UTC (permalink / raw)
  To: Andy Shevchenko, Rafael J . Wysocki, Len Brown, Wolfram Sang,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: linux-acpi, Takashi Iwai, linux-i2c, linux-kernel, linux-pm,
	Felipe Balbi

Hi,

On 17-03-17 18:18, Andy Shevchenko wrote:
> On Fri, 2017-03-17 at 10:55 +0100, Hans de Goede wrote:
>> Add a driver for charger detection / control on the Intel Cherrytrail
>> Whiskey Cove PMIC.
>
> +Cc: Felipe for some question(s) below.
>
>>  drivers/extcon/extcon-cht-wc.c | 356
>
> I would use same pattern across drivers, i.e. "chtwc" (same for the rest
> of the drivers in this series).

I already answered this in another part of the thread,
but for the archives sake let me copy and paste my answer:

"One thing I disagree with is the cht_wc > chtwc rename you are
proposing for one Cherry Trail and Whiskey Cove are 2 different
words (4 if you look at spelling but 2 if you look at pronunciation,
so IMHO cht_wc is more readable other then that I see the suggested
rename as a lot of extra churn without any tangible benefits."

>
>> +#define CHT_WC_PWRSRC_IRQ		0x6e03
>> +#define CHT_WC_PWRSRC_IRQ_MASK		0x6e0f
>> +#define CHT_WC_PWRSRC_STS		0x6e1e
>> +#define CHT_WC_PWRSRC_VBUS		BIT(0)
>> +#define CHT_WC_PWRSRC_DC		BIT(1)
>> +#define CHT_WC_PWRSRC_BAT		BIT(2)
>> +#define CHT_WC_PWRSRC_ID_GND		BIT(3)
>> +#define CHT_WC_PWRSRC_ID_FLOAT		BIT(4)
>
> Not obvious for which register those bit definitions are.

They are for all 3 CHT_WC_PWRSRC_* registers, this is the
more or less usual irq setup for some i2c devices where
there is a status register, an irq register where the hardware
sets bits to 1 (and we write 1 to clear) when the corresponding
status bits changes and a mask register to select which irq
register bits actually will raise the interrupt line.

> Also, keep them ordered by offset.

Will fix.

>
>> +
>> +#define CHT_WC_PHYCTRL			0x5e07
>> +
>
>> +#define CHT_WC_CHGRCTRL0		0x5e16
>
> Dup!

Good catch, will fix.


>
>> +
>> +#define CHT_WC_CHGRCTRL0		0x5e16
>
>> +static int cht_wc_extcon_get_charger(struct cht_wc_extcon_data *ext)
>> +{
>> +	int ret, usbsrc, status, retries = 5;
>> +
>> +	do {
>> +		ret = regmap_read(ext->regmap, CHT_WC_USBSRC,
>> &usbsrc);
>> +		if (ret) {
>> +			dev_err(ext->dev, "Error reading usbsrc:
>> %d\n", ret);
>> +			return ret;
>> +		}
>> +		status = usbsrc & CHT_WC_USBSRC_STS_MASK;
>> +		if (status == CHT_WC_USBSRC_STS_SUCCESS ||
>> +		    status == CHT_WC_USBSRC_STS_FAIL)
>> +			break;
>> +
>
>> +		msleep(200);
>
> Comment why and why so long?

Fixed for v2 (actually switched to using jiffies +
time_before for a more accurate timeout).

>> +	} while (retries--);
>
>> +static void cht_wc_extcon_det_event(struct cht_wc_extcon_data *ext)
>
> det -> detect ?

Renamed to more accurate cht_wc_extcon_pwrsrc_event

> +static irqreturn_t cht_wc_extcon_isr(int irq, void *data)
>> +{
>> +	struct cht_wc_extcon_data *ext = data;
>> +	int ret, irqs;
>> +
>> +	ret = regmap_read(ext->regmap, CHT_WC_PWRSRC_IRQ, &irqs);
>> +	if (ret)
>> +		dev_err(ext->dev, "Error reading irqs: %d\n", ret);
>
> Shouldn't we return IRQ_NONE here?

I was wondering the same myself here, there is no good
answer here, this should simply never fail ... which does
make returning IRQ_NONE a good idea, I was worried that
would lead to a "nobody cared, disabling irq", but as said this
should never happen, so when it does, disabling the irq is
probably for the best. Will fix.

>
>> +
>> +	cht_wc_extcon_det_event(ext);
>> +
>> +	ret = regmap_write(ext->regmap, CHT_WC_PWRSRC_IRQ, irqs);
>> +	if (ret)
>> +		dev_err(ext->dev, "Error writing irqs: %d\n", ret);
>> +
>> +	return IRQ_HANDLED;
>> +}
>> +
>
>> +/* usb_id sysfs attribute for debug / testing purposes */
>
> Hmm... I would use debugfs for debug, otherwise it looks like it should
> be framework (extcon) wide.

Unfortunately these kinda sysfs files are somewhat normal when
dealing with USB-OTG. For example my board does not have the
id-pin hooked up to the connector, so to test host mode
I need to echo "gnd" to the sysfs attr. But also if I actually
want to use host-mode (or anyone else with the same or a similar
board).

This definitely is not something which belongs in the extcon-core.

> Perhaps Felipe can advise something here.
>
>> +static int cht_wc_extcon_probe(struct platform_device *pdev)
>> +{
>
>> +	struct cht_wc_extcon_data *ext;
>> +	struct intel_soc_pmic *pmic = dev_get_drvdata(pdev-
>>> dev.parent);
>
> Exchange them (assignment first).

Fixed.

>
>> +	int irq, ret;
>> +
>
>
>> +	ret = devm_request_threaded_irq(ext->dev, irq, NULL,
>> cht_wc_extcon_isr,
>> +					IRQF_ONESHOT, pdev->name,
>> ext);
>> +	if (ret) {
>> +		dev_err(ext->dev, "Failed to request interrupt\n");
>> +		return ret;
>> +	}
>> +
>> +	/* Unmask irqs */
>> +	ret = regmap_write(ext->regmap, CHT_WC_PWRSRC_IRQ_MASK,
>> +			   (int)~(CHT_WC_PWRSRC_VBUS |
>
> Hmm... Do you need explicit casting here?

Yes because the BIT(x) macros are unsigned longs and the ~ sets
the MSB so then the compiler complaints about truncating the
variable without the cast.

>
>> CHT_WC_PWRSRC_ID_GND |
>> +				  CHT_WC_PWRSRC_ID_FLOAT));
>> +	if (ret) {
>> +		dev_err(ext->dev, "Error writing irq-mask: %d\n",
>> ret);
>> +		return ret;
>> +	}
>

Regards,

Hans

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [04/15] power: supply: bq24190_charger: Add no_register_reset pdata flag
  2017-03-20 18:01                         ` Hans de Goede
@ 2017-03-20 18:19                           ` Liam Breck
  2017-03-20 19:22                             ` Hans de Goede
  0 siblings, 1 reply; 90+ messages in thread
From: Liam Breck @ 2017-03-20 18:19 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Sebastian Reichel, Andy Shevchenko, Tony Lindgren, linux-pm, Liam Breck

On Mon, Mar 20, 2017 at 11:01 AM, Hans de Goede <hdegoede@redhat.com> wrote:
> Hi,
>
>
> On 20-03-17 18:51, Liam Breck wrote:
>>
>> On Mon, Mar 20, 2017 at 10:04 AM, Hans de Goede <hdegoede@redhat.com>
>> wrote:
>>>
>>> Hi,
>>>
>>>
>>> On 20-03-17 14:54, Hans de Goede wrote:
>>>>
>>>>
>>>> Hi,
>>>>
>>>> On 20-03-17 06:27, Sebastian Reichel wrote:
>>>>>
>>>>>
>>>>> Hi,
>>>>>
>>>>> On Sun, Mar 19, 2017 at 10:42:00AM +0100, Hans de Goede wrote:
>>>>
>>>>
>>>>
>>>> <snip>
>>>>
>>>>>> We want one driver which is solidly in control of the charger
>>>>>> since getting that wrong is quite bad and we want to extend
>>>>>> the information it is exporting to userspace in the form of
>>>>>> power_supply properties with some extra info.
>>>>>>
>>>>>> So taking that as a starting point and generalizing that,
>>>>>> I think that if we want we can make something more generic then
>>>>>> my original patch for this. My idea is to introduce something
>>>>>> called a power_supply_properties_provider, with an API
>>>>>> like this:
>>>>>
>>>>>
>>>>>
>>>>> Thanks for thinking about this. From what I can see it should
>>>>> be enough to just avoid exposing a battery device at all in
>>>>> the charger driver, though. It does not really provide useful
>>>>> information anyways.
>>>>
>>>>
>>>>
>>>> Interesting suggestion, 2 remarks / questions:
>>>>
>>>> 1) Given that we do not want to break existing setups
>>>> which may depend on the existing battery interface on the bq24190
>>>> driver and add a flag to not register it, or are you suggesting
>>>> to simply remove it all together? Removing it all together would
>>>> be better from a maintenance pov. Liam, you indicated that you
>>>> are the main user of the bq24190 driver currently, do you need
>>>> the battery power_supply interface for your use case ?
>>>>
>>>> 2) Not using the battery interface of the bq24190 driver at all
>>>> means that the fuelgauge driver needs to grow some extra
>>>> properties, specifically it will need to start reporting status,
>>>> something which the bq24190 driver really has a better idea
>>>> of the the fuel gauge.
>>
>>
>> Our userspace looks at bq24190-battery & -charger. If your userspace
>> can work with /sys/class/power_supply/whisky_cove-battery/* can't you
>> leave .bq24190-battery as is?
>
>
> No, my userspace is a generic distro which uses upower, which as I
> explained before will look at *all* battery type power_supply devices
> and will consider each of them being a separate battery. There *must*
> be only one battery type power_supply per physical battery, that is
> simply how the userspace ABI works.
>
>> bq24190-battery's properties could move to -charger, tho health &
>> online would have to change name, replace same in -charger, or be
>> dropped.
>
>
> That is one option, I can also simply make the registration dependent
> on a device-property, then you do not need to change your userspace.
>
> In that case I would prefer for the behavior to be to not register
> the battery power_supply device unless the boolean device(tree)-property
> named "linux,register-battery-power-supply" is present. But if you
> need things to keep working the same with older dtb files which
> will not contain that property, we can also go for:
> "linux,disable-battery-power-supply"

Just if (!pdata->x) register(battery). Eventually I'll have to move
those properties to charger, as we added a fuel gauge after charger
driver was written.

Or change bq24190_battery_desc.type to not be _BATTERY?

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [04/15] power: supply: bq24190_charger: Add no_register_reset pdata flag
  2017-03-20 18:19                           ` Liam Breck
@ 2017-03-20 19:22                             ` Hans de Goede
  2017-03-20 21:14                               ` Sebastian Reichel
  2017-03-20 21:15                               ` Liam Breck
  0 siblings, 2 replies; 90+ messages in thread
From: Hans de Goede @ 2017-03-20 19:22 UTC (permalink / raw)
  To: Liam Breck
  Cc: Sebastian Reichel, Andy Shevchenko, Tony Lindgren, linux-pm, Liam Breck

Hi,

On 20-03-17 19:19, Liam Breck wrote:
> On Mon, Mar 20, 2017 at 11:01 AM, Hans de Goede <hdegoede@redhat.com> wrote:
>> Hi,
>>
>>
>> On 20-03-17 18:51, Liam Breck wrote:
>>>
>>> On Mon, Mar 20, 2017 at 10:04 AM, Hans de Goede <hdegoede@redhat.com>
>>> wrote:
>>>>
>>>> Hi,
>>>>
>>>>
>>>> On 20-03-17 14:54, Hans de Goede wrote:
>>>>>
>>>>>
>>>>> Hi,
>>>>>
>>>>> On 20-03-17 06:27, Sebastian Reichel wrote:
>>>>>>
>>>>>>
>>>>>> Hi,
>>>>>>
>>>>>> On Sun, Mar 19, 2017 at 10:42:00AM +0100, Hans de Goede wrote:
>>>>>
>>>>>
>>>>>
>>>>> <snip>
>>>>>
>>>>>>> We want one driver which is solidly in control of the charger
>>>>>>> since getting that wrong is quite bad and we want to extend
>>>>>>> the information it is exporting to userspace in the form of
>>>>>>> power_supply properties with some extra info.
>>>>>>>
>>>>>>> So taking that as a starting point and generalizing that,
>>>>>>> I think that if we want we can make something more generic then
>>>>>>> my original patch for this. My idea is to introduce something
>>>>>>> called a power_supply_properties_provider, with an API
>>>>>>> like this:
>>>>>>
>>>>>>
>>>>>>
>>>>>> Thanks for thinking about this. From what I can see it should
>>>>>> be enough to just avoid exposing a battery device at all in
>>>>>> the charger driver, though. It does not really provide useful
>>>>>> information anyways.
>>>>>
>>>>>
>>>>>
>>>>> Interesting suggestion, 2 remarks / questions:
>>>>>
>>>>> 1) Given that we do not want to break existing setups
>>>>> which may depend on the existing battery interface on the bq24190
>>>>> driver and add a flag to not register it, or are you suggesting
>>>>> to simply remove it all together? Removing it all together would
>>>>> be better from a maintenance pov. Liam, you indicated that you
>>>>> are the main user of the bq24190 driver currently, do you need
>>>>> the battery power_supply interface for your use case ?
>>>>>
>>>>> 2) Not using the battery interface of the bq24190 driver at all
>>>>> means that the fuelgauge driver needs to grow some extra
>>>>> properties, specifically it will need to start reporting status,
>>>>> something which the bq24190 driver really has a better idea
>>>>> of the the fuel gauge.
>>>
>>>
>>> Our userspace looks at bq24190-battery & -charger. If your userspace
>>> can work with /sys/class/power_supply/whisky_cove-battery/* can't you
>>> leave .bq24190-battery as is?
>>
>>
>> No, my userspace is a generic distro which uses upower, which as I
>> explained before will look at *all* battery type power_supply devices
>> and will consider each of them being a separate battery. There *must*
>> be only one battery type power_supply per physical battery, that is
>> simply how the userspace ABI works.
>>
>>> bq24190-battery's properties could move to -charger, tho health &
>>> online would have to change name, replace same in -charger, or be
>>> dropped.
>>
>>
>> That is one option, I can also simply make the registration dependent
>> on a device-property, then you do not need to change your userspace.
>>
>> In that case I would prefer for the behavior to be to not register
>> the battery power_supply device unless the boolean device(tree)-property
>> named "linux,register-battery-power-supply" is present. But if you
>> need things to keep working the same with older dtb files which
>> will not contain that property, we can also go for:
>> "linux,disable-battery-power-supply"
>
> Just if (!pdata->x) register(battery). Eventually I'll have to move
> those properties to charger, as we added a fuel gauge after charger
> driver was written.

Sebastian want to kill the pdata and move to device-properties as
both you (IIRC) and Andy already suggested. So that is the plan now.

So we will end up with something like:

	if (!device_property_read_bool(dev, "disable-battery-power-supply")) {
		register(battery)...
	}

> Or change bq24190_battery_desc.type to not be _BATTERY?

That sounds like an ugly hack to me, the above will work fine, if you
want to you can move the bits you need to the charger power_supply
(as time permits) and then when they are all gone we can kill of the
battery one.

Regards,

Hans

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH 03/15] extcon: cht-wc: Add Intel Cherry Trail Whiskey Cove PMIC extcon driver
  2017-03-20  1:33   ` Chanwoo Choi
  2017-03-20 13:00     ` Andy Shevchenko
@ 2017-03-20 19:57     ` Hans de Goede
  2017-03-21  5:16       ` Chanwoo Choi
  1 sibling, 1 reply; 90+ messages in thread
From: Hans de Goede @ 2017-03-20 19:57 UTC (permalink / raw)
  To: Chanwoo Choi, Rafael J . Wysocki, Len Brown, Wolfram Sang,
	Andy Shevchenko, Lee Jones, Sebastian Reichel, MyungJoo Ham
  Cc: linux-acpi, Takashi Iwai, linux-i2c, linux-kernel, linux-pm

Hi,

On 20-03-17 02:33, Chanwoo Choi wrote:
> Hi,
>
> On 2017년 03월 17일 18:55, Hans de Goede wrote:
>> Add a driver for charger detection / control on the Intel Cherrytrail
>> Whiskey Cove PMIC.
>>
>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>> ---
>>  drivers/extcon/Kconfig         |   7 +
>>  drivers/extcon/Makefile        |   1 +
>>  drivers/extcon/extcon-cht-wc.c | 356 +++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 364 insertions(+)
>>  create mode 100644 drivers/extcon/extcon-cht-wc.c
>>
>> diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
>> index 96bbae5..4cace6b 100644
>> --- a/drivers/extcon/Kconfig
>> +++ b/drivers/extcon/Kconfig
>> @@ -52,6 +52,13 @@ config EXTCON_INTEL_INT3496
>>  	  This ACPI device is typically found on Intel Baytrail or Cherrytrail
>>  	  based tablets, or other Baytrail / Cherrytrail devices.
>>
>> +config EXTCON_CHT_WC
>
> Need to reorder it alpabetically as the following Makefile.

The idea is to have the items alphabetically listed in "make menuconfig"
and the name of the menu item starts with Intel:

>
>> +	tristate "Intel Cherrytrail Whiskey Cove PMIC extcon driver"
>> +	depends on INTEL_SOC_PMIC_CHTWC
>> +	help
>> +	  Say Y here to enable extcon support for charger detection / control
>> +	  on the Intel Cherrytrail Whiskey Cove PMIC.
>> +
>>  config EXTCON_MAX14577
>>  	tristate "Maxim MAX14577/77836 EXTCON Support"
>>  	depends on MFD_MAX14577
>> diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile
>> index 237ac3f..160f88b 100644
>> --- a/drivers/extcon/Makefile
>> +++ b/drivers/extcon/Makefile
>> @@ -7,6 +7,7 @@ extcon-core-objs		+= extcon.o devres.o
>>  obj-$(CONFIG_EXTCON_ADC_JACK)	+= extcon-adc-jack.o
>>  obj-$(CONFIG_EXTCON_ARIZONA)	+= extcon-arizona.o
>>  obj-$(CONFIG_EXTCON_AXP288)	+= extcon-axp288.o
>> +obj-$(CONFIG_EXTCON_CHT_WC)	+= extcon-cht-wc.o
>>  obj-$(CONFIG_EXTCON_GPIO)	+= extcon-gpio.o
>>  obj-$(CONFIG_EXTCON_INTEL_INT3496) += extcon-intel-int3496.o
>>  obj-$(CONFIG_EXTCON_MAX14577)	+= extcon-max14577.o
>> diff --git a/drivers/extcon/extcon-cht-wc.c b/drivers/extcon/extcon-cht-wc.c
>> new file mode 100644
>> index 0000000..896eee6
>> --- /dev/null
>> +++ b/drivers/extcon/extcon-cht-wc.c
>> @@ -0,0 +1,356 @@
>> +/*
>> + * Extcon charger detection driver for Intel Cherrytrail Whiskey Cove PMIC
>> + * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
>> + *
>> + * Based on various non upstream patches to support the CHT Whiskey Cove PMIC:
>
> Maybe, you don't need to add ':' at the end of line.

Th ':' is there because the following copyright line:
>
>> + * Copyright (C) 2013-2015 Intel Corporation. All rights reserved.

Comes from those various non upstream patches.

>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms and conditions of the GNU General Public License,
>> + * version 2, as published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope it will be useful, but WITHOUT
>> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
>> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
>> + * more details.
>> + */
>> +
>> +#include <linux/extcon.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/kernel.h>
>> +#include <linux/mfd/intel_soc_pmic.h>
>> +#include <linux/module.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/regmap.h>
>> +#include <linux/slab.h>
>> +
>> +#define CHT_WC_PWRSRC_IRQ		0x6e03
>> +#define CHT_WC_PWRSRC_IRQ_MASK		0x6e0f
>> +#define CHT_WC_PWRSRC_STS		0x6e1e
>> +#define CHT_WC_PWRSRC_VBUS		BIT(0)
>> +#define CHT_WC_PWRSRC_DC		BIT(1)
>> +#define CHT_WC_PWRSRC_BAT		BIT(2)
>> +#define CHT_WC_PWRSRC_ID_GND		BIT(3)
>> +#define CHT_WC_PWRSRC_ID_FLOAT		BIT(4)
>> +
>> +#define CHT_WC_PHYCTRL			0x5e07
>> +
>> +#define CHT_WC_CHGRCTRL0		0x5e16
>> +
>> +#define CHT_WC_CHGRCTRL0		0x5e16
>> +#define CHT_WC_CHGRCTRL0_CHGRRESET	BIT(0)
>> +#define CHT_WC_CHGRCTRL0_EMRGCHREN	BIT(1)
>> +#define CHT_WC_CHGRCTRL0_EXTCHRDIS	BIT(2)
>> +#define CHT_WC_CHGRCTRL0_SWCONTROL	BIT(3)
>> +#define CHT_WC_CHGRCTRL0_TTLCK_MASK	BIT(4)
>> +#define CHT_WC_CHGRCTRL0_CCSM_OFF_MASK	BIT(5)
>> +#define CHT_WC_CHGRCTRL0_DBPOFF_MASK	BIT(6)
>> +#define CHT_WC_CHGRCTRL0_WDT_NOKICK	BIT(7)
>> +
>> +#define CHT_WC_CHGRCTRL1		0x5e17
>> +
>> +#define CHT_WC_USBSRC			0x5e29
>> +#define CHT_WC_USBSRC_STS_MASK		GENMASK(1, 0)
>> +#define CHT_WC_USBSRC_STS_SUCCESS	2
>> +#define CHT_WC_USBSRC_STS_FAIL		3
>> +#define CHT_WC_USBSRC_TYPE_SHIFT	2
>> +#define CHT_WC_USBSRC_TYPE_MASK		GENMASK(5, 2)
>> +#define CHT_WC_USBSRC_TYPE_NONE		0
>> +#define CHT_WC_USBSRC_TYPE_SDP		1
>> +#define CHT_WC_USBSRC_TYPE_DCP		2
>> +#define CHT_WC_USBSRC_TYPE_CDP		3
>> +#define CHT_WC_USBSRC_TYPE_ACA		4
>> +#define CHT_WC_USBSRC_TYPE_SE1		5
>> +#define CHT_WC_USBSRC_TYPE_MHL		6
>> +#define CHT_WC_USBSRC_TYPE_FLOAT_DP_DN	7
>> +#define CHT_WC_USBSRC_TYPE_OTHER	8
>> +#define CHT_WC_USBSRC_TYPE_DCP_EXTPHY	9
>> +
>> +enum cht_wc_usb_id {
>> +	USB_ID_OTG,
>> +	USB_ID_GND,
>> +	USB_ID_FLOAT,
>> +	USB_RID_A,
>> +	USB_RID_B,
>> +	USB_RID_C,
>> +};
>> +
>> +/* Strings matching the cht_wc_usb_id enum labels */
>> +static const char * const usb_id_str[] = {
>> +	"otg", "gnd", "float", "rid_a", "rid_b", "rid_c" };
>> +
>> +enum cht_wc_mux_select {
>> +	MUX_SEL_PMIC = 0,
>> +	MUX_SEL_SOC,
>> +};
>> +
>> +static const unsigned int cht_wc_extcon_cables[] = {
>> +	EXTCON_USB,
>> +	EXTCON_USB_HOST,
>> +	EXTCON_CHG_USB_SDP,
>> +	EXTCON_CHG_USB_CDP,
>> +	EXTCON_CHG_USB_DCP,
>> +	EXTCON_NONE,
>> +};
>> +
>> +struct cht_wc_extcon_data {
>> +	struct device *dev;
>> +	struct regmap *regmap;
>> +	struct extcon_dev *edev;
>> +	unsigned int previous_cable;
>> +	int usb_id;
>> +};
>> +
>> +static int cht_wc_extcon_get_id(struct cht_wc_extcon_data *ext, int pwrsrc_sts)
>> +{
>> +	if (ext->usb_id)
>> +		return ext->usb_id;
>> +
>> +	if (pwrsrc_sts & CHT_WC_PWRSRC_ID_GND)
>> +		return USB_ID_GND;
>> +	if (pwrsrc_sts & CHT_WC_PWRSRC_ID_FLOAT)
>> +		return USB_ID_FLOAT;
>> +
>> +	/*
>> +	 * Once we have iio support for the gpadc we should read the USBID
>> +	 * gpadc channel here and determine ACA role based on that.
>> +	 */
>> +	return USB_ID_FLOAT;
>> +}
>> +
>> +static int cht_wc_extcon_get_charger(struct cht_wc_extcon_data *ext)
>> +{
>> +	int ret, usbsrc, status, retries = 5;
>
> You have to define the constant for '5' because the name of constant
> definition indicates what is meaning. So, maybe you will use the 'for' loope
> instead of 'do..while'.

Right, already fixed as a result of Andy's review.

>
>> +
>> +	do {
>> +		ret = regmap_read(ext->regmap, CHT_WC_USBSRC, &usbsrc);
>> +		if (ret) {
>> +			dev_err(ext->dev, "Error reading usbsrc: %d\n", ret);
>> +			return ret;
>> +		}
>
> Need to add one blank line.
>
>> +		status = usbsrc & CHT_WC_USBSRC_STS_MASK;
>> +		if (status == CHT_WC_USBSRC_STS_SUCCESS ||
>> +		    status == CHT_WC_USBSRC_STS_FAIL)
>> +			break;
>> +
>> +		msleep(200);
>
> You have to define the constant for '200' because the name of constant
> definition indicates what is meaning.
>
>> +	} while (retries--);
>> +
>> +	if (status != CHT_WC_USBSRC_STS_SUCCESS) {
>> +		if (status == CHT_WC_USBSRC_STS_FAIL)
>> +			dev_warn(ext->dev, "Could not detect charger type\n");
>> +		else
>> +			dev_warn(ext->dev, "Timeout detecting charger type\n");
>> +		return EXTCON_CHG_USB_SDP; /* Save fallback */
>> +	}
>> +
>> +	ret = (usbsrc & CHT_WC_USBSRC_TYPE_MASK) >> CHT_WC_USBSRC_TYPE_SHIFT;
>
> 'ret' is not proper indicates the meaning of 'CHT_WC_USBSRC_TYPE'.
> You have to use the more correct local variable such as 'usbsrc_type'.

Fixed for v2.
>
>> +	switch (ret) {
>> +	default:
>> +		dev_warn(ext->dev, "Unhandled charger type %d\n", ret);
>> +		/* Fall through treat as SDP */
>
> Is it right? Why do you located the 'default' on the top in the switch?

So that I can use fall-through, there is no rule in C where the default goes.

The fallthrough is there because assuming SDP (and thus max 500mA current
draw) is always safe.

>
>> +	case CHT_WC_USBSRC_TYPE_SDP:
>> +	case CHT_WC_USBSRC_TYPE_FLOAT_DP_DN:
>> +	case CHT_WC_USBSRC_TYPE_OTHER:
>> +		return EXTCON_CHG_USB_SDP;
>> +	case CHT_WC_USBSRC_TYPE_CDP:
>> +		return EXTCON_CHG_USB_CDP;
>> +	case CHT_WC_USBSRC_TYPE_DCP:
>> +	case CHT_WC_USBSRC_TYPE_DCP_EXTPHY:
>> +	case CHT_WC_USBSRC_TYPE_MHL: /* MHL2+ delivers upto 2A, treat as DCP */
>> +		return EXTCON_CHG_USB_DCP;
>> +	case CHT_WC_USBSRC_TYPE_ACA:
>> +		return EXTCON_CHG_USB_ACA;
>> +	}
>> +}
>> +
>> +static void cht_wc_extcon_set_phymux(struct cht_wc_extcon_data *ext, u8 state)
>> +{
>> +	int ret;
>> +
>> +	ret = regmap_write(ext->regmap, CHT_WC_PHYCTRL, state);
>> +	if (ret)
>> +		dev_err(ext->dev, "Error writing phyctrl: %d\n", ret);
>
> This function is only called in the cht_wc_extcon_det_event().
> Also, this funciton write only one register. It is too short.
> So, you don't need to add the separate function.
> You better to include this code in the cht_wc_extcon_det_event().

This is used multiple times in cht_wc_extcon_det_event() and is
also used in probe() so it saves having to copy and paste the error
check. Also the flow of cht_wc_extcon_det_event() is more readable
this way. If it is more efficient to have this inline the compiler
will auto-inline it.


>
>> +}
>> +
>> +static void cht_wc_extcon_det_event(struct cht_wc_extcon_data *ext)
>> +{
>> +	int ret, pwrsrc_sts, id;
>> +	unsigned int cable = EXTCON_NONE;
>> +
>> +	ret = regmap_read(ext->regmap, CHT_WC_PWRSRC_STS, &pwrsrc_sts);
>> +	if (ret) {
>> +		dev_err(ext->dev, "Error reading pwrsrc status: %d\n", ret);
>> +		return;
>> +	}
>> +
>> +	id = cht_wc_extcon_get_id(ext, pwrsrc_sts);
>> +	if (id == USB_ID_GND) {
>> +		/* The 5v boost causes a false VBUS / SDP detect, skip */
>> +		goto charger_det_done;
>> +	}
>> +
>> +	/* Plugged into a host/charger or not connected? */
>> +	if (!(pwrsrc_sts & CHT_WC_PWRSRC_VBUS)) {
>> +		/* Route D+ and D- to PMIC for future charger detection */
>> +		cht_wc_extcon_set_phymux(ext, MUX_SEL_PMIC);
>> +		goto set_state;
>> +	}
>
> The cht_wc_extcon_get_id() and cht_wc_extcon_det_event() use the value
> of CHT_WC_PWRSRC_STS register. So, I think you better to gather the
> code related to the CHT_WC_PWRSRC_STS for readability.
> - First suggestion, remove the separate the cht_wc_extcon_get_id()
> - Second suggestion, The code from regmap_read() to "!(pwrsrc_sts & CHT_WC_PWRSRC_VBUS)"
>           move into the cht_wc_extcon_get_id().
>
> In my opinion, I recommend that second way.

These register reads are i2c register reads which are quite costly,
so we really want to do this only once, which is why the code is
as it is.

>> +
>> +	ret = cht_wc_extcon_get_charger(ext);
>> +	if (ret >= 0)
>> +		cable = ret;
>> +
>> +charger_det_done:
>> +	/* Route D+ and D- to SoC for the host / gadget controller */
>
> Minor comment.
> You better to use '&' instead of '/'

The data lines get used by either the host OR the gadget controller,
as there is another mux inside the SoC.

>
>> +	cht_wc_extcon_set_phymux(ext, MUX_SEL_SOC);
>> +
>> +set_state:
>> +	extcon_set_state_sync(ext->edev, cable, true);
>> +	extcon_set_state_sync(ext->edev, ext->previous_cable, false);
>> +	extcon_set_state_sync(ext->edev, EXTCON_USB_HOST,
>> +			      id == USB_ID_GND || id == USB_RID_A);
>> +	ext->previous_cable = cable;
>> +}
>> +
>> +static irqreturn_t cht_wc_extcon_isr(int irq, void *data)
>> +{
>> +	struct cht_wc_extcon_data *ext = data;
>> +	int ret, irqs;
>> +
>> +	ret = regmap_read(ext->regmap, CHT_WC_PWRSRC_IRQ, &irqs);
>> +	if (ret)
>> +		dev_err(ext->dev, "Error reading irqs: %d\n", ret);
>> +
>> +	cht_wc_extcon_det_event(ext);
>> +
>> +	ret = regmap_write(ext->regmap, CHT_WC_PWRSRC_IRQ, irqs);
>> +	if (ret)
>> +		dev_err(ext->dev, "Error writing irqs: %d\n", ret);
>> +
>> +	return IRQ_HANDLED;
>> +}
>> +
>> +/* usb_id sysfs attribute for debug / testing purposes */
>> +static ssize_t usb_id_show(struct device *dev, struct device_attribute *attr,
>> +			   char *buf)
>> +{
>> +	struct cht_wc_extcon_data *ext = dev_get_drvdata(dev);
>> +
>> +	return sprintf(buf, "%s\n", usb_id_str[ext->usb_id]);
>> +}
>> +
>> +static ssize_t usb_id_store(struct device *dev, struct device_attribute *attr,
>> +			    const char *buf, size_t n)
>> +{
>> +	struct cht_wc_extcon_data *ext = dev_get_drvdata(dev);
>> +	int i;
>> +
>> +	for (i = 0; i < ARRAY_SIZE(usb_id_str); i++) {
>> +		if (sysfs_streq(buf, usb_id_str[i])) {
>> +			dev_info(ext->dev, "New usb_id %s\n", usb_id_str[i]);
>> +			ext->usb_id = i;
>> +			cht_wc_extcon_det_event(ext);
>> +			return n;
>> +		}
>> +	}
>> +
>> +	return -EINVAL;
>> +}
>> +
>> +static DEVICE_ATTR(usb_id, 0644, usb_id_show, usb_id_store);
>
> I think it is not good to add specific sysfs for only this device driver.
> The sysfs entry of framework must include the only common and standard interfarce
> for all extcon device drivers. Because the sysfs entry affects the ABI interface.
>
> So, It is not proper.

Unfortunately these kinda sysfs files are somewhat normal when
dealing with USB-OTG. For example my board does not have the
id-pin hooked up to the connector, so to test host mode
I need to echo "gnd" to the sysfs attr. But also if I actually
want to use host-mode (or anyone else with the same or a similar
board).

See for example also the "mode" sysfs attribute of the musb driver.

Since the id-pin setting influences multiple other drivers through
extcon the best place for this is in the extcon driver, as that
it the canonical source of the EXTCON_USB_HOST cable value.


>
>> +
>> +static int cht_wc_extcon_probe(struct platform_device *pdev)
>> +{
>> +	struct cht_wc_extcon_data *ext;
>> +	struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
>> +	int irq, ret;
>> +
>> +	irq = platform_get_irq(pdev, 0);
>> +	if (irq < 0)
>> +		return irq;
>> +
>> +	ext = devm_kzalloc(&pdev->dev, sizeof(*ext), GFP_KERNEL);
>> +	if (!ext)
>> +		return -ENOMEM;
>> +
>> +	ext->dev = &pdev->dev;
>> +	ext->regmap = pmic->regmap;
>> +	ext->previous_cable = EXTCON_NONE;
>> +
>> +	/* Initialize extcon device */
>> +	ext->edev = devm_extcon_dev_allocate(ext->dev, cht_wc_extcon_cables);
>> +	if (IS_ERR(ext->edev))
>> +		return PTR_ERR(ext->edev);
>> +
>> +	ret = regmap_update_bits(ext->regmap, CHT_WC_CHGRCTRL0,
>> +		 CHT_WC_CHGRCTRL0_SWCONTROL | CHT_WC_CHGRCTRL0_CCSM_OFF_MASK,
>> +		 CHT_WC_CHGRCTRL0_SWCONTROL | CHT_WC_CHGRCTRL0_CCSM_OFF_MASK);
>> +	if (ret) {
>> +		dev_err(ext->dev, "Error enabling sw control\n");
>> +		return ret;
>> +	}
>> +
>> +	/* Register extcon device */
>> +	ret = devm_extcon_dev_register(ext->dev, ext->edev);
>> +	if (ret) {
>> +		dev_err(ext->dev, "Failed to register extcon device\n");
>> +		return ret;
>> +	}
>> +
>> +	/* Route D+ and D- to PMIC for initial charger detection */
>> +	cht_wc_extcon_set_phymux(ext, MUX_SEL_PMIC);
>> +
>> +	/* Get initial state */
>> +	cht_wc_extcon_det_event(ext);
>> +
>> +	ret = devm_request_threaded_irq(ext->dev, irq, NULL, cht_wc_extcon_isr,
>> +					IRQF_ONESHOT, pdev->name, ext);
>> +	if (ret) {
>> +		dev_err(ext->dev, "Failed to request interrupt\n");
>> +		return ret;
>> +	}
>> +
>> +	/* Unmask irqs */
>> +	ret = regmap_write(ext->regmap, CHT_WC_PWRSRC_IRQ_MASK,
>> +			   (int)~(CHT_WC_PWRSRC_VBUS | CHT_WC_PWRSRC_ID_GND |
>> +				  CHT_WC_PWRSRC_ID_FLOAT));
>> +	if (ret) {
>> +		dev_err(ext->dev, "Error writing irq-mask: %d\n", ret);
>
> I prefer to use the consistent error log. In the probe function,
> you use the 'Failed to ...' when error hanppen. So, You better
> to use the consistent format for errr log as following:
> 	- "Failed to write the irq-mask: %d\n", ret);

Fixed for v2.

>
> I think it improve the readability of your device driver.
>
>> +		return ret;
>> +	}
>> +
>> +	platform_set_drvdata(pdev, ext);
>> +	device_create_file(ext->dev, &dev_attr_usb_id);
>> +
>> +	return 0;
>
>
> In the probe function, you touch the some register for initialization.
> But, if error happen, the probe function don't restore the register value.
> Is it ok? I think you need to handle the error case.

Fixed for v2.

>
>> +}
>> +
>> +static int cht_wc_extcon_remove(struct platform_device *pdev)
>> +{
>> +	struct cht_wc_extcon_data *ext = platform_get_drvdata(pdev);
>> +
>> +	device_remove_file(ext->dev, &dev_attr_usb_id);
>
> Don't need it.
>
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct platform_device_id cht_wc_extcon_table[] = {
>> +	{ .name = "cht_wcove_pwrsrc" },
>
> You use the 'cht_wc' word instead of 'cht_wcove_pwrsrc'.
> So, To maintain the consistency, you better to use the 'cht-wc' as the name.
> - I prefer to use '-' instead of '_' in the name.
> 	.name ="cht-wc"

Already answered by Andy.

>> +	{},
>> +};
>> +MODULE_DEVICE_TABLE(platform, cht_wc_extcon_table);
>> +
>> +static struct platform_driver cht_wc_extcon_driver = {
>> +	.probe = cht_wc_extcon_probe,
>> +	.remove = cht_wc_extcon_remove,
>> +	.id_table = cht_wc_extcon_table,
>> +	.driver = {
>> +		.name = "cht_wcove_pwrsrc",
>> +	},
>> +};
>> +module_platform_driver(cht_wc_extcon_driver);
>> +
>> +MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
>> +MODULE_DESCRIPTION("Intel Cherrytrail Whiskey Cove PMIC extcon driver");
>
> Minor comment.
> You better to locate the MODULE_DESCRIPTION at the first line
> and then MODULE_AUTHOR is at second line.

Fixed for v2.

Regards,

Hans

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [04/15] power: supply: bq24190_charger: Add no_register_reset pdata flag
  2017-03-20 19:22                             ` Hans de Goede
@ 2017-03-20 21:14                               ` Sebastian Reichel
  2017-03-20 21:34                                 ` Liam Breck
  2017-03-20 22:01                                 ` Hans de Goede
  2017-03-20 21:15                               ` Liam Breck
  1 sibling, 2 replies; 90+ messages in thread
From: Sebastian Reichel @ 2017-03-20 21:14 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Liam Breck, Andy Shevchenko, Tony Lindgren, linux-pm, Liam Breck

[-- Attachment #1: Type: text/plain, Size: 5577 bytes --]

On Mon, Mar 20, 2017 at 08:22:55PM +0100, Hans de Goede wrote:
> Hi,
> 
> On 20-03-17 19:19, Liam Breck wrote:
> > On Mon, Mar 20, 2017 at 11:01 AM, Hans de Goede <hdegoede@redhat.com> wrote:
> > > Hi,
> > > 
> > > 
> > > On 20-03-17 18:51, Liam Breck wrote:
> > > > 
> > > > On Mon, Mar 20, 2017 at 10:04 AM, Hans de Goede <hdegoede@redhat.com>
> > > > wrote:
> > > > > 
> > > > > Hi,
> > > > > 
> > > > > 
> > > > > On 20-03-17 14:54, Hans de Goede wrote:
> > > > > > 
> > > > > > 
> > > > > > Hi,
> > > > > > 
> > > > > > On 20-03-17 06:27, Sebastian Reichel wrote:
> > > > > > > 
> > > > > > > 
> > > > > > > Hi,
> > > > > > > 
> > > > > > > On Sun, Mar 19, 2017 at 10:42:00AM +0100, Hans de Goede wrote:
> > > > > > 
> > > > > > 
> > > > > > 
> > > > > > <snip>
> > > > > > 
> > > > > > > > We want one driver which is solidly in control of the charger
> > > > > > > > since getting that wrong is quite bad and we want to extend
> > > > > > > > the information it is exporting to userspace in the form of
> > > > > > > > power_supply properties with some extra info.
> > > > > > > > 
> > > > > > > > So taking that as a starting point and generalizing that,
> > > > > > > > I think that if we want we can make something more generic then
> > > > > > > > my original patch for this. My idea is to introduce something
> > > > > > > > called a power_supply_properties_provider, with an API
> > > > > > > > like this:
> > > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > Thanks for thinking about this. From what I can see it should
> > > > > > > be enough to just avoid exposing a battery device at all in
> > > > > > > the charger driver, though. It does not really provide useful
> > > > > > > information anyways.
> > > > > > 
> > > > > > 
> > > > > > 
> > > > > > Interesting suggestion, 2 remarks / questions:
> > > > > > 
> > > > > > 1) Given that we do not want to break existing setups
> > > > > > which may depend on the existing battery interface on the bq24190
> > > > > > driver and add a flag to not register it, or are you suggesting
> > > > > > to simply remove it all together? Removing it all together would
> > > > > > be better from a maintenance pov. Liam, you indicated that you
> > > > > > are the main user of the bq24190 driver currently, do you need
> > > > > > the battery power_supply interface for your use case ?
> > > > > > 
> > > > > > 2) Not using the battery interface of the bq24190 driver at all
> > > > > > means that the fuelgauge driver needs to grow some extra
> > > > > > properties, specifically it will need to start reporting status,
> > > > > > something which the bq24190 driver really has a better idea
> > > > > > of the the fuel gauge.
> > > > 
> > > > 
> > > > Our userspace looks at bq24190-battery & -charger. If your userspace
> > > > can work with /sys/class/power_supply/whisky_cove-battery/* can't you
> > > > leave .bq24190-battery as is?
> > > 
> > > 
> > > No, my userspace is a generic distro which uses upower, which as I
> > > explained before will look at *all* battery type power_supply devices
> > > and will consider each of them being a separate battery. There *must*
> > > be only one battery type power_supply per physical battery, that is
> > > simply how the userspace ABI works.
> > > 
> > > > bq24190-battery's properties could move to -charger, tho health &
> > > > online would have to change name, replace same in -charger, or be
> > > > dropped.
> > > 
> > > 
> > > That is one option, I can also simply make the registration dependent
> > > on a device-property, then you do not need to change your userspace.
> > > 
> > > In that case I would prefer for the behavior to be to not register
> > > the battery power_supply device unless the boolean device(tree)-property
> > > named "linux,register-battery-power-supply" is present. But if you
> > > need things to keep working the same with older dtb files which
> > > will not contain that property, we can also go for:
> > > "linux,disable-battery-power-supply"
> > 
> > Just if (!pdata->x) register(battery). Eventually I'll have to move
> > those properties to charger, as we added a fuel gauge after charger
> > driver was written.
> 
> Sebastian want to kill the pdata and move to device-properties as
> both you (IIRC) and Andy already suggested. So that is the plan now.
> 
> So we will end up with something like:
> 
> 	if (!device_property_read_bool(dev, "disable-battery-power-supply")) {
> 		register(battery)...
> 	}
> 
> > Or change bq24190_battery_desc.type to not be _BATTERY?
> 
> That sounds like an ugly hack to me, the above will work fine, if you
> want to you can move the bits you need to the charger power_supply
> (as time permits) and then when they are all gone we can kill of the
> battery one.

From my understanding Liam's platform uses bq27xxx based fuel-gauge,
so it also should not provide the bq24190-battery (since that would
result in two battery devices being exposed for the same battery).
So removing it seems to be the way to go.

Most of the properties should also be available from the fuel-gauge.
I see two exceptions:

 * The battery disable FET
 * The battery temperature monitoring

If that is needed by any of your platforms, something like the
API proposed by Hans to get properties from bq24190 into the
fuel-gauge driver should be introduced. According to my
understanding bq24190 checks temperature itself, so both
features seem to be optional.

-- Sebastian

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [04/15] power: supply: bq24190_charger: Add no_register_reset pdata flag
  2017-03-20 19:22                             ` Hans de Goede
  2017-03-20 21:14                               ` Sebastian Reichel
@ 2017-03-20 21:15                               ` Liam Breck
  1 sibling, 0 replies; 90+ messages in thread
From: Liam Breck @ 2017-03-20 21:15 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Sebastian Reichel, Andy Shevchenko, Tony Lindgren, linux-pm, Liam Breck

On Mon, Mar 20, 2017 at 12:22 PM, Hans de Goede <hdegoede@redhat.com> wrote:
> Hi,
>
>
> On 20-03-17 19:19, Liam Breck wrote:
>>
>> On Mon, Mar 20, 2017 at 11:01 AM, Hans de Goede <hdegoede@redhat.com>
>> wrote:
>>>
>>> Hi,
>>>
>>>
>>> On 20-03-17 18:51, Liam Breck wrote:
>>>>
>>>>
>>>> On Mon, Mar 20, 2017 at 10:04 AM, Hans de Goede <hdegoede@redhat.com>
>>>> wrote:
>>>>>
>>>>>
>>>>> Hi,
>>>>>
>>>>>
>>>>> On 20-03-17 14:54, Hans de Goede wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>> Hi,
>>>>>>
>>>>>> On 20-03-17 06:27, Sebastian Reichel wrote:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> Hi,
>>>>>>>
>>>>>>> On Sun, Mar 19, 2017 at 10:42:00AM +0100, Hans de Goede wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> <snip>
>>>>>>
>>>>>>>> We want one driver which is solidly in control of the charger
>>>>>>>> since getting that wrong is quite bad and we want to extend
>>>>>>>> the information it is exporting to userspace in the form of
>>>>>>>> power_supply properties with some extra info.
>>>>>>>>
>>>>>>>> So taking that as a starting point and generalizing that,
>>>>>>>> I think that if we want we can make something more generic then
>>>>>>>> my original patch for this. My idea is to introduce something
>>>>>>>> called a power_supply_properties_provider, with an API
>>>>>>>> like this:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> Thanks for thinking about this. From what I can see it should
>>>>>>> be enough to just avoid exposing a battery device at all in
>>>>>>> the charger driver, though. It does not really provide useful
>>>>>>> information anyways.
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> Interesting suggestion, 2 remarks / questions:
>>>>>>
>>>>>> 1) Given that we do not want to break existing setups
>>>>>> which may depend on the existing battery interface on the bq24190
>>>>>> driver and add a flag to not register it, or are you suggesting
>>>>>> to simply remove it all together? Removing it all together would
>>>>>> be better from a maintenance pov. Liam, you indicated that you
>>>>>> are the main user of the bq24190 driver currently, do you need
>>>>>> the battery power_supply interface for your use case ?
>>>>>>
>>>>>> 2) Not using the battery interface of the bq24190 driver at all
>>>>>> means that the fuelgauge driver needs to grow some extra
>>>>>> properties, specifically it will need to start reporting status,
>>>>>> something which the bq24190 driver really has a better idea
>>>>>> of the the fuel gauge.
>>>>
>>>>
>>>>
>>>> Our userspace looks at bq24190-battery & -charger. If your userspace
>>>> can work with /sys/class/power_supply/whisky_cove-battery/* can't you
>>>> leave .bq24190-battery as is?
>>>
>>>
>>>
>>> No, my userspace is a generic distro which uses upower, which as I
>>> explained before will look at *all* battery type power_supply devices
>>> and will consider each of them being a separate battery. There *must*
>>> be only one battery type power_supply per physical battery, that is
>>> simply how the userspace ABI works.
>>>
>>>> bq24190-battery's properties could move to -charger, tho health &
>>>> online would have to change name, replace same in -charger, or be
>>>> dropped.
>>>
>>>
>>>
>>> That is one option, I can also simply make the registration dependent
>>> on a device-property, then you do not need to change your userspace.
>>>
>>> In that case I would prefer for the behavior to be to not register
>>> the battery power_supply device unless the boolean device(tree)-property
>>> named "linux,register-battery-power-supply" is present. But if you
>>> need things to keep working the same with older dtb files which
>>> will not contain that property, we can also go for:
>>> "linux,disable-battery-power-supply"
>>
>>
>> Just if (!pdata->x) register(battery). Eventually I'll have to move
>> those properties to charger, as we added a fuel gauge after charger
>> driver was written.
>
>
> Sebastian want to kill the pdata and move to device-properties as
> both you (IIRC) and Andy already suggested. So that is the plan now.

Being able to set the same properties via DT is ideal. If there are
common acpi terms for any of the properties, let's use them.

BTW have you considered adding any acpi features for this board? Or
would your userspace not recognize them?

> So we will end up with something like:
>
>         if (!device_property_read_bool(dev, "disable-battery-power-supply"))

"hide-battery..." might be more accurate

> {
>                 register(battery)...
>         }
>
>> Or change bq24190_battery_desc.type to not be _BATTERY?
>
>
> That sounds like an ugly hack to me, the above will work fine, if you
> want to you can move the bits you need to the charger power_supply
> (as time permits) and then when they are all gone we can kill of the
> battery one.

It would be temporary, and prevent the -battery -> -charger transition
from making a device_property obsolete. Scaffolding hacks are useful.

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [04/15] power: supply: bq24190_charger: Add no_register_reset pdata flag
  2017-03-20 21:14                               ` Sebastian Reichel
@ 2017-03-20 21:34                                 ` Liam Breck
  2017-03-20 22:01                                 ` Hans de Goede
  1 sibling, 0 replies; 90+ messages in thread
From: Liam Breck @ 2017-03-20 21:34 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: Hans de Goede, Andy Shevchenko, Tony Lindgren, linux-pm, Liam Breck

On Mon, Mar 20, 2017 at 2:14 PM, Sebastian Reichel <sre@kernel.org> wrote:
> On Mon, Mar 20, 2017 at 08:22:55PM +0100, Hans de Goede wrote:
>> Hi,
>>
>> On 20-03-17 19:19, Liam Breck wrote:
>> > On Mon, Mar 20, 2017 at 11:01 AM, Hans de Goede <hdegoede@redhat.com> wrote:
>> > > Hi,
>> > >
>> > >
>> > > On 20-03-17 18:51, Liam Breck wrote:
>> > > >
>> > > > On Mon, Mar 20, 2017 at 10:04 AM, Hans de Goede <hdegoede@redhat.com>
>> > > > wrote:
>> > > > >
>> > > > > Hi,
>> > > > >
>> > > > >
>> > > > > On 20-03-17 14:54, Hans de Goede wrote:
>> > > > > >
>> > > > > >
>> > > > > > Hi,
>> > > > > >
>> > > > > > On 20-03-17 06:27, Sebastian Reichel wrote:
>> > > > > > >
>> > > > > > >
>> > > > > > > Hi,
>> > > > > > >
>> > > > > > > On Sun, Mar 19, 2017 at 10:42:00AM +0100, Hans de Goede wrote:
>> > > > > >
>> > > > > >
>> > > > > >
>> > > > > > <snip>
>> > > > > >
>> > > > > > > > We want one driver which is solidly in control of the charger
>> > > > > > > > since getting that wrong is quite bad and we want to extend
>> > > > > > > > the information it is exporting to userspace in the form of
>> > > > > > > > power_supply properties with some extra info.
>> > > > > > > >
>> > > > > > > > So taking that as a starting point and generalizing that,
>> > > > > > > > I think that if we want we can make something more generic then
>> > > > > > > > my original patch for this. My idea is to introduce something
>> > > > > > > > called a power_supply_properties_provider, with an API
>> > > > > > > > like this:
>> > > > > > >
>> > > > > > >
>> > > > > > >
>> > > > > > > Thanks for thinking about this. From what I can see it should
>> > > > > > > be enough to just avoid exposing a battery device at all in
>> > > > > > > the charger driver, though. It does not really provide useful
>> > > > > > > information anyways.
>> > > > > >
>> > > > > >
>> > > > > >
>> > > > > > Interesting suggestion, 2 remarks / questions:
>> > > > > >
>> > > > > > 1) Given that we do not want to break existing setups
>> > > > > > which may depend on the existing battery interface on the bq24190
>> > > > > > driver and add a flag to not register it, or are you suggesting
>> > > > > > to simply remove it all together? Removing it all together would
>> > > > > > be better from a maintenance pov. Liam, you indicated that you
>> > > > > > are the main user of the bq24190 driver currently, do you need
>> > > > > > the battery power_supply interface for your use case ?
>> > > > > >
>> > > > > > 2) Not using the battery interface of the bq24190 driver at all
>> > > > > > means that the fuelgauge driver needs to grow some extra
>> > > > > > properties, specifically it will need to start reporting status,
>> > > > > > something which the bq24190 driver really has a better idea
>> > > > > > of the the fuel gauge.
>> > > >
>> > > >
>> > > > Our userspace looks at bq24190-battery & -charger. If your userspace
>> > > > can work with /sys/class/power_supply/whisky_cove-battery/* can't you
>> > > > leave .bq24190-battery as is?
>> > >
>> > >
>> > > No, my userspace is a generic distro which uses upower, which as I
>> > > explained before will look at *all* battery type power_supply devices
>> > > and will consider each of them being a separate battery. There *must*
>> > > be only one battery type power_supply per physical battery, that is
>> > > simply how the userspace ABI works.
>> > >
>> > > > bq24190-battery's properties could move to -charger, tho health &
>> > > > online would have to change name, replace same in -charger, or be
>> > > > dropped.
>> > >
>> > >
>> > > That is one option, I can also simply make the registration dependent
>> > > on a device-property, then you do not need to change your userspace.
>> > >
>> > > In that case I would prefer for the behavior to be to not register
>> > > the battery power_supply device unless the boolean device(tree)-property
>> > > named "linux,register-battery-power-supply" is present. But if you
>> > > need things to keep working the same with older dtb files which
>> > > will not contain that property, we can also go for:
>> > > "linux,disable-battery-power-supply"
>> >
>> > Just if (!pdata->x) register(battery). Eventually I'll have to move
>> > those properties to charger, as we added a fuel gauge after charger
>> > driver was written.
>>
>> Sebastian want to kill the pdata and move to device-properties as
>> both you (IIRC) and Andy already suggested. So that is the plan now.
>>
>> So we will end up with something like:
>>
>>       if (!device_property_read_bool(dev, "disable-battery-power-supply")) {
>>               register(battery)...
>>       }
>>
>> > Or change bq24190_battery_desc.type to not be _BATTERY?
>>
>> That sounds like an ugly hack to me, the above will work fine, if you
>> want to you can move the bits you need to the charger power_supply
>> (as time permits) and then when they are all gone we can kill of the
>> battery one.
>
> From my understanding Liam's platform uses bq27xxx based fuel-gauge,
> so it also should not provide the bq24190-battery (since that would
> result in two battery devices being exposed for the same battery).
> So removing it seems to be the way to go.

Ya, let him hack battery_desc.type as a short-term workaround, and
I'll move the -battery properties to -charger in the patchset I'm
working on.

> Most of the properties should also be available from the fuel-gauge.
> I see two exceptions:
>
>  * The battery disable FET
>  * The battery temperature monitoring

I can just surface these in -charger. Is that a sin?

> If that is needed by any of your platforms, something like the
> API proposed by Hans to get properties from bq24190 into the
> fuel-gauge driver should be introduced. According to my
> understanding bq24190 checks temperature itself, so both
> features seem to be optional.

It sounds to me like the kernel needs a registry for all properties
associated with a certain power source, which forwards get/set
requests to the relevant driver method. That would also let userspace
extend a power source beyond what drivers provide.

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [04/15] power: supply: bq24190_charger: Add no_register_reset pdata flag
  2017-03-20 21:14                               ` Sebastian Reichel
  2017-03-20 21:34                                 ` Liam Breck
@ 2017-03-20 22:01                                 ` Hans de Goede
  1 sibling, 0 replies; 90+ messages in thread
From: Hans de Goede @ 2017-03-20 22:01 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: Liam Breck, Andy Shevchenko, Tony Lindgren, linux-pm, Liam Breck

Hi,

On 20-03-17 22:14, Sebastian Reichel wrote:
> On Mon, Mar 20, 2017 at 08:22:55PM +0100, Hans de Goede wrote:
>> Hi,
>>
>> On 20-03-17 19:19, Liam Breck wrote:
>>> On Mon, Mar 20, 2017 at 11:01 AM, Hans de Goede <hdegoede@redhat.com> wrote:
>>>> Hi,
>>>>
>>>>
>>>> On 20-03-17 18:51, Liam Breck wrote:
>>>>>
>>>>> On Mon, Mar 20, 2017 at 10:04 AM, Hans de Goede <hdegoede@redhat.com>
>>>>> wrote:
>>>>>>
>>>>>> Hi,
>>>>>>
>>>>>>
>>>>>> On 20-03-17 14:54, Hans de Goede wrote:
>>>>>>>
>>>>>>>
>>>>>>> Hi,
>>>>>>>
>>>>>>> On 20-03-17 06:27, Sebastian Reichel wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> On Sun, Mar 19, 2017 at 10:42:00AM +0100, Hans de Goede wrote:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> <snip>
>>>>>>>
>>>>>>>>> We want one driver which is solidly in control of the charger
>>>>>>>>> since getting that wrong is quite bad and we want to extend
>>>>>>>>> the information it is exporting to userspace in the form of
>>>>>>>>> power_supply properties with some extra info.
>>>>>>>>>
>>>>>>>>> So taking that as a starting point and generalizing that,
>>>>>>>>> I think that if we want we can make something more generic then
>>>>>>>>> my original patch for this. My idea is to introduce something
>>>>>>>>> called a power_supply_properties_provider, with an API
>>>>>>>>> like this:
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> Thanks for thinking about this. From what I can see it should
>>>>>>>> be enough to just avoid exposing a battery device at all in
>>>>>>>> the charger driver, though. It does not really provide useful
>>>>>>>> information anyways.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> Interesting suggestion, 2 remarks / questions:
>>>>>>>
>>>>>>> 1) Given that we do not want to break existing setups
>>>>>>> which may depend on the existing battery interface on the bq24190
>>>>>>> driver and add a flag to not register it, or are you suggesting
>>>>>>> to simply remove it all together? Removing it all together would
>>>>>>> be better from a maintenance pov. Liam, you indicated that you
>>>>>>> are the main user of the bq24190 driver currently, do you need
>>>>>>> the battery power_supply interface for your use case ?
>>>>>>>
>>>>>>> 2) Not using the battery interface of the bq24190 driver at all
>>>>>>> means that the fuelgauge driver needs to grow some extra
>>>>>>> properties, specifically it will need to start reporting status,
>>>>>>> something which the bq24190 driver really has a better idea
>>>>>>> of the the fuel gauge.
>>>>>
>>>>>
>>>>> Our userspace looks at bq24190-battery & -charger. If your userspace
>>>>> can work with /sys/class/power_supply/whisky_cove-battery/* can't you
>>>>> leave .bq24190-battery as is?
>>>>
>>>>
>>>> No, my userspace is a generic distro which uses upower, which as I
>>>> explained before will look at *all* battery type power_supply devices
>>>> and will consider each of them being a separate battery. There *must*
>>>> be only one battery type power_supply per physical battery, that is
>>>> simply how the userspace ABI works.
>>>>
>>>>> bq24190-battery's properties could move to -charger, tho health &
>>>>> online would have to change name, replace same in -charger, or be
>>>>> dropped.
>>>>
>>>>
>>>> That is one option, I can also simply make the registration dependent
>>>> on a device-property, then you do not need to change your userspace.
>>>>
>>>> In that case I would prefer for the behavior to be to not register
>>>> the battery power_supply device unless the boolean device(tree)-property
>>>> named "linux,register-battery-power-supply" is present. But if you
>>>> need things to keep working the same with older dtb files which
>>>> will not contain that property, we can also go for:
>>>> "linux,disable-battery-power-supply"
>>>
>>> Just if (!pdata->x) register(battery). Eventually I'll have to move
>>> those properties to charger, as we added a fuel gauge after charger
>>> driver was written.
>>
>> Sebastian want to kill the pdata and move to device-properties as
>> both you (IIRC) and Andy already suggested. So that is the plan now.
>>
>> So we will end up with something like:
>>
>> 	if (!device_property_read_bool(dev, "disable-battery-power-supply")) {
>> 		register(battery)...
>> 	}
>>
>>> Or change bq24190_battery_desc.type to not be _BATTERY?
>>
>> That sounds like an ugly hack to me, the above will work fine, if you
>> want to you can move the bits you need to the charger power_supply
>> (as time permits) and then when they are all gone we can kill of the
>> battery one.
>
> From my understanding Liam's platform uses bq27xxx based fuel-gauge,
> so it also should not provide the bq24190-battery (since that would
> result in two battery devices being exposed for the same battery).
> So removing it seems to be the way to go.

Ok, so for v2 of my series I will just remove it and then we can see
from there, we probably need to do some repair work on top to not
break stuff for Liam, but I agree that just removing it seems best.

Regards,

Hans

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH 10/15] power: supply: bq24190_charger: Use extcon to determine ilimit, 5v boost
  2017-03-17 17:33   ` Andy Shevchenko
@ 2017-03-20 22:38     ` Hans de Goede
  0 siblings, 0 replies; 90+ messages in thread
From: Hans de Goede @ 2017-03-20 22:38 UTC (permalink / raw)
  To: Andy Shevchenko, Rafael J . Wysocki, Len Brown, Wolfram Sang,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: linux-acpi, Takashi Iwai, linux-i2c, linux-kernel, linux-pm

Hi,

On 17-03-17 18:33, Andy Shevchenko wrote:
> On Fri, 2017-03-17 at 10:55 +0100, Hans de Goede wrote:
>> Add support for monitoring an extcon device with SDP/CDP/DCP and HOST
>> cables and adjust ilimit and enable/disable the 5v boost converter
>> accordingly. This is necessary on systems where the PSEL pin is
>> hardwired
>> high and ILIM needs to be set by software based on the detected
>> charger
>> type.
>>
>
>>  config CHARGER_BQ24190
>>  	tristate "TI BQ24190 battery charger driver"
>>  	depends on I2C
>
>> +	depends on EXTCON
>
> I dunno what is preferred here, but if we would like to keep
> compatibility with previous configurations "select" should be used over
> "depends on".

select really should only be used for hidden options,
using select in other scenarios leads to all sort of
problems (hard to debug Kconfig dependency loops).

>
>> +static void bq24190_extcon_work(struct work_struct *work)
>> +{
>> +	struct bq24190_dev_info *bdi =
>> +		container_of(work, struct bq24190_dev_info,
>> extcon_work);
>> +	int ret, iinlim = 0;
>> +
>> +	if (extcon_get_state(bdi->extcon, EXTCON_CHG_USB_SDP) == 1)
>> +		iinlim = 500000;
>> +	else if (extcon_get_state(bdi->extcon, EXTCON_CHG_USB_CDP) ==
>> 1 ||
>> +		 extcon_get_state(bdi->extcon, EXTCON_CHG_USB_ACA) ==
>> 1)
>> +		iinlim = 1500000;
>> +	else if (extcon_get_state(bdi->extcon, EXTCON_CHG_USB_DCP) ==
>> 1)
>> +		iinlim = 2000000;
>> +
>
>> +	if (iinlim) {
>
> Could be possible to call below unconditionally here (use 0)?

If there is no Vbus setting iinlim is not useful, the charger
will reset it to a default as soon as Vbus comes up and i2c
transactions are not free.

>
>> +		ret = bq24190_set_field_val(bdi, BQ24190_REG_ISC,
>> +				BQ24190_REG_ISC_IINLIM_MASK,
>> +				BQ24190_REG_ISC_IINLIM_SHIFT,
>> +				bq24190_iinlim_values,
>> +				ARRAY_SIZE(bq24190_iinlim_values),
>> +				iinlim);
>> +		if (ret)
>> +			dev_err(bdi->dev, "Can't set IINLIM: %d\n",
>> ret);
>> +	}
>
> Perhaps make above as a helper?
>
> In that case no need for "if (iinlim)" and perhaps switch-case might be
> used instead of if-else-if (latter is up to you).

I prefer to keep this as is.

Thanks & Regards,

Hans

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH 03/15] extcon: cht-wc: Add Intel Cherry Trail Whiskey Cove PMIC extcon driver
  2017-03-20 13:00     ` Andy Shevchenko
@ 2017-03-21  3:54       ` Chanwoo Choi
  2017-03-21  5:21         ` Chanwoo Choi
  0 siblings, 1 reply; 90+ messages in thread
From: Chanwoo Choi @ 2017-03-21  3:54 UTC (permalink / raw)
  To: Andy Shevchenko, Hans de Goede, Rafael J . Wysocki, Len Brown,
	Wolfram Sang, Lee Jones, Sebastian Reichel, MyungJoo Ham
  Cc: linux-acpi, Takashi Iwai, linux-i2c, linux-kernel, linux-pm

On 2017년 03월 20일 22:00, Andy Shevchenko wrote:
> On Mon, 2017-03-20 at 10:33 +0900, Chanwoo Choi wrote:
>> On 2017년 03월 17일 18:55, Hans de Goede wrote:
> 
>>> +static const struct platform_device_id cht_wc_extcon_table[] = {
>>> +	{ .name = "cht_wcove_pwrsrc" },
>>
>> You use the 'cht_wc' word instead of 'cht_wcove_pwrsrc'.
>> So, To maintain the consistency, you better to use the 'cht-wc' as the
>> name.
>> - I prefer to use '-' instead of '_' in the name.
>> 	.name ="cht-wc"
> 
> I would keep as Hans did for the sake of consistency among all Whiskey
> Cove device drivers (and predecessors like Crystal Cove).

The 'wcove' short word is not used in this patch.
If the author want to use the 'wcove', I recommend that
you should use the 'wcove' instead of 'wc' in this patch.

And, I think that  'pwrsrc' is not ambiguous.
Hans might use the 'pwrsrc' as the 'Power Source'.
But, this driver is not power source. Instead,
this driver supports the detection of external connector.

I think 'power source' means the power supply instead of detector.

> 
> I understand your point from extcon subsystem view, but PMICs like
> Whiskey Cove are multi-functional devices, and thus naming across them
> (same prefix in use to be precise) is better idea.
> 
>>
>>> +	{},
>>> +};
>>> +MODULE_DEVICE_TABLE(platform, cht_wc_extcon_table);
> 


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH 03/15] extcon: cht-wc: Add Intel Cherry Trail Whiskey Cove PMIC extcon driver
  2017-03-20 19:57     ` Hans de Goede
@ 2017-03-21  5:16       ` Chanwoo Choi
  2017-03-23 15:22         ` Hans de Goede
  0 siblings, 1 reply; 90+ messages in thread
From: Chanwoo Choi @ 2017-03-21  5:16 UTC (permalink / raw)
  To: Hans de Goede, Rafael J . Wysocki, Len Brown, Wolfram Sang,
	Andy Shevchenko, Lee Jones, Sebastian Reichel, MyungJoo Ham
  Cc: linux-acpi, Takashi Iwai, linux-i2c, linux-kernel, linux-pm

Hi,

On 2017년 03월 21일 04:57, Hans de Goede wrote:
> Hi,
> 
> On 20-03-17 02:33, Chanwoo Choi wrote:
>> Hi,
>>
>> On 2017년 03월 17일 18:55, Hans de Goede wrote:
>>> Add a driver for charger detection / control on the Intel Cherrytrail
>>> Whiskey Cove PMIC.
>>>
>>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>>> ---
>>>  drivers/extcon/Kconfig         |   7 +
>>>  drivers/extcon/Makefile        |   1 +
>>>  drivers/extcon/extcon-cht-wc.c | 356 +++++++++++++++++++++++++++++++++++++++++
>>>  3 files changed, 364 insertions(+)
>>>  create mode 100644 drivers/extcon/extcon-cht-wc.c
>>>
>>> diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
>>> index 96bbae5..4cace6b 100644
>>> --- a/drivers/extcon/Kconfig
>>> +++ b/drivers/extcon/Kconfig
>>> @@ -52,6 +52,13 @@ config EXTCON_INTEL_INT3496
>>>        This ACPI device is typically found on Intel Baytrail or Cherrytrail
>>>        based tablets, or other Baytrail / Cherrytrail devices.
>>>
>>> +config EXTCON_CHT_WC
>>
>> Need to reorder it alpabetically as the following Makefile.
> 
> The idea is to have the items alphabetically listed in "make menuconfig"
> and the name of the menu item starts with Intel:

If you want to locate it under the EXTCON_INTEL_INT3496,
you should change the filename as following style:
- extcon-intel-cht-wc.c

I want to locate all entry alphabetically. 

> 
>>
>>> +    tristate "Intel Cherrytrail Whiskey Cove PMIC extcon driver"
>>> +    depends on INTEL_SOC_PMIC_CHTWC
>>> +    help
>>> +      Say Y here to enable extcon support for charger detection / control
>>> +      on the Intel Cherrytrail Whiskey Cove PMIC.
>>> +
>>>  config EXTCON_MAX14577
>>>      tristate "Maxim MAX14577/77836 EXTCON Support"
>>>      depends on MFD_MAX14577
>>> diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile
>>> index 237ac3f..160f88b 100644
>>> --- a/drivers/extcon/Makefile
>>> +++ b/drivers/extcon/Makefile
>>> @@ -7,6 +7,7 @@ extcon-core-objs        += extcon.o devres.o
>>>  obj-$(CONFIG_EXTCON_ADC_JACK)    += extcon-adc-jack.o
>>>  obj-$(CONFIG_EXTCON_ARIZONA)    += extcon-arizona.o
>>>  obj-$(CONFIG_EXTCON_AXP288)    += extcon-axp288.o
>>> +obj-$(CONFIG_EXTCON_CHT_WC)    += extcon-cht-wc.o
>>>  obj-$(CONFIG_EXTCON_GPIO)    += extcon-gpio.o
>>>  obj-$(CONFIG_EXTCON_INTEL_INT3496) += extcon-intel-int3496.o
>>>  obj-$(CONFIG_EXTCON_MAX14577)    += extcon-max14577.o
>>> diff --git a/drivers/extcon/extcon-cht-wc.c b/drivers/extcon/extcon-cht-wc.c
>>> new file mode 100644
>>> index 0000000..896eee6
>>> --- /dev/null
>>> +++ b/drivers/extcon/extcon-cht-wc.c
>>> @@ -0,0 +1,356 @@
>>> +/*
>>> + * Extcon charger detection driver for Intel Cherrytrail Whiskey Cove PMIC
>>> + * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
>>> + *
>>> + * Based on various non upstream patches to support the CHT Whiskey Cove PMIC:
>>
>> Maybe, you don't need to add ':' at the end of line.
> 
> Th ':' is there because the following copyright line:
>>
>>> + * Copyright (C) 2013-2015 Intel Corporation. All rights reserved.
> 
> Comes from those various non upstream patches.
> 
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify it
>>> + * under the terms and conditions of the GNU General Public License,
>>> + * version 2, as published by the Free Software Foundation.
>>> + *
>>> + * This program is distributed in the hope it will be useful, but WITHOUT
>>> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
>>> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
>>> + * more details.
>>> + */
>>> +
>>> +#include <linux/extcon.h>
>>> +#include <linux/interrupt.h>
>>> +#include <linux/kernel.h>
>>> +#include <linux/mfd/intel_soc_pmic.h>
>>> +#include <linux/module.h>
>>> +#include <linux/platform_device.h>
>>> +#include <linux/regmap.h>
>>> +#include <linux/slab.h>
>>> +
>>> +#define CHT_WC_PWRSRC_IRQ        0x6e03
>>> +#define CHT_WC_PWRSRC_IRQ_MASK        0x6e0f
>>> +#define CHT_WC_PWRSRC_STS        0x6e1e
>>> +#define CHT_WC_PWRSRC_VBUS        BIT(0)
>>> +#define CHT_WC_PWRSRC_DC        BIT(1)
>>> +#define CHT_WC_PWRSRC_BAT        BIT(2)
>>> +#define CHT_WC_PWRSRC_ID_GND        BIT(3)
>>> +#define CHT_WC_PWRSRC_ID_FLOAT        BIT(4)
>>> +
>>> +#define CHT_WC_PHYCTRL            0x5e07
>>> +
>>> +#define CHT_WC_CHGRCTRL0        0x5e16
>>> +
>>> +#define CHT_WC_CHGRCTRL0        0x5e16
>>> +#define CHT_WC_CHGRCTRL0_CHGRRESET    BIT(0)
>>> +#define CHT_WC_CHGRCTRL0_EMRGCHREN    BIT(1)
>>> +#define CHT_WC_CHGRCTRL0_EXTCHRDIS    BIT(2)
>>> +#define CHT_WC_CHGRCTRL0_SWCONTROL    BIT(3)
>>> +#define CHT_WC_CHGRCTRL0_TTLCK_MASK    BIT(4)
>>> +#define CHT_WC_CHGRCTRL0_CCSM_OFF_MASK    BIT(5)
>>> +#define CHT_WC_CHGRCTRL0_DBPOFF_MASK    BIT(6)
>>> +#define CHT_WC_CHGRCTRL0_WDT_NOKICK    BIT(7)
>>> +
>>> +#define CHT_WC_CHGRCTRL1        0x5e17
>>> +
>>> +#define CHT_WC_USBSRC            0x5e29
>>> +#define CHT_WC_USBSRC_STS_MASK        GENMASK(1, 0)
>>> +#define CHT_WC_USBSRC_STS_SUCCESS    2
>>> +#define CHT_WC_USBSRC_STS_FAIL        3
>>> +#define CHT_WC_USBSRC_TYPE_SHIFT    2
>>> +#define CHT_WC_USBSRC_TYPE_MASK        GENMASK(5, 2)
>>> +#define CHT_WC_USBSRC_TYPE_NONE        0
>>> +#define CHT_WC_USBSRC_TYPE_SDP        1
>>> +#define CHT_WC_USBSRC_TYPE_DCP        2
>>> +#define CHT_WC_USBSRC_TYPE_CDP        3
>>> +#define CHT_WC_USBSRC_TYPE_ACA        4
>>> +#define CHT_WC_USBSRC_TYPE_SE1        5
>>> +#define CHT_WC_USBSRC_TYPE_MHL        6
>>> +#define CHT_WC_USBSRC_TYPE_FLOAT_DP_DN    7
>>> +#define CHT_WC_USBSRC_TYPE_OTHER    8
>>> +#define CHT_WC_USBSRC_TYPE_DCP_EXTPHY    9
>>> +
>>> +enum cht_wc_usb_id {
>>> +    USB_ID_OTG,
>>> +    USB_ID_GND,
>>> +    USB_ID_FLOAT,
>>> +    USB_RID_A,
>>> +    USB_RID_B,
>>> +    USB_RID_C,
>>> +};
>>> +
>>> +/* Strings matching the cht_wc_usb_id enum labels */
>>> +static const char * const usb_id_str[] = {
>>> +    "otg", "gnd", "float", "rid_a", "rid_b", "rid_c" };
>>> +
>>> +enum cht_wc_mux_select {
>>> +    MUX_SEL_PMIC = 0,
>>> +    MUX_SEL_SOC,
>>> +};
>>> +
>>> +static const unsigned int cht_wc_extcon_cables[] = {
>>> +    EXTCON_USB,
>>> +    EXTCON_USB_HOST,
>>> +    EXTCON_CHG_USB_SDP,
>>> +    EXTCON_CHG_USB_CDP,
>>> +    EXTCON_CHG_USB_DCP,
>>> +    EXTCON_NONE,
>>> +};
>>> +
>>> +struct cht_wc_extcon_data {
>>> +    struct device *dev;
>>> +    struct regmap *regmap;
>>> +    struct extcon_dev *edev;
>>> +    unsigned int previous_cable;
>>> +    int usb_id;
>>> +};
>>> +
>>> +static int cht_wc_extcon_get_id(struct cht_wc_extcon_data *ext, int pwrsrc_sts)
>>> +{
>>> +    if (ext->usb_id)
>>> +        return ext->usb_id;
>>> +
>>> +    if (pwrsrc_sts & CHT_WC_PWRSRC_ID_GND)
>>> +        return USB_ID_GND;
>>> +    if (pwrsrc_sts & CHT_WC_PWRSRC_ID_FLOAT)
>>> +        return USB_ID_FLOAT;
>>> +
>>> +    /*
>>> +     * Once we have iio support for the gpadc we should read the USBID
>>> +     * gpadc channel here and determine ACA role based on that.
>>> +     */
>>> +    return USB_ID_FLOAT;
>>> +}
>>> +
>>> +static int cht_wc_extcon_get_charger(struct cht_wc_extcon_data *ext)
>>> +{
>>> +    int ret, usbsrc, status, retries = 5;
>>
>> You have to define the constant for '5' because the name of constant
>> definition indicates what is meaning. So, maybe you will use the 'for' loope
>> instead of 'do..while'.
> 
> Right, already fixed as a result of Andy's review.
> 
>>
>>> +
>>> +    do {
>>> +        ret = regmap_read(ext->regmap, CHT_WC_USBSRC, &usbsrc);
>>> +        if (ret) {
>>> +            dev_err(ext->dev, "Error reading usbsrc: %d\n", ret);
>>> +            return ret;
>>> +        }
>>
>> Need to add one blank line.
>>
>>> +        status = usbsrc & CHT_WC_USBSRC_STS_MASK;
>>> +        if (status == CHT_WC_USBSRC_STS_SUCCESS ||
>>> +            status == CHT_WC_USBSRC_STS_FAIL)
>>> +            break;
>>> +
>>> +        msleep(200);
>>
>> You have to define the constant for '200' because the name of constant
>> definition indicates what is meaning.
>>
>>> +    } while (retries--);
>>> +
>>> +    if (status != CHT_WC_USBSRC_STS_SUCCESS) {
>>> +        if (status == CHT_WC_USBSRC_STS_FAIL)
>>> +            dev_warn(ext->dev, "Could not detect charger type\n");
>>> +        else
>>> +            dev_warn(ext->dev, "Timeout detecting charger type\n");
>>> +        return EXTCON_CHG_USB_SDP; /* Save fallback */
>>> +    }
>>> +
>>> +    ret = (usbsrc & CHT_WC_USBSRC_TYPE_MASK) >> CHT_WC_USBSRC_TYPE_SHIFT;
>>
>> 'ret' is not proper indicates the meaning of 'CHT_WC_USBSRC_TYPE'.
>> You have to use the more correct local variable such as 'usbsrc_type'.
> 
> Fixed for v2.
>>
>>> +    switch (ret) {
>>> +    default:
>>> +        dev_warn(ext->dev, "Unhandled charger type %d\n", ret);
>>> +        /* Fall through treat as SDP */
>>
>> Is it right? Why do you located the 'default' on the top in the switch?
> 
> So that I can use fall-through, there is no rule in C where the default goes.
> 
> The fallthrough is there because assuming SDP (and thus max 500mA current
> draw) is always safe.

If in the default statement, you treat the unhandled charger type as the SDP,
you don't remove the warning message. It makes the confusion.

Warning message is 'unhandled charger type'. But, the extcon
detects the 'SDP' connector type. It is not reasonable.

> 
>>
>>> +    case CHT_WC_USBSRC_TYPE_SDP:
>>> +    case CHT_WC_USBSRC_TYPE_FLOAT_DP_DN:
>>> +    case CHT_WC_USBSRC_TYPE_OTHER:
>>> +        return EXTCON_CHG_USB_SDP;
>>> +    case CHT_WC_USBSRC_TYPE_CDP:
>>> +        return EXTCON_CHG_USB_CDP;
>>> +    case CHT_WC_USBSRC_TYPE_DCP:
>>> +    case CHT_WC_USBSRC_TYPE_DCP_EXTPHY:
>>> +    case CHT_WC_USBSRC_TYPE_MHL: /* MHL2+ delivers upto 2A, treat as DCP */
>>> +        return EXTCON_CHG_USB_DCP;
>>> +    case CHT_WC_USBSRC_TYPE_ACA:
>>> +        return EXTCON_CHG_USB_ACA;
>>> +    }
>>> +}
>>> +
>>> +static void cht_wc_extcon_set_phymux(struct cht_wc_extcon_data *ext, u8 state)
>>> +{
>>> +    int ret;
>>> +
>>> +    ret = regmap_write(ext->regmap, CHT_WC_PHYCTRL, state);
>>> +    if (ret)
>>> +        dev_err(ext->dev, "Error writing phyctrl: %d\n", ret);
>>
>> This function is only called in the cht_wc_extcon_det_event().
>> Also, this funciton write only one register. It is too short.
>> So, you don't need to add the separate function.
>> You better to include this code in the cht_wc_extcon_det_event().
> 
> This is used multiple times in cht_wc_extcon_det_event() and is
> also used in probe() so it saves having to copy and paste the error
> check. Also the flow of cht_wc_extcon_det_event() is more readable
> this way. If it is more efficient to have this inline the compiler
> will auto-inline it.

OK. I recognized it was called only on the cht_wc_extcon_det_event().
But, it is called on multiple points. It's OK.

> 
> 
>>
>>> +}
>>> +
>>> +static void cht_wc_extcon_det_event(struct cht_wc_extcon_data *ext)
>>> +{
>>> +    int ret, pwrsrc_sts, id;
>>> +    unsigned int cable = EXTCON_NONE;
>>> +
>>> +    ret = regmap_read(ext->regmap, CHT_WC_PWRSRC_STS, &pwrsrc_sts);
>>> +    if (ret) {
>>> +        dev_err(ext->dev, "Error reading pwrsrc status: %d\n", ret);
>>> +        return;
>>> +    }
>>> +
>>> +    id = cht_wc_extcon_get_id(ext, pwrsrc_sts);
>>> +    if (id == USB_ID_GND) {
>>> +        /* The 5v boost causes a false VBUS / SDP detect, skip */
>>> +        goto charger_det_done;
>>> +    }
>>> +
>>> +    /* Plugged into a host/charger or not connected? */
>>> +    if (!(pwrsrc_sts & CHT_WC_PWRSRC_VBUS)) {
>>> +        /* Route D+ and D- to PMIC for future charger detection */
>>> +        cht_wc_extcon_set_phymux(ext, MUX_SEL_PMIC);
>>> +        goto set_state;
>>> +    }
>>
>> The cht_wc_extcon_get_id() and cht_wc_extcon_det_event() use the value
>> of CHT_WC_PWRSRC_STS register. So, I think you better to gather the
>> code related to the CHT_WC_PWRSRC_STS for readability.
>> - First suggestion, remove the separate the cht_wc_extcon_get_id()
>> - Second suggestion, The code from regmap_read() to "!(pwrsrc_sts & CHT_WC_PWRSRC_VBUS)"
>>           move into the cht_wc_extcon_get_id().
>>
>> In my opinion, I recommend that second way.
> 
> These register reads are i2c register reads which are quite costly,
> so we really want to do this only once, which is why the code is
> as it is.

Sure, If you use the my second suggestion, you can read i2c register
only one time for all codes as following:

	cht_wc_extcon_get_id(ext)
		// Read the CHT_WC_PWRSRC_STS register through i2c
		// Check the usb_id and pwersrc_sts with CHT_WC_PWRSRC_ID_GND/CHT_WC_PWRSRC_ID_FLOAT.
		// Plugged into a host/charger or not connected?
> 
>>> +
>>> +    ret = cht_wc_extcon_get_charger(ext);
>>> +    if (ret >= 0)
>>> +        cable = ret;
>>> +
>>> +charger_det_done:
>>> +    /* Route D+ and D- to SoC for the host / gadget controller */
>>
>> Minor comment.
>> You better to use '&' instead of '/'
> 
> The data lines get used by either the host OR the gadget controller,
> as there is another mux inside the SoC.

If '/' means the 'or', you can use the 'or' instead of '/'.

> 
>>
>>> +    cht_wc_extcon_set_phymux(ext, MUX_SEL_SOC);
>>> +
>>> +set_state:
>>> +    extcon_set_state_sync(ext->edev, cable, true);
>>> +    extcon_set_state_sync(ext->edev, ext->previous_cable, false);
>>> +    extcon_set_state_sync(ext->edev, EXTCON_USB_HOST,
>>> +                  id == USB_ID_GND || id == USB_RID_A);
>>> +    ext->previous_cable = cable;
>>> +}
>>> +
>>> +static irqreturn_t cht_wc_extcon_isr(int irq, void *data)
>>> +{
>>> +    struct cht_wc_extcon_data *ext = data;
>>> +    int ret, irqs;
>>> +
>>> +    ret = regmap_read(ext->regmap, CHT_WC_PWRSRC_IRQ, &irqs);
>>> +    if (ret)
>>> +        dev_err(ext->dev, "Error reading irqs: %d\n", ret);
>>> +
>>> +    cht_wc_extcon_det_event(ext);
>>> +
>>> +    ret = regmap_write(ext->regmap, CHT_WC_PWRSRC_IRQ, irqs);
>>> +    if (ret)
>>> +        dev_err(ext->dev, "Error writing irqs: %d\n", ret);
>>> +
>>> +    return IRQ_HANDLED;
>>> +}
>>> +
>>> +/* usb_id sysfs attribute for debug / testing purposes */
>>> +static ssize_t usb_id_show(struct device *dev, struct device_attribute *attr,
>>> +               char *buf)
>>> +{
>>> +    struct cht_wc_extcon_data *ext = dev_get_drvdata(dev);
>>> +
>>> +    return sprintf(buf, "%s\n", usb_id_str[ext->usb_id]);
>>> +}
>>> +
>>> +static ssize_t usb_id_store(struct device *dev, struct device_attribute *attr,
>>> +                const char *buf, size_t n)
>>> +{
>>> +    struct cht_wc_extcon_data *ext = dev_get_drvdata(dev);
>>> +    int i;
>>> +
>>> +    for (i = 0; i < ARRAY_SIZE(usb_id_str); i++) {
>>> +        if (sysfs_streq(buf, usb_id_str[i])) {
>>> +            dev_info(ext->dev, "New usb_id %s\n", usb_id_str[i]);
>>> +            ext->usb_id = i;
>>> +            cht_wc_extcon_det_event(ext);
>>> +            return n;
>>> +        }
>>> +    }
>>> +
>>> +    return -EINVAL;
>>> +}
>>> +
>>> +static DEVICE_ATTR(usb_id, 0644, usb_id_show, usb_id_store);
>>
>> I think it is not good to add specific sysfs for only this device driver.
>> The sysfs entry of framework must include the only common and standard interfarce
>> for all extcon device drivers. Because the sysfs entry affects the ABI interface.
>>
>> So, It is not proper.
> 
> Unfortunately these kinda sysfs files are somewhat normal when
> dealing with USB-OTG. For example my board does not have the
> id-pin hooked up to the connector, so to test host mode
> I need to echo "gnd" to the sysfs attr. But also if I actually
> want to use host-mode (or anyone else with the same or a similar
> board).

As I said, I don't want to create the non-standard sysfs interface
for only specific device driver.

If you want to change the some mode of device driver,
we should implement the something in the extcon framework
by keeping the standard interface for ABI. I don't want to
make such a special case.

> 
> See for example also the "mode" sysfs attribute of the musb driver.
> 
> Since the id-pin setting influences multiple other drivers through
> extcon the best place for this is in the extcon driver, as that
> it the canonical source of the EXTCON_USB_HOST cable value.
> 
> 
>>
>>> +
>>> +static int cht_wc_extcon_probe(struct platform_device *pdev)
>>> +{
>>> +    struct cht_wc_extcon_data *ext;
>>> +    struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
>>> +    int irq, ret;
>>> +
>>> +    irq = platform_get_irq(pdev, 0);
>>> +    if (irq < 0)
>>> +        return irq;
>>> +
>>> +    ext = devm_kzalloc(&pdev->dev, sizeof(*ext), GFP_KERNEL);
>>> +    if (!ext)
>>> +        return -ENOMEM;
>>> +
>>> +    ext->dev = &pdev->dev;
>>> +    ext->regmap = pmic->regmap;
>>> +    ext->previous_cable = EXTCON_NONE;
>>> +
>>> +    /* Initialize extcon device */
>>> +    ext->edev = devm_extcon_dev_allocate(ext->dev, cht_wc_extcon_cables);
>>> +    if (IS_ERR(ext->edev))
>>> +        return PTR_ERR(ext->edev);
>>> +
>>> +    ret = regmap_update_bits(ext->regmap, CHT_WC_CHGRCTRL0,
>>> +         CHT_WC_CHGRCTRL0_SWCONTROL | CHT_WC_CHGRCTRL0_CCSM_OFF_MASK,
>>> +         CHT_WC_CHGRCTRL0_SWCONTROL | CHT_WC_CHGRCTRL0_CCSM_OFF_MASK);
>>> +    if (ret) {
>>> +        dev_err(ext->dev, "Error enabling sw control\n");
>>> +        return ret;
>>> +    }
>>> +
>>> +    /* Register extcon device */
>>> +    ret = devm_extcon_dev_register(ext->dev, ext->edev);
>>> +    if (ret) {
>>> +        dev_err(ext->dev, "Failed to register extcon device\n");
>>> +        return ret;
>>> +    }
>>> +
>>> +    /* Route D+ and D- to PMIC for initial charger detection */
>>> +    cht_wc_extcon_set_phymux(ext, MUX_SEL_PMIC);
>>> +
>>> +    /* Get initial state */
>>> +    cht_wc_extcon_det_event(ext);
>>> +
>>> +    ret = devm_request_threaded_irq(ext->dev, irq, NULL, cht_wc_extcon_isr,
>>> +                    IRQF_ONESHOT, pdev->name, ext);
>>> +    if (ret) {
>>> +        dev_err(ext->dev, "Failed to request interrupt\n");
>>> +        return ret;
>>> +    }
>>> +
>>> +    /* Unmask irqs */
>>> +    ret = regmap_write(ext->regmap, CHT_WC_PWRSRC_IRQ_MASK,
>>> +               (int)~(CHT_WC_PWRSRC_VBUS | CHT_WC_PWRSRC_ID_GND |
>>> +                  CHT_WC_PWRSRC_ID_FLOAT));
>>> +    if (ret) {
>>> +        dev_err(ext->dev, "Error writing irq-mask: %d\n", ret);
>>
>> I prefer to use the consistent error log. In the probe function,
>> you use the 'Failed to ...' when error hanppen. So, You better
>> to use the consistent format for errr log as following:
>>     - "Failed to write the irq-mask: %d\n", ret);
> 
> Fixed for v2.
> 
>>
>> I think it improve the readability of your device driver.
>>
>>> +        return ret;
>>> +    }
>>> +
>>> +    platform_set_drvdata(pdev, ext);
>>> +    device_create_file(ext->dev, &dev_attr_usb_id);
>>> +
>>> +    return 0;
>>
>>
>> In the probe function, you touch the some register for initialization.
>> But, if error happen, the probe function don't restore the register value.
>> Is it ok? I think you need to handle the error case.
> 
> Fixed for v2.
> 
>>
>>> +}
>>> +
>>> +static int cht_wc_extcon_remove(struct platform_device *pdev)
>>> +{
>>> +    struct cht_wc_extcon_data *ext = platform_get_drvdata(pdev);
>>> +
>>> +    device_remove_file(ext->dev, &dev_attr_usb_id);
>>
>> Don't need it.
>>
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static const struct platform_device_id cht_wc_extcon_table[] = {
>>> +    { .name = "cht_wcove_pwrsrc" },
>>
>> You use the 'cht_wc' word instead of 'cht_wcove_pwrsrc'.
>> So, To maintain the consistency, you better to use the 'cht-wc' as the name.
>> - I prefer to use '-' instead of '_' in the name.
>>     .name ="cht-wc"
> 
> Already answered by Andy.

I replied again from the Andy's reply.

> 
>>> +    {},
>>> +};
>>> +MODULE_DEVICE_TABLE(platform, cht_wc_extcon_table);
>>> +
>>> +static struct platform_driver cht_wc_extcon_driver = {
>>> +    .probe = cht_wc_extcon_probe,
>>> +    .remove = cht_wc_extcon_remove,
>>> +    .id_table = cht_wc_extcon_table,
>>> +    .driver = {
>>> +        .name = "cht_wcove_pwrsrc",
>>> +    },
>>> +};
>>> +module_platform_driver(cht_wc_extcon_driver);
>>> +
>>> +MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
>>> +MODULE_DESCRIPTION("Intel Cherrytrail Whiskey Cove PMIC extcon driver");
>>
>> Minor comment.
>> You better to locate the MODULE_DESCRIPTION at the first line
>> and then MODULE_AUTHOR is at second line.
> 
> Fixed for v2.
> 
> Regards,
> 
> Hans
> 
> 
> 

-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH 03/15] extcon: cht-wc: Add Intel Cherry Trail Whiskey Cove PMIC extcon driver
  2017-03-21  3:54       ` Chanwoo Choi
@ 2017-03-21  5:21         ` Chanwoo Choi
  2017-03-21  6:27           ` Chanwoo Choi
  0 siblings, 1 reply; 90+ messages in thread
From: Chanwoo Choi @ 2017-03-21  5:21 UTC (permalink / raw)
  To: Andy Shevchenko, Hans de Goede, Rafael J . Wysocki, Len Brown,
	Wolfram Sang, Lee Jones, Sebastian Reichel, MyungJoo Ham
  Cc: linux-acpi, Takashi Iwai, linux-i2c, linux-kernel, linux-pm

On 2017년 03월 21일 12:54, Chanwoo Choi wrote:
> On 2017년 03월 20일 22:00, Andy Shevchenko wrote:
>> On Mon, 2017-03-20 at 10:33 +0900, Chanwoo Choi wrote:
>>> On 2017년 03월 17일 18:55, Hans de Goede wrote:
>>
>>>> +static const struct platform_device_id cht_wc_extcon_table[] = {
>>>> +	{ .name = "cht_wcove_pwrsrc" },
>>>
>>> You use the 'cht_wc' word instead of 'cht_wcove_pwrsrc'.
>>> So, To maintain the consistency, you better to use the 'cht-wc' as the
>>> name.
>>> - I prefer to use '-' instead of '_' in the name.
>>> 	.name ="cht-wc"
>>
>> I would keep as Hans did for the sake of consistency among all Whiskey
>> Cove device drivers (and predecessors like Crystal Cove).
> 
> The 'wcove' short word is not used in this patch.
> If the author want to use the 'wcove', I recommend that
> you should use the 'wcove' instead of 'wc' in this patch.
> 
> And, I think that  'pwrsrc' is not ambiguous.

I'm sorry. I used the wrong word. I mean that 'pwrsrc' is not correct.

> Hans might use the 'pwrsrc' as the 'Power Source'.
> But, this driver is not power source. Instead,
> this driver supports the detection of external connector.
> 
> I think 'power source' means the power supply instead of detector.
> 
>>
>> I understand your point from extcon subsystem view, but PMICs like
>> Whiskey Cove are multi-functional devices, and thus naming across them
>> (same prefix in use to be precise) is better idea.
>>
>>>
>>>> +	{},
>>>> +};
>>>> +MODULE_DEVICE_TABLE(platform, cht_wc_extcon_table);
>>
> 
> 


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH 03/15] extcon: cht-wc: Add Intel Cherry Trail Whiskey Cove PMIC extcon driver
  2017-03-21  5:21         ` Chanwoo Choi
@ 2017-03-21  6:27           ` Chanwoo Choi
  0 siblings, 0 replies; 90+ messages in thread
From: Chanwoo Choi @ 2017-03-21  6:27 UTC (permalink / raw)
  To: Andy Shevchenko, Hans de Goede, Rafael J . Wysocki, Len Brown,
	Wolfram Sang, Lee Jones, Sebastian Reichel, MyungJoo Ham
  Cc: linux-acpi, Takashi Iwai, linux-i2c, linux-kernel, linux-pm

Hi,

I think it again.
The "cht_wcove_pwrsrc' is ok, if the register use the 'pwrsrc' word
and using the 'wcove' instead of 'wc'. It is not big matter.

I agree to use the 'cht_wcove_pwrsrc'.

Best Regards,
Chanwoo Choi


On 2017년 03월 21일 14:21, Chanwoo Choi wrote:
> On 2017년 03월 21일 12:54, Chanwoo Choi wrote:
>> On 2017년 03월 20일 22:00, Andy Shevchenko wrote:
>>> On Mon, 2017-03-20 at 10:33 +0900, Chanwoo Choi wrote:
>>>> On 2017년 03월 17일 18:55, Hans de Goede wrote:
>>>
>>>>> +static const struct platform_device_id cht_wc_extcon_table[] = {
>>>>> +	{ .name = "cht_wcove_pwrsrc" },
>>>>
>>>> You use the 'cht_wc' word instead of 'cht_wcove_pwrsrc'.
>>>> So, To maintain the consistency, you better to use the 'cht-wc' as the
>>>> name.
>>>> - I prefer to use '-' instead of '_' in the name.
>>>> 	.name ="cht-wc"
>>>
>>> I would keep as Hans did for the sake of consistency among all Whiskey
>>> Cove device drivers (and predecessors like Crystal Cove).
>>
>> The 'wcove' short word is not used in this patch.
>> If the author want to use the 'wcove', I recommend that
>> you should use the 'wcove' instead of 'wc' in this patch.
>>
>> And, I think that  'pwrsrc' is not ambiguous.
> 
> I'm sorry. I used the wrong word. I mean that 'pwrsrc' is not correct.
> 
>> Hans might use the 'pwrsrc' as the 'Power Source'.
>> But, this driver is not power source. Instead,
>> this driver supports the detection of external connector.
>>
>> I think 'power source' means the power supply instead of detector.
>>
>>>
>>> I understand your point from extcon subsystem view, but PMICs like
>>> Whiskey Cove are multi-functional devices, and thus naming across them
>>> (same prefix in use to be precise) is better idea.
>>>
>>>>
>>>>> +	{},
>>>>> +};
>>>>> +MODULE_DEVICE_TABLE(platform, cht_wc_extcon_table);
>>>
>>
>>
> 
> 

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH 12/15] i2c: core: Add new i2c_acpi_new_device helper function
  2017-03-17 17:37   ` Andy Shevchenko
@ 2017-03-22 15:59     ` Hans de Goede
  0 siblings, 0 replies; 90+ messages in thread
From: Hans de Goede @ 2017-03-22 15:59 UTC (permalink / raw)
  To: Andy Shevchenko, Rafael J . Wysocki, Len Brown, Wolfram Sang,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: linux-acpi, Takashi Iwai, linux-i2c, linux-kernel, linux-pm

Hi,

On 17-03-17 18:37, Andy Shevchenko wrote:
> On Fri, 2017-03-17 at 10:55 +0100, Hans de Goede wrote:
>> By default the i2c subsys creates an i2c-client for the first
>> I2cSerialBus
>> resource of an acpi_device, but some acpi_devices have multiple
>> I2cSerialBus resources and the driver may need access to the others.
>>
>> This commit adds a new i2c_acpi_new_device function which can be used
>> by
>> drivers to create an i2c-client for any (other) I2cSerialBus resource
>> of
>> an acpi_device.
>>
>> Note that the other resources may even be on a different i2c bus, so
>> just
>> retrieving the client address is not enough.
>>
>
> Looks sane to me:
>
> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
>
> Nevertheless, one nit, can you update commit message with real excerpt
> of DSDT?

Sure, will do for v2.

Regards,

Hans


>
>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>> ---
>>  drivers/i2c/i2c-core.c | 48
>> ++++++++++++++++++++++++++++++++++++++++++++++++
>>  include/linux/i2c.h    |  5 +++++
>>  2 files changed, 53 insertions(+)
>>
>> diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
>> index 32b58fb..fd45207 100644
>> --- a/drivers/i2c/i2c-core.c
>> +++ b/drivers/i2c/i2c-core.c
>> @@ -421,6 +421,54 @@ static int i2c_acpi_notify(struct notifier_block
>> *nb, unsigned long value,
>>  static struct notifier_block i2c_acpi_notifier = {
>>  	.notifier_call = i2c_acpi_notify,
>>  };
>> +
>> +/**
>> + * i2c_acpi_new_device - Create i2c client for the Nth acpi resource
>> of dev
>> + * @dev:     Device owning the acpi resources to get the client from
>> + * @index:   Index of acpi resource to get
>> + *
>> + * By default the i2c subsys creates an i2c-client for the first
>> I2cSerialBus
>> + * resource of an acpi_device, but some acpi_devices have multiple
>> + * I2cSerialBus resources and the driver may need access to the
>> others.
>> + * This function can be used by drivers to create an i2c-client for
>> any
>> + * resource of an acpi_device.
>> + *
>> + * Returns a pointer to the new i2c-client, or NULL if the resource
>> or
>> + * adapter were not found.
>> + */
>> +struct i2c_client *i2c_acpi_new_device(struct device *dev, int index)
>> +{
>> +	struct i2c_acpi_lookup lookup;
>> +	struct i2c_board_info info;
>> +	struct i2c_adapter *adapter;
>> +	struct acpi_device *adev;
>> +	LIST_HEAD(resource_list);
>> +	int ret;
>> +
>> +	adev = ACPI_COMPANION(dev);
>> +	if (!adev)
>> +		return NULL;
>> +
>> +	memset(&info, 0, sizeof(info));
>> +	memset(&lookup, 0, sizeof(lookup));
>> +	lookup.info = &info;
>> +	lookup.device_handle = acpi_device_handle(adev);
>> +	lookup.index = index;
>> +
>> +	ret = acpi_dev_get_resources(adev, &resource_list,
>> +				     i2c_acpi_fill_info, &lookup);
>> +	acpi_dev_free_resource_list(&resource_list);
>> +
>> +	if (ret < 0 || !info.addr)
>> +		return NULL;
>> +
>> +	adapter =
>> i2c_acpi_find_adapter_by_handle(lookup.adapter_handle);
>> +	if (!adapter)
>> +		return NULL;
>> +
>> +	return i2c_new_device(adapter, &info);
>> +}
>> +EXPORT_SYMBOL_GPL(i2c_acpi_new_device);
>>  #else /* CONFIG_ACPI */
>>  static inline void i2c_acpi_register_devices(struct i2c_adapter
>> *adap) { }
>>  extern struct notifier_block i2c_acpi_notifier;
>> diff --git a/include/linux/i2c.h b/include/linux/i2c.h
>> index 6b18352..369ebfa 100644
>> --- a/include/linux/i2c.h
>> +++ b/include/linux/i2c.h
>> @@ -824,11 +824,16 @@ static inline const struct of_device_id
>>
>>  #if IS_ENABLED(CONFIG_ACPI)
>>  u32 i2c_acpi_find_bus_speed(struct device *dev);
>> +struct i2c_client *i2c_acpi_new_device(struct device *dev, int
>> index);
>>  #else
>>  static inline u32 i2c_acpi_find_bus_speed(struct device *dev)
>>  {
>>  	return 0;
>>  }
>> +static inline struct i2c_client *i2c_acpi_new_device(struct device
>> *d, int i)
>> +{
>> +	return NULL;
>> +}
>>  #endif /* CONFIG_ACPI */
>>
>>  #endif /* _LINUX_I2C_H */
>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH 14/15] power: supply: Add driver for Cherry Trail Whiskey Cove PMIC Fuel Gauge
  2017-03-17 17:58   ` Andy Shevchenko
@ 2017-03-22 17:03     ` Hans de Goede
  0 siblings, 0 replies; 90+ messages in thread
From: Hans de Goede @ 2017-03-22 17:03 UTC (permalink / raw)
  To: Andy Shevchenko, Rafael J . Wysocki, Len Brown, Wolfram Sang,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: linux-acpi, Takashi Iwai, linux-i2c, linux-kernel, linux-pm

Hi,

On 17-03-17 18:58, Andy Shevchenko wrote:
> On Fri, 2017-03-17 at 10:55 +0100, Hans de Goede wrote:
>> Add a driver for the Cherry Trail Whiskey Cove PMIC Fuel Gauge, note
>> the Cherry Trail Whiskey Cove PMIC Fuel Gauge block is purely a fuel
>> gauge
>> and not a full battery controller. As such it offers a platform_data
>> callback for extra power_supply properties for the actual external-
>> charger
>> ic driver and does not register a power_supply itself.
>
> ic -> IC
>
> Can we move to something like built-in device properties for additional
> properties instead of extending platform data?
>
>> +config CHT_WC_FUEL_GAUGE
>
> I would use similar pattern:
>
> FUEL_GAUGE_INTEL_CHTWC (or FUEL_GAUGE_CHTWC, but this might be less
> obvious about vendor)

Good point, although all the fuel-gauge's seem to use
BATTERY as prefix, so I've gone with that.

>
>> --- /dev/null
>> +++ b/drivers/power/supply/cht_wc_fuel_gauge.c
>> @@ -0,0 +1,209 @@
>> +/*
>> + * Intel CHT Whiskey Cove Fuel Gauge driver
>
> CHT -> Cherry Trail

Fixed.

>
>> + *
>> + * Cherrytrail Whiskey Cove devices have 2 functional blocks which
>> interact
>> + * with the battery.
>
> Cherry Trail?

Since after discussion about how to deal with the charger / fuel_gauge
comment v2 is going to be a stand-alone power_supply driver this
comment has been dropped.

>
>> +#define REG_CHARGE_NOW		0x05
>> +#define REG_VOLTAGE_NOW		0x09
>> +#define REG_CURRENT_NOW		0x0a
>> +#define REG_CURRENT_AVG		0x0b
>> +#define REG_CHARGE_FULL		0x10
>> +#define REG_CHARGE_DESIGN	0x18
>> +#define REG_VOLTAGE_AVG		0x19
>
>> +#define REG_VOLTAGE_OCV		0x1b /* Only updated during
>> charging */
>
> I think comment makes more sense where actual update is happening in the
> code.
>
>> +
>> +static int cht_wc_fg_read(struct cht_wc_fg_data *fg, u8 reg,
>> +			  union power_supply_propval *val, int scale,
>> +			  int sign_extend)
>> +{
>> +	int ret;
>> +
>> +	ret = i2c_smbus_read_word_data(fg->client, reg);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	if (sign_extend)
>> +		ret = sign_extend32(ret, 15);
>
> Magic?

Nope just simply dealing with i2c_smbus_read_word_data always
returning 16 bit unsigned data (or a negative error code)
and some of the registers being 16 bit signed.

>
>> +
>> +	val->intval = ret * scale;
>> +
>> +	return 0;
>> +}
>
>
>> +
>> +int cht_wc_fg_get_property(enum power_supply_property prop,
>> +			   union power_supply_propval *val)
>> +{
>> +	int ret = 0;
>
> Sounds like redundant assignment...

No longer redundant in v2.

>
>> +
>> +	mutex_lock(&cht_wc_fg_mutex);
>> +
>>
>
>> +	if (!cht_wc_fg) {
>> +		ret = -ENXIO;
>> +		goto out_unlock;
>> +	}
>
> ...otherwise maybe
>
> ret = cht_wc_fg ? 0 : -ENXIO;
> if (ret)
>  goto ...;
>
> ?

With the stand-alone power_supply driver version this ugliness is gone.

>
>> +	default:
>> +		ret = -ENODATA;
>> +	}
>> +out_unlock:
>> +	mutex_unlock(&cht_wc_fg_mutex);
>> +	return ret;
>> +}
>> +EXPORT_SYMBOL_GPL(cht_wc_fg_get_property);
>
>> +
>> +static int cht_wc_fg_probe(struct i2c_client *client,
>> +			const struct i2c_device_id *i2c_id)
>> +{
>> +	struct device *dev = &client->dev;
>> +	struct cht_wc_fg_data *fg;
>> +	acpi_status status;
>> +	unsigned long long ptyp;
>
>> +	status = acpi_evaluate_integer(ACPI_HANDLE(dev), "PTYP",
>> NULL, &ptyp);
>> +	if (ACPI_FAILURE(status)) {
>> +		dev_err(dev, "Failed to get PTYPE\n");
>> +		return -ENODEV;
>> +	}
>> +
>> +	/*
>> +	 * The same ACPI HID is used with different PMICs check PTYP
>> to
>> +	 * ensure that we are dealing with a Whiskey Cove PMIC.
>> +	 */
>> +	if (ptyp != CHT_WC_FG_PTYPE)
>> +		return -ENODEV;
>
> Logically I would split this part to be a main driver for device which
> would use actual driver based on this, though I think it too much churn
> for no benefit right now.

Ack.

>
>> +	mutex_lock(&cht_wc_fg_mutex);
>> +	cht_wc_fg = fg;
>> +	mutex_unlock(&cht_wc_fg_mutex);
>
> It's pity we have no common storage of single possible present device
> drivers in the kernel. I would use some kind of framework rather then
> keeping all those global variables with locking. Perhaps radix / RB
> tree.

With the stand-alone power_supply driver version this ugliness is gone.

Regards,

Hans


^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH 15/15] i2c-cht-wc: Add Intel Cherry Trail Whiskey Cove SMBUS controller driver
  2017-03-17 18:22   ` Andy Shevchenko
@ 2017-03-23 13:58     ` Hans de Goede
  0 siblings, 0 replies; 90+ messages in thread
From: Hans de Goede @ 2017-03-23 13:58 UTC (permalink / raw)
  To: Andy Shevchenko, Rafael J . Wysocki, Len Brown, Wolfram Sang,
	Lee Jones, Sebastian Reichel, MyungJoo Ham, Chanwoo Choi
  Cc: linux-acpi, Takashi Iwai, linux-i2c, linux-kernel, linux-pm

Hi,

On 17-03-17 19:22, Andy Shevchenko wrote:
> On Fri, 2017-03-17 at 10:55 +0100, Hans de Goede wrote:
>> The Intel Cherry Trail Whiskey Cove PMIC has a builtin SMBUS
>> controller
>> for talking to an external PMIC. Add a driver for this.
>
> Looking to all this mess we have with PMICs, perhaps some file under
> Documentation to explain all those dependencies with nice ASCII flow
> charts would be created.

With Sebastian's suggestion to turn the fuel-gauge driver
into a full-blown power_supply driver things luckily aren't
quite that messy anymore.

<snip>

>> +#define CHT_WC_I2C_CTRL			0x5e24
>> +#define CHT_WC_I2C_CTRL_WR		BIT(0)
>> +#define CHT_WC_I2C_CTRL_RD		BIT(1)
>> +#define CHT_WC_I2C_CLIENT_ADDR		0x5e25
>> +#define CHT_WC_I2C_REG_OFFSET		0x5e26
>> +#define CHT_WC_I2C_WRDATA		0x5e27
>> +#define CHT_WC_I2C_RDDATA		0x5e28
>> +
>> +#define CHT_WC_EXTCHGRIRQ		0x6e0a
>> +#define CHT_WC_EXTCHGRIRQ_CLIENT_IRQ	BIT(0)
>> +#define CHT_WC_EXTCHGRIRQ_WRITE_IRQ	BIT(1)
>> +#define CHT_WC_EXTCHGRIRQ_READ_IRQ	BIT(2)
>> +#define CHT_WC_EXTCHGRIRQ_NACK_IRQ	BIT(3)
>>
>
>> +#define CHT_WC_EXTCHGRIRQ_ADAP_IRQS	((u8)(BIT(1) | BIT(2) |
>> BIT(3)))
>
> _IRQ_MASK ?
>
> GENMASK() ?

Both good idea, both fixed for v2. Note I'm not posting
v2 until the bq24190_charger patches are in place
(so that the device-properties to use are known).

>> +#define CHT_WC_EXTCHGRIRQ_MSK		0x6e17
>
>> +struct cht_wc_i2c_adap {
>> +	struct i2c_adapter adapter;
>> +	wait_queue_head_t wait;
>> +	struct irq_chip irqchip;
>> +	struct mutex irqchip_lock;
>> +	struct regmap *regmap;
>> +	struct irq_domain *irq_domain;
>> +	struct i2c_client *client;
>> +	int client_irq;
>> +	u8 irq_mask;
>> +	u8 old_irq_mask;
>> +	bool nack;
>> +	bool done;
>> +};
>> +
>> +static irqreturn_t cht_wc_i2c_adap_thread_handler(int id, void *data)
>> +{
>> +	struct cht_wc_i2c_adap *adap = data;
>> +	int ret, reg;
>> +
>> +	/* Read irqs */
>
> IRQs
>
>> +	ret = regmap_read(adap->regmap, CHT_WC_EXTCHGRIRQ, &reg);
>> +	if (ret) {
>> +		dev_err(&adap->adapter.dev, "Error reading extchgrirq
>> reg\n");
>> +		return IRQ_NONE;
>> +	}
>> +
>> +	reg &= ~adap->irq_mask;
>> +
>> +	/*
>> +	 * Immediately ack irqs, so that if new irqs arrives while
>> we're
>> +	 * handling the previous ones our irq will re-trigger when
>> we're done.
>> +	 */
>> +	ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ, reg);
>> +	if (ret)
>> +		dev_err(&adap->adapter.dev, "Error writing extchgrirq
>> reg\n");
>> +
>> +	/*
>> +	 * Do NOT use handle_nested_irq here, the client irq handler
>> will
>> +	 * likely want to do i2c transfers and the i2c controller
>> uses this
>> +	 * interrupt handler as well, so running the client irq
>> handler from
>> +	 * this thread will cause things to lock up.
>> +	 */
>> +	if (reg & CHT_WC_EXTCHGRIRQ_CLIENT_IRQ) {
>> +		/*
>> +		 * generic_handle_irq expects local irqs to be
>> disabled
>> +		 * as normally it is called from interrupt context.
>> +		 */
>> +		local_irq_disable();
>> +		generic_handle_irq(adap->client_irq);
>> +		local_irq_enable();
>> +	}
>> +
>> +	if (reg & CHT_WC_EXTCHGRIRQ_ADAP_IRQS) {
>
>> +		if (reg & CHT_WC_EXTCHGRIRQ_NACK_IRQ)
>> +			adap->nack = true;
>
> adap->nack = !!(reg & ...);

Good idea, fixed for v2.

>
>> +		adap->done = true;
>> +		wake_up(&adap->wait);
>> +	}
>> +
>> +	return IRQ_HANDLED;
>> +}
>
>> +static u32 cht_wc_i2c_adap_master_func(struct i2c_adapter *adap)
>> +{
>> +	/* This i2c adapter only supports smbus byte transfers */
>
> smbus -> SMBUS
>
>> +	return I2C_FUNC_SMBUS_BYTE_DATA;
>> +}
>> +
>> +static int cht_wc_i2c_adap_smbus_xfer(struct i2c_adapter *_adap, u16
>> addr,
>> +				      unsigned short flags, char
>> read_write,
>> +				      u8 command, int size,
>> +				      union i2c_smbus_data *data)
>> +{
>> +	struct cht_wc_i2c_adap *adap = i2c_get_adapdata(_adap);
>> +	int ret, reg;
>> +
>
>> +
>> +	/* 3 second timeout, during cable plug the PMIC responds
>> quite slow */
>> +	ret = wait_event_timeout(adap->wait, adap->done, HZ * 3);
>
> 3 * HZ

Fixed for v2 (as well as all the capitalization remarks)

>
>> +	if (ret == 0)
>> +		return -ETIMEDOUT;
>> +	if (adap->nack)
>> +		return -EIO;
>> +
>> +	if (read_write == I2C_SMBUS_READ) {
>> +		ret = regmap_read(adap->regmap, CHT_WC_I2C_RDDATA,
>> &reg);
>> +		if (ret)
>> +			return ret;
>> +
>> +		data->byte = reg;
>> +	}
>> +
>> +	return 0;
>> +}
>
>> +/**** irqchip for the client connected to the extchgr i2c adapter
>> ****/
>
> Useless ?

It is meant as a visual separator between the i2c-adapter and
irqchip code.

>
>> +static void cht_wc_i2c_irq_lock(struct irq_data *data)
>> +{
>> +	struct cht_wc_i2c_adap *adap =
>> irq_data_get_irq_chip_data(data);
>> +
>> +	mutex_lock(&adap->irqchip_lock);
>> +}
>> +
>> +static void cht_wc_i2c_irq_sync_unlock(struct irq_data *data)
>> +{
>> +	struct cht_wc_i2c_adap *adap =
>> irq_data_get_irq_chip_data(data);
>> +	int ret;
>> +
>> +	if (adap->irq_mask != adap->old_irq_mask) {
>> +		ret = regmap_write(adap->regmap,
>> CHT_WC_EXTCHGRIRQ_MSK,
>> +				   adap->irq_mask);
>> +		if (ret == 0)
>> +			adap->old_irq_mask = adap->irq_mask;
>> +		else
>> +			dev_err(&adap->adapter.dev, "Error writing
>> extchgrirq_msk\n");
>
> extchgrirq_msk -> EXTCHGRIRQ_MSK ?

Fixed for v2.

>> +	}
>> +
>> +	mutex_unlock(&adap->irqchip_lock);
>> +}
>
>
>> +static const struct bq24190_platform_data bq24190_pdata = {
>> +	.no_register_reset = true,
>> +	.extcon_name = "cht_wcove_pwrsrc",
>> +	.get_ext_bat_property = cht_wc_fg_get_property,
>> +};
>> +
>> +static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev)
>> +{
>> +	struct intel_soc_pmic *pmic = dev_get_drvdata(pdev-
>>> dev.parent);
>> +	struct cht_wc_i2c_adap *adap;
>
>> +	struct i2c_board_info board_info = {
>> +		.type = "bq24190",
>> +		.addr = 0x6b,
>> +		.platform_data = (void *)&bq24190_pdata,
>> +	};
>> +	int ret, irq;
>> +
>
>> +	/* Clear and activate i2c-adapter interrupts, disable client
>> irq */
>
> irq -> IRQ
>
>> +
>> +	/* Alloc and register client irq */
>
> Ditto.
>
>> +	adap->irq_domain = irq_domain_add_linear(pdev->dev.of_node,
>> 1,
>> +						 &irq_domain_simple_o
>> ps, NULL);
>
> Can you use irq_domain_add_simple()?

We don't have (nor want) a static virq for the irq,
so we would pass 0 for irq_domain_add_simple()'s
first_irq argument which makes it equivalent to
irq_domain_add_linear but with one more function
argument and making it less clear what is going on.

> And why do we need separate domain for one IRQ line?

Every irq-chip needs its own domain to map its hwirq
numbers to virq numbers (which are globally unique).

>
>> +	if (!adap->irq_domain)
>> +		return -ENOMEM;
>> +
>> +	adap->client_irq = irq_create_mapping(adap->irq_domain, 0);
>> +	if (!adap->client_irq) {
>> +		ret = -ENOMEM;
>> +		goto remove_irq_domain;
>> +	}
>> +
>> +	irq_set_chip_data(adap->client_irq, adap);
>> +	irq_set_chip_and_handler(adap->client_irq, &adap->irqchip,
>> +				 handle_simple_irq);
>> +
>
>> +	board_info.irq = adap->client_irq;
>> +	adap->client = i2c_new_device(&adap->adapter, &board_info);
>> +	if (!adap->client) {
>> +		ret = -ENOMEM;
>> +		goto del_adapter;
>> +	}
>
> I would split this to some other module with board info.

We need both the adapter and the irq line to instantiate
the i2c-client for the external charger both of which are
readily available here.

> By the way, doesn't ACPI have the charger IC node?

There are several (disabled, _STA returns 0) ACPI nodes
for charger ICs in all the Cherrytrail DSTDs I've (all
DSTDs seem to be copy and paste from the same templates),
but none of them points to the i2c bus controlled by
the Whiskey Cove PMIC. Those nodes seem to all be
for when the charger IC is directly connected to one
of the designware-i2c busses. TL;DR: No there is no
ACPI node for the external charger IC in this case.

Regards,

Hans

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH 03/15] extcon: cht-wc: Add Intel Cherry Trail Whiskey Cove PMIC extcon driver
  2017-03-21  5:16       ` Chanwoo Choi
@ 2017-03-23 15:22         ` Hans de Goede
  0 siblings, 0 replies; 90+ messages in thread
From: Hans de Goede @ 2017-03-23 15:22 UTC (permalink / raw)
  To: Chanwoo Choi, Rafael J . Wysocki, Len Brown, Wolfram Sang,
	Andy Shevchenko, Lee Jones, Sebastian Reichel, MyungJoo Ham
  Cc: linux-acpi, Takashi Iwai, linux-i2c, linux-kernel, linux-pm

Hi,

On 21-03-17 06:16, Chanwoo Choi wrote:
> Hi,
>
> On 2017년 03월 21일 04:57, Hans de Goede wrote:
>> Hi,
>>
>> On 20-03-17 02:33, Chanwoo Choi wrote:
>>> Hi,
>>>
>>> On 2017년 03월 17일 18:55, Hans de Goede wrote:
>>>> Add a driver for charger detection / control on the Intel Cherrytrail
>>>> Whiskey Cove PMIC.
>>>>
>>>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>>>> ---
>>>>  drivers/extcon/Kconfig         |   7 +
>>>>  drivers/extcon/Makefile        |   1 +
>>>>  drivers/extcon/extcon-cht-wc.c | 356 +++++++++++++++++++++++++++++++++++++++++
>>>>  3 files changed, 364 insertions(+)
>>>>  create mode 100644 drivers/extcon/extcon-cht-wc.c
>>>>
>>>> diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
>>>> index 96bbae5..4cace6b 100644
>>>> --- a/drivers/extcon/Kconfig
>>>> +++ b/drivers/extcon/Kconfig
>>>> @@ -52,6 +52,13 @@ config EXTCON_INTEL_INT3496
>>>>        This ACPI device is typically found on Intel Baytrail or Cherrytrail
>>>>        based tablets, or other Baytrail / Cherrytrail devices.
>>>>
>>>> +config EXTCON_CHT_WC
>>>
>>> Need to reorder it alpabetically as the following Makefile.
>>
>> The idea is to have the items alphabetically listed in "make menuconfig"
>> and the name of the menu item starts with Intel:
>
> If you want to locate it under the EXTCON_INTEL_INT3496,
> you should change the filename as following style:
> - extcon-intel-cht-wc.c
>
> I want to locate all entry alphabetically.

Ok, will fix for v3

>
>>
>>>
>>>> +    tristate "Intel Cherrytrail Whiskey Cove PMIC extcon driver"
>>>> +    depends on INTEL_SOC_PMIC_CHTWC
>>>> +    help
>>>> +      Say Y here to enable extcon support for charger detection / control
>>>> +      on the Intel Cherrytrail Whiskey Cove PMIC.
>>>> +
>>>>  config EXTCON_MAX14577
>>>>      tristate "Maxim MAX14577/77836 EXTCON Support"
>>>>      depends on MFD_MAX14577
>>>> diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile
>>>> index 237ac3f..160f88b 100644
>>>> --- a/drivers/extcon/Makefile
>>>> +++ b/drivers/extcon/Makefile
>>>> @@ -7,6 +7,7 @@ extcon-core-objs        += extcon.o devres.o
>>>>  obj-$(CONFIG_EXTCON_ADC_JACK)    += extcon-adc-jack.o
>>>>  obj-$(CONFIG_EXTCON_ARIZONA)    += extcon-arizona.o
>>>>  obj-$(CONFIG_EXTCON_AXP288)    += extcon-axp288.o
>>>> +obj-$(CONFIG_EXTCON_CHT_WC)    += extcon-cht-wc.o
>>>>  obj-$(CONFIG_EXTCON_GPIO)    += extcon-gpio.o
>>>>  obj-$(CONFIG_EXTCON_INTEL_INT3496) += extcon-intel-int3496.o
>>>>  obj-$(CONFIG_EXTCON_MAX14577)    += extcon-max14577.o
>>>> diff --git a/drivers/extcon/extcon-cht-wc.c b/drivers/extcon/extcon-cht-wc.c
>>>> new file mode 100644
>>>> index 0000000..896eee6
>>>> --- /dev/null
>>>> +++ b/drivers/extcon/extcon-cht-wc.c
>>>> @@ -0,0 +1,356 @@
>>>> +/*
>>>> + * Extcon charger detection driver for Intel Cherrytrail Whiskey Cove PMIC
>>>> + * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
>>>> + *
>>>> + * Based on various non upstream patches to support the CHT Whiskey Cove PMIC:
>>>
>>> Maybe, you don't need to add ':' at the end of line.
>>
>> Th ':' is there because the following copyright line:
>>>
>>>> + * Copyright (C) 2013-2015 Intel Corporation. All rights reserved.
>>
>> Comes from those various non upstream patches.
>>
>>>> + *
>>>> + * This program is free software; you can redistribute it and/or modify it
>>>> + * under the terms and conditions of the GNU General Public License,
>>>> + * version 2, as published by the Free Software Foundation.
>>>> + *
>>>> + * This program is distributed in the hope it will be useful, but WITHOUT
>>>> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
>>>> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
>>>> + * more details.
>>>> + */
>>>> +
>>>> +#include <linux/extcon.h>
>>>> +#include <linux/interrupt.h>
>>>> +#include <linux/kernel.h>
>>>> +#include <linux/mfd/intel_soc_pmic.h>
>>>> +#include <linux/module.h>
>>>> +#include <linux/platform_device.h>
>>>> +#include <linux/regmap.h>
>>>> +#include <linux/slab.h>
>>>> +
>>>> +#define CHT_WC_PWRSRC_IRQ        0x6e03
>>>> +#define CHT_WC_PWRSRC_IRQ_MASK        0x6e0f
>>>> +#define CHT_WC_PWRSRC_STS        0x6e1e
>>>> +#define CHT_WC_PWRSRC_VBUS        BIT(0)
>>>> +#define CHT_WC_PWRSRC_DC        BIT(1)
>>>> +#define CHT_WC_PWRSRC_BAT        BIT(2)
>>>> +#define CHT_WC_PWRSRC_ID_GND        BIT(3)
>>>> +#define CHT_WC_PWRSRC_ID_FLOAT        BIT(4)
>>>> +
>>>> +#define CHT_WC_PHYCTRL            0x5e07
>>>> +
>>>> +#define CHT_WC_CHGRCTRL0        0x5e16
>>>> +
>>>> +#define CHT_WC_CHGRCTRL0        0x5e16
>>>> +#define CHT_WC_CHGRCTRL0_CHGRRESET    BIT(0)
>>>> +#define CHT_WC_CHGRCTRL0_EMRGCHREN    BIT(1)
>>>> +#define CHT_WC_CHGRCTRL0_EXTCHRDIS    BIT(2)
>>>> +#define CHT_WC_CHGRCTRL0_SWCONTROL    BIT(3)
>>>> +#define CHT_WC_CHGRCTRL0_TTLCK_MASK    BIT(4)
>>>> +#define CHT_WC_CHGRCTRL0_CCSM_OFF_MASK    BIT(5)
>>>> +#define CHT_WC_CHGRCTRL0_DBPOFF_MASK    BIT(6)
>>>> +#define CHT_WC_CHGRCTRL0_WDT_NOKICK    BIT(7)
>>>> +
>>>> +#define CHT_WC_CHGRCTRL1        0x5e17
>>>> +
>>>> +#define CHT_WC_USBSRC            0x5e29
>>>> +#define CHT_WC_USBSRC_STS_MASK        GENMASK(1, 0)
>>>> +#define CHT_WC_USBSRC_STS_SUCCESS    2
>>>> +#define CHT_WC_USBSRC_STS_FAIL        3
>>>> +#define CHT_WC_USBSRC_TYPE_SHIFT    2
>>>> +#define CHT_WC_USBSRC_TYPE_MASK        GENMASK(5, 2)
>>>> +#define CHT_WC_USBSRC_TYPE_NONE        0
>>>> +#define CHT_WC_USBSRC_TYPE_SDP        1
>>>> +#define CHT_WC_USBSRC_TYPE_DCP        2
>>>> +#define CHT_WC_USBSRC_TYPE_CDP        3
>>>> +#define CHT_WC_USBSRC_TYPE_ACA        4
>>>> +#define CHT_WC_USBSRC_TYPE_SE1        5
>>>> +#define CHT_WC_USBSRC_TYPE_MHL        6
>>>> +#define CHT_WC_USBSRC_TYPE_FLOAT_DP_DN    7
>>>> +#define CHT_WC_USBSRC_TYPE_OTHER    8
>>>> +#define CHT_WC_USBSRC_TYPE_DCP_EXTPHY    9
>>>> +
>>>> +enum cht_wc_usb_id {
>>>> +    USB_ID_OTG,
>>>> +    USB_ID_GND,
>>>> +    USB_ID_FLOAT,
>>>> +    USB_RID_A,
>>>> +    USB_RID_B,
>>>> +    USB_RID_C,
>>>> +};
>>>> +
>>>> +/* Strings matching the cht_wc_usb_id enum labels */
>>>> +static const char * const usb_id_str[] = {
>>>> +    "otg", "gnd", "float", "rid_a", "rid_b", "rid_c" };
>>>> +
>>>> +enum cht_wc_mux_select {
>>>> +    MUX_SEL_PMIC = 0,
>>>> +    MUX_SEL_SOC,
>>>> +};
>>>> +
>>>> +static const unsigned int cht_wc_extcon_cables[] = {
>>>> +    EXTCON_USB,
>>>> +    EXTCON_USB_HOST,
>>>> +    EXTCON_CHG_USB_SDP,
>>>> +    EXTCON_CHG_USB_CDP,
>>>> +    EXTCON_CHG_USB_DCP,
>>>> +    EXTCON_NONE,
>>>> +};
>>>> +
>>>> +struct cht_wc_extcon_data {
>>>> +    struct device *dev;
>>>> +    struct regmap *regmap;
>>>> +    struct extcon_dev *edev;
>>>> +    unsigned int previous_cable;
>>>> +    int usb_id;
>>>> +};
>>>> +
>>>> +static int cht_wc_extcon_get_id(struct cht_wc_extcon_data *ext, int pwrsrc_sts)
>>>> +{
>>>> +    if (ext->usb_id)
>>>> +        return ext->usb_id;
>>>> +
>>>> +    if (pwrsrc_sts & CHT_WC_PWRSRC_ID_GND)
>>>> +        return USB_ID_GND;
>>>> +    if (pwrsrc_sts & CHT_WC_PWRSRC_ID_FLOAT)
>>>> +        return USB_ID_FLOAT;
>>>> +
>>>> +    /*
>>>> +     * Once we have iio support for the gpadc we should read the USBID
>>>> +     * gpadc channel here and determine ACA role based on that.
>>>> +     */
>>>> +    return USB_ID_FLOAT;
>>>> +}
>>>> +
>>>> +static int cht_wc_extcon_get_charger(struct cht_wc_extcon_data *ext)
>>>> +{
>>>> +    int ret, usbsrc, status, retries = 5;
>>>
>>> You have to define the constant for '5' because the name of constant
>>> definition indicates what is meaning. So, maybe you will use the 'for' loope
>>> instead of 'do..while'.
>>
>> Right, already fixed as a result of Andy's review.
>>
>>>
>>>> +
>>>> +    do {
>>>> +        ret = regmap_read(ext->regmap, CHT_WC_USBSRC, &usbsrc);
>>>> +        if (ret) {
>>>> +            dev_err(ext->dev, "Error reading usbsrc: %d\n", ret);
>>>> +            return ret;
>>>> +        }
>>>
>>> Need to add one blank line.
>>>
>>>> +        status = usbsrc & CHT_WC_USBSRC_STS_MASK;
>>>> +        if (status == CHT_WC_USBSRC_STS_SUCCESS ||
>>>> +            status == CHT_WC_USBSRC_STS_FAIL)
>>>> +            break;
>>>> +
>>>> +        msleep(200);
>>>
>>> You have to define the constant for '200' because the name of constant
>>> definition indicates what is meaning.
>>>
>>>> +    } while (retries--);
>>>> +
>>>> +    if (status != CHT_WC_USBSRC_STS_SUCCESS) {
>>>> +        if (status == CHT_WC_USBSRC_STS_FAIL)
>>>> +            dev_warn(ext->dev, "Could not detect charger type\n");
>>>> +        else
>>>> +            dev_warn(ext->dev, "Timeout detecting charger type\n");
>>>> +        return EXTCON_CHG_USB_SDP; /* Save fallback */
>>>> +    }
>>>> +
>>>> +    ret = (usbsrc & CHT_WC_USBSRC_TYPE_MASK) >> CHT_WC_USBSRC_TYPE_SHIFT;
>>>
>>> 'ret' is not proper indicates the meaning of 'CHT_WC_USBSRC_TYPE'.
>>> You have to use the more correct local variable such as 'usbsrc_type'.
>>
>> Fixed for v2.
>>>
>>>> +    switch (ret) {
>>>> +    default:
>>>> +        dev_warn(ext->dev, "Unhandled charger type %d\n", ret);
>>>> +        /* Fall through treat as SDP */
>>>
>>> Is it right? Why do you located the 'default' on the top in the switch?
>>
>> So that I can use fall-through, there is no rule in C where the default goes.
>>
>> The fallthrough is there because assuming SDP (and thus max 500mA current
>> draw) is always safe.
>
> If in the default statement, you treat the unhandled charger type as the SDP,
> you don't remove the warning message. It makes the confusion.
>
> Warning message is 'unhandled charger type'. But, the extcon
> detects the 'SDP' connector type. It is not reasonable.

Ok, I will change the warning message to say that we are defaulting to
SDP.

>
>>
>>>
>>>> +    case CHT_WC_USBSRC_TYPE_SDP:
>>>> +    case CHT_WC_USBSRC_TYPE_FLOAT_DP_DN:
>>>> +    case CHT_WC_USBSRC_TYPE_OTHER:
>>>> +        return EXTCON_CHG_USB_SDP;
>>>> +    case CHT_WC_USBSRC_TYPE_CDP:
>>>> +        return EXTCON_CHG_USB_CDP;
>>>> +    case CHT_WC_USBSRC_TYPE_DCP:
>>>> +    case CHT_WC_USBSRC_TYPE_DCP_EXTPHY:
>>>> +    case CHT_WC_USBSRC_TYPE_MHL: /* MHL2+ delivers upto 2A, treat as DCP */
>>>> +        return EXTCON_CHG_USB_DCP;
>>>> +    case CHT_WC_USBSRC_TYPE_ACA:
>>>> +        return EXTCON_CHG_USB_ACA;
>>>> +    }
>>>> +}
>>>> +
>>>> +static void cht_wc_extcon_set_phymux(struct cht_wc_extcon_data *ext, u8 state)
>>>> +{
>>>> +    int ret;
>>>> +
>>>> +    ret = regmap_write(ext->regmap, CHT_WC_PHYCTRL, state);
>>>> +    if (ret)
>>>> +        dev_err(ext->dev, "Error writing phyctrl: %d\n", ret);
>>>
>>> This function is only called in the cht_wc_extcon_det_event().
>>> Also, this funciton write only one register. It is too short.
>>> So, you don't need to add the separate function.
>>> You better to include this code in the cht_wc_extcon_det_event().
>>
>> This is used multiple times in cht_wc_extcon_det_event() and is
>> also used in probe() so it saves having to copy and paste the error
>> check. Also the flow of cht_wc_extcon_det_event() is more readable
>> this way. If it is more efficient to have this inline the compiler
>> will auto-inline it.
>
> OK. I recognized it was called only on the cht_wc_extcon_det_event().
> But, it is called on multiple points. It's OK.
>
>>
>>
>>>
>>>> +}
>>>> +
>>>> +static void cht_wc_extcon_det_event(struct cht_wc_extcon_data *ext)
>>>> +{
>>>> +    int ret, pwrsrc_sts, id;
>>>> +    unsigned int cable = EXTCON_NONE;
>>>> +
>>>> +    ret = regmap_read(ext->regmap, CHT_WC_PWRSRC_STS, &pwrsrc_sts);
>>>> +    if (ret) {
>>>> +        dev_err(ext->dev, "Error reading pwrsrc status: %d\n", ret);
>>>> +        return;
>>>> +    }
>>>> +
>>>> +    id = cht_wc_extcon_get_id(ext, pwrsrc_sts);
>>>> +    if (id == USB_ID_GND) {
>>>> +        /* The 5v boost causes a false VBUS / SDP detect, skip */
>>>> +        goto charger_det_done;
>>>> +    }
>>>> +
>>>> +    /* Plugged into a host/charger or not connected? */
>>>> +    if (!(pwrsrc_sts & CHT_WC_PWRSRC_VBUS)) {
>>>> +        /* Route D+ and D- to PMIC for future charger detection */
>>>> +        cht_wc_extcon_set_phymux(ext, MUX_SEL_PMIC);
>>>> +        goto set_state;
>>>> +    }
>>>
>>> The cht_wc_extcon_get_id() and cht_wc_extcon_det_event() use the value
>>> of CHT_WC_PWRSRC_STS register. So, I think you better to gather the
>>> code related to the CHT_WC_PWRSRC_STS for readability.
>>> - First suggestion, remove the separate the cht_wc_extcon_get_id()
>>> - Second suggestion, The code from regmap_read() to "!(pwrsrc_sts & CHT_WC_PWRSRC_VBUS)"
>>>           move into the cht_wc_extcon_get_id().
>>>
>>> In my opinion, I recommend that second way.
>>
>> These register reads are i2c register reads which are quite costly,
>> so we really want to do this only once, which is why the code is
>> as it is.
>
> Sure, If you use the my second suggestion, you can read i2c register
> only one time for all codes as following:
>
> 	cht_wc_extcon_get_id(ext)
> 		// Read the CHT_WC_PWRSRC_STS register through i2c
> 		// Check the usb_id and pwersrc_sts with CHT_WC_PWRSRC_ID_GND/CHT_WC_PWRSRC_ID_FLOAT.
> 		// Plugged into a host/charger or not connected?
>>
>>>> +
>>>> +    ret = cht_wc_extcon_get_charger(ext);
>>>> +    if (ret >= 0)
>>>> +        cable = ret;
>>>> +
>>>> +charger_det_done:
>>>> +    /* Route D+ and D- to SoC for the host / gadget controller */
>>>
>>> Minor comment.
>>> You better to use '&' instead of '/'
>>
>> The data lines get used by either the host OR the gadget controller,
>> as there is another mux inside the SoC.
>
> If '/' means the 'or', you can use the 'or' instead of '/'.

Ok text changed to use or for v3.

>
>>
>>>
>>>> +    cht_wc_extcon_set_phymux(ext, MUX_SEL_SOC);
>>>> +
>>>> +set_state:
>>>> +    extcon_set_state_sync(ext->edev, cable, true);
>>>> +    extcon_set_state_sync(ext->edev, ext->previous_cable, false);
>>>> +    extcon_set_state_sync(ext->edev, EXTCON_USB_HOST,
>>>> +                  id == USB_ID_GND || id == USB_RID_A);
>>>> +    ext->previous_cable = cable;
>>>> +}
>>>> +
>>>> +static irqreturn_t cht_wc_extcon_isr(int irq, void *data)
>>>> +{
>>>> +    struct cht_wc_extcon_data *ext = data;
>>>> +    int ret, irqs;
>>>> +
>>>> +    ret = regmap_read(ext->regmap, CHT_WC_PWRSRC_IRQ, &irqs);
>>>> +    if (ret)
>>>> +        dev_err(ext->dev, "Error reading irqs: %d\n", ret);
>>>> +
>>>> +    cht_wc_extcon_det_event(ext);
>>>> +
>>>> +    ret = regmap_write(ext->regmap, CHT_WC_PWRSRC_IRQ, irqs);
>>>> +    if (ret)
>>>> +        dev_err(ext->dev, "Error writing irqs: %d\n", ret);
>>>> +
>>>> +    return IRQ_HANDLED;
>>>> +}
>>>> +
>>>> +/* usb_id sysfs attribute for debug / testing purposes */
>>>> +static ssize_t usb_id_show(struct device *dev, struct device_attribute *attr,
>>>> +               char *buf)
>>>> +{
>>>> +    struct cht_wc_extcon_data *ext = dev_get_drvdata(dev);
>>>> +
>>>> +    return sprintf(buf, "%s\n", usb_id_str[ext->usb_id]);
>>>> +}
>>>> +
>>>> +static ssize_t usb_id_store(struct device *dev, struct device_attribute *attr,
>>>> +                const char *buf, size_t n)
>>>> +{
>>>> +    struct cht_wc_extcon_data *ext = dev_get_drvdata(dev);
>>>> +    int i;
>>>> +
>>>> +    for (i = 0; i < ARRAY_SIZE(usb_id_str); i++) {
>>>> +        if (sysfs_streq(buf, usb_id_str[i])) {
>>>> +            dev_info(ext->dev, "New usb_id %s\n", usb_id_str[i]);
>>>> +            ext->usb_id = i;
>>>> +            cht_wc_extcon_det_event(ext);
>>>> +            return n;
>>>> +        }
>>>> +    }
>>>> +
>>>> +    return -EINVAL;
>>>> +}
>>>> +
>>>> +static DEVICE_ATTR(usb_id, 0644, usb_id_show, usb_id_store);
>>>
>>> I think it is not good to add specific sysfs for only this device driver.
>>> The sysfs entry of framework must include the only common and standard interfarce
>>> for all extcon device drivers. Because the sysfs entry affects the ABI interface.
>>>
>>> So, It is not proper.
>>
>> Unfortunately these kinda sysfs files are somewhat normal when
>> dealing with USB-OTG. For example my board does not have the
>> id-pin hooked up to the connector, so to test host mode
>> I need to echo "gnd" to the sysfs attr. But also if I actually
>> want to use host-mode (or anyone else with the same or a similar
>> board).
>
> As I said, I don't want to create the non-standard sysfs interface
> for only specific device driver.
>
> If you want to change the some mode of device driver,
> we should implement the something in the extcon framework
> by keeping the standard interface for ABI. I don't want to
> make such a special case.

Ok, I will drop this part of the driver for now, we can revisit
this later.

>> See for example also the "mode" sysfs attribute of the musb driver.
>>
>> Since the id-pin setting influences multiple other drivers through
>> extcon the best place for this is in the extcon driver, as that
>> it the canonical source of the EXTCON_USB_HOST cable value.
>>
>>
>>>
>>>> +
>>>> +static int cht_wc_extcon_probe(struct platform_device *pdev)
>>>> +{
>>>> +    struct cht_wc_extcon_data *ext;
>>>> +    struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
>>>> +    int irq, ret;
>>>> +
>>>> +    irq = platform_get_irq(pdev, 0);
>>>> +    if (irq < 0)
>>>> +        return irq;
>>>> +
>>>> +    ext = devm_kzalloc(&pdev->dev, sizeof(*ext), GFP_KERNEL);
>>>> +    if (!ext)
>>>> +        return -ENOMEM;
>>>> +
>>>> +    ext->dev = &pdev->dev;
>>>> +    ext->regmap = pmic->regmap;
>>>> +    ext->previous_cable = EXTCON_NONE;
>>>> +
>>>> +    /* Initialize extcon device */
>>>> +    ext->edev = devm_extcon_dev_allocate(ext->dev, cht_wc_extcon_cables);
>>>> +    if (IS_ERR(ext->edev))
>>>> +        return PTR_ERR(ext->edev);
>>>> +
>>>> +    ret = regmap_update_bits(ext->regmap, CHT_WC_CHGRCTRL0,
>>>> +         CHT_WC_CHGRCTRL0_SWCONTROL | CHT_WC_CHGRCTRL0_CCSM_OFF_MASK,
>>>> +         CHT_WC_CHGRCTRL0_SWCONTROL | CHT_WC_CHGRCTRL0_CCSM_OFF_MASK);
>>>> +    if (ret) {
>>>> +        dev_err(ext->dev, "Error enabling sw control\n");
>>>> +        return ret;
>>>> +    }
>>>> +
>>>> +    /* Register extcon device */
>>>> +    ret = devm_extcon_dev_register(ext->dev, ext->edev);
>>>> +    if (ret) {
>>>> +        dev_err(ext->dev, "Failed to register extcon device\n");
>>>> +        return ret;
>>>> +    }
>>>> +
>>>> +    /* Route D+ and D- to PMIC for initial charger detection */
>>>> +    cht_wc_extcon_set_phymux(ext, MUX_SEL_PMIC);
>>>> +
>>>> +    /* Get initial state */
>>>> +    cht_wc_extcon_det_event(ext);
>>>> +
>>>> +    ret = devm_request_threaded_irq(ext->dev, irq, NULL, cht_wc_extcon_isr,
>>>> +                    IRQF_ONESHOT, pdev->name, ext);
>>>> +    if (ret) {
>>>> +        dev_err(ext->dev, "Failed to request interrupt\n");
>>>> +        return ret;
>>>> +    }
>>>> +
>>>> +    /* Unmask irqs */
>>>> +    ret = regmap_write(ext->regmap, CHT_WC_PWRSRC_IRQ_MASK,
>>>> +               (int)~(CHT_WC_PWRSRC_VBUS | CHT_WC_PWRSRC_ID_GND |
>>>> +                  CHT_WC_PWRSRC_ID_FLOAT));
>>>> +    if (ret) {
>>>> +        dev_err(ext->dev, "Error writing irq-mask: %d\n", ret);
>>>
>>> I prefer to use the consistent error log. In the probe function,
>>> you use the 'Failed to ...' when error hanppen. So, You better
>>> to use the consistent format for errr log as following:
>>>     - "Failed to write the irq-mask: %d\n", ret);
>>
>> Fixed for v2.
>>
>>>
>>> I think it improve the readability of your device driver.
>>>
>>>> +        return ret;
>>>> +    }
>>>> +
>>>> +    platform_set_drvdata(pdev, ext);
>>>> +    device_create_file(ext->dev, &dev_attr_usb_id);
>>>> +
>>>> +    return 0;
>>>
>>>
>>> In the probe function, you touch the some register for initialization.
>>> But, if error happen, the probe function don't restore the register value.
>>> Is it ok? I think you need to handle the error case.
>>
>> Fixed for v2.
>>
>>>
>>>> +}
>>>> +
>>>> +static int cht_wc_extcon_remove(struct platform_device *pdev)
>>>> +{
>>>> +    struct cht_wc_extcon_data *ext = platform_get_drvdata(pdev);
>>>> +
>>>> +    device_remove_file(ext->dev, &dev_attr_usb_id);
>>>
>>> Don't need it.
>>>
>>>> +
>>>> +    return 0;
>>>> +}
>>>> +
>>>> +static const struct platform_device_id cht_wc_extcon_table[] = {
>>>> +    { .name = "cht_wcove_pwrsrc" },
>>>
>>> You use the 'cht_wc' word instead of 'cht_wcove_pwrsrc'.
>>> So, To maintain the consistency, you better to use the 'cht-wc' as the name.
>>> - I prefer to use '-' instead of '_' in the name.
>>>     .name ="cht-wc"
>>
>> Already answered by Andy.
>
> I replied again from the Andy's reply.
>
>>
>>>> +    {},
>>>> +};
>>>> +MODULE_DEVICE_TABLE(platform, cht_wc_extcon_table);
>>>> +
>>>> +static struct platform_driver cht_wc_extcon_driver = {
>>>> +    .probe = cht_wc_extcon_probe,
>>>> +    .remove = cht_wc_extcon_remove,
>>>> +    .id_table = cht_wc_extcon_table,
>>>> +    .driver = {
>>>> +        .name = "cht_wcove_pwrsrc",
>>>> +    },
>>>> +};
>>>> +module_platform_driver(cht_wc_extcon_driver);
>>>> +
>>>> +MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
>>>> +MODULE_DESCRIPTION("Intel Cherrytrail Whiskey Cove PMIC extcon driver");
>>>
>>> Minor comment.
>>> You better to locate the MODULE_DESCRIPTION at the first line
>>> and then MODULE_AUTHOR is at second line.
>>
>> Fixed for v2.

Regards,

Hans

^ permalink raw reply	[flat|nested] 90+ messages in thread

end of thread, other threads:[~2017-03-23 15:22 UTC | newest]

Thread overview: 90+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-17  9:55 [PATCH 00/15] Add Intel Cherry Trail Whiskey Cove PMIC support Hans de Goede
2017-03-17  9:55 ` [PATCH 01/15] mfd: Add Cherry Trail Whiskey Cove PMIC driver Hans de Goede
2017-03-17 17:00   ` Andy Shevchenko
2017-03-20 10:41     ` Lee Jones
2017-03-20 12:55       ` Andy Shevchenko
2017-03-17  9:55 ` [PATCH 02/15] ACPI / PMIC: Add opregion driver for Intel CHT Whiskey Cove PMIC Hans de Goede
2017-03-17  9:55 ` [PATCH 03/15] extcon: cht-wc: Add Intel Cherry Trail Whiskey Cove PMIC extcon driver Hans de Goede
2017-03-17 17:18   ` Andy Shevchenko
2017-03-20 18:08     ` Hans de Goede
2017-03-20  1:33   ` Chanwoo Choi
2017-03-20 13:00     ` Andy Shevchenko
2017-03-21  3:54       ` Chanwoo Choi
2017-03-21  5:21         ` Chanwoo Choi
2017-03-21  6:27           ` Chanwoo Choi
2017-03-20 19:57     ` Hans de Goede
2017-03-21  5:16       ` Chanwoo Choi
2017-03-23 15:22         ` Hans de Goede
2017-03-17  9:55 ` [PATCH 04/15] power: supply: bq24190_charger: Add no_register_reset pdata flag Hans de Goede
2017-03-17 17:20   ` Andy Shevchenko
2017-03-18  7:10   ` [04/15] " Liam Breck
2017-03-18 14:13     ` Hans de Goede
2017-03-18 18:51       ` Liam Breck
2017-03-18 22:51         ` Hans de Goede
2017-03-19  0:57           ` Liam Breck
2017-03-19  8:22             ` Hans de Goede
2017-03-19  9:42               ` Hans de Goede
2017-03-20  5:27                 ` Sebastian Reichel
2017-03-20 13:54                   ` Hans de Goede
2017-03-20 17:04                     ` Hans de Goede
2017-03-20 17:51                       ` Liam Breck
2017-03-20 18:01                         ` Hans de Goede
2017-03-20 18:19                           ` Liam Breck
2017-03-20 19:22                             ` Hans de Goede
2017-03-20 21:14                               ` Sebastian Reichel
2017-03-20 21:34                                 ` Liam Breck
2017-03-20 22:01                                 ` Hans de Goede
2017-03-20 21:15                               ` Liam Breck
2017-03-19 14:54             ` Andy Shevchenko
2017-03-19 18:13               ` Hans de Goede
2017-03-17  9:55 ` [PATCH 05/15] power: supply: bq24190_charger: Limit charging voltage to 4.3V Hans de Goede
2017-03-18  7:10   ` [05/15] " Liam Breck
2017-03-18 14:24     ` Hans de Goede
2017-03-18 19:01       ` Liam Breck
2017-03-17  9:55 ` [PATCH 06/15] power: supply: bq24190_charger: Use i2c-core irq-mapping code Hans de Goede
2017-03-17 17:24   ` Andy Shevchenko
2017-03-20  4:46     ` Sebastian Reichel
2017-03-18  7:10   ` [06/15] " Liam Breck
2017-03-18 14:16     ` Hans de Goede
2017-03-17  9:55 ` [PATCH 07/15] power: supply: bq24190_charger: Add support for bq24192[i] Hans de Goede
2017-03-18  7:10   ` [07/15] " Liam Breck
2017-03-18 14:30     ` Hans de Goede
2017-03-18 19:10       ` Liam Breck
2017-03-18 22:55         ` Hans de Goede
2017-03-17  9:55 ` [PATCH 08/15] power: supply: bq24190_charger: Add support for external fuel gauge Hans de Goede
2017-03-18  7:10   ` [08/15] " Liam Breck
2017-03-18 14:31     ` Hans de Goede
2017-03-18 19:18       ` Liam Breck
2017-03-18 23:02         ` Hans de Goede
2017-03-19  1:01           ` Liam Breck
2017-03-19  3:52           ` Liam Breck
2017-03-17  9:55 ` [PATCH 09/15] power: supply: bq24190_charger: Add voltage_max_design prop to battery Hans de Goede
2017-03-18  7:10   ` [09/15] " Liam Breck
2017-03-18 14:34     ` Hans de Goede
2017-03-18 19:34       ` Liam Breck
2017-03-18 23:10         ` Hans de Goede
2017-03-20  5:12   ` [PATCH 09/15] " Sebastian Reichel
2017-03-17  9:55 ` [PATCH 10/15] power: supply: bq24190_charger: Use extcon to determine ilimit, 5v boost Hans de Goede
2017-03-17 17:33   ` Andy Shevchenko
2017-03-20 22:38     ` Hans de Goede
2017-03-18  7:10   ` [10/15] " Liam Breck
2017-03-18 14:42     ` Hans de Goede
2017-03-18 19:57       ` Liam Breck
2017-03-18 23:11         ` Hans de Goede
2017-03-20  4:52   ` [PATCH 10/15] " Sebastian Reichel
2017-03-17  9:55 ` [PATCH 11/15] i2c: core: Allow getting ACPI info by index Hans de Goede
2017-03-17 17:35   ` Andy Shevchenko
2017-03-17  9:55 ` [PATCH 12/15] i2c: core: Add new i2c_acpi_new_device helper function Hans de Goede
2017-03-17 17:37   ` Andy Shevchenko
2017-03-22 15:59     ` Hans de Goede
2017-03-17  9:55 ` [PATCH 13/15] i2c: core: Allow drivers to specify index for irq to get from of / ACPI Hans de Goede
2017-03-17 17:41   ` Andy Shevchenko
2017-03-20  8:55   ` kbuild test robot
2017-03-20  8:55     ` kbuild test robot
2017-03-17  9:55 ` [PATCH 14/15] power: supply: Add driver for Cherry Trail Whiskey Cove PMIC Fuel Gauge Hans de Goede
2017-03-17 17:58   ` Andy Shevchenko
2017-03-22 17:03     ` Hans de Goede
2017-03-20  5:07   ` Sebastian Reichel
2017-03-17  9:55 ` [PATCH 15/15] i2c-cht-wc: Add Intel Cherry Trail Whiskey Cove SMBUS controller driver Hans de Goede
2017-03-17 18:22   ` Andy Shevchenko
2017-03-23 13:58     ` Hans de Goede

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.