Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* linux/drivers/char/nsc_gpio.c
0003 
0004    National Semiconductor common GPIO device-file/VFS methods.
0005    Allows a user space process to control the GPIO pins.
0006 
0007    Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>
0008    Copyright (c) 2005      Jim Cromie <jim.cromie@gmail.com>
0009 */
0010 
0011 #include <linux/fs.h>
0012 #include <linux/module.h>
0013 #include <linux/errno.h>
0014 #include <linux/kernel.h>
0015 #include <linux/init.h>
0016 #include <linux/nsc_gpio.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/uaccess.h>
0019 #include <asm/io.h>
0020 
0021 #define NAME "nsc_gpio"
0022 
0023 void nsc_gpio_dump(struct nsc_gpio_ops *amp, unsigned index)
0024 {
0025     /* retrieve current config w/o changing it */
0026     u32 config = amp->gpio_config(index, ~0, 0);
0027 
0028     /* user requested via 'v' command, so its INFO */
0029     dev_info(amp->dev, "io%02u: 0x%04x %s %s %s %s %s %s %s\tio:%d/%d\n",
0030          index, config,
0031          (config & 1) ? "OE" : "TS",      /* output-enabled/tristate */
0032          (config & 2) ? "PP" : "OD",      /* push pull / open drain */
0033          (config & 4) ? "PUE" : "PUD",    /* pull up enabled/disabled */
0034          (config & 8) ? "LOCKED" : "",    /* locked / unlocked */
0035          (config & 16) ? "LEVEL" : "EDGE",/* level/edge input */
0036          (config & 32) ? "HI" : "LO",     /* trigger on rise/fall edge */
0037          (config & 64) ? "DEBOUNCE" : "", /* debounce */
0038 
0039          amp->gpio_get(index), amp->gpio_current(index));
0040 }
0041 
0042 ssize_t nsc_gpio_write(struct file *file, const char __user *data,
0043                size_t len, loff_t *ppos)
0044 {
0045     unsigned m = iminor(file_inode(file));
0046     struct nsc_gpio_ops *amp = file->private_data;
0047     struct device *dev = amp->dev;
0048     size_t i;
0049     int err = 0;
0050 
0051     for (i = 0; i < len; ++i) {
0052         char c;
0053         if (get_user(c, data + i))
0054             return -EFAULT;
0055         switch (c) {
0056         case '0':
0057             amp->gpio_set(m, 0);
0058             break;
0059         case '1':
0060             amp->gpio_set(m, 1);
0061             break;
0062         case 'O':
0063             dev_dbg(dev, "GPIO%d output enabled\n", m);
0064             amp->gpio_config(m, ~1, 1);
0065             break;
0066         case 'o':
0067             dev_dbg(dev, "GPIO%d output disabled\n", m);
0068             amp->gpio_config(m, ~1, 0);
0069             break;
0070         case 'T':
0071             dev_dbg(dev, "GPIO%d output is push pull\n", m);
0072             amp->gpio_config(m, ~2, 2);
0073             break;
0074         case 't':
0075             dev_dbg(dev, "GPIO%d output is open drain\n", m);
0076             amp->gpio_config(m, ~2, 0);
0077             break;
0078         case 'P':
0079             dev_dbg(dev, "GPIO%d pull up enabled\n", m);
0080             amp->gpio_config(m, ~4, 4);
0081             break;
0082         case 'p':
0083             dev_dbg(dev, "GPIO%d pull up disabled\n", m);
0084             amp->gpio_config(m, ~4, 0);
0085             break;
0086         case 'v':
0087             /* View Current pin settings */
0088             amp->gpio_dump(amp, m);
0089             break;
0090         case '\n':
0091             /* end of settings string, do nothing */
0092             break;
0093         default:
0094             dev_err(dev, "io%2d bad setting: chr<0x%2x>\n",
0095                 m, (int)c);
0096             err++;
0097         }
0098     }
0099     if (err)
0100         return -EINVAL; /* full string handled, report error */
0101 
0102     return len;
0103 }
0104 
0105 ssize_t nsc_gpio_read(struct file *file, char __user * buf,
0106               size_t len, loff_t * ppos)
0107 {
0108     unsigned m = iminor(file_inode(file));
0109     int value;
0110     struct nsc_gpio_ops *amp = file->private_data;
0111 
0112     value = amp->gpio_get(m);
0113     if (put_user(value ? '1' : '0', buf))
0114         return -EFAULT;
0115 
0116     return 1;
0117 }
0118 
0119 /* common file-ops routines for both scx200_gpio and pc87360_gpio */
0120 EXPORT_SYMBOL(nsc_gpio_write);
0121 EXPORT_SYMBOL(nsc_gpio_read);
0122 EXPORT_SYMBOL(nsc_gpio_dump);
0123 
0124 static int __init nsc_gpio_init(void)
0125 {
0126     printk(KERN_DEBUG NAME " initializing\n");
0127     return 0;
0128 }
0129 
0130 static void __exit nsc_gpio_cleanup(void)
0131 {
0132     printk(KERN_DEBUG NAME " cleanup\n");
0133 }
0134 
0135 module_init(nsc_gpio_init);
0136 module_exit(nsc_gpio_cleanup);
0137 
0138 MODULE_AUTHOR("Jim Cromie <jim.cromie@gmail.com>");
0139 MODULE_DESCRIPTION("NatSemi GPIO Common Methods");
0140 MODULE_LICENSE("GPL");