l4re-base-25.08.0

This commit is contained in:
2025-09-12 15:55:45 +02:00
commit d959eaab98
37938 changed files with 9382688 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
provides: libdrivers-lcd libdrivers-input libdrivers-generic
requires: libc l4re_c libio input drivers-frst
Maintainer: adam@os.inf.tu-dresden.de

View File

@@ -0,0 +1,9 @@
PKGDIR = .
L4DIR ?= $(PKGDIR)/../..
TARGET = generic lcd input
include $(L4DIR)/mk/subdir.mk
lcd: generic
input: generic

View File

@@ -0,0 +1,8 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../..
TARGET := include src
include $(L4DIR)/mk/subdir.mk
src: include

View File

@@ -0,0 +1,4 @@
PKGDIR = ../..
L4DIR ?= $(PKGDIR)/../..
include $(L4DIR)/mk/include.mk

View File

@@ -0,0 +1,22 @@
/*
* (c) 2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
* This file is part of TUD:OS and distributed under the terms of the
* GNU Lesser General Public License 2.1.
* Please see the COPYING-LGPL-2.1 file for details.
*/
#ifndef __ARM_DRIVERS__GENERIC__INCLUDE__AMBA_H__
#define __ARM_DRIVERS__GENERIC__INCLUDE__AMBA_H__
#include <sys/cdefs.h>
#include <l4/sys/compiler.h>
#include <l4/sys/types.h>
#include <stdint.h>
L4_BEGIN_DECLS
void amba_read_id(l4_addr_t address, uint32_t *periphid, uint32_t *cellid);
L4_END_DECLS
#endif /* ! __ARM_DRIVERS__LCD__INCLUDE__LCD_H__ */

View File

@@ -0,0 +1,8 @@
PKGDIR ?= ../..
L4DIR ?= $(PKGDIR)/../..
SRC_CC := amba.cc
TARGET = libarm_generic.a
PC_FILENAME := libdrivers-generic
include $(L4DIR)/mk/lib.mk

View File

@@ -0,0 +1,19 @@
#include <l4/drivers/io_regblock.h>
#include <l4/drivers/amba.h>
void amba_read_id(l4_addr_t address, uint32_t *periphid, uint32_t *cellid)
{
L4::Io_register_block_mmio b(address);
*periphid = ((b.read32( 0) & 0xff) << 0)
| ((b.read32( 4) & 0xff) << 8)
| ((b.read32( 8) & 0xff) << 16)
| ((b.read32(12) & 0xff) << 24);
*cellid = ((b.read32(16) & 0xff) << 0)
| ((b.read32(20) & 0xff) << 8)
| ((b.read32(24) & 0xff) << 16)
| ((b.read32(28) & 0xff) << 24);
}

View File

@@ -0,0 +1,4 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../..
include $(L4DIR)/mk/subdir.mk

View File

@@ -0,0 +1,10 @@
PKGDIR ?= ../..
L4DIR ?= $(PKGDIR)/../..
SRC_C := tsc-omap3.c kp-omap3.c
TARGET = libarm_input.o.a
PC_FILENAME := libdrivers-input
REQUIRES_LIBS = l4re_c-util libio
include $(L4DIR)/mk/lib.mk

View File

@@ -0,0 +1,114 @@
#pragma once
/* Module ids */
#define TWL4030_MODULE_USB 0x00
#define TWL4030_MODULE_AUDIO_VOICE 0x01
#define TWL4030_MODULE_GPIO 0x02
#define TWL4030_MODULE_INTBR 0x03
#define TWL4030_MODULE_PIH 0x04
#define TWL4030_MODULE_TEST 0x05
#define TWL4030_MODULE_KEYPAD 0x06
#define TWL4030_MODULE_MADC 0x07
#define TWL4030_MODULE_INTERRUPTS 0x08
#define TWL4030_MODULE_LED 0x09
#define TWL4030_MODULE_MAIN_CHARGE 0x0A
#define TWL4030_MODULE_PRECHARGE 0x0B
#define TWL4030_MODULE_PWM0 0x0C
#define TWL4030_MODULE_PWM1 0x0D
#define TWL4030_MODULE_PWMA 0x0E
#define TWL4030_MODULE_PWMB 0x0F
#define TWL4030_MODULE_BACKUP 0x10
#define TWL4030_MODULE_INT 0x11
#define TWL4030_MODULE_PM_MASTER 0x12
#define TWL4030_MODULE_PM_RECEIVER 0x13
#define TWL4030_MODULE_RTC 0x14
#define TWL4030_MODULE_SECURED_REG 0x15
#define TWL4030_MODULES TWL4030_MODULE_SECURED_REG
/* Module address bases */
/* USB ID */
#define TWL4030_BASE_USB 0x00
/* AUD ID */
#define TWL4030_BASE_AUDIO_VOICE 0x00
#define TWL4030_BASE_GPIO 0x98
#define TWL4030_BASE_INTBR 0x85
#define TWL4030_BASE_PIH 0x80
#define TWL4030_BASE_TEST 0x4C
/* AUX ID */
#define TWL4030_BASE_INTERRUPTS 0xB9
#define TWL4030_BASE_LED 0xEE
#define TWL4030_BASE_MADC 0x00
#define TWL4030_BASE_MAIN_CHARGE 0x74
#define TWL4030_BASE_PRECHARGE 0xAA
#define TWL4030_BASE_PWM0 0xF8
#define TWL4030_BASE_PWM1 0xFB
#define TWL4030_BASE_PWMA 0xEF
#define TWL4030_BASE_PWMB 0xF1
#define TWL4030_BASE_KEYPAD 0xD2
/* POWER ID */
#define TWL4030_BASE_BACKUP 0x14
#define TWL4030_BASE_INT 0x2E
#define TWL4030_BASE_PM_MASTER 0x36
#define TWL4030_BASE_PM_RECIEVER 0x5B
#define TWL4030_BASE_RTC 0x1C
#define TWL4030_BASE_SECURED_REG 0x00
/* Primary Interrupt Handler registers */
#define REG_PIH_ISR_P1 0x01
#define REG_PIH_ISR_P2 0x02
#define REG_PIH_SIR 0x03
/* Keypad module registers */
#define REG_KEYP_CTRL_REG 0x00
#define REG_KEY_DEB_REG 0x01
#define REG_LONG_KEY_REG1 0x02
#define REG_LK_PTV_REG 0x03
#define REG_TIME_OUT_REG1 0x04
#define REG_TIME_OUT_REG2 0x05
#define REG_KBC_REG 0x06
#define REG_KBR_REG 0x07
#define REG_KEYP_SMS 0x08
#define REG_FULL_CODE_7_0 0x09
#define REG_FULL_CODE_7_0 0x09
#define REG_FULL_CODE_15_8 0x0A
#define REG_FULL_CODE_23_16 0x0B
#define REG_FULL_CODE_31_24 0x0C
#define REG_FULL_CODE_39_32 0x0D
#define REG_FULL_CODE_47_40 0x0E
#define REG_FULL_CODE_55_48 0x0F
#define REG_FULL_CODE_63_56 0x10
#define REG_KEYP_ISR1 0x11
#define REG_KEYP_IMR1 0x12
#define REG_KEYP_ISR2 0x13
#define REG_KEYP_IMR2 0x14
#define REG_KEYP_SIR 0x15
#define REG_KEYP_EDR 0x16
#define REG_KEYP_SIH_CTRL 0x17
#if 0
/* Keypad registers */
#define KEYP_CTRL_REG 0xD2
#define KEY_DEB_REG 0xD3
#define LONG_KEY_REG1 0xD4
#define LK_PTV_REG 0xD5
#define TIME_OUT_REG1 0xD6
#define TIME_OUT_REG2 0xD7
#define KBC_REG 0xD8
#define KBR_REG 0xD9
#define KEYP_SMS 0xDA
#define FULL_CODE_7_0 0xDB
#define FULL_CODE_15_8 0xDC
#define FULL_CODE_23_16 0xDD
#define FULL_CODE_31_24 0xDE
#define FULL_CODE_39_32 0xDF
#define FULL_CODE_47_40 0xE0
#define FULL_CODE_55_48 0xE1
#define FULL_CODE_63_56 0xE2
#define KEYP_ISR1 0xE3
#define KEYP_IMR1 0xE4
#define KEYP_ISR2 0xE5
#define KEYP_IMR2 0xE6
#define KEYP_SIR 0xE7
#define KEYP_EDR 0xE8
#define KEYP_SIH_CTRL 0xE9
#endif

View File

@@ -0,0 +1,385 @@
/*
* OMAP keypad driver
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <pthread-l4.h>
#include <l4/input/drv_reg.h>
#include <l4/io/io.h>
#include <l4/re/c/namespace.h>
#include <l4/re/c/util/cap_alloc.h>
#include <l4/re/event_enums.h>
#include <l4/util/util.h>
#include <l4/sys/irq.h>
#include <l4/sys/thread.h>
#include <l4/sys/debugger.h>
#include <l4/vbus/vbus.h>
#include <l4/vbus/vbus_i2c.h>
#include "kp-omap.h"
#define NUM_ROWS 5
#define NUM_COLS 4
static unsigned char kp_keycode[16] = {
L4RE_KEY_1, L4RE_KEY_2, L4RE_KEY_3, L4RE_KEY_4,
L4RE_KEY_5, L4RE_KEY_6, L4RE_KEY_7, L4RE_KEY_8,
L4RE_KEY_9, L4RE_KEY_0, L4RE_KEY_A, L4RE_KEY_B,
L4RE_KEY_C, L4RE_KEY_D, L4RE_KEY_E, L4RE_KEY_F,
};
static Input_handler kp_handler;
static void* kp_priv;
static pthread_t _pthread;
static l4_cap_idx_t vbus = L4_INVALID_CAP;
static l4vbus_device_handle_t i2c_handle = 0;
/* I2C slave ID */
#define TWL4030_SLAVENUM_NUM0 0x48
#define TWL4030_SLAVENUM_NUM1 0x49
#define TWL4030_SLAVENUM_NUM2 0x4a
#define TWL4030_SLAVENUM_NUM3 0x4b
/* Module Mapping */
struct twl4030mapping
{
unsigned char sid; /* Slave ID */
unsigned char base; /* base address */
};
/* mapping the module id to slave id and base address */
static struct twl4030mapping twl4030_map[TWL4030_MODULES + 1] = {
{ TWL4030_SLAVENUM_NUM0, TWL4030_BASE_USB },
{ TWL4030_SLAVENUM_NUM1, TWL4030_BASE_AUDIO_VOICE },
{ TWL4030_SLAVENUM_NUM1, TWL4030_BASE_GPIO },
{ TWL4030_SLAVENUM_NUM1, TWL4030_BASE_INTBR },
{ TWL4030_SLAVENUM_NUM1, TWL4030_BASE_PIH },
{ TWL4030_SLAVENUM_NUM1, TWL4030_BASE_TEST },
{ TWL4030_SLAVENUM_NUM2, TWL4030_BASE_KEYPAD },
{ TWL4030_SLAVENUM_NUM2, TWL4030_BASE_MADC },
{ TWL4030_SLAVENUM_NUM2, TWL4030_BASE_INTERRUPTS },
{ TWL4030_SLAVENUM_NUM2, TWL4030_BASE_LED },
{ TWL4030_SLAVENUM_NUM2, TWL4030_BASE_MAIN_CHARGE },
{ TWL4030_SLAVENUM_NUM2, TWL4030_BASE_PRECHARGE },
{ TWL4030_SLAVENUM_NUM2, TWL4030_BASE_PWM0 },
{ TWL4030_SLAVENUM_NUM2, TWL4030_BASE_PWM1 },
{ TWL4030_SLAVENUM_NUM2, TWL4030_BASE_PWMA },
{ TWL4030_SLAVENUM_NUM2, TWL4030_BASE_PWMB },
{ TWL4030_SLAVENUM_NUM3, TWL4030_BASE_BACKUP },
{ TWL4030_SLAVENUM_NUM3, TWL4030_BASE_INT },
{ TWL4030_SLAVENUM_NUM3, TWL4030_BASE_PM_MASTER },
{ TWL4030_SLAVENUM_NUM3, TWL4030_BASE_PM_RECIEVER },
{ TWL4030_SLAVENUM_NUM3, TWL4030_BASE_RTC },
{ TWL4030_SLAVENUM_NUM3, TWL4030_BASE_SECURED_REG },
};
#if 1
static int twl4030_i2c_write_u8(unsigned mod_no, l4_uint8_t value, l4_uint8_t reg)
{
return l4vbus_i2c_write(vbus, i2c_handle, twl4030_map[mod_no].sid, twl4030_map[mod_no].base + reg, &value, 1);
}
#endif
#if 0
static int twl4030_i2c_read_u8(unsigned mod_no, l4_uint8_t *value, l4_uint8_t reg)
{
unsigned long size = 1;
return l4vbus_i2c_read(vbus, i2c_handle, twl4030_map[mod_no].sid, twl4030_map[mod_no].base + reg, value, &size);
}
#endif
static int twl4030_i2c_read_u32(int mod_no, l4_uint8_t *value, l4_uint8_t reg)
{
unsigned long size = 4;
return l4vbus_i2c_read(vbus, i2c_handle, twl4030_map[mod_no].sid, twl4030_map[mod_no].base + reg, value, &size);
}
static int kp_read(int reg, l4_uint8_t *val)
{
unsigned long size = 1;
return l4vbus_i2c_read(vbus, i2c_handle, twl4030_map[TWL4030_MODULE_KEYPAD].sid,
twl4030_map[TWL4030_MODULE_KEYPAD].base + reg, val, &size);
}
static int kp_write(int reg, l4_uint8_t val)
{
return l4vbus_i2c_write(vbus, i2c_handle, twl4030_map[TWL4030_MODULE_KEYPAD].sid,
twl4030_map[TWL4030_MODULE_KEYPAD].base + reg, &val, 1);
}
#if 1
static int twl_init_irq(void)
{
int ret = 0;
/* PWR_ISR1 */
ret |= twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x00);
/* PWR_ISR2 */
ret |= twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x02);
/* PWR_IMR1 */
ret |= twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x1);
/* PWR_IMR2 */
ret |= twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x3);
/* PWR_ISR1 */
ret |= twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x00);
/* PWR_ISR2 */
ret |= twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x02);
/* BCIIMR1_1 */
ret |= twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xFF, 0x3);
/* BCIIMR1_2 */
ret |= twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xFF, 0x4);
/* BCIIMR2_1 */
ret |= twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xFF, 0x7);
/* BCIIMR2_2 */
ret |= twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xFF, 0x8);
/* MADC */
/* MADC_IMR1 */
ret |= twl4030_i2c_write_u8(TWL4030_MODULE_MADC, 0xFF, 0x62);
/* MADC_IMR2 */
ret |= twl4030_i2c_write_u8(TWL4030_MODULE_MADC, 0xFF, 0x64);
/* GPIO_IMR1A */
ret |= twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, 0x1C);
/* GPIO_IMR2A */
ret |= twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, 0x1D);
/* GPIO_IMR3A */
ret |= twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, 0x1E);
/* GPIO_IMR1B */
ret |= twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, 0x22);
/* GPIO_IMR2B */
ret |= twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, 0x23);
/* GPIO_IMR3B */
ret |= twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, 0x24);
return ret;
}
#endif
static int init_keypad(void)
{
int ret = 0;
twl_init_irq();
// Enable software mode and keypad power on
ret = kp_write(REG_KEYP_CTRL_REG, 0x43);
// Mask all interrupts
ret |= kp_write(REG_KEYP_IMR1, 0x0f);
{
/* Clear ISR */
l4_uint8_t v;
kp_read(REG_KEYP_ISR1, &v);
kp_read(REG_KEYP_ISR1, &v);
}
// Trigger interrupts on rising edge
ret |= kp_write(REG_KEYP_EDR, 0xaa);
// Set pre scalar field
ret |= kp_write(REG_LK_PTV_REG, 4 << 5);
// Set key debounce time
ret |= kp_write(REG_KEY_DEB_REG, 0x3f);
// Enable COR-mode
ret |= kp_write(REG_KEYP_SIH_CTRL, 0x4);
// unmask all interrupts
ret |= kp_write(REG_KEYP_IMR1, 0);
return ret;
}
#if 0
static void drive_vibr(void)
{
// VIBRATOR_CFG
l4_uint8_t v = (1<<3)|(1<<2)|1;
unsigned long s = 1;
l4vbus_i2c_write(vbus, i2c_handle, 0x4b, 0x60, &v, 1);
// configure mux
//v = 0x10;
//l4vbus_i2c_write(vbus, i2c_handle, 0x49, 0x92, &v, 1);
l4_uint16_t w = (0x4 << 13)|(0x1 << 12)|(0x1 << 4)|(0xe);
l4_uint8_t *p = (l4_uint8_t *)(&w);
l4vbus_i2c_write(vbus, i2c_handle, 0x4b, 0x4b, &(p[1]), 1);
l4vbus_i2c_write(vbus, i2c_handle, 0x4b, 0x4c, &(p[0]), 1);
printf("WRITE:%x %x\n", p[1], p[0]);
l4vbus_i2c_read(vbus, i2c_handle, 0x4b, 0x73, &v, &s);
printf("VAUX1_TYPE:%x\n", v);
l4vbus_i2c_read(vbus, i2c_handle, 0x4b, 0x74, &v, &s);
printf("VAUX1_REMAP:%x\n", v);
l4vbus_i2c_read(vbus, i2c_handle, 0x4b, 0x75, &v, &s);
printf("VAUX1_DEDICATED:%x\n", v);
l4vbus_i2c_read(vbus, i2c_handle, 0x4b, 0x76, &v, &s);
printf("VAUX1_DEV_GRP:%x\n", v);
}
#endif
static void reset_keypad(void)
{
kp_write(REG_KEYP_IMR1, 0xf);
}
static l4_uint8_t old_state[NUM_ROWS] = { 0 };
static int scan_key(void)
{
l4_uint8_t new_state[NUM_ROWS];
//unsigned long size = NUM_ROWS;
twl4030_i2c_read_u32(TWL4030_MODULE_KEYPAD, new_state, REG_FULL_CODE_7_0);
printf("[KEYP] state:%x %x %x %x %x\n",
new_state[0], new_state[1], new_state[2], new_state[3], new_state[4]);
/* check for changes and print those */
int row = 0;
for (row = 0; row < NUM_ROWS; row++)
{
int changed = new_state[row] ^ old_state[row];
if (!changed)
continue;
int col = 0;
for (col = 0; col < NUM_COLS; col++)
{
if (!(changed & (1 << col)))
continue;
int key_pressed = new_state[row] & (1 << col);
printf("***********************key %s:row:%d col:%d\n", key_pressed ? "pressed" : "released", row, col);
Input_event ev = { L4RE_EV_KEY, kp_keycode[row * NUM_COLS + col], key_pressed };
kp_handler(ev, kp_priv);
}
}
memcpy(old_state, new_state, NUM_ROWS);
return 0;
}
static int kp_irq_func(void)
{
l4_cap_idx_t irq_cap = l4re_util_cap_alloc();
l4_cap_idx_t thread_cap = pthread_l4_cap(_pthread);
l4_msgtag_t tag;
l4_debugger_set_object_name(thread_cap, "kp-omap3.irq");
if (l4io_request_irq(7, irq_cap) < 0)
return -2;
// was L4_IRQ_F_LEVEL_LOW
tag = l4_rcv_ep_bind_thread(irq_cap, thread_cap, 0);
if (l4_ipc_error(tag, l4_utcb()))
return -3;
while (1)
{
tag = l4_irq_receive(irq_cap, L4_IPC_NEVER);
if (l4_ipc_error(tag, l4_utcb()))
{
printf("[KEYP] Error: Receive irq failed\n");
continue;
}
kp_write(REG_KEYP_IMR1, 0xf);
if (kp_handler)
scan_key();
l4_uint8_t value = 0;
kp_read(REG_KEYP_ISR1, &value);
kp_write(REG_KEYP_IMR1, 0x0);
}
}
static void* __irq_func(void *data)
{
(void)data;
int ret = kp_irq_func();
printf("[KEYP] Warning: irq handler returned with:%d\n", ret);
l4_sleep_forever();
}
static
int kp_init(void)
{
vbus = l4re_env_get_cap("vbus");
if (l4_is_invalid_cap(vbus))
{
printf("[KEYP] Failed to query vbus\n");
return -1;
}
if (l4vbus_get_device_by_hid(vbus, 0, &i2c_handle, "i2c", 0, 0))
{
printf("[KEYP] ##### Cannot find I2C\n");
}
return init_keypad();
}
static const char *kp_get_info(void)
{ return "ARM OMAP3EVM Keypad"; }
static int kp_probe(const char *name)
{
if (strcmp("OMAP_KP", name))
{
printf("[KEYP] I'm not the right driver for %s\n", name);
return 0;
}
return !l4io_lookup_device("OMAP_KP", NULL, 0, 0);
}
static void kp_attach(Input_handler handler, void *priv)
{
kp_handler = handler;
kp_priv = priv;
pthread_attr_t thread_attr;
int err;
if ((err = pthread_attr_init(&thread_attr)) != 0)
printf("[KEYP] Error: Initializing pthread attr: %d\n", err);
struct sched_param sp;
sp.sched_priority = 0x20;
pthread_attr_setschedpolicy(&thread_attr, SCHED_L4);
pthread_attr_setschedparam(&thread_attr, &sp);
pthread_attr_setinheritsched(&thread_attr, PTHREAD_EXPLICIT_SCHED);
err = pthread_create(&_pthread, &thread_attr, __irq_func, 0);
if (err != 0)
printf("[KEYP] Error: Creating thread\n");
}
static void kp_enable(void)
{
if (kp_init())
{
printf("[KEYP] Error: Init failed!\n");
return;
}
}
static void kp_disable(void)
{
reset_keypad();
}
static struct arm_input_ops arm_kp_ops_omap3 = {
.get_info = kp_get_info,
.probe = kp_probe,
.attach = kp_attach,
.enable = kp_enable,
.disable = kp_disable,
};
arm_input_register(&arm_kp_ops_omap3);

View File

@@ -0,0 +1,277 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <pthread-l4.h>
#include <l4/input/drv_reg.h>
#include <l4/re/c/dataspace.h>
#include <l4/re/c/mem_alloc.h>
#include <l4/re/c/rm.h>
#include <l4/re/c/namespace.h>
#include <l4/re/c/util/cap_alloc.h>
#include <l4/re/event_enums.h>
#include <l4/io/io.h>
#include <l4/sys/icu.h>
#include <l4/sys/irq.h>
#include <l4/sys/thread.h>
#include <l4/sys/debugger.h>
#include <l4/util/util.h>
#include <l4/vbus/vbus.h>
#include <l4/vbus/vbus_gpio.h>
#include <l4/vbus/vbus_mcspi.h>
#include "tsc-omap3.h"
typedef struct {
int x;
int y;
} Tsc_coord;
typedef struct {
Tsc_coord ul; // upper left coordinate
Tsc_coord lr; // lower right coordinate
} Tsc_disp;
static int get_width(Tsc_disp *d)
{ return d->lr.x - d->ul.x; }
static int get_height(Tsc_disp *d)
{ return d->lr.y - d->ul.y; }
static int is_valid(Tsc_disp *d, int x, int y)
{
if ((x >= d->ul.x) && (x <= d->lr.x) &&
(y >= d->ul.y) && (y <= d->lr.y))
return 1;
else
return 0;
}
static char *omap_dev_name = "OMAP_TSC";
static Input_handler tsc_handler;
static void *tsc_priv;
static pthread_t _pthread;
static l4_cap_idx_t vbus = L4_INVALID_CAP;
static l4vbus_device_handle_t tsc_handle;
static l4vbus_device_handle_t gpio_handle;
static l4vbus_device_handle_t mcspi_handle;
static unsigned irq = 175;
static unsigned channel = 0; // This is fixed
// FIXME: the physical display depends on the touchscreen device
static Tsc_disp disp_phys = {{ 3856, 3856}, { 176, 176 }};
// FIXME: the virtual display depends on the LCD device
static Tsc_disp disp_virt = {{ 0, 0 }, { 480, 640 }};
static int tsc_init(void)
{
vbus = l4re_env_get_cap("vbus");
if (l4_is_invalid_cap(vbus))
{
printf("Failed to query vbus\n");
return -1;
}
if (l4vbus_get_device_by_hid(vbus, 0, &tsc_handle, omap_dev_name, 0, 0))
{
printf("[TSC] Cannot find TSC device\n");
return -L4_ENODEV;
}
if (l4vbus_get_device_by_hid(vbus, 0, &gpio_handle, "gpio", 0, 0))
{
printf("[TSC] Cannot find GPIO bus\n");
return -L4_ENODEV;
}
if (l4vbus_get_device_by_hid(vbus, 0, &mcspi_handle, "mcspi", 0, 0))
{
printf("[TSC] Cannot find McSPI bus\n");
return -L4_ENODEV;
}
return 0;
}
#if 0
static void tsc_get_pen_position(int *x, int *y)
{
l4_umword_t data1 = 0, data2 = 0, data3 = 0, data4 = 0;
l4vbus_bus_read(2, 0x8000, &data1);
l4vbus_bus_read(2, 0xd300, &data2);
l4vbus_bus_read(2, 0x9300, &data3);
l4vbus_bus_read(2, 0x8000, &data4);
// convert physical display coordinates to virtual display coordinates
*x = ((*x - disp_phys.ul.x) * get_width(&disp_virt))/get_width(&disp_phys) + disp_virt.ul.x;
*y = ((*y - disp_phys.ul.y) * get_height(&disp_virt))/get_height(&disp_phys) + disp_virt.ul.y;
}
#endif
static void tsc_get_pen_position(int *x, int *y)
{
l4_umword_t data1 = 0, data2 = 0, data3 = 0, data4 = 0;
l4vbus_mcspi_write(vbus, mcspi_handle, channel, 0x8000);
l4vbus_mcspi_read(vbus, mcspi_handle, channel, &data1);
l4vbus_mcspi_write(vbus, mcspi_handle, channel, 0xd300);
l4vbus_mcspi_read(vbus, mcspi_handle, channel, &data2);
l4vbus_mcspi_write(vbus, mcspi_handle, channel, 0x9300);
l4vbus_mcspi_read(vbus, mcspi_handle, channel, &data3);
l4vbus_mcspi_write(vbus, mcspi_handle, channel, 0x8000);
l4vbus_mcspi_read(vbus, mcspi_handle, channel, &data4);
*x = ((data2 & 0x7f) << 5) | ((data3 & 0xf800) >> 11);
*y = ((data3 & 0x7f) << 5) | ((data4 & 0xf800) >> 11);
// XXX convert physical display coordinates to virtual display coordinates
*x = ((*x - disp_phys.ul.x) * get_width(&disp_virt))/get_width(&disp_phys) + disp_virt.ul.x;
*y = ((*y - disp_phys.ul.y) * get_height(&disp_virt))/get_height(&disp_phys) + disp_virt.ul.y;
//printf ("[TSC] Info: (x,y)=(%d,%d)\n", *x, *y);
}
l4_cap_idx_t get_icu(void);
static void create_motion_event(void)
{
int x = 0, y = 0;
tsc_get_pen_position(&x, &y);
if (is_valid(&disp_virt, x, y))
{
Input_event ev_x = { L4RE_EV_ABS, L4RE_ABS_X, x };
tsc_handler(ev_x, tsc_priv);
Input_event ev_y = { L4RE_EV_ABS, L4RE_ABS_Y, y };
tsc_handler(ev_y, tsc_priv);
}
}
static int tsc_irq_func(void)
{
l4_cap_idx_t irq_cap = l4re_util_cap_alloc();
l4_cap_idx_t thread_cap = pthread_l4_cap(_pthread);
l4_msgtag_t tag;
l4_debugger_set_object_name(thread_cap, "tsc-omap3.irq");
#if 0
if (l4io_request_irq2(irq, irq_cap, L4_IRQ_F_NEG_EDGE) < 0)
return -2;
#endif
// was L4_IRQ_F_LEVEL_HIGH
tag = l4_rcv_ep_bind_thread(irq_cap, thread_cap, 0);
if (l4_ipc_error(tag, l4_utcb()))
return -3;
while (1)
{
tag = l4_irq_receive(irq_cap, L4_IPC_NEVER);
if (l4_ipc_error(tag, l4_utcb()))
{
printf("[TSC] Error: Receive irq failed\n");
continue;
}
if (!tsc_handler)
continue;
create_motion_event();
// generate touch start event;
Input_event ev = { L4RE_EV_KEY, L4RE_BTN_LEFT, 1 };
tsc_handler(ev, tsc_priv);
int pen_up = 0;
if ((pen_up = l4vbus_gpio_get(vbus, gpio_handle, irq)) < 0)
return -6;
while (!pen_up)
{
create_motion_event();
l4_usleep(2);
if ((pen_up = l4vbus_gpio_get(vbus, gpio_handle, irq)) < 0)
return -6;
}
// generate touch end event;
Input_event ev2 = { L4RE_EV_KEY, L4RE_BTN_LEFT, 0 };
tsc_handler(ev2, tsc_priv);
#if 0
l4_umword_t label = 0;
l4_icu_unmask(get_icu(), irq, &label, L4_IPC_NEVER);
#endif
}
}
static void* __irq_func(void *data)
{
(void)data;
int ret = tsc_irq_func();
printf("[TSC] Warning: irq handler returned with:%d\n", ret);
l4_sleep_forever();
}
static const char *tsc_get_info(void)
{ return "ARM OMAP3EVM TSC"; }
static int tsc_probe(const char *name)
{
if (strcmp(omap_dev_name, name)) {
printf("[TSC] I'm not the right driver for [%s]\n", name);
return 0;
}
return !l4io_lookup_device(omap_dev_name, NULL, 0, 0);
}
static void tsc_attach(Input_handler handler, void *priv)
{
tsc_handler = handler;
tsc_priv = priv;
pthread_attr_t thread_attr;
int err;
if ((err = pthread_attr_init(&thread_attr)) != 0)
printf("[TSC] Error: Initializing pthread attr: %d", err);
struct sched_param sp;
sp.sched_priority = 0x20;
pthread_attr_setschedpolicy(&thread_attr, SCHED_L4);
pthread_attr_setschedparam(&thread_attr, &sp);
pthread_attr_setinheritsched(&thread_attr, PTHREAD_EXPLICIT_SCHED);
err = pthread_create(&_pthread, &thread_attr, __irq_func, 0);
if (err != 0)
printf("[TSC] Error: Creating thread");
}
static void tsc_enable(void)
{
if (tsc_init())
{
printf("[TSC] Init failed!\n");
return;
}
}
static void tsc_disable(void)
{}
static struct arm_input_ops arm_tsc_ops_omap3 = {
.get_info = tsc_get_info,
.probe = tsc_probe,
.attach = tsc_attach,
.enable = tsc_enable,
.disable = tsc_disable,
};
arm_input_register(&arm_tsc_ops_omap3);

