gpio操作(LS1B)
1、一般gpio_request 封装了mem_request(),起保护作用,最后要调用mem_free之类的,主要是告诉内核这个地址被占用了。当其他地方调用同一地址gpio_request就会报告错误,改地址已被申请。在/proc/mem 可以看到有地址占用表描述。
这种用法的保护前提是大家都遵守先申请在访问,有一个地方没有遵守这个规则,这功能就失效了,就好比进程互斥,必须大家在访问临界资源的时候都先获取锁一样,其中一个没有遵守约定,代码报废;
2、__gpio_set_value 和 gpio_set_value的区别
一般的带有__这种操作的宏和函数是未保护的,对这种__操作的使用最好不用;主要是为了防止错误地址引用: __gpio_set_value是没有地址范围检测的,如果引用非法地址,有可能内核down掉;
//龙芯1b buzzer.c
#include <linux/fs.h>
#include <linux/module.h>
#include 
<linux/kernel.h>
#include <linux/init.h>
#include 
<linux/cdev.h>
#include <linux/io.h>
#include 
<linux/errno.h>
#include <linux/platform_device.h>
#include 
<linux/miscdevice.h> 
#include <linux/gpio_keys.h>
#include 
<asm/gpio.h>
#define DEVNAME "buzzer_gpio"
#define BUZZER_MINOR 123
MODULE_AUTHOR("liangqx 
<liangqingxin-gz@loongson.cn>");
MODULE_DESCRIPTION("Drive the buzzer 
through the gpio");
MODULE_LICENSE("GPL");
static int major;
module_param(major, int, 0);
static struct gpio_keys_platform_data *pkb = NULL;
static int buzzer_set_value(struct file *filp, const char __user 
*buffer,
				size_t count, loff_t *ppos)
{
	char code[2];
	int 
port,value;
copy_from_user(code, buffer, (count < 2)?count:2);
value = code[0] - ‘0‘;
if(value >= pkb->nbuttons) return -ENOMEM;
	port = pkb->buttons[value].gpio;
	value = code[1] - 
‘0‘;
	printk("prot is %d, value is 
%d\n",port,value);
	gpio_set_value_cansleep(port, value);
	return count;	
}
static int __devinit buzzer_gpio_probe(struct platform_device 
*pdev)
{
	struct gpio_keys_platform_data *pdata = 
pdev->dev.platform_data;
	int i;
pkb = pdata;
	for(i = 0;i < pkb->nbuttons;i++)
	{
gpio_request(pkb->buttons[i].gpio,"buzzer");
		gpio_direction_output(pkb->buttons[i].gpio, 
0);
	}
	return 0;
}
static const struct file_operations buzzer_fops = {
	.owner		= 
THIS_MODULE,
	.write		= buzzer_set_value,
};
static struct miscdevice buzzer_misc_device = 
{
	BUZZER_MINOR,
	"buzzer_gpio",
	&buzzer_fops,
};
struct platform_driver buzzer_device_driver = {
	.probe		= 
buzzer_gpio_probe,
	.driver		= {
		.name 	= "buzzer_gpio",
	}
};
static int __init 
buzzer_init(void)
{
	if(misc_register(&buzzer_misc_device)){
		printk(KERN_WARNING 
"buzzer:Couldn‘t register device 10, %d.\n", BUZZER_MINOR);
		return 
-EBUSY;
	}
	return platform_driver_register(&buzzer_device_driver);
}
static void __exit buzzer_exit(void)
{
	int 
i;
	misc_deregister(&buzzer_misc_device);
	for(i = 0;i < 
pkb->nbuttons;i++){
		gpio_free(pkb->buttons[i].gpio);
	}
}
module_init(buzzer_init);
module_exit(buzzer_exit);