IMX6のPAD構成(IOMUX)

注:この記事は、Yoctoによってコンパイルされたu-boot.2016.03に基づいています

参照:文書番号:IMX6DQRM
Rev. C、2012年1月

1、IOMUX

第4
章外部信号とピン多重化

i.MX 6Dual / 6Quadは、複数の信号オプションを有する大部分のピンの制限された数を含んでいます。これらの信号対ピンおよびピン対信号オプションは、IOMUXと呼ばれる入出力マルチプレクサによって選択されます。IOMUXは、電圧レベル、ドライブ強度、ヒステリシスなどの他のピン特性を構成するためにも使用されます。

i.MX 6Dual / 6Quadのチップピンは制限されています。ほとんどのピンは異なる信号機能で構成できます。ピン機能はIOMUXによって決定されます。IOMUXは、電圧などのピンの他の特性を構成するためにも使用されます。レベル、ドライブ強度、ヒステリシス。

2.例としてUART4を取り上げます

2.1関連する機能

mx6qsabreauto.c

这个board_early_init_f函数在初化序列里是在比较靠前的位置,这样可以来调试u-boot,用串口来打印。
int board_early_init_f(void)
{
	setup_iomux_uart();

	return 0;
}

imx_iomux_v3_setup_multiple_pads関数は、UART4のピンを初期化するために使用されます。

static void setup_iomux_uart(void)
{
	imx_iomux_v3_setup_multiple_pads(uart4_pads, ARRAY_SIZE(uart4_pads));
}

2.2UART4には構成する2つのピンがあります

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関数呼び出しの関係

この「MX6_PAD_KEY_COL0__UART4_TX_DATA」を検索しても見つかりません。

対応する関係は何ですか?下記参照
ここに画像の説明を挿入します

64ビットの符号なし長整数は「MX6_PAD_DECL」マクロによって定義されます

typedef u64 iomux_v3_cfg_t;

2.4パッドの定義

PAD KEY_COL0の場合、次の3つのレジスタを構成する必要があります
ここに画像の説明を挿入します

64ビット整数を使用して、オフセット値と構成値をまとめ、関数に渡します。

ここに画像の説明を挿入します

2.4.1 iomux_v3_cfg_tのメモリレイアウト:

sel_input pad_ctrl mux_mode sel_input_ofs pad_ctrl_ofs mux_ctrl_ofs
デイジーチェーン コントロール 再利用 デイジーチェーンオフセット コントロールオフセット マルチプレックスオフセット
4 19 7 12 12 12
0 バツ 4 0x938 0x05C8 0x01F8

デイジーチェーン:

ここに画像の説明を挿入します

BXの定義は次のとおりです。

#define UART_PAD_CTRL  (PAD_CTL_PUS_100K_UP |			\
	PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm |			\
	PAD_CTL_SRE_FAST  | PAD_CTL_HYS)

UART_PAD_CTRLマクロ定義は、次のビットを埋めます。
ここに画像の説明を挿入します

C多重化:

ここに画像の説明を挿入します

2.5、パッドの関連するレジスタを書き戻します

次の関数は、グループの64ビットパッドを解析し、関連するレジスタに書き込みます。

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

}

役立つリファレンス

https://blog.csdn.net/u013554213/article/details/79309235
https://www.jianshu.com/p/3c2053508342

おすすめ

転載: blog.csdn.net/amwha/article/details/86630494