mirror of
https://github.com/drasko/codezero.git
synced 2026-01-21 15:23:15 +01:00
Kernel updates since December 2009
This commit is contained in:
11
src/platform/beagle/SConscript
Normal file
11
src/platform/beagle/SConscript
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
|
||||
# Inherit global environment
|
||||
Import('env')
|
||||
|
||||
# The set of source files associated with this SConscript file.
|
||||
src_local = ['print-early.c', 'platform.c', 'perfmon.c', 'irq.c', 'cm.c']
|
||||
|
||||
obj = env.Object(src_local)
|
||||
|
||||
Return('obj')
|
||||
45
src/platform/beagle/cm.c
Normal file
45
src/platform/beagle/cm.c
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Clock mangaer module of the beagleboard.
|
||||
*
|
||||
* Copyright (C) 2007 Bahadir Balban
|
||||
*
|
||||
*/
|
||||
|
||||
#include INC_PLAT(cm.h)
|
||||
#include INC_ARCH(io.h)
|
||||
|
||||
/*
|
||||
* Enable Interface clock of device (represented by bit)
|
||||
* in CM module's(represented by CM_BASE) CM_FCLEN register
|
||||
*/
|
||||
void omap_cm_enable_iclk(unsigned long cm_base, int bit)
|
||||
{
|
||||
unsigned int val = 0;
|
||||
|
||||
val = read((cm_base + CM_FCLKEN_OFFSET));
|
||||
val |= (1 << bit);
|
||||
write(val, (cm_base + CM_FCLKEN_OFFSET));
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable Functional clock of device (represented by bit)
|
||||
* in CM module's(represented by CM_BASE) CM_FCLEN register
|
||||
*/
|
||||
void omap_cm_enable_fclk(unsigned long cm_base, int bit)
|
||||
{
|
||||
unsigned int val = 0;
|
||||
|
||||
val = read((cm_base + CM_ICLKEN_OFFSET));
|
||||
val |= (1 << bit);
|
||||
write(val, (cm_base + CM_FCLKEN_OFFSET));
|
||||
}
|
||||
|
||||
/* Set clock source for device */
|
||||
void omap_cm_clk_select(unsigned long cm_base, int bit, int src)
|
||||
{
|
||||
unsigned int val = 0;
|
||||
|
||||
val = read((cm_base + CM_CLKSEL_OFFSET));
|
||||
val |= (src << bit);
|
||||
write(val, (cm_base + CM_CLKSEL_OFFSET));
|
||||
}
|
||||
66
src/platform/beagle/irq.c
Normal file
66
src/platform/beagle/irq.c
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Support for generic irq handling using platform irq controller (PL190)
|
||||
*
|
||||
* Copyright (C) 2007 Bahadir Balban
|
||||
*/
|
||||
#include <l4/generic/platform.h>
|
||||
#include <l4/generic/irq.h>
|
||||
#include <l4/generic/time.h>
|
||||
#include INC_PLAT(irq.h)
|
||||
#include INC_PLAT(platform.h)
|
||||
#include INC_PLAT(timer.h)
|
||||
#include INC_ARCH(exception.h)
|
||||
#include <l4/drivers/irq/omap3/omap3_intc.h>
|
||||
|
||||
struct irq_chip irq_chip_array[IRQ_CHIPS_MAX] = {
|
||||
[0] = {
|
||||
.name = "OMAP 3 irq controller",
|
||||
.level = 0,
|
||||
.cascade = IRQ_NIL,
|
||||
.start = 0,
|
||||
.end = IRQS_MAX,
|
||||
.ops = {
|
||||
.init = omap3_intc_init,
|
||||
.read_irq = omap3_intc_read_irq,
|
||||
.ack_and_mask = omap3_intc_ack_and_mask,
|
||||
.unmask = omap3_intc_unmask_irq,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static int platform_timer_handler(struct irq_desc *desc)
|
||||
{
|
||||
timer_irq_clear(PLATFORM_TIMER0_VBASE);
|
||||
|
||||
return do_timer_irq();
|
||||
}
|
||||
|
||||
/*
|
||||
* Timer handler for userspace
|
||||
*/
|
||||
static int platform_timer_user_handler(struct irq_desc *desc)
|
||||
{
|
||||
/* Ack the device irq */
|
||||
timer_irq_clear(PLATFORM_TIMER1_VBASE);
|
||||
|
||||
/* Notify the userspace */
|
||||
irq_thread_notify(desc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Built-in irq handlers initialised at compile time.
|
||||
* Else register with register_irq() */
|
||||
struct irq_desc irq_desc_array[IRQS_MAX] = {
|
||||
[IRQ_TIMER0] = {
|
||||
.name = "Timer0",
|
||||
.chip = &irq_chip_array[0],
|
||||
.handler = platform_timer_handler,
|
||||
},
|
||||
[IRQ_TIMER1] = {
|
||||
.name = "Timer1",
|
||||
.chip = &irq_chip_array[0],
|
||||
.handler = platform_timer_user_handler,
|
||||
},
|
||||
};
|
||||
|
||||
89
src/platform/beagle/perfmon.c
Normal file
89
src/platform/beagle/perfmon.c
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Platform specific perfmon initialization
|
||||
*
|
||||
* Copyright (C) 2010 B Labs Ltd.
|
||||
*
|
||||
* Author: Bahadir Balban
|
||||
*/
|
||||
#include INC_PLAT(timer.h)
|
||||
#include <l4/lib/printk.h>
|
||||
#include INC_PLAT(offsets.h)
|
||||
#include INC_SUBARCH(perfmon.h)
|
||||
#include INC_SUBARCH(mmu_ops.h)
|
||||
#include INC_GLUE(memlayout.h)
|
||||
/*
|
||||
* Current findings by these tests:
|
||||
*
|
||||
* Cpu cycle count and timer ticks are consistently showing 400Mhz
|
||||
* with a reference timer tick of 1Mhz. So cycle counts are fixed
|
||||
* with regard to the timer.
|
||||
*
|
||||
* Instruction execute count on the busy_loop however, is varying
|
||||
* between x1, x2 combinations when compared to timer and cycle
|
||||
* count values. This is happening by trivial changes in code such
|
||||
* as adding a function call. (Other variables are ruled out, e.g.
|
||||
* no concurrent memory accesses, caches are off)
|
||||
*
|
||||
* There may be two causes to this:
|
||||
* - Due to missing dmb/dsb/isb instructions.
|
||||
* - Due to BTC (busy_loop has one branch) which may describe
|
||||
* the doubling in IPC, since out of the 2 instructions in the
|
||||
* busy loop one is a branch.
|
||||
*
|
||||
* Disabling the BTC increased cycle counts per instruction
|
||||
* significantly, advising us not to expect any accuracy in counting
|
||||
* instructions in cycles. Hence instruction-based tests are
|
||||
* commented out. It is wise to only rely upon timer and cycle counts.
|
||||
*/
|
||||
void platform_test_tick_cycles()
|
||||
{
|
||||
/* Initialize the timer */
|
||||
const unsigned int load_value = 0xffffffff - 100000;
|
||||
int mhz_top, mhz_bot, temp;
|
||||
unsigned long timer_base = PLATFORM_TIMER1_VBASE;
|
||||
int cyccnt;
|
||||
|
||||
/* Make sure timer is disabled */
|
||||
timer_stop(timer_base);
|
||||
|
||||
/* One shot, 32 bits, no irqs */
|
||||
timer_init_oneshot(timer_base);
|
||||
|
||||
/* Load the timer with ticks value */
|
||||
timer_load(timer_base, load_value);
|
||||
|
||||
/* Start the timer */
|
||||
timer_start(timer_base);
|
||||
|
||||
/* Start counter */
|
||||
perfmon_reset_start_cyccnt();
|
||||
|
||||
/* Wait until 0 */
|
||||
while (timer_read(timer_base) != 0)
|
||||
;
|
||||
|
||||
cyccnt = perfmon_read_cyccnt();
|
||||
|
||||
/* Fixed-point accuracy on bottom digit */
|
||||
temp = cyccnt * 64 * 10 * 13 / 100000;
|
||||
mhz_top = temp / 10;
|
||||
mhz_bot = temp - mhz_top * 10;
|
||||
|
||||
printk("Perfmon: 0x%x cycle count \n", cyccnt);
|
||||
printk("%s: %d.%d MHz CPU speed measured by timer REFCLK at 13MHz\n",
|
||||
__KERNELNAME__, mhz_top, mhz_bot);
|
||||
}
|
||||
|
||||
void platform_test_cpucycles(void)
|
||||
{
|
||||
/*
|
||||
* Variable results:
|
||||
*
|
||||
* platform_test_loop_cycles();
|
||||
* platform_test_loop_ticks();
|
||||
*/
|
||||
|
||||
/* Fixed result */
|
||||
platform_test_tick_cycles();
|
||||
}
|
||||
|
||||
142
src/platform/beagle/platform.c
Normal file
142
src/platform/beagle/platform.c
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Beagle Board platform-specific initialisation and setup
|
||||
*
|
||||
* Copyright (C) 2007 Bahadir Balban
|
||||
*/
|
||||
#include <l4/generic/platform.h>
|
||||
#include <l4/generic/space.h>
|
||||
#include <l4/generic/irq.h>
|
||||
#include <l4/generic/bootmem.h>
|
||||
#include INC_ARCH(linker.h)
|
||||
#include INC_SUBARCH(mm.h)
|
||||
#include INC_GLUE(mapping.h)
|
||||
#include INC_SUBARCH(mmu_ops.h)
|
||||
#include INC_GLUE(memory.h)
|
||||
#include INC_PLAT(platform.h)
|
||||
#include INC_PLAT(uart.h)
|
||||
#include INC_PLAT(timer.h)
|
||||
#include INC_PLAT(irq.h)
|
||||
#include INC_ARCH(asm.h)
|
||||
#include INC_PLAT(cm.h)
|
||||
|
||||
/*
|
||||
* The devices that are used by the kernel are mapped
|
||||
* independent of these capabilities, but these provide a
|
||||
* concise description of what is used by the kernel.
|
||||
*/
|
||||
int platform_setup_device_caps(struct kernel_resources *kres)
|
||||
{
|
||||
struct capability *timer[1];
|
||||
|
||||
/* Setup timer1 capability as free */
|
||||
timer[0] = alloc_bootmem(sizeof(*timer[0]), 0);
|
||||
timer[0]->start = __pfn(PLATFORM_TIMER1_BASE);
|
||||
timer[0]->end = timer[0]->start + 1;
|
||||
timer[0]->size = timer[0]->end - timer[0]->start;
|
||||
cap_set_devtype(timer[0], CAP_DEVTYPE_TIMER);
|
||||
cap_set_devnum(timer[0], 1);
|
||||
link_init(&timer[0]->list);
|
||||
cap_list_insert(timer[0], &kres->devmem_free);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use UART2 for kernel as well as user tasks,
|
||||
* so map it to kernel and user space, this only
|
||||
* is provided by beagle board
|
||||
*/
|
||||
void init_platform_console(void)
|
||||
{
|
||||
add_boot_mapping(PLATFORM_UART2_BASE, PLATFORM_CONSOLE_VBASE,
|
||||
PAGE_SIZE, MAP_IO_DEFAULT);
|
||||
|
||||
add_boot_mapping(PLATFORM_PERCM_BASE, PLATFORM_PERCM_VBASE,
|
||||
PAGE_SIZE, MAP_IO_DEFAULT);
|
||||
|
||||
/*
|
||||
* Map same UART IO area to userspace so that primitive uart-based
|
||||
* userspace printf can work. Note, this raw mapping is to be
|
||||
* removed in the future, when file-based io is implemented.
|
||||
*/
|
||||
add_boot_mapping(PLATFORM_UART2_BASE, USERSPACE_CONSOLE_VBASE,
|
||||
PAGE_SIZE, MAP_USR_IO);
|
||||
|
||||
/* use 32KHz clock signal */
|
||||
omap_cm_clk_select(PLATFORM_PERCM_VBASE, 11,
|
||||
OMAP_TIMER_CLKSRC_SYS_CLK);
|
||||
|
||||
/* Enable Interface and Functional clock */
|
||||
omap_cm_enable_iclk(PLATFORM_PERCM_VBASE, 11);
|
||||
omap_cm_enable_fclk(PLATFORM_PERCM_VBASE, 11);
|
||||
|
||||
uart_init(PLATFORM_CONSOLE_VBASE);
|
||||
}
|
||||
|
||||
void platform_timer_start(void)
|
||||
{
|
||||
/* Enable irq line for TIMER0 */
|
||||
irq_enable(IRQ_TIMER0);
|
||||
|
||||
/* Enable timer */
|
||||
timer_start(PLATFORM_TIMER0_VBASE);
|
||||
}
|
||||
|
||||
/*
|
||||
* We are using GPTIMER1 only, so we map GPTIMER1 base,
|
||||
* incase any other timer is needed we need to map it
|
||||
* to userspace or kernel space as needed
|
||||
*/
|
||||
void init_platform_timer(void)
|
||||
{
|
||||
add_boot_mapping(PLATFORM_TIMER0_BASE, PLATFORM_TIMER0_VBASE,
|
||||
PAGE_SIZE, MAP_IO_DEFAULT);
|
||||
|
||||
add_boot_mapping(PLATFORM_WKUP_CM_BASE, PLATFORM_WKUP_CM_VBASE,
|
||||
PAGE_SIZE, MAP_IO_DEFAULT);
|
||||
|
||||
#if 0
|
||||
/* use 32KHz clock signal */
|
||||
omap_cm_clk_select(PLATFORM_WKUP_CM_VBASE, 0,
|
||||
OMAP_TIMER_CLKSRC_32KHZ_CLK);
|
||||
#else
|
||||
/*
|
||||
* Assumption: Beagle board RevC manual says,
|
||||
* it has 26MHz oscillator present, so we are
|
||||
* assuming this oscillator is our system clock
|
||||
*/
|
||||
omap_cm_clk_select(PLATFORM_WKUP_CM_VBASE, 0,
|
||||
OMAP_TIMER_CLKSRC_SYS_CLK);
|
||||
#endif
|
||||
|
||||
/* Enable Interface and Functional clock */
|
||||
omap_cm_enable_iclk(PLATFORM_WKUP_CM_VBASE, 0);
|
||||
omap_cm_enable_fclk(PLATFORM_WKUP_CM_VBASE, 0);
|
||||
|
||||
timer_init(PLATFORM_TIMER0_VBASE);
|
||||
}
|
||||
|
||||
void init_platform_irq_controller()
|
||||
{
|
||||
add_boot_mapping(PLATFORM_INTC_BASE, PLATFORM_INTC_VBASE,
|
||||
PAGE_SIZE, MAP_IO_DEFAULT);
|
||||
|
||||
irq_controllers_init();
|
||||
}
|
||||
|
||||
void init_platform_devices()
|
||||
{
|
||||
/* Add userspace devices here as you develop their irq handlers */
|
||||
add_boot_mapping(PLATFORM_TIMER1_BASE, PLATFORM_TIMER1_VBASE,
|
||||
PAGE_SIZE, MAP_IO_DEFAULT);
|
||||
|
||||
}
|
||||
|
||||
void platform_init(void)
|
||||
{
|
||||
init_platform_console();
|
||||
init_platform_timer();
|
||||
init_platform_irq_controller();
|
||||
init_platform_devices();
|
||||
}
|
||||
|
||||
75
src/platform/beagle/print-early.c
Normal file
75
src/platform/beagle/print-early.c
Normal file
@@ -0,0 +1,75 @@
|
||||
|
||||
#include INC_PLAT(uart.h)
|
||||
#include INC_PLAT(offsets.h)
|
||||
#include INC_ARCH(io.h)
|
||||
|
||||
void print_early(char *str)
|
||||
{
|
||||
unsigned int reg = 0;
|
||||
unsigned long uart_base;
|
||||
|
||||
/* Check if mmu is on */
|
||||
__asm__ __volatile__ (
|
||||
"mrc p15, 0, %0, c1, c0"
|
||||
: "=r" (reg)
|
||||
: "r" (reg)
|
||||
);
|
||||
|
||||
/*
|
||||
* Get uart phys/virt base based on mmu on/off
|
||||
* Also strings are linked at virtual address, so if
|
||||
* we are running with mmu off we should translate
|
||||
* string address to physical
|
||||
*/
|
||||
if (reg & 1) {
|
||||
uart_base = PLATFORM_CONSOLE_VBASE;
|
||||
}
|
||||
else {
|
||||
uart_base = PLATFORM_UART2_BASE;
|
||||
str = (char *)(((unsigned long)str & ~KERNEL_AREA_START) |
|
||||
PLATFORM_PHYS_MEM_START);
|
||||
}
|
||||
|
||||
/* call uart tx function */
|
||||
while (*str != '\0') {
|
||||
uart_tx_char(uart_base, *str);
|
||||
|
||||
if (*str == '\n')
|
||||
uart_tx_char(uart_base, '\r');
|
||||
++str;
|
||||
}
|
||||
}
|
||||
|
||||
void printhex8(unsigned int val)
|
||||
{
|
||||
char hexbuf[16];
|
||||
char *temp = hexbuf + 15;
|
||||
int v;
|
||||
|
||||
/* put end of string */
|
||||
*(temp--) = '\0';
|
||||
|
||||
if (!val) {
|
||||
*temp = '0';
|
||||
}
|
||||
else {
|
||||
while (val) {
|
||||
v = val & 0xf;
|
||||
val = val >> 4;
|
||||
--temp;
|
||||
|
||||
/* convert decimal value to ascii */
|
||||
if (v >= 10)
|
||||
v += ('a' - 10);
|
||||
else
|
||||
v = v + '0';
|
||||
|
||||
*temp = *((char *)&v);
|
||||
}
|
||||
}
|
||||
|
||||
*(--temp) = 'x';
|
||||
*(--temp) = '0';
|
||||
print_early(temp);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user