mini6410 矩阵键盘接口 驱动移植 (2)

  1中讲了像内核注册了平台设备驱动,现在来查找下平台驱动中的 .probe  何时调用。

参考下大虾分析的,自己确实好是没找到哪里调用的。

do_basic_setup()->driver_init()->platform_bus_init()->...初始化platform bus(虚拟总线)
设备向内核注册的时候platform_device_register()->platform_device_add()->...内核把设备挂在虚拟的platform bus下
驱动注册的时候platform_driver_register()->driver_register()->bus_add_driver()->driver_attach()->bus_for_each_dev()对每个挂在虚拟的platform bus的设备作__driver_attach()->driver_probe_device()->drv->bus->match()==platform_match()->比较strncmp(pdev->name, drv->name, BUS_ID_SIZE),如果相符就调用platform_drv_probe()->driver->probe(),如果probe成功则绑定该设备到该驱动.

 

 

来看下samsung_keypad_probe到底做了些什么

 

 

 

static int __devinit samsung_keypad_probe(struct platform_device *pdev)

{

    const struct samsung_keypad_platdata *pdata;

    const struct matrix_keymap_data *keymap_data;

    struct samsung_keypad *keypad;

    struct resource *res;

    struct input_dev *input_dev;

    unsigned int row_shift;

    unsigned int keymap_size;

    int error;

 

pdata = pdev->dev.platform_data;

if (!pdata) {

dev_err(&pdev->dev, "no platform data defined/n");

return -EINVAL;

}

 

keymap_data = pdata->keymap_data;

if (!keymap_data) {

dev_err(&pdev->dev, "no keymap data defined/n");

return -EINVAL;

}

 

if (!pdata->rows || pdata->rows > SAMSUNG_MAX_ROWS)

return -EINVAL;

 

if (!pdata->cols || pdata->cols > SAMSUNG_MAX_COLS)

return -EINVAL;

 

/* initialize the gpio 调用 samsung_keypad_cfg_gpio*/

if (pdata->cfg_gpio)

pdata->cfg_gpio(pdata->rows, pdata->cols);

 

row_shift = get_count_order(pdata->cols);//3//

keymap_size = (pdata->rows << row_shift) * sizeof(keypad->keycodes[0]);//8*

sizeof(keypad->keycodes[0]

keypad = kzalloc(sizeof(*keypad) + keymap_size, GFP_KERNEL);

//分配输入设备

input_dev = input_allocate_device();

if (!keypad || !input_dev) {

error = -ENOMEM;

goto err_free_mem;

}

 

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

if (!res) {

error = -ENODEV;

goto err_free_mem;

}

 

keypad->base = ioremap(res->start, resource_size(res));

if (!keypad->base) {

error = -EBUSY;

goto err_free_mem;

}

 

keypad->clk = clk_get(&pdev->dev, "keypad");

if (IS_ERR(keypad->clk)) {

dev_err(&pdev->dev, "failed to get keypad clk/n");

error = PTR_ERR(keypad->clk);

goto err_unmap_base;

}

 

keypad->input_dev = input_dev;

keypad->row_shift = row_shift;

keypad->rows = pdata->rows;

keypad->cols = pdata->cols;

init_waitqueue_head(&keypad->wait);

 

input_dev->name = pdev->name;

input_dev->id.bustype = BUS_HOST;

input_dev->dev.parent = &pdev->dev;

input_set_drvdata(input_dev, keypad);

 

input_dev->open = samsung_keypad_open;

input_dev->close = samsung_keypad_close;

 

input_dev->evbit[0] = BIT_MASK(EV_KEY);

if (!pdata->no_autorepeat)

input_dev->evbit[0] |= BIT_MASK(EV_REP);

 

input_set_capability(input_dev, EV_MSC, MSC_SCAN);

 

input_dev->keycode = keypad->keycodes;

input_dev->keycodesize = sizeof(keypad->keycodes[0]);

input_dev->keycodemax = pdata->rows << row_shift;

 

matrix_keypad_build_keymap(keymap_data, row_shift,

input_dev->keycode, input_dev->keybit);

 

keypad->irq = platform_get_irq(pdev, 0);

if (keypad->irq < 0) {

error = keypad->irq;

goto err_put_clk;

}

//分配中断线

error = request_threaded_irq(keypad->irq, NULL, samsung_keypad_irq,

IRQF_ONESHOT, dev_name(&pdev->dev), keypad);

if (error) {

dev_err(&pdev->dev, "failed to register keypad interrupt/n");

goto err_put_clk;

}

 

error = input_register_device(keypad->input_dev);

if (error)

goto err_free_irq;

 

device_init_wakeup(&pdev->dev, pdata->wakeup);

platform_set_drvdata(pdev, keypad);

return 0;

 

err_free_irq:

free_irq(keypad->irq, keypad);

err_put_clk:

clk_put(keypad->clk);

err_unmap_base:

iounmap(keypad->base);

err_free_mem:

input_free_device(input_dev);

kfree(keypad);

 

return error;

}

2011-05-13 23:16:23

 

 

 
 

你可能感兴趣的:(struct,basic,input,Build,平台,Matrix)