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