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