/****************************************************************************** * This files declares the ioctl's that can be used to read/write EMIF Address * from the user application. * * Original Author: ******************************************************************************/ /* Include linux kernel header files */ #include #include #include #include #include #include #include #include #include #include #include #include //#include #include #include #include /* Include local header file */ #include "EMIF_Client.h" MODULE_LICENSE("GPL"); /* declare location variables */ static dev_t dev; static struct cdev *EMIF_cdev; /* declare local functions */ static int EMIF_open (struct inode *inode, struct file *filp); static int EMIF_release (struct inode *inode, struct file *filp); static int EMIF_ioctl (struct inode *inode, struct file *flip, unsigned int cmd, unsigned long args); static u32 EMIF_get_value(u8 addr); static int EMIF_set_value(u8 addr, u32 val); int EMIF_init_module(void); void EMIF_cleanup_module(void); /* declare file operation structure */ static struct file_operations EMIF_fops = { .owner = THIS_MODULE, .open = EMIF_open, .ioctl = EMIF_ioctl, .release = EMIF_release, }; struct nand_davinci_info { struct resource *reg_res; void __iomem *emifregs; unsigned ce; /* emif chip enable */ unsigned cle_mask; unsigned ale_mask; struct resource *data_res; void __iomem *ioaddr; struct clk *clk; }; #define EMIF_REG_SIZE 0x1000 #define DEVICESTART 0x00 /****************************************************************************** * EMIF_get_value - This function returns the value of EMIF Address. *****************************************************************************/ static u32 EMIF_get_value (u8 addr) { int status; struct nand_davinci_info *info; u32 val; val=__raw_readl(info->emifregs + addr); return val; } /****************************************************************************** * EMIF_set_value - This function sets the value to the EMIF Address. *****************************************************************************/ static int EMIF_set_value (u8 addr, u32 val) { int status; struct nand_davinci_info *info; __raw_writel(val, info->emifregs + addr); return 0; } /****************************************************************************** * EMIF_ioctl - function to implement the EMIF ioctl's *****************************************************************************/ static int EMIF_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long args) { void __user *argp = (void __user *) args; struct EMIF emif; if (_IOC_TYPE(cmd) != EMIF_MAGIC) { return -ENOTTY; } if (_IOC_NR(cmd) > EMIF_MAXNR) { return -ENOTTY; } switch (cmd) { case EMIF_READ: if (copy_from_user(&emif, argp, sizeof(struct EMIF))) return -EFAULT; emif.value = EMIF_get_value(emif.address); if (copy_to_user(argp, &emif, sizeof(struct EMIF))) return -EFAULT; break; case EMIF_WRITE: if (copy_from_user(&emif, argp, sizeof(struct EMIF))) return -EFAULT; EMIF_set_value(emif.address, emif.value); break; default: return -ENOTTY; break; } return 0; } /****************************************************************************** * EMIF_open - do nothing *****************************************************************************/ static int EMIF_open (struct inode *inode, struct file *filp) { printk(KERN_DEBUG "EMIF Driver OPENED\n"); return 0; } /****************************************************************************** * EMIF_release - do nothing *****************************************************************************/ static int EMIF_release (struct inode *inode, struct file *filp) { struct nand_davinci_info *info; release_resource(info->reg_res); kfree(info->reg_res); kfree(info); return 0; } #define res_size(_r) (((_r)->end - (_r)->start) + 1) /***************************************************************************** * EMIF_init_module - initialise user EMIF module ****************************************************************************/ int EMIF_init_module () { struct resource *res; struct nand_davinci_info *info; struct platform_device *pdev = to_platform_device(EMIF_cdev); int err = 0; if (alloc_chrdev_region(&dev, 0, 1, "EMIF_Client") < 0) { printk(KERN_DEBUG "Failed to register the device\n"); return 1; } EMIF_cdev = cdev_alloc(); if (EMIF_cdev == NULL) { printk(KERN_DEBUG "Failed to allocate cdev\n"); return 1; } cdev_init(EMIF_cdev, &EMIF_fops); if (cdev_add(EMIF_cdev, dev, 1) < 0) { printk(KERN_DEBUG "Failed to add cdev\n"); return 1; } info = kzalloc(sizeof(struct nand_davinci_info), GFP_KERNEL); if (!info) { err = -ENOMEM; return 0; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res || (res_size(res) < EMIF_REG_SIZE)) { // dev_err(user_EMIF_cdev, "insufficient resources\n"); // printk(); printk(KERN_DEBUG "insufficient resources\n"); kfree(info); //err = -ENOENT; //goto out_free_info; } /* * We exclude the EMIF registers prior to NANDFCR (the chip select * timing registers) from our resource reservation request because we * don't use them and another module might need them. */ info->reg_res = request_mem_region(res->start,res_size(res), pdev->name); if (!info->reg_res) { // dev_err(user_EMIF_cdev, "cannot claim register memory region\n"); printk("cannot claim register memory region\n"); printk(KERN_DEBUG "cannot claim register memory region\n"); kfree(info); // err = -EIO; //goto out_free_info; } info->emifregs = ioremap_nocache(res->start, res_size(res)); //out_free_info: // out: // return err; return 0; } /***************************************************************************** * EMIF_cleanup_module - cleanup user EMIF module ****************************************************************************/ void EMIF_cleanup_module () { cdev_del(EMIF_cdev); unregister_chrdev_region(dev, 1); } /* Register driver to the kernel */ module_init(EMIF_init_module); module_exit(EMIF_cleanup_module);