Skip to content

Commit ff5944d

Browse files
Fix-Pointxiaoxiang781216
authored andcommitted
arch/tricore: Add the clkdev driver for tricore.
This commit added the clkdev driver for tricore. Signed-off-by: ouyangxiangzhen <ouyangxiangzhen@xiaomi.com>
1 parent 3b52763 commit ff5944d

4 files changed

Lines changed: 106 additions & 110 deletions

File tree

arch/tricore/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ config ARCH_CHIP_TC397
4141
select ARCH_TC3XX
4242
select ALARM_ARCH
4343
select ONESHOT
44+
select ONESHOT_COUNT
4445
---help---
4546
AURIX TC39x family: TC397
4647

arch/tricore/src/common/tricore_internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
* Pre-processor Definitions
4747
****************************************************************************/
4848

49+
#define SCU_FREQUENCY 100000000UL
50+
4951
/* Determine which (if any) console driver to use. If a console is enabled
5052
* and no other console device is specified, then a serial console is
5153
* assumed.

arch/tricore/src/common/tricore_systimer.c

Lines changed: 103 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,24 @@
3434

3535
#include "IfxStm.h"
3636

37+
/****************************************************************************
38+
* Pre-processor Definitions
39+
****************************************************************************/
40+
41+
/* Since the tricore hardware timer triggers an interrupt only when the
42+
* compare value is equal to the counter, setting a compare value that has
43+
* already timed out will not trigger an interrupt. To avoid missing
44+
* interrupts when setting the timer, we should set a minimum delay.
45+
* The minimum delay is calculated based on the CPU frequency and the timer
46+
* frequency. We assume that the worst-case execution time for setting the
47+
* timer does not exceed 40 CPU cycles, and calculate the minimum timer
48+
* delay accordingly.
49+
* 40 CPU cycles (100ns at 400Mhz) ~ 10 timer cycles (for 100 Mhz timer).
50+
*/
51+
52+
#define TRICORE_SYSTIMER_MIN_DELAY \
53+
(40ull * SCU_FREQUENCY / IFX_CFG_CPU_CLOCK_FREQUENCY)
54+
3755
/****************************************************************************
3856
* Private Types
3957
****************************************************************************/
@@ -46,40 +64,7 @@
4664
struct tricore_systimer_lowerhalf_s
4765
{
4866
struct oneshot_lowerhalf_s lower;
49-
volatile void *tbase;
50-
uint64_t freq;
51-
uint64_t alarm;
52-
spinlock_t lock;
53-
};
54-
55-
/****************************************************************************
56-
* Private Function Prototypes
57-
****************************************************************************/
58-
59-
static int tricore_systimer_max_delay(struct oneshot_lowerhalf_s *lower,
60-
struct timespec *ts);
61-
static int tricore_systimer_start(struct oneshot_lowerhalf_s *lower,
62-
const struct timespec *ts);
63-
static int tricore_systimer_cancel(struct oneshot_lowerhalf_s *lower,
64-
struct timespec *ts);
65-
static int tricore_systimer_current(struct oneshot_lowerhalf_s *lower,
66-
struct timespec *ts);
67-
68-
/****************************************************************************
69-
* Private Data
70-
****************************************************************************/
71-
72-
static const struct oneshot_operations_s g_tricore_systimer_ops =
73-
{
74-
.max_delay = tricore_systimer_max_delay,
75-
.start = tricore_systimer_start,
76-
.cancel = tricore_systimer_cancel,
77-
.current = tricore_systimer_current,
78-
};
79-
80-
static struct tricore_systimer_lowerhalf_s g_systimer_lower =
81-
{
82-
.lower.ops = &g_tricore_systimer_ops,
67+
volatile void *tbase;
8368
};
8469

8570
/****************************************************************************
@@ -124,59 +109,87 @@ tricore_systimer_set_timecmp(struct tricore_systimer_lowerhalf_s *priv,
124109
* lower An instance of the lower-half oneshot state structure. This
125110
* structure must have been previously initialized via a call to
126111
* oneshot_initialize();
127-
* ts The location in which to return the maximum delay.
128112
*
129113
* Returned Value:
130-
* Zero (OK) is returned on success; a negated errno value is returned
131-
* on failure.
114+
* The maximum delay value.
132115
*
133116
****************************************************************************/
134117

135-
static int tricore_systimer_max_delay(struct oneshot_lowerhalf_s *lower,
136-
struct timespec *ts)
118+
static clkcnt_t tricore_systimer_max_delay(struct oneshot_lowerhalf_s *lower)
137119
{
138-
ts->tv_sec = UINT32_MAX;
139-
ts->tv_nsec = NSEC_PER_SEC - 1;
140-
141-
return 0;
120+
return UINT32_MAX;
142121
}
143122

