diff --git a/Documentation/platforms/risc-v/bl808/boards/ox64/index.rst b/Documentation/platforms/risc-v/bl808/boards/ox64/index.rst index 85d245ce7d..70e5fa48f3 100644 --- a/Documentation/platforms/risc-v/bl808/boards/ox64/index.rst +++ b/Documentation/platforms/risc-v/bl808/boards/ox64/index.rst @@ -150,3 +150,9 @@ spi This configuration enables support for SPI0 and spitool. By default, GPIO14 is MISO, 13 is MOSI, 15 is SCLK and 12 is SS. Serial Console is enabled on UART3 at 2 Mbps. + +timer +----- + +This configuration enables support for hardware timers and the timer example app. +Serial Console is enabled on UART3 at 2 Mbps. diff --git a/Documentation/platforms/risc-v/bl808/index.rst b/Documentation/platforms/risc-v/bl808/index.rst index f8f9d95d44..c7c68bdbcf 100644 --- a/Documentation/platforms/risc-v/bl808/index.rst +++ b/Documentation/platforms/risc-v/bl808/index.rst @@ -52,7 +52,7 @@ I2C No I2S No PWM No SPI Yes -Timers No +Timers Yes UART Yes USB No =========== ======= ==================== diff --git a/arch/risc-v/include/bl808/irq.h b/arch/risc-v/include/bl808/irq.h index 0b743f1063..752832bfcd 100644 --- a/arch/risc-v/include/bl808/irq.h +++ b/arch/risc-v/include/bl808/irq.h @@ -54,6 +54,8 @@ #define BL808_IRQ_UART3 (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + 4) #define BL808_IRQ_SPI1 (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + 7) #define BL808_IRQ_D0_IPC (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + 38) +#define BL808_IRQ_TIMER1_CH0 (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + 61) +#define BL808_IRQ_TIMER1_CH1 (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + 62) #define BL808_IRQ_M0IC (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + 65) /* M0 IRQs ******************************************************************/ @@ -63,5 +65,7 @@ #define BL808_IRQ_UART0 (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + BL808_M0_IRQ_OFFSET + 28) #define BL808_IRQ_UART1 (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + BL808_M0_IRQ_OFFSET + 29) #define BL808_IRQ_UART2 (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + BL808_M0_IRQ_OFFSET + 30) +#define BL808_IRQ_TIMER0_CH0 (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + BL808_M0_IRQ_OFFSET + 36) +#define BL808_IRQ_TIMER0_CH1 (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + BL808_M0_IRQ_OFFSET + 37) #endif /* __ARCH_RISCV_INCLUDE_BL808_IRQ_H */ diff --git a/arch/risc-v/src/bl808/Kconfig b/arch/risc-v/src/bl808/Kconfig index 0156783813..d534dedfc0 100644 --- a/arch/risc-v/src/bl808/Kconfig +++ b/arch/risc-v/src/bl808/Kconfig @@ -224,4 +224,9 @@ config BL808_SPI1_SS endif +config BL808_TIMERS + bool "Timers" + default n + select TIMER + endmenu diff --git a/arch/risc-v/src/bl808/Make.defs b/arch/risc-v/src/bl808/Make.defs index ffb276ace9..308c0e7603 100644 --- a/arch/risc-v/src/bl808/Make.defs +++ b/arch/risc-v/src/bl808/Make.defs @@ -28,4 +28,4 @@ HEAD_ASRC = bl808_head.S CHIP_CSRCS = bl808_start.c bl808_irq_dispatch.c bl808_irq.c CHIP_CSRCS += bl808_timerisr.c bl808_allocateheap.c CHIP_CSRCS += bl808_gpio.c bl808_mm_init.c bl808_pgalloc.c bl808_serial.c -CHIP_CSRCS += bl808_gpadc.c bl808_spi.c +CHIP_CSRCS += bl808_gpadc.c bl808_spi.c bl808_timer.c diff --git a/arch/risc-v/src/bl808/bl808_timer.c b/arch/risc-v/src/bl808/bl808_timer.c new file mode 100644 index 0000000000..9a666a456f --- /dev/null +++ b/arch/risc-v/src/bl808/bl808_timer.c @@ -0,0 +1,549 @@ +/**************************************************************************** + * arch/risc-v/src/bl808/bl808_timer.c + * + * 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "hardware/bl808_timer.h" +#include "riscv_internal.h" +#include "chip.h" +#include "bl808_timer.h" + +#ifdef CONFIG_BL808_TIMERS + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define TIMER_GET_BLK(n) (n >= 2) +#define TIMER_GET_CH(n) (n % 2) + +#define TIMER_CLK_SRC_XTAL 3 +#define TIMER_CLK_SRC_NONE 5 + +#define XCLK_DIV 39 /* XCLK is 40 MHz, so divide by 40 */ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +enum bl808_timer_ch_e + { + TIMER0_CH0 = 0, + TIMER0_CH1 = 1, + TIMER1_CH0 = 2, + TIMER1_CH1 = 3 + }; + +struct bl808_timer_ch_s +{ + const struct timer_ops_s *ops; + enum bl808_timer_ch_e blk_ch; + tccb_t callback; + void *arg; + bool started; + uint32_t timeout; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +int bl808_timer_start(FAR struct timer_lowerhalf_s *lower); +int bl808_timer_stop(FAR struct timer_lowerhalf_s *lower); +int bl808_timer_getstatus(FAR struct timer_lowerhalf_s *lower, + FAR struct timer_status_s *status); +int bl808_timer_settimeout(FAR struct timer_lowerhalf_s *lower, + uint32_t timeout); +void bl808_timer_setcallback(FAR struct timer_lowerhalf_s *lower, + CODE tccb_t callback, FAR void *arg); +int bl808_timer_ioctl(FAR struct timer_lowerhalf_s *lower, + int cmd, unsigned long arg); +int bl808_timer_maxtimeout(FAR struct timer_lowerhalf_s *lower, + FAR uint32_t *maxtimeout); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct timer_ops_s bl808_timer_ops = + { + .start = bl808_timer_start, + .stop = bl808_timer_stop, + .getstatus = bl808_timer_getstatus, + .settimeout = bl808_timer_settimeout, + .setcallback = bl808_timer_setcallback, + .ioctl = bl808_timer_ioctl, + .maxtimeout = bl808_timer_maxtimeout + }; + +static struct bl808_timer_ch_s timer0_ch0 = + { + .ops = &bl808_timer_ops, + .blk_ch = TIMER0_CH0, + .callback = NULL, + .arg = NULL, + .started = false, + .timeout = 0 + }; + +static struct bl808_timer_ch_s timer0_ch1 = + { + .ops = &bl808_timer_ops, + .blk_ch = TIMER0_CH1, + .callback = NULL, + .arg = NULL, + .started = false, + .timeout = 0 + }; + +static struct bl808_timer_ch_s timer1_ch0 = + { + .ops = &bl808_timer_ops, + .blk_ch = TIMER1_CH0, + .callback = NULL, + .arg = NULL, + .started = false, + .timeout = 0 + }; + +static struct bl808_timer_ch_s timer1_ch1 = + { + .ops = &bl808_timer_ops, + .blk_ch = TIMER1_CH1, + .callback = NULL, + .arg = NULL, + .started = false, + .timeout = 0 + }; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: timer_interrupt + * + * Description: + * Timer interrupt handler. Clears the interrupt and + * Calls the attached callback if there is one. + * + ****************************************************************************/ + +static int __timer_interrupt(int irq, void *context, void *arg) +{ + struct bl808_timer_ch_s *priv = (struct bl808_timer_ch_s *)arg; + uint32_t next_interval = 0; + + /* Clear IRQ */ + + switch (irq) + { + case BL808_IRQ_TIMER0_CH0: + modifyreg32(BL808_TIMER_CH0_ICLR(0), 0, TIMER_COMP0_INT); + break; + + case BL808_IRQ_TIMER0_CH1: + modifyreg32(BL808_TIMER_CH1_ICLR(0), 0, TIMER_COMP0_INT); + break; + + case BL808_IRQ_TIMER1_CH0: + modifyreg32(BL808_TIMER_CH0_ICLR(1), 0, TIMER_COMP0_INT); + break; + + case BL808_IRQ_TIMER1_CH1: + modifyreg32(BL808_TIMER_CH1_ICLR(1), 0, TIMER_COMP0_INT); + break; + + default: + return -EIO; + } + + if (priv->callback != NULL) + { + if (priv->callback(&next_interval, priv->arg)) + { + if (next_interval > 0) + { + bl808_timer_settimeout((struct timer_lowerhalf_s *)priv, + next_interval); + } + + bl808_timer_start((struct timer_lowerhalf_s *)priv); + } + } + + return OK; +} + +/**************************************************************************** + * Name: bl808_timer_start + * + * Description: + * Reset the time to the current timeout and start the timer. + * + ****************************************************************************/ + +int bl808_timer_start(FAR struct timer_lowerhalf_s *lower) +{ + struct bl808_timer_ch_s *priv = (struct bl808_timer_ch_s *)lower; + if (TIMER_GET_CH(priv->blk_ch) == 0) + { + modifyreg32(BL808_TIMER_TCCR(TIMER_GET_BLK(priv->blk_ch)), + TIMER_CH0_CLKSEL_MASK, + TIMER_CLK_SRC_XTAL << TIMER_CH0_CLKSEL_SHIFT); + + /* Clear timer */ + + modifyreg32(BL808_TIMER_EN_CLR(TIMER_GET_BLK(priv->blk_ch)), + 0, TIMER_CH0_CLR); + + /* Wait for the counter to clear */ + + while (getreg32(BL808_TIMER_CH0_COUNTER(TIMER_GET_BLK(priv->blk_ch))) + != 0); + + modifyreg32(BL808_TIMER_EN_CLR(TIMER_GET_BLK(priv->blk_ch)), + TIMER_CH0_CLR, 0); + } + else /* Channel 1 */ + { + modifyreg32(BL808_TIMER_TCCR(TIMER_GET_BLK(priv->blk_ch)), + TIMER_CH1_CLKSEL_MASK, + TIMER_CLK_SRC_XTAL << TIMER_CH1_CLKSEL_SHIFT); + + /* Clear timer */ + + modifyreg32(BL808_TIMER_EN_CLR(TIMER_GET_BLK(priv->blk_ch)), + 0, TIMER_CH1_CLR); + + /* Wait for the counter to clear */ + + while (getreg32(BL808_TIMER_CH1_COUNTER(TIMER_GET_BLK(priv->blk_ch))) + != 0); + + modifyreg32(BL808_TIMER_EN_CLR(TIMER_GET_BLK(priv->blk_ch)), + TIMER_CH1_CLR, 0); + } + + priv->started = true; + return OK; +} + +/**************************************************************************** + * Name: bl808_timer_stop + * + * Description: + * Stop the timer. + * + ****************************************************************************/ + +int bl808_timer_stop(FAR struct timer_lowerhalf_s *lower) +{ + struct bl808_timer_ch_s *priv = (struct bl808_timer_ch_s *)lower; + + /* Timers are stopped by setting the input clock to NONE. + * This is done to allow calling timer_stop and then get + * the time left to timeout afterwards. If we used the + * timer enable bits, the counter would reset to 0 when stopped. + */ + + if (TIMER_GET_CH(priv->blk_ch) == 0) + { + modifyreg32(BL808_TIMER_TCCR(TIMER_GET_BLK(priv->blk_ch)), + TIMER_CH0_CLKSEL_MASK, + TIMER_CLK_SRC_NONE << TIMER_CH0_CLKSEL_SHIFT); + } + else + { + modifyreg32(BL808_TIMER_TCCR(TIMER_GET_BLK(priv->blk_ch)), + TIMER_CH0_CLKSEL_MASK, + TIMER_CLK_SRC_NONE << TIMER_CH1_CLKSEL_SHIFT); + } + + priv->started = false; + return OK; +} + +/**************************************************************************** + * Name: bl808_timer_getstatus + * + * Description: + * Get current timer status. Returns to status parameter. + * + ****************************************************************************/ + +int bl808_timer_getstatus(FAR struct timer_lowerhalf_s *lower, + FAR struct timer_status_s *status) +{ + struct bl808_timer_ch_s *priv = (struct bl808_timer_ch_s *)lower; + uint32_t current_count; + + status->flags = priv->started + | ((priv->callback != NULL) << 1); + status->timeout = priv->timeout; + + if (TIMER_GET_CH(priv->blk_ch) == 0) + { + current_count = + getreg32(BL808_TIMER_CH0_COUNTER(TIMER_GET_BLK(priv->blk_ch))); + } + else + { + current_count = + getreg32(BL808_TIMER_CH1_COUNTER(TIMER_GET_BLK(priv->blk_ch))); + } + + status->timeleft = priv->timeout - current_count; + + return OK; +} + +/**************************************************************************** + * Name: bl808_timer_settimeout + * + * Description: + * Set a new timeout value and reset the timer. + * + ****************************************************************************/ + +int bl808_timer_settimeout(FAR struct timer_lowerhalf_s *lower, + uint32_t timeout) +{ + struct bl808_timer_ch_s *priv = (struct bl808_timer_ch_s *)lower; + if (TIMER_GET_CH(priv->blk_ch) == 0) + { + modifyreg32(BL808_TIMER_CH0_COMP0(TIMER_GET_BLK(priv->blk_ch)), + 0xffffffff, timeout); + priv->timeout = timeout; + + /* Clock is needed to clear counters */ + + modifyreg32(BL808_TIMER_TCCR(TIMER_GET_BLK(priv->blk_ch)), + TIMER_CH0_CLKSEL_MASK, + TIMER_CLK_SRC_XTAL << TIMER_CH0_CLKSEL_SHIFT); + + modifyreg32(BL808_TIMER_EN_CLR(TIMER_GET_BLK(priv->blk_ch)), + 0, TIMER_CH0_CLR); + + while (getreg32(BL808_TIMER_CH0_COUNTER(TIMER_GET_BLK(priv->blk_ch))) + != 0); + + /* Disable clock to stop timer from running after clear */ + + modifyreg32(BL808_TIMER_TCCR(TIMER_GET_BLK(priv->blk_ch)), + TIMER_CH0_CLKSEL_MASK, + TIMER_CLK_SRC_NONE << TIMER_CH0_CLKSEL_SHIFT); + + modifyreg32(BL808_TIMER_EN_CLR(TIMER_GET_BLK(priv->blk_ch)), + TIMER_CH0_CLR, 0); + } + else + { + modifyreg32(BL808_TIMER_CH1_COMP0(TIMER_GET_BLK(priv->blk_ch)), + 0xffffffff, timeout); + priv->timeout = timeout; + + /* Clock is needed to clear counters */ + + modifyreg32(BL808_TIMER_TCCR(TIMER_GET_BLK(priv->blk_ch)), + TIMER_CH1_CLKSEL_MASK, + TIMER_CLK_SRC_XTAL << TIMER_CH1_CLKSEL_SHIFT); + + modifyreg32(BL808_TIMER_EN_CLR(TIMER_GET_BLK(priv->blk_ch)), + 0, TIMER_CH1_CLR); + + while (getreg32(BL808_TIMER_CH1_COUNTER(TIMER_GET_BLK(priv->blk_ch))) + != 0); + + /* Disable clock to stop timer from running after clear */ + + modifyreg32(BL808_TIMER_TCCR(TIMER_GET_BLK(priv->blk_ch)), + TIMER_CH1_CLKSEL_MASK, + TIMER_CLK_SRC_NONE << TIMER_CH1_CLKSEL_SHIFT); + + modifyreg32(BL808_TIMER_EN_CLR(TIMER_GET_BLK(priv->blk_ch)), + TIMER_CH1_CLR, 0); + } + + return OK; +} + +/**************************************************************************** + * Name: bl808_timer_setcallback + * + * Description: + * Sets a new callback to be run on timeout. + * + ****************************************************************************/ + +void bl808_timer_setcallback(FAR struct timer_lowerhalf_s *lower, + CODE tccb_t callback, FAR void *arg) +{ + struct bl808_timer_ch_s *priv = (struct bl808_timer_ch_s *)lower; + priv->callback = callback; + priv->arg = arg; +} + +/**************************************************************************** + * Name: bl808_timer_ioctl + * + * Description: + * Handle ioctl commands not recognized by upper-half. + * + ****************************************************************************/ + +int bl808_timer_ioctl(FAR struct timer_lowerhalf_s *lower, + int cmd, unsigned long arg) +{ + /* No additional ioctl commands implemented */ + + return -EIO; +} + +/**************************************************************************** + * Name: bl808_timer_maxtimeout + * + * Description: + * Return the maximum allowed timeout value. + * Returns to maxtimeout parameter. + * + ****************************************************************************/ + +int bl808_timer_maxtimeout(FAR struct timer_lowerhalf_s *lower, + FAR uint32_t *maxtimeout) +{ + /* Timer comparators are 32-bit */ + + *maxtimeout = 0xffffffff; + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int bl808_timer_init(void) +{ + int ret = OK; + + /* The registered devpaths follow the recommended naming + * convention, i.e. timer0, timer1, etc. The order chosen + * for the numbering is the same as for bl808_timer_ch_e. + */ + + /* Timer 0, channel 0 */ + + modifyreg32(BL808_TIMER_TCCR(0), TIMER_CH0_CLKSEL_MASK, + TIMER_CLK_SRC_NONE << TIMER_CH0_CLKSEL_SHIFT); + modifyreg32(BL808_TIMER_CH0_IE(0), 0, TIMER_COMP0_INT); + modifyreg32(BL808_TIMER_DIV(0), TIMER_CH0_DIV_MASK, + (XCLK_DIV << TIMER_CH0_DIV_SHIFT)); + modifyreg32(BL808_TIMER_MODE(0), 0, TIMER_CH0_MODE); + modifyreg32(BL808_TIMER_EN_CLR(0), 0, TIMER_CH0_EN); + ret |= irq_attach(BL808_IRQ_TIMER0_CH0, __timer_interrupt, + (void *)&timer0_ch0); + if (ret == OK) + { + up_enable_irq(BL808_IRQ_TIMER0_CH0); + } + + timer_register("/dev/timer0", + (struct timer_lowerhalf_s *)&timer0_ch0); + + /* Timer 0, channel 1 */ + + modifyreg32(BL808_TIMER_TCCR(0), TIMER_CH1_CLKSEL_MASK, + TIMER_CLK_SRC_NONE << TIMER_CH1_CLKSEL_SHIFT); + modifyreg32(BL808_TIMER_CH1_IE(0), 0, TIMER_COMP0_INT); + modifyreg32(BL808_TIMER_DIV(0), TIMER_CH1_DIV_MASK, + (XCLK_DIV << TIMER_CH1_DIV_SHIFT)); + modifyreg32(BL808_TIMER_MODE(0), 0, TIMER_CH1_MODE); + modifyreg32(BL808_TIMER_EN_CLR(0), 0, TIMER_CH1_EN); + ret |= irq_attach(BL808_IRQ_TIMER0_CH1, __timer_interrupt, + (void *)&timer0_ch1); + if (ret == OK) + { + up_enable_irq(BL808_IRQ_TIMER0_CH1); + } + + timer_register("/dev/timer1", + (struct timer_lowerhalf_s *)&timer0_ch1); + + /* Timer 1, channel 0 */ + + modifyreg32(BL808_TIMER_TCCR(1), TIMER_CH0_CLKSEL_MASK, + TIMER_CLK_SRC_NONE << TIMER_CH0_CLKSEL_SHIFT); + modifyreg32(BL808_TIMER_CH0_IE(1), 0, TIMER_COMP0_INT); + modifyreg32(BL808_TIMER_DIV(1), TIMER_CH0_DIV_MASK, + (XCLK_DIV << TIMER_CH0_DIV_SHIFT)); + modifyreg32(BL808_TIMER_MODE(1), 0, TIMER_CH0_MODE); + modifyreg32(BL808_TIMER_EN_CLR(1), 0, TIMER_CH0_EN); + ret |= irq_attach(BL808_IRQ_TIMER1_CH0, __timer_interrupt, + (void *)&timer1_ch0); + if (ret == OK) + { + up_enable_irq(BL808_IRQ_TIMER1_CH0); + } + + timer_register("/dev/timer2", + (struct timer_lowerhalf_s *)&timer1_ch0); + + /* Timer 1, channel 1 */ + + modifyreg32(BL808_TIMER_TCCR(1), TIMER_CH1_CLKSEL_MASK, + TIMER_CLK_SRC_NONE << TIMER_CH1_CLKSEL_SHIFT); + modifyreg32(BL808_TIMER_CH1_IE(1), 0, TIMER_COMP0_INT); + modifyreg32(BL808_TIMER_DIV(1), TIMER_CH1_DIV_MASK, + (XCLK_DIV << TIMER_CH1_DIV_SHIFT)); + modifyreg32(BL808_TIMER_MODE(1), 0, TIMER_CH1_MODE); + modifyreg32(BL808_TIMER_EN_CLR(1), 0, TIMER_CH1_EN); + ret |= irq_attach(BL808_IRQ_TIMER1_CH1, __timer_interrupt, + (void *)&timer1_ch1); + if (ret == OK) + { + up_enable_irq(BL808_IRQ_TIMER1_CH1); + } + + timer_register("/dev/timer3", + (struct timer_lowerhalf_s *)&timer1_ch1); + + return ret; +} + +#endif /* CONFIG_BL808_TIMERS */ diff --git a/arch/risc-v/src/bl808/bl808_timer.h b/arch/risc-v/src/bl808/bl808_timer.h new file mode 100644 index 0000000000..6c7f5cfb1a --- /dev/null +++ b/arch/risc-v/src/bl808/bl808_timer.h @@ -0,0 +1,39 @@ +/**************************************************************************** + * arch/risc-v/src/bl808/bl808_timer.h + * + * 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_RISC_V_SRC_BL808_BL808_TIMER_H +#define __ARCH_RISC_V_SRC_BL808_BL808_TIMER_H + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: bl808_timer_init + * + * Description: + * Initialize timer hardware and register character drivers + * for enabled timer channels. + * + ****************************************************************************/ + +int bl808_timer_init(void); + +#endif /* __ARCH_RISC_V_SRC_BL808_BL808_TIMER_H */ diff --git a/arch/risc-v/src/bl808/hardware/bl808_memorymap.h b/arch/risc-v/src/bl808/hardware/bl808_memorymap.h index aaff526633..397e0809ea 100644 --- a/arch/risc-v/src/bl808/hardware/bl808_memorymap.h +++ b/arch/risc-v/src/bl808/hardware/bl808_memorymap.h @@ -34,11 +34,13 @@ #define BL808_UART0_BASE 0x2000a000ul #define BL808_UART1_BASE 0x2000a100ul #define BL808_SPI0_BASE 0x2000a200ul +#define BL808_TIMER0_BASE 0x2000a500ul #define BL808_UART2_BASE 0x2000aa00ul #define BL808_AON_BASE 0x2000f000ul #define BL808_UART3_BASE 0x30002000ul #define BL808_MM_GLB_BASE 0x30007000ul #define BL808_SPI1_BASE 0x30008000ul +#define BL808_TIMER1_BASE 0x30009000ul #define BL808_PLIC_BASE 0xe0000000ul #endif /* __ARCH_RISCV_SRC_BL808_HARDWARE_BL808_MEMORYMAP_H */ diff --git a/arch/risc-v/src/bl808/hardware/bl808_timer.h b/arch/risc-v/src/bl808/hardware/bl808_timer.h new file mode 100644 index 0000000000..01f342e9c6 --- /dev/null +++ b/arch/risc-v/src/bl808/hardware/bl808_timer.h @@ -0,0 +1,100 @@ +/**************************************************************************** + * arch/risc-v/src/bl808/hardware/bl808_timer.h + * + * 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_RISCV_SRC_BL808_HARDWARE_BL808_TIMER_H +#define __ARCH_RISCV_SRC_BL808_HARDWARE_BL808_TIMER_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "bl808_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define BL808_TIMER_BASE(n) ((n == 0) ? BL808_TIMER0_BASE \ + : BL808_TIMER1_BASE) + +/* Register offsets *********************************************************/ + +#define BL808_TIMER_TCCR_OFFSET 0x00 +#define BL808_TIMER_CH0_COMP0_OFFSET 0x10 +#define BL808_TIMER_CH1_COMP0_OFFSET 0x1c +#define BL808_TIMER_CH0_COUNTER_OFFSET 0x2c +#define BL808_TIMER_CH1_COUNTER_OFFSET 0x30 +#define BL808_TIMER_CH0_IE_OFFSET 0x44 +#define BL808_TIMER_CH1_IE_OFFSET 0x48 +#define BL808_TIMER_CH0_ICLR_OFFSET 0x78 +#define BL808_TIMER_CH1_ICLR_OFFSET 0x7c +#define BL808_TIMER_EN_CLR_OFFSET 0x84 +#define BL808_TIMER_MODE_OFFSET 0x88 +#define BL808_TIMER_DIV_OFFSET 0xBC + +/* Register definitions *****************************************************/ + +#define BL808_TIMER_TCCR(n) (BL808_TIMER_BASE(n) + BL808_TIMER_TCCR_OFFSET) +#define BL808_TIMER_CH0_COMP0(n) (BL808_TIMER_BASE(n) + BL808_TIMER_CH0_COMP0_OFFSET) +#define BL808_TIMER_CH1_COMP0(n) (BL808_TIMER_BASE(n) + BL808_TIMER_CH1_COMP0_OFFSET) +#define BL808_TIMER_CH0_COUNTER(n) (BL808_TIMER_BASE(n) + BL808_TIMER_CH0_COUNTER_OFFSET) +#define BL808_TIMER_CH1_COUNTER(n) (BL808_TIMER_BASE(n) + BL808_TIMER_CH1_COUNTER_OFFSET) +#define BL808_TIMER_CH0_IE(n) (BL808_TIMER_BASE(n) + BL808_TIMER_CH0_IE_OFFSET) +#define BL808_TIMER_CH1_IE(n) (BL808_TIMER_BASE(n) + BL808_TIMER_CH1_IE_OFFSET) +#define BL808_TIMER_CH0_ICLR(n) (BL808_TIMER_BASE(n) + BL808_TIMER_CH0_ICLR_OFFSET) +#define BL808_TIMER_CH1_ICLR(n) (BL808_TIMER_BASE(n) + BL808_TIMER_CH1_ICLR_OFFSET) +#define BL808_TIMER_EN_CLR(n) (BL808_TIMER_BASE(n) + BL808_TIMER_EN_CLR_OFFSET) +#define BL808_TIMER_MODE(n) (BL808_TIMER_BASE(n) + BL808_TIMER_MODE_OFFSET) +#define BL808_TIMER_DIV(n) (BL808_TIMER_BASE(n) + BL808_TIMER_DIV_OFFSET) + +/* Register bit definitions *************************************************/ + +/* TIMER_TCCR */ + +#define TIMER_CH0_CLKSEL_SHIFT (0) +#define TIMER_CH0_CLKSEL_MASK (0xf << TIMER_CH0_CLKSEL_SHIFT) +#define TIMER_CH1_CLKSEL_SHIFT (4) +#define TIMER_CH1_CLKSEL_MASK (0xf << TIMER_CH1_CLKSEL_SHIFT) + +/* TIMER_CH(0/1)_I(E/CLR) */ + +#define TIMER_COMP0_INT (1 << 0) + +/* TIMER_EN_CLR */ + +#define TIMER_CH0_EN (1 << 1) +#define TIMER_CH1_EN (1 << 2) +#define TIMER_CH0_CLR (1 << 5) +#define TIMER_CH1_CLR (1 << 6) + +/* TIMER_MODE */ + +#define TIMER_CH0_MODE (1 << 1) +#define TIMER_CH1_MODE (1 << 2) + +/* TIMER_DIV */ + +#define TIMER_CH0_DIV_SHIFT (8) +#define TIMER_CH0_DIV_MASK (0xff << TIMER_CH0_DIV_SHIFT) +#define TIMER_CH1_DIV_SHIFT (16) +#define TIMER_CH1_DIV_MASK (0xff << TIMER_CH1_DIV_SHIFT) + +#endif /* __ARCH_RISCV_SRC_BL808_HARDWARE_BL808_TIMER_H */ diff --git a/boards/risc-v/bl808/ox64/configs/timer/defconfig b/boards/risc-v/bl808/ox64/configs/timer/defconfig new file mode 100644 index 0000000000..351387af2e --- /dev/null +++ b/boards/risc-v/bl808/ox64/configs/timer/defconfig @@ -0,0 +1,100 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_DISABLE_OS_API is not set +# CONFIG_NSH_DISABLE_LOSMART is not set +# CONFIG_STANDARD_SERIAL is not set +CONFIG_ARCH="risc-v" +CONFIG_ARCH_ADDRENV=y +CONFIG_ARCH_BOARD="ox64" +CONFIG_ARCH_BOARD_BL808_OX64=y +CONFIG_ARCH_CHIP="bl808" +CONFIG_ARCH_CHIP_BL808=y +CONFIG_ARCH_DATA_NPAGES=128 +CONFIG_ARCH_DATA_VBASE=0x80100000 +CONFIG_ARCH_HEAP_NPAGES=128 +CONFIG_ARCH_HEAP_VBASE=0x80200000 +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_KERNEL_STACKSIZE=3072 +CONFIG_ARCH_PGPOOL_MAPPING=y +CONFIG_ARCH_PGPOOL_PBASE=0x50600000 +CONFIG_ARCH_PGPOOL_SIZE=4194304 +CONFIG_ARCH_PGPOOL_VBASE=0x50600000 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARCH_TEXT_NPAGES=128 +CONFIG_ARCH_TEXT_VBASE=0x80000000 +CONFIG_ARCH_USE_MMU=y +CONFIG_ARCH_USE_MPU=y +CONFIG_ARCH_USE_S_MODE=y +CONFIG_BL808_TIMERS=y +CONFIG_BL808_UART0=y +CONFIG_BL808_UART1=y +CONFIG_BL808_UART2=y +CONFIG_BL808_UART3=y +CONFIG_BOARDCTL_ROMDISK=y +CONFIG_BOARD_LATE_INITIALIZE=y +CONFIG_BOARD_LOOPSPERMSEC=1120 +CONFIG_BUILD_KERNEL=y +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_ASSERTIONS_EXPRESSION=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEV_ZERO=y +CONFIG_ELF=y +CONFIG_EXAMPLES_HELLO=m +CONFIG_EXAMPLES_TIMER=y +CONFIG_FS_PROCFS=y +CONFIG_FS_ROMFS=y +CONFIG_IDLETHREAD_STACKSIZE=3072 +CONFIG_INIT_FILEPATH="/system/bin/init" +CONFIG_INIT_MOUNT=y +CONFIG_INIT_MOUNT_FLAGS=0x1 +CONFIG_INIT_MOUNT_TARGET="/system/bin" +CONFIG_INIT_STACKSIZE=3072 +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_ENVPATH=y +CONFIG_LIBC_EXECFUNCS=y +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_MEMSET_64BIT=y +CONFIG_MEMSET_OPTSPEED=y +CONFIG_MM_PGALLOC=y +CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_FILE_APPS=y +CONFIG_NSH_READLINE=y +CONFIG_PATH_INITIAL="/system/bin" +CONFIG_RAM_SIZE=1048576 +CONFIG_RAM_START=0x50200000 +CONFIG_READLINE_CMD_HISTORY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HAVE_PARENT=y +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_STACK_COLORATION=y +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2021 +CONFIG_SYMTAB_ORDEREDBYNAME=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_NSH_PROGNAME="init" +CONFIG_TESTING_GETPRIME=y +CONFIG_TESTING_OSTEST=y +CONFIG_UART0_BAUD=2000000 +CONFIG_UART0_BITS=7 +CONFIG_UART1_BAUD=2000000 +CONFIG_UART1_BITS=7 +CONFIG_UART2_BAUD=2000000 +CONFIG_UART2_BITS=7 +CONFIG_UART3_BAUD=2000000 +CONFIG_UART3_BITS=7 +CONFIG_UART3_SERIAL_CONSOLE=y +CONFIG_USEC_PER_TICK=1000 +CONFIG_USERLED=y +CONFIG_USERLED_LOWER=y diff --git a/boards/risc-v/bl808/ox64/src/bl808_appinit.c b/boards/risc-v/bl808/ox64/src/bl808_appinit.c index 9f0305bcbd..7236b5e598 100644 --- a/boards/risc-v/bl808/ox64/src/bl808_appinit.c +++ b/boards/risc-v/bl808/ox64/src/bl808_appinit.c @@ -41,6 +41,9 @@ #if defined(CONFIG_BL808_SPI0) || defined(CONFIG_BL808_SPI1) #include "bl808_spi.h" #endif +#ifdef CONFIG_BL808_TIMERS +#include "bl808_timer.h" +#endif #include "bl808_gpadc.h" /**************************************************************************** @@ -168,9 +171,7 @@ void board_late_initialize(void) /* Perform board-specific initialization */ #ifdef CONFIG_BL808_GPADC - bl808_gpadc_init(); - #endif #ifdef CONFIG_BL808_SPI0 @@ -183,6 +184,10 @@ void board_late_initialize(void) spi_register(spi1, 1); #endif +#ifdef CONFIG_BL808_TIMERS + bl808_timer_init(); +#endif + #ifdef CONFIG_NSH_ARCHINIT mount(NULL, "/proc", "procfs", 0, NULL);