base-hw & imx53: enable nested init

Fix #575
This commit is contained in:
Stefan Kalkowski 2012-12-14 14:55:37 +01:00 committed by Norman Feske
parent 7f2f2d9120
commit edb48873c1
16 changed files with 854 additions and 3 deletions

View File

@ -0,0 +1,38 @@
/*
* \brief Serial output driver specific for the i.MX53
* \author Stefan Kalkowski
* \date 2012-10-24
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__PLATFORM__IMX53__DRIVERS__SERIAL_LOG_H_
#define _INCLUDE__PLATFORM__IMX53__DRIVERS__SERIAL_LOG_H_
/* Genode includes */
#include <drivers/board_base.h>
#include <drivers/uart/imx31_uart_base.h>
namespace Genode
{
struct Serial_log : Imx31_uart_base
{
/**
* Constructor
*
* \param baud_rate targeted transfer baud-rate
*
* XXX: The 'baud_rate' argument is ignored for now.
*/
Serial_log(unsigned const baud_rate)
: Imx31_uart_base(Board_base::UART_1_MMIO_BASE) { }
};
}
#endif /* _INCLUDE__PLATFORM__IMX53__DRIVERS__SERIAL_LOG_H_ */

View File

@ -0,0 +1,16 @@
#
# \brief Build configurations for 'base-hw' on Freescale i.MX53
# \author Stefan Kalkowski
# \date 2012-10-24
#
# denote wich specs are also fullfilled by this spec
SPECS += hw platform_imx53
# set address where to link the text segment at
LD_TEXT_ADDR ?= 0x70001000
# include implied specs
include $(call select_from_repositories,mk/spec-hw.mk)
include $(call select_from_repositories,mk/spec-platform_imx53.mk)

View File

@ -17,7 +17,15 @@
/* core includes */
#include <drivers/board_base.h>
namespace Genode { class Board : public Board_base { }; }
namespace Genode
{
class Board : public Board_base
{
public:
static void prepare_kernel() { }
};
}
#endif /* _BOARD_H_ */

View File

@ -183,6 +183,7 @@ namespace Arm_v7
*/
static void init_phys_kernel()
{
Board::prepare_kernel();
Psr::write(Psr::init_kernel());
flush_tlb();
}
@ -192,7 +193,7 @@ namespace Arm_v7
*/
static bool secure_mode()
{
if (!Board_base::SECURITY_EXTENSION) return 0;
if (!Board::SECURITY_EXTENSION) return 0;
return !Cpu::Scr::Ns::get(Cpu::Scr::read());
}

View File

@ -0,0 +1,105 @@
/*
* \brief Board definitions for core
* \author Stefan Kalkowski
* \date 2012-10-24
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _IMX53__BOARD_H_
#define _IMX53__BOARD_H_
/**
* Genode includes
*/
#include <platform/imx53/drivers/board_base.h>
#include <util/mmio.h>
namespace Imx53
{
class Aipstz : public Genode::Mmio
{
/**
* Configuration of the masters
*/
struct Mpr { enum { ALL_UNBUFFERED_AND_FULLY_TRUSTED = 0x77777777 }; };
struct Mpr1 : Register<0x0, 32>, Mpr { };
struct Mpr2 : Register<0x4, 32>, Mpr { };
/**
* Configuration of the platform peripherals
*/
struct Pacr { enum { ALL_UNBUFFERED_AND_FULLY_UNPROTECTED = 0 }; };
struct Pacr1 : Register<0x20, 32>, Pacr { };
struct Pacr2 : Register<0x24, 32>, Pacr { };
struct Pacr3 : Register<0x28, 32>, Pacr { };
struct Pacr4 : Register<0x2c, 32>, Pacr { };
/**
* Configuration of the off-platform peripherals
*/
struct Opacr1 : Register<0x40, 32>, Pacr { };
struct Opacr2 : Register<0x44, 32>, Pacr { };
struct Opacr3 : Register<0x48, 32>, Pacr { };
struct Opacr4 : Register<0x4c, 32>, Pacr { };
struct Opacr5 : Register<0x50, 32>, Pacr { };
public:
/**
* Constructor
*/
Aipstz(Genode::addr_t const base) : Genode::Mmio(base) { }
/**
* Configure this module appropriately for the first kernel run
*/
void prepare_kernel()
{
/* avoid AIPS intervention at any memory access */
write<Mpr1>(Mpr::ALL_UNBUFFERED_AND_FULLY_TRUSTED);
write<Mpr2>(Mpr::ALL_UNBUFFERED_AND_FULLY_TRUSTED);
write<Pacr1>(Pacr::ALL_UNBUFFERED_AND_FULLY_UNPROTECTED);
write<Pacr2>(Pacr::ALL_UNBUFFERED_AND_FULLY_UNPROTECTED);
write<Pacr3>(Pacr::ALL_UNBUFFERED_AND_FULLY_UNPROTECTED);
write<Pacr4>(Pacr::ALL_UNBUFFERED_AND_FULLY_UNPROTECTED);
write<Opacr1>(Pacr::ALL_UNBUFFERED_AND_FULLY_UNPROTECTED);
write<Opacr2>(Pacr::ALL_UNBUFFERED_AND_FULLY_UNPROTECTED);
write<Opacr3>(Pacr::ALL_UNBUFFERED_AND_FULLY_UNPROTECTED);
write<Opacr4>(Pacr::ALL_UNBUFFERED_AND_FULLY_UNPROTECTED);
write<Opacr5>(Pacr::ALL_UNBUFFERED_AND_FULLY_UNPROTECTED);
}
};
struct Board : Genode::Board_base
{
/**
* static AIPS 1 instance
*/
static Aipstz * aips_1() { static Aipstz a(AIPS_1_MMIO_BASE); return &a; }
/**
* Static AIPS 2 instance
*/
static Aipstz * aips_2() { static Aipstz a(AIPS_2_MMIO_BASE); return &a; }
/**
* Configure this module appropriately for the first kernel run
*/
static void prepare_kernel()
{
aips_1()->prepare_kernel();
aips_2()->prepare_kernel();
}
};
}
namespace Genode { class Board : public Imx53::Board { }; }
#endif /* _IMX53__BOARD_H_ */

