Davinci 引脚复用模块代码分析

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://blog.csdn.net/piaozhiye

这里只是记录一些日志,难免有些错误,欢迎批评指正。

在分析davinci输出视频模块的时候(drivers/media/video/davinci/davincihd_display.c )有这个函数set_vpif_display_pinmux();顾名思义是将引脚复用配置成VPIF的显示功能,刚开始没有在意,后来多看几下就看得迷糊了,就做个分析笔记。

arch/arm/mach-davinci/video_hdevm.c 定义如下:

	236 void set_vpif_display_pinmux()
	237 {
	238         davinci_cfg_reg(DM646X_STSOMUX_DISABLE);
	239         davinci_cfg_reg(DM646X_STSIMUX_DISABLE);
	240         davinci_cfg_reg(DM646X_PTSOMUX_DISABLE);
	241 } 

davinci_cfg_reg()是在arch/arm/mach-davinci/mux.c中定义的寄存器配置函数,其参数就是就是复用表的索引,如下:

100 enum davinci_dm646x_index {
101         /* ATA function */
102         DM646X_ATAEN,
103 
104         /* USB */
105         DM646X_VBUSDIS,
106         DM646X_VBUSDIS_GPIO22,
107 
108         /* STC source clock input */
109         DM646X_STCCK,
110 
111         /* AUDIO Clock */
112         DM646X_AUDCK1,
113         DM646X_AUDCK0,
114 
115         /* CRGEN Control */
116         DM646X_CRGMUX,
117 
118         /* VPIF Control */
119         DM646X_STSOMUX_DISABLE,
120         DM646X_STSIMUX_DISABLE,
121         DM646X_PTSOMUX_DISABLE,
122         DM646X_PTSIMUX_DISABLE,
	………………
	}

因为其索引表是枚举类型的,也就是整数,就没弄明白它是什么样配置寄存器的。刚开始就很疑惑。后来经进一步分析发现是在/board-dm6467-evm.c 中初始化,以下是整理一下流程。

在arch/arm/mach-davinci/board-dm6467-evm.c 中初始化,将其编译进内核。最开始内核启动的时候就会打印出DaVinci DM6467 EVM字符串了。

380 MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM6467 EVM")
381         .phys_io      = IO_PHYS,
382         .io_pg_offst  = (io_p2v(IO_PHYS) >> 18) & 0xfffc,
383         .boot_params  = (0x80000100),
384         .map_io       = davinci_map_io,
385         .init_irq     = davinci_dm6467_evm_irq_init,
386         .timer        = &davinci_timer,
387         .init_machine = dm6467_evm_init,
388 MACHINE_END

davinci_dm6467_evm_irq_init中调用davinci_init_common_hw()初始化公共硬件,函数如下,

static __init void davinci_dm6467_evm_irq_init(void)
{
        davinci_init_common_hw();
        davinci_irq_init();
}

 davinci_init_common_hw()在 arch/arm/mach-davinci/io.c 实现,主要是引脚复用初始化和时钟初始化。

 55 void __init davinci_init_common_hw(void)
 56 {       
 57         davinci_mux_init();
 58         davinci_clk_init();
 59 }   

davinci_mux_init()在arch/arm/mach-davinci/mux_cfg.c 中实现,代码如下:

调用在arch/arm/mach-davinci/mux.c 中实现的davinci_mux_register注册引脚复用表。

182 void __init davinci_mux_init(void)
183 {
184         if (cpu_is_davinci_dm355())
185                 davinci_mux_register(davinci_dm355_pins,
186                                         ARRAY_SIZE(davinci_dm355_pins));
187         else if (cpu_is_davinci_dm6467())
188                 davinci_mux_register(davinci_dm646x_pins,
189                                         ARRAY_SIZE(davinci_dm646x_pins));
190         else
191                 davinci_mux_register(davinci_dm644x_pins,
192                                         ARRAY_SIZE(davinci_dm644x_pins));
193 }

