it7230触摸按键驱动

          动手写的input中断驱动(挂在i2c上)

it7230.c         

#include <linux/input.h> 
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/input-polldev.h>
#include <linux/delay.h>
#include <linux/fsl_devices.h>
#include "It7230.h"
#include <linux/time.h>


#define stage00 0x001 //menu pad
#define stage01 0x002   //back pad
#define stage02 0x004   //home pad
#define stage03 0x008
#define stage04 0x010 //
#define POLL_INTERVAL 200
#define DEVICE_NAME "it7230"
//#define DEBUG  1

u8 current_page = 1;
static int suspend_flag = 0;
static struct workqueue_struct *it7230_wq;
static struct work_struct it7230_work;
static  int globle_irq;
//init it7230 register
const sInitCapSReg  asInitCapSReg[] = {
{ PAGE_1,  CAPS_PCR     ,0x0001}, 
{ PAGE_1,  CAPS_PSR     ,0x0001}, 
{ PAGE_1,  CAPS_PMR      ,0x0000},
{ PAGE_1,  CAPS_RTR      ,0x0000},
{ PAGE_1,  CAPS_CTR      ,0x0000},
{ PAGE_1,  CAPS_CRMR     ,0x0020},
{ PAGE_1,  CAPS_PDR      ,0x1FFF},
{ PAGE_1,  CAPS_DR       ,0x0050},
{ PAGE_1,  CAPS_S0CR    ,0xC021},
{ PAGE_1,  CAPS_S1CR    ,0xC043},
{ PAGE_1,  CAPS_S2CR    ,0xC097},
{ PAGE_1,  CAPS_C1COR   ,0x71B1},
{ PAGE_1,  CAPS_C2COR   ,0x71B1},
{ PAGE_1,  CAPS_C3COR   ,0x70B2},
{ PAGE_1,  CAPS_C4COR   ,0x71B2},
{ PAGE_1,  CAPS_C7COR   ,0x7AB2},
{ PAGE_1,  CAPS_C9COR   ,0x70B2},
{ PAGE_1,  CAPS_ICR0     ,0xBFBB},
{ PAGE_1,  CAPS_ICR1     ,0x0FFF},
{ PAGE_1,  CAPS_COER0    ,0xFFFF},
{ PAGE_1,  CAPS_COER1    ,0x03FF},
{ PAGE_1,  CAPS_CGCR     ,0x0001},
{ PAGE_1,  CAPS_LEDBR   ,0x0000},
{ PAGE_1,  CAPS_GPIODR   ,0x0000},
{ PAGE_1,  CAPS_GPIOOR   ,0x0000},
{ PAGE_1,  CAPS_GPIOMR   ,0x0000},
{ PAGE_1,  CAPS_GPIOLR   ,0x001C},
{ PAGE_1,  CAPS_GPIOER   ,0x0000},
{ PAGE_1,  CAPS_LEDCMR0  ,0x20DD},
{ PAGE_1,  CAPS_LEDCMR1  ,0xDDD1},
{ PAGE_1,  CAPS_LEDCMR2  ,0xDDDD},
{ PAGE_1,  CAPS_LEDCMR3  ,0x0DDD},
{ PAGE_1,  CAPS_LEDRPR   ,0x3030},
{ PAGE_1,  CAPS_LEDBR    ,0x001F},
{ PAGE_1,  CAPS_LEDCGCR  ,0x0000},
{ PAGE_1,  CAPS_LEDPR0   ,0x2244},
{ PAGE_1,  CAPS_LEDPR1   ,0x4442},
{ PAGE_1,  CAPS_LEDPR2   ,0x4444},
{ PAGE_1,  CAPS_LEDPR3   ,0x0444},
{ PAGE_1,  CAPS_GPIOMSR  ,0x001C},
{ PAGE_0,  CAPS_S0DLR   ,0x8000},
{ PAGE_0,  CAPS_S0OHCR  ,0x0700},
{ PAGE_0,  CAPS_S0OLCR  ,0x7000},
{ PAGE_0,  CAPS_S0SR    ,0xCC88},
{ PAGE_0,  CAPS_S1DLR   ,0x8000},
{ PAGE_0,  CAPS_S1OHCR  ,0x0700},
{ PAGE_0,  CAPS_S1OLCR  ,0x7000},
{ PAGE_0,  CAPS_S1SR    ,0xCC88},
{ PAGE_0,  CAPS_S2DLR   ,0x8000},
{ PAGE_0,  CAPS_S2OHCR  ,0x0700},
{ PAGE_0,  CAPS_S2OLCR  ,0x7000},
{ PAGE_0,  CAPS_S2SR    ,0xCC88},
{ PAGE_0,  CAPS_SXCHAIER ,0x0000},
{ PAGE_0,  CAPS_SXCHRIER ,0x0000},
{ PAGE_0,  CAPS_SXCLAIER ,0x0000},
{ PAGE_0,  CAPS_SXCLRIER ,0x0000},
{ PAGE_1,  CAPS_GPIONPCR ,0x1FFF},
{ PAGE_1,  CAPS_CFER     ,0x4000},
{ PAGE_1,  CAPS_PCR      ,0x2C06}
};


