1.查找驱动
触模屏驱动fts.c
kernel/msm-4.4/drivers/input/touchscreen/st/fts.c
ST FingerTips
msm8998:/ # getevent
add device 7: /dev/input/event4
name: “fts”
X_AXIS_MAX: 1440
Y_AXIS_MAX: 2560
I2C接口:gpio_87/88 ts_i2c_sda/scl
中断:GPIO_125 TP_INT_N
复位:GPIO_89 TP_RST_N
static struct of_device_id fts_of_match_table[] = {
{
.compatible = "st,fts",
},
{},
};
在kernel/msm-4.4/arch/arm/boot/dts/qcom/msm8998-qrd-skuk-hdk.dtsi里
&i2c_5 {
status = "okay";
st_fts@49 {
compatible = "st,fts";
reg = <0x49>;
interrupt-parent = <&tlmm>;
interrupts = <125 0x2008>;
vdd-supply = <&pm8998_l6>;
avdd-supply = <&pm8998_l28>;
pinctrl-names = "pmx_ts_active", "pmx_ts_suspend";
pinctrl-0 = <&ts_active>;
pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
st,irq-gpio = <&tlmm 125 0x2008>;
st,reset-gpio = <&tlmm 89 0x00>;
st,regulator_dvdd = "vdd";
st,regulator_avdd = "avdd";
};
};
2.驱动解析
static int fts_probe(struct i2c_client *client,
const struct i2c_device_id *idp)
{
...
struct device_node *dp = client->dev.of_node;
...
if (dp) {
...
parse_dt(&client->dev, info->bdata);
}
...
info->fwu_workqueue = create_singlethread_workqueue("fts-fwu-queue");//创建workqueue,创建内核线程
//msm8998:/ # ps | grep fts-fwu-queue
root 565 2 0 0 rescuer_th 0000000000 S fts-fwu-queue
}
static int parse_dt(struct device *dev, struct fts_i2c_platform_data *bdata)
{
...
struct device_node *np = dev->of_node;
bdata->irq_gpio = of_get_named_gpio_flags(np,
"st,irq-gpio", 0, NULL);
if (of_property_read_bool(np, "st, reset-gpio")) {
bdata->reset_gpio = of_get_named_gpio_flags(np,
"st, reset-gpio", 0, NULL);
logError(0, "%s reset_gpio =%d\n", tag, bdata->reset_gpio);
} else {
bdata->reset_gpio = GPIO_NOT_DEFINED;
}
}
of_get_named_gpio_flags(np,”st,irq-gpio”, 0, NULL);
of_get_named_gpio_flags(np,”st, reset-gpio”, 0, NULL);
从dts中获取gpio
int of_get_named_gpio_flags(struct device_node *np,
const char *list_name, int index, enum of_gpio_flags *flags)
request_irq(info->client->irq, fts_interrupt_handler,
IRQF_TRIGGER_LOW, info->client->name,
info))
static irqreturn_t fts_interrupt_handler(int irq, void *handle)
{
struct fts_ts_info *info = handle;
disable_irq_nosync(info->client->irq);
queue_work(info->event_wq, &info->work);//把耗时的操作放在工作队列中断底半部
return IRQ_HANDLED;
}
INIT_WORK(&info->work, fts_event_handler);
static void fts_event_handler(struct work_struct *work)
{
input_sync(info->input_dev);//)同步用于告诉input core子系统报告结束
}