Skip to content

[draft] driver: timer: mspm0: Add timer as sysclock #91490

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions drivers/timer/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ zephyr_library_sources_ifdef(CONFIG_SAM0_RTC_TIMER sam0_rtc_timer.c)
zephyr_library_sources_ifdef(CONFIG_SILABS_SLEEPTIMER_TIMER silabs_sleeptimer_timer.c)
zephyr_library_sources_ifdef(CONFIG_STM32_LPTIM_TIMER stm32_lptim_timer.c)
zephyr_library_sources_ifdef(CONFIG_TI_DM_TIMER ti_dmtimer.c)
zephyr_library_sources_ifdef(CONFIG_TI_MSPM0_TIMER ti_mspm0_timer.c)
zephyr_library_sources_ifdef(CONFIG_XLNX_PSTTC_TIMER xlnx_psttc_timer.c)
zephyr_library_sources_ifdef(CONFIG_XTENSA_TIMER xtensa_sys_timer.c)
zephyr_library_sources_ifdef(CONFIG_SMARTBOND_TIMER smartbond_timer.c)
Expand Down
1 change: 1 addition & 0 deletions drivers/timer/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ source "drivers/timer/Kconfig.silabs"
source "drivers/timer/Kconfig.smartbond"
source "drivers/timer/Kconfig.stm32_lptim"
source "drivers/timer/Kconfig.ti_dm_timer"
source "drivers/timer/Kconfig.ti_mspm0_timer"
source "drivers/timer/Kconfig.xlnx_psttc"
source "drivers/timer/Kconfig.xtensa"
source "drivers/timer/Kconfig.mtk_adsp"
Expand Down
12 changes: 12 additions & 0 deletions drivers/timer/Kconfig.ti_mspm0_timer
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Copyright (c) 2025 Linumiz GmbH
# SPDX-License-Identifier: Apache-2.0

config TI_MSPM0_TIMER
bool "TI MSPM0 timer"
default n
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you don't need to precise the default for a boolean if it is not about enabling it.

depends on DT_HAS_TI_MSPM0_TIMER_SYSCLOCK_ENABLED
select SYSTEM_TIMER_HAS_DISABLE_SUPPORT
help
This module implements a kernel device driver for the TI MSPM0
Timer and provides the standard "system clock driver"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you detail what could be the usage over the default cortex_m's systick driver? (any pros/cons etc..)

interfaces.
118 changes: 118 additions & 0 deletions drivers/timer/ti_mspm0_timer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/* Copyright (C) 2025 Linumiz GmbH
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <zephyr/device.h>
#include <zephyr/drivers/clock_control/mspm0_clock_control.h>
#include <zephyr/drivers/timer/system_timer.h>
#include <zephyr/irq.h>
#include <zephyr/sys_clock.h>
#include <zephyr/kernel.h>

#include <ti/driverlib/dl_timerg.h>
#include <ti/driverlib/dl_timer.h>

#define DT_DRV_COMPAT ti_mspm0_timer_sysclock

#define MSPM0_TMR_PRESCALE DT_PROP(DT_INST_PARENT(0), clk_prescaler)
#define MSPM0_TMR_IRQN DT_IRQN(DT_INST_PARENT(0))
#define MSPM0_TMR_IRQ_PRIO DT_IRQ(DT_INST_PARENT(0), priority)
#define MSPM0_TMR_BASE ((GPTIMER_Regs *)(DT_REG_ADDR(DT_INST_PARENT(0))))

Check warning on line 21 in drivers/timer/ti_mspm0_timer.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

SPACE_BEFORE_TAB

drivers/timer/ti_mspm0_timer.c:21 please, no space before tabs
#define MSPM0_TMR_CLK (DT_CLOCKS_CELL_BY_IDX(DT_INST_PARENT(0), 0, bus) & \
MSPM0_CLOCK_SEL_MASK)
#define MSPM0_CLK_DIV(div) DT_CAT(DL_TIMER_CLOCK_DIVIDE_, div)

Check warning on line 24 in drivers/timer/ti_mspm0_timer.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

SPACE_BEFORE_TAB

drivers/timer/ti_mspm0_timer.c:24 please, no space before tabs
#define MSPM0_TMR_CLK_DIV MSPM0_CLK_DIV(DT_PROP(DT_INST_PARENT(0), clk_div))

/* Timer cycles per tick */
#define CYC_PER_TICK ((uint32_t)((uint64_t)sys_clock_hw_cycles_per_sec() \
/ (uint64_t)CONFIG_SYS_CLOCK_TICKS_PER_SEC))

