Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F106128303
D19145.id53776.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D19145.id53776.diff
View Options
Index: sys/arm/allwinner/axp81x.c
===================================================================
--- sys/arm/allwinner/axp81x.c
+++ sys/arm/allwinner/axp81x.c
@@ -194,6 +194,11 @@
#define AXP_BAT_CAP_WARN_LV1 0xf0 /* Bits 4, 5, 6, 7 */
#define AXP_BAT_CAP_WARN_LV2 0xf /* Bits 0, 1, 2, 3 */
+/* Sensor conversion macros */
+#define AXP_SENSOR_BAT_H(hi) ((hi) << 4)
+#define AXP_SENSOR_BAT_L(lo) ((lo) & 0xf)
+#define AXP_SENSOR_COULOMB(hi, lo) (((hi & ~(1 << 7)) << 8) | (lo))
+
static const struct {
const char *name;
uint8_t ctrl_reg;
@@ -538,6 +543,123 @@
},
};
+enum axp8xx_sensor {
+ AXP_SENSOR_ACIN_PRESENT,
+ AXP_SENSOR_VBUS_PRESENT,
+ AXP_SENSOR_BATT_PRESENT,
+ AXP_SENSOR_BATT_CHARGING,
+ AXP_SENSOR_BATT_CHARGE_STATE,
+ AXP_SENSOR_BATT_VOLTAGE,
+ AXP_SENSOR_BATT_CHARGE_CURRENT,
+ AXP_SENSOR_BATT_DISCHARGE_CURRENT,
+ AXP_SENSOR_BATT_CAPACITY_PERCENT,
+ AXP_SENSOR_BATT_MAXIMUM_CAPACITY,
+ AXP_SENSOR_BATT_CURRENT_CAPACITY,
+};
+
+enum battery_capacity_state {
+ BATT_CAPACITY_NORMAL = 1, /* normal cap in battery */
+ BATT_CAPACITY_WARNING, /* warning cap in battery */
+ BATT_CAPACITY_CRITICAL, /* critical cap in battery */
+ BATT_CAPACITY_HIGH, /* high cap in battery */
+ BATT_CAPACITY_MAX, /* maximum cap in battery */
+ BATT_CAPACITY_LOW /* low cap in battery */
+};
+
+struct axp8xx_sensors {
+ int id;
+ const char *name;
+ const char *desc;
+ const char *format;
+};
+
+static const struct axp8xx_sensors axp8xx_common_sensors[] = {
+ {
+ .id = AXP_SENSOR_ACIN_PRESENT,
+ .name = "acin",
+ .format = "I",
+ .desc = "ACIN Present",
+ },
+ {
+ .id = AXP_SENSOR_VBUS_PRESENT,
+ .name = "vbus",
+ .format = "I",
+ .desc = "VBUS Present",
+ },
+ {
+ .id = AXP_SENSOR_BATT_PRESENT,
+ .name = "bat",
+ .format = "I",
+ .desc = "Battery Present",
+ },
+ {
+ .id = AXP_SENSOR_BATT_CHARGING,
+ .name = "batcharging",
+ .format = "I",
+ .desc = "Battery Charging",
+ },
+ {
+ .id = AXP_SENSOR_BATT_CHARGE_STATE,
+ .name = "batchargestate",
+ .format = "I",
+ .desc = "Battery Charge State",
+ },
+ {
+ .id = AXP_SENSOR_BATT_VOLTAGE,
+ .name = "batvolt",
+ .format = "I",
+ .desc = "Battery Voltage",
+ },
+ {
+ .id = AXP_SENSOR_BATT_CHARGE_CURRENT,
+ .name = "batchargecurrent",
+ .format = "I",
+ .desc = "Battery Charging Current",
+ },
+ {
+ .id = AXP_SENSOR_BATT_DISCHARGE_CURRENT,
+ .name = "batdischargecurrent",
+ .format = "I",
+ .desc = "Battery Discharging Current",
+ },
+ {
+ .id = AXP_SENSOR_BATT_CAPACITY_PERCENT,
+ .name = "batcapacitypercent",
+ .format = "I",
+ .desc = "Battery Capacity Percentage",
+ },
+ {
+ .id = AXP_SENSOR_BATT_MAXIMUM_CAPACITY,
+ .name = "batmaxcapacity",
+ .format = "I",
+ .desc = "Battery Maximum Capacity",
+ },
+ {
+ .id = AXP_SENSOR_BATT_CURRENT_CAPACITY,
+ .name = "batcurrentcapacity",
+ .format = "I",
+ .desc = "Battery Current Capacity",
+ },
+};
+
+struct axp8xx_config {
+ const char *name;
+ int batsense_step; /* uV */
+ int charge_step; /* uA */
+ int discharge_step; /* uA */
+ int maxcap_step; /* uAh */
+ int coulomb_step; /* uAh */
+};
+
+static struct axp8xx_config axp803_config = {
+ .name = "AXP803",
+ .batsense_step = 1100,
+ .charge_step = 1000,
+ .discharge_step = 1000,
+ .maxcap_step = 1456,
+ .coulomb_step = 1456,
+};
+
struct axp8xx_softc;
struct axp8xx_reg_sc {
@@ -558,9 +680,20 @@
int type;
+ /* Configs */
+ const struct axp8xx_config *config;
+
+ /* Sensors */
+ const struct axp8xx_sensors *sensors;
+ int nsensors;
+
/* Regulators */
struct axp8xx_reg_sc **regs;
int nregs;
+
+ /* Warning, shutdown thresholds */
+ int warn_thres;
+ int shut_thres;
};
#define AXP_LOCK(sc) mtx_lock(&(sc)->mtx)
@@ -756,6 +889,110 @@
axp8xx_write(dev, AXP_POWERBAT, AXP_POWERBAT_SHUTDOWN);
}
+static int
+axp8xx_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ struct axp8xx_softc *sc;
+ device_t dev = arg1;
+ enum axp8xx_sensor sensor = arg2;
+ const struct axp8xx_config *c;
+ uint8_t data;
+ int val, i, found, batt_val;
+ uint8_t lo, hi;
+
+ sc = device_get_softc(dev);
+ c = sc->config;
+
+ for (found = 0, i = 0; i < sc->nsensors; i++) {
+ if (sc->sensors[i].id == sensor) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (found == 0)
+ return (ENOENT);
+
+ switch (sensor) {
+ case AXP_SENSOR_ACIN_PRESENT:
+ if (axp8xx_read(dev, AXP_POWERSRC, &data, 1) == 0)
+ val = !!(data & AXP_POWERSRC_ACIN);
+ break;
+ case AXP_SENSOR_VBUS_PRESENT:
+ if (axp8xx_read(dev, AXP_POWERSRC, &data, 1) == 0)
+ val = !!(data & AXP_POWERSRC_VBUS);
+ break;
+ case AXP_SENSOR_BATT_PRESENT:
+ if (axp8xx_read(dev, AXP_POWERMODE, &data, 1) == 0) {
+ if (data & AXP_POWERMODE_BAT_VALID)
+ val = !!(data & AXP_POWERMODE_BAT_PRESENT);
+ }
+ break;
+ case AXP_SENSOR_BATT_CHARGING:
+ if (axp8xx_read(dev, AXP_POWERMODE, &data, 1) == 0)
+ val = !!(data & AXP_POWERMODE_BAT_CHARGING);
+ break;
+ case AXP_SENSOR_BATT_CHARGE_STATE:
+ if (axp8xx_read(dev, AXP_BAT_CAP, &data, 1) == 0 &&
+ (data & AXP_BAT_CAP_VALID) != 0) {
+ batt_val = (data & AXP_BAT_CAP_PERCENT);
+ if (batt_val <= sc->shut_thres)
+ val = BATT_CAPACITY_CRITICAL;
+ else if (batt_val <= sc->warn_thres)
+ val = BATT_CAPACITY_WARNING;
+ else
+ val = BATT_CAPACITY_NORMAL;
+ }
+ break;
+ case AXP_SENSOR_BATT_CAPACITY_PERCENT:
+ if (axp8xx_read(dev, AXP_BAT_CAP, &data, 1) == 0 &&
+ (data & AXP_BAT_CAP_VALID) != 0)
+ val = (data & AXP_BAT_CAP_PERCENT);
+ break;
+ case AXP_SENSOR_BATT_VOLTAGE:
+ if (axp8xx_read(dev, AXP_BATSENSE_HI, &hi, 1) == 0 &&
+ axp8xx_read(dev, AXP_BATSENSE_LO, &lo, 1) == 0) {
+ val = (AXP_SENSOR_BAT_H(hi) | AXP_SENSOR_BAT_L(lo));
+ val *= c->batsense_step;
+ }
+ break;
+ case AXP_SENSOR_BATT_CHARGE_CURRENT:
+ if (axp8xx_read(dev, AXP_POWERSRC, &data, 1) == 0 &&
+ (data & AXP_POWERSRC_CHARING) != 0 &&
+ axp8xx_read(dev, AXP_BATCHG_HI, &hi, 1) == 0 &&
+ axp8xx_read(dev, AXP_BATCHG_LO, &lo, 1) == 0) {
+ val = (AXP_SENSOR_BAT_H(hi) | AXP_SENSOR_BAT_L(lo));
+ val *= c->charge_step;
+ }
+ break;
+ case AXP_SENSOR_BATT_DISCHARGE_CURRENT:
+ if (axp8xx_read(dev, AXP_POWERSRC, &data, 1) == 0 &&
+ (data & AXP_POWERSRC_CHARING) == 0 &&
+ axp8xx_read(dev, AXP_BATDISCHG_HI, &hi, 1) == 0 &&
+ axp8xx_read(dev, AXP_BATDISCHG_LO, &lo, 1) == 0) {
+ val = (AXP_SENSOR_BAT_H(hi) | AXP_SENSOR_BAT_L(lo));
+ val *= c->discharge_step;
+ }
+ break;
+ case AXP_SENSOR_BATT_MAXIMUM_CAPACITY:
+ if (axp8xx_read(dev, AXP_BAT_MAX_CAP_HI, &hi, 1) == 0 &&
+ axp8xx_read(dev, AXP_BAT_MAX_CAP_LO, &lo, 1) == 0) {
+ val = AXP_SENSOR_COULOMB(hi, lo);
+ val *= c->maxcap_step;
+ }
+ break;
+ case AXP_SENSOR_BATT_CURRENT_CAPACITY:
+ if (axp8xx_read(dev, AXP_BAT_COULOMB_HI, &hi, 1) == 0 &&
+ axp8xx_read(dev, AXP_BAT_COULOMB_LO, &lo, 1) == 0) {
+ val = AXP_SENSOR_COULOMB(hi, lo);
+ val *= c->coulomb_step;
+ }
+ break;
+ }
+
+ return sysctl_handle_opaque(oidp, &val, sizeof(val), req);
+}
+
static void
axp8xx_intr(void *arg)
{
@@ -1157,7 +1394,7 @@
{
struct axp8xx_softc *sc;
struct axp8xx_reg_sc *reg;
- uint8_t chip_id;
+ uint8_t chip_id, val;
phandle_t rnode, child;
int error, i;
@@ -1187,6 +1424,10 @@
sc->nregs += nitems(axp813_regdefs);
break;
}
+ sc->config = &axp803_config;
+ sc->sensors = axp8xx_common_sensors;
+ sc->nsensors = nitems(axp8xx_common_sensors);
+
sc->regs = malloc(sizeof(struct axp8xx_reg_sc *) * sc->nregs,
M_AXP8XX_REG, M_WAITOK | M_ZERO);
@@ -1231,6 +1472,31 @@
}
}
+ /* Add sensors */
+ for (i = 0; i < sc->nsensors; i++) {
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, sc->sensors[i].name,
+ CTLTYPE_INT | CTLFLAG_RD,
+ dev, sc->sensors[i].id, axp8xx_sysctl,
+ sc->sensors[i].format,
+ sc->sensors[i].desc);
+ }
+
+ /* Get thresholds */
+ if (axp8xx_read(dev, AXP_BAT_CAP_WARN, &val, 1) == 0) {
+ sc->warn_thres = (val & AXP_BAT_CAP_WARN_LV1) >> 4;
+ sc->shut_thres = (val & AXP_BAT_CAP_WARN_LV2);
+ if (bootverbose) {
+ device_printf(dev,
+ "Raw reg val: 0x%02x\n", val);
+ device_printf(dev,
+ "Warning threshold: 0x%02x\n", sc->warn_thres);
+ device_printf(dev,
+ "Shutdown threshold: 0x%02x\n", sc->shut_thres);
+ }
+ }
+
/* Enable interrupts */
axp8xx_write(dev, AXP_IRQEN1,
AXP_IRQEN1_VBUS_LO |
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Dec 26, 9:05 PM (11 h, 58 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15607876
Default Alt Text
D19145.id53776.diff (8 KB)
Attached To
Mode
D19145: Expose AXP803 related sensors values via sysctl
Attached
Detach File
Event Timeline
Log In to Comment