Index: dev/spi/m25p.c =================================================================== RCS file: /cvsroot/src/sys/dev/spi/m25p.c,v retrieving revision 1.18 retrieving revision 1.18.8.1 diff -u -p -r1.18 -r1.18.8.1 --- dev/spi/m25p.c 14 May 2021 09:25:14 -0000 1.18 +++ dev/spi/m25p.c 9 Aug 2021 00:30:09 -0000 1.18.8.1 @@ -1,4 +1,4 @@ -/* $NetBSD: m25p.c,v 1.18 2021/05/14 09:25:14 jmcneill Exp $ */ +/* $NetBSD: m25p.c,v 1.18.8.1 2021/08/09 00:30:09 thorpej Exp $ */ /*- * Copyright (c) 2006 Urbana-Champaign Independent Media Center. @@ -42,7 +42,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: m25p.c,v 1.18 2021/05/14 09:25:14 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: m25p.c,v 1.18.8.1 2021/08/09 00:30:09 thorpej Exp $"); #include #include @@ -125,17 +125,8 @@ static int m25p_match(device_t parent, cfdata_t cf, void *aux) { struct spi_attach_args *sa = aux; - int res; - res = spi_compatible_match(sa, cf, compat_data); - if (!res) - return res; - - /* configure for 20MHz, which is the max for normal reads */ - if (spi_configure(sa->sa_handle, SPI_MODE_0, 20000000)) - res = 0; - - return res; + return spi_compatible_match(sa, cf, compat_data); } static void @@ -143,12 +134,21 @@ m25p_attach(device_t parent, device_t se { struct m25p_softc *sc = device_private(self); struct spi_attach_args *sa = aux; + int error; sc->sc_sh = sa->sa_handle; aprint_normal("\n"); aprint_naive("\n"); + /* configure for 20MHz, which is the max for normal reads */ + error = spi_configure(sa->sa_handle, SPI_MODE_0, 20000000); + if (error) { + aprint_error_dev(self, "spi_configure failed (error = %d)\n", + error); + return; + } + config_interrupts(self, m25p_doattach); } Index: dev/spi/mcp23s17.c =================================================================== RCS file: /cvsroot/src/sys/dev/spi/mcp23s17.c,v retrieving revision 1.4 retrieving revision 1.4.2.1 diff -u -p -r1.4 -r1.4.2.1 --- dev/spi/mcp23s17.c 7 Aug 2021 16:19:16 -0000 1.4 +++ dev/spi/mcp23s17.c 9 Aug 2021 00:30:09 -0000 1.4.2.1 @@ -1,4 +1,4 @@ -/* $NetBSD: mcp23s17.c,v 1.4 2021/08/07 16:19:16 thorpej Exp $ */ +/* $NetBSD: mcp23s17.c,v 1.4.2.1 2021/08/09 00:30:09 thorpej Exp $ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: mcp23s17.c,v 1.4 2021/08/07 16:19:16 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mcp23s17.c,v 1.4.2.1 2021/08/09 00:30:09 thorpej Exp $"); /* * Driver for Microchip MCP23S17 GPIO @@ -39,6 +39,7 @@ __KERNEL_RCSID(0, "$NetBSD: mcp23s17.c,v */ #include "gpio.h" +#include "opt_fdt.h" #include #include @@ -51,9 +52,12 @@ __KERNEL_RCSID(0, "$NetBSD: mcp23s17.c,v #include #include - #include +#ifdef FDT +#include +#endif /* FDT */ + /* #define MCP23S17_DEBUG */ #ifdef MCP23S17_DEBUG int mcp23S17debug = 3; @@ -87,25 +91,88 @@ static void mcp23s17gpio_gpio_pin_ct CFATTACH_DECL_NEW(mcp23s17gpio, sizeof(struct mcp23s17gpio_softc), mcp23s17gpio_match, mcp23s17gpio_attach, NULL, NULL); +static const struct device_compatible_entry compat_data[] = { + { .compat = "mcp,mcp23s17" }, + { .compat = "microchip,mcp23s17" }, + +#if 0 /* We should also add support for these: */ + { .compat = "mcp,mcp23s08" }, + { .compat = "microchip,mcp23s08" }, + + { .compat = "microchip,mcp23s18" }, +#endif + + DEVICE_COMPAT_EOL +}; + static int mcp23s17gpio_match(device_t parent, cfdata_t cf, void *aux) { struct spi_attach_args *sa = aux; - /* MCP23S17 has no way to detect it! */ + return spi_compatible_match(sa, cf, compat_data); +} - /* run at 10MHz */ - if (spi_configure(sa->sa_handle, SPI_MODE_0, 10000000)) - return 0; +#ifdef FDT +static bool +mcp23s17gpio_ha_fdt(struct mcp23s17gpio_softc *sc) +{ + devhandle_t devhandle = device_handle(sc->sc_dev); + int phandle = devhandle_to_of(devhandle); + uint32_t mask; + int count; + + /* + * The number of devices sharing this chip select, + * along with their assigned addresses, is encoded + * in the "microchip,spi-present-mask" property. + * + * N.B. we also check for "mcp,spi-present-mask" if + * the first one isn't present (it's a deprecated + * property that may be present in older device trees). + */ + if (of_getprop_uint32(phandle, "microchip,spi-present-mask", + &mask) != 0 || + of_getprop_uint32(phandle, "mcp,spi-present-mask", + &mask) != 0) { + aprint_error( + ": missing \"microchip,spi-present-mask\" property\n"); + return false; + } + + /* + * If we ever support the mcp23s08, then only bits 0-3 are valid + * on that device. + */ + if (mask == 0 || mask > __BITS(0,7)) { + aprint_error( + ": invalid \"microchip,spi-present-mask\" property\n"); + return false; + } - return 1; + count = popcount32(mask); + if (count > 1) { + /* + * XXX We only support a single chip on this chip + * select for now. + */ + aprint_error(": unsupported %d-chip configuration\n", count); + return false; + } + + sc->sc_ha = ffs(mask) - 1; + KASSERT(sc->sc_ha >= 0 && sc->sc_ha <= 7); + + return true; } +#endif /* FDT */ static void mcp23s17gpio_attach(device_t parent, device_t self, void *aux) { struct mcp23s17gpio_softc *sc; struct spi_attach_args *sa; + int error; #if NGPIO > 0 int i; struct gpiobus_attach_args gba; @@ -116,15 +183,53 @@ mcp23s17gpio_attach(device_t parent, dev sc->sc_dev = self; sc->sc_sh = sa->sa_handle; sc->sc_bank = 0; - sc->sc_ha = device_cfdata(sc->sc_dev)->cf_flags & 0x7; + + /* + * The MCP23S17 can multiplex multiple chips on the same + * chip select. + * + * If we got here using indirect configuration, our kernel + * config file directive has our address. Otherwise, we need + * to consult the device tree used for direct configuration. + */ + if (sa->sa_name == NULL) { + sc->sc_ha = device_cfdata(sc->sc_dev)->cf_flags & 0x7; + } else { + devhandle_t devhandle = device_handle(self); + + switch (devhandle_type(devhandle)) { +#ifdef FDT + case DEVHANDLE_TYPE_OF: + if (! mcp23s17gpio_ha_fdt(sc)) { + /* Error alredy displayed. */ + return; + } + break; +#endif /* FDT */ + default: + aprint_error(": unsupported device handle type\n"); + return; + } + } aprint_naive(": GPIO\n"); aprint_normal(": MCP23S17 GPIO (ha=%d)\n", sc->sc_ha); + /* run at 10MHz */ + error = spi_configure(sa->sa_handle, SPI_MODE_0, 10000000); + if (error) { + aprint_error_dev(self, "spi_configure failed (error = %d)\n", + error); + return; + } + DPRINTF(1, ("%s: initialize (HAEN|SEQOP)\n", device_xname(sc->sc_dev))); /* basic setup */ - mcp23s17gpio_write(sc, MCP23x17_IOCONA(sc->sc_bank), MCP23x17_IOCON_HAEN|MCP23x17_IOCON_SEQOP); + mcp23s17gpio_write(sc, MCP23x17_IOCONA(sc->sc_bank), + MCP23x17_IOCON_HAEN|MCP23x17_IOCON_SEQOP); + + /* XXX Hook up to FDT GPIO. */ #if NGPIO > 0 for (i = 0; i < MCP23x17_GPIO_NPINS; i++) { Index: dev/spi/mcp3k.c =================================================================== RCS file: /cvsroot/src/sys/dev/spi/mcp3k.c,v retrieving revision 1.2 retrieving revision 1.2.46.1 diff -u -p -r1.2 -r1.2.46.1 --- dev/spi/mcp3k.c 20 Nov 2016 12:38:04 -0000 1.2 +++ dev/spi/mcp3k.c 9 Aug 2021 00:30:09 -0000 1.2.46.1 @@ -1,4 +1,4 @@ -/* $NetBSD: mcp3k.c,v 1.2 2016/11/20 12:38:04 phx Exp $ */ +/* $NetBSD: mcp3k.c,v 1.2.46.1 2021/08/09 00:30:09 thorpej Exp $ */ /*- * Copyright (c) 2015 The NetBSD Foundation, Inc. @@ -45,6 +45,8 @@ * MPC3302/3304: http://ww1.microchip.com/downloads/en/DeviceDoc/21697F.pdf */ +#include "opt_fdt.h" + #include #include #include @@ -55,6 +57,10 @@ #include #include +#ifdef FDT +#include +#endif /* FDT */ + #define M3K_MAX_SENSORS 16 /* 8 single-ended & 8 diff. */ /* mcp3x0x model description */ @@ -72,14 +78,17 @@ 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; +#ifdef FDT + struct fdtbus_regulator *sc_vref_supply; +#endif - 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,127 +100,257 @@ 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; + + 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; + } + } - if (strcmp(cf->cf_name, "mcp3kadc") != 0) - return 0; + return rv; +} - /* configure for 1MHz */ - if (spi_configure(sa->sa_handle, SPI_MODE_0, 1000000)) - return 0; +#ifdef FDT +static bool +mcp3kadc_vref_fdt(struct mcp3kadc_softc *sc) +{ + devhandle_t devhandle = device_handle(sc->sc_dev); + int phandle = devhandle_to_of(devhandle); + int error; + u_int uvolts; + + sc->sc_vref_supply = fdtbus_regulator_acquire(phandle, "vref-supply"); + if (sc->sc_vref_supply == NULL) { + aprint_error_dev(sc->sc_dev, + "unable to acquire \"vref-supply\"\n"); + return false; + } - return 1; + error = fdtbus_regulator_enable(sc->sc_vref_supply); + if (error) { + aprint_error_dev(sc->sc_dev, + "failed to enable \"vref-supply\" (error = %d)\n", + error); + return false; + } + + error = fdtbus_regulator_get_voltage(sc->sc_vref_supply, &uvolts); + if (error) { + aprint_error_dev(sc->sc_dev, + "unable to get \"vref-supply\" voltage (error = %d)\n", + error); + (void) fdtbus_regulator_disable(sc->sc_vref_supply); + return false; + } + + /* + * Device tree property is uV, convert to mV that we use + * internally. + */ + sc->sc_vref_mv = uvolts / 1000; + return true; } +#endif /* FDT */ 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; - int ch, i; + struct spi_attach_args *sa = aux; + struct mcp3kadc_softc *sc = device_private(self); + devhandle_t devhandle = device_handle(self); + const struct mcp3kadc_model *model; + int ch, i, error; + bool vref_read_only; - 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); - /* 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); + /* configure for 1MHz */ + error = spi_configure(sa->sa_handle, SPI_MODE_0, 1000000); + if (error) { + aprint_error_dev(self, "spi_configure failed (error = %d)\n", + error); + return; + } + + vref_read_only = false; + switch (devhandle_type(devhandle)) { +#ifdef FDT + case DEVHANDLE_TYPE_OF: + vref_read_only = mcp3kadc_vref_fdt(sc); + if (! vref_read_only) { + /* Error already displayed. */ + return; + } + break; +#endif /* FDT */ + default: + /* + * 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); + break; + } + /* remember maximum value for this ADC - also used for masking */ sc->sc_adc_max = (1 << model->bits) - 1; @@ -266,9 +405,11 @@ mcp3kadc_attach(device_t parent, device_ NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL); + const int ctlflag = vref_read_only ? CTLFLAG_READONLY + : CTLFLAG_READWRITE; if (rnode != NULL) sysctl_createv(NULL, 0, NULL, &node, - CTLFLAG_READWRITE | CTLFLAG_OWNDESC, + ctlflag | CTLFLAG_OWNDESC, CTLTYPE_INT, "vref", SYSCTL_DESCR("ADC reference voltage"), sysctl_mcp3kadc_vref, 0, (void *)sc, 0, @@ -279,12 +420,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) { Index: dev/spi/mcp48x1.c =================================================================== RCS file: /cvsroot/src/sys/dev/spi/mcp48x1.c,v retrieving revision 1.1 retrieving revision 1.1.64.1 diff -u -p -r1.1 -r1.1.64.1 --- dev/spi/mcp48x1.c 25 Feb 2014 20:09:37 -0000 1.1 +++ dev/spi/mcp48x1.c 9 Aug 2021 00:30:09 -0000 1.1.64.1 @@ -1,4 +1,4 @@ -/* $NetBSD: mcp48x1.c,v 1.1 2014/02/25 20:09:37 rkujawa Exp $ */ +/* $NetBSD: mcp48x1.c,v 1.1.64.1 2021/08/09 00:30:09 thorpej Exp $ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: mcp48x1.c,v 1.1 2014/02/25 20:09:37 rkujawa Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mcp48x1.c,v 1.1.64.1 2021/08/09 00:30:09 thorpej Exp $"); /* * Driver for Microchip MCP4801/MCP4811/MCP4821 DAC. @@ -57,7 +57,7 @@ __KERNEL_RCSID(0, "$NetBSD: mcp48x1.c,v #define MCP48X1DAC_DATA __BITS(11,0) /* data */ struct mcp48x1dac_model { - const char *name; + u_int name; uint8_t resolution; uint8_t shift; /* data left shift during write */ }; @@ -66,7 +66,7 @@ struct mcp48x1dac_softc { device_t sc_dev; struct spi_handle *sc_sh; - struct mcp48x1dac_model *sc_dm; /* struct describing DAC model */ + const struct mcp48x1dac_model *sc_dm; uint16_t sc_dac_data; bool sc_dac_gain; @@ -93,55 +93,102 @@ static int sysctl_mcp48x1dac_gain(SYSCTL CFATTACH_DECL_NEW(mcp48x1dac, sizeof(struct mcp48x1dac_softc), mcp48x1dac_match, mcp48x1dac_attach, NULL, NULL); -static struct mcp48x1dac_model mcp48x1_models[] = { - { - .name = "MCP4801", - .resolution = 8, - .shift = 4 - }, - { - .name = "MCP4811", - .resolution = 10, - .shift = 2 - }, - { - .name = "MCP4821", - .resolution = 12, - .shift = 0 - } +static const struct mcp48x1dac_model mcp4801 = { + .name = 4801, + .resolution = 8, + .shift = 4 +}; + +static const struct mcp48x1dac_model mcp4811 = { + .name = 4811, + .resolution = 10, + .shift = 2 +}; + +static const struct mcp48x1dac_model mcp4821 = { + .name = 4821, + .resolution = 12, + .shift = 0 +}; + +static const struct device_compatible_entry compat_data[] = { + { .compat = "microchip,mcp4801", .data = &mcp4801 }, + { .compat = "microchip,mcp4811", .data = &mcp4811 }, + { .compat = "microchip,mcp4821", .data = &mcp4821 }, + DEVICE_COMPAT_EOL }; +static const struct mcp48x1dac_model * +mcp48x1dac_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 mcp48x1dac_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 mcp48x1dac_match(device_t parent, cfdata_t cf, void *aux) { struct spi_attach_args *sa = aux; + int rv; - /* MCP48x1 is a write-only device, so no way to detect it! */ - - if (spi_configure(sa->sa_handle, SPI_MODE_0, 20000000)) - return 0; + rv = spi_compatible_match(sa, cf, compat_data); + if (rv != 0) { + /* + * If we're doing indorect config, the user must + * have specified the correct model. + */ + if (sa->sa_clist == NULL && mcp48x1dac_lookup(sa, cf) == NULL) { + return 0; + } + } - return 1; + return rv; } static void mcp48x1dac_attach(device_t parent, device_t self, void *aux) { - struct mcp48x1dac_softc *sc; - struct spi_attach_args *sa; - int cf_flags; - - aprint_naive(": Digital to Analog converter\n"); - aprint_normal(": MCP48x1 DAC\n"); + struct mcp48x1dac_softc *sc = device_private(self); + struct spi_attach_args *sa = aux; + const struct mcp48x1dac_model *model; + int error; - sa = aux; - sc = device_private(self); sc->sc_dev = self; sc->sc_sh = sa->sa_handle; - cf_flags = device_cfdata(sc->sc_dev)->cf_flags; - sc->sc_dm = &mcp48x1_models[cf_flags]; /* flag value defines model */ + model = mcp48x1dac_lookup(sa, device_cfdata(self)); + KASSERT(model != NULL); + + sc->sc_dm = model; + + aprint_naive(": Digital to Analog converter\n"); + aprint_normal(": MCP%u DAC\n", model->name); + + /* configure for 20MHz */ + error = spi_configure(sa->sa_handle, SPI_MODE_0, 20000000); + if (error) { + aprint_error_dev(self, "spi_configure failed (error = %d)\n", + error); + return; + } if(!mcp48x1dac_envsys_attach(sc)) { aprint_error_dev(sc->sc_dev, "failed to attach envsys\n"); Index: dev/spi/oj6sh.c =================================================================== RCS file: /cvsroot/src/sys/dev/spi/oj6sh.c,v retrieving revision 1.9 retrieving revision 1.9.2.1 diff -u -p -r1.9 -r1.9.2.1 --- dev/spi/oj6sh.c 7 Aug 2021 16:19:16 -0000 1.9 +++ dev/spi/oj6sh.c 9 Aug 2021 00:30:09 -0000 1.9.2.1 @@ -1,4 +1,4 @@ -/* $NetBSD: oj6sh.c,v 1.9 2021/08/07 16:19:16 thorpej Exp $ */ +/* $NetBSD: oj6sh.c,v 1.9.2.1 2021/08/09 00:30:09 thorpej Exp $ */ /* * Copyright (c) 2014 Genetec Corporation. All rights reserved. @@ -31,7 +31,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: oj6sh.c,v 1.9 2021/08/07 16:19:16 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: oj6sh.c,v 1.9.2.1 2021/08/09 00:30:09 thorpej Exp $"); #include "opt_oj6sh.h" @@ -138,8 +138,6 @@ oj6sh_match(device_t parent, cfdata_t cf if (spi_compatible_match(sa, cf, compat_data) == 0) return 0; - if (spi_configure(sa->sa_handle, SPI_MODE_0, 2500000)) - return 0; return 2; } @@ -184,10 +182,18 @@ oj6sh_attach(device_t parent, device_t s struct oj6sh_softc *sc = device_private(self); struct spi_attach_args *sa = aux; struct wsmousedev_attach_args a; + int errir; aprint_naive("\n"); aprint_normal(": OJ6SH-T25 Optical Joystick\n"); + error = spi_configure(sa->sa_handle, SPI_MODE_0, 2500000); + if (error) { + aprint_error_dev(self, "spi_configure failed (error = %d)\n", + error); + return; + } + mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); sc->sc_dev = self; Index: dev/spi/ssdfb_spi.c =================================================================== RCS file: /cvsroot/src/sys/dev/spi/ssdfb_spi.c,v retrieving revision 1.9 retrieving revision 1.9.2.1 diff -u -p -r1.9 -r1.9.2.1 --- dev/spi/ssdfb_spi.c 5 Aug 2021 19:17:22 -0000 1.9 +++ dev/spi/ssdfb_spi.c 9 Aug 2021 00:30:09 -0000 1.9.2.1 @@ -1,4 +1,4 @@ -/* $NetBSD: ssdfb_spi.c,v 1.9 2021/08/05 19:17:22 tnn Exp $ */ +/* $NetBSD: ssdfb_spi.c,v 1.9.2.1 2021/08/09 00:30:09 thorpej Exp $ */ /* * Copyright (c) 2019 The NetBSD Foundation, Inc. @@ -30,19 +30,20 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ssdfb_spi.c,v 1.9 2021/08/05 19:17:22 tnn Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ssdfb_spi.c,v 1.9.2.1 2021/08/09 00:30:09 thorpej Exp $"); #include #include #include #include #include + #include #include #include "opt_fdt.h" #ifdef FDT #include -#endif +#endif /* FDT */ struct bs_state { uint8_t *base; @@ -56,7 +57,7 @@ struct ssdfb_spi_softc { #ifdef FDT struct fdtbus_gpio_pin *sc_gpio_dc; struct fdtbus_gpio_pin *sc_gpio_res; -#endif +#endif /* FDT */ bool sc_3wiremode; }; @@ -95,40 +96,72 @@ static int ssdfb_spi_match(device_t parent, cfdata_t match, void *aux) { struct spi_attach_args *sa = aux; - int res; - res = spi_compatible_match(sa, match, compat_data); - if (!res) - return res; + return spi_compatible_match(sa, match, compat_data); +} - /* - * SSD1306 and SSD1322 data sheets specify 100ns cycle time. - */ - if (spi_configure(sa->sa_handle, SPI_MODE_0, 10000000)) - res = 0; +#ifdef FDT +static void +ssdfb_spi_gpio_fdt(struct ssdfb_spi_softc *sc) +{ + devhandle_t devhandle = device_handle(sc->sc.sc_dev); + int phandle = devhandle_to_of(devhandle); - return res; + sc->sc_gpio_dc = fdtbus_gpio_acquire(phandle, "dc-gpio", + GPIO_PIN_OUTPUT); + if (sc->sc_gpio_dc == NULL) { + sc->sc_gpio_dc = fdtbus_gpio_acquire(phandle, "cd-gpio", + GPIO_PIN_OUTPUT); + } + if (sc->sc_gpio_dc != NULL) { + sc->sc_3wiremode = false; + } + + sc->sc_gpio_res = fdtbus_gpio_acquire(phandle, "res-gpio", + GPIO_PIN_OUTPUT); + if (sc->sc_gpio_res) { + fdtbus_gpio_write_raw(sc->sc_gpio_res, 0); + DELAY(100); + fdtbus_gpio_write_raw(sc->sc_gpio_res, 1); + DELAY(100); + } } +#endif /* FDT */ static void ssdfb_spi_attach(device_t parent, device_t self, void *aux) { struct ssdfb_spi_softc *sc = device_private(self); + devhandle_t devhandle = device_handle(self); struct cfdata *cf = device_cfdata(self); struct spi_attach_args *sa = aux; int flags = cf->cf_flags; + int error; sc->sc.sc_dev = self; sc->sc_sh = sa->sa_handle; sc->sc.sc_cookie = (void *)sc; + + /* + * SSD1306 and SSD1322 data sheets specify 100ns cycle time. + */ + error = spi_configure(sa->sa_handle, SPI_MODE_0, 10000000); + if (error) { + aprint_error(": spi_configure failed (error = %d)\n", + error); + return; + } + if ((flags & SSDFB_ATTACH_FLAG_PRODUCT_MASK) == SSDFB_PRODUCT_UNKNOWN) { const struct device_compatible_entry *dce = - device_compatible_lookup(sa->sa_compat, sa->sa_ncompat, compat_data); + device_compatible_lookup(sa->sa_compat, sa->sa_ncompat, + compat_data); if (dce) flags |= (int)dce->value; else flags |= SSDFB_PRODUCT_SSD1322_GENERIC; } + /* * Note on interface modes. * @@ -137,26 +170,20 @@ ssdfb_spi_attach(device_t parent, device * * 4 wire mode sends 8 bit sequences and requires an auxiliary GPIO * pin for the command/data bit. + * + * Default to 3 wire mode. If the device tree specifies a + * D/C GPIO pin, then we will use 4 wire mode. */ + sc->sc_3wiremode = true; + switch (devhandle_type(devhandle)) { #ifdef FDT - const int phandle = sa->sa_cookie; - sc->sc_gpio_dc = - fdtbus_gpio_acquire(phandle, "dc-gpio", GPIO_PIN_OUTPUT); - if (!sc->sc_gpio_dc) - sc->sc_gpio_dc = - fdtbus_gpio_acquire(phandle, "cd-gpio", GPIO_PIN_OUTPUT); - sc->sc_3wiremode = (sc->sc_gpio_dc == NULL); - sc->sc_gpio_res = - fdtbus_gpio_acquire(phandle, "res-gpio", GPIO_PIN_OUTPUT); - if (sc->sc_gpio_res) { - fdtbus_gpio_write_raw(sc->sc_gpio_res, 0); - DELAY(100); - fdtbus_gpio_write_raw(sc->sc_gpio_res, 1); - DELAY(100); + case DEVHANDLE_TYPE_OF: + ssdfb_spi_gpio_fdt(sc); + break; +#endif /* FDT */ + default: + break; } -#else - sc->sc_3wiremode = true; -#endif sc->sc.sc_cmd = sc->sc_3wiremode ? ssdfb_spi_cmd_3wire @@ -303,11 +330,15 @@ ssdfb_bitstream_final(struct bs_state *s static void ssdfb_spi_4wire_set_dc(struct ssdfb_spi_softc *sc, int value) { + /* TODO: refactor this if we ever support more that just FDT. */ + #ifdef FDT - fdtbus_gpio_write_raw(sc->sc_gpio_dc, value); + KASSERT(sc->sc_gpio_dc != NULL); + fdtbus_gpio_write(sc->sc_dc_gpio, value); #else + /* TODO: this should toggle an auxilliary GPIO pin */ panic("ssdfb_spi_4wire_set_dc"); -#endif +#endif /* FDT */ } static int Index: dev/spi/tmp121.c =================================================================== RCS file: /cvsroot/src/sys/dev/spi/tmp121.c,v retrieving revision 1.5 retrieving revision 1.5.82.1 diff -u -p -r1.5 -r1.5.82.1 --- dev/spi/tmp121.c 20 Jun 2011 17:31:37 -0000 1.5 +++ dev/spi/tmp121.c 9 Aug 2021 00:30:09 -0000 1.5.82.1 @@ -1,4 +1,4 @@ -/* $NetBSD: tmp121.c,v 1.5 2011/06/20 17:31:37 pgoyette Exp $ */ +/* $NetBSD: tmp121.c,v 1.5.82.1 2021/08/09 00:30:09 thorpej Exp $ */ /*- * Copyright (c) 2006 Urbana-Champaign Independent Media Center. @@ -42,7 +42,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: tmp121.c,v 1.5 2011/06/20 17:31:37 pgoyette Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tmp121.c,v 1.5.82.1 2021/08/09 00:30:09 thorpej Exp $"); #include #include @@ -68,16 +68,31 @@ static void tmp121temp_refresh(struct sy CFATTACH_DECL_NEW(tmp121temp, sizeof(struct tmp121temp_softc), tmp121temp_match, tmp121temp_attach, NULL, NULL); +static const struct device_compatible_entry compat_data[] = { + { .compat = "ti,tmp121" }, + { .compat = "TMP00121" }, + +#if 0 /* We should also add support for these: */ + { .compat = "ti,tmp122" }, + + { .compat = "ti,lm70" }, + { .compat = "LM000070" }, + + { .compat = "ti,lm71" }, + { .compat = "LM000071" }, + + { .compat = "ti,lm74" }, + { .compat = "LM000074" }, +#endif + DEVICE_COMPAT_EOL +}; + static int tmp121temp_match(device_t parent, cfdata_t cf, void *aux) { struct spi_attach_args *sa = aux; - /* configure for 10MHz */ - if (spi_configure(sa->sa_handle, SPI_MODE_0, 1000000)) - return 0; - - return 1; + return spi_compatible_match(sa, cf, compat_data); } static void @@ -85,10 +100,19 @@ tmp121temp_attach(device_t parent, devic { struct tmp121temp_softc *sc = device_private(self); struct spi_attach_args *sa = aux; + int error; aprint_naive(": Temperature Sensor\n"); aprint_normal(": TI TMP121 Temperature Sensor\n"); + /* configure for 10MHz */ + error = spi_configure(sa->sa_handle, SPI_MODE_0, 1000000); + if (error) { + aprint_error_dev(self, "spi_configure failed (error = %d)\n", + error); + return; + } + sc->sc_sh = sa->sa_handle; sc->sc_sme = sysmon_envsys_create();