From 3d2b87d4886d14067cc6d6355ce81c125afbf4dc Mon Sep 17 00:00:00 2001 From: Amit Mahajan Date: Fri, 4 Dec 2009 00:54:23 +0530 Subject: [PATCH] CLCD added as new capability, code note added yet --- config/cml/container_ruleset.template | 12 +- conts/baremetal/clcd_service/SConstruct | 67 +++++ conts/baremetal/clcd_service/container.c | 21 ++ .../clcd_service/include/capability.h | 12 + .../clcd_service/include/container.h | 13 + conts/baremetal/clcd_service/include/linker.h | 7 + conts/baremetal/clcd_service/main.c | 277 ++++++++++++++++++ conts/baremetal/clcd_service/src/test.c | 0 conts/libdev/SConscript | 9 +- conts/libdev/clcd/pl110/include/pl110_clcd.h | 104 +++++++ conts/libdev/clcd/pl110/src/pl110_clcd.c | 68 +++++ include/l4/platform/pb926/offsets.h | 1 + include/l4/platform/pb926/platform.h | 6 +- src/platform/pb926/platform.c | 12 +- 14 files changed, 604 insertions(+), 5 deletions(-) create mode 100644 conts/baremetal/clcd_service/SConstruct create mode 100644 conts/baremetal/clcd_service/container.c create mode 100644 conts/baremetal/clcd_service/include/capability.h create mode 100644 conts/baremetal/clcd_service/include/container.h create mode 100644 conts/baremetal/clcd_service/include/linker.h create mode 100644 conts/baremetal/clcd_service/main.c create mode 100644 conts/baremetal/clcd_service/src/test.c create mode 100644 conts/libdev/clcd/pl110/include/pl110_clcd.h create mode 100644 conts/libdev/clcd/pl110/src/pl110_clcd.c diff --git a/config/cml/container_ruleset.template b/config/cml/container_ruleset.template index fbf3899..5d47c15 100644 --- a/config/cml/container_ruleset.template +++ b/config/cml/container_ruleset.template @@ -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 diff --git a/conts/baremetal/clcd_service/SConstruct b/conts/baremetal/clcd_service/SConstruct new file mode 100644 index 0000000..7189aa4 --- /dev/null +++ b/conts/baremetal/clcd_service/SConstruct @@ -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') diff --git a/conts/baremetal/clcd_service/container.c b/conts/baremetal/clcd_service/container.c new file mode 100644 index 0000000..f570c3d --- /dev/null +++ b/conts/baremetal/clcd_service/container.c @@ -0,0 +1,21 @@ +/* + * Container entry point for pager + * + * Copyright (C) 2007-2009 B Labs Ltd. + */ + +#include +#include + + +extern void main(void); + +void __container_init(void) +{ + /* Generic L4 initialisation */ + __l4_init(); + + /* Entry to main */ + main(); +} + diff --git a/conts/baremetal/clcd_service/include/capability.h b/conts/baremetal/clcd_service/include/capability.h new file mode 100644 index 0000000..5cfce89 --- /dev/null +++ b/conts/baremetal/clcd_service/include/capability.h @@ -0,0 +1,12 @@ +#ifndef __UART_SERVICE_CAPABILITY_H__ +#define __UART_SERVICE_CAPABILITY_H__ + +#include +#include +#include + +void cap_print(struct capability *cap); +void cap_list_print(struct cap_list *cap_list); +int cap_read_all(); + +#endif /* header */ diff --git a/conts/baremetal/clcd_service/include/container.h b/conts/baremetal/clcd_service/include/container.h new file mode 100644 index 0000000..e6eece5 --- /dev/null +++ b/conts/baremetal/clcd_service/include/container.h @@ -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__ */ diff --git a/conts/baremetal/clcd_service/include/linker.h b/conts/baremetal/clcd_service/include/linker.h new file mode 100644 index 0000000..e39da2f --- /dev/null +++ b/conts/baremetal/clcd_service/include/linker.h @@ -0,0 +1,7 @@ +#ifndef __LINKER_H__ +#define __LINKER_H__ + +extern char vma_start[]; +extern char __end[]; + +#endif /* __LINKER_H__ */ diff --git a/conts/baremetal/clcd_service/main.c b/conts/baremetal/clcd_service/main.c new file mode 100644 index 0000000..72a8f85 --- /dev/null +++ b/conts/baremetal/clcd_service/main.c @@ -0,0 +1,277 @@ +/* + * CLCD service for userspace + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include /* FIXME: Its best if this is */ +#include + +#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(); +} + diff --git a/conts/baremetal/clcd_service/src/test.c b/conts/baremetal/clcd_service/src/test.c new file mode 100644 index 0000000..e69de29 diff --git a/conts/libdev/SConscript b/conts/libdev/SConscript index 96e5a46..1432a6f 100644 --- a/conts/libdev/SConscript +++ b/conts/libdev/SConscript @@ -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) diff --git a/conts/libdev/clcd/pl110/include/pl110_clcd.h b/conts/libdev/clcd/pl110/include/pl110_clcd.h new file mode 100644 index 0000000..b1f7777 --- /dev/null +++ b/conts/libdev/clcd/pl110/include/pl110_clcd.h @@ -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__ */ diff --git a/conts/libdev/clcd/pl110/src/pl110_clcd.c b/conts/libdev/clcd/pl110/src/pl110_clcd.c new file mode 100644 index 0000000..2ff23fd --- /dev/null +++ b/conts/libdev/clcd/pl110/src/pl110_clcd.c @@ -0,0 +1,68 @@ + + +#include + +#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)); + +} + diff --git a/include/l4/platform/pb926/offsets.h b/include/l4/platform/pb926/offsets.h index d8949ec..262ef51 100644 --- a/include/l4/platform/pb926/offsets.h +++ b/include/l4/platform/pb926/offsets.h @@ -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 diff --git a/include/l4/platform/pb926/platform.h b/include/l4/platform/pb926/platform.h index 035f26a..c131d6e 100644 --- a/include/l4/platform/pb926/platform.h +++ b/include/l4/platform/pb926/platform.h @@ -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); diff --git a/src/platform/pb926/platform.c b/src/platform/pb926/platform.c index c1b96d4..5ecdeee 100644 --- a/src/platform/pb926/platform.c +++ b/src/platform/pb926/platform.c @@ -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; }