static int __devinit msg21xx_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
int err = 0;
int ret = 0;
int retval = 0;
int rc =0;
unsigned char dbbus_tx_data[3];
int cnt = 0;
struct msg21xx_ts_data *msg;
// modified by yangze for hardware devices info (x310) 2013-10-11 begin
/* Added by zengguang to increase TP hardware info. (X211) 2013.5.5 */
#ifdef CONFIG_GET_HARDWARE_INFO
u8 dbbus_tx_data[3];
u8 dbbus_rx_data[4]={0};
dbbus_tx_data[0] = 0x53;
dbbus_tx_data[1] = 0x00;
dbbus_tx_data[2] = 0x2A;
#endif
/* Added by zengguang to increase TP hardware info. (X211) 2013.5.5 */
// modified by yangze for hardware devices info (x310) 2013-10-11 end
#ifdef __FIRMWARE_UPDATE__
// struct platform_device *pdev;
#endif
msg21xx_i2c_client = client;
TP_DEBUG (" \n");
if (!i2c_check_functionality(msg21xx_i2c_client->adapter, I2C_FUNC_I2C)) //用来判定设配器的能力,函数用于返回algorithm所支持的通信协议,比如I2C_FUNC_I2C,I2C_FUNC_10BIT_ADDR等 及sys/bus/i2c/devices下的设备
{
printk("I2C check functionality failed.");
return -ENODEV; //没找到I2C设备
}
#ifdef __CHIP_MSG_2133A__
dbbus_tx_data[0] = 0x53;
dbbus_tx_data[1] = 0x00;
dbbus_tx_data[2] = 0x2A;
#else
dbbus_tx_data[0] = 0x53;
dbbus_tx_data[1] = 0x00;
dbbus_tx_data[2] = 0x74;
#endif
// printk("<0>""111111111 wax->%s\n",__FUNCTION__);
TP_DEBUG (" i2cseq start\n");
#if 1
loop: err = HalTscrCDevWriteI2CSeq(FW_ADDR_MSG20XX_TP, &dbbus_tx_data[0], 3); //i2c 收发数据
TP_DEBUG (" i2cseq err is %d\n",err);
// printk("msg2138 msg21xx_ts_probe err = %d\n",err);
if (err < 0) {
cnt++;
if (cnt == 5)
return -ENODEV;
goto loop;
}
TP_DEBUG (" i2cseq end\n");
// printk("<0>""222222222 wax->%s\n",__FUNCTION__);
#endif
if (msg21xx_i2c_client->dev.of_node) { //判断设备节点是否存在
msg = devm_kzalloc(&msg21xx_i2c_client->dev, //devm_kzalloc:为i2c设备pdev 的私有数据分配内存,长度struct octeon_mdiobus的长度
sizeof(*msg),
GFP_KERNEL); //GFP_KERNEL是内核内存分配时最常用的,无内存可用时可引起休眠。
if (!msg) {
dev_err(&msg21xx_i2c_client->dev, "Failed to allocate memory\n");
return -ENOMEM;
}
memset(msg, 0, sizeof(*msg));
retval = msg21xx_parse_dt(&msg21xx_i2c_client->dev, msg);
if (retval)
return retval;
} else {
msg = kzalloc(sizeof(*msg), GFP_KERNEL); //用kzalloc申请内存的时候, 效果等同于先是用 kmalloc() 申请空间 , 然后用 memset() 来初始化 ,所有申请的元素都被初始化为 0.
}
if (gpio_is_valid(msg->irq_gpio)) 判断GPIO是否有效,有效返回0
{
/* configure touchscreen irq gpio */
retval = gpio_request(msg->irq_gpio, "msg21xx_irq_gpio"); 其原型为 int gpio_request(unsigned gpio, const char *label) 先说说其参数,gpio则为你要申请的哪一个管脚,label则是为其取一个名字。debugfs有效,一个/sys/kernel/debug/gpio文件在那里将被找到
if (retval)
{
printk("unable to request gpio [%d]\n",msg->irq_gpio);
return retval;
}
}
if (gpio_is_valid(msg->reset_gpio))
{
/* configure touchscreen reset out gpio */
retval = gpio_request(msg->reset_gpio,"msg21xx_reset_gpio");
if (retval)
{
printk("unable to request gpio [%d]\n",msg->reset_gpio);
return retval;
}
}
msg21xx_irq= gpio_to_irq(msg->irq_gpio); /*Added by liumx for tp irq 2013.11.22*/ // gpio_to_irq()返回的中断编号可以传给request_irq()和free_irq()。内核通过调用该函数将gpio端口转换为中断,在用户空间也有类似方法
msg->vdd = regulator_get(&msg21xx_i2c_client->dev, "vdd"); //dev 是设备“Vcc”一个字符串代表,校准器(regulator)然后返回一个指针,也是regulator_put(regulator)使用的。
if (IS_ERR(msg->vdd))
printk("regulator_get vdd fail");
ret=regulator_set_voltage(msg->vdd, 2850000, 2850000); //int regulator_set_voltage(regulator, int min_uV, int max_uV); 消费者可以申请提供给它们的电压
if(ret){
printk("regulator_set_voltage vdd fail ");
return ret;
}
/*
msg->vcc_i2c = regulator_get(&msg21xx_i2c_client->dev, "vcc_i2c");
if (IS_ERR(msg->vcc_i2c)) {
rc = PTR_ERR(msg->vcc_i2c);
dev_err(&msg21xx_i2c_client->dev,
"Regulator get failed vcc_i2c rc=%d\n", rc);
}
if (regul