View File

@ -0,0 +1,29 @@
/*
* \brief CPU driver for core
* \author Martin Stein
* \date 2012-12-14
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _IMX53__CPU_H_
#define _IMX53__CPU_H_
/* core includes */
#include <cpu/arm_v7.h>
namespace Genode
{
/**
* CPU driver for core
*/
class Cpu : public Arm_v7::Cpu { };
}
#endif /* _IMX53__CPU_H_ */

View File

@ -0,0 +1,203 @@
/*
* \brief Programmable interrupt controller for core
* \author Stefan Kalkowski
* \date 2012-10-24
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _IMX53__PIC_H_
#define _IMX53__PIC_H_
/* Genode includes */
#include <util/mmio.h>
/* core includes */
#include <board.h>
namespace Imx53
{
using namespace Genode;
/**
* Programmable interrupt controller for core
*/
class Pic : public Mmio
{
public:
enum { MAX_INTERRUPT_ID = 108 };
protected:
/**
* Interrupt control register
*/
struct Intctrl : Register<0, 32>
{
struct Enable : Bitfield<0,1> { };
struct Nsen : Bitfield<16,1> { };
struct Nsen_mask : Bitfield<31,1> { };
};
struct Priomask : Register<0xc, 32>
{
struct Mask : Bitfield<0,8> { };
};
struct Syncctrl : Register<0x10, 32>
{
struct Syncmode : Bitfield<0,2> { };
};
struct Dsmint : Register<0x14, 32>
{
struct Dsm : Bitfield<0,1> { };
};
/**
* Interrupt security registers
*/
struct Intsec : Register_array<0x80, 32, MAX_INTERRUPT_ID+1, 1>
{
struct Nonsecure : Bitfield<0, 1> { };
};
/**
* Interrupt set enable registers
*/
struct Enset : Register_array<0x100, 32, MAX_INTERRUPT_ID+1, 1, true>
{
struct Set_enable : Bitfield<0, 1> { };
};
/**
* Interrupt clear enable registers
*/
struct Enclear : Register_array<0x180, 32, MAX_INTERRUPT_ID+1, 1, true>
{
struct Clear_enable : Bitfield<0, 1> { };
};
/**
* Interrupt priority level registers
*/
struct Icdipr : Register_array<0x400, 32, MAX_INTERRUPT_ID+1, 8>
{
struct Priority : Bitfield<0, 8>
{
enum { GET_MIN_PRIORITY = 0xff };
};
};
/**
* Pending registers
*/
struct Pndr : Register_array<0xd00, 32, MAX_INTERRUPT_ID+1, 1>
{
struct Pending : Bitfield<0, 1> { };
};
/**
* Highest interrupt pending registers
*/
struct Hipndr : Register_array<0xd80, 32, MAX_INTERRUPT_ID+1, 1, true>
{
struct Pending : Bitfield<0, 1> { };
};
/**
* Maximum supported interrupt priority
*/
unsigned _max_priority() { return 255; }
public:
/**
* Constructor, all interrupts get masked
*/
Pic() : Mmio(Board::TZIC_MMIO_BASE)
{
/* configure interrupts as nonsecure, and disable them */
for (unsigned i = 0; i <= MAX_INTERRUPT_ID; i++) {
write<Enclear::Clear_enable>(1, i);
write<Intsec::Nonsecure>(1, i);
}
write<Priomask::Mask>(0x1f);
write<Intctrl>(Intctrl::Enable::bits(1) |
Intctrl::Nsen::bits(1) |
Intctrl::Nsen_mask::bits(1));
}
/**
* Receive a pending request number 'i'
*/
bool take_request(unsigned & i)
{
for (unsigned j = 0; j <= MAX_INTERRUPT_ID; j++) {
if (read<Pndr::Pending>(j)) {
i = j;
return true;
}
}
return false;
}
/**
* Finish the last taken request
*/
void finish_request() { }
/**
* Validate request number 'i'
*/
bool valid(unsigned const i) const {
return i <= MAX_INTERRUPT_ID; }
/**
* Unmask all interrupts
*/
void unmask()
{
for (unsigned i=0; i <= MAX_INTERRUPT_ID; i++)
write<Enset::Set_enable>(1, i);
}
/**
* Mask all interrupts
*/
void mask()
{
for (unsigned i=0; i <= MAX_INTERRUPT_ID; i++)
write<Enclear::Clear_enable>(1, i);
}
/**
* Unmask interrupt 'i'
*/
void unmask(unsigned const i)
{
if (i <= MAX_INTERRUPT_ID)
write<Enset::Set_enable>(1, i);
}
/**
* Mask interrupt 'i'
*/
void mask(unsigned const i)
{
if (i <= MAX_INTERRUPT_ID)
write<Enclear::Clear_enable>(1, i);
}
};
}
namespace Kernel { class Pic : public Imx53::Pic { }; }
#endif /* _IMX53__PIC_H_ */

View File

@ -0,0 +1,83 @@
/*
* \brief Specific core implementations
* \author Stefan Kalkowski
* \date 2012-10-24
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* core includes */
#include <platform.h>
#include <board.h>
#include <pic.h>
using namespace Genode;
Native_region * Platform::_ram_regions(unsigned const i)
{
static Native_region _regions[] =
{
{ Board::RAM_BASE, Board::RAM_SIZE }
};
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
}
Native_region * Platform::_irq_regions(unsigned const i)
{
static Native_region _regions[] =
{
{ 0, Imx53::Pic::MAX_INTERRUPT_ID + 1 }
};
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
}
Native_region * Platform::_core_only_irq_regions(unsigned const i)
{
static Native_region _regions[] =
{
/* core timer */
{ Board::EPIT_1_IRQ, 1 },
/* core UART */
{ Board::UART_1_IRQ, 1 }
};
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
}
Native_region * Platform::_mmio_regions(unsigned const i)
{
static Native_region _regions[] =
{
{ 0x07000000, 0x1000000 }, /* security controller */
{ 0x10000000, 0x30000000 }, /* SATA, IPU, GPU */
{ 0x50000000, 0x20000000 }, /* Misc. */
};
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
}
Native_region * Platform::_core_only_mmio_regions(unsigned const i)
{
static Native_region _regions[] =
{
/* core UART */
{ Board::UART_1_MMIO_BASE, Board::UART_1_MMIO_SIZE },
/* core timer */
{ Board::EPIT_1_MMIO_BASE, Board::EPIT_1_MMIO_SIZE },
/* interrupt controller */
{ Board::TZIC_MMIO_BASE, Board::TZIC_MMIO_SIZE },
};
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
}

View File

@ -0,0 +1,44 @@
#
# \brief Build config for Genodes core process
# \author Stefan Kalkowski
# \author Martin Stein
# \date 2012-10-24
#
# declare wich specs must be given to build this target
REQUIRES = platform_imx53
# add include paths
INC_DIR += $(REP_DIR)/src/core/imx53
# add C++ sources
SRC_CC += platform_services.cc \
platform_support.cc \
syscall.cc
# add assembly sources
SRC_S += mode_transition.s \
boot_modules.s \
crt0.s
# declare source paths
vpath platform_services.cc $(BASE_DIR)/src/core
vpath platform_support.cc $(REP_DIR)/src/core/imx53
vpath mode_transition.s $(REP_DIR)/src/core/arm_v7
vpath syscall.cc $(REP_DIR)/src/base/arm
vpath crt0.s $(REP_DIR)/src/core/arm
#
# Check if there are other images wich shall be linked to core.
# If not use a dummy boot-modules file wich includes only the symbols.
#
ifeq ($(wildcard $(BUILD_BASE_DIR)/boot_modules.s),)
vpath boot_modules.s $(REP_DIR)/src/core/arm
else
INC_DIR += $(BUILD_BASE_DIR)
vpath boot_modules.s $(BUILD_BASE_DIR)
endif
# include less specific target parts
include $(REP_DIR)/src/core/target.inc

