Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/i2c Implement sensor reports for power supplies (vol...
details: https://anonhg.NetBSD.org/src/rev/8dbb8f7e29d2
branches: trunk
changeset: 341047:8dbb8f7e29d2
user: bouyer <bouyer%NetBSD.org@localhost>
date: Thu Oct 15 13:41:11 2015 +0000
description:
Implement sensor reports for power supplies (voltage and intensities).
Implement a callback to change DCDC2 and DCDC3 voltages, so that
CPU management can change CPU core voltage when changing frequency.
diffstat:
sys/dev/i2c/axp20x.c | 486 +++++++++++++++++++++++++++++++++++++++++++++--
sys/dev/i2c/axp20xvar.h | 35 +++
2 files changed, 499 insertions(+), 22 deletions(-)
diffs (truncated from 597 to 300 lines):
diff -r 1d057490c779 -r 8dbb8f7e29d2 sys/dev/i2c/axp20x.c
--- a/sys/dev/i2c/axp20x.c Thu Oct 15 13:35:30 2015 +0000
+++ b/sys/dev/i2c/axp20x.c Thu Oct 15 13:41:11 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: axp20x.c,v 1.2 2014/09/09 23:39:16 jmcneill Exp $ */
+/* $NetBSD: axp20x.c,v 1.3 2015/10/15 13:41:11 bouyer Exp $ */
/*-
* Copyright (c) 2014 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: axp20x.c,v 1.2 2014/09/09 23:39:16 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: axp20x.c,v 1.3 2015/10/15 13:41:11 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -37,25 +37,136 @@
#include <sys/kmem.h>
#include <dev/i2c/i2cvar.h>
+#include <dev/i2c/axp20xvar.h>
#include <dev/sysmon/sysmonvar.h>
+#define AXP_INPUT_STATUS 0x00
+#define AXP_INPUT_STATUS_AC_PRESENT __BIT(7)
+#define AXP_INPUT_STATUS_AC_OK __BIT(6)
+#define AXP_INPUT_STATUS_VBUS_PRESENT __BIT(5)
+#define AXP_INPUT_STATUS_VBUS_OK __BIT(4)
+
+#define AXP_POWER_MODE 0x01
+#define AXP_POWER_MODE_OVERTEMP __BIT(7)
+#define AXP_POWER_MODE_CHARGING __BIT(6)
+#define AXP_POWER_MODE_BATTOK __BIT(5)
+
+#define AXP_POWEROUT_CTRL 0x12
+#define AXP_POWEROUT_CTRL_LDO3 __BIT(6)
+#define AXP_POWEROUT_CTRL_DCDC2 __BIT(4)
+#define AXP_POWEROUT_CTRL_LDO4 __BIT(3)
+#define AXP_POWEROUT_CTRL_LDO2 __BIT(2)
+#define AXP_POWEROUT_CTRL_DCDC3 __BIT(1)
+#define AXP_POWEROUT_CTRL_EXTEN __BIT(0)
+
+#define AXP_DCDC2 0x23
+#define AXP_DCDC2_VOLT_MASK __BITS(0,5)
+#define AXP_DCDC2_VOLT_SHIFT 0
+
+#define AXP_DCDC2_LDO3_VRC 0x25
+
+#define AXP_DCDC3 0x27
+#define AXP_DCDC3_VOLT_MASK __BITS(0,6)
+#define AXP_DCDC3_VOLT_SHIFT 0
+
+#define AXP_LDO2_4 0x28
+#define AXP_LDO2_VOLT_MASK __BITS(4,7)
+#define AXP_LDO2_VOLT_SHIFT 4
+#define AXP_LDO4_VOLT_MASK __BITS(0,3)
+#define AXP_LDO4_VOLT_SHIFT 0
+static int ldo4_mvV[] = {
+ 1250,
+ 1300,
+ 1400,
+ 1500,
+ 1600,
+ 1700,
+ 1800,
+ 1900,
+ 2000,
+ 2500,
+ 2700,
+ 2800,
+ 3000,
+ 3100,
+ 3200,
+ 3300
+};
+
+#define AXP_LDO3 0x29
+#define AXP_LDO3_TRACK __BIT(7)
+#define AXP_LDO3_VOLT_MASK __BITS(0,6)
+#define AXP_LDO3_VOLT_SHIFT 0
+
+#define AXP_ACV_MON_REG 0x56 /* 2 bytes */
+#define AXP_ACI_MON_REG 0x58 /* 2 bytes */
+#define AXP_VBUSV_MON_REG 0x5a /* 2 bytes */
+#define AXP_VBUSI_MON_REG 0x5c /* 2 bytes */
#define AXP_TEMP_MON_REG 0x5e /* 2 bytes */
+#define AXP_BATTV_MON_REG 0x78 /* 2 bytes */
+#define AXP_BATTCI_MON_REG 0x7a /* 2 bytes */
+#define AXP_BATTDI_MON_REG 0x7c /* 2 bytes */
+#define AXP_APSV_MON_REG 0x7e /* 2 bytes */
+
+#define AXP_ADC_EN1 0x82
+#define AXP_ADC_EN1_BATTV __BIT(7)
+#define AXP_ADC_EN1_BATTI __BIT(6)
+#define AXP_ADC_EN1_ACV __BIT(5)
+#define AXP_ADC_EN1_ACI __BIT(4)
+#define AXP_ADC_EN1_VBUSV __BIT(3)
+#define AXP_ADC_EN1_VBUSI __BIT(2)
+#define AXP_ADC_EN1_APSV __BIT(1)
+#define AXP_ADC_EN1_TS __BIT(0)
+#define AXP_ADC_EN2 0x83
+#define AXP_ADC_EN2_TEMP __BIT(7)
+
+#define AXP_SENSOR_ACOK 0
+#define AXP_SENSOR_ACV 1
+#define AXP_SENSOR_ACI 2
+#define AXP_SENSOR_VBUSOK 3
+#define AXP_SENSOR_VBUSV 4
+#define AXP_SENSOR_VBUSI 5
+#define AXP_SENSOR_BATTOK 6
+#define AXP_SENSOR_BATTV 7
+#define AXP_SENSOR_BATTI 8
+#define AXP_SENSOR_APSV 9
+#define AXP_SENSOR_TEMP 10
+#define AXP_NSENSORS (AXP_SENSOR_TEMP + 1)
+
+/* define per-ADC LSB to uV/uA values */
+static int axp20x_sensors_lsb[] = {
+ 0, /* AXP_SENSOR_ACOK */
+ 1700, /* AXP_SENSOR_ACV */
+ 625, /* AXP_SENSOR_ACI */
+ 0,
+ 1700, /* AXP_SENSOR_VBUSV */
+ 375, /* AXP_SENSOR_VBUSI */
+ 0,
+ 1100, /* AXP_SENSOR_BATTV */
+ 500, /* AXP_SENSOR_BATTI */
+ 1400, /* AXP_SENSOR_APSV */
+};
+
struct axp20x_softc {
device_t sc_dev;
i2c_tag_t sc_i2c;
i2c_addr_t sc_addr;
+ uint8_t sc_inputstatus;
+ uint8_t sc_powermode;
+
struct sysmon_envsys *sc_sme;
- envsys_data_t sc_sensor_temp;
+ envsys_data_t sc_sensor[AXP_NSENSORS];
};
static int axp20x_match(device_t, cfdata_t, void *);
static void axp20x_attach(device_t, device_t, void *);
static void axp20x_sensors_refresh(struct sysmon_envsys *, envsys_data_t *);
-static int axp20x_read(struct axp20x_softc *, uint8_t, uint8_t *, size_t);
+static int axp20x_read(struct axp20x_softc *, uint8_t, uint8_t *, size_t, int);
+static int axp20x_write(struct axp20x_softc *, uint8_t, uint8_t *, size_t, int);
CFATTACH_DECL_NEW(axp20x, sizeof(struct axp20x_softc),
axp20x_match, axp20x_attach, NULL, NULL);
@@ -71,12 +182,65 @@
{
struct axp20x_softc *sc = device_private(self);
struct i2c_attach_args *ia = aux;
+ int first;
+ int error;
+ uint8_t value;
sc->sc_dev = self;
sc->sc_i2c = ia->ia_tag;
sc->sc_addr = ia->ia_addr;
+ error = axp20x_read(sc, AXP_INPUT_STATUS,
+ &sc->sc_inputstatus, 1, I2C_F_POLL);
+ if (error) {
+ aprint_error(": can't read status: %d\n", error);
+ return;
+ }
+ error = axp20x_read(sc, AXP_POWER_MODE,
+ &sc->sc_powermode, 1, I2C_F_POLL);
+ if (error) {
+ aprint_error(": can't read power mode: %d\n", error);
+ return;
+ }
+ value = AXP_ADC_EN1_ACV | AXP_ADC_EN1_ACI | AXP_ADC_EN1_VBUSV | AXP_ADC_EN1_VBUSI | AXP_ADC_EN1_APSV | AXP_ADC_EN1_TS;
+ if (sc->sc_powermode & AXP_POWER_MODE_BATTOK)
+ value |= AXP_ADC_EN1_BATTV | AXP_ADC_EN1_BATTI;
+ error = axp20x_write(sc, AXP_ADC_EN1, &value, 1, I2C_F_POLL);
+ if (error) {
+ aprint_error(": can't set AXP_ADC_EN1\n");
+ return;
+ }
+ error = axp20x_read(sc, AXP_ADC_EN2, &value, 1, I2C_F_POLL);
+ if (error) {
+ aprint_error(": can't read AXP_ADC_EN2\n");
+ return;
+ }
+ value |= AXP_ADC_EN2_TEMP;
+ error = axp20x_write(sc, AXP_ADC_EN2, &value, 1, I2C_F_POLL);
+ if (error) {
+ aprint_error(": can't set AXP_ADC_EN2\n");
+ return;
+ }
+
aprint_naive("\n");
+ first = 1;
+ if (sc->sc_inputstatus & AXP_INPUT_STATUS_AC_OK) {
+ aprint_normal(": AC used");
+ first = 0;
+ } else if (sc->sc_inputstatus & AXP_INPUT_STATUS_AC_PRESENT) {
+ aprint_normal(": AC present (but unused)");
+ first = 0;
+ }
+ if (sc->sc_inputstatus & AXP_INPUT_STATUS_VBUS_OK) {
+ aprint_normal("%s VBUS used", first ? ":" : ",");
+ first = 0;
+ } else if (sc->sc_inputstatus & AXP_INPUT_STATUS_VBUS_PRESENT) {
+ aprint_normal("%s VBUS present (but unused)", first ? ":" : ",");
+ first = 0;
+ }
+ if (sc->sc_powermode & AXP_POWER_MODE_BATTOK) {
+ aprint_normal("%s battery present", first ? ":" : ",");
+ }
aprint_normal("\n");
sc->sc_sme = sysmon_envsys_create();
@@ -84,14 +248,139 @@
sc->sc_sme->sme_cookie = sc;
sc->sc_sme->sme_refresh = axp20x_sensors_refresh;
- sc->sc_sensor_temp.units = ENVSYS_STEMP;
- sc->sc_sensor_temp.state = ENVSYS_SINVALID;
- sc->sc_sensor_temp.flags = ENVSYS_FHAS_ENTROPY;
- snprintf(sc->sc_sensor_temp.desc, sizeof(sc->sc_sensor_temp.desc),
+ sc->sc_sensor[AXP_SENSOR_ACOK].units = ENVSYS_INDICATOR;
+ sc->sc_sensor[AXP_SENSOR_ACOK].state = ENVSYS_SVALID;
+ sc->sc_sensor[AXP_SENSOR_ACOK].value_cur =
+ (sc->sc_inputstatus & AXP_INPUT_STATUS_AC_OK) ? 1 : 0;
+ snprintf(sc->sc_sensor[AXP_SENSOR_ACOK].desc,
+ sizeof(sc->sc_sensor[AXP_SENSOR_ACOK].desc), "AC input");
+ sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_ACOK]);
+ sc->sc_sensor[AXP_SENSOR_ACV].units = ENVSYS_SVOLTS_DC;
+ sc->sc_sensor[AXP_SENSOR_ACV].state = ENVSYS_SINVALID;
+ sc->sc_sensor[AXP_SENSOR_ACV].flags = ENVSYS_FHAS_ENTROPY;
+ snprintf(sc->sc_sensor[AXP_SENSOR_ACV].desc,
+ sizeof(sc->sc_sensor[AXP_SENSOR_ACV].desc), "AC input voltage");
+ sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_ACV]);
+ sc->sc_sensor[AXP_SENSOR_ACI].units = ENVSYS_SAMPS;
+ sc->sc_sensor[AXP_SENSOR_ACI].state = ENVSYS_SINVALID;
+ sc->sc_sensor[AXP_SENSOR_ACI].flags = ENVSYS_FHAS_ENTROPY;
+ snprintf(sc->sc_sensor[AXP_SENSOR_ACI].desc,
+ sizeof(sc->sc_sensor[AXP_SENSOR_ACI].desc), "AC input current");
+ sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_ACI]);
+
+ sc->sc_sensor[AXP_SENSOR_VBUSOK].units = ENVSYS_INDICATOR;
+ sc->sc_sensor[AXP_SENSOR_VBUSOK].state = ENVSYS_SVALID;
+ sc->sc_sensor[AXP_SENSOR_VBUSOK].value_cur =
+ (sc->sc_inputstatus & AXP_INPUT_STATUS_VBUS_OK) ? 1 : 0;
+ snprintf(sc->sc_sensor[AXP_SENSOR_VBUSOK].desc,
+ sizeof(sc->sc_sensor[AXP_SENSOR_VBUSOK].desc), "VBUS input");
+ sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_VBUSOK]);
+ sc->sc_sensor[AXP_SENSOR_VBUSV].units = ENVSYS_SVOLTS_DC;
+ sc->sc_sensor[AXP_SENSOR_VBUSV].state = ENVSYS_SINVALID;
+ sc->sc_sensor[AXP_SENSOR_VBUSV].flags = ENVSYS_FHAS_ENTROPY;
+ snprintf(sc->sc_sensor[AXP_SENSOR_VBUSV].desc,
+ sizeof(sc->sc_sensor[AXP_SENSOR_VBUSV].desc), "VBUS input voltage");
+ sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_VBUSV]);
+ sc->sc_sensor[AXP_SENSOR_VBUSI].units = ENVSYS_SAMPS;
+ sc->sc_sensor[AXP_SENSOR_VBUSI].state = ENVSYS_SINVALID;
+ sc->sc_sensor[AXP_SENSOR_VBUSI].flags = ENVSYS_FHAS_ENTROPY;
+ snprintf(sc->sc_sensor[AXP_SENSOR_VBUSI].desc,
+ sizeof(sc->sc_sensor[AXP_SENSOR_VBUSI].desc), "VBUS input current");
+ sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_VBUSI]);
+
+ sc->sc_sensor[AXP_SENSOR_BATTOK].units = ENVSYS_INDICATOR;
+ sc->sc_sensor[AXP_SENSOR_BATTOK].state = ENVSYS_SVALID;
+ sc->sc_sensor[AXP_SENSOR_BATTOK].value_cur =
+ (sc->sc_powermode & AXP_POWER_MODE_BATTOK) ? 1 : 0;
+ snprintf(sc->sc_sensor[AXP_SENSOR_BATTOK].desc,
+ sizeof(sc->sc_sensor[AXP_SENSOR_BATTOK].desc), "battery");
+ sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_BATTOK]);
+ sc->sc_sensor[AXP_SENSOR_BATTV].units = ENVSYS_SVOLTS_DC;
+ sc->sc_sensor[AXP_SENSOR_BATTV].state = ENVSYS_SINVALID;
+ sc->sc_sensor[AXP_SENSOR_BATTV].flags = ENVSYS_FHAS_ENTROPY;
+ snprintf(sc->sc_sensor[AXP_SENSOR_BATTV].desc,
+ sizeof(sc->sc_sensor[AXP_SENSOR_BATTV].desc), "battery voltage");
+ sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_BATTV]);
+ sc->sc_sensor[AXP_SENSOR_BATTI].units = ENVSYS_SAMPS;
+ sc->sc_sensor[AXP_SENSOR_BATTI].state = ENVSYS_SINVALID;
+ sc->sc_sensor[AXP_SENSOR_BATTI].flags = ENVSYS_FHAS_ENTROPY;
+ snprintf(sc->sc_sensor[AXP_SENSOR_BATTI].desc,
+ sizeof(sc->sc_sensor[AXP_SENSOR_BATTI].desc), "battery current");
+ sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_BATTI]);
+
+ sc->sc_sensor[AXP_SENSOR_APSV].units = ENVSYS_SVOLTS_DC;
+ sc->sc_sensor[AXP_SENSOR_APSV].state = ENVSYS_SINVALID;
+ sc->sc_sensor[AXP_SENSOR_APSV].flags = ENVSYS_FHAS_ENTROPY;
+ snprintf(sc->sc_sensor[AXP_SENSOR_APSV].desc,
+ sizeof(sc->sc_sensor[AXP_SENSOR_APSV].desc), "APS output voltage");
+ sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[AXP_SENSOR_APSV]);
+ sc->sc_sensor[AXP_SENSOR_TEMP].units = ENVSYS_STEMP;
+ sc->sc_sensor[AXP_SENSOR_TEMP].state = ENVSYS_SINVALID;
+ sc->sc_sensor[AXP_SENSOR_TEMP].flags = ENVSYS_FHAS_ENTROPY;
Home |
Main Index |
Thread Index |
Old Index