struct capsTouch {
 //const struct ov5642_platform_data *platform_data;
 //struct v4l2_int_device *v4l2_int_device;
 struct i2c_client *i2c_client;
 //struct v4l2_pix_format pix;
 //struct v4l2_captureparm streamcap;
 //bool on;
        int (*get_key_status) (int);
} it7230_data;
static struct input_dev *it7230_idev;
//static struct input_polled_dev *it7230_idev;

extern void it7230_i2c_clk(void);
extern void it7230_i2c_gpio_low(void);

static int it7230_probe(struct i2c_client *client,
    const struct i2c_device_id *device_id);
static int it7230_remove(struct i2c_client *client);
static int it7230_suspend(struct i2c_client *client, pm_message_t state);
static int it7230_resume(struct i2c_client *client);
static s32 it7230_read_reg(u8 reg);
static s32 it7230_write_reg(u8 reg, u16 val);
//static void it7230_dev_poll(struct input_dev *it7230_idev);


void it7230_delay(int ms)
{
  if(suspend_flag)
    udelay(1000*ms);//suspend use udelay
  else
    msleep(ms); 
}

static const struct i2c_device_id it7230_id[] = {
 {"it7230", 0},
 {},
};
MODULE_DEVICE_TABLE(i2c, it7230_id);

static struct i2c_driver it7230_i2c_driver = {
 .driver = {
    .owner = THIS_MODULE,
    .name  = "it7230",
    },
 .probe  = it7230_probe,
 .remove = it7230_remove,
        .suspend = it7230_suspend,
 .resume = it7230_resume,
 .id_table = it7230_id,
};

