方法一:通过/sys/文件接口操作IO端口 ,转自CSDN。
gpio_operation 通过/sys/文件接口操作IO端口 GPIO到文件系统的映射
* 控制GPIO的目录位于/sys/class/gpio
* /sys/class/gpio/export文件用于通知系统需要导出控制的GPIO引脚编号
* /sys/class/gpio/unexport 用于通知系统取消导出
* /sys/class/gpio/gpiochipX目录保存系统中GPIO寄存器的信息,包括每个寄存器控制引脚的起始编号base,寄存器名称,引脚总数 导出一个引脚的操作步骤
* 首先计算此引脚编号,引脚编号 = 控制引脚的寄存器基数 + 控制引脚寄存器位数
* 向/sys/class/gpio/export写入此编号,比如12号引脚,在shell中可以通过以下命令实现,命令成功后生成/sys/class/gpio/gpio12目录,如果没有出现相应的目录,说明此引脚不可导出:
echo 12 > /sys/class/gpio/export
* direction文件,定义输入输入方向,可以通过下面命令定义为输出
echo out > direction
* direction接受的参数:in, out, high, low。high/low同时设置方向为输出,并将value设置为相应的1/0。
* value文件是端口的数值,为1或0.
echo 1 > value
此驱动位于:drivers/gpio/gpiolib.c,需要打开 CONFIG_GPIO_SYSFS 宏定义
方法二:通过proc文件系统访问
/********************** 应用层 *******************************/
#define GIO_DEV_PATH "/proc/gio/"
#define GIO_MAX_ID (103)
int gio_getname( char *pName, int gio_id )
{
if( gio_id < 0 || gio_id > GIO_MAX_ID )
{
printf("gio id = %d over range!!\n", gio_id);
return -1;
}
sprintf( pName, GIO_DEV_PATH"gio%d", gio_id );
return 0;
}
int gio_write( int gio_id , int IsOn)
{
int fd_gio = 0;
char data[5];
int result = 0;
char dev_name[25];
int cnt = 0;
/* Don't do anything on EVM */
if( gio_id < 0 || gio_id > GIO_MAX_ID )
{
printf("gio id = %d over range!!\n", gio_id);
return -1;
}
if( gio_getname(dev_name,gio_id) < 0 )
{
printf("gio get name error!!\n");
return -1;
}
fd_gio = open(dev_name, O_RDWR);
if( !fd_gio )
{
printf("open device error !! gio = %d\n", gio_id);
goto GIO_QUIT;
}
if( IsOn == 1 )
{
for( cnt = 0 ; cnt < sizeof(data) ; cnt ++ )
{
data[cnt]='1';
}
}
else if( IsOn == 0 )
{
for( cnt = 0 ; cnt < sizeof(data) ; cnt ++ )
{
data[cnt]='0';
}
}else{
goto GIO_QUIT;
}
result = write(fd_gio, data, 1);
if( result <= 0 )
{
printf("write device error !! gio = %d\n", gio_id);
close(fd_gio);
goto GIO_QUIT;
}
GIO_QUIT:
if( fd_gio )
close(fd_gio);
return 0;
}
int gio_read( int gio_id )
{
int fd_gio = 0;
char data[5];
int result = 0;
char dev_name[25];
if( gio_id < 0 || gio_id > GIO_MAX_ID )
{
printf("gio id = %d over range!!\n", gio_id);
return -1;
}
if(gio_getname(dev_name,gio_id) < 0 )
{
printf("gio get name error!!\n");
return -1;
}
fd_gio = open(dev_name, O_RDWR);
if( !fd_gio )
{
printf("open device error !! gio = %d\n", gio_id);
return -1;
}
result = read(fd_gio,data,1);
if( result <= 0 )
{
printf("read device error !! gio = %d\n", gio_id);
close(fd_gio);
return -1;
}
close(fd_gio);
if( data[0] == '1')
{
return 1;
}else{
return 0;
}
return -1;
}
/********************** 驱动 *********************************/
/*
* TI DaVinci GPIO Support
*
* Copyright (c) 2006 David Brownell
* Copyright (c) 2007, MontaVista Software, Inc. <source@mvista.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <linux/kernel.h>
#include <asm/arch/irqs.h>
#include <asm/arch/hardware.h>
#include <asm/arch/cpu.h>
#include <asm/arch/gpio.h>
#include <linux/proc_fs.h>
/* If a new chip is added with number of GPIO greater than 128, please
update DAVINCI_MAX_N_GPIO in include/asm-arm/arch-davinci/irqs.h */
#define DM646x_N_GPIO 48
#define DM644x_N_GPIO 71
#define DM3xx_N_GPIO 104
#if defined(CONFIG_ARCH_DAVINCI644x) || defined(CONFIG_ARCH_DAVINCI_DM357)
static DECLARE_BITMAP(dm644x_gpio_in_use, DM644x_N_GPIO);
struct gpio_bank gpio_bank_dm6446 = {
.base = DAVINCI_GPIO_BASE,
.num_gpio = DM644x_N_GPIO,
.irq_num = IRQ_DM644X_GPIOBNK0,
.irq_mask = 0x1f,
.in_use = dm644x_gpio_in_use,
};
#endif
#ifdef CONFIG_ARCH_DAVINCI_DM355
static DECLARE_BITMAP(dm355_gpio_in_use, DM3xx_N_GPIO);
struct gpio_bank gpio_bank_dm355 = {
.base = DAVINCI_GPIO_BASE,
.num_gpio = DM3xx_N_GPIO,
.irq_num = IRQ_DM355_GPIOBNK0,
.irq_mask = 0x7f,
.in_use = dm355_gpio_in_use,
};
#endif
#ifdef CONFIG_ARCH_DAVINCI_DM365
static DECLARE_BITMAP(dm365_gpio_in_use, DM3xx_N_GPIO);
struct gpio_bank gpio_bank_dm365 = {
.base = DAVINCI_GPIO_BASE,
.num_gpio = DM3xx_N_GPIO,
.irq_num = 0,
.irq_mask = 0x7f,
.in_use = dm365_gpio_in_use,
};
#endif
#ifdef CONFIG_ARCH_DAVINCI_DM646x
static DECLARE_BITMAP(dm646x_gpio_in_use, DM646x_N_GPIO);
struct gpio_bank gpio_bank_dm646x = {
.base = DAVINCI_GPIO_BASE,
.num_gpio = DM646x_N_GPIO,
.irq_num = IRQ_DM646X_GPIOBNK0,
.irq_mask = 0x7,
.in_use = dm646x_gpio_in_use,
};
#endif
void davinci_gpio_init(void)
{
struct gpio_bank *gpio_bank;
#if defined(CONFIG_ARCH_DAVINCI644x) || defined(CONFIG_ARCH_DAVINCI_DM357)
if (cpu_is_davinci_dm644x() || cpu_is_davinci_dm357())
gpio_bank = &gpio_bank_dm6446;
#endif
#ifdef CONFIG_ARCH_DAVINCI_DM355
if (cpu_is_davinci_dm355())
gpio_bank = &gpio_bank_dm355;
#endif
#ifdef CONFIG_ARCH_DAVINCI_DM365
if (cpu_is_davinci_dm365())
gpio_bank = &gpio_bank_dm365;
#endif
#ifdef CONFIG_ARCH_DAVINCI_DM646x
if (cpu_is_davinci_dm6467())
gpio_bank = &gpio_bank_dm646x;
#endif
if (!gpio_bank)
BUG();
davinci_gpio_irq_setup(gpio_bank);
}
#if CONFIG_PROC_FS
#define MAX_BUF 4*1024
#define DM3xx_N_MUX 5
static struct proc_dir_entry *gio_procdir;
static struct proc_dir_entry *gio_proc[DM3xx_N_GPIO];
static struct proc_dir_entry *gio_proc_mux[DM3xx_N_MUX];
static int proc_gio(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
int len = 0;
char buffer[MAX_BUF];
volatile unsigned long *reg;
if (!count)
return 0;
reg = (unsigned long *)IO_ADDRESS(DAVINCI_GPIO_BASE);
len += sprintf(&buffer[len], "GPIO Module:\n");
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x PID \n", reg,
(int)reg[0]);
reg += 2;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x BINTEN \n", reg,
(int)reg[0]);
//BANK 0 AND BANK 1
len += sprintf(&buffer[len], "GPIO Bank0 and Bank1:\n");
reg = (unsigned long *)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x10);
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Direction \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Output Data \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Set Data \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Clear Data \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Input Data \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Set Rising edge \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Clear Rising edge \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Set Falling edge \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Clear Falling edge\n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Interrupt Status \n", reg,
(int)reg[0]);
//BANK 2 AND BANK 3
len += sprintf(&buffer[len], "GPIO Bank2 and Bank3:\n");
reg = (unsigned long *)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x38);
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Direction \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Output Data \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Set Data \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Clear Data \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Input Data \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Set Rising edge \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Clear Rising edge \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Set Falling edge \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Clear Falling edge\n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Interrupt Status \n", reg,
(int)reg[0]);
//BANK 4 AND BANK 5 for DM355 and BANK 4 for DM6446
if (cpu_is_davinci_dm355())
len += sprintf(&buffer[len], "GPIO Bank4 and Bank5:\n");
else
len += sprintf(&buffer[len], "GPIO Bank4:\n");
reg = (unsigned long *)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x60);
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Direction \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Output Data \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Set Data \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Clear Data \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Input Data \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Set Rising edge \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Clear Rising edge \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Set Falling edge \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Clear Falling edge\n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Interrupt Status \n", reg,
(int)reg[0]);
//BANK 6
if (cpu_is_davinci_dm355())
{
len += sprintf(&buffer[len], "GPIO Bank6:\n");
reg = (unsigned long *)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x88);
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Direction \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Output Data \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Set Data \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Clear Data \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Input Data \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Set Rising edge \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Clear Rising edge \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Set Falling edge \n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Clear Falling edge\n", reg,
(int)reg[0]);
reg++;
len +=
sprintf(&buffer[len], " 0x%p: 0x%08x Interrupt Status \n", reg,
(int)reg[0]);
}
if (count > len)
count = len;
memcpy(page, &buffer[off], count);
*eof = 1;
*start = NULL;
return len;
}
static int proc_gio_read(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
int len;
if (count == 0)
return 0;
gpio_direction_input((int)data);//gpio_set_direction((int)data, GIO_DIR_INPUT);
len = sprintf(page, "%d\n", gpio_get_value((int)data));
*eof = 1;
*start = 0;
return len;
}
static int proc_gio_write(struct file *file, const char __user * buffer,
unsigned long count, void *data)
{
int i;
if (!count)
return 0;
//gpio_set_direction((int)data, GIO_DIR_OUTPUT);
for (i = 0; i < count; i++) {
if (buffer[i] == '0')
{
gpio_direction_output((int)data,0);//gpio_set_value((int)data, 0);
}
if (buffer[i] == '1')
{
gpio_direction_output((int)data,1);//gpio_set_value((int)data, 1);
}
}
return count;
}
static int proc_mux_read(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
int len;
if (count == 0)
return 0;
len = sprintf(page, "0x%x\n", davinci_readl(PINMUX0+(u32)data));
*eof = 1;
*start = 0;
return len;
}
static int proc_mux_write(struct file *file, const char __user * buffer,
unsigned long count, void *data)
{
int i;
unsigned long val = 0;
if (!count)
return 0;
val = simple_strtoul(buffer, NULL, 0);
davinci_writel(val, PINMUX0+(u32)data);
return count;
}
int __init gio_proc_client_create(void)
{
int i;
char name[16];
struct proc_dir_entry *ent;
u32 max_gpio = 0;
/*if (cpu_is_davinci_dm355())
max_gpio = DM355_NUM_GIOS;
else if (cpu_is_davinci_dm6443())
max_gpio = DM644x_NUM_GIOS;
*/
max_gpio = DM3xx_N_GPIO;
gio_procdir = proc_mkdir("gio", 0);
if (gio_procdir == NULL) {
printk(KERN_ERR "gio: failed to register proc directory gio\n");
return -ENOMEM;
}
ent = create_proc_read_entry("registers", 0, gio_procdir, proc_gio, 0);
if (ent == NULL) {
printk(KERN_ERR
"gio: failed to register proc device: registers\n");
return -ENOMEM;
}
for (i = 0; i < max_gpio; i++) {
sprintf(name, "gio%d", i);
gio_proc[i] = create_proc_entry(name, 0, gio_procdir);
if (gio_proc[i] == NULL) {
printk(KERN_ERR
"gio: failed to register proc device: %s\n",
name);
return -ENOMEM;
}
gio_proc[i]->data = (void *)i;
gio_proc[i]->read_proc = proc_gio_read;
gio_proc[i]->write_proc = proc_gio_write;
}
for (i = 0; i < DM3xx_N_MUX; i++) {
sprintf(name, "pinmux%d", i);
gio_proc_mux[i] = create_proc_entry(name, 0, gio_procdir);
if (gio_proc_mux[i] == NULL) {
printk(KERN_ERR
"gio: failed to register proc device: %s\n",
name);
return -ENOMEM;
}
gio_proc_mux[i]->data = (void *)i;
gio_proc_mux[i]->read_proc = proc_mux_read;
gio_proc_mux[i]->write_proc = proc_mux_write;
}
return 0;
}
#else /* CONFIG_PROC_FS */
#define gio_proc_client_create() do {} while(0);
#endif /* CONFIG_PROC_FS */
module_init(gio_proc_client_create);
方法三:写个字符设备驱动,略
方法四:内存映射,略