Configuración de PAD de IMX6 (IOMUX)

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
Inserte la descripción de la imagen aquí

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
Inserte la descripción de la imagen aquí

Use un número entero de 64 bits para juntar el valor de compensación y configuración y pasarlo a la función:

Inserte la descripción de la imagen aquí

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:

Inserte la descripción de la imagen aquí

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.
Inserte la descripción de la imagen aquí

Multiplexación C:

Inserte la descripción de la imagen aquí

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

Supongo que te gusta

Origin blog.csdn.net/amwha/article/details/86630494
Recomendado
Clasificación