Module Name: src
Committed By: thorpej
Date: Wed May 19 03:33:05 UTC 2021
Modified Files:
src/sys/dev/spi [thorpej-i2c-spi-conf]: mcp3k.c
Log Message:
Use spi_compatible_match().
XXX More work to do for proper FDT integration.
To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.2.36.1 src/sys/dev/spi/mcp3k.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/spi/mcp3k.c
diff -u src/sys/dev/spi/mcp3k.c:1.2 src/sys/dev/spi/mcp3k.c:1.2.36.1
--- src/sys/dev/spi/mcp3k.c:1.2 Sun Nov 20 12:38:04 2016
+++ src/sys/dev/spi/mcp3k.c Wed May 19 03:33:05 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: mcp3k.c,v 1.2 2016/11/20 12:38:04 phx Exp $ */
+/* $NetBSD: mcp3k.c,v 1.2.36.1 2021/05/19 03:33:05 thorpej Exp $ */
/*-
* Copyright (c) 2015 The NetBSD Foundation, Inc.
@@ -72,14 +72,14 @@ struct mcp3kadc_model {
};
struct mcp3kadc_softc {
- device_t sc_dev;
- struct spi_handle *sc_sh;
- int sc_model;
- uint32_t sc_adc_max;
- int32_t sc_vref_mv;
+ device_t sc_dev;
+ struct spi_handle *sc_sh;
+ const struct mcp3kadc_model *sc_model;
+ uint32_t sc_adc_max;
+ int32_t sc_vref_mv;
- struct sysmon_envsys *sc_sme;
- envsys_data_t sc_sensors[M3K_MAX_SENSORS];
+ struct sysmon_envsys *sc_sme;
+ envsys_data_t sc_sensors[M3K_MAX_SENSORS];
};
static int mcp3kadc_match(device_t, cfdata_t, void *);
@@ -91,124 +91,192 @@ static int sysctl_mcp3kadc_vref(SYSCTLFN
CFATTACH_DECL_NEW(mcp3kadc, sizeof(struct mcp3kadc_softc),
mcp3kadc_match, mcp3kadc_attach, NULL, NULL);
-static struct mcp3kadc_model mcp3k_models[] = {
- {
- .name = 3001,
- .bits = 10,
- .channels = 1,
- .lead = 3,
- .flags = 0
- },
- {
- .name = 3002,
- .bits = 10,
- .channels = 2,
- .lead = 2,
- .flags = M3K_SGLDIFF | M3K_MSBF
- },
- {
- .name = 3004,
- .bits = 10,
- .channels = 4,
- .lead = 2,
- .flags = M3K_SGLDIFF | M3K_D2D1D0
- },
- {
- .name = 3008,
- .bits = 10,
- .channels = 8,
- .lead = 2,
- .flags = M3K_SGLDIFF | M3K_D2D1D0
- },
- {
- .name = 3201,
- .bits = 12,
- .channels = 1,
- .lead = 3,
- .flags = 0
- },
- {
- .name = 3202,
- .bits = 12,
- .channels = 2,
- .lead = 2,
- .flags = M3K_SGLDIFF | M3K_MSBF
- },
- {
- .name = 3204,
- .bits = 12,
- .channels = 4,
- .lead = 2,
- .flags = M3K_SGLDIFF | M3K_D2D1D0
- },
- {
- .name = 3208,
- .bits = 12,
- .channels = 8,
- .lead = 2,
- .flags = M3K_SGLDIFF | M3K_D2D1D0
- },
- {
- .name = 3301,
- .bits = 13,
- .channels = 1,
- .lead = 3,
- .flags = M3K_SIGNED
- },
- {
- .name = 3302,
- .bits = 13,
- .channels = 4,
- .lead = 2,
- .flags = M3K_SIGNED | M3K_SGLDIFF | M3K_D2D1D0
- },
- {
- .name = 3304,
- .bits = 13,
- .channels = 8,
- .lead = 2,
- .flags = M3K_SIGNED | M3K_SGLDIFF | M3K_D2D1D0
- },
+static const struct mcp3kadc_model mcp3001 = {
+ .name = 3001,
+ .bits = 10,
+ .channels = 1,
+ .lead = 3,
+ .flags = 0
};
+static const struct mcp3kadc_model mcp3002 = {
+ .name = 3002,
+ .bits = 10,
+ .channels = 2,
+ .lead = 2,
+ .flags = M3K_SGLDIFF | M3K_MSBF
+};
+
+static const struct mcp3kadc_model mcp3004 = {
+ .name = 3004,
+ .bits = 10,
+ .channels = 4,
+ .lead = 2,
+ .flags = M3K_SGLDIFF | M3K_D2D1D0
+};
+
+static const struct mcp3kadc_model mcp3008 = {
+ .name = 3008,
+ .bits = 10,
+ .channels = 8,
+ .lead = 2,
+ .flags = M3K_SGLDIFF | M3K_D2D1D0
+};
+
+static const struct mcp3kadc_model mcp3201 = {
+ .name = 3201,
+ .bits = 12,
+ .channels = 1,
+ .lead = 3,
+ .flags = 0
+};
+
+static const struct mcp3kadc_model mcp3202 = {
+ .name = 3202,
+ .bits = 12,
+ .channels = 2,
+ .lead = 2,
+ .flags = M3K_SGLDIFF | M3K_MSBF
+};
+
+static const struct mcp3kadc_model mcp3204 = {
+ .name = 3204,
+ .bits = 12,
+ .channels = 4,
+ .lead = 2,
+ .flags = M3K_SGLDIFF | M3K_D2D1D0
+};
+
+static const struct mcp3kadc_model mcp3208 = {
+ .name = 3208,
+ .bits = 12,
+ .channels = 8,
+ .lead = 2,
+ .flags = M3K_SGLDIFF | M3K_D2D1D0
+};
+
+static const struct mcp3kadc_model mcp3301 = {
+ .name = 3301,
+ .bits = 13,
+ .channels = 1,
+ .lead = 3,
+ .flags = M3K_SIGNED
+};
+
+static const struct mcp3kadc_model mcp3302 = {
+ .name = 3302,
+ .bits = 13,
+ .channels = 4,
+ .lead = 2,
+ .flags = M3K_SIGNED | M3K_SGLDIFF | M3K_D2D1D0
+};
+
+static const struct mcp3kadc_model mcp3304 = {
+ .name = 3304,
+ .bits = 13,
+ .channels = 8,
+ .lead = 2,
+ .flags = M3K_SIGNED | M3K_SGLDIFF | M3K_D2D1D0
+};
+
+static const struct device_compatible_entry compat_data[] = {
+ { .compat = "microchip,mcp3001", .data = &mcp3001 },
+ { .compat = "microchip,mcp3002", .data = &mcp3002 },
+ { .compat = "microchip,mcp3004", .data = &mcp3004 },
+ { .compat = "microchip,mcp3008", .data = &mcp3008 },
+ { .compat = "microchip,mcp3201", .data = &mcp3201 },
+ { .compat = "microchip,mcp3202", .data = &mcp3202 },
+ { .compat = "microchip,mcp3204", .data = &mcp3204 },
+ { .compat = "microchip,mcp3208", .data = &mcp3208 },
+ { .compat = "microchip,mcp3301", .data = &mcp3301 },
+ { .compat = "microchip,mcp3302", .data = &mcp3302 },
+ { .compat = "microchip,mcp3304", .data = &mcp3304 },
+
+#if 0 /* We should also add support for these: */
+ { .compat = "microchip,mcp3550-50" },
+ { .compat = "microchip,mcp3550-60" },
+ { .compat = "microchip,mcp3551" },
+ { .compat = "microchip,mcp3553" },
+#endif
+
+ DEVICE_COMPAT_EOL
+};
+
+static const struct mcp3kadc_model *
+mcp3kadc_lookup(const struct spi_attach_args *sa, const cfdata_t cf)
+{
+ const struct device_compatible_entry *dce;
+
+ if (sa->sa_clist != NULL) {
+ dce = device_compatible_lookup_strlist(sa->sa_clist,
+ sa->sa_clist_size, compat_data);
+ if (dce == NULL) {
+ return NULL;
+ }
+ return dce->data;
+ } else {
+ const struct mcp3kadc_model *model;
+
+ for (dce = compat_data; dce->compat != NULL; dce++) {
+ model = dce->data;
+ if (model->name == cf->cf_flags) {
+ return model;
+ }
+ }
+ return NULL;
+ }
+}
+
static int
mcp3kadc_match(device_t parent, cfdata_t cf, void *aux)
{
struct spi_attach_args *sa = aux;
+ int rv;
- if (strcmp(cf->cf_name, "mcp3kadc") != 0)
- return 0;
+ rv = spi_compatible_match(sa, cf, compat_data);
+ if (rv != 0) {
+ /*
+ * If we're doing indirect config, the user must
+ * have specified the correct model.
+ */
+ if (sa->sa_clist == NULL && mcp3kadc_lookup(sa, cf) == NULL) {
+ return 0;
+ }
- /* configure for 1MHz */
- if (spi_configure(sa->sa_handle, SPI_MODE_0, 1000000))
- return 0;
+ /* configure for 1MHz */
+ if (spi_configure(sa->sa_handle, SPI_MODE_0, 1000000))
+ return 0;
+ }
- return 1;
+ return rv;
}
static void
mcp3kadc_attach(device_t parent, device_t self, void *aux)
{
const struct sysctlnode *rnode, *node;
- struct spi_attach_args *sa;
- struct mcp3kadc_softc *sc;
- struct mcp3kadc_model *model;
+ struct spi_attach_args *sa = aux;
+ struct mcp3kadc_softc *sc = device_private(self);
+ const struct mcp3kadc_model *model;
int ch, i;
- sa = aux;
- sc = device_private(self);
sc->sc_dev = self;
sc->sc_sh = sa->sa_handle;
- /* device flags define the model */
- sc->sc_model = device_cfdata(sc->sc_dev)->cf_flags;
- model = &mcp3k_models[sc->sc_model];
+ model = mcp3kadc_lookup(sa, device_cfdata(self));
+ KASSERT(model != NULL);
+
+ sc->sc_model = model;
aprint_naive(": Analog to Digital converter\n");
aprint_normal(": MCP%u %u-channel %u-bit ADC\n",
(unsigned)model->name, (unsigned)model->channels,
(unsigned)model->bits);
+ /*
+ * XXX Get vref-supply from device tree and make the sysctl
+ * XXX read-only in that case.
+ */
/* set a default Vref in mV according to the chip's ADC resolution */
sc->sc_vref_mv = 1 << ((model->flags & M3K_SIGNED) ?
model->bits - 1 : model->bits);
@@ -279,12 +347,12 @@ static void
mcp3kadc_envsys_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
{
struct mcp3kadc_softc *sc;
- struct mcp3kadc_model *model;
+ const struct mcp3kadc_model *model;
uint8_t buf[2], ctrl;
int32_t val, scale;
sc = sme->sme_cookie;
- model = &mcp3k_models[sc->sc_model];
+ model = sc->sc_model;
scale = sc->sc_adc_max + 1;
if (model->flags & M3K_CTRL_NEEDED) {