From 098f6cb6e685e672ba35084a77eceb5279f72fe4 Mon Sep 17 00:00:00 2001 From: Ian Lepore Date: Mon, 14 Aug 2017 00:00:24 +0000 Subject: [PATCH] Minor fixes and enhancements for the s35390a i2c RTC driver... - Add FDT probe code. - Do i2c transfers with exclusive bus ownership. - Use config_intrhook_oneshot() to defer chip setup because some i2c busses can't do transfers without interrupts. - Add a detach() routine. - Add to module build. --- sys/dev/iicbus/s35390a.c | 67 +++++++++++++++++++++++++------- sys/modules/i2c/Makefile | 1 + sys/modules/i2c/s35390a/Makefile | 7 ++++ 3 files changed, 60 insertions(+), 15 deletions(-) create mode 100644 sys/modules/i2c/s35390a/Makefile diff --git a/sys/dev/iicbus/s35390a.c b/sys/dev/iicbus/s35390a.c index 59369b3f238..042f088c410 100644 --- a/sys/dev/iicbus/s35390a.c +++ b/sys/dev/iicbus/s35390a.c @@ -59,6 +59,8 @@ __FBSDID("$FreeBSD$"); * Driver for Seiko Instruments S-35390A Real-time Clock */ +#include "opt_platform.h" + #include #include #include @@ -69,6 +71,12 @@ __FBSDID("$FreeBSD$"); #include #include +#ifdef FDT +#include +#include +#include +#endif + #include "clock_if.h" #include "iicbus_if.h" @@ -159,7 +167,7 @@ s390rtc_read(device_t dev, uint8_t reg, uint8_t *buf, size_t len) int i; int error; - error = iicbus_transfer(dev, msg, 1); + error = iicbus_transfer_excl(dev, msg, 1, IIC_WAIT); if (error) return (error); @@ -188,13 +196,20 @@ s390rtc_write(device_t dev, uint8_t reg, uint8_t *buf, size_t len) for (i = 0; i < len; ++i) buf[i] = bitreverse(buf[i]); - return (iicbus_transfer(dev, msg, 1)); + return (iicbus_transfer_excl(dev, msg, 1, IIC_WAIT)); } static int s390rtc_probe(device_t dev) { +#ifdef FDT + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (!ofw_bus_is_compatible(dev, "sii,s35390a")) + return (ENXIO); +#else if (iicbus_get_addr(dev) != S390_ADDR) { if (bootverbose) device_printf(dev, "slave address mismatch. " @@ -202,35 +217,35 @@ s390rtc_probe(device_t dev) S390_ADDR); return (ENXIO); } - device_set_desc(dev, "Seiko Instruments S-35390A Real-time Clock"); +#endif + device_set_desc(dev, "Seiko Instruments S-35390A RTC"); - return (BUS_PROBE_SPECIFIC); + return (BUS_PROBE_DEFAULT); } -static int -s390rtc_attach(device_t dev) +static void +s390rtc_start(void *arg) { - struct s390rtc_softc *sc; + device_t dev; uint8_t reg; int error; - sc = device_get_softc(dev); - sc->sc_dev = dev; - sc->sc_addr = iicbus_get_addr(dev); + dev = arg; /* Reset the chip and turn on 24h mode, after power-off or battery. */ error = s390rtc_read(dev, S390_STATUS1, ®, 1); if (error) { device_printf(dev, "%s: cannot read status1 register\n", __func__); - return (error); + return; } if (reg & (S390_ST1_POC | S390_ST1_BLD)) { reg |= S390_ST1_24H | S390_ST1_RESET; error = s390rtc_write(dev, S390_STATUS1, ®, 1); if (error) { - device_printf(dev, "%s: cannot initialize\n", __func__); - return (error); + device_printf(dev, + "%s: cannot initialize\n", __func__); + return; } } @@ -239,7 +254,7 @@ s390rtc_attach(device_t dev) if (error) { device_printf(dev, "%s: cannot read status2 register\n", __func__); - return (error); + return; } if (reg & S390_ST2_TEST) { reg &= ~S390_ST2_TEST; @@ -247,11 +262,32 @@ s390rtc_attach(device_t dev) if (error) { device_printf(dev, "%s: cannot disable the test mode\n", __func__); - return (error); + return; } } clock_register(dev, 1000000); /* 1 second resolution */ +} + +static int +s390rtc_attach(device_t dev) +{ + struct s390rtc_softc *sc; + + sc = device_get_softc(dev); + sc->sc_dev = dev; + sc->sc_addr = iicbus_get_addr(dev); + + config_intrhook_oneshot(s390rtc_start, dev); + + return (0); +} + +static int +s390rtc_detach(device_t dev) +{ + + clock_unregister(dev); return (0); } @@ -310,6 +346,7 @@ s390rtc_settime(device_t dev, struct timespec *ts) static device_method_t s390rtc_methods[] = { DEVMETHOD(device_probe, s390rtc_probe), DEVMETHOD(device_attach, s390rtc_attach), + DEVMETHOD(device_detach, s390rtc_detach), DEVMETHOD(clock_gettime, s390rtc_gettime), DEVMETHOD(clock_settime, s390rtc_settime), diff --git a/sys/modules/i2c/Makefile b/sys/modules/i2c/Makefile index 2ecfd852c8a..34124c6e625 100644 --- a/sys/modules/i2c/Makefile +++ b/sys/modules/i2c/Makefile @@ -15,6 +15,7 @@ SUBDIR = \ isl12xx \ jedec_ts \ nxprtc \ + s35390a \ smb \ smbus \ diff --git a/sys/modules/i2c/s35390a/Makefile b/sys/modules/i2c/s35390a/Makefile new file mode 100644 index 00000000000..1e6e93e60e4 --- /dev/null +++ b/sys/modules/i2c/s35390a/Makefile @@ -0,0 +1,7 @@ +# $FreeBSD$ + +.PATH: ${SRCTOP}/sys/dev/iicbus +KMOD = s35390a +SRCS = s35390a.c bus_if.h clock_if.h device_if.h iicbus_if.h ofw_bus_if.h + +.include