Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 3 Mar 2018 18:28:19 +0000 (UTC)
From:      Emmanuel Vadot <manu@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r330347 - head/sys/arm/allwinner
Message-ID:  <201803031828.w23ISJSA071917@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: manu
Date: Sat Mar  3 18:28:19 2018
New Revision: 330347
URL: https://svnweb.freebsd.org/changeset/base/330347

Log:
  axp81x: Add support for AXP803
  
  AXP803 and AXP813/818 are very similar, only two regulators differs.
  AXP803 is the companion chip for A64/R18
  AXP813 is the companion chip for A83T
  AXP818 is the companion chip for H8 (~A83T)
  Add support for all regulators found in both of them.

Modified:
  head/sys/arm/allwinner/axp81x.c

Modified: head/sys/arm/allwinner/axp81x.c
==============================================================================
--- head/sys/arm/allwinner/axp81x.c	Sat Mar  3 18:25:50 2018	(r330346)
+++ head/sys/arm/allwinner/axp81x.c	Sat Mar  3 18:28:19 2018	(r330347)
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2018 Emmanuel Vadot <manu@freebsd.org>
  * Copyright (c) 2016 Jared McNeill <jmcneill@invisible.ca>
  * All rights reserved.
  *
@@ -27,7 +28,7 @@
  */
 
 /*
- * X-Powers AXP813/818 PMU for Allwinner SoCs
+ * X-Powers AXP803/813/818 PMU for Allwinner SoCs
  */
 
 #include <sys/cdefs.h>
@@ -58,14 +59,59 @@ __FBSDID("$FreeBSD$");
 #include "iicbus_if.h"
 #include "regdev_if.h"
 
-MALLOC_DEFINE(M_AXP81X_REG, "AXP81x regulator", "AXP81x power regulator");
+MALLOC_DEFINE(M_AXP8XX_REG, "AXP8xx regulator", "AXP8xx power regulator");
 
+#define	AXP_POWERSRC		0x00
+#define	 AXP_POWERSRC_ACIN	(1 << 7)
+#define	 AXP_POWERSRC_VBUS	(1 << 5)
+#define	 AXP_POWERSRC_VBAT	(1 << 3)
+#define	 AXP_POWERSRC_CHARING	(1 << 2)
+#define	 AXP_POWERSRC_SHORTED	(1 << 1)
+#define	 AXP_POWERSRC_STARTUP	(1 << 0)
 #define	AXP_ICTYPE		0x03
 #define	AXP_POWERCTL1		0x10
+#define	 AXP_POWERCTL1_DCDC7	(1 << 6)	/* AXP813/818 only */
+#define	 AXP_POWERCTL1_DCDC6	(1 << 5)
+#define	 AXP_POWERCTL1_DCDC5	(1 << 4)
+#define	 AXP_POWERCTL1_DCDC4	(1 << 3)
+#define	 AXP_POWERCTL1_DCDC3	(1 << 2)
 #define	 AXP_POWERCTL1_DCDC2	(1 << 1)
+#define	 AXP_POWERCTL1_DCDC1	(1 << 0)
 #define	AXP_POWERCTL2		0x12
-#define	 AXP_POWERCTL2_DC1SW	(1 << 7)
+#define	 AXP_POWERCTL2_DC1SW	(1 << 7)	/* AXP803 only */
+#define	 AXP_POWERCTL2_DLDO4	(1 << 6)
+#define	 AXP_POWERCTL2_DLDO3	(1 << 5)
+#define	 AXP_POWERCTL2_DLDO2	(1 << 4)
+#define	 AXP_POWERCTL2_DLDO1	(1 << 3)
+#define	 AXP_POWERCTL2_ELDO3	(1 << 2)
+#define	 AXP_POWERCTL2_ELDO2	(1 << 1)
+#define	 AXP_POWERCTL2_ELDO1	(1 << 0)
+#define	AXP_POWERCTL3		0x13
+#define	 AXP_POWERCTL3_ALDO3	(1 << 7)
+#define	 AXP_POWERCTL3_ALDO2	(1 << 6)
+#define	 AXP_POWERCTL3_ALDO1	(1 << 5)
+#define	 AXP_POWERCTL3_FLDO3	(1 << 4)	/* AXP813/818 only */
+#define	 AXP_POWERCTL3_FLDO2	(1 << 3)
+#define	 AXP_POWERCTL3_FLDO1	(1 << 2)
+#define	AXP_VOLTCTL_DLDO1	0x15
+#define	AXP_VOLTCTL_DLDO2	0x16
+#define	AXP_VOLTCTL_DLDO3	0x17
+#define	AXP_VOLTCTL_DLDO4	0x18
+#define	AXP_VOLTCTL_ELDO1	0x19
+#define	AXP_VOLTCTL_ELDO2	0x1A
+#define	AXP_VOLTCTL_ELDO3	0x1B
+#define	AXP_VOLTCTL_FLDO1	0x1C
+#define	AXP_VOLTCTL_FLDO2	0x1D
+#define	AXP_VOLTCTL_DCDC1	0x20
 #define	AXP_VOLTCTL_DCDC2	0x21
