Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/i2c More cleanup to i2c autoconfiguration:



details:   https://anonhg.NetBSD.org/src/rev/b9cb460733b1
branches:  trunk
changeset: 362602:b9cb460733b1
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Sat Jun 16 21:28:07 2018 +0000

description:
More cleanup to i2c autoconfiguration:

- Get all of the drivers onto the new match quality constants.
- Introduce a new helper function, iic_use_direct_match(), that has
  all of the logic for direct-config matching.  If it returns true,
  the driver returns the match result (which may be 0).  If it returns
  false, the driver does indirect-config matching.
- iic_compat_match() now returns a weighted match quality; matches to
  lower-indexed "compatible" device property are more-specific matches,
  and return a better match quality accordingly.

In addition to the above:
- Add support for direct-config matching this driver based on
  "compatible" properties.
- Address-only matching is now done based on the specific addresses
  the requested model supports.
- "compatible" property can specify to the driver which model is to
  be used, so that using config "flags" directives aren't required
  in the direct-config case.

XXX More changes coming that require re-factoring some other code.

diffstat:

 sys/dev/i2c/ds1307.c |  115 ++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 101 insertions(+), 14 deletions(-)

diffs (211 lines):

diff -r a6c67ca42ebe -r b9cb460733b1 sys/dev/i2c/ds1307.c
--- a/sys/dev/i2c/ds1307.c      Sat Jun 16 21:24:36 2018 +0000
+++ b/sys/dev/i2c/ds1307.c      Sat Jun 16 21:28:07 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ds1307.c,v 1.25 2017/10/28 04:53:55 riastradh Exp $    */
+/*     $NetBSD: ds1307.c,v 1.26 2018/06/16 21:28:07 thorpej Exp $      */
 
 /*
  * Copyright (c) 2003 Wasabi Systems, Inc.
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ds1307.c,v 1.25 2017/10/28 04:53:55 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ds1307.c,v 1.26 2018/06/16 21:28:07 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -56,6 +56,8 @@
 #include "ioconf.h"
 
 struct dsrtc_model {
+       const char **dm_compats;
+       const i2c_addr_t *dm_valid_addrs;
        uint16_t dm_model;
        uint8_t dm_ch_reg;
        uint8_t dm_ch_value;
@@ -74,8 +76,23 @@
 #define        DSRTC_FLAG_CLOCK_HOLD_REVERSED  0x20
 };
 
+static const char *ds1307_compats[] = { "dallas,ds1307", "maxim,ds1307", NULL };
+static const char *ds1339_compats[] = { "dallas,ds1339", "maxim,ds1339", NULL };
+static const char *ds1340_compats[] = { "dallas,ds1340", "maxim,ds1340", NULL };
+static const char *ds1672_compats[] = { "dallas,ds1672", "maxim,ds1672", NULL };
+static const char *ds3231_compats[] = { "dallas,ds3231", "maxim,ds3231", NULL };
+static const char *ds3232_compats[] = { "dallas,ds3232", "maxim,ds3232", NULL };
+
+                               /* XXX vendor prefix */
+static const char *mcp7940_compats[] = { "microchip,mcp7940", NULL };
+
+static const i2c_addr_t ds1307_valid_addrs[] = { DS1307_ADDR, 0 };
+static const i2c_addr_t mcp7940_valid_addrs[] = { MCP7940_ADDR, 0 };
+
 static const struct dsrtc_model dsrtc_models[] = {
        {
+               .dm_compats = ds1307_compats,
+               .dm_valid_addrs = ds1307_valid_addrs,
                .dm_model = 1307,
                .dm_ch_reg = DSXXXX_SECONDS,
                .dm_ch_value = DS1307_SECONDS_CH,
@@ -85,11 +102,15 @@
                .dm_nvram_size = DS1307_NVRAM_SIZE,
                .dm_flags = DSRTC_FLAG_BCD | DSRTC_FLAG_CLOCK_HOLD,
        }, {
+               .dm_compats = ds1339_compats,
+               .dm_valid_addrs = ds1307_valid_addrs,
                .dm_model = 1339,
                .dm_rtc_start = DS1339_RTC_START,
                .dm_rtc_size = DS1339_RTC_SIZE,
                .dm_flags = DSRTC_FLAG_BCD,
        }, {
+               .dm_compats = ds1340_compats,
+               .dm_valid_addrs = ds1307_valid_addrs,
                .dm_model = 1340,
                .dm_ch_reg = DSXXXX_SECONDS,
                .dm_ch_value = DS1340_SECONDS_EOSC,
@@ -97,6 +118,8 @@
                .dm_rtc_size = DS1340_RTC_SIZE,
                .dm_flags = DSRTC_FLAG_BCD,
        }, {
+               .dm_compats = ds1672_compats,
+               .dm_valid_addrs = ds1307_valid_addrs,
                .dm_model = 1672,
                .dm_rtc_start = DS1672_RTC_START,
                .dm_rtc_size = DS1672_RTC_SIZE,
@@ -104,6 +127,8 @@
                .dm_ch_value = DS1672_CONTROL_CH,
                .dm_flags = 0,
        }, {
+               .dm_compats = ds3231_compats,
+               .dm_valid_addrs = ds1307_valid_addrs,
                .dm_model = 3231,
                .dm_rtc_start = DS3232_RTC_START,
                .dm_rtc_size = DS3232_RTC_SIZE,
@@ -114,6 +139,8 @@
                 */
                .dm_flags = DSRTC_FLAG_BCD | DSRTC_FLAG_TEMP,
        }, {
+               .dm_compats = ds3232_compats,
+               .dm_valid_addrs = ds1307_valid_addrs,
                .dm_model = 3232,
                .dm_rtc_start = DS3232_RTC_START,
                .dm_rtc_size = DS3232_RTC_SIZE,
@@ -122,6 +149,8 @@
                .dm_flags = DSRTC_FLAG_BCD,
        }, {
                /* MCP7940 */
+               .dm_compats = mcp7940_compats,
+               .dm_valid_addrs = mcp7940_valid_addrs,
                .dm_model = 7940,
                .dm_rtc_start = DS1307_RTC_START,
                .dm_rtc_size = DS1307_RTC_SIZE,
@@ -187,7 +216,7 @@
 static void dsrtc_refresh(struct sysmon_envsys *, envsys_data_t *);
 
 static const struct dsrtc_model *
-dsrtc_model(u_int model)
+dsrtc_model_by_number(u_int model)
 {
        /* no model given, assume it's a DS1307 (the first one) */
        if (model == 0)
@@ -201,20 +230,71 @@
        return NULL;
 }
 
+static const struct dsrtc_model *
+dsrtc_model_by_compat(const struct i2c_attach_args *ia)
+{
+       const struct dsrtc_model *best_model = NULL, *dm;
+       int best_match = 0, match_result;
+
+       for (dm = dsrtc_models;
+            dm < dsrtc_models + __arraycount(dsrtc_models); dm++) {
+               match_result = iic_compat_match(ia, dm->dm_compats);
+               if (match_result > best_match) {
+                       best_match = match_result;
+                       best_model = dm;
+               }
+       }
+       return best_model;
+}
+
+static bool
+dsrtc_direct_match(const struct i2c_attach_args *ia, const cfdata_t cf,
+                  int *best_matchp)
+{
+       const struct dsrtc_model *dm;
+       int best_match = 0, match_result;
+
+       for (dm = dsrtc_models;
+            dm < dsrtc_models + __arraycount(dsrtc_models); dm++) {
+               if (iic_use_direct_match(ia, cf, dm->dm_compats,
+                                        &match_result) == false)
+                       return false;
+               if (match_result > best_match)
+                       best_match = match_result;
+       }
+
+       *best_matchp = best_match;
+       return true;
+}
+
+static bool
+dsrtc_is_valid_addr_for_model(const struct dsrtc_model *dm, i2c_addr_t addr)
+{
+
+       for (int i = 0; dm->dm_valid_addrs[i] != 0; i++) {
+               if (addr == dm->dm_valid_addrs[i])
+                       return true;
+       }
+       return false;
+}
+
 static int
 dsrtc_match(device_t parent, cfdata_t cf, void *arg)
 {
        struct i2c_attach_args *ia = arg;
+       const struct dsrtc_model *dm;
+       int match_result;
 
-       if (ia->ia_name) {
-               /* direct config - check name */
-               if (strcmp(ia->ia_name, "dsrtc") == 0)
-                       return 1;
-       } else {
-               /* indirect config - check typical address */
-               if (ia->ia_addr == DS1307_ADDR || ia->ia_addr == MCP7940_ADDR)
-                       return dsrtc_model(cf->cf_flags & 0xffff) != NULL;
-       }
+       if (dsrtc_direct_match(ia, cf, &match_result))
+               return match_result;
+
+       dm = dsrtc_model_by_number(cf->cf_flags & 0xffff);
+       if (dm == NULL)
+               return 0;
+
+       if (dsrtc_is_valid_addr_for_model(dm, ia->ia_addr))
+               return I2C_MATCH_ADDRESS_ONLY;
+
        return 0;
 }
 
@@ -223,8 +303,15 @@
 {
        struct dsrtc_softc *sc = device_private(self);
        struct i2c_attach_args *ia = arg;
-       const struct dsrtc_model * const dm =
-           dsrtc_model(device_cfdata(self)->cf_flags);
+       const struct dsrtc_model *dm;
+
+       if ((dm = dsrtc_model_by_compat(ia)) == NULL)
+               dm = dsrtc_model_by_number(device_cfdata(self)->cf_flags);
+
+       if (dm == NULL) {
+               aprint_error(": unable to determine model!\n");
+               return;
+       }
 
        aprint_naive(": Real-time Clock%s\n",
            dm->dm_nvram_size > 0 ? "/NVRAM" : "");



Home | Main Index | Thread Index | Old Index