1/*
2 * Copyright 2014, General Dynamics C4 Systems
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 */
6
7#include <config.h>
8#include <types.h>
9#include <machine/io.h>
10#include <kernel/vspace.h>
11#include <arch/machine.h>
12#include <arch/kernel/vspace.h>
13#include <linker.h>
14#include <drivers/timer/imx31-epit_gen.h>
15
16#define L2_LINE_SIZE_BITS 5
17#define L2_LINE_SIZE BIT(L2_LINE_SIZE_BITS)
18
19#define L2_LINE_START(a) ROUND_DOWN(a, L2_LINE_SIZE_BITS)
20#define L2_LINE_INDEX(a) (L2_LINE_START(a)>>L2_LINE_SIZE_BITS)
21
22timer_t *epit1 = (timer_t *) EPIT_PPTR;
23
24enum IPGConstants {
25    IPG_CLK = 1,
26    IPG_CLK_HIGHFREQ = 2,
27    IPG_CLK_32K = 3
28};
29
30#define TIMER_CLOCK_SRC   IPG_CLK_32K
31
32/* Configure EPIT1 as kernel preemption timer */
33BOOT_CODE void initTimer(void)
34{
35    epitcr_t epitcr_kludge;
36
37    /* Stop timer */
38    epit1->epitcr = 0;
39
40    /* Configure timer */
41    epitcr_kludge.words[0] = 0; /* Zero struct */
42    epitcr_kludge = epitcr_set_clksrc(epitcr_kludge, TIMER_CLOCK_SRC);
43    /* Overwrite counter immediately on write */
44    epitcr_kludge = epitcr_set_iovw(epitcr_kludge, 1);
45    /* Reload from modulus register */
46    epitcr_kludge = epitcr_set_rld(epitcr_kludge, 1);
47    /* Enable interrupt */
48    epitcr_kludge = epitcr_set_ocien(epitcr_kludge, 1);
49    /* Count from modulus value on restart */
50    epitcr_kludge = epitcr_set_enmod(epitcr_kludge, 1);
51    epit1->epitcr = epitcr_kludge.words[0];
52
53    /* Set counter modulus */
54    epit1->epitlr = TIMER_RELOAD;
55
56    /* Interrupt at zero count */
57    epit1->epitcmpr = 0;
58
59    /* Clear pending interrupt */
60    epit1->epitsr = 1;
61
62    /* Enable timer */
63    epitcr_kludge = epitcr_set_en(epitcr_kludge, 1);
64    epit1->epitcr = epitcr_kludge.words[0];
65}
66
67