i.mx6的IOMUX代码不够直观

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

i.mx6的IOMUX代码不够直观

767 Views
lianghua
Contributor I

第一次接触飞思卡尔i.mx6,但觉得IOMUX代码不够直观。

不能很直观的知道一个signal使用哪个pad的ALT。而且目前代码的可扩展性不好。

目前寄存器是32位还好,使用了64位来组合起来。如果是64位呢?找不到128位变量类型吧?


我写了一个,大家不要拍砖啊。

#include <stdio.h>

#include <stdlib.h>

#include <linux/kernel.h>

#include <linux/slab.h>

/*

    this demo suitable for i.MX6Q

*/

enum{

    MODE_ALT0=0,

    MODE_ALT1,

    MODE_ALT2,

    MODE_ALT3,

    MODE_ALT4,

    MODE_ALT5,

    MODE_ALT6,

    MODE_ALT7,

};

#define iomux_reg32                    unsigned int

#define TO_NAME(_x)                    #_x

#define INVALID_INPUT_REG                ~0

struct pad_reg_detail{//e.g. IOMUXC_SW_PAD_CTL_PAD_SD1_DATA2

        unsigned SRE:1;//bit0

        unsigned reserved_2_1:2;//reserved bit[2:1]

        unsigned DSE:3;//bit[5:3]

        unsigned SPEED:2;//bit[7:6]

        unsigned reserved_10_8:2;//reserved bit[10:8]

        unsigned ODE:1;//bit11

        unsigned PKE:1;//bit12

        unsigned PUE:1;//bit13

        unsigned PUS:2;//bit[15:14]

        unsigned HYS:1;//bit16

        unsigned reserved_31_17:15;//bit[31:17]

};

struct mux_reg_detail {

    unsigned ALT:3;//mode, bit[2:0]

    unsigned reserved_3:1;//bit3

    unsigned SION:1;//bit4

    unsigned reserved_31_5:27;//bit[31:5]

};   

struct  input_reg_detail{

    unsigned DAISY:1;//bit0

    unsigned reserved_31_1:31;//bit[31:1]

}detail;   

struct IOMUX_pad_signal_cfg{

    char *pad_name;//pad name(e.g. SD1_DAT2)

    char *signal_name;//signal name(e.g. PWM2_OUT)

    /* Pad/Group Register */

    unsigned int pad_group_reg_addr;//register address or offset(e.g. IOMUXC_SW_PAD_CTL_PAD_SD1_DATA2)

    union{

        unsigned int value;//pad group reg value

        struct pad_reg_detail detail;//pad group reg value

    }pad_group_reg_data;

    /* Mux Select Register */

    unsigned int mux_reg_addr;//register address or offset(e.g. IOMUXC_SW_MUX_CTL_PAD_SD1_DATA2)

    union{

        unsigned int value;//value

        struct mux_reg_detail detail;//value   

    }mux_reg_data;

   

    /* Input Select Register */

    unsigned int input_reg_addr;////register address or offset(e.g. IOMUXC_ECSPI5_SS1_SELECT_INPUT)

    union{

        unsigned int value;//value

        struct input_reg_detail detail;//value

    }input_reg_data;

};

struct IOMUX_pad_signal_cfg mx6q_pad_cfgs[]={

    //----------------------------------------- pad: others ----------------------------------------------

    //......

    //----------------------------------------- pad: SD1_DAT2 ----------------------------------------------

