请教CPLD通过I²C升级时对SMC的依赖,以及无SMC场景的适配方法

各位大佬好,我正在研究openUBMC的CPLD I²C升级流程,参考了现有代码和下帖的流程图,想确认无 SMC 场景下的适配方式

目标:由 BMC 通过 I²C 升级目标板上的 CPLD 固件,目标板不提供 SMC 命令接口。

根据目前的理解:

  • 在 iic_process.lua 的 i2c_load_cpld() 中,通过 fw.smc_chip 构造 SMC 接口,并调用:

    • get_cpld_upgrade_info():获取并检查升级模式;
    • get_cpld_manufature():获取厂商类型和 SKU。
  • 后续根据厂商选择升级函数,传入的是 fw.i2c_upgrade_chip。安陆分支通过该对象执行模式设置、擦除,以及 PluginRequest('iic_upgrade_anlu') 数据写入。

  • 流程图中,上述两次信息查询明确指向 SMC,后续擦写操作指向I2C芯片。但仅凭流程图和接口名称,我还不能确定底层是否仍然依赖 SMC。

想请教以下几个问题:

  1. I2CUpgradeChip 是否支持配置为 BMC 直接通过 I²C 访问的 CPLD?还是现有实现要求由 SMC 转发或配合?这一点主要由 Chip 类型、总线拓扑配置决定,还是升级插件内部也存在 SMC 依赖?

  2. 假设硬件支持 BMC 直接访问 CPLD 的升级接口,无 SMC 场景下能否复用现有安陆升级算法?除了替代上述两次 SMC 信息查询外,是否还需要修改其他环节?

  3. 升级模式、厂商类型和 SKU,在无 SMC 场景下推荐从哪里获取?例如:

    • 在板型的 SR/CSR 配置中静态指定;
    • 从 EEPROM 或板卡识别信息获取;
    • 通过 CPLD 的可读寄存器或器件 ID 识别。

    这些方式中,框架是否已有可复用的配置项或接口?其中 SKU 是否只是板型相关的升级参数,还是必须从硬件动态读取?

  4. 是否有现成的 无 SMC、BMC 直连 I²C 升级 CPLD 的板型配置或示例可供参考?如果需要自行适配,建议从哪些文件或接口入手?

以上是我对当前流程的理解,如有偏差,也请帮忙指正,谢谢。

答案内容由AI生成,仅供参考:

总结

  • 当前实现存在插件级 SMC 依赖:i2c_load_cpld() 没有 fw.smc_chip 会直接失败,并通过 SMC 获取升级模式、厂商和 SKU。
  • I2CUpgradeChip 负责实际 I²C 擦写通信,但不能替代 SMC 信息查询。
  • 无 SMC 场景不能原样复用现有流程;需要替代升级模式、厂商类型和 SKU 的来源,之后才可能复用安陆擦写算法。
  • SKU 可通过 sub_component_sku 覆盖,但升级模式和厂商类型在上下文中没有现成静态配置接口。
  • 上下文中没有无 SMC 直连 I²C 升级 CPLD 的现成示例;适配应从 iic_process.lua、cpld_chip.lua、iic_upgrade_anlu、update.cfg 和 SR 中的 LogicFirmware/I2CUpgradeChip 配置入手,但具体无 SMC 实现需自行补充,当前资料不足以给出完整改造方案。
点击此处查看详细分析解答

结论先行

根据提供的代码片段、流程图说明和论坛内容,现有 openUBMC 的 CPLD I²C 升级实现并不是仅依赖 I2CUpgradeChip,而是在升级插件内部显式依赖 SMC 接口:

  • i2c_process.i2c_load_cpld() 入口首先检查 fw.smc_chip;没有则直接报错并返回:
    • [CPLD]no smc chip, can not get upgrade info
  • 随后通过 smc_interface.new(fw.smc_chip['bmc.kepler.Chip.BlockIO']) 调用:
    • get_cpld_upgrade_info():获取并检查升级模式;
    • get_cpld_manufature():获取厂商类型和 SKU。
  • 实际擦写阶段才使用 fw.i2c_upgrade_chip,例如安陆分支通过该对象执行 SPI 模式设置、扇区擦除和 PluginRequest('iic_upgrade_anlu') 数据写入。

因此,“无 SMC、BMC 直连 I²C 升级 CPLD”在当前代码路径下不能直接复用,需要替代上述 SMC 信息查询环节。上下文中没有给出已实现的无 SMC 板型示例。


1. I2CUpgradeChip 是否支持 BMC 直连 I²C?是否存在插件内部 SMC 依赖?

I2CUpgradeChip 的作用

I2CUpgradeChip 是用于 I²C 固件升级的芯片对象/属性,现有实现中用于和 CPLD 进行实际 I²C 通信:

  • I2CUpgradeChip 是 I²C 接口组件,负责通过 I²C 协议更新固件;
  • 它使能对 CPLD 的交互,用于 I²C 固件更新;
  • 示例 SR 配置中可见:
    • I2CUpgradeChip: #/Chip_Cpld
    • I2CUpgradeLockChip: #/Chip_Cpld
    • Chip_Cpld 的 Address 为 120

