platformデバイスの静的登録


前回のブログでは、デバイスとドライバは手動でロードされていましたが(デバッグ時にこの方式が採用されています)、カーネルがデバイスのためにplatformバスに登録されている場合もあります.ドライバを登録するだけでいいです.次に、デバイスの静的登録について説明します.
まずカーネルが静的登録のplatformをどこから取得したかを見てみましょう.device.
カーネルは.../linux-2.6.36/arch/arm/mach-s3c64xx/mach-mini6410.cファイルからplatform_を取得デバイスの情報:
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,

...
}

この配列にはすべての静的登録が格納されていることがわかります
platform_デバイス情報は、それらのフォーマットに従って、追加されました.
s3c_device_led構造体ポインタはこの配列にあります.次に、どこで定義されているかを見てみましょう.結果は.../linux-2.6.36/arch/arm/plat-samsungで発見
各デバイスのリソースは個別のファイルで含まれているので、私は同じように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);

2>Makefileにコンパイルオプション50行を追加
 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と一致します.
したがって、ここにコードを1行追加する必要があります:)
 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;

上のいくつかのファイルを修正した後、カーネルを再コンパイルして静的登録を実現しました.
platformデバイスは、カーネル起動時に自動的に登録されます
s3c_device_led.登録するだけです
platform駆動でいいです
以下はドライバのコードです.
  //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
"); 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
"); 45 return 0; 46 } 47 48 int led_driver_remove(struct platform_device *pdev) 49 { 50 printk("led_driver_remove
"); 51 pled.reg = ioread32(pled.gpkdat); 52 pled.reg |= (0x1<<8); 53 iowrite32(pled.reg, pled.gpkdat);  54  55     printk("led off
");  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!
");  73         return ret;  74     }  75     printk("led driver init
");  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");