    {//SD1_DATA2

        .pad_name = TO_NAME(SD1_DAT2),//pad: SD1_DAT2

        .signal_name = TO_NAME(SD1_DATA2),//config as SD1_DATA2

        .pad_group_reg_addr = 0x20E0734,//register address or offset of IOMUXC_SW_PAD_CTL_PAD_SD1_DATA2

        .pad_group_reg_data = {

            .value = 0,

            //or

            //.detail = {

            //    m = n,

    

       //}

        },

        .mux_reg_addr = 0x020E034C,//register address or offset of IOMUXC_SW_MUX_CTL_PAD_SD1_DATA2

        .mux_reg_data = {

            //or value = m | n | ...

            .detail={

                .ALT = MODE_ALT0,

            },

        },

        .input_reg_addr = INVALID_INPUT_REG,//no input reg   

    },{//ECSPI5_SS1

        .pad_name = TO_NAME(SD1_DAT2),//pad: SD1_DAT2

        .signal_name = TO_NAME(ECSPI5_SS1),//config as ECSPI5_SS1

        .pad_group_reg_addr = 0x20E0734,//register address or offset of IOMUXC_SW_PAD_CTL_PAD_SD1_DATA2

        .pad_group_reg_data = {

            .value = 0,

        },

        .mux_reg_addr = 0x020E034C,//register address or offset of IOMUXC_SW_MUX_CTL_PAD_SD1_DATA2

        .mux_reg_data = {

            .detail = {

                .ALT = MODE_ALT1,

            },

        },

        .input_reg_addr = 0x20E0838,//register address or offset of IOMUXC_ECSPI5_SS1_SELECT_INPUT

        .input_reg_data = {

            .detail = {

                .DAISY = 1,

            },

        },

    },{//GPT_COMPARE2

        .pad_name = TO_NAME(SD1_DAT2),//pad: SD1_DAT2

        .signal_name = TO_NAME(GPT_COMPARE2),//config as GPT_COMPARE2

        .pad_group_reg_addr = 0x20E0734,//register address or offset of IOMUXC_SW_PAD_CTL_PAD_SD1_DATA2

        .pad_group_reg_data = {

            .value = 0,

        },

        .mux_reg_addr = 0x020E034C,//register address or offset of IOMUXC_SW_MUX_CTL_PAD_SD1_DATA2

        .mux_reg_data = {

            .detail = {

                .ALT = MODE_ALT2,//mode

            },

        },

        .input_reg_addr = INVALID_INPUT_REG,//no input reg

    },{//PWM2_OUT

        .pad_name = TO_NAME(SD1_DAT2),//pad: SD1_DAT2

        .signal_name = TO_NAME(PWM2_OUT),//config as PWM2_OUT

        .pad_group_reg_addr = 0x20E0734,//register address or offset of IOMUXC_SW_PAD_CTL_PAD_SD1_DATA2

        .pad_group_reg_data={

            .value = 0,

        },

        .mux_reg_addr = 0x020E034C,//register address or offset of IOMUXC_SW_MUX_CTL_PAD_SD1_DATA2

        .mux_reg_data = {

            .detail = {

                .ALT = MODE_ALT3,

            },

        },

        .input_reg_addr = INVALID_INPUT_REG,//no input reg

    },{//WDOG1_B

        .pad_name = TO_NAME(SD1_DAT2),//pad: SD1_DAT2

        .signal_name = TO_NAME( WDOG1_B),//config as WDOG1_B

        .pad_group_reg_addr = 0x20E0734,//register address or offset of IOMUXC_SW_PAD_CTL_PAD_SD1_DATA2

        .pad_group_reg_data={

            .value = 0,

        },

        .mux_reg_addr = 0x020E034C,//register address or offset of IOMUXC_SW_MUX_CTL_PAD_SD1_DATA2

        .mux_reg_data = {

            .detail = {

                .ALT = MODE_ALT4,

            },

        },

        .input_reg_addr = INVALID_INPUT_REG,//no input reg

    },{//GPIO1_IO19

        .pad_name = TO_NAME(SD1_DAT2),//pad: SD1_DAT2

        .signal_name = TO_NAME( GPIO1_IO19),//config as GPIO1_IO19

        .pad_group_reg_addr = 0x20E0734,//register address or offset of IOMUXC_SW_PAD_CTL_PAD_SD1_DATA2

        .pad_group_reg_data={

            .value = 0,

        },

        .mux_reg_addr = 0x020E034C,//register address or offset of IOMUXC_SW_MUX_CTL_PAD_SD1_DATA2

        .mux_reg_data = {

            .detail = {

                .ALT = MODE_ALT5,

            },

        },

        .input_reg_addr = INVALID_INPUT_REG,//no input reg

    },{//WDOG1_RESET_B_DEB

        .pad_name = TO_NAME(SD1_DAT2),//pad: SD1_DAT2

        .signal_name = TO_NAME( GPIO1_IO19),//config as GPIO1_IO19

        .pad_group_reg_addr = 0x20E0734,//register address or offset of IOMUXC_SW_PAD_CTL_PAD_SD1_DATA2

        .pad_group_reg_data = {

            .value = 0,

        },

        .mux_reg_addr = 0x020E034C,//register address or offset of IOMUXC_SW_MUX_CTL_PAD_SD1_DATA2

        .mux_reg_data = {

            .detail = {

                .ALT = MODE_ALT6,

            },

        },

        .input_reg_addr = INVALID_INPUT_REG,//no input reg

    }

   

    //----------------------------------------- pad: others ----------------------------------------------

    //......

};

unsigned int *iomux_base;//IOMUX base address

int index_of_pad_cfgs(char *pad_name, char *signal_name, struct IOMUX_pad_signal_cfg *pad_cfgs)

{

    int i=0;

    int count=0;

    int ret=-1;

   

   

    if (NULL == pad_name || NULL==signal_name || NULL == pad_cfgs){

        return ret;

    }

   

    count = ARRAY_SIZE(pad_cfgs);

   

    for (i=0; i<count; i++){

        if (!strcmp(signal_name), pad_cfgs[i].signal_name && !strcmp(pad_name), pad_cfgs[i].pad_name) { //exist

            return i;

        }

    }

   

    return -1;

}

int setup_multiple_pads(int index, struct IOMUX_pad_signal_cfg *pad_cfgs)

{

    if (0 > index || NULL == pad_cfgs){

        return -1;

    }

   

    //here use base + offset address, just for demo

    *(iomux_base + pad_cfgs[index].pad_group_reg_addr) =  pad_cfgs[index].pad_group_reg_data.value;

    *(iomux_base + pad_cfgs[index].mux_reg_addr) =  pad_cfgs[index].mux_reg_data.value;

    if (INVALID_INPUT_REG != pad_cfgs[index].input_reg_addr){//some signal has no input register

        *(iomux_base + pad_cfgs[index].input_reg_addr) =  pad_cfgs[index].input_reg_data.value;

    }

   

    return 0;

}

int index_of_mx6q_pad_cfgs(char *pad_name, char *signal_name)

{

    return index_of_pad_cfgs(pad_name, signal_name, mx6q_pad_cfgs);

}

int mx6q_setup_multiple_pads(int index)

{

    return setup_multiple_pads(index, mx6q_pad_cfgs);

}

/* config the pad of SD1_DAT2 as PWM2_OUT signal */

#define MX6Q_MUX_SD1_DAT2___PWM2_OUT                index_of_mx6q_pad_cfgs("SD1_DAT2", "PWM2_OUT")       

int init_IOMUX(){

    iomux_base = kmalloc(1024 * sizeof(unsigned int), GFP_KERNEL);//no map, just for demo

   

    mx6q_setup_multiple_pads(MX6Q_MUX_SD1_DAT2___PWM2_OUT);

   

    return 0;

}

Tags (1)
0 Kudos
0 Replies