diff mbox series

[09/10] power: supply: axp20x_usb_power: Add support for AXP192

Message ID 20220603135714.12007-10-aidanmacdonald.0x0@gmail.com
State Superseded
Headers show
Series Add support for AXP192 PMIC | expand

Commit Message

Aidan MacDonald June 3, 2022, 1:57 p.m. UTC
The AXP192 is mostly the same as the AXP202 but has a different
current limit.

Signed-off-by: Aidan MacDonald <aidanmacdonald.0x0@gmail.com>
---
 drivers/power/supply/axp20x_usb_power.c | 75 +++++++++++++++++++++++--
 1 file changed, 70 insertions(+), 5 deletions(-)

Comments

kernel test robot June 5, 2022, 3:13 p.m. UTC | #1
Hi Aidan,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on lee-mfd/for-mfd-next]
[also build test WARNING on linusw-pinctrl/devel broonie-regmap/for-next jic23-iio/togreg sre-power-supply/for-next v5.18 next-20220603]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/intel-lab-lkp/linux/commits/Aidan-MacDonald/Add-support-for-AXP192-PMIC/20220605-165501
base:   https://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git for-mfd-next
config: riscv-randconfig-r023-20220605 (https://download.01.org/0day-ci/archive/20220605/202206052337.XAGi8JAq-lkp@intel.com/config)
compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project 416a5080d89066029f9889dc23f94de47c2fa895)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install riscv cross compiling tool for clang build
        # apt-get install binutils-riscv64-linux-gnu
        # https://github.com/intel-lab-lkp/linux/commit/1eaea00a34314bd851023b9feeea16d1219174a3
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Aidan-MacDonald/Add-support-for-AXP192-PMIC/20220605-165501
        git checkout 1eaea00a34314bd851023b9feeea16d1219174a3
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=riscv SHELL=/bin/bash drivers/power/supply/

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   In file included from drivers/power/supply/axp20x_usb_power.c:13:
   In file included from include/linux/interrupt.h:11:
   In file included from include/linux/hardirq.h:11:
   In file included from ./arch/riscv/include/generated/asm/hardirq.h:1:
   In file included from include/asm-generic/hardirq.h:17:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:136:
   include/asm-generic/io.h:464:31: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           val = __raw_readb(PCI_IOBASE + addr);
                             ~~~~~~~~~~ ^
   include/asm-generic/io.h:477:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           val = __le16_to_cpu((__le16 __force)__raw_readw(PCI_IOBASE + addr));
                                                           ~~~~~~~~~~ ^
   include/uapi/linux/byteorder/little_endian.h:37:51: note: expanded from macro '__le16_to_cpu'
   #define __le16_to_cpu(x) ((__force __u16)(__le16)(x))
                                                     ^
   In file included from drivers/power/supply/axp20x_usb_power.c:13:
   In file included from include/linux/interrupt.h:11:
   In file included from include/linux/hardirq.h:11:
   In file included from ./arch/riscv/include/generated/asm/hardirq.h:1:
   In file included from include/asm-generic/hardirq.h:17:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:136:
   include/asm-generic/io.h:490:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           val = __le32_to_cpu((__le32 __force)__raw_readl(PCI_IOBASE + addr));
                                                           ~~~~~~~~~~ ^
   include/uapi/linux/byteorder/little_endian.h:35:51: note: expanded from macro '__le32_to_cpu'
   #define __le32_to_cpu(x) ((__force __u32)(__le32)(x))
                                                     ^
   In file included from drivers/power/supply/axp20x_usb_power.c:13:
   In file included from include/linux/interrupt.h:11:
   In file included from include/linux/hardirq.h:11:
   In file included from ./arch/riscv/include/generated/asm/hardirq.h:1:
   In file included from include/asm-generic/hardirq.h:17:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:136:
   include/asm-generic/io.h:501:33: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           __raw_writeb(value, PCI_IOBASE + addr);
                               ~~~~~~~~~~ ^
   include/asm-generic/io.h:511:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           __raw_writew((u16 __force)cpu_to_le16(value), PCI_IOBASE + addr);
                                                         ~~~~~~~~~~ ^
   include/asm-generic/io.h:521:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           __raw_writel((u32 __force)cpu_to_le32(value), PCI_IOBASE + addr);
                                                         ~~~~~~~~~~ ^
   include/asm-generic/io.h:1024:55: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           return (port > MMIO_UPPER_LIMIT) ? NULL : PCI_IOBASE + port;
                                                     ~~~~~~~~~~ ^
>> drivers/power/supply/axp20x_usb_power.c:300:3: warning: unannotated fall-through between switch labels [-Wimplicit-fallthrough]
                   default:
                   ^
   drivers/power/supply/axp20x_usb_power.c:300:3: note: insert 'break;' to avoid fall-through
                   default:
                   ^
                   break; 
   8 warnings generated.

Kconfig warnings: (for reference only)
   WARNING: unmet direct dependencies detected for RISCV_SBI_CPUIDLE
   Depends on CPU_IDLE && RISCV && RISCV_SBI
   Selected by
   - SOC_VIRT && CPU_IDLE


vim +300 drivers/power/supply/axp20x_usb_power.c

   198	
   199	static int axp20x_usb_power_get_property(struct power_supply *psy,
   200		enum power_supply_property psp, union power_supply_propval *val)
   201	{
   202		struct axp20x_usb_power *power = power_supply_get_drvdata(psy);
   203		unsigned int input, v, reg;
   204		int ret;
   205	
   206		switch (psp) {
   207		case POWER_SUPPLY_PROP_VOLTAGE_MIN:
   208			ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v);
   209			if (ret)
   210				return ret;
   211	
   212			val->intval = AXP20X_VBUS_VHOLD_uV(v);
   213			return 0;
   214		case POWER_SUPPLY_PROP_VOLTAGE_NOW:
   215			if (IS_ENABLED(CONFIG_AXP20X_ADC)) {
   216				ret = iio_read_channel_processed(power->vbus_v,
   217								 &val->intval);
   218				if (ret)
   219					return ret;
   220	
   221				/*
   222				 * IIO framework gives mV but Power Supply framework
   223				 * gives uV.
   224				 */
   225				val->intval *= 1000;
   226				return 0;
   227			}
   228	
   229			ret = axp20x_read_variable_width(power->regmap,
   230							 AXP20X_VBUS_V_ADC_H, 12);
   231			if (ret < 0)
   232				return ret;
   233	
   234			val->intval = ret * 1700; /* 1 step = 1.7 mV */
   235			return 0;
   236		case POWER_SUPPLY_PROP_CURRENT_MAX:
   237			if (power->axp20x_id == AXP813_ID)
   238				return axp813_get_current_max(power, &val->intval);
   239			else if (power->axp20x_id == AXP192_ID)
   240				return axp192_get_current_max(power, &val->intval);
   241			return axp20x_get_current_max(power, &val->intval);
   242		case POWER_SUPPLY_PROP_CURRENT_NOW:
   243			if (IS_ENABLED(CONFIG_AXP20X_ADC)) {
   244				ret = iio_read_channel_processed(power->vbus_i,
   245								 &val->intval);
   246				if (ret)
   247					return ret;
   248	
   249				/*
   250				 * IIO framework gives mA but Power Supply framework
   251				 * gives uA.
   252				 */
   253				val->intval *= 1000;
   254				return 0;
   255			}
   256	
   257			ret = axp20x_read_variable_width(power->regmap,
   258							 AXP20X_VBUS_I_ADC_H, 12);
   259			if (ret < 0)
   260				return ret;
   261	
   262			val->intval = ret * 375; /* 1 step = 0.375 mA */
   263			return 0;
   264		default:
   265			break;
   266		}
   267	
   268		/* All the properties below need the input-status reg value */
   269		ret = regmap_read(power->regmap, AXP20X_PWR_INPUT_STATUS, &input);
   270		if (ret)
   271			return ret;
   272	
   273		switch (psp) {
   274		case POWER_SUPPLY_PROP_HEALTH:
   275			if (!(input & AXP20X_PWR_STATUS_VBUS_PRESENT)) {
   276				val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;
   277				break;
   278			}
   279	
   280			val->intval = POWER_SUPPLY_HEALTH_GOOD;
   281	
   282			switch (power->axp20x_id) {
   283			case AXP192_ID:
   284				/* Same layout as the AXP202, but different address */
   285				reg = AXP192_USB_OTG_STATUS;
   286				fallthrough;
   287	
   288			case AXP202_ID:
   289				if (power->axp20x_id == AXP202_ID)
   290					reg = AXP20X_USB_OTG_STATUS;
   291	
   292				ret = regmap_read(power->regmap, reg, &v);
   293				if (ret)
   294					return ret;
   295	
   296				if (!(v & AXP20X_USB_STATUS_VBUS_VALID))
   297					val->intval =
   298						POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
   299	
 > 300			default:
   301				break;
   302			}
   303			break;
   304		case POWER_SUPPLY_PROP_PRESENT:
   305			val->intval = !!(input & AXP20X_PWR_STATUS_VBUS_PRESENT);
   306			break;
   307		case POWER_SUPPLY_PROP_ONLINE:
   308			val->intval = !!(input & AXP20X_PWR_STATUS_VBUS_USED);
   309			break;
   310		default:
   311			return -EINVAL;
   312		}
   313	
   314		return 0;
   315	}
   316
