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