/*reset it7230 when i2c clk always high if press three keys.
pull i2c1_scl pin low for 4ms,it7230 ic will reset*/
void reset_it7230_i2c(void)
{
 //struct i2c_adapter *adap = it7230_data.i2c_client->adapter;
 //rt_mutex_lock(&adap->bus_lock);//get real time mutex lock
        it7230_i2c_gpio_low();//pull low the i2c1_scl pin
   #ifdef DEBUG
        printk("it7230 i2c reset\n");
   #endif
        //msleep(10);
        it7230_delay(15);//delay 10ms
        it7230_i2c_clk();
        //rt_mutex_unlock(&adap->bus_lock);
}
//write i2c
static s32 it7230_write_reg(u8 reg, u16 val)
{
 s32 ret = 0;
 int retry = 3;
 do {
  ret = i2c_smbus_write_word_data(it7230_data.i2c_client,reg,val);
  if(!retry--)
                {
                   pr_err("%s:write reg error:page=%x,reg=%x,val=%x\n",
   __func__, current_page,reg, val);
                  reset_it7230_i2c();
    break;
                }
 }while(ret < 0);
 return ret;
}
//read i2c
static s32 it7230_read_reg(u8 reg)
{
 s32 ret = 0;
 //int retry = 3;
 /*do {
  ret = i2c_smbus_read_word_data(it7230_data.i2c_client,reg);
  if(!retry--)
                {
                   pr_err("%s:read reg error:page=%x,reg=%x,val=%x\n",
   __func__, current_page,reg, ret);
                  reset_it7230_i2c();
    break;
                }
 }while(ret < 0);*/
 //for it7230 reset quickly,reduce read time
        ret = i2c_smbus_read_word_data(it7230_data.i2c_client,reg);
        if((ret > 0x00ff)||(ret < 0))//this program,only need to read CAPS_SIR and CAPS_SXCHSR,if above 0x00ff,I think it is failed too
        {
    pr_err("%s:read reg error:page=%x,reg=%x,val=%x\n",
   __func__, current_page,reg, ret);
                  reset_it7230_i2c();
        }
        return ret;
}
//power on
void CapS_PowerOn(void)
{
     u8 temp = 0x00;//59
     while (temp < (sizeof(asInitCapSReg)/sizeof(sInitCapSReg)))
     {
  CapS_Write_Reg(asInitCapSReg[temp].page, asInitCapSReg[temp].reg, asInitCapSReg[temp].value);
         temp++;
         if (temp == 1)
         {
              udelay(1000);//Delay 1 ms
         }
     }   
}
//check page
void checkPage(u8 page)
{
 u16 bTempData = 0x00;
 s32 ret = 0;
 if (page != current_page)
         {
        if (page == 0x01)
               {
   bTempData = 0x01;
   ret = it7230_write_reg(CAPS_PSR,bTempData);
        }
        else
               {
   bTempData = 0x00; 
          ret = it7230_write_reg(CAPS_PSR,bTempData);
        }
        if(ret >= 0)
   current_page = page;
  }
}

s32 CapS_Write_Reg(u8 page,u8 reg, u16 val)
{
     s32 flag = 0;
 checkPage(page);
 flag = it7230_write_reg(reg,val);
 if (CAPS_PCR == reg && 1 == page && (val & 0x0001))
 {
  current_page = 0;
 } 
 return flag;
}

s32 CapS_Read_Reg(u8 page, u8 reg)
{
     s32 value;
     checkPage(page);
    value = it7230_read_reg(reg);
     if(value < 0)
  value = 0;
    #ifdef DEBUG
     printk("it7230 i2c read data:%x \n", value);
    #endif
     return value;
}

void resetIT7230(void)
{
    int i;
    CapS_PowerOn();
    for( i=0; i<200; i++)//delay 200ms
    {
         udelay(1000);
    }
    CapS_Write_Reg(PAGE_1, CAPS_RTR, 0x005f);//me must set the value ??.
    CapS_Write_Reg(PAGE_1, CAPS_CTR, 0x001f);
    CapS_Write_Reg(PAGE_1, CAPS_CFER, 0xC000);
    CapS_Read_Reg(PAGE_0, CAPS_SIR);//To clear contact interrupts if any.
    CapS_Write_Reg(PAGE_0, CAPS_SXCHAIER, 0x0007);
        CapS_Write_Reg(PAGE_0, CAPS_SXCHRIER, 0x0007);
    //CapS_Write_Reg(PAGE_0, CAPS_SXCLAIER, 0x0000);
}
/*******************************************
read the SXCHSR
 *****************************************/
s32 KeyPolling(void)
{
    s32 wKeyValue = 0x0000;
        //if(CapS_Read_Reg(PAGE_0,CAPS_SXCSR)&0x0007)//conversion complete?
 wKeyValue=( CapS_Read_Reg(PAGE_0,CAPS_SXCHSR)&0x0007);//|(CapS_Read_Reg(PAGE_0,CAPS_SXCLSR)&0x0007);
        return wKeyValue;

}