同时mux_cfg.c中也初始化了复用列表,一直想找到复用列表就在这里初始化

 64 struct pin_config __initdata_or_module davinci_dm646x_pins[] = {
 65 /*
 66  *       description            mux  mode   mode  mux    dbg
 67  *                              reg  offset mask  mode
 68  */
 69 MUX_CFG("ATAEN",                 0,   0,     1,   1,     1)
 70 
 71 MUX_CFG("VBUSDIS",               0,   31,    1,   0,     0)
 72 
 73 MUX_CFG("VBUSDIS_GPIO22",        0,   31,    1,   1,     0)
 74 
 75 MUX_CFG("STCCK",                 0,   30,    1,   1,     0)
 76 
 77 MUX_CFG("AUDCK1",                0,   29,    1,   0,     0)
 78 
 79 MUX_CFG("AUDCK0",                0,   28,    1,   0,     0)
 80 
 81 MUX_CFG("CRGMUX",                0,   24,    7,   5,     0)
 82 
 83 MUX_CFG("STSOMUX_DISABLE",       0,   22,    3,   0,     0)
 84 
 85 MUX_CFG("STSIMUX_DISABLE",       0,   20,    3,   0,     0)
 86 
 87 MUX_CFG("PTSOMUX_DISABLE",       0,   18,    3,   0,     0)
 88 
 89 MUX_CFG("PTSIMUX_DISABLE",       0,   16,    3,   0,     0)

MUX_CFG 就是在include/asm-arm/arch-davinci/mux.h 中的配置宏。

 34 #define MUX_CFG(desc, mux_reg, mode_offset, mode_mask, mux_mode, dbg) \
 35 { \
 36         .name =  desc, \
 37         .debug = dbg, \
 38         MUX_REG(mux_reg, mode_offset, mode_mask, mux_mode) \
 39 },

arch/arm/mach-davinci/mux.c 提供了复用的注册和寄存器的配置的接口,具体如下:

 28 int __init davinci_mux_register(struct pin_config *pins, unsigned long size)
 29 {
 30         pin_table = pins;
 31         pin_table_sz = size;
 32                 
 33         return 0;                       
 34 }       
 35    
 36 /*
 37  * Sets the DAVINCI MUX register based on the table
 38  */
 39 int __init_or_module davinci_cfg_reg(const unsigned long index)
 40 {
 41         static DEFINE_SPINLOCK(mux_spin_lock);
 42 
 43         unsigned long flags;
 44         struct pin_config *cfg;
 45         unsigned int reg_orig = 0, reg = 0;
 46         unsigned int mask, warn = 0;
 47 
 48         if (!pin_table)
 49                 BUG();
 50 
 51         if (index >= pin_table_sz) {
 52                 printk(KERN_ERR "Invalid pin mux index: %lu (%lu)\n",
 53                        index, pin_table_sz);
 54                 dump_stack();
 55                 return -ENODEV;
 56         }
 57 
 58         cfg = (struct pin_config *)&pin_table[index];
 59 
 60         /* Check the mux register in question */
 61         if (cfg->mux_reg) {
 62                 unsigned        tmp1, tmp2;
 63 
 64                 spin_lock_irqsave(&mux_spin_lock, flags);
 65                 reg_orig = davinci_readl(cfg->mux_reg);
 66 
 67                 mask = (cfg->mask << cfg->mask_offset);
 68                 tmp1 = reg_orig & mask;
 69                 reg = reg_orig & ~mask;
 70 
 71                 tmp2 = (cfg->mode << cfg->mask_offset);
 72                 reg |= tmp2;
 73 
 74                 if (tmp1 != tmp2)
 75                         warn = 1;
 76 
 77                 davinci_writel(reg, cfg->mux_reg);
 78                 spin_unlock_irqrestore(&mux_spin_lock, flags);
 79         }
 80 
 81         if (warn) {
 82 #ifdef CONFIG_DAVINCI_MUX_WARNINGS
 83             printk(KERN_WARNING "MUX: initialized %s\n", cfg->name);
 84 #endif
 85         }
 86 
 87 #ifdef CONFIG_DAVINCI_MUX_DEBUG
 88         if (cfg->debug || warn) {
 89                 printk(KERN_WARNING "MUX: Setting register %s\n", cfg->name);
 90                 printk(KERN_WARNING "      %s (0x%08x) = 0x%08x -> 0x%08x\n",
 91                        cfg->mux_reg_name, cfg->mux_reg, reg_orig, reg);
 92         }
 93 #endif
 94 
 95         return 0;
 96 }
 97 EXPORT_SYMBOL(davinci_cfg_reg);

它的流程就是这样,使用的时候就像以下代码:

	236 void set_vpif_display_pinmux()
	237 {
	238         davinci_cfg_reg(DM646X_STSOMUX_DISABLE);
	239         davinci_cfg_reg(DM646X_STSIMUX_DISABLE);
	240         davinci_cfg_reg(DM646X_PTSOMUX_DISABLE);
	241 } 





你可能感兴趣的:(struct,IO,Module,table,代码分析,Warnings)