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

@@ -15,29 +15,32 @@ sys.path.append(PROJRELROOT)
from config.configuration import *
from config.projpaths import *
Import('env', 'arch', 'platform', 'type')
Import('env', 'platform', 'type')
variant = type
# Path for uart files
LIBDEV_UART_PATH = join(PROJROOT, 'conts/libdev/uart')
# To include setbit/clrbit functions
LIBL4_RELDIR = 'conts/libl4'
LIBL4_DIR = join(PROJROOT, LIBL4_RELDIR)
LIBL4_INC = join(LIBL4_DIR, 'include')
# Path for timer files
LIBDEV_TIEMR_PATH = join(PROJROOT, 'conts/libdev/timer/sp804')
# Path for clcd files
LIBDEV_CLCD_PATH = join(PROJROOT, 'conts/libdev/clcd/pl110')
LIBC_RELDIR = 'conts/libc'
LIBC_DIR = join(PROJROOT, LIBC_RELDIR)
LIBC_INC = join(LIBC_DIR, 'include')
e = env.Clone()
e.Append(CPPPATH = [LIBDEV_UART_PATH + '/include', LIBDEV_TIEMR_PATH + '/include',
LIBDEV_CLCD_PATH + '/include',],
CCFLAGS = ['-nostdinc', '-DVARIANT_' + variant.upper(),
'-DPLATFORM_' + platform.upper()])
e.Append(CPPPATH = ['#conts/libdev/include', LIBC_INC, LIBL4_INC],
CCFLAGS = ['-DVARIANT_' + variant.upper()])
source = Glob('uart/src' + '/*.c') + \
Glob('timer/sp804/src' + '/*.c') + \
Glob('clcd/pl110/src' + '/*.c')
objects = []
objects += SConscript('uart/pl011/SConscript', duplicate=0, \
exports = {'platform' : platform, 'env' : e})
objects += SConscript('timer/sp804/SConscript', duplicate=0, \
exports = {'platform' : platform, 'env' : e})
objects += SConscript('uart/omap/SConscript', duplicate=0, \
exports = {'platform' : platform, 'env' : e})
objects += SConscript('timer/omap/SConscript', duplicate=0, \
exports = {'platform' : platform, 'env' : e})
objects = e.StaticObject(source)
library = e.StaticLibrary('libdev-' + variant, objects)
Return('library')

51
conts/libdev/SConstruct Normal file
View File

@@ -0,0 +1,51 @@
# -*- mode: python; coding: utf-8; -*-
#
# Codezero -- a microkernel for embedded systems.
#
# Copyright © 2009 B Labs Ltd
#
import os, sys
PROJRELROOT = '../..'
sys.path.append(PROJRELROOT)
from config.projpaths import *
from config.configuration import *
config = configuration_retrieve()
gcc_arch_flag = config.gcc_arch_flag
platform = config.platform
# We assume we are compiling for userspace.
# variant can be specified from cmdline using
# scons variant=xxx
variant = ARGUMENTS.get('variant', 'userspace')
print '\nCompiling for variant: ' + variant + '\n'
# To include setbit/clrbit functions
LIBL4_RELDIR = 'conts/libl4'
LIBL4_DIR = join(PROJROOT, LIBL4_RELDIR)
LIBL4_INC = join(LIBL4_DIR, 'include')
LIBC_RELDIR = 'conts/libc'
LIBC_DIR = join(PROJROOT, LIBC_RELDIR)
LIBC_INC = join(LIBC_DIR, 'include')
env = Environment(CC = config.toolchain + 'gcc',
CCFLAGS = ['-g', '-nostdlib', '-ffreestanding', '-std=gnu99', \
'-nostdinc', '-Wall', '-DVARIANT_' + variant.upper(), \
'-march=' + gcc_arch_flag, '-Werror'],
LINKFLAGS = ['-nostdlib'],
ASFLAGS = ['-D__ASSEMBLY__'],
ENV = {'PATH' : os.environ['PATH']},
CPPPATH = ['#include', LIBC_INC, LIBL4_INC, join(PROJROOT,'include')])
objects = []
objects += SConscript('uart/pl011/SConscript', duplicate=0, \
exports = {'platform' : platform, 'env' : env})
objects += SConscript('timer/sp804/SConscript', duplicate=0, \
exports = {'platform' : platform, 'env' : env})
library = env.StaticLibrary('libdev-' + variant, objects)

View File

@@ -0,0 +1,12 @@
/*
* IO functions/macros.
*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __LIBDEV_IO_H__
#define __LIBDEV_IO_H__
#define read(address) *((volatile unsigned int *)(address))
#define write(val, address) *((volatile unsigned int *)(address)) = val
#endif /* __LIBDEV_IO_H__ */

View File

