NXP(旧 Freescale)製PowerPC(以下、PPC)プロセッサのPowerQUICCシリーズは、QUICC Engineと呼ばれるファームウェア(以下、FW)を使って各種通信コントローラーを実装できます。
このFWイメージのロードですが、PPCのブートローダーであるU-Bootに実装されてます。
https://github.com/nxp-qoriq/u-boot/blob/LSDK-19.09-update-311219/drivers/qe/qe.c
qe_init() です。
が、良く見ると、NORフラッシュのメモリーマップされたアドレスからのロードのみとなっています。
ブートデバイスにSPIフラッシュを使う場合、FWイメージもSPIフラッシュ上に置くと思います。で、CONFIG_SYS_QE_FW_ADDR にそのアドレスを指定すれば良いと思ってましたが、この実装ではロードされません。
そこで、SPIフラッシュからロードされるようパッチを作ったので公開します。
U-Bootの最新バージョンでもSPIフラッシュからのロードに非対応なので、NXPに対応するよう代理店経由で依頼しましたが、NXPからの回答は「その予定はない」とのつれないものでした。
FMAN(Frame Manager)と呼ばれるFWのロードはSPIフラッシュにも対応してるんですけどね...。
https://github.com/nxp-qoriq/u-boot/blob/LSDK-19.09-update-311219/drivers/net/fm/fm.c
fm_init_common() です。
diff --git a/drivers/qe/qe.c b/drivers/qe/qe.c index 70d02d3..6710680 100644 --- a/drivers/qe/qe.c +++ b/drivers/qe/qe.c @@ -15,6 +15,8 @@ #include <fsl_qe.h> #include <mmc.h> #include <environment.h> +#include <spi.h> +#include <spi_flash.h> #ifdef CONFIG_ARCH_LS1021A #include <asm/arch/immap_ls102xa.h> @@ -202,19 +204,46 @@ void qe_init(uint qe_base) #else void qe_init(uint qe_base) { + void *addr = NULL; + /* Init the QE IMMR base */ qe_immr = (qe_map_t *)qe_base; -#ifdef CONFIG_SYS_QE_FMAN_FW_IN_NOR - /* - * Upload microcode to IRAM for those SOCs which do not have ROM in QE. - */ - qe_upload_firmware((const void *)CONFIG_SYS_QE_FW_ADDR); +#if defined(CONFIG_SYS_QE_FMAN_FW_IN_NOR) + addr = (void *)CONFIG_SYS_QE_FW_ADDR; +#elif defined(CONFIG_SYS_QE_FW_IN_SPIFLASH) + struct spi_nor *nor; + int ret = 0; + + addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH); + +# ifdef CONFIG_DM_SPI_FLASH + struct udevice *new; - /* enable the microcode in IRAM */ - out_be32(&qe_immr->iram.iready,QE_IRAM_READY); + /* speed and mode will be read from DT */ + ret = spi_flash_probe_bus_cs(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS, 0, 0, &new); + nor = dev_get_uclass_priv(new); +# else + nor = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS, CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE); +# endif + + if (!nor) + printf("SF: probe for qe firmware failed\n"); + else { + ret = spi_flash_read(nor, CONFIG_SYS_QE_FW_ADDR, CONFIG_SYS_QE_FMAN_FW_LENGTH, addr); + if (ret) + printf("SF: read for qe firmware failed\n"); + spi_flash_free(nor); + } #endif + if (addr) { + /* Upload microcode to IRAM for those SOCs which do not have ROM in QE. */ + qe_upload_firmware((const void *)addr); + /* enable the microcode in IRAM */ + out_be32(&qe_immr->iram.iready,QE_IRAM_READY); + } + gd->arch.mp_alloc_base = QE_DATAONLY_BASE; gd->arch.mp_alloc_top = gd->arch.mp_alloc_base + QE_DATAONLY_SIZE;