timer: Add Xilinx ZynqMP PS ttc timer
Add Xilinx PS ttc timer for Xilinx ZynqMP platform. Signed-off-by: Wendy Liang <wendy.liang@xilinx.com>
This commit is contained in:
parent
5364a389e5
commit
4ef9d4b6bf
|
@ -165,6 +165,7 @@
|
|||
/drivers/timer/altera_avalon_timer_hal.c @wentongwu
|
||||
/drivers/timer/riscv_machine_timer.c @nategraff-sifive @kgugala @pgielda
|
||||
/drivers/timer/litex_timer.c @mateusz-holenko @kgugala @pgielda
|
||||
/drivers/timer/xlnx_psttc_timer.c @wjliang
|
||||
/drivers/usb/ @jfischer-phytec-iot @finikorg
|
||||
/drivers/usb/device/usb_dc_stm32.c @ydamigos @loicpoulain
|
||||
/drivers/i2c/i2c_ll_stm32* @ldts @ydamigos
|
||||
|
|
|
@ -15,3 +15,4 @@ zephyr_sources_if_kconfig( native_posix_timer.c)
|
|||
zephyr_sources_if_kconfig( sam0_rtc_timer.c)
|
||||
zephyr_sources_if_kconfig( litex_timer.c)
|
||||
zephyr_sources_if_kconfig( mchp_xec_rtos_timer.c)
|
||||
zephyr_sources_if_kconfig( xlnx_psttc_timer.c)
|
||||
|
|
|
@ -241,6 +241,23 @@ config MCHP_XEC_RTOS_TIMER
|
|||
XEC series RTOS timer and provides the standard "system clock
|
||||
driver" interfaces.
|
||||
|
||||
config XLNX_PSTTC_TIMER
|
||||
bool "Xilinx PS ttc timer support"
|
||||
default y
|
||||
depends on SOC_XILINX_ZYNQMP
|
||||
help
|
||||
This module implements a kernel device driver for the Xilinx ZynqMP
|
||||
platform provides the standard "system clock driver" interfaces.
|
||||
If unchecked, no timer will be used.
|
||||
|
||||
config XLNX_PSTTC_TIMER_INDEX
|
||||
int "Xilinx PS ttc timer index"
|
||||
range 0 3
|
||||
default 0
|
||||
depends on XLNX_PSTTC_TIMER
|
||||
help
|
||||
This is the index of TTC timer picked to provide system clock.
|
||||
|
||||
config SYSTEM_CLOCK_DISABLE
|
||||
bool "API to disable system clock"
|
||||
help
|
||||
|
|
196
drivers/timer/xlnx_psttc_timer.c
Normal file
196
drivers/timer/xlnx_psttc_timer.c
Normal file
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Xilinx, Inc.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <drivers/timer/system_timer.h>
|
||||
#include <sys_clock.h>
|
||||
#include "irq.h"
|
||||
#include "legacy_api.h"
|
||||
|
||||
#define TIMER_FREQ CONFIG_SYS_CLOCK_TICKS_PER_SEC
|
||||
|
||||
#if (CONFIG_XLNX_PSTTC_TIMER_INDEX == 0)
|
||||
#define TIMER_INPUT_CLKHZ DT_INST_0_CDNS_TTC_CLOCK_FREQUENCY
|
||||
#define TIMER_IRQ DT_INST_0_CDNS_TTC_IRQ_0
|
||||
#define TIMER_BASEADDR DT_INST_0_CDNS_TTC_BASE_ADDRESS
|
||||
#else
|
||||
#error ("No timer is specified")
|
||||
#endif
|
||||
|
||||
#define XTTCPS_CLK_CNTRL_OFFSET 0x00000000U /**< Clock Control Register */
|
||||
#define XTTCPS_CNT_CNTRL_OFFSET 0x0000000CU /**< Counter Control Register*/
|
||||
#define XTTCPS_COUNT_VALUE_OFFSET 0x00000018U /**< Current Counter Value */
|
||||
#define XTTCPS_INTERVAL_VAL_OFFSET 0x00000024U /**< Interval Count Value */
|
||||
#define XTTCPS_MATCH_0_OFFSET 0x00000030U /**< Match 1 value */
|
||||
#define XTTCPS_MATCH_1_OFFSET 0x0000003CU /**< Match 2 value */
|
||||
#define XTTCPS_MATCH_2_OFFSET 0x00000048U /**< Match 3 value */
|
||||
#define XTTCPS_ISR_OFFSET 0x00000054U /**< Interrupt Status Register */
|
||||
#define XTTCPS_IER_OFFSET 0x00000060U /**< Interrupt Enable Register */
|
||||
|
||||
/* Clock Control Register definitions */
|
||||
#define XTTCPS_CLK_CNTRL_PS_EN_MASK 0x00000001U /**< Prescale enable */
|
||||
#define XTTCPS_CLK_CNTRL_PS_VAL_MASK 0x0000001EU /**< Prescale value */
|
||||
#define XTTCPS_CLK_CNTRL_PS_VAL_SHIFT 1U /**< Prescale shift */
|
||||
#define XTTCPS_CLK_CNTRL_PS_DISABLE 16U /**< Prescale disable */
|
||||
#define XTTCPS_CLK_CNTRL_SRC_MASK 0x00000020U /**< Clock source */
|
||||
#define XTTCPS_CLK_CNTRL_EXT_EDGE_MASK 0x00000040U /**< External Clock edge */
|
||||
|
||||
/* Counter Control Register definitions */
|
||||
#define XTTCPS_CNT_CNTRL_DIS_MASK 0x00000001U /**< Disable the counter */
|
||||
#define XTTCPS_CNT_CNTRL_INT_MASK 0x00000002U /**< Interval mode */
|
||||
#define XTTCPS_CNT_CNTRL_DECR_MASK 0x00000004U /**< Decrement mode */
|
||||
#define XTTCPS_CNT_CNTRL_MATCH_MASK 0x00000008U /**< Match mode */
|
||||
#define XTTCPS_CNT_CNTRL_RST_MASK 0x00000010U /**< Reset counter */
|
||||
#define XTTCPS_CNT_CNTRL_EN_WAVE_MASK 0x00000020U /**< Enable waveform */
|
||||
#define XTTCPS_CNT_CNTRL_POL_WAVE_MASK 0x00000040U /**< Waveform polarity */
|
||||
#define XTTCPS_CNT_CNTRL_RESET_VALUE 0x00000021U /**< Reset value */
|
||||
|
||||
/* Interrupt register masks */
|
||||
#define XTTCPS_IXR_INTERVAL_MASK 0x00000001U /**< Interval Interrupt */
|
||||
#define XTTCPS_IXR_MATCH_0_MASK 0x00000002U /**< Match 1 Interrupt */
|
||||
#define XTTCPS_IXR_MATCH_1_MASK 0x00000004U /**< Match 2 Interrupt */
|
||||
#define XTTCPS_IXR_MATCH_2_MASK 0x00000008U /**< Match 3 Interrupt */
|
||||
#define XTTCPS_IXR_CNT_OVR_MASK 0x00000010U /**< Counter Overflow */
|
||||
#define XTTCPS_IXR_ALL_MASK 0x0000001FU /**< All valid Interrupts */
|
||||
|
||||
#define XTTC_MAX_INTERVAL_COUNT 0xFFFFFFFFU /**< Maximum value of interval counter */
|
||||
|
||||
static u32_t accumulated_cycles;
|
||||
static s32_t _sys_idle_elapsed_ticks = 1;
|
||||
|
||||
static int xttc_calculate_interval(u32_t *interval, u8_t *prescaler)
|
||||
{
|
||||
u32_t tmpinterval = 0;
|
||||
u8_t tmpprescaler = 0;
|
||||
unsigned int tmpval;
|
||||
|
||||
tmpval = (u32_t)(TIMER_INPUT_CLKHZ / TIMER_FREQ);
|
||||
|
||||
if (tmpval < (u32_t)65536U) {
|
||||
/* no prescaler is required */
|
||||
tmpinterval = tmpval;
|
||||
tmpprescaler = 0;
|
||||
} else {
|
||||
for (tmpprescaler = 1U; tmpprescaler < 16; tmpprescaler++) {
|
||||
tmpval = (u32_t)(TIMER_INPUT_CLKHZ /
|
||||
(TIMER_FREQ * (1U << tmpprescaler)));
|
||||
if (tmpval < (u32_t)65536U) {
|
||||
tmpinterval = tmpval;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tmpinterval != 0) {
|
||||
*interval = tmpinterval;
|
||||
*prescaler = tmpprescaler;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TBD: Is there a way to adjust the sys clock parameters such as
|
||||
* ticks per sec if it failed to configure the timer as specified
|
||||
*/
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief System timer tick handler
|
||||
*
|
||||
* This routine handles the system clock tick interrupt. A TICK_EVENT event
|
||||
* is pushed onto the kernel stack.
|
||||
*
|
||||
* The symbol for this routine is either _timer_int_handler.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
void _timer_int_handler(void *unused)
|
||||
{
|
||||
ARG_UNUSED(unused);
|
||||
|
||||
u32_t regval;
|
||||
|
||||
regval = sys_read32(TIMER_BASEADDR + XTTCPS_ISR_OFFSET);
|
||||
accumulated_cycles += sys_clock_hw_cycles_per_tick();
|
||||
z_clock_announce(_sys_idle_elapsed_ticks);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize and enable the system clock
|
||||
*
|
||||
* This routine is used to program the systick to deliver interrupts at the
|
||||
* rate specified via the 'sys_clock_us_per_tick' global variable.
|
||||
*
|
||||
* @return 0
|
||||
*/
|
||||
int z_clock_driver_init(struct device *device)
|
||||
{
|
||||
int ret;
|
||||
u32_t interval;
|
||||
u8_t prescaler;
|
||||
u32_t regval;
|
||||
|
||||
/* Stop timer */
|
||||
sys_write32(XTTCPS_CNT_CNTRL_DIS_MASK,
|
||||
TIMER_BASEADDR + XTTCPS_CNT_CNTRL_OFFSET);
|
||||
|
||||
/* Calculate prescaler */
|
||||
ret = xttc_calculate_interval(&interval, &prescaler);
|
||||
if (ret < 0) {
|
||||
printk("Failed to calculate prescaler.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Reset registers */
|
||||
sys_write32(XTTCPS_CNT_CNTRL_RESET_VALUE,
|
||||
TIMER_BASEADDR + XTTCPS_CNT_CNTRL_OFFSET);
|
||||
sys_write32(0, TIMER_BASEADDR + XTTCPS_CLK_CNTRL_OFFSET);
|
||||
sys_write32(0, TIMER_BASEADDR + XTTCPS_INTERVAL_VAL_OFFSET);
|
||||
sys_write32(0, TIMER_BASEADDR + XTTCPS_MATCH_0_OFFSET);
|
||||
sys_write32(0, TIMER_BASEADDR + XTTCPS_MATCH_1_OFFSET);
|
||||
sys_write32(0, TIMER_BASEADDR + XTTCPS_MATCH_2_OFFSET);
|
||||
sys_write32(0, TIMER_BASEADDR + XTTCPS_IER_OFFSET);
|
||||
sys_write32(XTTCPS_IXR_ALL_MASK, TIMER_BASEADDR + XTTCPS_ISR_OFFSET);
|
||||
/* Reset counter value */
|
||||
regval = sys_read32(TIMER_BASEADDR + XTTCPS_CNT_CNTRL_OFFSET);
|
||||
regval |= XTTCPS_CNT_CNTRL_RST_MASK;
|
||||
sys_write32(regval, TIMER_BASEADDR + XTTCPS_CNT_CNTRL_OFFSET);
|
||||
|
||||
/* Set options */
|
||||
regval = sys_read32(TIMER_BASEADDR + XTTCPS_CNT_CNTRL_OFFSET);
|
||||
regval |= XTTCPS_CNT_CNTRL_INT_MASK;
|
||||
sys_write32(regval, TIMER_BASEADDR + XTTCPS_CNT_CNTRL_OFFSET);
|
||||
|
||||
/* Set interval and prescaller */
|
||||
sys_write32(interval, TIMER_BASEADDR + XTTCPS_INTERVAL_VAL_OFFSET);
|
||||
regval = (u32_t)((prescaler & 0xFU) << 1);
|
||||
sys_write32(regval, TIMER_BASEADDR + XTTCPS_CLK_CNTRL_OFFSET);
|
||||
|
||||
/* Enable timer interrupt */
|
||||
IRQ_CONNECT(TIMER_IRQ, 0, _timer_int_handler, 0, 0);
|
||||
irq_enable(TIMER_IRQ);
|
||||
regval = sys_read32(TIMER_BASEADDR + XTTCPS_IER_OFFSET);
|
||||
regval |= XTTCPS_IXR_INTERVAL_MASK;
|
||||
sys_write32(regval, TIMER_BASEADDR + XTTCPS_IER_OFFSET);
|
||||
|
||||
/* Start timer */
|
||||
regval = sys_read32(TIMER_BASEADDR + XTTCPS_CNT_CNTRL_OFFSET);
|
||||
regval &= (~XTTCPS_CNT_CNTRL_DIS_MASK);
|
||||
sys_write32(regval, TIMER_BASEADDR + XTTCPS_CNT_CNTRL_OFFSET);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Read the platform's timer hardware
|
||||
*
|
||||
* This routine returns the current time in terms of timer hardware clock
|
||||
* cycles.
|
||||
*
|
||||
* @return up counter of elapsed clock cycles
|
||||
*/
|
||||
u32_t z_timer_cycle_get_32(void)
|
||||
{
|
||||
return accumulated_cycles;
|
||||
}
|
24
dts/bindings/timer/xlnx,ttcps.yaml
Normal file
24
dts/bindings/timer/xlnx,ttcps.yaml
Normal file
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
title: Xilinx ZynqMP PS TTC TIMERS
|
||||
|
||||
description: >
|
||||
This binding gives a base representation of the Xilinx ZynqMP PS TTC TIMERS
|
||||
|
||||
inherits:
|
||||
!include base.yaml
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
constraint: "cdns,ttc"
|
||||
|
||||
label:
|
||||
category: required
|
||||
|
||||
reg:
|
||||
category: required
|
||||
|
||||
clock-frequency:
|
||||
type: int
|
||||
category: optional
|
||||
description: Clock frequency information for Timer operation
|
||||
...
|
|
@ -67,6 +67,8 @@
|
|||
#define TICK_IRQ DT_LITEX_TIMER0_E0002800_IRQ_0
|
||||
#elif defined(CONFIG_RV32M1_LPTMR_TIMER)
|
||||
#define TICK_IRQ DT_OPENISA_RV32M1_LPTMR_SYSTEM_LPTMR_IRQ_0
|
||||
#elif defined(CONFIG_XLNX_PSTTC_TIMER)
|
||||
#define TICK_IRQ DT_INST_0_CDNS_TTC_IRQ_0
|
||||
#elif defined(CONFIG_CPU_CORTEX_M)
|
||||
/*
|
||||
* The Cortex-M use the SYSTICK exception for the system timer, which is
|
||||
|
|
Loading…
Reference in a new issue