@@ -0,0 +1,23 @@
/*
* Generic timer library API
*
* Copyright (C) 2010 B Labs Ltd.
*
* Author: Bahadir Balban
*/
#ifndef __LIBDEV_TIMER_H__
#define __LIBDEV_TIMER_H__
/*
* Simple API for the primary timer
* for userspace
*/
void timer_start(unsigned long timer_base);
void timer_load(u32 val, unsigned long timer_base);
u32 timer_read(unsigned long timer_base);
void timer_stop(unsigned long timer_base);
void timer_init_oneshot(unsigned long timer_base);
void timer_init_periodic(unsigned long timer_base);
void timer_init(unsigned long timer_base);
#endif /* __LIBDEV_TIMER_H__ */

View File

@@ -0,0 +1,21 @@
/*
* Generic uart API
*
* Copyright (C) 2010 B Labs Ltd.
*
* Author: Bahadir Balban
*/
#ifndef __LIBDEV_UART_H__
#define __LIBDEV_UART_H__
void uart_tx_char(unsigned long uart_base, char c);
char uart_rx_char(unsigned long uart_base);
void uart_set_baudrate(unsigned long uart_base, unsigned int val);
void uart_init(unsigned long base);
/*
* Base of primary uart used for printf
*/
extern unsigned long uart_print_base;
#endif /* __LIBDEV_UART_H__ */

View File

@@ -0,0 +1,15 @@
Import('env', 'platform')
#Platforms using omap_uart
plat_list = 'beagle'
# The set of source files associated with this SConscript file.
src_local = []
#for plat_supported in plat_list:
#if plat_supported == platform:
if plat_list == platform:
src_local += ['timer.c']
obj = env.StaticObject(src_local)
Return('obj')

View File

@@ -0,0 +1,97 @@
/*
* omap GP timer driver honoring generic
* timer library API
*
* Copyright (C) 2010 B Labs Ltd.
*
* Author: Bahadir Balban
*/
#include <libdev/io.h>
#include <l4lib/types.h>
#include "timer.h"
#define OMAP_TIMER_MAT_IT_FLAG (1 << 0)
#define OMAP_TIMER_OVR_IT_FLAG (1 << 1)
#define OMAP_TIMER_TCAR_IT_FLAG (1 << 2)
u32 timer_periodic_intr_status(unsigned long timer_base)
{
volatile u32 reg = read(timer_base + OMAP_TIMER_TISR);
return (reg & OMAP_TIMER_OVR_IT_FLAG);
}
#define OMAP_TIMER_SOFT_RESET (1 << 1)
void timer_reset(unsigned long timer_base)
{
/* Reset Timer */
write(OMAP_TIMER_SOFT_RESET, timer_base + OMAP_TIMER_TIOCP);
/* Wait for reset completion */
while (!read(timer_base + OMAP_TIMER_TSTAT));
}
void timer_load(unsigned long timer_base, u32 value)
{
write(value, timer_base + OMAP_TIMER_TLDR);
write(value, timer_base + OMAP_TIMER_TCRR);
}
u32 timer_read(unsigned long timer_base)
{
return read(timer_base + OMAP_TIMER_TCRR);
}
#define OMAP_TIMER_START (1 << 0)
void timer_start(unsigned long timer_base)
{
volatile u32 reg = read(timer_base + OMAP_TIMER_TCLR);
reg |= OMAP_TIMER_START;
write(reg, timer_base + OMAP_TIMER_TCLR);
}
void timer_stop(unsigned long timer_base)
{
volatile u32 reg = read(timer_base + OMAP_TIMER_TCLR);
reg &= (~OMAP_TIMER_START);
write(reg, timer_base + OMAP_TIMER_TCLR);
}
void timer_init_periodic(unsigned long timer_base)
{
volatile u32 reg;
/* Reset the timer */
timer_reset(timer_base);
/* Set timer to autoreload mode */
reg = read(timer_base + OMAP_TIMER_TCLR);
reg |= (1 << OMAP_TIMER_MODE_AUTORELAOD);
write(reg, timer_base + OMAP_TIMER_TCLR);
/*
* Beagle Board RevC manual:
* overflow period = (0xffffffff - TLDR + 1)*PS*(1/TIMER_FCLK)
* where,
* PS: Prescaler divisor (we are not using this)
*
* Beagle board manual says, 26MHz oscillator present on board.
* U-Boot divides the sys_clock by 2 if sys_clk is >19MHz,
* so,we have sys_clk frequency = 13MHz
*
* TIMER_FCLK = 13MHz
* So, for 1ms period, TLDR = 0xffffcd38
*
*/
timer_load(timer_base, 0xffffcd38);
/* Clear pending Interrupts, if any */
write(7, timer_base + OMAP_TIMER_TISR);
/* Enable inteerupts */
write((1 << OMAP_TIMER_INTR_OVERFLOW), timer_base + OMAP_TIMER_TIER);
}
void timer_init(unsigned long timer_base)
{
timer_init_periodic(timer_base);
}

View File

