summaryrefslogtreecommitdiffstats
path: root/sys/dev/mk48txx
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/mk48txx')
-rw-r--r--sys/dev/mk48txx/mk48txx.c67
-rw-r--r--sys/dev/mk48txx/mk48txxreg.h83
2 files changed, 131 insertions, 19 deletions
diff --git a/sys/dev/mk48txx/mk48txx.c b/sys/dev/mk48txx/mk48txx.c
index 9d28084..1cbb526 100644
--- a/sys/dev/mk48txx/mk48txx.c
+++ b/sys/dev/mk48txx/mk48txx.c
@@ -101,6 +101,13 @@ mk48txx_attach(device_t dev, bus_space_tag_t bt, bus_space_handle_t bh,
}
printf("\n");
+ if ((mk48txx_models[i].flags & MK48TXX_EXT_REGISTERS) &&
+ (bus_space_read_1(bt, bh, clkoff + MK48TXX_FLAGS) &
+ MK48TXX_FLAGS_BL)) {
+ device_printf(dev, "mk48txx_attach: battery low\n");
+ return (ENXIO);
+ }
+
sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT);
sc->mk_bt = bt;
sc->mk_bh = bh;
@@ -133,14 +140,33 @@ mk48txx_gettime(device_t dev, struct timespec *ts)
csr |= MK48TXX_CSR_READ;
bus_space_write_1(bt, bh, clkoff + MK48TXX_ICSR, csr);
+#define FROMREG(reg, mask) \
+ (bus_space_read_1(bt, bh, clkoff + (reg)) & (mask))
+
ct.nsec = 0;
- ct.sec = FROMBCD(bus_space_read_1(bt, bh, clkoff + MK48TXX_ISEC));
- ct.min = FROMBCD(bus_space_read_1(bt, bh, clkoff + MK48TXX_IMIN));
- ct.hour = FROMBCD(bus_space_read_1(bt, bh, clkoff + MK48TXX_IHOUR));
- ct.day = FROMBCD(bus_space_read_1(bt, bh, clkoff + MK48TXX_IDAY));
- ct.dow = FROMBCD(bus_space_read_1(bt, bh, clkoff + MK48TXX_IWDAY)) % 7;
- ct.mon = FROMBCD(bus_space_read_1(bt, bh, clkoff + MK48TXX_IMON));
- year = FROMBCD(bus_space_read_1(bt, bh, clkoff + MK48TXX_IYEAR));
+ ct.sec = FROMBCD(FROMREG(MK48TXX_ISEC, MK48TXX_SEC_MASK));
+ ct.min = FROMBCD(FROMREG(MK48TXX_IMIN, MK48TXX_MIN_MASK));
+ ct.hour = FROMBCD(FROMREG(MK48TXX_IHOUR, MK48TXX_HOUR_MASK));
+ ct.day = FROMBCD(FROMREG(MK48TXX_IDAY, MK48TXX_DAY_MASK));
+ /* Map dow from 1 - 7 to 0 - 6; FROMBCD() isn't necessary here. */
+ ct.dow = FROMREG(MK48TXX_IWDAY, MK48TXX_WDAY_MASK) - 1;
+ ct.mon = FROMBCD(FROMREG(MK48TXX_IMON, MK48TXX_MON_MASK));
+ year = FROMBCD(FROMREG(MK48TXX_IYEAR, MK48TXX_YEAR_MASK));
+
+ /*
+ * XXX: At least the MK48T59 (probably all MK48Txx models with
+ * extended registers) has a century bit in the MK48TXX_IWDAY
+ * register which should be used here to make up the century
+ * when mk48txx_auto_century_adjust (which actually means
+ * manually adjust the century in the driver) is set to 0.
+ * Sun/Solaris doesn't use this bit (probably for backwards
+ * compatibility with Sun hardware equipped with older MK48Txx
+ * models) and at present this driver is only used on sparc64
+ * so not respecting the century bit doesn't really matter at
+ * the moment but generally this should be implemented.
+ */
+
+#undef FROMREG
year += mk->mk_year0;
if (year < POSIX_BASE_YEAR && mk48txx_auto_century_adjust != 0)
@@ -186,13 +212,26 @@ mk48txx_settime(device_t dev, struct timespec *ts)
csr |= MK48TXX_CSR_WRITE;
bus_space_write_1(bt, bh, clkoff + MK48TXX_ICSR, csr);
- bus_space_write_1(bt, bh, clkoff + MK48TXX_ISEC, TOBCD(ct.sec));
- bus_space_write_1(bt, bh, clkoff + MK48TXX_IMIN, TOBCD(ct.min));
- bus_space_write_1(bt, bh, clkoff + MK48TXX_IHOUR, TOBCD(ct.hour));
- bus_space_write_1(bt, bh, clkoff + MK48TXX_IWDAY, TOBCD(ct.dow));
- bus_space_write_1(bt, bh, clkoff + MK48TXX_IDAY, TOBCD(ct.day));
- bus_space_write_1(bt, bh, clkoff + MK48TXX_IMON, TOBCD(ct.mon));
- bus_space_write_1(bt, bh, clkoff + MK48TXX_IYEAR, TOBCD(year));
+#define TOREG(reg, mask, val) \
+ (bus_space_write_1(bt, bh, clkoff + (reg), \
+ (bus_space_read_1(bt, bh, clkoff + (reg)) & ~(mask)) | \
+ ((val) & (mask))))
+
+ TOREG(MK48TXX_ISEC, MK48TXX_SEC_MASK, TOBCD(ct.sec));
+ TOREG(MK48TXX_IMIN, MK48TXX_MIN_MASK, TOBCD(ct.min));
+ TOREG(MK48TXX_IHOUR, MK48TXX_HOUR_MASK, TOBCD(ct.hour));
+ /* Map dow from 0 - 6 to 1 - 7; TOBCD() isn't necessary here. */
+ TOREG(MK48TXX_IWDAY, MK48TXX_WDAY_MASK, ct.dow + 1);
+ TOREG(MK48TXX_IDAY, MK48TXX_DAY_MASK, TOBCD(ct.day));
+ TOREG(MK48TXX_IMON, MK48TXX_MON_MASK, TOBCD(ct.mon));
+ TOREG(MK48TXX_IYEAR, MK48TXX_YEAR_MASK, TOBCD(year));
+
+ /*
+ * XXX: Use the century bit for storing the century when
+ * mk48txx_auto_century_adjust is set to 0.
+ */
+
+#undef TOREG
/* load them up */
csr = bus_space_read_1(bt, bh, clkoff + MK48TXX_ICSR);
diff --git a/sys/dev/mk48txx/mk48txxreg.h b/sys/dev/mk48txx/mk48txxreg.h
index 817f122..8bcadc2 100644
--- a/sys/dev/mk48txx/mk48txxreg.h
+++ b/sys/dev/mk48txx/mk48txxreg.h
@@ -59,22 +59,95 @@
* The first bank of eight registers at offset (nvramsz - 16) is
* available only on recenter (which?) MK48Txx models.
*/
-#define MK48TXX_X0 0 /* find out later */
- /* ... */
-#define MK48TXX_X7 7 /* find out later */
+#define MK48TXX_FLAGS 0 /* flags register */
+#define MK48TXX_UNUSED 1 /* unused */
+#define MK48TXX_ASEC 2 /* alarm seconds (0..59; BCD) */
+#define MK48TXX_AMIN 3 /* alarm minutes (0..59; BCD) */
+#define MK48TXX_AHOUR 4 /* alarm hours (0..23; BCD) */
+#define MK48TXX_ADAY 5 /* alarm day in month (1..31; BCD) */
+#define MK48TXX_INTR 6 /* interrupts register */
+#define MK48TXX_WDOG 7 /* watchdog register */
+
#define MK48TXX_ICSR 8 /* control register */
#define MK48TXX_ISEC 9 /* seconds (0..59; BCD) */
#define MK48TXX_IMIN 10 /* minutes (0..59; BCD) */
-#define MK48TXX_IHOUR 11 /* hour (0..23; BCD) */
+#define MK48TXX_IHOUR 11 /* hours (0..23; BCD) */
#define MK48TXX_IWDAY 12 /* weekday (1..7) */
#define MK48TXX_IDAY 13 /* day in month (1..31; BCD) */
#define MK48TXX_IMON 14 /* month (1..12; BCD) */
#define MK48TXX_IYEAR 15 /* year (0..99; BCD) */
+/*
+ * Note that some of the bits below that are not in the first eight
+ * registers are also only available on models with an extended
+ * register set.
+ */
+
+/* Bits in the flags register (extended only) */
+#define MK48TXX_FLAGS_BL 0x10 /* battery low (read only) */
+#define MK48TXX_FLAGS_AF 0x40 /* alarm flag (read only) */
+#define MK48TXX_FLAGS_WDF 0x80 /* watchdog flag (read only) */
+
+/* Bits in the alarm seconds register (extended only) */
+#define MK48TXX_ASEC_MASK 0x7f /* mask for alarm seconds */
+#define MK48TXX_ASEC_RPT1 0x80 /* alarm repeat mode bit 1 */
+
+/* Bits in the alarm minutes register (extended only) */
+#define MK48TXX_AMIN_MASK 0x7f /* mask for alarm minutes */
+#define MK48TXX_AMIN_RPT2 0x80 /* alarm repeat mode bit 2 */
+
+/* Bits in the alarm hours register (extended only) */
+#define MK48TXX_AHOUR_MASK 0x3f /* mask for alarm hours */
+#define MK48TXX_AHOUR_RPT3 0x80 /* alarm repeat mode bit 3 */
+
+/* Bits in the alarm day in month register (extended only) */
+#define MK48TXX_ADAY_MASK 0x3f /* mask for alarm day in month */
+#define MK48TXX_ADAY_RPT4 0x80 /* alarm repeat mode bit 4 */
+
+/* Bits in the interrupts register (extended only) */
+#define MK48TXX_INTR_ABE 0x20 /* alarm in battery back-up mode */
+#define MK48TXX_INTR_AFE 0x80 /* alarm flag enable */
+
+/* Bits in the watchdog register (extended only) */
+#define MK48TXX_WDOG_RB_1_16 0x00 /* watchdog resolution 1/16 second */
+#define MK48TXX_WDOG_RB_1_4 0x01 /* watchdog resolution 1/4 second */
+#define MK48TXX_WDOG_RB_1 0x02 /* watchdog resolution 1 second */
+#define MK48TXX_WDOG_RB_4 0x03 /* watchdog resolution 4 seconds */
+#define MK48TXX_WDOG_BMB_MASK 0x7c /* mask for watchdog multiplier */
+#define MK48TXX_WDOG_WDS 0x80 /* watchdog steering bit */
+
/* Bits in the control register */
-#define MK48TXX_CSR_WRITE 0x80 /* want to write */
+#define MK48TXX_CSR_CALIB_MASK 0x1f /* mask for calibration step width */
+#define MK48TXX_CSR_SIGN 0x20 /* sign of above calibration witdh */
#define MK48TXX_CSR_READ 0x40 /* want to read (freeze clock) */
+#define MK48TXX_CSR_WRITE 0x80 /* want to write */
+
+/* Bits in the seconds register */
+#define MK48TXX_SEC_MASK 0x7f /* mask for seconds */
+#define MK48TXX_SEC_ST 0x80 /* stop oscillator */
+
+/* Bits in the minutes register */
+#define MK48TXX_MIN_MASK 0x7f /* mask for minutes */
+
+/* Bits in the hours register */
+#define MK48TXX_HOUR_MASK 0x3f /* mask for hours */
+
+/* Bits in the century/weekday register */
+#define MK48TXX_WDAY_MASK 0x07 /* mask for weekday */
+#define MK48TXX_WDAY_CB 0x10 /* century bit (extended only) */
+#define MK48TXX_WDAY_CEB 0x20 /* century enable bit (extended only) */
+#define MK48TXX_WDAY_FT 0x30 /* frequency bit */
+
+/* Bits in the day in month register */
+#define MK48TXX_DAY_MASK 0x3f /* mask for day in month */
+
+/* Bits in the month register */
+#define MK48TXX_MON_MASK 0x1f /* mask for month */
+
+/* Bits in the year register */
+#define MK48TXX_YEAR_MASK 0xff /* mask for year */
+/* Model specific NVRAM sizes and clock offsets */
#define MK48T02_CLKSZ 2048
#define MK48T02_CLKOFF 0x7f0
OpenPOWER on IntegriCloud