1146011Snyan/*
243561Skato * Copyright 2014, General Dynamics C4 Systems
343561Skato *
443561Skato * This software may be distributed and modified according to the terms of
543561Skato * the GNU General Public License version 2. Note that NO WARRANTY is provided.
643561Skato * See "LICENSE_GPLv2.txt" for details.
743561Skato *
843561Skato * @TAG(GD_GPL)
943561Skato */
1043561Skato
1143561Skato#include <config.h>
1243561Skato#include <types.h>
1343561Skato#include <machine/io.h>
1443561Skato#include <kernel/vspace.h>
1543561Skato#include <arch/machine.h>
1643561Skato#include <arch/kernel/vspace.h>
1743561Skato#include <plat/machine.h>
1843561Skato#include <linker.h>
1943561Skato#include <plat/machine/devices.h>
2043561Skato#include <plat/machine/hardware.h>
2143561Skato#include <plat/machine/timer.h>
2243561Skato#include <plat/machine/hardware_gen.h>
2343561Skato#include <arch/benchmark_overflowHandler.h>
2443561Skato
2543561Skato#define L2_LINE_SIZE_BITS 5
2643561Skato#define L2_LINE_SIZE BIT(L2_LINE_SIZE_BITS)
27119880Sobrien
2843561Skato#define L2_LINE_START(a) ROUND_DOWN(a, L2_LINE_SIZE_BITS)
2943561Skato#define L2_LINE_INDEX(a) (L2_LINE_START(a)>>L2_LINE_SIZE_BITS)
30119880Sobrien
31119880Sobrientimer_t *epit1 = (timer_t *) EPIT_PPTR;
32119880Sobrien
3343561Skatoenum IPGConstants {
3443561Skato    IPG_CLK = 1,
3543561Skato    IPG_CLK_HIGHFREQ = 2,
3643561Skato    IPG_CLK_32K = 3
3768358Snyan};
3843561Skato
3943561Skato#define TIMER_CLOCK_SRC   IPG_CLK_32K
4043561Skato
4143561Skatointerrupt_t active_irq = irqInvalid;
4243561Skato
4343561Skato/* Configure EPIT1 as kernel preemption timer */
4443561SkatoBOOT_CODE void
4543561SkatoinitTimer(void)
4643561Skato{
4743561Skato    epitcr_t epitcr_kludge;
4843561Skato
4943561Skato    /* Stop timer */
5043561Skato    epit1->epitcr = 0;
5143561Skato
5243561Skato    /* Configure timer */
5385063Snyan    epitcr_kludge.words[0] = 0; /* Zero struct */
5485063Snyan    epitcr_kludge = epitcr_set_clksrc(epitcr_kludge, TIMER_CLOCK_SRC);
5585063Snyan    /* Overwrite counter immediately on write */
5685063Snyan    epitcr_kludge = epitcr_set_iovw(epitcr_kludge, 1);
5768358Snyan    /* Reload from modulus register */
5843561Skato    epitcr_kludge = epitcr_set_rld(epitcr_kludge, 1);
5943561Skato    /* Enable interrupt */
6043561Skato    epitcr_kludge = epitcr_set_ocien(epitcr_kludge, 1);
6143561Skato    /* Count from modulus value on restart */
6243561Skato    epitcr_kludge = epitcr_set_enmod(epitcr_kludge, 1);
6343561Skato    epit1->epitcr = epitcr_kludge.words[0];
6443561Skato
6543561Skato    /* Set counter modulus */
6643561Skato    epit1->epitlr = TIMER_RELOAD;
6743561Skato
6885063Snyan    /* Interrupt at zero count */
6985063Snyan    epit1->epitcmpr = 0;
7043561Skato
7143561Skato    /* Clear pending interrupt */
7243561Skato    epit1->epitsr = 1;
7343561Skato
7443561Skato    /* Enable timer */
7543561Skato    epitcr_kludge = epitcr_set_en(epitcr_kludge, 1);
7685065Snyan    epit1->epitcr = epitcr_kludge.words[0];
7785065Snyan}
7885065Snyan
7985065Snyanstatic void cleanL2(void)
8085065Snyan{
8185065Snyan    /* clean all ways */
8285065Snyan    imx31_l2cc_flush_regs->clean_by_way = 0xff;
8385065Snyan    /* Busy-wait for completion */
8485065Snyan    while (imx31_l2cc_flush_regs->clean_by_way);
8585065Snyan}
8685065Snyan
8785065Snyanstatic void invalidateL2(void)
8885065Snyan{
8985065Snyan    /* Invalidate all ways. */
9085065Snyan    imx31_l2cc_flush_regs->inv_by_way = 0xff;
9185065Snyan    /* Busy-wait for completion. */
9285065Snyan    while (imx31_l2cc_flush_regs->inv_by_way);
9343561Skato}
9485065Snyan
9585065Snyanstatic void finaliseL2Op(void)
9685065Snyan{
9785065Snyan    /* We sync the l2 cache, which drains the write and eviction
9885065Snyan       buffers, to ensure that everything is consistent with RAM. */
9985065Snyan    imx31_l2cc_flush_regs->sync = 1;
10085065Snyan}
10185065Snyan
10285065Snyanvoid plat_cleanL2Range(paddr_t start, paddr_t end)
10385065Snyan{
10485065Snyan    paddr_t line;
10585065Snyan    word_t index;
10685065Snyan
10785065Snyan    for (index = L2_LINE_INDEX(start);
10885065Snyan            index < L2_LINE_INDEX(end) + 1;
10985065Snyan            index++) {
11085065Snyan        line = index << L2_LINE_SIZE_BITS;
11185065Snyan        imx31_l2cc_flush_regs->clean_by_pa = line;
11285065Snyan    }
11385065Snyan    finaliseL2Op();
11443561Skato}
11543561Skato
11643561Skatovoid plat_invalidateL2Range(paddr_t start, paddr_t end)
11743561Skato{
11843561Skato    paddr_t line;
11943561Skato    word_t index;
12043561Skato
12143561Skato    for (index = L2_LINE_INDEX(start);
12243561Skato            index < L2_LINE_INDEX(end) + 1;
12343561Skato            index++) {
12443561Skato        line = index << L2_LINE_SIZE_BITS;
12543561Skato        imx31_l2cc_flush_regs->inv_by_pa = line;
12643561Skato    }
12743561Skato
12843561Skato    finaliseL2Op();
12943561Skato}
13043561Skato
13143561Skatovoid plat_cleanInvalidateL2Range(paddr_t start, paddr_t end)
13243561Skato{
13343561Skato    paddr_t line;
13443561Skato    word_t index;
13543561Skato
13643561Skato    for (index = L2_LINE_INDEX(start);
13743561Skato            index < L2_LINE_INDEX(end) + 1;
13843561Skato            index++) {
13943561Skato        line = index << L2_LINE_SIZE_BITS;
14043561Skato        imx31_l2cc_flush_regs->clinv_by_pa = line;
14143561Skato    }
14243561Skato    finaliseL2Op();
14343561Skato}
14443561Skato
145146011Snyanvoid plat_cleanInvalidateCache(void)
14643561Skato{
14743561Skato    cleanL2();
14885061Snyan    invalidateL2();
14943561Skato}
15043561Skato
15185061SnyanBOOT_CODE void
15285061SnyaninitL2Cache(void)
15343561Skato{
15485061Snyan#ifndef CONFIG_DEBUG_DISABLE_L2_CACHE
15585061Snyan    /* Configure L2 cache */
15643561Skato    imx31_l2cc_ctrl_regs->aux_control = 0x0003001b;
15743561Skato
15843561Skato    /* Invalidate the L2 cache */
15943561Skato    invalidateL2();
16043561Skato
16143561Skato    /* Enable the L2 cache */
16243561Skato    imx31_l2cc_ctrl_regs->control = 1;
16343561Skato#endif
16443561Skato}
16543561Skato
16685061SnyanBOOT_CODE void
16785063SnyaninitIRQController(void)
16885063Snyan{
16943561Skato    /* Do nothing */
17085061Snyan}
17185061Snyan
17285061SnyanBOOT_CODE void cpu_initLocalIRQController(void)
17343561Skato{
17443561Skato    /* Do nothing */
17543561Skato}
17654086Snyan