1d58da314SBiju Das /* 2d58da314SBiju Das * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. 3d58da314SBiju Das * 4d58da314SBiju Das * SPDX-License-Identifier: BSD-3-Clause 5d58da314SBiju Das */ 6d58da314SBiju Das 7d58da314SBiju Das #include <arch_helpers.h> 8d58da314SBiju Das #include <common/debug.h> 9d58da314SBiju Das #include <drivers/arm/gicv2.h> 10d58da314SBiju Das #include <lib/mmio.h> 11d58da314SBiju Das 12d58da314SBiju Das #include "rcar_def.h" 13d58da314SBiju Das 14d58da314SBiju Das extern void gicd_set_icenabler(uintptr_t base, unsigned int id); 15d58da314SBiju Das 16d58da314SBiju Das #define RST_BASE (0xE6160000U) 17d58da314SBiju Das #define RST_WDTRSTCR (RST_BASE + 0x0054U) 18d58da314SBiju Das #define SWDT_BASE (0xE6030000U) 19d58da314SBiju Das #define SWDT_WTCNT (SWDT_BASE + 0x0000U) 20d58da314SBiju Das #define SWDT_WTCSRA (SWDT_BASE + 0x0004U) 21d58da314SBiju Das #define SWDT_WTCSRB (SWDT_BASE + 0x0008U) 22d58da314SBiju Das #define SWDT_GICD_BASE (0xF1010000U) 23d58da314SBiju Das #define SWDT_GICC_BASE (0xF1020000U) 24d58da314SBiju Das #define SWDT_GICD_CTLR (SWDT_GICD_BASE + 0x0000U) 25d58da314SBiju Das #define SWDT_GICD_IGROUPR (SWDT_GICD_BASE + 0x0080U) 26d58da314SBiju Das #define SWDT_GICD_ISPRIORITYR (SWDT_GICD_BASE + 0x0400U) 27d58da314SBiju Das #define SWDT_GICC_CTLR (SWDT_GICC_BASE + 0x0000U) 28d58da314SBiju Das #define SWDT_GICC_PMR (SWDT_GICC_BASE + 0x0004U) 29d58da314SBiju Das #define SWDT_GICD_ITARGETSR (SWDT_GICD_BASE + 0x0800U) 30d58da314SBiju Das #define IGROUPR_NUM (16U) 31d58da314SBiju Das #define ISPRIORITY_NUM (128U) 32d58da314SBiju Das #define ITARGET_MASK (0x03U) 33d58da314SBiju Das 34d58da314SBiju Das #define WDTRSTCR_UPPER_BYTE (0xA55A0000U) 35d58da314SBiju Das #define WTCSRA_UPPER_BYTE (0xA5A5A500U) 36d58da314SBiju Das #define WTCSRB_UPPER_BYTE (0xA5A5A500U) 37d58da314SBiju Das #define WTCNT_UPPER_BYTE (0x5A5A0000U) 38d58da314SBiju Das #define WTCNT_RESET_VALUE (0xF488U) 39d58da314SBiju Das #define WTCSRA_BIT_CKS (0x0007U) 40d58da314SBiju Das #define WTCSRB_BIT_CKS (0x003FU) 41d58da314SBiju Das #define SWDT_RSTMSK (1U << 1U) 42d58da314SBiju Das #define WTCSRA_WOVFE (1U << 3U) 43d58da314SBiju Das #define WTCSRA_WRFLG (1U << 5U) 44d58da314SBiju Das #define SWDT_ENABLE (1U << 7U) 45d58da314SBiju Das 46d58da314SBiju Das #define WDTRSTCR_MASK_ALL (0x0000FFFFU) 47d58da314SBiju Das #define WTCSRA_MASK_ALL (0x000000FFU) 48d58da314SBiju Das #define WTCNT_INIT_DATA (WTCNT_UPPER_BYTE + WTCNT_RESET_VALUE) 49d58da314SBiju Das #define WTCSRA_INIT_DATA (WTCSRA_UPPER_BYTE + 0x0FU) 50d58da314SBiju Das #define WTCSRB_INIT_DATA (WTCSRB_UPPER_BYTE + 0x21U) 51d58da314SBiju Das 52d58da314SBiju Das #if RCAR_LSI == RCAR_D3 53d58da314SBiju Das #define WTCNT_COUNT_8p13k (0x10000U - 40760U) 54d58da314SBiju Das #else 55d58da314SBiju Das #define WTCNT_COUNT_8p13k (0x10000U - 40687U) 56d58da314SBiju Das #endif 57d58da314SBiju Das #define WTCNT_COUNT_8p13k_H3VER10 (0x10000U - 20343U) 58d58da314SBiju Das #define WTCNT_COUNT_8p22k (0x10000U - 41115U) 59d58da314SBiju Das #define WTCNT_COUNT_7p81k (0x10000U - 39062U) 60d58da314SBiju Das #define WTCSRA_CKS_DIV16 (0x00000002U) 61d58da314SBiju Das 62d58da314SBiju Das static void swdt_disable(void) 63d58da314SBiju Das { 64d58da314SBiju Das uint32_t rmsk; 65d58da314SBiju Das 66d58da314SBiju Das rmsk = mmio_read_32(RST_WDTRSTCR) & WDTRSTCR_MASK_ALL; 67d58da314SBiju Das rmsk |= SWDT_RSTMSK; 68d58da314SBiju Das mmio_write_32(RST_WDTRSTCR, WDTRSTCR_UPPER_BYTE | rmsk); 69d58da314SBiju Das 70d58da314SBiju Das mmio_write_32(SWDT_WTCNT, WTCNT_INIT_DATA); 71d58da314SBiju Das mmio_write_32(SWDT_WTCSRA, WTCSRA_INIT_DATA); 72d58da314SBiju Das mmio_write_32(SWDT_WTCSRB, WTCSRB_INIT_DATA); 73d58da314SBiju Das 74d58da314SBiju Das /* Set the interrupt clear enable register */ 75d58da314SBiju Das gicd_set_icenabler(RCAR_GICD_BASE, ARM_IRQ_SEC_WDT); 76d58da314SBiju Das } 77d58da314SBiju Das 78d58da314SBiju Das void rcar_swdt_init(void) 79d58da314SBiju Das { 80d58da314SBiju Das uint32_t rmsk, sr; 81*2c10d4e2SLad Prabhakar #if (RCAR_LSI != RCAR_E3) && (RCAR_LSI != RZ_G2E) 82d58da314SBiju Das uint32_t reg, val, product_cut, chk_data; 83d58da314SBiju Das 84d58da314SBiju Das reg = mmio_read_32(RCAR_PRR); 85d58da314SBiju Das product_cut = reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK); 86d58da314SBiju Das 87d58da314SBiju Das reg = mmio_read_32(RCAR_MODEMR); 88d58da314SBiju Das chk_data = reg & CHECK_MD13_MD14; 89d58da314SBiju Das #endif 90d58da314SBiju Das /* stop watchdog */ 91d58da314SBiju Das if (mmio_read_32(SWDT_WTCSRA) & SWDT_ENABLE) 92d58da314SBiju Das mmio_write_32(SWDT_WTCSRA, WTCSRA_UPPER_BYTE); 93d58da314SBiju Das 94d58da314SBiju Das mmio_write_32(SWDT_WTCSRA, WTCSRA_UPPER_BYTE | 95d58da314SBiju Das WTCSRA_WOVFE | WTCSRA_CKS_DIV16); 96d58da314SBiju Das 97*2c10d4e2SLad Prabhakar #if (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RZ_G2E) 98d58da314SBiju Das mmio_write_32(SWDT_WTCNT, WTCNT_UPPER_BYTE | WTCNT_COUNT_7p81k); 99d58da314SBiju Das #else 100d58da314SBiju Das val = WTCNT_UPPER_BYTE; 101d58da314SBiju Das 102d58da314SBiju Das switch (chk_data) { 103d58da314SBiju Das case MD14_MD13_TYPE_0: 104d58da314SBiju Das case MD14_MD13_TYPE_2: 105d58da314SBiju Das val |= WTCNT_COUNT_8p13k; 106d58da314SBiju Das break; 107d58da314SBiju Das case MD14_MD13_TYPE_1: 108d58da314SBiju Das val |= WTCNT_COUNT_8p22k; 109d58da314SBiju Das break; 110d58da314SBiju Das case MD14_MD13_TYPE_3: 111d58da314SBiju Das val |= product_cut == (PRR_PRODUCT_H3 | PRR_PRODUCT_10) ? 112d58da314SBiju Das WTCNT_COUNT_8p13k_H3VER10 : WTCNT_COUNT_8p13k; 113d58da314SBiju Das break; 114d58da314SBiju Das default: 115d58da314SBiju Das ERROR("MODEMR ERROR value = %x\n", chk_data); 116d58da314SBiju Das panic(); 117d58da314SBiju Das break; 118d58da314SBiju Das } 119d58da314SBiju Das 120d58da314SBiju Das mmio_write_32(SWDT_WTCNT, val); 121d58da314SBiju Das #endif 122d58da314SBiju Das rmsk = mmio_read_32(RST_WDTRSTCR) & WDTRSTCR_MASK_ALL; 123d58da314SBiju Das rmsk |= SWDT_RSTMSK | WDTRSTCR_UPPER_BYTE; 124d58da314SBiju Das mmio_write_32(RST_WDTRSTCR, rmsk); 125d58da314SBiju Das 126d58da314SBiju Das while ((mmio_read_8(SWDT_WTCSRA) & WTCSRA_WRFLG) != 0U) 127d58da314SBiju Das ; 128d58da314SBiju Das 129d58da314SBiju Das /* Start the System WatchDog Timer */ 130d58da314SBiju Das sr = mmio_read_32(SWDT_WTCSRA) & WTCSRA_MASK_ALL; 131d58da314SBiju Das mmio_write_32(SWDT_WTCSRA, (WTCSRA_UPPER_BYTE | sr | SWDT_ENABLE)); 132d58da314SBiju Das } 133d58da314SBiju Das 134d58da314SBiju Das void rcar_swdt_release(void) 135d58da314SBiju Das { 136d58da314SBiju Das uintptr_t itarget = SWDT_GICD_ITARGETSR + 137d58da314SBiju Das (ARM_IRQ_SEC_WDT & ~ITARGET_MASK); 138d58da314SBiju Das uint32_t i; 139d58da314SBiju Das 140d58da314SBiju Das /* Disable FIQ interrupt */ 141d58da314SBiju Das write_daifset(DAIF_FIQ_BIT); 142d58da314SBiju Das /* FIQ interrupts are not taken to EL3 */ 143d58da314SBiju Das write_scr_el3(read_scr_el3() & ~SCR_FIQ_BIT); 144d58da314SBiju Das 145d58da314SBiju Das swdt_disable(); 146d58da314SBiju Das gicv2_cpuif_disable(); 147d58da314SBiju Das 148d58da314SBiju Das for (i = 0; i < IGROUPR_NUM; i++) 149d58da314SBiju Das mmio_write_32(SWDT_GICD_IGROUPR + i * 4, 0U); 150d58da314SBiju Das 151d58da314SBiju Das for (i = 0; i < ISPRIORITY_NUM; i++) 152d58da314SBiju Das mmio_write_32(SWDT_GICD_ISPRIORITYR + i * 4, 0U); 153d58da314SBiju Das 154d58da314SBiju Das mmio_write_32(itarget, 0U); 155d58da314SBiju Das mmio_write_32(SWDT_GICD_CTLR, 0U); 156d58da314SBiju Das mmio_write_32(SWDT_GICC_CTLR, 0U); 157d58da314SBiju Das mmio_write_32(SWDT_GICC_PMR, 0U); 158d58da314SBiju Das } 159d58da314SBiju Das 160d58da314SBiju Das void rcar_swdt_exec(uint64_t p) 161d58da314SBiju Das { 162d58da314SBiju Das gicv2_end_of_interrupt(ARM_IRQ_SEC_WDT); 163d58da314SBiju Das rcar_swdt_release(); 164d58da314SBiju Das ERROR("\n"); 165d58da314SBiju Das ERROR("System WDT overflow, occurred address is %p\n", (void *)p); 166d58da314SBiju Das panic(); 167d58da314SBiju Das } 168