arch/arm/rp23xx: fix watchdog, enable TICK blocks
On the RP2350, the watchdog receives its tick input from the system-level ticks block, unlike the RP2040, where the watchdog includes its own tick generator. Enable the TICK blocks, update the watchdog routines. Signed-off-by: Serg Podtynnyi <serg@podtynnyi.com>
This commit is contained in:
parent
28abfb5fd1
commit
95cc862794
5 changed files with 188 additions and 85 deletions
|
|
@ -75,4 +75,6 @@
|
|||
#define RP23XX_PSM_OTP (1 << 1)
|
||||
#define RP23XX_PSM_PROC_COLD (1 << 0)
|
||||
|
||||
#define RP23XX_PSM_WDSEL_BITS 0x01ffffff
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_RP23XX_HARDWARE_RP23XX_PSM_H */
|
||||
|
|
|
|||
92
arch/arm/src/rp23xx/hardware/rp23xx_ticks.h
Normal file
92
arch/arm/src/rp23xx/hardware/rp23xx_ticks.h
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
/****************************************************************************
|
||||
* arch/arm/src/rp23xx/hardware/rp23xx_ticks.h
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_ARM_SRC_RP23XX_HARDWARE_RP23XX_TICKS_H
|
||||
#define __ARCH_ARM_SRC_RP23XX_HARDWARE_RP23XX_TICKS_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "hardware/rp23xx_memorymap.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Register offsets *********************************************************/
|
||||
|
||||
#define RP23XX_TICKS_PROC0_CTRL_OFFSET 0x00000000
|
||||
#define RP23XX_TICKS_PROC0_CYCLES_OFFSET 0x00000004
|
||||
#define RP23XX_TICKS_PROC0_COUNT_OFFSET 0x00000008
|
||||
|
||||
#define RP23XX_TICKS_PROC1_CTRL_OFFSET 0x0000000c
|
||||
#define RP23XX_TICKS_PROC1_CYCLES_OFFSET 0x00000010
|
||||
#define RP23XX_TICKS_PROC1_COUNT_OFFSET 0x00000014
|
||||
|
||||
#define RP23XX_TICKS_TIMER0_CTRL_OFFSET 0x00000018
|
||||
#define RP23XX_TICKS_TIMER0_CYCLES_OFFSET 0x0000001c
|
||||
#define RP23XX_TICKS_TIMER0_COUNT_OFFSET 0x00000020
|
||||
|
||||
#define RP23XX_TICKS_TIMER1_CTRL_OFFSET 0x00000024
|
||||
#define RP23XX_TICKS_TIMER1_CYCLES_OFFSET 0x00000028
|
||||
#define RP23XX_TICKS_TIMER1_COUNT_OFFSET 0x0000002c
|
||||
|
||||
#define RP23XX_TICKS_WATCHDOG_CTRL_OFFSET 0x00000030
|
||||
#define RP23XX_TICKS_WATCHDOG_CYCLES_OFFSET 0x00000034
|
||||
#define RP23XX_TICKS_WATCHDOG_COUNT_OFFSET 0x00000038
|
||||
|
||||
#define RP23XX_TICKS_CTRL_OFFSET(n) ((n) * 12 + RP23XX_TICKS_PROC0_CTRL_OFFSET)
|
||||
#define RP23XX_TICKS_CYCLES_OFFSET(n) ((n) * 12 + RP23XX_TICKS_PROC0_CYCLES_OFFSET)
|
||||
#define RP23XX_TICKS_COUNT_OFFSET(n) ((n) * 12 + RP23XX_TICKS_PROC0_COUNT_OFFSET)
|
||||
|
||||
/* Register definitions *****************************************************/
|
||||
|
||||
#define RP23XX_TICKS_CTRL(n) (RP23XX_TICKS_BASE + RP23XX_TICKS_CTRL_OFFSET(n))
|
||||
#define RP23XX_TICKS_CYCLES(n) (RP23XX_TICKS_BASE + RP23XX_TICKS_CYCLES_OFFSET(n))
|
||||
#define RP23XX_TICKS_COUNT(n) (RP23XX_TICKS_BASE + RP23XX_TICKS_COUNT_OFFSET(n))
|
||||
|
||||
#define RP23XX_TICKS_PROC0_CTRL (RP23XX_TICKS_BASE + RP23XX_TICKS_PROC0_CTRL_OFFSET)
|
||||
#define RP23XX_TICKS_PROC0_CYCLES (RP23XX_TICKS_BASE + RP23XX_TICKS_PROC0_CYCLES_OFFSET)
|
||||
#define RP23XX_TICKS_PROC0_COUNT (RP23XX_TICKS_BASE + RP23XX_TICKS_PROC0_COUNT_OFFSET)
|
||||
|
||||
#define RP23XX_TICKS_PROC1_CTRL (RP23XX_TICKS_BASE + RP23XX_TICKS_PROC1_CTRL_OFFSET)
|
||||
#define RP23XX_TICKS_PROC1_CYCLES (RP23XX_TICKS_BASE + RP23XX_TICKS_PROC1_CYCLES_OFFSET)
|
||||
#define RP23XX_TICKS_PROC1_COUNT (RP23XX_TICKS_BASE + RP23XX_TICKS_PROC1_COUNT_OFFSET)
|
||||
|
||||
#define RP23XX_TICKS_TIMER0_CTRL (RP23XX_TICKS_BASE + RP23XX_TICKS_TIMER0_CTRL_OFFSET)
|
||||
#define RP23XX_TICKS_TIMER0_CYCLES (RP23XX_TICKS_BASE + RP23XX_TICKS_TIMER0_CYCLES_OFFSET)
|
||||
#define RP23XX_TICKS_TIMER0_COUNT (RP23XX_TICKS_BASE + RP23XX_TICKS_TIMER0_COUNT_OFFSET)
|
||||
|
||||
#define RP23XX_TICKS_TIMER1_CTRL (RP23XX_TICKS_BASE + RP23XX_TICKS_TIMER1_CTRL_OFFSET)
|
||||
#define RP23XX_TICKS_TIMER1_CYCLES (RP23XX_TICKS_BASE + RP23XX_TICKS_TIMER1_CYCLES_OFFSET)
|
||||
#define RP23XX_TICKS_TIMER1_COUNT (RP23XX_TICKS_BASE + RP23XX_TICKS_TIMER1_COUNT_OFFSET)
|
||||
|
||||
#define RP23XX_TICKS_WATCHDOG_CTRL (RP23XX_TICKS_BASE + RP23XX_TICKS_WATCHDOG_CTRL_OFFSET)
|
||||
#define RP23XX_TICKS_WATCHDOG_CYCLES (RP23XX_TICKS_BASE + RP23XX_TICKS_WATCHDOG_CYCLES_OFFSET)
|
||||
#define RP23XX_TICKS_WATCHDOG_COUNT (RP23XX_TICKS_BASE + RP23XX_TICKS_WATCHDOG_COUNT_OFFSET)
|
||||
|
||||
/* Register bit definitions *************************************************/
|
||||
|
||||
#define RP23XX_TICKS_WATCHDOG_CTRL_EN (1 << 0)
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_RP23XX_HARDWARE_RP23XX_TICKS_H */
|
||||
|
|
@ -55,7 +55,7 @@
|
|||
#include "rp23xx_pll.h"
|
||||
#include "hardware/rp23xx_clocks.h"
|
||||
#include "hardware/rp23xx_resets.h"
|
||||
#include "hardware/rp23xx_watchdog.h"
|
||||
#include "hardware/rp23xx_ticks.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
|
@ -71,6 +71,12 @@ static uint32_t rp23xx_clock_freq[RP23XX_CLOCKS_NDX_MAX];
|
|||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static void tick_start(int tick, int cycles)
|
||||
{
|
||||
putreg32(cycles, RP23XX_TICKS_CYCLES(tick));
|
||||
putreg32(RP23XX_TICKS_WATCHDOG_CTRL_EN, RP23XX_TICKS_CTRL(tick));
|
||||
}
|
||||
|
||||
static inline bool has_glitchless_mux(int clk_index)
|
||||
{
|
||||
return clk_index == RP23XX_CLOCKS_NDX_SYS ||
|
||||
|
|
@ -202,11 +208,6 @@ bool rp23xx_clock_configure(int clk_index,
|
|||
|
||||
void clocks_init(void)
|
||||
{
|
||||
/* Start tick in watchdog */
|
||||
|
||||
putreg32((BOARD_REF_FREQ / MHZ) | RP23XX_WATCHDOG_CTRL_ENABLE,
|
||||
RP23XX_WATCHDOG_CTRL);
|
||||
|
||||
/* Disable resus that may be enabled from previous software */
|
||||
|
||||
putreg32(0, RP23XX_CLOCKS_CLK_SYS_RESUS_CTRL);
|
||||
|
|
@ -452,6 +453,13 @@ void rp23xx_clockconfig(void)
|
|||
|
||||
clocks_init();
|
||||
|
||||
/* Configure all TICK blocks */
|
||||
|
||||
for (int i = 0; i < (int)RP23XX_TICK_NUM; ++i)
|
||||
{
|
||||
tick_start(i, (BOARD_REF_FREQ / MHZ));
|
||||
}
|
||||
|
||||
/* Peripheral clocks should now all be running */
|
||||
|
||||
clrbits_reg32(RP23XX_RESETS_RESET_MASK, RP23XX_RESETS_RESET);
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@
|
|||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define RP23XX_TICK_NUM 6 /* Number of TICK blocks */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include <arch/chip/watchdog.h>
|
||||
|
||||
#include <hardware/rp23xx_ticks.h>
|
||||
#include <hardware/rp23xx_watchdog.h>
|
||||
#include <hardware/rp23xx_psm.h>
|
||||
|
||||
|
|
@ -48,33 +49,13 @@
|
|||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define WD_RESETS_BITS (RP23XX_PSM_RESETS \
|
||||
| RP23XX_PSM_CLOCKS \
|
||||
| RP23XX_PSM_PSM_READY \
|
||||
| RP23XX_PSM_BUSFABRIC \
|
||||
| RP23XX_PSM_ROM \
|
||||
| RP23XX_PSM_BOOTRAM \
|
||||
| RP23XX_PSM_SRAM0 \
|
||||
| RP23XX_PSM_SRAM1 \
|
||||
| RP23XX_PSM_SRAM2 \
|
||||
| RP23XX_PSM_SRAM3 \
|
||||
| RP23XX_PSM_SRAM4 \
|
||||
| RP23XX_PSM_SRAM5 \
|
||||
| RP23XX_PSM_SRAM6 \
|
||||
| RP23XX_PSM_SRAM7 \
|
||||
| RP23XX_PSM_SRAM8 \
|
||||
| RP23XX_PSM_SRAM9 \
|
||||
| RP23XX_PSM_XIP \
|
||||
| RP23XX_PSM_SIO \
|
||||
| RP23XX_PSM_ACCESSCTRL \
|
||||
| RP23XX_PSM_PROC0 \
|
||||
| RP23XX_PSM_PROC1)
|
||||
|
||||
#define WD_ENABLE_BITS (RP23XX_WATCHDOG_CTRL_ENABLE \
|
||||
| RP23XX_WATCHDOG_CTRL_PAUSE_DBG0 \
|
||||
| RP23XX_WATCHDOG_CTRL_PAUSE_DBG1 \
|
||||
| RP23XX_WATCHDOG_CTRL_PAUSE_JTAG)
|
||||
|
||||
#define WDT_MAX_TIMEOUT (0xffffff) /* 16777215 ~ 16 sec */
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
|
@ -100,14 +81,14 @@ typedef struct rp23xx_watchdog_lowerhalf_s
|
|||
|
||||
/* "Lower half" driver methods **********************************************/
|
||||
|
||||
static int my_wdt_start (struct watchdog_lowerhalf_s *lower);
|
||||
static int my_wdt_stop (struct watchdog_lowerhalf_s *lower);
|
||||
static int my_wdt_keepalive (struct watchdog_lowerhalf_s *lower);
|
||||
static int my_wdt_getstatus (struct watchdog_lowerhalf_s *lower,
|
||||
static int rp23xx_wdt_start (struct watchdog_lowerhalf_s *lower);
|
||||
static int rp23xx_wdt_stop (struct watchdog_lowerhalf_s *lower);
|
||||
static int rp23xx_wdt_keepalive (struct watchdog_lowerhalf_s *lower);
|
||||
static int rp23xx_wdt_getstatus (struct watchdog_lowerhalf_s *lower,
|
||||
struct watchdog_status_s *status);
|
||||
static int my_wdt_settimeout (struct watchdog_lowerhalf_s *lower,
|
||||
static int rp23xx_wdt_settimeout (struct watchdog_lowerhalf_s *lower,
|
||||
uint32_t timeout);
|
||||
static int my_wdt_ioctl (struct watchdog_lowerhalf_s *lower,
|
||||
static int rp23xx_wdt_ioctl (struct watchdog_lowerhalf_s *lower,
|
||||
int cmd,
|
||||
unsigned long arg);
|
||||
|
||||
|
|
@ -119,13 +100,13 @@ static int my_wdt_ioctl (struct watchdog_lowerhalf_s *lower,
|
|||
|
||||
static const struct watchdog_ops_s g_rp23xx_wdg_ops =
|
||||
{
|
||||
.start = my_wdt_start,
|
||||
.stop = my_wdt_stop,
|
||||
.keepalive = my_wdt_keepalive,
|
||||
.getstatus = my_wdt_getstatus,
|
||||
.settimeout = my_wdt_settimeout,
|
||||
.start = rp23xx_wdt_start,
|
||||
.stop = rp23xx_wdt_stop,
|
||||
.keepalive = rp23xx_wdt_keepalive,
|
||||
.getstatus = rp23xx_wdt_getstatus,
|
||||
.settimeout = rp23xx_wdt_settimeout,
|
||||
.capture = NULL,
|
||||
.ioctl = my_wdt_ioctl,
|
||||
.ioctl = rp23xx_wdt_ioctl,
|
||||
};
|
||||
|
||||
static watchdog_lowerhalf_t g_rp23xx_watchdog_lowerhalf =
|
||||
|
|
@ -138,105 +119,122 @@ static watchdog_lowerhalf_t g_rp23xx_watchdog_lowerhalf =
|
|||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: my_wdt_start
|
||||
* Name: rp23xx_wdt_start
|
||||
****************************************************************************/
|
||||
|
||||
int my_wdt_start(struct watchdog_lowerhalf_s *lower)
|
||||
int rp23xx_wdt_start(struct watchdog_lowerhalf_s *lower)
|
||||
{
|
||||
watchdog_lowerhalf_t *priv = (watchdog_lowerhalf_t *)lower;
|
||||
|
||||
/* Convert millisecond input to microseconds
|
||||
* Extra times 2 per errata RP23XX-E1
|
||||
*/
|
||||
wdinfo("Entry\n");
|
||||
|
||||
putreg32(priv->timeout * 2000, RP23XX_WATCHDOG_LOAD);
|
||||
if (priv->started == true)
|
||||
{
|
||||
/* Return EBUSY to indicate that the timer was already running */
|
||||
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
putreg32(priv->timeout * USEC_PER_MSEC, RP23XX_WATCHDOG_LOAD);
|
||||
|
||||
putreg32(RP23XX_PSM_WDSEL_BITS & ~(RP23XX_PSM_XOSC | RP23XX_PSM_ROSC),
|
||||
RP23XX_PSM_WDSEL);
|
||||
|
||||
modreg32(WD_ENABLE_BITS, WD_ENABLE_BITS, RP23XX_WATCHDOG_CTRL);
|
||||
|
||||
modreg32(WD_RESETS_BITS, WD_RESETS_BITS, RP23XX_PSM_WDSEL);
|
||||
|
||||
priv->started = true;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: my_wdt_stop
|
||||
* Name: rp23xx_wdt_stop
|
||||
****************************************************************************/
|
||||
|
||||
int my_wdt_stop(struct watchdog_lowerhalf_s *lower)
|
||||
{
|
||||
modreg32(0, RP23XX_WATCHDOG_CTRL_ENABLE, RP23XX_WATCHDOG_CTRL);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: my_wdt_keepalive
|
||||
****************************************************************************/
|
||||
|
||||
int my_wdt_keepalive(struct watchdog_lowerhalf_s *lower)
|
||||
int rp23xx_wdt_stop(struct watchdog_lowerhalf_s *lower)
|
||||
{
|
||||
watchdog_lowerhalf_t *priv = (watchdog_lowerhalf_t *)lower;
|
||||
|
||||
/* Convert millisecond input to microseconds
|
||||
* Extra times 2 per errata RP23XX-E1
|
||||
*/
|
||||
wdinfo("Entry\n");
|
||||
|
||||
putreg32(priv->timeout * 2000, RP23XX_WATCHDOG_LOAD);
|
||||
modreg32(0, RP23XX_WATCHDOG_CTRL_ENABLE, RP23XX_WATCHDOG_CTRL);
|
||||
|
||||
priv->started = false;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rp23xx_wdt_keepalive
|
||||
****************************************************************************/
|
||||
|
||||
int rp23xx_wdt_keepalive(struct watchdog_lowerhalf_s *lower)
|
||||
{
|
||||
watchdog_lowerhalf_t *priv = (watchdog_lowerhalf_t *)lower;
|
||||
|
||||
wdinfo("Entry\n");
|
||||
|
||||
putreg32(priv->timeout * USEC_PER_MSEC, RP23XX_WATCHDOG_LOAD);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: my_wdt_getstatus
|
||||
* Name: rp23xx_wdt_getstatus
|
||||
****************************************************************************/
|
||||
|
||||
int my_wdt_getstatus(struct watchdog_lowerhalf_s *lower,
|
||||
int rp23xx_wdt_getstatus(struct watchdog_lowerhalf_s *lower,
|
||||
struct watchdog_status_s *status)
|
||||
{
|
||||
watchdog_lowerhalf_t *priv = (watchdog_lowerhalf_t *)lower;
|
||||
uint32_t ctrl = getreg32(RP23XX_WATCHDOG_CTRL);
|
||||
|
||||
wdinfo("Entry\n");
|
||||
|
||||
status->flags = (ctrl & RP23XX_WATCHDOG_CTRL_ENABLE) ? WDFLAGS_ACTIVE
|
||||
: 0;
|
||||
|
||||
status->timeout = priv->timeout;
|
||||
|
||||
/* Convert microseconds to output microseconds.
|
||||
* Extra divide by 2 per errata RP23XX-E1.
|
||||
*/
|
||||
|
||||
status->timeleft = (ctrl & RP23XX_WATCHDOG_CTRL_TIME_MASK) / 2000;
|
||||
|
||||
/* WARNING: On (at least) version 2 RP23XX chips, the timeleft does
|
||||
* not seem to be reliable.
|
||||
*/
|
||||
|
||||
status->timeleft = (ctrl & RP23XX_WATCHDOG_CTRL_TIME_MASK) /
|
||||
USEC_PER_MSEC;
|
||||
wdinfo("Status :\n");
|
||||
wdinfo(" flags : %08" PRIx32 "\n", status->flags);
|
||||
wdinfo(" timeout : %" PRId32 "\n", status->timeout);
|
||||
wdinfo(" timeleft : %" PRId32 "\n", status->timeleft);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: my_wdt_settimeout
|
||||
* Name: rp23xx_wdt_settimeout
|
||||
****************************************************************************/
|
||||
|
||||
int my_wdt_settimeout (struct watchdog_lowerhalf_s *lower, uint32_t timeout)
|
||||
int rp23xx_wdt_settimeout (struct watchdog_lowerhalf_s *lower,
|
||||
uint32_t timeout)
|
||||
{
|
||||
watchdog_lowerhalf_t *priv = (watchdog_lowerhalf_t *)lower;
|
||||
|
||||
priv->timeout = timeout > (0x7fffff / 1000) ? 0x7fffff : timeout;
|
||||
wdinfo("Entry: timeout=%" PRId32 "\n", timeout);
|
||||
|
||||
/* Convert millisecond input to microseconds
|
||||
* Extra times 2 per errata RP23XX-E1
|
||||
if ((timeout == 0) || (timeout > (WDT_MAX_TIMEOUT / USEC_PER_MSEC)))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Load the watchdog timer. The maximum setting is 0xffffff which
|
||||
* corresponds to approximately 16 seconds
|
||||
*/
|
||||
|
||||
putreg32(priv->timeout * 2000, RP23XX_WATCHDOG_LOAD);
|
||||
priv->timeout = timeout;
|
||||
|
||||
putreg32(priv->timeout * USEC_PER_MSEC, RP23XX_WATCHDOG_LOAD);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: my_wdt_ioctl
|
||||
* Name: rp23xx_wdt_ioctl
|
||||
****************************************************************************/
|
||||
|
||||
int my_wdt_ioctl(struct watchdog_lowerhalf_s *lower,
|
||||
int rp23xx_wdt_ioctl(struct watchdog_lowerhalf_s *lower,
|
||||
int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
|
|
@ -282,6 +280,7 @@ int rp23xx_wdt_init(void)
|
|||
goto errout;
|
||||
}
|
||||
|
||||
putreg32(WDT_MAX_TIMEOUT, RP23XX_WATCHDOG_LOAD);
|
||||
modreg32(0, RP23XX_WATCHDOG_CTRL_ENABLE, RP23XX_WATCHDOG_CTRL);
|
||||
|
||||
errout:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue