OMAPL138/AM1808引脚复用配置

来源:互联网 发布:暗黑网络发生的事件 编辑:程序博客网 时间:2024/05/16 12:17

hawkboard和TI-OMAPL138-EVM相差不大。引脚复用设置都为一样,匹配性强,KERNEL版本为2.6.32,ti-am180x-sdk的KERNEL为2.6.37基本不匹配

引脚复用设置通过以下函数设置:mux.c
int da8xx_pinmux_setup(const short pins[]);
    -->int __init_or_module davinci_cfg_reg(const unsigned long index)

初始引脚的定义和初始化在da850.c中:
1225 void __init da850_init(void)
1226 {
1227         da8xx_syscfg_base = ioremap(DA8XX_SYSCFG_BASE, SZ_4K);
1228         if (WARN(!da8xx_syscfg_base, "Unable to map syscfg module     "))
1229                 return;
1230

1233         davinci_soc_info_da850.pinmux_base = DA8XX_SYSCFG_VIRT(0x 120);//0x01c1 4120
1234
1235         davinci_common_init(&davinci_soc_info_da850);
     }
。。。。

davinci_soc_info_da850结构初始化:
1203 static struct davinci_soc_info davinci_soc_info_da850 = {
       /*............*/
1211         .pinmux_pins            = da850_pins,
1212         .pinmux_pins_num        = ARRAY_SIZE(da850_pins),
       /*............*/
1223 };


与引脚相关的是pinmux_base,pinmux_pins,pinmux_pins_num,

