UMCPMIO(4)
π¦ NAME π¦
okay so bestie, welcome to umcpmio β the driver for the Microchip Technologies MCP2221 / MCP2221A multi-io bridge. that's it, that's the vibe, periodt. π
β¨ SYNOPSIS β¨
umcpmio* at uhidev? reportid ?
gpio* at gpiobus?
iic* at umcpmio? or
iic* at i2cbus?
like, that's literally the whole configuration aesthetic π«Ά
π DESCRIPTION π
so the umcpmio driver is here to hold your hand through the MCP2221 / MCP2221A multi-io bridge chip, and honestly? iconic. the chip serves up 4 simple gpio pins that have all these different functions, and they attach as a gpio(4) device. it also gives you an I2C port that attaches as an iic(4) device, plus a UART serial port that attaches using umodem(4) as a totally normal ucom(4) ttyU* device. no cap.
here's the lil plot twist tho: the UART is presented as one USB function, while the GPIO and I2C pins are presented as a second HID USB function. two functions, one chip, main character energy fr. π
π GPIO π
so there are 4 basic gpio pins and each one has its own little roster of functions. vibe check:
- Assignment
GPIOGP0βGPIOGP1βGPIOGP2βGPIOGP3βGPIO
- Assignment
ALT0GP0βUART RXGP1βADC1GP2βADC2GP3βADC3
- Assignment
ALT1GP0β-GP1βUART TXGP2βDAC1GP3βDAC2
- Assignment
ALT2GP0β-GP1βIRQGP2β-GP3β-
- Assignment
ALT3GP0βSSPNDGP1βClock outputGP2βUSBCFGGP3βI2C activity
now the tea on the ADC: ADC1, ADC2 and ADC3 are independent of each other and each one is 10 bits in length. to actually utilize one of the ADC pins, you do an open(2) against /dev/umcpmio0GP1, /dev/umcpmio0GP2 or /dev/umcpmio0GP3 with only the O_RDONLY flag set. reads against the open file descriptor will produce uint16_t values. slay. π
and the DAC? okay so 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. it's 5 bits in length, and to use it you do an open(2) against /dev/umcpmio0GP2 or /dev/umcpmio0GP3 with only the O_WRONLY flag set. writes of uint8_t bytes to the file descriptor will result in an analog signal being created on the output pin. it's giving magic, honestly. β¨
the clock output is derived from the USB clock of 48MHz. you can adjust the duty cycle and clock divider with sysctl(8) variables (more on those below, iykyk). to utilize GP1 as the clock output, you can set the ALT3 function with the gpioctl(8) command. go off. π
πΈ I2C πΈ
the chip supports a hardware I2C port with a simple scripting engine. when the driver attaches, the I2C speed is set to 100Kb/s.
now listen bestie, this part matters: 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 ds2482ow(4) device will not work as expected. so like, don't come for the driver when it doesn't work, it literally tried its best. π
the good news? the MCP2221 / MCP2221A chip will automatically detect and deal with a device that uses I2C clock stretching. we love an effortless queen. π
π§ UART π§
the UART utilizes the umodem(4) driver, and the UART function of the chip only supports 8-N-1 communications. that's the whole menu, no substitutions. π
β SYSCTL VARIABLES β
the following sysctl(3) variables are provided, and yes, they're all named after your fave:
hw.umcpmio0.debughw.umcpmio0.dump_buffersβ ifUMCPMIO_DEBUGis defined, additional debugging output can be enabled. πhw.umcpmio0.response_waithw.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 to2500. the driver will only allowresponse_errcntnumber of errors when waiting for a response from a HID report. this includes timeouts due to exceedingresponse_wait. so it's a whole patience situation. β³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. bestie got receipts. πhw.umcpmio0.i2c.busy_delayβ the driver checks in a number of cases if the I2C engine is busy and will wait forbusy_delaymicroseconds before checking again. it's the "are you done yet" of sysctls fr. πhw.umcpmio0.i2c.retry_busy_readβ the number of times to try to do an I2C READ when the engine is busy.hw.umcpmio0.i2c.retry_busy_writeβ the number of times to try to do an I2C WRITE when the engine is busy.hw.umcpmio0.gpio.clock_duty_cyclehw.umcpmio0.gpio.clock_dividerβ whenGP1is configured to use functionALT3, it will output a clock pulse. the valid values forclock_duty_cycleareβ75%β,β50%β,β25%β, andβ0%β. that is, 75% of the time a high and 25% of the time a low will be present on theGP1pin. the valid values forclock_dividerareβ375kHzβ,β750kHzβ,β1.5MHzβ,β3MHzβ,β6MHzβ,β12MHzβ, andβ24MHzβ. pick your fave, they're all valid. ποΈhw.umcpmio0.dac.vrefhw.umcpmio0.adc.vrefβ sets the VREF value for the DAC or ADC. the valid values areβ4.096Vβ,β2.048Vβ,β1.024Vβ,βOFFβ, andβVDDβ. voltage queen. β‘
π FILES π
/dev/umcpmio0ctlβ a control device for the chip instance that allows for a number of IOCTLs. π/dev/umcpmio0GP1/dev/umcpmio0GP2/dev/umcpmio0GP3β device files that allow access to the ADC or DAC functions of the associated gpio pin. π
π SEE ALSO π
gpio(4), iic(4), sysctl(8), umcpmioctl(8)
go read them, they're literally your study buddies. π«Ά
π¦ HISTORY π¦
the umcpmio driver first appeared in NetBSD 11.0. a whole era. π
π AUTHORS π
the umcpmio driver was written by Brad Spencer <brad@anduin.eldar.org>. thank you for your service, legend. π«‘
π BUGS π
okay bestie, sit down, we gotta talk. π
the gpio pins on the MCP2221 / MCP2221A 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 gpioiic(4) or gpioow(4). they're just not built for that kinda speed, and honestly same. π
the interrupt function 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:
- the
gpio(4)framework runs atIPL_VMwith a spin lock and when it attempts to establish an interrupt that uses the gpio fromumcpmio(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. autoconf(9)runs withKERNEL_LOCKand 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 holdingKERNEL_LOCK.
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 umcpmio(4). ππ
likewise, a βgpioctl gpio1 attach ...β type call will also panic for the same reason. yeah. π
the end result is that gpioirq(4), gpiopps(4) and gpioow(4) will not work with the gpio from umcpio(4).
please note that the 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. π«Ά
and last thing: 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. so like, don't @ us. π
and that's the whole page, bestie!! this lil rewrite was brought to you by the Debian crew, dated December 16, 2024 β mwah, go touch a gpio pin responsibly π β¨
π¦ where this page comes from
- nixpkgs unstable: netbsd-source 11.0
- Copyright (c) 2024 Brad Spencer <brad@anduin.eldar.org>
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms