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