^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * GPIO driver for Fintek Super-I/O F71869, F71869A, F71882, F71889 and F81866
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2010-2013 LaCie
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Author: Simon Guinot <simon.guinot@sequanux.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/gpio/driver.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define DRVNAME "gpio-f7188x"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * Super-I/O registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define SIO_LDSEL 0x07 /* Logical device select */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define SIO_DEVID 0x20 /* Device ID (2 bytes) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define SIO_DEVREV 0x22 /* Device revision */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define SIO_MANID 0x23 /* Fintek ID (2 bytes) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define SIO_LD_GPIO 0x06 /* GPIO logical device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define SIO_LOCK_KEY 0xAA /* Key to disable Super-I/O */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define SIO_FINTEK_ID 0x1934 /* Manufacturer ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define SIO_F71869_ID 0x0814 /* F71869 chipset ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define SIO_F71869A_ID 0x1007 /* F71869A chipset ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define SIO_F71882_ID 0x0541 /* F71882 chipset ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define SIO_F71889_ID 0x0909 /* F71889 chipset ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define SIO_F71889A_ID 0x1005 /* F71889A chipset ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define SIO_F81866_ID 0x1010 /* F81866 chipset ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define SIO_F81804_ID 0x1502 /* F81804 chipset ID, same for f81966 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define SIO_F81865_ID 0x0704 /* F81865 chipset ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) enum chips {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) f71869,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) f71869a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) f71882fg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) f71889a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) f71889f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) f81866,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) f81804,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) f81865,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static const char * const f7188x_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) "f71869",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) "f71869a",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) "f71882fg",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) "f71889a",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) "f71889f",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) "f81866",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) "f81804",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) "f81865",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct f7188x_sio {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) int addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) enum chips type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct f7188x_gpio_bank {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct gpio_chip chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) unsigned int regbase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct f7188x_gpio_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct f7188x_gpio_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) struct f7188x_sio *sio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) int nr_bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct f7188x_gpio_bank *bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * Super-I/O functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static inline int superio_inb(int base, int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) outb(reg, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return inb(base + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static int superio_inw(int base, int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) outb(reg++, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) val = inb(base + 1) << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) outb(reg, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) val |= inb(base + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static inline void superio_outb(int base, int reg, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) outb(reg, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) outb(val, base + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static inline int superio_enter(int base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /* Don't step on other drivers' I/O space by accident. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (!request_muxed_region(base, 2, DRVNAME)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) pr_err(DRVNAME "I/O address 0x%04x already in use\n", base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /* According to the datasheet the key must be send twice. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) outb(SIO_UNLOCK_KEY, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) outb(SIO_UNLOCK_KEY, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static inline void superio_select(int base, int ld)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) outb(SIO_LDSEL, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) outb(ld, base + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) static inline void superio_exit(int base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) outb(SIO_LOCK_KEY, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) release_region(base, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * GPIO chip.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static int f7188x_gpio_get_direction(struct gpio_chip *chip, unsigned offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static int f7188x_gpio_direction_in(struct gpio_chip *chip, unsigned offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static int f7188x_gpio_get(struct gpio_chip *chip, unsigned offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static int f7188x_gpio_direction_out(struct gpio_chip *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) unsigned offset, int value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static int f7188x_gpio_set_config(struct gpio_chip *chip, unsigned offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) unsigned long config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #define F7188X_GPIO_BANK(_base, _ngpio, _regbase) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) .chip = { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) .label = DRVNAME, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) .owner = THIS_MODULE, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) .get_direction = f7188x_gpio_get_direction, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) .direction_input = f7188x_gpio_direction_in, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) .get = f7188x_gpio_get, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) .direction_output = f7188x_gpio_direction_out, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) .set = f7188x_gpio_set, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) .set_config = f7188x_gpio_set_config, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) .base = _base, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .ngpio = _ngpio, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) .can_sleep = true, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) .regbase = _regbase, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) #define gpio_dir(base) (base + 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) #define gpio_data_out(base) (base + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) #define gpio_data_in(base) (base + 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) /* Output mode register (0:open drain 1:push-pull). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) #define gpio_out_mode(base) (base + 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) static struct f7188x_gpio_bank f71869_gpio_bank[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) F7188X_GPIO_BANK(0, 6, 0xF0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) F7188X_GPIO_BANK(10, 8, 0xE0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) F7188X_GPIO_BANK(20, 8, 0xD0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) F7188X_GPIO_BANK(30, 8, 0xC0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) F7188X_GPIO_BANK(40, 8, 0xB0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) F7188X_GPIO_BANK(50, 5, 0xA0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) F7188X_GPIO_BANK(60, 6, 0x90),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) static struct f7188x_gpio_bank f71869a_gpio_bank[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) F7188X_GPIO_BANK(0, 6, 0xF0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) F7188X_GPIO_BANK(10, 8, 0xE0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) F7188X_GPIO_BANK(20, 8, 0xD0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) F7188X_GPIO_BANK(30, 8, 0xC0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) F7188X_GPIO_BANK(40, 8, 0xB0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) F7188X_GPIO_BANK(50, 5, 0xA0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) F7188X_GPIO_BANK(60, 8, 0x90),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) F7188X_GPIO_BANK(70, 8, 0x80),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) static struct f7188x_gpio_bank f71882_gpio_bank[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) F7188X_GPIO_BANK(0, 8, 0xF0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) F7188X_GPIO_BANK(10, 8, 0xE0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) F7188X_GPIO_BANK(20, 8, 0xD0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) F7188X_GPIO_BANK(30, 4, 0xC0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) F7188X_GPIO_BANK(40, 4, 0xB0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) static struct f7188x_gpio_bank f71889a_gpio_bank[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) F7188X_GPIO_BANK(0, 7, 0xF0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) F7188X_GPIO_BANK(10, 7, 0xE0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) F7188X_GPIO_BANK(20, 8, 0xD0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) F7188X_GPIO_BANK(30, 8, 0xC0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) F7188X_GPIO_BANK(40, 8, 0xB0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) F7188X_GPIO_BANK(50, 5, 0xA0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) F7188X_GPIO_BANK(60, 8, 0x90),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) F7188X_GPIO_BANK(70, 8, 0x80),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static struct f7188x_gpio_bank f71889_gpio_bank[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) F7188X_GPIO_BANK(0, 7, 0xF0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) F7188X_GPIO_BANK(10, 7, 0xE0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) F7188X_GPIO_BANK(20, 8, 0xD0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) F7188X_GPIO_BANK(30, 8, 0xC0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) F7188X_GPIO_BANK(40, 8, 0xB0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) F7188X_GPIO_BANK(50, 5, 0xA0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) F7188X_GPIO_BANK(60, 8, 0x90),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) F7188X_GPIO_BANK(70, 8, 0x80),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) static struct f7188x_gpio_bank f81866_gpio_bank[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) F7188X_GPIO_BANK(0, 8, 0xF0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) F7188X_GPIO_BANK(10, 8, 0xE0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) F7188X_GPIO_BANK(20, 8, 0xD0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) F7188X_GPIO_BANK(30, 8, 0xC0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) F7188X_GPIO_BANK(40, 8, 0xB0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) F7188X_GPIO_BANK(50, 8, 0xA0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) F7188X_GPIO_BANK(60, 8, 0x90),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) F7188X_GPIO_BANK(70, 8, 0x80),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) F7188X_GPIO_BANK(80, 8, 0x88),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) static struct f7188x_gpio_bank f81804_gpio_bank[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) F7188X_GPIO_BANK(0, 8, 0xF0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) F7188X_GPIO_BANK(10, 8, 0xE0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) F7188X_GPIO_BANK(20, 8, 0xD0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) F7188X_GPIO_BANK(50, 8, 0xA0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) F7188X_GPIO_BANK(60, 8, 0x90),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) F7188X_GPIO_BANK(70, 8, 0x80),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) F7188X_GPIO_BANK(90, 8, 0x98),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static struct f7188x_gpio_bank f81865_gpio_bank[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) F7188X_GPIO_BANK(0, 8, 0xF0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) F7188X_GPIO_BANK(10, 8, 0xE0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) F7188X_GPIO_BANK(20, 8, 0xD0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) F7188X_GPIO_BANK(30, 8, 0xC0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) F7188X_GPIO_BANK(40, 8, 0xB0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) F7188X_GPIO_BANK(50, 8, 0xA0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) F7188X_GPIO_BANK(60, 5, 0x90),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) static int f7188x_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) struct f7188x_gpio_bank *bank = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) struct f7188x_sio *sio = bank->data->sio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) u8 dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) err = superio_enter(sio->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) superio_select(sio->addr, SIO_LD_GPIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) dir = superio_inb(sio->addr, gpio_dir(bank->regbase));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) superio_exit(sio->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (dir & 1 << offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return GPIO_LINE_DIRECTION_OUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return GPIO_LINE_DIRECTION_IN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) static int f7188x_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) struct f7188x_gpio_bank *bank = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) struct f7188x_sio *sio = bank->data->sio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) u8 dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) err = superio_enter(sio->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) superio_select(sio->addr, SIO_LD_GPIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) dir = superio_inb(sio->addr, gpio_dir(bank->regbase));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) dir &= ~BIT(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) superio_outb(sio->addr, gpio_dir(bank->regbase), dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) superio_exit(sio->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) static int f7188x_gpio_get(struct gpio_chip *chip, unsigned offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) struct f7188x_gpio_bank *bank = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) struct f7188x_sio *sio = bank->data->sio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) u8 dir, data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) err = superio_enter(sio->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) superio_select(sio->addr, SIO_LD_GPIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) dir = superio_inb(sio->addr, gpio_dir(bank->regbase));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) dir = !!(dir & BIT(offset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if (dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) data = superio_inb(sio->addr, gpio_data_out(bank->regbase));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) data = superio_inb(sio->addr, gpio_data_in(bank->regbase));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) superio_exit(sio->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) return !!(data & BIT(offset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) static int f7188x_gpio_direction_out(struct gpio_chip *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) unsigned offset, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) struct f7188x_gpio_bank *bank = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) struct f7188x_sio *sio = bank->data->sio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) u8 dir, data_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) err = superio_enter(sio->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) superio_select(sio->addr, SIO_LD_GPIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) data_out = superio_inb(sio->addr, gpio_data_out(bank->regbase));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) data_out |= BIT(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) data_out &= ~BIT(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) superio_outb(sio->addr, gpio_data_out(bank->regbase), data_out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) dir = superio_inb(sio->addr, gpio_dir(bank->regbase));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) dir |= BIT(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) superio_outb(sio->addr, gpio_dir(bank->regbase), dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) superio_exit(sio->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) struct f7188x_gpio_bank *bank = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) struct f7188x_sio *sio = bank->data->sio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) u8 data_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) err = superio_enter(sio->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) superio_select(sio->addr, SIO_LD_GPIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) data_out = superio_inb(sio->addr, gpio_data_out(bank->regbase));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) data_out |= BIT(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) data_out &= ~BIT(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) superio_outb(sio->addr, gpio_data_out(bank->regbase), data_out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) superio_exit(sio->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) static int f7188x_gpio_set_config(struct gpio_chip *chip, unsigned offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) unsigned long config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) enum pin_config_param param = pinconf_to_config_param(config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) struct f7188x_gpio_bank *bank = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) struct f7188x_sio *sio = bank->data->sio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) u8 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if (param != PIN_CONFIG_DRIVE_OPEN_DRAIN &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) param != PIN_CONFIG_DRIVE_PUSH_PULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) err = superio_enter(sio->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) superio_select(sio->addr, SIO_LD_GPIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) data = superio_inb(sio->addr, gpio_out_mode(bank->regbase));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) data &= ~BIT(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) data |= BIT(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) superio_outb(sio->addr, gpio_out_mode(bank->regbase), data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) superio_exit(sio->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) * Platform device and driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) static int f7188x_gpio_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) struct f7188x_sio *sio = dev_get_platdata(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) struct f7188x_gpio_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) switch (sio->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) case f71869:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) data->nr_bank = ARRAY_SIZE(f71869_gpio_bank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) data->bank = f71869_gpio_bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) case f71869a:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) data->nr_bank = ARRAY_SIZE(f71869a_gpio_bank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) data->bank = f71869a_gpio_bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) case f71882fg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) data->nr_bank = ARRAY_SIZE(f71882_gpio_bank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) data->bank = f71882_gpio_bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) case f71889a:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) data->nr_bank = ARRAY_SIZE(f71889a_gpio_bank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) data->bank = f71889a_gpio_bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) case f71889f:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) data->nr_bank = ARRAY_SIZE(f71889_gpio_bank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) data->bank = f71889_gpio_bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) case f81866:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) data->nr_bank = ARRAY_SIZE(f81866_gpio_bank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) data->bank = f81866_gpio_bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) case f81804:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) data->nr_bank = ARRAY_SIZE(f81804_gpio_bank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) data->bank = f81804_gpio_bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) case f81865:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) data->nr_bank = ARRAY_SIZE(f81865_gpio_bank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) data->bank = f81865_gpio_bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) data->sio = sio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) platform_set_drvdata(pdev, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) /* For each GPIO bank, register a GPIO chip. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) for (i = 0; i < data->nr_bank; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) struct f7188x_gpio_bank *bank = &data->bank[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) bank->chip.parent = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) bank->data = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) err = devm_gpiochip_add_data(&pdev->dev, &bank->chip, bank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) dev_err(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) "Failed to register gpiochip %d: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) i, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) static int __init f7188x_find(int addr, struct f7188x_sio *sio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) u16 devid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) err = superio_enter(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) devid = superio_inw(addr, SIO_MANID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) if (devid != SIO_FINTEK_ID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) pr_debug(DRVNAME ": Not a Fintek device at 0x%08x\n", addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) devid = superio_inw(addr, SIO_DEVID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) switch (devid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) case SIO_F71869_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) sio->type = f71869;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) case SIO_F71869A_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) sio->type = f71869a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) case SIO_F71882_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) sio->type = f71882fg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) case SIO_F71889A_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) sio->type = f71889a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) case SIO_F71889_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) sio->type = f71889f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) case SIO_F81866_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) sio->type = f81866;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) case SIO_F81804_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) sio->type = f81804;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) case SIO_F81865_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) sio->type = f81865;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) pr_info(DRVNAME ": Unsupported Fintek device 0x%04x\n", devid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) sio->addr = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) pr_info(DRVNAME ": Found %s at %#x, revision %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) f7188x_names[sio->type],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) (unsigned int) addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) (int) superio_inb(addr, SIO_DEVREV));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) superio_exit(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) static struct platform_device *f7188x_gpio_pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) static int __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) f7188x_gpio_device_add(const struct f7188x_sio *sio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) f7188x_gpio_pdev = platform_device_alloc(DRVNAME, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) if (!f7188x_gpio_pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) err = platform_device_add_data(f7188x_gpio_pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) sio, sizeof(*sio));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) pr_err(DRVNAME "Platform data allocation failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) err = platform_device_add(f7188x_gpio_pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) pr_err(DRVNAME "Device addition failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) platform_device_put(f7188x_gpio_pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) * Try to match a supported Fintek device by reading the (hard-wired)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) * configuration I/O ports. If available, then register both the platform
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) * device and driver to support the GPIOs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) static struct platform_driver f7188x_gpio_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) .name = DRVNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) .probe = f7188x_gpio_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) static int __init f7188x_gpio_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) struct f7188x_sio sio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) if (f7188x_find(0x2e, &sio) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) f7188x_find(0x4e, &sio))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) err = platform_driver_register(&f7188x_gpio_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) if (!err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) err = f7188x_gpio_device_add(&sio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) platform_driver_unregister(&f7188x_gpio_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) subsys_initcall(f7188x_gpio_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) static void __exit f7188x_gpio_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) platform_device_unregister(f7188x_gpio_pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) platform_driver_unregister(&f7188x_gpio_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) module_exit(f7188x_gpio_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) MODULE_DESCRIPTION("GPIO driver for Super-I/O chips F71869, F71869A, F71882FG, F71889A, F71889F and F81866");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) MODULE_AUTHOR("Simon Guinot <simon.guinot@sequanux.org>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) MODULE_LICENSE("GPL");