| // SPDX-License-Identifier: BSD-2-Clause |
| /* |
| * Copyright 2017-2019 NXP |
| * |
| * Peng Fan <peng.fan@nxp.com> |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| * POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include <assert.h> |
| #include <drivers/imx_wdog.h> |
| #include <io.h> |
| #include <keep.h> |
| #include <kernel/dt.h> |
| #include <kernel/generic_boot.h> |
| #include <kernel/panic.h> |
| #ifdef CFG_DT |
| #include <libfdt.h> |
| #endif |
| #include <mm/core_mmu.h> |
| #include <mm/core_memprot.h> |
| #include <util.h> |
| |
| static bool ext_reset; |
| static vaddr_t wdog_base; |
| |
| void imx_wdog_restart(void) |
| { |
| uint32_t val; |
| |
| if (!wdog_base) { |
| EMSG("No wdog mapped\n"); |
| panic(); |
| } |
| |
| #ifdef CFG_MX7ULP |
| val = io_read32(wdog_base + WDOG_CS); |
| |
| io_write32(wdog_base + WDOG_CNT, UNLOCK); |
| /* Enable wdog */ |
| io_write32(wdog_base + WDOG_CS, val | WDOG_CS_EN); |
| |
| io_write32(wdog_base + WDOG_CNT, UNLOCK); |
| io_write32(wdog_base + WDOG_TOVAL, 1000); |
| io_write32(wdog_base + WDOG_CNT, REFRESH); |
| #else |
| if (ext_reset) |
| val = 0x14; |
| else |
| val = 0x24; |
| |
| DMSG("val %x\n", val); |
| |
| io_write16(wdog_base + WDT_WCR, val); |
| dsb(); |
| |
| if (io_read16(wdog_base + WDT_WCR) & WDT_WCR_WDE) { |
| io_write16(wdog_base + WDT_WSR, WDT_SEQ1); |
| io_write16(wdog_base + WDT_WSR, WDT_SEQ2); |
| } |
| |
| io_write16(wdog_base + WDT_WCR, val); |
| io_write16(wdog_base + WDT_WCR, val); |
| #endif |
| |
| while (1) |
| ; |
| } |
| KEEP_PAGER(imx_wdog_restart); |
| |
| #if defined(CFG_DT) && !defined(CFG_EXTERNAL_DTB_OVERLAY) |
| static TEE_Result imx_wdog_base(vaddr_t *wdog_vbase) |
| { |
| enum teecore_memtypes mtype; |
| void *fdt; |
| paddr_t pbase; |
| vaddr_t vbase; |
| ssize_t sz; |
| int off; |
| int st; |
| uint32_t i; |
| |
| #ifdef CFG_MX7 |
| static const char * const wdog_path[] = { |
| "/soc/aips-bus@30000000/wdog@30280000", |
| "/soc/aips-bus@30000000/wdog@30290000", |
| "/soc/aips-bus@30000000/wdog@302a0000", |
| "/soc/aips-bus@30000000/wdog@302b0000", |
| }; |
| #elif defined CFG_MX7ULP |
| static const char * const wdog_path[] = { |
| "/ahb-bridge0@40000000/wdog@403D0000", |
| "/ahb-bridge0@40000000/wdog@40430000", |
| }; |
| #else |
| static const char * const wdog_path[] = { |
| "/soc/aips-bus@2000000/wdog@20bc000", |
| "/soc/aips-bus@2000000/wdog@20c0000", |
| }; |
| #endif |
| |
| fdt = get_dt(); |
| if (!fdt) { |
| EMSG("No DTB\n"); |
| return TEE_ERROR_NOT_SUPPORTED; |
| } |
| |
| /* search the first usable wdog */ |
| for (i = 0; i < ARRAY_SIZE(wdog_path); i++) { |
| off = fdt_path_offset(fdt, wdog_path[i]); |
| if (off < 0) |
| continue; |
| |
| st = _fdt_get_status(fdt, off); |
| if (st & DT_STATUS_OK_SEC) |
| break; |
| } |
| |
| if (i == ARRAY_SIZE(wdog_path)) |
| return TEE_ERROR_ITEM_NOT_FOUND; |
| |
| DMSG("path: %s\n", wdog_path[i]); |
| |
| ext_reset = dt_have_prop(fdt, off, "fsl,ext-reset-output"); |
| |
| pbase = _fdt_reg_base_address(fdt, off); |
| if (pbase == (paddr_t)-1) |
| return TEE_ERROR_ITEM_NOT_FOUND; |
| |
| sz = _fdt_reg_size(fdt, off); |
| if (sz < 0) |
| return TEE_ERROR_ITEM_NOT_FOUND; |
| |
| if ((st & DT_STATUS_OK_SEC) && !(st & DT_STATUS_OK_NSEC)) |
| mtype = MEM_AREA_IO_SEC; |
| else |
| mtype = MEM_AREA_IO_NSEC; |
| |
| /* |
| * Check to see whether it has been mapped using |
| * register_phys_mem or not. |
| */ |
| vbase = (vaddr_t)phys_to_virt(pbase, mtype); |
| if (!vbase) { |
| if (!core_mmu_add_mapping(mtype, pbase, sz)) { |
| EMSG("Failed to map %zu bytes at PA 0x%"PRIxPA, |
| (size_t)sz, pbase); |
| return TEE_ERROR_GENERIC; |
| } |
| } |
| |
| vbase = (vaddr_t)phys_to_virt(pbase, mtype); |
| if (!vbase) { |
| EMSG("Failed to get VA for PA 0x%"PRIxPA, pbase); |
| return TEE_ERROR_GENERIC; |
| } |
| |
| *wdog_vbase = vbase; |
| |
| return TEE_SUCCESS; |
| } |
| #else |
| register_phys_mem_pgdir(MEM_AREA_IO_SEC, WDOG_BASE, CORE_MMU_PGDIR_SIZE); |
| static TEE_Result imx_wdog_base(vaddr_t *wdog_vbase) |
| { |
| *wdog_vbase = (vaddr_t)phys_to_virt(WDOG_BASE, MEM_AREA_IO_SEC); |
| #if defined(CFG_IMX_WDOG_EXT_RESET) |
| ext_reset = true; |
| #endif |
| return TEE_SUCCESS; |
| } |
| #endif |
| |
| static TEE_Result imx_wdog_init(void) |
| { |
| #if defined(PLATFORM_FLAVOR_mx7dsabresd) || \ |
| defined(PLATFORM_FLAVOR_mx7dclsom) |
| |
| ext_reset = true; |
| #endif |
| return imx_wdog_base(&wdog_base); |
| } |
| driver_init(imx_wdog_init); |