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 TPS65950 RTC support
details: https://anonhg.NetBSD.org/src/rev/05000c5204cc
branches: trunk
changeset: 783612:05000c5204cc
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Mon Dec 31 21:45:36 2012 +0000
description:
add TPS65950 RTC support
diffstat:
sys/dev/i2c/tps65950.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 123 insertions(+), 5 deletions(-)
diffs (185 lines):
diff -r 8674d3dc6698 -r 05000c5204cc sys/dev/i2c/tps65950.c
--- a/sys/dev/i2c/tps65950.c Mon Dec 31 21:34:31 2012 +0000
+++ b/sys/dev/i2c/tps65950.c Mon Dec 31 21:45:36 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: tps65950.c,v 1.2 2012/12/31 19:47:27 jmcneill Exp $ */
+/* $NetBSD: tps65950.c,v 1.3 2012/12/31 21:45:36 jmcneill Exp $ */
/*-
* Copyright (c) 2012 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tps65950.c,v 1.2 2012/12/31 19:47:27 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tps65950.c,v 1.3 2012/12/31 21:45:36 jmcneill Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -44,6 +44,7 @@
#include <dev/i2c/i2cvar.h>
+#include <dev/clock_subr.h>
#include <dev/sysmon/sysmonvar.h>
/* Default watchdog period, in seconds */
@@ -77,6 +78,17 @@
/* ID4 */
#define TPS65950_PM_RECEIVER_BASE 0x5b
#define TPS65950_ID4_REG_WATCHDOG_CFG (TPS65950_PM_RECEIVER_BASE + 3)
+#define TPS65950_RTC_BASE 0x1c
+#define TPS65950_ID4_REG_SECONDS_REG (TPS65950_RTC_BASE + 0)
+#define TPS65950_ID4_REG_MINUTES_REG (TPS65950_RTC_BASE + 1)
+#define TPS65950_ID4_REG_HOURS_REG (TPS65950_RTC_BASE + 2)
+#define TPS65950_ID4_REG_DAYS_REG (TPS65950_RTC_BASE + 3)
+#define TPS65950_ID4_REG_MONTHS_REG (TPS65950_RTC_BASE + 4)
+#define TPS65950_ID4_REG_YEARS_REG (TPS65950_RTC_BASE + 5)
+#define TPS65950_ID4_REG_WEEKS_REG (TPS65950_RTC_BASE + 6)
+#define TPS65950_ID4_REG_RTC_CTRL_REG (TPS65950_RTC_BASE + 13)
+#define TPS65950_ID4_REG_RTC_CTRL_REG_GET_TIME __BIT(6)
+#define TPS65950_ID4_REG_RTC_CTRL_REG_STOP_RTC __BIT(1)
struct tps65950_softc {
device_t sc_dev;
@@ -85,7 +97,7 @@
struct sysctllog *sc_sysctllog;
struct sysmon_wdog sc_smw;
- uint8_t sc_watchdog_cfg;
+ struct todr_chip_handle sc_todr;
};
static int tps65950_match(device_t, cfdata_t, void *);
@@ -95,8 +107,13 @@
static int tps65950_write_1(struct tps65950_softc *, uint8_t, uint8_t);
static void tps65950_sysctl_attach(struct tps65950_softc *);
+
+static void tps65950_rtc_attach(struct tps65950_softc *);
+static int tps65950_rtc_enable(struct tps65950_softc *, bool);
+static int tps65950_rtc_gettime(todr_chip_handle_t, struct clock_ymdhms *);
+static int tps65950_rtc_settime(todr_chip_handle_t, struct clock_ymdhms *);
+
static void tps65950_wdog_attach(struct tps65950_softc *);
-
static int tps65950_wdog_setmode(struct sysmon_wdog *);
static int tps65950_wdog_tickle(struct sysmon_wdog *);
@@ -154,7 +171,8 @@
tps65950_sysctl_attach(sc);
break;
case TPS65950_ADDR_ID4:
- aprint_normal(": WATCHDOG\n");
+ aprint_normal(": RTC, WATCHDOG\n");
+ tps65950_rtc_attach(sc);
tps65950_wdog_attach(sc);
break;
default:
@@ -281,6 +299,106 @@
}
static void
+tps65950_rtc_attach(struct tps65950_softc *sc)
+{
+ sc->sc_todr.todr_gettime_ymdhms = tps65950_rtc_gettime;
+ sc->sc_todr.todr_settime_ymdhms = tps65950_rtc_settime;
+ sc->sc_todr.cookie = sc;
+ todr_attach(&sc->sc_todr);
+
+ iic_acquire_bus(sc->sc_i2c, 0);
+ tps65950_rtc_enable(sc, true);
+ iic_release_bus(sc->sc_i2c, 0);
+}
+
+static int
+tps65950_rtc_enable(struct tps65950_softc *sc, bool enable)
+{
+ uint8_t rtc_ctrl;
+ int error;
+
+ error = tps65950_read_1(sc, TPS65950_ID4_REG_RTC_CTRL_REG, &rtc_ctrl);
+ if (error)
+ return error;
+
+ if (enable) {
+ rtc_ctrl |= TPS65950_ID4_REG_RTC_CTRL_REG_STOP_RTC;
+ } else {
+ rtc_ctrl &= ~TPS65950_ID4_REG_RTC_CTRL_REG_STOP_RTC;
+ }
+
+ return tps65950_write_1(sc, TPS65950_ID4_REG_RTC_CTRL_REG, rtc_ctrl);
+}
+
+#define RTC_READ(reg, var) \
+ do { \
+ tps65950_write_1(sc, TPS65950_ID4_REG_RTC_CTRL_REG, \
+ TPS65950_ID4_REG_RTC_CTRL_REG_GET_TIME); \
+ if ((error = tps65950_read_1(sc, (reg), &(var))) != 0) { \
+ iic_release_bus(sc->sc_i2c, 0); \
+ return error; \
+ } \
+ } while (0)
+
+#define RTC_WRITE(reg, val) \
+ do { \
+ if ((error = tps65950_write_1(sc, (reg), (val))) != 0) { \
+ iic_release_bus(sc->sc_i2c, 0); \
+ return error; \
+ } \
+ } while (0)
+
+static int
+tps65950_rtc_gettime(todr_chip_handle_t tch, struct clock_ymdhms *dt)
+{
+ struct tps65950_softc *sc = tch->cookie;
+ uint8_t seconds_reg, minutes_reg, hours_reg,
+ days_reg, months_reg, years_reg, weeks_reg;
+ int error = 0;
+
+ iic_acquire_bus(sc->sc_i2c, 0);
+ RTC_READ(TPS65950_ID4_REG_SECONDS_REG, seconds_reg);
+ RTC_READ(TPS65950_ID4_REG_MINUTES_REG, minutes_reg);
+ RTC_READ(TPS65950_ID4_REG_HOURS_REG, hours_reg);
+ RTC_READ(TPS65950_ID4_REG_DAYS_REG, days_reg);
+ RTC_READ(TPS65950_ID4_REG_MONTHS_REG, months_reg);
+ RTC_READ(TPS65950_ID4_REG_YEARS_REG, years_reg);
+ RTC_READ(TPS65950_ID4_REG_WEEKS_REG, weeks_reg);
+ iic_release_bus(sc->sc_i2c, 0);
+
+ dt->dt_sec = FROMBCD(seconds_reg);
+ dt->dt_min = FROMBCD(minutes_reg);
+ dt->dt_hour = FROMBCD(hours_reg);
+ dt->dt_day = FROMBCD(days_reg);
+ dt->dt_mon = FROMBCD(months_reg);
+ dt->dt_year = FROMBCD(years_reg) + 2000;
+ dt->dt_wday = FROMBCD(weeks_reg);
+
+ return 0;
+}
+
+static int
+tps65950_rtc_settime(todr_chip_handle_t tch, struct clock_ymdhms *dt)
+{
+ struct tps65950_softc *sc = tch->cookie;
+ int error = 0;
+
+ iic_acquire_bus(sc->sc_i2c, 0);
+ tps65950_rtc_enable(sc, false);
+ RTC_WRITE(TPS65950_ID4_REG_SECONDS_REG, TOBCD(dt->dt_sec));
+ RTC_WRITE(TPS65950_ID4_REG_MINUTES_REG, TOBCD(dt->dt_min));
+ RTC_WRITE(TPS65950_ID4_REG_HOURS_REG, TOBCD(dt->dt_hour));
+ RTC_WRITE(TPS65950_ID4_REG_DAYS_REG, TOBCD(dt->dt_day));
+ RTC_WRITE(TPS65950_ID4_REG_MONTHS_REG, TOBCD(dt->dt_mon));
+ RTC_WRITE(TPS65950_ID4_REG_YEARS_REG, TOBCD(dt->dt_year % 100));
+ RTC_WRITE(TPS65950_ID4_REG_WEEKS_REG, TOBCD(dt->dt_wday));
+ tps65950_rtc_enable(sc, true);
+ iic_release_bus(sc->sc_i2c, 0);
+
+ return error;
+}
+
+static void
tps65950_wdog_attach(struct tps65950_softc *sc)
{
sc->sc_smw.smw_name = device_xname(sc->sc_dev);
Home |
Main Index |
Thread Index |
Old Index