1.1: Initial commit

This commit is contained in:
Arif Ali 2011-11-06 23:26:22 +00:00
parent ea15405e85
commit 2e6545f612
466 changed files with 69344 additions and 0 deletions

BIN
bin/NBMerge.exe Normal file

Binary file not shown.

BIN
bin/osnbtool.exe Normal file

Binary file not shown.

BIN
bin/template_os.nb.payload Normal file

Binary file not shown.

BIN
bin/yang.exe Normal file

Binary file not shown.

55
compile Normal file
View File

@ -0,0 +1,55 @@
#!/bin/bash
#use codesourcery toolchain
TOOLCHAIN_PREFIX=arm-none-eabi-
export TOOLCHAIN_PREFIX
if [ "$1" = "clean" ]; then
rm -rf lk/build-htcleo
rm bin/nbfix
rm bin/lk.bin
rm bin/tinboot
rm tinboot/tinboot
rm tinboot/tinboot.o
rm bin/os.nb.payload
rm bin/os.nb
rm bin/RUU_signed.nbh
fi
TOOLCHAIN_PREFIX="arm-none-eabi-"
export TOOLCHAIN_PREFIX
if [ ! -f bin/nbfix ]; then
gcc nbfix.c -o bin/nbfix
fi
if [ ! -f bin/lk.bin ]; then
cd lk
make htcleo EMMC_BOOT=0 DEBUG=1
[ $? -eq 0 ] || exit 1
cp build-htcleo/lk.bin ../bin/
cd ..
fi
if [ ! -f bin/tinboot ]; then
cd tinboot
${TOOLCHAIN_PREFIX}as tinboot.S -o tinboot.o
${TOOLCHAIN_PREFIX}objcopy tinboot.o -O binary tinboot
cp tinboot ../bin/
cd ..
fi
if [ ! -f bin/RUU_signed.nbh ]; then
cd bin
cp template_os.nb.payload os.nb.payload
wine osnbtool.exe -c os.nb.payload 0 tinboot
mv os.nb.payload.NEW os.nb.payload
./nbfix
wine NBMerge.exe -kaiser os.nb
wine yang.exe -F RUU_signed.nbh -f os.nb -t 0x400 -s 64 -d PB8110000 -c 11111111 -v CLK1.1 -l WWE
cd ..
fi

66
lk/AndroidBoot.mk Normal file
View File

@ -0,0 +1,66 @@
#Android makefile to build lk bootloader as a part of Android Build
TARGET_BOOTLOADER := $(PRODUCT_OUT)/appsboot.mbn
BOOTLOADER_OUT := $(TOP)/$(TARGET_OUT_INTERMEDIATES)/BOOTLOADER_OBJ
# Force GCC 4.4.0 crosstool chain for Android builds
CROSS_TOOL := ../../../prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi-
# Remove bootloader binary to trigger recompile when source changes
appsbootldr_clean:
$(hide) rm -f $(TARGET_BOOTLOADER)
$(hide) rm -rf $(BOOTLOADER_OUT)
$(BOOTLOADER_OUT):
mkdir -p $(BOOTLOADER_OUT)
TARGET_EMMC := 0
ifeq ($(TARGET_USERIMAGES_USE_EXT2),true)
TARGET_EMMC := 1
endif
ifeq ($(TARGET_USERIMAGES_USE_EXT3),true)
TARGET_EMMC := 1
endif
ifeq ($(TARGET_USERIMAGES_USE_EXT4),true)
TARGET_EMMC := 1
endif
ifeq ($(TARGET_EMMC),1)
TARGET_BOOTLOADER_EMMC := $(PRODUCT_OUT)/EMMCBOOT.MBN
BOOTLOADER_EMMC_OUT := $(TOP)/$(TARGET_OUT_INTERMEDIATES)/BOOTLOADER_EMMC_OBJ
emmc_appsbootldr_clean:
$(hide) rm -f $(TARGET_BOOTLOADER_EMMC)
$(hide) rm -rf $(BOOTLOADER_EMMC_OUT)
$(BOOTLOADER_EMMC_OUT):
mkdir -p $(BOOTLOADER_EMMC_OUT)
$(TARGET_BOOTLOADER): appsbootldr_clean emmc_appsbootldr_clean $(BOOTLOADER_OUT) $(BOOTLOADER_EMMC_OUT)
$(MAKE) -C bootable/bootloader/lk TOOLCHAIN_PREFIX=$(CROSS_TOOL) BOOTLOADER_OUT=../../../$(BOOTLOADER_OUT) $(TARGET_PRODUCT)
$(MAKE) -C bootable/bootloader/lk TOOLCHAIN_PREFIX=$(CROSS_TOOL) BOOTLOADER_OUT=../../../$(BOOTLOADER_EMMC_OUT) $(TARGET_PRODUCT) EMMC_BOOT=1
else
$(TARGET_BOOTLOADER): appsbootldr_clean $(BOOTLOADER_OUT)
$(MAKE) -C bootable/bootloader/lk TOOLCHAIN_PREFIX=$(CROSS_TOOL) BOOTLOADER_OUT=../../../$(BOOTLOADER_OUT) $(TARGET_PRODUCT)
endif
#build nandwrite as a part of Android Build
TARGET_NANDWRITE := $(PRODUCT_OUT)/obj/nandwrite/build-$(TARGET_PRODUCT)_nandwrite/lk
NANDWRITE_OUT := $(TOP)/$(TARGET_OUT_INTERMEDIATES)/nandwrite
nandwrite_clean:
$(hide) rm -f $(TARGET_NANDWRITE)
$(hide) rm -rf $(NANDWRITE_OUT)
$(NANDWRITE_OUT):
mkdir -p $(NANDWRITE_OUT)
$(TARGET_NANDWRITE): nandwrite_clean $(NANDWRITE_OUT)
@echo $(TARGET_PRODUCT)_nandwrite
$(MAKE) -C bootable/bootloader/lk TOOLCHAIN_PREFIX=$(CROSS_TOOL) BOOTLOADER_OUT=../../../$(NANDWRITE_OUT) $(TARGET_PRODUCT)_nandwrite BUILD_NANDWRITE=1

735
lk/app/aboot/aboot.c Normal file
View File

@ -0,0 +1,735 @@
/*
* Copyright (c) 2009, Google Inc.
* All rights reserved.
*
* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Code Aurora nor
* the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <app.h>
#include <debug.h>
#include <arch/arm.h>
#include <dev/udc.h>
#include <string.h>
#include <kernel/thread.h>
#include <arch/ops.h>
#include <dev/flash.h>
#include <lib/ptable.h>
#include <dev/keys.h>
#include <dev/fbcon.h>
#include "recovery.h"
#include "bootimg.h"
#include "fastboot.h"
#define EXPAND(NAME) #NAME
#define TARGET(NAME) EXPAND(NAME)
#define DEFAULT_CMDLINE "console=null";
#ifdef MEMBASE
#define EMMC_BOOT_IMG_HEADER_ADDR (0xFF000+(MEMBASE))
#else
#define EMMC_BOOT_IMG_HEADER_ADDR 0xFF000
#endif
#define RECOVERY_MODE 0x77665502
#define FASTBOOT_MODE 0x77665500
static const char *emmc_cmdline = " androidboot.emmc=true";
static const char *battchg_pause = " androidboot.battchg_pause=true";
static struct udc_device surf_udc_device = {
.vendor_id = 0x18d1,
.product_id = 0x0D02,
.version_id = 0x0001,
.manufacturer = "Google",
.product = "Android",
};
struct atag_ptbl_entry
{
char name[16];
unsigned offset;
unsigned size;
unsigned flags;
};
void platform_uninit_timer(void);
unsigned* target_atag_mem(unsigned* ptr);
unsigned board_machtype(void);
unsigned check_reboot_mode(void);
void *target_get_scratch_address(void);
int target_is_emmc_boot(void);
void reboot_device(unsigned);
void target_battery_charging_enable(unsigned enable, unsigned disconnect);
unsigned int mmc_write (unsigned long long data_addr,
unsigned int data_len, unsigned int* in);
unsigned long long mmc_ptn_offset (unsigned char * name);
unsigned long long mmc_ptn_size (unsigned char * name);
void display_shutdown(void);
static void ptentry_to_tag(unsigned **ptr, struct ptentry *ptn)
{
struct atag_ptbl_entry atag_ptn;
if (ptn->type == TYPE_MODEM_PARTITION)
return;
memcpy(atag_ptn.name, ptn->name, 16);
atag_ptn.name[15] = '\0';
atag_ptn.offset = ptn->start;
atag_ptn.size = ptn->length;
atag_ptn.flags = ptn->flags;
memcpy(*ptr, &atag_ptn, sizeof(struct atag_ptbl_entry));
*ptr += sizeof(struct atag_ptbl_entry) / sizeof(unsigned);
}
void boot_linux(void *kernel, unsigned *tags,
const char *cmdline, unsigned machtype,
void *ramdisk, unsigned ramdisk_size)
{
unsigned *ptr = tags;
unsigned pcount = 0;
void (*entry)(unsigned,unsigned,unsigned*) = kernel;
struct ptable *ptable;
int cmdline_len = 0;
int have_cmdline = 0;
int pause_at_bootup = 0;
/* CORE */
*ptr++ = 2;
*ptr++ = 0x54410001;
if (ramdisk_size) {
*ptr++ = 4;
*ptr++ = 0x54420005;
*ptr++ = (unsigned)ramdisk;
*ptr++ = ramdisk_size;
}
ptr = target_atag_mem(ptr);
if (!target_is_emmc_boot()) {
/* Skip NAND partition ATAGS for eMMC boot */
if ((ptable = flash_get_ptable()) && (ptable->count != 0)) {
int i;
for(i=0; i < ptable->count; i++) {
struct ptentry *ptn;
ptn = ptable_get(ptable, i);
if (ptn->type == TYPE_APPS_PARTITION)
pcount++;
}
*ptr++ = 2 + (pcount * (sizeof(struct atag_ptbl_entry) /
sizeof(unsigned)));
*ptr++ = 0x4d534d70;
for (i = 0; i < ptable->count; ++i)
ptentry_to_tag(&ptr, ptable_get(ptable, i));
}
}
if (cmdline && cmdline[0]) {
cmdline_len = strlen(cmdline);
have_cmdline = 1;
}
if (target_is_emmc_boot()) {
cmdline_len += strlen(emmc_cmdline);
}
if (target_pause_for_battery_charge()) {
pause_at_bootup = 1;
cmdline_len += strlen(battchg_pause);
}
if (cmdline_len > 0) {
const char *src;
char *dst;
unsigned n;
/* include terminating 0 and round up to a word multiple */
n = (cmdline_len + 4) & (~3);
*ptr++ = (n / 4) + 2;
*ptr++ = 0x54410009;
dst = (char *)ptr;
if (have_cmdline) {
src = cmdline;
while ((*dst++ = *src++));
}
if (target_is_emmc_boot()) {
src = emmc_cmdline;
if (have_cmdline) --dst;
have_cmdline = 1;
while ((*dst++ = *src++));
}
if (pause_at_bootup) {
src = battchg_pause;
if (have_cmdline) --dst;
while ((*dst++ = *src++));
}
ptr += (n / 4);
}
/* END */
*ptr++ = 0;
*ptr++ = 0;
dprintf(INFO, "booting linux @ %p, ramdisk @ %p (%d)\n",
kernel, ramdisk, ramdisk_size);
if (cmdline)
dprintf(INFO, "cmdline: %s\n", cmdline);
enter_critical_section();
//cedesmith: this will hang
//platform_uninit_timer();
arch_disable_cache(UCACHE);
arch_disable_mmu();
#if DISPLAY_SPLASH_SCREEN
display_shutdown();
#endif
__asm__ volatile (
"dsb \n"
"isb \n"
);
//cedesmith: cotulla's code so kernel will not crash. aux control register
__asm__ volatile (
"MRC p15, 0, r0, c1, c0, 1 \n"
"BIC r0, r0, #0x40 \n" // (1<<6) Instruction cache reload on a parity error disabled
"BIC r0, r0, #0x200000 \n" // (1<<21) undocumented bit ?
"MCR p15, 0, r0, c1, c0, 1 \n"
);
/*
// flash on to see we get here
__asm__ volatile (
"ldr r4, =0xa9000864 @ bank6_in (phys) \n"
"ldr r5, =0xa9000814 @ bank6_out (phys) \n"
"orr r6, r4, #0x200000 @ 22nd bit for flash \n"
"str r6, [r5, #0] @ store in out (enables bright for 500ms, limited by hardware) \n"
);
*/
entry(0, machtype, tags);
}
unsigned page_size = 0;
unsigned page_mask = 0;
#define ROUND_TO_PAGE(x,y) (((x) + (y)) & (~(y)))
static unsigned char buf[4096]; //Equal to max-supported pagesize
int boot_linux_from_mmc(void)
{
struct boot_img_hdr *hdr = (void*) buf;
struct boot_img_hdr *uhdr;
unsigned offset = 0;
unsigned long long ptn = 0;
unsigned n = 0;
const char *cmdline;
uhdr = (struct boot_img_hdr *)EMMC_BOOT_IMG_HEADER_ADDR;
if (!memcmp(uhdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
dprintf(INFO, "Unified boot method!\n");
hdr = uhdr;
goto unified_boot;
}
if(!boot_into_recovery)
{
ptn = mmc_ptn_offset("boot");
if(ptn == 0) {
dprintf(CRITICAL, "ERROR: No boot partition found\n");
return -1;
}
}
else
{
ptn = mmc_ptn_offset("recovery");
if(ptn == 0) {
dprintf(CRITICAL, "ERROR: No recovery partition found\n");
return -1;
}
}
if (mmc_read(ptn + offset, (unsigned int *)buf, page_size)) {
dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
return -1;
}
if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
dprintf(CRITICAL, "ERROR: Invaled boot image header\n");
return -1;
}
if (hdr->page_size && (hdr->page_size != page_size)) {
page_size = hdr->page_size;
page_mask = page_size - 1;
}
offset += page_size;
n = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
if (mmc_read(ptn + offset, (void *)hdr->kernel_addr, n)) {
dprintf(CRITICAL, "ERROR: Cannot read kernel image\n");
return -1;
}
offset += n;
n = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
if (mmc_read(ptn + offset, (void *)hdr->ramdisk_addr, n)) {
dprintf(CRITICAL, "ERROR: Cannot read ramdisk image\n");
return -1;
}
offset += n;
unified_boot:
dprintf(INFO, "\nkernel @ %x (%d bytes)\n", hdr->kernel_addr,
hdr->kernel_size);
dprintf(INFO, "ramdisk @ %x (%d bytes)\n", hdr->ramdisk_addr,
hdr->ramdisk_size);
if(hdr->cmdline[0]) {
cmdline = (char*) hdr->cmdline;
} else {
cmdline = DEFAULT_CMDLINE;
}
dprintf(INFO, "cmdline = '%s'\n", cmdline);
dprintf(INFO, "\nBooting Linux\n");
boot_linux((void *)hdr->kernel_addr, (void *)TAGS_ADDR,
(const char *)cmdline, board_machtype(),
(void *)hdr->ramdisk_addr, hdr->ramdisk_size);
return 0;
}
int boot_linux_from_flash(void)
{
struct boot_img_hdr *hdr = (void*) buf;
unsigned n;
struct ptentry *ptn;
struct ptable *ptable;
unsigned offset = 0;
const char *cmdline;
if (target_is_emmc_boot()) {
hdr = (struct boot_img_hdr *)EMMC_BOOT_IMG_HEADER_ADDR;
if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
dprintf(CRITICAL, "ERROR: Invalid boot image header\n");
return -1;
}
goto continue_boot;
}
ptable = flash_get_ptable();
if (ptable == NULL) {
dprintf(CRITICAL, "ERROR: Partition table not found\n");
return -1;
}
if(!boot_into_recovery)
{
ptn = ptable_find(ptable, "boot");
if (ptn == NULL) {
dprintf(CRITICAL, "ERROR: No boot partition found\n");
return -1;
}
}
else
{
ptn = ptable_find(ptable, "recovery");
if (ptn == NULL) {
dprintf(CRITICAL, "ERROR: No recovery partition found\n");
return -1;
}
}
if (flash_read(ptn, offset, buf, page_size)) {
dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
return -1;
}
offset += page_size;
if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
dprintf(CRITICAL, "ERROR: Invaled boot image heador\n");
return -1;
}
if (hdr->page_size != page_size) {
dprintf(CRITICAL, "ERROR: Invaled boot image pagesize. Device pagesize: %d, Image pagesize: %d\n",page_size,hdr->page_size);
return -1;
}
n = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
if (flash_read(ptn, offset, (void *)hdr->kernel_addr, n)) {
dprintf(CRITICAL, "ERROR: Cannot read kernel image\n");
return -1;
}
offset += n;
n = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
if (flash_read(ptn, offset, (void *)hdr->ramdisk_addr, n)) {
dprintf(CRITICAL, "ERROR: Cannot read ramdisk image\n");
return -1;
}
offset += n;
continue_boot:
dprintf(INFO, "\nkernel @ %x (%d bytes)\n", hdr->kernel_addr,
hdr->kernel_size);
dprintf(INFO, "ramdisk @ %x (%d bytes)\n", hdr->ramdisk_addr,
hdr->ramdisk_size);
if(hdr->cmdline[0]) {
cmdline = (char*) hdr->cmdline;
} else {
cmdline = DEFAULT_CMDLINE;
}
dprintf(INFO, "cmdline = '%s'\n", cmdline);
/* TODO: create/pass atags to kernel */
dprintf(INFO, "\nBooting Linux\n");
boot_linux((void *)hdr->kernel_addr, (void *)TAGS_ADDR,
(const char *)cmdline, board_machtype(),
(void *)hdr->ramdisk_addr, hdr->ramdisk_size);
return 0;
}
void cmd_boot(const char *arg, void *data, unsigned sz)
{
unsigned kernel_actual;
unsigned ramdisk_actual;
static struct boot_img_hdr hdr;
char *ptr = ((char*) data);
if (sz < sizeof(hdr)) {
fastboot_fail("invalid bootimage header");
return;
}
memcpy(&hdr, data, sizeof(hdr));
/* ensure commandline is terminated */
hdr.cmdline[BOOT_ARGS_SIZE-1] = 0;
if(target_is_emmc_boot() && hdr.page_size) {
page_size = hdr.page_size;
page_mask = page_size - 1;
}
kernel_actual = ROUND_TO_PAGE(hdr.kernel_size, page_mask);
ramdisk_actual = ROUND_TO_PAGE(hdr.ramdisk_size, page_mask);
//cedesmith: this will prevent lk booting lk.bin
//if (page_size + kernel_actual + ramdisk_actual < sz) {
// fastboot_fail("incomplete bootimage");
// return;
//}
memmove((void*) KERNEL_ADDR, ptr + page_size, hdr.kernel_size);
memmove((void*) RAMDISK_ADDR, ptr + page_size + kernel_actual, hdr.ramdisk_size);
fastboot_okay("");
target_battery_charging_enable(0, 1);
udc_stop();
boot_linux((void*) KERNEL_ADDR, (void*) TAGS_ADDR,
(const char*) hdr.cmdline, board_machtype(),
(void*) RAMDISK_ADDR, hdr.ramdisk_size);
}
void cmd_erase(const char *arg, void *data, unsigned sz)
{
struct ptentry *ptn;
struct ptable *ptable;
ptable = flash_get_ptable();
if (ptable == NULL) {
fastboot_fail("partition table doesn't exist");
return;
}
ptn = ptable_find(ptable, arg);
if (ptn == NULL) {
fastboot_fail("unknown partition name");
return;
}
if (flash_erase(ptn)) {
fastboot_fail("failed to erase partition");
return;
}
fastboot_okay("");
}
void cmd_erase_mmc(const char *arg, void *data, unsigned sz)
{
unsigned long long ptn = 0;
unsigned int out[512] = {0};
ptn = mmc_ptn_offset(arg);
if(ptn == 0) {
fastboot_fail("partition table doesn't exist");
return;
}
/* Simple inefficient version of erase. Just writing
0 in first block */
if (mmc_write(ptn , 512, (unsigned int *)out)) {
fastboot_fail("failed to erase partition");
return;
}
fastboot_okay("");
}
void cmd_flash_mmc(const char *arg, void *data, unsigned sz)
{
unsigned long long ptn = 0;
unsigned long long size = 0;
ptn = mmc_ptn_offset(arg);
if(ptn == 0) {
fastboot_fail("partition table doesn't exist");
return;
}
if (!strcmp(arg, "boot") || !strcmp(arg, "recovery")) {
if (memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
fastboot_fail("image is not a boot image");
return;
}
}
size = mmc_ptn_size(arg);
if (ROUND_TO_PAGE(sz,511) > size) {
fastboot_fail("size too large");
return;
}
if (mmc_write(ptn , sz, (unsigned int *)data)) {
fastboot_fail("flash write failure");
return;
}
fastboot_okay("");
return;
}
void cmd_flash(const char *arg, void *data, unsigned sz)
{
struct ptentry *ptn;
struct ptable *ptable;
unsigned extra = 0;
ptable = flash_get_ptable();
if (ptable == NULL) {
fastboot_fail("partition table doesn't exist");
return;
}
ptn = ptable_find(ptable, arg);
if (ptn == NULL) {
fastboot_fail("unknown partition name");
return;
}
if (!strcmp(ptn->name, "boot") || !strcmp(ptn->name, "recovery")) {
if (memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
fastboot_fail("image is not a boot image");
return;
}
}
if (!strcmp(ptn->name, "system") || !strcmp(ptn->name, "userdata")
|| !strcmp(ptn->name, "persist"))
extra = ((page_size >> 9) * 16);
else
sz = ROUND_TO_PAGE(sz, page_mask);
dprintf(INFO, "writing %d bytes to '%s'\n", sz, ptn->name);
if (flash_write(ptn, extra, data, sz)) {
fastboot_fail("flash write failure");
return;
}
dprintf(INFO, "partition '%s' updated\n", ptn->name);
fastboot_okay("");
}
void cmd_continue(const char *arg, void *data, unsigned sz)
{
fastboot_okay("");
target_battery_charging_enable(0, 1);
udc_stop();
if (target_is_emmc_boot())
{
boot_linux_from_mmc();
}
else
{
boot_linux_from_flash();
}
}
void cmd_reboot(const char *arg, void *data, unsigned sz)
{
dprintf(INFO, "rebooting the device\n");
fastboot_okay("");
reboot_device(0);
}
void cmd_reboot_bootloader(const char *arg, void *data, unsigned sz)
{
dprintf(INFO, "rebooting the device\n");
fastboot_okay("");
reboot_device(FASTBOOT_MODE);
}
void splash_screen ()
{
struct ptentry *ptn;
struct ptable *ptable;
struct fbcon_config *fb_display = NULL;
if (!target_is_emmc_boot())
{
ptable = flash_get_ptable();
if (ptable == NULL) {
dprintf(CRITICAL, "ERROR: Partition table not found\n");
return -1;
}
ptn = ptable_find(ptable, "splash");
if (ptn == NULL) {
dprintf(CRITICAL, "ERROR: No splash partition found\n");
} else {
fb_display = fbcon_display();
if (fb_display) {
if (flash_read(ptn, 0, fb_display->base,
(fb_display->width * fb_display->height * fb_display->bpp/8))) {
fbcon_clear();
dprintf(CRITICAL, "ERROR: Cannot read splash image\n");
}
}
}
}
}
void aboot_init(const struct app_descriptor *app)
{
unsigned reboot_mode = 0;
unsigned disp_init = 0;
unsigned usb_init = 0;
/* Setup page size information for nand/emmc reads */
if (target_is_emmc_boot())
{
page_size = 2048;
page_mask = page_size - 1;
}
else
{
page_size = flash_page_size();
page_mask = page_size - 1;
}
/* Display splash screen if enabled */
#if DISPLAY_SPLASH_SCREEN
display_init();
dprintf(INFO, "Diplay initialized\n");
disp_init = 1;
diplay_image_on_screen();
#endif
/* Check if we should do something other than booting up */
if (keys_get_state(KEY_HOME) != 0)
boot_into_recovery = 1;
if (keys_get_state(KEY_BACK) != 0)
goto fastboot;
if (keys_get_state(KEY_CLEAR) != 0)
goto fastboot;
#if NO_KEYPAD_DRIVER
/* With no keypad implementation, check the status of USB connection. */
/* If USB is connected then go into fastboot mode. */
usb_init = 1;
udc_init(&surf_udc_device);
if (usb_cable_status())
goto fastboot;
#endif
reboot_mode = check_reboot_mode();
if (reboot_mode == RECOVERY_MODE) {
boot_into_recovery = 1;
} else if(reboot_mode == FASTBOOT_MODE) {
goto fastboot;
}
if (target_is_emmc_boot())
{
boot_linux_from_mmc();
}
else
{
recovery_init();
boot_linux_from_flash();
}
dprintf(CRITICAL, "ERROR: Could not do normal boot. Reverting "
"to fastboot mode.\n");
fastboot:
if(!usb_init)
udc_init(&surf_udc_device);
fastboot_register("boot", cmd_boot);
if (target_is_emmc_boot())
{
fastboot_register("flash:", cmd_flash_mmc);
fastboot_register("erase:", cmd_erase_mmc);
}
else
{
fastboot_register("flash:", cmd_flash);
fastboot_register("erase:", cmd_erase);
}
fastboot_register("continue", cmd_continue);
fastboot_register("reboot", cmd_reboot);
fastboot_register("reboot-bootloader", cmd_reboot_bootloader);
fastboot_publish("product", TARGET(BOARD));
fastboot_publish("kernel", "lk");
//fastboot_init(target_get_scratch_address(), 120 * 1024 * 1024);
fastboot_init(target_get_scratch_address(), MEMBASE - SCRATCH_ADDR - 0x00100000);
udc_start();
target_battery_charging_enable(1, 0);
}
APP_START(aboot)
.init = aboot_init,
APP_END

97
lk/app/aboot/bootimg.h Normal file
View File

@ -0,0 +1,97 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _BOOT_IMAGE_H_
#define _BOOT_IMAGE_H_
typedef struct boot_img_hdr boot_img_hdr;
#define BOOT_MAGIC "ANDROID!"
#define BOOT_MAGIC_SIZE 8
#define BOOT_NAME_SIZE 16
#define BOOT_ARGS_SIZE 512
struct boot_img_hdr
{
unsigned char magic[BOOT_MAGIC_SIZE];
unsigned kernel_size; /* size in bytes */
unsigned kernel_addr; /* physical load addr */
unsigned ramdisk_size; /* size in bytes */
unsigned ramdisk_addr; /* physical load addr */
unsigned second_size; /* size in bytes */
unsigned second_addr; /* physical load addr */
unsigned tags_addr; /* physical addr for kernel tags */
unsigned page_size; /* flash page size we assume */
unsigned unused[2]; /* future expansion: should be 0 */
unsigned char name[BOOT_NAME_SIZE]; /* asciiz product name */
unsigned char cmdline[BOOT_ARGS_SIZE];
unsigned id[8]; /* timestamp / checksum / sha1 / etc */
};
/*
** +-----------------+
** | boot header | 1 page
** +-----------------+
** | kernel | n pages
** +-----------------+
** | ramdisk | m pages
** +-----------------+
** | second stage | o pages
** +-----------------+
**
** n = (kernel_size + page_size - 1) / page_size
** m = (ramdisk_size + page_size - 1) / page_size
** o = (second_size + page_size - 1) / page_size
**
** 0. all entities are page_size aligned in flash
** 1. kernel and ramdisk are required (size != 0)
** 2. second is optional (second_size == 0 -> no second)
** 3. load each element (kernel, ramdisk, second) at
** the specified physical address (kernel_addr, etc)
** 4. prepare tags at tag_addr. kernel_args[] is
** appended to the kernel commandline in the tags.
** 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr
** 6. if second_size != 0: jump to second_addr
** else: jump to kernel_addr
*/
boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size,
void *ramdisk, unsigned ramdisk_size,
void *second, unsigned second_size,
unsigned page_size,
unsigned *bootimg_size);
void bootimg_set_cmdline(boot_img_hdr *hdr, const char *cmdline);
#endif

372
lk/app/aboot/fastboot.c Normal file
View File

