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
This commit is contained in:
Justin Hibbits 2016-04-05 03:27:33 +00:00
parent 2db664d7b5
commit cc8a3448d9
2 changed files with 34 additions and 8 deletions

View File

@ -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.

View File

@ -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)