@@ -0,0 +1,51 @@
/*
* OMAP GP Timer offsets
*
* Copyright (C) 2007 Bahadir Balban
*
*/
#ifndef __OMAP_GPTIMER_H__
#define __OMAP_GPTIMER_H__
/* Register offsets */
#define OMAP_TIMER_TIOCP 0x10
#define OMAP_TIMER_TSTAT 0x14
#define OMAP_TIMER_TISR 0x18
#define OMAP_TIMER_TIER 0x1C
#define OMAP_TIMER_TCLR 0x24
#define OMAP_TIMER_TCRR 0x28
#define OMAP_TIMER_TLDR 0x2C
#define OMAP_TIMER_TPIR 0x48
#define OMAP_TIMER_TNIR 0x4C
#define OMAP_TIMER_TCVR 0x50
/* Enable/Disable IRQ */
#define OMAP_TIMER_IRQENABLE 1
#define OMAP_TIMER_IRQDISABLE 0
/* Timer modes supported */
#define OMAP_TIMER_MODE_AUTORELAOD 1
#define OMAP_TIMER_MODE_COMPARE 6
#define OMAP_TIMER_MODE_CAPTURE 13
/* Interrupt types */
#define OMAP_TIMER_INTR_MATCH 0x0
#define OMAP_TIMER_INTR_OVERFLOW 0x1
#define OMAP_TIMER_INTR_CAPTURE 0x2
/* Clock source for timer */
#define OMAP_TIMER_CLKSRC_SYS_CLK 0x1
#define OMAP_TIMER_CLKSRC_32KHZ_CLK 0x0
u32 timer_periodic_intr_status(unsigned long timer_base);
void timer_start(unsigned long base);
void timer_set_mode(unsigned long base, int mode);
void timer_reset(unsigned long timer_base);
void timer_load(unsigned long timer_base, u32 value);
u32 timer_read(unsigned long timer_base);
void timer_start(unsigned long timer_base);
void timer_stop(unsigned long timer_base);
void timer_init_periodic(unsigned long timer_base);
void timer_init(unsigned long timer_base);
#endif /* __OMAP_GPTIMER_H__*/

View File

@@ -0,0 +1,14 @@
Import('env', 'platform')
#Platforms using sp804
plat_list = ('eb', 'pba8', 'pba9', 'pb11mpcore', 'pb926')
# The set of source files associated with this SConscript file.
src_local = []
for plat_supported in plat_list:
if plat_supported == platform:
src_local += Glob('*.c')
obj = env.StaticObject(src_local)
Return('obj')

View File

@@ -0,0 +1,65 @@
/*
* SP804 primecell driver honoring generic
* timer library API
*
* Copyright (C) 2010 B Labs Ltd.
*
* Author: Bahadir Balban
*/
#include <l4lib/types.h>
#include "timer.h"
/* Enable timer with its current configuration */
void timer_start(unsigned long timer_base)
{
volatile u32 reg = read(timer_base + SP804_CTRL);
reg |= SP804_ENABLE;
write(reg, timer_base + SP804_CTRL);
}
/* Load the timer with ticks value */
void timer_load(u32 loadval, unsigned long timer_base)
{
write(loadval, timer_base + SP804_LOAD);
}
u32 timer_read(unsigned long timer_base)
{
return read(timer_base + SP804_VALUE);
}
void timer_stop(unsigned long timer_base)
{
write(0, timer_base + SP804_CTRL);
}
void timer_init_periodic(unsigned long timer_base)
{
volatile u32 reg = read(timer_base + SP804_CTRL);
reg |= SP804_PERIODIC | SP804_32BIT | SP804_IRQEN;
write(reg, timer_base + SP804_CTRL);
/* 1 tick per usec, 1 irq per msec */
timer_load(1000, timer_base);
}
void timer_init_oneshot(unsigned long timer_base)
{
volatile u32 reg = read(timer_base + SP804_CTRL);
/* One shot, 32 bits, no irqs */
reg |= SP804_32BIT | SP804_ONESHOT;
write(reg, timer_base + SP804_CTRL);
}
void timer_init(unsigned long timer_base)
{
timer_stop(timer_base);
timer_init_periodic(timer_base);
}

View File

