Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.14 432 lines 11 kB view raw
1/* 2 * GPIO driver for the SMSC SCH311x Super-I/O chips 3 * 4 * Copyright (C) 2013 Bruno Randolf <br1@einfach.org> 5 * 6 * SuperIO functions and chip detection: 7 * (c) Copyright 2008 Wim Van Sebroeck <wim@iguana.be>. 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 */ 14 15#include <linux/module.h> 16#include <linux/kernel.h> 17#include <linux/init.h> 18#include <linux/platform_device.h> 19#include <linux/gpio.h> 20#include <linux/bitops.h> 21#include <linux/io.h> 22 23#define DRV_NAME "gpio-sch311x" 24 25#define SCH311X_GPIO_CONF_OUT 0x00 26#define SCH311X_GPIO_CONF_IN 0x01 27#define SCH311X_GPIO_CONF_INVERT 0x02 28#define SCH311X_GPIO_CONF_OPEN_DRAIN 0x80 29 30#define SIO_CONFIG_KEY_ENTER 0x55 31#define SIO_CONFIG_KEY_EXIT 0xaa 32 33#define GP1 0x4b 34 35static int sch311x_ioports[] = { 0x2e, 0x4e, 0x162e, 0x164e }; 36 37static struct platform_device *sch311x_gpio_pdev; 38 39struct sch311x_pdev_data { /* platform device data */ 40 unsigned short runtime_reg; /* runtime register base address */ 41}; 42 43struct sch311x_gpio_block { /* one GPIO block runtime data */ 44 struct gpio_chip chip; 45 unsigned short data_reg; /* from definition below */ 46 unsigned short *config_regs; /* pointer to definition below */ 47 unsigned short runtime_reg; /* runtime register */ 48 spinlock_t lock; /* lock for this GPIO block */ 49}; 50 51struct sch311x_gpio_priv { /* driver private data */ 52 struct sch311x_gpio_block blocks[6]; 53}; 54 55struct sch311x_gpio_block_def { /* register address definitions */ 56 unsigned short data_reg; 57 unsigned short config_regs[8]; 58 unsigned short base; 59}; 60 61/* Note: some GPIOs are not available, these are marked with 0x00 */ 62 63static struct sch311x_gpio_block_def sch311x_gpio_blocks[] = { 64 { 65 .data_reg = 0x4b, /* GP1 */ 66 .config_regs = {0x23, 0x24, 0x25, 0x26, 0x27, 0x29, 0x2a, 0x2b}, 67 .base = 10, 68 }, 69 { 70 .data_reg = 0x4c, /* GP2 */ 71 .config_regs = {0x00, 0x2c, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x32}, 72 .base = 20, 73 }, 74 { 75 .data_reg = 0x4d, /* GP3 */ 76 .config_regs = {0x33, 0x34, 0x35, 0x36, 0x37, 0x00, 0x39, 0x3a}, 77 .base = 30, 78 }, 79 { 80 .data_reg = 0x4e, /* GP4 */ 81 .config_regs = {0x3b, 0x00, 0x3d, 0x00, 0x6e, 0x6f, 0x72, 0x73}, 82 .base = 40, 83 }, 84 { 85 .data_reg = 0x4f, /* GP5 */ 86 .config_regs = {0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46}, 87 .base = 50, 88 }, 89 { 90 .data_reg = 0x50, /* GP6 */ 91 .config_regs = {0x47, 0x48, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59}, 92 .base = 60, 93 }, 94}; 95 96static inline struct sch311x_gpio_block * 97to_sch311x_gpio_block(struct gpio_chip *chip) 98{ 99 return container_of(chip, struct sch311x_gpio_block, chip); 100} 101 102 103/* 104 * Super-IO functions 105 */ 106 107static inline int sch311x_sio_enter(int sio_config_port) 108{ 109 /* Don't step on other drivers' I/O space by accident. */ 110 if (!request_muxed_region(sio_config_port, 2, DRV_NAME)) { 111 pr_err(DRV_NAME "I/O address 0x%04x already in use\n", 112 sio_config_port); 113 return -EBUSY; 114 } 115 116 outb(SIO_CONFIG_KEY_ENTER, sio_config_port); 117 return 0; 118} 119 120static inline void sch311x_sio_exit(int sio_config_port) 121{ 122 outb(SIO_CONFIG_KEY_EXIT, sio_config_port); 123 release_region(sio_config_port, 2); 124} 125 126static inline int sch311x_sio_inb(int sio_config_port, int reg) 127{ 128 outb(reg, sio_config_port); 129 return inb(sio_config_port + 1); 130} 131 132static inline void sch311x_sio_outb(int sio_config_port, int reg, int val) 133{ 134 outb(reg, sio_config_port); 135 outb(val, sio_config_port + 1); 136} 137 138 139/* 140 * GPIO functions 141 */ 142 143static int sch311x_gpio_request(struct gpio_chip *chip, unsigned offset) 144{ 145 struct sch311x_gpio_block *block = to_sch311x_gpio_block(chip); 146 147 if (block->config_regs[offset] == 0) /* GPIO is not available */ 148 return -ENODEV; 149 150 if (!request_region(block->runtime_reg + block->config_regs[offset], 151 1, DRV_NAME)) { 152 dev_err(chip->dev, "Failed to request region 0x%04x.\n", 153 block->runtime_reg + block->config_regs[offset]); 154 return -EBUSY; 155 } 156 return 0; 157} 158 159static void sch311x_gpio_free(struct gpio_chip *chip, unsigned offset) 160{ 161 struct sch311x_gpio_block *block = to_sch311x_gpio_block(chip); 162 163 if (block->config_regs[offset] == 0) /* GPIO is not available */ 164 return; 165 166 release_region(block->runtime_reg + block->config_regs[offset], 1); 167} 168 169static int sch311x_gpio_get(struct gpio_chip *chip, unsigned offset) 170{ 171 struct sch311x_gpio_block *block = to_sch311x_gpio_block(chip); 172 unsigned char data; 173 174 spin_lock(&block->lock); 175 data = inb(block->runtime_reg + block->data_reg); 176 spin_unlock(&block->lock); 177 178 return !!(data & BIT(offset)); 179} 180 181static void __sch311x_gpio_set(struct sch311x_gpio_block *block, 182 unsigned offset, int value) 183{ 184 unsigned char data = inb(block->runtime_reg + block->data_reg); 185 if (value) 186 data |= BIT(offset); 187 else 188 data &= ~BIT(offset); 189 outb(data, block->runtime_reg + block->data_reg); 190} 191 192static void sch311x_gpio_set(struct gpio_chip *chip, unsigned offset, 193 int value) 194{ 195 struct sch311x_gpio_block *block = to_sch311x_gpio_block(chip); 196 197 spin_lock(&block->lock); 198 __sch311x_gpio_set(block, offset, value); 199 spin_unlock(&block->lock); 200} 201 202static int sch311x_gpio_direction_in(struct gpio_chip *chip, unsigned offset) 203{ 204 struct sch311x_gpio_block *block = to_sch311x_gpio_block(chip); 205 206 spin_lock(&block->lock); 207 outb(SCH311X_GPIO_CONF_IN, block->runtime_reg + 208 block->config_regs[offset]); 209 spin_unlock(&block->lock); 210 211 return 0; 212} 213 214static int sch311x_gpio_direction_out(struct gpio_chip *chip, unsigned offset, 215 int value) 216{ 217 struct sch311x_gpio_block *block = to_sch311x_gpio_block(chip); 218 219 spin_lock(&block->lock); 220 221 outb(SCH311X_GPIO_CONF_OUT, block->runtime_reg + 222 block->config_regs[offset]); 223 224 __sch311x_gpio_set(block, offset, value); 225 226 spin_unlock(&block->lock); 227 return 0; 228} 229 230static int sch311x_gpio_probe(struct platform_device *pdev) 231{ 232 struct sch311x_pdev_data *pdata = pdev->dev.platform_data; 233 struct sch311x_gpio_priv *priv; 234 struct sch311x_gpio_block *block; 235 int err, i; 236 237 /* we can register all GPIO data registers at once */ 238 if (!request_region(pdata->runtime_reg + GP1, 6, DRV_NAME)) { 239 dev_err(&pdev->dev, "Failed to request region 0x%04x-0x%04x.\n", 240 pdata->runtime_reg + GP1, pdata->runtime_reg + GP1 + 5); 241 return -EBUSY; 242 } 243 244 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 245 if (!priv) 246 return -ENOMEM; 247 248 platform_set_drvdata(pdev, priv); 249 250 for (i = 0; i < ARRAY_SIZE(priv->blocks); i++) { 251 block = &priv->blocks[i]; 252 253 spin_lock_init(&block->lock); 254 255 block->chip.label = DRV_NAME; 256 block->chip.owner = THIS_MODULE; 257 block->chip.request = sch311x_gpio_request; 258 block->chip.free = sch311x_gpio_free; 259 block->chip.direction_input = sch311x_gpio_direction_in; 260 block->chip.direction_output = sch311x_gpio_direction_out; 261 block->chip.get = sch311x_gpio_get; 262 block->chip.set = sch311x_gpio_set; 263 block->chip.ngpio = 8; 264 block->chip.dev = &pdev->dev; 265 block->chip.base = sch311x_gpio_blocks[i].base; 266 block->config_regs = sch311x_gpio_blocks[i].config_regs; 267 block->data_reg = sch311x_gpio_blocks[i].data_reg; 268 block->runtime_reg = pdata->runtime_reg; 269 270 err = gpiochip_add(&block->chip); 271 if (err < 0) { 272 dev_err(&pdev->dev, 273 "Could not register gpiochip, %d\n", err); 274 goto exit_err; 275 } 276 dev_info(&pdev->dev, 277 "SMSC SCH311x GPIO block %d registered.\n", i); 278 } 279 280 return 0; 281 282exit_err: 283 release_region(pdata->runtime_reg + GP1, 6); 284 /* release already registered chips */ 285 for (--i; i >= 0; i--) 286 gpiochip_remove(&priv->blocks[i].chip); 287 return err; 288} 289 290static int sch311x_gpio_remove(struct platform_device *pdev) 291{ 292 struct sch311x_pdev_data *pdata = pdev->dev.platform_data; 293 struct sch311x_gpio_priv *priv = platform_get_drvdata(pdev); 294 int err, i; 295 296 release_region(pdata->runtime_reg + GP1, 6); 297 298 for (i = 0; i < ARRAY_SIZE(priv->blocks); i++) { 299 err = gpiochip_remove(&priv->blocks[i].chip); 300 if (err) 301 return err; 302 dev_info(&pdev->dev, 303 "SMSC SCH311x GPIO block %d unregistered.\n", i); 304 } 305 return 0; 306} 307 308static struct platform_driver sch311x_gpio_driver = { 309 .driver.name = DRV_NAME, 310 .driver.owner = THIS_MODULE, 311 .probe = sch311x_gpio_probe, 312 .remove = sch311x_gpio_remove, 313}; 314 315 316/* 317 * Init & exit routines 318 */ 319 320static int __init sch311x_detect(int sio_config_port, unsigned short *addr) 321{ 322 int err = 0, reg; 323 unsigned short base_addr; 324 unsigned char dev_id; 325 326 err = sch311x_sio_enter(sio_config_port); 327 if (err) 328 return err; 329 330 /* Check device ID. We currently know about: 331 * SCH3112 (0x7c), SCH3114 (0x7d), and SCH3116 (0x7f). */ 332 reg = sch311x_sio_inb(sio_config_port, 0x20); 333 if (!(reg == 0x7c || reg == 0x7d || reg == 0x7f)) { 334 err = -ENODEV; 335 goto exit; 336 } 337 dev_id = reg == 0x7c ? 2 : reg == 0x7d ? 4 : 6; 338 339 /* Select logical device A (runtime registers) */ 340 sch311x_sio_outb(sio_config_port, 0x07, 0x0a); 341 342 /* Check if Logical Device Register is currently active */ 343 if ((sch311x_sio_inb(sio_config_port, 0x30) & 0x01) == 0) 344 pr_info("Seems that LDN 0x0a is not active...\n"); 345 346 /* Get the base address of the runtime registers */ 347 base_addr = (sch311x_sio_inb(sio_config_port, 0x60) << 8) | 348 sch311x_sio_inb(sio_config_port, 0x61); 349 if (!base_addr) { 350 pr_err("Base address not set\n"); 351 err = -ENODEV; 352 goto exit; 353 } 354 *addr = base_addr; 355 356 pr_info("Found an SMSC SCH311%d chip at 0x%04x\n", dev_id, base_addr); 357 358exit: 359 sch311x_sio_exit(sio_config_port); 360 return err; 361} 362 363static int __init sch311x_gpio_pdev_add(const unsigned short addr) 364{ 365 struct sch311x_pdev_data pdata; 366 int err; 367 368 pdata.runtime_reg = addr; 369 370 sch311x_gpio_pdev = platform_device_alloc(DRV_NAME, -1); 371 if (!sch311x_gpio_pdev) 372 return -ENOMEM; 373 374 err = platform_device_add_data(sch311x_gpio_pdev, 375 &pdata, sizeof(pdata)); 376 if (err) { 377 pr_err(DRV_NAME "Platform data allocation failed\n"); 378 goto err; 379 } 380 381 err = platform_device_add(sch311x_gpio_pdev); 382 if (err) { 383 pr_err(DRV_NAME "Device addition failed\n"); 384 goto err; 385 } 386 return 0; 387 388err: 389 platform_device_put(sch311x_gpio_pdev); 390 return err; 391} 392 393static int __init sch311x_gpio_init(void) 394{ 395 int err, i; 396 unsigned short addr = 0; 397 398 for (i = 0; i < ARRAY_SIZE(sch311x_ioports); i++) 399 if (sch311x_detect(sch311x_ioports[i], &addr) == 0) 400 break; 401 402 if (!addr) 403 return -ENODEV; 404 405 err = platform_driver_register(&sch311x_gpio_driver); 406 if (err) 407 return err; 408 409 err = sch311x_gpio_pdev_add(addr); 410 if (err) 411 goto unreg_platform_driver; 412 413 return 0; 414 415unreg_platform_driver: 416 platform_driver_unregister(&sch311x_gpio_driver); 417 return err; 418} 419 420static void __exit sch311x_gpio_exit(void) 421{ 422 platform_device_unregister(sch311x_gpio_pdev); 423 platform_driver_unregister(&sch311x_gpio_driver); 424} 425 426module_init(sch311x_gpio_init); 427module_exit(sch311x_gpio_exit); 428 429MODULE_AUTHOR("Bruno Randolf <br1@einfach.org>"); 430MODULE_DESCRIPTION("SMSC SCH311x GPIO Driver"); 431MODULE_LICENSE("GPL"); 432MODULE_ALIAS("platform:gpio-sch311x");