Nota: este artículo se basa en u-boot.2016.03 compilado por Yocto
Referencia: Número de documento: IMX6DQRM
Rev. C, 1/2012
1 、 IOMUX
Capítulo 4
Señales externas y multiplexación de pines
El i.MX 6Dual / 6Quad contiene un número limitado de pines, la mayoría de los cuales tienen múltiples opciones de señal. Estas opciones de señal a pin y pin a señal son seleccionadas por el multiplexor de entrada y salida llamado IOMUX. El IOMUX también se utiliza para configurar otras características de los pines, como el nivel de voltaje, la fuerza del accionamiento y la histéresis.
Los pines del chip de i.MX 6Dual / 6Quad son limitados. La mayoría de los pines se pueden configurar con diferentes funciones de señal. Las funciones de los pines están determinadas por IOMUX. IOMUX también se utiliza para configurar otras características de los pines, como el voltaje nivel, fuerza e histéresis de la unidad.
2. Tome UART4 como ejemplo
2.1 Funciones involucradas
mx6qsabreauto.c
这个board_early_init_f函数在初化序列里是在比较靠前的位置,这样可以来调试u-boot,用串口来打印。
int board_early_init_f(void)
{
setup_iomux_uart();
return 0;
}
La función imx_iomux_v3_setup_multiple_pads se utiliza para inicializar los pines de UART4.
static void setup_iomux_uart(void)
{
imx_iomux_v3_setup_multiple_pads(uart4_pads, ARRAY_SIZE(uart4_pads));
}
2.2 UART4 tiene dos pines para configurar
static iomux_v3_cfg_t const uart4_pads[] = {
MX6_PAD_KEY_COL0__UART4_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
MX6_PAD_KEY_ROW0__UART4_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
};
2.3 Relación de llamada a función
Si busca este "MX6_PAD_KEY_COL0__UART4_TX_DATA", no podrá encontrarlo.
¿Cuál es la relación correspondiente? Vea abajo
La macro "MX6_PAD_DECL" define un entero largo sin signo de 64 bits.
typedef u64 iomux_v3_cfg_t;
2.4 definición de pad
Para el PAD KEY_COL0, los siguientes tres registros deben configurarse
Use un número entero de 64 bits para juntar el valor de compensación y configuración y pasarlo a la función:
2.4.1 El diseño de la memoria de iomux_v3_cfg_t:
sel_input | pad_ctrl | mux_mode | sel_input_ofs | pad_ctrl_ofs | mux_ctrl_ofs |
---|---|---|---|---|---|
cadena de margaritas | control | Reutilizar | Desplazamiento de cadena tipo margarita | Desplazamiento de control | Desplazamiento multiplex |
4 | 19 | 7 | 12 | 12 | 12 |
0 | X | 4 | 0x938 | 0x05C8 | 0x01F8 |
Una cadena de margaritas:
La definición de BX es:
#define UART_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \
PAD_CTL_SRE_FAST | PAD_CTL_HYS)
La definición de macro UART_PAD_CTRL llena los siguientes bits.
Multiplexación C:
2.5, vuelva a escribir los registros relevantes del pad
La siguiente función analiza un pad de 64 bits del grupo y lo escribe en el registro relevante
void imx_iomux_v3_setup_pad(iomux_v3_cfg_t pad)
{
u32 mux_ctrl_ofs = (pad & MUX_CTRL_OFS_MASK) >> MUX_CTRL_OFS_SHIFT;
u32 mux_mode = (pad & MUX_MODE_MASK) >> MUX_MODE_SHIFT;
u32 sel_input_ofs =
(pad & MUX_SEL_INPUT_OFS_MASK) >> MUX_SEL_INPUT_OFS_SHIFT;
u32 sel_input =
(pad & MUX_SEL_INPUT_MASK) >> MUX_SEL_INPUT_SHIFT;
u32 pad_ctrl_ofs =
(pad & MUX_PAD_CTRL_OFS_MASK) >> MUX_PAD_CTRL_OFS_SHIFT;
u32 pad_ctrl = (pad & MUX_PAD_CTRL_MASK) >> MUX_PAD_CTRL_SHIFT;
#if defined(CONFIG_MX6SL) || defined(CONFIG_MX6SLL)
/* Check whether LVE bit needs to be set */
if (pad_ctrl & PAD_CTL_LVE) {
pad_ctrl &= ~PAD_CTL_LVE;
pad_ctrl |= PAD_CTL_LVE_BIT;
}
#endif
#ifdef CONFIG_IOMUX_LPSR
u32 lpsr = (pad & MUX_MODE_LPSR) >> MUX_MODE_SHIFT;
#ifdef CONFIG_MX7
if (lpsr == IOMUX_CONFIG_LPSR) {
base = (void *)IOMUXC_LPSR_BASE_ADDR;
mux_mode &= ~IOMUX_CONFIG_LPSR;
/* set daisy chain sel_input */
if (sel_input_ofs)
sel_input_ofs += IOMUX_LPSR_SEL_INPUT_OFS;
}
#else
if (is_cpu_type(MXC_CPU_MX6ULL) || is_cpu_type(MXC_CPU_MX6SLL)) {
if (lpsr == IOMUX_CONFIG_LPSR) {
base = (void *)IOMUXC_SNVS_BASE_ADDR;
mux_mode &= ~IOMUX_CONFIG_LPSR;
}
}
#endif
#endif
if (is_soc_type(MXC_SOC_MX7) || is_cpu_type(MXC_CPU_MX6ULL) ||
is_cpu_type(MXC_CPU_MX6SLL) || mux_ctrl_ofs)
__raw_writel(mux_mode, base + mux_ctrl_ofs);
if (sel_input_ofs)
__raw_writel(sel_input, base + sel_input_ofs);
#ifdef CONFIG_IOMUX_SHARE_CONF_REG
if (!(pad_ctrl & NO_PAD_CTRL))
__raw_writel((mux_mode << PAD_MUX_MODE_SHIFT) | pad_ctrl,
base + pad_ctrl_ofs);
#else
if (!(pad_ctrl & NO_PAD_CTRL) && pad_ctrl_ofs)
__raw_writel(pad_ctrl, base + pad_ctrl_ofs);
#if defined(CONFIG_MX6SLL)
else if ((pad_ctrl & NO_PAD_CTRL) && pad_ctrl_ofs)
clrbits_le32(base + pad_ctrl_ofs, PAD_CTL_IPD_BIT);
#endif
#endif
#ifdef CONFIG_IOMUX_LPSR
if (lpsr == IOMUX_CONFIG_LPSR)
base = (void *)IOMUXC_BASE_ADDR;
#endif
}
Referencia útil
https://blog.csdn.net/u013554213/article/details/79309235
https://www.jianshu.com/p/3c2053508342