所以,从属性定义和 SR 示例看,I2CUpgradeChip 可以配置为指向 I²C 芯片对象,用于实际升级通信。

但现有实现仍要求 SMC 配合

代码片段明确显示:

  • i2c_load_cpld() 中先判断 fw.smc_chip;
  • 没有 smc_chip 时直接返回 defs.RET.ERR;
  • 升级模式和厂商/SKU 信息均通过 SMC 接口获取。

知识图谱关系也表明:

  • IIC 通过 get_cpld_upgrade_info 从 SMC 获取 I2C_UPGRADE_MODE;
  • IIC 通过 get_cpld_manufature 从 SMC 获取厂商类型和 SKU_ID;
  • C2A 在 I²C 升级期间通过 LogicFirmware.SmcChip 访问 SMC 接口。

因此,SMC 依赖不仅由 Chip 类型或总线拓扑决定,升级插件内部也存在 SMC 依赖。I2CUpgradeChip 解决的是“实际通过哪个 I²C 芯片对象擦写 CPLD”,但不能替代 smc_chip 完成升级模式、厂商和 SKU 查询。


2. 无 SMC 场景能否复用现有安陆升级算法?

不能原样复用

现有 i2c_load_cpld() 在进入安陆升级算法前,必须先完成:

  1. 检查 fw.smc_chip 是否存在;
  2. 通过 get_cpld_upgrade_info() 获取升级信息,并确认等于 I2C_UPGRADE_MODE;
  3. 通过 get_cpld_manufature() 获取厂商类型和 SKU_ID;
  4. 根据厂商类型选择 MANUFACTURE_CFG 和升级文件 cpld%02x.bin;
  5. 调用对应 upgrade_func(fw.i2c_upgrade_chip, upgrade_path, sku_id)。

因此,无 SMC 场景下不能直接原样复用;若没有 fw.smc_chip,代码会在入口处直接返回错误。

安陆写入/擦除算法本身可复用的条件

从流程图和说明看,安陆分支的算法包括:

  • 读取 cpld01.bin;
  • set_spi_mode(0xF0) 配置 SPI 模式;
  • 按 SKU 擦除扇区:
    • SKU_ID == EF2 时擦除 4 个扇区;
    • 其他 SKU 擦除 6 个扇区;
  • 循环设置 bypass、擦除扇区并等待 400ms;
  • 通过 PluginRequest('iic_upgrade_anlu') 写入数据。

这些擦写步骤使用 fw.i2c_upgrade_chip 与 CPLD 交互。因此,如果无 SMC 场景下能够提供等效的升级模式、厂商类型和 SKU,并保证 fw.i2c_upgrade_chip 可访问目标 CPLD,则底层安陆擦写算法具备复用基础。但当前上下文没有给出替代 SMC 查询的具体实现。

还需要关注的环节

除两次 SMC 查询外,现有 I²C CPLD 升级还涉及以下约束:

  • update.cfg 需配置 UpdateLink=1,才会走 I²C 升级分支;
  • SR 中需要配置 I2CUpgradeChip,否则可能走 JTAG 分支并因缺少 I2CUpgradeChip 而失败;
  • 升级前会根据 Routes 关联寄存器切换到预期升级通道,并与 FirmwareRoute 匹配;
  • I²C 升级仅支持冷升级,不支持热升级,升级文件格式为 .bin;
  • 升级文件命名按厂商生成,如 cpld01.bin、cpld02.bin;
  • cpld_chip.lua 中存在 support_list 数组,用于标识支持的 CPLD 型号;若型号不在数组中,会直接报错退出;
  • SMC 级联场景下,由于上一级 SMC 会填充下一级控制头 4 字节,iic_upgrade_anlu 中单次写入长度 written_len 应取 128,而不是 256。

这些环节是否全部需要因“无 SMC”而修改,上下文不能完全确认;但至少入口处的 SMC 查询是明确阻塞点。


3. 无 SMC 场景下升级模式、厂商类型和 SKU 从哪里获取?

升级模式

当前上下文中,升级模式仅见通过 get_cpld_upgrade_info() 从 SMC 获取,并要求等于 I2C_UPGRADE_MODE(流程图中为 3)。

未看到 SR/CSR 中静态配置升级模式的现成项或接口。

厂商类型

当前仅见通过 get_cpld_manufature() 从 SMC 获取厂商类型和 SKU。

厂商类型会用于:

  • 选择 MANUFACTURE_CFG;
  • 生成升级文件路径 cpld%02x.bin;
  • 选择安陆或其他厂商升级函数。

未看到 SR/CSR 或 EEPROM 中获取厂商类型的现成配置项或接口。

SKU

SKU 当前先从 SMC 获取,但代码中存在覆盖逻辑:

