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