TI AM335x ti am335x_tsc.c 代码跟踪
在kernel 首层目录:
先运行make ARCH=arm tags
这个作用是建立tags文件,只含有arm架构的,利用ctag即可进行跟中代码。
drivers/input/touchscreen/ti_am335x_tsc.c
看到代码最后,
module_platform_driver(ti_tsc_driver);
其实跟进入有如下定义:
#define module_platform_driver(__platform_driver) \
module_driver(__platform_driver, platform_driver_register, \
platform_driver_unregister)
其实最终有如下定义:
#define module_driver(__driver, __register, __unregister, ...) \
static int __init __driver##_init(void) \
{ \
return __register(&(__driver) , ##__VA_ARGS__); \
} \
module_init(__driver##_init); \
static void __exit __driver##_exit(void) \
{ \
__unregister(&(__driver) , ##__VA_ARGS__); \
} \
module_exit(__driver##_exit);
整合便是如下代码:
static int __init ti_tsc_driver_init(void)
{
return platform_driver_register(&(ti_tsc_driver) , ##__VA_ARGS__);
}
module_init(ti_tsc_driver_init);
static void __exit ti_tsc_driver_exit(void)
{
platform_driver_unregister(&(ti_tsc_driver) , ##__VA_ARGS__);
}
module_exit(ti_tsc_driver_exit);
相当于新版kernel将本来用做的kernel __init platform_driver_register 所有的必须做的事情通过一个module_platform_driver(driver);都做完了。
这里我们看到他注册了一个平台设备驱动,有关ti_tsc_driver。
platform_driver_register()这个函数就是将平台驱动进行了注册。
也就是说
568 int __platform_driver_register(struct platform_driver *drv,
569 struct module *owner)
570 {
571 drv->driver.owner = owner;
572 drv->driver.bus = &platform_bus_type;
573 drv->driver.probe = platform_drv_probe;
574 drv->driver.remove = platform_drv_remove;
575 drv->driver.shutdown = platform_drv_shutdown;
576
577 return driver_register(&drv->driver);
578 }
579 EXPORT_SYMBOL_GPL(__platform_driver_register);
driver_register()
drivers/base/driver.c
148 int driver_register(struct device_driver *drv)
149 {
150 int ret;
151 struct device_driver *other;
152
153 BUG_ON(!drv->bus->p);
154
155 if ((drv->bus->probe && drv->probe) ||
156 (drv->bus->remove && drv->remove) ||
157 (drv->bus->shutdown && drv->shutdown))
158 printk(KERN_WARNING "Driver '%s' needs updating - please use "
159 "bus_type methods\n", drv->name);
160 /* 验证这个驱动是否重名 */
161 other = driver_find(drv->name, drv->bus);
162 if (other) {
163 printk(KERN_ERR "Error: Driver '%s' is already registered, "
164 "aborting...\n", drv->name);
165 return -EBUSY;
166 }
167 /* 将驱动添加到总线 */
168 ret = bus_add_driver(drv);
169 if (ret)
170 return ret;
171 ret = driver_add_groups(drv, drv->groups); /* 添加到所属组 */
172 if (ret) {
173 bus_remove_driver(drv);
174 return ret;
175 }
176 kobject_uevent(&drv->p->kobj, KOBJ_ADD);
177
178 return ret;
179 }
180 EXPORT_SYMBOL_GPL(driver_register);
下面看一下ti_tsc_driver 这个驱动中包含什么东西。
553 static struct platform_driver ti_tsc_driver = {
554 .probe = titsc_probe,
555 .remove = titsc_remove,
556 .driver = {
557 .name = "TI-am335x-tsc",
558 .pm = TITSC_PM_OPS,
559 .of_match_table = ti_tsc_dt_ids,
560 },
561 };
在很早以前我写过有关平台总线相关的东西,现在想起来也记不太清了。
include/linux/platform_device.h
平台驱动结构体:
174 struct platform_driver {
175 int (*probe)(struct platform_device *);
176 int (*remove)(struct platform_device *);
177 void (*shutdown)(struct platform_device *);
178 int (*suspend)(struct platform_device *, pm_message_t state);
179 int (*resume)(struct platform_device *);
180 struct device_driver driver;
181 const struct platform_device_id *id_table;
182 bool prevent_deferred_probe;
183 };
184
185 #define to_platform_driver(drv) (container_of((drv), struct platform_driver, \
186 driver))
上面首先将probe,remove,driver,直接定义过去。
使用module_platform_driver(ti_tsc_driver); 进行注册平台驱动。
我现在假定平台驱动与设备已经match成功。
那么,他将运行他的probe 函数。
titsc_probe:
404 static int titsc_probe(struct platform_device *pdev)
405 {
406 struct titsc *ts_dev;
407 struct input_dev *input_dev;
408 struct ti_tscadc_dev *tscadc_dev = ti_tscadc_dev_get(pdev);
409 int err;
410
411 /* Allocate memory for device */
412 ts_dev = kzalloc(sizeof(struct titsc), GFP_KERNEL);
413 input_dev = input_allocate_device();
/* 申请一个输入设备结构体 */
/* 判断ts_dev input_dev 如果有不存在就报错 */
414 if (!ts_dev || !input_dev) {
415 dev_err(&pdev->dev, "failed to allocate memory.\n");
416 err = -ENOMEM;
417 goto err_free_mem;
418 }
419 /* 赋值,初始化 */
420 tscadc_dev->tsc = ts_dev;
421 ts_dev->mfd_tscadc = tscadc_dev;
422 ts_dev->input = input_dev;
423 ts_dev->irq = tscadc_dev->irq;
424 /* 解析设备树相关信息 */
425 err = titsc_parse_dt(pdev, ts_dev);
426 if (err) {
427 dev_err(&pdev->dev, "Could not find valid DT data.\n");
428 goto err_free_mem;
429 }
430 /* 绑定中断函数, */
431 err = request_irq(ts_dev->irq, titsc_irq,
432 IRQF_SHARED, pdev->dev.driver->name, ts_dev);
433 if (err) {
434 dev_err(&pdev->dev, "failed to allocate irq.\n");
435 goto err_free_mem;
436 }
437
438 if (device_may_wakeup(tscadc_dev->dev)) {
439 err = dev_pm_set_wake_irq(tscadc_dev->dev, ts_dev->irq);
440 if (err)
441 dev_err(&pdev->dev, "irq wake enable failed.\n");
442 }
443 /* 设置中断寄存器相关状态 */
444 titsc_writel(ts_dev, REG_IRQSTATUS, IRQENB_MASK);
445 titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES);
446 titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_EOS);
447 err = titsc_config_wires(ts_dev);
448 if (err) {
449 dev_err(&pdev->dev, "wrong i/p wire configuration\n");
450 goto err_free_irq;
451 }
452 titsc_step_config(ts_dev);
453 titsc_writel(ts_dev, REG_FIFO0THR,
454 ts_dev->coordinate_readouts * 2 + 2 - 1);
455
456 input_dev->name = "ti-tsc";
457 input_dev->dev.parent = &pdev->dev;
458
459 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
460 input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
461
462 input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
463 input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
464 input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0);
465
466 /* register to the input system */
467 err = input_register_device(input_dev);
468 if (err)
469 goto err_free_irq;
470
471 platform_set_drvdata(pdev, ts_dev);
472 return 0;
473
474 err_free_irq:
475 dev_pm_clear_wake_irq(tscadc_dev->dev);
476 free_irq(ts_dev->irq, ts_dev);
477 err_free_mem:
478 input_free_device(input_dev);
479 kfree(ts_dev);
480 return err;
481 }
/* 明天着重跟踪中断请求相关信息。 */