0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
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
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
0037 #define REG 0x2e
0038 #define VAL 0x2f
0039
0040
0041 #define GPIO 0x07
0042
0043
0044 #define LDNREG 0x07
0045 #define CHIPID 0x20
0046 #define CHIPREV 0x22
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
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
0076
0077 static inline int superio_enter(void)
0078 {
0079
0080
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
0162
0163
0164 if (group < it87_gpio->simple_size)
0165 superio_set_mask(mask, group + it87_gpio->simple_base);
0166
0167
0168
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
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
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;
0295 it87_gpio->output_base = 0xc8;
0296 it87_gpio->simple_base = 0xc0;
0297 it87_gpio->simple_size = 6;
0298 it87_gpio->chip.ngpio = 64;
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
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
0356
0357
0358
0359
0360
0361
0362
0363
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");