在没有设备树的情况下,需要手动注册 platform 设备,下面分别注册platform 设备 和 platform 驱动,以此来驱动LED。
一、platform 设备注册
新建文件 led-device.c 文件,该文件保存的是外设信息,在当前背景下便是 LED 相关的寄存器信息,该文件最终会被编程成 ko 模块文件,加入到 Linux 内核中。
1、注册 / 注销 platform 设备
在 Linux 内核中使用 platform_device 类型来表示 platform 设备,platform_device 类型的实例化对象为 leddevice,重点是 name、num_resources、resource 成员的初始化:
- name:platform设备名,用于和下面 platform 驱动进行匹配
- release:dev 成员下的 release 函数,当platform 设备从内核移除时调用
- num_resources:resource 数组的资源个数(数组中元素个数)
- resource:资源数组,每一个元素都对应一个寄存器的相关信息
static struct platform_device leddevice = {
.name = "imx6ull-led",
.id = -1,
// .dev = {
// .release = led_release,
// },
.num_resources = ARRAY_SIZE(led_resources),
.resource = led_resources,
};
static int __init leddevice_init(void)
{
return platform_device_register(&leddevice);
}
static void __exit leddevice_exit(void)
{
platform_device_unregister(&leddevice);
}
module_init(leddevice_init);
module_exit(leddevice_exit);
2、resource 数组定义
现定义一个 resource 类型的数组,数组名为 led_resources,数组中的每一个元素都对应一个寄存器。resource 类型数组成员的解析放在上一篇。
#define CCM_CCGR1_BASE 0x20C406C // 时钟源
#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03_BASE 0x20E0068 // IO 复用
#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03_BASE 0x20E02F4 // 复用引脚初始化
#define GPIO1_GDIR_BASE 0x209C004 // 输出方向
#define GPIO1_DR_BASE 0x209C000 // LED输出引脚
#define REGISTER_LENGTH 0x04 // 寄存器地址长度
static struct resource led_resources[] = {
[0] = {
.start = CCM_CCGR1_BASE,
.end = CCM_CCGR1_BASE + REGISTER_LENGTH - 1,
.flags = IORESOURCE_MEM
},
[1] = {
.start = IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03_BASE,
.end = IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03_BASE + REGISTER_LENGTH - 1,
.flags = IORESOURCE_MEM
},
[2] = {
.start = IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03_BASE,
.end = IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03_BASE + REGISTER_LENGTH - 1,
.flags = IORESOURCE_MEM
},
[3] = {
.start = GPIO1_GDIR_BASE,
.end = GPIO1_GDIR_BASE + REGISTER_LENGTH - 1,
.flags = IORESOURCE_MEM
},
[4] = {
.start = GPIO1_DR_BASE,
.end = GPIO1_DR_BASE + REGISTER_LENGTH - 1,
.flags = IORESOURCE_MEM
},
};
3、完整 platform 设备注册
#include <linux/types.h>
#include <linux/ker