diff mbox series

Patch

diff --git a/drivers/power/supply/axp20x_usb_power.c b/drivers/power/supply/axp20x_usb_power.c
index a1e6d1d44808..e1266b8265bc 100644
--- a/drivers/power/supply/axp20x_usb_power.c
+++ b/drivers/power/supply/axp20x_usb_power.c
@@ -48,6 +48,9 @@ 
 #define AXP813_VBUS_CLIMIT_2000mA	2
 #define AXP813_VBUS_CLIMIT_2500mA	3
 
+#define AXP192_VBUS_CLIMIT_EN		BIT(1)
+#define AXP192_VBUS_CLIMIT_100mA	BIT(0)
+
 #define AXP20X_ADC_EN1_VBUS_CURR	BIT(2)
 #define AXP20X_ADC_EN1_VBUS_VOLT	BIT(3)
 
@@ -121,6 +124,24 @@  static void axp20x_usb_power_poll_vbus(struct work_struct *work)
 		mod_delayed_work(system_power_efficient_wq, &power->vbus_detect, DEBOUNCE_TIME);
 }
 
+static int axp192_get_current_max(struct axp20x_usb_power *power, int *val)
+{
+	unsigned int v;
+	int ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v);
+
+	if (ret)
+		return ret;
+
+	if (!(v & AXP192_VBUS_CLIMIT_EN))
+		*val = -1;
+	else if (v & AXP192_VBUS_CLIMIT_100mA)
+		*val = 100000;
+	else
+		*val = 500000;
+
+	return 0;
+}
+
 static int axp20x_get_current_max(struct axp20x_usb_power *power, int *val)
 {
 	unsigned int v;
@@ -179,7 +200,7 @@  static int axp20x_usb_power_get_property(struct power_supply *psy,
 	enum power_supply_property psp, union power_supply_propval *val)
 {
 	struct axp20x_usb_power *power = power_supply_get_drvdata(psy);
-	unsigned int input, v;
+	unsigned int input, v, reg;
 	int ret;
 
 	switch (psp) {
@@ -215,6 +236,8 @@  static int axp20x_usb_power_get_property(struct power_supply *psy,
 	case POWER_SUPPLY_PROP_CURRENT_MAX:
 		if (power->axp20x_id == AXP813_ID)
 			return axp813_get_current_max(power, &val->intval);
+		else if (power->axp20x_id == AXP192_ID)
+			return axp192_get_current_max(power, &val->intval);
 		return axp20x_get_current_max(power, &val->intval);
 	case POWER_SUPPLY_PROP_CURRENT_NOW:
 		if (IS_ENABLED(CONFIG_AXP20X_ADC)) {
@@ -256,15 +279,26 @@  static int axp20x_usb_power_get_property(struct power_supply *psy,
 
 		val->intval = POWER_SUPPLY_HEALTH_GOOD;
 
-		if (power->axp20x_id == AXP202_ID) {
-			ret = regmap_read(power->regmap,
-					  AXP20X_USB_OTG_STATUS, &v);
+		switch (power->axp20x_id) {
+		case AXP192_ID:
+			/* Same layout as the AXP202, but different address */
+			reg = AXP192_USB_OTG_STATUS;
+			fallthrough;
+
+		case AXP202_ID:
+			if (power->axp20x_id == AXP202_ID)
+				reg = AXP20X_USB_OTG_STATUS;
+
+			ret = regmap_read(power->regmap, reg, &v);
 			if (ret)
 				return ret;
 
 			if (!(v & AXP20X_USB_STATUS_VBUS_VALID))
 				val->intval =
 					POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+
+		default:
+			break;
 		}
 		break;
 	case POWER_SUPPLY_PROP_PRESENT:
@@ -316,6 +350,24 @@  static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,
 	return -EINVAL;
 }
 
+static int axp192_usb_power_set_current_max(struct axp20x_usb_power *power,
+					    int intval)
+{
+	int val = AXP192_VBUS_CLIMIT_EN;
+	const int mask = AXP192_VBUS_CLIMIT_EN | AXP192_VBUS_CLIMIT_100mA;
+
+	switch (intval) {
+	case 100000:
+		val |= AXP192_VBUS_CLIMIT_100mA;
+		fallthrough;
+	case 500000:
+		return regmap_update_bits(power->regmap,
+					  AXP20X_VBUS_IPSOUT_MGMT, mask, val);
+	default:
+		return -EINVAL;
+	}
+}
+
 static int axp813_usb_power_set_current_max(struct axp20x_usb_power *power,
 					    int intval)
 {
@@ -383,6 +435,9 @@  static int axp20x_usb_power_set_property(struct power_supply *psy,
 		if (power->axp20x_id == AXP813_ID)
 			return axp813_usb_power_set_current_max(power,
 								val->intval);
+		else if (power->axp20x_id == AXP192_ID)
+			return axp192_usb_power_set_current_max(power,
+								val->intval);
 		return axp20x_usb_power_set_current_max(power, val->intval);
 
 	default:
@@ -468,6 +523,13 @@  struct axp_data {
 	enum axp20x_variants		axp20x_id;
 };
 
+static const struct axp_data axp192_data = {
+	.power_desc	= &axp20x_usb_power_desc,
+	.irq_names	= axp20x_irq_names,
+	.num_irq_names	= ARRAY_SIZE(axp20x_irq_names),
+	.axp20x_id	= AXP192_ID,
+};
+
 static const struct axp_data axp202_data = {
 	.power_desc	= &axp20x_usb_power_desc,
 	.irq_names	= axp20x_irq_names,
@@ -600,7 +662,7 @@  static int axp20x_usb_power_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	if (power->axp20x_id == AXP202_ID) {
+	if (power->axp20x_id == AXP192_ID || power->axp20x_id == AXP202_ID) {
 		/* Enable vbus valid checking */
 		ret = regmap_update_bits(power->regmap, AXP20X_VBUS_MON,
 					 AXP20X_VBUS_MON_VBUS_VALID,
@@ -659,6 +721,9 @@  static int axp20x_usb_power_probe(struct platform_device *pdev)
 
 static const struct of_device_id axp20x_usb_power_match[] = {
 	{
+		.compatible = "x-powers,axp192-usb-power-supply",
+		.data = &axp192_data,
+	}, {
 		.compatible = "x-powers,axp202-usb-power-supply",
 		.data = &axp202_data,
 	}, {