From cc8a3448d9f88b9d22eae8f0f1bf504ec7b73589 Mon Sep 17 00:00:00 2001 From: Justin Hibbits Date: Tue, 5 Apr 2016 03:27:33 +0000 Subject: [PATCH] Add support for the Microchip mcp7941x. This is compatible with the ds1307, but comparing the mcp7941x datasheet vs the ds1307 code, appears there is one bit placement difference, so that is now accounted for. Relnotes: yes --- sys/dev/iicbus/ds1307.c | 41 ++++++++++++++++++++++++++++++-------- sys/dev/iicbus/ds1307reg.h | 1 + 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/sys/dev/iicbus/ds1307.c b/sys/dev/iicbus/ds1307.c index 9c7cd65171ce..987db0d0e75b 100644 --- a/sys/dev/iicbus/ds1307.c +++ b/sys/dev/iicbus/ds1307.c @@ -60,10 +60,20 @@ struct ds1307_softc { struct intr_config_hook enum_hook; uint16_t sc_addr; /* DS1307 slave address. */ uint8_t sc_ctrl; + int sc_mcp7941x; }; static void ds1307_start(void *); +#ifdef FDT +static const struct ofw_compat_data ds1307_compat_data[] = { + {"dallas,ds1307", (uintptr_t)"Maxim DS1307 RTC"}, + {"maxim,ds1307", (uintptr_t)"Maxim DS1307 RTC"}, + {"microchip,mcp7941x", (uintptr_t)"Microchip MCP7941x RTC"}, + { NULL, 0 } +}; +#endif + static int ds1307_read(device_t dev, uint16_t addr, uint8_t reg, uint8_t *data, size_t len) { @@ -167,21 +177,25 @@ ds1307_set_24hrs_mode(struct ds1307_softc *sc) static int ds1307_sqwe_sysctl(SYSCTL_HANDLER_ARGS) { - int sqwe, error, newv; + int sqwe, error, newv, sqwe_bit; struct ds1307_softc *sc; sc = (struct ds1307_softc *)arg1; error = ds1307_ctrl_read(sc); if (error != 0) return (error); - sqwe = newv = (sc->sc_ctrl & DS1307_CTRL_SQWE) ? 1 : 0; + if (sc->sc_mcp7941x) + sqwe_bit = MCP7941X_CTRL_SQWE; + else + sqwe_bit = DS1307_CTRL_SQWE; + sqwe = newv = (sc->sc_ctrl & sqwe_bit) ? 1 : 0; error = sysctl_handle_int(oidp, &newv, 0, req); if (error != 0 || req->newptr == NULL) return (error); if (sqwe != newv) { - sc->sc_ctrl &= ~DS1307_CTRL_SQWE; + sc->sc_ctrl &= ~sqwe_bit; if (newv) - sc->sc_ctrl |= DS1307_CTRL_SQWE; + sc->sc_ctrl |= sqwe_bit; error = ds1307_ctrl_write(sc); if (error != 0) return (error); @@ -252,17 +266,25 @@ ds1307_sqw_out_sysctl(SYSCTL_HANDLER_ARGS) static int ds1307_probe(device_t dev) { - #ifdef FDT + const struct ofw_compat_data *compat; + if (!ofw_bus_status_okay(dev)) return (ENXIO); - if (!ofw_bus_is_compatible(dev, "dallas,ds1307") && - !ofw_bus_is_compatible(dev, "maxim,ds1307")) + + compat = ofw_bus_search_compatible(dev, ds1307_compat_data); + + if (compat == NULL) return (ENXIO); -#endif + + device_set_desc(dev, (const char *)compat->ocd_data); + + return (BUS_PROBE_DEFAULT); +#else device_set_desc(dev, "Maxim DS1307 RTC"); return (BUS_PROBE_DEFAULT); +#endif } static int @@ -277,6 +299,9 @@ ds1307_attach(device_t dev) sc->enum_hook.ich_func = ds1307_start; sc->enum_hook.ich_arg = dev; + if (ofw_bus_is_compatible(dev, "microchip,mcp7941x")) + sc->sc_mcp7941x = 1; + /* * We have to wait until interrupts are enabled. Usually I2C read * and write only works when the interrupts are available. diff --git a/sys/dev/iicbus/ds1307reg.h b/sys/dev/iicbus/ds1307reg.h index 0c7c356c7492..ddad40b2417c 100644 --- a/sys/dev/iicbus/ds1307reg.h +++ b/sys/dev/iicbus/ds1307reg.h @@ -50,6 +50,7 @@ #define DS1307_YEAR_MASK 0xff #define DS1307_CONTROL 0x07 #define DS1307_CTRL_OUT (1 << 7) +#define MCP7941X_CTRL_SQWE (1 << 6) #define DS1307_CTRL_SQWE (1 << 4) #define DS1307_CTRL_RS1 (1 << 1) #define DS1307_CTRL_RS0 (1 << 0)