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/boot.h> 36 #include <kernel/panic.h> 37 #include <libfdt.h> 38 #include <mm/core_memprot.h> 39 #include <mm/core_mmu.h> 40 #include <util.h> 41 42 static bool ext_reset; 43 static vaddr_t wdog_base; 44 45 void imx_wdog_restart(void) 46 { 47 uint32_t val; 48 49 if (!wdog_base) { 50 EMSG("No wdog mapped\n"); 51 panic(); 52 } 53 54 #ifdef CFG_MX7ULP 55 val = io_read32(wdog_base + WDOG_CS); 56 57 io_write32(wdog_base + WDOG_CNT, UNLOCK); 58 /* Enable wdog */ 59 io_write32(wdog_base + WDOG_CS, val | WDOG_CS_EN); 60 61 io_write32(wdog_base + WDOG_CNT, UNLOCK); 62 io_write32(wdog_base + WDOG_TOVAL, 1000); 63 io_write32(wdog_base + WDOG_CNT, REFRESH); 64 #else 65 if (ext_reset) 66 val = 0x14; 67 else 68 val = 0x24; 69 70 DMSG("val %x\n", val); 71 72 io_write16(wdog_base + WDT_WCR, val); 73 dsb(); 74 75 if (io_read16(wdog_base + WDT_WCR) & WDT_WCR_WDE) { 76 io_write16(wdog_base + WDT_WSR, WDT_SEQ1); 77 io_write16(wdog_base + WDT_WSR, WDT_SEQ2); 78 } 79 80 io_write16(wdog_base + WDT_WCR, val); 81 io_write16(wdog_base + WDT_WCR, val); 82 #endif 83 84 while (1) 85 ; 86 } 87 DECLARE_KEEP_PAGER(imx_wdog_restart); 88 89 #if defined(CFG_DT) && !defined(CFG_EXTERNAL_DTB_OVERLAY) 90 static TEE_Result imx_wdog_base(vaddr_t *wdog_vbase) 91 { 92 enum teecore_memtypes mtype; 93 void *fdt; 94 paddr_t pbase; 95 vaddr_t vbase; 96 ssize_t sz; 97 int off; 98 int st; 99 uint32_t i; 100 101 #ifdef CFG_MX7 102 static const char * const wdog_path[] = { 103 "/soc/aips-bus@30000000/wdog@30280000", 104 "/soc/aips-bus@30000000/wdog@30290000", 105 "/soc/aips-bus@30000000/wdog@302a0000", 106 "/soc/aips-bus@30000000/wdog@302b0000", 107 }; 108 #elif defined CFG_MX7ULP 109 static const char * const wdog_path[] = { 110 "/ahb-bridge0@40000000/wdog@403D0000", 111 "/ahb-bridge0@40000000/wdog@40430000", 112 }; 113 #else 114 static const char * const wdog_path[] = { 115 "/soc/aips-bus@2000000/wdog@20bc000", 116 "/soc/aips-bus@2000000/wdog@20c0000", 117 }; 118 #endif 119 120 fdt = get_dt(); 121 if (!fdt) { 122 EMSG("No DTB\n"); 123 return TEE_ERROR_NOT_SUPPORTED; 124 } 125 126 /* search the first usable wdog */ 127 for (i = 0; i < ARRAY_SIZE(wdog_path); i++) { 128 off = fdt_path_offset(fdt, wdog_path[i]); 129 if (off < 0) 130 continue; 131 132 st = _fdt_get_status(fdt, off); 133 if (st & DT_STATUS_OK_SEC) 134 break; 135 } 136 137 if (i == ARRAY_SIZE(wdog_path)) 138 return TEE_ERROR_ITEM_NOT_FOUND; 139 140 DMSG("path: %s\n", wdog_path[i]); 141 142 ext_reset = dt_have_prop(fdt, off, "fsl,ext-reset-output"); 143 144 pbase = _fdt_reg_base_address(fdt, off); 145 if (pbase == (paddr_t)-1) 146 return TEE_ERROR_ITEM_NOT_FOUND; 147 148 sz = _fdt_reg_size(fdt, off); 149 if (sz < 0) 150 return TEE_ERROR_ITEM_NOT_FOUND; 151 152 if ((st & DT_STATUS_OK_SEC) && !(st & DT_STATUS_OK_NSEC)) 153 mtype = MEM_AREA_IO_SEC; 154 else 155 mtype = MEM_AREA_IO_NSEC; 156 157 /* 158 * Check to see whether it has been mapped using 159 * register_phys_mem or not. 160 */ 161 vbase = (vaddr_t)phys_to_virt(pbase, mtype); 162 if (!vbase) { 163 if (!core_mmu_add_mapping(mtype, pbase, sz)) { 164 EMSG("Failed to map %zu bytes at PA 0x%"PRIxPA, 165 (size_t)sz, pbase); 166 return TEE_ERROR_GENERIC; 167 } 168 } 169 170 vbase = (vaddr_t)phys_to_virt(pbase, mtype); 171 if (!vbase) { 172 EMSG("Failed to get VA for PA 0x%"PRIxPA, pbase); 173 return TEE_ERROR_GENERIC; 174 } 175 176 *wdog_vbase = vbase; 177 178 return TEE_SUCCESS; 179 } 180 #else 181 register_phys_mem_pgdir(MEM_AREA_IO_SEC, WDOG_BASE, CORE_MMU_PGDIR_SIZE); 182 static TEE_Result imx_wdog_base(vaddr_t *wdog_vbase) 183 { 184 *wdog_vbase = (vaddr_t)phys_to_virt(WDOG_BASE, MEM_AREA_IO_SEC); 185 #if defined(CFG_IMX_WDOG_EXT_RESET) 186 ext_reset = true; 187 #endif 188 return TEE_SUCCESS; 189 } 190 #endif 191 192 static TEE_Result imx_wdog_init(void) 193 { 194 #if defined(PLATFORM_FLAVOR_mx7dsabresd) || \ 195 defined(PLATFORM_FLAVOR_mx7dclsom) 196 197 ext_reset = true; 198 #endif 199 return imx_wdog_base(&wdog_base); 200 } 201 driver_init(imx_wdog_init); 202