Locating the AIROHA FW within the filesystem at the designated partition and path will trigger its automatic loading and writing to the PHY via MDIO.
Signed-off-by: Lucien.Jheng <lucienzx...@gmail.com> --- drivers/net/phy/Kconfig | 39 ++++++++------ drivers/net/phy/air_en8811h.c | 97 +++++++++++++++++++---------------- 2 files changed, 78 insertions(+), 58 deletions(-) diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 5b4cf30b0a3..384cef845e1 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -94,24 +94,33 @@ choice depends on PHY_AIROHA_EN8811H config PHY_AIROHA_FW_IN_MMC - bool "Airoha firmware in MMC boot1 partition" - -endchoice + bool "Airoha firmware in MMC partition" + help + Airoha PHYs use firmware which can be loaded automatically + from storage directly attached to the PHY, and then loaded + via MDIO commands by the boot loader. The firmware is loaded + from a file specified by the PHY_AIROHA_FW_PART, + PHY_AIROHA_FW_DM_FILEPATH and PHY_AIROHA_FW_DSP_FILEPATH options. + +config PHY_AIROHA_FW_PART + string "Airoha firmware partition" + depends on PHY_AIROHA_FW_IN_MMC + help + Partition containing the firmware file. -config AIROHA_FW_ADDR - hex "Airoha Firmware Address" - depends on PHY_AIROHA_EN8811H - default 0x0 +config PHY_AIROHA_FW_DM_FILEPATH + string "Airoha firmware DM file path in the filesystem" + depends on PHY_AIROHA_FW_IN_MMC + help + Specify Airoha firmware DM file path in the filesystem. -config AIROHA_MD32_DM_SIZE - hex "Airoha Firmware MD32 DM Size" - depends on PHY_AIROHA_EN8811H - default 0x4000 +config PHY_AIROHA_FW_DSP_FILEPATH + string "Airoha firmware DSP file path in the filesystem" + depends on PHY_AIROHA_FW_IN_MMC + help + Specify Airoha firmware DSP file path in the filesystem. -config AIROHA_MD32_DSP_SIZE - hex "Airoha Firmware MD32 DSP Size" - depends on PHY_AIROHA_EN8811H - default 0x20000 +endchoice menuconfig PHY_AQUANTIA bool "Aquantia Ethernet PHYs support" diff --git a/drivers/net/phy/air_en8811h.c b/drivers/net/phy/air_en8811h.c index 96bb24418a0..8a2a25a8c74 100644 --- a/drivers/net/phy/air_en8811h.c +++ b/drivers/net/phy/air_en8811h.c @@ -12,12 +12,14 @@ */ #include <phy.h> #include <errno.h> +#include <log.h> #include <malloc.h> +#include <fs.h> #include <asm/unaligned.h> #include <linux/iopoll.h> -#include <dm/device_compat.h> #include <linux/bitops.h> -#include <mmc.h> +#include <dm/device_compat.h> +#include <u-boot/crc.h> #define EN8811H_PHY_ID 0x03a2a411 @@ -415,11 +417,6 @@ restore_page: return air_phy_restore_page(phydev, saved_page, ret); } -__weak ulong *en8811h_get_fw_addr(void) -{ - return (ulong *)CONFIG_AIROHA_FW_ADDR; -} - static int en8811h_wait_mcu_ready(struct phy_device *phydev) { int ret, reg_value; @@ -437,85 +434,99 @@ static int en8811h_wait_mcu_ready(struct phy_device *phydev) return 0; } +static void crc32_check(unsigned char *name, unsigned char *buf, u32 len) +{ + u32 ca_crc32; + + ca_crc32 = crc32(0, buf, len); + debug("%s: crc32 is 0x%x\n", name, ca_crc32); +} + static int en8811h_load_firmware(struct phy_device *phydev) { int ret; - char *addr = NULL; + void *addr = NULL; struct en8811h_priv *priv = phydev->priv; - int dev = CONFIG_SYS_MMC_ENV_DEV; - u32 cnt = (CONFIG_AIROHA_MD32_DM_SIZE + - CONFIG_AIROHA_MD32_DSP_SIZE) / 512; - ulong airoha_fw_addr = (ulong)en8811h_get_fw_addr(); - u32 blk = airoha_fw_addr / 512; - - addr = malloc(CONFIG_AIROHA_MD32_DM_SIZE + CONFIG_AIROHA_MD32_DSP_SIZE); - if (!addr) { - puts("cannot allocated buffer for firmware.\n"); - return -ENOMEM; - } if (IS_ENABLED(CONFIG_PHY_AIROHA_FW_IN_MMC)) { - struct mmc *mmc = find_mmc_device(dev); + loff_t read; - if (!mmc) { - puts("Failed to find MMC device for Airoha ucode\n"); - goto en8811h_load_firmware_out; + addr = malloc(EN8811H_MD32_DM_SIZE + + EN8811H_MD32_DSP_SIZE); + if (!addr) { + puts("cannot allocated buffer for firmware.\n"); + return -ENOMEM; } - printf("MMC read: dev # %u, block # %u, count %u ...\n", - dev, blk, cnt); + debug("\nLoading Airoha FW from %s %s\n", + CONFIG_PHY_AIROHA_FW_PART, + CONFIG_PHY_AIROHA_FW_DM_FILEPATH); + ret = fs_set_blk_dev("mmc", CONFIG_PHY_AIROHA_FW_PART, FS_TYPE_ANY); + if (ret < 0) + goto en8811h_load_firmware_out; - if (mmc_init(mmc)) { - puts("initializing MMC device failed.\n"); + ret = fs_read(CONFIG_PHY_AIROHA_FW_DM_FILEPATH, + (ulong)addr, 0, EN8811H_MD32_DM_SIZE, &read); + if (ret < 0) goto en8811h_load_firmware_out; - } - ret = mmc_set_part_conf(mmc, 1, 2, 2); - if (ret) { - puts("cannot access eMMC boot1 hw partition.\n"); + /* Calculate the CRC32 */ + crc32_check(CONFIG_PHY_AIROHA_FW_DM_FILEPATH, + (unsigned char *)addr, EN8811H_MD32_DM_SIZE); + + debug("Loading Airoha FW from %s %s\n", + CONFIG_PHY_AIROHA_FW_PART, + CONFIG_PHY_AIROHA_FW_DSP_FILEPATH); + ret = fs_set_blk_dev("mmc", CONFIG_PHY_AIROHA_FW_PART, FS_TYPE_ANY); + if (ret < 0) goto en8811h_load_firmware_out; - } - (void)blk_dread(mmc_get_blk_desc(mmc), blk, cnt, addr); + ret = fs_read(CONFIG_PHY_AIROHA_FW_DSP_FILEPATH, + (ulong)addr + EN8811H_MD32_DM_SIZE, + 0, EN8811H_MD32_DSP_SIZE, &read); + if (ret < 0) + goto en8811h_load_firmware_out; - mmc_set_part_conf(mmc, 1, 1, 0); + /* Calculate the CRC32 */ + crc32_check(CONFIG_PHY_AIROHA_FW_DSP_FILEPATH, + (unsigned char *)addr + EN8811H_MD32_DM_SIZE, + EN8811H_MD32_DSP_SIZE); } else { puts("EN8811H firmware loading not implemented"); - free(addr); - addr = NULL; return -EOPNOTSUPP; } ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1, EN8811H_FW_CTRL_1_START); if (ret < 0) - return ret; + goto en8811h_load_firmware_out; ret = air_buckpbus_reg_modify(phydev, EN8811H_FW_CTRL_2, EN8811H_FW_CTRL_2_LOADING, EN8811H_FW_CTRL_2_LOADING); if (ret < 0) - return ret; + goto en8811h_load_firmware_out; - ret = air_write_buf(phydev, AIR_FW_ADDR_DM, CONFIG_AIROHA_MD32_DM_SIZE, addr); + ret = air_write_buf(phydev, AIR_FW_ADDR_DM, EN8811H_MD32_DM_SIZE, + (unsigned char *)addr); if (ret < 0) goto en8811h_load_firmware_out; - ret = air_write_buf(phydev, AIR_FW_ADDR_DSP, CONFIG_AIROHA_MD32_DSP_SIZE, - addr + CONFIG_AIROHA_MD32_DM_SIZE); + ret = air_write_buf(phydev, AIR_FW_ADDR_DSP, EN8811H_MD32_DSP_SIZE, + (unsigned char *)addr + EN8811H_MD32_DM_SIZE); if (ret < 0) goto en8811h_load_firmware_out; ret = air_buckpbus_reg_modify(phydev, EN8811H_FW_CTRL_2, EN8811H_FW_CTRL_2_LOADING, 0); if (ret < 0) - return ret; + goto en8811h_load_firmware_out; ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1, EN8811H_FW_CTRL_1_FINISH); if (ret < 0) - return ret; + goto en8811h_load_firmware_out; ret = en8811h_wait_mcu_ready(phydev); -- 2.34.1