counter: cmsdk: Add DualTimer as Counter

This patch adds Dualtimer to be used as a counter.

Jira: ZEP-1300
Change-Id: Ic4a2d89ec7fc0c0c2a0bc7f6d32d97637049faaf
Signed-off-by: Vincenzo Frascino <vincenzo.frascino@linaro.org>
This commit is contained in:
Vincenzo Frascino 2016-12-13 11:53:08 +00:00 committed by Kumar Gala
commit b1e02a594a
5 changed files with 230 additions and 0 deletions

View file

@ -18,4 +18,6 @@ source "drivers/counter/Kconfig.qmsi"
source "drivers/counter/Kconfig.tmr_cmsdk_apb"
source "drivers/counter/Kconfig.dtmr_cmsdk_apb"
endif # COUNTER

View file

@ -0,0 +1,39 @@
# Kconfig - counter configuration options
#
#
# Copyright (c) 2016 Linaro Limited
#
# SPDX-License-Identifier: Apache-2.0
#
if SOC_FAMILY_ARM
config COUNTER_DTMR_CMSDK_APB
bool
prompt "ARM CMSDK (Cortex-M System Design Kit) DTMR Counter driver"
default n
help
The dualtimer (DTMR) present in the platform is used as a counter.
This option enables the support for the counter.
if COUNTER_DTMR_CMSDK_APB
# ---------- Counter 0 ----------
config COUNTER_DTMR_CMSDK_APB_0
bool
prompt "Counter 0 driver"
default n
help
Enable support for Counter 0.
config COUNTER_DTMR_CMSDK_APB_0_DEV_NAME
string "Counter 0 Device Name"
depends on COUNTER_DTMR_CMSDK_APB_0
default "COUNTER_0"
help
Specify the device name for Counter 0 driver.
endif # COUNTER_DTMR_CMSDK_APB
endif # SOC_FAMILY_ARM

View file

@ -2,3 +2,4 @@ obj-$(CONFIG_AON_COUNTER_QMSI) += counter_qmsi_aon.o
obj-$(CONFIG_AON_TIMER_QMSI) += counter_qmsi_aonpt.o
obj-$(CONFIG_COUNTER_TMR_CMSDK_APB) += counter_tmr_cmsdk_apb.o
obj-$(CONFIG_TIMER_TMR_CMSDK_APB) += timer_tmr_cmsdk_apb.o
obj-$(CONFIG_COUNTER_DTMR_CMSDK_APB) += counter_dtmr_cmsdk_apb.o

View file

@ -0,0 +1,120 @@
/*
* Copyright (c) 2016 Linaro Limited.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <counter.h>
#include <device.h>
#include <errno.h>
#include <init.h>
#include <soc.h>
#include <clock_control/arm_clock_control.h>
#include "dualtimer_cmsdk_apb.h"
#define DUALTIMER_MAX_RELOAD 0xFFFFFFFF
struct counter_dtmr_cmsdk_apb_cfg {
volatile struct dualtimer_cmsdk_apb *dtimer;
/* Dualtimer Clock control in Active State */
const struct arm_clock_control_t dtimer_cc_as;
/* Dualtimer Clock control in Sleep State */
const struct arm_clock_control_t dtimer_cc_ss;
/* Dualtimer Clock control in Deep Sleep State */
const struct arm_clock_control_t dtimer_cc_dss;
};
static int counter_dtmr_cmsdk_apb_start(struct device *dev)
{
const struct counter_dtmr_cmsdk_apb_cfg * const cfg =
dev->config->config_info;
/* Set the dualtimer to Max reload */
cfg->dtimer->timer1load = DUALTIMER_MAX_RELOAD;
/* Enable the dualtimer in 32 bit mode */
cfg->dtimer->timer1ctrl = (DUALTIMER_CTRL_EN | DUALTIMER_CTRL_SIZE_32);
return 0;
}
static int counter_dtmr_cmsdk_apb_stop(struct device *dev)
{
const struct counter_dtmr_cmsdk_apb_cfg * const cfg =
dev->config->config_info;
/* Disable the dualtimer */
cfg->dtimer->timer1ctrl = 0x0;
return 0;
}
static uint32_t counter_dtmr_cmsdk_apb_read(struct device *dev)
{
const struct counter_dtmr_cmsdk_apb_cfg * const cfg =
dev->config->config_info;
/* Return Counter Value */
uint32_t value = 0;
value = DUALTIMER_MAX_RELOAD - cfg->dtimer->timer1value;
return value;
}
static int counter_dtmr_cmsdk_apb_set_alarm(struct device *dev,
counter_callback_t callback,
uint32_t count, void *user_data)
{
return -ENODEV;
}
static const struct counter_driver_api counter_dtmr_cmsdk_apb_api = {
.start = counter_dtmr_cmsdk_apb_start,
.stop = counter_dtmr_cmsdk_apb_stop,
.read = counter_dtmr_cmsdk_apb_read,
.set_alarm = counter_dtmr_cmsdk_apb_set_alarm,
};
static int counter_dtmr_cmsdk_apb_init(struct device *dev)
{
#ifdef CONFIG_CLOCK_CONTROL
/* Enable clock for subsystem */
struct device *clk =
device_get_binding(CONFIG_ARM_CLOCK_CONTROL_DEV_NAME);
const struct counter_dtmr_cmsdk_apb_cfg * const cfg =
dev->config->config_info;
#ifdef CONFIG_SOC_SERIES_BEETLE
clock_control_on(clk, (clock_control_subsys_t *) &cfg->dtimer_cc_as);
clock_control_on(clk, (clock_control_subsys_t *) &cfg->dtimer_cc_ss);
clock_control_on(clk, (clock_control_subsys_t *) &cfg->dtimer_cc_dss);
#endif /* CONFIG_SOC_SERIES_BEETLE */
#else
ARG_UNUSED(dev);
#endif /* CONFIG_CLOCK_CONTROL */
return 0;
}
/* COUNTER 0 */
#ifdef CONFIG_COUNTER_DTMR_CMSDK_APB_0
static const struct counter_dtmr_cmsdk_apb_cfg counter_dtmr_cmsdk_apb_cfg_0 = {
.dtimer = ((volatile struct dualtimer_cmsdk_apb *)CMSDK_APB_DTIMER),
.dtimer_cc_as = {.bus = CMSDK_APB, .state = SOC_ACTIVE,
.device = CMSDK_APB_DTIMER,},
.dtimer_cc_ss = {.bus = CMSDK_APB, .state = SOC_SLEEP,
.device = CMSDK_APB_DTIMER,},
.dtimer_cc_dss = {.bus = CMSDK_APB, .state = SOC_DEEPSLEEP,
.device = CMSDK_APB_DTIMER,},
};
DEVICE_AND_API_INIT(counter_dtmr_cmsdk_apb_0,
CONFIG_COUNTER_DTMR_CMSDK_APB_0_DEV_NAME,
counter_dtmr_cmsdk_apb_init, NULL,
&counter_dtmr_cmsdk_apb_cfg_0, POST_KERNEL,
CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
&counter_dtmr_cmsdk_apb_api);
#endif /* CONFIG_COUNTER_DTMR_CMSDK_APB_0 */

