代碼清單8第2行獲取platform_data,而platform_data實際上是定義GPIO按鍵硬件信息的數組,第31行的for循環工具這些信息申請GPIO并初始化中斷,對于LDD6140電路板而言,這些信息如代碼清單10。
代碼清單10 LDD6410開發板GPIO按鍵的platform_data
1 static struct gpio_keys_button ldd6410_buttons[] = {
2 {
3 .gpio = S3C64XX_GPN(0),
4 .code = KEY_DOWN,
5 .desc = "Down",
6 .active_low = 1,
7 },
8 {
9 .gpio = S3C64XX_GPN(1),
10 .code = KEY_ENTER,
11 .desc = "Enter",
12 .active_low = 1,
13 .wakeup = 1,
14 },
15 {
16 .gpio = S3C64XX_GPN(2),
17 .code = KEY_HOME,
18 .desc = "Home",
19 .active_low = 1,
20 },
21 {
22 .gpio = S3C64XX_GPN(3),
23 .code = KEY_POWER,
24 .desc = "Power",
25 .active_low = 1,
26 .wakeup = 1,
27 },
28 {
29 .gpio = S3C64XX_GPN(4),
30 .code = KEY_TAB,
31 .desc = "Tab",
32 .active_low = 1,
33 },
34 {
35 .gpio = S3C64XX_GPN(5),
36 .code = KEY_MENU,
37 .desc = "Menu",
38 .active_low = 1,
39 },
40 };
41
42 static struct gpio_keys_platform_data ldd6410_button_data = {
43 .buttons = ldd6410_buttons,
44 .nbuttons = ARRAY_SIZE(ldd6410_buttons),
45 };
46
47 static struct platform_device ldd6410_device_button = {
48 .name = "gpio-keys",
49 .id = -1,
50 .dev = {
51 .platform_data = &ldd6410_button_data,
52 }
53 };
1.3 RTC設備驅動
RTC(實時鐘)借助電池供電,在系統掉電的情況下依然可以行走。它通常還具有產生周期中斷以及產生鬧鐘(alarm)中斷的能力,是一種典型的字符設備。作為一種字符設備驅動,RTC需要有file_operations中接口函數的實現,如open()、release()、read()、 poll()、ioctl()等,而典型的IOCTL包括RTC_SET_TIME、RTC_ALM_READ、RTC_ALM_SET、 RTC_IRQP_SET、RTC_IRQP_READ等,這些對于所有的RTC是通用的,只有底層的具體實現是設備相關的。
因此,drivers/rtc/rtc-dev.c實現了RTC驅動通用的字符設備驅動層,它實現了file_opearations的成員函數以及一些關于RTC的通用的控制代碼,并向底層導出rtc_device_register()、rtc_device_unregister()用于注冊和注銷RTC;導出rtc_class_ops結構體用于描述底層的RTC硬件操作。這一RTC通用層實現的結果是,底層的RTC驅動不再需要關心RTC 作為字符設備驅動的具體實現,也無需關心一些通用的RTC控制邏輯,圖3表明了這種關系。
圖3 Linux RTC設備驅動的分層
drivers/rtc/rtc-s3c.c實現了S3C6410的RTC驅動,其注冊RTC以及綁定的rtc_class_ops的代碼如代碼清單11。
代碼清單11 S3C6410 RTC驅動的rtc_class_ops實例與RTC注冊
1 static const struct rtc_class_ops s3c_rtcops = {
2 .open = s3c_rtc_open,
3 .release = s3c_rtc_release,
4 .ioctl = s3c_rtc_ioctl,
5 .read_time = s3c_rtc_gettime,
6 .set_time = s3c_rtc_settime,
7 .read_alarm = s3c_rtc_getalarm,
8 .set_alarm = s3c_rtc_setalarm,
9 .irq_set_freq = s3c_rtc_setfreq,
10 .irq_set_state = s3c_rtc_setpie,
11 .proc = s3c_rtc_proc,
12 };
13
14 static int s3c_rtc_probe(struct platform_device *pdev)
15 {
16 ...
17 rtc = rtc_device_register("s3c", &pdev->dev, &s3c_rtcops,
18 THIS_MODULE);
19 ...
20 }