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

前几天做矩阵键盘驱动移植,虽然步骤简单还是来记录下,顺便整理下思路。贵人多忘事  虽然咱不是贵人也记性不好啊

水平有限,此文档只供自己参考,但也欢迎扔砖

2.6.38 中6410键盘接口驱动对应的是 samsung-keypad.c位于driver/input/keyboard目录。

另外 Dev-key.c 定义了keypad设备 samsung_device_keypad,及resource samsung_keypad_resources。

除此之外还有系统板文件 mach-mini6410.c,把 samsung_device_keypad 设备加入 mini6410_devices数组,及开机时设置键盘参数 samsung_keypad_set_platdata。

系统开机后调用 mini6410_machine_init(void) 函数 ,在此函数中调用了

 

platform_add_devices(mini6410_devices, ARRAY_SIZE(mini6410_devices));像系统添加了一系列平台设备,我们把keypad设备也加到数组中

 

&s3c_device_fimc1,

&s3c_device_g2d,

&s3c_device_g3d,

#endif

&samsung_device_keypad,

 

而这个keypad设备定义是在 Dev-key.c中 注册为平台设备
struct platform_device samsung_device_keypad = {
.name = "samsung-keypad",
.id = -1,
.num_resources = ARRAY_SIZE(samsung_keypad_resources),
.resource = samsung_keypad_resources,
};
KEYPAD设备资源同样定义在 Dev-keypad.c中 
static struct resource samsung_keypad_resources[] = {
[0] = {
.start = SAMSUNG_PA_KEYPAD,
.end = SAMSUNG_PA_KEYPAD + 0x20 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_KEYPAD,
.end = IRQ_KEYPAD,
.flags = IORESOURCE_IRQ,
},
};
mini6410_machine_init函数把 设备keypad设备加入系统后调了
samsung_keypad_set_platdata(&smdk6410_keypad_data);
 对设备参数进行了初始化 
static struct samsung_keypad_platdata smdk6410_keypad_data __initdata = {
.keymap_data = &smdk6410_keymap_data, //按键映射表
.rows = 2, //矩阵键盘行数
.cols = 2, //矩阵键盘列数
};
按键映射表是上传事件报告中用到的,具体后面再来讨论。呵呵 其实我也没看到
在 Dev-keypad.c中 
void __init samsung_keypad_set_platdata(struct samsung_keypad_platdata *pd)
{
struct samsung_keypad_platdata *npd;
//此函数就是把 smdk6410_keypad_data 复制了一份给了 samsung_device_keypad->dev.platform_data
npd = s3c_set_platdata(pd, sizeof(struct samsung_keypad_platdata),
&samsung_device_keypad);
//配置矩阵键盘接口用到的 GPIO
if (!npd->cfg_gpio)
npd->cfg_gpio = samsung_keypad_cfg_gpio;
}
在setup-keypad.c中 
void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols)
{
/* Set all the necessary GPK pins to special-function 3: KP_ROW[x] */
// s3c_gpio_cfgrange_nopull(S3C64XX_GPK(8), rows, S3C_GPIO_SFN(3));
//从GPN0开始的rows个端口设置为功能三 即键盘接口
s3c_gpio_cfgrange_nopull(S3C64XX_GPN(0), rows, S3C_GPIO_SFN(3));
/* Set all the necessary GPL pins to special-function 3: KP_COL[x] */
// s3c_gpio_cfgrange_nopull(S3C64XX_GPL(0), cols, S3C_GPIO_SFN(3));
s3c_gpio_cfgrange_nopull(S3C64XX_GPH(0), cols, S3C_GPIO_SFN(3));
}
6410 键盘接口可以用 K/L口或 N/H口
到此 divice 工作基本完成 。  休息下。
  linux 2.6设备驱动模型中,关心总线、设备、驱动这三个实体,总线将设备和驱动绑定。上面我们向内核添加了设备,下面我们来看是如何添加驱动及驱动是如何和设备绑定的。
我们来看 samsung-keypad.c  samsung_keypad_init中注册了平台设备驱动 samsung_keypad_driver
static int __init samsung_keypad_init(void)
{
return platform_driver_register(&samsung_keypad_driver);
}
module_init(samsung_keypad_init);
 samsung_keypad_driver定义如下,
