Freescale QUICC Engine 固件上传

  1. 2007 Timur Tabi <timur at freescale.com>, Freescale Semiconductor

修订信息

2007年11月30日:版本 1.0 - 初始版本

I - 固件软件许可

每个固件文件都附带其自己的软件许可。有关特定许可的信息,请参阅随固件一起分发的许可文本。

II - 微代码可用性

固件文件通过各种渠道进行分发。部分文件可在 http://opensource.freescale.com 获取。对于其他固件文件,请联系您的 Freescale 代表或您的操作系统供应商。

III - 描述与术语

在本文档中,术语“微代码”(microcode)指组成实际 QE 微代码的一系列 32 位整数。

术语“固件”(firmware)指一个二进制 blob,它包含微代码以及其他以下数据:

  1. 描述微代码的用途

  2. 描述如何以及在哪里上传微代码

  3. 指定各种寄存器的值

  4. 包含供特定设备驱动程序使用的附加数据

固件文件是仅包含固件的二进制文件。

IV - 微代码编程细节

QE 架构允许每个 RISC 处理器的 I-RAM 中仅存在一个微代码。要替换任何当前的微代码,必须首先执行完整的 QE 复位(这会禁用微代码)。

QE 微代码通过以下步骤进行上传:

  1. 使用 IRAM.IADD 和 IRAM.IDATA 寄存器,将微代码置于 I-RAM 的特定位置。

  2. 根据固件是否需要拆分 I-RAM,将 CERCR.CIR 位设置为 0 或 1。拆分 I-RAM 仅对于具有多 RISC 处理器 QE 的 SOC(例如 8360)才有意义。拆分 I-RAM 允许每个处理器运行不同的微代码,从而有效地创建一个非对称多处理(AMP)系统。

  3. 将微代码中陷阱处理程序的地址加载到 TIBCR 陷阱寄存器中。

  4. 使用提供的值对 RSP.ECCR 寄存器进行编程。

  5. 如有必要,需要虚拟陷阱和扩展模式数据的设备驱动程序将使用它们。

虚拟微代码陷阱

这些虚拟陷阱是微代码中的条件分支。为了实现更高的灵活性并节省硬件陷阱,ROMcode 中引入了这些“软”临时机制。如果在 RAM 软件包中激活了新功能或正在修复问题,则应将其激活。此数据结构向微代码指示哪些虚拟陷阱处于活动状态。

此结构包含应用程序应复制到某些特定已定义位置的 6 个字。下表描述了该结构

---------------------------------------------------------------
| Offset in |                  | Destination Offset | Size of |
|   array   |     Protocol     |   within PRAM      | Operand |
--------------------------------------------------------------|
|     0     | Ethernet         |      0xF8          | 4 bytes |
|           | interworking     |                    |         |
---------------------------------------------------------------
|     4     | ATM              |      0xF8          | 4 bytes |
|           | interworking     |                    |         |
---------------------------------------------------------------
|     8     | PPP              |      0xF8          | 4 bytes |
|           | interworking     |                    |         |
---------------------------------------------------------------
|     12    | Ethernet RX      |      0x22          | 1 byte  |
|           | Distributor Page |                    |         |
---------------------------------------------------------------
|     16    | ATM Globtal      |      0x28          | 1 byte  |
|           | Params Table     |                    |         |
---------------------------------------------------------------
|     20    | Insert Frame     |      0xF8          | 4 bytes |
---------------------------------------------------------------

扩展模式

这是一个双字位数组(64 位),定义了对软件驱动程序有影响的特殊功能。每一位都有其自己的影响,并为其关联的软件提供了特殊说明。下表描述了此结构

-----------------------------------------------------------------------
| Bit #  |     Name     |   Description                               |
-----------------------------------------------------------------------
|   0    | General      | Indicates that prior to each host command   |
|        | push command | given by the application, the software must |
|        |              | assert a special host command (push command)|
|        |              | CECDR = 0x00800000.                         |
|        |              | CECR = 0x01c1000f.                          |
-----------------------------------------------------------------------
|   1    | UCC ATM      | Indicates that after issuing ATM RX INIT    |
|        | RX INIT      | command, the host must issue another special|
|        | push command | command (push command) and immediately      |
|        |              | following that re-issue the ATM RX INIT     |
|        |              | command. (This makes the sequence of        |
|        |              | initializing the ATM receiver a sequence of |
|        |              | three host commands)                        |
|        |              | CECDR = 0x00800000.                         |
|        |              | CECR = 0x01c1000f.                          |
-----------------------------------------------------------------------
|   2    | Add/remove   | Indicates that following the specific host  |
|        | command      | command: "Add/Remove entry in Hash Lookup   |
|        | validation   | Table" used in Interworking setup, the user |
|        |              | must issue another command.                 |
|        |              | CECDR = 0xce000003.                         |
|        |              | CECR = 0x01c10f58.                          |
-----------------------------------------------------------------------
|   3    | General push | Indicates that the s/w has to initialize    |
|        | command      | some pointers in the Ethernet thread pages  |
|        |              | which are used when Header Compression is   |
|        |              | activated.  The full details of these       |
|        |              | pointers is located in the software drivers.|
-----------------------------------------------------------------------
|   4    | General push | Indicates that after issuing Ethernet TX    |
|        | command      | INIT command, user must issue this command  |
|        |              | for each SNUM of Ethernet TX thread.        |
|        |              | CECDR = 0x00800003.                         |
|        |              | CECR = 0x7'b{0}, 8'b{Enet TX thread SNUM},  |
|        |              |        1'b{1}, 12'b{0}, 4'b{1}              |
-----------------------------------------------------------------------
| 5 - 31 |     N/A      | Reserved, set to zero.                      |
-----------------------------------------------------------------------