//
static irqreturn_t  it7230_dev_detect_handler(int irq, void *data)
{
      //printk("requst globle irq %d irq %d\n", globle_irq, irq);//debug
      disable_irq_nosync(irq);
      queue_work( it7230_wq, &it7230_work);//use queue work
      return IRQ_HANDLED;
}

//work to schedule
static void it7230_ts_poscheck(struct work_struct *work)
{
     //struct timeval tpstart,tpend;
     //int timeuse;
     //do_gettimeofday(&tpstart);
      u32 ButtonValue = 0x0000;
      static u32 lastButtonValue = 0;
      //int PinStatus;
     //struct mxc_ite_platform_data *plat = it7230_data.i2c_client->dev.platform_data;
    
      //it7230_data.get_key_status = plat->get_pins;
    //PinStatus = it7230_int_pin_getstatus(0);
    //printk("pin status:%x",PinStatus);

      ButtonValue = KeyPolling();//CapS_Read_Reg(PAGE_0,CAPS_SXCHSR)&0x0007;
   #ifdef DEBUG
      printk("ButtonValue:%x",ButtonValue);
   #endif
       
        if( (ButtonValue!=7) && (ButtonValue!=3) && (ButtonValue!=5) && (ButtonValue!=6))
       {
 if(lastButtonValue != ButtonValue)
    {
       u32 tmpLastButtonValue = lastButtonValue;
       u32 tmpButtonValue     =  ButtonValue;
       lastButtonValue = ButtonValue;
       tmpButtonValue ^= tmpLastButtonValue;

       if(tmpButtonValue & stage00)
       {
    if(ButtonValue & stage00)
         input_event(it7230_idev, EV_KEY, 0x8b, 1);//menu pad
    else
         input_event(it7230_idev, EV_KEY, 0x8b, 0);//menu pad
       }

      if(tmpButtonValue & stage01)
      {
    if(ButtonValue & stage01)
         input_event(it7230_idev, EV_KEY, 0x9e, 1);//back pad
    else
                input_event(it7230_idev, EV_KEY, 0x9e, 0);//back pad
      }
    
      if(tmpButtonValue & stage02)
      {
    if(ButtonValue & stage02)
         input_event(it7230_idev, EV_KEY, 0x66, 1);//home pad
    else
         input_event(it7230_idev, EV_KEY, 0x66, 0);//home pad
      }
          
       input_sync(it7230_idev);
     
   }
      }
      //do_gettimeofday(&tpend);
      //timeuse = 1000000*(tpend.tv_sec - tpstart.tv_sec) + tpend.tv_usec - tpstart.tv_usec;
      //timeuse /= 1000;//ms
      //printk("used time:%d\n",timeuse);

       enable_irq(globle_irq);
}

static int it7230_probe(struct i2c_client *client,
    const struct i2c_device_id *device_id)
{

        int ret,i;
 it7230_data.i2c_client = client;
 resetIT7230();
        for(i=0; i<200; i++)//delay 200ms
 {
     udelay(1000);
        }

 /*input device register */
 it7230_idev = input_allocate_device();
 if (!it7230_idev)
 {
  dev_err(&client->dev, "alloc input device failed!\n");
  ret = -ENOMEM;
  //goto error_rm_hwmon_dev;
 }
        INIT_WORK(&it7230_work, it7230_ts_poscheck);

 //it7230_idev->poll = it7230_dev_poll;
 //it7230_idev->poll_interval = POLL_INTERVAL;
 /*idev = it7230_idev->input;*/
 it7230_idev->name = DEVICE_NAME;
 it7230_idev->id.bustype = BUS_I2C;
 it7230_idev->dev.parent = &client->dev;
 it7230_idev->evbit[0] = BIT_MASK(EV_KEY);
        input_set_capability(it7230_idev,EV_KEY,0x8b);//menu pad
        input_set_capability(it7230_idev,EV_KEY,0x9e);//back pad
        input_set_capability(it7230_idev,EV_KEY,0x66);//home pad
 ret = input_register_device(it7230_idev);
 if (ret)
 {
  dev_err(&client->dev, "register device failed!\n");
  //goto error_free_poll_dev;
 }
        globle_irq = client->irq;
        if(client->irq)
        {
           //ret = request_irq(client->irq, it7230_dev_detect_handler, IRQF_TRIGGER_FALLING, DEVICE_NAME, &it7230_data);
               ret = request_irq(client->irq, it7230_dev_detect_handler, IRQF_TRIGGER_LOW, DEVICE_NAME, &it7230_data);
           if(ret < 0)
           {
              dev_warn(&client->dev, "error:it7230 can not requst irq %d\n", client->irq);
           }
           else
               printk("it7230 can requst irq %d\n", client->irq);
        }
     return ret;
}