static struct platform_driver samsung_keypad_driver = {
.probe = samsung_keypad_probe,
.remove = __devexit_p(samsung_keypad_remove),
.driver = {
.name = "samsung-keypad",
.owner = THIS_MODULE,
#ifdef CONFIG_PM
.pm = &samsung_keypad_pm_ops,
#endif
},
.id_table = samsung_keypad_driver_ids,
};
其中 .name = "samsung-keypad",必须和设备
struct platform_device samsung_device_keypad = {
.name = "samsung-keypad",
一致,这是为什么呢?  估计是 platform_driver_register 注册时查找与之匹配的设备时用到,
/**
 * platform_driver_register - register a driver for platform-level devices
 * @drv: platform driver structure
 */
int platform_driver_register(struct platform_driver *drv)
{
drv->driver.bus = &platform_bus_type;
if (drv->probe)
drv->driver.probe = platform_drv_probe;
if (drv->remove)
drv->driver.remove = platform_drv_remove;
if (drv->shutdown)
drv->driver.shutdown = platform_drv_shutdown;
return driver_register(&drv->driver);
}
晕 没做什么事就 用转到了 driver_register(&drv->driver); 只能看看driver_register做了些啥东东
/**
 * driver_register - register driver with bus
 * @drv: driver to register
 *
 * We pass off most of the work to the bus_add_driver() call,
 * since most of the things we have to do deal with the bus
 * structures.
 */
int driver_register(struct device_driver *drv)
{
int ret;
struct device_driver *other;
BUG_ON(!drv->bus->p);
if ((drv->bus->probe && drv->probe) ||
   (drv->bus->remove && drv->remove) ||
   (drv->bus->shutdown && drv->shutdown))
printk(KERN_WARNING "Driver '%s' needs updating - please use "
"bus_type methods/n", drv->name);
other = driver_find(drv->name, drv->bus);
if (other) {
put_driver(other);
printk(KERN_ERR "Error: Driver '%s' is already registered, "
"aborting.../n", drv->name);
return -EBUSY;
}
//上面只是做了些正确性检查
//像总线添加了一个设备驱动
ret = bus_add_driver(drv);
if (ret)
return ret;
ret = driver_add_groups(drv, drv->groups);
if (ret)
bus_remove_driver(drv);
return ret;
}
下面来分析一下 bus_add_driver 估计此函数对搞懂设备驱动模型很重要
/**
 * bus_add_driver - Add a driver to the bus.
 * @drv: driver.
 */
int bus_add_driver(struct device_driver *drv)
{
struct bus_type *bus;
struct driver_private *priv;
int error = 0;
//向总线添加设备驱动
bus = bus_get(drv->bus);
if (!bus)
return -EINVAL;
pr_debug("bus: '%s': add driver %s/n", bus->name, drv->name);
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) {
error = -ENOMEM;
goto out_put_bus;
}
//初始化一个内核链表
klist_init(&priv->klist_devices, NULL, NULL);
priv->driver = drv;
drv->p = priv;
priv->kobj.kset = bus->p->drivers_kset;
//像链表添加对象
error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
    "%s", drv->name);
if (error)
goto out_unregister;
//driver 和 device 绑定
if (drv->bus->p->drivers_autoprobe) {
error = driver_attach(drv);
if (error)
goto out_unregister;
}
//
klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
module_add_driver(drv->owner, drv);
//创建sysfs file
error = driver_create_file(drv, &driver_attr_uevent);
if (error) {
printk(KERN_ERR "%s: uevent attr (%s) failed/n",
__func__, drv->name);
}
error = driver_add_attrs(bus, drv);
if (error) {
/* How the hell do we get out of this pickle? Give up */
printk(KERN_ERR "%s: driver_add_attrs(%s) failed/n",
__func__, drv->name);
}
if (!drv->suppress_bind_attrs) {
error = add_bind_files(drv);
if (error) {
/* Ditto */
printk(KERN_ERR "%s: add_bind_files(%s) failed/n",
__func__, drv->name);
}
}
kobject_uevent(&priv->kobj, KOBJ_ADD);
return 0;
out_unregister:
kobject_put(&priv->kobj);
kfree(drv->p);
drv->p = NULL;
out_put_bus:
bus_put(bus);
return error;
}
2011-05-13   01:06:34

你可能感兴趣的:(c,struct,Module,null,resources,structure)