@@ -0,0 +1,63 @@
/*
* SP804 Primecell Timer offsets
*
* Copyright (C) 2007 Bahadir Balban
*
*/
#ifndef __SP804_TIMER_H__
#define __SP804_TIMER_H__
#include <libdev/io.h>
/* Register offsets */
#define SP804_LOAD 0x0
#define SP804_VALUE 0x4
#define SP804_CTRL 0x8
#define SP804_INTCLR 0xC
#define SP804_RIS 0x10
#define SP804_MIS 0x14
#define SP804_BGLOAD 0x18
#define SP804_ENABLE (1 << 7)
#define SP804_PERIODIC (1 << 6)
#define SP804_IRQEN (1 << 5)
#define SP804_32BIT (1 << 1)
#define SP804_ONESHOT (1 << 0)
/* Timer prescaling */
#define SP804_SCALE_SHIFT 2
#define SP804_SCALE_DIV16 1
#define SP804_SCALE_DIV256 2
/* Wrapping = 0, Oneshot = 1 */
#define SP804_ONESHOT (1 << 0)
static inline __attribute__ ((always_inline))
void sp804_load(unsigned long timer_base, u32 val)
{
write(val, timer_base + SP804_LOAD);
}
static inline __attribute__ ((always_inline))
void sp804_irq_clear(unsigned long timer_base)
{
write(1, timer_base + SP804_INTCLR);
}
static inline __attribute__ ((always_inline))
void sp804_enable(unsigned long timer_base)
{
volatile u32 reg = read(timer_base + SP804_CTRL);
write(reg | SP804_ENABLE, timer_base + SP804_CTRL);
}
void timer_start(unsigned long timer_base);
void timer_load(u32 loadval, unsigned long timer_base);
u32 timer_read(unsigned long timer_base);
void timer_stop(unsigned long timer_base);
void timer_init_periodic(unsigned long timer_base);
void timer_init_oneshot(unsigned long timer_base);
void timer_init(unsigned long timer_base);
#endif /* __SP804_TIMER_H__ */

View File

@@ -0,0 +1,15 @@
Import('env', 'platform')
#Platforms using omap_uart
plat_list = 'beagle'
# The set of source files associated with this SConscript file.
src_local = []
#for plat_supported in plat_list:
#if plat_supported == platform:
if plat_list == platform:
src_local += ['uart.c']
obj = env.StaticObject(src_local)
Return('obj')

View File

@@ -0,0 +1,115 @@
/*
* UART driver used by OMAP devices
*
* Copyright (C) 2007 Bahadir Balban
*/
#include <libdev/uart.h>
#include <libdev/io.h>
#include "uart.h"
#define OMAP_UART_TXFE 0x20
void uart_tx_char(unsigned long uart_base, char c)
{
volatile u32 reg;
/* Check if there is space for tx */
do {
reg = read(uart_base + OMAP_UART_LSR);
} while(!(reg & OMAP_UART_TXFE));
write(c, uart_base + OMAP_UART_THR);
}
#define OMAP_UART_RXFNE 0x1
#define OMAP_UART_RX_FIFO_STATUS 0x8
char uart_rx_char(unsigned long uart_base)
{
volatile u32 reg;
/* Check if pending data is there */
do {
reg = read(uart_base + OMAP_UART_LSR);
} while(!(reg & OMAP_UART_RXFNE));
#if 0
/* Check if there is some error in recieve */
if(reg & OMAP_UART_RX_FIFO_STATUS)
return -1;
#endif
return (char)read(uart_base + OMAP_UART_RHR);
}
void uart_set_baudrate(unsigned long uart_base, u32 baudrate)
{
u32 clk_div;
/* 48Mhz clock fixed on beagleboard */
const u32 clkrate = 48000000;
/* If baud out of range, set default rate */
if(baudrate > 3686400 || baudrate < 300)
baudrate = 115200;
clk_div = clkrate/(16 * baudrate);
/* Set clockrate in DLH and DLL */
write((clk_div & 0xff), uart_base + OMAP_UART_DLL);
write(((clk_div >> 8) & 0xff ), uart_base + OMAP_UART_DLH);
}
void uart_init(unsigned long uart_base)
{
/* Disable UART */
uart_select_mode(uart_base, OMAP_UART_MODE_DEFAULT);
/* Disable interrupts */
uart_disable_interrupt(uart_base);
/* Change to config mode, to set baud divisor */
uart_set_link_control(uart_base, OMAP_UART_BANKED_MODE_CONFIG_A);
/* Set the baud rate */
uart_set_baudrate(uart_base, 115200);
/* Switch to operational mode */
uart_set_link_control(uart_base, OMAP_UART_BANKED_MODE_OPERATIONAL);
/* Set up the link- parity, data bits stop bits to 8N1 */
uart_disable_parity(uart_base);
uart_set_data_bits(uart_base, OMAP_UART_DATA_BITS_8);
uart_set_stop_bits(uart_base, OMAP_UART_STOP_BITS_1);
/* Disable Fifos */
uart_disable_fifo(uart_base);
/* Enable modem Rx/Tx */
uart_enable_tx(uart_base);
uart_enable_rx(uart_base);
/* Enable UART in 16x mode */
uart_select_mode(uart_base, OMAP_UART_MODE_UART16X);
}
unsigned long uart_print_base;
void platform_init(void)
{
uart_print_base = OMAP_UART_BASE;
/*
* We dont need to initialize uart here for variant-userspace,
* as this is the same uart as used by kernel and hence
* already initialized, we just need
* a uart struct instance with proper base address.
*
* But in case of baremetal like loader, no one has done
* initialization, so we need to do it.
*/
#if defined(VARIANT_BAREMETAL)
uart_init(uart_print_base);
#endif
}

