http://blog.csdn.net/xiangpingli/article/details/7251734
1、GPIO口的对比:
3520:
应用:16路CIF,4路、8路D1
管脚总数:768pin
GPIO: 8组,GPIO0~GPIO7
GPIO基地址:从NAND、NOR、DDR映射GPIOX寄存器地址都是一样的:
3531:
应用:
单片:16D1+16CIF编码+4D1解码,8路D1同编同解,4路高清同编同解
双片(+3532):16路D1同编同解,8路720P同编同解,4路1080P实时解码
管脚总数:817pin
GPIO:19组,GPIO0~GPIO18
3520与3531GPIO对比总结:
1、3531有19组GPIO,3520有8组GPIO,两者GPIO0~7的地址是相同的。
2、各寄存器偏移地址不变
3520gpio驱动中针对3531修改:
1、首先把多出的寄存器组添加上,多了11组寄存器。
2、然后因为内核的接口变化了,修改ioctl相关的部分,记得unlocked_ioctl参数比原来的参数少了一个inode。
3、创建和初始化信号量的地方也要修改掉,DECLARE_MUTEX在linux3.0中也不存在了,取而代之的是DEFINE_SEMAPHORE
4、就是地址映射部分,哪里映射失败,要把之前映射的全部释放掉再退出:
hi_gpio.c:
#include <linux/module.h>
//#include <asm/hardware.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/fcntl.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/proc_fs.h>
#include <linux/workqueue.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/io.h>
#include "hi_gpio.h"
#define GPIO_0_BASE_ADDR 0x20150000
#define GPIO_1_BASE_ADDR 0x20160000
#define GPIO_2_BASE_ADDR 0x20170000
#define GPIO_3_BASE_ADDR 0x20180000
#define GPIO_4_BASE_ADDR 0x20190000
#define GPIO_5_BASE_ADDR 0x201a0000
#define GPIO_6_BASE_ADDR 0x201b0000
#define GPIO_7_BASE_ADDR 0x201c0000
#define GPIO_8_BASE_ADDR 0x201d0000
/* changed for 3531 */
#define GPIO_9_BASE_ADDR 0x201e0000
#define GPIO_10_BASE_ADDR 0x201f0000
#define GPIO_11_BASE_ADDR 0x20200000
#define GPIO_12_BASE_ADDR 0x20210000
#define GPIO_13_BASE_ADDR 0x20220000
#define GPIO_14_BASE_ADDR 0x20230000
#define GPIO_15_BASE_ADDR 0x20240000
#define GPIO_16_BASE_ADDR 0x20250000
#define GPIO_17_BASE_ADDR 0x20260000
#define GPIO_18_BASE_ADDR 0x20270000
#define GPIO_DIR_BASE (groupbase+0x400)
#define GPIO_INTR_MASK (groupbase+0x410)
#define GPIO_DATA_BASE data_reg_base
#define WRITE_REG(Addr, Value) ((*(volatile unsigned int *)(Addr)) = (Value))
#define READ_REG(Addr) (*(volatile unsigned int *)(Addr))
static DEFINE_SEMAPHORE(gpio_sem); /* 根据linux3.0.y 的源码,DEFINE_SEMAPHORE取代了DECLARE_MUTEX */
//static DECLARE_MUTEX(gpio_sem);
unsigned int groupbase=-1;
unsigned int data_reg_base=0;
unsigned int gpio_0_base_addr_virtual=0;
unsigned int gpio_1_base_addr_virtual=0;
unsigned int gpio_2_base_addr_virtual=0;
unsigned int gpio_3_base_addr_virtual=0;
unsigned int gpio_4_base_addr_virtual=0;
unsigned int gpio_5_base_addr_virtual=0;
unsigned int gpio_6_base_addr_virtual=0;
unsigned int gpio_7_base_addr_virtual=0;
unsigned int gpio_8_base_addr_virtual=0;
unsigned int gpio_9_base_addr_virtual=0;
unsigned int gpio_10_base_addr_virtual=0;
unsigned int gpio_11_base_addr_virtual=0;
unsigned int gpio_12_base_addr_virtual=0;
unsigned int gpio_13_base_addr_virtual=0;
unsigned int gpio_14_base_addr_virtual=0;
unsigned int gpio_15_base_addr_virtual=0;
unsigned int gpio_16_base_addr_virtual=0;
unsigned int gpio_17_base_addr_virtual=0;
unsigned int gpio_18_base_addr_virtual=0;
static void gpio_calculate_data_groupbase(unsigned int groupnum, unsigned int bitnum)
{
switch(groupnum)
{
case 0:
groupbase =gpio_0_base_addr_virtual;
break;
case 1:
groupbase =gpio_1_base_addr_virtual;
break;
case 2:
groupbase =gpio_2_base_addr_virtual;
break;
case 3:
groupbase =gpio_3_base_addr_virtual;
break;
case 4:
groupbase =gpio_4_base_addr_virtual;
break;
case 5:
groupbase =gpio_5_base_addr_virtual;
break;
case 6:
groupbase =gpio_6_base_addr_virtual;
break;
case 7:
groupbase =gpio_7_base_addr_virtual;
break;
case 8:
groupbase =gpio_8_base_addr_virtual;
break;
case 9:
groupbase =gpio_9_base_addr_virtual;
break;
case 10:
groupbase =gpio_10_base_addr_virtual;
break;
case 11:
groupbase =gpio_11_base_addr_virtual;
break;
case 12:
groupbase =gpio_12_base_addr_virtual;
break;
case 13:
groupbase =gpio_13_base_addr_virtual;
break;
case 14:
groupbase =gpio_14_base_addr_virtual;
break;
case 15:
groupbase =gpio_15_base_addr_virtual;
break;
case 16:
groupbase =gpio_16_base_addr_virtual;
break;
case 17:
groupbase =gpio_17_base_addr_virtual;
break;
case 18:
groupbase =gpio_18_base_addr_virtual;
break;
default:
break;
}
// printk("groupbase:%x !\n",groupbase);
data_reg_base=groupbase+(1<<(bitnum+2));
// printk("data_reg_base:%x !\n",data_reg_base);
}
static int gpio_open(struct inode *inode, struct file *filp)
{
return 0;
}
static int gpio_release(struct inode *inode, struct file *filp)
{
return 0;
}
//static int gpio_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
static int gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
//这里代码没改
return 0;
}
static struct file_operations gpio_fops = {
owner:THIS_MODULE,
open:gpio_open,
// ioctl:gpio_ioctl,
unlocked_ioctl:gpio_ioctl, /* linux3.0.y 不再使用ioctl,采用unlocked_ioctl */
release:gpio_release,
};
static struct miscdevice gpio_dev = {
MISC_DYNAMIC_MINOR,
"hi_gpio",
&gpio_fops,
};
//gpio的复用关系要放在uboot下面;
static int __init hi_gpio_init(void)
{
signed int ret=0;
ret = misc_register(&gpio_dev);
if (ret)
{
printk(KERN_ERR "register misc dev for hi_gpio fail!\n");
return ret;
}
gpio_0_base_addr_virtual=(unsigned int)ioremap_nocache(GPIO_0_BASE_ADDR,0x40000);
if(!gpio_0_base_addr_virtual)
{
printk("ioremap gpio group0 failed!\n");
return -1;
}
gpio_1_base_addr_virtual=gpio_0_base_addr_virtual+0x10000;
gpio_2_base_addr_virtual=gpio_0_base_addr_virtual+0x20000;
gpio_3_base_addr_virtual=gpio_0_base_addr_virtual+0x30000;
gpio_4_base_addr_virtual=(unsigned int) ioremap_nocache(GPIO_4_BASE_ADDR,0x40000);
if(!gpio_4_base_addr_virtual)
{
printk("ioremap gpio group0 failed!\n");
/*说明gpio_0 映射成功了,但gpio_4没成功,所以要把gpio_0的释放掉*/
iounmap((void*)gpio_0_base_addr_virtual);
return -1;
}
gpio_5_base_addr_virtual=gpio_4_base_addr_virtual+0x10000;
gpio_6_base_addr_virtual=gpio_4_base_addr_virtual+0x20000;
gpio_7_base_addr_virtual=gpio_4_base_addr_virtual+0x30000;
gpio_8_base_addr_virtual=(unsigned int) ioremap_nocache(GPIO_8_BASE_ADDR,0x40000);
if(!gpio_8_base_addr_virtual)
{
printk("ioremap gpio group0 failed!\n");
/*说明gpio_0 和gpio_4都映射成功了,但gpio_8没映射成功,所以将之前映射的释放*/
iounmap((void*)gpio_0_base_addr_virtual);
iounmap((void*)gpio_4_base_addr_virtual);
return -1;
}
gpio_9_base_addr_virtual = gpio_8_base_addr_virtual + 0x10000;
gpio_10_base_addr_virtual = gpio_8_base_addr_virtual + 0x20000;
gpio_11_base_addr_virtual = gpio_8_base_addr_virtual + 0x30000;
gpio_12_base_addr_virtual=(unsigned int) ioremap_nocache(GPIO_12_BASE_ADDR,0x40000);
if(!gpio_12_base_addr_virtual)
{
printk("ioremap gpio group0 failed!\n");
iounmap((void*)gpio_0_base_addr_virtual);
iounmap((void*)gpio_4_base_addr_virtual);
iounmap((void*)gpio_8_base_addr_virtual);
return -1;
}
gpio_13_base_addr_virtual = gpio_12_base_addr_virtual + 0x10000;
gpio_14_base_addr_virtual = gpio_12_base_addr_virtual + 0x20000;
gpio_15_base_addr_virtual = gpio_12_base_addr_virtual + 0x30000;
gpio_16_base_addr_virtual=(unsigned int) ioremap_nocache(GPIO_16_BASE_ADDR,0x30000); /* 注意:这里不能再是0x40000了*/
if(!gpio_16_base_addr_virtual)
{
printk("ioremap gpio group0 failed!\n");
iounmap((void*)gpio_0_base_addr_virtual);
iounmap((void*)gpio_4_base_addr_virtual);
iounmap((void*)gpio_8_base_addr_virtual);
iounmap((void*)gpio_12_base_addr_virtual);
return -1;
}
gpio_17_base_addr_virtual = gpio_16_base_addr_virtual + 0x10000;
gpio_18_base_addr_virtual = gpio_16_base_addr_virtual + 0x20000;
return 0;
}
static void __exit hi_gpio_exit(void)
{
misc_deregister(&gpio_dev);
iounmap((void*)gpio_0_base_addr_virtual);
iounmap((void*)gpio_4_base_addr_virtual);
iounmap((void*)gpio_8_base_addr_virtual);
iounmap((void*)gpio_12_base_addr_virtual);
iounmap((void*)gpio_16_base_addr_virtual);
}
module_init(hi_gpio_init);
module_exit(hi_gpio_exit);
MODULE_AUTHOR("Digital Media Team ,Hisilicon crop ");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Real Time Clock interface for HI3511");