#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/ioport.h>
#include <linux/device.h>
#include <linux/ioctl.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <plat/gpmc.h>
MODULE_AUTHOR("<xxx@xxx.com>");
MODULE_DESCRIPTION("fpga Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION("0.1");
//#define debug
/* GPMC register offsets */
#define GPMC_REVISION 0x00
#define GPMC_SYSCONFIG 0x10
#define GPMC_SYSSTATUS 0x14
#define GPMC_IRQSTATUS 0x18
#define GPMC_IRQENABLE 0x1C
#define GPMC_TIMEOUT_CONTROL 0x40
#define GPMC_NAND_COMMAND_1 0xAC
#define GPMC_NAND_ADDRESS_1 0xB0
#define GPMC_NAND_DATA_1 0xB4
#define GPMC_ERR_ADDRESS 0x44
#define GPMC_ERR_TYPE 0x48
#define GPMC_CONFIG 0x50
#define GPMC_STATUS 0x54
#define GPMC_PREFETCH_CONFIG1 0x1E0
#define GPMC_PREFETCH_CONFIG2 0x1E4
#define GPMC_PREFETCH_CONTROL 0x1Ec
#define GPMC_PREFETCH_STATUS 0x1F0
#define GPMC_ECC_CONFIG 0x1F4
#define GPMC_ECC_CONTROL 0x1F8
#define GPMC_ECC_SIZE_CONFIG 0x1FC
#define GPMC_ECC1_RESULT 0x200
#define GPMC_ECC_BCH_RESULT_0 0x240
#define CONTROL_BASE 0x44E10000
#define GPMC_BASE_ADDR 0x50000000
#define GPMC_CS 0x01
#define GPMC_CS0 0x60
#define GPMC_CS_SIZE 0x30
#define GPMC_COMMAND_WRITE 0x80
#define GPMC_COMMAND_READ 0x30
#define NAND_GPMC_CONFIG1 0x00000800
#define NAND_GPMC_CONFIG2 0x00101200 //20-16:CSWROFFTIME,12-8:CSRDOFFTIME,3-0:CSONTIME
#define NAND_GPMC_CONFIG3 0x00141400
#define NAND_GPMC_CONFIG4 0x0F010F01 //28-24:WEOFFTIME,19-16:WEONTIME,12-8:OEOFFTIME,3-0:OEONTIME
#define NAND_GPMC_CONFIG5 0x010C1414 //20-16:RDACCESSTIME means Delay between start cycle time and first data valid 12-8:WRCYCLETIME,4-0:RDCYCLETIME
#define NAND_GPMC_CONFIG6 0x1F0F0A80 //28-24:WRACCESSTIME
#define NAND_GPMC_CONFIG7 0x00000F1F //28-24:WRACCESSTIME
static const u32 gpmc_nand[8] = {
NAND_GPMC_CONFIG1,
NAND_GPMC_CONFIG2,
NAND_GPMC_CONFIG3,
NAND_GPMC_CONFIG4,
NAND_GPMC_CONFIG5,
NAND_GPMC_CONFIG6,
NAND_GPMC_CONFIG7,
0
};
static void __iomem *gpmc_base;
static void __iomem *fpga_base;
static void __iomem *control_base;
unsigned long mem_base;
struct semaphore sem;
#define USER_BUFF_SIZE 2047
static void register_configuration(void)
{
control_base = ioremap(CONTROL_BASE,0x89C);
iowrite32(0x30,(control_base+0x800)); //configure ad0
iowrite32(0x30,(control_base+0x804)); //configure ad1
iowrite32(0x30,(control_base+0x808)); //configure ad2
iowrite32(0x30,(control_base+0x80C)); //configure ad3
iowrite32(0x30,(control_base+0x810)); //configure ad4
iowrite32(0x30,(control_base+0x814)); //configure ad5
iowrite32(0x30,(control_base+0x818)); //configure ad6
iowrite32(0x30,(control_base+0x81C)); //configure ad7
iowrite32(0x08,(control_base+0x870)); //configure wait0
iowrite32(0x08,(control_base+0x874)); //configure wpn
iowrite32(0x08,(control_base+0x880)); //configure csn1
iowrite32(0x08,(control_base+0x890)); //configure advn ale
iowrite32(0x08,(control_base+0x894)); //configure oen ren
iowrite32(0x08,(control_base+0x898)); //configure we
iowrite32(0x08,(control_base+0x89C)); //configure ben0 cle
}
static void gpmc_write_cs_reg(int cs, int idx, u32 val)
{
void __iomem *reg_addr;
reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
iowrite32(val,reg_addr);
}
u32 gpmc_read_cs_reg(int cs, int idx)
{
void __iomem *reg_addr;
reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx;
return ioread32(reg_addr);
}
#ifdef debug
static void show_gpmc_reg(int cs)
{
u32 val;
int i=0;
for(i=0; i<7; i++)
{
val = gpmc_read_cs_reg(cs, GPMC_CS_CONFIG1 + i*4);
printk(KERN_INFO"gpmc cs%d GPMC_CS_CONFIG%d reg: 0x%08x\n",cs, i+1, val);
}
}
#endif
static void gpmc_write_reg(int idx, u8 val)
{
iowrite8(val, gpmc_base + idx);
}
static u8 gpmc_read_reg(int idx)
{
return ioread8(gpmc_base + idx);
}
static void gpmc_write_data(int idx, u8 val)
{
iowrite8(val, gpmc_base + idx);
}
static u8 gpmc_read_data(int idx)
{
return ioread8(gpmc_base + idx);
}
static void gpmc_write_address(int idx, u16 val)
{
iowrite16(val, gpmc_base + idx);
}
static void gpmc_write_command(int idx, u32 val)
{
iowrite8(val, gpmc_base + idx);
}
static int gpmc_setup(void)
{
u32 val;
register_configuration();
sema_init(&sem,1);
gpmc_base = ioremap(GPMC_BASE_ADDR,SZ_4K);
printk("Getting Chip Select\n");
val = gpmc_read_reg(GPMC_REVISION);
printk("GPMC revision %d.%d\n", (val >> 4) & 0x0f, val & 0x0f);
gpmc_write_reg(GPMC_IRQENABLE, 0);
gpmc_write_reg(GPMC_TIMEOUT_CONTROL, 0);
gpmc_write_cs_reg(GPMC_CS, GPMC_CS_CONFIG1, gpmc_nand[0]);
gpmc_write_cs_reg(GPMC_CS, GPMC_CS_CONFIG2, gpmc_nand[1]);
gpmc_write_cs_reg(GPMC_CS, GPMC_CS_CONFIG3, gpmc_nand[2]);
gpmc_write_cs_reg(GPMC_CS, GPMC_CS_CONFIG4, gpmc_nand[3]);
gpmc_write_cs_reg(GPMC_CS, GPMC_CS_CONFIG5, gpmc_nand[4]);
gpmc_write_cs_reg(GPMC_CS, GPMC_CS_CONFIG6, gpmc_nand[5]);
// gpmc_write_cs_reg(GPMC_CS, GPMC_CS_CONFIG7, gpmc_nand[6]);
#ifdef debug
show_gpmc_reg(GPMC_CS);
#endif
if (gpmc_cs_request(GPMC_CS, SZ_4K, (unsigned long *)&mem_base) < 0)
{
printk(KERN_ERR "Failed request for GPMC mem for usrp_e\n");
return -1;
}
#ifdef debug
printk("Got CS1, address = %lx\n", mem_base);
#endif
if (!request_mem_region(mem_base, SZ_4K, "mem_fpga"))
{
printk(KERN_ERR "Request_mem_region failed.\n");
gpmc_cs_free(GPMC_CS);
return -1;
}
fpga_base = ioremap(mem_base, SZ_4K);
return 1;
}
static void fpga_relash(void)
{
release_mem_region(mem_base,SZ_4K);
gpmc_cs_free(GPMC_CS);
iounmap(fpga_base);
}
static long fpga_ioctl(struct file *filp,unsigned int cmd,unsigned long arg)
{
if(down_interruptible(&sem))
return -ERESTARTSYS;
up(&sem);
return 1;
}
static ssize_t fpga_write(struct file *filp,const char __user *buff,size_t count,loff_t *f_pos)
{
ssize_t status;
ssize_t len = USER_BUFF_SIZE - 1;
unsigned char data_usr[USER_BUFF_SIZE];
int i;
if(count==0)
return 0;
if(down_interruptible(&sem))
return -ERESTARTSYS;
if(len > count)
len = count;
#ifdef debug
for (i = 0; i < len; i++) {
printk("[0x%x] ",buff[i]);
}
printk("\n");
#endif
memset(data_usr,0,USER_BUFF_SIZE);
if(copy_from_user(data_usr,buff,len))
{
status=-EFAULT;
goto fpga_write_done;
}
#ifdef debug
printk("the count is %d the len is %d\n",count,len);
printk("fpga_write start\n");
#endif
for(i = 0; i < len - 2; i++)
{
gpmc_write_command(GPMC_NAND_COMMAND_1, GPMC_COMMAND_WRITE);
gpmc_write_address(GPMC_NAND_ADDRESS_1, (data_usr[0] | (data_usr[1] << 8))+i);
gpmc_write_data(GPMC_NAND_DATA_1, data_usr[2+i]);
}
#ifdef debug
for (i = 0; i < len; i++) {
printk("[0x%x] ",data_usr[i]);
}
printk("\n");
#endif
fpga_write_done:
up(&sem);
#ifdef debug
printk("write finished\n");
#endif
status = len;
return status;
}
static ssize_t fpga_read(struct file *filp,char __user *buff,size_t count,loff_t *offp)
{
ssize_t status;
ssize_t len = USER_BUFF_SIZE - 1;
unsigned char data_usr[USER_BUFF_SIZE];
int address;
int i;
if(down_interruptible(&sem))
return -ERESTARTSYS;
if(len > count)
len = count;
#ifdef debug
for (i = 0; i < len; i++) {
printk("buff[%d]:[0x%x]\n",i,buff[i]);
}
#endif
memset(data_usr,0,USER_BUFF_SIZE);
address = buff[0]|(buff[1]<<8);
for(i = 0; i < len; i++)
{
gpmc_write_command(GPMC_NAND_COMMAND_1, GPMC_COMMAND_READ);
gpmc_write_address(GPMC_NAND_ADDRESS_1, address+i);
data_usr[i] = gpmc_read_data(GPMC_NAND_DATA_1)
am3352_gpmc_fpga_nand flash
5星 · 超过95%的资源 需积分: 50 32 浏览量
2017-02-23
14:50:56
上传
评论 4
收藏 4KB GZ 举报
zhenonline1
- 粉丝: 3
- 资源: 3
最新资源
- Three.js介绍.zip
- Android14 CTS Verifier测试手册.pdf
- NC65 UAP65 流程开发 – 业务流 – 推单 详细笔记
- 两种计算CDF累加分布函数的Matlab程序,可以选择使用 .rar
- Windows操作系统介绍.zip
- 汉森的广义t分布的matlab程序(金融)cdf.zip
- Three.js介绍.zip0002
- 人工智能BBSO算法,MATLAB实现,很基本的人工智能算法,里面有很多源程序
- 高端大气科技互联网项目融资商业计划书产品公司品牌介绍PPT模板.pptx
- Sora AI文字生成视频实操教程、由给定的图片生成视频的教程说明书,祝你一臂之力 轻松上手Sora
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