Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/i2c Add RTC support
details: https://anonhg.NetBSD.org/src/rev/1d506c8d6682
branches: trunk
changeset: 460717:1d506c8d6682
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Fri Nov 01 09:49:55 2019 +0000
description:
Add RTC support
diffstat:
sys/dev/i2c/twl4030.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 113 insertions(+), 3 deletions(-)
diffs (188 lines):
diff -r 2e017a64e52c -r 1d506c8d6682 sys/dev/i2c/twl4030.c
--- a/sys/dev/i2c/twl4030.c Fri Nov 01 09:49:21 2019 +0000
+++ b/sys/dev/i2c/twl4030.c Fri Nov 01 09:49:55 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: twl4030.c,v 1.1 2019/10/30 21:38:28 jmcneill Exp $ */
+/* $NetBSD: twl4030.c,v 1.2 2019/11/01 09:49:55 jmcneill Exp $ */
/*-
* Copyright (c) 2019 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: twl4030.c,v 1.1 2019/10/30 21:38:28 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: twl4030.c,v 1.2 2019/11/01 09:49:55 jmcneill Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -50,6 +50,12 @@
#define ADDR_AUX 0x02
#define ADDR_POWER 0x03
+/* INTBR registers */
+#define IDCODE_7_0 0x85
+#define IDCODE_15_8 0x86
+#define IDCODE_23_16 0x87
+#define IDCODE_31_24 0x88
+
/* GPIO registers */
#define GPIOBASE 0x98
#define GPIODATAIN(pin) (GPIOBASE + 0x00 + (pin) / 8)
@@ -60,6 +66,18 @@
#define GPIOPUPDCTR(pin) (GPIOBASE + 0x13 + (n) / 4)
#define PUPD_BITS(pin) __BITS((pin) % 4 + 1, (pin) % 4)
+/* POWER registers */
+#define SECONDS_REG 0x1c
+#define MINUTES_REG 0x1d
+#define HOURS_REG 0x1e
+#define DAYS_REG 0x1f
+#define MONTHS_REG 0x20
+#define YEARS_REG 0x21
+#define WEEKS_REG 0x22
+#define RTC_CTRL_REG 0x29
+#define GET_TIME __BIT(6)
+#define STOP_RTC __BIT(0)
+
struct twl_softc {
device_t sc_dev;
i2c_tag_t sc_i2c;
@@ -67,6 +85,8 @@
int sc_phandle;
int sc_npins;
+
+ struct todr_chip_handle sc_todr;
};
struct twl_pin {
@@ -81,6 +101,7 @@
{ NULL, 0 }
};
+static const char * const rtc_compatible[] = { "ti,twl4030-rtc", NULL };
static const char * const gpio_compatible[] = { "ti,twl4030-gpio", NULL };
static uint8_t
@@ -118,6 +139,70 @@
#define INT_READ(sc, reg) twl_read((sc), ADDR_INT, (reg), I2C_F_POLL)
#define INT_WRITE(sc, reg, val) twl_write((sc), ADDR_INT, (reg), (val), I2C_F_POLL)
+#define POWER_READ(sc, reg) twl_read((sc), ADDR_POWER, (reg), I2C_F_POLL)
+#define POWER_WRITE(sc, reg, val) twl_write((sc), ADDR_POWER, (reg), (val), I2C_F_POLL)
+
+static void
+twl_rtc_enable(struct twl_softc *sc, bool onoff)
+{
+ uint8_t rtc_ctrl;
+
+ rtc_ctrl = POWER_READ(sc, RTC_CTRL_REG);
+ if (onoff)
+ rtc_ctrl |= STOP_RTC; /* 1: RTC is running */
+ else
+ rtc_ctrl &= ~STOP_RTC; /* 0: RTC is frozen */
+ POWER_WRITE(sc, RTC_CTRL_REG, rtc_ctrl);
+}
+
+static int
+twl_rtc_gettime(todr_chip_handle_t tch, struct clock_ymdhms *dt)
+{
+ struct twl_softc *sc = tch->cookie;
+ uint8_t seconds_reg, minutes_reg, hours_reg,
+ days_reg, months_reg, years_reg, weeks_reg;
+
+ iic_acquire_bus(sc->sc_i2c, I2C_F_POLL);
+ seconds_reg = POWER_READ(sc, SECONDS_REG);
+ minutes_reg = POWER_READ(sc, MINUTES_REG);
+ hours_reg = POWER_READ(sc, HOURS_REG);
+ days_reg = POWER_READ(sc, DAYS_REG);
+ months_reg = POWER_READ(sc, MONTHS_REG);
+ years_reg = POWER_READ(sc, YEARS_REG);
+ weeks_reg = POWER_READ(sc, WEEKS_REG);
+ iic_release_bus(sc->sc_i2c, I2C_F_POLL);
+
+ dt->dt_sec = bcdtobin(seconds_reg);
+ dt->dt_min = bcdtobin(minutes_reg);
+ dt->dt_hour = bcdtobin(hours_reg);
+ dt->dt_day = bcdtobin(days_reg);
+ dt->dt_mon = bcdtobin(months_reg);
+ dt->dt_year = bcdtobin(years_reg) + 2000;
+ dt->dt_wday = bcdtobin(weeks_reg);
+
+ return 0;
+}
+
+static int
+twl_rtc_settime(todr_chip_handle_t tch, struct clock_ymdhms *dt)
+{
+ struct twl_softc *sc = tch->cookie;
+
+ iic_acquire_bus(sc->sc_i2c, I2C_F_POLL);
+ twl_rtc_enable(sc, false);
+ POWER_WRITE(sc, SECONDS_REG, bintobcd(dt->dt_sec));
+ POWER_WRITE(sc, MINUTES_REG, bintobcd(dt->dt_min));
+ POWER_WRITE(sc, HOURS_REG, bintobcd(dt->dt_hour));
+ POWER_WRITE(sc, DAYS_REG, bintobcd(dt->dt_day));
+ POWER_WRITE(sc, MONTHS_REG, bintobcd(dt->dt_mon));
+ POWER_WRITE(sc, YEARS_REG, bintobcd(dt->dt_year % 100));
+ POWER_WRITE(sc, WEEKS_REG, bintobcd(dt->dt_wday));
+ twl_rtc_enable(sc, true);
+ iic_release_bus(sc->sc_i2c, I2C_F_POLL);
+
+ return 0;
+}
+
static int
twl_gpio_config(struct twl_softc *sc, int pin, int flags)
{
@@ -235,6 +320,19 @@
};
static void
+twl_rtc_attach(struct twl_softc *sc, const int phandle)
+{
+ iic_acquire_bus(sc->sc_i2c, I2C_F_POLL);
+ twl_rtc_enable(sc, true);
+ iic_release_bus(sc->sc_i2c, I2C_F_POLL);
+
+ sc->sc_todr.todr_gettime_ymdhms = twl_rtc_gettime;
+ sc->sc_todr.todr_settime_ymdhms = twl_rtc_settime;
+ sc->sc_todr.cookie = sc;
+ fdtbus_todr_attach(sc->sc_dev, phandle, &sc->sc_todr);
+}
+
+static void
twl_gpio_attach(struct twl_softc *sc, const int phandle)
{
fdtbus_register_gpio_controller(sc->sc_dev, phandle, &twl_gpio_funcs);
@@ -257,6 +355,7 @@
{
struct twl_softc * const sc = device_private(self);
struct i2c_attach_args *ia = aux;
+ uint32_t idcode;
int child;
sc->sc_dev = self;
@@ -272,9 +371,20 @@
if (of_match_compatible(child, gpio_compatible)) {
aprint_normal(", GPIO");
twl_gpio_attach(sc, child);
+ } else if (of_match_compatible(child, rtc_compatible)) {
+ aprint_normal(", RTC");
+ twl_rtc_attach(sc, child);
}
}
- aprint_normal("\n");
+
+ I2C_LOCK(sc);
+ idcode = INT_READ(sc, IDCODE_7_0);
+ idcode |= (uint32_t)INT_READ(sc, IDCODE_15_8) << 8;
+ idcode |= (uint32_t)INT_READ(sc, IDCODE_23_16) << 16;
+ idcode |= (uint32_t)INT_READ(sc, IDCODE_31_24) << 24;
+ I2C_UNLOCK(sc);
+
+ aprint_normal(", IDCODE 0x%08x\n", idcode);
}
CFATTACH_DECL_NEW(twl, sizeof(struct twl_softc),
Home |
Main Index |
Thread Index |
Old Index