root/drivers/gpio/gpio-it87.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. superio_enter
  2. superio_exit
  3. superio_select
  4. superio_inb
  5. superio_outb
  6. superio_inw
  7. superio_outw
  8. superio_set_mask
  9. superio_clear_mask
  10. it87_gpio_request
  11. it87_gpio_get
  12. it87_gpio_direction_in
  13. it87_gpio_set
  14. it87_gpio_direction_out
  15. it87_gpio_init
  16. it87_gpio_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  *  GPIO interface for IT87xx Super I/O chips
   4  *
   5  *  Author: Diego Elio Pettenò <flameeyes@flameeyes.eu>
   6  *  Copyright (c) 2017 Google, Inc.
   7  *
   8  *  Based on it87_wdt.c     by Oliver Schuster
   9  *           gpio-it8761e.c by Denis Turischev
  10  *           gpio-stmpe.c   by Rabin Vincent
  11  */
  12 
  13 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  14 
  15 #include <linux/init.h>
  16 #include <linux/kernel.h>
  17 #include <linux/module.h>
  18 #include <linux/io.h>
  19 #include <linux/errno.h>
  20 #include <linux/ioport.h>
  21 #include <linux/slab.h>
  22 #include <linux/gpio/driver.h>
  23 
  24 /* Chip Id numbers */
  25 #define NO_DEV_ID       0xffff
  26 #define IT8613_ID       0x8613
  27 #define IT8620_ID       0x8620
  28 #define IT8628_ID       0x8628
  29 #define IT8718_ID       0x8718
  30 #define IT8728_ID       0x8728
  31 #define IT8732_ID       0x8732
  32 #define IT8761_ID       0x8761
  33 #define IT8772_ID       0x8772
  34 #define IT8786_ID       0x8786
  35 
  36 /* IO Ports */
  37 #define REG             0x2e
  38 #define VAL             0x2f
  39 
  40 /* Logical device Numbers LDN */
  41 #define GPIO            0x07
  42 
  43 /* Configuration Registers and Functions */
  44 #define LDNREG          0x07
  45 #define CHIPID          0x20
  46 #define CHIPREV         0x22
  47 
  48 /**
  49  * struct it87_gpio - it87-specific GPIO chip
  50  * @chip the underlying gpio_chip structure
  51  * @lock a lock to avoid races between operations
  52  * @io_base base address for gpio ports
  53  * @io_size size of the port rage starting from io_base.
  54  * @output_base Super I/O register address for Output Enable register
  55  * @simple_base Super I/O 'Simple I/O' Enable register
  56  * @simple_size Super IO 'Simple I/O' Enable register size; this is
  57  *      required because IT87xx chips might only provide Simple I/O
  58  *      switches on a subset of lines, whereas the others keep the
  59  *      same status all time.
  60  */
  61 struct it87_gpio {
  62         struct gpio_chip chip;
  63         spinlock_t lock;
  64         u16 io_base;
  65         u16 io_size;
  66         u8 output_base;
  67         u8 simple_base;
  68         u8 simple_size;
  69 };
  70 
  71 static struct it87_gpio it87_gpio_chip = {
  72         .lock = __SPIN_LOCK_UNLOCKED(it87_gpio_chip.lock),
  73 };
  74 
  75 /* Superio chip access functions; copied from wdt_it87 */
  76 
  77 static inline int superio_enter(void)
  78 {
  79         /*
  80          * Try to reserve REG and REG + 1 for exclusive access.
  81          */
  82         if (!request_muxed_region(REG, 2, KBUILD_MODNAME))
  83                 return -EBUSY;
  84 
  85         outb(0x87, REG);
  86         outb(0x01, REG);
  87         outb(0x55, REG);
  88         outb(0x55, REG);
  89         return 0;
  90 }
  91 
  92 static inline void superio_exit(void)
  93 {
  94         outb(0x02, REG);
  95         outb(0x02, VAL);
  96         release_region(REG, 2);
  97 }
  98 
  99 static inline void superio_select(int ldn)
 100 {
 101         outb(LDNREG, REG);
 102         outb(ldn, VAL);
 103 }
 104 
 105 static inline int superio_inb(int reg)
 106 {
 107         outb(reg, REG);
 108         return inb(VAL);
 109 }
 110 
 111 static inline void superio_outb(int val, int reg)
 112 {
 113         outb(reg, REG);
 114         outb(val, VAL);
 115 }
 116 
 117 static inline int superio_inw(int reg)
 118 {
 119         int val;
 120 
 121         outb(reg++, REG);
 122         val = inb(VAL) << 8;
 123         outb(reg, REG);
 124         val |= inb(VAL);
 125         return val;
 126 }
 127 
 128 static inline void superio_outw(int val, int reg)
 129 {
 130         outb(reg++, REG);
 131         outb(val >> 8, VAL);
 132         outb(reg, REG);
 133         outb(val, VAL);
 134 }
 135 
 136 static inline void superio_set_mask(int mask, int reg)
 137 {
 138         u8 curr_val = superio_inb(reg);
 139         u8 new_val = curr_val | mask;
 140 
 141         if (curr_val != new_val)
 142                 superio_outb(new_val, reg);
 143 }
 144 
 145 static inline void superio_clear_mask(int mask, int reg)
 146 {
 147         u8 curr_val = superio_inb(reg);
 148         u8 new_val = curr_val & ~mask;
 149 
 150         if (curr_val != new_val)
 151                 superio_outb(new_val, reg);
 152 }
 153 
 154 static int it87_gpio_request(struct gpio_chip *chip, unsigned gpio_num)
 155 {
 156         u8 mask, group;
 157         int rc = 0;
 158         struct it87_gpio *it87_gpio = gpiochip_get_data(chip);
 159 
 160         mask = 1 << (gpio_num % 8);
 161         group = (gpio_num / 8);
 162 
 163         spin_lock(&it87_gpio->lock);
 164 
 165         rc = superio_enter();
 166         if (rc)
 167                 goto exit;
 168 
 169         /* not all the IT87xx chips support Simple I/O and not all of
 170          * them allow all the lines to be set/unset to Simple I/O.
 171          */
 172         if (group < it87_gpio->simple_size)
 173                 superio_set_mask(mask, group + it87_gpio->simple_base);
 174 
 175         /* clear output enable, setting the pin to input, as all the
 176          * newly-exported GPIO interfaces are set to input.
 177          */
 178         superio_clear_mask(mask, group + it87_gpio->output_base);
 179 
 180         superio_exit();
 181 
 182 exit:
 183         spin_unlock(&it87_gpio->lock);
 184         return rc;
 185 }
 186 
 187 static int it87_gpio_get(struct gpio_chip *chip, unsigned gpio_num)
 188 {
 189         u16 reg;
 190         u8 mask;
 191         struct it87_gpio *it87_gpio = gpiochip_get_data(chip);
 192 
 193         mask = 1 << (gpio_num % 8);
 194         reg = (gpio_num / 8) + it87_gpio->io_base;
 195 
 196         return !!(inb(reg) & mask);
 197 }
 198 
 199 static int it87_gpio_direction_in(struct gpio_chip *chip, unsigned gpio_num)
 200 {
 201         u8 mask, group;
 202         int rc = 0;
 203         struct it87_gpio *it87_gpio = gpiochip_get_data(chip);
 204 
 205         mask = 1 << (gpio_num % 8);
 206         group = (gpio_num / 8);
 207 
 208         spin_lock(&it87_gpio->lock);
 209 
 210         rc = superio_enter();
 211         if (rc)
 212                 goto exit;
 213 
 214         /* clear the output enable bit */
 215         superio_clear_mask(mask, group + it87_gpio->output_base);
 216 
 217         superio_exit();
 218 
 219 exit:
 220         spin_unlock(&it87_gpio->lock);
 221         return rc;
 222 }
 223 
 224 static void it87_gpio_set(struct gpio_chip *chip,
 225                           unsigned gpio_num, int val)
 226 {
 227         u8 mask, curr_vals;
 228         u16 reg;
 229         struct it87_gpio *it87_gpio = gpiochip_get_data(chip);
 230 
 231         mask = 1 << (gpio_num % 8);
 232         reg = (gpio_num / 8) + it87_gpio->io_base;
 233 
 234         curr_vals = inb(reg);
 235         if (val)
 236                 outb(curr_vals | mask, reg);
 237         else
 238                 outb(curr_vals & ~mask, reg);
 239 }
 240 
 241 static int it87_gpio_direction_out(struct gpio_chip *chip,
 242                                    unsigned gpio_num, int val)
 243 {
 244         u8 mask, group;
 245         int rc = 0;
 246         struct it87_gpio *it87_gpio = gpiochip_get_data(chip);
 247 
 248         mask = 1 << (gpio_num % 8);
 249         group = (gpio_num / 8);
 250 
 251         spin_lock(&it87_gpio->lock);
 252 
 253         rc = superio_enter();
 254         if (rc)
 255                 goto exit;
 256 
 257         /* set the output enable bit */
 258         superio_set_mask(mask, group + it87_gpio->output_base);
 259 
 260         it87_gpio_set(chip, gpio_num, val);
 261 
 262         superio_exit();
 263 
 264 exit:
 265         spin_unlock(&it87_gpio->lock);
 266         return rc;
 267 }
 268 
 269 static const struct gpio_chip it87_template_chip = {
 270         .label                  = KBUILD_MODNAME,
 271         .owner                  = THIS_MODULE,
 272         .request                = it87_gpio_request,
 273         .get                    = it87_gpio_get,
 274         .direction_input        = it87_gpio_direction_in,
 275         .set                    = it87_gpio_set,
 276         .direction_output       = it87_gpio_direction_out,
 277         .base                   = -1
 278 };
 279 
 280 static int __init it87_gpio_init(void)
 281 {
 282         int rc = 0, i;
 283         u16 chip_type;
 284         u8 chip_rev, gpio_ba_reg;
 285         char *labels, **labels_table;
 286 
 287         struct it87_gpio *it87_gpio = &it87_gpio_chip;
 288 
 289         rc = superio_enter();
 290         if (rc)
 291                 return rc;
 292 
 293         chip_type = superio_inw(CHIPID);
 294         chip_rev  = superio_inb(CHIPREV) & 0x0f;
 295         superio_exit();
 296 
 297         it87_gpio->chip = it87_template_chip;
 298 
 299         switch (chip_type) {
 300         case IT8613_ID:
 301                 gpio_ba_reg = 0x62;
 302                 it87_gpio->io_size = 8;  /* it8613 only needs 6, use 8 for alignment */
 303                 it87_gpio->output_base = 0xc8;
 304                 it87_gpio->simple_base = 0xc0;
 305                 it87_gpio->simple_size = 6;
 306                 it87_gpio->chip.ngpio = 64;  /* has 48, use 64 for convenient calc */
 307                 break;
 308         case IT8620_ID:
 309         case IT8628_ID:
 310                 gpio_ba_reg = 0x62;
 311                 it87_gpio->io_size = 11;
 312                 it87_gpio->output_base = 0xc8;
 313                 it87_gpio->simple_size = 0;
 314                 it87_gpio->chip.ngpio = 64;
 315                 break;
 316         case IT8718_ID:
 317         case IT8728_ID:
 318         case IT8732_ID:
 319         case IT8772_ID:
 320         case IT8786_ID:
 321                 gpio_ba_reg = 0x62;
 322                 it87_gpio->io_size = 8;
 323                 it87_gpio->output_base = 0xc8;
 324                 it87_gpio->simple_base = 0xc0;
 325                 it87_gpio->simple_size = 5;
 326                 it87_gpio->chip.ngpio = 64;
 327                 break;
 328         case IT8761_ID:
 329                 gpio_ba_reg = 0x60;
 330                 it87_gpio->io_size = 4;
 331                 it87_gpio->output_base = 0xf0;
 332                 it87_gpio->simple_size = 0;
 333                 it87_gpio->chip.ngpio = 16;
 334                 break;
 335         case NO_DEV_ID:
 336                 pr_err("no device\n");
 337                 return -ENODEV;
 338         default:
 339                 pr_err("Unknown Chip found, Chip %04x Revision %x\n",
 340                        chip_type, chip_rev);
 341                 return -ENODEV;
 342         }
 343 
 344         rc = superio_enter();
 345         if (rc)
 346                 return rc;
 347 
 348         superio_select(GPIO);
 349 
 350         /* fetch GPIO base address */
 351         it87_gpio->io_base = superio_inw(gpio_ba_reg);
 352 
 353         superio_exit();
 354 
 355         pr_info("Found Chip IT%04x rev %x. %u GPIO lines starting at %04xh\n",
 356                 chip_type, chip_rev, it87_gpio->chip.ngpio,
 357                 it87_gpio->io_base);
 358 
 359         if (!request_region(it87_gpio->io_base, it87_gpio->io_size,
 360                                                         KBUILD_MODNAME))
 361                 return -EBUSY;
 362 
 363         /* Set up aliases for the GPIO connection.
 364          *
 365          * ITE documentation for recent chips such as the IT8728F
 366          * refers to the GPIO lines as GPxy, with a coordinates system
 367          * where x is the GPIO group (starting from 1) and y is the
 368          * bit within the group.
 369          *
 370          * By creating these aliases, we make it easier to understand
 371          * to which GPIO pin we're referring to.
 372          */
 373         labels = kcalloc(it87_gpio->chip.ngpio, sizeof("it87_gpXY"),
 374                                                                 GFP_KERNEL);
 375         labels_table = kcalloc(it87_gpio->chip.ngpio, sizeof(const char *),
 376                                                                 GFP_KERNEL);
 377 
 378         if (!labels || !labels_table) {
 379                 rc = -ENOMEM;
 380                 goto labels_free;
 381         }
 382 
 383         for (i = 0; i < it87_gpio->chip.ngpio; i++) {
 384                 char *label = &labels[i * sizeof("it87_gpXY")];
 385 
 386                 sprintf(label, "it87_gp%u%u", 1+(i/8), i%8);
 387                 labels_table[i] = label;
 388         }
 389 
 390         it87_gpio->chip.names = (const char *const*)labels_table;
 391 
 392         rc = gpiochip_add_data(&it87_gpio->chip, it87_gpio);
 393         if (rc)
 394                 goto labels_free;
 395 
 396         return 0;
 397 
 398 labels_free:
 399         kfree(labels_table);
 400         kfree(labels);
 401         release_region(it87_gpio->io_base, it87_gpio->io_size);
 402         return rc;
 403 }
 404 
 405 static void __exit it87_gpio_exit(void)
 406 {
 407         struct it87_gpio *it87_gpio = &it87_gpio_chip;
 408 
 409         gpiochip_remove(&it87_gpio->chip);
 410         release_region(it87_gpio->io_base, it87_gpio->io_size);
 411         kfree(it87_gpio->chip.names[0]);
 412         kfree(it87_gpio->chip.names);
 413 }
 414 
 415 module_init(it87_gpio_init);
 416 module_exit(it87_gpio_exit);
 417 
 418 MODULE_AUTHOR("Diego Elio Pettenò <flameeyes@flameeyes.eu>");
 419 MODULE_DESCRIPTION("GPIO interface for IT87xx Super I/O chips");
 420 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */