最近在写一个am3354和FPGA通信的Linux驱动, FPGA是16位,异步,不复用引脚设备,使用的片选2,下面是我的驱动程序,无法实现两者的数据传输,跪求指教!
#include <linux/kernel.h> #include <linux/platform_device.h> #include <linux/gpio.h> #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/delay.h> #include <plat/board.h> #include <plat/gpmc.h> #include <plat/gpmc-smc91x.h> #include <asm/uaccess.h> #include <linux/dma-mapping.h> #include <linux/string.h>
static int major ; static struct class *gpmc_fpga_cls; static struct device *gpmc_fpga_dev; static char __iomem *fpga_access_base; dma_addr_t fpga_phy_base;
#define GPCM_FPGA_CS 2 //FPGA选择通道3 #define FPGA_ACCESS_SIZE SZ_16M//FPGA通道的大小
static struct gpmc_timings fpga_default_timings = {
.sync_clk = 0,
.cs_on = 0, .cs_rd_off = 89, .cs_wr_off = 57,
.adv_on = 3, .adv_rd_off = 9, .adv_wr_off = 9,
.we_on = 3, .we_off = 48, .oe_off = 89,
.access = 80, .rd_cycle = 96, .wr_cycle = 57,
}; static void gpmc_write_reg(int idx, u32 val) { writel(val, gpmc->io_base + idx); }
static u32 gpmc_read_reg(int idx) { return readl(gpmc->io_base + idx); }
static int gpmc_fpga_open(struct inode * inode, struct file * file) { unsigned long val;
/*申请GPMC通道*/ if(gpmc_cs_request(GPCM_FPGA_CS,FPGA_ACCESS_SIZE,&fpga_phy_base) < 0) { printk("fail to gpmc_cs_request!\n"); return -1; }
if (!request_mem_region(fpga_phy_base, FPGA_ACCESS_SIZE, "gpmc_fpga_mem")) { printk("fail to request_mem_region\n"); return -EBUSY; } else printk("fpga_phy_base = 0x%0x\n",fpga_phy_base); fpga_access_base = ioremap(fpga_phy_base,FPGA_ACCESS_SIZE); if(fpga_access_base == NULL) { printk("fail to ioremap!\n"); return -ENOMEM; } gpmc_write_reg(GPMC_IRQENABLE, 0); gpmc_write_reg(GPMC_TIMEOUT_CONTROL, 0); /*3,利用内核提供的函数设置时序*/ gpmc_cs_set_timings(GPCM_FPGA_CS,&fpga_default_timings); return 0; } static ssize_t gpmc_fpga_read(struct file *flle, char __user *ubuf, size_t count, loff_t *ppos) { int ret = 0; unsigned int temp;
temp = readl(fpga_access_base + 0x31); if(copy_to_user(ubuf,&temp ,count)) { ret = -EINVAL; }
return ret; }
static ssize_t gpmc_fpga_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { int ret = 0; unsigned int temp;
if(copy_from_user(&temp ,ubuf ,count)) ret = -EINVAL; else { writel(temp,fpga_access_base + 0x31); *ppos += count; ret = count; }
return ret; }
static struct file_operations gpmc_fpga_fops = { .open = gpmc_fpga_open, .read = gpmc_fpga_read, .write = gpmc_fpga_write, .owner = THIS_MODULE, };
static int gpmc_fpga_init(void) { int val; printk("gpmc_fpga_init\n"); major = register_chrdev(0, "gpmc_fpga", &gpmc_fpga_fops); gpmc_fpga_cls = class_create(THIS_MODULE, "gpmc_fpga"); gpmc_fpga_dev = device_create(gpmc_fpga_cls, NULL, MKDEV(major, 0), NULL, "gpmc_fpga_dev"); /* /dev/buttons */
return 0; }
static void gpmc_fpga_exit(void) { iounmap(fpga_access_base); gpmc_cs_free(GPCM_FPGA_CS); device_destroy(gpmc_fpga_cls,MKDEV(major, 0)); class_destroy(gpmc_fpga_cls); unregister_chrdev(major,"gpmc_fpga"); return ; }
module_init(gpmc_fpga_init); module_exit(gpmc_fpga_exit); MODULE_LICENSE("GPL");
Eason Wang:
Move to sitara forum
Jian Zhou:
回复 Eason Wang:
板级驱动文件夹下,要给FPGA分配访问空间,要在GPMC的驱动文件中修改,不知道您是怎么修改的?