Compare commits

...

7 Commits

Author SHA1 Message Date
e7f332764b 1.3.3: small fix on get_boot_reason 2011-11-07 00:04:57 +00:00
6092922424 1.3.2: updated
* ROMHDR base addr is spl virtual 0x80000000 = 11800000 physical, LK will relocate to correct address (MEMBASE)
* save reboot reason at 0x2FFB0000 (ramconsole - 0x1000 (PAGE_SIZE)) and @0x2FFB0004 XOR 0x004b4c63 (cLK signature)
* added oem cmd to fastboot and oemcmd.bat for PC
2011-11-07 00:03:59 +00:00
cb8df35955 1.3.1: updated
* sharp display fix
* added patches
2011-11-07 00:01:51 +00:00
fc88e6ffb9 1.3: update to latest
* - removed other targets from source
- removed tinboot like wrapper, now romhdr is in crt0
- power collapse fix
- off charge support.
- misc partition check removed
2011-11-06 23:50:25 +00:00
72ee75a82d 1.2: updated 2011-11-06 23:48:03 +00:00
2e6545f612 1.1: Initial commit 2011-11-06 23:26:22 +00:00
ea15405e85 1.1: Initial commit 2011-11-06 23:25:14 +00:00
178 changed files with 15793 additions and 526 deletions

@ -1,28 +0,0 @@
export VERSION=1.4.0.1
export TOOLCHAIN_PREFIX=arm-none-eabi-
default: bin/RUU_signed.nbh
clean:
$(MAKE) -C lk htcleo clean
rm -rf lk/build-htcleo
rm -rf bin/nbgen
rm -rf bin/lk.bin
rm -rf bin/os.nb.payload
rm -rf bin/os.nb
rm -rf bin/RUU_signed.nbh
bin/nbgen:
gcc -std=c99 nbgen.c -o bin/nbgen
bin/RUU_signed.nbh: bin/nbgen
$(MAKE) -C lk htcleo DEBUG=1
cp lk/build-htcleo/lk.bin bin/
cd bin ; ./nbgen os.nb
cd bin ; ./yang -F RUU_signed.nbh -f os.nb -t 0x400 -s 64 -d PB8110000 -c 11111111 -v CLK$(VERSION) -l WWE
partition:
rm -rf lk/build-htcleo/target/htcleo/init.*
rm -rf bin/RUU_signed.nbh
$(MAKE)

93
README

@ -1,93 +0,0 @@
=================
cLK by cedesmith
=================
URL: http://forum.xda-developers.com/showthread.php?t=901305
1. Disclaimer
2. FAQ
3. How To
3.1. Flash cLK
3.2. Compiling cLK
4. Known Issues
5. Credits
================
1. DISCLAIMER
================
This comes with no warranties, if you use it you do it on your own risk.
Please read carefully the flowing information and make sure you know what you are doing.
I don't have time or patience for questions and support. If you use it you are on your own (well and this community).
================
2. FAQ
================
Q&A
Q: What it is ?
A: A bootloader for android like magldr.
Q: Is it better then magldr ?
A1: NO, it is missing tetris .
A2: NO, magldr has some nice features like partitioning and rmnet.
Q: Can i use last 24MB of nand with this?
A: NO, SPL will erase them. When i have some time i may try to fix it.
Q: Does battery charge with this ?
A: YES, from version 1.3
Q: Does it boot WP7?
A: NO. I am only interested in android but in can load and execute any program.
Q: Should i install it ?
A: If you had to ask probably not. If has no functional benefits over magldr.
=================
3. How To
=================
3.1 Flash cLK
--------------
- make sure you have hspl
- enter SPL by holding VOL DOWN key while powering/resting the phone.
- flash with customruu like you would a windows rom and/or magldr
Flash a ROM
- download android sdk (or rather, just adb, drivers and fastboot)
- fastboot flash recovery recovery.img
- after recovery you can reboot and use CWM or you can flash with fastboot
(fastboot flash boot boot.img, fastboot flash system system.img, fastboot flash userdata userdata.img)
Start recovery / fastboot / text console
- holding down any key ( except power ) will show text console
- home key will enter recovery ( if flashed )
- back key will enter fastboot mode
The following URL has a fantastic howto by stirkac
http://forum.xda-developers.com/showpost.php?p=12327648&postcount=844
3.2 Compiling cLK
-----------------
Linux: http://forum.xda-developers.com/showpost.php?p=12461912&postcount=934
Windows: http://forum.xda-developers.com/showpost.php?p=12461551&postcount=932
=================
4. Known issues
=================
RMNET does not work.
=================
5. Credits
=================
- cedesmith for make LK available for the HD2
- codeaurrora for making LK and for making it open
- Martin Johnson for his tinboot witch was a great inspiration
- Martijn Stolk for his kernel segfault solving code and and cotulla for pointing it and his contribution to android on HD2
- all how worked on making linux kernel possible on hd2

BIN
bin/NBMerge.exe Normal file

Binary file not shown.

BIN
bin/dmesg_filter.exe Normal file

Binary file not shown.

BIN
bin/osnbtool.exe Normal file

Binary file not shown.

BIN
bin/template_os.nb.payload Normal file

Binary file not shown.

BIN
bin/yang

Binary file not shown.

BIN
bin/yang.exe Normal file

Binary file not shown.

Binary file not shown.

@ -1,19 +0,0 @@
cLK 1.4
---------
Built by arif-ali from xda-developers
using 2009q3 of Codesourcery Toolchain
misc 1M
recovery 5M
boot 8M
system 90M
cache 5M
userdata remaining
Thanks and credits
------------------
* cedesmith
* seadersn
- 27 Mar 2011

@ -1,8 +1,3 @@
1.4
- nbgen for making .nb file
1.3.3
- small fix on get_boot_reason
- cwm off charge fully implemented, inspired by dan1j3l's code (http://gitorious.org/htc-hd2-android-libraries/cmon/blobs/master/cmon.c)
1.3.2
- ROMHDR base addr is spl virtual 0x80000000 = 11800000 physical, LK will relocate to correct address (MEMBASE)
- save reboot reason at 0x2FFB0000 (ramconsole - 0x1000 (PAGE_SIZE)) and @0x2FFB0004 XOR 0x004b4c63 (cLK signature)

22
compile Executable file → Normal file

@ -1,13 +1,14 @@
#!/bin/bash
[ `which arm-none-eabi-gcc` ] && TOOLCHAIN_PREFIX="arm-none-eabi-" || TOOLCHAIN_PREFIX="arm-eabi-"
#use codesourcery toolchain
TOOLCHAIN_PREFIX="arm-none-eabi-"
export TOOLCHAIN_PREFIX
if [ "$1" = "clean" ]; then
cd lk
make htcleo clean
cd ..
rm bin/nbgen
rm bin/nbfix
fi
rm bin/lk.bin
@ -15,8 +16,10 @@ rm bin/os.nb.payload
rm bin/os.nb
rm bin/RUU_signed.nbh
if [ ! -f bin/nbgen ]; then
gcc -std=c99 nbgen.c -o bin/nbgen
if [ ! -f bin/nbfix ]; then
gcc nbfix.c -o bin/nbfix
fi
cd lk
@ -25,10 +28,15 @@ make htcleo DEBUG=1
cp build-htcleo/lk.bin ../bin/
cd ..
cd bin
chmod +x yang
./nbgen os.nb
./yang -F RUU_signed.nbh -f os.nb -t 0x400 -s 64 -d PB8110000 -c 11111111 -v CLK1.4 -l WWE
cp template_os.nb.payload os.nb.payload
wine osnbtool.exe -c os.nb.payload 0 lk.bin
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.3 -l WWE
cd ..

@ -1,41 +0,0 @@
#!/bin/bash
export ARM=$PWD/../../../toolchain/arm-2009q3/bin
export PATH=$ARM:$PATH
export VERSION=1.4.0.1
#export SIZES="`echo {80..150..10} {160..460..20} 250 350 450`"
export SIZES="`echo {80..450..10}`"
export CACHE="5 44"
export OUTPUT=$PWD/../cLK-out
export O_ALL=$OUTPUT/allInOne
export O_ZIP=$OUTPUT/zips
make clean
mkdir -p $O_ALL
mkdir -p $O_ZIP
rm -rf $O_ALL/{*.nbh,*.zip}
rm -rf $O_ZIP/*.zip
for cache in $CACHE
do
for size in $SIZES
do
sed -i s/DEFINES\ +=\ SYSTEM_PARTITION_SIZE=.*/DEFINES\ +=\ SYSTEM_PARTITION_SIZE=${size}/ lk/target/htcleo/rules.mk
sed -i s/DEFINES\ +=\ CACHE_PARTITION_SIZE=.*/DEFINES\ +=\ CACHE_PARTITION_SIZE=${cache}/ lk/target/htcleo/rules.mk
sed -i s/system\ .*/system\ ${size}M/ build-stuff/readme.txt
sed -i s/cache\ .*/cache\ ${cache}M/ build-stuff/readme.txt
make partition
pushd build-stuff
rm -rf $O_ZIP/cLK_${VERSION}_${size}_${cache}.zip
mv ../bin/RUU_signed.nbh .
zip -9Dr $O_ZIP/cLK_${VERSION}_${size}_${cache}.zip readme.txt CustomRUU.exe RUU_signed.nbh
cp RUU_signed.nbh $O_ALL/RUU_signed-${size}-${cache}.nbh
rm -rf RUU_signed.nbh
popd
done
done
pushd $O_ALL
rm -rf cLK_${VERSION}_layouts_arif.zip
zip -9Dr cLK_${VERSION}_layouts_arif.zip *.nbh
popd

24
dmesg_filter.c Normal file

@ -0,0 +1,24 @@
#include <stdio.h>
#include <string.h>
int main() {
char buff[0x40000];
char* ptr = buff;
while(!feof(stdin) && fgetc(stdin)!='\n');
while(!feof(stdin))
{
*ptr++=fgetc(stdin);*ptr=0;
if(ptr-buff>=5 && memcmp(ptr-5,"\nINFO",5)==0)
{
ptr[-5]=0;
if(ptr-buff>=6 && ptr[-6]=='\r' ) ptr[-6]=0;
printf("%s", buff);
ptr=buff;
}
}
printf("%s", buff);
}

4
gau_flash.cfg Normal file

@ -0,0 +1,4 @@
clk_recovery raw|ro 5M
clk_boot raw|ro 5M
system ya|boot|ro filesize system.bin
userdata ya|asize allsize

@ -46,7 +46,6 @@
#include "recovery.h"
#include "bootimg.h"
#include "fastboot.h"
#include "version.h"
#define EXPAND(NAME) #NAME
#define TARGET(NAME) EXPAND(NAME)
@ -293,11 +292,8 @@ unified_boot:
} else {
cmdline = DEFAULT_CMDLINE;
}
strcat(cmdline," clk=");
strcat(cmdline,cLK_version);
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(),
@ -388,9 +384,6 @@ continue_boot:
} else {
cmdline = DEFAULT_CMDLINE;
}
strcat(cmdline," clk=");
strcat(cmdline,cLK_version);
dprintf(INFO, "cmdline = '%s'\n", cmdline);
/* TODO: create/pass atags to kernel */
@ -653,8 +646,6 @@ void aboot_init(const struct app_descriptor *app)
/* 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_SOFT1) != 0)
try_flash_recovery = 1;
if (keys_get_state(KEY_BACK) != 0)
goto fastboot;
if (keys_get_state(KEY_CLEAR) != 0)

@ -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

@ -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);
}

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

@ -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

@ -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

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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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;
}

@ -1,7 +0,0 @@
#ifndef __VERSION_H
#define __VERSION_H
static const char *cLK_version = "1.4.0.1";
#endif

@ -0,0 +1,93 @@
/*
* 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 <stdarg.h>
#include <reg.h>
#include <printf.h>
#include <kernel/thread.h>
#include <platform/armemu/memmap.h>
#include <platform/debug.h>
void _dputc(char c)
{
*REG8(DEBUG_STDOUT) = c;
}
int dgetc(char *c)
{
int8_t result = (int8_t)*REG8(DEBUG_STDIN);
if (result == -1)
return -1;
*c = (char)result;
return 0;
}
void debug_dump_regs(void)
{
*REG32(DEBUG_REGDUMP) = 1;
}
void platform_halt(void)
{
*REG32(DEBUG_HALT) = 1;
for(;;);
}
void debug_dump_memory_bytes(void *mem, int len)
{
*REG32(DEBUG_MEMDUMPADDR) = (unsigned int)mem;
*REG32(DEBUG_MEMDUMPLEN) = len;
*REG32(DEBUG_MEMDUMP_BYTE) = 1;
}
void debug_dump_memory_halfwords(void *mem, int len)
{
len /= 2;
*REG32(DEBUG_MEMDUMPADDR) = (unsigned int)mem;
*REG32(DEBUG_MEMDUMPLEN) = len;
*REG32(DEBUG_MEMDUMP_HALFWORD) = 1;
}
void debug_dump_memory_words(void *mem, int len)
{
len /= 4;
*REG32(DEBUG_MEMDUMPADDR) = (unsigned int)mem;
*REG32(DEBUG_MEMDUMPLEN) = len;
*REG32(DEBUG_MEMDUMP_WORD) = 1;
}
void debug_set_trace_level(int trace_type, int level)
{
if(trace_type < 0 || trace_type >= 4)
return;
*REG32(DEBUG_SET_TRACELEVEL_CPU + trace_type * 4) = level;
}
uint32_t debug_cycle_count()
{
return *REG32(DEBUG_CYCLE_COUNT);
}

@ -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 __PLATFORM_ARMEMU_H
#define __PLATFORM_ARMEMU_H
#include <platform/armemu/memmap.h>
#endif

@ -0,0 +1,148 @@
/*
* Copyright (c) 2005-2006 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 __MEMMAP_H
#define __MEMMAP_H
#define MEMBANK_SIZE (4*1024*1024)
/* some helpful macros */
#define REG(x) ((volatile unsigned int *)(x))
#define REG_H(x) ((volatile unsigned short *)(x))
#define REG_B(x) ((volatile unsigned char *)(x))
/* memory map of our generic arm system */
// XXX make more dynamic
#define MAINMEM_BASE 0x0
#define MAINMEM_SIZE (MEMBANK_SIZE)
/* peripherals are all mapped here */
#define PERIPHERAL_BASE (0xf0000000)
/* system info */
#define SYSINFO_REGS_BASE (PERIPHERAL_BASE)
#define SYSINFO_REGS_SIZE MEMBANK_SIZE
#define SYSINFO_FEATURES (SYSINFO_REGS_BASE + 0)
#define SYSINFO_FEATURE_DISPLAY 0x00000001
#define SYSINFO_FEATURE_CONSOLE 0x00000002
#define SYSINFO_FEATURE_NETWORK 0x00000004
/* a write to this register latches the current emulator system time, so the next two regs can be read atomically */
#define SYSINFO_TIME_LATCH (SYSINFO_REGS_BASE + 4)
/* gettimeofday() style time values */
#define SYSINFO_TIME_SECS (SYSINFO_REGS_BASE + 8)
#define SYSINFO_TIME_USECS (SYSINFO_REGS_BASE + 12)
/* display */
#define DISPLAY_BASE (SYSINFO_REGS_BASE + SYSINFO_REGS_SIZE)
#define DISPLAY_SIZE MEMBANK_SIZE
#define DISPLAY_FRAMEBUFFER DISPLAY_BASE
#define DISPLAY_REGS_BASE (DISPLAY_BASE + DISPLAY_SIZE)
#define DISPLAY_REGS_SIZE MEMBANK_SIZE
/* no display regs for now */
/* console (keyboard controller */
#define CONSOLE_REGS_BASE (DISPLAY_REGS_BASE + DISPLAY_REGS_SIZE)
#define CONSOLE_REGS_SIZE MEMBANK_SIZE
#define KYBD_STAT (CONSOLE_REGS_BASE + 0)
#define KYBD_DATA (CONSOLE_REGS_BASE + 4)
/* programmable timer */
#define PIT_REGS_BASE (CONSOLE_REGS_BASE + CONSOLE_REGS_SIZE)
#define PIT_REGS_SIZE MEMBANK_SIZE
#define PIT_STATUS (PIT_REGS_BASE + 0) // status bit
#define PIT_CLEAR (PIT_REGS_BASE + 4) // a nonzero write clears any pending timer
#define PIT_CLEAR_INT (PIT_REGS_BASE + 8) // a nonzero write clears the pending interrupt
#define PIT_INTERVAL (PIT_REGS_BASE + 12) // set the countdown interval, and what the interval is reset to if periodic
#define PIT_START_ONESHOT (PIT_REGS_BASE + 16) // a nonzero write starts a oneshot countdown
#define PIT_START_PERIODIC (PIT_REGS_BASE + 20) // a nonzero write starts a periodic countdown
#define PIT_STATUS_ACTIVE 0x1
#define PIT_STATUS_INT_PEND 0x2
/* interrupt controller */
#define PIC_REGS_BASE (PIT_REGS_BASE + PIT_REGS_SIZE)
#define PIC_REGS_SIZE MEMBANK_SIZE
/* Current vector mask, read-only */
#define PIC_MASK (PIC_REGS_BASE + 0)
/* Mask any of the 32 interrupt vectors by writing a 1 in the appropriate bit */
#define PIC_MASK_LATCH (PIC_REGS_BASE + 4)
/* Unmask any of the 32 interrupt vectors by writing a 1 in the appropriate bit */
#define PIC_UNMASK_LATCH (PIC_REGS_BASE + 8)
/* each bit corresponds to the current status of the interrupt line */
#define PIC_STAT (PIC_REGS_BASE + 12)
/* one bit set for the highest priority non-masked active interrupt */
#define PIC_CURRENT_BIT (PIC_REGS_BASE + 16)
/* holds the current interrupt number of the highest priority non-masked active interrupt,
* or 0xffffffff if no interrupt is active
*/
#define PIC_CURRENT_NUM (PIC_REGS_BASE + 20)
/* interrupt map */
#define INT_PIT 0
#define INT_KEYBOARD 1
#define INT_NET 2
#define PIC_MAX_INT 32
/* debug interface */
#define DEBUG_REGS_BASE (PIC_REGS_BASE + PIC_REGS_SIZE)
#define DEBUG_REGS_SIZE MEMBANK_SIZE
#define DEBUG_STDOUT (DEBUG_REGS_BASE + 0) /* writes to this register are sent through to stdout */
#define DEBUG_STDIN (DEBUG_REGS_BASE + 0) /* reads from this register return the contents of stdin
* or -1 if no data is pending */
#define DEBUG_REGDUMP (DEBUG_REGS_BASE + 4) /* writes to this register cause the emulator to dump registers */
#define DEBUG_HALT (DEBUG_REGS_BASE + 8) /* writes to this register will halt the emulator */
#define DEBUG_MEMDUMPADDR (DEBUG_REGS_BASE + 12) /* set the base address of memory to dump */
#define DEBUG_MEMDUMPLEN (DEBUG_REGS_BASE + 16) /* set the length of memory to dump */
#define DEBUG_MEMDUMP_BYTE (DEBUG_REGS_BASE + 20) /* trigger a memory dump in byte format */
#define DEBUG_MEMDUMP_HALFWORD (DEBUG_REGS_BASE + 24) /* trigger a memory dump in halfword format */
#define DEBUG_MEMDUMP_WORD (DEBUG_REGS_BASE + 28) /* trigger a memory dump in word format */
/* lets you set the trace level of the various subsystems from within the emulator */
/* only works on emulator builds that support dynamic trace levels */
#define DEBUG_SET_TRACELEVEL_CPU (DEBUG_REGS_BASE + 32)
#define DEBUG_SET_TRACELEVEL_UOP (DEBUG_REGS_BASE + 36)
#define DEBUG_SET_TRACELEVEL_SYS (DEBUG_REGS_BASE + 40)
#define DEBUG_SET_TRACELEVEL_MMU (DEBUG_REGS_BASE + 44)
#define DEBUG_CYCLE_COUNT (DEBUG_REGS_BASE + 48)
#define DEBUG_INS_COUNT (DEBUG_REGS_BASE + 52)
/* network interface */
#define NET_REGS_BASE (DEBUG_REGS_BASE + DEBUG_REGS_SIZE)
#define NET_REGS_SIZE MEMBANK_SIZE
#define NET_BUF_LEN 2048
#define NET_IN_BUF_COUNT 32
#define NET_HEAD (NET_REGS_BASE + 0) /* current next buffer the hardware will write to */
#define NET_TAIL (NET_REGS_BASE + 4) /* currently selected input buffer */
#define NET_SEND (NET_REGS_BASE + 8) /* writes to this register sends whatever is in the out buf */
#define NET_SEND_LEN (NET_REGS_BASE + 12) /* length of packet to send */
#define NET_OUT_BUF (NET_REGS_BASE + NET_BUF_LEN)
#define NET_IN_BUF_LEN (NET_REGS_BASE + 16) /* length of the currently selected in buffer, via tail register */
#define NET_IN_BUF (NET_REGS_BASE + NET_BUF_LEN*2)
#endif

@ -0,0 +1,117 @@
/*
* 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 <err.h>
#include <sys/types.h>
#include <debug.h>
#include <reg.h>
#include <kernel/thread.h>
#include <platform/interrupts.h>
#include <platform/armemu.h>
#include <arch/ops.h>
#include <arch/arm.h>
#include "platform_p.h"
struct int_handler_struct {
int_handler handler;
void *arg;
};
static struct int_handler_struct int_handler_table[PIC_MAX_INT];
void platform_init_interrupts(void)
{
// mask all the interrupts
*REG32(PIC_MASK_LATCH) = 0xffffffff;
}
status_t mask_interrupt(unsigned int vector)
{
if (vector >= PIC_MAX_INT)
return ERR_INVALID_ARGS;
// dprintf("%s: vector %d\n", __PRETTY_FUNCTION__, vector);
enter_critical_section();
*REG32(PIC_MASK_LATCH) = 1 << vector;
exit_critical_section();
return NO_ERROR;
}
status_t unmask_interrupt(unsigned int vector)
{
if (vector >= PIC_MAX_INT)
return ERR_INVALID_ARGS;
// dprintf("%s: vector %d\n", __PRETTY_FUNCTION__, vector);
enter_critical_section();
*REG32(PIC_UNMASK_LATCH) = 1 << vector;
exit_critical_section();
return NO_ERROR;
}
enum handler_return platform_irq(struct arm_iframe *frame)
{
// get the current vector
unsigned int vector = *REG32(PIC_CURRENT_NUM);
if (vector == 0xffffffff)
return INT_NO_RESCHEDULE;
// dprintf("platform_irq: spsr 0x%x, pc 0x%x, currthread %p, vector %d\n", frame->spsr, frame->pc, current_thread, vector);
// deliver the interrupt
enum handler_return ret;
ret = INT_NO_RESCHEDULE;
if (int_handler_table[vector].handler)
ret = int_handler_table[vector].handler(int_handler_table[vector].arg);
// dprintf("platform_irq: exit %d\n", ret);
return ret;
}
void platform_fiq(struct arm_iframe *frame)
{
panic("FIQ: unimplemented\n");
}
void register_int_handler(unsigned int vector, int_handler handler, void *arg)
{
if (vector >= PIC_MAX_INT)
panic("register_int_handler: vector out of range %d\n", vector);
enter_critical_section();
int_handler_table[vector].handler = handler;
int_handler_table[vector].arg = arg;
exit_critical_section();
}

398
lk/platform/armemu/net.c Normal file

@ -0,0 +1,398 @@
#if WITH_LWIP
/*
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. 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.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
/*
* This file is a skeleton for developing Ethernet network interface
* drivers for lwIP. Add code to the low_level functions and do a
* search-and-replace for the word "ethernetif" to replace it with
* something that better describes your network interface.
*/
/*
* ARMEMU bits
* Copyright (c) 2006 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 <malloc.h>
#include <dev/ethernet.h>
#include <err.h>
#include <reg.h>
#include <string.h>
#include <platform/interrupts.h>
#include <platform/armemu/memmap.h>
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/sys.h"
#include <lwip/stats.h>
#include "netif/etharp.h"
/* Define those to better describe your network interface. */
#define IFNAME0 'e'
#define IFNAME1 'n'
struct ethernetif {
struct eth_addr *ethaddr;
/* Add whatever per-interface state that is needed here. */
};
static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
/* Forward declarations. */
static void ethernetif_input(struct netif *netif);
static err_t ethernetif_output(struct netif *netif, struct pbuf *p,
struct ip_addr *ipaddr);
static void
low_level_init(struct netif *netif)
{
struct ethernetif *ethernetif = netif->state;
/* set MAC hardware address length */
netif->hwaddr_len = 6;
/* set MAC hardware address */
netif->hwaddr[0] = 0;
netif->hwaddr[1] = 0x01;
netif->hwaddr[2] = 0x02;
netif->hwaddr[3] = 0x03;
netif->hwaddr[4] = 0x04;
netif->hwaddr[5] = 0x05;
/* maximum transfer unit */
netif->mtu = 1500;
/* broadcast capability */
netif->flags = NETIF_FLAG_BROADCAST;
/* Do whatever else is needed to initialize interface. */
}
/*
* low_level_output():
*
* Should do the actual transmission of the packet. The packet is
* contained in the pbuf that is passed to the function. This pbuf
* might be chained.
*
*/
static err_t
low_level_output(struct netif *netif, struct pbuf *p)
{
struct ethernetif *ethernetif = netif->state;
struct pbuf *q;
int i;
int j;
#if ETH_PAD_SIZE
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
#endif
/* XXX maybe just a mutex? */
enter_critical_section();
i = 0;
for(q = p; q != NULL; q = q->next) {
/* Send the data from the pbuf to the interface, one pbuf at a
time. The size of the data in each pbuf is kept in the ->len
variable. */
// debug_dump_memory_bytes(q->payload, q->len);
for (j = 0; j < q->len; j++)
*REG8(NET_OUT_BUF + i + j) = ((unsigned char *)q->payload)[j];
i += q->len;
}
*REG(NET_SEND_LEN) = i;
*REG(NET_SEND) = 1;
exit_critical_section();
#if ETH_PAD_SIZE
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
#if LINK_STATS
lwip_stats.link.xmit++;
#endif /* LINK_STATS */
return ERR_OK;
}
/*
* low_level_input():
*
* Should allocate a pbuf and transfer the bytes of the incoming
* packet from the interface into the pbuf.
*
*/
static struct pbuf *
low_level_input(struct netif *netif)
{
struct ethernetif *ethernetif = netif->state;
struct pbuf *p, *q;
u16_t len;
int i;
int head, tail;
/* get the head and tail pointers from the ethernet interface */
head = *REG(NET_HEAD);
tail = *REG(NET_TAIL);
if (tail == head)
return NULL; // false alarm
/* Obtain the size of the packet and put it into the "len"
variable. */
len = *REG(NET_IN_BUF_LEN);
#if ETH_PAD_SIZE
len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
#endif
/* We allocate a pbuf chain of pbufs from the pool. */
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
if (p != NULL) {
#if ETH_PAD_SIZE
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
#endif
/* We iterate over the pbuf chain until we have read the entire
* packet into the pbuf. */
int pos = 0;
for(q = p; q != NULL; q = q->next) {
/* Read enough bytes to fill this pbuf in the chain. The
* available data in the pbuf is given by the q->len
* variable. */
for (i=0; i < q->len; i++) {
((unsigned char *)q->payload)[i] = *REG8(NET_IN_BUF + pos);
pos++;
}
}
#if ETH_PAD_SIZE
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
#if LINK_STATS
lwip_stats.link.recv++;
#endif /* LINK_STATS */
} else {
#if LINK_STATS
lwip_stats.link.memerr++;
lwip_stats.link.drop++;
#endif /* LINK_STATS */
}
/* push the tail pointer up by one, giving the buffer back to the hardware */
*REG(NET_TAIL) = (tail + 1) % NET_IN_BUF_COUNT;
return p;
}
/*
* ethernetif_output():
*
* This function is called by the TCP/IP stack when an IP packet
* should be sent. It calls the function called low_level_output() to
* do the actual transmission of the packet.
*
*/
static err_t
ethernetif_output(struct netif *netif, struct pbuf *p,
struct ip_addr *ipaddr)
{
// dprintf("ethernetif_output: netif %p, pbuf %p, ipaddr %p\n", netif, p, ipaddr);
/* resolve hardware address, then send (or queue) packet */
return etharp_output(netif, ipaddr, p);
}
/*
* ethernetif_input():
*
* This function should be called when a packet is ready to be read
* from the interface. It uses the function low_level_input() that
* should handle the actual reception of bytes from the network
* interface.
*
*/
static void
ethernetif_input(struct netif *netif)
{
struct ethernetif *ethernetif;
struct eth_hdr *ethhdr;
struct pbuf *p;
ethernetif = netif->state;
/* move received packet into a new pbuf */
p = low_level_input(netif);
/* no packet could be read, silently ignore this */
if (p == NULL) return;
/* points to packet payload, which starts with an Ethernet header */
ethhdr = p->payload;
#if LINK_STATS
lwip_stats.link.recv++;
#endif /* LINK_STATS */
ethhdr = p->payload;
// dprintf("ethernetif_input: type 0x%x\n", htons(ethhdr->type));
switch (htons(ethhdr->type)) {
/* IP packet? */
case ETHTYPE_IP:
/* update ARP table */
etharp_ip_input(netif, p);
/* skip Ethernet header */
pbuf_header(p, -sizeof(struct eth_hdr));
/* pass to network layer */
netif->input(p, netif);
break;
case ETHTYPE_ARP:
/* pass p to ARP module */
etharp_arp_input(netif, ethernetif->ethaddr, p);
break;
default:
pbuf_free(p);
p = NULL;
break;
}
}
static enum handler_return ethernet_int(void *arg)
{
struct netif *netif = (struct netif *)arg;
ethernetif_input(netif);
return INT_RESCHEDULE;
}
/*
* ethernetif_init():
*
* Should be called at the beginning of the program to set up the
* network interface. It calls the function low_level_init() to do the
* actual setup of the hardware.
*
*/
static err_t
ethernetif_init(struct netif *netif)
{
struct ethernetif *ethernetif;
ethernetif = mem_malloc(sizeof(struct ethernetif));
if (ethernetif == NULL)
{
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
return ERR_MEM;
}
netif->state = ethernetif;
netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;
netif->output = ethernetif_output;
netif->linkoutput = low_level_output;
ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
low_level_init(netif);
return ERR_OK;
}
status_t ethernet_init(void)
{
/* check to see if the ethernet feature is turned on */
if ((*REG(SYSINFO_FEATURES) & SYSINFO_FEATURE_NETWORK) == 0)
return ERR_NOT_FOUND;
struct netif *netif = calloc(sizeof(struct netif), 1);
struct ip_addr *ipaddr = calloc(sizeof(struct ip_addr), 1);
struct ip_addr *netmask = calloc(sizeof(struct ip_addr), 1);
struct ip_addr *gw = calloc(sizeof(struct ip_addr), 1);
struct netif *netifret = netif_add(netif, ipaddr, netmask, gw, NULL, &ethernetif_init, &ip_input);
if (netifret == NULL) {
free(netif);
free(ipaddr);
free(netmask);
free(gw);
return ERR_NOT_FOUND;
}
/* register for interrupt handlers */
register_int_handler(INT_NET, ethernet_int, netif);
netif_set_default(netif);
unmask_interrupt(INT_NET, NULL);
return NO_ERROR;
}
#endif // WITH_LWIP

@ -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.
*/
#include <err.h>
#include <debug.h>
#include <platform.h>
#include "platform_p.h"
void platform_init_mmu_mappings(void)
{
}
void platform_early_init(void)
{
/* initialize the interrupt controller */
platform_init_interrupts();
/* initialize the timer block */
platform_init_timer();
}
void platform_init(void)
{
}

@ -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 __PLATFORM_P_H
#define __PLATFORM_P_H
void platform_init_interrupts(void);
void platform_init_timer(void);
#endif

@ -0,0 +1,28 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
ARCH := arm
ARM_CPU := arm926ej-s
CPU := generic
# emulater doesn't support thumb properly
ENABLE_THUMB := false
INCLUDES += \
-I$(LOCAL_DIR)/include
OBJS += \
$(LOCAL_DIR)/debug.o \
$(LOCAL_DIR)/interrupts.o \
$(LOCAL_DIR)/platform.o \
$(LOCAL_DIR)/timer.o \
# $(LOCAL_DIR)/console.o \
$(LOCAL_DIR)/net.o \
MEMBASE := 0x0
MEMSIZE := 0x400000 # 4MB
LINKER_SCRIPT += \
$(BUILDDIR)/system-onesegment.ld

@ -0,0 +1,75 @@
/*
* 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 <err.h>
#include <kernel/thread.h>
#include <platform.h>
#include <platform/interrupts.h>
#include <platform/timer.h>
#include <platform/armemu.h>
#include "platform_p.h"
static platform_timer_callback t_callback;
status_t platform_set_periodic_timer(platform_timer_callback callback, void *arg, time_t interval)
{
enter_critical_section();
t_callback = callback;
*REG(PIT_CLEAR) = 1;
*REG(PIT_INTERVAL) = interval;
*REG(PIT_START_PERIODIC) = 1;
unmask_interrupt(INT_PIT);
exit_critical_section();
return NO_ERROR;
}
time_t current_time(void)
{
time_t time;
*REG(SYSINFO_TIME_LATCH) = 1;
time = *REG(SYSINFO_TIME_SECS) * 1000;
time += *REG(SYSINFO_TIME_USECS) / 1000;
return time;
}
static enum handler_return platform_tick(void *arg)
{
*REG(PIT_CLEAR_INT) = 1;
if (t_callback) {
return t_callback(arg, current_time());
} else {
return INT_NO_RESCHEDULE;
}
}
void platform_init_timer(void)
{
register_int_handler(INT_PIT, &platform_tick, NULL);
}

@ -0,0 +1,15 @@
Platform support for the ATMEL AT91SAM7[XS] ARM7 microcontrollers.
This is a base platform -- it needs to be specialized for a particular
board (see sam7ex256 as an example of this) to be useful. In particular
it does not provide the platform/board.h (which must include the
correct at91sam7*h file and mux config).
TODO:
- support clock rates other than (and above) 18MHz
- compute uart divisor, PIT interval, etc from MCK
- timer hook should honor the requested interval
- current_time() should return a meaningful value
- actually pass argument to interrupt handlers?

@ -0,0 +1,32 @@
PA0 PWM0 TIOA0
PA1 PWM1 TIOB0
PA2 PWM2 SCK0
PA3 TWD NPCS3
PA4 TWCK TCLK0
PA5 RXD0 NPCS3
PA6 TXD0 PCK0
PA7 RTS0 PWM3
PA8 CTS0 ADTRG
PA9 DRXD NPCS1
PA10 DTXD NPCS2
PA11 NPCS0 PWM0
PA12 MISO PWM1
PA13 MOSI PWM2
PA14 SPCK PWM3
PA15 TF TIOA1
PA16 TK TIOB1
PA17 TD PCK1
PA18 RD PCK2
PA19 RK FIQ
PA20 RF IRQ0
PA21 RXD1 PCK1
PA22 TXD1 NPCS3
PA23 SCK1 PWM0
PA24 RTS1 PWM1
PA25 CTS1 PWM2
PA26 DCD1 TIOA2
PA27 DTR1 TIOB2
PA28 DSR1 TCLK1
PA29 RI1 TCLK2
PA30 IRQ1 NPCS2
PA31 NPCS1 PCK2

@ -0,0 +1,31 @@
PA0 RXD0 NC
PA1 TXD0 NC
PA2 SCK0 SPI1_NPCS1
PA3 RTS0 SPI1_NPCS2
PA4 CTS0 SPI1_NPCS3
PA5 RXD1 NC
PA6 TXD1 NC
PA7 SCK1 SPI0_NPCS1
PA8 RTS1 SPI0_NPCS2
PA9 CTS1 SPI0_NPCS3
PA10 TWD NC
PA11 TWCK NC
PA12 SPI0_NPCS0 NC
PA13 SPI0_NPCS1 PCK1
PA14 SPI0_NPCS2 IRQ1
PA15 SPI0_NPCS3 TCLK2
PA16 SPI0_MISO NC
PA17 SPI0_MOSI NC
PA18 SPI0_SPCK NC
PA19 CANRX NC
PA20 CANTX NC
PA21 TF SPI1_NPCS0
PA22 TK SPI1_SPCK
PA23 TD SPI1_MOSI
PA24 RD SPI1_MISO
PA25 RK SPI1_NPCS1
PA26 RF SPI1_NPCS2
PA27 DRXD PCK3
PA28 DTXD NC
PA29 FIQ SPI1_NPCS3
PA30 IRQ0 PCK2

@ -0,0 +1,81 @@
/*
* 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 <printf.h>
#include <platform/at91sam7.h>
#include <kernel/thread.h>
#include <stdarg.h>
void ser_init(void)
{
AT91DBGU *dbgu = AT91DBGU_ADDR;
// AT91PIO *pio = AT91PIO_ADDR;
// pio->select_a = PIN_DRXD | PIN_DTXD;
// pio->pio_disable = PIN_DRXD | PIN_DTXD;
dbgu->MR = DBGU_PAR_NONE | DBGU_MODE_NORMAL;
// dbgu->BRGR = 10; //MCK_IN_MHZ / 115200 / 16;
dbgu->BRGR = AT91_MCK_MHZ / 115200 / 16;
dbgu->CR = DBGU_RXEN | DBGU_TXEN;
}
void ser_putc(unsigned c)
{
AT91DBGU *dbgu = AT91DBGU_ADDR;
if(c == 10) {
while(!(dbgu->SR & DBGU_TXRDY));
dbgu->THR = 13;
}
while(!(dbgu->SR & DBGU_TXRDY));
dbgu->THR = c;
}
void ser_puts(const char *s)
{
AT91DBGU *dbgu = AT91DBGU_ADDR;
while(*s) {
if(*s == 10) {
while(!(dbgu->SR & DBGU_TXRDY));
dbgu->THR = 13;
}
while(!(dbgu->SR & DBGU_TXRDY));
dbgu->THR = *s++;
}
}
void _dputc(char c)
{
ser_putc(c);
}
void platform_halt()
{
arch_disable_ints();
for(;;);
}
uint32_t debug_cycle_count()
{
PANIC_UNIMPLEMENTED;
}

@ -0,0 +1,250 @@
/*
* 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 <kernel/thread.h>
#include <kernel/mutex.h>
#include <platform/at91sam7.h>
#include <platform/debug.h>
#include <dev/ethernet.h>
#include <malloc.h>
#include <string.h>
#include <hw/mii.h>
void emac_init_send(void);
#define PHYA 31
static unsigned mi_rd(AT91EMAC *emac, unsigned addr)
{
addr &= 0x1f;
thread_sleep(20);
emac->MAN =
(1 << 30) | /* sof: 01 */
(2 << 28) | /* rw: 10 = read */
(PHYA << 23) | /* phya: PHYA */
(addr << 18) | /* rega: addr */
(2 << 16); /* code: 10 */
while(!(emac->NSR & NSR_IDLE)) ;
thread_sleep(20);
return emac->MAN & 0xffff;
}
static void mi_wr(AT91EMAC *emac, unsigned addr, unsigned val)
{
addr &= 0x1f;
val &= 0xffff;
emac->MAN =
(1 << 30) | /* sof: 01 */
(1 << 28) | /* rw: 01 = read */
(PHYA << 23) | /* phya: PHYA */
(addr << 18) | /* rega: addr */
(2 << 16) | /* code: 10 */
val; /* data: val */
while(!(emac->NSR & NSR_IDLE)) ;
}
#define PIN_EMAC_ALL 0x3ffff
#define PIN_PHY_PD (1 << 18)
#define PIN_PHY_IRQ (1 << 26)
#define PIN_PHYAD0 (1 << 26)
#define PIN_PHYAD1 (1 << 14)
#define PIN_PHYAD2 (1 << 13)
#define PIN_PHYAD3 (1 << 6)
#define PIN_PHYAD4 (1 << 5)
#define PIN_LPBK (1 << 15)
#define PIN_ISOLATE (1 << 7)
#define PIN_RMII_MODE (1 << 16)
#define PIN_RMII_BTB (1 << 4)
/* select RMII w/ BTB, 100mbps duplex autonegotiate
** disable ISOLATE and LPBK
** phya=00001b
*/
#define PIN_RESET_LOW (PIN_LPBK)
int emac_init(void)
{
AT91EMAC *emac = AT91EMAC_ADDR;
AT91PIO *piob = AT91PIOB_ADDR;
AT91PMC *pmc = AT91PMC_ADDR;
AT91RSTC *rstc = AT91RSTC_ADDR;
dprintf(INFO, "emac_init()\n");
/* enable clock to EMAC */
pmc->PCER = (1 << PID_EMAC);
thread_sleep(10);
/* for reset, all lines are gpio inputs and pullups are
enabled or disabled per strapping mode defined above */
piob->pio_enable = PIN_EMAC_ALL | PIN_PHY_PD | PIN_PHY_IRQ;
piob->select_a = PIN_EMAC_ALL;
piob->pullup_enable = PIN_EMAC_ALL | PIN_PHY_IRQ;
piob->pullup_disable = PIN_LPBK | PIN_ISOLATE | PIN_RMII_MODE;
piob->output_disable = PIN_EMAC_ALL;
/* PHY PD becomes output and high (no powerdown mode */
piob->data_set = PIN_PHY_PD;
piob->output_enable = PIN_PHY_PD;
thread_sleep(30);
dprintf(INFO, "emac_init() - reset phy\n");
/* assert the RST line and wait until the it deasserts */
rstc->CR = RSTC_KEY | RSTC_EXTRST;
while(rstc->SR & RSTC_NRSTL) ;
thread_sleep(30);
/* after reset all the gpios are assigned to the EMAC,
except for PHY_PD (which remains output and high) */
piob->pio_disable = PIN_EMAC_ALL;
emac->USRIO = USRIO_CLKEN;
thread_sleep(1000);
dprintf(INFO, "emac_init() - read state\n");
emac->NCR = NCR_MPE;
emac->NCFG = NCFG_CLK_d64;
dprintf(INFO, "bcr = %x\n", mi_rd(emac, MII_REG_BCR));
dprintf(INFO, "id1 = %x\n", mi_rd(emac, MII_REG_PHY_ID1));
dprintf(INFO, "id2 = %x\n", mi_rd(emac, MII_REG_PHY_ID2));
#if 0
unsigned state, last;
last = 0xff;
for(;;) {
state = mi_rd(emac, MII_REG_100TX_PHY) & MII_100TX_MODE_MASK;
if(last != state) {
last = state;
char *name;
switch(state) {
case MII_100TX_MODE_AUTO:
name = "auto negotiate";
break;
case MII_100TX_MODE_10T_H:
name = "10-T half duplex";
break;
case MII_100TX_MODE_10T_F:
name = "10-T full duplex";
break;
case MII_100TX_MODE_100TX_H:
name = "100-TX half duplex";
break;
case MII_100TX_MODE_100TX_F:
name = "100-TX full duplex";
break;
case MII_100TX_MODE_ISOLATE:
name = "isolate";
break;
default:
name = "unknown";
}
dprintf(INFO, "link state: %s\n", name);
}
thread_sleep(100);
}
#endif
emac_init_send();
return 0;
}
#define XMIT_ENTRY_COUNT 32
static emac_xmit_entry xmit_list[XMIT_ENTRY_COUNT];
static unsigned xmit_next = 0;
static mutex_t xmit_lock;
void emac_init_send(void)
{
AT91EMAC *emac = AT91EMAC_ADDR;
int i;
for(i = 0; i < XMIT_ENTRY_COUNT; i++) {
xmit_list[i].info = XMIT_USED;
xmit_list[i].addr = 0;
}
xmit_list[i-1].info |= XMIT_LAST;
emac->NCFG = NCFG_CLK_d64 | NCFG_SPD | NCFG_FD;
emac->NCR = NCR_TE | NCR_MPE;
emac->TBQP = (unsigned) xmit_list;
mutex_init(&xmit_lock);
}
int ethernet_send(void *data, unsigned len)
{
AT91EMAC *emac = AT91EMAC_ADDR;
emac_xmit_entry *xe;
int waited = 0;
mutex_acquire(&xmit_lock);
xe = xmit_list + xmit_next;
while(!(xe->info & XMIT_USED)) {
thread_yield();
waited++;
}
if(waited) dprintf(INFO, "W%d\n",waited);
if(xe->addr != 0) {
free((void*) xe->addr);
}
xe->addr = (unsigned) data;
if(xmit_next == (XMIT_ENTRY_COUNT - 1)) {
xe->info = XMIT_LENGTH(len) | XMIT_LAST | XMIT_WRAP;
xmit_next = 0;
} else {
xe->info = XMIT_LENGTH(len) | XMIT_LAST;
xmit_next++;
}
emac->NCR |= NCR_TSTART;
mutex_release(&xmit_lock);
return 0;
}

@ -0,0 +1,794 @@
/* at91sam7s.h -- AT91SAM7S hardware definitions
**
** Copyright 2006, Brian Swetland. All rights reserved.
** See provided LICENSE file or http://frotz.net/LICENSE for details.
*/
#ifndef __PLATFORM_AT91SAM7_H__
#define __PLATFORM_AT91SAM7_H__
#if !defined(AT91_SAM7X) && !defined(AT91_SAM7S)
#error Unspecified Architecture - AT91SAM7S or AT91SAM7X must be defined
#endif
/* peripheral ids */
#define PID_AIC_FIQ 0
#define PID_SYSIRQ 1
#define PID_PIOA 2
#define PID_USART0 6
#define PID_USART1 7
#define PID_SSC 8
#define PID_TWI 9
#define PID_PWMC 10
#define PID_UDP 11
#define PID_TC0 12
#define PID_TC1 13
#define PID_TC2 14
#if AT91_SAM7X
#define PID_PIOB 3
#define PID_SPI0 4
#define PID_SPI1 5
#define PID_CAN 15
#define PID_EMAC 16
#define PID_ADC 17
#define PID_AIC_IRQ0 30
#define PID_AIC_IRQ1 31
#else
#define PID_ADC 4
#define PID_SPI0 5
#define PID_AIC_IRQ 30
#endif
#define BASE_FLASH 0x00100000
#define BASE_SRAM 0x00200000
#define BASE_TC 0xFFFA0000
#define BASE_UDP 0xFFFB0000
#define BASE_TWI 0xFFFB8000
#define BASE_USART0 0xFFFC0000
#define BASE_USART1 0xFFFC4000
#define BASE_PWMC 0xFFFCC000
#define BASE_SSC 0xFFFD4000
#define BASE_ADC 0xFFFD8000
#define BASE_SPI0 0xFFFE0000
#define BASE_AIC 0xFFFFF000
#define BASE_DBGU 0xFFFFF200
#define BASE_PIOA 0xFFFFF400
#define BASE_PMC 0xFFFFFC00
#define BASE_RSTC 0xFFFFFD00
#define BASE_RTT 0xFFFFFD20
#define BASE_PIT 0xFFFFFD30
#define BASE_WDT 0xFFFFFD40
#define BASE_VREG 0xFFFFFD60
#define BASE_MC 0xFFFFFF00
#if AT91_SAM7X
#define BASE_CAN 0xFFFD0000
#define BASE_EMAC 0xFFFDC000
#define BASE_SPI1 0xFFFE4000
#define BASE_PIOB 0xFFFFF600
#endif
typedef volatile unsigned int vu4;
typedef struct
{
vu4 MR;
vu4 SR;
vu4 PIVR;
vu4 PIIR;
} AT91PIT;
/* MR */
#define PIT_PITEN (1 << 24)
#define PIT_PITIEN (1 << 25)
/* SR */
#define PIT_PITS (1)
/* PIxR */
#define PIT_PICNT(x) (x >> 20)
#define PIT_CPIV(x) (x & 0x000fffff)
#define AT91PIT_ADDR ((AT91PIT*) BASE_PIT)
typedef struct
{
vu4 CR;
vu4 MR;
vu4 IER;
vu4 IDR;
vu4 IMR;
vu4 SR;
vu4 RHR;
vu4 THR;
vu4 BRGR;
vu4 __0[7];
vu4 CIDR;
vu4 EXID;
vu4 FNR;
} AT91DBGU;
/* CR bits */
#define DBGU_RSTRX 0x00000004
#define DBGU_RSTTX 0x00000008
#define DBGU_RXEN 0x00000010
#define DBGU_RXDIS 0x00000020
#define DBGU_TXEN 0x00000040
#define DBGU_TXDIS 0x00000080
#define DBGU_RSTSTA 0x00000100
/* MR bits */
#define DBGU_PAR_EVEN 0x00000000
#define DBGU_PAR_ODD 0x00000200
#define DBGU_PAR_SPACE 0x00000400
#define DBGU_PAR_MARK 0x00000600
#define DBGU_PAR_NONE 0x00000800
#define DBGU_MODE_NORMAL 0x00000000
#define DBGU_MODE_ECHO 0x0000C000
#define DBGU_MODE_LLOOP 0x00008000
#define DBGU_MODE_RLOOP 0x00004000
/* IER, IDR, IMR, and SR bits */
#define DBGU_RXRDY 0x00000001
#define DBGU_TXRDY 0x00000002
#define DBGU_ENDRX 0x00000008
#define DBGU_ENDTX 0x00000010
#define DBGU_OVRE 0x00000020
#define DBGU_FRAME 0x00000040
#define DBGU_PARE 0x00000080
#define DBGU_TXEMPTY 0x00000200
#define DBGU_TXBUFE 0x00000800
#define DBGU_RXBUFF 0x00001000
#define DBGU_COMMTX 0x40000000
#define DBGU_COMMRX 0x80000000
#define AT91DBGU_ADDR ((AT91DBGU*) BASE_DBGU)
typedef struct
{
vu4 pio_enable;
vu4 pio_disable;
vu4 pio_status;
vu4 __0;
vu4 output_enable;
vu4 output_disable;
vu4 output_status;
vu4 __1;
vu4 filter_enable;
vu4 filter_disable;
vu4 filter_status;
vu4 __2;
vu4 data_set;
vu4 data_clear;
vu4 data_status;
vu4 pin_status;
vu4 irq_enable;
vu4 irq_disable;
vu4 irq_mask;
vu4 irq_status;
vu4 multidriver_enable;
vu4 multidriver_disable;
vu4 multidriver_status;
vu4 __3;
vu4 pullup_disable;
vu4 pullup_enable;
vu4 pullup_status;
vu4 __4;
vu4 select_a;
vu4 select_b;
vu4 select_status;
vu4 __5[9];
vu4 write_enable;
vu4 write_disable;
vu4 write_status;
} AT91PIO;
#define AT91PIOA_ADDR ((AT91PIO*) BASE_PIOA)
#if AT91_SAM7X
#define AT91PIOB_ADDR ((AT91PIO*) BASE_PIOB)
#endif
typedef struct
{
vu4 SCER;
vu4 SCDR;
vu4 SCSR;
vu4 __0;
vu4 PCER;
vu4 PCDR;
vu4 PCSR;
vu4 __1;
vu4 MOR;
vu4 MCFR;
vu4 __2;
vu4 PLLR;
vu4 MCKR;
vu4 __3[2];
vu4 PCK0;
vu4 PCK1;
vu4 PCK2;
} AT91PMC;
#define AT91PMC_ADDR ((AT91PMC*) BASE_PMC)
/* PMC_SCER/SCDR */
#define PMC_PCK 0x00000001
#define PMC_UDP 0x00000080
#define PMC_PCK0 0x00000100
#define PMC_PCK1 0x00000200
#define PMC_PCK2 0x00000400
typedef struct
{
vu4 CR;
vu4 MR;
vu4 RDR;
vu4 TDR;
vu4 SR;
vu4 IER;
vu4 IDR;
vu4 IMR;
vu4 __0[4];
vu4 CSR0;
vu4 CSR1;
vu4 CSR2;
vu4 CSR3;
} AT91SPI;
#define AT91SPI0_ADDR ((AT91SPI*) BASE_SPI0)
#if AT91_SAM7X
#define AT91SPI1_ADDR ((AT91SPI*) BASE_SPI0)
#endif
/* CR bits */
#define SPI_SPIEN 0x00000001
#define SPI_SPIDIS 0x00000002
#define SPI_SWRST 0x00000080
#define SPI_LASTXFER 0x01000000
/* MR bits */
#define SPI_MSTR 0x00000001
#define SPI_PS 0x00000002
#define SPI_PCSDEC 0x00000004
#define SPI_MODFDIS 0x00000010
#define SPI_LLB 0x00000080
#define SPI_DLYBCS(n) (((n) & 0xff) << 24)
#define SPI_PCS0 0x000e0000
#define SPI_PCS1 0x000d0000
#define SPI_PCS2 0x000b0000
#define SPI_PCS3 0x00070000
/* SR bits */
#define SPI_RDRF 0x00000001 /* recv data reg full */
#define SPI_TDRE 0x00000002 /* xmit data reg empty */
#define SPI_MODF 0x00000004 /* mode fault error */
#define SPI_OVRES 0x00000008 /* overrun error */
#define SPI_ENDRX 0x00000010 /* end of rx buffer */
#define SPI_ENDTX 0x00000020 /* end of tx buffer */
#define SPI_RXBUFF 0x00000040 /* rx buffer full */
#define SPI_TXBUFE 0x00000080 /* tx buffer empty */
#define SPI_NSSR 0x00000100 /* rising edge on NSS */
#define SPI_TXEMPTY 0x00000200 /* transmission regs empty */
#define SPI_SPIENS 0x00010000
typedef struct
{
vu4 FRM_NUM;
vu4 GLB_STAT;
vu4 FADDR;
vu4 __0;
vu4 IER;
vu4 IDR;
vu4 IMR;
vu4 ISR;
vu4 ICR;
vu4 __1;
vu4 RST_EP;
vu4 __2;
vu4 CSR0;
vu4 CSR1;
vu4 CSR2;
vu4 CSR3;
vu4 __3[4];
vu4 FDR0;
vu4 FDR1;
vu4 FDR2;
vu4 FDR3;
vu4 __4[5];
vu4 TXVC;
} AT91UDP;
#define AT91UDP_ADDR ((AT91UDP*) BASE_UDP)
// GLB_STAT bits
#define UDP_FADDEN 0x00000001
#define UDP_CONFG 0x00000002
#define UDP_ESR 0x00000004
#define UDP_RSMINPR 0x00000008
#define UDP_RMWUPE 0x00000010
// FADDR bits
#define UDP_FEN 0x00000100
// interrupt bits
#define UDP_EP0INT 0x00000001
#define UDP_EP1INT 0x00000002
#define UDP_EP2INT 0x00000004
#define UDP_EP3INT 0x00000008
#define UDP_RXSUSP 0x00000100
#define UDP_RXRSM 0x00000200
#define UDP_EXTRSM 0x00000400
#define UDP_SOFINT 0x00000800
#define UDP_ENDBUSRES 0x00001000
#define UDP_WAKEUP 0x00002000
// RST_EP bits
#define UDP_EP0 0x00000001
#define UDP_EP1 0x00000002
#define UDP_EP2 0x00000004
#define UDP_EP3 0x00000008
// CSR bits
#define UDP_TXCOMP 0x00000001
#define UDP_RX_DATA_BK0 0x00000002
#define UDP_RXSETUP 0x00000004
#define UDP_STALLSENT 0x00000008
#define UDP_ISOERROR 0x00000008
#define UDP_TXPKTRDY 0x00000010
#define UDP_FORCESTALL 0x00000020
#define UDP_RX_DATA_BK1 0x00000040
#define UDP_DIR 0x00000080
#define UDP_DTGL 0x00000800
#define UDP_EPEDS 0x00008000
#define UDP_TYPE_CONTROL 0x00000000
#define UDP_TYPE_ISOCH_OUT 0x00000100
#define UDP_TYPE_BULK_OUT 0x00000200
#define UDP_TYPE_INT_OUT 0x00000300
#define UDP_TYPE_ISOCH_IN 0x00000500
#define UDP_TYPE_BULK_IN 0x00000600
#define UDP_TYPE_INT_IN 0x00000700
typedef struct
{
vu4 SMR[32];
vu4 SVR[32];
vu4 IVR;
vu4 FVR;
vu4 ISR;
vu4 IPR;
vu4 IMR;
vu4 CISR;
vu4 __0[2];
vu4 IECR;
vu4 IDCR;
vu4 ICCR;
vu4 ISCR;
vu4 EOICR;
vu4 SPU;
vu4 DCR;
vu4 __1;
vu4 FFER;
vu4 FFDR;
vu4 FFSR;
} AT91AIC;
#define AT91AIC_ADDR ((AT91AIC*) BASE_AIC)
typedef struct
{
vu4 CR;
vu4 MR;
vu4 IER;
vu4 IDR;
vu4 IMD;
vu4 CSR;
vu4 RHR;
vu4 THR;
vu4 BRGR;
vu4 RTOR;
vu4 TTGR;
vu4 __0[5];
vu4 FIDI;
vu4 NER;
vu4 __1;
vu4 IF;
vu4 MAN;
} AT91USART;
#define AT91USART0_ADDR ((AT91USART*) 0xFFFC0000)
#define AT91USART1_ADDR ((AT91USART*) 0xFFFC4000)
/* CR */
#define USART_RSTRX 0x00000004
#define USART_RSTTX 0x00000008
#define USART_RXEN 0x00000010
#define USART_RXDIS 0x00000020
#define USART_TXEN 0x00000040
#define USART_TXDIS 0x00000080
#define USART_RSTSTA 0x00000100
#define USART_STTBRK 0x00000200
#define USART_STPBRK 0x00000400
#define USART_STTTO 0x00000800
#define USART_SENDA 0x00001000
#define USART_RSTIT 0x00002000
#define USART_RSTNACK 0x00004000
#define USART_RETTO 0x00008000
#define USART_DTREN 0x00010000
#define USART_DTRDIS 0x00020000
#define USART_RTSEN 0x00040000
#define USART_RTSDIS 0x00080000
/* MR */
#define USART_MODE_NORMAL 0x00000000
#define USART_MODE_RS485 0x00000001
#define USART_MODE_HWHS 0x00000002
#define USART_MODE_MODEM 0x00000003
#define USART_MODE_ISO7816T0 0x00000004
#define USART_MODE_ISO7816T1 0x00000006
#define USART_MODE_IRDA 0x00000008
#define USART_CLK_MCK 0x00000000
#define USART_CLK_MCK_DIV 0x00000010
#define USART_CLK_SCK 0x00000030
#define USART_CHRL_5BITS 0x00000000
#define USART_CHRL_6BITS 0x00000040
#define USART_CHRL_7BITS 0x00000080
#define USART_CHRL_8BITS 0x000000C0
#define USART_SYNCHRONOUS 0x00000100
#define USART_PARITY_EVEN 0x00000000
#define USART_PARITY_ODD 0x00000200
#define USART_PARITY_SPACE 0x00000400
#define USART_PARITY_MARK 0x00000600
#define USART_PARITY_NONE 0x00000800
#define USART_PARITY_MULTIDROP 0x00000C00
#define USART_1STOP 0x00000000
#define USART_1X5STOP 0x00001000
#define USART_2STOP 0x00002000
#define USART_CHMODE_NORMAL 0x00000000
#define USART_CHMODE_ECHO 0x00004000
#define USART_CHMODE_LLOOP 0x00008000
#define USART_CHMODE_RLOOP 0x0000C000
#define USART_MSBF 0x00010000
#define USART_MODE9 0x00020000
#define USART_CLKO 0x00040000
#define USART_OVER 0x00080000
#define USART_INACK 0x00100000
#define USART_DSNACK 0x00200000
#define USART_VAR_SYNC 0x00400000
#define USART_FILTER 0x10000000
#define USART_MAN 0x20000000
#define USART_ONEBIT 0x80000000
/* CSR */
#define USART_RXRDY 0x00000001
#define USART_TXRDY 0x00000002
#define USART_RXBRK 0x00000004
#define USART_ENDRX 0x00000008
#define USART_ENDTX 0x00000010
#define USART_OVRE 0x00000020
#define USART_FRAME 0x00000040
#define USART_PARE 0x00000080
#define USART_TIMEOUT 0x00000100
#define USART_TXEMPTY 0x00000200
#define USART_ITERATION 0x00000400
#define USART_TXBUFE 0x00000800
#define USART_RXBUFF 0x00001000
#define USART_NACK 0x00002000
typedef struct
{
vu4 CR;
vu4 SR;
vu4 MR;
} AT91RSTC;
#define RSTC_KEY 0xA5000000
/* cr */
#define RSTC_PROCRST 0x00000001
#define RSTC_PERRST 0x00000004
#define RSTC_EXTRST 0x00000008
/* sr */
#define RSTC_URSTS 0x00000001
#define RSTC_BODSTS 0x00000002
#define RSTC_RSTTYP_MASK 0x00000070
#define RSTC_RSTTYP_COLD 0x00000000
#define RSTC_RSTTYP_WATCHDOG 0x00000020
#define RSTC_RSTTYP_SOFTWARE 0x00000030
#define RSTC_RSTTYP_NRST_PIN 0x00000040
#define RSTC_RSTTYP_BROWNOUT 0x00000060
#define RSTC_NRSTL 0x00010000
#define RSTC_SRCMP 0x00020000
/* mr */
#define RSTC_URSTEN 0x00000001
#define RSTC_URSTIEN 0x00000010
#define RSTC_ERSTL(n) (((n) & 0xf) << 8)
#define RSTC_BODIEN 0x00010000
#define AT91RSTC_ADDR ((AT91RSTC*) BASE_RSTC)
#if AT91_SAM7X
typedef struct
{
vu4 NCR;
vu4 NCFG;
vu4 NSR;
vu4 __0;
vu4 __1;
vu4 TSR;
vu4 RBQP;
vu4 TBQP;
vu4 RSR;
vu4 ISR;
vu4 IER;
vu4 IDR;
vu4 IMR;
vu4 MAN;
vu4 PTR;
vu4 PFR;
vu4 FTO;
vu4 SCF;
vu4 MCF;
vu4 FRO;
vu4 FCSE;
vu4 ALE;
vu4 DTF;
vu4 LCOL;
vu4 ECOL;
vu4 TUND;
vu4 CSE;
vu4 RRE;
vu4 ROV;
vu4 RSE;
vu4 ELE;
vu4 RJA;
vu4 USF;
vu4 STE;
vu4 RLE;
vu4 __2;
vu4 HRB;
vu4 HRT;
vu4 SA1B;
vu4 SA1T;
vu4 SA2B;
vu4 SA2T;
vu4 SA3B;
vu4 SA3T;
vu4 SA4B;
vu4 SA5T;
vu4 TID;
vu4 __3;
vu4 USRIO;
} AT91EMAC;
#define NCR_LB 0x00000001
#define NCR_LLB 0x00000002
#define NCR_RE 0x00000004
#define NCR_TE 0x00000008
#define NCR_MPE 0x00000010
#define NCR_CLRSTAT 0x00000020
#define NCR_INCSTAT 0x00000040
#define NCR_WESTAT 0x00000080
#define NCR_BP 0x00000100
#define NCR_TSTART 0x00000200
#define NCR_THALT 0x00000400
#define NCFG_SPD 0x00000001
#define NCFG_FD 0x00000002
#define NCFG_JFRAME 0x00000008
#define NCFG_CAF 0x00000010
#define NCFG_NBC 0x00000020
#define NCFG_MTI 0x00000040
#define NCFG_UNI 0x00000080
#define NCFG_BIG 0x00000100
#define NCFG_CLK_d8 0x00000000
#define NCFG_CLK_d16 0x00000400
#define NCFG_CLK_d32 0x00000800
#define NCFG_CLK_d64 0x00000C00
#define NCFG_RTY 0x00001000
#define NCFG_PAE 0x00002000
#define NCFG_RBOF_0 0x00000000
#define NCFG_RBOF_1 0x00004000
#define NCFG_RBOF_2 0x00008000
#define NCFG_RBOF_3 0x0000C000
#define NCFG_RLCE 0x00010000
#define NCFG_DRFCS 0x00020000
#define NCFG_EFRHD 0x00040000
#define NCFG_IRXFCS 0x00080000
#define NSR_MDIO 0x00000002
#define NSR_IDLE 0x00000004
#define TSR_UBR 0x00000001
#define TSR_COL 0x00000002
#define TSR_RLE 0x00000004
#define TSR_TGO 0x00000008
#define TSR_BEX 0x00000010
#define TSR_COMP 0x00000020
#define TSR_UND 0x00000040
#define RSR_BNA 0x00000001
#define RSR_REC 0x00000002
#define RSR_OVR 0x00000004
#define ISR_MFD 0x00000001
#define ISR_RCOMP 0x00000002
#define ISR_RXUBR 0x00000004
#define ISR_TXUBR 0x00000008
#define ISR_TUND 0x00000010
#define ISR_RLE 0x00000020
#define ISR_TXERR 0x00000040
#define ISR_TCOMP 0x00000080
#define ISR_ROVR 0x00000400
#define ISR_HRESP 0x00000800
#define ISR_PFR 0x00001000
#define ISR_PTZ 0x00002000
#define USRIO_RMII 0x00000001
#define USRIO_CLKEN 0x00000002
#define AT91EMAC_ADDR ((AT91EMAC*) BASE_EMAC)
typedef struct
{
vu4 addr;
vu4 info;
} emac_xmit_entry;
#define XMIT_USED 0x80000000
#define XMIT_WRAP 0x40000000
#define XMIT_ERR_RETRY 0x20000000
#define XMIT_ERR_UNDERRUN 0x10000000
#define XMIT_ERR_EXHAUSTED 0x08000000
#define XMIT_NO_CRC 0x00010000
#define XMIT_LAST 0x00008000
#define XMIT_LENGTH(n) ((n) & 0x3FF)
/* CAN Registers */
typedef struct
{
vu4 MMR; /* Mailbox Mode Register */
vu4 MAM; /* Mailbox Acceptance Mask Register */
vu4 MID; /* Mailbox ID Register */
vu4 MFID; /* Mailbox Family ID Register */
vu4 MSR; /* Mailbox Status Register */
vu4 MDL; /* Mailbox Data Low Register */
vu4 MDH; /* Mailbox Data High Register */
vu4 MCR; /* Mailbox Control Register */
} AT91CAN_MAILBOX;
typedef struct
{
vu4 MR; /* Mode Register */
vu4 IER; /* Interrupt Enable Register */
vu4 IDR; /* Interrupt Disable Register */
vu4 IMR; /* Interrupt Mask Register */
vu4 SR; /* Status Register */
vu4 BR; /* Baudrate Register */
vu4 TIM; /* Timer Register */
vu4 TIMESTP; /* Timestamp Register */
vu4 ECR; /* Error Counter Register */
vu4 TCR; /* Transfer Command Register */
vu4 ACR; /* Abort Command Register */
vu4 __0[53]; /* 0x002c - 0x0100 is undefined */
vu4 __1[63]; /* 0x0200 - 0x01fc is reserved */
AT91CAN_MAILBOX Mailbox[8];
} AT91CAN;
#define CAN_CANEN 0x00000001 /* CAN Controller Enable */
#define CAN_LPM 0x00000002 /* Enable Low Power Mode */
#define CAN_ABM 0x00000004 /* Enable Autoband/Listen Mode */
#define CAN_OVL 0x00000008 /* Enable Overload Frame */
#define CAN_TEOF 0x00000010 /* Timestamp Messages at each Frame */
#define CAN_TTM 0x00000020 /* Enable Time Trigger Mode */
#define CAN_TIMFRZ 0x00000040 /* Enable Timer Freeze */
#define CAN_DRPT 0x00000080 /* Disable Repeat */
#define CAN_MB(x) (0x00000001 << x) /* Enable Interrupt Enable */
#define CAN_ERRA 0x00010000 /* Enable Error Active Mode Interrupt */
#define CAN_WARN 0x00020000 /* Enable Warning Limit Interrupt */
#define CAN_ERRP 0x00040000 /* Enable Passive mode interrupt */
#define CAN_BOFF 0x00080000 /* Enable Bus-off mode interrupt */
#define CAN_SLEEP 0x00100000 /* Enable Sleep Interrupt */
#define CAN_WAKEUP 0x00200000 /* Enable Wakeup Interrupt */
#define CAN_TOVF 0x00400000 /* Enable Timer Overflow Interrupt */
#define CAN_TSTP 0x00800000 /* Enable TimeStamp Interrupt */
#define CAN_CERR 0x01000000 /* Enable CRC Error Interrupt */
#define CAN_SERR 0x02000000 /* Enable Stuffing Error Interrupt */
#define CAN_AERR 0x04000000 /* Enable Acknowledgement Error Int */
#define CAN_FERR 0x08000000 /* Enable Form Error Interrupt */
#define CAN_BERR 0x10000000 /* Enable Bit Error Interrupt */
#define CAN_RBSY 0x20000000 /* Receiver Busy */
#define CAN_TBSY 0x40000000 /* Transmitter Busy */
#define CAN_OVLSY 0x80000000 /* Overload Busy */
/* Can Baudrate Regiister */
#define CAN_PHASE2(x) (x)
#define CAN_PHASE2_MASK 0x07
#define CAN_PHASE1(x) (x<<4)
#define CAN_PHASE1_MASK (0x07 << 4)
#define CAN_PROPAG(x) (x<<8)
#define CAN_PROPAG_MASK (0x07 << 8)
#define CAN_SJW(x) (x<<12)
#define CAN_SJW_MASK(x) (0x03 << 12)
#define CAN_BRP(x) (x<<16)
#define CAN_BRP_MASK (0x7f << 16)
#define CAN_SMP 0x01000000 /* Sampling Mode */
/* CAN Transfer Command Register */
#define TCR_TIMRST 0x80000000 /* Timer Reset */
/* CAN Message Mode Register */
#define CAN_MTIMEMARK(x) (0x0000001 << x)
#define CAN_PRIOR(x) (x << 16)
#define CAN_MOT(x) (x << 24)
#define CAN_MIDVB(x) (x)
#define CAN_MIDVA(x) (x << 18)
#define CAN_MIDE 0x20000000
/* CAN MSRx */
/* These are receive, so pass in the value of the register... */
#define CAN_MTIMESTAMP(x) (x & 0x0000ffff)
#define CAN_MDLC(x) ( (x >> 16) & 0x0f) /* Mailbox code length */
#define CAN_MRTR 0x00100000 /* Mailbox Remote Trx Request*/
#define CAN_MABT 0x00400000 /* Mailbox Message Abort */
#define CAN_MRDY 0x00800000 /* Mailbox Ready */
#define CAN_MMI 0x01000000 /* Mailbox Message Ignored */
/* Message Control Register */
//#define CAN_MDLC(x) (x<<16) /* Mailbox Data Length Code */
#define CAN_MACR (0x01 << 22) /* Abort Request */
#define CAN_MTCR (0x01 << 23) /* Mailbox Transfer Command */
#define AT91CAN_ADDR ((AT91CAN*) BASE_CAN)
#endif
#endif

@ -0,0 +1,101 @@
/* init_clock.S -- AT91SAM7 clock coldstart code
**
** Copyright 2006, Brian Swetland. All rights reserved.
** See provided LICENSE file or http://frotz.net/LICENSE for details.
*/
.globl init_clock
init_clock:
/* init flash controller timing for 18.432MHz */
mov r1, #0xffffff00
ldr r0, =0x00340100
str r0, [r1, #0x60]
#define PMC_MOR 0x20
#define PMC_MCFR 0x24
#define PMC_PLLR 0x2c
#define PMC_MCKR 0x30
#define PMC_SR 0x68
/* PMC_MOR */
#define PMC_MOSCEN 0x01
#define PMC_OSCBYPASS 0x02
/* PMC_MCFR */
#define PMC_MAINRDY 0x00010000
/* PMC_SR */
#define PMC_MOSCS 0x01
#define PMC_LOCK 0x04
#define PMC_MCKRDY 0x08
/* PMC_MCKR */
#define PMC_CSS_SLOW 0x00
#define PMC_CSS_MAIN 0x01
#define PMC_CSS_PLL 0x03
#define PMC_PRES_NONE 0x00
#define PMC_PRES_DIV2 0x04
#define PMC_PRES_DIV4 0x08
/* Oscillator Init Sequence based on the Atmel sample code
** in cstartup_boot_SAM7S32_64.s
**
** I cleaned it up a bit -- why they use a temporary register,
** AND and then CMP instead of just TSTing against an immediate
** boggles my mind. I think this could be a bit simpler yet,
** but debugging it is a pain, so Good Enough wins for now.
*/
ldr r1, =0xfffffc00
/* bypass main oscillator */
mov r0, #PMC_OSCBYPASS
str r0, [r1, #PMC_MOR]
/* compensate MAINRDY rising flag (45 SCLK) */
mov r0, #45
1: subs r0, r0, #1
bhi 1b
/* if MAINRDY is set, we have an external oscillator */
ldr r0, [r1, #PMC_MCFR]
tst r0, #PMC_MAINRDY
bne ext_osc_found
/* reset MOSCS flag */
mov r0, #0
str r0, [r1, #PMC_MOR]
/* enable main oscillator */
ldr r0, =((0x40 << 8) | PMC_MOSCEN)
str r0, [r1, #PMC_MOR]
/* wait for main oscillator to come online */
1: ldr r0, [r1, #PMC_SR]
tst r0, #PMC_MOSCS
beq 1b
ext_osc_found:
/* select main oscillator, no prescaler for MCK */
mov r0, #(PMC_CSS_MAIN | PMC_PRES_NONE)
str r0, [r1, #PMC_MCKR]
/* wait until MCK settles to continue */
1: ldr r0, [r1, #PMC_SR]
tst r0, #PMC_MCKRDY
beq 1b
/* this is a bit of voodoo for selecting a 96.109MHz PLL
** freq (MUL=72, DIV=14, OUT=0, USBDIV=/1) from the 18.432MHz
** main clock.
*/
ldr r0, =0x10483f0e
str r0, [r1, #PMC_PLLR]
/* let the PLL lock before we continue */
1: ldr r0, [r1, #PMC_SR]
tst r0, #PMC_LOCK
beq 1b
mov pc, lr

@ -0,0 +1,58 @@
/*
* 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.
*/
.globl init_48mhz_clock
#define PMC_MCKR 0x30
#define PMC_SR 0x68
#define PMC_MCKRDY 0x08
#define PMC_PRES_DIV2 0x04
#define PMC_CSS_PLL 0x03
/* BUG?
**
** If I try to exit by bx lr, lr is corrupted somewhere in here.
** No clue why. FIQ USB wedge not playing nice? Am I cheating
** with my CPSR calls?
*/
init_48mhz_clock:
ldr r1, =0xfffffc00
mov r2, lr
// turn on /2 prescaler
mov r0, #PMC_PRES_DIV2
str r0, [r1, #PMC_MCKR]
wait_for_clock1:
ldr r0, [r1, #PMC_SR]
tst r0, #PMC_MCKRDY
beq wait_for_clock1
// switch to pll clock
mov r0, #(PMC_PRES_DIV2 | PMC_CSS_PLL)
str r0, [r1, #PMC_MCKR]
wait_for_clock2:
ldr r0, [r1, #PMC_SR]
tst r0, #PMC_MCKRDY
beq wait_for_clock2
bx r2

@ -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 <err.h>
#include <sys/types.h>
#include <kernel/thread.h>
#include <platform.h>
#include <platform/interrupts.h>
#include <platform/at91sam7.h>
#include <arch/arm.h>
static int do_nothing()
{
return INT_NO_RESCHEDULE;
}
void platform_init_interrupts(void)
{
AT91AIC *aic = AT91AIC_ADDR;
int n;
for(n = 0; n < 31; n++) {
aic->SVR[n] = (unsigned) do_nothing;
}
aic->SPU = (unsigned) do_nothing;
}
status_t mask_interrupt(unsigned int vector)
{
AT91AIC *aic = AT91AIC_ADDR;
if(vector > 31) return ERR_INVALID_ARGS;
aic->IDCR = (1 << vector);
return NO_ERROR;
}
status_t unmask_interrupt(unsigned int vector)
{
AT91AIC *aic = AT91AIC_ADDR;
if(vector > 31) return ERR_INVALID_ARGS;
aic->IECR = (1 << vector);
return NO_ERROR;
}
void platform_irq(struct arm_iframe *frame)
{
AT91AIC *aic = AT91AIC_ADDR;
int_handler func;
enum handler_return ret;
inc_critical_section();
func = (int_handler) aic->IVR;
// dprintf("platform_irq() -> %p\n", func);
ret = func(0);
aic->EOICR = (unsigned) aic;
if(ret == INT_RESCHEDULE) {
thread_preempt();
}
dec_critical_section();
}
void platform_fiq(struct arm_iframe *frame)
{
}
void register_int_handler(unsigned int vector, int_handler handler, void *arg)
{
AT91AIC *aic = AT91AIC_ADDR;
if(vector > 31) return;
aic->SVR[vector] = (unsigned) handler;
}

@ -0,0 +1,178 @@
#!/usr/bin/python
## mkboard.py -- atmel pio mux utility
##
## Copyright 2006, Brian Swetland. All rights reserved.
## See provided LICENSE file or http://frotz.net/LICENSE for details.
##
import os, sys, string
# pindef -> num, out, pull, pio, sela, selb
reg_output_disable = 0
reg_output_enable = 0
reg_pullup_disable = 0
reg_pullup_enable = 0
reg_pio_disable = 0
reg_pio_enable = 0
reg_select_a = 0
reg_select_b = 0
def setup_registers(pindef):
global reg_output_disable
global reg_output_enable
global reg_pullup_disable
global reg_pullup_enable
global reg_pio_disable
global reg_pio_enable
global reg_select_a
global reg_select_b
(num, out, pull, pio, sela, selb) = pindef
bit = 1 << num
if out:
reg_output_enable |= bit
reg_output_disable &= (~bit)
else:
reg_output_enable &= (~bit)
reg_output_disable |= bit
if pull:
reg_pullup_enable |= bit
reg_pullup_disable &= (~bit)
else:
reg_pullup_enable &= (~bit)
reg_pullup_disable |= bit
if pio:
reg_pio_enable |= bit
reg_pio_disable &= (~bit)
else:
reg_pio_enable &= (~bit)
reg_pio_disable |= bit
if sela:
reg_select_a |= bit
if selb:
reg_select_b |= bit
def import_pindef(fn):
pass
def read_pins_def(fn, table):
output = ""
fd = open(fn,'r')
for line in fd.xreadlines():
line = line.split('#')[0].strip()
if not line: continue
(gpio,pa,pb) = line.split()
num = int(gpio[2:])
table[gpio+"_IN"] = (num, 0, 0, 1, 0, 0)
table[gpio+"_IN_PULLUP"] = (num, 0, 1, 1, 0, 0)
table[gpio+"_OUT"] = (num, 1, 0, 1, 0, 0)
table[gpio+"_"+pa] = (num, 0, 0, 0, 1, 0)
table[gpio+"_"+pb] = (num, 0, 0, 0, 0, 1)
return output
def read_board_def(fn, table):
pins = {}
output = ""
for n in range(0,32):
pins[n] = ''
fd = open(fn,'r')
for line in fd.xreadlines():
line = line.split('#')[0].strip()
if not line: continue
if len(line.split('=')) == 2:
(line,func) = line.split('=')
line = line.strip()
func = func.strip()
else:
func = ''
parts = line.split()
if len(parts) < 2:
print "ERROR: invalid definition '%s'" % line
sys.exit(1)
if not func:
if (parts[1] == 'IN') or (parts[1] == 'OUT'):
func = parts[0]
else:
func = parts[1]
pin = string.join(parts,"_")
if not table.has_key(pin):
print "ERROR: pin '%s' does not exist" % pin
sys.exit(1)
pindef = table[pin]
num = pindef[0]
if pins[num]:
print "ERROR: pin '%s' conflicts with pin '%s'" % (pin, pins[num])
sys.exit(1)
pins[num] = pin
setup_registers(pindef)
output += "#define PIN_%-12s (1 << %d)\n" % (func, num)
return output
table = {}
output = ""
for fn in sys.argv[1:]:
if fn.endswith('.pins'):
if table:
print "ERROR: only one pin definition file allowed"
sys.exit(1)
output = read_pins_def(fn, table)
continue
if fn.endswith('.def'):
if not table:
print "ERROR: must specify a pin definition file first"
sys.exit(1)
reg_output_disable = 0xffffffffL
reg_output_enable = 0L
reg_pullup_disable = 0L
reg_pullup_enable = 0xffffffffL
reg_pio_disable = 0L
reg_pio_enable = 0xffffffffL
reg_select_a = 0L
reg_select_b = 0L
output = read_board_def(fn, table)
fd = open(fn[:-4] + ".h", 'w')
fd.write("/* DO NOT EDIT -- AUTOGENERATED FROM '%s' */\n\n" % fn)
fd.write("#ifndef __BOARD_DEFINITION_FILE__\n")
fd.write("#define __BOARD_DEFINITION_FILE__\n\n")
fd.write(output)
fd.write("\n")
fd.write("#define BOARD_OUTPUT_DISABLE 0x%08x\n" % reg_output_disable)
fd.write("#define BOARD_OUTPUT_ENABLE 0x%08x\n" % reg_output_enable)
fd.write("#define BOARD_PULLUP_DISABLE 0x%08x\n" % reg_pullup_disable)
fd.write("#define BOARD_PULLUP_ENABLE 0x%08x\n" % reg_pullup_enable)
fd.write("#define BOARD_PIO_DISABLE 0x%08x\n" % reg_pio_disable)
fd.write("#define BOARD_PIO_ENABLE 0x%08x\n" % reg_pio_enable)
fd.write("#define BOARD_SELECT_A 0x%08x\n" % reg_select_a)
fd.write("#define BOARD_SELECT_B 0x%08x\n" % reg_select_b)
fd.write("\n#endif\n")
fd.close()
continue
print "ERROR: what is '%s'?" % fn
sys.exit(1)

@ -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.
*/
#include <platform/at91sam7.h>
#include <platform/mux.h>
void mux_init(void)
{
AT91PIO *pio = AT91PIOA_ADDR;
pio->output_disable = BOARD_OUTPUT_DISABLE;
pio->output_enable = BOARD_OUTPUT_ENABLE;
pio->pullup_disable = BOARD_PULLUP_DISABLE;
pio->pullup_enable = BOARD_PULLUP_ENABLE;
pio->pio_disable = BOARD_PIO_DISABLE;
pio->pio_enable = BOARD_PIO_ENABLE;
pio->select_a = BOARD_SELECT_A;
pio->select_b = BOARD_SELECT_B;
}

@ -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.
*/
void emac_init();
void platform_init(void)
{
#if AT91_SAM7X
emac_init();
#endif
}

@ -0,0 +1,56 @@
/*
* 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.
*/
.globl platform_early_init
platform_early_init:
stmdb sp!, {lr}
/* enable the NRST reset pin */
ldr r1, =0xfffffd08
ldr r0, =0xa5000401
str r0, [r1]
/* disable watchdog */
ldr r1, =0xfffffd44
ldr r0, =0x3fff8fff
str r0, [r1]
bl init_clock
bl init_48mhz_clock
/* copy the .data section from ROM to RAM */
ldr r0, =__rodata_end
ldr r1, =__data_start
ldr r2, =__bss_start
__data_loop:
cmp r1, r2
ldrlt r3, [r0], #4
strlt r3, [r1], #4
blt __data_loop
bl mux_init
bl ser_init
bl platform_init_interrupts
ldmia sp!, {lr}
bx lr

@ -0,0 +1,70 @@
#
# The TARGET is expected to indicate which *specific* AT91SAM7 chip
# is being used, since features and memory vary from chip to chip
#
# chip ram rom EMAC CAN
# AT91CHIP := sam7s64 16k 64k N N
# AT91CHIP := sam7s256 64k 256k N N
# AT91CHIP := sam7x256 64k 256k Y Y
#
# ROMBASE, MEMBASE, and MEMSIZE are required for the linker script
ROMBASE := 0x0
MEMBASE := 0x200000
TMP_CFG := bad
ifeq ($(AT91CHIP), sam7x256)
DEFINES += AT91_SAM7X=1
DEFINES += AT91_RAMSIZE=65536
DEFINES += AT91_ROMSIZE=262144
MEMSIZE := 65536
TMP_CFG := ok
endif
ifeq ($(AT91CHIP), sam7s256)
DEFINES += AT91_SAM7S=1
DEFINES += AT91_RAMSIZE=65536
DEFINES += AT91_ROMSIZE=262144
MEMSIZE := 65536
TMP_CFG := ok
endif
ifeq ($(AT91CHIP), sam7s64)
DEFINES += AT91_SAM7S=1
DEFINES += AT91_RAMSIZE=16384
DEFINES += AT91_ROMSIZE=65536
MEMSIZE := 16384
TMP_CFG := ok
endif
ifeq ($(TMP_CFG), bad)
$(error The AT91SAM7 platform requires AT91CHIP be set by the target)
endif
LOCAL_DIR := $(GET_LOCAL_DIR)
ARCH := arm
ARM_CPU := arm7tdmi
DEFINES += AT91_MCK_MHZ=48000000
INCLUDES += \
-I$(LOCAL_DIR)/include
OBJS += \
$(LOCAL_DIR)/debug.o \
$(LOCAL_DIR)/interrupts.o \
$(LOCAL_DIR)/platform_early.o \
$(LOCAL_DIR)/platform.o \
$(LOCAL_DIR)/timer.o \
$(LOCAL_DIR)/init_clock.o \
$(LOCAL_DIR)/init_clock_48mhz.o \
$(LOCAL_DIR)/mux.o \
$(LOCAL_DIR)/emac_dev.o
# use a two segment memory layout, where all of the read-only sections
# of the binary reside in rom, and the read/write are in memory. The
# ROMBASE, MEMBASE, and MEMSIZE make variables are required to be set
# for the linker script to be generated properly.
#
LINKER_SCRIPT += \
$(BUILDDIR)/system-twosegment.ld

@ -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 <err.h>
#include <debug.h>
#include <sys/types.h>
#include <kernel/thread.h>
#include <platform/timer.h>
#include <platform/interrupts.h>
#include <platform/debug.h>
#include <platform/at91sam7.h>
#define FIXED_1KHZ_TIMER 0
static platform_timer_callback timer_func;
static volatile time_t ticks = 0;
#if FIXED_1KHZ_TIMER
static volatile int timer_interval;
static volatile int timer_downcount;
#else
static int timer_ms_per_tick;
#endif
time_t current_time(void)
{
return ticks;
}
static enum handler_return pit_irq_handler(void *arg)
{
AT91PIT *pit = AT91PIT_ADDR;
unsigned n = PIT_PICNT(pit->PIVR);
#if FIXED_1KHZ_TIMER
ticks += n;
timer_downcount -= n;
if(timer_downcount <= 0) {
timer_downcount = timer_interval;
return timer_func(0, ticks);
} else {
return INT_NO_RESCHEDULE;
}
#else
ticks += (n * timer_ms_per_tick);
return timer_func(0, ticks);
#endif
}
status_t platform_set_periodic_timer(platform_timer_callback callback,
void *arg, time_t interval)
{
unsigned n;
AT91PIT *pit = AT91PIT_ADDR;
n = AT91_MCK_MHZ / 16 / 1000;
dprintf(INFO, "timer: MCK=%dKHz, n=%d\n", AT91_MCK_MHZ / 1000, n);
enter_critical_section();
timer_func = callback;
#if FIXED_1KHZ_TIMER
timer_interval = interval;
timer_downcount = interval;
#else
timer_ms_per_tick = interval;
n *= interval;
#endif
pit->MR = PIT_PITEN | PIT_PITIEN | (n & 0xfffff);
register_int_handler(PID_SYSIRQ, pit_irq_handler, 0);
unmask_interrupt(PID_SYSIRQ);
exit_critical_section();
return NO_ERROR;
}

@ -0,0 +1,146 @@
/*
* 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 <stdarg.h>
#include <reg.h>
#include <debug.h>
#include <printf.h>
#include <kernel/thread.h>
#include <platform/debug.h>
#include <arch/ops.h>
#include <platform/integrator.h>
static void write_uart_reg(int uart, int reg, unsigned char data)
{
unsigned long base;
int mul = 4;
switch(uart) {
case 0: base = INTEGRATOR_UART0_REG_BASE; break;
case 1: base = INTEGRATOR_UART1_REG_BASE; break;
default: return;
}
*(volatile unsigned char *)(base + reg * mul) = data;
}
static unsigned char read_uart_reg(int uart, int reg)
{
unsigned long base;
int mul = 4;
switch(uart) {
case 0: base = INTEGRATOR_UART0_REG_BASE; break;
case 1: base = INTEGRATOR_UART1_REG_BASE; break;
default: return 0;
}
return *(volatile unsigned char *)(base + reg * mul);
}
static int uart_init(void)
{
#if 0
/* clear the tx & rx fifo and disable */
write_uart_reg(0, UART_FCR, 0x6);
#endif
return 0;
}
static int uart_putc(int port, char c )
{
write_uart_reg(0, PL011_UARTDR, c);
#if 0
while (!(read_uart_reg(port, UART_LSR) & (1<<6))) // wait for the shift register to empty
;
write_uart_reg(port, UART_THR, c);
#endif
return 0;
}
static int uart_getc(int port, bool wait) /* returns -1 if no data available */
{
#if 0
if (wait) {
while (!(read_uart_reg(port, UART_LSR) & (1<<0))) // wait for data to show up in the rx fifo
;
} else {
if (!(read_uart_reg(port, UART_LSR) & (1<<0)))
return -1;
}
return read_uart_reg(port, UART_RHR);
#endif
return -1;
}
void _dputc(char c)
{
uart_putc(0, c);
}
int dgetc(char *c)
{
int result = uart_getc(0, false);
if (result < 0)
return -1;
*c = result;
return 0;
}
void debug_dump_regs(void)
{
PANIC_UNIMPLEMENTED;
}
void platform_halt(void)
{
dprintf(ALWAYS, "HALT: spinning forever...\n");
for(;;);
}
void debug_dump_memory_bytes(void *mem, int len)
{
PANIC_UNIMPLEMENTED;
}
void debug_dump_memory_halfwords(void *mem, int len)
{
PANIC_UNIMPLEMENTED;
}
void debug_dump_memory_words(void *mem, int len)
{
PANIC_UNIMPLEMENTED;
}
void debug_set_trace_level(int trace_type, int level)
{
PANIC_UNIMPLEMENTED;
}
uint32_t debug_cycle_count()
{
PANIC_UNIMPLEMENTED;
}

@ -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 __INTEGRATOR_H
#define __INTEGRATOR_H
/* memory map */
#define SDRAM_BASE 0x00000000
#define INTEGRATOR_CORE_REG_BASE 0x10000000
#define INTEGRATOR_SYS_REG_BASE 0x11000000
#define INTEGRATOR_EBI_REG_BASE 0x12000000
#define INTEGRATOR_TIMER_REG_BASE 0x13000000
#define INTEGRATOR_INT_REG_BASE 0x14000000
#define INTEGRATOR_UART0_REG_BASE 0x16000000
#define INTEGRATOR_UART1_REG_BASE 0x17000000
#define INTEGRATOR_LEDS_REG_BASE 0x1a000000
#define INTEGRATOR_GPIO_REG_BASE 0x1b000000
/* uart stuff */
#define PL011_UARTDR (0)
#define PL011_UARTRSR (1)
#define PL011_UARTECR (1)
#define PL011_UARTFR (6)
#define PL011_UARTILPR (8)
#define PL011_UARTIBRD (9)
#define PL011_UARTFBRD (10)
#define PL011_UARTLCR_H (11)
#define PL011_UARTCR (12)
#define PL011_UARTIFLS (13)
#define PL011_UARTIMSC (14)
#define PL011_UARTTRIS (15)
#define PL011_UARTTMIS (16)
#define PL011_UARTICR (17)
#define PL011_UARTMACR (18)
#define INT_VECTORS 32 // XXX just made this up
#endif

@ -0,0 +1,238 @@
/*
* 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 <err.h>
#include <sys/types.h>
#include <debug.h>
#include <reg.h>
#include <kernel/thread.h>
#include <platform/interrupts.h>
#include <arch/ops.h>
#include <arch/arm.h>
#include "platform_p.h"
#include <platform/integrator.h>
struct int_handler_struct {
int_handler handler;
void *arg;
};
static struct int_handler_struct int_handler_table[INT_VECTORS];
#if 0
static const uint32_t icBase[5] = {
INTCON0_BASE, INTCON1_BASE, INTCON2_BASE, INTCON3_BASE, INTCON4_BASE };
/* a bitmap of the level triggered interrupt vectors */
static uint32_t level_trigger[5] = {
0xb3fefe8f, // level 1 0-31
0xfdb3c1fd, // level 2 0-31
0xfffff7ff, // level 2 32-63
0xbfffffff, // level 2 64-95
0xffffffff // level 2 96-128
};
inline volatile uint32_t *ICReg(uint controller, uint reg)
{
return (volatile uint32_t *)(icBase[controller] + reg);
}
inline uint32_t readICReg(uint controller, uint reg)
{
return *ICReg(controller, reg);
}
inline void writeICReg(uint controller, uint reg, uint val)
{
*ICReg(controller, reg) = val;
}
inline uint vectorToController(uint vector)
{
return vector / 32;
}
#endif
void platform_init_interrupts(void)
{
#if 0
unsigned int i;
// mask all interrupts
*ICReg(0, INTCON_MIR) = 0xfffffffa;
*ICReg(1, INTCON_MIR) = 0xffffffff;
*ICReg(2, INTCON_MIR) = 0xffffffff;
*ICReg(3, INTCON_MIR) = 0xffffffff;
*ICReg(4, INTCON_MIR) = 0xffffffff;
// set up each of the interrupts
for (i = 0; i < INT_VECTORS; i++) {
// set each vector up as high priority, IRQ, and default edge/level sensitivity
*ICReg(i / 32, INTCON_ILR_BASE + 4*(i%32)) = ((level_trigger[i/32] & (1<<(i%32))) ? (1<<1) : (0<<1)) | 0;
}
// clear any pending interrupts
*ICReg(0, INTCON_ITR) = 0;
*ICReg(1, INTCON_ITR) = 0;
*ICReg(2, INTCON_ITR) = 0;
*ICReg(3, INTCON_ITR) = 0;
*ICReg(4, INTCON_ITR) = 0;
// globally unmask interrupts
*ICReg(1, INTCON_CONTROL) = 3;
*ICReg(0, INTCON_CONTROL) = 3;
*ICReg(0, INTCON_GMR) = 0;
dprintf("end of platform_init_interrupts\n");
#if 0
arch_enable_ints();
dprintf("&ITR0 0x%x\n", (uint32_t)ICReg(0, INTCON_ITR));
dprintf("ITR0 0x%x\n", *ICReg(0, INTCON_ITR));
dprintf("MIR0 0x%x\n", *ICReg(0, INTCON_MIR));
dprintf("SIR_IRQ0 0x%x\n", *ICReg(0, INTCON_SIR_IRQ));
*ICReg(0, INTCON_ILR_BASE + 4*7) = 0;
*ICReg(0, INTCON_MIR) &= ~0x80;
dprintf("triggering int\n");
*ICReg(0, INTCON_SISR) = 0x80;
dprintf("ITR0 0x%x\n", *ICReg(0, INTCON_ITR));
dprintf("MIR0 0x%x\n", *ICReg(0, INTCON_MIR));
dprintf("SIR_IRQ0 0x%x\n", *ICReg(0, INTCON_SIR_IRQ));
for(;;);
#endif
#endif
}
status_t mask_interrupt(unsigned int vector)
{
#if 0
if (vector >= INT_VECTORS)
return ERR_INVALID_ARGS;
// dprintf("%s: vector %d\n", __PRETTY_FUNCTION__, vector);
enter_critical_section();
if (oldstate)
*oldstate = false;
volatile uint32_t *mir = ICReg(vectorToController(vector), INTCON_MIR);
*mir = *mir | (1<<(vector % 32));
exit_critical_section();
#endif
return NO_ERROR;
}
status_t unmask_interrupt(unsigned int vector)
{
#if 0
if (vector >= INT_VECTORS)
return ERR_INVALID_ARGS;
// dprintf("%s: vector %d\n", __PRETTY_FUNCTION__, vector);
enter_critical_section();
if (oldstate)
*oldstate = false;
volatile uint32_t *mir = ICReg(vectorToController(vector), INTCON_MIR);
*mir = *mir & ~(1<<(vector % 32));
exit_critical_section();
#endif
return NO_ERROR;
}
void platform_irq(struct arm_iframe *frame)
{
PANIC_UNIMPLEMENTED;
#if 0
// get the current vector
unsigned int vector;
inc_critical_section();
// read from the first level int handler
vector = *ICReg(0, INTCON_SIR_IRQ);
// see if it's coming from the second level handler
if (vector == 0) {
vector = *ICReg(1, INTCON_SIR_IRQ) + 32;
}
// dprintf("platform_irq: spsr 0x%x, pc 0x%x, currthread %p, vector %d\n", frame->spsr, frame->pc, current_thread, vector);
// deliver the interrupt
enum handler_return ret;
ret = INT_NO_RESCHEDULE;
if (int_handler_table[vector].handler)
ret = int_handler_table[vector].handler(int_handler_table[vector].arg);
// ack the interrupt
if (vector >= 32) {
// interrupt is chained, so ack the second level first, and then the first
*ICReg(vector / 32, INTCON_ITR) = ~(1 << (vector % 32));
*ICReg(1, INTCON_CONTROL) |= 1;
vector = 0; // force the following code to ack the chained first level vector
}
*ICReg(0, INTCON_ITR) = ~(1 << vector);
*ICReg(0, INTCON_CONTROL) = 1;
if (ret == INT_RESCHEDULE)
thread_preempt();
dec_critical_section();
// dprintf("platform_irq: exit\n");
#endif
}
void platform_fiq(struct arm_iframe *frame)
{
PANIC_UNIMPLEMENTED;
}
void register_int_handler(unsigned int vector, int_handler handler, void *arg)
{
if (vector >= INT_VECTORS)
panic("register_int_handler: vector out of range %d\n", vector);
enter_critical_section();
int_handler_table[vector].handler = handler;
int_handler_table[vector].arg = arg;
exit_critical_section();
}

@ -0,0 +1,55 @@
/*
* 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 <err.h>
#include <debug.h>
#include <platform.h>
#include "platform_p.h"
#include <platform/integrator.h>
#include <arch/arm/mmu.h>
void platform_init_mmu_mappings(void)
{
}
void platform_early_init(void)
{
#if 0
/* do some memory map initialization */
addr_t addr;
arm_mmu_map_section(SDRAM_BASE, 0, MMU_FLAG_CACHED|MMU_FLAG_BUFFERED);
for (addr = SDRAM_BASE; addr < SDRAM_BASE + SDRAM_SIZE; addr += (1024*1024)) {
arm_mmu_map_section(addr, addr, MMU_FLAG_CACHED|MMU_FLAG_BUFFERED|MMU_FLAG_READWRITE);
}
/* initialize the interrupt controller */
platform_init_interrupts();
/* initialize the timer block */
platform_init_timer();
#endif
}
void platform_init(void)
{
}

@ -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 __PLATFORM_P_H
#define __PLATFORM_P_H
void platform_init_interrupts(void);
void platform_init_timer(void);
#endif

@ -0,0 +1,26 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
ARCH := arm
ARM_CPU := arm926ej-s
CPU := generic
INCLUDES += \
-I$(LOCAL_DIR)/include
OBJS += \
$(LOCAL_DIR)/debug.o \
$(LOCAL_DIR)/platform.o \
$(LOCAL_DIR)/interrupts.o \
$(LOCAL_DIR)/timer.o \
# $(LOCAL_DIR)/net.o \
# $(LOCAL_DIR)/console.o \
MEMBASE ?= 0x0
MEMSIZE ?= 0x08000000 # 128MB
LINKER_SCRIPT += \
$(BUILDDIR)/system-onesegment.ld

@ -0,0 +1,101 @@
/*
* 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 <err.h>
#include <kernel/thread.h>
#include <debug.h>
#include <platform.h>
#include <platform/interrupts.h>
#include <platform/timer.h>
#include <platform/integrator.h>
#include "platform_p.h"
static time_t system_time = 0;
static time_t tick_interval;
static uint32_t ticks_per_interval;
static platform_timer_callback t_callback;
static void *callback_arg;
status_t platform_set_periodic_timer(platform_timer_callback callback, void *arg, time_t interval)
{
#if 0
enter_critical_section();
t_callback = callback;
callback_arg = arg;
tick_interval = interval;
ticks_per_interval = interval * 32768 / 1000; // interval is in ms
OS_TIMER_CTRL_REG = 0; // stop it
OS_TIMER_TICK_VALUE_REG = ticks_per_interval;
OS_TIMER_CTRL_REG = (1<<3) | (1<<2) | (1<<1) | (1<<0);
exit_critical_section();
#endif
return NO_ERROR;
}
time_t current_time(void)
{
#if 0
time_t t;
uint32_t delta_ticks;
uint32_t delta_ticks2;
retry:
delta_ticks = OS_TIMER_TICK_COUNTER_REG;
t = system_time;
delta_ticks2 = OS_TIMER_TICK_COUNTER_REG;
if (delta_ticks2 > delta_ticks)
goto retry;
t += ((ticks_per_interval - delta_ticks2) * tick_interval) / ticks_per_interval;
return t;
#else
static time_t time = 0;
return time++;
#endif
}
static enum handler_return os_timer_tick(void *arg)
{
system_time += tick_interval;
// dprintf("os_timer_tick %d\n", system_time);
return t_callback(callback_arg, system_time);
}
void platform_init_timer(void)
{
#if 0
OS_TIMER_CTRL_REG = 0; // stop the timer if it's already running
register_int_handler(IRQ_OS_TIMER, &os_timer_tick, NULL);
unmask_interrupt(IRQ_OS_TIMER, NULL);
#endif
}

@ -0,0 +1,153 @@
/*
* Copyright (c) 2008, Google Inc.
* 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 <stdint.h>
#include <kernel/thread.h>
#include <platform/iomap.h>
#include <reg.h>
#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
#define A11S_CLK_CNTL_ADDR (MSM_CSR_BASE + 0x100)
#define A11S_CLK_SEL_ADDR (MSM_CSR_BASE + 0x104)
#define VDD_SVS_PLEVEL_ADDR (MSM_CSR_BASE + 0x124)
#define PLL2_L_VAL_ADDR (MSM_CLK_CTL_BASE + 0x33C)
#define SRC_SEL_PLL1 1 /* PLL1. */
#define SRC_SEL_PLL2 2 /* PLL2. */
#define SRC_SEL_PLL3 3 /* PLL3. Used for 7x25. */
#define DIV_4 3
#define DIV_2 1
#define WAIT_CNT 100
#define VDD_LEVEL 7
#define MIN_AXI_HZ 120000000
#define ACPU_800MHZ 41
void pll_request(unsigned pll, unsigned enable);
void axi_clock_init(unsigned rate);
/* The stepping frequencies have been choosen to make sure the step
* is <= 256 MHz for both turbo mode and normal mode targets. The
* table also assumes the ACPU is running at TCXO freq and AHB div is
* set to DIV_1.
*
* To use the tables:
* - Start at location 0/1 depending on clock source sel bit.
* - Set values till end of table skipping every other entry.
* - When you reach the end of the table, you are done scaling.
*
* TODO: Need to fix SRC_SEL_PLL1 for 7x25.
*/
uint32_t const clk_cntl_reg_val_7625[] = {
(WAIT_CNT << 16) | (SRC_SEL_PLL1 << 4) | DIV_4,
(WAIT_CNT << 16) | (SRC_SEL_PLL1 << 12) | (DIV_4 << 8),
(WAIT_CNT << 16) | (SRC_SEL_PLL1 << 12) | (DIV_2 << 8),
(WAIT_CNT << 16) | (SRC_SEL_PLL1 << 4) | DIV_2,
(WAIT_CNT << 16) | (SRC_SEL_PLL3 << 4) | DIV_2,
(WAIT_CNT << 16) | (SRC_SEL_PLL3 << 12) | (DIV_2 << 8),
};
uint32_t const clk_cntl_reg_val_7627[] = {
(WAIT_CNT << 16) | (SRC_SEL_PLL1 << 4) | DIV_4,
(WAIT_CNT << 16) | (SRC_SEL_PLL1 << 12) | (DIV_4 << 8),
(WAIT_CNT << 16) | (SRC_SEL_PLL1 << 12) | (DIV_2 << 8),
(WAIT_CNT << 16) | (SRC_SEL_PLL1 << 4) | DIV_2,
(WAIT_CNT << 16) | (SRC_SEL_PLL2 << 4) | DIV_2,
(WAIT_CNT << 16) | (SRC_SEL_PLL2 << 12) | (DIV_2 << 8),
};
uint32_t const clk_cntl_reg_val_7627T[] = {
(WAIT_CNT << 16) | (SRC_SEL_PLL1 << 4) | DIV_4,
(WAIT_CNT << 16) | (SRC_SEL_PLL1 << 12) | (DIV_4 << 8),
(WAIT_CNT << 16) | (SRC_SEL_PLL1 << 12) | (DIV_2 << 8),
(WAIT_CNT << 16) | (SRC_SEL_PLL1 << 4) | DIV_2,
(WAIT_CNT << 16) | (SRC_SEL_PLL2 << 4),
(WAIT_CNT << 16) | (SRC_SEL_PLL2 << 12),
};
/* Using DIV_4 for all cases to avoid worrying about turbo vs. normal
* mode. Able to use DIV_4 for all steps because it's the largest AND
* the final value. */
uint32_t const clk_sel_reg_val[] = {
DIV_4 << 1 | 1,
DIV_4 << 1 | 0,
DIV_4 << 1 | 0,
DIV_4 << 1 | 1,
DIV_4 << 1 | 1,
DIV_4 << 1 | 0,
};
void mdelay(unsigned msecs);
void acpu_clock_init(void)
{
unsigned i,clk;
#if (!ENABLE_NANDWRITE)
int *modem_stat_check = (MSM_SHARED_BASE + 0x14);
/* Wait for modem to be ready before clock init */
while (readl(modem_stat_check) != 1);
#endif
/* Increase VDD level to the final value. */
writel((1 << 7) | (VDD_LEVEL << 3), VDD_SVS_PLEVEL_ADDR);
#if (!ENABLE_NANDWRITE)
thread_sleep(1);
#else
mdelay(1);
#endif
/* Read clock source select bit. */
i = readl(A11S_CLK_SEL_ADDR) & 1;
clk = readl(PLL2_L_VAL_ADDR) & 0x3F;
/* Jump into table and set every other entry. */
for(; i < ARRAY_SIZE(clk_cntl_reg_val_7627); i += 2) {
#ifdef ENABLE_PLL3
writel(clk_cntl_reg_val_7625[i], A11S_CLK_CNTL_ADDR);
#else
if(clk == ACPU_800MHZ)
writel(clk_cntl_reg_val_7627T[i], A11S_CLK_CNTL_ADDR);
else
writel(clk_cntl_reg_val_7627[i], A11S_CLK_CNTL_ADDR);
#endif
/* Would need a dmb() here but the whole address space is
* strongly ordered, so it should be fine.
*/
writel(clk_sel_reg_val[i], A11S_CLK_SEL_ADDR);
#if (!ENABLE_NANDWRITE)
thread_sleep(1);
#else
mdelay(1);
#endif
}
}

228
lk/platform/msm7k/gpio.c Normal file

@ -0,0 +1,228 @@
/*
* 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.
*/
#include <debug.h>
#include <reg.h>
#include <platform/iomap.h>
#include <dev/gpio.h>
#define GPIO1_REG(off) (MSM_GPIO1_BASE + 0x800 + (off))
#define GPIO2_REG(off) (MSM_GPIO2_BASE + 0xC00 + (off))
/* output value */
#define GPIO_OUT_0 GPIO1_REG(0x00) /* gpio 15-0 */
#define GPIO_OUT_1 GPIO2_REG(0x00) /* gpio 42-16 */
#define GPIO_OUT_2 GPIO1_REG(0x04) /* gpio 67-43 */
#define GPIO_OUT_3 GPIO1_REG(0x08) /* gpio 94-68 */
#define GPIO_OUT_4 GPIO1_REG(0x0C) /* gpio 106-95 */
/* same pin map as above, output enable */
#define GPIO_OE_0 GPIO1_REG(0x10)
#define GPIO_OE_1 GPIO2_REG(0x08)
#define GPIO_OE_2 GPIO1_REG(0x14)
#define GPIO_OE_3 GPIO1_REG(0x18)
#define GPIO_OE_4 GPIO1_REG(0x1C)
/* same pin map as above, input read */
#define GPIO_IN_0 GPIO1_REG(0x34)
#define GPIO_IN_1 GPIO2_REG(0x20)
#define GPIO_IN_2 GPIO1_REG(0x38)
#define GPIO_IN_3 GPIO1_REG(0x3C)
#define GPIO_IN_4 GPIO1_REG(0x40)
/* same pin map as above, 1=edge 0=level interrup */
#define GPIO_INT_EDGE_0 GPIO1_REG(0x60)
#define GPIO_INT_EDGE_1 GPIO2_REG(0x50)
#define GPIO_INT_EDGE_2 GPIO1_REG(0x64)
#define GPIO_INT_EDGE_3 GPIO1_REG(0x68)
#define GPIO_INT_EDGE_4 GPIO1_REG(0x6C)
/* same pin map as above, 1=positive 0=negative */
#define GPIO_INT_POS_0 GPIO1_REG(0x70)
#define GPIO_INT_POS_1 GPIO2_REG(0x58)
#define GPIO_INT_POS_2 GPIO1_REG(0x74)
#define GPIO_INT_POS_3 GPIO1_REG(0x78)
#define GPIO_INT_POS_4 GPIO1_REG(0x7C)
/* same pin map as above, interrupt enable */
#define GPIO_INT_EN_0 GPIO1_REG(0x80)
#define GPIO_INT_EN_1 GPIO2_REG(0x60)
#define GPIO_INT_EN_2 GPIO1_REG(0x84)
#define GPIO_INT_EN_3 GPIO1_REG(0x88)
#define GPIO_INT_EN_4 GPIO1_REG(0x8C)
/* same pin map as above, write 1 to clear interrupt */
#define GPIO_INT_CLEAR_0 GPIO1_REG(0x90)
#define GPIO_INT_CLEAR_1 GPIO2_REG(0x68)
#define GPIO_INT_CLEAR_2 GPIO1_REG(0x94)
#define GPIO_INT_CLEAR_3 GPIO1_REG(0x98)
#define GPIO_INT_CLEAR_4 GPIO1_REG(0x9C)
/* same pin map as above, 1=interrupt pending */
#define GPIO_INT_STATUS_0 GPIO1_REG(0xA0)
#define GPIO_INT_STATUS_1 GPIO2_REG(0x70)
#define GPIO_INT_STATUS_2 GPIO1_REG(0xA4)
#define GPIO_INT_STATUS_3 GPIO1_REG(0xA8)
#define GPIO_INT_STATUS_4 GPIO1_REG(0xAC)
typedef struct gpioregs gpioregs;
struct gpioregs
{
unsigned out;
unsigned in;
unsigned int_status;
unsigned int_clear;
unsigned int_en;
unsigned int_edge;
unsigned int_pos;
unsigned oe;
};
static gpioregs GPIO_REGS[] = {
{
.out = GPIO_OUT_0,
.in = GPIO_IN_0,
.int_status = GPIO_INT_STATUS_0,
.int_clear = GPIO_INT_CLEAR_0,
.int_en = GPIO_INT_EN_0,
.int_edge = GPIO_INT_EDGE_0,
.int_pos = GPIO_INT_POS_0,
.oe = GPIO_OE_0,
},
{
.out = GPIO_OUT_1,
.in = GPIO_IN_1,
.int_status = GPIO_INT_STATUS_1,
.int_clear = GPIO_INT_CLEAR_1,
.int_en = GPIO_INT_EN_1,
.int_edge = GPIO_INT_EDGE_1,
.int_pos = GPIO_INT_POS_1,
.oe = GPIO_OE_1,
},
{
.out = GPIO_OUT_2,
.in = GPIO_IN_2,
.int_status = GPIO_INT_STATUS_2,
.int_clear = GPIO_INT_CLEAR_2,
.int_en = GPIO_INT_EN_2,
.int_edge = GPIO_INT_EDGE_2,
.int_pos = GPIO_INT_POS_2,
.oe = GPIO_OE_2,
},
{
.out = GPIO_OUT_3,
.in = GPIO_IN_3,
.int_status = GPIO_INT_STATUS_3,
.int_clear = GPIO_INT_CLEAR_3,
.int_en = GPIO_INT_EN_3,
.int_edge = GPIO_INT_EDGE_3,
.int_pos = GPIO_INT_POS_3,
.oe = GPIO_OE_3,
},
{
.out = GPIO_OUT_4,
.in = GPIO_IN_4,
.int_status = GPIO_INT_STATUS_4,
.int_clear = GPIO_INT_CLEAR_4,
.int_en = GPIO_INT_EN_4,
.int_edge = GPIO_INT_EDGE_4,
.int_pos = GPIO_INT_POS_4,
.oe = GPIO_OE_4,
},
};
static gpioregs *find_gpio(unsigned n, unsigned *bit)
{
if(n > 106)
return 0;
if(n > 94) {
*bit = 1 << (n - 95);
return GPIO_REGS + 4;
}
if(n > 67) {
*bit = 1 << (n - 68);
return GPIO_REGS + 3;
}
if(n > 42) {
*bit = 1 << (n - 43);
return GPIO_REGS + 2;
}
if(n > 15) {
*bit = 1 << (n - 16);
return GPIO_REGS + 1;
}
*bit = 1 << n;
return GPIO_REGS + 0;
}
int gpio_config(unsigned n, unsigned flags)
{
gpioregs *r;
unsigned b;
unsigned v;
if ((r = find_gpio(n, &b)) == 0)
return -1;
v = readl(r->oe);
if (flags & GPIO_OUTPUT) {
writel(v | b, r->oe);
} else {
writel(v & (~b), r->oe);
}
return 0;
}
void gpio_set(unsigned n, unsigned on)
{
gpioregs *r;
unsigned b;
unsigned v;
if((r = find_gpio(n, &b)) == 0)
return;
v = readl(r->out);
if(on) {
writel(v | b, r->out);
} else {
writel(v & (~b), r->out);
}
}
int gpio_get(unsigned n)
{
gpioregs *r;
unsigned b;
if((r = find_gpio(n, &b)) == 0) return 0;
return (readl(r->in) & b) ? 1 : 0;
}

@ -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.
* * 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 _PLATFORM_MSM7K_IOMAP_H_
#define _PLATFORM_MSM7K_IOMAP_H_
#define MSM_GPIO1_BASE 0xA9200000
#define MSM_GPIO2_BASE 0xA9300000
#define MSM_UART1_BASE 0xA9A00000
#define MSM_UART2_BASE 0xA9B00000
#define MSM_UART3_BASE 0xA9C00000
#define MSM_VIC_BASE 0xC0000000
#define MSM_GPT_BASE 0xC0100000
#define MSM_CSR_BASE 0xC0100000
#define MSM_CLK_CTL_BASE 0xA8600000
#define MSM_SHARED_BASE 0x00100000
#define MSM_SDC1_BASE 0xA0400000
#endif

@ -0,0 +1,95 @@
/*
* 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.
*/
#ifndef _PLATFORM_MSM7K_IRQS_H_
#define _PLATFORM_MSM7K_IRQS_H_
#define INT_A9_M2A_0 0
#define INT_A9_M2A_1 1
#define INT_A9_M2A_2 2
#define INT_A9_M2A_3 3
#define INT_A9_M2A_4 4
#define INT_A9_M2A_5 5
#define INT_A9_M2A_6 6
#define INT_GP_TIMER_EXP 7
#define INT_DEBUG_TIMER_EXP 8
#define INT_UART1 9
#define INT_UART2 10
#define INT_UART3 11
#define INT_UART1_RX 12
#define INT_UART2_RX 13
#define INT_UART3_RX 14
#define INT_USB_OTG 15
#define INT_MDDI_PRI 16
#define INT_MDDI_EXT 17
#define INT_MDDI_CLIENT 18
#define INT_MDP 19
#define INT_GRAPHICS 20
#define INT_ADM_AARM 21
#define INT_ADSP_A11 22
#define INT_ADSP_A9_A11 23
#define INT_SDC1_0 24
#define INT_SDC1_1 25
#define INT_SDC2_0 26
#define INT_SDC2_1 27
#define INT_KEYSENSE 28
#define INT_TCHSCRN_SSBI 29
#define INT_TCHSCRN1 30
#define INT_TCHSCRN2 31
#define INT_GPIO_GROUP1 (32 + 0)
#define INT_GPIO_GROUP2 (32 + 1)
#define INT_PWB_I2C (32 + 2)
#define INT_NAND_WR_ER_DONE (32 + 3)
#define INT_NAND_OP_DONE (32 + 4)
#define INT_SOFTRESET (32 + 5)
#define INT_PBUS_ARM11 (32 + 6)
#define INT_AXI_MPU_SMI (32 + 7)
#define INT_AXI_MPU_EBI1 (32 + 8)
#define INT_AD_HSSD (32 + 9)
#define INT_ARM11_PM (32 + 10)
#define INT_ARM11_DMA (32 + 11)
#define INT_TSIF_IRQ (32 + 12)
#define INT_UART1DM_IRQ (32 + 13)
#define INT_UART1DM_RX (32 + 14)
#define INT_USB_HS (32 + 15)
#define INT_SDC3_0 (32 + 16)
#define INT_SDC3_1 (32 + 17)
#define INT_SDC4_0 (32 + 18)
#define INT_SDC4_1 (32 + 19)
#define INT_UART2DM_RX (32 + 20)
#define INT_UART2DM_IRQ (32 + 21)
#define MSM_IRQ_BIT(irq) (1 << ((irq) & 31))
#define NR_IRQS 54
#endif

@ -0,0 +1,140 @@
/*
* 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 <debug.h>
#include <arch/arm.h>
#include <reg.h>
#include <kernel/thread.h>
#include <platform/interrupts.h>
#include <platform/irqs.h>
#include <platform/iomap.h>
#define VIC_REG(off) (MSM_VIC_BASE + (off))
#define VIC_INT_SELECT0 VIC_REG(0x0000) /* 1: FIQ, 0: IRQ */
#define VIC_INT_SELECT1 VIC_REG(0x0004) /* 1: FIQ, 0: IRQ */
#define VIC_INT_EN0 VIC_REG(0x0010)
#define VIC_INT_EN1 VIC_REG(0x0014)
#define VIC_INT_ENCLEAR0 VIC_REG(0x0020)
#define VIC_INT_ENCLEAR1 VIC_REG(0x0024)
#define VIC_INT_ENSET0 VIC_REG(0x0030)
#define VIC_INT_ENSET1 VIC_REG(0x0034)
#define VIC_INT_TYPE0 VIC_REG(0x0040) /* 1: EDGE, 0: LEVEL */
#define VIC_INT_TYPE1 VIC_REG(0x0044) /* 1: EDGE, 0: LEVEL */
#define VIC_INT_POLARITY0 VIC_REG(0x0050) /* 1: NEG, 0: POS */
#define VIC_INT_POLARITY1 VIC_REG(0x0054) /* 1: NEG, 0: POS */
#define VIC_NO_PEND_VAL VIC_REG(0x0060)
#define VIC_INT_MASTEREN VIC_REG(0x0064) /* 1: IRQ, 2: FIQ */
#define VIC_PROTECTION VIC_REG(0x006C) /* 1: ENABLE */
#define VIC_CONFIG VIC_REG(0x0068) /* 1: USE ARM1136 VIC */
#define VIC_IRQ_STATUS0 VIC_REG(0x0080)
#define VIC_IRQ_STATUS1 VIC_REG(0x0084)
#define VIC_FIQ_STATUS0 VIC_REG(0x0090)
#define VIC_FIQ_STATUS1 VIC_REG(0x0094)
#define VIC_RAW_STATUS0 VIC_REG(0x00A0)
#define VIC_RAW_STATUS1 VIC_REG(0x00A4)
#define VIC_INT_CLEAR0 VIC_REG(0x00B0)
#define VIC_INT_CLEAR1 VIC_REG(0x00B4)
#define VIC_SOFTINT0 VIC_REG(0x00C0)
#define VIC_SOFTINT1 VIC_REG(0x00C4)
#define VIC_IRQ_VEC_RD VIC_REG(0x00D0) /* pending int # */
#define VIC_IRQ_VEC_PEND_RD VIC_REG(0x00D4) /* pending vector addr */
#define VIC_IRQ_VEC_WR VIC_REG(0x00D8)
#define VIC_IRQ_IN_SERVICE VIC_REG(0x00E0)
#define VIC_IRQ_IN_STACK VIC_REG(0x00E4)
#define VIC_TEST_BUS_SEL VIC_REG(0x00E8)
struct ihandler {
int_handler func;
void *arg;
};
static struct ihandler handler[NR_IRQS];
void platform_init_interrupts(void)
{
writel(0xffffffff, VIC_INT_CLEAR0);
writel(0xffffffff, VIC_INT_CLEAR1);
writel(0, VIC_INT_SELECT0);
writel(0, VIC_INT_SELECT1);
writel(0xffffffff, VIC_INT_TYPE0);
writel(0xffffffff, VIC_INT_TYPE1);
writel(0, VIC_CONFIG);
writel(1, VIC_INT_MASTEREN);
}
enum handler_return platform_irq(struct arm_iframe *frame)
{
unsigned num;
enum handler_return ret;
num = readl(VIC_IRQ_VEC_RD);
num = readl(VIC_IRQ_VEC_PEND_RD);
if (num > NR_IRQS)
return 0;
writel(1 << (num & 31), (num > 31) ? VIC_INT_CLEAR1 : VIC_INT_CLEAR0);
ret = handler[num].func(handler[num].arg);
writel(0, VIC_IRQ_VEC_WR);
return ret;
}
void platform_fiq(struct arm_iframe *frame)
{
PANIC_UNIMPLEMENTED;
}
status_t mask_interrupt(unsigned int vector)
{
unsigned reg = (vector > 31) ? VIC_INT_ENCLEAR1 : VIC_INT_ENCLEAR0;
unsigned bit = 1 << (vector & 31);
writel(bit, reg);
return 0;
}
status_t unmask_interrupt(unsigned int vector)
{
unsigned reg = (vector > 31) ? VIC_INT_ENSET1 : VIC_INT_ENSET0;
unsigned bit = 1 << (vector & 31);
writel(bit, reg);
return 0;
}
void register_int_handler(unsigned int vector, int_handler func, void *arg)
{
if (vector >= NR_IRQS)
return;
enter_critical_section();
handler[vector].func = func;
handler[vector].arg = arg;
exit_critical_section();
}

471
lk/platform/msm7k/panel.c Normal file

@ -0,0 +1,471 @@
/* Copyright 2007, Google Inc. */
#include <debug.h>
#include <dev/gpio.h>
#include <kernel/thread.h>
#include <mddi.h>
#define MDDI_CLIENT_CORE_BASE 0x108000
#define LCD_CONTROL_BLOCK_BASE 0x110000
#define SPI_BLOCK_BASE 0x120000
#define I2C_BLOCK_BASE 0x130000
#define PWM_BLOCK_BASE 0x140000
#define GPIO_BLOCK_BASE 0x150000
#define SYSTEM_BLOCK1_BASE 0x160000
#define SYSTEM_BLOCK2_BASE 0x170000
#define MDDICAP0 (MDDI_CLIENT_CORE_BASE|0x00)
#define MDDICAP1 (MDDI_CLIENT_CORE_BASE|0x04)
#define MDDICAP2 (MDDI_CLIENT_CORE_BASE|0x08)
#define MDDICAP3 (MDDI_CLIENT_CORE_BASE|0x0C)
#define MDCAPCHG (MDDI_CLIENT_CORE_BASE|0x10)
#define MDCRCERC (MDDI_CLIENT_CORE_BASE|0x14)
#define TTBUSSEL (MDDI_CLIENT_CORE_BASE|0x18)
#define DPSET0 (MDDI_CLIENT_CORE_BASE|0x1C)
#define DPSET1 (MDDI_CLIENT_CORE_BASE|0x20)
#define DPSUS (MDDI_CLIENT_CORE_BASE|0x24)
#define DPRUN (MDDI_CLIENT_CORE_BASE|0x28)
#define SYSCKENA (MDDI_CLIENT_CORE_BASE|0x2C)
#define TESTMODE (MDDI_CLIENT_CORE_BASE|0x30)
#define FIFOMONI (MDDI_CLIENT_CORE_BASE|0x34)
#define INTMONI (MDDI_CLIENT_CORE_BASE|0x38)
#define MDIOBIST (MDDI_CLIENT_CORE_BASE|0x3C)
#define MDIOPSET (MDDI_CLIENT_CORE_BASE|0x40)
#define BITMAP0 (MDDI_CLIENT_CORE_BASE|0x44)
#define BITMAP1 (MDDI_CLIENT_CORE_BASE|0x48)
#define BITMAP2 (MDDI_CLIENT_CORE_BASE|0x4C)
#define BITMAP3 (MDDI_CLIENT_CORE_BASE|0x50)
#define BITMAP4 (MDDI_CLIENT_CORE_BASE|0x54)
#define SRST (LCD_CONTROL_BLOCK_BASE|0x00)
#define PORT_ENB (LCD_CONTROL_BLOCK_BASE|0x04)
#define START (LCD_CONTROL_BLOCK_BASE|0x08)
#define PORT (LCD_CONTROL_BLOCK_BASE|0x0C)
#define CMN (LCD_CONTROL_BLOCK_BASE|0x10)
#define GAMMA (LCD_CONTROL_BLOCK_BASE|0x14)
#define INTFLG (LCD_CONTROL_BLOCK_BASE|0x18)
#define INTMSK (LCD_CONTROL_BLOCK_BASE|0x1C)
#define MPLFBUF (LCD_CONTROL_BLOCK_BASE|0x20)
#define HDE_LEFT (LCD_CONTROL_BLOCK_BASE|0x24)
#define VDE_TOP (LCD_CONTROL_BLOCK_BASE|0x28)
#define PXL (LCD_CONTROL_BLOCK_BASE|0x30)
#define HCYCLE (LCD_CONTROL_BLOCK_BASE|0x34)
#define HSW (LCD_CONTROL_BLOCK_BASE|0x38)
#define HDE_START (LCD_CONTROL_BLOCK_BASE|0x3C)
#define HDE_SIZE (LCD_CONTROL_BLOCK_BASE|0x40)
#define VCYCLE (LCD_CONTROL_BLOCK_BASE|0x44)
#define VSW (LCD_CONTROL_BLOCK_BASE|0x48)
#define VDE_START (LCD_CONTROL_BLOCK_BASE|0x4C)
#define VDE_SIZE (LCD_CONTROL_BLOCK_BASE|0x50)
#define WAKEUP (LCD_CONTROL_BLOCK_BASE|0x54)
#define WSYN_DLY (LCD_CONTROL_BLOCK_BASE|0x58)
#define REGENB (LCD_CONTROL_BLOCK_BASE|0x5C)
#define VSYNIF (LCD_CONTROL_BLOCK_BASE|0x60)
#define WRSTB (LCD_CONTROL_BLOCK_BASE|0x64)
#define RDSTB (LCD_CONTROL_BLOCK_BASE|0x68)
#define ASY_DATA (LCD_CONTROL_BLOCK_BASE|0x6C)
#define ASY_DATB (LCD_CONTROL_BLOCK_BASE|0x70)
#define ASY_DATC (LCD_CONTROL_BLOCK_BASE|0x74)
#define ASY_DATD (LCD_CONTROL_BLOCK_BASE|0x78)
#define ASY_DATE (LCD_CONTROL_BLOCK_BASE|0x7C)
#define ASY_DATF (LCD_CONTROL_BLOCK_BASE|0x80)
#define ASY_DATG (LCD_CONTROL_BLOCK_BASE|0x84)
#define ASY_DATH (LCD_CONTROL_BLOCK_BASE|0x88)
#define ASY_CMDSET (LCD_CONTROL_BLOCK_BASE|0x8C)
#define MONI (LCD_CONTROL_BLOCK_BASE|0xB0)
#define Current (LCD_CONTROL_BLOCK_BASE|0xC0)
#define LCD (LCD_CONTROL_BLOCK_BASE|0xC4)
#define COMMAND (LCD_CONTROL_BLOCK_BASE|0xC8)
#define SSICTL (SPI_BLOCK_BASE|0x00)
#define SSITIME (SPI_BLOCK_BASE|0x04)
#define SSITX (SPI_BLOCK_BASE|0x08)
#define SSIRX (SPI_BLOCK_BASE|0x0C)
#define SSIINTC (SPI_BLOCK_BASE|0x10)
#define SSIINTS (SPI_BLOCK_BASE|0x14)
#define SSIDBG1 (SPI_BLOCK_BASE|0x18)
#define SSIDBG2 (SPI_BLOCK_BASE|0x1C)
#define SSIID (SPI_BLOCK_BASE|0x20)
#define I2CSETUP (I2C_BLOCK_BASE|0x00)
#define I2CCTRL (I2C_BLOCK_BASE|0x04)
#define TIMER0LOAD (PWM_BLOCK_BASE|0x00)
#define TIMER0VALUE (PWM_BLOCK_BASE|0x04)
#define TIMER0CONTROL (PWM_BLOCK_BASE|0x08)
#define TIMER0INTCLR (PWM_BLOCK_BASE|0x0C)
#define TIMER0RIS (PWM_BLOCK_BASE|0x10)
#define TIMER0MIS (PWM_BLOCK_BASE|0x14)
#define TIMER0BGLOAD (PWM_BLOCK_BASE|0x18)
#define PWM0OFF (PWM_BLOCK_BASE|0x1C)
#define TIMER1LOAD (PWM_BLOCK_BASE|0x20)
#define TIMER1VALUE (PWM_BLOCK_BASE|0x24)
#define TIMER1CONTROL (PWM_BLOCK_BASE|0x28)
#define TIMER1INTCLR (PWM_BLOCK_BASE|0x2C)
#define TIMER1RIS (PWM_BLOCK_BASE|0x30)
#define TIMER1MIS (PWM_BLOCK_BASE|0x34)
#define TIMER1BGLOAD (PWM_BLOCK_BASE|0x38)
#define PWM1OFF (PWM_BLOCK_BASE|0x3C)
#define TIMERITCR (PWM_BLOCK_BASE|0x60)
#define TIMERITOP (PWM_BLOCK_BASE|0x64)
#define PWMCR (PWM_BLOCK_BASE|0x68)
#define PWMID (PWM_BLOCK_BASE|0x6C)
#define PWMMON (PWM_BLOCK_BASE|0x70)
#define GPIODATA (GPIO_BLOCK_BASE|0x00)
#define GPIODIR (GPIO_BLOCK_BASE|0x04)
#define GPIOIS (GPIO_BLOCK_BASE|0x08)
#define GPIOIBE (GPIO_BLOCK_BASE|0x0C)
#define GPIOIEV (GPIO_BLOCK_BASE|0x10)
#define GPIOIE (GPIO_BLOCK_BASE|0x14)
#define GPIORIS (GPIO_BLOCK_BASE|0x18)
#define GPIOMIS (GPIO_BLOCK_BASE|0x1C)
#define GPIOIC (GPIO_BLOCK_BASE|0x20)
#define GPIOOMS (GPIO_BLOCK_BASE|0x24)
#define GPIOPC (GPIO_BLOCK_BASE|0x28)
#define GPIOID (GPIO_BLOCK_BASE|0x30)
#define WKREQ (SYSTEM_BLOCK1_BASE|0x00)
#define CLKENB (SYSTEM_BLOCK1_BASE|0x04)
#define DRAMPWR (SYSTEM_BLOCK1_BASE|0x08)
#define INTMASK (SYSTEM_BLOCK1_BASE|0x0C)
#define GPIOSEL (SYSTEM_BLOCK2_BASE|0x00)
struct init_table {
unsigned int reg;
unsigned int val;
};
static struct init_table toshiba_480x640_init_table[] = {
{ DPSET0, 0x4BEC0066 }, // # MDC.DPSET0 # Setup DPLL parameters
{ DPSET1, 0x00000113 }, // # MDC.DPSET1
{ DPSUS, 0x00000000 }, // # MDC.DPSUS # Set DPLL oscillation enable
{ DPRUN, 0x00000001 }, // # MDC.DPRUN # Release reset signal for DPLL
{ 0, 14 }, // wait_ms(14);
{ SYSCKENA, 0x00000001 }, // # MDC.SYSCKENA # Enable system clock output
{ CLKENB, 0x000000EF }, // # SYS.CLKENB # Enable clocks for each module (without DCLK , i2cCLK)
{ GPIO_BLOCK_BASE, 0x03FF0000 }, // # GPI .GPIODATA # GPIO2(RESET_LCD_N) set to 0 , GPIO3(eDRAM_Power) set to 0
{ GPIODIR, 0x0000024D }, // # GPI .GPIODIR # Select direction of GPIO port (0,2,3,6,9 output)
{ SYSTEM_BLOCK2_BASE, 0x00000173 }, // # SYS.GPIOSEL # GPIO port multiplexing control
{ GPIOPC, 0x03C300C0 }, // # GPI .GPIOPC # GPIO2,3 PD cut
{ SYSTEM_BLOCK1_BASE, 0x00000000 }, // # SYS.WKREQ # Wake-up request event is VSYNC alignment
{ GPIOIS, 0x00000000 }, // # GPI .GPIOIS # Set interrupt sense of GPIO
{ GPIOIEV, 0x00000001 }, // # GPI .GPIOIEV # Set interrupt event of GPIO
{ GPIOIC, 0x000003FF }, // # GPI .GPIOIC # GPIO interrupt clear
{ GPIO_BLOCK_BASE, 0x00060006 }, // # GPI .GPIODATA # Release LCDD reset
{ GPIO_BLOCK_BASE, 0x00080008 }, // # GPI .GPIODATA # eDRAM VD supply
{ GPIO_BLOCK_BASE, 0x02000200 }, // # GPI .GPIODATA # TEST LED ON
{ DRAMPWR, 0x00000001 }, // # SYS.DRAMPWR # eDRAM power up
{ TIMER0CONTROL, 0x00000060 }, // # PWM.Timer0Control # PWM0 output stop
{ PWM_BLOCK_BASE, 0x00001388 }, // # PWM.Timer0Load # PWM0 10kHz , Duty 99 (BackLight OFF)
//{PWM0OFF, 0x00000001 }, // # PWM.PWM0OFF
#if 0
{ PWM0OFF, 0x00001387 }, // SURF 100% backlight
{ PWM0OFF, 0x00000000 }, // FFA 100% backlight
#endif
{ PWM0OFF, 0x000009C3 }, // 50% BL
{ TIMER1CONTROL, 0x00000060 }, // # PWM.Timer1Control # PWM1 output stop
{ TIMER1LOAD, 0x00001388 }, // # PWM.Timer1Load # PWM1 10kHz , Duty 99 (BackLight OFF)
//{PWM1OFF, 0x00000001 }, // # PWM.PWM1OFF
{ PWM1OFF, 0x00001387 },
{ TIMER0CONTROL, 0x000000E0 }, // # PWM.Timer0Control # PWM0 output start
{ TIMER1CONTROL, 0x000000E0 }, // # PWM.Timer1Control # PWM1 output start
{ PWMCR, 0x00000003 }, // # PWM.PWMCR # PWM output enable
{ 0, 1 }, // wait_ms(1);
{ SPI_BLOCK_BASE, 0x00000799 }, // # SPI .SSICTL # SPI operation mode setting
{ SSITIME, 0x00000100 }, // # SPI .SSITIME # SPI serial interface timing setting
{ SPI_BLOCK_BASE, 0x0000079b }, // # SPI .SSICTL # Set SPI active mode
{ SSITX, 0x00000000 }, // # SPI.SSITX # Release from Deep Stanby mode
{ 0, 1 }, // wait_ms(1);
{ SSITX, 0x00000000 }, // # SPI.SSITX
{ 0, 1 }, // wait_ms(1);
{ SSITX, 0x00000000 }, // # SPI.SSITX
{ 0, 1 }, // wait_ms(1);
{ SSITX, 0x000800BA }, // # SPI.SSITX *NOTE 1 # Command setting of SPI block
{ SSITX, 0x00000111 }, // # Display mode setup(1) : Normaly Black
{ SSITX, 0x00080036 }, // # Command setting of SPI block
{ SSITX, 0x00000100 }, // # Memory access control
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800BB }, // # Command setting of SPI block
{ SSITX, 0x00000100 }, // # Display mode setup(2)
{ SSITX, 0x0008003A }, // # Command setting of SPI block
{ SSITX, 0x00000160 }, // # RGB Interface data format
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800BF }, // # Command setting of SPI block
{ SSITX, 0x00000100 }, // # Drivnig method
{ SSITX, 0x000800B1 }, // # Command setting of SPI block
{ SSITX, 0x0000015D }, // # Booster operation setup
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800B2 }, // # Command setting of SPI block
{ SSITX, 0x00000133 }, // # Booster mode setup
{ SSITX, 0x000800B3 }, // # Command setting of SPI block
{ SSITX, 0x00000122 }, // # Booster frequencies setup
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800B4 }, // # Command setting of SPI block
{ SSITX, 0x00000102 }, // # OP-amp capability/System clock freq. division setup
{ SSITX, 0x000800B5 }, // # Command setting of SPI block
{ SSITX, 0x0000011F }, // # VCS Voltage adjustment (1C->1F for Rev 2)
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800B6 }, // # Command setting of SPI block
{ SSITX, 0x00000128 }, // # VCOM Voltage adjustment
{ SSITX, 0x000800B7 }, // # Command setting of SPI block
{ SSITX, 0x00000103 }, // # Configure an external display signal
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800B9 }, // # Command setting of SPI block
{ SSITX, 0x00000120 }, // # DCCK/DCEV timing setup
{ SSITX, 0x000800BD }, // # Command setting of SPI block
{ SSITX, 0x00000102 }, // # ASW signal control
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800BE }, // # Command setting of SPI block
{ SSITX, 0x00000100 }, // # Dummy display (white/black) count setup for QUAD Data operation
{ SSITX, 0x000800C0 }, // # Command setting of SPI block
{ SSITX, 0x00000111 }, // # wait_ms(-out FR count setup (A)
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800C1 }, // # Command setting of SPI block
{ SSITX, 0x00000111 }, // # wait_ms(-out FR count setup (B)
{ SSITX, 0x000800C2 }, // # Command setting of SPI block
{ SSITX, 0x00000111 }, // # wait_ms(-out FR count setup (C)
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800C3 }, // # Command setting of SPI block
{ SSITX, 0x0008010A }, // # wait_ms(-in line clock count setup (D)
{ SSITX, 0x0000010A }, //
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800C4 }, // # Command setting of SPI block
{ SSITX, 0x00080160 }, // # Seep-in line clock count setup (E)
{ SSITX, 0x00000160 }, //
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800C5 }, // # Command setting of SPI block
{ SSITX, 0x00080160 }, // # wait_ms(-in line clock count setup (F)
{ SSITX, 0x00000160 }, //
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800C6 }, // # Command setting of SPI block
{ SSITX, 0x00080160 }, // # wait_ms(-in line clock setup (G)
{ SSITX, 0x00000160 }, //
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800C7 }, // # Command setting of SPI block
{ SSITX, 0x00080133 }, // # Gamma 1 fine tuning (1)
{ SSITX, 0x00000143 }, //
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800C8 }, // # Command setting of SPI block
{ SSITX, 0x00000144 }, // # Gamma 1 fine tuning (2)
{ SSITX, 0x000800C9 }, // # Command setting of SPI block
{ SSITX, 0x00000133 }, // # Gamma 1 inclination adjustment
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800CA }, // # Command setting of SPI block
{ SSITX, 0x00000100 }, // # Gamma 1 blue offset adjustment
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800EC }, // # Command setting of SPI block
{ SSITX, 0x00080102 }, // # Total number of horizontal clock cycles (1) [PCLK Sync. VGA setting]
{ SSITX, 0x00000118 }, //
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800CF }, // # Command setting of SPI block
{ SSITX, 0x00000101 }, // # Blanking period control (1) [PCLK Sync. Table1 for VGA]
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800D0 }, // # Command setting of SPI block
{ SSITX, 0x00080110 }, // # Blanking period control (2) [PCLK Sync. Table1 for VGA]
{ SSITX, 0x00000104 }, //
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800D1 }, // # Command setting of SPI block
{ SSITX, 0x00000101 }, // # CKV timing control on/off [PCLK Sync. Table1 for VGA]
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800D2 }, // # Command setting of SPI block
{ SSITX, 0x00080100 }, // # CKV1,2 timing control [PCLK Sync. Table1 for VGA]
{ SSITX, 0x0000013A }, //
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800D3 }, // # Command setting of SPI block
{ SSITX, 0x00080100 }, // # OEV timing control [PCLK Sync. Table1 for VGA]
{ SSITX, 0x0000013A }, //
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800D4 }, // # Command setting of SPI block
{ SSITX, 0x00080124 }, // # ASW timing control (1) [PCLK Sync. Table1 for VGA]
{ SSITX, 0x0000016E }, //
{ 0, 1 }, // wait_ms(1); // # Wait SPI fifo empty
{ SSITX, 0x000800D5 }, // # Command setting of SPI block
{ SSITX, 0x00000124 }, // # ASW timing control (2) [PCLK Sync. Table1 for VGA]
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800ED }, // # Command setting of SPI block
{ SSITX, 0x00080101 }, // # Total number of horizontal clock cycles (2) [PCLK Sync. Table1 for QVGA ]
{ SSITX, 0x0000010A }, //
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800D6 }, // # Command setting of SPI block
{ SSITX, 0x00000101 }, // # Blanking period control (1) [PCLK Sync. Table2 for QVGA]
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800D7 }, // # Command setting of SPI block
{ SSITX, 0x00080110 }, // # Blanking period control (2) [PCLK Sync. Table2 for QVGA]
{ SSITX, 0x0000010A }, //
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800D8 }, // # Command setting of SPI block
{ SSITX, 0x00000101 }, // # CKV timing control on/off [PCLK Sync. Table2 for QVGA]
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800D9 }, // # Command setting of SPI block
{ SSITX, 0x00080100 }, // # CKV1,2 timing control [PCLK Sync. Table2 for QVGA]
{ SSITX, 0x00000114 }, //
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800DE }, // # Command setting of SPI block
{ SSITX, 0x00080100 }, // # OEV timing control [PCLK Sync. Table2 for QVGA]
{ SSITX, 0x00000114 }, //
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800DF }, // # Command setting of SPI block
{ SSITX, 0x00080112 }, // # ASW timing control (1) [PCLK Sync. Table2 for QVGA]
{ SSITX, 0x0000013F }, //
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800E0 }, // # Command setting of SPI block
{ SSITX, 0x0000010B }, // # ASW timing control (2) [PCLK Sync. Table2 for QVGA]
{ SSITX, 0x000800E2 }, // # Command setting of SPI block
{ SSITX, 0x00000101 }, // # Built-in oscillator frequency division setup [Frequency division ratio : 2 (60Hq)
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800E3 }, // # Command setting of SPI block
{ SSITX, 0x00000136 }, // # Built-in oscillator clock count setup
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800E4 }, // # Command setting of SPI block
{ SSITX, 0x00080100 }, // # CKV timing control for using build-in osc
{ SSITX, 0x00000103 }, //
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800E5 }, // # Command setting of SPI block
{ SSITX, 0x00080102 }, // # OEV timing control for using build-in osc
{ SSITX, 0x00000104 }, //
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800E6 }, // # Command setting of SPI block
{ SSITX, 0x00000103 }, // # DCEV timing control for using build-in osc
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800E7 }, // # Command setting of SPI block
{ SSITX, 0x00080104 }, // # ASW timing setup for using build-in osc(1)
{ SSITX, 0x0000010A }, //
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800E8 }, // # Command setting of SPI block
{ SSITX, 0x00000104 }, // # ASW timing setup for using build-in osc(2)
{ CLKENB, 0x000001EF }, // # SYS.CLKENB # DCLK enable
{ START, 0x00000000 }, // # LCD.START # LCDC wait_ms( mode
{ WRSTB, 0x0000003F }, // # LCD.WRSTB # write_client_reg( strobe
{ RDSTB, 0x00000432 }, // # LCD.RDSTB # Read strobe
{ PORT_ENB, 0x00000002 }, // # LCD.PORT_ENB # Asynchronous port enable
{ VSYNIF, 0x00000000 }, // # LCD.VSYNCIF # VSYNC I/F mode set
{ ASY_DATA, 0x80000000 }, // # LCD.ASY_DATx # Index setting of SUB LCDD
{ ASY_DATB, 0x00000001 }, // # Oscillator start
{ ASY_CMDSET, 0x00000005 }, // # LCD.ASY_CMDSET # Direct command transfer enable
{ ASY_CMDSET, 0x00000004 }, // # LCD.ASY_CMDSET # Direct command transfer disable
{ 0, 10 }, // wait_ms(10);
{ ASY_DATA, 0x80000000 }, // # LCD.ASY_DATx # DUMMY write_client_reg(<28>@*NOTE2
{ ASY_DATB, 0x80000000 }, //
{ ASY_DATC, 0x80000000 }, //
{ ASY_DATD, 0x80000000 }, //
{ ASY_CMDSET, 0x00000009 }, // # LCD.ASY_CMDSET
{ ASY_CMDSET, 0x00000008 }, // # LCD.ASY_CMDSET
{ ASY_DATA, 0x80000007 }, // # LCD.ASY_DATx # Index setting of SUB LCDD
{ ASY_DATB, 0x00004005 }, // # LCD driver control
{ ASY_CMDSET, 0x00000005 }, // # LCD.ASY_CMDSET # Direct command transfer enable
{ ASY_CMDSET, 0x00000004 }, // # LCD.ASY_CMDSET # Direct command transfer disable
{ 0, 20 }, // wait_ms(20);
{ ASY_DATA, 0x80000059 }, // # LCD.ASY_DATx # Index setting of SUB LCDD
{ ASY_DATB, 0x00000000 }, // # LTPS I/F control
{ ASY_CMDSET, 0x00000005 }, // # LCD.ASY_CMDSET # Direct command transfer enable
{ ASY_CMDSET, 0x00000004 }, // # LCD.ASY_CMDSET # Direct command transfer disable
{ VSYNIF, 0x00000001 }, // # LCD.VSYNCIF # VSYNC I/F mode OFF
{ PORT_ENB, 0x00000001 }, // # LCD.PORT_ENB # SYNC I/F output select
/******************************/
{ VSYNIF, 0x00000001 }, // VSYNC I/F mode OFF
{ PORT_ENB, 0x00000001 }, // SYNC I/F mode ON
{ BITMAP1, 0x01E000F0 }, // MDC.BITMAP2 ); // Setup of PITCH size to Frame buffer1
{ BITMAP2, 0x01E000F0 }, // MDC.BITMAP3 ); // Setup of PITCH size to Frame buffer2
{ BITMAP3, 0x01E000F0 }, // MDC.BITMAP4 ); // Setup of PITCH size to Frame buffer3
{ BITMAP4, 0x00DC00B0 }, // MDC.BITMAP5 ); // Setup of PITCH size to Frame buffer4
{ CLKENB, 0x000001EF }, // SYS.CLKENB ); // DCLK supply
{ PORT_ENB, 0x00000001 }, // LCD.PORT_ENB ); // Synchronous port enable
{ PORT, 0x00000004 }, // LCD.PORT ); // Polarity of DE is set to high active
{ PXL, 0x00000002 }, // LCD.PXL ); // ACTMODE 2 set (1st frame black data output)
{ MPLFBUF, 0x00000000 }, // LCD.MPLFBUF ); // Select the reading buffer
{ HCYCLE, 0x0000010b }, // LCD.HCYCLE ); // Setup to VGA size
{ HSW, 0x00000003 }, // LCD.HSW
{ HDE_START, 0x00000007 }, // LCD.HDE_START
{ HDE_SIZE, 0x000000EF }, // LCD.HDE_SIZE
{ VCYCLE, 0x00000285 }, // LCD.VCYCLE
{ VSW, 0x00000001 }, // LCD.VSW
{ VDE_START, 0x00000003 }, // LCD.VDE_START
{ VDE_SIZE, 0x0000027F }, // LCD.VDE_SIZE
{ START, 0x00000001 }, // LCD.START ); // LCDC - Pixel data transfer start
{ 0, 10 }, // wait_ms( 10 );
{ SSITX, 0x000800BC }, // SPI.SSITX ); // Command setting of SPI block
{ SSITX, 0x00000180 }, // Display data setup
{ SSITX, 0x0008003B }, // Command setting of SPI block
{ SSITX, 0x00000100 }, // Quad Data configuration - VGA
{ 0, 1 }, // wait_ms( 1 ); // Wait SPI fifo empty
{ SSITX, 0x000800B0 }, // Command setting of SPI block
{ SSITX, 0x00000116 }, // Power supply ON/OFF control
{ 0, 1 }, // wait_ms( 1 ); // Wait SPI fifo empty
{ SSITX, 0x000800B8 }, // Command setting of SPI block
{ SSITX, 0x000801FF }, // Output control
{ SSITX, 0x000001F5 },
{ 0, 1 }, // wait_ms( 1); // Wait SPI fifo empty
{ SSITX, 0x00000011 }, // wait_ms(-out (Command only)
{ SSITX, 0x00000029 }, // Display on (Command only)
{ SYSTEM_BLOCK1_BASE, 0x00000002 }, // # wakeREQ -> GPIO
{ 0, 0 }
};
static void _panel_init(struct init_table *init_table)
{
unsigned n;
dprintf(INFO, "panel_init()\n");
n = 0;
while (init_table[n].reg != 0 || init_table[n].val != 0) {
if (init_table[n].reg != 0)
mddi_remote_write(init_table[n].val, init_table[n].reg);
else
mdelay(init_table[n].val);
n++;
}
dprintf(INFO, "panel_init() done\n");
}
void panel_init(struct mddi_client_caps *client_caps)
{
switch(client_caps->manufacturer_name) {
case 0xd263: // Toshiba
dprintf(INFO, "Found Toshiba panel\n");
_panel_init(toshiba_480x640_init_table);
break;
case 0x4474: //??
if (client_caps->product_code == 0xc065)
dprintf(INFO, "Found WVGA panel\n");
break;
}
}
void panel_poweron(void)
{
gpio_set(88, 0);
gpio_config(88, GPIO_OUTPUT);
udelay(10);
gpio_set(88, 1);
mdelay(10);
//mdelay(1000); // uncomment for second stage boot
}
void panel_backlight(int on)
{}

@ -0,0 +1,80 @@
/*
* 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.
*/
#include <debug.h>
#include <kernel/thread.h>
#include <platform/debug.h>
#include <mddi.h>
#include <dev/fbcon.h>
static struct fbcon_config *fb_config;
void platform_init_interrupts(void);
void platform_init_timer();
void uart3_clock_init(void);
void uart_init(void);
void acpu_clock_init(void);
void mddi_clock_init(unsigned num, unsigned rate);
void platform_early_init(void)
{
//uart3_clock_init();
//uart_init();
platform_init_interrupts();
platform_init_timer();
}
void platform_init(void)
{
dprintf(INFO, "platform_init()\n");
acpu_clock_init();
}
void display_init(void)
{
#if DISPLAY_TYPE_MDDI
fb_config = mddi_init();
ASSERT(fb_config);
fbcon_setup(fb_config);
#endif
#if DISPLAY_TYPE_LCDC
fb_config = lcdc_init();
ASSERT(fb_config);
fbcon_setup(fb_config);
#endif
}

@ -0,0 +1,24 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
ARCH := arm
ARM_CPU := arm1136j-s
CPU := generic
MMC_SLOT := 1
DEFINES += MMC_SLOT=$(MMC_SLOT)
INCLUDES += -I$(LOCAL_DIR)/include
MODULES += dev/fbcon
OBJS += \
$(LOCAL_DIR)/platform.o \
$(LOCAL_DIR)/interrupts.o \
$(LOCAL_DIR)/gpio.o \
$(LOCAL_DIR)/panel.o \
$(LOCAL_DIR)/acpuclock.o
LINKER_SCRIPT += $(BUILDDIR)/system-onesegment.ld
include platform/msm_shared/rules.mk

@ -0,0 +1,175 @@
/*
* 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.
* * 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 <stdint.h>
#include <kernel/thread.h>
#include <platform/iomap.h>
#include <reg.h>
#define REG_BASE(off) (MSM_CLK_CTL_BASE + (off))
#define REG(off) (MSM_CLK_CTL_SH2_BASE + (off))
#define PLL_ENA_REG REG(0x0264)
#define PLL2_STATUS_BASE_REG REG_BASE(0x0350)
#define SH2_OWN_ROW2_BASE_REG REG_BASE(0x0424)
/* Macros to select PLL2 with divide by 1 */
#define ACPU_SRC_SEL 3
#define ACPU_SRC_DIV 0
#define BIT(n) (1 << (n))
#define VREG_CONFIG (BIT(7) | BIT(6)) /* Enable VREG, pull-down if disabled. */
#define VREG_DATA (VREG_CONFIG | (VREF_SEL << 5))
#define VREF_SEL 1 /* 0: 0.625V (50mV step), 1: 0.3125V (25mV step). */
#define V_STEP (25 * (2 - VREF_SEL)) /* Minimum voltage step size. */
#define MV(mv) ((mv) / (!((mv) % V_STEP)))
/* mv = (750mV + (raw * 25mV)) * (2 - VREF_SEL) */
#define VDD_RAW(mv) (((MV(mv) / V_STEP) - 30) | VREG_DATA)
void spm_init(void)
{
writel(0x05, MSM_SAW_BASE + 0x10); /* MSM_SPM_REG_SAW_CFG */
writel(0x18, MSM_SAW_BASE + 0x14); /* MSM_SPM_REG_SAW_SPM_CTL */
writel(0x00006666, MSM_SAW_BASE + 0x18); /* MSM_SPM_REG_SAW_SPM_SLP_TMR_DLY */
writel(0xFF000666, MSM_SAW_BASE + 0x1C); /* MSM_SPM_REG_SAW_SPM_WAKE_TMR_DLY */
writel(0x01, MSM_SAW_BASE + 0x24); /* MSM_SPM_REG_SAW_SLP_CLK_EN */
writel(0x03, MSM_SAW_BASE + 0x28); /* MSM_SPM_REG_SAW_SLP_HSFS_PRECLMP_EN */
writel(0x00, MSM_SAW_BASE + 0x2C); /* MSM_SPM_REG_SAW_SLP_HSFS_POSTCLMP_EN */
writel(0x01, MSM_SAW_BASE + 0x30); /* MSM_SPM_REG_SAW_SLP_CLMP_EN */
writel(0x00, MSM_SAW_BASE + 0x34); /* MSM_SPM_REG_SAW_SLP_RST_EN */
writel(0x00, MSM_SAW_BASE + 0x38); /* MSM_SPM_REG_SAW_SPM_MPM_CFG */
}
/* Configures msmc2 voltage. vlevel is in mV */
void msmc2_config(unsigned vlevel)
{
unsigned val;
val = readl(MSM_SAW_BASE + 0x08); /* MSM_SPM_REG_SAW_VCTL */
val &= ~0xFF;
val |= VDD_RAW(vlevel);
writel(val, MSM_SAW_BASE + 0x08); /* MSM_SPM_REG_SAW_VCTL */
/* Wait for PMIC state to return to idle and for VDD to stabilize */
while(((readl(MSM_SAW_BASE + 0x0C) >> 0x20) & 0x3) != 0);
udelay(160);
}
void enable_pll(unsigned num)
{
unsigned reg_val;
reg_val = readl(PLL_ENA_REG);
reg_val |= (1 << num);
writel(reg_val, PLL_ENA_REG);
/* Wait until PLL is enabled */
while ((readl(PLL2_STATUS_BASE_REG) & (1 << 16)) == 0);
}
void acpu_clock_init(void)
{
unsigned reg_clksel, reg_clkctl, src_sel;
/* Fixing msmc2 voltage */
spm_init();
msmc2_config(1200); /* Setting msmc2 1.2V */
/* Enable pll 2 */
enable_pll(2);
reg_clksel = readl(SCSS_CLK_SEL);
/* CLK_SEL_SRC1NO */
src_sel = reg_clksel & 1;
/* Program clock source and divider. */
reg_clkctl = readl(SCSS_CLK_CTL);
reg_clkctl &= ~(0xFF << (8 * src_sel));
reg_clkctl |= ACPU_SRC_SEL<< (4 + 8 * src_sel);
reg_clkctl |= ACPU_SRC_DIV<< (0 + 8 * src_sel);
writel(reg_clkctl, SCSS_CLK_CTL);
/* Toggle clock source. */
reg_clksel ^= 1;
/* Program clock source selection. */
writel(reg_clksel, SCSS_CLK_SEL);
}
void hsusb_clock_init(void)
{
int val = 0;
unsigned sh2_own_row2;
unsigned sh2_own_row2_hsusb_mask = (1 << 11);
sh2_own_row2 = readl(SH2_OWN_ROW2_BASE_REG);
if(sh2_own_row2 & sh2_own_row2_hsusb_mask)
{
/* USB local clock control enabled */
/* Set value in MD register */
val = 0x5DF;
writel(val, SH2_USBH_MD_REG);
/* Set value in NS register */
val = 1 << 8;
val = val | readl(SH2_USBH_NS_REG);
writel(val, SH2_USBH_NS_REG);
val = 1 << 11;
val = val | readl(SH2_USBH_NS_REG);
writel(val, SH2_USBH_NS_REG);
val = 1 << 9;
val = val | readl(SH2_USBH_NS_REG);
writel(val, SH2_USBH_NS_REG);
val = 1 << 13;
val = val | readl(SH2_USBH_NS_REG);
writel(val, SH2_USBH_NS_REG);
/* Enable USBH_P_CLK */
val = 1 << 25;
val = val | readl(SH2_GLBL_CLK_ENA_SC);
writel(val, SH2_GLBL_CLK_ENA_SC);
}
else
{
/* USB local clock control not enabled; use proc comm */
usb_clock_init();
}
}
void adm_enable_clock(void)
{
unsigned int val=0;
/* Enable ADM_CLK */
val = 1 << 5;
val = val | readl(SH2_GLBL_CLK_ENA_SC);
writel(val, SH2_GLBL_CLK_ENA_SC);
}

@ -0,0 +1,699 @@
/*
* 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.
*/
/* TODO:
* - style cleanup
* - do we need to do *all* of this at boot?
*/
.text
.code 32
#define DSB .byte 0x4f, 0xf0, 0x7f, 0xf5
#define ISB .byte 0x6f, 0xf0, 0x7f, 0xf5
/*
; LVT Ring Osc counter
; used to determine sense amp settings
; Clobbers registers r0, r4, r5, r6, r7, r9, r10, r11
*/
.equ CLK_CTL_BASE, 0xA8600000
.equ A_GLBL_CLK_ENA, 0x0000
.equ A_PRPH_WEB_NS_REG,0x0080
.equ A_MSM_CLK_RINGOSC,0x00D0
.equ A_TCXO_CNT, 0x00D4
.equ A_TCXO_CNT_DONE, 0x00D8
.equ A_RINGOSC_CNT, 0x00DC
.equ A_MISC_CLK_CTL, 0x0108
.equ CLK_TEST, 0xA8600114
.equ SPSS_CSR_BASE, 0xAC100000
.equ A_SCRINGOSC, 0x0510
//;; Number of TCXO cycles to count ring oscillations
.equ TCXO_CNT_VAL, 0x100
//; Halcyon addresses
.equ TCSR_CONF_FUSE_1, 0xAB600060 //; TCSR_CONF_FUSE_1 register
.equ TCSR_CONF_FUSE_4, 0xAB60006C //; TCSR_CONF_FUSE_4 register
//; SCORPION_L1_ACC (1:0) Fuses bit location
.equ L1_ACC_BIT_0, 12 //;12th bit of TCSR_CONF_FUSE_4
.equ L1_ACC_BIT_1, 13 //;13th bit of TCSR_CONF_FUSE_4
//; SCORPION_L2_ACC (2:0) Fuses bit location
.equ L2_ACC_BIT_0, 25 //;25th bit of TCSR_CONF_FUSE_1
.equ L2_ACC_BIT_1, 10 //;10th bit of TCSR_CONF_FUSE_4
.equ L2_ACC_BIT_2, 11 //;11th bit of TCSR_CONF_FUSE_4
//; CP15: PVR2F0 values according to SCORPION_L1_ACC (1:0)
.equ PVR2F0_00, 0x00000000
.equ PVR2F0_01, 0x04000000
.equ PVR2F0_10, 0x08000000
.equ PVR2F0_11, 0x0C000000
//; CP15: PVR2F1 values according to SCORPION_L1_ACC (1:0)
.equ PVR2F1_00, 0x00000008
.equ PVR2F1_01, 0x00000008
.equ PVR2F1_10, 0x00000208
.equ PVR2F1_11, 0x00000208
//; CP15: PVR0F2 values according to SCORPION_L1_ACC (1:0)
.equ PVR0F2_00, 0x00000000
.equ PVR0F2_01, 0x00000000
.equ PVR0F2_10, 0x00000200
.equ PVR0F2_11, 0x00000200
//; CP15: PVR0F0 values according to SCORPION_L1_ACC (1:0)
.equ PVR0F0_00, 0x7F000000
.equ PVR0F0_01, 0x7F000400
.equ PVR0F0_10, 0x7F000000
.equ PVR0F0_11, 0x7F000400
//; CP15: L2VR3F1 values according to SCORPION_L2_ACC (2:0)
.equ L2VR3F1_000, 0x00FFFF60
.equ L2VR3F1_001, 0x00FFFF40
.equ L2VR3F1_010, 0x00FFFC60
.equ L2VR3F1_011, 0x00FFFC40
.equ L2VR3F1_100, 0x00FCFF60
.equ L2VR3F1_101, 0x00FCFF40
.equ L2VR3F1_110, 0x00FCFC60
.equ L2VR3F1_111, 0x00FCFC40
.globl SET_SA
SET_SA:
//;--------------------------------------------------------------------
//; Fuse bits used to determine sense amp settings
//;--------------------------------------------------------------------
//; Reading L1_ACC
LDR r4, = 0x0
//; Read L1_ACC_BIT_0
LDR r1, =TCSR_CONF_FUSE_4
LDR r2, =L1_ACC_BIT_0
LDR r3, [r1]
MOV r3, r3, LSR r2
AND r3, r3, #1
ORR r4, r3, r4
//; Read L1_ACC_BIT_1
LDR r1, =TCSR_CONF_FUSE_4
LDR r2, =L1_ACC_BIT_1
LDR r3, [r1]
MOV r3, r3, LSR r2
AND r3, r3, #1
MOV r3, r3, LSL #1
ORR r4, r3, r4
l1_ck_0:
//; if L1_[1:0] == 00
LDR r5, = 0x0
CMP r4, r5
BNE l1_ck_1
LDR r0, =PVR0F0_00
LDR r1, =PVR0F2_00
LDR r2, =PVR2F0_00
LDR r3, =PVR2F1_00
B WRITE_L1_SA_SETTINGS
l1_ck_1:
//; if L1_[1:0] == 01
LDR r1, = 0x01
CMP r4, r1
BNE l1_ck_2
LDR r0, =PVR0F0_01
LDR r1, =PVR0F2_01
LDR r2, =PVR2F0_01
LDR r3, =PVR2F1_01
B WRITE_L1_SA_SETTINGS
l1_ck_2:
//; if L1_[2:0] == 10
LDR r1, = 0x02
CMP r4, r1
BNE l1_ck_3
LDR r0, =PVR0F0_10
LDR r1, =PVR0F2_10
LDR r2, =PVR2F0_10
LDR r3, =PVR2F1_10
B WRITE_L1_SA_SETTINGS
l1_ck_3:
//; if L1_[2:0] == 11
LDR r1, = 0x03
CMP r4, r1
LDR r0, =PVR0F0_11
LDR r1, =PVR0F2_11
LDR r2, =PVR2F0_11
LDR r3, =PVR2F1_11
B WRITE_L1_SA_SETTINGS
WRITE_L1_SA_SETTINGS:
//;WCP15_PVR0F0 r0
MCR p15, 0x0, r0, c15, c15, 0x0 //; write R0 to PVR0F0
//;WCP15_PVR0F2 r1
MCR p15, 0x0, r1, c15, c15, 0x2 //; write R1 to PVR0F2
//;WCP15_PVR2F0 r2
MCR p15, 0x2, r2, c15, c15, 0x0 //; write R2 to PVR2F0
// Disable predecode repair cache on certain Scorpion revisions
// (Raptor V2 and earlier, or Halcyon V1)
MRC p15, 0, r1, c0, c0, 0 //; MIDR
BIC r2, r1, #0xf0 //; check for Halcyon V1
LDR r4, =0x511f0000
CMP r2, r4
BNE PVR2F1
DPRC:
MRC p15, 0, r1, c15, c15, 2 //; PVR0F2
ORR r1, r1, #0x10 //; enable bit 4
MCR p15, 0, r1, c15, c15, 2 //; disable predecode repair cache
PVR2F1:
//;WCP15_PVR2F1 r3
MCR p15, 0x2, r3, c15, c15, 0x1 //; write R3 to PVR2F1
//; Reading L2_ACC
LDR r4, = 0x0
//; Read L2_ACC_BIT_0
LDR r1, =TCSR_CONF_FUSE_1
LDR r2, =L2_ACC_BIT_0
LDR r3, [r1]
MOV r3, r3, LSR r2
AND r3, r3, #1
ORR r4, r3, r4
//; Read L2_ACC_BIT_1
LDR r1, =TCSR_CONF_FUSE_4
LDR r2, =L2_ACC_BIT_1
LDR r3, [r1]
MOV r3, r3, LSR r2
AND r3, r3, #1
MOV r3, r3, LSL #1
ORR r4, r3, r4
//; Read L2_ACC_BIT_2
LDR r1, =TCSR_CONF_FUSE_4
LDR r2, =L2_ACC_BIT_2
LDR r3, [r1]
MOV r3, r3, LSR r2
AND r3, r3, #1
MOV r3, r3, LSL #2
ORR r4, r3, r4
l2_ck_0:
//; if L2_[2:0] == 000
LDR r5, = 0x0
CMP r4, r5
BNE l2_ck_1
LDR r0, =L2VR3F1_000
B WRITE_L2_SA_SETTINGS
l2_ck_1:
//; if L2_[2:0] == 001
LDR r5, = 0x1
CMP r4, r5
BNE l2_ck_2
LDR r0, =L2VR3F1_001
B WRITE_L2_SA_SETTINGS
l2_ck_2:
//; if L2_[2:0] == 010
LDR r5, = 0x2
CMP r4, r5
BNE l2_ck_3
LDR r0, =L2VR3F1_010
B WRITE_L2_SA_SETTINGS
l2_ck_3:
//; if L2_[2:0] == 011
LDR r5, = 0x3
CMP r4, r5
BNE l2_ck_4
LDR r0, =L2VR3F1_011
B WRITE_L2_SA_SETTINGS
l2_ck_4:
//; if L2_[2:0] == 100
LDR r5, = 0x4
CMP r4, r5
BNE l2_ck_5
LDR r0, =L2VR3F1_100
B WRITE_L2_SA_SETTINGS
l2_ck_5:
//; if L2_[2:0] == 101
LDR r5, = 0x5
CMP r4, r5
BNE l2_ck_6
LDR r0, =L2VR3F1_101
B WRITE_L2_SA_SETTINGS
l2_ck_6:
//; if L2_[2:0] == 110
LDR r5, = 0x6
CMP r4, r5
BNE l2_ck_7
LDR r0, =L2VR3F1_110
B WRITE_L2_SA_SETTINGS
l2_ck_7:
//; if L2_[2:0] == 111
LDR r5, = 0x7
CMP r4, r5
LDR r0, =L2VR3F1_111
B WRITE_L2_SA_SETTINGS
WRITE_L2_SA_SETTINGS:
//;WCP15_L2VR3F1 r0
MCR p15, 0x3, r0, c15, c15, 0x1 //;write r0 to L2VR3F1
DSB
ISB
LDR r0, =0 //;make sure the registers we touched
LDR r1, =0 //;are cleared when we return
LDR r2, =0
LDR r3, =0
LDR r4, =0
LDR r5, =0
//; routine complete
B _cpu_early_init_complete
.ltorg
.globl __cpu_early_init
__cpu_early_init:
//; Zero out r0 for use throughout this code. All other GPRs
//; (r1-r3) are set throughout this code to help establish
//; a consistent startup state for any code that follows.
//; Users should add code at the end of this routine to establish
//; their own stack address (r13), add translation page tables, enable
//; the caches, etc.
MOV r0, #0x0
//; Remove hardcoded cache settings. appsbl_handler.s calls Set_SA
//; API to dynamically configure cache for slow/nominal/fast parts
//; DCIALL to invalidate L2 cache bank (needs to be run 4 times, once per bank)
//; This must be done early in code (prior to enabling the caches)
MOV r1, #0x2
MCR p15, 0, r1, c9, c0, 6 //; DCIALL bank D ([15:14] == 2'b00)
ORR r1, r1, #0x00004000
MCR p15, 0, r1, c9, c0, 6 //; DCIALL bank C ([15:14] == 2'b01)
ADD r1, r1, #0x00004000
MCR p15, 0, r1, c9, c0, 6 //; DCIALL bank B ([15:14] == 2'b10)
ADD r1, r1, #0x00004000
MCR p15, 0, r1, c9, c0, 6 //; DCIALL bank A ([15:14] == 2'b11)
//; Initialize the BPCR - setup Global History Mask (GHRM) to all 1's
//; and have all address bits (AM) participate.
//; Different settings can be used to improve performance
// MOVW r1, #0x01FF
.word 0xe30011ff // hardcoded MOVW instruction due to lack of compiler support
// MOVT r1, #0x01FF
.word 0xe34011ff // hardcoded MOVT instruction due to lack of compiler support
MCR p15, 7, r1, c15, c0, 2 //; WCP15_BPCR
//; Initialize all I$ Victim Registers to 0 for startup
MCR p15, 0, r0, c9, c1, 0 //; WCP15_ICVIC0 r0
MCR p15, 0, r0, c9, c1, 1 //; WCP15_ICVIC1 r0
MCR p15, 0, r0, c9, c1, 2 //; WCP15_ICVIC2 r0
MCR p15, 0, r0, c9, c1, 3 //; WCP15_ICVIC3 r0
MCR p15, 0, r0, c9, c1, 4 //; WCP15_ICVIC4 r0
MCR p15, 0, r0, c9, c1, 5 //; WCP15_ICVIC5 r0
MCR p15, 0, r0, c9, c1, 6 //; WCP15_ICVIC5 r0
MCR p15, 0, r0, c9, c1, 7 //; WCP15_ICVIC7 r0
//; Initialize all I$ Locked Victim Registers (Unlocked Floors) to 0
MCR p15, 1, r0, c9, c1, 0 //; WCP15_ICFLOOR0 r0
MCR p15, 1, r0, c9, c1, 1 //; WCP15_ICFLOOR1 r0
MCR p15, 1, r0, c9, c1, 2 //; WCP15_ICFLOOR2 r0
MCR p15, 1, r0, c9, c1, 3 //; WCP15_ICFLOOR3 r0
MCR p15, 1, r0, c9, c1, 4 //; WCP15_ICFLOOR4 r0
MCR p15, 1, r0, c9, c1, 5 //; WCP15_ICFLOOR5 r0
MCR p15, 1, r0, c9, c1, 6 //; WCP15_ICFLOOR6 r0
MCR p15, 1, r0, c9, c1, 7 //; WCP15_ICFLOOR7 r0
//; Initialize all D$ Victim Registers to 0
MCR p15, 2, r0, c9, c1, 0 //; WP15_DCVIC0 r0
MCR p15, 2, r0, c9, c1, 1 //; WP15_DCVIC1 r0
MCR p15, 2, r0, c9, c1, 2 //; WP15_DCVIC2 r0
MCR p15, 2, r0, c9, c1, 3 //; WP15_DCVIC3 r0
MCR p15, 2, r0, c9, c1, 4 //; WP15_DCVIC4 r0
MCR p15, 2, r0, c9, c1, 5 //; WP15_DCVIC5 r0
MCR p15, 2, r0, c9, c1, 6 //; WP15_DCVIC6 r0
MCR p15, 2, r0, c9, c1, 7 //; WP15_DCVIC7 r0
//; Initialize all D$ Locked VDCtim Registers (Unlocked Floors) to 0
MCR p15, 3, r0, c9, c1, 0 //; WCP15_DCFLOOR0 r0
MCR p15, 3, r0, c9, c1, 1 //; WCP15_DCFLOOR1 r0
MCR p15, 3, r0, c9, c1, 2 //; WCP15_DCFLOOR2 r0
MCR p15, 3, r0, c9, c1, 3 //; WCP15_DCFLOOR3 r0
MCR p15, 3, r0, c9, c1, 4 //; WCP15_DCFLOOR4 r0
MCR p15, 3, r0, c9, c1, 5 //; WCP15_DCFLOOR5 r0
MCR p15, 3, r0, c9, c1, 6 //; WCP15_DCFLOOR6 r0
MCR p15, 3, r0, c9, c1, 7 //; WCP15_DCFLOOR7 r0
//; Initialize ASID to zero
MCR p15, 0, r0, c13, c0, 1 //; WCP15_CONTEXTIDR r0
//; ICIALL to invalidate entire I-Cache
MCR p15, 0, r0, c7, c5, 0 //; ICIALLU
//; DCIALL to invalidate entire D-Cache
MCR p15, 0, r0, c9, c0, 6 //; DCIALL r0
//; Initialize ADFSR to zero
MCR p15, 0, r0, c5, c1, 0 //; ADFSR r0
//; Initialize EFSR to zero
MCR p15, 7, r0, c15, c0, 1 //; EFSR r0
//; The VBAR (Vector Base Address Register) should be initialized
//; early in your code. We are setting it to zero
MCR p15, 0, r0, c12, c0, 0 //; WCP15_VBAR r0
//; Ensure the MCR's above have completed their operation before continuing
DSB
ISB
//; Setup CCPR - Cache Coherency Policy Register
//; setup CCPR[L1ISHP, L2ISHP] both to 0b00 (no forcing)
//; setup CCPR[L1OSHP, L2OSHP] both to 0b10 (force non-cacheable)
MOVW r2, #0x88
MCR p15, 0, r2, c10, c4, 2
//;-------------------------------------------------------------------
//; There are a number of registers that must be set prior to enabling
//; the MMU. The DCAR is one of these registers. We are setting
//; it to zero (no access) to easily detect improper setup in subsequent
//; code sequences
//;-------------------------------------------------------------------
//; Setup DACR (Domain Access Control Register) to zero
MCR p15, 0, r0, c3, c0, 0 //; WCP15_DACR r0
//; Setup DCLKCR to allow normal D-Cache line fills
MCR p15, 1, r0, c9, c0, 7 //; WCP15_DCLKCR r0
//; Setup the TLBLKCR
//; Victim = 6'b000000; Floor = 6'b000000;
//; IASIDCFG = 2'b00 (State-Machine); IALLCFG = 2'b01 (Flash); BNA = 1'b0;
MOV r1, #0x02
MCR p15, 0, r1, c10, c1, 3 //; WCP15_TLBLKCR r1
//;Make sure TLBLKCR is complete before continuing
ISB
//; Invalidate the UTLB
MCR p15, 0, r0, c8, c7, 0 //; UTLBIALL
//; Make sure UTLB request has been presented to macro before continuing
ISB
SYSI2:
//; setup L2CR1 to some default Instruction and data prefetching values
//; Users may want specific settings for various performance enhancements
//; In Halcyon we do not have broadcasting barriers. So we need to turn
// ; on bit 8 of L2CR1; which DBB:( Disable barrier broadcast )
LDR r2, =0x133
MCR p15, 3, r2, c15, c0, 3 //; WCP15_L2CR1 r0
//; Enable Z bit to enable branch prediction (default is off)
MRC p15, 0, r2, c1, c0, 0 //; RCP15_SCTLR r2
ORR r2, r2, #0x00000800
MCR p15, 0, r2, c1, c0, 0 //; WCP15_SCTLR r2
//; Make sure Link stack is initialized with branch and links to sequential addresses
//; This aids in creating a predictable startup environment
BL SEQ1
SEQ1: BL SEQ2
SEQ2: BL SEQ3
SEQ3: BL SEQ4
SEQ4: BL SEQ5
SEQ5: BL SEQ6
SEQ6: BL SEQ7
SEQ7: BL SEQ8
SEQ8:
//; REMOVE FOLLOWING THREE INSTRUCTIONS WHEN POWER COLLAPSE IS ENA
//;Make sure the DBGOSLSR[LOCK] bit is cleared to allow access to the debug registers
//; Writing anything but the "secret code" to the DBGOSLAR clears the DBGOSLSR[LOCK] bit
MCR p14, 0, r0, c1, c0, 4 //; WCP14_DBGOSLAR r0
//; Read the DBGPRSR to clear the DBGPRSR[STICKYPD]
//; Any read to DBGPRSR clear the STICKYPD bit
//; ISB guarantees the read completes before attempting to
//; execute a CP14 instruction.
MRC p14, 0, r3, c1, c5, 4 //; RCP14_DBGPRSR r3
ISB
//; Initialize the Watchpoint Control Registers to zero (optional)
//;;; MCR p14, 0, r0, c0, c0, 7 ; WCP14_DBGWCR0 r0
//;;; MCR p14, 0, r0, c0, c1, 7 ; WCP14_DBGWCR1 r0
//;----------------------------------------------------------------------
//; The saved Program Status Registers (SPSRs) should be setup
//; prior to any automatic mode switches. The following
//; code sets these registers up to a known state. Users will need to
//; customize these settings to meet their needs.
//;----------------------------------------------------------------------
MOV r2, #0x1f
MOV r1, #0xd7 //;ABT mode
msr cpsr_c, r1 //;ABT mode
msr spsr_cxfs, r2 //;clear the spsr
MOV r1, #0xdb //;UND mode
msr cpsr_c, r1 //;UND mode
msr spsr_cxfs, r2 //;clear the spsr
MOV r1, #0xd1 //;FIQ mode
msr cpsr_c, r1 //;FIQ mode
msr spsr_cxfs, r2 //;clear the spsr
MOV r1, #0xd2 //;IRQ mode
msr cpsr_c, r1 //;IRQ mode
msr spsr_cxfs, r2 //;clear the spsr
MOV r1, #0xd6 //;Monitor mode
msr cpsr_c, r1 //;Monitor mode
msr spsr_cxfs, r2 //;clear the spsr
MOV r1, #0xd3 //;SVC mode
msr cpsr_c, r1 //;SVC mode
msr spsr_cxfs, r2 //;clear the spsr
//;----------------------------------------------------------------------
//; Enabling Error reporting is something users may want to do at
//; some other point in time. We have chosen some default settings
//; that should be reviewed. Most of these registers come up in an
//; unpredictable state after reset.
//;----------------------------------------------------------------------
//;Start of error and control setting
//; setup L2CR0 with various L2/TCM control settings
//; enable out of order bus attributes and error reporting
//; this register comes up unpredictable after reset
// MOVW r1, #0x0F0F
.word 0xe3001f0f // hardcoded MOVW instruction due to lack of compiler support
// MOVT r1, #0xC005
.word 0xe34c1005 // hardcoded MOVW instruction due to lack of compiler support
MCR p15, 3, r1, c15, c0, 1 //; WCP15_L2CR0 r1
//; setup L2CPUCR
//; MOV r2, #0xFF
//; Enable I and D cache parity
//;L2CPUCR[7:5] = 3~Rh7 ~V enable parity error reporting for modified,
//;tag, and data parity errors
MOV r2, #0xe0
MCR p15, 3, r2, c15, c0, 2 //; WCP15_L2CPUCR r2
//; setup SPCR
//; enable all error reporting (reset value is unpredicatble for most bits)
MOV r3, #0x0F
MCR p15, 0, r3, c9, c7, 0 //; WCP15_SPCR r3
//; setup DMACHCRs (reset value unpredictable)
//; control setting and enable all error reporting
MOV r1, #0x0F
//; DMACHCR0 = 0000000F
MOV r2, #0x00 //; channel 0
MCR p15, 0, r2, c11, c0, 0 //; WCP15_DMASELR r2
MCR p15, 0, r1, c11, c0, 2 //; WCP15_DMACHCR r1
//; DMACHCR1 = 0000000F
MOV r2, #0x01 //; channel 1
MCR p15, 0, r2, c11, c0, 0 //; WCP15_DMASELR r2
MCR p15, 0, r1, c11, c0, 2 //; WCP15_DMACHCR r1
//; DMACHCR2 = 0000000F
MOV r2, #0x02 //; channel 2
MCR p15, 0, r2, c11, c0, 0 //; WCP15_DMASELR r2
MCR p15, 0, r1, c11, c0, 2 //; WCP15_DMACHCR r1
//; DMACHCR3 = 0000000F
MOV r2, #0x03 //; channel 3
MCR p15, 0, r2, c11, c0, 0 //; WCP15_DMASELR r2
MCR p15, 0, r1, c11, c0, 2 //; WCP15_DMACHCR r1
//; Set ACTLR (reset unpredictable)
//; Set AVIVT control, error reporting, etc.
//; MOV r3, #0x07
//; Enable I and D cache parity
//;ACTLR[2:0] = 3'h7 - enable parity error reporting from L2/I$/D$)
//;ACTLR[5:4] = 2'h3 - enable parity
//;ACTLR[19:18] =2'h3 - always generate and check parity(when MMU disabled).
//;Value to be written #0xC0037
// MOVW r3, #0x0037
.word 0xe3003037 // hardcoded MOVW instruction due to lack of compiler support
// MOVT r3, #0x000C
.word 0xe340300c // hardcoded MOVW instruction due to lack of compiler support
MCR p15, 0, r3, c1, c0, 1 //; WCP15_ACTLR r3
//;End of error and control setting
//;----------------------------------------------------------------------
//; Unlock ETM and read StickyPD to halt the ETM clocks from running.
//; This is required for power saving whether the ETM is used or not.
//;----------------------------------------------------------------------
//;Clear ETMOSLSR[LOCK] bit
MOV r1, #0x00000000
MCR p14, 1, r1, c1, c0, 4 //; WCP14_ETMOSLAR r1
//;Clear ETMPDSR[STICKYPD] bit
MRC p14, 1, r2, c1, c5, 4 //; RCP14_ETMPDSR r2
/*
#ifdef APPSBL_ETM_ENABLE
;----------------------------------------------------------------------
; Optionally Enable the ETM (Embedded Trace Macro) which is used for debug
;----------------------------------------------------------------------
; enable ETM clock if disabled
MRC p15, 7, r1, c15, c0, 5 ; RCP15_CPMR r1
ORR r1, r1, #0x00000008
MCR p15, 7, r1, c15, c0, 5 ; WCP15_CPMR r1
ISB
; set trigger event to counter1 being zero
MOV r3, #0x00000040
MCR p14, 1, r3, c0, c2, 0 ; WCP14_ETMTRIGGER r3
; clear ETMSR
MOV r2, #0x00000000
MCR p14, 1, r2, c0, c4, 0 ; WCP14_ETMSR r2
; clear trace enable single address comparator usage
MCR p14, 1, r2, c0, c7, 0 ; WCP14_ETMTECR2 r2
; set trace enable to always
MOV r2, #0x0000006F
MCR p14, 1, r2, c0, c8, 0 ; WCP14_ETMTEEVR r2
; clear trace enable address range comparator usage and exclude nothing
MOV r2, #0x01000000
MCR p14, 1, r2, c0, c9, 0 ; WCP14_ETMTECR1 r2
; set view data to always
MOV r2, #0x0000006F
MCR p14, 1, r2, c0, c12, 0 ; WCP14_ETMVDEVR r2
; clear view data single address comparator usage
MOV r2, #0x00000000
MCR p14, 1, r2, c0, c13, 0 ; WCP14_ETMVDCR1 r2
; clear view data address range comparator usage and exclude nothing
MOV r2, #0x00010000
MCR p14, 1, r2, c0, c15, 0 ; WCP14_ETMVDCR3 r2
; set counter1 to 194
MOV r2, #0x000000C2
MCR p14, 1, r2, c0, c0, 5 ; WCP14_ETMCNTRLDVR1 r2
; set counter1 to never reload
MOV r2, #0x0000406F
MCR p14, 1, r2, c0, c8, 5 ; WCP14_ETMCNTRLDEVR1 r2
; set counter1 to decrement every cycle
MOV r2, #0x0000006F
MCR p14, 1, r2, c0, c4, 5 ; WCP14_ETMCNTENR1 r2
; Set trace synchronization frequency 1024 bytes
MOV r2, #0x00000400
MCR p14, 1, r2, c0, c8, 7 ; WCP14_ETMSYNCFR r2
; Program etm control register
; - Set the CPU to ETM clock ratio to 1:1
; - Set the ETM to perform data address tracing
MOV r2, #0x00002008
MCR p14, 1, r2, c0, c0, 0 ; WCP14_ETMCR r2
ISB
#endif *//* APPSBL_ETM_ENABLE */
/*
#ifdef APPSBL_VFP_ENABLE
;----------------------------------------------------------------------
; Perform the following operations if you intend to make use of
; the VFP/Neon unit. Note that the FMXR instruction requires a CPU ID
; indicating the VFP unit is present (i.e.Cortex-A8). .
; Some tools will require full double precision floating point support
; which will become available in Scorpion pass 2
;----------------------------------------------------------------------
; allow full access to CP 10 and 11 space for VFP/NEON use
MRC p15, 0, r1, c1, c0, 2 ; Read CP Access Control Register
ORR r1, r1, #0x00F00000 ; enable full access for p10,11
MCR p15, 0, r1, c1, c0, 2 ; Write CPACR
;make sure the CPACR is complete before continuing
ISB
; Enable VFP itself (certain OSes may want to dynamically set/clear
; the enable bit based on the application being executed
MOV r1, #0x40000000
FMXR FPEXC, r1
#endif *//* APPSBL_VFP_ENABLE */
/* we have no stack, so just tail-call into the SET_SA routine... */
b SET_SA
.ltorg

241
lk/platform/msm7x30/gpio.c Normal file

@ -0,0 +1,241 @@
/*
* 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 <reg.h>
#include <platform/iomap.h>
#include <dev/gpio.h>
#include "gpio_hw.h"
typedef struct gpioregs gpioregs;
struct gpioregs
{
unsigned out;
unsigned in;
unsigned int_status;
unsigned int_clear;
unsigned int_en;
unsigned int_edge;
unsigned int_pos;
unsigned oe;
};
static gpioregs GPIO_REGS[] = {
{
.out = GPIO_OUT_0,
.in = GPIO_IN_0,
.int_status = GPIO_INT_STATUS_0,
.int_clear = GPIO_INT_CLEAR_0,
.int_en = GPIO_INT_EN_0,
.int_edge = GPIO_INT_EDGE_0,
.int_pos = GPIO_INT_POS_0,
.oe = GPIO_OE_0,
},
{
.out = GPIO_OUT_1,
.in = GPIO_IN_1,
.int_status = GPIO_INT_STATUS_1,
.int_clear = GPIO_INT_CLEAR_1,
.int_en = GPIO_INT_EN_1,
.int_edge = GPIO_INT_EDGE_1,
.int_pos = GPIO_INT_POS_1,
.oe = GPIO_OE_1,
},
{
.out = GPIO_OUT_2,
.in = GPIO_IN_2,
.int_status = GPIO_INT_STATUS_2,
.int_clear = GPIO_INT_CLEAR_2,
.int_en = GPIO_INT_EN_2,
.int_edge = GPIO_INT_EDGE_2,
.int_pos = GPIO_INT_POS_2,
.oe = GPIO_OE_2,
},
{
.out = GPIO_OUT_3,
.in = GPIO_IN_3,
.int_status = GPIO_INT_STATUS_3,
.int_clear = GPIO_INT_CLEAR_3,
.int_en = GPIO_INT_EN_3,
.int_edge = GPIO_INT_EDGE_3,
.int_pos = GPIO_INT_POS_3,
.oe = GPIO_OE_3,
},
{
.out = GPIO_OUT_4,
.in = GPIO_IN_4,
.int_status = GPIO_INT_STATUS_4,
.int_clear = GPIO_INT_CLEAR_4,
.int_en = GPIO_INT_EN_4,
.int_edge = GPIO_INT_EDGE_4,
.int_pos = GPIO_INT_POS_4,
.oe = GPIO_OE_4,
},
{
.out = GPIO_OUT_5,
.in = GPIO_IN_5,
.int_status = GPIO_INT_STATUS_5,
.int_clear = GPIO_INT_CLEAR_5,
.int_en = GPIO_INT_EN_5,
.int_edge = GPIO_INT_EDGE_5,
.int_pos = GPIO_INT_POS_5,
.oe = GPIO_OE_5,
},
{
.out = GPIO_OUT_6,
.in = GPIO_IN_6,
.int_status = GPIO_INT_STATUS_6,
.int_clear = GPIO_INT_CLEAR_6,
.int_en = GPIO_INT_EN_6,
.int_edge = GPIO_INT_EDGE_6,
.int_pos = GPIO_INT_POS_6,
.oe = GPIO_OE_6,
},
{
.out = GPIO_OUT_7,
.in = GPIO_IN_7,
.int_status = GPIO_INT_STATUS_7,
.int_clear = GPIO_INT_CLEAR_7,
.int_en = GPIO_INT_EN_7,
.int_edge = GPIO_INT_EDGE_7,
.int_pos = GPIO_INT_POS_7,
.oe = GPIO_OE_7,
},
};
static gpioregs *find_gpio(unsigned n, unsigned *bit)
{
if(n > 150) {
*bit = 1 << (n - 151);
return GPIO_REGS + 7;
}
if(n > 133) {
*bit = 1 << (n - 134);
return GPIO_REGS + 6;
}
if(n > 106) {
*bit = 1 << (n - 107);
return GPIO_REGS + 5;
}
if(n > 94) {
*bit = 1 << (n - 95);
return GPIO_REGS + 4;
}
if(n > 67) {
*bit = 1 << (n - 68);
return GPIO_REGS + 3;
}
if(n > 43) {
*bit = 1 << (n - 44);
return GPIO_REGS + 2;
}
if(n > 15) {
*bit = 1 << (n - 16);
return GPIO_REGS + 1;
}
*bit = 1 << n;
return GPIO_REGS + 0;
}
int gpio_config(unsigned n, unsigned flags)
{
gpioregs *r;
unsigned b;
unsigned v;
if ((r = find_gpio(n, &b)) == 0)
return -1;
v = readl(r->oe);
if (flags & GPIO_OUTPUT) {
writel(v | b, r->oe);
} else {
writel(v & (~b), r->oe);
}
return 0;
}
void gpio_set(unsigned n, unsigned on)
{
gpioregs *r;
unsigned b;
unsigned v;
if((r = find_gpio(n, &b)) == 0) return;
v = readl(r->out);
if(on) {
writel(v | b, r->out);
} else {
writel(v & (~b), r->out);
}
}
int gpio_get(unsigned n)
{
gpioregs *r;
unsigned b;
if((r = find_gpio(n, &b)) == 0) return 0;
return (readl(r->in) & b) ? 1 : 0;
}
void platform_config_interleaved_mode_gpios(void)
{
/* configure EB2_CS1 through GPIO86 */
writel (GPIO_ALT_FUNC_PAGE_REG, 0x56);
writel (GPIO_ALT_FUNC_CFG_REG, 0x04);
/* configure the EBI2_BUSY1_N through GPIO115 */
writel (GPIO_ALT_FUNC_PAGE_REG, 0x73);
writel (GPIO_ALT_FUNC_CFG_REG, 0x08);
}
/* Enables all gpios passed in table*/
int platform_gpios_enable(const struct msm_gpio *table, int size)
{
int rc;
int i;
const struct msm_gpio *g;
for (i = 0; i < size; i++) {
g = table + i;
/* Enable gpio */
rc = gpio_tlmm_config(g->gpio_cfg, GPIO_ENABLE);
if (rc) {
goto err;
}
}
return 0;
err:
return rc;
}

@ -0,0 +1,181 @@
/*
* 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 __PLATFORM_MSM7X30_GPIO_HW_H
#define __PLATFORM_MSM7X30_GPIO_HW_H
#define MSM_GPIO1_BASE 0xAC001000
#define MSM_GPIO2_BASE 0xAC101000
#define GPIO1_REG(off) (MSM_GPIO1_BASE + (off))
#define GPIO2_REG(off) (MSM_GPIO2_BASE + 0x400 + (off))
/* output value */
#define GPIO_OUT_0 GPIO1_REG(0x00) /* gpio 15-0 */
#define GPIO_OUT_1 GPIO2_REG(0x00) /* gpio 43-16 */
#define GPIO_OUT_2 GPIO1_REG(0x04) /* gpio 67-44 */
#define GPIO_OUT_3 GPIO1_REG(0x08) /* gpio 94-68 */
#define GPIO_OUT_4 GPIO1_REG(0x0C) /* gpio 106-95 */
#define GPIO_OUT_5 GPIO1_REG(0x50) /* gpio 133-107 */
#define GPIO_OUT_6 GPIO1_REG(0xC4) /* gpio 150-134 */
#define GPIO_OUT_7 GPIO1_REG(0x214) /* gpio 181-151 */
/* same pin map as above, output enable */
#define GPIO_OE_0 GPIO1_REG(0x10)
#define GPIO_OE_1 GPIO2_REG(0x08)
#define GPIO_OE_2 GPIO1_REG(0x14)
#define GPIO_OE_3 GPIO1_REG(0x18)
#define GPIO_OE_4 GPIO1_REG(0x1C)
#define GPIO_OE_5 GPIO1_REG(0x54)
#define GPIO_OE_6 GPIO1_REG(0xC8)
#define GPIO_OE_7 GPIO1_REG(0x218)
/* same pin map as above, input read */
#define GPIO_IN_0 GPIO1_REG(0x34)
#define GPIO_IN_1 GPIO2_REG(0x20)
#define GPIO_IN_2 GPIO1_REG(0x38)
#define GPIO_IN_3 GPIO1_REG(0x3C)
#define GPIO_IN_4 GPIO1_REG(0x40)
#define GPIO_IN_5 GPIO1_REG(0x44)
#define GPIO_IN_6 GPIO1_REG(0xCC)
#define GPIO_IN_7 GPIO1_REG(0x21C)
/* same pin map as above, 1=edge 0=level interrup */
#define GPIO_INT_EDGE_0 GPIO1_REG(0x60)
#define GPIO_INT_EDGE_1 GPIO2_REG(0x50)
#define GPIO_INT_EDGE_2 GPIO1_REG(0x64)
#define GPIO_INT_EDGE_3 GPIO1_REG(0x68)
#define GPIO_INT_EDGE_4 GPIO1_REG(0x6C)
#define GPIO_INT_EDGE_5 GPIO1_REG(0xC0)
#define GPIO_INT_EDGE_6 GPIO1_REG(0xD0)
#define GPIO_INT_EDGE_7 GPIO1_REG(0x240)
/* same pin map as above, 1=positive 0=negative */
#define GPIO_INT_POS_0 GPIO1_REG(0x70)
#define GPIO_INT_POS_1 GPIO2_REG(0x58)
#define GPIO_INT_POS_2 GPIO1_REG(0x74)
#define GPIO_INT_POS_3 GPIO1_REG(0x78)
#define GPIO_INT_POS_4 GPIO1_REG(0x7C)
#define GPIO_INT_POS_5 GPIO1_REG(0xBC)
#define GPIO_INT_POS_6 GPIO1_REG(0xD4)
#define GPIO_INT_POS_7 GPIO1_REG(0x228)
/* same pin map as above, interrupt enable */
#define GPIO_INT_EN_0 GPIO1_REG(0x80)
#define GPIO_INT_EN_1 GPIO2_REG(0x60)
#define GPIO_INT_EN_2 GPIO1_REG(0x84)
#define GPIO_INT_EN_3 GPIO1_REG(0x88)
#define GPIO_INT_EN_4 GPIO1_REG(0x8C)
#define GPIO_INT_EN_5 GPIO1_REG(0xB8)
#define GPIO_INT_EN_6 GPIO1_REG(0xD8)
#define GPIO_INT_EN_7 GPIO1_REG(0x22C)
/* same pin map as above, write 1 to clear interrupt */
#define GPIO_INT_CLEAR_0 GPIO1_REG(0x90)
#define GPIO_INT_CLEAR_1 GPIO2_REG(0x68)
#define GPIO_INT_CLEAR_2 GPIO1_REG(0x94)
#define GPIO_INT_CLEAR_3 GPIO1_REG(0x98)
#define GPIO_INT_CLEAR_4 GPIO1_REG(0x9C)
#define GPIO_INT_CLEAR_5 GPIO1_REG(0xB4)
#define GPIO_INT_CLEAR_6 GPIO1_REG(0xDC)
#define GPIO_INT_CLEAR_7 GPIO1_REG(0x230)
/* same pin map as above, 1=interrupt pending */
#define GPIO_INT_STATUS_0 GPIO1_REG(0xA0)
#define GPIO_INT_STATUS_1 GPIO2_REG(0x70)
#define GPIO_INT_STATUS_2 GPIO1_REG(0xA4)
#define GPIO_INT_STATUS_3 GPIO1_REG(0xA8)
#define GPIO_INT_STATUS_4 GPIO1_REG(0xAC)
#define GPIO_INT_STATUS_5 GPIO1_REG(0xB0)
#define GPIO_INT_STATUS_6 GPIO1_REG(0xE0)
#define GPIO_INT_STATUS_7 GPIO1_REG(0x234)
#define GPIO_OUT_VAL_REG_BASE 0xABC00000
#define GPIO_ALT_FUNC_PAGE_REG (GPIO_OUT_VAL_REG_BASE + 0x20)
#define GPIO_ALT_FUNC_CFG_REG (GPIO_OUT_VAL_REG_BASE + 0x24)
/* GPIO TLMM: Direction */
#define GPIO_INPUT 0
#define GPIO_OUTPUT 1
/* GPIO TLMM: Pullup/Pulldown */
#define GPIO_NO_PULL 0
#define GPIO_PULL_DOWN 1
#define GPIO_KEEPER 2
#define GPIO_PULL_UP 3
/* GPIO TLMM: Drive Strength */
#define GPIO_2MA 0
#define GPIO_4MA 1
#define GPIO_6MA 2
#define GPIO_8MA 3
#define GPIO_10MA 4
#define GPIO_12MA 5
#define GPIO_14MA 6
#define GPIO_16MA 7
#define GPIO38_GPIO_CNTRL 0x175
/* GPIO TLMM: Status */
#define GPIO_ENABLE 0
#define GPIO_DISABLE 1
#define GPIO_CFG(gpio, func, dir, pull, drvstr) \
((((gpio) & 0x3FF) << 4) | \
((func) & 0xf) | \
(((dir) & 0x1) << 14) | \
(((pull) & 0x3) << 15) | \
(((drvstr) & 0xF) << 17))
/**
* struct msm_gpio - GPIO pin description
* @gpio_cfg - configuration bitmap, as per gpio_tlmm_config()
* @label - textual label
*
* Usually, GPIO's are operated by sets.
* This struct accumulate all GPIO information in single source
* and facilitete group operations provided by msm_gpios_xxx()
*/
struct msm_gpio {
unsigned gpio_cfg;
const char *label;
};
/**
* extract GPIO pin from bit-field used for gpio_tlmm_config
*/
#define GPIO_PIN(gpio_cfg) (((gpio_cfg) >> 4) & 0x3ff)
#define GPIO_FUNC(gpio_cfg) (((gpio_cfg) >> 0) & 0xf)
#define GPIO_DIR(gpio_cfg) (((gpio_cfg) >> 14) & 0x1)
#define GPIO_PULL(gpio_cfg) (((gpio_cfg) >> 15) & 0x3)
#define GPIO_DRVSTR(gpio_cfg) (((gpio_cfg) >> 17) & 0xf)
#endif

@ -0,0 +1,64 @@
/*
* Copyright (c) 2008, Google Inc.
* 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.
* * 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 _PLATFORM_MSM7X30_IOMAP_H_
#define _PLATFORM_MSM7X30_IOMAP_H_
#define MSM_UART1_BASE 0xACA00000
#define MSM_UART2_BASE 0xACB00000
#define MSM_UART3_BASE 0xACC00000
#define MSM_VIC_BASE 0xC0080000
#define MSM_TMR_BASE 0xC0100000
#define MSM_GPT_BASE (MSM_TMR_BASE + 0x04)
#define MSM_CSR_BASE 0xC0100000
#define MSM_GCC_BASE 0xC0182000
#define MSM_SDC1_BASE 0xA0400000
#define MSM_SDC2_BASE 0xA0500000
#define MSM_SDC3_BASE 0xA3000000
#define MSM_SDC4_BASE 0xA3100000
#define MSM_SHARED_BASE 0x00100000
#define MSM_CLK_CTL_BASE 0xAB800000
#define MSM_CLK_CTL_SH2_BASE 0xABA01000
#define SCSS_CLK_CTL 0xC0101004
#define SCSS_CLK_SEL 0xC0101008
#define MSM_USB_BASE 0xA3600000
#define SH2_USBH_MD_REG 0xABA012BC
#define SH2_USBH_NS_REG 0xABA012C0
#define SH2_GLBL_CLK_ENA_SC 0xABA013BC
#define MSM_SAW_BASE 0xC0102000
#endif

@ -0,0 +1,170 @@
/* 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.
* * 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.
*
*/
#ifndef __ASM_ARCH_MSM_IRQS_7X30_H
#define __ASM_ARCH_MSM_IRQS_7X30_H
/* MSM ACPU Interrupt Numbers */
#define INT_DEBUG_TIMER_EXP 0
#define INT_GPT0_TIMER_EXP 1
#define INT_GPT1_TIMER_EXP 2
#define INT_WDT0_ACCSCSSBARK 3
#define INT_WDT1_ACCSCSSBARK 4
#define INT_AVS_SVIC 5
#define INT_AVS_SVIC_SW_DONE 6
#define INT_SC_DBG_RX_FULL 7
#define INT_SC_DBG_TX_EMPTY 8
#define INT_SC_PERF_MON 9
#define INT_AVS_REQ_DOWN 10
#define INT_AVS_REQ_UP 11
#define INT_SC_ACG 12
/* SCSS_VICFIQSTS1[13:15] are RESERVED */
#define INT_L2_SVICCPUIRPTREQ 16
#define INT_L2_SVICDMANSIRPTREQ 17
#define INT_L2_SVICDMASIRPTREQ 18
#define INT_L2_SVICSLVIRPTREQ 19
#define INT_AD5A_MPROC_APPS_0 20
#define INT_AD5A_MPROC_APPS_1 21
#define INT_A9_M2A_0 22
#define INT_A9_M2A_1 23
#define INT_A9_M2A_2 24
#define INT_A9_M2A_3 25
#define INT_A9_M2A_4 26
#define INT_A9_M2A_5 27
#define INT_A9_M2A_6 28
#define INT_A9_M2A_7 29
#define INT_A9_M2A_8 30
#define INT_A9_M2A_9 31
#define INT_AXI_EBI1_SC (32 + 0)
#define INT_IMEM_ERR (32 + 1)
#define INT_AXI_EBI0_SC (32 + 2)
#define INT_PBUS_SC_IRQC (32 + 3)
#define INT_PERPH_BUS_BPM (32 + 4)
#define INT_CC_TEMP_SENSE (32 + 5)
#define INT_UXMC_EBI0 (32 + 6)
#define INT_UXMC_EBI1 (32 + 7)
#define INT_EBI2_OP_DONE (32 + 8)
#define INT_EBI2_WR_ER_DONE (32 + 9)
#define INT_TCSR_SPSS_CE (32 + 10)
#define INT_EMDH (32 + 11)
#define INT_PMDH (32 + 12)
#define INT_MDC (32 + 13)
#define INT_MIDI_TO_SUPSS (32 + 14)
#define INT_LPA_2 (32 + 15)
#define INT_GPIO_GROUP1_SECURE (32 + 16)
#define INT_GPIO_GROUP2_SECURE (32 + 17)
#define INT_GPIO_GROUP1 (32 + 18)
#define INT_GPIO_GROUP2 (32 + 19)
#define INT_MPRPH_SOFTRESET (32 + 20)
#define INT_PWB_I2C (32 + 21)
#define INT_PWB_I2C_2 (32 + 22)
#define INT_TSSC_SAMPLE (32 + 23)
#define INT_TSSC_PENUP (32 + 24)
#define INT_TCHSCRN_SSBI (32 + 25)
#define INT_FM_RDS (32 + 26)
#define INT_KEYSENSE (32 + 27)
#define INT_USB_OTG_HS (32 + 28)
#define INT_USB_OTG_HS2 (32 + 29)
#define INT_USB_OTG_HS3 (32 + 30)
#define INT_RESERVED_BIT31 (32 + 31)
#define INT_SPI_OUTPUT (64 + 0)
#define INT_SPI_INPUT (64 + 1)
#define INT_SPI_ERROR (64 + 2)
#define INT_UART1 (64 + 3)
#define INT_UART1_RX (64 + 4)
#define INT_UART2 (64 + 5)
#define INT_UART2_RX (64 + 6)
#define INT_UART3 (64 + 7)
#define INT_UART3_RX (64 + 8)
#define INT_UART1DM_IRQ (64 + 9)
#define INT_UART1DM_RX (64 + 10)
#define INT_UART2DM_IRQ (64 + 11)
#define INT_UART2DM_RX (64 + 12)
#define INT_TSIF (64 + 13)
#define INT_ADM_SC1 (64 + 14)
#define INT_ADM_SC2 (64 + 15)
#define INT_MDP (64 + 16)
#define INT_VPE (64 + 17)
#define INT_GRP_2D (64 + 18)
#define INT_GRP_3D (64 + 19)
#define INT_ROTATOR (64 + 20)
#define INT_MFC720 (64 + 21)
#define INT_JPEG (64 + 22)
#define INT_VFE (64 + 23)
#define INT_TV_ENC (64 + 24)
#define INT_PMIC_SSBI (64 + 25)
#define INT_MPM_1 (64 + 26)
#define INT_TCSR_SPSS_SAMPLE (64 + 27)
#define INT_TCSR_SPSS_PENUP (64 + 28)
#define INT_MPM_2 (64 + 29)
#define INT_SDC1_0 (64 + 30)
#define INT_SDC1_1 (64 + 31)
#define INT_SDC3_0 (96 + 0)
#define INT_SDC3_1 (96 + 1)
#define INT_SDC2_0 (96 + 2)
#define INT_SDC2_1 (96 + 3)
#define INT_SDC4_0 (96 + 4)
#define INT_SDC4_1 (96 + 5)
#define INT_PWB_QUP_IN (96 + 6)
#define INT_PWB_QUP_OUT (96 + 7)
#define INT_PWB_QUP_ERR (96 + 8)
/* SCSS_VICFIQSTS3[6:31] are RESERVED */
/* Retrofit universal macro names */
#define INT_ADM_AARM INT_ADM_SC2
#define INT_USB_HS INT_USB_OTG_HS
#define INT_USB_OTG INT_USB_OTG_HS
#define INT_TCHSCRN1 INT_TSSC_SAMPLE
#define INT_TCHSCRN2 INT_TSSC_PENUP
#define INT_GP_TIMER_EXP INT_GPT0_TIMER_EXP
#define INT_ADSP_A11 INT_AD5A_MPROC_APPS_0
#define INT_ADSP_A9_A11 INT_AD5A_MPROC_APPS_1
#define INT_MDDI_EXT INT_EMDH
#define INT_MDDI_PRI INT_PMDH
#define INT_MDDI_CLIENT INT_MDC
#define INT_NAND_WR_ER_DONE INT_EBI2_WR_ER_DONE
#define INT_NAND_OP_DONE INT_EBI2_OP_DONE
#define NR_MSM_IRQS 128
#define NR_GPIO_IRQS 182
#define PMIC8058_IRQ_BASE (NR_MSM_IRQS + NR_GPIO_IRQS)
#define NR_PMIC8058_GPIO_IRQS 40
#define NR_PMIC8058_MPP_IRQS 12
#define NR_PMIC8058_MISC_IRQS 8
#define NR_PMIC8058_IRQS (NR_PMIC8058_GPIO_IRQS +\
NR_PMIC8058_MPP_IRQS +\
NR_PMIC8058_MISC_IRQS)
#define NR_BOARD_IRQS NR_PMIC8058_IRQS
#define NR_IRQS (NR_MSM_IRQS + NR_GPIO_IRQS + NR_BOARD_IRQS)
#endif /* __ASM_ARCH_MSM_IRQS_7X30_H */

@ -0,0 +1,159 @@
/*
* 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 <debug.h>
#include <arch/arm.h>
#include <reg.h>
#include <kernel/thread.h>
#include <platform/interrupts.h>
#include <platform/irqs.h>
#include <platform/iomap.h>
#define VIC_REG(off) (MSM_VIC_BASE + (off))
#define VIC_INT_SELECT0 VIC_REG(0x0000) /* 1: FIQ, 0: IRQ */
#define VIC_INT_SELECT1 VIC_REG(0x0004) /* 1: FIQ, 0: IRQ */
#define VIC_INT_EN0 VIC_REG(0x0010)
#define VIC_INT_EN1 VIC_REG(0x0014)
#define VIC_INT_ENCLEAR0 VIC_REG(0x0020)
#define VIC_INT_ENCLEAR1 VIC_REG(0x0024)
#define VIC_INT_ENSET0 VIC_REG(0x0030)
#define VIC_INT_ENSET1 VIC_REG(0x0034)
#define VIC_INT_TYPE0 VIC_REG(0x0040) /* 1: EDGE, 0: LEVEL */
#define VIC_INT_TYPE1 VIC_REG(0x0044) /* 1: EDGE, 0: LEVEL */
#define VIC_INT_POLARITY0 VIC_REG(0x0050) /* 1: NEG, 0: POS */
#define VIC_INT_POLARITY1 VIC_REG(0x0054) /* 1: NEG, 0: POS */
#define VIC_NO_PEND_VAL VIC_REG(0x0060)
#define VIC_INT_MASTEREN VIC_REG(0x0068) /* 1: IRQ, 2: FIQ */
#define VIC_CONFIG VIC_REG(0x006C) /* 1: USE ARM1136 VIC */
#define VIC_SECURITY0 VIC_REG(0x0070)
#define VIC_SECURITY1 VIC_REG(0x0074)
#define VIC_IRQ_STATUS0 VIC_REG(0x0080)
#define VIC_IRQ_STATUS1 VIC_REG(0x0084)
#define VIC_FIQ_STATUS0 VIC_REG(0x0090)
#define VIC_FIQ_STATUS1 VIC_REG(0x0094)
#define VIC_RAW_STATUS0 VIC_REG(0x00A0)
#define VIC_RAW_STATUS1 VIC_REG(0x00A4)
#define VIC_INT_CLEAR0 VIC_REG(0x00B0)
#define VIC_INT_CLEAR1 VIC_REG(0x00B4)
#define VIC_SOFTINT0 VIC_REG(0x00C0)
#define VIC_SOFTINT1 VIC_REG(0x00C4)
#define VIC_IRQ_VEC_RD VIC_REG(0x00D0) /* pending int # */
#define VIC_IRQ_VEC_PEND_RD VIC_REG(0x00D4) /* pending vector addr */
#define VIC_IRQ_VEC_WR VIC_REG(0x00D8)
#define VIC_FIQ_VEC_RD VIC_REG(0x00DC) /* pending int # */
#define VIC_FIQ_VEC_PEND_RD VIC_REG(0x00E0) /* pending vector addr */
#define VIC_FIQ_VEC_WR VIC_REG(0x00E4)
#define VIC_IRQ_IN_SERVICE VIC_REG(0x00E8)
#define VIC_IRQ_IN_STACK VIC_REG(0x00EC)
#define VIC_FIQ_IN_SERVICE VIC_REG(0x00F0)
#define VIC_FIQ_IN_STACK VIC_REG(0x00F4)
#define VIC_TEST_BUS_SEL VIC_REG(0x00F8)
#define SIRC_REG(off) (MSM_SIRC_BASE + (off))
#define SIRC_INT_SELECT SIRC_REG(0x0000) /* 0: IRQ0 1: IRQ1 */
#define SIRC_INT_ENABLE SIRC_REG(0x0004)
#define SIRC_INT_ENCLEAR SIRC_REG(0x0008)
#define SIRC_INT_ENSET SIRC_REG(0x000C)
#define SIRC_INT_TYPE SIRC_REG(0x0010) /* 1: EDGE, 0: LEVEL */
#define SIRC_INT_POLARITY SIRC_REG(0x0014) /* 1: NEG, 0: POS */
#define SIRC_SECURITY SIRC_REG(0x0018) /* 0: SEC, 1: NSEC */
#define SIRC_IRQ0_STATUS SIRC_REG(0x001C)
#define SIRC_IRQ1_STATUS SIRC_REG(0x0020)
#define SIRC_RAW_STATUS SIRC_REG(0x0024)
struct ihandler {
int_handler func;
void *arg;
};
static struct ihandler handler[NR_IRQS];
void platform_init_interrupts(void)
{
writel(0xffffffff, VIC_INT_CLEAR0);
writel(0xffffffff, VIC_INT_CLEAR1);
writel(0, VIC_INT_SELECT0);
writel(0, VIC_INT_SELECT1);
writel(0xffffffff, VIC_INT_TYPE0);
writel(0xffffffff, VIC_INT_TYPE1);
writel(0, VIC_CONFIG);
writel(1, VIC_INT_MASTEREN);
}
enum handler_return platform_irq(struct arm_iframe *frame)
{
unsigned num;
enum handler_return ret;
num = readl(VIC_IRQ_VEC_RD);
num = readl(VIC_IRQ_VEC_PEND_RD);
if (num > NR_IRQS)
return 0;
writel(1 << (num & 31), (num > 31) ? VIC_INT_CLEAR1 : VIC_INT_CLEAR0);
ret = handler[num].func(handler[num].arg);
writel(0, VIC_IRQ_VEC_WR);
return ret;
}
void platform_fiq(struct arm_iframe *frame)
{
PANIC_UNIMPLEMENTED;
}
status_t mask_interrupt(unsigned int vector)
{
unsigned reg = (vector > 31) ? VIC_INT_ENCLEAR1 : VIC_INT_ENCLEAR0;
unsigned bit = 1 << (vector & 31);
writel(bit, reg);
return 0;
}
status_t unmask_interrupt(unsigned int vector)
{
unsigned reg = (vector > 31) ? VIC_INT_ENSET1 : VIC_INT_ENSET0;
unsigned bit = 1 << (vector & 31);
writel(bit, reg);
return 0;
}
void register_int_handler(unsigned int vector, int_handler func, void *arg)
{
if (vector >= NR_IRQS)
return;
enter_critical_section();
handler[vector].func = func;
handler[vector].arg = arg;
exit_critical_section();
}

674
lk/platform/msm7x30/panel.c Normal file

@ -0,0 +1,674 @@
/*
* Copyright (c) 2007, 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 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 <dev/gpio.h>
#include <kernel/thread.h>
#include "gpio_hw.h"
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
static int display_common_power(int);
#if DISPLAY_TYPE_MDDI
#include <mddi.h>
#define MDDI_CLIENT_CORE_BASE 0x108000
#define LCD_CONTROL_BLOCK_BASE 0x110000
#define SPI_BLOCK_BASE 0x120000
#define I2C_BLOCK_BASE 0x130000
#define PWM_BLOCK_BASE 0x140000
#define GPIO_BLOCK_BASE 0x150000
#define SYSTEM_BLOCK1_BASE 0x160000
#define SYSTEM_BLOCK2_BASE 0x170000
#define MDDICAP0 (MDDI_CLIENT_CORE_BASE|0x00)
#define MDDICAP1 (MDDI_CLIENT_CORE_BASE|0x04)
#define MDDICAP2 (MDDI_CLIENT_CORE_BASE|0x08)
#define MDDICAP3 (MDDI_CLIENT_CORE_BASE|0x0C)
#define MDCAPCHG (MDDI_CLIENT_CORE_BASE|0x10)
#define MDCRCERC (MDDI_CLIENT_CORE_BASE|0x14)
#define TTBUSSEL (MDDI_CLIENT_CORE_BASE|0x18)
#define DPSET0 (MDDI_CLIENT_CORE_BASE|0x1C)
#define DPSET1 (MDDI_CLIENT_CORE_BASE|0x20)
#define DPSUS (MDDI_CLIENT_CORE_BASE|0x24)
#define DPRUN (MDDI_CLIENT_CORE_BASE|0x28)
#define SYSCKENA (MDDI_CLIENT_CORE_BASE|0x2C)
#define TESTMODE (MDDI_CLIENT_CORE_BASE|0x30)
#define FIFOMONI (MDDI_CLIENT_CORE_BASE|0x34)
#define INTMONI (MDDI_CLIENT_CORE_BASE|0x38)
#define MDIOBIST (MDDI_CLIENT_CORE_BASE|0x3C)
#define MDIOPSET (MDDI_CLIENT_CORE_BASE|0x40)
#define BITMAP0 (MDDI_CLIENT_CORE_BASE|0x44)
#define BITMAP1 (MDDI_CLIENT_CORE_BASE|0x48)
#define BITMAP2 (MDDI_CLIENT_CORE_BASE|0x4C)
#define BITMAP3 (MDDI_CLIENT_CORE_BASE|0x50)
#define BITMAP4 (MDDI_CLIENT_CORE_BASE|0x54)
#define SRST (LCD_CONTROL_BLOCK_BASE|0x00)
#define PORT_ENB (LCD_CONTROL_BLOCK_BASE|0x04)
#define START (LCD_CONTROL_BLOCK_BASE|0x08)
#define PORT (LCD_CONTROL_BLOCK_BASE|0x0C)
#define CMN (LCD_CONTROL_BLOCK_BASE|0x10)
#define GAMMA (LCD_CONTROL_BLOCK_BASE|0x14)
#define INTFLG (LCD_CONTROL_BLOCK_BASE|0x18)
#define INTMSK (LCD_CONTROL_BLOCK_BASE|0x1C)
#define MPLFBUF (LCD_CONTROL_BLOCK_BASE|0x20)
#define HDE_LEFT (LCD_CONTROL_BLOCK_BASE|0x24)
#define VDE_TOP (LCD_CONTROL_BLOCK_BASE|0x28)
#define PXL (LCD_CONTROL_BLOCK_BASE|0x30)
#define HCYCLE (LCD_CONTROL_BLOCK_BASE|0x34)
#define HSW (LCD_CONTROL_BLOCK_BASE|0x38)
#define HDE_START (LCD_CONTROL_BLOCK_BASE|0x3C)
#define HDE_SIZE (LCD_CONTROL_BLOCK_BASE|0x40)
#define VCYCLE (LCD_CONTROL_BLOCK_BASE|0x44)
#define VSW (LCD_CONTROL_BLOCK_BASE|0x48)
#define VDE_START (LCD_CONTROL_BLOCK_BASE|0x4C)
#define VDE_SIZE (LCD_CONTROL_BLOCK_BASE|0x50)
#define WAKEUP (LCD_CONTROL_BLOCK_BASE|0x54)
#define WSYN_DLY (LCD_CONTROL_BLOCK_BASE|0x58)
#define REGENB (LCD_CONTROL_BLOCK_BASE|0x5C)
#define VSYNIF (LCD_CONTROL_BLOCK_BASE|0x60)
#define WRSTB (LCD_CONTROL_BLOCK_BASE|0x64)
#define RDSTB (LCD_CONTROL_BLOCK_BASE|0x68)
#define ASY_DATA (LCD_CONTROL_BLOCK_BASE|0x6C)
#define ASY_DATB (LCD_CONTROL_BLOCK_BASE|0x70)
#define ASY_DATC (LCD_CONTROL_BLOCK_BASE|0x74)
#define ASY_DATD (LCD_CONTROL_BLOCK_BASE|0x78)
#define ASY_DATE (LCD_CONTROL_BLOCK_BASE|0x7C)
#define ASY_DATF (LCD_CONTROL_BLOCK_BASE|0x80)
#define ASY_DATG (LCD_CONTROL_BLOCK_BASE|0x84)
#define ASY_DATH (LCD_CONTROL_BLOCK_BASE|0x88)
#define ASY_CMDSET (LCD_CONTROL_BLOCK_BASE|0x8C)
#define MONI (LCD_CONTROL_BLOCK_BASE|0xB0)
#define Current (LCD_CONTROL_BLOCK_BASE|0xC0)
#define LCD (LCD_CONTROL_BLOCK_BASE|0xC4)
#define COMMAND (LCD_CONTROL_BLOCK_BASE|0xC8)
#define SSICTL (SPI_BLOCK_BASE|0x00)
#define SSITIME (SPI_BLOCK_BASE|0x04)
#define SSITX (SPI_BLOCK_BASE|0x08)
#define SSIRX (SPI_BLOCK_BASE|0x0C)
#define SSIINTC (SPI_BLOCK_BASE|0x10)
#define SSIINTS (SPI_BLOCK_BASE|0x14)
#define SSIDBG1 (SPI_BLOCK_BASE|0x18)
#define SSIDBG2 (SPI_BLOCK_BASE|0x1C)
#define SSIID (SPI_BLOCK_BASE|0x20)
#define I2CSETUP (I2C_BLOCK_BASE|0x00)
#define I2CCTRL (I2C_BLOCK_BASE|0x04)
#define TIMER0LOAD (PWM_BLOCK_BASE|0x00)
#define TIMER0VALUE (PWM_BLOCK_BASE|0x04)
#define TIMER0CONTROL (PWM_BLOCK_BASE|0x08)
#define TIMER0INTCLR (PWM_BLOCK_BASE|0x0C)
#define TIMER0RIS (PWM_BLOCK_BASE|0x10)
#define TIMER0MIS (PWM_BLOCK_BASE|0x14)
#define TIMER0BGLOAD (PWM_BLOCK_BASE|0x18)
#define PWM0OFF (PWM_BLOCK_BASE|0x1C)
#define TIMER1LOAD (PWM_BLOCK_BASE|0x20)
#define TIMER1VALUE (PWM_BLOCK_BASE|0x24)
#define TIMER1CONTROL (PWM_BLOCK_BASE|0x28)
#define TIMER1INTCLR (PWM_BLOCK_BASE|0x2C)
#define TIMER1RIS (PWM_BLOCK_BASE|0x30)
#define TIMER1MIS (PWM_BLOCK_BASE|0x34)
#define TIMER1BGLOAD (PWM_BLOCK_BASE|0x38)
#define PWM1OFF (PWM_BLOCK_BASE|0x3C)
#define TIMERITCR (PWM_BLOCK_BASE|0x60)
#define TIMERITOP (PWM_BLOCK_BASE|0x64)
#define PWMCR (PWM_BLOCK_BASE|0x68)
#define PWMID (PWM_BLOCK_BASE|0x6C)
#define PWMMON (PWM_BLOCK_BASE|0x70)
#define GPIODATA (GPIO_BLOCK_BASE|0x00)
#define GPIODIR (GPIO_BLOCK_BASE|0x04)
#define GPIOIS (GPIO_BLOCK_BASE|0x08)
#define GPIOIBE (GPIO_BLOCK_BASE|0x0C)
#define GPIOIEV (GPIO_BLOCK_BASE|0x10)
#define GPIOIE (GPIO_BLOCK_BASE|0x14)
#define GPIORIS (GPIO_BLOCK_BASE|0x18)
#define GPIOMIS (GPIO_BLOCK_BASE|0x1C)
#define GPIOIC (GPIO_BLOCK_BASE|0x20)
#define GPIOOMS (GPIO_BLOCK_BASE|0x24)
#define GPIOPC (GPIO_BLOCK_BASE|0x28)
#define GPIOID (GPIO_BLOCK_BASE|0x30)
#define WKREQ (SYSTEM_BLOCK1_BASE|0x00)
#define CLKENB (SYSTEM_BLOCK1_BASE|0x04)
#define DRAMPWR (SYSTEM_BLOCK1_BASE|0x08)
#define INTMASK (SYSTEM_BLOCK1_BASE|0x0C)
#define CNT_DIS (SYSTEM_BLOCK1_BASE|0x10)
#define GPIOSEL (SYSTEM_BLOCK2_BASE|0x00)
struct init_table {
unsigned int reg;
unsigned int val;
};
static struct init_table toshiba_480x800_init_table[] = {
{ DPSET0, 0x4BEC0066 }, // # MDC.DPSET0 # Setup DPLL parameters
{ DPSET1, 0x00000113 }, // # MDC.DPSET1
{ DPSUS, 0x00000000 }, // # MDC.DPSUS # Set DPLL oscillation enable
{ DPRUN, 0x00000001 }, // # MDC.DPRUN # Release reset signal for DPLL
{ 0, 15 }, // wait_ms(15);
{ SYSCKENA, 0x00000001 }, // # MDC.SYSCKENA # Enable system clock output
{ CLKENB, 0x000000E9 }, // # SYS.CLKENB # Enable clocks for each module (without DCLK , i2cCLK)
{ GPIO_BLOCK_BASE, 0x03FF0000 }, // # GPI .GPIODATA # GPIO2(RESET_LCD_N) set to 0 , GPIO3(eDRAM_Power) set to 0
{ GPIODIR, 0x0000024D }, // # GPI .GPIODIR # Select direction of GPIO port (0,2,3,6,9 output)
{ SYSTEM_BLOCK2_BASE, 0x00000173 }, // # SYS.GPIOSEL # GPIO port multiplexing control
{ GPIOPC, 0x03C300C0 }, // # GPI .GPIOPC # GPIO2,3 PD cut
{ SYSTEM_BLOCK1_BASE, 0x00000000 }, // # SYS.WKREQ # Wake-up request event is VSYNC alignment
{ GPIOIS, 0x00000000 }, // # GPI .GPIOIS # Set interrupt sense of GPIO
{ GPIOIEV, 0x00000001 }, // # GPI .GPIOIEV # Set interrupt event of GPIO
{ GPIOIC, 0x000003FF }, // # GPI .GPIOIC # GPIO interrupt clear
{ GPIO_BLOCK_BASE, 0x00040004 }, // # GPI .GPIODATA # Release LCDD reset
{ GPIO_BLOCK_BASE, 0x00080008 }, // # GPI .GPIODATA # eDRAM VD supply
{ DRAMPWR, 0x00000001 }, // # SYS.DRAMPWR # eDRAM power up
{ CLKENB, 0x000000EB }, // # enable eDRAM clock
{ PWMCR, 0x00000000 }, // # PWM.PWMCR # PWM output enable
{ 0, 1 }, // wait_ms(1);
{ SPI_BLOCK_BASE, 0x00060399}, // # SPI .SSICTL # SPI operation mode setting
{ SSITIME, 0x00000100 }, // # SPI .SSITIME # SPI serial interface timing setting
{ CNT_DIS, 0x00000002 }, // # SPI .SSITIME # SPI serial interface timing setting
{ SPI_BLOCK_BASE, 0x0006039B }, // # SPI .SSICTL # Set SPI active mode
{ SSITX, 0x00000000 }, // # SPI.SSITX # Release from Deep Stanby mode
{ 0, 7 }, // wait_ms(2);
{ SSITX, 0x00000000 }, // # SPI.SSITX
{ 0, 7 }, // wait_ms(2);
{ SSITX, 0x00000000 }, // # SPI.SSITX
{ 0, 7 }, // wait_ms(2);
{ SSITX, 0x000800BA }, // # SPI.SSITX *NOTE 1 # Command setting of SPI block
{ SSITX, 0x00000111 }, // # Display mode setup(1) : Normaly Black
{ SSITX, 0x00080036 }, // # Command setting of SPI block
{ SSITX, 0x00000100 }, // # Memory access control
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x0008003A }, // # Command setting of SPI block
{ SSITX, 0x00000160 }, // # Display mode setup(2)
{ SSITX, 0x000800B1 }, // # Command setting of SPI block
{ SSITX, 0x0000015D }, // # RGB Interface data format
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800B2 }, // # Command setting of SPI block
{ SSITX, 0x00000133 }, // # Drivnig method
{ SSITX, 0x000800B3 }, // # Command setting of SPI block
{ SSITX, 0x00000122 }, // # Booster operation setup
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800B4 }, // # Command setting of SPI block
{ SSITX, 0x00000102 }, // # OP-amp capability/System clock freq. division setup
{ SSITX, 0x000800B5 }, // # Command setting of SPI block
{ SSITX, 0x0000011E }, // # VCS Voltage adjustment (1C->1F for Rev 2)
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800B6 }, // # Command setting of SPI block
{ SSITX, 0x00000127 }, // # VCOM Voltage adjustment
{ SSITX, 0x000800B7 }, // # Command setting of SPI block
{ SSITX, 0x00000103 }, // # Configure an external display signal
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800B9 }, // # Command setting of SPI block
{ SSITX, 0x00000124 }, // # DCCK/DCEV timing setup
{ SSITX, 0x000800BD }, // # Command setting of SPI block
{ SSITX, 0x000001A1 }, // # ASW signal control
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800BB }, // # Command setting of SPI block
{ SSITX, 0x00000100 }, // # Dummy display (white/black) count setup for QUAD Data operation
{ SSITX, 0x000800BF }, // # Command setting of SPI block
{ SSITX, 0x00000101 }, // # Dummy display (white/black) count setup for QUAD Data operation
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800BE }, // # Command setting of SPI block
{ SSITX, 0x00000100 }, // # wait_ms(-out FR count setup (A)
{ SSITX, 0x000800C0 }, // # Command setting of SPI block
{ SSITX, 0x00000111 }, // # wait_ms(-out FR count setup (A)
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800C1 }, // # Command setting of SPI block
{ SSITX, 0x00000111 }, // # wait_ms(-out FR count setup (B)
{ SSITX, 0x000800C2 }, // # Command setting of SPI block
{ SSITX, 0x00000111 }, // # wait_ms(-out FR count setup (C)
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800C3 }, // # Command setting of SPI block
{ SSITX, 0x00080132 }, // # wait_ms(-in line clock count setup (D)
{ SSITX, 0x00000132 }, //
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800C4 }, // # Command setting of SPI block
{ SSITX, 0x00080132 }, // # Seep-in line clock count setup (E)
{ SSITX, 0x00000132 }, //
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800C5 }, // # Command setting of SPI block
{ SSITX, 0x00080132 }, // # wait_ms(-in line clock count setup (F)
{ SSITX, 0x00000132 }, //
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800C6 }, // # Command setting of SPI block
{ SSITX, 0x00080132 }, // # wait_ms(-in line clock setup (G)
{ SSITX, 0x00000132 }, //
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800C7 }, // # Command setting of SPI block
{ SSITX, 0x00080164 }, // # Gamma 1 fine tuning (1)
{ SSITX, 0x00000145 }, //
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800C8 }, // # Command setting of SPI block
{ SSITX, 0x00000144 }, // # Gamma 1 fine tuning (2)
{ SSITX, 0x000800C9 }, // # Command setting of SPI block
{ SSITX, 0x00000152 }, // # Gamma 1 inclination adjustment
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800CA }, // # Command setting of SPI block
{ SSITX, 0x00000100 }, // # Gamma 1 blue offset adjustment
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800EC }, // # Command setting of SPI block
{ SSITX, 0x00080102 }, // # Total number of horizontal clock cycles (1) [PCLK Sync. VGA setting]
{ SSITX, 0x00000118 }, //
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800CF }, // # Command setting of SPI block
{ SSITX, 0x00000101 }, // # Blanking period control (1) [PCLK Sync. Table1 for VGA]
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800D0 }, // # Command setting of SPI block
{ SSITX, 0x00080110 }, // # Blanking period control (2) [PCLK Sync. Table1 for VGA]
{ SSITX, 0x00000104 }, //
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800D1 }, // # Command setting of SPI block
{ SSITX, 0x00000101 }, // # CKV timing control on/off [PCLK Sync. Table1 for VGA]
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800D2 }, // # Command setting of SPI block
{ SSITX, 0x00080100 }, // # CKV1,2 timing control [PCLK Sync. Table1 for VGA]
{ SSITX, 0x00000128 }, //
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800D3 }, // # Command setting of SPI block
{ SSITX, 0x00080100 }, // # OEV timing control [PCLK Sync. Table1 for VGA]
{ SSITX, 0x00000128 }, //
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800D4 }, // # Command setting of SPI block
{ SSITX, 0x00080126 }, // # ASW timing control (1) [PCLK Sync. Table1 for VGA]
{ SSITX, 0x000001A4 }, //
{ 0, 1 }, // wait_ms(1); // # Wait SPI fifo empty
{ SSITX, 0x000800D5 }, // # Command setting of SPI block
{ SSITX, 0x00000120 }, // # ASW timing control (2) [PCLK Sync. Table1 for VGA]
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ SSITX, 0x000800EF }, // # Command setting of SPI block
{ SSITX, 0x00080132 }, // # Total number of horizontal clock cycles (2) [PCLK Sync. Table1 for QVGA ]
{ SSITX, 0x00000100 }, //
{ 0, 2 }, // wait_ms(2); // # Wait SPI fifo empty
{ BITMAP0, 0x032001E0 }, // MDC.BITMAP0 ); // Setup of PITCH size to Frame buffer1
{ BITMAP1, 0x032001E0 }, // MDC.BITMAP1 ); // Setup of PITCH size to Frame buffer1
{ BITMAP2, 0x014000F0 }, // MDC.BITMAP3 ); // Setup of PITCH size to Frame buffer2
{ BITMAP3, 0x014000F0 }, // MDC.BITMAP4 ); // Setup of PITCH size to Frame buffer3
{ BITMAP4, 0x014000F0 }, // MDC.BITMAP5 ); // Setup of PITCH size to Frame buffer4
{ CLKENB, 0x000001EB }, // SYS.CLKENB ); // DCLK supply
{ PORT_ENB, 0x00000001 }, // LCD.PORT_ENB ); // Synchronous port enable
{ PORT, 0x00000004 }, // LCD.PORT ); // Polarity of DE is set to high active
{ PXL, 0x00000002 }, // LCD.PXL ); // ACTMODE 2 set (1st frame black data output)
{ MPLFBUF, 0x00000000 }, // LCD.MPLFBUF ); // Select the reading buffer
{ HCYCLE, 0x0000010B }, // LCD.HCYCLE ); // Setup to VGA size
{ HSW, 0x00000003 }, // LCD.HSW
{ HDE_START, 0x00000007 }, // LCD.HDE_START
{ HDE_SIZE, 0x000000EF }, // LCD.HDE_SIZE
{ VCYCLE, 0x00000325 }, // LCD.VCYCLE
{ VSW, 0x00000001 }, // LCD.VSW
{ VDE_START, 0x00000003 }, // LCD.VDE_START
{ VDE_SIZE, 0x0000031F }, // LCD.VDE_SIZE
{ START, 0x00000001 }, // LCD.START ); // LCDC - Pixel data transfer start
{ 0, 10 }, // wait_ms( 10 );
{ SSITX, 0x000800BC }, // SPI.SSITX ); // Command setting of SPI block
{ SSITX, 0x00000180 }, // Display data setup
{ SSITX, 0x0008003B }, // Command setting of SPI block
{ SSITX, 0x00000100 }, // Quad Data configuration - VGA
{ 0, 1 }, // wait_ms( 1 ); // Wait SPI fifo empty
{ SSITX, 0x000800B0 }, // Command setting of SPI block
{ SSITX, 0x00000116 }, // Power supply ON/OFF control
{ 0, 1 }, // wait_ms( 1 ); // Wait SPI fifo empty
{ SSITX, 0x000800B8 }, // Command setting of SPI block
{ SSITX, 0x000801FF }, // Output control
{ SSITX, 0x000001F5 },
{ 0, 1 }, // wait_ms( 1); // Wait SPI fifo empty
{ SSITX, 0x00000011 }, // wait_ms(-out (Command only)
{ 0, 5 }, // wait_ms( 1); // Wait SPI fifo empty
{ SSITX, 0x00000029 }, // Display on (Command only)
//{ SYSTEM_BLOCK1_BASE, 0x00000002 }, // # wakeREQ -> GPIO
{ 0, 0 }
};
void mddi_panel_poweron(void)
{
display_common_power(1);
}
static void _panel_init(struct init_table *init_table)
{
unsigned n;
dprintf(INFO, "panel_init()\n");
n = 0;
while (init_table[n].reg != 0 || init_table[n].val != 0) {
if (init_table[n].reg != 0)
mddi_remote_write(init_table[n].val, init_table[n].reg);
else
mdelay(init_table[n].val);
n++;
}
dprintf(INFO, "panel_init() done\n");
}
void panel_init(struct mddi_client_caps *client_caps)
{
switch(client_caps->manufacturer_name) {
case 0xd263: // Toshiba
dprintf(INFO, "Found Toshiba panel\n");
_panel_init(toshiba_480x800_init_table);
break;
case 0x4474: //??
if (client_caps->product_code == 0xc065)
dprintf(INFO, "Found WVGA panel\n");
break;
}
}
#endif //mddi
void panel_poweron(void)
{
#if DISPLAY_TYPE_LCDC
panel_backlight(1);
lcdc_on();
#endif
}
void panel_backlight(int on)
{
unsigned char reg_data = 0xA0;
if(on)
pmic_write(0x132, reg_data);
else
pmic_write(0x132, 0);
}
static unsigned wega_reset_gpio =
GPIO_CFG(180, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA);
#define LDO12_CNTRL 0x015
#define LDO15_CNTRL 0x089
#define LDO16_CNTRL 0x08A
#define LDO20_CNTRL 0x11F // PM8058 only
#define LDO_LOCAL_EN_BMSK 0x80
static int display_common_power(int on)
{
int rc = 0, flag_on = !!on;
static int display_common_power_save_on;
unsigned int vreg_ldo12, vreg_ldo15, vreg_ldo20, vreg_ldo16, vreg_ldo8;
if (display_common_power_save_on == flag_on)
return 0;
display_common_power_save_on = flag_on;
if (on) {
/* reset Toshiba WeGA chip -- toggle reset pin -- gpio_180 */
rc = gpio_tlmm_config(wega_reset_gpio, GPIO_ENABLE);
if (rc) {
return rc;
}
gpio_set(180, 0); /* bring reset line low to hold reset*/
}
// Set power for WEGA chip.
// Set LD020 to 1.5V
pmic_write(LDO20_CNTRL, 0x00 | LDO_LOCAL_EN_BMSK);
mdelay(5);
// Set LD012 to 1.8V
pmic_write(LDO12_CNTRL, 0x06 | LDO_LOCAL_EN_BMSK);
mdelay(5);
// Set LD016 to 2.6V
pmic_write(LDO16_CNTRL, 0x16 | LDO_LOCAL_EN_BMSK);
mdelay(5);
// Set LD015 to 3.0V
pmic_write(LDO15_CNTRL, 0x1E | LDO_LOCAL_EN_BMSK);
mdelay(5);
gpio_set(180, 1); /* bring reset line high */
mdelay(10); /* 10 msec before IO can be accessed */
if (rc) {
return rc;
}
return rc;
}
#if DISPLAY_TYPE_LCDC
static struct msm_gpio lcd_panel_gpios[] = {
{ GPIO_CFG(45, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "spi_clk" },
{ GPIO_CFG(46, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "spi_cs0" },
{ GPIO_CFG(47, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "spi_mosi" },
{ GPIO_CFG(48, 0, GPIO_INPUT, GPIO_NO_PULL, GPIO_2MA), "spi_miso" }
};
int lcdc_toshiba_panel_power(int on)
{
int rc, i;
struct msm_gpio *gp;
rc = display_common_power(on);
if (rc < 0) {
return rc;
}
if (on) {
rc = platform_gpios_enable(lcd_panel_gpios,
ARRAY_SIZE(lcd_panel_gpios));
if(rc)
{
return rc;
}
} else { /* off */
gp = lcd_panel_gpios;
for (i = 0; i < ARRAY_SIZE(lcd_panel_gpios); i++) {
/* ouput low */
gpio_set(GPIO_PIN(gp->gpio_cfg), 0);
gp++;
}
}
return rc;
}
#define SPI_SCLK 45
#define SPI_CS 46
#define SPI_MOSI 47
#define SPI_MISO 48
static void toshiba_spi_write_byte(char dc, unsigned char data)
{
unsigned bit;
int bnum;
gpio_set(SPI_SCLK, 0); /* clk low */
/* dc: 0 for command, 1 for parameter */
gpio_set(SPI_MOSI, dc);
mdelay(1); /* at least 20 ns */
gpio_set(SPI_SCLK, 1); /* clk high */
mdelay(1); /* at least 20 ns */
bnum = 8; /* 8 data bits */
bit = 0x80;
while (bnum) {
gpio_set(SPI_SCLK, 0); /* clk low */
if (data & bit)
gpio_set(SPI_MOSI, 1);
else
gpio_set(SPI_MOSI, 0);
mdelay(1);
gpio_set(SPI_SCLK, 1); /* clk high */
mdelay(1);
bit >>= 1;
bnum--;
}
}
static int toshiba_spi_write (char cmd, unsigned data, int num)
{
char *bp;
gpio_set(SPI_CS, 1); /* cs high */
/* command byte first */
toshiba_spi_write_byte(0, cmd);
/* followed by parameter bytes */
if (num) {
bp = (char *)&data;;
bp += (num - 1);
while (num) {
toshiba_spi_write_byte(1, *bp);
num--;
bp--;
}
}
gpio_set(SPI_CS, 0); /* cs low */
mdelay(1);
return 0;
}
void lcdc_disp_on (void)
{
gpio_set(SPI_CS, 0); /* low */
gpio_set(SPI_SCLK, 1); /* high */
gpio_set(SPI_MOSI, 0);
gpio_set(SPI_MISO, 0);
if (1) {
toshiba_spi_write(0, 0, 0);
mdelay(7);
toshiba_spi_write(0, 0, 0);
mdelay(7);
toshiba_spi_write(0, 0, 0);
mdelay(7);
toshiba_spi_write(0xba, 0x11, 1);
toshiba_spi_write(0x36, 0x00, 1);
mdelay(1);
toshiba_spi_write(0x3a, 0x60, 1);
toshiba_spi_write(0xb1, 0x5d, 1);
mdelay(1);
toshiba_spi_write(0xb2, 0x33, 1);
toshiba_spi_write(0xb3, 0x22, 1);
mdelay(1);
toshiba_spi_write(0xb4, 0x02, 1);
toshiba_spi_write(0xb5, 0x1e, 1); /* vcs -- adjust brightness */
mdelay(1);
toshiba_spi_write(0xb6, 0x27, 1);
toshiba_spi_write(0xb7, 0x03, 1);
mdelay(1);
toshiba_spi_write(0xb9, 0x24, 1);
toshiba_spi_write(0xbd, 0xa1, 1);
mdelay(1);
toshiba_spi_write(0xbb, 0x00, 1);
toshiba_spi_write(0xbf, 0x01, 1);
mdelay(1);
toshiba_spi_write(0xbe, 0x00, 1);
toshiba_spi_write(0xc0, 0x11, 1);
mdelay(1);
toshiba_spi_write(0xc1, 0x11, 1);
toshiba_spi_write(0xc2, 0x11, 1);
mdelay(1);
toshiba_spi_write(0xc3, 0x3232, 2);
mdelay(1);
toshiba_spi_write(0xc4, 0x3232, 2);
mdelay(1);
toshiba_spi_write(0xc5, 0x3232, 2);
mdelay(1);
toshiba_spi_write(0xc6, 0x3232, 2);
mdelay(1);
toshiba_spi_write(0xc7, 0x6445, 2);
mdelay(1);
toshiba_spi_write(0xc8, 0x44, 1);
toshiba_spi_write(0xc9, 0x52, 1);
mdelay(1);
toshiba_spi_write(0xca, 0x00, 1);
mdelay(1);
toshiba_spi_write(0xec, 0x02a4, 2); /* 0x02a4 */
mdelay(1);
toshiba_spi_write(0xcf, 0x01, 1);
mdelay(1);
toshiba_spi_write(0xd0, 0xc003, 2); /* c003 */
mdelay(1);
toshiba_spi_write(0xd1, 0x01, 1);
mdelay(1);
toshiba_spi_write(0xd2, 0x0028, 2);
mdelay(1);
toshiba_spi_write(0xd3, 0x0028, 2);
mdelay(1);
toshiba_spi_write(0xd4, 0x26a4, 2);
mdelay(1);
toshiba_spi_write(0xd5, 0x20, 1);
mdelay(1);
toshiba_spi_write(0xef, 0x3200, 2);
mdelay(32);
toshiba_spi_write(0xbc, 0x80, 1); /* wvga pass through */
toshiba_spi_write(0x3b, 0x00, 1);
mdelay(1);
toshiba_spi_write(0xb0, 0x16, 1);
mdelay(1);
toshiba_spi_write(0xb8, 0xfff5, 2);
mdelay(1);
toshiba_spi_write(0x11, 0, 0);
mdelay(5);
toshiba_spi_write(0x29, 0, 0);
mdelay(5);
}
}
void lcdc_on(void)
{
lcdc_clock_init(27648000);
lcdc_toshiba_panel_power(1);
lcdc_disp_on();
}
#endif

@ -0,0 +1,141 @@
/*
* Copyright (c) 2008, Google Inc.
* 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.
* * 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 <debug.h>
#include <reg.h>
#include <dev/fbcon.h>
#include <kernel/thread.h>
#include <platform/debug.h>
#include <mddi_hw.h>
#include "gpio_hw.h"
void platform_init_interrupts(void);
void platform_init_timer();
void uart2_clock_init(void);
void uart_init(void);
struct fbcon_config *lcdc_init(void);
#define ARRAY_SIZE(a) (sizeof(a)/(sizeof((a)[0])))
static unsigned uart2_gpio_table[] = {
GPIO_CFG(49, 2, GPIO_OUTPUT, GPIO_PULL_DOWN, GPIO_2MA),
GPIO_CFG(50, 2, GPIO_INPUT, GPIO_PULL_DOWN, GPIO_2MA),
GPIO_CFG(51, 2, GPIO_INPUT, GPIO_PULL_DOWN, GPIO_2MA),
GPIO_CFG(52, 2, GPIO_OUTPUT, GPIO_PULL_DOWN, GPIO_2MA),
};
void uart2_mux_init(void)
{
platform_gpios_enable(uart2_gpio_table, ARRAY_SIZE(uart2_gpio_table));
}
void platform_early_init(void)
{
#if WITH_DEBUG_UART
uart2_mux_init();
uart2_clock_init();
uart_init();
#endif
platform_init_interrupts();
platform_init_timer();
}
void platform_init(void)
{
struct fbcon_config *fb_cfg;
dprintf(INFO, "platform_init()\n");
acpu_clock_init();
adm_enable_clock();
}
void mdp4_display_intf_sel(int output, int intf)
{
unsigned bits, mask;
unsigned dma2_cfg_reg;
bits = readl(MSM_MDP_BASE1 + 0x0038);
mask = 0x03; /* 2 bits */
intf &= 0x03; /* 2 bits */
switch (output) {
case EXTERNAL_INTF_SEL:
intf <<= 4;
mask <<= 4;
break;
case SECONDARY_INTF_SEL:
intf &= 0x02; /* only MDDI and EBI2 support */
intf <<= 2;
mask <<= 2;
break;
default:
break;
}
bits &= ~mask;
bits |= intf;
writel(bits, MSM_MDP_BASE1 + 0x0038); /* MDP_DISP_INTF_SEL */
}
void display_init(void)
{
struct fbcon_config *fb_cfg;
#if DISPLAY_TYPE_MDDI
mddi_clock_init(0, 480000000);
mddi_panel_poweron();
/* We need to config GPIO 38 for Sleep clock with Spl Fun 2 */
toshiba_pmic_gpio_init(GPIO38_GPIO_CNTRL);
fb_cfg = mddi_init();
fbcon_setup(fb_cfg);
#endif
#if DISPLAY_TYPE_LCDC
mdp_clock_init(122880000);
fb_cfg = lcdc_init();
panel_poweron();
fbcon_setup(fb_cfg);
#endif
}
void display_shutdown(void)
{
#if DISPLAY_TYPE_LCDC
/* Turning off LCDC */
lcdc_shutdown();
#endif
}

@ -0,0 +1,29 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
ARCH := arm
ARM_CPU := cortex-a8
#arm1136j-s
CPU := generic
MMC_SLOT := 2
DEFINES += WITH_CPU_EARLY_INIT=1 WITH_CPU_WARM_BOOT=1 \
MMC_SLOT=$(MMC_SLOT) MDP4=1
INCLUDES += -I$(LOCAL_DIR)/include -I$(LK_TOP_DIR)/target/$(TARGET)/include
DEVS += fbcon
MODULES += dev/fbcon
OBJS += \
$(LOCAL_DIR)/arch_init.o \
$(LOCAL_DIR)/platform.o \
$(LOCAL_DIR)/interrupts.o \
$(LOCAL_DIR)/gpio.o \
$(LOCAL_DIR)/panel.o \
$(LOCAL_DIR)/acpuclock.o
LINKER_SCRIPT += $(BUILDDIR)/system-onesegment.ld
include platform/msm_shared/rules.mk

@ -0,0 +1,273 @@
/*
* 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 <stdint.h>
#include <debug.h>
#include <kernel/thread.h>
#include <platform/iomap.h>
#include <platform/clock.h>
#include <reg.h>
/* Read, modify, then write-back a register. */
static void rmwreg(uint32_t val, uint32_t reg, uint32_t mask)
{
uint32_t regval = readl(reg);
regval &= ~mask;
regval |= val;
writel(regval, reg);
}
/* Enable/disable for non-shared NT PLLs. */
int nt_pll_enable(uint8_t src, uint8_t enable)
{
static const struct {
uint32_t const mode_reg;
uint32_t const status_reg;
} pll_reg[] = {
[PLL_1] = { MM_PLL0_MODE_REG, MM_PLL0_STATUS_REG },
[PLL_2] = { MM_PLL1_MODE_REG, MM_PLL1_STATUS_REG },
[PLL_3] = { MM_PLL2_MODE_REG, MM_PLL2_STATUS_REG },
};
uint32_t pll_mode;
pll_mode = readl(pll_reg[src].mode_reg);
if (enable) {
/* Disable PLL bypass mode. */
pll_mode |= (1<<1);
writel( pll_mode, pll_reg[src].mode_reg);
/* H/W requires a 5us delay between disabling the bypass and
* de-asserting the reset. Delay 10us just to be safe. */
udelay(10);
/* De-assert active-low PLL reset. */
pll_mode |= (1<<2);
writel( pll_mode, pll_reg[src].mode_reg);
/* Enable PLL output. */
pll_mode |= (1<<0);
writel( pll_mode, pll_reg[src].mode_reg);
/* Wait until PLL is enabled. */
while (!readl(pll_reg[src].status_reg));
} else {
/* Disable the PLL output, disable test mode, enable
* the bypass mode, and assert the reset. */
pll_mode &= 0xFFFFFFF0;
writel( pll_mode, pll_reg[src].mode_reg);
}
return 0;
}
/* Write the M,N,D values and enable the MDP Core Clock */
void config_mdp_clk( uint32_t ns,
uint32_t md,
uint32_t cc,
uint32_t ns_addr,
uint32_t md_addr,
uint32_t cc_addr)
{
int val = 0;
/* MN counter reset */
val = 1 << 31;
writel(val, ns_addr);
/* Write the MD and CC register values */
writel(md, md_addr);
writel(cc, cc_addr);
/* Reset the clk control, and Write ns val */
val = 1 << 31;
val |= ns;
writel(val, ns_addr);
/* Clear MN counter reset */
val = 1 << 31;
val = ~val;
val = val & readl(ns_addr);
writel(val, ns_addr);
/* Enable MND counter */
val = 1 << 8;
val = val | readl(cc_addr);
writel(val, cc_addr);
/* Enable the root of the clock tree */
val = 1 << 2;
val = val | readl(cc_addr);
writel(val, cc_addr);
/* Enable the MDP Clock */
val = 1 << 0;
val = val | readl(cc_addr);
writel(val, cc_addr);
}
/* Write the M,N,D values and enable the Pixel Core Clock */
void config_pixel_clk( uint32_t ns,
uint32_t md,
uint32_t cc,
uint32_t ns_addr,
uint32_t md_addr,
uint32_t cc_addr){
unsigned int val = 0;
/* Activate the reset for the M/N Counter */
val = 1 << 7;
writel(val, ns_addr);
/* Write the MD and CC register values */
writel(md, md_addr);
writel(cc, cc_addr);
/* Write the ns value, and active reset for M/N Counter, again */
val = 1 << 7;
val |= ns;
writel(val, ns_addr);
/* De-activate the reset for M/N Counter */
val = 1 << 7;
val = ~val;
val = val & readl(ns_addr);
writel(val, ns_addr);
/* Enable MND counter */
val = 1 << 5;
val = val | readl(cc_addr);
writel(val, cc_addr);
/* Enable the root of the clock tree */
val = 1 << 2;
val = val | readl(cc_addr);
writel(val, cc_addr);
/* Enable the MDP Clock */
val = 1 << 0;
val = val | readl(cc_addr);
writel(val, cc_addr);
/* Enable the LCDC Clock */
val = 1 << 8;
val = val | readl(cc_addr);
writel(val, cc_addr);
}
/* Set rate and enable the clock */
void clock_config(uint32_t ns,
uint32_t md,
uint32_t ns_addr,
uint32_t md_addr)
{
unsigned int val = 0;
/* Activate the reset for the M/N Counter */
val = 1 << 7;
writel(val, ns_addr);
/* Write the MD value into the MD register */
writel(md, md_addr);
/* Write the ns value, and active reset for M/N Counter, again */
val = 1 << 7;
val |= ns;
writel(val, ns_addr);
/* De-activate the reset for M/N Counter */
val = 1 << 7;
val = ~val;
val = val & readl(ns_addr);
writel(val, ns_addr);
/* Enable the M/N Counter */
val = 1 << 8;
val = val | readl(ns_addr);
writel(val, ns_addr);
/* Enable the Clock Root */
val = 1 << 11;
val = val | readl(ns_addr);
writel(val, ns_addr);
/* Enable the Clock Branch */
val = 1 << 9;
val = val | readl(ns_addr);
writel(val, ns_addr);
}
void acpu_clock_init (void)
{
}
void hsusb_clock_init(void)
{
int val;
/* Vote for PLL8 */
val = readl(0x009034C0);
val |= (1<<8);
writel(val, 0x009034C0);
/* Wait until PLL is enabled. */
while (!(readl(0x00903158) & (1<<16)));
//Set 7th bit in NS Register
val = 1 << 7;
writel(val, USB_HS1_XVCR_FS_CLK_NS);
//Set rate specific value in MD
writel(0x000500DF, USB_HS1_XVCR_FS_CLK_MD);
//Set value in NS register
val = 1 << 7;
val |= 0x00E400C3;
writel(val, USB_HS1_XVCR_FS_CLK_NS);
// Clear 7th bit
val = 1 << 7;
val = ~val;
val = val & readl(USB_HS1_XVCR_FS_CLK_NS);
writel(val, USB_HS1_XVCR_FS_CLK_NS);
//set 11th bit
val = 1 << 11;
val |= readl(USB_HS1_XVCR_FS_CLK_NS);
writel(val, USB_HS1_XVCR_FS_CLK_NS);
//set 9th bit
val = 1 << 9;
val |= readl(USB_HS1_XVCR_FS_CLK_NS);
writel(val, USB_HS1_XVCR_FS_CLK_NS);
//set 8th bit
val = 1 << 8;
val |= readl(USB_HS1_XVCR_FS_CLK_NS);
writel(val, USB_HS1_XVCR_FS_CLK_NS);
}

@ -0,0 +1,48 @@
/* 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 <reg.h>
#include <platform/iomap.h>
#include <dev/gpio.h>
#include <platform/gpio_hw.h>
void gpio_tlmm_config(uint32_t gpio, uint8_t func,
uint8_t dir, uint8_t pull,
uint8_t drvstr, uint32_t enable)
{
unsigned int val = 0;
val |= pull;
val |= func << 2;
val |= drvstr << 6;
val |= enable << 9;
unsigned int *addr = (unsigned int *)GPIO_BASE_ADDR(gpio);
writel(val, addr);
return;
}

@ -0,0 +1,105 @@
/*
* * 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 __PLATFORM_MSM8X60_CLOCK_H
#define __PLATFORM_MSM8X60_CLOCK_H
/* MMSS CLK CTR base address */
#define MSM_MMSS_CLK_CTL 0x04000000
#define REG_MM(off) (MSM_MMSS_CLK_CTL + (off))
#define AHB_NS_REG REG_MM(0x0004)
#define AXI_NS_REG REG_MM(0x0014)
#define MM_PLL0_CONFIG_REG REG_MM(0x0310)
#define MM_PLL0_L_VAL_REG REG_MM(0x0304)
#define MM_PLL0_M_VAL_REG REG_MM(0x0308)
#define MM_PLL0_MODE_REG REG_MM(0x0300)
#define MM_PLL0_N_VAL_REG REG_MM(0x030C)
#define MM_PLL0_STATUS_REG REG_MM(0x0318)
#define MM_PLL1_CONFIG_REG REG_MM(0x032C)
#define MM_PLL1_L_VAL_REG REG_MM(0x0320)
#define MM_PLL1_M_VAL_REG REG_MM(0x0324)
#define MM_PLL1_MODE_REG REG_MM(0x031C)
#define MM_PLL1_N_VAL_REG REG_MM(0x0328)
#define MM_PLL1_STATUS_REG REG_MM(0x0334)
#define MM_PLL2_CONFIG_REG REG_MM(0x0348)
#define MM_PLL2_L_VAL_REG REG_MM(0x033C)
#define MM_PLL2_M_VAL_REG REG_MM(0x0340)
#define MM_PLL2_MODE_REG REG_MM(0x0338)
#define MM_PLL2_N_VAL_REG REG_MM(0x0344)
#define MM_PLL2_STATUS_REG REG_MM(0x0350)
/* LCD related clock defines */
#define MMSS_AHB_NS_REG (MSM_MMSS_CLK_CTL + 0x04)
#define MMSS_AHB_EN_REG (MSM_MMSS_CLK_CTL + 0x08)
#define MMSS_AXI_NS_REG (MSM_MMSS_CLK_CTL + 0x14)
#define MMSS_MAXI_EN_REG (MSM_MMSS_CLK_CTL + 0x18)
#define MMSS_MAXI_EN2_REG (MSM_MMSS_CLK_CTL + 0x20)
#define MMSS_SAXI_EN_REG (MSM_MMSS_CLK_CTL + 0x30)
#define MDP_CC_REG (MSM_MMSS_CLK_CTL + 0xC0)
#define MDP_MD_REG (MSM_MMSS_CLK_CTL + 0xC4)
#define MDP_NS_REG (MSM_MMSS_CLK_CTL + 0xD0)
#define LCD_PIXEL_CC_REG (MSM_MMSS_CLK_CTL + 0xD4)
#define LCD_PIXEL_NS_REG (MSM_MMSS_CLK_CTL + 0xDC)
#define LCD_PIXEL_MD_REG (MSM_MMSS_CLK_CTL + 0xD8)
/* Configured at 200 MHz */
#define MDP_NS_VAL 0x3F000008
#define MDP_MD_VAL 0x000001FB
#define MDP_CC_VAL 0x00000400
/* Configured at 53.99 MHz */
#define PIXEL_NS_VAL 0xFE4F4002
#define PIXEL_MD_VAL 0x00A9FDA6
#define PIXEL_CC_VAL 0x00000080
#define MSM_CLK_CTL_BASE 0x00900000
#define BB_PLL8_L_VAL_REG (MSM_CLK_CTL_BASE + 0x3144)
#define BB_PLL8_M_VAL_REG (MSM_CLK_CTL_BASE + 0x3148)
#define BB_PLL8_MODE_REG (MSM_CLK_CTL_BASE + 0x3140)
#define BB_PLL8_N_VAL_REG (MSM_CLK_CTL_BASE + 0x314C)
enum clk_sources {
PLL_0 = 0,
PLL_1,
PLL_2,
PLL_3,
PLL_4,
PLL_5,
PLL_6,
PLL_7,
PLL_8,
MXO,
PXO,
CXO,
NUM_SRC
};
#endif

@ -0,0 +1,60 @@
/* 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 __PLATFORM_MSM8X60_GPIO_HW_H
#define __PLATFORM_MSM8X60_GPIO_HW_H
#define TLMM_BASE_ADDR (0x800000)
#define GPIO_BASE (0x1000)
#define GPIO_BASE_ADDR(x) (TLMM_BASE_ADDR + GPIO_BASE + (x)*0x10)
/* GPIO TLMM: Direction */
#define GPIO_INPUT 0
#define GPIO_OUTPUT 1
/* GPIO TLMM: Pullup/Pulldown */
#define GPIO_NO_PULL 0
#define GPIO_PULL_DOWN 1
#define GPIO_KEEPER 2
#define GPIO_PULL_UP 3
/* GPIO TLMM: Drive Strength */
#define GPIO_2MA 0
#define GPIO_4MA 1
#define GPIO_6MA 2
#define GPIO_8MA 3
#define GPIO_10MA 4
#define GPIO_12MA 5
#define GPIO_14MA 6
#define GPIO_16MA 7
/* GPIO TLMM: Status */
#define GPIO_ENABLE 0
#define GPIO_DISABLE 1
#endif

@ -0,0 +1,138 @@
/* 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 _PLATFORM_MSM8X60_IOMAP_H_
#define _PLATFORM_MSM8X60_IOMAP_H_
#define MSM_UART3_BASE 0xA9C00000
#define MSM_VIC_BASE 0x02080000
#define MSM_TMR_BASE 0x02000000
#define MSM_GPT_BASE (MSM_TMR_BASE + 0x04)
#define MSM_CSR_BASE 0x02081000
#define MSM_GCC_BASE 0x02082000
#define MSM_ACC0_BASE 0x02041000
#define MSM_ACC1_BASE 0x02051000
#define MSM_TCSR_BASE 0x16B00000
#define TCSR_WDOG_CFG 0x30
#define MSM_WDT0_RST (MSM_TMR_BASE + 0x38)
#define MSM_WDT0_EN (MSM_TMR_BASE + 0x40)
#define MSM_WDT0_BT (MSM_TMR_BASE + 0x4C)
#define MSM_GIC_CPU_BASE 0x02081000
#define MSM_GIC_DIST_BASE 0x02080000
#define MSM_SDC1_BASE 0x12400000
#define MSM_SHARED_BASE 0x40000000
#define SURF_DEBUG_LED_ADDR 0x1D000202
#define GPIO_CFG133_ADDR 0x00801850
#define GPIO_CFG135_ADDR 0x00801870
#define GPIO_CFG136_ADDR 0x00801880
#define GPIO_CFG137_ADDR 0x00801890
#define GPIO_CFG138_ADDR 0x008018A0
#define GPIO_CFG139_ADDR 0x008018B0
#define GPIO_CFG140_ADDR 0x008018C0
#define GPIO_CFG141_ADDR 0x008018D0
#define GPIO_CFG142_ADDR 0x008018E0
#define GPIO_CFG143_ADDR 0x008018F0
#define GPIO_CFG144_ADDR 0x00801900
#define GPIO_CFG145_ADDR 0x00801910
#define GPIO_CFG146_ADDR 0x00801920
#define GPIO_CFG147_ADDR 0x00801930
#define GPIO_CFG148_ADDR 0x00801940
#define GPIO_CFG149_ADDR 0x00801950
#define GPIO_CFG150_ADDR 0x00801960
#define GPIO_CFG151_ADDR 0x00801970
#define GPIO_CFG152_ADDR 0x00801980
#define GPIO_CFG153_ADDR 0x00801990
#define GPIO_CFG154_ADDR 0x008019A0
#define GPIO_CFG155_ADDR 0x008019B0
#define GPIO_CFG156_ADDR 0x008019C0
#define GPIO_CFG157_ADDR 0x008019D0
#define GPIO_CFG158_ADDR 0x008019E0
#define GSBI1_BASE (0x16000000)
#define GSBI2_BASE (0x16100000)
#define GSBI3_BASE (0x16200000)
#define GSBI4_BASE (0x16300000)
#define GSBI5_BASE (0x16400000)
#define GSBI6_BASE (0x16500000)
#define GSBI7_BASE (0x16600000)
#define GSBI8_BASE (0x19800000)
#define GSBI9_BASE (0x19900000)
#define GSBI10_BASE (0x19A00000)
#define GSBI11_BASE (0x19B00000)
#define GSBI12_BASE (0x19C00000)
#define GSBI1_QUP_BASE (GSBI1_BASE + 0x80000)
#define GSBI2_QUP_BASE (GSBI2_BASE + 0x80000)
#define GSBI3_QUP_BASE (GSBI3_BASE + 0x80000)
#define GSBI4_QUP_BASE (GSBI4_BASE + 0x80000)
#define GSBI5_QUP_BASE (GSBI5_BASE + 0x80000)
#define GSBI6_QUP_BASE (GSBI6_BASE + 0x80000)
#define GSBI7_QUP_BASE (GSBI7_BASE + 0x80000)
#define GSBI8_QUP_BASE (GSBI8_BASE + 0x80000)
#define GSBI9_QUP_BASE (GSBI9_BASE + 0x80000)
#define GSBI10_QUP_BASE (GSBI10_BASE + 0x80000)
#define GSBI11_QUP_BASE (GSBI11_BASE + 0x80000)
#define GSBI12_QUP_BASE (GSBI12_BASE + 0x80000)
#define GSBI_CTL_PROTOCOL_CODE_I2C (0x20)
#define CLK_CTL_BASE 0x00900000
#define GSBIn_HCLK_CTL(n) ((CLK_CTL_BASE) + 0x29C0 + (32 * ((n) - 1)))
#define GSBIn_HCLK_FS(n) ((CLK_CTL_BASE) + 0x29C4 + (32 * ((n) - 1)))
#define GSBIn_QUP_APPS_MD(n) ((CLK_CTL_BASE) + 0x29C8 + (32 * ((n) - 1)))
#define GSBIn_QUP_APPS_NS(n) ((CLK_CTL_BASE) + 0x29CC + (32 * ((n) - 1)))
/* Defines for the GPIO EXPANDER chip, SX1509QIULTRT */
#define GPIO_EXPANDER_REG_OPEN_DRAIN_A (0x0B)
#define GPIO_EXPANDER_REG_DIR_B (0x0E)
#define GPIO_EXPANDER_REG_DIR_A (0x0F)
#define GPIO_EXPANDER_REG_DATA_B (0x10)
#define GPIO_EXPANDER_REG_DATA_A (0x11)
#define CORE_GPIO_EXPANDER_I2C_ADDRESS (0x3E)
#define EEPROM_I2C_ADDRESS (0x52)
#define EBI2_CHIP_SELECT_CFG0 0x1A100000
#define EBI2_XMEM_CS3_CFG1 0x1A110034
#define MSM_USB_BASE 0x12500000
#define USB_HS1_XVCR_FS_CLK_MD 0x00902908
#define USB_HS1_XVCR_FS_CLK_NS 0x0090290C
#endif

@ -0,0 +1,75 @@
/* 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.
*
*/
#ifndef __ASM_ARCH_MSM_IRQS_8x60_H
#define __ASM_ARCH_MSM_IRQS_8x60_H
/* MSM ACPU Interrupt Numbers */
#define GIC_PPI_START 16
#define GIC_SPI_START 32
#define INT_DEBUG_TIMER_EXP (GIC_PPI_START + 0)
#define USB1_HS_IRQ (GIC_SPI_START + 100)
#define USB1_HS_BAM_IRQ (GIC_SPI_START + 94)
#define USB2_IRQ (GIC_SPI_START + 141)
#define USB1_IRQ (GIC_SPI_START + 142)
#define GSBI1_QUP_IRQ (GIC_SPI_START + 147)
#define GSBI2_UART_IRQ (GIC_SPI_START + 148)
#define GSBI2_QUP_IRQ (GIC_SPI_START + 149)
#define GSBI3_UART_IRQ (GIC_SPI_START + 150)
#define GSBI3_QUP_IRQ (GIC_SPI_START + 151)
#define GSBI4_UART_IRQ (GIC_SPI_START + 152)
#define GSBI4_QUP_IRQ (GIC_SPI_START + 153)
#define GSBI5_UART_IRQ (GIC_SPI_START + 154)
#define GSBI5_QUP_IRQ (GIC_SPI_START + 155)
#define GSBI6_UART_IRQ (GIC_SPI_START + 156)
#define GSBI6_QUP_IRQ (GIC_SPI_START + 157)
#define GSBI7_UART_IRQ (GIC_SPI_START + 158)
#define GSBI7_QUP_IRQ (GIC_SPI_START + 159)
#define GSBI8_UART_IRQ (GIC_SPI_START + 160)
#define GSBI8_QUP_IRQ (GIC_SPI_START + 161)
#define GSBI9_UART_IRQ (GIC_SPI_START + 189)
#define GSBI9_QUP_IRQ (GIC_SPI_START + 190)
#define GSBI10_UART_IRQ (GIC_SPI_START + 191)
#define GSBI10_QUP_IRQ (GIC_SPI_START + 192)
#define GSBI11_UART_IRQ (GIC_SPI_START + 193)
#define GSBI11_QUP_IRQ (GIC_SPI_START + 194)
#define GSBI12_UART_IRQ (GIC_SPI_START + 195)
#define GSBI12_QUP_IRQ (GIC_SPI_START + 196)
/* Retrofit universal macro names */
#define INT_USB_HS USB1_HS_IRQ
#define NR_MSM_IRQS 256
#define NR_GPIO_IRQS 173
#define NR_BOARD_IRQS 0
#define NR_IRQS (NR_MSM_IRQS + NR_GPIO_IRQS + NR_BOARD_IRQS)
#endif /* __ASM_ARCH_MSM_IRQS_8x60_H */

@ -0,0 +1,85 @@
/*
* * 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 __PLATFORM_MSM8X60_PMIC_H
#define __PLATFORM_MSM8X60_PMIC_H
/* PMIC 8901 LDO Module defines */
#define PM8901_LDO_BASE (0x2F)
#define PM8901_LDO_L0 (PM8901_LDO_BASE + 0x00)
#define PM8901_LDO_L0_TEST_BANK (PM8901_LDO_BASE + 0x01)
#define PM8901_LDO_L1 (PM8901_LDO_BASE + 0x02)
#define PM8901_LDO_L1_TEST_BANK (PM8901_LDO_BASE + 0x03)
#define PM8901_LDO_L2 (PM8901_LDO_BASE + 0x04)
#define PM8901_LDO_L2_TEST_BANK (PM8901_LDO_BASE + 0x05)
#define PM8901_LDO_L3 (PM8901_LDO_BASE + 0x06)
#define PM8901_LDO_L3_TEST_BANK (PM8901_LDO_BASE + 0x07)
#define PM8901_LDO_L4 (PM8901_LDO_BASE + 0x08)
#define PM8901_LDO_L4_TEST_BANK (PM8901_LDO_BASE + 0x09)
#define PM8901_LDO_L5 (PM8901_LDO_BASE + 0x0A)
#define PM8901_LDO_L5_TEST_BANK (PM8901_LDO_BASE + 0x0B)
#define PM8901_LDO_L6 (PM8901_LDO_BASE + 0x0C)
#define PM8901_LDO_L6_TEST_BANK (PM8901_LDO_BASE + 0x0D)
#define PM8901_LDO_L7 (PM8901_LDO_BASE + 0x0E)
#define PM8901_LDO_L7_TEST_BANK (PM8901_LDO_BASE + 0x0F)
#define PM8901_LDO_TEST_BANK(n) ((n)<<4)
#define PM8901_LDO_CTL_ENABLE__S (7)
#define PM8901_LDO_CTL_PULL_DOWN__S (6)
#define PM8901_LDO_CTL_MODE__S (5)
/* LDO CTL */
#define LDO_CTL_ENABLE_MASK (0x80)
#define LDO_CTL_PULL_DOWN_MASK (0x40)
#define LDO_CTL_NORMAL_POWER_MODE_MASK (0x20)
#define LDO_CTL_VOLTAGE_SET_MASK (0x1F)
/* LDO TEST BANK 2 */
#define LDO_TEST_RANGE_SELECT_MASK (0x01)
/* LDO TEST BANK 4 */
#define LDO_TEST_OUTPUT_RANGE_MASK (0x01)
/* LDO TEST BANK 5 */
#define LDO_TEST_XO_EN_ALL_MASK (0x1F)
/* PMIC 8058 defines */
#define LPG_CTL_0 (0x13C)
#define LPG_CTL_1 (0x13D)
#define LPG_CTL_2 (0x13E)
#define LPG_CTL_3 (0x13F)
#define LPG_CTL_4 (0x140)
#define LPG_CTL_5 (0x141)
#define LPG_CTL_6 (0x142)
#define LPG_BANK_SEL (0x143)
#define LPG_BANK_ENABLE (0x144)
#define GPIO24_GPIO_CNTRL (0x167)
#define GPIO25_GPIO_CNTRL (0x168)
#endif

@ -0,0 +1,187 @@
/*
* 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.
*/
#include <debug.h>
#include <arch/arm.h>
#include <reg.h>
#include <kernel/thread.h>
#include <platform/interrupts.h>
#include <platform/irqs.h>
#include <platform/iomap.h>
#define GIC_CPU_REG(off) (MSM_GIC_CPU_BASE + (off))
#define GIC_DIST_REG(off) (MSM_GIC_DIST_BASE + (off))
#define GIC_CPU_CTRL GIC_CPU_REG(0x00)
#define GIC_CPU_PRIMASK GIC_CPU_REG(0x04)
#define GIC_CPU_BINPOINT GIC_CPU_REG(0x08)
#define GIC_CPU_INTACK GIC_CPU_REG(0x0c)
#define GIC_CPU_EOI GIC_CPU_REG(0x10)
#define GIC_CPU_RUNNINGPRI GIC_CPU_REG(0x14)
#define GIC_CPU_HIGHPRI GIC_CPU_REG(0x18)
#define GIC_DIST_CTRL GIC_DIST_REG(0x000)
#define GIC_DIST_CTR GIC_DIST_REG(0x004)
#define GIC_DIST_ENABLE_SET GIC_DIST_REG(0x100)
#define GIC_DIST_ENABLE_CLEAR GIC_DIST_REG(0x180)
#define GIC_DIST_PENDING_SET GIC_DIST_REG(0x200)
#define GIC_DIST_PENDING_CLEAR GIC_DIST_REG(0x280)
#define GIC_DIST_ACTIVE_BIT GIC_DIST_REG(0x300)
#define GIC_DIST_PRI GIC_DIST_REG(0x400)
#define GIC_DIST_TARGET GIC_DIST_REG(0x800)
#define GIC_DIST_CONFIG GIC_DIST_REG(0xc00)
#define GIC_DIST_SOFTINT GIC_DIST_REG(0xf00)
struct ihandler {
int_handler func;
void *arg;
};
static struct ihandler handler[NR_IRQS];
void platform_init_interrupts(void)
{
platform_gic_dist_init();
platform_gic_cpu_init();
}
void platform_gic_dist_init(void)
{
unsigned int i;
unsigned num_irq = 0;
unsigned cpumask = 1;
cpumask |= cpumask << 8;
cpumask |= cpumask << 16;
/* Disabling GIC */
writel(0, GIC_DIST_CTRL);
/*
* Find out how many interrupts are supported.
*/
num_irq = readl(GIC_DIST_CTR) & 0x1f;
num_irq = (num_irq + 1) * 32;
/* Set each interrupt line to use N-N software model
and edge sensitive, active high */
for (i=32; i < num_irq; i += 16)
writel(0xffffffff, GIC_DIST_CONFIG + i * 4/16 );
writel(0xffffffff, GIC_DIST_CONFIG + 4);
/* Set up interrupts for this CPU */
for (i = 32; i < num_irq; i += 4)
writel(cpumask, GIC_DIST_TARGET + i * 4 / 4);
/* Set priority of all interrupts*/
/*
* In bootloader we dont care about priority so
* setting up equal priorities for all
*/
for (i=0; i < num_irq; i += 4)
writel(0xa0a0a0a0, GIC_DIST_PRI + i * 4/4);
/*Disabling interrupts*/
for (i=0; i < num_irq; i += 32)
writel(0xffffffff, GIC_DIST_ENABLE_CLEAR + i * 4/32);
writel(0x0000ffff, GIC_DIST_ENABLE_SET);
/*Enabling GIC*/
writel(1, GIC_DIST_CTRL);
}
void platform_gic_cpu_init(void)
{
writel(0xf0, GIC_CPU_PRIMASK);
writel(1, GIC_CPU_CTRL);
}
enum handler_return platform_irq(struct arm_iframe *frame)
{
unsigned num;
enum handler_return ret;
num = readl(GIC_CPU_INTACK);
if (num > NR_IRQS)
return 0;
ret = handler[num].func(handler[num].arg);
writel(num, GIC_CPU_EOI);
return ret;
}
void platform_fiq(struct arm_iframe *frame)
{
PANIC_UNIMPLEMENTED;
}
status_t mask_interrupt(unsigned int vector)
{
unsigned reg = GIC_DIST_ENABLE_CLEAR + (vector/32)*4;
unsigned bit = 1 << (vector & 31);
writel(bit, reg);
return 0;
}
status_t unmask_interrupt(unsigned int vector)
{
unsigned reg = GIC_DIST_ENABLE_SET + (vector/32)*4;
unsigned bit = 1 << (vector & 31);
writel(bit, reg);
return 0;
}
void register_int_handler(unsigned int vector, int_handler func, void *arg)
{
if (vector >= NR_IRQS)
return;
enter_critical_section();
handler[vector].func = func;
handler[vector].arg = arg;
exit_critical_section();
}
void clear_pending_int(void)
{
unsigned num_irq = 0;
num_irq = readl(GIC_DIST_CTR) & 0x1f;
num_irq = (num_irq + 1) * 32;
unsigned i;
for (i = 0; i < num_irq; i += 32)
writel(0xffffffff, GIC_DIST_PENDING_CLEAR + i * 4 / 32);
}

@ -0,0 +1,104 @@
/* 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 <string.h>
#include <stdlib.h>
#include <debug.h>
#include <reg.h>
#include "mmc.h"
#define CLK_CTL_BASE 0x00900000
#define SDC_NS(n) (CLK_CTL_BASE + 0x282C + 32*((n) - 1))
#define SDC1_NS SDC_NS(1)
#define SDC2_NS SDC_NS(2)
#define SDC3_NS SDC_NS(3)
#define SDC4_NS SDC_NS(4)
#define SDC5_NS SDC_NS(5)
#define SDC_MD(n) (CLK_CTL_BASE + 0x2828 + 32*((n) - 1))
#define SDC1_MD SDC_MD(1)
#define SDC2_MD SDC_MD(2)
#define SDC3_MD SDC_MD(3)
#define SDC4_MD SDC_MD(4)
#define SDC5_MD SDC_MD(5)
static void mmc_set_clk(unsigned ns, unsigned md)
{
unsigned int val;
/*Clock Init*/
// 1. Set bit 7 in the NS registers
val = 1 << 7;
writel(val, SDC1_NS);
//2. Program MD registers
writel(md, SDC1_MD);
//3. Program NS resgister OR'd with Bit 7
val = 1 << 7;
val |= ns;
writel(val, SDC1_NS);
//4. Clear bit 7 of NS register
val = 1 << 7;
val = ~val;
val = val & readl(SDC1_NS);
writel(val, SDC1_NS);
//5. For MD != NA set bit 8 of NS register
val = 1 << 8;
val = val | readl(SDC1_NS);
writel(val, SDC1_NS);
//6. Set bit 11 in NS register
val = 1 << 11;
val = val | readl(SDC1_NS);
writel(val, SDC1_NS);
//7. Set bit 9 in NS register
val = 1 << 9;
val = val | readl(SDC1_NS);
writel(val, SDC1_NS);
}
void clock_set_enable (unsigned int mclk)
{
if (mclk == MMC_CLK_400KHZ)
{
mmc_set_clk(0x0010005B, 0x0001000F);
}
else if (mclk == MMC_CLK_20MHZ)
{
mmc_set_clk(0x00ED0043, 0x000100EC);
}
else if (mclk == MMC_CLK_48MHZ)
{
mmc_set_clk(0x00FE005B, 0x000100FD);
}
}

363
lk/platform/msm8x60/panel.c Normal file

@ -0,0 +1,363 @@
/*
* * 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 <kernel/thread.h>
#include <i2c_qup.h>
#include <platform/iomap.h>
#include <platform/gpio_hw.h>
#include <platform/clock.h>
#include <platform/pmic.h>
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
static struct qup_i2c_dev *dev = NULL;
uint8_t expander_read(uint8_t addr)
{
uint8_t ret = 0;
/* Create a i2c_msg buffer, that is used to put the controller into read
mode and then to read some data. */
struct i2c_msg msg_buf[] = {
{CORE_GPIO_EXPANDER_I2C_ADDRESS, I2C_M_WR, 1, &addr},
{CORE_GPIO_EXPANDER_I2C_ADDRESS, I2C_M_RD, 1, &ret}
};
qup_i2c_xfer(dev, msg_buf, 2);
return ret;
}
uint8_t expander_write(uint8_t addr, uint8_t val)
{
uint8_t data_buf[] = { addr, val };
/* Create a i2c_msg buffer, that is used to put the controller into write
mode and then to write some data. */
struct i2c_msg msg_buf[] = { {CORE_GPIO_EXPANDER_I2C_ADDRESS,
I2C_M_WR, 2, data_buf}
};
qup_i2c_xfer(dev, msg_buf, 1);
/* Double check that the write worked. */
if (val != expander_read(addr)) {
return -1;
}
return 0;
}
void panel_poweron(void)
{
panel_backlight(1);
lcdc_on();
}
void panel_backlight(int on)
{
}
static int display_common_power(int on)
{
}
static int lcd_power_on()
{
uint8_t buffer = 0x0, mask = 0x0, prev_val = 0x0;
int ret = 0;
/* Configure LDO L2 TEST Bank 2, to Range Select 0 */
buffer = (0x80); /* Write mode */
buffer |= (PM8901_LDO_TEST_BANK(2)); /* Test Bank 2 */
mask = buffer | LDO_TEST_RANGE_SELECT_MASK;
if ((ret = pm8901_test_bank_read(&prev_val,
PM8901_LDO_TEST_BANK(2),
PM8901_LDO_L2_TEST_BANK))) {
return ret;
}
if ((ret = pm8901_vreg_write(&buffer, mask, PM8901_LDO_L2_TEST_BANK,
prev_val))) {
return ret;
}
/* Configure LDO L2 TEST Bank 4, for High Range Mode */
buffer = (0x80); /* Write mode */
buffer |= (PM8901_LDO_TEST_BANK(4)); /* Test Bank 4 */
buffer |= (0x01); /* Put into High Range Mode */
mask = buffer | LDO_TEST_OUTPUT_RANGE_MASK;
if ((ret = pm8901_test_bank_read(&prev_val,
PM8901_LDO_TEST_BANK(4),
PM8901_LDO_L2_TEST_BANK))) {
return ret;
}
if ((ret = pm8901_vreg_write(&buffer, mask, PM8901_LDO_L2_TEST_BANK,
prev_val))) {
return ret;
}
/* Configure LDO L2 TEST Bank 5, for XO_EN<3-0> to 1 */
buffer = (0x80); /* Write mode */
buffer |= (PM8901_LDO_TEST_BANK(5)); /* Test Bank 5 */
buffer |= (0x0F); /* Enable XO_EN */
mask = buffer | LDO_TEST_XO_EN_ALL_MASK;
if ((ret = pm8901_test_bank_read(&prev_val,
PM8901_LDO_TEST_BANK(5),
PM8901_LDO_L2_TEST_BANK))) {
return ret;
}
if ((ret = pm8901_vreg_write(&buffer, mask, PM8901_LDO_L2_TEST_BANK,
prev_val))) {
return ret;
}
/* Enable LDO L2 at Max Voltage (should be around 3.3v) */
buffer = (0x1 << PM8901_LDO_CTL_ENABLE__S);
/* Disable Pull Down */
buffer |= (0x0 << PM8901_LDO_CTL_PULL_DOWN__S);
/* Put LDO into normal mode instead of low power mode */
buffer |= (0x0 << PM8901_LDO_CTL_MODE__S);
/* Write a 31 into the Voltage Programming value to obtain 3.3v VREG =
1.75V + X * 100mV */
buffer |= (0x1F);
mask = buffer | LDO_CTL_ENABLE_MASK |
LDO_CTL_PULL_DOWN_MASK |
LDO_CTL_NORMAL_POWER_MODE_MASK | LDO_CTL_VOLTAGE_SET_MASK;
/* Do a normal read here, as to not destroy the value in LDO control */
if ((ret = pm8901_read(&prev_val, 1, PM8901_LDO_L2))) {
return ret;
}
/* Configure the LDO2 for 3.3v */
ret = pm8901_vreg_write(&buffer, mask, PM8901_LDO_L2, prev_val);
return ret;
}
/* Configures the GPIO that are needed to enable LCD.
* This function also configures the PMIC for PWM control of the LCD backlight.
*/
static void lcd_gpio_cfg(uint8_t on)
{
uint32_t func;
uint32_t pull;
uint32_t dir;
uint32_t enable = 0; /* not used in gpio_tlmm_config */
uint32_t drv;
if (on) {
func = 1; /* Configure GPIO for LCDC function */
pull = GPIO_NO_PULL;
dir = 1; /* doesn't matter since it is not configured as
GPIO */
drv = GPIO_16MA;
} else {
/* As discussed in the MSM8660 FFA HW SW Control Doc configure these
GPIO as input and pull down. */
func = 0; /* GPIO */
pull = GPIO_PULL_DOWN;
dir = 0; /* Input */
drv = 0; /* does not matter configured as input */
}
gpio_tlmm_config(0, func, dir, pull, drv, enable); /* lcdc_pclk */
gpio_tlmm_config(1, func, dir, pull, drv, enable); /* lcdc_hsync */
gpio_tlmm_config(2, func, dir, pull, drv, enable); /* lcdc_vsync */
gpio_tlmm_config(3, func, dir, pull, drv, enable); /* lcdc_den */
gpio_tlmm_config(4, func, dir, pull, drv, enable); /* lcdc_red7 */
gpio_tlmm_config(5, func, dir, pull, drv, enable); /* lcdc_red6 */
gpio_tlmm_config(6, func, dir, pull, drv, enable); /* lcdc_red5 */
gpio_tlmm_config(7, func, dir, pull, drv, enable); /* lcdc_red4 */
gpio_tlmm_config(8, func, dir, pull, drv, enable); /* lcdc_red3 */
gpio_tlmm_config(9, func, dir, pull, drv, enable); /* lcdc_red2 */
gpio_tlmm_config(10, func, dir, pull, drv, enable); /* lcdc_red1 */
gpio_tlmm_config(11, func, dir, pull, drv, enable); /* lcdc_red0 */
gpio_tlmm_config(12, func, dir, pull, drv, enable); /* lcdc_rgn7 */
gpio_tlmm_config(13, func, dir, pull, drv, enable); /* lcdc_rgn6 */
gpio_tlmm_config(14, func, dir, pull, drv, enable); /* lcdc_rgn5 */
gpio_tlmm_config(15, func, dir, pull, drv, enable); /* lcdc_rgn4 */
gpio_tlmm_config(16, func, dir, pull, drv, enable); /* lcdc_rgn3 */
gpio_tlmm_config(17, func, dir, pull, drv, enable); /* lcdc_rgn2 */
gpio_tlmm_config(18, func, dir, pull, drv, enable); /* lcdc_rgn1 */
gpio_tlmm_config(19, func, dir, pull, drv, enable); /* lcdc_rgn0 */
gpio_tlmm_config(20, func, dir, pull, drv, enable); /* lcdc_blu7 */
gpio_tlmm_config(21, func, dir, pull, drv, enable); /* lcdc_blu6 */
gpio_tlmm_config(22, func, dir, pull, drv, enable); /* lcdc_blu5 */
gpio_tlmm_config(23, func, dir, pull, drv, enable); /* lcdc_blu4 */
gpio_tlmm_config(24, func, dir, pull, drv, enable); /* lcdc_blu3 */
gpio_tlmm_config(25, func, dir, pull, drv, enable); /* lcdc_blu2 */
gpio_tlmm_config(26, func, dir, pull, drv, enable); /* lcdc_blu1 */
gpio_tlmm_config(27, func, dir, pull, drv, enable); /* lcdc_blu0 */
}
/* Backlight duty cycle init is used to configure the PMIC8058 for
* PWM output and drive those pins.
*/
static void bl_duty_cycle_init(void)
{
/* Disable backlight LPG channels before configuring them and dedicated
PMIC GPIOs */
pm8058_write_one(0x00, LPG_BANK_ENABLE);
/* Configure PM8058 GPIO24 as a PWM driver (LPG ch0) for chain 1 of 6 LEDs */
pm8058_write_one(0x81, GPIO24_GPIO_CNTRL); /* Write, Bank0, VIN0, Mode
selection enabled */
pm8058_write_one(0x98, GPIO24_GPIO_CNTRL); /* Write, Bank1, OutOn/InOff,
CMOS, Don't Invert Output */
pm8058_write_one(0xAA, GPIO24_GPIO_CNTRL); /* Write, Bank2, GPIO no pull */
pm8058_write_one(0xB4, GPIO24_GPIO_CNTRL); /* Write, Bank3, high drv
strength */
pm8058_write_one(0xC6, GPIO24_GPIO_CNTRL); /* Write, Bank4, Src: LPG_DRV1
(Spec. Fnc 2) */
pm8058_write_one(0xD8, GPIO24_GPIO_CNTRL); /* Write, Bank5, Interrupt
polarity noninversion */
/* Configure PM8058 GPIO25 as a PWM driver (LPG ch1) for chain 2 of 5 LEDs */
pm8058_write_one(0x81, GPIO25_GPIO_CNTRL); /* Write, Bank0, VIN0, Mode
selection enabled */
pm8058_write_one(0x98, GPIO25_GPIO_CNTRL); /* Write, Bank1, OutOn/InOff,
CMOS, Don't Invert Output */
pm8058_write_one(0xAA, GPIO25_GPIO_CNTRL); /* Write, Bank2, GPIO no pull */
pm8058_write_one(0xB4, GPIO25_GPIO_CNTRL); /* Write, Bank3, high drv
strength */
pm8058_write_one(0xC6, GPIO25_GPIO_CNTRL); /* Write, Bank4, Src: LPG_DRV2
(Spec. Fnc 2) */
pm8058_write_one(0xD8, GPIO25_GPIO_CNTRL); /* Write, Bank5, Interrupt
polarity noninversion */
/* Configure PM8058 LPG channel 0 as non-LUT PWM for PM8058 GPIO24 */
pm8058_write_one(0x0, LPG_BANK_SEL); /* Select LPG ch0 slice of control
regs */
pm8058_write_one(0x00, LPG_CTL_0); /* Disable PWM, PWM output, and LPG
ramp generator */
pm8058_write_one(0x40, LPG_CTL_1); /* Dont Toggle, Enable user PWM value,
no LUT high value idx */
pm8058_write_one(0x00, LPG_CTL_2); /* Dont Loop, no LUT low value index */
pm8058_write_one(0xDE, LPG_CTL_3); /* LS 8 bits of 9-bit PWM user value */
pm8058_write_one(0x7F, LPG_CTL_4); /* MSbit of 9-bit PWM user value,
19.2MHz, Dev 6, Expo M = 7 */
pm8058_write_one(0x01, LPG_CTL_5); /* PWM = 9bit, disable pause at high
value LUT index */
pm8058_write_one(0x00, LPG_CTL_6); /* Disable pause at low value LUT index
*/
pm8058_write_one(0x0C, LPG_CTL_0); /* Enable PWM and PWM output, LPG ramp
generator remains disabled */
/* Configure PM8058 LPG chan 1 as PWM for PM8058 GPIO25 */
pm8058_write_one(0x1, LPG_BANK_SEL); /* Select LPG ch1 slice of control
regs */
pm8058_write_one(0x00, LPG_CTL_0); /* Disable PWM, PWM output, and LPG
ramp generator */
pm8058_write_one(0x40, LPG_CTL_1); /* Dont Toggle, Enable user PWM value,
no LUT high value idx */
pm8058_write_one(0x00, LPG_CTL_2); /* Dont Loop, no LUT low value index */
pm8058_write_one(0x00, LPG_CTL_3); /* LS 8 bits of 9-bit PWM user value */
pm8058_write_one(0x7F, LPG_CTL_4); /* MSbit of 9-bit PWM user value,
19.2MHz, Dev 6, Expo M = 7 */
pm8058_write_one(0x01, LPG_CTL_5); /* PWM = 9bit, disable pause at high
value LUT index */
pm8058_write_one(0x00, LPG_CTL_6); /* Disable pause at low value LUT index
*/
pm8058_write_one(0x0C, LPG_CTL_0); /* Enable PWM and PWM output, LPG ramp
generator remains disabled */
/* Enable both LPG channels to enable backlight driver */
pm8058_write_one(0x03, LPG_BANK_ENABLE); /* Enable LPG ch0 (GPIO24) &
ch1 (GPIO25) */
}
void board_lcd_enable(void)
{
dev = qup_i2c_init(GSBI8_BASE, 100000, 24000000);
/* Make sure dev is created and initialized properly */
if (!dev) {
while (1) ;
return;
}
/* Store current value of these registers as to not destroy their previous
state. */
uint8_t open_drain_a = expander_read(GPIO_EXPANDER_REG_OPEN_DRAIN_A);
uint8_t dir_b = expander_read(GPIO_EXPANDER_REG_DIR_B);
uint8_t dir_a = expander_read(GPIO_EXPANDER_REG_DIR_A);
uint8_t data_b = expander_read(GPIO_EXPANDER_REG_DATA_B);
uint8_t data_a = expander_read(GPIO_EXPANDER_REG_DATA_A);
/* Set the LVDS_SHUTDOWN_N to open drain and output low. */
dprintf(INFO, "Enable lvds_shutdown_n line for Open Drain.\n");
expander_write(GPIO_EXPANDER_REG_OPEN_DRAIN_A, 0x04 | open_drain_a);
dprintf(INFO, "Enable lvds_shutdown_n line for output.\n");
expander_write(GPIO_EXPANDER_REG_DIR_A, ~0x04 & dir_a);
dprintf(INFO, "Drive the LVDS_SHUTDOWN_N pin high here.\n");
expander_write(GPIO_EXPANDER_REG_DATA_A, 0x04 | data_a);
/* Turn on the VREG_L2B to 3.3V. */
/* Power on the appropiate PMIC LDO power rails */
if (lcd_power_on())
return;
/* Enable the GPIO as LCDC mode LCD. */
lcd_gpio_cfg(1);
/* Arbitrary delay */
udelay(20000);
/* Set the backlight duty cycle via the PM8058 LPG_DRV1 and LPG_DRV2 */
bl_duty_cycle_init();
dprintf(INFO, "Enable BACKLIGHT_EN line for output.\n");
expander_write(GPIO_EXPANDER_REG_DIR_B, ~0x10 & dir_b);
dprintf(INFO, "Drive BACKLIGHT_EN to high\n");
expander_write(GPIO_EXPANDER_REG_DATA_B, 0x10 | data_b);
}
void mdp_clock_init(void)
{
/* Turn on the PLL2, to ramp up the MDP clock to max (200MHz) */
nt_pll_enable(PLL_2, 1);
config_mdp_clk(MDP_NS_VAL, MDP_MD_VAL,
MDP_CC_VAL, MDP_NS_REG, MDP_MD_REG, MDP_CC_REG);
config_pixel_clk(PIXEL_NS_VAL, PIXEL_MD_VAL,
PIXEL_CC_VAL, LCD_PIXEL_NS_REG,
LCD_PIXEL_MD_REG, LCD_PIXEL_CC_REG);
}
void lcdc_on(void)
{
board_lcd_enable();
}

@ -0,0 +1,151 @@
/*
* 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.
*/
#include <debug.h>
#include <reg.h>
#include <dev/fbcon.h>
#include <kernel/thread.h>
#include <platform/debug.h>
#include <platform/iomap.h>
#include <i2c_qup.h>
#define CONVERT_ENDIAN_U32(val) \
((((uint32_t)(val) & 0x000000FF) << 24) | \
(((uint32_t)(val) & 0x0000FF00) << 8) | \
(((uint32_t)(val) & 0x00FF0000) >> 8) | \
(((uint32_t)(val) & 0xFF000000) >> 24))
#define CONVERT_ENDIAN_U16(val) \
((((uint16_t)(val) & 0x00FF) << 8) | \
(((uint16_t)(val) & 0xFF00) >> 8))
/* Configuration Data Table */
#define CDT_MAGIC_NUMBER 0x43445400
struct cdt_header
{
uint32_t magic; /* Magic number */
uint16_t version; /* Version number */
uint32_t reserved1;
uint32_t reserved2;
}__attribute__((packed));
void platform_init_interrupts(void);
void platform_init_timer();
void uart3_clock_init(void);
void uart_init(void);
struct fbcon_config *lcdc_init(void);
void platform_early_init(void)
{
uart_init();
platform_init_interrupts();
platform_init_timer();
}
void platform_init(void)
{
dprintf(INFO, "platform_init()\n");
}
void display_init(void)
{
struct fbcon_config *fb_cfg;
#if DISPLAY_TYPE_LCDC
mdp_clock_init();
fb_cfg = lcdc_init();
panel_poweron();
fbcon_setup(fb_cfg);
#endif
#if DISPLAY_TYPE_MIPI
mdp_clock_init();
fb_cfg = mipi_init();
fbcon_setup(fb_cfg);
#endif
}
void display_shutdown(void)
{
#if DISPLAY_TYPE_LCDC
/* Turning off LCDC */
lcdc_shutdown();
#endif
#if DISPLAY_TYPE_MIPI
mipi_dsi_shutdown();
#endif
}
static struct qup_i2c_dev* dev = NULL;
uint32_t eprom_read (uint16_t addr, uint8_t count) {
uint32_t ret = 0;
if(!dev){
return ret;
}
/* Create a i2c_msg buffer, that is used to put the controller into
* read mode and then to read some data.
*/
struct i2c_msg msg_buf[] = {
{EEPROM_I2C_ADDRESS, I2C_M_WR, 2, &addr},
{EEPROM_I2C_ADDRESS, I2C_M_RD, count, &ret}
};
qup_i2c_xfer(dev, msg_buf, 2);
return ret;
}
/* Read EEPROM to find out product id. Return 0 in case of failure */
uint32_t platform_id_read (void)
{
uint32_t id = 0;
uint16_t offset = 0;
dev = qup_i2c_init(GSBI8_BASE, 100000, 24000000);
if(!dev){
return id;
}
/* Check if EPROM is valid */
if (CONVERT_ENDIAN_U32(eprom_read(0, 4)) == CDT_MAGIC_NUMBER)
{
/* Get offset for platform ID info from Meta Data block 0 */
offset = eprom_read(CONVERT_ENDIAN_U16(0 +
sizeof(struct cdt_header)), 2);
/* Read platform ID */
id = eprom_read(CONVERT_ENDIAN_U16(offset), 4);
id = CONVERT_ENDIAN_U32(id);
id = (id & 0x00FF0000) >> 16;
}
return id;
}

101
lk/platform/msm8x60/pmic.c Normal file

@ -0,0 +1,101 @@
/*
* * 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 <reg.h>
#include <platform/iomap.h>
#include <platform/pmic.h>
typedef int (*pm8058_write_func) (unsigned char *, unsigned short,
unsigned short);
extern int pa1_ssbi2_write_bytes(unsigned char *buffer, unsigned short length,
unsigned short slave_addr);
/*PM8058*/
void pm8058_write_one(unsigned data, unsigned address)
{
pm8058_write_func wr_function = &pa1_ssbi2_write_bytes;
if (wr_function == NULL)
return;
if ((*wr_function) (&data, 1, address))
dprintf(CRITICAL, "Error in initializing register\n");
}
/*PM8901*/
extern int pa2_ssbi2_write_bytes(unsigned char *buffer, unsigned short length,
unsigned short slave_addr);
extern int pa2_ssbi2_read_bytes(unsigned char *buffer, unsigned short length,
unsigned short slave_addr);
/*
* Write to the control registers on PMIC via the SSBI2 interface.
* Returns : (0) on success and (-1) on error.
*/
int pm8901_write(uint8_t * buffer, uint32_t length, uint32_t slave_addr)
{
return pa2_ssbi2_write_bytes(buffer, length, slave_addr);
}
/*
* Read from the control registers on PMIC via the SSBI2 interface.
* Returns : (0) on success and (-1) on error.
*/
int pm8901_read(uint8_t * buffer, uint32_t length, uint32_t slave_addr)
{
return pa2_ssbi2_read_bytes(buffer, length, slave_addr);
}
/*
* PMIC 8901 LDO vreg read.
*/
int pm8901_test_bank_read(uint8_t * buffer, uint8_t bank, uint16_t addr)
{
int ret = pm8901_write(&bank, 1, addr);
/* if the write does not work we can't read. */
if (ret) {
return ret;
}
return pm8901_read(buffer, 1, addr);
}
/*
* PMIC 8901 LDO vreg write.
*/
int pm8901_vreg_write(uint8_t * buffer, uint8_t mask, uint16_t addr,
uint8_t prev_val)
{
uint8_t reg;
/* Clear the bits we want to try and set. */
reg = (prev_val & ~mask);
/* Set the bits we want to set, before writing them to addr */
reg |= (*buffer & mask);
return pm8901_write(&reg, 1, addr);
}

@ -0,0 +1,30 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
ARCH := arm
ARM_CPU := cortex-a8
#arm1136j-s
CPU := generic
MMC_SLOT := 1
DEFINES += WITH_CPU_EARLY_INIT=0 WITH_CPU_WARM_BOOT=0 \
MMC_SLOT=$(MMC_SLOT) MDP4=1
INCLUDES += -I$(LOCAL_DIR)/include -I$(LK_TOP_DIR)/platform/msm_shared/include
DEVS += fbcon
MODULES += dev/fbcon
OBJS += \
$(LOCAL_DIR)/platform.o \
$(LOCAL_DIR)/interrupts.o \
$(LOCAL_DIR)/acpuclock.o \
$(LOCAL_DIR)/mmc_init.o \
$(LOCAL_DIR)/gpio.o \
$(LOCAL_DIR)/panel.o \
$(LOCAL_DIR)/pmic.o
LINKER_SCRIPT += $(BUILDDIR)/system-onesegment.ld
include platform/msm_shared/rules.mk

@ -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.
*/
.text
.globl __cpu_early_init
__cpu_early_init:
/* do an omap3 specific setup of the L2 */
mov r12, #1
.word 0xe1600070
bx lr

86
lk/platform/omap3/debug.c Normal file

@ -0,0 +1,86 @@
/*
* 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 <stdarg.h>
#include <reg.h>
#include <debug.h>
#include <printf.h>
#include <kernel/thread.h>
#include <platform/debug.h>
#include <arch/ops.h>
#include <dev/uart.h>
#include <target/debugconfig.h>
void _dputc(char c)
{
if (c == '\n')
uart_putc(DEBUG_UART, '\r');
uart_putc(DEBUG_UART, c);
}
int dgetc(char *c)
{
int _c;
if ((_c = uart_getc(DEBUG_UART, false)) < 0)
return -1;
*c = _c;
return 0;
}
void debug_dump_regs(void)
{
PANIC_UNIMPLEMENTED;
}
void platform_halt(void)
{
dprintf(ALWAYS, "HALT: spinning forever...\n");
for(;;);
}
void debug_dump_memory_bytes(void *mem, int len)
{
PANIC_UNIMPLEMENTED;
}
void debug_dump_memory_halfwords(void *mem, int len)
{
PANIC_UNIMPLEMENTED;
}
void debug_dump_memory_words(void *mem, int len)
{
PANIC_UNIMPLEMENTED;
}
void debug_set_trace_level(int trace_type, int level)
{
PANIC_UNIMPLEMENTED;
}
uint32_t debug_cycle_count(void)
{
// PANIC_UNIMPLEMENTED;
return 0;
}

315
lk/platform/omap3/i2c.c Normal file

@ -0,0 +1,315 @@
/*
* 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 <reg.h>
#include <string.h>
#include <platform.h>
#include <platform/omap3.h>
#define LOCAL_TRACE 0
#define I2C_TIMEOUT 200
static const addr_t i2c_reg_base[] = {
I2C1_BASE,
I2C2_BASE,
I2C3_BASE,
};
#define I2C_REG_ADDR(bus, reg) (i2c_reg_base[bus] + (reg))
#define I2C_REG(bus, reg) (*REG16(I2C_REG_ADDR(bus, reg)))
#define I2C_RMW_REG(bus, reg, startbit, width, val) RMWREG16(I2C_REG_ADDR(bus, reg), startbit, width, val)
static void i2c_dump_bus(int bus)
{
hexdump((void *)i2c_reg_base[bus], 128);
}
static void i2c_reset_bus(int bus)
{
I2C_REG(bus, I2C_CON) &= ~(1<<15); // make sure the bus is disabled
/* reset the bus */
I2C_REG(bus, I2C_SYSC) = (1<<1);
I2C_REG(bus, I2C_CON) = (1<<15); // enable the bus
while ((I2C_REG(bus, I2C_SYSS) & 1) == 0)
;
/* disable the bus again and set up some internals */
I2C_REG(bus, I2C_CON) &= ~(1<<15); // make sure the bus is disabled
/* set up the clock */
I2C_REG(bus, I2C_PSC) = 23; // 96Mhz / 23 == 4Mhz
I2C_REG(bus, I2C_SCLL) = 13;
I2C_REG(bus, I2C_SCLH) = 15; // 4Mhz / combined divider of 40 (13+7 + 15+5) == 100khz
/* slave address */
I2C_REG(bus, I2C_OA0) = 1; // XXX made this up
/* fifo is set to 1 byte trigger */
I2C_REG(bus, I2C_BUF) = 0;
/* disable all interrupts */
I2C_REG(bus, I2C_IE) = 0;
/* enable the bus */
I2C_REG(bus, I2C_CON) = (1<<15)|(1<<10)|(1<<9); // enable, master, transmitter mode
}
static void i2c_wait_for_bb(int bus)
{
I2C_REG(bus, I2C_STAT) = 0xffff; // clear whatever is pending
while (I2C_REG(bus, I2C_STAT) & (1<<12)) {
I2C_REG(bus, I2C_STAT) = 0xffff; // clear whatever is pending
}
I2C_REG(bus, I2C_STAT) = 0xffff; // clear whatever is pending
}
int i2c_transmit(int bus, uint8_t address, const void *buf, size_t count)
{
int err;
LTRACEF("bus %d, address 0x%hhx, buf %p, count %zd\n", bus, address, buf, count);
i2c_wait_for_bb(bus);
I2C_REG(bus, I2C_SA) = address;
I2C_REG(bus, I2C_CNT) = count;
I2C_REG(bus, I2C_CON) = (1<<15)|(1<<10)|(1<<9)|(1<<1)|(1<<0); // enable, master, transmit, STP, STT
time_t t = current_time();
const uint8_t *ptr = (const uint8_t *)buf;
for(;;) {
uint16_t stat = I2C_REG(bus, I2C_STAT);
if (stat & (1<<1)) {
// NACK
// printf("NACK\n");
err = -1;
goto out;
}
if (stat & (1<<0)) {
// AL (arbitration lost)
// printf("arbitration lost!\n");
err = -1;
goto out;
}
if (stat & (1<<2)) {
// ARDY
// printf("ARDY, completed\n");
break;
}
if (stat & (1<<4)) {
// RRDY
// printf("XRDY\n");
// transmit a byte
*REG8(I2C_REG_ADDR(bus, I2C_DATA)) = *ptr;
ptr++;
}
I2C_REG(bus, I2C_STAT) = stat;
if (current_time() - t > I2C_TIMEOUT) {
// printf("i2c timeout\n");
err = ERR_TIMED_OUT;
goto out;
}
}
err = 0;
out:
I2C_REG(bus, I2C_STAT) = 0xffff;
I2C_REG(bus, I2C_CNT) = 0;
return err;
}
int i2c_receive(int bus, uint8_t address, void *buf, size_t count)
{
int err;
LTRACEF("bus %d, address 0x%hhx, buf %p, count %zd\n", bus, address, buf, count);
i2c_wait_for_bb(bus);
I2C_REG(bus, I2C_SA) = address;
I2C_REG(bus, I2C_CNT) = count;
I2C_REG(bus, I2C_CON) = (1<<15)|(1<<10)|(1<<1)|(1<<0); // enable, master, STP, STT
time_t t = current_time();
uint8_t *ptr = (uint8_t *)buf;
for(;;) {
uint16_t stat = I2C_REG(bus, I2C_STAT);
if (stat & (1<<1)) {
// NACK
// printf("NACK\n");
err = -1;
goto out;
}
if (stat & (1<<0)) {
// AL (arbitration lost)
// printf("arbitration lost!\n");
err = -1;
goto out;
}
if (stat & (1<<2)) {
// ARDY
// printf("ARDY, completed\n");
break;
}
if (stat & (1<<3)) {
// RRDY
// printf("RRDY\n");
// read a byte, since our fifo threshold is set to 1 byte
*ptr = *REG8(I2C_REG_ADDR(bus, I2C_DATA));
ptr++;
}
I2C_REG(bus, I2C_STAT) = stat;
if (current_time() - t > I2C_TIMEOUT) {
// printf("i2c timeout\n");
err = ERR_TIMED_OUT;
goto out;
}
}
err = 0;
out:
I2C_REG(bus, I2C_STAT) = 0xffff;
I2C_REG(bus, I2C_CNT) = 0;
return err;
}
int i2c_write_reg(int bus, uint8_t address, uint8_t reg, uint8_t val)
{
uint8_t buf[2];
buf[0] = reg;
buf[1] = val;
return i2c_transmit(bus, address, buf, 2);
}
int i2c_read_reg(int bus, uint8_t address, uint8_t reg, uint8_t *val)
{
int err = i2c_transmit(bus, address, &reg, 1);
if (err < 0)
return err;
return i2c_receive(bus, address, val, 1);
}
void i2c_init_early(void)
{
LTRACE_ENTRY;
/* enable clocks on i2c 0-2 */
RMWREG32(CM_FCLKEN1_CORE, 15, 3, 0x7),
RMWREG32(CM_ICLKEN1_CORE, 15, 3, 0x7),
i2c_reset_bus(0);
i2c_reset_bus(1);
i2c_reset_bus(2);
#if 0
// write something into a reg
char buf[2];
i2c_write_reg(0, 0x4b, 0x14, 0x99);
i2c_write_reg(0, 0x4b, 0x15, 0x98);
i2c_read_reg(0, 0x4b, 0x15, buf);
printf("0x%hhx\n", buf[0]);
i2c_read_reg(0, 0x4b, 0x14, buf);
printf("0x%hhx\n", buf[0]);
int i;
for (i=0; i < 255; i++) {
char buf[1];
buf[0] = i;
i2c_transmit(0, 0x4b, buf, 1);
i2c_receive(0, 0x4b, buf, sizeof(buf));
printf("0x%hhx\n", buf[0]);
}
#endif
LTRACE_EXIT;
}
void i2c_init(void)
{
}
#if WITH_LIB_CONSOLE
#include <lib/console.h>
static int cmd_i2c(int argc, const cmd_args *argv);
STATIC_COMMAND_START
{ "i2c", "i2c read/write commands", &cmd_i2c },
STATIC_COMMAND_END(i2c);
static int cmd_i2c(int argc, const cmd_args *argv)
{
int err;
if (argc < 5) {
printf("not enough arguments\n");
usage:
printf("%s read_reg <bus> <i2c address> <register>\n", argv[0].str);
printf("%s write_reg <bus> <i2c address> <register> <val>\n", argv[0].str);
return -1;
}
int bus = argv[2].u;
uint8_t i2c_address = argv[3].u;
if (!strcmp(argv[1].str, "read_reg")) {
uint8_t reg = argv[4].u;
uint8_t val;
err = i2c_read_reg(bus, i2c_address, reg, &val);
printf("i2c_read_reg err %d, val 0x%hhx\n", err, val);
} else if (!strcmp(argv[1].str, "write_reg")) {
uint8_t reg = argv[4].u;
uint8_t val = argv[5].u;
err = i2c_write_reg(bus, i2c_address, reg, val);
printf("i2c_write_reg err %d\n", err);
} else {
printf("unrecognized subcommand\n");
goto usage;
}
return 0;
}
#endif // WITH_APP_CONSOLE

@ -0,0 +1,257 @@
/*
* 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 __PLATFORM_OMAP3_H
#define __PLATFORM_OMAP3_H
#define SDRAM_BASE 0x80000000
#define L4_BASE 0x48000000
#define L4_WKUP_BASE 0x48300000
#define L4_PER_BASE 0x49000000
#define L4_EMU_BASE 0x54000000
#define GFX_BASE 0x50000000
#define L3_BASE 0x68000000
#define SMS_BASE 0x6C000000
#define SDRC_BASE 0x6D000000
#define GPMC_BASE 0x6E000000
#define SCM_BASE 0x48002000
/* clocks */
#define CM_CLKSEL_PER (L4_BASE + 0x5040)
/* PRCM */
#define CM_FCLKEN_IVA2 (L4_BASE + 0x4000)
#define CM_CLKEN_PLL_IVA2 (L4_BASE + 0x4004)
#define CM_IDLEST_PLL_IVA2 (L4_BASE + 0x4024)
#define CM_CLKSEL1_PLL_IVA2 (L4_BASE + 0x4040)
#define CM_CLKSEL2_PLL_IVA2 (L4_BASE + 0x4044)
#define CM_CLKEN_PLL_MPU (L4_BASE + 0x4904)
#define CM_IDLEST_PLL_MPU (L4_BASE + 0x4924)
#define CM_CLKSEL1_PLL_MPU (L4_BASE + 0x4940)
#define CM_CLKSEL2_PLL_MPU (L4_BASE + 0x4944)
#define CM_FCLKEN1_CORE (L4_BASE + 0x4a00)
#define CM_ICLKEN1_CORE (L4_BASE + 0x4a10)
#define CM_ICLKEN2_CORE (L4_BASE + 0x4a14)
#define CM_CLKSEL_CORE (L4_BASE + 0x4a40)
#define CM_FCLKEN_GFX (L4_BASE + 0x4b00)
#define CM_ICLKEN_GFX (L4_BASE + 0x4b10)
#define CM_CLKSEL_GFX (L4_BASE + 0x4b40)
#define CM_FCLKEN_WKUP (L4_BASE + 0x4c00)
#define CM_ICLKEN_WKUP (L4_BASE + 0x4c10)
#define CM_CLKSEL_WKUP (L4_BASE + 0x4c40)
#define CM_IDLEST_WKUP (L4_BASE + 0x4c20)
#define CM_CLKEN_PLL (L4_BASE + 0x4d00)
#define CM_IDLEST_CKGEN (L4_BASE + 0x4d20)
#define CM_CLKSEL1_PLL (L4_BASE + 0x4d40)
#define CM_CLKSEL2_PLL (L4_BASE + 0x4d44)
#define CM_CLKSEL3_PLL (L4_BASE + 0x4d48)
#define CM_FCLKEN_DSS (L4_BASE + 0x4e00)
#define CM_ICLKEN_DSS (L4_BASE + 0x4e10)
#define CM_CLKSEL_DSS (L4_BASE + 0x4e40)
#define CM_FCLKEN_CAM (L4_BASE + 0x4f00)
#define CM_ICLKEN_CAM (L4_BASE + 0x4f10)
#define CM_CLKSEL_CAM (L4_BASE + 0x4F40)
#define CM_FCLKEN_PER (L4_BASE + 0x5000)
#define CM_ICLKEN_PER (L4_BASE + 0x5010)
#define CM_CLKSEL_PER (L4_BASE + 0x5040)
#define CM_CLKSEL1_EMU (L4_BASE + 0x5140)
#define PRM_CLKSEL (L4_BASE + 0x306d40)
#define PRM_RSTCTRL (L4_BASE + 0x307250)
#define PRM_CLKSRC_CTRL (L4_BASE + 0x307270)
/* General Purpose Timers */
#define OMAP34XX_GPT1 (L4_BASE + 0x318000)
#define OMAP34XX_GPT2 (L4_BASE + 0x1032000)
#define OMAP34XX_GPT3 (L4_BASE + 0x1034000)
#define OMAP34XX_GPT4 (L4_BASE + 0x1036000)
#define OMAP34XX_GPT5 (L4_BASE + 0x1038000)
#define OMAP34XX_GPT6 (L4_BASE + 0x103A000)
#define OMAP34XX_GPT7 (L4_BASE + 0x103C000)
#define OMAP34XX_GPT8 (L4_BASE + 0x103E000)
#define OMAP34XX_GPT9 (L4_BASE + 0x1040000)
#define OMAP34XX_GPT10 (L4_BASE + 0x86000)
#define OMAP34XX_GPT11 (L4_BASE + 0x88000)
#define OMAP34XX_GPT12 (L4_BASE + 0x304000)
#define TIDR 0x00
#define TIOCP_CFG 0x10
#define TISTAT 0x14
#define TISR 0x18
#define TIER 0x1C
#define TWER 0x20
#define TCLR 0x24
#define TCRR 0x28
#define TLDR 0x2C
#define TTGR 0x30
#define TWPS 0x34
#define TMAR 0x38
#define TCAR1 0x3C
#define TSICR 0x40
#define TCAR2 0x44
#define TPIR 0x48
#define TNIR 0x4C
#define TCVR 0x50
#define TOCR 0x54
#define TOWR 0x58
/* WatchDog Timers (1 secure, 3 GP) */
#define WD1_BASE (0x4830C000)
#define WD2_BASE (0x48314000)
#define WD3_BASE (0x49030000)
#define WIDR 0x00
#define WD_SYSCONFIG 0x10
#define WD_SYSSTATUS 0x14
#define WISR 0x18
#define WIER 0x1C
#define WCLR 0x24
#define WCRR 0x28
#define WLDR 0x2C
#define WTGR 0x30
#define WWPS 0x34
#define WSPR 0x48
#define W_PEND_WCLR (1<<0)
#define W_PEND_WCRR (1<<1)
#define W_PEND_WLDR (1<<2)
#define W_PEND_WTGR (1<<3)
#define W_PEND_WSPR (1<<4)
#define WD_UNLOCK1 0xAAAA
#define WD_UNLOCK2 0x5555
/* 32KTIMER */
#define TIMER32K_BASE (L4_BASE + 0x320000)
#define TIMER32K_REV (TIMER32K_BASE + 0x00)
#define TIMER32K_CR (TIMER32K_BASE + 0x10)
/* UART */
#define OMAP_UART1_BASE (L4_BASE + 0x6a000)
#define OMAP_UART2_BASE (L4_BASE + 0x6c000)
#define OMAP_UART3_BASE (L4_BASE + 0x01020000)
#define UART_RHR 0
#define UART_THR 0
#define UART_DLL 0
#define UART_IER 1
#define UART_DLH 1
#define UART_IIR 2
#define UART_FCR 2
#define UART_EFR 2
#define UART_LCR 3
#define UART_MCR 4
#define UART_LSR 5
#define UART_MSR 6
#define UART_TCR 6
#define UART_SPR 7
#define UART_TLR 7
#define UART_MDR1 8
#define UART_MDR2 9
#define UART_SFLSR 10
#define UART_RESUME 11
#define UART_TXFLL 10
#define UART_TXFLH 11
#define UART_SFREGL 12
#define UART_SFREGH 13
#define UART_RXFLL 12
#define UART_RXFLH 13
#define UART_BLR 14
#define UART_UASR 14
#define UART_ACREG 15
#define UART_SCR 16
#define UART_SSR 17
#define UART_EBLR 18
#define UART_MVR 19
#define UART_SYSC 20
/* MPU INTC */
#define INTC_BASE (L4_BASE + 0x200000)
#define INTC_REVISION (INTC_BASE + 0x000)
#define INTC_SYSCONFIG (INTC_BASE + 0x010)
#define INTC_SYSSTATUS (INTC_BASE + 0x014)
#define INTC_SIR_IRQ (INTC_BASE + 0x040)
#define INTC_SIR_FIQ (INTC_BASE + 0x044)
#define INTC_CONTROL (INTC_BASE + 0x048)
#define INTC_PROTECTION (INTC_BASE + 0x04C)
#define INTC_IDLE (INTC_BASE + 0x050)
#define INTC_IRQ_PRIORITY (INTC_BASE + 0x060)
#define INTC_FIQ_PRIORITY (INTC_BASE + 0x064)
#define INTC_THRESHOLD (INTC_BASE + 0x068)
#define INTC_ITR(n) (INTC_BASE + 0x080 + (n) * 0x20)
#define INTC_MIR(n) (INTC_BASE + 0x084 + (n) * 0x20)
#define INTC_MIR_CLEAR(n) (INTC_BASE + 0x088 + (n) * 0x20)
#define INTC_MIR_SET(n) (INTC_BASE + 0x08C + (n) * 0x20)
#define INTC_ISR_SET(n) (INTC_BASE + 0x090 + (n) * 0x20)
#define INTC_ISR_CLEAR(n) (INTC_BASE + 0x094 + (n) * 0x20)
#define INTC_PENDING_IRQ(n) (INTC_BASE + 0x098 + (n) * 0x20)
#define INTC_PENDING_FIQ(n) (INTC_BASE + 0x09C + (n) * 0x20)
#define INTC_ILR(n) (INTC_BASE + 0x100 + (n) * 4)
/* interrupts */
#define INT_VECTORS 96
#define GPT2_IRQ 38
/* HS USB */
#define USB_HS_BASE (L4_BASE + 0xab000)
/* USB OTG */
#define OTG_BASE (L4_BASE + 0xab400)
#define OTG_REVISION (OTG_BASE + 0x00)
#define OTG_SYSCONFIG (OTG_BASE + 0x04)
#define OTG_SYSSTATUS (OTG_BASE + 0x08)
#define OTG_INTERFSEL (OTG_BASE + 0x0C)
#define OTG_SIMENABLE (OTG_BASE + 0x10)
#define OTG_FORCESTDBY (OTG_BASE + 0x14)
/* I2C */
#define I2C1_BASE (L4_BASE + 0x70000)
#define I2C2_BASE (L4_BASE + 0x72000)
#define I2C3_BASE (L4_BASE + 0x60000)
#define I2C_REV (0x00)
#define I2C_IE (0x04)
#define I2C_STAT (0x08)
#define I2C_WE (0x0C)
#define I2C_SYSS (0x10)
#define I2C_BUF (0x14)
#define I2C_CNT (0x18)
#define I2C_DATA (0x1C)
#define I2C_SYSC (0x20)
#define I2C_CON (0x24)
#define I2C_OA0 (0x28)
#define I2C_SA (0x2C)
#define I2C_PSC (0x30)
#define I2C_SCLL (0x34)
#define I2C_SCLH (0x38)
#define I2C_SYSTEST (0x3C)
#define I2C_BUFSTAT (0x40)
#define I2C_OA1 (0x44)
#define I2C_OA2 (0x48)
#define I2C_OA3 (0x4C)
#define I2C_ACTOA (0x50)
#define I2C_SBLOCK (0x54)
#endif

@ -0,0 +1,161 @@
/*
* 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 <err.h>
#include <reg.h>
#include <kernel/thread.h>
#include <platform/interrupts.h>
#include <arch/ops.h>
#include <arch/arm.h>
#include "platform_p.h"
#include <platform/omap3.h>
struct int_handler_struct {
int_handler handler;
void *arg;
};
static struct int_handler_struct int_handler_table[INT_VECTORS];
#define vectorToController(vector) ((vector) / 32)
void platform_init_interrupts(void)
{
unsigned int i;
// reset the controller
*REG32(INTC_SYSCONFIG) = 0x2; // start a reset
while ((*REG32(INTC_SYSSTATUS) & 0x1) == 0)
;
// mask all interrupts
*REG32(INTC_MIR(0)) = 0xffffffff;
*REG32(INTC_MIR(1)) = 0xffffffff;
*REG32(INTC_MIR(2)) = 0xffffffff;
// set up each of the interrupts
for (i = 0; i < INT_VECTORS; i++) {
// set each vector up as high priority IRQ
*REG32(INTC_ILR(i)) = 0;
//*ICReg(i / 32, INTCON_ILR_BASE + 4*(i%32)) = ((level_trigger[i/32] & (1<<(i%32))) ? (1<<1) : (0<<1)) | 0;
}
// disable the priority threshold
*REG32(INTC_THRESHOLD) = 0xff;
// clear any pending sw interrupts
*REG32(INTC_ISR_CLEAR(0)) = 0xffffffff;
*REG32(INTC_ISR_CLEAR(1)) = 0xffffffff;
*REG32(INTC_ISR_CLEAR(2)) = 0xffffffff;
// globally unmask interrupts
*REG32(INTC_CONTROL) = 3; // reset and enable the controller
}
status_t mask_interrupt(unsigned int vector)
{
if (vector >= INT_VECTORS)
return ERR_INVALID_ARGS;
// dprintf("%s: vector %d\n", __PRETTY_FUNCTION__, vector);
enter_critical_section();
*REG32(INTC_MIR_SET(vectorToController(vector))) = 1 << (vector % 32);
exit_critical_section();
return NO_ERROR;
}
void platform_mask_irqs(void)
{
int i;
for (i=0; i<INT_VECTORS; i++)
mask_interrupt(i);
}
status_t unmask_interrupt(unsigned int vector)
{
if (vector >= INT_VECTORS)
return ERR_INVALID_ARGS;
// dprintf("%s: vector %d\n", __PRETTY_FUNCTION__, vector);
enter_critical_section();
*REG32(INTC_MIR_CLEAR(vectorToController(vector))) = 1 << (vector % 32);
exit_critical_section();
return NO_ERROR;
}
enum handler_return platform_irq(struct arm_iframe *frame)
{
// get the current vector
unsigned int vector;
// read the currently active IRQ
vector = *REG32(INTC_SIR_IRQ) & 0x7f;
// TRACEF("spsr 0x%x, pc 0x%x, currthread %p, vector %d, handler %p\n", frame->spsr, frame->pc, current_thread, vector, int_handler_table[vector].handler);
#if THREAD_STATS
thread_stats.interrupts++;
#endif
// deliver the interrupt
enum handler_return ret;
ret = INT_NO_RESCHEDULE;
if (int_handler_table[vector].handler)
ret = int_handler_table[vector].handler(int_handler_table[vector].arg);
// ack the interrupt
*REG32(INTC_CONTROL) = 0x1;
return ret;
}
void platform_fiq(struct arm_iframe *frame)
{
PANIC_UNIMPLEMENTED;
}
void register_int_handler(unsigned int vector, int_handler handler, void *arg)
{
if (vector >= INT_VECTORS)
panic("register_int_handler: vector out of range %d\n", vector);
enter_critical_section();
int_handler_table[vector].arg = arg;
int_handler_table[vector].handler = handler;
exit_critical_section();
}

@ -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.
*/
#include <err.h>
#include <debug.h>
#include <arch/arm/mmu.h>
#include <platform.h>
#include "platform_p.h"
#include <platform/omap3.h>
#include <dev/i2c.h>
#include <dev/uart.h>
#include <dev/usbc.h>
void platform_init_mmu_mappings(void)
{
/* do some memory map initialization */
addr_t addr;
arm_mmu_map_section(SDRAM_BASE, 0, MMU_FLAG_CACHED|MMU_FLAG_BUFFERED);
for (addr = SDRAM_BASE; addr < SDRAM_BASE + SDRAM_SIZE; addr += (1024*1024)) {
arm_mmu_map_section(addr, addr, MMU_FLAG_CACHED|MMU_FLAG_BUFFERED|MMU_FLAG_READWRITE);
}
}
void platform_early_init(void)
{
/* initialize the interrupt controller */
platform_init_interrupts();
/* initialize the timer block */
platform_init_timer();
/* initialize the uart */
uart_init_early();
i2c_init_early();
}
void platform_init(void)
{
i2c_init();
uart_init();
usbc_init();
}

@ -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 __PLATFORM_P_H
#define __PLATFORM_P_H
void platform_init_interrupts(void);
void platform_init_timer(void);
#endif

@ -0,0 +1,37 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
ARCH := arm
ARM_CPU := cortex-a8
CPU := generic
DEVS += usb
# provides a few devices
DEFINES += \
WITH_DEV_USBC=1 \
WITH_DEV_UART=1
MODULES += \
dev/usb
INCLUDES += \
-I$(LOCAL_DIR)/include
OBJS += \
$(LOCAL_DIR)/cpu_early_init.Ao \
$(LOCAL_DIR)/debug.o \
$(LOCAL_DIR)/i2c.o \
$(LOCAL_DIR)/interrupts.o \
$(LOCAL_DIR)/platform.o \
$(LOCAL_DIR)/timer.o \
$(LOCAL_DIR)/uart.o \
$(LOCAL_DIR)/usbc.o
MEMBASE := 0x80000000
DEFINES += MEMBASE=$(MEMBASE) \
WITH_CPU_EARLY_INIT=1
LINKER_SCRIPT += \
$(BUILDDIR)/system-onesegment.ld

133
lk/platform/omap3/timer.c Normal file

@ -0,0 +1,133 @@
/*
* 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 <err.h>
#include <reg.h>
#include <debug.h>
#include <kernel/thread.h>
#include <platform.h>
#include <platform/interrupts.h>
#include <platform/timer.h>
#include <platform/omap3.h>
#include "platform_p.h"
static time_t tick_interval;
static platform_timer_callback t_callback;
static void *callback_arg;
/* timer 2 */
static const ulong timer_base = OMAP34XX_GPT2;
#define TIMER_TICK_RATE 32768
#define TIMER_REG(reg) *REG32(timer_base + (reg))
status_t platform_set_periodic_timer(platform_timer_callback callback, void *arg, time_t interval)
{
enter_critical_section();
t_callback = callback;
callback_arg = arg;
tick_interval = interval;
uint32_t ticks_per_interval = (uint64_t)interval * TIMER_TICK_RATE / 1000; // interval is in ms
TIMER_REG(TCLR) = 0; // stop the timer
TIMER_REG(TLDR) = -ticks_per_interval;
TIMER_REG(TTGR) = 1;
TIMER_REG(TIER) = 0x2;
TIMER_REG(TCLR) = 0x3; // autoreload, start
unmask_interrupt(GPT2_IRQ);
exit_critical_section();
return NO_ERROR;
}
time_t current_time(void)
{
uint32_t delta_ticks;
uint32_t delta_ticks2;
retry:
delta_ticks = *REG32(TIMER32K_CR);
delta_ticks2 = *REG32(TIMER32K_CR);
if (delta_ticks2 != delta_ticks)
goto retry;
uint64_t longtime = delta_ticks * 1000ULL / 32768ULL;
return (time_t)longtime;
}
bigtime_t current_time_hires(void)
{
uint32_t delta_ticks;
uint32_t delta_ticks2;
retry:
delta_ticks = *REG32(TIMER32K_CR);
delta_ticks2 = *REG32(TIMER32K_CR);
if (delta_ticks2 != delta_ticks)
goto retry;
uint64_t longtime = delta_ticks * 1000000ULL / 32768ULL;
return (bigtime_t)longtime;
}
static enum handler_return os_timer_tick(void *arg)
{
TIMER_REG(TISR) = TIMER_REG(TISR);
return t_callback(callback_arg, current_time());
}
void platform_init_timer(void)
{
/* GPT2 */
RMWREG32(CM_CLKSEL_PER, 0, 1, 1);
RMWREG32(CM_ICLKEN_PER, 3, 1, 1);
RMWREG32(CM_FCLKEN_PER, 3, 1, 1);
// reset the GP timer
TIMER_REG(TIOCP_CFG) = 0x2;
while ((TIMER_REG(TISTAT) & 1) == 0)
;
// set GPT2-9 clock inputs over to 32k
*REG32(CM_CLKSEL_PER) = 0;
// disable ints
TIMER_REG(TIER) = 0;
TIMER_REG(TISR) = 0x7; // clear any pending bits
// XXX make sure 32K timer is running
register_int_handler(GPT2_IRQ, &os_timer_tick, NULL);
}
void platform_halt_timers(void)
{
TIMER_REG(TCLR) = 0;
}

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