Message ID | 20220811153908.31283-2-henning.schild@siemens.com |
---|---|
State | New |
Headers | show |
Series | add support for another simatic board | expand |
Am Fri, 12 Aug 2022 10:37:02 +0200 schrieb Andy Shevchenko <andy.shevchenko@gmail.com>: > On Thursday, August 11, 2022, Henning Schild > <henning.schild@siemens.com> wrote: > > > Add GPIO support for Nuvoton NCT6116 chip. Nuvoton SuperIO chips are > > very similar to the ones from Fintek. In other subsystems they also > > share drivers and are called a family of drivers. > > > > For the GPIO subsystem the only difference is that the direction > > bit is reversed and that there is only one data bit per pin. On the > > SuperIO level the logical device is another one. > > > > Signed-off-by: Henning Schild <henning.schild@siemens.com> > > --- > > drivers/gpio/gpio-f7188x.c | 71 > > +++++++++++++++++++++++++++----------- 1 file changed, 51 > > insertions(+), 20 deletions(-) > > > > diff --git a/drivers/gpio/gpio-f7188x.c b/drivers/gpio/gpio-f7188x.c > > index 18a3147f5a42..7b05ecc611e9 100644 > > --- a/drivers/gpio/gpio-f7188x.c > > +++ b/drivers/gpio/gpio-f7188x.c > > @@ -1,6 +1,7 @@ > > // SPDX-License-Identifier: GPL-2.0-or-later > > /* > > * GPIO driver for Fintek Super-I/O F71869, F71869A, F71882, > > F71889 and F81866 > > + * and Nuvoton Super-I/O NCT6116D > > * > > * Copyright (C) 2010-2013 LaCie > > * > > @@ -22,13 +23,12 @@ > > #define SIO_LDSEL 0x07 /* Logical device select */ > > #define SIO_DEVID 0x20 /* Device ID (2 bytes) */ > > #define SIO_DEVREV 0x22 /* Device revision */ > > -#define SIO_MANID 0x23 /* Fintek ID (2 bytes) */ > > > > -#define SIO_LD_GPIO 0x06 /* GPIO logical device */ > > #define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O > > */ #define SIO_LOCK_KEY 0xAA /* Key to disable > > Super-I/O */ > > > > -#define SIO_FINTEK_ID 0x1934 /* Manufacturer ID */ > > +#define SIO_LD_GPIO_FINTEK 0x06 /* GPIO logical device */ > > +#define SIO_LD_GPIO_NUVOTON 0x07 /* GPIO logical device */ > > #define SIO_F71869_ID 0x0814 /* F71869 chipset ID */ > > #define SIO_F71869A_ID 0x1007 /* F71869A chipset ID */ > > #define SIO_F71882_ID 0x0541 /* F71882 chipset ID */ > > @@ -37,7 +37,7 @@ > > #define SIO_F81866_ID 0x1010 /* F81866 chipset ID */ > > #define SIO_F81804_ID 0x1502 /* F81804 chipset ID, same > > for f81966 */ > > #define SIO_F81865_ID 0x0704 /* F81865 chipset ID */ > > - > > > > Logical split by leaving blank line here is good to have. Already discussed those bits and changed them. There will be another round because i will re-introduce the vendor ID check. Let us see what that will do to those defines. But i will give Simon the last call here. > > > > +#define SIO_NCT6116D_ID 0xD283 /* NCT6116D chipset > > ID */ > > > > enum chips { > > f71869, > > @@ -48,6 +48,7 @@ enum chips { > > f81866, > > f81804, > > f81865, > > + nct6116d, > > }; > > > > static const char * const f7188x_names[] = { > > @@ -59,10 +60,12 @@ static const char * const f7188x_names[] = { > > "f81866", > > "f81804", > > "f81865", > > + "nct6116d", > > }; > > > > struct f7188x_sio { > > int addr; > > + int device; > > enum chips type; > > }; > > > > @@ -170,6 +173,9 @@ static int f7188x_gpio_set_config(struct > > gpio_chip *chip, unsigned offset, > > /* Output mode register (0:open drain 1:push-pull). */ > > #define gpio_out_mode(base) (base + 3) > > > > +#define gpio_dir_invert(type) ((type) == nct6116d) > > +#define gpio_data_single(type) ((type) == nct6116d) > > > > I think with namespace prefix it should be fine, otherwise it might > be a renaming burden in the future. > > Also I would rather see them static inline one-liners, so compiler > will perform a type check. > Simon already acked that. The additional code is in line with other code already in that file. So while your suggestion is valid and i also wondered why it was defines instead of inline functions, i will leave it like that for consistency reasons. Henning > > static struct f7188x_gpio_bank f71869_gpio_bank[] = { > > F7188X_GPIO_BANK(0, 6, 0xF0), > > F7188X_GPIO_BANK(10, 8, 0xE0), > > @@ -254,6 +260,17 @@ static struct f7188x_gpio_bank > > f81865_gpio_bank[] = { F7188X_GPIO_BANK(60, 5, 0x90), > > }; > > > > +static struct f7188x_gpio_bank nct6116d_gpio_bank[] = { > > + F7188X_GPIO_BANK(0, 8, 0xE0), > > + F7188X_GPIO_BANK(10, 8, 0xE4), > > + F7188X_GPIO_BANK(20, 8, 0xE8), > > + F7188X_GPIO_BANK(30, 8, 0xEC), > > + F7188X_GPIO_BANK(40, 8, 0xF0), > > + F7188X_GPIO_BANK(50, 8, 0xF4), > > + F7188X_GPIO_BANK(60, 8, 0xF8), > > + F7188X_GPIO_BANK(70, 1, 0xFC), > > +}; > > + > > static int f7188x_gpio_get_direction(struct gpio_chip *chip, > > unsigned offset) > > { > > int err; > > @@ -264,13 +281,16 @@ static int f7188x_gpio_get_direction(struct > > gpio_chip *chip, unsigned offset) > > err = superio_enter(sio->addr); > > if (err) > > return err; > > - superio_select(sio->addr, SIO_LD_GPIO); > > + superio_select(sio->addr, sio->device); > > > > dir = superio_inb(sio->addr, gpio_dir(bank->regbase)); > > > > superio_exit(sio->addr); > > > > - if (dir & 1 << offset) > > + if (gpio_dir_invert(sio->type)) > > + dir = ~dir; > > + > > + if (dir & BIT(offset)) > > return GPIO_LINE_DIRECTION_OUT; > > > > return GPIO_LINE_DIRECTION_IN; > > @@ -286,10 +306,14 @@ static int f7188x_gpio_direction_in(struct > > gpio_chip *chip, unsigned offset) > > err = superio_enter(sio->addr); > > if (err) > > return err; > > - superio_select(sio->addr, SIO_LD_GPIO); > > + superio_select(sio->addr, sio->device); > > > > dir = superio_inb(sio->addr, gpio_dir(bank->regbase)); > > - dir &= ~BIT(offset); > > + > > + if (gpio_dir_invert(sio->type)) > > + dir |= BIT(offset); > > + else > > + dir &= ~BIT(offset); > > superio_outb(sio->addr, gpio_dir(bank->regbase), dir); > > > > superio_exit(sio->addr); > > @@ -307,11 +331,11 @@ static int f7188x_gpio_get(struct gpio_chip > > *chip, unsigned offset) > > err = superio_enter(sio->addr); > > if (err) > > return err; > > - superio_select(sio->addr, SIO_LD_GPIO); > > + superio_select(sio->addr, sio->device); > > > > dir = superio_inb(sio->addr, gpio_dir(bank->regbase)); > > dir = !!(dir & BIT(offset)); > > - if (dir) > > + if (gpio_data_single(sio->type) || dir) > > data = superio_inb(sio->addr, > > gpio_data_out(bank->regbase)); > > else > > data = superio_inb(sio->addr, > > gpio_data_in(bank->regbase)); @@ -332,7 +356,7 @@ static int > > f7188x_gpio_direction_out(struct gpio_chip *chip, > > err = superio_enter(sio->addr); > > if (err) > > return err; > > - superio_select(sio->addr, SIO_LD_GPIO); > > + superio_select(sio->addr, sio->device); > > > > data_out = superio_inb(sio->addr, > > gpio_data_out(bank->regbase)); if (value) > > @@ -342,7 +366,10 @@ static int f7188x_gpio_direction_out(struct > > gpio_chip *chip, > > superio_outb(sio->addr, gpio_data_out(bank->regbase), > > data_out); > > > > dir = superio_inb(sio->addr, gpio_dir(bank->regbase)); > > - dir |= BIT(offset); > > + if (gpio_dir_invert(sio->type)) > > + dir &= ~BIT(offset); > > + else > > + dir |= BIT(offset); > > superio_outb(sio->addr, gpio_dir(bank->regbase), dir); > > > > superio_exit(sio->addr); > > @@ -360,7 +387,7 @@ static void f7188x_gpio_set(struct gpio_chip > > *chip, unsigned offset, int value) > > err = superio_enter(sio->addr); > > if (err) > > return; > > - superio_select(sio->addr, SIO_LD_GPIO); > > + superio_select(sio->addr, sio->device); > > > > data_out = superio_inb(sio->addr, > > gpio_data_out(bank->regbase)); if (value) > > @@ -388,7 +415,7 @@ static int f7188x_gpio_set_config(struct > > gpio_chip *chip, unsigned offset, > > err = superio_enter(sio->addr); > > if (err) > > return err; > > - superio_select(sio->addr, SIO_LD_GPIO); > > + superio_select(sio->addr, sio->device); > > > > data = superio_inb(sio->addr, gpio_out_mode(bank->regbase)); > > if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN) > > @@ -449,6 +476,10 @@ static int f7188x_gpio_probe(struct > > platform_device *pdev) > > data->nr_bank = ARRAY_SIZE(f81865_gpio_bank); > > data->bank = f81865_gpio_bank; > > break; > > + case nct6116d: > > + data->nr_bank = ARRAY_SIZE(nct6116d_gpio_bank); > > + data->bank = nct6116d_gpio_bank; > > + break; > > default: > > return -ENODEV; > > } > > @@ -485,12 +516,8 @@ static int __init f7188x_find(int addr, struct > > f7188x_sio *sio) > > return err; > > > > err = -ENODEV; > > - devid = superio_inw(addr, SIO_MANID); > > - if (devid != SIO_FINTEK_ID) { > > - pr_debug(DRVNAME ": Not a Fintek device at > > 0x%08x\n", addr); > > - goto err; > > - } > > > > + sio->device = SIO_LD_GPIO_FINTEK; > > devid = superio_inw(addr, SIO_DEVID); > > switch (devid) { > > case SIO_F71869_ID: > > @@ -517,8 +544,12 @@ static int __init f7188x_find(int addr, struct > > f7188x_sio *sio) > > case SIO_F81865_ID: > > sio->type = f81865; > > break; > > + case SIO_NCT6116D_ID: > > + sio->device = SIO_LD_GPIO_NUVOTON; > > + sio->type = nct6116d; > > + break; > > default: > > - pr_info(DRVNAME ": Unsupported Fintek device > > 0x%04x\n", devid); > > + pr_info(DRVNAME ": Unsupported device 0x%04x\n", > > devid); goto err; > > } > > sio->addr = addr; > > -- > > 2.35.1 > > > > >
Am Thu, 11 Aug 2022 17:39:05 +0200 schrieb Henning Schild <henning.schild@siemens.com>: > Add GPIO support for Nuvoton NCT6116 chip. Nuvoton SuperIO chips are > very similar to the ones from Fintek. In other subsystems they also > share drivers and are called a family of drivers. > > For the GPIO subsystem the only difference is that the direction bit > is reversed and that there is only one data bit per pin. On the > SuperIO level the logical device is another one. > > Signed-off-by: Henning Schild <henning.schild@siemens.com> > --- > drivers/gpio/gpio-f7188x.c | 71 > +++++++++++++++++++++++++++----------- 1 file changed, 51 > insertions(+), 20 deletions(-) > > diff --git a/drivers/gpio/gpio-f7188x.c b/drivers/gpio/gpio-f7188x.c > index 18a3147f5a42..7b05ecc611e9 100644 > --- a/drivers/gpio/gpio-f7188x.c > +++ b/drivers/gpio/gpio-f7188x.c > @@ -1,6 +1,7 @@ > // SPDX-License-Identifier: GPL-2.0-or-later > /* > * GPIO driver for Fintek Super-I/O F71869, F71869A, F71882, F71889 > and F81866 > + * and Nuvoton Super-I/O NCT6116D That Kconfig item could also use an update, will include in next version. Henning > * > * Copyright (C) 2010-2013 LaCie > * > @@ -22,13 +23,12 @@ > #define SIO_LDSEL 0x07 /* Logical device > select */ #define SIO_DEVID 0x20 /* Device ID > (2 bytes) */ #define SIO_DEVREV 0x22 /* Device > revision */ -#define SIO_MANID 0x23 /* Fintek > ID (2 bytes) */ > -#define SIO_LD_GPIO 0x06 /* GPIO logical > device */ #define SIO_UNLOCK_KEY 0x87 /* Key to > enable Super-I/O */ #define SIO_LOCK_KEY 0xAA > /* Key to disable Super-I/O */ > -#define SIO_FINTEK_ID 0x1934 /* Manufacturer > ID */ +#define SIO_LD_GPIO_FINTEK 0x06 /* GPIO logical > device */ +#define SIO_LD_GPIO_NUVOTON 0x07 /* GPIO > logical device */ #define SIO_F71869_ID 0x0814 > /* F71869 chipset ID */ #define SIO_F71869A_ID > 0x1007 /* F71869A chipset ID */ #define SIO_F71882_ID > 0x0541 /* F71882 chipset ID */ @@ -37,7 +37,7 @@ > #define SIO_F81866_ID 0x1010 /* F81866 chipset > ID */ #define SIO_F81804_ID 0x1502 /* F81804 chipset > ID, same for f81966 */ #define SIO_F81865_ID > 0x0704 /* F81865 chipset ID */ - > +#define SIO_NCT6116D_ID 0xD283 /* NCT6116D chipset > ID */ > enum chips { > f71869, > @@ -48,6 +48,7 @@ enum chips { > f81866, > f81804, > f81865, > + nct6116d, > }; > > static const char * const f7188x_names[] = { > @@ -59,10 +60,12 @@ static const char * const f7188x_names[] = { > "f81866", > "f81804", > "f81865", > + "nct6116d", > }; > > struct f7188x_sio { > int addr; > + int device; > enum chips type; > }; > > @@ -170,6 +173,9 @@ static int f7188x_gpio_set_config(struct > gpio_chip *chip, unsigned offset, /* Output mode register (0:open > drain 1:push-pull). */ #define gpio_out_mode(base) (base + 3) > > +#define gpio_dir_invert(type) ((type) == nct6116d) > +#define gpio_data_single(type) ((type) == nct6116d) > + > static struct f7188x_gpio_bank f71869_gpio_bank[] = { > F7188X_GPIO_BANK(0, 6, 0xF0), > F7188X_GPIO_BANK(10, 8, 0xE0), > @@ -254,6 +260,17 @@ static struct f7188x_gpio_bank > f81865_gpio_bank[] = { F7188X_GPIO_BANK(60, 5, 0x90), > }; > > +static struct f7188x_gpio_bank nct6116d_gpio_bank[] = { > + F7188X_GPIO_BANK(0, 8, 0xE0), > + F7188X_GPIO_BANK(10, 8, 0xE4), > + F7188X_GPIO_BANK(20, 8, 0xE8), > + F7188X_GPIO_BANK(30, 8, 0xEC), > + F7188X_GPIO_BANK(40, 8, 0xF0), > + F7188X_GPIO_BANK(50, 8, 0xF4), > + F7188X_GPIO_BANK(60, 8, 0xF8), > + F7188X_GPIO_BANK(70, 1, 0xFC), > +}; > + > static int f7188x_gpio_get_direction(struct gpio_chip *chip, > unsigned offset) { > int err; > @@ -264,13 +281,16 @@ static int f7188x_gpio_get_direction(struct > gpio_chip *chip, unsigned offset) err = superio_enter(sio->addr); > if (err) > return err; > - superio_select(sio->addr, SIO_LD_GPIO); > + superio_select(sio->addr, sio->device); > > dir = superio_inb(sio->addr, gpio_dir(bank->regbase)); > > superio_exit(sio->addr); > > - if (dir & 1 << offset) > + if (gpio_dir_invert(sio->type)) > + dir = ~dir; > + > + if (dir & BIT(offset)) > return GPIO_LINE_DIRECTION_OUT; > > return GPIO_LINE_DIRECTION_IN; > @@ -286,10 +306,14 @@ static int f7188x_gpio_direction_in(struct > gpio_chip *chip, unsigned offset) err = superio_enter(sio->addr); > if (err) > return err; > - superio_select(sio->addr, SIO_LD_GPIO); > + superio_select(sio->addr, sio->device); > > dir = superio_inb(sio->addr, gpio_dir(bank->regbase)); > - dir &= ~BIT(offset); > + > + if (gpio_dir_invert(sio->type)) > + dir |= BIT(offset); > + else > + dir &= ~BIT(offset); > superio_outb(sio->addr, gpio_dir(bank->regbase), dir); > > superio_exit(sio->addr); > @@ -307,11 +331,11 @@ static int f7188x_gpio_get(struct gpio_chip > *chip, unsigned offset) err = superio_enter(sio->addr); > if (err) > return err; > - superio_select(sio->addr, SIO_LD_GPIO); > + superio_select(sio->addr, sio->device); > > dir = superio_inb(sio->addr, gpio_dir(bank->regbase)); > dir = !!(dir & BIT(offset)); > - if (dir) > + if (gpio_data_single(sio->type) || dir) > data = superio_inb(sio->addr, > gpio_data_out(bank->regbase)); else > data = superio_inb(sio->addr, > gpio_data_in(bank->regbase)); @@ -332,7 +356,7 @@ static int > f7188x_gpio_direction_out(struct gpio_chip *chip, err = > superio_enter(sio->addr); if (err) > return err; > - superio_select(sio->addr, SIO_LD_GPIO); > + superio_select(sio->addr, sio->device); > > data_out = superio_inb(sio->addr, > gpio_data_out(bank->regbase)); if (value) > @@ -342,7 +366,10 @@ static int f7188x_gpio_direction_out(struct > gpio_chip *chip, superio_outb(sio->addr, > gpio_data_out(bank->regbase), data_out); > dir = superio_inb(sio->addr, gpio_dir(bank->regbase)); > - dir |= BIT(offset); > + if (gpio_dir_invert(sio->type)) > + dir &= ~BIT(offset); > + else > + dir |= BIT(offset); > superio_outb(sio->addr, gpio_dir(bank->regbase), dir); > > superio_exit(sio->addr); > @@ -360,7 +387,7 @@ static void f7188x_gpio_set(struct gpio_chip > *chip, unsigned offset, int value) err = superio_enter(sio->addr); > if (err) > return; > - superio_select(sio->addr, SIO_LD_GPIO); > + superio_select(sio->addr, sio->device); > > data_out = superio_inb(sio->addr, > gpio_data_out(bank->regbase)); if (value) > @@ -388,7 +415,7 @@ static int f7188x_gpio_set_config(struct > gpio_chip *chip, unsigned offset, err = superio_enter(sio->addr); > if (err) > return err; > - superio_select(sio->addr, SIO_LD_GPIO); > + superio_select(sio->addr, sio->device); > > data = superio_inb(sio->addr, gpio_out_mode(bank->regbase)); > if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN) > @@ -449,6 +476,10 @@ static int f7188x_gpio_probe(struct > platform_device *pdev) data->nr_bank = ARRAY_SIZE(f81865_gpio_bank); > data->bank = f81865_gpio_bank; > break; > + case nct6116d: > + data->nr_bank = ARRAY_SIZE(nct6116d_gpio_bank); > + data->bank = nct6116d_gpio_bank; > + break; > default: > return -ENODEV; > } > @@ -485,12 +516,8 @@ static int __init f7188x_find(int addr, struct > f7188x_sio *sio) return err; > > err = -ENODEV; > - devid = superio_inw(addr, SIO_MANID); > - if (devid != SIO_FINTEK_ID) { > - pr_debug(DRVNAME ": Not a Fintek device at > 0x%08x\n", addr); > - goto err; > - } > > + sio->device = SIO_LD_GPIO_FINTEK; > devid = superio_inw(addr, SIO_DEVID); > switch (devid) { > case SIO_F71869_ID: > @@ -517,8 +544,12 @@ static int __init f7188x_find(int addr, struct > f7188x_sio *sio) case SIO_F81865_ID: > sio->type = f81865; > break; > + case SIO_NCT6116D_ID: > + sio->device = SIO_LD_GPIO_NUVOTON; > + sio->type = nct6116d; > + break; > default: > - pr_info(DRVNAME ": Unsupported Fintek device > 0x%04x\n", devid); > + pr_info(DRVNAME ": Unsupported device 0x%04x\n", > devid); goto err; > } > sio->addr = addr;
diff --git a/drivers/gpio/gpio-f7188x.c b/drivers/gpio/gpio-f7188x.c index 18a3147f5a42..7b05ecc611e9 100644 --- a/drivers/gpio/gpio-f7188x.c +++ b/drivers/gpio/gpio-f7188x.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* * GPIO driver for Fintek Super-I/O F71869, F71869A, F71882, F71889 and F81866 + * and Nuvoton Super-I/O NCT6116D * * Copyright (C) 2010-2013 LaCie * @@ -22,13 +23,12 @@ #define SIO_LDSEL 0x07 /* Logical device select */ #define SIO_DEVID 0x20 /* Device ID (2 bytes) */ #define SIO_DEVREV 0x22 /* Device revision */ -#define SIO_MANID 0x23 /* Fintek ID (2 bytes) */ -#define SIO_LD_GPIO 0x06 /* GPIO logical device */ #define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */ #define SIO_LOCK_KEY 0xAA /* Key to disable Super-I/O */ -#define SIO_FINTEK_ID 0x1934 /* Manufacturer ID */ +#define SIO_LD_GPIO_FINTEK 0x06 /* GPIO logical device */ +#define SIO_LD_GPIO_NUVOTON 0x07 /* GPIO logical device */ #define SIO_F71869_ID 0x0814 /* F71869 chipset ID */ #define SIO_F71869A_ID 0x1007 /* F71869A chipset ID */ #define SIO_F71882_ID 0x0541 /* F71882 chipset ID */ @@ -37,7 +37,7 @@ #define SIO_F81866_ID 0x1010 /* F81866 chipset ID */ #define SIO_F81804_ID 0x1502 /* F81804 chipset ID, same for f81966 */ #define SIO_F81865_ID 0x0704 /* F81865 chipset ID */ - +#define SIO_NCT6116D_ID 0xD283 /* NCT6116D chipset ID */ enum chips { f71869, @@ -48,6 +48,7 @@ enum chips { f81866, f81804, f81865, + nct6116d, }; static const char * const f7188x_names[] = { @@ -59,10 +60,12 @@ static const char * const f7188x_names[] = { "f81866", "f81804", "f81865", + "nct6116d", }; struct f7188x_sio { int addr; + int device; enum chips type; }; @@ -170,6 +173,9 @@ static int f7188x_gpio_set_config(struct gpio_chip *chip, unsigned offset, /* Output mode register (0:open drain 1:push-pull). */ #define gpio_out_mode(base) (base + 3) +#define gpio_dir_invert(type) ((type) == nct6116d) +#define gpio_data_single(type) ((type) == nct6116d) + static struct f7188x_gpio_bank f71869_gpio_bank[] = { F7188X_GPIO_BANK(0, 6, 0xF0), F7188X_GPIO_BANK(10, 8, 0xE0), @@ -254,6 +260,17 @@ static struct f7188x_gpio_bank f81865_gpio_bank[] = { F7188X_GPIO_BANK(60, 5, 0x90), }; +static struct f7188x_gpio_bank nct6116d_gpio_bank[] = { + F7188X_GPIO_BANK(0, 8, 0xE0), + F7188X_GPIO_BANK(10, 8, 0xE4), + F7188X_GPIO_BANK(20, 8, 0xE8), + F7188X_GPIO_BANK(30, 8, 0xEC), + F7188X_GPIO_BANK(40, 8, 0xF0), + F7188X_GPIO_BANK(50, 8, 0xF4), + F7188X_GPIO_BANK(60, 8, 0xF8), + F7188X_GPIO_BANK(70, 1, 0xFC), +}; + static int f7188x_gpio_get_direction(struct gpio_chip *chip, unsigned offset) { int err; @@ -264,13 +281,16 @@ static int f7188x_gpio_get_direction(struct gpio_chip *chip, unsigned offset) err = superio_enter(sio->addr); if (err) return err; - superio_select(sio->addr, SIO_LD_GPIO); + superio_select(sio->addr, sio->device); dir = superio_inb(sio->addr, gpio_dir(bank->regbase)); superio_exit(sio->addr); - if (dir & 1 << offset) + if (gpio_dir_invert(sio->type)) + dir = ~dir; + + if (dir & BIT(offset)) return GPIO_LINE_DIRECTION_OUT; return GPIO_LINE_DIRECTION_IN; @@ -286,10 +306,14 @@ static int f7188x_gpio_direction_in(struct gpio_chip *chip, unsigned offset) err = superio_enter(sio->addr); if (err) return err; - superio_select(sio->addr, SIO_LD_GPIO); + superio_select(sio->addr, sio->device); dir = superio_inb(sio->addr, gpio_dir(bank->regbase)); - dir &= ~BIT(offset); + + if (gpio_dir_invert(sio->type)) + dir |= BIT(offset); + else + dir &= ~BIT(offset); superio_outb(sio->addr, gpio_dir(bank->regbase), dir); superio_exit(sio->addr); @@ -307,11 +331,11 @@ static int f7188x_gpio_get(struct gpio_chip *chip, unsigned offset) err = superio_enter(sio->addr); if (err) return err; - superio_select(sio->addr, SIO_LD_GPIO); + superio_select(sio->addr, sio->device); dir = superio_inb(sio->addr, gpio_dir(bank->regbase)); dir = !!(dir & BIT(offset)); - if (dir) + if (gpio_data_single(sio->type) || dir) data = superio_inb(sio->addr, gpio_data_out(bank->regbase)); else data = superio_inb(sio->addr, gpio_data_in(bank->regbase)); @@ -332,7 +356,7 @@ static int f7188x_gpio_direction_out(struct gpio_chip *chip, err = superio_enter(sio->addr); if (err) return err; - superio_select(sio->addr, SIO_LD_GPIO); + superio_select(sio->addr, sio->device); data_out = superio_inb(sio->addr, gpio_data_out(bank->regbase)); if (value) @@ -342,7 +366,10 @@ static int f7188x_gpio_direction_out(struct gpio_chip *chip, superio_outb(sio->addr, gpio_data_out(bank->regbase), data_out); dir = superio_inb(sio->addr, gpio_dir(bank->regbase)); - dir |= BIT(offset); + if (gpio_dir_invert(sio->type)) + dir &= ~BIT(offset); + else + dir |= BIT(offset); superio_outb(sio->addr, gpio_dir(bank->regbase), dir); superio_exit(sio->addr); @@ -360,7 +387,7 @@ static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value) err = superio_enter(sio->addr); if (err) return; - superio_select(sio->addr, SIO_LD_GPIO); + superio_select(sio->addr, sio->device); data_out = superio_inb(sio->addr, gpio_data_out(bank->regbase)); if (value) @@ -388,7 +415,7 @@ static int f7188x_gpio_set_config(struct gpio_chip *chip, unsigned offset, err = superio_enter(sio->addr); if (err) return err; - superio_select(sio->addr, SIO_LD_GPIO); + superio_select(sio->addr, sio->device); data = superio_inb(sio->addr, gpio_out_mode(bank->regbase)); if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN) @@ -449,6 +476,10 @@ static int f7188x_gpio_probe(struct platform_device *pdev) data->nr_bank = ARRAY_SIZE(f81865_gpio_bank); data->bank = f81865_gpio_bank; break; + case nct6116d: + data->nr_bank = ARRAY_SIZE(nct6116d_gpio_bank); + data->bank = nct6116d_gpio_bank; + break; default: return -ENODEV; } @@ -485,12 +516,8 @@ static int __init f7188x_find(int addr, struct f7188x_sio *sio) return err; err = -ENODEV; - devid = superio_inw(addr, SIO_MANID); - if (devid != SIO_FINTEK_ID) { - pr_debug(DRVNAME ": Not a Fintek device at 0x%08x\n", addr); - goto err; - } + sio->device = SIO_LD_GPIO_FINTEK; devid = superio_inw(addr, SIO_DEVID); switch (devid) { case SIO_F71869_ID: @@ -517,8 +544,12 @@ static int __init f7188x_find(int addr, struct f7188x_sio *sio) case SIO_F81865_ID: sio->type = f81865; break; + case SIO_NCT6116D_ID: + sio->device = SIO_LD_GPIO_NUVOTON; + sio->type = nct6116d; + break; default: - pr_info(DRVNAME ": Unsupported Fintek device 0x%04x\n", devid); + pr_info(DRVNAME ": Unsupported device 0x%04x\n", devid); goto err; } sio->addr = addr;
Add GPIO support for Nuvoton NCT6116 chip. Nuvoton SuperIO chips are very similar to the ones from Fintek. In other subsystems they also share drivers and are called a family of drivers. For the GPIO subsystem the only difference is that the direction bit is reversed and that there is only one data bit per pin. On the SuperIO level the logical device is another one. Signed-off-by: Henning Schild <henning.schild@siemens.com> --- drivers/gpio/gpio-f7188x.c | 71 +++++++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 20 deletions(-)