144123
/****************************************************************************
145124
* Name: tricore_systimer_start
146125
*
147126
* Description:
148-
* Start the oneshot timer
127+
* Start the oneshot timer. Note that the tricore systimer is special, the
128+
* IRQ is only triggered when timecmp == mtime, so we should avoid the case
129+
* that we miss the timecmp.
149130
*
150131
* Input Parameters:
151132
* lower An instance of the lower-half oneshot state structure. This
152133
* structure must have been previously initialized via a call to
153134
* oneshot_initialize();
154-
* handler The function to call when when the oneshot timer expires.
155-
* arg An opaque argument that will accompany the callback.
156-
* ts Provides the duration of the one shot timer.
135+
* delta Provides the duration of delta count.
157136
*
158137
* Returned Value:
159-
* Zero (OK) is returned on success; a negated errno value is returned
160-
* on failure.
138+
* None.
161139
*
162140
****************************************************************************/
163141

164-
static int tricore_systimer_start(struct oneshot_lowerhalf_s *lower,
165-
const struct timespec *ts)
142+
static void tricore_systimer_start(struct oneshot_lowerhalf_s *lower,
143+
clkcnt_t delta)
166144
{
167145
struct tricore_systimer_lowerhalf_s *priv =
168146
(struct tricore_systimer_lowerhalf_s *)lower;
169-
uint64_t mtime = tricore_systimer_get_time(priv);
147+
irqstate_t flags;
148+
uint64_t mtime;
149+
150+
delta = delta < TRICORE_SYSTIMER_MIN_DELAY ?
151+
TRICORE_SYSTIMER_MIN_DELAY : delta;
152+
flags = up_irq_save();
153+
mtime = tricore_systimer_get_time(priv);
170154

171-
priv->alarm = mtime + ts->tv_sec * priv->freq +
172-
ts->tv_nsec * priv->freq / NSEC_PER_SEC;
173-
if (priv->alarm < mtime)
174-
{
175-
priv->alarm = UINT64_MAX;
176-
}
155+
tricore_systimer_set_timecmp(priv, mtime + delta);
177156

178-
tricore_systimer_set_timecmp(priv, priv->alarm);
179-
return 0;
157+
up_irq_restore(flags);
158+
}
159+
160+
/****************************************************************************
161+
* Name: tricore_systimer_start_absolute
162+
*
163+
* Description:
164+
* Start the oneshot timer. Note that the tricore systimer is special, the
165+
* IRQ is only triggered when timecmp == mtime, so we should avoid the case
166+
* that we miss the timecmp.
167+
*
168+
* Input Parameters:
169+
* lower An instance of the lower-half oneshot state structure. This
170+
* structure must have been previously initialized via a call to
171+
* oneshot_initialize();
172+
* expected Target
173+
*
174+
* Returned Value:
175+
* None.
176+
*
177+
****************************************************************************/
178+
179+
static void
180+
tricore_systimer_start_absolute(struct oneshot_lowerhalf_s *lower,
181+
clkcnt_t expected)
182+
{
183+
struct tricore_systimer_lowerhalf_s *priv =
184+
(struct tricore_systimer_lowerhalf_s *)lower;
185+
186+
irqstate_t flags = up_irq_save();
187+
uint64_t min_expected = tricore_systimer_get_time(priv) +
188+
TRICORE_SYSTIMER_MIN_DELAY;
189+
expected = expected < min_expected ? min_expected : expected;
190+
tricore_systimer_set_timecmp(priv, expected);
191+
192+
up_irq_restore(flags);
180193
}
181194

182195
/****************************************************************************
@@ -192,44 +205,18 @@ static int tricore_systimer_start(struct oneshot_lowerhalf_s *lower,
192205
* lower Caller allocated instance of the oneshot state structure. This
193206
* structure must have been previously initialized via a call to
194207
* oneshot_initialize();
195-
* ts The location in which to return the time remaining on the
196-
* oneshot timer. A time of zero is returned if the timer is
197-
* not running.
198208
*
199209
* Returned Value:
200-
* Zero (OK) is returned on success. A call to up_timer_cancel() when
201-
* the timer is not active should also return success; a negated errno
202-
* value is returned on any failure.
210+
* None.
203211
*
204212
****************************************************************************/
205213

