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