diff --git a/arch/arm/src/rp23xx/hardware/rp23xx_psm.h b/arch/arm/src/rp23xx/hardware/rp23xx_psm.h index 37b17d00fa..489b6cb129 100644 --- a/arch/arm/src/rp23xx/hardware/rp23xx_psm.h +++ b/arch/arm/src/rp23xx/hardware/rp23xx_psm.h @@ -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 */ diff --git a/arch/arm/src/rp23xx/hardware/rp23xx_ticks.h b/arch/arm/src/rp23xx/hardware/rp23xx_ticks.h new file mode 100644 index 0000000000..838799fdf3 --- /dev/null +++ b/arch/arm/src/rp23xx/hardware/rp23xx_ticks.h @@ -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 */ diff --git a/arch/arm/src/rp23xx/rp23xx_clock.c b/arch/arm/src/rp23xx/rp23xx_clock.c index 71fc46cddb..1dbd440cfe 100644 --- a/arch/arm/src/rp23xx/rp23xx_clock.c +++ b/arch/arm/src/rp23xx/rp23xx_clock.c @@ -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); diff --git a/arch/arm/src/rp23xx/rp23xx_clock.h b/arch/arm/src/rp23xx/rp23xx_clock.h index 179a341de6..0ec9a4e2d4 100644 --- a/arch/arm/src/rp23xx/rp23xx_clock.h +++ b/arch/arm/src/rp23xx/rp23xx_clock.h @@ -33,6 +33,8 @@ * Pre-processor Definitions ****************************************************************************/ +#define RP23XX_TICK_NUM 6 /* Number of TICK blocks */ + /**************************************************************************** * Public Types ****************************************************************************/ diff --git a/arch/arm/src/rp23xx/rp23xx_wdt.c b/arch/arm/src/rp23xx/rp23xx_wdt.c index 37cfead5bf..7273026af5 100644 --- a/arch/arm/src/rp23xx/rp23xx_wdt.c +++ b/arch/arm/src/rp23xx/rp23xx_wdt.c @@ -35,6 +35,7 @@ #include +#include #include #include @@ -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: