博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
TI AM335x Linux MUX hacking
阅读量:6311 次
发布时间:2019-06-22

本文共 18864 字,大约阅读时间需要 62 分钟。

/********************************************************************************************* *                           TI AM335x Linux MUX hacking *  声明: *      1. 本文主要是对TI的AM335x Linux驱动中的引脚复用配置代码进行跟踪; *      2. 参考书籍:AM335x ARM® Cortex™-A8 Microprocessors (MPUs) Technical Reference Manual * *                                             2015-6-25 阵雨 深圳 南山平山村 曾剑锋 *********************************************************************************************/                    \\\\\\\\\\\\\-*- 目录 -*-/                    | 一、跟踪板级文件:                                     | 二、跟踪am335x_evm_init()函数:                        | 三、跟踪board_mux参数:                                | 四、跟踪am33xx_mux_init()函数:                        | 五、跟踪am33xx_muxmodes参数:                         | 六、跟踪omap_mux_init()函数:                          | 七、跟踪omap_mux_init_list()函数:                     | 八、跟踪omap_mux_init_signals函数:                    \\\\\\\\\\\\\\\\\\\\//一、跟踪板级文件:    ......    MACHINE_START(AM335XEVM, "am335xevm")        /* Maintainer: Texas Instruments */        .atag_offset    = 0x100,        .map_io     = am335x_evm_map_io,        .init_early = am33xx_init_early,        .init_irq   = ti81xx_init_irq,        .handle_irq     = omap3_intc_handle_irq,        .timer      = &omap3_am33xx_timer,        .init_machine   = am335x_evm_init,          // 跟踪该函数    MACHINE_END                                            ^                                                           |    MACHINE_START(AM335XIAEVM, "am335xiaevm")              |        /* Maintainer: Texas Instruments */                |        .atag_offset    = 0x100,                           |        .map_io     = am335x_evm_map_io,                   |        .init_irq   = ti81xx_init_irq,                     |        .init_early = am33xx_init_early,                   |        .timer      = &omap3_am33xx_timer,                 |        .init_machine   = am335x_evm_init,    -------------+    MACHINE_END二、跟踪am335x_evm_init()函数:    static void __init am335x_evm_init(void)    {        am33xx_cpuidle_init();        am33xx_mux_init(board_mux);         // 跟踪函数、参数        omap_serial_init();        am335x_evm_i2c_init();        omap_sdrc_init(NULL, NULL);        usb_musb_init(&musb_board_data);        omap_board_config = am335x_evm_config;        omap_board_config_size = ARRAY_SIZE(am335x_evm_config);        /* Create an alias for icss clock */        if (clk_add_alias("pruss", NULL, "pruss_uart_gclk", NULL))            pr_warn("failed to create an alias: icss_uart_gclk --> pruss\n");        /* Create an alias for gfx/sgx clock */        if (clk_add_alias("sgx_ck", NULL, "gfx_fclk", NULL))            pr_warn("failed to create an alias: gfx_fclk --> sgx_ck\n");    } 三、跟踪board_mux参数:    1. 跟踪board_mux[]数组:        static struct omap_board_mux board_mux[] __initdata = {            /*             * Setting SYSBOOT[5] should set xdma_event_intr0 pin to mode 3 thereby             * allowing clkout1 to be available on xdma_event_intr0.             * However, on some boards (like EVM-SK), SYSBOOT[5] isn't properly             * latched.             * To be extra cautious, setup the pin-mux manually.             * If any modules/usecase requries it in different mode, then subsequent             * module init call will change the mux accordingly.             *             * 参考书籍:AM335x ARM® Cortex™-A8 Microprocessors (MPUs) Technical Reference Manual -- 760页             * --------------------------------------------------------------------             * | Offset | Acronym               | Register | Description Section  |             * --------------------------------------------------------------------             * | 9B0h   | conf_xdma_event_intr0 |          | Section 9.3.51       |             * --------------------------------------------------------------------             * 观察上面的内容和接下来要配置引脚,我们只需要将Acronym中的conf_前缀去掉,             * 然后将剩下的字符串大写,就能配置对应的引脚了,如:             *      1. conf_xdma_event_intr0             *      2. xdma_event_intr0             *      3. XDMA_EVENT_INTR0             *                 |             *                 |             */                V            AM33XX_MUX(XDMA_EVENT_INTR0, OMAP_MUX_MODE3 | AM33XX_PIN_OUTPUT), // 跟踪宏            AM33XX_MUX(I2C0_SDA, OMAP_MUX_MODE0 | AM33XX_SLEWCTRL_SLOW |                    AM33XX_INPUT_EN | AM33XX_PIN_OUTPUT),            AM33XX_MUX(I2C0_SCL, OMAP_MUX_MODE0 | AM33XX_SLEWCTRL_SLOW |                    AM33XX_INPUT_EN | AM33XX_PIN_OUTPUT),            { .reg_offset = OMAP_MUX_TERMINATOR }, //后面的程序通过判断这个表示来结束注册        };    2. 跟踪struct omap_board_mux结构体:        /**           * struct omap_board_mux - data for initializing mux registers         * @reg_offset: mux register offset from the mux base         * @mux_value:  desired mux value to set          */                  struct omap_board_mux {            u16 reg_offset;            u16 value;        };    3. 跟踪AM33XX_MUX()宏:        /* If pin is not defined as input, pull would get disabled.         * If defined as input, flags supplied will determine pull on/off.         */          // 以此为例:        //     AM33XX_MUX(XDMA_EVENT_INTR0, OMAP_MUX_MODE3 | AM33XX_PIN_OUTPUT)        //        // .reg_offset = (AM33XX_CONTROL_PADCONF_XDMA_EVENT_INTR0_OFFSET) // 跟踪宏           // .value      = (((OMAP_MUX_MODE3 | AM33XX_PIN_OUTPUT) & AM33XX_INPUT_EN) \        //               ? (OMAP_MUX_MODE3 | AM33XX_PIN_OUTPUT) \        //               : ((mux_value) | AM33XX_PULL_DISA))         #define AM33XX_MUX(mode0, mux_value)                    \        {                                   \            .reg_offset = (AM33XX_CONTROL_PADCONF_##mode0##_OFFSET),    \            .value      = (((mux_value) & AM33XX_INPUT_EN) ? (mux_value)\                        : ((mux_value) | AM33XX_PULL_DISA)),    \        }    4. 跟踪模式宏声明:        /* 34xx mux mode options for each pin. See TRM for options */        #define OMAP_MUX_MODE0      0        #define OMAP_MUX_MODE1      1        #define OMAP_MUX_MODE2      2        #define OMAP_MUX_MODE3      3        #define OMAP_MUX_MODE4      4        #define OMAP_MUX_MODE5      5        #define OMAP_MUX_MODE6      6        #define OMAP_MUX_MODE7      7    5. 跟踪输出宏声明:        /* Definition of output pin could have pull disabled, but         * this has not been done due to two reasons         * 1. AM33XX_MUX will take care of it         * 2. If pull was disabled for out macro, combining out & in pull on macros         *    would disable pull resistor and AM33XX_MUX cannot take care of the         *    correct pull setting and unintentionally pull would get disabled         */        #define AM33XX_PIN_OUTPUT       (0)    6. 跟踪引脚配置偏移宏,并对比数据手册:        // 参考书籍:AM335x ARM® Cortex™-A8 Microprocessors (MPUs) Technical Reference Manual -- 760页        // -----------------------------------------------------------------------        // | Offset | Acronym               | Register   |  Description Section  |        // +--------+-----------------------+------------+-----------------------+        // | 9B0h   | conf_xdma_event_intr0 |            |  Section 9.3.51       |        // -----------------------------------------------------------------------        #define AM33XX_CONTROL_PADCONF_XDMA_EVENT_INTR0_OFFSET      0x09B0四、跟踪am33xx_mux_init()函数:    1. 跟踪am33xx_mux_init()函数:    int __init am33xx_mux_init(struct omap_board_mux *board_subset)    {        return omap_mux_init("core", 0, AM33XX_CONTROL_PADCONF_MUX_PBASE, // 跟踪参数                AM33XX_CONTROL_PADCONF_MUX_SIZE, am33xx_muxmodes,                NULL, board_subset, NULL);    }    2. 跟踪AM33XX_CONTROL_PADCONF_MUX_PBASE宏:        // 参考书籍:AM335x ARM® Cortex™-A8 Microprocessors (MPUs) Technical Reference  Manual -- 158页        // ----------------------------------------------------------------------------------------------------        // | Region Name     | Start Address (hex) | End Address (hex)  | Size   |       Description          |        // +-----------------+---------------------+--------------------+--------+----------------------------+        // | Control Module  |  0x44E1_0000        | 0x44E1_1FFF        | 128KB  |  Control Module Registers  |        // ----------------------------------------------------------------------------------------------------        #define AM33XX_CONTROL_PADCONF_MUX_PBASE            0x44E10000LU    3. 跟踪AM33XX_CONTROL_PADCONF_MUX_SIZE宏:        // 参考书籍:AM335x ARM® Cortex™-A8 Microprocessors (MPUs) Technical Reference  Manual -- 761页        // 这里的大小没有搞懂,在datasheet中是1444h,而这里是B34h,没搞懂        // ----------------------------------------------------------------        // | Offset | Acronym           | Register | Description Section  |        // +--------+-------------------+----------+----------------------+        // | 1444h  | ddr_data1_ioctrl  |          | Section 9.3.92       |        // ----------------------------------------------------------------        #define AM33XX_CONTROL_PADCONF_VREFN_OFFSET         0x0B34                  #define AM33XX_CONTROL_PADCONF_MUX_SIZE             \                 (AM33XX_CONTROL_PADCONF_VREFN_OFFSET + 0x4)五、跟踪am33xx_muxmodes参数:    1. 跟踪am33xx_muxmodes[]数组:        /* AM33XX pin mux super set */        static struct omap_mux am33xx_muxmodes[] = {            _AM33XX_MUXENTRY(GPMC_AD0, 0,                "gpmc_ad0", "mmc1_dat0", NULL, NULL,                NULL, NULL, NULL, "gpio1_0"),            _AM33XX_MUXENTRY(GPMC_AD1, 0,                "gpmc_ad1", "mmc1_dat1", NULL, NULL,                NULL, NULL, NULL, "gpio1_1"),            _AM33XX_MUXENTRY(GPMC_AD2, 0,                "gpmc_ad2", "mmc1_dat2", NULL, NULL,                NULL, NULL, NULL, "gpio1_2"),            _AM33XX_MUXENTRY(GPMC_AD3, 0,                "gpmc_ad3", "mmc1_dat3", NULL, NULL,                NULL, NULL, NULL, "gpio1_3"),            _AM33XX_MUXENTRY(GPMC_AD4, 0,                "gpmc_ad4", "mmc1_dat4", NULL, NULL,                NULL, NULL, NULL, "gpio1_4"),            ......            { .reg_offset = OMAP_MUX_TERMINATOR },  //后面的程序通过判断这个表示来结束注册        }    2. 跟踪struct omap_mux结构体:        /**         * struct omap_mux - data for omap mux register offset and it's value         * @reg_offset: mux register offset from the mux base         * @gpio:       GPIO number         * @muxnames:   available signal modes for a ball         * @balls:      available balls on the package         * @partition:  mux partition         */        struct omap_mux {            u16 reg_offset;            u16 gpio;        #ifdef CONFIG_OMAP_MUX            char    *muxnames[OMAP_MUX_NR_MODES];        #ifdef CONFIG_DEBUG_FS            char    *balls[OMAP_MUX_NR_SIDES];        #endif           #endif        };     2. 跟踪_AM33XX_MUXENTRY宏:        //        // 以此为例:        //  _AM33XX_MUXENTRY(GPMC_AD0, 0, "gpmc_ad0", "mmc1_dat0", NULL, NULL, NULL, NULL, NULL, "gpio1_0")        //          // .reg_offset = AM33XX_CONTROL_PADCONF_GPMC_AD0_OFFSET         // .gpio       = 0      // 相当于取下面muxnames中的第0个        // .muxnames   = {"gpmc_ad0", "mmc1_dat0", NULL, NULL, NULL, NULL, NULL, "gpio1_0"}        #define _AM33XX_MUXENTRY(M0, g, m0, m1, m2, m3, m4, m5, m6, m7)     \        {                                   \            .reg_offset = (AM33XX_CONTROL_PADCONF_##M0##_OFFSET),   \            .gpio       = (g),                      \            .muxnames   = { m0, m1, m2, m3, m4, m5, m6, m7 },       \        }    3. 跟踪AM33XX_CONTROL_PADCONF_GPMC_AD0_OFFSET宏,并对比datasheet:        // 参考书籍:AM335x ARM® Cortex™-A8 Microprocessors (MPUs) Technical Reference Manual -- 758页        // ------------------------------------------------------------------------------------------------------------        // | Offset | Acronym        | Register  | Description Section                                                        // +--------+----------------+-----------+---------------------------------------------------------------------        // | 800h   | conf_gpmc_ad0  |           | See the device datasheet for information on default pin Section 9.3.51        // ------------------------------------------------------------------------------------------------------------        #define AM33XX_CONTROL_PADCONF_GPMC_AD0_OFFSET          0x0800六、跟踪omap_mux_init()函数:    int __init omap_mux_init(const char *name, u32 flags,                 u32 mux_pbase, u32 mux_size,                 struct omap_mux *superset,                 struct omap_mux *package_subset,                 struct omap_board_mux *board_mux,                 struct omap_ball *package_balls)    {        struct omap_mux_partition *partition;            partition = kzalloc(sizeof(struct omap_mux_partition), GFP_KERNEL);        if (!partition)            return -ENOMEM;            partition->name = name;                             // 分区的意思相当于模块的意思        partition->flags = flags;        partition->size = mux_size;        partition->phys = mux_pbase;        partition->base = ioremap(mux_pbase, mux_size);     // 重新映射IO地址        if (!partition->base) {            pr_err("%s: Could not ioremap mux partition at 0x%08x\n",                __func__, partition->phys);            kfree(partition);            return -ENODEV;        }            INIT_LIST_HEAD(&partition->muxmodes);               // 初始化分区头结点链表            list_add_tail(&partition->node, &mux_partitions);   // 将分区加入分区链表        mux_partitions_cnt++;                               // 分区总数统计        pr_info("%s: Add partition: #%d: %s, flags: %x\n", __func__,            mux_partitions_cnt, partition->name, partition->flags);            omap_mux_init_package(superset, package_subset, package_balls); // 两个都是null        omap_mux_init_list(partition, superset);                        // 跟踪函数        omap_mux_init_signals(partition, board_mux);                    // 跟踪函数            return 0;    }七、跟踪omap_mux_init_list()函数:    1. 跟踪omap_mux_init_list()函数:        /*         * Note if CONFIG_OMAP_MUX is not selected, we will only initialize         * the GPIO to mux offset mapping that is needed for dynamic muxing         * of GPIO pins for off-idle.         */        static void __init omap_mux_init_list(struct omap_mux_partition *partition,                              struct omap_mux *superset)        {            while (superset->reg_offset !=  OMAP_MUX_TERMINATOR) {                struct omap_mux *entry;                // 去掉一些不符合要求的的配置引脚        #ifdef CONFIG_OMAP_MUX                if (!superset->muxnames || !superset->muxnames[0]) {                    superset++;                    continue;                }        #else                /* Skip pins that are not muxed as GPIO by bootloader */                if (!OMAP_MODE_GPIO(omap_mux_read(partition,                            superset->reg_offset))) {                    superset++;                    continue;                }        #endif                        entry = omap_mux_list_add(partition, superset);                if (!entry) {                    pr_err("%s: Could not add entry\n", __func__);                    return;                }                superset++;            }        }    2. 跟踪omap_mux_list_add()函数:        static struct omap_mux * __init omap_mux_list_add(                            struct omap_mux_partition *partition,                            struct omap_mux *src)        {            struct omap_mux_entry *entry;            struct omap_mux *m;                    entry = kzalloc(sizeof(struct omap_mux_entry), GFP_KERNEL);            if (!entry)                return NULL;                    m = &entry->mux;            entry->mux = *src;                #ifdef CONFIG_OMAP_MUX            if (omap_mux_copy_names(src, m)) {      // 将数据另存的感觉                kfree(entry);                return NULL;            }        #endif                    mutex_lock(&muxmode_mutex);            list_add_tail(&entry->node, &partition->muxmodes);      // 将节点放入分区节点链表中            mutex_unlock(&muxmode_mutex);                    return m;        }    3. 跟踪omap_mux_copy_names()函数:        // 这个函数的大概意思也就是转存的感觉        static int __init omap_mux_copy_names(struct omap_mux *src,                              struct omap_mux *dst)        {            int i;                    for (i = 0; i < OMAP_MUX_NR_MODES; i++) {                if (src->muxnames[i]) {                    dst->muxnames[i] = kstrdup(src->muxnames[i],                                   GFP_KERNEL);                    if (!dst->muxnames[i])                        goto free;                }            }                #ifdef CONFIG_DEBUG_FS            for (i = 0; i < OMAP_MUX_NR_SIDES; i++) {                if (src->balls[i]) {                    dst->balls[i] = kstrdup(src->balls[i], GFP_KERNEL);                    if (!dst->balls[i])                        goto free;                }            }        #endif                    return 0;                free:            omap_mux_free_names(dst);            return -ENOMEM;                }八、跟踪omap_mux_init_signals函数:    1. 跟踪omap_mux_init_signals()函数:        static void omap_mux_init_signals(struct omap_mux_partition *partition,                          struct omap_board_mux *board_mux)        {            omap_mux_set_cmdline_signals();             // 不知道这里是干啥的,不跟踪            omap_mux_write_array(partition, board_mux); // 跟踪该函数        }    2. 跟踪omap_mux_write_array()函数:        void omap_mux_write_array(struct omap_mux_partition *partition,                         struct omap_board_mux *board_mux)        {            if (!board_mux)                return;                    while (board_mux->reg_offset != OMAP_MUX_TERMINATOR) {                omap_mux_write(partition, board_mux->value,  // 跟踪函数                           board_mux->reg_offset);                board_mux++;            }        }    3. 跟踪am33xx_mux_init()函数:        /*         * int __init am33xx_mux_init(struct omap_board_mux *board_subset)         *  {            *      return omap_mux_init("core", 0 /* flag = 0 */, AM33XX_CONTROL_PADCONF_MUX_PBASE,         *              AM33XX_CONTROL_PADCONF_MUX_SIZE, am33xx_muxmodes,         *              NULL, board_subset, NULL);         *  }          */        void omap_mux_write(struct omap_mux_partition *partition, u16 val,                       u16 reg)        {            if (partition->flags & OMAP_MUX_REG_8BIT)                __raw_writeb(val, partition->base + reg);            else                __raw_writew(val, partition->base + reg);        }    4. 跟踪OMAP_MUX_REG_8BIT宏:        /*                       * omap_mux_init flags definition:         *            * OMAP_MUX_REG_8BIT: Ensure that access to padconf is done in 8 bits.         * The default value is 16 bits.         * OMAP_MUX_GPIO_IN_MODE3: The GPIO is selected in mode3.         * The default is mode4.         */        #define OMAP_MUX_REG_8BIT       (1 << 0)

 

转载于:https://www.cnblogs.com/zengjfgit/p/4599595.html

你可能感兴趣的文章
我的友情链接
查看>>
oracle表分区详解
查看>>
网络编程中常见结构体
查看>>
SSL/TLS原理详解
查看>>
Docker 自定义SSH服务镜像
查看>>
JavaScript强化教程 —— Cocos2d-JS自动JSB绑定规则修改
查看>>
configure: error: in `/root/httpd-2.2.11/srclib/apr': c
查看>>
CentOS7搭建Kubernetes-dashboard管理服务
查看>>
buildroot下查找外部编译器通过ext-toolchain-wrapper调用的参数
查看>>
MySQL Replication 主主配置详细说明
查看>>
Linux的任务调度
查看>>
在Android studio中添加jar包方法如下
查看>>
iframe 在ie下面总是弹出新窗口解决方法
查看>>
分享10款漂亮实用的CSS3按钮
查看>>
安装nginx 常见错误及 解决方法
查看>>
Gorun8电子商城
查看>>
在之前链表的基础上改良的链表
查看>>
android编译系统makefile(Android.mk)写法
查看>>
MD5源代码C++
查看>>
Eclipse 添加 Ibator
查看>>