注:この記事は、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