View File

@@ -0,0 +1,195 @@
/*
* OMAP UART Generic driver implementation.
*
* Copyright (C) 2007 Bahadir Balban
*
* The particular intention of this code is that it has been carefully written
* as decoupled from os-specific code and in a verbose way such that it clearly
* demonstrates how the device operates, reducing the amount of time to be spent
* for understanding the operational model and implementing a driver from
* scratch. This is the very first to be such a driver so far, hopefully it will
* turn out to be useful.
*/
#ifndef __OMAP_UART_H__
#define __OMAP_UART_H__
#include <l4/config.h> /* To get PLATFORM */
#include <l4lib/types.h>
#if defined(VARIANT_USERSPACE)
/* FIXME: Take this value in agreement from kernel, or from kernel only */
#include <l4/macros.h>
#include INC_ARCH(io.h)
#define OMAP_UART_BASE USERSPACE_CONSOLE_VBASE
#endif
#if defined(VARIANT_BAREMETAL)
#if defined(CONFIG_PLATFORM_BEAGLE)
#define OMAP_UART_BASE 0x49020000
#endif
#endif
/* Register offsets */
#define OMAP_UART_DLL 0x00
#define OMAP_UART_THR 0x00
#define OMAP_UART_RHR 0x00
#define OMAP_UART_DLH 0x04
#define OMAP_UART_IER 0x04
#define OMAP_UART_FCR 0x08
#define OMAP_UART_MCR 0x10
#define OMAP_UART_LSR 0x14
#define OMAP_UART_MDR1 0x20
#define OMAP_UART_LCR 0x0C
/* Modes supported by OMAP UART/IRDA/CIR IP */
#define OMAP_UART_MODE_UART16X 0x0
#define OMAP_UART_MODE_SIR 0x1
#define OMAP_UART_MODE_UART16X_AUTO_BAUD 0x2
#define OMAP_UART_MODE_UART13X 0x3
#define OMAP_UART_MODE_MIR 0x4
#define OMAP_UART_MODE_FIR 0x5
#define OMAP_UART_MODE_CIR 0x6
#define OMAP_UART_MODE_DEFAULT 0x7 /* Disable */
/* Number of data bits for UART */
#define OMAP_UART_DATA_BITS_5 0x0
#define OMAP_UART_DATA_BITS_6 0x1
#define OMAP_UART_DATA_BITS_7 0x2
#define OMAP_UART_DATA_BITS_8 0x3
/* Stop bits to be used for UART data */
#define OMAP_UART_STOP_BITS_1 0x0
#define OMAP_UART_STOP_BITS_1_5 0x1
/* Banked Register modes- ConfigA, ConfigB, Operational */
#define OMAP_UART_BANKED_MODE_OPERATIONAL 0x00
#define OMAP_UART_BANKED_MODE_CONFIG_A 0x80
#define OMAP_UART_BANKED_MODE_CONFIG_B 0xBF
void uart_tx_char(unsigned long uart_base, char c);
char uart_rx_char(unsigned long uart_base);
void uart_set_baudrate(unsigned long uart_base, u32 baudrate);
void uart_init(unsigned long uart_base);
#define OMAP_UART_FIFO_ENABLE (1 << 0)
#define OMAP_UART_RX_FIFO_CLR (1 << 1)
#define OMAP_UART_TX_FIFO_CLR (1 << 2)
static inline void uart_enable_fifo(unsigned long uart_base)
{
volatile u32 reg = read(uart_base + OMAP_UART_FCR);
reg |= (OMAP_UART_FIFO_ENABLE | OMAP_UART_RX_FIFO_CLR |
OMAP_UART_TX_FIFO_CLR);
write(reg, uart_base + OMAP_UART_FCR);
}
static inline void uart_disable_fifo(unsigned long uart_base)
{
volatile u32 reg= read(uart_base + OMAP_UART_FCR);
reg &= (~OMAP_UART_FIFO_ENABLE | OMAP_UART_RX_FIFO_CLR |
OMAP_UART_TX_FIFO_CLR);
write(reg, uart_base + OMAP_UART_FCR);
}
#define OMAP_UART_TX_ENABLE (1 << 0)
static inline void uart_enable_tx(unsigned long uart_base)
{
volatile u32 reg = read(uart_base + OMAP_UART_MCR);
reg |= OMAP_UART_TX_ENABLE;
write(reg, uart_base + OMAP_UART_MCR);
}
static inline void uart_disable_tx(unsigned long uart_base)
{
volatile u32 reg = read(uart_base + OMAP_UART_MCR);
reg &= ~OMAP_UART_TX_ENABLE;
write(reg, uart_base + OMAP_UART_MCR);
}
#define OMAP_UART_RX_ENABLE (1 << 1)
static inline void uart_enable_rx(unsigned long uart_base)
{
volatile u32 reg = read(uart_base + OMAP_UART_MCR);
reg |= OMAP_UART_RX_ENABLE;
write(reg, uart_base + OMAP_UART_MCR);
}
static inline void uart_disable_rx(unsigned long uart_base)
{
volatile u32 reg = read(uart_base + OMAP_UART_MCR);
reg &= ~OMAP_UART_RX_ENABLE;
write(reg, uart_base + OMAP_UART_MCR);
}
#define OMAP_UART_STOP_BITS_MASK (1 << 2)
static inline void uart_set_stop_bits(unsigned long uart_base, int bits)
{
volatile u32 reg = read(uart_base + OMAP_UART_LCR);
reg &= ~OMAP_UART_STOP_BITS_MASK;
reg |= (bits << 2);
write(reg, uart_base + OMAP_UART_LCR);
}
#define OMAP_UART_DATA_BITS_MASK (0x3)
static inline void uart_set_data_bits(unsigned long uart_base, int bits)
{
volatile u32 reg = read(uart_base + OMAP_UART_LCR);
reg &= ~OMAP_UART_DATA_BITS_MASK;
reg |= bits;
write(reg, uart_base + OMAP_UART_LCR);
}
#define OMAP_UART_PARITY_ENABLE (1 << 3)
static inline void uart_enable_parity(unsigned long uart_base)
{
volatile u32 reg = read(uart_base + OMAP_UART_LCR);
reg |= OMAP_UART_PARITY_ENABLE;
write(reg, uart_base + OMAP_UART_LCR);
}
static inline void uart_disable_parity(unsigned long uart_base)
{
volatile u32 reg = read(uart_base + OMAP_UART_LCR);
reg &= ~OMAP_UART_PARITY_ENABLE;
write(reg, uart_base + OMAP_UART_LCR);
}
#define OMAP_UART_PARITY_EVEN (1 << 4)
static inline void uart_set_even_parity(unsigned long uart_base)
{
volatile u32 reg = read(uart_base + OMAP_UART_LCR);
reg |= OMAP_UART_PARITY_EVEN;
write(reg, uart_base + OMAP_UART_LCR);
}
static inline void uart_set_odd_parity(unsigned long uart_base)
{
volatile u32 reg = read(uart_base + OMAP_UART_LCR);
reg &= ~OMAP_UART_PARITY_EVEN;
write(reg, uart_base + OMAP_UART_LCR);
}
static inline void uart_select_mode(unsigned long uart_base, int mode)
{
write(mode, uart_base + OMAP_UART_MDR1);
}
#define OMAP_UART_INTR_EN 1
static inline void uart_enable_interrupt(unsigned long uart_base)
{
write(OMAP_UART_INTR_EN, uart_base + OMAP_UART_IER);
}
static inline void uart_disable_interrupt(unsigned long uart_base)
{
write((~OMAP_UART_INTR_EN), uart_base + OMAP_UART_IER);
}
static inline void uart_set_link_control(unsigned long uart_base, int mode)
{
write(mode, uart_base + OMAP_UART_LCR);
}
#endif /* __OMAP_UART_H__ */