@ -0,0 +1,372 @@
/*
* Copyright (c) 2009, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <debug.h>
#include <string.h>
#include <stdlib.h>
#include <kernel/thread.h>
#include <kernel/event.h>
#include <dev/udc.h>
void boot_linux(void *bootimg, unsigned sz);
/* todo: give lk strtoul and nuke this */
static unsigned hex2unsigned(const char *x)
{
unsigned n = 0;
while(*x) {
switch(*x) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
n = (n << 4) | (*x - '0');
break;
case 'a': case 'b': case 'c':
case 'd': case 'e': case 'f':
n = (n << 4) | (*x - 'a' + 10);
break;
case 'A': case 'B': case 'C':
case 'D': case 'E': case 'F':
n = (n << 4) | (*x - 'A' + 10);
break;
default:
return n;
}
x++;
}
return n;
}
struct fastboot_cmd {
struct fastboot_cmd *next;
const char *prefix;
unsigned prefix_len;
void (*handle)(const char *arg, void *data, unsigned sz);
};
struct fastboot_var {
struct fastboot_var *next;
const char *name;
const char *value;
};
static struct fastboot_cmd *cmdlist;
void fastboot_register(const char *prefix,
void (*handle)(const char *arg, void *data, unsigned sz))
{
struct fastboot_cmd *cmd;
cmd = malloc(sizeof(*cmd));
if (cmd) {
cmd->prefix = prefix;
cmd->prefix_len = strlen(prefix);
cmd->handle = handle;
cmd->next = cmdlist;
cmdlist = cmd;
}
}
static struct fastboot_var *varlist;
void fastboot_publish(const char *name, const char *value)
{
struct fastboot_var *var;
var = malloc(sizeof(*var));
if (var) {
var->name = name;
var->value = value;
var->next = varlist;
varlist = var;
}
}
static event_t usb_online;
static event_t txn_done;
static unsigned char buffer[4096];
static struct udc_endpoint *in, *out;
static struct udc_request *req;
int txn_status;
static void *download_base;
static unsigned download_max;
static unsigned download_size;
#define STATE_OFFLINE 0
#define STATE_COMMAND 1
#define STATE_COMPLETE 2
#define STATE_ERROR 3
static unsigned fastboot_state = STATE_OFFLINE;
static void req_complete(struct udc_request *req, unsigned actual, int status)
{
txn_status = status;
req->length = actual;
event_signal(&txn_done, 0);
}
static int usb_read(void *_buf, unsigned len)
{
int r;
unsigned xfer;
unsigned char *buf = _buf;
int count = 0;
if (fastboot_state == STATE_ERROR)
goto oops;
while (len > 0) {
xfer = (len > 4096) ? 4096 : len;
req->buf = buf;
req->length = xfer;
req->complete = req_complete;
r = udc_request_queue(out, req);
if (r < 0) {
dprintf(INFO, "usb_read() queue failed\n");
goto oops;
}
event_wait(&txn_done);
if (txn_status < 0) {
dprintf(INFO, "usb_read() transaction failed\n");
goto oops;
}
count += req->length;
buf += req->length;
len -= req->length;
/* short transfer? */
if (req->length != xfer) break;
}
return count;
oops:
fastboot_state = STATE_ERROR;
return -1;
}
static int usb_write(void *buf, unsigned len)
{
int r;
if (fastboot_state == STATE_ERROR)
goto oops;
req->buf = buf;
req->length = len;
req->complete = req_complete;
r = udc_request_queue(in, req);
if (r < 0) {
dprintf(INFO, "usb_write() queue failed\n");
goto oops;
}
event_wait(&txn_done);
if (txn_status < 0) {
dprintf(INFO, "usb_write() transaction failed\n");
goto oops;
}
return req->length;
oops:
fastboot_state = STATE_ERROR;
return -1;
}
void fastboot_ack(const char *code, const char *reason)
{
char response[64];
if (fastboot_state != STATE_COMMAND)
return;
if (reason == 0)
reason = "";
snprintf(response, 64, "%s%s", code, reason);
fastboot_state = STATE_COMPLETE;
usb_write(response, strlen(response));
}
void fastboot_fail(const char *reason)
{
fastboot_ack("FAIL", reason);
}
void fastboot_okay(const char *info)
{
fastboot_ack("OKAY", info);
}
static void cmd_getvar(const char *arg, void *data, unsigned sz)
{
struct fastboot_var *var;
for (var = varlist; var; var = var->next) {
if (!strcmp(var->name, arg)) {
fastboot_okay(var->value);
return;
}
}
fastboot_okay("");
}
static void cmd_download(const char *arg, void *data, unsigned sz)
{
char response[64];
unsigned len = hex2unsigned(arg);
int r;
download_size = 0;
if (len > download_max) {
fastboot_fail("data too large");
return;
}
sprintf(response,"DATA%08x", len);
if (usb_write(response, strlen(response)) < 0)
return;
r = usb_read(download_base, len);
if ((r < 0) || (r != len)) {
fastboot_state = STATE_ERROR;
return;
}
download_size = len;
fastboot_okay("");
}
static void fastboot_command_loop(void)
{
struct fastboot_cmd *cmd;
int r;
dprintf(INFO,"fastboot: processing commands\n");
again:
while (fastboot_state != STATE_ERROR) {
r = usb_read(buffer, 64);
if (r < 0) break;
buffer[r] = 0;
dprintf(INFO,"fastboot: %s\n", buffer);
for (cmd = cmdlist; cmd; cmd = cmd->next) {
if (memcmp(buffer, cmd->prefix, cmd->prefix_len))
continue;
fastboot_state = STATE_COMMAND;
cmd->handle((const char*) buffer + cmd->prefix_len,
(void*) download_base, download_size);
if (fastboot_state == STATE_COMMAND)
fastboot_fail("unknown reason");
goto again;
}
fastboot_fail("unknown command");
}
fastboot_state = STATE_OFFLINE;
dprintf(INFO,"fastboot: oops!\n");
}
static int fastboot_handler(void *arg)
{
for (;;) {
event_wait(&usb_online);
fastboot_command_loop();
}
return 0;
}
static void fastboot_notify(struct udc_gadget *gadget, unsigned event)
{
if (event == UDC_EVENT_ONLINE) {
event_signal(&usb_online, 0);
}
}
static struct udc_endpoint *fastboot_endpoints[2];
static struct udc_gadget fastboot_gadget = {
.notify = fastboot_notify,
.ifc_class = 0xff,
.ifc_subclass = 0x42,
.ifc_protocol = 0x03,
.ifc_endpoints = 2,
.ifc_string = "fastboot",
.ept = fastboot_endpoints,
};
int fastboot_init(void *base, unsigned size)
{
thread_t *thr;
dprintf(INFO, "fastboot_init()\n");
download_base = base;
download_max = size;
event_init(&usb_online, 0, EVENT_FLAG_AUTOUNSIGNAL);
event_init(&txn_done, 0, EVENT_FLAG_AUTOUNSIGNAL);
in = udc_endpoint_alloc(UDC_TYPE_BULK_IN, 512);
if (!in)
goto fail_alloc_in;
out = udc_endpoint_alloc(UDC_TYPE_BULK_OUT, 512);
if (!out)
goto fail_alloc_out;
fastboot_endpoints[0] = in;
fastboot_endpoints[1] = out;
req = udc_request_alloc();
if (!req)
goto fail_alloc_req;
if (udc_register_gadget(&fastboot_gadget))
goto fail_udc_register;
fastboot_register("getvar:", cmd_getvar);
fastboot_register("download:", cmd_download);
fastboot_publish("version", "0.5");
thr = thread_create("fastboot", fastboot_handler, 0, DEFAULT_PRIORITY, 4096);
thread_resume(thr);
return 0;
fail_udc_register:
udc_request_free(req);
fail_alloc_req:
udc_endpoint_free(out);
fail_alloc_out:
udc_endpoint_free(in);
fail_alloc_in:
return -1;
}

50
lk/app/aboot/fastboot.h Normal file
View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2009, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef __APP_FASTBOOT_H
#define __APP_FASTBOOT_H
int fastboot_init(void *xfer_buffer, unsigned max);
/* register a command handler
* - command handlers will be called if their prefix matches
* - they are expected to call fastboot_okay() or fastboot_fail()
* to indicate success/failure before returning
*/
void fastboot_register(const char *prefix,
void (*handle)(const char *arg, void *data, unsigned size));
/* publish a variable readable by the built-in getvar command */
void fastboot_publish(const char *name, const char *value);
/* only callable from within a command handler */
void fastboot_okay(const char *result);
void fastboot_fail(const char *reason);
#endif

277
lk/app/aboot/recovery.c Normal file
View File

@ -0,0 +1,277 @@
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Code Aurora Forum, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <debug.h>
#include <arch/arm.h>
#include <dev/udc.h>
#include <string.h>
#include <kernel/thread.h>
#include <arch/ops.h>
#include <dev/flash.h>
#include <lib/ptable.h>
#include <dev/keys.h>
#include "recovery.h"
#include "bootimg.h"
static const int MISC_PAGES = 3; // number of pages to save
static const int MISC_COMMAND_PAGE = 1; // bootloader command is this page
static char buf[4096];
unsigned boot_into_recovery = 0;
void reboot_device(unsigned);
int get_recovery_message(struct recovery_message *out)
{
struct ptentry *ptn;
struct ptable *ptable;
unsigned offset = 0;
unsigned pagesize = flash_page_size();
ptable = flash_get_ptable();
if (ptable == NULL) {
dprintf(CRITICAL, "ERROR: Partition table not found\n");
return -1;
}
ptn = ptable_find(ptable, "misc");
if (ptn == NULL) {
dprintf(CRITICAL, "ERROR: No misc partition found\n");
return -1;
}
offset += (pagesize * MISC_COMMAND_PAGE);
dprintf(CRITICAL, "flash_read misc partition \n");
if (flash_read(ptn, offset, buf, pagesize)) {
dprintf(CRITICAL, "ERROR: Cannot read recovery_header\n");
return -1;
}
dprintf(CRITICAL, "flash_read misc partition done\n");
memcpy(out, buf, sizeof(*out));
return 0;
}
int set_recovery_message(const struct recovery_message *in)
{
struct ptentry *ptn;
struct ptable *ptable;
unsigned offset = 0;
unsigned pagesize = flash_page_size();
unsigned n = 0;
ptable = flash_get_ptable();
if (ptable == NULL) {
dprintf(CRITICAL, "ERROR: Partition table not found\n");
return -1;
}
ptn = ptable_find(ptable, "misc");
if (ptn == NULL) {
dprintf(CRITICAL, "ERROR: No misc partition found\n");
return -1;
}
n = pagesize * (MISC_COMMAND_PAGE + 1);
if (flash_read(ptn, offset, SCRATCH_ADDR, n)) {
dprintf(CRITICAL, "ERROR: Cannot read recovery_header\n");
return -1;
}
offset += (pagesize * MISC_COMMAND_PAGE);
offset += SCRATCH_ADDR;
memcpy(offset, in, sizeof(*in));
if (flash_write(ptn, 0, (void *)SCRATCH_ADDR, n)) {
dprintf(CRITICAL, "ERROR: flash write fail!\n");
return -1;
}
}
int read_update_header_for_bootloader(struct update_header *header)
{
struct ptentry *ptn;
struct ptable *ptable;
unsigned offset = 0;
unsigned pagesize = flash_page_size();
ptable = flash_get_ptable();
if (ptable == NULL) {
dprintf(CRITICAL, "ERROR: Partition table not found\n");
return -1;
}
ptn = ptable_find(ptable, "cache");
if (ptn == NULL) {
dprintf(CRITICAL, "ERROR: No cache partition found\n");
return -1;
}
if (flash_read(ptn, offset, buf, pagesize)) {
dprintf(CRITICAL, "ERROR: Cannot read recovery_header\n");
return -1;
}
memcpy(header, buf, sizeof(*header));
if(strncmp(header->MAGIC, UPDATE_MAGIC, UPDATE_MAGIC_SIZE))
{
return -1;
}
return 0;
}
int update_firmware_image (struct update_header *header, char *name)
{
struct ptentry *ptn;
struct ptable *ptable;
unsigned offset = 0;
unsigned pagesize = flash_page_size();
unsigned pagemask = pagesize -1;
unsigned n = 0;
ptable = flash_get_ptable();
if (ptable == NULL) {
dprintf(CRITICAL, "ERROR: Partition table not found\n");
return -1;
}
ptn = ptable_find(ptable, "cache");
if (ptn == NULL) {
dprintf(CRITICAL, "ERROR: No cache partition found\n");
return -1;
}
offset += header->image_offset;
n = (header->image_length + pagemask) & (~pagemask);
if (flash_read(ptn, offset, SCRATCH_ADDR, n)) {
dprintf(CRITICAL, "ERROR: Cannot read radio image\n");
return -1;
}
ptn = ptable_find(ptable, name);
if (ptn == NULL) {
dprintf(CRITICAL, "ERROR: No %s partition found\n", name);
return -1;
}
if (flash_write(ptn, 0, SCRATCH_ADDR, n)) {
dprintf(CRITICAL, "ERROR: flash write fail!\n");
return -1;
}
dprintf(INFO, "Partition writen successfully!");
return 0;
}
/* Bootloader / Recovery Flow
*
* On every boot, the bootloader will read the recovery_message
* from flash and check the command field. The bootloader should
* deal with the command field not having a 0 terminator correctly
* (so as to not crash if the block is invalid or corrupt).
*
* The bootloader will have to publish the partition that contains
* the recovery_message to the linux kernel so it can update it.
*
* if command == "boot-recovery" -> boot recovery.img
* else if command == "update-radio" -> update radio image (below)
* else -> boot boot.img (normal boot)
*
* Radio Update Flow
* 1. the bootloader will attempt to load and validate the header
* 2. if the header is invalid, status="invalid-update", goto #8
* 3. display the busy image on-screen
* 4. if the update image is invalid, status="invalid-radio-image", goto #8
* 5. attempt to update the firmware (depending on the command)
* 6. if successful, status="okay", goto #8
* 7. if failed, and the old image can still boot, status="failed-update"
* 8. write the recovery_message, leaving the recovery field
* unchanged, updating status, and setting command to
* "boot-recovery"
* 9. reboot
*
* The bootloader will not modify or erase the cache partition.
* It is recovery's responsibility to clean up the mess afterwards.
*/
int recovery_init (void)
{
struct recovery_message msg;
struct update_header header;
char partition_name[32];
unsigned valid_command = 0;
// get recovery message
if(get_recovery_message(&msg))
return -1;
if (msg.command[0] != 0 && msg.command[0] != 255) {
dprintf("Recovery command: %.*s\n", sizeof(msg.command), msg.command);
}
msg.command[sizeof(msg.command)-1] = '\0'; //Ensure termination
if (!strcmp("boot-recovery",msg.command)) {
valid_command = 1;
strcpy(msg.command, ""); // to safe against multiple reboot into recovery
strcpy(msg.status, "OKAY");
set_recovery_message(&msg); // send recovery message
boot_into_recovery = 1; // Boot in recovery mode
return 0;
}
if (!strcmp("update-radio",msg.command)) {
valid_command = 1;
strcpy(partition_name, "FOTA");
}
//Todo: Add support for bootloader update too.
if(!valid_command) {
//We need not to do anything
return 0; // Boot in normal mode
}
if (read_update_header_for_bootloader(&header)) {
strcpy(msg.status, "invalid-update");
goto SEND_RECOVERY_MSG;
}
if (update_firmware_image (&header, partition_name)) {
strcpy(msg.status, "failed-update");
goto SEND_RECOVERY_MSG;
}
strcpy(msg.status, "OKAY");
SEND_RECOVERY_MSG:
strcpy(msg.command, "boot-recovery");
set_recovery_message(&msg); // send recovery message
boot_into_recovery = 1; // Boot in recovery mode
reboot_device(0);
return 0;
}

77
lk/app/aboot/recovery.h Normal file
View File

@ -0,0 +1,77 @@
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Code Aurora Forum, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _BOOTLOADER_RECOVERY_H
#define _BOOTLOADER_RECOVERY_H
#define UPDATE_MAGIC "MSM-RADIO-UPDATE"
#define UPDATE_MAGIC_SIZE 16
#define UPDATE_VERSION 0x00010000
/* Recovery Message */
struct recovery_message {
char command[32];
char status[32];
char recovery[1024];
};
struct update_header {
unsigned char MAGIC[UPDATE_MAGIC_SIZE];
unsigned version;
unsigned size;
unsigned image_offset;
unsigned image_length;
unsigned bitmap_width;
unsigned bitmap_height;
unsigned bitmap_bpp;
unsigned busy_bitmap_offset;
unsigned busy_bitmap_length;
unsigned fail_bitmap_offset;
unsigned fail_bitmap_length;
};
int get_recovery_message(struct recovery_message *out);
int set_recovery_message(const struct recovery_message *in);
int read_update_header_for_bootloader(struct update_header *header);
int update_firmware_image (struct update_header *header, char *name);
int recovery_init (void);
extern unsigned boot_into_recovery;
#endif

7
lk/app/aboot/rules.mk Normal file
View File

@ -0,0 +1,7 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
OBJS += \
$(LOCAL_DIR)/aboot.o \
$(LOCAL_DIR)/fastboot.o \
$(LOCAL_DIR)/recovery.o

66
lk/app/app.c Normal file
View File

