全志A20 GPIO 总结文档

时间:2022-02-11 03:32:59
/*
* author: chwenj@gmail.com.
* Agreement: GPL.
*/

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define GPIO_SET 0xAC
#define GPIO_GET 0xAB

#define DEVICE_FILE "/dev/gpio_cdev"

typedef struct {
unsigned char count; //GPIO序列
unsigned char data; //GPIO电平状态
} gpio_userspace_t;

/*main*/
int main(/* int argc, char **argv */)
{
/*open*/
int gpio_fd, ret;

gpio_fd = open(DEVICE_FILE, O_RDWR); //读写权限打开文件
if (gpio_fd < 0) {
printf("gpio device fail to open.\n");
return -1;
}
printf("%s opend.\n", DEVICE_FILE);

#if 1
/*write*/
gpio_userspace_t write_gpio;
write_gpio.count = 5; //GPIO序列号
write_gpio.data = 1; //GPIO电平值

printf("write: count = %d , data = %d.\n", write_gpio.count, write_gpio.data);

ret = write(gpio_fd, &write_gpio, sizeof(gpio_userspace_t));
if (ret < 0) {
printf("%s fail to write.\n", DEVICE_FILE);
return -1;
}
#endif

/*ioctl*/
gpio_userspace_t ioctl_gpio;
ioctl_gpio.data = 0xff; //level:0xff
ioctl_gpio.count = 5; //pin:4

ret = ioctl(gpio_fd, GPIO_SET, &ioctl_gpio);
if (ret < 0) {
printf("ioctl: ioctl fail.\n");
return -1;
}

/*read*/
gpio_userspace_t read_gpio;

ret = read(gpio_fd, &read_gpio, sizeof(gpio_userspace_t));
if (ret < 0) {
printf("read: fail to read.\n");
return -1;
}
printf("read: count = %d, data = %d.\n", read_gpio.count, read_gpio.data);

/*close*/
close(gpio_fd);
printf("%s close.\n", DEVICE_FILE);

return 0;
}
 
 


