Hello,
I have connected FPGA on GPMC interface using multiplexed IO mode. I have modifiled pin mux in u-boot as per attached mux_data.h file. Also I have done modification in gpmc_init function of u-boot as below:
#else
const u32 gpmc_regs[GPMC_MAX_REG] = { 0x1A00, //GPMC Config 1
M_NAND_GPMC_CONFIG2,
M_NAND_GPMC_CONFIG3,
M_NAND_GPMC_CONFIG4,
M_NAND_GPMC_CONFIG5,
M_NAND_GPMC_CONFIG6,
0
};
// u32 base = CONFIG_SYS_NAND_BASE;
u32 base = 0x18000000;
u32 size = GPMC_SIZE_16M;
#if 0
const u32 gpmc_regs[GPMC_MAX_REG] = { 0, 0, 0, 0, 0, 0, 0 };
u32 size = 0;
u32 base = 0;
#endif
#endif
Below is the device tree modification
&gpmc{
status = "okay";
};
After this much of modification I am trying to access FPGA registers, but I am not able to read any register. When I have probed GPMC signals I have found that there is no any transactions on signals. Even I can not see the clock also.
Here I have attached my fpga driver. Please note that I am using CS3 to access FPGA.
Could anyone please suggest me if I am missing anything?8171.mux_data.h
/* * copyright (c)2016 eInfochips - All rights reserved. * * This software is authored by eInfochips and is eInfochips' * intelletual property,including the copyrights in all countries in the world. * This software is provided under a license to use only with all other rights, * including ownership rights, being retained by eInfochips. * * This file may not be distributed, copied or reproduced in any manner, * electronic or otherwise, without the written consent of eInfochips. */ #include <linux/module.h> #include <linux/slab.h> /* for kmalloc() and kfree() */ #include <linux/major.h> #include <linux/types.h> #include <linux/errno.h> #include <linux/delay.h> #include <linux/fs.h> #include <linux/mm.h> #include <linux/init.h> #include <linux/device.h> #include <linux/sched.h> #include <linux/proc_fs.h> #include <linux/gpio.h> #include <linux/firmware.h> #include <linux/platform_device.h> #include <linux/uaccess.h> /* For put_user and get_user */ #include <linux/moduleparam.h> /* for module parameter */ #include <linux/omap-gpmc.h> #include <misc/zeiss_fpga.h> #if 0 #define ZEISS_FPGA_MAJOR (233) #define ZEISS_FPGA_MINOR (0) //#define FPGA_INITIAL_REG_SKIP (256) #define FPGA_INITIAL_REG_SKIP (0) #define REG_BIT(x) (0x1 << x) #define FPGA_IOC_MAGIC ('r') /* define all ioctls */ #define FPGA_IOC_MAXNR (28) #define FPGA_RW_CTRL _IOWR(FPGA_IOC_MAGIC, 1, fpga_ctrl_t) typedef enum _fpga_reg_t { VIC_FPGA_INFO = 0, FPGA_CONFIG_REG_COUNT=0x016F, } fpga_reg_t; typedef struct _fpga_ctrl_t { char rw; /* 0 = write else read */ unsigned char reg; unsigned short val; } fpga_ctrl_t; #endif static unsigned long fpga_base; static struct class *fw_class; static int fpga_device_open = 0; static void __iomem *base_reg; void __iomem *fpga_reg[FPGA_CONFIG_REG_COUNT]; EXPORT_SYMBOL(fpga_reg); int zeiss_fpga_fw_open (struct inode *inode,struct file *file) { if (fpga_device_open){ return -EBUSY; } fpga_device_open++; return 0; } int zeiss_fpga_fw_close (struct inode *inode,struct file *file) { fpga_device_open--; return 0; } static void zeiss_fpga_reg_write(unsigned short val, void __iomem *reg_addr) { __raw_writew(val, reg_addr); } static unsigned short zeiss_fpga_reg_read(void __iomem *reg_addr) { return(__raw_readw(reg_addr)); } long zeiss_fpga_fw_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int err = 0; fpga_ctrl_t fpga; if (_IOC_TYPE(cmd) != FPGA_IOC_MAGIC){ printk("error in ioctl magic no, FPGA_IOC_MAGIC should" " be \'%c\'\n", _IOC_TYPE(cmd)); return -EINVAL; } if (_IOC_NR(cmd) > FPGA_IOC_MAXNR){ printk("error in FPGA_IOC_MAXNR \n"); return -ENOTTY; } if (_IOC_DIR(cmd) & _IOC_READ) err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd)); else if (_IOC_DIR(cmd) & _IOC_WRITE) err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)); if (err){ printk("error in _IOC_READ or _IOC_WRITE \n"); return -EFAULT; } /* Get data from user space */ if (copy_from_user(&fpga, (fpga_ctrl_t *) arg, sizeof(fpga_ctrl_t))) { err = -EFAULT; return err; } if(cmd == FPGA_RW_CTRL) { if(true == fpga.rw) { fpga.val = zeiss_fpga_reg_read(fpga_reg[fpga.reg]); } else { zeiss_fpga_reg_write(fpga.val, fpga_reg[fpga.reg]); } /* Set data from user space */ if(copy_to_user((fpga_ctrl_t *)arg, &fpga, sizeof(fpga_ctrl_t))) err = -EFAULT; } else err = -EINVAL; return err; } static const struct file_operations zeiss_fpga_fops = { .owner = THIS_MODULE, .unlocked_ioctl = zeiss_fpga_fw_ioctl, .open = zeiss_fpga_fw_open, .release = zeiss_fpga_fw_close }; static int zeiss_fpga_gpmc_mem_map(void) { int count; /* Map FPGA registers into driver memory to access it later on */ /* Increment FPGA_CONFIG_REG_COUNT by 1 if you add configuration reg. */ for(count = 0; count < FPGA_CONFIG_REG_COUNT; count++) { fpga_reg[count] = ioremap((fpga_base + FPGA_INITIAL_REG_SKIP + count*2), 0x2); } return 0; } static int zeiss_fpga_gpmc_mem_unmap(void) { int count; /* Un-mapped FPGA registers */ for(count = 0; count < FPGA_CONFIG_REG_COUNT; count++) iounmap((void *)fpga_reg[count]); return 0; } static int zeiss_fpga_gpmc_init(void) { int err; err = gpmc_cs_request(3, SZ_16M - 1,(unsigned long*)&fpga_base); printk("\n$$$$$$$$$ fpga_base = %x $$$$$$$$$$\n", fpga_base); return err; } static void zeiss_fpga_gpmc_clean(void) { gpmc_cs_free(1); } static int __init zeiss_fpga_init(void) { int err = 0; printk("\n$$$$$$$$$ zeiss_fpga_init $$$$$$$$$$\n"); /* Register the driver */ if(register_chrdev(ZEISS_FPGA_MAJOR, "zeiss_fpga_fw", &zeiss_fpga_fops)) { printk("zeiss_fpga driver: Unable to register driver\n"); return (-ENODEV); } /* Create device class */ fw_class = class_create(THIS_MODULE, "zeiss_fpga_fw"); if (IS_ERR(fw_class)) { err = PTR_ERR(fw_class); goto out_chrdev; } /* Initilize GPMCMap FPGA configuration register memory to GPMC CS1 memory */ if(zeiss_fpga_gpmc_init() < 0) { printk("zeiss_fpga driver: unable to initialize gpmc\n"); err = -1; } /* Map FPGA configuration register memory to GPMC CS1 progrramed memory */ zeiss_fpga_gpmc_mem_map(); /* Create the device entry of the driver */ device_create(fw_class, NULL, MKDEV(ZEISS_FPGA_MAJOR, ZEISS_FPGA_MINOR), NULL, "zeiss_fpga_fw"); return err; out_chrdev: /* Unregister the driver */ unregister_chrdev(ZEISS_FPGA_MAJOR, "zeiss_fpga_fw"); return err; } static void __exit zeiss_fpga_exit(void) { /* Remove the device entry of the driver */ device_destroy(fw_class, MKDEV(ZEISS_FPGA_MAJOR, ZEISS_FPGA_MINOR)); class_destroy(fw_class); zeiss_fpga_gpmc_mem_unmap(); zeiss_fpga_gpmc_clean(); /* Unregister the driver */ unregister_chrdev(ZEISS_FPGA_MAJOR, "zeiss_fpga_fw"); } module_init(zeiss_fpga_init); module_exit(zeiss_fpga_exit); MODULE_AUTHOR("eInfochips"); MODULE_DESCRIPTION("FPGA register access driver"); MODULE_LICENSE("GPL");