85xx: add ability to upload QE firmware
PATCH v2 1/1 85xx: add ability to upload QE firmware
Define the layout of a binary blob that contains a QE firmware and instructions on how to upload it. Add function qe_upload_firmware() to parse the blob and perform the actual upload. Add command-line command "qe fw" to take a firmware blob in memory and upload it. Update ft_cpu_setup() on 83xx to create the 'firmware' device tree node if U-Boot has uploaded a firmware. Fully define 'struct rsp' in immap_qe.h to include the actual RISC Special Registers.
---
Updated device tree property names, based on mailing list review.
Tested on an MPC8568 MDS.
common/fdt_support.c | 48 ++++++++++ cpu/mpc85xx/fdt.c | 1 + drivers/qe/qe.c | 219 ++++++++++++++++++++++++++++++++++++++++++++ drivers/qe/qe.h | 56 +++++++++++ include/asm-ppc/immap_qe.h | 33 ++++++- include/fdt_support.h | 1 + 6 files changed, 356 insertions(+), 2 deletions(-)
common/fdt_support.c +48 -0
@@ -30,6 +30,9 @@#include <fdt_support.h> #include <exports.h> +#ifdef CONFIG_QE +#include "../drivers/qe/qe.h" +#endif /* * Global data (for the gd->bd) */
@@ -607,4 +610,49 @@ void fdt_fixup_ethernet(void *fdt, bd_t *bd) #endif } } + +#ifdef CONFIG_QE +/* +* If a QE firmware has been uploaded, then add the 'firmware' node under +* the 'qe' node. +*/ +void fdt_fixup_qe_firmware (void *fdt) +{ +struct qe_firmware_info *qe_fw_info; +int node, ret; + + qe_fw_info =qe_get_firmware_info (); +if (!qe_fw_info) +return ; + + node =fdt_path_offset (fdt,"/qe" ); +if (node <0 ) +return ; + +/* We assume the node doesn't exist yet */ + node =fdt_add_subnode (fdt, node,"firmware" ); +if (node <0 ) +return ; + + ret =fdt_setprop (fdt, node,"extended-modes" , + &qe_fw_info->extended_modes,sizeof (u64)); +if (ret <0 ) + goto error; + + ret =fdt_setprop_string (fdt, node,"id" , qe_fw_info->id); +if (ret <0 ) + goto error; + + ret =fdt_setprop (fdt, node,"virtual-traps" , qe_fw_info->vtraps, +sizeof (qe_fw_info->vtraps)); +if (ret <0 ) + goto error; + +return ; + +error: +fdt_del_node (fdt, node); +} +#endif +#endif
cpu/mpc85xx/fdt.c +1 -0
@@ -45,6 +45,7 @@ void ft_cpu_setup(void *blob, bd_t *bd)#ifdef CONFIG_QE do_fixup_by_prop_u32 (blob,"device_type" ,"soc" ,4 ,"bus-frequency" , bd->bi_busfreq,1 ); +fdt_fixup_qe_firmware (blob);#endif #ifdef CFG_NS16550
drivers/qe/qe.c +219 -0
229 lines not on this page · raw message
drivers/qe/qe.h +56 -0
67 lines not on this page · raw message
include/asm-ppc/immap_qe.h +31 -2
@@ -513,10 +513,39 @@ typedef struct dbg {u8 res2[0x48 ]; } __attribute__ ((packed)) dbg_t; -/* RISC Special Registers (Trap and Breakpoint) +/* +* RISC Special Registers (Trap and Breakpoint). These are described in +* the QE Developer's Handbook. */ typedef struct rsp { -u8 fixme[0x100 ]; +u32 tibcr[16 ];/* Trap/instruction breakpoint control regs */ +u8 res0[64 ]; +u32 ibcr0; +u32 ibs0; +u32 ibcnr0; +u8 res1[4 ]; +u32 ibcr1; +u32 ibs1; +u32 ibcnr1; +u32 npcr; +u32 dbcr; +u32 dbar; +u32 dbamr; +u32 dbsr; +u32 dbcnr; +u8 res2[12 ]; +u32 dbdr_h; +u32 dbdr_l; +u32 dbdmr_h; +u32 dbdmr_l; +u32 bsr; +u32 bor; +u32 bior; +u8 res3[4 ]; +u32 iatr[4 ]; +u32 eccr;/* Exception control configuration register */ +u32 eicr; +u8 res4[0x100 -0xf8 ]; } __attribute__ ((packed))rsp_t ; typedef struct qe_immap {
include/fdt_support.h +1 -0
@@ -46,6 +46,7 @@ void do_fixup_by_compat_u32(void *fdt, const char *compat, const char *prop, u32 val, int create);int fdt_fixup_memory (void *blob,u64 start,u64 size);void fdt_fixup_ethernet (void *fdt,bd_t *bd); +void fdt_fixup_qe_firmware (void *fdt);#ifdef CONFIG_OF_HAS_UBOOT_ENV int fdt_env (void *fdt);
Signature · 1 line
1.5.2.4
PATCH v2 1/1 85xx: add ability to upload QE firmware
Quoted 11 lines · Timur Tabi
Define the layout of a binary blob that contains a QE firmware and instructions
on how to upload it. Add functionqe_upload_firmware()to parse the blob and
perform the actual upload. Add command-line command "qe fw" to take a firmware
blob in memory and upload it. Updateft_cpu_setup()on 83xx to create the 'firmware' device tree node if U-Boot has uploaded a firmware. Fully define
'struct rsp' inimmap_qe.hto include the actual RISC Special Registers.
Did you mean "Update ft_cpu_setup() on 85xx"?
Andy
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.denx.de/pipermail/u-boot/attachments/20080107/a4edb01f/attachment.htm
PATCH v2 1/1 85xx: add ability to upload QE firmware
Quoted 1 line · Andy Fleming
Did you mean "Update
ft_cpu_setup()on 85xx"?
Yes, sorry. I thought I fixed that already.
Signature · 2 lines
Timur Tabi Linux kernel developer at Freescale
Andy Fleming
AppliedPATCH v2 1/1 85xx: add ability to upload QE firmware
In reply to Timur Tabiapplied, thanks!
I changed the 83xx to 85xx in the description
Quoted 478 lines · Timur Tabi
Define the layout of a binary blob that contains a QE firmware and instructions on how to upload it. Add function
qe_upload_firmware()to parse the blob and perform the actual upload. Add command-line command "qe fw" to take a firmware blob in memory and upload it. Updateft_cpu_setup()on 83xx to create the 'firmware' device tree node if U-Boot has uploaded a firmware. Fully define 'struct rsp' inimmap_qe.hto include the actual RISC Special Registers.Signed-off-by Timur Tabi <[email protected]>---
Updated device tree property names, based on mailing list review.
Tested on an MPC8568 MDS.
common/fdt_support.c | 48 ++++++++++ cpu/mpc85xx/fdt.c | 1 + drivers/qe/qe.c | 219 ++++++++++++++++++++++++++++++++++++++++++++ drivers/qe/qe.h | 56 +++++++++++ include/asm-ppc/immap_qe.h | 33 ++++++- include/fdt_support.h | 1 + 6 files changed, 356 insertions(+), 2 deletions(-)common/fdt_support.c +48
-0@@ -30,6 +30,9 @@#include <fdt_support.h> #include <exports.h> +#ifdef CONFIG_QE +#include "../drivers/qe/qe.h" +#endif /* * Global data (for the gd->bd) */ @@ -607,4 +610,49 @@ void fdt_fixup_ethernet(void *fdt, bd_t *bd) #endif } } + +#ifdef CONFIG_QE +/* +* If a QE firmware has been uploaded, then add the 'firmware' node under +* the 'qe' node. +*/ +void fdt_fixup_qe_firmware (void *fdt) +{ +struct qe_firmware_info *qe_fw_info; +int node, ret; + + qe_fw_info =qe_get_firmware_info (); +if (!qe_fw_info) +return ; + + node =fdt_path_offset (fdt,"/qe" ); +if (node <0 ) +return ; + +/* We assume the node doesn't exist yet */ + node =fdt_add_subnode (fdt, node,"firmware" ); +if (node <0 ) +return ; + + ret =fdt_setprop (fdt, node,"extended-modes" , + &qe_fw_info->extended_modes,sizeof (u64)); +if (ret <0 ) + goto error; + + ret =fdt_setprop_string (fdt, node,"id" , qe_fw_info->id); +if (ret <0 ) + goto error; + + ret =fdt_setprop (fdt, node,"virtual-traps" , qe_fw_info->vtraps, +sizeof (qe_fw_info->vtraps)); +if (ret <0 ) + goto error; + +return ; + +error: +fdt_del_node (fdt, node); +} +#endif +#endif cpu/mpc85xx/fdt.c +1
-0@@ -45,6 +45,7 @@ void ft_cpu_setup(void *blob, bd_t *bd)#ifdef CONFIG_QE do_fixup_by_prop_u32 (blob,"device_type" ,"soc" ,4 ,"bus-frequency" , bd->bi_busfreq,1 ); +fdt_fixup_qe_firmware (blob);#endif #ifdef CFG_NS16550 drivers/qe/qe.c +219
-0@@ -21,6 +21,7 @@*/ #include "common.h" +#include <command.h> #include "asm/errno.h" #include "asm/io.h" #include "asm/immap_qe.h" @@ -248,4 +249,222 @@ int qe_set_mii_clk_src(int ucc_num) return 0; } +/* The maximum number of RISCs we support */ +#define MAX_QE_RISC 2 + +/* Firmware information stored here for qe_get_firmware_info() */ +static struct qe_firmware_info qe_firmware_info; + +/* +* Set to 1 if QE firmware has been uploaded, and therefore +* qe_firmware_info contains valid data. +*/ +static int qe_firmware_uploaded; + +/* +* Upload a QE microcode +* +* This function is a worker function for qe_upload_firmware(). It does +* the actual uploading of the microcode. +*/ +static void qe_upload_microcode (const void *base, +const struct qe_microcode *ucode) +{ +const u32 *code = base +be32_to_cpu (ucode->code_offset); +unsigned int i; + +if (ucode->major || ucode->minor || ucode->revision) +printf ("QE: uploading microcode '%s' version %u.%u.%u\n" , + ucode->id, ucode->major, ucode->minor, ucode->revision); +else +printf ("QE: uploading microcode '%s'\n" , ucode->id); + +/* Use auto-increment */ +out_be32 (&qe_immr->iram.iadd,be32_to_cpu (ucode->iram_offset) | +QE_IRAM_IADD_AIE |QE_IRAM_IADD_BADDR ); + +for (i =0 ; i <be32_to_cpu (ucode->count); i++) +out_be32 (&qe_immr->iram.idata,be32_to_cpu (code[i])); +} + +/* +* Upload a microcode to the I-RAM at a specific address. +* +* See docs/README.qe_firmware for information on QE microcode uploading. +* +* Currently, only version 1 is supported, so the 'version' field must be +* set to 1. +* +* The SOC model and revision are not validated, they are only displayed for +* informational purposes. +* +* 'calc_size' is the calculated size, in bytes, of the firmware structure and +* all of the microcode structures, minus the CRC. +* +* 'length' is the size that the structure says it is, including the CRC. +*/ +int qe_upload_firmware (const struct qe_firmware *firmware) +{ +unsigned int i; +unsigned int j; +u32 crc; +size_t calc_size =sizeof (struct qe_firmware ); +size_t length; +const struct qe_header *hdr; + +if (!firmware) { +printf ("Invalid address\n" ); +return -EINVAL ; + } + + hdr = &firmware->header; + length =be32_to_cpu (hdr->length); + +/* Check the magic */ +if ((hdr->magic[0 ] !='Q' ) || (hdr->magic[1 ] !='E' ) || + (hdr->magic[2 ] !='F' )) { +printf ("Not a microcode\n" ); +return -EPERM ; + } + +/* Check the version */ +if (hdr->version !=1 ) { +printf ("Unsupported version\n" ); +return -EPERM ; + } + +/* Validate some of the fields */ +if ((firmware->count <1 ) || (firmware->count >=MAX_QE_RISC )) { +printf ("Invalid data\n" ); +return -EINVAL ; + } + +/* Validate the length and check if there's a CRC */ + calc_size += (firmware->count -1 ) *sizeof (struct qe_microcode ); + +for (i =0 ; i < firmware->count; i++) +/* +* For situations where the second RISC uses the same microcode +* as the first, the 'code_offset' and 'count' fields will be +* zero, so it's okay to add those. +*/ + calc_size +=sizeof (u32) * +be32_to_cpu (firmware->microcode[i].count); + +/* Validate the length */ +if (length != calc_size +sizeof (u32)) { +printf ("Invalid length\n" ); +return -EPERM ; + } + +/* +* Validate the CRC. We would normally call crc32_no_comp(), but that +* function isn't available unless you turn on JFFS support. +*/ + crc =be32_to_cpu (*(u32 *)((void *)firmware + calc_size)); +if (crc != (crc32 (-1 , (const void *) firmware, calc_size) ^-1 )) { +printf ("Firmware CRC is invalid\n" ); +return -EIO ; + } + +/* +* If the microcode calls for it, split the I-RAM. +*/ +if (!firmware->split) { +out_be16 (&qe_immr->cp.cercr, +in_be16 (&qe_immr->cp.cercr) |QE_CP_CERCR_CIR ); + } + +if (firmware->soc.model) +printf ("Firmware '%s' for %u V%u.%u\n" , + firmware->id,be16_to_cpu (firmware->soc.model), + firmware->soc.major, firmware->soc.minor); +else +printf ("Firmware '%s'\n" , firmware->id); + +/* +* The QE only supports one microcode per RISC, so clear out all the +* saved microcode information and put in the new. +*/ +memset (&qe_firmware_info,0 ,sizeof (qe_firmware_info)); +strcpy (qe_firmware_info.id, firmware->id); + qe_firmware_info.extended_modes = firmware->extended_modes; +memcpy (qe_firmware_info.vtraps, firmware->vtraps, +sizeof (firmware->vtraps)); + qe_firmware_uploaded =1 ; + +/* Loop through each microcode. */ +for (i =0 ; i < firmware->count; i++) { +const struct qe_microcode *ucode = &firmware->microcode[i]; + +/* Upload a microcode if it's present */ +if (ucode->code_offset) +qe_upload_microcode (firmware, ucode); + +/* Program the traps for this processor */ +for (j =0 ; j <16 ; j++) { +u32 trap =be32_to_cpu (ucode->traps[j]); + +if (trap) +out_be32 (&qe_immr->rsp[i].tibcr[j], trap); + } + +/* Enable traps */ +out_be32 (&qe_immr->rsp[i].eccr,be32_to_cpu (ucode->eccr)); + } + +return 0 ; +} + +struct qe_firmware_info *qe_get_firmware_info (void ) +{ +return qe_firmware_uploaded ? &qe_firmware_info :NULL ; +} + +static int qe_cmd (cmd_tbl_t *cmdtp,int flag,int argc,char *argv[]) +{ +ulong addr; + +if (argc <3 ) { +printf ("Usage:\n%s\n" , cmdtp->usage); +return 1 ; + } + +if (strcmp (argv[1 ],"fw" ) ==0 ) { + addr =simple_strtoul (argv[2 ],NULL ,16 ); + +if (!addr) { +printf ("Invalid address\n" ); +return -EINVAL ; + } + +/* +* If a length was supplied, compare that with the 'length' +* field. +*/ + +if (argc >3 ) { +ulong length =simple_strtoul (argv[3 ],NULL ,16 ); +struct qe_firmware *firmware = (void *) addr; + +if (length !=be32_to_cpu (firmware->header.length)) { +printf ("Length mismatch\n" ); +return -EINVAL ; + } + } + +return qe_upload_firmware ((const struct qe_firmware *) addr); + } + +printf ("Usage:\n%s\n" , cmdtp->usage); +return 1 ; +} + +U_BOOT_CMD ( + qe,4 ,0 , qe_cmd, +"qe - QUICC Engine commands\n" , +"fw <addr> [<length>] - Upload firmware binary at address <addr> to " +"the QE,\n\twith optional length <length> verification.\n" + ); +#endif /* CONFIG_QE */ drivers/qe/qe.h +56
-0@@ -222,6 +222,60 @@ typedef enum qe_clock {#define QE_SDEBCR_BA_MASK 0x01FFFFFF +/* Communication Processor */ +#define QE_CP_CERCR_MEE 0x8000/* Multi-user RAM ECC enable */ +#define QE_CP_CERCR_IEE 0x4000/* Instruction RAM ECC enable */ +#define QE_CP_CERCR_CIR 0x0800/* Common instruction RAM */ + +/* I-RAM */ +#define QE_IRAM_IADD_AIE 0x80000000/* Auto Increment Enable */ +#define QE_IRAM_IADD_BADDR 0x00080000/* Base Address */ + +/* Structure that defines QE firmware binary files. +* +* See doc/README.qe_firmware for a description of these fields. +*/ +struct qe_firmware { +struct qe_header { +u32 length;/* Length of the entire structure, in bytes */ +u8 magic[3 ];/* Set to { 'Q', 'E', 'F' } */ +u8 version;/* Version of this layout. First ver is '1' */ + } header; +u8 id[62 ];/* Null-terminated identifier string */ +u8 split;/* 0 = shared I-RAM, 1 = split I-RAM */ +u8 count;/* Number of microcode[] structures */ +struct { +u16 model;/* The SOC model */ +u8 major;/* The SOC revision major */ +u8 minor;/* The SOC revision minor */ + } __attribute__ ((packed)) soc; +u8 padding[4 ];/* Reserved, for alignment */ +u64 extended_modes;/* Extended modes */ +u32 vtraps[8 ];/* Virtual trap addresses */ +u8 reserved[4 ];/* Reserved, for future expansion */ +struct qe_microcode { +u8 id[32 ];/* Null-terminated identifier */ +u32 traps[16 ];/* Trap addresses, 0 == ignore */ +u32 eccr;/* The value for the ECCR register */ +u32 iram_offset;/* Offset into I-RAM for the code */ +u32 count;/* Number of 32-bit words of the code */ +u32 code_offset;/* Offset of the actual microcode */ +u8 major;/* The microcode version major */ +u8 minor;/* The microcode version minor */ +u8 revision;/* The microcode version revision */ +u8 padding;/* Reserved, for alignment */ +u8 reserved[4 ];/* Reserved, for future expansion */ + } __attribute__ ((packed)) microcode[1 ]; +/* All microcode binaries should be located here */ +/* CRC32 should be located here, after the microcode binaries */ +} __attribute__ ((packed)); + +struct qe_firmware_info { +char id[64 ];/* Firmware name */ +u32 vtraps[8 ];/* Virtual trap addresses */ +u64 extended_modes;/* Extended modes */ +}; +void qe_config_iopin (u8 port,u8 pin,int dir,int open_drain,int assign);void qe_issue_cmd (uint cmd,uint sbc,u8 mcn,u32 cmd_data);uint qe_muram_alloc (uint size,uint align);@@ -233,5 +287,7 @@ void qe_reset(void);void qe_assign_page (uint snum,uint para_ram_base);int qe_set_brg (uint brg,uint rate);int qe_set_mii_clk_src (int ucc_num); +int qe_upload_firmware (const struct qe_firmware *firmware); +struct qe_firmware_info *qe_get_firmware_info (void );#endif /* __QE_H__ */ include/asm-ppc/immap_qe.h +31
-2@@ -513,10 +513,39 @@ typedef struct dbg {u8 res2[0x48 ]; } __attribute__ ((packed)) dbg_t; -/* RISC Special Registers (Trap and Breakpoint) +/* +* RISC Special Registers (Trap and Breakpoint). These are described in +* the QE Developer's Handbook. */ typedef struct rsp { -u8 fixme[0x100 ]; +u32 tibcr[16 ];/* Trap/instruction breakpoint control regs */ +u8 res0[64 ]; +u32 ibcr0; +u32 ibs0; +u32 ibcnr0; +u8 res1[4 ]; +u32 ibcr1; +u32 ibs1; +u32 ibcnr1; +u32 npcr; +u32 dbcr; +u32 dbar; +u32 dbamr; +u32 dbsr; +u32 dbcnr; +u8 res2[12 ]; +u32 dbdr_h; +u32 dbdr_l; +u32 dbdmr_h; +u32 dbdmr_l; +u32 bsr; +u32 bor; +u32 bior; +u8 res3[4 ]; +u32 iatr[4 ]; +u32 eccr;/* Exception control configuration register */ +u32 eicr; +u8 res4[0x100 -0xf8 ]; } __attribute__ ((packed))rsp_t ; typedef struct qe_immap {include/fdt_support.h +1
-1@@ -46,6 +46,7 @@ void do_fixup_by_compat_u32(void *fdt, const char *compat, const char *prop, u32 val, int create);int fdt_fixup_memory (void *blob,u64 start,u64 size);void fdt_fixup_ethernet (void *fdt,bd_t *bd); +void fdt_fixup_qe_firmware (void *fdt);#ifdef CONFIG_OF_HAS_UBOOT_ENV int fdt_env (void *fdt); --1.5.2.4
-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace
_______________________________________________
U-Boot-Users mailing list
U-Boot-Users at lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/u-boot-users