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