Linux设备驱动--LCD平台设备与驱动(smdk6410)

来源:互联网 发布:重庆行知职业技术学校 编辑:程序博客网 时间:2024/05/16 12:18

1 环境与简介

    Host:Ubuntu14.04(64bit)

    Target:smdk6410

    Kernel:linux-3.5.0
    在《Linux设备驱动--LCD平台设备与驱动(smdk2440)》中基于linux-2.6.39.4对LCD平台设备与驱动进行了分析,在此继续基于linux-3.5.0对LCD平台设备与驱动进行分析(本文所有源码均来自Linux内核)。

2 平台设备

2.1 声明

extern struct platform_device s3c_device_fb;
源文件:arch/arm/plat-samsung/include/plat/devs.h
对比分析:与《Linux设备驱动--LCD平台设备与驱动(smdk2440)》不同的是,这里不是通过EXPORT_SYMBOL(s3c_device_fb)使其在别的源文件可见,而是在头文件中声明该变量。

2.2 定义

(1)平台设备

    定义全局变量s3c_device_fb

struct platform_device s3c_device_fb = {.name       = "s3c-fb",.id     = -1,.num_resources  = ARRAY_SIZE(s3c_fb_resource),.resource   = s3c_fb_resource,.dev        = {  .dma_mask       = &samsung_device_dma_mask,  .coherent_dma_mask  = DMA_BIT_MASK(32),},   };
源文件:arch/arm/plat-samsung/devs.c

(2)平台资源

static struct resource s3c_fb_resource[] = {[0] = DEFINE_RES_MEM(S3C_PA_FB, SZ_16K),[1] = DEFINE_RES_IRQ(IRQ_LCD_VSYNC),[2] = DEFINE_RES_IRQ(IRQ_LCD_FIFO),[3] = DEFINE_RES_IRQ(IRQ_LCD_SYSTEM),};
源文件:arch/arm/plat-samsung/devs.c

2.3 引用

    定义一个平台设备数组smdk6410_devices,该数组包含了smdk6410开发板的所有平台设备,其中当然包括上述s3c_device_fb,如下第10行所示:

static struct platform_device *smdk6410_devices[] __initdata = {#ifdef CONFIG_SMDK6410_SD_CH0    &s3c_device_hsmmc0,#endif#ifdef CONFIG_SMDK6410_SD_CH1    &s3c_device_hsmmc1,#endif    &s3c_device_i2c0,    &s3c_device_i2c1,    &s3c_device_fb,    &s3c_device_ohci,    &s3c_device_usb_hsotg,    &samsung_asoc_dma,    &s3c64xx_device_iisv4,    &samsung_device_keypad,#ifdef CONFIG_REGULATOR    &smdk6410_b_pwr_5v,#endif    &smdk6410_lcd_powerdev,    &smdk6410_smsc911x,    &s3c_device_adc,    &s3c_device_cfcon,    &s3c_device_rtc,    &s3c_device_ts,    &s3c_device_wdt,};

源文件:arch/arm/mach-s3c64xx/mach-smdk6410.c

2.4 注册

(1)注册函数

    在smdk6410_machine_init()函数中调用platform_add_devices()函数将上述smdk6410_devices注册到系统,即可完成平台设备的注册,如下最后1行所示:

static void __init smdk6410_machine_init(void){    u32 cs1;    s3c_i2c0_set_platdata(NULL);    s3c_i2c1_set_platdata(NULL);    s3c_fb_set_platdata(&smdk6410_lcd_pdata);    /* LCD平台数据. */    s3c_hsotg_set_platdata(&smdk6410_hsotg_pdata);    samsung_keypad_set_platdata(&smdk6410_keypad_data);    s3c24xx_ts_set_platdata(NULL);    /* configure nCS1 width to 16 bits */    cs1 = __raw_readl(S3C64XX_SROM_BW) &            ~(S3C64XX_SROM_BW__CS_MASK << S3C64XX_SROM_BW__NCS1__SHIFT);    cs1 |= ((1 << S3C64XX_SROM_BW__DATAWIDTH__SHIFT) |        (1 << S3C64XX_SROM_BW__WAITENABLE__SHIFT) |        (1 << S3C64XX_SROM_BW__BYTEENABLE__SHIFT)) <<                           S3C64XX_SROM_BW__NCS1__SHIFT;    __raw_writel(cs1, S3C64XX_SROM_BW);        /* set timing for nCS1 suitable for ethernet chip */                 __raw_writel((0 << S3C64XX_SROM_BCX__PMC__SHIFT) |             (6 << S3C64XX_SROM_BCX__TACP__SHIFT) |              (4 << S3C64XX_SROM_BCX__TCAH__SHIFT) |             (1 << S3C64XX_SROM_BCX__TCOH__SHIFT) |             (0xe << S3C64XX_SROM_BCX__TACC__SHIFT) |             (4 << S3C64XX_SROM_BCX__TCOS__SHIFT) |             (0 << S3C64XX_SROM_BCX__TACS__SHIFT), S3C64XX_SROM_BC1);    gpio_request(S3C64XX_GPN(5), "LCD power");    gpio_request(S3C64XX_GPF(13), "LCD power");    i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));    i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));        s3c_ide_set_platdata(&smdk6410_ide_pdata);        samsung_bl_set(&smdk6410_bl_gpio_info, &smdk6410_bl_data);    platform_add_devices(smdk6410_devices, ARRAY_SIZE(smdk6410_devices)); /* 注册平台设备. */} 
源文件:arch/arm/mach-s3c64xx/mach-smdk6410.c

(2)注册时机

    上述smdk6410_machine_init()函数是何时被调用的呢?答案是在内核初始化设备的时候,如下第8行所示:

MACHINE_START(SMDK6410, "SMDK6410")    /* Maintainer: Ben Dooks <ben-linux@fluff.org> */    .atag_offset    = 0x100,        .init_irq   = s3c6410_init_irq,    .handle_irq = vic_handle_irq,    .map_io     = smdk6410_map_io,    .init_machine   = smdk6410_machine_init,    .init_late  = s3c64xx_init_late,    .timer      = &s3c24xx_timer,    .restart    = s3c64xx_restart,MACHINE_END   
源文件:arch/arm/mach-s3c64xx/mach-smdk6410.c

3 平台驱动

3.1 定义

    为了和平台设备匹配,平台驱动的name要与平台设备的name一致:

static struct platform_driver s3c_fb_driver = {.probe      = s3c_fb_probe,.remove     = __devexit_p(s3c_fb_remove),.id_table   = s3c_fb_driver_ids,.driver     = {                                                                                                                                                           .name   = "s3c-fb",                                                                                                                                                   .owner  = THIS_MODULE,                                                                                                                                                .pm = &s3cfb_pm_ops,                                                                                                                                                },                                                                                                                                                                      }; 
源文件:drivers/video/s3c-fb.c

3.2 注册

module_platform_driver(s3c_fb_driver); 

源文件:drivers/video/s3c-fb.c

    module_platform_driver()是新版本内核新添加的宏,根据参考资料[1]的提示,上述宏可展开为:

static int __init s3c_fb_driver_init(void){        return platform_driver_register(&s3c_fb_driver);}module_init(s3c_fb_driver_init);static void __exit s3c_fb_driver_init(void){        return platform_driver_unregister(&s3c_fb_driver);}module_exit(s3c_fb_driver_exit);

4 设备与驱动匹配

    同《Linux设备驱动--WDT平台设备与驱动》第4节。

参考资料

[1]module_platform_driver宏解析

0 0
原创粉丝点击