Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * GPIO driver for the SMSC SCH311x Super-I/O chips
0004  *
0005  * Copyright (C) 2013 Bruno Randolf <br1@einfach.org>
0006  *
0007  * SuperIO functions and chip detection:
0008  * (c) Copyright 2008 Wim Van Sebroeck <wim@iguana.be>.
0009  */
0010 
0011 #include <linux/ioport.h>
0012 #include <linux/module.h>
0013 #include <linux/kernel.h>
0014 #include <linux/init.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/gpio/driver.h>
0017 #include <linux/bitops.h>
0018 #include <linux/io.h>
0019 
0020 #define DRV_NAME            "gpio-sch311x"
0021 
0022 #define SCH311X_GPIO_CONF_DIR       BIT(0)
0023 #define SCH311X_GPIO_CONF_INVERT    BIT(1)
0024 #define SCH311X_GPIO_CONF_OPEN_DRAIN    BIT(7)
0025 
0026 #define SIO_CONFIG_KEY_ENTER        0x55
0027 #define SIO_CONFIG_KEY_EXIT     0xaa
0028 
0029 #define GP1             0x4b
0030 
0031 static int sch311x_ioports[] = { 0x2e, 0x4e, 0x162e, 0x164e };
0032 
0033 static struct platform_device *sch311x_gpio_pdev;
0034 
0035 struct sch311x_pdev_data {      /* platform device data */
0036     unsigned short runtime_reg; /* runtime register base address */
0037 };
0038 
0039 struct sch311x_gpio_block {     /* one GPIO block runtime data */
0040     struct gpio_chip chip;
0041     unsigned short data_reg;    /* from definition below */
0042     unsigned short *config_regs;    /* pointer to definition below */
0043     unsigned short runtime_reg; /* runtime register */
0044     spinlock_t lock;        /* lock for this GPIO block */
0045 };
0046 
0047 struct sch311x_gpio_priv {      /* driver private data */
0048     struct sch311x_gpio_block blocks[6];
0049 };
0050 
0051 struct sch311x_gpio_block_def {     /* register address definitions */
0052     unsigned short data_reg;
0053     unsigned short config_regs[8];
0054     unsigned short base;
0055 };
0056 
0057 /* Note: some GPIOs are not available, these are marked with 0x00 */
0058 
0059 static struct sch311x_gpio_block_def sch311x_gpio_blocks[] = {
0060     {
0061         .data_reg = 0x4b,   /* GP1 */
0062         .config_regs = {0x23, 0x24, 0x25, 0x26, 0x27, 0x29, 0x2a, 0x2b},
0063         .base = 10,
0064     },
0065     {
0066         .data_reg = 0x4c,   /* GP2 */
0067         .config_regs = {0x00, 0x2c, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x32},
0068         .base = 20,
0069     },
0070     {
0071         .data_reg = 0x4d,   /* GP3 */
0072         .config_regs = {0x33, 0x34, 0x35, 0x36, 0x37, 0x00, 0x39, 0x3a},
0073         .base = 30,
0074     },
0075     {
0076         .data_reg = 0x4e,   /* GP4 */
0077         .config_regs = {0x3b, 0x00, 0x3d, 0x00, 0x6e, 0x6f, 0x72, 0x73},
0078         .base = 40,
0079     },
0080     {
0081         .data_reg = 0x4f,   /* GP5 */
0082         .config_regs = {0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46},
0083         .base = 50,
0084     },
0085     {
0086         .data_reg = 0x50,   /* GP6 */
0087         .config_regs = {0x47, 0x48, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59},
0088         .base = 60,
0089     },
0090 };
0091 
0092 /*
0093  *  Super-IO functions
0094  */
0095 
0096 static inline int sch311x_sio_enter(int sio_config_port)
0097 {
0098     /* Don't step on other drivers' I/O space by accident. */
0099     if (!request_muxed_region(sio_config_port, 2, DRV_NAME)) {
0100         pr_err(DRV_NAME "I/O address 0x%04x already in use\n",
0101                sio_config_port);
0102         return -EBUSY;
0103     }
0104 
0105     outb(SIO_CONFIG_KEY_ENTER, sio_config_port);
0106     return 0;
0107 }
0108 
0109 static inline void sch311x_sio_exit(int sio_config_port)
0110 {
0111     outb(SIO_CONFIG_KEY_EXIT, sio_config_port);
0112     release_region(sio_config_port, 2);
0113 }
0114 
0115 static inline int sch311x_sio_inb(int sio_config_port, int reg)
0116 {
0117     outb(reg, sio_config_port);
0118     return inb(sio_config_port + 1);
0119 }
0120 
0121 static inline void sch311x_sio_outb(int sio_config_port, int reg, int val)
0122 {
0123     outb(reg, sio_config_port);
0124     outb(val, sio_config_port + 1);
0125 }
0126 
0127 
0128 /*
0129  *  GPIO functions
0130  */
0131 
0132 static int sch311x_gpio_request(struct gpio_chip *chip, unsigned offset)
0133 {
0134     struct sch311x_gpio_block *block = gpiochip_get_data(chip);
0135 
0136     if (block->config_regs[offset] == 0) /* GPIO is not available */
0137         return -ENODEV;
0138 
0139     if (!request_region(block->runtime_reg + block->config_regs[offset],
0140                 1, DRV_NAME)) {
0141         dev_err(chip->parent, "Failed to request region 0x%04x.\n",
0142             block->runtime_reg + block->config_regs[offset]);
0143         return -EBUSY;
0144     }
0145     return 0;
0146 }
0147 
0148 static void sch311x_gpio_free(struct gpio_chip *chip, unsigned offset)
0149 {
0150     struct sch311x_gpio_block *block = gpiochip_get_data(chip);
0151 
0152     if (block->config_regs[offset] == 0) /* GPIO is not available */
0153         return;
0154 
0155     release_region(block->runtime_reg + block->config_regs[offset], 1);
0156 }
0157 
0158 static int sch311x_gpio_get(struct gpio_chip *chip, unsigned offset)
0159 {
0160     struct sch311x_gpio_block *block = gpiochip_get_data(chip);
0161     u8 data;
0162 
0163     spin_lock(&block->lock);
0164     data = inb(block->runtime_reg + block->data_reg);
0165     spin_unlock(&block->lock);
0166 
0167     return !!(data & BIT(offset));
0168 }
0169 
0170 static void __sch311x_gpio_set(struct sch311x_gpio_block *block,
0171                    unsigned offset, int value)
0172 {
0173     u8 data = inb(block->runtime_reg + block->data_reg);
0174     if (value)
0175         data |= BIT(offset);
0176     else
0177         data &= ~BIT(offset);
0178     outb(data, block->runtime_reg + block->data_reg);
0179 }
0180 
0181 static void sch311x_gpio_set(struct gpio_chip *chip, unsigned offset,
0182                  int value)
0183 {
0184     struct sch311x_gpio_block *block = gpiochip_get_data(chip);
0185 
0186     spin_lock(&block->lock);
0187     __sch311x_gpio_set(block, offset, value);
0188     spin_unlock(&block->lock);
0189 }
0190 
0191 static int sch311x_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
0192 {
0193     struct sch311x_gpio_block *block = gpiochip_get_data(chip);
0194     u8 data;
0195 
0196     spin_lock(&block->lock);
0197     data = inb(block->runtime_reg + block->config_regs[offset]);
0198     data |= SCH311X_GPIO_CONF_DIR;
0199     outb(data, block->runtime_reg + block->config_regs[offset]);
0200     spin_unlock(&block->lock);
0201 
0202     return 0;
0203 }
0204 
0205 static int sch311x_gpio_direction_out(struct gpio_chip *chip, unsigned offset,
0206                       int value)
0207 {
0208     struct sch311x_gpio_block *block = gpiochip_get_data(chip);
0209     u8 data;
0210 
0211     spin_lock(&block->lock);
0212 
0213     data = inb(block->runtime_reg + block->config_regs[offset]);
0214     data &= ~SCH311X_GPIO_CONF_DIR;
0215     outb(data, block->runtime_reg + block->config_regs[offset]);
0216     __sch311x_gpio_set(block, offset, value);
0217 
0218     spin_unlock(&block->lock);
0219     return 0;
0220 }
0221 
0222 static int sch311x_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
0223 {
0224     struct sch311x_gpio_block *block = gpiochip_get_data(chip);
0225     u8 data;
0226 
0227     spin_lock(&block->lock);
0228     data = inb(block->runtime_reg + block->config_regs[offset]);
0229     spin_unlock(&block->lock);
0230 
0231     if (data & SCH311X_GPIO_CONF_DIR)
0232         return GPIO_LINE_DIRECTION_IN;
0233 
0234     return GPIO_LINE_DIRECTION_OUT;
0235 }
0236 
0237 static int sch311x_gpio_set_config(struct gpio_chip *chip, unsigned offset,
0238                    unsigned long config)
0239 {
0240     struct sch311x_gpio_block *block = gpiochip_get_data(chip);
0241     enum pin_config_param param = pinconf_to_config_param(config);
0242     u8 data;
0243 
0244     switch (param) {
0245     case PIN_CONFIG_DRIVE_OPEN_DRAIN:
0246         spin_lock(&block->lock);
0247         data = inb(block->runtime_reg + block->config_regs[offset]);
0248         data |= SCH311X_GPIO_CONF_OPEN_DRAIN;
0249         outb(data, block->runtime_reg + block->config_regs[offset]);
0250         spin_unlock(&block->lock);
0251         return 0;
0252     case PIN_CONFIG_DRIVE_PUSH_PULL:
0253         spin_lock(&block->lock);
0254         data = inb(block->runtime_reg + block->config_regs[offset]);
0255         data &= ~SCH311X_GPIO_CONF_OPEN_DRAIN;
0256         outb(data, block->runtime_reg + block->config_regs[offset]);
0257         spin_unlock(&block->lock);
0258         return 0;
0259     default:
0260         break;
0261     }
0262     return -ENOTSUPP;
0263 }
0264 
0265 static int sch311x_gpio_probe(struct platform_device *pdev)
0266 {
0267     struct sch311x_pdev_data *pdata = dev_get_platdata(&pdev->dev);
0268     struct sch311x_gpio_priv *priv;
0269     struct sch311x_gpio_block *block;
0270     int err, i;
0271 
0272     /* we can register all GPIO data registers at once */
0273     if (!devm_request_region(&pdev->dev, pdata->runtime_reg + GP1, 6,
0274         DRV_NAME)) {
0275         dev_err(&pdev->dev, "Failed to request region 0x%04x-0x%04x.\n",
0276             pdata->runtime_reg + GP1, pdata->runtime_reg + GP1 + 5);
0277         return -EBUSY;
0278     }
0279 
0280     priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
0281     if (!priv)
0282         return -ENOMEM;
0283 
0284     platform_set_drvdata(pdev, priv);
0285 
0286     for (i = 0; i < ARRAY_SIZE(priv->blocks); i++) {
0287         block = &priv->blocks[i];
0288 
0289         spin_lock_init(&block->lock);
0290 
0291         block->chip.label = DRV_NAME;
0292         block->chip.owner = THIS_MODULE;
0293         block->chip.request = sch311x_gpio_request;
0294         block->chip.free = sch311x_gpio_free;
0295         block->chip.direction_input = sch311x_gpio_direction_in;
0296         block->chip.direction_output = sch311x_gpio_direction_out;
0297         block->chip.get_direction = sch311x_gpio_get_direction;
0298         block->chip.set_config = sch311x_gpio_set_config;
0299         block->chip.get = sch311x_gpio_get;
0300         block->chip.set = sch311x_gpio_set;
0301         block->chip.ngpio = 8;
0302         block->chip.parent = &pdev->dev;
0303         block->chip.base = sch311x_gpio_blocks[i].base;
0304         block->config_regs = sch311x_gpio_blocks[i].config_regs;
0305         block->data_reg = sch311x_gpio_blocks[i].data_reg;
0306         block->runtime_reg = pdata->runtime_reg;
0307 
0308         err = gpiochip_add_data(&block->chip, block);
0309         if (err < 0) {
0310             dev_err(&pdev->dev,
0311                 "Could not register gpiochip, %d\n", err);
0312             goto exit_err;
0313         }
0314         dev_info(&pdev->dev,
0315              "SMSC SCH311x GPIO block %d registered.\n", i);
0316     }
0317 
0318     return 0;
0319 
0320 exit_err:
0321     /* release already registered chips */
0322     for (--i; i >= 0; i--)
0323         gpiochip_remove(&priv->blocks[i].chip);
0324     return err;
0325 }
0326 
0327 static int sch311x_gpio_remove(struct platform_device *pdev)
0328 {
0329     struct sch311x_gpio_priv *priv = platform_get_drvdata(pdev);
0330     int i;
0331 
0332     for (i = 0; i < ARRAY_SIZE(priv->blocks); i++) {
0333         gpiochip_remove(&priv->blocks[i].chip);
0334         dev_info(&pdev->dev,
0335              "SMSC SCH311x GPIO block %d unregistered.\n", i);
0336     }
0337     return 0;
0338 }
0339 
0340 static struct platform_driver sch311x_gpio_driver = {
0341     .driver.name    = DRV_NAME,
0342     .probe      = sch311x_gpio_probe,
0343     .remove     = sch311x_gpio_remove,
0344 };
0345 
0346 
0347 /*
0348  *  Init & exit routines
0349  */
0350 
0351 static int __init sch311x_detect(int sio_config_port, unsigned short *addr)
0352 {
0353     int err = 0, reg;
0354     unsigned short base_addr;
0355     u8 dev_id;
0356 
0357     err = sch311x_sio_enter(sio_config_port);
0358     if (err)
0359         return err;
0360 
0361     /* Check device ID. */
0362     reg = sch311x_sio_inb(sio_config_port, 0x20);
0363     switch (reg) {
0364     case 0x7c: /* SCH3112 */
0365         dev_id = 2;
0366         break;
0367     case 0x7d: /* SCH3114 */
0368         dev_id = 4;
0369         break;
0370     case 0x7f: /* SCH3116 */
0371         dev_id = 6;
0372         break;
0373     default:
0374         err = -ENODEV;
0375         goto exit;
0376     }
0377 
0378     /* Select logical device A (runtime registers) */
0379     sch311x_sio_outb(sio_config_port, 0x07, 0x0a);
0380 
0381     /* Check if Logical Device Register is currently active */
0382     if ((sch311x_sio_inb(sio_config_port, 0x30) & 0x01) == 0)
0383         pr_info("Seems that LDN 0x0a is not active...\n");
0384 
0385     /* Get the base address of the runtime registers */
0386     base_addr = (sch311x_sio_inb(sio_config_port, 0x60) << 8) |
0387                sch311x_sio_inb(sio_config_port, 0x61);
0388     if (!base_addr) {
0389         pr_err("Base address not set\n");
0390         err = -ENODEV;
0391         goto exit;
0392     }
0393     *addr = base_addr;
0394 
0395     pr_info("Found an SMSC SCH311%d chip at 0x%04x\n", dev_id, base_addr);
0396 
0397 exit:
0398     sch311x_sio_exit(sio_config_port);
0399     return err;
0400 }
0401 
0402 static int __init sch311x_gpio_pdev_add(const unsigned short addr)
0403 {
0404     struct sch311x_pdev_data pdata;
0405     int err;
0406 
0407     pdata.runtime_reg = addr;
0408 
0409     sch311x_gpio_pdev = platform_device_alloc(DRV_NAME, -1);
0410     if (!sch311x_gpio_pdev)
0411         return -ENOMEM;
0412 
0413     err = platform_device_add_data(sch311x_gpio_pdev,
0414                        &pdata, sizeof(pdata));
0415     if (err) {
0416         pr_err(DRV_NAME "Platform data allocation failed\n");
0417         goto err;
0418     }
0419 
0420     err = platform_device_add(sch311x_gpio_pdev);
0421     if (err) {
0422         pr_err(DRV_NAME "Device addition failed\n");
0423         goto err;
0424     }
0425     return 0;
0426 
0427 err:
0428     platform_device_put(sch311x_gpio_pdev);
0429     return err;
0430 }
0431 
0432 static int __init sch311x_gpio_init(void)
0433 {
0434     int err, i;
0435     unsigned short addr = 0;
0436 
0437     for (i = 0; i < ARRAY_SIZE(sch311x_ioports); i++)
0438         if (sch311x_detect(sch311x_ioports[i], &addr) == 0)
0439             break;
0440 
0441     if (!addr)
0442         return -ENODEV;
0443 
0444     err = platform_driver_register(&sch311x_gpio_driver);
0445     if (err)
0446         return err;
0447 
0448     err = sch311x_gpio_pdev_add(addr);
0449     if (err)
0450         goto unreg_platform_driver;
0451 
0452     return 0;
0453 
0454 unreg_platform_driver:
0455     platform_driver_unregister(&sch311x_gpio_driver);
0456     return err;
0457 }
0458 
0459 static void __exit sch311x_gpio_exit(void)
0460 {
0461     platform_device_unregister(sch311x_gpio_pdev);
0462     platform_driver_unregister(&sch311x_gpio_driver);
0463 }
0464 
0465 module_init(sch311x_gpio_init);
0466 module_exit(sch311x_gpio_exit);
0467 
0468 MODULE_AUTHOR("Bruno Randolf <br1@einfach.org>");
0469 MODULE_DESCRIPTION("SMSC SCH311x GPIO Driver");
0470 MODULE_LICENSE("GPL");
0471 MODULE_ALIAS("platform:gpio-sch311x");