/* 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*/},
};
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;
}
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;
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 */
printk(KERN_ERR "|||||||||||||||||||||||||||||||||||||||||||||||| \r\n");
printk(KERN_ERR "|||||||||||||||||||||||||||||||||||||||||||||||| \r\n");
printk(KERN_ERR "|||||||||||||||||||||||||||||||||||||||||||||||| \r\n");
printk(KERN_ERR "\r\n");
// #############################################
// OF FUNCTIONS THAT FIND NODES TEST CODE INSERT
// #############################################
// of_find_node_by_name
struct device_node *test_ofnbn;
test_ofnbn = of_find_node_by_name(NULL, "test_node2");
if(NULL == &test_ofnbn){
printk(KERN_ERR "Node was not found via of_find_node_by_name \r\n");
}
if(NULL != &test_ofnbn){
printk(KERN_ERR "Node was successfully found via of_find_node_by_name \r\n");
printk(KERN_ERR "Node name is: %s \r\n", test_ofnbn->name);
}
printk(KERN_ERR "\r\n");
// of_find_node_by_type
struct device_node *test_ofnbt;
test_ofnbt = of_find_node_by_type(NULL, "test_device_type1");
if(NULL == &test_ofnbt){
printk(KERN_ERR "Node was not found via of_find_node_by_type \r\n");
}
if(NULL != &test_ofnbt){
printk(KERN_ERR "Node was successfully found via of_find_node_by_type \r\n");
printk(KERN_ERR "Node name is: %s \r\n", test_ofnbt->name);
}
printk(KERN_ERR "\r\n");
// of_find_compatible_node
struct device_node *test_ofcndn;
test_ofcndn = of_find_compatible_node(NULL, "test_device_type1", "fii,fii-dt-driver");
if(NULL == &test_ofcndn){
printk(KERN_ERR "Node was not found via of_find_compatible_node \r\n");
}
if(NULL != &test_ofcndn){
printk(KERN_ERR "Node was successfully found via of_find_compatible_node \r\n");
printk(KERN_ERR "Node name is: %s \r\n", test_ofcndn->name);
}
printk(KERN_ERR "\r\n");
// of_find_matching_node_and_match
const struct of_device_id *test_np;
struct device_node *test_dn;
test_dn = of_find_matching_node_and_match(NULL, of_match_fii_dt_driver, &test_np);
if(NULL == &test_dn){
printk(KERN_ERR "Node was not found via of_find_matching_node_and_match \r\n");
}
if(NULL != &test_dn){
printk(KERN_ERR "Node was successfully found via of_find_matching_node_and_match \r\n");
printk(KERN_ERR "Node name is: %s \r\n", test_dn->name);
}
printk(KERN_ERR "\r\n");
// of_find_node_by_path
struct device_node *test_ofnbp;
test_ofnbp = of_find_node_by_path("/test_node1");
if(NULL == &test_ofnbp){
printk(KERN_ERR "Node was not found via of_find_node_by_path \r\n");
}
if(NULL != &test_ofnbp){
printk(KERN_ERR "Node was successfully found via of_find_node_by_path \r\n");
printk(KERN_ERR "Node name is: %s \r\n", test_ofnbp->name);
}
printk(KERN_ERR "\r\n");
printk(KERN_ERR "################################################ \r\n");
printk(KERN_ERR "\r\n");
// ##########################################################
// OF FUNCTIONS THAT FIND PARENT/CHILD NODES TEST CODE INSERT
// ##########################################################
// of_get_parent
struct device_node *test_ogp;
test_ogp = of_get_parent(of_find_node_by_name(NULL, "test_node2"));
if(NULL == &test_ogp){
printk(KERN_ERR "Parent node of test_node2 was not found via of_get_parent \r\n");
}
if(NULL != &test_ogp){
printk(KERN_ERR "Parent node of test_node2 was successfully found via of_get_parent \r\n");
printk(KERN_ERR "Node name is: %s \r\n", test_ogp->name);
}
printk(KERN_ERR "\r\n");
// of_get_next_child
struct device_node *test_ognc;
test_ognc = of_get_next_child(of_find_node_by_name(NULL, "test_node1"), NULL);
if(NULL == &test_ognc){
printk(KERN_ERR "Next child node of test_node1 was not found via of_get_next_child \r\n");
}
if(NULL != &test_ognc){
printk(KERN_ERR "Next child node of test_node1 was successfully found via of_get_next_child \r\n");
printk(KERN_ERR "Node name is: %s \r\n", test_ognc->name);
}
printk(KERN_ERR "\r\n");
printk(KERN_ERR "################################################ \r\n");
printk(KERN_ERR "\r\n");
// ##########################################################
// OF FUNCTIONS THAT EXTRACT PROPERTY VALUES TEST CODE INSERT
// ##########################################################
// of_find_property
int plen;
struct property *test_ofp;
test_ofp = of_find_property(of_find_node_by_name(NULL, "test_node1"), "compatible", &plen);
printk(KERN_ERR "Compatible property of test_node1 was successfully found via of_find_property \r\n");
printk(KERN_ERR "Property name is: %s \r\n", test_ofp->name);
printk(KERN_ERR "\r\n");
// of_property_count_elems_of_size
int test_opceos;
const char propname[] = "reg";
printk(KERN_ERR "propname = %d \r\n" , sizeof(propname));
test_opceos = of_property_count_elems_of_size(of_find_node_by_name(NULL, "fii-dt-driver"),"compatible", 1);
printk(KERN_ERR "Compatible property of test_node1 was successfully found via of_property_count_elems_of_size \r\n");
printk(KERN_ERR "Property element count is: %d \r\n", test_opceos);
printk(KERN_ERR "\r\n");
// of_property_read_u32_index
u32 oprui_output;
int ret = 0;
ret = of_property_read_u32_index(of_find_node_by_name(NULL, "test_node1"), "test_array", 0,&oprui_output);
printk(KERN_ERR "test_array of test_node1 was successfully found via of_property_read_u32_index \r\n");
printk(KERN_ERR "Property value at index 0 is: ret = %d, 0x%08x\r\n", ret, oprui_output);
printk(KERN_ERR "\r\n");
ret = of_property_read_u32_index(of_find_node_by_name(NULL, "test_node1"), "test_array", 1,&oprui_output);
printk(KERN_ERR "Property value at index 1 is: ret = %d, 0x%08x\r\n", ret, oprui_output);
printk(KERN_ERR "\r\n");
ret = of_property_read_u32_index(of_find_node_by_name(NULL, "test_node1"), "test_array", 2,&oprui_output);
printk(KERN_ERR "Property value at index 2 is: ret = %d, 0x%08x\r\n", ret, oprui_output);
printk(KERN_ERR "\r\n");
ret = of_property_read_u32_index(of_find_node_by_name(NULL, "test_node1"), "test_array", 3,&oprui_output);
printk(KERN_ERR "Property value at index 3 is: ret = %d, 0x%08x\r\n", ret, oprui_output);
printk(KERN_ERR "\r\n");
ret = of_property_read_u32_index(of_find_node_by_name(NULL, "test_node1"), "test_array", 4,&oprui_output);
printk(KERN_ERR "Property value at index 4 is: ret = %d, 0x%08x\r\n", ret, oprui_output);
printk(KERN_ERR "\r\n");
printk(KERN_ERR "\r\n");
printk(KERN_ERR "---------------------------------------------------- \r\n");
printk(KERN_ERR "\r\n");
// of_property_read_u_array
size_t elements;
int i;
// of_property_read_u8_array
u8 test_opru8a_out[5];
int test_opru8a;
elements = 5;
test_opru8a = of_property_read_u8_array(of_find_node_by_name(NULL, "test_node1"),"test_array", test_opru8a_out, elements);
printk(KERN_ERR "test_array of test_node1 was successfully found via of_property_read_u8_array \r\n");
for(i = 0; i < elements; i++){
printk(KERN_ERR "Return value : %d \nProperty value is: 0x%02x\r\n", test_opru8a,test_opru8a_out[i]);
}
printk(KERN_ERR "\r\n");
elements = 5;
test_opru8a = of_property_read_u8_array(of_find_node_by_name(NULL, "test_node2"),"u8_test_array", test_opru8a_out, elements);
printk(KERN_ERR "u8_test_array of test_node2 was successfully found via of_property_read_u8_array \r\n");
for(i = 0; i < elements; i++){
printk(KERN_ERR "Return value : %d \nProperty value is: 0x%02x\r\n", test_opru8a,test_opru8a_out[i]);
}
printk(KERN_ERR "\r\n");
// of_property_read_u16_array
u16 test_opru16a_out[5];
int test_opru16a;
elements = 5;
test_opru16a = of_property_read_u16_array(of_find_node_by_name(NULL, "test_node1"),"test_array", test_opru16a_out, elements);
printk(KERN_ERR "test_array of test_node1 was successfully found via of_property_read_u16_array \r\n");
for(i = 0; i < elements; i++){
printk(KERN_ERR "Return value : %d \nProperty value is: 0x%04x\r\n", test_opru16a,test_opru16a_out[i]);
}
printk(KERN_ERR "\r\n");
elements = 5;
test_opru16a = of_property_read_u16_array(of_find_node_by_name(NULL, "test_node2"),"u16_test_array", test_opru16a_out, elements);
printk(KERN_ERR "u16_test_array of test_node2 was successfully found via of_property_read_u16_array \r\n");
for(i = 0; i < elements; i++){
printk(KERN_ERR "Return value : %d \nProperty value is: 0x%04x\r\n", test_opru16a,test_opru16a_out[i]);
}
printk(KERN_ERR "\r\n");
// of_property_read_u32_array
u32 test_opru32a_out[5];
int test_opru32a;
elements = 5;
test_opru32a = of_property_read_u32_array(of_find_node_by_name(NULL, "test_node2"),"u32_test_array", test_opru32a_out, elements);
printk(KERN_ERR "u32_test_array of test_node2 was successfully found via of_property_read_u32_array \r\n");
for(i = 0; i < elements; i++){
printk(KERN_ERR "Return value : %d \nProperty value is: 0x%06x\r\n", test_opru32a,test_opru32a_out[i]);
}
printk(KERN_ERR "\r\n");
// of_property_read_u64_array
u64 test_opru64a_out[5];
int test_opru64a;
elements = 5;
test_opru64a = of_property_read_u64_array(of_find_node_by_name(NULL, "test_node2"),"u64_test_array", test_opru64a_out, elements);
printk(KERN_ERR "u64_test_array of test_node2 was successfully found via of_property_read_u64_array \r\n");
for(i = 0; i < elements; i++){
printk(KERN_ERR "Return value : %d \nProperty value is: 0x%08x\r\n", test_opru64a,test_opru64a_out[i]);
}
printk(KERN_ERR "\r\n");
printk(KERN_ERR "\r\n");
printk(KERN_ERR "---------------------------------------------------- \r\n");
printk(KERN_ERR "\r\n");
// of_property_read_u8
u8 test_opru8_out;
int test_opru8;
test_opru8 = of_property_read_u8(of_find_node_by_name(NULL, "test_node2"), "u8_test_array",&test_opru8_out);
printk(KERN_ERR "u8_test_array of test_node2 was successfully found via of_property_read_u8 \r\n");
printk(KERN_ERR "Return value : %d \nProperty value is: 0x%02x\r\n", test_opru8,test_opru8_out);
printk(KERN_ERR "\r\n");
test_opru8 = of_property_read_u8(of_find_node_by_name(NULL, "test_node2"), "u8_test",&test_opru8_out);
printk(KERN_ERR "u8_test of test_node2 was successfully found via of_property_read_u8 \r\n");
printk(KERN_ERR "Return value : %d \nProperty value is: 0x%02x\r\n", test_opru8,test_opru8_out);
printk(KERN_ERR "\r\n");
// of_property_read_u16
u16 test_opru16_out;
int test_opru16;
test_opru16 = of_property_read_u16(of_find_node_by_name(NULL, "test_node2"),"u16_test_array", &test_opru16_out);
printk(KERN_ERR "u16_test_array of test_node2 was successfully found via of_property_read_u16 \r\n");
printk(KERN_ERR "Return value : %d \nProperty value is: 0x%04x\r\n", test_opru16,test_opru16_out);
printk(KERN_ERR "\r\n");
test_opru16 = of_property_read_u16(of_find_node_by_name(NULL, "test_node2"), "u16_test",&test_opru16_out);
printk(KERN_ERR "u16_test of test_node2 was successfully found via of_property_read_u16 \r\n");
printk(KERN_ERR "Return value : %d \nProperty value is: 0x%04x\r\n", test_opru16,test_opru16_out);
printk(KERN_ERR "\r\n");
// of_property_read_u32
u32 test_opru32_out;
int test_opru32;
test_opru32 = of_property_read_u32(of_find_node_by_name(NULL, "test_node2"),"u32_test_array", &test_opru32_out);
printk(KERN_ERR "u32_test_array of test_node2 was successfully found via of_property_read_u32 \r\n");
printk(KERN_ERR "Return value : %d \nProperty value is: 0x%06x\r\n", test_opru32,test_opru32_out);
printk(KERN_ERR "\r\n");
test_opru32 = of_property_read_u32(of_find_node_by_name(NULL, "test_node2"), "u32_test",&test_opru32_out);
printk(KERN_ERR "u32_test of test_node2 was successfully found via of_property_read_u32 \r\n");
printk(KERN_ERR "Return value : %d \nProperty value is: 0x%06x\r\n", test_opru32,test_opru32_out);
printk(KERN_ERR "\r\n");
// of_property_read_u64
u64 test_opru64_out;
int test_opru64;
test_opru64 = of_property_read_u64(of_find_node_by_name(NULL, "test_node2"),"u64_test_array", &test_opru64_out);
printk(KERN_ERR "u64_test_array of test_node2 was successfully found via of_property_read_u64 \r\n");
printk(KERN_ERR "Return value : %d \nProperty value is: 0x%08x\r\n", test_opru64,test_opru64_out);
printk(KERN_ERR "\r\n");
test_opru64 = of_property_read_u64(of_find_node_by_name(NULL, "test_node2"), "u64_test",&test_opru64_out);
printk(KERN_ERR "u64_test of test_node2 was successfully found via of_property_read_u64 \r\n");
printk(KERN_ERR "Return value : %d \nProperty value is: 0x%08x\r\n", test_opru64,test_opru64_out);
printk(KERN_ERR "\r\n");
printk(KERN_ERR "---------------------------------------------------- \r\n");
printk(KERN_ERR "\r\n");
// of_property_read_string
const char *test_oprs_out;
int test_oprs;
test_oprs = of_property_read_string(of_find_node_by_name(NULL, "test_node1"), "status",&test_oprs_out);
printk(KERN_ERR "status was successfully found via of_property_read_string \r\n");
printk(KERN_ERR "Return value : %d \nProperty value is: %s\r\n", test_oprs, test_oprs_out);
printk(KERN_ERR "\r\n");
// of_n_addr_cells
int test_onac;
test_onac = of_n_addr_cells(of_find_node_by_name(NULL, "fii-dt-driver"));
printk(KERN_ERR "Address Cells was successfully found via of_n_addr_cells \r\n");
printk(KERN_ERR "Return value : %d\n", test_onac);
printk(KERN_ERR "\r\n");
// of_n_size_cells
int test_onsc;
test_onsc = of_n_size_cells(of_find_node_by_name(NULL, "fii-dt-driver"));
printk(KERN_ERR "Size Cells was successfully found via of_n_size_cells \r\n");
printk(KERN_ERR "Return value : %d\n", test_onsc);
printk(KERN_ERR "\r\n");
printk(KERN_ERR "################################################ \r\n");
printk(KERN_ERR "\r\n");
// ##########################################
// OTHER COMMON OF FUNCTIONS TEST CODE INSERT
// ##########################################
// of_device_is_compatible
int test_odic;
test_odic = of_device_is_compatible(of_find_node_by_name(NULL, "fii-dt-driver"), "fii,fii-dt-driver");
printk(KERN_ERR "Compatible was successfully found via of_device_is_compatible \r\n");
printk(KERN_ERR "Return value : %d\n", test_odic);
printk(KERN_ERR "\r\n");
// of_get_address
const __be32 *test_oga;
u64 test_oga_size;
test_oga = of_get_address(of_find_node_by_name(NULL, "fii-dt-driver"), 0, &test_oga_size,NULL);
printk(KERN_ERR "Address was successfully found via of_get_address \r\n");
printk(KERN_ERR "Return value : 0x%08x\n", test_oga);
printk(KERN_ERR "\r\n");
// of_translate_address
u64 test_ota;
test_ota = of_translate_address(of_find_node_by_name(NULL, "fii-dt-driver"), test_oga);
printk(KERN_ERR "Address was successfully translated via of_translate_address \r\n");
printk(KERN_ERR "Return value : 0x%08x\n", test_ota);
printk(KERN_ERR "\r\n");
// of_address_to_resource
int test_oatr;
struct resource res;
test_oatr = of_address_to_resource(of_find_node_by_name(NULL, "fii-dt-driver"), 0, &res);
printk(KERN_ERR "Resource was successfully transfered via of_address_to_resource \n");
printk(KERN_ERR "Return value: %d \nProperty value is: 0x%08x\n", test_oatr, res);
printk(KERN_ERR "\r\n");
// of_iomap
void __iomem *test_oi;
test_oi = of_iomap(of_find_node_by_name(NULL, "fii-dt-driver"), 0);
printk(KERN_ERR "Mapping was successful via of_iomap \n");
printk(KERN_ERR "Return value: 0x%08x\n", test_oi);
printk(KERN_ERR "\r\n");
printk(KERN_ERR "||||||||||||||||||||||||||||||||||||||||||||| \r\n");
printk(KERN_ERR "||||||||||||||||||||||||||||||||||||||||||||| \r\n");
printk(KERN_ERR "||||||||||||||||||||||||||||||||||||||||||||| \r\n");
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");