View file

@ -0,0 +1,68 @@
/*
* Copyright (c) 2017 Linaro Limited.
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _DRIVERS_DUALTIMER_CMSDK_AHB_
#define _DRIVERS_DUALTIMER_CMSDK_AHB_
#include <counter.h>
#ifdef __cplusplus
extern "C" {
#endif
struct dualtimer_cmsdk_apb {
/* Offset: 0x000 (R/W) Timer 1 Load */
volatile uint32_t timer1load;
/* Offset: 0x004 (R/ ) Timer 1 Counter Current Value */
volatile uint32_t timer1value;
/* Offset: 0x008 (R/W) Timer 1 Control */
volatile uint32_t timer1ctrl;
/* Offset: 0x00C ( /W) Timer 1 Interrupt Clear */
volatile uint32_t timer1intclr;
/* Offset: 0x010 (R/ ) Timer 1 Raw Interrupt Status */
volatile uint32_t timer1ris;
/* Offset: 0x014 (R/ ) Timer 1 Masked Interrupt Status */
volatile uint32_t timer1mis;
/* Offset: 0x018 (R/W) Background Load Register */
volatile uint32_t timer1bgload;
/* Reserved */
volatile uint32_t reserved0;
/* Offset: 0x020 (R/W) Timer 2 Load */
volatile uint32_t timer2load;
/* Offset: 0x024 (R/ ) Timer 2 Counter Current Value */
volatile uint32_t timer2value;
/* Offset: 0x028 (R/W) Timer 2 Control */
volatile uint32_t timer2ctrl;
/* Offset: 0x02C ( /W) Timer 2 Interrupt Clear */
volatile uint32_t timer2intclr;
/* Offset: 0x030 (R/ ) Timer 2 Raw Interrupt Status */
volatile uint32_t timer2ris;
/* Offset: 0x034 (R/ ) Timer 2 Masked Interrupt Status */
volatile uint32_t timer2mis;
/* Offset: 0x038 (R/W) Background Load Register */
volatile uint32_t timer2bgload;
/* Reserved */
volatile uint32_t reserved1[945];
/* Offset: 0xF00 (R/W) Integration Test Control Register */
volatile uint32_t itcr;
/* Offset: 0xF04 ( /W) Integration Test Output Set Register */
volatile uint32_t itop;
};
#define DUALTIMER_CTRL_EN (1 << 7)
#define DUALTIMER_CTRL_MODE (1 << 6)
#define DUALTIMER_CTRL_INTEN (1 << 5)
#define DUALTIMER_CTRL_PRESCALE (3 << 2)
#define DUALTIMER_CTRL_SIZE_32 (1 << 1)
#define DUALTIMER_CTRL_ONESHOOT (1 << 0)
#define DUALTIMER_INTCLR (1 << 0)
#define DUALTIMER_RAWINTSTAT (1 << 0)
#define DUALTIMER_MASKINTSTAT (1 << 0)
#ifdef __cplusplus
}
#endif
#endif /* _DRIVERS_DUALTIMER_CMSDK_AHB_ */