root/drivers/gpio/gpio-sch311x.c

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

DEFINITIONS

This source file includes following definitions.
  1. sch311x_sio_enter
  2. sch311x_sio_exit
  3. sch311x_sio_inb
  4. sch311x_sio_outb
  5. sch311x_gpio_request
  6. sch311x_gpio_free
  7. sch311x_gpio_get
  8. __sch311x_gpio_set
  9. sch311x_gpio_set
  10. sch311x_gpio_direction_in
  11. sch311x_gpio_direction_out
  12. sch311x_gpio_get_direction
  13. sch311x_gpio_set_config
  14. sch311x_gpio_probe
  15. sch311x_gpio_remove
  16. sch311x_detect
  17. sch311x_gpio_pdev_add
  18. sch311x_gpio_init
  19. sch311x_gpio_exit

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

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