4.3.6. IO-Domain 调试指南

4.3.6.1. IO-Domain 概述

在嵌入式系统中,电压域( Voltage Domain)指的是为某一部分硬件或电路提供特定电压的电源区域。一个系统可能包含多个电压域,每个电压域会根据不同模块的需要提供不同的电压。这些电压域通常通过不同的模块或子系统进行管理与控制

注意:

  • 电压域配置:如果硬件设计外接电压域为 3.3V, IO-Domain 需要配置为 3.3V;如果外接电压域为 1.8V, IO-Domain 需要配置为 1.8V。

  • 电压不匹配问题:外接电压域为 3.3V,而 IO-Domain 配置为 1.8V,可能会对芯片造成损伤;如果外接电压域为 1.8V,而 IO-Domain 配置为 3.3V,相关模块可能无法正常工作。

4.3.6.2. IO-Domain 特点

在芯片中,电源管理通常按不同的功能域划分,每个功能域根据需求管理不同的电源:

  • AON (Always On) Power Domain:该电源域负责总是处于活动状态的电源管理,保证即使在设备休眠时也能保持某些基本功能(例如,唤醒和时间跟踪)正常工作。

  • DSP (DSP Subsystem) Power Domain:负责数字信号处理器( DSP)子系统的电源管理。 DSP 是处理数字信号(如音频、视频、语音识别等)的专用硬件模块,通常在特定的多媒体应用中使用。

  • SOC (System on Chip) Power Domain:包括整个芯片的管理,负责与芯片的主要控制器、总线以及其他基本功能模块相关的电源供应。

  • CPU (CPU Subsystem) Power Domain:该电源域管理 CPU 子系统的电源, CPU 是执行大部分计算任务的核心单元。

  • BPU (BPU Subsystem) Power Domain: BPU(即神经网络处理单元或智能处理单元)负责处理与人工智能( AI)、机器学习( ML)等相关的任务。

  • DDR (DDR Subsystem) Power Domain:负责动态随机访问内存( DDR)的电源管理。 DDR 存储器用于系统数据存取,在大部分应用中占用较大功耗。

  • VIDEO (Video Subsystem) Power Domain:该电源域负责视频处理模块的电源供应,包括视频解码、编码、显示等功能。

  • GPU (GPU Subsystem) Power Domain:负责图形处理单元( GPU)的电源管理。 GPU 主要用于图形渲染、图像处理、计算加速等任务,在图形密集型应用中发挥重要作用。

  • ISP (ISP Subsystem) Power Domain:该电源域管理图像信号处理器( ISP)的电源供应。 ISP 通常用于处理从相机传感器获取的原始图像数据,执行图像的滤波、降噪、白平衡等处理。

4.3.6.3. 功能描述

IO-Domain 典型应用

在芯片中通常使用设备树来配置 IO-Domain , 但不同引脚使用的 IO-Domain 与硬件原理图强相关,查看原理图, AON GPIO 电源域配置如下:

io-IO_DOMAIN_AON

设备树中 AON Domain 对应上图中原理图 AON_GPIO_XX 的引脚,配置如下:

/* AON_GPIO 0-7 */
	aon_gpio_0: aon_gpio_0 {
		horizon,pins = <
			AON_GPIO0_PIN0	INVALID_PINMUX	BIT_OFFSET0		MUX_ALT0	&pconf_input_en_1v8
		>;
	};

	aon_gpio_1: aon_gpio_1 {
		horizon,pins = <
			AON_GPIO0_PIN1	INVALID_PINMUX	BIT_OFFSET0		MUX_ALT0	&pconf_input_en_1v8
		>;
	};

	pconf_input_en_1v8: pconf-input-en-1v8 {
		input-enable;
		power-source = <HORIZON_IO_PAD_VOLTAGE_1V8>;
		drive-strength = <3>;
	};

