Kernel updates since December 2009

This commit is contained in:
Bahadir Balban
2010-03-25 01:12:40 +02:00
parent 16818191b3
commit 74b5963fcb
487 changed files with 22477 additions and 3857 deletions

View 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
View 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
View 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,
},
};

View 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();
}

View 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();
}

View 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);
}