Hi Martin, thanks for your patch! As noted on the earlier patches I think this should be folded into the existing XHCI USB driver in drivers/usb/host/xhci-pci.c or, if that gets messy, as a separate bolt-on, something like xhci-pci-gpio.[c|h] in the drivers/usb/host/* directory. You can use a Kconfig symbol for the GPIO portions or not. On Sun, Oct 4, 2020 at 8:00 PM Martin Blumenstingl <martin.blumenstingl@xxxxxxxxxxxxxx> wrote: > EJ168/EJ188/EJ198 are USB xHCI controllers. They also contain four GPIO > lines which are used on some systems to toggle an LED based on whether a > USB device is connected. > > There is no public datasheet available for this hardware. All > information in this driver is taken from the > "F9K1115v2.03.97-GPL-10.2.85-20140313" GPL code dump of the Belkin > F9K1115v2. This board comes with an EJ168 USB xHCI controller and the > USB 3.0 LED is connected to one of the GPIOs. Inside the GPL source > archive the related code can be found in: > linux/kernels/mips-linux-2.6.31/drivers/usb/host/etxhci-pci.c > > Signed-off-by: Martin Blumenstingl <martin.blumenstingl@xxxxxxxxxxxxxx> (...) > +config GPIO_EJ1X8 > + tristate "Etron Tech Inc. EJ168/EJ188/EJ198 GPIO driver" > + depends on OF_GPIO && PCI It is fine to just select GPIOLIB if you want this to always be compiled-in (if the USB maintainers agree). > + help > + Selecting this option will enable the GPIO pins present on > + the Etron Tech Inc. EJ168/EJ188/EJ198 USB xHCI controllers. > + > + If unsure, say N. (...) > +#define EJ1X8_GPIO_INIT 0x44 > +#define EJ1X8_GPIO_WRITE 0x68 > +#define EJ1X8_GPIO_READ 0x6c > + > +#define EJ1X8_GPIO_CTRL 0x18005020 > +#define EJ1X8_GPIO_CTRL_READ_ALL_MASK GENMASK(7, 0) > +#define EJ1X8_GPIO_CTRL_WRITE_ALL_MASK GENMASK(23, 16) > +#define EJ1X8_GPIO_CTRL_OUT_LOW 0x0 > +#define EJ1X8_GPIO_CTRL_OUT_HIGH 0x1 > +#define EJ1X8_GPIO_CTRL_IN 0x2 > +#define EJ1X8_GPIO_CTRL_MASK 0x3 > + > +#define EJ1X8_GPIO_MODE 0x18005022 > +#define EJ1X8_GPIO_MODE_READ_WRITE_ALL_MASK GENMASK(23, 16) > +#define EJ1X8_GPIO_MODE_DISABLE 0x0 > +#define EJ1X8_GPIO_MODE_ENABLE 0x1 > +#define EJ1X8_GPIO_MODE_MASK 0x3 Nice that you got all of this out of reverse-engineering! > +static LIST_HEAD(ej1x8_gpios); This should not be necessary. Tie the GPIO state into the PCI device driver state, possibly using some #ifdefs. > +static u8 ej1x8_gpio_shift(unsigned int gpio, u8 mask) > +{ > + return (gpio * fls(mask)); > +} > + > +static u8 ej1x8_gpio_mask(unsigned int gpio, u8 mask) > +{ > + return mask << ej1x8_gpio_shift(gpio, mask); > +} This looks a bit like regmap but trying to use regmap for this would probably be overengineering. Looking at the code I get annoyed that it uses the config space to manipulate the GPIOs, else you could have used GPIO_GENERIC but now you can't, how typical. Other than that the code looks nice, but fold it into the USB host driver somehow unless there is a compelling argument as to why not. Yours, Linus Walleij