飞思卡尔 QUICC 引擎固件上传¶
2007 Timur Tabi <timur at freescale.com>, 飞思卡尔半导体
修订信息¶
2007 年 11 月 30 日:Rev 1.0 - 初始版本
I - 固件软件许可¶
每个固件文件都有其自己的软件许可。有关特定许可的信息,请参阅随固件分发的许可文本。
II - 微码可用性¶
固件文件通过各种渠道分发。有些可以在 http://opensource.freescale.com 上找到。对于其他固件文件,请联系您的飞思卡尔代表或您的操作系统供应商。
III - 描述和术语¶
在本文档中,术语“微码”是指组成实际 QE 微码的 32 位整数序列。
术语“固件”是指包含微码以及其他数据的二进制 blob,这些数据
描述微码的用途
描述如何以及在哪里上传微码
指定各种寄存器的值
包括特定设备驱动程序使用的其他数据
固件文件是仅包含固件的二进制文件。
IV - 微码编程细节¶
QE 架构只允许每个 RISC 处理器在 I-RAM 中存在一个微码。要替换任何当前的微码,必须首先执行完整的 QE 复位(这会禁用微码)。
使用以下过程上传 QE 微码
使用 IRAM.IADD 和 IRAM.IDATA 寄存器将微码放置在 I-RAM 中的特定位置。
根据固件是否需要拆分 I-RAM,将 CERCR.CIR 位设置为 0 或 1。拆分 I-RAM 仅对于具有多个 RISC 处理器的 QE 的 SOC(例如 8360)有意义。拆分 I-RAM 允许每个处理器运行不同的微码,从而有效地创建一个非对称多处理 (AMP) 系统。
TIBCR 陷阱寄存器加载微码中陷阱处理程序的地址。
RSP.ECCR 寄存器使用提供的值进行编程。
如有必要,需要虚拟陷阱和扩展模式数据的设备驱动程序将使用它们。
虚拟微码陷阱
这些虚拟陷阱是微码中的条件分支。这些是在 ROM 代码中引入的“软”临时分支,以便实现更高的灵活性并节省硬件陷阱。如果在 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 - 固件结构布局¶
来自飞思卡尔的 QE 微码通常以头文件形式提供。此头文件包含定义微码二进制文件本身以及上传该微码时使用的其他一些数据的宏。这些文件的格式不利于简单地包含到其他代码中。因此,需要一种更便携的格式。本节定义该格式。
微码和相关数据不是分发头文件,而是嵌入到二进制 blob 中。此 blob 被传递到 qe_upload_firmware() 函数,该函数解析 blob 并执行上传微码所需的一切操作。
所有整数都是大端字节序。有关最新的实现信息,请参阅函数 qe_upload_firmware() 的注释。
此结构支持版本控制,其中结构的 version 嵌入到结构本身中。为确保向前和向后兼容性,所有版本的结构都必须在开头使用相同的“qe_header”结构。
- ‘header’(类型:struct qe_header)
‘length’ 字段是整个结构的大小(以字节为单位),包括其中嵌入的所有微码以及 CRC(如果存在)。
‘magic’ 字段是一个三字节数组,其中包含字母“Q”、“E”和“F”。这是一个标识符,指示此结构是 QE 固件结构。
‘version’ 字段是一个单字节,指示此结构的 version。如果结构的布局需要更改以添加对其他类型微码的支持,则也应更改 version 号。
‘id’ 字段是一个以 null 结尾的字符串(适合打印),用于标识固件。
‘count’ 字段指示“微码”结构的数目。每个 RISC 处理器必须有且只有一个“微码”结构。因此,此字段也表示此 SOC 的 RISC 处理器数量。
‘soc’ 结构包含用于将微码与 SOC 本身匹配的 SOC 编号和修订版本。通常,微码加载程序应使用 SOC 编号和修订版本检查此结构中的数据,并且仅在匹配时才上传微码。但是,并非在所有平台上都进行此检查。
虽然不建议这样做,但您可以在 soc.model 字段中指定 ‘0’ 以完全跳过匹配 SOC。
‘model’ 字段是一个 16 位数字,与实际的 SOC 匹配。‘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 程序,该程序从通常由飞思卡尔分发的头文件创建固件二进制文件。