|
发表于 2013-6-6 11:16:50
|
显示全部楼层
本帖最后由 freechinaren 于 2013-6-6 11:21 编辑
本人参考sun4i-gpio写了一个控制LED驱动的程序,但是加载编译好的驱动后,系统会重启。
本人用的GPIO的是PE4,PE5,PE6,PE7配置成输出口,控制四个LED灯,PE8,PE9,PE10,PE11 配置成输入口,控制四个按键,
下面为本人写的驱动代码,请大虾指点,不胜感激!!!
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <asm/uaccess.h>
#include <linux/pm.h>
#include <linux/sysdev.h>
#include <linux/slab.h>
#include <linux/earlysuspend.h>
#include <linux/device.h>
// 定义设备文件名
#define DEVICE_NAME "cbio"
#define SW_PA_PORTC_IO_BASE 0x01c20800
/*
*
* GPIO(PIN) Operations
*
*/
//#define CSP_OSAL_PHY_2_VIRT(phys, size) SW_VA_PORTC_IO_BASE
//#define CSP_PIN_PHY_ADDR_BASE SW_PA_PORTC_IO_BASE
//#define CSP_PIN_PHY_ADDR_SIZE 0x1000
//u32 gpio_g_pioMemBase;//=SW_PA_PORTC_IO_BASE ;
#define PIOC_REGS_BASE SW_PA_PORTC_IO_BASE
//extern char sys_cofig_data[];
//extern char sys_cofig_data_end[];
#define __REG(x) (*(volatile unsigned int *)(x))
#define PIO_REG_CFG(n, i) ((volatile unsigned int *)(PIOC_REGS_BASE + ((n)-1)*0x24 + ((i)<<2) + 0x00))
#define PIO_REG_DLEVEL(n, i) ((volatile unsigned int *)(PIOC_REGS_BASE + ((n)-1)*0x24 + ((i)<<2) + 0x14))
#define PIO_REG_PULL(n, i) ((volatile unsigned int *)(PIOC_REGS_BASE + ((n)-1)*0x24 + ((i)<<2) + 0x1C))
#define PIO_REG_DATA(n) ((volatile unsigned int *)(PIOC_REGS_BASE + ((n)-1)*0x24 + 0x10))
#define PIO_REG_CFG_VALUE(n, i) __REG(PIOC_REGS_BASE + ((n)-1)*0x24 + ((i)<<2) + 0x00)
#define PIO_REG_DLEVEL_VALUE(n, i) __REG(PIOC_REGS_BASE + ((n)-1)*0x24 + ((i)<<2) + 0x14)
#define PIO_REG_PULL_VALUE(n, i) __REG(PIOC_REGS_BASE + ((n)-1)*0x24 + ((i)<<2) + 0x1C)
#define PIO_REG_DATA_VALUE(n) __REG(PIOC_REGS_BASE + ((n)-1)*0x24 + 0x10)
//end
//static unsigned int led_key_status; // 保存4个Leds的设置状态(d4-d7)和保存4个Buttons的状态(d8-d11)
static unsigned char mem[1]; //
static ssize_t cbio_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
// unsigned char temp[4];
unsigned char temp=0;
//读PE DATA Register
unsigned int led_key_status=PIO_REG_DATA_VALUE(4);
//read led status
temp =(led_key_status>>4)&0x01;//led0
temp|=((led_key_status>>5)&0x01)<<1;//led1
temp|=((led_key_status>>6)&0x01)<<2;//led2
temp|=((led_key_status>>7)&0x01)<<3;//led3
//read key status
temp|=((led_key_status>>8)&0x01)<<4; //key0
temp|=((led_key_status>>9)&0x01)<<5; //key1
temp|=((led_key_status>>10)&0x01)<<6;//key2
temp|=((led_key_status>>11)&0x01)<<7;//key3
//temp[0] = led_key_status >> 24;
//temp[1] = led_key_status >> 16;
//temp[2] = led_key_status >> 8;
//temp[3] = led_key_status;
if (copy_to_user(buf, (void*) &temp, 1))
{
return -EINVAL;
}
printk("read:status of cbio:%d", (int) count);
return count;
}
static ssize_t cbio_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
ssize_t written = count;
unsigned int tmp;
unsigned char c;
volatile __u32 *tmp_addr;
if(written!=1)
{
printk("write:data len invalid\n");
return -EINVAL;
}
if (copy_from_user(mem, buf, count))
{
return -EINVAL;
}
//mem[count] = '\0';
//目前只设置低四位为灯得状态
tmp=PIO_REG_DATA_VALUE(4);
//设置灯的状态
c=mem[0];
//led0->pin34
if(c&0x01)//led0
tmp|=0x10;
else
tmp&=0xffffffef;
//led1->pin36
if(c&0x01)//led1
tmp|=0x20;
else
tmp&=0xffffffdf;
//led2->pin38
if(c&0x01)//led2
tmp|=0x40;
else
tmp&=0xffffffbf;
//led3->pin40
if(c&0x01)//led3
tmp|=0x80;
else
tmp&=0xffffff7f;
//tmp|=0xf0;//LED灯全亮或全熄灭
tmp_addr=PIO_REG_DATA(4);
*tmp_addr=tmp;
printk("write:status word count:%d\n", (int)count);
return written;
}
// 描述与设备文件触发的事件对应的回调函数指针
static struct file_operations dev_fops =
{ .owner = THIS_MODULE, .read = cbio_read, .write = cbio_write };
// 描述设备文件的信息
static struct miscdevice misc =
{ .minor = MISC_DYNAMIC_MINOR, .name = DEVICE_NAME, .fops = &dev_fops };
// 初始化Linux驱动
static int __init cbio_init(void)
{
int ret;
volatile __u32 *tmp_addr;
unsigned int tmp;
// 建立设备文件
ret = misc_register(&misc);
//printk(KERN_INFO "Init eGon pin module V2.0\n");
//gpio_g_pioMemBase = (u32)CSP_OSAL_PHY_2_VIRT(CSP_PIN_PHY_ADDR_BASE , CSP_PIN_PHY_ADDR_SIZE);
//初始化配置寄存器
//使用PE_CFG0(offset:0x90)
//LED0-LED3:输出pin
//save the PE_CFG0 register's value
//debug
tmp=ioread32(PIOC_REGS_BASE + ((4)-1)*0x24 + ((0)<<2) + 0x00));
printk("Get PE CFG0:%d\n",tmp);
//end
tmp=PIO_REG_CFG_VALUE(4,0);
printk("Get PE CFG0:%d\n",tmp);
//modify PE4(18:16) :001
//modify PE5(22:20) :001
//modify PE6(26:24) :001
//modify PE7(30:28) :001
tmp&=0x9999ffff;
tmp|=0x11110000;
//使用修改后的配置cfg0
tmp_addr=PIO_REG_CFG(4,0);
*tmp_addr=tmp;
//KEY0-KEY3:输入pin
//使用PE_CFG1(offset:0X94)
tmp=PIO_REG_CFG_VALUE(4,1);
printk("Get PE CFG1:%d\n",tmp);
//modify PE8(2:0) :000
//tmp&=0xfffffff8;
//modify PE9(6:4) :000
//tmp&=0xffffff8f;
//modify PE10(10:8) :000
//tmp&=0xfffff8ff;
//modify PE11(14:12) :000
//tmp&=0xffff8fff;
tmp&=0xffff8888;
//使用修改后的配置cfg1
tmp_addr=PIO_REG_CFG(4,1);
*tmp_addr=tmp;
//set led default value
tmp=PIO_REG_DATA_VALUE(4);
tmp|=0xf0;//LED灯全亮或全熄灭
tmp_addr=PIO_REG_DATA(4);
*tmp_addr=tmp;
// 输出日志信息
printk("cbio_init_success\n");
return ret;
}
// 卸载Linux驱动
static void __exit cbio_exit(void)
{
// 删除设备文件
misc_deregister(&misc);
// 输出日志信息
printk("cbio_init_exit_success\n");
}
// 注册初始化Linux驱动的函数
module_init( cbio_init);
// 注册卸载Linux驱动的函数
module_exit( cbio_exit);
MODULE_DESCRIPTION("gpio of cubieboard.");
MODULE_ALIAS("led and button module.");
MODULE_LICENSE("GPL"); |
|