2007-11-05 13:39:07 +00:00
|
|
|
/*
|
|
|
|
* cpu.c - A few helper functions for ARM
|
|
|
|
*
|
|
|
|
* Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
|
|
|
|
*
|
|
|
|
* See file CREDITS for list of people who contributed to this
|
|
|
|
* project.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License version 2
|
|
|
|
* as published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @file
|
|
|
|
* @brief A few helper functions for ARM
|
|
|
|
*/
|
|
|
|
|
2007-07-05 16:01:59 +00:00
|
|
|
#include <common.h>
|
2011-12-10 15:41:07 +00:00
|
|
|
#include <init.h>
|
2007-07-05 16:01:59 +00:00
|
|
|
#include <command.h>
|
2010-10-15 06:28:25 +00:00
|
|
|
#include <cache.h>
|
2009-02-20 16:44:46 +00:00
|
|
|
#include <asm/mmu.h>
|
2010-04-28 09:46:04 +00:00
|
|
|
#include <asm/system.h>
|
2011-07-29 09:43:45 +00:00
|
|
|
#include <asm/memory.h>
|
2013-01-25 22:39:20 +00:00
|
|
|
#include <asm-generic/memory_layout.h>
|
2012-10-09 21:50:20 +00:00
|
|
|
#include <asm/cputype.h>
|
2012-10-12 14:58:22 +00:00
|
|
|
#include <asm/cache.h>
|
2012-10-15 00:22:37 +00:00
|
|
|
#include <asm/ptrace.h>
|
2007-11-05 13:39:07 +00:00
|
|
|
|
2013-02-11 17:01:30 +00:00
|
|
|
#include "mmu.h"
|
|
|
|
|
2007-11-05 13:39:07 +00:00
|
|
|
/**
|
|
|
|
* Enable processor's instruction cache
|
|
|
|
*/
|
2010-04-28 09:46:04 +00:00
|
|
|
void icache_enable(void)
|
2007-07-05 16:01:58 +00:00
|
|
|
{
|
2010-04-28 09:46:04 +00:00
|
|
|
u32 r;
|
2007-07-05 16:01:58 +00:00
|
|
|
|
2010-04-28 09:46:04 +00:00
|
|
|
r = get_cr();
|
|
|
|
r |= CR_I;
|
|
|
|
set_cr(r);
|
2007-07-05 16:01:58 +00:00
|
|
|
}
|
|
|
|
|
2007-11-05 13:39:07 +00:00
|
|
|
/**
|
|
|
|
* Disable processor's instruction cache
|
|
|
|
*/
|
2010-04-28 09:46:04 +00:00
|
|
|
void icache_disable(void)
|
2007-07-05 16:01:58 +00:00
|
|
|
{
|
2010-04-28 09:46:04 +00:00
|
|
|
u32 r;
|
2007-07-05 16:01:58 +00:00
|
|
|
|
2010-04-28 09:46:04 +00:00
|
|
|
r = get_cr();
|
|
|
|
r &= ~CR_I;
|
|
|
|
set_cr(r);
|
2007-07-05 16:01:58 +00:00
|
|
|
}
|
|
|
|
|
2007-11-05 13:39:07 +00:00
|
|
|
/**
|
|
|
|
* Detect processor's current instruction cache status
|
|
|
|
* @return 0=disabled, 1=enabled
|
|
|
|
*/
|
2010-04-28 09:46:04 +00:00
|
|
|
int icache_status(void)
|
2007-07-05 16:01:58 +00:00
|
|
|
{
|
2010-04-28 09:46:04 +00:00
|
|
|
return (get_cr () & CR_I) != 0;
|
2007-07-05 16:01:58 +00:00
|
|
|
}
|
|
|
|
|
2013-02-11 17:01:30 +00:00
|
|
|
/*
|
|
|
|
* SoC like the ux500 have the l2x0 always enable
|
|
|
|
* with or without MMU enable
|
|
|
|
*/
|
|
|
|
struct outer_cache_fns outer_cache;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Clean and invalide caches, disable MMU
|
|
|
|
*/
|
|
|
|
void mmu_disable(void)
|
|
|
|
{
|
|
|
|
if (outer_cache.disable)
|
|
|
|
outer_cache.disable();
|
|
|
|
|
|
|
|
__mmu_cache_flush();
|
|
|
|
__mmu_cache_off();
|
|
|
|
}
|
|
|
|
|
2007-11-05 13:39:07 +00:00
|
|
|
/**
|
2010-03-30 08:40:06 +00:00
|
|
|
* Disable MMU and D-cache, flush caches
|
2007-11-05 13:39:07 +00:00
|
|
|
* @return 0 (always)
|
|
|
|
*
|
2010-03-30 08:40:06 +00:00
|
|
|
* This function is called by shutdown_barebox to get a clean
|
|
|
|
* memory/cache state.
|
2007-07-05 16:02:18 +00:00
|
|
|
*/
|
2010-03-30 08:40:06 +00:00
|
|
|
void arch_shutdown(void)
|
2007-07-05 16:01:58 +00:00
|
|
|
{
|
2012-10-15 00:22:37 +00:00
|
|
|
uint32_t r;
|
|
|
|
|
2009-02-20 16:44:46 +00:00
|
|
|
mmu_disable();
|
2012-10-12 14:58:22 +00:00
|
|
|
flush_icache();
|
2012-10-15 00:22:37 +00:00
|
|
|
/*
|
|
|
|
* barebox normally does not use interrupts, but some functionalities
|
|
|
|
* (eg. OMAP4_USBBOOT) require them enabled. So be sure interrupts are
|
|
|
|
* disabled before exiting.
|
|
|
|
*/
|
|
|
|
__asm__ __volatile__("mrs %0, cpsr" : "=r"(r));
|
|
|
|
r |= PSR_I_BIT;
|
|
|
|
__asm__ __volatile__("msr cpsr, %0" : : "r"(r));
|
2007-07-05 16:01:58 +00:00
|
|
|
}
|
2011-12-10 15:41:07 +00:00
|
|
|
|
2013-01-25 22:39:20 +00:00
|
|
|
extern unsigned long arm_stack_top;
|
|
|
|
|
|
|
|
static int arm_request_stack(void)
|
|
|
|
{
|
|
|
|
if (!request_sdram_region("stack", arm_stack_top - STACK_SIZE, STACK_SIZE))
|
|
|
|
pr_err("Error: Cannot request SDRAM region for stack\n");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
coredevice_initcall(arm_request_stack);
|
|
|
|
|
2011-12-10 15:41:07 +00:00
|
|
|
#ifdef CONFIG_THUMB2_BAREBOX
|
|
|
|
static void thumb2_execute(void *func, int argc, char *argv[])
|
|
|
|
{
|
|
|
|
/*
|
2014-05-30 09:07:33 +00:00
|
|
|
* Switch back to ARM mode before executing external
|
2011-12-10 15:41:07 +00:00
|
|
|
* programs.
|
|
|
|
*/
|
|
|
|
__asm__ __volatile__ (
|
|
|
|
"mov r0, #0\n"
|
|
|
|
"mov r1, %0\n"
|
|
|
|
"mov r2, %1\n"
|
|
|
|
"bx %2\n"
|
|
|
|
:
|
|
|
|
: "r" (argc - 1), "r" (&argv[1]), "r" (func)
|
|
|
|
: "r0", "r1", "r2"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int execute_init(void)
|
|
|
|
{
|
|
|
|
do_execute = thumb2_execute;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
postcore_initcall(execute_init);
|
|
|
|
#endif
|