+#define	AXP_VOLTCTL_DCDC3	0x22
+#define	AXP_VOLTCTL_DCDC4	0x23
+#define	AXP_VOLTCTL_DCDC5	0x24
+#define	AXP_VOLTCTL_DCDC6	0x25
+#define	AXP_VOLTCTL_DCDC7	0x26
+#define	AXP_VOLTCTL_ALDO1	0x28
+#define	AXP_VOLTCTL_ALDO2	0x29
+#define	AXP_VOLTCTL_ALDO3	0x2A
 #define	 AXP_VOLTCTL_STATUS	(1 << 7)
 #define	 AXP_VOLTCTL_MASK	0x7f
 #define	AXP_POWERBAT		0x32
@@ -92,23 +138,29 @@ MALLOC_DEFINE(M_AXP81X_REG, "AXP81x regulator", "AXP81
 static const struct {
 	const char *name;
 	uint8_t	ctrl_reg;
-} axp81x_pins[] = {
+} axp8xx_pins[] = {
 	{ "GPIO0", AXP_GPIO0_CTRL },
 	{ "GPIO1", AXP_GPIO1_CTRL },
 };
 
+enum AXP8XX_TYPE {
+	AXP803 = 1,
+	AXP813,
+};
+
 static struct ofw_compat_data compat_data[] = {
-	{ "x-powers,axp813",			1 },
-	{ "x-powers,axp818",			1 },
+	{ "x-powers,axp803",			AXP803 },
+	{ "x-powers,axp813",			AXP813 },
+	{ "x-powers,axp818",			AXP813 },
 	{ NULL,					0 }
 };
 
-static struct resource_spec axp81x_spec[] = {
+static struct resource_spec axp8xx_spec[] = {
 	{ SYS_RES_IRQ,		0,	RF_ACTIVE },
 	{ -1, 0 }
 };
 
-struct axp81x_regdef {
+struct axp8xx_regdef {
 	intptr_t		id;
 	char			*name;
 	char			*supply_name;
@@ -123,20 +175,69 @@ struct axp81x_regdef {
 	int			voltage_nstep2;
 };
 
-enum axp81x_reg_id {
-	AXP81X_REG_ID_DC1SW,
-	AXP81X_REG_ID_DCDC2,
+enum axp8xx_reg_id {
+	AXP8XX_REG_ID_DCDC1 = 100,
+	AXP8XX_REG_ID_DCDC2,
+	AXP8XX_REG_ID_DCDC3,
+	AXP8XX_REG_ID_DCDC4,
+	AXP8XX_REG_ID_DCDC5,
+	AXP8XX_REG_ID_DCDC6,
+	AXP813_REG_ID_DCDC7,
+	AXP803_REG_ID_DC1SW,
+	AXP8XX_REG_ID_DLDO1,
+	AXP8XX_REG_ID_DLDO2,
+	AXP8XX_REG_ID_DLDO3,
+	AXP8XX_REG_ID_DLDO4,
+	AXP8XX_REG_ID_ELDO1,
+	AXP8XX_REG_ID_ELDO2,
+	AXP8XX_REG_ID_ELDO3,
+	AXP8XX_REG_ID_ALDO1,
+	AXP8XX_REG_ID_ALDO2,
+	AXP8XX_REG_ID_ALDO3,
+	AXP8XX_REG_ID_FLDO1,
+	AXP8XX_REG_ID_FLDO2,
+	AXP813_REG_ID_FLDO3,
 };
 
-static struct axp81x_regdef axp81x_regdefs[] = {
+static struct axp8xx_regdef axp803_regdefs[] = {
 	{
-		.id = AXP81X_REG_ID_DC1SW,
+		.id = AXP803_REG_ID_DC1SW,
 		.name = "dc1sw",
 		.enable_reg = AXP_POWERCTL2,
 		.enable_mask = AXP_POWERCTL2_DC1SW,
 	},
+};
+
+static struct axp8xx_regdef axp813_regdefs[] = {
 	{
-		.id = AXP81X_REG_ID_DCDC2,
+		.id = AXP813_REG_ID_DCDC7,
+		.name = "dcdc7",
+		.enable_reg = AXP_POWERCTL1,
+		.enable_mask = AXP_POWERCTL1_DCDC7,
+		.voltage_reg = AXP_VOLTCTL_DCDC7,
+		.voltage_min = 600,
+		.voltage_max = 1520,
+		.voltage_step1 = 10,
+		.voltage_nstep1 = 50,
+		.voltage_step2 = 20,
+		.voltage_nstep2 = 21,
+	},
+};
+
+static struct axp8xx_regdef axp8xx_common_regdefs[] = {
+	{
+		.id = AXP8XX_REG_ID_DCDC1,
+		.name = "dcdc1",
+		.enable_reg = AXP_POWERCTL1,
+		.enable_mask = AXP_POWERCTL1_DCDC1,
+		.voltage_reg = AXP_VOLTCTL_DCDC1,
+		.voltage_min = 1600,
+		.voltage_max = 3400,
+		.voltage_step1 = 100,
+		.voltage_nstep1 = 18,
+	},
+	{
+		.id = AXP8XX_REG_ID_DCDC2,
 		.name = "dcdc2",
 		.enable_reg = AXP_POWERCTL1,
 		.enable_mask = AXP_POWERCTL1_DCDC2,
@@ -148,19 +249,197 @@ static struct axp81x_regdef axp81x_regdefs[] = {
 		.voltage_step2 = 20,
 		.voltage_nstep2 = 5,
 	},
+	{
+		.id = AXP8XX_REG_ID_DCDC3,
+		.name = "dcdc3",
+		.enable_reg = AXP_POWERCTL1,
+		.enable_mask = AXP_POWERCTL1_DCDC3,
+		.voltage_reg = AXP_VOLTCTL_DCDC3,
+		.voltage_min = 500,
+		.voltage_max = 1300,
+		.voltage_step1 = 10,
+		.voltage_nstep1 = 70,
+		.voltage_step2 = 20,
+		.voltage_nstep2 = 5,
+	},
+	{
+		.id = AXP8XX_REG_ID_DCDC4,
+		.name = "dcdc4",
+		.enable_reg = AXP_POWERCTL1,
+		.enable_mask = AXP_POWERCTL1_DCDC4,
+		.voltage_reg = AXP_VOLTCTL_DCDC4,
+		.voltage_min = 500,
+		.voltage_max = 1300,
+		.voltage_step1 = 10,
+		.voltage_nstep1 = 70,
+		.voltage_step2 = 20,
+		.voltage_nstep2 = 5,
+	},
+	{
+		.id = AXP8XX_REG_ID_DCDC5,
+		.name = "dcdc5",
+		.enable_reg = AXP_POWERCTL1,
+		.enable_mask = AXP_POWERCTL1_DCDC5,
+		.voltage_reg = AXP_VOLTCTL_DCDC5,
+		.voltage_min = 800,
+		.voltage_max = 1840,
+		.voltage_step1 = 10,
+		.voltage_nstep1 = 42,
+		.voltage_step2 = 20,
+		.voltage_nstep2 = 36,
+	},
+	{
+		.id = AXP8XX_REG_ID_DCDC6,
+		.name = "dcdc6",
+		.enable_reg = AXP_POWERCTL1,
+		.enable_mask = AXP_POWERCTL1_DCDC6,
+		.voltage_reg = AXP_VOLTCTL_DCDC6,
+		.voltage_min = 600,
+		.voltage_max = 1520,
+		.voltage_step1 = 10,
+		.voltage_nstep1 = 50,
+		.voltage_step2 = 20,
+		.voltage_nstep2 = 21,
+	},
+	{
+		.id = AXP8XX_REG_ID_DLDO1,
+		.name = "dldo1",
+		.enable_reg = AXP_POWERCTL2,
+		.enable_mask = AXP_POWERCTL2_DLDO1,
+		.voltage_reg = AXP_VOLTCTL_DLDO1,
+		.voltage_min = 700,
+		.voltage_max = 3300,
+		.voltage_step1 = 100,
+		.voltage_nstep1 = 26,
+	},
+	{
+		.id = AXP8XX_REG_ID_DLDO2,
+		.name = "dldo2",
+		.enable_reg = AXP_POWERCTL2,
+		.enable_mask = AXP_POWERCTL2_DLDO2,
+		.voltage_reg = AXP_VOLTCTL_DLDO2,
+		.voltage_min = 700,
+		.voltage_max = 4200,
+		.voltage_step1 = 100,
+		.voltage_nstep1 = 27,
+		.voltage_step2 = 200,
+		.voltage_nstep2 = 4,
+	},
+	{
+		.id = AXP8XX_REG_ID_DLDO3,
+		.name = "dldo3",
+		.enable_reg = AXP_POWERCTL2,
+		.enable_mask = AXP_POWERCTL2_DLDO3,
+		.voltage_reg = AXP_VOLTCTL_DLDO3,
+		.voltage_min = 700,
+		.voltage_max = 3300,
+		.voltage_step1 = 100,
+		.voltage_nstep1 = 26,
+	},
+	{
+		.id = AXP8XX_REG_ID_DLDO4,
+		.name = "dldo4",
+		.enable_reg = AXP_POWERCTL2,
+		.enable_mask = AXP_POWERCTL2_DLDO4,
+		.voltage_reg = AXP_VOLTCTL_DLDO4,
+		.voltage_min = 700,
+		.voltage_max = 3300,
+		.voltage_step1 = 100,
+		.voltage_nstep1 = 26,
+	},
+	{
+		.id = AXP8XX_REG_ID_ALDO1,
+		.name = "aldo1",
+		.enable_reg = AXP_POWERCTL3,
+		.enable_mask = AXP_POWERCTL3_ALDO1,
+		.voltage_min = 700,
+		.voltage_max = 3300,
+		.voltage_step1 = 100,
+		.voltage_nstep1 = 26,
+	},
+	{
+		.id = AXP8XX_REG_ID_ALDO2,
+		.name = "aldo2",
+		.enable_reg = AXP_POWERCTL3,
+		.enable_mask = AXP_POWERCTL3_ALDO2,
+		.voltage_min = 700,
+		.voltage_max = 3300,
+		.voltage_step1 = 100,
+		.voltage_nstep1 = 26,
+	},
+	{
+		.id = AXP8XX_REG_ID_ALDO3,
+		.name = "aldo3",
+		.enable_reg = AXP_POWERCTL3,
+		.enable_mask = AXP_POWERCTL3_ALDO3,
+		.voltage_min = 700,
+		.voltage_max = 3300,
+		.voltage_step1 = 100,
+		.voltage_nstep1 = 26,
+	},
+	{
+		.id = AXP8XX_REG_ID_ELDO1,
+		.name = "eldo1",
+		.enable_reg = AXP_POWERCTL2,
+		.enable_mask = AXP_POWERCTL2_ELDO1,
+		.voltage_min = 700,
+		.voltage_max = 1900,
+		.voltage_step1 = 50,
+		.voltage_nstep1 = 24,
+	},
+	{
+		.id = AXP8XX_REG_ID_ELDO2,
+		.name = "eldo2",
+		.enable_reg = AXP_POWERCTL2,
+		.enable_mask = AXP_POWERCTL2_ELDO2,
+		.voltage_min = 700,
+		.voltage_max = 1900,
+		.voltage_step1 = 50,
+		.voltage_nstep1 = 24,
+	},
+	{
+		.id = AXP8XX_REG_ID_ELDO3,
+		.name = "eldo3",
+		.enable_reg = AXP_POWERCTL2,
+		.enable_mask = AXP_POWERCTL2_ELDO3,
+		.voltage_min = 700,
+		.voltage_max = 1900,
+		.voltage_step1 = 50,
+		.voltage_nstep1 = 24,
+	},
+	{
+		.id = AXP8XX_REG_ID_FLDO1,
+		.name = "fldo1",
+		.enable_reg = AXP_POWERCTL3,
+		.enable_mask = AXP_POWERCTL3_FLDO1,
+		.voltage_min = 700,
+		.voltage_max = 1450,
+		.voltage_step1 = 50,
+		.voltage_nstep1 = 15,
+	},
+	{
+		.id = AXP8XX_REG_ID_FLDO2,
+		.name = "fldo2",
+		.enable_reg = AXP_POWERCTL3,
+		.enable_mask = AXP_POWERCTL3_FLDO2,
+		.voltage_min = 700,
+		.voltage_max = 1450,
+		.voltage_step1 = 50,
+		.voltage_nstep1 = 15,
+	},
 };
 
-struct axp81x_softc;
+struct axp8xx_softc;
 
-struct axp81x_reg_sc {
+struct axp8xx_reg_sc {
 	struct regnode		*regnode;
 	device_t		base_dev;
-	struct axp81x_regdef	*def;
+	struct axp8xx_regdef	*def;
 	phandle_t		xref;
 	struct regnode_std_param *param;
 };
 
-struct axp81x_softc {
+struct axp8xx_softc {
 	struct resource		*res;
 	uint16_t		addr;
 	void			*ih;
@@ -168,8 +447,10 @@ struct axp81x_softc {
 	struct mtx		mtx;
 	int			busy;
 
+	int			type;
+
 	/* Regulators */
-	struct axp81x_reg_sc	**regs;
+	struct axp8xx_reg_sc	**regs;
 	int			nregs;
 };
 
@@ -177,9 +458,9 @@ struct axp81x_softc {
 #define	AXP_UNLOCK(sc)	mtx_unlock(&(sc)->mtx)
 
 static int
-axp81x_read(device_t dev, uint8_t reg, uint8_t *data, uint8_t size)
+axp8xx_read(device_t dev, uint8_t reg, uint8_t *data, uint8_t size)
 {
-	struct axp81x_softc *sc;
+	struct axp8xx_softc *sc;
 	struct iic_msg msg[2];
 
 	sc = device_get_softc(dev);
@@ -198,9 +479,9 @@ axp81x_read(device_t dev, uint8_t reg, uint8_t *data, 
 }
 
 static int
-axp81x_write(device_t dev, uint8_t reg, uint8_t val)
+axp8xx_write(device_t dev, uint8_t reg, uint8_t val)
 {
-	struct axp81x_softc *sc;
+	struct axp8xx_softc *sc;
 	struct iic_msg msg[2];
 
 	sc = device_get_softc(dev);
@@ -219,25 +500,31 @@ axp81x_write(device_t dev, uint8_t reg, uint8_t val)
 }
 
 static int
-axp81x_regnode_init(struct regnode *regnode)
+axp8xx_regnode_init(struct regnode *regnode)
 {
 	return (0);
 }
 
 static int
-axp81x_regnode_enable(struct regnode *regnode, bool enable, int *udelay)
+axp8xx_regnode_enable(struct regnode *regnode, bool enable, int *udelay)
 {
-	struct axp81x_reg_sc *sc;
+	struct axp8xx_reg_sc *sc;
 	uint8_t val;
 
 	sc = regnode_get_softc(regnode);
 
-	axp81x_read(sc->base_dev, sc->def->enable_reg, &val, 1);
+	if (bootverbose)
+		device_printf(sc->base_dev, "%sable %s (%s)\n",
+		    enable ? "En" : "Dis",
+		    regnode_get_name(regnode),
+		    sc->def->name);
+
+	axp8xx_read(sc->base_dev, sc->def->enable_reg, &val, 1);
 	if (enable)
 		val |= sc->def->enable_mask;
 	else
 		val &= ~sc->def->enable_mask;
-	axp81x_write(sc->base_dev, sc->def->enable_reg, val);
+	axp8xx_write(sc->base_dev, sc->def->enable_reg, val);
 
 	*udelay = 0;
 
@@ -245,7 +532,7 @@ axp81x_regnode_enable(struct regnode *regnode, bool en
 }
 
 static void
-axp81x_regnode_reg_to_voltage(struct axp81x_reg_sc *sc, uint8_t val, int *uv)
+axp8xx_regnode_reg_to_voltage(struct axp8xx_reg_sc *sc, uint8_t val, int *uv)
 {
 	if (val < sc->def->voltage_nstep1)
 		*uv = sc->def->voltage_min + val * sc->def->voltage_step1;
@@ -257,7 +544,7 @@ axp81x_regnode_reg_to_voltage(struct axp81x_reg_sc *sc
 }
 
 static int
-axp81x_regnode_voltage_to_reg(struct axp81x_reg_sc *sc, int min_uvolt,
+axp8xx_regnode_voltage_to_reg(struct axp8xx_reg_sc *sc, int min_uvolt,
     int max_uvolt, uint8_t *val)
 {
 	uint8_t nval;
@@ -284,21 +571,27 @@ axp81x_regnode_voltage_to_reg(struct axp81x_reg_sc *sc
 }
 
 static int
-axp81x_regnode_set_voltage(struct regnode *regnode, int min_uvolt,
+axp8xx_regnode_set_voltage(struct regnode *regnode, int min_uvolt,
     int max_uvolt, int *udelay)
 {
-	struct axp81x_reg_sc *sc;
+	struct axp8xx_reg_sc *sc;
 	uint8_t val;
 
 	sc = regnode_get_softc(regnode);
 
-	if (!sc->def->voltage_step1 || !sc->def->voltage_step2)
+	if (bootverbose)
+		device_printf(sc->base_dev, "Setting %s (%s) to %d<->%d\n",
+		    regnode_get_name(regnode),
+		    sc->def->name,
+		    min_uvolt, max_uvolt);
+
+	if (sc->def->voltage_step1 == 0)
 		return (ENXIO);
 
-	if (axp81x_regnode_voltage_to_reg(sc, min_uvolt, max_uvolt, &val) != 0)
+	if (axp8xx_regnode_voltage_to_reg(sc, min_uvolt, max_uvolt, &val) != 0)
 		return (ERANGE);
 
-	axp81x_write(sc->base_dev, sc->def->voltage_reg, val);
+	axp8xx_write(sc->base_dev, sc->def->voltage_reg, val);
 
 	*udelay = 0;
 
@@ -306,9 +599,9 @@ axp81x_regnode_set_voltage(struct regnode *regnode, in
 }
 
 static int
-axp81x_regnode_get_voltage(struct regnode *regnode, int *uvolt)
+axp8xx_regnode_get_voltage(struct regnode *regnode, int *uvolt)
 {
-	struct axp81x_reg_sc *sc;
+	struct axp8xx_reg_sc *sc;
 	uint8_t val;
 
 	sc = regnode_get_softc(regnode);
@@ -316,25 +609,25 @@ axp81x_regnode_get_voltage(struct regnode *regnode, in
 	if (!sc->def->voltage_step1 || !sc->def->voltage_step2)
 		return (ENXIO);
 
-	axp81x_read(sc->base_dev, sc->def->voltage_reg, &val, 1);
-	axp81x_regnode_reg_to_voltage(sc, val & AXP_VOLTCTL_MASK, uvolt);
+	axp8xx_read(sc->base_dev, sc->def->voltage_reg, &val, 1);
+	axp8xx_regnode_reg_to_voltage(sc, val & AXP_VOLTCTL_MASK, uvolt);
 
 	return (0);
 }
 
-static regnode_method_t axp81x_regnode_methods[] = {
+static regnode_method_t axp8xx_regnode_methods[] = {
 	/* Regulator interface */
-	REGNODEMETHOD(regnode_init,		axp81x_regnode_init),
-	REGNODEMETHOD(regnode_enable,		axp81x_regnode_enable),
-	REGNODEMETHOD(regnode_set_voltage,	axp81x_regnode_set_voltage),
-	REGNODEMETHOD(regnode_get_voltage,	axp81x_regnode_get_voltage),
+	REGNODEMETHOD(regnode_init,		axp8xx_regnode_init),
+	REGNODEMETHOD(regnode_enable,		axp8xx_regnode_enable),
+	REGNODEMETHOD(regnode_set_voltage,	axp8xx_regnode_set_voltage),
+	REGNODEMETHOD(regnode_get_voltage,	axp8xx_regnode_get_voltage),
 	REGNODEMETHOD_END
 };
-DEFINE_CLASS_1(axp81x_regnode, axp81x_regnode_class, axp81x_regnode_methods,
-    sizeof(struct axp81x_reg_sc), regnode_class);
+DEFINE_CLASS_1(axp8xx_regnode, axp8xx_regnode_class, axp8xx_regnode_methods,
+    sizeof(struct axp8xx_reg_sc), regnode_class);
 
 static void
-axp81x_shutdown(void *devp, int howto)
+axp8xx_shutdown(void *devp, int howto)
 {
 	device_t dev;
 
@@ -344,13 +637,13 @@ axp81x_shutdown(void *devp, int howto)
 	dev = devp;
 
 	if (bootverbose)
-		device_printf(dev, "Shutdown AXP81x\n");
+		device_printf(dev, "Shutdown Axp8xx\n");
 
-	axp81x_write(dev, AXP_POWERBAT, AXP_POWERBAT_SHUTDOWN);
+	axp8xx_write(dev, AXP_POWERBAT, AXP_POWERBAT_SHUTDOWN);
 }
 
 static void
-axp81x_intr(void *arg)
+axp8xx_intr(void *arg)
 {
 	device_t dev;
 	uint8_t val;
@@ -358,7 +651,7 @@ axp81x_intr(void *arg)
 
 	dev = arg;
 
-	error = axp81x_read(dev, AXP_IRQSTAT5, &val, 1);
+	error = axp8xx_read(dev, AXP_IRQSTAT5, &val, 1);
 	if (error != 0)
 		return;
 
@@ -369,14 +662,14 @@ axp81x_intr(void *arg)
 			shutdown_nice(RB_POWEROFF);
 		}
 		/* Acknowledge */
-		axp81x_write(dev, AXP_IRQSTAT5, val);
+		axp8xx_write(dev, AXP_IRQSTAT5, val);
 	}
 }
 
 static device_t
-axp81x_gpio_get_bus(device_t dev)
+axp8xx_gpio_get_bus(device_t dev)
 {
-	struct axp81x_softc *sc;
+	struct axp8xx_softc *sc;
 
 	sc = device_get_softc(dev);
 
@@ -384,28 +677,28 @@ axp81x_gpio_get_bus(device_t dev)
 }
 
 static int
-axp81x_gpio_pin_max(device_t dev, int *maxpin)
+axp8xx_gpio_pin_max(device_t dev, int *maxpin)
 {
-	*maxpin = nitems(axp81x_pins) - 1;
+	*maxpin = nitems(axp8xx_pins) - 1;
 
 	return (0);
 }
 
 static int
-axp81x_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
+axp8xx_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
 {
-	if (pin >= nitems(axp81x_pins))
+	if (pin >= nitems(axp8xx_pins))
 		return (EINVAL);
 
-	snprintf(name, GPIOMAXNAME, "%s", axp81x_pins[pin].name);
+	snprintf(name, GPIOMAXNAME, "%s", axp8xx_pins[pin].name);
 
 	return (0);
 }
 
 static int
-axp81x_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
+axp8xx_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
 {
-	if (pin >= nitems(axp81x_pins))
+	if (pin >= nitems(axp8xx_pins))
 		return (EINVAL);
 
 	*caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
@@ -414,19 +707,19 @@ axp81x_gpio_pin_getcaps(device_t dev, uint32_t pin, ui
 }
 
 static int
-axp81x_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
+axp8xx_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
 {
-	struct axp81x_softc *sc;
+	struct axp8xx_softc *sc;
 	uint8_t data, func;
 	int error;
 
-	if (pin >= nitems(axp81x_pins))
+	if (pin >= nitems(axp8xx_pins))
 		return (EINVAL);
 
 	sc = device_get_softc(dev);
 
 	AXP_LOCK(sc);
-	error = axp81x_read(dev, axp81x_pins[pin].ctrl_reg, &data, 1);
+	error = axp8xx_read(dev, axp8xx_pins[pin].ctrl_reg, &data, 1);
 	if (error == 0) {
 		func = (data & AXP_GPIO_FUNC) >> AXP_GPIO_FUNC_SHIFT;
 		if (func == AXP_GPIO_FUNC_INPUT)
@@ -443,26 +736,26 @@ axp81x_gpio_pin_getflags(device_t dev, uint32_t pin, u
 }
 
 static int
-axp81x_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
+axp8xx_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
 {
-	struct axp81x_softc *sc;
+	struct axp8xx_softc *sc;
 	uint8_t data;
 	int error;
 
-	if (pin >= nitems(axp81x_pins))
+	if (pin >= nitems(axp8xx_pins))
 		return (EINVAL);
 
 	sc = device_get_softc(dev);
 
 	AXP_LOCK(sc);
-	error = axp81x_read(dev, axp81x_pins[pin].ctrl_reg, &data, 1);
+	error = axp8xx_read(dev, axp8xx_pins[pin].ctrl_reg, &data, 1);
 	if (error == 0) {
 		data &= ~AXP_GPIO_FUNC;
 		if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) != 0) {
 			if ((flags & GPIO_PIN_OUTPUT) == 0)
 				data |= AXP_GPIO_FUNC_INPUT;
 		}
-		error = axp81x_write(dev, axp81x_pins[pin].ctrl_reg, data);
+		error = axp8xx_write(dev, axp8xx_pins[pin].ctrl_reg, data);
 	}
 	AXP_UNLOCK(sc);
 
@@ -470,19 +763,19 @@ axp81x_gpio_pin_setflags(device_t dev, uint32_t pin, u
 }
 
 static int
-axp81x_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
+axp8xx_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
 {
-	struct axp81x_softc *sc;
+	struct axp8xx_softc *sc;
 	uint8_t data, func;
 	int error;
 
-	if (pin >= nitems(axp81x_pins))
+	if (pin >= nitems(axp8xx_pins))
 		return (EINVAL);
 
 	sc = device_get_softc(dev);
 
 	AXP_LOCK(sc);
-	error = axp81x_read(dev, axp81x_pins[pin].ctrl_reg, &data, 1);
+	error = axp8xx_read(dev, axp8xx_pins[pin].ctrl_reg, &data, 1);
 	if (error == 0) {
 		func = (data & AXP_GPIO_FUNC) >> AXP_GPIO_FUNC_SHIFT;
 		switch (func) {
@@ -493,7 +786,7 @@ axp81x_gpio_pin_get(device_t dev, uint32_t pin, unsign
 			*val = 1;
 			break;
 		case AXP_GPIO_FUNC_INPUT:
-			error = axp81x_read(dev, AXP_GPIO_SIGBIT, &data, 1);
+			error = axp8xx_read(dev, AXP_GPIO_SIGBIT, &data, 1);
 			if (error == 0)
 				*val = (data & (1 << pin)) ? 1 : 0;
 			break;
@@ -508,19 +801,19 @@ axp81x_gpio_pin_get(device_t dev, uint32_t pin, unsign
 }
 
 static int
-axp81x_gpio_pin_set(device_t dev, uint32_t pin, unsigned int val)
+axp8xx_gpio_pin_set(device_t dev, uint32_t pin, unsigned int val)
 {
-	struct axp81x_softc *sc;
+	struct axp8xx_softc *sc;
 	uint8_t data, func;
 	int error;
 
-	if (pin >= nitems(axp81x_pins))
+	if (pin >= nitems(axp8xx_pins))
 		return (EINVAL);
 
 	sc = device_get_softc(dev);
 
 	AXP_LOCK(sc);
-	error = axp81x_read(dev, axp81x_pins[pin].ctrl_reg, &data, 1);
+	error = axp8xx_read(dev, axp8xx_pins[pin].ctrl_reg, &data, 1);
 	if (error == 0) {
 		func = (data & AXP_GPIO_FUNC) >> AXP_GPIO_FUNC_SHIFT;
 		switch (func) {
@@ -535,7 +828,7 @@ axp81x_gpio_pin_set(device_t dev, uint32_t pin, unsign
 		}
 	}
 	if (error == 0)
-		error = axp81x_write(dev, axp81x_pins[pin].ctrl_reg, data);
+		error = axp8xx_write(dev, axp8xx_pins[pin].ctrl_reg, data);
 	AXP_UNLOCK(sc);
 
 	return (error);
@@ -543,19 +836,19 @@ axp81x_gpio_pin_set(device_t dev, uint32_t pin, unsign
 
 
 static int
-axp81x_gpio_pin_toggle(device_t dev, uint32_t pin)
+axp8xx_gpio_pin_toggle(device_t dev, uint32_t pin)
 {
-	struct axp81x_softc *sc;
+	struct axp8xx_softc *sc;
 	uint8_t data, func;
 	int error;
 
-	if (pin >= nitems(axp81x_pins))
+	if (pin >= nitems(axp8xx_pins))
 		return (EINVAL);
 
 	sc = device_get_softc(dev);
 
 	AXP_LOCK(sc);
-	error = axp81x_read(dev, axp81x_pins[pin].ctrl_reg, &data, 1);
+	error = axp8xx_read(dev, axp8xx_pins[pin].ctrl_reg, &data, 1);
 	if (error == 0) {
 		func = (data & AXP_GPIO_FUNC) >> AXP_GPIO_FUNC_SHIFT;
 		switch (func) {
@@ -573,17 +866,17 @@ axp81x_gpio_pin_toggle(device_t dev, uint32_t pin)
 		}
 	}
 	if (error == 0)
-		error = axp81x_write(dev, axp81x_pins[pin].ctrl_reg, data);
+		error = axp8xx_write(dev, axp8xx_pins[pin].ctrl_reg, data);
 	AXP_UNLOCK(sc);
 
 	return (error);
 }
 
 static int
-axp81x_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent,
+axp8xx_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent,
     int gcells, pcell_t *gpios, uint32_t *pin, uint32_t *flags)
 {
-	if (gpios[0] >= nitems(axp81x_pins))
+	if (gpios[0] >= nitems(axp8xx_pins))
 		return (EINVAL);
 
 	*pin = gpios[0];
@@ -593,16 +886,16 @@ axp81x_gpio_map_gpios(device_t bus, phandle_t dev, pha
 }
 
 static phandle_t
-axp81x_get_node(device_t dev, device_t bus)
+axp8xx_get_node(device_t dev, device_t bus)
 {
 	return (ofw_bus_get_node(dev));
 }
 
-static struct axp81x_reg_sc *
-axp81x_reg_attach(device_t dev, phandle_t node,
-    struct axp81x_regdef *def)
+static struct axp8xx_reg_sc *
+axp8xx_reg_attach(device_t dev, phandle_t node,
+    struct axp8xx_regdef *def)
 {
-	struct axp81x_reg_sc *reg_sc;
+	struct axp8xx_reg_sc *reg_sc;
 	struct regnode_init_def initdef;
 	struct regnode *regnode;
 
@@ -614,7 +907,7 @@ axp81x_reg_attach(device_t dev, phandle_t node,
 		initdef.std_param.max_uvolt = def->voltage_max * 1000;
 	initdef.id = def->id;
 	initdef.ofw_node = node;
-	regnode = regnode_create(dev, &axp81x_regnode_class, &initdef);
+	regnode = regnode_create(dev, &axp8xx_regnode_class, &initdef);
 	if (regnode == NULL) {
 		device_printf(dev, "cannot create regulator\n");
 		return (NULL);
@@ -633,10 +926,10 @@ axp81x_reg_attach(device_t dev, phandle_t node,
 }
 
 static int
-axp81x_regdev_map(device_t dev, phandle_t xref, int ncells, pcell_t *cells,
+axp8xx_regdev_map(device_t dev, phandle_t xref, int ncells, pcell_t *cells,
     intptr_t *num)
 {
-	struct axp81x_softc *sc;
+	struct axp8xx_softc *sc;
 	int i;
 
 	sc = device_get_softc(dev);
@@ -653,24 +946,31 @@ axp81x_regdev_map(device_t dev, phandle_t xref, int nc
 }
 
 static int
-axp81x_probe(device_t dev)
+axp8xx_probe(device_t dev)
 {
 	if (!ofw_bus_status_okay(dev))
 		return (ENXIO);
 
-	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+	switch (ofw_bus_search_compatible(dev, compat_data)->ocd_data)
+	{
+	case AXP803:
+		device_set_desc(dev, "X-Powers AXP803 Power Management Unit");
+		break;
+	case AXP813:
+		device_set_desc(dev, "X-Powers AXP813 Power Management Unit");
+		break;
+	default:
 		return (ENXIO);
+	}
 
-	device_set_desc(dev, "X-Powers AXP81x Power Management Unit");
-
 	return (BUS_PROBE_DEFAULT);
 }
 
 static int
-axp81x_attach(device_t dev)
+axp8xx_attach(device_t dev)
 {
-	struct axp81x_softc *sc;
-	struct axp81x_reg_sc *reg;
+	struct axp8xx_softc *sc;
+	struct axp8xx_reg_sc *reg;
 	uint8_t chip_id;
 	phandle_t rnode, child;
 	int error, i;
@@ -680,34 +980,65 @@ axp81x_attach(device_t dev)
 	sc->addr = iicbus_get_addr(dev);
 	mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
 
-	error = bus_alloc_resources(dev, axp81x_spec, &sc->res);
+	error = bus_alloc_resources(dev, axp8xx_spec, &sc->res);
 	if (error != 0) {
 		device_printf(dev, "cannot allocate resources for device\n");
 		return (error);
 	}
 
 	if (bootverbose) {
-		axp81x_read(dev, AXP_ICTYPE, &chip_id, 1);
+		axp8xx_read(dev, AXP_ICTYPE, &chip_id, 1);
 		device_printf(dev, "chip ID 0x%02x\n", chip_id);
 	}
 
-	sc->nregs = nitems(axp81x_regdefs);
-	sc->regs = malloc(sizeof(struct axp81x_reg_sc *) * sc->nregs,
-	    M_AXP81X_REG, M_WAITOK | M_ZERO);
+	sc->nregs = nitems(axp8xx_common_regdefs);
+	sc->type = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
+	switch (sc->type) {
+	case AXP803:
+		sc->nregs += nitems(axp803_regdefs);
+		break;
+	case AXP813:
+		sc->nregs += nitems(axp813_regdefs);
+		break;
+	}
+	sc->regs = malloc(sizeof(struct axp8xx_reg_sc *) * sc->nregs,
+	    M_AXP8XX_REG, M_WAITOK | M_ZERO);
 
 	/* Attach known regulators that exist in the DT */
 	rnode = ofw_bus_find_child(ofw_bus_get_node(dev), "regulators");
 	if (rnode > 0) {
 		for (i = 0; i < sc->nregs; i++) {
+			char *regname;
+			struct axp8xx_regdef *regdef;
+
+			if (i <= nitems(axp8xx_common_regdefs)) {
+				regname = axp8xx_common_regdefs[i].name;
+				regdef = &axp8xx_common_regdefs[i];
+			} else {
+				int off;
+
+				off = i - nitems(axp8xx_common_regdefs);
+				switch (sc->type) {
+				case AXP803:
+					regname = axp803_regdefs[off].name;
+					regdef = &axp803_regdefs[off];
+					break;
+				case AXP813:
+					regname = axp813_regdefs[off].name;
+					regdef = &axp813_regdefs[off];
+					break;
+				}
+			}
 			child = ofw_bus_find_child(rnode,
-			    axp81x_regdefs[i].name);
+			    regname);
 			if (child == 0)
 				continue;
-			reg = axp81x_reg_attach(dev, child, &axp81x_regdefs[i]);
+			reg = axp8xx_reg_attach(dev, child,
+			    regdef);
 			if (reg == NULL) {
 				device_printf(dev,
 				    "cannot attach regulator %s\n",
-				    axp81x_regdefs[i].name);
+				    regname);
 				return (ENXIO);
 			}
 			sc->regs[i] = reg;
@@ -715,22 +1046,22 @@ axp81x_attach(device_t dev)
 	}
 
 	/* Enable IRQ on short power key press */
-	axp81x_write(dev, AXP_IRQEN1, 0);
-	axp81x_write(dev, AXP_IRQEN2, 0);
-	axp81x_write(dev, AXP_IRQEN3, 0);
-	axp81x_write(dev, AXP_IRQEN4, 0);
-	axp81x_write(dev, AXP_IRQEN5, AXP_IRQEN5_POKSIRQ);
-	axp81x_write(dev, AXP_IRQEN6, 0);
+	axp8xx_write(dev, AXP_IRQEN1, 0);
+	axp8xx_write(dev, AXP_IRQEN2, 0);
+	axp8xx_write(dev, AXP_IRQEN3, 0);
+	axp8xx_write(dev, AXP_IRQEN4, 0);
+	axp8xx_write(dev, AXP_IRQEN5, AXP_IRQEN5_POKSIRQ);
+	axp8xx_write(dev, AXP_IRQEN6, 0);
 
 	/* Install interrupt handler */
 	error = bus_setup_intr(dev, sc->res, INTR_TYPE_MISC | INTR_MPSAFE,
-	    NULL, axp81x_intr, dev, &sc->ih);
+	    NULL, axp8xx_intr, dev, &sc->ih);
 	if (error != 0) {
 		device_printf(dev, "cannot setup interrupt handler\n");
 		return (error);
 	}
 
-	EVENTHANDLER_REGISTER(shutdown_final, axp81x_shutdown, dev,
+	EVENTHANDLER_REGISTER(shutdown_final, axp8xx_shutdown, dev,
 	    SHUTDOWN_PRI_LAST);
 
 	sc->gpiodev = gpiobus_attach_bus(dev);
@@ -738,46 +1069,46 @@ axp81x_attach(device_t dev)

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201803031828.w23ISJSA071917>