diff --git a/arch/arm/cpu/armv7/qca/common/scm.c b/arch/arm/cpu/armv7/qca/common/scm.c index 61ad5f233d..d519848c08 100644 --- a/arch/arm/cpu/armv7/qca/common/scm.c +++ b/arch/arm/cpu/armv7/qca/common/scm.c @@ -492,6 +492,28 @@ int qca_scm_part_info(void *cmd_buf, return ret; } +int qca_scm_dpr(u32 svc_id, u32 cmd_id, void *buf, size_t len) +{ + int ret = 0; + uint32_t *status; + if (is_scm_armv8()) + { + struct qca_scm_desc desc = {0}; + desc.arginfo = QCA_SCM_ARGS(1, SCM_VAL); + desc.args[0] = *((unsigned int *)buf); + + ret = scm_call_64(svc_id, cmd_id, &desc); + + status = (uint32_t *)(*(((uint32_t *)buf) + 1)); + *status = desc.ret[0]; + } + else + { + ret = scm_call(svc_id, cmd_id, buf, len, NULL, 0); + } + return ret; +} + int qca_scm_auth_kernel(void *cmd_buf, size_t cmd_len) { @@ -563,6 +585,8 @@ int qca_scm_secure_authenticate(void *cmd_buf, size_t cmd_len) desc.args[2] = * (((unsigned long *)cmd_buf) + 2); ret = scm_call_64(SCM_SVC_BOOT, SCM_CMD_SEC_AUTH, &desc); + if(!ret && desc.ret[0]) + return SCM_ERROR; } else { @@ -664,6 +688,10 @@ int qca_scm_part_info(void *cmd_buf, size_t cmd_len) { return 0; } +int qca_scm_dpr(u32 svc_id, u32 cmd_id, void *buf, size_t len) +{ + return 0; +} int qca_scm_auth_kernel(void *cmd_buf, size_t cmd_len) { @@ -713,6 +741,30 @@ int qca_scm_call_write(u32 svc_id, u32 cmd_id, u32 *addr, u32 val) return ret; } +int qca_scm_call_read(u32 svc_id, u32 cmd_id, u32 *addr, u32 *val) +{ + int ret = 0; + struct qca_scm_desc desc = {0}; + + /* In ipq807x, this SCM call is called as a Fast + * SCM call which means it will get executed in + * EL3 monitor mode itself without jumping to QSEE. + * But, In ipq6018, We need to jump into QSEE which + * will execute the SCM call, as we do not have + * support for Fast SCM call in ipq6018. + */ + + desc.arginfo = QCA_SCM_ARGS(1, SCM_VAL); + + desc.args[0] = (u32)addr; + + ret = scm_call_64(svc_id, cmd_id, &desc); + *val = (u32)desc.ret[0]; + + return ret; +} + + static int qca_scm_sdi_v8(void) { struct qca_scm_desc desc = {0}; diff --git a/arch/arm/cpu/armv7/qca/common/smem.c b/arch/arm/cpu/armv7/qca/common/smem.c index bb731ba8c0..197a2891e8 100644 --- a/arch/arm/cpu/armv7/qca/common/smem.c +++ b/arch/arm/cpu/armv7/qca/common/smem.c @@ -38,6 +38,11 @@ #include "fdt_info.h" #include #include +#ifdef CONFIG_IPQ_RUNTIME_FAILSAFE +#include +#include +#endif + #ifdef IPQ_UBI_VOL_WRITE_SUPPORT static struct ubi_device *ubi; @@ -145,6 +150,12 @@ static struct smem *smem = (void *)(CONFIG_QCA_SMEM_BASE); qca_smem_flash_info_t qca_smem_flash_info; qca_smem_bootconfig_info_t qca_smem_bootconfig_info; +#ifdef CONFIG_IPQ_RUNTIME_FAILSAFE +unsigned ipq_runtime_failsafe_status; +unsigned ipq_runtime_fs_skip_status_check = 0; +unsigned ipq_runtime_fs_feature_enabled = 0; +#endif + #ifdef CONFIG_SMEM_VERSION_C #define SMEM_COMMON_HOST 0xFFFE @@ -496,10 +507,121 @@ int smem_bootconfig_info(void) return 0; } +#ifdef CONFIG_IPQ_RUNTIME_FAILSAFE +int smem_runtime_failsafe_info(void) +{ + unsigned ret; + + ret = smem_read_alloc_entry(SMEM_RUNTIME_FAILSAFE_INFO, + &ipq_runtime_failsafe_status, sizeof(ipq_runtime_failsafe_status)); + if (ret != 0) { + printf("\nsmem: Failed to fetch the runtime failsafe status.." \ + "Disabling the feature.\n"); + ipq_runtime_fs_feature_enabled = 0; + } + if (ipq_runtime_failsafe_status & IPQ_RUNTIME_FAILSAFE_ENABLED) { + printf("\nRuntime Failsafe Feature Enabled\n"); + ipq_runtime_fs_feature_enabled = 1; + } + return 0; +} +#endif + +#ifndef CONFIG_SDHCI_SUPPORT +extern qca_mmc mmc_host; +#else +extern struct sdhci_host mmc_host; +#endif +#ifdef CONFIG_IPQ_RUNTIME_FAILSAFE +int smem_update_bootconfig_to_flash(void) +{ + + unsigned i, j, len; + uint32_t load_addr = 0; + char *part_name[] = {"0:BOOTCONFIG", "0:BOOTCONFIG1"}; + char runcmd[256]; + + if (smem_runtime_failsafe_info() != 0) + return -ENOMSG; + + if (ipq_runtime_fs_feature_enabled == 0) + return 0; + + /* Update BOOTCONFIG in flash only if there is an update in SMEM by SBL */ + if (!ipq_runtime_fs_skip_status_check) { + if (ipq_runtime_failsafe_status & IPQ_RUNTIME_FS_BOOTCONFIG_UPDATED) { + printf("\nRuntime hang detected: Partitions switched by SBL.\n"); + } else { + return 0; + } + } + + if (qca_smem_bootconfig_info.magic_start != _SMEM_DUAL_BOOTINFO_MAGIC_START) { + if(smem_bootconfig_info() != 0) + return -1; + } + + fs_debug("\nFailsafe: SMEM bootinfo from SBL: "); + for (j = 0; j < qca_smem_bootconfig_info.numaltpart; j++) + fs_debug("\nPartition: %s primaryboot = %d\n", + qca_smem_bootconfig_info.per_part_entry[j].name, + qca_smem_bootconfig_info.per_part_entry[j].primaryboot); + + len = sizeof(part_name)/sizeof(part_name[0]); + load_addr = (uint32_t)&qca_smem_bootconfig_info; + + for (i = 0; i < len; i++) { + + snprintf(runcmd, sizeof(runcmd), "setenv fileaddr 0x%x && \ + setenv filesize %d && flash %s", + load_addr, sizeof(qca_smem_bootconfig_info), part_name[i]); + + if (run_command(runcmd, 0) != CMD_RET_SUCCESS) + return CMD_RET_FAILURE; + } + + return CMD_RET_SUCCESS; +} + +__weak int is_hlos_crashed(void) +{ + return 0; +} + +void update_hlos_rootfs_primaryboot(void) +{ + unsigned int i; + qca_smem_flash_info_t *sfi = &qca_smem_flash_info; + + fs_debug("\nFailsafe: %s: HLOS bit is SET", __func__); + printf("\nHLOS runtime hang detected: Switching Partitions.\n"); + for (i = 0; i < qca_smem_bootconfig_info.numaltpart; i++) { + if (sfi->flash_type == SMEM_BOOT_MMC_FLASH || + sfi->flash_type == SMEM_BOOT_SPI_FLASH) { + /* Note: SBL swaps the offsets for NAND case */ + if (strncmp("0:HLOS", qca_smem_bootconfig_info.per_part_entry[i].name, + ALT_PART_NAME_LENGTH) == 0) + qca_smem_bootconfig_info.per_part_entry[i].primaryboot = 1; + if (strncmp("rootfs", qca_smem_bootconfig_info.per_part_entry[i].name, + ALT_PART_NAME_LENGTH) == 0) + qca_smem_bootconfig_info.per_part_entry[i].primaryboot = 1; + } + } + ipq_runtime_fs_skip_status_check = 1; +} +#endif + unsigned int get_rootfs_active_partition(void) { int i; +#ifdef CONFIG_IPQ_RUNTIME_FAILSAFE + if (ipq_runtime_fs_feature_enabled && is_hlos_crashed()) { + update_hlos_rootfs_primaryboot(); + smem_update_bootconfig_to_flash(); + } +#endif + for (i = 0; i < qca_smem_bootconfig_info.numaltpart; i++) { if (strncmp("rootfs", qca_smem_bootconfig_info.per_part_entry[i].name, ALT_PART_NAME_LENGTH) == 0) diff --git a/arch/arm/dts/ipq5018-mp02.1.dts b/arch/arm/dts/ipq5018-mp02.1.dts index ff1d553848..e29aea8266 100644 --- a/arch/arm/dts/ipq5018-mp02.1.dts +++ b/arch/arm/dts/ipq5018-mp02.1.dts @@ -21,6 +21,7 @@ aliases { console = "/serial@78AF000"; + nand = "/nand-controller@79B0000"; }; console: serial@78AF000 { @@ -57,6 +58,52 @@ }; }; + nand: nand-controller@79B0000 { + status = "okay"; + nand_gpio { + qspi_dat3 { + gpio = <4>; + func = <2>; + pull = ; + od_en = ; + drvstr = ; + }; + qspi_dat2 { + gpio = <5>; + func = <2>; + pull = ; + od_en = ; + drvstr = ; + }; + qspi_dat1 { + gpio = <6>; + func = <2>; + pull = ; + od_en = ; + drvstr = ; + }; + qspi_dat0 { + gpio = <7>; + func = <2>; + pull = ; + od_en = ; + drvstr = ; + }; + qspi_cs_n { + gpio = <8>; + func = <2>; + od_en = ; + drvstr = ; + }; + qspi_clk { + gpio = <9>; + func = <2>; + od_en = ; + drvstr = ; + }; + }; + }; + gmac_cfg { ext_mdio_gpio = <36 37>; gephy_led = <30>; diff --git a/arch/arm/dts/ipq6018-cp01-c1.dts b/arch/arm/dts/ipq6018-cp01-c1.dts index d88d22d73b..df36e0a00c 100644 --- a/arch/arm/dts/ipq6018-cp01-c1.dts +++ b/arch/arm/dts/ipq6018-cp01-c1.dts @@ -52,7 +52,7 @@ }; ess-switch { switch_mac_mode = ; - switch_mac_mode1 = ; + switch_mac_mode1 = ; napa_gpio = <77>; napa_gpio_cnt = <1>; malibu_gpio = <75>; diff --git a/arch/arm/dts/ipq6018-cp02-c1.dts b/arch/arm/dts/ipq6018-cp02-c1.dts index 4822dea115..90fd71e1e2 100644 --- a/arch/arm/dts/ipq6018-cp02-c1.dts +++ b/arch/arm/dts/ipq6018-cp02-c1.dts @@ -25,8 +25,8 @@ i2c1 = "/i2c@78ba000"; }; ess-switch { - switch_mac_mode = ; - switch_mac_mode1 = ; + switch_mac_mode = ; + switch_mac_mode1 = ; napa_gpio = <77>; napa_gpio_cnt = <1>; mdc_mdio_gpio = <64 65>; diff --git a/arch/arm/dts/ipq6018-db-cp01.dts b/arch/arm/dts/ipq6018-db-cp01.dts index 5480528cad..1300602a8d 100644 --- a/arch/arm/dts/ipq6018-db-cp01.dts +++ b/arch/arm/dts/ipq6018-db-cp01.dts @@ -179,7 +179,7 @@ ess-switch { switch_mac_mode = ; - switch_mac_mode1 = ; + switch_mac_mode1 = ; napa_gpio = <77>; napa_gpio_cnt = <1>; malibu_gpio = <75>; diff --git a/arch/arm/dts/ipq6018-db-cp02.dts b/arch/arm/dts/ipq6018-db-cp02.dts index bf5b68dd9f..8f21a11722 100644 --- a/arch/arm/dts/ipq6018-db-cp02.dts +++ b/arch/arm/dts/ipq6018-db-cp02.dts @@ -26,8 +26,8 @@ i2c1 = "/i2c@78ba000"; }; ess-switch { - switch_mac_mode = ; - switch_mac_mode1 = ; + switch_mac_mode = ; + switch_mac_mode1 = ; napa_gpio = <77>; napa_gpio_cnt = <1>; mdc_mdio_gpio = <64 65>; diff --git a/arch/arm/dts/ipq807x-ac01.dts b/arch/arm/dts/ipq807x-ac01.dts index e0bfdd2ec0..fe4a931300 100644 --- a/arch/arm/dts/ipq807x-ac01.dts +++ b/arch/arm/dts/ipq807x-ac01.dts @@ -25,8 +25,8 @@ }; ess-switch { switch_mac_mode = <0x0>; - switch_mac_mode1 = <0x6>; - switch_mac_mode2 = <0x6>; + switch_mac_mode1 = <0x1>; + switch_mac_mode2 = <0x1>; napa_gpio = <25 44>; napa_gpio_cnt = <2>; port_phyinfo { diff --git a/arch/arm/dts/ipq807x-ac03.dts b/arch/arm/dts/ipq807x-ac03.dts index 3963522681..731a4c2900 100644 --- a/arch/arm/dts/ipq807x-ac03.dts +++ b/arch/arm/dts/ipq807x-ac03.dts @@ -25,8 +25,8 @@ }; ess-switch { switch_mac_mode = <0x0>; - switch_mac_mode1 = <0x6>; - switch_mac_mode2 = <0x6>; + switch_mac_mode1 = <0x1>; + switch_mac_mode2 = <0x1>; napa_gpio = <25 44>; napa_gpio_cnt = <2>; port_phyinfo { diff --git a/arch/arm/dts/ipq807x-ac04.dts b/arch/arm/dts/ipq807x-ac04.dts index 9d2af07cc9..06ce0d8f99 100644 --- a/arch/arm/dts/ipq807x-ac04.dts +++ b/arch/arm/dts/ipq807x-ac04.dts @@ -25,8 +25,8 @@ }; ess-switch { switch_mac_mode = <0x0>; - switch_mac_mode1 = <0x6>; - switch_mac_mode2 = <0x6>; + switch_mac_mode1 = <0x1>; + switch_mac_mode2 = <0x1>; napa_gpio = <25 44>; napa_gpio_cnt = <2>; port_phyinfo { diff --git a/arch/arm/dts/ipq807x-db-hk02.dts b/arch/arm/dts/ipq807x-db-hk02.dts index b7912e07cc..41c8cc27b5 100644 --- a/arch/arm/dts/ipq807x-db-hk02.dts +++ b/arch/arm/dts/ipq807x-db-hk02.dts @@ -27,7 +27,7 @@ ess-switch { switch_mac_mode = <0x0>; switch_mac_mode1 = <0x2>; - switch_mac_mode2 = <0x6>; + switch_mac_mode2 = <0x1>; napa_gpio = <26>; napa_gpio_cnt = <1>; aquantia_port = <4>; diff --git a/arch/arm/dts/ipq807x-hk07.dts b/arch/arm/dts/ipq807x-hk07.dts index 4f132a1d82..b4d1f89d1d 100644 --- a/arch/arm/dts/ipq807x-hk07.dts +++ b/arch/arm/dts/ipq807x-hk07.dts @@ -25,7 +25,7 @@ ess-switch { switch_mac_mode = <0x0>; switch_mac_mode1 = <0xFF>; - switch_mac_mode2 = <0x6>; + switch_mac_mode2 = <0x1>; napa_gpio = <44>; napa_gpio_cnt = <1>; port_phyinfo { diff --git a/arch/arm/dts/ipq807x-hk08.dts b/arch/arm/dts/ipq807x-hk08.dts index 1671cd9bef..31486d6033 100644 --- a/arch/arm/dts/ipq807x-hk08.dts +++ b/arch/arm/dts/ipq807x-hk08.dts @@ -25,7 +25,7 @@ }; ess-switch { switch_mac_mode = <0x1>; - switch_mac_mode1 = <0x6>; + switch_mac_mode1 = <0x1>; switch_mac_mode2 = <0x2>; 8033_port = <0>; aquantia_port = <5>; diff --git a/arch/arm/dts/ipq807x-hk09.dts b/arch/arm/dts/ipq807x-hk09.dts index be225448b1..96f628d2bb 100644 --- a/arch/arm/dts/ipq807x-hk09.dts +++ b/arch/arm/dts/ipq807x-hk09.dts @@ -25,8 +25,8 @@ }; ess-switch { switch_mac_mode = <0x0>; - switch_mac_mode1 = <0x6>; - switch_mac_mode2 = <0x6>; + switch_mac_mode1 = <0x1>; + switch_mac_mode2 = <0x1>; napa_gpio = <25 44>; napa_gpio_cnt = <2>; port_phyinfo { diff --git a/arch/arm/dts/ipq807x-hk10-c2.dts b/arch/arm/dts/ipq807x-hk10-c2.dts index b74b23ad05..792f617313 100644 --- a/arch/arm/dts/ipq807x-hk10-c2.dts +++ b/arch/arm/dts/ipq807x-hk10-c2.dts @@ -28,7 +28,7 @@ ess-switch { switch_mac_mode = <0x0>; switch_mac_mode1 = <0x2>; - switch_mac_mode2 = <0x6>; + switch_mac_mode2 = <0x1>; aquantia_port = <4>; aquantia_gpio = <44>; uniphy_ext_ref_clk; diff --git a/arch/arm/dts/ipq9574-db-al01-c1.dts b/arch/arm/dts/ipq9574-db-al01-c1.dts index 1bc30f2a79..56d08ee391 100644 --- a/arch/arm/dts/ipq9574-db-al01-c1.dts +++ b/arch/arm/dts/ipq9574-db-al01-c1.dts @@ -191,7 +191,7 @@ ess-switch { switch_mac_mode0 = ; switch_mac_mode1 = ; - switch_mac_mode2 = ; + switch_mac_mode2 = ; qca807x_gpio = <60>; qca807x_gpio_cnt = <1>; aquantia_gpio = <36>; diff --git a/arch/arm/dts/ipq9574-db-al02-c1.dts b/arch/arm/dts/ipq9574-db-al02-c1.dts index afa5040e22..af3724f049 100644 --- a/arch/arm/dts/ipq9574-db-al02-c1.dts +++ b/arch/arm/dts/ipq9574-db-al02-c1.dts @@ -190,7 +190,7 @@ ess-switch { switch_mac_mode0 = ; - switch_mac_mode1 = ; + switch_mac_mode1 = ; switch_mac_mode2 = ; qca807x_gpio = <60>; qca807x_gpio_cnt = <1>; diff --git a/arch/arm/include/asm/arch-ipq9574/clk.h b/arch/arm/include/asm/arch-ipq9574/clk.h index 19e6e7ea06..9339f01852 100644 --- a/arch/arm/include/asm/arch-ipq9574/clk.h +++ b/arch/arm/include/asm/arch-ipq9574/clk.h @@ -19,12 +19,27 @@ /* I2C clocks configuration */ #ifdef CONFIG_IPQ9574_I2C +#define BLSP1_QUP_BASE 0x078B5000 +#define GCC_BLSP1_QUP1_I2C_APPS_CMD_RCGR 0x1802018 +#define GCC_BLSP1_QUP1_I2C_APPS_CBCR 0x1802024 #define GCC_BLSP1_QUP1_I2C_APPS_CFG_RCGR 0x180201C #define GCC_BLSP1_QUP1_I2C_APPS_CFG_RCGR_SRC_SEL (1 << 8) #define GCC_BLSP1_QUP1_I2C_APPS_CFG_RCGR_SRC_DIV (0x1F << 0) +#define GCC_BLSP1_QUP_I2C_OFFSET_INC 0x1000 -#define GCC_BLSP1_QUP1_I2C_APPS_CMD_RCGR 0x1802018 -#define GCC_BLSP1_QUP1_I2C_APPS_CBCR 0x1802024 +#define GCC_BLSP1_QUP_I2C_APPS_CFG_RCGR(id) ((id < 1) ? \ + (GCC_BLSP1_QUP1_I2C_APPS_CFG_RCGR):\ + (GCC_BLSP1_QUP1_I2C_APPS_CFG_RCGR + (GCC_BLSP1_QUP_I2C_OFFSET_INC * id))) + +#define GCC_BLSP1_QUP_I2C_APPS_CMD_RCGR(id) ((id < 1) ? \ + (GCC_BLSP1_QUP1_I2C_APPS_CMD_RCGR):\ + (GCC_BLSP1_QUP1_I2C_APPS_CMD_RCGR + (GCC_BLSP1_QUP_I2C_OFFSET_INC * id))) + +#define GCC_BLSP1_QUP_I2C_APPS_CBCR(id) ((id < 1) ? \ + (GCC_BLSP1_QUP1_I2C_APPS_CBCR):\ + (GCC_BLSP1_QUP1_I2C_APPS_CBCR + (GCC_BLSP1_QUP_I2C_OFFSET_INC * id))) + +#define I2C_PORT_ID(reg) ((reg - BLSP1_QUP_BASE) / GCC_BLSP1_QUP_I2C_OFFSET_INC) #define CMD_UPDATE 0x1 #define ROOT_EN 0x2 diff --git a/arch/arm/include/asm/arch-ipq9574/edma_regs.h b/arch/arm/include/asm/arch-ipq9574/edma_regs.h index 5d8c6a6af5..fe496e98f4 100644 --- a/arch/arm/include/asm/arch-ipq9574/edma_regs.h +++ b/arch/arm/include/asm/arch-ipq9574/edma_regs.h @@ -29,6 +29,7 @@ #define IPQ9574_EDMA_REG_RXDESC2FILL_MAP_0 0x14 #define IPQ9574_EDMA_REG_RXDESC2FILL_MAP_1 0x18 #define IPQ9574_EDMA_REG_RXDESC2FILL_MAP_2 0x1c +#define IPQ9574_EDMA_REG_DMAR_CTRL 0x48 #define IPQ9574_EDMA_REG_MISC_INT_STAT 0x5c #define IPQ9574_EDMA_REG_MISC_INT_MASK 0x60 #define IPQ9574_EDMA_REG_TXDESC2CMPL_MAP_0 0x8c @@ -50,6 +51,7 @@ #define IPQ9574_EDMA_REG_TXCMPL_CTRL(n) (0x79014 + (0x1000 * n)) #define IPQ9574_EDMA_REG_TX_INT_STAT(n) (0x99000 + (0x1000 * n)) #define IPQ9574_EDMA_REG_TX_INT_MASK(n) (0x99004 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_TX_MOD_TIMER(n) (0x9900c + (0x1000 * n)) #define IPQ9574_EDMA_REG_TX_INT_CTRL(n) (0x9900c + (0x1000 * n)) #define IPQ9574_EDMA_REG_RXFILL_BA(n) (0x29000 + (0x1000 * n)) #define IPQ9574_EDMA_REG_RXFILL_PROD_IDX(n) (0x29004 + (0x1000 * n)) @@ -66,13 +68,41 @@ #define IPQ9574_EDMA_REG_RXDESC_CTRL(n) (0x39018 + (0x1000 * n)) #define IPQ9574_EDMA_REG_RXDESC_INT_STAT(n) (0x59000 + (0x1000 * n)) #define IPQ9574_EDMA_REG_RXDESC_INT_MASK(n) (0x59004 + (0x1000 * n)) +#define IPQ9574_EDMA_REG_RX_MOD_TIMER(n) (0x59008 + (0x1000 * n)) #define IPQ9574_EDMA_REG_RX_INT_CTRL(n) (0x5900c + (0x1000 * n)) #define IPQ9574_EDMA_QID2RID_TABLE_MEM(q) (0xb9000 + (0x4 * q)) +/* + * EDMA_REG_DMAR_CTRL register + */ +#define IPQ9574_EDMA_DMAR_REQ_PRI_MASK 0x7 +#define IPQ9574_EDMA_DMAR_REQ_PRI_SHIFT 0x0 +#define IPQ9574_EDMA_DMAR_BURST_LEN_MASK 0x1 +#define IPQ9574_EDMA_DMAR_BURST_LEN_SHIFT 3 +#define IPQ9574_EDMA_DMAR_TXDATA_OUTSTANDING_NUM_MASK 0x1f +#define IPQ9574_EDMA_DMAR_TXDATA_OUTSTANDING_NUM_SHIFT 4 +#define IPQ9574_EDMA_DMAR_TXDESC_OUTSTANDING_NUM_MASK 0x7 +#define IPQ9574_EDMA_DMAR_TXDESC_OUTSTANDING_NUM_SHIFT 9 +#define IPQ9574_EDMA_DMAR_RXFILL_OUTSTANDING_NUM_MASK 0x7 +#define IPQ9574_EDMA_DMAR_RXFILL_OUTSTANDING_NUM_SHIFT 12 + +#define IPQ9574_EDMA_DMAR_REQ_PRI_SET(x) (((x) & IPQ9574_EDMA_DMAR_REQ_PRI_MASK) \ + << IPQ9574_EDMA_DMAR_REQ_PRI_SHIFT) +#define IPQ9574_EDMA_DMAR_TXDATA_OUTSTANDING_NUM_SET(x) (((x) & IPQ9574_EDMA_DMAR_TXDATA_OUTSTANDING_NUM_MASK) \ + << IPQ9574_EDMA_DMAR_TXDATA_OUTSTANDING_NUM_SHIFT) +#define IPQ9574_EDMA_DMAR_TXDESC_OUTSTANDING_NUM_SET(x) (((x) & IPQ9574_EDMA_DMAR_TXDESC_OUTSTANDING_NUM_MASK) \ + << IPQ9574_EDMA_DMAR_TXDESC_OUTSTANDING_NUM_SHIFT) +#define IPQ9574_EDMA_DMAR_RXFILL_OUTSTANDING_NUM_SET(x) (((x) & IPQ9574_EDMA_DMAR_RXFILL_OUTSTANDING_NUM_MASK) \ + << IPQ9574_EDMA_DMAR_RXFILL_OUTSTANDING_NUM_SHIFT) +#define IPQ9574_EDMA_DMAR_BURST_LEN_SET(x) (((x) & IPQ9574_EDMA_DMAR_BURST_LEN_MASK) \ + << IPQ9574_EDMA_DMAR_BURST_LEN_SHIFT) + +#define IPQ9574_EDMA_BURST_LEN_ENABLE 0x0 + /* * EDMA_REG_PORT_CTRL register */ -#define IPQ9574_EDMA_PORT_CTRL_EN 0x3 +#define IPQ9574_EDMA_PORT_CTRL_EN 0x3 /* * EDMA_REG_TXDESC_PROD_IDX register @@ -170,6 +200,18 @@ #define IPQ9574_EDMA_RXDESC_INT_MASK_PKT_INT 0x1 #define IPQ9574_EDMA_MASK_INT_DISABLE 0x0 +/* + * EDMA_REG_RX_MOD_TIMER register + */ +#define IPQ9574_EDMA_RX_MOD_TIMER_INIT_MASK 0xffff +#define IPQ9574_EDMA_RX_MOD_TIMER_INIT_SHIFT 0 + +/* + * EDMA_REG_TX_MOD_TIMER register + */ +#define IPQ9574_EDMA_TX_MOD_TIMER_INIT_MASK 0xffff +#define IPQ9574_EDMA_TX_MOD_TIMER_INIT_SHIFT 0 + /* * TXDESC shift values */ @@ -179,10 +221,27 @@ #define IPQ9574_EDMA_TXDESC_DATA_OFFSET_MASK 0xfff #define IPQ9574_EDMA_TXDESC_DATA_LENGTH_SHIFT 0 -#define IPQ9574_EDMA_TXDESC_DATA_LENGTH_MASK 0x3ffff +#define IPQ9574_EDMA_TXDESC_DATA_LENGTH_MASK 0x1ffff + +#define IPQ9574_EDMA_TXDESC_SERVICE_CODE_SHIFT 16 +#define IPQ9574_EDMA_TXDESC_SERVICE_CODE_MASK (0x1FF << IPQ9574_EDMA_TXDESC_SERVICE_CODE_SHIFT) +#define IPQ9574_EDMA_TXDESC_SERVICE_CODE_SET(x) (((x) << IPQ9574_EDMA_TXDESC_SERVICE_CODE_SHIFT) & IPQ9574_EDMA_TXDESC_SERVICE_CODE_MASK) +#define IPQ9574_EDMA_SC_BYPASS 1 + +#define IPQ9574_EDMA_DST_PORT_TYPE 2 +#define IPQ9574_EDMA_DST_PORT_TYPE_SHIFT 28 +#define IPQ9574_EDMA_DST_PORT_TYPE_MASK (0xf << IPQ9574_EDMA_DST_PORT_TYPE_SHIFT) +#define IPQ9574_EDMA_DST_PORT_ID_SHIFT 16 +#define IPQ9574_EDMA_DST_PORT_ID_MASK (0xfff << IPQ9574_EDMA_DST_PORT_ID_SHIFT) + +#define IPQ9574_EDMA_DST_PORT_TYPE_SET(x) (((x) << IPQ9574_EDMA_DST_PORT_TYPE_SHIFT) & IPQ9574_EDMA_DST_PORT_TYPE_MASK) +#define IPQ9574_EDMA_DST_PORT_ID_SET(x) (((x) << EDMA_DST_PORT_ID_SHIFT) & EDMA_DST_PORT_ID_MASK) + +#define IPQ9574_EDMA_RXDESC_SRCINFO_TYPE_PORTID 0x2000 +#define IPQ9574_EDMA_RXDESC_SRCINFO_TYPE_SHIFT 8 +#define IPQ9574_EDMA_RXDESC_SRCINFO_TYPE_MASK 0xf000 +#define IPQ9574_EDMA_RXDESC_PORTNUM_BITS 0x0FFF -#define IPQ9574_EDMA_PREHDR_DSTINFO_PORTID_IND 0x20 -#define IPQ9574_EDMA_PREHDR_PORTNUM_BITS 0x0fff #define IPQ9574_EDMA_RING_DMA_MASK 0xffffffff /* @@ -190,9 +249,14 @@ */ #define IPQ9574_EDMA_RXDESC_PKT_SIZE_MASK 0x3ffff #define IPQ9574_EDMA_RXDESC_PKT_SIZE_SHIFT 0 +#define IPQ9574_EDMA_RXDESC_SRC_INFO_GET(x) (x & 0xFFFF) #define IPQ9574_EDMA_RXDESC_RING_INT_STATUS_MASK 0x3 -#define IPQ9574_EDMA_TXCMPL_RING_INT_STATUS_MASK 0x3 -#define IPQ9574_EDMA_TXCMPL_RETMODE_OPAQUE 0x0 #define IPQ9574_EDMA_RXFILL_RING_INT_STATUS_MASK 0x1 +#define IPQ9574_EDMA_TXCMPL_RING_INT_STATUS_MASK 0x3 +#define IPQ9574_EDMA_TXCMPL_RETMODE_OPAQUE 0x0 +#define IPQ9574_EDMA_TX_NE_INT_EN 0x2 +#define IPQ9574_EDMA_RX_NE_INT_EN 0x2 +#define IPQ9574_EDMA_TX_INITIAL_PROD_IDX 0x0 + #endif /* __EDMA_REGS__ */ diff --git a/arch/arm/include/asm/arch-qca-common/qca_common.h b/arch/arm/include/asm/arch-qca-common/qca_common.h index 8b8a8f0c4b..f97133e41b 100644 --- a/arch/arm/include/asm/arch-qca-common/qca_common.h +++ b/arch/arm/include/asm/arch-qca-common/qca_common.h @@ -100,15 +100,15 @@ void dump_func(unsigned int dump_level); int do_dumpqca_flash_data(const char *); int do_dumpqca_usb_data(unsigned int dump_level); int apps_iscrashed(void); +int is_hlos_crashed(void); +int ipq_read_tcsr_boot_misc(void); int set_uuid_bootargs(char *boot_args, char *part_name, int buflen, bool gpt_flag); int get_eth_mac_address(uchar *enetaddr, uint no_of_macs); void set_ethmac_addr(void); -#ifndef CONFIG_IPQ9574_RUMI void aquantia_phy_reset_init_done(void); void aquantia_phy_reset_init(void); -#endif int bring_sec_core_up(unsigned int cpuid, unsigned int entry, unsigned int arg); int is_secondary_core_off(unsigned int cpuid); diff --git a/arch/arm/include/asm/arch-qca-common/scm.h b/arch/arm/include/asm/arch-qca-common/scm.h index 9e52a2094c..2088e388ce 100644 --- a/arch/arm/include/asm/arch-qca-common/scm.h +++ b/arch/arm/include/asm/arch-qca-common/scm.h @@ -124,7 +124,7 @@ extern int qca_scm_call(u32 svc_id, u32 cmd_id, void *buf, size_t len); int qca_scm_usb_mode_write(u32, u32); int qca_scm_call_write(u32, u32, u32 *, u32); -int qca_scm_call_read(u32, u32, u32 *, u32 *); +int qca_scm_call_read(u32, u32, u32 *, u32*); int qca_scm_crypto(int, void *, u32); int qca_scm_sdi(void); int qca_scm_dload(u32); diff --git a/arch/arm/include/asm/arch-qca-common/smem.h b/arch/arm/include/asm/arch-qca-common/smem.h index 0438ed4f30..8618feb5c6 100644 --- a/arch/arm/include/asm/arch-qca-common/smem.h +++ b/arch/arm/include/asm/arch-qca-common/smem.h @@ -127,6 +127,7 @@ typedef struct extern qca_smem_bootconfig_info_t qca_smem_bootconfig_info; int smem_bootconfig_info(void); +int smem_update_bootconfig_to_flash(void); unsigned int get_smem_spi_addr_len(void); unsigned int get_rootfs_active_partition(void); unsigned int get_mibib_active_partition(void); @@ -134,4 +135,6 @@ void qca_smem_part_to_mtdparts(char *mtdid, int len); int ipq_smem_get_socinfo_cpu_type(uint32_t *cpu_type); int ipq_smem_get_socinfo_version(uint32_t *version); int ipq_smem_get_boot_flash(uint32_t *flash_type); +int write_to_flash(int flash_type, uint32_t address, uint32_t offset, +uint32_t part_size, uint32_t file_size, char *layout); #endif diff --git a/arch/arm/include/asm/mach-types.h b/arch/arm/include/asm/mach-types.h index 7cf8f72d26..16e88426db 100644 --- a/arch/arm/include/asm/mach-types.h +++ b/arch/arm/include/asm/mach-types.h @@ -1146,6 +1146,9 @@ extern unsigned int __machine_arch_type; #define MACH_TYPE_IPQ6018_AP_CP01_C4 0x8030003 #define MACH_TYPE_IPQ6018_AP_CP01_C5 0x8030004 #define MACH_TYPE_IPQ5018_AP_MP02_1 0x8040000 +#define MACH_TYPE_IPQ5018_AP_MP03_1 0x8040001 +#define MACH_TYPE_IPQ5018_AP_MP03_3 0x8040002 +#define MACH_TYPE_IPQ5018_AP_MP05_1 0x8040006 #define MACH_TYPE_IPQ5018_DB_MP02_1 0X1040003 #define MACH_TYPE_IPQ807x_AP_HK01_C1 0x8010000 #define MACH_TYPE_IPQ807x_AP_HK01_C3 0x8010200 @@ -1156,6 +1159,10 @@ extern unsigned int __machine_arch_type; #define MACH_TYPE_IPQ807x_AP_HK12_C1 0x8010013 #define MACH_TYPE_IPQ807x_AP_HK10_C2 0x801010E #define MACH_TYPE_IPQ9574_EMULATION 0xF050000 +#define MACH_TYPE_IPQ9574_AP_AL02_C1 0x8050001 +#define MACH_TYPE_IPQ9574_AP_AL02_C4 0x8050301 +#define MACH_TYPE_IPQ9574_AP_AL02_C5 0x8050401 +#define MACH_TYPE_IPQ9574_AP_AL02_C6 0x8050501 #ifdef CONFIG_ARCH_EBSA110 # ifdef machine_arch_type diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index 4ef3dbb697..adadc8d12b 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -33,6 +33,7 @@ DECLARE_GLOBAL_DATA_PTR; static struct tag *params; +extern unsigned ipq_runtime_fs_feature_enabled; static ulong get_sp(void) { @@ -277,6 +278,21 @@ struct aarch64_hdr { /* Subcommand: GO */ static void boot_jump_linux(bootm_headers_t *images, int flag) { +#ifdef CONFIG_IPQ_RUNTIME_FAILSAFE + unsigned int cookie, ret; + if (ipq_runtime_fs_feature_enabled) { + cookie = ipq_read_tcsr_boot_misc(); + + cookie &= ~IPQ_FS_NONHLOS_BIT; + cookie |= IPQ_FS_HLOS_BIT; + + fs_debug("\nFailsafe: %s: Clear NonHLOS bit and set HLOS bit\n", __func__); + ret = qca_scm_dload(cookie); + if (ret) + printf ("Error in setting HLOS failsafe bit\n"); + } +#endif + #ifdef CONFIG_ARM64 void (*kernel_entry)(void *fdt_addr, void *res0, void *res1, void *res2); diff --git a/board/qca/arm/common/board_init.c b/board/qca/arm/common/board_init.c index 50bec5fc38..48d08ef57d 100644 --- a/board/qca/arm/common/board_init.c +++ b/board/qca/arm/common/board_init.c @@ -113,7 +113,9 @@ int board_init(void) qca_smem_flash_info_t *sfi = &qca_smem_flash_info; gd->bd->bi_boot_params = QCA_BOOT_PARAMS_ADDR; +#ifndef CONFIG_OF_BOARD_FIXUP gd->bd->bi_arch_number = smem_get_board_platform_type(); +#endif ret = smem_get_boot_flash(&sfi->flash_type, &sfi->flash_index, @@ -223,7 +225,6 @@ int board_init(void) aquantia_phy_reset_init(); #endif disable_audio_clks(); - ipq_uboot_fdt_fixup(); /* * Needed by ipq806x to avoid TX FIFO curruption during * serial init after relocation @@ -319,6 +320,14 @@ int board_early_init_f(void) return 0; } +int board_fix_fdt(void *rw_fdt_blob) +{ + gd->bd->bi_arch_number = smem_get_board_platform_type(); + + ipq_uboot_fdt_fixup(); + return 0; +} + #ifdef CONFIG_FLASH_PROTECT void board_flash_protect(void) { diff --git a/board/qca/arm/common/cmd_bootqca.c b/board/qca/arm/common/cmd_bootqca.c index 74a5295df5..90d6ef50d4 100644 --- a/board/qca/arm/common/cmd_bootqca.c +++ b/board/qca/arm/common/cmd_bootqca.c @@ -307,9 +307,9 @@ static int parse_elf_image_phdr(image_info *img_info, unsigned int addr) #ifdef CONFIG_IPQ_ROOTFS_AUTH static int copy_rootfs(unsigned int request, uint32_t size) { - int ret; char runcmd[256]; #ifdef CONFIG_QCA_MMC + int ret; block_dev_desc_t *blk_dev; disk_partition_t disk_info; unsigned int active_part = 0; @@ -401,6 +401,11 @@ static int authenticate_rootfs(unsigned int kernel_addr) rootfs_img_info.size = sizeof(mbn_header_t) + mbn_ptr->image_size; ret = qca_scm_secure_authenticate(&rootfs_img_info, sizeof(rootfs_img_info)); + + memset((void *)kernel_img_info.kernel_load_addr, 0, sizeof(mbn_header_t)); + memset(mbn_ptr, 0, + (sizeof(mbn_header_t) + mbn_ptr->signature_size + mbn_ptr->cert_chain_size)); + if (ret) return CMD_RET_FAILURE; @@ -435,6 +440,7 @@ static int authenticate_rootfs_elf(unsigned int rootfs_hdr) rootfs_img_info.size = img_info.img_offset + img_info.img_size; ret = qca_scm_secure_authenticate(&rootfs_img_info, sizeof(rootfs_img_info)); + memset((void *)rootfs_hdr, 0, img_info.img_offset); if (ret) return CMD_RET_FAILURE; @@ -635,6 +641,7 @@ static int do_boot_signedimg(cmd_tbl_t *cmdtp, int flag, int argc, char *const a setenv("mtdids", mtdids); #ifndef CONFIG_IPQ_ELF_AUTH + mbn_header_t * mbn_ptr = (mbn_header_t *) request; request += sizeof(mbn_header_t); #else kernel_img_info.kernel_load_addr = request; @@ -649,6 +656,11 @@ static int do_boot_signedimg(cmd_tbl_t *cmdtp, int flag, int argc, char *const a ret = qca_scm_auth_kernel(&kernel_img_info, sizeof(kernel_img_info)); +#ifndef CONFIG_IPQ_ELF_AUTH + memset((void *)mbn_ptr->signature_ptr, 0,(mbn_ptr->signature_size + mbn_ptr->cert_chain_size)); +#else + memset((void *)kernel_img_info.kernel_load_addr, 0, img_info.img_offset); +#endif if (ret) { printf("Kernel image authentication failed \n"); BUG(); @@ -711,6 +723,9 @@ static int do_boot_unsignedimg(cmd_tbl_t *cmdtp, int flag, int argc, char *const disk_partition_t disk_info; unsigned int active_part = 0; #endif +#ifdef CONFIG_IPQ_ELF_AUTH + image_info img_info; +#endif if (argc == 2 && strncmp(argv[1], "debug", 5) == 0) debug = 1; @@ -829,6 +844,13 @@ static int do_boot_unsignedimg(cmd_tbl_t *cmdtp, int flag, int argc, char *const ret = config_select((CONFIG_SYS_LOAD_ADDR + sizeof(mbn_header_t)), runcmd, sizeof(runcmd)); +#ifdef CONFIG_IPQ_ELF_AUTH + } else if (!parse_elf_image_phdr(&img_info, + CONFIG_SYS_LOAD_ADDR)) { + ret = config_select((CONFIG_SYS_LOAD_ADDR + + img_info.img_offset), + runcmd, sizeof(runcmd)); +#endif } else if (ret == IMAGE_FORMAT_LEGACY) { snprintf(runcmd, sizeof(runcmd), "bootm 0x%x\n", (CONFIG_SYS_LOAD_ADDR + diff --git a/board/qca/arm/common/fdt_fixup.c b/board/qca/arm/common/fdt_fixup.c index 2da6f0cc95..ca56a84070 100644 --- a/board/qca/arm/common/fdt_fixup.c +++ b/board/qca/arm/common/fdt_fixup.c @@ -400,8 +400,11 @@ void ipq_fdt_mem_rsvd_fixup(void *blob) if (nodeoff < 0) { nodeoff = fdt_path_offset(blob, "/qti,scm_restart_reason"); if (nodeoff < 0) { - debug("fdt-fixup: unable to find compatible node\n"); - return; + nodeoff = fdt_path_offset(blob, "/soc/qti,scm_restart_reason"); + if (nodeoff < 0) { + debug("fdt-fixup: unable to find compatible node\n"); + return; + } } } @@ -888,6 +891,11 @@ __weak void fdt_fixup_sdx65_gpio(void *blob) return; } +__weak void fdt_fixup_runtime_failsafe(void *blob) +{ + return; +} + void set_mtdids(void) { char mtdids[256]; @@ -1047,6 +1055,9 @@ int ft_board_setup(void *blob, bd_t *bd) fdt_fixup_cpus_node(blob); fdt_low_memory_fixup(blob); fdt_fixup_qpic(blob); +#ifdef CONFIG_IPQ_RUNTIME_FAILSAFE + fdt_fixup_runtime_failsafe(blob); +#endif s = getenv("dload_warm_reset"); if (s) fdt_fixup_set_dload_warm_reset(blob); diff --git a/board/qca/arm/ipq5018/ipq5018.c b/board/qca/arm/ipq5018/ipq5018.c index 06501e7982..17c0aa7490 100644 --- a/board/qca/arm/ipq5018/ipq5018.c +++ b/board/qca/arm/ipq5018/ipq5018.c @@ -22,6 +22,16 @@ #include #include #include +#include +#include +#if defined(CONFIG_ART_COMPRESSED) && \ + (defined(CONFIG_GZIP) || defined(CONFIG_LZMA)) +#ifndef CONFIG_COMPRESSED_LOAD_ADDR +#define CONFIG_COMPRESSED_LOAD_ADDR CONFIG_SYS_LOAD_ADDR +#endif +#include +#include +#endif #ifdef CONFIG_QCA_MMC #include #include @@ -31,6 +41,7 @@ #endif #ifdef CONFIG_QPIC_NAND #include +#include #endif #ifdef CONFIG_IPQ_BT_SUPPORT #include @@ -1330,6 +1341,7 @@ int board_eth_init(bd_t *bis) gmac_cfg[loop].unit = -1; status = ipq_gmac_init(gmac_cfg); + board_update_caldata(); return status; } @@ -1893,6 +1905,200 @@ void board_pci_deinit() } #endif + /* + * Gets the Caldata from the ART partition table and return the value + */ +int get_eth_caldata(u32 *caldata, u32 offset) +{ + s32 ret = 0 ; + u32 flash_type=0u; + u32 start_blocks; + u32 size_blocks; + u32 art_offset=0U ; + u32 length = 4; + qca_smem_flash_info_t *sfi = &qca_smem_flash_info; + + struct spi_flash *flash = NULL; + +#if defined(CONFIG_ART_COMPRESSED) && (defined(CONFIG_GZIP) || defined(CONFIG_LZMA)) + void *load_buf, *image_buf; + unsigned long img_size; + unsigned long desMaxSize; +#endif + +#ifdef CONFIG_QCA_MMC + block_dev_desc_t *blk_dev; + disk_partition_t disk_info; + struct mmc *mmc; + char mmc_blks[512]; +#endif + + if ((sfi->flash_type == SMEM_BOOT_SPI_FLASH) || + (sfi->flash_type == SMEM_BOOT_NOR_FLASH) || + (sfi->flash_type == SMEM_BOOT_NORPLUSNAND) || + (sfi->flash_type == SMEM_BOOT_NORPLUSEMMC)) + { + ret = smem_getpart("0:ART", &start_blocks, &size_blocks); + if (ret < 0) { + printf("No ART partition found\n"); + return ret; + } + + /* + * ART partition 0th position. + */ + art_offset = (u32)((u32) qca_smem_flash_info.flash_block_size * start_blocks); + +#ifndef CONFIG_ART_COMPRESSED + art_offset = (art_offset + offset); +#endif + + flash = spi_flash_probe(CONFIG_SF_DEFAULT_BUS, CONFIG_SF_DEFAULT_CS, + CONFIG_SF_DEFAULT_SPEED, CONFIG_SF_DEFAULT_MODE); + + + if (flash == NULL){ + printf("No SPI flash device found\n"); + ret = -1; + } + else { +#if defined(CONFIG_ART_COMPRESSED) && defined(CONFIG_LZMA) + image_buf = map_sysmem(CONFIG_COMPRESSED_LOAD_ADDR, 0); + load_buf = map_sysmem(CONFIG_COMPRESSED_LOAD_ADDR + 0x100000, 0); + img_size = qca_smem_flash_info.flash_block_size * size_blocks; + desMaxSize = 0x100000; + ret = spi_flash_read(flash, art_offset, img_size, image_buf); + if (ret == 0) { + ret = -1; +#ifdef CONFIG_LZMA + if (ret != 0){ + + ret = lzmaBuffToBuffDecompress(load_buf, + (SizeT *)&desMaxSize, + image_buf, + (SizeT)img_size); + } +#endif + if((!ret) && (memcpy(caldata, load_buf + offset , length))){} + else { + printf("Invalid compression type..\n"); + ret = -1; + } + } +#else + ret = spi_flash_read(flash, art_offset, length, caldata); +#endif + } + + if (ret < 0) + printf("ART partition read failed..\n"); + } +#ifdef CONFIG_QPIC_NAND + else if ((sfi->flash_type == SMEM_BOOT_NAND_FLASH ) || (sfi->flash_type == SMEM_BOOT_QSPI_NAND_FLASH)) + { + if (qca_smem_flash_info.flash_type == SMEM_BOOT_SPI_FLASH) + flash_type = CONFIG_SPI_FLASH_INFO_IDX; + else{ + flash_type = CONFIG_NAND_FLASH_INFO_IDX; + } + + ret = smem_getpart("0:ART", &start_blocks, &size_blocks); + if (ret < 0) { + printf("No ART partition found\n"); + return ret; + } + + /* + * ART partition 0th position. + */ + art_offset = (u32)((u32) qca_smem_flash_info.flash_block_size * start_blocks); + art_offset = /*(loff_t)*/(art_offset + offset); + + ret = nand_read(&nand_info[flash_type],art_offset, &length,(u_char*) caldata); + + if (ret < 0) + printf("ART partition read failed..\n"); + } +#endif + else{ +#ifdef CONFIG_QCA_MMC + blk_dev = mmc_get_dev(mmc_host.dev_num); + ret = get_partition_info_efi_by_name(blk_dev, "0:ART", &disk_info); + /* + * ART partition 0th position will contain MAC address. + * Read 1 block. + */ + if (ret == 0) { + mmc = mmc_host.mmc; + ret = mmc->block_dev.block_read + (mmc_host.dev_num, (disk_info.start+(offset/512)), + 1, mmc_blks); + memcpy(caldata, (mmc_blks+(offset%512)), length); + } + if (ret < 0) + printf("ART partition read failed..\n"); +#endif + } + + /* + * Avoid unused warning + * */ + (void)flash_type; + + return ret; + +} + +void board_update_caldata() +{ + u32 reg_val=0u; + s32 ret = 0 ; + u32 u32_calDataOffset = 0U; + u32 u32_calData = 0u; + u32 u32_CDACIN =0U, u32_CDACOUT = 0u; + int node_off,slotId; + + node_off = fdt_path_offset(gd->fdt_blob, "/slot_Id"); + if (node_off < 0) { + printf("%s: Unable to find slot-Id, Default CapIn/CapOut values used\n", + __func__); + return; + } + + slotId = fdtdec_get_uint(gd->fdt_blob,node_off, "slotId", 0); + + u32_calDataOffset = (u32)(((slotId*150)+4)*1024 + 0x106E4); + ret = get_eth_caldata(&u32_calData,u32_calDataOffset); + if (ret < 0) + return; + + u32_CDACIN = u32_calData & 0x3FF; + u32_CDACOUT = (u32_calData >> 16) & 0x1FFu; + + if(((u32_CDACIN == 0x0u) || (u32_CDACIN == 0x3FFu)) && ((u32_CDACOUT == 0x0u) || (u32_CDACOUT == 0x1FFu))) + { + u32_CDACIN = 0x230; + u32_CDACOUT = 0xB0; + } + u32_CDACIN = u32_CDACIN<<22u; + u32_CDACOUT = u32_CDACOUT<<13u; + + qca_scm_call_read(0x2, 0x22, (u32 *)IRON2G_RFA_RFA_OTP_OTP_OV_1,®_val); + reg_val = (reg_val & 0xFFF9FFFF) | (0x3 << 17u); + qca_scm_call_write(0x2, 0x23,(u32 *)IRON2G_RFA_RFA_OTP_OTP_OV_1, reg_val); + + qca_scm_call_read(0x2, 0x22, (u32 *)IRON2G_RFA_RFA_OTP_OTP_XO_0,®_val); + + if((u32_CDACIN == (reg_val & (0x3FF<<22u))) && (u32_CDACOUT == (reg_val & (0x1FF<<13u)))) + { + printf("ART data same as IRON2G_RFA_RFA_OTP_OTP_XO_0\n"); + return; + } + + reg_val = ((reg_val&0x00001FFF) | ((u32_CDACIN | u32_CDACOUT)&(~0x00001FFF))); + qca_scm_call_write(0x2, 0x23,(u32 *)IRON2G_RFA_RFA_OTP_OTP_XO_0, reg_val); +} + void fdt_fixup_qpic(void *blob) { int node_off, ret; @@ -2022,6 +2228,39 @@ int bring_sec_core_up(unsigned int cpuid, unsigned int entry, unsigned int arg) } #endif +unsigned int get_dts_machid(unsigned int machid) +{ + switch (machid) + { + case MACH_TYPE_IPQ5018_AP_MP05_1: + return MACH_TYPE_IPQ5018_AP_MP03_3; + default: + return machid; + } +} + +void ipq_uboot_fdt_fixup(void) +{ + int ret, len; + const char *config = "config@mp05.1"; + len = fdt_totalsize(gd->fdt_blob) + strlen(config) + 1; + if (gd->bd->bi_arch_number == MACH_TYPE_IPQ5018_AP_MP05_1) + { + /* + * Open in place with a new length. + */ + ret = fdt_open_into(gd->fdt_blob, (void *)gd->fdt_blob, len); + if (ret) + printf("uboot-fdt-fixup: Cannot expand FDT: %s\n", fdt_strerror(ret)); + + ret = fdt_setprop((void *)gd->fdt_blob, 0, "config_name", + config, (strlen(config)+1)); + if (ret) + printf("uboot-fdt-fixup: unable to set config_name(%d)\n", ret); + } + return; +} + int get_soc_hw_version(void) { return readl(TCSR_SOC_HW_VERSION_REG); diff --git a/board/qca/arm/ipq5018/ipq5018.h b/board/qca/arm/ipq5018/ipq5018.h index b6e5c0f86e..ebbcbb8b69 100644 --- a/board/qca/arm/ipq5018/ipq5018.h +++ b/board/qca/arm/ipq5018/ipq5018.h @@ -351,6 +351,13 @@ setbits_le32(addr, value); \ mdelay(delay); \ clrbits_le32(addr, value); \ + +/* + * OTP Register + */ +#define IRON2G_RFA_RFA_OTP_OTP_XO_0 0xC4D44A0 +#define IRON2G_RFA_RFA_OTP_OTP_OV_1 0xC4D4484 + /* * PCIE Register */ @@ -558,6 +565,8 @@ struct smem_ram_ptable { struct smem_ram_ptn parts[32]; } __attribute__ ((__packed__)); +int get_eth_caldata(u32 *caldata, u32 offset); +void board_update_caldata(void); int smem_ram_ptable_init(struct smem_ram_ptable *smem_ram_ptable); void reset_crashdump(void); void reset_board(void); diff --git a/board/qca/arm/ipq6018/ipq6018.c b/board/qca/arm/ipq6018/ipq6018.c index 9e8d93598e..3756b1f7fc 100644 --- a/board/qca/arm/ipq6018/ipq6018.c +++ b/board/qca/arm/ipq6018/ipq6018.c @@ -28,9 +28,11 @@ #include #include #include +#include #define DLOAD_MAGIC_COOKIE 0x10 #define DLOAD_DISABLED 0x40 +#define DLOAD_BITS 0xFF #define TCSR_SOC_HW_VERSION_REG 0x194D000 @@ -45,6 +47,8 @@ const char *del_node[] = {"uboot", NULL}; const add_node_t add_fdt_node[] = {{}}; static int aq_phy_initialised; +extern unsigned ipq_runtime_fs_feature_enabled; + struct dumpinfo_t dumpinfo_n[] = { /* TZ stores the DDR physical address at which it stores the * APSS regs, UTCM copy dump. We will have the TZ IMEM @@ -133,6 +137,31 @@ void qca_serial_init(struct ipq_serial_platdata *plat) return; } +#ifdef CONFIG_IPQ_RUNTIME_FAILSAFE +void fdt_fixup_runtime_failsafe(void *blob) +{ + int node_off, ret; + const char *fs_node = {"/soc/qti,scm_restart_reason"}; + + /* This fixup is for informing HLOS whether + * runtime failsafe feature is enabled or not + */ + node_off = fdt_path_offset(blob, fs_node); + if (node_off < 0) { + printf("%s: Failsafe: unable to find node '%s'\n", + __func__, fs_node); + return; + } + + ret = fdt_setprop_u32(blob, node_off, "qti,runtime-failsafe", + ipq_runtime_fs_feature_enabled); + if (ret) { + printf("%s : Unable to set property 'ipq,runtime_failsafe'\n",__func__); + return; + } +} +#endif + int do_pmic_reset() { struct udevice *bus, *dev; @@ -167,11 +196,26 @@ int do_pmic_reset() return 0; } +#ifdef CONFIG_HW_WATCHDOG +void hw_watchdog_reset(void) +{ + writel(1, APCS_WDT_RST); +} +#endif + void reset_crashdump(void) { unsigned int ret = 0; + unsigned int cookie = 0; + +#ifdef CONFIG_IPQ_RUNTIME_FAILSAFE + cookie = ipq_read_tcsr_boot_misc(); + fs_debug("\nFailsafe: %s: Clearing DLOAD and NonHLOS bits\n", __func__); + cookie &= ~(DLOAD_BITS); + cookie &= ~(IPQ_FS_NONHLOS_BIT); +#endif qca_scm_sdi(); - ret = qca_scm_dload(CLEAR_MAGIC); + ret = qca_scm_dload(cookie); if (ret) printf ("Error in reseting the Magic cookie\n"); return; @@ -803,11 +847,29 @@ __weak int ipq_get_tz_version(char *version_name, int buf_size) return 1; } +#ifdef CONFIG_IPQ_RUNTIME_FAILSAFE +int ipq_read_tcsr_boot_misc(void) +{ + u32 *dmagic = (u32 *)CONFIG_IPQ6018_DMAGIC_ADDR; + return *dmagic; +} + +int is_hlos_crashed(void) +{ + u32 *dmagic = (u32 *)CONFIG_IPQ6018_DMAGIC_ADDR; + + if (*dmagic & IPQ_FS_HLOS_BIT) + return 1; + + return 0; +} +#endif + int apps_iscrashed_crashdump_disabled(void) { u32 *dmagic = (u32 *)CONFIG_IPQ6018_DMAGIC_ADDR; - if (*dmagic == DLOAD_DISABLED) + if (*dmagic & DLOAD_DISABLED) return 1; return 0; @@ -817,7 +879,7 @@ int apps_iscrashed(void) { u32 *dmagic = (u32 *)CONFIG_IPQ6018_DMAGIC_ADDR; - if (*dmagic == DLOAD_MAGIC_COOKIE) + if (*dmagic & DLOAD_MAGIC_COOKIE) return 1; return 0; @@ -1383,8 +1445,12 @@ void fdt_fixup_set_qca_cold_reboot_enable(void *blob) void fdt_fixup_wcss_rproc_for_atf(void *blob) { - parse_fdt_fixup("/soc/qcom_q6v5_wcss@CD00000%qcom,nosecure%1", blob); - parse_fdt_fixup("/soc/qcom_q6v5_wcss@CD00000%qca,wcss-aon-reset-seq%1", blob); + if (fdt_path_offset(blob, "/soc/remoteproc@cd00000") >= 0) + parse_fdt_fixup("/soc/remoteproc@cd00000%qcom,nosecure%1", blob); + else { + parse_fdt_fixup("/soc/qcom_q6v5_wcss@CD00000%qcom,nosecure%1", blob); + parse_fdt_fixup("/soc/qcom_q6v5_wcss@CD00000%qca,wcss-aon-reset-seq%1", blob); + } } int get_soc_hw_version(void) diff --git a/board/qca/arm/ipq6018/ipq6018.h b/board/qca/arm/ipq6018/ipq6018.h index c02fb9bbfa..5600ad0f31 100644 --- a/board/qca/arm/ipq6018/ipq6018.h +++ b/board/qca/arm/ipq6018/ipq6018.h @@ -263,6 +263,8 @@ #define ARM_PSCI_TZ_FN_CPU_ON ARM_PSCI_TZ_FN(3) #define ARM_PSCI_TZ_FN_AFFINITY_INFO ARM_PSCI_TZ_FN(4) +#define APCS_WDT_RST 0xB017004 + unsigned int __invoke_psci_fn_smc(unsigned int, unsigned int, unsigned int, unsigned int); @@ -365,9 +367,10 @@ typedef enum { SMEM_BOOT_DUALPARTINFO = 503, SMEM_PARTITION_TABLE_OFFSET = 504, SMEM_SPI_FLASH_ADDR_LEN = 505, + SMEM_RUNTIME_FAILSAFE_INFO = 507, SMEM_FIRST_VALID_TYPE = SMEM_SPINLOCK_ARRAY, - SMEM_LAST_VALID_TYPE = SMEM_SPI_FLASH_ADDR_LEN, - SMEM_MAX_SIZE = SMEM_SPI_FLASH_ADDR_LEN + 1, + SMEM_LAST_VALID_TYPE = SMEM_RUNTIME_FAILSAFE_INFO, + SMEM_MAX_SIZE = SMEM_RUNTIME_FAILSAFE_INFO + 1, } smem_mem_type_t; extern const char *rsvd_node; diff --git a/board/qca/arm/ipq807x/ipq807x.c b/board/qca/arm/ipq807x/ipq807x.c index 4d398bad9f..9c89d2dc04 100644 --- a/board/qca/arm/ipq807x/ipq807x.c +++ b/board/qca/arm/ipq807x/ipq807x.c @@ -1036,6 +1036,9 @@ int sdx65_attached(void) void fdt_fixup_sdx65_gpio(void *blob) { unsigned int machid = gd->bd->bi_arch_number; + int offset, len; + u32 *data; + if (machid != 0x08010400) return; @@ -1044,10 +1047,41 @@ void fdt_fixup_sdx65_gpio(void *blob) parse_fdt_fixup("/soc/pci@20000000/%add%x65_attached", blob); parse_fdt_fixup("/soc/pci@20000000/%x65_attached%1", blob); - parse_fdt_fixup("/soc/pci@20000000/pcie0_rp/qcom,mhi@0/%mdm2ap%21", blob); - parse_fdt_fixup("/soc/pci@20000000/pcie0_rp/qcom,mhi@0/%ap2mdm%45", blob); - parse_fdt_fixup("/soc/pinctrl@1000000/ap2mdm_status/%pins%?gpio45", blob); - parse_fdt_fixup("/soc/pinctrl@1000000/mdm2ap_e911_status/%pins%?gpio22", blob); + + offset = fdt_path_offset(blob, "/soc/pci@20000000/pcie0_rp/qcom,mhi@0"); + if(offset >= 0) { + data = (u32 *)fdt_getprop(blob, offset, "mdm2ap", &len); + if (data) { + parse_fdt_fixup("/soc/pci@20000000/pcie0_rp/qcom,mhi@0/%mdm2ap%21", blob); + } else { + data = (u32 *)fdt_getprop(blob, offset, "mdm2ap-gpio", &len); + if (data) { + data[1] = cpu_to_fdt32(21); + fdt_setprop_inplace(blob, offset, "mdm2ap-gpio", data, len); + } + } + + data = (u32 *)fdt_getprop(blob, offset, "ap2mdm", &len); + if (data) { + parse_fdt_fixup("/soc/pci@20000000/pcie0_rp/qcom,mhi@0/%ap2mdm%45", blob); + } else { + data = (u32 *)fdt_getprop(blob, offset, "ap2mdm-gpio", &len); + if (data) { + data[1] = cpu_to_fdt32(45); + fdt_setprop_inplace(blob, offset, "ap2mdm-gpio", data, len); + } + } + } + + if (fdt_path_offset(blob, "/soc/pinctrl@1000000/ap2mdm_status") >= 0) + parse_fdt_fixup("/soc/pinctrl@1000000/ap2mdm_status/%pins%?gpio45", blob); + else if (fdt_path_offset(blob, "/soc/pinctrl@1000000/pcie_sdx_pinmux/ap2mdm_status") >= 0) + parse_fdt_fixup("/soc/pinctrl@1000000/pcie_sdx_pinmux/ap2mdm_status/%pins%?gpio45", blob); + + if (fdt_path_offset(blob, "/soc/pinctrl@1000000/mdm2ap_e911_status/") >= 0) + parse_fdt_fixup("/soc/pinctrl@1000000/mdm2ap_e911_status/%pins%?gpio22", blob); + else if (fdt_path_offset(blob, "/soc/pinctrl@1000000/pcie_sdx_pinmux/mdm2ap_e911_status") >= 0) + parse_fdt_fixup("/soc/pinctrl@1000000/pcie_sdx_pinmux/mdm2ap_e911_status/%pins%?gpio22", blob); } #ifdef CONFIG_USB_XHCI_IPQ diff --git a/board/qca/arm/ipq9574/clock.c b/board/qca/arm/ipq9574/clock.c index 4572671b52..3858d470ed 100644 --- a/board/qca/arm/ipq9574/clock.c +++ b/board/qca/arm/ipq9574/clock.c @@ -12,28 +12,39 @@ */ #include +#include #include #include #include +#include + +DECLARE_GLOBAL_DATA_PTR; #ifdef CONFIG_IPQ9574_I2C -void i2c_clock_config(void) +void i2c_clock_config() { -#ifndef CONFIG_IPQ9574_RUMI - int cfg; + int cfg, i2c_id; + int i2c_node; + const u32 *i2c_base; - /* Configure qup1_i2c_apps_clk_src */ - cfg = (GCC_BLSP1_QUP1_I2C_APPS_CFG_RCGR_SRC_SEL | - GCC_BLSP1_QUP1_I2C_APPS_CFG_RCGR_SRC_DIV); - writel(cfg, GCC_BLSP1_QUP1_I2C_APPS_CFG_RCGR); + i2c_node = fdt_path_offset(gd->fdt_blob, "i2c0"); + if (i2c_node >= 0) { + i2c_base = fdt_getprop(gd->fdt_blob, i2c_node, "reg", NULL); + if (i2c_base) { + i2c_id = I2C_PORT_ID(fdt32_to_cpu(i2c_base[0])); + /* Configure qup1_i2c_apps_clk_src */ + cfg = (GCC_BLSP1_QUP1_I2C_APPS_CFG_RCGR_SRC_SEL | + GCC_BLSP1_QUP1_I2C_APPS_CFG_RCGR_SRC_DIV); + writel(cfg, GCC_BLSP1_QUP_I2C_APPS_CFG_RCGR(i2c_id)); - writel(CMD_UPDATE, GCC_BLSP1_QUP1_I2C_APPS_CMD_RCGR); - mdelay(100); - writel(ROOT_EN, GCC_BLSP1_QUP1_I2C_APPS_CMD_RCGR); + writel(CMD_UPDATE, GCC_BLSP1_QUP_I2C_APPS_CMD_RCGR(i2c_id)); + mdelay(100); + writel(ROOT_EN, GCC_BLSP1_QUP_I2C_APPS_CMD_RCGR(i2c_id)); - /* Configure CBCR */ - writel(CLK_ENABLE, GCC_BLSP1_QUP1_I2C_APPS_CBCR); -#endif + /* Configure CBCR */ + writel(CLK_ENABLE, GCC_BLSP1_QUP_I2C_APPS_CBCR(i2c_id)); + } + } } #endif @@ -159,7 +170,6 @@ void qpic_set_clk_rate(unsigned int clk_rate, int blk_type, int req_clk_src_type #ifdef CONFIG_PCI_IPQ void pcie_v2_clock_init(int pcie_id) { -#ifndef CONFIG_IPQ9574_RUMI int cfg, div; /* Configure pcie_aux_clk_src */ @@ -224,12 +234,10 @@ void pcie_v2_clock_init(int pcie_id) writel(ROOT_EN, GCC_PCIE_REG(GCC_PCIE_RCHNG_CMD_RCGR, pcie_id)); writel(CLK_ENABLE, GCC_PCIE_REG(GCC_PCIE_AUX_CBCR, pcie_id)); -#endif } void pcie_v2_clock_deinit(int pcie_id) { -#ifndef CONFIG_IPQ9574_RUMI writel(0x0, GCC_PCIE_REG(GCC_PCIE_AUX_CMD_RCGR, 0)); mdelay(100); writel(0x0, GCC_PCIE_REG(GCC_PCIE_AHB_CBCR, pcie_id)); @@ -255,14 +263,12 @@ void pcie_v2_clock_deinit(int pcie_id) writel(0x0, GCC_ANOC_PCIE3_2LANE_M_CBCR); break; } -#endif } #endif #ifdef CONFIG_USB_XHCI_IPQ void usb_clock_init(int id) { -#ifndef CONFIG_IPQ9574_RUMI int cfg; /* Configure usb0_master_clk_src */ cfg = (GCC_USB0_MASTER_CFG_RCGR_SRC_SEL | @@ -305,13 +311,11 @@ void usb_clock_init(int id) writel((CLK_ENABLE | NOC_HANDSHAKE_FSM_EN), GCC_USB0_PHY_CFG_AHB_CBCR); writel(CLK_ENABLE, GCC_USB0_PIPE_CBCR); -#endif } void usb_clock_deinit(void) { -#ifndef CONFIG_IPQ9574_RUMI /* Disable clocks */ writel(0x8000, GCC_USB0_PHY_CFG_AHB_CBCR); writel(0xcff0, GCC_USB0_MASTER_CBCR); @@ -320,14 +324,12 @@ void usb_clock_deinit(void) writel(0, GCC_USB0_AUX_CBCR); writel(0, GCC_ANOC_USB_AXI_CBCR); writel(0, GCC_SNOC_USB_CBCR); -#endif } #endif #ifdef CONFIG_QCA_MMC void emmc_clock_init(void) { -#ifndef CONFIG_IPQ9574_RUMI int cfg; /* Configure sdcc1_apps_clk_src */ @@ -345,15 +347,12 @@ void emmc_clock_init(void) writel(readl(GCC_SDCC1_APPS_CBCR) | CLK_ENABLE, GCC_SDCC1_APPS_CBCR); udelay(10); writel(readl(GCC_SDCC1_AHB_CBCR) | CLK_ENABLE, GCC_SDCC1_AHB_CBCR); -#endif } void emmc_clock_reset(void) { -#ifndef CONFIG_IPQ9574_RUMI writel(0x1, GCC_SDCC1_BCR); udelay(10); writel(0x0, GCC_SDCC1_BCR); -#endif } #endif diff --git a/board/qca/arm/ipq9574/ipq9574.c b/board/qca/arm/ipq9574/ipq9574.c index 8439af636e..4992f7b7b3 100644 --- a/board/qca/arm/ipq9574/ipq9574.c +++ b/board/qca/arm/ipq9574/ipq9574.c @@ -27,9 +27,11 @@ #include #include #include +#include #define DLOAD_MAGIC_COOKIE 0x10 #define DLOAD_DISABLED 0x40 +#define DLOAD_BITS 0xFF DECLARE_GLOBAL_DATA_PTR; @@ -39,6 +41,9 @@ extern int ipq_spi_init(u16); unsigned int qpic_frequency = 0, qpic_phase = 0; extern unsigned int qpic_training_offset; +extern unsigned ipq_runtime_fs_feature_enabled; + +extern int qca_scm_dpr(u32, u32, void *, size_t); void qca_serial_init(struct ipq_serial_platdata *plat) { @@ -58,6 +63,31 @@ void qca_serial_init(struct ipq_serial_platdata *plat) return; } +#ifdef CONFIG_IPQ_RUNTIME_FAILSAFE +void fdt_fixup_runtime_failsafe(void *blob) +{ + int node_off, ret; + const char *fs_node = {"/soc/qti,scm_restart_reason"}; + + /* This fixup is for informing HLOS whether + * runtime failsafe feature is enabled or not + */ + node_off = fdt_path_offset(blob, fs_node); + if (node_off < 0) { + printf("%s: Failsafe: unable to find node '%s'\n", + __func__, fs_node); + return; + } + + ret = fdt_setprop_u32(blob, node_off, "qti,runtime-failsafe", + ipq_runtime_fs_feature_enabled); + if (ret) { + printf("%s : Unable to set property 'ipq,runtime_failsafe'\n",__func__); + return; + } +} +#endif + void fdt_fixup_qpic(void *blob) { int node_off, ret; @@ -78,15 +108,6 @@ void fdt_fixup_qpic(void *blob) } } - -void qpic_emulation_set_clk(void) -{ - writel(QPIC_CBCR_VAL, GCC_QPIC_CBCR_ADDR); - writel(CLK_ENABLE, GCC_QPIC_AHB_CBCR_ADDR); - writel(CLK_ENABLE, GCC_QPIC_SLEEP_CBCR); - writel(CLK_ENABLE, GCC_QPIC_IO_MACRO_CBCR); -} - void board_nand_init(void) { #ifdef CONFIG_QPIC_SERIAL @@ -100,9 +121,6 @@ void board_nand_init(void) if (!fdtdec_get_is_enabled(gd->fdt_blob, node)) { printf("QPIC: disabled, skipping initialization\n"); } else { -#ifdef CONFIG_IPQ9574_RUMI - qpic_emulation_set_clk(); -#endif qpic_nand_init(NULL); } #endif @@ -849,8 +867,16 @@ void set_function_select_as_mdc_mdio(void) } } -void nssnoc_init(void) -{ +void nssnoc_init(void){ + unsigned int gcc_nssnoc_memnoc_bfdcd_cmd_rcgr_addr = 0x1817004; + unsigned int gcc_qdss_at_cmd_rcgr_addr = 0x182D004; + + writel(0x102, gcc_nssnoc_memnoc_bfdcd_cmd_rcgr_addr + 4); + writel(0x1, gcc_nssnoc_memnoc_bfdcd_cmd_rcgr_addr); + + writel(0x109, gcc_qdss_at_cmd_rcgr_addr + 4); + writel(0x1, gcc_qdss_at_cmd_rcgr_addr); + /* Enable required NSSNOC clocks */ writel(readl(GCC_MEM_NOC_NSSNOC_CLK) | GCC_CBCR_CLK_ENABLE, GCC_MEM_NOC_NSSNOC_CLK); @@ -1195,11 +1221,26 @@ unsigned long timer_read_counter(void) return 0; } +#ifdef CONFIG_HW_WATCHDOG +void hw_watchdog_reset(void) +{ + writel(1, APCS_WDT_RST); +} +#endif + void reset_crashdump(void) { unsigned int ret = 0; + unsigned int cookie = 0; + +#ifdef CONFIG_IPQ_RUNTIME_FAILSAFE + cookie = ipq_read_tcsr_boot_misc(); + fs_debug("\nFailsafe: %s: Clearing DLOAD and NonHLOS bits\n", __func__); + cookie &= ~(DLOAD_BITS); + cookie &= ~(IPQ_FS_NONHLOS_BIT); +#endif qca_scm_sdi(); - ret = qca_scm_dload(CLEAR_MAGIC); + ret = qca_scm_dload(cookie); if (ret) printf ("Error in reseting the Magic cookie\n"); return; @@ -1268,7 +1309,6 @@ struct dumpinfo_t dumpinfo_n[] = { { "DATARAM.BIN", 0x00290000, 0x00014000, 0 }, { "MSGRAM.BIN", 0x00060000, 0x00006000, 1 }, { "IMEM.BIN", 0x08600000, 0x00001000, 0 }, - { "NSSUTCM.BIN", 0x08600658, 0x00030000, 0, 1, 0x2000 }, { "UNAME.BIN", 0, 0, 0, 0, 0, MINIMAL_DUMP }, { "CPU_INFO.BIN", 0, 0, 0, 0, 0, MINIMAL_DUMP }, { "DMESG.BIN", 0, 0, 0, 0, 0, MINIMAL_DUMP }, @@ -1292,7 +1332,6 @@ struct dumpinfo_t dumpinfo_s[] = { { "DATARAM.BIN", 0x00290000, 0x00014000, 0 }, { "MSGRAM.BIN", 0x00060000, 0x00006000, 1 }, { "IMEM.BIN", 0x08600000, 0x00001000, 0 }, - { "NSSUTCM.BIN", 0x08600658, 0x00030000, 0, 1, 0x2000 }, { "UNAME.BIN", 0, 0, 0, 0, 0, MINIMAL_DUMP }, { "CPU_INFO.BIN", 0, 0, 0, 0, 0, MINIMAL_DUMP }, { "DMESG.BIN", 0, 0, 0, 0, 0, MINIMAL_DUMP }, @@ -1301,11 +1340,29 @@ struct dumpinfo_t dumpinfo_s[] = { }; int dump_entries_s = ARRAY_SIZE(dumpinfo_s); +#ifdef CONFIG_IPQ_RUNTIME_FAILSAFE +int ipq_read_tcsr_boot_misc(void) +{ + u32 *dmagic = (u32 *)CONFIG_IPQ9574_DMAGIC_ADDR; + return *dmagic; +} + +int is_hlos_crashed(void) +{ + u32 *dmagic = (u32 *)CONFIG_IPQ9574_DMAGIC_ADDR; + + if (*dmagic & IPQ_FS_HLOS_BIT) + return 1; + + return 0; +} +#endif + int apps_iscrashed_crashdump_disabled(void) { u32 *dmagic = (u32 *)CONFIG_IPQ9574_DMAGIC_ADDR; - if (*dmagic == DLOAD_DISABLED) + if (*dmagic & DLOAD_DISABLED) return 1; return 0; @@ -1315,7 +1372,7 @@ int apps_iscrashed(void) { u32 *dmagic = (u32 *)CONFIG_IPQ9574_DMAGIC_ADDR; - if (*dmagic == DLOAD_MAGIC_COOKIE) + if (*dmagic & DLOAD_MAGIC_COOKIE) return 1; return 0; @@ -1413,6 +1470,10 @@ unsigned int get_dts_machid(unsigned int machid) { case MACH_TYPE_IPQ9574_EMULATION: return MACH_TYPE_IPQ9574_EMULATION; + case MACH_TYPE_IPQ9574_AP_AL02_C5: + return MACH_TYPE_IPQ9574_AP_AL02_C4; + case MACH_TYPE_IPQ9574_AP_AL02_C6: + return MACH_TYPE_IPQ9574_AP_AL02_C1; default: return machid; } @@ -1428,6 +1489,12 @@ void ipq_uboot_fdt_fixup(void) case MACH_TYPE_IPQ9574_EMULATION: config = "config@emulation-fbc"; break; + case MACH_TYPE_IPQ9574_AP_AL02_C5: + config = "config@al02-c5"; + break; + case MACH_TYPE_IPQ9574_AP_AL02_C6: + config = "config@al02-c6"; + break; } if (config != NULL) @@ -1448,3 +1515,49 @@ void ipq_uboot_fdt_fixup(void) } return; } + +int do_dpr(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + int ret; + char *loadaddr; + uint32_t dpr_status = 0; + struct dpr { + uint32_t address; + uint32_t status; + } dpr; + + if (argc > 2) { + return CMD_RET_USAGE; + } + + if (argc == 2){ + dpr.address = simple_strtoul(argv[1], NULL, 16); + } else { + loadaddr = getenv("fileaddr"); + + if (loadaddr == NULL) { + printf("No Arguments provided\n"); + printf("Command format: dpr_execute
\n"); + return CMD_RET_USAGE; + } + if (loadaddr != NULL) + dpr.address = simple_strtoul(loadaddr, NULL, 16); + } + + dpr.status = (uint32_t)&dpr_status; + + ret = qca_scm_dpr(SCM_SVC_FUSE, TME_DPR_PROCESSING, + &dpr, sizeof(dpr)); + + if (ret || dpr_status){ + printf("%s: Error in DPR Processing (%d, %d)\n", + __func__, ret, dpr_status); + } else { + printf("DPR Process sucessful\n"); + } + return ret; +} + +U_BOOT_CMD(dpr_execute, 2, 0, do_dpr, + "Debug Policy Request processing\n", + "dpr_execute [address] - Processing dpr\n"); diff --git a/board/qca/arm/ipq9574/ipq9574.h b/board/qca/arm/ipq9574/ipq9574.h index 51a6a25399..9207237d8a 100644 --- a/board/qca/arm/ipq9574/ipq9574.h +++ b/board/qca/arm/ipq9574/ipq9574.h @@ -108,6 +108,7 @@ #define KERNEL_AUTH_CMD 0x1E #define SCM_CMD_SEC_AUTH 0x1F +#define TME_DPR_PROCESSING 0x21 #ifdef CONFIG_SMEM_VERSION_C #define RAM_PART_NAME_LENGTH 16 @@ -122,6 +123,8 @@ #define ARM_PSCI_TZ_FN_CPU_ON ARM_PSCI_TZ_FN(3) #define ARM_PSCI_TZ_FN_AFFINITY_INFO ARM_PSCI_TZ_FN(4) +#define APCS_WDT_RST 0xB017004 + /* * GCC-QPIC Registers */ @@ -370,9 +373,10 @@ typedef enum { SMEM_BOOT_DUALPARTINFO = 503, SMEM_PARTITION_TABLE_OFFSET = 504, SMEM_SPI_FLASH_ADDR_LEN = 505, + SMEM_RUNTIME_FAILSAFE_INFO = 507, SMEM_FIRST_VALID_TYPE = SMEM_SPINLOCK_ARRAY, - SMEM_LAST_VALID_TYPE = SMEM_SPI_FLASH_ADDR_LEN, - SMEM_MAX_SIZE = SMEM_SPI_FLASH_ADDR_LEN + 1, + SMEM_LAST_VALID_TYPE = SMEM_RUNTIME_FAILSAFE_INFO, + SMEM_MAX_SIZE = SMEM_RUNTIME_FAILSAFE_INFO + 1, } smem_mem_type_t; #define MSM_SDC1_BASE 0x7800000 diff --git a/common/autoboot.c b/common/autoboot.c index 96d2a841cc..8392f6f302 100644 --- a/common/autoboot.c +++ b/common/autoboot.c @@ -15,10 +15,12 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; extern int do_dumpqca_minimal_data(const char *offset); +extern unsigned ipq_runtime_fs_feature_enabled; #define MAX_DELAY_STOP_STR 32 @@ -225,6 +227,9 @@ static int abortboot_normal(int bootdelay) { int abort = 0; unsigned long ts; +#ifdef CONFIG_IPQ_RUNTIME_FAILSAFE + unsigned int cookie, ret; +#endif #ifdef CONFIG_MENUPROMPT printf(CONFIG_MENUPROMPT); @@ -255,6 +260,20 @@ static int abortboot_normal(int bootdelay) if (tstc()) { /* we got a key press */ abort = 1; /* don't auto boot */ bootdelay = 0; /* no more delay */ + +#ifdef CONFIG_IPQ_RUNTIME_FAILSAFE + if (ipq_runtime_fs_feature_enabled) { + cookie = ipq_read_tcsr_boot_misc(); + + cookie &= ~IPQ_FS_NONHLOS_BIT; + + fs_debug("\nFailsafe: %s: Clear NonHLOS bit\n", __func__); + ret = qca_scm_dload(cookie); + if (ret) + printf ("Error in SCM to clear NonHLOS failsafe bit\n"); + } +#endif + # ifdef CONFIG_MENUKEY menukey = getc(); # else diff --git a/common/board_f.c b/common/board_f.c index 26b1e644eb..d936107e8e 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -763,6 +763,13 @@ static int setup_reloc(void) return 0; } +#ifdef CONFIG_OF_BOARD_FIXUP +static int fix_fdt(void) +{ + return board_fix_fdt((void *)gd->fdt_blob); +} +#endif + /* ARM calls relocate_code from its crt0.S */ #if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) @@ -1026,6 +1033,9 @@ static init_fnc_t init_sequence_f[] = { display_new_sp, #ifdef CONFIG_SYS_EXTBDINFO setup_board_extra, +#endif +#ifdef CONFIG_OF_BOARD_FIXUP + fix_fdt, #endif INIT_FUNC_WATCHDOG_RESET reloc_fdt, diff --git a/common/board_r.c b/common/board_r.c index 44ac8ed6be..fe675704cc 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -64,6 +64,9 @@ #ifdef CONFIG_AVR32 #include #endif +#if defined(CONFIG_IPQ_RUNTIME_FAILSAFE) +#include +#endif DECLARE_GLOBAL_DATA_PTR; @@ -951,6 +954,9 @@ init_fnc_t init_sequence_r[] = { #endif #if defined(CONFIG_SPARC) prom_init, +#endif +#if defined(CONFIG_IPQ_RUNTIME_FAILSAFE) + smem_update_bootconfig_to_flash, #endif run_main_loop, }; diff --git a/common/cmd_flashwrite.c b/common/cmd_flashwrite.c index 50aeb3d81f..e591ad903c 100644 --- a/common/cmd_flashwrite.c +++ b/common/cmd_flashwrite.c @@ -33,7 +33,7 @@ extern struct sdhci_host mmc_host; #define SMEM_PTN_NAME_MAX 16 -static int write_to_flash(int flash_type, uint32_t address, uint32_t offset, +int write_to_flash(int flash_type, uint32_t address, uint32_t offset, uint32_t part_size, uint32_t file_size, char *layout) { diff --git a/configs/ipq40xx_defconfig b/configs/ipq40xx_defconfig index cc221fe197..2829dca389 100644 --- a/configs/ipq40xx_defconfig +++ b/configs/ipq40xx_defconfig @@ -124,6 +124,7 @@ CONFIG_SUPPORT_OF_CONTROL=y # Device Tree Control # CONFIG_OF_CONTROL=y +CONFIG_OF_BOARD_FIXUP=y CONFIG_OF_SEPARATE=y # CONFIG_OF_EMBED is not set CONFIG_NET=y diff --git a/configs/ipq40xx_standard_defconfig b/configs/ipq40xx_standard_defconfig index 6fde706b96..1381ec6fb1 100644 --- a/configs/ipq40xx_standard_defconfig +++ b/configs/ipq40xx_standard_defconfig @@ -124,6 +124,7 @@ CONFIG_SUPPORT_OF_CONTROL=y # Device Tree Control # CONFIG_OF_CONTROL=y +CONFIG_OF_BOARD_FIXUP=y CONFIG_OF_SEPARATE=y # CONFIG_OF_EMBED is not set CONFIG_NET=y diff --git a/configs/ipq5018_defconfig b/configs/ipq5018_defconfig index b10406f814..19fbabdbe4 100644 --- a/configs/ipq5018_defconfig +++ b/configs/ipq5018_defconfig @@ -134,6 +134,7 @@ CONFIG_SUPPORT_OF_CONTROL=y # Device Tree Control # CONFIG_OF_CONTROL=y +CONFIG_OF_BOARD_FIXUP=y CONFIG_OF_SEPARATE=y # CONFIG_OF_EMBED is not set CONFIG_NET=y diff --git a/configs/ipq5018_tiny_defconfig b/configs/ipq5018_tiny_defconfig index 40cf113167..67602d62d7 100644 --- a/configs/ipq5018_tiny_defconfig +++ b/configs/ipq5018_tiny_defconfig @@ -128,6 +128,7 @@ CONFIG_SUPPORT_OF_CONTROL=y # Device Tree Control # CONFIG_OF_CONTROL=y +CONFIG_OF_BOARD_FIXUP=y CONFIG_OF_SEPARATE=y # CONFIG_OF_EMBED is not set CONFIG_NET=y diff --git a/configs/ipq6018_defconfig b/configs/ipq6018_defconfig index 8b83a56810..02c7fc9750 100644 --- a/configs/ipq6018_defconfig +++ b/configs/ipq6018_defconfig @@ -133,6 +133,7 @@ CONFIG_SUPPORT_OF_CONTROL=y # Device Tree Control # CONFIG_OF_CONTROL=y +CONFIG_OF_BOARD_FIXUP=y CONFIG_OF_SEPARATE=y # CONFIG_OF_EMBED is not set CONFIG_NET=y diff --git a/configs/ipq6018_tiny_defconfig b/configs/ipq6018_tiny_defconfig index 30758e29be..f6db3e70d8 100644 --- a/configs/ipq6018_tiny_defconfig +++ b/configs/ipq6018_tiny_defconfig @@ -133,6 +133,7 @@ CONFIG_SUPPORT_OF_CONTROL=y # Device Tree Control # CONFIG_OF_CONTROL=y +CONFIG_OF_BOARD_FIXUP=y CONFIG_OF_SEPARATE=y # CONFIG_OF_EMBED is not set CONFIG_NET=y diff --git a/configs/ipq806x_defconfig b/configs/ipq806x_defconfig index 57da183e52..c25a034bb4 100644 --- a/configs/ipq806x_defconfig +++ b/configs/ipq806x_defconfig @@ -125,6 +125,7 @@ CONFIG_SUPPORT_OF_CONTROL=y # Device Tree Control # CONFIG_OF_CONTROL=y +CONFIG_OF_BOARD_FIXUP=y CONFIG_OF_SEPARATE=y # CONFIG_OF_EMBED is not set CONFIG_NET=y diff --git a/configs/ipq806x_standard_defconfig b/configs/ipq806x_standard_defconfig index b921d1c8a8..5dc4b57fc3 100644 --- a/configs/ipq806x_standard_defconfig +++ b/configs/ipq806x_standard_defconfig @@ -125,6 +125,7 @@ CONFIG_SUPPORT_OF_CONTROL=y # Device Tree Control # CONFIG_OF_CONTROL=y +CONFIG_OF_BOARD_FIXUP=y CONFIG_OF_SEPARATE=y # CONFIG_OF_EMBED is not set CONFIG_NET=y diff --git a/configs/ipq807x_defconfig b/configs/ipq807x_defconfig index 6fa49f5fef..fe3be64a6c 100644 --- a/configs/ipq807x_defconfig +++ b/configs/ipq807x_defconfig @@ -135,6 +135,7 @@ CONFIG_SUPPORT_OF_CONTROL=y # Device Tree Control # CONFIG_OF_CONTROL=y +CONFIG_OF_BOARD_FIXUP=y CONFIG_OF_SEPARATE=y # CONFIG_OF_EMBED is not set CONFIG_NET=y diff --git a/configs/ipq807x_tiny_defconfig b/configs/ipq807x_tiny_defconfig index b79e5da8b2..50665a730a 100644 --- a/configs/ipq807x_tiny_defconfig +++ b/configs/ipq807x_tiny_defconfig @@ -135,6 +135,7 @@ CONFIG_SUPPORT_OF_CONTROL=y # Device Tree Control # CONFIG_OF_CONTROL=y +CONFIG_OF_BOARD_FIXUP=y CONFIG_OF_SEPARATE=y # CONFIG_OF_EMBED is not set CONFIG_NET=y diff --git a/configs/ipq9574_defconfig b/configs/ipq9574_defconfig index 0ab5991785..57be3284fd 100644 --- a/configs/ipq9574_defconfig +++ b/configs/ipq9574_defconfig @@ -134,6 +134,7 @@ CONFIG_SUPPORT_OF_CONTROL=y # Device Tree Control # CONFIG_OF_CONTROL=y +CONFIG_OF_BOARD_FIXUP=y CONFIG_OF_SEPARATE=y # CONFIG_OF_EMBED is not set CONFIG_NET=y diff --git a/doc/driver-model/fdt-fixup.txt b/doc/driver-model/fdt-fixup.txt new file mode 100644 index 0000000000..70344bd2c3 --- /dev/null +++ b/doc/driver-model/fdt-fixup.txt @@ -0,0 +1,132 @@ +Pre-relocation device tree manipulation +======================================= + +Contents: + +1. Purpose +2. Implementation +3. Example +4. Work to be done + +1. Purpose +---------- + +In certain markets, it is beneficial for manufacturers of embedded devices to +offer certain ranges of products, where the functionality of the devices within +one series either don't differ greatly from another, or can be thought of as +"extensions" of each other, where one device only differs from another in the +addition of a small number of features (e.g. an additional output connector). + +To realize this in hardware, one method is to have a motherboard, and several +possible daughter boards that can be attached to this mother board. Different +daughter boards then either offer the slightly different functionality, or the +addition of the daughter board to the device realizes the "extension" of +functionality to the device described previously. + +For the software, we obviously want to reuse components for all these +variations of the device. This means that the software somehow needs to cope +with the situation that certain ICs may or may not be present on any given +system, depending on which daughter boards are connected to the motherboard. + +In the Linux kernel, one possible solution to this problem is to employ the +device tree overlay mechanism: There exists one "base" device tree, which +features only the components guaranteed to exist in all varieties of the +device. At the start of the kernel, the presence and type of the daughter +boards is then detected, and the corresponding device tree overlays are applied +to support the components on the daughter boards. + +Note that the components present on every variety of the board must, of course, +provide a way to find out if and which daughter boards are installed for this +mechanism to work. + +In the U-Boot boot loader, support for device tree overlays has recently been +integrated, and is used on some boards to alter the device tree that is later +passed to Linux. But since U-Boot's driver model, which is device tree-based as +well, is being used in more and more drivers, the same problem of altering the +device tree starts cropping up in U-Boot itself as well. + +An additional problem with the device tree in U-Boot is that it is read-only, +and the current mechanisms don't allow easy manipulation of the device tree +after the driver model has been initialized. While migrating to a live device +tree (at least after the relocation) would greatly simplify the solution of +this problem, it is a non-negligible task to implement it, an a interim +solution is needed to address the problem at least in the medium-term. + +Hence, we propose a solution to this problem by offering a board-specific +call-back function, which is passed a writeable pointer to the device tree. +This function is called before the device tree is relocated, and specifically +before the main U-Boot's driver model is instantiated, hence the main U-Boot +"sees" all modifications to the device tree made in this function. Furthermore, +we have the pre-relocation driver model at our disposal at this stage, which +means that we can query the hardware for the existence and variety of the +components easily. + +2. Implementation +----------------- + +To take advantage of the pre-relocation device tree manipulation mechanism, +boards have to implement the function board_fix_fdt, which has the following +signature: + +int board_fix_fdt (void *rw_fdt_blob) + +The passed-in void pointer is a writeable pointer to the device tree, which can +be used to manipulate the device tree using e.g. functions from +include/fdt_support.h. The return value should either be 0 in case of +successful execution of the device tree manipulation or something else for a +failure. Note that returning a non-null value from the function will +unrecoverably halt the boot process, as with any function from init_sequence_f +(in common/board_f.c). + +Furthermore, the Kconfig option OF_BOARD_FIXUP has to be set for the function +to be called: + +Device Tree Control +-> [*] Board-specific manipulation of Device Tree + ++----------------------------------------------------------+ +| WARNING: The actual manipulation of the device tree has | +| to be the _last_ set of operations in board_fix_fdt! | +| Since the pre-relocation driver model does not adapt to | +| changes made to the device tree either, its references | +| into the device tree will be invalid after manipulating | +| it, and unpredictable behavior might occur when | +| functions that rely on them are executed! | ++----------------------------------------------------------+ + +Hence, the recommended layout of the board_fixup_fdt call-back function is the +following: + +int board_fix_fdt(void *rw_fdt_blob) +{ + /* Collect information about device's hardware and store them in e.g. + local variables */ + + /* Do device tree manipulation using the values previously collected */ + + /* Return 0 on successful manipulation and non-zero otherwise */ +} + +If this convention is kept, both an "additive" approach, meaning that nodes for +detected components are added to the device tree, as well as a "subtractive" +approach, meaning that nodes for absent components are removed from the tree, +as well as a combination of both approaches should work. + +3. Example +---------- + +The controlcenterdc board (board/gdsys/a38x/controlcenterdc.c) features a +board_fix_fdt function, in which six GPIO expanders (which might be present or +not, since they are on daughter boards) on a I2C bus are queried for, and +subsequently deactivated in the device tree if they are not present. + +Note that the dm_i2c_simple_probe function does not use the device tree, hence +it is safe to call it after the tree has already been manipulated. + +4. Work to be done +------------------ + +* The application of device tree overlay should be possible in board_fixup_fdt, + but has not been tested at this stage. + +2017-01-06, Mario Six diff --git a/drivers/mtd/nand/qpic_nand.c b/drivers/mtd/nand/qpic_nand.c index 0697e58ac4..fc36f45c35 100644 --- a/drivers/mtd/nand/qpic_nand.c +++ b/drivers/mtd/nand/qpic_nand.c @@ -221,6 +221,22 @@ static struct qpic_serial_nand_params qpic_serial_nand_tbl[] = { .check_quad_config = true, .name = "W25N02JWZEIF", }, + { + .id = { 0xef, 0xba }, + .page_size = 2048, + .erase_blk_size = 0x00020000, + .pgs_per_blk = 64, + .no_of_blocks = 1024, + .spare_size = 64, + .density = 0x8000000, + .otp_region = 0x2000, + .no_of_addr_cycle = 0x3, + .num_bits_ecc_correctability = 4, + .timing_mode_support = 0, + .quad_mode = true, + .check_quad_config = false, + .name = "W25N01GWZEIG", + }, { .id = { 0xc2, 0x92 }, .page_size = 2048, @@ -285,6 +301,22 @@ static struct qpic_serial_nand_params qpic_serial_nand_tbl[] = { .check_quad_config = true, .name = "GD5F2GQ5REYIG", }, + { + .id = { 0xc2, 0xa6 }, + .page_size = 2048, + .erase_blk_size = 0x00020000, + .pgs_per_blk = 64, + .no_of_blocks = 2048, + .spare_size = 160, + .density = 0x08000000, + .otp_region = 0x2000, + .no_of_addr_cycle = 0x3, + .num_bits_ecc_correctability = 4, + .timing_mode_support = 0, + .quad_mode = true, + .check_quad_config = true, + .name = "MX35UF2GE4AD", + }, { .id = { 0xc2, 0xb7 }, .page_size = 4096, @@ -305,7 +337,7 @@ static struct qpic_serial_nand_params qpic_serial_nand_tbl[] = { }; struct qpic_serial_nand_params *serial_params; #define MICRON_DEVICE_ID 0x152c152c -#define WINBOND_DEVICE_ID 0x0021bcef +#define WINBOND_MFR_ID 0xef #define CMD3_MASK 0xfff0ffff /* * An array holding the fixed pattern to compare with @@ -1389,6 +1421,7 @@ int qpic_spi_nand_config(struct mtd_info *mtd) if ((status >> 8) & FLASH_SPI_NAND_FR_ECC_ENABLE) { qspi_debug("%s : Internal ECC enabled, disabling internal ECC\n",__func__); + status >>= 8; status &= ~(FLASH_SPI_NAND_FR_ECC_ENABLE); status = qpic_serial_set_feature(mtd, FLASH_SPI_NAND_FR_ADDR, status); @@ -1415,6 +1448,30 @@ int qpic_spi_nand_config(struct mtd_info *mtd) } else qspi_debug("%s : Internal ECC disabled on power on.\n",__func__); + if (dev->vendor == WINBOND_MFR_ID) { + status = qpic_serial_get_feature(mtd, FLASH_SPI_NAND_FR_ADDR); + if (status < 0) { + printf("%s : Error in getting feature.\n",__func__); + return status; + } + + if (!((status >> 8) & FLASH_SPI_NAND_FR_BUFF_ENABLE)) { + qspi_debug("%s :continous buffer mode disabled\n", + __func__); + qspi_debug("%s : Issuing set feature command to enable it\n", + __func__); + status = qpic_serial_set_feature(mtd, FLASH_SPI_NAND_FR_ADDR, + (FLASH_SPI_NAND_FR_BUFF_ENABLE | (status >> 8))); + if (status < 0) { + printf("%s : Error in disabling continous buffer bit.\n", + __func__); + return status; + } + } else { + qspi_debug("%s : continous buffer mode enabled on power on\n", + __func__); + } + } /* Enable QUAD mode if device supported. Check this condition only * if dev->quad_mode = true , means device will support Quad mode * else no need to check for Quad mode. @@ -1466,31 +1523,6 @@ int qpic_spi_nand_config(struct mtd_info *mtd) } } - if (dev->id == WINBOND_DEVICE_ID) { - status = qpic_serial_get_feature(mtd, FLASH_SPI_NAND_FR_ADDR); - if (status < 0) { - printf("%s : Error in getting feature.\n",__func__); - return status; - } - - if (!((status >> 8) & FLASH_SPI_NAND_FR_BUFF_ENABLE)) { - qspi_debug("%s :continous buffer mode disabled\n", - __func__); - qspi_debug("%s : Issuing set feature command to enable it\n", - __func__); - status = qpic_serial_set_feature(mtd, FLASH_SPI_NAND_FR_ADDR, - (FLASH_SPI_NAND_FR_BUFF_ENABLE | (status >> 8))); - if (status < 0) { - printf("%s : Error in disabling continous buffer bit.\n", - __func__); - return status; - } - } else { - qspi_debug("%s : continous buffer mode enabled on power on\n", - __func__); - } - } - return 0; } #endif diff --git a/drivers/net/ipq807x/ipq807x_ppe.c b/drivers/net/ipq807x/ipq807x_ppe.c index 1d2bc57a0c..751b4db986 100644 --- a/drivers/net/ipq807x/ipq807x_ppe.c +++ b/drivers/net/ipq807x/ipq807x_ppe.c @@ -1118,7 +1118,7 @@ static void ppe_port_mux_set(int port_id, int port_type, int mode) port_mux_ctrl.bf.port4_pcs_sel = PORT4_PCS_SEL_GMII_FROM_PCS0; if (port_id == PORT5) { if (port_type == PORT_GMAC_TYPE) { - if (mode == PORT_WRAPPER_SGMII_PLUS) + if (mode == PORT_WRAPPER_SGMII_PLUS || mode == PORT_WRAPPER_SGMII0_RGMII4) port_mux_ctrl.bf.port5_pcs_sel = PORT5_PCS_SEL_GMII_FROM_PCS1; else port_mux_ctrl.bf.port5_pcs_sel = PORT5_PCS_SEL_GMII_FROM_PCS0; diff --git a/drivers/net/ipq9574/ipq9574_edma.c b/drivers/net/ipq9574/ipq9574_edma.c index b66d80024b..9bac612be2 100644 --- a/drivers/net/ipq9574/ipq9574_edma.c +++ b/drivers/net/ipq9574/ipq9574_edma.c @@ -113,7 +113,6 @@ int ipq9574_edma_alloc_rx_buffer(struct ipq9574_edma_hw *ehw, cons = reg_data & IPQ9574_EDMA_RXFILL_CONS_IDX_MASK; while (1) { - counter = next; if (++counter == rxfill_ring->count) @@ -141,8 +140,8 @@ int ipq9574_edma_alloc_rx_buffer(struct ipq9574_edma_hw *ehw, * Save buffer size in RXFILL descriptor */ rxfill_desc->rdes1 |= (IPQ9574_EDMA_RX_BUFF_SIZE << - IPQ9574_EDMA_RXFILL_BUF_SIZE_SHIFT) & - IPQ9574_EDMA_RXFILL_BUF_SIZE_MASK; + IPQ9574_EDMA_RXFILL_BUF_SIZE_SHIFT) & + IPQ9574_EDMA_RXFILL_BUF_SIZE_MASK; num_alloc++; next = counter; } @@ -160,6 +159,8 @@ int ipq9574_edma_alloc_rx_buffer(struct ipq9574_edma_hw *ehw, ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RXFILL_PROD_IDX( rxfill_ring->id), reg_data); + rxfill_ring->prod_idx = reg_data; + pr_debug("%s: num_alloc = %d\n", __func__, num_alloc); } @@ -272,13 +273,13 @@ uint32_t ipq9574_edma_clean_rx(struct ipq9574_edma_common_info *c_info, /* * Check src_info from Rx Descriptor */ - if (IPQ9574_EDMA_RXPH_SRC_INFO_TYPE_GET(rxdesc_desc->rdes4) == - IPQ9574_EDMA_PREHDR_DSTINFO_PORTID_IND) { - src_port_num = rxdesc_desc->rdes4 & - IPQ9574_EDMA_PREHDR_PORTNUM_BITS; + src_port_num = IPQ9574_EDMA_RXDESC_SRC_INFO_GET(rxdesc_desc->rdes4); + if ((src_port_num & IPQ9574_EDMA_RXDESC_SRCINFO_TYPE_MASK) == + IPQ9574_EDMA_RXDESC_SRCINFO_TYPE_PORTID) { + src_port_num &= IPQ9574_EDMA_RXDESC_PORTNUM_BITS; } else { pr_warn("WARN: src_info_type:0x%x. Drop skb:%p\n", - IPQ9574_EDMA_RXPH_SRC_INFO_TYPE_GET(rxdesc_desc->rdes4), + (src_port_num & IPQ9574_EDMA_RXDESC_SRCINFO_TYPE_MASK), skb); goto next_rx_desc; } @@ -348,7 +349,7 @@ static int ipq9574_edma_rx_complete(struct ipq9574_edma_common_info *c_info) } /* - * Set RXDESC ring interrupt mask + * Enable RX EDMA interrupt masks */ for (i = 0; i < ehw->rxdesc_rings; i++) { rxdesc_ring = &ehw->rxdesc_ring[i]; @@ -358,7 +359,7 @@ static int ipq9574_edma_rx_complete(struct ipq9574_edma_common_info *c_info) } /* - * Set TXCMPL ring interrupt mask + * Enable TX EDMA interrupt masks */ for (i = 0; i < ehw->txcmpl_rings; i++) { txcmpl_ring = &ehw->txcmpl_ring[i]; @@ -367,16 +368,6 @@ static int ipq9574_edma_rx_complete(struct ipq9574_edma_common_info *c_info) ehw->txcmpl_intr_mask); } - /* - * Set RXFILL ring interrupt mask - */ - for (i = 0; i < ehw->rxfill_rings; i++) { - rxfill_ring = &ehw->rxfill_ring[i]; - ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RXFILL_INT_MASK( - rxfill_ring->id), - ehw->rxfill_intr_mask); - } - /* * Read Misc intr status */ @@ -450,8 +441,20 @@ static int ipq9574_eth_snd(struct eth_device *dev, void *packet, int length) */ txdesc = IPQ9574_EDMA_TXDESC_DESC(txdesc_ring, hw_next_to_use); + txdesc->tdes1 = 0; + txdesc->tdes2 = 0; + txdesc->tdes3 = 0; + txdesc->tdes4 = 0; + txdesc->tdes5 = 0; + txdesc->tdes6 = 0; + txdesc->tdes7 = 0; skb = (uchar *)txdesc->tdes0; + /* + * Set SC BYPASS + */ + txdesc->tdes1 |= IPQ9574_EDMA_TXDESC_SERVICE_CODE_SET(IPQ9574_EDMA_SC_BYPASS); + pr_debug("%s: txdesc->tdes0 (buffer addr) = 0x%x length = %d \ prod_idx = %d cons_idx = %d\n", __func__, txdesc->tdes0, length, @@ -464,9 +467,15 @@ static int ipq9574_eth_snd(struct eth_device *dev, void *packet, int length) #else /* * Populate Tx dst info, port id is macid in dp_dev + * We have separate netdev for each port in Kernel but that is not the + * case in U-Boot. + * This part needs to be fixed to support multiple ports in non bridged + * mode during when all the ports are currently under same netdev. + * + * Currently mac port no. is fixed as 3 for the purpose of testing */ - txdesc->tdes4 |= (((IPQ9574_EDMA_PREHDR_DSTINFO_PORTID_IND << 8) | - (IPQ9574_EDMA_MAC_PORT_NO & 0x0fff)) << 16); + txdesc->tdes4 |= (IPQ9574_EDMA_DST_PORT_TYPE_SET(IPQ9574_EDMA_DST_PORT_TYPE) | + IPQ9574_EDMA_DST_PORT_ID_SET(IPQ9574_EDMA_MAC_PORT_NO)); #endif /* @@ -600,11 +609,9 @@ static int ipq9574_edma_setup_ring_resources(struct ipq9574_edma_hw *ehw) { struct ipq9574_edma_txcmpl_ring *txcmpl_ring; struct ipq9574_edma_txdesc_ring *txdesc_ring; - struct ipq9574_edma_sec_txdesc_ring *sec_txdesc_ring; struct ipq9574_edma_rxfill_ring *rxfill_ring; struct ipq9574_edma_rxdesc_ring *rxdesc_ring; - struct ipq9574_edma_sec_rxdesc_ring *sec_rxdesc_ring; - struct ipq9574_edma_txdesc_desc *tx_desc; + struct ipq9574_edma_txdesc_desc *txdesc_desc; struct ipq9574_edma_rxfill_desc *rxfill_desc; int i, j, index; void *tx_buf; @@ -640,6 +647,9 @@ static int ipq9574_edma_setup_ring_resources(struct ipq9574_edma_hw *ehw) return -ENOMEM; } + /* + * Allocate buffers for each of the desc + */ for (j = 0; j < rxfill_ring->count; j++) { rxfill_desc = IPQ9574_EDMA_RXFILL_DESC(rxfill_ring, j); rxfill_desc->rdes0 = virt_to_phys(rx_buf); @@ -652,26 +662,6 @@ static int ipq9574_edma_setup_ring_resources(struct ipq9574_edma_hw *ehw) } } - /* - * Allocate secondary RxDesc ring descriptors - */ - for (i = 0; i < ehw->sec_rxdesc_rings; i++) { - sec_rxdesc_ring = &ehw->sec_rxdesc_ring[i]; - sec_rxdesc_ring->count = EDMA_RING_SIZE; - sec_rxdesc_ring->id = ehw->sec_rxdesc_ring_start + i; - sec_rxdesc_ring->desc = (void *)noncached_alloc( - IPQ9574_EDMA_RX_SEC_DESC_SIZE * sec_rxdesc_ring->count, - CONFIG_SYS_CACHELINE_SIZE); - if (sec_rxdesc_ring->desc == NULL) { - pr_info("%s: sec_rxdesc_ring->desc alloc error\n", __func__); - return -ENOMEM; - } - sec_rxdesc_ring->dma = virt_to_phys(sec_rxdesc_ring->desc); - pr_debug("sec rxdesc ring id = %d, sec rxdesc ring ptr = %p, sec rxdesc ring dma = %u\n", - sec_rxdesc_ring->id, sec_rxdesc_ring->desc, (unsigned int) - sec_rxdesc_ring->dma); - } - /* * Allocate RxDesc ring descriptors */ @@ -685,7 +675,6 @@ static int ipq9574_edma_setup_ring_resources(struct ipq9574_edma_hw *ehw) * Number of fill rings are lesser than the descriptor rings * Share the fill rings across descriptor rings. */ - index = ehw->rxfill_ring_start + (i % ehw->rxfill_rings); rxdesc_ring->rxfill = &ehw->rxfill_ring[index - ehw->rxfill_ring_start]; @@ -694,7 +683,6 @@ static int ipq9574_edma_setup_ring_resources(struct ipq9574_edma_hw *ehw) rxdesc_ring->desc = (void *)noncached_alloc( IPQ9574_EDMA_RXDESC_DESC_SIZE * rxdesc_ring->count, CONFIG_SYS_CACHELINE_SIZE); - if (rxdesc_ring->desc == NULL) { pr_info("%s: rxdesc_ring->desc alloc error\n", __func__); return -ENOMEM; @@ -703,47 +691,21 @@ static int ipq9574_edma_setup_ring_resources(struct ipq9574_edma_hw *ehw) pr_debug("rxdesc ring id = %d, rxdesc ring ptr = %p, rxdesc ring dma = %u\n", rxdesc_ring->id, rxdesc_ring->desc, (unsigned int) rxdesc_ring->dma); - } - /* - * Allocate TxCmpl ring descriptors - */ - for (i = 0; i < ehw->txcmpl_rings; i++) { - txcmpl_ring = &ehw->txcmpl_ring[i]; - txcmpl_ring->count = EDMA_RING_SIZE; - txcmpl_ring->id = ehw->txcmpl_ring_start + i; - txcmpl_ring->desc = (void *)noncached_alloc( - IPQ9574_EDMA_TXCMPL_DESC_SIZE * txcmpl_ring->count, + /* + * Allocate secondary Rx ring descriptors + */ + rxdesc_ring->sdesc = (void *)noncached_alloc( + IPQ9574_EDMA_RX_SEC_DESC_SIZE * rxdesc_ring->count, CONFIG_SYS_CACHELINE_SIZE); - - if (txcmpl_ring->desc == NULL) { - pr_info("%s: txcmpl_ring->desc alloc error\n", __func__); + if (rxdesc_ring->sdesc == NULL) { + pr_info("%s: rxdesc_ring->sdesc alloc error\n", __func__); return -ENOMEM; } - txcmpl_ring->dma = virt_to_phys(txcmpl_ring->desc); - pr_debug("txcmpl ring id = %d, txcmpl ring ptr = %p, txcmpl ring dma = %u\n", - txcmpl_ring->id, txcmpl_ring->desc, (unsigned int) - txcmpl_ring->dma); - } - - /* - * Allocate secondary TxDesc ring descriptors - */ - for (i = 0; i < ehw->sec_txdesc_rings; i++) { - sec_txdesc_ring = &ehw->sec_txdesc_ring[i]; - sec_txdesc_ring->count = EDMA_RING_SIZE; - sec_txdesc_ring->id = ehw->sec_txdesc_ring_start + i; - sec_txdesc_ring->desc = (void *)noncached_alloc( - IPQ9574_EDMA_TX_SEC_DESC_SIZE * sec_txdesc_ring->count, - CONFIG_SYS_CACHELINE_SIZE); - if (sec_txdesc_ring->desc == NULL) { - pr_info("%s: sec_txdesc_ring->desc alloc error\n", __func__); - return -ENOMEM; - } - sec_txdesc_ring->dma = virt_to_phys(sec_txdesc_ring->desc); - pr_debug("sec txdesc ring id = %d, sec txdesc ring ptr = %p, sec txdesc ring dma = %u\n", - sec_txdesc_ring->id, sec_txdesc_ring->desc, (unsigned int) - sec_txdesc_ring->dma); + rxdesc_ring->sdma = virt_to_phys(rxdesc_ring->sdesc); + pr_debug("sec rxdesc ring id = %d, sec rxdesc ring ptr = %p, sec rxdesc ring dma = %u\n", + rxdesc_ring->id, rxdesc_ring->sdesc, (unsigned int) + rxdesc_ring->sdma); } /* @@ -774,21 +736,60 @@ static int ipq9574_edma_setup_ring_resources(struct ipq9574_edma_hw *ehw) return -ENOMEM; } + /* + * Allocate buffers for each of the desc + */ for (j = 0; j < txdesc_ring->count; j++) { - tx_desc = IPQ9574_EDMA_TXDESC_DESC(txdesc_ring, j); - tx_desc->tdes0 = virt_to_phys(tx_buf); - tx_desc->tdes1 = 0; - tx_desc->tdes2 = 0; - tx_desc->tdes3 = 0; - tx_desc->tdes4 = 0; - tx_desc->tdes5 = 0; - tx_desc->tdes6 = 0; - tx_desc->tdes7 = 0; + txdesc_desc = IPQ9574_EDMA_TXDESC_DESC(txdesc_ring, j); + txdesc_desc->tdes0 = virt_to_phys(tx_buf); + txdesc_desc->tdes1 = 0; + txdesc_desc->tdes2 = 0; + txdesc_desc->tdes3 = 0; + txdesc_desc->tdes4 = 0; + txdesc_desc->tdes5 = 0; + txdesc_desc->tdes6 = 0; + txdesc_desc->tdes7 = 0; tx_buf += IPQ9574_EDMA_TX_BUFF_SIZE; pr_debug("Ring %d: txdesc ring dis0 ptr = %p, txdesc ring dis0 dma = %u\n", - j, tx_desc, (unsigned int)tx_desc->tdes0); + j, txdesc_desc, (unsigned int)txdesc_desc->tdes0); } + + /* + * Allocate secondary Tx ring descriptors + */ + txdesc_ring->sdesc = (void *)noncached_alloc( + IPQ9574_EDMA_TX_SEC_DESC_SIZE * txdesc_ring->count, + CONFIG_SYS_CACHELINE_SIZE); + if (txdesc_ring->sdesc == NULL) { + pr_info("%s: txdesc_ring->sdesc alloc error\n", __func__); + return -ENOMEM; + } + txdesc_ring->sdma = virt_to_phys(txdesc_ring->sdesc); + pr_debug("txdesc sec desc ring id = %d, txdesc ring ptr = %p, txdesc ring dma = %u\n", + txdesc_ring->id, txdesc_ring->sdesc, (unsigned int) + txdesc_ring->sdma); + } + + /* + * Allocate TxCmpl ring descriptors + */ + for (i = 0; i < ehw->txcmpl_rings; i++) { + txcmpl_ring = &ehw->txcmpl_ring[i]; + txcmpl_ring->count = EDMA_RING_SIZE; + txcmpl_ring->id = ehw->txcmpl_ring_start + i; + txcmpl_ring->desc = (void *)noncached_alloc( + IPQ9574_EDMA_TXCMPL_DESC_SIZE * txcmpl_ring->count, + CONFIG_SYS_CACHELINE_SIZE); + + if (txcmpl_ring->desc == NULL) { + pr_info("%s: txcmpl_ring->desc alloc error\n", __func__); + return -ENOMEM; + } + txcmpl_ring->dma = virt_to_phys(txcmpl_ring->desc); + pr_debug("txcmpl ring id = %d, txcmpl ring ptr = %p, txcmpl ring dma = %u\n", + txcmpl_ring->id, txcmpl_ring->desc, (unsigned int) + txcmpl_ring->dma); } pr_info("%s: successfull\n", __func__); @@ -807,13 +808,18 @@ static void ipq9574_edma_free_desc(struct ipq9574_edma_common_info *c_info) struct ipq9574_edma_txdesc_ring *txdesc_ring; struct ipq9574_edma_rxfill_ring *rxfill_ring; struct ipq9574_edma_rxdesc_ring *rxdesc_ring; - struct ipq9574_edma_txdesc_desc *tx_desc; + struct ipq9574_edma_txdesc_desc *txdesc_desc; + struct ipq9574_edma_rxfill_desc *rxfill_desc; int i; for (i = 0; i < ehw->rxfill_rings; i++) { rxfill_ring = &ehw->rxfill_ring[i]; - if (rxfill_ring->desc) + if (rxfill_ring->desc) { + rxfill_desc = IPQ9574_EDMA_RXFILL_DESC(rxfill_ring, 0); + if (rxfill_desc->rdes0) + ipq9574_free_mem((void *)rxfill_desc->rdes0); ipq9574_free_mem(rxfill_ring->desc); + } } for (i = 0; i < ehw->rxdesc_rings; i++) { @@ -832,9 +838,9 @@ static void ipq9574_edma_free_desc(struct ipq9574_edma_common_info *c_info) for (i = 0; i < ehw->txdesc_rings; i++) { txdesc_ring = &ehw->txdesc_ring[i]; if (txdesc_ring->desc) { - tx_desc = IPQ9574_EDMA_TXDESC_DESC(txdesc_ring, 0); - if (tx_desc->tdes0) - ipq9574_free_mem((void *)tx_desc->tdes0); + txdesc_desc = IPQ9574_EDMA_TXDESC_DESC(txdesc_ring, 0); + if (txdesc_desc->tdes0) + ipq9574_free_mem((void *)txdesc_desc->tdes0); ipq9574_free_mem(txdesc_ring->desc); } } @@ -898,15 +904,15 @@ static void ipq9574_edma_disable_intr(struct ipq9574_edma_hw *ehw) /* * Disable interrupts */ - for (i = 0; i < IPQ9574_EDMA_MAX_TXCMPL_RINGS; i++) - ipq9574_edma_reg_write(IPQ9574_EDMA_REG_TX_INT_MASK(i), 0); - - for (i = 0; i < IPQ9574_EDMA_MAX_RXFILL_RINGS; i++) - ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RXFILL_INT_MASK(i), 0); - for (i = 0; i < IPQ9574_EDMA_MAX_RXDESC_RINGS; i++) ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RX_INT_CTRL(i), 0); + for (i = 0; i < IPQ9574_EDMA_MAX_TXCMPL_RINGS; i++) + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_TX_INT_MASK(i), 0); + + /* + * Clear MISC interrupt mask + */ ipq9574_edma_reg_write(IPQ9574_EDMA_REG_MISC_INT_MASK, IPQ9574_EDMA_MASK_INT_DISABLE); } @@ -1305,6 +1311,37 @@ static int ipq9574_edma_wr_macaddr(struct eth_device *dev) static void ipq9574_eth_halt(struct eth_device *dev) { + pr_debug("\n\n*****GMAC0 info*****\n"); + pr_debug("GMAC0 RXPAUSE(0x3a001044):%x\n", readl(0x3a001044)); + pr_debug("GMAC0 TXPAUSE(0x3a0010A4):%x\n", readl(0x3a0010A4)); + pr_debug("GMAC0 RXGOODBYTE_L(0x3a001084):%x\n", readl(0x3a001084)); + pr_debug("GMAC0 RXGOODBYTE_H(0x3a001088):%x\n", readl(0x3a001088)); + pr_debug("GMAC0 RXBADBYTE_L(0x3a00108c):%x\n", readl(0x3a00108c)); + pr_debug("GMAC0 RXBADBYTE_H(0x3a001090):%x\n", readl(0x3a001090)); + + pr_debug("\n\n*****GMAC1 info*****\n"); + pr_debug("GMAC1 RXPAUSE(0x3a001244):%x\n", readl(0x3a001244)); + pr_debug("GMAC1 TXPAUSE(0x3a0012A4):%x\n", readl(0x3a0012A4)); + pr_debug("GMAC1 RXGOODBYTE_L(0x3a001284):%x\n", readl(0x3a001284)); + pr_debug("GMAC1 RXGOODBYTE_H(0x3a001288):%x\n", readl(0x3a001288)); + pr_debug("GMAC1 RXBADBYTE_L(0x3a00128c):%x\n", readl(0x3a00128c)); + pr_debug("GMAC1 RXBADBYTE_H(0x3a001290):%x\n", readl(0x3a001290)); + + pr_debug("\n\n*****GMAC2 info*****\n"); + pr_debug("GMAC2 RXPAUSE(0x3a001444):%x\n", readl(0x3a001444)); + pr_debug("GMAC2 TXPAUSE(0x3a0014A4):%x\n", readl(0x3a0014A4)); + pr_debug("GMAC2 RXGOODBYTE_L(0x3a001484):%x\n", readl(0x3a001484)); + pr_debug("GMAC2 RXGOODBYTE_H(0x3a001488):%x\n", readl(0x3a001488)); + pr_debug("GMAC2 RXBADBYTE_L(0x3a00148c):%x\n", readl(0x3a00148c)); + pr_debug("GMAC2 RXBADBYTE_H(0x3a001490):%x\n", readl(0x3a001490)); + + pr_debug("\n\n*****GMAC3 info*****\n"); + pr_debug("GMAC3 RXPAUSE(0x3a001644):%x\n", readl(0x3a001644)); + pr_debug("GMAC3 TXPAUSE(0x3a0016A4):%x\n", readl(0x3a0016A4)); + pr_debug("GMAC3 RXGOODBYTE_L(0x3a001684):%x\n", readl(0x3a001684)); + pr_debug("GMAC3 RXGOODBYTE_H(0x3a001688):%x\n", readl(0x3a001688)); + pr_debug("GMAC3 RXBADBYTE_L(0x3a00168c):%x\n", readl(0x3a00168c)); + pr_debug("GMAC3 RXBADBYTE_H(0x3a001690):%x\n", readl(0x3a001690)); pr_info("%s: done\n", __func__); } @@ -1314,10 +1351,6 @@ static void ipq9574_edma_set_ring_values(struct ipq9574_edma_hw *edma_hw) edma_hw->txdesc_rings = IPQ9574_EDMA_TX_DESC_RING_NOS; edma_hw->txdesc_ring_end = IPQ9574_EDMA_TX_DESC_RING_SIZE; - edma_hw->sec_txdesc_ring_start = IPQ9574_EDMA_SEC_TX_DESC_RING_START; - edma_hw->sec_txdesc_rings = IPQ9574_EDMA_SEC_TX_DESC_RING_NOS; - edma_hw->sec_txdesc_ring_end = IPQ9574_EDMA_SEC_TX_DESC_RING_SIZE; - edma_hw->txcmpl_ring_start = IPQ9574_EDMA_TX_CMPL_RING_START; edma_hw->txcmpl_rings = IPQ9574_EDMA_RX_FILL_RING_NOS; edma_hw->txcmpl_ring_end = IPQ9574_EDMA_TX_CMPL_RING_SIZE; @@ -1330,10 +1363,6 @@ static void ipq9574_edma_set_ring_values(struct ipq9574_edma_hw *edma_hw) edma_hw->rxdesc_rings = IPQ9574_EDMA_RX_DESC_RING_NOS; edma_hw->rxdesc_ring_end = IPQ9574_EDMA_RX_DESC_RING_SIZE; - edma_hw->sec_rxdesc_ring_start = IPQ9574_EDMA_SEC_RX_DESC_RING_START; - edma_hw->sec_rxdesc_rings = IPQ9574_EDMA_SEC_RX_DESC_RING_NOS; - edma_hw->sec_rxdesc_ring_end = IPQ9574_EDMA_SEC_RX_DESC_RING_SIZE; - pr_info("Num rings - TxDesc:%u (%u-%u) TxCmpl:%u (%u-%u)\n", edma_hw->txdesc_rings, edma_hw->txdesc_ring_start, (edma_hw->txdesc_ring_start + edma_hw->txdesc_rings - 1), @@ -1371,15 +1400,6 @@ static int ipq9574_edma_alloc_rings(struct ipq9574_edma_hw *ehw) return -ENOMEM; } - ehw->sec_rxdesc_ring = (void *)noncached_alloc((sizeof( - struct ipq9574_edma_sec_rxdesc_ring) * - ehw->sec_rxdesc_rings), - CONFIG_SYS_CACHELINE_SIZE); - if (!ehw->sec_rxdesc_ring) { - pr_info("%s: sec_rxdesc_ring alloc error\n", __func__); - return -ENOMEM; - } - ehw->txdesc_ring = (void *)noncached_alloc((sizeof( struct ipq9574_edma_txdesc_ring) * ehw->txdesc_rings), @@ -1389,15 +1409,6 @@ static int ipq9574_edma_alloc_rings(struct ipq9574_edma_hw *ehw) return -ENOMEM; } - ehw->sec_txdesc_ring = (void *)noncached_alloc((sizeof( - struct ipq9574_edma_sec_txdesc_ring) * - ehw->sec_txdesc_rings), - CONFIG_SYS_CACHELINE_SIZE); - if (!ehw->sec_txdesc_ring) { - pr_info("%s: txdesc_ring alloc error\n", __func__); - return -ENOMEM; - } - ehw->txcmpl_ring = (void *)noncached_alloc((sizeof( struct ipq9574_edma_txcmpl_ring) * ehw->txcmpl_rings), @@ -1444,17 +1455,6 @@ static int ipq9574_edma_init_rings(struct ipq9574_edma_hw *ehw) return 0; } -/* - * ipq9574_edma_configure_sec_txdesc_ring() - * Configure one secondary TxDesc ring - */ -static void ipq9574_edma_configure_sec_txdesc_ring(struct ipq9574_edma_hw *ehw, - struct ipq9574_edma_sec_txdesc_ring *sec_txdesc_ring) -{ - ipq9574_edma_reg_write(IPQ9574_EDMA_REG_TXDESC_BA2(sec_txdesc_ring->id), - (uint32_t)(sec_txdesc_ring->dma & 0xffffffff)); -} - /* * ipq9574_edma_configure_txdesc_ring() * Configure one TxDesc ring @@ -1462,9 +1462,6 @@ static void ipq9574_edma_configure_sec_txdesc_ring(struct ipq9574_edma_hw *ehw, static void ipq9574_edma_configure_txdesc_ring(struct ipq9574_edma_hw *ehw, struct ipq9574_edma_txdesc_ring *txdesc_ring) { - uint32_t data; - uint16_t hw_cons_idx; - /* * Configure TXDESC ring */ @@ -1472,24 +1469,17 @@ static void ipq9574_edma_configure_txdesc_ring(struct ipq9574_edma_hw *ehw, (uint32_t)(txdesc_ring->dma & IPQ9574_EDMA_RING_DMA_MASK)); + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_TXDESC_BA2(txdesc_ring->id), + (uint32_t)(txdesc_ring->sdma & + IPQ9574_EDMA_RING_DMA_MASK)); + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_TXDESC_RING_SIZE( txdesc_ring->id), (uint32_t)(txdesc_ring->count & IPQ9574_EDMA_TXDESC_RING_SIZE_MASK)); - data = ipq9574_edma_reg_read(IPQ9574_EDMA_REG_TXDESC_CONS_IDX( - txdesc_ring->id)); - - data &= ~(IPQ9574_EDMA_TXDESC_CONS_IDX_MASK); - hw_cons_idx = data; - - data = ipq9574_edma_reg_read(IPQ9574_EDMA_REG_TXDESC_PROD_IDX( - txdesc_ring->id)); - - data &= ~(IPQ9574_EDMA_TXDESC_PROD_IDX_MASK); - data |= hw_cons_idx & IPQ9574_EDMA_TXDESC_PROD_IDX_MASK; - ipq9574_edma_reg_write(IPQ9574_EDMA_REG_TXDESC_PROD_IDX( - txdesc_ring->id), data); + txdesc_ring->id), + IPQ9574_EDMA_TX_INITIAL_PROD_IDX); } /* @@ -1499,6 +1489,8 @@ static void ipq9574_edma_configure_txdesc_ring(struct ipq9574_edma_hw *ehw, static void ipq9574_edma_configure_txcmpl_ring(struct ipq9574_edma_hw *ehw, struct ipq9574_edma_txcmpl_ring *txcmpl_ring) { + uint32_t tx_mod_timer; + /* * Configure TxCmpl ring base address */ @@ -1516,20 +1508,20 @@ static void ipq9574_edma_configure_txcmpl_ring(struct ipq9574_edma_hw *ehw, ipq9574_edma_reg_write(IPQ9574_EDMA_REG_TXCMPL_CTRL(txcmpl_ring->id), IPQ9574_EDMA_TXCMPL_RETMODE_OPAQUE); + /* + * Configure the default timer mitigation value + */ + tx_mod_timer = (IPQ9574_EDMA_REG_TX_MOD_TIMER(txcmpl_ring->id) & + IPQ9574_EDMA_TX_MOD_TIMER_INIT_MASK) + << IPQ9574_EDMA_TX_MOD_TIMER_INIT_SHIFT; + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_TX_MOD_TIMER(txcmpl_ring->id), + tx_mod_timer); + + /* + * Enable ring. Set ret mode to 'opaque'. + */ ipq9574_edma_reg_write(IPQ9574_EDMA_REG_TX_INT_CTRL(txcmpl_ring->id), - 0x2); -} - - -/* - * ipq9574_edma_configure_sec_rxdesc_ring() - * Configure one secondary RxDesc ring - */ -static void ipq9574_edma_configure_sec_rxdesc_ring(struct ipq9574_edma_hw *ehw, - struct ipq9574_edma_sec_rxdesc_ring *sec_rxdesc_ring) -{ - ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RXDESC_BA2(sec_rxdesc_ring->id), - (uint32_t)(sec_rxdesc_ring->dma & 0xffffffff)); + IPQ9574_EDMA_TX_NE_INT_EN); } /* @@ -1542,7 +1534,10 @@ static void ipq9574_edma_configure_rxdesc_ring(struct ipq9574_edma_hw *ehw, uint32_t data; ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RXDESC_BA(rxdesc_ring->id), - (uint32_t)(rxdesc_ring->dma & 0xffffffff)); + (uint32_t)(rxdesc_ring->dma & IPQ9574_EDMA_RING_DMA_MASK)); + + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RXDESC_BA2(rxdesc_ring->id), + (uint32_t)(rxdesc_ring->sdma & IPQ9574_EDMA_RING_DMA_MASK)); data = rxdesc_ring->count & IPQ9574_EDMA_RXDESC_RING_SIZE_MASK; data |= (ehw->rx_payload_offset & IPQ9574_EDMA_RXDESC_PL_OFFSET_MASK) << @@ -1551,11 +1546,20 @@ static void ipq9574_edma_configure_rxdesc_ring(struct ipq9574_edma_hw *ehw, ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RXDESC_RING_SIZE( rxdesc_ring->id), data); + /* + * Configure the default timer mitigation value + */ + data = (IPQ9574_EDMA_REG_RX_MOD_TIMER(rxdesc_ring->id) & + IPQ9574_EDMA_RX_MOD_TIMER_INIT_MASK) + << IPQ9574_EDMA_RX_MOD_TIMER_INIT_SHIFT; + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RX_MOD_TIMER(rxdesc_ring->id), + data); + /* * Enable ring. Set ret mode to 'opaque'. */ ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RX_INT_CTRL(rxdesc_ring->id), - 0x2); + IPQ9574_EDMA_RX_NE_INT_EN); } /* @@ -1590,12 +1594,6 @@ static void ipq9574_edma_configure_rings(struct ipq9574_edma_hw *ehw) for (i = 0; i < ehw->txdesc_rings; i++) ipq9574_edma_configure_txdesc_ring(ehw, &ehw->txdesc_ring[i]); - /* - * Configure secondary TXDESC ring - */ - for (i = 0; i < ehw->sec_txdesc_rings; i++) - ipq9574_edma_configure_sec_txdesc_ring(ehw, &ehw->sec_txdesc_ring[i]); - /* * Configure TXCMPL ring */ @@ -1614,12 +1612,6 @@ static void ipq9574_edma_configure_rings(struct ipq9574_edma_hw *ehw) for (i = 0; i < ehw->rxdesc_rings; i++) ipq9574_edma_configure_rxdesc_ring(ehw, &ehw->rxdesc_ring[i]); - /* - * Configure secondary RXDESC ring - */ - for (i = 0; i < ehw->rxdesc_rings; i++) - ipq9574_edma_configure_sec_rxdesc_ring(ehw, &ehw->sec_rxdesc_ring[i]); - pr_info("%s: successfull\n", __func__); } @@ -1642,7 +1634,7 @@ void ipq9574_edma_hw_reset(void) int ipq9574_edma_hw_init(struct ipq9574_edma_hw *ehw) { int ret, desc_index; - uint32_t i, reg; + uint32_t i, reg, ring_id; volatile uint32_t data; struct ipq9574_edma_rxdesc_ring *rxdesc_ring = NULL; @@ -1657,8 +1649,7 @@ int ipq9574_edma_hw_init(struct ipq9574_edma_hw *ehw) */ ehw->rxfill_intr_mask = IPQ9574_EDMA_RXFILL_INT_MASK; ehw->rxdesc_intr_mask = IPQ9574_EDMA_RXDESC_INT_MASK_PKT_INT; - ehw->txcmpl_intr_mask = IPQ9574_EDMA_TX_INT_MASK_PKT_INT | - IPQ9574_EDMA_TX_INT_MASK_UGT_INT; + ehw->txcmpl_intr_mask = IPQ9574_EDMA_TX_INT_MASK_PKT_INT; ehw->misc_intr_mask = 0xff; ehw->rx_payload_offset = 0x0; @@ -1753,17 +1744,19 @@ int ipq9574_edma_hw_init(struct ipq9574_edma_hw *ehw) /* * Set PPE QID to EDMA Rx ring mapping. - * When coming up use only queue 0. - * HOST EDMA rings. - * Each entry can hold mapping for 8 PPE queues and entry size is + * Each entry can hold mapping for 4 PPE queues and entry size is * 4 bytes */ - desc_index = ehw->rxdesc_ring_start; + desc_index = (ehw->rxdesc_ring_start & 0x1F); + reg = IPQ9574_EDMA_QID2RID_TABLE_MEM(0); - data = 0; - data |= (desc_index & 0xF); + data = ((desc_index << 0) & 0xFF) | + (((desc_index + 1) << 8) & 0xff00) | + (((desc_index + 2) << 16) & 0xff0000) | + (((desc_index + 3) << 24) & 0xff000000); + ipq9574_edma_reg_write(reg, data); - pr_debug("Configure QID2RID reg:0x%x to 0x%x\n", reg, data); + pr_debug("Configure QID2RID(0) reg:0x%x to 0x%x\n", reg, data); /* * Set RXDESC2FILL_MAP_xx reg. @@ -1775,31 +1768,27 @@ int ipq9574_edma_hw_init(struct ipq9574_edma_hw *ehw) ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RXDESC2FILL_MAP_1, 0); ipq9574_edma_reg_write(IPQ9574_EDMA_REG_RXDESC2FILL_MAP_2, 0); - for (i = ehw->rxdesc_ring_start; - i < ehw->rxdesc_ring_end; i++) { - if ((i >= 0) && (i <= 9)) + for (i = 0; i < ehw->rxdesc_rings; i++) { + rxdesc_ring = &ehw->rxdesc_ring[i]; + + ring_id = rxdesc_ring->id; + if ((ring_id >= 0) && (ring_id <= 9)) reg = IPQ9574_EDMA_REG_RXDESC2FILL_MAP_0; - else if ((i >= 10) && (i <= 19)) + else if ((ring_id >= 10) && (ring_id <= 19)) reg = IPQ9574_EDMA_REG_RXDESC2FILL_MAP_1; else reg = IPQ9574_EDMA_REG_RXDESC2FILL_MAP_2; - rxdesc_ring = &ehw->rxdesc_ring[i - ehw->rxdesc_ring_start]; pr_debug("Configure RXDESC:%u to use RXFILL:%u\n", - rxdesc_ring->id, rxdesc_ring->rxfill->id); + ring_id, rxdesc_ring->rxfill->id); /* * Set the Rx fill descriptor ring number in the mapping * register. - * E.g. If (rxfill ring)rxdesc_ring->rxfill->id = 7, (rxdesc ring)i = 13. - * reg = IPQ9574_EDMA_REG_RXDESC2FILL_MAP_1 - * data |= (rxdesc_ring->rxfill->id & 0x7) << ((i % 10) * 3); - * data |= (0x7 << 9); - This sets 111 at 9th bit of - * register IPQ9574_EDMA_REG_RXDESC2FILL_MAP_1 */ data = ipq9574_edma_reg_read(reg); - data |= (rxdesc_ring->rxfill->id & 0x7) << ((i % 10) * 3); + data |= (rxdesc_ring->rxfill->id & 0x7) << ((ring_id % 10) * 3); ipq9574_edma_reg_write(reg, data); } @@ -1810,6 +1799,23 @@ int ipq9574_edma_hw_init(struct ipq9574_edma_hw *ehw) pr_debug("EDMA_REG_RXDESC2FILL_MAP_2: 0x%x\n", ipq9574_edma_reg_read(IPQ9574_EDMA_REG_RXDESC2FILL_MAP_2)); + /* + * Configure DMA request priority, DMA read burst length, + * and AXI write size. + */ + data = IPQ9574_EDMA_DMAR_BURST_LEN_SET(IPQ9574_EDMA_BURST_LEN_ENABLE) + | IPQ9574_EDMA_DMAR_REQ_PRI_SET(0) + | IPQ9574_EDMA_DMAR_TXDATA_OUTSTANDING_NUM_SET(31) + | IPQ9574_EDMA_DMAR_TXDESC_OUTSTANDING_NUM_SET(7) + | IPQ9574_EDMA_DMAR_RXFILL_OUTSTANDING_NUM_SET(7); + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_DMAR_CTRL, data); + + /* + * Enable MISC interrupt mask + */ + ipq9574_edma_reg_write(IPQ9574_EDMA_REG_MISC_INT_MASK, + ehw->misc_intr_mask); + /* * Enable EDMA */ @@ -1840,12 +1846,6 @@ int ipq9574_edma_hw_init(struct ipq9574_edma_hw *ehw) ipq9574_edma_reg_write(IPQ9574_EDMA_REG_TXDESC_CTRL(i), data); } - /* - * Enable MISC interrupt - */ - ipq9574_edma_reg_write(IPQ9574_EDMA_REG_MISC_INT_MASK, - ehw->misc_intr_mask); - pr_info("%s: successfull\n", __func__); return 0; } diff --git a/drivers/net/ipq9574/ipq9574_edma.h b/drivers/net/ipq9574/ipq9574_edma.h index e750d7a8cd..b153415f60 100644 --- a/drivers/net/ipq9574/ipq9574_edma.h +++ b/drivers/net/ipq9574/ipq9574_edma.h @@ -38,21 +38,20 @@ #define IPQ9574_EDMA_START_GMACS IPQ9574_NSS_DP_START_PHY_PORT #define IPQ9574_EDMA_MAX_GMACS IPQ9574_NSS_DP_MAX_PHY_PORTS -#define IPQ9574_EDMA_TX_BUFF_SIZE 1572 +#define IPQ9574_EDMA_TX_BUFF_SIZE 2048 #define IPQ9574_EDMA_RX_BUFF_SIZE 2048 /* Max number of rings of each type is defined with below macro */ #define IPQ9574_EDMA_MAX_TXCMPL_RINGS 32 /* Max TxCmpl rings */ +#define IPQ9574_EDMA_MAX_TXDESC_RINGS 32 /* Max TxDesc rings */ #define IPQ9574_EDMA_MAX_RXDESC_RINGS 24 /* Max RxDesc rings */ #define IPQ9574_EDMA_MAX_RXFILL_RINGS 8 /* Max RxFill rings */ -#define IPQ9574_EDMA_MAX_TXDESC_RINGS 32 /* Max TxDesc rings */ #define IPQ9574_EDMA_GET_DESC(R, i, type) (&(((type *)((R)->desc))[i])) #define IPQ9574_EDMA_RXFILL_DESC(R, i) IPQ9574_EDMA_GET_DESC(R, i, struct ipq9574_edma_rxfill_desc) #define IPQ9574_EDMA_RXDESC_DESC(R, i) IPQ9574_EDMA_GET_DESC(R, i, struct ipq9574_edma_rxdesc_desc) #define IPQ9574_EDMA_TXDESC_DESC(R, i) IPQ9574_EDMA_GET_DESC(R, i, struct ipq9574_edma_txdesc_desc) #define IPQ9574_EDMA_TXCMPL_DESC(R, i) IPQ9574_EDMA_GET_DESC(R, i, struct ipq9574_edma_txcmpl_desc) -#define IPQ9574_EDMA_RXPH_SRC_INFO_TYPE_GET(rxph) (((rxph & 0xffff) >> 8) & 0xf0) #define IPQ9574_EDMA_DEV 1 #define IPQ9574_EDMA_TX_QUEUE 1 @@ -65,26 +64,16 @@ #define IPQ9574_EDMA_TX_DESC_RING_SIZE \ (IPQ9574_EDMA_TX_DESC_RING_START + IPQ9574_EDMA_TX_DESC_RING_NOS) -#define IPQ9574_EDMA_SEC_TX_DESC_RING_START 31 -#define IPQ9574_EDMA_SEC_TX_DESC_RING_NOS 1 -#define IPQ9574_EDMA_SEC_TX_DESC_RING_SIZE \ -(IPQ9574_EDMA_SEC_TX_DESC_RING_START + IPQ9574_EDMA_SEC_TX_DESC_RING_NOS) - #define IPQ9574_EDMA_TX_CMPL_RING_START 31 #define IPQ9574_EDMA_TX_CMPL_RING_NOS 1 #define IPQ9574_EDMA_TX_CMPL_RING_SIZE \ (IPQ9574_EDMA_TX_CMPL_RING_START + IPQ9574_EDMA_TX_CMPL_RING_NOS) -#define IPQ9574_EDMA_RX_DESC_RING_START 15 +#define IPQ9574_EDMA_RX_DESC_RING_START 23 #define IPQ9574_EDMA_RX_DESC_RING_NOS 1 #define IPQ9574_EDMA_RX_DESC_RING_SIZE \ (IPQ9574_EDMA_RX_DESC_RING_START + IPQ9574_EDMA_RX_DESC_RING_NOS) -#define IPQ9574_EDMA_SEC_RX_DESC_RING_START 15 -#define IPQ9574_EDMA_SEC_RX_DESC_RING_NOS 1 -#define IPQ9574_EDMA_SEC_RX_DESC_RING_SIZE \ -(IPQ9574_EDMA_SEC_RX_DESC_RING_START + IPQ9574_EDMA_SEC_RX_DESC_RING_NOS) - #define IPQ9574_EDMA_RX_FILL_RING_START 7 #define IPQ9574_EDMA_RX_FILL_RING_NOS 1 #define IPQ9574_EDMA_RX_FILL_RING_SIZE \ @@ -96,129 +85,89 @@ * RxDesc descriptor */ struct ipq9574_edma_rxdesc_desc { - uint32_t rdes0; - /* buffer_address_lo */ - uint32_t rdes1; - /* valid toggle, more, int_pri, drop_prec, reserved x 3, - * tunnel_type, tunnel_term_ind, cpu_code_valid, known_ind, - * wifi_qos_flag, wifi_qos, buffer_address_hi */ - uint32_t rdes2; - /* opaque_lo */ - uint32_t rdes3; - /* opaque_hi */ - uint32_t rdes4; - /* dst_info, src_info */ - uint32_t rdes5; - /* dspcp, pool_id, data_lengh */ - uint32_t rdes6; - /* hash_value, hash_flag, l3_csum_status, l4_csum_status, - * data_offset */ - uint32_t rdes7; - /* l4_offset, l3_offset, pid, CVLAN flag, SVLAN flag, PPPOE flag - * service_code */ -}; - -/* - * RxFill descriptor - */ -struct ipq9574_edma_rxfill_desc { - uint32_t rdes0; - /* buffer_address_lo */ - uint32_t rdes1; - /* buffer_size, reserved x 1, buffer_address_hi */ - uint32_t rdes2; - /* opaque_lo */ - uint32_t rdes3; - /* opaque_hu */ -}; - -/* - * TxDesc descriptor - */ -struct ipq9574_edma_txdesc_desc { - uint32_t tdes0; - /* buffer_address_lo */ - uint32_t tdes1; - /* reserved x 1, more, int_pri, drop_prec, reserved x 4, - * buff_recycling, fake_mac_header,ptp_tag_flag, pri_valid, - * buffer_address_high_bits_tbi, buffer_address_hi */ - uint32_t tdes2; - /* opaque_lo */ - uint32_t tdes3; - /* opaque_hi */ - uint32_t tdes4; - /* dst_info, src_info */ - uint32_t tdes5; - /* adv_offload_en, vlan_offload_en, frm_fmt_indication_en, - * edit_offload_en, csum_mode, ip_csum_en, tso_en, pool_id, - * data_lengh */ - uint32_t tdes6; - /* mss/hash_value/pip_tag, hash_flag, reserved x 2, - * data_offset */ - uint32_t tdes7; - /* l4_offset, l3_offset, reserved, prot_type, l2_type, - * CVLAN flag, SVLAN flag, PPPOE flag, service_code */ -}; - -/* - * TxCmpl descriptor - */ -struct ipq9574_edma_txcmpl_desc { - uint32_t tdes0; - /* buffer_address_lo */ - uint32_t tdes1; - /* buffer_size, reserved x 1, buffer_address_hi */ - uint32_t tdes2; - /* opaque_lo */ - uint32_t tdes3; - /* opaque_hu */ + uint32_t rdes0; /* Contains buffer address */ + uint32_t rdes1; /* Contains more bit, priority bit, service code */ + uint32_t rdes2; /* Contains opaque */ + uint32_t rdes3; /* Contains opaque high bits */ + uint32_t rdes4; /* Contains destination and source information */ + uint32_t rdes5; /* Contains WiFi QoS, data length */ + uint32_t rdes6; /* Contains hash value, check sum status */ + uint32_t rdes7; /* Contains DSCP, packet offsets */ }; /* * EDMA Rx Secondary Descriptor */ struct ipq9574_edma_rx_sec_desc { - uint32_t rx_sec0; - uint32_t rx_sec1; - uint32_t rx_sec2; - uint32_t rx_sec3; - uint32_t rx_sec4; - uint32_t rx_sec5; - uint32_t rx_sec6; - uint32_t rx_sec7; + uint32_t rx_sec0; /* Contains timestamp */ + uint32_t rx_sec1; /* Contains secondary checksum status */ + uint32_t rx_sec2; /* Contains QoS tag */ + uint32_t rx_sec3; /* Contains flow index details */ + uint32_t rx_sec4; /* Contains secondary packet offsets */ + uint32_t rx_sec5; /* Contains multicast bit, checksum */ + uint32_t rx_sec6; /* Contains SVLAN, CVLAN */ + uint32_t rx_sec7; /* Contains secondary SVLAN, CVLAN */ +}; + +/* + * RxFill descriptor + */ +struct ipq9574_edma_rxfill_desc { + uint32_t rdes0; /* Contains buffer address */ + uint32_t rdes1; /* Contains buffer size */ + uint32_t rdes2; /* Contains opaque */ + uint32_t rdes3; /* Contains opaque high bits */ +}; + +/* + * TxDesc descriptor + */ +struct ipq9574_edma_txdesc_desc { + uint32_t tdes0; /* Low 32-bit of buffer address */ + uint32_t tdes1; /* Buffer recycling, PTP tag flag, PRI valid flag */ + uint32_t tdes2; /* Low 32-bit of opaque value */ + uint32_t tdes3; /* High 32-bit of opaque value */ + uint32_t tdes4; /* Source/Destination port info */ + uint32_t tdes5; /* VLAN offload, csum_mode, ip_csum_en, tso_en, data length */ + uint32_t tdes6; /* MSS/hash_value/PTP tag, data offset */ + uint32_t tdes7; /* L4/L3 offset, PROT type, L2 type, CVLAN/SVLAN tag, service code */ }; /* * EDMA Tx Secondary Descriptor */ struct ipq9574_edma_tx_sec_desc { - uint32_t tx_sec0; - uint32_t tx_sec1; - uint32_t rx_sec2; - uint32_t rx_sec3; - uint32_t rx_sec4; - uint32_t rx_sec5; - uint32_t rx_sec6; - uint32_t rx_sec7; + uint32_t tx_sec0; /* Reserved */ + uint32_t tx_sec1; /* Custom csum offset, payload offset, TTL/NAT action */ + uint32_t rx_sec2; /* NAPT translated port, DSCP value, TTL value */ + uint32_t rx_sec3; /* Flow index value and valid flag */ + uint32_t rx_sec4; /* Reserved */ + uint32_t rx_sec5; /* Reserved */ + uint32_t rx_sec6; /* CVLAN/SVLAN command */ + uint32_t rx_sec7; /* CVLAN/SVLAN tag value */ }; /* - * secondary Tx descriptor ring + * TxCmpl descriptor */ -struct ipq9574_edma_sec_txdesc_ring { - uint32_t id; /* TXDESC ring number */ - void *desc; /* descriptor ring virtual address */ - dma_addr_t dma; /* descriptor ring physical address */ - uint16_t count; /* number of descriptors */ +struct ipq9574_edma_txcmpl_desc { + uint32_t tdes0; /* Low 32-bit opaque value */ + uint32_t tdes1; /* High 32-bit opaque value */ + uint32_t tdes2; /* More fragment, transmit ring id, pool id */ + uint32_t tdes3; /* Error indications */ }; /* * Tx descriptor ring */ struct ipq9574_edma_txdesc_ring { + uint32_t prod_idx; /* Producer index */ + uint32_t avail_desc; /* Number of available descriptor to process */ uint32_t id; /* TXDESC ring number */ - void *desc; /* descriptor ring virtual address */ + struct ipq9574_edma_txdesc_desc *desc; /* descriptor ring virtual address */ dma_addr_t dma; /* descriptor ring physical address */ + struct ipq9574_edma_tx_sec_desc *sdesc; /* Secondary descriptor ring virtual addr */ + dma_addr_t sdma; /* Secondary descriptor ring physical address */ uint16_t count; /* number of descriptors */ }; @@ -226,10 +175,12 @@ struct ipq9574_edma_txdesc_ring { * TxCmpl ring */ struct ipq9574_edma_txcmpl_ring { + uint32_t cons_idx; /* Consumer index */ + uint32_t avail_pkt; /* Number of available packets to process */ + struct ipq9574_edma_txcmpl_desc *desc; /* descriptor ring virtual address */ uint32_t id; /* TXCMPL ring number */ - void *desc; /* descriptor ring virtual address */ dma_addr_t dma; /* descriptor ring physical address */ - uint16_t count; /* number of descriptors in the ring */ + uint32_t count; /* Number of descriptors in the ring */ }; /* @@ -237,19 +188,10 @@ struct ipq9574_edma_txcmpl_ring { */ struct ipq9574_edma_rxfill_ring { uint32_t id; /* RXFILL ring number */ - void *desc; /* descriptor ring virtual address */ + uint32_t count; /* number of descriptors in the ring */ + uint32_t prod_idx; /* Ring producer index */ + struct ipq9574_edma_rxfill_desc *desc; /* descriptor ring virtual address */ dma_addr_t dma; /* descriptor ring physical address */ - uint16_t count; /* number of descriptors in the ring */ -}; - -/* - * secondary RxDesc ring - */ -struct ipq9574_edma_sec_rxdesc_ring { - uint32_t id; /* RXDESC ring number */ - void *desc; /* descriptor ring virtual address */ - dma_addr_t dma; /* descriptor ring physical address */ - uint16_t count; /* number of descriptors in the ring */ }; /* @@ -257,10 +199,13 @@ struct ipq9574_edma_sec_rxdesc_ring { */ struct ipq9574_edma_rxdesc_ring { uint32_t id; /* RXDESC ring number */ + uint32_t count; /* number of descriptors in the ring */ + uint32_t cons_idx; /* Ring consumer index */ + struct ipq9574_edma_rxdesc_desc *desc; /* Primary descriptor ring virtual addr */ + struct ipq9574_edma_sec_rxdesc_ring *sdesc; /* Secondary desc ring VA */ struct ipq9574_edma_rxfill_ring *rxfill; /* RXFILL ring used */ - void *desc; /* descriptor ring virtual address */ - dma_addr_t dma; /* descriptor ring physical address */ - uint16_t count; /* number of descriptors in the ring */ + dma_addr_t dma; /* Primary descriptor ring physical address */ + dma_addr_t sdma; /* Secondary descriptor ring physical address */ }; enum ipq9574_edma_tx { @@ -292,17 +237,12 @@ struct ipq9574_edma_hw { uint32_t flags; /* internal flags */ int active; /* status */ struct ipq9574_edma_txdesc_ring *txdesc_ring; /* Tx Descriptor Ring, SW is producer */ - struct ipq9574_edma_sec_txdesc_ring *sec_txdesc_ring; /* secondary Tx Descriptor Ring, SW is producer */ struct ipq9574_edma_txcmpl_ring *txcmpl_ring; /* Tx Completion Ring, SW is consumer */ struct ipq9574_edma_rxdesc_ring *rxdesc_ring; /* Rx Descriptor Ring, SW is consumer */ - struct ipq9574_edma_sec_rxdesc_ring *sec_rxdesc_ring; /* secondary Rx Descriptor Ring, SW is consumer */ struct ipq9574_edma_rxfill_ring *rxfill_ring; /* Rx Fill Ring, SW is producer */ uint32_t txdesc_rings; /* Number of TxDesc rings */ uint32_t txdesc_ring_start; /* Id of first TXDESC ring */ uint32_t txdesc_ring_end; /* Id of the last TXDESC ring */ - uint32_t sec_txdesc_rings; /* Number of secondary TxDesc rings */ - uint32_t sec_txdesc_ring_start; /* Id of first secondary TxDesc ring */ - uint32_t sec_txdesc_ring_end; /* Id of last secondary TxDesc ring */ uint32_t txcmpl_rings; /* Number of TxCmpl rings */ uint32_t txcmpl_ring_start; /* Id of first TXCMPL ring */ uint32_t txcmpl_ring_end; /* Id of last TXCMPL ring */ @@ -312,9 +252,6 @@ struct ipq9574_edma_hw { uint32_t rxdesc_rings; /* Number of RxDesc rings */ uint32_t rxdesc_ring_start; /* Id of first RxDesc ring */ uint32_t rxdesc_ring_end; /* Id of last RxDesc ring */ - uint32_t sec_rxdesc_rings; /* Number of secondary RxDesc rings */ - uint32_t sec_rxdesc_ring_start; /* Id of first secondary RxDesc ring */ - uint32_t sec_rxdesc_ring_end; /* Id of last secondary RxDesc ring */ uint32_t tx_intr_mask; /* tx interrupt mask */ uint32_t rx_intr_mask; /* rx interrupt mask */ uint32_t rxfill_intr_mask; /* Rx fill ring interrupt mask */ diff --git a/drivers/net/ipq9574/ipq9574_ppe.c b/drivers/net/ipq9574/ipq9574_ppe.c index 30d3eddaf6..5b7be0e14c 100644 --- a/drivers/net/ipq9574/ipq9574_ppe.c +++ b/drivers/net/ipq9574/ipq9574_ppe.c @@ -110,8 +110,8 @@ void ipq9574_ppe_acl_set(int rule_id, int rule_type, int pkt_type, int l4_port_n hw_reg.bf.pri = 0x0; } - hw_reg.bf.src_0 = 0x6; - hw_reg.bf.src_1 = 0x7; + hw_reg.bf.src_0 = 0x0; + hw_reg.bf.src_1 = 0x3f; ppe_ipo_rule_reg_set(&hw_reg, rule_id); ppe_ipo_mask_reg_set(&hw_mask, rule_id); ppe_ipo_action_set(&hw_act, rule_id); @@ -153,7 +153,7 @@ static void ipq9574_ppe_ucast_queue_map_tbl_queue_id_set(int queue, int port) */ static void ipq9574_vsi_setup(int vsi, uint8_t group_mask) { - uint32_t val = (group_mask << 24 | group_mask << 16 | group_mask << 8 + uint32_t val = (group_mask << 24 | group_mask << 16 | 0x1 | group_mask); /* Set mask */ @@ -473,7 +473,7 @@ void ipq9574_pqsgmii_speed_set(int port, int speed, int status) ppe_port_bridge_txmac_set(port + 1, status); ipq9574_ppe_reg_write(IPQ9574_PPE_MAC_SPEED + (0x200 * port), speed); ipq9574_ppe_reg_write(IPQ9574_PPE_MAC_ENABLE + (0x200 * port), 0x73); - ipq9574_ppe_reg_write(IPQ9574_PPE_MAC_MIB_CTL + (0x200 * port), 0x5); + ipq9574_ppe_reg_write(IPQ9574_PPE_MAC_MIB_CTL + (0x200 * port), 0x1); } /* @@ -895,6 +895,8 @@ void ipq9574_ppe_provision_init(void) ipq9574_ppe_vp_port_tbl_set(2, 3); ipq9574_ppe_vp_port_tbl_set(3, 4); ipq9574_ppe_vp_port_tbl_set(4, 5); + ipq9574_ppe_vp_port_tbl_set(5, 6); + ipq9574_ppe_vp_port_tbl_set(6, 7); #endif /* Unicast priority map */ @@ -914,10 +916,6 @@ void ipq9574_ppe_provision_init(void) ipq9574_ppe_e_sp_cfg_tbl_drr_id_set(i); } - /* sp_cfg_l0 and sp_cfg_l1 configuration */ - ipq9574_ppe_reg_write(IPQ9574_PPE_TM_SHP_CFG_L0, 0x12b); - ipq9574_ppe_reg_write(IPQ9574_PPE_TM_SHP_CFG_L1, 0x3f); - /* Port0 multicast queue */ ipq9574_ppe_reg_write(0x409000, 0x00000000); ipq9574_ppe_reg_write(0x403000, 0x00401000); @@ -956,6 +954,8 @@ void ipq9574_ppe_provision_init(void) ipq9574_vsi_setup(3, 0x05); ipq9574_vsi_setup(4, 0x09); ipq9574_vsi_setup(5, 0x11); + ipq9574_vsi_setup(6, 0x21); + ipq9574_vsi_setup(7, 0x41); #endif /* Port 0-7 STP */ diff --git a/drivers/net/ipq9574/ipq9574_ppe.h b/drivers/net/ipq9574/ipq9574_ppe.h index c1ec72dc45..9e0a8d953e 100644 --- a/drivers/net/ipq9574/ipq9574_ppe.h +++ b/drivers/net/ipq9574/ipq9574_ppe.h @@ -77,14 +77,14 @@ struct ipo_rule_reg { uint32_t fake_mac_header:1; uint32_t range_en:1; uint32_t inverse_en:1; - uint32_t rule_type:4; - uint32_t src_type:2; - uint32_t src_0:3; - uint32_t src_1:5; + uint32_t rule_type:5; + uint32_t src_type:3; + uint32_t src_0:1; + uint32_t src_1:7; uint32_t pri:9; uint32_t res_chain:1; uint32_t post_routing_en:1; - uint32_t _reserved0:16; + uint32_t _reserved0:14; }; union ipo_rule_reg_u { diff --git a/dts/Kconfig b/dts/Kconfig index fb2d79edbc..f3c784e087 100644 --- a/dts/Kconfig +++ b/dts/Kconfig @@ -14,6 +14,16 @@ config OF_CONTROL This feature provides for run-time configuration of U-Boot via a flattened device tree. +config OF_BOARD_FIXUP + bool "Board-specific manipulation of Device Tree" + help + In certain circumstances it is necessary to be able to modify + U-Boot's device tree (e.g. to delete device from it). This option + make the Device Tree writeable and provides a board-specific + "board_fix_fdt" callback (called during pre-relocation time), which + enables the board initialization to modifiy the Device Tree. The + modified copy is subsequently used by U-Boot after relocation. + config SPL_OF_CONTROL bool "Enable run-time configuration via Device Tree in SPL" depends on SPL && OF_CONTROL diff --git a/include/common.h b/include/common.h index c1ad31ae2e..749c7f33a4 100644 --- a/include/common.h +++ b/include/common.h @@ -532,6 +532,7 @@ extern ssize_t spi_write (uchar *, int, uchar *, int); /* $(BOARD)/$(BOARD).c */ int board_early_init_f (void); +int board_fix_fdt (void *rw_fdt_blob); /* manipulate the U-Boot fdt before its relocation */ int board_late_init (void); int board_postclk_init (void); /* after clocks/timebase, before env/serial */ int board_early_init_r (void); diff --git a/include/configs/ipq5018.h b/include/configs/ipq5018.h index 48532d8b3b..f623bfad6c 100644 --- a/include/configs/ipq5018.h +++ b/include/configs/ipq5018.h @@ -169,6 +169,7 @@ extern loff_t board_env_size; #endif /* QSPI DEBUG */ #define CONFIG_PAGE_SCOPE_MULTI_PAGE_READ #define CONFIG_QSPI_SERIAL_TRAINING +#define CONFIG_QSPI_LAYOUT_SWITCH #endif /* diff --git a/include/configs/ipq6018.h b/include/configs/ipq6018.h index 78e3fe7718..3ca25cb773 100644 --- a/include/configs/ipq6018.h +++ b/include/configs/ipq6018.h @@ -291,6 +291,19 @@ extern loff_t board_env_size; #ifdef CONFIG_OF_BOARD_SETUP #define DLOAD_DISABLE 0x1 + +#ifdef CONFIG_IPQ_RUNTIME_FAILSAFE +#define CONFIG_HW_WATCHDOG +#define IPQ_FS_NONHLOS_BIT (1 << 9) +#define IPQ_FS_HLOS_BIT (1 << 10) +#endif + +#ifdef CONFIG_IPQ_RUNTIME_FAILSAFE_DEBUG +#define fs_debug(fmt, args...) printf(fmt, ##args); +#else +#define fs_debug(fmt, args...) +#endif + /* * Below Configs need to be updated after enabling reset_crashdump * Included now to avoid build failure diff --git a/include/configs/ipq9574.h b/include/configs/ipq9574.h index 4a832186f4..d67edd6d90 100644 --- a/include/configs/ipq9574.h +++ b/include/configs/ipq9574.h @@ -285,6 +285,23 @@ extern loff_t board_env_size; #ifdef CONFIG_OF_BOARD_SETUP #define DLOAD_DISABLE 0x1 + +#define CONFIG_IPQ_RUNTIME_FAILSAFE +#ifdef CONFIG_IPQ_RUNTIME_FAILSAFE +#define CONFIG_HW_WATCHDOG +#define IPQ_FS_NONHLOS_BIT (1 << 9) +#define IPQ_FS_HLOS_BIT (1 << 10) +#define IPQ_RUNTIME_FAILSAFE_ENABLED (1 << 0) +#define IPQ_RUNTIME_FS_BOOTCONFIG_UPDATED (1 << 1) + +#endif + +#ifdef CONFIG_IPQ_RUNTIME_FAILSAFE_DEBUG +#define fs_debug(fmt, args...) printf(fmt, ##args); +#else +#define fs_debug(fmt, args...) +#endif + /* * Below Configs need to be updated after enabling reset_crashdump * Included now to avoid build failure diff --git a/tools/pack.py b/tools/pack.py index 0e819db84b..4d223fb210 100644 --- a/tools/pack.py +++ b/tools/pack.py @@ -89,8 +89,8 @@ memory_size = "default" lk = "false" skip_4k_nand = "false" atf = "false" -qcn6122 = "false" tiny_16m = "false" +multi_wifi_fw = "false" # Note: ipq806x didn't expose any relevant version */ soc_hw_version_ipq40xx = { 0x20050100 }; @@ -1101,11 +1101,11 @@ class Pack(object): if part_info.which_flash == 0: offset = part_info.offset script.erase(offset, part_info.length) - if ARCH_NAME in ["ipq9574", "ipq9574_64"]: + if ARCH_NAME in ["ipq5018", "ipq5018_64", "ipq9574", "ipq9574_64"]: if self.flash_type == "nand-4k" and section_conf == "sbl1": script.switch_layout_qpic("sbl") script.write(offset, img_size) - if ARCH_NAME in ["ipq9574", "ipq9574_64"]: + if ARCH_NAME in ["ipq5018", "ipq5018_64", "ipq9574", "ipq9574_64"]: if self.flash_type == "nand-4k" and section_conf == "sbl1": script.switch_layout_qpic("linux") else: @@ -1275,7 +1275,7 @@ class Pack(object): try: diff_soc_ver_files = section.attrib['diff_soc_ver_files'] except KeyError, e: - if (qcn6122 == "true" or tiny_16m == "true") and 'wififw_type_min' in section.attrib: + if (multi_wifi_fw == "true" or tiny_16m == "true") and 'wififw_type_min' in section.attrib: wifi_fw_type_min = section.attrib['wififw_type_min'] wifi_fw_type_max = section.attrib['wififw_type_max'] else: @@ -1341,7 +1341,7 @@ class Pack(object): if flinfo.type != "emmc": img = section.find('img_name') - if img != None and 'wififw_type' in img.attrib and (qcn6122 == "true" or tiny_16m == "true"): + if img != None and 'wififw_type' in img.attrib and (multi_wifi_fw == "true" or tiny_16m == "true"): imgs = section.findall('img_name') try: for img in imgs: @@ -1438,7 +1438,7 @@ class Pack(object): if ret == 0: return 0 - if self.flash_type in [ "nand", "nand-4k", "norplusnand", "norplusnand-4k" ] and partition == "rootfs" and qcn6122 == "true": + if self.flash_type in [ "nand", "nand-4k", "norplusnand", "norplusnand-4k" ] and partition == "rootfs" and multi_wifi_fw == "true": fw_imgs = section.findall('img_name') for fw_img in fw_imgs: @@ -1717,7 +1717,7 @@ class Pack(object): diff_soc_ver_files = section.attrib['diff_soc_ver_files'] partition = section.attrib['label'] except KeyError, e: - if (qcn6122 == "true" or tiny_16m == "true") and 'wififw_type_min' in section.attrib: + if (multi_wifi_fw == "true" or tiny_16m == "true") and 'wififw_type_min' in section.attrib: wifi_fw_type_min = section.attrib['wififw_type_min'] wifi_fw_type_max = section.attrib['wififw_type_max'] partition = section.attrib['label'] @@ -1783,7 +1783,7 @@ class Pack(object): img = section.find('img_name') - if img != None and 'wififw_type' in img.attrib and (qcn6122 == "true" or tiny_16m == "true"): + if img != None and 'wififw_type' in img.attrib and (multi_wifi_fw == "true" or tiny_16m == "true"): imgs = section.findall('img_name') try: for img in imgs: @@ -1888,7 +1888,7 @@ class Pack(object): if filename != "": self.__gen_script_append_images(filename, soc_version, wifi_fw_type, images, flinfo, root, section_conf, partition) - if self.flash_type in [ "nand", "nand-4k", "norplusnand", "norplusnand-4k" ] and section_conf == "rootfs" and qcn6122 == "true": + if self.flash_type in [ "nand", "nand-4k", "norplusnand", "norplusnand-4k" ] and section_conf == "rootfs" and multi_wifi_fw == "true": fw_imgs = section.findall('img_name') try: @@ -2241,7 +2241,7 @@ class ArgParser(object): global lk global atf global skip_4k_nand - global qcn6122 + global multi_wifi_fw """Start the parsing process, and populate members with parsed value. @@ -2251,7 +2251,7 @@ class ArgParser(object): cdir = os.path.abspath(os.path.dirname("")) if len(sys.argv) > 1: try: - opts, args = getopt(sys.argv[1:], "", ["arch=", "fltype=", "srcPath=", "inImage=", "outImage=", "image_type=", "memory=", "lk", "skip_4k_nand", "atf", "qcn6122"]) + opts, args = getopt(sys.argv[1:], "", ["arch=", "fltype=", "srcPath=", "inImage=", "outImage=", "image_type=", "memory=", "lk", "skip_4k_nand", "atf", "qcn6122", "multi_wifi_fw"]) except GetoptError, e: raise UsageError(e.msg) @@ -2287,7 +2287,10 @@ class ArgParser(object): skip_4k_nand = "true" elif option == "--qcn6122": - qcn6122 = "true" + multi_wifi_fw = "true" + + elif option == "--multi_wifi_fw": + multi_wifi_fw = "true" #Verify Arguments passed by user