View File

@ -0,0 +1,42 @@
/*
* \brief Timer for kernel
* \author Martin Stein
* \date 2012-04-23
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _IMX53__TIMER_H_
#define _IMX53__TIMER_H_
/* core includes */
#include <board.h>
#include <drivers/timer/epit_base.h>
namespace Imx53
{
/**
* Kernel timer
*/
class Timer : public Genode::Epit_base
{
public:
enum { IRQ = Board::EPIT_1_IRQ };
/**
* Constructor
*/
Timer() : Epit_base(Board::EPIT_1_MMIO_BASE) { }
};
}
namespace Kernel { class Timer : public Imx53::Timer { }; }
#endif /* _IMX53__TIMER_H_ */

View File

@ -0,0 +1,47 @@
/*
* \brief Translation lookaside buffer
* \author Stefan Kalkowski
* \author Martin Stein
* \date 2012-10-24
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _IMX53__TLB_H_
#define _IMX53__TLB_H_
/* core includes */
#include <board.h>
#include <tlb/arm_v7.h>
namespace Genode
{
struct Page_flags : Arm::Page_flags { };
class Tlb : public Arm_v7::Section_table { };
/**
* Translation lookaside buffer of core
*/
class Core_tlb : public Tlb
{
public:
/**
* Constructor - ensures that core never gets a pagefault
*/
Core_tlb()
{
map_core_area(Board::RAM_BASE, Board::RAM_SIZE, 0);
map_core_area(Board::MMIO_BASE, Board::MMIO_SIZE, 1);
}
};
}
#endif /* _IMX53__TLB_H_ */

View File

@ -0,0 +1,174 @@
/*
* \brief Driver base for the Enhanced Periodic Interrupt Timer (Freescale)
* \author Norman Feske
* \author Martin Stein
* \author Stefan Kalkowski
* \date 2012-10-25
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__DRIVERS__TIMER__EPIT_BASE_H_
#define _INCLUDE__DRIVERS__TIMER__EPIT_BASE_H_
/* Genode includes */
#include <util/mmio.h>
namespace Genode
{
/**
* Core timer
*/
class Epit_base : public Mmio
{
protected:
enum { TICS_PER_MS = 32 };
/**
* Control register
*/
struct Cr : Register<0x0, 32>
{
struct En : Bitfield<0, 1> { }; /* enable timer */
struct En_mod : Bitfield<1, 1> /* reload on enable */
{
enum { RELOAD = 1 };
};
struct Oci_en : Bitfield<2, 1> { }; /* interrupt on compare */
struct Rld : Bitfield<3, 1> /* reload or roll-over */
{
enum { RELOAD_FROM_LR = 1 };
};
struct Prescaler : Bitfield<4, 12> /* clock input divisor */
{
enum { DIVIDE_BY_1 = 0 };
};
struct Swr : Bitfield<16, 1> { }; /* software reset bit */
struct Iovw : Bitfield<17, 1> { }; /* enable overwrite */
struct Dbg_en : Bitfield<18, 1> { }; /* enable in debug mode */
struct Wait_en : Bitfield<19, 1> { }; /* enable in wait mode */
struct Doz_en : Bitfield<20, 1> { }; /* enable in doze mode */
struct Stop_en : Bitfield<21, 1> { }; /* enable in stop mode */
struct Om : Bitfield<22, 2> /* mode of the output pin */
{
enum { DISCONNECTED = 0 };
};
struct Clk_src : Bitfield<24, 2> /* select clock input */
{
enum { IPG_CLK_32K = 3 };
};
/**
* Register value that configures the timer for a one-shot run
*/
static access_t prepare_one_shot()
{
return En::bits(0) |
En_mod::bits(En_mod::RELOAD) |
Oci_en::bits(1) |
Rld::bits(Rld::RELOAD_FROM_LR) |
Prescaler::bits(Prescaler::DIVIDE_BY_1) |
Swr::bits(0) |
Iovw::bits(0) |
Dbg_en::bits(0) |
Wait_en::bits(0) |
Doz_en::bits(0) |
Stop_en::bits(0) |
Om::bits(Om::DISCONNECTED) |
Clk_src::bits(Clk_src::IPG_CLK_32K);
}
};
/**
* Status register
*/
struct Sr : Register<0x4, 32>
{
struct Ocif : Bitfield<0, 1> { }; /* IRQ status, write 1 clears */
};
struct Lr : Register<0x8, 32> { }; /* load value register */
struct Cmpr : Register<0xc, 32> { }; /* compare value register */
struct Cnt : Register<0x10, 32> { }; /* counter register */
/**
* Disable timer and clear its interrupt output
*/
void _reset()
{
/* wait until ongoing reset operations are finished */
while (read<Cr::Swr>()) ;
/* disable timer */
write<Cr::En>(0);
clear_interrupt();
}
public:
/**
* Constructor
*/
Epit_base(addr_t base) : Mmio(base) { _reset(); }
/**
* Start a one-shot run
*
* \param tics native timer value used to assess the delay
* of the timer interrupt as of the call
*/
void start_one_shot(unsigned const tics)
{
/* stop timer */
_reset();
/* configure timer for a one-shot */
write<Cr>(Cr::prepare_one_shot());
write<Lr>(tics);
write<Cmpr>(0);
/* start timer */
write<Cr::En>(1);
}
/**
* Stop the timer from a one-shot run
*
* \return last native timer value of the one-shot run
*/
unsigned long stop_one_shot()
{
/* disable timer */
write<Cr::En>(0);
/* if the timer has hit zero already return 0 */
return read<Sr::Ocif>() ? 0 : read<Cnt>();
}
/**
* Clear interrupt output line
*/
void clear_interrupt() { write<Sr::Ocif>(1); }
/**
* Translate milliseconds to a native timer value
*/
static unsigned ms_to_tics(unsigned const ms) {
return TICS_PER_MS * ms; }
};
}
#endif /* _INCLUDE__DRIVERS__TIMER__EPIT_BASE_H_ */

