|  | Freescale QUICC Engine Firmware Uploading | 
|  | ----------------------------------------- | 
|  |  | 
|  | (c) 2007 Timur Tabi <timur at freescale.com>, | 
|  | Freescale Semiconductor | 
|  |  | 
|  | Table of Contents | 
|  | ================= | 
|  |  | 
|  | I - Software License for Firmware | 
|  |  | 
|  | II - Microcode Availability | 
|  |  | 
|  | III - Description and Terminology | 
|  |  | 
|  | IV - Microcode Programming Details | 
|  |  | 
|  | V - Firmware Structure Layout | 
|  |  | 
|  | VI - Sample Code for Creating Firmware Files | 
|  |  | 
|  | Revision Information | 
|  | ==================== | 
|  |  | 
|  | November 30, 2007: Rev 1.0 - Initial version | 
|  |  | 
|  | I - Software License for Firmware | 
|  | ================================= | 
|  |  | 
|  | Each firmware file comes with its own software license.  For information on | 
|  | the particular license, please see the license text that is distributed with | 
|  | the firmware. | 
|  |  | 
|  | II - Microcode Availability | 
|  | =========================== | 
|  |  | 
|  | Firmware files are distributed through various channels.  Some are available on | 
|  | http://opensource.freescale.com.  For other firmware files, please contact | 
|  | your Freescale representative or your operating system vendor. | 
|  |  | 
|  | III - Description and Terminology | 
|  | ================================ | 
|  |  | 
|  | In this document, the term 'microcode' refers to the sequence of 32-bit | 
|  | integers that compose the actual QE microcode. | 
|  |  | 
|  | The term 'firmware' refers to a binary blob that contains the microcode as | 
|  | well as other data that | 
|  |  | 
|  | 1) describes the microcode's purpose | 
|  | 2) describes how and where to upload the microcode | 
|  | 3) specifies the values of various registers | 
|  | 4) includes additional data for use by specific device drivers | 
|  |  | 
|  | Firmware files are binary files that contain only a firmware. | 
|  |  | 
|  | IV - Microcode Programming Details | 
|  | =================================== | 
|  |  | 
|  | The QE architecture allows for only one microcode present in I-RAM for each | 
|  | RISC processor.  To replace any current microcode, a full QE reset (which | 
|  | disables the microcode) must be performed first. | 
|  |  | 
|  | QE microcode is uploaded using the following procedure: | 
|  |  | 
|  | 1) The microcode is placed into I-RAM at a specific location, using the | 
|  | IRAM.IADD and IRAM.IDATA registers. | 
|  |  | 
|  | 2) The CERCR.CIR bit is set to 0 or 1, depending on whether the firmware | 
|  | needs split I-RAM.  Split I-RAM is only meaningful for SOCs that have | 
|  | QEs with multiple RISC processors, such as the 8360.  Splitting the I-RAM | 
|  | allows each processor to run a different microcode, effectively creating an | 
|  | asymmetric multiprocessing (AMP) system. | 
|  |  | 
|  | 3) The TIBCR trap registers are loaded with the addresses of the trap handlers | 
|  | in the microcode. | 
|  |  | 
|  | 4) The RSP.ECCR register is programmed with the value provided. | 
|  |  | 
|  | 5) If necessary, device drivers that need the virtual traps and extended mode | 
|  | data will use them. | 
|  |  | 
|  | Virtual Microcode Traps | 
|  |  | 
|  | These virtual traps are conditional branches in the microcode.  These are | 
|  | "soft" provisional introduced in the ROMcode in order to enable higher | 
|  | flexibility and save h/w traps If new features are activated or an issue is | 
|  | being fixed in the RAM package utilizing they should be activated.  This data | 
|  | structure signals the microcode which of these virtual traps is active. | 
|  |  | 
|  | This structure contains 6 words that the application should copy to some | 
|  | specific been defined.  This table describes the structure. | 
|  |  | 
|  | --------------------------------------------------------------- | 
|  | | 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 | | 
|  | --------------------------------------------------------------- | 
|  |  | 
|  |  | 
|  | Extended Modes | 
|  |  | 
|  | This is a double word bit array (64 bits) that defines special functionality | 
|  | which has an impact on the software drivers.  Each bit has its own impact | 
|  | and has special instructions for the s/w associated with it.  This structure is | 
|  | described in this table: | 
|  |  | 
|  | ----------------------------------------------------------------------- | 
|  | | 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 - Firmware Structure Layout | 
|  | ============================== | 
|  |  | 
|  | QE microcode from Freescale is typically provided as a header file.  This | 
|  | header file contains macros that define the microcode binary itself as well as | 
|  | some other data used in uploading that microcode.  The format of these files | 
|  | do not lend themselves to simple inclusion into other code.  Hence, | 
|  | the need for a more portable format.  This section defines that format. | 
|  |  | 
|  | Instead of distributing a header file, the microcode and related data are | 
|  | embedded into a binary blob.  This blob is passed to the qe_upload_firmware() | 
|  | function, which parses the blob and performs everything necessary to upload | 
|  | the microcode. | 
|  |  | 
|  | All integers are big-endian.  See the comments for function | 
|  | qe_upload_firmware() for up-to-date implementation information. | 
|  |  | 
|  | This structure supports versioning, where the version of the structure is | 
|  | embedded into the structure itself.  To ensure forward and backwards | 
|  | compatibility, all versions of the structure must use the same 'qe_header' | 
|  | structure at the beginning. | 
|  |  | 
|  | 'header' (type: struct qe_header): | 
|  | The 'length' field is the size, in bytes, of the entire structure, | 
|  | including all the microcode embedded in it, as well as the CRC (if | 
|  | present). | 
|  |  | 
|  | The 'magic' field is an array of three bytes that contains the letters | 
|  | 'Q', 'E', and 'F'.  This is an identifier that indicates that this | 
|  | structure is a QE Firmware structure. | 
|  |  | 
|  | The 'version' field is a single byte that indicates the version of this | 
|  | structure.  If the layout of the structure should ever need to be | 
|  | changed to add support for additional types of microcode, then the | 
|  | version number should also be changed. | 
|  |  | 
|  | The 'id' field is a null-terminated string(suitable for printing) that | 
|  | identifies the firmware. | 
|  |  | 
|  | The 'count' field indicates the number of 'microcode' structures.  There | 
|  | must be one and only one 'microcode' structure for each RISC processor. | 
|  | Therefore, this field also represents the number of RISC processors for this | 
|  | SOC. | 
|  |  | 
|  | The 'soc' structure contains the SOC numbers and revisions used to match | 
|  | the microcode to the SOC itself.  Normally, the microcode loader should | 
|  | check the data in this structure with the SOC number and revisions, and | 
|  | only upload the microcode if there's a match.  However, this check is not | 
|  | made on all platforms. | 
|  |  | 
|  | Although it is not recommended, you can specify '0' in the soc.model | 
|  | field to skip matching SOCs altogether. | 
|  |  | 
|  | The 'model' field is a 16-bit number that matches the actual SOC. The | 
|  | 'major' and 'minor' fields are the major and minor revision numbers, | 
|  | respectively, of the SOC. | 
|  |  | 
|  | For example, to match the 8323, revision 1.0: | 
|  | soc.model = 8323 | 
|  | soc.major = 1 | 
|  | soc.minor = 0 | 
|  |  | 
|  | 'padding' is necessary for structure alignment.  This field ensures that the | 
|  | 'extended_modes' field is aligned on a 64-bit boundary. | 
|  |  | 
|  | 'extended_modes' is a bitfield that defines special functionality which has an | 
|  | impact on the device drivers.  Each bit has its own impact and has special | 
|  | instructions for the driver associated with it.  This field is stored in | 
|  | the QE library and available to any driver that calles qe_get_firmware_info(). | 
|  |  | 
|  | 'vtraps' is an array of 8 words that contain virtual trap values for each | 
|  | virtual traps.  As with 'extended_modes', this field is stored in the QE | 
|  | library and available to any driver that calles qe_get_firmware_info(). | 
|  |  | 
|  | 'microcode' (type: struct qe_microcode): | 
|  | For each RISC processor there is one 'microcode' structure.  The first | 
|  | 'microcode' structure is for the first RISC, and so on. | 
|  |  | 
|  | The 'id' field is a null-terminated string suitable for printing that | 
|  | identifies this particular microcode. | 
|  |  | 
|  | 'traps' is an array of 16 words that contain hardware trap values | 
|  | for each of the 16 traps.  If trap[i] is 0, then this particular | 
|  | trap is to be ignored (i.e. not written to TIBCR[i]).  The entire value | 
|  | is written as-is to the TIBCR[i] register, so be sure to set the EN | 
|  | and T_IBP bits if necessary. | 
|  |  | 
|  | 'eccr' is the value to program into the ECCR register. | 
|  |  | 
|  | 'iram_offset' is the offset into IRAM to start writing the | 
|  | microcode. | 
|  |  | 
|  | 'count' is the number of 32-bit words in the microcode. | 
|  |  | 
|  | 'code_offset' is the offset, in bytes, from the beginning of this | 
|  | structure where the microcode itself can be found.  The first | 
|  | microcode binary should be located immediately after the 'microcode' | 
|  | array. | 
|  |  | 
|  | 'major', 'minor', and 'revision' are the major, minor, and revision | 
|  | version numbers, respectively, of the microcode.  If all values are 0, | 
|  | then these fields are ignored. | 
|  |  | 
|  | 'reserved' is necessary for structure alignment.  Since 'microcode' | 
|  | is an array, the 64-bit 'extended_modes' field needs to be aligned | 
|  | on a 64-bit boundary, and this can only happen if the size of | 
|  | 'microcode' is a multiple of 8 bytes.  To ensure that, we add | 
|  | 'reserved'. | 
|  |  | 
|  | After the last microcode is a 32-bit CRC.  It can be calculated using | 
|  | this algorithm: | 
|  |  | 
|  | 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 - Sample Code for Creating Firmware Files | 
|  | ============================================ | 
|  |  | 
|  | A Python program that creates firmware binaries from the header files normally | 
|  | distributed by Freescale can be found on http://opensource.freescale.com. |