mirror of
https://github.com/drasko/codezero.git
synced 2026-01-11 18:33:16 +01:00
CLCD added as new capability, code note added yet
This commit is contained in:
@@ -134,7 +134,8 @@ derive baremetal%(cn)d from
|
||||
((CONT%(cn)d_BAREMETAL_PROJ_THREADS_DEMO==y) ? "thread_demo%(cn)d" :
|
||||
((CONT%(cn)d_BAREMETAL_PROJ_TEST==y) ? "test%(cn)d" :
|
||||
((CONT%(cn)d_BAREMETAL_PROJ_UART_SERVICE==y) ? "uart_service%(cn)d" :
|
||||
((CONT%(cn)d_BAREMETAL_PROJ_TIMER_SERVICE==y) ? "timer_service%(cn)d" : "baremetal_noname%(cn)d" )))))
|
||||
((CONT%(cn)d_BAREMETAL_PROJ_CLCD_SERVICE==y) ? "clcd_service%(cn)d" :
|
||||
((CONT%(cn)d_BAREMETAL_PROJ_TIMER_SERVICE==y) ? "timer_service%(cn)d" : "baremetal_noname%(cn)d" ))))))
|
||||
|
||||
default CONT%(cn)d_OPT_NAME from (CONT%(cn)d_TYPE_LINUX==y) ? "linux%(cn)d" : ((CONT%(cn)d_TYPE_BAREMETAL==y) ? baremetal%(cn)d : "posix%(cn)d")
|
||||
|
||||
@@ -167,6 +168,7 @@ CONT%(cn)d_BAREMETAL_PROJ_THREADS_DEMO 'Thread Library Demo'
|
||||
CONT%(cn)d_BAREMETAL_PROJ_TEST 'Test Project'
|
||||
CONT%(cn)d_BAREMETAL_PROJ_UART_SERVICE 'UART Service'
|
||||
CONT%(cn)d_BAREMETAL_PROJ_TIMER_SERVICE 'Timer Service'
|
||||
CONT%(cn)d_BAREMETAL_PROJ_CLCD_SERVICE 'CLCD Service'
|
||||
|
||||
choices cont%(cn)d_baremetal_params
|
||||
CONT%(cn)d_BAREMETAL_PROJ_EMPTY
|
||||
@@ -175,6 +177,7 @@ choices cont%(cn)d_baremetal_params
|
||||
CONT%(cn)d_BAREMETAL_PROJ_TEST
|
||||
CONT%(cn)d_BAREMETAL_PROJ_UART_SERVICE
|
||||
CONT%(cn)d_BAREMETAL_PROJ_TIMER_SERVICE
|
||||
CONT%(cn)d_BAREMETAL_PROJ_CLCD_SERVICE
|
||||
default CONT%(cn)d_BAREMETAL_PROJ_EMPTY
|
||||
|
||||
menu cont%(cn)d_default_pager_params
|
||||
@@ -231,16 +234,19 @@ cont%(cn)d_cap_device_uart1 'Container %(cn)d UART1 Menu'
|
||||
cont%(cn)d_cap_device_uart2 'Container %(cn)d UART2 Menu'
|
||||
cont%(cn)d_cap_device_uart3 'Container %(cn)d UART3 Menu'
|
||||
cont%(cn)d_cap_device_timer1 'Container %(cn)d TIMER23 Menu'
|
||||
cont%(cn)d_cap_device_clcd 'Container %(cn)d CLCD Menu'
|
||||
|
||||
CONT%(cn)d_CAP_DEVICE_UART1_USE 'Container %(cn)d UART1 Enable'
|
||||
CONT%(cn)d_CAP_DEVICE_UART2_USE 'Container %(cn)d UART2 Enable'
|
||||
CONT%(cn)d_CAP_DEVICE_UART3_USE 'Container %(cn)d UART3 Enable'
|
||||
CONT%(cn)d_CAP_DEVICE_TIMER1_USE 'Container %(cn)d TIMER23 Enable'
|
||||
CONT%(cn)d_CAP_DEVICE_CLCD0_USE 'Container %(cn)d CLCD Enable'
|
||||
|
||||
default CONT%(cn)d_CAP_DEVICE_UART1_USE from n
|
||||
default CONT%(cn)d_CAP_DEVICE_UART2_USE from n
|
||||
default CONT%(cn)d_CAP_DEVICE_UART3_USE from n
|
||||
default CONT%(cn)d_CAP_DEVICE_TIMER1_USE from n
|
||||
default CONT%(cn)d_CAP_DEVICE_CLCD0_USE from n
|
||||
|
||||
menu cont%(cn)d_cap_device_uart1
|
||||
CONT%(cn)d_CAP_DEVICE_UART1_USE
|
||||
@@ -254,11 +260,15 @@ menu cont%(cn)d_cap_device_uart3
|
||||
menu cont%(cn)d_cap_device_timer1
|
||||
CONT%(cn)d_CAP_DEVICE_TIMER1_USE
|
||||
|
||||
menu cont%(cn)d_cap_device_clcd
|
||||
CONT%(cn)d_CAP_DEVICE_CLCD0_USE
|
||||
|
||||
menu cont%(cn)d_device_list
|
||||
cont%(cn)d_cap_device_uart1
|
||||
cont%(cn)d_cap_device_uart2
|
||||
cont%(cn)d_cap_device_uart3
|
||||
cont%(cn)d_cap_device_timer1
|
||||
cont%(cn)d_cap_device_clcd
|
||||
|
||||
#
|
||||
# Settings for Custom Capabilities
|
||||
|
||||
67
conts/baremetal/clcd_service/SConstruct
Normal file
67
conts/baremetal/clcd_service/SConstruct
Normal file
@@ -0,0 +1,67 @@
|
||||
# -*- mode: python; coding: utf-8; -*-
|
||||
#
|
||||
# Codezero -- Virtualization microkernel for embedded systems.
|
||||
#
|
||||
# Copyright © 2009 B Labs Ltd
|
||||
#
|
||||
import os, shelve, sys
|
||||
from os.path import *
|
||||
|
||||
PROJRELROOT = '../..'
|
||||
|
||||
sys.path.append(PROJRELROOT)
|
||||
|
||||
from config.projpaths import *
|
||||
from config.configuration import *
|
||||
|
||||
config = configuration_retrieve()
|
||||
platform = config.platform
|
||||
arch = config.arch
|
||||
gcc_cpu_flag = config.gcc_cpu_flag
|
||||
|
||||
LIBL4_RELDIR = 'conts/libl4'
|
||||
KERNEL_INCLUDE = join(PROJROOT, 'include')
|
||||
LIBL4_DIR = join(PROJROOT, LIBL4_RELDIR)
|
||||
LIBL4_INCLUDE = join(LIBL4_DIR, 'include')
|
||||
LIBL4_LIBPATH = join(BUILDDIR, LIBL4_RELDIR)
|
||||
|
||||
# Locally important paths are here
|
||||
LIBC_RELDIR = 'conts/libc'
|
||||
LIBC_DIR = join(PROJROOT, LIBC_RELDIR)
|
||||
LIBC_LIBPATH = join(BUILDDIR, LIBC_RELDIR)
|
||||
LIBC_INCLUDE = [join(LIBC_DIR, 'include'), \
|
||||
join(LIBC_DIR, 'include/arch' + '/' + arch)]
|
||||
|
||||
LIBDEV_RELDIR = 'conts/libdev'
|
||||
LIBDEV_DIR = join(PROJROOT, LIBDEV_RELDIR)
|
||||
LIBDEV_LIBPATH = join(join(BUILDDIR, LIBDEV_RELDIR), 'sys-userspace')
|
||||
LIBDEV_INCLUDE = [join(LIBDEV_DIR, 'uart/include'),
|
||||
join(LIBDEV_DIR, 'clcd/pl110/include')]
|
||||
LIBDEV_CCFLAGS = '-DPLATFORM_' + platform.upper()
|
||||
|
||||
# FIXME: Add these to autogenerated SConstruct !!!
|
||||
LIBMEM_RELDIR = 'conts/libmem'
|
||||
LIBMEM_DIR = join(PROJROOT, LIBMEM_RELDIR)
|
||||
LIBMEM_LIBPATH = join(BUILDDIR, LIBMEM_RELDIR)
|
||||
LIBMEM_INCLUDE = LIBMEM_DIR
|
||||
|
||||
env = Environment(CC = config.user_toolchain + 'gcc',
|
||||
# We don't use -nostdinc because sometimes we need standard headers,
|
||||
# such as stdarg.h e.g. for variable args, as in printk().
|
||||
CCFLAGS = ['-g', '-nostdlib', '-ffreestanding', '-std=gnu99', '-Wall', \
|
||||
'-Werror', ('-mcpu=' + gcc_cpu_flag), LIBDEV_CCFLAGS],
|
||||
LINKFLAGS = ['-nostdlib', '-T' + "include/linker.lds", "-u_start"],
|
||||
ASFLAGS = ['-D__ASSEMBLY__'], \
|
||||
PROGSUFFIX = '.elf', # The suffix to use for final executable\
|
||||
ENV = {'PATH' : os.environ['PATH']}, # Inherit shell path\
|
||||
LIBS = ['gcc', 'libl4', 'libmalloc', 'c-userspace', 'libdev-userspace', 'gcc', 'c-userspace'], # libgcc.a - This is required for division routines.
|
||||
CPPPATH = ["#include", KERNEL_INCLUDE, LIBL4_INCLUDE, LIBDEV_INCLUDE, LIBC_INCLUDE, LIBMEM_INCLUDE],
|
||||
LIBPATH = [LIBL4_LIBPATH, LIBDEV_LIBPATH, LIBC_LIBPATH, LIBMEM_LIBPATH],
|
||||
CPPFLAGS = '-include l4/config.h -include l4/macros.h -include l4/types.h')
|
||||
|
||||
src = Glob('*.[cS]')
|
||||
src += Glob('src/*.[cS]')
|
||||
|
||||
objs = env.Object(src)
|
||||
prog = env.Program('main.elf', objs)
|
||||
Depends(prog, 'include/linker.lds')
|
||||
21
conts/baremetal/clcd_service/container.c
Normal file
21
conts/baremetal/clcd_service/container.c
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Container entry point for pager
|
||||
*
|
||||
* Copyright (C) 2007-2009 B Labs Ltd.
|
||||
*/
|
||||
|
||||
#include <l4lib/init.h>
|
||||
#include <l4lib/utcb.h>
|
||||
|
||||
|
||||
extern void main(void);
|
||||
|
||||
void __container_init(void)
|
||||
{
|
||||
/* Generic L4 initialisation */
|
||||
__l4_init();
|
||||
|
||||
/* Entry to main */
|
||||
main();
|
||||
}
|
||||
|
||||
12
conts/baremetal/clcd_service/include/capability.h
Normal file
12
conts/baremetal/clcd_service/include/capability.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef __UART_SERVICE_CAPABILITY_H__
|
||||
#define __UART_SERVICE_CAPABILITY_H__
|
||||
|
||||
#include <l4lib/capability.h>
|
||||
#include <l4/api/capability.h>
|
||||
#include <l4/generic/cap-types.h>
|
||||
|
||||
void cap_print(struct capability *cap);
|
||||
void cap_list_print(struct cap_list *cap_list);
|
||||
int cap_read_all();
|
||||
|
||||
#endif /* header */
|
||||
13
conts/baremetal/clcd_service/include/container.h
Normal file
13
conts/baremetal/clcd_service/include/container.h
Normal file
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Autogenerated definitions for this container.
|
||||
*/
|
||||
#ifndef __CONTAINER_H__
|
||||
#define __CONTAINER_H__
|
||||
|
||||
|
||||
#define __CONTAINER_NAME__ "uart_service"
|
||||
#define __CONTAINER_ID__ 0
|
||||
#define __CONTAINER__ "cont0"
|
||||
|
||||
|
||||
#endif /* __CONTAINER_H__ */
|
||||
7
conts/baremetal/clcd_service/include/linker.h
Normal file
7
conts/baremetal/clcd_service/include/linker.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#ifndef __LINKER_H__
|
||||
#define __LINKER_H__
|
||||
|
||||
extern char vma_start[];
|
||||
extern char __end[];
|
||||
|
||||
#endif /* __LINKER_H__ */
|
||||
277
conts/baremetal/clcd_service/main.c
Normal file
277
conts/baremetal/clcd_service/main.c
Normal file
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* CLCD service for userspace
|
||||
*/
|
||||
#include <l4lib/arch/syslib.h>
|
||||
#include <l4lib/arch/syscalls.h>
|
||||
#include <l4lib/addr.h>
|
||||
#include <l4lib/exregs.h>
|
||||
#include <l4lib/ipcdefs.h>
|
||||
#include <l4/api/errno.h>
|
||||
|
||||
#include <l4/api/space.h>
|
||||
#include <capability.h>
|
||||
#include <container.h>
|
||||
#include <pl110_clcd.h> /* FIXME: Its best if this is <libdev/uart/pl011.h> */
|
||||
#include <linker.h>
|
||||
|
||||
#define CLCD_TOTAL 1
|
||||
|
||||
static struct capability caparray[32];
|
||||
static int total_caps = 0;
|
||||
|
||||
struct capability clcd_cap[CLCD_TOTAL];
|
||||
|
||||
int cap_read_all()
|
||||
{
|
||||
int ncaps;
|
||||
int err;
|
||||
|
||||
/* Read number of capabilities */
|
||||
if ((err = l4_capability_control(CAP_CONTROL_NCAPS,
|
||||
0, 0, 0, &ncaps)) < 0) {
|
||||
printf("l4_capability_control() reading # of"
|
||||
" capabilities failed.\n Could not "
|
||||
"complete CAP_CONTROL_NCAPS request.\n");
|
||||
BUG();
|
||||
}
|
||||
total_caps = ncaps;
|
||||
|
||||
/* Read all capabilities */
|
||||
if ((err = l4_capability_control(CAP_CONTROL_READ,
|
||||
0, 0, 0, caparray)) < 0) {
|
||||
printf("l4_capability_control() reading of "
|
||||
"capabilities failed.\n Could not "
|
||||
"complete CAP_CONTROL_READ_CAPS request.\n");
|
||||
BUG();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scans for up to CLCD_TOTAL clcd devices in capabilities.
|
||||
*/
|
||||
int clcd_probe_devices(void)
|
||||
{
|
||||
int clcds = 0;
|
||||
|
||||
/* Scan for clcd devices */
|
||||
for (int i = 0; i < total_caps; i++) {
|
||||
/* Match device type */
|
||||
if (cap_devtype(&caparray[i]) == CAP_DEVTYPE_CLCD) {
|
||||
/* Copy to correct device index */
|
||||
memcpy(&clcd_cap[cap_devnum(&caparray[i])],
|
||||
&caparray[i], sizeof(clcd_cap[0]));
|
||||
clcds++;
|
||||
}
|
||||
}
|
||||
|
||||
if (clcds != CLCD_TOTAL) {
|
||||
printf("%s: Error, not all clcd could be found. "
|
||||
"total clcds=%d\n", __CONTAINER_NAME__, clcds);
|
||||
return -ENODEV;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 1MB frame buffer,
|
||||
* FIXME: can we do dma in this buffer?
|
||||
*/
|
||||
#define CLCD_FRAMEBUFFER_SZ 0x100000
|
||||
static char framebuffer[CLCD_FRAMEBUFFER_SZ];
|
||||
|
||||
static struct pl110_clcd clcd[CLCD_TOTAL];
|
||||
|
||||
int clcd_setup_devices(void)
|
||||
{
|
||||
for (int i = 0; i < CLCD_TOTAL; i++) {
|
||||
/* Get one page from address pool */
|
||||
clcd[i].virt_base = (unsigned long)l4_new_virtual(1);
|
||||
|
||||
/* Map clcd to a virtual address region */
|
||||
if (IS_ERR(l4_map((void *)__pfn_to_addr(clcd_cap[i].start),
|
||||
(void *)clcd[i].virt_base, clcd_cap[i].size,
|
||||
MAP_USR_IO_FLAGS,
|
||||
self_tid()))) {
|
||||
printf("%s: FATAL: Failed to map CLCD device "
|
||||
"%d to a virtual address\n",
|
||||
__CONTAINER_NAME__,
|
||||
cap_devnum(&clcd_cap[i]));
|
||||
BUG();
|
||||
}
|
||||
|
||||
/* Initialize clcd */
|
||||
pl110_initialise(&clcd[i], framebuffer);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct address_pool device_vaddr_pool;
|
||||
|
||||
/*
|
||||
* Initialize a virtual address pool
|
||||
* for mapping physical devices.
|
||||
*/
|
||||
void init_vaddr_pool(void)
|
||||
{
|
||||
for (int i = 0; i < total_caps; i++) {
|
||||
/* Find the virtual memory region for this process */
|
||||
if (cap_type(&caparray[i]) == CAP_TYPE_MAP_VIRTMEM &&
|
||||
__pfn_to_addr(caparray[i].start) ==
|
||||
(unsigned long)vma_start) {
|
||||
|
||||
/*
|
||||
* Do we have any unused virtual space
|
||||
* where we run, and do we have enough
|
||||
* pages of it to map all clcd?
|
||||
*/
|
||||
if (__pfn(page_align_up(__end))
|
||||
+ CLCD_TOTAL <= caparray[i].end) {
|
||||
/*
|
||||
* Yes. We initialize the device
|
||||
* virtual memory pool here.
|
||||
*
|
||||
* We may allocate virtual memory
|
||||
* addresses from this pool.
|
||||
*/
|
||||
address_pool_init(&device_vaddr_pool,
|
||||
page_align_up(__end),
|
||||
__pfn_to_addr(caparray[i].end),
|
||||
CLCD_TOTAL);
|
||||
return;
|
||||
} else
|
||||
goto out_err;
|
||||
}
|
||||
}
|
||||
|
||||
out_err:
|
||||
printf("%s: FATAL: No virtual memory "
|
||||
"region available to map "
|
||||
"devices.\n", __CONTAINER_NAME__);
|
||||
BUG();
|
||||
}
|
||||
|
||||
void *l4_new_virtual(int npages)
|
||||
{
|
||||
return address_new(&device_vaddr_pool, npages, PAGE_SIZE);
|
||||
}
|
||||
|
||||
void handle_requests(void)
|
||||
{
|
||||
u32 mr[MR_UNUSED_TOTAL];
|
||||
l4id_t senderid;
|
||||
u32 tag;
|
||||
int ret;
|
||||
|
||||
printf("%s: Initiating ipc.\n", __CONTAINER__);
|
||||
if ((ret = l4_receive(L4_ANYTHREAD)) < 0) {
|
||||
printf("%s: %s: IPC Error: %d. Quitting...\n",
|
||||
__CONTAINER__, __FUNCTION__, ret);
|
||||
BUG();
|
||||
}
|
||||
|
||||
/* Syslib conventional ipc data which uses first few mrs. */
|
||||
tag = l4_get_tag();
|
||||
senderid = l4_get_sender();
|
||||
|
||||
/* Read mrs not used by syslib */
|
||||
for (int i = 0; i < MR_UNUSED_TOTAL; i++)
|
||||
mr[i] = read_mr(MR_UNUSED_START + i);
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
*
|
||||
* Maybe add tags here that handle requests for sharing
|
||||
* of the requested cld device with the client?
|
||||
*
|
||||
* In order to be able to do that, we should have a
|
||||
* shareable/grantable capability to the device. Also
|
||||
* the request should (currently) come from a task
|
||||
* inside the current container
|
||||
*/
|
||||
|
||||
/*
|
||||
* FIXME: Right now we are talking to CLCD by default, we need to define protocol
|
||||
* for sommunication with CLCD service
|
||||
*/
|
||||
switch (tag) {
|
||||
|
||||
default:
|
||||
printf("%s: Error received ipc from 0x%x residing "
|
||||
"in container %x with an unrecognized tag: "
|
||||
"0x%x\n", __CONTAINER__, senderid,
|
||||
__cid(senderid), tag);
|
||||
}
|
||||
|
||||
/* Reply */
|
||||
if ((ret = l4_ipc_return(ret)) < 0) {
|
||||
printf("%s: IPC return error: %d.\n", __FUNCTION__, ret);
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* UTCB-size aligned utcb.
|
||||
*
|
||||
* BIG WARNING NOTE:
|
||||
* This in-place declaration is legal if we are running
|
||||
* in a disjoint virtual address space, where the utcb
|
||||
* declaration lies in a unique virtual address in
|
||||
* the system.
|
||||
*/
|
||||
#define DECLARE_UTCB(name) \
|
||||
struct utcb name ALIGN(sizeof(struct utcb))
|
||||
|
||||
DECLARE_UTCB(utcb);
|
||||
|
||||
/* Set up own utcb for ipc */
|
||||
int l4_utcb_setup(void *utcb_address)
|
||||
{
|
||||
struct task_ids ids;
|
||||
struct exregs_data exregs;
|
||||
int err;
|
||||
|
||||
l4_getid(&ids);
|
||||
|
||||
/* Clear utcb */
|
||||
memset(utcb_address, 0, sizeof(struct utcb));
|
||||
|
||||
/* Setup exregs for utcb request */
|
||||
memset(&exregs, 0, sizeof(exregs));
|
||||
exregs_set_utcb(&exregs, (unsigned long)utcb_address);
|
||||
|
||||
if ((err = l4_exchange_registers(&exregs, ids.tid)) < 0)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* Read all capabilities */
|
||||
cap_read_all();
|
||||
|
||||
/* Scan for clcd devices in capabilities */
|
||||
clcd_probe_devices();
|
||||
|
||||
/* Initialize virtual address pool for clcds */
|
||||
init_vaddr_pool();
|
||||
|
||||
/* Map and initialize clcd devices */
|
||||
clcd_setup_devices();
|
||||
|
||||
/* Setup own utcb */
|
||||
if ((err = l4_utcb_setup(&utcb)) < 0) {
|
||||
printf("FATAL: Could not set up own utcb. "
|
||||
"err=%d\n", err);
|
||||
BUG();
|
||||
}
|
||||
|
||||
/* Listen for clcd requests */
|
||||
while (1)
|
||||
handle_requests();
|
||||
}
|
||||
|
||||
0
conts/baremetal/clcd_service/src/test.c
Normal file
0
conts/baremetal/clcd_service/src/test.c
Normal file
@@ -24,13 +24,18 @@ LIBDEV_UART_PATH = join(PROJROOT, 'conts/libdev/uart')
|
||||
# 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')
|
||||
|
||||
e = env.Clone()
|
||||
e.Append(CPPPATH = [LIBDEV_UART_PATH + '/include', LIBDEV_TIEMR_PATH + '/include'],
|
||||
e.Append(CPPPATH = [LIBDEV_UART_PATH + '/include', LIBDEV_TIEMR_PATH + '/include',
|
||||
LIBDEV_CLCD_PATH + '/include',],
|
||||
CCFLAGS = ['-nostdinc', '-DVARIANT_' + variant.upper(),
|
||||
'-DPLATFORM_' + platform.upper()])
|
||||
|
||||
source = Glob('uart/src' + '/*.c') + \
|
||||
Glob('timer/sp804/src' + '/*.c')
|
||||
Glob('timer/sp804/src' + '/*.c') + \
|
||||
Glob('clcd/pl110/src' + '/*.c')
|
||||
|
||||
objects = e.StaticObject(source)
|
||||
library = e.StaticLibrary('libdev-' + variant, objects)
|
||||
|
||||
104
conts/libdev/clcd/pl110/include/pl110_clcd.h
Normal file
104
conts/libdev/clcd/pl110/include/pl110_clcd.h
Normal file
@@ -0,0 +1,104 @@
|
||||
|
||||
#ifndef __PL110_CLCD_H__
|
||||
#define __PL110_CLCD_H__
|
||||
|
||||
/* Register offsets */
|
||||
#define PL110_CLCD_TIMING0 0x000 /* Horizontal Axis Panel Control*/
|
||||
#define PL110_CLCD_TIMING1 0x004 /* Vertical Axis Panel Control */
|
||||
#define PL110_CLCD_TIMING2 0x008 /* Clock and Polarity Signal Control*/
|
||||
#define PL110_CLCD_TIMING3 0x00c /* Line End Control */
|
||||
#define PL110_CLCD_UPBASE 0x010 /* Upper Panel Frame Base Address*/
|
||||
#define PL110_CLCD_LPBASE 0x014 /* Lower Panel Frame Base Address */
|
||||
#define PL110_CLCD_IMSC 0x018 /* Interrupt Mast Set Clear */
|
||||
#define PL110_CLCD_CONTROL 0x01c /* CLCD Control */
|
||||
#define PL110_CLCD_RIS 0x020 /* Raw Interrupt Status */
|
||||
#define PL110_CLCD_MIS 0x024 /* Masked Interrupt Status */
|
||||
#define PL110_CLCD_ICR 0x028 /* Interrupt Clear */
|
||||
#define PL110_CLCD_UPCURR 0x02c /* Upper Panel Current Address Value */
|
||||
#define PL110_CLCD_LPCURR 0x030 /* Lower Panel Current Address Value */
|
||||
//#define PL110_LCD_PALETTE
|
||||
#define PL110_CLCD_PERIPHID0 0xfe0 /* Peripheral Identification */
|
||||
#define PL110_CLCD_PERIPHID1 0xfe4 /* Peripheral Identification */
|
||||
#define PL110_CLCD_PERIPHID2 0xfe8 /* Peripheral Identification */
|
||||
#define PL110_CLCD_PERIPHID3 0xfec /* Peripheral Identification */
|
||||
#define PL110_CLCD_PCELLID0 0xff0 /* Peripheral Identification */
|
||||
#define PL110_CLCD_PCELLID1 0xff4 /* PrimeCell Identification */
|
||||
#define PL110_CLCD_PCELLID2 0xff8 /* PrimeCell Identification */
|
||||
#define PL110_CLCD_PCELLID3 0xffc /* PrimeCell Identification */
|
||||
|
||||
/* Scan mode */
|
||||
#define SCAN_VMODE_NONINTERLACED 0 /* non interlaced */
|
||||
#define SCAN_VMODE_INTERLACED 1 /* interlaced */
|
||||
#define SCAN_VMODE_DOUBLE 2 /* double scan */
|
||||
#define SCAN_VMODE_ODD_FLD_FIRST 4 /* interlaced: top line first */
|
||||
#define SCAN_VMODE_MASK 255
|
||||
|
||||
/* Control Register Bits */
|
||||
#define PL110_CNTL_LCDEN (1 << 0)
|
||||
#define PL110_CNTL_LCDBPP1 (0 << 1)
|
||||
#define PL110_CNTL_LCDBPP2 (1 << 1)
|
||||
#define PL110_CNTL_LCDBPP4 (2 << 1)
|
||||
#define PL110_CNTL_LCDBPP8 (3 << 1)
|
||||
#define PL110_CNTL_LCDBPP16 (4 << 1)
|
||||
#define PL110_CNTL_LCDBPP16_565 (6 << 1)
|
||||
#define PL110_CNTL_LCDBPP24 (5 << 1)
|
||||
#define PL110_CNTL_LCDBW (1 << 4)
|
||||
#define PL110_CNTL_LCDTFT (1 << 5)
|
||||
#define PL110_CNTL_LCDMONO8 (1 << 6)
|
||||
#define PL110_CNTL_LCDDUAL (1 << 7)
|
||||
#define PL110_CNTL_BGR (1 << 8)
|
||||
#define PL110_CNTL_BEBO (1 << 9)
|
||||
#define PL110_CNTL_BEPO (1 << 10)
|
||||
#define PL110_CNTL_LCDPWR (1 << 11)
|
||||
#define PL110_CNTL_LCDVCOMP(x) ((x) << 12)
|
||||
#define PL110_CNTL_LDMAFIFOTIME (1 << 15)
|
||||
#define PL110_CNTL_WATERMARK (1 << 16)
|
||||
|
||||
#define PL110_TIM2_CLKSEL (1 << 5)
|
||||
#define PL110_TIM2_IVS (1 << 11)
|
||||
#define PL110_TIM2_IHS (1 << 12)
|
||||
#define PL110_TIM2_IPC (1 << 13)
|
||||
#define PL110_TIM2_IOE (1 << 14)
|
||||
#define PL110_TIM2_BCD (1 << 26)
|
||||
|
||||
|
||||
|
||||
struct videomode {
|
||||
const char *name; /* optional */
|
||||
unsigned int refresh; /* optional */
|
||||
unsigned int xres;
|
||||
unsigned int yres;
|
||||
unsigned int pixclock;
|
||||
unsigned int left_margin;
|
||||
unsigned int right_margin;
|
||||
unsigned int upper_margin;
|
||||
unsigned int lower_margin;
|
||||
unsigned int hsync_len;
|
||||
unsigned int vsync_len;
|
||||
unsigned int sync;
|
||||
unsigned int vmode;
|
||||
unsigned int flag;
|
||||
};
|
||||
|
||||
struct pl110_clcd_panel {
|
||||
struct videomode mode;
|
||||
signed short width; /* width in mm */
|
||||
signed short height; /* height in mm */
|
||||
unsigned int tim2;
|
||||
unsigned int tim3;
|
||||
unsigned int cntl;
|
||||
unsigned int bpp:8,
|
||||
fixedtimings:1,
|
||||
grayscale:1;
|
||||
unsigned int connector;
|
||||
};
|
||||
|
||||
struct pl110_clcd {
|
||||
unsigned int virt_base;
|
||||
struct pl110_clcd_panel *panel;
|
||||
char *frame_buffer;
|
||||
};
|
||||
|
||||
void pl110_initialise(struct pl110_clcd *clcd, char *buf);
|
||||
|
||||
#endif /* __PL110_CLCD_H__ */
|
||||
68
conts/libdev/clcd/pl110/src/pl110_clcd.c
Normal file
68
conts/libdev/clcd/pl110/src/pl110_clcd.c
Normal file
@@ -0,0 +1,68 @@
|
||||
|
||||
|
||||
#include <pl110_clcd.h>
|
||||
|
||||
#define read(a) *((volatile unsigned int *)(a))
|
||||
#define write(v, a) (*((volatile unsigned int *)(a)) = v)
|
||||
#define setbit(bit, a) write(read(a) | bit, a)
|
||||
#define clrbit(bit, a) write(read(a) & ~bit, a)
|
||||
|
||||
/*
|
||||
* Default panel, we will use this for now
|
||||
* Seems like qemu has support for this
|
||||
*/
|
||||
static struct pl110_clcd_panel vga = {
|
||||
.mode = {
|
||||
.name = "VGA",
|
||||
.refresh = 60,
|
||||
.xres = 640,
|
||||
.yres = 480,
|
||||
.pixclock = 39721,
|
||||
.left_margin = 40,
|
||||
.right_margin = 24,
|
||||
.upper_margin = 32,
|
||||
.lower_margin = 11,
|
||||
.hsync_len = 96,
|
||||
.vsync_len = 2,
|
||||
.sync = 0,
|
||||
.vmode = SCAN_VMODE_NONINTERLACED,
|
||||
},
|
||||
.width = -1,
|
||||
.height = -1,
|
||||
.tim2 = PL110_TIM2_BCD | PL110_TIM2_IPC,
|
||||
.cntl = PL110_CNTL_LCDTFT | PL110_CNTL_LCDVCOMP(1),
|
||||
.bpp = 16,
|
||||
};
|
||||
|
||||
static void pl110_clcd_set_uppanel_fb(unsigned int clcd_base,
|
||||
unsigned int fb_base)
|
||||
{
|
||||
write(fb_base, (clcd_base + PL110_CLCD_UPBASE));
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void pl110_clcd_set_lwrpanel_fb(unsigned int clcd_base, unsigned int fb_base)
|
||||
{
|
||||
write(fb_base, (clcd_base +PL110_CLCD_LPBASE));
|
||||
}
|
||||
|
||||
static unsigned int pl110_clcd_get_uppanel_fb(unsigned int clcd_base)
|
||||
{
|
||||
return read((clcd_base +PL110_CLCD_UPBASE));
|
||||
}
|
||||
|
||||
static unsigned int pl110_clcd_get_lwrpanel_fb(unsigned int clcd_base)
|
||||
{
|
||||
return read((clcd_base +PL110_CLCD_LPBASE));
|
||||
}
|
||||
#endif
|
||||
|
||||
void pl110_initialise(struct pl110_clcd *clcd, char *buf)
|
||||
{
|
||||
clcd->panel = &vga;
|
||||
clcd->frame_buffer = buf;
|
||||
|
||||
pl110_clcd_set_uppanel_fb(clcd->virt_base, (unsigned int)(buf));
|
||||
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#define PB926_UART1_BASE 0x101F2000 /* Console port (UART1) */
|
||||
#define PB926_UART2_BASE 0x101F3000 /* Console port (UART2) */
|
||||
#define PB926_UART3_BASE 0x10009000 /* Console port (UART3) */
|
||||
#define PB926_CLCD_BASE 0x10120000 /* Color LCD */
|
||||
|
||||
/*
|
||||
* Uart virtual address until a file-based console access
|
||||
|
||||
@@ -28,17 +28,21 @@
|
||||
|
||||
#define PB926_UART_SIZE 0x1000
|
||||
#define PB926_TIMER_SIZE 0x1000
|
||||
#define PB926_CLCD_SIZE 0x1000
|
||||
|
||||
#define PLATFORM_UART1_BASE PB926_UART1_BASE
|
||||
#define PLATFORM_UART2_BASE PB926_UART2_BASE
|
||||
#define PLATFORM_UART3_BASE PB926_UART3_BASE
|
||||
|
||||
#define PLATFORM_UART1_SIZE PB926_UART_SIZE
|
||||
#define PLATFORM_UART2_SIZE PB926_UART_SIZE
|
||||
#define PLATFORM_UART3_SIZE PB926_UART_SIZE
|
||||
|
||||
#define PLATFORM_TIMER1_BASE PB926_TIMER23_BASE
|
||||
#define PLATFORM_TIMER1_SIZE PB926_TIMER_SIZE
|
||||
|
||||
#define PLATFORM_CLCD0_BASE PB926_CLCD_BASE
|
||||
#define PLATFORM_CLCD0_SIZE PB926_CLCD_SIZE
|
||||
|
||||
int platform_setup_device_caps(struct kernel_resources *kres);
|
||||
void platform_irq_enable(int irq);
|
||||
void platform_irq_disable(int irq);
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
*/
|
||||
int platform_setup_device_caps(struct kernel_resources *kres)
|
||||
{
|
||||
struct capability *uart[4], *timer[4];
|
||||
struct capability *uart[4], *timer[4], *clcd[1];
|
||||
|
||||
/* Setup capabilities for userspace uarts and timers */
|
||||
uart[1] = alloc_bootmem(sizeof(*uart[1]), 0);
|
||||
@@ -66,6 +66,16 @@ int platform_setup_device_caps(struct kernel_resources *kres)
|
||||
link_init(&timer[1]->list);
|
||||
cap_list_insert(timer[1], &kres->devmem_free);
|
||||
|
||||
/* Setup clcd capability as free */
|
||||
clcd[0] = alloc_bootmem(sizeof(*clcd[0]), 0);
|
||||
clcd[0]->start = __pfn(PB926_CLCD_BASE);
|
||||
clcd[0]->end = clcd[0]->start + 1;
|
||||
clcd[0]->size = clcd[0]->end - clcd[0]->start;
|
||||
cap_set_devtype(clcd[0], CAP_DEVTYPE_CLCD);
|
||||
cap_set_devnum(clcd[0], 0);
|
||||
link_init(&clcd[0]->list);
|
||||
cap_list_insert(clcd[0], &kres->devmem_free);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user