svn commit: r294678 - stable/10/sys/arm/freescale/imx
Ian Lepore
ian at FreeBSD.org
Sun Jan 24 19:34:07 UTC 2016
Author: ian
Date: Sun Jan 24 19:34:05 2016
New Revision: 294678
URL: https://svnweb.freebsd.org/changeset/base/294678
Log:
MFC r291149, r291367:
Update the imx5/imx6 cpu_reset() implementation based on a new understanding
of the SRS (software reset) bit in the watchdog control register. Despite
what the manual seems to imply, this bit DOES trigger an immediate reset, as
opposed to simply flagging the type of reset as software-triggered.
Rename sysctl node hw.imx6 to hw.imx. Move its definition to imx_machdep.c
so that code shared between imx5 and imx6 can work with OIDs under that node.
Add last_reset_status (integer) and last_reset_reason (string) OIDs that
provide info about the last chip reset (power-on, software reset, watchdog
timeout).
Modified:
stable/10/sys/arm/freescale/imx/imx6_anatop.c
stable/10/sys/arm/freescale/imx/imx6_machdep.c
stable/10/sys/arm/freescale/imx/imx_machdep.c
stable/10/sys/arm/freescale/imx/imx_machdep.h
stable/10/sys/arm/freescale/imx/imx_wdogreg.h
Directory Properties:
stable/10/ (props changed)
Modified: stable/10/sys/arm/freescale/imx/imx6_anatop.c
==============================================================================
--- stable/10/sys/arm/freescale/imx/imx6_anatop.c Sun Jan 24 19:21:53 2016 (r294677)
+++ stable/10/sys/arm/freescale/imx/imx6_anatop.c Sun Jan 24 19:34:05 2016 (r294678)
@@ -73,11 +73,10 @@ __FBSDID("$FreeBSD$");
#include <arm/freescale/fsl_ocotpreg.h>
#include <arm/freescale/fsl_ocotpvar.h>
#include <arm/freescale/imx/imx_ccmvar.h>
+#include <arm/freescale/imx/imx_machdep.h>
#include <arm/freescale/imx/imx6_anatopreg.h>
#include <arm/freescale/imx/imx6_anatopvar.h>
-static SYSCTL_NODE(_hw, OID_AUTO, imx6, CTLFLAG_RW, NULL, "i.MX6 container");
-
static struct resource_spec imx6_anatop_spec[] = {
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
{ SYS_RES_IRQ, 0, RF_ACTIVE },
@@ -396,23 +395,23 @@ cpufreq_initialize(struct imx6_anatop_so
uint32_t cfg3speed;
struct oppt * op;
- SYSCTL_ADD_INT(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx6),
+ SYSCTL_ADD_INT(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx),
OID_AUTO, "cpu_mhz", CTLFLAG_RD, &sc->cpu_curmhz, 0,
"CPU frequency");
- SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx6),
+ SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx),
OID_AUTO, "cpu_minmhz", CTLTYPE_INT | CTLFLAG_RWTUN, sc, 0,
cpufreq_sysctl_minmhz, "IU", "Minimum CPU frequency");
- SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx6),
+ SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx),
OID_AUTO, "cpu_maxmhz", CTLTYPE_INT | CTLFLAG_RWTUN, sc, 0,
cpufreq_sysctl_maxmhz, "IU", "Maximum CPU frequency");
- SYSCTL_ADD_INT(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx6),
+ SYSCTL_ADD_INT(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx),
OID_AUTO, "cpu_maxmhz_hw", CTLFLAG_RD, &sc->cpu_maxmhz_hw, 0,
"Maximum CPU frequency allowed by hardware");
- SYSCTL_ADD_INT(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx6),
+ SYSCTL_ADD_INT(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx),
OID_AUTO, "cpu_overclock_enable", CTLFLAG_RWTUN,
&sc->cpu_overclock_enable, 0,
"Allow setting CPU frequency higher than cpu_maxmhz_hw");
@@ -630,10 +629,10 @@ initialize_tempmon(struct imx6_anatop_so
callout_reset_sbt(&sc->temp_throttle_callout, sc->temp_throttle_delay,
0, tempmon_throttle_check, sc, 0);
- SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx6),
+ SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx),
OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD, sc, 0,
temp_sysctl_handler, "IK", "Current die temperature");
- SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx6),
+ SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx),
OID_AUTO, "throttle_temperature", CTLTYPE_INT | CTLFLAG_RW, sc,
0, temp_throttle_sysctl_handler, "IK",
"Throttle CPU when exceeding this temperature");
Modified: stable/10/sys/arm/freescale/imx/imx6_machdep.c
==============================================================================
--- stable/10/sys/arm/freescale/imx/imx6_machdep.c Sun Jan 24 19:21:53 2016 (r294677)
+++ stable/10/sys/arm/freescale/imx/imx6_machdep.c Sun Jan 24 19:34:05 2016 (r294678)
@@ -99,7 +99,6 @@ initarm_lastaddr(void)
void
initarm_early_init(void)
{
-
/* Inform the MPCore timer driver that its clock is variable. */
arm_tmr_change_frequency(ARM_TMR_FREQUENCY_VARIES);
}
@@ -113,6 +112,9 @@ initarm_gpio_init(void)
void
initarm_late_init(void)
{
+ const uint32_t IMX6_WDOG_SR_PHYS = 0x020bc004;
+
+ imx_wdog_init_last_reset(IMX6_WDOG_SR_PHYS);
/* Cache the gpio1 node handle for imx6_decode_fdt() workaround code. */
gpio1_node = OF_node_from_xref(
Modified: stable/10/sys/arm/freescale/imx/imx_machdep.c
==============================================================================
--- stable/10/sys/arm/freescale/imx/imx_machdep.c Sun Jan 24 19:21:53 2016 (r294677)
+++ stable/10/sys/arm/freescale/imx/imx_machdep.c Sun Jan 24 19:34:05 2016 (r294678)
@@ -45,6 +45,15 @@ __FBSDID("$FreeBSD$");
#include <arm/freescale/imx/imx_machdep.h>
#include <arm/freescale/imx/imx_wdogreg.h>
+SYSCTL_NODE(_hw, OID_AUTO, imx, CTLFLAG_RW, NULL, "i.MX container");
+
+static int last_reset_status;
+SYSCTL_UINT(_hw_imx, OID_AUTO, last_reset_status, CTLFLAG_RD,
+ &last_reset_status, 0, "Last reset status register");
+
+SYSCTL_STRING(_hw_imx, OID_AUTO, last_reset_reason, CTLFLAG_RD,
+ "unknown", 0, "Last reset reason");
+
struct arm32_dma_range *
bus_dma_get_range(void)
{
@@ -72,21 +81,36 @@ imx_wdog_cpu_reset(vm_offset_t wdcr_phys
volatile uint16_t * pcr;
/*
- * The deceptively simple write of WDOG_CR_WDE enables the watchdog,
- * sets the timeout to its minimum value (half a second), and also
- * clears the SRS bit which results in the SFTW (software-requested
- * reset) bit being set in the watchdog status register after the reset.
- * This is how software can distinguish a reset from a wdog timeout.
+ * Trigger an immediate reset by clearing the SRS bit in the watchdog
+ * control register. The reset happens on the next cycle of the wdog
+ * 32KHz clock, so hang out in a spin loop until the reset takes effect.
*/
if ((pcr = arm_devmap_ptov(wdcr_physaddr, sizeof(*pcr))) == NULL) {
printf("cpu_reset() can't find its control register... locking up now.");
} else {
- *pcr = WDOG_CR_WDE;
+ *pcr &= ~WDOG_CR_SRS;
}
for (;;)
continue;
}
+void
+imx_wdog_init_last_reset(vm_offset_t wdsr_phys)
+{
+ volatile uint16_t * psr;
+
+ if ((psr = arm_devmap_ptov(wdsr_phys, sizeof(*psr))) == NULL)
+ return;
+ last_reset_status = *psr;
+ if (last_reset_status & WDOG_RSR_SFTW) {
+ sysctl___hw_imx_last_reset_reason.oid_arg1 = "SoftwareReset";
+ } else if (last_reset_status & WDOG_RSR_TOUT) {
+ sysctl___hw_imx_last_reset_reason.oid_arg1 = "WatchdogTimeout";
+ } else if (last_reset_status & WDOG_RSR_POR) {
+ sysctl___hw_imx_last_reset_reason.oid_arg1 = "PowerOnReset";
+ }
+}
+
u_int
imx_soc_family(void)
{
Modified: stable/10/sys/arm/freescale/imx/imx_machdep.h
==============================================================================
--- stable/10/sys/arm/freescale/imx/imx_machdep.h Sun Jan 24 19:21:53 2016 (r294677)
+++ stable/10/sys/arm/freescale/imx/imx_machdep.h Sun Jan 24 19:34:05 2016 (r294678)
@@ -30,10 +30,14 @@
#define IMX_MACHDEP_H
#include <sys/types.h>
+#include <sys/sysctl.h>
+
+SYSCTL_DECL(_hw_imx);
/* Common functions, implemented in imx_machdep.c. */
void imx_wdog_cpu_reset(vm_offset_t _wdcr_phys) __attribute__((__noreturn__));
+void imx_wdog_init_last_reset(vm_offset_t _wdsr_phys);
/* From here down, routines are implemented in imxNN_machdep.c. */
Modified: stable/10/sys/arm/freescale/imx/imx_wdogreg.h
==============================================================================
--- stable/10/sys/arm/freescale/imx/imx_wdogreg.h Sun Jan 24 19:21:53 2016 (r294677)
+++ stable/10/sys/arm/freescale/imx/imx_wdogreg.h Sun Jan 24 19:34:05 2016 (r294678)
@@ -47,6 +47,7 @@
#define WDOG_SR_STEP2 0xaaaa
#define WDOG_RSR_REG 0x04 /* Reset Status Register */
+#define WDOG_RSR_POR (1 << 4) /* Due to Power-On Reset */
#define WDOG_RSR_TOUT (1 << 1) /* Due WDog timeout reset */
#define WDOG_RSR_SFTW (1 << 0) /* Due Soft reset */
More information about the svn-src-stable
mailing list