diff --git a/board/qca/arm/ipq807x/ipq807x.c b/board/qca/arm/ipq807x/ipq807x.c index 08dc8bc3c4..8b9bb6a438 100644 --- a/board/qca/arm/ipq807x/ipq807x.c +++ b/board/qca/arm/ipq807x/ipq807x.c @@ -251,9 +251,8 @@ void board_mmc_deinit(void) emmc_clock_disable(); } -int board_eth_init(bd_t *bis) +void eth_clock_enable(void) { - int ret=0; int tlmm_base = 0x1025000; int aquantia_gpio = -1, node; unsigned int *aquantia_gpio_base; @@ -329,6 +328,13 @@ int board_eth_init(bd_t *bis) writel(0x3, aquantia_gpio_base); mdelay(500); } +} + +int board_eth_init(bd_t *bis) +{ + int ret=0; + + eth_clock_enable(); ret = ipq807x_edma_init(NULL); if (ret != 0) diff --git a/drivers/net/ipq807x/ipq807x_aquantia_phy.c b/drivers/net/ipq807x/ipq807x_aquantia_phy.c index e5ebf5199d..be77046fe6 100644 --- a/drivers/net/ipq807x/ipq807x_aquantia_phy.c +++ b/drivers/net/ipq807x/ipq807x_aquantia_phy.c @@ -21,12 +21,44 @@ #include "ipq_phy.h" #include "ipq807x_aquantia_phy.h" #include +#include +#include +#include +#include +#include + +typedef struct { + unsigned int image_type; + unsigned int header_vsn_num; + unsigned int image_src; + unsigned char *image_dest_ptr; + unsigned int image_size; + unsigned int code_size; + unsigned char *signature_ptr; + unsigned int signature_size; + unsigned char *cert_chain_ptr; + unsigned int cert_chain_size; +} mbn_header_t; + +mbn_header_t *fwimg_header; +static int debug = 0; + +#ifdef CONFIG_QCA_MMC +extern qca_mmc mmc_host; +static qca_mmc *host = &mmc_host; +#endif extern int ipq_mdio_write(int mii_id, int regnum, u16 value); extern int ipq_mdio_read(int mii_id, int regnum, ushort *data); +extern int ipq_sw_mdio_init(const char *); +extern void eth_clock_enable(void); +static int program_ethphy_fw(unsigned int phy_addr, + uint32_t load_addr,uint32_t file_size ); +static qca_smem_flash_info_t *sfi = &qca_smem_flash_info; + u16 aq_phy_reg_write(u32 dev_id, u32 phy_id, u32 reg_id, u16 reg_val) { @@ -167,13 +199,116 @@ int ipq_qca_aquantia_phy_init(struct phy_ops **ops, u32 phy_id) return 0; } -#define AQ_PHY_IMAGE_HEADER_CONTENT_OFFSET_HHD 0x300 static int do_load_fw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + unsigned int phy_addr=0x7; + + if (argc > 2) + return CMD_RET_USAGE; + + if (argc == 2) + phy_addr = simple_strtoul(argv[1], NULL, 16); + + if (phy_addr != AQU_PHY_ADDR) { + printf("Phy address is not correct: use 0x7\n"); + return 0; + } + miiphy_init(); + eth_clock_enable(); + ipq_sw_mdio_init("IPQ MDIO0"); + ipq_board_fw_download(phy_addr); + return 0; +} + +int ipq_board_fw_download(unsigned int phy_addr) +{ + char runcmd[256]; + int ret,i=0; + uint32_t start; /* block number */ + uint32_t size; /* no. of blocks */ + qca_part_entry_t ethphyfw; + struct { char *name; qca_part_entry_t *part; } entries[] = { + { "0:ETHPHYFW", ðphyfw }, + }; +#ifdef CONFIG_QCA_MMC + block_dev_desc_t *blk_dev; + disk_partition_t disk_info; +#endif + /* check the smem info to see which flash used for booting */ + if (sfi->flash_type == SMEM_BOOT_SPI_FLASH) { + if (debug) { + printf("Using nand device %d\n", CONFIG_SPI_FLASH_INFO_IDX); + } + sprintf(runcmd, "nand device %d", CONFIG_SPI_FLASH_INFO_IDX); + run_command(runcmd, 0); + + } else if (sfi->flash_type == SMEM_BOOT_NAND_FLASH) { + if (debug) { + printf("Using nand device 0\n"); + } + } else if (sfi->flash_type == SMEM_BOOT_MMC_FLASH) { + if (debug) { + printf("Using MMC device\n"); + } + } else { + printf("Unsupported BOOT flash type\n"); + return -1; + } + + ret = smem_getpart(entries[i].name, &start, &size); + if (ret < 0) { + debug("cdp: get part failed for %s\n", entries[i].name); + } else { + qca_set_part_entry(entries[i].name, sfi, entries[i].part, start, size); + } + + if ( (sfi->flash_type == SMEM_BOOT_NAND_FLASH) || (sfi->flash_type == SMEM_BOOT_SPI_FLASH)) { + /* + * Kernel is in a separate partition + */ + snprintf(runcmd, sizeof(runcmd), + /* NOR is treated as psuedo NAND */ + "nand read 0x%x 0x%llx 0x%llx && ", + CONFIG_SYS_LOAD_ADDR, ethphyfw.offset, ethphyfw.size); + + if (debug) + printf("%s", runcmd); + + if (run_command(runcmd, 0) != CMD_RET_SUCCESS) + return CMD_RET_FAILURE; +#ifdef CONFIG_QCA_MMC + } else if (sfi->flash_type == SMEM_BOOT_MMC_FLASH ) { + blk_dev = mmc_get_dev(host->dev_num); + ret = get_partition_info_efi_by_name(blk_dev, + "0:ETHPHYFW", &disk_info); + if (ret == 0) { + snprintf(runcmd, sizeof(runcmd), "mmc read 0x%x 0x%X 0x%X", + CONFIG_SYS_LOAD_ADDR, + (uint)disk_info.start, (uint)disk_info.size); + + if (run_command(runcmd, 0) != CMD_RET_SUCCESS) + return CMD_RET_FAILURE; + } +#endif + } + + fwimg_header = CONFIG_SYS_LOAD_ADDR; + + if( fwimg_header->image_type == 0x13 && fwimg_header->header_vsn_num == 0x3) { + program_ethphy_fw(phy_addr, (uint32_t )(CONFIG_SYS_LOAD_ADDR + sizeof(mbn_header_t)), + (uint32_t )(fwimg_header->image_size)); + }else { + printf("bad magic on ETHPHYFW partition\n"); + return -1; + } + return 0; +} + + +#define AQ_PHY_IMAGE_HEADER_CONTENT_OFFSET_HHD 0x300 +static int program_ethphy_fw(unsigned int phy_addr, uint32_t load_addr, uint32_t file_size) { int i; - uint32_t load_addr; - uint32_t file_size; - unsigned int phy_addr; uint8_t *buf; uint16_t file_crc; uint16_t computed_crc; @@ -197,24 +332,13 @@ static int do_load_fw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) uint8_t lsb2; uint16_t mailbox_crc; - if (argc < 4) - return CMD_RET_USAGE; - - phy_addr = simple_strtoul(argv[1], NULL, 16); - load_addr = simple_strtoul(argv[2], NULL, 16); - file_size = simple_strtoul(argv[3], NULL, 16); - - if (phy_addr != AQU_PHY_ADDR) { - printf("Phy address is not correct: use 0x7\n"); - return 0; - } aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x300), 0xdead); aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x301), 0xbeaf); reg1 = aq_phy_reg_read(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x300)); reg2 = aq_phy_reg_read(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x301)); if(reg1 != 0xdead && reg2 != 0xbeaf) { - printf("Scratchpad Read/Write test fail\n"); + printf("PHY::Scratchpad Read/Write test fail\n"); return 0; } buf = (uint8_t *)load_addr; @@ -222,10 +346,10 @@ static int do_load_fw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) computed_crc = cyg_crc16(buf, file_size - 2); if (file_crc != computed_crc) { - printf("CRC check failed on image file\n"); + printf("CRC check failed on phy fw file\n"); return 0; } else { - printf ("CRC check good on image file (0x%04X)\n",computed_crc); + printf ("CRC check good on phy fw file (0x%04X)\n",computed_crc); } daisy_chain_dis = aq_phy_reg_read(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0xc452)); @@ -255,15 +379,10 @@ static int do_load_fw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) primary_iram_ptr += primary_header_ptr; primary_dram_ptr += primary_header_ptr; - printf ("\nSegment Addresses and Sizes as read from the PHY ROM image header:\n\n"); - printf ("Primary Iram Address: 0x%x\n", primary_iram_ptr); - printf ("Primary Iram Size: 0x%x\n", primary_iram_sz); - printf ("Primary Dram Address: 0x%x\n", primary_dram_ptr); - printf ("Primary Dram Size: 0x%x\n", primary_dram_sz); aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x200), 0x1000); aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x200), 0x0); computed_crc = 0; - printf("Loading IRAM\n"); + printf("PHYFW:Loading IRAM..........."); aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x202), 0x4000); aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x203), 0x0); byte_sz = primary_iram_sz; @@ -285,8 +404,6 @@ static int do_load_fw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) computed_crc = cyg_crc16_computed(&msb2, 0x1, computed_crc); computed_crc = cyg_crc16_computed(&lsb1, 0x1, computed_crc); computed_crc = cyg_crc16_computed(&lsb2, 0x1, computed_crc); - if (i && ((i % 512) == 0)) - printf(" Byte: %X:\n", i << 2); } switch (byte_sz & 0x3) { @@ -319,7 +436,8 @@ static int do_load_fw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) computed_crc = cyg_crc16_computed(&lsb1, 0x1, computed_crc); computed_crc = cyg_crc16_computed(&lsb2, 0x1, computed_crc); } - printf("Loading DRAM\n"); + printf("done.\n"); + printf("PHYFW:Loading DRAM.............."); aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x202), 0x3ffe); aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x203), 0x0); byte_sz = primary_dram_sz; @@ -341,8 +459,6 @@ static int do_load_fw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) computed_crc = cyg_crc16_computed(&msb2, 0x1, computed_crc); computed_crc = cyg_crc16_computed(&lsb1, 0x1, computed_crc); computed_crc = cyg_crc16_computed(&lsb2, 0x1, computed_crc); - if (i && ((i % 512) == 0)) - printf(" Byte: %X:\n", i << 2); } switch (byte_sz & 0x3) { @@ -375,12 +491,13 @@ static int do_load_fw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) computed_crc = cyg_crc16_computed(&lsb1, 0x1, computed_crc); computed_crc = cyg_crc16_computed(&lsb2, 0x1, computed_crc); } + printf("done.\n"); aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0xc441), 0x2010); mailbox_crc = aq_phy_reg_read(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x201)); if (mailbox_crc != computed_crc) - printf("Mailbox CRC-16 (0x%X) does not match calculated CRC-16 (0x%X)\n", mailbox_crc, computed_crc); + printf("phy fw image load CRC-16 (0x%X) does not match calculated CRC-16 (0x%X)\n", mailbox_crc, computed_crc); else - printf("Image load good - mailbox CRC-16 matches (0x%X)\n", mailbox_crc); + printf("phy fw image load good CRC-16 matches (0x%X)\n", mailbox_crc); aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0x0), 0x0); aq_phy_reg_write(0x0, phy_addr, AQUANTIA_REG_ADDRESS(0x1e, 0xc001), 0x41); @@ -391,7 +508,6 @@ static int do_load_fw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) aquantia_phy_restart_autoneg(phy_addr); return 0; } - U_BOOT_CMD( aq_load_fw, 5, 1, do_load_fw, "LOAD aq-fw-binary", diff --git a/drivers/net/ipq807x/ipq807x_edma.c b/drivers/net/ipq807x/ipq807x_edma.c index 7950bdfe86..4cb825ebf7 100644 --- a/drivers/net/ipq807x/ipq807x_edma.c +++ b/drivers/net/ipq807x/ipq807x_edma.c @@ -1726,6 +1726,7 @@ int ipq807x_edma_init(void *edma_board_cfg) break; case AQUANTIA_PHY_107: case AQUANTIA_PHY_109: + ipq_board_fw_download(phy_addr); ipq_qca_aquantia_phy_init(&ipq807x_edma_dev[i]->ops[phy_id], phy_addr); break; default: