[U-Boot, v1, 1/1] net: phy: air_en8811h: load the PHY firmware from filesystem on block device by default
Lucien.Jheng
lucienzx159 at gmail.com
Sat May 10 14:52:13 CEST 2025
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.
If need board specific loading override,
please override the en8811h_read_fw function on board or architecture level.
Signed-off-by: Lucien.Jheng <lucienzx159 at gmail.com>
---
drivers/net/phy/Kconfig | 39 ++++++-----
drivers/net/phy/air_en8811h.c | 119 ++++++++++++++++++++--------------
2 files changed, 95 insertions(+), 63 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..b5f27a23343 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 <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,111 @@ static int en8811h_wait_mcu_ready(struct phy_device *phydev)
return 0;
}
-static int en8811h_load_firmware(struct phy_device *phydev)
+static void crc32_check(unsigned char *buf, u32 len)
+{
+ u32 ca_crc32;
+
+ ca_crc32 = crc32(0, buf, len);
+ printf("crc32 is 0x%x\n", ca_crc32);
+}
+
+__weak int en8811h_read_fw(void **addr)
{
+ loff_t read;
int ret;
- char *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);
+ printf("\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)
+ return ret;
- if (!mmc) {
- puts("Failed to find MMC device for Airoha ucode\n");
- goto en8811h_load_firmware_out;
- }
+ ret = fs_read(CONFIG_PHY_AIROHA_FW_DM_FILEPATH,
+ (ulong)*addr, 0, EN8811H_MD32_DM_SIZE, &read);
+ if (ret < 0)
+ return ret;
- printf("MMC read: dev # %u, block # %u, count %u ...\n",
- dev, blk, cnt);
+ /* Calculate the CRC32 */
+ crc32_check((unsigned char *)*addr, EN8811H_MD32_DM_SIZE);
- if (mmc_init(mmc)) {
- puts("initializing MMC device failed.\n");
- goto en8811h_load_firmware_out;
- }
+ printf("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)
+ return ret;
- ret = mmc_set_part_conf(mmc, 1, 2, 2);
- if (ret) {
- puts("cannot access eMMC boot1 hw partition.\n");
- goto en8811h_load_firmware_out;
- }
+ ret = fs_read(CONFIG_PHY_AIROHA_FW_DSP_FILEPATH,
+ (ulong)*addr + EN8811H_MD32_DM_SIZE,
+ 0, EN8811H_MD32_DSP_SIZE, &read);
+ if (ret < 0)
+ return ret;
- (void)blk_dread(mmc_get_blk_desc(mmc), blk, cnt, addr);
+ /* Calculate the CRC32 */
+ crc32_check((unsigned char *)*addr + EN8811H_MD32_DM_SIZE,
+ EN8811H_MD32_DSP_SIZE);
- mmc_set_part_conf(mmc, 1, 1, 0);
+ printf("Found Airoha Firmware.\n");
+ return 0;
+}
+
+static int en8811h_load_firmware(struct phy_device *phydev)
+{
+ struct en8811h_priv *priv = phydev->priv;
+ void *addr = NULL;
+ int ret;
+
+ if (IS_ENABLED(CONFIG_PHY_AIROHA_FW_IN_MMC)) {
+ u32 fw_length = EN8811H_MD32_DM_SIZE + EN8811H_MD32_DSP_SIZE;
+
+ addr = malloc(fw_length);
+ if (!addr) {
+ printf("Failed to allocate memory for firmware\n");
+ return -ENOMEM;
+ }
+
+ ret = en8811h_read_fw(&addr);
+ if (ret < 0) {
+ free(addr);
+ return ret;
+ }
} 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
More information about the U-Boot
mailing list