View File

@@ -0,0 +1,14 @@
Import('env', 'platform')
#Platforms using pl011
plat_list = ('eb', 'pba8', 'pba9', 'pb11mpcore', 'pb926')
# The set of source files associated with this SConscript file.
src_local = []
for plat_supported in plat_list:
if plat_supported == platform:
src_local += Glob('*.c')
obj = env.StaticObject(src_local)
Return('obj')

View File

@@ -0,0 +1,127 @@
/*
* PL011 UART driver
*
* Copyright (C) 2009 B Labs Ltd.
*/
#include <libdev/uart.h>
#include <libdev/io.h>
#include "uart.h"
/* Error status bits in receive status register */
#define PL011_FE (1 << 0)
#define PL011_PE (1 << 1)
#define PL011_BE (1 << 2)
#define PL011_OE (1 << 3)
/* Status bits in flag register */
#define PL011_TXFE (1 << 7)
#define PL011_RXFF (1 << 6)
#define PL011_TXFF (1 << 5)
#define PL011_RXFE (1 << 4)
#define PL011_BUSY (1 << 3)
#define PL011_DCD (1 << 2)
#define PL011_DSR (1 << 1)
#define PL011_CTS (1 << 0)
void uart_tx_char(unsigned long base, char c)
{
unsigned int val = 0;
do {
val = read((base + PL011_UARTFR));
} while (val & PL011_TXFF); /* TX FIFO FULL */
write(c, (base + PL011_UARTDR));
}
char uart_rx_char(unsigned long base)
{
unsigned int val = 0;
do {
val = read(base + PL011_UARTFR);
} while (val & PL011_RXFE); /* RX FIFO Empty */
return (char)read((base + PL011_UARTDR));
}
/*
* Sets the baud rate in kbps. It is recommended to use
* standard rates such as: 1200, 2400, 3600, 4800, 7200,
* 9600, 14400, 19200, 28800, 38400, 57600 76800, 115200.
*/
void pl011_set_baudrate(unsigned long base, unsigned int baud,
unsigned int clkrate)
{
const unsigned int uartclk = 24000000; /* 24Mhz clock fixed on pb926 */
unsigned int val = 0, ipart = 0, fpart = 0;
/* Use default pb926 rate if no rate is supplied */
if (clkrate == 0)
clkrate = uartclk;
if (baud > 115200 || baud < 1200)
baud = 38400; /* Default rate. */
/* 24000000 / (38400 * 16) */
ipart = 39;
write(ipart, base + PL011_UARTIBRD);
write(fpart, base + PL011_UARTFBRD);
/*
* For the IBAUD and FBAUD to update, we need to
* write to UARTLCR_H because the 3 registers are
* actually part of a single register in hardware
* which only updates by a write to UARTLCR_H
*/
val = read(base + PL011_UARTLCR_H);
write(val, base + PL011_UARTLCR_H);
}
void uart_init(unsigned long uart_base)
{
/* Initialise data register for 8 bit data read/writes */
pl011_set_word_width(uart_base, 8);
/*
* Fifos are disabled because by default it is assumed the port
* will be used as a user terminal, and in that case the typed
* characters will only show up when fifos are flushed, rather than
* when each character is typed. We avoid this by not using fifos.
*/
pl011_disable_fifos(uart_base);
/* Set default baud rate of 38400 */
pl011_set_baudrate(uart_base, 38400, 24000000);
/* Set default settings of 1 stop bit, no parity, no hw flow ctrl */
pl011_set_stopbits(uart_base, 1);
pl011_parity_disable(uart_base);
/* Enable rx, tx, and uart chip */
pl011_tx_enable(uart_base);
pl011_rx_enable(uart_base);
pl011_uart_enable(uart_base);
}
unsigned long uart_print_base;
void platform_init(void)
{
uart_print_base = PL011_BASE;
/*
* We dont need to initialize uart here for variant-userspace,
* as this is the same uart as used by kernel and hence
* already initialized, we just need
* a uart struct instance with proper base address.
*
* But in case of baremetal like loader, no one has done
* initialization, so we need to do it.
*/
#if defined(VARIANT_BAREMETAL)
uart_init(uart_print_base);
#endif
}

