xref: /optee_os/core/drivers/imx_wdog.c (revision 5a913ee74d3c71af2a2860ce8a4e7aeab2916f9b)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright 2017-2019 NXP
4  *
5  * Peng Fan <peng.fan@nxp.com>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice,
11  * this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  * this list of conditions and the following disclaimer in the documentation
15  * and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include <assert.h>
31 #include <drivers/imx_wdog.h>
32 #include <io.h>
33 #include <keep.h>
34 #include <kernel/dt.h>
35 #include <kernel/generic_boot.h>
36 #include <kernel/panic.h>
37 #ifdef CFG_DT
38 #include <libfdt.h>
39 #endif
40 #include <mm/core_mmu.h>
41 #include <mm/core_memprot.h>
42 #include <util.h>
43 
44 static bool ext_reset;
45 static vaddr_t wdog_base;
46 
47 void imx_wdog_restart(void)
48 {
49 	uint32_t val;
50 
51 	if (!wdog_base) {
52 		EMSG("No wdog mapped\n");
53 		panic();
54 	}
55 
56 #ifdef CFG_MX7ULP
57 	val = io_read32(wdog_base + WDOG_CS);
58 
59 	io_write32(wdog_base + WDOG_CNT, UNLOCK);
60 	/* Enable wdog */
61 	io_write32(wdog_base + WDOG_CS, val | WDOG_CS_EN);
62 
63 	io_write32(wdog_base + WDOG_CNT, UNLOCK);
64 	io_write32(wdog_base + WDOG_TOVAL, 1000);
65 	io_write32(wdog_base + WDOG_CNT, REFRESH);
66 #else
67 	if (ext_reset)
68 		val = 0x14;
69 	else
70 		val = 0x24;
71 
72 	DMSG("val %x\n", val);
73 
74 	io_write16(wdog_base + WDT_WCR, val);
75 	dsb();
76 
77 	if (io_read16(wdog_base + WDT_WCR) & WDT_WCR_WDE) {
78 		io_write16(wdog_base + WDT_WSR, WDT_SEQ1);
79 		io_write16(wdog_base + WDT_WSR, WDT_SEQ2);
80 	}
81 
82 	io_write16(wdog_base + WDT_WCR, val);
83 	io_write16(wdog_base + WDT_WCR, val);
84 #endif
85 
86 	while (1)
87 		;
88 }
89 KEEP_PAGER(imx_wdog_restart);
90 
91 #if defined(CFG_DT) && !defined(CFG_EXTERNAL_DTB_OVERLAY)
92 static TEE_Result imx_wdog_base(vaddr_t *wdog_vbase)
93 {
94 	enum teecore_memtypes mtype;
95 	void *fdt;
96 	paddr_t pbase;
97 	vaddr_t vbase;
98 	ssize_t sz;
99 	int off;
100 	int st;
101 	uint32_t i;
102 
103 #ifdef CFG_MX7
104 	static const char * const wdog_path[] = {
105 		"/soc/aips-bus@30000000/wdog@30280000",
106 		"/soc/aips-bus@30000000/wdog@30290000",
107 		"/soc/aips-bus@30000000/wdog@302a0000",
108 		"/soc/aips-bus@30000000/wdog@302b0000",
109 	};
110 #elif defined CFG_MX7ULP
111 	static const char * const wdog_path[] = {
112 		"/ahb-bridge0@40000000/wdog@403D0000",
113 		"/ahb-bridge0@40000000/wdog@40430000",
114 	};
115 #else
116 	static const char * const wdog_path[] = {
117 		"/soc/aips-bus@2000000/wdog@20bc000",
118 		"/soc/aips-bus@2000000/wdog@20c0000",
119 	};
120 #endif
121 
122 	fdt = get_dt();
123 	if (!fdt) {
124 		EMSG("No DTB\n");
125 		return TEE_ERROR_NOT_SUPPORTED;
126 	}
127 
128 	/* search the first usable wdog */
129 	for (i = 0; i < ARRAY_SIZE(wdog_path); i++) {
130 		off = fdt_path_offset(fdt, wdog_path[i]);
131 		if (off < 0)
132 			continue;
133 
134 		st = _fdt_get_status(fdt, off);
135 		if (st & DT_STATUS_OK_SEC)
136 			break;
137 	}
138 
139 	if (i == ARRAY_SIZE(wdog_path))
140 		return TEE_ERROR_ITEM_NOT_FOUND;
141 
142 	DMSG("path: %s\n", wdog_path[i]);
143 
144 	ext_reset = dt_have_prop(fdt, off, "fsl,ext-reset-output");
145 
146 	pbase = _fdt_reg_base_address(fdt, off);
147 	if (pbase == (paddr_t)-1)
148 		return TEE_ERROR_ITEM_NOT_FOUND;
149 
150 	sz = _fdt_reg_size(fdt, off);
151 	if (sz < 0)
152 		return TEE_ERROR_ITEM_NOT_FOUND;
153 
154 	if ((st & DT_STATUS_OK_SEC) && !(st & DT_STATUS_OK_NSEC))
155 		mtype = MEM_AREA_IO_SEC;
156 	else
157 		mtype = MEM_AREA_IO_NSEC;
158 
159 	/*
160 	 * Check to see whether it has been mapped using
161 	 * register_phys_mem or not.
162 	 */
163 	vbase = (vaddr_t)phys_to_virt(pbase, mtype);
164 	if (!vbase) {
165 		if (!core_mmu_add_mapping(mtype, pbase, sz)) {
166 			EMSG("Failed to map %zu bytes at PA 0x%"PRIxPA,
167 			     (size_t)sz, pbase);
168 			return TEE_ERROR_GENERIC;
169 		}
170 	}
171 
172 	vbase = (vaddr_t)phys_to_virt(pbase, mtype);
173 	if (!vbase) {
174 		EMSG("Failed to get VA for PA 0x%"PRIxPA, pbase);
175 		return TEE_ERROR_GENERIC;
176 	}
177 
178 	*wdog_vbase = vbase;
179 
180 	return TEE_SUCCESS;
181 }
182 #else
183 register_phys_mem_pgdir(MEM_AREA_IO_SEC, WDOG_BASE, CORE_MMU_PGDIR_SIZE);
184 static TEE_Result imx_wdog_base(vaddr_t *wdog_vbase)
185 {
186 	*wdog_vbase = (vaddr_t)phys_to_virt(WDOG_BASE, MEM_AREA_IO_SEC);
187 #if defined(CFG_IMX_WDOG_EXT_RESET)
188 	ext_reset = true;
189 #endif
190 	return TEE_SUCCESS;
191 }
192 #endif
193 
194 static TEE_Result imx_wdog_init(void)
195 {
196 #if defined(PLATFORM_FLAVOR_mx7dsabresd) || \
197 	defined(PLATFORM_FLAVOR_mx7dclsom)
198 
199 	ext_reset = true;
200 #endif
201 	return imx_wdog_base(&wdog_base);
202 }
203 driver_init(imx_wdog_init);
204