diff options
Diffstat (limited to 'sys/dev/mk48txx')
-rw-r--r-- | sys/dev/mk48txx/mk48txx.c | 67 | ||||
-rw-r--r-- | sys/dev/mk48txx/mk48txxreg.h | 83 |
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 |