#include <linux/fs.h>#include <linux/types.h>#include <linux/module.h>#include <linux/errno.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/cdev.h>#include <linux/platform_device.h>#include <linux/utsname.h>#include <asm/uaccess.h>#include <asm/io.h>#include <mach/sys_config.h>#include <mach/includes.h>#include <linux/gpio.h>#include <linux/delay.h>/**********************************************************/#define GPIO_SET      0xAC  #define GPIO_GET      0xAB /**********************************************************/script_item_u *gpio_list = NULL;//gpio_userspace_t 和 gpio_pdata_t 在序列上是一一对应的关系.typedef struct {    unsigned char count;      //IO序列:0,1,2,..., 19.    unsigned char data;       //IO电平.} gpio_userspace_t;typedef struct {    struct gpio_config gpio;    char gpio_name[32];    int gpio_cnt;} gpio_pdata_t;typedef struct {//debug tag for printk    #define __DEBUG_TAG__    #ifdef __DEBUG_TAG__        #define dprintk(fmt, arg...) printk(fmt, ## arg)    #else        #define dprintk(fmt, arg...)      #endif//char device name: /dev/gpio_cdev    #define DEVICE_NAME "gpio_cdev"//multiple    #define MUL_SEL_INPUT   0    #define MUL_SEL_OUTPUT  1//char device     struct cdev *gpio_cdev;    dev_t devid;    struct class *gpio_class;//gpio count     int gpio_cnt;//general gpio subsystem    gpio_pdata_t pin[20];//} gpio_info_t;static gpio_info_t info;//global gpio pin record:char pin_count;/**********************************************************/static int gpio_cdev_open(struct inode *inode, struct file *file){    dprintk("[gpio]: gpio_cdev_open fn.\n");<span style="white-space:pre">	</span>return 0;}static int gpio_cdev_release(struct inode *inode, struct file *file){    dprintk("[gpio]: gpio_cdev_release fn.\n");<span style="white-space:pre">	</span>return 0;}/**********************************************************///writestatic ssize_t gpio_cdev_write(struct file *file, const char __user *buf, \        size_t count, loff_t *ppos){    gpio_userspace_t write_gpio;    unsigned char write_data, write_count;    dprintk("[gpio]: gpio_cdev_write fn.\n");    copy_from_user(&write_gpio, (gpio_userspace_t *)buf, sizeof(gpio_userspace_t));    write_data = write_gpio.data;    write_count = write_gpio.count;    dprintk("[gpio][write]: data=%d, count=%d.\n", write_data, write_count);    //error correction.    if ((write_data != 0) && (write_data != 1)) {        dprintk("[gpio][write][error]: write_data invalid.\n");     }    if ((write_count < 0) || (write_count >19)) {        dprintk("[gpio][write][error]: write_count does not exit.\n");       }    gpio_direction_output(info.pin[write_count].gpio.gpio, write_data);    //mdelay(1);    return 0;}//read static ssize_t gpio_cdev_read(struct file *file, char __user *buf, \        size_t count, loff_t *ppos){    int i;    unsigned char data;    unsigned int gpio;    gpio_userspace_t read_gpio;    dprintk("[gpio]: gpio_cdev_read fn.\n");#if 0    gpio_userspace_t read_gpio[20];    for (i = 0; i < 20; i++) {        gpio = info.pin[i].gpio.gpio;    //调试用;不要轻易打开:    #if 0        if(0 != gpio_direction_input(gpio)) {            dprintk("set to input failed.\n");            continue;        }    #endif        data = __gpio_get_value(gpio);        read_gpio[i].count = i;            read_gpio[i].data = data;        dprintk("[gpio][read]: pin_%d = %d.\n", read_gpio[i].count, read_gpio[i].data);    }    copy_to_user(buf, read_gpio, 20*sizeof(gpio_userspace_t));#else    i = pin_count;    dprintk("[gpio][read]: pin_count = %d.\n", i);    gpio = info.pin[i].gpio.gpio;    data = __gpio_get_value(gpio);    read_gpio.count = i;        read_gpio.data = data;    dprintk("[gpio][read]: count = %d; data = %d.\n", read_gpio.count, read_gpio.data);    copy_to_user(buf, &read_gpio, sizeof(gpio_userspace_t));#endif    return 0;}static long gpio_cdev_ioctl(struct file *file, unsigned int cmd, \        unsigned long arg){    dprintk("[gpio]: gpio_cdev_ioctl fn;");    dprintk(" cmd = %d.\n", cmd);    void __user *uarg;      uarg = (void __user *)arg;      gpio_userspace_t ioctl_gpio;    copy_from_user(&ioctl_gpio, (gpio_userspace_t *)uarg, sizeof(gpio_userspace_t));      dprintk("[gpio]:count = %d, data = %d.\n", ioctl_gpio.count, ioctl_gpio.data);    switch(cmd) {    case GPIO_SET:        dprintk("[gpio]: ioctl cmd = GPIO_SET.\n");        pin_count = ioctl_gpio.count;        dprintk("[gpio]: pin_count = %d.\n", pin_count);        if ((pin_count > 19)|| (pin_count < 0)) {            dprintk("[gpio][error]: gpio_cdev_ioctl: pin_count invalide.\n");         }        break;    case GPIO_GET:        dprintk("[gpio]: ioctl cmd = GPIO_SET.\n");        break;    default:        dprintk("[gpio]: ioctl cmd = default.\n");        break;    }    return 0;}static const struct file_operations gpio_cdev_fops = {    .owner          = THIS_MODULE,    .open           = gpio_cdev_open,    .release        = gpio_cdev_release,    .write          = gpio_cdev_write,    .read           = gpio_cdev_read,    .unlocked_ioctl = gpio_cdev_ioctl,};static int gpio_fetch_config(void){    char buffer[32] = {};    int i;    int cnt = info.gpio_cnt;    script_item_value_type_e  type;    script_item_u   val;    dprintk("[gpio]: gpio_fetch_config fn.\n");    dprintk("[gpio]: gpio_cnt=%d.\n", cnt);    dprintk("--------------------\n");    for(i=0; i< cnt; i++) {        //format sprintf        sprintf(buffer, "gpio_pin_%d", i);        dprintk("[gpio]: buffer=%s.\n", buffer);        //fetch gpio_pin_# issue        type = script_get_item("gpio_para", buffer, &val);        if (SCIRPT_ITEM_VALUE_TYPE_PIO != type) {            dprintk("[gpio]: item value type INVALID.\n");            return -1;        }        else {            info.pin[i].gpio.gpio = val.gpio.gpio;            info.pin[i].gpio.mul_sel = val.gpio.mul_sel;            dprintk("[gpio][pin%d]: gpio=%d, mul_sel=%d, ", i, info.pin[i].gpio.gpio, info.pin[i].gpio.mul_sel);            strcpy(info.pin[i].gpio_name, buffer);             dprintk("name=%s, ", info.pin[i].gpio_name);            info.pin[i].gpio_cnt = i;            dprintk("gpio_cnt=%d.\n", info.pin[i].gpio_cnt);            dprintk("--------------------\n");        }    }     dprintk("[gpio]: success to gpio_fetch_config.\n");    return 0;}static int __init gpio_module_init(void){    int ret = 0, err;    int cnt = 0, i;    script_item_value_type_e  type;    script_item_u   val;    dprintk("[gpio]: gpio_module_init fn.\n");    ret = alloc_chrdev_region(&(info.devid), 0, 20, DEVICE_NAME);    if ( ret ) {        dprintk("[gpio]: fail to alloc_chrdev_region.\n");        return -1;    }    dprintk("[gpio]: devid major=%d, minor=%d.\n", MAJOR(info.devid), MINOR(info.devid));    info.gpio_cdev = cdev_alloc();    cdev_init(info.gpio_cdev, &gpio_cdev_fops);    info.gpio_cdev->owner = THIS_MODULE;    err = cdev_add(info.gpio_cdev, info.devid, 1);    if (err) {        dprintk("[gpio]: cdev_add fail.\n");        return -1;    }    info.gpio_class = class_create(THIS_MODULE, DEVICE_NAME);    if (IS_ERR(info.gpio_class)) {        dprintk("[gpio]: class_create fail.\n");        return -1;    }    <span style="white-space:pre">	</span>device_create(info.gpio_class, NULL, info.devid, NULL, DEVICE_NAME);<span style="white-space:pre">	</span>    dprintk("[gpio]: success to create a gpio cdev.\n");    //    type = script_get_item("gpio_para", "gpio_used", &val);    if (SCIRPT_ITEM_VALUE_TYPE_INT != type) {        dprintk("[gpio]: type not right.\n");         return -1;    }    if (!val.val) {        dprintk("[gpio]: gpio is not used.\n");        return -1;    }    dprintk("[gpio]: gpio is used.\n");        //    cnt = script_get_pio_list("gpio_para", &gpio_list);    dprintk("[gpio]: cnt = %d.\n", cnt);    info.gpio_cnt = cnt;    if (cnt == 0) {        dprintk("[gpio]: fail to script_get_pio_list.\n");        return -1;    }    else {        dprintk("[gpio]: requeset gpio(s).\n");         for (i=0; i < cnt; i++) {            dprintk("[gpio]: requeset gpio No.%d.\n", i+1);             if (0 != gpio_request(gpio_list[i].gpio.gpio, NULL))                 dprintk("[gpio]: i = %d; fail to gpio_request.\n", i);         }        }    //dprintk("[gpio]: 1.\n");     //config gpio.    if (0 != sw_gpio_setall_range(&gpio_list[0], cnt)) {        dprintk("[gpio]: fail to sw_gpio_setall_range.\n");        return -1;     }    //dprintk("[gpio]: 2.\n");     /*************************************************************/    gpio_fetch_config();    //dprintk("[gpio]: 3.\n"); #if 0    //test gpio.    gpio_direction_output(info.pin[4].gpio.gpio, 0);    mdelay(5);    gpio_direction_output(info.pin[4].gpio.gpio, 1);    mdelay(5);#endif    //dprintk("[gpio]: 4.\n"); <span style="white-space:pre">	</span>return 0;}static void __exit gpio_module_exit(void){    dprintk("[gpio]: gpio_module_exit fn.\n");        <span style="white-space:pre">	</span>    device_destroy(info.gpio_class,  info.devid);    class_destroy(info.gpio_class);    cdev_del(info.gpio_cdev);}module_init(gpio_module_init);module_exit(gpio_module_exit);MODULE_AUTHOR("chwenj@gmail.com");MODULE_DESCRIPTION("gpio driver");MODULE_LICENSE("GPL");