Path: blob/main/sys/arm/freescale/imx/imx_machdep.c
39536 views
/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2013 Ian Lepore <[email protected]>4* All rights reserved.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11* 2. Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14*15* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND16* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE17* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE18* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE19* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL20* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS21* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)22* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT23* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY24* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF25* SUCH DAMAGE.26*/2728#include "opt_platform.h"2930#include <sys/param.h>31#include <sys/systm.h>32#include <sys/reboot.h>3334#include <vm/vm.h>35#include <vm/pmap.h>3637#include <machine/armreg.h>38#include <machine/bus.h>39#include <machine/cpu.h>40#include <machine/machdep.h>4142#include <arm/freescale/imx/imx_machdep.h>43#include <arm/freescale/imx/imx_wdogreg.h>4445SYSCTL_NODE(_hw, OID_AUTO, imx, CTLFLAG_RW | CTLFLAG_MPSAFE, NULL,46"i.MX container");4748static int last_reset_status;49SYSCTL_UINT(_hw_imx, OID_AUTO, last_reset_status, CTLFLAG_RD,50&last_reset_status, 0, "Last reset status register");5152SYSCTL_STRING(_hw_imx, OID_AUTO, last_reset_reason, CTLFLAG_RD,53"unknown", 0, "Last reset reason");5455/*56* This code which manipulates the watchdog hardware is here to implement57* cpu_reset() because the watchdog is the only way for software to reset the58* chip. Why here and not in imx_wdog.c? Because there's no requirement that59* the watchdog driver be compiled in, but it's nice to be able to reboot even60* if it's not.61*/62void63imx_wdog_cpu_reset(vm_offset_t wdcr_physaddr)64{65volatile uint16_t cr, *pcr;6667if ((pcr = pmap_mapdev(wdcr_physaddr, sizeof(*pcr))) == NULL) {68printf("imx_wdog_cpu_reset(): "69"cannot find control register... locking up now.");70for (;;)71cpu_spinwait();72}73cr = *pcr;7475/*76* If the watchdog hardware has been set up to trigger an external reset77* signal on watchdog timeout, then we do software-requested rebooting78* the same way, by asserting the external reset signal.79*80* Asserting external reset is supposed to result in some external81* component asserting the POR pin on the SoC, possibly after adjusting82* and stabilizing system voltages, or taking other system-wide reset83* actions. Just in case there is some kind of misconfiguration, we84* hang out and do nothing for a full second, then continue on into85* the code to assert a software reset as well.86*/87if (cr & WDOG_CR_WDT) {88cr &= ~WDOG_CR_WDA; /* Assert active-low ext reset bit. */89*pcr = cr;90DELAY(1000000);91printf("imx_wdog_cpu_reset(): "92"External reset failed, trying internal cpu-reset\n");93DELAY(10000); /* Time for printf to appear */94}9596/*97* Imx6 erratum ERR004346 says the SRS bit has to be cleared twice98* within the same cycle of the 32khz clock to reliably trigger the99* reset. Writing it 3 times in a row ensures at least 2 of the writes100* happen in the same 32k clock cycle.101*/102cr &= ~WDOG_CR_SRS; /* Assert active-low software reset bit. */103*pcr = cr;104*pcr = cr;105*pcr = cr;106107/* Reset happens on the next tick of the 32khz clock, wait for it. */108for (;;)109cpu_spinwait();110}111112void113imx_wdog_init_last_reset(vm_offset_t wdsr_phys)114{115volatile uint16_t * psr;116117if ((psr = pmap_mapdev(wdsr_phys, sizeof(*psr))) == NULL)118return;119last_reset_status = *psr;120if (last_reset_status & WDOG_RSR_SFTW) {121sysctl___hw_imx_last_reset_reason.oid_arg1 = "SoftwareReset";122} else if (last_reset_status & WDOG_RSR_TOUT) {123sysctl___hw_imx_last_reset_reason.oid_arg1 = "WatchdogTimeout";124} else if (last_reset_status & WDOG_RSR_POR) {125sysctl___hw_imx_last_reset_reason.oid_arg1 = "PowerOnReset";126}127pmap_unmapdev((void *)(uintptr_t)psr, sizeof(*psr));128}129130131