1. 程式人生 > >android 串列埠擴充套件(wk2xxx)移植

android 串列埠擴充套件(wk2xxx)移植


1.驅動移植
 將wk2xxx_i2c.c wk2xxx.h 放到lichee\linux-3.4\drivers\hwmon目錄下
1.makefile
obj-$(CONFIG_SERIAL_I2C_WK2XXX) += wk2xxx_i2c.o
2. kconfig
 config SERIAL_I2C_WK2XXX
tristate "i2c to 4 uart for wk2xxx chips "
select I2C  
select SERIAL_CORE
depends on HWMON
default m
help
i2c to 4 uart for wk2xxx chips
說明:由於是串列埠擴充套件,所以需要選擇 SERIAL_CORE,基於i2c,所以要select i2c


3.i2c irq中斷配置
在sysconfig.fex中新增相關的io配置
;-------------------------------------------------------------------------------
;wk2 irq configuration
;-------------------------------------------------------------------------------
[wk2_para]
wk2_used            = 1
wk2_twi_id          = 1
wk2_twi_addr        = 0x10
wk2_freq            = 400000
wk2_irq_port        = port:PI16<6><default><default><default>




4.驅動程式碼的移植
4.1. init函式
在這個函式中首先要獲取sysconfig中的相關的配置,同時將設備註冊到相應的i2c總線上
int ret;
printk("wk2xxx_init-------------------------\n");
        int retval;
ret=wk2xxx_fetch_sysconfig_para();
if(ret < 0){
printk("wk2xxx_fetch_sysconfig_para failed in init \n");
}
// wk2xxx_i2c_driver.detect = wk2xxx_detect;
        struct i2c_board_info info;
      struct i2c_adapter *adapter;
      struct i2c_client *client;
 memset(&info, 0, sizeof(struct i2c_board_info));
 info.addr = 0x10;
  strlcpy(info.type, "wk2xxx_i2c", I2C_NAME_SIZE);
  adapter = i2c_get_adapter(1);

  if (!adapter) {
  printk("*******get_adapter error!********\n");
  }
  client = i2c_new_device(adapter, &info);
 wk2xxx_detect(client, &info);



/*   i2c_add_driver(&msg21xx_ts_driver);
  if (msg21xx_device_check == 0) {
  i2c_del_driver(&msg21xx_ts_driver);
  printk("msg21xx_device_check is 0 =========================\n");
  }
  return ret;
struct i2c_board_info bi = {I2C_BOARD_INFO("wk2xxx_i2c", 0x10),};
i2c_new_device(i2c_get_adapter( wk2xxx_i2c_pdata.bus_num), &bi);
*/    
 retval = i2c_add_driver(&wk2xxx_i2c_driver);
if (retval !=0)
{
printk("======wk2xxx_i2c_driver init fail, ret=0x%x======\n", retval);
i2c_del_driver(&wk2xxx_i2c_driver);
return ret;
}






static int wk2xxx_detect(struct i2c_client *client, struct i2c_board_info *info)
{
printk("wk2xxx_detect-----\n");
struct i2c_adapter *adapter = client->adapter;
int ret;


        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
                return -ENODEV;


if(twi_id == adapter->nr){
                printk("%s: addr= %x\n",__func__,client->addr);
               ret = i2c_test(client);
                if(!ret){
        printk("%s:I2C connection might be something wrong \n",__func__);
        return -ENODEV;
       
}else{
strlcpy(info->type, "wk2xxx_i2c", I2C_NAME_SIZE);
return 0;
       }



}else{
return -ENODEV;
}
}




4.2 獲取配置檔案相關資訊函式


static int wk2xxx_fetch_sysconfig_para(void){
printk("wk2xxx_fetch_sysconfig_para-------------------\n");
int ret =  -1;
int i = -1;
int device_used = -1;
script_item_u val;
script_item_value_type_e  type;
type = script_get_item("wk2_para", "wk2_used", &val);
 if(SCIRPT_ITEM_VALUE_TYPE_INT != type){
  printk("%s, type err device_used =%d \n", __func__, val.val);
goto script_get_err;
  }
device_used = val.val;
if(1 == device_used){
type = script_get_item("wk2_para", "wk2_twi_id", &val);
if(SCIRPT_ITEM_VALUE_TYPE_INT != type){
printk("%s: type err twi_id = %d. \n", __func__, val.val);
goto script_get_err;
  }
  wk2xxx_i2c_pdata.bus_num = val.val;
printk("wk2xxx_i2c_pdata.bus_num =%d\n",wk2xxx_i2c_pdata.bus_num);
  
  type = script_get_item("wk2_para", "wk2_twi_addr", &val);
if(SCIRPT_ITEM_VALUE_TYPE_INT != type){
printk("%s: type err twi_id = %d. \n", __func__, val.val);
goto script_get_err;
  }
  wk2xxx_i2c_pdata.slave_addr = val.val;   
  
  printk("wk2xxx_i2c_pdata.slave_addr =%d\n",wk2xxx_i2c_pdata.slave_addr);


  
  type = script_get_item("wk2_para", "wk2_freq", &val);   
  if(SCIRPT_ITEM_VALUE_TYPE_INT != type){
printk("%s: type err twi_id = %d. \n", __func__, val.val);
  goto script_get_err;
 }
 wk2xxx_i2c_pdata.frequency = val.val;
 printk("wk2 frequency=%d\n",wk2xxx_i2c_pdata.frequency);
 
type = script_get_item("wk2_para", "wk2_irq_port", &val);
if (type != SCIRPT_ITEM_VALUE_TYPE_PIO) {
printk("get uarts IO(uart_irq) failed\n");
goto script_get_err;
}
                      int_number= val.gpio.gpio;
printk("wk2 int_number=%d\n",int_number);
/* i =  i2c_register_board_info( wk2xxx_i2c_pdata.bus_num, wk2xxx_i2c_board_info,
 ARRAY_SIZE(wk2xxx_i2c_board_info));
if(i < 0){
printk("wk2 register i2c device failed \n");
goto script_get_err;
}*/
printk("wk2xxx_fetch_sysconfig_para--is ok----------\n");
  return 0;
  
  }else{


printk("wk2xxx get sysconfig failed \n");
ret = -1;
  }
script_get_err:
printk("get erro");
return ret;
 


}


4.3 構建board info
static struct wk2xxx_platform_data  wk2xxx_i2c_pdata = {
.flag  = 0,
};


4.4 中斷函式的修改
由於a20對中斷函式進行了重新的封裝,所以要對應平臺函式為
 if(sw_gpio_irq_request(s->port.irq, TRIG_EDGE_NEGATIVE , (peint_handle)wk2xxx_irq, s) <0)
同時使能和關閉中斷函式也要分別進行修改
 //disable_irq_nosync(s->port.irq);
      --------》  sw_gpio_eint_set_enable(s->port.irq, 0);


  //enable_irq(s->port.irq);
 ===========》           sw_gpio_eint_set_enable(s->port.irq, 1);




/static irqreturn_t wk2xxx_irq(int irq, void *dev_id)//
----------------》static u32 wk2xxx_irq(struct wk2xxx_port  *dev_id){
return 0;
}


4.5 還有就是一些標頭檔案的修改了


4.6 編譯成ko 或者build-in都ok,如果是ko,在android init 的時候記得要insod






5.總結的關鍵點
1.a20的對中斷函式進行了重新的封裝,對應於程式碼中要注意這一系列函式的引數以及
返回值的使用
2.其他就是一些細節問題了
3.最開始除錯的是uart to uart 但是datasheet對於暫存器的設定流程基本無描述。
所以這個是非常難的一個部分