summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/arm/ti/am335x/am335x_pmic.c154
-rw-r--r--sys/arm/ti/am335x/tps65217x.h114
2 files changed, 227 insertions, 41 deletions
diff --git a/sys/arm/ti/am335x/am335x_pmic.c b/sys/arm/ti/am335x/am335x_pmic.c
index 18bc438..5ff9936 100644
--- a/sys/arm/ti/am335x/am335x_pmic.c
+++ b/sys/arm/ti/am335x/am335x_pmic.c
@@ -27,7 +27,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
-* TPS65217 PMIC companion chip for AM335x SoC sitting on I2C bus
+* TI TPS65217 PMIC companion chip for AM335x SoC sitting on I2C bus
*/
#include <sys/param.h>
#include <sys/systm.h>
@@ -50,30 +50,10 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/ofw_bus_subr.h>
#include <arm/ti/am335x/am335x_rtcvar.h>
+#include <arm/ti/am335x/tps65217x.h>
#include "iicbus_if.h"
-#define TPS65217A 0x7
-#define TPS65217B 0xF
-#define TPS65217C 0xE
-#define TPS65217D 0x6
-
-/* TPS65217 Reisters */
-#define TPS65217_CHIPID_REG 0x00
-#define TPS65217_INT_REG 0x02
-#define TPS65217_INT_PBM (1U << 6)
-#define TPS65217_INT_ACM (1U << 5)
-#define TPS65217_INT_USBM (1U << 4)
-#define TPS65217_INT_PBI (1U << 2)
-#define TPS65217_INT_ACI (1U << 1)
-#define TPS65217_INT_USBI (1U << 0)
-
-#define TPS65217_STATUS_REG 0x0A
-#define TPS65217_STATUS_OFF (1U << 7)
-#define TPS65217_STATUS_ACPWR (1U << 3)
-#define TPS65217_STATUS_USBPWR (1U << 2)
-#define TPS65217_STATUS_BT (1U << 0)
-
#define MAX_IIC_DATA_SIZE 2
@@ -85,6 +65,13 @@ struct am335x_pmic_softc {
void *sc_intrhand;
};
+static const char *tps65217_voreg_c[4] = {"4.10V", "4.15V", "4.20V", "4.25V"};
+
+static int am335x_pmic_bootverbose = 0;
+TUNABLE_INT("hw.am335x_pmic.bootverbose", &am335x_pmic_bootverbose);
+static char am335x_pmic_vo[6];
+TUNABLE_STR("hw.am335x_pmic.vo", am335x_pmic_vo, sizeof(am335x_pmic_vo));
+
static void am335x_pmic_shutdown(void *, int);
static int
@@ -120,18 +107,19 @@ static void
am335x_pmic_intr(void *arg)
{
struct am335x_pmic_softc *sc = (struct am335x_pmic_softc *)arg;
- uint8_t int_reg, status_reg;
+ struct tps65217_status_reg status_reg;
+ struct tps65217_int_reg int_reg;
int rv;
char notify_buf[16];
THREAD_SLEEPING_OK();
- rv = am335x_pmic_read(sc->sc_dev, TPS65217_INT_REG, &int_reg, 1);
+ rv = am335x_pmic_read(sc->sc_dev, TPS65217_INT_REG, (uint8_t *)&int_reg, 1);
if (rv != 0) {
device_printf(sc->sc_dev, "Cannot read interrupt register\n");
THREAD_NO_SLEEPING();
return;
}
- rv = am335x_pmic_read(sc->sc_dev, TPS65217_STATUS_REG, &status_reg, 1);
+ rv = am335x_pmic_read(sc->sc_dev, TPS65217_STATUS_REG, (uint8_t *)&status_reg, 1);
if (rv != 0) {
device_printf(sc->sc_dev, "Cannot read status register\n");
THREAD_NO_SLEEPING();
@@ -139,11 +127,11 @@ am335x_pmic_intr(void *arg)
}
THREAD_NO_SLEEPING();
- if ((int_reg & TPS65217_INT_PBI) && (status_reg & TPS65217_STATUS_BT))
+ if (int_reg.pbi && status_reg.pb)
shutdown_nice(RB_POWEROFF);
- if (int_reg & TPS65217_INT_ACI) {
+ if (int_reg.aci) {
snprintf(notify_buf, sizeof(notify_buf), "notify=0x%02x",
- (status_reg & TPS65217_STATUS_ACPWR) ? 1 : 0);
+ status_reg.acpwr ? 1 : 0);
devctl_notify_f("ACPI", "ACAD", "power", notify_buf, M_NOWAIT);
}
}
@@ -167,37 +155,120 @@ am335x_pmic_probe(device_t dev)
}
static void
+am335x_pmic_dump_chgconfig(device_t dev)
+{
+ struct tps65217_chgconfig0_reg reg0;
+ struct tps65217_chgconfig1_reg reg1;
+ struct tps65217_chgconfig2_reg reg2;
+ struct tps65217_chgconfig3_reg reg3;
+ const char *e_d[] = {"enabled", "disabled"};
+ const char *d_e[] = {"disabled", "enabled"};
+ const char *i_a[] = {"inactive", "active"};
+ const char *f_t[] = {"false", "true"};
+ const char *timer_c[] = {"4h", "5h", "6h", "8h"};
+ const char *ntc_type_c[] = {"100k", "10k"};
+ const char *vprechg_c[] = {"2.9V", "2.5V"};
+ const char *trange_c[] = {"0-45 C", "0-60 C"};
+ const char *termif_c[] = {"2.5%", "7.5%", "15%", "18%"};
+ const char *pchrgt_c[] = {"30 min", "60 min"};
+ const char *dppmth_c[] = {"3.50V", "3.75V", "4.00V", "4.25V"};
+ const char *ichrg_c[] = {"300mA", "400mA", "500mA", "700mA"};
+
+ am335x_pmic_read(dev, TPS65217_CHGCONFIG0_REG, (uint8_t *)&reg0, 1);
+ device_printf(dev, " BAT TEMP/NTC ERROR: %s\n", f_t[reg0.battemp]);
+ device_printf(dev, " Pre-charge timer time-out: %s\n", f_t[reg0.pchgtout]);
+ device_printf(dev, " Charge timer time-out: %s\n", f_t[reg0.chgtout]);
+ device_printf(dev, " Charger active: %s\n", f_t[reg0.active]);
+ device_printf(dev, " Termination current detected: %s\n", f_t[reg0.termi]);
+ device_printf(dev, " Thermal suspend: %s\n", f_t[reg0.tsusp]);
+ device_printf(dev, " DPPM active: %s\n", f_t[reg0.dppm]);
+ device_printf(dev, " Thermal regulation: %s\n", i_a[reg0.treg]);
+
+ am335x_pmic_read(dev, TPS65217_CHGCONFIG1_REG, (uint8_t *)&reg1, 1);
+ device_printf(dev, " Charger: %s\n", d_e[reg1.chg_en]);
+ device_printf(dev, " Suspend charge: %s\n", i_a[reg1.susp]);
+ device_printf(dev, " Charge termination: %s\n", e_d[reg1.term]);
+ device_printf(dev, " Charger reset: %s\n", i_a[reg1.reset]);
+ device_printf(dev, " NTC TYPE: %s\n", ntc_type_c[reg1.ntc_type]);
+ device_printf(dev, " Safety timer: %s\n", d_e[reg1.tmr_en]);
+ device_printf(dev, " Charge safety timer: %s\n", timer_c[reg1.timer]);
+
+ am335x_pmic_read(dev, TPS65217_CHGCONFIG2_REG, (uint8_t *)&reg2, 1);
+ device_printf(dev, " Charge voltage: %s\n", tps65217_voreg_c[reg2.voreg]);
+ device_printf(dev, " Pre-charge to fast charge transition voltage: %s\n",
+ vprechg_c[reg2.vprechg]);
+ device_printf(dev, " Dynamic timer function: %s\n", d_e[reg2.dyntmr]);
+
+ am335x_pmic_read(dev, TPS65217_CHGCONFIG3_REG, (uint8_t *)&reg3, 1);
+ device_printf(dev, " Temperature range for charging: %s\n", trange_c[reg3.trange]);
+ device_printf(dev, " Termination current factor: %s\n", termif_c[reg3.termif]);
+ device_printf(dev, " Pre-charge time: %s\n", pchrgt_c[reg3.pchrgt]);
+ device_printf(dev, " Power path DPPM threshold: %s\n", dppmth_c[reg3.dppmth]);
+ device_printf(dev, " Charge current: %s\n", ichrg_c[reg3.ichrg]);
+}
+
+static void
+am335x_pmic_setvo(device_t dev, uint8_t vo)
+{
+ struct tps65217_chgconfig2_reg reg2;
+
+ am335x_pmic_read(dev, TPS65217_CHGCONFIG2_REG, (uint8_t *)&reg2, 1);
+ reg2.voreg = vo;
+ am335x_pmic_write(dev, TPS65217_CHGCONFIG2_REG, (uint8_t *)&reg2, 1);
+}
+
+static void
am335x_pmic_start(void *xdev)
{
struct am335x_pmic_softc *sc;
device_t dev = (device_t)xdev;
- uint8_t reg;
+ struct tps65217_status_reg status_reg;
+ struct tps65217_chipid_reg chipid_reg;
+ uint8_t reg, vo;
char name[20];
- char pwr[4][11] = {"Unknown", "USB", "AC", "USB and AC"};
+ char pwr[4][11] = {"Battery", "USB", "AC", "USB and AC"};
int rv;
sc = device_get_softc(dev);
- am335x_pmic_read(dev, TPS65217_CHIPID_REG, &reg, 1);
- switch (reg>>4) {
+ am335x_pmic_read(dev, TPS65217_CHIPID_REG, (uint8_t *)&chipid_reg, 1);
+ switch (chipid_reg.chip) {
case TPS65217A:
- sprintf(name, "TPS65217A ver 1.%u", reg & 0xF);
+ sprintf(name, "TPS65217A ver 1.%u", chipid_reg.rev);
break;
case TPS65217B:
- sprintf(name, "TPS65217B ver 1.%u", reg & 0xF);
+ sprintf(name, "TPS65217B ver 1.%u", chipid_reg.rev);
break;
case TPS65217C:
- sprintf(name, "TPS65217C ver 1.%u", reg & 0xF);
+ sprintf(name, "TPS65217C ver 1.%u", chipid_reg.rev);
break;
case TPS65217D:
- sprintf(name, "TPS65217D ver 1.%u", reg & 0xF);
+ sprintf(name, "TPS65217D ver 1.%u", chipid_reg.rev);
break;
default:
sprintf(name, "Unknown PMIC");
}
- am335x_pmic_read(dev, TPS65217_STATUS_REG, &reg, 1);
- device_printf(dev, "%s powered by %s\n", name, pwr[(reg>>2)&0x03]);
+ am335x_pmic_read(dev, TPS65217_STATUS_REG, (uint8_t *)&status_reg, 1);
+ device_printf(dev, "%s powered by %s\n", name,
+ pwr[status_reg.usbpwr | (status_reg.acpwr << 1)]);
+
+ if (am335x_pmic_vo[0] != '\0') {
+ for (vo = 0; vo < 4; vo++) {
+ if (strcmp(tps65217_voreg_c[vo], am335x_pmic_vo) == 0)
+ break;
+ }
+ if (vo == 4) {
+ device_printf(dev, "WARNING: hw.am335x_pmic.vo=\"%s\""
+ ": unsupported value\n", am335x_pmic_vo);
+ } else {
+ am335x_pmic_setvo(dev, vo);
+ }
+ }
+
+ if (bootverbose || am335x_pmic_bootverbose) {
+ am335x_pmic_dump_chgconfig(dev);
+ }
EVENTHANDLER_REGISTER(shutdown_final, am335x_pmic_shutdown, dev,
SHUTDOWN_PRI_LAST);
@@ -248,14 +319,15 @@ static void
am335x_pmic_shutdown(void *xdev, int howto)
{
device_t dev;
- uint8_t reg;
+ struct tps65217_status_reg reg;
if (!(howto & RB_POWEROFF))
return;
dev = (device_t)xdev;
+ am335x_pmic_read(dev, TPS65217_STATUS_REG, (uint8_t *)&reg, 1);
/* Set the OFF bit on status register to start the shutdown sequence. */
- reg = TPS65217_STATUS_OFF;
- am335x_pmic_write(dev, TPS65217_STATUS_REG, &reg, 1);
+ reg.off = 1;
+ am335x_pmic_write(dev, TPS65217_STATUS_REG, (uint8_t *)&reg, 1);
/* Toggle pmic_pwr_enable to shutdown the PMIC. */
am335x_rtc_pmic_pwr_toggle();
}
diff --git a/sys/arm/ti/am335x/tps65217x.h b/sys/arm/ti/am335x/tps65217x.h
new file mode 100644
index 0000000..96f16dd
--- /dev/null
+++ b/sys/arm/ti/am335x/tps65217x.h
@@ -0,0 +1,114 @@
+/*-
+ * Copyright (c) 2012 Damjan Marion <dmarion@FreeBSD.org>
+ * Copyright (c) 2015 Maksym Sobolyev <sobomax@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __TPS65217X_H__
+#define __TPS65217X_H__
+
+/*
+ * TPS65217 PMIC is a companion chip for AM335x SoC sitting on I2C bus
+ */
+
+/* TPS65217 Reisters */
+#define TPS65217_CHIPID_REG 0x00
+struct tps65217_chipid_reg {
+ unsigned int rev:4;
+ unsigned int chip:4;
+#define TPS65217A 0x7
+#define TPS65217B 0xF
+#define TPS65217C 0xE
+#define TPS65217D 0x6
+} __attribute__((__packed__));
+
+#define TPS65217_INT_REG 0x02
+struct tps65217_int_reg {
+ unsigned int usbi:1;
+ unsigned int aci:1;
+ unsigned int pbi:1;
+ unsigned int reserved3:1;
+ unsigned int usbm:1;
+ unsigned int acm:1;
+ unsigned int pbm:1;
+ unsigned int reserved7:1;
+} __attribute__((__packed__));
+
+#define TPS65217_STATUS_REG 0x0A
+struct tps65217_status_reg {
+ unsigned int pb:1;
+ unsigned int reserved1:1;
+ unsigned int usbpwr:1;
+ unsigned int acpwr:1;
+ unsigned int reserved4:3;
+ unsigned int off:1;
+} __attribute__((__packed__));
+
+#define TPS65217_CHGCONFIG0_REG 0x03
+struct tps65217_chgconfig0_reg {
+ unsigned int battemp:1;
+ unsigned int pchgtout:1;
+ unsigned int chgtout:1;
+ unsigned int active:1;
+ unsigned int termi:1;
+ unsigned int tsusp:1;
+ unsigned int dppm:1;
+ unsigned int treg:1;
+} __attribute__((__packed__));
+
+#define TPS65217_CHGCONFIG1_REG 0x04
+struct tps65217_chgconfig1_reg {
+ unsigned int chg_en:1;
+ unsigned int susp:1;
+ unsigned int term:1;
+ unsigned int reset:1;
+ unsigned int ntc_type:1;
+ unsigned int tmr_en:1;
+ unsigned int timer:2;
+} __attribute__((__packed__));
+
+#define TPS65217_CHGCONFIG2_REG 0x05
+struct tps65217_chgconfig2_reg {
+ unsigned int reserved:4;
+ unsigned int voreg:2;
+#define TPS65217_VO_410V 0b00
+#define TPS65217_VO_415V 0b01
+#define TPS65217_VO_420V 0b10
+#define TPS65217_VO_425V 0b11
+ unsigned int vprechg:1;
+ unsigned int dyntmr:1;
+} __attribute__((__packed__));
+
+#define TPS65217_CHGCONFIG3_REG 0x06
+struct tps65217_chgconfig3_reg {
+ unsigned int trange:1;
+ unsigned int termif:2;
+ unsigned int pchrgt:1;
+ unsigned int dppmth:2;
+ unsigned int ichrg:2;
+} __attribute__((__packed__));
+
+#endif /* __TPS65217X_H__ */
OpenPOWER on IntegriCloud