1 分钟阅读 次阅读

概要:本文探讨了RK3568 GPIO驱动强度的设置方法,分析了相关代码实现及驱动强度的特性。文中指出驱动强度的设置与引脚类型有关,并提到官方文档中驱动能力与level的对应关系存在特殊情况。

1. 驱动强度设置背景

1.1 文件位置

  • 设备树文件
    kernel/arch/arm64/boot/dts/rockchip/rockchip-pinconf.dtsi
    定义了与驱动强度相关的内容,例如:
    pcfg_pull_none_drv_level_0: pcfg-pull-none-drv-level-0 {
        bias-disable;
        drive-strength = <0>;
    };
    

2. 驱动强度设置代码分析

2.1 核心代码片段

  • 驱动代码文件
    kernel/drivers/pinctrl/pinctrl-rockchip.c

以下是删除与RK3568无关内容后的驱动强度设置代码:

static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
				     int pin_num, int strength)
{
	struct rockchip_pinctrl *info = bank->drvdata;
	struct rockchip_pin_ctrl *ctrl = info->ctrl;
	struct regmap *regmap;
	int reg, ret, i, err;
	u32 data, rmask, rmask_bits, temp;
	u8 bit;
	int drv_type = bank->drv[pin_num / 8].drv_type;

	dev_dbg(info->dev, "setting drive of GPIO%d-%d to %d\n",
		bank->bank_num, pin_num, strength);

	ctrl->drv_calc_reg(bank, pin_num, &regmap, &reg, &bit);
	if (ctrl->type == RV1126) {
		rmask_bits = RV1126_DRV_BITS_PER_PIN;
		ret = strength;
		goto config;
	} else if (ctrl->type == RK3568) {
		rmask_bits = RK3568_DRV_BITS_PER_PIN;
		ret = (1 << (strength + 1)) - 1;
		goto config;
	}
...
config:
	/* enable the write to the equivalent lower bits */
	data = ((1 << rmask_bits) - 1) << (bit + 16);
	rmask = data | (data >> 16);
	data |= (ret << bit);

	err = regmap_update_bits(regmap, reg, rmask, data);
	if (err)
		return err;

	if (ctrl->type == RK3568 && rockchip_get_cpu_version() == 0) {
		// 特定引脚的特殊处理
		if (bank->bank_num == 1 && pin_num == 21)
			reg = 0x0840;
		else if (bank->bank_num == 2 && pin_num == 2)
			reg = 0x0844;
		else if (bank->bank_num == 2 && pin_num == 8)
			reg = 0x0848;
		else if (bank->bank_num == 3 && pin_num == 0)
			reg = 0x084c;
		else if (bank->bank_num == 3 && pin_num == 6)
			reg = 0x0850;
		else if (bank->bank_num == 4 && pin_num == 0)
			reg = 0x0854;
		else
			return 0;

		data = ((1 << rmask_bits) - 1) << 16;
		rmask = data | (data >> 16);
		data |= (1 << (strength + 1)) - 1;

		err = regmap_update_bits(regmap, reg, rmask, data);
		if (err)
			return err;
	}

	if (drv_type == DRV_TYPE_IO_SMIC) {
		ctrl->slew_rate_calc_reg(bank, pin_num, &regmap, &reg, &bit);
		data = BIT(bit + 16) | (((ret >> 2) & 0x1) << bit);
		err = regmap_write(regmap, reg, data);
		if (err)
			return err;
	}

	return 0;
}

2.2 驱动强度设置的关键逻辑

  • rmask_bits
    • 对于RK3568,rmask_bits 的值为8。
  • 驱动强度计算
    • 假设设置驱动强度为1:
      data = ((1 << rmask_bits) - 1) << 16; // data = 11111111 00000000 00000000
      rmask = data | (data >> 16);         // rmask = 11111111 00000000 11111111
      data |= (1 << (strength + 1)) - 1;   // data = 0000 0011
      
  • 寄存器更新
    • 使用 regmap_update_bits 更新寄存器值。

3. 驱动强度的特性

3.1 不同引脚的驱动强度支持

  • GPIO3A6
    alt text

    • 从手册中可以看到,GPIO3A6 double bonding PAD Strength control,DS[11:6]
    • 也就是说GPIO3A6是支持双键合驱动强度控制,0-11共十二级
  • GPIO1B1alt text

    • 仅支持6级驱动强度。

3.2 官方文档中的驱动强度表

  • 在文件 RK3568_PinOut_V1.1_20210202.xlsx 中,可以查到每个引脚支持的驱动强度及默认值。

3.3 驱动能力与level的特殊对应关系

  • 在官方文档 RK官方文档\01、Linux\Common\Pin-Ctrl\Rockchip_Developer_Guide_Linux_Pinctrl_CN.pdf 中,驱动能力与level的对应关系如下:
    alt text
    • 驱动能力由小到大依次是:level0level4level2level6level1level5
    • 这表明驱动能力似乎并非随着level的增大而线性增强,而是存在特定的映射关系。

留下评论