@ -0,0 +1,66 @@
/*
* Copyright (c) 2009 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <debug.h>
#include <app.h>
#include <kernel/thread.h>
extern const struct app_descriptor __apps_start;
extern const struct app_descriptor __apps_end;
static void start_app(const struct app_descriptor *app);
/* one time setup */
void apps_init(void)
{
const struct app_descriptor *app;
/* call all the init routines */
for (app = &__apps_start; app != &__apps_end; app++) {
if (app->init)
app->init(app);
}
/* start any that want to start on boot */
for (app = &__apps_start; app != &__apps_end; app++) {
if (app->entry && (app->flags & APP_FLAG_DONT_START_ON_BOOT) == 0) {
start_app(app);
}
}
}
static int app_thread_entry(void *arg)
{
const struct app_descriptor *app = (const struct app_descriptor *)arg;
app->entry(app, NULL);
return 0;
}
static void start_app(const struct app_descriptor *app)
{
printf("starting app %s\n", app->name);
thread_resume(thread_create(app->name, &app_thread_entry, (void *)app, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
}

View File

@ -0,0 +1,99 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _BOOT_IMAGE_H_
#define _BOOT_IMAGE_H_
typedef struct boot_img_hdr boot_img_hdr;
#define BOOT_MAGIC "ANDROID!"
#define BOOT_MAGIC_SIZE 8
#define BOOT_NAME_SIZE 16
#define BOOT_ARGS_SIZE 512
struct boot_img_hdr
{
unsigned char magic[BOOT_MAGIC_SIZE];
unsigned kernel_size; /* size in bytes */
unsigned kernel_addr; /* physical load addr */
unsigned ramdisk_size; /* size in bytes */
unsigned ramdisk_addr; /* physical load addr */
unsigned second_size; /* size in bytes */
unsigned second_addr; /* physical load addr */
unsigned tags_addr; /* physical addr for kernel tags */
unsigned page_size; /* flash page size we assume */
unsigned unused[2]; /* future expansion: should be 0 */
unsigned char name[BOOT_NAME_SIZE]; /* asciiz product name */
unsigned char cmdline[BOOT_ARGS_SIZE];
unsigned id[8]; /* timestamp / checksum / sha1 / etc */
};
/*
** +-----------------+
** | boot header | 1 page
** +-----------------+
** | kernel | n pages
** +-----------------+
** | ramdisk | m pages
** +-----------------+
** | second stage | o pages
** +-----------------+
**
** n = (kernel_size + page_size - 1) / page_size
** m = (ramdisk_size + page_size - 1) / page_size
** o = (second_size + page_size - 1) / page_size
**
** 0. all entities are page_size aligned in flash
** 1. kernel and ramdisk are required (size != 0)
** 2. second is optional (second_size == 0 -> no second)
** 3. load each element (kernel, ramdisk, second) at
** the specified physical address (kernel_addr, etc)
** 4. prepare tags at tag_addr. kernel_args[] is
** appended to the kernel commandline in the tags.
** 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr
** 6. if second_size != 0: jump to second_addr
** else: jump to kernel_addr
*/
boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size,
void *ramdisk, unsigned ramdisk_size,
void *second, unsigned second_size,
unsigned page_size,
unsigned *bootimg_size);
void bootimg_set_cmdline(boot_img_hdr *hdr, const char *cmdline);
#endif

View File

@ -0,0 +1,220 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <app.h>
#include <debug.h>
#include <lib/ptable.h>
#include <malloc.h>
#include <dev/flash.h>
#include <string.h>
#include <jtag.h>
#include <kernel/thread.h>
#include <smem.h>
#include "bootimg.h"
#define FLASH_PAGE_SIZE 2048
#define FLASH_PAGE_BITS 11
unsigned page_size = 0;
unsigned page_mask = 0;
static unsigned load_addr = 0xffffffff;
#define ROUND_TO_PAGE(x,y) (((x) + (y)) & (~(y)))
void acpu_clock_init(void);
void platform_uninit_timer(void);
int startswith(const char *str, const char *prefix)
{
while(*prefix){
if(*prefix++ != *str++) return 0;
}
return 1;
}
/* XXX */
void verify_flash(struct ptentry *p, void *addr, unsigned len, int extra)
{
uint32_t offset = 0;
void *buf = malloc(FLASH_PAGE_SIZE + extra);
int verify_extra = extra;
if(verify_extra > 4)
verify_extra = 16;
while(len > 0) {
flash_read_ext(p, extra, offset, buf, FLASH_PAGE_SIZE);
if(memcmp(addr, buf, FLASH_PAGE_SIZE + verify_extra)) {
dprintf(CRITICAL, "verify failed at 0x%08x\n", offset);
jtag_fail("verify failed");
return;
}
offset += FLASH_PAGE_SIZE;
addr += FLASH_PAGE_SIZE;
len -= FLASH_PAGE_SIZE;
if(extra) {
addr += extra;
len -= extra;
}
}
dprintf(INFO, "verify done %d extra bytes\n", verify_extra);
jtag_okay("verify done");
}
void handle_flash(const char *name, unsigned addr, unsigned sz)
{
struct ptentry *ptn;
struct ptable *ptable;
void *data = (void *) addr;
unsigned extra = 0;
ptable = flash_get_ptable();
if (ptable == NULL) {
jtag_fail("partition table doesn't exist");
return;
}
ptn = ptable_find(ptable, name);
if (ptn == NULL) {
jtag_fail("unknown partition name");
return;
}
if (!strcmp(ptn->name, "boot") || !strcmp(ptn->name, "recovery")) {
if (memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
jtag_fail("image is not a boot image");
return;
}
}
if (!strcmp(ptn->name, "system") || !strcmp(ptn->name, "userdata") || !strcmp(ptn->name, "persist"))
extra = ((page_size >> 9) * 16);
else
sz = ROUND_TO_PAGE(sz, page_mask);
data = (void *)target_get_scratch_address();
dprintf(INFO, "writing %d bytes to '%s'\n", sz, ptn->name);
if (flash_write(ptn, extra, data, sz)) {
jtag_fail("flash write failure");
return;
}
dprintf(INFO, "partition '%s' updated\n", ptn->name);
jtag_okay("Done");
enter_critical_section();
platform_uninit_timer();
arch_disable_cache(UCACHE);
arch_disable_mmu();
}
static unsigned char *tmpbuf = 0;
/*XXX*/
void handle_dump(const char *name, unsigned offset)
{
struct ptentry *p;
struct ptable *ptable;
if(tmpbuf == 0) {
tmpbuf = malloc(4096);
}
dprintf(INFO, "dump '%s' partition\n", name);
ptable = flash_get_ptable();
if (ptable == NULL) {
jtag_fail("partition table doesn't exist");
return;
}
p = ptable_find(ptable, name);
if(p == 0) {
jtag_fail("partition not found");
return;
} else {
#if 0
/* XXX reimpl */
if(flash_read_page(p->start * 64, tmpbuf, tmpbuf + 2048)){
jtag_fail("flash_read() failed");
return;
}
#endif
dprintf(INFO, "page %d data:\n", p->start * 64);
hexdump(tmpbuf, 256);
dprintf(INFO, "page %d extra:\n", p->start * 64);
hexdump(tmpbuf, 16);
jtag_okay("done");
enter_critical_section();
platform_uninit_timer();
arch_disable_cache(UCACHE);
arch_disable_mmu();
}
}
void handle_query_load_address(unsigned addr)
{
unsigned *return_addr = (unsigned *)addr;
if (return_addr)
*return_addr = target_get_scratch_address();
jtag_okay("done");
}
void handle_command(const char *cmd, unsigned a0, unsigned a1, unsigned a2)
{
if(startswith(cmd,"flash:")){
handle_flash(cmd + 6, a0, a1);
return;
}
if(startswith(cmd,"dump:")){
handle_dump(cmd + 5, a0);
return;
}
if(startswith(cmd,"loadaddr:")){
handle_query_load_address(a0);
return;
}
jtag_fail("unknown command");
}
void nandwrite_init(void)
{
page_size = flash_page_size();
page_mask = page_size - 1;
jtag_cmd_loop(handle_command);
}

View File

@ -0,0 +1,6 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
OBJS += \
$(LOCAL_DIR)/nandwrite.o \

5
lk/app/rules.mk Normal file
View File

@ -0,0 +1,5 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
OBJS += \
$(LOCAL_DIR)/app.o

7
lk/app/shell/rules.mk Normal file
View File

@ -0,0 +1,7 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
MODULES += \
lib/console
OBJS += \
$(LOCAL_DIR)/shell.o

41
lk/app/shell/shell.c Normal file
View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2009 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <app.h>
#include <debug.h>
#include <lib/console.h>
static void shell_init(const struct app_descriptor *app)
{
console_init();
}
static void shell_entry(const struct app_descriptor *app, void *args)
{
console_start();
}
APP_START(shell)
.init = shell_init,
.entry = shell_entry,
APP_END

View File

@ -0,0 +1,169 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <asm.h>
#include <arch/arm/cores.h>
.text
.align 2
.global mymemcpy
mymemcpy:
// check for zero length copy or the same pointer
cmp r2, #0
cmpne r1, r0
bxeq lr
// save a few registers for use and the return code (input dst)
stmfd sp!, {r0, r4, r5, lr}
// check for forwards overlap (src > dst, distance < len)
subs r3, r0, r1
cmpgt r2, r3
bgt .L_forwardoverlap
// check for a short copy len.
// 20 bytes is enough so that if a 16 byte alignment needs to happen there is at least a
// wordwise copy worth of work to be done.
cmp r2, #(16+4)
blt .L_bytewise
// see if they are similarly aligned on 4 byte boundaries
eor r3, r0, r1
tst r3, #3
bne .L_bytewise // dissimilarly aligned, nothing we can do (for now)
// check for 16 byte alignment on dst.
// this will also catch src being not 4 byte aligned, since it is similarly 4 byte
// aligned with dst at this point.
tst r0, #15
bne .L_not16bytealigned
// check to see if we have at least 32 bytes of data to copy.
// if not, just revert to wordwise copy
cmp r2, #32
blt .L_wordwise
.L_bigcopy:
// copy 32 bytes at a time. src & dst need to be at least 4 byte aligned,
// and we need at least 32 bytes remaining to copy
// save r6-r7 for use in the big copy
stmfd sp!, {r6-r7}
sub r2, r2, #32 // subtract an extra 32 to the len so we can avoid an extra compare
.L_bigcopy_loop:
ldmia r1!, {r4, r5, r6, r7}
stmia r0!, {r4, r5, r6, r7}
ldmia r1!, {r4, r5, r6, r7}
subs r2, r2, #32
stmia r0!, {r4, r5, r6, r7}
bge .L_bigcopy_loop
// restore r6-r7
ldmfd sp!, {r6-r7}
// see if we are done
adds r2, r2, #32
beq .L_done
// less then 4 bytes left?
cmp r2, #4
blt .L_bytewise
.L_wordwise:
// copy 4 bytes at a time.
// src & dst are guaranteed to be word aligned, and at least 4 bytes are left to copy.
subs r2, r2, #4
.L_wordwise_loop:
ldr r3, [r1], #4
subs r2, r2, #4
str r3, [r0], #4
bge .L_wordwise_loop
// correct the remaining len and test for completion
adds r2, r2, #4
beq .L_done
.L_bytewise:
// simple bytewise copy
ldrb r3, [r1], #1
subs r2, r2, #1
strb r3, [r0], #1
bgt .L_bytewise
.L_done:
// load dst for return and restore r4,r5
#if ARM_ARCH_LEVEL >= 5
ldmfd sp!, {r0, r4, r5, pc}
#else
ldmfd sp!, {r0, r4, r5, lr}
bx lr
#endif
.L_not16bytealigned:
// dst is not 16 byte aligned, so we will copy up to 15 bytes to get it aligned.
// src is guaranteed to be similarly word aligned with dst.
// set the condition flags based on the alignment.
lsl r12, r0, #28
rsb r12, r12, #0
msr CPSR_f, r12 // move into NZCV fields in CPSR
// move as many bytes as necessary to get the dst aligned
ldrvsb r3, [r1], #1 // V set
ldrcsh r4, [r1], #2 // C set
ldreq r5, [r1], #4 // Z set
strvsb r3, [r0], #1
strcsh r4, [r0], #2
streq r5, [r0], #4
ldmmiia r1!, {r3-r4} // N set
stmmiia r0!, {r3-r4}
// fix the remaining len
sub r2, r2, r12, lsr #28
// test to see what we should do now
cmp r2, #32
bge .L_bigcopy
b .L_wordwise
// src and dest overlap 'forwards' or dst > src
.L_forwardoverlap:
// do a bytewise reverse copy for now
add r1, r1, r2
add r0, r0, r2
.L_bytewisereverse:
// simple bytewise reverse copy
ldrb r3, [r1], #-1
subs r2, r2, #1
strb r3, [r0], #-1
bgt .L_bytewisereverse
b .L_done

View File

@ -0,0 +1,109 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <asm.h>
#include <arch/arm/cores.h>
.text
.align 2
/* void *memset(void *s, int c, size_t n); */
.global mymemset
mymemset:
// check for zero length
cmp r2, #0
bxeq lr
// save the original pointer
mov r12, r0
// short memsets aren't worth optimizing
cmp r2, #(32 + 16)
blt .L_bytewise
// fill a 32 bit register with the 8 bit value
and r1, r1, #0xff
orr r1, r1, r1, lsl #8
orr r1, r1, r1, lsl #16
// check for 16 byte alignment
tst r0, #15
bne .L_not16bytealigned
.L_bigset:
// dump some registers to make space for our values
stmfd sp!, { r4-r5 }
// fill a bunch of registers with the set value
mov r3, r1
mov r4, r1
mov r5, r1
// prepare the count register so we can avoid an extra compare
sub r2, r2, #32
// 32 bytes at a time
.L_bigset_loop:
stmia r0!, { r1, r3, r4, r5 }
subs r2, r2, #32
stmia r0!, { r1, r3, r4, r5 }
bge .L_bigset_loop
// restore our dumped registers
ldmfd sp!, { r4-r5 }
// see if we're done
adds r2, r2, #32
beq .L_done
.L_bytewise:
// bytewise memset
subs r2, r2, #1
strb r1, [r0], #1
bgt .L_bytewise
.L_done:
// restore the base pointer as return value
mov r0, r12
bx lr
.L_not16bytealigned:
// dst is not 16 byte aligned, so we will set up to 15 bytes to get it aligned.
// set the condition flags based on the alignment.
lsl r3, r0, #28
rsb r3, r3, #0
msr CPSR_f, r3 // move into NZCV fields in CPSR
// move as many bytes as necessary to get the dst aligned
strvsb r1, [r0], #1 // V set
strcsh r1, [r0], #2 // C set
streq r1, [r0], #4 // Z set
strmi r1, [r0], #4 // N set
strmi r1, [r0], #4 // N set
// fix the remaining len
sub r2, r2, r3, lsr #28
// do the large memset
b .L_bigset

View File

@ -0,0 +1,6 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
OBJS += \
$(LOCAL_DIR)/string_tests.o \
$(LOCAL_DIR)/mymemcpy.o \
$(LOCAL_DIR)/mymemset.o

View File

@ -0,0 +1,249 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <debug.h>
#include <string.h>
#include <malloc.h>
#include <app.h>
#include <platform.h>
#include <kernel/thread.h>
static uint8_t *src;
static uint8_t *dst;
static uint8_t *src2;
static uint8_t *dst2;
#define BUFFER_SIZE (1024*1024)
#define ITERATIONS 16
extern void *mymemcpy(void *dst, const void *src, size_t len);
extern void *mymemset(void *dst, int c, size_t len);
static void *null_memcpy(void *dst, const void *src, size_t len)
{
return dst;
}
static time_t bench_memcpy_routine(void *memcpy_routine(void *, const void *, size_t), size_t srcalign, size_t dstalign)
{
int i;
time_t t0;
t0 = current_time();
for (i=0; i < ITERATIONS; i++) {
memcpy_routine(dst + dstalign, src + srcalign, BUFFER_SIZE);
}
return current_time() - t0;
}
static void bench_memcpy(void)
{
time_t null, libc, mine;
size_t srcalign, dstalign;
printf("memcpy speed test\n");
thread_sleep(200); // let the debug string clear the serial port
for (srcalign = 0; srcalign < 64; ) {
for (dstalign = 0; dstalign < 64; ) {
null = bench_memcpy_routine(&null_memcpy, srcalign, dstalign);
libc = bench_memcpy_routine(&memcpy, srcalign, dstalign);
mine = bench_memcpy_routine(&mymemcpy, srcalign, dstalign);
printf("srcalign %lu, dstalign %lu\n", srcalign, dstalign);
printf(" null memcpy %u msecs\n", null);
printf(" libc memcpy %u msecs, %llu bytes/sec\n", libc, BUFFER_SIZE * ITERATIONS * 1000ULL / libc);
printf(" my memcpy %u msecs, %llu bytes/sec\n", mine, BUFFER_SIZE * ITERATIONS * 1000ULL / mine);
if (dstalign == 0)
dstalign = 1;
else
dstalign <<= 1;
}
if (srcalign == 0)
srcalign = 1;
else
srcalign <<= 1;
}
}
static void fillbuf(void *ptr, size_t len, uint32_t seed)
{
size_t i;
for (i = 0; i < len; i++) {
((char *)ptr)[i] = seed;
seed *= 0x1234567;
}
}
static void validate_memcpy(void)
{
size_t srcalign, dstalign, size;
const size_t maxsize = 256;
printf("testing memcpy for correctness\n");
/*
* do the simple tests to make sure that memcpy doesn't color outside
* the lines for all alignment cases
*/
for (srcalign = 0; srcalign < 64; srcalign++) {
for (dstalign = 0; dstalign < 64; dstalign++) {
// printf("srcalign %zu, dstalign %zu\n", srcalign, dstalign);
for (size = 0; size < maxsize; size++) {
// printf("srcalign %zu, dstalign %zu, size %zu\n", srcalign, dstalign, size);
fillbuf(src, maxsize * 2, 567);
fillbuf(src2, maxsize * 2, 567);
fillbuf(dst, maxsize * 2, 123514);
fillbuf(dst2, maxsize * 2, 123514);
memcpy(dst + dstalign, src + srcalign, size);
mymemcpy(dst2 + dstalign, src2 + srcalign, size);
int comp = memcmp(dst, dst2, maxsize * 2);
if (comp != 0) {
printf("error! srcalign %zu, dstalign %zu, size %zu\n", srcalign, dstalign, size);
}
}
}
}
}
static time_t bench_memset_routine(void *memset_routine(void *, int, size_t), size_t dstalign)
{
int i;
time_t t0;
t0 = current_time();
for (i=0; i < ITERATIONS; i++) {
memset_routine(dst + dstalign, 0, BUFFER_SIZE);
}
return current_time() - t0;
}
static void bench_memset(void)
{
time_t libc, mine;
size_t dstalign;
printf("memset speed test\n");
thread_sleep(200); // let the debug string clear the serial port
for (dstalign = 0; dstalign < 64; dstalign++) {
libc = bench_memset_routine(&memset, dstalign);
mine = bench_memset_routine(&mymemset, dstalign);
printf("dstalign %lu\n", dstalign);
printf(" libc memset %u msecs, %llu bytes/sec\n", libc, BUFFER_SIZE * ITERATIONS * 1000ULL / libc);
printf(" my memset %u msecs, %llu bytes/sec\n", mine, BUFFER_SIZE * ITERATIONS * 1000ULL / mine);
}
}
static void validate_memset(void)
{
size_t dstalign, size;
int c;
const size_t maxsize = 256;
printf("testing memset for correctness\n");
for (dstalign = 0; dstalign < 64; dstalign++) {
printf("align %zd\n", dstalign);
for (size = 0; size < maxsize; size++) {
for (c = 0; c < 256; c++) {
fillbuf(dst, maxsize * 2, 123514);
fillbuf(dst2, maxsize * 2, 123514);
memset(dst + dstalign, c, size);
mymemset(dst2 + dstalign, c, size);
int comp = memcmp(dst, dst2, maxsize * 2);
if (comp != 0) {
printf("error! align %zu, c %d, size %zu\n", dstalign, c, size);
}
}
}
}
}
#if defined(WITH_LIB_CONSOLE)
#include <lib/console.h>
static int string_tests(int argc, cmd_args *argv)
{
src = memalign(64, BUFFER_SIZE + 256);
dst = memalign(64, BUFFER_SIZE + 256);
src2 = memalign(64, BUFFER_SIZE + 256);
dst2 = memalign(64, BUFFER_SIZE + 256);
printf("src %p, dst %p\n", src, dst);
printf("src2 %p, dst2 %p\n", src2, dst2);
if (argc < 3) {
printf("not enough arguments:\n");
usage:
printf("%s validate <routine>\n", argv[0].str);
printf("%s bench <routine>\n", argv[0].str);
goto out;
}
if (!strcmp(argv[1].str, "validate")) {
if (!strcmp(argv[2].str, "memcpy")) {
validate_memcpy();
} else if (!strcmp(argv[2].str, "memset")) {
validate_memset();
}
} else if (!strcmp(argv[1].str, "bench")) {
if (!strcmp(argv[2].str, "memcpy")) {
bench_memcpy();
} else if (!strcmp(argv[2].str, "memset")) {
bench_memset();
}
} else {
goto usage;
}
out:
free(src);
free(dst);
free(src2);
free(dst2);
return 0;
}
STATIC_COMMAND_START
{ "string", NULL, &string_tests },
STATIC_COMMAND_END(stringtests);
#endif
APP_START(stringtests)
APP_END

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __APP_TESTS_H
#define __APP_TESTS_H
int thread_tests(void);
void printf_tests(void);
#endif

View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <app/tests.h>
#include <debug.h>
void printf_tests(void)
{
printf("printf tests\n");
printf("numbers:\n");
printf("int8: %hhd %hhd %hhd\n", -12, 0, 254);
printf("uint8: %hhu %hhu %hhu\n", -12, 0, 254);
printf("int16: %hd %hd %hd\n", -1234, 0, 1234);
printf("uint16:%hu %hu %hu\n", -1234, 0, 1234);
printf("int: %d %d %d\n", -12345678, 0, 12345678);
printf("uint: %u %u %u\n", -12345678, 0, 12345678);
printf("long: %ld %ld %ld\n", -12345678, 0, 12345678);
printf("ulong: %lu %lu %lu\n", -12345678, 0, 12345678);
printf("long: %D %D %D\n", -12345678, 0, 12345678);
printf("ulong: %U %U %U\n", -12345678, 0, 12345678);
printf("longlong: %lli %lli %lli\n", -12345678LL, 0LL, 12345678LL);
printf("ulonglong: %llu %llu %llu\n", -12345678LL, 0LL, 12345678LL);
printf("size_t: %zd %zd %zd\n", -12345678, 0, 12345678);
printf("usize_t: %zu %zu %zu\n", -12345678, 0, 12345678);
printf("hex:\n");
printf("uint8: %hhx %hhx %hhx\n", -12, 0, 254);
printf("uint16:%hx %hx %hx\n", -1234, 0, 1234);
printf("uint: %x %x %x\n", -12345678, 0, 12345678);
printf("ulong: %lx %lx %lx\n", -12345678, 0, 12345678);
printf("ulong: %X %X %X\n", -12345678, 0, 12345678);
printf("ulonglong: %llx %llx %llx\n", -12345678LL, 0LL, 12345678LL);
printf("usize_t: %zx %zx %zx\n", -12345678, 0, 12345678);
printf("alt/sign:\n");
printf("uint: %#x %#X\n", 0xabcdef, 0xabcdef);
printf("int: %+d %+d\n", 12345678, -12345678);
printf("formatting\n");
printf("int: a%8da\n", 12345678);
printf("int: a%9da\n", 12345678);
printf("int: a%-9da\n", 12345678);
printf("int: a%10da\n", 12345678);
printf("int: a%-10da\n", 12345678);
printf("int: a%09da\n", 12345678);
printf("int: a%010da\n", 12345678);
printf("int: a%6da\n", 12345678);
printf("a%1sa\n", "b");
printf("a%9sa\n", "b");
printf("a%-9sa\n", "b");
printf("a%5sa\n", "thisisatest");
int err;
err = printf("a");
printf(" returned %d\n", err);
err = printf("ab");
printf(" returned %d\n", err);
err = printf("abc");
printf(" returned %d\n", err);
err = printf("abcd");
printf(" returned %d\n", err);
err = printf("abcde");
printf(" returned %d\n", err);
err = printf("abcdef");
printf(" returned %d\n", err);
}

8
lk/app/tests/rules.mk Normal file
View File

@ -0,0 +1,8 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
INCLUDES += -I$(LOCAL_DIR)/include
OBJS += \
$(LOCAL_DIR)/tests.o \
$(LOCAL_DIR)/thread_tests.o \
$(LOCAL_DIR)/printf_tests.o

46
lk/app/tests/tests.c Normal file
View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <app.h>
#include <debug.h>
#include <app/tests.h>
#include <compiler.h>
#if defined(WITH_LIB_CONSOLE)
#include <lib/console.h>
STATIC_COMMAND_START
{ "printf_tests", NULL, (console_cmd)&printf_tests },
{ "thread_tests", NULL, (console_cmd)&thread_tests },
STATIC_COMMAND_END(tests);
#endif
static void tests_init(const struct app_descriptor *app)
{
}
APP_START(tests)
.init = tests_init,
.flags = 0,
APP_END

322
lk/app/tests/thread_tests.c Normal file
View File

@ -0,0 +1,322 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <debug.h>
#include <rand.h>
#include <app/tests.h>
#include <kernel/thread.h>
#include <kernel/mutex.h>
#include <kernel/event.h>
static int sleep_thread(void *arg)
{
for(;;) {
printf("sleeper %p\n", current_thread);
thread_sleep(rand() % 500);
}
return 0;
}
int sleep_test(void)
{
int i;
for(i=0; i < 16; i++)
thread_resume(thread_create("sleeper", &sleep_thread, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
return 0;
}
static volatile int shared = 0;
static mutex_t m;
static volatile int mutex_thread_count = 0;
static int mutex_thread(void *arg)
{
int i;
const int iterations = 10000;
atomic_add(&mutex_thread_count, 1);
printf("mutex tester thread %p starting up, will go for %d iterations\n", current_thread, iterations);
for (i = 0; i < iterations; i++) {
mutex_acquire(&m);
if (shared != 0)
panic("someone else has messed with the shared data\n");
shared = (int)current_thread;
thread_yield();
shared = 0;
mutex_release(&m);
thread_yield();
}
atomic_add(&mutex_thread_count, -1);
return 0;
}
static int mutex_timeout_thread(void *arg)
{
mutex_t *timeout_mutex = (mutex_t *)arg;
status_t err;
printf("mutex_timeout_thread acquiring mutex %p with 1 second timeout\n", timeout_mutex);
err = mutex_acquire_timeout(timeout_mutex, 1000);
printf("mutex_acquire_timeout returns %d\n", err);
return err;
}
static int mutex_zerotimeout_thread(void *arg)
{
mutex_t *timeout_mutex = (mutex_t *)arg;
status_t err;
printf("mutex_zerotimeout_thread acquiring mutex %p with zero second timeout\n", timeout_mutex);
err = mutex_acquire_timeout(timeout_mutex, 0);
printf("mutex_acquire_timeout returns %d\n", err);
return err;
}
int mutex_test(void)
{
mutex_init(&m);
int i;
for(i=0; i < 5; i++)
thread_resume(thread_create("mutex tester", &mutex_thread, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_sleep(1000);
while (mutex_thread_count > 0)
thread_yield();
printf("done with simple mutex tests\n");
printf("testing mutex timeout\n");
mutex_t timeout_mutex;
mutex_init(&timeout_mutex);
mutex_acquire(&timeout_mutex);
for (i=0; i < 2; i++)
thread_resume(thread_create("mutex timeout tester", &mutex_timeout_thread, (void *)&timeout_mutex, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
for (i=0; i < 2; i++)
thread_resume(thread_create("mutex timeout tester", &mutex_zerotimeout_thread, (void *)&timeout_mutex, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_sleep(5000);
mutex_release(&timeout_mutex);
printf("done with mutex tests\n");
mutex_destroy(&timeout_mutex);
return 0;
}
static event_t e;
static int event_signaller(void *arg)
{
printf("event signaller pausing\n");
thread_sleep(1000);
// for (;;) {
printf("signalling event\n");
event_signal(&e, true);
printf("done signalling event\n");
thread_yield();
// }
return 0;
}
static int event_waiter(void *arg)
{
printf("event waiter starting\n");
for (;;) {
printf("%p: waiting on event...\n", current_thread);
if (event_wait(&e) < 0) {
printf("%p: event_wait() returned error\n", current_thread);
return -1;
}
printf("%p: done waiting on event...\n", current_thread);
thread_yield();
}
return 0;
}
void event_test(void)
{
/* make sure signalling the event wakes up all the threads */
event_init(&e, false, 0);
thread_resume(thread_create("event signaller", &event_signaller, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("event waiter 0", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("event waiter 1", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("event waiter 2", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("event waiter 3", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_sleep(2000);
event_destroy(&e);
/* make sure signalling the event wakes up precisely one thread */
event_init(&e, false, EVENT_FLAG_AUTOUNSIGNAL);
thread_resume(thread_create("event signaller", &event_signaller, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("event waiter 0", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("event waiter 1", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("event waiter 2", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("event waiter 3", &event_waiter, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_sleep(2000);
event_destroy(&e);
}
static int quantum_tester(void *arg)
{
for (;;) {
printf("%p: in this thread. rq %d\n", current_thread, current_thread->remaining_quantum);
}
return 0;
}
void quantum_test(void)
{
thread_resume(thread_create("quantum tester 0", &quantum_tester, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("quantum tester 1", &quantum_tester, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("quantum tester 2", &quantum_tester, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("quantum tester 3", &quantum_tester, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
}
static event_t context_switch_event;
static event_t context_switch_done_event;
static int context_switch_tester(void *arg)
{
int i;
uint total_count = 0;
const int iter = 100000;
int thread_count = (int)arg;
event_wait(&context_switch_event);
uint count = debug_cycle_count();
for (i = 0; i < iter; i++) {
thread_yield();
}
total_count += debug_cycle_count() - count;
thread_sleep(1000);
printf("took %u cycles to yield %d times, %u per yield, %u per yield per thread\n",
total_count, iter, total_count / iter, total_count / iter / thread_count);
event_signal(&context_switch_done_event, true);
return 0;
}
void context_switch_test(void)
{
event_init(&context_switch_event, false, 0);
event_init(&context_switch_done_event, false, 0);
thread_resume(thread_create("context switch idle", &context_switch_tester, (void *)1, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_sleep(100);
event_signal(&context_switch_event, true);
event_wait(&context_switch_done_event);
thread_sleep(100);
event_unsignal(&context_switch_event);
event_unsignal(&context_switch_done_event);
thread_resume(thread_create("context switch 2a", &context_switch_tester, (void *)2, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("context switch 2b", &context_switch_tester, (void *)2, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_sleep(100);
event_signal(&context_switch_event, true);
event_wait(&context_switch_done_event);
thread_sleep(100);
event_unsignal(&context_switch_event);
event_unsignal(&context_switch_done_event);
thread_resume(thread_create("context switch 4a", &context_switch_tester, (void *)4, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("context switch 4b", &context_switch_tester, (void *)4, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("context switch 4c", &context_switch_tester, (void *)4, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("context switch 4d", &context_switch_tester, (void *)4, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
thread_sleep(100);
event_signal(&context_switch_event, true);
event_wait(&context_switch_done_event);
thread_sleep(100);
}
static volatile int atomic;
static volatile int atomic_count;
static int atomic_tester(void *arg)
{
int add = (int)arg;
int i;
TRACEF("add %d\n", add);
for (i=0; i < 1000000; i++) {
atomic_add(&atomic, add);
}
int old = atomic_add(&atomic_count, -1);
TRACEF("exiting, old count %d\n", old);
return 0;
}
static void atomic_test(void)
{
atomic = 0;
atomic_count = 8;
thread_resume(thread_create("atomic tester 1", &atomic_tester, (void *)1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("atomic tester 1", &atomic_tester, (void *)1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("atomic tester 1", &atomic_tester, (void *)1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("atomic tester 1", &atomic_tester, (void *)1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("atomic tester 2", &atomic_tester, (void *)-1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("atomic tester 2", &atomic_tester, (void *)-1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("atomic tester 2", &atomic_tester, (void *)-1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
thread_resume(thread_create("atomic tester 2", &atomic_tester, (void *)-1, LOW_PRIORITY, DEFAULT_STACK_SIZE));
while (atomic_count > 0) {
thread_sleep(1);
}
printf("atomic count == %d (should be zero)\n", atomic);
}
int thread_tests(void)
{
mutex_test();
event_test();
thread_sleep(200);
context_switch_test();
atomic_test();
return 0;
}

72
lk/arch/arm/arch.c Normal file
View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <debug.h>
#include <arch.h>
#include <arch/ops.h>
#include <arch/arm.h>
#include <arch/arm/mmu.h>
#include <platform.h>
#if ARM_CPU_CORTEX_A8
static void set_vector_base(addr_t addr)
{
__asm__ volatile("mcr p15, 0, %0, c12, c0, 0" :: "r" (addr));
}
#endif
void arch_early_init(void)
{
/* turn off the cache */
arch_disable_cache(UCACHE);
/* set the vector base to our exception vectors so we dont need to double map at 0 */
#if ARM_CPU_CORTEX_A8
set_vector_base(MEMBASE);
#endif
#if ARM_WITH_MMU
arm_mmu_init();
platform_init_mmu_mappings();
#endif
/* turn the cache back on */
arch_enable_cache(UCACHE);
#if ARM_WITH_NEON
/* enable cp10 and cp11 */
uint32_t val;
__asm__ volatile("mrc p15, 0, %0, c1, c0, 2" : "=r" (val));
val |= (3<<22)|(3<<20);
__asm__ volatile("mcr p15, 0, %0, c1, c0, 2" :: "r" (val));
/* set enable bit in fpexc */
val = (1<<30);
__asm__ volatile("mcr p10, 7, %0, c8, c0, 0" :: "r" (val));
#endif
}
void arch_init(void)
{
}

103
lk/arch/arm/asm.S Normal file
View File

@ -0,0 +1,103 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <asm.h>
/* context switch frame is as follows:
* ulr
* usp
* lr
* r11
* r10
* r9
* r8
* r7
* r6
* r5
* r4
*/
/* arm_context_switch(addr_t *old_sp, addr_t new_sp) */
FUNCTION(arm_context_switch)
/* save all the usual registers + user regs */
/* the spsr is saved and restored in the iframe by exceptions.S */
sub r3, sp, #(11*4) /* can't use sp in user mode stm */
mov r12, lr
stmia r3, { r4-r11, r12, r13, r14 }^
/* save old sp */
str r3, [r0]
/* clear any exlusive locks that the old thread holds */
#if ARM_ISA_ARMV7
/* can clear it directly */
.word 0xf57ff01f // clrex
#elif ARM_ISA_ARMV6
/* have to do a fake strex to clear it */
ldr r0, =strex_spot
strex r3, r2, [r0]
#endif
/* load new regs */
ldmia r1, { r4-r11, r12, r13, r14 }^
mov lr, r12 /* restore lr */
add sp, r1, #(11*4) /* restore sp */
bx lr
.ltorg
FUNCTION(arm_save_mode_regs)
mrs r1, cpsr
#if ARM_ISA_ARMv6
cps #0x11 /* fiq */
str r13, [r0], #4
str r14, [r0], #4
cps #0x12 /* irq */
str r13, [r0], #4
str r14, [r0], #4
cps #0x13 /* svc */
str r13, [r0], #4
str r14, [r0], #4
cps #0x17 /* abt */
str r13, [r0], #4
str r14, [r0], #4
cps #0x1b /* und */
str r13, [r0], #4
str r14, [r0], #4
cps #0x1f /* sys */
str r13, [r0], #4
str r14, [r0], #4
#else
// XXX implement
b .
#endif
msr cpsr_c, r1
bx lr
.data
strex_spot:
.word 0

366
lk/arch/arm/cache-ops.S Normal file
View File

@ -0,0 +1,366 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <asm.h>
#include <arch/ops.h>
#include <arch/defines.h>
.text
#if ARM_WITH_CACHE
/* low level cache routines for various cpu families */
#if ARM_CPU_ARM1136 || ARM_CPU_ARM926
/* void arch_disable_cache(uint flags) */
FUNCTION(arch_disable_cache)
mov r12, #0 // zero register
mrs r3, cpsr // save the old interrupt state
#if ARM_ISA_ARMv6
.word 0xf10c01c0 /* cpsid iaf */ // interrupts disabled
#else
orr r3, r3, #(1<<7)
msr cpsr, r3
#endif
.Ldcache_disable:
tst r0, #DCACHE
beq .Licache_disable
mrc p15, 0, r1, c1, c0, 0 // cr1
tst r1, #(1<<2) // is the dcache already disabled?
beq .Licache_disable
bic r1, #(1<<2)
mcr p15, 0, r1, c1, c0, 0 // disable dcache
#if ARM_CPU_ARM1136
mcr p15, 0, r12, c7, c14, 0 // clean & invalidate dcache
#elif ARM_CPU_ARM926
0:
mrc p15, 0, r15, c7, c14, 3 // clean & invalidate dcache
bne 0b
#else
#error whut?
#endif
mcr p15, 0, r0, c7, c10, 4 // data sync barrier (formerly drain write buffer)
.Licache_disable:
tst r0, #ICACHE
beq .Ldone_disable
mrc p15, 0, r1, c1, c0, 0 // cr1
bic r1, #(1<<12)
mcr p15, 0, r1, c1, c0, 0 // disable icache
mcr p15, 0, r12, c7, c5, 0 // invalidate icache
.Ldone_disable:
msr cpsr, r3
bx lr
/* void arch_enable_cache(uint flags) */
FUNCTION(arch_enable_cache)
mov r12, #0 // zero register
mrs r3, cpsr // save the old interrupt state
#if ARM_ISA_ARMv6
.word 0xf10c01c0 /* cpsid iaf */ // interrupts disabled
#else
orr r3, r3, #(1<<7)
msr cpsr, r3
#endif
.Ldcache_enable:
tst r0, #DCACHE
beq .Licache_enable
mrc p15, 0, r1, c1, c0, 0 // cr1
tst r1, #(1<<2) // is the dcache already enabled?
bne .Licache_enable
mcr p15, 0, r12, c7, c6, 0 // invalidate dcache
orr r1, #(1<<2)
mcr p15, 0, r1, c1, c0, 0 // enable dcache
.Licache_enable:
tst r0, #ICACHE
beq .Ldone_enable
mcr p15, 0, r12, c7, c5, 0 // invalidate icache
mrc p15, 0, r1, c1, c0, 0 // cr1
orr r1, #(1<<12)
mcr p15, 0, r1, c1, c0, 0 // enable icache
.Ldone_enable:
msr cpsr, r3
bx lr
#elif ARM_CPU_CORTEX_A8
/* void arch_disable_cache(uint flags) */
FUNCTION(arch_disable_cache)
stmfd sp!, {r4-r11, lr}
mov r7, r0 // save flags
mrs r12, cpsr // save the old interrupt state
.word 0xf10c01c0 /* cpsid iaf */ // interrupts disabled
.Ldcache_disable:
tst r7, #DCACHE
beq .Licache_disable
mrc p15, 0, r0, c1, c0, 0 // cr1
tst r0, #(1<<2) // is the dcache already disabled?
beq .Ldcache_already_disabled
bic r0, #(1<<2)
mcr p15, 0, r0, c1, c0, 0 // disable dcache
// flush and invalidate the dcache
// NOTE: trashes a bunch of registers, can't be spilling stuff to the stack
bl flush_invalidate_cache_v7
b .Ldcache_disable_L2
.Ldcache_already_disabled:
// make sure all of the caches are invalidated
// NOTE: trashes a bunch of registers, can't be spilling stuff to the stack
bl invalidate_cache_v7
.Ldcache_disable_L2:
#if ARM_WITH_L2
// disable the L2, if present
mrc p15, 0, r0, c1, c0, 1 // aux cr1
bic r0, #(1<<1)
mcr p15, 0, r0, c1, c0, 1 // disable L2 dcache
#endif
.Licache_disable:
tst r7, #ICACHE
beq .Ldone_disable
mrc p15, 0, r0, c1, c0, 0 // cr1
bic r0, #(1<<12)
mcr p15, 0, r0, c1, c0, 0 // disable icache
.Ldone_disable:
// make sure the icache is always invalidated
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 // invalidate icache to PoU
msr cpsr, r12
ldmfd sp!, {r4-r11, pc}
/* void arch_enable_cache(uint flags) */
FUNCTION(arch_enable_cache)
stmfd sp!, {r4-r11, lr}
mov r7, r0 // save flags
mrs r12, cpsr // save the old interrupt state
.word 0xf10c01c0 /* cpsid iaf */ // interrupts disabled
.Ldcache_enable:
tst r7, #DCACHE
beq .Licache_enable
mrc p15, 0, r0, c1, c0, 0 // cr1
tst r0, #(1<<2) // is the dcache already enabled?
bne .Licache_enable
// invalidate L1 and L2
// NOTE: trashes a bunch of registers, can't be spilling stuff to the stack
bl invalidate_cache_v7
#if ARM_WITH_L2
// enable the L2, if present
mrc p15, 0, r0, c1, c0, 1 // aux cr1
orr r0, #(1<<1)
mcr p15, 0, r0, c1, c0, 1 // enable L2 dcache
#endif
mrc p15, 0, r0, c1, c0, 0 // cr1
orr r0, #(1<<2)
mcr p15, 0, r0, c1, c0, 0 // enable dcache
.Licache_enable:
tst r7, #ICACHE
beq .Ldone_enable
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 // invalidate icache to PoU
mrc p15, 0, r0, c1, c0, 0 // cr1
orr r0, #(1<<12)
mcr p15, 0, r0, c1, c0, 0 // enable icache
.Ldone_enable:
msr cpsr, r12
ldmfd sp!, {r4-r11, pc}
// flush & invalidate cache routine, trashes r0-r6, r9-r11
flush_invalidate_cache_v7:
/* from ARMv7 manual, B2-17 */
MRC p15, 1, R0, c0, c0, 1 // Read CLIDR
ANDS R3, R0, #0x7000000
MOV R3, R3, LSR #23 // Cache level value (naturally aligned)
BEQ .Lfinished
MOV R10, #0
.Loop1:
ADD R2, R10, R10, LSR #1 // Work out 3xcachelevel
MOV R1, R0, LSR R2 // bottom 3 bits are the Cache type for this level
AND R1, R1, #7 // get those 3 bits alone
CMP R1, #2
BLT .Lskip // no cache or only instruction cache at this level
MCR p15, 2, R10, c0, c0, 0 // write the Cache Size selection register
.word 0xf57ff06f // ISB // ISB to sync the change to the CacheSizeID reg
MRC p15, 1, R1, c0, c0, 0 // reads current Cache Size ID register
AND R2, R1, #0x7 // extract the line length field
ADD R2, R2, #4 // add 4 for the line length offset (log2 16 bytes)
LDR R4, =0x3FF
ANDS R4, R4, R1, LSR #3 // R4 is the max number on the way size (right aligned)
CLZ R5, R4 // R5 is the bit position of the way size increment
LDR R6, =0x00007FFF
ANDS R6, R6, R1, LSR #13 // R6 is the max number of the index size (right aligned)
.Loop2:
MOV R9, R4 // R9 working copy of the max way size (right aligned)
.Loop3:
ORR R11, R10, R9, LSL R5 // factor in the way number and cache number into R11
ORR R11, R11, R6, LSL R2 // factor in the index number
MCR p15, 0, R11, c7, c14, 2 // clean & invalidate by set/way
SUBS R9, R9, #1 // decrement the way number
BGE .Loop3
SUBS R6, R6, #1 // decrement the index
BGE .Loop2
.Lskip:
ADD R10, R10, #2 // increment the cache number
CMP R3, R10
BGT .Loop1
.Lfinished:
mov r10, #0
mcr p15, 2, r10, c0, c0, 0 // select cache level 0
.word 0xf57ff06f // isb
bx lr
// invalidate cache routine, trashes r0-r6, r9-r11
invalidate_cache_v7:
/* from ARMv7 manual, B2-17 */
MRC p15, 1, R0, c0, c0, 1 // Read CLIDR
ANDS R3, R0, #0x7000000
MOV R3, R3, LSR #23 // Cache level value (naturally aligned)
BEQ .Lfinished_invalidate
MOV R10, #0
.Loop1_invalidate:
ADD R2, R10, R10, LSR #1 // Work out 3xcachelevel
MOV R1, R0, LSR R2 // bottom 3 bits are the Cache type for this level
AND R1, R1, #7 // get those 3 bits alone
CMP R1, #2
BLT .Lskip_invalidate // no cache or only instruction cache at this level
MCR p15, 2, R10, c0, c0, 0 // write the Cache Size selection register
.word 0xf57ff06f // ISB // ISB to sync the change to the CacheSizeID reg
MRC p15, 1, R1, c0, c0, 0 // reads current Cache Size ID register
AND R2, R1, #0x7 // extract the line length field
ADD R2, R2, #4 // add 4 for the line length offset (log2 16 bytes)
LDR R4, =0x3FF
ANDS R4, R4, R1, LSR #3 // R4 is the max number on the way size (right aligned)
CLZ R5, R4 // R5 is the bit position of the way size increment
LDR R6, =0x00007FFF
ANDS R6, R6, R1, LSR #13 // R6 is the max number of the index size (right aligned)
.Loop2_invalidate:
MOV R9, R4 // R9 working copy of the max way size (right aligned)
.Loop3_invalidate:
ORR R11, R10, R9, LSL R5 // factor in the way number and cache number into R11
ORR R11, R11, R6, LSL R2 // factor in the index number
MCR p15, 0, R11, c7, c6, 2 // invalidate by set/way
SUBS R9, R9, #1 // decrement the way number
BGE .Loop3_invalidate
SUBS R6, R6, #1 // decrement the index
BGE .Loop2_invalidate
.Lskip_invalidate:
ADD R10, R10, #2 // increment the cache number
CMP R3, R10
BGT .Loop1_invalidate
.Lfinished_invalidate:
mov r10, #0
mcr p15, 2, r10, c0, c0, 0 // select cache level 0
.word 0xf57ff06f // isb
bx lr
#else
#error unhandled cpu
#endif
#if ARM_CPU_ARM926 || ARM_CPU_ARM1136 || ARM_CPU_CORTEX_A8
/* shared cache flush routines */
/* void arch_flush_cache_range(addr_t start, size_t len); */
FUNCTION(arch_clean_cache_range)
0:
mcr p15, 0, r0, c7, c10, 1 // clean cache to PoC by MVA
add r0, r0, #CACHE_LINE
subs r1, r1, #CACHE_LINE
bhs 0b
mov r0, #0
mcr p15, 0, r0, c7, c10, 4 // data sync barrier (formerly drain write buffer)
bx lr
/* void arch_flush_invalidate_cache_range(addr_t start, size_t len); */
FUNCTION(arch_clean_invalidate_cache_range)
0:
mcr p15, 0, r0, c7, c14, 1 // clean & invalidate cache to PoC by MVA
add r0, r0, #CACHE_LINE
subs r1, r1, #CACHE_LINE
bhs 0b
mov r0, #0
mcr p15, 0, r0, c7, c10, 4 // data sync barrier (formerly drain write buffer)
bx lr
#else
#error unhandled cpu
#endif
#else
/* no cache */
FUNCTION(arch_disable_cache)
bx lr
FUNCTION(arch_enable_cache)
bx lr
FUNCTION(arch_clean_cache_range)
bx lr
FUNCTION(arch_clean_invalidate_cache_range)
bx lr
#endif // ARM_WITH_CACHE

22
lk/arch/arm/cache.c Normal file
View File

@ -0,0 +1,22 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

33
lk/arch/arm/compile.mk Normal file
View File

@ -0,0 +1,33 @@
$(BUILDDIR)/%.o: %.c $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) $(CFLAGS) $(THUMBCFLAGS) --std=c99 $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
$(BUILDDIR)/%.o: %.cpp $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) $(CFLAGS) $(CPPFLAGS) $(THUMBCFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
# to override thumb setting, mark the .o file as .Ao
$(BUILDDIR)/%.Ao: %.c $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) $(CFLAGS) --std=c99 $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
$(BUILDDIR)/%.Ao: %.cpp $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) $(CFLAGS) $(CPPFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
# assembly is always compiled in ARM mode at the moment
$(BUILDDIR)/%.Ao: %.S $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) $(CFLAGS) $(ASMFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
$(BUILDDIR)/%.o: %.S $(SRCDEPS)
@$(MKDIR)
@echo compiling $<
$(NOECHO)$(CC) $(CFLAGS) $(ASMFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@

175
lk/arch/arm/crt0.S Normal file
View File

@ -0,0 +1,175 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#define DSB .byte 0x4f, 0xf0, 0x7f, 0xf5
#define ISB .byte 0x6f, 0xf0, 0x7f, 0xf5
.text
.globl _start
_start:
b reset
b arm_undefined
b arm_syscall
b arm_prefetch_abort
b arm_data_abort
b arm_reserved
b arm_irq
b arm_fiq
reset:
/* do some cpu setup */
#if ARM_WITH_CP15
mrc p15, 0, r0, c1, c0, 0
/* XXX this is currently for arm926, revist with armv6 cores */
/* new thumb behavior, low exception vectors, i/d cache disable, mmu disabled */
bic r0, r0, #(1<<15| 1<<13 | 1<<12)
bic r0, r0, #(1<<2 | 1<<0)
/* enable alignment faults */
orr r0, r0, #(1<<1)
mcr p15, 0, r0, c1, c0, 0
#endif
#if WITH_CPU_EARLY_INIT
/* call platform/arch/etc specific init code */
bl __cpu_early_init
/* declare return address as global to avoid using stack */
.globl _cpu_early_init_complete
_cpu_early_init_complete:
#endif
#if (!ENABLE_NANDWRITE)
#if WITH_CPU_WARM_BOOT
ldr r0, warm_boot_tag
cmp r0, #1
/* if set, warm boot */
ldreq pc, =BASE_ADDR
mov r0, #1
str r0, warm_boot_tag
#endif
#endif
/* see if we need to relocate */
mov r0, pc
sub r0, r0, #(.Laddr - _start)
.Laddr:
ldr r1, =_start
cmp r0, r1
beq .Lstack_setup
/* we need to relocate ourselves to the proper spot */
ldr r2, =__data_end
.Lrelocate_loop:
ldr r3, [r0], #4
str r3, [r1], #4
cmp r1, r2
bne .Lrelocate_loop
/* we're relocated, jump to the right address */
ldr r0, =.Lstack_setup
bx r0
.ltorg
#if WITH_CPU_WARM_BOOT
warm_boot_tag:
.word 0
#endif
.Lstack_setup:
/* set up the stack for irq, fiq, abort, undefined, system/user, and lastly supervisor mode */
mrs r0, cpsr
bic r0, r0, #0x1f
ldr r2, =abort_stack_top
orr r1, r0, #0x12 // irq
msr cpsr_c, r1
ldr r13, =irq_save_spot /* save a pointer to a temporary dumping spot used during irq delivery */
orr r1, r0, #0x11 // fiq
msr cpsr_c, r1
mov sp, r2
orr r1, r0, #0x17 // abort
msr cpsr_c, r1
mov sp, r2
orr r1, r0, #0x1b // undefined
msr cpsr_c, r1
mov sp, r2
orr r1, r0, #0x1f // system
msr cpsr_c, r1
mov sp, r2
orr r1, r0, #0x13 // supervisor
msr cpsr_c, r1
mov sp, r2
/* copy the initialized data segment out of rom if necessary */
ldr r0, =__data_start_rom
ldr r1, =__data_start
ldr r2, =__data_end
cmp r0, r1
beq .L__do_bss
.L__copy_loop:
cmp r1, r2
ldrlt r3, [r0], #4
strlt r3, [r1], #4
blt .L__copy_loop
.L__do_bss:
/* clear out the bss */
ldr r0, =__bss_start
ldr r1, =_end
mov r2, #0
.L__bss_loop:
cmp r0, r1
strlt r2, [r0], #4
blt .L__bss_loop
#ifdef ARM_CPU_CORTEX_A8
DSB
ISB
#endif
bl kmain
b .
.ltorg
.bss
.align 2
/* the abort stack is for unrecoverable errors.
* also note the initial working stack is set to here.
* when the threading system starts up it'll switch to a new
* dynamically allocated stack, so we don't need it for very long
*/
abort_stack:
.skip 1024
abort_stack_top:

41
lk/arch/arm/dcc.S Normal file
View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2008 Brian Swetland
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
.global dcc_putc
.global dcc_getc
#if defined(ARM_ISA_ARMV6) || defined(ARM_ISA_ARMV7)
dcc_getc:
mrc 14, 0, r0, c0, c1, 0
tst r0, #(1 << 30)
moveq r0, #-1
mrcne 14, 0, r0, c0, c5, 0
bx lr
dcc_putc:
mrc 14, 0, r15, c0, c1, 0
mcrcc 14, 0, r0, c0, c5, 0
movcc r0, #0
movcs r0, #-1
bx lr
#endif

132
lk/arch/arm/exceptions.S Normal file
View File

@ -0,0 +1,132 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <asm.h>
FUNCTION(arm_undefined)
stmfd sp!, { r0-r12, r14 }
sub sp, sp, #12
mov r0, sp
mrs r1, spsr
stmia r0, { r1, r13-r14 }^
b arm_undefined_handler
b .
FUNCTION(arm_syscall)
stmfd sp!, { r0-r12, r14 }
sub sp, sp, #12
mov r0, sp
mrs r1, spsr
stmia r0, { r1, r13-r14 }^
b arm_syscall_handler
b .
FUNCTION(arm_prefetch_abort)
stmfd sp!, { r0-r12, r14 }
sub sp, sp, #12
mov r0, sp
mrs r1, spsr
stmia r0, { r1, r13-r14 }^
b arm_prefetch_abort_handler
b .
FUNCTION(arm_data_abort)
stmfd sp!, { r0-r12, r14 }
sub sp, sp, #12
mov r0, sp
mrs r1, spsr
stmia r0, { r1, r13-r14 }^
b arm_data_abort_handler
b .
FUNCTION(arm_reserved)
b .
FUNCTION(arm_irq)
/* XXX only deals with interrupting supervisor mode */
/* save r4-r6 and use as a temporary place to save while we switch into supervisor mode */
stmia r13, { r4-r6 }
mov r4, r13
sub r5, lr, #4
mrs r6, spsr
/* move into supervisor mode. irq/fiq disabled */
msr cpsr_c, #(3<<6 | 0x13)
/* save the return address */
stmfd sp!, { r5 }
/* save C trashed regs, supervisor lr */
stmfd sp!, { r0-r3, r12, lr }
/* save spsr */
stmfd sp!, { r6 }
/* restore r4-r6 */
ldmia r4, { r4-r6 }
/* increment the global critical section count */
ldr r1, =critical_section_count
ldr r0, [r1]
add r0, r0, #1
str r0, [r1]
/* call into higher level code */
mov r0, sp /* iframe */
bl platform_irq
/* reschedule if the handler returns nonzero */
cmp r0, #0
blne thread_preempt
/* decrement the global critical section count */
ldr r1, =critical_section_count
ldr r0, [r1]
sub r0, r0, #1
str r0, [r1]
/* restore spsr */
ldmfd sp!, { r0 }
msr spsr_cxsf, r0
/* restore back to where we came from */
ldmfd sp!, { r0-r3, r12, lr, pc }^
.bss
.align 2
.global irq_save_spot
irq_save_spot:
.word 0 /* r4 */
.word 0 /* r5 */
.word 0 /* r6 */
.text
FUNCTION(arm_fiq)
sub lr, lr, #4
stmfd sp!, { r0-r3, r12, lr }
bl platform_fiq
ldmfd sp!, { r0-r3, r12, pc }^
.ltorg

91
lk/arch/arm/faults.c Normal file
View File

@ -0,0 +1,91 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <debug.h>
#include <arch/arm.h>
#include <kernel/thread.h>
static void dump_fault_frame(struct arm_fault_frame *frame)
{
dprintf(CRITICAL, "r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\n", frame->r[0], frame->r[1], frame->r[2], frame->r[3]);
dprintf(CRITICAL, "r4 0x%08x r5 0x%08x r6 0x%08x r7 0x%08x\n", frame->r[4], frame->r[5], frame->r[6], frame->r[7]);
dprintf(CRITICAL, "r8 0x%08x r9 0x%08x r10 0x%08x r11 0x%08x\n", frame->r[8], frame->r[9], frame->r[10], frame->r[11]);
dprintf(CRITICAL, "r12 0x%08x usp 0x%08x ulr 0x%08x pc 0x%08x\n", frame->r[12], frame->usp, frame->ulr, frame->pc);
dprintf(CRITICAL, "spsr 0x%08x\n", frame->spsr);
struct arm_mode_regs regs;
arm_save_mode_regs(&regs);
dprintf(CRITICAL, "%c%s r13 0x%08x r14 0x%08x\n", ((frame->spsr & MODE_MASK) == MODE_FIQ) ? '*' : ' ', "fiq", regs.fiq_r13, regs.fiq_r14);
dprintf(CRITICAL, "%c%s r13 0x%08x r14 0x%08x\n", ((frame->spsr & MODE_MASK) == MODE_IRQ) ? '*' : ' ', "irq", regs.irq_r13, regs.irq_r14);
dprintf(CRITICAL, "%c%s r13 0x%08x r14 0x%08x\n", ((frame->spsr & MODE_MASK) == MODE_SVC) ? '*' : ' ', "svc", regs.svc_r13, regs.svc_r14);
dprintf(CRITICAL, "%c%s r13 0x%08x r14 0x%08x\n", ((frame->spsr & MODE_MASK) == MODE_UND) ? '*' : ' ', "und", regs.und_r13, regs.und_r14);
dprintf(CRITICAL, "%c%s r13 0x%08x r14 0x%08x\n", ((frame->spsr & MODE_MASK) == MODE_SYS) ? '*' : ' ', "sys", regs.sys_r13, regs.sys_r14);
// dump the bottom of the current stack
addr_t stack;
switch (frame->spsr & MODE_MASK) {
case MODE_FIQ: stack = regs.fiq_r13; break;
case MODE_IRQ: stack = regs.irq_r13; break;
case MODE_SVC: stack = regs.svc_r13; break;
case MODE_UND: stack = regs.und_r13; break;
case MODE_SYS: stack = regs.sys_r13; break;
default:
stack = 0;
}
if (stack != 0) {
dprintf(CRITICAL, "bottom of stack at 0x%08x:\n", (unsigned int)stack);
hexdump((void *)stack, 128);
}
}
static void exception_die(struct arm_fault_frame *frame, int pc_off, const char *msg)
{
inc_critical_section();
frame->pc += pc_off;
dprintf(CRITICAL, msg);
dump_fault_frame(frame);
halt();
for(;;);
}
void arm_syscall_handler(struct arm_fault_frame *frame)
{
exception_die(frame, -4, "unhandled syscall, halting\n");
}
void arm_undefined_handler(struct arm_fault_frame *frame)
{
exception_die(frame, -4, "undefined abort, halting\n");
}
void arm_data_abort_handler(struct arm_fault_frame *frame)
{
exception_die(frame, -8, "data abort, halting\n");
}
void arm_prefetch_abort_handler(struct arm_fault_frame *frame)
{
exception_die(frame, -4, "prefetch abort, halting\n");
}

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __ARM_ARCH_THREAD_H
#define __ARM_ARCH_THREAD_H
struct arch_thread {
vaddr_t sp;
};
#endif

View File

@ -0,0 +1,94 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __ARCH_ARM_H
#define __ARCH_ARM_H
#include <sys/types.h>
#include <arch/arm/cores.h>
#if defined(__cplusplus)
extern "C" {
#endif
void arm_context_switch(vaddr_t *old_sp, vaddr_t new_sp);
static inline uint32_t read_cpsr() {
uint32_t cpsr;
__asm__ volatile("mrs %0, cpsr" : "=r" (cpsr));
return cpsr;
}
struct arm_iframe {
uint32_t spsr;
uint32_t r0;
uint32_t r1;
uint32_t r2;
uint32_t r3;
uint32_t r12;
uint32_t lr;
uint32_t pc;
};
struct arm_fault_frame {
uint32_t spsr;
uint32_t usp;
uint32_t ulr;
uint32_t r[13];
uint32_t pc;
};
#define MODE_MASK 0x1f
#define MODE_USR 0x10
#define MODE_FIQ 0x11
#define MODE_IRQ 0x12
#define MODE_SVC 0x13
#define MODE_MON 0x16
#define MODE_ABT 0x17
#define MODE_UND 0x1b
#define MODE_SYS 0x1f
struct arm_mode_regs {
uint32_t fiq_r13, fiq_r14;
uint32_t irq_r13, irq_r14;
uint32_t svc_r13, svc_r14;
uint32_t abt_r13, abt_r14;
uint32_t und_r13, und_r14;
uint32_t sys_r13, sys_r14;
};
void arm_save_mode_regs(struct arm_mode_regs *regs);
uint32_t arm_read_cr1(void);
void arm_write_cr1(uint32_t val);
uint32_t arm_read_cr1_aux(void);
void arm_write_cr1_aux(uint32_t val);
void arm_write_ttbr(uint32_t val);
void arm_write_dacr(uint32_t val);
void arm_invalidate_tlb(void);
#if defined(__cplusplus)
}
#endif
#endif

View File

@ -0,0 +1,122 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __ARM_CORES_H
#define __ARM_CORES_H
/*
* make the gcc built in define a little easier to deal with
* to decide what core it is generating code for
*
* ARM_ARCH_LEVEL gets assigned a numeric value of the general family
*
* ARM_ARCH_* gets defined for each feature recursively
*/
#if defined(__ARM_ARCH_7M__)
#define ARM_ARCH_7M 1
#endif
#if defined(__ARM_ARCH_7R__)
#define ARM_ARCH_7R 1
#endif
#if defined(__ARM_ARCH_7A__) || defined(ARM_ARCH_7R)
#define ARM_ARCH_7A 1
#endif
#if defined(__ARM_ARCH_7__) || defined(ARM_ARCH_7A) || defined(ARM_ARCH_7M)
#define ARM_ARCH_7 1
#ifndef ARM_ARCH_LEVEL
#define ARM_ARCH_LEVEL 7
#endif
#endif
#if defined(__ARM_ARCH_6M__)
#define ARM_ARCH_6M 1
#endif
#if defined(__ARM_ARCH_6T2__) || defined(ARM_ARCH_7)
#define ARM_ARCH_6T2 1
#endif
#if defined(__ARM_ARCH_6ZK__)
#define ARM_ARCH_6ZK 1
#endif
#if defined(__ARM_ARCH_6Z__) || defined(ARM_ARCH_6ZK)
#define ARM_ARCH_6Z 1
#endif
#if defined(__ARM_ARCH_6K__) || defined(ARM_ARCH_6ZK) || defined(ARM_ARCH_7)
#define ARM_ARCH_6K 1
#endif
#if defined(__ARM_ARCH_6J__)
#define ARM_ARCH_6J 1
#endif
#if defined(__ARM_ARCH_6__) || defined(ARM_ARCH_6J) || defined(ARM_ARCH_6K) || defined(ARM_ARCH_6Z) || defined(ARM_ARCH_6T2) || defined(ARM_ARCH_6M)
#define ARM_ARCH_6 1
#ifndef ARM_ARCH_LEVEL
#define ARM_ARCH_LEVEL 6
#endif
#endif
#if defined(__ARM_ARCH_5TEJ__)
#define ARM_ARCH_5TEJ 1
#endif
#if defined(__ARM_ARCH_5TE__) || defined(ARM_ARCH_5TEJ) || defined(ARM_ARCH_6)
#define ARM_ARCH_5TE 1
#endif
#if defined(__ARM_ARCH_5E__) || defined(ARM_ARCH_5TE)
#define ARM_ARCH_5E 1
#endif
#if defined(__ARM_ARCH_5T__) || defined(ARM_ARCH_5TE)
#define ARM_ARCH_5T 1
#endif
#if defined(__ARM_ARCH_5__) || defined(ARM_ARCH_5E) || defined(ARM_ARCH_5T)
#define ARM_ARCH_5 1
#ifndef ARM_ARCH_LEVEL
#define ARM_ARCH_LEVEL 5
#endif
#endif
#if defined(__ARM_ARCH_4T__) || defined(ARM_ARCH_5T)
#define ARM_ARCH_4T 1
#endif
#if defined(__ARM_ARCH_4__) || defined(ARM_ARCH_4T) || defined(ARM_ARCH_5)
#define ARM_ARCH_4 1
#ifndef ARM_ARCH_LEVEL
#define ARM_ARCH_LEVEL 4
#endif
#endif
#if 0
/* test */
#if ARM_ARCH_LEVEL >= 7
#warning ARM_ARCH_LEVEL >= 7
#endif
#if ARM_ARCH_LEVEL >= 6
#warning ARM_ARCH_LEVEL >= 6
#endif
#if ARM_ARCH_LEVEL >= 5
#warning ARM_ARCH_LEVEL >= 5
#endif
#if ARM_ARCH_LEVEL >= 4
#warning ARM_ARCH_LEVEL >= 4
#endif
#endif
#endif

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2008 Brian Swetland
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __ARCH_ARM_DCC_H
#define __ARCH_ARM_DCC_H
/* returns < 0 if no data available */
int dcc_getc(void);
/* returns < 0 if output register was already full */
int dcc_putc(unsigned c);
#endif

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __ARCH_ARM_MMU_H
#define __ARCH_ARM_MMU_H
#include <sys/types.h>
#if defined(__cplusplus)
extern "C" {
#endif
void arm_mmu_init(void);
#define MMU_FLAG_CACHED 0x1
#define MMU_FLAG_BUFFERED 0x2
#define MMU_FLAG_READWRITE 0x4
void arm_mmu_map_section(addr_t paddr, addr_t vaddr, uint flags);
#if defined(__cplusplus)
}
#endif
#endif

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __ARCH_ARM_OPS_H
#define __ARHC_ARM_OPS_H
#if 0
#include <compiler.h>
#ifndef ASSEMBLY
#if ARM_ISA_ARMV7 || ARM_ISA_ARMV6
// override of some routines
__GNU_INLINE __ALWAYS_INLINE extern inline void arch_enable_ints(void)
{
__asm__("cpsie i");
}
__GNU_INLINE __ALWAYS_INLINE extern inline void arch_disable_ints(void)
{
__asm__("cpsid i");
}
#endif
#endif
#endif
#endif

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __ARCH_CPU_H
#define __ARCH_CPU_H
/* arm specific stuff */
#define PAGE_SIZE 4096
#if ARM_CPU_ARM7
/* irrelevant, no consistent cache */
#define CACHE_LINE 32
#elif ARM_CPU_ARM926
#define CACHE_LINE 32
#elif ARM_CPU_ARM1136
#define CACHE_LINE 32
#elif ARM_CPU_CORTEX_A8
#define CACHE_LINE 64
#else
#error unknown cpu
#endif
#endif

100
lk/arch/arm/mmu.c Normal file
View File

@ -0,0 +1,100 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <debug.h>
#include <sys/types.h>
#include <compiler.h>
#include <arch.h>
#include <arch/arm.h>
#include <arch/arm/mmu.h>
#if ARM_WITH_MMU
#define MB (1024*1024)
/* the location of the table may be brought in from outside */
#if WITH_EXTERNAL_TRANSLATION_TABLE
#if !defined(MMU_TRANSLATION_TABLE_ADDR)
#error must set MMU_TRANSLATION_TABLE_ADDR in the make configuration
#endif
static uint32_t *tt = (void *)MMU_TRANSLATION_TABLE_ADDR;
#else
/* the main translation table */
static uint32_t tt[4096] __ALIGNED(16384);
#endif
void arm_mmu_map_section(addr_t paddr, addr_t vaddr, uint flags)
{
int index;
uint AP;
uint CB;
uint TEX = 0;
#if defined(PLATFORM_MSM7K)
if ((paddr >= 0x88000000) && (paddr < 0xD0000000)) {
/* peripherals in the 0x88000000 - 0xD0000000 range must
* be mapped as DEVICE NON-SHARED: TEX=2, C=0, B=0
*/
TEX = 2;
flags &= (~(MMU_FLAG_CACHED | MMU_FLAG_BUFFERED));
}
#endif
AP = (flags & MMU_FLAG_READWRITE) ? 0x3 : 0x2;
CB = ((flags & MMU_FLAG_CACHED) ? 0x2 : 0) | ((flags & MMU_FLAG_BUFFERED) ? 0x1 : 0);
index = vaddr / MB;
// section mapping
tt[index] = (paddr & ~(MB-1)) | (TEX << 12) | (AP << 10) | (0<<5) | (CB << 2) | (2<<0);
arm_invalidate_tlb();
}
void arm_mmu_init(void)
{
int i;
/* set some mmu specific control bits */
arm_write_cr1(arm_read_cr1() & ~((1<<29)|(1<<28)|(1<<0))); // access flag disabled, TEX remap disabled, mmu disabled
/* set up an identity-mapped translation table with cache disabled */
for (i=0; i < 4096; i++) {
arm_mmu_map_section(i * MB, i * MB, MMU_FLAG_READWRITE); // map everything uncached
}
/* set up the translation table base */
arm_write_ttbr((uint32_t)tt);
/* set up the domain access register */
arm_write_dacr(0x00000001);
/* turn on the mmu */
arm_write_cr1(arm_read_cr1() | 0x1);
}
void arch_disable_mmu(void)
{
arm_write_cr1(arm_read_cr1() & ~(1<<0)); // access flag disabled, TEX remap disabled, mmu disabled
}
#endif // ARM_WITH_MMU

213
lk/arch/arm/ops.S Normal file
View File

@ -0,0 +1,213 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <asm.h>
.text
/* void arch_enable_ints(void); */
FUNCTION(arch_enable_ints)
mrs r0, cpsr
bic r0, r0, #(1<<7) /* clear the I bit */
msr cpsr_c, r0
bx lr
/* void arch_disable_ints(void); */
FUNCTION(arch_disable_ints)
mrs r0, cpsr
orr r0, r0, #(1<<7)
msr cpsr_c, r0
bx lr
/* int atomic_swap(int *ptr, int val); */
FUNCTION(atomic_swap)
swp r0, r2, [r1]
bx lr
/* int atomic_add(int *ptr, int val); */
FUNCTION(atomic_add)
#if ARM_ISA_ARMV6 || ARM_ISA_ARMV7
/* use load/store exclusive */
.L_loop_add:
ldrex r12, [r0]
add r2, r12, r1
strex r3, r2, [r0]
cmp r3, #0
bne .L_loop_add
/* save old value */
mov r0, r12
bx lr
#else
/* disable interrupts, do the add, and reenable */
mrs r2, cpsr
mov r12, r2
orr r2, r2, #(3<<6)
msr cpsr_c, r2
/* ints disabled, old cpsr state in r12 */
/* do the add, leave the previous value in r0 */
mov r3, r0
ldr r0, [r3]
add r2, r0, r1
str r2, [r3]
/* restore interrupts and exit */
msr cpsr_c, r12
bx lr
#endif
/* int atomic_and(int *ptr, int val); */
FUNCTION(atomic_and)
#if ARM_ISA_ARMV6 || ARM_ISA_ARMV7
/* use load/store exclusive */
.L_loop_and:
ldrex r12, [r0]
and r2, r12, r1
strex r3, r2, [r0]
cmp r3, #0
bne .L_loop_and
/* save old value */
mov r0, r12
bx lr
#else
/* disable interrupts, do the and, and reenable */
mrs r2, cpsr
mov r12, r2
orr r2, r2, #(3<<6)
msr cpsr_c, r2
/* ints disabled, old cpsr state in r12 */
/* do the and, leave the previous value in r0 */
mov r3, r0
ldr r0, [r3]
and r2, r0, r1
str r2, [r3]
/* restore interrupts and exit */
msr cpsr_c, r12
bx lr
#endif
/* int atomic_or(int *ptr, int val); */
FUNCTION(atomic_or)
#if ARM_ISA_ARMV6 || ARM_ISA_ARMV7
/* use load/store exclusive */
.L_loop_or:
ldrex r12, [r0]
orr r2, r12, r1
strex r3, r2, [r0]
cmp r3, #0
bne .L_loop_or
/* save old value */
mov r0, r12
bx lr
#else
/* disable interrupts, do the or, and reenable */
mrs r2, cpsr
mov r12, r2
orr r2, r2, #(3<<6)
msr cpsr_c, r2
/* ints disabled, old cpsr state in r12 */
/* do the or, leave the previous value in r0 */
mov r3, r0
ldr r0, [r3]
orr r2, r0, r1
str r2, [r3]
/* restore interrupts and exit */
msr cpsr_c, r12
bx lr
#endif
/* void arch_idle(); */
FUNCTION(arch_idle)
#if ARM_CPU_CORTEX_A8
.word 0xe320f003 /* wfi */
#elif PLATFORM_MSM7K
/* TODO: safely handle wfi */
#elif ARM_CPU_ARM1136 || ARM_CPU_ARM926
mov r0, #0
mcr p15, 0, r0, c7, c0, #4
#elif ARM_CPU_ARM7
/* nothing to do here */
#else
#error unknown cpu
#endif
bx lr
/* uint32_t arm_read_cr1(void) */
FUNCTION(arm_read_cr1)
mrc p15, 0, r0, c1, c0, 0
bx lr
/* void arm_write_cr1(uint32_t val) */
FUNCTION(arm_write_cr1)
mcr p15, 0, r0, c1, c0, 0
bx lr
/* uint32_t arm_read_cr1_aux(void) */
FUNCTION(arm_read_cr1_aux)
mrc p15, 0, r0, c1, c0, 1
bx lr
/* void arm_write_cr1_aux(uint32_t val) */
FUNCTION(arm_write_cr1_aux)
mcr p15, 0, r0, c1, c0, 1
bx lr
/* void arm_write_ttbr(uint32_t val) */
FUNCTION(arm_write_ttbr)
mcr p15, 0, r0, c2, c0, 0
bx lr
/* void arm_write_dacr(uint32_t val) */
FUNCTION(arm_write_dacr)
mcr p15, 0, r0, c3, c0, 0
bx lr
/* void arm_invalidate_tlb(void) */
FUNCTION(arm_invalidate_tlb)
mov r0, #0
mcr p15, 0, r0, c8, c7, 0
bx lr
/* void arch_switch_stacks_and_call(addr_t call, addr_t stack) */
FUNCTION(arch_switch_stacks_and_call)
mov sp, r1
bx r0
/*void dmb(void) */
FUNCTION(dmb)
#if ARM_CPU_CORTEX_A8
dmb sy
#elif ARM_CPU_ARM1136
mov r0, #0
mcr p15, 0, r0, c7, c10, 5
#endif
bx lr

142
lk/arch/arm/rules.mk Normal file
View File

@ -0,0 +1,142 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
# can override this in local.mk
ENABLE_THUMB?=true
DEFINES += \
ARM_CPU_$(ARM_CPU)=1
# do set some options based on the cpu core
HANDLED_CORE := false
ifeq ($(ARM_CPU),cortex-a8)
DEFINES += \
ARM_WITH_CP15=1 \
ARM_WITH_MMU=1 \
ARM_ISA_ARMv7=1 \
ARM_WITH_VFP=1 \
ARM_WITH_NEON=1 \
ARM_WITH_THUMB=1 \
ARM_WITH_THUMB2=1 \
ARM_WITH_CACHE=1 \
ARM_WITH_L2=1
CFLAGS += -mcpu=$(ARM_CPU)
#CFLAGS += -mcpu=arm1136jf-s # compiler doesn't understand cortex yet
HANDLED_CORE := true
#CFLAGS += -mfpu=vfp -mfloat-abi=softfp
endif
ifeq ($(ARM_CPU),arm1136j-s)
DEFINES += \
ARM_WITH_CP15=1 \
ARM_WITH_MMU=1 \
ARM_ISA_ARMv6=1 \
ARM_WITH_THUMB=1 \
ARM_WITH_CACHE=1 \
ARM_CPU_ARM1136=1
CFLAGS += -mcpu=$(ARM_CPU)
HANDLED_CORE := true
endif
ifeq ($(ARM_CPU),arm1176jzf-s)
DEFINES += \
ARM_WITH_CP15=1 \
ARM_WITH_MMU=1 \
ARM_ISA_ARMv6=1 \
ARM_WITH_VFP=1 \
ARM_WITH_THUMB=1 \
ARM_WITH_CACHE=1 \
ARM_CPU_ARM1136=1
CFLAGS += -mcpu=$(ARM_CPU)
HANDLED_CORE := true
endif
ifeq ($(ARM_CPU),arm926ej-s)
DEFINES += \
ARM_WITH_CP15=1 \
ARM_WITH_MMU=1 \
ARM_ISA_ARMv5E=1 \
ARM_WITH_THUMB=1 \
ARM_WITH_CACHE=1 \
ARM_CPU_ARM9=1 \
ARM_CPU_ARM926=1
CFLAGS += -mcpu=$(ARM_CPU)
HANDLED_CORE := true
endif
ifeq ($(ARM_CPU),arm7tdmi)
DEFINES += \
ARM_ISA_ARMv4=1 \
ARM_WITH_THUMB=1 \
ARM_CPU_ARM7=1
CFLAGS += -mcpu=$(ARM_CPU)
HANDLED_CORE := true
endif
ifneq ($(HANDLED_CORE),true)
$(warning $(LOCAL_DIR)/rules.mk doesnt have logic for arm core $(ARM_CPU))
$(warning this is likely to be broken)
endif
THUMBCFLAGS :=
THUMBINTERWORK :=
ifeq ($(ENABLE_THUMB),true)
THUMBCFLAGS := -mthumb -D__thumb__
THUMBINTERWORK := -mthumb-interwork
endif
INCLUDES += \
-I$(LOCAL_DIR)/include
BOOTOBJS += \
$(LOCAL_DIR)/crt0.o
OBJS += \
$(LOCAL_DIR)/arch.Ao \
$(LOCAL_DIR)/asm.o \
$(LOCAL_DIR)/cache.o \
$(LOCAL_DIR)/cache-ops.o \
$(LOCAL_DIR)/ops.o \
$(LOCAL_DIR)/exceptions.o \
$(LOCAL_DIR)/faults.o \
$(LOCAL_DIR)/mmu.o \
$(LOCAL_DIR)/thread.o \
$(LOCAL_DIR)/dcc.o
# set the default toolchain to arm eabi and set a #define
TOOLCHAIN_PREFIX ?= arm-eabi-
ifeq ($(TOOLCHAIN_PREFIX),arm-none-linux-gnueabi-)
# XXX test for EABI better than this
# eabi compilers dont need this
THUMBINTERWORK:=
endif
CFLAGS += $(THUMBINTERWORK)
# make sure some bits were set up
MEMVARS_SET := 0
ifneq ($(MEMBASE),)
MEMVARS_SET := 1
endif
ifneq ($(MEMSIZE),)
MEMVARS_SET := 1
endif
ifeq ($(MEMVARS_SET),0)
$(error missing MEMBASE or MEMSIZE variable, please set in target rules.mk)
endif
LIBGCC := $(shell $(TOOLCHAIN_PREFIX)gcc $(CFLAGS) $(THUMBCFLAGS) -print-libgcc-file-name)
#$(info LIBGCC = $(LIBGCC))
# potentially generated files that should be cleaned out with clean make rule
GENERATED += \
$(BUILDDIR)/system-onesegment.ld \
$(BUILDDIR)/system-twosegment.ld
# rules for generating the linker scripts
$(BUILDDIR)/system-onesegment.ld: $(LOCAL_DIR)/system-onesegment.ld
@echo generating $@
@$(MKDIR)
$(NOECHO)sed "s/%MEMBASE%/$(MEMBASE)/;s/%MEMSIZE%/$(MEMSIZE)/" < $< > $@
$(BUILDDIR)/system-twosegment.ld: $(LOCAL_DIR)/system-twosegment.ld
@echo generating $@
@$(MKDIR)
$(NOECHO)sed "s/%ROMBASE%/$(ROMBASE)/;s/%MEMBASE%/$(MEMBASE)/;s/%MEMSIZE%/$(MEMSIZE)/" < $< > $@

View File

@ -0,0 +1,82 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = %MEMBASE%;
.interp : { *(.interp) }
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) }
.rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) }
.rel.data : { *(.rel.data) *(.rel.gnu.linkonce.d*) }
.rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) }
.rel.rodata : { *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
.rela.rodata : { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
.rel.got : { *(.rel.got) }
.rela.got : { *(.rela.got) }
.rel.ctors : { *(.rel.ctors) }
.rela.ctors : { *(.rela.ctors) }
.rel.dtors : { *(.rel.dtors) }
.rela.dtors : { *(.rela.dtors) }
.rel.init : { *(.rel.init) }
.rela.init : { *(.rela.init) }
.rel.fini : { *(.rel.fini) }
.rela.fini : { *(.rela.fini) }
.rel.bss : { *(.rel.bss) }
.rela.bss : { *(.rela.bss) }
.rel.plt : { *(.rel.plt) }
.rela.plt : { *(.rela.plt) }
.init : { *(.init) } =0x9090
.plt : { *(.plt) }
/* text/read-only data */
.text : { *(.text .text.* .glue_7* .gnu.linkonce.t.*) } =0x9090
.rodata : {
*(.rodata .rodata.* .gnu.linkonce.r.*)
. = ALIGN(4);
__commands_start = .;
KEEP (*(.commands))
__commands_end = .;
. = ALIGN(4);
__apps_start = .;
KEEP (*(.apps))
__apps_end = .;
. = ALIGN(4);
__rodata_end = . ;
}
/* writable data */
__data_start_rom = .; /* in one segment binaries, the rom data address is on top of the ram data address */
__data_start = .;
.data : SUBALIGN(4) { *(.data .data.* .gnu.linkonce.d.*) }
__ctor_list = .;
.ctors : { *(.ctors) }
__ctor_end = .;
__dtor_list = .;
.dtors : { *(.dtors) }
__dtor_end = .;
.got : { *(.got.plt) *(.got) }
.dynamic : { *(.dynamic) }
__data_end = .;
/* unintialized data (in same segment as writable data) */
. = ALIGN(4);
__bss_start = .;
.bss : { *(.bss .bss.*) }
. = ALIGN(4);
_end = .;
. = %MEMBASE% + %MEMSIZE%;
_end_of_ram = .;
/* Strip unnecessary stuff */
/DISCARD/ : { *(.comment .note .eh_frame) }
}

View File

@ -0,0 +1,85 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = %ROMBASE%;
.interp : { *(.interp) }
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) }
.rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) }
.rel.data : { *(.rel.data) *(.rel.gnu.linkonce.d*) }
.rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) }
.rel.rodata : { *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
.rela.rodata : { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
.rel.got : { *(.rel.got) }
.rela.got : { *(.rela.got) }
.rel.ctors : { *(.rel.ctors) }
.rela.ctors : { *(.rela.ctors) }
.rel.dtors : { *(.rel.dtors) }
.rela.dtors : { *(.rela.dtors) }
.rel.init : { *(.rel.init) }
.rela.init : { *(.rela.init) }
.rel.fini : { *(.rel.fini) }
.rela.fini : { *(.rela.fini) }
.rel.bss : { *(.rel.bss) }
.rela.bss : { *(.rela.bss) }
.rel.plt : { *(.rel.plt) }
.rela.plt : { *(.rela.plt) }
.init : { *(.init) } =0x9090
.plt : { *(.plt) }
/* text/read-only data */
.text : { *(.text .text.* .glue_7* .gnu.linkonce.t.*) } =0x9090
.rodata : {
*(.rodata .rodata.* .gnu.linkonce.r.*)
. = ALIGN(4);
__commands_start = .;
KEEP (*(.commands))
__commands_end = .;
. = ALIGN(4);
__apps_start = .;
KEEP (*(.apps))
__apps_end = .;
. = ALIGN(4);
__rodata_end = . ;
}
/* writable data */
__data_start_rom = .;
. = %MEMBASE%;
__data_start = .;
.data :
AT ( ADDR (.rodata) + SIZEOF (.rodata) )
{ *(.data .data.* .gnu.linkonce.d.*) }
__ctor_list = .;
.ctors : { *(.ctors) }
__ctor_end = .;
__dtor_list = .;
.dtors : { *(.dtors) }
__dtor_end = .;
.got : { *(.got.plt) *(.got) }
.dynamic : { *(.dynamic) }
__data_end = .;
/* unintialized data (in same segment as writable data) */
. = ALIGN(4);
__bss_start = .;
.bss : { *(.bss .bss.*) }
. = ALIGN(4);
_end = . ;
. = %MEMBASE% + %MEMSIZE%;
_end_of_ram = . ;
/* Strip unnecessary stuff */
/DISCARD/ : { *(.comment .note .eh_frame) }
}

88
lk/arch/arm/thread.c Normal file
View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <debug.h>
#include <kernel/thread.h>
#include <arch/arm.h>
struct context_switch_frame {
vaddr_t r4;
vaddr_t r5;
vaddr_t r6;
vaddr_t r7;
vaddr_t r8;
vaddr_t r9;
vaddr_t r10;
vaddr_t r11;
vaddr_t lr;
vaddr_t usp;
vaddr_t ulr;
};
extern void arm_context_switch(addr_t *old_sp, addr_t new_sp);
static void initial_thread_func(void) __NO_RETURN;
static void initial_thread_func(void)
{
int ret;
// dprintf("initial_thread_func: thread %p calling %p with arg %p\n", current_thread, current_thread->entry, current_thread->arg);
// dump_thread(current_thread);
/* exit the implicit critical section we're within */
exit_critical_section();
ret = current_thread->entry(current_thread->arg);
// dprintf("initial_thread_func: thread %p exiting with %d\n", current_thread, ret);
thread_exit(ret);
}
void arch_thread_initialize(thread_t *t)
{
// create a default stack frame on the stack
vaddr_t stack_top = (vaddr_t)t->stack + t->stack_size;
// make sure the top of the stack is 8 byte aligned for EABI compliance
stack_top = ROUNDDOWN(stack_top, 8);
struct context_switch_frame *frame = (struct context_switch_frame *)(stack_top);
frame--;
// fill it in
memset(frame, 0, sizeof(*frame));
frame->lr = (vaddr_t)&initial_thread_func;
// set the stack pointer
t->arch.sp = (vaddr_t)frame;
}
void arch_context_switch(thread_t *oldthread, thread_t *newthread)
{
// dprintf("arch_context_switch: old %p (%s), new %p (%s)\n", oldthread, oldthread->name, newthread, newthread->name);
arm_context_switch(&oldthread->arch.sp, newthread->arch.sp);
}

28
lk/dev/dev.c Normal file
View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
void dev_init(void)
{
}

245
lk/dev/fbcon/fbcon.c Normal file
View File

@ -0,0 +1,245 @@
/*
* Copyright (c) 2008, Google Inc.
* All rights reserved.
*
* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <debug.h>
#include <err.h>
#include <stdlib.h>
#include <dev/fbcon.h>
#include <splash.h>
#include "font5x12.h"
struct pos {
int x;
int y;
};
static struct fbcon_config *config = NULL;
#define RGB565_BLACK 0x0000
#define RGB565_WHITE 0xffff
#define RGB888_BLACK 0x000000
#define RGB888_WHITE 0xffffff
#define FONT_WIDTH 5
#define FONT_HEIGHT 12
static uint16_t BGCOLOR;
static uint16_t FGCOLOR;
static struct pos cur_pos;
static struct pos max_pos;
static void fbcon_drawglyph(uint16_t *pixels, uint16_t paint, unsigned stride,
unsigned *glyph)
{
unsigned x, y, data;
stride -= FONT_WIDTH;
data = glyph[0];
for (y = 0; y < (FONT_HEIGHT / 2); ++y) {
for (x = 0; x < FONT_WIDTH; ++x) {
if (data & 1)
*pixels = paint;
data >>= 1;
pixels++;
}
pixels += stride;
}
data = glyph[1];
for (y = 0; y < (FONT_HEIGHT / 2); y++) {
for (x = 0; x < FONT_WIDTH; x++) {
if (data & 1)
*pixels = paint;
data >>= 1;
pixels++;
}
pixels += stride;
}
}
static void fbcon_flush(void)
{
if (config->update_start)
config->update_start();
if (config->update_done)
while (!config->update_done());
}
/* TODO: Take stride into account */
static void fbcon_scroll_up(void)
{
unsigned short *dst = config->base;
unsigned short *src = dst + (config->width * FONT_HEIGHT);
unsigned count = config->width * (config->height - FONT_HEIGHT);
while(count--) {
*dst++ = *src++;
}
count = config->width * FONT_HEIGHT;
while(count--) {
*dst++ = BGCOLOR;
}
fbcon_flush();
}
/* TODO: take stride into account */
void fbcon_clear(void)
{
unsigned count = config->width * config->height;
memset(config->base, BGCOLOR, count * ((config->bpp) / 8));
}
static void fbcon_set_colors(unsigned bg, unsigned fg)
{
BGCOLOR = bg;
FGCOLOR = fg;
}
void fbcon_putc(char c)
{
uint16_t *pixels;
/* ignore anything that happens before fbcon is initialized */
if (!config)
return;
if((unsigned char)c > 127)
return;
if((unsigned char)c < 32) {
if(c == '\n')
goto newline;
else if (c == '\r')
cur_pos.x = 0;
return;
}
pixels = config->base;
pixels += cur_pos.y * FONT_HEIGHT * config->width;
pixels += cur_pos.x * (FONT_WIDTH + 1);
fbcon_drawglyph(pixels, FGCOLOR, config->stride,
font5x12 + (c - 32) * 2);
cur_pos.x++;
if (cur_pos.x < max_pos.x)
return;
newline:
cur_pos.y++;
cur_pos.x = 0;
if(cur_pos.y >= max_pos.y) {
cur_pos.y = max_pos.y - 1;
fbcon_scroll_up();
} else
fbcon_flush();
}
void fbcon_setup(struct fbcon_config *_config)
{
uint32_t bg;
uint32_t fg;
ASSERT(_config);
config = _config;
switch (config->format) {
case FB_FORMAT_RGB565:
fg = RGB565_WHITE;
bg = RGB565_BLACK;
break;
case FB_FORMAT_RGB888:
fg = RGB888_WHITE;
bg = RGB888_BLACK;
break;
default:
dprintf(CRITICAL, "unknown framebuffer pixel format\n");
ASSERT(0);
break;
}
fbcon_set_colors(bg, fg);
cur_pos.x = 0;
cur_pos.y = 0;
max_pos.x = config->width / (FONT_WIDTH+1);
max_pos.y = (config->height - 1) / FONT_HEIGHT;
#if !DISPLAY_SPLASH_SCREEN
fbcon_clear();
#endif
}
struct fbcon_config* fbcon_display(void)
{
return config;
}
void diplay_image_on_screen(void)
{
unsigned i = 0;
unsigned total_x = config->width;
unsigned total_y = config->height;
unsigned bytes_per_bpp = ((config->bpp) / 8);
unsigned image_base = ((((total_y/2) - (SPLASH_IMAGE_WIDTH / 2) - 1) *
(config->width)) + (total_x/2 - (SPLASH_IMAGE_HEIGHT / 2)));
fbcon_clear();
#if DISPLAY_TYPE_MIPI
if (bytes_per_bpp == 3)
{
for (i = 0; i < SPLASH_IMAGE_WIDTH; i++)
{
memcpy (config->base + ((image_base + (i * (config->width))) * bytes_per_bpp),
imageBuffer_rgb888 + (i * SPLASH_IMAGE_HEIGHT * bytes_per_bpp),
SPLASH_IMAGE_HEIGHT * bytes_per_bpp);
}
}
fbcon_flush();
if(is_cmd_mode_enabled())
mipi_dsi_cmd_mode_trigger();
#else
if (bytes_per_bpp == 2)
{
for (i = 0; i < SPLASH_IMAGE_WIDTH; i++)
{
memcpy (config->base + ((image_base + (i * (config->width))) * bytes_per_bpp),
imageBuffer + (i * SPLASH_IMAGE_HEIGHT * bytes_per_bpp),
SPLASH_IMAGE_HEIGHT * bytes_per_bpp);
}
}
fbcon_flush();
#endif
}

126
lk/dev/fbcon/font5x12.h Normal file
View File

@ -0,0 +1,126 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
unsigned font5x12[] = {
0x00000000, 0x00000000,
0x08421080, 0x00020084,
0x00052940, 0x00000000,
0x15f52800, 0x0000295f,
0x1c52f880, 0x00023e94,
0x08855640, 0x0004d542,
0x04528800, 0x000b2725,
0x00021080, 0x00000000,
0x04211088, 0x00821042,
0x10841082, 0x00221108,
0x09575480, 0x00000000,
0x3e420000, 0x00000084,
0x00000000, 0x00223000,
0x3e000000, 0x00000000,
0x00000000, 0x00471000,
0x08844200, 0x00008442,
0x2318a880, 0x00022a31,
0x08429880, 0x000f9084,
0x1108c5c0, 0x000f8444,
0x1c4443e0, 0x00074610,
0x14a62100, 0x000423e9,
0x26d087e0, 0x00074610,
0x1e10c5c0, 0x00074631,
0x088443e0, 0x00010844,
0x1d18c5c0, 0x00074631,
0x3d18c5c0, 0x00074610,
0x08e20000, 0x00471000,
0x08e20000, 0x00223000,
0x02222200, 0x00082082,
0x01f00000, 0x000003e0,
0x20820820, 0x00008888,
0x1108c5c0, 0x00020084,
0x2b98c5c0, 0x000f05b5,
0x2318a880, 0x0008c63f,
0x1d2949e0, 0x0007ca52,
0x0210c5c0, 0x00074421,
0x252949e0, 0x0007ca52,
0x1e1087e0, 0x000f8421,
0x1e1087e0, 0x00008421,
0x0210c5c0, 0x00074639,
0x3f18c620, 0x0008c631,
0x084211c0, 0x00071084,
0x10842380, 0x00032508,
0x0654c620, 0x0008c525,
0x02108420, 0x000f8421,
0x2b5dc620, 0x0008c631,
0x2b59ce20, 0x0008c739,
0x2318c5c0, 0x00074631,
0x1f18c5e0, 0x00008421,
0x2318c5c0, 0x01075631,
0x1f18c5e0, 0x0008c525,
0x1c10c5c0, 0x00074610,
0x084213e0, 0x00021084,
0x2318c620, 0x00074631,
0x1518c620, 0x0002114a,
0x2b18c620, 0x000556b5,
0x08a54620, 0x0008c54a,
0x08a54620, 0x00021084,
0x088443e0, 0x000f8442,
0x0421084e, 0x00e10842,
0x08210420, 0x00084108,
0x1084210e, 0x00e42108,
0x0008a880, 0x00000000,
0x00000000, 0x01f00000,
0x00000104, 0x00000000,
0x20e00000, 0x000b663e,
0x22f08420, 0x0007c631,
0x22e00000, 0x00074421,
0x23e84200, 0x000f4631,
0x22e00000, 0x0007443f,
0x1e214980, 0x00010842,
0x22e00000, 0x1d187a31,
0x26d08420, 0x0008c631,
0x08601000, 0x00071084,
0x10c02000, 0x0c94a108,
0x0a908420, 0x0008a4a3,
0x084210c0, 0x00071084,
0x2ab00000, 0x0008d6b5,
0x26d00000, 0x0008c631,
0x22e00000, 0x00074631,
0x22f00000, 0x0210be31,
0x23e00000, 0x21087a31,
0x26d00000, 0x00008421,
0x22e00000, 0x00074506,
0x04f10800, 0x00064842,
0x23100000, 0x000b6631,
0x23100000, 0x00022951,
0x23100000, 0x000556b5,
0x15100000, 0x0008a884,
0x23100000, 0x1d185b31,
0x11f00000, 0x000f8444,
0x06421098, 0x01821084,
0x08421080, 0x00021084,
0x30421083, 0x00321084,
0x0004d640, 0x00000000,
0x00000000, 0x00000000,
};

5
lk/dev/fbcon/rules.mk Normal file
View File

@ -0,0 +1,5 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
OBJS += \
$(LOCAL_DIR)/fbcon.o

618
lk/dev/keys/gpio_keypad.c Normal file
View File

@ -0,0 +1,618 @@
/*
* Copyright (c) 2009, Google Inc.
* All rights reserved.
*
* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google, Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <assert.h>
#include <bits.h>
#include <stdlib.h>
#include <string.h>
#include <dev/keys.h>
#include <dev/gpio.h>
#include <dev/gpio_keypad.h>
#include <kernel/event.h>
#include <kernel/timer.h>
#include <reg.h>
#include <platform/iomap.h>
struct gpio_kp {
struct gpio_keypad_info *keypad_info;
struct timer timer;
event_t full_scan;
int current_output;
unsigned int some_keys_pressed:2;
unsigned long keys_pressed[0];
};
struct gpio_qwerty_kp {
struct qwerty_keypad_info *keypad_info;
struct timer timer;
event_t full_scan;
int num_of_scans;
unsigned int some_keys_pressed:2;
unsigned long keys_pressed[0];
};
static struct gpio_qwerty_kp *qwerty_keypad;
/* TODO: Support multiple keypads? */
static struct gpio_kp *keypad;
static void check_output(struct gpio_kp *kp, int out, int polarity)
{
struct gpio_keypad_info *kpinfo = kp->keypad_info;
int key_index;
int in;
int gpio;
int changed = 0;
key_index = out * kpinfo->ninputs;
for (in = 0; in < kpinfo->ninputs; in++, key_index++) {
gpio = kpinfo->input_gpios[in];
changed = 0;
if (gpio_get(gpio) ^ !polarity) {
if (kp->some_keys_pressed < 3)
kp->some_keys_pressed++;
changed = !bitmap_set(kp->keys_pressed, key_index);
} else {
changed = bitmap_clear(kp->keys_pressed, key_index);
}
if (changed) {
int state = bitmap_test(kp->keys_pressed, key_index);
keys_post_event(kpinfo->keymap[key_index], state);
}
}
/* sets up the right state for the next poll cycle */
gpio = kpinfo->output_gpios[out];
if (kpinfo->flags & GPIOKPF_DRIVE_INACTIVE)
gpio_set(gpio, !polarity);
else
gpio_config(gpio, GPIO_INPUT);
}
static enum handler_return
gpio_keypad_timer_func(struct timer *timer, time_t now, void *arg)
{
struct gpio_kp *kp = keypad;
struct gpio_keypad_info *kpinfo = kp->keypad_info;
int polarity = !!(kpinfo->flags & GPIOKPF_ACTIVE_HIGH);
int out;
int gpio;
out = kp->current_output;
if (out == kpinfo->noutputs) {
out = 0;
kp->some_keys_pressed = 0;
} else {
check_output(kp, out, polarity);
out++;
}
kp->current_output = out;
if (out < kpinfo->noutputs) {
gpio = kpinfo->output_gpios[out];
if (kpinfo->flags & GPIOKPF_DRIVE_INACTIVE)
gpio_set(gpio, polarity);
else
gpio_config(gpio, polarity ? GPIO_OUTPUT : 0);
timer_set_oneshot(timer, kpinfo->settle_time,
gpio_keypad_timer_func, NULL);
goto done;
}
if (/*!kp->use_irq*/ 1 || kp->some_keys_pressed) {
event_signal(&kp->full_scan, false);
timer_set_oneshot(timer, kpinfo->poll_time,
gpio_keypad_timer_func, NULL);
goto done;
}
#if 0
/* No keys are pressed, reenable interrupt */
for (out = 0; out < kpinfo->noutputs; out++) {
if (gpio_keypad_flags & GPIOKPF_DRIVE_INACTIVE)
gpio_set(kpinfo->output_gpios[out], polarity);
else
gpio_config(kpinfo->output_gpios[out], polarity ? GPIO_OUTPUT : 0);
}
for (in = 0; in < kpinfo->ninputs; in++)
enable_irq(gpio_to_irq(kpinfo->input_gpios[in]));
return INT_RESCHEDULE;
#endif
done:
return INT_RESCHEDULE;
}
void gpio_keypad_init(struct gpio_keypad_info *kpinfo)
{
int key_count;
int output_val;
int output_cfg;
int i;
int len;
ASSERT(kpinfo->keymap && kpinfo->input_gpios && kpinfo->output_gpios);
key_count = kpinfo->ninputs * kpinfo->noutputs;
len = sizeof(struct gpio_kp) + (sizeof(unsigned long) *
BITMAP_NUM_WORDS(key_count));
keypad = malloc(len);
ASSERT(keypad);
memset(keypad, 0, len);
keypad->keypad_info = kpinfo;
output_val = (!!(kpinfo->flags & GPIOKPF_ACTIVE_HIGH)) ^
(!!(kpinfo->flags & GPIOKPF_DRIVE_INACTIVE));
output_cfg = kpinfo->flags & GPIOKPF_DRIVE_INACTIVE ? GPIO_OUTPUT : 0;
for (i = 0; i < kpinfo->noutputs; i++) {
gpio_set(kpinfo->output_gpios[i], output_val);
gpio_config(kpinfo->output_gpios[i], output_cfg);
}
for (i = 0; i < kpinfo->ninputs; i++)
gpio_config(kpinfo->input_gpios[i], GPIO_INPUT);
keypad->current_output = kpinfo->noutputs;
event_init(&keypad->full_scan, false, EVENT_FLAG_AUTOUNSIGNAL);
timer_initialize(&keypad->timer);
timer_set_oneshot(&keypad->timer, 0, gpio_keypad_timer_func, NULL);
/* wait for the keypad to complete one full scan */
event_wait(&keypad->full_scan);
}
int i2c_ssbi_poll_for_device_ready(void)
{
unsigned long timeout = SSBI_TIMEOUT_US;
while (!(readl(MSM_SSBI_BASE + SSBI2_STATUS) & SSBI_STATUS_READY)) {
if (--timeout == 0) {
dprintf(INFO, "In Device ready function:Timeout, status %x\n", readl(MSM_SSBI_BASE + SSBI2_STATUS));
return 1;
}
}
return 0;
}
int i2c_ssbi_poll_for_read_completed(void)
{
unsigned long timeout = SSBI_TIMEOUT_US;
while (!(readl(MSM_SSBI_BASE + SSBI2_STATUS) & SSBI_STATUS_RD_READY)) {
if (--timeout == 0) {
dprintf(INFO, "In read completed function:Timeout, status %x\n", readl(MSM_SSBI_BASE + SSBI2_STATUS));
return 1;
}
}
return 0;
}
int i2c_ssbi_read_bytes(unsigned char *buffer, unsigned short length,
unsigned short slave_addr)
{
int ret = 0;
unsigned char *buf = buffer;
unsigned short len = length;
unsigned short addr = slave_addr;
unsigned long read_cmd = SSBI_CMD_READ(addr);
unsigned long mode2 = readl(MSM_SSBI_BASE + SSBI2_MODE2);
//buf = alloc(len * sizeof(8));
if (mode2 & SSBI_MODE2_SSBI2_MODE)
writel(SSBI_MODE2_REG_ADDR_15_8(mode2, addr),
MSM_SSBI_BASE + SSBI2_MODE2);
while (len) {
ret = i2c_ssbi_poll_for_device_ready();
if (ret) {
dprintf (CRITICAL, "Error: device not ready\n");
return ret;
}
writel(read_cmd, MSM_SSBI_BASE + SSBI2_CMD);
ret = i2c_ssbi_poll_for_read_completed();
if (ret) {
dprintf (CRITICAL, "Error: read not completed\n");
return ret;
}
*buf++ = readl(MSM_SSBI_BASE + SSBI2_RD) & SSBI_RD_REG_DATA_MASK;
len--;
}
return 0;
}
int i2c_ssbi_write_bytes(unsigned char *buffer, unsigned short length,
unsigned short slave_addr)
{
int ret = 0;
unsigned long timeout = SSBI_TIMEOUT_US;
unsigned char *buf = buffer;
unsigned short len = length;
unsigned short addr = slave_addr;
unsigned long mode2 = readl(MSM_SSBI_BASE + SSBI2_MODE2);
if (mode2 & SSBI_MODE2_SSBI2_MODE)
writel(SSBI_MODE2_REG_ADDR_15_8(mode2, addr),
MSM_SSBI_BASE + SSBI2_MODE2);
while (len) {
ret = i2c_ssbi_poll_for_device_ready();
if (ret) {
dprintf (CRITICAL, "Error: device not ready\n");
return ret;
}
writel(SSBI_CMD_WRITE(addr, *buf++), MSM_SSBI_BASE + SSBI2_CMD);
while (readl(MSM_SSBI_BASE + SSBI2_STATUS) & SSBI_STATUS_MCHN_BUSY) {
if (--timeout == 0) {
dprintf(INFO, "In Device ready function:Timeout, status %x\n", readl(MSM_SSBI_BASE + SSBI2_STATUS));
return 1;
}
}
len--;
}
return 0;
}
int pa1_ssbi2_read_bytes(unsigned char *buffer, unsigned short length,
unsigned short slave_addr)
{
unsigned val = 0x0;
unsigned temp = 0x0000;
unsigned char *buf = buffer;
unsigned short len = length;
unsigned short addr = slave_addr;
unsigned long timeout = SSBI_TIMEOUT_US;
while(len)
{
val |= ((addr << PA1_SSBI2_REG_ADDR_SHIFT) |
(PA1_SSBI2_CMD_READ << PA1_SSBI2_CMD_RDWRN_SHIFT));
writel(val, PA1_SSBI2_CMD);
while(!((temp = readl(PA1_SSBI2_RD_STATUS)) & (1 << PA1_SSBI2_TRANS_DONE_SHIFT))) {
if (--timeout == 0) {
dprintf(INFO, "In Device ready function:Timeout\n");
return 1;
}
}
len--;
*buf++ = (temp & (PA1_SSBI2_REG_DATA_MASK << PA1_SSBI2_REG_DATA_SHIFT));
}
return 0;
}
int pa1_ssbi2_write_bytes(unsigned char *buffer, unsigned short length,
unsigned short slave_addr)
{
unsigned val;
unsigned char *buf = buffer;
unsigned short len = length;
unsigned short addr = slave_addr;
unsigned temp = 0x00;
unsigned char written_data1 = 0x00;
unsigned long timeout = SSBI_TIMEOUT_US;
//unsigned char written_data2 = 0x00;
while(len)
{
temp = 0x00;
written_data1 = 0x00;
val = (addr << PA1_SSBI2_REG_ADDR_SHIFT) |
(PA1_SSBI2_CMD_WRITE << PA1_SSBI2_CMD_RDWRN_SHIFT) |
(*buf & 0xFF);
writel(val, PA1_SSBI2_CMD);
while(!((temp = readl(PA1_SSBI2_RD_STATUS)) & (1 << PA1_SSBI2_TRANS_DONE_SHIFT))) {
if (--timeout == 0) {
dprintf(INFO, "In Device write function:Timeout\n");
return 1;
}
}
len--;
buf++;
}
return 0;
}
int pa2_ssbi2_read_bytes(unsigned char *buffer, unsigned short length,
unsigned short slave_addr)
{
unsigned val = 0x0;
unsigned temp = 0x0000;
unsigned char *buf = buffer;
unsigned short len = length;
unsigned short addr = slave_addr;
unsigned long timeout = SSBI_TIMEOUT_US;
while(len)
{
val |= ((addr << PA2_SSBI2_REG_ADDR_SHIFT) |
(PA2_SSBI2_CMD_READ << PA2_SSBI2_CMD_RDWRN_SHIFT));
writel(val, PA2_SSBI2_CMD);
while(!((temp = readl(PA2_SSBI2_RD_STATUS)) & (1 << PA2_SSBI2_TRANS_DONE_SHIFT))) {
if (--timeout == 0) {
dprintf(INFO, "In Device ready function:Timeout\n");
return 1;
}
}
len--;
*buf++ = (temp & (PA2_SSBI2_REG_DATA_MASK << PA2_SSBI2_REG_DATA_SHIFT));
}
return 0;
}
int pa2_ssbi2_write_bytes(unsigned char *buffer, unsigned short length,
unsigned short slave_addr)
{
unsigned val;
unsigned char *buf = buffer;
unsigned short len = length;
unsigned short addr = slave_addr;
unsigned temp = 0x00;
unsigned char written_data1 = 0x00;
unsigned long timeout = SSBI_TIMEOUT_US;
while(len)
{
temp = 0x00;
written_data1 = 0x00;
val = (addr << PA2_SSBI2_REG_ADDR_SHIFT) |
(PA2_SSBI2_CMD_WRITE << PA2_SSBI2_CMD_RDWRN_SHIFT) |
(*buf & 0xFF);
writel(val, PA2_SSBI2_CMD);
while(!((temp = readl(PA2_SSBI2_RD_STATUS)) & (1 << PA2_SSBI2_TRANS_DONE_SHIFT))) {
if (--timeout == 0) {
dprintf(INFO, "In Device write function:Timeout\n");
return 1;
}
}
len--;
buf++;
}
return 0;
}
int pm8058_gpio_config(int gpio, struct pm8058_gpio *param)
{
int rc;
write_func wr_function = (qwerty_keypad->keypad_info)->wr_func;
unsigned char bank[8];
static int dir_map[] = {
PM8058_GPIO_MODE_OFF,
PM8058_GPIO_MODE_OUTPUT,
PM8058_GPIO_MODE_INPUT,
PM8058_GPIO_MODE_BOTH,
};
if (param == 0) {
dprintf (INFO, "pm8058_gpio struct not defined\n");
return -1;
}
/* Select banks and configure the gpio */
bank[0] = PM8058_GPIO_WRITE |
((param->vin_sel << PM8058_GPIO_VIN_SHIFT) &
PM8058_GPIO_VIN_MASK) |
PM8058_GPIO_MODE_ENABLE;
bank[1] = PM8058_GPIO_WRITE |
((1 << PM8058_GPIO_BANK_SHIFT) & PM8058_GPIO_BANK_MASK) |
((dir_map[param->direction] << PM8058_GPIO_MODE_SHIFT) &
PM8058_GPIO_MODE_MASK) |
((param->direction & PM_GPIO_DIR_OUT) ?
PM8058_GPIO_OUT_BUFFER : 0);
bank[2] = PM8058_GPIO_WRITE |
((2 << PM8058_GPIO_BANK_SHIFT) & PM8058_GPIO_BANK_MASK) |
((param->pull << PM8058_GPIO_PULL_SHIFT) &
PM8058_GPIO_PULL_MASK);
bank[3] = PM8058_GPIO_WRITE |
((3 << PM8058_GPIO_BANK_SHIFT) & PM8058_GPIO_BANK_MASK) |
((param->out_strength << PM8058_GPIO_OUT_STRENGTH_SHIFT) &
PM8058_GPIO_OUT_STRENGTH_MASK);
bank[4] = PM8058_GPIO_WRITE |
((4 << PM8058_GPIO_BANK_SHIFT) & PM8058_GPIO_BANK_MASK) |
((param->function << PM8058_GPIO_FUNC_SHIFT) &
PM8058_GPIO_FUNC_MASK);
rc = (*wr_function)(bank, 5, SSBI_REG_ADDR_GPIO(gpio));
if (rc) {
dprintf(INFO, "Failed on 1st ssbi_write(): rc=%d.\n", rc);
return 1;
}
return 0;
}
int pm8058_gpio_config_kypd_drv(int gpio_start, int num_gpios)
{
int rc;
struct pm8058_gpio kypd_drv = {
.direction = PM_GPIO_DIR_OUT,
.pull = PM_GPIO_PULL_NO,
.vin_sel = 2,
.out_strength = PM_GPIO_STRENGTH_LOW,
.function = PM_GPIO_FUNC_1,
.inv_int_pol = 1,
};
while (num_gpios--) {
rc = pm8058_gpio_config(gpio_start++, &kypd_drv);
if (rc) {
dprintf(INFO, "FAIL pm8058_gpio_config(): rc=%d.\n", rc);
return rc;
}
}
return 0;
}
int pm8058_gpio_config_kypd_sns(int gpio_start, int num_gpios)
{
int rc;
struct pm8058_gpio kypd_sns = {
.direction = PM_GPIO_DIR_IN,
.pull = PM_GPIO_PULL_UP1,
.vin_sel = 2,
.out_strength = PM_GPIO_STRENGTH_NO,
.function = PM_GPIO_FUNC_NORMAL,
.inv_int_pol = 1,
};
while (num_gpios--) {
rc = pm8058_gpio_config(gpio_start++, &kypd_sns);
if (rc) {
dprintf(INFO, "FAIL pm8058_gpio_config(): rc=%d.\n", rc);
return rc;
}
}
return 0;
}
void ssbi_gpio_init(void)
{
unsigned char kypd_cntl_init = 0x84;
unsigned char kypd_scan_init = 0x20;
int rows = (qwerty_keypad->keypad_info)->rows;
int columns = (qwerty_keypad->keypad_info)->columns;
write_func wr_function = (qwerty_keypad->keypad_info)->wr_func;
if ((*wr_function)(&kypd_cntl_init, 1, SSBI_REG_KYPD_CNTL_ADDR))
dprintf (CRITICAL, "Error in initializing SSBI_REG_KYPD_CNTL register\n");
if ((*wr_function)(&kypd_scan_init, 1, SSBI_REG_KYPD_SCAN_ADDR))
dprintf (CRITICAL, "Error in initializing SSBI_REG_KYPD_SCAN register\n");
pm8058_gpio_config_kypd_sns(SSBI_OFFSET_ADDR_GPIO_KYPD_SNS, columns);
pm8058_gpio_config_kypd_drv(SSBI_OFFSET_ADDR_GPIO_KYPD_DRV, rows);
}
static enum handler_return
scan_qwerty_keypad(struct timer *timer, time_t now, void *arg)
{
unsigned int rows = (qwerty_keypad->keypad_info)->rows;
unsigned int columns = (qwerty_keypad->keypad_info)->columns;
unsigned int num_of_ssbi_reads = (qwerty_keypad->keypad_info)->num_of_reads;
read_func rd_function = (qwerty_keypad->keypad_info)->rd_func;
unsigned char column_new_keys = 0x00;
unsigned char column_old_keys = 0x00;
int shift = 0;
static int key_detected = 0;
if ((*rd_function)((qwerty_keypad->keypad_info)->rec_keys, num_of_ssbi_reads,
SSBI_REG_KYPD_REC_DATA_ADDR))
dprintf (CRITICAL, "Error in initializing SSBI_REG_KYPD_CNTL register\n");
if ((*rd_function)((qwerty_keypad->keypad_info)->old_keys, num_of_ssbi_reads,
SSBI_REG_KYPD_OLD_DATA_ADDR))
dprintf (CRITICAL, "Error in initializing SSBI_REG_KYPD_CNTL register\n");
while (rows--) {
if (((qwerty_keypad->keypad_info)->rec_keys[rows]
!= (qwerty_keypad->keypad_info)->old_keys[rows])
&& ((qwerty_keypad->keypad_info)->rec_keys[rows] != 0x00)
&& ((qwerty_keypad->keypad_info)->old_keys[rows] != 0x00)) {
while (columns--) {
column_new_keys = ((qwerty_keypad->keypad_info)->rec_keys[rows]);
column_old_keys = ((qwerty_keypad->keypad_info)->old_keys[rows]);
if (((0x01 << columns) & (~column_new_keys))
&& !((0x01 << columns) & (~column_old_keys))) {
shift = (rows * 8) + columns;
if ((qwerty_keypad->keypad_info)->keymap[shift]) {
if (shift != key_detected) {
key_detected = shift;
keys_post_event((qwerty_keypad->keypad_info)->keymap[shift], 1);
event_signal(&qwerty_keypad->full_scan, false);
timer_set_oneshot(timer, (qwerty_keypad->keypad_info)->poll_time,
scan_qwerty_keypad, NULL);
return INT_RESCHEDULE;
}
}
}
}
}
}
if (qwerty_keypad->num_of_scans < 10)
{
(qwerty_keypad->num_of_scans)++;
timer_set_oneshot(timer, (qwerty_keypad->keypad_info)->settle_time,
scan_qwerty_keypad, NULL);
return INT_RESCHEDULE;
}
event_signal(&qwerty_keypad->full_scan, false);
return INT_RESCHEDULE;
}
void ssbi_keypad_init(struct qwerty_keypad_info *qwerty_kp)
{
int len;
len = sizeof(struct gpio_qwerty_kp);
qwerty_keypad = malloc(len);
ASSERT(qwerty_keypad);
memset(qwerty_keypad, 0, len);
qwerty_keypad->keypad_info = qwerty_kp;
ssbi_gpio_init();
qwerty_keypad->num_of_scans = 0;
event_init(&qwerty_keypad->full_scan, false, EVENT_FLAG_AUTOUNSIGNAL);
timer_initialize(&qwerty_keypad->timer);
timer_set_oneshot(&qwerty_keypad->timer, 0, scan_qwerty_keypad, NULL);
/* wait for the keypad to complete one full scan */
event_wait(&qwerty_keypad->full_scan);
}
void pmic_write(unsigned address, unsigned data)
{
write_func wr_function = &i2c_ssbi_write_bytes;
if(wr_function == NULL)
return;
if ((*wr_function)(&data, 1, address))
dprintf (CRITICAL, "Error in initializing register\n");
}
void toshiba_pmic_gpio_init(unsigned gpio)
{
pmic_write(gpio,0x85);
pmic_write(gpio,0x98);
pmic_write(gpio,0xB8);
pmic_write(gpio,0xC6);
}

67
lk/dev/keys/keys.c Normal file
View File

@ -0,0 +1,67 @@
/*
* Copyright (c) 2008, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google, Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <bits.h>
#include <debug.h>
#include <string.h>
#include <dev/keys.h>
static unsigned long key_bitmap[BITMAP_NUM_WORDS(MAX_KEYS)];
void keys_init(void)
{
memset(key_bitmap, 0, sizeof(key_bitmap));
}
void keys_post_event(uint16_t code, int16_t value)
{
if (code >= MAX_KEYS) {
dprintf(INFO, "Invalid keycode posted: %d\n", code);
return;
}
/* TODO: Implement an actual event queue if it becomes necessary */
if (value)
bitmap_set(key_bitmap, code);
else
bitmap_clear(key_bitmap, code);
// dprintf(INFO, "key state change: %d %d\n", code, value);
}
int keys_get_state(uint16_t code)
{
if (code >= MAX_KEYS) {
dprintf(INFO, "Invalid keycode requested: %d\n", code);
return -1;
}
return bitmap_test(key_bitmap, code);
}

10
lk/dev/keys/rules.mk Normal file
View File

@ -0,0 +1,10 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
OBJS += \
$(LOCAL_DIR)/keys.o
ifeq ($(KEYS_USE_GPIO_KEYPAD),1)
OBJS += \
$(LOCAL_DIR)/gpio_keypad.o
endif

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _DEV_NET_SMC91C96_H
#define _DEV_NET_SMC91C96_H
void smc91c96_init(void);
#endif

View File

@ -0,0 +1,8 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
INCLUDES += \
-I$(LOCAL_DIR)/include
OBJS += \
$(LOCAL_DIR)/smc91c96.o

View File

@ -0,0 +1,70 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <sys/types.h>
#include <debug.h>
#include <printf.h>
#include <dev/net/smc91c96.h>
#include "smc91c96_p.h"
#if !defined(SMC91C96_BASE_ADDR) || !defined(SMC91C96_IRQ)
#error need to define SMC91C96_BASE_ADDR and SMC91C96_IRQ in project
#endif
static addr_t smc91c96_base = SMC91C96_BASE_ADDR;
static uint8_t mac_addr[6];
#define SMC_REG16(reg) ((volatile uint16_t *)(smc91c96_base + (reg)))
#define SMC_REG8(reg) ((volatile uint8_t *)(smc91c96_base + (reg)))
static inline void smc_bank(int bank)
{
*SMC_REG16(SMC_BSR) = bank;
}
void smc91c96_init(void)
{
int i;
TRACE;
// try to detect it
if ((*SMC_REG16(SMC_BSR) & 0xff00) != 0x3300) {
TRACEF("didn't see smc91c96 chip at 0x%x\n", (unsigned int)smc91c96_base);
}
// read revision
smc_bank(3);
TRACEF("detected, revision 0x%x\n", *SMC_REG16(SMC_REV));
// read in the mac address
smc_bank(1);
for (i=0; i < 6; i++) {
mac_addr[i] = *SMC_REG8(SMC_IAR0 + i);
}
TRACEF("mac address %02x:%02x:%02x:%02x:%02x:%02x\n",
mac_addr[0], mac_addr[1], mac_addr[2],
mac_addr[3], mac_addr[4], mac_addr[5]);
smc_bank(0);
}

View File

@ -0,0 +1,80 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __SMC91C96_P_H
#define __SMC91C96_P_H
// LAN91C96 stuffs
/* registers */
#define SMC_BSR 14
/* bank 0 */
#define SMC_TCR 0
#define SMC_EPHSR 2
#define SMC_RCR 4
#define SMC_ECR 6
#define SMC_MIR 8
#define SMC_MCR 10
/* bank 1 */
#define SMC_CR 0
#define SMC_BAR 2
#define SMC_IAR0 4
#define SMC_IAR1 5
#define SMC_IAR2 6
#define SMC_IAR3 7
#define SMC_IAR4 8
#define SMC_IAR5 9
#define SMC_GPR 10
#define SMC_CTR 12
/* bank 2 */
#define SMC_MMUCR 0
#define SMC_AUTOTX 1
#define SMC_PNR 2
#define SMC_ARR 3
#define SMC_FIFO 4
#define SMC_PTR 6
#define SMC_DATA0 8
#define SMC_DATA1 10
#define SMC_IST 12
#define SMC_ACK 12
#define SMC_MSK 13
/* bank 3 */
#define SMC_MT0 0
#define SMC_MT1 1
#define SMC_MT2 2
#define SMC_MT3 3
#define SMC_MT4 4
#define SMC_MT5 5
#define SMC_MT6 6
#define SMC_MT7 7
#define SMC_MGMT 8
#define SMC_REV 10
#define SMC_ERCV 12
#endif

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __DEV_TWL4030_H
#define __DEV_TWL4030_H
#include <sys/types.h>
void twl4030_init(void);
/* USB parts of the pmic */
int twl4030_usb_reset(void);
int twl4030_set_usb_pullup(bool pullup);
int twl4030_init_hs(void);
#endif

View File

@ -0,0 +1,7 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
INCLUDES += -I$(LOCAL_DIR)/include
OBJS += \
$(LOCAL_DIR)/twl4030.o

View File

@ -0,0 +1,169 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <debug.h>
#include <sys/types.h>
#include <dev/i2c.h>
#include <dev/twl4030.h>
#include "twl4030_hw.h"
// XXX move to target specific setup
#define TWL_I2C_BUS 0
void twl4030_init(void)
{
}
static int twl4030_usb_write(uint8_t address, uint8_t data)
{
return i2c_write_reg(TWL_I2C_BUS, TWL_USB_ADDR, address, data);
}
static int twl4030_usb_read(uint8_t address)
{
uint8_t data;
int err = i2c_read_reg(TWL_I2C_BUS, TWL_USB_ADDR, address, &data);
if (err < 0)
return err;
return data;
}
static int twl4030_usb_set_bits(uint8_t reg, uint8_t bits)
{
return twl4030_usb_write(reg + 1, bits);
}
static int twl4030_usb_clear_bits(uint8_t reg, uint8_t bits)
{
return twl4030_usb_write(reg + 2, bits);
}
static void twl4030_i2c_access(bool on)
{
int val;
if ((val = twl4030_usb_read(PHY_CLK_CTRL)) >= 0) {
if (on) {
/* enable DPLL to access PHY registers over I2C */
val |= REQ_PHY_DPLL_CLK;
twl4030_usb_write(PHY_CLK_CTRL, (uint8_t)val);
while (!(twl4030_usb_read(PHY_CLK_CTRL_STS) & PHY_DPLL_CLK)) {
spin(10);
}
if (!(twl4030_usb_read(PHY_CLK_CTRL_STS) & PHY_DPLL_CLK))
printf("Timeout setting T2 HSUSB " "PHY DPLL clock\n");
} else {
/* let ULPI control the DPLL clock */
val &= ~REQ_PHY_DPLL_CLK;
twl4030_usb_write(PHY_CLK_CTRL, (uint8_t)val);
}
}
return;
}
int twl4030_usb_reset(void)
{
TRACE_ENTRY;
#if 0
twl4030_usb_clear_bits(OTG_CTRL, DMPULLDOWN | DPPULLDOWN);
twl4030_usb_clear_bits(USB_INT_EN_RISE, ~0);
twl4030_usb_clear_bits(USB_INT_EN_FALL, ~0);
twl4030_usb_clear_bits(MCPC_IO_CTRL, ~TXDTYP);
twl4030_usb_set_bits(MCPC_IO_CTRL, TXDTYP);
twl4030_usb_clear_bits(OTHER_FUNC_CTRL, (BDIS_ACON_EN | FIVEWIRE_MODE));
twl4030_usb_clear_bits(OTHER_IFC_CTRL, ~0);
twl4030_usb_clear_bits(OTHER_INT_EN_RISE, ~0);
twl4030_usb_clear_bits(OTHER_INT_EN_FALL, ~0);
twl4030_usb_clear_bits(OTHER_IFC_CTRL2, ~0);
twl4030_usb_clear_bits(REG_CTRL_EN, ULPI_I2C_CONFLICT_INTEN);
twl4030_usb_clear_bits(OTHER_FUNC_CTRL2, VBAT_TIMER_EN);
#endif
/* Enable writing to power configuration registers */
i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, PROTECT_KEY, 0xC0);
i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, PROTECT_KEY, 0x0C);
/* put VUSB3V1 LDO in active state */
i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB_DEDICATED2, 0);
/* input to VUSB3V1 LDO is from VBAT, not VBUS */
i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB_DEDICATED1, 0x14);
/* turn on 3.1V regulator */
i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB3V1_DEV_GRP, 0x20);
i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB3V1_TYPE, 0);
/* turn on 1.5V regulator */
i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB1V5_DEV_GRP, 0x20);
i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB1V5_TYPE, 0);
/* turn on 1.8V regulator */
i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB1V8_DEV_GRP, 0x20);
i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB1V8_TYPE, 0);
/* disable access to power configuration registers */
i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, PROTECT_KEY, 0);
/* turn on the phy */
uint8_t pwr = twl4030_usb_read(PHY_PWR_CTRL);
pwr &= ~PHYPWD;
twl4030_usb_write(PHY_PWR_CTRL, pwr);
twl4030_usb_write(PHY_CLK_CTRL,
twl4030_usb_read(PHY_CLK_CTRL) |
(CLOCKGATING_EN | CLK32K_EN));
/* set DPLL i2c access mode */
twl4030_i2c_access(true);
/* set ulpi mode */
twl4030_usb_clear_bits(IFC_CTRL, CARKITMODE);
twl4030_usb_set_bits(POWER_CTRL, OTG_ENAB);
twl4030_usb_write(FUNC_CTRL, XCVRSELECT_HS); // set high speed mode
// twl4030_usb_write(FUNC_CTRL, XCVRSELECT_FS); // set full speed mode
twl4030_i2c_access(false);
return 0;
}
int twl4030_init_hs(void)
{
return 0;
}
int twl4030_set_usb_pullup(bool pullup)
{
TRACE_ENTRY;
if (pullup) {
twl4030_usb_clear_bits(OTG_CTRL, DPPULLDOWN);
twl4030_usb_set_bits(FUNC_CTRL, TERMSELECT);
} else {
twl4030_usb_clear_bits(FUNC_CTRL, TERMSELECT);
twl4030_usb_set_bits(OTG_CTRL, DPPULLDOWN);
}
return 0;
}

View File

@ -0,0 +1,369 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __TWL4030_HW_H
#define __TWL4030_HW_H
/* TWL i2c addresses */
#define TWL_I2C_ADDR0 0x48
#define TWL_I2C_ADDR1 0x49
#define TWL_I2C_ADDR2 0x4a
#define TWL_I2C_ADDR3 0x4b
#define TWL_USB_ADDR TWL_I2C_ADDR0
#define TWL_INTBR_ADDR TWL_I2C_ADDR1
#define TWL_PM_RECEIVER_ADDR TWL_I2C_ADDR3
/* TWL registers */
#define PROTECT_KEY 0x44
#define VAUX1_DEV_GRP 0x72
#define VAUX1_TYPE 0x73
#define VAUX1_REMAP 0x74
#define VAUX1_DEDICATED 0x75
#define VAUX2_DEV_GRP 0x76
#define VAUX2_TYPE 0x77
#define VAUX2_REMAP 0x78
#define VAUX2_DEDICATED 0x79
#define VAUX3_DEV_GRP 0x7a
#define VAUX3_TYPE 0x7b
#define VAUX3_REMAP 0x7c
#define VAUX3_DEDICATED 0x7d
#define VAUX4_DEV_GRP 0x7e
#define VAUX4_TYPE 0x7f
#define VAUX4_REMAP 0x80
#define VAUX4_DEDICATED 0x81
#define VMMC1_DEV_GRP 0x82
#define VMMC1_TYPE 0x83
#define VMMC1_REMAP 0x84
#define VMMC1_DEDICATED 0x85
#define VMMC2_DEV_GRP 0x86
#define VMMC2_TYPE 0x87
#define VMMC2_REMAP 0x88
#define VMMC2_DEDICATED 0x89
#define VPLL1_DEV_GRP 0x8a
#define VPLL1_TYPE 0x8b
#define VPLL1_REMAP 0x8c
#define VPLL1_DEDICATED 0x8d
#define VPLL2_DEV_GRP 0x8e
#define VPLL2_TYPE 0x8f
#define VPLL2_REMAP 0x90
#define VPLL2_DEDICATED 0x91
#define VDAC_DEV_GRP 0x96
#define VDAC_DEDICATED 0x99
#define VDD2_DEV_GRP 0xBE
#define VDD2_TYPE 0xBF
#define VDD2_REMAP 0xC0
#define VDD2_CFG 0xC1
#define VSIM_DEV_GRP 0x92
#define VSIM_TYPE 0x93
#define VSIM_REMAP 0x94
#define VSIM_DEDICATED 0x95
#define PMBR1 0x92
#define SECONDS_REG 0x1C
#define MINUTES_REG 0x1D
#define ALARM_SECONDS_REG 0x23
#define ALARM_MINUTES_REG 0x24
#define ALARM_HOURS_REG 0x25
#define RTC_STATUS_REG 0x2A
#define RTC_INTERRUPTS_REG 0x2B
#define PWR_ISR1 0x2E
#define PWR_IMR1 0x2F
#define PWR_ISR2 0x30
#define PWR_IMR2 0x31
#define PWR_EDR1 0x33
#define CFG_PWRANA2 0x3F
#define RTC_INTERRUPTS_REG 0x2B
#define STS_HW_CONDITIONS 0x45
#define P1_SW_EVENTS 0x46
#define P2_SW_EVENTS 0x47
#define P3_SW_EVENTS 0x48
#define VDD1_TRIM1 0x62
#define VDD1_TRIM2 0x63
#define VDD1_VFLOOR 0xBB
#define VDD1_VROOF 0xBC
#define PB_CFG 0x4A
#define PB_WORD_MSB 0x4B
#define PB_WORD_LSB 0x4C
#define VSIM_REMAP 0x94
#define VDAC_REMAP 0x98
#define VINTANA1_DEV_GRP 0x9A
#define VINTANA1_REMAP 0x9C
#define VINTANA2_REMAP 0xA0
#define VINTANA2_DEV_GRP 0x9E
#define VINTDIG_DEV_GRP 0xA2
#define VINTDIG_REMAP 0xA4
#define VIO_DEV_GRP 0xA6
#define VIO_REMAP 0xA8
#define VDD1_REMAP 0xB2
#define VDD2_REMAP 0xC0
#define REGEN_REMAP 0xDC
#define NRESPWRON_REMAP 0xDF
#define CLKEN_REMAP 0xE2
#define SYSEN_REMAP 0xE5
#define HFCLKOUT_REMAP 0xE8
#define HFCLKOUT_DEV_GRP 0xE6
#define T32KCLKOUT_REMAP 0xEB
#define TRITON_RESET_REMAP 0xEE
#define MAINREF_REMAP 0xF1
#define VIBRA_CTL 0x45
#define VUSB1V5_DEV_GRP 0xCC
#define VUSB1V5_TYPE 0xCD
#define VUSB1V5_REMAP 0xCE
#define VUSB1V8_DEV_GRP 0xCF
#define VUSB1V8_TYPE 0xD0
#define VUSB1V8_REMAP 0xD1
#define VUSB3V1_DEV_GRP 0xD2
#define VUSB3V1_TYPE 0xD3
#define VUSB3V1_REMAP 0xD4
#define VUSBCP_DEV_GRP 0xD5
#define VUSBCP_TYPE 0xD6
#define VUSBCP_REMAP 0xD7
#define VUSB_DEDICATED1 0xD8
#define VUSB_DEDICATED2 0xD9
/* USB registers */
#define VENDOR_ID_LO 0x0
#define VENDOR_ID_HI 0x1
#define PRODUCT_ID_LO 0x2
#define PRODUCT_ID_HI 0x3
#define FUNC_CTRL 0x4
#define FUNC_CTRL_SET 0x5
#define FUNC_CTRL_CLR 0x6
# define SUSPENDM (1 << 6)
# define RESET (1 << 5)
# define OPMODE_MASK (3 << 3) /* bits 3 and 4 */
# define OPMODE_NORMAL (0 << 3)
# define OPMODE_NONDRIVING (1 << 3)
# define OPMODE_DISABLE_BIT_NRZI (2 << 3)
# define TERMSELECT (1 << 2)
# define XCVRSELECT_MASK (3 << 0) /* bits 0 and 1 */
# define XCVRSELECT_HS (0 << 0)
# define XCVRSELECT_FS (1 << 0)
# define XCVRSELECT_LS (2 << 0)
# define XCVRSELECT_FS4LS (3 << 0)
#define IFC_CTRL 0x7
#define IFC_CTRL_SET 0x8
#define IFC_CTRL_CLR 0x9
# define INTERFACE_PROTECT_DISABLE (1 << 7)
# define AUTORESUME (1 << 4)
# define CLOCKSUSPENDM (1 << 3)
# define CARKITMODE (1 << 2)
# define FSLSSERIALMODE_3PIN (1 << 1)
#define OTG_CTRL 0xa
#define OTG_CTRL_SET 0xb
#define OTG_CTRL_CLR 0xc
#define DRVVBUS (1 << 5)
#define CHRGVBUS (1 << 4)
#define DISCHRGVBUS (1 << 3)
#define DMPULLDOWN (1 << 2)
#define DPPULLDOWN (1 << 1)
#define IDPULLUP (1 << 0)
#define USB_INT_EN_RISE 0xd
#define USB_INT_EN_RISE_SET 0xe
#define USB_INT_EN_RISE_CLR 0xf
#define USB_INT_EN_FALL 0x10
#define USB_INT_EN_FALL_SET 0x11
#define USB_INT_EN_FALL_CLR 0x12
# define HOSTDISCONNECT (1 << 0)
#define USB_INT_STS 0x13
#define USB_INT_LATCH 0x14
#define USB_DEBUG 0x15
#define SCRATCH_REG 0x16
#define SCRATCH_REG_SET 0x17
#define SCRATCH_REG_CLR 0x18
#define CARKIT_CTRL 0x19
#define CARKIT_CTRL_SET 0x1a
#define CARKIT_CTRL_CLR 0x1b
#define MICEN (1 << 6)
#define SPKRIGHTEN (1 << 5)
#define SPKLEFTEN (1 << 4)
#define RXDEN (1 << 3)
#define TXDEN (1 << 2)
#define IDGNDDRV (1 << 1)
#define CARKITPWR (1 << 0)
#define CARKIT_INT_DELAY 0x1c
#define CARKIT_INT_EN 0x1d
#define CARKIT_INT_EN_SET 0x1e
#define CARKIT_INT_EN_CLR 0x1f
#define CARKIT_INT_STS 0x20
#define CARKIT_INT_LATCH 0x21
#define CARKIT_PLS_CTRL 0x22
#define CARKIT_PLS_CTRL_SET 0x23
#define CARKIT_PLS_CTRL_CLR 0x24
# define SPKRRIGHT_BIASEN (1 << 3)
# define SPKRLEFT_BIASEN (1 << 2)
# define RXPLSEN (1 << 1)
# define TXPLSEN (1 << 0)
#define TRANS_POS_WIDTH 0x25
#define TRANS_NEG_WIDTH 0x26
#define RCV_PLTY_RECOVERY 0x27
#define MCPC_CTRL 0x30
#define MCPC_CTRL_SET 0x31
#define MCPC_CTRL_CLR 0x32
#define RTSOL (1 << 7)
#define EXTSWR (1 << 6)
#define EXTSWC (1 << 5)
#define VOICESW (1 << 4)
#define OUT64K (1 << 3)
#define RTSCTSSW (1 << 2)
#define HS_UART (1 << 0)
#define MCPC_IO_CTRL 0x033
#define MCPC_IO_CTRL_SET 0x034
#define MCPC_IO_CTRL_CLR 0x035
#define MICBIASEN (1<< 5)
#define CTS_NPU (1 << 4)
#define RXD_PU (1 << 3)
#define TXDTYP (1 << 2)
#define CTSTYP (1 << 1)
#define RTSTYP (1 << 0)
#define MCPC_CTRL2 0x036
#define MCPC_CTRL2_SET 0x037
#define MCPC_CTRL2_CLR 0x038
# define MCPC_CK_EN (1 << 0)
#define OTHER_FUNC_CTRL 0x080
#define OTHER_FUNC_CTRL_SET 0x081
#define OTHER_FUNC_CTRL_CLR 0x082
#define BDIS_ACON_EN (1<< 4)
#define FIVEWIRE_MODE (1 << 2)
#define OTHER_IFC_CTRL 0x083
#define OTHER_IFC_CTRL_SET 0x084
#define OTHER_IFC_CTRL_CLR 0x085
# define OE_INT_EN (1 << 6)
# define CEA2011_MODE (1 << 5)
# define FSLSSERIALMODE_4PIN (1 << 4)
# define HIZ_ULPI_60MHZ_OUT (1 << 3)
# define HIZ_ULPI (1 << 2)
# define ALT_INT_REROUTE (1 << 0)
#define OTHER_INT_EN_RISE 0x086
#define OTHER_INT_EN_RISE_SET 0x087
#define OTHER_INT_EN_RISE_CLR 0x088
#define OTHER_INT_EN_FALL 0x089
#define OTHER_INT_EN_FALL_SET 0x08A
#define OTHER_INT_EN_FALL_CLR 0x08B
#define OTHER_INT_STS 0x8C
#define OTHER_INT_LATCH 0x8D
#define ID_INT_EN_RISE 0x08E
#define ID_INT_EN_RISE_SET 0x08F
#define ID_INT_EN_RISE_CLR 0x090
#define ID_INT_EN_FALL 0x091
#define ID_INT_EN_FALL_SET 0x092
#define ID_INT_EN_FALL_CLR 0x093
#define ID_INT_STS 0x094
#define ID_INT_LATCH 0x95
#define ID_STATUS 0x96
#define CARKIT_SM_1_INT_EN 0x097
#define CARKIT_SM_1_INT_EN_SET 0x098
#define CARKIT_SM_1_INT_EN_CLR 0x099
#define CARKIT_SM_1_INT_STS 0x09A
#define CARKIT_SM_1_INT_LATCH 0x9B
#define CARKIT_SM_2_INT_EN 0x09C
#define CARKIT_SM_2_INT_EN_SET 0x09D
#define CARKIT_SM_2_INT_EN_CLR 0x09E
#define CARKIT_SM_2_INT_STS 0x09F
#define CARKIT_SM_2_INT_LATCH 0xA0
#define CARKIT_SM_CTRL 0x0A1
#define CARKIT_SM_CTRL_SET 0x0A2
#define CARKIT_SM_CTRL_CLR 0x0A3
#define CARKIT_SM_CMD 0x0A4
#define CARKIT_SM_CMD_SET 0x0A5
#define CARKIT_SM_CMD_CLR 0x0A6
#define CARKIT_SM_CMD_STS 0xA7
#define CARKIT_SM_STATUS 0xA8
#define CARKIT_SM_NEXT_STATUS 0xA9
#define CARKIT_SM_ERR_STATUS 0xAA
#define CARKIT_SM_CTRL_STATE 0xAB
#define POWER_CTRL 0xAC
#define POWER_CTRL_SET 0xAD
#define POWER_CTRL_CLR 0xAE
# define OTG_ENAB (1 << 5)
#define OTHER_IFC_CTRL2 0xAF
#define OTHER_IFC_CTRL2_SET 0xB0
#define OTHER_IFC_CTRL2_CLR 0xB1
# define ULPI_TXEN_POL (1 << 3)
# define ULPI_4PIN_2430 (1 << 2)
#define REG_CTRL_EN 0xB2
#define REG_CTRL_EN_SET 0xB3
#define REG_CTRL_EN_CLR 0xB4
#define REG_CTRL_ERROR 0xB5
#define ULPI_I2C_CONFLICT_INTEN (1 << 0)
#define OTHER_FUNC_CTRL2 0xB8
#define OTHER_FUNC_CTRL2_SET 0xB9
#define OTHER_FUNC_CTRL2_CLR 0xBA
#define VBAT_TIMER_EN (1 << 0)
#define CARKIT_ANA_CTRL 0xBB
#define CARKIT_ANA_CTRL_SET 0xBC
#define CARKIT_ANA_CTRL_CLR 0xBD
#define VBUS_DEBOUNCE 0xC0
#define ID_DEBOUNCE 0xC1
#define TPH_DP_CON_MIN 0xC2
#define TPH_DP_CON_MAX 0xC3
#define TCR_DP_CON_MIN 0xC4
#define TCR_DP_CON_MAX 0xC5
#define TPH_DP_PD_SHORT 0xC6
#define TPH_CMD_DLY 0xC7
#define TPH_DET_RST 0xC8
#define TPH_AUD_BIAS 0xC9
#define TCR_UART_DET_MIN 0xCA
#define TCR_UART_DET_MAX 0xCB
#define TPH_ID_INT_PW 0xCD
#define TACC_ID_INT_WAIT 0xCE
#define TACC_ID_INT_PW 0xCF
#define TPH_CMD_WAIT 0xD0
#define TPH_ACK_WAIT 0xD1
#define TPH_DP_DISC_DET 0xD2
#define VBAT_TIMER 0xD3
#define CARKIT_4W_DEBUG 0xE0
#define CARKIT_5W_DEBUG 0xE1
#define CARKIT_5W_DEBUG 0xE1
#define TEST_CTRL_CLR 0xEB
#define TEST_CARKIT_SET 0xEC
#define TEST_CARKIT_CLR 0xED
#define TEST_POWER_SET 0xEE
#define TEST_POWER_CLR 0xEF
#define TEST_ULPI 0xF0
#define TXVR_EN_TEST_SET 0xF2
#define TXVR_EN_TEST_CLR 0xF3
#define VBUS_EN_TEST 0xF4
#define ID_EN_TEST 0xF5
#define PSM_EN_TEST_SET 0xF6
#define PSM_EN_TEST_CLR 0xF7
#define PHY_TRIM_CTRL 0xFC
#define PHY_PWR_CTRL 0xFD
# define PHYPWD (1 << 0)
#define PHY_CLK_CTRL 0xFE
# define CLOCKGATING_EN (1 << 2)
# define CLK32K_EN (1 << 1)
# define REQ_PHY_DPLL_CLK (1 << 0)
#define PHY_CLK_CTRL_STS 0xFF
# define PHY_DPLL_CLK (1 << 0)
#endif

5
lk/dev/rules.mk Normal file
View File

@ -0,0 +1,5 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
OBJS += \
$(LOCAL_DIR)/dev.o

5
lk/dev/usb/rules.mk Normal file
View File

@ -0,0 +1,5 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
OBJS += \
$(LOCAL_DIR)/usb.o

307
lk/dev/usb/usb.c Normal file
View File

@ -0,0 +1,307 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <debug.h>
#include <err.h>
#include <stdlib.h>
#include <string.h>
#include <dev/usbc.h>
#include <dev/usb.h>
#define LOCAL_TRACE 0
#define MAX_STRINGS 8
static usb_string strings[MAX_STRINGS];
static usb_config *config;
static uint8_t active_config;
static bool usb_active = false;
static void append_desc_data(usb_descriptor *desc, const void *dat, size_t len)
{
uint8_t *ptr = malloc(desc->len + len);
memcpy(ptr, desc->desc, desc->len);
memcpy(ptr + desc->len, dat, len);
free(desc->desc);
desc->desc = ptr;
desc->len += len;
}
/* returns the interface number assigned */
static int usb_append_interface(usb_descriptor *desc, const uint8_t *int_descr, size_t len)
{
uint8_t *ptr = malloc(len);
int interface_num;
// create a temporary copy of the interface
memcpy(ptr, int_descr, len);
// find the last interface used
interface_num = ((uint8_t *)desc->desc)[4]; // current interface
// patch our interface descriptor with the new id
ptr[2] = interface_num;
// append it to our config desriptor
append_desc_data(desc, ptr, len);
free(ptr);
// patch the total length of the config descriptor and set the number of interfaces
((uint16_t *)desc->desc)[1] += len;
interface_num++;
((uint8_t *)desc->desc)[4] = interface_num;
return interface_num - 1;
}
int usb_append_interface_highspeed(const uint8_t *int_descr, size_t len)
{
return usb_append_interface(&config->highspeed.config, int_descr, len);
}
int usb_append_interface_lowspeed(const uint8_t *int_descr, size_t len)
{
return usb_append_interface(&config->lowspeed.config, int_descr, len);
}
void usb_set_string_descriptor(usb_descriptor *desc, const char *string)
{
int len = strlen(string);
ushort *data;
int datalen = len * 2 + 2;
data = malloc(datalen);
/* write length field */
data[0] = 0x0300 + datalen;
/* copy the string into the uint16_t based usb string */
int i;
for (i = 0; i < len; i++) {
data[i + 1] = string[i];
}
desc->desc = (void *)data;
desc->len = datalen;
}
static void set_usb_id(uint16_t vendor, uint16_t product)
{
// patch the current configuration to with the vendor/product id
((uint16_t *)config->lowspeed.device.desc)[4] = vendor;
((uint16_t *)config->lowspeed.device.desc)[5] = product;
((uint16_t *)config->highspeed.device.desc)[4] = vendor;
((uint16_t *)config->highspeed.device.desc)[5] = product;
}
void usb_add_string(const char *string, uint8_t id)
{
uint i;
size_t len = strlen(string);
uint16_t *strbuf = malloc(len * 2 + 2);
/* build the usb string descriptor */
strbuf[0] = 0x300 | (len * 2 + 2);
for (i = 0; i < len; i++) {
strbuf[i + 1] = (uint16_t)string[i];
}
/* find a slot to put it */
for (i = 0; i < MAX_STRINGS; i++) {
if (strings[i].id == 0) {
strings[i].string.desc = strbuf;
strings[i].string.len = len * 2 + 2;
strings[i].id = id;
break;
}
}
}
static int default_usb_callback(usbc_callback_op_t op, const union usb_callback_args *args)
{
LTRACEF("op %d, args %p\n", op, args);
/* start looking for specific things to handle */
if (op == CB_SETUP_MSG) {
const struct usb_setup *setup = args->setup;
DEBUG_ASSERT(setup);
LTRACEF("SETUP: req_type=%#x req=%#x value=%#x index=%#x len=%#x\n", setup->request_type, setup->request, setup->value, setup->index, setup->length);
if ((setup->request_type & TYPE_MASK) == TYPE_STANDARD) {
switch (setup->request) {
case SET_ADDRESS:
LTRACEF("SET_ADDRESS 0x%x\n", setup->value);
usbc_ep0_ack();
break;
case SET_FEATURE:
case CLEAR_FEATURE:
// OTAY
LTRACEF("SET/CLEAR_FEATURE, feature 0x%x\n", setup->value);
usbc_ep0_ack();
break;
case SET_DESCRIPTOR:
LTRACEF("SET_DESCRIPTOR\n");
usbc_ep0_stall();
break;
case GET_DESCRIPTOR: {
/* Get the right descriptors based on current speed */
const struct usb_descriptor_speed *speed;
if (usbc_is_highspeed()) {
speed = &config->highspeed;
} else {
speed = &config->lowspeed;
}
if ((setup->request_type & RECIP_MASK) == RECIP_DEVICE) {
switch (setup->value) {
case 0x100: /* device */
LTRACEF("got GET_DESCRIPTOR, device descriptor\n");
usbc_ep0_send(speed->device.desc, speed->device.len,
setup->length);
break;
case 0x200: /* CONFIGURATION */
LTRACEF("got GET_DESCRIPTOR, config descriptor\n");
usbc_ep0_send(speed->config.desc, speed->config.len,
setup->length);
break;
case 0x300: /* Language ID */
LTRACEF("got GET_DESCRIPTOR, language id\n");
usbc_ep0_send(config->langid.desc,
config->langid.len, setup->length);
break;
case (0x301)...(0x3ff): {
/* string descriptor, search our list for a match */
uint i;
bool found = false;
uint8_t id = setup->value & 0xff;
for (i = 0; i < MAX_STRINGS; i++) {
if (strings[i].id == id) {
usbc_ep0_send(strings[i].string.desc,
strings[i].string.len,
setup->length);
found = true;
break;
}
}
if (!found) {
/* couldn't find one, stall */
usbc_ep0_stall();
}
break;
}
case 0x600: /* DEVICE QUALIFIER */
LTRACEF("got GET_DESCRIPTOR, device qualifier\n");
usbc_ep0_send(speed->device_qual.desc,
speed->device_qual.len, setup->length);
break;
case 0xa00:
/* we aint got one of these */
LTRACEF("got GET_DESCRIPTOR, debug descriptor\n");
usbc_ep0_stall();
break;
default:
LTRACEF("unhandled descriptor %#x\n", setup->value);
// stall
break;
}
} else {
// interface/endpoint descriptors? let someone else handle it
// STALL
}
break;
}
case SET_CONFIGURATION:
LTRACEF("SET_CONFIGURATION %d\n", setup->value);
active_config = setup->value;
usbc_ep0_ack();
break;
case GET_CONFIGURATION:
LTRACEF("GET_CONFIGURATION\n");
usbc_ep0_send(&active_config, 1, setup->length);
break;
case SET_INTERFACE:
LTRACEF("SET_INTERFACE %d\n", setup->value);
usbc_ep0_ack();
break;
case GET_INTERFACE: {
static uint8_t i = 1;
LTRACEF("GET_INTERFACE\n");
usbc_ep0_send(&i, 1, setup->length);
break;
}
case GET_STATUS: {
static uint16_t i = 1; // self powered
LTRACEF("GET_STATUS\n");
usbc_ep0_send(&i, 2, setup->length);
break;
}
default:
LTRACEF("unhandled standard request 0x%x\n", setup->request);
}
}
}
return 0;
}
void usb_setup(usb_config *_config)
{
ASSERT(_config);
config = _config;
ASSERT(usb_active == false);
// set the default usb control callback handler
usbc_set_callback(&default_usb_callback);
}
void usb_start(void)
{
ASSERT(config);
ASSERT(usb_active == false);
// go online
usbc_set_active(true);
usb_active = true;
}
void usb_stop(void)
{
ASSERT(usb_active == true);
usb_active = false;
usbc_set_active(false);
}
void usb_init(void)
{
}

49
lk/include/app.h Normal file
View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2009 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __APP_H
#define __APP_H
/* app support api */
void apps_init(void); /* one time setup */
/* app entry point */
struct app_descriptor;
typedef void (*app_init)(const struct app_descriptor *);
typedef void (*app_entry)(const struct app_descriptor *, void *args);
/* app startup flags */
#define APP_FLAG_DONT_START_ON_BOOT 0x1
/* each app needs to define one of these to define its startup conditions */
struct app_descriptor {
const char *name;
app_init init;
app_entry entry;
unsigned int flags;
};
#define APP_START(appname) struct app_descriptor _app_##appname __SECTION(".apps") = { .name = #appname,
#define APP_END };
#endif

37
lk/include/arch.h Normal file
View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __ARCH_H
#define __ARCH_H
#if defined(__cplusplus)
extern "C" {
#endif
void arch_early_init(void);
void arch_init(void);
#if defined(__cplusplus)
}
#endif
#endif

71
lk/include/arch/ops.h Normal file
View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __ARCH_OPS_H
#define __ARCH_OPS_H
#ifndef ASSEMBLY
#include <sys/types.h>
#include <compiler.h>
#if defined(__cplusplus)
extern "C" {
#endif
void arch_enable_ints(void);
void arch_disable_ints(void);
int atomic_swap(volatile int *ptr, int val);
int atomic_add(volatile int *ptr, int val);
int atomic_and(volatile int *ptr, int val);
int atomic_or(volatile int *ptr, int val);
#endif // !ASSEMBLY
#define ICACHE 1
#define DCACHE 2
#define UCACHE (ICACHE|DCACHE)
#ifndef ASSEMBLY
void arch_disable_cache(uint flags);
void arch_enable_cache(uint flags);
void arch_clean_cache_range(addr_t start, size_t len);
void arch_clean_invalidate_cache_range(addr_t start, size_t len);
void arch_idle(void);
void arch_disable_mmu(void);
void arch_switch_stacks_and_call(addr_t call, addr_t stack) __NO_RETURN;
#if defined(__cplusplus)
}
#endif
#endif // !ASSEMBLY
#if ARCH_ARM
#include <arch/arm/ops.h>
#endif
#endif

34
lk/include/arch/thread.h Normal file
View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __ARCH_THREAD_H
#define __ARCH_THREAD_H
// give the arch code a chance to declare the arch_thread struct
#include <arch/arch_thread.h>
struct thread;
void arch_thread_initialize(struct thread *);
void arch_context_switch(struct thread *oldthread, struct thread *newthread);
#endif

30
lk/include/asm.h Normal file
View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __ASM_H
#define __ASM_H
//#define FUNCTION(x) .global x; .type x,@function; x:
#define FUNCTION(x) .global x; x:
#endif

40
lk/include/assert.h Normal file
View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __ASSERT_H
#define __ASSERT_H
#include <compiler.h>
#include <debug.h>
#define ASSERT(x) \
do { if (unlikely(!(x))) { panic("ASSERT FAILED at (%s:%d): %s\n", __FILE__, __LINE__, #x); } } while (0)
#if DEBUGLEVEL > 1
#define DEBUG_ASSERT(x) \
do { if (unlikely(!(x))) { panic("DEBUG ASSERT FAILED at (%s:%d): %s\n", __FILE__, __LINE__, #x); } } while (0)
#else
#define DEBUG_ASSERT(x) \
do { } while(0)
#endif
#endif

59
lk/include/bits.h Normal file
View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __BITS_H
#define __BITS_H
#include <arch/ops.h>
#define clz(x) __builtin_clz(x)
#define BIT(x, bit) ((x) & (1 << (bit)))
#define BIT_SHIFT(x, bit) (((x) >> (bit)) & 1)
#define BITS(x, high, low) ((x) & (((1<<((high)+1))-1) & ~((1<<(low))-1)))
#define BITS_SHIFT(x, high, low) (((x) >> (low)) & ((1<<((high)-(low)+1))-1))
#define BIT_SET(x, bit) (((x) & (1 << (bit))) ? 1 : 0)
#define BITMAP_BITS_PER_WORD (sizeof(unsigned long) * 8)
#define BITMAP_NUM_WORDS(x) (((x) / BITMAP_BITS_PER_WORD) + 1)
#define BITMAP_WORD(x) ((x) / BITMAP_BITS_PER_WORD)
#define BITMAP_BIT_IN_WORD(x) ((x) & (BITMAP_BITS_PER_WORD - 1))
static inline int bitmap_set(unsigned long *bitmap, int bit)
{
unsigned long mask = 1 << BITMAP_BIT_IN_WORD(bit);
return atomic_or((int*)&bitmap[BITMAP_WORD(bit)], mask) & mask ? 1 : 0;
}
static inline int bitmap_clear(unsigned long *bitmap, int bit)
{
unsigned long mask = 1 << BITMAP_BIT_IN_WORD(bit);
return atomic_and((int*)&bitmap[BITMAP_WORD(bit)], ~mask) & mask ? 1:0;
}
static inline int bitmap_test(unsigned long *bitmap, int bit)
{
return BIT_SET(bitmap[BITMAP_WORD(bit)], BITMAP_BIT_IN_WORD(bit));
}
#endif

109
lk/include/compiler.h Normal file
View File

@ -0,0 +1,109 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __COMPILER_H
#define __COMPILER_H
#ifndef __ASSEMBLY__
#if __GNUC__
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#define __UNUSED __attribute__((__unused__))
#define __PACKED __attribute__((packed))
#define __ALIGNED(x) __attribute__((aligned(x)))
#define __PRINTFLIKE(__fmt,__varargs) __attribute__((__format__ (__printf__, __fmt, __varargs)))
#define __SCANFLIKE(__fmt,__varargs) __attribute__((__format__ (__scanf__, __fmt, __varargs)))
#define __SECTION(x) __attribute((section(x)))
#define __PURE __attribute((pure))
#define __CONST __attribute((const))
#define __NO_RETURN __attribute__((noreturn))
#define __MALLOC __attribute__((malloc))
#define __WEAK __attribute__((weak))
#define __GNU_INLINE __attribute__((gnu_inline))
#define __GET_CALLER(x) __builtin_return_address(0)
/* look for gcc 3.0 and above */
#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 0)
#define __ALWAYS_INLINE __attribute__((always_inline))
#else
#define __ALWAYS_INLINE
#endif
/* look for gcc 3.1 and above */
#if !defined(__DEPRECATED) // seems to be built in in some versions of the compiler
#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
#define __DEPRECATED __attribute((deprecated))
#else
#define __DEPRECATED
#endif
#endif
/* look for gcc 3.3 and above */
#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
/* the may_alias attribute was introduced in gcc 3.3; before that, there
* was no way to specify aliasiang rules on a type-by-type basis */
#define __MAY_ALIAS __attribute__((may_alias))
/* nonnull was added in gcc 3.3 as well */
#define __NONNULL(x) __attribute((nonnull x))
#else
#define __MAY_ALIAS
#define __NONNULL(x)
#endif
/* look for gcc 3.4 and above */
#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
#define __WARN_UNUSED_RESULT __attribute((warn_unused_result))
#else
#define __WARN_UNUSED_RESULT
#endif
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)
#define __EXTERNALLY_VISIBLE __attribute__((externally_visible))
#else
#define __EXTERNALLY_VISIBLE
#endif
#else
#define likely(x) (x)
#define unlikely(x) (x)
#define __UNUSED
#define __PACKED
#define __ALIGNED(x)
#define __PRINTFLIKE(__fmt,__varargs)
#define __SCANFLIKE(__fmt,__varargs)
#define __SECTION(x)
#define __PURE
#define __CONST
#define __NONNULL(x)
#define __DEPRECATED
#define __WARN_UNUSED_RESULT
#define __ALWAYS_INLINE
#define __MAY_ALIAS
#define __NO_RETURN
#endif
#endif
#endif

43
lk/include/ctype.h Normal file
View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __CTYPE_H
#define __CTYPE_H
int isalnum(int c);
int isalpha(int c);
int isblank(int c);
int iscntrl(int c);
int isdigit(int c);
int isgraph(int c);
int islower(int c);
int isprint(int c);
int ispunct(int c);
int isspace(int c);
int isupper(int c);
int isxdigit(int c);
int tolower(int c);
int toupper(int c);
#endif

95
lk/include/debug.h Normal file
View File

@ -0,0 +1,95 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __DEBUG_H
#define __DEBUG_H
#include <assert.h>
#include <stdarg.h>
#include <compiler.h>
#include <platform/debug.h>
#include <printf.h>
#if defined(__cplusplus)
extern "C" {
#endif
#if defined(DEBUG)
#define DEBUGLEVEL DEBUG
#else
#define DEBUGLEVEL 2
#endif
/* debug levels */
#define CRITICAL 0
#define ALWAYS 0
#define INFO 1
#define SPEW 2
/* output */
void _dputc(char c); // XXX for now, platform implements
int _dputs(const char *str);
int _dprintf(const char *fmt, ...) __PRINTFLIKE(1, 2);
int _dvprintf(const char *fmt, va_list ap);
#define dputc(level, str) do { if ((level) <= DEBUGLEVEL) { _dputc(str); } } while (0)
#define dputs(level, str) do { if ((level) <= DEBUGLEVEL) { _dputs(str); } } while (0)
#define dprintf(level, x...) do { if ((level) <= DEBUGLEVEL) { _dprintf(x); } } while (0)
#define dvprintf(level, x...) do { if ((level) <= DEBUGLEVEL) { _dvprintf(x); } } while (0)
/* input */
int dgetc(char *c);
/* systemwide halts */
void halt(void) __NO_RETURN;
void _panic(void *caller, const char *fmt, ...) __PRINTFLIKE(2, 3) __NO_RETURN;
#define panic(x...) _panic(__GET_CALLER(), x)
#define PANIC_UNIMPLEMENTED panic("%s unimplemented\n", __PRETTY_FUNCTION__)
/* spin the cpu for a period of (short) time */
void spin(uint32_t usecs);
/* dump memory */
void hexdump(const void *ptr, size_t len);
void hexdump8(const void *ptr, size_t len);
/* trace routines */
#define TRACE_ENTRY printf("%s: entry\n", __PRETTY_FUNCTION__)
#define TRACE_EXIT printf("%s: exit\n", __PRETTY_FUNCTION__)
#define TRACE_ENTRY_OBJ printf("%s: entry obj %p\n", __PRETTY_FUNCTION__, this)
#define TRACE_EXIT_OBJ printf("%s: exit obj %p\n", __PRETTY_FUNCTION__, this)
#define TRACE printf("%s:%d\n", __PRETTY_FUNCTION__, __LINE__)
#define TRACEF(x...) do { printf("%s:%d: ", __PRETTY_FUNCTION__, __LINE__); printf(x); } while (0)
/* trace routines that work if LOCAL_TRACE is set */
#define LTRACE_ENTRY do { if (LOCAL_TRACE) { TRACE_ENTRY; } } while (0)
#define LTRACE_EXIT do { if (LOCAL_TRACE) { TRACE_EXIT; } } while (0)
#define LTRACE do { if (LOCAL_TRACE) { TRACE; } } while (0)
#define LTRACEF(x...) do { if (LOCAL_TRACE) { TRACEF(x); } } while (0)
#if defined(__cplusplus)
}
#endif
#endif

38
lk/include/dev/ethernet.h Normal file
View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __DEV_ETHERNET_H
#define __DEV_ETHERNET_H
/* Queue an ethernet frame for send.
**
** CRC and minimum length padding are handled by the driver.
**
** Data is malloc()'d and ownership is transfered to the ethernet
** device which will free() it once the packet is transmitted.
**
*/
int ethernet_send(void *data, unsigned length);
status_t ethernet_init(void); /* initialize the ethernet device */
#endif

54
lk/include/dev/fbcon.h Normal file
View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2008, Google Inc.
* All rights reserved.
*
* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef __DEV_FBCON_H
#define __DEV_FBCON_H
#define FB_FORMAT_RGB565 0
#define FB_FORMAT_RGB888 1
struct fbcon_config {
void *base;
unsigned width;
unsigned height;
unsigned stride;
unsigned bpp;
unsigned format;
void (*update_start)(void);
int (*update_done)(void);
};
void fbcon_setup(struct fbcon_config *cfg);
void fbcon_putc(char c);
void fbcon_clear(void);
struct fbcon_config* fbcon_display(void);
#endif /* __DEV_FBCON_H */

67
lk/include/dev/flash.h Normal file
View File

@ -0,0 +1,67 @@
/*
* Copyright (c) 2008, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef __DEV_FLASH_H
#define __DEV_FLASH_H
#include <lib/ptable.h>
struct flash_info {
unsigned id;
unsigned type;
unsigned vendor;
unsigned device;
unsigned page_size;
unsigned block_size;
unsigned spare_size;
unsigned num_blocks;
};
void flash_init(void);
struct ptable *flash_get_ptable(void);
void flash_set_ptable(struct ptable *ptable);
struct flash_info *flash_get_info(void);
/* flash operations */
int flash_erase(struct ptentry *ptn);
int flash_read_ext(struct ptentry *ptn, unsigned extra_per_page,
unsigned offset, void *data, unsigned bytes);
int flash_write(struct ptentry *ptn, unsigned extra_per_page, const void *data,
unsigned bytes);
static inline int flash_read(struct ptentry *ptn, unsigned offset, void *data,
unsigned bytes)
{
return flash_read_ext(ptn, 0, offset, data, bytes);
}
unsigned flash_page_size(void);
#endif /* __DEV_FLASH_H */

51
lk/include/dev/gpio.h Normal file
View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2008, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef __DEV_GPIO_H
#define __DEV_GPIO_H
#define GPIO_INPUT 0x0000
#define GPIO_OUTPUT 0x0001
#define GPIO_LEVEL 0x0000
#define GPIO_EDGE 0x0010
#define GPIO_RISING 0x0020
#define GPIO_FALLING 0x0040
#define GPIO_HIGH 0x0020
#define GPIO_LOW 0x0040
#define GPIO_PULLUP 0x0100
#define GPIO_PULLDOWN 0x0200
int gpio_config(unsigned nr, unsigned flags);
void gpio_set(unsigned nr, unsigned on);
int gpio_get(unsigned nr);
#endif

View File

@ -0,0 +1,248 @@
/*
* Copyright (c) 2008, Google Inc.
* All rights reserved.
*
* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google, Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef __DEV_GPIO_KEYPAD_H
#define __DEV_GPIO_KEYPAD_H
#include <sys/types.h>
/* unset: drive active output low, set: drive active output high */
#define GPIOKPF_ACTIVE_HIGH (1U << 0)
#define GPIOKPF_DRIVE_INACTIVE (1U << 1)
struct gpio_keypad_info {
/* size must be ninputs * noutputs */
const uint16_t *keymap;
unsigned *input_gpios;
unsigned *output_gpios;
int ninputs;
int noutputs;
/* time to wait before reading inputs after driving each output */
time_t settle_time;
time_t poll_time;
unsigned flags;
};
void gpio_keypad_init(struct gpio_keypad_info *kpinfo);
//Macros for SSBI Qwerty keypad for 7x30
/* SSBI 2.0 controller registers */
#define MSM_SSBI_BASE 0xAD900000
#define SSBI_TIMEOUT_US 100
#define SSBI2_CTL 0x0000
#define SSBI2_RESET 0x0004
#define SSBI2_CMD 0x0008
#define SSBI2_RD 0x0010
#define SSBI2_STATUS 0x0014
#define SSBI2_PRIORITIES 0x0018
#define SSBI2_MODE2 0x001C
/* SSBI_CMD fields */
#define SSBI_CMD_SEND_TERM_SYM (0x01 << 27)
#define SSBI_CMD_WAKEUP_SLAVE (0x01 << 26)
#define SSBI_CMD_USE_ENABLE (0x01 << 25)
#define SSBI_CMD_RDWRN (0x01 << 24)
#define SSBI_CMD_REG_ADDR_SHFT (0x10)
#define SSBI_CMD_REG_ADDR_MASK (0xFF << SSBI_CMD_REG_ADDR_SHFT)
#define SSBI_CMD_REG_DATA_SHFT (0x00)
#define SSBI_CMD_REG_DATA_MASK (0xFF << SSBI_CMD_REG_DATA_SHFT)
/* SSBI_STATUS fields */
#define SSBI_STATUS_DATA_IN 0x10
#define SSBI_STATUS_RD_CLOBBERED 0x08
#define SSBI_STATUS_RD_READY 0x04
#define SSBI_STATUS_READY 0x02
#define SSBI_STATUS_MCHN_BUSY 0x01
/* SSBI_RD fields */
#define SSBI_RD_USE_ENABLE 0x02000000
#define SSBI_RD_RDWRN 0x01000000
#define SSBI_RD_REG_ADDR_SHFT 0x10
#define SSBI_RD_REG_ADDR_MASK (0xFF << SSBI_RD_REG_ADDR_SHFT)
#define SSBI_RD_REG_DATA_SHFT (0x00)
#define SSBI_RD_REG_DATA_MASK (0xFF << SSBI_RD_REG_DATA_SHFT)
/* SSBI_MODE2 fields */
#define SSBI_MODE2_REG_ADDR_15_8_SHFT 0x04
#define SSBI_MODE2_REG_ADDR_15_8_MASK (0x7F << SSBI_MODE2_REG_ADDR_15_8_SHFT)
#define SSBI_MODE2_ADDR_WIDTH_SHFT 0x01
#define SSBI_MODE2_ADDR_WIDTH_MASK (0x07 << SSBI_MODE2_ADDR_WIDTH_SHFT)
#define SSBI_MODE2_SSBI2_MODE 0x00000001
//Keypad controller configurations
#define SSBI_REG_KYPD_CNTL_ADDR 0x148
#define SSBI_REG_KYPD_SCAN_ADDR 0x149
#define SSBI_REG_KYPD_TEST_ADDR 0x14A
#define SSBI_REG_KYPD_REC_DATA_ADDR 0x14B
#define SSBI_REG_KYPD_OLD_DATA_ADDR 0x14C
// GPIO configurations
#define SSBI_REG_ADDR_GPIO_BASE 0x150
#define SSBI_OFFSET_ADDR_GPIO_KYPD_SNS 0x000
#define SSBI_OFFSET_ADDR_GPIO_KYPD_DRV 0x008
#define SSBI_REG_ADDR_GPIO(n) (SSBI_REG_ADDR_GPIO_BASE + n)
#define PM_GPIO_DIR_OUT 0x01
#define PM_GPIO_DIR_IN 0x02
#define PM_GPIO_DIR_BOTH (PM_GPIO_DIR_OUT | PM_GPIO_DIR_IN)
#define PM_GPIO_PULL_UP1 2
#define PM_GPIO_PULL_UP2 3
#define PM_GPIO_PULL_DN 4
#define PM_GPIO_PULL_NO 5
#define PM_GPIO_STRENGTH_NO 0
#define PM_GPIO_STRENGTH_HIGH 1
#define PM_GPIO_STRENGTH_MED 2
#define PM_GPIO_STRENGTH_LOW 3
#define PM_GPIO_FUNC_NORMAL 0
#define PM_GPIO_FUNC_PAIRED 1
#define PM_GPIO_FUNC_1 2
#define PM_GPIO_FUNC_2 3
#define PM8058_GPIO_BANK_MASK 0x70
#define PM8058_GPIO_BANK_SHIFT 4
#define PM8058_GPIO_WRITE 0x80
/* Bank 0 */
#define PM8058_GPIO_VIN_MASK 0x0E
#define PM8058_GPIO_VIN_SHIFT 1
#define PM8058_GPIO_MODE_ENABLE 0x01
/* Bank 1 */
#define PM8058_GPIO_MODE_MASK 0x0C
#define PM8058_GPIO_MODE_SHIFT 2
#define PM8058_GPIO_OUT_BUFFER 0x02
#define PM8058_GPIO_OUT_INVERT 0x01
#define PM8058_GPIO_MODE_OFF 3
#define PM8058_GPIO_MODE_OUTPUT 2
#define PM8058_GPIO_MODE_INPUT 0
#define PM8058_GPIO_MODE_BOTH 1
/* Bank 2 */
#define PM8058_GPIO_PULL_MASK 0x0E
#define PM8058_GPIO_PULL_SHIFT 1
/* Bank 3 */
#define PM8058_GPIO_OUT_STRENGTH_MASK 0x0C
#define PM8058_GPIO_OUT_STRENGTH_SHIFT 2
/* Bank 4 */
#define PM8058_GPIO_FUNC_MASK 0x0E
#define PM8058_GPIO_FUNC_SHIFT 1
/* PMIC Arbiter 1: SSBI2 Configuration Micro ARM registers */
#define PA1_SSBI2_CMD 0x00500000
#define PA1_SSBI2_RD_STATUS 0x00500004
#define PA1_SSBI2_REG_ADDR_SHIFT 8
#define PA1_SSBI2_CMD_RDWRN_SHIFT 24
#define PA1_SSBI2_TRANS_DONE_SHIFT 27
#define PA1_SSBI2_REG_DATA_MASK 0xFF
#define PA1_SSBI2_REG_DATA_SHIFT 0
#define PA1_SSBI2_CMD_READ 1
#define PA1_SSBI2_CMD_WRITE 0
/* PMIC Arbiter 2: SSBI2 Configuration Micro ARM registers */
#define PA2_SSBI2_CMD 0x00C00000
#define PA2_SSBI2_RD_STATUS 0x00C00004
#define PA2_SSBI2_REG_ADDR_SHIFT 8
#define PA2_SSBI2_CMD_RDWRN_SHIFT 24
#define PA2_SSBI2_TRANS_DONE_SHIFT 27
#define PA2_SSBI2_REG_DATA_MASK 0xFF
#define PA2_SSBI2_REG_DATA_SHIFT 0
#define PA2_SSBI2_CMD_READ 1
#define PA2_SSBI2_CMD_WRITE 0
struct pm8058_gpio {
int direction;
int pull;
int vin_sel; /* 0..7 */
int out_strength;
int function;
int inv_int_pol; /* invert interrupt polarity */
};
typedef int (*read_func)(unsigned char *, unsigned short, unsigned short);
typedef int (*write_func)(unsigned char *, unsigned short, unsigned short);
struct qwerty_keypad_info {
/* size must be ninputs * noutputs */
unsigned int *keymap;
unsigned char *old_keys;
unsigned char *rec_keys;
unsigned int rows;
unsigned int columns;
unsigned int num_of_reads;
read_func rd_func;
write_func wr_func;
/* time to wait before reading inputs after driving each output */
time_t settle_time;
time_t poll_time;
unsigned flags;
};
#define SSBI_CMD_READ(AD) \
(SSBI_CMD_RDWRN | (((AD) & 0xFF) << SSBI_CMD_REG_ADDR_SHFT))
#define SSBI_CMD_WRITE(AD, DT) \
((((AD) & 0xFF) << SSBI_CMD_REG_ADDR_SHFT) | \
(((DT) & 0xFF) << SSBI_CMD_REG_DATA_SHFT))
#define SSBI_MODE2_REG_ADDR_15_8(MD, AD) \
(((MD) & 0x0F) | ((((AD) >> 8) << SSBI_MODE2_REG_ADDR_15_8_SHFT) & \
SSBI_MODE2_REG_ADDR_15_8_MASK))
void ssbi_keypad_init (struct qwerty_keypad_info *);
int i2c_ssbi_read_bytes(unsigned char *buffer, unsigned short length,
unsigned short slave_addr);
int i2c_ssbi_write_bytes(unsigned char *buffer, unsigned short length,
unsigned short slave_addr);
int pa1_ssbi2_read_bytes(unsigned char *buffer, unsigned short length,
unsigned short slave_addr);
int pa1_ssbi2_write_bytes(unsigned char *buffer, unsigned short length,
unsigned short slave_addr);
#endif /* __DEV_GPIO_KEYPAD_H */

39
lk/include/dev/i2c.h Normal file
View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __DEV_I2C_H
#define __DEV_I2C_H
void i2c_init(void);
void i2c_init_early(void);
/* send and receive blocks of data */
int i2c_transmit(int bus, uint8_t address, const void *buf, size_t count);
int i2c_receive(int bus, uint8_t address, void *buf, size_t count);
/* a few convenience routines based on the usual way of accessing 8 byte registers on i2c slave devices */
int i2c_write_reg(int bus, uint8_t address, uint8_t reg, uint8_t val);
int i2c_read_reg(int bus, uint8_t address, uint8_t reg, uint8_t *val);
#endif

91
lk/include/dev/keys.h Normal file
View File

@ -0,0 +1,91 @@
/*
* Copyright (c) 2009, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google, Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef __DEV_KEYS_H
#define __DEV_KEYS_H
#include <sys/types.h>
/* these are just the ascii values for the chars */
#define KEY_0 0x30
#define KEY_1 0x31
#define KEY_2 0x32
#define KEY_3 0x33
#define KEY_4 0x34
#define KEY_5 0x35
#define KEY_6 0x36
#define KEY_7 0x37
#define KEY_8 0x38
#define KEY_9 0x39
#define KEY_A 0x61
#define KEY_ESC 0x100
#define KEY_F1 0x101
#define KEY_F2 0x102
#define KEY_F3 0x103
#define KEY_F4 0x104
#define KEY_F5 0x105
#define KEY_F6 0x106
#define KEY_F7 0x107
#define KEY_F8 0x108
#define KEY_F9 0x109
#define KEY_LEFT 0x110
#define KEY_RIGHT 0x111
#define KEY_UP 0x112
#define KEY_DOWN 0x113
#define KEY_CENTER 0x114
#define KEY_VOLUMEUP 0x115
#define KEY_VOLUMEDOWN 0x116
#define KEY_MUTE 0x117
#define KEY_SOUND 0x118
#define KEY_SOFT1 0x11a
#define KEY_SOFT2 0x11b
#define KEY_STAR 0x11c
#define KEY_SHARP 0x11d
#define KEY_MAIL 0x11e
#define KEY_SEND 0x120
#define KEY_CLEAR 0x121
#define KEY_HOME 0x122
#define KEY_BACK 0x123
#define KEY_MENU 0x124
#define MAX_KEYS 0x1ff
void keys_init(void);
void keys_post_event(uint16_t code, int16_t value);
int keys_get_state(uint16_t code);
#endif /* __DEV_KEYS_H */

38
lk/include/dev/uart.h Normal file
View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __DEV_UART_H
#define __DEV_UART_H
#include <sys/types.h>
void uart_init(void);
void uart_init_early(void);
int uart_putc(int port, char c);
int uart_getc(int port, bool wait);
void uart_flush_tx(int port);
void uart_flush_rx(int port);
void uart_init_port(int port, uint baud);
#endif

120
lk/include/dev/udc.h Normal file
View File

@ -0,0 +1,120 @@
/*
* Copyright (c) 2009, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef __DEV_UDC_H
#define __DEV_UDC_H
/* USB Device Controller Transfer Request */
struct udc_request {
void *buf;
unsigned length;
void (*complete)(struct udc_request *req, unsigned actual, int status);
void *context;
};
/* endpoints are opaque handles specific to the particular device controller */
struct udc_endpoint;
struct udc_request *udc_request_alloc(void);
void udc_request_free(struct udc_request *req);
int udc_request_queue(struct udc_endpoint *ept, struct udc_request *req);
int udc_request_cancel(struct udc_endpoint *ept, struct udc_request *req);
#define UDC_TYPE_BULK_IN 1
#define UDC_TYPE_BULK_OUT 2
struct udc_endpoint *udc_endpoint_alloc(unsigned type, unsigned maxpkt);
void udc_endpoint_free(struct udc_endpoint *ept);
#define UDC_EVENT_ONLINE 1
#define UDC_EVENT_OFFLINE 2
struct udc_gadget {
void (*notify)(struct udc_gadget *gadget, unsigned event);
void *context;
unsigned char ifc_class;
unsigned char ifc_subclass;
unsigned char ifc_protocol;
unsigned char ifc_endpoints;
const char *ifc_string;
unsigned flags;
struct udc_endpoint **ept;
};
struct udc_device {
unsigned short vendor_id;
unsigned short product_id;
unsigned short version_id;
const char *manufacturer;
const char *product;
const char *serialno;
};
int udc_init(struct udc_device *devinfo);
int udc_register_gadget(struct udc_gadget *gadget);
int udc_start(void);
int udc_stop(void);
/* these should probably go elsewhere */
#define GET_STATUS 0
#define CLEAR_FEATURE 1
#define SET_FEATURE 3
#define SET_ADDRESS 5
#define GET_DESCRIPTOR 6
#define SET_DESCRIPTOR 7
#define GET_CONFIGURATION 8
#define SET_CONFIGURATION 9
#define GET_INTERFACE 10
#define SET_INTERFACE 11
#define SYNCH_FRAME 12
#define TYPE_DEVICE 1
#define TYPE_CONFIGURATION 2
#define TYPE_STRING 3
#define TYPE_INTERFACE 4
#define TYPE_ENDPOINT 5
#define DEVICE_READ 0x80
#define DEVICE_WRITE 0x00
#define INTERFACE_READ 0x81
#define INTERFACE_WRITE 0x01
#define ENDPOINT_READ 0x82
#define ENDPOINT_WRITE 0x02
struct setup_packet {
unsigned char type;
unsigned char request;
unsigned short value;
unsigned short index;
unsigned short length;
} __attribute__ ((packed));
#endif

65
lk/include/dev/usb.h Normal file
View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __DEV_USB_H
#define __DEV_USB_H
#include <sys/types.h>
#include <compiler.h>
/* top level initialization for usb client, abstracts away the interfaces */
typedef struct {
void *desc;
size_t len;
} usb_descriptor __ALIGNED(2);
typedef struct {
usb_descriptor string;
uint8_t id;
} usb_string;
/* complete usb config struct, passed in to usb_setup() */
typedef struct {
struct usb_descriptor_speed {
usb_descriptor device;
usb_descriptor device_qual;
usb_descriptor config;
} lowspeed, highspeed;
usb_descriptor langid;
} usb_config;
void usb_init(void);
/* external code needs to set up the usb stack via the following calls */
void usb_setup(usb_config *config);
/* apped new interface descriptors to the existing config if desired */
int usb_append_interface_highspeed(const uint8_t *int_descr, size_t len);
int usb_append_interface_lowspeed(const uint8_t *int_descr, size_t len);
void usb_add_string(const char *string, uint8_t id);
void usb_start(void);
void usb_stop(void);
#endif

98
lk/include/dev/usbc.h Normal file
View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __DEV_USBC_H
#define __DEV_USBC_H
#include <sys/types.h>
#include <debug.h>
#include <hw/usb.h>
void usbc_init(void);
typedef uint ep_t;
typedef enum {
IN = 0,
OUT
} ep_dir_t;
typedef enum {
CB_RESET,
CB_SUSPEND,
CB_RESUME,
CB_DISCONNECT,
CB_ONLINE,
CB_OFFLINE,
CB_SETUP_MSG,
/* endpoint transfer stuff */
CB_EP_RXCOMPLETE,
CB_EP_TXCOMPLETE,
CB_EP_TRANSFER_CANCELLED,
} usbc_callback_op_t;
typedef struct {
void *buf;
size_t buflen;
uint bufpos;
int result;
void *extra; // extra pointer to store whatever you want
} usbc_transfer;
enum {
USB_TRANSFER_RESULT_OK = 0,
USB_TRANSFER_RESULT_ERR = -1,
USB_TRANSFER_RESULT_CANCELLED = -2,
};
typedef int (*ep_callback)(ep_t endpoint, usbc_callback_op_t op, usbc_transfer *transfer);
void usbc_setup_endpoint(ep_t ep, ep_dir_t dir, bool active, ep_callback callback, uint width, uint blocksize);
int usbc_queue_rx(ep_t ep, usbc_transfer *transfer);
int usbc_queue_tx(ep_t ep, usbc_transfer *transfer);
/* setup arg is valid during CB_SETUP_MSG */
union usb_callback_args {
const struct usb_setup *setup;
};
typedef int (*usb_callback)(usbc_callback_op_t op, const union usb_callback_args *args);
int usbc_set_callback(usb_callback);
int usbc_set_active(bool active);
/* called back from within a callback to handle setup responses */
void usbc_ep0_ack(void);
void usbc_ep0_stall(void);
void usbc_ep0_send(const void *buf, size_t len, size_t maxlen);
void usbc_ep0_recv(void *buf, size_t len, ep_callback);
bool usbc_is_highspeed(void);
static inline void usbc_dump_transfer(const usbc_transfer *t)
{
printf("usb transfer %p: buf %p, buflen %zd, bufpos %u, result %d\n", t, t->buf, t->buflen, t->bufpos, t->result);
}
#endif

95
lk/include/endian.h Normal file
View File

@ -0,0 +1,95 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __ENDIAN_H
#define __ENDIAN_H
#include <sys/types.h>
#ifndef LITTLE_ENDIAN
#define LITTLE_ENDIAN 1234
#endif
#ifndef BIG_ENDIAN
#define BIG_ENDIAN 4321
#endif
#if __POWERPC__
#include <ppc_intrinsics.h>
#endif
#if defined(ARCH_ARM)
#define BYTE_ORDER LITTLE_ENDIAN
#endif
#ifndef BYTE_ORDER
#error "need to get the BYTE_ORDER define from somewhere"
#endif
// define a macro that unconditionally swaps
#define SWAP_32(x) \
(((uint32_t)(x) << 24) | (((uint32_t)(x) & 0xff00) << 8) |(((uint32_t)(x) & 0x00ff0000) >> 8) | ((uint32_t)(x) >> 24))
#define SWAP_16(x) \
((((uint16_t)(x) & 0xff) << 8) | ((uint16_t)(x) >> 8))
// standard swap macros
#if BYTE_ORDER == BIG_ENDIAN
#define LE32(val) SWAP_32(val)
#define LE16(val) SWAP_16(val)
#define BE32(val) (val)
#define BE16(val) (val)
#else
#define LE32(val) (val)
#define LE16(val) (val)
#define BE32(val) SWAP_32(val)
#define BE16(val) SWAP_16(val)
#endif
#define LE32SWAP(var) (var) = LE32(var);
#define LE16SWAP(var) (var) = LE16(var);
#define BE32SWAP(var) (var) = BE32(var);
#define BE16SWAP(var) (var) = BE16(var);
/* classic network byte swap stuff */
#define ntohs(n) BE16(n)
#define htons(h) BE16(h)
#define ntohl(n) BE32(n)
#define htonl(h) BE32(h)
// some memory access macros
#if __POWERPC__
#define READ_MEM_WORD(ptr) __lwbrx((word *)(ptr), 0)
#define READ_MEM_HALFWORD(ptr) __lhbrx((halfword *)(ptr), 0)
#define READ_MEM_BYTE(ptr) (*(byte *)(ptr))
#define WRITE_MEM_WORD(ptr, data) __stwbrx(data, (word *)(ptr), 0)
#define WRITE_MEM_HALFWORD(ptr, data) __sthbrx(data, (halfword *)(ptr), 0)
#define WRITE_MEM_BYTE(ptr, data) (*(byte *)(ptr) = (data))
#else
#define READ_MEM_WORD(ptr) SWAPIT_32(*(word *)(ptr))
#define READ_MEM_HALFWORD(ptr) SWAPIT_16(*(halfword *)(ptr))
#define READ_MEM_BYTE(ptr) (*(byte *)(ptr))
#define WRITE_MEM_WORD(ptr, data) (*(word *)(ptr) = SWAPIT_32(data))
#define WRITE_MEM_HALFWORD(ptr, data) (*(halfword *)(ptr) = SWAPIT_16(data))
#define WRITE_MEM_BYTE(ptr, data) (*(byte *)(ptr) = (data))
#endif
#endif

41
lk/include/err.h Normal file
View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __ERR_H
#define __ERR_H
#define NO_ERROR 0
#define ERROR -1
#define ERR_NOT_FOUND -2
#define ERR_NOT_READY -3
#define ERR_NO_MSG -4
#define ERR_NO_MEMORY -5
#define ERR_ALREADY_STARTED -6
#define ERR_NOT_VALID -7
#define ERR_INVALID_ARGS -8
#define ERR_NOT_ENOUGH_BUFFER -9
#define ERR_NOT_SUSPENDED -10
#define ERR_OBJECT_DESTROYED -11
#define ERR_NOT_BLOCKED -12
#define ERR_TIMED_OUT -13
#endif

75
lk/include/hw/mii.h Normal file
View File

@ -0,0 +1,75 @@
/*
* Copyright (c) 2006 Brian Swetland
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __HW_MII_H
#define __HW_MII_H
#define MII_REG_BCR 0x00
#define MII_REG_BSR 0x01
#define MII_REG_PHY_ID1 0x02
#define MII_REG_PHY_ID2 0x03
#define MII_REG_AUTO_ADV 0x04
#define MII_REG_AUTO_LINK 0x05
#define MII_REG_AUTO_EXPN 0x06
#define MII_REG_AUTO_NEXT 0x07
#define MII_REG_LINK_NEXT 0x08
#define MII_REG_RXER_CNT 0x15
#define MII_REG_ICSR 0x1b
#define MII_REG_100TX_PHY 0x1f
#define MII_BCR_RESET 0x8000
#define MII_BCR_LOOPBACK 0x4000
#define MII_BCR_100MBPS 0x2000
#define MII_BCR_AUTO_ENABLE 0x1000
#define MII_BCR_PWR_DOWN 0x0800
#define MII_BCR_ISOLATE 0x0400
#define MII_BCR_AUTO_RESTART 0x0200
#define MII_BCR_FULL_DUPLEX 0x0100
#define MII_BCR_COL_TEST 0x0080
#define MII_BCR_TX_DISABLE 0x0001
#define MII_BSR_T4 0x8000
#define MII_BSR_100TX_FULL 0x4000
#define MII_BSR_100TX_HALF 0x2000
#define MII_BSR_10T_FULL 0x1000
#define MII_BSR_10T_HALF 0x0800
#define MII_BSR_NO_PREAMBLE 0x0040
#define MII_BSR_AUTO_COMPLETE 0x0020
#define MII_BSR_REMOTE_FAULT 0x0010
#define MII_BSR_AUTO_ABLE 0x0008
#define MII_BSR_LINK_UP 0x0004
#define MII_BSR_JABBER 0x0002
#define MII_BSR_EXTEND 0x0001
#define MII_100TX_PHY_ISOLATE 0x0040
#define MII_100TX_MODE_MASK 0x001C
#define MII_100TX_MODE_AUTO 0x0000
#define MII_100TX_MODE_10T_H 0x0004
#define MII_100TX_MODE_100TX_H 0x0008
#define MII_100TX_MODE_10T_F 0x0014
#define MII_100TX_MODE_100TX_F 0x0018
#define MII_100TX_MODE_ISOLATE 0x001C
#define MII_100TX_SQE_TEST 0x0002
#define MII_100TX_NO_SCRAMBLE 0x0001
#endif

106
lk/include/hw/usb.h Normal file
View File

@ -0,0 +1,106 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __HW_USB_H
#define __HW_USB_H
#include <sys/types.h>
#include <compiler.h>
/* GLOBAL STATUS VALUES */
#define STD_COMMAND 0x00
#define SETUP_COMMAND_PHASE 0x40
#define FUNCTION_ERROR 0x7F /* Used when we are stalling the function EP0 */
#define HUB_ERROR 0xFF /* Used when we are stalling the HUB EP0 */
/* Request Types */
#define DIR_OUT (0 << 7)
#define DIR_IN (1 << 7)
#define DIR_MASK (1 << 7)
#define TYPE_STANDARD (0 << 5)
#define TYPE_CLASS (1 << 5)
#define TYPE_VENDOR (2 << 5)
#define TYPE_MASK (3 << 5)
#define RECIP_DEVICE (0 << 0)
#define RECIP_INTERFACE (1 << 0)
#define RECIP_ENDPOINT (2 << 0)
#define RECIP_OTHER (3 << 0)
#define RECIP_MASK (0x1f << 0)
/* 1.0 Request Values */
#define GET_STATUS 0x00
#define CLEAR_FEATURE 0x01
#define SET_FEATURE 0x03
#define SET_ADDRESS 0x05
#define GET_DESCRIPTOR 0x06
#define SET_DESCRIPTOR 0x07
#define GET_CONFIGURATION 0x08
#define SET_CONFIGURATION 0x09
#define GET_INTERFACE 0x0A
#define SET_INTERFACE 0x0B
#define SYNCH_FRAME 0x0C
/* Mass storage requests */
#define MASS_STORAGE_GET_MAX_LUN 0xfe
#define MASS_STORAGE_RESET 0xff
/* DFU requests */
#define DFU_DETACH 0x00
#define DFU_DNLOAD 0x01
#define DFU_UPLOAD 0x02
#define DFU_GETSTATUS 0x03
#define DFU_CLRSTATUS 0x04
#define DFU_GETSTATE 0x05
#define DFU_ABORT 0x06
/* HID Request Values */
#define GET_REPORT 0x01
#define GET_IDLE 0x02
#define GET_PROTOCOL 0x03
#define SET_REPORT 0x09
#define SET_IDLE 0x0A
#define SET_PROTOCOL 0x0B
/* Descriptor Types */
#define DEVICE 0x01
#define CONFIGURATION 0x02
#define STRING 0x03
#define INTERFACE 0x04
#define ENDPOINT 0x05
#define DEVICE_QUALIFIER 0x06
#define OTHER_SPEED_CONFIGURATION 0x07
#define INTERFACE_POWER 0x08
#define HID 0x21
#define HIDREPORT 0x22
#define HIDPHYSICAL 0x23
/* general USB defines */
struct usb_setup {
uint8_t request_type;
uint8_t request;
uint16_t value;
uint16_t index;
uint16_t length;
} __PACKED;
#endif

29
lk/include/inttypes.h Normal file
View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __INTTYPES_H
#define __INTTYPES_H
#include <stdint.h>
#endif

38
lk/include/kernel/dpc.h Normal file
View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __KERNEL_DPC_H
#define __KERNEL_DPC_H
#include <list.h>
#include <sys/types.h>
void dpc_init(void);
typedef void (*dpc_callback)(void *arg);
#define DPC_FLAG_NORESCHED 0x1
status_t dpc_queue(dpc_callback, void *arg, uint flags);
#endif

63
lk/include/kernel/event.h Normal file
View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __KERNEL_EVENT_H
#define __KERNEL_EVENT_H
#include <kernel/thread.h>
#define EVENT_MAGIC 'evnt'
typedef struct event {
int magic;
bool signalled;
uint flags;
wait_queue_t wait;
} event_t;
#define EVENT_FLAG_AUTOUNSIGNAL 1
/* Rules for Events:
* - Events may be signaled from interrupt context *but* the reschedule
* parameter must be false in that case.
* - Events may not be waited upon from interrupt context.
* - Events without FLAG_AUTOUNSIGNAL:
* - Wake up any waiting threads when signaled.
* - Continue to do so (no threads will wait) until unsignaled.
* - Events with FLAG_AUTOUNSIGNAL:
* - If one or more threads are waiting when signaled, one thread will
* be woken up and return. The signaled state will not be set.
* - If no threads are waiting when signaled, the Event will remain
* in the signaled state until a thread attempts to wait (at which
* time it will unsignal atomicly and return immediately) or
* event_unsignal() is called.
*/
void event_init(event_t *, bool initial, uint flags);
void event_destroy(event_t *);
status_t event_wait(event_t *);
status_t event_wait_timeout(event_t *, time_t); /* wait on the event with a timeout */
status_t event_signal(event_t *, bool reschedule);
status_t event_unsignal(event_t *);
#endif

49
lk/include/kernel/mutex.h Normal file
View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __KERNEL_MUTEX_H
#define __KERNEL_MUTEX_H
#include <kernel/thread.h>
#define MUTEX_MAGIC 'mutx'
typedef struct mutex {
int magic;
int count;
thread_t *holder;
wait_queue_t wait;
} mutex_t;
/* Rules for Mutexes:
* - Mutexes are only safe to use from thread context.
* - Mutexes are non-recursive.
*/
void mutex_init(mutex_t *);
void mutex_destroy(mutex_t *);
status_t mutex_acquire(mutex_t *);
status_t mutex_acquire_timeout(mutex_t *, time_t); /* try to acquire the mutex with a timeout value */
status_t mutex_release(mutex_t *);
#endif

227
lk/include/kernel/thread.h Normal file
View File

@ -0,0 +1,227 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __KERNEL_THREAD_H
#define __KERNEL_THREAD_H
#include <sys/types.h>
#include <list.h>
#include <compiler.h>
#include <arch/ops.h>
#include <arch/thread.h>
enum thread_state {
THREAD_SUSPENDED = 0,
THREAD_READY,
THREAD_RUNNING,
THREAD_BLOCKED,
THREAD_SLEEPING,
THREAD_DEATH,
};
typedef int (*thread_start_routine)(void *arg);
/* thread local storage */
enum thread_tls_list {
MAX_TLS_ENTRY
};
#define THREAD_MAGIC 'thrd'
typedef struct thread {
int magic;
struct list_node thread_list_node;
/* active bits */
struct list_node queue_node;
int priority;
enum thread_state state;
int saved_critical_section_count;
int remaining_quantum;
/* if blocked, a pointer to the wait queue */
struct wait_queue *blocking_wait_queue;
status_t wait_queue_block_ret;
/* architecture stuff */
struct arch_thread arch;
/* stack stuff */
void *stack;
size_t stack_size;
/* entry point */
thread_start_routine entry;
void *arg;
/* return code */
int retcode;
/* thread local storage */
uint32_t tls[MAX_TLS_ENTRY];
char name[32];
} thread_t;
/* thread priority */
#define NUM_PRIORITIES 32
#define LOWEST_PRIORITY 0
#define HIGHEST_PRIORITY (NUM_PRIORITIES - 1)
#define DPC_PRIORITY (NUM_PRIORITIES - 2)
#define IDLE_PRIORITY LOWEST_PRIORITY
#define LOW_PRIORITY (NUM_PRIORITIES / 4)
#define DEFAULT_PRIORITY (NUM_PRIORITIES / 2)
#define HIGH_PRIORITY ((NUM_PRIORITIES / 4) * 3)
/* stack size */
#define DEFAULT_STACK_SIZE 8192
/* functions */
void thread_init_early(void);
void thread_init(void);
void thread_become_idle(void) __NO_RETURN;
void thread_set_name(const char *name);
void thread_set_priority(int priority);
thread_t *thread_create(const char *name, thread_start_routine entry, void *arg, int priority, size_t stack_size);
status_t thread_resume(thread_t *);
void thread_exit(int retcode) __NO_RETURN;
void thread_sleep(time_t delay);
void dump_thread(thread_t *t);
void dump_all_threads(void);
/* scheduler routines */
void thread_yield(void); /* give up the cpu voluntarily */
void thread_preempt(void); /* get preempted (inserted into head of run queue) */
void thread_block(void); /* block on something and reschedule */
/* called on every timer tick for the scheduler to do quantum expiration */
enum handler_return thread_timer_tick(void);
/* the current thread */
extern thread_t *current_thread;
/* the idle thread */
extern thread_t *idle_thread;
/* critical sections */
extern int critical_section_count;
static inline __ALWAYS_INLINE void enter_critical_section(void)
{
critical_section_count++;
if (critical_section_count == 1)
arch_disable_ints();
}
static inline __ALWAYS_INLINE void exit_critical_section(void)
{
critical_section_count--;
if (critical_section_count == 0)
arch_enable_ints();
}
static inline __ALWAYS_INLINE bool in_critical_section(void)
{
return critical_section_count > 0;
}
/* only used by interrupt glue */
static inline void inc_critical_section(void) { critical_section_count++; }
static inline void dec_critical_section(void) { critical_section_count--; }
/* thread local storage */
static inline __ALWAYS_INLINE uint32_t tls_get(uint entry)
{
return current_thread->tls[entry];
}
static inline __ALWAYS_INLINE uint32_t tls_set(uint entry, uint32_t val)
{
uint32_t oldval = current_thread->tls[entry];
current_thread->tls[entry] = val;
return oldval;
}
/* wait queue stuff */
#define WAIT_QUEUE_MAGIC 'wait'
typedef struct wait_queue {
int magic;
struct list_node list;
int count;
} wait_queue_t;
/* wait queue primitive */
/* NOTE: must be inside critical section when using these */
void wait_queue_init(wait_queue_t *);
/*
* release all the threads on this wait queue with a return code of ERR_OBJECT_DESTROYED.
* the caller must assure that no other threads are operating on the wait queue during or
* after the call.
*/
void wait_queue_destroy(wait_queue_t *, bool reschedule);
/*
* block on a wait queue.
* return status is whatever the caller of wait_queue_wake_*() specifies.
* a timeout other than INFINITE_TIME will set abort after the specified time
* and return ERR_TIMED_OUT. a timeout of 0 will immediately return.
*/
status_t wait_queue_block(wait_queue_t *, time_t timeout);
/*
* release one or more threads from the wait queue.
* reschedule = should the system reschedule if any is released.
* wait_queue_error = what wait_queue_block() should return for the blocking thread.
*/
int wait_queue_wake_one(wait_queue_t *, bool reschedule, status_t wait_queue_error);
int wait_queue_wake_all(wait_queue_t *, bool reschedule, status_t wait_queue_error);
/*
* remove the thread from whatever wait queue it's in.
* return an error if the thread is not currently blocked (or is the current thread)
*/
status_t thread_unblock_from_wait_queue(thread_t *t, bool reschedule, status_t wait_queue_error);
/* thread level statistics */
#define THREAD_STATS 0
#if THREAD_STATS
struct thread_stats {
bigtime_t idle_time;
bigtime_t last_idle_timestamp;
int reschedules;
int context_switches;
int preempts;
int yields;
int interrupts; /* platform code increment this */
int timer_ints; /* timer code increment this */
int timers; /* timer code increment this */
};
extern struct thread_stats thread_stats;
#endif
#endif

59
lk/include/kernel/timer.h Normal file
View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __KERNEL_TIMER_H
#define __KERNEL_TIMER_H
#include <list.h>
#include <sys/types.h>
void timer_init(void);
struct timer;
typedef enum handler_return (*timer_callback)(struct timer *, time_t now, void *arg);
#define TIMER_MAGIC 'timr'
typedef struct timer {
int magic;
struct list_node node;
time_t scheduled_time;
time_t periodic_time;
timer_callback callback;
void *arg;
} timer_t;
/* Rules for Timers:
* - Timer callbacks occur from interrupt context
* - Timers may be programmed or canceled from interrupt or thread context
* - Timers may be canceled or reprogrammed from within their callback
* - Timers currently are dispatched from a 10ms periodic tick
*/
void timer_initialize(timer_t *);
void timer_set_oneshot(timer_t *, time_t delay, timer_callback, void *arg);
void timer_set_periodic(timer_t *, time_t period, timer_callback, void *arg);
void timer_cancel(timer_t *);
#endif

Some files were not shown because too many files have changed in this diff Show More