Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * OMAP2+ MPU WD_TIMER-specific code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2012 Texas Instruments, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/platform_data/omap-wd-timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include "omap_hwmod.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include "omap_device.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include "wd_timer.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include "common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include "prm.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include "soc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  * In order to avoid any assumptions from bootloader regarding WDT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  * settings, WDT module is reset during init. This enables the watchdog
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  * timer. Hence it is required to disable the watchdog after the WDT reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  * during init. Otherwise the system would reboot as per the default
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  * watchdog timer registers settings.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #define OMAP_WDT_WPS		0x34
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #define OMAP_WDT_SPR		0x48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) int omap2_wd_timer_disable(struct omap_hwmod *oh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	if (!oh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 		pr_err("%s: Could not look up wdtimer_hwmod\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	base = omap_hwmod_get_mpu_rt_va(oh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	if (!base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 		pr_err("%s: Could not get the base address for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 				oh->name, __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	/* sequence required to disable watchdog */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	writel_relaxed(0xAAAA, base + OMAP_WDT_SPR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	while (readl_relaxed(base + OMAP_WDT_WPS) & 0x10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 		cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	writel_relaxed(0x5555, base + OMAP_WDT_SPR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	while (readl_relaxed(base + OMAP_WDT_WPS) & 0x10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 		cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60)  * omap2_wdtimer_reset - reset and disable the WDTIMER IP block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61)  * @oh: struct omap_hwmod *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63)  * After the WDTIMER IP blocks are reset on OMAP2/3, we must also take
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64)  * care to execute the special watchdog disable sequence.  This is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65)  * because the watchdog is re-armed upon OCP softreset.  (On OMAP4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66)  * this behavior was apparently changed and the watchdog is no longer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67)  * re-armed after an OCP soft-reset.)  Returns -ETIMEDOUT if the reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68)  * did not complete, or 0 upon success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70)  * XXX Most of this code should be moved to the omap_hwmod.c layer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71)  * during a normal merge window.  omap_hwmod_softreset() should be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72)  * renamed to omap_hwmod_set_ocp_softreset(), and omap_hwmod_softreset()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73)  * should call the hwmod _ocp_softreset() code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) int omap2_wd_timer_reset(struct omap_hwmod *oh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	int c = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	/* Write to the SOFTRESET bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	omap_hwmod_softreset(oh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	/* Poll on RESETDONE bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	omap_test_timeout((omap_hwmod_read(oh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 					   oh->class->sysc->syss_offs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 			   & SYSS_RESETDONE_MASK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 			  MAX_MODULE_SOFTRESET_WAIT, c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	if (oh->class->sysc->srst_udelay)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 		udelay(oh->class->sysc->srst_udelay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	if (c == MAX_MODULE_SOFTRESET_WAIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		pr_warn("%s: %s: softreset failed (waited %d usec)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 			__func__, oh->name, MAX_MODULE_SOFTRESET_WAIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 		pr_debug("%s: %s: softreset in %d usec\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 			 oh->name, c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	return (c == MAX_MODULE_SOFTRESET_WAIT) ? -ETIMEDOUT :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 		omap2_wd_timer_disable(oh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }