Chinaunix首页 | 论坛 | 博客
  • 博客访问: 115418
  • 博文数量: 20
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 77
  • 用 户 组: 普通用户
  • 注册时间: 2014-01-21 09:11
文章分类

全部博文(20)

文章存档

2015年(1)

2014年(19)

我的朋友

分类: LINUX

2014-03-05 10:25:58

原文地址:gpiolib管理gpio过程 作者:chumojing

linux2.6.38中提供了统一管理外部io的模块。本文的内容是跟踪这些模块,是如何关联起来的。

环境:龙芯1b开发板


一、重点关注的相关的结构体:

gpiolib.c文件,被移植到driver/gpio/目录下。

structgpio_desc {

structgpio_chip *chip;

unsignedlong flags;

/*flag symbols are bit numbers */

#defineFLAG_REQUESTED 0

#defineFLAG_IS_OUT 1

#defineFLAG_RESERVED 2

#defineFLAG_EXPORT 3 /* protected by sysfs_lock */

#defineFLAG_SYSFS 4 /* exported via /sys/class/gpio/control */

#defineFLAG_TRIG_FALL 5 /* trigger on falling edge */

#defineFLAG_TRIG_RISE 6 /* trigger on rising edge */

#defineFLAG_ACTIVE_LOW 7 /* sysfs value has active low */


#defineID_SHIFT 16 /* add new flags before this one */


#defineGPIO_FLAGS_MASK ((1 << ID_SHIFT) - 1)

#defineGPIO_TRIGGER_MASK (BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE))


#ifdefCONFIG_DEBUG_FS

constchar *label;

#endif

};


对于上面这个结构体,现在只关心structgpio_chip *chip;

structgpio_chip {

constchar *label;

structdevice *dev;

structmodule *owner;


int (*request)(struct gpio_chip *chip,

unsignedoffset);

void (*free)(struct gpio_chip *chip,

unsignedoffset);


int (*direction_input)(struct gpio_chip *chip,

unsignedoffset);

int (*get)(struct gpio_chip *chip,

unsignedoffset);

int (*direction_output)(struct gpio_chip *chip,

unsignedoffset, int value);

int (*set_debounce)(struct gpio_chip *chip,

unsignedoffset, unsigned debounce);


void (*set)(struct gpio_chip *chip,

unsignedoffset, int value);


int (*to_irq)(struct gpio_chip *chip,

unsignedoffset);


void (*dbg_show)(struct seq_file *s,

structgpio_chip *chip);

int base;

u16 ngpio;

constchar *const *names;

unsigned can_sleep:1;

unsigned exported:1;

/****省略了一些内容********/

};



二、把目光转到龙芯自身的gpio文件。

1b的内容是放在arch/mips/loongson/sb2f-board/gpio.c


staticstruct gpio_chip ls2f_chip = {

.label = "ls2f",

.direction_input = ls2f_gpio_direction_input,

.get = ls2f_gpio_get_value,

.direction_output = ls2f_gpio_direction_output,

.set = ls2f_gpio_set_value,

.base = 0,

.ngpio = STLS2F_N_GPIO,

};


staticint __init ls2f_gpio_setup(void)

{

returngpiochip_add(&ls2f_chip);

}

arch_initcall(ls2f_gpio_setup);


arch_initcall函数在内核启动的时候被初始化。(详细情况,以后再写)

跟着调用了ls2f_gpio_setup -> gpiochip_add

增加了ls2f_chip

注意ls2f_chip里面的函数指针(我们姑且成为接口吧)已经在本文件(gpio.c里面实现。)


三、现在跳到gpiochip_add函数(在driver/gpio/gpiolib.c中)

intgpiochip_add(struct gpio_chip *chip)

{

……

for(id = base; id < base + chip->ngpio; id++) {

gpio_desc[id].chip= chip;


……

}

……

}


上述的代码初始化了gpio_desc数组。在gpiolib.c中定义:

staticstruct gpio_desc gpio_desc[ARCH_NR_GPIOS];


直到这里,gpio_desc已经可以和龙芯下面的函数接口关联起来!



四、在驱动中利用这些接口

如在驱动中调用函数:gpio_direction_output(57,0);

函数定义位gpiolib.c文件中

intgpio_direction_output(unsigned gpio, int value)

{

……

status= chip->direction_output(chip, gpio, value);

……

}


第三点已经说明了是如何关联起来的。于是相当于调用龙芯芯片下的函数:

staticint ls2f_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,int level)

{

u32temp;

u32mask;


if(gpio >= STLS2F_N_GPIO)

return-EINVAL;


gpio_set_value(gpio,level);

if(gpio>= 32){

spin_lock(&gpio_lock);

mask= 1 << (gpio - 32);

temp= LOONGSON_GPIOCFG1;

temp|= mask;

LOONGSON_GPIOCFG1= temp;

temp= LOONGSON_GPIOIE1;

temp&= (~mask);

LOONGSON_GPIOIE1= temp;

spin_unlock(&gpio_lock);

}else{

spin_lock(&gpio_lock);

mask= 1 << gpio;

temp= LOONGSON_GPIOCFG0;

temp|= mask;

LOONGSON_GPIOCFG0= temp;

temp= LOONGSON_GPIOIE0;

temp&= (~mask);

LOONGSON_GPIOIE0= temp;

spin_unlock(&gpio_lock);

}

return0;

}


直到这里,gpio的调用过程已经完成了。

其余的函数:

ls2f_gpio_direction_input,

ls2f_gpio_get_value,

ls2f_gpio_direction_output,

ls2f_gpio_set_value,


的函数类似。



五、debugfs调试gpio端口

可以利用mount-t debugfs none /mnt

那么可以在/mnt下面看到gpio文件

通过echo57 w1 > gpio

就可以对gpio的第57个关键写入1


疑问:为什么这样可以调试呢?

查看文件 ~/driver/gpio/gpiolib.c

staticconst struct file_operations gpiolib_operations = {

.open = gpiolib_open,

.read = gpiolib_read,

.write = gpiolib_write,

.llseek = seq_lseek,

.release = single_release,

};

staticint __init gpiolib_debugfs_init(void)

{

(void)debugfs_create_file("gpio", S_IFREG | S_IRUGO,

NULL,NULL, &gpiolib_operations);

return0;

}

subsys_initcall(gpiolib_debugfs_init);


gpiolib_debugfs_init函数在内核启动的时候被调用。

于是创建了一个gpio文件,同时关联上了gpiolib_operations

于是,echo57 w1 > gpio

相当于调用 gpiolib_write函数;

staticssize_t gpiolib_write(struct file *file, const char __user *buf,size_t size, loff_t *ppos)

{

charinfo[255];

int port=0,value=0;

memset(info,0, 255);

memcpy(info,buf, size);

printk("gpio:%s\n",info);

if((info[0]>= '0') && (info[0] <= '9')){

port= (info[0] - 48)*10;

if((info[1]>= '0') && (info[1] <= '9')){

port+= (info[1] - 48);

if(info[2]== ' '){

if(info[3] == 'w'){

value = (info[4] == '0')?0:1;

}

}

}

}

if(info[3]== 'r'){

gpio_direction_input(port);

printk("gpio%dstatus = %d\n", port, __gpio_get_value(port));

}elseif(info[3] == 'w'){

printk("write%d to gpio%d\n", value, port);

gpio_direction_output(port, value);

__gpio_set_value(port,value);

}

returnsize;

}


这就很明显了。

阅读(1927) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~