RK30SDK开发板驱动分析(一):platform device 的概念与注册
做过51单片机或者ARM开发的人都知道,单片机内部都有自己的“片内外设”,比如UART,比如I2C,比如SPI等等。。。
写单片机程序的时候,比如对于UART的驱动,我们都是在程序中直接写一套函数,来操作相关的UART寄存器,在程序中的其它地方调用这些函数,完成串口的收发。 在小规模的单片机程序中,这样做是再正常不过的。
但是,在规模庞大的LINUX内核中,要处理各种各样的CPU,各种各样的UART收发器,上述办法就有心无力了:没有灵活性,无法移植,接口不一致,很难想象有一个UART驱动程序能够完成这个工作。
OK,有了上面的理解,我们再来看LINUX中的platform device和platform driver。 platform device 其实就是相当于“片内外设”,比如UART,内核刚开始启动时,并不知道它所运行的CPU上面有哪些片内外设。有没有UART? 有没有I2C?等等这些问题,内核都是一无所知。而platform device的作用就是全面定义描述该CPU的所有片内外设,并注册到系统中,每一个platform device都有一个唯一的名字name。
更进一步,将“片内外设”扩展到“板载外设”,一块电路板上不止有CPU,还有很多其它设备通过GPIO,I2C/SPI等总线来连接,比如led灯,就需要一个GPIO来控制它的亮灭;比如继电器,也需要一个GPIO来控制它的开合。 GPIO控制的开关设备是最简单的,对应的驱动也是非常简单的。
RK30SDK使用了ROCKCHIP的CPU,型号是RK3066。在RK30SDK中,我们以led驱动为例,首先查找它的platform device定义,在arch/arm/mach-rk30/board-rk30-box.c文件中,有如下的定义:
static struct platform_device rk29_device_gpio_leds = {
.name = "leds-gpio",
.id = -1,
.dev = {
.platform_data = &rk29_leds_pdata,
},
};
这个设备的名称是"leds-gpio",这个platform_data里面包含了各个不同led的名称/GPIO资源占用情况,它的定义如下:
static struct gpio_led_platform_data rk29_leds_pdata = {
.leds = rk29_leds,
.num_leds = ARRAY_SIZE(rk29_leds),
};
似乎有很多led,定义成了一个数组?带着疑问,我们找到rk29_leds的定义:
#ifdef CONFIG_LEDS_GPIO_PLATFORM
static struct gpio_led rk29_leds[] = {
#ifdef CONFIG_DISPLAY_KEY_LED_CONTROL
#ifdef CONFIG_HDMI_RK30
{
.name = "hdmi-soc",
.gpio = RK30_PIN4_PD7,
// .default_trigger = "timer",
.active_low = 0,
.retain_state_suspended = 0,
.default_state = LEDS_GPIO_DEFSTATE_OFF,
},
#endif
#ifdef CONFIG_HDMI_ITV
{
.name = "hdmi-transmitter",
.gpio = RK30_PIN4_PD2,
.active_low = 0,
.retain_state_suspended = 0,
.default_state = LEDS_GPIO_DEFSTATE_OFF,
},
#endif
没错,这就是一个数组,只是有很多ifdef。不用管它,他们的意思是这里的源码支持在make menuconfig里面进行配置,如果将来你设计的电路板上有hdmi发送的指示灯,就可以把CONFIG_HDMI_ITV打开,这样led驱动里面就包含HDMI的发送指示灯了。gpio = RK30_PIN4_PD2这句话表示这个led灯是通过RK30_PIN4_PD2这个管脚进行控制的,如果你去看电路原理图,这个管脚一定是连着一个led灯,如果在你设计的电路板上是另外的管脚,那么这里改成你自己的管脚名称就行了。
至此,我们看完了RK上led的platform device定义了,一句话,它描述了RK开发板上led的所有控制IO口管脚,led名称等信息。实际上,这些配置代码是通过电路原理图写出来的,如果你能看懂原理图,那你也能写出这样的代码。

那么,platform device是如何告知内核自己的存在呢?我们继续在board-rk30-box.c中寻找rk29_device_gpio_leds出现的地方:
static struct platform_device *devices[] __initdata = {
#ifdef CONFIG_BACKLIGHT_RK29_BL
&rk29_device_backlight,
#endif
#ifdef CONFIG_FB_ROCKCHIP
&device_fb,
#endif
#ifdef CONFIG_ION
&device_ion,
#endif
#ifdef CONFIG_ANDROID_TIMED_GPIO
&rk29_device_vibrator,
#endif
#ifdef CONFIG_LEDS_GPIO_PLATFORM
&rk29_device_gpio_leds,
#endif
OK,看来我们的rk29_device_gpio_leds被包含在了devices数组中,而且是支持make menuconfig配置的,这是多么的合情合理啊!我们可以在menuconfig中打开或者关闭led,非常好。其它地方没有再用到rk29_device_gpio_leds这个device了,我们需要继续寻找devices数组是怎么被使用的:
static void __init machine_rk30_board_init(void)
{
avs_init();
gpio_request(POWER_ON_PIN, "poweronpin");
gpio_direction_output(POWER_ON_PIN, GPIO_HIGH);
pm_power_off = rk30_pm_power_off;
rk30_i2c_register_board_info();
spi_register_board_info(board_spi_devices, ARRAY_SIZE(board_spi_devices));
platform_add_devices(devices, ARRAY_SIZE(devices));
board_usb_detect_init(RK30_PIN6_PA3);
#ifdef CONFIG_WIFI_CONTROL_FUNC
rk29sdk_wifi_bt_gpio_control_init();
#endif
}
哈哈,终于找到它了,看名字也知道这里是向内核注册platform device了,关于platform_add_devices的工作原理这里就不说了,网上一大把,无非就是调用另外一个函数将devices数组中的每一个device分别注册到系统中。这里上面的代码,这里先打个埋伏:platform_add_devices是注册所有的"platform"总线上的设备,"platform"是一个虚拟的总线,因为实际上这些外设并没有挂在总线上,只是通过GPIO简单的连接起来。而上面的rk30_i2c_register_board_info和spi_register_board_info则是分别注册I2C总线和SPI总线上的设备了,逻辑上来说,他们和platform总线的概念是对等的。I2C是广泛使用的,用来连接CPU和其它外部IC的总线,你所看到的各种sensor,EEPROM等都是通过I2C和CPU进行通信的。
在文件的末尾,有这样的代码:
MACHINE_START(RK30, "RK30board")
.boot_params = PLAT_PHYS_OFFSET + 0x800,
.fixup = rk30_fixup,
.reserve = &rk30_reserve,
.map_io = rk30_map_io,
.init_irq = rk30_init_irq,
.timer = &rk30_timer,
.init_machine = machine_rk30_board_init,
MACHINE_END
看样子,一起都是从machine_rk30_board_init函数开始的,如果我们倒回来看,就知道这个led device是如何被注册到内核里面的。
至于led device对应的platform driver,我们在下一篇分析。
RK30SDK开发板驱动分析(一):platform device 的概念与注册的更多相关文章
- RK30SDK开发板驱动分析(二):DDR频率配置
在内核配置界界面,我们可以很容易的配置DDR的频率,300M OR 600M, so easy! 那么它是如何起作用的呢? 回想 RK30SDK开发板驱动分析(一) 末尾提到MACHINE_START ...
- 驱动开发学习笔记. 0.05 linux 2.6 platform device register 平台设备注册 2/2 共2篇
驱动开发读书笔记. 0.05 linux 2.6 platform device register 平台设备注册 2/2 共2篇 下面这段摘自 linux源码里面的文档 : 内核版本2.6.22Doc ...
- 驱动开发学习笔记. 0.04 linux 2.6 platform device register 平台设备注册 1/2 共2篇
驱动开发读书笔记. 0.04 linux 2.6 platform device register 平台设备注册 1/2 共2篇下面这段摘自 linux源码里面的文档 : Documentatio ...
- 迅为iTOP-4418/6818开发板-驱动-实现GPIO扩展
实现 GPIO 扩展,先弄清楚“复用”的概念,将调用这些 GPIO 的驱动去掉配置,重新编译,加到自己的驱动中,就可以实现扩展的 GPIO 的输入和输出.另外必须要先看文档“迅为iTOP-4418开发 ...
- 迅为iTOP-4418/6818开发板-驱动-IO初始化配置介绍和例程
对于所有的处理器,pad 一般可以分为两大类:IO(输入输出).Power(VDD 和GDD).类似摄像头 IO.以太网 IO.PWM 的 IO 等等,都可以统称为 IO.一个 IO,有可能能够被配置 ...
- 【分享】iTOP-iMX6UL开发板驱动看门狗 watchdog 以及 Linux-c 测试例程
iTOP-iMX6UL开发板看门狗测试例程,iTOP-iMX6UL 开发板的看门狗驱动默认已经配置,可以直接使用测试例程. 版本 V1.1:1.格式修改:2.例程修改完善,其中增加喂狗代码.1 看门狗 ...
- Digispark(ATTINY85) 微型开发板驱动安装与开发环境配置教程
前几天无聊就弄了弄这个玩,网上教程可能有点杂,在这里就总结一下. Digispark开发板(也就是badusb)能干什么,自己搜去,/坏笑. 1.准备材料:Attiny85微型 USB接口开发板 Di ...
- 使用FPGA开发板驱动VGA显示器
1. 本次使用的是cyclone4开发板,先看下原理图,因为右边的RGB应该是模拟信号量,但是本次例程只接了3根线,那就是说颜色只有8种. 2. 代码,输出信号有R,G,B三色,就是上图右边的,行同步 ...
- 东芝开发板驱动OLED模块显示LOGO图片
前言 在之前的两篇评测文章: 使用系统定时器SysTick实现精确延时微秒和毫秒函数 东芝MCU实现位带操作 介绍了系统SysTick实现精确延时,GPIO的输入输出使用,并实现了位带方式操作GPIO ...
随机推荐
- Python中何时使用断言(转)
原文:http://blog.jobbole.com/76285/ 本文由 伯乐在线 - 贱圣OMG 翻译.未经许可,禁止转载!英文出处:python maillist.欢迎加入翻译小组. 这个问题是 ...
- Hosts文件的位置
Operating System Version(s) Location Unix, Unix-like, POSIX /etc/hosts Microsoft Windows 3.1 %WinD ...
- python多线程(三)
同步锁 两个需要注意的点: 线程抢的是GIL锁,GIL锁相当于执行权限,拿到执行权限后才能拿到互斥锁Lock,其他线程也可以抢到GIL,但如果发现Lock仍然没有被释放则阻塞,即便是拿到执行权限GIL ...
- [置顶] 我的Android进阶之旅------>Android中制作和查看自定义的Debug版本Android签名证书
Android应用开发接入各种SDK时会发现,有很多SDK是需要靠package name和的证书指纹SHA1码来识别的,如百度地图SDK.这样如果使用默认自动生成的debug的话就会给开发调试工作带 ...
- 解决后台无法进入提示DedeCMS Error: (PHP 5.3 and above) Please set 'request_order' ini value
最近小美眉的网站被盯上了,被添加了非常多的dubo页面,删除了5w多个文件,但还是不停的增加,因为网站权重还可以,很多都被收录了,结果可想而知,ytkah帮她迁移,在迁移网站时遇到了一些问题,后台登录 ...
- python中json.dumps使用的坑以及字符编码
我们知道,python中的字符串分普通字符串和unicode字符串,一般从数据库中读取的字符串会自动被转换为unicode字符串 下面回到重点,使用json.dumps时,一般的用法为: >&g ...
- 通过js代码来制作数据库增删改查插件
代码流程 1.订制表头:table_config 2.订制显示内容: table_config,data_list 3.加载框: 图片,position:fixed 4.-字符串格式化 ...
- 每天一个linux命令(6/18):lsof命令
lsof(list open files)是一个列出当前系统打开文件的工具.在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件.所以,lsof的功 ...
- 收集整理的awk用法小结
awk 用法:awk ‘ pattern {action} ‘ 变量名 含义 ARGC 命令行变元个数 ARGV 命令行变元数组 FILENAME 当前输入文件名 FNR 当前文件中的记录号 FS 输 ...
- CSR1010 sdk蓝牙
转:http://blog.csdn.net/lorain_lynies/article/details/52038640CSR1010 I/O开发须知:关于I/O操作的函数库被定义在头文件<p ...