USB: serial: cp210x: fix alternate function for CP2102N QFN20

The QFN20 part has a different GPIO/port function assignment. The
configuration struct bit field ordered as TX/RX/RS485/WAKEUP/CLK
which exactly matches GPIO0-3 for QFN24/28. However, QFN20 has a
different GPIO to primary function assignment.

Special case QFN20 to follow to properly detect which GPIOs are
available.

Signed-off-by: Stefan Agner <stefan@agner.ch>
Link: https://lore.kernel.org/r/51830b2b24118eb0f77c5c9ac64ffb2f519dbb1d.1622218300.git.stefan@agner.ch
Fixes: c8acfe0aadbe ("USB: serial: cp210x: implement GPIO support for CP2102N")
Cc: stable@vger.kernel.org # 4.19
Signed-off-by: Johan Hovold <johan@kernel.org>

authored by Stefan Agner and committed by Johan Hovold 6f7ec77c bc96c72d

+19 -1
+19 -1
drivers/usb/serial/cp210x.c
··· 537 537 #define CP210X_2NCONFIG_GPIO_RSTLATCH_IDX 587 538 538 #define CP210X_2NCONFIG_GPIO_CONTROL_IDX 600 539 539 540 + /* CP2102N QFN20 port configuration values */ 541 + #define CP2102N_QFN20_GPIO2_TXLED_MODE BIT(2) 542 + #define CP2102N_QFN20_GPIO3_RXLED_MODE BIT(3) 543 + #define CP2102N_QFN20_GPIO1_RS485_MODE BIT(4) 544 + #define CP2102N_QFN20_GPIO0_CLK_MODE BIT(6) 545 + 540 546 /* CP210X_VENDOR_SPECIFIC, CP210X_WRITE_LATCH call writes these 0x2 bytes. */ 541 547 struct cp210x_gpio_write { 542 548 u8 mask; ··· 1739 1733 priv->gpio_pushpull = (gpio_pushpull >> 3) & 0x0f; 1740 1734 1741 1735 /* 0 indicates GPIO mode, 1 is alternate function */ 1742 - priv->gpio_altfunc = (gpio_ctrl >> 2) & 0x0f; 1736 + if (priv->partnum == CP210X_PARTNUM_CP2102N_QFN20) { 1737 + /* QFN20 is special... */ 1738 + if (gpio_ctrl & CP2102N_QFN20_GPIO0_CLK_MODE) /* GPIO 0 */ 1739 + priv->gpio_altfunc |= BIT(0); 1740 + if (gpio_ctrl & CP2102N_QFN20_GPIO1_RS485_MODE) /* GPIO 1 */ 1741 + priv->gpio_altfunc |= BIT(1); 1742 + if (gpio_ctrl & CP2102N_QFN20_GPIO2_TXLED_MODE) /* GPIO 2 */ 1743 + priv->gpio_altfunc |= BIT(2); 1744 + if (gpio_ctrl & CP2102N_QFN20_GPIO3_RXLED_MODE) /* GPIO 3 */ 1745 + priv->gpio_altfunc |= BIT(3); 1746 + } else { 1747 + priv->gpio_altfunc = (gpio_ctrl >> 2) & 0x0f; 1748 + } 1743 1749 1744 1750 if (priv->partnum == CP210X_PARTNUM_CP2102N_QFN28) { 1745 1751 /*