blob: dd2e6beb83a98193ee9a20538100f083bbbcada5 [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/*
2 * Copyright (c) 2012 Corey Tabaka
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23#include <sys/types.h>
24#include <err.h>
25#include <debug.h>
26#include <kernel/thread.h>
27#include <platform.h>
28#include <platform/interrupts.h>
29#include <platform/timer.h>
30#include <platform/am335x.h>
31#include "platform_p.h"
32
33#include <soc_AM335x.h>
34#include <dmtimer.h>
35#include <hw_cm_per.h>
36#include <hw_cm_dpll.h>
37#include <hw_types.h>
38#include <interrupt.h>
39
40#define CLK_RATE (24000000)
41
42static volatile lk_time_t current_ms;
43static lk_time_t delta_ms;
44
45static uint32_t tdlr;
46
47static platform_timer_callback t_callback;
48
49status_t platform_set_periodic_timer(platform_timer_callback callback, void *arg, lk_time_t interval)
50{
51 spin_lock_saved_state_t statep;
52 arch_interrupt_save(&statep, SPIN_LOCK_FLAG_IRQ);
53
54 t_callback = callback;
55 delta_ms = interval;
56
57 DMTimerCounterSet(SOC_DMTIMER_2_REGS, tdlr);
58 DMTimerReloadSet(SOC_DMTIMER_2_REGS, tdlr);
59 DMTimerModeConfigure(SOC_DMTIMER_2_REGS, DMTIMER_AUTORLD_NOCMP_ENABLE);
60
61 DMTimerIntEnable(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_EN_FLAG);
62 DMTimerEnable(SOC_DMTIMER_2_REGS);
63
64 unmask_interrupt(SYS_INT_TINT2);
65
66 arch_interrupt_restore(statep, SPIN_LOCK_FLAG_IRQ);
67
68 return NO_ERROR;
69}
70
71lk_bigtime_t current_time_hires(void)
72{
73 lk_bigtime_t ret;
74 lk_bigtime_t counter;
75
76 ret = current_ms;
77
78 counter = DMTimerCounterGet(SOC_DMTIMER_2_REGS);
79
80 return ret * 1000 + (counter - tdlr) * 1000000 / CLK_RATE;
81}
82
83lk_time_t current_time(void)
84{
85 lk_time_t ret;
86 lk_time_t counter;
87
88 ret = current_ms;
89
90 counter = DMTimerCounterGet(SOC_DMTIMER_2_REGS);
91
92 return ret + (counter - tdlr) * 1000 / CLK_RATE;
93}
94
95static enum handler_return platform_tick(void *arg)
96{
97 enum handler_return ret;
98
99 DMTimerIntDisable(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_EN_FLAG);
100 DMTimerIntStatusClear(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_EN_FLAG);
101
102 current_ms += delta_ms;
103
104 if (t_callback) {
105 ret = t_callback(arg, current_time());
106 } else {
107 ret = INT_NO_RESCHEDULE;
108 }
109
110 DMTimerEndOfInterrupt(SOC_DMTIMER_2_REGS);
111 DMTimerIntEnable(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_EN_FLAG);
112
113 return ret;
114}
115
116void platform_init_timer(void)
117{
118 HWREG(SOC_CM_DPLL_REGS + CM_DPLL_CLKSEL_TIMER2_CLK) &=
119 ~(CM_DPLL_CLKSEL_TIMER2_CLK_CLKSEL);
120
121 HWREG(SOC_CM_DPLL_REGS + CM_DPLL_CLKSEL_TIMER2_CLK) |=
122 CM_DPLL_CLKSEL_TIMER2_CLK_CLKSEL_CLK_M_OSC;
123
124 while ((HWREG(SOC_CM_DPLL_REGS + CM_DPLL_CLKSEL_TIMER2_CLK) &
125 CM_DPLL_CLKSEL_TIMER2_CLK_CLKSEL) !=
126 CM_DPLL_CLKSEL_TIMER2_CLK_CLKSEL_CLK_M_OSC);
127
128 HWREG(SOC_CM_PER_REGS + CM_PER_TIMER2_CLKCTRL) |=
129 CM_PER_TIMER2_CLKCTRL_MODULEMODE_ENABLE;
130
131 while ((HWREG(SOC_CM_PER_REGS + CM_PER_TIMER2_CLKCTRL) &
132 CM_PER_TIMER2_CLKCTRL_MODULEMODE) != CM_PER_TIMER2_CLKCTRL_MODULEMODE_ENABLE);
133
134 while (!(HWREG(SOC_CM_PER_REGS + CM_PER_L4LS_CLKSTCTRL) &
135 (CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_L4LS_GCLK |
136 CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_TIMER2_GCLK)));
137
138 DMTimerResetConfigure(SOC_DMTIMER_2_REGS, DMTIMER_SFT_RESET_ENABLE);
139 DMTimerReset(SOC_DMTIMER_2_REGS);
140
141 register_int_handler(SYS_INT_TINT2, platform_tick, NULL);
142}
143