1. 程式人生 > >OMAPL138/AM1808引腳複用配置

OMAPL138/AM1808引腳複用配置

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.設定配置中的引腳狀態