.\" $NetBSD: umcpmio.4,v 1.7 2025/11/29 18:39:14 brad Exp $ .\" .\" Copyright (c) 2024, 2025 Brad Spencer .\" .\" Permission to use, copy, modify, and distribute this software for any .\" purpose with or without fee is hereby granted, provided that the above .\" copyright notice and this permission notice appear in all copies. .\" .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" .Dd November 13, 2025 .Dt UMCPMIO 4 .Os .Sh NAME .Nm umcpmio .Nd Driver for Microchip Technologies MCP2210 and MCP2221 / MCP2221A multi-io bridge chips. .Sh SYNOPSIS .Cd "umcpmio* at uhidev? reportid ?" .Cd "gpio* at gpiobus?" .Cd "spi* at umcpmio?" .Cd "iic* at umcpmio?" or .Cd "iic* at i2cbus?" .Sh DESCRIPTION The .Nm driver provides support for the MCP2210 and MCP2221 / MCP2221A multi-io bridge chips. The MCP2210 provides 9 simple gpio pins with multiple functions that attach as a .Xr gpio 4 device and the ability to do SPI via the .Xr spi 4 framework. The pins function as .Xr gpio 4 pins or as chip select for the .Xr spi 4 function. The MCP2221 provides 4 simple gpio pins with multiple functions that attach as a .Xr gpio 4 device, an I2C port that attaches as an .Xr iic 4 device and a UART serial port that attaches using .Xr umodem 4 as a normal .Xr ucom 4 .Pa ttyU Ns Ar \&* device. The UART is presented as one USB function, while the GPIO and I2C pins are presented as a second HID USB function. .Ss GPIO ON THE MCP2210 There are 9 basic gpio pins available with the following functions: .Bd -filled -offset indent .TS box tab(:); l | l | l | l | l | l | l | l | l | l = | = | = | = | = | = | = | = | = | = l | l | l | l | l | l | l | l | l | l l | l | l | l | l | l | l | l | l | l l | l | l | l | l | l | l | l | l | l l | l | l | l | l | l | l | l | l | l l | l | l | l | l | l | l | l | l | l l | l | l | l | l | l | l | l | l | l l | l | l | l | l | l | l | l | l | l. Assignment:GP0:GP1:GP2:GP3:GP4:GP5:GP6:GP7:GP8 GPIO:I/O:I/O:I/O:I/O:I/O:I/O:I/O:I/O:I ALT0:CS:CS:CS:CS:CS:CS:CS:CS:- ALT3:-:-:SSPND:SPI activity:LOWPWR:USBCFG:Falling edge:Release ACK:Release REQ ALT4:-:-:-:-:-:-:Rising edge:-:- ALT5:-:-:-:-:-:-:Low pulse:-:- ALT6:-:-:-:-:-:-:High pulse:-:- .TE .Ed .Pp The IRQ counter on GP6 can be read with a .Xr sysctl 8 . The manor in which the GP6 IRQ counter detects the event is configured by setting it to ALT3 to ALT6. GP8 is only an input pin when configured for gpio purposes. The chip select, CS, function will be enabled automatically if a request to use the .Xr spi 8 framework is performed that requests the use of the associated chip select pin. .Pp .Ss SPI The MCP2210 supports a basic SPI engine via the .Xr spi 8 framework. Various SPI delays are configured with .Xr umcpmioctl 8 . .Pp The SPI engine on the MCP2210 only functions in full duplex mode. That is, it is not possible to just send bytes without also receiving them. The driver will queue up any recived bytes that might have come though on a transaction and present them to the upstream layer from the queue when asked. This queue will be cleared out for a particular slave address when a configuration call is made against a particular slave device. .Pp Upon making a configuration call to the .Nm driver, the driver will set the pin associated with the requested slave address to ALT0. Since the .Xr spi 8 framework does not support the notion of a session, this pin will never be reset by the .Nm driver. Further, it is entirely possible to use .Xr gpioctl 8 to change the pin assignment in such a way that SPI no longer works as it is also not possible to know if a pin is in use at any moment in time. .Ss EEPROM The MCP2210 has 256 bytes of EEPROM available via the .Pa /dev/umcpmio0EEP device. Random reads and writes may be performed against this device, but there can only one one opener at a time. .Ss GPIO ON THE MCP2221 There are 4 basic gpio pins available with the following functions: .Bd -filled -offset indent .TS box tab(:); l | l | l | l | l = | = | = | = | = l | l | l | l | l l | l | l | l | l l | l | l | l | l l | l | l | l | l. Assignment:GP0:GP1:GP2:GP3 GPIO:I/O:I/O:I/O:I/O ALT0:UART RX:ADC1:ADC2:ADC3 ALT1:-:UART TX:DAC1:DAC2 ALT2:-:IRQ:-:- ALT3:SSPND:Clock output:USBCFG:I2C activity .TE .Ed .Pp ADC1, ADC2 and ADC3 are independent of each other and each 10 bits in length. To utilize one of the ADC pins, an .Xr open 2 is performed against .Pa /dev/umcpmio0GP1 , .Pa /dev/umcpmio0GP2 or .Pa /dev/umcpmio0GP3 with only the .Dv O_RDONLY flag set. Reads against the open file descriptor will produce .Vt uint16_t values. .Pp There is actually only one DAC present in the chip, but it is mirrored to GP2 and GP3 if the pin is set to ALT1. The DAC is 5 bits in length, and to use it, an .Xr open 2 is performed against .Pa /dev/umcpmio0GP2 or .Pa /dev/umcpmio0GP3 with only the .Dv O_WRONLY flag set. Writes of .Vt uint8_t bytes to the file descriptor will result in an analog signal being created on the output pin. .Pp The clock output is derived from the USB clock of 48MHz. The duty cycle and clock divider can be adjusted with .Xr sysctl 8 variables. To utilize GP1 as the clock output, the ALT3 function can be set with .Xr gpioctl 8 command. .Ss I2C The MCP2221 / MCP2221A supports a hardware I2C port with a simple scripting engine. When the driver attaches, the I2C speed is set to 100Kb/s. The ability to perform an I2C READ without a STOP is not supported by the MCP2221 / MCP2221A engine and the driver turns a READ without STOP into a READ with STOP. This behavior is just an attempt to allow a device to function, and it may not work for any particular device. In particular, it is known that the .Xr ds2482ow 4 device will not work as expected. .Pp The MCP2221 / MCP2221A chip will automatically detect and deal with a device that uses I2C clock stretching. .Ss UART The UART on the MCP2221 / MCP2221A utilizes the .Xr umodem 4 driver. The UART function of the chip only supports .Tn 8-N-1 communications. .Sh SYSCTL VARIABLES ON BOTH CHIP TYPES The following .Xr sysctl 3 variables are provided: . .Pp .Bl -tag -width Li -compact . .It Li hw.umcpmio0.debug .It Li hw.umcpmio0.dump_buffers If .Dv UMCPMIO_DEBUG is defined, additional debugging output can be enabled. . .Pp .It Li hw.umcpmio0.response_wait .It Li hw.umcpmio0.response_errcnt This is how long the driver will wait for a HID response to come back from the chip. This variable is in microseconds and defaults to 2500. The driver will only allow .Li response_errcnt number of errors when waiting for a response from a HID report. This includes timeouts due to exceeding .Li response_wait . . .El .Sh SYSCTL VARIABLES ON THE MCP2210 .Bl -tag -width Li -compact .It Li hw.umcpmio0.spi.verbose Enable or disable verbose connection reset messages when there are errors. .It Li hw.umcpmio0.spi.busy_delay When the MCP2210 is busy, use busy_delay number of ms to wait before trying the operation again. The default is 0 as there usually will not be any reason is wait. .It Li hw.umcpmio0.spi.retry_busy_chipdrain .It Li hw.umcpmio0.spi.retry_busy_transfer The number of times to retry either a chipdrain or transfer operation. A chipdrain is used when the chip has sent back data, but the upstream is not ready for it yet. A transfer is a normal SPI transfer. .It Li hw.umcpmio0.gpio.counter .It Li hw.umcpmio0.gpio.reset_counter When the GP6 pin is set to ALT3 to ALT6, this sysctl reads back the counter. To reset the counter write 1 to the reset_counter sysctl. The counter will also be reset if any pin changes from a input or output pin to one of the ALT functions or vise versa. The trigger for this could be the use of .Xr gpioctl 8 or if the pin is changed to become a CS from a general I/O pin for the .Xr spi 4 infrastructure. .El . .Sh SYSCTL VARIABLES ON THE MCP2221 / MCP2221A .Bl -tag -width Li -compact .It Li hw.umcpmio0.i2c.reportreadnostop Report on the console if a driver attempts to use an I2C READ without STOP. A READ without STOP is not supported by the MCP2221 / MCP2221A I2C engine and will be turned into a READ with STOP by the driver. . .Pp .It Li hw.umcpmio0.i2c.busy_delay The driver checks in a number of cases if the I2C engine is busy and will wait for .Li busy_delay microseconds before checking again. . .Pp .It Li hw.umcpmio0.i2c.retry_busy_read The number of times to try to do an I2C READ when the engine is busy. . .Pp .It Li hw.umcpmio0.i2c.retry_busy_write The number of times to try to do an I2C WRITE when the engine is busy. . .Pp .It Li hw.umcpmio0.gpio.clock_duty_cycle .It Li hw.umcpmio0.gpio.clock_divider When GP1 is configured to use function ALT3, it will output a clock pulse. The valid values for .Li clock_duty_cycle are .Ql 75% , .Ql 50% , .Ql 25% , and .Ql \^0% . That is, 75% of the time a high and 25% of the time a low will be present on the GP1 pin. The valid values for .Li clock_divider are .Ql 375kHz , .Ql 750kHz , .Ql 1.5MHz , .Ql 3MHz , .Ql 6MHz , .Ql 12MHz , and .Ql 24MHz . . .Pp .It Li hw.umcpmio0.dac.vref .It Li hw.umcpmio0.adc.vref Sets the VREF value for the DAC or ADC. The valid values are .Ql 4.096V , .Ql 2.048V , .Ql 1.024V , .Ql OFF , and .Ql VDD . . .El . .Sh FILES .Bl -tag -width Pa -compact .It Pa /dev/umcpmio0ctl A control device for the chip instance that allows for a number of IOCTLs. .Pp .It Pa /dev/umcpmio0GP1 .It Pa /dev/umcpmio0GP2 .It Pa /dev/umcpmio0GP3 Device files that allow access to the ADC or DAC functions of the associated gpio pin on the MCP2221 / MCP2221A. .Pp .It Pa /dev/umcpmio0EEP Device file that interacts with the EEPROM on the MCP2210. .El .Sh SEE ALSO .Xr gpio 4 , .Xr iic 4 , .Xr sysctl 8 , .Xr umcpmioctl 8 .Sh HISTORY The .Nm driver first appeared in .Nx 11.0 . Support for the MCP2210 was added in .Nx 12.0 . .Sh AUTHORS .An -nosplit The .Nm driver was written by .An Brad Spencer Aq Mt brad@anduin.eldar.org . .Sh BUGS The gpio pins on the these two chips are very slow and one should not expect to be able to rapidly change their state. Even if the problem mentioned below did not exist, one should not expect to be able to use any of the gpio bit banger drivers such as .Xr gpioiic 4 or .Xr gpioow 4 . .Pp The interrupt function of the MCP2221 / MCP2221A on GP1 cannot currently be used because it is currently not possible to attach through the driver. There may be two possible problems going on: .Bl -bullet .It The .Xr gpio 4 framework runs at .Dv IPL_VM with a spin lock and when it attempts to establish an interrupt that uses the gpio from .Xr umcpmio 4 , calls are made into the USB stack that will want to wait in a way that is not allowed while holding a spin lock. . .It .Xr autoconf 9 runs with .Dv KERNEL_LOCK and during the attachment, this lock is held when calls are made into the USB stack that will cause a wait that is not allowed while holding .Dv KERNEL_LOCK . .El . .Pp Either or both of these may be going on, but the end result is that the kernel will panic while attempting to perform a USB transfer while another driver is attempting to attach through .Xr umcpmio 4 . .Pp Likewise, a .Ql \|gpioctl gpio1 attach ...\| type call will also panic for the same reason. .Pp The end result is that .Xr gpioirq 4 , .Xr gpiopps 4 and .Xr gpioow 4 will not work with the gpio from .Xr umcpio 4 . .Pp Please note that the .Xr umcpmio 4 driver itself can use the USB stack during attachment and there does not appear to be any problems using the GPIO pins or setting GPIO pin configurations. It is only when the driver is a target during another driver's attachment that there is a problem. .Pp The ability to set or change values in most of the chip's FLASH memory is not supported. This includes changing the configuration protection password. Likewise, support for entering the configuration protection password does not exist, should a particular chip have password protection enabled. .Pp On the MCP2210, changing any pin from INPUT or OUTPUT to ALTx or vise versa has to rewrite some of the setting for all pins. A consequence of doing this is that for a very brief time, the default direction and values will be set on all pins. This has the biggest impact on OUTPUT pins which might generate a small pulse. This behavior really can't be avoided as there is no way with the MCP2210 to write the configuration of just one pin at a time. For this same reason, the IRQ event counter will be reset if any pin switches from INPUT or OUTPUT to ALTx or vise versa. .Pp The MCP2210 supports active high or active low CS signals per CS. However, the .Xr spi 8 framework does not have any way to specify the direction of the CS signal, so the only SPI CS signal supported is the usual active low signal.