View File

@@ -0,0 +1,11 @@
#pragma once
#define GPIO_NUM_VDD 153
enum {
Tsc2046_start = 0x1 << 7,
Tsc2046_x = 0x1 << 4,
Tsc2046_z1 = 0x3 << 4,
Tsc2046_z2 = 0x4 << 4,
Tsc2046_y = 0x5 << 4,
};

View File

@@ -0,0 +1,8 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../..
TARGET := include src
include $(L4DIR)/mk/subdir.mk
src: include

View File

@@ -0,0 +1,4 @@
PKGDIR = ../..
L4DIR ?= $(PKGDIR)/../..
include $(L4DIR)/mk/include.mk

View File

@@ -0,0 +1,33 @@
#ifndef __ARM_DRIVERS__LCD__INCLUDE__LCD_H__
#define __ARM_DRIVERS__LCD__INCLUDE__LCD_H__
#include <l4/sys/compiler.h>
#include <l4/sys/types.h>
#include <l4/re/c/video/view.h>
L4_BEGIN_DECLS
struct arm_lcd_ops {
int (*probe)(const char *configstr);
void * (*get_fb)(void);
unsigned int (*get_video_mem_size)(void);
const char * (*get_info)(void);
int (*get_fbinfo)(l4re_video_view_info_t *vinfo);
void (*enable)(void);
void (*disable)(void);
};
struct arm_lcd_ops *arm_lcd_probe(const char *configstr);
void arm_lcd_register_driver(struct arm_lcd_ops *);
/* Callable once per file (should be enough?) */
#define arm_lcd_register(ops) \
static void __attribute__((constructor)) __register_ops(void) \
{ arm_lcd_register_driver(ops); }
L4_END_DECLS
#endif /* ! __ARM_DRIVERS__LCD__INCLUDE__LCD_H__ */

View File

@@ -0,0 +1,12 @@
PKGDIR ?= ../..
L4DIR ?= $(PKGDIR)/../..
SRC_C := lcd.c lcd-virtual.c lcd-amba.c lcd-s3c2410.c lcd-omap3.c #lcd-h3800.c
SRC_C += lcd-tegra2.c lcd-mdp5.c
TARGET = libarm_lcd.o.a
PC_FILENAME := libdrivers-lcd
REQUIRES_LIBS := libio l4re_c l4re_c-util libdrivers-generic
PRIVATE_INCDIR += $(PKGDIR)/lcd/src
include $(L4DIR)/mk/lib.mk

View File

@@ -0,0 +1,159 @@
/*
*
* Definitions for H3600 Handheld Computer
*
* Copyright 2000 Compaq Computer Corporation.
*
* Use consistent with the GNU GPL is permitted,
* provided that this copyright notice is
* preserved in its entirety in all copies and derived works.
*
* COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
* AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
* FITNESS FOR ANY PARTICULAR PURPOSE.
*
* Author: Jamey Hicks.
*
* History:
*
* 2001-10-?? Andrew Christian Added support for iPAQ H3800
*
*/
#ifndef _INCLUDE_H3600_H_
#define _INCLUDE_H3600_H_
#ifndef __ASSEMBLY__
//#include "serial.h"
#endif
/* generalized support for H3xxx series Compaq Pocket PC's */
#define machine_is_h3xxx() (machine_is_h3100() || machine_is_h3600() || machine_is_h3800())
/* Virtual memory regions corresponding to chip selects 2 & 4 (used on sleeves) */
// #define H3600_EGPIO_VIRT 0xf0000000
// #define H3600_BANK_2_VIRT 0xf1000000
// #define H3600_BANK_4_VIRT 0xf3800000
/*
Machine-independent GPIO definitions
--- these are common across all current iPAQ platforms
*/
#define GPIO_H3600_NPOWER_BUTTON GPIO_GPIO (0) /* Also known as the "off button" */
#define GPIO_H3600_PCMCIA_CD1 GPIO_GPIO (10)
#define GPIO_H3600_PCMCIA_IRQ1 GPIO_GPIO (11)
/* UDA1341 L3 Interface */
#define GPIO_H3600_L3_DATA GPIO_GPIO (14)
#define GPIO_H3600_L3_MODE GPIO_GPIO (15)
#define GPIO_H3600_L3_CLOCK GPIO_GPIO (16)
#define GPIO_H3600_PCMCIA_CD0 GPIO_GPIO (17)
#define GPIO_H3600_SYS_CLK GPIO_GPIO (19)
#define GPIO_H3600_PCMCIA_IRQ0 GPIO_GPIO (21)
#define GPIO_H3600_COM_DCD GPIO_GPIO (23)
#define GPIO_H3600_OPT_IRQ GPIO_GPIO (24)
#define GPIO_H3600_COM_CTS GPIO_GPIO (25)
#define GPIO_H3600_COM_RTS GPIO_GPIO (26)
#define IRQ_GPIO_H3600_NPOWER_BUTTON IRQ_GPIO0
#define IRQ_GPIO_H3600_PCMCIA_CD1 IRQ_GPIO10
#define IRQ_GPIO_H3600_PCMCIA_IRQ1 IRQ_GPIO11
#define IRQ_GPIO_H3600_PCMCIA_CD0 IRQ_GPIO17
#define IRQ_GPIO_H3600_PCMCIA_IRQ0 IRQ_GPIO21
#define IRQ_GPIO_H3600_COM_DCD IRQ_GPIO23
#define IRQ_GPIO_H3600_OPT_IRQ IRQ_GPIO24
#define IRQ_GPIO_H3600_COM_CTS IRQ_GPIO25
#ifndef __ASSEMBLY__
enum ipaq_egpio_type {
IPAQ_EGPIO_LCD_ON, /* Power to the LCD panel */
IPAQ_EGPIO_CODEC_NRESET, /* Clear to reset the audio codec (remember to return high) */
IPAQ_EGPIO_AUDIO_ON, /* Audio power */
IPAQ_EGPIO_QMUTE, /* Audio muting */
IPAQ_EGPIO_OPT_NVRAM_ON, /* Non-volatile RAM on extension sleeves (SPI interface) */
IPAQ_EGPIO_OPT_ON, /* Power to extension sleeves */
IPAQ_EGPIO_CARD_RESET, /* Reset PCMCIA cards on extension sleeve (???) */
IPAQ_EGPIO_OPT_RESET, /* Reset option pack (???) */
IPAQ_EGPIO_IR_ON, /* IR sensor/emitter power */
IPAQ_EGPIO_IR_FSEL, /* IR speed selection 1->fast, 0->slow */
IPAQ_EGPIO_RS232_ON, /* Maxim RS232 chip power */
IPAQ_EGPIO_VPP_ON, /* Turn on power to flash programming */
IPAQ_EGPIO_COM_DSR, /* only on H3800 */
};
struct ipaq_model_ops {
const char *generic_name;
void (*control)(enum ipaq_egpio_type, int);
unsigned long (*read)(void);
void (*blank_callback)(int blank);
int (*pm_callback)(int req); /* Primary model callback */
int (*pm_callback_aux)(int req); /* Secondary callback (used by HAL modules) */
};
extern struct ipaq_model_ops ipaq_model_ops;
static __inline__ const char * h3600_generic_name( void ) {
return ipaq_model_ops.generic_name;
}
static __inline__ void assign_h3600_egpio( enum ipaq_egpio_type x, int level ) {
if (ipaq_model_ops.control)
ipaq_model_ops.control(x,level);
else
putstr("no control function\r\n");
}
static __inline__ void clr_h3600_egpio( enum ipaq_egpio_type x ) {
if (ipaq_model_ops.control)
ipaq_model_ops.control(x,0);
else
putstr("no control function\r\n");
}
static __inline__ void set_h3600_egpio( enum ipaq_egpio_type x ) {
if (ipaq_model_ops.control)
ipaq_model_ops.control(x,1);
else
putstr("no control function\r\n");
}
static __inline__ unsigned long read_h3600_egpio( void ) {
if (ipaq_model_ops.read)
return ipaq_model_ops.read();
return 0;
}
static __inline__ int h3600_register_blank_callback( void (*f)(int) ) {
ipaq_model_ops.blank_callback = f;
return 0;
}
static __inline__ void h3600_unregister_blank_callback( void (*f)(int) ) {
ipaq_model_ops.blank_callback = NULL;
}
static __inline__ int h3600_register_pm_callback( int (*f)(int) ) {
ipaq_model_ops.pm_callback_aux = f;
return 0;
}
static __inline__ void h3600_unregister_pm_callback( int (*f)(int) ) {
ipaq_model_ops.pm_callback_aux = NULL;
}
static __inline__ int h3600_power_management( int req ) {
if ( ipaq_model_ops.pm_callback )
return ipaq_model_ops.pm_callback(req);
return 0;
}
#endif /* ASSEMBLY */
#endif /* _INCLUDE_H3600_H_ */

View File