上面是da850系列的板级支持,下面进行初始化,
void __init davinci_common_init(struct davinci_soc_info *soc_info)
 57 {
 58         int ret;
 59         struct davinci_id *dip;
 60
 61         if (!soc_info) {
 62                 ret = -EINVAL;
 63                 goto err;
 64         }
 65
 66         memcpy(&davinci_soc_info, soc_info, sizeof(struct davinci_soc_info));//消除硬件差异性,linux分层及硬件无关可移植性无处不在

与pin设置有关的结构体还有
static const struct mux_config da850_pins[]
 490 #ifdef CONFIG_DAVINCI_MUX
 491         /* UART0 function */
 492         MUX_CFG(DA850, NUART0_CTS,      3,      24,     15,     2     ,      false)
 493         MUX_CFG(DA850, NUART0_RTS,      3,      28,     15,     2     ,      false)
 494         MUX_CFG(DA850, UART0_RXD,       3,      16,     15,     2     ,      false)
 495         MUX_CFG(DA850, UART0_TXD,       3,      20,     15,     2     ,      false)

。。。。。
 18 #define MUX_CFG(soc, desc, muxreg, mode_offset, mode_mask, mux_mode, dbg)\
 19 [soc##_##desc] = {                                                      \
 20                         .name =  #desc,                                 \
 21                         .debug = dbg,                                   \
 22                         .mux_reg_name = "PINMUX"#muxreg,                \
 23                         .mux_reg = PINMUX##muxreg,                      \
 24                         .mask_offset = mode_offset,                     \
 25                         .mask = mode_mask,                              \
 26                         .mode = mux_mode,                               \
 27                 },
 28
 22 struct mux_config {
 23         const char *name; //SOC
 24         const char *mux_reg_name;//DESC
 25         const unsigned char mux_reg;//复用寄存器
 26         const unsigned char mask_offset;//偏移
 27         const unsigned char mask;//位掩码
 28         const unsigned char mode;//模式
 29         bool debug;
 30 };
以上都是一个结构,MUX_CFG是完成mux_config匹配的宏,需要设定某些引脚时添加对应的MUX_CFG宏即可

以pruss uart引脚设置来分析
178 static __init int omapl138_hawk_config_pru_suart(void)
179 {
    /* ....... */
181
182         ret = da8xx_pinmux_setup(da850_pru_suart_pins);
183         if (ret)
184                 pr_warning("hawk_init: hawk_pru_suart_pins mux set     failed:%d\n", ret);
   /* ........ */
191 }
da850_pru_suart_pins[]数组是软串口的引脚定义:
const short da850_pru_suart_pins[] __initdata = {
         DA850_AHCLKX, DA850_ACLKX, DA850_AFSX,
    DA850_AHCLKR, DA850_ACLKR, DA850_AFSR,
        DA850_AXR_11 DA850_AXR_9,
        DA850_AXR_12 DA850_AXR_10,
        -1
};
这是函数原型:
 94 int da8xx_pinmux_setup(const short pins[])
 95 {
 96         int i, error = -EINVAL;
 97
 98         if (pins)
 99                 for (i = 0; pins[i] >= 0; i++) {//if ping[i] == -1,break;
100                         error = davinci_cfg_reg(pins[i]);
101                         if (error)
102                                 break;
103                 }
104
105         return error;
106 }

这里可以看出da850_pru_suart_pins[]的内容是一组索引号,用来传递给davinci_cfg_reg()函数,至于索引号是怎么定义的呢?

可以查看mux.c中static const struct mux_config da850_pins[]和 mux.h中enum davinci_da850_index 内容
会惊奇的发现他们的引脚定义顺序完全一样,davinci_da850_index是一个枚举类型的数组。从0开始,作为索引匹配mux_config da850_pins
的内容,而MUX_CFG这个宏完成mux_config的匹配。故我们在增加引脚设置索引后,在mux.c中也许要在对应的位置添加MUX_CFG宏。
例程:
#define MUX_CFG(soc,     desc,          muxreg, mode_offset, mode_mask, mux_mode, dbg)
    MUX_CFG(DA850,  AHCLKX,         0,      20,         15,     1,      false)


int __init_or_module davinci_cfg_reg(const unsigned long index)
 29 {
 30         static DEFINE_SPINLOCK(mux_spin_lock);
 31         struct davinci_soc_info *soc_info = &davinci_soc_info;
 32         void __iomem *base = soc_info->pinmux_base;//0x01C1 4120
 33         unsigned long flags;
 34         const struct mux_config *cfg;
 35         unsigned int reg_orig = 0, reg = 0;
 36         unsigned int mask, warn = 0;
 37
 38         if (!soc_info->pinmux_pins)
 39                 BUG();
 40
 41         if (index >= soc_info->pinmux_pins_num) {
 42                 printk(KERN_ERR "Invalid pin mux index: %lu (%lu)\n",
 43                        index, soc_info->pinmux_pins_num);
 44                 dump_stack();
 45                 return -ENODEV;
 46         }
 47
 48         cfg = &soc_info->pinmux_pins[index];
 49
 50         if (cfg->name == NULL) {
 51                 printk(KERN_ERR "No entry for the specified index\n");
 52                 return -ENODEV;
 53         }
 54
 55         /* Update the mux register in question */
 56         if (cfg->mask) {//0x0F
 57                 unsigned        tmp1, tmp2;
 58
 59                 spin_lock_irqsave(&mux_spin_lock, flags);
 60                 reg_orig = __raw_readl(base + cfg->mux_reg);//PINMUX0
 61
 62                 mask = (cfg->mask << cfg->mask_offset);//20
 63                 tmp1 = reg_orig & mask;//0x0f << 20
 64                 reg = reg_orig & ~mask;//~(0x0f << 20)
 65
 66                 tmp2 = (cfg->mode << cfg->mask_offset);//0x01 << 20
 67                 reg |= tmp2;
 68
 69                 if (tmp1 != tmp2)
 70                         warn = 1;
 71
 72                 __raw_writel(reg, base + cfg->mux_reg);
 73                 spin_unlock_irqrestore(&mux_spin_lock, flags);
 74         }
 75
 76         if (warn) {
 77 #ifdef CONFIG_DAVINCI_MUX_WARNINGS
 78                 printk(KERN_WARNING "MUX: initialized %s\n", cfg->name);
 79 #endif
 80         }
 81
 82 #ifdef CONFIG_DAVINCI_MUX_DEBUG
 83         if (cfg->debug || warn) {
 84                 printk(KERN_WARNING "MUX: Setting register %s\n", cfg->name)    ;
 85                 printk(KERN_WARNING "      %s (0x%08x) = 0x%08x -> 0x%08x\n"    ,
 86                        cfg->mux_reg_name, cfg->mux_reg, reg_orig, reg);
 87         }
 88 #endif
 89
 90         return 0;
 91 }
流程:
1.索引号是否正确
2.根据索引得到对应mux_config结构
3.读取当前引脚状态备份
4.设置配置中的引脚状态

原创粉丝点击