V - 固件结构布局

Freescale 的 QE 微代码通常作为头文件提供。该头文件包含定义微代码二进制文件本身的宏,以及用于上传该微代码的其他一些数据。这些文件的格式不适合简单地包含到其他代码中。因此,需要一种更具可移植性的格式。本节定义了该格式。

微代码和相关数据没有分发头文件,而是嵌入到了一个二进制 blob 中。该 blob 被传递给 qe_upload_firmware() 函数,该函数解析 blob 并执行上传微代码所需的一切操作。

所有整数均为大端序。有关最新的实现信息,请参阅函数 qe_upload_firmware() 的注释。

此结构支持版本控制,结构的版本嵌入在结构本身中。为确保向前和向后兼容性,所有版本的结构必须在开头使用相同的“qe_header”结构。

‘header’(类型:struct qe_header)

‘length’ 字段是整个结构的大小(以字节为单位),包括其中嵌入的所有微代码以及 CRC(如果存在)。

‘magic’ 字段是一个包含字母 ‘Q’、‘E’ 和 ‘F’ 的三个字节的数组。这是一个标识符,指示此结构是 QE 固件结构。

‘version’ 字段是一个单字节,指示此结构的版本。如果需要更改结构的布局以支持其他类型的微代码,则也应更改版本号。

‘id’ 字段是一个以 null 结尾的字符串(适合打印),用于标识固件。

‘count’ 字段指示 ‘microcode’ 结构的数量。每个 RISC 处理器必须有且仅有一个 ‘microcode’ 结构。因此,该字段也表示此 SOC 的 RISC 处理器的数量。

‘soc’ 结构包含用于将微代码与 SOC 本身进行匹配的 SOC 编号和修订版本。通常,微代码加载程序应使用 SOC 编号和修订版本检查此结构中的数据,并且仅在匹配时才上传微代码。但是,并非所有平台都进行此项检查。

尽管不推荐,但您可以在 soc.model 字段中指定“0”以完全跳过 SOC 匹配。

‘model’ 字段是一个与实际 SOC 匹配的 16 位数字。‘major’ 和 ‘minor’ 字段分别是 SOC 的主修订号和次修订号。

例如,要匹配 8323,版本 1.0

soc.model = 8323
soc.major = 1
soc.minor = 0

‘padding’ 对于结构对齐是必需的。此字段确保 ‘extended_modes’ 字段对齐到 64 位边界。

‘extended_modes’ 是一个位域,定义了对设备驱动程序有影响的特殊功能。每一位都有其自己的影响,并为其关联的驱动程序提供特殊说明。此字段存储在 QE 库中,可供任何调用 qe_get_firmware_info() 的驱动程序使用。

‘vtraps’ 是一个包含 8 个字的数组,其中包含每个虚拟陷阱的虚拟陷阱值。与 ‘extended_modes’ 一样,此字段存储在 QE 库中,可供任何调用 qe_get_firmware_info() 的驱动程序使用。

‘microcode’(类型:struct qe_microcode)

每个 RISC 处理器都有一个 ‘microcode’ 结构。第一个 ‘microcode’ 结构对应第一个 RISC,依此类推。

‘id’ 字段是一个适合打印的以 null 结尾的字符串,用于标识此特定微代码。

‘traps’ 是一个包含 16 个字的数组,其中包含 16 个陷阱中每一个的硬件陷阱值。如果 trap[i] 为 0,则应忽略此特定陷阱(即不写入 TIBCR[i])。整个值将原样写入 TIBCR[i] 寄存器,因此请确保在必要时设置 EN 和 T_IBP 位。

‘eccr’ 是要编程到 ECCR 寄存器中的值。

‘iram_offset’ 是开始写入微代码的 IRAM 偏移量。

‘count’ 是微代码中 32 位字的数量。

‘code_offset’ 是从该结构开头到可以找到微代码本身的偏移量(以字节为单位)。第一个微代码二进制文件应位于 ‘microcode’ 数组之后。

‘major’、‘minor’ 和 ‘revision’ 分别是微代码的主版本号、次版本号和修订版本号。如果所有值都为 0,则忽略这些字段。

‘reserved’ 对于结构对齐是必需的。由于 ‘microcode’ 是一个数组,64 位的 ‘extended_modes’ 字段需要对齐到 64 位边界,而这只有在 ‘microcode’ 的大小是 8 字节的倍数时才能实现。为了确保这一点,我们添加了 ‘reserved’。

最后一个微代码之后是一个 32 位 CRC。可以使用以下算法计算它

u32 crc32(const u8 *p, unsigned int len)
{
      unsigned int i;
      u32 crc = 0;

      while (len--) {
         crc ^= *p++;
         for (i = 0; i < 8; i++)
                 crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0);
      }
      return crc;
}

VI - 用于创建固件文件的示例代码

可以从 http://opensource.freescale.com 找到一个 Python 程序,它用于从 Freescale 通常分发的头文件创建固件二进制文件。