这段代码描述了与 AON_GPIO( Always On GPIO)复用引脚 的相关配置和使用的电源域:

  • aon_gpio_0aon_gpio_1 是为两个 GPIO 引脚设置的别名。它们分别描述了两个物理 GPIO 引脚, aon_gpio_0 和 aon_gpio_1 ,对应的是 AON_GPIO0_PIN0 和 AON_GPIO0_PIN1 。

  • `horizon,pins 是一个属性,定义了每个引脚的配置信息。

  • AON_GPIO0_PIN0AON_GPIO0_PIN1:这些是设备树中定义的物理 GPIO 引脚标识符。

  • INVALID_PINMUX:表示该引脚的默认引脚复用( Pin Muxing)配置无效或没有被设置。通常, Pin Muxing 用于设置一个引脚的功能,例如作为输入、输出、或者特定功能(如 UART、 SPI 等)的引脚。

  • BIT_OFFSET0:这个字段可能是指定该引脚的位偏移量。位偏移用于指示该引脚在寄存器或内存中的位置,通常用于位掩码操作。

  • MUX_ALT0:表示引脚复用的选择。 MUX_ALT0 指该引脚被配置为某个特定的备用功能。

  • &pconf_input_en_1v8:这个是一个引用,指向在设备树中定义的另一个节点 pconf-input-en-1v8 ,它表示此引脚的电源配置 1.8V 输入启用。

其中 pinmux-func 中 pconf_input_en_1v8 节点定义了电源配置与驱动能力:

  • input-enable:这个属性表示启用了输入功能,即该引脚将作为输入引脚工作

  • power-source = <HORIZON_IO_PAD_VOLTAGE_1V8>:指定该引脚的电源电压为 1.8V,表明该引脚需要一个 1.8V 的电源电压来正常工作。

  • drive-strength = <3>:表示驱动强度的设置。驱动强度指的是引脚在驱动信号时能够提供的电流,其中高低电平输出电流对应驱动级如下表:

IOL Low Level Output Current @VOL (max) = 0.125*VDDIO

DS (Drive Strength) Typical Current Unit
0b0000 3.8 mA
0b0001 5.7 mA
0b0010 7.5 mA
0b0011 9.4 mA
0b0100 11.3 mA
0b0101 13.2 mA
0b0110 15.0 mA
0b0111 16.9 mA
0b1000 18.8 mA
0b1001 20.7 mA
0b1010 22.6 mA
0b1011 24.4 mA
0b1100 26.3 mA
0b1101 28.2 mA
0b1110 30.0 mA
0b1111 31.9 mA

IOH High Level Output Current @VOH (min) = 0.75*VDDIO

DS (Drive Strength) Typical Current Unit
0b0000 5.3 mA
0b0001 7.9 mA
0b0010 10.6 mA
0b0011 13.2 mA
0b0100 15.8 mA
0b0101 18.5 mA
0b0110 21.1 mA
0b0111 23.7 mA
0b1000 26.3 mA
0b1001 29.0 mA
0b1010 31.6 mA
0b1011 34.2 mA
0b1100 36.9 mA
0b1101 39.5 mA
0b1110 42.1 mA
0b1111 44.7 mA

IO-Domain 功能原理

设备树中的 GPIO 复用配置与 IO-DOMAIN 都需要通过 pinctrl 子系统来完成,在 Pinctrl_select_state 中 使用 pinconf_apply_setting 来完成电气属性的配置, 具体内核调用过程如图:

io-domain_flow_chart

IO-Domain 工作方式

在驱动的实现中, IO Domain 的流程可以概括为以下几个步骤

1. 引脚配置(Pin Configuration)

  • 通过硬件原理图编写设备树,驱动程序能够读取引脚配置。每个引脚都有一组与之相关的配置参数,包括复用功能(如 GPIO、 UART、 SPI 等)、电压配置(如 1.8V、 3.3V)以及其他电气特性。

horizon,pins = < AON_GPIO0_PIN0 INVALID_PINMUX BIT_OFFSET0 MUX_ALT0 &pconf_input_en_1v8 >;

上述设备树配置指定了 AON_GPIO0_PIN0 引脚的复用方式为 MUX_ALT0 ( GPIO 功能),并且指定了该引脚的电压为 1.8V(通过 &pconf_input_en_1v8 )。

2. IO Domain 的初始化

  • 在驱动中, horizon_pinctrl_probe 函数会读取设备树的配置,并将相关的引脚和硬件资源进行初始化。此时,驱动会为每个引脚分配资源、配置寄存器以及设置相应的电气参数。

ret = horizon_pinctrl_parse_gpio_bank(pdev, ipctl);

3. 电源管理和电气设置

  • 驱动程序通过对 IO Domain 控制寄存器的操作,管理引脚的电气特性(例如电压和电流)。 horizon_pin_power_source 函数会根据传入的标志位设置相应的电压源:

if (flags == HORIZON_IO_PAD_VOLTAGE_IP_CTRL) {
    val |= MS_BIT_CTRL;
}

4. 引脚方向控制(Input/Output Direction Control)

  • 在配置完引脚的电气特性后,驱动程序还会根据需要设置引脚的输入或输出方向。 horizon_gpio_set_direction 用于控制引脚的工作模式:

ret = horizon_gpio_set_direction(pctldev, pin, true, arg);

5. 引脚多路复用(Pin Multiplexing)

  • 通过设备树和驱动的配置,系统能够将一个引脚分配给不同的外设功能。多路复用配置会根据需求切换引脚的功能。例如,某个引脚可能同时支持 GPIO 和 UART 功能,通过设置 MUX_ALT 复用寄存器来进行切换。

pinmux_enable_setting(const struct pinctrl_setting *setting)

4.3.6.4. 驱动代码

Kernel Space

代码位置

drivers/pinctrl/hobot/ # pinctrl 驱动代码源文件所在文件夹
include/linux/platform_data/pinctrl-single.h # pinctrl 驱动代码头文件

IO-Domain 的 DTS

Pinctrl 功能相关定义位于 BSP 源码包的 kernel 文件夹下的 arch/arm64/boot/dts/hobot/pinmux-func.dtsi 文件内。

由于 IO-Domain 在 pinctrl-single 的框架下实现,因此其 DTS 和 pinctrl 的类似,在 IO-Domain 的 DTS 里已经列出了所有模块 1.8V 和 3.3V 的配置组,一般不需要修改,在具体开发时根据实际情况选择使用即可。

	pconf_bias_disabled_ds2_1v8: pconf-bias-disabled-ds2-1v8 {
		bias-disable;
		power-source = <HORIZON_IO_PAD_VOLTAGE_1V8>;
		drive-strength = <2>;
	};
	pinctrl_enet: enetgrp {
		horizon,pins = <
			HSIO_ENET_MDC		HSIO_PINMUX_1	BIT_OFFSET30	MUX_ALT0	&pconf_bias_disabled_ds2_1v8
			HSIO_ENET_MDIO		HSIO_PINMUX_1	BIT_OFFSET28	MUX_ALT0	&pconf_bias_disabled_ds2_1v8
			HSIO_ENET_TXD_0		HSIO_PINMUX_1	BIT_OFFSET26	MUX_ALT0	&pconf_bias_disabled_ds2_1v8
			HSIO_ENET_TXD_1		HSIO_PINMUX_1	BIT_OFFSET24	MUX_ALT0	&pconf_bias_disabled_ds2_1v8
			HSIO_ENET_TXD_2		HSIO_PINMUX_1	BIT_OFFSET22	MUX_ALT0	&pconf_bias_disabled_ds2_1v8
			HSIO_ENET_TXD_3		HSIO_PINMUX_1	BIT_OFFSET20	MUX_ALT0	&pconf_bias_disabled_ds2_1v8
			HSIO_ENET_TXEN		HSIO_PINMUX_1	BIT_OFFSET18	MUX_ALT0	&pconf_bias_disabled_ds2_1v8
			HSIO_ENET_TX_CLK	HSIO_PINMUX_1	BIT_OFFSET16	MUX_ALT0	&pconf_bias_disabled_ds2_1v8
			HSIO_ENET_RX_CLK	HSIO_PINMUX_1	BIT_OFFSET14	MUX_ALT0	&pconf_bias_disabled_ds2_1v8
			HSIO_ENET_RXD_0		HSIO_PINMUX_1	BIT_OFFSET12	MUX_ALT0	&pconf_bias_disabled_ds2_1v8
			HSIO_ENET_RXD_1		HSIO_PINMUX_1	BIT_OFFSET10	MUX_ALT0	&pconf_bias_disabled_ds2_1v8
			HSIO_ENET_RXD_2		HSIO_PINMUX_1	BIT_OFFSET8	MUX_ALT0	&pconf_bias_disabled_ds2_1v8
			HSIO_ENET_RXD_3		HSIO_PINMUX_1	BIT_OFFSET6	MUX_ALT0	&pconf_bias_disabled_ds2_1v8
			HSIO_ENET_RXDV		HSIO_PINMUX_1	BIT_OFFSET4	MUX_ALT0	&pconf_bias_disabled_ds2_1v8
			HSIO_ENET_PHY_CLK	HSIO_PINMUX_1	BIT_OFFSET2	MUX_ALT0	&pconf_bias_disabled_ds2_1v8
		>;
	};

pinctrl_enet: enetgrp

  • pinctrl_enet 是一个引脚控制配置组, enetgrp 是该配置组的名称。这个组主要用于定义与以太网( Ethernet)相关的引脚设置。

  • horizon,pins = < … >:

    • 引脚名称:(例如 HSIO_ENET_MDC、 HSIO_ENET_MDIO、 HSIO_ENET_TXD_0 等)。

    • 复用组:(例如 HSIO_PINMUX_1 )表示引脚复用的硬件资源组,决定该引脚的具体用途。

    • 位偏移:(例如 BIT_OFFSET30 )引脚控制寄存器的偏移值,指定引脚在寄存器中的位置。

    • 复用模式:(如 MUX_ALT0 )指引脚的复用模式,例如使用 MUX_ALT0 来表示该引脚的特定功能。

    • 配置参数引用:(例如 &pconf_bias_disabled_ds2_1v8 ) 引脚的电气特性配置,通过引用其他的配置结构来设置,比如禁用偏置电流、设定驱动能力等。

这里主要详细介绍电压域在设备树中的解析,pconf_bias_disabled_ds2_1v8) 详细信息如下:

	pconf_bias_disabled_ds2_1v8: pconf-bias-disabled-ds2-1v8 {
		bias-disable;
		power-source = <HORIZON_IO_PAD_VOLTAGE_1V8>;
		drive-strength = <2>;
	};
  • pconf_bias_disabled_ds2_1v8:这是设备树中的一个节点名称,用于定义与某些硬件引脚相关的电源配置和驱动特性。这个名称可能是一个通用配置,用于多个引脚或设备模块的电气特性设置。

  • bias-disable:此属性表示禁用该引脚的电气偏置( bias)。在许多硬件设计中,某些引脚可能需要使用偏置(例如上拉电阻或下拉电阻),用于确保引脚处于稳定状态。禁用偏置意味着该引脚不会使用上拉或下拉电阻,而是保持无偏置的状态,通常用于需要高阻抗或浮空状态的情况。

  • power-source:此属性指定了该引脚的电源电压。 HORIZON_IO_PAD_VOLTAGE_1V8 表示该引脚的电源电压为 1.8V,

  • drive-strength:此属性定义了引脚的驱动强度,表示引脚能够提供的电流大小或驱动能力。

备注: 电气属性的具体配置应参考 《X5 PIN SW Reg.xlsx》 文档

RW [30] hsio_enet_rxd_3_pu 0x0 hsio_enet_rxd_3 pull up enable: 1: pull up enable; 0: pull up disable;
RW [29] hsio_enet_rxd_3_pd 0x0 hsio_enet_rxd_3 pull down enable: 1: pull down enable; 0: pull down disable;
RW [28:25] hsio_enet_rxd_3_ds 0x8 hsio_enet_rxd_3 driving selector;
RW [24] hsio_enet_rxd_3_st 0x0 hsio_enet_rxd_3; Schmitt trigger enable. 1: enables Schmitt trigger input function; 0: no Schmitt trigger input function;

该手册提供了不同 GPIO 的硬件寄存器位配置的详细信息。每一行代表寄存器中的一个特定位或一组位,并包含以下信息:

  • 访问类型 (RW/RSV):表示该位是可读写的( Read/Write)。

  • 位宽或位范围 [ 起始 : 结束 ]: 指明了该配置项在寄存器中的具体位置。例如,[6] 表示第 6 位,[4:1] 表示从第 4 位到第 1 位的一组位。

  • 配置项名称 : 描述了该位或位组的功能,如 hsio_enet_rx_clk_pu 表示以太网接收时钟线上拉使能。

  • 默认值 (Default Value): 显示了在寄存器复位或初始化时该位或位组的值

  • 提供了关于该位或位组功能的详细描述,包括它们如何影响硬件的行为,例如,上拉或下拉使能,施密特触发,电流驱动能力等。

驱动调用示例代码

和 pinctrl 调用方法一致,驱动先通过 pinctrl-names 查找对应的 pinctrl state,然后再切换到对应的 state,具体调用流程可看 功能原理 章节。

static int hobot_pinctrl_probe(struct platform_device *pdev)
{
    ...
    g_xxx_dev->pinctrl = devm_pinctrl_get(&pdev->dev);
    if (IS_ERR(g_xxx_dev->pinctrl)) {
        dev_warn(&pdev->dev, "pinctrl get none\n");
        g_xxx_dev->pins_voltage = NULL;
    }
    ...
        /* 按照 pinctrl-names lookup state */
        g_xxx_dev->pins_voltage = pinctrl_lookup_state(g_xxx_dev->pinctrl,
                "xxx_voltage_func");
    if (IS_ERR(g_xxx_dev->pins_voltage)) {
        dev_info(&pdev->dev, "xxx_voltage_func get error %ld\n",
                PTR_ERR(g_xxx_dev->pins_voltage));
        g_xxx_dev->pins_voltage = NULL;
    }
    ...
        /* select state */
        if (g_xxx_dev->pins_voltage) {
            ret = pinctrl_select_state(g_xxx_dev->pinctrl, g_xxx_dev->pins_voltage);
            if (ret) {
                dev_info(&pdev->dev, "xxx_voltage_func set error %d\n", ret);
            }
        }
    ...
}

4.3.6.5. 功能使用

User Space

根据 《X5 PIN SW Reg.xlsx》 文档,举例将 HSIO_ENET_RX_CLK(即 HSIO_GPIO0_PIN08 )配置为输出 GPIO 的步骤

1. 设置 HSIO_GPIO0_PIN08 为输出模式:

  • 读取寄存器 GPIO_SWPORTA_DDR(地址 0x35060004 )的值

  • 将寄存器 GPIO_SWPORTA_DDR 的 bit8 设置为 1 ,以将引脚配置为输出模式。

devmem 0x35060004  # 读取寄存器 0x35060004
devmem 0x35060004 32 0xxxxxxxxx  # 写寄存器 0x35060004 ,将 bit8 设置为 0x1

2. 设置 HSIO_ENET_RX_CLK 输出电平:

  • 读取寄存器 GPIO_SWPORTA_DR(地址 0x35060000 )的值。

  • 将寄存器 GPIO_SWPORTA_DR 的 bit8 设置为 1 ,将输出电平设置为 1 ;或者将其设置为 0 ,将输出电平设置为 0 。

devmem 0x35060000  # 读取寄存器 0x35060000
devmem 0x35060000 32 0xxxxxxxxx  # 写寄存器 0x35060000 ,将 bit8 设置为所需电平( 0 或 1 )

3. 设置 HSIO_ENET_RX_CLK 输出电平:

  • 读取寄存器 hsio_pin_ctrl_1 (地址 0x35050018 )的值。

  • 将寄存器 hsio_pin_ctrl_1 的 bit[4:1] 设置为 0x2 ,以设置驱动强度为 7.5mA/10.6mA(具体驱动强度与硬件文档中的映射有关)。

devmem 0x35050018  # 读取寄存器 0x35050018
devmem 0x35050018 32 0xxxxxxxxx  # 写寄存器 0x35050018 ,将 bit[4:1] 设置为 0x2

4. 设置引脚为 GPIO 功能模式::

  • 读取寄存器 hsio_pinmux_ctl_1 (地址 0x3505005c)的值。

  • 将寄存器 hsio_pinmux_ctl_1 的 bit[15:14] 设置为 0x2 ,以将引脚设置为 GPIO 功能模式。

devmem 0x3505005c  # 读取寄存器 0x3505005c
devmem 0x3505005c 32 0xxxxxxxxx  # 写寄存器 0x3505005c,将 bit[15:14] 设置为 0x2

Uboot Space

Uboot 内已实现了 Pinctrl 驱动,使用方法与内核一致,在设备树内进行配置和使用,这里主要示例如何在 Uboot 下修改设备树和使用命令查看 IO-Domain 寄存器。

代码位置

/uboot/arch/arm/dts/pinmux-func.dtsi  # uboot 设备树 pinctrl 复用关系位置
/uboot/arch/arm/dts/x5.dtsi  # uboot 设备树引用节点位置

IO-Domain 的 DTS

配置选项为自定义的“ power-source”宏,如下所示。

...
	pconf_drv_pu_3v3_max: pconf-dev-pu-max-high {
		bias-pull-up;
		power-source = <HORIZON_IO_PAD_VOLTAGE_3V3>;
		drive-strength = <15>;
	};

	pconf_drv_pu_1v8_max: pconf-dev-pu-max-low {
		bias-pull-up;
		power-source = <HORIZON_IO_PAD_VOLTAGE_1V8>;
		drive-strength = <15>;
	};
...

	pinctrl_uart7: uart7grp {
		horizon,pins = <
			LSIO_UART7_RX	LSIO_PINMUX_3	BIT_OFFSET4		MUX_ALT0 &pconf_drv_pu_1v8_max
			LSIO_UART7_TX	LSIO_PINMUX_3	BIT_OFFSET6		MUX_ALT0 &pconf_drv_pu_1v8_max
			LSIO_UART7_CTS	LSIO_PINMUX_3	BIT_OFFSET8		MUX_ALT0 &pconf_drv_pu_1v8_max
			LSIO_UART7_RTS	LSIO_PINMUX_3	BIT_OFFSET10	MUX_ALT0 &pconf_drv_pu_1v8_max
		>;
	};
...

驱动调用时 DTS 配置

首先,在 DTS 内定义当前硬件的电压域配置,以配置 i2c 为 1.8V 为例:

	pinctrl_i2c1: i2c1grp {
		horizon,pins = <
			LSIO_I2C1_SCL  LSIO_PINMUX_2 BIT_OFFSET20  MUX_ALT0 &pconf_drv_pu_1v8_max
			LSIO_I2C1_SDA  LSIO_PINMUX_2 BIT_OFFSET22  MUX_ALT0 &pconf_drv_pu_1v8_max
		>;
	};

UBOOT 中设备树与内核中设备树基本一致, pinctrl 是用于配置引脚复用和电气特性的机制。在设备树中, pinctrl 节点指定了与特定硬件外设相关的引脚配置。在这里, pinctrl_i2c1 节点定义了与 I2C1 外设相关的引脚配置。

  • horizon,pins:这个属性定义了与 I2C1 相关的引脚配置。这里的每个项都是一个特定引脚的设置。

  • LSIO_I2C1_SCL:代表 I2C1 的时钟引脚( SCL)。

  • LSIO_I2C1_SDA:代表 I2C1 的数据引脚( SDA)。

  • LSIO_PINMUX_2:指定了一个特定的引脚复用组,用来配置这些引脚的功能。

  • BIT_OFFSET20BIT_OFFSET22:这些指定了具体引脚在寄存器中的位置偏移。

  • MUX_ALT0:设置引脚的复用功能为 I2C,即将引脚配置为 I2C 通信。

  • &pconf_drv_pu_1v8_max:引用外部的配置节点,通常定义了与引脚相关的电气特性,比如上拉电阻和驱动电压。

和 pinctrl 的使用方法类似,驱动在自己的 DTS 中引用需要配置的 IO-Domain ,以 i2c1 为例,配置如下:

	i2c1: i2c@340c0000 {
	    compatible = "snps,designware-i2c";
		status = "okay";
		reg = <0x340c0000 0x10000>;
		#address-cells = <1>;
		#size-cells = <0>;
		#clock-names = "i2c-clk";
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_i2c1>;
	};

这个节点描述了硬件外设 I2C1 本身,提供了外设的基地址、配置和状态信息 :

  • i2c@340c0000:节点的名称,标识了 I2C1 外设在系统中的位置。地址 0x340c0000 是该外设在内存中的起始地址。

  • compatible = “snps,designware-i2c”:这个属性指定了与该外设兼容的驱动程序。 snps,designware-i2c 是一个常见的 I2C 控制器 IP 核的兼容标识,表示这个 I2C 外设使用 Synopsys 的设计。

  • status = “okay”:启用该外设的状态。”okay” 表示启用该 I2C 外设, U-Boot 会为此外设加载相应的驱动程序。

  • reg = <0x340c0000 0x10000>:指定该外设的物理地址范围。 0x340c0000 是外设的起始地址, 0x10000 是外设的地址范围( 16KB)。

  • #address-cells = <1>#size-cells = <0>:这两个属性定义了地址和大小单元的数量。#address-cells = <1> 表示外设的地址由一个单元( 32 位)表示,#size-cells = <0> 表示没有额外的大小信息。

  • #clock-names = “i2c-clk”:指定与该外设相关的时钟名称,通常用来引用系统时钟。

  • pinctrl-names = “default”:指定使用默认的引脚控制配置。

  • pinctrl-0 = <&pinctrl_i2c1>:将前面定义的 pinctrl_i2c1 引脚配置应用于此 I2C 外设,确保该外设的引脚配置为 I2C1 引脚。

命令查询与使用方式

进入 UBOOT 时输入 I2C BUS 命令来查询 uboot 设备树中添加修改的 I2C1 配置是否生效。

Hobot>i2c bus
Bus 0:  i2c@340d0000
Bus 1:  i2c@340c0000

可以发现在 Uboot 中除了默认的 I2C2 总线外,额外探测到 I2C1 总线,地址为 0X340C 0000 ,说明 Uboot 中设备树的配置已生效,继续输入 MD 命令来查询电压域的寄存器 。

Hobot>md 0x34180080 1
34180080: 50555555

通过查询 Pin_Mux_List 手册, I2C1 的属性如下,通过 MD 输出结果对应电压域的偏移位 bit = 1 ,电压域为 1.8V ,与 Uboot 中设备树配置的电压域一致。

PinName Default IO Domain IO Domain Reg Reg Offset Reg Value
LSIO_I2C1_SCL 3.3v 0x34180080 21:20 1: 1.8V
LSIO_I2C1_SDA 3.3v 0x34180080 23:22 0: 3.3V

注意:

  • 以上 I2C 电源域修改仅为示例,实际电压域修改需要和实际硬件需求来修改对应的 dts 配置

4.3.6.6. FAQ

1、为什么 pinmux-func.dtsi 中 pinctrl_sd 和 pinctrl_sdio 中的电压域使用的配置为 pconf_sd_sdio_pu_ds3_ipctrl , 没有明确指明电压域的具体电压

	pconf_sd_sdio_pu_ds3_ipctrl: pconf-sd-sdio-pu-ds3-ipctrl {
		bias-pull-up;
		drive-strength = <3>;
		power-source = <HORIZON_IO_PAD_VOLTAGE_IP_CTRL>;
	};

:在 pinmux-func.dtsi 中,只有 pinctrl_sd 和 pinctrl_sdio 节点使用了相关的电压域配置,HORIZON_IO_PAD_VOLTAGE_IP_CTRL 代表此模块的电压域由硬件中配置引脚的电压而改变,通常主控在启动时首先以 3.3V 电压与 SDIO 设备进行通信, SDIO 设备会通过主控发出的命令确认其支持的电压,并决定是否切换到 1.8V 电压。

2、SDIO 设备的电压域是如何进行切换的

&sdio_0 {
	status = "okay";
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_sd &hsio_gpio0_26 &hsio_gpio1_1>;
	power-gpios = <&hs_gpio0_porta 26 GPIO_ACTIVE_HIGH>;
	/* Drive voltage gpio to 0 to switch to 1.8V */
	voltage-gpios = <&hs_gpio1_porta 1 GPIO_ACTIVE_LOW>;
};

HSIO_CTRL_DOMAIN HSIO_CTRL_DOMAIN

:在 硬件原理图中 HSIO_SD_XX 引脚相关的电压域由 VDDIO_SD 提供,那么如何实现 3v3 和 1v8 电压间的切换呢,可以发现在设备树中定义了 power-gpiosvoltage-gpios ,其配置中的引脚都被复用为 GPIO 功能,当此设备数的节点被内核 SDIO 控制器解析时,hsio_gpio0_26 用来控制 SD 卡 VDD 的电压开关,当引脚为高时开关打开 3.3V ,hsio_gpio1_1 默认状态的电压域为 3.3v,当引脚被拉低时硬件设计切换为 1.8v。这里列出手册中部分相关参数分别为 引脚名默认电压电源域偏移位 ,当第一位 bit 为 1 则代表 1.8v,为 0 则代表 3.3v。

引脚名 电压域默认值 偏移位 0:1.8v 1:3.3v
HSIO_SD_SDCLK 3.3V 1
HSIO_SD_CMD 3.3V 1
HSIO_SD_CDN 3.3V 1
HSIO_SD_DATA_0 3.3V 1
HSIO_SD_DATA_1 3.3V 1
HSIO_SD_DATA_2 3.3V 1
HSIO_SD_DATA_3 3.3V 1
HSIO_SDIO_WP 3.3V 1
HSIO_SDIO_SDCLK 3.3V 1
HSIO_SDIO_CMD 3.3V 1
HSIO_SDIO_CDN 3.3V 1
HSIO_SDIO_DATA_0 3.3V 1
HSIO_SDIO_DATA_1 3.3V 1
HSIO_SDIO_DATA_2 3.3V 1
HSIO_SDIO_DATA_3 3.3V 1

在内核驱动中 horizon_pin_power_source 添加打印,内核日志如下

[    2.236243] horizon-hsio-pinctrl 35050000.hsio_iomuxc: Read value from register: 0xd
[    2.248841] horizon-hsio-pinctrl 35050000.hsio_iomuxc: ms_bits_offset: 0x2
[    2.261723] horizon-hsio-pinctrl 35050000.hsio_iomuxc: flags: 0x2
[    2.277303] horizon-hsio-pinctrl 35050000.hsio_iomuxc: Read value from register: 0xf

[    3.915439] horizon-hsio-pinctrl 35050000.hsio_iomuxc: Modified value for register: 0xf
[    3.930253] horizon-hsio-pinctrl 35050000.hsio_iomuxc: ms_bits_offset: 0x2
[    3.930258] horizon-hsio-pinctrl 35050000.hsio_iomuxc: flags: 0x2
[    3.930262] horizon-hsio-pinctrl 35050000.hsio_iomuxc: Read value from register: 0xf
  • Read value from register: 代表读当前电压域地址的值。

  • ms_bits_offset:代表电压域地址的偏移。

  • flags:代表设备树中电压域使用的是 power-source = <HORIZON_IO_PAD_VOLTAGE_IP_CTRL>。

    • HORIZON_IO_PAD_VOLTAGE_3V3 : 0

    • HORIZON_IO_PAD_VOLTAGE_1V8 : 1

    • HORIZON_IO_PAD_CTRL_VOLTAGE_1V8 : 3

    • HORIZON_IO_PAD_CTRL_VOLTAGE_3V3 : 4

  • Modified value for register: 代表位操作后电压域地址的值。

通过 dmesg 打印信息可以发现 HSIO_SD_XX 引脚的电压域由 3.3v 切换至了 1.8v。