On Thu, Aug 08, 2019 at 10:23:48PM +0000, Matthew Michilot wrote: > Enable support for cbus gpios on FT232H. The cbus configuration is > stored in one word in the EEPROM at byte-offset 0x1a with the mux It seems to be stored in two words. > config for ACBUS5, ACBUS6, ACBUS8 and ACBUS9 (only pins that can be > configured as I/O mode). > > Tested using FT232H by configuring one ACBUS pin at a time. > > Review-by: Tim Harvey <tharvey@xxxxxxxxxxxxx> typo: Reviewed-by > Signed-off-by: Matthew Michilot <matthew.michilot@xxxxxxxxx> > --- > drivers/usb/serial/ftdi_sio.c | 43 +++++++++++++++++++++++++++++++++++ > 1 file changed, 43 insertions(+) > > diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c > index 4b3a049561f3..c8d35faa8f61 100644 > --- a/drivers/usb/serial/ftdi_sio.c > +++ b/drivers/usb/serial/ftdi_sio.c > @@ -2023,6 +2023,46 @@ static int ftdi_read_eeprom(struct usb_serial *serial, void *dst, u16 addr, > return 0; > } > > +static int ftdi_gpio_init_ft232h(struct usb_serial_port *port) > +{ > + struct ftdi_private *priv = usb_get_serial_port_data(port); > + u8 *buf; > + u16 cbus_config; > + int ret; > + int i; > + > + buf = kmalloc(2, GFP_KERNEL); > + if (!buf) > + return -ENOMEM; > + > + ret = ftdi_read_eeprom(port->serial, buf, 0x1A, 4); You allocate 2 byte above, but write 4 bytes into buf here. Please also use lower-case hex notation consistently throughout. > + if (ret < 0) > + goto out_free; > + > + /* > + * FT232H CBUS Memory Map > + * > + * 0x1A: 8X (upper nibble -> AC5) > + * 0x1B: X8 (lower nibble -> AC6) > + * 0x1C: 88 (upper nibble -> AC8 | lower nibble -> AC9) > + */ > + cbus_config = (((buf[0] & 0xf0) | (buf[1] & 0xf)) << 8 | buf[2]); Have you verified the order you use here by enabling one gpio at a time and toggling it? The reason I ask is that the above would give a mapping of gpio0 -> AC9 gpio1 -> AC8 gpio2 -> AC6 gpio4 -> AC5 which looks backwards but may be correct. Also please drop the outer parentheses in the above expression. > + > + priv->gc.ngpio = 4; > + priv->gpio_altfunc = 0xff; > + > + for (i = 0; i < priv->gc.ngpio; ++i) { > + if ((cbus_config & 0xf) == FTDI_FTX_CBUS_MUX_GPIO) > + priv->gpio_altfunc &= ~BIT(i); > + cbus_config >>= 4; > + } > + > +out_free: > + kfree(buf); > + > + return ret; > +} > + > static int ftdi_gpio_init_ft232r(struct usb_serial_port *port) > { > struct ftdi_private *priv = usb_get_serial_port_data(port); > @@ -2104,6 +2144,9 @@ static int ftdi_gpio_init(struct usb_serial_port *port) > case FTX: > result = ftdi_gpio_init_ftx(port); > break; > + case FT232H: > + result = ftdi_gpio_init_ft232h(port); > + break; Please keep the case labels sorted alphabetically. > default: > return 0; > } Johan