From 4c904e23a5dd117d4072efa8ef04cfb5f8d89e44 Mon Sep 17 00:00:00 2001 From: Prasanna Kumar Thoorvas Samyrao Muralidharan Date: Tue, 1 Oct 2019 16:31:42 +0530 Subject: [PATCH] ipq807x: Detect NOC error Detect NOC error and reset the board. Change-Id: Id03e7c58d5ea47ef7fe508f0598fd57b80cba1dd Signed-off-by: Prasanna Kumar Thoorvas Samyrao Muralidharan --- board/qca/arm/common/board_init.c | 2 + board/qca/arm/ipq40xx/ipq40xx.h | 2 + board/qca/arm/ipq6018/ipq6018.h | 2 + board/qca/arm/ipq806x/ipq806x.h | 2 + board/qca/arm/ipq807x/ipq807x.c | 106 ++++++++++++++++++++++++++++++ board/qca/arm/ipq807x/ipq807x.h | 2 + common/bootm.c | 3 + 7 files changed, 119 insertions(+) diff --git a/board/qca/arm/common/board_init.c b/board/qca/arm/common/board_init.c index fff4d27474..7210387e36 100644 --- a/board/qca/arm/common/board_init.c +++ b/board/qca/arm/common/board_init.c @@ -107,6 +107,8 @@ int board_init(void) report_l2err(l2esr); #endif + qgic_init(); + qca_smem_flash_info_t *sfi = &qca_smem_flash_info; gd->bd->bi_boot_params = QCA_BOOT_PARAMS_ADDR; diff --git a/board/qca/arm/ipq40xx/ipq40xx.h b/board/qca/arm/ipq40xx/ipq40xx.h index b7fe71b412..37ebf01110 100644 --- a/board/qca/arm/ipq40xx/ipq40xx.h +++ b/board/qca/arm/ipq40xx/ipq40xx.h @@ -81,6 +81,8 @@ void board_pci_init(int id); __weak void board_pcie_clock_init(int id) {} __weak void aquantia_phy_reset_init_done(void) {} __weak void aquantia_phy_reset_init(void) {} +__weak void qgic_init(void) {} +__weak void handle_noc_err(void) {} __weak int ipq_get_tz_version(char *version_name, int buf_size) { return 1; diff --git a/board/qca/arm/ipq6018/ipq6018.h b/board/qca/arm/ipq6018/ipq6018.h index b3c42bf272..b04ff959f7 100644 --- a/board/qca/arm/ipq6018/ipq6018.h +++ b/board/qca/arm/ipq6018/ipq6018.h @@ -359,6 +359,8 @@ int ipq_board_usb_init(void); void board_pci_init(int id); __weak void board_pcie_clock_init(int id) {} +__weak void qgic_init(void) {} +__weak void handle_noc_err(void) {} #endif #endif /* _IPQ6018_CDP_H_ */ diff --git a/board/qca/arm/ipq806x/ipq806x.h b/board/qca/arm/ipq806x/ipq806x.h index f57eb71620..44357362a2 100644 --- a/board/qca/arm/ipq806x/ipq806x.h +++ b/board/qca/arm/ipq806x/ipq806x.h @@ -154,6 +154,8 @@ static inline int gmac_cfg_is_valid(ipq_gmac_board_cfg_t *cfg) __weak void aquantia_phy_reset_init_done(void) {} __weak void aquantia_phy_reset_init(void) {} +__weak void qgic_init(void) {} +__weak void handle_noc_err(void) {} struct smem_ram_ptn { char name[16]; diff --git a/board/qca/arm/ipq807x/ipq807x.c b/board/qca/arm/ipq807x/ipq807x.c index b6ac0a2f23..0e1cba3bfe 100644 --- a/board/qca/arm/ipq807x/ipq807x.c +++ b/board/qca/arm/ipq807x/ipq807x.c @@ -28,6 +28,36 @@ #include #include +#define MSM_GIC_DIST_BASE 0x0B000000 +#define MSM_GIC_CPU_BASE 0x0B002000 + +#define GIC_CPU_REG(off) (MSM_GIC_CPU_BASE + (off)) +#define GIC_DIST_REG(off) (MSM_GIC_DIST_BASE + (off)) + +#define GIC_CPU_CTRL GIC_CPU_REG(0x00) +#define GIC_CPU_PRIMASK GIC_CPU_REG(0x04) +#define GIC_CPU_BINPOINT GIC_CPU_REG(0x08) +#define GIC_CPU_INTACK GIC_CPU_REG(0x0c) +#define GIC_CPU_EOI GIC_CPU_REG(0x10) +#define GIC_CPU_RUNNINGPRI GIC_CPU_REG(0x14) +#define GIC_CPU_HIGHPRI GIC_CPU_REG(0x18) + +#define GIC_DIST_CTRL GIC_DIST_REG(0x000) +#define GIC_DIST_CTR GIC_DIST_REG(0x004) +#define GIC_DIST_ENABLE_SET GIC_DIST_REG(0x100) +#define GIC_DIST_ENABLE_CLEAR GIC_DIST_REG(0x180) +#define GIC_DIST_PENDING_SET GIC_DIST_REG(0x200) +#define GIC_DIST_PENDING_CLEAR GIC_DIST_REG(0x280) +#define GIC_DIST_ACTIVE_BIT GIC_DIST_REG(0x300) +#define GIC_DIST_PRI GIC_DIST_REG(0x400) +#define GIC_DIST_TARGET GIC_DIST_REG(0x800) +#define GIC_DIST_CONFIG GIC_DIST_REG(0xc00) +#define GIC_DIST_SOFTINT GIC_DIST_REG(0xf00) + +#define REG_VAL_NOC_ERR 0x100000 +#define NOC_ERR_STATUS_REG 0xb000220 +#define NOC_ERR_CLR_REG 0xb0002a0 + #define DLOAD_MAGIC_COOKIE 0x10 DECLARE_GLOBAL_DATA_PTR; @@ -1555,3 +1585,79 @@ void sdi_disable(void) { qca_scm_sdi(); } + +void handle_noc_err(void) +{ + uint32_t noc_err_pending = 0; + noc_err_pending = readl(NOC_ERR_STATUS_REG); + + printf("NOC Error detected, restarting"); + if ((noc_err_pending & REG_VAL_NOC_ERR) == REG_VAL_NOC_ERR) { + writel(REG_VAL_NOC_ERR, NOC_ERR_CLR_REG); + run_command("reset", 0); + } +} + +/* Intialize distributor */ +static void qgic_dist_init(void) +{ + uint32_t i; + uint32_t num_irq = 0; + uint32_t cpumask = 1; + + cpumask |= cpumask << 8; + cpumask |= cpumask << 16; + + /* Disabling GIC */ + writel(0, GIC_DIST_CTRL); + + /* + * Find out how many interrupts are supported. + */ + num_irq = readl(GIC_DIST_CTR) & 0x1f; + num_irq = (num_irq + 1) * 32; + + /* Set each interrupt line to use N-N software model + * and edge sensitive, active high + */ + for (i = 32; i < num_irq; i += 16) + writel(0xffffffff, GIC_DIST_CONFIG + i * 4 / 16); + + writel(0xffffffff, GIC_DIST_CONFIG + 4); + + /* Set up interrupts for this CPU */ + for (i = 32; i < num_irq; i += 4) + writel(cpumask, GIC_DIST_TARGET + i * 4 / 4); + + /* Set priority of all interrupts */ + + /* + * In bootloader we dont care about priority so + * setting up equal priorities for all + */ + for (i = 0; i < num_irq; i += 4) + writel(0xa0a0a0a0, GIC_DIST_PRI + i * 4 / 4); + + /* Disabling interrupts */ + for (i = 0; i < num_irq; i += 32) + writel(0xffffffff, GIC_DIST_ENABLE_CLEAR + i * 4 / 32); + + writel(0x0000ffff, GIC_DIST_ENABLE_SET); + + /*Enabling GIC */ + writel(1, GIC_DIST_CTRL); +} + +/* Intialize cpu specific controller */ +static void qgic_cpu_init(void) +{ + writel(0xf0, GIC_CPU_PRIMASK); + writel(1, GIC_CPU_CTRL); +} + +/* Initialize QGIC. Called from platform specific init code */ +void qgic_init(void) +{ + qgic_dist_init(); + qgic_cpu_init(); +} diff --git a/board/qca/arm/ipq807x/ipq807x.h b/board/qca/arm/ipq807x/ipq807x.h index dd128e7c59..3e9408794d 100644 --- a/board/qca/arm/ipq807x/ipq807x.h +++ b/board/qca/arm/ipq807x/ipq807x.h @@ -310,6 +310,8 @@ void reset_crashdump(void); void board_pci_init(int id); __weak void board_pcie_clock_init(int id) {} #endif +void qgic_init(void); +void handle_noc_err(void); void ipq_fdt_fixup_socinfo(void *blob); int ipq_board_usb_init(void); unsigned smem_read_alloc_entry(smem_mem_type_t type, void *buf, int len); diff --git a/common/bootm.c b/common/bootm.c index 9c8d28a621..8d1a7ccd89 100644 --- a/common/bootm.c +++ b/common/bootm.c @@ -595,6 +595,7 @@ static void fixup_silent_linux(void) * then the intent is to boot an OS, so this function will not return * unless the image type is standalone. */ +void handle_noc_err(void); int do_bootm_states(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], int states, bootm_headers_t *images, int boot_progress) { @@ -604,6 +605,8 @@ int do_bootm_states(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], images->state |= states; + handle_noc_err(); + /* * Work through the states and see how far we get. We stop on * any error.