Module Name:    src
Committed By:   jmcneill
Date:           Mon May 27 21:10:44 UTC 2019

Modified Files:
        src/sys/dev/i2c: axppmic.c

Log Message:
Add support for AXP806


To generate a diff of this commit:
cvs rdiff -u -r1.18 -r1.19 src/sys/dev/i2c/axppmic.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/i2c/axppmic.c
diff -u src/sys/dev/i2c/axppmic.c:1.18 src/sys/dev/i2c/axppmic.c:1.19
--- src/sys/dev/i2c/axppmic.c:1.18	Wed Jan  2 18:38:03 2019
+++ src/sys/dev/i2c/axppmic.c	Mon May 27 21:10:44 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: axppmic.c,v 1.18 2019/01/02 18:38:03 jmcneill Exp $ */
+/* $NetBSD: axppmic.c,v 1.19 2019/05/27 21:10:44 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2014-2018 Jared McNeill <jmcne...@invisible.ca>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: axppmic.c,v 1.18 2019/01/02 18:38:03 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: axppmic.c,v 1.19 2019/05/27 21:10:44 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -54,6 +54,8 @@ __KERNEL_RCSID(0, "$NetBSD: axppmic.c,v 
 #define	 AXP_POWER_MODE_BATT_PRESENT	__BIT(5)
 #define	 AXP_POWER_MODE_BATT_CHARGING	__BIT(6)
 
+#define	AXP_CHIP_ID_REG		0x03
+
 #define AXP_POWER_DISABLE_REG	0x32
 #define	 AXP_POWER_DISABLE_CTRL	__BIT(7)
 
@@ -98,6 +100,10 @@ __KERNEL_RCSID(0, "$NetBSD: axppmic.c,v 
 #define	 AXP_BATT_CAP_WARN_LV1	__BITS(7,4)
 #define	 AXP_BATT_CAP_WARN_LV2	__BITS(3,0)
 
+#define	AXP_ADDR_EXT_REG	0xff	/* AXP806 */
+#define	 AXP_ADDR_EXT_MASTER	0
+#define	 AXP_ADDR_EXT_SLAVE	__BIT(4)
+
 struct axppmic_ctrl {
 	device_t	c_dev;
 
@@ -258,6 +264,7 @@ struct axppmic_config {
 	u_int irq_regs;
 	bool has_battery;
 	bool has_fuel_gauge;
+	bool has_mode_set;
 	struct axppmic_irq poklirq;
 	struct axppmic_irq acinirq;
 	struct axppmic_irq vbusirq;
@@ -339,11 +346,22 @@ static const struct axppmic_config axp80
 };
 
 static const struct axppmic_config axp805_config = {
-	.name = "AXP805/806",
+	.name = "AXP805",
+	.controls = axp805_ctrls,
+	.ncontrols = __arraycount(axp805_ctrls),
+	.irq_regs = 2,
+	.poklirq = AXPPMIC_IRQ(2, __BIT(0)),
+};
+
+static const struct axppmic_config axp806_config = {
+	.name = "AXP806",
 	.controls = axp805_ctrls,
 	.ncontrols = __arraycount(axp805_ctrls),
+#if notyet
 	.irq_regs = 2,
 	.poklirq = AXPPMIC_IRQ(2, __BIT(0)),
+#endif
+	.has_mode_set = true,
 };
 
 static const struct axppmic_config axp813_config = {
@@ -369,7 +387,7 @@ static const struct axppmic_config axp81
 static const struct device_compatible_entry compat_data[] = {
 	{ "x-powers,axp803",		(uintptr_t)&axp803_config },
 	{ "x-powers,axp805",		(uintptr_t)&axp805_config },
-	{ "x-powers,axp806",		(uintptr_t)&axp805_config },
+	{ "x-powers,axp806",		(uintptr_t)&axp806_config },
 	{ "x-powers,axp813",		(uintptr_t)&axp813_config },
 	{ NULL,				0 }
 };
@@ -808,7 +826,8 @@ axppmic_attach(device_t parent, device_t
 	struct axpreg_attach_args aaa;
 	struct i2c_attach_args *ia = aux;
 	int phandle, child, i;
-	uint32_t irq_mask;
+	uint8_t irq_mask, val;
+	int error;
 	void *ih;
 
 	(void) iic_compatible_match(ia, compat_data, &dce);
@@ -824,33 +843,54 @@ axppmic_attach(device_t parent, device_t
 	aprint_naive("\n");
 	aprint_normal(": %s\n", c->name);
 
-	sc->sc_smpsw.smpsw_name = device_xname(self);
-	sc->sc_smpsw.smpsw_type = PSWITCH_TYPE_POWER;
-	sysmon_pswitch_register(&sc->sc_smpsw);
+	if (c->has_mode_set) {
+		const bool master_mode = of_hasprop(sc->sc_phandle, "x-powers,self-working-mode") ||
+		    of_hasprop(sc->sc_phandle, "x-powers,master-mode");
+
+		iic_acquire_bus(sc->sc_i2c, I2C_F_POLL);
+		axppmic_write(sc->sc_i2c, sc->sc_addr, AXP_ADDR_EXT_REG,
+		    master_mode ? AXP_ADDR_EXT_MASTER : AXP_ADDR_EXT_SLAVE, I2C_F_POLL);
+		iic_release_bus(sc->sc_i2c, I2C_F_POLL);
+	}
 
 	iic_acquire_bus(sc->sc_i2c, I2C_F_POLL);
-	for (i = 1; i <= c->irq_regs; i++) {
-		irq_mask = 0;
-		if (i == c->poklirq.reg)
-			irq_mask |= c->poklirq.mask;
-		if (i == c->acinirq.reg)
-			irq_mask |= c->acinirq.mask;
-		if (i == c->vbusirq.reg)
-			irq_mask |= c->vbusirq.mask;
-		if (i == c->battirq.reg)
-			irq_mask |= c->battirq.mask;
-		if (i == c->chargeirq.reg)
-			irq_mask |= c->chargeirq.mask;
-		if (i == c->chargestirq.reg)
-			irq_mask |= c->chargestirq.mask;
-		axppmic_write(sc->sc_i2c, sc->sc_addr, AXP_IRQ_ENABLE_REG(i), irq_mask, I2C_F_POLL);
-	}
+	error = axppmic_read(sc->sc_i2c, sc->sc_addr, AXP_CHIP_ID_REG, &val, I2C_F_POLL);
 	iic_release_bus(sc->sc_i2c, I2C_F_POLL);
+	if (error != 0) {
+		aprint_error_dev(self, "couldn't read chipid\n");
+		return;
+	}
+	aprint_debug_dev(self, "chipid %#x\n", val);
 
-	ih = fdtbus_intr_establish(sc->sc_phandle, 0, IPL_VM, FDT_INTR_MPSAFE,
-	    axppmic_intr, sc);
-	if (ih == NULL) {
-		aprint_error_dev(self, "WARNING: couldn't establish interrupt handler\n");
+	sc->sc_smpsw.smpsw_name = device_xname(self);
+	sc->sc_smpsw.smpsw_type = PSWITCH_TYPE_POWER;
+	sysmon_pswitch_register(&sc->sc_smpsw);
+
+	if (c->irq_regs > 0) {
+		iic_acquire_bus(sc->sc_i2c, I2C_F_POLL);
+		for (i = 1; i <= c->irq_regs; i++) {
+			irq_mask = 0;
+			if (i == c->poklirq.reg)
+				irq_mask |= c->poklirq.mask;
+			if (i == c->acinirq.reg)
+				irq_mask |= c->acinirq.mask;
+			if (i == c->vbusirq.reg)
+				irq_mask |= c->vbusirq.mask;
+			if (i == c->battirq.reg)
+				irq_mask |= c->battirq.mask;
+			if (i == c->chargeirq.reg)
+				irq_mask |= c->chargeirq.mask;
+			if (i == c->chargestirq.reg)
+				irq_mask |= c->chargestirq.mask;
+			axppmic_write(sc->sc_i2c, sc->sc_addr, AXP_IRQ_ENABLE_REG(i), irq_mask, I2C_F_POLL);
+		}
+		iic_release_bus(sc->sc_i2c, I2C_F_POLL);
+
+		ih = fdtbus_intr_establish(sc->sc_phandle, 0, IPL_VM, FDT_INTR_MPSAFE,
+		    axppmic_intr, sc);
+		if (ih == NULL) {
+			aprint_error_dev(self, "WARNING: couldn't establish interrupt handler\n");
+		}
 	}
 
 	fdtbus_register_power_controller(sc->sc_dev, sc->sc_phandle,

Reply via email to