View File

@@ -0,0 +1,252 @@
/*
* PL011 UART Generic driver implementation.
* Copyright Bahadir Balban (C) 2009
*/
#ifndef __PL011_H__
#define __PL011_H__
#include <l4/config.h> /* To get PLATFORM */
#include <libdev/io.h>
#if defined(VARIANT_USERSPACE)
/* FIXME: Take this value in agreement from kernel, or from kernel only */
#include <l4/macros.h>
#include INC_ARCH(io.h)
#define PL011_BASE USERSPACE_CONSOLE_VBASE
#endif
#if defined(VARIANT_BAREMETAL)
#if defined(CONFIG_PLATFORM_PB926)
#define PL011_BASE 0x101F1000
#elif defined(CONFIG_PLATFORM_EB) || defined(CONFIG_PLATFORM_PB11MPCORE)
#define PL011_BASE 0x10009000
#elif defined(CONFIG_PLATFORM_PBA9) || defined(CONFIG_PLATFORM_PBA8)
#define PL011_BASE 0x10009000
#endif
#endif
/* Register offsets */
#define PL011_UARTDR 0x00
#define PL011_UARTRSR 0x04
#define PL011_UARTECR 0x04
#define PL011_UARTFR 0x18
#define PL011_UARTILPR 0x20
#define PL011_UARTIBRD 0x24
#define PL011_UARTFBRD 0x28
#define PL011_UARTLCR_H 0x2C
#define PL011_UARTCR 0x30
#define PL011_UARTIFLS 0x34
#define PL011_UARTIMSC 0x38
#define PL011_UARTRIS 0x3C
#define PL011_UARTMIS 0x40
#define PL011_UARTICR 0x44
#define PL011_UARTDMACR 0x48
/* IRQ bits for each uart irq event */
#define PL011_RXIRQ (1 << 4)
#define PL011_TXIRQ (1 << 5)
#define PL011_RXTIMEOUTIRQ (1 << 6)
#define PL011_FEIRQ (1 << 7)
#define PL011_PEIRQ (1 << 8)
#define PL011_BEIRQ (1 << 9)
#define PL011_OEIRQ (1 << 10)
void pl011_set_baudrate(unsigned long base, unsigned int baud,
unsigned int clkrate);
#define PL011_UARTEN (1 << 0)
static inline void pl011_uart_enable(unsigned long base)
{
unsigned int val = 0;
val = read((base + PL011_UARTCR));
val |= PL011_UARTEN;
write(val, (base + PL011_UARTCR));
return;
}
static inline void pl011_uart_disable(unsigned long base)
{
unsigned int val = 0;
val = read((base + PL011_UARTCR));
val &= ~PL011_UARTEN;
write(val, (base + PL011_UARTCR));
return;
}
#define PL011_TXE (1 << 8)
static inline void pl011_tx_enable(unsigned long base)
{
unsigned int val = 0;
val = read((base + PL011_UARTCR));
val |= PL011_TXE;
write(val, (base + PL011_UARTCR));
return;
}
static inline void pl011_tx_disable(unsigned long base)
{
unsigned int val = 0;
val =read((base + PL011_UARTCR));
val &= ~PL011_TXE;
write(val, (base + PL011_UARTCR));
return;
}
#define PL011_RXE (1 << 9)
static inline void pl011_rx_enable(unsigned long base)
{
unsigned int val = 0;
val = read((base + PL011_UARTCR));
val |= PL011_RXE;
write(val, (base + PL011_UARTCR));
return;
}
static inline void pl011_rx_disable(unsigned long base)
{
unsigned int val = 0;
val = read((base + PL011_UARTCR));
val &= ~PL011_RXE;
write(val, (base + PL011_UARTCR));
return;
}
#define PL011_TWO_STOPBITS_SELECT (1 << 3)
static inline void pl011_set_stopbits(unsigned long base, int stopbits)
{
unsigned int val = 0;
val = read((base + PL011_UARTLCR_H));
if(stopbits == 2) { /* Set to two bits */
val |= PL011_TWO_STOPBITS_SELECT;
} else { /* Default is 1 */
val &= ~PL011_TWO_STOPBITS_SELECT;
}
write(val, (base + PL011_UARTLCR_H));
return;
}
#define PL011_PARITY_ENABLE (1 << 1)
static inline void pl011_parity_enable(unsigned long base)
{
unsigned int val = 0;
val = read((base +PL011_UARTLCR_H));
val |= PL011_PARITY_ENABLE;
write(val, (base + PL011_UARTLCR_H));
return;
}
static inline void pl011_parity_disable(unsigned long base)
{
unsigned int val = 0;
val = read((base + PL011_UARTLCR_H));
val &= ~PL011_PARITY_ENABLE;
write(val, (base + PL011_UARTLCR_H));
return;
}
#define PL011_PARITY_EVEN (1 << 2)
static inline void pl011_set_parity_even(unsigned long base)
{
unsigned int val = 0;
val = read((base + PL011_UARTLCR_H));
val |= PL011_PARITY_EVEN;
write(val, (base + PL011_UARTLCR_H));
return;
}
static inline void pl011_set_parity_odd(unsigned long base)
{
unsigned int val = 0;
val = read((base + PL011_UARTLCR_H));
val &= ~PL011_PARITY_EVEN;
write(val, (base + PL011_UARTLCR_H));
return;
}
#define PL011_ENABLE_FIFOS (1 << 4)
static inline void pl011_enable_fifos(unsigned long base)
{
unsigned int val = 0;
val = read((base + PL011_UARTLCR_H));
val |= PL011_ENABLE_FIFOS;
write(val, (base + PL011_UARTLCR_H));
return;
}
static inline void pl011_disable_fifos(unsigned long base)
{
unsigned int val = 0;
val = read((base + PL011_UARTLCR_H));
val &= ~PL011_ENABLE_FIFOS;
write(val, (base + PL011_UARTLCR_H));
return;
}
/* Sets the transfer word width for the data register. */
static inline void pl011_set_word_width(unsigned long base, int size)
{
unsigned int val = 0;
if(size < 5 || size > 8) /* Default is 8 */
size = 8;
/* Clear size field */
val = read((base + PL011_UARTLCR_H));
val &= ~(0x3 << 5);
write(val, (base + PL011_UARTLCR_H));
/*
* The formula is to write 5 less of size given:
* 11 = 8 bits
* 10 = 7 bits
* 01 = 6 bits
* 00 = 5 bits
*/
val = read((base + PL011_UARTLCR_H));
val |= (size - 5) << 5;
write(val, (base + PL011_UARTLCR_H));
return;
}
/*
* Defines at which level of fifo fullness an irq will be generated.
* @xfer: tx fifo = 0, rx fifo = 1
* @level: Generate irq if:
* 0 rxfifo >= 1/8 full txfifo <= 1/8 full
* 1 rxfifo >= 1/4 full txfifo <= 1/4 full
* 2 rxfifo >= 1/2 full txfifo <= 1/2 full
* 3 rxfifo >= 3/4 full txfifo <= 3/4 full
* 4 rxfifo >= 7/8 full txfifo <= 7/8 full
* 5-7 reserved reserved
*/
static inline void pl011_set_irq_fifolevel(unsigned long base, \
unsigned int xfer, unsigned int level)
{
if(xfer != 1 && xfer != 0) /* Invalid fifo */
return;
if(level > 4) /* Invalid level */
return;
write(level << (xfer * 3), (base + PL011_UARTIFLS));
return;
}
#endif /* __PL011__UART__ */