@@ -0,0 +1,611 @@
/*
*
* Definitions for H3600 Handheld Computer
*
* Copyright 2001 Compaq Computer Corporation.
*
* Use consistent with the GNU GPL is permitted,
* provided that this copyright notice is
* preserved in its entirety in all copies and derived works.
*
* COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
* AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
* FITNESS FOR ANY PARTICULAR PURPOSE.
*
* Author: Andrew Christian
*
*/
#ifndef _INCLUDE_H3600_ASIC_H_
#define _INCLUDE_H3600_ASIC_H_
//#include <asm-arm/arch-sa1100/h3600.h>
#include <arch-sa1100/h3600.h>
/*
* GPIO lines that are common across ALL iPAQ models are in "h3600.h"
* This file contains machine-specific definitions for the H3800
*/
#define GPIO_H3800_ASIC GPIO_GPIO (1)
#define GPIO_H3800_AC_IN GPIO_GPIO (12)
#define GPIO_H3800_COM_DSR GPIO_GPIO (13)
#define GPIO_H3800_MMC_INT GPIO_GPIO (18)
#define GPIO_H3800_NOPT_IND GPIO_GPIO (20) /* Almost exactly the same as GPIO_H3600_OPT_DET */
#define GPIO_H3800_OPT_BAT_FAULT GPIO_GPIO (22)
#define GPIO_H3800_CLK_OUT GPIO_GPIO (27)
/****************************************************/
#define IRQ_GPIO_H3800_ASIC IRQ_GPIO1
#define IRQ_GPIO_H3800_AC_IN IRQ_GPIO12
#define IRQ_GPIO_H3800_MMC_INT IRQ_GPIO18
#define IRQ_GPIO_H3800_NOPT_IND IRQ_GPIO20 /* almost same as OPT_DET */
/********************* H3800, ASIC #2 ********************/
#define _H3800_ASIC2_Base (H3600_EGPIO_VIRT)
#define H3800_ASIC2_OFFSET(s,x,y) \
(*((volatile s *) (_H3800_ASIC2_Base + _H3800_ASIC2_ ## x ## _Base + _H3800_ASIC2_ ## x ## _ ## y)))
#define H3800_ASIC2_NOFFSET(s,x,n,y) \
(*((volatile s *) (_H3800_ASIC2_Base + _H3800_ASIC2_ ## x ## _ ## n ## _Base + _H3800_ASIC2_ ## x ## _ ## y)))
#define _H3800_ASIC2_GPIO_Base 0x0000
#define _H3800_ASIC2_GPIO_Direction 0x0000 /* R/W, 16 bits 1:input, 0:output */
#define _H3800_ASIC2_GPIO_InterruptType 0x0004 /* R/W, 12 bits 1:edge, 0:level */
#define _H3800_ASIC2_GPIO_InterruptEdgeType 0x0008 /* R/W, 12 bits 1:rising, 0:falling */
#define _H3800_ASIC2_GPIO_InterruptLevelType 0x000C /* R/W, 12 bits 1:high, 0:low */
#define _H3800_ASIC2_GPIO_InterruptClear 0x0010 /* W, 12 bits */
#define _H3800_ASIC2_GPIO_InterruptFlag 0x0010 /* R, 12 bits - reads int status */
#define _H3800_ASIC2_GPIO_Data 0x0014 /* R/W, 16 bits */
#define _H3800_ASIC2_GPIO_BattFaultOut 0x0018 /* R/W, 16 bit - sets level on batt fault */
#define _H3800_ASIC2_GPIO_InterruptEnable 0x001c /* R/W, 12 bits 1:enable interrupt */
#define _H3800_ASIC2_GPIO_Alternate 0x003c /* R/W, 12+1 bits - set alternate functions */
#define H3800_ASIC2_GPIODIR H3800_ASIC2_OFFSET( u16, GPIO, Direction )
#define H3800_ASIC2_GPIINTTYPE H3800_ASIC2_OFFSET( u16, GPIO, InterruptType )
#define H3800_ASIC2_GPIINTESEL H3800_ASIC2_OFFSET( u16, GPIO, InterruptEdgeType )
#define H3800_ASIC2_GPIINTALSEL H3800_ASIC2_OFFSET( u16, GPIO, InterruptLevelType )
#define H3800_ASIC2_GPIINTCLR H3800_ASIC2_OFFSET( u16, GPIO, InterruptClear )
#define H3800_ASIC2_GPIINTFLAG H3800_ASIC2_OFFSET( u16, GPIO, InterruptFlag )
#define H3800_ASIC2_GPIOPIOD H3800_ASIC2_OFFSET( u16, GPIO, Data )
#define H3800_ASIC2_GPOBFSTAT H3800_ASIC2_OFFSET( u16, GPIO, BattFaultOut )
#define H3800_ASIC2_GPIINTSTAT H3800_ASIC2_OFFSET( u16, GPIO, InterruptEnable )
#define H3800_ASIC2_GPIOALT H3800_ASIC2_OFFSET( u16, GPIO, Alternate )
#define GPIO2_IN_Y1_N (1 << 0) /* Output: Touchscreen Y1 */
#define GPIO2_IN_X0 (1 << 1) /* Output: Touchscreen X0 */
#define GPIO2_IN_Y0 (1 << 2) /* Output: Touchscreen Y0 */
#define GPIO2_IN_X1_N (1 << 3) /* Output: Touchscreen X1 */
#define GPIO2_BT_RST (1 << 4) /* Output: Bluetooth reset */
#define GPIO2_PEN_IRQ (1 << 5) /* Input : Pen down */
#define GPIO2_SD_DETECT (1 << 6) /* Input : SD detect */
#define GPIO2_EAR_IN_N (1 << 7) /* Input : Audio jack plug inserted */
#define GPIO2_OPT_PCM_RESET (1 << 8) /* Output: Card reset (pin 2 on expansion) */
#define GPIO2_OPT_RESET (1 << 9) /* Output: Option pack reset (pin 8 on expansion) */
#define GPIO2_USB_DETECT_N (1 << 10) /* Input : */
#define GPIO2_SD_CON_SLT (1 << 11) /* Input : */
#define GPIO2_OPT_ON (1 << 12) /* Output: Option jacket power */
#define GPIO2_OPT_ON_NVRAM (1 << 13) /* Output: Option jacket NVRAM power */
#define _H3800_ASIC2_KPIO_Base 0x0200
#define _H3800_ASIC2_KPIO_Direction 0x0000 /* R/W, 12 bits 1:input, 0:output */
#define _H3800_ASIC2_KPIO_InterruptType 0x0004 /* R/W, 12 bits 1:edge, 0:level */
#define _H3800_ASIC2_KPIO_InterruptEdgeType 0x0008 /* R/W, 12 bits 1:rising, 0:falling */
#define _H3800_ASIC2_KPIO_InterruptLevelType 0x000C /* R/W, 12 bits 1:high, 0:low */
#define _H3800_ASIC2_KPIO_InterruptClear 0x0010 /* W, 20 bits - 8 special */
#define _H3800_ASIC2_KPIO_InterruptFlag 0x0010 /* R, 20 bits - 8 special - reads int status */
#define _H3800_ASIC2_KPIO_Data 0x0014 /* R/W, 16 bits */
#define _H3800_ASIC2_KPIO_BattFaultOut 0x0018 /* R/W, 16 bit - sets level on batt fault */
#define _H3800_ASIC2_KPIO_InterruptEnable 0x001c /* R/W, 20 bits - 8 special (DON'T TRY TO READ!) */
#define _H3800_ASIC2_KPIO_Alternate 0x003c /* R/W, 6 bits */
#define H3800_ASIC2_KPIODIR H3800_ASIC2_OFFSET( u16, KPIO, Direction )
#define H3800_ASIC2_KPIINTTYPE H3800_ASIC2_OFFSET( u16, KPIO, InterruptType )
#define H3800_ASIC2_KPIINTESEL H3800_ASIC2_OFFSET( u16, KPIO, InterruptEdgeType )
#define H3800_ASIC2_KPIINTALSEL H3800_ASIC2_OFFSET( u16, KPIO, InterruptLevelType )
#define H3800_ASIC2_KPIINTCLR H3800_ASIC2_OFFSET( u32, KPIO, InterruptClear )
#define H3800_ASIC2_KPIINTFLAG H3800_ASIC2_OFFSET( u32, KPIO, InterruptFlag )
#define H3800_ASIC2_KPIOPIOD H3800_ASIC2_OFFSET( u16, KPIO, Data )
#define H3800_ASIC2_KPOBFSTAT H3800_ASIC2_OFFSET( u16, KPIO, BattFaultOut )
#define H3800_ASIC2_KPIINTSTAT H3800_ASIC2_OFFSET( u32, KPIO, InterruptEnable )
#define H3800_ASIC2_KPIOALT H3800_ASIC2_OFFSET( u16, KPIO, Alternate )
#define KPIO_SPI_INT (1 << 16)
#define KPIO_OWM_INT (1 << 17)
#define KPIO_ADC_INT (1 << 18)
#define KPIO_UART_0_INT (1 << 19)
#define KPIO_UART_1_INT (1 << 20)
#define KPIO_TIMER_0_INT (1 << 21)
#define KPIO_TIMER_1_INT (1 << 22)
#define KPIO_TIMER_2_INT (1 << 23)
#define KPIO_RECORD_BTN_N (1 << 0) /* Record button */
#define KPIO_KEY_5W1_N (1 << 1) /* Keypad */
#define KPIO_KEY_5W2_N (1 << 2) /* */
#define KPIO_KEY_5W3_N (1 << 3) /* */
#define KPIO_KEY_5W4_N (1 << 4) /* */
#define KPIO_KEY_5W5_N (1 << 5) /* */
#define KPIO_KEY_LEFT_N (1 << 6) /* */
#define KPIO_KEY_RIGHT_N (1 << 7) /* */
#define KPIO_KEY_AP1_N (1 << 8) /* Old "Calendar" */
#define KPIO_KEY_AP2_N (1 << 9) /* Old "Schedule" */
#define KPIO_KEY_AP3_N (1 << 10) /* Old "Q" */
#define KPIO_KEY_AP4_N (1 << 11) /* Old "Undo" */
#define KPIO_KEY_ALL 0x0fff
/* Alternate KPIO functions (set by default) */
#define KPIO_ALT_KEY_5W1_N (1 << 1) /* Action key */
#define KPIO_ALT_KEY_5W2_N (1 << 2) /* J1 of keypad input */
#define KPIO_ALT_KEY_5W3_N (1 << 3) /* J2 of keypad input */
#define KPIO_ALT_KEY_5W4_N (1 << 4) /* J3 of keypad input */
#define KPIO_ALT_KEY_5W5_N (1 << 5) /* J4 of keypad input */
#define KPIO_ALT_KEY_ALL 0x003e
#define _H3800_ASIC2_SPI_Base 0x0400
#define _H3800_ASIC2_SPI_Control 0x0000 /* R/W 8 bits */
#define _H3800_ASIC2_SPI_Data 0x0004 /* R/W 8 bits */
#define _H3800_ASIC2_SPI_ChipSelectDisabled 0x0008 /* W 8 bits */
#define H3800_ASIC2_SPI_Control H3800_ASIC2_OFFSET( u8, SPI, Control )
#define H3800_ASIC2_SPI_Data H3800_ASIC2_OFFSET( u8, SPI, Data )
#define H3800_ASIC2_SPI_ChipSelectDisabled H3800_ASIC2_OFFSET( u8, SPI, ChipSelectDisabled )
#define SPI_CONTROL_SPR(clk) ((clk) & 0x0f) /* Clock rate: valid from 0000 (8kHz) to 1000 (2.048 MHz) */
#define SPI_CONTROL_SPE (1 << 4) /* SPI Enable (1:enable, 0:disable) */
#define SPI_CONTROL_SPIE (1 << 5) /* SPI Interrupt enable (1:enable, 0:disable) */
#define SPI_CONTROL_SEL (1 << 6) /* Chip select: 1:SPI_CS1 enable, 0:SPI_CS0 enable */
#define SPI_CONTROL_SEL_CS0 (0 << 6) /* Set CS0 low */
#define SPI_CONTROL_SEL_CS1 (1 << 6) /* Set CS0 high */
#define SPI_CONTROL_CPOL (1 << 7) /* Clock polarity, 1:SCK high when idle */
#define _H3800_ASIC2_PWM_0_Base 0x0600
#define _H3800_ASIC2_PWM_1_Base 0x0700
#define _H3800_ASIC2_PWM_TimeBase 0x0000 /* R/W 6 bits */
#define _H3800_ASIC2_PWM_PeriodTime 0x0004 /* R/W 12 bits */
#define _H3800_ASIC2_PWM_DutyTime 0x0008 /* R/W 12 bits */
#define H3800_ASIC2_PWM_0_TimeBase H3800_ASIC2_NOFFSET( u8, PWM, 0, TimeBase )
#define H3800_ASIC2_PWM_0_PeriodTime H3800_ASIC2_NOFFSET( u16, PWM, 0, PeriodTime )
#define H3800_ASIC2_PWM_0_DutyTime H3800_ASIC2_NOFFSET( u16, PWM, 0, DutyTime )
#define H3800_ASIC2_PWM_1_TimeBase H3800_ASIC2_NOFFSET( u8, PWM, 1, TimeBase )
#define H3800_ASIC2_PWM_1_PeriodTime H3800_ASIC2_NOFFSET( u16, PWM, 1, PeriodTime )
#define H3800_ASIC2_PWM_1_DutyTime H3800_ASIC2_NOFFSET( u16, PWM, 1, DutyTime )
#define PWM_TIMEBASE_VALUE(x) ((x)&0xf) /* Low 4 bits sets time base, max = 8 */
#define PWM_TIMEBASE_ENABLE ( 1 << 4 ) /* Enable clock */
#define PWM_TIMEBASE_CLEAR ( 1 << 5 ) /* Clear the PWM */
#define _H3800_ASIC2_LED_0_Base 0x0800
#define _H3800_ASIC2_LED_1_Base 0x0880
#define _H3800_ASIC2_LED_2_Base 0x0900
#define _H3800_ASIC2_LED_TimeBase 0x0000 /* R/W 7 bits */
#define _H3800_ASIC2_LED_PeriodTime 0x0004 /* R/W 12 bits */
#define _H3800_ASIC2_LED_DutyTime 0x0008 /* R/W 12 bits */
#define _H3800_ASIC2_LED_AutoStopCount 0x000c /* R/W 16 bits */
#define H3800_ASIC2_LED_0_TimeBase H3800_ASIC2_NOFFSET( u8, LED, 0, TimeBase )
#define H3800_ASIC2_LED_0_PeriodTime H3800_ASIC2_NOFFSET( u16, LED, 0, PeriodTime )
#define H3800_ASIC2_LED_0_DutyTime H3800_ASIC2_NOFFSET( u16, LED, 0, DutyTime )
#define H3800_ASIC2_LED_0_AutoStopClock H3800_ASIC2_NOFFSET( u16, LED, 0, AutoStopClock )
#define H3800_ASIC2_LED_1_TimeBase H3800_ASIC2_NOFFSET( u8, LED, 1, TimeBase )
#define H3800_ASIC2_LED_1_PeriodTime H3800_ASIC2_NOFFSET( u16, LED, 1, PeriodTime )
#define H3800_ASIC2_LED_1_DutyTime H3800_ASIC2_NOFFSET( u16, LED, 1, DutyTime )
#define H3800_ASIC2_LED_1_AutoStopClock H3800_ASIC2_NOFFSET( u16, LED, 1, AutoStopClock )
#define H3800_ASIC2_LED_2_TimeBase H3800_ASIC2_NOFFSET( u8, LED, 2, TimeBase )
#define H3800_ASIC2_LED_2_PeriodTime H3800_ASIC2_NOFFSET( u16, LED, 2, PeriodTime )
#define H3800_ASIC2_LED_2_DutyTime H3800_ASIC2_NOFFSET( u16, LED, 2, DutyTime )
#define H3800_ASIC2_LED_2_AutoStopClock H3800_ASIC2_NOFFSET( u16, LED, 2, AutoStopClock )
#define LEDTBS_MASK 0x0f /* Low 4 bits sets time base, max = 13 */
#define LEDTBS_BLINK ( 1 << 4 ) /* Enable blinking */
#define LEDTBS_AUTOSTOP ( 1 << 5 )
#define LEDTBS_ALWAYS ( 1 << 6 ) /* Enable blink always */
#define _H3800_ASIC2_UART_0_Base 0x0A00
#define _H3800_ASIC2_UART_1_Base 0x0C00
#define _H3800_ASIC2_UART_Receive 0x0000 /* R 8 bits */
#define _H3800_ASIC2_UART_Transmit 0x0000 /* W 8 bits */
#define _H3800_ASIC2_UART_IntEnable 0x0004 /* R/W 8 bits */
#define _H3800_ASIC2_UART_IntVerify 0x0008 /* R/W 8 bits */
#define _H3800_ASIC2_UART_FIFOControl 0x000c /* R/W 8 bits */
#define _H3800_ASIC2_UART_LineControl 0x0010 /* R/W 8 bits */
#define _H3800_ASIC2_UART_ModemStatus 0x0014 /* R/W 8 bits */
#define _H3800_ASIC2_UART_LineStatus 0x0018 /* R/W 8 bits */
#define _H3800_ASIC2_UART_ScratchPad 0x001c /* R/W 8 bits */
#define _H3800_ASIC2_UART_DivisorLatchL 0x0020 /* R/W 8 bits */
#define _H3800_ASIC2_UART_DivisorLatchH 0x0024 /* R/W 8 bits */
#define H3800_ASIC2_UART_0_Receive H3800_ASIC2_NOFFSET( u8, UART, 0, Receive )
#define H3800_ASIC2_UART_0_Transmit H3800_ASIC2_NOFFSET( u8, UART, 0, Transmit )
#define H3800_ASIC2_UART_0_IntEnable H3800_ASIC2_NOFFSET( u8, UART, 0, IntEnable )
#define H3800_ASIC2_UART_0_IntVerify H3800_ASIC2_NOFFSET( u8, UART, 0, IntVerify )
#define H3800_ASIC2_UART_0_FIFOControl H3800_ASIC2_NOFFSET( u8, UART, 0, FIFOControl )
#define H3800_ASIC2_UART_0_LineControl H3800_ASIC2_NOFFSET( u8, UART, 0, LineControl )
#define H3800_ASIC2_UART_0_ModemStatus H3800_ASIC2_NOFFSET( u8, UART, 0, ModemStatus )
#define H3800_ASIC2_UART_0_LineStatus H3800_ASIC2_NOFFSET( u8, UART, 0, LineStatus )
#define H3800_ASIC2_UART_0_ScratchPad H3800_ASIC2_NOFFSET( u8, UART, 0, ScratchPad )
#define H3800_ASIC2_UART_0_DivisorLatchL H3800_ASIC2_NOFFSET( u8, UART, 0, DivisorLatchL )
#define H3800_ASIC2_UART_0_DivisorLatchH H3800_ASIC2_NOFFSET( u8, UART, 0, DivisorLatchH )
#define H3800_ASIC2_UART_1_Receive H3800_ASIC2_NOFFSET( u8, UART, 1, Receive )
#define H3800_ASIC2_UART_1_Transmit H3800_ASIC2_NOFFSET( u8, UART, 1, Transmit )
#define H3800_ASIC2_UART_1_IntEnable H3800_ASIC2_NOFFSET( u8, UART, 1, IntEnable )
#define H3800_ASIC2_UART_1_IntVerify H3800_ASIC2_NOFFSET( u8, UART, 1, IntVerify )
#define H3800_ASIC2_UART_1_FIFOControl H3800_ASIC2_NOFFSET( u8, UART, 1, FIFOControl )
#define H3800_ASIC2_UART_1_LineControl H3800_ASIC2_NOFFSET( u8, UART, 1, LineControl )
#define H3800_ASIC2_UART_1_ModemStatus H3800_ASIC2_NOFFSET( u8, UART, 1, ModemStatus )
#define H3800_ASIC2_UART_1_LineStatus H3800_ASIC2_NOFFSET( u8, UART, 1, LineStatus )
#define H3800_ASIC2_UART_1_ScratchPad H3800_ASIC2_NOFFSET( u8, UART, 1, ScratchPad )
#define H3800_ASIC2_UART_1_DivisorLatchL H3800_ASIC2_NOFFSET( u8, UART, 1, DivisorLatchL )
#define H3800_ASIC2_UART_1_DivisorLatchH H3800_ASIC2_NOFFSET( u8, UART, 1, DivisorLatchH )
#define _H3800_ASIC2_TIMER_Base 0x0E00 /* 8254-compatible timers */
#define _H3800_ASIC2_TIMER_Counter0 0x0000 /* R/W 8 bits */
#define _H3800_ASIC2_TIMER_Counter1 0x0004 /* R/W 8 bits */
#define _H3800_ASIC2_TIMER_Counter2 0x0008 /* R/W 8 bits */
#define _H3800_ASIC2_TIMER_Control 0x000a /* W 8 bits */
#define _H3800_ASIC2_TIMER_Command 0x0010 /* R/W 8 bits */
#define H3800_ASIC2_TIMER_Counter0 H3800_ASIC2_OFFSET( u8, TIMER, Counter0 )
#define H3800_ASIC2_TIMER_Counter1 H3800_ASIC2_OFFSET( u8, TIMER, Counter1 )
#define H3800_ASIC2_TIMER_Counter2 H3800_ASIC2_OFFSET( u8, TIMER, Counter2 )
#define H3800_ASIC2_TIMER_Control H3800_ASIC2_OFFSET( u8, TIMER, Control )
#define H3800_ASIC2_TIMER_Command H3800_ASIC2_OFFSET( u8, TIMER, Command )
/* These defines are likely incorrect - in particular, TIMER_CNTL_MODE_4 might
need to be 0x04 */
#define TIMER_CNTL_SELECT(x) (((x)&0x3)<<6) /* Select counter */
#define TIMER_CNTL_RW(x) (((x)&0x3)<<4) /* Read/write mode */
#define TIMER_CNTL_RW_LATCH TIMER_CNTL_RW(0)
#define TIMER_CNTL_RW_LSB_MSB TIMER_CNTL_RW(3) /* LSB first, then MSB */
#define TIMER_CNTL_MODE(x) (((x)&0x7)<<1) /* Mode */
#define TIMER_CNTL_MODE_0 TIMER_CNTL_MODE(0) /* Supported for 0 & 1 */
#define TIMER_CNTL_MODE_2 TIMER_CNTL_MODE(2) /* Supported for all timers */
#define TIMER_CNTL_MODE_4 TIMER_CNTL_MODE(4) /* Supported for all timers */
#define TIMER_CNTL_BCD ( 1 << 0 ) /* 1=Use BCD counter, 4 decades */
#define TIMER_CMD_GAT_0 ( 1 << 0 ) /* Gate enable, counter 0 */
#define TIMER_CMD_GAT_1 ( 1 << 1 ) /* Gate enable, counter 1 */
#define TIMER_CMD_GAT_2 ( 1 << 2 ) /* Gate enable, counter 2 */
#define TIMER_CMD_CLK_0 ( 1 << 3 ) /* Clock enable, counter 0 */
#define TIMER_CMD_CLK_1 ( 1 << 4 ) /* Clock enable, counter 1 */
#define TIMER_CMD_CLK_2 ( 1 << 5 ) /* Clock enable, counter 2 */
#define TIMER_CMD_MODE_0 ( 1 << 6 ) /* Mode 0 enable, counter 0 */
#define TIMER_CMD_MODE_1 ( 1 << 7 ) /* Mode 0 enable, counter 1 */
#define _H3800_ASIC2_CLOCK_Base 0x1000
#define _H3800_ASIC2_CLOCK_Enable 0x0000 /* R/W 18 bits */
#define H3800_ASIC2_CLOCK_Enable H3800_ASIC2_OFFSET( u32, CLOCK, Enable )
#define ASIC2_CLOCK_AUDIO_1 0x01 /* Enable 4.1 MHz clock for 8Khz and 4khz sample rate */
#define ASIC2_CLOCK_AUDIO_2 0x02 /* Enable 12.3 MHz clock for 48Khz and 32khz sample rate */
#define ASIC2_CLOCK_AUDIO_3 0x04 /* Enable 5.6 MHz clock for 11 kHZ sample rate */
#define ASIC2_CLOCK_AUDIO_4 0x08 /* Enable 11.289 MHz clock for 44 and 22 kHz sample rate */
#define ASIC2_CLOCK_AUDIO_MASK 0x0f /* Bottom four bits are for audio */
#define ASIC2_CLOCK_ADC ( 1 << 4 ) /* 1.024 MHz clock to ADC (CX4) */
#define ASIC2_CLOCK_SPI ( 1 << 5 ) /* 4.096 MHz clock to SPI (CX5) */
#define ASIC2_CLOCK_OWM ( 1 << 6 ) /* 4.096 MHz clock to OWM (CX6) */
#define ASIC2_CLOCK_PWM ( 1 << 7 ) /* 2.048 MHz clock to PWM (CX7) */
#define ASIC2_CLOCK_UART_1 ( 1 << 8 ) /* 24.576 MHz clock to UART1 (turn off bit 16) (CX8) */
#define ASIC2_CLOCK_UART_0 ( 1 << 9 ) /* 24.576 MHz clock to UART0 (turn off bit 17) (CX9) */
#define ASIC2_CLOCK_SD_1 ( 1 << 10 ) /* 16.934 MHz to SD */
#define ASIC2_CLOCK_SD_2 ( 2 << 10 ) /* 24.576 MHz to SD */
#define ASIC2_CLOCK_SD_3 ( 3 << 10 ) /* 33.869 MHz to SD */
#define ASIC2_CLOCK_SD_4 ( 4 << 10 ) /* 49.152 MHz to SD */
#define ASIC2_CLOCK_SD_MASK 0x1c00 /* Bits 10 through 12 are for SD */
#define ASIC2_CLOCK_EX0 ( 1 << 13 ) /* Enable 32.768 kHz (LED,Timer,Interrupt) */
#define ASIC2_CLOCK_EX1 ( 1 << 14 ) /* Enable 24.576 MHz (ADC,PCM,SPI,PWM,UART,SD,Audio) */
#define ASIC2_CLOCK_EX2 ( 1 << 15 ) /* Enable 33.869 MHz (SD,Audio) */
#define ASIC2_CLOCK_SLOW_UART_1 ( 1 << 16 ) /* Enable 3.686 MHz to UART1 (turn off bit 8) */
#define ASIC2_CLOCK_SLOW_UART_0 ( 1 << 17 ) /* Enable 3.686 MHz to UART0 (turn off bit 9) */
#define _H3800_ASIC2_ADC_Base 0x1200
#define _H3800_ASIC2_ADC_Multiplexer 0x0000 /* R/W 4 bits - low 3 bits set channel */
#define _H3800_ASIC2_ADC_ControlStatus 0x0004 /* R/W 8 bits */
#define _H3800_ASIC2_ADC_Data 0x0008 /* R 10 bits */
#define H3800_ASIC2_ADMUX H3800_ASIC2_OFFSET( u32, ADC, Multiplexer )
#define H3800_ASIC2_ADCSR H3800_ASIC2_OFFSET( u8, ADC, ControlStatus )
#define H3800_ASIC2_ADCDR H3800_ASIC2_OFFSET( u16, ADC, Data )
#define ASIC2_ADMUX(x) ((x)&0x07) /* Low 3 bits sets channel. max = 4 */
#define ASIC2_ADMUX_MASK 0x07
#define ASIC2_ADMUX_0_LIGHTSENSOR ASIC2_ADMUX(0)
#define ASIC2_ADMUX_1_IMIN ASIC2_ADMUX(1)
#define ASIC2_ADMUX_2_VS_MBAT ASIC2_ADMUX(2)
#define ASIC2_ADMUX_3_TP_X0 ASIC2_ADMUX(3) /* Touchpanel X0 */
#define ASIC2_ADMUX_4_TP_Y1 ASIC2_ADMUX(4) /* Touchpanel Y1 */
#define ASIC2_ADMUX_CLKEN ( 1 << 3 ) /* Enable clock */
#define ASIC2_ADCSR_ADPS(x) ((x)&0x0f) /* Low 4 bits sets prescale, max = 8 */
#define ASIC2_ADCSR_FREE_RUN ( 1 << 4 )
#define ASIC2_ADCSR_INT_ENABLE ( 1 << 5 )
#define ASIC2_ADCSR_START ( 1 << 6 ) /* Set to start conversion. Goes to 0 when done */
#define ASIC2_ADCSR_ENABLE ( 1 << 7 ) /* 1:power up ADC, 0:power down */
#define _H3800_ASIC2_INTR_Base 0x1600
#define _H3800_ASIC2_INTR_MaskAndFlag 0x0000 /* R/(W) 8bits */
#define _H3800_ASIC2_INTR_ClockPrescale 0x0004 /* R/(W) 5bits */
#define _H3800_ASIC2_INTR_TimerSet 0x0008 /* R/(W) 8bits */
#define H3800_ASIC2_INTR_MaskAndFlag H3800_ASIC2_OFFSET( u8, INTR, MaskAndFlag )
#define H3800_ASIC2_INTR_ClockPrescale H3800_ASIC2_OFFSET( u8, INTR, ClockPrescale )
#define H3800_ASIC2_INTR_TimerSet H3800_ASIC2_OFFSET( u16, INTR, TimerSet )
#define ASIC2_INTMASK_GLOBAL ( 1 << 0 ) /* Global interrupt mask */
//#define ASIC2_INTR_POWER_ON_RESET ( 1 << 1 ) /* 01: Power on reset (bits 1 & 2 ) */
//#define ASIC2_INTR_EXTERNAL_RESET ( 2 << 1 ) /* 10: External reset (bits 1 & 2 ) */
#define ASIC2_INTMASK_UART_0 ( 1 << 4 )
#define ASIC2_INTMASK_UART_1 ( 1 << 5 )
#define ASIC2_INTMASK_TIMER ( 1 << 6 )
#define ASIC2_INTMASK_OWM ( 1 << 7 )
#define ASIC2_INTCPS_CPS(x) ((x)&0x0f) /* 4 bits, max 14 */
#define ASIC2_INTCPS_SET ( 1 << 4 ) /* Time base enable */
#define _H3800_ASIC2_OWM_Base 0x1800
#define _H3800_ASIC2_OWM_Command 0x0000 /* R/W 4 bits command register */
#define _H3800_ASIC2_OWM_Data 0x0004 /* R/W 8 bits, transmit / receive buffer */
#define _H3800_ASIC2_OWM_Interrupt 0x0008 /* R/W Command register */
#define _H3800_ASIC2_OWM_InterruptEnable 0x000c /* R/W Command register */
#define _H3800_ASIC2_OWM_ClockDivisor 0x0010 /* R/W 5 bits of divisor and pre-scale */
#define H3800_ASIC2_OWM_Command H3800_ASIC2_OFFSET( u8, OWM, Command )
#define H3800_ASIC2_OWM_Data H3800_ASIC2_OFFSET( u8, OWM, Data )
#define H3800_ASIC2_OWM_Interrupt H3800_ASIC2_OFFSET( u8, OWM, Interrupt )
#define H3800_ASIC2_OWM_InterruptEnable H3800_ASIC2_OFFSET( u8, OWM, InterruptEnable )
#define H3800_ASIC2_OWM_ClockDivisor H3800_ASIC2_OFFSET( u8, OWM, ClockDivisor )
#define OWM_CMD_ONE_WIRE_RESET ( 1 << 0 ) /* Set to force reset on 1-wire bus */
#define OWM_CMD_SRA ( 1 << 1 ) /* Set to switch to Search ROM accelerator mode */
#define OWM_CMD_DQ_OUTPUT ( 1 << 2 ) /* Write only - forces bus low */
#define OWM_CMD_DQ_INPUT ( 1 << 3 ) /* Read only - reflects state of bus */
#define OWM_INT_PD ( 1 << 0 ) /* Presence detect */
#define OWM_INT_PDR ( 1 << 1 ) /* Presence detect result */
#define OWM_INT_TBE ( 1 << 2 ) /* Transmit buffer empty */
#define OWM_INT_TEMT ( 1 << 3 ) /* Transmit shift register empty */
#define OWM_INT_RBF ( 1 << 4 ) /* Receive buffer full */
#define OWM_INTEN_EPD ( 1 << 0 ) /* Enable presence detect interrupt */
#define OWM_INTEN_IAS ( 1 << 1 ) /* INTR active state */
#define OWM_INTEN_ETBE ( 1 << 2 ) /* Enable transmit buffer empty interrupt */
#define OWM_INTEN_ETMT ( 1 << 3 ) /* Enable transmit shift register empty interrupt */
#define OWM_INTEN_ERBF ( 1 << 4 ) /* Enable receive buffer full interrupt */
#define _H3800_ASIC2_FlashCtl_Base 0x1A00
/****************************************************/
/* H3800, ASIC #1
* This ASIC is accesed through ASIC #2, and
* mapped into the 1c00 - 1f00 region
*/
#define H3800_ASIC1_OFFSET(s,x,y) \
(*((volatile s *) (_H3800_ASIC2_Base + _H3800_ASIC1_ ## x ## _Base + (_H3800_ASIC1_ ## x ## _ ## y))))
#define _H3800_ASIC1_MMC_Base 0x1c00
#define _H3800_ASIC1_MMC_StartStopClock 0x00 /* R/W 8bit */
#define _H3800_ASIC1_MMC_Status 0x04 /* R See below, default 0x0040 */
#define _H3800_ASIC1_MMC_ClockRate 0x08 /* R/W 8bit, low 3 bits are clock divisor */
#define _H3800_ASIC1_MMC_SPIRegister 0x10 /* R/W 8bit, see below */
#define _H3800_ASIC1_MMC_CmdDataCont 0x14 /* R/W 8bit, write to start MMC adapter */
#define _H3800_ASIC1_MMC_ResponseTimeout 0x18 /* R/W 8bit, clocks before response timeout */
#define _H3800_ASIC1_MMC_ReadTimeout 0x1c /* R/W 16bit, clocks before received data timeout */
#define _H3800_ASIC1_MMC_BlockLength 0x20 /* R/W 10bit */
#define _H3800_ASIC1_MMC_NumOfBlocks 0x24 /* R/W 16bit, in block mode, number of blocks */
#define _H3800_ASIC1_MMC_InterruptMask 0x34 /* R/W 8bit */
#define _H3800_ASIC1_MMC_CommandNumber 0x38 /* R/W 6 bits */
#define _H3800_ASIC1_MMC_ArgumentH 0x3c /* R/W 16 bits */
#define _H3800_ASIC1_MMC_ArgumentL 0x40 /* R/W 16 bits */
#define _H3800_ASIC1_MMC_ResFifo 0x44 /* R 8 x 16 bits - contains response FIFO */
#define _H3800_ASIC1_MMC_BufferPartFull 0x50 /* R/W 8 bits */
#define H3800_ASIC1_MMC_StartStopClock H3800_ASIC1_OFFSET( u8, MMC, StartStopClock )
#define H3800_ASIC1_MMC_Status H3800_ASIC1_OFFSET( u16, MMC, Status )
#define H3800_ASIC1_MMC_ClockRate H3800_ASIC1_OFFSET( u8, MMC, ClockRate )
#define H3800_ASIC1_MMC_SPIRegister H3800_ASIC1_OFFSET( u8, MMC, SPIRegister )
#define H3800_ASIC1_MMC_CmdDataCont H3800_ASIC1_OFFSET( u8, MMC, CmdDataCont )
#define H3800_ASIC1_MMC_ResponseTimeout H3800_ASIC1_OFFSET( u8, MMC, ResponseTimeout )
#define H3800_ASIC1_MMC_ReadTimeout H3800_ASIC1_OFFSET( u16, MMC, ReadTimeout )
#define H3800_ASIC1_MMC_BlockLength H3800_ASIC1_OFFSET( u16, MMC, BlockLength )
#define H3800_ASIC1_MMC_NumOfBlocks H3800_ASIC1_OFFSET( u16, MMC, NumOfBlocks )
#define H3800_ASIC1_MMC_InterruptMask H3800_ASIC1_OFFSET( u8, MMC, InterruptMask )
#define H3800_ASIC1_MMC_CommandNumber H3800_ASIC1_OFFSET( u8, MMC, CommandNumber )
#define H3800_ASIC1_MMC_ArgumentH H3800_ASIC1_OFFSET( u16, MMC, ArgumentH )
#define H3800_ASIC1_MMC_ArgumentL H3800_ASIC1_OFFSET( u16, MMC, ArgumentL )
#define H3800_ASIC1_MMC_ResFifo H3800_ASIC1_OFFSET( u16, MMC, ResFifo )
#define H3800_ASIC1_MMC_BufferPartFull H3800_ASIC1_OFFSET( u8, MMC, BufferPartFull )
#define H3800_ASIC1_MMC_STOP_CLOCK (1 << 0) /* Write to "StartStopClock" register */
#define H3800_ASIC1_MMC_START_CLOCK (1 << 1)
#define H3800_ASIC1_MMC_STATUS_READ_TIMEOUT (1 << 0)
#define H3800_ASIC1_MMC_STATUS_RESPONSE_TIMEOUT (1 << 1)
#define H3800_ASIC1_MMC_STATUS_CRC_WRITE_ERROR (1 << 2)
#define H3800_ASIC1_MMC_STATUS_CRC_READ_ERROR (1 << 3)
#define H3800_ASIC1_MMC_STATUS_SPI_READ_ERROR (1 << 4) /* SPI data token error received */
#define H3800_ASIC1_MMC_STATUS_CRC_RESPONSE_ERROR (1 << 5)
#define H3800_ASIC1_MMC_STATUS_FIFO_EMPTY (1 << 6)
#define H3800_ASIC1_MMC_STATUS_FIFO_FULL (1 << 7)
#define H3800_ASIC1_MMC_STATUS_CLOCK_ENABLE (1 << 8) /* MultiMediaCard clock stopped */
#define H3800_ASIC1_MMC_STATUS_DATA_TRANSFER_DONE (1 << 11) /* Write operation, indicates transfer finished */
#define H3800_ASIC1_MMC_STATUS_END_PROGRAM (1 << 12) /* End write and read operations */
#define H3800_ASIC1_MMC_STATUS_END_COMMAND_RESPONSE (1 << 13) /* End command response */
#define H3800_ASIC1_MMC_SPI_REG_SPI_ENABLE (1 << 0) /* Enables SPI mode */
#define H3800_ASIC1_MMC_SPI_REG_CRC_ON (1 << 1) /* 1:turn on CRC */
#define H3800_ASIC1_MMC_SPI_REG_SPI_CS_ENABLE (1 << 2) /* 1:turn on SPI CS */
#define H3800_ASIC1_MMC_SPI_REG_CS_ADDRESS_MASK 0x38 /* Bits 3,4,5 are the SPI CS relative address */
#define H3800_ASIC1_MMC_CMD_DATA_CONT_FORMAT_NO_RESPONSE 0x00
#define H3800_ASIC1_MMC_CMD_DATA_CONT_FORMAT_R1 0x01
#define H3800_ASIC1_MMC_CMD_DATA_CONT_FORMAT_R2 0x02
#define H3800_ASIC1_MMC_CMD_DATA_CONT_FORMAT_R3 0x03
#define H3800_ASIC1_MMC_CMD_DATA_CONT_DATA_ENABLE (1 << 2) /* This command contains a data transfer */
#define H3800_ASIC1_MMC_CMD_DATA_CONT_WRITE (1 << 3) /* This data transfer is a write */
#define H3800_ASIC1_MMC_CMD_DATA_CONT_STREAM_MODE (1 << 4) /* This data transfer is in stream mode */
#define H3800_ASIC1_MMC_CMD_DATA_CONT_BUSY_BIT (1 << 5) /* Busy signal expected after current cmd */
#define H3800_ASIC1_MMC_CMD_DATA_CONT_INITIALIZE (1 << 6) /* Enables the 80 bits for initializing card */
#define H3800_ASIC1_MMC_INT_MASK_DATA_TRANSFER_DONE (1 << 0)
#define H3800_ASIC1_MMC_INT_MASK_PROGRAM_DONE (1 << 1)
#define H3800_ASIC1_MMC_INT_MASK_END_COMMAND_RESPONSE (1 << 2)
#define H3800_ASIC1_MMC_INT_MASK_BUFFER_READY (1 << 3)
#define H3800_ASIC1_MMC_BUFFER_PART_FULL (1 << 0)
/********* GPIO **********/
#define _H3800_ASIC1_GPIO_Base 0x1e00
#define _H3800_ASIC1_GPIO_Mask 0x60 /* R/W 0:don't mask, 1:mask interrupt */
#define _H3800_ASIC1_GPIO_Direction 0x64 /* R/W 0:input, 1:output */
#define _H3800_ASIC1_GPIO_Out 0x68 /* R/W 0:output low, 1:output high */
#define _H3800_ASIC1_GPIO_TriggerType 0x6c /* R/W 0:level, 1:edge */
#define _H3800_ASIC1_GPIO_EdgeTrigger 0x70 /* R/W 0:falling, 1:rising */
#define _H3800_ASIC1_GPIO_LevelTrigger 0x74 /* R/W 0:low, 1:high level detect */
#define _H3800_ASIC1_GPIO_LevelStatus 0x78 /* R/W 0:none, 1:detect */
#define _H3800_ASIC1_GPIO_EdgeStatus 0x7c /* R/W 0:none, 1:detect */
#define _H3800_ASIC1_GPIO_State 0x80 /* R See masks below (default 0) */
#define _H3800_ASIC1_GPIO_Reset 0x84 /* R/W See masks below (default 0x04) */
#define _H3800_ASIC1_GPIO_SleepMask 0x88 /* R/W 0:don't mask, 1:mask trigger in sleep mode */
#define _H3800_ASIC1_GPIO_SleepDir 0x8c /* R/W direction 0:input, 1:ouput in sleep mode */
#define _H3800_ASIC1_GPIO_SleepOut 0x90 /* R/W level 0:low, 1:high in sleep mode */
#define _H3800_ASIC1_GPIO_Status 0x94 /* R Pin status */
#define _H3800_ASIC1_GPIO_BattFaultDir 0x98 /* R/W direction 0:input, 1:output in batt_fault */
#define _H3800_ASIC1_GPIO_BattFaultOut 0x9c /* R/W level 0:low, 1:high in batt_fault */
#define H3800_ASIC1_GPIO_MASK H3800_ASIC1_OFFSET( u16, GPIO, Mask )
#define H3800_ASIC1_GPIO_DIR H3800_ASIC1_OFFSET( u16, GPIO, Direction )
#define H3800_ASIC1_GPIO_OUT H3800_ASIC1_OFFSET( u16, GPIO, Out )
#define H3800_ASIC1_GPIO_LEVELTRI H3800_ASIC1_OFFSET( u16, GPIO, TriggerType )
#define H3800_ASIC1_GPIO_RISING H3800_ASIC1_OFFSET( u16, GPIO, EdgeTrigger )
#define H3800_ASIC1_GPIO_LEVEL H3800_ASIC1_OFFSET( u16, GPIO, LevelTrigger )
#define H3800_ASIC1_GPIO_LEVEL_STATUS H3800_ASIC1_OFFSET( u16, GPIO, LevelStatus )
#define H3800_ASIC1_GPIO_EDGE_STATUS H3800_ASIC1_OFFSET( u16, GPIO, EdgeStatus )
#define H3800_ASIC1_GPIO_STATE H3800_ASIC1_OFFSET( u8, GPIO, State )
#define H3800_ASIC1_GPIO_RESET H3800_ASIC1_OFFSET( u8, GPIO, Reset )
#define H3800_ASIC1_GPIO_SLEEP_MASK H3800_ASIC1_OFFSET( u16, GPIO, SleepMask )
#define H3800_ASIC1_GPIO_SLEEP_DIR H3800_ASIC1_OFFSET( u16, GPIO, SleepDir )
#define H3800_ASIC1_GPIO_SLEEP_OUT H3800_ASIC1_OFFSET( u16, GPIO, SleepOut )
#define H3800_ASIC1_GPIO_STATUS H3800_ASIC1_OFFSET( u16, GPIO, Status )
#define H3800_ASIC1_GPIO_BATT_FAULT_DIR H3800_ASIC1_OFFSET( u16, GPIO, BattFaultDir )
#define H3800_ASIC1_GPIO_BATT_FAULT_OUT H3800_ASIC1_OFFSET( u16, GPIO, BattFaultOut )
#define H3800_ASIC1_GPIO_STATE_MASK (1 << 0)
#define H3800_ASIC1_GPIO_STATE_DIRECTION (1 << 1)
#define H3800_ASIC1_GPIO_STATE_OUT (1 << 2)
#define H3800_ASIC1_GPIO_STATE_TRIGGER_TYPE (1 << 3)
#define H3800_ASIC1_GPIO_STATE_EDGE_TRIGGER (1 << 4)
#define H3800_ASIC1_GPIO_STATE_LEVEL_TRIGGER (1 << 5)
#define H3800_ASIC1_GPIO_RESET_SOFTWARE (1 << 0)
#define H3800_ASIC1_GPIO_RESET_AUTO_SLEEP (1 << 1)
#define H3800_ASIC1_GPIO_RESET_FIRST_PWR_ON (1 << 2)
/* These are all outputs */
#define GPIO1_IR_ON_N (1 << 0) /* Apply power to the IR Module */
#define GPIO1_SD_PWR_ON (1 << 1) /* Secure Digital power on */
#define GPIO1_RS232_ON (1 << 2) /* Turn on power to the RS232 chip ? */
#define GPIO1_PULSE_GEN (1 << 3) /* Goes to speaker / earphone */
#define GPIO1_CH_TIMER (1 << 4) /* Charger */
#define GPIO1_LCD_5V_ON (1 << 5) /* Enables LCD_5V */
#define GPIO1_LCD_ON (1 << 6) /* Enables LCD_3V */
#define GPIO1_LCD_PCI (1 << 7) /* Connects to PDWN on LCD controller */
#define GPIO1_VGH_ON (1 << 8) /* Drives VGH on the LCD (+9??) */
#define GPIO1_VGL_ON (1 << 9) /* Drivers VGL on the LCD (-6??) */
#define GPIO1_FL_PWR_ON (1 << 10) /* Frontlight power on */
#define GPIO1_BT_PWR_ON (1 << 11) /* Bluetooth power on */
#define GPIO1_SPK_ON (1 << 12) /* Built-in speaker on */
#define GPIO1_EAR_ON_N (1 << 13) /* Headphone jack on */
#define GPIO1_AUD_PWR_ON (1 << 14) /* All audio power */
/* Write enable for the flash */
#define _H3800_ASIC2_FlashWP_Base 0x1f00
#define _H3800_ASIC2_FlashWP_VPP_ON 0x00 /* R 1: write, 0: protect */
#define H3800_ASIC2_FlashWP_VPP_ON H3800_ASIC2_OFFSET( u8, FlashWP, VPP_ON )
/****************************************************/
/* H3900, ASIC #3, replaces ASIC #1
* This ASIC is at CS5# + 0x00000000
*/
#ifdef CONFIG_MACH_H3900
#define H3900_ASIC3_OFFSET(s,x,y) \
(*((volatile s *) (H3900_ASIC3_VIRT + _H3900_ASIC3_ ## x ## _Base + (_H3900_ASIC3_ ## x ## _ ## y))))
#define _H3900_ASIC3_GPIO_A_Base 0x0000
#define _H3900_ASIC3_GPIO_B_Base 0x0100
#define _H3900_ASIC3_GPIO_B_Mask 0x00 /* R/W 0:don't mask, 1:mask interrupt */
#define _H3900_ASIC3_GPIO_B_Direction 0x04 /* R/W 0:input, 1:output */
#define _H3900_ASIC3_GPIO_B_Out 0x08 /* R/W 0:output low, 1:output high */
#define _H3900_ASIC3_GPIO_B_TriggerType 0x0c /* R/W 0:level, 1:edge */
#define _H3900_ASIC3_GPIO_B_EdgeTrigger 0x10 /* R/W 0:falling, 1:rising */
#define _H3900_ASIC3_GPIO_B_LevelTrigger 0x14 /* R/W 0:low, 1:high level detect */
#define _H3900_ASIC3_GPIO_B_SleepMask 0x18 /* R/W 0:don't mask, 1:mask trigger in sleep mode */
#define _H3900_ASIC3_GPIO_B_SleepOut 0x1c /* R/W level 0:low, 1:high in sleep mode */
#define _H3900_ASIC3_GPIO_B_BattFaultOut 0x20 /* R/W level 0:low, 1:high in batt_fault */
#define _H3900_ASIC3_GPIO_B_IntStatus 0x24 /* R/W 0:none, 1:detect */
/* no 0x28 */
#define _H3900_ASIC3_GPIO_B_SleepConf 0x2c /* R/W bit 1: autosleep 0: disable gposlpout in normal mode, enable gposlpout in sleep mode */
#define _H3900_ASIC3_GPIO_B_Status 0x30 /* R Pin status */
#define H3900_ASIC3_GPIO_B_MASK H3900_ASIC3_OFFSET( u16, GPIO_B, Mask )
#define H3900_ASIC3_GPIO_B_DIR H3900_ASIC3_OFFSET( u16, GPIO_B, Direction )
#define H3900_ASIC3_GPIO_B_OUT H3900_ASIC3_OFFSET( u16, GPIO_B, Out )
#define H3900_ASIC3_GPIO_B_LEVELTRI H3900_ASIC3_OFFSET( u16, GPIO_B, TriggerType )
#define H3900_ASIC3_GPIO_B_RISING H3900_ASIC3_OFFSET( u16, GPIO_B, EdgeTrigger )
#define H3900_ASIC3_GPIO_B_LEVEL H3900_ASIC3_OFFSET( u16, GPIO_B, LevelTrigger )
#define H3900_ASIC3_GPIO_B_SLEEP_MASK H3900_ASIC3_OFFSET( u16, GPIO_B, SleepMask )
#define H3900_ASIC3_GPIO_B_SLEEP_OUT H3900_ASIC3_OFFSET( u16, GPIO_B, SleepOut )
#define H3900_ASIC3_GPIO_B_BATT_FAULT_OUT H3900_ASIC3_OFFSET( u16, GPIO_B, BattFaultOut )
#define H3900_ASIC3_GPIO_B_INT_STATUS H3900_ASIC3_OFFSET( u16, GPIO_B, IntStatus )
#define H3900_ASIC3_GPIO_B_SLEEP_CONF H3900_ASIC3_OFFSET( u16, GPIO_B, SleepConf )
#define H3900_ASIC3_GPIO_B_STATUS H3900_ASIC3_OFFSET( u16, GPIO_B, Status )
/* these gpio's are on GPIO_B */
#define GPIO3_IR_ON_N (1 << 0) /* Apply power to the IR Module */
#define GPIO3_LCD_9V_ON (1 << 1)
#define GPIO3_RS232_ON (1 << 2) /* Turn on power to the RS232 chip ? */
#define GPIO3_LCD_NV_ON (1 << 3)
#define GPIO3_CH_TIMER (1 << 4) /* Charger */
#define GPIO3_LCD_5V_ON (1 << 5) /* Enables LCD_5V */
#define GPIO3_LCD_ON (1 << 6) /* Enables LCD_3V */
#define GPIO3_LCD_PCI (1 << 7) /* Connects to PDWN on LCD controller */
// 8 is not connected
#define GPIO3_CIR_CTL_PWR_ON (1 << 9)
#define GPIO3_AUD_RESET (1 << 10)
#define GPIO3_BT_PWR_ON (1 << 11) /* Bluetooth power on */
#define GPIO3_SPK_ON (1 << 12) /* Built-in speaker on */
#define GPIO3_FL_PWR_ON (1 << 13) /* Frontlight power on */
#define GPIO3_AUD_PWR_ON (1 << 14) /* All audio power */
#define _H3900_ASIC3_GPIO_B_Base 0x0100
#define _H3900_ASIC3_GPIO_C_Base 0x0200
#define _H3900_ASIC3_GPIO_D_Base 0x0300
#define _H3900_ASIC3_CLOCK_Base 0x0A00
#define _H3900_ASIC3_INTR_Base 0x0B00
#define _H3900_ASIC3_SDHWCTRL_Base 0x0E00
#define _H3900_ASIC3_HWPROTECT_Base 0x1000
#define _H3900_ASIC3_EXTCF_Base 0x1100
#define ASIC3GPIO_INIT_DIR 0xFFFF // initial status, sleep direction
#define ASIC3GPIO_INIT_OUT 0x8200 // Strain 2001.12.15
#define ASIC3GPIO_BATFALT_OUT 0x8000
#define ASIC3GPIO_SLEEP_OUT 0x8000
#define ASIC3CLOCK_INIT 0x0
#endif
#endif /* _INCLUDE_H3600_GPIO_H_ */

View File

@@ -0,0 +1,17 @@
#define EGPIO_IPAQ_VPEN (1 << 0) /* enables erasing and programming flash. active high. */
#define EGPIO_IPAQ_CARD_RESET (1 << 1) /* reset the attached pcmcia/compactflash card. active high. */
#define EGPIO_IPAQ_OPT_RESET (1 << 2) /* reset the attached option pack. active high. */
#define EGPIO_IPAQ_CODEC_nRESET (1 << 3) /* reset the onboard UDA1341. active low. */
#define EGPIO_IPAQ_OPT_NVRAM_ON (1 << 4) /* apply power to optionpack nvram, active high. */
#define EGPIO_IPAQ_OPT_ON (1 << 5) /* full power to option pack. active high. */
#define EGPIO_IPAQ_LCD_ON (1 << 6) /* enable 3.3V to LCD. active high. */
#define EGPIO_IPAQ_RS232_ON (1 << 7) /* UART3 transceiver force on. Active high. */
#define EGPIO_IPAQ_LCD_PCI (1 << 8) /* LCD control IC enable. active high. */
#define EGPIO_IPAQ_IR_ON (1 << 9) /* apply power to IR module. active high. */
#define EGPIO_IPAQ_AUD_AMP_ON (1 << 10) /* apply power to audio power amp. active high. */
#define EGPIO_IPAQ_AUD_PWR_ON (1 << 11) /* apply poewr to reset of audio circuit. active high. */
#define EGPIO_IPAQ_QMUTE (1 << 12) /* mute control for onboard UDA1341. active high. */
#define EGPIO_IPAQ_IR_FSEL (1 << 13) /* IR speed select: 1->fast, 0->slow */
#define EGPIO_IPAQ_LCD_5V_ON (1 << 14) /* enable 5V to LCD. active high. */
#define EGPIO_IPAQ_LVDD_ON (1 << 15) /* enable 9V and -6.5V to LCD. */

View File

@@ -0,0 +1,334 @@
#ifndef _SA1100_LCD_H_
#define _SA1100_LCD_H_
/*
* ganked from:
* FILE SA-1100.h
*
* Version 1.2
* Author Copyright (c) Marc A. Viredaz, 1998
* DEC Western Research Laboratory, Palo Alto, CA
* Date January 1998 (April 1997)
* System StrongARM SA-1100
* Language C or ARM Assembly
* Purpose Definition of constants related to the StrongARM
* SA-1100 microprocessor (Advanced RISC Machine (ARM)
* architecture version 4). This file is based on the
* StrongARM SA-1100 data sheet version 2.2.
*
* Language-specific definitions are selected by the
* macro "LANGUAGE", which should be defined as either
* "C" (default) or "Assembly".
*
* and hacked by davep@crl.dec.com
*/
#define Fld(Size, Shft) (((Size) << 16) + (Shft))
#define FSize(Field) ((Field) >> 16)
#define FShft(Field) ((Field) & 0x0000FFFF)
#define FMsk(Field) (((UData (1) << FSize (Field)) - 1) << FShft (Field))
#define FAlnMsk(Field) ((UData (1) << FSize (Field)) - 1)
#define F1stBit(Field) (UData (1) << FShft (Field))
#define LCD_MAX_BPP (16) /* that we allow in this simple situation */
#define LCD_BPP (16)
#define LCD_MONO_BPP (4)
#define LCD_XRES (320)
#define LCD_YRES (240)
#define MAX_PALETTE_COLORS() (1<<12)
#define NUM_PALETTE_ENTRIES(bpp) ((bpp)==8?256:16)
#define PALETTE_MEM_SIZE(bpp) (NUM_PALETTE_ENTRIES(bpp)<<1)
#define PALETTE_MODE_VAL(bpp) (((bpp) & 0x018) << 9)
#define LCD_PALETTE_SIZExx (512)
#define LCD_NUM_PIXELS() (LCD_XRES * LCD_YRES)
#define LCD_NUM_DISPLAY_BYTES(bpp) ((LCD_NUM_PIXELS() * (bpp) + 7)/8)
#define LCD_FB_SIZE(bpp) ((LCD_NUM_DISPLAY_BYTES(bpp) + \
PALETTE_MEM_SIZE(bpp) + 3) & ~3)
#define LCD_FB_MAX() LCD_FB_SIZE(LCD_MAX_BPP)
#define LCD_FB_IMAGE_OFFSET(bpp) PALETTE_MEM_SIZE(bpp)
#define LCD_FB_IMAGE(p, bpp) (((char*)(p)) + LCD_FB_IMAGE_OFFSET(bpp))
#define io_p2v(a) a
typedef unsigned long u_long;
typedef unsigned long Word;
typedef unsigned long Address;
/*
* Liquid Crystal Display (LCD) control registers
*
* Registers
* LCCR0 Liquid Crystal Display (LCD) Control Register 0
* (read/write).
* [Bits LDM, BAM, and ERM are only implemented in
* versions 2.0 (rev. = 8) and higher of the StrongARM
* SA-1100.]
* LCSR Liquid Crystal Display (LCD) Status Register
* (read/write).
* [Bit LDD can be only read in versions 1.0 (rev. = 1)
* and 1.1 (rev. = 2) of the StrongARM SA-1100, it can be
* read and written (cleared) in versions 2.0 (rev. = 8)
* and higher.]
* DBAR1 Liquid Crystal Display (LCD) Direct Memory Access
* (DMA) Base Address Register channel 1 (read/write).
* DCAR1 Liquid Crystal Display (LCD) Direct Memory Access
* (DMA) Current Address Register channel 1 (read).
* DBAR2 Liquid Crystal Display (LCD) Direct Memory Access
* (DMA) Base Address Register channel 2 (read/write).
* DCAR2 Liquid Crystal Display (LCD) Direct Memory Access
* (DMA) Current Address Register channel 2 (read).
* LCCR1 Liquid Crystal Display (LCD) Control Register 1
* (read/write).
* [The LCCR1 register can be only written in
* versions 1.0 (rev. = 1) and 1.1 (rev. = 2) of the
* StrongARM SA-1100, it can be written and read in
* versions 2.0 (rev. = 8) and higher.]
* LCCR2 Liquid Crystal Display (LCD) Control Register 2
* (read/write).
* [The LCCR1 register can be only written in
* versions 1.0 (rev. = 1) and 1.1 (rev. = 2) of the
* StrongARM SA-1100, it can be written and read in
* versions 2.0 (rev. = 8) and higher.]
* LCCR3 Liquid Crystal Display (LCD) Control Register 3
* (read/write).
* [The LCCR1 register can be only written in
* versions 1.0 (rev. = 1) and 1.1 (rev. = 2) of the
* StrongARM SA-1100, it can be written and read in
* versions 2.0 (rev. = 8) and higher. Bit PCP is only
* implemented in versions 2.0 (rev. = 8) and higher of
* the StrongARM SA-1100.]
*
* Clocks
* fcpu, Tcpu Frequency, period of the CPU core clock (CCLK).
* fmem, Tmem Frequency, period of the memory clock (fmem = fcpu/2).
* fpix, Tpix Frequency, period of the pixel clock.
* fln, Tln Frequency, period of the line clock.
* fac, Tac Frequency, period of the AC bias clock.
*/
#define LCD_PEntrySp 2 /* LCD Palette Entry Space [byte] */
#define LCD_4BitPSp /* LCD 4-Bit pixel Palette Space */ \
/* [byte] */ \
(16*LCD_PEntrySp)
#define LCD_8BitPSp /* LCD 8-Bit pixel Palette Space */ \
/* [byte] */ \
(256*LCD_PEntrySp)
#define LCD_12_16BitPSp /* LCD 12/16-Bit pixel */ \
/* dummy-Palette Space [byte] */ \
(16*LCD_PEntrySp)
#define LCD_PGrey Fld (4, 0) /* LCD Palette entry Grey value */
#define LCD_PBlue Fld (4, 0) /* LCD Palette entry Blue value */
#define LCD_PGreen Fld (4, 4) /* LCD Palette entry Green value */
#define LCD_PRed Fld (4, 8) /* LCD Palette entry Red value */
#define LCD_PBS Fld (2, 12) /* LCD Pixel Bit Size */
#define LCD_4Bit /* LCD 4-Bit pixel mode */ \
(0 << FShft (LCD_PBS))
#define LCD_8Bit /* LCD 8-Bit pixel mode */ \
(1 << FShft (LCD_PBS))
#define LCD_12_16Bit /* LCD 12/16-Bit pixel mode */ \
(2 << FShft (LCD_PBS))
#define LCD_Int0_0 0x0 /* LCD Intensity = 0.0% = 0 */
#define LCD_Int11_1 0x1 /* LCD Intensity = 11.1% = 1/9 */
#define LCD_Int20_0 0x2 /* LCD Intensity = 20.0% = 1/5 */
#define LCD_Int26_7 0x3 /* LCD Intensity = 26.7% = 4/15 */
#define LCD_Int33_3 0x4 /* LCD Intensity = 33.3% = 3/9 */
#define LCD_Int40_0 0x5 /* LCD Intensity = 40.0% = 2/5 */
#define LCD_Int44_4 0x6 /* LCD Intensity = 44.4% = 4/9 */
#define LCD_Int50_0 0x7 /* LCD Intensity = 50.0% = 1/2 */
#define LCD_Int55_6 0x8 /* LCD Intensity = 55.6% = 5/9 */
#define LCD_Int60_0 0x9 /* LCD Intensity = 60.0% = 3/5 */
#define LCD_Int66_7 0xA /* LCD Intensity = 66.7% = 6/9 */
#define LCD_Int73_3 0xB /* LCD Intensity = 73.3% = 11/15 */
#define LCD_Int80_0 0xC /* LCD Intensity = 80.0% = 4/5 */
#define LCD_Int88_9 0xD /* LCD Intensity = 88.9% = 8/9 */
#define LCD_Int100_0 0xE /* LCD Intensity = 100.0% = 1 */
#define LCD_Int100_0A 0xF /* LCD Intensity = 100.0% = 1 */
/* (Alternative) */
#define _LCCR0 0xB0100000 /* LCD Control Reg. 0 */
#define _LCSR 0xB0100004 /* LCD Status Reg. */
#define _DBAR1 0xB0100010 /* LCD DMA Base Address Reg. */
/* channel 1 */
#define _DCAR1 0xB0100014 /* LCD DMA Current Address Reg. */
/* channel 1 */
#define _DBAR2 0xB0100018 /* LCD DMA Base Address Reg. */
/* channel 2 */
#define _DCAR2 0xB010001C /* LCD DMA Current Address Reg. */
/* channel 2 */
#define _LCCR1 0xB0100020 /* LCD Control Reg. 1 */
#define _LCCR2 0xB0100024 /* LCD Control Reg. 2 */
#define _LCCR3 0xB0100028 /* LCD Control Reg. 3 */
#if LANGUAGE == C
#define LCCR0 /* LCD Control Reg. 0 */ \
(*((volatile Word *) io_p2v (_LCCR0)))
#define LCSR /* LCD Status Reg. */ \
(*((volatile Word *) io_p2v (_LCSR)))
#define DBAR1 /* LCD DMA Base Address Reg. */ \
/* channel 1 */ \
(*((volatile Address *) io_p2v (_DBAR1)))
#define DCAR1 /* LCD DMA Current Address Reg. */ \
/* channel 1 */ \
(*((volatile Address *) io_p2v (_DCAR1)))
#define DBAR2 /* LCD DMA Base Address Reg. */ \
/* channel 2 */ \
(*((volatile Address *) io_p2v (_DBAR2)))
#define DCAR2 /* LCD DMA Current Address Reg. */ \
/* channel 2 */ \
(*((volatile Address *) io_p2v (_DCAR2)))
#define LCCR1 /* LCD Control Reg. 1 */ \
(*((volatile Word *) io_p2v (_LCCR1)))
#define LCCR2 /* LCD Control Reg. 2 */ \
(*((volatile Word *) io_p2v (_LCCR2)))
#define LCCR3 /* LCD Control Reg. 3 */ \
(*((volatile Word *) io_p2v (_LCCR3)))
#endif /* LANGUAGE == C */
#define LCCR0_LEN 0x00000001 /* LCD ENable */
#define LCCR0_CMS 0x00000002 /* Color/Monochrome display Select */
#define LCCR0_Color (LCCR0_CMS*0) /* Color display */
#define LCCR0_Mono (LCCR0_CMS*1) /* Monochrome display */
#define LCCR0_SDS 0x00000004 /* Single/Dual panel display */
/* Select */
#define LCCR0_Sngl (LCCR0_SDS*0) /* Single panel display */
#define LCCR0_Dual (LCCR0_SDS*1) /* Dual panel display */
#define LCCR0_LDM 0x00000008 /* LCD Disable done (LDD) */
/* interrupt Mask (disable) */
#define LCCR0_BAM 0x00000010 /* Base Address update (BAU) */
/* interrupt Mask (disable) */
#define LCCR0_ERM 0x00000020 /* LCD ERror (BER, IOL, IUL, IOU, */
/* IUU, OOL, OUL, OOU, and OUU) */
/* interrupt Mask (disable) */
#define LCCR0_PAS 0x00000080 /* Passive/Active display Select */
#define LCCR0_Pas (LCCR0_PAS*0) /* Passive display (STN) */
#define LCCR0_Act (LCCR0_PAS*1) /* Active display (TFT) */
#define LCCR0_BLE 0x00000100 /* Big/Little Endian select */
#define LCCR0_LtlEnd (LCCR0_BLE*0) /* Little Endian frame buffer */
#define LCCR0_BigEnd (LCCR0_BLE*1) /* Big Endian frame buffer */
#define LCCR0_DPD 0x00000200 /* Double Pixel Data (monochrome */
/* display mode) */
#define LCCR0_4PixMono (LCCR0_DPD*0) /* 4-Pixel/clock Monochrome */
/* display */
#define LCCR0_8PixMono (LCCR0_DPD*1) /* 8-Pixel/clock Monochrome */
/* display */
#define LCCR0_PDD Fld (8, 12) /* Palette DMA request Delay */
/* [Tmem] */
#define LCCR0_DMADel(Tcpu) /* palette DMA request Delay */ \
/* [0..510 Tcpu] */ \
((Tcpu)/2 << FShft (LCCR0_PDD))
#define LCSR_LDD 0x00000001 /* LCD Disable Done */
#define LCSR_BAU 0x00000002 /* Base Address Update (read) */
#define LCSR_BER 0x00000004 /* Bus ERror */
#define LCSR_ABC 0x00000008 /* AC Bias clock Count */
#define LCSR_IOL 0x00000010 /* Input FIFO Over-run Lower */
/* panel */
#define LCSR_IUL 0x00000020 /* Input FIFO Under-run Lower */
/* panel */
#define LCSR_IOU 0x00000040 /* Input FIFO Over-run Upper */
/* panel */
#define LCSR_IUU 0x00000080 /* Input FIFO Under-run Upper */
/* panel */
#define LCSR_OOL 0x00000100 /* Output FIFO Over-run Lower */
/* panel */
#define LCSR_OUL 0x00000200 /* Output FIFO Under-run Lower */
/* panel */
#define LCSR_OOU 0x00000400 /* Output FIFO Over-run Upper */
/* panel */
#define LCSR_OUU 0x00000800 /* Output FIFO Under-run Upper */
/* panel */
#define LCCR1_PPL Fld (6, 4) /* Pixels Per Line/16 - 1 */
#define LCCR1_DisWdth(Pixel) /* Display Width [16..1024 pix.] */ \
(((Pixel) - 16)/16 << FShft (LCCR1_PPL))
#define LCCR1_HSW Fld (6, 10) /* Horizontal Synchronization */
/* pulse Width - 2 [Tpix] (L_LCLK) */
#define LCCR1_HorSnchWdth(Tpix) /* Horizontal Synchronization */ \
/* pulse Width [2..65 Tpix] */ \
(((Tpix) - 2) << FShft (LCCR1_HSW))
#define LCCR1_ELW Fld (8, 16) /* End-of-Line pixel clock Wait */
/* count - 1 [Tpix] */
#define LCCR1_EndLnDel(Tpix) /* End-of-Line Delay */ \
/* [1..256 Tpix] */ \
(((Tpix) - 1) << FShft (LCCR1_ELW))
#define LCCR1_BLW Fld (8, 24) /* Beginning-of-Line pixel clock */
/* Wait count - 1 [Tpix] */
#define LCCR1_BegLnDel(Tpix) /* Beginning-of-Line Delay */ \
/* [1..256 Tpix] */ \
(((Tpix) - 1) << FShft (LCCR1_BLW))
#define LCCR2_LPP Fld (10, 0) /* Line Per Panel - 1 */
#define LCCR2_DisHght(Line) /* Display Height [1..1024 lines] */ \
(((Line) - 1) << FShft (LCCR2_LPP))
#define LCCR2_VSW Fld (6, 10) /* Vertical Synchronization pulse */
/* Width - 1 [Tln] (L_FCLK) */
#define LCCR2_VrtSnchWdth(Tln) /* Vertical Synchronization pulse */ \
/* Width [1..64 Tln] */ \
(((Tln) - 1) << FShft (LCCR2_VSW))
#define LCCR2_EFW Fld (8, 16) /* End-of-Frame line clock Wait */
/* count [Tln] */
#define LCCR2_EndFrmDel(Tln) /* End-of-Frame Delay */ \
/* [0..255 Tln] */ \
((Tln) << FShft (LCCR2_EFW))
#define LCCR2_BFW Fld (8, 24) /* Beginning-of-Frame line clock */
/* Wait count [Tln] */
#define LCCR2_BegFrmDel(Tln) /* Beginning-of-Frame Delay */ \
/* [0..255 Tln] */ \
((Tln) << FShft (LCCR2_BFW))
#define LCCR3_PCD Fld (8, 0) /* Pixel Clock Divisor/2 - 2 */
/* [1..255] (L_PCLK) */
/* fpix = fcpu/(2*(PCD + 2)) */
/* Tpix = 2*(PCD + 2)*Tcpu */
#define LCCR3_PixClkDiv(Div) /* Pixel Clock Divisor [6..514] */ \
(((Div) - 4)/2 << FShft (LCCR3_PCD))
/* fpix = fcpu/(2*Floor (Div/2)) */
/* Tpix = 2*Floor (Div/2)*Tcpu */
#define LCCR3_CeilPixClkDiv(Div) /* Ceil. of PixClkDiv [6..514] */ \
(((Div) - 3)/2 << FShft (LCCR3_PCD))
/* fpix = fcpu/(2*Ceil (Div/2)) */
/* Tpix = 2*Ceil (Div/2)*Tcpu */
#define LCCR3_ACB Fld (8, 8) /* AC Bias clock half period - 1 */
/* [Tln] (L_BIAS) */
#define LCCR3_ACBsDiv(Div) /* AC Bias clock Divisor [2..512] */ \
(((Div) - 2)/2 << FShft (LCCR3_ACB))
/* fac = fln/(2*Floor (Div/2)) */
/* Tac = 2*Floor (Div/2)*Tln */
#define LCCR3_CeilACBsDiv(Div) /* Ceil. of ACBsDiv [2..512] */ \
(((Div) - 1)/2 << FShft (LCCR3_ACB))
/* fac = fln/(2*Ceil (Div/2)) */
/* Tac = 2*Ceil (Div/2)*Tln */
#define LCCR3_API Fld (4, 16) /* AC bias Pin transitions per */
/* Interrupt */
#define LCCR3_ACBsCntOff /* AC Bias clock transition Count */ \
/* Off */ \
(0 << FShft (LCCR3_API))
#define LCCR3_ACBsCnt(Trans) /* AC Bias clock transition Count */ \
/* [1..15] */ \
((Trans) << FShft (LCCR3_API))
#define LCCR3_VSP 0x00100000 /* Vertical Synchronization pulse */
/* Polarity (L_FCLK) */
#define LCCR3_VrtSnchH (LCCR3_VSP*0) /* Vertical Synchronization pulse */
/* active High */
#define LCCR3_VrtSnchL (LCCR3_VSP*1) /* Vertical Synchronization pulse */
/* active Low */
#define LCCR3_HSP 0x00200000 /* Horizontal Synchronization */
/* pulse Polarity (L_LCLK) */
#define LCCR3_HorSnchH (LCCR3_HSP*0) /* Horizontal Synchronization */
/* pulse active High */
#define LCCR3_HorSnchL (LCCR3_HSP*1) /* Horizontal Synchronization */
/* pulse active Low */
#define LCCR3_PCP 0x00400000 /* Pixel Clock Polarity (L_PCLK) */
#define LCCR3_PixRsEdg (LCCR3_PCP*0) /* Pixel clock Rising-Edge */
#define LCCR3_PixFlEdg (LCCR3_PCP*1) /* Pixel clock Falling-Edge */
#define LCCR3_OEP 0x00800000 /* Output Enable Polarity (L_BIAS, */
/* active display mode) */
#define LCCR3_OutEnH (LCCR3_OEP*0) /* Output Enable active High */
#define LCCR3_OutEnL (LCCR3_OEP*1) /* Output Enable active Low */
#endif /* _SA1100_LCD_H_ */

View File

@@ -0,0 +1,439 @@
/****************************************************************************/
/* Copyright 2000 Compaq Computer Corporation. */
/* . */
/* Copying or modifying this code for any purpose is permitted, */
/* provided that this copyright notice is preserved in its entirety */
/* in all copies or modifications. COMPAQ COMPUTER CORPORATION */
/* MAKES NO WARRANTIES, EXPRESSED OR IMPLIED, AS TO THE USEFULNESS */
/* OR CORRECTNESS OF THIS CODE OR ITS FITNESS FOR ANY PARTICULAR */
/* PURPOSE. */
/****************************************************************************/
#ifndef SA1100_H_INCLUDED
#define SA1100_H_INCLUDED
#define UTCR0 0x00
#define UTCR1 0x04
#define UTCR2 0x08
#define UTCR3 0x0C
#define UTCR4 0x10
#define UTDR 0x14
#define UTSR0 0x1c
#define UTSR1 0x20
#define UTCR0_PE (1 << 0) /* parity enable */
#define UTCR0_OES (1 << 1) /* 1 for even parity */
#define UTCR0_2STOP (1 << 2) /* 1 for 2 stop bits */
#define UTCR0_8BIT (1 << 3) /* 1 for 8 bit data */
#define UTCR0_SCE (1 << 4) /* sample clock enable */
#define UTCR0_RCE (1 << 5) /* receive clock edge select */
#define UTCR0_TCE (1 << 6) /* transmit clock edge select */
#define UTCR1_BRDHIMASK 0xF
#define UTCR2_BRDLoMASK 0xFF
#define UTCR3_RXE (1 << 0) /* receiver enable */
#define UTCR3_TXE (1 << 1) /* transmit enable */
#define UTCR3_BRK (1 << 2) /* send a BRK */
#define UTCR3_RIE (1 << 3) /* receive FIFO interrupt enable */
#define UTCR3_TIE (1 << 4) /* transmit FIFO interrupt enable */
#define UTCR3_LBM (1 << 5) /* loopback mode */
/* [1] 11.11.6 */
#define UTDR_PRE (1 << 8) /* parity error */
#define UTDR_FRE (1 << 9) /* framing error */
#define UTDR_ROR (1 << 10) /* receiver overrun */
/* [1] 11.11.7 */
#define UTSR0_TFS 0x00000001 /* transmit FIFO service request */
#define UTSR0_RFS 0x00000002 /* Receive FIFO 1/3-to-2/3-full or */
/* more Service request (read) */
#define UTSR0_RID 0x00000004 /* Receiver IDle */
#define UTSR0_RBB 0x00000008 /* Receive Beginning of Break */
#define UTSR0_REB 0x00000010 /* Receive End of Break */
#define UTSR0_EIF 0x00000020 /* Error In FIFO (read) */
/* [1] 11.11.8 */
#define UTSR1_TBY (1 << 0) /* transmit FIFO busy */
#define UTSR1_RNE (1 << 1) /* receive FIFO not empty */
#define UTSR1_TNF (1 << 2) /* transmit FIFO not full */
#define UTSR1_PRE (1 << 3) /* parity error */
#define UTSR1_FRE (1 << 4) /* framing error */
#define UTSR1_ROR (1 << 5) /* receiver overrun */
/* infrared */
#define HSCR0_ITR 0x00000001 /* IrDA Transmission Rate */
#define HSCR0_UART (HSCR0_ITR*0) /* UART mode (115.2 kb/s if IrDA) */
#define HSCR0_HSSP (HSCR0_ITR*1) /* HSSP mode (4 Mb/s) */
/* (HP-SIR) modulation Enable */
#define UTCR4_HSE 0x00000001 /* Hewlett-Packard Serial InfraRed */
#define UTCR4_NRZ (UTCR4_HSE*0) /* Non-Return to Zero modulation */
#define UTCR4_HPSIR (UTCR4_HSE*1) /* HP-SIR modulation */
#define UTCR4_LPM 0x00000002 /* Low-Power Mode */
#define UTCR4_Z3_16Bit (UTCR4_LPM*0) /* Zero pulse = 3/16 Bit time */
#define UTCR4_Z1_6us (UTCR4_LPM*1) /* Zero pulse = 1.6 us */
#define UTSR1_ERROR_MASK 0x38
#define SDLCBASE 0x80020060
#define UART1BASE 0x80010000
#define UART2BASE 0x80030000
#define UART3BASE 0x80050000
#define UART1_UTCR0 (UART1BASE + UTCR0)
#define UART1_UTCR1 (UART1BASE + UTCR1)
#define UART1_UTCR2 (UART1BASE + UTCR2)
#define UART1_UTCR3 (UART1BASE + UTCR3)
#define UART1_UTDR (UART1BASE + UTDR)
#define UART1_UTSR0 (UART1BASE + UTSR0)
#define UART1_UTSR1 (UART1BASE + UTSR1)
#define UART2_UTCR0 (UART2BASE + UTCR0)
#define UART2_UTCR1 (UART2BASE + UTCR1)
#define UART2_UTCR2 (UART2BASE + UTCR2)
#define UART2_UTCR3 (UART2BASE + UTCR3)
/* the IR uart has an extra control register */
#define UART2_UTCR4 (UART2BASE + UTCR4)
#define UART2_UTDR (UART2BASE + UTDR)
#define UART2_UTSR0 (UART2BASE + UTSR0)
#define UART2_UTSR1 (UART2BASE + UTSR1)
#define UART3_UTCR0 (UART3BASE + UTCR0)
#define UART3_UTCR1 (UART3BASE + UTCR1)
#define UART3_UTCR2 (UART3BASE + UTCR2)
#define UART3_UTCR3 (UART3BASE + UTCR3)
#define UART3_UTDR (UART3BASE + UTDR)
#define UART3_UTSR0 (UART3BASE + UTSR0)
#define UART3_UTSR1 (UART3BASE + UTSR1)
/*
* Operating System (OS) timer control registers
*
* Registers
* OSMR0 Operating System (OS) timer Match Register 0
* (read/write).
* OSMR1 Operating System (OS) timer Match Register 1
* (read/write).
* OSMR2 Operating System (OS) timer Match Register 2
* (read/write).
* OSMR3 Operating System (OS) timer Match Register 3
* (read/write).
* OSCR Operating System (OS) timer Counter Register
* (read/write).
* OSSR Operating System (OS) timer Status Register
* (read/write).
* OWER Operating System (OS) timer Watch-dog Enable Register
* (read/write).
* OIER Operating System (OS) timer Interrupt Enable Register
* (read/write).
*/
#define OSMR0 *(long*)(0x90000000) /* OS timer Match Reg. 0 */
#define OSMR1 *(long*)(0x90000004) /* OS timer Match Reg. 1 */
#define OSMR2 *(long*)(0x90000008) /* OS timer Match Reg. 2 */
#define OSMR3 *(long*)(0x9000000c) /* OS timer Match Reg. 3 */
#define OSCR *(volatile long*)(0x90000010) /* OS timer Counter Reg. */
#define OSSR *(volatile long*)(0x90000014 ) /* OS timer Status Reg. */
#define OWER *(volatile long*)(0x90000018 ) /* OS timer Watch-dog Enable Reg. */
#define OIER *(volatile long*)(0x9000001C ) /* OS timer Interrupt Enable Reg. */
/*
* DRAM Configuration values
*/
/* [1] 10.2 */
#define DRAM_CONFIGURATION_BASE 0xA0000000
#define MDCNFG 0x00 /* must be initialized */
#define MDCAS00 0x04 /* must be initialized */
#define MDCAS01 0x08 /* must be initialized */
#define MDCAS02 0x0c /* must be initialized */
#define MSC0 0x10 /* must be initialized */
#define MSC1 0x14 /* must be initialized */
#define MECR 0x18 /* should be initialized */
#define MDREFR 0x1c /* must be initialized */
#define MDCAS20 0x20 /* OK not to initialize this register, because the enable bits are cleared on reset */
#define MDCAS21 0x24 /* OK not to initialize this register, because the enable bits are cleared on reset */
#define MDCAS22 0x28 /* OK not to initialize this register, because the enable bits are cleared on reset */
#define MSC2 0x2C /* must be initialized */
#define SMCNFG 0x30 /* should be initialized */
#define ABS_MDCNFG *(volatile unsigned long*)(((char*)DRAM_CONFIGURATION_BASE)+MDCNFG)
#define ABS_MSC0 *(volatile unsigned long*)(((char*)DRAM_CONFIGURATION_BASE)+MSC0)
#define ABS_MSC1 *(volatile unsigned long*)(((char*)DRAM_CONFIGURATION_BASE)+MSC1)
#define ABS_MSC2 *(volatile unsigned long*)(((char*)DRAM_CONFIGURATION_BASE)+MSC2)
#define MDCNFG_BANK0_ENABLE (1 << 0)
#define MDCNFG_BANK1_ENABLE (1 << 1)
#define MDCNFG_DTIM0_SDRAM (1 << 2)
#define MDCNFG_DWID0_32B (0 << 3)
#define MDCNFG_DWID0_16B (1 << 3)
#define MDCNFG_DRAC0(n_) (((n_) & 7) << 4)
#define MDCNFG_TRP0(n_) (((n_) & 0xF) << 8)
#define MDCNFG_TDL0(n_) (((n_) & 3) << 12)
#define MDCNFG_TWR0(n_) (((n_) & 3) << 14)
/* DRAM Refresh Control Register (MDREFR) [1] 10.2.2 */
#define MDREFR_TRASR(n_) (((n_) & 0xF) << 0)
#define MDREFR_DRI(n_) (((n_) & 0xFFF) << 4)
#define MDREFR_E0PIN (1 << 16)
#define MDREFR_K0RUN (1 << 17)
#define MDREFR_K0DB2 (1 << 18)
#define MDREFR_E1PIN (1 << 20) /* SDRAM clock enable pin 1 (banks 0-1) */
#define MDREFR_K1RUN (1 << 21) /* SDRAM clock pin 1 run (banks 0-1) */
#define MDREFR_K1DB2 (1 << 22) /* SDRAM clock pin 1 divide-by-two (banks 0-1) */
#define MDREFR_K2RUN (1 << 25) /* SDRAM clock enable pin 2 (banks 2-3) */
#define MDREFR_K2DB2 (1 << 26) /* SDRAM clock pin 2 run (banks 2-3) */
#define MDREFR_EAPD (1 << 28) /* SDRAM clock pin 2 divide-by-two (banks 2-3) */
#define MDREFR_KAPD (1 << 29)
#define MDREFR_SLFRSH (1 << 31) /* SDRAM self refresh */
#define MSC_RT_ROMFLASH 0
#define MSC_RT_SRAM_012 1
#define MSC_RT_VARLAT_345 1
#define MSC_RT_BURST4 2
#define MSC_RT_BURST8 3
#define MSC_RBW32 (0 << 2)
#define MSC_RBW16 (1 << 2)
#define MSC_RDF(n_) (((n_)&0x1f)<<3)
#define MSC_RDN(n_) (((n_)&0x1f)<<8)
#define MSC_RRR(n_) (((n_)&0x7)<<13)
#define RCSR_REG 0x90030004
#define RCSR_HWR (1 << 0)
#define RCSR_SWR (1 << 1)
#define RCSR_WDR (1 << 2)
#define RCSR_SMR (1 << 3)
#define PSSR_REG 0x90020004
#define PSSR_SSS (1 << 0)
#define PSSR_BFS (1 << 1)
#define PSSR_VFS (1 << 2)
#define PSSR_DH (1 << 3)
#define PSSR_PH (1 << 4)
#define PSPR_REG 0x90020008
#define ICMR_REG 0x90050004
#define PPCR_REG 0x90020014
#define PPCR_59MHZ 0
#define PPCR_73MHZ 1
#define PPCR_88MHZ 2
#define PPCR_103MHZ 3
#define PPCR_118MHZ 4
#define PPCR_132MHZ 5
#define PPCR_147MHZ 6
#define PPCR_162MHZ 7
#define PPCR_176MHZ 8
#define PPCR_191MHZ 9
#define PPCR_206MHZ 10
#define PPCR_221MHZ 11
/* ser. port 2: */
#define PPC_TXD2 0x00004000 /* IPC Transmit Data 2 */
#define PPC_RXD2 0x00008000 /* IPC Receive Data 2 */
#define PPDR_REG 0x90060000 /* PPC Pin Direction Reg. */
#define PPDR_LFCLK 0x400
#define PPSR_REG 0x90060004 /* PPC Pin State Reg. */
#define GPIO_GPIO(Nb) /* GPIO [0..27] */ \
(0x00000001 << (Nb))
#if defined(CONFIG_MACH_IPAQ)
/* The EGPIO is a write only control register at physical address 0x49000000
* See the hardware spec for more details.
*/
#define IPAQ_EGPIO 0x49000000
#define H3600_EGPIO_VIRT 0x49000000
#define H3800_ASIC_BASE 0x49000000
//3800 stuff
#define H3800_FLASH_VPP_ADDR (H3800_ASIC_BASE + _H3800_ASIC2_FlashWP_Base)
#define H3800_FLASH_VPP_ON 0xf1e1;
#define H3800_FLASH_VPP_OFF 0xf1e0;
// defines for our access to the 3800 asics. requires h3600_asic.h andh3600_gpio.h from linux.
#define H3800_ASIC1_GPIO_MASK_ADDR (H3800_ASIC_BASE + _H3800_ASIC1_GPIO_Base + _H3800_ASIC1_GPIO_Mask)
#define H3800_ASIC1_GPIO_DIR_ADDR (H3800_ASIC_BASE + _H3800_ASIC1_GPIO_Base + _H3800_ASIC1_GPIO_Direction)
#define H3800_ASIC1_GPIO_OUT_ADDR (H3800_ASIC_BASE + _H3800_ASIC1_GPIO_Base + _H3800_ASIC1_GPIO_Out)
#define _H3800_ASIC2_KPIO_Base 0x0200
#define _H3800_ASIC2_KPIO_Data 0x0014 /* R/W, 16 bits */
#define _H3800_ASIC2_KPIO_Alternate 0x003c /* R/W, 6 bits */
#define H3800_ASIC2_KPIO_ADDR (H3800_ASIC_BASE + _H3800_ASIC2_KPIO_Base + _H3800_ASIC2_KPIO_Data)
#define H3800_ASIC1_GPIO_MASK_INIT 0x7fff
#define H3800_ASIC1_GPIO_DIR_INIT 0x7fff
#define H3800_ASIC1_GPIO_OUT_INIT 0x2405
#include "ipaq-egpio.h"
#endif
#if defined(CONFIG_MACH_ASSABET) || defined(CONFIG_NEPONSET)
#define ASSABET_BCR 0x12000000
#define BCR_CF_PWR (1 << 0)
#define BCR_CF_RST (1 << 1)
#define BCR_SOFT_RST (1 << 2)
#define BCR_IRDA_FSEL (1 << 3)
#define BCR_CF_BUS_ON (1 << 7)
#define BCR_RS232EN (1 << 12)
#endif
#if defined(CONFIG_MACH_JORNADA56X) || defined(CONFIG_MACH_IPAQ)
#define JORNADA56X_ASIC_BASE_PHYSICAL 0x40000000
#ifdef __ASSEMBLY__
#define JORNADA_E_GPIO_BASE_PHYSICAL(A) (JORNADA56X_ASIC_BASE_PHYSICAL+0x700 + (A * 4))
#else
#define JORNADA_E_GPIO_BASE_PHYSICAL(A) (*(long*)(JORNADA56X_ASIC_BASE_PHYSICAL+0x700 + (A * 4)))
#endif
#define JORNADA_GPDPSR_PHYSICAL JORNADA_E_GPIO_BASE_PHYSICAL(24)
#define JORNADA_GPDPCR_PHYSICAL JORNADA_E_GPIO_BASE_PHYSICAL(25)
#define JORNADA_GPDPLR_PHYSICAL JORNADA_E_GPIO_BASE_PHYSICAL(26)
#define JORNADA_GPDPDR_PHYSICAL JORNADA_E_GPIO_BASE_PHYSICAL(27)
#define JORNADA_RS232_ON (1 << 1) /* ASIC GPIO D */
#define JORNADA_ASIC_RESET (1 << 20) /* SA-1110 GPIO */
#endif
#if defined(CONFIG_MACH_SKIFF)
#define GPIO_BASE (0x41800000)
#else
#define GPIO_BASE (0x90040000)
#endif
#define GPIO_GPLR_OFF (0)
#define GPIO_GPDR_OFF (4)
#define GPIO_GPSR_OFF (8)
#define GPIO_GPCR_OFF (0xc)
#define GPIO_GRER_OFF (0x10)
#define GPIO_GFER_OFF (0x14)
#define GPIO_GEDR_OFF (0x18)
#define GPIO_GAFR_OFF (0x1c)
#define GPIO_SET(off, bits) \
((*((volatile unsigned long *)(((char*)GPIO_BASE)+(off))))|=(bits))
#define GPIO_CLR(off, bits) \
((*((volatile unsigned long *)(((char*)GPIO_BASE)+(off))))&=~(bits))
#define GPIO_READ(off) \
(*((volatile unsigned long *)(((char*)GPIO_BASE)+(off))))
#define GPIO_WRITE(off, v) \
((*((volatile unsigned long *)(((char*)GPIO_BASE)+(off)))) = (v))
#define GPIO_GAFR_LCD_BITS (0xff << 2)
#define GPIO_GPDR_LCD_BITS (0xff << 2)
#define GPIO_GPLR_READ() GPIO_READ(GPIO_GPLR_OFF)
#define GPIO_GPDR_READ() GPIO_READ(GPIO_GPDR_OFF)
#define GPIO_GPSR_READ() GPIO_READ(GPIO_GPSR_OFF)
#define GPIO_GPCR_READ() GPIO_READ(GPIO_GPCR_OFF)
#define GPIO_GRER_READ() GPIO_READ(GPIO_GRER_OFF)
#define GPIO_GFER_READ() GPIO_READ(GPIO_GFER_OFF)
#define GPIO_GEDR_READ() GPIO_READ(GPIO_GEDR_OFF)
#define GPIO_GAFR_READ() GPIO_READ(GPIO_GAFR_OFF)
#define GPIO_GPLR_WRITE(v) GPIO_WRITE(GPIO_GPLR_OFF,v)
#define GPIO_GPDR_WRITE(v) GPIO_WRITE(GPIO_GPDR_OFF,v)
#define GPIO_GPSR_WRITE(v) GPIO_WRITE(GPIO_GPSR_OFF,v)
#define GPIO_GPCR_WRITE(v) GPIO_WRITE(GPIO_GPCR_OFF,v)
#define GPIO_GRER_WRITE(v) GPIO_WRITE(GPIO_GRER_OFF,v)
#define GPIO_GFER_WRITE(v) GPIO_WRITE(GPIO_GFER_OFF,v)
#define GPIO_GEDR_WRITE(v) GPIO_WRITE(GPIO_GEDR_OFF,v)
#define GPIO_GAFR_WRITE(v) GPIO_WRITE(GPIO_GAFR_OFF,v)
#define GPIO_GPLR_SET(v) GPIO_SET(GPIO_GPLR_OFF,v)
#define GPIO_GPDR_SET(v) GPIO_SET(GPIO_GPDR_OFF,v)
#define GPIO_GPSR_SET(v) GPIO_SET(GPIO_GPSR_OFF,v)
#define GPIO_GPCR_SET(v) GPIO_SET(GPIO_GPCR_OFF,v)
#define GPIO_GRER_SET(v) GPIO_SET(GPIO_GRER_OFF,v)
#define GPIO_GFER_SET(v) GPIO_SET(GPIO_GFER_OFF,v)
#define GPIO_GEDR_SET(v) GPIO_SET(GPIO_GEDR_OFF,v)
#define GPIO_GAFR_SET(v) GPIO_SET(GPIO_GAFR_OFF,v)
#define GPIO_GPLR_CLR(v) GPIO_CLR(GPIO_GPLR_OFF,v)
#define GPIO_GPDR_CLR(v) GPIO_CLR(GPIO_GPDR_OFF,v)
#define GPIO_GPSR_CLR(v) GPIO_CLR(GPIO_GPSR_OFF,v)
#define GPIO_GPCR_CLR(v) GPIO_CLR(GPIO_GPCR_OFF,v)
#define GPIO_GRER_CLR(v) GPIO_CLR(GPIO_GRER_OFF,v)
#define GPIO_GFER_CLR(v) GPIO_CLR(GPIO_GFER_OFF,v)
#define GPIO_GEDR_CLR(v) GPIO_CLR(GPIO_GEDR_OFF,v)
#define GPIO_GAFR_CLR(v) GPIO_CLR(GPIO_GAFR_OFF,v)
#define GPIO_LDD8 (1 << 2)
#define GPIO_LDD9 (1 << 3)
#define GPIO_LDD10 (1 << 4)
#define GPIO_LDD11 (1 << 5)
#define GPIO_LDD12 (1 << 6)
#define GPIO_LDD13 (1 << 7)
#define GPIO_LDD14 (1 << 8)
#define GPIO_LDD15 (1 << 9)
#define GAFR *(volatile unsigned long*)(((char*)GPIO_BASE)+(GPIO_GAFR_OFF))
#define GPCR *(volatile unsigned long*)(((char*)GPIO_BASE)+(GPIO_GPCR_OFF))
#define GPDR *(volatile unsigned long*)(((char*)GPIO_BASE)+(GPIO_GPDR_OFF))
#define GPLR *(volatile unsigned long*)(((char*)GPIO_BASE)+(GPIO_GPLR_OFF))
#define GPSR *(volatile unsigned long*)(((char*)GPIO_BASE)+(GPIO_GPSR_OFF))
/*
* power management reggies
*/
#define PMCR 0x90020000 /* Power manager control register */
#define PSSR 0x90020004 /* Power manager sleep status register */
#define PSPR 0x90020008 /* Power manager scratch pad register */
#define PWER 0x9002000C /* Power manager wake-up enable register */
#define PCFR 0x90020010 /* Power manager general configuration reg */
#define PCFR_OPDE (1<<0) /* power down 3.6MHz osc */
#define PCFR_FP (1<<1) /* float PCMCIA controls during sleep */
#define PCFR_FS (1<<2) /* float static chip selects during sleep */
#define PCFR_FO (1<<3) /* force 32KHz osc enable on */
#define PPCR 0x90020014 /* Power manager PLL configuration register */
#define PGSR 0x90020018 /* Power manager GPIO sleep state register */
#define POSR 0x9002001C /* Power manager oscillator status register */
#define RSRR_SWR (1<<0) /* software reset bit */
#define RSRR 0x90030000 /* Reset controller software reset register */
#define RCSR 0x90030004 /* Reset controller status register */
#define ICIP 0x90050000 /* interrupt controller IRQ pend reg */
#define ICFP 0x90050010 /* interrupt controller FIQ pend reg */
#define ICMR 0x90050004 /* interrupt controller mask reg */
#define ICLR 0x90050008 /* interrupt controller level reg */
#define ICCR 0x9005000C /* interrupt controller control reg */
#define RTC_BASE 0x90010000
#define RTAR_OFFSET 0 /* RTC alarm reg */
#define RTAR (RTC_BASE + RTAR_OFFSET)
#define RCNR_OFFSET 4 /* RTC count reg */
#define RCNR (RTC_BASE + RCNR_OFFSET)
#define RTTR_OFFSET 8 /* RTC timer trim reg */
#define RTTR (RTC_BASE + RTTR_OFFSET)
#define RTSR_OFFSET 0x10 /* RTC status reg */
#define RTSR (RTC_BASE + RTSR_OFFSET)
#define UART2_HSCR0_OFFSET 0x80040060
#define UART2_HSCR0 (RTC_BASE + UART2_HSCR0_OFFSET)
#endif /* SA1100_H_INCLUDED */

View File

@@ -0,0 +1,396 @@
/*
* AMBA CLCD PL110 driver
*/
// Support the strcasestr GNU extension
#define _GNU_SOURCE
#include <l4/drivers/lcd.h>
#include <l4/drivers/amba.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <l4/sys/factory.h>
#include <l4/re/c/dataspace.h>
#include <l4/re/c/util/cap_alloc.h>
#include <l4/re/c/mem_alloc.h>
#include <l4/re/c/dma_space.h>
#include <l4/re/c/rm.h>
#include <l4/re/protocols.h>
#include <l4/io/io.h>
#include "lcd-amba.h"
int config_do_bgr;
int config_request_xga;
int config_use_565;
enum pl11x_type
{
UNINITIALIZED, PL110, PL111, PL_UNKNOWN
};
static enum pl11x_type type;
static void *fb_vaddr;
static l4re_dma_space_dma_addr_t fb_paddr;
static int is_qemu;
static int use_xga;
static void config(const char *c)
{
// this driver scans for the following:
// 1024: XGA mode, VGA mode otherwise
// BGR: do bgr mode instead of rgb
// 565: mode (if PL111 available)
if (!c)
return;
config_request_xga = strcasestr(c, "1024") != NULL;
config_do_bgr = strcasestr(c, "bgr") != NULL;
config_use_565 = strcasestr(c, "565") != NULL;
}
static void set_colors(l4re_video_view_info_t *vinfo,
int wr, int wg, int wb,
int sr, int sg, int sb)
{
vinfo->pixel_info.r.shift = sr;
vinfo->pixel_info.r.size = wr;
vinfo->pixel_info.g.shift = sg;
vinfo->pixel_info.g.size = wg;
vinfo->pixel_info.b.shift = sb;
vinfo->pixel_info.b.size = wb;
vinfo->pixel_info.a.shift = 0;
vinfo->pixel_info.a.size = 0;
printf("Color mode: %d:%d:%d %d:%d:%d\n", sr, sg, sb, wr, wg, wb);
}
static int get_fbinfo(l4re_video_view_info_t *vinfo)
{
vinfo->width = use_xga ? 1024 : 640;
vinfo->height = use_xga ? 768 : 480;
vinfo->pixel_info.bytes_per_pixel = 2;
vinfo->bytes_per_line = 2 * vinfo->width;
if ((config_use_565 && type == PL111) || (is_qemu && type == PL110))
{
if (config_do_bgr)
set_colors(vinfo, 5, 6, 5, 11, 5, 0);
else
set_colors(vinfo, 5, 6, 5, 0, 5, 11);
}
else
{
if (config_do_bgr)
set_colors(vinfo, 5, 5, 5, 10, 5, 0);
else
set_colors(vinfo, 5, 5, 5, 0, 5, 10);
}
return 0;
}
static int probe(const char *c)
{
config(c);
return !l4io_lookup_device("AMBA PL110", NULL, 0, 0);
}
static unsigned int fbmem_size(void)
{ return use_xga ? (1024 * 768 * 2) : (480 * 640 * 2); }
unsigned long amba_pl110_lcd_control_virt_base;
unsigned long amba_pl110_sys_base_virt;
static void setup_type(void)
{
uint32_t cellid, periphid;
amba_read_id(amba_pl110_lcd_control_virt_base + 0xfe0, &periphid, &cellid);
if ((periphid & 0xff0fffff) == 0x00041111 && cellid == 0xb105f00d)
type = PL111;
else if (periphid == 0x00041110 && cellid == 0xb105f00d)
type = PL110;
else
{
printf("Unknown LCD: periphid = %08x, cellid = %08x\n", periphid, cellid);
type = PL_UNKNOWN;
}
}
static const char *arm_lcd_get_info(void)
{
return "ARM AMBA PrimeCell 11x";
}
static
l4_uint32_t read_sys_reg(unsigned reg)
{
return *((volatile l4_uint32_t *)(amba_pl110_sys_base_virt + reg));
}
static
void write_sys_reg(unsigned reg, l4_uint32_t val)
{
*((volatile l4_uint32_t *)(amba_pl110_sys_base_virt + reg)) = val;
}
static
void set_clcd_clock(l4_umword_t val)
{
write_sys_reg(Reg_sys_lock, Sys_lock_unlock);
write_sys_reg(Reg_sys_osc4, val);
write_sys_reg(Reg_sys_lock, Sys_lock_lock);
}
static
l4_uint32_t read_clcd_reg(unsigned reg)
{
return *((volatile l4_uint32_t *)(amba_pl110_lcd_control_virt_base + reg));
}
static
void write_clcd_reg(unsigned reg, l4_umword_t val)
{
*((volatile l4_uint32_t *)(amba_pl110_lcd_control_virt_base + reg)) = val;
}
static
unsigned is_vexpress(void)
{
return (read_sys_reg(Reg_sys_id) & 0xfff0000) == 0x1900000;
}
static
int init(unsigned long fb_phys_addr)
{
l4_umword_t id;
id = read_sys_reg(Reg_sys_clcd) & Sys_clcd_idmask;
if (is_vexpress())
id = Sys_clcd_id84;
switch (id)
{
case Sys_clcd_id84:
case Sys_clcd_idmask:
printf("Configure 8.4 CLCD\n");
if (use_xga)
{
set_clcd_clock(Sys_osc4_xga);
write_clcd_reg(Reg_clcd_tim0, Clcd_tim0_84_xga);
write_clcd_reg(Reg_clcd_tim1, Clcd_tim1_84_xga);
write_clcd_reg(Reg_clcd_tim2, Clcd_tim2_84_xga);
write_clcd_reg(Reg_clcd_tim3, Clcd_tim3_84_xga);
}
else
{
set_clcd_clock(Sys_osc4_25mhz);
write_clcd_reg(Reg_clcd_tim0, Clcd_tim0_84_vga);
write_clcd_reg(Reg_clcd_tim1, Clcd_tim1_84_vga);
write_clcd_reg(Reg_clcd_tim2, Clcd_tim2_84_vga);
write_clcd_reg(Reg_clcd_tim3, Clcd_tim3_84_vga);
}
break;
case Sys_clcd_id38:
printf("Configure 3.8 CLCD\n");
set_clcd_clock(Sys_osc4_10mhz);
write_clcd_reg(Reg_clcd_tim0, Clcd_tim0_38);
write_clcd_reg(Reg_clcd_tim1, Clcd_tim1_38);
write_clcd_reg(Reg_clcd_tim2, Clcd_tim2_38);
write_clcd_reg(Reg_clcd_tim3, Clcd_tim3_38);
break;
case Sys_clcd_id25:
printf("Configure 2.5 CLCD\n");
set_clcd_clock(Sys_osc4_5p4mhz);
write_clcd_reg(Reg_clcd_tim0, Clcd_tim0_25);
write_clcd_reg(Reg_clcd_tim1, Clcd_tim1_25);
write_clcd_reg(Reg_clcd_tim2, Clcd_tim2_25);
write_clcd_reg(Reg_clcd_tim3, Clcd_tim3_25);
// Turn the backlight on
//write_ib2_reg(Reg_ib2_ctrl, read_ib2_reg(Reg_ib2_ctrl) | 0x01);
break;
default:
printf("Error: Unknown display type (ID: %lx)\n", id >> 8);
return 0;
}
// Set physical framebuffer address
write_clcd_reg(Reg_clcd_ubas, fb_phys_addr);
write_clcd_reg(Reg_clcd_lbas, 0);
write_clcd_reg(Reg_clcd_ienb, 0);
// Switch power off and configure
write_clcd_reg(Reg_clcd_cntl,
((type == PL111 && config_use_565 && !is_qemu)
? Clcd_cntl_lcdbpp16_pl111_565
: Clcd_cntl_lcdbpp16)
| Clcd_cntl_lcden | Clcd_cntl_lcdbw
| Clcd_cntl_lcdtft | Clcd_cntl_lcdvcomp
| (config_do_bgr ? Clcd_cntl_lcdbgr : 0));
// Switch power on
write_clcd_reg(Reg_clcd_cntl, read_clcd_reg(Reg_clcd_cntl) | Clcd_cntl_lcdpwr);
return 1;
}
static void setup_memory(void)
{
l4_size_t phys_size;
l4io_device_handle_t dh;
l4io_resource_handle_t hdl;
l4re_dma_space_t dma;
if (fb_vaddr)
return;
if (l4io_lookup_device("System Control", &dh, 0, &hdl))
{
printf("Could not get system controller space\n");
return;
}
/* System controller -- XXX Wrong Place XXX */
amba_pl110_sys_base_virt
= l4io_request_resource_iomem(dh, &hdl);
if (amba_pl110_sys_base_virt == 0)
{
printf("Could not map system controller space\n");
return;
}
if (l4io_lookup_device("AMBA PL110", &dh, 0, &hdl))
{
printf("Could not get PL110 LCD device\n");
return;
}
amba_pl110_lcd_control_virt_base
= l4io_request_resource_iomem(dh, &hdl);
if (amba_pl110_lcd_control_virt_base == 0)
{
printf("Could not map controller space for '%s'\n", arm_lcd_get_info());
return;
}
setup_type();
if ((read_sys_reg(Reg_sys_clcd) & Sys_clcd_idmask) == 0x1000)
{
is_qemu = 1; // remember if we run on qemu because of the different
// handling of the bpp16 mode with PL110: my hardware has
// 5551 mode, qemu does 565
type = PL111; // also set the type to PL111 because qemu only
// announces a PL110 but can do the 1024 resolution too
printf("Running on QEmu (assuming PL111).\n");
}
if (config_request_xga && type == PL111)
use_xga = 1;
// get some frame buffer
l4re_ds_t mem = l4re_util_cap_alloc();
if (l4_is_invalid_cap(mem))
return;
if (l4re_ma_alloc(fbmem_size(), mem, L4RE_MA_CONTINUOUS | L4RE_MA_PINNED))
{
printf("Error allocating memory\n");
return;
}
fb_vaddr = 0;
if (l4re_rm_attach(&fb_vaddr, fbmem_size(),
L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_EAGER_MAP | L4RE_RM_F_RW,
mem, 0, L4_PAGESHIFT))
{
printf("Error getting memory\n");
return;
}
printf("Video memory is at virtual %p (size: 0x%x Bytes)\n",
fb_vaddr, fbmem_size());
dma = l4re_util_cap_alloc();
if (l4_is_invalid_cap(dma))
{
printf("error: failed to allocate DMA space capability.\n");
return;
}
if (l4_error(l4_factory_create(l4re_global_env->mem_alloc,
L4RE_PROTO_DMA_SPACE, dma)))
{
printf("error: failed to create DMA space\n");
return;
}
phys_size = fbmem_size();
// get physical address
if (l4re_dma_space_map(dma, mem | L4_CAP_FPAGE_RW, 0, &phys_size, 0,
L4RE_DMA_SPACE_BIDIRECTIONAL, &fb_paddr)
|| phys_size != fbmem_size())
{
printf("Getting the physical address failed or not contiguous\n");
return;
}
printf("Physical video memory is at %llx\n", fb_paddr);
}
static void *fb(void)
{
if (!fb_vaddr)
setup_memory();
return fb_vaddr;
}
static void pl110_enable(void)
{
const char *s;
setup_memory();
switch (type)
{
case PL110: s = "ARM AMBA PrimeCell PL110"; break;
case PL111: s = "ARM AMBA PrimeCell PL111"; break;
default: s = "Unknown"; break;
}
printf("Detected a '%s' device.\n", s);
if (!fb_vaddr || !init(fb_paddr))
{
printf("CLCD init failed!\n");
return;
}
}
static void pl110_disable(void)
{
}
static struct arm_lcd_ops arm_lcd_ops_pl11x = {
.probe = probe,
.get_fbinfo = get_fbinfo,
.get_fb = fb,
.get_video_mem_size = fbmem_size,
.get_info = arm_lcd_get_info,
.enable = pl110_enable,
.disable = pl110_disable,
};
arm_lcd_register(&arm_lcd_ops_pl11x)

View File

@@ -0,0 +1,139 @@
// System Controller Registers
enum
{
Reg_sys_id = 0x00,
Reg_sys_sw = 0x04,
Reg_sys_led = 0x08,
Reg_sys_osc0 = 0x0C,
Reg_sys_osc1 = 0x10,
Reg_sys_osc2 = 0x14,
Reg_sys_osc3 = 0x18,
Reg_sys_osc4 = 0x1C,
Reg_sys_lock = 0x20,
Reg_sys_mci = 0x48,
Reg_sys_misc = 0x60,
Reg_sys_clcd = 0x50,
};
enum
{
Sys_clcd_idmask = 0x1F00,
Sys_clcd_id84 = 0x0100,
Sys_clcd_id38 = 0x0000,
Sys_clcd_id25 = 0x0700,
};
enum
{
Sys_lock_unlock = 0xA05F,
Sys_lock_lock = 0x0000,
};
enum
{
Sys_osc4_xga = 0x15c77,
Sys_osc4_25mhz = 0x2C77,
Sys_osc4_10mhz = 0x2C2A,
Sys_osc4_5p4mhz = 0x2C13,
};
// CLCD Controller Registers
enum
{
Reg_clcd_tim0 = 0x000,
Reg_clcd_tim1 = 0x004,
Reg_clcd_tim2 = 0x008,
Reg_clcd_tim3 = 0x00C,
Reg_clcd_ubas = 0x010,
Reg_clcd_lbas = 0x014,
Reg_clcd_cntl = 0x018,
Reg_clcd_ienb = 0x01c,
Reg_clcd_stat = 0x020,
Reg_clcd_intr = 0x024,
Reg_clcd_ucur = 0x028,
Reg_clcd_lcur = 0x02C,
Reg_clcd_pal = 0x200,
};
enum
{
Clcd_tim0_ppl84_xga = ((1024 / 16) - 1) << 2,
Clcd_tim0_ppl84_vga = (( 640 / 16) - 1) << 2,
Clcd_tim0_hsw84 = 63 << 8, // hsync
Clcd_tim0_hfp84 = 31 << 16, // hfront
Clcd_tim0_hbp84 = 63 << 24, // hback
Clcd_tim0_ppl38 = ((320/16)-1) << 2,
Clcd_tim0_hsw38 = 5 << 8,
Clcd_tim0_hfp38 = 5 << 16,
Clcd_tim0_hbp38 = 5 << 24,
Clcd_tim0_ppl25 = ((240/16)-1) << 2,
Clcd_tim0_hsw25 = 10 << 8,
Clcd_tim0_hfp25 = 30 << 16,
Clcd_tim0_hbp25 = 20 << 24,
Clcd_tim0_84_xga = Clcd_tim0_hbp84 | Clcd_tim0_hfp84| Clcd_tim0_hsw84 | Clcd_tim0_ppl84_xga,
Clcd_tim0_84_vga = Clcd_tim0_hbp84 | Clcd_tim0_hfp84| Clcd_tim0_hsw84 | Clcd_tim0_ppl84_vga,
Clcd_tim0_38 = Clcd_tim0_hbp38 | Clcd_tim0_hfp38| Clcd_tim0_hfp38 | Clcd_tim0_ppl38,
Clcd_tim0_25 = Clcd_tim0_hbp25 | Clcd_tim0_hfp25| Clcd_tim0_hsw25 | Clcd_tim0_ppl25,
};
enum
{
Clcd_tim1_lpp84_xga = (768-1),
Clcd_tim1_lpp84_vga = (480-1),
Clcd_tim1_vsw84 = 24 << 10, // vsync
Clcd_tim1_vfp84 = 11 << 16, // vfront
Clcd_tim1_vbp84 = 9 << 24, // vback
Clcd_tim1_lpp38 = (240-1),
Clcd_tim1_vsw38 = 5 << 10,
Clcd_tim1_vfp38 = 5 << 16,
Clcd_tim1_vbp38 = 5 << 24,
Clcd_tim1_lpp25 = (320-1),
Clcd_tim1_vsw25 = 2 << 10,
Clcd_tim1_vfp25 = 2 << 16,
Clcd_tim1_vbp25 = 1 << 24,
Clcd_tim1_84_xga = Clcd_tim1_vbp84 | Clcd_tim1_vfp84 | Clcd_tim1_vsw84 | Clcd_tim1_lpp84_xga,
Clcd_tim1_84_vga = Clcd_tim1_vbp84 | Clcd_tim1_vfp84 | Clcd_tim1_vsw84 | Clcd_tim1_lpp84_vga,
Clcd_tim1_38 = Clcd_tim1_vbp38 | Clcd_tim1_vfp38 | Clcd_tim1_vsw38 | Clcd_tim1_lpp38,
Clcd_tim1_25 = Clcd_tim1_vbp25 | Clcd_tim1_vfp25 | Clcd_tim1_vsw25 | Clcd_tim1_lpp25,
};
enum
{
Clcd_tim2_ivs = 1 << 11,
Clcd_tim2_ihs = 1 << 12,
Clcd_tim2_cpl84_xga = (1024-1) << 16,
Clcd_tim2_cpl84_vga = (640-1) << 16,
Clcd_tim2_cpl38 = (320-1) << 16,
Clcd_tim2_cpl25 = (240-1) << 16,
Clcd_tim2_bcd = 1 << 26,
Clcd_tim2_84_xga = Clcd_tim2_bcd | Clcd_tim2_cpl84_xga | Clcd_tim2_ihs | Clcd_tim2_ivs,
Clcd_tim2_84_vga = Clcd_tim2_bcd | Clcd_tim2_cpl84_vga | Clcd_tim2_ihs | Clcd_tim2_ivs,
Clcd_tim2_38 = Clcd_tim2_bcd | Clcd_tim2_cpl38 | Clcd_tim2_ihs | Clcd_tim2_ivs,
Clcd_tim2_25 = Clcd_tim2_bcd | Clcd_tim2_cpl25 | Clcd_tim2_ihs | Clcd_tim2_ivs,
};
enum
{
Clcd_tim3_84_xga = 0,
Clcd_tim3_84_vga = 0,
Clcd_tim3_38 = 0,
Clcd_tim3_25 = 0,
};
enum
{
Clcd_cntl_lcden = 1,
Clcd_cntl_lcdbpp4 = 2 << 1,
Clcd_cntl_lcdbpp8 = 3 << 1,
Clcd_cntl_lcdbpp16 = 4 << 1,
Clcd_cntl_lcdbpp24 = 5 << 1,
Clcd_cntl_lcdbpp16_pl111_565 = 6 << 1,
Clcd_cntl_lcdbpp12_pl111_444 = 7 << 1,
Clcd_cntl_lcdbw = 0 << 4,
Clcd_cntl_lcdtft = 1 << 5,
Clcd_cntl_lcdbgr = 1 << 8,
Clcd_cntl_lcdbebo = 1 << 9,
Clcd_cntl_lcdbepo = 1 << 10,
Clcd_cntl_lcdpwr = 1 << 11,
Clcd_cntl_lcdvcomp = 1 << 12,
};

View File

@@ -0,0 +1,239 @@
/*
* Some routines to enable the LCD in an IPAQ H3800 (and maybe others).
*
* Contains stuff taken from Linux and bootldr.
*
*/
#include <l4/drivers/lcd.h>
#include <stdio.h>
/* Gnah... */
void putstr(const char *);
#define CONFIG_MACH_IPAQ 1
#include <arch-sa1100/sa1100.h>
#include <arch-sa1100/sa1100-lcd.h>
#define __SERIAL_H__ /* don't include serial.h */
#include <arch-sa1100/h3600.h>
#include <arch-sa1100/h3600_asic.h>
typedef unsigned short u16;
#define SET_ASIC1(x) \
do {if ( setp ) { H3800_ASIC1_GPIO_OUT |= (x); } else { H3800_ASIC1_GPIO_OUT &= ~(x); }} while(0)
#define CTL_REG_READ(addr) (*(volatile unsigned long *)(addr))
#define CTL_REG_WRITE(addr, val) (*(volatile unsigned long *)(addr) = (val))
#define CTL_REG_READ_BYTE(addr) (*(volatile unsigned char *)(addr))
#define CTL_REG_WRITE_BYTE(addr, val) (*(volatile unsigned char *)(addr) = (val))
#define TIMEOUT 350000
static void sa_lcd_light(int on, int level)
{
(void)on; (void)level;
}
static void sa_control_egpio(enum ipaq_egpio_type x, int setp)
{
switch (x) {
case IPAQ_EGPIO_LCD_ON:
SET_ASIC1( GPIO1_LCD_5V_ON
| GPIO1_LCD_ON
| GPIO1_LCD_PCI
| GPIO1_VGH_ON
| GPIO1_VGL_ON);
case IPAQ_EGPIO_CODEC_NRESET:
case IPAQ_EGPIO_AUDIO_ON:
case IPAQ_EGPIO_QMUTE:
case IPAQ_EGPIO_OPT_NVRAM_ON:
case IPAQ_EGPIO_OPT_ON:
case IPAQ_EGPIO_CARD_RESET:
case IPAQ_EGPIO_OPT_RESET:
case IPAQ_EGPIO_IR_ON:
case IPAQ_EGPIO_IR_FSEL:
case IPAQ_EGPIO_RS232_ON:
case IPAQ_EGPIO_VPP_ON:
case IPAQ_EGPIO_COM_DSR:
break;
}
}
static void arm_lcd_h3800_disable(void)
{
sa_lcd_light(0, 0);
LCSR = 0; /* Clear LCD Status Register */
LCCR0 &= ~(LCCR0_LDM); /* Enable LCD Disable Done Interrupt */
LCCR0 &= ~(LCCR0_LEN); /* Disable LCD Controller */
CTL_REG_WRITE(GPIO_BASE+GPIO_GPCR_OFF, 0 /*params->gpio*/);
sa_control_egpio(IPAQ_EGPIO_LCD_ON, 0);
}
#define GPIO_WRITE(off, v) \
((*((volatile unsigned long *)(((char*)GPIO_BASE)+(off)))) = (v))
#define GPIO_GAFR_WRITE(v) GPIO_WRITE(GPIO_GAFR_OFF,v)
#define GPIO_GPDR_WRITE(v) GPIO_WRITE(GPIO_GPDR_OFF,v)
static unsigned long *sa_vidmem;
static void arm_lcd_h3800_enable(void)
{
//arm_lcd_h3800_disable();
//printf("Enabling LCD controller.\n");
#if 0
GPIO_GAFR_WRITE(0xff << 2);
GPIO_GPDR_WRITE(0xff << 2);
sa_vidmem[0] = 0x2077;
LCCR3 = 0x10 | LCCR3_VrtSnchL | LCCR3_HorSnchL;
LCCR2 = LCCR2_DisHght(VESA_YRES + 1) + LCCR2_VrtSnchWdth(3)
+ LCCR2_BegFrmDel(10) + LCCR2_EndFrmDel(1);
LCCR1 = LCCR1_DisWdth(VESA_XRES) + LCCR1_HorSnchWdth(4) +
LCCR1_BegLnDel(0xC) + LCCR1_EndLnDel(0x11);
LCCR0 = (LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act +
LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM +
LCCR0_DMADel(0))
& ~LCCR0_LEN;
#endif
{
l4_size_t phys_size;
if (!l4dm_mem_phys_addr(sa_vidmem, 4, &phys, 1, &pnum)
|| !pnum)
{
printf("Cannot get physical address of vidmem.\n");
return;
}
printf("Physical address of vidmem is %08lx\n", phys.addr);
DBAR1 = phys.addr;
}
#if 0
LCCR0 |= LCCR0_LEN;
sa_control_egpio(IPAQ_EGPIO_LCD_ON, 1);
CTL_REG_WRITE(GPIO_BASE+GPIO_GPDR_OFF, 0xff << 2);
CTL_REG_WRITE(GPIO_BASE+GPIO_GPSR_OFF, 0);
sa_control_egpio(IPAQ_EGPIO_LCD_ON, 1);
#endif
sa_lcd_light(1, 5);
}
/*
* Returns the address to the framebuffer, and does some initialisation
* stuff.
*/
static void *arm_lcd_h3800_fb(void)
{
if (arm_driver_reserve_region(H3800_ASIC_BASE, 0x100000))
return NULL;
if (arm_driver_reserve_region(_LCCR0, 0x100000))
return NULL;
if (arm_driver_reserve_region(GPIO_BASE, 0x100000))
return NULL;
// get some frame buffer memory
if (!(sa_vidmem = l4dm_mem_allocate(0x100000,
L4DM_PINNED | L4DM_CONTIGUOUS |
L4RM_MAP | L4RM_LOG2_ALLOC)))
{
printf("Could not get video memory.\n");
return NULL;
}
printf("Video memory is at virtual %p\n", sa_vidmem);
// --------------------------------------------------------------------
//H3800_ASIC2_GPIODIR = GPIO2_PEN_IRQ | GPIO2_SD_DETECT | GPIO2_EAR_IN_N | GPIO2_USB_DETECT_N | GPIO2_SD_CON_SLT;
// This is all for the H3800 display
//*((unsigned short *) H3800_ASIC1_GPIO_MASK_ADDR) = H3800_ASIC1_GPIO_MASK_INIT;
//*((unsigned short *) H3800_ASIC1_GPIO_OUT_ADDR) = H3800_ASIC1_GPIO_OUT_INIT;
//*((unsigned short *) H3800_ASIC1_GPIO_DIR_ADDR) = H3800_ASIC1_GPIO_DIR_INIT;
//*((unsigned short *) H3800_ASIC1_GPIO_OUT_ADDR) = H3800_ASIC1_GPIO_OUT_INIT;
//sa_disable_controller();
{
int num_pixels;
unsigned short* bufp = (unsigned short*)LCD_FB_IMAGE(sa_vidmem, 16);
for (num_pixels = LCD_NUM_PIXELS(); num_pixels; num_pixels--)
{
*bufp++ = (unsigned short)num_pixels;
}
}
arm_lcd_h3800_enable();
return LCD_FB_IMAGE(sa_vidmem, 16);
}
static unsigned int arm_lcd_h3800_video_mem_size(void)
{ return LCD_XRES * LCD_YRES * ((LCD_BPP + 7) >> 3); }
static unsigned int arm_lcd_h3800_get_screen_width(void)
{ return LCD_XRES; }
static unsigned int arm_lcd_h3800_get_screen_height(void)
{ return LCD_YRES; }
static unsigned int arm_lcd_h3800_get_bpp(void)
{ return LCD_BPP; }
static unsigned int arm_lcd_h3800_get_bytes_per_line(void)
{ return LCD_XRES * ((LCD_BPP + 7) >> 3); }
static int get_fbinfo(l4re_fb_info_t *fbinfo)
{
fbinfo->x_res = LCD_XRES;
fbinfo->y_res = LCD_YRES;
fbinfo->bits_per_pixel = LCD_BPP;
fbinfo->bytes_per_pixel = (LCD_BPP + 7) >> 3;
fbinfo->bytes_per_scan_line = ((LCD_BPP + 7) >> 3) * fbinfo->x_res;
fbinfo->r.shift = 0;
fbinfo->r.size = 5;
fbinfo->g.shift = 5;
fbinfo->g.size = 6;
fbinfo->b.shift = 11;
fbinfo->b.size = 5;
return 0;
}
static const char *arm_lcd_h3800_get_info(void)
{ return "ARM LCD driver for IPAQ H3800 series"; }
static int arm_lcd_h3800_probe(const char *configstr)
{
(void)configstr;
return !l4io_lookup_device("H3800 LCD", NULL, 0, 0);
}
struct arm_lcd_ops arm_lcd_ops_h3800 = {
.probe = arm_lcd_h3800_probe,
.get_fb = arm_lcd_h3800_fb,
.get_fbinfo = get_fbinfo,
.get_video_mem_size = arm_lcd_h3800_video_mem_size,
.get_info = arm_lcd_h3800_get_info,
.enable = arm_lcd_h3800_enable,
.disable = arm_lcd_h3800_disable,
};
arm_lcd_register(&arm_lcd_ops_h3800);

View File

@@ -0,0 +1,367 @@
/* SPDX-License-Identifier: GPL-2.0-only OR License-Ref-kk-custom */
/*
* Copyright (C) 2021-2023 Stephan Gerhold <stephan@gerhold.net>
*
* Qualcomm MDP5 FB driver (panel must be init'ed by boot-loader)
*/
// Support the strcasestr GNU extension
#define _GNU_SOURCE
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <l4/drivers/lcd.h>
#include <l4/io/io.h>
#include <l4/re/c/dma_space.h>
#include <l4/re/c/mem_alloc.h>
#include <l4/re/c/rm.h>
#include <l4/re/c/util/cap_alloc.h>
#include <l4/re/protocols.h>
#include <l4/sys/factory.h>
#include <l4/util/util.h>
#include <l4/vbus/vbus.h>
#define HW_VERSION(major, minor, step) \
(((major) << 28) | ((minor) << 16) | ((step) << 0))
enum {
CTL_FLUSH = 0x18,
CTL_START = 0x1c,
};
struct mdp5_pipe {
const char *name;
unsigned int base;
l4_uint32_t flush;
};
struct mdp5_hw {
const char *name;
unsigned int ctl0_base;
struct mdp5_pipe pipes[];
};
static struct mdp5_hw const mdp5_hw_v1_0 = {
.name = "MDP5 v1.0",
.ctl0_base = 0x00500,
.pipes = {
{
.name = "VIG_0",
.base = 0x01100,
.flush = 1 << 0,
},
{
.name = "RGB_0",
.base = 0x01d00,
.flush = 1 << 3,
},
{
.name = "DMA_0",
.base = 0x02900,
.flush = 1 << 11,
},
{ }
},
};
static struct mdp5_hw const mdp5_hw_v1_6 = {
.name = "MDP5 v1.6",
.ctl0_base = 0x01000,
.pipes = {
{
.name = "VIG_0",
.base = 0x04000,
.flush = 1 << 0,
},
{
.name = "RGB_0",
.base = 0x14000,
.flush = 1 << 3,
},
{
.name = "DMA_0",
.base = 0x24000,
.flush = 1 << 11,
},
{ }
},
};
enum {
SSPP_SRC_SIZE = 0x00,
SSPP_SRC_IMG_SIZE = 0x04,
SSPP_SRC_XY = 0x08,
SSPP_OUT_SIZE = 0x0c,
SSPP_OUT_XY = 0x10,
SSPP_SRC0_ADDR = 0x14,
SSPP_SRC_YSTRIDE0 = 0x24,
SSPP_SRC_FORMAT = 0x30,
SSPP_SRC_UNPACK_PATTERN = 0x34,
SSPP_SRC_FORMAT_SRC_RGB565 = 0x1 << 9 | 0x1 << 4 | 0x1 << 2 | 0x2 << 0,
SSPP_SRC_FORMAT_SRC_RGB888 = 0x2 << 9 | 0x3 << 4 | 0x3 << 2 | 0x3 << 0,
SSPP_SRC_FORMAT_UNPACK_RGB = 0x1 << 17 | 0x2 << 12,
SSPP_SRC_UNPACK_PATTERN_RGB = 0x2 << 16 | 0x0 << 8 | 0x1 << 0,
};
static l4_addr_t mdp5_base;
static struct mdp5_hw const *fb_hw;
static struct mdp5_pipe const *fb_pipe;
static l4_uint16_t fb_width, fb_height;
static void *fb_vaddr;
static l4re_dma_space_dma_addr_t fb_paddr;
static bool fb_need_refresh;
static pthread_t fb_refresh_pthread;
static int width(void) { return fb_width; }
static int height(void) { return fb_height; }
static int bytes_per_pixel(void) { return 2; }
static unsigned int fbmem_size(void)
{ return height() * width() * bytes_per_pixel(); }
static void write_ctl(unsigned reg, l4_uint32_t val)
{ *((volatile l4_uint32_t *)(mdp5_base + fb_hw->ctl0_base + reg)) = val; }
static l4_uint32_t read_pipe(unsigned reg)
{ return *((volatile l4_uint32_t *)(mdp5_base + fb_pipe->base + reg)); }
static void write_pipe(unsigned reg, l4_uint32_t val)
{ *((volatile l4_uint32_t *)(mdp5_base + fb_pipe->base + reg)) = val; }
static bool read_size(void)
{
l4io_device_handle_t dh;
l4io_resource_handle_t hdl;
l4_uint32_t val;
if (mdp5_base)
return fb_width && fb_height;
if (l4io_lookup_device("qcom,mdp5", &dh, NULL, &hdl))
{
printf("Could not lookup MDP5 device\n");
return false;
}
mdp5_base = l4io_request_resource_iomem(dh, &hdl);
if (mdp5_base == 0)
{
printf("Could not map MDP5 registers\n");
return false;
}
/* Detect hardware version */
val = *(volatile l4_uint32_t *)mdp5_base;
if (val >= HW_VERSION(1, 6, 0))
fb_hw = &mdp5_hw_v1_6;
else
fb_hw = &mdp5_hw_v1_0;
printf("Detected hardware version: %s\n", fb_hw->name);
for (fb_pipe = fb_hw->pipes; fb_pipe->base; fb_pipe++)
{
val = read_pipe(SSPP_OUT_SIZE);
fb_width = val;
fb_height = val >> 16;
if (fb_width && fb_height)
{
printf("Found active pipe %s (%dx%d)\n",
fb_pipe->name, fb_width, fb_height);
return true;
}
}
printf("No active pipe found, display not initialized by bootloader?\n");
return false;
}
static void setup_memory(void)
{
if (fb_vaddr || !read_size())
return;
// get some frame buffer
l4re_ds_t mem = l4re_util_cap_alloc();
if (l4_is_invalid_cap(mem))
return;
if (l4re_ma_alloc(fbmem_size(), mem,
L4RE_MA_CONTINUOUS | L4RE_MA_PINNED | L4RE_MA_SUPER_PAGES))
{
printf("Error allocating memory\n");
return;
}
fb_vaddr = 0;
if (l4re_rm_attach(&fb_vaddr, fbmem_size(),
L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_EAGER_MAP | L4RE_RM_F_RW,
mem, 0, L4_SUPERPAGESHIFT))
{
printf("Error getting memory\n");
return;
}
printf("Video memory is at virtual %p (size: 0x%x Bytes)\n",
fb_vaddr, fbmem_size());
l4re_dma_space_t dma = l4re_util_cap_alloc();
if (l4_is_invalid_cap(dma))
{
printf("error: failed to allocate DMA space capability.\n");
return;
}
if (l4_error(l4_factory_create(l4re_global_env->mem_alloc,
L4RE_PROTO_DMA_SPACE, dma)))
{
printf("error: failed to create DMA space\n");
return;
}
l4_cap_idx_t vbus = l4re_env_get_cap("vbus");
if (l4_is_invalid_cap(vbus))
{
printf("Failed to get 'vbus' capability\n");
return;
}
int ret = l4vbus_assign_dma_domain(vbus, ~0U, L4VBUS_DMAD_BIND |
L4VBUS_DMAD_L4RE_DMA_SPACE, dma);
if (ret)
{
printf("Failed to assign DMA domain to vbus\n");
return;
}
printf("DMA domain assigned successfully\n");
l4_size_t phys_size = fbmem_size();
// get physical address
if (l4re_dma_space_map(dma, mem | L4_CAP_FPAGE_RW, 0, &phys_size, 0,
L4RE_DMA_SPACE_TO_DEVICE, &fb_paddr)
|| phys_size != fbmem_size())
{
printf("Getting the physical address failed or not contiguous\n");
return;
}
printf("Physical video memory is at %llx\n", fb_paddr);
}
static int lcd_probe(const char *configstr)
{
fb_need_refresh = configstr && strcasestr(configstr, "refresh") != NULL;
return !l4io_lookup_device("qcom,mdp5", NULL, 0, 0);
}
static void *lcd_get_fb(void)
{
setup_memory();
return fb_vaddr;
}
static unsigned int lcd_fbmem_size(void)
{ return fbmem_size(); }
static const char *lcd_get_info(void)
{ return "MDP5 FASTBOOT init'ed FB"; }
static int lcd_get_fbinfo(l4re_video_view_info_t *vinfo)
{
if (!read_size())
return 1;
vinfo->width = width();
vinfo->height = height();
vinfo->bytes_per_line = bytes_per_pixel() * vinfo->width;
vinfo->pixel_info.bytes_per_pixel = bytes_per_pixel();
vinfo->pixel_info.r.shift = 11;
vinfo->pixel_info.r.size = 5;
vinfo->pixel_info.g.shift = 5;
vinfo->pixel_info.g.size = 6;
vinfo->pixel_info.b.shift = 0;
vinfo->pixel_info.b.size = 5;
vinfo->pixel_info.a.shift = 0;
vinfo->pixel_info.a.size = 0;
return 0;
}
static void *lcd_refresh_func(void *data)
{
while (true)
{
write_ctl(CTL_START, 1);
l4_sleep(20); // ~50 Hz
}
return data;
}
static void lcd_start_refresh_thread(void)
{
pthread_attr_t thread_attr;
int err;
if ((err = pthread_attr_init(&thread_attr)) != 0) {
printf("Error: Initializing pthread attr: %d\n", err);
return;
}
struct sched_param sp;
sp.sched_priority = 0xff;
pthread_attr_setschedpolicy(&thread_attr, SCHED_L4);
pthread_attr_setschedparam(&thread_attr, &sp);
pthread_attr_setinheritsched(&thread_attr, PTHREAD_EXPLICIT_SCHED);
err = pthread_create(&fb_refresh_pthread, &thread_attr, lcd_refresh_func, NULL);
if (err != 0)
printf("Error: Creating thread: %d\n", err);
}
static void lcd_enable(void)
{
setup_memory();
if (!fb_paddr)
return;
// write pipe configuration
write_pipe(SSPP_SRC_SIZE, width() | height() << 16);
write_pipe(SSPP_SRC_IMG_SIZE, width() | height() << 16);
write_pipe(SSPP_SRC_XY, 0);
write_pipe(SSPP_SRC0_ADDR, fb_paddr);
write_pipe(SSPP_SRC_YSTRIDE0, bytes_per_pixel() * width());
write_pipe(SSPP_SRC_FORMAT,
SSPP_SRC_FORMAT_SRC_RGB565 | SSPP_SRC_FORMAT_UNPACK_RGB);
write_pipe(SSPP_SRC_UNPACK_PATTERN, SSPP_SRC_UNPACK_PATTERN_RGB);
// flush pipe configuration
write_ctl(CTL_FLUSH, fb_pipe->flush);
if (fb_need_refresh)
lcd_start_refresh_thread();
}
static void lcd_disable(void)
{
printf("%s unimplemented.\n", __func__);
}
static struct arm_lcd_ops arm_lcd_ops_mdp5 = {
.probe = lcd_probe,
.get_fb = lcd_get_fb,
.get_fbinfo = lcd_get_fbinfo,
.get_video_mem_size = lcd_fbmem_size,
.get_info = lcd_get_info,
.enable = lcd_enable,
.disable = lcd_disable,
};
arm_lcd_register(&arm_lcd_ops_mdp5);

View File

@@ -0,0 +1,580 @@
/*
* OMAP3 CLCD driver
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <l4/sys/factory.h>
#include <l4/drivers/lcd.h>
#include <l4/io/io.h>
#include <l4/re/c/dataspace.h>
#include <l4/re/c/dma_space.h>
#include <l4/re/c/mem_alloc.h>
#include <l4/re/c/namespace.h>
#include <l4/re/c/rm.h>
#include <l4/re/protocols.h>
#include <l4/re/c/util/cap_alloc.h>
#include <l4/util/util.h>
#include <l4/vbus/vbus.h>
#include <l4/vbus/vbus_gpio.h>
#include <l4/vbus/vbus_i2c.h>
#include "lcd-omap3.h"
enum {
/* Beagleboard mode assumes that U-Boot has set up everything and we
* basically just need to set the framebuffer address */
MODE_BEAGLEBOARD = 0,
MODE_EVM = 1,
};
static int lcd_mode;
static inline int is_omap3evm(void) { return lcd_mode == MODE_EVM; }
static inline int is_beagleboard(void) { return lcd_mode == MODE_BEAGLEBOARD; }
static inline int width(void)
{
if (is_omap3evm())
return 480;
if (is_beagleboard())
return 1280;
return 0;
}
static inline int height(void)
{
if (is_omap3evm())
return 640;
if (is_beagleboard())
return 720;
return 0;
}
static inline int bytes_per_pixel(void)
{ return 2; }
static unsigned int fbmem_size(void)
{ return height() * width() * bytes_per_pixel(); }
static l4_addr_t omap_dss_virt_base;
static void *fb_vaddr;
static l4re_dma_space_dma_addr_t fb_paddr;
static l4_cap_idx_t vbus = L4_INVALID_CAP;
static l4vbus_device_handle_t i2c_handle;
static l4vbus_device_handle_t gpio_handle;
static l4_umword_t read_dss_reg(unsigned reg)
{
return *((volatile l4_umword_t *)(omap_dss_virt_base + reg));
}
static void write_dss_reg(unsigned reg, l4_umword_t val)
{
*((volatile l4_umword_t *)(omap_dss_virt_base + reg)) = val;
}
#if 0
static int disable_dss(void)
{
l4_umword_t val = read_dss_reg(Reg_dispc_control);
/* check if digital output or the lcd output are enabled */
if (val & (Dispc_control_digitalenable | Dispc_control_lcdenable))
{
/*Disable the lcd output and digital output*/
val &= ~(Dispc_control_digitalenable | Dispc_control_lcdenable);
write_dss_reg(Reg_dispc_control, val);
write_dss_reg(Reg_dispc_irqstatus, Dispc_irqstatus_framedone);
l4_usleep(100);
if (!(read_dss_reg(Reg_dispc_irqstatus) & Dispc_irqstatus_framedone))
{
printf("OMAP LCD: Disable DSS timeout.\n");
return -1;
}
}
return 0;
}
static void reset_display_controller(void)
{
disable_dss();
/* Reset the display controller. */
write_dss_reg(Reg_dispc_sysconfig, Dispc_sysconfig_softreset);
/* Wait until reset completes OR timeout occurs. */
l4_usleep(100);
if (!(read_dss_reg(Reg_dispc_sysstatus) & Dispc_sysstatus_resetdone))
{
printf("[LCD]: Warning: Reset DISPC timeout.\n");
}
l4_uint32_t reg_val = read_dss_reg(Reg_dispc_sysconfig);
reg_val &= ~Dispc_sysconfig_softreset;
write_dss_reg(Reg_dispc_sysconfig, reg_val);
}
static int enable_lcd_backlight(void)
{
l4_uint8_t val;
val = 0x32;
if (l4vbus_i2c_write(vbus, i2c_handle, T2_I2C_LED_ADDR_GROUP, TRITON2_LED_LEDEN_REG, &val, 1))
return -1;
val = 0x7f;
if (l4vbus_i2c_write(vbus, i2c_handle, T2_I2C_LED_ADDR_GROUP, TRITON2_LED_PWMAON_REG, &val, 1))
return -1;
val = 0x7f;
if (l4vbus_i2c_write(vbus, i2c_handle, T2_I2C_LED_ADDR_GROUP, TRITON2_LED_PWMBON_REG, &val, 1))
return -1;
val = 0x7f;
if (l4vbus_i2c_write(vbus, i2c_handle, T2_I2C_LED_ADDR_GROUP, TRITON2_LED_PWMAOFF_REG, &val, 1))
return -1;
val = 0x7f;
if (l4vbus_i2c_write(vbus, i2c_handle, T2_I2C_LED_ADDR_GROUP, TRITON2_LED_PWMBOFF_REG, &val, 1))
return -1;
val = 0x0b;
if (l4vbus_i2c_write(vbus, i2c_handle, 0x4b, TRITON2_VDAC_DEDICATED, &val, 1))
return -1;
val = 0xe0;
if (l4vbus_i2c_write(vbus, i2c_handle, 0x4b, TRITON2_VDAC_DEV_GRP, &val, 1))
return -1;
return 0;
}
static int enable_lcd_power(void)
{
if (l4vbus_gpio_write(vbus, gpio_handle, GPIO_NUM_VDD, 0))
return -1;
return 0;
}
#if 0
static int disable_lcd_power(void)
{
if (l4vbus_gpio_write(vbus, GPIO_NUM_VDD, 1))
return -1;
return 0;
}
#endif
static int configure_vga_mode(void)
{
if (l4vbus_gpio_write(vbus, gpio_handle, GPIO_NUM_QVGA_nVGA, 0))
return -1;
return 0;
}
static int configure_vert_scan_direction(int direction)
{
if (l4vbus_gpio_write(vbus, gpio_handle, GPIO_NUM_UD, direction))
return -1;
return 0;
}
static int configure_horiz_scan_direction(int direction)
{
if (l4vbus_gpio_write(vbus, gpio_handle, GPIO_NUM_LR, direction))
return -1;
return 0;
}
static int disable_lcd_reset(void)
{
if (l4vbus_gpio_write(vbus, gpio_handle, GPIO_NUM_RESB, 0))
return -1;
l4_usleep(100);
return 0;
}
static int enable_lcd_HVIF(void)
{
l4_umword_t val = read_dss_reg(Reg_dispc_pol_freq);
val |= ((0 << Dispc_pol_freq_rf_shift) |
(1 << Dispc_pol_freq_onoff_shift));
write_dss_reg(Reg_dispc_pol_freq, val);
return 0;
}
static int enable_lcd_reset(void)
{
if (l4vbus_gpio_write(vbus, gpio_handle, GPIO_NUM_RESB, 1))
return -1;
return 0;
}
static int enable_INI(void)
{
if (l4vbus_gpio_write(vbus, gpio_handle, GPIO_NUM_INI, 1))
return -1;
return 0;
}
#if 0
static int disble_INI(void)
{
if (l4vbus_gpio_write(vbus, GPIO_NUM_INI, 0))
return -1;
return 0;
}
#endif
#endif
static void issue_go_lcd(void)
{
l4_umword_t val = read_dss_reg(Reg_dispc_control);
val |= Dispc_control_golcd;
write_dss_reg(Reg_dispc_control, val);
l4_usleep(1000);
if (read_dss_reg(Reg_dispc_control) & Dispc_control_golcd)
{
printf("[LCD] Info: Update DISPC timeout.\n");
}
}
static void configure_dss_omap3evm(l4_addr_t frame_buffer)
{
l4_uint32_t val;
val = read_dss_reg(Reg_dss_control);
val &= 0xfffffffe;
write_dss_reg(Reg_dss_control, val);
/* No standby, No idle,mormal mode, ocp clock free running */
//val = Dispc_sysconfig_midlemode_nstandby | Dispc_sysconfig_sidlemode_nidle;
//val &= ~Dispc_sysconfig_softreset ;
//write_dss_reg(Reg_dispc_sysconfig, val);
write_dss_reg(Reg_dispc_sysconfig, 0x2015);
/* Not enabling any interrupts */
write_dss_reg(Reg_dispc_irqenable, 0x00);
/* 2:1 - Frame Data only loaded every frame (10) */
write_dss_reg(Reg_dispc_config, Dispc_config_loadmode_frdatlefr);
/* Default Color is white */
write_dss_reg(Reg_dispc_default_colour0, 0xffffff & Default_colour_mask);
/* Default Transparency Color is black */
write_dss_reg(Reg_dispc_trans_colour0, 0xffffff & Transparency_colour_mask);
/*timing logic for HSYNC signal */
val = (38 << Dispc_timing_h_hbp_shift) |
(44 << Dispc_timing_h_hfp_shift) |
(2 << Dispc_timing_h_hsw_shift);
write_dss_reg(Reg_dispc_timing_h, val);
/*timing logic for VSYNC signal */
val = (1 << Dispc_timing_v_vbp_shift) |
(2 << Dispc_timing_v_vfp_shift) |
(1 << Dispc_timing_v_vsw_shift) ;
write_dss_reg(Reg_dispc_timing_v, val);
/*signal configuration*/
val = read_dss_reg(Reg_dispc_pol_freq);
val |= (0 << Dispc_pol_freq_rf_shift) |
(1 << Dispc_pol_freq_onoff_shift) |
(1 << Dispc_pol_freq_ipc_shift) |
(1 << Dispc_pol_freq_ihs_shift) |
(1 << Dispc_pol_freq_ivs_shift);
write_dss_reg(Reg_dispc_pol_freq, val);
/*configure the divisor*/
//val = (1 << Dispc_divisor_lcd_shift) | (3 << Dispc_divisor_pcd_shift);
//write_dss_reg(Dispc_divisor, val);
write_dss_reg(Reg_dispc_divisor, 0x10012);
/* Set panel size */
val = (((width() - 1) << Dispc_size_lcd_ppl_shift) & Dispc_size_lcd_ppl) |
(((height() - 1) << Dispc_size_lcd_lpp_shift) & Dispc_size_lcd_lpp);
write_dss_reg(Reg_dispc_size_lcd, val);
/* Set tft interface width */
val = read_dss_reg(Reg_dispc_control);
val &= ~Dispc_control_tftdatalines_oalsb16b;
val |= Dispc_control_tftdatalines_oalsb18b;
write_dss_reg(Reg_dispc_control, val);
/* Configure Graphics Window. */
write_dss_reg(Reg_dispc_gfx_ba0, frame_buffer);
write_dss_reg(Reg_dispc_gfx_ba1, frame_buffer);
write_dss_reg(Reg_dispc_gfx_position, 0);
val = (((width() - 1) << Dispc_gfx_size_ppl_shift) & Dispc_gfx_size_ppl) |
(((height() - 1) << Dispc_gfx_size_lpp_shift) & Dispc_gfx_size_lpp);
write_dss_reg(Reg_dispc_gfx_size, val);
val = read_dss_reg(Reg_dispc_gfx_attributes);
val |= (RGB16 << 1);
write_dss_reg(Reg_dispc_gfx_attributes, val);
val = (252 << Dispc_gfx_fifo_threshold_high_shift) |
(192 << Dispc_gfx_fifo_threshold_low_shift);
write_dss_reg(Reg_dispc_gfx_fifo_threshold, val);
/* Default row inc = 1. */
write_dss_reg(Reg_dispc_gfx_row_inc, 1);
/* Default pixel inc = 1. */
write_dss_reg(Reg_dispc_gfx_pixel_inc, 1);
/* Enable GFX pipeline */
val = read_dss_reg(Reg_dispc_gfx_attributes);
val |= Attributes_enable;
write_dss_reg(Reg_dispc_gfx_attributes, val);
}
static void configure_dss_beagleboard(l4_addr_t frame_buffer)
{
// for beagleboard just set the framebuffer address and let it run,
// everything else is already configured by U-Boot
write_dss_reg(Reg_dispc_gfx_ba0, frame_buffer);
write_dss_reg(Reg_dispc_gfx_ba1, frame_buffer);
}
static void configure_dss(l4_addr_t frame_buffer)
{
if (is_omap3evm())
configure_dss_omap3evm(frame_buffer);
if (is_beagleboard())
configure_dss_beagleboard(frame_buffer);
printf("[LCD] Info: Configured display controller.\n");
}
static void display_lcd_image(void)
{
if (is_omap3evm())
{
l4_umword_t val;
/* Lcd output enabled, active display, 16-bit output */
val = Dispc_control_gpout1 |
Dispc_control_gpout0 |
Dispc_control_tftdatalines_oalsb18b |
Dispc_control_stntft |
Dispc_control_lcdenable;
val &= ~Dispc_control_rfbimode;
write_dss_reg(Reg_dispc_control, val);
}
issue_go_lcd();
}
static int configure_lcd(l4_addr_t frame_buffer)
{
#if 0
if (is_omap3evm())
{
reset_display_controller();
if (enable_lcd_backlight())
return -1;
if (enable_lcd_power())
return -1;
if (configure_vga_mode())
return -1;
disable_lcd_reset();
enable_lcd_HVIF();
enable_lcd_reset();
enable_INI();
configure_vert_scan_direction(CONV_SCAN_DIRECTION);
configure_horiz_scan_direction(CONV_SCAN_DIRECTION);
}
#endif
configure_dss(frame_buffer);
//enable_replication_logic(GFX_PIPELINE);
display_lcd_image();
return 0;
}
static
int clcd_init(void)
{
if (is_omap3evm())
{
vbus = l4re_env_get_cap("vbus");
if (l4_is_invalid_cap(vbus))
{
printf("[LCD] Error: Could not query <vbus> capability\n");
return -1;
}
if (l4vbus_get_device_by_hid(vbus, 0, &i2c_handle, "i2c", 0, 0))
{
printf("[LCD] Error: Could not find <i2c> vbus device\n");
return -1;
}
if (l4vbus_get_device_by_hid(vbus, 0, &gpio_handle, "gpio", 0, 0))
{
printf("[LCD] Error: Could not find <gpio> vbus device\n");
return -L4_ENODEV;
}
}
return configure_lcd(fb_paddr);
}
static void setup_memory(void)
{
int ret;
l4re_dma_space_t dma;
l4_size_t phys_size;
if (fb_vaddr)
return;
ret = l4io_request_iomem(0x48050000, 0x1000, 0, &omap_dss_virt_base);
if (ret)
{
printf("[LCD] Error: Could not map device memory\n");
return;
}
// get some frame buffer
l4re_ds_t mem = l4re_util_cap_alloc();
if (l4_is_invalid_cap(mem))
return;
if (l4re_ma_alloc(fbmem_size(), mem, L4RE_MA_CONTINUOUS | L4RE_MA_PINNED))
{
printf("[LCD] Error: Could not allocate memory\n");
return;
}
fb_vaddr = 0;
if (l4re_rm_attach(&fb_vaddr, fbmem_size(),
L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_EAGER_MAP | L4RE_RM_F_RW,
mem, 0, L4_PAGESHIFT))
{
printf("[LCD] Error: Could not attach memory\n");
return;
}
printf("[LCD] Info: Video memory is at virtual %p (size: 0x%x Bytes)\n",
fb_vaddr, fbmem_size());
// get physical address
dma = l4re_util_cap_alloc();
if (l4_is_invalid_cap(dma))
{
printf("error: failed to allocate DMA space capability.\n");
return;
}
if (l4_error(l4_factory_create(l4re_global_env->mem_alloc,
L4RE_PROTO_DMA_SPACE, dma)))
{
printf("error: failed to create DMA space\n");
return;
}
phys_size = fbmem_size();
// get physical address
if (l4re_dma_space_map(dma, mem | L4_CAP_FPAGE_RW, 0, &phys_size, 0,
L4RE_DMA_SPACE_BIDIRECTIONAL, &fb_paddr)
|| phys_size != fbmem_size())
{
printf("[LCD] Error: Could not get physical address\n");
return;
}
printf("[LCD] Info: Physical video memory is at %llx\n", fb_paddr);
}
static int lcd_probe(const char *configstr)
{
lcd_mode = MODE_BEAGLEBOARD;
if (configstr &&
(strstr(configstr, "evm")
|| strstr(configstr, "init")))
lcd_mode = MODE_EVM;
return !l4io_lookup_device("OMAP_LCD", NULL, 0, 0);
}
static void *lcd_get_fb(void)
{
if (!fb_vaddr)
setup_memory();
return fb_vaddr;
}
static unsigned int lcd_fbmem_size(void) { return fbmem_size(); }
static const char *lcd_get_info(void)
{
if (is_beagleboard())
return "ARM OMAP3 Beagleboard LCD";
if (is_omap3evm())
return "ARM OMAP3EVM LCD";
return "ARM OMAP3EVM unknown";
}
static int get_fbinfo(l4re_video_view_info_t *vinfo)
{
vinfo->width = width();
vinfo->height = height();
vinfo->bytes_per_line = bytes_per_pixel() * vinfo->width;
vinfo->pixel_info.bytes_per_pixel = bytes_per_pixel();
vinfo->pixel_info.r.shift = 11;
vinfo->pixel_info.r.size = 5;
vinfo->pixel_info.g.shift = 5;
vinfo->pixel_info.g.size = 6;
vinfo->pixel_info.b.shift = 0;
vinfo->pixel_info.b.size = 5;
vinfo->pixel_info.a.shift = 0;
vinfo->pixel_info.a.size = 0;
return 0;
}
static void lcd_enable(void)
{
setup_memory();
if (clcd_init())
{
printf("CLCD init failed!\n");
return;
}
}
static void lcd_disable(void)
{
printf("%s unimplemented.\n", __func__);
}
static struct arm_lcd_ops arm_lcd_ops_omap3 = {
.probe = lcd_probe,
.get_fb = lcd_get_fb,
.get_fbinfo = get_fbinfo,
.get_video_mem_size = lcd_fbmem_size,
.get_info = lcd_get_info,
.enable = lcd_enable,
.disable = lcd_disable,
};
arm_lcd_register(&arm_lcd_ops_omap3);

View File

@@ -0,0 +1,160 @@
#pragma once
enum
{
Reg_dss_control = 0x40,
};
enum
{
Reg_dispc_revision = 0x400,
Reg_dispc_sysconfig = 0x410,
Reg_dispc_sysstatus = 0x414,
Reg_dispc_irqstatus = 0x418,
Reg_dispc_irqenable = 0x41C,
Reg_dispc_control = 0x440,
Reg_dispc_config = 0x444,
Reg_dispc_capable = 0x448,
Reg_dispc_default_colour0 = 0x44C,
Reg_dispc_default_colour1 = 0x450,
Reg_dispc_trans_colour0 = 0x454,
Reg_dispc_trans_colour1 = 0x458,
Reg_dispc_line_status = 0x45C,
Reg_dispc_line_number = 0x460,
Reg_dispc_timing_h = 0x464,
Reg_dispc_timing_v = 0x468,
Reg_dispc_pol_freq = 0x46C,
Reg_dispc_divisor = 0x470,
Reg_dispc_size_dig = 0x478,
Reg_dispc_size_lcd = 0x47C,
Reg_dispc_gfx_ba0 = 0x480,
Reg_dispc_gfx_ba1 = 0x484,
Reg_dispc_gfx_position = 0x488,
Reg_dispc_gfx_size = 0x48C,
Reg_dispc_gfx_attributes = 0x4A0,
Reg_dispc_gfx_fifo_threshold = 0x4A4,
Reg_dispc_gfx_fifo_size_status = 0x4A8,
Reg_dispc_gfx_row_inc = 0x4AC,
Reg_dispc_gfx_pixel_inc = 0x4B0,
Reg_dispc_gfx_window_skip = 0x4B4,
Reg_dispc_gfx_table_ba = 0x4B8,
};
enum
{
Default_colour_mask = 0x0FFFFFF,
Transparency_colour_mask = 0x0FFFFFF,
X_pos_mask = 0x00007FF,
Y_pos_mask = 0x00007FF,
Pixel_inc_mask = 0x000FFFF,
Attributes_enable = (1 << 0),
};
/* DISPC_CONTROL register fields. */
#define Dispc_control_gpout1 (1 << 16)
#define Dispc_control_gpout0 (1 << 15)
#define Dispc_control_rfbimode (1 << 11)
#define Dispc_control_tftdatalines_oalsb24b (3 << 8)
#define Dispc_control_tftdatalines_oalsb18b (2 << 8)
#define Dispc_control_tftdatalines_oalsb16b (1 << 8)
#define Dispc_control_godigital (1 << 6)
#define Dispc_control_golcd (1 << 5)
#define Dispc_control_stntft (1 << 3)
#define Dispc_control_digitalenable (1 << 1)
#define Dispc_control_lcdenable (1 << 0)
/* DISPC_SYSCONFIG register fields. */
#define Dispc_sysconfig_midlemode_nstandby (1 << 12)
#define Dispc_sysconfig_sidlemode_nidle (1 << 3)
#define Dispc_sysconfig_softreset (1 << 1)
/* DISPC_SYSSTATUS register field. */
#define Dispc_sysstatus_resetdone (1 << 0)
/* DISPC_CONFIG register fields. */
#define Dispc_config_palettegammatable (1 << 3)
#define Dispc_config_loadmode_frdatlefr (1 << 2)
#define Dispc_config_loadmode_pgtabusetb (1 << 1)
/* DISPC_TIMING_H register fields. */
#define Dispc_timing_h_hbp_shift (20)
#define Dispc_timing_h_hfp_shift (8)
#define Dispc_timing_h_hsw_shift (0)
/* DISPC_TIMING_V register fields. */
#define Dispc_timing_v_vbp_shift (20)
#define Dispc_timing_v_vfp_shift (8)
#define Dispc_timing_v_vsw_shift (0)
/* DISPC_POL_FREQ register fields. */
#define Dispc_pol_freq_ihs (1 << 13)
#define Dispc_pol_freq_rf_shift (16)
#define Dispc_pol_freq_onoff_shift (17)
#define Dispc_pol_freq_ipc_shift (14)
#define Dispc_pol_freq_ihs_shift (13)
#define Dispc_pol_freq_ivs_shift (12)
/* DISPC_DIVISOR. */
#define Dispc_divisor_lcd_shift (16)
#define Dispc_divisor_pcd_shift (0)
/* DISPC_SIZE_LCD register fields. */
#define Dispc_size_lcd_lpp (0x7FF << 16)
#define Dispc_size_lcd_lpp_shift (16)
#define Dispc_size_lcd_ppl (0x7FF)
#define Dispc_size_lcd_ppl_shift (0)
/* DISPC_GFX_SIZE register fields. */
#define Dispc_gfx_size_lpp (0x7FF << 16)
#define Dispc_gfx_size_lpp_shift (16)
#define Dispc_gfx_size_ppl (0x7FF)
#define Dispc_gfx_size_ppl_shift (0)
/* DISPC_ATTRIBUTES register fields. */
#define Dispc_attributes_gfxenable (1 << 0)
#define Dispc_gfx_attributes_replication_en (1 << 5)
#define Dispc_vid_attributes_replication_en (1 << 10)
/* DISPC_GFX_FIFO_THRESHOLD register fields. */
#define Dispc_gfx_fifo_threshold_high_shift (16)
#define Dispc_gfx_fifo_threshold_low_shift (0)
#define Dispc_fifo_threshold_high (225)
#define Dispc_fifo_threshold_low (194)
/* DISPC_IRQSTATUS registerr fields. */
#define Dispc_irqstatus_framedone (1 << 0)
/* Image Formats. */
#define BITMAP1 (0x0)
#define BITMAP2 (0x1)
#define BITMAP4 (0x2)
#define BITMAP8 (0x3)
#define RGB12 (0x4)
#define RGB16 (0x6)
#define RGB24 (0x8)
#define YUV422 (0xA)
#define UYVY422 (0xB)
#define GPIO_NUM_RESB 155
#define GPIO_NUM_QVGA_nVGA 154
#define GPIO_NUM_VDD 153
#define GPIO_NUM_INI 152
#define GPIO_NUM_LR 2
#define GPIO_NUM_UD 3
#define CONV_SCAN_DIRECTION 1
#define INVR_SCAN_DIRECTION 0
#define T2_I2C_LED_ADDR_GROUP 0x4a
#define T2_I2C_XXX_ADDR_GROUP 0x4b
/* Triton2 power module registers */
#define TRITON2_LED_LEDEN_REG 0xee
#define TRITON2_LED_PWMAON_REG 0xef
#define TRITON2_LED_PWMAOFF_REG 0xf0
#define TRITON2_LED_PWMBON_REG 0xf1
#define TRITON2_LED_PWMBOFF_REG 0xf2
#define TRITON2_VDAC_DEDICATED 0x91
#define TRITON2_VDAC_DEV_GRP 0x8e

View File

@@ -0,0 +1,260 @@
/*
* LCD driver for s3c2410
*/
#include <l4/drivers/lcd.h>
#include <stdlib.h>
#include <stdio.h>
#include <l4/sys/factory.h>
#include <l4/re/c/dataspace.h>
#include <l4/re/c/rm.h>
#include <l4/re/c/util/cap_alloc.h>
#include <l4/re/c/mem_alloc.h>
#include <l4/re/c/dma_space.h>
#include <l4/re/protocols.h>
#include <l4/io/io.h>
#define LCD_NAME "LCD s3c2410"
static void *fb_vaddr;
static l4re_dma_space_dma_addr_t fb_paddr;
enum {
LCDCON1 = 0x00,
LCDCON2 = 0x04,
LCDCON3 = 0x08,
LCDCON4 = 0x0c,
LCDCON5 = 0x10,
LCDSADDR1 = 0x14,
LCDSADDR2 = 0x18,
LCDSADDR3 = 0x1c,
WIDTH = 480,
HEIGHT = 640,
LCDCON1_ENABLE_BIT = 1,
LCDCON1_BPPMODE_16BPP = 0xc << 1,
LCDCON1_PNRMODE_LCD = 3 << 5,
LCDCON1_CLKVAL = 0,
LCDCON1_ENABLE_VALUE = LCDCON1_ENABLE_BIT | LCDCON1_BPPMODE_16BPP
| LCDCON1_PNRMODE_LCD | LCDCON1_CLKVAL,
LCDCON2_LINEVAL = (HEIGHT-1) << 14,
LCDCON2_ENABLE_VALUE = LCDCON2_LINEVAL,
LCDCON3_HOZVAL = (WIDTH-1) << 8,
LCDCON3_ENABLE_VALUE = LCDCON3_HOZVAL,
LCDCON4_ENABLE_VALUE = 7,
LCDCON5_PWREN = 1 << 3,
LCDCON5_FRM565 = 1 << 11,
LCDCON5_ENABLE_VALUE = LCDCON5_PWREN | LCDCON5_FRM565 | 1,
// wr(0x00000179 & ~LCDCON1_ENABLE_BIT, LCDCON1);
// wr(0x019fc3c1, LCDCON2);
// wr(0x0039df67, LCDCON3);
// wr(0x00000007, LCDCON4);
// wr(0x00000f09, LCDCON5);
};
static const char *arm_lcd_get_info(void)
{ return "S3C2410"; }
static int probe(const char *configstr)
{
(void)configstr;
return !l4io_lookup_device(LCD_NAME, NULL, 0, 0);
}
static unsigned int fbmem_size(void) { return (1 << 22); } //height() * bpl(); }
static unsigned long lcd_control_virt_base;
static int get_fbinfo(l4re_video_view_info_t *vinfo)
{
vinfo->width = 480;
vinfo->width = 640;
vinfo->bytes_per_line = 2 * vinfo->width;
vinfo->pixel_info.bytes_per_pixel = 2;
vinfo->pixel_info.r.shift = 0;
vinfo->pixel_info.r.size = 5;
vinfo->pixel_info.g.shift = 5;
vinfo->pixel_info.g.size = 6;
vinfo->pixel_info.b.shift = 11;
vinfo->pixel_info.b.size = 5;
vinfo->pixel_info.a.shift = 0;
vinfo->pixel_info.a.size = 0;
return 0;
}
static void setup_memory(void)
{
l4re_dma_space_t dma;
l4_size_t phys_size;
l4io_device_handle_t dh;
l4io_resource_handle_t hdl;
if (fb_vaddr)
return;
if (l4io_lookup_device(LCD_NAME, &dh, 0, &hdl))
{
printf("Could not get s3c2410fb\n");
return;
}
lcd_control_virt_base = l4io_request_resource_iomem(dh, &hdl);
if (lcd_control_virt_base == 0)
{
printf("Could not map controller space for '%s'\n", arm_lcd_get_info());
return;
}
// get some frame buffer
l4re_ds_t mem = l4re_util_cap_alloc();
if (l4_is_invalid_cap(mem))
return;
if (l4re_ma_alloc(fbmem_size(), mem, L4RE_MA_CONTINUOUS | L4RE_MA_PINNED))
{
printf("Could not get video memory.\n");
return;
}
fb_vaddr = 0;
if (l4re_rm_attach(&fb_vaddr, fbmem_size(),
L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_EAGER_MAP | L4RE_RM_F_RW,
mem, 0, L4_PAGESHIFT))
{
printf("Could not map fb\n");
return;
}
printf("Video memory is at virtual %p (size: 0x%x Bytes)\n",
fb_vaddr, fbmem_size());
// get physical address
dma = l4re_util_cap_alloc();
if (l4_is_invalid_cap(dma))
{
printf("error: failed to allocate DMA space capability.\n");
return;
}
if (l4_error(l4_factory_create(l4re_global_env->mem_alloc,
L4RE_PROTO_DMA_SPACE, dma)))
{
printf("error: failed to create DMA space\n");
return;
}
phys_size = fbmem_size();
// get physical address
if (l4re_dma_space_map(dma, mem | L4_CAP_FPAGE_RW, 0, &phys_size, 0,
L4RE_DMA_SPACE_BIDIRECTIONAL, &fb_paddr)
|| phys_size != fbmem_size())
{
printf("Getting the physical address failed or not contiguous\n");
return;
}
printf("Physical video memory is at %llx\n", fb_paddr);
}
static inline void wr(unsigned long val, unsigned long regoff)
{ *(volatile unsigned long *)(lcd_control_virt_base + regoff) = val; }
static inline unsigned long rd(unsigned long regoff)
{ return *(volatile unsigned long *)(lcd_control_virt_base + regoff); }
static void *fb(void)
{
if (!fb_vaddr)
setup_memory();
return fb_vaddr;
}
#if 0
s3c2410fb: devinit
s3c2410fb: got LCD region
s3c2410fb: got and enabled clock
s3c2410fb: map_video_memory(fbi=c04ce274)
s3c2410fb: map_video_memory: clear ffc00000:0012c000
s3c2410fb: map_video_memory: dma=30600000 cpu=ffc00000 size=0012c000
s3c2410fb: got video memory
s3c2410fb: LCDSADDR1 = 0x18300000
s3c2410fb: LCDSADDR2 = 0x1834b000
s3c2410fb: LCDSADDR3 = 0x000001e0
s3c2410fb: LPCSEL = 0x00000cf0
s3c2410fb: replacing TPAL 00000000
s3c2410fb: check_var(var=c04ce008, info=c04ce000)
s3c2410fb: s3c2410fb_activate_var: var->xres = 480
s3c2410fb: s3c2410fb_activate_var: var->yres = 640
s3c2410fb: s3c2410fb_activate_var: var->bpp = 16
s3c2410fb: setting vert: up=2, low=16, sync=2
s3c2410fb: setting horz: lft=104, rt=8, sync=8
s3c2410fb: new register set:
s3c2410fb: lcdcon[1] = 0x00000179
s3c2410fb: lcdcon[2] = 0x019fc3c1
s3c2410fb: lcdcon[3] = 0x0039df67
s3c2410fb: lcdcon[4] = 0x00000007
s3c2410fb: lcdcon[5] = 0x00000f09
s3c2410fb: LCDSADDR1 = 0x18300000
s3c2410fb: LCDSADDR2 = 0x1834b000
s3c2410fb: LCDSADDR3 = 0x000001e0
Console: switching to colour frame buffer device 80x58
fb0: s3c2410fb frame buffer device
#endif
static void pl110_enable(void)
{
setup_memory();
wr(0x00000179 & ~LCDCON1_ENABLE_BIT, LCDCON1);
wr(0x019fc3c1, LCDCON2);
wr(0x0039df67, LCDCON3);
wr(0x00000007, LCDCON4);
wr(0x00000f09, LCDCON5);
#if 0
wr(LCDCON1_ENABLE_VALUE & ~LCDCON1_ENABLE_BIT, LCDCON1);
wr(LCDCON2_ENABLE_VALUE, LCDCON2);
wr(LCDCON3_ENABLE_VALUE, LCDCON3);
wr(LCDCON4_ENABLE_VALUE, LCDCON4);
wr(LCDCON5_ENABLE_VALUE, LCDCON5);
#endif
wr(fb_paddr >> 1, LCDSADDR1);
wr((fb_paddr + 640*480*2) >> 1, LCDSADDR2);
wr(480, LCDSADDR3);
wr(0x00000179, LCDCON1);
{
// int i = 0;
// for (; i < 0x20; i+=4)
// printf("%02x: %08lx\n", i, rd(i));
}
}
static void pl110_disable(void)
{
}
static struct arm_lcd_ops arm_lcd_ops_pl110 = {
.probe = probe,
.get_fb = fb,
.get_fbinfo = get_fbinfo,
.get_video_mem_size = fbmem_size,
.get_info = arm_lcd_get_info,
.enable = pl110_enable,
.disable = pl110_disable,
};
arm_lcd_register(&arm_lcd_ops_pl110);

View File

@@ -0,0 +1,106 @@
/*
* Tegra2 FB driver (just pass-through, must be init'ed by boot-loader)
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <l4/drivers/lcd.h>
#include <l4/io/io.h>
#include <l4/util/util.h>
static inline int width(void) { return 1280; }
static inline int height(void) { return 1024; }
static inline int bytes_per_pixel(void) { return 2; }
static unsigned int fbmem_size(void)
{ return height() * width() * bytes_per_pixel(); }
static void *fb_vaddr;
static void setup_memory(void)
{
l4_addr_t fb_paddr;
l4_addr_t a = 0;
int ret;
if (fb_vaddr)
return;
fb_paddr = 0x1c012000;
ret = l4io_request_iomem(fb_paddr, 0x500000, 0, &a);
if (ret)
{
printf("[LCD] Error: Could not map device memory\n");
return;
}
fb_vaddr = (void *)a;
printf("[LCD] Info: Video memory is at virtual %p (size: 0x%x Bytes)\n",
fb_vaddr, fbmem_size());
printf("[LCD] Info: Physical video memory is at %p\n", (void *)fb_paddr);
}
static int lcd_probe(const char *configstr)
{
(void)configstr;
return !l4io_lookup_device("FBMEM", NULL, 0, 0);
}
static void *lcd_get_fb(void)
{
if (!fb_vaddr)
setup_memory();
return fb_vaddr;
}
static unsigned int lcd_fbmem_size(void) { return fbmem_size(); }
static const char *lcd_get_info(void)
{
return "TEGRA2 FASTBOOT init'ed FB";
}
static int get_fbinfo(l4re_video_view_info_t *vinfo)
{
vinfo->width = width();
vinfo->height = height();
vinfo->bytes_per_line = bytes_per_pixel() * vinfo->width;
vinfo->pixel_info.bytes_per_pixel = bytes_per_pixel();
vinfo->pixel_info.r.shift = 11;
vinfo->pixel_info.r.size = 5;
vinfo->pixel_info.g.shift = 5;
vinfo->pixel_info.g.size = 6;
vinfo->pixel_info.b.shift = 0;
vinfo->pixel_info.b.size = 5;
vinfo->pixel_info.a.shift = 0;
vinfo->pixel_info.a.size = 0;
return 0;
}
static void lcd_enable(void)
{
setup_memory();
}
static void lcd_disable(void)
{
printf("%s unimplemented.\n", __func__);
}
static struct arm_lcd_ops arm_lcd_ops_omap3 = {
.probe = lcd_probe,
.get_fb = lcd_get_fb,
.get_fbinfo = get_fbinfo,
.get_video_mem_size = lcd_fbmem_size,
.get_info = lcd_get_info,
.enable = lcd_enable,
.disable = lcd_disable,
};
arm_lcd_register(&arm_lcd_ops_omap3);

View File

@@ -0,0 +1,46 @@
/*
* Dummy LCD driver
*/
#include <l4/drivers/lcd.h>
#include <stdlib.h>
static const char *arm_lcd_none_get_info(void)
{ return "ARM LCD virtual driver"; }
static void void_dummy(void) {}
static int probe(const char *c) { (void)c; return 0; }
static unsigned int mem_size(void) { return 200 * 320 * 4; }
static void *fb(void) { return malloc(mem_size()); }
static int get_fbinfo(l4re_video_view_info_t *vinfo)
{
vinfo->width = 320;
vinfo->width = 200;
vinfo->bytes_per_line = 4 * vinfo->width;
vinfo->pixel_info.bytes_per_pixel = 4;
vinfo->pixel_info.r.shift = 0;
vinfo->pixel_info.r.size = 8;
vinfo->pixel_info.g.shift = 8;
vinfo->pixel_info.g.size = 8;
vinfo->pixel_info.b.shift = 16;
vinfo->pixel_info.b.size = 8;
vinfo->pixel_info.a.shift = 0;
vinfo->pixel_info.a.size = 0;
return 0;
}
static struct arm_lcd_ops arm_lcd_ops_virtual = {
.probe = probe,
.get_fbinfo = get_fbinfo,
.get_fb = fb,
.get_video_mem_size = mem_size,
.get_info = arm_lcd_none_get_info,
.enable = void_dummy,
.disable = void_dummy,
};
arm_lcd_register(&arm_lcd_ops_virtual);

View File

@@ -0,0 +1,26 @@
/*
* Some generic functions for LCD drivers.
*/
#include <l4/drivers/lcd.h>
enum { nr_drivers = 10 };
static struct arm_lcd_ops *ops[nr_drivers];
static int ops_alloced;
struct arm_lcd_ops *arm_lcd_probe(const char *configstr)
{
int i;
for (i = 0; i < ops_alloced; i++)
if (ops[i]->probe && ops[i]->probe(configstr))
return ops[i];
return NULL;
}
void arm_lcd_register_driver(struct arm_lcd_ops *_ops)
{
if (ops_alloced < nr_drivers)
ops[ops_alloced++] = _ops;
}