View File

@ -0,0 +1,55 @@
/*
* \brief Board definitions for the i.MX53
* \author Stefan Kalkowski
* \date 2012-10-24
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__PLATFORM__IMX53__DRIVERS__BOARD_BASE_H_
#define _INCLUDE__PLATFORM__IMX53__DRIVERS__BOARD_BASE_H_
namespace Genode
{
/**
* i.MX53 motherboard
*/
struct Board_base
{
enum {
MMIO_BASE = 0x0,
MMIO_SIZE = 0x70000000,
RAM_BASE = 0x70000000,
RAM_SIZE = 0x40000000,
UART_1_IRQ = 31,
UART_1_MMIO_BASE = 0x53fbc000,
UART_1_MMIO_SIZE = 0x00004000,
EPIT_1_IRQ = 40,
EPIT_1_MMIO_BASE = 0x53fac000,
EPIT_1_MMIO_SIZE = 0x00004000,
EPIT_2_IRQ = 41,
EPIT_2_MMIO_BASE = 0x53fb0000,
EPIT_2_MMIO_SIZE = 0x00004000,
TZIC_MMIO_BASE = 0x0fffc000,
TZIC_MMIO_SIZE = 0x00004000,
AIPS_1_MMIO_BASE = 0x53f00000,
AIPS_2_MMIO_BASE = 0x63f00000,
SECURITY_EXTENSION = 1,
};
};
}
#endif /* _INCLUDE__PLATFORM__IMX53__DRIVERS__BOARD_BASE_H_ */

View File

@ -5,10 +5,11 @@
#
# denote wich specs are also fullfilled by this spec
SPECS += cortex_a8 imx53 imx
SPECS += cortex_a8 imx53 imx epit
# add repository relative include paths
REP_INC_DIR += include/platform/imx53
# include implied specs
include $(call select_from_repositories,mk/spec-cortex_a8.mk)

View File

@ -0,0 +1 @@
REPOSITORIES += $(GENODE_DIR)/base-hw

View File

@ -31,6 +31,7 @@ usage:
@echo " 'hw_vea9x4'"
@echo " 'hw_pbxa9'"
@echo " 'hw_imx31'"
@echo " 'hw_imx53'"
@echo " 'foc_x86_32'"
@echo " 'foc_x86_64'"
@echo " 'foc_pbxa9'"
@ -197,6 +198,9 @@ hw_panda::
hw_imx31::
@echo "SPECS = genode hw_imx31" > $(BUILD_DIR)/etc/specs.conf
hw_imx53::
@echo "SPECS = genode hw_imx53" > $(BUILD_DIR)/etc/specs.conf
lx_hybrid_x86::
@echo "CROSS_DEV_PREFIX =" > $(BUILD_DIR)/etc/tools.conf
@echo "SPECS += always_hybrid" >> $(BUILD_DIR)/etc/specs.conf