55#include "opt_platform.h"
61#include <sys/kernel.h>
62#include <sys/libkern.h>
63#include <sys/module.h>
64#include <sys/sysctl.h>
69#include <dev/ofw/openfirm.h>
70#include <dev/ofw/ofw_bus.h>
71#include <dev/ofw/ofw_bus_subr.h>
81#define PCF8563_ADDR 0xa2
82#define PCF8523_ADDR 0xd0
87#define PCF85xx_R_CS1 0x00
88#define PCF85xx_R_CS2 0x01
90#define PCF85xx_B_CS1_STOP 0x20
91#define PCF85xx_B_SECOND_OS 0x80
93#define PCF85xx_M_SECOND 0x7f
94#define PCF85xx_M_MINUTE 0x7f
95#define PCF85xx_M_12HOUR 0x1f
96#define PCF85xx_M_24HOUR 0x3f
97#define PCF85xx_M_DAY 0x3f
98#define PCF85xx_M_MONTH 0x1f
99#define PCF85xx_M_YEAR 0xff
104#define PCF2127_R_TMR_CTL 0x10
106#define PCF2127_M_TMR_CTRL 0xe3
108#define PCF2127_B_TMR_CD 0x40
109#define PCF2127_B_TMR_64HZ 0x01
111#define PCF2127_R_TS_CTL 0x12
112#define PCF2127_B_TSOFF 0x40
114#define PCF2127_R_AGING_OFFSET 0x19
119#define PCF2129_B_CS1_12HR 0x04
120#define PCF2129_B_CLKOUT_OTPR 0x20
121#define PCF2129_B_CLKOUT_HIGHZ 0x07
126#define PCF8523_R_CS3 0x02
127#define PCF8523_R_SECOND 0x03
128#define PCF8523_R_TMR_CLKOUT 0x0F
129#define PCF8523_R_TMR_A_FREQ 0x10
130#define PCF8523_R_TMR_A_COUNT 0x11
132#define PCF8523_M_TMR_A_FREQ 0x07
134#define PCF8523_B_HOUR_PM 0x20
135#define PCF8523_B_CS1_SOFTRESET 0x58
136#define PCF8523_B_CS1_12HR 0x08
137#define PCF8523_B_CLKOUT_TACD 0x02
138#define PCF8523_B_CLKOUT_HIGHZ 0x38
139#define PCF8523_B_TMR_A_64HZ 0x01
141#define PCF8523_M_CS3_PM 0xE0
142#define PCF8523_B_CS3_PM_NOBAT 0xE0
143#define PCF8523_B_CS3_PM_STD 0x00
144#define PCF8523_B_CS3_PM_DSNBM 0xa0
145#define PCF8523_B_CS3_BLF 0x04
150#define PCF8563_R_SECOND 0x02
152#define PCF8563_R_CLKOUT 0x0d
154#define PCF8563_R_TMR_CTRL 0x0e
155#define PCF8563_R_TMR_COUNT 0x0f
157#define PCF8563_M_TMR_CTRL 0x93
159#define PCF8563_B_TMR_ENABLE 0x80
160#define PCF8563_B_TMR_64HZ 0x01
162#define PCF8563_B_MONTH_C 0x80
168#define TMR_TICKS_SEC 64
169#define TMR_TICKS_HALFSEC 32
206 struct intr_config_hook
219#define SC_F_CPOL (1 << 0)
228#define WAITFLAGS (IIC_WAIT | IIC_RECURSIVE)
261 uint16_t buflen,
int waithow)
274 slaveaddr = iicbus_get_addr(slavedev);
276 msg.
slave = slaveaddr;
284 msg.
slave = slaveaddr;
310 uint8_t sec, tmr1, tmr2;
367 int err, freqppm, newppm;
372 freqppm = newppm = 8 - sc->
freqadj;
374 err = sysctl_handle_int(oidp, &newppm, 0, req);
375 if (err != 0 || req->newptr == NULL)
377 if (freqppm != newppm) {
378 if (newppm < -7 || newppm > 8)
398 sc->
bat_time = ts.tv_sec + (60 * 60 * 24);
418 device_printf(sc->
dev,
"cannot write CS3 reg\n");
421 pause_sbt(
"nxpbat", mstosbt(10), 0, 0);
423 device_printf(sc->
dev,
"cannot read CS3 reg\n");
428 device_printf(sc->
dev,
"cannot write CS3 reg\n");
433 device_printf(sc->
dev,
"WARNING: RTC battery is low\n");
441 struct sysctl_ctx_list *ctx;
442 struct sysctl_oid_list *tree;
450 uint8_t clkout, freqadj;
455 device_printf(sc->
dev,
"cannot read RTC control regs\n");
467 device_printf(sc->
dev,
468 "WARNING: RTC battery failed; time is invalid\n");
482 device_printf(sc->
dev,
483 "cannot write CS1 reg\n");
489 device_printf(sc->
dev,
490 "cannot write timestamp control\n");
500 device_printf(sc->
dev,
501 "cannot write CLKOUT control\n");
504 pause_sbt(
"nxpotp", mstosbt(100), mstosbt(10), 0);
510 device_printf(sc->
dev,
"cannot write CLKOUT control\n");
536 device_printf(sc->
dev,
537 "cannot read AGINGOFFSET register\n");
542 ctx = device_get_sysctl_ctx(sc->
dev);
543 tree = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->
dev));
545 SYSCTL_ADD_PROC(ctx, tree, OID_AUTO,
"freqadj",
546 CTLFLAG_RWTUN | CTLTYPE_INT | CTLFLAG_MPSAFE, sc, 0,
559 uint8_t clkout, stdclk, stdfreq, tmrfreq;
591 uint8_t stdctl, tmrctl;
627 device_printf(sc->
dev,
"cannot read RTC control regs\n");
638 device_printf(sc->
dev,
639 "WARNING: RTC battery failed; time is invalid\n");
647 device_printf(sc->
dev,
"cannot write CS1 reg\n");
652 device_printf(sc->
dev,
"cannot write CS1 reg\n");
664 uint8_t stdctl, tmrctl;
685 int clockflags, resolution;
687 sc = device_get_softc((device_t)
dev);
699 device_printf(sc->
dev,
"cannot set up timer\n");
707 device_printf(sc->
dev,
"cannot set up timer\n");
716 device_printf(sc->
dev,
"cannot set up timer\n");
721 device_printf(sc->
dev,
"missing init code for this chiptype\n");
736 clockflags = CLOCKF_GETTIME_NO_ADJ | CLOCKF_SETTIME_NO_TS;
737 clock_register_flags(sc->
dev, resolution, clockflags);
738 clock_schedule(sc->
dev, 495000000);
744 struct bcd_clocktime bct;
748 uint8_t cs1, hourmask, tmrcount;
750 sc = device_get_softc(
dev);
768 device_printf(
dev,
"RTC clock not running\n");
777 bct.nsec = ((uint64_t)tmrcount * 1000000000) /
TMR_TICKS_SEC;
781 bct.hour = tregs.
hour & hourmask;
796 }
else if (bct.year >= 0x70)
800 clock_dbgprint_bcd(sc->
dev, CLOCK_DBG_READ, &bct);
801 err = clock_bcd_to_ts(&bct, ts, sc->
use_ampm);
802 ts->tv_sec += utc_offset();
810 struct bcd_clocktime bct;
816 sc = device_get_softc(
dev);
838 ts->tv_sec -= utc_offset();
840 clock_ts_to_bcd(ts, &bct, sc->
use_ampm);
841 clock_dbgprint_bcd(sc->
dev, CLOCK_DBG_WRITE, &bct);
847 if (bct.year >= 0x2000)
849 }
else if (bct.year < 0x2000)
857 tregs.
month = bct.mon;
858 tregs.
year = (bct.year & 0xff) | cflag;
859 tregs.
wday = bct.dow;
870 cs1 &= ~PCF85xx_B_CS1_STOP;
884 device_printf(
dev,
"cannot write RTC time\n");
905 if (resource_string_value(device_get_name(
dev),
906 device_get_unit(
dev),
"compatible", &htype) == 0) {
908 if (strcmp(htype, cdata->
ocd_str) == 0)
932 if (!ofw_bus_status_okay(
dev))
934 rv = BUS_PROBE_GENERIC;
936 rv = BUS_PROBE_NOWILDCARD;
950 sc = device_get_softc(
dev);
974 device_printf(
dev,
"impossible: cannot determine chip type\n");
984 if (config_intrhook_establish(&sc->
config_hook) != 0)
994 clock_unregister(
dev);
int iicbus_request_bus(device_t bus, device_t dev, int how)
int iicbus_release_bus(device_t bus, device_t dev)
int iicbus_transfer_excl(device_t dev, struct iic_msg *msgs, uint32_t nmsgs, int how)
int iicdev_writeto(device_t slavedev, uint8_t regaddr, void *buffer, uint16_t buflen, int waithow)
static int write_timeregs(struct nxprtc_softc *sc, struct time_regs *tregs)
static int nxprtc_probe(device_t dev)
static int pcf8563_start_timer(struct nxprtc_softc *sc)
static void nxprtc_start(void *dev)
#define PCF8563_R_TMR_COUNT
#define PCF8523_B_CS3_PM_STD
#define PCF8563_B_TMR_64HZ
static int nxprtc_gettime(device_t dev, struct timespec *ts)
static int nxprtc_readfrom(device_t slavedev, uint8_t regaddr, void *buffer, uint16_t buflen, int waithow)
static int nxprtc_get_chiptype(device_t dev)
#define PCF8563_R_TMR_CTRL
#define PCF8523_B_CS3_PM_DSNBM
#define PCF2129_B_CLKOUT_HIGHZ
#define PCF8523_R_TMR_A_FREQ
#define PCF8523_R_TMR_A_COUNT
static devclass_t nxprtc_devclass
static const char * desc_strings[]
DRIVER_MODULE(nxprtc, iicbus, nxprtc_driver, nxprtc_devclass, NULL, NULL)
static int pcf8563_start(struct nxprtc_softc *sc)
static int pcf2127_start_timer(struct nxprtc_softc *sc)
#define PCF2127_R_AGING_OFFSET
#define PCF8523_B_CS3_BLF
#define PCF8523_M_TMR_A_FREQ
#define PCF85xx_B_SECOND_OS
#define PCF8523_B_CLKOUT_TACD
static driver_t nxprtc_driver
#define TMR_TICKS_HALFSEC
#define PCF2127_M_TMR_CTRL
#define PCF2127_R_TMR_CTL
#define PCF8523_R_TMR_CLKOUT
#define PCF2129_B_CLKOUT_OTPR
static device_method_t nxprtc_methods[]
MODULE_VERSION(nxprtc, 1)
static int freqadj_sysctl(SYSCTL_HANDLER_ARGS)
static int nxprtc_detach(device_t dev)
#define PCF8523_B_CS3_PM_NOBAT
static int read_timeregs(struct nxprtc_softc *sc, struct time_regs *tregs, uint8_t *tmr)
#define PCF8563_B_TMR_ENABLE
IICBUS_FDT_PNP_INFO(compat_data)
static int nxprtc_settime(device_t dev, struct timespec *ts)
static int write_reg(struct nxprtc_softc *sc, uint8_t reg, uint8_t val)
MODULE_DEPEND(nxprtc, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER)
static int pcf8523_start(struct nxprtc_softc *sc)
#define PCF8523_B_HOUR_PM
static nxprtc_compat_data compat_data[]
static int nxprtc_attach(device_t dev)
#define PCF8523_B_CLKOUT_HIGHZ
#define PCF8563_M_TMR_CTRL
#define PCF85xx_B_CS1_STOP
#define PCF2129_B_CS1_12HR
#define PCF8523_B_TMR_A_64HZ
#define PCF8563_B_MONTH_C
static int pcf8523_battery_check(struct nxprtc_softc *sc)
static int read_reg(struct nxprtc_softc *sc, uint8_t reg, uint8_t *val)
static int pcf8523_start_timer(struct nxprtc_softc *sc)
#define PCF8523_B_CS1_12HR
CTASSERT(nitems(desc_strings)==TYPE_COUNT)
struct intr_config_hook config_hook