1.1: Initial commit
This commit is contained in:
parent
ea15405e85
commit
2e6545f612
BIN
bin/NBMerge.exe
Normal file
BIN
bin/NBMerge.exe
Normal file
Binary file not shown.
BIN
bin/osnbtool.exe
Normal file
BIN
bin/osnbtool.exe
Normal file
Binary file not shown.
BIN
bin/template_os.nb.payload
Normal file
BIN
bin/template_os.nb.payload
Normal file
Binary file not shown.
BIN
bin/yang.exe
Normal file
BIN
bin/yang.exe
Normal file
Binary file not shown.
55
compile
Normal file
55
compile
Normal 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
66
lk/AndroidBoot.mk
Normal 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
735
lk/app/aboot/aboot.c
Normal 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
97
lk/app/aboot/bootimg.h
Normal 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
372
lk/app/aboot/fastboot.c
Normal 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
50
lk/app/aboot/fastboot.h
Normal 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
277
lk/app/aboot/recovery.c
Normal 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
77
lk/app/aboot/recovery.h
Normal 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
7
lk/app/aboot/rules.mk
Normal 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
66
lk/app/app.c
Normal 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));
|
||||
}
|
||||
|
99
lk/app/nandwrite/bootimg.h
Normal file
99
lk/app/nandwrite/bootimg.h
Normal 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
|
||||
|
220
lk/app/nandwrite/nandwrite.c
Normal file
220
lk/app/nandwrite/nandwrite.c
Normal 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);
|
||||
}
|
||||
|
||||
|
6
lk/app/nandwrite/rules.mk
Normal file
6
lk/app/nandwrite/rules.mk
Normal file
@ -0,0 +1,6 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
OBJS += \
|
||||
$(LOCAL_DIR)/nandwrite.o \
|
||||
|
||||
|
5
lk/app/rules.mk
Normal file
5
lk/app/rules.mk
Normal file
@ -0,0 +1,5 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
OBJS += \
|
||||
$(LOCAL_DIR)/app.o
|
||||
|
7
lk/app/shell/rules.mk
Normal file
7
lk/app/shell/rules.mk
Normal 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
41
lk/app/shell/shell.c
Normal 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
|
||||
|
169
lk/app/stringtests/mymemcpy.S
Normal file
169
lk/app/stringtests/mymemcpy.S
Normal 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
|
||||
|
109
lk/app/stringtests/mymemset.S
Normal file
109
lk/app/stringtests/mymemset.S
Normal 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
|
||||
|
6
lk/app/stringtests/rules.mk
Normal file
6
lk/app/stringtests/rules.mk
Normal file
@ -0,0 +1,6 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
OBJS += \
|
||||
$(LOCAL_DIR)/string_tests.o \
|
||||
$(LOCAL_DIR)/mymemcpy.o \
|
||||
$(LOCAL_DIR)/mymemset.o
|
249
lk/app/stringtests/string_tests.c
Normal file
249
lk/app/stringtests/string_tests.c
Normal 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
|
||||
|
30
lk/app/tests/include/app/tests.h
Normal file
30
lk/app/tests/include/app/tests.h
Normal 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
|
||||
|
90
lk/app/tests/printf_tests.c
Normal file
90
lk/app/tests/printf_tests.c
Normal 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
8
lk/app/tests/rules.mk
Normal 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
46
lk/app/tests/tests.c
Normal 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
322
lk/app/tests/thread_tests.c
Normal 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
72
lk/arch/arm/arch.c
Normal 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
103
lk/arch/arm/asm.S
Normal 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
366
lk/arch/arm/cache-ops.S
Normal 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
22
lk/arch/arm/cache.c
Normal 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
33
lk/arch/arm/compile.mk
Normal 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
175
lk/arch/arm/crt0.S
Normal 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
41
lk/arch/arm/dcc.S
Normal 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
132
lk/arch/arm/exceptions.S
Normal 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
91
lk/arch/arm/faults.c
Normal 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(®s);
|
||||
|
||||
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");
|
||||
}
|
31
lk/arch/arm/include/arch/arch_thread.h
Normal file
31
lk/arch/arm/include/arch/arch_thread.h
Normal 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
|
||||
|
94
lk/arch/arm/include/arch/arm.h
Normal file
94
lk/arch/arm/include/arch/arm.h
Normal 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
|
122
lk/arch/arm/include/arch/arm/cores.h
Normal file
122
lk/arch/arm/include/arch/arm/cores.h
Normal 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
|
||||
|
33
lk/arch/arm/include/arch/arm/dcc.h
Normal file
33
lk/arch/arm/include/arch/arm/dcc.h
Normal 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
|
44
lk/arch/arm/include/arch/arm/mmu.h
Normal file
44
lk/arch/arm/include/arch/arm/mmu.h
Normal 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
|
48
lk/arch/arm/include/arch/arm/ops.h
Normal file
48
lk/arch/arm/include/arch/arm/ops.h
Normal 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
|
||||
|
43
lk/arch/arm/include/arch/defines.h
Normal file
43
lk/arch/arm/include/arch/defines.h
Normal 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
100
lk/arch/arm/mmu.c
Normal 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
213
lk/arch/arm/ops.S
Normal 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
142
lk/arch/arm/rules.mk
Normal 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)/" < $< > $@
|
||||
|
82
lk/arch/arm/system-onesegment.ld
Normal file
82
lk/arch/arm/system-onesegment.ld
Normal 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) }
|
||||
}
|
85
lk/arch/arm/system-twosegment.ld
Normal file
85
lk/arch/arm/system-twosegment.ld
Normal 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
88
lk/arch/arm/thread.c
Normal 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
28
lk/dev/dev.c
Normal 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
245
lk/dev/fbcon/fbcon.c
Normal 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
126
lk/dev/fbcon/font5x12.h
Normal 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
5
lk/dev/fbcon/rules.mk
Normal file
@ -0,0 +1,5 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
OBJS += \
|
||||
$(LOCAL_DIR)/fbcon.o
|
||||
|
618
lk/dev/keys/gpio_keypad.c
Normal file
618
lk/dev/keys/gpio_keypad.c
Normal 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
67
lk/dev/keys/keys.c
Normal 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
10
lk/dev/keys/rules.mk
Normal 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
|
||||
|
29
lk/dev/net/smc91c96/include/dev/net/smc91c96.h
Normal file
29
lk/dev/net/smc91c96/include/dev/net/smc91c96.h
Normal 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
|
||||
|
8
lk/dev/net/smc91c96/rules.mk
Normal file
8
lk/dev/net/smc91c96/rules.mk
Normal file
@ -0,0 +1,8 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
INCLUDES += \
|
||||
-I$(LOCAL_DIR)/include
|
||||
|
||||
OBJS += \
|
||||
$(LOCAL_DIR)/smc91c96.o
|
||||
|
70
lk/dev/net/smc91c96/smc91c96.c
Normal file
70
lk/dev/net/smc91c96/smc91c96.c
Normal 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);
|
||||
}
|
||||
|
80
lk/dev/net/smc91c96/smc91c96_p.h
Normal file
80
lk/dev/net/smc91c96/smc91c96_p.h
Normal 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
|
||||
|
36
lk/dev/pmic/twl4030/include/dev/twl4030.h
Normal file
36
lk/dev/pmic/twl4030/include/dev/twl4030.h
Normal 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
|
||||
|
7
lk/dev/pmic/twl4030/rules.mk
Normal file
7
lk/dev/pmic/twl4030/rules.mk
Normal file
@ -0,0 +1,7 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
INCLUDES += -I$(LOCAL_DIR)/include
|
||||
|
||||
OBJS += \
|
||||
$(LOCAL_DIR)/twl4030.o
|
||||
|
169
lk/dev/pmic/twl4030/twl4030.c
Normal file
169
lk/dev/pmic/twl4030/twl4030.c
Normal 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;
|
||||
}
|
||||
|
||||
|
369
lk/dev/pmic/twl4030/twl4030_hw.h
Normal file
369
lk/dev/pmic/twl4030/twl4030_hw.h
Normal 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
5
lk/dev/rules.mk
Normal file
@ -0,0 +1,5 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
OBJS += \
|
||||
$(LOCAL_DIR)/dev.o
|
||||
|
5
lk/dev/usb/rules.mk
Normal file
5
lk/dev/usb/rules.mk
Normal file
@ -0,0 +1,5 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
OBJS += \
|
||||
$(LOCAL_DIR)/usb.o
|
||||
|
307
lk/dev/usb/usb.c
Normal file
307
lk/dev/usb/usb.c
Normal 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
49
lk/include/app.h
Normal 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
37
lk/include/arch.h
Normal 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
71
lk/include/arch/ops.h
Normal 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
34
lk/include/arch/thread.h
Normal 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
30
lk/include/asm.h
Normal 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
40
lk/include/assert.h
Normal 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
59
lk/include/bits.h
Normal 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
109
lk/include/compiler.h
Normal 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
43
lk/include/ctype.h
Normal 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
95
lk/include/debug.h
Normal 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
38
lk/include/dev/ethernet.h
Normal 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
54
lk/include/dev/fbcon.h
Normal 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
67
lk/include/dev/flash.h
Normal 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
51
lk/include/dev/gpio.h
Normal 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
|
248
lk/include/dev/gpio_keypad.h
Normal file
248
lk/include/dev/gpio_keypad.h
Normal 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
39
lk/include/dev/i2c.h
Normal 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
91
lk/include/dev/keys.h
Normal 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
38
lk/include/dev/uart.h
Normal 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
120
lk/include/dev/udc.h
Normal 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
65
lk/include/dev/usb.h
Normal 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
98
lk/include/dev/usbc.h
Normal 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
95
lk/include/endian.h
Normal 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
41
lk/include/err.h
Normal 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
75
lk/include/hw/mii.h
Normal 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
106
lk/include/hw/usb.h
Normal 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
29
lk/include/inttypes.h
Normal 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
38
lk/include/kernel/dpc.h
Normal 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
63
lk/include/kernel/event.h
Normal 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
49
lk/include/kernel/mutex.h
Normal 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
227
lk/include/kernel/thread.h
Normal 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
59
lk/include/kernel/timer.h
Normal 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
Loading…
x
Reference in New Issue
Block a user