206-
static int tricore_systimer_cancel(struct oneshot_lowerhalf_s *lower,
207-
struct timespec *ts)
214+
static void tricore_systimer_cancel(struct oneshot_lowerhalf_s *lower)
208215
{
209216
struct tricore_systimer_lowerhalf_s *priv =
210217
(struct tricore_systimer_lowerhalf_s *)lower;
211-
uint64_t mtime;
212218

213219
tricore_systimer_set_timecmp(priv, UINT64_MAX);
214-
215-
mtime = tricore_systimer_get_time(priv);
216-
if (priv->alarm > mtime)
217-
{
218-
uint64_t nsec = (priv->alarm - mtime) *
219-
NSEC_PER_SEC / priv->freq;
220-
221-
ts->tv_sec = nsec / NSEC_PER_SEC;
222-
ts->tv_nsec = nsec % NSEC_PER_SEC;
223-
}
224-
else
225-
{
226-
ts->tv_sec = 0;
227-
ts->tv_nsec = 0;
228-
}
229-
230-
priv->alarm = 0;
231-
232-
return 0;
233220
}
234221

235222
/****************************************************************************
@@ -242,27 +229,18 @@ static int tricore_systimer_cancel(struct oneshot_lowerhalf_s *lower,
242229
* lower Caller allocated instance of the oneshot state structure. This
243230
* structure must have been previously initialized via a call to
244231
* oneshot_initialize();
245-
* ts The location in which to return the current time. A time of zero
246-
* is returned for the initialization moment.
247232
*
248233
* Returned Value:
249-
* Zero (OK) is returned on success, a negated errno value is returned on
250-
* any failure.
234+
* Current timer count.
251235
*
252236
****************************************************************************/
253237

254-
static int tricore_systimer_current(struct oneshot_lowerhalf_s *lower,
255-
struct timespec *ts)
238+
static clkcnt_t tricore_systimer_current(struct oneshot_lowerhalf_s *lower)
256239
{
257240
struct tricore_systimer_lowerhalf_s *priv =
258241
(struct tricore_systimer_lowerhalf_s *)lower;
259-
uint64_t mtime = tricore_systimer_get_time(priv);
260-
uint64_t nsec = mtime / (priv->freq / USEC_PER_SEC) * NSEC_PER_USEC;
261242

262-
ts->tv_sec = nsec / NSEC_PER_SEC;
263-
ts->tv_nsec = nsec % NSEC_PER_SEC;
264-
265-
return 0;
243+
return tricore_systimer_get_time(priv);
266244
}
267245

268246
/****************************************************************************
@@ -278,12 +256,31 @@ static int tricore_systimer_interrupt(int irq, void *context, void *arg)
278256
{
279257
struct tricore_systimer_lowerhalf_s *priv = arg;
280258

281-
tricore_systimer_set_timecmp(priv, UINT64_MAX);
259+
/* We do not need to clear the compare register here. */
260+
282261
oneshot_process_callback(&priv->lower);
283262

284263
return 0;
285264
}
286265

266+
/****************************************************************************
267+
* Private Data
268+
****************************************************************************/
269+
270+
static const struct oneshot_operations_s g_tricore_oneshot_ops =
271+
{
272+
.current = tricore_systimer_current,
273+
.start = tricore_systimer_start,
274+
.start_absolute = tricore_systimer_start_absolute,
275+
.cancel = tricore_systimer_cancel,
276+
.max_delay = tricore_systimer_max_delay
277+
};
278+
279+
static struct tricore_systimer_lowerhalf_s g_tricore_oneshot_lowerhalf =
280+
{
281+
.lower.ops = &g_tricore_oneshot_ops
282+
};
283+
287284
/****************************************************************************
288285
* Public Functions
289286
****************************************************************************/
@@ -300,11 +297,13 @@ static int tricore_systimer_interrupt(int irq, void *context, void *arg)
300297
struct oneshot_lowerhalf_s *
301298
tricore_systimer_initialize(volatile void *tbase, int irq, uint64_t freq)
302299
{
303-
struct tricore_systimer_lowerhalf_s *priv = &g_systimer_lower;
300+
struct tricore_systimer_lowerhalf_s *priv = &g_tricore_oneshot_lowerhalf;
304301

305302
priv->tbase = tbase;
306-
priv->freq = freq;
307-
spin_lock_init(&priv->lock);
303+
304+
ASSERT(freq <= UINT32_MAX);
305+
306+
oneshot_count_init(&priv->lower, (uint32_t)freq);
308307

309308
IfxStm_setCompareControl(tbase,
310309
IfxStm_Comparator_0,

arch/tricore/src/tc3xx/tc3xx_timerisr.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,6 @@
3434

3535
#include "IfxStm.h"
3636

37-
/****************************************************************************
38-
* Pre-processor Definitions
39-
****************************************************************************/
40-
41-
#define SCU_FREQUENCY 100000000UL
42-
4337
/****************************************************************************
4438
* Public Functions
4539
****************************************************************************/

0 commit comments

Comments
 (0)