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