在上一篇博文中,设备和驱动都是通过手动加载的(调试的时候采用这种方式),但有些情况下,内核已经为设备注册到platform总线上,只需要我们注册驱动就可以了。接下来介绍一下设备的静态注册。
先看一下内核是从哪里获取静态注册的platform_device。
内核是从../linux-2.6.36/arch/arm/mach-s3c64xx/mach-mini6410.c文件中获取到platform_device的信息:
362 static struct platform_device *mini6410_devices[] __initdata = { 363 &globalfifo_device, 364 &s3c_device_led, //add by wenhui 365 #ifdef CONFIG_MINI6410_SD_CH0 366 &s3c_device_hsmmc0, 367 #endif 368 #ifdef CONFIG_MINI6410_SD_CH1 369 &s3c_device_hsmmc1, 370 #endif 371 &s3c_device_i2c0, 372 #ifdef CONFIG_S3C_DEV_I2C1 373 &s3c_device_i2c1, 374 #endif 375 &s3c_device_nand, 376 &s3c_device_fb, ... }
每个设备的资源都是以一个单独的文件来包含的 所以我就可以照样画葫芦新建一个dev-led.c
1> cp dev-wdt.c dev-led.c ; vim dev-led.c 经修改后
1 /* linux/arch/arm/plat-samsung/dev-led.c 2 * 3 * Copyright (c) 2004 Simtec Electronics 4 * Ben Dooks <[email protected]> 5 * 6 * S3C series device definition for the watchdog timer 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 */ 12 13 #include <linux/kernel.h> 14 #include <linux/platform_device.h> 15 16 #include <mach/irqs.h> 17 #include <mach/map.h> 18 19 #include <plat/devs.h> 20 21 static struct resource s3c_led_resource[1] = { 22 [0] = { 23 .start = 0x7F008800, 24 .end = 0X7F00880C, 25 .flags = IORESOURCE_MEM, 26 }, 27 }; 28 29 struct platform_device s3c_device_led = { 30 .name = "plat-led", 31 .id = -1, 32 .num_resources = 1, 33 .resource = s3c_led_resource, 34 }; 35 EXPORT_SYMBOL(s3c_device_led);
45 obj-$(CONFIG_S3C_DEV_USB_HOST) += dev-usb.o 46 obj-$(CONFIG_S3C_DEV_USB_HSOTG) += dev-usb-hsotg.o 47 obj-$(CONFIG_S3C_DEV_WDT) += dev-wdt.o 48 49 #add by wenhui for platform led 50 obj-y += dev-led.o 51 52 obj-$(CONFIG_S3C_DEV_NAND) += dev-nand.o
3>在../linux-2.6.36/arch/arm/plat-samsung/include/plat/devs.h中增加
(platform_match函数是通过包含该文件后读取里面的platform_device信息来跟platform_driver匹配。
所以,必须在这里加上一行代码:)
42 extern struct platform_device s3c_device_fb; 43 extern struct platform_device s3c_device_ohci; 44 extern struct platform_device s3c_device_lcd; 45 extern struct platform_device s3c_device_wdt; 46 47 extern struct platform_device s3c_device_led; //add by wenhui 48 49 extern struct platform_device s3c_device_i2c0;
以下是驱动的代码:
//driver.c 1 #include<linux/module.h> 2 #include<linux/init.h> 3 4 #include<linux/platform_device.h> 5 #include<asm/io.h> 6 #include<asm/sizes.h> 7 8 struct plat_led{ 9 unsigned long phys, virt; 10 unsigned long gpkcon1, gpkdat, gpkup; 11 unsigned long reg; 12 }; 13 14 struct plat_led pled; 15 16 int led_driver_probe(struct platform_device *pdev) 17 { 18 printk("led_driver_probe\n"); 19 pled.phys = pdev->resource[0].start; /*0x7F008800*/ 20 21 /*不加强制性转换 会报 warning: assignment makes integer from pointer without a cast*/ 22 pled.virt = (unsigned long)ioremap(pled.phys, SZ_4K); 23 24 pled.gpkcon1 = pled.virt + 0x4; 25 pled.gpkdat = pled.virt + 0x8; 26 pled.gpkup = pled.virt + 0xc; 27 28 //config 29 pled.reg = ioread32(pled.gpkcon1); /*GPK4 LED1*/ 30 pled.reg &= ~(0xe<<0); /*0001 output*/ 31 pled.reg |= (0x1<<0); 32 iowrite32(pled.reg, pled.gpkcon1); 33 34 //up 35 pled.reg = ioread32(pled.gpkup); 36 pled.reg &= ~(0x3<<8); /*disable pull-up/down*/ 37 iowrite32(pled.reg, pled.gpkup); 38 39 //dat 40 pled.reg = ioread32(pled.gpkdat); 41 pled.reg &= ~(0x1<<8); /*low */ 42 iowrite32(pled.reg, pled.gpkdat); 43 44 printk("led on\n"); 45 return 0; 46 } 47 48 int led_driver_remove(struct platform_device *pdev) 49 { 50 printk("led_driver_remove\n"); 51 pled.reg = ioread32(pled.gpkdat); 52 pled.reg |= (0x1<<8); 53 iowrite32(pled.reg, pled.gpkdat); 54 55 printk("led off\n"); 56 return 0; 57 } 58 59 struct platform_driver s3c_led_drv = { 60 .probe = led_driver_probe, 61 .remove = led_driver_remove, 62 .driver = { 63 .name = "plat-led", /*在/sys/ 中的驱动目录名字*/ 64 }, 65 }; 66 67 static int __init plat_led_init(void) 68 { 69 int ret; 70 ret = platform_driver_register(&s3c_led_drv); 71 if(ret){ 72 printk("led register failed!\n"); 73 return ret; 74 } 75 printk("led driver init\n"); 76 77 return ret; 78 } 79 80 static void __exit plat_led_exit(void) 81 { 82 platform_driver_unregister(&s3c_led_drv); 83 printk("led driver exit"); 84 } 85 86 module_init(plat_led_init); 87 module_exit(plat_led_exit); 88 89 MODULE_LICENSE("GPL"); 90 MODULE_AUTHOR("wenhui");