1/*
2 * Copyright 2014, General Dynamics C4 Systems
3 *
4 * This software may be distributed and modified according to the terms of
5 * the GNU General Public License version 2. Note that NO WARRANTY is provided.
6 * See "LICENSE_GPLv2.txt" for details.
7 *
8 * @TAG(GD_GPL)
9 */
10
11#include <config.h>
12#include <types.h>
13#include <machine/io.h>
14#include <kernel/vspace.h>
15#include <arch/machine.h>
16#include <arch/kernel/vspace.h>
17#include <plat/machine.h>
18#include <linker.h>
19#include <plat/machine/devices.h>
20#include <plat/machine/hardware.h>
21#include <plat/machine/timer.h>
22#include <plat/machine/hardware_gen.h>
23#include <arch/benchmark_overflowHandler.h>
24
25#define L2_LINE_SIZE_BITS 5
26#define L2_LINE_SIZE BIT(L2_LINE_SIZE_BITS)
27
28#define L2_LINE_START(a) ROUND_DOWN(a, L2_LINE_SIZE_BITS)
29#define L2_LINE_INDEX(a) (L2_LINE_START(a)>>L2_LINE_SIZE_BITS)
30
31timer_t *epit1 = (timer_t *) EPIT_PPTR;
32
33enum IPGConstants {
34    IPG_CLK = 1,
35    IPG_CLK_HIGHFREQ = 2,
36    IPG_CLK_32K = 3
37};
38
39#define TIMER_CLOCK_SRC   IPG_CLK_32K
40
41interrupt_t active_irq = irqInvalid;
42
43/* Configure EPIT1 as kernel preemption timer */
44BOOT_CODE void
45initTimer(void)
46{
47    epitcr_t epitcr_kludge;
48
49    /* Stop timer */
50    epit1->epitcr = 0;
51
52    /* Configure timer */
53    epitcr_kludge.words[0] = 0; /* Zero struct */
54    epitcr_kludge = epitcr_set_clksrc(epitcr_kludge, TIMER_CLOCK_SRC);
55    /* Overwrite counter immediately on write */
56    epitcr_kludge = epitcr_set_iovw(epitcr_kludge, 1);
57    /* Reload from modulus register */
58    epitcr_kludge = epitcr_set_rld(epitcr_kludge, 1);
59    /* Enable interrupt */
60    epitcr_kludge = epitcr_set_ocien(epitcr_kludge, 1);
61    /* Count from modulus value on restart */
62    epitcr_kludge = epitcr_set_enmod(epitcr_kludge, 1);
63    epit1->epitcr = epitcr_kludge.words[0];
64
65    /* Set counter modulus */
66    epit1->epitlr = TIMER_RELOAD;
67
68    /* Interrupt at zero count */
69    epit1->epitcmpr = 0;
70
71    /* Clear pending interrupt */
72    epit1->epitsr = 1;
73
74    /* Enable timer */
75    epitcr_kludge = epitcr_set_en(epitcr_kludge, 1);
76    epit1->epitcr = epitcr_kludge.words[0];
77}
78
79static void cleanL2(void)
80{
81    /* clean all ways */
82    imx31_l2cc_flush_regs->clean_by_way = 0xff;
83    /* Busy-wait for completion */
84    while (imx31_l2cc_flush_regs->clean_by_way);
85}
86
87static void invalidateL2(void)
88{
89    /* Invalidate all ways. */
90    imx31_l2cc_flush_regs->inv_by_way = 0xff;
91    /* Busy-wait for completion. */
92    while (imx31_l2cc_flush_regs->inv_by_way);
93}
94
95static void finaliseL2Op(void)
96{
97    /* We sync the l2 cache, which drains the write and eviction
98       buffers, to ensure that everything is consistent with RAM. */
99    imx31_l2cc_flush_regs->sync = 1;
100}
101
102void plat_cleanL2Range(paddr_t start, paddr_t end)
103{
104    paddr_t line;
105    word_t index;
106
107    for (index = L2_LINE_INDEX(start);
108            index < L2_LINE_INDEX(end) + 1;
109            index++) {
110        line = index << L2_LINE_SIZE_BITS;
111        imx31_l2cc_flush_regs->clean_by_pa = line;
112    }
113    finaliseL2Op();
114}
115
116void plat_invalidateL2Range(paddr_t start, paddr_t end)
117{
118    paddr_t line;
119    word_t index;
120
121    for (index = L2_LINE_INDEX(start);
122            index < L2_LINE_INDEX(end) + 1;
123            index++) {
124        line = index << L2_LINE_SIZE_BITS;
125        imx31_l2cc_flush_regs->inv_by_pa = line;
126    }
127
128    finaliseL2Op();
129}
130
131void plat_cleanInvalidateL2Range(paddr_t start, paddr_t end)
132{
133    paddr_t line;
134    word_t index;
135
136    for (index = L2_LINE_INDEX(start);
137            index < L2_LINE_INDEX(end) + 1;
138            index++) {
139        line = index << L2_LINE_SIZE_BITS;
140        imx31_l2cc_flush_regs->clinv_by_pa = line;
141    }
142    finaliseL2Op();
143}
144
145void plat_cleanInvalidateCache(void)
146{
147    cleanL2();
148    invalidateL2();
149}
150
151BOOT_CODE void
152initL2Cache(void)
153{
154#ifndef CONFIG_DEBUG_DISABLE_L2_CACHE
155    /* Configure L2 cache */
156    imx31_l2cc_ctrl_regs->aux_control = 0x0003001b;
157
158    /* Invalidate the L2 cache */
159    invalidateL2();
160
161    /* Enable the L2 cache */
162    imx31_l2cc_ctrl_regs->control = 1;
163#endif
164}
165
166BOOT_CODE void
167initIRQController(void)
168{
169    /* Do nothing */
170}
171
172BOOT_CODE void cpu_initLocalIRQController(void)
173{
174    /* Do nothing */
175}
176