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