static int it7230_remove(struct i2c_client *client)
{
 input_unregister_device(it7230_idev);
 input_free_device(it7230_idev);
 return 0;
}
static int it7230_suspend(struct i2c_client *client, pm_message_t state)
{
 suspend_flag = 1;
        CapS_Write_Reg(PAGE_1, CAPS_PMR, 0x0008);//idle mode
 printk("it7230 SUSPEND\n");
 return 0;
}
//need init register after resume
static int it7230_resume(struct i2c_client *client)
{
 int i;
        suspend_flag = 0;
        //CapS_Write_Reg(PAGE_1, CAPS_PMR, 0x0000);//active mode
        resetIT7230();
        for(i=0; i<200; i++)//delay 200ms
 {
     udelay(1000);
        }
 return 0;
}

static __init int it7230_init(void)
{
 u8 err;

 err = i2c_add_driver(&it7230_i2c_driver);
 if (err != 0)
  pr_err("%s:driver registration failed, error=%d \n",
   __func__, err);
 it7230_wq = create_singlethread_workqueue("it7230_wq");
 return err;
}

/*
 * @return  Error code indicating success or failure
 */
static void __exit it7230_clean(void)
{
 i2c_del_driver(&it7230_i2c_driver);
        if(it7230_wq)
 destroy_workqueue(it7230_wq);
}

module_init(it7230_init);
module_exit(it7230_clean);

MODULE_AUTHOR("GAEA, Inc.");
MODULE_DESCRIPTION("it7230 cap sensor touch driver");
MODULE_LICENSE("GPL");
MODULE_VERSION("1.0");

 

在mx51_babbage.c中,一些gpio操作函数和i2c注册

//envi20110825 +<< change gpio
void it7230_i2c_clk(void)
{
        gpio_free(BABBAGE_IT7230_I2C1_GPIO);
 iomux_v3_cfg_t  i2c_clk = MX51_PAD_EIM_D19__I2C1_SCL;
        mxc_iomux_v3_setup_pad(i2c_clk);
}
EXPORT_SYMBOL(it7230_i2c_clk);

void it7230_i2c_gpio_low(void)
{
  iomux_v3_cfg_t  i2c_gpio = MX51_PAD_EIM_D19__GPIO2_3;
        mxc_iomux_v3_setup_pad(i2c_gpio);
        gpio_request(BABBAGE_IT7230_I2C1_GPIO, "it7230-gpio");
 gpio_direction_output(BABBAGE_IT7230_I2C1_GPIO, 0);
 gpio_set_value(BABBAGE_IT7230_I2C1_GPIO, 0);
}
EXPORT_SYMBOL(it7230_i2c_gpio_low);
//envi

//envi20110809++ <<
static int it7230_int_pin_getstatus(int id)
{
 return gpio_get_value(BABBAGE_IT7230_INT_PIN);
};
EXPORT_SYMBOL(it7230_int_pin_getstatus);
static struct mxc_ite_platform_data  it7230_pin_data = {
 .get_pins = it7230_int_pin_getstatus,
};
//envi20110809++ >>
static struct i2c_board_info mxc_i2c0_board_info[] __initdata = {
 {
 .type = "it7230",
 .addr = 0x46,
         .irq = gpio_to_irq(BABBAGE_IT7230_INT_PIN), 
 .platform_data =(void *)&it7230_pin_data,
 },

 

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值