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>