/* fii-dt-driver.c - The simplest kernel module.
* Copyright (C) 2013 - 2016 Xilinx, Inc
*
* This program is free software; you can redistribute it and/or modify
* it unde r the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*/
#include
#include
#include
#include
#include
#include
#include /* for put_user */
#include
#include
#include
/* Standard module information, edit as appropriate */
MODULE_LICENSE("GPL");
MODULE_AUTHOR
("FII inc.");
MODULE_DESCRIPTION
("fii-dt-driver - loadable module template generated by petalinux-create -t modules");
#define DRIVER_NAME "fii-dt-driver"
static const struct of_device_id of_match_fii_dt_driver[] = {
// {.compatible = "fii,fii-dt-driver", .data = NULL},
{.compatible = "fii,fii-dt-driver", },
{/*sentinel*/},
};
//platform driver
static struct class *fii_dt_driver_class;
static unsigned int major;
static unsigned int * gpio_base;
static unsigned int * gpio_data;
static unsigned int * gpio_dir;
static int fii_dt_driver_init(void);
static int fii_dt_driver_open(struct inode* node,struct file* filp){
gpio_data = ioremap(gpio_base, 8);
if(gpio_data){
printk("kernel: ioremap(0x%08x)=0x%08x \n", gpio_base, gpio_data);
}
else{
return -EINVAL;
}
gpio_dir = gpio_data + 1;
return 0;
}
static int fii_dt_driver_release(struct platform_device * dev)
{
iounmap(gpio_data);
unregister_chrdev(major, "fii-dt-driver");
device_destroy(fii_dt_driver_class,MKDEV(major,0));
class_destroy(fii_dt_driver_class);
return 0;
}
/*
0x43c0_0000 + 4 = value
0x43c0_0000 + 8 = direction
*/
static ssize_t fii_dt_driver_read(struct file *filp, char *buf, size_t size, loff_t *offset)
{
unsigned char val[32];
unsigned int temp;
unsigned int *addr_p;
int i,cnt;
printk("kernel: fii-dt-driver read start.... size = %d\n", size);
// cnt = size - 1;
cnt = size;
addr_p = gpio_data;
temp = *addr_p ;
for(i = 0; i < cnt/4; i++ )
{
val[i*4 + 3] = temp & 0xff;
val[i*4 + 2] = (temp >> 8) & 0xff;
val[i*4 + 1] = (temp >> 16) & 0xff;
val[i*4 + 0] = (temp >> 24) & 0xff;
addr_p ++;
temp = *addr_p;
}
if(i % 4 == 1)
{
val[i*4 + 0] = temp & 0xff;
}
if(i % 4 == 2)
{
val[i*4 + 1] = temp & 0xff;
val[i*4 + 0] = (temp >> 8) & 0xff;
}
if(i % 4 == 3)
{
val[i*4 + 2] = temp & 0xff;
val[i*4 + 1] = (temp >> 8) & 0xff;
val[i*4 + 0] = (temp >> 16) & 0xff;
}
copy_to_user(buf, val, cnt);
return cnt;
}
static ssize_t fii_dt_driver_write(struct file * filp, const char __user *buf, size_t size, loff_t * offset) {
unsigned char val[32];
unsigned int temp = 0;
unsigned int * addr_p;
int i,cnt;
memset(val,0,32);
addr_p = gpio_data;
printk("kernel: fii-dt-driver write start.... size = %d\n", size);
copy_from_user(&val, buf, size);
cnt = size - 1;
printk("kernel: val[0] = 0x%08x \n", val[0]);
if(val[0] == 'w')
{
temp = val[2];
temp = temp << 8 | val[3];
temp = temp << 8 | val[4];
temp = temp << 8 | val[5];
*addr_p = temp;
printk("kernel: gpio_data = 0x%08x \n", temp);
}
else if(val[0] == 'd')
{
addr_p ++;
temp = val[2];
temp = temp << 8 | val[3];
temp = temp << 8 | val[4];
temp = temp << 8 | val[5];
*addr_p = temp;
printk("kernel: gpio_dir = 0x%08x \n", temp);
}
else
{
printk("kernel: invalid parameter \n");
}
return size;
}
static struct file_operations fii_dt_driver_oprs = {
.owner = THIS_MODULE,
.open = fii_dt_driver_open,
.write = fii_dt_driver_write,
.read = fii_dt_driver_read,
};
static int fii_dt_driver_probe(struct platform_device *pdev)
{
struct resource *res;
printk ("kernel: enter fii_dt_driver probe ...... \n");
printk ("kernel: enter fii_dt_driver probe ...... \n");
printk ("kernel: enter fii_dt_driver probe ...... \n");
printk ("kernel: enter fii_dt_driver probe ...... \n");
printk ("kernel: enter fii_dt_driver probe ...... \n");
printk ("kernel: enter fii_dt_driver probe ...... \n");
res = platform_get_resource(pdev, IORESOURCE_MEM,0);
if(res){
gpio_base = res->start;
}
major=register_chrdev(0, "fii-dt-driver", &fii_dt_driver_oprs);
if (major < 0) {
printk ("Registering the character device failed with %d\n", major);
return major;
}
fii_dt_driver_class = class_create(THIS_MODULE, "fii-dt-driver_class");
device_create(fii_dt_driver_class,NULL,MKDEV(major,0),NULL,"fii-dt-driver");
return 0;
}
MODULE_DEVICE_TABLE(of, of_match_fii_dt_driver);
static struct platform_driver fii_dt_driver_drv = {
.driver = {
.name = "fii-dt-driver",
.owner = THIS_MODULE,
.of_match_table = of_match_fii_dt_driver,
},
.probe = fii_dt_driver_probe,
.remove = fii_dt_driver_release,
};
static int fii_dt_driver_init(void){ /* register device */
return platform_driver_register(&fii_dt_driver_drv);
}
static void fii_dt_driver_exit(void){
platform_driver_unregister(&fii_dt_driver_drv);
return;
};
module_init(fii_dt_driver_init);
module_exit(fii_dt_driver_exit);
MODULE_ALIAS("platform:fii-dt-driver");