Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  GPIO interface for IT87xx Super I/O chips
0004  *
0005  *  Author: Diego Elio Pettenò <flameeyes@flameeyes.eu>
0006  *  Copyright (c) 2017 Google, Inc.
0007  *
0008  *  Based on it87_wdt.c     by Oliver Schuster
0009  *           gpio-it8761e.c by Denis Turischev
0010  *           gpio-stmpe.c   by Rabin Vincent
0011  */
0012 
0013 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0014 
0015 #include <linux/init.h>
0016 #include <linux/kernel.h>
0017 #include <linux/module.h>
0018 #include <linux/io.h>
0019 #include <linux/errno.h>
0020 #include <linux/ioport.h>
0021 #include <linux/slab.h>
0022 #include <linux/gpio/driver.h>
0023 
0024 /* Chip Id numbers */
0025 #define NO_DEV_ID   0xffff
0026 #define IT8613_ID   0x8613
0027 #define IT8620_ID   0x8620
0028 #define IT8628_ID   0x8628
0029 #define IT8718_ID       0x8718
0030 #define IT8728_ID   0x8728
0031 #define IT8732_ID   0x8732
0032 #define IT8761_ID   0x8761
0033 #define IT8772_ID   0x8772
0034 #define IT8786_ID   0x8786
0035 
0036 /* IO Ports */
0037 #define REG     0x2e
0038 #define VAL     0x2f
0039 
0040 /* Logical device Numbers LDN */
0041 #define GPIO        0x07
0042 
0043 /* Configuration Registers and Functions */
0044 #define LDNREG      0x07
0045 #define CHIPID      0x20
0046 #define CHIPREV     0x22
0047 
0048 /**
0049  * struct it87_gpio - it87-specific GPIO chip
0050  * @chip: the underlying gpio_chip structure
0051  * @lock: a lock to avoid races between operations
0052  * @io_base: base address for gpio ports
0053  * @io_size: size of the port rage starting from io_base.
0054  * @output_base: Super I/O register address for Output Enable register
0055  * @simple_base: Super I/O 'Simple I/O' Enable register
0056  * @simple_size: Super IO 'Simple I/O' Enable register size; this is
0057  *  required because IT87xx chips might only provide Simple I/O
0058  *  switches on a subset of lines, whereas the others keep the
0059  *  same status all time.
0060  */
0061 struct it87_gpio {
0062     struct gpio_chip chip;
0063     spinlock_t lock;
0064     u16 io_base;
0065     u16 io_size;
0066     u8 output_base;
0067     u8 simple_base;
0068     u8 simple_size;
0069 };
0070 
0071 static struct it87_gpio it87_gpio_chip = {
0072     .lock = __SPIN_LOCK_UNLOCKED(it87_gpio_chip.lock),
0073 };
0074 
0075 /* Superio chip access functions; copied from wdt_it87 */
0076 
0077 static inline int superio_enter(void)
0078 {
0079     /*
0080      * Try to reserve REG and REG + 1 for exclusive access.
0081      */
0082     if (!request_muxed_region(REG, 2, KBUILD_MODNAME))
0083         return -EBUSY;
0084 
0085     outb(0x87, REG);
0086     outb(0x01, REG);
0087     outb(0x55, REG);
0088     outb(0x55, REG);
0089     return 0;
0090 }
0091 
0092 static inline void superio_exit(void)
0093 {
0094     outb(0x02, REG);
0095     outb(0x02, VAL);
0096     release_region(REG, 2);
0097 }
0098 
0099 static inline void superio_select(int ldn)
0100 {
0101     outb(LDNREG, REG);
0102     outb(ldn, VAL);
0103 }
0104 
0105 static inline int superio_inb(int reg)
0106 {
0107     outb(reg, REG);
0108     return inb(VAL);
0109 }
0110 
0111 static inline void superio_outb(int val, int reg)
0112 {
0113     outb(reg, REG);
0114     outb(val, VAL);
0115 }
0116 
0117 static inline int superio_inw(int reg)
0118 {
0119     int val;
0120 
0121     outb(reg++, REG);
0122     val = inb(VAL) << 8;
0123     outb(reg, REG);
0124     val |= inb(VAL);
0125     return val;
0126 }
0127 
0128 static inline void superio_set_mask(int mask, int reg)
0129 {
0130     u8 curr_val = superio_inb(reg);
0131     u8 new_val = curr_val | mask;
0132 
0133     if (curr_val != new_val)
0134         superio_outb(new_val, reg);
0135 }
0136 
0137 static inline void superio_clear_mask(int mask, int reg)
0138 {
0139     u8 curr_val = superio_inb(reg);
0140     u8 new_val = curr_val & ~mask;
0141 
0142     if (curr_val != new_val)
0143         superio_outb(new_val, reg);
0144 }
0145 
0146 static int it87_gpio_request(struct gpio_chip *chip, unsigned gpio_num)
0147 {
0148     u8 mask, group;
0149     int rc = 0;
0150     struct it87_gpio *it87_gpio = gpiochip_get_data(chip);
0151 
0152     mask = 1 << (gpio_num % 8);
0153     group = (gpio_num / 8);
0154 
0155     spin_lock(&it87_gpio->lock);
0156 
0157     rc = superio_enter();
0158     if (rc)
0159         goto exit;
0160 
0161     /* not all the IT87xx chips support Simple I/O and not all of
0162      * them allow all the lines to be set/unset to Simple I/O.
0163      */
0164     if (group < it87_gpio->simple_size)
0165         superio_set_mask(mask, group + it87_gpio->simple_base);
0166 
0167     /* clear output enable, setting the pin to input, as all the
0168      * newly-exported GPIO interfaces are set to input.
0169      */
0170     superio_clear_mask(mask, group + it87_gpio->output_base);
0171 
0172     superio_exit();
0173 
0174 exit:
0175     spin_unlock(&it87_gpio->lock);
0176     return rc;
0177 }
0178 
0179 static int it87_gpio_get(struct gpio_chip *chip, unsigned gpio_num)
0180 {
0181     u16 reg;
0182     u8 mask;
0183     struct it87_gpio *it87_gpio = gpiochip_get_data(chip);
0184 
0185     mask = 1 << (gpio_num % 8);
0186     reg = (gpio_num / 8) + it87_gpio->io_base;
0187 
0188     return !!(inb(reg) & mask);
0189 }
0190 
0191 static int it87_gpio_direction_in(struct gpio_chip *chip, unsigned gpio_num)
0192 {
0193     u8 mask, group;
0194     int rc = 0;
0195     struct it87_gpio *it87_gpio = gpiochip_get_data(chip);
0196 
0197     mask = 1 << (gpio_num % 8);
0198     group = (gpio_num / 8);
0199 
0200     spin_lock(&it87_gpio->lock);
0201 
0202     rc = superio_enter();
0203     if (rc)
0204         goto exit;
0205 
0206     /* clear the output enable bit */
0207     superio_clear_mask(mask, group + it87_gpio->output_base);
0208 
0209     superio_exit();
0210 
0211 exit:
0212     spin_unlock(&it87_gpio->lock);
0213     return rc;
0214 }
0215 
0216 static void it87_gpio_set(struct gpio_chip *chip,
0217               unsigned gpio_num, int val)
0218 {
0219     u8 mask, curr_vals;
0220     u16 reg;
0221     struct it87_gpio *it87_gpio = gpiochip_get_data(chip);
0222 
0223     mask = 1 << (gpio_num % 8);
0224     reg = (gpio_num / 8) + it87_gpio->io_base;
0225 
0226     curr_vals = inb(reg);
0227     if (val)
0228         outb(curr_vals | mask, reg);
0229     else
0230         outb(curr_vals & ~mask, reg);
0231 }
0232 
0233 static int it87_gpio_direction_out(struct gpio_chip *chip,
0234                    unsigned gpio_num, int val)
0235 {
0236     u8 mask, group;
0237     int rc = 0;
0238     struct it87_gpio *it87_gpio = gpiochip_get_data(chip);
0239 
0240     mask = 1 << (gpio_num % 8);
0241     group = (gpio_num / 8);
0242 
0243     spin_lock(&it87_gpio->lock);
0244 
0245     rc = superio_enter();
0246     if (rc)
0247         goto exit;
0248 
0249     /* set the output enable bit */
0250     superio_set_mask(mask, group + it87_gpio->output_base);
0251 
0252     it87_gpio_set(chip, gpio_num, val);
0253 
0254     superio_exit();
0255 
0256 exit:
0257     spin_unlock(&it87_gpio->lock);
0258     return rc;
0259 }
0260 
0261 static const struct gpio_chip it87_template_chip = {
0262     .label          = KBUILD_MODNAME,
0263     .owner          = THIS_MODULE,
0264     .request        = it87_gpio_request,
0265     .get            = it87_gpio_get,
0266     .direction_input    = it87_gpio_direction_in,
0267     .set            = it87_gpio_set,
0268     .direction_output   = it87_gpio_direction_out,
0269     .base           = -1
0270 };
0271 
0272 static int __init it87_gpio_init(void)
0273 {
0274     int rc = 0, i;
0275     u16 chip_type;
0276     u8 chip_rev, gpio_ba_reg;
0277     char *labels, **labels_table;
0278 
0279     struct it87_gpio *it87_gpio = &it87_gpio_chip;
0280 
0281     rc = superio_enter();
0282     if (rc)
0283         return rc;
0284 
0285     chip_type = superio_inw(CHIPID);
0286     chip_rev  = superio_inb(CHIPREV) & 0x0f;
0287     superio_exit();
0288 
0289     it87_gpio->chip = it87_template_chip;
0290 
0291     switch (chip_type) {
0292     case IT8613_ID:
0293         gpio_ba_reg = 0x62;
0294         it87_gpio->io_size = 8;  /* it8613 only needs 6, use 8 for alignment */
0295         it87_gpio->output_base = 0xc8;
0296         it87_gpio->simple_base = 0xc0;
0297         it87_gpio->simple_size = 6;
0298         it87_gpio->chip.ngpio = 64;  /* has 48, use 64 for convenient calc */
0299         break;
0300     case IT8620_ID:
0301     case IT8628_ID:
0302         gpio_ba_reg = 0x62;
0303         it87_gpio->io_size = 11;
0304         it87_gpio->output_base = 0xc8;
0305         it87_gpio->simple_size = 0;
0306         it87_gpio->chip.ngpio = 64;
0307         break;
0308     case IT8718_ID:
0309     case IT8728_ID:
0310     case IT8732_ID:
0311     case IT8772_ID:
0312     case IT8786_ID:
0313         gpio_ba_reg = 0x62;
0314         it87_gpio->io_size = 8;
0315         it87_gpio->output_base = 0xc8;
0316         it87_gpio->simple_base = 0xc0;
0317         it87_gpio->simple_size = 5;
0318         it87_gpio->chip.ngpio = 64;
0319         break;
0320     case IT8761_ID:
0321         gpio_ba_reg = 0x60;
0322         it87_gpio->io_size = 4;
0323         it87_gpio->output_base = 0xf0;
0324         it87_gpio->simple_size = 0;
0325         it87_gpio->chip.ngpio = 16;
0326         break;
0327     case NO_DEV_ID:
0328         pr_err("no device\n");
0329         return -ENODEV;
0330     default:
0331         pr_err("Unknown Chip found, Chip %04x Revision %x\n",
0332                chip_type, chip_rev);
0333         return -ENODEV;
0334     }
0335 
0336     rc = superio_enter();
0337     if (rc)
0338         return rc;
0339 
0340     superio_select(GPIO);
0341 
0342     /* fetch GPIO base address */
0343     it87_gpio->io_base = superio_inw(gpio_ba_reg);
0344 
0345     superio_exit();
0346 
0347     pr_info("Found Chip IT%04x rev %x. %u GPIO lines starting at %04xh\n",
0348         chip_type, chip_rev, it87_gpio->chip.ngpio,
0349         it87_gpio->io_base);
0350 
0351     if (!request_region(it87_gpio->io_base, it87_gpio->io_size,
0352                             KBUILD_MODNAME))
0353         return -EBUSY;
0354 
0355     /* Set up aliases for the GPIO connection.
0356      *
0357      * ITE documentation for recent chips such as the IT8728F
0358      * refers to the GPIO lines as GPxy, with a coordinates system
0359      * where x is the GPIO group (starting from 1) and y is the
0360      * bit within the group.
0361      *
0362      * By creating these aliases, we make it easier to understand
0363      * to which GPIO pin we're referring to.
0364      */
0365     labels = kcalloc(it87_gpio->chip.ngpio, sizeof("it87_gpXY"),
0366                                 GFP_KERNEL);
0367     labels_table = kcalloc(it87_gpio->chip.ngpio, sizeof(const char *),
0368                                 GFP_KERNEL);
0369 
0370     if (!labels || !labels_table) {
0371         rc = -ENOMEM;
0372         goto labels_free;
0373     }
0374 
0375     for (i = 0; i < it87_gpio->chip.ngpio; i++) {
0376         char *label = &labels[i * sizeof("it87_gpXY")];
0377 
0378         sprintf(label, "it87_gp%u%u", 1+(i/8), i%8);
0379         labels_table[i] = label;
0380     }
0381 
0382     it87_gpio->chip.names = (const char *const*)labels_table;
0383 
0384     rc = gpiochip_add_data(&it87_gpio->chip, it87_gpio);
0385     if (rc)
0386         goto labels_free;
0387 
0388     return 0;
0389 
0390 labels_free:
0391     kfree(labels_table);
0392     kfree(labels);
0393     release_region(it87_gpio->io_base, it87_gpio->io_size);
0394     return rc;
0395 }
0396 
0397 static void __exit it87_gpio_exit(void)
0398 {
0399     struct it87_gpio *it87_gpio = &it87_gpio_chip;
0400 
0401     gpiochip_remove(&it87_gpio->chip);
0402     release_region(it87_gpio->io_base, it87_gpio->io_size);
0403     kfree(it87_gpio->chip.names[0]);
0404     kfree(it87_gpio->chip.names);
0405 }
0406 
0407 module_init(it87_gpio_init);
0408 module_exit(it87_gpio_exit);
0409 
0410 MODULE_AUTHOR("Diego Elio Pettenò <flameeyes@flameeyes.eu>");
0411 MODULE_DESCRIPTION("GPIO interface for IT87xx Super I/O chips");
0412 MODULE_LICENSE("GPL");