if fw.sub_component_sku and fw.sub_component_sku ~= 255 then
    sku_id = fw.sub_component_sku
end

说明:

  • SubComponentSku 默认值为 255;
  • 如果配置了 fw.sub_component_sku 且不等于 255,则可用配置值覆盖 SMC 返回的 SKU;
  • SKU 会影响升级路径和安陆擦除策略,例如 SKU_ID == EF2 时擦除 4 个扇区,其他 SKU 擦除 6 个扇区。

因此,从现有代码看,SKU 至少可以通过 sub_component_sku 配置覆盖,不一定必须完全依赖 SMC 动态读取。但上下文没有明确说明 SKU 是否只是板型相关参数,还是必须从硬件动态读取。

其他配置项

FirmwareComponentInfo 可用于在 platform.sr 中配置固件识别信息,例如:

  • ComponentID
  • ComponentIDEx
  • Name
  • RevisionNumber

但这些字段用于确认固件类型和防回退等,不是升级模式、厂商类型或 SKU 的替代来源。上下文也没有提供通过 EEPROM、板卡识别信息或 CPLD 可读寄存器获取这三类信息的现成接口。


4. 是否有无 SMC、BMC 直连 I²C 升级 CPLD 的示例?适配应从哪些文件入手?

是否有现成示例

根据当前上下文,没有看到“无 SMC、BMC 直连 I²C 升级 CPLD”的完整板型配置或示例。

现有 I²C SR 示例可以作为 I2CUpgradeChip 配置参考,例如:

  • Chip_Cpld 配置 Address: 120;
  • LogicFirmware_BCU_1 中配置:
    • I2CUpgradeChip: #/Chip_Cpld
    • I2CUpgradeLockChip: #/Chip_Cpld
    • Routes: #/Accessor_JtagSwitch.Value
    • DefaultRoute: 0
    • FirmwareRoute: 0
    • ValidMode: 1
    • ValidAction: #/Accessor_AC.Value
    • SoftwareId: CPLD-BC83AMDA

但这些示例不能证明无 SMC 场景可直接使用;当前代码仍要求 fw.smc_chip。

建议关注的代码和配置入口

若自行适配,建议从以下位置入手:

  1. general_hardware 中的 iic_process.lua

    • 重点看 i2c_process.i2c_load_cpld();
    • 当前 SMC 依赖集中在该函数入口的 fw.smc_chip 检查、get_cpld_upgrade_info() 和 get_cpld_manufature() 调用。
  2. cpld_chip.lua 中的 support_list

    • 用于判断待升级 CPLD 型号是否受支持;
    • 若型号不在数组中,会直接报错退出。
  3. include/hwproxy/plugins/general_hardware/init.lua 中的 iic_upgrade_anlu

    • 关注单次写入长度 written_len;
    • 级联场景下应取 128,避免因 SMC 级联控制头导致长度问题。
  4. 固件包 update.cfg

    • 配置 UpdateLink=1 以选择 I²C 升级链路;
    • 关注 ComponentID、ComponentIDEx 与 FirmwareComponentInfo 的匹配;
    • 热升级相关配置如 HotValidList;但 I²C 升级当前仅支持冷升级。
  5. SR/CSR 中的 LogicFirmware 对象

    • 配置 I2CUpgradeChip、I2CUpgradeLockChip;
    • 配置 Routes、DefaultRoute、FirmwareRoute;
    • Location 表示逻辑位号,是固定配置,后台会转换为接口查询展示的 Uxx;
    • Routes 关联寄存器会在升级 CPLD 前切换到预期升级通道,并与 FirmwareRoute 匹配。
  6. platform.sr 中的 FirmwareComponentInfo

    • 新增固件升级类型时需要配置;
    • ComponentID 和 ComponentIDEx 会确认一个固件;
    • 若升级固件的 ComponentID/ComponentIDEx 无法与已有 FirmwareComponentInfo 匹配,则无法升级;
    • 新增 FirmwareComponentInfo 后,firmware_mgmt 组件不需要改动。

总结

  • 当前实现存在插件级 SMC 依赖:i2c_load_cpld() 没有 fw.smc_chip 会直接失败,并通过 SMC 获取升级模式、厂商和 SKU。
  • I2CUpgradeChip 负责实际 I²C 擦写通信,但不能替代 SMC 信息查询。
  • 无 SMC 场景不能原样复用现有流程;需要替代升级模式、厂商类型和 SKU 的来源,之后才可能复用安陆擦写算法。
  • SKU 可通过 sub_component_sku 覆盖,但升级模式和厂商类型在上下文中没有现成静态配置接口。
  • 上下文中没有无 SMC 直连 I²C 升级 CPLD 的现成示例;适配应从 iic_process.lua、cpld_chip.lua、iic_upgrade_anlu、update.cfg 和 SR 中的 LogicFirmware/I2CUpgradeChip 配置入手,但具体无 SMC 实现需自行补充,当前资料不足以给出完整改造方案。