static uint32_t cycles;

static void mspm0_timer_isr(void *arg)
{
uint32_t status;
ARG_UNUSED(arg);

Check warning on line 36 in drivers/timer/ti_mspm0_timer.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LINE_SPACING

drivers/timer/ti_mspm0_timer.c:36 Missing a blank line after declarations

status = DL_Timer_getPendingInterrupt(MSPM0_TMR_BASE);
if ((status & DL_TIMER_IIDX_LOAD) == 0) {
return;
}

cycles += CYC_PER_TICK;
sys_clock_announce(1);
}

void sys_clock_set_timeout(int32_t ticks, bool idle)
{
ARG_UNUSED(idle);

if (idle && (ticks == K_TICKS_FOREVER)) {
DL_Timer_disableInterrupt(MSPM0_TMR_BASE,
DL_TIMER_INTERRUPT_LOAD_EVENT);
}
}

void sys_clock_idle_exit(void)
{
if (DL_Timer_getEnabledInterruptStatus(MSPM0_TMR_BASE,
DL_TIMER_INTERRUPT_LOAD_EVENT) == 0) {
DL_Timer_enableInterrupt(MSPM0_TMR_BASE,
DL_TIMER_INTERRUPT_LOAD_EVENT);
}
}

void sys_clock_disable(void)
{
DL_Timer_disableInterrupt(MSPM0_TMR_BASE,
DL_TIMER_INTERRUPT_LOAD_EVENT);
DL_Timer_stopCounter(MSPM0_TMR_BASE);
}

uint32_t sys_clock_elapsed(void)
{
return 0;
}

uint32_t sys_clock_cycle_get_32(void)
{
return DL_Timer_getTimerCount(MSPM0_TMR_BASE) + cycles;
}

static int mspm0_sysclock_init(void)
{
DL_Timer_TimerConfig tim_config = {
.period = CYC_PER_TICK,
.timerMode = DL_TIMER_TIMER_MODE_PERIODIC_UP,
.startTimer = DL_TIMER_START,
};

DL_Timer_ClockConfig clk_config = {
.clockSel = MSPM0_TMR_CLK,
.divideRatio = MSPM0_TMR_CLK_DIV,
.prescale = MSPM0_TMR_PRESCALE,
};

DL_Timer_reset(MSPM0_TMR_BASE);
DL_Timer_enablePower(MSPM0_TMR_BASE);

delay_cycles(16);
DL_Timer_setClockConfig(MSPM0_TMR_BASE, &clk_config);
DL_Timer_initTimerMode(MSPM0_TMR_BASE, &tim_config);
DL_Timer_setCounterRepeatMode(MSPM0_TMR_BASE,
DL_TIMER_REPEAT_MODE_ENABLED);

IRQ_CONNECT(MSPM0_TMR_IRQN, MSPM0_TMR_IRQ_PRIO, mspm0_timer_isr, 0, 0);
irq_enable(MSPM0_TMR_IRQN);

DL_Timer_clearInterruptStatus(MSPM0_TMR_BASE,
DL_TIMER_INTERRUPT_LOAD_EVENT);
DL_Timer_enableInterrupt(MSPM0_TMR_BASE,
DL_TIMER_INTERRUPT_LOAD_EVENT);

return 0;
}

SYS_INIT(mspm0_sysclock_init, PRE_KERNEL_2,
CONFIG_SYSTEM_CLOCK_INIT_PRIORITY);
8 changes: 8 additions & 0 deletions dts/bindings/timer/ti,mspm0-timer-sysclock.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Copyright 2025 Linumiz GmbH
# SPDX-License-Identifier: Apache-2.0

description: TI MSPM0 Timer used as sysclock

compatible: "ti,mspm0-timer-sysclock"

include: base.yaml
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a required: true for interrupt and reg attributes.

Loading