Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <linux/kernel.h>
- #include <linux/device.h>
- #include <linux/mutex.h>
- #include <linux/module.h>
- #include <linux/i2c.h>
- #include <linux/slab.h>
- #include <asm/byteorder.h>
- #include <linux/of.h>
- #include <linux/of_device.h>
- #include <linux/cdev.h>
- #include <linux/errno.h>
- #include <linux/fs.h>
- #include <asm/uaccess.h>
- #include <linux/list.h>
- #include <linux/of_address.h>
- #include <linux/of_gpio.h>
- #include <linux/poll.h>
- #include <linux/of_irq.h>
- #include <linux/interrupt.h> // Required for the IRQ code
- #define DEV_COUNT 1
- #define MODNAME "bt125"
- #define BT125_GPIO_IN_REG 0x00
- #define BT125_GPIO_OUT_REG 0x01
- #define BT125_PWR_CTRL_REG 0x04
- #define BT125_BKL_REG 0x08
- #define BT125_PWR_REG 0x09
- #define BT125_TACHO_REG 0x10
- #define BT125_WDT_REG 0x20
- #define BT125_FW_REG 0x3C
- #define BT125_EXP_GPIO 0x13
- #define BT125_EXP_LED 0x12
- #define BT125_ADP_OI_REG 0x2A
- //https://code.google.com/p/ldd-templates/source/browse/drivers/i2c/sample-i2c-client.c
- //http://www.embedded-bits.co.uk/2009/i2c-in-the-2632-linux-kernel/
- //http://renjucnair.blogspot.ca/2012/01/writing-i2c-client-driver.html
- //http://lxr.free-electrons.com/source/drivers/hwmon/lm75.c#L325
- enum bt125_func_modules{
- bt125_IN,
- bt125_OUT,
- bt125_PWR_CTRL,
- bt125_BKL,
- bt125_PWR,
- bt125_TACHO,
- bt125_WDT,
- bt125_DIP,
- bt125_ROTARY,
- bt125_LED,
- };
- enum bt125_data_access{
- bt125_BIT,
- bt125_8B,
- bt125_16B,
- bt125_32B,
- };
- enum bt125_access{
- bt125_READ=0x01,
- bt125_WRITE=0x02,
- bt125_READWRITE=0x03,
- };
- struct bt125_k{
- u8 bt125_modul;
- enum bt125_data_access data_access;
- enum bt125_access access;
- u8 i2c_addr;
- int i2c_mask;//hodnota vyctena z I2C se vymaskuje touto maskou, u binarniho pristupu se ocekavaji pouze bity v teto masce
- char * name;
- };
- static const struct bt125_k bt125_keys_exp[]={
- {bt125_DIP,bt125_BIT,bt125_READ,BT125_EXP_GPIO,0xf0,"D:"},
- {bt125_ROTARY,bt125_8B,bt125_READ,BT125_EXP_GPIO,0x0f,"R:"},
- {bt125_LED,bt125_BIT,bt125_READWRITE,BT125_EXP_LED,0xf0,"L:"},
- { }
- };
- static const struct bt125_k bt125_keys_cpu[]={
- {bt125_IN,bt125_BIT,bt125_READ,BT125_GPIO_IN_REG,0x0f,"IN:"},
- {bt125_OUT,bt125_BIT,bt125_READWRITE,BT125_GPIO_OUT_REG,0x01,"OUT:"},
- {bt125_PWR_CTRL,bt125_BIT,bt125_READWRITE,BT125_PWR_CTRL_REG,0x01,"PWR_CTRL:"},
- {bt125_BKL,bt125_8B,bt125_READ,BT125_BKL_REG,0xff,"BKL:"},
- {bt125_PWR,bt125_8B,bt125_READ,BT125_PWR_REG,0xff,"PWR:"},
- {bt125_TACHO,bt125_32B,bt125_READ,BT125_TACHO_REG,0xffffffff,"TCH:"},
- {bt125_WDT,bt125_8B,bt125_WRITE,BT125_WDT_REG,0xff,"WDT:"},
- { }
- };
- static const struct bt125_k bt125_adp5589[]={
- {bt125_LED,bt125_BIT,bt125_READWRITE,BT125_ADP_OI_REG,0x78,"L:"},
- { }
- };
- ////////////////////////
- struct bt125_i2c_handler{
- struct list_head list;
- struct i2c_client * client;
- int minor;
- int major;
- };
- static DEFINE_SPINLOCK(bt125_i2c_list_lock);
- static LIST_HEAD(bt125_i2c_dev_list);
- static struct bt125_i2c_handler *bt125_i2c_dev_get_by_minor(unsigned minor,unsigned major){
- struct bt125_i2c_handler *handler;
- //printk(KERN_INFO "%s %s Try find i2c handler %d , %d \n",MODNAME,__func__,minor,major);
- spin_lock(&bt125_i2c_list_lock);
- list_for_each_entry(handler, &bt125_i2c_dev_list,list) {
- if (handler->minor == minor && handler->major == major)
- goto found;
- }
- handler = NULL;
- found:
- spin_unlock(&bt125_i2c_list_lock);
- return handler;
- }
- static struct bt125_i2c_handler *bt125_get_free_i2c_dev(struct i2c_client *client,int minor, int major){
- struct bt125_i2c_handler *handler;
- //Sanity check (minor and major must be unique)
- if(bt125_i2c_dev_get_by_minor(minor,major)!=NULL){
- printk(KERN_ERR "%s %s Device allredy exist. DRIVER!ERRO!! \n",MODNAME,__func__);
- return ERR_PTR(-ENXIO);
- }
- //printk(KERN_INFO "%s %s Add i2c handler %d, %d \n",MODNAME,__func__,minor,major);
- handler = kzalloc(sizeof(*handler), GFP_KERNEL);
- if (!handler)
- return ERR_PTR(-ENOMEM);
- handler->client = client;
- handler->minor = minor;
- handler->major = major;
- spin_lock(&bt125_i2c_list_lock);
- list_add_tail(&handler->list, &bt125_i2c_dev_list);
- spin_unlock(&bt125_i2c_list_lock);
- return handler;
- }
- static void bt125_return_i2c_dev(unsigned minor, unsigned major){
- struct bt125_i2c_handler * handler;
- //printk(KERN_INFO "%s %s Destroying handler %d, %d \n",MODNAME,__func__,minor,major);
- handler=bt125_i2c_dev_get_by_minor(minor,major);
- if (!handler){
- printk(KERN_ERR "%s %s Cannot find i2c handler! \n",MODNAME,__func__);
- return;
- }
- spin_lock(&bt125_i2c_list_lock);
- list_del(&handler->list);
- spin_unlock(&bt125_i2c_list_lock);
- kfree(handler);
- }
- //////////////////
- struct bt125{
- struct i2c_client * client;
- dev_t dev_num;
- // ukazatel na strukturu cdev reprezentujici znakove zarizeni
- struct cdev cdev;
- // ukazatel na tridu zarizeni v adresari /sys/class
- struct class * sys_class_ptr;
- struct device * sys_dev_ptr;
- const struct bt125_k *ops;
- wait_queue_head_t wait_queue;
- //asi by melo byt chraneno mutexem protoze muzu pristupovat z vice vlakem, otazka je zda mi to vadi
- int data_cookie;
- };
- int bt125_i2c_read_value(struct i2c_client *client, u8 reg){
- return i2c_smbus_read_byte_data(client, reg);
- }
- int bt125_i2c_write_value(struct i2c_client *client, u8 reg, u16 value){
- return i2c_smbus_write_byte_data(client,reg,value);
- }
- int bt125_read_value(struct i2c_client *client, const struct bt125_k * modul){
- int value=0;
- switch(modul->data_access){
- case bt125_16B:
- value=bt125_i2c_read_value(client, modul->i2c_addr);
- value=value<<8;
- value|=bt125_i2c_read_value(client, modul->i2c_addr+1);
- break;
- case bt125_32B:
- value=bt125_i2c_read_value(client, modul->i2c_addr);
- value=value<<8;
- value|=bt125_i2c_read_value(client, modul->i2c_addr+1);
- value=value<<8;
- value|=bt125_i2c_read_value(client, modul->i2c_addr+2);
- value=value<<8;
- value|=bt125_i2c_read_value(client, modul->i2c_addr+3);
- break;
- case bt125_BIT:
- case bt125_8B:
- default:
- value=bt125_i2c_read_value(client, modul->i2c_addr);
- break;
- }
- //printk(KERN_INFO "%s %d %d mod: %d \n",modul->name,modul->i2c_addr,bt125_i2c_read_value(client,modul->i2c_addr),modul->data_access);
- return value;
- }
- int bt125_write_value(struct i2c_client *client,const struct bt125_k * modul, int value){
- int ret;
- switch(modul->data_access){
- case bt125_16B:
- ret=bt125_i2c_write_value(client,modul->i2c_addr,value&0xff);
- value=value>>8;
- ret|=bt125_i2c_write_value(client,modul->i2c_addr+1,value&0xff);
- break;
- case bt125_32B:
- ret=bt125_i2c_write_value(client,modul->i2c_addr,value&0xff);
- value=value>>8;
- ret|=bt125_i2c_write_value(client,modul->i2c_addr+1,value&0xff);
- value=value>>8;
- ret|=bt125_i2c_write_value(client,modul->i2c_addr+2,value&0xff);
- value=value>>8;
- ret|=bt125_i2c_write_value(client,modul->i2c_addr+3,value&0xff);
- break;
- case bt125_BIT:
- case bt125_8B:
- default:
- return bt125_i2c_write_value(client,modul->i2c_addr,value);
- break;
- }
- return ret;
- }
- /////////////////////
- int bt125_read_module(const struct bt125_k * modul,char * buffer,int max_buffer,struct i2c_client *client){
- int value;
- int i;
- memset(buffer,0,max_buffer);
- value=bt125_read_value(client,modul);
- //printk(KERN_INFO "%s %s Reading module %s value: %d \n",MODNAME,__func__,modul->name,value);
- //printk(KERN_INFO "%s %s %d %d \n",MODNAME,__func__,modul->i2c_addr,bt125_i2c_read_value(client,modul->i2c_addr));
- switch(modul->data_access){
- case bt125_BIT:
- sprintf(buffer, "%s", modul->name);
- for(i=0;i<8;i++){
- if((modul->i2c_mask&(0x01<<i))==0)
- continue;
- if(strlen(buffer)+20>max_buffer){
- printk(KERN_ERR "%s %s Not enought buffer size! \n",MODNAME,__func__);
- return -ENOMEM;
- }
- sprintf(buffer+strlen(buffer), "%d,", value>>i&(0x01));
- }
- strcat(buffer,"\n");
- break;
- case bt125_16B:
- case bt125_32B:
- default://default je 8B
- if(max_buffer<20)
- return -ENOMEM;
- value&=modul->i2c_mask;
- sprintf(buffer, "%s%d\n", modul->name,value);
- break;
- };
- return 0;
- }
- int bt125_write_module(const struct bt125_k * modul,char * msg,struct i2c_client * client){
- int value;
- int i;
- int count;
- int msg_len;
- char *pch;
- value=bt125_read_value(client,modul);
- pch = strstr (msg,"\n");
- if(pch==NULL)
- msg_len=strlen(msg);
- else
- msg_len=pch-msg;
- switch(modul->data_access){
- case bt125_BIT:
- count=0;
- for(i=0;i<8;i++){
- if((modul->i2c_mask&(0x01<<i))==0)
- continue;
- if((count*2)>=msg_len) {//mimo buffer
- printk(KERN_ERR "%s %s Outside buffer! %s shift %d \n",MODNAME,__func__,modul->name,count);
- return -EINVAL;
- }
- switch(msg[count*2]){
- case '0':
- value&=~(0x01<<i);
- break;
- case '1':
- value|=(0x01<<i);
- break;
- case 'x':
- case 'X':
- break;
- default:
- printk(KERN_ERR "%s %s Neocekavany znak %c na pozici %d v stringu %s \n",MODNAME,__func__,msg[count*2],(count*2),msg);
- return -EINVAL;
- break;
- };
- count++;
- }
- if(count>1 && ((count*2)-1)!=msg_len)
- return -EINVAL;
- if(count==1 && count!=msg_len)
- return -EINVAL;
- break;
- default://default je INT
- if(sscanf(msg,"%d",&count)!=1)
- return -EINVAL;
- value=count;
- break;
- };
- return bt125_write_value(client,modul,value);
- }
- ///DEVICE OPS
- struct BT125_FILE{
- int data_cookie;
- struct bt125 * pbt125;
- };
- ssize_t bt125_dev_read(struct file * filp, char __user * buff, size_t count, loff_t * ppos){
- const int txt_buff_len=50;
- long result;
- int ret;
- int i;
- char *txt;
- char txt_buff[txt_buff_len];
- int txt_len=150;
- struct BT125_FILE * file_info;
- struct bt125 * handler;
- //printk("Ctu %d %llu \n",count,*ppos);
- file_info=filp->private_data;
- if(file_info==NULL){
- return -ENXIO;
- }
- handler=file_info->pbt125;
- if(handler==NULL){
- return -ENXIO;
- }
- if(file_info->data_cookie!=handler->data_cookie){
- file_info->data_cookie=handler->data_cookie;
- *ppos=0;
- }
- if((*ppos)>=txt_len){//mynule jsem nakopiroval vsechno
- //printk("All data has been sended\n");
- return 0;
- }
- txt = kzalloc(txt_len, GFP_KERNEL);
- if (!txt)
- return -ENOMEM;
- for(i=0;handler->ops[i].name!=NULL;i++){
- if((handler->ops[i].access&bt125_READ)==0)
- continue;
- //dev_err(&client->dev,"Reading %s\n",bt125_keys[i].name);
- ret=bt125_read_module(&handler->ops[i],txt_buff,txt_buff_len,handler->client);
- if(ret!=0){
- printk(KERN_ERR "%s %s Error reading module %s \n",MODNAME,__func__,handler->ops[i].name);
- goto End;
- }
- if(strlen(txt)+strlen(txt_buff)>=txt_len){
- ret =-ENOMEM;
- printk(KERN_ERR "%s %s Error out of memory \n",MODNAME,__func__);
- goto End;
- }
- //printk(KERN_ERR "%s %s Message is %s %s \n",MODNAME,__func__,handler->ops[i].name,txt_buff);
- strcat(txt,txt_buff);//*/
- }
- if(*ppos>=strlen(txt)){//mynule jsem nakopiroval vsechno
- //printk("All data has been sended\n");
- ret=0;
- goto End;
- }
- i=strlen(txt)-(*ppos);
- if(i>=count)
- i=count;
- //SANITY CHACK:
- if((*ppos)+i>=txt_len){
- printk(KERN_ERR "Out of memory! %llu + %u >= %u\n",*ppos,i,txt_len);
- return -ENOMEM;
- }
- result=copy_to_user(buff,txt+(*ppos),i);
- if(result==0){
- ret=i;
- *ppos+=i;
- }else
- ret=-EFAULT;
- //printk("Sending %u, cookie: %u\n",ret,file_info->data_cookie);
- End:
- kfree(txt);
- return ret;
- }
- ssize_t bt125_dev_write (struct file *filp, const char __user *buff, size_t count, loff_t *ppos){
- int i;
- int result;
- char *txt;
- char *pch;
- int parsed_ok=0;
- struct BT125_FILE * file_info;
- struct bt125 * handler;
- file_info=filp->private_data;
- if(file_info==NULL){
- return -ENXIO;
- }
- handler=file_info->pbt125;
- if(handler==NULL){
- return -ENXIO;
- }
- txt = kzalloc(count, GFP_KERNEL);
- if (!txt)
- return -ENOMEM;
- result=copy_from_user(txt,buff,count);
- if(result!=0)
- goto End;
- for(i=0;handler->ops[i].name!=NULL;i++){
- pch = strstr (txt,handler->ops[i].name);
- if(pch==NULL)
- continue;
- if((handler->ops[i].access&bt125_WRITE)==0){
- printk(KERN_ERR "%s %s Modul nema opraveni pro zapis %s \n",MODNAME,__func__,handler->ops[i].name);
- result=-EACCES;
- goto End;
- }
- if(bt125_write_module(&handler->ops[i],pch+strlen(handler->ops[i].name),handler->client)!=0){
- printk(KERN_ERR "%s %s Nepodarilo se zapsat do modulu %s \n",MODNAME,__func__,handler->ops[i].name);
- result=-EINVAL;
- goto End;
- }
- parsed_ok++;
- }
- if(parsed_ok!=0)
- result=count;
- else
- result=-EINVAL;
- End:
- kfree(txt);
- return result;
- }
- unsigned int bt125_poll (struct file * filp, poll_table * wait){
- struct BT125_FILE * file_info=filp->private_data;
- unsigned int mask = 0;
- if(file_info==NULL){
- printk(KERN_ERR "%s %s Handler is NULL! \n",MODNAME,__func__);
- return mask;
- }
- //printk("%s\tGoing to sleep\n",__func__);
- poll_wait(filp,&file_info->pbt125->wait_queue,wait);
- if(file_info->data_cookie != file_info->pbt125->data_cookie){
- mask |= POLLIN | POLLRDNORM;
- printk("%s\tAwakening! cookie:%u x %u\n",__func__,file_info->data_cookie,file_info->pbt125->data_cookie);
- }
- return mask;
- }
- static int bt125_dev_open(struct inode * inode_ptr, struct file * file_ptr){
- unsigned int minor;
- unsigned int major;
- int result = 0;
- struct bt125_i2c_handler * i2c_handler;
- struct BT125_FILE * file_info;
- minor= iminor(inode_ptr);
- major= imajor(inode_ptr);
- //printk(KERN_INFO "%s %s Openening file minor %d, %d\n",MODNAME,__func__,minor,major);
- i2c_handler=bt125_i2c_dev_get_by_minor(minor,major);
- if(!i2c_handler){
- printk(KERN_ERR "%s %s Cannot find i2c handler! \n",MODNAME,__func__);
- return -ENODEV;
- }
- file_info= kzalloc(sizeof(struct BT125_FILE), GFP_KERNEL);
- if(file_info==NULL){
- printk(KERN_ERR "%s %s Cannot get memory! \n",MODNAME,__func__);
- return -ENOMEM;
- }
- //result = nonseekable_open(inode_ptr, file_ptr);
- result=generic_file_open(inode_ptr, file_ptr);
- if ( result < 0 ){
- goto End;
- }
- file_info->pbt125=i2c_get_clientdata(i2c_handler->client);
- file_ptr->private_data = file_info;
- //printk(KERN_INFO "%s %s Open file - return: %d \n",MODNAME,__func__,result);
- return result;
- End:
- kfree(file_info);
- return -ENODEV;
- }
- static int bt125_dev_release(struct inode * inode_ptr, struct file * file_ptr){
- struct BT125_FILE * file_info;
- file_info=file_ptr->private_data;
- if(file_info!=NULL)
- kfree(file_info);
- else
- printk(KERN_ERR "%s %s Handler is NULL \n",MODNAME,__func__);
- file_ptr->private_data=NULL;
- return 0;
- }
- //pool:http://stackoverflow.com/questions/20646200/how-to-implement-poll-in-linux-driver-that-notices-fd-closed
- //pool http://www.makelinux.net/ldd3/chp-6-sect-3
- //pool: !! http://www.makelinux.net/ldd3/chp-6-sect-2
- //KOD google: "wait_queue_driver.c" gauss.ececs.uc.edu
- //http://www.makelinux.net/ldd3/chp-3-sect-3
- //http://www.cs.usfca.edu/~cruse/cs686s08/
- static struct file_operations bt125_dev_file_ops ={
- .owner = THIS_MODULE,
- .open = &bt125_dev_open, //&dskel_open,
- .release = &bt125_dev_release, //&dskel_release,
- .read = &bt125_dev_read, //&dskel_read,
- .write = &bt125_dev_write, //&dskel_write,
- .poll = &bt125_poll
- // modul nepodporuje metodu llseek
- //.llseek = &no_llseek,
- };
- #ifdef CONFIG_OF
- static const struct of_device_id bt125_of_match[] = {
- {
- .compatible = "bustec,bt125",
- .data = (void *) 0,
- },
- {
- .compatible = "bustec,bt125_exp",
- .data = (void *) 0,
- },
- {
- .compatible = "bustec,bt125_adp5589",
- .data = (void *) 0,
- },
- { },
- };
- MODULE_DEVICE_TABLE(of, bt125_of_match);
- #endif /* CONFIG_OF */
- static const struct i2c_device_id bt125_ids[] = {
- { "bt125", 0, },
- { "bt125_exp", 0, },
- { "bt125_adp5589", 0, },
- { /* LIST END */ }
- };
- MODULE_DEVICE_TABLE(i2c, bt125_ids);
- struct BT_MODULE_NAME{
- char * of_name;
- char * name;
- };
- static const struct BT_MODULE_NAME BT_MODULES_NAME[]={
- {"none","none"},
- {"bustec,bt125","bt125"},
- {"bustec,bt125_exp","bt125_exp"},
- {"bustec,bt125_adp5589","bt125_adp5589"},
- { }
- };
- enum BT_MODULES{
- BT125_NONE,
- BT125_CPU,
- BT125_EXP,
- BT125_ADP5589
- };
- static int bt125_Init_exp(struct i2c_client *client){
- int ret=0;
- ret|=bt125_i2c_write_value(client,0x00,0xff);//direction A
- ret|=bt125_i2c_write_value(client,0x00,0x00);//direction B
- ret|=bt125_i2c_write_value(client,0x0d,0xff);//pull UP B
- return ret;
- }
- static int bt125_Init_ADP5889(struct i2c_client *client,unsigned char led_init){
- int ret=0;
- ret|=bt125_i2c_write_value(client,0x30,0xff);//GPIO - output
- ret|=bt125_i2c_write_value(client,BT125_ADP_OI_REG,led_init);//direction B
- return ret;
- }
- static irqreturn_t bt125_irq_handler(int irq, void *dev){
- struct bt125 *handler;
- handler=dev;
- if(dev==NULL)
- return IRQ_NONE;
- handler->data_cookie++;
- wake_up_interruptible(&handler->wait_queue);
- printk(KERN_INFO "%s %s Interrupt!!!! .\n",MODNAME,__func__);
- return IRQ_NONE;
- //return IRQ_HANDLED;
- }
- static int bt125_probe(struct i2c_client *client,const struct i2c_device_id *id){
- struct device_node *node ;
- struct bt125 *data;
- int modul;
- int result=0;
- const void * ptr;
- unsigned int irq;
- int value;
- modul=BT125_NONE;
- printk(KERN_INFO "%s Probing ... \n",MODNAME);
- node= client->dev.of_node;
- if(of_device_is_compatible(node, BT_MODULES_NAME[BT125_EXP].of_name)>0){
- printk(KERN_INFO "%s %s Compatible with bt125_exp .\n",MODNAME,__func__);
- modul=BT125_EXP;
- if(bt125_Init_exp(client)){
- printk(KERN_ERR "%s %s Cannot inicialize I2C expander device!.\n",MODNAME,__func__);
- result=-EIO;
- goto End;
- }
- }else if(of_device_is_compatible(node, BT_MODULES_NAME[BT125_CPU].of_name)>0){
- printk(KERN_INFO "%s %s Compatible with bt125 .\n",MODNAME,__func__);
- modul=BT125_CPU;
- value=bt125_i2c_read_value(client,BT125_FW_REG);
- printk(KERN_INFO "%s Version: %X \n",MODNAME,value);
- if(value<0x02){
- printk(KERN_ERR "%s %sSupport version 0x02 but get %i \n",MODNAME,__func__,value);
- result= -ENODEV;
- goto End;
- }
- bt125_i2c_write_value(client,BT125_PWR_CTRL_REG,0xff);//direction A
- }else if(of_device_is_compatible(node, BT_MODULES_NAME[BT125_ADP5589].of_name)>0){
- printk(KERN_INFO "%s %s Compatible with bt125 adp5589 .\n",MODNAME,__func__);
- modul=BT125_ADP5589;
- ptr=of_get_property(node,"led_init",NULL);
- if(ptr!=NULL){
- value=be32_to_cpup(ptr);
- printk(KERN_INFO "%s %s VALUE IS 0x%x .\n",MODNAME,__func__,value);
- bt125_Init_ADP5889(client,0xaf);
- //bt125_Init_ADP5889(client,0x9f);
- }else{
- bt125_Init_ADP5889(client,0xff);
- }
- }else{
- printk(KERN_ERR "%s %sUnknown compatible string...\n",MODNAME,__func__);
- result= -ENODEV;
- goto End;
- }
- data = devm_kzalloc(&client->dev, sizeof(struct bt125), GFP_KERNEL);
- if (!data){
- result= -ENOMEM;
- printk(KERN_INFO "%s %s Not enought memory.\n",MODNAME,__func__);
- goto End;
- }
- init_waitqueue_head(&data->wait_queue);
- if(modul==BT125_EXP){
- data->ops=bt125_keys_exp;
- }else if(modul==BT125_CPU){
- data->ops=bt125_keys_cpu;
- }else if(modul==BT125_ADP5589){
- data->ops=bt125_adp5589;
- }else{
- printk(KERN_INFO "%s %s Modul not exist %d .\n",MODNAME,__func__,modul);
- goto End;
- }
- data->client=client;
- i2c_set_clientdata(client, data);
- cdev_init(&data->cdev,&bt125_dev_file_ops);
- //alokuji minor major pary
- result = alloc_chrdev_region(&data->dev_num, MINOR(data->dev_num),DEV_COUNT, BT_MODULES_NAME[modul].name);
- if ( result < 0 ){
- // jeste nic se nealokovalo, takze neni co vracet
- printk(KERN_ERR "%s %s Cannot allocate dev pair.\n",MODNAME,__func__);
- goto End;
- }
- // vytvorime si tridu v /sys/class
- data->sys_class_ptr = class_create(THIS_MODULE, BT_MODULES_NAME[modul].name);
- if ( IS_ERR(data->sys_class_ptr) ){
- printk(KERN_ERR "%s %s Cannot create clas in /sys/class.\n",MODNAME,__func__);
- result = PTR_ERR(data->sys_class_ptr);
- goto Error_cdev;
- }
- // pridame nas modul do /sys/class/bt125_x
- data->sys_dev_ptr = device_create(data->sys_class_ptr,&client->dev, data->dev_num, NULL, BT_MODULES_NAME[modul].name);
- if ( IS_ERR(data->sys_dev_ptr) ){
- printk(KERN_ERR "%s %s Module cannot be probe to system class.\n",MODNAME,__func__);
- result = PTR_ERR(data->sys_dev_ptr);
- goto Error_SysDev;
- }
- if (IS_ERR(bt125_get_free_i2c_dev(client,MINOR(data->dev_num),MAJOR(data->dev_num)))){
- printk(KERN_ERR "%s %s Cannot add I2c client to the list.\n",MODNAME,__func__);
- result=-ENOMEM;
- goto Error_SysDev;
- }
- //vlozeni zarizeni do systemu
- result =cdev_add(&data->cdev, data->dev_num, DEV_COUNT);
- if ( result < 0 ){
- printk(KERN_ERR "%s %s Cannot add device to system.\n",MODNAME,__func__);
- goto Error_SysDev;
- }
- //Registr GPIO-IRQ
- irq=irq_of_parse_and_map(node, 0);
- if (irq != 0 ) {
- //printk("%s %s IRQ is valid:%d\n", MODNAME,__func__,irq);
- //result=devm_request_irq(&client->dev,irq,bt125_irq_handler,IRQF_TRIGGER_FALLING|IRQF_SHARED,"bt125_IRQ",data);
- result=devm_request_irq(&client->dev,irq,bt125_irq_handler,IRQF_TRIGGER_FALLING|IRQF_SHARED,"bt125_IRQ",data);
- if(result){
- printk("%s %s Failed registry IRQ:%d,Err:%d, device: %d\n", MODNAME,__func__,irq,result,client->dev.id);
- irq=0;
- }else{
- printk(KERN_INFO "%s %s Irq was activated %d\n",MODNAME,__func__,irq);
- }
- }else{
- printk(KERN_INFO "%s %s Irq is not activated \n", MODNAME,__func__);
- }
- return 0;
- Error_SysDev:
- class_destroy(data->sys_class_ptr);
- Error_cdev:
- unregister_chrdev_region(data->dev_num, DEV_COUNT);
- End:
- return result;
- }
- static int bt125_remove(struct i2c_client *client){
- struct bt125 *data;
- printk(KERN_ERR "%s:Stoper\n", __func__);
- data = i2c_get_clientdata(client);
- cdev_del(&data->cdev);
- bt125_return_i2c_dev(MINOR(data->dev_num),MAJOR(data->dev_num));
- device_destroy(data->sys_class_ptr, data->dev_num);
- class_destroy(data->sys_class_ptr);
- unregister_chrdev_region(data->dev_num, DEV_COUNT);
- return 0;
- }
- static struct i2c_driver bt125_driver = {
- .driver = {
- .name = "bt125",
- .owner = THIS_MODULE,
- //.pm = &foo_pm_ops, /* optional - power managment*/
- .of_match_table = of_match_ptr(bt125_of_match),
- },
- .id_table = bt125_ids,
- .probe = bt125_probe,
- .remove = bt125_remove,
- /* if device autodetection is needed: */
- //.class = I2C_CLASS_SOMETHING,
- //.shutdown = foo_shutdown, /* optional */
- //.command = foo_command, /* optional, deprecated */
- };
- module_i2c_driver(bt125_driver);
- MODULE_LICENSE("GPL");
- MODULE_DESCRIPTION("Driver for communicanion with 125 ");
- MODULE_VERSION("0.0.7");
- MODULE_LICENSE("GPL");
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement