mirror of
git://projects.qi-hardware.com/xburst-tools.git
synced 2024-11-22 13:25:20 +02:00
Merge /home/xiangfu/workspace/qi-boot
This commit is contained in:
commit
1c8765eb8a
283
qiboot/6410-partition-sd.sh
Executable file
283
qiboot/6410-partition-sd.sh
Executable file
@ -0,0 +1,283 @@
|
||||
#!/bin/sh
|
||||
# 6410 SD Boot formatter
|
||||
# (C) 2008 Openmoko, Inc
|
||||
# Author: Andy Green <andy@openmoko.com>
|
||||
|
||||
# LAYOUT (if partition parameter is not specified)
|
||||
# Partition table, then
|
||||
# VFAT takes up remaining space here
|
||||
# then...
|
||||
#
|
||||
EXT3_ROOTFS_SECTORS=$(( 256 * 1024 * 2 ))
|
||||
EXT3_BACKUP_FS_SECTORS=$(( 8 * 1024 * 2 ))
|
||||
QI_ALLOCATION=$(( 256 * 2 ))
|
||||
#
|
||||
# lastly fixed stuff: 8KByte initial boot, sig, padding
|
||||
#
|
||||
# ----------------------
|
||||
|
||||
echo "s3c6410 bootable SD partitioning utility"
|
||||
echo "(C) Openmoko, Inc Andy Green <andy@openmoko.com>"
|
||||
echo
|
||||
|
||||
# these are fixed in iROM
|
||||
QI_INITIAL=$(( 8 * 2 ))
|
||||
SIG=1
|
||||
|
||||
|
||||
# display usage message and exit
|
||||
# any arguments are displayed as an error message
|
||||
USAGE()
|
||||
{
|
||||
echo
|
||||
[ -z "$1" ] || echo ERROR: $*
|
||||
echo
|
||||
echo 'This formats a SD card for usage on SD Card boot'
|
||||
echo ' on 6410 based systems'
|
||||
echo
|
||||
echo Usage: $(basename "$0") '<device> <card> <bootloader> <partition>'
|
||||
echo ' device = disk device name for SD Card, e.g. sde /dev/sdf'
|
||||
echo ' card = sd | sdhc'
|
||||
echo ' bootloader = /path/to/qi-binary'
|
||||
echo ' partition = vfat | NN | NN,NN | NN,NN,NN | NN,NN,NN,NN | no'
|
||||
echo ' * vfat -> main-vfat[rest] + rootfs[256M] + backupfs[8M]'
|
||||
echo ' NN -> rootfs1[NN%] + .. + rootfs4[NN%]'
|
||||
echo ' NN=0 -> will skip the partition'
|
||||
echo ' no -> leave partitions alone'
|
||||
echo
|
||||
echo 'Note: * => default action if no parameter specified'
|
||||
echo ' sum(NN) must be in [1..100]'
|
||||
echo
|
||||
echo 'e.g. '$(basename "$0")' sdb sdhc images/qi 0,30,0,45'
|
||||
echo ' will format an SDHC with partition 2 receiving 20% and partition 4'
|
||||
echo ' receiving 45% of the disk capacity and the remaining 35% will be'
|
||||
echo ' unused.'
|
||||
echo ' Capacity is calculated after subtracting the space reserved for Qi.'
|
||||
echo ' Partitions 1 and 3 will not be used.'
|
||||
exit 1
|
||||
}
|
||||
|
||||
[ -z "$1" -o -z "$2" -o -z "$3" ] && USAGE 'Missing arguments'
|
||||
|
||||
dev="$1"
|
||||
card="$2"
|
||||
qi="$3"
|
||||
partition="$4"
|
||||
|
||||
case "${card}" in
|
||||
[sS][dD][hH][cC])
|
||||
PADDING=1025
|
||||
;;
|
||||
[sS][dD])
|
||||
PADDING=1
|
||||
;;
|
||||
*)
|
||||
USAGE "${card} is an unknown card type"
|
||||
esac
|
||||
|
||||
# the amount of space that must remain unused at the end of the disk
|
||||
REAR_SECTORS=$(( $QI_ALLOCATION + $QI_INITIAL + $SIG + $PADDING ))
|
||||
|
||||
# validate parameters
|
||||
[ -b "${dev}" ] || dev="/dev/${dev}"
|
||||
[ -b "${dev}" ] || USAGE "${dev} is not a valid block device"
|
||||
[ X"${dev}" = X"${dev%%[0-9]}" ] || USAGE "${dev} is a partition, please use device: perhaps ${dev%%[0-9]}"
|
||||
|
||||
echo "Checking for mounted partitions..."
|
||||
grep "${dev}" /proc/mounts && USAGE "partitions on ${dev} are mounted, please unmount them"
|
||||
[ -e "${qi}" ] || USAGE "bootloader file: ${qi} does not exist"
|
||||
|
||||
# get size of device
|
||||
bytes=$(echo p | fdisk "${dev}" 2>&1 | sed '/^Disk.*, \([0-9]*\) bytes/s//\1/p;d')
|
||||
SECTORS=$(($bytes / 512))
|
||||
|
||||
[ -z "$SECTORS" ] && USAGE "could not find size for ${dev}"
|
||||
[ "$SECTORS" -le 0 ] && USAGE "invalid size: '${SECTORS}' for ${dev}"
|
||||
|
||||
echo "${dev} is $SECTORS 512-byte blocks"
|
||||
|
||||
|
||||
# Partition and format a disk (or SD card)
|
||||
# Parameters to format function are:
|
||||
#
|
||||
# device -> device to partition e.g. /dev/sdX
|
||||
#
|
||||
# Partition 1 parameters:
|
||||
#
|
||||
# label -> file system volume label e.g. rootfs
|
||||
# sizeMB -> size of the partition in MB e.g. 256
|
||||
# fstype -> filesystem type e.g. ext2, ext3, vfat (look at /sbin/mkfs.* for others)
|
||||
#
|
||||
# Notes: 1. Repeat "label, sizeMB, fstype" for partitions 2..4
|
||||
# 2. Partitions 2..4 are optional
|
||||
# 3. Do not repeat device parameter
|
||||
# 4. To skip a partition use: 'null 0 none' for that partition
|
||||
|
||||
FORMAT()
|
||||
{
|
||||
local device label sizeMB fstype p partition flag skip
|
||||
device="$1"; shift
|
||||
(
|
||||
p=0
|
||||
flag=0
|
||||
echo o
|
||||
while [ $# -gt 0 ]
|
||||
do
|
||||
label="$1"; shift
|
||||
sizeMB="$1"; shift
|
||||
fstype="$1"; shift
|
||||
p=$((${p} + 1))
|
||||
skip=NO
|
||||
[ ${sizeMB} -le 0 ] && skip=YES
|
||||
case "${label}" in
|
||||
[nN][uU][lL][lL])
|
||||
skip=YES
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
case "${skip}" in
|
||||
[yY][eE][sS]|[yY])
|
||||
;;
|
||||
*)
|
||||
echo n
|
||||
echo p
|
||||
echo ${p}
|
||||
echo
|
||||
echo +${sizeMB}M
|
||||
case "${fstype}" in
|
||||
[vV][fF][aA][tT]|[mM][sS][dD][oO][sS])
|
||||
echo t
|
||||
# fdisk is "helpful" & will auto select partition if there is only one
|
||||
# so do not output partition number if this is the first partition
|
||||
[ "${flag}" -eq 1 ] && echo ${p}
|
||||
echo 0b
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
flag=1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
echo p
|
||||
echo w
|
||||
echo q
|
||||
) | fdisk "${device}"
|
||||
p=0
|
||||
while [ $# -gt 0 ]
|
||||
do
|
||||
label="$1"; shift
|
||||
sizeMB="$1"; shift
|
||||
fstype="$1"; shift
|
||||
p=$((${p} + 1))
|
||||
partition="${dev}${p}"
|
||||
skip=NO
|
||||
[ ${sizeMB} -eq 0 ] && skip=YES
|
||||
case "${label}" in
|
||||
[nN][uU][lL][lL])
|
||||
skip=YES
|
||||
;;
|
||||
esac
|
||||
|
||||
case "${skip}" in
|
||||
[yY][eE][sS]|[yY])
|
||||
echo "Skipping: ${partition}"
|
||||
;;
|
||||
*)
|
||||
echo "Formatting: ${partition} -> ${fstype}[${sizeMB}MB]"
|
||||
case "${fstype}" in
|
||||
[vV][fF][aA][tT]|[mM][sS][dD][oO][sS])
|
||||
mkfs.${fstype} -n "${label}" "${partition}"
|
||||
;;
|
||||
*)
|
||||
mkfs.${fstype} -L "${label}" "${partition}"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# format the disk
|
||||
case "${partition}" in
|
||||
|
||||
# this case also hadles the default case (i.e. empty string: "")
|
||||
[vV][fF][aA][tT]|"")
|
||||
EXT3_TOTAL_SECTORS=$(( $EXT3_ROOTFS_SECTORS + $EXT3_BACKUP_FS_SECTORS ))
|
||||
FAT_SECTORS=$(( $SECTORS - $EXT3_TOTAL_SECTORS - $REAR_SECTORS ))
|
||||
FAT_MB=$(( $FAT_SECTORS / 2048 ))
|
||||
EXT3_ROOTFS_MB=$(( ${EXT3_ROOTFS_SECTORS} / 2048 ))
|
||||
EXT3_BACKUP_FS_MB=$(( ${EXT3_BACKUP_FS_SECTORS} / 2048 ))
|
||||
|
||||
echo Creating VFAT partition of ${FAT_MB} MB
|
||||
echo Creating Linux partition of ${EXT3_ROOTFS_MB} MB
|
||||
echo Creating backup Linux partition of ${EXT3_BACKUP_FS_MB} MB
|
||||
FORMAT "${dev}" \
|
||||
main-vfat "${FAT_MB}" vfat \
|
||||
rootfs "${EXT3_ROOTFS_MB}" ext3 \
|
||||
backupfs "${EXT3_BACKUP_FS_MB}" ext3
|
||||
;;
|
||||
|
||||
# decode partition or partition list
|
||||
*,*|100|[1-9][0-9]|[1-9])
|
||||
arg="${partition},"
|
||||
for v in 1 2 3 4
|
||||
do
|
||||
eval n${v}="\${arg%%,*}"
|
||||
eval n${v}="\${n${v}:-0}"
|
||||
arg="${arg#*,},"
|
||||
done
|
||||
total=$(( ${n1} + ${n2} + ${n3} + ${n4} ))
|
||||
echo Percentage of disk partitioned = ${total}%
|
||||
[ ${total} -gt 100 -o ${total} -lt 1 ] && USAGE partition: "'${partition}' => ${total}% outside [1..100]"
|
||||
|
||||
EXT3_TOTAL_SECTORS=$(( $SECTORS - $REAR_SECTORS ))
|
||||
EXT3_ROOTFS1_SECTORS=$(( $EXT3_TOTAL_SECTORS * $n1 / 100 ))
|
||||
EXT3_ROOTFS2_SECTORS=$(( $EXT3_TOTAL_SECTORS * $n2 / 100 ))
|
||||
EXT3_ROOTFS3_SECTORS=$(( $EXT3_TOTAL_SECTORS * $n3 / 100 ))
|
||||
EXT3_ROOTFS4_SECTORS=$(( $EXT3_TOTAL_SECTORS * $n4 / 100 ))
|
||||
EXT3_ROOTFS1_MB=$(( ${EXT3_ROOTFS1_SECTORS} / 2048 ))
|
||||
EXT3_ROOTFS2_MB=$(( ${EXT3_ROOTFS2_SECTORS} / 2048 ))
|
||||
EXT3_ROOTFS3_MB=$(( ${EXT3_ROOTFS3_SECTORS} / 2048 ))
|
||||
EXT3_ROOTFS4_MB=$(( ${EXT3_ROOTFS4_SECTORS} / 2048 ))
|
||||
|
||||
echo Creating Linux partition 1 of ${EXT3_ROOTFS1_MB} MB
|
||||
echo Creating Linux partition 2 of ${EXT3_ROOTFS2_MB} MB
|
||||
echo Creating Linux partition 3 of ${EXT3_ROOTFS3_MB} MB
|
||||
echo Creating Linux partition 4 of ${EXT3_ROOTFS4_MB} MB
|
||||
|
||||
FORMAT "${dev}" \
|
||||
rootfs1 "${EXT3_ROOTFS1_MB}" ext3 \
|
||||
rootfs2 "${EXT3_ROOTFS2_MB}" ext3 \
|
||||
rootfs3 "${EXT3_ROOTFS3_MB}" ext3 \
|
||||
rootfs4 "${EXT3_ROOTFS4_MB}" ext3
|
||||
;;
|
||||
|
||||
[Nn]*)
|
||||
# do not format
|
||||
;;
|
||||
|
||||
*)
|
||||
USAGE "'${partition}' is an unknown partition config"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
# copy the full bootloader image to the right place after the
|
||||
# partitioned area
|
||||
echo
|
||||
echo Installing Qi bootloader from: ${qi}
|
||||
|
||||
dd if="${qi}" of="${dev}" bs=512 count=512 \
|
||||
seek=$(( $SECTORS - $REAR_SECTORS ))
|
||||
dd if="${qi}" of="${dev}" bs=512 \
|
||||
seek=$(( $SECTORS - $REAR_SECTORS + $QI_ALLOCATION )) \
|
||||
count=$QI_INITIAL
|
||||
dd if=/dev/zero of="${dev}" bs=512 \
|
||||
seek=$(( $SECTORS - $REAR_SECTORS + $QI_ALLOCATION + $QI_INITIAL )) \
|
||||
count=$(( $SIG + $PADDING ))
|
||||
|
||||
# done
|
||||
echo
|
||||
echo "**** completed"
|
93
qiboot/Makefile
Normal file
93
qiboot/Makefile
Normal file
@ -0,0 +1,93 @@
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 2 of
|
||||
# the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
# MA 02111-1307 USA
|
||||
#
|
||||
|
||||
include config.mk
|
||||
|
||||
BUILD_DATE := $(shell date)
|
||||
BUILD_HOST := $(shell hostname)
|
||||
BUILD_BRANCH := $(shell git branch | grep ^\* | cut -d' ' -f2)
|
||||
BUILD_HEAD := $(shell git show --pretty=oneline | head -n1 | cut -d' ' -f1 | cut -b1-16)
|
||||
BUILD_VERSION := ${BUILD_BRANCH}_${BUILD_HEAD}
|
||||
|
||||
LDS = src/cpu/$(CPU)/qi.lds
|
||||
INCLUDE = include
|
||||
IMAGE_DIR = image
|
||||
TOOLS = tools
|
||||
CFLAGS = -Wall -Werror -I $(INCLUDE) -g -c -Os -fno-strict-aliasing -mlong-calls \
|
||||
-fno-common -ffixed-r8 -msoft-float -fno-builtin -ffreestanding \
|
||||
-march=armv4t -mno-thumb-interwork -Wstrict-prototypes \
|
||||
-DBUILD_HOST="${BUILD_HOST}" -DBUILD_VERSION="${BUILD_VERSION}" \
|
||||
-DBUILD_DATE="${BUILD_DATE}" -DQI_CPU="${CPU}"
|
||||
LDFLAGS =
|
||||
|
||||
S_SRCS = $(wildcard src/cpu/$(CPU)/*.S)
|
||||
S_OBJS = $(patsubst %.S,%.o, $(S_SRCS))
|
||||
C_SRCS = $(wildcard src/*.c) \
|
||||
$(wildcard src/drivers/*.c) $(wildcard src/fs/*.c) \
|
||||
$(wildcard src/cpu/$(CPU)/*.c)
|
||||
C_OBJS = $(patsubst %.c,%.o, $(C_SRCS))
|
||||
|
||||
SRCS = ${S_SRCS} ${C_SRCS}
|
||||
OBJS = ${S_OBJS} ${C_OBJS}
|
||||
LIBS = -L${COMPILER_LIB_PATH} -lgcc
|
||||
|
||||
ifeq ($(CPU),s3c2410)
|
||||
# GTA01 U-Boot IDs
|
||||
UDFU_VID = 0x1457
|
||||
UDFU_PID = 0x5119
|
||||
UDFU_REV = 0x0240
|
||||
else
|
||||
# GTA02 A5 and A6 U-Boot will eat these for DFU action
|
||||
UDFU_VID = 0x1d50
|
||||
UDFU_PID = 0x5119
|
||||
UDFU_REV = 0x350
|
||||
endif
|
||||
|
||||
TARGET = $(IMAGE_DIR)/start_qi_all-$(CPU)
|
||||
IMAGE = $(IMAGE_DIR)/qi-$(CPU)-$(BUILD_VERSION)
|
||||
UDFU_IMAGE = $(IMAGE_DIR)/qi-$(CPU)-$(BUILD_VERSION).udfu
|
||||
|
||||
MKUDFU = $(TOOLS)/mkudfu
|
||||
|
||||
%.o: %.S
|
||||
@$(CC) $(CFLAGS) -o $@ $<
|
||||
|
||||
%.o: %.c
|
||||
@$(CC) $(CFLAGS) -o $@ $<
|
||||
|
||||
all:${UDFU_IMAGE}
|
||||
|
||||
${OBJS}:${SRCS} ${INCLUDE}/*.h
|
||||
|
||||
${MKUDFU}:
|
||||
make -C $(TOOLS)
|
||||
|
||||
${UDFU_IMAGE}:${OBJS} ${MKUDFU}
|
||||
mkdir -p image
|
||||
@$(LD) ${LDFLAGS} -T$(LDS) -g $(OBJS) -o ${TARGET} ${LIBS}
|
||||
@$(OBJCOPY) -O binary -S ${TARGET} ${IMAGE}
|
||||
@$(MKUDFU) -v ${UDFU_VID} -p ${UDFU_PID} -r ${UDFU_REV} \
|
||||
-d ${IMAGE} ${UDFU_IMAGE}
|
||||
@$(OBJDUMP) -d ${TARGET} >${IMAGE}.dis
|
||||
|
||||
clean:
|
||||
@rm -f *~ src/*.o src/*~
|
||||
@rm -f src/cpu/*/*.o src/cpu/*/*~
|
||||
@rm -f src/drivers/*.o src/drivers/*~
|
||||
@rm -f src/fs/*.o src/fs/*~
|
||||
@rm -f include/*~ ${IMAGE_DIR}/*
|
||||
@make clean -C $(TOOLS)
|
||||
|
149
qiboot/README
Normal file
149
qiboot/README
Normal file
@ -0,0 +1,149 @@
|
||||
Qi
|
||||
==
|
||||
|
||||
Qi (named by Alan Cox on Openmoko kernel list) is a minimal bootloader that
|
||||
"breathes life" into Linux. Its goal is to stay close to the minimum needed
|
||||
to "load" and then "boot" Linux -- no boot menus, additional peripheral init
|
||||
or private states.
|
||||
|
||||
|
||||
What's wrong with U-Boot, they keep telling people to not reinvent the wheel?
|
||||
=============================================================================
|
||||
|
||||
U-Boot is gradually becoming a simplified knockoff of Linux. After using it a
|
||||
while, it became clear we were cutting and pasting drivers into U-Boot from
|
||||
Linux, cutting them down and not having a plan to maintain the U-Boot versions
|
||||
as the Linux ones were changed.
|
||||
|
||||
We decided that we would use full Linux for things that Linux is good at and
|
||||
only have the bootloader do the device init that is absolutely required before
|
||||
Linux can be pulled into memory and started. In practice since we had a working
|
||||
U-Boot implementation it meant cutting that right down to the bone (start.S
|
||||
mainly for s3c2442) and then building it up from scratch optimized to just do
|
||||
load and boot.
|
||||
|
||||
|
||||
Samsung - specific boot sequence
|
||||
================================
|
||||
|
||||
Right now Qi supports Samsung "steppingstone" scheme devices, but in fact it's
|
||||
the same in processors like iMX31 that there is a small area of SRAM that is
|
||||
prepped with NAND content via ROM on the device. There's nothing that stops Qi
|
||||
use on processors without steppingstone, although the ATAG stuff assumes we deal
|
||||
with ARM based processor.
|
||||
|
||||
|
||||
Per-CPU Qi
|
||||
==========
|
||||
|
||||
Qi has a concept of a single bootloader binary created per CPU type. The
|
||||
different devices that use that CPU are all supported in the same binary. At
|
||||
runtime after the common init is done, Qi asks each supported device code in
|
||||
turn if it recognizes the device as being handled by it, the first one to reply
|
||||
that it knows the device gets to control the rest of the process.
|
||||
|
||||
Consequently, there is NO build-time configuration file as found on U-Boot
|
||||
except a make env var that sets the CPU type being built, eg:
|
||||
|
||||
make CPU=s3c6410
|
||||
|
||||
|
||||
Booting Heuristics
|
||||
==================
|
||||
|
||||
Qi has one or more ways to fetch a kernel depending on the device it finds it is
|
||||
running on, for example on GTA02 it can use NAND and SD card devices. It goes
|
||||
through these device-specific storage devices in order and tries to boot the
|
||||
first viable kernel it finds, usually /boot/<uImage-device>.bin for example
|
||||
/boot/uImage-GTA02.bin.
|
||||
|
||||
The default order for GTA02 is: 1st SD primary partition, 2nd primary
|
||||
partition, 3rd primary partition, NAND kernel partition.
|
||||
|
||||
You can disable a rootfs for consideration for boot if you add a file
|
||||
/boot/noboot-<device>, eg, /boot/noboot-GTA02. This differs from renaming or
|
||||
deleting the kernel image because updating the kernel package would give you a
|
||||
working kernel again and allow boot, whereas the noboot indication will remain
|
||||
until you remove it.
|
||||
|
||||
The kernel commandline used is associated with the storage device and partition,
|
||||
this allows the correct root= line to be arrived at without any work.
|
||||
|
||||
If no kernel image can be found, Qi falls back to doing a memory test.
|
||||
|
||||
|
||||
Appending to commandline
|
||||
========================
|
||||
|
||||
You can append to the Qi commandline by creating a file /boot/append-<device>,
|
||||
eg, /boot/append-GTA02 containing the additional kernel commandline you want.
|
||||
|
||||
This means you can affect the boot per-rootfs, but that if you reimage the
|
||||
rootfs you at the same time define what is appeneded. Because these files are
|
||||
looked for with the <device> name in them, options can be selected depending on
|
||||
the device the rootfs is run on.
|
||||
|
||||
|
||||
Initrd support
|
||||
==============
|
||||
|
||||
Initrd or initramfs in separate file is supported to be loaded at given
|
||||
memory address in addition to kernel image. The ATAGs are issued accordingly.
|
||||
|
||||
|
||||
Interactive UI
|
||||
==============
|
||||
|
||||
Being minimalistic by its nature, Qi has very limited abilities to
|
||||
interact with a user. On GTA02 the red LED and the vibrator are used
|
||||
(if the battery is in good condition) to notify user of the following
|
||||
actions:
|
||||
|
||||
The LED is turned on either on:
|
||||
- Successful partition mount
|
||||
- Successful kernel pull
|
||||
- Successful initramfs pull
|
||||
|
||||
The LED is turned off and vibrator runs briefly either on:
|
||||
- Fail of kernel pull
|
||||
- Fail of initramfs pull
|
||||
- Fail of mount partition
|
||||
- Skipping of current boot possibility
|
||||
|
||||
The LED is turned off either on:
|
||||
- Start of the kernel
|
||||
- Start of the mem test
|
||||
- Start of the kernel pull
|
||||
- Start of the initramfs pull
|
||||
|
||||
If a user presses the AUX button after successful partition mount and
|
||||
before start of the kernel pull (that is, while the red LED is on),
|
||||
this boot possibility is skipped (and GTA02 owners can feel
|
||||
vibration). If a user holds the POWER button just before start of the
|
||||
kernel, debugging parameters are added to the kernel command line
|
||||
and a lot of information is output to the screen.
|
||||
|
||||
Functional Differences from U-Boot on GTA02
|
||||
===========================================
|
||||
|
||||
- Backlight and USB is not enabled until Linux starts after a few seconds
|
||||
|
||||
- No startup splash screen
|
||||
|
||||
- by default there is no boot spew on the LCM
|
||||
|
||||
- On GTAxx boots from first uSD ext2 / 3 partition containing
|
||||
/boot/uImage-<devicename>.bin present, eg, /boot/uImage-GTA02.bin, it checks
|
||||
first three partitions in turn
|
||||
|
||||
- On GTA01 and 02 if nothing is workable on the SD Card, or it is not present,
|
||||
Qi will try to boot from NAND
|
||||
|
||||
- You can disable a partition for boot by creating /boot/noboot-<devicename>,
|
||||
eg, /boot/noboot-GTA02, it will skip it and check the next partition
|
||||
|
||||
- Way faster
|
||||
|
||||
- There is no concept of "staying in the bootloader". The bootloader exits to
|
||||
Linux as fast as possible, that's all it does.
|
||||
|
12
qiboot/build
Executable file
12
qiboot/build
Executable file
@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
|
||||
make clean && \
|
||||
make CPU=s3c6410 && \
|
||||
make CPU=s3c2442 && \
|
||||
make CPU=s3c2410
|
||||
|
||||
# as root then...
|
||||
#
|
||||
# ./6410-partition-sd.sh sde sdhc image/qi-s3c6410-andy_???????????????? x
|
||||
# mount /dev/sde2 /mnt ; cp ../kernel/linux-2.6/uImage.bin /mnt/boot ; umount /dev/sde2
|
||||
|
22
qiboot/config.mk
Normal file
22
qiboot/config.mk
Normal file
@ -0,0 +1,22 @@
|
||||
#
|
||||
# Include the make variables (CC, etc...)
|
||||
#
|
||||
|
||||
CROSS_PATH=/usr/local/openmoko/arm
|
||||
CROSS_COMPILE=${CROSS_PATH}/bin/arm-angstrom-linux-gnueabi-
|
||||
|
||||
####
|
||||
COMPILER_LIB_PATH_PRE=${CROSS_PATH}/lib/gcc/arm-angstrom-linux-gnueabi
|
||||
COMPILER_LIB_PATH=${COMPILER_LIB_PATH_PRE}/`ls ${COMPILER_LIB_PATH_PRE}`
|
||||
|
||||
AS = $(CROSS_COMPILE)as
|
||||
LD = $(CROSS_COMPILE)ld
|
||||
CC = $(CROSS_COMPILE)gcc
|
||||
OBJCOPY = $(CROSS_COMPILE)objcopy
|
||||
OBJDUMP = $(CROSS_COMPILE)objdump
|
||||
HOSTCC = gcc
|
||||
|
||||
# we need the mkudfu tool from U-Boot build
|
||||
#MKUDFU = ../uboot/u-boot/tools/mkudfu
|
||||
|
||||
export CROSS_COMPILE AD LD CC OBJCOPY OBJDUMP MKUDFU
|
7
qiboot/dfu-qi
Executable file
7
qiboot/dfu-qi
Executable file
@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
../dfu-util/src/dfu-util -a 1 -d 0x1d50:0x5119 -D image/qi-s3c2442*.udfu
|
||||
if [ $? -eq 1 ] ; then
|
||||
../dfu-util/src/dfu-util -a 1 -d 0x1d50:0x5120 -D image/qi-s3c2442*.udfu
|
||||
../dfu-util/src/dfu-util -a 1 -d 0x1d50:0x5119 -D image/qi-s3c2442*.udfu
|
||||
fi
|
||||
|
34
qiboot/gta02-qi.ocd
Executable file
34
qiboot/gta02-qi.ocd
Executable file
@ -0,0 +1,34 @@
|
||||
# gta02 Qi script
|
||||
# Andy Green <andy@openmoko.com>
|
||||
|
||||
reset halt
|
||||
wait_halt
|
||||
sleep 2000
|
||||
|
||||
# bring the steppingstone part of qi image into steppingstone
|
||||
#
|
||||
load_binary /projects/openmoko/bootloader/image/qi 0x0
|
||||
#
|
||||
# mark ourselves as JTAG load
|
||||
#
|
||||
mww 0x4 0xffffffff
|
||||
|
||||
#
|
||||
# we have to run that so SDRAM exists in a usable way
|
||||
# fixed jumpthrough at 0x8 is executed after steppingstone
|
||||
# init (including RAM) has completed
|
||||
#
|
||||
bp 0x8 4 hw
|
||||
resume 0x0
|
||||
wait_halt
|
||||
rbp 0x8
|
||||
|
||||
#
|
||||
# now prep the SDRAM
|
||||
#
|
||||
load_binary /projects/openmoko/bootloader/image/qi 0x33000000
|
||||
#
|
||||
# and continue...
|
||||
resume 0x8
|
||||
#
|
||||
|
80
qiboot/include/ext2.h
Normal file
80
qiboot/include/ext2.h
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* (C) Copyright 2003 Sysgo Real-Time Solutions, AG <www.elinos.com>
|
||||
* Pavel Bartusek <pba@sysgo.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/* An implementation for the Ext2FS filesystem ported from GRUB.
|
||||
* Some parts of this code (mainly the structures and defines) are
|
||||
* from the original ext2 fs code, as found in the linux kernel.
|
||||
*/
|
||||
|
||||
|
||||
#define SECTOR_SIZE 0x200
|
||||
#define SECTOR_BITS 9
|
||||
|
||||
/* Error codes */
|
||||
typedef enum
|
||||
{
|
||||
ERR_NONE = 0,
|
||||
ERR_BAD_FILENAME,
|
||||
ERR_BAD_FILETYPE,
|
||||
ERR_BAD_GZIP_DATA,
|
||||
ERR_BAD_GZIP_HEADER,
|
||||
ERR_BAD_PART_TABLE,
|
||||
ERR_BAD_VERSION,
|
||||
ERR_BELOW_1MB,
|
||||
ERR_BOOT_COMMAND,
|
||||
ERR_BOOT_FAILURE,
|
||||
ERR_BOOT_FEATURES,
|
||||
ERR_DEV_FORMAT,
|
||||
ERR_DEV_VALUES,
|
||||
ERR_EXEC_FORMAT,
|
||||
ERR_FILELENGTH,
|
||||
ERR_FILE_NOT_FOUND,
|
||||
ERR_FSYS_CORRUPT,
|
||||
ERR_FSYS_MOUNT,
|
||||
ERR_GEOM,
|
||||
ERR_NEED_LX_KERNEL,
|
||||
ERR_NEED_MB_KERNEL,
|
||||
ERR_NO_DISK,
|
||||
ERR_NO_PART,
|
||||
ERR_NUMBER_PARSING,
|
||||
ERR_OUTSIDE_PART,
|
||||
ERR_READ,
|
||||
ERR_SYMLINK_LOOP,
|
||||
ERR_UNRECOGNIZED,
|
||||
ERR_WONT_FIT,
|
||||
ERR_WRITE,
|
||||
ERR_BAD_ARGUMENT,
|
||||
ERR_UNALIGNED,
|
||||
ERR_PRIVILEGED,
|
||||
ERR_DEV_NEED_INIT,
|
||||
ERR_NO_DISK_SPACE,
|
||||
ERR_NUMBER_OVERFLOW,
|
||||
|
||||
MAX_ERR_NUM
|
||||
} ext2fs_error_t;
|
||||
|
||||
|
||||
extern int ext2fs_ls(char *dirname);
|
||||
extern int ext2fs_open(const char *filename);
|
||||
extern int ext2fs_read(char *buf, unsigned len);
|
||||
extern int ext2fs_mount(void);
|
||||
extern int ext2fs_close(void);
|
220
qiboot/include/fat.h
Normal file
220
qiboot/include/fat.h
Normal file
@ -0,0 +1,220 @@
|
||||
/*
|
||||
* R/O (V)FAT 12/16/32 filesystem implementation by Marcus Sundberg
|
||||
*
|
||||
* 2002-07-28 - rjones@nexus-tech.net - ported to ppcboot v1.1.6
|
||||
* 2003-03-10 - kharris@nexus-tech.net - ported to u-boot
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _FAT_H_
|
||||
#define _FAT_H_
|
||||
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#define CONFIG_SUPPORT_VFAT
|
||||
|
||||
#define SECTOR_SIZE FS_BLOCK_SIZE
|
||||
|
||||
#define FS_BLOCK_SIZE 512
|
||||
|
||||
#if FS_BLOCK_SIZE != SECTOR_SIZE
|
||||
#error FS_BLOCK_SIZE != SECTOR_SIZE - This code needs to be fixed!
|
||||
#endif
|
||||
|
||||
#define MAX_CLUSTSIZE 65536
|
||||
#define DIRENTSPERBLOCK (FS_BLOCK_SIZE/sizeof(dir_entry))
|
||||
#define DIRENTSPERCLUST ((mydata->clust_size*SECTOR_SIZE)/sizeof(dir_entry))
|
||||
|
||||
#define FATBUFBLOCKS 6
|
||||
#define FATBUFSIZE (FS_BLOCK_SIZE*FATBUFBLOCKS)
|
||||
#define FAT12BUFSIZE ((FATBUFSIZE*2)/3)
|
||||
#define FAT16BUFSIZE (FATBUFSIZE/2)
|
||||
#define FAT32BUFSIZE (FATBUFSIZE/4)
|
||||
|
||||
|
||||
/* Filesystem identifiers */
|
||||
#define FAT12_SIGN "FAT12 "
|
||||
#define FAT16_SIGN "FAT16 "
|
||||
#define FAT32_SIGN "FAT32 "
|
||||
#define SIGNLEN 8
|
||||
|
||||
/* File attributes */
|
||||
#define ATTR_RO 1
|
||||
#define ATTR_HIDDEN 2
|
||||
#define ATTR_SYS 4
|
||||
#define ATTR_VOLUME 8
|
||||
#define ATTR_DIR 16
|
||||
#define ATTR_ARCH 32
|
||||
|
||||
#define ATTR_VFAT (ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME)
|
||||
|
||||
#define DELETED_FLAG ((char)0xe5) /* Marks deleted files when in name[0] */
|
||||
#define aRING 0x05 /* Used to represent 'å' in name[0] */
|
||||
|
||||
/* Indicates that the entry is the last long entry in a set of long
|
||||
* dir entries
|
||||
*/
|
||||
#define LAST_LONG_ENTRY_MASK 0x40
|
||||
|
||||
/* Flags telling whether we should read a file or list a directory */
|
||||
#define LS_NO 0
|
||||
#define LS_YES 1
|
||||
#define LS_DIR 1
|
||||
#define LS_ROOT 2
|
||||
|
||||
#ifdef DEBUG
|
||||
#define FAT_DPRINT(args...) printf(args)
|
||||
#else
|
||||
#define FAT_DPRINT(args...)
|
||||
#endif
|
||||
#define FAT_ERROR(arg) printf(arg)
|
||||
|
||||
#define ISDIRDELIM(c) ((c) == '/' || (c) == '\\')
|
||||
|
||||
#define FSTYPE_NONE (-1)
|
||||
|
||||
#if defined(__linux__) && defined(__KERNEL__)
|
||||
#define FAT2CPU16 le16_to_cpu
|
||||
#define FAT2CPU32 le32_to_cpu
|
||||
#else
|
||||
#if __LITTLE_ENDIAN
|
||||
#define FAT2CPU16(x) (x)
|
||||
#define FAT2CPU32(x) (x)
|
||||
#else
|
||||
#define FAT2CPU16(x) ((((x) & 0x00ff) << 8) | (((x) & 0xff00) >> 8))
|
||||
#define FAT2CPU32(x) ((((x) & 0x000000ff) << 24) | \
|
||||
(((x) & 0x0000ff00) << 8) | \
|
||||
(((x) & 0x00ff0000) >> 8) | \
|
||||
(((x) & 0xff000000) >> 24))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define TOLOWER(c) if((c) >= 'A' && (c) <= 'Z'){(c)+=('a' - 'A');}
|
||||
#define START(dent) (FAT2CPU16((dent)->start) \
|
||||
+ (mydata->fatsize != 32 ? 0 : \
|
||||
(FAT2CPU16((dent)->starthi) << 16)))
|
||||
#define CHECK_CLUST(x, fatsize) ((x) <= 1 || \
|
||||
(x) >= ((fatsize) != 32 ? 0xfff0 : 0xffffff0))
|
||||
|
||||
typedef struct boot_sector {
|
||||
__u8 ignored[3]; /* Bootstrap code */
|
||||
char system_id[8]; /* Name of fs */
|
||||
__u8 sector_size[2]; /* Bytes/sector */
|
||||
__u8 cluster_size; /* Sectors/cluster */
|
||||
__u16 reserved; /* Number of reserved sectors */
|
||||
__u8 fats; /* Number of FATs */
|
||||
__u8 dir_entries[2]; /* Number of root directory entries */
|
||||
__u8 sectors[2]; /* Number of sectors */
|
||||
__u8 media; /* Media code */
|
||||
__u16 fat_length; /* Sectors/FAT */
|
||||
__u16 secs_track; /* Sectors/track */
|
||||
__u16 heads; /* Number of heads */
|
||||
__u32 hidden; /* Number of hidden sectors */
|
||||
__u32 total_sect; /* Number of sectors (if sectors == 0) */
|
||||
|
||||
/* FAT32 only */
|
||||
__u32 fat32_length; /* Sectors/FAT */
|
||||
__u16 flags; /* Bit 8: fat mirroring, low 4: active fat */
|
||||
__u8 version[2]; /* Filesystem version */
|
||||
__u32 root_cluster; /* First cluster in root directory */
|
||||
__u16 info_sector; /* Filesystem info sector */
|
||||
__u16 backup_boot; /* Backup boot sector */
|
||||
__u16 reserved2[6]; /* Unused */
|
||||
} boot_sector;
|
||||
|
||||
typedef struct volume_info
|
||||
{
|
||||
__u8 drive_number; /* BIOS drive number */
|
||||
__u8 reserved; /* Unused */
|
||||
__u8 ext_boot_sign; /* 0x29 if fields below exist (DOS 3.3+) */
|
||||
__u8 volume_id[4]; /* Volume ID number */
|
||||
char volume_label[11]; /* Volume label */
|
||||
char fs_type[8]; /* Typically FAT12, FAT16, or FAT32 */
|
||||
/* Boot code comes next, all but 2 bytes to fill up sector */
|
||||
/* Boot sign comes last, 2 bytes */
|
||||
} volume_info;
|
||||
|
||||
typedef struct dir_entry {
|
||||
char name[8],ext[3]; /* Name and extension */
|
||||
__u8 attr; /* Attribute bits */
|
||||
__u8 lcase; /* Case for base and extension */
|
||||
__u8 ctime_ms; /* Creation time, milliseconds */
|
||||
__u16 ctime; /* Creation time */
|
||||
__u16 cdate; /* Creation date */
|
||||
__u16 adate; /* Last access date */
|
||||
__u16 starthi; /* High 16 bits of cluster in FAT32 */
|
||||
__u16 time,date,start;/* Time, date and first cluster */
|
||||
__u32 size; /* File size in bytes */
|
||||
} dir_entry;
|
||||
|
||||
typedef struct dir_slot {
|
||||
__u8 id; /* Sequence number for slot */
|
||||
__u8 name0_4[10]; /* First 5 characters in name */
|
||||
__u8 attr; /* Attribute byte */
|
||||
__u8 reserved; /* Unused */
|
||||
__u8 alias_checksum;/* Checksum for 8.3 alias */
|
||||
__u8 name5_10[12]; /* 6 more characters in name */
|
||||
__u16 start; /* Unused */
|
||||
__u8 name11_12[4]; /* Last 2 characters in name */
|
||||
} dir_slot;
|
||||
|
||||
/* Private filesystem parameters
|
||||
*
|
||||
* Note: FAT buffer has to be 32 bit aligned
|
||||
* (see FAT32 accesses)
|
||||
*/
|
||||
typedef struct {
|
||||
__u8 fatbuf[FATBUFSIZE]; /* Current FAT buffer */
|
||||
int fatsize; /* Size of FAT in bits */
|
||||
__u16 fatlength; /* Length of FAT in sectors */
|
||||
__u16 fat_sect; /* Starting sector of the FAT */
|
||||
__u16 rootdir_sect; /* Start sector of root directory */
|
||||
__u16 clust_size; /* Size of clusters in sectors */
|
||||
short data_begin; /* The sector of the first cluster, can be negative */
|
||||
int fatbufnum; /* Used by get_fatent, init to -1 */
|
||||
} fsdata;
|
||||
|
||||
typedef int (file_detectfs_func)(void);
|
||||
typedef int (file_ls_func)(const char *dir);
|
||||
typedef long (file_read_func)(const char *filename, void *buffer,
|
||||
unsigned long maxsize);
|
||||
|
||||
struct filesystem {
|
||||
file_detectfs_func *detect;
|
||||
file_ls_func *ls;
|
||||
file_read_func *read;
|
||||
const char name[12];
|
||||
};
|
||||
|
||||
/* FAT tables */
|
||||
file_detectfs_func file_fat_detectfs;
|
||||
file_ls_func file_fat_ls;
|
||||
file_read_func file_fat_read;
|
||||
|
||||
/* Currently this doesn't check if the dir exists or is valid... */
|
||||
int file_cd(const char *path);
|
||||
int file_fat_detectfs(void);
|
||||
int file_fat_ls(const char *dir);
|
||||
long file_fat_read(const char *filename, void *buffer, unsigned long maxsize);
|
||||
const char *file_getfsname(int idx);
|
||||
int fat_register_device(block_dev_desc_t *dev_desc, int part_no);
|
||||
|
||||
#endif /* _FAT_H_ */
|
1
qiboot/include/glamo-init.h
Normal file
1
qiboot/include/glamo-init.h
Normal file
@ -0,0 +1 @@
|
||||
extern void glamo_core_init(void);
|
149
qiboot/include/glamo-mmc.h
Normal file
149
qiboot/include/glamo-mmc.h
Normal file
@ -0,0 +1,149 @@
|
||||
#ifndef __GLAMO_MMC_H__
|
||||
#define __GLAMO_MMC_H__
|
||||
|
||||
/* Standard MMC commands (4.1) type argument response */
|
||||
/* class 1 */
|
||||
#define MMC_GO_IDLE_STATE 0 /* bc */
|
||||
#define MMC_SEND_OP_COND 1 /* bcr [31:0] OCR R3 */
|
||||
#define MMC_ALL_SEND_CID 2 /* bcr R2 */
|
||||
#define MMC_SET_RELATIVE_ADDR 3 /* ac [31:16] RCA R1 */
|
||||
#define MMC_SET_DSR 4 /* bc [31:16] RCA */
|
||||
#define MMC_SWITCH 6 /* ac [31:0] See below R1b */
|
||||
#define MMC_SELECT_CARD 7 /* ac [31:16] RCA R1 */
|
||||
#define MMC_SEND_EXT_CSD 8 /* adtc R1 */
|
||||
#define MMC_SEND_CSD 9 /* ac [31:16] RCA R2 */
|
||||
#define MMC_SEND_CID 10 /* ac [31:16] RCA R2 */
|
||||
#define MMC_READ_DAT_UNTIL_STOP 11 /* adtc [31:0] dadr R1 */
|
||||
#define MMC_STOP_TRANSMISSION 12 /* ac R1b */
|
||||
#define MMC_SEND_STATUS 13 /* ac [31:16] RCA R1 */
|
||||
#define MMC_GO_INACTIVE_STATE 15 /* ac [31:16] RCA */
|
||||
#define MMC_SPI_READ_OCR 58 /* spi spi_R3 */
|
||||
#define MMC_SPI_CRC_ON_OFF 59 /* spi [0:0] flag spi_R1 */
|
||||
|
||||
#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */
|
||||
#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */
|
||||
|
||||
/* class 2 */
|
||||
#define MMC_SET_BLOCKLEN 16 /* ac [31:0] block len R1 */
|
||||
#define MMC_READ_SINGLE_BLOCK 17 /* adtc [31:0] data addr R1 */
|
||||
#define MMC_READ_MULTIPLE_BLOCK 18 /* adtc [31:0] data addr R1 */
|
||||
|
||||
/* class 3 */
|
||||
#define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1 */
|
||||
|
||||
/* class 4 */
|
||||
#define MMC_SET_BLOCK_COUNT 23 /* adtc [31:0] data addr R1 */
|
||||
#define MMC_WRITE_BLOCK 24 /* adtc [31:0] data addr R1 */
|
||||
#define MMC_WRITE_MULTIPLE_BLOCK 25 /* adtc R1 */
|
||||
#define MMC_PROGRAM_CID 26 /* adtc R1 */
|
||||
#define MMC_PROGRAM_CSD 27 /* adtc R1 */
|
||||
|
||||
/* class 6 */
|
||||
#define MMC_SET_WRITE_PROT 28 /* ac [31:0] data addr R1b */
|
||||
#define MMC_CLR_WRITE_PROT 29 /* ac [31:0] data addr R1b */
|
||||
#define MMC_SEND_WRITE_PROT 30 /* adtc [31:0] wpdata addr R1 */
|
||||
|
||||
/* class 5 */
|
||||
#define MMC_ERASE_GROUP_START 35 /* ac [31:0] data addr R1 */
|
||||
#define MMC_ERASE_GROUP_END 36 /* ac [31:0] data addr R1 */
|
||||
#define MMC_ERASE 38 /* ac R1b */
|
||||
|
||||
/* class 9 */
|
||||
#define MMC_FAST_IO 39 /* ac <Complex> R4 */
|
||||
#define MMC_GO_IRQ_STATE 40 /* bcr R5 */
|
||||
|
||||
/* class 7 */
|
||||
#define MMC_LOCK_UNLOCK 42 /* adtc R1b */
|
||||
|
||||
/* class 8 */
|
||||
#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */
|
||||
#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */
|
||||
|
||||
#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */
|
||||
#define SD_APP_SEND_NUM_WR_BLKS 22 /* adtc R1 */
|
||||
#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */
|
||||
#define SD_APP_SEND_SCR 51 /* adtc R1 */
|
||||
|
||||
|
||||
#define MMC_RSP_PRESENT (1 << 0)
|
||||
#define MMC_RSP_136 (1 << 1) /* 136 bit response */
|
||||
#define MMC_RSP_CRC (1 << 2) /* expect valid crc */
|
||||
#define MMC_RSP_BUSY (1 << 3) /* card may send busy */
|
||||
#define MMC_RSP_OPCODE (1 << 4) /* response contains opcode */
|
||||
|
||||
#define MMC_CMD_MASK (3 << 5) /* non-SPI command type */
|
||||
#define MMC_CMD_AC (0 << 5)
|
||||
#define MMC_CMD_ADTC (1 << 5)
|
||||
#define MMC_CMD_BC (2 << 5)
|
||||
#define MMC_CMD_BCR (3 << 5)
|
||||
|
||||
#define MMC_RSP_SPI_S1 (1 << 7) /* one status byte */
|
||||
#define MMC_RSP_SPI_S2 (1 << 8) /* second byte */
|
||||
#define MMC_RSP_SPI_B4 (1 << 9) /* four data bytes */
|
||||
#define MMC_RSP_SPI_BUSY (1 << 10) /* card may send busy */
|
||||
|
||||
/*
|
||||
* These are the native response types, and correspond to valid bit
|
||||
* patterns of the above flags. One additional valid pattern
|
||||
* is all zeros, which means we don't expect a response.
|
||||
*/
|
||||
#define MMC_RSP_NONE (0)
|
||||
#define MMC_RSP_R1 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
|
||||
#define MMC_RSP_R1B (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE|MMC_RSP_BUSY)
|
||||
#define MMC_RSP_R2 (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC)
|
||||
#define MMC_RSP_R3 (MMC_RSP_PRESENT)
|
||||
#define MMC_RSP_R4 (MMC_RSP_PRESENT)
|
||||
#define MMC_RSP_R5 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
|
||||
#define MMC_RSP_R6 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
|
||||
#define MMC_RSP_R7 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
|
||||
|
||||
#define mmc_resp_type(f) ((f) & (MMC_RSP_PRESENT | MMC_RSP_136 | MMC_RSP_CRC |\
|
||||
MMC_RSP_BUSY | MMC_RSP_OPCODE))
|
||||
#define mmc_cmd_type(f) ((f) & MMC_CMD_MASK)
|
||||
|
||||
/*
|
||||
* These are the SPI response types for MMC, SD, and SDIO cards.
|
||||
* Commands return R1, with maybe more info. Zero is an error type;
|
||||
* callers must always provide the appropriate MMC_RSP_SPI_Rx flags.
|
||||
*/
|
||||
#define MMC_RSP_SPI_R1 (MMC_RSP_SPI_S1)
|
||||
#define MMC_RSP_SPI_R1B (MMC_RSP_SPI_S1|MMC_RSP_SPI_BUSY)
|
||||
#define MMC_RSP_SPI_R2 (MMC_RSP_SPI_S1|MMC_RSP_SPI_S2)
|
||||
#define MMC_RSP_SPI_R3 (MMC_RSP_SPI_S1|MMC_RSP_SPI_B4)
|
||||
#define MMC_RSP_SPI_R4 (MMC_RSP_SPI_S1|MMC_RSP_SPI_B4)
|
||||
#define MMC_RSP_SPI_R5 (MMC_RSP_SPI_S1|MMC_RSP_SPI_S2)
|
||||
#define MMC_RSP_SPI_R7 (MMC_RSP_SPI_S1|MMC_RSP_SPI_B4)
|
||||
|
||||
#define MMC_DATA_WRITE (1 << 8)
|
||||
#define MMC_DATA_READ (1 << 9)
|
||||
#define MMC_DATA_STREAM (1 << 10)
|
||||
|
||||
struct sd_cid {
|
||||
char pnm_0; /* product name */
|
||||
char oid_1; /* OEM/application ID */
|
||||
char oid_0;
|
||||
u8 mid; /* manufacturer ID */
|
||||
char pnm_4;
|
||||
char pnm_3;
|
||||
char pnm_2;
|
||||
char pnm_1;
|
||||
u8 psn_2; /* product serial number */
|
||||
u8 psn_1;
|
||||
u8 psn_0; /* MSB */
|
||||
u8 prv; /* product revision */
|
||||
u8 crc; /* CRC7 checksum, b0 is unused and set to 1 */
|
||||
u8 mdt_1; /* manufacturing date, LSB, RRRRyyyy yyyymmmm */
|
||||
u8 mdt_0; /* MSB */
|
||||
u8 psn_3; /* LSB */
|
||||
};
|
||||
|
||||
enum card_type {
|
||||
CARDTYPE_NONE = 0,
|
||||
CARDTYPE_MMC,
|
||||
CARDTYPE_SD,
|
||||
CARDTYPE_SD20,
|
||||
CARDTYPE_SDHC
|
||||
};
|
||||
|
||||
|
||||
#endif /* __GLAMO_MMC_H__ */
|
628
qiboot/include/glamo-regs.h
Normal file
628
qiboot/include/glamo-regs.h
Normal file
@ -0,0 +1,628 @@
|
||||
#ifndef _GLAMO_REGS_H
|
||||
#define _GLAMO_REGS_H
|
||||
|
||||
/* Smedia Glamo 336x/337x driver
|
||||
*
|
||||
* (C) 2007 by OpenMoko, Inc.
|
||||
* Author: Harald Welte <laforge@openmoko.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
enum glamo_regster_offsets {
|
||||
GLAMO_REGOFS_GENERIC = 0x0000,
|
||||
GLAMO_REGOFS_HOSTBUS = 0x0200,
|
||||
GLAMO_REGOFS_MEMORY = 0x0300,
|
||||
GLAMO_REGOFS_VIDCAP = 0x0400,
|
||||
GLAMO_REGOFS_ISP = 0x0500,
|
||||
GLAMO_REGOFS_JPEG = 0x0800,
|
||||
GLAMO_REGOFS_MPEG = 0x0c00,
|
||||
GLAMO_REGOFS_LCD = 0x1100,
|
||||
GLAMO_REGOFS_MMC = 0x1400,
|
||||
GLAMO_REGOFS_MPROC0 = 0x1500,
|
||||
GLAMO_REGOFS_MPROC1 = 0x1580,
|
||||
GLAMO_REGOFS_CMDQUEUE = 0x1600,
|
||||
GLAMO_REGOFS_RISC = 0x1680,
|
||||
GLAMO_REGOFS_2D = 0x1700,
|
||||
GLAMO_REGOFS_3D = 0x1b00,
|
||||
GLAMO_REGOFS_END = 0x2400,
|
||||
};
|
||||
|
||||
|
||||
enum glamo_register_generic {
|
||||
GLAMO_REG_GCONF1 = 0x0000,
|
||||
GLAMO_REG_GCONF2 = 0x0002,
|
||||
#define GLAMO_REG_DEVICE_ID GLAMO_REG_GCONF2
|
||||
GLAMO_REG_GCONF3 = 0x0004,
|
||||
#define GLAMO_REG_REVISION_ID GLAMO_REG_GCONF3
|
||||
GLAMO_REG_IRQ_GEN1 = 0x0006,
|
||||
#define GLAMO_REG_IRQ_ENABLE GLAMO_REG_IRQ_GEN1
|
||||
GLAMO_REG_IRQ_GEN2 = 0x0008,
|
||||
#define GLAMO_REG_IRQ_SET GLAMO_REG_IRQ_GEN2
|
||||
GLAMO_REG_IRQ_GEN3 = 0x000a,
|
||||
#define GLAMO_REG_IRQ_CLEAR GLAMO_REG_IRQ_GEN3
|
||||
GLAMO_REG_IRQ_GEN4 = 0x000c,
|
||||
#define GLAMO_REG_IRQ_STATUS GLAMO_REG_IRQ_GEN4
|
||||
GLAMO_REG_CLOCK_HOST = 0x0010,
|
||||
GLAMO_REG_CLOCK_MEMORY = 0x0012,
|
||||
GLAMO_REG_CLOCK_LCD = 0x0014,
|
||||
GLAMO_REG_CLOCK_MMC = 0x0016,
|
||||
GLAMO_REG_CLOCK_ISP = 0x0018,
|
||||
GLAMO_REG_CLOCK_JPEG = 0x001a,
|
||||
GLAMO_REG_CLOCK_3D = 0x001c,
|
||||
GLAMO_REG_CLOCK_2D = 0x001e,
|
||||
GLAMO_REG_CLOCK_RISC1 = 0x0020, /* 3365 only? */
|
||||
GLAMO_REG_CLOCK_RISC2 = 0x0022, /* 3365 only? */
|
||||
GLAMO_REG_CLOCK_MPEG = 0x0024,
|
||||
GLAMO_REG_CLOCK_MPROC = 0x0026,
|
||||
|
||||
GLAMO_REG_CLOCK_GEN5_1 = 0x0030,
|
||||
GLAMO_REG_CLOCK_GEN5_2 = 0x0032,
|
||||
GLAMO_REG_CLOCK_GEN6 = 0x0034,
|
||||
GLAMO_REG_CLOCK_GEN7 = 0x0036,
|
||||
GLAMO_REG_CLOCK_GEN8 = 0x0038,
|
||||
GLAMO_REG_CLOCK_GEN9 = 0x003a,
|
||||
GLAMO_REG_CLOCK_GEN10 = 0x003c,
|
||||
GLAMO_REG_CLOCK_GEN11 = 0x003e,
|
||||
GLAMO_REG_PLL_GEN1 = 0x0040,
|
||||
GLAMO_REG_PLL_GEN2 = 0x0042,
|
||||
GLAMO_REG_PLL_GEN3 = 0x0044,
|
||||
GLAMO_REG_PLL_GEN4 = 0x0046,
|
||||
GLAMO_REG_PLL_GEN5 = 0x0048,
|
||||
GLAMO_REG_GPIO_GEN1 = 0x0050,
|
||||
GLAMO_REG_GPIO_GEN2 = 0x0052,
|
||||
GLAMO_REG_GPIO_GEN3 = 0x0054,
|
||||
GLAMO_REG_GPIO_GEN4 = 0x0056,
|
||||
GLAMO_REG_GPIO_GEN5 = 0x0058,
|
||||
GLAMO_REG_GPIO_GEN6 = 0x005a,
|
||||
GLAMO_REG_GPIO_GEN7 = 0x005c,
|
||||
GLAMO_REG_GPIO_GEN8 = 0x005e,
|
||||
GLAMO_REG_GPIO_GEN9 = 0x0060,
|
||||
GLAMO_REG_GPIO_GEN10 = 0x0062,
|
||||
GLAMO_REG_DFT_GEN1 = 0x0070,
|
||||
GLAMO_REG_DFT_GEN2 = 0x0072,
|
||||
GLAMO_REG_DFT_GEN3 = 0x0074,
|
||||
GLAMO_REG_DFT_GEN4 = 0x0076,
|
||||
|
||||
GLAMO_REG_PLL_GEN6 = 0x01e0,
|
||||
GLAMO_REG_PLL_GEN7 = 0x01f0,
|
||||
};
|
||||
|
||||
#define GLAMO_REG_HOSTBUS(x) (GLAMO_REGOFS_HOSTBUS-2+(x*2))
|
||||
|
||||
#define REG_MEM(x) (GLAMO_REGOFS_MEMORY+(x))
|
||||
#define GLAMO_REG_MEM_TIMING(x) (GLAMO_REG_MEM_TIMING1-2+(x*2))
|
||||
|
||||
enum glamo_register_mem {
|
||||
GLAMO_REG_MEM_TYPE = REG_MEM(0x00),
|
||||
GLAMO_REG_MEM_GEN = REG_MEM(0x02),
|
||||
GLAMO_REG_MEM_TIMING1 = REG_MEM(0x04),
|
||||
GLAMO_REG_MEM_TIMING2 = REG_MEM(0x06),
|
||||
GLAMO_REG_MEM_TIMING3 = REG_MEM(0x08),
|
||||
GLAMO_REG_MEM_TIMING4 = REG_MEM(0x0a),
|
||||
GLAMO_REG_MEM_TIMING5 = REG_MEM(0x0c),
|
||||
GLAMO_REG_MEM_TIMING6 = REG_MEM(0x0e),
|
||||
GLAMO_REG_MEM_TIMING7 = REG_MEM(0x10),
|
||||
GLAMO_REG_MEM_TIMING8 = REG_MEM(0x12),
|
||||
GLAMO_REG_MEM_TIMING9 = REG_MEM(0x14),
|
||||
GLAMO_REG_MEM_TIMING10 = REG_MEM(0x16),
|
||||
GLAMO_REG_MEM_TIMING11 = REG_MEM(0x18),
|
||||
GLAMO_REG_MEM_POWER1 = REG_MEM(0x1a),
|
||||
GLAMO_REG_MEM_POWER2 = REG_MEM(0x1c),
|
||||
GLAMO_REG_MEM_LCD_BUF1 = REG_MEM(0x1e),
|
||||
GLAMO_REG_MEM_LCD_BUF2 = REG_MEM(0x20),
|
||||
GLAMO_REG_MEM_LCD_BUF3 = REG_MEM(0x22),
|
||||
GLAMO_REG_MEM_LCD_BUF4 = REG_MEM(0x24),
|
||||
GLAMO_REG_MEM_BIST1 = REG_MEM(0x26),
|
||||
GLAMO_REG_MEM_BIST2 = REG_MEM(0x28),
|
||||
GLAMO_REG_MEM_BIST3 = REG_MEM(0x2a),
|
||||
GLAMO_REG_MEM_BIST4 = REG_MEM(0x2c),
|
||||
GLAMO_REG_MEM_BIST5 = REG_MEM(0x2e),
|
||||
GLAMO_REG_MEM_MAH1 = REG_MEM(0x30),
|
||||
GLAMO_REG_MEM_MAH2 = REG_MEM(0x32),
|
||||
GLAMO_REG_MEM_DRAM1 = REG_MEM(0x34),
|
||||
GLAMO_REG_MEM_DRAM2 = REG_MEM(0x36),
|
||||
GLAMO_REG_MEM_CRC = REG_MEM(0x38),
|
||||
};
|
||||
|
||||
#define GLAMO_MEM_TYPE_MASK 0x03
|
||||
|
||||
enum glamo_reg_mem_dram1 {
|
||||
GLAMO_MEM_DRAM1_EN_SDRAM_CLK = (1 << 11),
|
||||
GLAMO_MEM_DRAM1_SELF_REFRESH = (1 << 12),
|
||||
};
|
||||
|
||||
enum glamo_reg_mem_dram2 {
|
||||
GLAMO_MEM_DRAM2_DEEP_PWRDOWN = (1 << 12),
|
||||
};
|
||||
|
||||
enum glamo_irq_index {
|
||||
GLAMO_IRQIDX_HOSTBUS = 0,
|
||||
GLAMO_IRQIDX_JPEG = 1,
|
||||
GLAMO_IRQIDX_MPEG = 2,
|
||||
GLAMO_IRQIDX_MPROC1 = 3,
|
||||
GLAMO_IRQIDX_MPROC0 = 4,
|
||||
GLAMO_IRQIDX_CMDQUEUE = 5,
|
||||
GLAMO_IRQIDX_2D = 6,
|
||||
GLAMO_IRQIDX_MMC = 7,
|
||||
GLAMO_IRQIDX_RISC = 8,
|
||||
};
|
||||
|
||||
enum glamo_irq {
|
||||
GLAMO_IRQ_HOSTBUS = (1 << GLAMO_IRQIDX_HOSTBUS),
|
||||
GLAMO_IRQ_JPEG = (1 << GLAMO_IRQIDX_JPEG),
|
||||
GLAMO_IRQ_MPEG = (1 << GLAMO_IRQIDX_MPEG),
|
||||
GLAMO_IRQ_MPROC1 = (1 << GLAMO_IRQIDX_MPROC1),
|
||||
GLAMO_IRQ_MPROC0 = (1 << GLAMO_IRQIDX_MPROC0),
|
||||
GLAMO_IRQ_CMDQUEUE = (1 << GLAMO_IRQIDX_CMDQUEUE),
|
||||
GLAMO_IRQ_2D = (1 << GLAMO_IRQIDX_2D),
|
||||
GLAMO_IRQ_MMC = (1 << GLAMO_IRQIDX_MMC),
|
||||
GLAMO_IRQ_RISC = (1 << GLAMO_IRQIDX_RISC),
|
||||
};
|
||||
|
||||
enum glamo_reg_clock_host {
|
||||
GLAMO_CLOCK_HOST_DG_BCLK = 0x0001,
|
||||
GLAMO_CLOCK_HOST_DG_M0CLK = 0x0004,
|
||||
GLAMO_CLOCK_HOST_RESET = 0x1000,
|
||||
};
|
||||
|
||||
enum glamo_reg_clock_mem {
|
||||
GLAMO_CLOCK_MEM_DG_M1CLK = 0x0001,
|
||||
GLAMO_CLOCK_MEM_EN_M1CLK = 0x0002,
|
||||
GLAMO_CLOCK_MEM_DG_MOCACLK = 0x0004,
|
||||
GLAMO_CLOCK_MEM_EN_MOCACLK = 0x0008,
|
||||
GLAMO_CLOCK_MEM_RESET = 0x1000,
|
||||
GLAMO_CLOCK_MOCA_RESET = 0x2000,
|
||||
};
|
||||
|
||||
enum glamo_reg_clock_lcd {
|
||||
GLAMO_CLOCK_LCD_DG_DCLK = 0x0001,
|
||||
GLAMO_CLOCK_LCD_EN_DCLK = 0x0002,
|
||||
GLAMO_CLOCK_LCD_DG_DMCLK = 0x0004,
|
||||
GLAMO_CLOCK_LCD_EN_DMCLK = 0x0008,
|
||||
//
|
||||
GLAMO_CLOCK_LCD_EN_DHCLK = 0x0020,
|
||||
GLAMO_CLOCK_LCD_DG_M5CLK = 0x0040,
|
||||
GLAMO_CLOCK_LCD_EN_M5CLK = 0x0080,
|
||||
GLAMO_CLOCK_LCD_RESET = 0x1000,
|
||||
};
|
||||
|
||||
enum glamo_reg_clock_mmc {
|
||||
GLAMO_CLOCK_MMC_DG_TCLK = 0x0001,
|
||||
GLAMO_CLOCK_MMC_EN_TCLK = 0x0002,
|
||||
GLAMO_CLOCK_MMC_DG_M9CLK = 0x0004,
|
||||
GLAMO_CLOCK_MMC_EN_M9CLK = 0x0008,
|
||||
GLAMO_CLOCK_MMC_RESET = 0x1000,
|
||||
};
|
||||
|
||||
enum glamo_reg_basic_mmc {
|
||||
/* set to disable CRC error rejection */
|
||||
GLAMO_BASIC_MMC_DISABLE_CRC = 0x0001,
|
||||
/* enable completion interrupt */
|
||||
GLAMO_BASIC_MMC_EN_COMPL_INT = 0x0002,
|
||||
/* stop MMC clock while enforced idle waiting for data from card */
|
||||
GLAMO_BASIC_MMC_NO_CLK_RD_WAIT = 0x0004,
|
||||
/* 0 = 1-bit bus to card, 1 = use 4-bit bus (has to be negotiated) */
|
||||
GLAMO_BASIC_MMC_EN_4BIT_DATA = 0x0008,
|
||||
/* enable 75K pullups on D3..D0 */
|
||||
GLAMO_BASIC_MMC_EN_DATA_PUPS = 0x0010,
|
||||
/* enable 75K pullup on CMD */
|
||||
GLAMO_BASIC_MMC_EN_CMD_PUP = 0x0020,
|
||||
/* IO drive strength 00=weak -> 11=strongest */
|
||||
GLAMO_BASIC_MMC_EN_DR_STR0 = 0x0040,
|
||||
GLAMO_BASIC_MMC_EN_DR_STR1 = 0x0080,
|
||||
/* TCLK delay stage A, 0000 = 500ps --> 1111 = 8ns */
|
||||
GLAMO_BASIC_MMC_EN_TCLK_DLYA0 = 0x0100,
|
||||
GLAMO_BASIC_MMC_EN_TCLK_DLYA1 = 0x0200,
|
||||
GLAMO_BASIC_MMC_EN_TCLK_DLYA2 = 0x0400,
|
||||
GLAMO_BASIC_MMC_EN_TCLK_DLYA3 = 0x0800,
|
||||
/* TCLK delay stage B (cumulative), 0000 = 500ps --> 1111 = 8ns */
|
||||
GLAMO_BASIC_MMC_EN_TCLK_DLYB0 = 0x1000,
|
||||
GLAMO_BASIC_MMC_EN_TCLK_DLYB1 = 0x2000,
|
||||
GLAMO_BASIC_MMC_EN_TCLK_DLYB2 = 0x4000,
|
||||
GLAMO_BASIC_MMC_EN_TCLK_DLYB3 = 0x8000,
|
||||
};
|
||||
|
||||
enum glamo_reg_stat1_mmc {
|
||||
/* command "counter" (really: toggle) */
|
||||
GLAMO_STAT1_MMC_CMD_CTR = 0x8000,
|
||||
/* engine is idle */
|
||||
GLAMO_STAT1_MMC_IDLE = 0x4000,
|
||||
/* readback response is ready */
|
||||
GLAMO_STAT1_MMC_RB_RRDY = 0x0200,
|
||||
/* readback data is ready */
|
||||
GLAMO_STAT1_MMC_RB_DRDY = 0x0100,
|
||||
/* no response timeout */
|
||||
GLAMO_STAT1_MMC_RTOUT = 0x0020,
|
||||
/* no data timeout */
|
||||
GLAMO_STAT1_MMC_DTOUT = 0x0010,
|
||||
/* CRC error on block write */
|
||||
GLAMO_STAT1_MMC_BWERR = 0x0004,
|
||||
/* CRC error on block read */
|
||||
GLAMO_STAT1_MMC_BRERR = 0x0002
|
||||
};
|
||||
|
||||
enum glamo_reg_fire_mmc {
|
||||
/* command "counter" (really: toggle)
|
||||
* the STAT1 register reflects this so you can ensure you don't look
|
||||
* at status for previous command
|
||||
*/
|
||||
GLAMO_FIRE_MMC_CMD_CTR = 0x8000,
|
||||
/* sets kind of response expected */
|
||||
GLAMO_FIRE_MMC_RES_MASK = 0x0700,
|
||||
/* sets command type */
|
||||
GLAMO_FIRE_MMC_TYP_MASK = 0x00C0,
|
||||
/* sets command class */
|
||||
GLAMO_FIRE_MMC_CLS_MASK = 0x000F,
|
||||
};
|
||||
|
||||
enum glamo_fire_mmc_response_types {
|
||||
GLAMO_FIRE_MMC_RSPT_R1 = 0x0000,
|
||||
GLAMO_FIRE_MMC_RSPT_R1b = 0x0100,
|
||||
GLAMO_FIRE_MMC_RSPT_R2 = 0x0200,
|
||||
GLAMO_FIRE_MMC_RSPT_R3 = 0x0300,
|
||||
GLAMO_FIRE_MMC_RSPT_R4 = 0x0400,
|
||||
GLAMO_FIRE_MMC_RSPT_R5 = 0x0500,
|
||||
};
|
||||
|
||||
enum glamo_fire_mmc_command_types {
|
||||
/* broadcast, no response */
|
||||
GLAMO_FIRE_MMC_CMDT_BNR = 0x0000,
|
||||
/* broadcast, with response */
|
||||
GLAMO_FIRE_MMC_CMDT_BR = 0x0040,
|
||||
/* addressed, no data */
|
||||
GLAMO_FIRE_MMC_CMDT_AND = 0x0080,
|
||||
/* addressed, with data */
|
||||
GLAMO_FIRE_MMC_CMDT_AD = 0x00C0,
|
||||
};
|
||||
|
||||
enum glamo_fire_mmc_command_class {
|
||||
/* "Stream Read" */
|
||||
GLAMO_FIRE_MMC_CC_STRR = 0x0000,
|
||||
/* Single Block Read */
|
||||
GLAMO_FIRE_MMC_CC_SBR = 0x0001,
|
||||
/* Multiple Block Read With Stop */
|
||||
GLAMO_FIRE_MMC_CC_MBRS = 0x0002,
|
||||
/* Multiple Block Read No Stop */
|
||||
GLAMO_FIRE_MMC_CC_MBRNS = 0x0003,
|
||||
/* RESERVED for "Stream Write" */
|
||||
GLAMO_FIRE_MMC_CC_STRW = 0x0004,
|
||||
/* "Stream Write" */
|
||||
GLAMO_FIRE_MMC_CC_SBW = 0x0005,
|
||||
/* RESERVED for Multiple Block Write With Stop */
|
||||
GLAMO_FIRE_MMC_CC_MBWS = 0x0006,
|
||||
/* Multiple Block Write No Stop */
|
||||
GLAMO_FIRE_MMC_CC_MBWNS = 0x0007,
|
||||
/* STOP command */
|
||||
GLAMO_FIRE_MMC_CC_STOP = 0x0008,
|
||||
/* Cancel on Running Command */
|
||||
GLAMO_FIRE_MMC_CC_CANCL = 0x0009,
|
||||
/* "Basic Command" */
|
||||
GLAMO_FIRE_MMC_CC_BASIC = 0x000a,
|
||||
};
|
||||
|
||||
/* these are offsets from the start of the MMC register region */
|
||||
enum glamo_register_mmc {
|
||||
/* MMC command, b15..8 = cmd arg b7..0; b7..1 = CRC; b0 = end bit */
|
||||
GLAMO_REG_MMC_CMD_REG1 = 0x00,
|
||||
/* MMC command, b15..0 = cmd arg b23 .. 8 */
|
||||
GLAMO_REG_MMC_CMD_REG2 = 0x02,
|
||||
/* MMC command, b15=start, b14=transmission,
|
||||
* b13..8=cmd idx, b7..0=cmd arg b31..24
|
||||
*/
|
||||
GLAMO_REG_MMC_CMD_REG3 = 0x04,
|
||||
GLAMO_REG_MMC_CMD_FIRE = 0x06,
|
||||
GLAMO_REG_MMC_CMD_RSP1 = 0x10,
|
||||
GLAMO_REG_MMC_CMD_RSP2 = 0x12,
|
||||
GLAMO_REG_MMC_CMD_RSP3 = 0x14,
|
||||
GLAMO_REG_MMC_CMD_RSP4 = 0x16,
|
||||
GLAMO_REG_MMC_CMD_RSP5 = 0x18,
|
||||
GLAMO_REG_MMC_CMD_RSP6 = 0x1a,
|
||||
GLAMO_REG_MMC_CMD_RSP7 = 0x1c,
|
||||
GLAMO_REG_MMC_CMD_RSP8 = 0x1e,
|
||||
GLAMO_REG_MMC_RB_STAT1 = 0x20,
|
||||
GLAMO_REG_MMC_RB_BLKCNT = 0x22,
|
||||
GLAMO_REG_MMC_RB_BLKLEN = 0x24,
|
||||
GLAMO_REG_MMC_BASIC = 0x30,
|
||||
GLAMO_REG_MMC_RDATADS1 = 0x34,
|
||||
GLAMO_REG_MMC_RDATADS2 = 0x36,
|
||||
GLAMO_REG_MMC_WDATADS1 = 0x38,
|
||||
GLAMO_REG_MMC_WDATADS2 = 0x3a,
|
||||
GLAMO_REG_MMC_DATBLKCNT = 0x3c,
|
||||
GLAMO_REG_MMC_DATBLKLEN = 0x3e,
|
||||
GLAMO_REG_MMC_TIMEOUT = 0x40,
|
||||
|
||||
};
|
||||
|
||||
enum glamo_reg_clock_isp {
|
||||
GLAMO_CLOCK_ISP_DG_I1CLK = 0x0001,
|
||||
GLAMO_CLOCK_ISP_EN_I1CLK = 0x0002,
|
||||
GLAMO_CLOCK_ISP_DG_CCLK = 0x0004,
|
||||
GLAMO_CLOCK_ISP_EN_CCLK = 0x0008,
|
||||
//
|
||||
GLAMO_CLOCK_ISP_EN_SCLK = 0x0020,
|
||||
GLAMO_CLOCK_ISP_DG_M2CLK = 0x0040,
|
||||
GLAMO_CLOCK_ISP_EN_M2CLK = 0x0080,
|
||||
GLAMO_CLOCK_ISP_DG_M15CLK = 0x0100,
|
||||
GLAMO_CLOCK_ISP_EN_M15CLK = 0x0200,
|
||||
GLAMO_CLOCK_ISP1_RESET = 0x1000,
|
||||
GLAMO_CLOCK_ISP2_RESET = 0x2000,
|
||||
};
|
||||
|
||||
enum glamo_reg_clock_jpeg {
|
||||
GLAMO_CLOCK_JPEG_DG_JCLK = 0x0001,
|
||||
GLAMO_CLOCK_JPEG_EN_JCLK = 0x0002,
|
||||
GLAMO_CLOCK_JPEG_DG_M3CLK = 0x0004,
|
||||
GLAMO_CLOCK_JPEG_EN_M3CLK = 0x0008,
|
||||
GLAMO_CLOCK_JPEG_RESET = 0x1000,
|
||||
};
|
||||
|
||||
enum glamo_reg_clock_2d {
|
||||
GLAMO_CLOCK_2D_DG_GCLK = 0x0001,
|
||||
GLAMO_CLOCK_2D_EN_GCLK = 0x0002,
|
||||
GLAMO_CLOCK_2D_DG_M7CLK = 0x0004,
|
||||
GLAMO_CLOCK_2D_EN_M7CLK = 0x0008,
|
||||
GLAMO_CLOCK_2D_DG_M6CLK = 0x0010,
|
||||
GLAMO_CLOCK_2D_EN_M6CLK = 0x0020,
|
||||
GLAMO_CLOCK_2D_RESET = 0x1000,
|
||||
GLAMO_CLOCK_2D_CQ_RESET = 0x2000,
|
||||
};
|
||||
|
||||
enum glamo_reg_clock_3d {
|
||||
GLAMO_CLOCK_3D_DG_ECLK = 0x0001,
|
||||
GLAMO_CLOCK_3D_EN_ECLK = 0x0002,
|
||||
GLAMO_CLOCK_3D_DG_RCLK = 0x0004,
|
||||
GLAMO_CLOCK_3D_EN_RCLK = 0x0008,
|
||||
GLAMO_CLOCK_3D_DG_M8CLK = 0x0010,
|
||||
GLAMO_CLOCK_3D_EN_M8CLK = 0x0020,
|
||||
GLAMO_CLOCK_3D_BACK_RESET = 0x1000,
|
||||
GLAMO_CLOCK_3D_FRONT_RESET = 0x2000,
|
||||
};
|
||||
|
||||
enum glamo_reg_clock_mpeg {
|
||||
GLAMO_CLOCK_MPEG_DG_X0CLK = 0x0001,
|
||||
GLAMO_CLOCK_MPEG_EN_X0CLK = 0x0002,
|
||||
GLAMO_CLOCK_MPEG_DG_X1CLK = 0x0004,
|
||||
GLAMO_CLOCK_MPEG_EN_X1CLK = 0x0008,
|
||||
GLAMO_CLOCK_MPEG_DG_X2CLK = 0x0010,
|
||||
GLAMO_CLOCK_MPEG_EN_X2CLK = 0x0020,
|
||||
GLAMO_CLOCK_MPEG_DG_X3CLK = 0x0040,
|
||||
GLAMO_CLOCK_MPEG_EN_X3CLK = 0x0080,
|
||||
GLAMO_CLOCK_MPEG_DG_X4CLK = 0x0100,
|
||||
GLAMO_CLOCK_MPEG_EN_X4CLK = 0x0200,
|
||||
GLAMO_CLOCK_MPEG_DG_X6CLK = 0x0400,
|
||||
GLAMO_CLOCK_MPEG_EN_X6CLK = 0x0800,
|
||||
GLAMO_CLOCK_MPEG_ENC_RESET = 0x1000,
|
||||
GLAMO_CLOCK_MPEG_DEC_RESET = 0x2000,
|
||||
};
|
||||
|
||||
enum glamo_reg_clock51 {
|
||||
GLAMO_CLOCK_GEN51_EN_DIV_MCLK = 0x0001,
|
||||
GLAMO_CLOCK_GEN51_EN_DIV_SCLK = 0x0002,
|
||||
GLAMO_CLOCK_GEN51_EN_DIV_JCLK = 0x0004,
|
||||
GLAMO_CLOCK_GEN51_EN_DIV_DCLK = 0x0008,
|
||||
GLAMO_CLOCK_GEN51_EN_DIV_DMCLK = 0x0010,
|
||||
GLAMO_CLOCK_GEN51_EN_DIV_DHCLK = 0x0020,
|
||||
GLAMO_CLOCK_GEN51_EN_DIV_GCLK = 0x0040,
|
||||
GLAMO_CLOCK_GEN51_EN_DIV_TCLK = 0x0080,
|
||||
/* FIXME: higher bits */
|
||||
};
|
||||
|
||||
enum glamo_reg_hostbus2 {
|
||||
GLAMO_HOSTBUS2_MMIO_EN_ISP = 0x0001,
|
||||
GLAMO_HOSTBUS2_MMIO_EN_JPEG = 0x0002,
|
||||
GLAMO_HOSTBUS2_MMIO_EN_MPEG = 0x0004,
|
||||
GLAMO_HOSTBUS2_MMIO_EN_LCD = 0x0008,
|
||||
GLAMO_HOSTBUS2_MMIO_EN_MMC = 0x0010,
|
||||
GLAMO_HOSTBUS2_MMIO_EN_MICROP0 = 0x0020,
|
||||
GLAMO_HOSTBUS2_MMIO_EN_MICROP1 = 0x0040,
|
||||
GLAMO_HOSTBUS2_MMIO_EN_CQ = 0x0080,
|
||||
GLAMO_HOSTBUS2_MMIO_EN_RISC = 0x0100,
|
||||
GLAMO_HOSTBUS2_MMIO_EN_2D = 0x0200,
|
||||
GLAMO_HOSTBUS2_MMIO_EN_3D = 0x0400,
|
||||
};
|
||||
|
||||
/* LCD Controller */
|
||||
|
||||
#define REG_LCD(x) (x)
|
||||
enum glamo_reg_lcd {
|
||||
GLAMO_REG_LCD_MODE1 = REG_LCD(0x00),
|
||||
GLAMO_REG_LCD_MODE2 = REG_LCD(0x02),
|
||||
GLAMO_REG_LCD_MODE3 = REG_LCD(0x04),
|
||||
GLAMO_REG_LCD_WIDTH = REG_LCD(0x06),
|
||||
GLAMO_REG_LCD_HEIGHT = REG_LCD(0x08),
|
||||
GLAMO_REG_LCD_POLARITY = REG_LCD(0x0a),
|
||||
GLAMO_REG_LCD_A_BASE1 = REG_LCD(0x0c),
|
||||
GLAMO_REG_LCD_A_BASE2 = REG_LCD(0x0e),
|
||||
GLAMO_REG_LCD_B_BASE1 = REG_LCD(0x10),
|
||||
GLAMO_REG_LCD_B_BASE2 = REG_LCD(0x12),
|
||||
GLAMO_REG_LCD_C_BASE1 = REG_LCD(0x14),
|
||||
GLAMO_REG_LCD_C_BASE2 = REG_LCD(0x16),
|
||||
GLAMO_REG_LCD_PITCH = REG_LCD(0x18),
|
||||
/* RES */
|
||||
GLAMO_REG_LCD_HORIZ_TOTAL = REG_LCD(0x1c),
|
||||
/* RES */
|
||||
GLAMO_REG_LCD_HORIZ_RETR_START = REG_LCD(0x20),
|
||||
/* RES */
|
||||
GLAMO_REG_LCD_HORIZ_RETR_END = REG_LCD(0x24),
|
||||
/* RES */
|
||||
GLAMO_REG_LCD_HORIZ_DISP_START = REG_LCD(0x28),
|
||||
/* RES */
|
||||
GLAMO_REG_LCD_HORIZ_DISP_END = REG_LCD(0x2c),
|
||||
/* RES */
|
||||
GLAMO_REG_LCD_VERT_TOTAL = REG_LCD(0x30),
|
||||
/* RES */
|
||||
GLAMO_REG_LCD_VERT_RETR_START = REG_LCD(0x34),
|
||||
/* RES */
|
||||
GLAMO_REG_LCD_VERT_RETR_END = REG_LCD(0x38),
|
||||
/* RES */
|
||||
GLAMO_REG_LCD_VERT_DISP_START = REG_LCD(0x3c),
|
||||
/* RES */
|
||||
GLAMO_REG_LCD_VERT_DISP_END = REG_LCD(0x40),
|
||||
/* RES */
|
||||
GLAMO_REG_LCD_POL = REG_LCD(0x44),
|
||||
GLAMO_REG_LCD_DATA_START = REG_LCD(0x46),
|
||||
GLAMO_REG_LCD_FRATE_CONTRO = REG_LCD(0x48),
|
||||
GLAMO_REG_LCD_DATA_CMD_HDR = REG_LCD(0x4a),
|
||||
GLAMO_REG_LCD_SP_START = REG_LCD(0x4c),
|
||||
GLAMO_REG_LCD_SP_END = REG_LCD(0x4e),
|
||||
GLAMO_REG_LCD_CURSOR_BASE1 = REG_LCD(0x50),
|
||||
GLAMO_REG_LCD_CURSOR_BASE2 = REG_LCD(0x52),
|
||||
GLAMO_REG_LCD_CURSOR_PITCH = REG_LCD(0x54),
|
||||
GLAMO_REG_LCD_CURSOR_X_SIZE = REG_LCD(0x56),
|
||||
GLAMO_REG_LCD_CURSOR_Y_SIZE = REG_LCD(0x58),
|
||||
GLAMO_REG_LCD_CURSOR_X_POS = REG_LCD(0x5a),
|
||||
GLAMO_REG_LCD_CURSOR_Y_POS = REG_LCD(0x5c),
|
||||
GLAMO_REG_LCD_CURSOR_PRESET = REG_LCD(0x5e),
|
||||
GLAMO_REG_LCD_CURSOR_FG_COLOR = REG_LCD(0x60),
|
||||
/* RES */
|
||||
GLAMO_REG_LCD_CURSOR_BG_COLOR = REG_LCD(0x64),
|
||||
/* RES */
|
||||
GLAMO_REG_LCD_CURSOR_DST_COLOR = REG_LCD(0x68),
|
||||
/* RES */
|
||||
GLAMO_REG_LCD_STATUS1 = REG_LCD(0x80),
|
||||
GLAMO_REG_LCD_STATUS2 = REG_LCD(0x82),
|
||||
GLAMO_REG_LCD_STATUS3 = REG_LCD(0x84),
|
||||
GLAMO_REG_LCD_STATUS4 = REG_LCD(0x86),
|
||||
/* RES */
|
||||
GLAMO_REG_LCD_COMMAND1 = REG_LCD(0xa0),
|
||||
GLAMO_REG_LCD_COMMAND2 = REG_LCD(0xa2),
|
||||
/* RES */
|
||||
GLAMO_REG_LCD_WFORM_DELAY1 = REG_LCD(0xb0),
|
||||
GLAMO_REG_LCD_WFORM_DELAY2 = REG_LCD(0xb2),
|
||||
/* RES */
|
||||
GLAMO_REG_LCD_GAMMA_CORR = REG_LCD(0x100),
|
||||
/* RES */
|
||||
GLAMO_REG_LCD_GAMMA_R_ENTRY01 = REG_LCD(0x110),
|
||||
GLAMO_REG_LCD_GAMMA_R_ENTRY23 = REG_LCD(0x112),
|
||||
GLAMO_REG_LCD_GAMMA_R_ENTRY45 = REG_LCD(0x114),
|
||||
GLAMO_REG_LCD_GAMMA_R_ENTRY67 = REG_LCD(0x116),
|
||||
GLAMO_REG_LCD_GAMMA_R_ENTRY8 = REG_LCD(0x118),
|
||||
/* RES */
|
||||
GLAMO_REG_LCD_GAMMA_G_ENTRY01 = REG_LCD(0x130),
|
||||
GLAMO_REG_LCD_GAMMA_G_ENTRY23 = REG_LCD(0x132),
|
||||
GLAMO_REG_LCD_GAMMA_G_ENTRY45 = REG_LCD(0x134),
|
||||
GLAMO_REG_LCD_GAMMA_G_ENTRY67 = REG_LCD(0x136),
|
||||
GLAMO_REG_LCD_GAMMA_G_ENTRY8 = REG_LCD(0x138),
|
||||
/* RES */
|
||||
GLAMO_REG_LCD_GAMMA_B_ENTRY01 = REG_LCD(0x150),
|
||||
GLAMO_REG_LCD_GAMMA_B_ENTRY23 = REG_LCD(0x152),
|
||||
GLAMO_REG_LCD_GAMMA_B_ENTRY45 = REG_LCD(0x154),
|
||||
GLAMO_REG_LCD_GAMMA_B_ENTRY67 = REG_LCD(0x156),
|
||||
GLAMO_REG_LCD_GAMMA_B_ENTRY8 = REG_LCD(0x158),
|
||||
/* RES */
|
||||
GLAMO_REG_LCD_SRAM_DRIVING1 = REG_LCD(0x160),
|
||||
GLAMO_REG_LCD_SRAM_DRIVING2 = REG_LCD(0x162),
|
||||
GLAMO_REG_LCD_SRAM_DRIVING3 = REG_LCD(0x164),
|
||||
};
|
||||
|
||||
enum glamo_reg_lcd_mode1 {
|
||||
GLAMO_LCD_MODE1_PWRSAVE = 0x0001,
|
||||
GLAMO_LCD_MODE1_PARTIAL_PRT = 0x0002,
|
||||
GLAMO_LCD_MODE1_HWFLIP = 0x0004,
|
||||
GLAMO_LCD_MODE1_LCD2 = 0x0008,
|
||||
/* RES */
|
||||
GLAMO_LCD_MODE1_PARTIAL_MODE = 0x0020,
|
||||
GLAMO_LCD_MODE1_CURSOR_DSTCOLOR = 0x0040,
|
||||
GLAMO_LCD_MODE1_PARTIAL_ENABLE = 0x0080,
|
||||
GLAMO_LCD_MODE1_TVCLK_IN_ENABLE = 0x0100,
|
||||
GLAMO_LCD_MODE1_HSYNC_HIGH_ACT = 0x0200,
|
||||
GLAMO_LCD_MODE1_VSYNC_HIGH_ACT = 0x0400,
|
||||
GLAMO_LCD_MODE1_HSYNC_FLIP = 0x0800,
|
||||
GLAMO_LCD_MODE1_GAMMA_COR_EN = 0x1000,
|
||||
GLAMO_LCD_MODE1_DITHER_EN = 0x2000,
|
||||
GLAMO_LCD_MODE1_CURSOR_EN = 0x4000,
|
||||
GLAMO_LCD_MODE1_ROTATE_EN = 0x8000,
|
||||
};
|
||||
|
||||
enum glamo_reg_lcd_mode2 {
|
||||
GLAMO_LCD_MODE2_CRC_CHECK_EN = 0x0001,
|
||||
GLAMO_LCD_MODE2_DCMD_PER_LINE = 0x0002,
|
||||
GLAMO_LCD_MODE2_NOUSE_BDEF = 0x0004,
|
||||
GLAMO_LCD_MODE2_OUT_POS_MODE = 0x0008,
|
||||
GLAMO_LCD_MODE2_FRATE_CTRL_EN = 0x0010,
|
||||
GLAMO_LCD_MODE2_SINGLE_BUFFER = 0x0020,
|
||||
GLAMO_LCD_MODE2_SER_LSB_TO_MSB = 0x0040,
|
||||
/* FIXME */
|
||||
};
|
||||
|
||||
enum glamo_reg_lcd_mode3 {
|
||||
/* LCD color source data format */
|
||||
GLAMO_LCD_SRC_RGB565 = 0x0000,
|
||||
GLAMO_LCD_SRC_ARGB1555 = 0x4000,
|
||||
GLAMO_LCD_SRC_ARGB4444 = 0x8000,
|
||||
/* interface type */
|
||||
GLAMO_LCD_MODE3_LCD = 0x1000,
|
||||
GLAMO_LCD_MODE3_RGB = 0x0800,
|
||||
GLAMO_LCD_MODE3_CPU = 0x0000,
|
||||
/* mode */
|
||||
GLAMO_LCD_MODE3_RGB332 = 0x0000,
|
||||
GLAMO_LCD_MODE3_RGB444 = 0x0100,
|
||||
GLAMO_LCD_MODE3_RGB565 = 0x0200,
|
||||
GLAMO_LCD_MODE3_RGB666 = 0x0300,
|
||||
/* depth */
|
||||
GLAMO_LCD_MODE3_6BITS = 0x0000,
|
||||
GLAMO_LCD_MODE3_8BITS = 0x0010,
|
||||
GLAMO_LCD_MODE3_9BITS = 0x0020,
|
||||
GLAMO_LCD_MODE3_16BITS = 0x0030,
|
||||
GLAMO_LCD_MODE3_18BITS = 0x0040,
|
||||
};
|
||||
|
||||
enum glamo_lcd_rot_mode {
|
||||
GLAMO_LCD_ROT_MODE_0 = 0x0000,
|
||||
GLAMO_LCD_ROT_MODE_180 = 0x2000,
|
||||
GLAMO_LCD_ROT_MODE_MIRROR = 0x4000,
|
||||
GLAMO_LCD_ROT_MODE_FLIP = 0x6000,
|
||||
GLAMO_LCD_ROT_MODE_90 = 0x8000,
|
||||
GLAMO_LCD_ROT_MODE_270 = 0xa000,
|
||||
};
|
||||
#define GLAMO_LCD_ROT_MODE_MASK 0xe000
|
||||
|
||||
enum glamo_lcd_cmd_type {
|
||||
GLAMO_LCD_CMD_TYPE_DISP = 0x0000,
|
||||
GLAMO_LCD_CMD_TYPE_PARALLEL = 0x4000,
|
||||
GLAMO_LCD_CMD_TYPE_SERIAL = 0x8000,
|
||||
GLAMO_LCD_CMD_TYPE_SERIAL_DIRECT= 0xc000,
|
||||
};
|
||||
#define GLAMO_LCD_CMD_TYPE_MASK 0xc000
|
||||
|
||||
enum glamo_lcd_cmds {
|
||||
GLAMO_LCD_CMD_DATA_DISP_FIRE = 0x00,
|
||||
GLAMO_LCD_CMD_DATA_DISP_SYNC = 0x01, /* RGB only */
|
||||
/* switch to command mode, no display */
|
||||
GLAMO_LCD_CMD_DATA_FIRE_NO_DISP = 0x02,
|
||||
/* display until VSYNC, switch to command */
|
||||
GLAMO_LCD_CMD_DATA_FIRE_VSYNC = 0x11,
|
||||
/* display until HSYNC, switch to command */
|
||||
GLAMO_LCD_CMD_DATA_FIRE_HSYNC = 0x12,
|
||||
/* display until VSYNC, 1 black frame, VSYNC, switch to command */
|
||||
GLAMO_LCD_CMD_DATA_FIRE_VSYNC_B = 0x13,
|
||||
/* don't care about display and switch to command */
|
||||
GLAMO_LCD_CMD_DATA_FIRE_FREE = 0x14, /* RGB only */
|
||||
/* don't care about display, keep data display but disable data,
|
||||
* and switch to command */
|
||||
GLAMO_LCD_CMD_DATA_FIRE_FREE_D = 0x15, /* RGB only */
|
||||
};
|
||||
|
||||
enum glamo_core_revisions {
|
||||
GLAMO_CORE_REV_A0 = 0x0000,
|
||||
GLAMO_CORE_REV_A1 = 0x0001,
|
||||
GLAMO_CORE_REV_A2 = 0x0002,
|
||||
GLAMO_CORE_REV_A3 = 0x0003,
|
||||
};
|
||||
|
||||
#endif /* _GLAMO_REGS_H */
|
3
qiboot/include/i2c-bitbang-s3c24xx.h
Normal file
3
qiboot/include/i2c-bitbang-s3c24xx.h
Normal file
@ -0,0 +1,3 @@
|
||||
#include <i2c-bitbang.h>
|
||||
|
||||
extern struct i2c_bitbang bb_s3c24xx;
|
3
qiboot/include/i2c-bitbang-s3c6410.h
Normal file
3
qiboot/include/i2c-bitbang-s3c6410.h
Normal file
@ -0,0 +1,3 @@
|
||||
#include <i2c-bitbang.h>
|
||||
|
||||
extern struct i2c_bitbang bb_s3c6410;
|
102
qiboot/include/i2c-bitbang.h
Normal file
102
qiboot/include/i2c-bitbang.h
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
* Author: Andy Green <andy@openmoko.com>
|
||||
*
|
||||
* Generic i2c bitbang state machine
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* controls symbol sequencing on i2c */
|
||||
|
||||
enum i2c_bitbang_control {
|
||||
IBCONTROL_DO_START = -1,
|
||||
IBCONTROL_DO_STOP = -2,
|
||||
IBCONTROL_DO_READ = -3,
|
||||
IBCONTROL_COMPLETE = -4
|
||||
};
|
||||
|
||||
/* control intra-bit and byte states */
|
||||
|
||||
enum i2c_bitbang_states {
|
||||
IBS_INIT,
|
||||
|
||||
IBS_START1,
|
||||
IBS_START2,
|
||||
|
||||
IBS_ADS_TX_S,
|
||||
IBS_ADS_TX_H,
|
||||
IBS_ADS_TX_L,
|
||||
IBS_ADS_TX_ACK_H,
|
||||
IBS_ADS_TX_ACK_L,
|
||||
|
||||
IBS_DATA_RX_S,
|
||||
IBS_DATA_RX_H,
|
||||
IBS_DATA_RX_L,
|
||||
|
||||
IBS_DATA_RX_ACK_H,
|
||||
IBS_DATA_RX_ACK_L,
|
||||
|
||||
IBS_STOP1,
|
||||
IBS_STOP2,
|
||||
IBS_STOP3,
|
||||
IBS_STOP4
|
||||
};
|
||||
|
||||
/* context for bitbang GPIO pins and transaction */
|
||||
|
||||
struct i2c_bitbang {
|
||||
|
||||
enum i2c_bitbang_states state;
|
||||
int count;
|
||||
unsigned int data[8]; /* read result found here */
|
||||
int index;
|
||||
int index_read;
|
||||
|
||||
char (*read_sda)(void);
|
||||
/* data = 0 = op low, 1 == inp */
|
||||
void (*set)(char clock, char data);
|
||||
/* delay > 1 half-bit time, used by i2c_complete_synchronously() */
|
||||
void (*spin)(void);
|
||||
void (*close)(void);
|
||||
};
|
||||
|
||||
/* synchronous read and write functions spin until completed or failed
|
||||
* i2c_read_sync returns -1 for fail or byte result from device
|
||||
*/
|
||||
|
||||
extern int i2c_read_sync(struct i2c_bitbang * bb, unsigned char ads7,
|
||||
unsigned char reg);
|
||||
extern void i2c_write_sync(struct i2c_bitbang * bb, unsigned char ads7,
|
||||
unsigned char reg, unsigned char data);
|
||||
|
||||
|
||||
/*
|
||||
* set up an asynchronous read or write transaction
|
||||
*/
|
||||
extern void i2c_read(struct i2c_bitbang * bb, unsigned char ads7,
|
||||
unsigned char reg);
|
||||
extern void i2c_write(struct i2c_bitbang * bb, unsigned char ads7,
|
||||
unsigned char reg, unsigned char data);
|
||||
|
||||
/*
|
||||
* after setting up a read or write transaction above, you loop calling this
|
||||
* with >= 1.25us (400kHz) or >= 5us (100kHz) delay between calls. You don't
|
||||
* have to spin but can do something useful if you know it will take more than
|
||||
* an i2c bit-time, hiding the time for the i2c transaction completely.
|
||||
*/
|
||||
extern int i2c_next_state(struct i2c_bitbang * bb); /* return !=0 = completed */
|
570
qiboot/include/image.h
Normal file
570
qiboot/include/image.h
Normal file
@ -0,0 +1,570 @@
|
||||
/*
|
||||
* (C) Copyright 2008 Semihalf
|
||||
*
|
||||
* (C) Copyright 2000-2005
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
********************************************************************
|
||||
* NOTE: This header file defines an interface to U-Boot. Including
|
||||
* this (unmodified) header file in another file is considered normal
|
||||
* use of U-Boot, and does *not* fall under the heading of "derived
|
||||
* work".
|
||||
********************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __IMAGE_H__
|
||||
#define __IMAGE_H__
|
||||
|
||||
/*
|
||||
* Operating System Codes
|
||||
*/
|
||||
#define IH_OS_INVALID 0 /* Invalid OS */
|
||||
#define IH_OS_OPENBSD 1 /* OpenBSD */
|
||||
#define IH_OS_NETBSD 2 /* NetBSD */
|
||||
#define IH_OS_FREEBSD 3 /* FreeBSD */
|
||||
#define IH_OS_4_4BSD 4 /* 4.4BSD */
|
||||
#define IH_OS_LINUX 5 /* Linux */
|
||||
#define IH_OS_SVR4 6 /* SVR4 */
|
||||
#define IH_OS_ESIX 7 /* Esix */
|
||||
#define IH_OS_SOLARIS 8 /* Solaris */
|
||||
#define IH_OS_IRIX 9 /* Irix */
|
||||
#define IH_OS_SCO 10 /* SCO */
|
||||
#define IH_OS_DELL 11 /* Dell */
|
||||
#define IH_OS_NCR 12 /* NCR */
|
||||
#define IH_OS_LYNXOS 13 /* LynxOS */
|
||||
#define IH_OS_VXWORKS 14 /* VxWorks */
|
||||
#define IH_OS_PSOS 15 /* pSOS */
|
||||
#define IH_OS_QNX 16 /* QNX */
|
||||
#define IH_OS_U_BOOT 17 /* Firmware */
|
||||
#define IH_OS_RTEMS 18 /* RTEMS */
|
||||
#define IH_OS_ARTOS 19 /* ARTOS */
|
||||
#define IH_OS_UNITY 20 /* Unity OS */
|
||||
|
||||
/*
|
||||
* CPU Architecture Codes (supported by Linux)
|
||||
*/
|
||||
#define IH_ARCH_INVALID 0 /* Invalid CPU */
|
||||
#define IH_ARCH_ALPHA 1 /* Alpha */
|
||||
#define IH_ARCH_ARM 2 /* ARM */
|
||||
#define IH_ARCH_I386 3 /* Intel x86 */
|
||||
#define IH_ARCH_IA64 4 /* IA64 */
|
||||
#define IH_ARCH_MIPS 5 /* MIPS */
|
||||
#define IH_ARCH_MIPS64 6 /* MIPS 64 Bit */
|
||||
#define IH_ARCH_PPC 7 /* PowerPC */
|
||||
#define IH_ARCH_S390 8 /* IBM S390 */
|
||||
#define IH_ARCH_SH 9 /* SuperH */
|
||||
#define IH_ARCH_SPARC 10 /* Sparc */
|
||||
#define IH_ARCH_SPARC64 11 /* Sparc 64 Bit */
|
||||
#define IH_ARCH_M68K 12 /* M68K */
|
||||
#define IH_ARCH_NIOS 13 /* Nios-32 */
|
||||
#define IH_ARCH_MICROBLAZE 14 /* MicroBlaze */
|
||||
#define IH_ARCH_NIOS2 15 /* Nios-II */
|
||||
#define IH_ARCH_BLACKFIN 16 /* Blackfin */
|
||||
#define IH_ARCH_AVR32 17 /* AVR32 */
|
||||
#define IH_ARCH_ST200 18 /* STMicroelectronics ST200 */
|
||||
|
||||
/*
|
||||
* Image Types
|
||||
*
|
||||
* "Standalone Programs" are directly runnable in the environment
|
||||
* provided by U-Boot; it is expected that (if they behave
|
||||
* well) you can continue to work in U-Boot after return from
|
||||
* the Standalone Program.
|
||||
* "OS Kernel Images" are usually images of some Embedded OS which
|
||||
* will take over control completely. Usually these programs
|
||||
* will install their own set of exception handlers, device
|
||||
* drivers, set up the MMU, etc. - this means, that you cannot
|
||||
* expect to re-enter U-Boot except by resetting the CPU.
|
||||
* "RAMDisk Images" are more or less just data blocks, and their
|
||||
* parameters (address, size) are passed to an OS kernel that is
|
||||
* being started.
|
||||
* "Multi-File Images" contain several images, typically an OS
|
||||
* (Linux) kernel image and one or more data images like
|
||||
* RAMDisks. This construct is useful for instance when you want
|
||||
* to boot over the network using BOOTP etc., where the boot
|
||||
* server provides just a single image file, but you want to get
|
||||
* for instance an OS kernel and a RAMDisk image.
|
||||
*
|
||||
* "Multi-File Images" start with a list of image sizes, each
|
||||
* image size (in bytes) specified by an "uint32_t" in network
|
||||
* byte order. This list is terminated by an "(uint32_t)0".
|
||||
* Immediately after the terminating 0 follow the images, one by
|
||||
* one, all aligned on "uint32_t" boundaries (size rounded up to
|
||||
* a multiple of 4 bytes - except for the last file).
|
||||
*
|
||||
* "Firmware Images" are binary images containing firmware (like
|
||||
* U-Boot or FPGA images) which usually will be programmed to
|
||||
* flash memory.
|
||||
*
|
||||
* "Script files" are command sequences that will be executed by
|
||||
* U-Boot's command interpreter; this feature is especially
|
||||
* useful when you configure U-Boot to use a real shell (hush)
|
||||
* as command interpreter (=> Shell Scripts).
|
||||
*/
|
||||
|
||||
#define IH_TYPE_INVALID 0 /* Invalid Image */
|
||||
#define IH_TYPE_STANDALONE 1 /* Standalone Program */
|
||||
#define IH_TYPE_KERNEL 2 /* OS Kernel Image */
|
||||
#define IH_TYPE_RAMDISK 3 /* RAMDisk Image */
|
||||
#define IH_TYPE_MULTI 4 /* Multi-File Image */
|
||||
#define IH_TYPE_FIRMWARE 5 /* Firmware Image */
|
||||
#define IH_TYPE_SCRIPT 6 /* Script file */
|
||||
#define IH_TYPE_FILESYSTEM 7 /* Filesystem Image (any type) */
|
||||
#define IH_TYPE_FLATDT 8 /* Binary Flat Device Tree Blob */
|
||||
|
||||
/*
|
||||
* Compression Types
|
||||
*/
|
||||
#define IH_COMP_NONE 0 /* No Compression Used */
|
||||
#define IH_COMP_GZIP 1 /* gzip Compression Used */
|
||||
#define IH_COMP_BZIP2 2 /* bzip2 Compression Used */
|
||||
|
||||
#define IH_MAGIC 0x27051956 /* Image Magic Number */
|
||||
#define IH_NMLEN 32 /* Image Name Length */
|
||||
|
||||
/*
|
||||
* Legacy format image header,
|
||||
* all data in network byte order (aka natural aka bigendian).
|
||||
*/
|
||||
typedef struct image_header {
|
||||
uint32_t ih_magic; /* Image Header Magic Number */
|
||||
uint32_t ih_hcrc; /* Image Header CRC Checksum */
|
||||
uint32_t ih_time; /* Image Creation Timestamp */
|
||||
uint32_t ih_size; /* Image Data Size */
|
||||
uint32_t ih_load; /* Data Load Address */
|
||||
uint32_t ih_ep; /* Entry Point Address */
|
||||
uint32_t ih_dcrc; /* Image Data CRC Checksum */
|
||||
uint8_t ih_os; /* Operating System */
|
||||
uint8_t ih_arch; /* CPU architecture */
|
||||
uint8_t ih_type; /* Image Type */
|
||||
uint8_t ih_comp; /* Compression Type */
|
||||
uint8_t ih_name[IH_NMLEN]; /* Image Name */
|
||||
} image_header_t;
|
||||
|
||||
/*
|
||||
* Legacy and FIT format headers used by do_bootm() and do_bootm_<os>()
|
||||
* routines.
|
||||
*/
|
||||
typedef struct bootm_headers {
|
||||
/*
|
||||
* Legacy os image header, if it is a multi component image
|
||||
* then boot_get_ramdisk() and get_fdt() will attempt to get
|
||||
* data from second and third component accordingly.
|
||||
*/
|
||||
image_header_t *legacy_hdr_os;
|
||||
ulong legacy_hdr_valid;
|
||||
|
||||
#if defined(CONFIG_FIT)
|
||||
const char *fit_uname_cfg; /* configuration node unit name */
|
||||
|
||||
void *fit_hdr_os; /* os FIT image header */
|
||||
const char *fit_uname_os; /* os subimage node unit name */
|
||||
int fit_noffset_os; /* os subimage node offset */
|
||||
|
||||
void *fit_hdr_rd; /* init ramdisk FIT image header */
|
||||
const char *fit_uname_rd; /* init ramdisk subimage node unit name */
|
||||
int fit_noffset_rd; /* init ramdisk subimage node offset */
|
||||
|
||||
#if defined(CONFIG_PPC)
|
||||
void *fit_hdr_fdt; /* FDT blob FIT image header */
|
||||
const char *fit_uname_fdt; /* FDT blob subimage node unit name */
|
||||
int fit_noffset_fdt;/* FDT blob subimage node offset */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int verify; /* getenv("verify")[0] != 'n' */
|
||||
int autostart; /* getenv("autostart")[0] != 'n' */
|
||||
struct lmb *lmb; /* for memory mgmt */
|
||||
} bootm_headers_t;
|
||||
|
||||
/*
|
||||
* Some systems (for example LWMON) have very short watchdog periods;
|
||||
* we must make sure to split long operations like memmove() or
|
||||
* crc32() into reasonable chunks.
|
||||
*/
|
||||
#define CHUNKSZ (64 * 1024)
|
||||
|
||||
#define uimage_to_cpu(x) __be32_to_cpu(x)
|
||||
#define cpu_to_uimage(x) __cpu_to_be32(x)
|
||||
|
||||
const char *genimg_get_os_name (uint8_t os);
|
||||
const char *genimg_get_arch_name (uint8_t arch);
|
||||
const char *genimg_get_type_name (uint8_t type);
|
||||
const char *genimg_get_comp_name (uint8_t comp);
|
||||
int genimg_get_os_id (const char *name);
|
||||
int genimg_get_arch_id (const char *name);
|
||||
int genimg_get_type_id (const char *name);
|
||||
int genimg_get_comp_id (const char *name);
|
||||
|
||||
#ifndef USE_HOSTCC
|
||||
/* Image format types, returned by _get_format() routine */
|
||||
#define IMAGE_FORMAT_INVALID 0x00
|
||||
#define IMAGE_FORMAT_LEGACY 0x01 /* legacy image_header based format */
|
||||
#define IMAGE_FORMAT_FIT 0x02 /* new, libfdt based format */
|
||||
|
||||
int genimg_get_format (void *img_addr);
|
||||
int genimg_has_config (bootm_headers_t *images);
|
||||
ulong genimg_get_image (ulong img_addr);
|
||||
|
||||
int boot_get_ramdisk (int argc, char *argv[], bootm_headers_t *images,
|
||||
uint8_t arch, ulong *rd_start, ulong *rd_end);
|
||||
|
||||
#if defined(CONFIG_PPC) || defined(CONFIG_M68K)
|
||||
int boot_ramdisk_high (struct lmb *lmb, ulong rd_data, ulong rd_len,
|
||||
ulong *initrd_start, ulong *initrd_end);
|
||||
|
||||
int boot_get_cmdline (struct lmb *lmb, ulong *cmd_start, ulong *cmd_end,
|
||||
ulong bootmap_base);
|
||||
int boot_get_kbd (struct lmb *lmb, bd_t **kbd, ulong bootmap_base);
|
||||
#endif /* CONFIG_PPC || CONFIG_M68K */
|
||||
#endif /* !USE_HOSTCC */
|
||||
|
||||
/*******************************************************************/
|
||||
/* Legacy format specific code (prefixed with image_) */
|
||||
/*******************************************************************/
|
||||
static inline uint32_t image_get_header_size (void)
|
||||
{
|
||||
return (sizeof (image_header_t));
|
||||
}
|
||||
|
||||
#define image_get_hdr_l(f) \
|
||||
static inline uint32_t image_get_##f(image_header_t *hdr) \
|
||||
{ \
|
||||
return uimage_to_cpu (hdr->ih_##f); \
|
||||
}
|
||||
image_get_hdr_l (magic);
|
||||
image_get_hdr_l (hcrc);
|
||||
image_get_hdr_l (time);
|
||||
image_get_hdr_l (size);
|
||||
image_get_hdr_l (load);
|
||||
image_get_hdr_l (ep);
|
||||
image_get_hdr_l (dcrc);
|
||||
|
||||
#define image_get_hdr_b(f) \
|
||||
static inline uint8_t image_get_##f(image_header_t *hdr) \
|
||||
{ \
|
||||
return hdr->ih_##f; \
|
||||
}
|
||||
image_get_hdr_b (os);
|
||||
image_get_hdr_b (arch);
|
||||
image_get_hdr_b (type);
|
||||
image_get_hdr_b (comp);
|
||||
|
||||
static inline char *image_get_name (image_header_t *hdr)
|
||||
{
|
||||
return (char *)hdr->ih_name;
|
||||
}
|
||||
|
||||
static inline uint32_t image_get_data_size (image_header_t *hdr)
|
||||
{
|
||||
return image_get_size (hdr);
|
||||
}
|
||||
|
||||
/**
|
||||
* image_get_data - get image payload start address
|
||||
* @hdr: image header
|
||||
*
|
||||
* image_get_data() returns address of the image payload. For single
|
||||
* component images it is image data start. For multi component
|
||||
* images it points to the null terminated table of sub-images sizes.
|
||||
*
|
||||
* returns:
|
||||
* image payload data start address
|
||||
*/
|
||||
static inline ulong image_get_data (image_header_t *hdr)
|
||||
{
|
||||
return ((ulong)hdr + image_get_header_size ());
|
||||
}
|
||||
|
||||
static inline uint32_t image_get_image_size (image_header_t *hdr)
|
||||
{
|
||||
return (image_get_size (hdr) + image_get_header_size ());
|
||||
}
|
||||
static inline ulong image_get_image_end (image_header_t *hdr)
|
||||
{
|
||||
return ((ulong)hdr + image_get_image_size (hdr));
|
||||
}
|
||||
|
||||
#define image_set_hdr_l(f) \
|
||||
static inline void image_set_##f(image_header_t *hdr, uint32_t val) \
|
||||
{ \
|
||||
hdr->ih_##f = cpu_to_uimage (val); \
|
||||
}
|
||||
image_set_hdr_l (magic);
|
||||
image_set_hdr_l (hcrc);
|
||||
image_set_hdr_l (time);
|
||||
image_set_hdr_l (size);
|
||||
image_set_hdr_l (load);
|
||||
image_set_hdr_l (ep);
|
||||
image_set_hdr_l (dcrc);
|
||||
|
||||
#define image_set_hdr_b(f) \
|
||||
static inline void image_set_##f(image_header_t *hdr, uint8_t val) \
|
||||
{ \
|
||||
hdr->ih_##f = val; \
|
||||
}
|
||||
image_set_hdr_b (os);
|
||||
image_set_hdr_b (arch);
|
||||
image_set_hdr_b (type);
|
||||
image_set_hdr_b (comp);
|
||||
|
||||
static inline void image_set_name (image_header_t *hdr, const char *name)
|
||||
{
|
||||
strncpy (image_get_name (hdr), name, IH_NMLEN);
|
||||
}
|
||||
|
||||
int image_check_hcrc (image_header_t *hdr);
|
||||
int image_check_dcrc (image_header_t *hdr);
|
||||
#ifndef USE_HOSTCC
|
||||
int image_check_dcrc_wd (image_header_t *hdr, ulong chunksize);
|
||||
int getenv_verify (void);
|
||||
int getenv_autostart (void);
|
||||
ulong getenv_bootm_low(void);
|
||||
ulong getenv_bootm_size(void);
|
||||
void memmove_wd (void *to, void *from, size_t len, ulong chunksz);
|
||||
#endif
|
||||
|
||||
static inline int image_check_magic (image_header_t *hdr)
|
||||
{
|
||||
return (image_get_magic (hdr) == IH_MAGIC);
|
||||
}
|
||||
static inline int image_check_type (image_header_t *hdr, uint8_t type)
|
||||
{
|
||||
return (image_get_type (hdr) == type);
|
||||
}
|
||||
static inline int image_check_arch (image_header_t *hdr, uint8_t arch)
|
||||
{
|
||||
return (image_get_arch (hdr) == arch);
|
||||
}
|
||||
static inline int image_check_os (image_header_t *hdr, uint8_t os)
|
||||
{
|
||||
return (image_get_os (hdr) == os);
|
||||
}
|
||||
|
||||
ulong image_multi_count (image_header_t *hdr);
|
||||
void image_multi_getimg (image_header_t *hdr, ulong idx,
|
||||
ulong *data, ulong *len);
|
||||
|
||||
inline void image_print_contents (image_header_t *hdr);
|
||||
inline void image_print_contents_noindent (image_header_t *hdr);
|
||||
|
||||
#ifndef USE_HOSTCC
|
||||
static inline int image_check_target_arch (image_header_t *hdr)
|
||||
{
|
||||
#if defined(__ARM__)
|
||||
if (!image_check_arch (hdr, IH_ARCH_ARM))
|
||||
#elif defined(__avr32__)
|
||||
if (!image_check_arch (hdr, IH_ARCH_AVR32))
|
||||
#elif defined(__bfin__)
|
||||
if (!image_check_arch (hdr, IH_ARCH_BLACKFIN))
|
||||
#elif defined(__I386__)
|
||||
if (!image_check_arch (hdr, IH_ARCH_I386))
|
||||
#elif defined(__M68K__)
|
||||
if (!image_check_arch (hdr, IH_ARCH_M68K))
|
||||
#elif defined(__microblaze__)
|
||||
if (!image_check_arch (hdr, IH_ARCH_MICROBLAZE))
|
||||
#elif defined(__mips__)
|
||||
if (!image_check_arch (hdr, IH_ARCH_MIPS))
|
||||
#elif defined(__nios__)
|
||||
if (!image_check_arch (hdr, IH_ARCH_NIOS))
|
||||
#elif defined(__nios2__)
|
||||
if (!image_check_arch (hdr, IH_ARCH_NIOS2))
|
||||
#elif defined(__PPC__)
|
||||
if (!image_check_arch (hdr, IH_ARCH_PPC))
|
||||
#elif defined(__sh__)
|
||||
if (!image_check_arch (hdr, IH_ARCH_SH))
|
||||
#else
|
||||
# error Unknown CPU type
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif /* USE_HOSTCC */
|
||||
|
||||
/*******************************************************************/
|
||||
/* New uImage format specific code (prefixed with fit_) */
|
||||
/*******************************************************************/
|
||||
#if defined(CONFIG_FIT)
|
||||
|
||||
#define FIT_IMAGES_PATH "/images"
|
||||
#define FIT_CONFS_PATH "/configurations"
|
||||
|
||||
/* hash node */
|
||||
#define FIT_HASH_NODENAME "hash"
|
||||
#define FIT_ALGO_PROP "algo"
|
||||
#define FIT_VALUE_PROP "value"
|
||||
|
||||
/* image node */
|
||||
#define FIT_DATA_PROP "data"
|
||||
#define FIT_TIMESTAMP_PROP "timestamp"
|
||||
#define FIT_DESC_PROP "description"
|
||||
#define FIT_ARCH_PROP "arch"
|
||||
#define FIT_TYPE_PROP "type"
|
||||
#define FIT_OS_PROP "os"
|
||||
#define FIT_COMP_PROP "compression"
|
||||
#define FIT_ENTRY_PROP "entry"
|
||||
#define FIT_LOAD_PROP "load"
|
||||
|
||||
/* configuration node */
|
||||
#define FIT_KERNEL_PROP "kernel"
|
||||
#define FIT_RAMDISK_PROP "ramdisk"
|
||||
#define FIT_FDT_PROP "fdt"
|
||||
#define FIT_DEFAULT_PROP "default"
|
||||
|
||||
#define FIT_MAX_HASH_LEN 20 /* max(crc32_len(4), sha1_len(20)) */
|
||||
|
||||
/* cmdline argument format parsing */
|
||||
inline int fit_parse_conf (const char *spec, ulong addr_curr,
|
||||
ulong *addr, const char **conf_name);
|
||||
inline int fit_parse_subimage (const char *spec, ulong addr_curr,
|
||||
ulong *addr, const char **image_name);
|
||||
|
||||
inline void fit_print_contents (const void *fit);
|
||||
inline void fit_print_contents_noindent (const void *fit);
|
||||
void fit_image_print (const void *fit, int noffset, const char *p);
|
||||
void fit_image_print_hash (const void *fit, int noffset, const char *p);
|
||||
|
||||
/**
|
||||
* fit_get_end - get FIT image size
|
||||
* @fit: pointer to the FIT format image header
|
||||
*
|
||||
* returns:
|
||||
* size of the FIT image (blob) in memory
|
||||
*/
|
||||
static inline ulong fit_get_size (const void *fit)
|
||||
{
|
||||
return fdt_totalsize (fit);
|
||||
}
|
||||
|
||||
/**
|
||||
* fit_get_end - get FIT image end
|
||||
* @fit: pointer to the FIT format image header
|
||||
*
|
||||
* returns:
|
||||
* end address of the FIT image (blob) in memory
|
||||
*/
|
||||
static inline ulong fit_get_end (const void *fit)
|
||||
{
|
||||
return (ulong)fit + fdt_totalsize (fit);
|
||||
}
|
||||
|
||||
/**
|
||||
* fit_get_name - get FIT node name
|
||||
* @fit: pointer to the FIT format image header
|
||||
*
|
||||
* returns:
|
||||
* NULL, on error
|
||||
* pointer to node name, on success
|
||||
*/
|
||||
static inline const char *fit_get_name (const void *fit_hdr,
|
||||
int noffset, int *len)
|
||||
{
|
||||
return fdt_get_name (fit_hdr, noffset, len);
|
||||
}
|
||||
|
||||
int fit_get_desc (const void *fit, int noffset, char **desc);
|
||||
int fit_get_timestamp (const void *fit, int noffset, time_t *timestamp);
|
||||
|
||||
int fit_image_get_node (const void *fit, const char *image_uname);
|
||||
int fit_image_get_os (const void *fit, int noffset, uint8_t *os);
|
||||
int fit_image_get_arch (const void *fit, int noffset, uint8_t *arch);
|
||||
int fit_image_get_type (const void *fit, int noffset, uint8_t *type);
|
||||
int fit_image_get_comp (const void *fit, int noffset, uint8_t *comp);
|
||||
int fit_image_get_load (const void *fit, int noffset, ulong *load);
|
||||
int fit_image_get_entry (const void *fit, int noffset, ulong *entry);
|
||||
int fit_image_get_data (const void *fit, int noffset,
|
||||
const void **data, size_t *size);
|
||||
|
||||
int fit_image_hash_get_algo (const void *fit, int noffset, char **algo);
|
||||
int fit_image_hash_get_value (const void *fit, int noffset, uint8_t **value,
|
||||
int *value_len);
|
||||
|
||||
int fit_set_timestamp (void *fit, int noffset, time_t timestamp);
|
||||
int fit_set_hashes (void *fit);
|
||||
int fit_image_set_hashes (void *fit, int image_noffset);
|
||||
int fit_image_hash_set_value (void *fit, int noffset, uint8_t *value,
|
||||
int value_len);
|
||||
|
||||
int fit_image_check_hashes (const void *fit, int noffset);
|
||||
int fit_image_check_os (const void *fit, int noffset, uint8_t os);
|
||||
int fit_image_check_arch (const void *fit, int noffset, uint8_t arch);
|
||||
int fit_image_check_type (const void *fit, int noffset, uint8_t type);
|
||||
int fit_image_check_comp (const void *fit, int noffset, uint8_t comp);
|
||||
int fit_check_format (const void *fit);
|
||||
|
||||
int fit_conf_get_node (const void *fit, const char *conf_uname);
|
||||
int fit_conf_get_kernel_node (const void *fit, int noffset);
|
||||
int fit_conf_get_ramdisk_node (const void *fit, int noffset);
|
||||
int fit_conf_get_fdt_node (const void *fit, int noffset);
|
||||
|
||||
void fit_conf_print (const void *fit, int noffset, const char *p);
|
||||
|
||||
#ifndef USE_HOSTCC
|
||||
static inline int fit_image_check_target_arch (const void *fdt, int node)
|
||||
{
|
||||
#if defined(__ARM__)
|
||||
if (!fit_image_check_arch (fdt, node, IH_ARCH_ARM))
|
||||
#elif defined(__avr32__)
|
||||
if (!fit_image_check_arch (fdt, node, IH_ARCH_AVR32))
|
||||
#elif defined(__bfin__)
|
||||
if (!fit_image_check_arch (fdt, node, IH_ARCH_BLACKFIN))
|
||||
#elif defined(__I386__)
|
||||
if (!fit_image_check_arch (fdt, node, IH_ARCH_I386))
|
||||
#elif defined(__M68K__)
|
||||
if (!fit_image_check_arch (fdt, node, IH_ARCH_M68K))
|
||||
#elif defined(__microblaze__)
|
||||
if (!fit_image_check_arch (fdt, node, IH_ARCH_MICROBLAZE))
|
||||
#elif defined(__mips__)
|
||||
if (!fit_image_check_arch (fdt, node, IH_ARCH_MIPS))
|
||||
#elif defined(__nios__)
|
||||
if (!fit_image_check_arch (fdt, node, IH_ARCH_NIOS))
|
||||
#elif defined(__nios2__)
|
||||
if (!fit_image_check_arch (fdt, node, IH_ARCH_NIOS2))
|
||||
#elif defined(__PPC__)
|
||||
if (!fit_image_check_arch (fdt, node, IH_ARCH_PPC))
|
||||
#elif defined(__sh__)
|
||||
if (!fit_image_check_arch (fdt, node, IH_ARCH_SH))
|
||||
#else
|
||||
# error Unknown CPU type
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif /* USE_HOSTCC */
|
||||
|
||||
#ifdef CONFIG_FIT_VERBOSE
|
||||
#define fit_unsupported(msg) printf ("! %s:%d " \
|
||||
"FIT images not supported for '%s'\n", \
|
||||
__FILE__, __LINE__, (msg))
|
||||
|
||||
#define fit_unsupported_reset(msg) printf ("! %s:%d " \
|
||||
"FIT images not supported for '%s' " \
|
||||
"- must reset board to recover!\n", \
|
||||
__FILE__, __LINE__, (msg))
|
||||
#else
|
||||
#define fit_unsupported(msg)
|
||||
#define fit_unsupported_reset(msg)
|
||||
#endif /* CONFIG_FIT_VERBOSE */
|
||||
#endif /* CONFIG_FIT */
|
||||
|
||||
#endif /* __IMAGE_H__ */
|
382
qiboot/include/linux-mmc-protocol.h
Normal file
382
qiboot/include/linux-mmc-protocol.h
Normal file
@ -0,0 +1,382 @@
|
||||
/*
|
||||
* Header for MultiMediaCard (MMC)
|
||||
*
|
||||
* Copyright 2002 Hewlett-Packard Company
|
||||
*
|
||||
* Use consistent with the GNU GPL is permitted,
|
||||
* provided that this copyright notice is
|
||||
* preserved in its entirety in all copies and derived works.
|
||||
*
|
||||
* HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
|
||||
* AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
|
||||
* FITNESS FOR ANY PARTICULAR PURPOSE.
|
||||
*
|
||||
* Many thanks to Alessandro Rubini and Jonathan Corbet!
|
||||
*
|
||||
* Based strongly on code by:
|
||||
*
|
||||
* Author: Yong-iL Joh <tolkien@mizi.com>
|
||||
* Date : $Date: 2006/12/06 02:50:52 $
|
||||
*
|
||||
* Author: Andrew Christian
|
||||
* 15 May 2002
|
||||
*/
|
||||
|
||||
#ifndef MMC_MMC_PROTOCOL_H
|
||||
#define MMC_MMC_PROTOCOL_H
|
||||
|
||||
#ifdef CONFIG_SUPPORT_MMC_PLUS
|
||||
/* Standard MMC commands (4.2) type argument response */
|
||||
#else
|
||||
/* Standard MMC commands (3.1) type argument response */
|
||||
#endif
|
||||
/* class 1 */
|
||||
#define MMC_GO_IDLE_STATE 0 /* bc */
|
||||
#define MMC_SEND_OP_COND 1 /* bcr [31:0] OCR R3 */
|
||||
#define MMC_ALL_SEND_CID 2 /* bcr R2 */
|
||||
#define MMC_SET_RELATIVE_ADDR 3 /* ac [31:16] RCA R1 */
|
||||
#define MMC_SET_DSR 4 /* bc [31:16] RCA */
|
||||
#define MMC_SWITCH 6 /* ac R1b */
|
||||
#define MMC_SELECT_CARD 7 /* ac [31:16] RCA R1 */
|
||||
#define MMC_SEND_EXT_CSD 8 /* adtc R1 */
|
||||
#define MMC_SEND_CSD 9 /* ac [31:16] RCA R2 */
|
||||
#define MMC_SEND_CID 10 /* ac [31:16] RCA R2 */
|
||||
#define MMC_READ_DAT_UNTIL_STOP 11 /* adtc [31:0] dadr R1 */
|
||||
#define MMC_STOP_TRANSMISSION 12 /* ac R1b */
|
||||
#define MMC_SEND_STATUS 13 /* ac [31:16] RCA R1 */
|
||||
#define MMC_BUSTEST_R 14 /* adtc R1 */
|
||||
#define MMC_GO_INACTIVE_STATE 15 /* ac [31:16] RCA */
|
||||
#define MMC_BUSTEST_W 19 /* adtc R1 */
|
||||
|
||||
/* class 2 */
|
||||
#define MMC_SET_BLOCKLEN 16 /* ac [31:0] block len R1 */
|
||||
#define MMC_READ_SINGLE_BLOCK 17 /* adtc [31:0] data addr R1 */
|
||||
#define MMC_READ_MULTIPLE_BLOCK 18 /* adtc [31:0] data addr R1 */
|
||||
|
||||
/* class 3 */
|
||||
#define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1 */
|
||||
|
||||
/* class 4 */
|
||||
#define MMC_SET_BLOCK_COUNT 23 /* adtc [31:0] data addr R1 */
|
||||
#define MMC_WRITE_BLOCK 24 /* adtc [31:0] data addr R1 */
|
||||
#define MMC_WRITE_MULTIPLE_BLOCK 25 /* adtc R1 */
|
||||
#define MMC_PROGRAM_CID 26 /* adtc R1 */
|
||||
#define MMC_PROGRAM_CSD 27 /* adtc R1 */
|
||||
|
||||
/* class 6 */
|
||||
#define MMC_SET_WRITE_PROT 28 /* ac [31:0] data addr R1b */
|
||||
#define MMC_CLR_WRITE_PROT 29 /* ac [31:0] data addr R1b */
|
||||
#define MMC_SEND_WRITE_PROT 30 /* adtc [31:0] wpdata addr R1 */
|
||||
|
||||
/* class 5 */
|
||||
#define MMC_ERASE_GROUP_START 35 /* ac [31:0] data addr R1 */
|
||||
#define MMC_ERASE_GROUP_END 36 /* ac [31:0] data addr R1 */
|
||||
#define MMC_ERASE 38 /* ac R1b */
|
||||
|
||||
/* class 9 */
|
||||
#define MMC_FAST_IO 39 /* ac <Complex> R4 */
|
||||
#define MMC_GO_IRQ_STATE 40 /* bcr R5 */
|
||||
|
||||
/* class 7 */
|
||||
#define MMC_LOCK_UNLOCK 42 /* adtc R1b */
|
||||
|
||||
/* class 8 */
|
||||
#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */
|
||||
#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */
|
||||
|
||||
/* SD commands type argument response */
|
||||
/* class 8 */
|
||||
/* This is basically the same command as for MMC with some quirks. */
|
||||
#define SD_SEND_RELATIVE_ADDR 3 /* ac R6 */
|
||||
|
||||
/* Application commands */
|
||||
#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */
|
||||
#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */
|
||||
#define SD_APP_SEND_SCR 51 /* adtc R1 */
|
||||
|
||||
/*
|
||||
MMC status in R1
|
||||
Type
|
||||
e : error bit
|
||||
s : status bit
|
||||
r : detected and set for the actual command response
|
||||
x : detected and set during command execution. the host must poll
|
||||
the card by sending status command in order to read these bits.
|
||||
Clear condition
|
||||
a : according to the card state
|
||||
b : always related to the previous command. Reception of
|
||||
a valid command will clear it (with a delay of one command)
|
||||
c : clear by read
|
||||
*/
|
||||
|
||||
#define R1_OUT_OF_RANGE (1 << 31) /* er, c */
|
||||
#define R1_ADDRESS_ERROR (1 << 30) /* erx, c */
|
||||
#define R1_BLOCK_LEN_ERROR (1 << 29) /* er, c */
|
||||
#define R1_ERASE_SEQ_ERROR (1 << 28) /* er, c */
|
||||
#define R1_ERASE_PARAM (1 << 27) /* ex, c */
|
||||
#define R1_WP_VIOLATION (1 << 26) /* erx, c */
|
||||
#define R1_CARD_IS_LOCKED (1 << 25) /* sx, a */
|
||||
#define R1_LOCK_UNLOCK_FAILED (1 << 24) /* erx, c */
|
||||
#define R1_COM_CRC_ERROR (1 << 23) /* er, b */
|
||||
#define R1_ILLEGAL_COMMAND (1 << 22) /* er, b */
|
||||
#define R1_CARD_ECC_FAILED (1 << 21) /* ex, c */
|
||||
#define R1_CC_ERROR (1 << 20) /* erx, c */
|
||||
#define R1_ERROR (1 << 19) /* erx, c */
|
||||
#define R1_UNDERRUN (1 << 18) /* ex, c */
|
||||
#define R1_OVERRUN (1 << 17) /* ex, c */
|
||||
#define R1_CID_CSD_OVERWRITE (1 << 16) /* erx, c, CID/CSD overwrite */
|
||||
#define R1_WP_ERASE_SKIP (1 << 15) /* sx, c */
|
||||
#define R1_CARD_ECC_DISABLED (1 << 14) /* sx, a */
|
||||
#define R1_ERASE_RESET (1 << 13) /* sr, c */
|
||||
#define R1_STATUS(x) (x & 0xFFFFE000)
|
||||
#define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */
|
||||
#define R1_READY_FOR_DATA (1 << 8) /* sx, a */
|
||||
#define R1_APP_CMD (1 << 5) /* sr, c */
|
||||
|
||||
/*
|
||||
MMC CURRENT_STATE in R1 [12:9]
|
||||
*/
|
||||
#define STATE_IDLE (0x0 << 9) /* 0 */
|
||||
#define STATE_READY (0x1 << 9) /* 1 */
|
||||
#define STATE_IDENT (0x2 << 9) /* 2 */
|
||||
#define STATE_STBY (0x3 << 9) /* 3 */
|
||||
#define STATE_TRAN (0x4 << 9) /* 4 */
|
||||
#define STATE_DATA (0x5 << 9) /* 5 */
|
||||
#define STATE_RCV (0x6 << 9) /* 6 */
|
||||
#define STATE_PRG (0x7 << 9) /* 7 */
|
||||
#define STATE_DIS (0x8 << 9) /* 8 */
|
||||
#define STATE_BTST (0x9 << 9) /* 9 */
|
||||
|
||||
/* These are unpacked versions of the actual responses */
|
||||
|
||||
struct _mmc_csd {
|
||||
u8 csd_structure;
|
||||
u8 spec_vers;
|
||||
u8 taac;
|
||||
u8 nsac;
|
||||
u8 tran_speed;
|
||||
u16 ccc;
|
||||
u8 read_bl_len;
|
||||
u8 read_bl_partial;
|
||||
u8 write_blk_misalign;
|
||||
u8 read_blk_misalign;
|
||||
u8 dsr_imp;
|
||||
u16 c_size;
|
||||
u8 vdd_r_curr_min;
|
||||
u8 vdd_r_curr_max;
|
||||
u8 vdd_w_curr_min;
|
||||
u8 vdd_w_curr_max;
|
||||
u8 c_size_mult;
|
||||
union {
|
||||
struct { /* MMC system specification version 3.1 */
|
||||
u8 erase_grp_size;
|
||||
u8 erase_grp_mult;
|
||||
} v31;
|
||||
struct { /* MMC system specification version 2.2 */
|
||||
u8 sector_size;
|
||||
u8 erase_grp_size;
|
||||
} v22;
|
||||
} erase;
|
||||
u8 wp_grp_size;
|
||||
u8 wp_grp_enable;
|
||||
u8 default_ecc;
|
||||
u8 r2w_factor;
|
||||
u8 write_bl_len;
|
||||
u8 write_bl_partial;
|
||||
u8 file_format_grp;
|
||||
u8 copy;
|
||||
u8 perm_write_protect;
|
||||
u8 tmp_write_protect;
|
||||
u8 file_format;
|
||||
u8 ecc;
|
||||
};
|
||||
|
||||
struct _mmc_ext_csd {
|
||||
u8 s_cmd_set;
|
||||
u32 sec_count;
|
||||
u8 MIN_PERF_W_8_52;
|
||||
u8 MIN_PERF_R_8_52;
|
||||
u8 MIN_PERF_W_8_26_4_52;
|
||||
u8 MIN_PERF_R_8_26_4_52;
|
||||
u8 MIN_PERF_W_4_26;
|
||||
u8 MIN_PERF_R_4_26;
|
||||
u8 PWR_CL_26_360;
|
||||
u8 PWR_CL_52_360;
|
||||
u8 PWR_CL_26_195;
|
||||
u8 PWR_CL_52_195;
|
||||
u8 card_type;
|
||||
u8 csd_structure;
|
||||
u8 ext_csd_rev;
|
||||
u8 cmd_set;
|
||||
u8 cmd_set_rev;
|
||||
u8 power_class;
|
||||
u8 hs_timing;
|
||||
u8 bus_width;
|
||||
};
|
||||
|
||||
#define MMC_VDD_145_150 0x00000001 /* VDD voltage 1.45 - 1.50 */
|
||||
#define MMC_VDD_150_155 0x00000002 /* VDD voltage 1.50 - 1.55 */
|
||||
#define MMC_VDD_155_160 0x00000004 /* VDD voltage 1.55 - 1.60 */
|
||||
#define MMC_VDD_160_165 0x00000008 /* VDD voltage 1.60 - 1.65 */
|
||||
#define MMC_VDD_165_170 0x00000010 /* VDD voltage 1.65 - 1.70 */
|
||||
#define MMC_VDD_17_18 0x00000020 /* VDD voltage 1.7 - 1.8 */
|
||||
#define MMC_VDD_18_19 0x00000040 /* VDD voltage 1.8 - 1.9 */
|
||||
#define MMC_VDD_19_20 0x00000080 /* VDD voltage 1.9 - 2.0 */
|
||||
#define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */
|
||||
#define MMC_VDD_21_22 0x00000200 /* VDD voltage 2.1 ~ 2.2 */
|
||||
#define MMC_VDD_22_23 0x00000400 /* VDD voltage 2.2 ~ 2.3 */
|
||||
#define MMC_VDD_23_24 0x00000800 /* VDD voltage 2.3 ~ 2.4 */
|
||||
#define MMC_VDD_24_25 0x00001000 /* VDD voltage 2.4 ~ 2.5 */
|
||||
#define MMC_VDD_25_26 0x00002000 /* VDD voltage 2.5 ~ 2.6 */
|
||||
#define MMC_VDD_26_27 0x00004000 /* VDD voltage 2.6 ~ 2.7 */
|
||||
#define MMC_VDD_27_28 0x00008000 /* VDD voltage 2.7 ~ 2.8 */
|
||||
#define MMC_VDD_28_29 0x00010000 /* VDD voltage 2.8 ~ 2.9 */
|
||||
#define MMC_VDD_29_30 0x00020000 /* VDD voltage 2.9 ~ 3.0 */
|
||||
#define MMC_VDD_30_31 0x00040000 /* VDD voltage 3.0 ~ 3.1 */
|
||||
#define MMC_VDD_31_32 0x00080000 /* VDD voltage 3.1 ~ 3.2 */
|
||||
#define MMC_VDD_32_33 0x00100000 /* VDD voltage 3.2 ~ 3.3 */
|
||||
#define MMC_VDD_33_34 0x00200000 /* VDD voltage 3.3 ~ 3.4 */
|
||||
#define MMC_VDD_34_35 0x00400000 /* VDD voltage 3.4 ~ 3.5 */
|
||||
#define MMC_VDD_35_36 0x00800000 /* VDD voltage 3.5 ~ 3.6 */
|
||||
#define MMC_CARD_BUSY 0x80000000 /* Card Power up status bit */
|
||||
|
||||
/*
|
||||
* Card Command Classes (CCC)
|
||||
*/
|
||||
#define CCC_BASIC (1<<0) /* (0) Basic protocol functions */
|
||||
/* (CMD0,1,2,3,4,7,9,10,12,13,15) */
|
||||
#define CCC_STREAM_READ (1<<1) /* (1) Stream read commands */
|
||||
/* (CMD11) */
|
||||
#define CCC_BLOCK_READ (1<<2) /* (2) Block read commands */
|
||||
/* (CMD16,17,18) */
|
||||
#define CCC_STREAM_WRITE (1<<3) /* (3) Stream write commands */
|
||||
/* (CMD20) */
|
||||
#define CCC_BLOCK_WRITE (1<<4) /* (4) Block write commands */
|
||||
/* (CMD16,24,25,26,27) */
|
||||
#define CCC_ERASE (1<<5) /* (5) Ability to erase blocks */
|
||||
/* (CMD32,33,34,35,36,37,38,39) */
|
||||
#define CCC_WRITE_PROT (1<<6) /* (6) Able to write protect blocks */
|
||||
/* (CMD28,29,30) */
|
||||
#define CCC_LOCK_CARD (1<<7) /* (7) Able to lock down card */
|
||||
/* (CMD16,CMD42) */
|
||||
#define CCC_APP_SPEC (1<<8) /* (8) Application specific */
|
||||
/* (CMD55,56,57,ACMD*) */
|
||||
#define CCC_IO_MODE (1<<9) /* (9) I/O mode */
|
||||
/* (CMD5,39,40,52,53) */
|
||||
#define CCC_SWITCH (1<<10) /* (10) High speed switch */
|
||||
/* (CMD6,34,35,36,37,50) */
|
||||
/* (11) Reserved */
|
||||
/* (CMD?) */
|
||||
|
||||
/*
|
||||
* CSD field definitions
|
||||
*/
|
||||
|
||||
#define CSD_STRUCT_VER_1_0 0 /* Valid for system specification 1.0 - 1.2 */
|
||||
#define CSD_STRUCT_VER_1_1 1 /* Valid for system specification 1.4 - 2.2 */
|
||||
#define CSD_STRUCT_VER_1_2 2 /* Valid for system specification 3.1 */
|
||||
|
||||
#define CSD_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.2 */
|
||||
#define CSD_SPEC_VER_1 1 /* Implements system specification 1.4 */
|
||||
#define CSD_SPEC_VER_2 2 /* Implements system specification 2.0 - 2.2 */
|
||||
#define CSD_SPEC_VER_3 3 /* Implements system specification 3.1 */
|
||||
#define CSD_SPEC_VER_4 4 /* Implements system specification 4.0 ~ 4.2 */
|
||||
|
||||
/*
|
||||
* SD bus widths
|
||||
*/
|
||||
#define SD_BUS_WIDTH_1 0
|
||||
#define SD_BUS_WIDTH_4 2
|
||||
|
||||
/*
|
||||
* EXT_CSD field definitions
|
||||
*/
|
||||
|
||||
/*
|
||||
* S_CMD_SET
|
||||
*/
|
||||
|
||||
#define STANDARD_MMC 0 /* Standard MMC */
|
||||
#define SECURE_MMC 1 /* Secure MMC */
|
||||
#define CPS_MMC 2 /* Content Protection Secure MMC */
|
||||
#define SECURE_MMC_2 3 /* Secure MMC 2.0 */
|
||||
#define ATA_MMC 4 /* ATA on MMC */
|
||||
|
||||
/*
|
||||
* MIN_PERF_a_b_ff
|
||||
*/
|
||||
#define NO_CLASS 0x0 /* For cards not reaching the 2.4MB/s minimum value */
|
||||
#define CLASS_A 0x08 /* Class A */
|
||||
#define CLASS_B 0x0A /* Class B */
|
||||
#define CLASS_C 0x0F /* Class C */
|
||||
#define CLASS_D 0x14 /* Class D */
|
||||
#define CLASS_E 0x1E /* Class E */
|
||||
#define CLASS_F 0x28 /* Class F */
|
||||
#define CLASS_G 0x32 /* Class G */
|
||||
#define CLASS_H 0x3c /* Class H */
|
||||
#define CLASS_J 0x46 /* Class J */
|
||||
#define CLASS_K 0x50 /* Class E */
|
||||
#define CLASS_M 0x64 /* Class M */
|
||||
#define CLASS_O 0x78 /* Class O */
|
||||
#define CLASS_R 0x8c /* Class R */
|
||||
#define CLASS_T 0xa0 /* Class T */
|
||||
|
||||
/*
|
||||
* CARD_TYPE
|
||||
*/
|
||||
|
||||
#define MMCPLUS_26MHZ (1<<0)
|
||||
#define MMCPLUS_52MHZ (1<<1)
|
||||
|
||||
/*
|
||||
* EXT_CSD_REV
|
||||
*/
|
||||
|
||||
#define EXT_CSD_REV_1_0 0
|
||||
#define EXT_CSD_REV_1_1 1
|
||||
#define EXT_CSD_REV_1_2 2
|
||||
|
||||
/*
|
||||
* HS_TIMING
|
||||
*/
|
||||
#define HS_TIMING_LOW 0
|
||||
#define HS_TIMING_HIGH 1
|
||||
|
||||
/*
|
||||
* BUS_WIDTH
|
||||
*/
|
||||
#define MMCPLUS_BUS_WIDTH_1 0
|
||||
#define MMCPLUS_BUS_WIDTH_4 1
|
||||
#define MMCPLUS_BUS_WIDTH_8 2
|
||||
|
||||
|
||||
/*
|
||||
* ERASED_MEM_CONT
|
||||
*/
|
||||
|
||||
#define ERASED_MEM_CONT_0 0
|
||||
#define ERASED_MEM_CONT_1 1
|
||||
|
||||
/*
|
||||
* Argument for CMD6
|
||||
*/
|
||||
|
||||
/*
|
||||
* EXT_CSD Access Modes
|
||||
*/
|
||||
|
||||
#define EXT_CSD_COMMAND_SET 0
|
||||
#define EXT_CSD_SET_BITS 1
|
||||
#define EXT_CSD_CLEAR_BITS 2
|
||||
#define EXT_CSD_WRITE_BYTE 3
|
||||
|
||||
/*
|
||||
* EXT_CSD Argument Byte
|
||||
*/
|
||||
|
||||
#define EXT_CSD_POWER_CLASS 187
|
||||
#define EXT_CSD_BUS_WIDTH 183
|
||||
#define EXT_CSD_HS_TIMING 185
|
||||
|
||||
#endif /* MMC_MMC_PROTOCOL_H */
|
||||
|
120
qiboot/include/linux-mmc.h
Normal file
120
qiboot/include/linux-mmc.h
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* linux/include/linux/mmc/mmc.h
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef MMC_H
|
||||
#define MMC_H
|
||||
|
||||
/* removed by scsuh */
|
||||
#if 0
|
||||
#include <linux/list.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
struct request;
|
||||
struct mmc_data;
|
||||
struct mmc_request;
|
||||
#endif
|
||||
|
||||
#define MMC_RSP_PRESENT (1 << 0)
|
||||
#define MMC_RSP_136 (1 << 1) /* 136 bit response */
|
||||
#define MMC_RSP_CRC (1 << 2) /* expect valid crc */
|
||||
#define MMC_RSP_BUSY (1 << 3) /* card may send busy */
|
||||
#define MMC_RSP_OPCODE (1 << 4) /* response contains opcode */
|
||||
#define MMC_CMD_MASK (3 << 5) /* command type */
|
||||
#define MMC_CMD_AC (0 << 5)
|
||||
#define MMC_CMD_ADTC (1 << 5)
|
||||
#define MMC_CMD_BC (2 << 5)
|
||||
#define MMC_CMD_BCR (3 << 5)
|
||||
|
||||
/*
|
||||
* These are the response types, and correspond to valid bit
|
||||
* patterns of the above flags. One additional valid pattern
|
||||
* is all zeros, which means we don't expect a response.
|
||||
*/
|
||||
#define MMC_RSP_NONE (0)
|
||||
#define MMC_RSP_R1 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
|
||||
#define MMC_RSP_R1B (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE|MMC_RSP_BUSY)
|
||||
#define MMC_RSP_R2 (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC)
|
||||
#define MMC_RSP_R3 (MMC_RSP_PRESENT)
|
||||
#define MMC_RSP_R6 (MMC_RSP_PRESENT|MMC_RSP_CRC)
|
||||
|
||||
#define mmc_resp_type(cmd) ((cmd)->flags & (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC|MMC_RSP_BUSY|MMC_RSP_OPCODE))
|
||||
|
||||
/*
|
||||
* These are the command types.
|
||||
*/
|
||||
#define mmc_cmd_type(cmd) ((cmd)->flags & MMC_CMD_MASK)
|
||||
|
||||
#define MMC_ERR_NONE 0
|
||||
#define MMC_ERR_TIMEOUT 1
|
||||
#define MMC_ERR_BADCRC 2
|
||||
#define MMC_ERR_FIFO 3
|
||||
#define MMC_ERR_FAILED 4
|
||||
#define MMC_ERR_INVALID 5
|
||||
|
||||
struct mmc_command {
|
||||
u32 opcode;
|
||||
u32 arg;
|
||||
u32 resp[4];
|
||||
unsigned int flags; /* expected response type */
|
||||
struct mmc_data *data; /* data segment associated with cmd */
|
||||
struct mmc_request *mrq; /* associated request */
|
||||
unsigned int retries; /* max number of retries */
|
||||
unsigned int error; /* command error */
|
||||
|
||||
};
|
||||
|
||||
struct mmc_data {
|
||||
unsigned int timeout_ns; /* data timeout (in ns, max 80ms) */
|
||||
unsigned int timeout_clks; /* data timeout (in clocks) */
|
||||
unsigned int blksz_bits; /* data block size */
|
||||
unsigned int blksz; /* data block size */
|
||||
unsigned int blocks; /* number of blocks */
|
||||
unsigned int error; /* data error */
|
||||
unsigned int flags;
|
||||
|
||||
#define MMC_DATA_WRITE (1 << 8)
|
||||
#define MMC_DATA_READ (1 << 9)
|
||||
#define MMC_DATA_STREAM (1 << 10)
|
||||
#define MMC_DATA_MULTI (1 << 11)
|
||||
|
||||
unsigned int bytes_xfered;
|
||||
|
||||
struct mmc_command *stop; /* stop command */
|
||||
struct mmc_request *mrq; /* associated request */
|
||||
|
||||
unsigned int sg_len; /* size of scatter list */
|
||||
struct scatterlist *sg; /* I/O scatter list */
|
||||
};
|
||||
|
||||
struct mmc_request {
|
||||
struct mmc_command *cmd;
|
||||
struct mmc_data *data;
|
||||
struct mmc_command *stop;
|
||||
|
||||
void *done_data; /* completion data */
|
||||
void (*done)(struct mmc_request *);/* completion function */
|
||||
};
|
||||
|
||||
struct mmc_host;
|
||||
struct mmc_card;
|
||||
|
||||
extern int mmc_wait_for_req(struct mmc_host *, struct mmc_request *);
|
||||
extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int);
|
||||
extern int mmc_wait_for_app_cmd(struct mmc_host *, unsigned int,
|
||||
struct mmc_command *, int);
|
||||
|
||||
extern int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card);
|
||||
|
||||
static inline void mmc_claim_host(struct mmc_host *host)
|
||||
{
|
||||
__mmc_claim_host(host, (struct mmc_card *)-1);
|
||||
}
|
||||
|
||||
extern void mmc_release_host(struct mmc_host *host);
|
||||
|
||||
#endif
|
110
qiboot/include/mmc.h
Normal file
110
qiboot/include/mmc.h
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* linux/drivers/mmc/mmc_pxa.h
|
||||
*
|
||||
* Author: Vladimir Shebordaev, Igor Oblakov
|
||||
* Copyright: MontaVista Software Inc.
|
||||
*
|
||||
* $Id: mmc_pxa.h,v 0.3.1.6 2002/09/25 19:25:48 ted Exp ted $
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef __MMC_PXA_P_H__
|
||||
#define __MMC_PXA_P_H__
|
||||
|
||||
#define MMC_DEFAULT_RCA (1<<16)
|
||||
|
||||
#define MMC_BLOCK_SIZE 512
|
||||
#define MMC_CMD_RESET 0
|
||||
#define MMC_CMD_SEND_OP_COND 1
|
||||
#define MMC_CMD_ALL_SEND_CID 2
|
||||
#define MMC_CMD_SET_RCA 3
|
||||
#define MMC_CMD_SELECT_CARD 7
|
||||
#define MMC_CMD_SEND_CSD 9
|
||||
#define MMC_CMD_SEND_CID 10
|
||||
#define MMC_CMD_SEND_STATUS 13
|
||||
#define MMC_CMD_SET_BLOCKLEN 16
|
||||
#define MMC_CMD_READ_BLOCK 17
|
||||
#define MMC_CMD_RD_BLK_MULTI 18
|
||||
#define MMC_CMD_WRITE_BLOCK 24
|
||||
|
||||
#define MMC_MAX_BLOCK_SIZE 512
|
||||
|
||||
#define MMC_R1_IDLE_STATE 0x01
|
||||
#define MMC_R1_ERASE_STATE 0x02
|
||||
#define MMC_R1_ILLEGAL_CMD 0x04
|
||||
#define MMC_R1_COM_CRC_ERR 0x08
|
||||
#define MMC_R1_ERASE_SEQ_ERR 0x01
|
||||
#define MMC_R1_ADDR_ERR 0x02
|
||||
#define MMC_R1_PARAM_ERR 0x04
|
||||
|
||||
#define MMC_R1B_WP_ERASE_SKIP 0x0002
|
||||
#define MMC_R1B_ERR 0x0004
|
||||
#define MMC_R1B_CC_ERR 0x0008
|
||||
#define MMC_R1B_CARD_ECC_ERR 0x0010
|
||||
#define MMC_R1B_WP_VIOLATION 0x0020
|
||||
#define MMC_R1B_ERASE_PARAM 0x0040
|
||||
#define MMC_R1B_OOR 0x0080
|
||||
#define MMC_R1B_IDLE_STATE 0x0100
|
||||
#define MMC_R1B_ERASE_RESET 0x0200
|
||||
#define MMC_R1B_ILLEGAL_CMD 0x0400
|
||||
#define MMC_R1B_COM_CRC_ERR 0x0800
|
||||
#define MMC_R1B_ERASE_SEQ_ERR 0x1000
|
||||
#define MMC_R1B_ADDR_ERR 0x2000
|
||||
#define MMC_R1B_PARAM_ERR 0x4000
|
||||
|
||||
typedef struct mmc_cid
|
||||
{
|
||||
/* FIXME: BYTE_ORDER */
|
||||
u8 year:4,
|
||||
month:4;
|
||||
u8 sn[3];
|
||||
u8 fwrev:4,
|
||||
hwrev:4;
|
||||
u8 name[6];
|
||||
u8 id[3];
|
||||
} mmc_cid_t;
|
||||
|
||||
typedef struct mmc_csd
|
||||
{
|
||||
u8 ecc:2,
|
||||
file_format:2,
|
||||
tmp_write_protect:1,
|
||||
perm_write_protect:1,
|
||||
copy:1,
|
||||
file_format_grp:1;
|
||||
unsigned long long content_prot_app:1,
|
||||
rsvd3:4,
|
||||
write_bl_partial:1,
|
||||
write_bl_len:4,
|
||||
r2w_factor:3,
|
||||
default_ecc:2,
|
||||
wp_grp_enable:1,
|
||||
wp_grp_size:5,
|
||||
erase_grp_mult:5,
|
||||
erase_grp_size:5,
|
||||
c_size_mult1:3,
|
||||
vdd_w_curr_max:3,
|
||||
vdd_w_curr_min:3,
|
||||
vdd_r_curr_max:3,
|
||||
vdd_r_curr_min:3,
|
||||
c_size:12,
|
||||
rsvd2:2,
|
||||
dsr_imp:1,
|
||||
read_blk_misalign:1,
|
||||
write_blk_misalign:1,
|
||||
read_bl_partial:1;
|
||||
|
||||
u16 read_bl_len:4,
|
||||
ccc:12;
|
||||
u8 tran_speed;
|
||||
u8 nsac;
|
||||
u8 taac;
|
||||
u8 rsvd1:2,
|
||||
spec_vers:4,
|
||||
csd_structure:2;
|
||||
} mmc_csd_t;
|
||||
|
||||
|
||||
#endif /* __MMC_PXA_P_H__ */
|
30
qiboot/include/neo_gta01.h
Normal file
30
qiboot/include/neo_gta01.h
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
* Author: xiangfu liu <xiangfu@openmoko.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __CONFIG_H
|
||||
#define __CONFIG_H
|
||||
#ifndef __ASM_MODE__
|
||||
#include <qi.h>
|
||||
extern const struct board_api board_api_gta01;
|
||||
#endif
|
||||
|
||||
#define TEXT_BASE 0x33000000
|
||||
|
||||
#endif /* __CONFIG_H */
|
32
qiboot/include/neo_gta02.h
Normal file
32
qiboot/include/neo_gta02.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
* Author: xiangfu liu <xiangfu@openmoko.org>
|
||||
*
|
||||
* Configuation settings for the FIC Neo GTA02 Linux GSM phone
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __CONFIG_H
|
||||
#define __CONFIG_H
|
||||
#ifndef __ASM_MODE__
|
||||
#include <qi.h>
|
||||
extern const struct board_api board_api_gta02;
|
||||
#endif
|
||||
|
||||
#define TEXT_BASE 0x33000000
|
||||
|
||||
#endif /* __CONFIG_H */
|
28
qiboot/include/neo_om_3d7k.h
Normal file
28
qiboot/include/neo_om_3d7k.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
* Author: xiangfu liu <xiangfu@openmoko.org>
|
||||
*
|
||||
* Configuation settings for the FIC Neo GTA02 Linux GSM phone
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __ASM_MODE__
|
||||
#include <qi.h>
|
||||
extern const struct board_api board_api_om_3d7k;
|
||||
#endif
|
||||
|
||||
#define TEXT_BASE_OM_3D7K 0x53000000
|
6
qiboot/include/neo_smdk6410.h
Normal file
6
qiboot/include/neo_smdk6410.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef __ASM_MODE__
|
||||
#include <qi.h>
|
||||
extern const struct board_api board_api_smdk6410;
|
||||
#endif
|
||||
|
||||
#define TEXT_BASE_SMDK6410 0x53000000
|
260
qiboot/include/pcf50606.h
Normal file
260
qiboot/include/pcf50606.h
Normal file
@ -0,0 +1,260 @@
|
||||
#ifndef _PCF50606_H
|
||||
#define _PCF50606_H
|
||||
|
||||
/* Philips PCF50606 Power Managemnt Unit (PMU) driver
|
||||
* (C) 2006-2007 by OpenMoko, Inc.
|
||||
* Author: Harald Welte <laforge@openmoko.org>
|
||||
*
|
||||
*/
|
||||
|
||||
enum pfc50606_regs {
|
||||
PCF50606_REG_ID = 0x00,
|
||||
PCF50606_REG_OOCS = 0x01,
|
||||
PCF50606_REG_INT1 = 0x02, /* Interrupt Status */
|
||||
PCF50606_REG_INT2 = 0x03, /* Interrupt Status */
|
||||
PCF50606_REG_INT3 = 0x04, /* Interrupt Status */
|
||||
PCF50606_REG_INT1M = 0x05, /* Interrupt Mask */
|
||||
PCF50606_REG_INT2M = 0x06, /* Interrupt Mask */
|
||||
PCF50606_REG_INT3M = 0x07, /* Interrupt Mask */
|
||||
PCF50606_REG_OOCC1 = 0x08,
|
||||
PCF50606_REG_OOCC2 = 0x09,
|
||||
PCF50606_REG_RTCSC = 0x0a, /* Second */
|
||||
PCF50606_REG_RTCMN = 0x0b, /* Minute */
|
||||
PCF50606_REG_RTCHR = 0x0c, /* Hour */
|
||||
PCF50606_REG_RTCWD = 0x0d, /* Weekday */
|
||||
PCF50606_REG_RTCDT = 0x0e, /* Day */
|
||||
PCF50606_REG_RTCMT = 0x0f, /* Month */
|
||||
PCF50606_REG_RTCYR = 0x10, /* Year */
|
||||
PCF50606_REG_RTCSCA = 0x11, /* Alarm Second */
|
||||
PCF50606_REG_RTCMNA = 0x12, /* Alarm Minute */
|
||||
PCF50606_REG_RTCHRA = 0x13, /* Alarm Hour */
|
||||
PCF50606_REG_RTCWDA = 0x14, /* Alarm Weekday */
|
||||
PCF50606_REG_RTCDTA = 0x15, /* Alarm Day */
|
||||
PCF50606_REG_RTCMTA = 0x16, /* Alarm Month */
|
||||
PCF50606_REG_RTCYRA = 0x17, /* Alarm Year */
|
||||
PCF50606_REG_PSSC = 0x18, /* Power sequencing */
|
||||
PCF50606_REG_PWROKM = 0x19, /* PWROK mask */
|
||||
PCF50606_REG_PWROKS = 0x1a, /* PWROK status */
|
||||
PCF50606_REG_DCDC1 = 0x1b,
|
||||
PCF50606_REG_DCDC2 = 0x1c,
|
||||
PCF50606_REG_DCDC3 = 0x1d,
|
||||
PCF50606_REG_DCDC4 = 0x1e,
|
||||
PCF50606_REG_DCDEC1 = 0x1f,
|
||||
PCF50606_REG_DCDEC2 = 0x20,
|
||||
PCF50606_REG_DCUDC1 = 0x21,
|
||||
PCF50606_REG_DCUDC2 = 0x22,
|
||||
PCF50606_REG_IOREGC = 0x23,
|
||||
PCF50606_REG_D1REGC1 = 0x24,
|
||||
PCF50606_REG_D2REGC1 = 0x25,
|
||||
PCF50606_REG_D3REGC1 = 0x26,
|
||||
PCF50606_REG_LPREGC1 = 0x27,
|
||||
PCF50606_REG_LPREGC2 = 0x28,
|
||||
PCF50606_REG_MBCC1 = 0x29,
|
||||
PCF50606_REG_MBCC2 = 0x2a,
|
||||
PCF50606_REG_MBCC3 = 0x2b,
|
||||
PCF50606_REG_MBCS1 = 0x2c,
|
||||
PCF50606_REG_BBCC = 0x2d,
|
||||
PCF50606_REG_ADCC1 = 0x2e,
|
||||
PCF50606_REG_ADCC2 = 0x2f,
|
||||
PCF50606_REG_ADCS1 = 0x30,
|
||||
PCF50606_REG_ADCS2 = 0x31,
|
||||
PCF50606_REG_ADCS3 = 0x32,
|
||||
PCF50606_REG_ACDC1 = 0x33,
|
||||
PCF50606_REG_BVMC = 0x34,
|
||||
PCF50606_REG_PWMC1 = 0x35,
|
||||
PCF50606_REG_LEDC1 = 0x36,
|
||||
PCF50606_REG_LEDC2 = 0x37,
|
||||
PCF50606_REG_GPOC1 = 0x38,
|
||||
PCF50606_REG_GPOC2 = 0x39,
|
||||
PCF50606_REG_GPOC3 = 0x3a,
|
||||
PCF50606_REG_GPOC4 = 0x3b,
|
||||
PCF50606_REG_GPOC5 = 0x3c,
|
||||
__NUM_PCF50606_REGS
|
||||
};
|
||||
|
||||
enum pcf50606_reg_oocs {
|
||||
PFC50606_OOCS_ONKEY = 0x01,
|
||||
PCF50606_OOCS_EXTON = 0x02,
|
||||
PCF50606_OOCS_PWROKRST = 0x04,
|
||||
PCF50606_OOCS_BATOK = 0x08,
|
||||
PCF50606_OOCS_BACKOK = 0x10,
|
||||
PCF50606_OOCS_CHGOK = 0x20,
|
||||
PCF50606_OOCS_TEMPOK = 0x40,
|
||||
PCF50606_OOCS_WDTEXP = 0x80,
|
||||
};
|
||||
|
||||
enum pcf50606_reg_oocc1 {
|
||||
PCF50606_OOCC1_GOSTDBY = 0x01,
|
||||
PCF50606_OOCC1_TOTRST = 0x02,
|
||||
PCF50606_OOCC1_CLK32ON = 0x04,
|
||||
PCF50606_OOCC1_WDTRST = 0x08,
|
||||
PCF50606_OOCC1_RTCWAK = 0x10,
|
||||
PCF50606_OOCC1_CHGWAK = 0x20,
|
||||
PCF50606_OOCC1_EXTONWAK_HIGH = 0x40,
|
||||
PCF50606_OOCC1_EXTONWAK_LOW = 0x80,
|
||||
PCF50606_OOCC1_EXTONWAK_NO_WAKEUP = 0x3f,
|
||||
};
|
||||
|
||||
enum pcf50606_reg_oocc2 {
|
||||
PCF50606_OOCC2_ONKEYDB_NONE = 0x00,
|
||||
PCF50606_OOCC2_ONKEYDB_14ms = 0x01,
|
||||
PCF50606_OOCC2_ONKEYDB_62ms = 0x02,
|
||||
PCF50606_OOCC2_ONKEYDB_500ms = 0x03,
|
||||
PCF50606_OOCC2_EXTONDB_NONE = 0x00,
|
||||
PCF50606_OOCC2_EXTONDB_14ms = 0x04,
|
||||
PCF50606_OOCC2_EXTONDB_62ms = 0x08,
|
||||
PCF50606_OOCC2_EXTONDB_500ms = 0x0c,
|
||||
};
|
||||
|
||||
enum pcf50606_reg_int1 {
|
||||
PCF50606_INT1_ONKEYR = 0x01, /* ONKEY rising edge */
|
||||
PCF50606_INT1_ONKEYF = 0x02, /* ONKEY falling edge */
|
||||
PCF50606_INT1_ONKEY1S = 0x04, /* OMKEY at least 1sec low */
|
||||
PCF50606_INT1_EXTONR = 0x08, /* EXTON rising edge */
|
||||
PCF50606_INT1_EXTONF = 0x10, /* EXTON falling edge */
|
||||
PCF50606_INT1_SECOND = 0x40, /* RTC periodic second interrupt */
|
||||
PCF50606_INT1_ALARM = 0x80, /* RTC alarm time is reached */
|
||||
};
|
||||
|
||||
enum pcf50606_reg_int2 {
|
||||
PCF50606_INT2_CHGINS = 0x01, /* Charger inserted */
|
||||
PCF50606_INT2_CHGRM = 0x02, /* Charger removed */
|
||||
PCF50606_INT2_CHGFOK = 0x04, /* Fast charging OK */
|
||||
PCF50606_INT2_CHGERR = 0x08, /* Error in charging mode */
|
||||
PCF50606_INT2_CHGFRDY = 0x10, /* Fast charge completed */
|
||||
PCF50606_INT2_CHGPROT = 0x20, /* Charging protection interrupt */
|
||||
PCF50606_INT2_CHGWD10S = 0x40, /* Charger watchdig expires in 10s */
|
||||
PCF50606_INT2_CHGWDEXP = 0x80, /* Charger watchdog expires */
|
||||
};
|
||||
|
||||
enum pcf50606_reg_int3 {
|
||||
PCF50606_INT3_ADCRDY = 0x01, /* ADC conversion finished */
|
||||
PCF50606_INT3_ACDINS = 0x02, /* Accessory inserted */
|
||||
PCF50606_INT3_ACDREM = 0x04, /* Accessory removed */
|
||||
PCF50606_INT3_TSCPRES = 0x08, /* Touch screen pressed */
|
||||
PCF50606_INT3_LOWBAT = 0x40, /* Low battery voltage */
|
||||
PCF50606_INT3_HIGHTMP = 0x80, /* High temperature */
|
||||
};
|
||||
|
||||
/* used by PSSC, PWROKM, PWROKS, */
|
||||
enum pcf50606_regu {
|
||||
PCF50606_REGU_DCD = 0x01, /* DCD in phase 2 */
|
||||
PCF50606_REGU_DCDE = 0x02, /* DCDE in phase 2 */
|
||||
PCF50606_REGU_DCUD = 0x04, /* DCDU in phase 2 */
|
||||
PCF50606_REGU_IO = 0x08, /* IO in phase 2 */
|
||||
PCF50606_REGU_D1 = 0x10, /* D1 in phase 2 */
|
||||
PCF50606_REGU_D2 = 0x20, /* D2 in phase 2 */
|
||||
PCF50606_REGU_D3 = 0x40, /* D3 in phase 2 */
|
||||
PCF50606_REGU_LP = 0x80, /* LP in phase 2 */
|
||||
};
|
||||
|
||||
enum pcf50606_reg_dcdc4 {
|
||||
PCF50606_DCDC4_MODE_AUTO = 0x00,
|
||||
PCF50606_DCDC4_MODE_PWM = 0x01,
|
||||
PCF50606_DCDC4_MODE_PCF = 0x02,
|
||||
PCF50606_DCDC4_OFF_FLOAT = 0x00,
|
||||
PCF50606_DCDC4_OFF_BYPASS = 0x04,
|
||||
PCF50606_DCDC4_OFF_PULLDOWN = 0x08,
|
||||
PCF50606_DCDC4_CURLIM_500mA = 0x00,
|
||||
PCF50606_DCDC4_CURLIM_750mA = 0x10,
|
||||
PCF50606_DCDC4_CURLIM_1000mA = 0x20,
|
||||
PCF50606_DCDC4_CURLIM_1250mA = 0x30,
|
||||
PCF50606_DCDC4_TOGGLE = 0x40,
|
||||
PCF50606_DCDC4_REGSEL_DCDC2 = 0x80,
|
||||
};
|
||||
|
||||
enum pcf50606_reg_dcdec2 {
|
||||
PCF50606_DCDEC2_MODE_AUTO = 0x00,
|
||||
PCF50606_DCDEC2_MODE_PWM = 0x01,
|
||||
PCF50606_DCDEC2_MODE_PCF = 0x02,
|
||||
PCF50606_DCDEC2_OFF_FLOAT = 0x00,
|
||||
PCF50606_DCDEC2_OFF_BYPASS = 0x04,
|
||||
};
|
||||
|
||||
enum pcf50606_reg_dcudc2 {
|
||||
PCF50606_DCUDC2_MODE_AUTO = 0x00,
|
||||
PCF50606_DCUDC2_MODE_PWM = 0x01,
|
||||
PCF50606_DCUDC2_MODE_PCF = 0x02,
|
||||
PCF50606_DCUDC2_OFF_FLOAT = 0x00,
|
||||
PCF50606_DCUDC2_OFF_BYPASS = 0x04,
|
||||
};
|
||||
|
||||
enum pcf50606_reg_adcc1 {
|
||||
PCF50606_ADCC1_TSCMODACT = 0x01,
|
||||
PCF50606_ADCC1_TSCMODSTB = 0x02,
|
||||
PCF50606_ADCC1_TRATSET = 0x04,
|
||||
PCF50606_ADCC1_NTCSWAPE = 0x08,
|
||||
PCF50606_ADCC1_NTCSWAOFF = 0x10,
|
||||
PCF50606_ADCC1_EXTSYNCBREAK = 0x20,
|
||||
/* reserved */
|
||||
PCF50606_ADCC1_TSCINT = 0x80,
|
||||
};
|
||||
|
||||
enum pcf50606_reg_adcc2 {
|
||||
PCF50606_ADCC2_ADCSTART = 0x01,
|
||||
/* see enum pcf50606_adcc2_adcmux */
|
||||
PCF50606_ADCC2_SYNC_NONE = 0x00,
|
||||
PCF50606_ADCC2_SYNC_TXON = 0x20,
|
||||
PCF50606_ADCC2_SYNC_PWREN1 = 0x40,
|
||||
PCF50606_ADCC2_SYNC_PWREN2 = 0x60,
|
||||
PCF50606_ADCC2_RES_10BIT = 0x00,
|
||||
PCF50606_ADCC2_RES_8BIT = 0x80,
|
||||
};
|
||||
|
||||
#define PCF50606_ADCC2_ADCMUX_MASK (0xf << 1)
|
||||
|
||||
#define ADCMUX_SHIFT 1
|
||||
enum pcf50606_adcc2_adcmux {
|
||||
PCF50606_ADCMUX_BATVOLT_RES = 0x0 << ADCMUX_SHIFT,
|
||||
PCF50606_ADCMUX_BATVOLT_SUBTR = 0x1 << ADCMUX_SHIFT,
|
||||
PCF50606_ADCMUX_ADCIN1_RES = 0x2 << ADCMUX_SHIFT,
|
||||
PCF50606_ADCMUX_ADCIN1_SUBTR = 0x3 << ADCMUX_SHIFT,
|
||||
PCF50606_ADCMUX_BATTEMP = 0x4 << ADCMUX_SHIFT,
|
||||
PCF50606_ADCMUX_ADCIN2 = 0x5 << ADCMUX_SHIFT,
|
||||
PCF50606_ADCMUX_ADCIN3 = 0x6 << ADCMUX_SHIFT,
|
||||
PCF50606_ADCMUX_ADCIN3_RATIO = 0x7 << ADCMUX_SHIFT,
|
||||
PCF50606_ADCMUX_XPOS = 0x8 << ADCMUX_SHIFT,
|
||||
PCF50606_ADCMUX_YPOS = 0x9 << ADCMUX_SHIFT,
|
||||
PCF50606_ADCMUX_P1 = 0xa << ADCMUX_SHIFT,
|
||||
PCF50606_ADCMUX_P2 = 0xb << ADCMUX_SHIFT,
|
||||
PCF50606_ADCMUX_BATVOLT_ADCIN1 = 0xc << ADCMUX_SHIFT,
|
||||
PCF50606_ADCMUX_XY_SEQUENCE = 0xe << ADCMUX_SHIFT,
|
||||
PCF50606_P1_P2_RESISTANCE = 0xf << ADCMUX_SHIFT,
|
||||
};
|
||||
|
||||
enum pcf50606_adcs2 {
|
||||
PCF50606_ADCS2_ADCRDY = 0x80,
|
||||
};
|
||||
|
||||
enum pcf50606_reg_mbcc1 {
|
||||
PCF50606_MBCC1_CHGAPE = 0x01,
|
||||
PCF50606_MBCC1_AUTOFST = 0x02,
|
||||
#define PCF50606_MBCC1_CHGMOD_MASK 0x1c
|
||||
#define PCF50606_MBCC1_CHGMOD_SHIFT 2
|
||||
PCF50606_MBCC1_CHGMOD_QUAL = 0x00,
|
||||
PCF50606_MBCC1_CHGMOD_PRE = 0x04,
|
||||
PCF50606_MBCC1_CHGMOD_TRICKLE = 0x08,
|
||||
PCF50606_MBCC1_CHGMOD_FAST_CCCV = 0x0c,
|
||||
PCF50606_MBCC1_CHGMOD_FAST_NOCC = 0x10,
|
||||
PCF50606_MBCC1_CHGMOD_FAST_NOCV = 0x14,
|
||||
PCF50606_MBCC1_CHGMOD_FAST_SW = 0x18,
|
||||
PCF50606_MBCC1_CHGMOD_IDLE = 0x1c,
|
||||
PCF50606_MBCC1_DETMOD_LOWCHG = 0x20,
|
||||
PCF50606_MBCC1_DETMOD_WDRST = 0x40,
|
||||
};
|
||||
|
||||
enum pcf50606_reg_bvmc {
|
||||
PCF50606_BVMC_LOWBAT = 0x01,
|
||||
PCF50606_BVMC_THRSHLD_NULL = 0x00,
|
||||
PCF50606_BVMC_THRSHLD_2V8 = 0x02,
|
||||
PCF50606_BVMC_THRSHLD_2V9 = 0x04,
|
||||
PCF50606_BVMC_THRSHLD_3V = 0x08,
|
||||
PCF50606_BVMC_THRSHLD_3V1 = 0x08,
|
||||
PCF50606_BVMC_THRSHLD_3V2 = 0x0a,
|
||||
PCF50606_BVMC_THRSHLD_3V3 = 0x0c,
|
||||
PCF50606_BVMC_THRSHLD_3V4 = 0x0e,
|
||||
PCF50606_BVMC_DISDB = 0x10,
|
||||
};
|
||||
|
||||
#endif /* _PCF50606_H */
|
||||
|
392
qiboot/include/pcf50633.h
Normal file
392
qiboot/include/pcf50633.h
Normal file
@ -0,0 +1,392 @@
|
||||
#ifndef _PCF50633_H
|
||||
#define _PCF50633_H
|
||||
|
||||
/* Philips PCF50633 Power Managemnt Unit (PMU) driver
|
||||
* (C) 2006-2007 by OpenMoko, Inc.
|
||||
* Author: Harald Welte <laforge@openmoko.org>
|
||||
*
|
||||
*/
|
||||
|
||||
enum pfc50633_regs {
|
||||
PCF50633_REG_VERSION = 0x00,
|
||||
PCF50633_REG_VARIANT = 0x01,
|
||||
PCF50633_REG_INT1 = 0x02, /* Interrupt Status */
|
||||
PCF50633_REG_INT2 = 0x03, /* Interrupt Status */
|
||||
PCF50633_REG_INT3 = 0x04, /* Interrupt Status */
|
||||
PCF50633_REG_INT4 = 0x05, /* Interrupt Status */
|
||||
PCF50633_REG_INT5 = 0x06, /* Interrupt Status */
|
||||
PCF50633_REG_INT1M = 0x07, /* Interrupt Mask */
|
||||
PCF50633_REG_INT2M = 0x08, /* Interrupt Mask */
|
||||
PCF50633_REG_INT3M = 0x09, /* Interrupt Mask */
|
||||
PCF50633_REG_INT4M = 0x0a, /* Interrupt Mask */
|
||||
PCF50633_REG_INT5M = 0x0b, /* Interrupt Mask */
|
||||
PCF50633_REG_OOCSHDWN = 0x0c,
|
||||
PCF50633_REG_OOCWAKE = 0x0d,
|
||||
PCF50633_REG_OOCTIM1 = 0x0e,
|
||||
PCF50633_REG_OOCTIM2 = 0x0f,
|
||||
PCF50633_REG_OOCMODE = 0x10,
|
||||
PCF50633_REG_OOCCTL = 0x11,
|
||||
PCF50633_REG_OOCSTAT = 0x12,
|
||||
PCF50633_REG_GPIOCTL = 0x13,
|
||||
PCF50633_REG_GPIO1CFG = 0x14,
|
||||
PCF50633_REG_GPIO2CFG = 0x15,
|
||||
PCF50633_REG_GPIO3CFG = 0x16,
|
||||
PCF50633_REG_GPOCFG = 0x17,
|
||||
PCF50633_REG_BVMCTL = 0x18,
|
||||
PCF50633_REG_SVMCTL = 0x19,
|
||||
PCF50633_REG_AUTOOUT = 0x1a,
|
||||
PCF50633_REG_AUTOENA = 0x1b,
|
||||
PCF50633_REG_AUTOCTL = 0x1c,
|
||||
PCF50633_REG_AUTOMXC = 0x1d,
|
||||
PCF50633_REG_DOWN1OUT = 0x1e,
|
||||
PCF50633_REG_DOWN1ENA = 0x1f,
|
||||
PCF50633_REG_DOWN1CTL = 0x20,
|
||||
PCF50633_REG_DOWN1MXC = 0x21,
|
||||
PCF50633_REG_DOWN2OUT = 0x22,
|
||||
PCF50633_REG_DOWN2ENA = 0x23,
|
||||
PCF50633_REG_DOWN2CTL = 0x24,
|
||||
PCF50633_REG_DOWN2MXC = 0x25,
|
||||
PCF50633_REG_MEMLDOOUT = 0x26,
|
||||
PCF50633_REG_MEMLDOENA = 0x27,
|
||||
PCF50633_REG_LEDOUT = 0x28,
|
||||
PCF50633_REG_LEDENA = 0x29,
|
||||
PCF50633_REG_LEDCTL = 0x2a,
|
||||
PCF50633_REG_LEDDIM = 0x2b,
|
||||
/* reserved */
|
||||
PCF50633_REG_LDO1OUT = 0x2d,
|
||||
PCF50633_REG_LDO1ENA = 0x2e,
|
||||
PCF50633_REG_LDO2OUT = 0x2f,
|
||||
PCF50633_REG_LDO2ENA = 0x30,
|
||||
PCF50633_REG_LDO3OUT = 0x31,
|
||||
PCF50633_REG_LDO3ENA = 0x32,
|
||||
PCF50633_REG_LDO4OUT = 0x33,
|
||||
PCF50633_REG_LDO4ENA = 0x34,
|
||||
PCF50633_REG_LDO5OUT = 0x35,
|
||||
PCF50633_REG_LDO5ENA = 0x36,
|
||||
PCF50633_REG_LDO6OUT = 0x37,
|
||||
PCF50633_REG_LDO6ENA = 0x38,
|
||||
PCF50633_REG_HCLDOOUT = 0x39,
|
||||
PCF50633_REG_HCLDOENA = 0x3a,
|
||||
PCF50633_REG_STBYCTL1 = 0x3b,
|
||||
PCF50633_REG_STBYCTL2 = 0x3c,
|
||||
PCF50633_REG_DEBPF1 = 0x3d,
|
||||
PCF50633_REG_DEBPF2 = 0x3e,
|
||||
PCF50633_REG_DEBPF3 = 0x3f,
|
||||
PCF50633_REG_HCLDOOVL = 0x40,
|
||||
PCF50633_REG_DCDCSTAT = 0x41,
|
||||
PCF50633_REG_LDOSTAT = 0x42,
|
||||
PCF50633_REG_MBCC1 = 0x43,
|
||||
PCF50633_REG_MBCC2 = 0x44,
|
||||
PCF50633_REG_MBCC3 = 0x45,
|
||||
PCF50633_REG_MBCC4 = 0x46,
|
||||
PCF50633_REG_MBCC5 = 0x47,
|
||||
PCF50633_REG_MBCC6 = 0x48,
|
||||
PCF50633_REG_MBCC7 = 0x49,
|
||||
PCF50633_REG_MBCC8 = 0x4a,
|
||||
PCF50633_REG_MBCS1 = 0x4b,
|
||||
PCF50633_REG_MBCS2 = 0x4c,
|
||||
PCF50633_REG_MBCS3 = 0x4d,
|
||||
PCF50633_REG_BBCCTL = 0x4e,
|
||||
PCF50633_REG_ALMGAIN = 0x4f,
|
||||
PCF50633_REG_ALMDATA = 0x50,
|
||||
/* reserved */
|
||||
PCF50633_REG_ADCC3 = 0x52,
|
||||
PCF50633_REG_ADCC2 = 0x53,
|
||||
PCF50633_REG_ADCC1 = 0x54,
|
||||
PCF50633_REG_ADCS1 = 0x55,
|
||||
PCF50633_REG_ADCS2 = 0x56,
|
||||
PCF50633_REG_ADCS3 = 0x57,
|
||||
/* reserved */
|
||||
PCF50633_REG_RTCSC = 0x59, /* Second */
|
||||
PCF50633_REG_RTCMN = 0x5a, /* Minute */
|
||||
PCF50633_REG_RTCHR = 0x5b, /* Hour */
|
||||
PCF50633_REG_RTCWD = 0x5c, /* Weekday */
|
||||
PCF50633_REG_RTCDT = 0x5d, /* Day */
|
||||
PCF50633_REG_RTCMT = 0x5e, /* Month */
|
||||
PCF50633_REG_RTCYR = 0x5f, /* Year */
|
||||
PCF50633_REG_RTCSCA = 0x60, /* Alarm Second */
|
||||
PCF50633_REG_RTCMNA = 0x61, /* Alarm Minute */
|
||||
PCF50633_REG_RTCHRA = 0x62, /* Alarm Hour */
|
||||
PCF50633_REG_RTCWDA = 0x63, /* Alarm Weekday */
|
||||
PCF50633_REG_RTCDTA = 0x64, /* Alarm Day */
|
||||
PCF50633_REG_RTCMTA = 0x65, /* Alarm Month */
|
||||
PCF50633_REG_RTCYRA = 0x66, /* Alarm Year */
|
||||
|
||||
PCF50633_REG_MEMBYTE0 = 0x67,
|
||||
PCF50633_REG_MEMBYTE1 = 0x68,
|
||||
PCF50633_REG_MEMBYTE2 = 0x69,
|
||||
PCF50633_REG_MEMBYTE3 = 0x6a,
|
||||
PCF50633_REG_MEMBYTE4 = 0x6b,
|
||||
PCF50633_REG_MEMBYTE5 = 0x6c,
|
||||
PCF50633_REG_MEMBYTE6 = 0x6d,
|
||||
PCF50633_REG_MEMBYTE7 = 0x6e,
|
||||
/* reserved */
|
||||
PCF50633_REG_DCDCPFM = 0x84,
|
||||
__NUM_PCF50633_REGS
|
||||
};
|
||||
|
||||
enum pcf50633_reg_int1 {
|
||||
PCF50633_INT1_ADPINS = 0x01, /* Adapter inserted */
|
||||
PCF50633_INT1_ADPREM = 0x02, /* Adapter removed */
|
||||
PCF50633_INT1_USBINS = 0x04, /* USB inserted */
|
||||
PCF50633_INT1_USBREM = 0x08, /* USB removed */
|
||||
/* reserved */
|
||||
PCF50633_INT1_ALARM = 0x40, /* RTC alarm time is reached */
|
||||
PCF50633_INT1_SECOND = 0x80, /* RTC periodic second interrupt */
|
||||
};
|
||||
|
||||
enum pcf50633_reg_int2 {
|
||||
PCF50633_INT2_ONKEYR = 0x01, /* ONKEY rising edge */
|
||||
PCF50633_INT2_ONKEYF = 0x02, /* ONKEY falling edge */
|
||||
PCF50633_INT2_EXTON1R = 0x04, /* EXTON1 rising edge */
|
||||
PCF50633_INT2_EXTON1F = 0x08, /* EXTON1 falling edge */
|
||||
PCF50633_INT2_EXTON2R = 0x10, /* EXTON2 rising edge */
|
||||
PCF50633_INT2_EXTON2F = 0x20, /* EXTON2 falling edge */
|
||||
PCF50633_INT2_EXTON3R = 0x40, /* EXTON3 rising edge */
|
||||
PCF50633_INT2_EXTON3F = 0x80, /* EXTON3 falling edge */
|
||||
};
|
||||
|
||||
enum pcf50633_reg_int3 {
|
||||
PCF50633_INT3_BATFULL = 0x01, /* Battery full */
|
||||
PCF50633_INT3_CHGHALT = 0x02, /* Charger halt */
|
||||
PCF50633_INT3_THLIMON = 0x04,
|
||||
PCF50633_INT3_THLIMOFF = 0x08,
|
||||
PCF50633_INT3_USBLIMON = 0x10,
|
||||
PCF50633_INT3_USBLIMOFF = 0x20,
|
||||
PCF50633_INT3_ADCRDY = 0x40, /* ADC conversion finished */
|
||||
PCF50633_INT3_ONKEY1S = 0x80, /* ONKEY pressed 1 second */
|
||||
};
|
||||
|
||||
enum pcf50633_reg_int4 {
|
||||
PCF50633_INT4_LOWSYS = 0x01,
|
||||
PCF50633_INT4_LOWBAT = 0x02,
|
||||
PCF50633_INT4_HIGHTMP = 0x04,
|
||||
PCF50633_INT4_AUTOPWRFAIL = 0x08,
|
||||
PCF50633_INT4_DWN1PWRFAIL = 0x10,
|
||||
PCF50633_INT4_DWN2PWRFAIL = 0x20,
|
||||
PCF50633_INT4_LEDPWRFAIL = 0x40,
|
||||
PCF50633_INT4_LEDOVP = 0x80,
|
||||
};
|
||||
|
||||
enum pcf50633_reg_int5 {
|
||||
PCF50633_INT4_LDO1PWRFAIL = 0x01,
|
||||
PCF50633_INT4_LDO2PWRFAIL = 0x02,
|
||||
PCF50633_INT4_LDO3PWRFAIL = 0x04,
|
||||
PCF50633_INT4_LDO4PWRFAIL = 0x08,
|
||||
PCF50633_INT4_LDO5PWRFAIL = 0x10,
|
||||
PCF50633_INT4_LDO6PWRFAIL = 0x20,
|
||||
PCF50633_INT4_HCLDOPWRFAIL = 0x40,
|
||||
PCF50633_INT4_HCLDOOVL = 0x80,
|
||||
};
|
||||
|
||||
enum pcf50633_reg_oocwake {
|
||||
PCF50633_OOCWAKE_ONKEY = 0x01,
|
||||
PCF50633_OOCWAKE_EXTON1 = 0x02,
|
||||
PCF50633_OOCWAKE_EXTON2 = 0x04,
|
||||
PCF50633_OOCWAKE_EXTON3 = 0x08,
|
||||
PCF50633_OOCWAKE_RTC = 0x10,
|
||||
/* reserved */
|
||||
PCF50633_OOCWAKE_USB = 0x40,
|
||||
PCF50633_OOCWAKE_ADP = 0x80,
|
||||
};
|
||||
|
||||
enum pcf50633_reg_mbcc1 {
|
||||
PCF50633_MBCC1_CHGENA = 0x01, /* Charger enable */
|
||||
PCF50633_MBCC1_AUTOSTOP = 0x02,
|
||||
PCF50633_MBCC1_AUTORES = 0x04, /* automatic resume */
|
||||
PCF50633_MBCC1_RESUME = 0x08, /* explicit resume cmd */
|
||||
PCF50633_MBCC1_RESTART = 0x10, /* restart charging */
|
||||
PCF50633_MBCC1_PREWDTIME_60M = 0x20, /* max. precharging time */
|
||||
PCF50633_MBCC1_WDTIME_1H = 0x00,
|
||||
PCF50633_MBCC1_WDTIME_2H = 0x40,
|
||||
PCF50633_MBCC1_WDTIME_4H = 0x80,
|
||||
PCF50633_MBCC1_WDTIME_6H = 0xc0,
|
||||
};
|
||||
#define PCF50633_MBCC1_WDTIME_MASK 0xc0
|
||||
|
||||
enum pcf50633_reg_mbcc2 {
|
||||
PCF50633_MBCC2_VBATCOND_2V7 = 0x00,
|
||||
PCF50633_MBCC2_VBATCOND_2V85 = 0x01,
|
||||
PCF50633_MBCC2_VBATCOND_3V = 0x02,
|
||||
PCF50633_MBCC2_VBATCOND_3V15 = 0x03,
|
||||
PCF50633_MBCC2_VMAX_4V = 0x00,
|
||||
PCF50633_MBCC2_VMAX_4V20 = 0x28,
|
||||
PCF50633_MBCC2_VRESDEBTIME_64S = 0x80, /* debounce time (32/64sec) */
|
||||
};
|
||||
#define PCF50633_MBCC2_VBATCOND_MASK 0x03
|
||||
#define PCF50633_MBCC2_VMAX_MASK 0x3c
|
||||
|
||||
#define PCF50633_OOCSTAT_ONKEY 0x01
|
||||
|
||||
|
||||
enum pcf50633_reg_adcc1 {
|
||||
PCF50633_ADCC1_ADCSTART = 0x01,
|
||||
PCF50633_ADCC1_RES_10BIT = 0x02,
|
||||
PCF50633_ADCC1_AVERAGE_NO = 0x00,
|
||||
PCF50633_ADCC1_AVERAGE_4 = 0x04,
|
||||
PCF50633_ADCC1_AVERAGE_8 = 0x08,
|
||||
PCF50633_ADCC1_AVERAGE_16 = 0x0c,
|
||||
|
||||
PCF50633_ADCC1_MUX_BATSNS_RES = 0x00,
|
||||
PCF50633_ADCC1_MUX_BATSNS_SUBTR = 0x10,
|
||||
PCF50633_ADCC1_MUX_ADCIN2_RES = 0x20,
|
||||
PCF50633_ADCC1_MUX_ADCIN2_SUBTR = 0x30,
|
||||
PCF50633_ADCC1_MUX_BATTEMP = 0x60,
|
||||
PCF50633_ADCC1_MUX_ADCIN1 = 0x70,
|
||||
};
|
||||
#define PCF50633_ADCC1_AVERAGE_MASK 0x0c
|
||||
#define PCF50633_ADCC1_ADCMUX_MASK 0xf0
|
||||
|
||||
enum pcf50633_reg_adcc2 {
|
||||
PCF50633_ADCC2_RATIO_NONE = 0x00,
|
||||
PCF50633_ADCC2_RATIO_BATTEMP = 0x01,
|
||||
PCF50633_ADCC2_RATIO_ADCIN1 = 0x02,
|
||||
PCF50633_ADCC2_RATIO_BOTH = 0x03,
|
||||
PCF50633_ADCC2_RATIOSETTL_100US = 0x04,
|
||||
};
|
||||
#define PCF50633_ADCC2_RATIO_MASK 0x03
|
||||
|
||||
enum pcf50633_reg_adcc3 {
|
||||
PCF50633_ADCC3_ACCSW_EN = 0x01,
|
||||
PCF50633_ADCC3_NTCSW_EN = 0x04,
|
||||
PCF50633_ADCC3_RES_DIV_TWO = 0x10,
|
||||
PCF50633_ADCC3_RES_DIV_THREE = 0x00,
|
||||
};
|
||||
|
||||
enum pcf50633_reg_adcs3 {
|
||||
PCF50633_ADCS3_REF_NTCSW = 0x00,
|
||||
PCF50633_ADCS3_REF_ACCSW = 0x10,
|
||||
PCF50633_ADCS3_REF_2V0 = 0x20,
|
||||
PCF50633_ADCS3_REF_VISA = 0x30,
|
||||
PCF50633_ADCS3_REF_2V0_2 = 0x70,
|
||||
PCF50633_ADCS3_ADCRDY = 0x80,
|
||||
};
|
||||
#define PCF50633_ADCS3_ADCDAT1L_MASK 0x03
|
||||
#define PCF50633_ADCS3_ADCDAT2L_MASK 0x0c
|
||||
#define PCF50633_ADCS3_ADCDAT2L_SHIFT 2
|
||||
#define PCF50633_ASCS3_REF_MASK 0x70
|
||||
|
||||
enum pcf50633_regulator_enable {
|
||||
PCF50633_REGULATOR_ON = 0x01,
|
||||
PCF50633_REGULATOR_ON_GPIO1 = 0x02,
|
||||
PCF50633_REGULATOR_ON_GPIO2 = 0x04,
|
||||
PCF50633_REGULATOR_ON_GPIO3 = 0x08,
|
||||
};
|
||||
#define PCF50633_REGULATOR_ON_MASK 0x0f
|
||||
|
||||
enum pcf50633_regulator_phase {
|
||||
PCF50633_REGULATOR_ACTPH1 = 0x00,
|
||||
PCF50633_REGULATOR_ACTPH2 = 0x10,
|
||||
PCF50633_REGULATOR_ACTPH3 = 0x20,
|
||||
PCF50633_REGULATOR_ACTPH4 = 0x30,
|
||||
};
|
||||
#define PCF50633_REGULATOR_ACTPH_MASK 0x30
|
||||
|
||||
enum pcf50633_reg_gpocfg {
|
||||
PCF50633_GPOCFG_GPOSEL_0 = 0x00,
|
||||
PCF50633_GPOCFG_GPOSEL_LED_NFET = 0x01,
|
||||
PCF50633_GPOCFG_GPOSEL_SYSxOK = 0x02,
|
||||
PCF50633_GPOCFG_GPOSEL_CLK32K = 0x03,
|
||||
PCF50633_GPOCFG_GPOSEL_ADAPUSB = 0x04,
|
||||
PCF50633_GPOCFG_GPOSEL_USBxOK = 0x05,
|
||||
PCF50633_GPOCFG_GPOSEL_ACTPH4 = 0x06,
|
||||
PCF50633_GPOCFG_GPOSEL_1 = 0x07,
|
||||
PCF50633_GPOCFG_GPOSEL_INVERSE = 0x08,
|
||||
};
|
||||
#define PCF50633_GPOCFG_GPOSEL_MASK 0x07
|
||||
|
||||
#if 0
|
||||
enum pcf50633_reg_mbcc1 {
|
||||
PCF50633_MBCC1_CHGENA = 0x01,
|
||||
PCF50633_MBCC1_AUTOSTOP = 0x02,
|
||||
PCF50633_MBCC1_AUTORES = 0x04,
|
||||
PCF50633_MBCC1_RESUME = 0x08,
|
||||
PCF50633_MBCC1_RESTART = 0x10,
|
||||
PCF50633_MBCC1_PREWDTIME_30MIN = 0x00,
|
||||
PCF50633_MBCC1_PREWDTIME_60MIN = 0x20,
|
||||
PCF50633_MBCC1_WDTIME_2HRS = 0x40,
|
||||
PCF50633_MBCC1_WDTIME_4HRS = 0x80,
|
||||
PCF50633_MBCC1_WDTIME_6HRS = 0xc0,
|
||||
};
|
||||
|
||||
enum pcf50633_reg_mbcc2 {
|
||||
PCF50633_MBCC2_VBATCOND_2V7 = 0x00,
|
||||
PCF50633_MBCC2_VBATCOND_2V85 = 0x01,
|
||||
PCF50633_MBCC2_VBATCOND_3V0 = 0x02,
|
||||
PCF50633_MBCC2_VBATCOND_3V15 = 0x03,
|
||||
PCF50633_MBCC2_VRESDEBTIME_64S = 0x80,
|
||||
};
|
||||
#define PCF50633_MBCC2_VMAX_MASK 0x3c
|
||||
#endif
|
||||
|
||||
enum pcf50633_reg_mbcc7 {
|
||||
PCF50633_MBCC7_USB_100mA = 0x00,
|
||||
PCF50633_MBCC7_USB_500mA = 0x01,
|
||||
PCF50633_MBCC7_USB_1000mA = 0x02,
|
||||
PCF50633_MBCC7_USB_SUSPEND = 0x03,
|
||||
PCF50633_MBCC7_BATTEMP_EN = 0x04,
|
||||
PCF50633_MBCC7_BATSYSIMAX_1A6 = 0x00,
|
||||
PCF50633_MBCC7_BATSYSIMAX_1A8 = 0x40,
|
||||
PCF50633_MBCC7_BATSYSIMAX_2A0 = 0x80,
|
||||
PCF50633_MBCC7_BATSYSIMAX_2A2 = 0xc0,
|
||||
};
|
||||
#define PCF56033_MBCC7_USB_MASK 0x03
|
||||
|
||||
enum pcf50633_reg_mbcc8 {
|
||||
PCF50633_MBCC8_USBENASUS = 0x10,
|
||||
};
|
||||
|
||||
enum pcf50633_reg_mbcs1 {
|
||||
PCF50633_MBCS1_USBPRES = 0x01,
|
||||
PCF50633_MBCS1_USBOK = 0x02,
|
||||
PCF50633_MBCS1_ADAPTPRES = 0x04,
|
||||
PCF50633_MBCS1_ADAPTOK = 0x08,
|
||||
PCF50633_MBCS1_TBAT_OK = 0x00,
|
||||
PCF50633_MBCS1_TBAT_ABOVE = 0x10,
|
||||
PCF50633_MBCS1_TBAT_BELOW = 0x20,
|
||||
PCF50633_MBCS1_TBAT_UNDEF = 0x30,
|
||||
PCF50633_MBCS1_PREWDTEXP = 0x40,
|
||||
PCF50633_MBCS1_WDTEXP = 0x80,
|
||||
};
|
||||
|
||||
enum pcf50633_reg_mbcs2_mbcmod {
|
||||
PCF50633_MBCS2_MBC_PLAY = 0x00,
|
||||
PCF50633_MBCS2_MBC_USB_PRE = 0x01,
|
||||
PCF50633_MBCS2_MBC_USB_PRE_WAIT = 0x02,
|
||||
PCF50633_MBCS2_MBC_USB_FAST = 0x03,
|
||||
PCF50633_MBCS2_MBC_USB_FAST_WAIT= 0x04,
|
||||
PCF50633_MBCS2_MBC_USB_SUSPEND = 0x05,
|
||||
PCF50633_MBCS2_MBC_ADP_PRE = 0x06,
|
||||
PCF50633_MBCS2_MBC_ADP_PRE_WAIT = 0x07,
|
||||
PCF50633_MBCS2_MBC_ADP_FAST = 0x08,
|
||||
PCF50633_MBCS2_MBC_ADP_FAST_WAIT= 0x09,
|
||||
PCF50633_MBCS2_MBC_BAT_FULL = 0x0a,
|
||||
PCF50633_MBCS2_MBC_HALT = 0x0b,
|
||||
};
|
||||
#define PCF50633_MBCS2_MBC_MASK 0x0f
|
||||
enum pcf50633_reg_mbcs2_chgstat {
|
||||
PCF50633_MBCS2_CHGS_NONE = 0x00,
|
||||
PCF50633_MBCS2_CHGS_ADAPTER = 0x10,
|
||||
PCF50633_MBCS2_CHGS_USB = 0x20,
|
||||
PCF50633_MBCS2_CHGS_BOTH = 0x30,
|
||||
};
|
||||
#define PCF50633_MBCS2_RESSTAT_AUTO 0x40
|
||||
|
||||
enum pcf50633_reg_mbcs3 {
|
||||
PCF50633_MBCS3_USBLIM_PLAY = 0x01,
|
||||
PCF50633_MBCS3_USBLIM_CGH = 0x02,
|
||||
PCF50633_MBCS3_TLIM_PLAY = 0x04,
|
||||
PCF50633_MBCS3_TLIM_CHG = 0x08,
|
||||
PCF50633_MBCS3_ILIM = 0x10, /* 1: Ibat > Icutoff */
|
||||
PCF50633_MBCS3_VLIM = 0x20, /* 1: Vbat == Vmax */
|
||||
PCF50633_MBCS3_VBATSTAT = 0x40, /* 1: Vbat > Vbatcond */
|
||||
PCF50633_MBCS3_VRES = 0x80, /* 1: Vbat > Vth(RES) */
|
||||
};
|
||||
|
||||
struct pcf50633_init {
|
||||
u8 index;
|
||||
u8 value;
|
||||
};
|
||||
|
||||
#endif /* _PCF50633_H */
|
||||
|
41
qiboot/include/ports-s3c24xx.h
Normal file
41
qiboot/include/ports-s3c24xx.h
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef __PORTS_S3C24XX_H__
|
||||
#define __PORTS_S3C24XX_H__
|
||||
|
||||
|
||||
// I/O PORT
|
||||
#define rGPACON (*(volatile unsigned *)0x56000000)
|
||||
#define rGPADAT (*(volatile unsigned *)0x56000004)
|
||||
|
||||
#define rGPBCON (*(volatile unsigned *)0x56000010)
|
||||
#define rGPBDAT (*(volatile unsigned *)0x56000014)
|
||||
#define rGPBUP (*(volatile unsigned *)0x56000018)
|
||||
|
||||
#define rGPCCON (*(volatile unsigned *)0x56000020)
|
||||
#define rGPCDAT (*(volatile unsigned *)0x56000024)
|
||||
#define rGPCUP (*(volatile unsigned *)0x56000028)
|
||||
|
||||
#define rGPDCON (*(volatile unsigned *)0x56000030)
|
||||
#define rGPDDAT (*(volatile unsigned *)0x56000034)
|
||||
#define rGPDUP (*(volatile unsigned *)0x56000038)
|
||||
|
||||
#define rGPECON (*(volatile unsigned *)0x56000040)
|
||||
#define rGPEDAT (*(volatile unsigned *)0x56000044)
|
||||
#define rGPEUP (*(volatile unsigned *)0x56000048)
|
||||
|
||||
#define rGPFCON (*(volatile unsigned *)0x56000050)
|
||||
#define rGPFDAT (*(volatile unsigned *)0x56000054)
|
||||
#define rGPFUP (*(volatile unsigned *)0x56000058)
|
||||
|
||||
#define rGPGCON (*(volatile unsigned *)0x56000060)
|
||||
#define rGPGDAT (*(volatile unsigned *)0x56000064)
|
||||
#define rGPGUP (*(volatile unsigned *)0x56000068)
|
||||
|
||||
#define rGPHCON (*(volatile unsigned *)0x56000070)
|
||||
#define rGPHDAT (*(volatile unsigned *)0x56000074)
|
||||
#define rGPHUP (*(volatile unsigned *)0x56000078)
|
||||
|
||||
#define rGPJCON (*(volatile unsigned *)0x560000d0) //Port J control
|
||||
#define rGPJDAT (*(volatile unsigned *)0x560000d4) //Port J data
|
||||
#define rGPJUP (*(volatile unsigned *)0x560000d8) //Port J data
|
||||
|
||||
#endif
|
45
qiboot/include/qi-ctype.h
Normal file
45
qiboot/include/qi-ctype.h
Normal file
@ -0,0 +1,45 @@
|
||||
#define _U 0x01 /* upper */
|
||||
#define _L 0x02 /* lower */
|
||||
#define _D 0x04 /* digit */
|
||||
#define _C 0x08 /* cntrl */
|
||||
#define _P 0x10 /* punct */
|
||||
#define _S 0x20 /* white space (space/lf/tab) */
|
||||
#define _X 0x40 /* hex digit */
|
||||
#define _SP 0x80 /* hard space (0x20) */
|
||||
|
||||
extern unsigned char _ctype[];
|
||||
|
||||
#define __ismask(x) (_ctype[(int)(unsigned char)(x)])
|
||||
|
||||
#define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0)
|
||||
#define isalpha(c) ((__ismask(c)&(_U|_L)) != 0)
|
||||
#define iscntrl(c) ((__ismask(c)&(_C)) != 0)
|
||||
#define isdigit(c) ((__ismask(c)&(_D)) != 0)
|
||||
#define isgraph(c) ((__ismask(c)&(_P|_U|_L|_D)) != 0)
|
||||
#define islower(c) ((__ismask(c)&(_L)) != 0)
|
||||
#define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)
|
||||
#define ispunct(c) ((__ismask(c)&(_P)) != 0)
|
||||
#define isspace(c) ((__ismask(c)&(_S)) != 0)
|
||||
#define isupper(c) ((__ismask(c)&(_U)) != 0)
|
||||
#define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0)
|
||||
|
||||
#define isascii(c) (((unsigned char)(c))<=0x7f)
|
||||
#define toascii(c) (((unsigned char)(c))&0x7f)
|
||||
|
||||
static inline unsigned char __tolower(unsigned char c)
|
||||
{
|
||||
if (isupper(c))
|
||||
c -= 'A'-'a';
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline unsigned char __toupper(unsigned char c)
|
||||
{
|
||||
if (islower(c))
|
||||
c -= 'a'-'A';
|
||||
return c;
|
||||
}
|
||||
|
||||
#define tolower(c) __tolower(c)
|
||||
#define toupper(c) __toupper(c)
|
||||
|
144
qiboot/include/qi.h
Normal file
144
qiboot/include/qi.h
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* (C) Copyright 2008 Openmoko, Inc.
|
||||
* Author: Andy Green <andy@openmoko.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __QI_H__
|
||||
#define __QI_H__
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <qi-ctype.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#define MALLOC_POOL_EXTENT (100 * 1024)
|
||||
|
||||
#define u32 unsigned int
|
||||
#define u16 unsigned short
|
||||
#define u8 unsigned char
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned char uint8_t;
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
|
||||
|
||||
enum filesystem {
|
||||
FS_RAW,
|
||||
FS_FAT,
|
||||
FS_EXT2
|
||||
};
|
||||
|
||||
enum ui_actions {
|
||||
UI_ACTION_ADD_DEBUG = (1 << 0),
|
||||
UI_ACTION_SKIPKERNEL = (1 << 1),
|
||||
};
|
||||
|
||||
enum ui_indication {
|
||||
UI_IND_UPDATE_ONLY,
|
||||
UI_IND_MOUNT_PART,
|
||||
UI_IND_MOUNT_FAIL,
|
||||
UI_IND_SKIPPING,
|
||||
UI_IND_KERNEL_PULL,
|
||||
UI_IND_KERNEL_PULL_OK,
|
||||
UI_IND_KERNEL_PULL_FAIL,
|
||||
UI_IND_INITRAMFS_PULL,
|
||||
UI_IND_INITRAMFS_PULL_OK,
|
||||
UI_IND_INITRAMFS_PULL_FAIL,
|
||||
UI_IND_KERNEL_START,
|
||||
UI_IND_MEM_TEST
|
||||
};
|
||||
|
||||
/* describes a source for getting kernel image */
|
||||
|
||||
struct kernel_source {
|
||||
const char *name; /* NULL name means invalid */
|
||||
const char *filepath;
|
||||
const char *initramfs_filepath;
|
||||
int (*block_init)(void);
|
||||
int (*block_read)(unsigned char * buf, unsigned long start512,
|
||||
int blocks512);
|
||||
int partition_index; /* -1 means no partition table */
|
||||
int offset_blocks512_if_no_partition; /* used if partition_index is -1 */
|
||||
enum filesystem filesystem;
|
||||
const char * commandline_append;
|
||||
};
|
||||
|
||||
/* describes a board variant, eg, PCB revision */
|
||||
|
||||
struct board_variant {
|
||||
const char * name;
|
||||
int machine_revision; /* passed in revision tag to linux */
|
||||
};
|
||||
|
||||
/* describes a "board", ie, a device like GTA02 including revisions */
|
||||
|
||||
struct board_api {
|
||||
const char * name;
|
||||
int linux_machine_id;
|
||||
unsigned long linux_mem_start;
|
||||
unsigned long linux_mem_size;
|
||||
unsigned long linux_tag_placement;
|
||||
const char *commandline_board;
|
||||
const char *commandline_board_debug;
|
||||
const char *noboot;
|
||||
const char *append;
|
||||
|
||||
const struct board_variant const * (*get_board_variant)(void);
|
||||
int (*is_this_board)(void);
|
||||
void (*early_port_init)(void);
|
||||
void (*port_init)(void);
|
||||
void (*post_serial_init)(void); /* print device-specific things */
|
||||
char * (*append_device_specific_cmdline)(char *);
|
||||
void (*putc)(char);
|
||||
void (*close)(void);
|
||||
u8 (*get_ui_keys)(void);
|
||||
u8 (*get_ui_debug)(void);
|
||||
void (*set_ui_indication)(enum ui_indication);
|
||||
|
||||
struct kernel_source kernel_source[8];
|
||||
};
|
||||
|
||||
/* this is the board we are running on */
|
||||
|
||||
extern struct board_api const * this_board;
|
||||
extern struct kernel_source const * this_kernel;
|
||||
|
||||
int printk(const char *fmt, ...);
|
||||
int vsprintf(char *buf, const char *fmt, va_list args);
|
||||
int puts(const char *string);
|
||||
void printhex(unsigned char v);
|
||||
void print8(unsigned char u);
|
||||
void print32(unsigned int u);
|
||||
void printdec(int n);
|
||||
void hexdump(unsigned char *start, int len);
|
||||
void udelay(int n);
|
||||
|
||||
/* phase2 only */
|
||||
void setnybble(char *p, unsigned char n);
|
||||
void set8(char *p, unsigned char n);
|
||||
void set32(char *p, unsigned int u);
|
||||
|
||||
unsigned long crc32(unsigned long crc, const unsigned char *buf,
|
||||
unsigned int len);
|
||||
int nand_read_ll(unsigned char *buf, unsigned long start512, int blocks512);
|
||||
|
||||
extern void memory_test(void * start, unsigned int length);
|
||||
|
||||
void set_putc_func(void (*p)(char));
|
||||
|
||||
#endif
|
||||
|
33
qiboot/include/s3c24xx-mci.h
Normal file
33
qiboot/include/s3c24xx-mci.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* (C) Copyright 2000-2003
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _S3C24XX_MMC_H_
|
||||
#define _S3C24XX_MMC_H_
|
||||
#include <mmc.h>
|
||||
|
||||
int s3c24xx_mmc_init(int verbose);
|
||||
u32 s3c24xx_mmc_bread(int dev_num, u32 blknr, u32 blkcnt, void *dst);
|
||||
int s3c24xx_mmc_read(u32 src, u8 *dst, int size);
|
||||
int s3c24xx_mmc_write(u8 *src, u32 dst, int size);
|
||||
|
||||
#endif /* _MMC_H_ */
|
110
qiboot/include/s3c24xx-regs-sdi.h
Normal file
110
qiboot/include/s3c24xx-regs-sdi.h
Normal file
@ -0,0 +1,110 @@
|
||||
/* linux/include/asm/arch-s3c2410/regs-sdi.h
|
||||
*
|
||||
* Copyright (c) 2004 Simtec Electronics <linux@simtec.co.uk>
|
||||
* http://www.simtec.co.uk/products/SWLINUX/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* S3C2410 MMC/SDIO register definitions
|
||||
*
|
||||
* Changelog:
|
||||
* 18-Aug-2004 Ben Dooks Created initial file
|
||||
* 29-Nov-2004 Koen Martens Added some missing defines, fixed duplicates
|
||||
* 29-Nov-2004 Ben Dooks Updated Koen's patch
|
||||
*/
|
||||
|
||||
#ifndef __ASM_ARM_REGS_SDI
|
||||
#define __ASM_ARM_REGS_SDI "regs-sdi.h"
|
||||
|
||||
#define S3C2440_SDICON_SDRESET (1<<8)
|
||||
#define S3C2440_SDICON_MMCCLOCK (1<<5)
|
||||
#define S3C2410_SDICON_BYTEORDER (1<<4)
|
||||
#define S3C2410_SDICON_SDIOIRQ (1<<3)
|
||||
#define S3C2410_SDICON_RWAITEN (1<<2)
|
||||
#define S3C2410_SDICON_FIFORESET (1<<1)
|
||||
#define S3C2410_SDICON_CLOCKTYPE (1<<0)
|
||||
|
||||
#define S3C2410_SDICMDCON_ABORT (1<<12)
|
||||
#define S3C2410_SDICMDCON_WITHDATA (1<<11)
|
||||
#define S3C2410_SDICMDCON_LONGRSP (1<<10)
|
||||
#define S3C2410_SDICMDCON_WAITRSP (1<<9)
|
||||
#define S3C2410_SDICMDCON_CMDSTART (1<<8)
|
||||
#define S3C2410_SDICMDCON_SENDERHOST (1<<6)
|
||||
#define S3C2410_SDICMDCON_INDEX (0x3f)
|
||||
|
||||
#define S3C2410_SDICMDSTAT_CRCFAIL (1<<12)
|
||||
#define S3C2410_SDICMDSTAT_CMDSENT (1<<11)
|
||||
#define S3C2410_SDICMDSTAT_CMDTIMEOUT (1<<10)
|
||||
#define S3C2410_SDICMDSTAT_RSPFIN (1<<9)
|
||||
#define S3C2410_SDICMDSTAT_XFERING (1<<8)
|
||||
#define S3C2410_SDICMDSTAT_INDEX (0xff)
|
||||
|
||||
#define S3C2440_SDIDCON_DS_BYTE (0<<22)
|
||||
#define S3C2440_SDIDCON_DS_HALFWORD (1<<22)
|
||||
#define S3C2440_SDIDCON_DS_WORD (2<<22)
|
||||
#define S3C2410_SDIDCON_IRQPERIOD (1<<21)
|
||||
#define S3C2410_SDIDCON_TXAFTERRESP (1<<20)
|
||||
#define S3C2410_SDIDCON_RXAFTERCMD (1<<19)
|
||||
#define S3C2410_SDIDCON_BUSYAFTERCMD (1<<18)
|
||||
#define S3C2410_SDIDCON_BLOCKMODE (1<<17)
|
||||
#define S3C2410_SDIDCON_WIDEBUS (1<<16)
|
||||
#define S3C2410_SDIDCON_DMAEN (1<<15)
|
||||
#define S3C2410_SDIDCON_STOP (1<<14)
|
||||
#define S3C2440_SDIDCON_DATSTART (1<<14)
|
||||
#define S3C2410_SDIDCON_DATMODE (3<<12)
|
||||
#define S3C2410_SDIDCON_BLKNUM (0x7ff)
|
||||
|
||||
/* constants for S3C2410_SDIDCON_DATMODE */
|
||||
#define S3C2410_SDIDCON_XFER_READY (0<<12)
|
||||
#define S3C2410_SDIDCON_XFER_CHKSTART (1<<12)
|
||||
#define S3C2410_SDIDCON_XFER_RXSTART (2<<12)
|
||||
#define S3C2410_SDIDCON_XFER_TXSTART (3<<12)
|
||||
|
||||
#define S3C2410_SDIDCNT_BLKNUM_MASK (0xFFF)
|
||||
#define S3C2410_SDIDCNT_BLKNUM_SHIFT (12)
|
||||
|
||||
#define S3C2410_SDIDSTA_RDYWAITREQ (1<<10)
|
||||
#define S3C2410_SDIDSTA_SDIOIRQDETECT (1<<9)
|
||||
#define S3C2410_SDIDSTA_FIFOFAIL (1<<8) /* reserved on 2440 */
|
||||
#define S3C2410_SDIDSTA_CRCFAIL (1<<7)
|
||||
#define S3C2410_SDIDSTA_RXCRCFAIL (1<<6)
|
||||
#define S3C2410_SDIDSTA_DATATIMEOUT (1<<5)
|
||||
#define S3C2410_SDIDSTA_XFERFINISH (1<<4)
|
||||
#define S3C2410_SDIDSTA_BUSYFINISH (1<<3)
|
||||
#define S3C2410_SDIDSTA_SBITERR (1<<2) /* reserved on 2410a/2440 */
|
||||
#define S3C2410_SDIDSTA_TXDATAON (1<<1)
|
||||
#define S3C2410_SDIDSTA_RXDATAON (1<<0)
|
||||
|
||||
#define S3C2440_SDIFSTA_FIFORESET (1<<16)
|
||||
#define S3C2440_SDIFSTA_FIFOFAIL (3<<14) /* 3 is correct (2 bits) */
|
||||
#define S3C2410_SDIFSTA_TFDET (1<<13)
|
||||
#define S3C2410_SDIFSTA_RFDET (1<<12)
|
||||
#define S3C2410_SDIFSTA_TFHALF (1<<11)
|
||||
#define S3C2410_SDIFSTA_TFEMPTY (1<<10)
|
||||
#define S3C2410_SDIFSTA_RFLAST (1<<9)
|
||||
#define S3C2410_SDIFSTA_RFFULL (1<<8)
|
||||
#define S3C2410_SDIFSTA_RFHALF (1<<7)
|
||||
#define S3C2410_SDIFSTA_COUNTMASK (0x7f)
|
||||
|
||||
#define S3C2410_SDIIMSK_RESPONSECRC (1<<17)
|
||||
#define S3C2410_SDIIMSK_CMDSENT (1<<16)
|
||||
#define S3C2410_SDIIMSK_CMDTIMEOUT (1<<15)
|
||||
#define S3C2410_SDIIMSK_RESPONSEND (1<<14)
|
||||
#define S3C2410_SDIIMSK_READWAIT (1<<13)
|
||||
#define S3C2410_SDIIMSK_SDIOIRQ (1<<12)
|
||||
#define S3C2410_SDIIMSK_FIFOFAIL (1<<11)
|
||||
#define S3C2410_SDIIMSK_CRCSTATUS (1<<10)
|
||||
#define S3C2410_SDIIMSK_DATACRC (1<<9)
|
||||
#define S3C2410_SDIIMSK_DATATIMEOUT (1<<8)
|
||||
#define S3C2410_SDIIMSK_DATAFINISH (1<<7)
|
||||
#define S3C2410_SDIIMSK_BUSYFINISH (1<<6)
|
||||
#define S3C2410_SDIIMSK_SBITERR (1<<5) /* reserved 2440/2410a */
|
||||
#define S3C2410_SDIIMSK_TXFIFOHALF (1<<4)
|
||||
#define S3C2410_SDIIMSK_TXFIFOEMPTY (1<<3)
|
||||
#define S3C2410_SDIIMSK_RXFIFOLAST (1<<2)
|
||||
#define S3C2410_SDIIMSK_RXFIFOFULL (1<<1)
|
||||
#define S3C2410_SDIIMSK_RXFIFOHALF (1<<0)
|
||||
|
||||
#endif /* __ASM_ARM_REGS_SDI */
|
1394
qiboot/include/s3c6410.h
Normal file
1394
qiboot/include/s3c6410.h
Normal file
File diff suppressed because it is too large
Load Diff
72
qiboot/include/serial-s3c24xx.h
Normal file
72
qiboot/include/serial-s3c24xx.h
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
* Author: xiangfu liu <xiangfu@openmoko.org>
|
||||
*
|
||||
* Configuation settings for the FIC Neo GTA02 Linux GSM phone
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __SERIAL_S3C24XX_H__
|
||||
#define __SERIAL_S3C24XX_H__
|
||||
|
||||
#define UART0 0
|
||||
#define UART1 1
|
||||
#define UART2 2
|
||||
|
||||
#define rGPHCON (*(volatile unsigned *)0x56000070) /*UART 0 Line control*/
|
||||
|
||||
#define rULCON0 (*(volatile unsigned *)0x50000000) /*UART 0 Line control*/
|
||||
#define rUCON0 (*(volatile unsigned *)0x50000004) /*UART 0 Control*/
|
||||
#define rUFCON0 (*(volatile unsigned *)0x50000008) /*UART 0 FIFO control*/
|
||||
#define rUMCON0 (*(volatile unsigned *)0x5000000c) /*UART 0 Modem control*/
|
||||
#define rUTRSTAT0 (*(volatile unsigned *)0x50000010) /*UART 0 Tx/Rx status*/
|
||||
#define rUERSTAT0 (*(volatile unsigned *)0x50000014) /*UART 0 Rx error status*/
|
||||
#define rUFSTAT0 (*(volatile unsigned *)0x50000018) /*UART 0 FIFO status*/
|
||||
#define rUMSTAT0 (*(volatile unsigned *)0x5000001c) /*UART 0 Modem status*/
|
||||
#define rUBRDIV0 (*(volatile unsigned *)0x50000028) /*UART 0 Baud rate divisor*/
|
||||
|
||||
#define rULCON1 (*(volatile unsigned *)0x50004000) /*UART 1 Line control*/
|
||||
#define rUCON1 (*(volatile unsigned *)0x50004004) /*UART 1 Control*/
|
||||
#define rUFCON1 (*(volatile unsigned *)0x50004008) /*UART 1 FIFO control*/
|
||||
#define rUMCON1 (*(volatile unsigned *)0x5000400c) /*UART 1 Modem control*/
|
||||
#define rUTRSTAT1 (*(volatile unsigned *)0x50004010) /*UART 1 Tx/Rx status*/
|
||||
#define rUERSTAT1 (*(volatile unsigned *)0x50004014) /*UART 1 Rx error status*/
|
||||
#define rUFSTAT1 (*(volatile unsigned *)0x50004018) /*UART 1 FIFO status*/
|
||||
#define rUMSTAT1 (*(volatile unsigned *)0x5000401c) /*UART 1 Modem status*/
|
||||
#define rUBRDIV1 (*(volatile unsigned *)0x50004028) /*UART 1 Baud rate divisor*/
|
||||
|
||||
#define rULCON2 (*(volatile unsigned *)0x50008000) /*UART 2 Line control*/
|
||||
#define rUCON2 (*(volatile unsigned *)0x50008004) /*UART 2 Control*/
|
||||
#define rUFCON2 (*(volatile unsigned *)0x50008008) /*UART 2 FIFO control*/
|
||||
#define rUTRSTAT2 (*(volatile unsigned *)0x50008010) /*UART 2 Tx/Rx status*/
|
||||
#define rUERSTAT2 (*(volatile unsigned *)0x50008014) /*UART 2 Rx error status*/
|
||||
#define rUFSTAT2 (*(volatile unsigned *)0x50008018) /*UART 2 FIFO status*/
|
||||
#define rUBRDIV2 (*(volatile unsigned *)0x50008028) /*UART 2 Baud rate divisor*/
|
||||
|
||||
#define WrUTXH0(ch) (*(volatile unsigned char *)0x50000020)=(unsigned char)(ch)
|
||||
#define RdURXH0() (*(volatile unsigned char *)0x50000024)
|
||||
#define WrUTXH1(ch) (*(volatile unsigned char *)0x50004020)=(unsigned char)(ch)
|
||||
#define RdURXH1() (*(volatile unsigned char *)0x50004024)
|
||||
#define WrUTXH2(ch) (*(volatile unsigned char *)0x50008020)=(unsigned char)(ch)
|
||||
#define RdURXH2() (*(volatile unsigned char *)0x50008024)
|
||||
|
||||
extern void serial_init_115200_s3c24xx(const int uart, const int pclk_MHz);
|
||||
extern void serial_putc_s3c24xx(const int uart, const char c);
|
||||
extern int puts(const char *string);
|
||||
|
||||
#endif
|
72
qiboot/include/serial-s3c64xx.h
Normal file
72
qiboot/include/serial-s3c64xx.h
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
* Author: xiangfu liu <xiangfu@openmoko.org>
|
||||
*
|
||||
* Configuation settings for the FIC Neo GTA02 Linux GSM phone
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __SERIAL_S3C64XX_H__
|
||||
#define __SERIAL_S3C64XX_H__
|
||||
|
||||
#define UART0 0
|
||||
#define UART1 1
|
||||
#define UART2 2
|
||||
|
||||
#define rGPHCON (*(volatile unsigned *)0x56000070) /*UART 0 Line control*/
|
||||
|
||||
#define rULCON0 (*(volatile unsigned *)0x50000000) /*UART 0 Line control*/
|
||||
#define rUCON0 (*(volatile unsigned *)0x50000004) /*UART 0 Control*/
|
||||
#define rUFCON0 (*(volatile unsigned *)0x50000008) /*UART 0 FIFO control*/
|
||||
#define rUMCON0 (*(volatile unsigned *)0x5000000c) /*UART 0 Modem control*/
|
||||
#define rUTRSTAT0 (*(volatile unsigned *)0x50000010) /*UART 0 Tx/Rx status*/
|
||||
#define rUERSTAT0 (*(volatile unsigned *)0x50000014) /*UART 0 Rx error status*/
|
||||
#define rUFSTAT0 (*(volatile unsigned *)0x50000018) /*UART 0 FIFO status*/
|
||||
#define rUMSTAT0 (*(volatile unsigned *)0x5000001c) /*UART 0 Modem status*/
|
||||
#define rUBRDIV0 (*(volatile unsigned *)0x50000028) /*UART 0 Baud rate divisor*/
|
||||
|
||||
#define rULCON1 (*(volatile unsigned *)0x50004000) /*UART 1 Line control*/
|
||||
#define rUCON1 (*(volatile unsigned *)0x50004004) /*UART 1 Control*/
|
||||
#define rUFCON1 (*(volatile unsigned *)0x50004008) /*UART 1 FIFO control*/
|
||||
#define rUMCON1 (*(volatile unsigned *)0x5000400c) /*UART 1 Modem control*/
|
||||
#define rUTRSTAT1 (*(volatile unsigned *)0x50004010) /*UART 1 Tx/Rx status*/
|
||||
#define rUERSTAT1 (*(volatile unsigned *)0x50004014) /*UART 1 Rx error status*/
|
||||
#define rUFSTAT1 (*(volatile unsigned *)0x50004018) /*UART 1 FIFO status*/
|
||||
#define rUMSTAT1 (*(volatile unsigned *)0x5000401c) /*UART 1 Modem status*/
|
||||
#define rUBRDIV1 (*(volatile unsigned *)0x50004028) /*UART 1 Baud rate divisor*/
|
||||
|
||||
#define rULCON2 (*(volatile unsigned *)0x50008000) /*UART 2 Line control*/
|
||||
#define rUCON2 (*(volatile unsigned *)0x50008004) /*UART 2 Control*/
|
||||
#define rUFCON2 (*(volatile unsigned *)0x50008008) /*UART 2 FIFO control*/
|
||||
#define rUTRSTAT2 (*(volatile unsigned *)0x50008010) /*UART 2 Tx/Rx status*/
|
||||
#define rUERSTAT2 (*(volatile unsigned *)0x50008014) /*UART 2 Rx error status*/
|
||||
#define rUFSTAT2 (*(volatile unsigned *)0x50008018) /*UART 2 FIFO status*/
|
||||
#define rUBRDIV2 (*(volatile unsigned *)0x50008028) /*UART 2 Baud rate divisor*/
|
||||
|
||||
#define WrUTXH0(ch) (*(volatile unsigned char *)0x50000020)=(unsigned char)(ch)
|
||||
#define RdURXH0() (*(volatile unsigned char *)0x50000024)
|
||||
#define WrUTXH1(ch) (*(volatile unsigned char *)0x50004020)=(unsigned char)(ch)
|
||||
#define RdURXH1() (*(volatile unsigned char *)0x50004024)
|
||||
#define WrUTXH2(ch) (*(volatile unsigned char *)0x50008020)=(unsigned char)(ch)
|
||||
#define RdURXH2() (*(volatile unsigned char *)0x50008024)
|
||||
|
||||
extern void serial_init_115200_s3c64xx(const int uart, const int pclk_MHz);
|
||||
extern void serial_putc_s3c64xx(const int uart, const char c);
|
||||
extern int puts(const char *string);
|
||||
|
||||
#endif
|
269
qiboot/include/setup.h
Normal file
269
qiboot/include/setup.h
Normal file
@ -0,0 +1,269 @@
|
||||
/*
|
||||
* linux/include/asm/setup.h
|
||||
*
|
||||
* Copyright (C) 1997-1999 Russell King
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Structure passed to kernel to tell it about the
|
||||
* hardware it's running on. See linux/Documentation/arm/Setup
|
||||
* for more info.
|
||||
*
|
||||
* NOTE:
|
||||
* This file contains two ways to pass information from the boot
|
||||
* loader to the kernel. The old struct param_struct is deprecated,
|
||||
* but it will be kept in the kernel for 5 years from now
|
||||
* (2001). This will allow boot loaders to convert to the new struct
|
||||
* tag way.
|
||||
*/
|
||||
#ifndef __ASMARM_SETUP_H
|
||||
#define __ASMARM_SETUP_H
|
||||
|
||||
/*
|
||||
* Usage:
|
||||
* - do not go blindly adding fields, add them at the end
|
||||
* - when adding fields, don't rely on the address until
|
||||
* a patch from me has been released
|
||||
* - unused fields should be zero (for future expansion)
|
||||
* - this structure is relatively short-lived - only
|
||||
* guaranteed to contain useful data in setup_arch()
|
||||
*/
|
||||
#define COMMAND_LINE_SIZE 1024
|
||||
|
||||
/* This is the old deprecated way to pass parameters to the kernel */
|
||||
struct param_struct {
|
||||
union {
|
||||
struct {
|
||||
unsigned long page_size; /* 0 */
|
||||
unsigned long nr_pages; /* 4 */
|
||||
unsigned long ramdisk_size; /* 8 */
|
||||
unsigned long flags; /* 12 */
|
||||
#define FLAG_READONLY 1
|
||||
#define FLAG_RDLOAD 4
|
||||
#define FLAG_RDPROMPT 8
|
||||
unsigned long rootdev; /* 16 */
|
||||
unsigned long video_num_cols; /* 20 */
|
||||
unsigned long video_num_rows; /* 24 */
|
||||
unsigned long video_x; /* 28 */
|
||||
unsigned long video_y; /* 32 */
|
||||
unsigned long memc_control_reg; /* 36 */
|
||||
unsigned char sounddefault; /* 40 */
|
||||
unsigned char adfsdrives; /* 41 */
|
||||
unsigned char bytes_per_char_h; /* 42 */
|
||||
unsigned char bytes_per_char_v; /* 43 */
|
||||
unsigned long pages_in_bank[4]; /* 44 */
|
||||
unsigned long pages_in_vram; /* 60 */
|
||||
unsigned long initrd_start; /* 64 */
|
||||
unsigned long initrd_size; /* 68 */
|
||||
unsigned long rd_start; /* 72 */
|
||||
unsigned long system_rev; /* 76 */
|
||||
unsigned long system_serial_low; /* 80 */
|
||||
unsigned long system_serial_high; /* 84 */
|
||||
unsigned long mem_fclk_21285; /* 88 */
|
||||
} s;
|
||||
char unused[256];
|
||||
} u1;
|
||||
union {
|
||||
char paths[8][128];
|
||||
struct {
|
||||
unsigned long magic;
|
||||
char n[1024 - sizeof(unsigned long)];
|
||||
} s;
|
||||
} u2;
|
||||
char commandline[COMMAND_LINE_SIZE];
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* The new way of passing information: a list of tagged entries
|
||||
*/
|
||||
|
||||
/* The list ends with an ATAG_NONE node. */
|
||||
#define ATAG_NONE 0x00000000
|
||||
|
||||
struct tag_header {
|
||||
u32 size;
|
||||
u32 tag;
|
||||
};
|
||||
|
||||
/* The list must start with an ATAG_CORE node */
|
||||
#define ATAG_CORE 0x54410001
|
||||
|
||||
struct tag_core {
|
||||
u32 flags; /* bit 0 = read-only */
|
||||
u32 pagesize;
|
||||
u32 rootdev;
|
||||
};
|
||||
|
||||
/* it is allowed to have multiple ATAG_MEM nodes */
|
||||
#define ATAG_MEM 0x54410002
|
||||
|
||||
struct tag_mem32 {
|
||||
u32 size;
|
||||
u32 start; /* physical start address */
|
||||
};
|
||||
|
||||
/* VGA text type displays */
|
||||
#define ATAG_VIDEOTEXT 0x54410003
|
||||
|
||||
struct tag_videotext {
|
||||
u8 x;
|
||||
u8 y;
|
||||
u16 video_page;
|
||||
u8 video_mode;
|
||||
u8 video_cols;
|
||||
u16 video_ega_bx;
|
||||
u8 video_lines;
|
||||
u8 video_isvga;
|
||||
u16 video_points;
|
||||
};
|
||||
|
||||
/* describes how the ramdisk will be used in kernel */
|
||||
#define ATAG_RAMDISK 0x54410004
|
||||
|
||||
struct tag_ramdisk {
|
||||
u32 flags; /* bit 0 = load, bit 1 = prompt */
|
||||
u32 size; /* decompressed ramdisk size in _kilo_ bytes */
|
||||
u32 start; /* starting block of floppy-based RAM disk image */
|
||||
};
|
||||
|
||||
/* describes where the compressed ramdisk image lives (virtual address) */
|
||||
/*
|
||||
* this one accidentally used virtual addresses - as such,
|
||||
* its depreciated.
|
||||
*/
|
||||
#define ATAG_INITRD 0x54410005
|
||||
|
||||
/* describes where the compressed ramdisk image lives (physical address) */
|
||||
#define ATAG_INITRD2 0x54420005
|
||||
|
||||
struct tag_initrd {
|
||||
u32 start; /* physical start address */
|
||||
u32 size; /* size of compressed ramdisk image in bytes */
|
||||
};
|
||||
|
||||
/* board serial number. "64 bits should be enough for everybody" */
|
||||
#define ATAG_SERIAL 0x54410006
|
||||
|
||||
struct tag_serialnr {
|
||||
u32 low;
|
||||
u32 high;
|
||||
};
|
||||
|
||||
/* board revision */
|
||||
#define ATAG_REVISION 0x54410007
|
||||
|
||||
struct tag_revision {
|
||||
u32 rev;
|
||||
};
|
||||
|
||||
/* initial values for vesafb-type framebuffers. see struct screen_info
|
||||
* in include/linux/tty.h
|
||||
*/
|
||||
#define ATAG_VIDEOLFB 0x54410008
|
||||
|
||||
struct tag_videolfb {
|
||||
u16 lfb_width;
|
||||
u16 lfb_height;
|
||||
u16 lfb_depth;
|
||||
u16 lfb_linelength;
|
||||
u32 lfb_base;
|
||||
u32 lfb_size;
|
||||
u8 red_size;
|
||||
u8 red_pos;
|
||||
u8 green_size;
|
||||
u8 green_pos;
|
||||
u8 blue_size;
|
||||
u8 blue_pos;
|
||||
u8 rsvd_size;
|
||||
u8 rsvd_pos;
|
||||
};
|
||||
|
||||
/* command line: \0 terminated string */
|
||||
#define ATAG_CMDLINE 0x54410009
|
||||
|
||||
struct tag_cmdline {
|
||||
char cmdline[1]; /* this is the minimum size */
|
||||
};
|
||||
|
||||
/* acorn RiscPC specific information */
|
||||
#define ATAG_ACORN 0x41000101
|
||||
|
||||
struct tag_acorn {
|
||||
u32 memc_control_reg;
|
||||
u32 vram_pages;
|
||||
u8 sounddefault;
|
||||
u8 adfsdrives;
|
||||
};
|
||||
|
||||
/* footbridge memory clock, see arch/arm/mach-footbridge/arch.c */
|
||||
#define ATAG_MEMCLK 0x41000402
|
||||
|
||||
struct tag_memclk {
|
||||
u32 fmemclk;
|
||||
};
|
||||
|
||||
struct tag {
|
||||
struct tag_header hdr;
|
||||
union {
|
||||
struct tag_core core;
|
||||
struct tag_mem32 mem;
|
||||
struct tag_videotext videotext;
|
||||
struct tag_ramdisk ramdisk;
|
||||
struct tag_initrd initrd;
|
||||
struct tag_serialnr serialnr;
|
||||
struct tag_revision revision;
|
||||
struct tag_videolfb videolfb;
|
||||
struct tag_cmdline cmdline;
|
||||
|
||||
/*
|
||||
* Acorn specific
|
||||
*/
|
||||
struct tag_acorn acorn;
|
||||
|
||||
/*
|
||||
* DC21285 specific
|
||||
*/
|
||||
struct tag_memclk memclk;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct tagtable {
|
||||
u32 tag;
|
||||
int (*parse)(const struct tag *);
|
||||
};
|
||||
|
||||
#define __tag __attribute__((unused, __section__(".taglist")))
|
||||
#define __tagtable(tag, fn) \
|
||||
static struct tagtable __tagtable_##fn __tag = { tag, fn }
|
||||
|
||||
#define tag_member_present(tag,member) \
|
||||
((unsigned long)(&((struct tag *)0L)->member + 1) \
|
||||
<= (tag)->hdr.size * 4)
|
||||
|
||||
#define tag_next(t) ((struct tag *)((u32 *)(t) + (t)->hdr.size))
|
||||
#define tag_size(type) ((sizeof(struct tag_header) + sizeof(struct type)) >> 2)
|
||||
|
||||
#define for_each_tag(t,base) \
|
||||
for (t = base; t->hdr.size; t = tag_next(t))
|
||||
|
||||
/*
|
||||
* Memory map description
|
||||
*/
|
||||
#define NR_BANKS 8
|
||||
|
||||
struct meminfo {
|
||||
int nr_banks;
|
||||
unsigned long end;
|
||||
struct {
|
||||
unsigned long start;
|
||||
unsigned long size;
|
||||
int node;
|
||||
} bank[NR_BANKS];
|
||||
};
|
||||
|
||||
extern struct meminfo meminfo;
|
||||
|
||||
#endif
|
6
qiboot/include/smdk6410.h
Normal file
6
qiboot/include/smdk6410.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef __ASM_MODE__
|
||||
#include <qi.h>
|
||||
extern const struct board_api board_api_smdk6410;
|
||||
#endif
|
||||
|
||||
#define TEXT_BASE_SMDK6410 0x53000000
|
16
qiboot/openocd-openmoko-debug-6410.cfg
Normal file
16
qiboot/openocd-openmoko-debug-6410.cfg
Normal file
@ -0,0 +1,16 @@
|
||||
# ARM1176 / s3c6410 OpenOCD config suitable for Openmoko Debug board usage
|
||||
|
||||
telnet_port 4444
|
||||
gdb_port 3333
|
||||
interface ft2232
|
||||
jtag_speed 18
|
||||
ft2232_layout oocdlink
|
||||
|
||||
#Info: 446 309386 jtag.c:1410 jtag_examine_chain(): JTAG device found: 0x2b900f0f (Manufacturer: 0x787, Part: 0xb900, Version: 0x2)
|
||||
#Info: 447 309386 jtag.c:1410 jtag_examine_chain(): JTAG device found: 0x07b76f0f (Manufacturer: 0x787, Part: 0x7b76, Version: 0x0)
|
||||
jtag_device 4 0x1 0xF 0xE
|
||||
jtag_device 5 0x1 0x1F 0x1E
|
||||
|
||||
reset_config trst_and_srst
|
||||
target create target0 arm11 -endian little -chain-position 1 -variant arm11
|
||||
|
90
qiboot/src/blink_led.c
Normal file
90
qiboot/src/blink_led.c
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
* Author: xiangfu liu <xiangfu@openmoko.org>
|
||||
*
|
||||
* Configuation settings for the FIC Neo GTA02 Linux GSM phone
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "blink_led.h"
|
||||
|
||||
int delay(int time)
|
||||
{
|
||||
int i=0;
|
||||
for(i=0;i<time;i++);
|
||||
return 0;
|
||||
}
|
||||
int set_GPB(void)
|
||||
{
|
||||
GPBCON = 0x5;
|
||||
GPBDW = 0xffff;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int orange_on(int times)
|
||||
{
|
||||
int count=0;
|
||||
set_GPB();
|
||||
|
||||
for(count=0;count<times;count++)
|
||||
{
|
||||
ORANGE_ON();
|
||||
delay(0xfffff);
|
||||
ORANGE_OFF() ;
|
||||
delay(0xfffff);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blue_on(int times)
|
||||
{
|
||||
int count=0;
|
||||
set_GPB();
|
||||
|
||||
for(count=0;count<times;count++)
|
||||
{
|
||||
BLUE_ON();
|
||||
delay(0xfffff);
|
||||
BLUE_OFF();
|
||||
delay(0xfffff);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blink_led(void)
|
||||
{
|
||||
set_GPB();
|
||||
|
||||
while(1)
|
||||
{
|
||||
ORANGE_ON();
|
||||
delay(0xfffff);
|
||||
ORANGE_OFF() ;
|
||||
delay(0xfffff);
|
||||
|
||||
BLUE_ON();
|
||||
delay(0xfffff);
|
||||
BLUE_OFF();
|
||||
delay(0xfffff);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
39
qiboot/src/blink_led.h
Normal file
39
qiboot/src/blink_led.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
* Author: xiangfu liu <xiangfu@openmoko.org>
|
||||
*
|
||||
* Configuation settings for the FIC Neo GTA02 Linux GSM phone
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __BLINK_LED_H
|
||||
#define __BLINK_LED_H
|
||||
|
||||
#define GPBCON (*(volatile unsigned *)0x56000010)
|
||||
#define GPBDAT (*(volatile unsigned *)0x56000014)
|
||||
#define GPBDW (*(volatile unsigned *)0x56000018)
|
||||
#define ORANGE_OFF() (GPBDAT &= ~(0x1))
|
||||
#define BLUE_OFF() (GPBDAT &= ~(0x2))
|
||||
#define ORANGE_ON() (GPBDAT |= (0x1))
|
||||
#define BLUE_ON() (GPBDAT |= (0x2))
|
||||
|
||||
int orange_on(int times);
|
||||
int blue_on(int times);
|
||||
int blink_led(void);
|
||||
int delay(int time);
|
||||
|
||||
#endif /* __BLINK_LED_H */
|
681
qiboot/src/common.h
Normal file
681
qiboot/src/common.h
Normal file
@ -0,0 +1,681 @@
|
||||
/*
|
||||
* (C) Copyright 2000-2007
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __COMMON_H_
|
||||
#define __COMMON_H_ 1
|
||||
|
||||
#undef _LINUX_CONFIG_H
|
||||
#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */
|
||||
|
||||
typedef unsigned char uchar;
|
||||
typedef volatile unsigned long vu_long;
|
||||
typedef volatile unsigned short vu_short;
|
||||
typedef volatile unsigned char vu_char;
|
||||
|
||||
#include <config.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/string.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <stdarg.h>
|
||||
#if defined(CONFIG_PCI) && (defined(CONFIG_4xx) && !defined(CONFIG_AP1000))
|
||||
#include <pci.h>
|
||||
#endif
|
||||
#if defined(CONFIG_8xx)
|
||||
#include <asm/8xx_immap.h>
|
||||
#if defined(CONFIG_MPC852) || defined(CONFIG_MPC852T) || \
|
||||
defined(CONFIG_MPC859) || defined(CONFIG_MPC859T) || \
|
||||
defined(CONFIG_MPC859DSL) || \
|
||||
defined(CONFIG_MPC866) || defined(CONFIG_MPC866T) || \
|
||||
defined(CONFIG_MPC866P)
|
||||
# define CONFIG_MPC866_FAMILY 1
|
||||
#elif defined(CONFIG_MPC870) \
|
||||
|| defined(CONFIG_MPC875) \
|
||||
|| defined(CONFIG_MPC880) \
|
||||
|| defined(CONFIG_MPC885)
|
||||
# define CONFIG_MPC885_FAMILY 1
|
||||
#endif
|
||||
#if defined(CONFIG_MPC860) \
|
||||
|| defined(CONFIG_MPC860T) \
|
||||
|| defined(CONFIG_MPC866_FAMILY) \
|
||||
|| defined(CONFIG_MPC885_FAMILY)
|
||||
# define CONFIG_MPC86x 1
|
||||
#endif
|
||||
#elif defined(CONFIG_5xx)
|
||||
#include <asm/5xx_immap.h>
|
||||
#elif defined(CONFIG_MPC5xxx)
|
||||
#include <mpc5xxx.h>
|
||||
#elif defined(CONFIG_MPC512X)
|
||||
#include <mpc512x.h>
|
||||
#include <asm/immap_512x.h>
|
||||
#elif defined(CONFIG_MPC8220)
|
||||
#include <asm/immap_8220.h>
|
||||
#elif defined(CONFIG_8260)
|
||||
#if defined(CONFIG_MPC8247) \
|
||||
|| defined(CONFIG_MPC8248) \
|
||||
|| defined(CONFIG_MPC8271) \
|
||||
|| defined(CONFIG_MPC8272)
|
||||
#define CONFIG_MPC8272_FAMILY 1
|
||||
#endif
|
||||
#if defined(CONFIG_MPC8272_FAMILY)
|
||||
#define CONFIG_MPC8260 1
|
||||
#endif
|
||||
#include <asm/immap_8260.h>
|
||||
#endif
|
||||
#ifdef CONFIG_MPC86xx
|
||||
#include <mpc86xx.h>
|
||||
#include <asm/immap_86xx.h>
|
||||
#endif
|
||||
#ifdef CONFIG_MPC85xx
|
||||
#include <mpc85xx.h>
|
||||
#include <asm/immap_85xx.h>
|
||||
#endif
|
||||
#ifdef CONFIG_MPC83XX
|
||||
#include <mpc83xx.h>
|
||||
#include <asm/immap_83xx.h>
|
||||
#endif
|
||||
#ifdef CONFIG_4xx
|
||||
#include <ppc4xx.h>
|
||||
#endif
|
||||
#ifdef CONFIG_HYMOD
|
||||
#include <board/hymod/hymod.h>
|
||||
#endif
|
||||
#ifdef CONFIG_ARM
|
||||
#define asmlinkage /* nothing */
|
||||
#endif
|
||||
#ifdef CONFIG_BLACKFIN
|
||||
#include <asm/blackfin.h>
|
||||
#endif
|
||||
|
||||
#include <part.h>
|
||||
#include <flash.h>
|
||||
#include <image.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#define debug(fmt,args...) printf (fmt ,##args)
|
||||
#define debugX(level,fmt,args...) if (DEBUG>=level) printf(fmt,##args);
|
||||
#else
|
||||
#define debug(fmt,args...)
|
||||
#define debugX(level,fmt,args...)
|
||||
#endif /* DEBUG */
|
||||
|
||||
#define BUG() do { \
|
||||
printf("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __FUNCTION__); \
|
||||
panic("BUG!"); \
|
||||
} while (0)
|
||||
#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
|
||||
|
||||
typedef void (interrupt_handler_t)(void *);
|
||||
|
||||
#include <asm/u-boot.h> /* boot information for Linux kernel */
|
||||
#include <asm/global_data.h> /* global data used for startup functions */
|
||||
|
||||
/*
|
||||
* enable common handling for all TQM8xxL/M boards:
|
||||
* - CONFIG_TQM8xxM will be defined for all TQM8xxM boards
|
||||
* - CONFIG_TQM8xxL will be defined for all TQM8xxL _and_ TQM8xxM boards
|
||||
* and for the TQM885D board
|
||||
*/
|
||||
#if defined(CONFIG_TQM823M) || defined(CONFIG_TQM850M) || \
|
||||
defined(CONFIG_TQM855M) || defined(CONFIG_TQM860M) || \
|
||||
defined(CONFIG_TQM862M) || defined(CONFIG_TQM866M)
|
||||
# ifndef CONFIG_TQM8xxM
|
||||
# define CONFIG_TQM8xxM
|
||||
# endif
|
||||
#endif
|
||||
#if defined(CONFIG_TQM823L) || defined(CONFIG_TQM850L) || \
|
||||
defined(CONFIG_TQM855L) || defined(CONFIG_TQM860L) || \
|
||||
defined(CONFIG_TQM862L) || defined(CONFIG_TQM8xxM) || \
|
||||
defined(CONFIG_TQM885D)
|
||||
# ifndef CONFIG_TQM8xxL
|
||||
# define CONFIG_TQM8xxL
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SERIAL_MULTI
|
||||
|
||||
#if defined(CONFIG_8xx_CONS_SMC1) || defined(CONFIG_8xx_CONS_SMC2) \
|
||||
|| defined(CONFIG_8xx_CONS_SCC1) || defined(CONFIG_8xx_CONS_SCC2) \
|
||||
|| defined(CONFIG_8xx_CONS_SCC3) || defined(CONFIG_8xx_CONS_SCC4)
|
||||
|
||||
#define CONFIG_SERIAL_MULTI 1
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_SERIAL_MULTI */
|
||||
|
||||
/*
|
||||
* General Purpose Utilities
|
||||
*/
|
||||
#define min(X, Y) \
|
||||
({ typeof (X) __x = (X), __y = (Y); \
|
||||
(__x < __y) ? __x : __y; })
|
||||
|
||||
#define max(X, Y) \
|
||||
({ typeof (X) __x = (X), __y = (Y); \
|
||||
(__x > __y) ? __x : __y; })
|
||||
|
||||
|
||||
/*
|
||||
* Function Prototypes
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SERIAL_SOFTWARE_FIFO
|
||||
void serial_buffered_init (void);
|
||||
void serial_buffered_putc (const char);
|
||||
void serial_buffered_puts (const char *);
|
||||
int serial_buffered_getc (void);
|
||||
int serial_buffered_tstc (void);
|
||||
#endif /* CONFIG_SERIAL_SOFTWARE_FIFO */
|
||||
|
||||
void hang (void) __attribute__ ((noreturn));
|
||||
|
||||
/* */
|
||||
long int initdram (int);
|
||||
int display_options (void);
|
||||
void print_size (ulong, const char *);
|
||||
int print_buffer (ulong addr, void* data, uint width, uint count, uint linelen);
|
||||
|
||||
/* common/main.c */
|
||||
void main_loop (void);
|
||||
int run_command (const char *cmd, int flag);
|
||||
int readline (const char *const prompt);
|
||||
int readline_into_buffer (const char *const prompt, char * buffer);
|
||||
int parse_line (char *, char *[]);
|
||||
void init_cmd_timeout(void);
|
||||
void reset_cmd_timeout(void);
|
||||
|
||||
/* lib_$(ARCH)/board.c */
|
||||
void board_init_f (ulong) __attribute__ ((noreturn));
|
||||
void board_init_r (gd_t *, ulong) __attribute__ ((noreturn));
|
||||
int checkboard (void);
|
||||
int checkflash (void);
|
||||
int checkdram (void);
|
||||
char * strmhz(char *buf, long hz);
|
||||
int last_stage_init(void);
|
||||
extern ulong monitor_flash_len;
|
||||
#ifdef CFG_ID_EEPROM
|
||||
int mac_read_from_eeprom(void);
|
||||
#endif
|
||||
|
||||
/* common/flash.c */
|
||||
void flash_perror (int);
|
||||
|
||||
/* common/cmd_autoscript.c */
|
||||
int autoscript (ulong addr, const char *fit_uname);
|
||||
|
||||
extern ulong load_addr; /* Default Load Address */
|
||||
|
||||
/* common/cmd_nvedit.c */
|
||||
int env_init (void);
|
||||
void env_relocate (void);
|
||||
int envmatch (uchar *, int);
|
||||
char *getenv (char *);
|
||||
int getenv_r (char *name, char *buf, unsigned len);
|
||||
int saveenv (void);
|
||||
#ifdef CONFIG_PPC /* ARM version to be fixed! */
|
||||
void inline setenv (char *, char *);
|
||||
#else
|
||||
void setenv (char *, char *);
|
||||
#ifdef CONFIG_HAS_UID
|
||||
void forceenv (char *, char *);
|
||||
#endif
|
||||
#endif /* CONFIG_PPC */
|
||||
#ifdef CONFIG_ARM
|
||||
# include <asm/mach-types.h>
|
||||
# include <asm/setup.h>
|
||||
# include <asm/u-boot-arm.h> /* ARM version to be fixed! */
|
||||
#endif /* CONFIG_ARM */
|
||||
#ifdef CONFIG_I386 /* x86 version to be fixed! */
|
||||
# include <asm/u-boot-i386.h>
|
||||
#endif /* CONFIG_I386 */
|
||||
|
||||
#ifdef CONFIG_AUTO_COMPLETE
|
||||
int env_complete(char *var, int maxv, char *cmdv[], int maxsz, char *buf);
|
||||
#endif
|
||||
|
||||
void pci_init (void);
|
||||
void pci_init_board(void);
|
||||
void pciinfo (int, int);
|
||||
|
||||
#if defined(CONFIG_PCI) && (defined(CONFIG_4xx) && !defined(CONFIG_AP1000))
|
||||
int pci_pre_init (struct pci_controller * );
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_PCI) && (defined(CONFIG_440) || defined(CONFIG_405EX))
|
||||
# if defined(CFG_PCI_TARGET_INIT)
|
||||
void pci_target_init (struct pci_controller *);
|
||||
# endif
|
||||
# if defined(CFG_PCI_MASTER_INIT)
|
||||
void pci_master_init (struct pci_controller *);
|
||||
# endif
|
||||
int is_pci_host (struct pci_controller *);
|
||||
#if defined(CONFIG_440SPE) || \
|
||||
defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
|
||||
defined(CONFIG_405EX)
|
||||
void pcie_setup_hoses(int busno);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int misc_init_f (void);
|
||||
int misc_init_r (void);
|
||||
|
||||
/* common/exports.c */
|
||||
void jumptable_init(void);
|
||||
|
||||
/* api/api.c */
|
||||
void api_init (void);
|
||||
|
||||
/* common/memsize.c */
|
||||
long get_ram_size (volatile long *, long);
|
||||
|
||||
/* $(BOARD)/$(BOARD).c */
|
||||
void reset_phy (void);
|
||||
void fdc_hw_init (void);
|
||||
|
||||
/* $(BOARD)/eeprom.c */
|
||||
void eeprom_init (void);
|
||||
#ifndef CONFIG_SPI
|
||||
int eeprom_probe (unsigned dev_addr, unsigned offset);
|
||||
#endif
|
||||
int eeprom_read (unsigned dev_addr, unsigned offset, uchar *buffer, unsigned cnt);
|
||||
int eeprom_write (unsigned dev_addr, unsigned offset, uchar *buffer, unsigned cnt);
|
||||
#ifdef CONFIG_LWMON
|
||||
extern uchar pic_read (uchar reg);
|
||||
extern void pic_write (uchar reg, uchar val);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set this up regardless of board
|
||||
* type, to prevent errors.
|
||||
*/
|
||||
#if defined(CONFIG_SPI) || !defined(CFG_I2C_EEPROM_ADDR)
|
||||
# define CFG_DEF_EEPROM_ADDR 0
|
||||
#else
|
||||
# define CFG_DEF_EEPROM_ADDR CFG_I2C_EEPROM_ADDR
|
||||
#endif /* CONFIG_SPI || !defined(CFG_I2C_EEPROM_ADDR) */
|
||||
|
||||
#if defined(CONFIG_SPI)
|
||||
extern void spi_init_f (void);
|
||||
extern void spi_init_r (void);
|
||||
extern ssize_t spi_read (uchar *, int, uchar *, int);
|
||||
extern ssize_t spi_write (uchar *, int, uchar *, int);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_RPXCLASSIC
|
||||
void rpxclassic_init (void);
|
||||
#endif
|
||||
|
||||
void rpxlite_init (void);
|
||||
|
||||
#ifdef CONFIG_MBX
|
||||
/* $(BOARD)/mbx8xx.c */
|
||||
void mbx_init (void);
|
||||
void board_serial_init (void);
|
||||
void board_ether_init (void);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_RPXCLASSIC) || defined(CONFIG_MBX) || \
|
||||
defined(CONFIG_IAD210) || defined(CONFIG_XPEDITE1K) || \
|
||||
defined(CONFIG_METROBOX) || defined(CONFIG_KAREF) || \
|
||||
defined(CONFIG_V38B)
|
||||
void board_get_enetaddr (uchar *addr);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HERMES
|
||||
/* $(BOARD)/hermes.c */
|
||||
void hermes_start_lxt980 (int speed);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EVB64260
|
||||
void evb64260_init(void);
|
||||
void debug_led(int, int);
|
||||
void display_mem_map(void);
|
||||
void perform_soft_reset(void);
|
||||
#endif
|
||||
|
||||
void load_sernum_ethaddr (void);
|
||||
|
||||
/* $(BOARD)/$(BOARD).c */
|
||||
int board_early_init_f (void);
|
||||
int board_late_init (void);
|
||||
int board_postclk_init (void); /* after clocks/timebase, before env/serial */
|
||||
int board_early_init_r (void);
|
||||
void board_poweroff (void);
|
||||
|
||||
#if defined(CFG_DRAM_TEST)
|
||||
int testdram(void);
|
||||
#endif /* CFG_DRAM_TEST */
|
||||
|
||||
/* $(CPU)/start.S */
|
||||
#if defined(CONFIG_5xx) || \
|
||||
defined(CONFIG_8xx)
|
||||
uint get_immr (uint);
|
||||
#endif
|
||||
uint get_pir (void);
|
||||
#if defined(CONFIG_MPC5xxx)
|
||||
uint get_svr (void);
|
||||
#endif
|
||||
uint get_pvr (void);
|
||||
uint get_svr (void);
|
||||
uint rd_ic_cst (void);
|
||||
void wr_ic_cst (uint);
|
||||
void wr_ic_adr (uint);
|
||||
uint rd_dc_cst (void);
|
||||
void wr_dc_cst (uint);
|
||||
void wr_dc_adr (uint);
|
||||
int icache_status (void);
|
||||
void icache_enable (void);
|
||||
void icache_disable(void);
|
||||
int dcache_status (void);
|
||||
void dcache_enable (void);
|
||||
void dcache_disable(void);
|
||||
void relocate_code (ulong, gd_t *, ulong) __attribute__ ((noreturn));
|
||||
ulong get_endaddr (void);
|
||||
void trap_init (ulong);
|
||||
#if defined (CONFIG_4xx) || \
|
||||
defined (CONFIG_MPC5xxx) || \
|
||||
defined (CONFIG_74xx_7xx) || \
|
||||
defined (CONFIG_74x) || \
|
||||
defined (CONFIG_75x) || \
|
||||
defined (CONFIG_74xx) || \
|
||||
defined (CONFIG_MPC8220) || \
|
||||
defined (CONFIG_MPC85xx) || \
|
||||
defined (CONFIG_MPC86xx) || \
|
||||
defined (CONFIG_MPC83XX)
|
||||
unsigned char in8(unsigned int);
|
||||
void out8(unsigned int, unsigned char);
|
||||
unsigned short in16(unsigned int);
|
||||
unsigned short in16r(unsigned int);
|
||||
void out16(unsigned int, unsigned short value);
|
||||
void out16r(unsigned int, unsigned short value);
|
||||
unsigned long in32(unsigned int);
|
||||
unsigned long in32r(unsigned int);
|
||||
void out32(unsigned int, unsigned long value);
|
||||
void out32r(unsigned int, unsigned long value);
|
||||
void ppcDcbf(unsigned long value);
|
||||
void ppcDcbi(unsigned long value);
|
||||
void ppcSync(void);
|
||||
void ppcDcbz(unsigned long value);
|
||||
#endif
|
||||
#if defined (CONFIG_MICROBLAZE)
|
||||
unsigned short in16(unsigned int);
|
||||
void out16(unsigned int, unsigned short value);
|
||||
#endif
|
||||
|
||||
#if defined (CONFIG_MPC83XX)
|
||||
void ppcDWload(unsigned int *addr, unsigned int *ret);
|
||||
void ppcDWstore(unsigned int *addr, unsigned int *value);
|
||||
#endif
|
||||
|
||||
/* $(CPU)/cpu.c */
|
||||
int checkcpu (void);
|
||||
int checkicache (void);
|
||||
int checkdcache (void);
|
||||
void upmconfig (unsigned int, unsigned int *, unsigned int);
|
||||
ulong get_tbclk (void);
|
||||
void reset_cpu (ulong addr);
|
||||
#if defined (CONFIG_OF_LIBFDT) && defined (CONFIG_OF_BOARD_SETUP)
|
||||
void ft_cpu_setup(void *blob, bd_t *bd);
|
||||
#ifdef CONFIG_PCI
|
||||
void ft_pci_setup(void *blob, bd_t *bd);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* $(CPU)/serial.c */
|
||||
int serial_init (void);
|
||||
void serial_addr (unsigned int);
|
||||
void serial_setbrg (void);
|
||||
void serial_putc (const char);
|
||||
void serial_putc_raw(const char);
|
||||
void serial_puts (const char *);
|
||||
int serial_getc (void);
|
||||
int serial_tstc (void);
|
||||
|
||||
void _serial_setbrg (const int);
|
||||
void _serial_putc (const char, const int);
|
||||
void _serial_putc_raw(const char, const int);
|
||||
void _serial_puts (const char *, const int);
|
||||
int _serial_getc (const int);
|
||||
int _serial_tstc (const int);
|
||||
|
||||
/* $(CPU)/speed.c */
|
||||
int get_clocks (void);
|
||||
int get_clocks_866 (void);
|
||||
int sdram_adjust_866 (void);
|
||||
int adjust_sdram_tbs_8xx (void);
|
||||
#if defined(CONFIG_8260)
|
||||
int prt_8260_clks (void);
|
||||
#elif defined(CONFIG_MPC5xxx)
|
||||
int prt_mpc5xxx_clks (void);
|
||||
#endif
|
||||
#if defined(CONFIG_MPC512X)
|
||||
int prt_mpc512xxx_clks (void);
|
||||
#endif
|
||||
#if defined(CONFIG_MPC8220)
|
||||
int prt_mpc8220_clks (void);
|
||||
#endif
|
||||
#ifdef CONFIG_4xx
|
||||
ulong get_OPB_freq (void);
|
||||
ulong get_PCI_freq (void);
|
||||
#endif
|
||||
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || \
|
||||
defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442) || \
|
||||
defined(CONFIG_LH7A40X)
|
||||
void s3c2410_irq(void);
|
||||
#define ARM920_IRQ_CALLBACK s3c2410_irq
|
||||
ulong get_FCLK (void);
|
||||
ulong get_HCLK (void);
|
||||
ulong get_PCLK (void);
|
||||
ulong get_UCLK (void);
|
||||
#endif
|
||||
#if defined(CONFIG_LH7A40X)
|
||||
ulong get_PLLCLK (void);
|
||||
#endif
|
||||
#if defined CONFIG_INCA_IP
|
||||
uint incaip_get_cpuclk (void);
|
||||
#endif
|
||||
#if defined(CONFIG_IMX)
|
||||
ulong get_systemPLLCLK(void);
|
||||
ulong get_FCLK(void);
|
||||
ulong get_HCLK(void);
|
||||
ulong get_BCLK(void);
|
||||
ulong get_PERCLK1(void);
|
||||
ulong get_PERCLK2(void);
|
||||
ulong get_PERCLK3(void);
|
||||
#endif
|
||||
ulong get_bus_freq (ulong);
|
||||
|
||||
#if defined(CONFIG_MPC85xx)
|
||||
typedef MPC85xx_SYS_INFO sys_info_t;
|
||||
void get_sys_info ( sys_info_t * );
|
||||
ulong get_ddr_freq (ulong);
|
||||
#endif
|
||||
#if defined(CONFIG_MPC86xx)
|
||||
typedef MPC86xx_SYS_INFO sys_info_t;
|
||||
void get_sys_info ( sys_info_t * );
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_4xx) || defined(CONFIG_IOP480)
|
||||
# if defined(CONFIG_440)
|
||||
# if defined(CONFIG_440SPE)
|
||||
unsigned long determine_sysper(void);
|
||||
unsigned long determine_pci_clock_per(void);
|
||||
# endif
|
||||
# endif
|
||||
typedef PPC4xx_SYS_INFO sys_info_t;
|
||||
int ppc440spe_revB(void);
|
||||
void get_sys_info ( sys_info_t * );
|
||||
#endif
|
||||
|
||||
/* $(CPU)/cpu_init.c */
|
||||
#if defined(CONFIG_8xx) || defined(CONFIG_8260)
|
||||
void cpu_init_f (volatile immap_t *immr);
|
||||
#endif
|
||||
#if defined(CONFIG_4xx) || defined(CONFIG_MPC85xx) || defined(CONFIG_MCF52x2) ||defined(CONFIG_MPC86xx)
|
||||
void cpu_init_f (void);
|
||||
#endif
|
||||
|
||||
int cpu_init_r (void);
|
||||
#if defined(CONFIG_8260)
|
||||
int prt_8260_rsr (void);
|
||||
#elif defined(CONFIG_MPC83XX)
|
||||
int prt_83xx_rsr (void);
|
||||
#endif
|
||||
|
||||
/* $(CPU)/interrupts.c */
|
||||
int interrupt_init (void);
|
||||
void timer_interrupt (struct pt_regs *);
|
||||
void external_interrupt (struct pt_regs *);
|
||||
void irq_install_handler(int, interrupt_handler_t *, void *);
|
||||
void irq_free_handler (int);
|
||||
void reset_timer (void);
|
||||
ulong get_timer (ulong base);
|
||||
void set_timer (ulong t);
|
||||
void enable_interrupts (void);
|
||||
int disable_interrupts (void);
|
||||
|
||||
/* $(CPU)/.../commproc.c */
|
||||
int dpram_init (void);
|
||||
uint dpram_base(void);
|
||||
uint dpram_base_align(uint align);
|
||||
uint dpram_alloc(uint size);
|
||||
uint dpram_alloc_align(uint size,uint align);
|
||||
void post_word_store (ulong);
|
||||
ulong post_word_load (void);
|
||||
void bootcount_store (ulong);
|
||||
ulong bootcount_load (void);
|
||||
#define BOOTCOUNT_MAGIC 0xB001C041
|
||||
|
||||
/* $(CPU)/.../<eth> */
|
||||
void mii_init (void);
|
||||
|
||||
/* $(CPU)/.../lcd.c */
|
||||
ulong lcd_setmem (ulong);
|
||||
|
||||
/* $(CPU)/.../vfd.c */
|
||||
ulong vfd_setmem (ulong);
|
||||
|
||||
/* $(CPU)/.../video.c */
|
||||
ulong video_setmem (ulong);
|
||||
|
||||
/* lib_$(ARCH)/cache.c */
|
||||
void flush_cache (unsigned long, unsigned long);
|
||||
|
||||
|
||||
/* lib_$(ARCH)/ticks.S */
|
||||
unsigned long long get_ticks(void);
|
||||
void wait_ticks (unsigned long);
|
||||
|
||||
/* lib_$(ARCH)/time.c */
|
||||
void udelay (unsigned long);
|
||||
ulong usec2ticks (unsigned long usec);
|
||||
ulong ticks2usec (unsigned long ticks);
|
||||
int init_timebase (void);
|
||||
|
||||
/* lib_generic/vsprintf.c */
|
||||
ulong simple_strtoul(const char *cp,char **endp,unsigned int base);
|
||||
#ifdef CFG_64BIT_VSPRINTF
|
||||
unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base);
|
||||
#endif
|
||||
long simple_strtol(const char *cp,char **endp,unsigned int base);
|
||||
void panic(const char *fmt, ...);
|
||||
int sprintf(char * buf, const char *fmt, ...);
|
||||
int vsprintf(char *buf, const char *fmt, va_list args);
|
||||
|
||||
/* lib_generic/crc32.c */
|
||||
ulong crc32 (ulong, const unsigned char *, uint);
|
||||
ulong crc32_no_comp (ulong, const unsigned char *, uint);
|
||||
|
||||
/* common/console.c */
|
||||
int console_init_f(void); /* Before relocation; uses the serial stuff */
|
||||
int console_init_r(void); /* After relocation; uses the console stuff */
|
||||
int console_assign (int file, char *devname); /* Assign the console */
|
||||
int ctrlc (void);
|
||||
int had_ctrlc (void); /* have we had a Control-C since last clear? */
|
||||
void clear_ctrlc (void); /* clear the Control-C condition */
|
||||
int disable_ctrlc (int); /* 1 to disable, 0 to enable Control-C detect */
|
||||
|
||||
/*
|
||||
* STDIO based functions (can always be used)
|
||||
*/
|
||||
|
||||
/* serial stuff */
|
||||
void serial_printf (const char *fmt, ...);
|
||||
|
||||
/* stdin */
|
||||
int getc(void);
|
||||
int tstc(void);
|
||||
|
||||
/* stdout */
|
||||
void putc(const char c);
|
||||
void puts(const char *s);
|
||||
void printf(const char *fmt, ...);
|
||||
void vprintf(const char *fmt, va_list args);
|
||||
|
||||
/* stderr */
|
||||
#define eputc(c) fputc(stderr, c)
|
||||
#define eputs(s) fputs(stderr, s)
|
||||
#define eprintf(fmt,args...) fprintf(stderr,fmt ,##args)
|
||||
|
||||
/*
|
||||
* FILE based functions (can only be used AFTER relocation!)
|
||||
*/
|
||||
|
||||
#define stdin 0
|
||||
#define stdout 1
|
||||
#define stderr 2
|
||||
#define MAX_FILES 3
|
||||
|
||||
void fprintf(int file, const char *fmt, ...);
|
||||
void fputs(int file, const char *s);
|
||||
void fputc(int file, const char c);
|
||||
int ftstc(int file);
|
||||
int fgetc(int file);
|
||||
|
||||
int pcmcia_init (void);
|
||||
|
||||
#ifdef CONFIG_STATUS_LED
|
||||
# include <status_led.h>
|
||||
#endif
|
||||
/*
|
||||
* Board-specific Platform code can reimplement show_boot_progress () if needed
|
||||
*/
|
||||
void inline show_boot_progress (int val);
|
||||
|
||||
#ifdef CONFIG_INIT_CRITICAL
|
||||
#error CONFIG_INIT_CRITICAL is deprecated!
|
||||
#error Read section CONFIG_SKIP_LOWLEVEL_INIT in README.
|
||||
#endif
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
/* Multicore arch functions */
|
||||
#ifdef CONFIG_MP
|
||||
int cpu_status(int nr);
|
||||
int cpu_reset(int nr);
|
||||
int cpu_release(int nr, int argc, char *argv[]);
|
||||
#endif
|
||||
|
||||
#endif /* __COMMON_H_ */
|
312
qiboot/src/cpu/s3c2410/gta01.c
Normal file
312
qiboot/src/cpu/s3c2410/gta01.c
Normal file
@ -0,0 +1,312 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
* Author: Andy Green <andy@openmoko.com>
|
||||
*
|
||||
* Configuation settings for the OPENMOKO Neo GTA02 Linux GSM phone
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <qi.h>
|
||||
#include <neo_gta01.h>
|
||||
#include <serial-s3c24xx.h>
|
||||
#include <ports-s3c24xx.h>
|
||||
#include <s3c24xx-mci.h>
|
||||
#include <i2c-bitbang-s3c24xx.h>
|
||||
#include <pcf50606.h>
|
||||
|
||||
#define GTA01_DEBUG_UART 0
|
||||
#define PCF50606_I2C_ADS 0x08
|
||||
|
||||
|
||||
struct pcf50606_init {
|
||||
u8 index;
|
||||
u8 value;
|
||||
};
|
||||
|
||||
/* initial register set for PCF50606 in Neo1973 devices */
|
||||
const struct pcf50606_init pcf50606_initial_regs[] = {
|
||||
{ PCF50606_REG_OOCS, 0x00 },
|
||||
{ PCF50606_REG_INT1M, 0x00 },
|
||||
{ PCF50606_REG_INT2M, 0x00 },
|
||||
{ PCF50606_REG_INT3M, PCF50606_INT3_TSCPRES },
|
||||
{ PCF50606_REG_OOCC1, PCF50606_OOCC1_RTCWAK | PCF50606_OOCC1_CHGWAK |
|
||||
PCF50606_OOCC1_EXTONWAK_HIGH },
|
||||
{ PCF50606_REG_OOCC2, PCF50606_OOCC2_ONKEYDB_14ms | PCF50606_OOCC2_EXTONDB_14ms },
|
||||
{ PCF50606_REG_PSSC, 0x00 },
|
||||
{ PCF50606_REG_PWROKM, 0x00 },
|
||||
{ PCF50606_REG_DCDC1, 0x18 }, /* GL_1V5: off */
|
||||
{ PCF50606_REG_DCDC2, 0x00 },
|
||||
{ PCF50606_REG_DCDC3, 0x00 },
|
||||
{ PCF50606_REG_DCDC4, 0x30 }, /* 1.25A */
|
||||
|
||||
{ PCF50606_REG_DCDEC1, 0xe8 }, /* IO_3V3: on */
|
||||
{ PCF50606_REG_DCDEC2, 0x00 },
|
||||
|
||||
{ PCF50606_REG_DCUDC1, 0xc4 }, /* CORE_1V8: 2.1V if PWREN2 = HIGH */
|
||||
{ PCF50606_REG_DCUDC2, 0x30 }, /* 1.25A current limit */
|
||||
|
||||
{ PCF50606_REG_IOREGC, 0xf8 }, /* CODEC_3V3: on */
|
||||
{ PCF50606_REG_D1REGC1, 0x16 }, /* BT_3V15: off */
|
||||
|
||||
{ PCF50606_REG_D2REGC1, 0x10 }, /* GL_2V5: off */
|
||||
|
||||
{ PCF50606_REG_D3REGC1, 0xec }, /* STBY_1V8: 2.1V */
|
||||
|
||||
{ PCF50606_REG_LPREGC1, 0xf8 }, /* LCM_3V3: on */
|
||||
{ PCF50606_REG_LPREGC2, 0x00 },
|
||||
|
||||
{ PCF50606_REG_MBCC1, 0x01 }, /* CHGAPE */
|
||||
{ PCF50606_REG_MBCC2, 0x00 }, /* unlimited charging */
|
||||
{ PCF50606_REG_MBCC3, 0x1a }, /* 0.2*Ifast, 4.20V */
|
||||
{ PCF50606_REG_BBCC, 0x1f }, /* 400uA */
|
||||
{ PCF50606_REG_ADCC1, 0x00 },
|
||||
{ PCF50606_REG_ADCC2, 0x00 },
|
||||
{ PCF50606_REG_ACDC1, 0x86 }, /* ACD thresh 1.6V, enabled */
|
||||
{ PCF50606_REG_BVMC, PCF50606_BVMC_THRSHLD_3V3 },
|
||||
{ PCF50606_REG_PWMC1, 0x00 },
|
||||
{ PCF50606_REG_LEDC1, 0x00 },
|
||||
{ PCF50606_REG_LEDC2, 0x00 },
|
||||
{ PCF50606_REG_GPOC1, 0x00 },
|
||||
{ PCF50606_REG_GPOC2, 0x00 },
|
||||
{ PCF50606_REG_GPOC3, 0x00 },
|
||||
{ PCF50606_REG_GPOC4, 0x00 },
|
||||
{ PCF50606_REG_GPOC5, 0x00 },
|
||||
};
|
||||
|
||||
|
||||
static const struct board_variant board_variants[] = {
|
||||
[0] = {
|
||||
.name = "Bv4",
|
||||
.machine_revision = 0x240,
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void port_init_gta01(void)
|
||||
{
|
||||
int n;
|
||||
unsigned int * MPLLCON = (unsigned int *)0x4c000004;
|
||||
|
||||
rGPACON = 0x005E0FFF;
|
||||
rGPADAT = 0x00010000; /* nNAND_WP set high */
|
||||
|
||||
rGPBCON = 0x00045455;
|
||||
rGPBUP = 0x000007FF;
|
||||
rGPBDAT = 0x00000004; /* SD-card pwr off */
|
||||
|
||||
rGPCCON = 0xAAAA12A9;
|
||||
rGPCUP = 0x0000FFFF;
|
||||
|
||||
rGPDCON = 0xAAAAAAAA;
|
||||
rGPDUP = 0x0000FFFF;
|
||||
|
||||
rGPECON = 0xAAAAAAAA;
|
||||
rGPEUP = 0x0000FFFF;
|
||||
|
||||
rGPFCON = 0x0000aa99;
|
||||
rGPFUP = 0x000000FF;
|
||||
rGPFDAT = 0x00000004;
|
||||
|
||||
rGPGCON = 0xFF14F0F8;
|
||||
rGPGUP = 0x0000AFEF;
|
||||
|
||||
rGPHCON = 0x0000FAAA;
|
||||
rGPHUP = 0x000007FF;
|
||||
|
||||
|
||||
/* Load PMU with safe values */
|
||||
|
||||
for (n = 0; n < ARRAY_SIZE(pcf50606_initial_regs); n++)
|
||||
i2c_write_sync(&bb_s3c24xx, PCF50606_I2C_ADS,
|
||||
pcf50606_initial_regs[n].index,
|
||||
pcf50606_initial_regs[n].value);
|
||||
|
||||
/* Give a short vibrate notification */
|
||||
rGPBDAT |= (1 << 3);
|
||||
udelay(1000000);
|
||||
rGPBDAT &= ~(1 << 3);
|
||||
|
||||
|
||||
/* change CPU to 266MHz 1:2:4 */
|
||||
*MPLLCON = ((0x7d << 12) + (0x1 << 4) + 0x1);
|
||||
/* Delay after update of PLL: Page 7-19, seven nops */
|
||||
asm __volatile__ (
|
||||
"nop\n"
|
||||
"nop\n"
|
||||
"nop\n"
|
||||
"nop\n"
|
||||
"nop\n"
|
||||
"nop\n"
|
||||
"nop\n"
|
||||
);
|
||||
|
||||
|
||||
/* set debug UART working at 115kbps */
|
||||
serial_init_115200_s3c24xx(GTA01_DEBUG_UART, 66 /* 66.5MHz PCLK */);
|
||||
}
|
||||
|
||||
|
||||
int sd_card_init_gta01(void)
|
||||
{
|
||||
int retval = -1;
|
||||
|
||||
/* Check if AUX is held. Then skip SD-card kernels!
|
||||
* FIXME: This would be nicer to do with an API.
|
||||
*/
|
||||
if (!(rGPFDAT & (1 << 6))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* if SD card inserted, power it up and initialize*/
|
||||
if (!(rGPFDAT & (1 << 5)))
|
||||
{
|
||||
rGPBDAT &= ~(1 << 2);
|
||||
retval = s3c24xx_mmc_init(1);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
int sd_card_block_read_gta01(unsigned char * buf, unsigned long start512,
|
||||
int blocks512)
|
||||
{
|
||||
return s3c24xx_mmc_bread(0, start512, blocks512, buf);
|
||||
}
|
||||
|
||||
int is_this_board_gta01(void)
|
||||
{
|
||||
/* FIXME: How to check for GTA01 ? */
|
||||
return 1;
|
||||
}
|
||||
|
||||
const struct board_variant const * get_board_variant_gta01(void)
|
||||
{
|
||||
return &board_variants[0];
|
||||
}
|
||||
|
||||
static __attribute__ (( section (".steppingstone") )) void putc_gta01(char c)
|
||||
{
|
||||
serial_putc_s3c24xx(GTA01_DEBUG_UART, c);
|
||||
}
|
||||
|
||||
static void close_gta01(void)
|
||||
{
|
||||
/* set I2C GPIO back to peripheral unit */
|
||||
(bb_s3c24xx.close)();
|
||||
}
|
||||
|
||||
/* Here we will care only about AUX button as polling for PWR button
|
||||
* through i2c slows down the boot */
|
||||
|
||||
static u8 get_ui_keys_gta01(void)
|
||||
{
|
||||
u8 keys;
|
||||
u8 ret = 0;
|
||||
static u8 old_keys = 0; /* previous state for debounce */
|
||||
static u8 older_keys = 0; /* previous debounced output for edge detect */
|
||||
|
||||
/* GPF6 is AUX on GTA01, map to UI_ACTION_SKIPKERNEL, down = 0 */
|
||||
keys = ! (rGPFDAT & (1 << 6));
|
||||
|
||||
/* edge action */
|
||||
if ((old_keys & 1) && !(older_keys & 1))
|
||||
ret |= UI_ACTION_SKIPKERNEL;
|
||||
|
||||
older_keys = old_keys;
|
||||
old_keys = keys;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u8 get_ui_debug_gta01(void)
|
||||
{
|
||||
/* PWR button state can be seen in OOCS b0, down = 0, map to UI_ACTION_ADD_DEBUG */
|
||||
return !(i2c_read_sync(&bb_s3c24xx, PCF50606_I2C_ADS, PCF50606_REG_OOCS) & 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* API for bootloader on this machine
|
||||
*/
|
||||
|
||||
const struct board_api board_api_gta01 = {
|
||||
.name = "Neo1973 GTA01",
|
||||
.linux_machine_id = 1182,
|
||||
.linux_mem_start = 0x30000000,
|
||||
.linux_mem_size = (128 * 1024 * 1024),
|
||||
.linux_tag_placement = 0x30000000 + 0x100,
|
||||
.get_board_variant = get_board_variant_gta01,
|
||||
.is_this_board = is_this_board_gta01,
|
||||
.port_init = port_init_gta01,
|
||||
.putc = putc_gta01,
|
||||
.close = close_gta01,
|
||||
.get_ui_keys = get_ui_keys_gta01,
|
||||
.get_ui_debug = get_ui_debug_gta01,
|
||||
|
||||
.commandline_board = "mtdparts="
|
||||
"neo1973-nand:"
|
||||
"0x00040000(qi),"
|
||||
"0x00004000(u-boot_env),"
|
||||
"0x00200000(kernel),"
|
||||
"0x000a0000(splash),"
|
||||
"0x03d1c000(rootfs) "
|
||||
"loglevel=4 "
|
||||
"console=tty0 "
|
||||
"console=ttySAC0,115200 "
|
||||
"init=/sbin/init "
|
||||
"ro ",
|
||||
.commandline_board_debug = " loglevel=8 ",
|
||||
.noboot = "boot/noboot-GTA01",
|
||||
.append = "boot/append-GTA01",
|
||||
/* these are the ways we could boot GTA01 in order to try */
|
||||
.kernel_source = {
|
||||
[0] = {
|
||||
.name = "SD Card EXT2 Kernel p1",
|
||||
.block_init = sd_card_init_gta01,
|
||||
.block_read = sd_card_block_read_gta01,
|
||||
.partition_index = 1,
|
||||
.filesystem = FS_EXT2,
|
||||
.filepath = "boot/uImage-GTA01.bin",
|
||||
.commandline_append = "root=/dev/mmcblk0p1 rootdelay=1 ",
|
||||
},
|
||||
[1] = {
|
||||
.name = "SD Card EXT2 Kernel p2",
|
||||
.block_init = sd_card_init_gta01,
|
||||
.block_read = sd_card_block_read_gta01,
|
||||
.partition_index = 2,
|
||||
.filesystem = FS_EXT2,
|
||||
.filepath = "boot/uImage-GTA01.bin",
|
||||
.commandline_append = "root=/dev/mmcblk0p2 rootdelay=1 ",
|
||||
},
|
||||
[2] = {
|
||||
.name = "SD Card EXT2 Kernel p3",
|
||||
.block_init = sd_card_init_gta01,
|
||||
.block_read = sd_card_block_read_gta01,
|
||||
.partition_index = 3,
|
||||
.filesystem = FS_EXT2,
|
||||
.filepath = "boot/uImage-GTA01.bin",
|
||||
.commandline_append = "root=/dev/mmcblk0p3 rootdelay=1 ",
|
||||
},
|
||||
[3] = {
|
||||
.name = "NAND Kernel",
|
||||
.block_read = nand_read_ll,
|
||||
.offset_blocks512_if_no_partition = 0x44000 / 512,
|
||||
.filesystem = FS_RAW,
|
||||
.commandline_append = "rootfstype=jffs2 "
|
||||
"root=/dev/mtdblock4 ",
|
||||
},
|
||||
},
|
||||
};
|
68
qiboot/src/cpu/s3c2410/i2c-bitbang-s3c24xx.c
Normal file
68
qiboot/src/cpu/s3c2410/i2c-bitbang-s3c24xx.c
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
* Author: Andy Green <andy@openmoko.com>
|
||||
*
|
||||
* s3c24xx-specific i2c shared by, eg, GTA02 and GTA03
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <qi.h>
|
||||
#include <i2c-bitbang.h>
|
||||
#include <ports-s3c24xx.h>
|
||||
|
||||
static char i2c_read_sda_s3c24xx(void)
|
||||
{
|
||||
return (rGPEDAT & 0x8000) != 0;
|
||||
}
|
||||
|
||||
static void i2c_set_s3c24xx(char clock, char data)
|
||||
{
|
||||
if (clock) /* SCL <- input */
|
||||
rGPECON = (rGPECON & ~0x30000000);
|
||||
else { /* SCL <- output 0 */
|
||||
rGPEDAT = (rGPEDAT & ~0x4000);
|
||||
rGPECON = (rGPECON & ~0x30000000) | 0x10000000;
|
||||
}
|
||||
if (data) /* SDA <- input */
|
||||
rGPECON = (rGPECON & ~0xc0000000);
|
||||
else { /* SDA <- output 0 */
|
||||
rGPEDAT = (rGPEDAT & ~0x8000);
|
||||
rGPECON = (rGPECON & ~0xc0000000) | 0x40000000;
|
||||
}
|
||||
}
|
||||
|
||||
static void i2c_close_s3c24xx(void)
|
||||
{
|
||||
/* set back to hardware I2C ready for Linux */
|
||||
rGPECON = (rGPECON & ~0xf0000000) | 0xa0000000;
|
||||
}
|
||||
|
||||
static void i2c_spin_s3c24xx(void)
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < 1000; n++)
|
||||
rGPJDAT |= (1 << 5);
|
||||
}
|
||||
|
||||
struct i2c_bitbang bb_s3c24xx = {
|
||||
.read_sda = i2c_read_sda_s3c24xx,
|
||||
.set = i2c_set_s3c24xx,
|
||||
.spin = i2c_spin_s3c24xx,
|
||||
.close = i2c_close_s3c24xx,
|
||||
};
|
162
qiboot/src/cpu/s3c2410/lowlevel_init.S
Normal file
162
qiboot/src/cpu/s3c2410/lowlevel_init.S
Normal file
@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Memory Setup stuff - taken from blob memsetup.S
|
||||
*
|
||||
* Modified for the FIC Neo1973 GTA01 by Harald Welte <laforge@openmoko.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* NOTE this stuff runs in steppingstone context! */
|
||||
|
||||
|
||||
/*
|
||||
* #include <config.h>
|
||||
* #include <version.h>
|
||||
*/
|
||||
#define __ASM_MODE__
|
||||
#include <neo_gta01.h>
|
||||
|
||||
/*
|
||||
*
|
||||
* Taken from linux/arch/arm/boot/compressed/head-s3c2410.S
|
||||
*
|
||||
* Copyright (C) 2002 Samsung Electronics SW.LEE <hitchcar@sec.samsung.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#define BWSCON 0x48000000
|
||||
|
||||
/* BWSCON */
|
||||
#define DW8 (0x0)
|
||||
#define DW16 (0x1)
|
||||
#define DW32 (0x2)
|
||||
#define WAIT (0x1<<2)
|
||||
#define UBLB (0x1<<3)
|
||||
|
||||
#define B1_BWSCON (DW16 + WAIT + UBLB)
|
||||
#define B2_BWSCON (DW16)
|
||||
#define B3_BWSCON (DW16 + WAIT + UBLB)
|
||||
#define B4_BWSCON (DW16)
|
||||
#define B5_BWSCON (DW16)
|
||||
#define B6_BWSCON (DW32)
|
||||
#define B7_BWSCON (DW32)
|
||||
|
||||
/* BANK0CON */
|
||||
#define B0_Tacs 0x0 /* 0clk */
|
||||
#define B0_Tcos 0x0 /* 0clk */
|
||||
#define B0_Tacc 0x7 /* 14clk */
|
||||
#define B0_Tcoh 0x0 /* 0clk */
|
||||
#define B0_Tah 0x0 /* 0clk */
|
||||
#define B0_Tacp 0x0
|
||||
#define B0_PMC 0x0 /* normal */
|
||||
|
||||
/* BANK1CON: Smedia Glamo 3362 (on GTA02) */
|
||||
#define B1_Tacs 0x0 /* 0clk */
|
||||
#define B1_Tcos 0x3 /* 4clk */
|
||||
#define B1_Tacc 0x3 /* 4clk */
|
||||
#define B1_Tcoh 0x3 /* 4clk */
|
||||
#define B1_Tah 0x0 /* 0clk */
|
||||
#define B1_Tacp 0x0
|
||||
#define B1_PMC 0x0
|
||||
|
||||
#define B2_Tacs 0x0
|
||||
#define B2_Tcos 0x0
|
||||
#define B2_Tacc 0x7
|
||||
#define B2_Tcoh 0x0
|
||||
#define B2_Tah 0x0
|
||||
#define B2_Tacp 0x0
|
||||
#define B2_PMC 0x0
|
||||
|
||||
#define B3_Tacs 0x0 /* 0clk */
|
||||
#define B3_Tcos 0x3 /* 4clk */
|
||||
#define B3_Tacc 0x7 /* 14clk */
|
||||
#define B3_Tcoh 0x1 /* 1clk */
|
||||
#define B3_Tah 0x0 /* 0clk */
|
||||
#define B3_Tacp 0x3 /* 6clk */
|
||||
#define B3_PMC 0x0 /* normal */
|
||||
|
||||
#define B4_Tacs 0x0 /* 0clk */
|
||||
#define B4_Tcos 0x0 /* 0clk */
|
||||
#define B4_Tacc 0x7 /* 14clk */
|
||||
#define B4_Tcoh 0x0 /* 0clk */
|
||||
#define B4_Tah 0x0 /* 0clk */
|
||||
#define B4_Tacp 0x0
|
||||
#define B4_PMC 0x0 /* normal */
|
||||
|
||||
#define B5_Tacs 0x0 /* 0clk */
|
||||
#define B5_Tcos 0x0 /* 0clk */
|
||||
#define B5_Tacc 0x7 /* 14clk */
|
||||
#define B5_Tcoh 0x0 /* 0clk */
|
||||
#define B5_Tah 0x0 /* 0clk */
|
||||
#define B5_Tacp 0x0
|
||||
#define B5_PMC 0x0 /* normal */
|
||||
|
||||
#define B6_MT 0x3 /* SDRAM */
|
||||
#define B6_Trcd 0x1 /* 3clk */
|
||||
|
||||
#define B6_SCAN 0x2 /* 10bit */
|
||||
#define B7_SCAN 0x2 /* 10bit */
|
||||
|
||||
|
||||
#define B7_MT 0x3 /* SDRAM */
|
||||
#define B7_Trcd 0x1 /* 3clk */
|
||||
|
||||
/* REFRESH parameter */
|
||||
#define REFEN 0x1 /* Refresh enable */
|
||||
#define TREFMD 0x0 /* CBR(CAS before RAS)/Auto refresh */
|
||||
#define Trp 0x1 /* 3clk */
|
||||
#define Trc 0x3 /* 7clk */
|
||||
#define Tchr 0x2 /* 3clk */
|
||||
//#define REFCNT 1113 /* period=15.6us, HCLK=60Mhz, (2048+1-15.6*60) */
|
||||
#define REFCNT 997 /* period=17.5us, HCLK=60Mhz, (2048+1-15.6*60) */
|
||||
/**************************************/
|
||||
|
||||
.globl lowlevel_init
|
||||
lowlevel_init:
|
||||
|
||||
ldr r0, =SMRDATA
|
||||
ldr r1, =BWSCON /* Bus Width Status Controller */
|
||||
add r2, r0, #13*4
|
||||
0:
|
||||
ldr r3, [r0], #4
|
||||
str r3, [r1], #4
|
||||
cmp r2, r0
|
||||
bne 0b
|
||||
|
||||
/* setup asynchronous bus mode */
|
||||
mrc p15, 0, r1 ,c1 ,c0, 0
|
||||
orr r1, r1, #0xc0000000
|
||||
mcr p15, 0, r1, c1, c0, 0
|
||||
|
||||
/* everything is fine now */
|
||||
mov pc, lr
|
||||
|
||||
.ltorg
|
||||
/* the literal pools origin */
|
||||
SMRDATA:
|
||||
.word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
|
||||
.word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
|
||||
.word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
|
||||
.word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
|
||||
.word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
|
||||
.word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
|
||||
.word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
|
||||
.word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
|
||||
.word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
|
||||
.word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
|
||||
.word 0xb2
|
||||
.word 0x30
|
||||
.word 0x30
|
136
qiboot/src/cpu/s3c2410/nand_read.c
Normal file
136
qiboot/src/cpu/s3c2410/nand_read.c
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* nand_read.c: Simple NAND read functions for booting from NAND
|
||||
*
|
||||
* This is used by cpu/arm920/start.S assembler code,
|
||||
* and the board-specific linker script must make sure this
|
||||
* file is linked within the first 4kB of NAND flash.
|
||||
*
|
||||
* Taken from GPLv2 licensed vivi bootloader,
|
||||
* Copyright (C) 2002 MIZI Research, Inc.
|
||||
*
|
||||
* Author: Hwang, Chideok <hwang@mizi.com>
|
||||
* Date : $Date: 2004/02/04 10:37:37 $
|
||||
*
|
||||
* u-boot integration and bad-block skipping (C) 2006 by OpenMoko, Inc.
|
||||
* Author: Harald Welte <laforge@openmoko.org>
|
||||
*/
|
||||
|
||||
/* NOTE this stuff runs in steppingstone context! */
|
||||
|
||||
/* the API refers to 512-byte blocks */
|
||||
|
||||
#include <qi.h>
|
||||
#include "nand_read.h"
|
||||
|
||||
#define NAND_CMD_READ0 0
|
||||
#define NAND_CMD_READOOB 0x50
|
||||
|
||||
#define __REGb(x) (*(volatile unsigned char *)(x))
|
||||
#define __REGw(x) (*(volatile unsigned short *)(x))
|
||||
#define __REGi(x) (*(volatile unsigned int *)(x))
|
||||
#define NF_BASE 0x4e000000
|
||||
#define NFCONF __REGi(NF_BASE + 0x0)
|
||||
#define NFCMD __REGb(NF_BASE + 0x4)
|
||||
#define NFADDR __REGb(NF_BASE + 0x8)
|
||||
#define NFDATA __REGb(NF_BASE + 0xc)
|
||||
#define NFSTAT __REGb(NF_BASE + 0x10)
|
||||
#define NFSTAT_BUSY 1
|
||||
#define nand_select() (NFCONF &= ~0x800)
|
||||
#define nand_deselect() (NFCONF |= 0x800)
|
||||
#define nand_clear_RnB() do {} while (0)
|
||||
|
||||
|
||||
static inline void nand_wait(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
while (!(NFSTAT & NFSTAT_BUSY))
|
||||
for (i=0; i<10; i++);
|
||||
}
|
||||
|
||||
/* configuration for 2410 with 512byte sized flash */
|
||||
#define NAND_PAGE_SIZE 512
|
||||
#define BAD_BLOCK_OFFSET 5
|
||||
#define NAND_BLOCK_MASK (NAND_PAGE_SIZE - 1)
|
||||
#define NAND_BLOCK_SIZE 0x4000
|
||||
|
||||
static int is_bad_block(unsigned long block_index)
|
||||
{
|
||||
unsigned char data;
|
||||
|
||||
nand_clear_RnB();
|
||||
|
||||
NFCMD = NAND_CMD_READOOB; /* 0x50 */
|
||||
NFADDR = BAD_BLOCK_OFFSET & 0xf;
|
||||
NFADDR = (block_index ) & 0xff;
|
||||
NFADDR = (block_index >> 8 ) & 0xff;
|
||||
NFADDR = (block_index >> 16) & 0xff;
|
||||
|
||||
nand_wait();
|
||||
data = (NFDATA & 0xff);
|
||||
|
||||
if (data != 0xff)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nand_read_page_ll(unsigned char *buf, unsigned long block512)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
nand_clear_RnB();
|
||||
|
||||
NFCMD = NAND_CMD_READ0;
|
||||
|
||||
/* Write Address */
|
||||
NFADDR = 0;
|
||||
NFADDR = (block512 ) & 0xff;
|
||||
NFADDR = (block512 >> 8 ) & 0xff;
|
||||
NFADDR = (block512 >> 16) & 0xff;
|
||||
|
||||
nand_wait();
|
||||
|
||||
for (i = 0; i < NAND_PAGE_SIZE; i++) {
|
||||
*buf = (NFDATA & 0xff);
|
||||
buf++;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* low level nand read function */
|
||||
int nand_read_ll(unsigned char *buf, unsigned long start_block512, int blocks512)
|
||||
{
|
||||
int i, j;
|
||||
int bad_count = 0;
|
||||
|
||||
/* chip Enable */
|
||||
nand_select();
|
||||
nand_clear_RnB();
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
;
|
||||
|
||||
while (blocks512 > 0) {
|
||||
if (is_bad_block(start_block512) ||
|
||||
is_bad_block(start_block512 + 1)) {
|
||||
start_block512 += 1;
|
||||
blocks512 += 1;
|
||||
if (bad_count++ == 4)
|
||||
return -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
j = nand_read_page_ll(buf, start_block512);
|
||||
start_block512 += j;
|
||||
buf += j << 9;
|
||||
blocks512 -= j;
|
||||
}
|
||||
|
||||
/* chip Disable */
|
||||
nand_deselect();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
22
qiboot/src/cpu/s3c2410/nand_read.h
Normal file
22
qiboot/src/cpu/s3c2410/nand_read.h
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* nand_read.c: Simple NAND read functions for booting from NAND
|
||||
*
|
||||
* This is used by cpu/arm920/start.S assembler code,
|
||||
* and the board-specific linker script must make sure this
|
||||
* file is linked within the first 4kB of NAND flash.
|
||||
*
|
||||
* Taken from GPLv2 licensed vivi bootloader,
|
||||
* Copyright (C) 2002 MIZI Research, Inc.
|
||||
*
|
||||
* Author: Hwang, Chideok <hwang@mizi.com>
|
||||
* Date : $Date: 2004/02/04 10:37:37 $
|
||||
*
|
||||
* u-boot integration and bad-block skipping (C) 2006 by OpenMoko, Inc.
|
||||
* Author: Harald Welte <laforge@openmoko.org>
|
||||
*/
|
||||
#ifndef __NAND_READ_H
|
||||
#define __NAND_READ_H
|
||||
|
||||
int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size);
|
||||
|
||||
#endif /* __NAND_READ_H */
|
63
qiboot/src/cpu/s3c2410/qi.lds
Normal file
63
qiboot/src/cpu/s3c2410/qi.lds
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* (C) Copyright 2002
|
||||
* Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
|
||||
/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
|
||||
OUTPUT_ARCH(arm)
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x00000000;
|
||||
|
||||
/* this is intended to take the first 4KBytes of stuff initially.
|
||||
* We have to make sure we have .rodata* in there for everything
|
||||
* because we do not compile PIC.
|
||||
*/
|
||||
|
||||
. = ALIGN(4);
|
||||
.text :
|
||||
{
|
||||
src/cpu/s3c2410/start.o (.text .rodata* .data .bss)
|
||||
src/cpu/s3c2410/lowlevel_init.o (.text .rodata* .data .bss)
|
||||
src/cpu/s3c2410/start_qi.o (.text .rodata* .data .bss)
|
||||
src/cpu/s3c2410/nand_read.o (.text .rodata* .data .bss)
|
||||
src/cpu/s3c2410/serial-s3c24xx.o (.text .rodata* .data .bss)
|
||||
src/memory-test.o (.text .rodata* .data .bss)
|
||||
src/utils.o (.text .rodata* .data .bss)
|
||||
src/ctype.o (.text .rodata* .data .bss)
|
||||
* (.steppingstone)
|
||||
}
|
||||
|
||||
. = ALIGN(4);
|
||||
.everything_else ADDR (.text) + SIZEOF (.text) + 0x33000000 :
|
||||
AT ( ADDR (.text) + SIZEOF (.text) ) { *(.text .rodata* .data) }
|
||||
|
||||
. = 0x33800000 ;
|
||||
__bss_start = .;
|
||||
.bss (NOLOAD) :
|
||||
{
|
||||
*(.bss)
|
||||
}
|
||||
|
||||
_end = .;
|
||||
}
|
579
qiboot/src/cpu/s3c2410/s3c24xx-mci.c
Normal file
579
qiboot/src/cpu/s3c2410/s3c24xx-mci.c
Normal file
@ -0,0 +1,579 @@
|
||||
/*
|
||||
* qi s3c24xx SD card driver
|
||||
* Author: Andy Green <andy@openmoko.com>
|
||||
* based on ---->
|
||||
*
|
||||
* u-boot S3C2410 MMC/SD card driver
|
||||
* (C) Copyright 2006 by OpenMoko, Inc.
|
||||
* Author: Harald Welte <laforge@openmoko.org>
|
||||
*
|
||||
* based on u-boot pxa MMC driver and linux/drivers/mmc/s3c2410mci.c
|
||||
* (C) 2005-2005 Thomas Kleffel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <qi.h>
|
||||
#include <mmc.h>
|
||||
#include <s3c24xx-regs-sdi.h>
|
||||
#include <string.h>
|
||||
|
||||
#define SDICON (*(u32 *)0x5a000000)
|
||||
#define SDIPRE (*(u32 *)0x5a000004)
|
||||
#define SDICARG (*(u32 *)0x5a000008)
|
||||
#define SDICCON (*(u32 *)0x5a00000c)
|
||||
#define SDICSTA (*(u32 *)0x5a000010)
|
||||
#define SDIRSP0 (*(u32 *)0x5a000014)
|
||||
#define SDIRSP1 (*(u32 *)0x5a000018)
|
||||
#define SDIRSP2 (*(u32 *)0x5a00001c)
|
||||
#define SDIRSP3 (*(u32 *)0x5a000020)
|
||||
#define SDIDTIMER (*(u32 *)0x5a000024)
|
||||
#define SDIBSIZE (*(u32 *)0x5a000028)
|
||||
#define SDIDCON (*(u32 *)0x5a00002c)
|
||||
#define SDIDCNT (*(u32 *)0x5a000030)
|
||||
#define SDIDSTA (*(u32 *)0x5a000034)
|
||||
#define SDIFSTA (*(u32 *)0x5a000038)
|
||||
/* s3c2410 in GTA01 has these two last ones the other way around!!! */
|
||||
#define SDIIMSK (*(u32 *)0x5a00003c)
|
||||
#define SDIDAT (*(u32 *)0x5a000040)
|
||||
#define SDIDAT2410 (*(u32 *)0x5a00003c)
|
||||
#define SDIIMSK2410 (*(u32 *)0x5a000040)
|
||||
|
||||
#define CFG_MMC_BASE 0xff000000
|
||||
|
||||
int am_i_s3c2410(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define CONFIG_MMC_WIDE
|
||||
#define MMC_BLOCK_SIZE 512
|
||||
|
||||
/*
|
||||
* FIXME needs to read cid and csd info to determine block size
|
||||
* and other parameters
|
||||
*/
|
||||
static u8 mmc_buf[MMC_BLOCK_SIZE];
|
||||
static mmc_csd_t mmc_csd;
|
||||
static int mmc_ready = 0;
|
||||
static int wide = 0;
|
||||
static int is_sdhc = 0;
|
||||
|
||||
|
||||
#define CMD_F_RESP 0x01
|
||||
#define CMD_F_RESP_LONG 0x02
|
||||
|
||||
static u32 *mmc_cmd(u16 cmd, u32 arg, u16 flags)
|
||||
{
|
||||
static u32 resp[5];
|
||||
|
||||
u32 ccon, csta;
|
||||
u32 csta_rdy_bit = S3C2410_SDICMDSTAT_CMDSENT;
|
||||
|
||||
memset(resp, 0, sizeof(resp));
|
||||
|
||||
// debug("mmc_cmd CMD%d arg=0x%08x flags=%x\n", cmd, arg, flags);
|
||||
|
||||
SDICSTA = 0xffffffff;
|
||||
SDIDSTA = 0xffffffff;
|
||||
SDIFSTA = 0xffffffff;
|
||||
|
||||
SDICARG = arg;
|
||||
|
||||
ccon = cmd & S3C2410_SDICMDCON_INDEX;
|
||||
ccon |= S3C2410_SDICMDCON_SENDERHOST|S3C2410_SDICMDCON_CMDSTART;
|
||||
|
||||
if (flags & CMD_F_RESP) {
|
||||
ccon |= S3C2410_SDICMDCON_WAITRSP;
|
||||
csta_rdy_bit = S3C2410_SDICMDSTAT_RSPFIN; /* 1 << 9 */
|
||||
}
|
||||
|
||||
if (flags & CMD_F_RESP_LONG)
|
||||
ccon |= S3C2410_SDICMDCON_LONGRSP;
|
||||
|
||||
SDICCON = ccon;
|
||||
|
||||
while (1) {
|
||||
csta = SDICSTA;
|
||||
if (csta & csta_rdy_bit)
|
||||
break;
|
||||
if (csta & S3C2410_SDICMDSTAT_CMDTIMEOUT) {
|
||||
puts("===============> MMC CMD Timeout\n");
|
||||
SDICSTA |= S3C2410_SDICMDSTAT_CMDTIMEOUT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// debug("final MMC CMD status 0x%x\n", csta);
|
||||
|
||||
SDICSTA |= csta_rdy_bit;
|
||||
|
||||
if (flags & CMD_F_RESP) {
|
||||
resp[0] = SDIRSP0;
|
||||
resp[1] = SDIRSP1;
|
||||
resp[2] = SDIRSP2;
|
||||
resp[3] = SDIRSP3;
|
||||
}
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
#define FIFO_FILL() ((SDIFSTA & S3C2410_SDIFSTA_COUNTMASK) >> 2)
|
||||
|
||||
static int mmc_block_read(u8 *dst, u32 src, u32 len)
|
||||
{
|
||||
u32 dcon, fifo;
|
||||
u32 *dst_u32 = (u32 *)dst;
|
||||
u32 *resp;
|
||||
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
// debug("mmc_block_rd dst %lx src %lx len %d\n", (u32)dst, src, len);
|
||||
|
||||
/* set block len */
|
||||
resp = mmc_cmd(MMC_CMD_SET_BLOCKLEN, len, CMD_F_RESP);
|
||||
SDIBSIZE = len;
|
||||
|
||||
//SDIPRE = 0xff;
|
||||
|
||||
/* setup data */
|
||||
dcon = (len >> 9) & S3C2410_SDIDCON_BLKNUM;
|
||||
dcon |= S3C2410_SDIDCON_BLOCKMODE;
|
||||
dcon |= S3C2410_SDIDCON_RXAFTERCMD|S3C2410_SDIDCON_XFER_RXSTART;
|
||||
if (wide)
|
||||
dcon |= S3C2410_SDIDCON_WIDEBUS;
|
||||
|
||||
if (!am_i_s3c2410())
|
||||
dcon |= S3C2440_SDIDCON_DS_WORD | S3C2440_SDIDCON_DATSTART;
|
||||
|
||||
SDIDCON = dcon;
|
||||
|
||||
/* send read command */
|
||||
if (!is_sdhc)
|
||||
resp = mmc_cmd(MMC_CMD_READ_BLOCK, src, CMD_F_RESP);
|
||||
else
|
||||
resp = mmc_cmd(MMC_CMD_READ_BLOCK, src / MMC_BLOCK_SIZE, CMD_F_RESP);
|
||||
|
||||
while (len > 0) {
|
||||
u32 sdidsta = SDIDSTA;
|
||||
fifo = FIFO_FILL();
|
||||
if (sdidsta & (S3C2410_SDIDSTA_FIFOFAIL|
|
||||
S3C2410_SDIDSTA_CRCFAIL|
|
||||
S3C2410_SDIDSTA_RXCRCFAIL|
|
||||
S3C2410_SDIDSTA_DATATIMEOUT)) {
|
||||
puts("mmc_block_read: err SDIDSTA=0x");
|
||||
print32(sdidsta);
|
||||
puts("\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (am_i_s3c2410()) {
|
||||
while (fifo--) {
|
||||
//debug("dst_u32 = 0x%08x\n", dst_u32);
|
||||
*(dst_u32++) = SDIDAT2410;
|
||||
if (len >= 4)
|
||||
len -= 4;
|
||||
else {
|
||||
len = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (fifo--) {
|
||||
//debug("dst_u32 = 0x%08x\n", dst_u32);
|
||||
*(dst_u32++) = SDIDAT;
|
||||
if (len >= 4)
|
||||
len -= 4;
|
||||
else {
|
||||
len = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// debug("waiting for SDIDSTA (currently 0x%08x\n", SDIDSTA);
|
||||
while (!(SDIDSTA & (1 << 4))) {}
|
||||
// debug("done waiting for SDIDSTA (currently 0x%08x\n", SDIDSTA);
|
||||
|
||||
SDIDCON = 0;
|
||||
|
||||
if (!(SDIDSTA & S3C2410_SDIDSTA_XFERFINISH))
|
||||
puts("mmc_block_read; transfer not finished!\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mmc_block_write(u32 dst, u8 *src, int len)
|
||||
{
|
||||
puts("MMC block write not yet supported on S3C2410!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int s3c24xx_mmc_read(u32 src, u8 *dst, int size)
|
||||
{
|
||||
u32 end, part_start, part_end, part_len, aligned_start, aligned_end;
|
||||
u32 mmc_block_size, mmc_block_address;
|
||||
|
||||
if (size == 0)
|
||||
return 0;
|
||||
|
||||
if (!mmc_ready) {
|
||||
puts("Please initialize the MMC first\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mmc_block_size = MMC_BLOCK_SIZE;
|
||||
mmc_block_address = ~(mmc_block_size - 1);
|
||||
|
||||
src -= CFG_MMC_BASE;
|
||||
end = src + size;
|
||||
part_start = ~mmc_block_address & src;
|
||||
part_end = ~mmc_block_address & end;
|
||||
aligned_start = mmc_block_address & src;
|
||||
aligned_end = mmc_block_address & end;
|
||||
|
||||
/* all block aligned accesses */
|
||||
// debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
if (part_start) {
|
||||
part_len = mmc_block_size - part_start;
|
||||
// debug("ps src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
if ((mmc_block_read(mmc_buf, aligned_start, mmc_block_size)) < 0)
|
||||
return -1;
|
||||
|
||||
memcpy(dst, mmc_buf+part_start, part_len);
|
||||
dst += part_len;
|
||||
src += part_len;
|
||||
}
|
||||
// debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
for (; src < aligned_end; src += mmc_block_size, dst += mmc_block_size) {
|
||||
// debug("al src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
if ((mmc_block_read((u8 *)(dst), src, mmc_block_size)) < 0)
|
||||
return -1;
|
||||
}
|
||||
// debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
if (part_end && src < end) {
|
||||
// debug("pe src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
if ((mmc_block_read(mmc_buf, aligned_end, mmc_block_size)) < 0)
|
||||
return -1;
|
||||
|
||||
memcpy(dst, mmc_buf, part_end);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int s3c24xx_mmc_write(u8 *src, u32 dst, int size)
|
||||
{
|
||||
u32 end, part_start, part_end, part_len, aligned_start, aligned_end;
|
||||
u32 mmc_block_size, mmc_block_address;
|
||||
|
||||
if (size == 0)
|
||||
return 0;
|
||||
|
||||
if (!mmc_ready) {
|
||||
puts("Please initialize the MMC first\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mmc_block_size = MMC_BLOCK_SIZE;
|
||||
mmc_block_address = ~(mmc_block_size - 1);
|
||||
|
||||
dst -= CFG_MMC_BASE;
|
||||
end = dst + size;
|
||||
part_start = ~mmc_block_address & dst;
|
||||
part_end = ~mmc_block_address & end;
|
||||
aligned_start = mmc_block_address & dst;
|
||||
aligned_end = mmc_block_address & end;
|
||||
|
||||
/* all block aligned accesses */
|
||||
// debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
if (part_start) {
|
||||
part_len = mmc_block_size - part_start;
|
||||
// debug("ps src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// (u32)src, dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
if ((mmc_block_read(mmc_buf, aligned_start, mmc_block_size)) < 0)
|
||||
return -1;
|
||||
|
||||
memcpy(mmc_buf+part_start, src, part_len);
|
||||
if ((mmc_block_write(aligned_start, mmc_buf, mmc_block_size)) < 0)
|
||||
return -1;
|
||||
|
||||
dst += part_len;
|
||||
src += part_len;
|
||||
}
|
||||
// debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
for (; dst < aligned_end; src += mmc_block_size, dst += mmc_block_size) {
|
||||
// debug("al src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
if ((mmc_block_write(dst, (u8 *)src, mmc_block_size)) < 0)
|
||||
return -1;
|
||||
|
||||
}
|
||||
// debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
if (part_end && dst < end) {
|
||||
// debug("pe src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
if ((mmc_block_read(mmc_buf, aligned_end, mmc_block_size)) < 0)
|
||||
return -1;
|
||||
|
||||
memcpy(mmc_buf, src, part_end);
|
||||
if ((mmc_block_write(aligned_end, mmc_buf, mmc_block_size)) < 0)
|
||||
return -1;
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 s3c24xx_mmc_bread(int dev_num, u32 blknr, u32 blkcnt, void *dst)
|
||||
{
|
||||
int mmc_block_size = MMC_BLOCK_SIZE;
|
||||
u32 src = blknr * mmc_block_size + CFG_MMC_BASE;
|
||||
|
||||
s3c24xx_mmc_read(src, dst, blkcnt*mmc_block_size);
|
||||
return blkcnt;
|
||||
}
|
||||
|
||||
/* MMC_DEFAULT_RCA should probably be just 1, but this may break other code
|
||||
that expects it to be shifted. */
|
||||
static u_int16_t rca = MMC_DEFAULT_RCA >> 16;
|
||||
|
||||
#if 0
|
||||
static u32 mmc_size(const struct mmc_csd *csd)
|
||||
{
|
||||
u32 block_len, mult, blocknr;
|
||||
|
||||
block_len = csd->read_bl_len << 12;
|
||||
mult = csd->c_size_mult1 << 8;
|
||||
blocknr = (csd->c_size+1) * mult;
|
||||
|
||||
return blocknr * block_len;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct sd_cid {
|
||||
char pnm_0; /* product name */
|
||||
char oid_1; /* OEM/application ID */
|
||||
char oid_0;
|
||||
uint8_t mid; /* manufacturer ID */
|
||||
char pnm_4;
|
||||
char pnm_3;
|
||||
char pnm_2;
|
||||
char pnm_1;
|
||||
uint8_t psn_2; /* product serial number */
|
||||
uint8_t psn_1;
|
||||
uint8_t psn_0; /* MSB */
|
||||
uint8_t prv; /* product revision */
|
||||
uint8_t crc; /* CRC7 checksum, b0 is unused and set to 1 */
|
||||
uint8_t mdt_1; /* manufacturing date, LSB, RRRRyyyy yyyymmmm */
|
||||
uint8_t mdt_0; /* MSB */
|
||||
uint8_t psn_3; /* LSB */
|
||||
};
|
||||
|
||||
static void print_mmc_cid(mmc_cid_t *cid)
|
||||
{
|
||||
puts("MMC found. Card desciption is:\n");
|
||||
puts("Manufacturer ID = ");
|
||||
print8(cid->id[0]);
|
||||
print8(cid->id[1]);
|
||||
print8(cid->id[2]);
|
||||
puts("\nHW/FW Revision = ");
|
||||
print8(cid->hwrev);
|
||||
print8(cid->fwrev);
|
||||
cid->hwrev = cid->fwrev = 0; /* null terminate string */
|
||||
puts("Product Name = ");
|
||||
puts((char *)cid->name);
|
||||
puts("\nSerial Number = ");
|
||||
print8(cid->sn[0]);
|
||||
print8(cid->sn[1]);
|
||||
print8(cid->sn[2]);
|
||||
puts("\nMonth = ");
|
||||
printdec(cid->month);
|
||||
puts("\nYear = ");
|
||||
printdec(1997 + cid->year);
|
||||
puts("\n");
|
||||
}
|
||||
|
||||
static void print_sd_cid(const struct sd_cid *cid)
|
||||
{
|
||||
puts("Manufacturer: 0x");
|
||||
print8(cid->mid);
|
||||
puts("OEM \"");
|
||||
this_board->putc(cid->oid_0);
|
||||
this_board->putc(cid->oid_1);
|
||||
puts("\"\nProduct name: \"");
|
||||
this_board->putc(cid->pnm_0);
|
||||
this_board->putc(cid->pnm_1);
|
||||
this_board->putc(cid->pnm_2);
|
||||
this_board->putc(cid->pnm_3);
|
||||
this_board->putc(cid->pnm_4);
|
||||
puts("\", revision ");
|
||||
printdec(cid->prv >> 4);
|
||||
puts(".");
|
||||
printdec(cid->prv & 15);
|
||||
puts("\nSerial number: ");
|
||||
printdec(cid->psn_0 << 24 | cid->psn_1 << 16 | cid->psn_2 << 8 |
|
||||
cid->psn_3);
|
||||
puts("\nManufacturing date: ");
|
||||
printdec(cid->mdt_1 & 15);
|
||||
puts("/");
|
||||
printdec(2000+((cid->mdt_0 & 15) << 4)+((cid->mdt_1 & 0xf0) >> 4));
|
||||
puts("\nCRC: 0x");
|
||||
print8(cid->crc >> 1);
|
||||
puts(" b0 = ");
|
||||
print8(cid->crc & 1);
|
||||
puts("\n");
|
||||
}
|
||||
|
||||
int s3c24xx_mmc_init(int verbose)
|
||||
{
|
||||
int retries, rc = -2;
|
||||
int is_sd = 0;
|
||||
u32 *resp;
|
||||
u32 hcs = 0;
|
||||
|
||||
SDICON = S3C2410_SDICON_FIFORESET | S3C2410_SDICON_CLOCKTYPE;
|
||||
SDIBSIZE = 512;
|
||||
if (am_i_s3c2410()) {
|
||||
/* S3C2410 has some bug that prevents reliable operation at higher speed */
|
||||
//SDIPRE = 0x3e; /* SDCLK = PCLK/2 / (SDIPRE+1) = 396kHz */
|
||||
SDIPRE = 0x02; /* 2410: SDCLK = PCLK/2 / (SDIPRE+1) = 11MHz */
|
||||
SDIDTIMER = 0xffff;
|
||||
SDIIMSK2410 = 0x0;
|
||||
} else {
|
||||
SDIPRE = 0x05; /* 2410: SDCLK = PCLK / (SDIPRE+1) = 11MHz */
|
||||
SDIDTIMER = 0x7fffff;
|
||||
SDIIMSK = 0x0;
|
||||
}
|
||||
|
||||
udelay(1250000); /* FIXME: 74 SDCLK cycles */
|
||||
|
||||
mmc_csd.c_size = 0;
|
||||
|
||||
puts("Sending reset...\n");
|
||||
|
||||
/* reset */
|
||||
retries = 10;
|
||||
resp = mmc_cmd(MMC_CMD_RESET, 0, 0);
|
||||
|
||||
resp = mmc_cmd(8, 0x000001aa, CMD_F_RESP);
|
||||
if ((resp[0] & 0xff) == 0xaa) {
|
||||
puts("The card is either SD2.0 or SDHC\n");
|
||||
hcs = 0x40000000;
|
||||
}
|
||||
|
||||
puts("trying to detect SD Card...\n");
|
||||
while (retries--) {
|
||||
udelay(1000000);
|
||||
resp = mmc_cmd(55, 0x00000000, CMD_F_RESP);
|
||||
resp = mmc_cmd(41, hcs | 0x00300000, CMD_F_RESP);
|
||||
|
||||
if (resp[0] & (1 << 30))
|
||||
is_sdhc = 1;
|
||||
|
||||
if (resp[0] & (1 << 31)) {
|
||||
is_sd = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (retries < 0 && !is_sd)
|
||||
return -3;
|
||||
|
||||
/* try to get card id */
|
||||
resp = mmc_cmd(MMC_CMD_ALL_SEND_CID, hcs, CMD_F_RESP|CMD_F_RESP_LONG);
|
||||
if (resp) {
|
||||
if (!is_sd) {
|
||||
/* TODO configure mmc driver depending on card
|
||||
attributes */
|
||||
mmc_cid_t *cid = (mmc_cid_t *)resp;
|
||||
|
||||
if (verbose)
|
||||
print_mmc_cid(cid);
|
||||
#if 0
|
||||
sprintf((char *) mmc_dev.vendor,
|
||||
"Man %02x%02x%02x Snr %02x%02x%02x",
|
||||
cid->id[0], cid->id[1], cid->id[2],
|
||||
cid->sn[0], cid->sn[1], cid->sn[2]);
|
||||
sprintf((char *) mmc_dev.product,"%s",cid->name);
|
||||
sprintf((char *) mmc_dev.revision,"%x %x",
|
||||
cid->hwrev, cid->fwrev);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
struct sd_cid *cid = (struct sd_cid *) resp;
|
||||
|
||||
if (verbose)
|
||||
print_sd_cid(cid);
|
||||
#if 0
|
||||
sprintf((char *) mmc_dev.vendor,
|
||||
"Man %02 OEM %c%c \"%c%c%c%c%c\"",
|
||||
cid->mid, cid->oid_0, cid->oid_1,
|
||||
cid->pnm_0, cid->pnm_1, cid->pnm_2, cid->pnm_3,
|
||||
cid->pnm_4);
|
||||
sprintf((char *) mmc_dev.product, "%d",
|
||||
cid->psn_0 << 24 | cid->psn_1 << 16 |
|
||||
cid->psn_2 << 8 | cid->psn_3);
|
||||
sprintf((char *) mmc_dev.revision, "%d.%d",
|
||||
cid->prv >> 4, cid->prv & 15);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* MMC exists, get CSD too */
|
||||
resp = mmc_cmd(MMC_CMD_SET_RCA, MMC_DEFAULT_RCA, CMD_F_RESP);
|
||||
if (is_sd)
|
||||
rca = resp[0] >> 16;
|
||||
|
||||
resp = mmc_cmd(MMC_CMD_SEND_CSD, rca<<16, CMD_F_RESP|CMD_F_RESP_LONG);
|
||||
if (resp) {
|
||||
mmc_csd_t *csd = (mmc_csd_t *)resp;
|
||||
memcpy(&mmc_csd, csd, sizeof(csd));
|
||||
rc = 0;
|
||||
mmc_ready = 1;
|
||||
#if 0
|
||||
/* FIXME add verbose printout for csd */
|
||||
printf("READ_BL_LEN=%u, C_SIZE_MULT=%u, C_SIZE=%u\n",
|
||||
csd->read_bl_len, csd->c_size_mult1, csd->c_size);
|
||||
printf("size = %u\n", mmc_size(csd));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
resp = mmc_cmd(MMC_CMD_SELECT_CARD, rca<<16, CMD_F_RESP);
|
||||
|
||||
#ifdef CONFIG_MMC_WIDE
|
||||
if (is_sd) {
|
||||
resp = mmc_cmd(55, rca<<16, CMD_F_RESP);
|
||||
resp = mmc_cmd(6, 0x02, CMD_F_RESP);
|
||||
wide = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
77
qiboot/src/cpu/s3c2410/serial-s3c24xx.c
Normal file
77
qiboot/src/cpu/s3c2410/serial-s3c24xx.c
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
* Author: xiangfu liu <xiangfu@openmoko.org>
|
||||
*
|
||||
* Configuation settings for the FIC Neo GTA02 Linux GSM phone
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <qi.h>
|
||||
#include <serial-s3c24xx.h>
|
||||
|
||||
void serial_init_115200_s3c24xx(const int uart, const int pclk_MHz)
|
||||
{
|
||||
int div = (((54 * pclk_MHz) + 26) / 100) -1;
|
||||
switch(uart)
|
||||
{
|
||||
case UART0:
|
||||
rULCON0 = 0x3;
|
||||
rUCON0 = 0x245;
|
||||
rUFCON0 = 0x0;
|
||||
rUMCON0 = 0x0;
|
||||
rUBRDIV0 = div;
|
||||
break;
|
||||
case UART1:
|
||||
rULCON1 = 0x3;
|
||||
rUCON1 = 0x245;
|
||||
rUFCON1 = 0x0;
|
||||
rUMCON1 = 0x0;
|
||||
rUBRDIV1 = div;
|
||||
break;
|
||||
case UART2:
|
||||
rULCON2 = 0x3;
|
||||
rUCON2 = 0x245;
|
||||
rUFCON2 = 0x1;
|
||||
rUBRDIV2 = div;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Output a single byte to the serial port.
|
||||
*/
|
||||
void serial_putc_s3c24xx(const int uart, const char c)
|
||||
{
|
||||
switch(uart)
|
||||
{
|
||||
case UART0:
|
||||
while ( !( rUTRSTAT0 & 0x2 ) );
|
||||
WrUTXH0(c);
|
||||
break;
|
||||
case UART1:
|
||||
while ( !( rUTRSTAT1 & 0x2 ) );
|
||||
WrUTXH1(c);
|
||||
break;
|
||||
case UART2:
|
||||
while ( !( rUTRSTAT2 & 0x2 ) );
|
||||
WrUTXH2(c);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
304
qiboot/src/cpu/s3c2410/start.S
Normal file
304
qiboot/src/cpu/s3c2410/start.S
Normal file
@ -0,0 +1,304 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
*
|
||||
* Configuation settings for the OPENMOKO Neo GTA02 Linux GSM phone
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#define __ASM_MODE__
|
||||
#define __ASSEMBLY__
|
||||
|
||||
#include <neo_gta01.h>
|
||||
|
||||
#define S3C2410_MISCCR_nEN_SCLK0 (1 << 17)
|
||||
#define S3C2410_MISCCR_nEN_SCLK1 (1 << 18)
|
||||
#define S3C2410_MISCCR_nEN_SCLKE (1 << 19)
|
||||
|
||||
|
||||
.globl _start, processor_id, is_jtag
|
||||
|
||||
_start: b start_code
|
||||
/* if we are injected by JTAG, the script sets _istag content to nonzero */
|
||||
is_jtag:
|
||||
.word 0
|
||||
|
||||
/* it's at a fixed address (+0x8) so we can breakpoint it in the JTAG script
|
||||
* we need to go through this hassle because before this moment, SDRAM is not
|
||||
* working so we can't prep it from JTAG
|
||||
*/
|
||||
|
||||
_steppingstone_done:
|
||||
ldr pc, _start_armboot
|
||||
|
||||
_start_armboot:
|
||||
.word start_qi
|
||||
|
||||
_TEXT_BASE:
|
||||
.word TEXT_BASE
|
||||
|
||||
/*
|
||||
* These are defined in the board-specific linker script.
|
||||
*/
|
||||
.globl _bss_start
|
||||
_bss_start:
|
||||
.word __bss_start
|
||||
|
||||
.globl _bss_end
|
||||
_bss_end:
|
||||
.word _end
|
||||
/*
|
||||
* we have a stack in steppingstone because we can want to run full memory
|
||||
* memory tests
|
||||
*/
|
||||
|
||||
.fill 128
|
||||
.globl _ss_stack
|
||||
_ss_stack:
|
||||
|
||||
|
||||
start_code:
|
||||
/*
|
||||
* set the cpu to SVC32 mode
|
||||
*/
|
||||
mrs r0,cpsr
|
||||
bic r0,r0,#0x1f
|
||||
orr r0,r0,#0xd3
|
||||
msr cpsr,r0
|
||||
|
||||
# define pWTCON 0x53000000
|
||||
|
||||
ldr r0, =pWTCON
|
||||
mov r1, #0x0
|
||||
str r1, [r0]
|
||||
|
||||
/*
|
||||
* mask all IRQs by setting all bits in the INTMR - default
|
||||
*/
|
||||
# define INTMSK 0x4A000008 /* Interupt-Controller base addresses */
|
||||
# define INTSUBMSK 0x4A00001C
|
||||
# define INTSUBMSK_val 0x000007ff
|
||||
|
||||
mov r1, #0xffffffff
|
||||
ldr r0, =INTMSK
|
||||
str r1, [r0]
|
||||
|
||||
ldr r1, =INTSUBMSK_val
|
||||
ldr r0, =INTSUBMSK
|
||||
str r1, [r0]
|
||||
|
||||
/* Clock asynchronous mode */
|
||||
mrc p15, 0, r1, c1, c0, 0
|
||||
orr r1, r1, #0xc0000000
|
||||
mcr p15, 0, r1, c1, c0, 0
|
||||
|
||||
#define LOCKTIME 0x4c000000
|
||||
|
||||
ldr r0, =LOCKTIME
|
||||
mov r1, #0xffffff
|
||||
str r1, [r0]
|
||||
|
||||
# define UPLLCON 0x4c000008
|
||||
# define MPLLCON_val ((0x90 << 12) + (0x7 << 4) + 0x0) /* 202 MHz */
|
||||
# define UPLLCON_val ((0x78 << 12) + (0x2 << 4) + 0x3)
|
||||
|
||||
ldr r0, =UPLLCON
|
||||
ldr r1, =UPLLCON_val
|
||||
str r1, [r0]
|
||||
|
||||
/* Page 7-19, seven nops between UPLL and MPLL */
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
ldr r1, =MPLLCON_val
|
||||
str r1, [r0, #-4] /* MPLLCON */
|
||||
|
||||
# define CLKDIVN 0x4C000014 /* clock divisor register */
|
||||
# define CLKDIVN_val 3 /* FCLK:HCLK:PCLK = 1:2:4 */
|
||||
|
||||
/* FCLK:HCLK:PCLK = 1:3:6 */
|
||||
ldr r0, =CLKDIVN
|
||||
mov r1, #CLKDIVN_val
|
||||
str r1, [r0]
|
||||
|
||||
/* enable only CPU peripheral block clocks we actually use */
|
||||
ldr r0, =0x4c00000c /* clkcon */
|
||||
ldr r1, =0x3f10 /* uart, pwm, gpio, nand, sdi clocks on */
|
||||
str r1, [r0]
|
||||
|
||||
/* gpio UART0 init */
|
||||
ldr r0, =0x56000070
|
||||
ldr r1, =0x000000AA
|
||||
str r1, [r0]
|
||||
|
||||
/* init uart0 */
|
||||
ldr r0, =0x50000000
|
||||
mov r1, #0x03
|
||||
str r1, [r0]
|
||||
ldr r1, =0x245
|
||||
str r1, [r0, #0x04]
|
||||
mov r1, #0x01
|
||||
str r1, [r0, #0x08]
|
||||
mov r1, #0x00
|
||||
str r1, [r0, #0x0c]
|
||||
mov r1, #0x1a
|
||||
str r1, [r0, #0x28]
|
||||
|
||||
/* reset nand controller, or it is dead to us */
|
||||
|
||||
#define oNFCONF 0x00
|
||||
#define oNFCMD 0x04
|
||||
#define oNFSTAT 0x10
|
||||
|
||||
mov r1, #0x4E000000
|
||||
ldr r2, =0xf842 @ initial value enable tacls=3,rph0=6,rph1=0
|
||||
str r2, [r1, #oNFCONF]
|
||||
ldr r2, [r1, #oNFCONF]
|
||||
bic r2, r2, #0x800 @ enable chip
|
||||
str r2, [r1, #oNFCONF]
|
||||
mov r2, #0xff @ RESET command
|
||||
strb r2, [r1, #oNFCMD]
|
||||
mov r3, #0 @ wait
|
||||
1: add r3, r3, #0x1
|
||||
cmp r3, #0xa
|
||||
blt 1b
|
||||
2: ldr r2, [r1, #oNFSTAT] @ wait ready
|
||||
tst r2, #0x1
|
||||
beq 2b
|
||||
ldr r2, [r1, #oNFCONF]
|
||||
orr r2, r2, #0x800 @ disable chip
|
||||
str r2, [r1, #oNFCONF]
|
||||
|
||||
/* take sdram out of power down */
|
||||
ldr r0, =0x56000080 /* misccr */
|
||||
ldr r1, [ r0 ]
|
||||
bic r1, r1, #(S3C2410_MISCCR_nEN_SCLK0 | S3C2410_MISCCR_nEN_SCLK1 | S3C2410_MISCCR_nEN_SCLKE)
|
||||
str r1, [ r0 ]
|
||||
|
||||
/* ensure signals stabalise */
|
||||
mov r1, #128
|
||||
3: subs r1, r1, #1
|
||||
bpl 3b
|
||||
|
||||
bl cpu_init_crit
|
||||
|
||||
/* ensure some refresh has happened */
|
||||
ldr r1, =0xfffff
|
||||
4: subs r1, r1, #1
|
||||
bpl 4b
|
||||
|
||||
/* capture full EINT situation into gstatus 4 */
|
||||
|
||||
ldr r0, =0x4A000000 /* SRCPND */
|
||||
ldr r1, [ r0 ]
|
||||
and r1, r1, #0xf
|
||||
|
||||
ldr r0, =0x560000BC /* gstatus4 */
|
||||
str r1, [ r0 ]
|
||||
|
||||
ldr r0, =0x560000A8 /* EINTPEND */
|
||||
ldr r1, [ r0 ]
|
||||
ldr r0, =0xfff0
|
||||
and r1, r1, r0
|
||||
ldr r0, =0x560000BC /* gstatus4 */
|
||||
ldr r0, [ r0 ]
|
||||
orr r1, r1, r0
|
||||
ldr r0, =0x560000BC /* gstatus4 */
|
||||
str r1, [ r0 ]
|
||||
|
||||
/* test for resume */
|
||||
|
||||
ldr r1, =0x560000B4 /* gstatus2 */
|
||||
ldr r0, [ r1 ]
|
||||
tst r0, #0x02 /* is this resume from power down */
|
||||
/* well, if it was, we are going to jump to
|
||||
* whatever address we stashed in gstatus3,
|
||||
* and gstatus4 will hold the wake interrupt
|
||||
* source for the OS to look at
|
||||
*/
|
||||
ldrne pc, [r1, #4]
|
||||
|
||||
|
||||
/* >> CFG_VIDEO_LOGO_MAX_SIZE */
|
||||
#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
|
||||
|
||||
stack_setup:
|
||||
ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
|
||||
sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */
|
||||
sub sp, r0, #12 /* leave 3 words for abort-stack */
|
||||
|
||||
clear_bss:
|
||||
ldr r0, _bss_start /* find start of bss segment */
|
||||
ldr r1, _bss_end /* stop here */
|
||||
mov r2, #0x00000000 /* clear */
|
||||
|
||||
clbss_l:
|
||||
str r2, [r0] /* clear loop... */
|
||||
add r0, r0, #4
|
||||
cmp r0, r1
|
||||
ble clbss_l
|
||||
|
||||
/* we are going to jump into the C part of the init now */
|
||||
spin:
|
||||
b _steppingstone_done
|
||||
|
||||
/*
|
||||
*************************************************************************
|
||||
*
|
||||
* CPU_init_critical registers
|
||||
*
|
||||
* setup important registers
|
||||
* setup memory timing
|
||||
*
|
||||
*************************************************************************
|
||||
*/
|
||||
|
||||
cpu_init_crit:
|
||||
|
||||
/*
|
||||
* flush v4 I/D caches
|
||||
*/
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
|
||||
mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
|
||||
|
||||
/*
|
||||
* disable MMU stuff and caches
|
||||
*/
|
||||
mrc p15, 0, r0, c1, c0, 0
|
||||
bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
|
||||
bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
|
||||
orr r0, r0, #0x00000002 @ set bit 2 (A) Align
|
||||
orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
|
||||
mcr p15, 0, r0, c1, c0, 0
|
||||
|
||||
/*
|
||||
* before relocating, we have to setup RAM timing
|
||||
* because memory timing is board-dependend, you will
|
||||
* find a lowlevel_init.S in your board directory.
|
||||
*/
|
||||
mov ip, lr
|
||||
|
||||
bl lowlevel_init
|
||||
|
||||
mov lr, ip
|
||||
mov pc, lr
|
||||
|
131
qiboot/src/cpu/s3c2410/start_qi.c
Normal file
131
qiboot/src/cpu/s3c2410/start_qi.c
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
* Author: xiangfu liu <xiangfu@openmoko.org>
|
||||
* Andy Green <andy@openmoko.com>
|
||||
*
|
||||
* Configuation settings for the OPENMOKO Neo GTA02 Linux GSM phone
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* NOTE this stuff runs in steppingstone context! */
|
||||
|
||||
|
||||
#include <qi.h>
|
||||
#include "nand_read.h"
|
||||
#include <neo_gta01.h>
|
||||
|
||||
#define stringify2(s) stringify1(s)
|
||||
#define stringify1(s) #s
|
||||
|
||||
|
||||
extern void bootloader_second_phase(void);
|
||||
|
||||
const struct board_api *boards[] = {
|
||||
&board_api_gta01,
|
||||
NULL /* always last */
|
||||
};
|
||||
|
||||
|
||||
struct board_api const * this_board;
|
||||
extern int is_jtag;
|
||||
|
||||
void start_qi(void)
|
||||
{
|
||||
int flag = 0;
|
||||
int board = 0;
|
||||
|
||||
/*
|
||||
* well, we can be running on this CPU two different ways.
|
||||
*
|
||||
* 1) We were copied into steppingstone and TEXT_BASE already
|
||||
* by JTAG. We don't have to do anything else. JTAG script
|
||||
* then sets data at address 0x4 to 0xffffffff as a signal we
|
||||
* are running by JTAG.
|
||||
*
|
||||
* 2) We only got our first 4K into steppingstone, we need to copy
|
||||
* the rest of ourselves into TEXT_BASE.
|
||||
*
|
||||
* So we do the copy out of NAND only if we see we did not come up
|
||||
* under control of JTAG.
|
||||
*/
|
||||
|
||||
if (!is_jtag)
|
||||
/*
|
||||
* We got the first 4KBytes of the bootloader pulled into the
|
||||
* steppingstone SRAM for free. Now we pull the whole bootloader
|
||||
* image into SDRAM.
|
||||
*
|
||||
* This code and the .S files are arranged by the linker script
|
||||
* to expect to run from 0x0. But the linker script has told
|
||||
* everything else to expect to run from 0x33000000+. That's
|
||||
* why we are going to be able to copy this code and not have it
|
||||
* crash when we run it from there.
|
||||
*/
|
||||
|
||||
/* We randomly pull 32KBytes of bootloader */
|
||||
if (nand_read_ll((u8 *)TEXT_BASE, 0, 32 * 1024 / 512) < 0)
|
||||
goto unhappy;
|
||||
|
||||
/* ask all the boards we support in turn if they recognize this
|
||||
* hardware we are running on, accept the first positive answer
|
||||
*/
|
||||
|
||||
this_board = boards[board];
|
||||
while (!flag && this_board) {
|
||||
|
||||
/* check if it is the right board... */
|
||||
if (this_board->is_this_board()) {
|
||||
flag = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
this_board = boards[board++];
|
||||
}
|
||||
|
||||
/* No valid board found */
|
||||
if (!this_board)
|
||||
goto unhappy;
|
||||
|
||||
this_board->port_init();
|
||||
set_putc_func(this_board->putc);
|
||||
|
||||
/* stick some hello messages on debug console */
|
||||
|
||||
puts("\n\n\nQi Bootloader "stringify2(QI_CPU)" "
|
||||
stringify2(BUILD_HOST)" "
|
||||
stringify2(BUILD_VERSION)" "
|
||||
"\n");
|
||||
|
||||
puts(stringify2(BUILD_DATE) " Copyright (C) 2008 Openmoko, Inc.\n");
|
||||
puts("\n Detected: ");
|
||||
|
||||
puts(this_board->name);
|
||||
puts(", ");
|
||||
puts((this_board->get_board_variant)()->name);
|
||||
puts("\n");
|
||||
|
||||
|
||||
/*
|
||||
* jump to bootloader_second_phase() running from DRAM copy
|
||||
*/
|
||||
bootloader_second_phase();
|
||||
|
||||
unhappy:
|
||||
while(1)
|
||||
;
|
||||
|
||||
}
|
740
qiboot/src/cpu/s3c2442/gta02.c
Normal file
740
qiboot/src/cpu/s3c2442/gta02.c
Normal file
@ -0,0 +1,740 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
* Author: Andy Green <andy@openmoko.com>
|
||||
*
|
||||
* (port_init_gta02 came out of Openmoko U-Boot)
|
||||
*
|
||||
* Configuation settings for the OPENMOKO Neo GTA02 Linux GSM phone
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <qi.h>
|
||||
#include <neo_gta02.h>
|
||||
#include <serial-s3c24xx.h>
|
||||
#include <ports-s3c24xx.h>
|
||||
#include <i2c-bitbang-s3c24xx.h>
|
||||
#include <pcf50633.h>
|
||||
#include <glamo-init.h>
|
||||
#include <string.h>
|
||||
#include <ext2.h>
|
||||
|
||||
#define GTA02_DEBUG_UART 2
|
||||
#define PCF50633_I2C_ADS 0x73
|
||||
#define BOOST_TO_400MHZ 1
|
||||
|
||||
static int battery_condition_reasonable = 0;
|
||||
|
||||
extern unsigned long partition_offset_blocks;
|
||||
extern unsigned long partition_length_blocks;
|
||||
|
||||
const struct board_api board_api_gta02;
|
||||
|
||||
struct nand_dynparts {
|
||||
const char *name; /* name of this partition for Linux */
|
||||
u32 good_length; /* bytes needed from good sectors in this partition */
|
||||
u32 true_offset;
|
||||
};
|
||||
|
||||
/*
|
||||
* These are the NAND partitions U-Boot leaves in GTA02 NAND.
|
||||
* The "dynparts" business means that in the case of bad blocks, all the
|
||||
* following partitions move up accordingly to have the right amount of
|
||||
* good blocks. To allow for this, the length of the last, largest
|
||||
* partition is computed according to the bad blocks that went before.
|
||||
*/
|
||||
|
||||
static struct nand_dynparts nand_dynparts[] = {
|
||||
{ "qi", 0x40000 },
|
||||
{ "depr-ub-env", 0x40000 },
|
||||
{ "kernel", 0x800000 },
|
||||
{ "depr", 0xa0000 },
|
||||
{ "identity-ext2", 0x40000 },
|
||||
{ "rootfs", 0 },
|
||||
};
|
||||
|
||||
static u32 nand_extent_block512 = 256 * 1024 * 1024 / 512;
|
||||
|
||||
const struct pcf50633_init pcf50633_init[] = {
|
||||
|
||||
{ PCF50633_REG_OOCWAKE, 0xd3 }, /* wake from ONKEY,EXTON!,RTC,USB,ADP */
|
||||
{ PCF50633_REG_OOCTIM1, 0xaa }, /* debounce 14ms everything */
|
||||
{ PCF50633_REG_OOCTIM2, 0x4a },
|
||||
{ PCF50633_REG_OOCMODE, 0x55 },
|
||||
{ PCF50633_REG_OOCCTL, 0x47 },
|
||||
|
||||
{ PCF50633_REG_GPIO2CFG, 0x00 }, /* GSM_ON = 0 */
|
||||
{ PCF50633_REG_GPIOCTL, 0x01 }, /* only GPIO1 is input */
|
||||
|
||||
{ PCF50633_REG_SVMCTL, 0x08 }, /* 3.10V SYS vth, 62ms filter */
|
||||
{ PCF50633_REG_BVMCTL, 0x02 }, /* 2.80V BAT vth, 62ms filter */
|
||||
|
||||
{ PCF50633_REG_AUTOENA, 0x01 }, /* always on */
|
||||
|
||||
{ PCF50633_REG_DOWN1OUT, 0x1b }, /* 1.3V (0x1b * .025V + 0.625V) */
|
||||
{ PCF50633_REG_DOWN1ENA, 0x02 }, /* enabled if GPIO1 = HIGH */
|
||||
{ PCF50633_REG_HCLDOOUT, 21 }, /* 3.0V (21 * 0.1V + 0.9V) */
|
||||
{ PCF50633_REG_HCLDOENA, 0x01 }, /* ON by default*/
|
||||
|
||||
{ PCF50633_REG_DOWN1OUT, 0x1b }, /* 1.3V (0x1b * .025V + 0.625V) */
|
||||
{ PCF50633_REG_DOWN1ENA, 0x02 }, /* enabled if GPIO1 = HIGH */
|
||||
|
||||
{ PCF50633_REG_INT1M, 0x00 },
|
||||
{ PCF50633_REG_INT2M, 0x00 },
|
||||
{ PCF50633_REG_INT3M, 0x00 },
|
||||
{ PCF50633_REG_INT4M, 0x00 },
|
||||
{ PCF50633_REG_INT5M, 0x00 },
|
||||
|
||||
{ PCF50633_REG_MBCC2, 0x28 }, /* Vbatconid=2.7V, Vmax=4.20V */
|
||||
{ PCF50633_REG_MBCC3, 0x19 }, /* 25/255 == 98mA pre-charge */
|
||||
{ PCF50633_REG_MBCC4, 0xff }, /* 255/255 == 1A adapter fast */
|
||||
{ PCF50633_REG_MBCC5, 0xff }, /* 255/255 == 1A usb fast */
|
||||
{ PCF50633_REG_MBCC6, 0x01 }, /* cutoff current 2/32 * Ichg */
|
||||
{ PCF50633_REG_MBCC7, 0x00 }, /* 1.6A max bat curr, USB 100mA */
|
||||
{ PCF50633_REG_MBCC8, 0x00 },
|
||||
{ PCF50633_REG_MBCC1, 0xff }, /* chgena */
|
||||
|
||||
{ PCF50633_REG_LDO1ENA, 2 }, /* accel enabled if GPIO1 = H */
|
||||
{ PCF50633_REG_LDO2ENA, 2 }, /* codec enabled if GPIO1 = H */
|
||||
{ PCF50633_REG_LDO4ENA, 0 }, /* bt off */
|
||||
{ PCF50633_REG_LDO5ENA, 0 }, /* gps off */
|
||||
{ PCF50633_REG_LDO6ENA, 2 }, /* lcm enabled if GPIO1 = H */
|
||||
|
||||
{ PCF50633_REG_BBCCTL, 0x19 }, /* 3V, 200uA, on */
|
||||
{ PCF50633_REG_OOCSHDWN, 0x04 }, /* defeat 8s death from lowsys on A5 */
|
||||
|
||||
};
|
||||
|
||||
static const struct board_variant board_variants[] = {
|
||||
[0] = {
|
||||
.name = "A5 PCB",
|
||||
.machine_revision = 0x350,
|
||||
},
|
||||
[1] = {
|
||||
.name = "A6 PCB",
|
||||
.machine_revision = 0x360,
|
||||
},
|
||||
[9] = { /* 01001 */
|
||||
.name = "A7 PCB",
|
||||
.machine_revision = 0x360, /* report as A6 */
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
void port_init_gta02(void)
|
||||
{
|
||||
unsigned int * MPLLCON = (unsigned int *)0x4c000004;
|
||||
unsigned int * UPLLCON = (unsigned int *)0x4c000008;
|
||||
unsigned int * CLKDIVN = (unsigned int *)0x4c000014;
|
||||
int n;
|
||||
u32 block512 = 0;
|
||||
u32 start_block512 = 0;
|
||||
const u32 GTA02_NAND_READBLOCK_SIZE = 2048;
|
||||
extern int s3c2442_nand_is_bad_block(unsigned long block_index_512);
|
||||
|
||||
//CAUTION:Follow the configuration order for setting the ports.
|
||||
// 1) setting value(GPnDAT)
|
||||
// 2) setting control register (GPnCON)
|
||||
// 3) configure pull-down resistor(GPnUP)
|
||||
|
||||
/* 32bit data bus configuration */
|
||||
/*
|
||||
* === PORT A GROUP
|
||||
* Ports : GPA22 GPA21 GPA20 GPA19 GPA18 GPA17 GPA16 GPA15 GPA14 GPA13 GPA12
|
||||
* Signal : nFCE nRSTOUT nFRE nFWE ALE CLE nGCS5 nGCS4 nGCS3 nGCS2 nGCS1
|
||||
* Binary : 1 1 1 , 1 1 1 1 , 1 1 1 1
|
||||
* Ports : GPA11 GPA10 GPA9 GPA8 GPA7 GPA6 GPA5 GPA4 GPA3 GPA2 GPA1 GPA0
|
||||
* Signal : ADDR26 ADDR25 ADDR24 ADDR23 ADDR22 ADDR21 ADDR20 ADDR19 ADDR18 ADDR17 ADDR16 ADDR0
|
||||
* Binary : 1 1 1 1 , 1 1 1 1 , 1 1 1 1
|
||||
*/
|
||||
rGPACON = 0x007E5FFF;
|
||||
rGPADAT = 0x00000000;
|
||||
/*
|
||||
* ===* PORT B GROUP
|
||||
* Ports : GPB10 GPB9 GPB8 GPB7 GPB6 GPB5 GPB4 GPB3 GPB2 GPB1 GPB0
|
||||
* Signal : nXDREQ0 nXDACK0 nXDREQ1 nXDACK1 nSS_KBD nDIS_OFF L3CLOCK L3DATA L3MODE nIrDATXDEN Keyboard
|
||||
* Setting: INPUT OUTPUT INPUT OUTPUT INPUT OUTPUT OUTPUT OUTPUT OUTPUT OUTPUT OUTPUT
|
||||
* Binary : 00 , 01 00 , 01 00 , 01 01 , 01 01 , 01 01
|
||||
*/
|
||||
rGPBCON = 0x00155555;
|
||||
rGPBUP = 0x000007FF;
|
||||
rGPBDAT = 0x00000000;
|
||||
/*
|
||||
* === PORT C GROUP
|
||||
* Ports : GPC15 GPC14 GPC13 GPC12 GPC11 GPC10 GPC9 GPC8 GPC7 GPC6 GPC5 GPC4 GPC3 GPC2 GPC1 GPC0
|
||||
* Signal : VD7 VD6 VD5 VD4 VD3 VD2 VD1 VD0 LCDVF2 LCDVF1 LCDVF0 VM VFRAME VLINE VCLK LEND
|
||||
* Binary : 10 10 , 10 10 , 10 10 , 10 10 , 10 10 , 10 10 , 10 10 , 10 10
|
||||
*/
|
||||
rGPCCON = 0x55555155;
|
||||
rGPCUP = 0x0000FFFF & ~(1 << 5);
|
||||
rGPCDAT = (1 << 13) | (1 << 15); /* index detect -> hi */
|
||||
/*
|
||||
* === PORT D GROUP
|
||||
* Ports : GPD15 GPD14 GPD13 GPD12 GPD11 GPD10 GPD9 GPD8 GPD7 GPD6 GPD5 GPD4 GPD3 GPD2 GPD1 GPD0
|
||||
* Signal : VD23 VD22 VD21 VD20 VD19 VD18 VD17 VD16 VD15 VD14 VD13 VD12 VD11 VD10 VD9 VD8
|
||||
* Binary : 10 10 , 10 10 , 10 10 , 10 10 , 10 10 , 10 10 , 10 10 ,10 10
|
||||
*/
|
||||
rGPDCON = 0x55555555;
|
||||
rGPDUP = 0x0000FFFF;
|
||||
rGPDDAT = (1 << 0) | (1 << 3) | (1 << 4); /* index detect -> hi */
|
||||
/*
|
||||
* === PORT E GROUP
|
||||
* Ports : GPE15 GPE14 GPE13 GPE12 GPE11 GPE10 GPE9 GPE8 GPE7 GPE6 GPE5 GPE4
|
||||
* Signal : IICSDA IICSCL SPICLK SPIMOSI SPIMISO SDDATA3 SDDATA2 SDDATA1 SDDATA0 SDCMD SDCLK I2SSDO
|
||||
* Binary : 10 10 , 10 10 , 10 10 , 10 10 , 10 10 , 10 10 ,
|
||||
* -------------------------------------------------------------------------------------------------------
|
||||
* Ports : GPE3 GPE2 GPE1 GPE0
|
||||
* Signal : I2SSDI CDCLK I2SSCLK I2SLRCK
|
||||
* Binary : 10 10 , 10 10
|
||||
*/
|
||||
rGPECON = 0xAAAAAAAA;
|
||||
rGPEUP = 0x0000FFFF & ~(1 << 11);
|
||||
rGPEDAT = 0x00000000;
|
||||
/*
|
||||
* === PORT F GROUP
|
||||
* Ports : GPF7 GPF6 GPF5 GPF4 GPF3 GPF2 GPF1 GPF0
|
||||
* Signal : nLED_8 nLED_4 nLED_2 nLED_1 nIRQ_PCMCIA EINT2 KBDINT EINT0
|
||||
* Setting: Output Output Output Output EINT3 EINT2 EINT1 EINT0
|
||||
* Binary : 01 01 , 01 01 , 10 10 , 10 10
|
||||
*/
|
||||
/* pulldown on GPF03: TP-4705+debug - debug conn will float */
|
||||
rGPFCON = 0x00008AAA;
|
||||
rGPFUP = 0x000000FF & ~(1 << 3);
|
||||
rGPFDAT = 0x00000000;
|
||||
|
||||
|
||||
/*
|
||||
* === PORT G GROUP
|
||||
* Ports : GPG15 GPG14 GPG13 GPG12 GPG11 GPG10 GPG9 GPG8 GPG7 GPG6
|
||||
* Signal : nYPON YMON nXPON XMON EINT19 DMAMODE1 DMAMODE0 DMASTART KBDSPICLK KBDSPIMOSI
|
||||
* Setting: nYPON YMON nXPON XMON EINT19 Output Output Output SPICLK1 SPIMOSI1
|
||||
* Binary : 11 11 , 11 11 , 10 01 , 01 01 , 11 11
|
||||
* -----------------------------------------------------------------------------------------
|
||||
* Ports : GPG5 GPG4 GPG3 GPG2 GPG1 GPG0
|
||||
* Signal : KBDSPIMISO LCD_PWREN EINT11 nSS_SPI IRQ_LAN IRQ_PCMCIA
|
||||
* Setting: SPIMISO1 LCD_PWRDN EINT11 nSS0 EINT9 EINT8
|
||||
* Binary : 11 11 , 10 11 , 10 10
|
||||
*/
|
||||
rGPGCON = 0x01AAFE79;
|
||||
rGPGUP = 0x0000FFFF;
|
||||
rGPGDAT = 0x00000000;
|
||||
|
||||
/*
|
||||
* === PORT H GROUP
|
||||
* Ports : GPH10 GPH9 GPH8 GPH7 GPH6 GPH5 GPH4 GPH3 GPH2 GPH1 GPH0
|
||||
* Signal : CLKOUT1 CLKOUT0 UCLK RXD2 TXD2 RXD1 TXD1 RXD0 TXD0 nRTS0 nCTS0
|
||||
* Binary : 10 , 10 10 , 11 11 , 10 10 , 10 10 , 10 10
|
||||
*/
|
||||
|
||||
/*
|
||||
* FIXME the following should be removed eventually and only the first stanza
|
||||
* kept unconditionally. As it stands it allows TX and RTS to drive high into
|
||||
* a powered-down GSM unit, which draws considerable fault current.
|
||||
*
|
||||
* However kernels earlier than andy-tracking from end Feb 2009 do not enforce
|
||||
* the mode of these GPIOs, so Qi doing the correct thing here "breaks GSM"
|
||||
* apparently for those users.
|
||||
*
|
||||
* Upgrading to current kernel will solve this, so after most distros are on
|
||||
* 2.6.29-rc3 and later, we should return here and again disable driving out
|
||||
* into unpowered GSM.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
rGPHCON = 0x001AAA82; /* H1 and H2 are INPUTs to start with, not UART */
|
||||
#else
|
||||
rGPHCON = 0x001AAAAA; /* Wrong but compatible: H1 and H2 = UART */
|
||||
#endif
|
||||
|
||||
/* pulldown on GPH08: UEXTCLK, just floats!
|
||||
* pulldown GPH1 -- nCTS0 / RTS_MODEM -- floats when GSM off
|
||||
* pulldown GPH3 -- RXD[0] / RX_MODEM -- floats when GSM off
|
||||
*/
|
||||
rGPHUP = 0x000007FF & ~(1 << 8) & ~(1 << 1) & ~(1 << 3);
|
||||
rGPHDAT = 0x00000000;
|
||||
|
||||
/* pulldown on GPJ00: input, just floats! */
|
||||
/* pulldown on GPJ07: WLAN module WLAN_GPIO0, no ext pull */
|
||||
rGPJCON = 0x1551544;
|
||||
rGPJUP = 0x1ffff & ~(1 << 0) & ~(1 << 7);
|
||||
rGPJDAT = 0x00000100;
|
||||
|
||||
rGPJDAT |= (1 << 4) | (1 << 6);
|
||||
/* Set GPJ4 to high (nGSM_EN) */
|
||||
/* Set GPJ6 to high (nDL_GSM) */
|
||||
rGPJDAT &= ~(1 << 5); /* Set GPJ5 to low 3D RST */
|
||||
|
||||
/* leaving Glamo forced to Reset# active here killed
|
||||
* U-Boot when you touched the memory region
|
||||
*/
|
||||
|
||||
rGPJDAT |= (1 << 5); /* Set GPJ5 to high 3D RST */
|
||||
|
||||
|
||||
/*
|
||||
* We have to talk to the PMU a little bit
|
||||
*/
|
||||
|
||||
for (n = 0; n < ARRAY_SIZE(pcf50633_init); n++)
|
||||
i2c_write_sync(&bb_s3c24xx, PCF50633_I2C_ADS,
|
||||
pcf50633_init[n].index, pcf50633_init[n].value);
|
||||
|
||||
/* what does the battery monitoring unit say about the battery? */
|
||||
|
||||
battery_condition_reasonable = !(i2c_read_sync(&bb_s3c24xx,
|
||||
PCF50633_I2C_ADS, PCF50633_REG_BVMCTL) & 1);
|
||||
|
||||
if (battery_condition_reasonable) {
|
||||
/* change CPU clocking to 400MHz 1:4:8 */
|
||||
|
||||
/* clock divide 1:4:8 - do it first */
|
||||
*CLKDIVN = 5;
|
||||
/* configure UPLL */
|
||||
*UPLLCON = ((88 << 12) + (4 << 4) + 2);
|
||||
/* Magic delay: Page 7-19, seven nops between UPLL and MPLL */
|
||||
asm __volatile__ (
|
||||
"nop\n"
|
||||
"nop\n"
|
||||
"nop\n"
|
||||
"nop\n"
|
||||
"nop\n"
|
||||
"nop\n"
|
||||
"nop\n"
|
||||
);
|
||||
/* configure MPLL */
|
||||
*MPLLCON = ((42 << 12) + (1 << 4) + 0);
|
||||
|
||||
/* get debug UART working at 115kbps */
|
||||
serial_init_115200_s3c24xx(GTA02_DEBUG_UART, 50 /* 50MHz */);
|
||||
} else {
|
||||
serial_init_115200_s3c24xx(GTA02_DEBUG_UART, 33 /* 33MHz */);
|
||||
}
|
||||
|
||||
/* we're going to use Glamo for SD Card access, so we need to init the
|
||||
* evil beast
|
||||
*/
|
||||
glamo_core_init();
|
||||
|
||||
/*
|
||||
* dynparts computation
|
||||
*/
|
||||
|
||||
n = 0;
|
||||
while (n < ARRAY_SIZE(nand_dynparts)) {
|
||||
|
||||
if (nand_dynparts[n].good_length)
|
||||
while (nand_dynparts[n].good_length) {
|
||||
if (!s3c2442_nand_is_bad_block(block512))
|
||||
nand_dynparts[n].good_length -=
|
||||
GTA02_NAND_READBLOCK_SIZE;
|
||||
block512 += GTA02_NAND_READBLOCK_SIZE / 512;
|
||||
}
|
||||
else
|
||||
/*
|
||||
* cannot afford to compute real size of last block
|
||||
* set it to extent - end of last block
|
||||
*/
|
||||
block512 = nand_extent_block512;
|
||||
|
||||
/* stash a copy of real offset for each partition */
|
||||
nand_dynparts[n].true_offset = start_block512;
|
||||
|
||||
/* and the accurate length */
|
||||
nand_dynparts[n].good_length = block512 - start_block512;
|
||||
|
||||
start_block512 = block512;
|
||||
|
||||
n++;
|
||||
}
|
||||
|
||||
/* fix up the true start of kernel partition */
|
||||
|
||||
((struct board_api *)&board_api_gta02)->kernel_source[3].
|
||||
offset_blocks512_if_no_partition = nand_dynparts[2].true_offset;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* returns PCB revision information in b9,b8 and b2,b1,b0
|
||||
* Pre-GTA02 A6 returns 0x000
|
||||
* GTA02 A6 returns 0x001
|
||||
*/
|
||||
|
||||
int gta02_get_pcb_revision(void)
|
||||
{
|
||||
int n;
|
||||
u32 u;
|
||||
|
||||
/* make C13 and C15 pulled-down inputs */
|
||||
rGPCCON &= ~0xcc000000;
|
||||
rGPCUP &= ~((1 << 13) | (1 << 15));
|
||||
/* D0, D3 and D4 pulled-down inputs */
|
||||
rGPDCON &= ~0x000003c3;
|
||||
rGPDUP &= ~((1 << 0) | (1 << 3) | (1 << 4));
|
||||
|
||||
/* delay after changing pulldowns */
|
||||
u = rGPCDAT;
|
||||
u = rGPDDAT;
|
||||
|
||||
/* read the version info */
|
||||
u = rGPCDAT;
|
||||
n = (u >> (13 - 0)) & 0x001;
|
||||
n |= (u >> (15 - 1)) & 0x002;
|
||||
u = rGPDDAT;
|
||||
n |= (u << (0 + 2)) & 0x004;
|
||||
|
||||
n |= (u << (3 - 3)) & 0x008;
|
||||
n |= (u << (4 - 4)) & 0x010;
|
||||
|
||||
/*
|
||||
* when not being interrogated, all of the revision GPIO
|
||||
* are set to output HIGH without pulldown so no current flows
|
||||
* if they are NC or pulled up.
|
||||
*/
|
||||
/* make C13 and C15 high ouputs with no pulldowns */
|
||||
rGPCCON |= 0x44000000;
|
||||
rGPCUP |= (1 << 13) | (1 << 15);
|
||||
rGPCDAT |= (1 << 13) | (1 << 15);
|
||||
/* D0, D3 and D4 high ouputs with no pulldowns */
|
||||
rGPDCON |= 0x00000141;
|
||||
rGPDUP |= (1 << 0) | (1 << 3) | (1 << 4);
|
||||
rGPDDAT |= (1 << 0) | (1 << 3) | (1 << 4);
|
||||
|
||||
n &= 1;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int sd_card_init_gta02(void)
|
||||
{
|
||||
extern int mmc_init(int verbose);
|
||||
|
||||
return mmc_init(1);
|
||||
}
|
||||
|
||||
int sd_card_block_read_gta02(unsigned char * buf, unsigned long start512,
|
||||
int blocks512)
|
||||
{
|
||||
unsigned long mmc_bread(int dev_num, unsigned long blknr, unsigned long blkcnt,
|
||||
void *dst);
|
||||
|
||||
return mmc_bread(0, start512, blocks512, buf);
|
||||
}
|
||||
|
||||
/* return nonzero if we believe we run on GTA02 */
|
||||
|
||||
int is_this_board_gta02(void)
|
||||
{
|
||||
/* look for GTA02 NOR */
|
||||
|
||||
*(volatile unsigned short *)(0x18000000) = 0x98;
|
||||
|
||||
return !!(*(volatile unsigned short *)(0x18000000) == 0x0020);
|
||||
}
|
||||
|
||||
const struct board_variant const * get_board_variant_gta02(void)
|
||||
{
|
||||
int rev = gta02_get_pcb_revision() & 0x1f;
|
||||
|
||||
if (!board_variants[rev].name)
|
||||
return &board_variants[1]; /* A6 */
|
||||
|
||||
return &board_variants[rev];
|
||||
}
|
||||
|
||||
static __attribute__ (( section (".steppingstone") )) void putc_gta02(char c)
|
||||
{
|
||||
serial_putc_s3c24xx(GTA02_DEBUG_UART, c);
|
||||
}
|
||||
|
||||
static void close_gta02(void)
|
||||
{
|
||||
/* explicitly clear any pending 8s timeout */
|
||||
|
||||
i2c_write_sync(&bb_s3c24xx, PCF50633_I2C_ADS, PCF50633_REG_OOCSHDWN, 0x04);
|
||||
|
||||
/* clear any pending timeouts by reading interrupts */
|
||||
|
||||
i2c_read_sync(&bb_s3c24xx, PCF50633_I2C_ADS, PCF50633_REG_INT1);
|
||||
i2c_read_sync(&bb_s3c24xx, PCF50633_I2C_ADS, PCF50633_REG_INT2);
|
||||
i2c_read_sync(&bb_s3c24xx, PCF50633_I2C_ADS, PCF50633_REG_INT3);
|
||||
i2c_read_sync(&bb_s3c24xx, PCF50633_I2C_ADS, PCF50633_REG_INT4);
|
||||
i2c_read_sync(&bb_s3c24xx, PCF50633_I2C_ADS, PCF50633_REG_INT5);
|
||||
|
||||
/* set I2C GPIO back to peripheral unit */
|
||||
|
||||
(bb_s3c24xx.close)();
|
||||
|
||||
/* aux back to being EINT */
|
||||
rGPFCON = 0x0000AAAA;
|
||||
|
||||
}
|
||||
|
||||
/* Here we will care only about AUX button as polling for PWR button
|
||||
* through i2c slows down the boot */
|
||||
|
||||
static u8 get_ui_keys_gta02(void)
|
||||
{
|
||||
u8 keys;
|
||||
u8 ret = 0;
|
||||
static u8 old_keys = 0; /* previous state for debounce */
|
||||
static u8 older_keys = 0; /* previous debounced output for edge detect */
|
||||
|
||||
/* GPF6 is AUX on GTA02, map to UI_ACTION_SKIPKERNEL, down = 1 */
|
||||
keys = !!(rGPFDAT & (1 << 6));
|
||||
|
||||
/* edge action */
|
||||
if ((old_keys & 1) && !(older_keys & 1))
|
||||
ret |= UI_ACTION_SKIPKERNEL;
|
||||
|
||||
older_keys = old_keys;
|
||||
old_keys = keys;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u8 get_ui_debug_gta02(void)
|
||||
{
|
||||
/* PWR button state can be seen in OOCSTAT b0, down = 0, map to UI_ACTION_ADD_DEBUG */
|
||||
return !(i2c_read_sync(&bb_s3c24xx, PCF50633_I2C_ADS, PCF50633_REG_OOCSTAT) & 1);
|
||||
}
|
||||
|
||||
static void set_ui_indication_gta02(enum ui_indication ui_indication)
|
||||
{
|
||||
|
||||
switch (ui_indication) {
|
||||
case UI_IND_UPDATE_ONLY:
|
||||
break;
|
||||
|
||||
case UI_IND_MOUNT_PART:
|
||||
case UI_IND_KERNEL_PULL_OK:
|
||||
case UI_IND_INITRAMFS_PULL_OK:
|
||||
if (battery_condition_reasonable)
|
||||
rGPBDAT |= 4;
|
||||
break;
|
||||
|
||||
case UI_IND_KERNEL_PULL_FAIL:
|
||||
case UI_IND_SKIPPING:
|
||||
case UI_IND_INITRAMFS_PULL_FAIL:
|
||||
case UI_IND_MOUNT_FAIL:
|
||||
rGPBDAT &= ~4;
|
||||
if (battery_condition_reasonable) {
|
||||
rGPBDAT |= 8;
|
||||
udelay(2000000);
|
||||
rGPBDAT &= ~8;
|
||||
udelay(200000);
|
||||
}
|
||||
break;
|
||||
|
||||
case UI_IND_KERNEL_START:
|
||||
case UI_IND_MEM_TEST:
|
||||
case UI_IND_KERNEL_PULL:
|
||||
case UI_IND_INITRAMFS_PULL:
|
||||
rGPBDAT &= ~4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void post_serial_init_gta02(void)
|
||||
{
|
||||
if (battery_condition_reasonable)
|
||||
puts("Battery condition reasonable\n");
|
||||
else
|
||||
puts("BATTERY CONDITION LOW\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Increment a hexadecimal digit represented by a char and
|
||||
* return 1 if an overflow occured.
|
||||
*/
|
||||
static char inc_hexchar(char * p)
|
||||
{
|
||||
if (*p == '9')
|
||||
*p = 'A';
|
||||
else if (*p != 'F')
|
||||
(*p)++;
|
||||
else {
|
||||
*p = '0';
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* create and append device-specific Linux kernel commandline
|
||||
*
|
||||
* This takes care of legacy dyanmic partition sizing and USB Ethernet
|
||||
* MAC address identity information.
|
||||
*/
|
||||
|
||||
char * append_device_specific_cmdline_gta02(char * cmdline)
|
||||
{
|
||||
int n = 0;
|
||||
int i;
|
||||
int len;
|
||||
static char mac[64];
|
||||
struct kernel_source const * real_kernel = this_kernel;
|
||||
|
||||
/*
|
||||
* dynparts computation
|
||||
*/
|
||||
|
||||
cmdline += strlen(strcpy(cmdline,
|
||||
" mtdparts=physmap-flash:-(nor);neo1973-nand:"));
|
||||
|
||||
while (n < ARRAY_SIZE(nand_dynparts)) {
|
||||
|
||||
*cmdline++ = '0';
|
||||
*cmdline++ = 'x';
|
||||
set32(cmdline, nand_dynparts[n].good_length * 512);
|
||||
cmdline += 8;
|
||||
*cmdline++ = '(';
|
||||
cmdline += strlen(strcpy(cmdline, nand_dynparts[n].name));
|
||||
*cmdline++ = ')';
|
||||
|
||||
if (++n == ARRAY_SIZE(nand_dynparts))
|
||||
*cmdline++ = ' ';
|
||||
else
|
||||
*cmdline++ = ',';
|
||||
|
||||
}
|
||||
|
||||
*cmdline = '\0';
|
||||
|
||||
/*
|
||||
* Identity
|
||||
*/
|
||||
|
||||
/* position ourselves at true start of GTA02 identity partition */
|
||||
partition_offset_blocks = nand_dynparts[4].true_offset;
|
||||
partition_length_blocks = 0x40000 / 512;
|
||||
|
||||
/*
|
||||
* lie that we are in NAND context... GTA02 specific
|
||||
* all filesystem access is completed before we are called
|
||||
*/
|
||||
this_kernel = &board_api_gta02.kernel_source[3];
|
||||
|
||||
if (!ext2fs_mount()) {
|
||||
puts("Unable to mount ext2 filesystem\n");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
len = ext2fs_open("usb");
|
||||
if (len < 0) {
|
||||
puts(" Open failed\n");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
n = ext2fs_read(mac, sizeof(mac));
|
||||
if (n < 0) {
|
||||
puts(" Read failed\n");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
mac[len] = '\0';
|
||||
|
||||
cmdline += strlen(strcpy(cmdline, " g_ether.dev_addr="));
|
||||
cmdline += strlen(strcpy(cmdline, &mac[2]));
|
||||
|
||||
for (i = 0; i != 10; i++) {
|
||||
if ((i % 3) == 2)
|
||||
continue;
|
||||
if (!inc_hexchar(mac + 18 - i))
|
||||
break; /* Carry not needed. */
|
||||
}
|
||||
|
||||
cmdline += strlen(strcpy(cmdline, " g_ether.host_addr="));
|
||||
cmdline += strlen(strcpy(cmdline, &mac[2]));
|
||||
*cmdline++ = ' ' ;
|
||||
bail:
|
||||
this_kernel = real_kernel;
|
||||
|
||||
*cmdline = '\0';
|
||||
|
||||
return cmdline;
|
||||
}
|
||||
|
||||
/*
|
||||
* our API for bootloader on this machine
|
||||
*/
|
||||
|
||||
const struct board_api board_api_gta02 = {
|
||||
.name = "Freerunner / GTA02",
|
||||
.linux_machine_id = 1304,
|
||||
.linux_mem_start = 0x30000000,
|
||||
.linux_mem_size = (128 * 1024 * 1024),
|
||||
.linux_tag_placement = 0x30000000 + 0x100,
|
||||
.get_board_variant = get_board_variant_gta02,
|
||||
.is_this_board = is_this_board_gta02,
|
||||
.port_init = port_init_gta02,
|
||||
.post_serial_init = post_serial_init_gta02,
|
||||
.append_device_specific_cmdline = append_device_specific_cmdline_gta02,
|
||||
.putc = putc_gta02,
|
||||
.close = close_gta02,
|
||||
.get_ui_keys = get_ui_keys_gta02,
|
||||
.get_ui_debug = get_ui_debug_gta02,
|
||||
.set_ui_indication = set_ui_indication_gta02,
|
||||
.commandline_board = "loglevel=4 "
|
||||
"console=tty0 "
|
||||
"console=ttySAC2,115200 "
|
||||
"init=/sbin/init "
|
||||
"ro ",
|
||||
.commandline_board_debug = " loglevel=8",
|
||||
.noboot = "boot/noboot-GTA02",
|
||||
.append = "boot/append-GTA02",
|
||||
/* these are the ways we could boot GTA02 in the order to try */
|
||||
.kernel_source = {
|
||||
[0] = {
|
||||
.name = "SD Card EXT2 P1 Kernel",
|
||||
.block_init = sd_card_init_gta02,
|
||||
.block_read = sd_card_block_read_gta02,
|
||||
.partition_index = 1,
|
||||
.filesystem = FS_EXT2,
|
||||
.filepath = "boot/uImage-GTA02.bin",
|
||||
.commandline_append = " root=/dev/mmcblk0p1 rootdelay=1 ",
|
||||
},
|
||||
[1] = {
|
||||
.name = "SD Card EXT2 P2 Kernel",
|
||||
.block_init = sd_card_init_gta02,
|
||||
.block_read = sd_card_block_read_gta02,
|
||||
.partition_index = 2,
|
||||
.filesystem = FS_EXT2,
|
||||
.filepath = "boot/uImage-GTA02.bin",
|
||||
.commandline_append = " root=/dev/mmcblk0p2 rootdelay=1 ",
|
||||
},
|
||||
[2] = {
|
||||
.name = "SD Card EXT2 P3 Kernel",
|
||||
.block_init = sd_card_init_gta02,
|
||||
.block_read = sd_card_block_read_gta02,
|
||||
.partition_index = 3,
|
||||
.filesystem = FS_EXT2,
|
||||
.filepath = "boot/uImage-GTA02.bin",
|
||||
.commandline_append = " root=/dev/mmcblk0p3 rootdelay=1 ",
|
||||
},
|
||||
[3] = {
|
||||
.name = "NAND Kernel",
|
||||
.block_read = nand_read_ll,
|
||||
/* NOTE offset below is replaced at runtime */
|
||||
.offset_blocks512_if_no_partition = 0x80000 / 512,
|
||||
.filesystem = FS_RAW,
|
||||
.commandline_append = " rootfstype=jffs2 "
|
||||
"root=/dev/mtdblock6 ",
|
||||
},
|
||||
},
|
||||
};
|
68
qiboot/src/cpu/s3c2442/i2c-bitbang-s3c24xx.c
Normal file
68
qiboot/src/cpu/s3c2442/i2c-bitbang-s3c24xx.c
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
* Author: Andy Green <andy@openmoko.com>
|
||||
*
|
||||
* s3c24xx-specific i2c used by, eg, GTA02
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <qi.h>
|
||||
#include <i2c-bitbang.h>
|
||||
#include <ports-s3c24xx.h>
|
||||
|
||||
static char i2c_read_sda_s3c24xx(void)
|
||||
{
|
||||
return (rGPEDAT & 0x8000) != 0;
|
||||
}
|
||||
|
||||
static void i2c_set_s3c24xx(char clock, char data)
|
||||
{
|
||||
if (clock) /* SCL <- input */
|
||||
rGPECON = (rGPECON & ~0x30000000);
|
||||
else { /* SCL <- output 0 */
|
||||
rGPEDAT = (rGPEDAT & ~0x4000);
|
||||
rGPECON = (rGPECON & ~0x30000000) | 0x10000000;
|
||||
}
|
||||
if (data) /* SDA <- input */
|
||||
rGPECON = (rGPECON & ~0xc0000000);
|
||||
else { /* SDA <- output 0 */
|
||||
rGPEDAT = (rGPEDAT & ~0x8000);
|
||||
rGPECON = (rGPECON & ~0xc0000000) | 0x40000000;
|
||||
}
|
||||
}
|
||||
|
||||
static void i2c_close_s3c24xx(void)
|
||||
{
|
||||
/* set back to hardware I2C ready for Linux */
|
||||
rGPECON = (rGPECON & ~0xf0000000) | 0xa0000000;
|
||||
}
|
||||
|
||||
static void i2c_spin_s3c24xx(void)
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < 1000; n++)
|
||||
rGPJDAT |= (1 << 5);
|
||||
}
|
||||
|
||||
struct i2c_bitbang bb_s3c24xx = {
|
||||
.read_sda = i2c_read_sda_s3c24xx,
|
||||
.set = i2c_set_s3c24xx,
|
||||
.spin = i2c_spin_s3c24xx,
|
||||
.close = i2c_close_s3c24xx,
|
||||
};
|
162
qiboot/src/cpu/s3c2442/lowlevel_init.S
Normal file
162
qiboot/src/cpu/s3c2442/lowlevel_init.S
Normal file
@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Memory Setup stuff - taken from blob memsetup.S
|
||||
*
|
||||
* Modified for the FIC Neo1973 GTA01 by Harald Welte <laforge@openmoko.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* NOTE this stuff runs in steppingstone context! */
|
||||
|
||||
|
||||
/*
|
||||
* #include <config.h>
|
||||
* #include <version.h>
|
||||
*/
|
||||
#define __ASM_MODE__
|
||||
#include <neo_gta02.h>
|
||||
|
||||
/*
|
||||
*
|
||||
* Taken from linux/arch/arm/boot/compressed/head-s3c2410.S
|
||||
*
|
||||
* Copyright (C) 2002 Samsung Electronics SW.LEE <hitchcar@sec.samsung.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#define BWSCON 0x48000000
|
||||
|
||||
/* BWSCON */
|
||||
#define DW8 (0x0)
|
||||
#define DW16 (0x1)
|
||||
#define DW32 (0x2)
|
||||
#define WAIT (0x1<<2)
|
||||
#define UBLB (0x1<<3)
|
||||
|
||||
#define B1_BWSCON (DW16 + WAIT + UBLB)
|
||||
#define B2_BWSCON (DW16)
|
||||
#define B3_BWSCON (DW16 + WAIT + UBLB)
|
||||
#define B4_BWSCON (DW16)
|
||||
#define B5_BWSCON (DW16)
|
||||
#define B6_BWSCON (DW32)
|
||||
#define B7_BWSCON (DW32)
|
||||
|
||||
/* BANK0CON */
|
||||
#define B0_Tacs 0x0 /* 0clk */
|
||||
#define B0_Tcos 0x0 /* 0clk */
|
||||
#define B0_Tacc 0x7 /* 14clk */
|
||||
#define B0_Tcoh 0x0 /* 0clk */
|
||||
#define B0_Tah 0x0 /* 0clk */
|
||||
#define B0_Tacp 0x0
|
||||
#define B0_PMC 0x0 /* normal */
|
||||
|
||||
/* BANK1CON: Smedia Glamo 3362 (on GTA02) */
|
||||
#define B1_Tacs 0x0 /* 0clk */
|
||||
#define B1_Tcos 0x3 /* 4clk */
|
||||
#define B1_Tacc 0x3 /* 4clk */
|
||||
#define B1_Tcoh 0x3 /* 4clk */
|
||||
#define B1_Tah 0x0 /* 0clk */
|
||||
#define B1_Tacp 0x0
|
||||
#define B1_PMC 0x0
|
||||
|
||||
#define B2_Tacs 0x0
|
||||
#define B2_Tcos 0x0
|
||||
#define B2_Tacc 0x7
|
||||
#define B2_Tcoh 0x0
|
||||
#define B2_Tah 0x0
|
||||
#define B2_Tacp 0x0
|
||||
#define B2_PMC 0x0
|
||||
|
||||
#define B3_Tacs 0x0 /* 0clk */
|
||||
#define B3_Tcos 0x3 /* 4clk */
|
||||
#define B3_Tacc 0x7 /* 14clk */
|
||||
#define B3_Tcoh 0x1 /* 1clk */
|
||||
#define B3_Tah 0x0 /* 0clk */
|
||||
#define B3_Tacp 0x3 /* 6clk */
|
||||
#define B3_PMC 0x0 /* normal */
|
||||
|
||||
#define B4_Tacs 0x0 /* 0clk */
|
||||
#define B4_Tcos 0x0 /* 0clk */
|
||||
#define B4_Tacc 0x7 /* 14clk */
|
||||
#define B4_Tcoh 0x0 /* 0clk */
|
||||
#define B4_Tah 0x0 /* 0clk */
|
||||
#define B4_Tacp 0x0
|
||||
#define B4_PMC 0x0 /* normal */
|
||||
|
||||
#define B5_Tacs 0x0 /* 0clk */
|
||||
#define B5_Tcos 0x0 /* 0clk */
|
||||
#define B5_Tacc 0x7 /* 14clk */
|
||||
#define B5_Tcoh 0x0 /* 0clk */
|
||||
#define B5_Tah 0x0 /* 0clk */
|
||||
#define B5_Tacp 0x0
|
||||
#define B5_PMC 0x0 /* normal */
|
||||
|
||||
#define B6_MT 0x3 /* SDRAM */
|
||||
#define B6_Trcd 0x1 /* 3clk */
|
||||
|
||||
#define B6_SCAN 0x1 /* 9bit */
|
||||
#define B7_SCAN 0x1 /* 9bit */
|
||||
|
||||
|
||||
#define B7_MT 0x3 /* SDRAM */
|
||||
#define B7_Trcd 0x1 /* 3clk */
|
||||
|
||||
/* REFRESH parameter */
|
||||
#define REFEN 0x1 /* Refresh enable */
|
||||
#define TREFMD 0x0 /* CBR(CAS before RAS)/Auto refresh */
|
||||
#define Trp 0x1 /* 3clk */
|
||||
#define Trc 0x3 /* 7clk */
|
||||
#define Tchr 0x2 /* 3clk */
|
||||
//#define REFCNT 1113 /* period=15.6us, HCLK=60Mhz, (2048+1-15.6*60) */
|
||||
#define REFCNT 997 /* period=17.5us, HCLK=60Mhz, (2048+1-15.6*60) */
|
||||
/**************************************/
|
||||
|
||||
.globl lowlevel_init
|
||||
lowlevel_init:
|
||||
|
||||
ldr r0, =SMRDATA
|
||||
ldr r1, =BWSCON /* Bus Width Status Controller */
|
||||
add r2, r0, #13*4
|
||||
0:
|
||||
ldr r3, [r0], #4
|
||||
str r3, [r1], #4
|
||||
cmp r2, r0
|
||||
bne 0b
|
||||
|
||||
/* setup asynchronous bus mode */
|
||||
mrc p15, 0, r1 ,c1 ,c0, 0
|
||||
orr r1, r1, #0xc0000000
|
||||
mcr p15, 0, r1, c1, c0, 0
|
||||
|
||||
/* everything is fine now */
|
||||
mov pc, lr
|
||||
|
||||
.ltorg
|
||||
/* the literal pools origin */
|
||||
SMRDATA:
|
||||
.word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
|
||||
.word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
|
||||
.word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
|
||||
.word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
|
||||
.word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
|
||||
.word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
|
||||
.word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
|
||||
.word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
|
||||
.word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
|
||||
.word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
|
||||
.word 0xb1
|
||||
.word 0x30
|
||||
.word 0x30
|
156
qiboot/src/cpu/s3c2442/nand_read.c
Normal file
156
qiboot/src/cpu/s3c2442/nand_read.c
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* nand_read.c: Simple NAND read functions for booting from NAND
|
||||
*
|
||||
* This is used by cpu/arm920/start.S assembler code,
|
||||
* and the board-specific linker script must make sure this
|
||||
* file is linked within the first 4kB of NAND flash.
|
||||
*
|
||||
* Taken from GPLv2 licensed vivi bootloader,
|
||||
* Copyright (C) 2002 MIZI Research, Inc.
|
||||
*
|
||||
* Author: Hwang, Chideok <hwang@mizi.com>
|
||||
* Date : $Date: 2004/02/04 10:37:37 $
|
||||
*
|
||||
* u-boot integration and bad-block skipping (C) 2006 by OpenMoko, Inc.
|
||||
* Author: Harald Welte <laforge@openmoko.org>
|
||||
*/
|
||||
|
||||
/* NOTE this stuff runs in steppingstone context! */
|
||||
|
||||
/* the API refers to 512-byte blocks */
|
||||
|
||||
#include <qi.h>
|
||||
#include "nand_read.h"
|
||||
|
||||
#define NAND_CMD_READ0 0
|
||||
#define NAND_CMD_READSTART 0x30
|
||||
|
||||
#define __REGb(x) (*(volatile unsigned char *)(x))
|
||||
#define __REGw(x) (*(volatile unsigned short *)(x))
|
||||
#define __REGi(x) (*(volatile unsigned int *)(x))
|
||||
#define NF_BASE 0x4e000000
|
||||
#define NFCONF __REGi(NF_BASE + 0x0)
|
||||
#define NFCONT __REGi(NF_BASE + 0x4)
|
||||
#define NFCMD __REGb(NF_BASE + 0x8)
|
||||
#define NFADDR __REGb(NF_BASE + 0xc)
|
||||
#define NFDATA __REGb(NF_BASE + 0x10)
|
||||
#define NFDATA16 __REGw(NF_BASE + 0x10)
|
||||
#define NFSTAT __REGb(NF_BASE + 0x20)
|
||||
#define NFSTAT_BUSY 1
|
||||
#define nand_select() (NFCONT &= ~(1 << 1))
|
||||
#define nand_deselect() (NFCONT |= (1 << 1))
|
||||
#define nand_clear_RnB() (NFSTAT |= (1 << 2))
|
||||
|
||||
static inline void nand_wait(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
while (!(NFSTAT & NFSTAT_BUSY))
|
||||
for (i=0; i<10; i++);
|
||||
}
|
||||
|
||||
/* configuration for 2440 with 2048byte sized flash */
|
||||
#define NAND_5_ADDR_CYCLE
|
||||
#define NAND_PAGE_SIZE 2048
|
||||
#define BAD_BLOCK_OFFSET NAND_PAGE_SIZE
|
||||
#define NAND_BLOCK_MASK (NAND_PAGE_SIZE - 1)
|
||||
#define NAND_BLOCK_SIZE (NAND_PAGE_SIZE * 64)
|
||||
|
||||
int s3c2442_nand_is_bad_block(unsigned long block_index)
|
||||
{
|
||||
unsigned char data;
|
||||
unsigned long page_num;
|
||||
|
||||
nand_select();
|
||||
nand_clear_RnB();
|
||||
page_num = block_index >> 2; /* addr / 2048 */
|
||||
NFCMD = NAND_CMD_READ0;
|
||||
NFADDR = BAD_BLOCK_OFFSET & 0xff;
|
||||
NFADDR = (BAD_BLOCK_OFFSET >> 8) & 0xff;
|
||||
NFADDR = page_num & 0xff;
|
||||
NFADDR = (page_num >> 8) & 0xff;
|
||||
NFADDR = (page_num >> 16) & 0xff;
|
||||
NFCMD = NAND_CMD_READSTART;
|
||||
nand_wait();
|
||||
data = (NFDATA & 0xff);
|
||||
|
||||
if (data != 0xff)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nand_read_page_ll(unsigned char *buf, unsigned long block512, int blocks512)
|
||||
{
|
||||
unsigned short *ptr16 = (unsigned short *)buf;
|
||||
unsigned int i, page_num;
|
||||
unsigned int block_amount;
|
||||
int blocks_possible = (3 - (block512 & 3)) + 1;
|
||||
|
||||
|
||||
if (blocks512 > blocks_possible)
|
||||
blocks512 = blocks_possible;
|
||||
|
||||
block_amount = (NAND_PAGE_SIZE / 4 / 2) * blocks512;
|
||||
|
||||
nand_clear_RnB();
|
||||
|
||||
NFCMD = NAND_CMD_READ0;
|
||||
|
||||
page_num = block512 >> 2; /* 512 block -> 2048 block */
|
||||
/* Write Address */
|
||||
NFADDR = 0;
|
||||
NFADDR = (block512 & 3) << 1; /* which 512 block in 2048 */
|
||||
NFADDR = page_num & 0xff;
|
||||
NFADDR = (page_num >> 8) & 0xff;
|
||||
NFADDR = (page_num >> 16) & 0xff;
|
||||
NFCMD = NAND_CMD_READSTART;
|
||||
nand_wait();
|
||||
|
||||
for (i = 0; i < block_amount; i++)
|
||||
*ptr16++ = NFDATA16;
|
||||
|
||||
return blocks512;
|
||||
}
|
||||
|
||||
|
||||
/* low level nand read function */
|
||||
int nand_read_ll(unsigned char *buf, unsigned long start_block512,
|
||||
int blocks512)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
/* chip Enable */
|
||||
nand_select();
|
||||
nand_clear_RnB();
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
;
|
||||
|
||||
while (blocks512 > 0) {
|
||||
if (s3c2442_nand_is_bad_block(start_block512)) {
|
||||
start_block512 += 4;
|
||||
if (start_block512 >> 2 > BAD_BLOCK_OFFSET)
|
||||
/* end of NAND */
|
||||
return -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
j = nand_read_page_ll(buf, start_block512, blocks512);
|
||||
start_block512 += j;
|
||||
buf += j << 9;
|
||||
blocks512 -= j;
|
||||
|
||||
if (this_board->get_ui_keys)
|
||||
if ((this_board->get_ui_keys)() & UI_ACTION_SKIPKERNEL) {
|
||||
puts(" ** skipping \n");
|
||||
return -3;
|
||||
}
|
||||
}
|
||||
|
||||
/* chip Disable */
|
||||
nand_deselect();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
22
qiboot/src/cpu/s3c2442/nand_read.h
Normal file
22
qiboot/src/cpu/s3c2442/nand_read.h
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* nand_read.c: Simple NAND read functions for booting from NAND
|
||||
*
|
||||
* This is used by cpu/arm920/start.S assembler code,
|
||||
* and the board-specific linker script must make sure this
|
||||
* file is linked within the first 4kB of NAND flash.
|
||||
*
|
||||
* Taken from GPLv2 licensed vivi bootloader,
|
||||
* Copyright (C) 2002 MIZI Research, Inc.
|
||||
*
|
||||
* Author: Hwang, Chideok <hwang@mizi.com>
|
||||
* Date : $Date: 2004/02/04 10:37:37 $
|
||||
*
|
||||
* u-boot integration and bad-block skipping (C) 2006 by OpenMoko, Inc.
|
||||
* Author: Harald Welte <laforge@openmoko.org>
|
||||
*/
|
||||
#ifndef __NAND_READ_H
|
||||
#define __NAND_READ_H
|
||||
|
||||
int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size);
|
||||
|
||||
#endif /* __NAND_READ_H */
|
65
qiboot/src/cpu/s3c2442/qi.lds
Normal file
65
qiboot/src/cpu/s3c2442/qi.lds
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* (C) Copyright 2002
|
||||
* Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
|
||||
/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
|
||||
OUTPUT_ARCH(arm)
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
__steppingstone_always = 0x40000000;
|
||||
__qi_sdram_copy = 0x33000000;
|
||||
|
||||
. = __steppingstone_always;
|
||||
|
||||
/* this is intended to take the first 4KBytes of stuff initially.
|
||||
* We have to make sure we have .rodata* in there for everything
|
||||
* because we do not compile PIC.
|
||||
*/
|
||||
|
||||
.text __steppingstone_always : AT (0x0)
|
||||
{
|
||||
src/cpu/s3c2442/start.o (.text .rodata* .data .bss)
|
||||
src/cpu/s3c2442/lowlevel_init.o (.text .rodata* .data .bss)
|
||||
src/cpu/s3c2442/start_qi.o (.text .rodata* .data .bss)
|
||||
src/cpu/s3c2442/nand_read.o (.text .rodata* .data .bss)
|
||||
src/cpu/s3c2442/serial-s3c24xx.o (.text .rodata* .data .bss)
|
||||
src/memory-test.o (.text .rodata* .data .bss)
|
||||
src/utils.o (.text .rodata* .data .bss)
|
||||
src/ctype.o (.text .rodata* .data .bss)
|
||||
* (.steppingstone)
|
||||
}
|
||||
|
||||
. = ALIGN(4);
|
||||
.everything_else ADDR (.text) - __steppingstone_always + SIZEOF (.text) + __qi_sdram_copy :
|
||||
AT ( ADDR (.text) - __steppingstone_always + SIZEOF (.text) ) { *(.text .rodata* .data) }
|
||||
|
||||
. = __qi_sdram_copy + 0x800000 ;
|
||||
__bss_start = .;
|
||||
.bss (NOLOAD) :
|
||||
{
|
||||
*(.bss)
|
||||
}
|
||||
|
||||
_end = .;
|
||||
}
|
569
qiboot/src/cpu/s3c2442/s3c24xx-mci.c
Normal file
569
qiboot/src/cpu/s3c2442/s3c24xx-mci.c
Normal file
@ -0,0 +1,569 @@
|
||||
/*
|
||||
* qi s3c24xx SD card driver
|
||||
* Author: Andy Green <andy@openmoko.com>
|
||||
* based on ---->
|
||||
*
|
||||
* u-boot S3C2410 MMC/SD card driver
|
||||
* (C) Copyright 2006 by OpenMoko, Inc.
|
||||
* Author: Harald Welte <laforge@openmoko.org>
|
||||
*
|
||||
* based on u-boot pxa MMC driver and linux/drivers/mmc/s3c2410mci.c
|
||||
* (C) 2005-2005 Thomas Kleffel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <qi.h>
|
||||
#include <mmc.h>
|
||||
#include <s3c24xx-regs-sdi.h>
|
||||
#include <string.h>
|
||||
|
||||
#define SDICON (*(u32 *)0x5a000000)
|
||||
#define SDIPRE (*(u32 *)0x5a000004)
|
||||
#define SDICARG (*(u32 *)0x5a000008)
|
||||
#define SDICCON (*(u32 *)0x5a00000c)
|
||||
#define SDICSTA (*(u32 *)0x5a000010)
|
||||
#define SDIRSP0 (*(u32 *)0x5a000014)
|
||||
#define SDIRSP1 (*(u32 *)0x5a000018)
|
||||
#define SDIRSP2 (*(u32 *)0x5a00001c)
|
||||
#define SDIRSP3 (*(u32 *)0x5a000020)
|
||||
#define SDIDTIMER (*(u32 *)0x5a000024)
|
||||
#define SDIBSIZE (*(u32 *)0x5a000028)
|
||||
#define SDIDCON (*(u32 *)0x5a00002c)
|
||||
#define SDIDCNT (*(u32 *)0x5a000030)
|
||||
#define SDIDSTA (*(u32 *)0x5a000034)
|
||||
#define SDIFSTA (*(u32 *)0x5a000038)
|
||||
/* s3c2410 in GTA01 has these two last ones the other way around!!! */
|
||||
#define SDIIMSK (*(u32 *)0x5a00003c)
|
||||
#define SDIDAT (*(u32 *)0x5a000040)
|
||||
#define SDIDAT2410 (*(u32 *)0x5a00003c)
|
||||
#define SDIIMSK2410 (*(u32 *)0x5a000040)
|
||||
|
||||
#define CFG_MMC_BASE 0xff000000
|
||||
|
||||
/* FIXME: anyone who wants to use this on GTA01 / s3c2410 need to
|
||||
* have this return 1 on that CPU
|
||||
*/
|
||||
|
||||
int am_i_s3c2410(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define CONFIG_MMC_WIDE
|
||||
#define MMC_BLOCK_SIZE 512
|
||||
|
||||
/*
|
||||
* FIXME needs to read cid and csd info to determine block size
|
||||
* and other parameters
|
||||
*/
|
||||
static u8 mmc_buf[MMC_BLOCK_SIZE];
|
||||
static mmc_csd_t mmc_csd;
|
||||
static int mmc_ready = 0;
|
||||
static int wide = 0;
|
||||
|
||||
|
||||
#define CMD_F_RESP 0x01
|
||||
#define CMD_F_RESP_LONG 0x02
|
||||
|
||||
static u32 *mmc_cmd(u16 cmd, u32 arg, u16 flags)
|
||||
{
|
||||
static u32 resp[5];
|
||||
|
||||
u32 ccon, csta;
|
||||
u32 csta_rdy_bit = S3C2410_SDICMDSTAT_CMDSENT;
|
||||
|
||||
memset(resp, 0, sizeof(resp));
|
||||
|
||||
// debug("mmc_cmd CMD%d arg=0x%08x flags=%x\n", cmd, arg, flags);
|
||||
|
||||
SDICSTA = 0xffffffff;
|
||||
SDIDSTA = 0xffffffff;
|
||||
SDIFSTA = 0xffffffff;
|
||||
|
||||
SDICARG = arg;
|
||||
|
||||
ccon = cmd & S3C2410_SDICMDCON_INDEX;
|
||||
ccon |= S3C2410_SDICMDCON_SENDERHOST|S3C2410_SDICMDCON_CMDSTART;
|
||||
|
||||
if (flags & CMD_F_RESP) {
|
||||
ccon |= S3C2410_SDICMDCON_WAITRSP;
|
||||
csta_rdy_bit = S3C2410_SDICMDSTAT_RSPFIN; /* 1 << 9 */
|
||||
}
|
||||
|
||||
if (flags & CMD_F_RESP_LONG)
|
||||
ccon |= S3C2410_SDICMDCON_LONGRSP;
|
||||
|
||||
SDICCON = ccon;
|
||||
|
||||
while (1) {
|
||||
csta = SDICSTA;
|
||||
if (csta & csta_rdy_bit)
|
||||
break;
|
||||
if (csta & S3C2410_SDICMDSTAT_CMDTIMEOUT) {
|
||||
puts("===============> MMC CMD Timeout\n");
|
||||
SDICSTA |= S3C2410_SDICMDSTAT_CMDTIMEOUT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// debug("final MMC CMD status 0x%x\n", csta);
|
||||
|
||||
SDICSTA |= csta_rdy_bit;
|
||||
|
||||
if (flags & CMD_F_RESP) {
|
||||
resp[0] = SDIRSP0;
|
||||
resp[1] = SDIRSP1;
|
||||
resp[2] = SDIRSP2;
|
||||
resp[3] = SDIRSP3;
|
||||
}
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
#define FIFO_FILL() ((SDIFSTA & S3C2410_SDIFSTA_COUNTMASK) >> 2)
|
||||
|
||||
static int mmc_block_read(u8 *dst, u32 src, u32 len)
|
||||
{
|
||||
u32 dcon, fifo;
|
||||
u32 *dst_u32 = (u32 *)dst;
|
||||
u32 *resp;
|
||||
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
// debug("mmc_block_rd dst %lx src %lx len %d\n", (u32)dst, src, len);
|
||||
|
||||
/* set block len */
|
||||
resp = mmc_cmd(MMC_CMD_SET_BLOCKLEN, len, CMD_F_RESP);
|
||||
SDIBSIZE = len;
|
||||
|
||||
//SDIPRE = 0xff;
|
||||
|
||||
/* setup data */
|
||||
dcon = (len >> 9) & S3C2410_SDIDCON_BLKNUM;
|
||||
dcon |= S3C2410_SDIDCON_BLOCKMODE;
|
||||
dcon |= S3C2410_SDIDCON_RXAFTERCMD|S3C2410_SDIDCON_XFER_RXSTART;
|
||||
if (wide)
|
||||
dcon |= S3C2410_SDIDCON_WIDEBUS;
|
||||
|
||||
if (!am_i_s3c2410())
|
||||
dcon |= S3C2440_SDIDCON_DS_WORD | S3C2440_SDIDCON_DATSTART;
|
||||
|
||||
SDIDCON = dcon;
|
||||
|
||||
/* send read command */
|
||||
resp = mmc_cmd(MMC_CMD_READ_BLOCK, src, CMD_F_RESP);
|
||||
|
||||
while (len > 0) {
|
||||
u32 sdidsta = SDIDSTA;
|
||||
fifo = FIFO_FILL();
|
||||
if (sdidsta & (S3C2410_SDIDSTA_FIFOFAIL|
|
||||
S3C2410_SDIDSTA_CRCFAIL|
|
||||
S3C2410_SDIDSTA_RXCRCFAIL|
|
||||
S3C2410_SDIDSTA_DATATIMEOUT)) {
|
||||
puts("mmc_block_read: err SDIDSTA=0x");
|
||||
print32(sdidsta);
|
||||
puts("\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (am_i_s3c2410()) {
|
||||
while (fifo--) {
|
||||
//debug("dst_u32 = 0x%08x\n", dst_u32);
|
||||
*(dst_u32++) = SDIDAT2410;
|
||||
if (len >= 4)
|
||||
len -= 4;
|
||||
else {
|
||||
len = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (fifo--) {
|
||||
//debug("dst_u32 = 0x%08x\n", dst_u32);
|
||||
*(dst_u32++) = SDIDAT;
|
||||
if (len >= 4)
|
||||
len -= 4;
|
||||
else {
|
||||
len = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// debug("waiting for SDIDSTA (currently 0x%08x\n", SDIDSTA);
|
||||
while (!(SDIDSTA & (1 << 4))) {}
|
||||
// debug("done waiting for SDIDSTA (currently 0x%08x\n", SDIDSTA);
|
||||
|
||||
SDIDCON = 0;
|
||||
|
||||
if (!(SDIDSTA & S3C2410_SDIDSTA_XFERFINISH))
|
||||
puts("mmc_block_read; transfer not finished!\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mmc_block_write(u32 dst, u8 *src, int len)
|
||||
{
|
||||
puts("MMC block write not yet supported on S3C2410!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int s3c24xx_mmc_read(u32 src, u8 *dst, int size)
|
||||
{
|
||||
u32 end, part_start, part_end, part_len, aligned_start, aligned_end;
|
||||
u32 mmc_block_size, mmc_block_address;
|
||||
|
||||
if (size == 0)
|
||||
return 0;
|
||||
|
||||
if (!mmc_ready) {
|
||||
puts("Please initialize the MMC first\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mmc_block_size = MMC_BLOCK_SIZE;
|
||||
mmc_block_address = ~(mmc_block_size - 1);
|
||||
|
||||
src -= CFG_MMC_BASE;
|
||||
end = src + size;
|
||||
part_start = ~mmc_block_address & src;
|
||||
part_end = ~mmc_block_address & end;
|
||||
aligned_start = mmc_block_address & src;
|
||||
aligned_end = mmc_block_address & end;
|
||||
|
||||
/* all block aligned accesses */
|
||||
// debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
if (part_start) {
|
||||
part_len = mmc_block_size - part_start;
|
||||
// debug("ps src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
if ((mmc_block_read(mmc_buf, aligned_start, mmc_block_size)) < 0)
|
||||
return -1;
|
||||
|
||||
memcpy(dst, mmc_buf+part_start, part_len);
|
||||
dst += part_len;
|
||||
src += part_len;
|
||||
}
|
||||
// debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
for (; src < aligned_end; src += mmc_block_size, dst += mmc_block_size) {
|
||||
// debug("al src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
if ((mmc_block_read((u8 *)(dst), src, mmc_block_size)) < 0)
|
||||
return -1;
|
||||
}
|
||||
// debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
if (part_end && src < end) {
|
||||
// debug("pe src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
if ((mmc_block_read(mmc_buf, aligned_end, mmc_block_size)) < 0)
|
||||
return -1;
|
||||
|
||||
memcpy(dst, mmc_buf, part_end);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int s3c24xx_mmc_write(u8 *src, u32 dst, int size)
|
||||
{
|
||||
u32 end, part_start, part_end, part_len, aligned_start, aligned_end;
|
||||
u32 mmc_block_size, mmc_block_address;
|
||||
|
||||
if (size == 0)
|
||||
return 0;
|
||||
|
||||
if (!mmc_ready) {
|
||||
puts("Please initialize the MMC first\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mmc_block_size = MMC_BLOCK_SIZE;
|
||||
mmc_block_address = ~(mmc_block_size - 1);
|
||||
|
||||
dst -= CFG_MMC_BASE;
|
||||
end = dst + size;
|
||||
part_start = ~mmc_block_address & dst;
|
||||
part_end = ~mmc_block_address & end;
|
||||
aligned_start = mmc_block_address & dst;
|
||||
aligned_end = mmc_block_address & end;
|
||||
|
||||
/* all block aligned accesses */
|
||||
// debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
if (part_start) {
|
||||
part_len = mmc_block_size - part_start;
|
||||
// debug("ps src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// (u32)src, dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
if ((mmc_block_read(mmc_buf, aligned_start, mmc_block_size)) < 0)
|
||||
return -1;
|
||||
|
||||
memcpy(mmc_buf+part_start, src, part_len);
|
||||
if ((mmc_block_write(aligned_start, mmc_buf, mmc_block_size)) < 0)
|
||||
return -1;
|
||||
|
||||
dst += part_len;
|
||||
src += part_len;
|
||||
}
|
||||
// debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
for (; dst < aligned_end; src += mmc_block_size, dst += mmc_block_size) {
|
||||
// debug("al src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
if ((mmc_block_write(dst, (u8 *)src, mmc_block_size)) < 0)
|
||||
return -1;
|
||||
|
||||
}
|
||||
// debug("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
if (part_end && dst < end) {
|
||||
// debug("pe src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
|
||||
// src, (u32)dst, end, part_start, part_end, aligned_start, aligned_end);
|
||||
if ((mmc_block_read(mmc_buf, aligned_end, mmc_block_size)) < 0)
|
||||
return -1;
|
||||
|
||||
memcpy(mmc_buf, src, part_end);
|
||||
if ((mmc_block_write(aligned_end, mmc_buf, mmc_block_size)) < 0)
|
||||
return -1;
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 s3c24xx_mmc_bread(int dev_num, u32 blknr, u32 blkcnt, void *dst)
|
||||
{
|
||||
int mmc_block_size = MMC_BLOCK_SIZE;
|
||||
u32 src = blknr * mmc_block_size + CFG_MMC_BASE;
|
||||
|
||||
s3c24xx_mmc_read(src, dst, blkcnt*mmc_block_size);
|
||||
return blkcnt;
|
||||
}
|
||||
|
||||
/* MMC_DEFAULT_RCA should probably be just 1, but this may break other code
|
||||
that expects it to be shifted. */
|
||||
static u_int16_t rca = MMC_DEFAULT_RCA >> 16;
|
||||
|
||||
#if 0
|
||||
static u32 mmc_size(const struct mmc_csd *csd)
|
||||
{
|
||||
u32 block_len, mult, blocknr;
|
||||
|
||||
block_len = csd->read_bl_len << 12;
|
||||
mult = csd->c_size_mult1 << 8;
|
||||
blocknr = (csd->c_size+1) * mult;
|
||||
|
||||
return blocknr * block_len;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct sd_cid {
|
||||
char pnm_0; /* product name */
|
||||
char oid_1; /* OEM/application ID */
|
||||
char oid_0;
|
||||
uint8_t mid; /* manufacturer ID */
|
||||
char pnm_4;
|
||||
char pnm_3;
|
||||
char pnm_2;
|
||||
char pnm_1;
|
||||
uint8_t psn_2; /* product serial number */
|
||||
uint8_t psn_1;
|
||||
uint8_t psn_0; /* MSB */
|
||||
uint8_t prv; /* product revision */
|
||||
uint8_t crc; /* CRC7 checksum, b0 is unused and set to 1 */
|
||||
uint8_t mdt_1; /* manufacturing date, LSB, RRRRyyyy yyyymmmm */
|
||||
uint8_t mdt_0; /* MSB */
|
||||
uint8_t psn_3; /* LSB */
|
||||
};
|
||||
|
||||
static void print_mmc_cid(mmc_cid_t *cid)
|
||||
{
|
||||
puts("MMC found. Card desciption is:\n");
|
||||
puts("Manufacturer ID = ");
|
||||
print8(cid->id[0]);
|
||||
print8(cid->id[1]);
|
||||
print8(cid->id[2]);
|
||||
puts("\nHW/FW Revision = ");
|
||||
print8(cid->hwrev);
|
||||
print8(cid->fwrev);
|
||||
cid->hwrev = cid->fwrev = 0; /* null terminate string */
|
||||
puts("Product Name = ");
|
||||
puts((char *)cid->name);
|
||||
puts("\nSerial Number = ");
|
||||
print8(cid->sn[0]);
|
||||
print8(cid->sn[1]);
|
||||
print8(cid->sn[2]);
|
||||
puts("\nMonth = ");
|
||||
printdec(cid->month);
|
||||
puts("\nYear = ");
|
||||
printdec(1997 + cid->year);
|
||||
puts("\n");
|
||||
}
|
||||
|
||||
static void print_sd_cid(const struct sd_cid *cid)
|
||||
{
|
||||
puts("Manufacturer: 0x");
|
||||
print8(cid->mid);
|
||||
puts("OEM \"");
|
||||
this_board->putc(cid->oid_0);
|
||||
this_board->putc(cid->oid_1);
|
||||
puts("\"\nProduct name: \"");
|
||||
this_board->putc(cid->pnm_0);
|
||||
this_board->putc(cid->pnm_1);
|
||||
this_board->putc(cid->pnm_2);
|
||||
this_board->putc(cid->pnm_3);
|
||||
this_board->putc(cid->pnm_4);
|
||||
puts("\", revision ");
|
||||
printdec(cid->prv >> 4);
|
||||
puts(".");
|
||||
printdec(cid->prv & 15);
|
||||
puts("\nSerial number: ");
|
||||
printdec(cid->psn_0 << 24 | cid->psn_1 << 16 | cid->psn_2 << 8 |
|
||||
cid->psn_3);
|
||||
puts("\nManufacturing date: ");
|
||||
printdec(cid->mdt_1 & 15);
|
||||
puts("/");
|
||||
printdec(2000+((cid->mdt_0 & 15) << 4)+((cid->mdt_1 & 0xf0) >> 4));
|
||||
puts("\nCRC: 0x");
|
||||
print8(cid->crc >> 1);
|
||||
puts(" b0 = ");
|
||||
print8(cid->crc & 1);
|
||||
puts("\n");
|
||||
}
|
||||
|
||||
int s3c24xx_mmc_init(int verbose)
|
||||
{
|
||||
int retries, rc = -2;
|
||||
int is_sd = 0;
|
||||
u32 *resp;
|
||||
|
||||
SDICON = S3C2410_SDICON_FIFORESET | S3C2410_SDICON_CLOCKTYPE;
|
||||
SDIBSIZE = 512;
|
||||
if (am_i_s3c2410()) {
|
||||
/* S3C2410 has some bug that prevents reliable operation at higher speed */
|
||||
//SDIPRE = 0x3e; /* SDCLK = PCLK/2 / (SDIPRE+1) = 396kHz */
|
||||
SDIPRE = 0x02; /* 2410: SDCLK = PCLK/2 / (SDIPRE+1) = 11MHz */
|
||||
SDIDTIMER = 0xffff;
|
||||
SDIIMSK2410 = 0x0;
|
||||
} else {
|
||||
SDIPRE = 0x05; /* 2410: SDCLK = PCLK / (SDIPRE+1) = 11MHz */
|
||||
SDIDTIMER = 0x7fffff;
|
||||
SDIIMSK = 0x0;
|
||||
}
|
||||
|
||||
udelay(1250000); /* FIXME: 74 SDCLK cycles */
|
||||
|
||||
mmc_csd.c_size = 0;
|
||||
|
||||
puts("Sending reset...\n");
|
||||
|
||||
/* reset */
|
||||
retries = 10;
|
||||
resp = mmc_cmd(MMC_CMD_RESET, 0, 0);
|
||||
|
||||
puts("trying to detect SD Card...\n");
|
||||
while (retries--) {
|
||||
udelay(1000000);
|
||||
resp = mmc_cmd(55, 0x00000000, CMD_F_RESP);
|
||||
resp = mmc_cmd(41, 0x00300000, CMD_F_RESP);
|
||||
|
||||
if (resp[0] & (1 << 31)) {
|
||||
is_sd = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (retries < 0 && !is_sd)
|
||||
return -3;
|
||||
|
||||
/* try to get card id */
|
||||
resp = mmc_cmd(MMC_CMD_ALL_SEND_CID, 0, CMD_F_RESP|CMD_F_RESP_LONG);
|
||||
if (resp) {
|
||||
if (!is_sd) {
|
||||
/* TODO configure mmc driver depending on card
|
||||
attributes */
|
||||
mmc_cid_t *cid = (mmc_cid_t *)resp;
|
||||
|
||||
if (verbose)
|
||||
print_mmc_cid(cid);
|
||||
#if 0
|
||||
sprintf((char *) mmc_dev.vendor,
|
||||
"Man %02x%02x%02x Snr %02x%02x%02x",
|
||||
cid->id[0], cid->id[1], cid->id[2],
|
||||
cid->sn[0], cid->sn[1], cid->sn[2]);
|
||||
sprintf((char *) mmc_dev.product,"%s",cid->name);
|
||||
sprintf((char *) mmc_dev.revision,"%x %x",
|
||||
cid->hwrev, cid->fwrev);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
struct sd_cid *cid = (struct sd_cid *) resp;
|
||||
|
||||
if (verbose)
|
||||
print_sd_cid(cid);
|
||||
#if 0
|
||||
sprintf((char *) mmc_dev.vendor,
|
||||
"Man %02 OEM %c%c \"%c%c%c%c%c\"",
|
||||
cid->mid, cid->oid_0, cid->oid_1,
|
||||
cid->pnm_0, cid->pnm_1, cid->pnm_2, cid->pnm_3,
|
||||
cid->pnm_4);
|
||||
sprintf((char *) mmc_dev.product, "%d",
|
||||
cid->psn_0 << 24 | cid->psn_1 << 16 |
|
||||
cid->psn_2 << 8 | cid->psn_3);
|
||||
sprintf((char *) mmc_dev.revision, "%d.%d",
|
||||
cid->prv >> 4, cid->prv & 15);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* MMC exists, get CSD too */
|
||||
resp = mmc_cmd(MMC_CMD_SET_RCA, MMC_DEFAULT_RCA, CMD_F_RESP);
|
||||
if (is_sd)
|
||||
rca = resp[0] >> 16;
|
||||
|
||||
resp = mmc_cmd(MMC_CMD_SEND_CSD, rca<<16, CMD_F_RESP|CMD_F_RESP_LONG);
|
||||
if (resp) {
|
||||
mmc_csd_t *csd = (mmc_csd_t *)resp;
|
||||
memcpy(&mmc_csd, csd, sizeof(csd));
|
||||
rc = 0;
|
||||
mmc_ready = 1;
|
||||
#if 0
|
||||
/* FIXME add verbose printout for csd */
|
||||
printf("READ_BL_LEN=%u, C_SIZE_MULT=%u, C_SIZE=%u\n",
|
||||
csd->read_bl_len, csd->c_size_mult1, csd->c_size);
|
||||
printf("size = %u\n", mmc_size(csd));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
resp = mmc_cmd(MMC_CMD_SELECT_CARD, rca<<16, CMD_F_RESP);
|
||||
|
||||
#ifdef CONFIG_MMC_WIDE
|
||||
if (is_sd) {
|
||||
resp = mmc_cmd(55, rca<<16, CMD_F_RESP);
|
||||
resp = mmc_cmd(6, 0x02, CMD_F_RESP);
|
||||
wide = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
77
qiboot/src/cpu/s3c2442/serial-s3c24xx.c
Normal file
77
qiboot/src/cpu/s3c2442/serial-s3c24xx.c
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
* Author: xiangfu liu <xiangfu@openmoko.org>
|
||||
*
|
||||
* Configuation settings for the FIC Neo GTA02 Linux GSM phone
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <qi.h>
|
||||
#include <serial-s3c24xx.h>
|
||||
|
||||
void serial_init_115200_s3c24xx(const int uart, const int pclk_MHz)
|
||||
{
|
||||
int div = (((54 * pclk_MHz) + 26) / 100) -1;
|
||||
switch(uart)
|
||||
{
|
||||
case UART0:
|
||||
rULCON0 = 0x3;
|
||||
rUCON0 = 0x245;
|
||||
rUFCON0 = 0x0;
|
||||
rUMCON0 = 0x0;
|
||||
rUBRDIV0 = div;
|
||||
break;
|
||||
case UART1:
|
||||
rULCON1 = 0x3;
|
||||
rUCON1 = 0x245;
|
||||
rUFCON1 = 0x0;
|
||||
rUMCON1 = 0x0;
|
||||
rUBRDIV1 = div;
|
||||
break;
|
||||
case UART2:
|
||||
rULCON2 = 0x3;
|
||||
rUCON2 = 0x245;
|
||||
rUFCON2 = 0x1;
|
||||
rUBRDIV2 = div;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Output a single byte to the serial port.
|
||||
*/
|
||||
void serial_putc_s3c24xx(const int uart, const char c)
|
||||
{
|
||||
switch(uart)
|
||||
{
|
||||
case UART0:
|
||||
while ( !( rUTRSTAT0 & 0x2 ) );
|
||||
WrUTXH0(c);
|
||||
break;
|
||||
case UART1:
|
||||
while ( !( rUTRSTAT1 & 0x2 ) );
|
||||
WrUTXH1(c);
|
||||
break;
|
||||
case UART2:
|
||||
while ( !( rUTRSTAT2 & 0x2 ) );
|
||||
WrUTXH2(c);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
315
qiboot/src/cpu/s3c2442/start.S
Normal file
315
qiboot/src/cpu/s3c2442/start.S
Normal file
@ -0,0 +1,315 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
*
|
||||
* Configuation settings for the OPENMOKO Neo GTA02 Linux GSM phone
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#define __ASM_MODE__
|
||||
#define __ASSEMBLY__
|
||||
|
||||
#include <neo_gta02.h>
|
||||
|
||||
#define S3C2410_MISCCR_nEN_SCLK0 (1 << 17)
|
||||
#define S3C2410_MISCCR_nEN_SCLK1 (1 << 18)
|
||||
#define S3C2410_MISCCR_nEN_SCLKE (1 << 19)
|
||||
|
||||
|
||||
.globl _start, processor_id, is_jtag
|
||||
|
||||
_start: b start_code
|
||||
/* if we are injected by JTAG, the script sets _istag content to nonzero */
|
||||
is_jtag:
|
||||
.word 0
|
||||
|
||||
/* it's at a fixed address (+0x8) so we can breakpoint it in the JTAG script
|
||||
* we need to go through this hassle because before this moment, SDRAM is not
|
||||
* working so we can't prep it from JTAG
|
||||
*/
|
||||
|
||||
_steppingstone_done:
|
||||
ldr pc, _start_armboot
|
||||
|
||||
_start_armboot:
|
||||
.word start_qi
|
||||
|
||||
_TEXT_BASE:
|
||||
.word TEXT_BASE
|
||||
|
||||
/*
|
||||
* These are defined in the board-specific linker script.
|
||||
*/
|
||||
.globl _bss_start
|
||||
_bss_start:
|
||||
.word __bss_start
|
||||
|
||||
.globl _bss_end
|
||||
_bss_end:
|
||||
.word _end
|
||||
/*
|
||||
* we have a stack in steppingstone because we can want to run full memory
|
||||
* memory tests
|
||||
*/
|
||||
|
||||
.fill 128
|
||||
.globl _ss_stack
|
||||
_ss_stack:
|
||||
|
||||
|
||||
start_code:
|
||||
/*
|
||||
* set the cpu to SVC32 mode
|
||||
*/
|
||||
mrs r0,cpsr
|
||||
bic r0,r0,#0x1f
|
||||
orr r0,r0,#0xd3
|
||||
msr cpsr,r0
|
||||
|
||||
# define pWTCON 0x53000000
|
||||
|
||||
ldr r0, =pWTCON
|
||||
mov r1, #0x0
|
||||
str r1, [r0]
|
||||
|
||||
/*
|
||||
* mask all IRQs by setting all bits in the INTMR - default
|
||||
*/
|
||||
# define INTMSK 0x4A000008 /* Interupt-Controller base addresses */
|
||||
# define INTSUBMSK 0x4A00001C
|
||||
# define INTSUBMSK_val 0x0000ffff
|
||||
|
||||
mov r1, #0xffffffff
|
||||
ldr r0, =INTMSK
|
||||
str r1, [r0]
|
||||
|
||||
ldr r1, =INTSUBMSK_val
|
||||
ldr r0, =INTSUBMSK
|
||||
str r1, [r0]
|
||||
|
||||
|
||||
/* Make sure we get FCLK:HCLK:PCLK = 1:3:6 */
|
||||
# define CAMDIVN 0x4C000018
|
||||
|
||||
ldr r0, =CAMDIVN
|
||||
mov r1, #0
|
||||
str r1, [r0]
|
||||
|
||||
/* Clock asynchronous mode */
|
||||
mrc p15, 0, r1, c1, c0, 0
|
||||
orr r1, r1, #0xc0000000
|
||||
mcr p15, 0, r1, c1, c0, 0
|
||||
|
||||
#define LOCKTIME 0x4c000000
|
||||
|
||||
ldr r0, =LOCKTIME
|
||||
mov r1, #0xffffff
|
||||
str r1, [r0]
|
||||
|
||||
# define UPLLCON 0x4c000008
|
||||
# define MPLLCON_val ((142 << 12) + (7 << 4) + 1)
|
||||
# define UPLLCON_val (( 88 << 12) + (8 << 4) + 2)
|
||||
|
||||
ldr r0, =UPLLCON
|
||||
ldr r1, =UPLLCON_val
|
||||
str r1, [r0]
|
||||
|
||||
/* Page 7-19, seven nops between UPLL and MPLL */
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
ldr r1, =MPLLCON_val
|
||||
str r1, [r0, #-4] /* MPLLCON */
|
||||
|
||||
# define CLKDIVN 0x4C000014 /* clock divisor register */
|
||||
# define CLKDIVN_val 7 /* FCLK:HCLK:PCLK = 1:3:6 */
|
||||
|
||||
/* FCLK:HCLK:PCLK = 1:3:6 */
|
||||
ldr r0, =CLKDIVN
|
||||
mov r1, #CLKDIVN_val
|
||||
str r1, [r0]
|
||||
|
||||
/* enable only CPU peripheral block clocks we actually use */
|
||||
ldr r0, =0x4c00000c /* clkcon */
|
||||
ldr r1, =0x3f10 /* uart, pwm, gpio, nand, sdi clocks on */
|
||||
str r1, [r0]
|
||||
|
||||
/* gpio UART2 init, H port */
|
||||
ldr r0, =0x56000070
|
||||
ldr r1, =0x001AAAAA
|
||||
str r1, [r0]
|
||||
|
||||
/* enable KEEPACT(GPJ8) to make sure PMU keeps us alive */
|
||||
ldr r0, =0x56000000 /* GPJ base */
|
||||
ldr r1, [r0, #0xd0] /* GPJCON */
|
||||
orr r1, r1, #(1 << 16)
|
||||
str r1, [r0, #0xd0]
|
||||
|
||||
ldr r1, [r0, #0xd4] /* GPJDAT */
|
||||
orr r1, r1, #(1 << 8)
|
||||
str r1, [r0, #0xd4]
|
||||
|
||||
|
||||
/* init uart2 */
|
||||
ldr r0, =0x50008000
|
||||
mov r1, #0x03
|
||||
str r1, [r0]
|
||||
ldr r1, =0x245
|
||||
str r1, [r0, #0x04]
|
||||
mov r1, #0x00
|
||||
str r1, [r0, #0x08]
|
||||
mov r1, #0x00
|
||||
str r1, [r0, #0x0c]
|
||||
mov r1, #0x11
|
||||
str r1, [r0, #0x28]
|
||||
|
||||
ldr r0, =0x50008000
|
||||
ldr r1, =0x54
|
||||
str r1, [r0, #0x20]
|
||||
|
||||
/* reset nand controller, or it is dead to us */
|
||||
|
||||
mov r1, #0x4E000000
|
||||
ldr r2, =0xfff0 @ initial value tacls=3,rph0=7,rph1=7
|
||||
ldr r3, [r1, #0]
|
||||
orr r3, r3, r2
|
||||
str r3, [r1, #0]
|
||||
|
||||
ldr r3, [r1, #4]
|
||||
orr r3, r3, #1 @ enable nand controller
|
||||
str r3, [r1, #4]
|
||||
|
||||
|
||||
/* take sdram out of power down */
|
||||
ldr r0, =0x56000080 /* misccr */
|
||||
ldr r1, [ r0 ]
|
||||
bic r1, r1, #(S3C2410_MISCCR_nEN_SCLK0 | S3C2410_MISCCR_nEN_SCLK1 | S3C2410_MISCCR_nEN_SCLKE)
|
||||
str r1, [ r0 ]
|
||||
|
||||
/* ensure signals stabalise */
|
||||
mov r1, #128
|
||||
1: subs r1, r1, #1
|
||||
bpl 1b
|
||||
|
||||
bl cpu_init_crit
|
||||
|
||||
/* ensure some refresh has happened */
|
||||
ldr r1, =0xfffff
|
||||
1: subs r1, r1, #1
|
||||
bpl 1b
|
||||
|
||||
/* capture full EINT situation into gstatus 4 */
|
||||
|
||||
ldr r0, =0x4A000000 /* SRCPND */
|
||||
ldr r1, [ r0 ]
|
||||
and r1, r1, #0xf
|
||||
|
||||
ldr r0, =0x560000BC /* gstatus4 */
|
||||
str r1, [ r0 ]
|
||||
|
||||
ldr r0, =0x560000A8 /* EINTPEND */
|
||||
ldr r1, [ r0 ]
|
||||
ldr r0, =0xfff0
|
||||
and r1, r1, r0
|
||||
ldr r0, =0x560000BC /* gstatus4 */
|
||||
ldr r0, [ r0 ]
|
||||
orr r1, r1, r0
|
||||
ldr r0, =0x560000BC /* gstatus4 */
|
||||
str r1, [ r0 ]
|
||||
|
||||
/* test for resume */
|
||||
|
||||
ldr r1, =0x560000B4 /* gstatus2 */
|
||||
ldr r0, [ r1 ]
|
||||
tst r0, #0x02 /* is this resume from power down */
|
||||
/* well, if it was, we are going to jump to
|
||||
* whatever address we stashed in gstatus3,
|
||||
* and gstatus4 will hold the wake interrupt
|
||||
* source for the OS to look at
|
||||
*/
|
||||
ldrne pc, [r1, #4]
|
||||
|
||||
|
||||
/* >> CFG_VIDEO_LOGO_MAX_SIZE */
|
||||
#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
|
||||
|
||||
stack_setup:
|
||||
ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
|
||||
sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */
|
||||
sub sp, r0, #12 /* leave 3 words for abort-stack */
|
||||
|
||||
clear_bss:
|
||||
ldr r0, _bss_start /* find start of bss segment */
|
||||
ldr r1, _bss_end /* stop here */
|
||||
mov r2, #0x00000000 /* clear */
|
||||
|
||||
clbss_l:
|
||||
str r2, [r0] /* clear loop... */
|
||||
add r0, r0, #4
|
||||
cmp r0, r1
|
||||
ble clbss_l
|
||||
|
||||
/* we are going to jump into the C part of the init now */
|
||||
spin:
|
||||
b _steppingstone_done
|
||||
|
||||
/*
|
||||
*************************************************************************
|
||||
*
|
||||
* CPU_init_critical registers
|
||||
*
|
||||
* setup important registers
|
||||
* setup memory timing
|
||||
*
|
||||
*************************************************************************
|
||||
*/
|
||||
|
||||
cpu_init_crit:
|
||||
|
||||
/*
|
||||
* flush v4 I/D caches
|
||||
*/
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
|
||||
mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
|
||||
|
||||
/*
|
||||
* disable MMU stuff and caches
|
||||
*/
|
||||
mrc p15, 0, r0, c1, c0, 0
|
||||
bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
|
||||
bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
|
||||
orr r0, r0, #0x00000002 @ set bit 2 (A) Align
|
||||
orr r0, r0, #0x00005000 @ set bits 14, 12 D and I-Cache
|
||||
mcr p15, 0, r0, c1, c0, 0
|
||||
|
||||
/*
|
||||
* before relocating, we have to setup RAM timing
|
||||
* because memory timing is board-dependend, you will
|
||||
* find a lowlevel_init.S in your board directory.
|
||||
*/
|
||||
mov ip, lr
|
||||
|
||||
bl lowlevel_init
|
||||
|
||||
mov lr, ip
|
||||
mov pc, lr
|
||||
|
126
qiboot/src/cpu/s3c2442/start_qi.c
Normal file
126
qiboot/src/cpu/s3c2442/start_qi.c
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
* Author: xiangfu liu <xiangfu@openmoko.org>
|
||||
* Andy Green <andy@openmoko.com>
|
||||
*
|
||||
* Configuation settings for the OPENMOKO Neo GTA02 Linux GSM phone
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* NOTE this stuff runs in steppingstone context! */
|
||||
|
||||
|
||||
#include <qi.h>
|
||||
#include "nand_read.h"
|
||||
#include <neo_gta02.h>
|
||||
|
||||
#define stringify2(s) stringify1(s)
|
||||
#define stringify1(s) #s
|
||||
|
||||
|
||||
extern void bootloader_second_phase(void);
|
||||
|
||||
const struct board_api *boards[] = {
|
||||
&board_api_gta02,
|
||||
NULL /* always last */
|
||||
};
|
||||
|
||||
|
||||
struct board_api const * this_board;
|
||||
extern int is_jtag;
|
||||
|
||||
void start_qi(void)
|
||||
{
|
||||
int flag = 0;
|
||||
int board = 0;
|
||||
|
||||
/*
|
||||
* well, we can be running on this CPU two different ways.
|
||||
*
|
||||
* 1) We were copied into steppingstone and TEXT_BASE already
|
||||
* by JTAG. We don't have to do anything else. JTAG script
|
||||
* then sets data at address 0x4 to 0xffffffff as a signal we
|
||||
* are running by JTAG.
|
||||
*
|
||||
* 2) We only got our first 4K into steppingstone, we need to copy
|
||||
* the rest of ourselves into TEXT_BASE.
|
||||
*
|
||||
* So we do the copy out of NAND only if we see we did not come up
|
||||
* under control of JTAG.
|
||||
*/
|
||||
|
||||
if (!is_jtag)
|
||||
/*
|
||||
* We got the first 4KBytes of the bootloader pulled into the
|
||||
* steppingstone SRAM for free. Now we pull the whole bootloader
|
||||
* image into SDRAM.
|
||||
*
|
||||
* This code and the .S files are arranged by the linker script
|
||||
* to expect to run from 0x0. But the linker script has told
|
||||
* everything else to expect to run from 0x33000000+. That's
|
||||
* why we are going to be able to copy this code and not have it
|
||||
* crash when we run it from there.
|
||||
*/
|
||||
|
||||
/* We randomly pull 32KBytes of bootloader */
|
||||
if (nand_read_ll((u8 *)TEXT_BASE, 0, 32 * 1024 / 512) < 0)
|
||||
goto unhappy;
|
||||
|
||||
/* ask all the boards we support in turn if they recognize this
|
||||
* hardware we are running on, accept the first positive answer
|
||||
*/
|
||||
|
||||
this_board = boards[board];
|
||||
while (!flag && this_board) {
|
||||
|
||||
/* check if it is the right board... */
|
||||
if (this_board->is_this_board()) {
|
||||
flag = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
this_board = boards[board++];
|
||||
}
|
||||
|
||||
this_board->port_init();
|
||||
set_putc_func(this_board->putc);
|
||||
|
||||
/* stick some hello messages on debug console */
|
||||
|
||||
puts("\n\n\nQi Bootloader "stringify2(QI_CPU)" "
|
||||
stringify2(BUILD_HOST)" "
|
||||
stringify2(BUILD_VERSION)" "
|
||||
"\n");
|
||||
|
||||
puts(stringify2(BUILD_DATE) " Copyright (C) 2008 Openmoko, Inc.\n");
|
||||
puts("\n Detected: ");
|
||||
|
||||
puts(this_board->name);
|
||||
puts(", ");
|
||||
puts((this_board->get_board_variant)()->name);
|
||||
puts("\n");
|
||||
|
||||
/*
|
||||
* jump to bootloader_second_phase() running from DRAM copy
|
||||
*/
|
||||
bootloader_second_phase();
|
||||
|
||||
unhappy:
|
||||
while(1)
|
||||
;
|
||||
|
||||
}
|
650
qiboot/src/cpu/s3c6410/hs_mmc.c
Normal file
650
qiboot/src/cpu/s3c6410/hs_mmc.c
Normal file
@ -0,0 +1,650 @@
|
||||
#include <qi.h>
|
||||
#include "hs_mmc.h"
|
||||
#include <string.h>
|
||||
#include <glamo-mmc.h>
|
||||
|
||||
#define HCLK_OPERATION
|
||||
#undef DEBUG_HSMMC
|
||||
#ifdef DEBUG_HSMMC
|
||||
#define dbg(x...) printf(x)
|
||||
#else
|
||||
#define dbg(x...) do { } while (0)
|
||||
#endif
|
||||
|
||||
//#include <linux-mmc.h>
|
||||
#include <linux-mmc-protocol.h>
|
||||
#include <s3c6410.h>
|
||||
//#include <linux/mmc/protocol.h>
|
||||
//#include <asm/io.h>
|
||||
//#include <movi.h>
|
||||
|
||||
#include "hs_mmc.h"
|
||||
#include <mmc.h>
|
||||
|
||||
#define SDI_Tx_buffer_HSMMC (0x51000000)
|
||||
#define SDI_Rx_buffer_HSMMC (0x51000000+(0x300000))
|
||||
#define SDI_Compare_buffer_HSMMC (0x51000000+(0x600000))
|
||||
|
||||
#define Card_OneBlockSize_ver1 512
|
||||
|
||||
#define MMC_DEFAULT_RCA (1<<16)
|
||||
|
||||
/* Global variables */
|
||||
|
||||
static u32 HS_DMA_END = 0;
|
||||
static u32 rca = 0;
|
||||
|
||||
static ulong HCLK;
|
||||
|
||||
int movi_hc = 1; /* sdhc style block indexing */
|
||||
enum card_type card_type;
|
||||
|
||||
/* extern functions */
|
||||
extern ulong get_HCLK(void);
|
||||
|
||||
|
||||
#define s3c_hsmmc_readl(x) *((unsigned int *)(((ELFIN_HSMMC_BASE + (HSMMC_CHANNEL * 0x100000)) + (x))))
|
||||
#define s3c_hsmmc_readw(x) *((unsigned short *)(((ELFIN_HSMMC_BASE + (HSMMC_CHANNEL * 0x100000)) + (x))))
|
||||
#define s3c_hsmmc_readb(x) *((unsigned char *)(((ELFIN_HSMMC_BASE + (HSMMC_CHANNEL * 0x100000)) + (x))))
|
||||
|
||||
#define s3c_hsmmc_writel(v,x) *((unsigned int *) (((ELFIN_HSMMC_BASE + (HSMMC_CHANNEL * 0x100000)) + (x)))) = v
|
||||
#define s3c_hsmmc_writew(v,x) *((unsigned short *)(((ELFIN_HSMMC_BASE + (HSMMC_CHANNEL * 0x100000)) + (x)))) = v
|
||||
#define s3c_hsmmc_writeb(v,x) *((unsigned char *)(((ELFIN_HSMMC_BASE + (HSMMC_CHANNEL * 0x100000)) + (x)))) = v
|
||||
|
||||
#define readl(x) *((unsigned int *)(x))
|
||||
#define writel(v, x) *((unsigned int *)(x)) = v
|
||||
|
||||
#define UNSTUFF_BITS(resp,start,size) \
|
||||
({ \
|
||||
const int __size = size; \
|
||||
const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1; \
|
||||
const int __off = 3 - ((start) / 32); \
|
||||
const int __shft = (start) & 31; \
|
||||
u32 __res; \
|
||||
\
|
||||
__res = resp[__off] >> __shft; \
|
||||
if (__size + __shft > 32) \
|
||||
__res |= resp[__off-1] << ((32 - __shft) & 31); \
|
||||
__res & __mask; \
|
||||
})
|
||||
|
||||
static int wait_for_cmd_done (void)
|
||||
{
|
||||
u32 i;
|
||||
ushort n_int, e_int;
|
||||
|
||||
dbg("wait_for_cmd_done\n");
|
||||
for (i = 0; i < 0x20000000; i++) {
|
||||
n_int = s3c_hsmmc_readw(HM_NORINTSTS);
|
||||
dbg(" HM_NORINTSTS: %04x\n", n_int);
|
||||
if (n_int & 0x8000)
|
||||
/* any error */
|
||||
break;
|
||||
if (n_int & 0x0001)
|
||||
/* command complete */
|
||||
return 0;
|
||||
}
|
||||
|
||||
e_int = s3c_hsmmc_readw(HM_ERRINTSTS);
|
||||
s3c_hsmmc_writew(e_int, HM_ERRINTSTS);
|
||||
s3c_hsmmc_writew(n_int, HM_NORINTSTS);
|
||||
puts("cmd error1: 0x");
|
||||
print32(e_int);
|
||||
puts(", HM_NORINTSTS: 0x");
|
||||
print32(n_int);
|
||||
puts("\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static void ClearCommandCompleteStatus(void)
|
||||
{
|
||||
s3c_hsmmc_writew(1 << 0, HM_NORINTSTS);
|
||||
while (s3c_hsmmc_readw(HM_NORINTSTS) & 0x1) {
|
||||
s3c_hsmmc_writew(1 << 0, HM_NORINTSTS);
|
||||
}
|
||||
}
|
||||
|
||||
static void card_irq_enable(ushort temp)
|
||||
{
|
||||
s3c_hsmmc_writew((s3c_hsmmc_readw(HM_NORINTSTSEN) & 0xFEFF) | (temp << 8), HM_NORINTSTSEN);
|
||||
}
|
||||
|
||||
void hsmmc_reset (void)
|
||||
{
|
||||
s3c_hsmmc_writeb(0x3, HM_SWRST);
|
||||
}
|
||||
|
||||
void hsmmc_set_gpio (void)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
reg = readl(GPGCON) & 0xf0000000;
|
||||
writel(reg | 0x02222222, GPGCON);
|
||||
|
||||
reg = readl(GPGPUD) & 0xfffff000;
|
||||
writel(reg, GPGPUD);
|
||||
}
|
||||
|
||||
static void set_transfer_mode_register (u32 MultiBlk, u32 DataDirection, u32 AutoCmd12En, u32 BlockCntEn, u32 DmaEn)
|
||||
{
|
||||
s3c_hsmmc_writew((s3c_hsmmc_readw(HM_TRNMOD) & ~(0xffff)) | (MultiBlk << 5)
|
||||
| (DataDirection << 4) | (AutoCmd12En << 2)
|
||||
| (BlockCntEn << 1) | (DmaEn << 0), HM_TRNMOD);
|
||||
// dbg("\nHM_TRNMOD = 0x%04x\n", HM_TRNMOD);
|
||||
}
|
||||
|
||||
static void set_arg_register (u32 arg)
|
||||
{
|
||||
s3c_hsmmc_writel(arg, HM_ARGUMENT);
|
||||
}
|
||||
|
||||
static void set_blkcnt_register(ushort uBlkCnt)
|
||||
{
|
||||
s3c_hsmmc_writew(uBlkCnt, HM_BLKCNT);
|
||||
}
|
||||
|
||||
static void SetSystemAddressReg(u32 SysAddr)
|
||||
{
|
||||
s3c_hsmmc_writel(SysAddr, HM_SYSAD);
|
||||
}
|
||||
|
||||
static void set_blksize_register(ushort uDmaBufBoundary, ushort uBlkSize)
|
||||
{
|
||||
s3c_hsmmc_writew((uDmaBufBoundary << 12) | (uBlkSize), HM_BLKSIZE);
|
||||
}
|
||||
|
||||
static void ClearErrInterruptStatus(void)
|
||||
{
|
||||
while (s3c_hsmmc_readw(HM_NORINTSTS) & (0x1 << 15)) {
|
||||
s3c_hsmmc_writew(s3c_hsmmc_readw(HM_NORINTSTS), HM_NORINTSTS);
|
||||
s3c_hsmmc_writew(s3c_hsmmc_readw(HM_ERRINTSTS), HM_ERRINTSTS);
|
||||
}
|
||||
}
|
||||
|
||||
static void InterruptEnable(ushort NormalIntEn, ushort ErrorIntEn)
|
||||
{
|
||||
ClearErrInterruptStatus();
|
||||
s3c_hsmmc_writew(NormalIntEn, HM_NORINTSTSEN);
|
||||
s3c_hsmmc_writew(ErrorIntEn, HM_ERRINTSTSEN);
|
||||
}
|
||||
|
||||
static void hsmmc_clock_onoff (int on)
|
||||
{
|
||||
u16 reg16;
|
||||
|
||||
if (on == 0) {
|
||||
reg16 = s3c_hsmmc_readw(HM_CLKCON) & ~(0x1<<2);
|
||||
s3c_hsmmc_writew(reg16, HM_CLKCON);
|
||||
} else {
|
||||
reg16 = s3c_hsmmc_readw(HM_CLKCON);
|
||||
s3c_hsmmc_writew(reg16 | (0x1<<2), HM_CLKCON);
|
||||
|
||||
while (1) {
|
||||
reg16 = s3c_hsmmc_readw(HM_CLKCON);
|
||||
if (reg16 & (0x1<<3)) /* SD_CLKSRC is Stable */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void set_clock (u32 clksrc, u32 div)
|
||||
{
|
||||
u16 reg16;
|
||||
u32 i;
|
||||
|
||||
s3c_hsmmc_writel(0xC0004100 | (clksrc << 4), HM_CONTROL2); // rx feedback control
|
||||
s3c_hsmmc_writel(0x00008080, HM_CONTROL3); // Low clock: 00008080
|
||||
s3c_hsmmc_writel(0x3 << 16, HM_CONTROL4);
|
||||
|
||||
s3c_hsmmc_writew(s3c_hsmmc_readw(HM_CLKCON) & ~(0xff << 8), HM_CLKCON);
|
||||
|
||||
/* SDCLK Value Setting + Internal Clock Enable */
|
||||
s3c_hsmmc_writew(((div<<8) | 0x1), HM_CLKCON);
|
||||
|
||||
/* CheckInternalClockStable */
|
||||
for (i = 0; i < 0x10000; i++) {
|
||||
reg16 = s3c_hsmmc_readw(HM_CLKCON);
|
||||
if (reg16 & 0x2)
|
||||
break;
|
||||
}
|
||||
if (i == 0x10000)
|
||||
puts("internal clock stabilization failed\n");
|
||||
|
||||
hsmmc_clock_onoff(1);
|
||||
}
|
||||
|
||||
static void set_cmd_register (ushort cmd, u32 data, u32 flags)
|
||||
{
|
||||
ushort val = (cmd << 8);
|
||||
|
||||
if (cmd == 12)
|
||||
val |= (3 << 6);
|
||||
|
||||
if (flags & MMC_RSP_136) /* Long RSP */
|
||||
val |= 0x01;
|
||||
else if (flags & MMC_RSP_BUSY) /* R1B */
|
||||
val |= 0x03;
|
||||
else if (flags & MMC_RSP_PRESENT) /* Normal RSP */
|
||||
val |= 0x02;
|
||||
|
||||
if (flags & MMC_RSP_OPCODE)
|
||||
val |= (1<<4);
|
||||
|
||||
if (flags & MMC_RSP_CRC)
|
||||
val |= (1<<3);
|
||||
|
||||
if (data)
|
||||
val |= (1<<5);
|
||||
|
||||
// puts("cmdreg = 0x");
|
||||
// print32(val);
|
||||
// puts("\n");
|
||||
s3c_hsmmc_writew(val, HM_CMDREG);
|
||||
}
|
||||
|
||||
static int issue_command (ushort cmd, u32 arg, u32 data, u32 flags)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* puts("### issue_command: ");
|
||||
printdec(cmd);
|
||||
puts(" 0x");
|
||||
print32(arg);
|
||||
puts(" ");
|
||||
printdec(data);
|
||||
puts(" 0x");
|
||||
print32(flags);
|
||||
puts("\n");
|
||||
*/
|
||||
/* Check CommandInhibit_CMD */
|
||||
for (i = 0; i < 0x1000000; i++) {
|
||||
if (!(s3c_hsmmc_readl(HM_PRNSTS) & 0x1))
|
||||
break;
|
||||
}
|
||||
if (i == 0x1000000) {
|
||||
puts("@@@@@@1 rHM_PRNSTS: ");
|
||||
printdec(s3c_hsmmc_readl(HM_PRNSTS));
|
||||
puts("\n");
|
||||
}
|
||||
|
||||
/* Check CommandInhibit_DAT */
|
||||
if (flags & MMC_RSP_BUSY) {
|
||||
for (i = 0; i < 0x1000000; i++) {
|
||||
if (!(s3c_hsmmc_readl(HM_PRNSTS) & 0x2))
|
||||
break;
|
||||
}
|
||||
if (i == 0x1000000) {
|
||||
puts("@@@@@@2 rHM_PRNSTS: ");
|
||||
print32(s3c_hsmmc_readl(HM_PRNSTS));
|
||||
puts("\n");
|
||||
}
|
||||
}
|
||||
|
||||
s3c_hsmmc_writel(arg, HM_ARGUMENT);
|
||||
|
||||
set_cmd_register(cmd, data, flags);
|
||||
|
||||
if (wait_for_cmd_done())
|
||||
return 0;
|
||||
|
||||
ClearCommandCompleteStatus();
|
||||
|
||||
if (!(s3c_hsmmc_readw(HM_NORINTSTS) & 0x8000))
|
||||
return 1;
|
||||
|
||||
puts("Command = ");
|
||||
printdec((s3c_hsmmc_readw(HM_CMDREG) >> 8));
|
||||
puts(", Error Stat = 0x");
|
||||
print32(s3c_hsmmc_readw(HM_ERRINTSTS));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_card_status(void)
|
||||
{
|
||||
if (!issue_command(MMC_SEND_STATUS, rca<<16, 0, MMC_RSP_R1))
|
||||
return 0;
|
||||
|
||||
if (((s3c_hsmmc_readl(HM_RSPREG0) >> 9) & 0xf) == 4) {
|
||||
// puts("Card is transfer status\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void set_hostctl_speed (u8 mode)
|
||||
{
|
||||
u8 reg8;
|
||||
|
||||
reg8 = s3c_hsmmc_readb(HM_HOSTCTL) & ~(0x1<<2);
|
||||
s3c_hsmmc_writeb(reg8 | (mode<<2), HM_HOSTCTL);
|
||||
}
|
||||
|
||||
/* return 0: OK
|
||||
* return -1: error
|
||||
*/
|
||||
static int set_bus_width (u32 width)
|
||||
{
|
||||
u8 reg = s3c_hsmmc_readb(HM_HOSTCTL);
|
||||
u8 bitmode = 0;
|
||||
|
||||
card_irq_enable(0); // Disable sd card interrupt
|
||||
|
||||
|
||||
if (!issue_command(MMC_APP_CMD, rca<<16, 0, MMC_RSP_R1))
|
||||
return -1;
|
||||
else {
|
||||
if (width == 1) { // 1-bits
|
||||
bitmode = 0;
|
||||
if (!issue_command(MMC_SWITCH, 0, 0, MMC_RSP_R1B))
|
||||
return -1;
|
||||
} else { // 4-bits
|
||||
bitmode = 1;
|
||||
if (!issue_command(MMC_SWITCH, 2, 0, MMC_RSP_R1B))
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (bitmode == 2)
|
||||
reg |= 1 << 5;
|
||||
else
|
||||
reg |= bitmode << 1;
|
||||
|
||||
s3c_hsmmc_writeb(reg, HM_HOSTCTL);
|
||||
card_irq_enable(1);
|
||||
// puts(" transfer rHM_HOSTCTL(0x28) = 0x");
|
||||
// print32(s3c_hsmmc_readb(HM_HOSTCTL));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void clock_config (u32 Divisior)
|
||||
{
|
||||
if (100000000 / (Divisior * 2) > 25000000) // Higher than 25MHz, it is necessary to enable high speed mode of the host controller.
|
||||
set_hostctl_speed(HIGH);
|
||||
else
|
||||
set_hostctl_speed(NORMAL);
|
||||
|
||||
hsmmc_clock_onoff(0); // when change the sd clock frequency, need to stop sd clock.
|
||||
set_clock(SD_EPLL, Divisior);
|
||||
}
|
||||
|
||||
static void check_dma_int (void)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < 0x10000000; i++) {
|
||||
if (s3c_hsmmc_readw(HM_NORINTSTS) & 0x0002) {
|
||||
HS_DMA_END = 1;
|
||||
s3c_hsmmc_writew(s3c_hsmmc_readw(HM_NORINTSTS) | 0x0002, HM_NORINTSTS);
|
||||
return;
|
||||
}
|
||||
if (s3c_hsmmc_readw(HM_NORINTSTS) & 0x8000) {
|
||||
puts("error found: ");
|
||||
print32(s3c_hsmmc_readw(HM_ERRINTSTS));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
puts("check_dma_int: timeout\n");
|
||||
}
|
||||
|
||||
|
||||
static void print_sd_cid(const struct sd_cid *cid)
|
||||
{
|
||||
puts(" Card Type: ");
|
||||
switch (card_type) {
|
||||
case CARDTYPE_NONE:
|
||||
puts("(None) / ");
|
||||
break;
|
||||
case CARDTYPE_MMC:
|
||||
puts("MMC / ");
|
||||
break;
|
||||
case CARDTYPE_SD:
|
||||
puts("SD / ");
|
||||
break;
|
||||
case CARDTYPE_SD20:
|
||||
puts("SD 2.0 / ");
|
||||
break;
|
||||
case CARDTYPE_SDHC:
|
||||
puts("SD 2.0 SDHC / ");
|
||||
break;
|
||||
}
|
||||
|
||||
puts("Mfr: 0x");
|
||||
print8(cid->mid);
|
||||
puts(", OEM \"");
|
||||
this_board->putc(cid->oid_0);
|
||||
this_board->putc(cid->oid_1);
|
||||
puts("\" / ");
|
||||
|
||||
this_board->putc(cid->pnm_0);
|
||||
this_board->putc(cid->pnm_1);
|
||||
this_board->putc(cid->pnm_2);
|
||||
this_board->putc(cid->pnm_3);
|
||||
this_board->putc(cid->pnm_4);
|
||||
puts("\", rev ");
|
||||
printdec(cid->prv >> 4);
|
||||
puts(".");
|
||||
printdec(cid->prv & 15);
|
||||
puts(" / s/n: ");
|
||||
print32(cid->psn_0 << 24 | cid->psn_1 << 16 | cid->psn_2 << 8 |
|
||||
cid->psn_3);
|
||||
puts(" / date: ");
|
||||
printdec(cid->mdt_1 & 15);
|
||||
puts("/");
|
||||
printdec(2000 + ((cid->mdt_0 & 15) << 4)+((cid->mdt_1 & 0xf0) >> 4));
|
||||
puts("\n");
|
||||
}
|
||||
|
||||
unsigned int s3c6410_mmc_init (int verbose)
|
||||
{
|
||||
u32 reg;
|
||||
u32 width;
|
||||
int resp;
|
||||
int hcs;
|
||||
int retries = 50;
|
||||
u8 response[16];
|
||||
unsigned int r1[4];
|
||||
struct sd_cid *sd_cid = (struct sd_cid *)response;
|
||||
struct mmc_csd *csd = (struct mmc_csd *)response;
|
||||
u8 *p8 = (u8 *)&r1[0];
|
||||
unsigned int sd_sectors = 0;
|
||||
/* we need to shift result by 8 bits spread over 4 x 32-bit regs */
|
||||
u8 mangle[] = { 7, 0, 1, 2, 11, 4, 5, 6, 15, 8, 9, 10, 0, 12, 13, 14 };
|
||||
int n;
|
||||
|
||||
hsmmc_set_gpio();
|
||||
|
||||
hsmmc_reset();
|
||||
|
||||
width = 4;
|
||||
|
||||
HCLK = 33000000; /* FIXME */
|
||||
hsmmc_clock_onoff(0);
|
||||
|
||||
reg = readl(SCLK_GATE);
|
||||
writel(reg | (1<<27), SCLK_GATE);
|
||||
|
||||
set_clock(SD_EPLL, 0x80);
|
||||
s3c_hsmmc_writeb(0xe, HM_TIMEOUTCON);
|
||||
set_hostctl_speed(NORMAL);
|
||||
|
||||
InterruptEnable(0xff, 0xff);
|
||||
|
||||
// dbg("HM_NORINTSTS = %x\n", s3c_hsmmc_readw(HM_NORINTSTS));
|
||||
|
||||
/* MMC_GO_IDLE_STATE */
|
||||
issue_command(MMC_GO_IDLE_STATE, 0x00, 0, 0);
|
||||
|
||||
udelay(100000);
|
||||
udelay(100000);
|
||||
udelay(100000);
|
||||
udelay(100000);
|
||||
|
||||
/* SDHC card? */
|
||||
|
||||
resp = issue_command(SD_SEND_IF_COND, 0x000001aa,
|
||||
0, MMC_CMD_BCR | MMC_RSP_R7);
|
||||
if (resp && ((s3c_hsmmc_readl(HM_RSPREG0) & 0xff) == 0xaa)) {
|
||||
card_type = CARDTYPE_SD20; /* 2.0 SD, may not be SDHC */
|
||||
hcs = 0x40000000;
|
||||
}
|
||||
|
||||
/* Well, either way let's say hello in SD card protocol */
|
||||
|
||||
while (retries--) {
|
||||
|
||||
udelay(100000);
|
||||
udelay(100000);
|
||||
udelay(100000);
|
||||
|
||||
resp = issue_command(MMC_APP_CMD, 0x00000000, 0,
|
||||
MMC_RSP_R1);
|
||||
if (!resp)
|
||||
continue;
|
||||
resp = issue_command(SD_APP_OP_COND, hcs | 0x00300000, 0,
|
||||
MMC_RSP_R3);
|
||||
if (!resp)
|
||||
continue;
|
||||
|
||||
if ((s3c_hsmmc_readl(HM_RSPREG0) >> 24) & (1 << 6)) { /* asserts block addressing */
|
||||
retries = -2;
|
||||
card_type = CARDTYPE_SDHC;
|
||||
}
|
||||
|
||||
if ((s3c_hsmmc_readl(HM_RSPREG0) >> 24) & (1 << 7)) { /* not busy */
|
||||
retries = -2;
|
||||
if (card_type == CARDTYPE_NONE)
|
||||
card_type = CARDTYPE_SD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (retries == -1) {
|
||||
puts("no response\n");
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (!issue_command(MMC_ALL_SEND_CID, 0, 0, MMC_RSP_R2)) {
|
||||
puts("CID broken\n");
|
||||
return -3;
|
||||
}
|
||||
|
||||
r1[0] = s3c_hsmmc_readl(HM_RSPREG3);
|
||||
r1[1] = s3c_hsmmc_readl(HM_RSPREG2);
|
||||
r1[2] = s3c_hsmmc_readl(HM_RSPREG1);
|
||||
r1[3] = s3c_hsmmc_readl(HM_RSPREG0);
|
||||
|
||||
for (n = 0; n < 16; n++)
|
||||
response[n] = p8[mangle[n]];
|
||||
|
||||
switch (card_type) {
|
||||
case CARDTYPE_SD:
|
||||
case CARDTYPE_SD20:
|
||||
case CARDTYPE_SDHC:
|
||||
|
||||
if (verbose)
|
||||
print_sd_cid(sd_cid);
|
||||
resp = issue_command(SD_SEND_RELATIVE_ADDR, MMC_DEFAULT_RCA,
|
||||
0, MMC_RSP_R6);
|
||||
rca = s3c_hsmmc_readl(HM_RSPREG0) >> 16;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* grab the CSD */
|
||||
|
||||
resp = issue_command(MMC_SEND_CSD, rca << 16, 0, MMC_RSP_R2);
|
||||
if (resp) {
|
||||
|
||||
r1[0] = s3c_hsmmc_readl(HM_RSPREG3);
|
||||
r1[1] = s3c_hsmmc_readl(HM_RSPREG2);
|
||||
r1[2] = s3c_hsmmc_readl(HM_RSPREG1);
|
||||
r1[3] = s3c_hsmmc_readl(HM_RSPREG0);
|
||||
for (n = 0; n < 16; n++)
|
||||
response[n] = p8[mangle[n]];
|
||||
|
||||
switch (card_type) {
|
||||
case CARDTYPE_SDHC:
|
||||
puts(" SDHC size: ");
|
||||
sd_sectors = (UNSTUFF_BITS(((u32 *)&response[0]), 48, 22)
|
||||
+ 1) << 10;
|
||||
break;
|
||||
default:
|
||||
puts(" MMC/SD size: ");
|
||||
sd_sectors = ((((unsigned long)1 << csd->c_size_mult1) *
|
||||
(unsigned long)(csd->c_size)) >> 9);
|
||||
}
|
||||
printdec(sd_sectors / 2048);
|
||||
puts(" MiB\n");
|
||||
} else
|
||||
puts("CSD grab broken\n");
|
||||
|
||||
resp = issue_command(MMC_SELECT_CARD, rca<<16, 0, MMC_RSP_R1);
|
||||
if (!resp)
|
||||
return 1;
|
||||
|
||||
/* Operating Clock setting */
|
||||
clock_config(2); // Divisor 1 = Base clk /2 ,Divisor 2 = Base clk /4, Divisor 4 = Base clk /8 ...
|
||||
|
||||
while (set_bus_width(width));
|
||||
while (!check_card_status());
|
||||
|
||||
/* MMC_SET_BLOCKLEN */
|
||||
while (!issue_command(MMC_SET_BLOCKLEN, 512, 0, MMC_RSP_R1));
|
||||
|
||||
s3c_hsmmc_writew(0xffff, HM_NORINTSTS);
|
||||
|
||||
return sd_sectors;
|
||||
}
|
||||
|
||||
unsigned long s3c6410_mmc_bread(int dev_num, unsigned long start_blk, unsigned long blknum,
|
||||
void *dst)
|
||||
{
|
||||
u32 blksize; //j, , Addr_temp = start_blk;
|
||||
u32 dma = 0, cmd, multi; //, TotalReadByte, read_blk_cnt = 0;
|
||||
|
||||
HS_DMA_END = 0;
|
||||
|
||||
blksize = Card_OneBlockSize_ver1;
|
||||
|
||||
while (!check_card_status());
|
||||
|
||||
s3c_hsmmc_writew(s3c_hsmmc_readw(HM_NORINTSTSEN) & ~(DMA_STS_INT_EN | BLOCKGAP_EVENT_STS_INT_EN), HM_NORINTSTSEN);
|
||||
s3c_hsmmc_writew((HM_NORINTSIGEN & ~(0xffff)) | TRANSFERCOMPLETE_SIG_INT_EN, HM_NORINTSIGEN);
|
||||
|
||||
SetSystemAddressReg((unsigned long)dst); // AHB System Address For Write
|
||||
dma = 1;
|
||||
|
||||
set_blksize_register(7, 512); // Maximum DMA Buffer Size, Block Size
|
||||
set_blkcnt_register(blknum); // Block Numbers to Write
|
||||
|
||||
if (movi_hc)
|
||||
set_arg_register(start_blk); // Card Start Block Address to Write
|
||||
else
|
||||
set_arg_register(start_blk * 512); // Card Start Block Address to Write
|
||||
|
||||
cmd = (blknum > 1) ? 18 : 17;
|
||||
multi = (blknum > 1);
|
||||
|
||||
set_transfer_mode_register(multi, 1, multi, 1, dma);
|
||||
set_cmd_register(cmd, 1, MMC_RSP_R1);
|
||||
|
||||
if (wait_for_cmd_done()) {
|
||||
puts("Command NOT Complete\n");
|
||||
return -1;
|
||||
} else
|
||||
ClearCommandCompleteStatus();
|
||||
|
||||
|
||||
check_dma_int();
|
||||
while (!HS_DMA_END);
|
||||
|
||||
HS_DMA_END = 0;
|
||||
|
||||
return blknum;
|
||||
}
|
40
qiboot/src/cpu/s3c6410/hs_mmc.h
Normal file
40
qiboot/src/cpu/s3c6410/hs_mmc.h
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef __HS_MMC_H__
|
||||
#define __HS_MMC_H__
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//#define SDHC_MONITOR (*(volatile unsigned *)0x4800004c)
|
||||
//#define SDHC_SLOT_INT_STAT (*(volatile unsigned *)0x480000fc)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define SD_HCLK 1
|
||||
#define SD_EPLL 2
|
||||
#define SD_EXTCLK 3
|
||||
|
||||
#define NORMAL 0
|
||||
#define HIGH 1
|
||||
|
||||
//Normal Interrupt Signal Enable
|
||||
#define READWAIT_SIG_INT_EN (1<<10)
|
||||
#define CARD_SIG_INT_EN (1<<8)
|
||||
#define CARD_REMOVAL_SIG_INT_EN (1<<7)
|
||||
#define CARD_INSERT_SIG_INT_EN (1<<6)
|
||||
#define BUFFER_READREADY_SIG_INT_EN (1<<5)
|
||||
#define BUFFER_WRITEREADY_SIG_INT_EN (1<<4)
|
||||
#define DMA_SIG_INT_EN (1<<3)
|
||||
#define BLOCKGAP_EVENT_SIG_INT_EN (1<<2)
|
||||
#define TRANSFERCOMPLETE_SIG_INT_EN (1<<1)
|
||||
#define COMMANDCOMPLETE_SIG_INT_EN (1<<0)
|
||||
|
||||
//Normal Interrupt Status Enable
|
||||
#define READWAIT_STS_INT_EN (1<<10)
|
||||
#define CARD_STS_INT_EN (1<<8)
|
||||
#define CARD_REMOVAL_STS_INT_EN (1<<7)
|
||||
#define CARD_INSERT_STS_INT_EN (1<<6)
|
||||
#define BUFFER_READREADY_STS_INT_EN (1<<5)
|
||||
#define BUFFER_WRITEREADY_STS_INT_EN (1<<4)
|
||||
#define DMA_STS_INT_EN (1<<3)
|
||||
#define BLOCKGAP_EVENT_STS_INT_EN (1<<2)
|
||||
#define TRANSFERCOMPLETE_STS_INT_EN (1<<1)
|
||||
#define COMMANDCOMPLETE_STS_INT_EN (1<<0)
|
||||
|
||||
#endif /*__HS_MMC_H__*/
|
69
qiboot/src/cpu/s3c6410/i2c-bitbang-s3c6410.c
Normal file
69
qiboot/src/cpu/s3c6410/i2c-bitbang-s3c6410.c
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
* Author: Andy Green <andy@openmoko.com>
|
||||
*
|
||||
* s3c6410-specific i2c
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <qi.h>
|
||||
#include <i2c-bitbang.h>
|
||||
#include <s3c6410.h>
|
||||
|
||||
static char i2c_read_sda_s3c6410(void)
|
||||
{
|
||||
return !!(__REG(GPBDAT) & (1 << 6));
|
||||
}
|
||||
|
||||
static void i2c_set_s3c6410(char clock, char data)
|
||||
{
|
||||
if (clock) /* SCL <- input */
|
||||
__REG(GPBCON) = (__REG(GPBCON) & ~(3 << (5 * 4)));
|
||||
else { /* SCL <- output 0 */
|
||||
__REG(GPBDAT) = (__REG(GPBDAT) & ~(1 << 5));
|
||||
__REG(GPBCON) = (__REG(GPBCON) & ~(3 << (5 * 4))) | (1 << (5 * 4));
|
||||
}
|
||||
if (data) /* SDA <- input */
|
||||
__REG(GPBCON) = (__REG(GPBCON) & ~(3 << (6 * 4)));
|
||||
else { /* SDA <- output 0 */
|
||||
__REG(GPBDAT) = (__REG(GPBDAT) & ~(1 << 6));
|
||||
__REG(GPBCON) = (__REG(GPBCON) & ~(3 << (6 * 4))) | (1 << (6 * 4));
|
||||
}
|
||||
}
|
||||
|
||||
static void i2c_close_s3c6410(void)
|
||||
{
|
||||
/* set back to hardware I2C ready for Linux */
|
||||
__REG(GPBCON) = (__REG(GPBCON) & ~(3 << (5 * 4))) | (2 << (5 * 4));
|
||||
__REG(GPBCON) = (__REG(GPBCON) & ~(3 << (6 * 4))) | (2 << (6 * 4));
|
||||
}
|
||||
|
||||
static void i2c_spin_s3c6410(void)
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < 1000; n++)
|
||||
__REG(GPBDAT) = __REG(GPBDAT);
|
||||
}
|
||||
|
||||
struct i2c_bitbang bb_s3c6410 = {
|
||||
.read_sda = i2c_read_sda_s3c6410,
|
||||
.set = i2c_set_s3c6410,
|
||||
.spin = i2c_spin_s3c6410,
|
||||
.close = i2c_close_s3c6410,
|
||||
};
|
114
qiboot/src/cpu/s3c6410/om_3d7k-steppingstone.c
Normal file
114
qiboot/src/cpu/s3c6410/om_3d7k-steppingstone.c
Normal file
@ -0,0 +1,114 @@
|
||||
#include <qi.h>
|
||||
#include <neo_om_3d7k.h>
|
||||
#include <s3c6410.h>
|
||||
#include <serial-s3c64xx.h>
|
||||
|
||||
#define OM_3D7K_DEBUG_UART 3
|
||||
|
||||
/* out of steppingstone */
|
||||
extern const struct board_variant const * get_board_variant_om_3d7k(void);
|
||||
extern void port_init_om_3d7k(void);
|
||||
|
||||
|
||||
int is_this_board_om_3d7k(void)
|
||||
{
|
||||
/* FIXME: find something om_3d7k specific */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void putc_om_3d7k(char c)
|
||||
{
|
||||
serial_putc_s3c64xx(OM_3D7K_DEBUG_UART, c);
|
||||
}
|
||||
|
||||
int sd_card_init_om_3d7k(void)
|
||||
{
|
||||
extern int s3c6410_mmc_init(int verbose);
|
||||
|
||||
return s3c6410_mmc_init(1);
|
||||
}
|
||||
|
||||
int sd_card_block_read_om_3d7k(unsigned char * buf, unsigned long start512,
|
||||
int blocks512)
|
||||
{
|
||||
unsigned long s3c6410_mmc_bread(int dev_num, unsigned long blknr, unsigned long blkcnt,
|
||||
void *dst);
|
||||
|
||||
return s3c6410_mmc_bread(0, start512, blocks512, buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* our API for bootloader on this machine
|
||||
*/
|
||||
|
||||
/* for initrd:
|
||||
* .initramfs_filepath = "boot/initramfs.gz",
|
||||
* and
|
||||
* "root=/dev/ram ramdisk_size=6000000"
|
||||
*/
|
||||
|
||||
static u8 get_ui_keys_om_3d7k(void)
|
||||
{
|
||||
u8 keys;
|
||||
u8 ret;
|
||||
static u8 old_keys = 0; /* previous state for debounce */
|
||||
static u8 old_ret = 0; /* previous debounced output for edge detect */
|
||||
|
||||
/* GPN1 is MINUS on OM_3D7K, map to UI_ACTION_ADD_DEBUG, down = 1 */
|
||||
keys = !!(__REG(GPMDAT) & (1 << 1));
|
||||
|
||||
if (keys == old_keys)
|
||||
ret = keys;
|
||||
else
|
||||
ret = old_keys;
|
||||
|
||||
/* edge action */
|
||||
if ((ret & 1) && !(old_ret & 1))
|
||||
ret |= UI_ACTION_SKIPKERNEL;
|
||||
|
||||
old_keys = keys;
|
||||
old_ret = ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const struct board_api board_api_om_3d7k = {
|
||||
.name = "OM_3D7K",
|
||||
.linux_machine_id = 2120,
|
||||
.linux_mem_start = 0x50000000,
|
||||
.linux_mem_size = (128 * 1024 * 1024),
|
||||
.linux_tag_placement = 0x50000000 + 0x100,
|
||||
.get_board_variant = get_board_variant_om_3d7k,
|
||||
.is_this_board = is_this_board_om_3d7k,
|
||||
.port_init = port_init_om_3d7k,
|
||||
.putc = putc_om_3d7k,
|
||||
.noboot = "boot/noboot-OM_3D7K",
|
||||
.append = "boot/append-OM_3D7K",
|
||||
.get_ui_keys = get_ui_keys_om_3d7k,
|
||||
.commandline_board = "console=tty0 "
|
||||
"console=ttySAC3,115200 "
|
||||
"init=/sbin/init "
|
||||
"loglevel=8 "
|
||||
"rootdelay=1 no_console_suspend "
|
||||
"ro ",
|
||||
.commandline_board_debug = " loglevel=8",
|
||||
.kernel_source = {
|
||||
[0] = {
|
||||
.name = "SD Card rootfs",
|
||||
.block_read = sd_card_block_read_om_3d7k,
|
||||
.filesystem = FS_EXT2,
|
||||
.partition_index = 2,
|
||||
.filepath = "boot/uImage-OM_3D7K.bin",
|
||||
.commandline_append = "root=/dev/mmcblk0p2 ",
|
||||
},
|
||||
[1] = {
|
||||
.name = "SD Card backup rootfs",
|
||||
.block_read = sd_card_block_read_om_3d7k,
|
||||
.filesystem = FS_EXT2,
|
||||
.partition_index = 3,
|
||||
.filepath = "boot/uImage-OM_3D7K.bin",
|
||||
.commandline_append = "root=/dev/mmcblk0p3 ",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
935
qiboot/src/cpu/s3c6410/om_3d7k.c
Normal file
935
qiboot/src/cpu/s3c6410/om_3d7k.c
Normal file
@ -0,0 +1,935 @@
|
||||
#include <qi.h>
|
||||
#include <neo_om_3d7k.h>
|
||||
#include <s3c6410.h>
|
||||
#include <serial-s3c64xx.h>
|
||||
#include <i2c-bitbang-s3c6410.h>
|
||||
#include <pcf50633.h>
|
||||
|
||||
#define PCF50633_I2C_ADS 0x73
|
||||
|
||||
const struct pcf50633_init om_3d7k_pcf50633_init[] = {
|
||||
|
||||
{ PCF50633_REG_OOCWAKE, 0xd3 }, /* wake from ONKEY,EXTON!,RTC,USB,ADP */
|
||||
{ PCF50633_REG_OOCTIM1, 0xaa }, /* debounce 14ms everything */
|
||||
{ PCF50633_REG_OOCTIM2, 0x4a },
|
||||
{ PCF50633_REG_OOCMODE, 0x55 },
|
||||
{ PCF50633_REG_OOCCTL, 0x47 },
|
||||
|
||||
{ PCF50633_REG_SVMCTL, 0x08 }, /* 3.10V SYS voltage thresh. */
|
||||
{ PCF50633_REG_BVMCTL, 0x02 }, /* 2.80V BAT voltage thresh. */
|
||||
|
||||
{ PCF50633_REG_AUTOENA, 0x01 }, /* always on */
|
||||
|
||||
{ PCF50633_REG_DOWN1OUT, 0x17 }, /* 1.2V (0x17 * .025V + 0.625V) */
|
||||
|
||||
/* all of these are down in 3d7k suspend except MEMLDO */
|
||||
|
||||
{ PCF50633_REG_DOWN1ENA, 0x02 }, /* enabled if GPIO1 = HIGH */
|
||||
{ PCF50633_REG_DOWN2ENA, 0x02 }, /* enabled if GPIO1 = HIGH */
|
||||
{ PCF50633_REG_HCLDOENA, 0x00 }, /* Camera 2.8V power off */
|
||||
{ PCF50633_REG_MEMLDOENA, 0x01 }, /* Memory LDO always ON */
|
||||
{ PCF50633_REG_LDO1ENA, 0x00 }, /* Gsensor power off */
|
||||
{ PCF50633_REG_LDO2ENA, 0x00 }, /* Camera 1.5V power off */
|
||||
{ PCF50633_REG_LDO3ENA, 0x02 }, /* Codec power ON */
|
||||
{ PCF50633_REG_LDO4ENA, 0x02 }, /* SD power ON */
|
||||
{ PCF50633_REG_LDO5ENA, 0x00 }, /* BT power off */
|
||||
{ PCF50633_REG_LDO6ENA, 0x00 }, /* LCM power off */
|
||||
|
||||
{ PCF50633_REG_INT1M, 0x00 },
|
||||
{ PCF50633_REG_INT2M, 0x00 },
|
||||
{ PCF50633_REG_INT3M, 0x00 },
|
||||
{ PCF50633_REG_INT4M, 0x00 },
|
||||
{ PCF50633_REG_INT5M, 0x00 },
|
||||
|
||||
{ PCF50633_REG_MBCC2, 0x28 }, /* Vbatconid=2.7V, Vmax=4.20V */
|
||||
{ PCF50633_REG_MBCC3, 0x19 }, /* 25/255 == 98mA pre-charge */
|
||||
{ PCF50633_REG_MBCC4, 0xff }, /* 255/255 == 1A adapter fast */
|
||||
{ PCF50633_REG_MBCC5, 0xff }, /* 255/255 == 1A USB fast */
|
||||
|
||||
{ PCF50633_REG_MBCC6, 0x00 }, /* cutoff current 1/32 * Ichg */
|
||||
|
||||
/* current prototype is pulling > 100mA at startup */
|
||||
{ PCF50633_REG_MBCC7, 0xc1 }, /* 2.2A max bat curr, USB 500mA */
|
||||
|
||||
{ PCF50633_REG_MBCC8, 0x00 },
|
||||
{ PCF50633_REG_MBCC1, 0xff }, /* chgena */
|
||||
|
||||
{ PCF50633_REG_BBCCTL, 0x19 }, /* 3V, 200uA, on */
|
||||
{ PCF50633_REG_OOCSHDWN, 0x04 }, /* defeat 8s death from lowsys on A5 */
|
||||
|
||||
};
|
||||
|
||||
static const struct board_variant board_variants[] = {
|
||||
[0] = {
|
||||
.name = "OM 3D7K unknown",
|
||||
.machine_revision = 0
|
||||
},
|
||||
[1] = {
|
||||
.name = "OM 3D7K A1",
|
||||
.machine_revision = 1
|
||||
},
|
||||
[2] = {
|
||||
.name = "OM 3D7K A2",
|
||||
.machine_revision = 2
|
||||
},
|
||||
[3] = {
|
||||
.name = "OM 3D7K A3",
|
||||
.machine_revision = 3
|
||||
},
|
||||
[4] = {
|
||||
.name = "OM 3D7K A4",
|
||||
.machine_revision = 4
|
||||
},
|
||||
[5] = {
|
||||
.name = "OM 3D7K A5",
|
||||
.machine_revision = 5
|
||||
},
|
||||
[6] = {
|
||||
.name = "OM 3D7K A6",
|
||||
.machine_revision = 6
|
||||
},
|
||||
[7] = {
|
||||
.name = "OM 3D7K A7",
|
||||
.machine_revision = 7
|
||||
}
|
||||
};
|
||||
|
||||
#define S0 0
|
||||
#define S1 1
|
||||
#define SIN 2
|
||||
#define SHOLD 3
|
||||
|
||||
#define SNP 0
|
||||
#define SPD 1
|
||||
#define SPU 2
|
||||
|
||||
void port_init_om_3d7k(void)
|
||||
{
|
||||
int n;
|
||||
|
||||
/*
|
||||
* We leave iROM up for clock and power otherwise resume fails
|
||||
*/
|
||||
|
||||
__REG(EINT_MASK) =
|
||||
(0 << 4) /* PMU interrupt */
|
||||
;
|
||||
|
||||
__REG(PWR_CFG) =
|
||||
(1 << 17) | /* kill OSCotg clock pad */
|
||||
(0 << 0) /* 27MHz osc off */
|
||||
;
|
||||
|
||||
__REG(STOP_MEM_CFG) =
|
||||
(0 << 6) | /* modem */
|
||||
(0 << 5) | /* host IF */
|
||||
(1 << 4) | /* OTG */
|
||||
(1 << 3) | /* HSMMC */
|
||||
(1 << 2) | /* iROM */
|
||||
(0 << 1) | /* IRDA */
|
||||
(1 << 0) /* NFCON / steppingstone */
|
||||
;
|
||||
|
||||
__REG(NOR_CFG) =
|
||||
(1 << 31) | /* reserved */
|
||||
(1 << 30) | /* iROM */
|
||||
(0x1fff << 17) | /* reserved */
|
||||
(1 << 16) | /* ETM domain */
|
||||
(1 << 15) | /* S domain */
|
||||
(1 << 14) | /* F domain / LCD */
|
||||
(0 << 13) | /* P domain / 2D, scaler, TV encoder */
|
||||
(0 << 12) | /* I domain / JPEG / Camera */
|
||||
(1 << 11) | /* reserved */
|
||||
(0 << 10) | /* G domain / 3D */
|
||||
(0 << 9) | /* V domain / MFC */
|
||||
(1 << 8) | /* reserved */
|
||||
(0x00 << 0) /* reserved */
|
||||
;
|
||||
|
||||
|
||||
__REG(HCLK_GATE) =
|
||||
(0 << 31) | /* 3D unit */
|
||||
(1 << 30) | /* reserved */
|
||||
(0 << 29) | /* USB host */
|
||||
(0 << 28) | /* "security subsystem" */
|
||||
(0 << 27) | /* SDMA1 */
|
||||
(0 << 26) | /* SDMA0 */
|
||||
(1 << 25) | /* iROM */
|
||||
(1 << 24) | /* DDR 1 */
|
||||
(1 << 23) | /* reserved */
|
||||
(1 << 22) | /* DMC1 */
|
||||
(1 << 21) | /* SROM / NAND controller / NAND */
|
||||
(0 << 20) | /* USB OTG */
|
||||
(0 << 19) | /* HSMMC 2 */
|
||||
(0 << 18) | /* HSMMC 1 */
|
||||
(1 << 17) | /* HSMMC 0 */
|
||||
(0 << 16) | /* MDP */
|
||||
(0 << 15) | /* direct host */
|
||||
(0 << 14) | /* indirect host */
|
||||
(1 << 13) | /* DMA1 */
|
||||
(1 << 12) | /* DMA0 */
|
||||
(0 << 11) | /* JPEG */
|
||||
(0 << 10) | /* camera */
|
||||
(0 << 9) | /* scaler */
|
||||
(0 << 8) | /* 2D */
|
||||
(0 << 7) | /* TV */
|
||||
(1 << 6) | /* reserved */
|
||||
(1 << 5) | /* POST0 */
|
||||
(1 << 4) | /* rotator */
|
||||
(1 << 3) | /* LCD controller */
|
||||
(1 << 2) | /* TZICs */
|
||||
(1 << 1) | /* VICs */
|
||||
(0 << 0) /* MFC */
|
||||
;
|
||||
__REG(PCLK_GATE) =
|
||||
(0x1f << 28) | /* reserved */
|
||||
(0 << 27) | /* I2C1 */
|
||||
(0 << 26) | /* IIS2 */
|
||||
(1 << 25) | /* reserved */
|
||||
(0 << 24) | /* security key */
|
||||
(1 << 23) | /* chip ID */
|
||||
(0 << 22) | /* SPI1 */
|
||||
(0 << 21) | /* SPI0 */
|
||||
(0 << 20) | /* HSI RX */
|
||||
(0 << 19) | /* HSI TX */
|
||||
(1 << 18) | /* GPIO */
|
||||
(1 << 17) | /* I2C 0 */
|
||||
(1 << 16) | /* IIS1 */
|
||||
(1 << 15) | /* IIS0 */
|
||||
(0 << 14) | /* AC97 */
|
||||
(0 << 13) | /* TZPC */
|
||||
(0 << 12) | /* TS ADC */
|
||||
(0 << 11) | /* keypad */
|
||||
(0 << 10) | /* IRDA */
|
||||
(0 << 9) | /* PCM1 */
|
||||
(0 << 8) | /* PCM0 */
|
||||
(1 << 7) | /* PWM */
|
||||
(0 << 6) | /* RTC */
|
||||
(1 << 5) | /* WDC */
|
||||
(1 << 4) | /* UART3 */
|
||||
(1 << 3) | /* UART2 */
|
||||
(1 << 2) | /* UART1 */
|
||||
(1 << 1) | /* UART0 */
|
||||
(0 << 0) /* MFC */
|
||||
;
|
||||
|
||||
__REG(SCLK_GATE) =
|
||||
(1 << 31) |
|
||||
(0 << 30) | /* USB Host */
|
||||
(0 << 29) | /* HSMMC2 48MHz */
|
||||
(0 << 28) | /* HSMMC1 48MHz */
|
||||
(0 << 27) | /* HSMMC0 48MHz */
|
||||
(0 << 26) | /* HSMMC2 */
|
||||
(0 << 25) | /* HSMMC1 */
|
||||
(1 << 24) | /* HSMMC0 */
|
||||
(0 << 23) | /* SPI1 - 48MHz */
|
||||
(0 << 22) | /* SPI0 - 48MHz */
|
||||
(0 << 21) | /* SPI1 */
|
||||
(0 << 20) | /* SPI0 */
|
||||
(0 << 19) | /* TV DAC */
|
||||
(0 << 18) | /* TV encoder */
|
||||
(0 << 17) | /* scaler 27 */
|
||||
(0 << 16) | /* scaler */
|
||||
(1 << 15) | /* LCD 27MHz */
|
||||
(1 << 14) | /* LCD */
|
||||
(1 << 13) | /* camera and LCD */
|
||||
(1 << 12) | /* POST0 */
|
||||
(1 << 11) | /* AUDIO2 */
|
||||
(1 << 10) | /* POST0 again */
|
||||
(1 << 9) | /* IIS1 */
|
||||
(1 << 8) | /* IIS0 */
|
||||
(0 << 7) | /* security */
|
||||
(0 << 6) | /* IRDA */
|
||||
(1 << 5) | /* UART */
|
||||
(1 << 4) | /* reserved */
|
||||
(0 << 3) | /* MFC */
|
||||
(0 << 2) | /* Cam */
|
||||
(0 << 1) | /* JPEG */
|
||||
(1 << 0) /* reserved */
|
||||
;
|
||||
|
||||
|
||||
/* ---------------------------- Port A ---------------------------- */
|
||||
|
||||
__REG(GPACON) =
|
||||
(2 << 0) | /* GPA0 - UART_RXD0 */
|
||||
(2 << 4) | /* GPA1 - UART_TXD0 */
|
||||
(2 << 8) | /* GPA2 - UART_CTS0 */
|
||||
(2 << 12) | /* GPA3 - UART_RTS0 */
|
||||
(2 << 16) | /* GPA4 - UART_RXD1 */
|
||||
(2 << 20) | /* GPA5 - UART_TXD1 */
|
||||
(2 << 24) | /* GPA6 - UART_CTS1 */
|
||||
(2 << 28) /* GPA7 - UART_RTS1 */
|
||||
;
|
||||
|
||||
__REG(GPAPUD) = /* pullup inputs */
|
||||
0x2222
|
||||
;
|
||||
__REG(GPADAT) = 0; /* just for determinism */
|
||||
|
||||
__REG(GPACONSLP) =
|
||||
(SIN << 0) | /* GPA0 bluetooth down in suspend*/
|
||||
(S0 << 2) | /* GPA1 */
|
||||
(SIN << 4) | /* GPA2 */
|
||||
(S0 << 6) | /* GPA3 */
|
||||
(SIN << 8) | /* GPA4 gsm */
|
||||
(SHOLD << 10) | /* GPA5 */
|
||||
(SIN << 12) | /* GPA6 */
|
||||
(SHOLD << 14) /* GPA7 */
|
||||
;
|
||||
__REG(GPAPUDSLP) =
|
||||
(SPD << 0) | /* GPA0 */
|
||||
(SNP << 2) | /* GPA1 */
|
||||
(SPD << 4) | /* GPA2 */
|
||||
(SNP << 6) | /* GPA3 */
|
||||
(SPU << 8) | /* GPA4 */
|
||||
(SNP << 10) | /* GPA5 */
|
||||
(SPU << 12) | /* GPA6 */
|
||||
(SNP << 14) /* GPA7 */
|
||||
;
|
||||
|
||||
/* ---------------------------- Port B ---------------------------- */
|
||||
|
||||
__REG(GPBCON) =
|
||||
(1 << 0) | /* GPB0 - (NC) output low */
|
||||
(1 << 4) | /* GPB1 - (NC) output low */
|
||||
(2 << 8) | /* GPB2 - UART_RXD3 */
|
||||
(2 << 12) | /* GPB3 - UART_TXD3 */
|
||||
(1 << 16) | /* GPB4 - (NC) output low */
|
||||
(1 << 20) | /* GPB5 - (I2C BB SCL) OUTPUT */
|
||||
(1 << 24) /* GPB6 - (I2C BB SDA) OUTPUT */
|
||||
;
|
||||
|
||||
__REG(GPBPUD) = /* all pullup and pulldown disabled */
|
||||
(SPU << (2 * 2)) /* pullup console rx */
|
||||
;
|
||||
|
||||
__REG(GPBDAT) = 0; /* just for determinism */
|
||||
|
||||
__REG(GPBCONSLP) =
|
||||
(SHOLD << 0) | /* GPB0 */
|
||||
(SHOLD << 2) | /* GPB1 */
|
||||
(SIN << 4) | /* GPB2 */
|
||||
(SHOLD << 6) | /* GPB3 */
|
||||
(SHOLD << 8) | /* GPB4 */
|
||||
(SIN << 10) | /* GPB5 ext pullup */
|
||||
(SIN << 12) /* GPB6 ext pullup */
|
||||
;
|
||||
|
||||
__REG(GPBPUDSLP) =
|
||||
(SNP << 0) | /* GPB0 */
|
||||
(SNP << 2) | /* GPB1 */
|
||||
(SPU << 4) | /* GPB2 */
|
||||
(SNP << 6) | /* GPB3 */
|
||||
(SNP << 8) | /* GPB4 */
|
||||
(SNP << 10) | /* GPB5 */
|
||||
(SNP << 12) /* GPB6 */
|
||||
;
|
||||
|
||||
/* ---------------------------- Port C ---------------------------- */
|
||||
|
||||
__REG(GPCCON) =
|
||||
(0 << 0) | /* GPC0 - SPI_MISO0 INPUT motion sensor spi */
|
||||
(1 << 4) | /* GPC1 - SPI_CLK0 OUTPUT */
|
||||
(1 << 8) | /* GPC2 - SPI_MOSI0 OUTPUT */
|
||||
(1 << 12) | /* GPC3 - SPI_CS0 OUTPUT */
|
||||
(1 << 16) | /* GPC4 - (NC) OUTPUT lcm spi*/
|
||||
(1 << 20) | /* GPC5 - SPI_CLK1 OUTPUT */
|
||||
(1 << 24) | /* GPC6 - SPI_MOSI1 OUTPUT */
|
||||
(1 << 28) /* GPC7 - SPI_CS1 OUTPUT */
|
||||
;
|
||||
|
||||
__REG(GPCPUD) =
|
||||
(SPD << 0)
|
||||
;
|
||||
__REG(GPCDAT) = 0; /* just for determinism */
|
||||
|
||||
__REG(GPCCONSLP) = /* both peripherals down in suspend */
|
||||
(SIN << 0) | /* GPC0 */
|
||||
(S0 << 2) | /* GPC1 */
|
||||
(S0 << 4) | /* GPC2 */
|
||||
(S0 << 6) | /* GPC3 */
|
||||
(SIN << 8) | /* GPC4 */
|
||||
(S0 << 10) | /* GPC5 */
|
||||
(S0 << 12) | /* GPC6 */
|
||||
(S0 << 14) /* GPC7 */
|
||||
;
|
||||
|
||||
__REG(GPCPUDSLP) =
|
||||
(SPD << 0) | /* GPC0 */
|
||||
(SNP << 2) | /* GPC1 */
|
||||
(SNP << 4) | /* GPC2 */
|
||||
(SNP << 6) | /* GPC3 */
|
||||
(SPD << 8) | /* GPC4 */
|
||||
(SNP << 10) | /* GPC5 */
|
||||
(SNP << 12) | /* GPC6 */
|
||||
(SNP << 14) /* GPC7 */
|
||||
;
|
||||
|
||||
/* ---------------------------- Port D ---------------------------- */
|
||||
|
||||
__REG(GPDCON) =
|
||||
(3 << 0) | /* GPD0 - I2S_CLK0 */
|
||||
(3 << 4) | /* GPD1 - I2S_CDCLK0 */
|
||||
(3 << 8) | /* GPD2 - I2S_LRCLK0 */
|
||||
(3 << 12) | /* GPD3 - I2S_DI */
|
||||
(3 << 16) /* GPD4 - I2S_DO */
|
||||
;
|
||||
|
||||
__REG(GPDPUD) = 0; /* all pullup and pulldown disabled */
|
||||
|
||||
__REG(GPDDAT) = 0; /* just for determinism */
|
||||
|
||||
__REG(GPDCONSLP) =
|
||||
(S0 << 0) | /* GPD0 */
|
||||
(S0 << 2) | /* GPD1 */
|
||||
(S0 << 4) | /* GPD2 */
|
||||
(SIN << 6) | /* GPD3 */
|
||||
(S0 << 8) /* GPD4 */
|
||||
;
|
||||
|
||||
__REG(GPDPUDSLP) =
|
||||
(SNP << 0) | /* GPD0 */
|
||||
(SNP << 2) | /* GPD1 */
|
||||
(SNP << 4) | /* GPD2 */
|
||||
(SPD << 6) | /* GPD3 */
|
||||
(SNP << 8) /* GPD4 */
|
||||
;
|
||||
|
||||
/* ---------------------------- Port E ---------------------------- */
|
||||
|
||||
__REG(GPECON) =
|
||||
(3 << 0) | /* GPE0 - PCM_SCLK1 */
|
||||
(3 << 4) | /* GPE1 - PCM_EXTCLK1 */
|
||||
(3 << 8) | /* GPE2 - PCM_FSYNC1 */
|
||||
(3 << 12) | /* GPE3 - PCM_SIN */
|
||||
(3 << 16) /* GPE4 - PCM_SOUT */
|
||||
;
|
||||
|
||||
__REG(GPEPUD) = 0; /* all pullup and pulldown disabled */
|
||||
|
||||
__REG(GPEDAT) = 0; /* just for determinism */
|
||||
|
||||
__REG(GPECONSLP) =
|
||||
(S0 << 0) | /* GPE0 */
|
||||
(S0 << 2) | /* GPE1 */
|
||||
(S0 << 4) | /* GPE2 */
|
||||
(SIN << 6) | /* GPE3 */
|
||||
(S0 << 8) /* GPE4 */
|
||||
;
|
||||
|
||||
__REG(GPEPUDSLP) =
|
||||
(SNP << 0) | /* GPE0 */
|
||||
(SNP << 2) | /* GPE1 */
|
||||
(SNP << 4) | /* GPE2 */
|
||||
(SPD << 6) | /* GPE3 */
|
||||
(SNP << 8) /* GPE4 */
|
||||
;
|
||||
|
||||
/* ---------------------------- Port F ---------------------------- */
|
||||
|
||||
__REG(GPFCON) =
|
||||
(2 << 0) | /* GPF0 - CAMIF_CLK */
|
||||
(2 << 2) | /* GPF1 - CAMIF_HREF */
|
||||
(2 << 4) | /* GPF2 - CAMIF_PCLK */
|
||||
(2 << 6) | /* GPF3 - CAMIF_RSTn */
|
||||
(2 << 8) | /* GPF4 - CAMIF_VSYNC */
|
||||
(2 << 10) | /* GPF5 - CAMIF_YDATA0 */
|
||||
(2 << 12) | /* GPF6 - CAMIF_YDATA1 */
|
||||
(2 << 14) | /* GPF7 - CAMIF_YDATA2 */
|
||||
(2 << 16) | /* GPF8 - CAMIF_YDATA3 */
|
||||
(2 << 18) | /* GPF9 - CAMIF_YDATA4 */
|
||||
(2 << 20) | /* GPF10 - CAMIF_YDATA5 */
|
||||
(2 << 22) | /* GPF11 - CAMIF_YDATA6 */
|
||||
(2 << 24) | /* GPF12 - CAMIF_YDATA7 */
|
||||
(1 << 26) | /* GPF13 - OUTPUT Vibrator */
|
||||
(1 << 28) | /* GPF14 - output not CLKOUT0 */
|
||||
(1 << 30) /* GPF15 - OUTPUT CAM_PWRDN */
|
||||
;
|
||||
|
||||
__REG(GPFPUD) =
|
||||
(SPD << (2 * 12)) |
|
||||
(SPD << (2 * 11)) |
|
||||
(SPD << (2 * 10)) |
|
||||
(SPD << (2 * 9)) |
|
||||
(SPD << (2 * 8)) |
|
||||
(SPD << (2 * 7)) |
|
||||
(SPD << (2 * 6)) |
|
||||
(SPD << (2 * 5)); /* all cam data pulldown */
|
||||
|
||||
__REG(GPFDAT) = (1 << 15); /* assert CAM_PWRDN */
|
||||
|
||||
__REG(GPFCONSLP) =
|
||||
(S0 << 0) | /* GPF0 */
|
||||
(S0 << 2) | /* GPF1 */
|
||||
(SIN << 4) | /* GPF2 */
|
||||
(S0 << 6) | /* GPF3 */
|
||||
(S0 << 8) | /* GPF4 */
|
||||
(SIN << 10) | /* GPF5 */
|
||||
(SIN << 12) | /* GPF6 */
|
||||
(SIN << 14) | /* GPF7 */
|
||||
(SIN << 16) | /* GPF8 */
|
||||
(SIN << 18) | /* GPF9 */
|
||||
(SIN << 20) | /* GPF10 */
|
||||
(SIN << 22) | /* GPF11 */
|
||||
(SIN << 24) | /* GPF12 */
|
||||
(S0 << 26) | /* GPF13 */
|
||||
(S0 << 28) | /* GPF14 */
|
||||
(S0 << 30) /* GPF15 */
|
||||
;
|
||||
|
||||
__REG(GPFPUDSLP) =
|
||||
(SPD << 4) | /* GPF2 - pull down */
|
||||
(SPD << 10) | /* GPF5 - pull down */
|
||||
(SPD << 12) | /* GPF6 - pull down */
|
||||
(SPD << 14) | /* GPF7 - pull down */
|
||||
(SPD << 16) | /* GPF8 - pull down */
|
||||
(SPD << 18) | /* GPF9 - pull down */
|
||||
(SPD << 20) | /* GPF10 - pull down */
|
||||
(SPD << 22) | /* GPF11 - pull down */
|
||||
(SPD << 24) /* GPF12 - pull down */
|
||||
;
|
||||
|
||||
/* ---------------------------- Port G ---------------------------- */
|
||||
|
||||
__REG(GPGCON) =
|
||||
(2 << 0) | /* GPG0 - MMC_CLK0 */
|
||||
(2 << 4) | /* GPG1 - MMC_CMD0 */
|
||||
(2 << 8) | /* GPG2 - MMC_DATA00 */
|
||||
(2 << 12) | /* GPG3 - MMC_DATA10 */
|
||||
(2 << 16) | /* GPG4 - MMC_DATA20 */
|
||||
(2 << 20) | /* GPG5 - MMC_DATA30 */
|
||||
(2 << 24) /* GPG6 - (NC) MMC CARD DETECT */
|
||||
;
|
||||
|
||||
__REG(GPGPUD) = (1 << (6 * 2)); /* pull down card detect */
|
||||
|
||||
__REG(GPGDAT) = 0; /* just for determinism */
|
||||
|
||||
__REG(GPGCONSLP) =
|
||||
(SIN << 0) | /* GPG0 - it's not powered*/
|
||||
(SIN << 2) | /* GPG1 */
|
||||
(SIN << 4) | /* GPG2 */
|
||||
(SIN << 6) | /* GPG3 */
|
||||
(SIN << 8) | /* GPG4 */
|
||||
(SIN << 10) | /* GPG5 */
|
||||
(SIN << 12) /* GPG6 */
|
||||
;
|
||||
|
||||
__REG(GPGPUDSLP) =
|
||||
(SPD << 0) | /* GPG0 - it's not powered*/
|
||||
(SPD << 2) | /* GPG1 */
|
||||
(SPD << 4) | /* GPG2 */
|
||||
(SPD << 6) | /* GPG3 */
|
||||
(SPD << 8) | /* GPG4 */
|
||||
(SPD << 10) | /* GPG5 */
|
||||
(SPD << 12) /* GPG6 */
|
||||
;
|
||||
|
||||
/* ---------------------------- Port H ---------------------------- */
|
||||
|
||||
__REG(GPHCON0) =
|
||||
(1 << 0) | /* GPH0 - NC OUT 0 */
|
||||
(1 << 4) | /* GPH1 - NC OUT 0 */
|
||||
(1 << 8) | /* GPH2 - NC OUT 0 */
|
||||
(1 << 12) | /* GPH3 - NC OUT 0 */
|
||||
(1 << 16) | /* GPH4 - NC OUT 0 */
|
||||
(1 << 20) | /* GPH5 - NC OUT 0 */
|
||||
(1 << 24) | /* GPH6 - OUTPUT nBT_RESET */
|
||||
(0 << 28) /* GPH7 - INPUT HDQ */
|
||||
;
|
||||
__REG(GPHCON1) =
|
||||
(1 << 0) | /* GPH8 - OUTPUT BT PIO5 */
|
||||
(0 << 4) /* GPH9 - INPUT LED INT */
|
||||
;
|
||||
|
||||
__REG(GPHPUD) = (SPU << (9 * 2)) | (SPU << (7 * 2));
|
||||
|
||||
__REG(GPHDAT) = 0;
|
||||
|
||||
__REG(GPHCONSLP) =
|
||||
(S0 << 0) | /* GPH0 */
|
||||
(S0 << 2) | /* GPH1 */
|
||||
(S0 << 4) | /* GPH2 */
|
||||
(S0 << 6) | /* GPH3 */
|
||||
(S0 << 8) | /* GPH4 */
|
||||
(S0 << 10) | /* GPH5 */
|
||||
(S0 << 12) | /* GPH6 */
|
||||
(SIN << 14) | /* GPH7 - INPUT (HDQ) */
|
||||
(S0 << 16) | /* GPH8 */
|
||||
(SIN << 18) /* GPH9 */
|
||||
;
|
||||
|
||||
__REG(GPHPUDSLP) = (SPU << (7 * 2)) | (SPU << (9 * 2));
|
||||
|
||||
/* ---------------------------- Port I ---------------------------- */
|
||||
|
||||
__REG(GPICON) =
|
||||
(0 << 0) | /* GPI0 - INPUT version b0 */
|
||||
(0 << 2) | /* GPI1 - INPUT version b1 */
|
||||
(2 << 4) | /* GPI2 - LCD_VD2 */
|
||||
(2 << 6) | /* GPI3 - LCD_VD3 */
|
||||
(2 << 8) | /* GPI4 - LCD_VD4 */
|
||||
(2 << 10) | /* GPI5 - LCD_VD5 */
|
||||
(2 << 12) | /* GPI6 - LCD_VD6 */
|
||||
(2 << 14) | /* GPI7 - LCD_VD7 */
|
||||
(0 << 16) | /* GPI8 - INPUT version b2 */
|
||||
(2 << 18) | /* GPI9 - LCD_VD9 */
|
||||
(2 << 20) | /* GPI10 - LCD_VD10 */
|
||||
(2 << 22) | /* GPI11 - LCD_VD11 */
|
||||
(2 << 24) | /* GPI12 - LCD_VD12 */
|
||||
(2 << 26) | /* GPI13 - LCD_VD13 */
|
||||
(2 << 28) | /* GPI14 - LCD_VD14 */
|
||||
(2 << 30) /* GPI15 - LCD_VD15 */
|
||||
;
|
||||
|
||||
__REG(GPIPUD) = 0; /* all pullup and pulldown disabled */
|
||||
|
||||
__REG(GPIDAT) = 0; /* just for determinism */
|
||||
|
||||
__REG(GPICONSLP) =
|
||||
(SIN << 0) | /* GPI0 - input */
|
||||
(SIN << 2) | /* GPI1 - input */
|
||||
(S0 << 4) | /* GPI2 - input */
|
||||
(S0 << 6) | /* GPI3 - input */
|
||||
(S0 << 8) | /* GPI4 - input */
|
||||
(S0 << 10) | /* GPI5 - input */
|
||||
(S0 << 12) | /* GPI6 - input */
|
||||
(S0 << 14) | /* GPI7 - input */
|
||||
(SIN << 16) | /* GPI8 - input */
|
||||
(S0 << 18) | /* GPI9 - input */
|
||||
(S0 << 20) | /* GPI10 - input */
|
||||
(S0 << 22) | /* GPI11 - input */
|
||||
(S0 << 24) | /* GPI12 - input */
|
||||
(S0 << 26) | /* GPI13 - input */
|
||||
(S0 << 28) | /* GPI14 - input */
|
||||
(S0 << 30) /* GPI15 - input */
|
||||
;
|
||||
|
||||
__REG(GPIPUDSLP) =
|
||||
(1 << 0) | /* GPI0 - pull down */
|
||||
(1 << 2) | /* GPI1 - pull down */
|
||||
(1 << 16) /* GPI8 - pull down */
|
||||
;
|
||||
|
||||
/* ---------------------------- Port J ---------------------------- */
|
||||
|
||||
__REG(GPJCON) =
|
||||
(2 << 0) | /* GPJ0 - LCD_VD16 */
|
||||
(2 << 2) | /* GPJ1 - LCD_VD17 */
|
||||
(2 << 4) | /* GPJ2 - LCD_VD18 */
|
||||
(2 << 6) | /* GPJ3 - LCD_VD19 */
|
||||
(2 << 8) | /* GPJ4 - LCD_VD20 */
|
||||
(2 << 10) | /* GPJ5 - LCD_VD21 */
|
||||
(2 << 12) | /* GPJ6 - LCD_VD22 */
|
||||
(2 << 14) | /* GPJ7 - LCD_VD23 */
|
||||
(2 << 16) | /* GPJ8 - LCD_HSYNC */
|
||||
(2 << 18) | /* GPJ9 - LCD_VSYNC */
|
||||
(2 << 20) | /* GPJ10 - LCD_VDEN */
|
||||
(2 << 22) /* GPJ11 - LCD_VCLK */
|
||||
;
|
||||
|
||||
__REG(GPJPUD) = 0; /* all pullup and pulldown disabled */
|
||||
|
||||
__REG(GPJDAT) = 0; /* just for determinism */
|
||||
|
||||
__REG(GPJCONSLP) =
|
||||
(S0 << 0) | /* GPJ0 */
|
||||
(S0 << 2) | /* GPJ1 */
|
||||
(S0 << 4) | /* GPJ2 */
|
||||
(S0 << 6) | /* GPJ3 */
|
||||
(S0 << 8) | /* GPJ4 */
|
||||
(S0 << 10) | /* GPJ5 */
|
||||
(S0 << 12) | /* GPJ6 */
|
||||
(S0 << 14) | /* GPJ7 */
|
||||
(S0 << 16) | /* GPJ8 */
|
||||
(S0 << 18) | /* GPJ9 */
|
||||
(S0 << 20) | /* GPJ10 */
|
||||
(S0 << 22) /* GPJ11 */
|
||||
;
|
||||
|
||||
__REG(GPJPUDSLP) =
|
||||
0
|
||||
;
|
||||
|
||||
/* ---------------------------- Port K ---------------------------- */
|
||||
|
||||
__REG(GPKCON0) =
|
||||
(1 << 0) | /* GPK0 - OUTPUT NC */
|
||||
(1 << 4) | /* GPK1 - OUTPUT NC */
|
||||
(1 << 8) | /* GPK2 - OUTPUT (nMODEM_ON) */
|
||||
|
||||
(1 << 12) | /* GPK3 - OUTPUT (LED_TRIG) */
|
||||
(1 << 16) | /* GPK4 - OUTPUT (LED_EN) */
|
||||
(0 << 20) | /* GPK5 - OUTPUT NC */
|
||||
(1 << 24) | /* GPK6 - OUTPUT (LCD_RESET) */
|
||||
(0 << 28) /* GPK7 - OUTPUT NC */
|
||||
;
|
||||
__REG(GPKCON1) =
|
||||
(1 << 0) | /* GPK8 - OUTPUT NC */
|
||||
(1 << 4) | /* GPK9 - OUTPUT NC */
|
||||
(1 << 8) | /* GPK10 - OUTPUT NC */
|
||||
(1 << 12) | /* GPK11 - OUTPUT NC */
|
||||
(1 << 16) | /* GPK12 - OUTPUT NC */
|
||||
(1 << 20) | /* GPK13 - OUTPUT NC */
|
||||
(1 << 24) | /* GPK14 - OUTPUT NC */
|
||||
(1 << 28) /* GPK15 - OUTPUT NC */
|
||||
;
|
||||
|
||||
__REG(GPKPUD) = 0;
|
||||
|
||||
__REG(GPKDAT) = /* rest output 0 */
|
||||
(SHOLD << (2 * 2)) | /* nMODEM_ON */
|
||||
(SHOLD << (2 * 3)) | /* LED_TRIG */
|
||||
(SHOLD << (2 * 4)) | /* LED_EN */
|
||||
(S0 << (2 * 6)) /* LCD_RESET */
|
||||
;
|
||||
|
||||
/* ---------------------------- Port L ---------------------------- */
|
||||
|
||||
__REG(GPLCON0) =
|
||||
(1 << 0) | /* GPL0 - OUTPUT (NC) */
|
||||
(1 << 4) | /* GPL1 - OUTPUT (NC) */
|
||||
(1 << 8) | /* GPL2 - OUTPUT (NC) */
|
||||
(1 << 12) | /* GPL3 - OUTPUT (NC) */
|
||||
(1 << 16) | /* GPL4 - OUTPUT (NC) */
|
||||
(1 << 20) | /* GPL5 - OUTPUT (NC) */
|
||||
(1 << 24) | /* GPL6 - OUTPUT (NC) */
|
||||
(1 << 28) /* GPL7 - OUTPUT (NC) */
|
||||
;
|
||||
__REG(GPLCON1) =
|
||||
(1 << 0) | /* GPL8 - OUTPUT (NC) */
|
||||
(1 << 4) | /* GPL9 - OUTPUT (NC) */
|
||||
(1 << 8) | /* GPL10 - OUTPUT (NC) */
|
||||
(1 << 12) | /* GPL11 - OUTPUT (NC) */
|
||||
(1 << 16) | /* GPL12 - OUTPUT (NC) */
|
||||
(1 << 20) | /* GPL13 - OUTPUT (NC) */
|
||||
(1 << 24) /* GPL14 - OUTPUT (NC) */
|
||||
;
|
||||
|
||||
__REG(GPLPUD) = 0; /* all pullup and pulldown disabled */
|
||||
|
||||
__REG(GPLDAT) = 0;
|
||||
|
||||
|
||||
/* ---------------------------- Port M ---------------------------- */
|
||||
|
||||
__REG(GPMCON) =
|
||||
(1 << 0) | /* GPM0 - OUTPUT (TP_RESET) */
|
||||
(1 << 4) | /* GPM1 - OUTPUT (NC) */
|
||||
(1 << 8) | /* GPM2 - OUTPUT (NC) */
|
||||
(1 << 12) | /* GPM3 - OUTPUT (NC) */
|
||||
(0 << 16) | /* GPM4 - INPUT (nUSB_FLT) */
|
||||
(0 << 20) /* GPM5 - INPUT (nUSB_OC) */
|
||||
;
|
||||
|
||||
__REG(GPMPUD) = (2 << (4 * 2)) | (2 << (5 * 2)); /* Pup on inputs */
|
||||
|
||||
__REG(GPMDAT) = 0;
|
||||
|
||||
/* ---------------------------- Port N ---------------------------- */
|
||||
|
||||
__REG(GPNCON) =
|
||||
(2 << 0) | /* GPN0 - EXINT0 nG1INT1 */
|
||||
(2 << 2) | /* GPN1 - EXINT1 KEY_MINUS */
|
||||
(2 << 4) | /* GPN2 - EXINT2 KEY_PLUS */
|
||||
(2 << 6) | /* GPN3 - EXINT3 PWR_IND */
|
||||
(2 << 8) | /* GPN4 - EXINT4 PWR_IRQ */
|
||||
(2 << 10) | /* GPN5 - EXINT5 nTOUCH */
|
||||
(2 << 12) | /* GPN6 - EXINT6 nJACK_INSERT */
|
||||
(1 << 14) | /* GPN7 - EXINT7 NC OUTPUT */
|
||||
(2 << 16) | /* GPN8 - EXINT8 nHOLD */
|
||||
(2 << 18) | /* GPN9 - EXINT9 WLAN_WAKEUP */
|
||||
(2 << 20) | /* GPN10 - EXINT10 nG1INT2 */
|
||||
(2 << 22) | /* GPN11 - EXINT11 nIO1 */
|
||||
(2 << 24) | /* GPN12 - EXINT12 nONKEYWAKE */
|
||||
(0 << 26) | /* GPN13 - INPUT (iROM CFG0) */
|
||||
(0 << 28) | /* GPN14 - INPUT (iROM CFG1) */
|
||||
(0 << 30) /* GPN15 - INPUT (iROM CFG2) */
|
||||
;
|
||||
|
||||
__REG(GPNPUD) =
|
||||
(SPD << 0) | /* GPN0 - EXINT0 nG1INT1 */
|
||||
(SPU << 2) | /* GPN1 - EXINT1 KEY_MINUS */
|
||||
(SPU << 4) | /* GPN2 - EXINT2 KEY_PLUS */
|
||||
(SPU << 6) | /* GPN3 - EXINT3 PWR_IND */
|
||||
(SNP << 8) | /* GPN4 - EXINT4 PWR_IRQ */
|
||||
(SPU << 10) | /* GPN5 - EXINT5 nTOUCH */
|
||||
(SNP << 12) | /* GPN6 - EXINT6 nJACK_INSERT */
|
||||
(SNP << 14) | /* GPN7 - EXINT7 NC OP */
|
||||
(SPU << 16) | /* GPN8 - EXINT8 nHOLD */
|
||||
(SPU << 18) | /* GPN9 - EXINT9 BT_WAKEUP */
|
||||
(SPD << 20) | /* GPN10 - EXINT10 nG1INT2 */
|
||||
(SPD << 22) | /* GPN11 - EXINT11 nIO1 */
|
||||
(SPU << 24) | /* GPN12 - EXINT12 nONKEYWAKE */
|
||||
(SPD << 26) | /* GPN13 - INPUT (iROM CFG0) */
|
||||
(SPD << 28) | /* GPN14 - INPUT (iROM CFG1) */
|
||||
(SPD << 30) /* GPN15 - INPUT (iROM CFG2) */
|
||||
;
|
||||
|
||||
__REG(GPNDAT) = 0;
|
||||
|
||||
|
||||
/* ---------------------------- Port O ---------------------------- */
|
||||
|
||||
__REG(GPOCON) =
|
||||
(2 << 0) | /* GPO0 - XM0CS2 (nNANDCS0) */
|
||||
(1 << 2) | /* GPO1 - OUTPUT (nMODEM_RESET) */
|
||||
(1 << 4) | /* GPO2 - OUTPUT (NC) */
|
||||
(1 << 6) | /* GPO3 - OUTPUT (NC) */
|
||||
(1 << 8) | /* GPO4 - OUTPUT (NC) */
|
||||
(1 << 10) | /* GPO5 - OUTPUT (NC) */
|
||||
(1 << 12) | /* GPO6 - OUTPUT (NC) */
|
||||
(1 << 14) | /* GPO7 - OUTPUT (NC) */
|
||||
(1 << 16) | /* GPO8 - OUTPUT (NC) */
|
||||
(1 << 18) | /* GPO9 - OUTPUT (NC) */
|
||||
(1 << 20) | /* GPO10 - OUTPUT (NC) */
|
||||
(1 << 22) | /* GPO11 - OUTPUT (NC) */
|
||||
(1 << 24) | /* GPO12 - OUTPUT (NC) */
|
||||
(1 << 26) | /* GPO13 - OUTPUT (NC) */
|
||||
(1 << 28) | /* GPO14 - OUTPUT (NC) */
|
||||
(1 << 30) /* GPO15 - OUTPUT (NC) */
|
||||
;
|
||||
|
||||
__REG(GPOPUD) = 0; /* no pulling */
|
||||
|
||||
__REG(GPODAT) = (1 << 15); /* assert CAM_PWRDN */
|
||||
|
||||
__REG(GPOCONSLP) =
|
||||
(SHOLD << 0) | /* GPO0 - hold state */
|
||||
(SHOLD << 2) | /* GPO1 - OUTPUT 1 (do not reset modem) */
|
||||
(S0 << 4) | /* GPO2 - OUTPUT 0 */
|
||||
(S0 << 6) | /* GPO3 - OUTPUT 0 */
|
||||
(S0 << 8) | /* GPO4 - OUTPUT 0 */
|
||||
(S0 << 10) | /* GPO5 - OUTPUT 0 */
|
||||
(S0 << 12) | /* GPO6 - OUTPUT 0 */
|
||||
(S0 << 14) | /* GPO7 - OUTPUT 0 */
|
||||
(S0 << 16) | /* GPO8 - OUTPUT 0 */
|
||||
(S0 << 18) | /* GPO9 - OUTPUT 0 */
|
||||
(S0 << 20) | /* GPO10 - OUTPUT 0 */
|
||||
(S0 << 22) | /* GPO11 - OUTPUT 0 */
|
||||
(S0 << 24) | /* GPO12 - OUTPUT 0 */
|
||||
(S0 << 26) | /* GPO13 - OUTPUT 0 */
|
||||
(S0 << 28) | /* GPO14 - OUTPUT 0 */
|
||||
(S0 << 30) /* GPO15 - OUTPUT 0 */
|
||||
;
|
||||
|
||||
__REG(GPOPUDSLP) =
|
||||
0
|
||||
;
|
||||
|
||||
/* ---------------------------- Port P ---------------------------- */
|
||||
|
||||
__REG(GPPCON) =
|
||||
(1 << 0) | /* GPP0 - input (NC) */
|
||||
(1 << 2) | /* GPP1 - input (NC) */
|
||||
(1 << 4) | /* GPP2 - input (NC) */
|
||||
(1 << 6) | /* GPP3 - input (NC) */
|
||||
(1 << 8) | /* GPP4 - input (NC) */
|
||||
(1 << 10) | /* GPP5 - input (NC) */
|
||||
(1 << 12) | /* GPP6 - input (NC) */
|
||||
(1 << 14) | /* GPP7 - input (NC) */
|
||||
(1 << 16) | /* GPP8 - input (NC) */
|
||||
(1 << 18) | /* GPP9 - input (NC) */
|
||||
(1 << 20) | /* GPP10 - input (NC) */
|
||||
(1 << 22) | /* GPP11 - input (NC) */
|
||||
(1 << 24) | /* GPP12 - input (NC) */
|
||||
(1 << 26) | /* GPP13 - input (NC) */
|
||||
(1 << 28) /* GPP14 - input (NC) */
|
||||
;
|
||||
|
||||
__REG(GPPPUD) = 0; /* no pull */
|
||||
|
||||
__REG(GPPDAT) = 0;
|
||||
|
||||
__REG(GPPCONSLP) =
|
||||
(S0 << 0) | /* GPP0 - OUTPUT 0 */
|
||||
(S0 << 2) | /* GPP1 - OUTPUT 0 */
|
||||
(S0 << 4) | /* GPP2 - OUTPUT 0 */
|
||||
(S0 << 6) | /* GPP3 - OUTPUT 0 */
|
||||
(S0 << 8) | /* GPP4 - OUTPUT 0 */
|
||||
(S0 << 10) | /* GPP5 - OUTPUT 0 */
|
||||
(S0 << 12) | /* GPP6 - OUTPUT 0 */
|
||||
(S0 << 14) | /* GPP7 - OUTPUT 0 */
|
||||
(S0 << 16) | /* GPP8 - OUTPUT 0 */
|
||||
(S0 << 18) | /* GPP9 - OUTPUT 0 */
|
||||
(S0 << 20) | /* GPP10 - OUTPUT 0 */
|
||||
(S0 << 22) | /* GPP11 - OUTPUT 0 */
|
||||
(S0 << 24) | /* GPP12 - OUTPUT 0 */
|
||||
(S0 << 26) | /* GPP13 - OUTPUT 0 */
|
||||
(S0 << 28) /* GPP14 - OUTPUT 0 */
|
||||
;
|
||||
|
||||
__REG(GPPPUDSLP) = 0;
|
||||
|
||||
/* ---------------------------- Port Q ---------------------------- */
|
||||
|
||||
__REG(GPQCON) =
|
||||
(1 << 0) | /* GPQ0 - OUTPUT (NC) */
|
||||
(1 << 2) | /* GPQ1 - OUTPUT (NC) */
|
||||
(1 << 4) | /* GPQ2 - OUTPUT (NC) */
|
||||
(1 << 6) | /* GPQ3 - OUTPUT (NC) */
|
||||
(1 << 8) | /* GPQ4 - OUTPUT (NC) */
|
||||
(1 << 10) | /* GPQ5 - OUTPUT (NC) */
|
||||
(1 << 12) | /* GPQ6 - OUTPUT (NC) */
|
||||
(1 << 14) | /* GPQ7 - OUTPUT (NC) */
|
||||
(1 << 16) /* GPQ8 - OUTPUT (NC) */
|
||||
;
|
||||
|
||||
__REG(GPQPUD) = 0; /* no pull */
|
||||
|
||||
__REG(GPQDAT) = 0;
|
||||
|
||||
__REG(GPQCONSLP) =
|
||||
(S0 << 0) | /* GPQ0 - OUTPUT 0 */
|
||||
(S0 << 2) | /* GPQ1 - OUTPUT 0 */
|
||||
(S0 << 4) | /* GPQ2 - OUTPUT 0 */
|
||||
(S0 << 6) | /* GPQ3 - OUTPUT 0 */
|
||||
(S0 << 8) | /* GPQ4 - OUTPUT 0 */
|
||||
(S0 << 10) | /* GPQ5 - OUTPUT 0 */
|
||||
(S0 << 12) | /* GPQ6 - OUTPUT 0 */
|
||||
(S0 << 14) | /* GPQ7 - OUTPUT 0 */
|
||||
(S0 << 16) /* GPQ8 - OUTPUT 0 */
|
||||
;
|
||||
|
||||
__REG(GPQPUDSLP) = 0;
|
||||
|
||||
/* LCD Controller enable */
|
||||
|
||||
__REG(0x7410800c) = 0;
|
||||
__REG(0x7f0081a0) = 0xbfc115c1;
|
||||
|
||||
/*
|
||||
* We have to talk to the PMU a little bit
|
||||
*/
|
||||
for (n = 0; n < ARRAY_SIZE(om_3d7k_pcf50633_init); n++)
|
||||
i2c_write_sync(&bb_s3c6410, PCF50633_I2C_ADS,
|
||||
om_3d7k_pcf50633_init[n].index,
|
||||
om_3d7k_pcf50633_init[n].value);
|
||||
|
||||
}
|
||||
|
||||
int om_3d7k_get_pcb_revision(void)
|
||||
{
|
||||
u32 v = __REG(GPIDAT);
|
||||
/*
|
||||
* PCB rev is 3 bit code (info from Dkay)
|
||||
* (b2, b1, b0) = (0,0,1) => pcb rev A1
|
||||
* maximum rev = A7
|
||||
* bit0 = GPI8
|
||||
* bit1 = GPI1
|
||||
* bit2 = GPI0
|
||||
*/
|
||||
|
||||
return (
|
||||
((v & (1 << 8)) ? 1 : 0) |
|
||||
((v & (1 << 1)) ? 2 : 0) |
|
||||
((v & (1 << 0)) ? 4 : 0)
|
||||
);
|
||||
}
|
||||
|
||||
const struct board_variant const * get_board_variant_om_3d7k(void)
|
||||
{
|
||||
return &board_variants[om_3d7k_get_pcb_revision()];
|
||||
}
|
||||
|
75
qiboot/src/cpu/s3c6410/qi.lds
Normal file
75
qiboot/src/cpu/s3c6410/qi.lds
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* (C) Copyright 2002
|
||||
* Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
|
||||
/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
|
||||
OUTPUT_ARCH(arm)
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x00000000;
|
||||
|
||||
__system_ram_start = 0x50000000;
|
||||
__steppingstone = 0x0c000000;
|
||||
|
||||
/* this text section is magically pulled from the SD Card
|
||||
* and stored by the iRom at 0x0c000000, then it is jumped into
|
||||
* by the iRom. So we arrange our early parts needed at 0 in the
|
||||
* output file, but set to run at 0x0c000000+
|
||||
*/
|
||||
|
||||
.text
|
||||
__steppingstone :
|
||||
AT (0)
|
||||
{
|
||||
src/cpu/s3c6410/start.o (.text .rodata* .data .bss)
|
||||
src/cpu/s3c6410/start_qi.o (.text .rodata* .data .bss)
|
||||
src/cpu/s3c6410/serial-s3c64xx.o (.text .rodata* .data .bss)
|
||||
src/cpu/s3c6410/om_3d7k-steppingstone.o (.text .rodata* .data .bss)
|
||||
src/cpu/s3c6410/smdk6410-steppingstone.o (.text .rodata* .data .bss)
|
||||
src/cpu/s3c6410/hs_mmc.o (.text .rodata* .data .bss)
|
||||
src/utils.o (.text .rodata* .data .bss)
|
||||
src/memory-test.o (.text .rodata* .data .bss)
|
||||
/* src/ctype.o (.text .rodata* .data .bss) */
|
||||
* (.steppingstone)
|
||||
}
|
||||
|
||||
. = ALIGN(4);
|
||||
.everything_else
|
||||
__system_ram_start + 0x3000000 + SIZEOF(.text) :
|
||||
AT (SIZEOF(.text))
|
||||
{
|
||||
*(.text .rodata* .data)
|
||||
}
|
||||
|
||||
|
||||
__bss_start = __system_ram_start + 0x03800000;
|
||||
.bss_6410
|
||||
__bss_start (NOLOAD) :
|
||||
AT (SIZEOF(.text) + SIZEOF(.everything_else))
|
||||
{
|
||||
* (.bss)
|
||||
}
|
||||
|
||||
_end = .;
|
||||
}
|
38
qiboot/src/cpu/s3c6410/serial-s3c64xx.c
Normal file
38
qiboot/src/cpu/s3c6410/serial-s3c64xx.c
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
* Author: Andy Green <andy@openmoko.com>
|
||||
*
|
||||
* Configuation settings for the FIC Neo GTA02 Linux GSM phone
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <qi.h>
|
||||
#include <s3c6410.h>
|
||||
|
||||
/*
|
||||
* Output a single byte to the serial port.
|
||||
*/
|
||||
void serial_putc_s3c64xx(const int uart, const char c)
|
||||
{
|
||||
if (uart >= 4)
|
||||
return;
|
||||
|
||||
while (!(__REG(0x7F005000 + UTRSTAT_OFFSET + (uart << 10)) & 0x2))
|
||||
;
|
||||
|
||||
__REG(0x7F005000 + UTXH_OFFSET + (uart << 10)) = c;
|
||||
}
|
73
qiboot/src/cpu/s3c6410/smdk6410-steppingstone.c
Normal file
73
qiboot/src/cpu/s3c6410/smdk6410-steppingstone.c
Normal file
@ -0,0 +1,73 @@
|
||||
#include <qi.h>
|
||||
#include <neo_smdk6410.h>
|
||||
#include <serial-s3c64xx.h>
|
||||
|
||||
#define SMDK6410_DEBUG_UART 0
|
||||
|
||||
extern const struct board_variant const * get_board_variant_smdk6410(void);
|
||||
|
||||
int is_this_board_smdk6410(void)
|
||||
{
|
||||
/* FIXME: find something smdk6410 specific */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void putc_smdk6410(char c)
|
||||
{
|
||||
serial_putc_s3c64xx(SMDK6410_DEBUG_UART, c);
|
||||
}
|
||||
|
||||
int sd_card_init_smdk6410(void)
|
||||
{
|
||||
extern int s3c6410_mmc_init(int verbose);
|
||||
|
||||
return s3c6410_mmc_init(1);
|
||||
}
|
||||
|
||||
int sd_card_block_read_smdk6410(unsigned char * buf, unsigned long start512,
|
||||
int blocks512)
|
||||
{
|
||||
unsigned long s3c6410_mmc_bread(int dev_num, unsigned long blknr,
|
||||
unsigned long blkcnt, void *dst);
|
||||
|
||||
return s3c6410_mmc_bread(0, start512, blocks512, buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* our API for bootloader on this machine
|
||||
*/
|
||||
const struct board_api board_api_smdk6410 = {
|
||||
.name = "SMDK6410",
|
||||
.linux_machine_id = 1866 /* 1626 */,
|
||||
.linux_mem_start = 0x50000000,
|
||||
.linux_mem_size = (128 * 1024 * 1024),
|
||||
.linux_tag_placement = 0x50000000 + 0x100,
|
||||
.get_board_variant = get_board_variant_smdk6410,
|
||||
.is_this_board = is_this_board_smdk6410,
|
||||
.putc = putc_smdk6410,
|
||||
.commandline_board = "console=ttySAC0,115200 "
|
||||
"loglevel=3 "
|
||||
"init=/bin/sh ",
|
||||
.commandline_board_debug = " loglevel=8",
|
||||
.noboot = "boot/noboot-SDMK6410",
|
||||
.append = "boot/append-SMDK6410",
|
||||
.kernel_source = {
|
||||
[0] = {
|
||||
.name = "SD Card rootfs",
|
||||
.block_read = sd_card_block_read_smdk6410,
|
||||
.filesystem = FS_EXT2,
|
||||
.partition_index = 2,
|
||||
.filepath = "boot/uImage-SMDK6410.bin",
|
||||
.commandline_append = "root=/dev/mmcblk0p2 "
|
||||
},
|
||||
[1] = {
|
||||
.name = "SD Card backup rootfs",
|
||||
.block_read = sd_card_block_read_smdk6410,
|
||||
.filesystem = FS_EXT2,
|
||||
.partition_index = 3,
|
||||
.filepath = "boot/uImage-SMDK6410.bin",
|
||||
.commandline_append = "root=/dev/mmcblk0p3 "
|
||||
},
|
||||
},
|
||||
};
|
||||
|
27
qiboot/src/cpu/s3c6410/smdk6410.c
Normal file
27
qiboot/src/cpu/s3c6410/smdk6410.c
Normal file
@ -0,0 +1,27 @@
|
||||
#include <qi.h>
|
||||
#include <neo_smdk6410.h>
|
||||
#include <serial-s3c64xx.h>
|
||||
|
||||
static const struct board_variant board_variants[] = {
|
||||
[0] = {
|
||||
.name = "SMDK",
|
||||
.machine_revision = 0,
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* returns PCB revision information in b0, d8, d9
|
||||
* SMDK6410 EVB returns 0x000
|
||||
* SMDK6410 returns 0x001
|
||||
*/
|
||||
|
||||
int smdk6410_get_pcb_revision(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct board_variant const * get_board_variant_smdk6410(void)
|
||||
{
|
||||
return &board_variants[smdk6410_get_pcb_revision()];
|
||||
}
|
||||
|
487
qiboot/src/cpu/s3c6410/start.S
Normal file
487
qiboot/src/cpu/s3c6410/start.S
Normal file
@ -0,0 +1,487 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
*
|
||||
* Configuation settings for the OPENMOKO Neo GTA02 Linux GSM phone
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#define __ASM_MODE__
|
||||
#define __ASSEMBLY__
|
||||
|
||||
#include <s3c6410.h>
|
||||
|
||||
#define TEXT_BASE 0x53000000
|
||||
|
||||
|
||||
#define S3C6410_POP_A 1
|
||||
|
||||
#define set_pll(mdiv, pdiv, sdiv) (1<<31 | mdiv<<16 | pdiv<<8 | sdiv)
|
||||
|
||||
/* fixed MPLL 533MHz */
|
||||
#define MPLL_MDIV 266
|
||||
#define MPLL_PDIV 3
|
||||
#define MPLL_SDIV 1
|
||||
|
||||
#define Startup_APLLdiv 0
|
||||
#define APLL_MDIV 266
|
||||
#define APLL_PDIV 3
|
||||
#define APLL_SDIV 1
|
||||
#define Startup_PCLKdiv 3
|
||||
#define Startup_HCLKdiv 1
|
||||
#define Startup_MPLLdiv 1
|
||||
#define Startup_HCLKx2div 1
|
||||
#define Startup_APLL (12000000/(APLL_PDIV<<APLL_SDIV)*APLL_MDIV)
|
||||
#define Startup_HCLK (Startup_APLL/(Startup_HCLKx2div+1)/(Startup_HCLKdiv+1))
|
||||
|
||||
#define CLK_DIV_VAL ((Startup_PCLKdiv<<12)|(Startup_HCLKx2div<<9)|(Startup_HCLKdiv<<8)|(Startup_MPLLdiv<<4)|Startup_APLLdiv)
|
||||
#define APLL_VAL set_pll(APLL_MDIV, APLL_PDIV, APLL_SDIV)
|
||||
#define MPLL_VAL set_pll(MPLL_MDIV, MPLL_PDIV, MPLL_SDIV)
|
||||
#if S3C6410_POP_A
|
||||
|
||||
#define DMC1_MEM_CFG 0x00210011 /* Supports one CKE control, Chip1, Burst4, Row/Column bit */
|
||||
#define DMC1_MEM_CFG2 0xB41
|
||||
#define DMC1_CHIP0_CFG 0x150FC
|
||||
#define DMC1_CHIP1_CFG 0x154FC
|
||||
#define DMC_DDR_32_CFG 0x0 /* 32bit, DDR */
|
||||
|
||||
/* Memory Parameters */
|
||||
/* DDR Parameters */
|
||||
#define DDR_tREFRESH 5865 /* ns */
|
||||
#define DDR_tRAS 50 /* ns (min: 45ns)*/
|
||||
#define DDR_tRC 68 /* ns (min: 67.5ns)*/
|
||||
#define DDR_tRCD 23 /* ns (min: 22.5ns)*/
|
||||
#define DDR_tRFC 133 /* ns (min: 80ns)*/
|
||||
#define DDR_tRP 23 /* ns (min: 22.5ns)*/
|
||||
#define DDR_tRRD 20 /* ns (min: 15ns)*/
|
||||
#define DDR_tWR 20 /* ns (min: 15ns)*/
|
||||
#define DDR_tXSR 125 /* ns (min: 120ns)*/
|
||||
#define DDR_CASL 3 /* CAS Latency 3 */
|
||||
|
||||
#else
|
||||
|
||||
#define DMC1_MEM_CFG 0x00010012 /* Supports one CKE control, Chip1, Burst4, Row/Column bit */
|
||||
#define DMC1_MEM_CFG2 0xB45
|
||||
#define DMC1_CHIP0_CFG 0x150F8
|
||||
#define DMC_DDR_32_CFG 0x0 /* 32bit, DDR */
|
||||
|
||||
/* Memory Parameters */
|
||||
/* DDR Parameters */
|
||||
#define DDR_tREFRESH 7800 /* ns */
|
||||
#define DDR_tRAS 45 /* ns (min: 45ns)*/
|
||||
#define DDR_tRC 68 /* ns (min: 67.5ns)*/
|
||||
#define DDR_tRCD 23 /* ns (min: 22.5ns)*/
|
||||
#define DDR_tRFC 80 /* ns (min: 80ns)*/
|
||||
#define DDR_tRP 23 /* ns (min: 22.5ns)*/
|
||||
#define DDR_tRRD 15 /* ns (min: 15ns)*/
|
||||
#define DDR_tWR 15 /* ns (min: 15ns)*/
|
||||
#define DDR_tXSR 120 /* ns (min: 120ns)*/
|
||||
#define DDR_CASL 3 /* CAS Latency 3 */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* mDDR memory configuration
|
||||
*/
|
||||
#define DMC_DDR_BA_EMRS 2
|
||||
#define DMC_DDR_MEM_CASLAT 3
|
||||
#define DMC_DDR_CAS_LATENCY (DDR_CASL<<1) //6 Set Cas Latency to 3
|
||||
#define DMC_DDR_t_DQSS 1 // Min 0.75 ~ 1.25
|
||||
#define DMC_DDR_t_MRD 2 //Min 2 tck
|
||||
#define DMC_DDR_t_RAS (((Startup_HCLK / 1000 * DDR_tRAS) - 1) / 1000000 + 1) //7, Min 45ns
|
||||
#define DMC_DDR_t_RC (((Startup_HCLK / 1000 * DDR_tRC) - 1) / 1000000 + 1) //10, Min 67.5ns
|
||||
#define DMC_DDR_t_RCD (((Startup_HCLK / 1000 * DDR_tRCD) - 1) / 1000000 + 1) //4,5(TRM), Min 22.5ns
|
||||
#define DMC_DDR_schedule_RCD ((DMC_DDR_t_RCD - 3) << 3)
|
||||
#define DMC_DDR_t_RFC (((Startup_HCLK / 1000 * DDR_tRFC) - 1) / 1000000 + 1) //11,18(TRM) Min 80ns
|
||||
#define DMC_DDR_schedule_RFC ((DMC_DDR_t_RFC - 3) << 5)
|
||||
#define DMC_DDR_t_RP (((Startup_HCLK / 1000 * DDR_tRP) - 1) / 1000000 + 1) //4, 5(TRM) Min 22.5ns
|
||||
#define DMC_DDR_schedule_RP ((DMC_DDR_t_RP - 3) << 3)
|
||||
#define DMC_DDR_t_RRD (((Startup_HCLK / 1000 * DDR_tRRD) - 1) / 1000000 + 1) //3, Min 15ns
|
||||
#define DMC_DDR_t_WR (((Startup_HCLK / 1000 * DDR_tWR) - 1) / 1000000 + 1) //Min 15ns
|
||||
#define DMC_DDR_t_WTR 2
|
||||
#define DMC_DDR_t_XP 2 //1tck + tIS(1.5ns)
|
||||
#define DMC_DDR_t_XSR (((Startup_HCLK / 1000 * DDR_tXSR) - 1) / 1000000 + 1) //17, Min 120ns
|
||||
#define DMC_DDR_t_ESR DMC_DDR_t_XSR
|
||||
#define DMC_DDR_REFRESH_PRD (((Startup_HCLK / 1000 * DDR_tREFRESH) - 1) / 1000000) // TRM 2656
|
||||
#define DMC_DDR_USER_CONFIG 1 // 2b01 : mDDR
|
||||
|
||||
|
||||
.globl _start, processor_id, is_jtag
|
||||
|
||||
_start: b start_code
|
||||
/* if we are injected by JTAG, the script sets _istag content to nonzero */
|
||||
is_jtag:
|
||||
.word 0
|
||||
|
||||
/* it's at a fixed address (+0x8) so we can breakpoint it in the JTAG script
|
||||
* we need to go through this hassle because before this moment, SDRAM is not
|
||||
* working so we can't prep it from JTAG
|
||||
*/
|
||||
|
||||
_steppingstone_done:
|
||||
ldr pc, _start_armboot
|
||||
|
||||
_start_armboot:
|
||||
.word start_qi
|
||||
|
||||
_TEXT_BASE:
|
||||
.word TEXT_BASE
|
||||
|
||||
/*
|
||||
* These are defined in the board-specific linker script.
|
||||
*/
|
||||
.globl _bss_start
|
||||
_bss_start:
|
||||
.word __bss_start
|
||||
|
||||
.globl _bss_end
|
||||
_bss_end:
|
||||
.word _end
|
||||
|
||||
/*
|
||||
* we have a stack in steppingstone because we can want to run full memory
|
||||
* memory tests
|
||||
*/
|
||||
|
||||
.fill 128
|
||||
.globl _ss_stack
|
||||
_ss_stack:
|
||||
|
||||
start_code:
|
||||
/*
|
||||
* set the cpu to SVC32 mode
|
||||
*/
|
||||
mrs r0,cpsr
|
||||
bic r0,r0,#0x1f
|
||||
orr r0,r0,#0xd3
|
||||
msr cpsr,r0
|
||||
|
||||
/*
|
||||
* flush v4 I/D caches
|
||||
*/
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
|
||||
mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
|
||||
|
||||
/*
|
||||
* disable MMU stuff and caches
|
||||
*/
|
||||
mrc p15, 0, r0, c1, c0, 0
|
||||
bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
|
||||
bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
|
||||
orr r0, r0, #0x00000002 @ set bit 2 (A) Align
|
||||
orr r0, r0, #0x00005000 @ Enable I and D-Cache
|
||||
mcr p15, 0, r0, c1, c0, 0
|
||||
|
||||
/* Peri port setup */
|
||||
ldr r0, =0x70000000
|
||||
orr r0, r0, #0x13
|
||||
mcr p15,0,r0,c15,c2,4 @ 256M(0x70000000-0x7fffffff)
|
||||
|
||||
/* SDRAM */
|
||||
|
||||
ldr r0, =ELFIN_MEM_SYS_CFG @Memory sussystem address 0x7e00f120
|
||||
mov r1, #0xd @ Xm0CSn2 = NFCON CS0, Xm0CSn3 = NFCON CS1
|
||||
str r1, [r0]
|
||||
|
||||
ldr r0, =ELFIN_DMC1_BASE @DMC1 base address 0x7e001000
|
||||
|
||||
ldr r1, =0x04
|
||||
str r1, [r0, #INDEX_DMC_MEMC_CMD]
|
||||
|
||||
ldr r1, =DMC_DDR_REFRESH_PRD
|
||||
str r1, [r0, #INDEX_DMC_REFRESH_PRD]
|
||||
|
||||
ldr r1, =DMC_DDR_CAS_LATENCY
|
||||
str r1, [r0, #INDEX_DMC_CAS_LATENCY]
|
||||
|
||||
ldr r1, =DMC_DDR_t_DQSS
|
||||
str r1, [r0, #INDEX_DMC_T_DQSS]
|
||||
|
||||
ldr r1, =DMC_DDR_t_MRD
|
||||
str r1, [r0, #INDEX_DMC_T_MRD]
|
||||
|
||||
ldr r1, =DMC_DDR_t_RAS
|
||||
str r1, [r0, #INDEX_DMC_T_RAS]
|
||||
|
||||
ldr r1, =DMC_DDR_t_RC
|
||||
str r1, [r0, #INDEX_DMC_T_RC]
|
||||
|
||||
ldr r1, =DMC_DDR_t_RCD
|
||||
ldr r2, =DMC_DDR_schedule_RCD
|
||||
orr r1, r1, r2
|
||||
str r1, [r0, #INDEX_DMC_T_RCD]
|
||||
|
||||
ldr r1, =DMC_DDR_t_RFC
|
||||
ldr r2, =DMC_DDR_schedule_RFC
|
||||
orr r1, r1, r2
|
||||
str r1, [r0, #INDEX_DMC_T_RFC]
|
||||
|
||||
ldr r1, =DMC_DDR_t_RP
|
||||
ldr r2, =DMC_DDR_schedule_RP
|
||||
orr r1, r1, r2
|
||||
str r1, [r0, #INDEX_DMC_T_RP]
|
||||
|
||||
ldr r1, =DMC_DDR_t_RRD
|
||||
str r1, [r0, #INDEX_DMC_T_RRD]
|
||||
|
||||
ldr r1, =DMC_DDR_t_WR
|
||||
str r1, [r0, #INDEX_DMC_T_WR]
|
||||
|
||||
ldr r1, =DMC_DDR_t_WTR
|
||||
str r1, [r0, #INDEX_DMC_T_WTR]
|
||||
|
||||
ldr r1, =DMC_DDR_t_XP
|
||||
str r1, [r0, #INDEX_DMC_T_XP]
|
||||
|
||||
ldr r1, =DMC_DDR_t_XSR
|
||||
str r1, [r0, #INDEX_DMC_T_XSR]
|
||||
|
||||
ldr r1, =DMC_DDR_t_ESR
|
||||
str r1, [r0, #INDEX_DMC_T_ESR]
|
||||
|
||||
ldr r1, =DMC1_MEM_CFG
|
||||
str r1, [r0, #INDEX_DMC_MEMORY_CFG]
|
||||
|
||||
ldr r1, =DMC1_MEM_CFG2
|
||||
str r1, [r0, #INDEX_DMC_MEMORY_CFG2]
|
||||
|
||||
ldr r1, =DMC1_CHIP0_CFG
|
||||
str r1, [r0, #INDEX_DMC_CHIP_0_CFG]
|
||||
|
||||
ldr r1, =DMC_DDR_32_CFG
|
||||
str r1, [r0, #INDEX_DMC_USER_CONFIG]
|
||||
|
||||
@DMC0 DDR Chip 0 configuration direct command reg
|
||||
ldr r1, =DMC_NOP0
|
||||
str r1, [r0, #INDEX_DMC_DIRECT_CMD]
|
||||
|
||||
@Precharge All
|
||||
ldr r1, =DMC_PA0
|
||||
str r1, [r0, #INDEX_DMC_DIRECT_CMD]
|
||||
|
||||
@Auto Refresh 2 time
|
||||
ldr r1, =DMC_AR0
|
||||
str r1, [r0, #INDEX_DMC_DIRECT_CMD]
|
||||
str r1, [r0, #INDEX_DMC_DIRECT_CMD]
|
||||
|
||||
@MRS
|
||||
ldr r1, =DMC_mDDR_EMR0
|
||||
str r1, [r0, #INDEX_DMC_DIRECT_CMD]
|
||||
|
||||
@Mode Reg
|
||||
ldr r1, =DMC_mDDR_MR0
|
||||
str r1, [r0, #INDEX_DMC_DIRECT_CMD]
|
||||
|
||||
#if S3C6410_POP_A
|
||||
ldr r1, =DMC1_CHIP1_CFG
|
||||
str r1, [r0, #INDEX_DMC_CHIP_1_CFG]
|
||||
|
||||
@DMC0 DDR Chip 0 configuration direct command reg
|
||||
ldr r1, =DMC_NOP1
|
||||
str r1, [r0, #INDEX_DMC_DIRECT_CMD]
|
||||
|
||||
@Precharge All
|
||||
ldr r1, =DMC_PA1
|
||||
str r1, [r0, #INDEX_DMC_DIRECT_CMD]
|
||||
|
||||
@Auto Refresh 2 time
|
||||
ldr r1, =DMC_AR1
|
||||
str r1, [r0, #INDEX_DMC_DIRECT_CMD]
|
||||
str r1, [r0, #INDEX_DMC_DIRECT_CMD]
|
||||
|
||||
@MRS
|
||||
ldr r1, =DMC_mDDR_EMR1
|
||||
str r1, [r0, #INDEX_DMC_DIRECT_CMD]
|
||||
|
||||
@Mode Reg
|
||||
ldr r1, =DMC_mDDR_MR1
|
||||
str r1, [r0, #INDEX_DMC_DIRECT_CMD]
|
||||
#endif
|
||||
|
||||
@Enable DMC1
|
||||
mov r1, #0x0
|
||||
str r1, [r0, #INDEX_DMC_MEMC_CMD]
|
||||
|
||||
1:
|
||||
ldr r1, [r0, #INDEX_DMC_MEMC_STATUS]
|
||||
mov r2, #0x3
|
||||
and r1, r1, r2
|
||||
cmp r1, #0x1
|
||||
bne 1b
|
||||
nop
|
||||
|
||||
ldr r0, =ELFIN_CLOCK_POWER_BASE @0x7e00f000
|
||||
|
||||
ldr r1, [r0, #OTHERS_OFFSET]
|
||||
mov r2, #0x40
|
||||
orr r1, r1, r2
|
||||
str r1, [r0, #OTHERS_OFFSET]
|
||||
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
ldr r2, =0x80
|
||||
orr r1, r1, r2
|
||||
str r1, [r0, #OTHERS_OFFSET]
|
||||
|
||||
2:
|
||||
ldr r1, [r0, #OTHERS_OFFSET]
|
||||
ldr r2, =0xf00
|
||||
and r1, r1, r2
|
||||
cmp r1, #0xf00
|
||||
bne 2b
|
||||
|
||||
mov r1, #0xff00
|
||||
orr r1, r1, #0xff
|
||||
str r1, [r0, #APLL_LOCK_OFFSET]
|
||||
str r1, [r0, #MPLL_LOCK_OFFSET]
|
||||
str r1, [r0, #EPLL_LOCK_OFFSET]
|
||||
/* CLKUART(=66.5Mhz) = CLKUART_input(532/2=266Mhz) / (UART_RATIO(3)+1) */
|
||||
/* CLKUART(=50Mhz) = CLKUART_input(400/2=200Mhz) / (UART_RATIO(3)+1) */
|
||||
/* Now, When you use UART CLK SRC by EXT_UCLK1, We support 532MHz & 400MHz value */
|
||||
|
||||
ldr r1, [r0, #CLK_DIV2_OFFSET]
|
||||
bic r1, r1, #0x70000
|
||||
orr r1, r1, #0x30000
|
||||
str r1, [r0, #CLK_DIV2_OFFSET]
|
||||
|
||||
|
||||
ldr r1, [r0, #CLK_DIV0_OFFSET] /*Set Clock Divider*/
|
||||
bic r1, r1, #0x30000
|
||||
bic r1, r1, #0xff00
|
||||
bic r1, r1, #0xff
|
||||
ldr r2, =CLK_DIV_VAL
|
||||
orr r1, r1, r2
|
||||
str r1, [r0, #CLK_DIV0_OFFSET]
|
||||
|
||||
ldr r1, =APLL_VAL
|
||||
str r1, [r0, #APLL_CON_OFFSET]
|
||||
ldr r1, =MPLL_VAL
|
||||
str r1, [r0, #MPLL_CON_OFFSET]
|
||||
|
||||
ldr r1, =0x80200203 /* FOUT of EPLL is 96MHz */
|
||||
str r1, [r0, #EPLL_CON0_OFFSET]
|
||||
ldr r1, =0x0
|
||||
str r1, [r0, #EPLL_CON1_OFFSET]
|
||||
|
||||
ldr r1, [r0, #CLK_SRC_OFFSET] /* APLL, MPLL, EPLL select to Fout */
|
||||
|
||||
ldr r2, =0x2007
|
||||
orr r1, r1, r2
|
||||
|
||||
str r1, [r0, #CLK_SRC_OFFSET]
|
||||
|
||||
/* wait at least 200us to stablize all clock */
|
||||
mov r1, #0x10000
|
||||
3: subs r1, r1, #1
|
||||
bne 3b
|
||||
|
||||
ldr r1, [r0, #OTHERS_OFFSET]
|
||||
orr r1, r1, #0x20
|
||||
str r1, [r0, #OTHERS_OFFSET]
|
||||
|
||||
|
||||
/* set GPIO to enable UART */
|
||||
@ GPIO setting for UART
|
||||
ldr r0, =ELFIN_GPIO_BASE
|
||||
ldr r1, =0x2222
|
||||
str r1, [r0, #GPBCON_OFFSET]
|
||||
|
||||
ldr r0, =ELFIN_UART_BASE + ELFIN_UART3_OFFSET @0x7F005c00 uart 3
|
||||
mov r1, #0x0
|
||||
str r1, [r0, #UFCON_OFFSET]
|
||||
str r1, [r0, #UMCON_OFFSET]
|
||||
|
||||
mov r1, #0x3 @was 0.
|
||||
str r1, [r0, #ULCON_OFFSET]
|
||||
|
||||
ldr r1, =0xe45 /* UARTCLK SRC = 11 => EXT_UCLK1*/
|
||||
|
||||
str r1, [r0, #UCON_OFFSET]
|
||||
|
||||
ldr r1, =0x22
|
||||
str r1, [r0, #UBRDIV_OFFSET]
|
||||
|
||||
ldr r1, =0x1FFF
|
||||
str r1, [r0, #UDIVSLOT_OFFSET]
|
||||
|
||||
/* resuming? */
|
||||
|
||||
ldr r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET)
|
||||
ldr r1, [r0]
|
||||
bic r1, r1, #0xfffffff7
|
||||
cmp r1, #0x8
|
||||
beq wakeup_reset
|
||||
|
||||
/* no, cold boot */
|
||||
|
||||
ldr r0, =ELFIN_UART_BASE + ELFIN_UART3_OFFSET
|
||||
ldr r1, =0x55
|
||||
str r1, [r0, #UTXH_OFFSET] @'U'
|
||||
/* >> CFG_VIDEO_LOGO_MAX_SIZE */
|
||||
#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
|
||||
|
||||
|
||||
ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
|
||||
sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */
|
||||
sub sp, r0, #12 /* leave 3 words for abort-stack */
|
||||
clear_bss:
|
||||
ldr r0, _bss_start /* find start of bss segment */
|
||||
ldr r1, _bss_end /* stop here */
|
||||
mov r2, #0x00000000 /* clear */
|
||||
|
||||
clbss_l:
|
||||
str r2, [r0] /* clear loop... */
|
||||
add r0, r0, #4
|
||||
cmp r0, r1
|
||||
ble clbss_l
|
||||
|
||||
b _steppingstone_done
|
||||
|
||||
/* resume */
|
||||
|
||||
wakeup_reset:
|
||||
|
||||
ldr r0, =ELFIN_UART_BASE + ELFIN_UART3_OFFSET
|
||||
ldr r1, =0x4b4b4b4b
|
||||
str r1, [r0, #UTXH_OFFSET]
|
||||
|
||||
/*Clear wakeup status register*/
|
||||
ldr r0, =(ELFIN_CLOCK_POWER_BASE+WAKEUP_STAT_OFFSET)
|
||||
ldr r1, [r0]
|
||||
str r1, [r0]
|
||||
|
||||
#if 0
|
||||
/*LED test*/
|
||||
ldr r0, =ELFIN_GPIO_BASE
|
||||
ldr r1, =0x3000
|
||||
str r1, [r0, #GPNDAT_OFFSET]
|
||||
#endif
|
||||
|
||||
/*Load return address and jump to kernel*/
|
||||
ldr r0, =(ELFIN_CLOCK_POWER_BASE+INF_REG0_OFFSET)
|
||||
ldr r1, [r0] /* r1 = physical address of s3c6400_cpu_resume function*/
|
||||
mov pc, r1 /*Jump to kernel (sleep-s3c6400.S)*/
|
||||
nop
|
||||
nop
|
||||
|
||||
4:
|
||||
b 4b
|
136
qiboot/src/cpu/s3c6410/start_qi.c
Normal file
136
qiboot/src/cpu/s3c6410/start_qi.c
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
* Author: xiangfu liu <xiangfu@openmoko.org>
|
||||
* Andy Green <andy@openmoko.com>
|
||||
*
|
||||
* Configuation settings for the OPENMOKO Neo GTA02 Linux GSM phone
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* NOTE this stuff runs in steppingstone context! */
|
||||
|
||||
|
||||
#include <qi.h>
|
||||
#include <neo_om_3d7k.h>
|
||||
#include <neo_smdk6410.h>
|
||||
|
||||
#define stringify2(s) stringify1(s)
|
||||
#define stringify1(s) #s
|
||||
|
||||
extern void bootloader_second_phase(void);
|
||||
|
||||
const struct board_api *boards[] = {
|
||||
&board_api_om_3d7k,
|
||||
&board_api_smdk6410,
|
||||
NULL /* always last */
|
||||
};
|
||||
|
||||
struct board_api const * this_board;
|
||||
extern int is_jtag;
|
||||
|
||||
#include <serial-s3c64xx.h>
|
||||
|
||||
void start_qi(void)
|
||||
{
|
||||
int flag = 0;
|
||||
int board = 0;
|
||||
unsigned int sd_sectors = 0;
|
||||
|
||||
/*
|
||||
* well, we can be running on this CPU two different ways.
|
||||
*
|
||||
* 1) We were copied into steppingstone and TEXT_BASE already
|
||||
* by JTAG. We don't have to do anything else. JTAG script
|
||||
* then sets data at address 0x4 to 0xffffffff as a signal we
|
||||
* are running by JTAG.
|
||||
*
|
||||
* 2) We only got our first 4K into steppingstone, we need to copy
|
||||
* the rest of ourselves into TEXT_BASE.
|
||||
*
|
||||
* So we do the copy out of NAND only if we see we did not come up
|
||||
* under control of JTAG.
|
||||
*/
|
||||
|
||||
|
||||
/* ask all the boards we support in turn if they recognize this
|
||||
* hardware we are running on, accept the first positive answer
|
||||
*/
|
||||
|
||||
this_board = boards[board];
|
||||
while (!flag && this_board)
|
||||
/* check if it is the right board... */
|
||||
if (this_board->is_this_board())
|
||||
flag = 1;
|
||||
else
|
||||
this_board = boards[board++];
|
||||
|
||||
/* okay, do the critical port and serial init for our board */
|
||||
|
||||
if (this_board->early_port_init)
|
||||
this_board->early_port_init();
|
||||
|
||||
set_putc_func(this_board->putc);
|
||||
|
||||
/* stick some hello messages on debug console */
|
||||
|
||||
puts("\n\n\nQi Bootloader "stringify2(QI_CPU)" "
|
||||
stringify2(BUILD_HOST)" "
|
||||
stringify2(BUILD_VERSION)" "
|
||||
"\n");
|
||||
|
||||
puts(stringify2(BUILD_DATE) " Copyright (C) 2008 Openmoko, Inc.\n\n");
|
||||
|
||||
if (!is_jtag) {
|
||||
/*
|
||||
* We got the first 8KBytes of the bootloader pulled into the
|
||||
* steppingstone SRAM for free. Now we pull the whole bootloader
|
||||
* image into SDRAM.
|
||||
*
|
||||
* This code and the .S files are arranged by the linker script
|
||||
* to expect to run from 0x0. But the linker script has told
|
||||
* everything else to expect to run from 0x53000000+. That's
|
||||
* why we are going to be able to copy this code and not have it
|
||||
* crash when we run it from there.
|
||||
*/
|
||||
|
||||
/* We randomly pull 32KBytes of bootloader */
|
||||
|
||||
extern unsigned int s3c6410_mmc_init(int verbose);
|
||||
unsigned long s3c6410_mmc_bread(int dev_num,
|
||||
unsigned long start_blk, unsigned long blknum,
|
||||
void *dst);
|
||||
sd_sectors = s3c6410_mmc_init(1);
|
||||
s3c6410_mmc_bread(0, sd_sectors - 1026 - 16 - (256 * 2),
|
||||
32 * 2, (u8 *)0x53000000);
|
||||
}
|
||||
|
||||
/* all of Qi is in memory now, stuff outside steppingstone too */
|
||||
|
||||
if (this_board->port_init)
|
||||
this_board->port_init();
|
||||
|
||||
puts("\n Detected: ");
|
||||
puts(this_board->name);
|
||||
puts(", ");
|
||||
puts((this_board->get_board_variant)()->name);
|
||||
puts("\n");
|
||||
|
||||
/*
|
||||
* jump to bootloader_second_phase() running from DRAM copy
|
||||
*/
|
||||
bootloader_second_phase();
|
||||
}
|
90
qiboot/src/crc32.c
Normal file
90
qiboot/src/crc32.c
Normal file
@ -0,0 +1,90 @@
|
||||
#include <qi.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/* original copyright notice for this crc code (it is from U-Boot) --> */
|
||||
/*
|
||||
* This file is derived from crc32.c from the zlib-1.1.3 distribution
|
||||
* by Jean-loup Gailly and Mark Adler.
|
||||
*/
|
||||
|
||||
/* crc32.c -- compute the CRC-32 of a data stream
|
||||
* Copyright (C) 1995-1998 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
const unsigned long crc_table[256] = {
|
||||
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
|
||||
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
|
||||
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
|
||||
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
|
||||
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
|
||||
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
|
||||
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
|
||||
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
|
||||
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
|
||||
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
|
||||
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
|
||||
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
|
||||
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
|
||||
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
|
||||
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
|
||||
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
|
||||
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
|
||||
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
|
||||
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
|
||||
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
|
||||
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
|
||||
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
|
||||
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
|
||||
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
|
||||
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
|
||||
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
|
||||
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
|
||||
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
|
||||
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
|
||||
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
|
||||
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
|
||||
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
|
||||
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
|
||||
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
|
||||
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
|
||||
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
|
||||
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
|
||||
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
|
||||
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
|
||||
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
|
||||
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
|
||||
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
|
||||
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
|
||||
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
|
||||
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
|
||||
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
|
||||
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
|
||||
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
|
||||
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
|
||||
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
|
||||
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
|
||||
0x2d02ef8dL
|
||||
};
|
||||
|
||||
#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
|
||||
#define DO2(buf) DO1(buf); DO1(buf);
|
||||
#define DO4(buf) DO2(buf); DO2(buf);
|
||||
#define DO8(buf) DO4(buf); DO4(buf);
|
||||
|
||||
unsigned long crc32(unsigned long crc, const unsigned char *buf,
|
||||
unsigned int len)
|
||||
{
|
||||
crc = crc ^ 0xffffffffL;
|
||||
while (len >= 8) {
|
||||
DO8(buf);
|
||||
len -= 8;
|
||||
}
|
||||
if (len)
|
||||
do {
|
||||
DO1(buf);
|
||||
} while (--len);
|
||||
|
||||
return crc ^ 0xffffffffL;
|
||||
}
|
27
qiboot/src/ctype.c
Normal file
27
qiboot/src/ctype.c
Normal file
@ -0,0 +1,27 @@
|
||||
#include <qi-ctype.h>
|
||||
|
||||
unsigned char _ctype[] = {
|
||||
_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
|
||||
_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
|
||||
_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
|
||||
_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
|
||||
_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
|
||||
_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
|
||||
_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
|
||||
_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
|
||||
_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
|
||||
_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
|
||||
_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
|
||||
_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
|
||||
_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
|
||||
_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
|
||||
_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
|
||||
_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
|
||||
_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */
|
||||
_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */
|
||||
_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */
|
||||
_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */
|
||||
_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */
|
||||
_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */
|
103
qiboot/src/drivers/glamo-init.c
Normal file
103
qiboot/src/drivers/glamo-init.c
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* (C) Copyright 2007 by OpenMoko, Inc.
|
||||
* Author: Harald Welte <laforge@openmoko.org>
|
||||
* Andy Green <andy@openmoko.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <qi.h>
|
||||
#include <glamo-regs.h>
|
||||
|
||||
#define GLAMO_REG(x) (*(volatile unsigned short *)(0x08000000 + x))
|
||||
|
||||
static void glamo_reg_write(u16 reg, u16 val)
|
||||
{
|
||||
GLAMO_REG(reg) = val;
|
||||
}
|
||||
|
||||
static u16 glamo_reg_read(u16 reg)
|
||||
{
|
||||
return GLAMO_REG(reg);
|
||||
}
|
||||
|
||||
|
||||
static u16 u16a_gen_init_0x0000[] = {
|
||||
0x2020, 0x3650, 0x0002, 0x01FF, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x000D, 0x000B, 0x00EE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x1801 /*0x1839*/, 0x0000, 0x2000, 0x0001, 0x0100, 0x0000, 0x0000, 0x0000,
|
||||
0x05DB, 0x5231, 0x09C3, 0x8261, 0x0003, 0x0000, 0x0000, 0x0000,
|
||||
0x000F, 0x101E, 0xC0C3, 0x101E, 0x000F, 0x0001, 0x030F, 0x020F,
|
||||
0x080F, 0x0F0F
|
||||
};
|
||||
|
||||
static u16 u16a_gen_init_0x0200[] = {
|
||||
0x0EF0, 0x07FF, 0x0000, 0x0080, 0x0344, 0x0600, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x4000, 0xF00E, 0x00C0, 0x00C0, 0x00C0, 0x00C0,
|
||||
0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0,
|
||||
0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0,
|
||||
0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0,
|
||||
0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0,
|
||||
0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0,
|
||||
0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0,
|
||||
0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0,
|
||||
0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0,
|
||||
0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0,
|
||||
0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0,
|
||||
0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0,
|
||||
0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0,
|
||||
0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0,
|
||||
0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C0,
|
||||
0x0873, 0xAFAF, 0x0108, 0x0010, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x1002, 0x6006, 0x00FF, 0x0001, 0x0020, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x3210, 0x5432, 0xE100, 0x01D6
|
||||
};
|
||||
|
||||
|
||||
void glamo_core_init(void)
|
||||
{
|
||||
int bp;
|
||||
|
||||
/* power up PLL1 and PLL2 */
|
||||
glamo_reg_write(GLAMO_REG_PLL_GEN7, 0x0000);
|
||||
glamo_reg_write(GLAMO_REG_PLL_GEN3, 0x0400);
|
||||
|
||||
/* enable memory clock and get it out of deep pwrdown */
|
||||
glamo_reg_write(GLAMO_REG_CLOCK_MEMORY,
|
||||
glamo_reg_read(GLAMO_REG_CLOCK_MEMORY) | 8);
|
||||
glamo_reg_write(GLAMO_REG_MEM_DRAM2,
|
||||
glamo_reg_read(GLAMO_REG_MEM_DRAM2) & (~(1 << 12)));
|
||||
glamo_reg_write(GLAMO_REG_MEM_DRAM1,
|
||||
glamo_reg_read(GLAMO_REG_MEM_DRAM1) & (~(1 << 12)));
|
||||
/*
|
||||
* we just fill up the general hostbus and LCD register sets
|
||||
* with magic values taken from the Linux framebuffer init action
|
||||
*/
|
||||
for (bp = 0; bp < ARRAY_SIZE(u16a_gen_init_0x0000); bp++)
|
||||
glamo_reg_write(0x0 | (bp << 1),
|
||||
u16a_gen_init_0x0000[bp]);
|
||||
|
||||
for (bp = 0; bp < ARRAY_SIZE(u16a_gen_init_0x0200); bp++)
|
||||
glamo_reg_write(0x200 | (bp << 1),
|
||||
u16a_gen_init_0x0200[bp]);
|
||||
|
||||
/* spin until PLL1 lock */
|
||||
while (!(glamo_reg_read(GLAMO_REG_PLL_GEN5) & 1))
|
||||
;
|
||||
}
|
||||
|
851
qiboot/src/drivers/glamo-mmc.c
Normal file
851
qiboot/src/drivers/glamo-mmc.c
Normal file
@ -0,0 +1,851 @@
|
||||
/*
|
||||
* linux/drivers/mmc/host/glamo-mmc.c - Glamo MMC driver
|
||||
*
|
||||
* Copyright (C) 2007 OpenMoko, Inc, Andy Green <andy@openmoko.com>
|
||||
* Based on the Glamo MCI driver that was -->
|
||||
*
|
||||
* Copyright (C) 2007 OpenMoko, Inc, Andy Green <andy@openmoko.com>
|
||||
* Based on S3C MMC driver that was:
|
||||
* Copyright (C) 2004-2006 maintech GmbH, Thomas Kleffel <tk@maintech.de>
|
||||
*
|
||||
* and
|
||||
*
|
||||
* Based on S3C MMC driver that was (original copyright notice ---->)
|
||||
*
|
||||
* (C) Copyright 2006 by OpenMoko, Inc.
|
||||
* Author: Harald Welte <laforge@openmoko.org>
|
||||
*
|
||||
* based on u-boot pxa MMC driver and linux/drivers/mmc/s3c2410mci.c
|
||||
* (C) 2005-2005 Thomas Kleffel
|
||||
*
|
||||
* Copyright (C) 2004-2006 maintech GmbH, Thomas Kleffel <tk@maintech.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <qi.h>
|
||||
#include <mmc.h>
|
||||
|
||||
#include <glamo-regs.h>
|
||||
#include <glamo-mmc.h>
|
||||
|
||||
#define CONFIG_GLAMO_BASE 0x08000000
|
||||
|
||||
#define MMC_BLOCK_SIZE_BITS 9
|
||||
|
||||
#define GLAMO_REG(x) (*(volatile u16 *)(CONFIG_GLAMO_BASE + x))
|
||||
#define GLAMO_INTRAM_OFFSET (8 * 1024 * 1024)
|
||||
#define GLAMO_FB_SIZE ((8 * 1024 * 1024) - 0x10000)
|
||||
#define GLAMO_START_OF_MMC_INTMEM ((volatile u16 *)(CONFIG_GLAMO_BASE + \
|
||||
GLAMO_INTRAM_OFFSET + GLAMO_FB_SIZE))
|
||||
|
||||
static int ccnt;
|
||||
//static mmc_csd_t mmc_csd;
|
||||
static int mmc_ready = 0;
|
||||
//static int wide = 0;
|
||||
static enum card_type card_type = CARDTYPE_NONE;
|
||||
|
||||
|
||||
#define MULTI_READ_BLOCKS_PER_COMMAND 64
|
||||
|
||||
int mmc_read(unsigned long src, u8 *dst, int size);
|
||||
|
||||
#define UNSTUFF_BITS(resp,start,size) \
|
||||
({ \
|
||||
const int __size = size; \
|
||||
const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1; \
|
||||
const int __off = 3 - ((start) / 32); \
|
||||
const int __shft = (start) & 31; \
|
||||
u32 __res; \
|
||||
\
|
||||
__res = resp[__off] >> __shft; \
|
||||
if (__size + __shft > 32) \
|
||||
__res |= resp[__off-1] << ((32 - __shft) & 31); \
|
||||
__res & __mask; \
|
||||
})
|
||||
|
||||
|
||||
static void
|
||||
glamo_reg_write(u16 val, u16 reg)
|
||||
{
|
||||
GLAMO_REG(reg) = val;
|
||||
}
|
||||
|
||||
static u16
|
||||
glamo_reg_read(u16 reg)
|
||||
{
|
||||
return GLAMO_REG(reg);
|
||||
}
|
||||
|
||||
unsigned char CRC7(u8 * pu8, int cnt)
|
||||
{
|
||||
u8 crc = 0;
|
||||
|
||||
while (cnt--) {
|
||||
int n;
|
||||
u8 d = *pu8++;
|
||||
for (n = 0; n < 8; n++) {
|
||||
crc <<= 1;
|
||||
if ((d & 0x80) ^ (crc & 0x80))
|
||||
crc ^= 0x09;
|
||||
d <<= 1;
|
||||
}
|
||||
}
|
||||
return (crc << 1) | 1;
|
||||
}
|
||||
|
||||
unsigned long mmc_bread(int dev_num, unsigned long blknr, unsigned long blkcnt,
|
||||
void *dst)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!blkcnt)
|
||||
return 0;
|
||||
|
||||
/* printf("mmc_bread(%d, %ld, %ld, %p)\n", dev_num, blknr, blkcnt, dst); */
|
||||
ret = mmc_read(blknr, dst, blkcnt);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return blkcnt;
|
||||
}
|
||||
|
||||
/* MMC_DEFAULT_RCA should probably be just 1, but this may break other code
|
||||
that expects it to be shifted. */
|
||||
static u16 rca = MMC_DEFAULT_RCA >> 16;
|
||||
|
||||
static void do_pio_read(u16 *buf, int count_words)
|
||||
{
|
||||
volatile u16 *from_ptr = GLAMO_START_OF_MMC_INTMEM;
|
||||
|
||||
while (count_words--)
|
||||
*buf++ = *from_ptr++;
|
||||
}
|
||||
|
||||
static void do_pio_write(u16 *buf, int count_words)
|
||||
{
|
||||
volatile u16 *to_ptr = GLAMO_START_OF_MMC_INTMEM;
|
||||
|
||||
while (count_words--)
|
||||
*to_ptr++ = *buf++;
|
||||
}
|
||||
|
||||
|
||||
static int mmc_cmd(int opcode, int arg, int flags,
|
||||
int data_size, int data_blocks,
|
||||
int will_stop, u16 *resp)
|
||||
{
|
||||
u16 * pu16 = (u16 *)&resp[0];
|
||||
u16 * reg_resp = (u16 *)(CONFIG_GLAMO_BASE + GLAMO_REGOFS_MMC +
|
||||
GLAMO_REG_MMC_CMD_RSP1);
|
||||
u16 status;
|
||||
int n;
|
||||
u8 u8a[6];
|
||||
u16 fire = 0;
|
||||
int cmd_is_stop = 0;
|
||||
int error = 0;
|
||||
|
||||
#if 0
|
||||
printf("mmc_cmd(opcode=%d, arg=0x%08X, flags=0x%x, "
|
||||
"data_size=%d, data_blocks=%d, will_stop=%d, resp=%p)\n",
|
||||
opcode, arg, flags, data_size, data_blocks, will_stop, resp);
|
||||
#endif
|
||||
switch (opcode) {
|
||||
case MMC_STOP_TRANSMISSION:
|
||||
cmd_is_stop = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ccnt++;
|
||||
|
||||
/* this guy has data to read/write? */
|
||||
if ((!cmd_is_stop) && (flags & (MMC_DATA_WRITE | MMC_DATA_READ))) {
|
||||
/*
|
||||
* the S-Media-internal RAM offset for our MMC buffer
|
||||
*/
|
||||
glamo_reg_write((u16)GLAMO_FB_SIZE,
|
||||
GLAMO_REGOFS_MMC + GLAMO_REG_MMC_WDATADS1);
|
||||
glamo_reg_write((u16)(GLAMO_FB_SIZE >> 16),
|
||||
GLAMO_REGOFS_MMC + GLAMO_REG_MMC_WDATADS2);
|
||||
glamo_reg_write((u16)GLAMO_FB_SIZE,
|
||||
GLAMO_REGOFS_MMC + GLAMO_REG_MMC_RDATADS1);
|
||||
glamo_reg_write((u16)(GLAMO_FB_SIZE >> 16),
|
||||
GLAMO_REGOFS_MMC + GLAMO_REG_MMC_RDATADS2);
|
||||
|
||||
/* set up the block info */
|
||||
glamo_reg_write(data_size, GLAMO_REGOFS_MMC +
|
||||
GLAMO_REG_MMC_DATBLKLEN);
|
||||
glamo_reg_write(data_blocks, GLAMO_REGOFS_MMC +
|
||||
GLAMO_REG_MMC_DATBLKCNT);
|
||||
}
|
||||
|
||||
/* if we can't do it, reject as busy */
|
||||
if (!glamo_reg_read(GLAMO_REGOFS_MMC + GLAMO_REG_MMC_RB_STAT1) &
|
||||
GLAMO_STAT1_MMC_IDLE)
|
||||
return -1;
|
||||
|
||||
/* create an array in wire order for CRC computation */
|
||||
u8a[0] = 0x40 | (opcode & 0x3f);
|
||||
u8a[1] = (arg >> 24);
|
||||
u8a[2] = (arg >> 16);
|
||||
u8a[3] = (arg >> 8);
|
||||
u8a[4] = arg;
|
||||
u8a[5] = CRC7(&u8a[0], 5); /* CRC7 on first 5 bytes of packet */
|
||||
|
||||
/* issue the wire-order array including CRC in register order */
|
||||
glamo_reg_write((u8a[4] << 8) | u8a[5],
|
||||
GLAMO_REGOFS_MMC + GLAMO_REG_MMC_CMD_REG1);
|
||||
glamo_reg_write((u8a[2] << 8) | u8a[3],
|
||||
GLAMO_REGOFS_MMC + GLAMO_REG_MMC_CMD_REG2);
|
||||
glamo_reg_write((u8a[0] << 8) | u8a[1],
|
||||
GLAMO_REGOFS_MMC + GLAMO_REG_MMC_CMD_REG3);
|
||||
|
||||
/* command index toggle */
|
||||
fire |= (ccnt & 1) << 12;
|
||||
|
||||
/* set type of command */
|
||||
switch (mmc_cmd_type(flags)) {
|
||||
case MMC_CMD_BC:
|
||||
fire |= GLAMO_FIRE_MMC_CMDT_BNR;
|
||||
break;
|
||||
case MMC_CMD_BCR:
|
||||
fire |= GLAMO_FIRE_MMC_CMDT_BR;
|
||||
break;
|
||||
case MMC_CMD_AC:
|
||||
fire |= GLAMO_FIRE_MMC_CMDT_AND;
|
||||
break;
|
||||
case MMC_CMD_ADTC:
|
||||
fire |= GLAMO_FIRE_MMC_CMDT_AD;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* if it expects a response, set the type expected
|
||||
*
|
||||
* R1, Length : 48bit, Normal response
|
||||
* R1b, Length : 48bit, same R1, but added card busy status
|
||||
* R2, Length : 136bit (really 128 bits with CRC snipped)
|
||||
* R3, Length : 48bit (OCR register value)
|
||||
* R4, Length : 48bit, SDIO_OP_CONDITION, Reverse SDIO Card
|
||||
* R5, Length : 48bit, IO_RW_DIRECTION, Reverse SDIO Card
|
||||
* R6, Length : 48bit (RCA register)
|
||||
* R7, Length : 48bit (interface condition, VHS(voltage supplied),
|
||||
* check pattern, CRC7)
|
||||
*/
|
||||
switch (mmc_resp_type(flags)) {
|
||||
case MMC_RSP_R6: /* same index as R7 and R1 */
|
||||
fire |= GLAMO_FIRE_MMC_RSPT_R1;
|
||||
break;
|
||||
case MMC_RSP_R1B:
|
||||
fire |= GLAMO_FIRE_MMC_RSPT_R1b;
|
||||
break;
|
||||
case MMC_RSP_R2:
|
||||
fire |= GLAMO_FIRE_MMC_RSPT_R2;
|
||||
break;
|
||||
case MMC_RSP_R3:
|
||||
fire |= GLAMO_FIRE_MMC_RSPT_R3;
|
||||
break;
|
||||
/* R4 and R5 supported by chip not defined in linux/mmc/core.h (sdio) */
|
||||
}
|
||||
/*
|
||||
* From the command index, set up the command class in the host ctrllr
|
||||
*
|
||||
* missing guys present on chip but couldn't figure out how to use yet:
|
||||
* 0x0 "stream read"
|
||||
* 0x9 "cancel running command"
|
||||
*/
|
||||
switch (opcode) {
|
||||
case MMC_READ_SINGLE_BLOCK:
|
||||
fire |= GLAMO_FIRE_MMC_CC_SBR; /* single block read */
|
||||
break;
|
||||
case MMC_SWITCH: /* 64 byte payload */
|
||||
case 0x33: /* observed issued by MCI */
|
||||
case MMC_READ_MULTIPLE_BLOCK:
|
||||
/* we will get an interrupt off this */
|
||||
if (!will_stop)
|
||||
/* multiblock no stop */
|
||||
fire |= GLAMO_FIRE_MMC_CC_MBRNS;
|
||||
else
|
||||
/* multiblock with stop */
|
||||
fire |= GLAMO_FIRE_MMC_CC_MBRS;
|
||||
break;
|
||||
case MMC_WRITE_BLOCK:
|
||||
fire |= GLAMO_FIRE_MMC_CC_SBW; /* single block write */
|
||||
break;
|
||||
case MMC_WRITE_MULTIPLE_BLOCK:
|
||||
if (will_stop)
|
||||
/* multiblock with stop */
|
||||
fire |= GLAMO_FIRE_MMC_CC_MBWS;
|
||||
else
|
||||
/* multiblock NO stop-- 'RESERVED'? */
|
||||
fire |= GLAMO_FIRE_MMC_CC_MBWNS;
|
||||
break;
|
||||
case MMC_STOP_TRANSMISSION:
|
||||
fire |= GLAMO_FIRE_MMC_CC_STOP; /* STOP */
|
||||
break;
|
||||
default:
|
||||
fire |= GLAMO_FIRE_MMC_CC_BASIC; /* "basic command" */
|
||||
break;
|
||||
}
|
||||
/* enforce timeout */
|
||||
glamo_reg_write(0xfff, GLAMO_REGOFS_MMC + GLAMO_REG_MMC_TIMEOUT);
|
||||
|
||||
/* Generate interrupt on txfer; drive strength max */
|
||||
glamo_reg_write((glamo_reg_read(GLAMO_REGOFS_MMC +
|
||||
GLAMO_REG_MMC_BASIC) & 0xfe) |
|
||||
0x0800 | GLAMO_BASIC_MMC_NO_CLK_RD_WAIT |
|
||||
GLAMO_BASIC_MMC_EN_COMPL_INT |
|
||||
GLAMO_BASIC_MMC_EN_DR_STR0 |
|
||||
GLAMO_BASIC_MMC_EN_DR_STR1,
|
||||
GLAMO_REGOFS_MMC + GLAMO_REG_MMC_BASIC);
|
||||
|
||||
/* send the command out on the wire */
|
||||
/* dev_info(&host->pdev->dev, "Using FIRE %04X\n", fire); */
|
||||
glamo_reg_write(fire, GLAMO_REGOFS_MMC + GLAMO_REG_MMC_CMD_FIRE);
|
||||
|
||||
/*
|
||||
* we must spin until response is ready or timed out
|
||||
* -- we don't get interrupts unless there is a bulk rx
|
||||
*/
|
||||
do
|
||||
status = glamo_reg_read(GLAMO_REGOFS_MMC +
|
||||
GLAMO_REG_MMC_RB_STAT1);
|
||||
while ((((status >> 15) & 1) != (ccnt & 1)) ||
|
||||
(!(status & (GLAMO_STAT1_MMC_RB_RRDY |
|
||||
GLAMO_STAT1_MMC_RTOUT |
|
||||
GLAMO_STAT1_MMC_DTOUT |
|
||||
GLAMO_STAT1_MMC_BWERR |
|
||||
GLAMO_STAT1_MMC_BRERR))));
|
||||
|
||||
if (status & (GLAMO_STAT1_MMC_RTOUT | GLAMO_STAT1_MMC_DTOUT))
|
||||
error = -4;
|
||||
if (status & (GLAMO_STAT1_MMC_BWERR | GLAMO_STAT1_MMC_BRERR))
|
||||
error = -5;
|
||||
|
||||
if (cmd_is_stop)
|
||||
return 0;
|
||||
|
||||
if (error) {
|
||||
#if 0
|
||||
puts("cmd 0x");
|
||||
print8(opcode);
|
||||
puts(", arg 0x");
|
||||
print8(arg);
|
||||
puts(", flags 0x");
|
||||
print32(flags);
|
||||
puts("\n");
|
||||
puts("Error after cmd: 0x");
|
||||
print32(error);
|
||||
puts("\n");
|
||||
#endif
|
||||
goto done;
|
||||
}
|
||||
/*
|
||||
* mangle the response registers in two different exciting
|
||||
* undocumented ways discovered by trial and error
|
||||
*/
|
||||
if (mmc_resp_type(flags) == MMC_RSP_R2)
|
||||
/* grab the response */
|
||||
for (n = 0; n < 8; n++) /* super mangle power 1 */
|
||||
pu16[n ^ 6] = reg_resp[n];
|
||||
else
|
||||
for (n = 0; n < 3; n++) /* super mangle power 2 */
|
||||
pu16[n] = (reg_resp[n] >> 8) |
|
||||
(reg_resp[n + 1] << 8);
|
||||
/*
|
||||
* if we don't have bulk data to take care of, we're done
|
||||
*/
|
||||
if (!(flags & (MMC_DATA_READ | MMC_DATA_WRITE)))
|
||||
goto done;
|
||||
|
||||
/* enforce timeout */
|
||||
glamo_reg_write(0xfff, GLAMO_REGOFS_MMC + GLAMO_REG_MMC_TIMEOUT);
|
||||
/*
|
||||
* spin
|
||||
*/
|
||||
while (!(glamo_reg_read(GLAMO_REG_IRQ_STATUS) & GLAMO_IRQ_MMC))
|
||||
;
|
||||
/* ack this interrupt source */
|
||||
glamo_reg_write(GLAMO_IRQ_MMC, GLAMO_REG_IRQ_CLEAR);
|
||||
|
||||
if (status & GLAMO_STAT1_MMC_DTOUT)
|
||||
error = -1;
|
||||
if (status & (GLAMO_STAT1_MMC_BWERR | GLAMO_STAT1_MMC_BRERR))
|
||||
error = -2;
|
||||
if (status & GLAMO_STAT1_MMC_RTOUT)
|
||||
error = -5;
|
||||
if (error) {
|
||||
// printf("cmd 0x%x, arg 0x%x flags 0x%x\n", opcode, arg, flags);
|
||||
#if 0
|
||||
puts("Error after resp: 0x");
|
||||
print32(status);
|
||||
puts("\n");
|
||||
#endif
|
||||
goto done;
|
||||
}
|
||||
#if 0
|
||||
if (flags & MMC_DATA_READ) {
|
||||
volatile u8 * pu8 = (volatile u8 *)GLAMO_START_OF_MMC_INTMEM;
|
||||
for (n = 0; n < 512; n += 16) {
|
||||
int n1;
|
||||
for (n1 = 0; n1 < 16; n1++) {
|
||||
printf("%02X ", pu8[n + n1]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
done:
|
||||
return error;
|
||||
}
|
||||
|
||||
static void glamo_mci_reset(void)
|
||||
{
|
||||
/* reset MMC controller */
|
||||
glamo_reg_write(GLAMO_CLOCK_MMC_RESET | GLAMO_CLOCK_MMC_DG_TCLK |
|
||||
GLAMO_CLOCK_MMC_EN_TCLK | GLAMO_CLOCK_MMC_DG_M9CLK |
|
||||
GLAMO_CLOCK_MMC_EN_M9CLK,
|
||||
GLAMO_REG_CLOCK_MMC);
|
||||
/* and disable reset */
|
||||
glamo_reg_write(GLAMO_CLOCK_MMC_DG_TCLK |
|
||||
GLAMO_CLOCK_MMC_EN_TCLK | GLAMO_CLOCK_MMC_DG_M9CLK |
|
||||
GLAMO_CLOCK_MMC_EN_M9CLK,
|
||||
GLAMO_REG_CLOCK_MMC);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int mmc_read(unsigned long src, u8 *dst, int size)
|
||||
{
|
||||
int resp;
|
||||
u8 response[16];
|
||||
int size_original = size;
|
||||
int lump;
|
||||
|
||||
if (((int)dst) & 1) {
|
||||
puts("Bad align on dst\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
resp = mmc_cmd(MMC_SET_BLOCKLEN, MMC_BLOCK_SIZE,
|
||||
MMC_CMD_AC | MMC_RSP_R1, 0, 0, 0,
|
||||
(u16 *)&response[0]);
|
||||
if (resp)
|
||||
return resp;
|
||||
|
||||
while (size) {
|
||||
/* glamo mmc times out as this increases too much */
|
||||
lump = MULTI_READ_BLOCKS_PER_COMMAND;
|
||||
if (lump > size)
|
||||
lump = size;
|
||||
|
||||
switch (card_type) {
|
||||
case CARDTYPE_SDHC: /* block addressing */
|
||||
resp = mmc_cmd(MMC_READ_MULTIPLE_BLOCK,
|
||||
src,
|
||||
MMC_CMD_ADTC | MMC_RSP_R1 |
|
||||
MMC_DATA_READ, MMC_BLOCK_SIZE, lump, 1,
|
||||
(u16 *)&response[0]);
|
||||
break;
|
||||
default: /* byte addressing */
|
||||
resp = mmc_cmd(MMC_READ_MULTIPLE_BLOCK, src * MMC_BLOCK_SIZE,
|
||||
MMC_CMD_ADTC | MMC_RSP_R1 | MMC_DATA_READ,
|
||||
MMC_BLOCK_SIZE, lump, 1,
|
||||
(u16 *)&response[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
if (resp)
|
||||
return resp;
|
||||
|
||||
/* final speed 16MHz */
|
||||
glamo_reg_write((glamo_reg_read(GLAMO_REG_CLOCK_GEN8) &
|
||||
0xff00) | 2, GLAMO_REG_CLOCK_GEN8);
|
||||
|
||||
|
||||
do_pio_read((u16 *)dst, lump * MMC_BLOCK_SIZE >> 1);
|
||||
|
||||
if (size)
|
||||
size -= lump;
|
||||
|
||||
dst += lump * MMC_BLOCK_SIZE;
|
||||
src += lump;
|
||||
|
||||
resp = mmc_cmd(MMC_STOP_TRANSMISSION, 0,
|
||||
MMC_CMD_AC | MMC_RSP_R1B, 0, 0, 0,
|
||||
(u16 *)&response[0]);
|
||||
if (resp)
|
||||
return resp;
|
||||
|
||||
}
|
||||
|
||||
return size_original;
|
||||
}
|
||||
|
||||
int mmc_write(u8 *src, unsigned long dst, int size)
|
||||
{
|
||||
int resp;
|
||||
u8 response[16];
|
||||
int size_original = size;
|
||||
|
||||
if ((!size) || (size & (MMC_BLOCK_SIZE - 1))) {
|
||||
puts("Bad size 0x");
|
||||
print32(size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (((int)dst) & 1) {
|
||||
puts("Bad align on dst\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
resp = mmc_cmd(MMC_SET_BLOCKLEN, MMC_BLOCK_SIZE,
|
||||
MMC_CMD_AC | MMC_RSP_R1, 0, 0, 0,
|
||||
(u16 *)&response[0]);
|
||||
|
||||
while (size) {
|
||||
do_pio_write((u16 *)src, MMC_BLOCK_SIZE >> 1);
|
||||
switch (card_type) {
|
||||
case CARDTYPE_SDHC: /* block addressing */
|
||||
resp = mmc_cmd(MMC_WRITE_BLOCK,
|
||||
dst >> MMC_BLOCK_SIZE_BITS,
|
||||
MMC_CMD_ADTC | MMC_RSP_R1 |
|
||||
MMC_DATA_WRITE,
|
||||
MMC_BLOCK_SIZE, 1, 0,
|
||||
(u16 *)&response[0]);
|
||||
break;
|
||||
default: /* byte addressing */
|
||||
resp = mmc_cmd(MMC_WRITE_BLOCK, dst,
|
||||
MMC_CMD_ADTC | MMC_RSP_R1 |
|
||||
MMC_DATA_WRITE,
|
||||
MMC_BLOCK_SIZE, 1, 0,
|
||||
(u16 *)&response[0]);
|
||||
break;
|
||||
}
|
||||
if (size >= MMC_BLOCK_SIZE)
|
||||
size -= MMC_BLOCK_SIZE;
|
||||
else
|
||||
size = 0;
|
||||
dst += MMC_BLOCK_SIZE;
|
||||
src += MMC_BLOCK_SIZE;
|
||||
}
|
||||
return size_original;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void print_mmc_cid(mmc_cid_t *cid)
|
||||
{
|
||||
puts("MMC found. Card desciption is:\n");
|
||||
puts("Manufacturer ID = ");
|
||||
print8(cid->id[0]);
|
||||
print8(cid->id[1]);
|
||||
print8(cid->id[2]);
|
||||
/*
|
||||
puts("HW/FW Revision = %x %x\n",cid->hwrev, cid->fwrev);
|
||||
cid->hwrev = cid->fwrev = 0;
|
||||
puts("Product Name = %s\n",cid->name);
|
||||
printf("Serial Number = %02x%02x%02x\n",
|
||||
cid->sn[0], cid->sn[1], cid->sn[2]);
|
||||
printf("Month = %d\n",cid->month);
|
||||
printf("Year = %d\n",1997 + cid->year);
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
static void print_sd_cid(const struct sd_cid *cid)
|
||||
{
|
||||
puts(" Card Type: ");
|
||||
switch (card_type) {
|
||||
case CARDTYPE_NONE:
|
||||
puts("(None) / ");
|
||||
break;
|
||||
case CARDTYPE_MMC:
|
||||
puts("MMC / ");
|
||||
break;
|
||||
case CARDTYPE_SD:
|
||||
puts("SD / ");
|
||||
break;
|
||||
case CARDTYPE_SD20:
|
||||
puts("SD 2.0 / ");
|
||||
break;
|
||||
case CARDTYPE_SDHC:
|
||||
puts("SD 2.0 SDHC / ");
|
||||
break;
|
||||
}
|
||||
|
||||
puts("Mfr: 0x");
|
||||
print8(cid->mid);
|
||||
puts(", OEM \"");
|
||||
this_board->putc(cid->oid_0);
|
||||
this_board->putc(cid->oid_1);
|
||||
puts("\" / ");
|
||||
|
||||
this_board->putc(cid->pnm_0);
|
||||
this_board->putc(cid->pnm_1);
|
||||
this_board->putc(cid->pnm_2);
|
||||
this_board->putc(cid->pnm_3);
|
||||
this_board->putc(cid->pnm_4);
|
||||
puts("\", rev ");
|
||||
printdec(cid->prv >> 4);
|
||||
puts(".");
|
||||
printdec(cid->prv & 15);
|
||||
puts(" / s/n: ");
|
||||
printdec(cid->psn_0 << 24 | cid->psn_1 << 16 | cid->psn_2 << 8 |
|
||||
cid->psn_3);
|
||||
puts(" / date: ");
|
||||
printdec(cid->mdt_1 & 15);
|
||||
puts("/");
|
||||
printdec(2000 + ((cid->mdt_0 & 15) << 4)+((cid->mdt_1 & 0xf0) >> 4));
|
||||
puts("\n");
|
||||
|
||||
/* printf("CRC: 0x%02x, b0 = %d\n",
|
||||
cid->crc >> 1, cid->crc & 1); */
|
||||
}
|
||||
|
||||
|
||||
int mmc_init(int verbose)
|
||||
{
|
||||
int retries = 1000, rc = -1;
|
||||
int resp;
|
||||
u8 response[16];
|
||||
// mmc_cid_t *mmc_cid = (mmc_cid_t *)response;
|
||||
struct sd_cid *sd_cid = (struct sd_cid *)response;
|
||||
u32 hcs = 0;
|
||||
|
||||
card_type = CARDTYPE_NONE;
|
||||
|
||||
/* enable engine */
|
||||
|
||||
glamo_reg_write(GLAMO_CLOCK_MMC_EN_M9CLK |
|
||||
GLAMO_CLOCK_MMC_EN_TCLK |
|
||||
GLAMO_CLOCK_MMC_DG_M9CLK |
|
||||
GLAMO_CLOCK_MMC_DG_TCLK, GLAMO_REG_CLOCK_MMC);
|
||||
glamo_reg_write(glamo_reg_read(GLAMO_REG_HOSTBUS(2)) |
|
||||
GLAMO_HOSTBUS2_MMIO_EN_MMC, GLAMO_REG_HOSTBUS(2));
|
||||
|
||||
/* controller reset */
|
||||
|
||||
glamo_mci_reset();
|
||||
|
||||
/* start the clock -- slowly (50MHz / 250 == 195kHz */
|
||||
|
||||
glamo_reg_write((glamo_reg_read(GLAMO_REG_CLOCK_GEN8) & 0xff00) | 250,
|
||||
GLAMO_REG_CLOCK_GEN8);
|
||||
|
||||
/* enable clock to divider input */
|
||||
|
||||
glamo_reg_write(glamo_reg_read(
|
||||
GLAMO_REG_CLOCK_GEN5_1) | GLAMO_CLOCK_GEN51_EN_DIV_TCLK,
|
||||
GLAMO_REG_CLOCK_GEN5_1);
|
||||
|
||||
udelay(100000);
|
||||
|
||||
/* set bus width to 1 */
|
||||
|
||||
glamo_reg_write((glamo_reg_read(GLAMO_REGOFS_MMC +
|
||||
GLAMO_REG_MMC_BASIC) &
|
||||
(~GLAMO_BASIC_MMC_EN_4BIT_DATA)),
|
||||
GLAMO_REGOFS_MMC + GLAMO_REG_MMC_BASIC);
|
||||
|
||||
/* reset */
|
||||
|
||||
resp = mmc_cmd(MMC_GO_IDLE_STATE, 0, MMC_CMD_BCR, 0, 0, 0,
|
||||
(u16 *)&response[0]);
|
||||
|
||||
udelay(100000);
|
||||
udelay(100000);
|
||||
udelay(100000);
|
||||
udelay(100000);
|
||||
|
||||
/* SDHC card? */
|
||||
|
||||
resp = mmc_cmd(SD_SEND_IF_COND, 0x000001aa,
|
||||
MMC_CMD_BCR | MMC_RSP_R7, 0, 0, 0,
|
||||
(u16 *)&response[0]);
|
||||
if (!resp && (response[0] == 0xaa)) {
|
||||
card_type = CARDTYPE_SD20; /* 2.0 SD, may not be SDHC */
|
||||
hcs = 0x40000000;
|
||||
}
|
||||
|
||||
/* Well, either way let's say hello in SD card protocol */
|
||||
|
||||
while (retries--) {
|
||||
|
||||
udelay(10000);
|
||||
|
||||
resp = mmc_cmd(MMC_APP_CMD, 0x00000000,
|
||||
MMC_CMD_AC | MMC_RSP_R1, 0, 0, 0,
|
||||
(u16 *)&response[0]);
|
||||
if (resp)
|
||||
continue;
|
||||
resp = mmc_cmd(SD_APP_OP_COND, hcs | 0x00300000,
|
||||
MMC_CMD_BCR | MMC_RSP_R3, 0, 0, 0,
|
||||
(u16 *)&response[0]);
|
||||
if (resp)
|
||||
continue;
|
||||
|
||||
if (response[3] & (1 << 6)) { /* asserts block addressing */
|
||||
retries = -2;
|
||||
card_type = CARDTYPE_SDHC;
|
||||
}
|
||||
if (response[3] & (1 << 7)) { /* not busy */
|
||||
if (card_type == CARDTYPE_NONE)
|
||||
card_type = CARDTYPE_SD;
|
||||
retries = -2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (retries == -1) {
|
||||
puts("no response\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (card_type == CARDTYPE_NONE) {
|
||||
retries = 10;
|
||||
puts("failed to detect SD Card, trying MMC\n");
|
||||
do {
|
||||
resp = mmc_cmd(MMC_SEND_OP_COND, 0x00ffc000,
|
||||
MMC_CMD_BCR | MMC_RSP_R3, 0, 0, 0,
|
||||
(u16 *)&response[0]);
|
||||
udelay(50);
|
||||
} while (retries-- && !(response[3] & 0x80));
|
||||
if (retries >= 0)
|
||||
card_type = CARDTYPE_MMC;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* fill in device description */
|
||||
#if 0
|
||||
mmc_dev.if_type = IF_TYPE_MMC;
|
||||
mmc_dev.part_type = PART_TYPE_DOS;
|
||||
mmc_dev.dev = 0;
|
||||
mmc_dev.lun = 0;
|
||||
mmc_dev.type = 0;
|
||||
mmc_dev.removable = 0;
|
||||
mmc_dev.block_read = mmc_bread;
|
||||
mmc_dev.blksz = 512;
|
||||
mmc_dev.lba = 1 << 16; /* 64K x 512 blocks = 32MB default */
|
||||
#endif
|
||||
/* try to get card id */
|
||||
resp = mmc_cmd(MMC_ALL_SEND_CID, hcs,
|
||||
MMC_CMD_BCR | MMC_RSP_R2, 0, 0, 0,
|
||||
(u16 *)&response[0]);
|
||||
if (resp)
|
||||
return 1;
|
||||
|
||||
switch (card_type) {
|
||||
case CARDTYPE_MMC:
|
||||
/* TODO configure mmc driver depending on card
|
||||
attributes */
|
||||
#if 0
|
||||
if (verbose)
|
||||
print_mmc_cid(mmc_cid);
|
||||
sprintf((char *) mmc_dev.vendor,
|
||||
"Man %02x%02x%02x Snr %02x%02x%02x",
|
||||
mmc_cid->id[0], mmc_cid->id[1], mmc_cid->id[2],
|
||||
mmc_cid->sn[0], mmc_cid->sn[1], mmc_cid->sn[2]);
|
||||
sprintf((char *) mmc_dev.product, "%s", mmc_cid->name);
|
||||
sprintf((char *) mmc_dev.revision, "%x %x",
|
||||
mmc_cid->hwrev, mmc_cid->fwrev);
|
||||
#endif
|
||||
/* MMC exists, get CSD too */
|
||||
resp = mmc_cmd(MMC_SET_RELATIVE_ADDR, MMC_DEFAULT_RCA,
|
||||
MMC_CMD_AC | MMC_RSP_R1, 0, 0, 0,
|
||||
(u16 *)&response[0]);
|
||||
break;
|
||||
|
||||
case CARDTYPE_SD:
|
||||
case CARDTYPE_SD20:
|
||||
case CARDTYPE_SDHC:
|
||||
|
||||
if (verbose)
|
||||
print_sd_cid(sd_cid);
|
||||
#if 0
|
||||
sprintf((char *) mmc_dev.vendor,
|
||||
"Man %02 OEM %c%c \"%c%c%c%c%c\"",
|
||||
sd_cid->mid, sd_cid->oid_0, sd_cid->oid_1,
|
||||
sd_cid->pnm_0, sd_cid->pnm_1, sd_cid->pnm_2,
|
||||
sd_cid->pnm_3, sd_cid->pnm_4);
|
||||
sprintf((char *) mmc_dev.product, "%d",
|
||||
sd_cid->psn_0 << 24 | sd_cid->psn_1 << 16 |
|
||||
sd_cid->psn_2 << 8 | sd_cid->psn_3);
|
||||
sprintf((char *) mmc_dev.revision, "%d.%d",
|
||||
sd_cid->prv >> 4, sd_cid->prv & 15);
|
||||
#endif
|
||||
resp = mmc_cmd(SD_SEND_RELATIVE_ADDR, MMC_DEFAULT_RCA,
|
||||
MMC_CMD_BCR | MMC_RSP_R6, 0, 0, 0,
|
||||
(u16 *)&response[0]);
|
||||
rca = response[2] | (response[3] << 8);
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* grab the CSD */
|
||||
|
||||
resp = mmc_cmd(MMC_SEND_CSD, rca << 16,
|
||||
MMC_CMD_AC | MMC_RSP_R2, 0, 0, 0,
|
||||
(u16 *)&response[0]);
|
||||
if (!resp) {
|
||||
mmc_csd_t *csd = (mmc_csd_t *)response;
|
||||
|
||||
// memcpy(&mmc_csd, csd, sizeof(csd));
|
||||
rc = 0;
|
||||
mmc_ready = 1;
|
||||
/* FIXME add verbose printout for csd */
|
||||
/* printf("READ_BL_LEN=%u, C_SIZE_MULT=%u, C_SIZE=%u\n",
|
||||
csd->read_bl_len, csd->c_size_mult1,
|
||||
csd->c_size); */
|
||||
// mmc_dev.blksz = 512;
|
||||
// mmc_dev.lba = (((unsigned long)1 << csd->c_size_mult1) *
|
||||
// (unsigned long)csd->c_size) >> 9;
|
||||
|
||||
switch (card_type) {
|
||||
case CARDTYPE_SDHC:
|
||||
puts(" SDHC size: ");
|
||||
printdec((UNSTUFF_BITS(((u32 *)&response[0]), 48, 22)
|
||||
+ 1) / 2);
|
||||
break;
|
||||
default:
|
||||
puts(" MMC/SD size: ");
|
||||
printdec((((unsigned long)1 << csd->c_size_mult1) *
|
||||
(unsigned long)(csd->c_size)) >> 10);
|
||||
}
|
||||
puts(" MiB\n");
|
||||
}
|
||||
|
||||
resp = mmc_cmd(MMC_SELECT_CARD, rca<<16, MMC_CMD_AC | MMC_RSP_R1,
|
||||
0, 0, 0, (u16 *)&response[0]);
|
||||
if (resp)
|
||||
return 1;
|
||||
|
||||
#ifdef CONFIG_MMC_WIDE
|
||||
/* yay 4-bit! */
|
||||
if (card_type == CARDTYPE_SD || card_type == CARDTYPE_SDHC) {
|
||||
resp = mmc_cmd(MMC_APP_CMD, rca<<16, MMC_CMD_AC | MMC_RSP_R1,
|
||||
0, 0, 0, (u16 *)&response[0]);
|
||||
resp = mmc_cmd(MMC_SWITCH, 0x02, MMC_CMD_AC | MMC_RSP_R1B,
|
||||
0, 0, 0, (u16 *)&response[0]);
|
||||
wide = 1;
|
||||
glamo_reg_write(glamo_reg_read(GLAMO_REGOFS_MMC +
|
||||
GLAMO_REG_MMC_BASIC) | GLAMO_BASIC_MMC_EN_4BIT_DATA,
|
||||
GLAMO_REGOFS_MMC + GLAMO_REG_MMC_BASIC);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* set the clock to slow until first bulk completes (for slow SDHC) */
|
||||
|
||||
glamo_reg_write((glamo_reg_read(GLAMO_REG_CLOCK_GEN8) & 0xff00) | 32,
|
||||
GLAMO_REG_CLOCK_GEN8);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
252
qiboot/src/drivers/i2c-bitbang.c
Normal file
252
qiboot/src/drivers/i2c-bitbang.c
Normal file
@ -0,0 +1,252 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
* Author: Andy Green <andy@openmoko.com>
|
||||
*
|
||||
* Generic i2c bitbang state machine
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <qi.h>
|
||||
#include <i2c-bitbang.h>
|
||||
|
||||
void i2c_read(struct i2c_bitbang * bb, unsigned char ads7, unsigned char reg)
|
||||
{
|
||||
bb->data[0] = (ads7 << 1); /* write the register address */
|
||||
bb->data[1] = reg;
|
||||
bb->data[2] = IBCONTROL_DO_START;
|
||||
bb->data[3] = (ads7 << 1) | 1; /* then issue read cycle to device */
|
||||
bb->data[4] = IBCONTROL_DO_READ;
|
||||
bb->data[5] = IBCONTROL_DO_STOP;
|
||||
bb->data[6] = IBCONTROL_COMPLETE;
|
||||
bb->state = IBS_INIT;
|
||||
}
|
||||
|
||||
void i2c_write(struct i2c_bitbang * bb, unsigned char ads7, unsigned char reg,
|
||||
unsigned char b)
|
||||
{
|
||||
bb->data[0] = (ads7 << 1);
|
||||
bb->data[1] = reg;
|
||||
bb->data[2] = b;
|
||||
bb->data[3] = IBCONTROL_DO_STOP;
|
||||
bb->data[4] = IBCONTROL_COMPLETE;
|
||||
bb->state = IBS_INIT;
|
||||
}
|
||||
|
||||
int i2c_next_state(struct i2c_bitbang * bb)
|
||||
{
|
||||
switch (bb->state) {
|
||||
case IBS_INIT:
|
||||
bb->index = 0;
|
||||
bb->index_read = 0;
|
||||
(bb->set)(1, 1);
|
||||
bb->state = IBS_START1;
|
||||
break;
|
||||
|
||||
case IBS_START1:
|
||||
(bb->set)(1, 0);
|
||||
bb->state = IBS_START2;
|
||||
break;
|
||||
|
||||
case IBS_START2:
|
||||
(bb->set)(0, 0); /* start */
|
||||
bb->count = 8;
|
||||
bb->state = IBS_ADS_TX_S;
|
||||
break;
|
||||
|
||||
/* transmit address or data */
|
||||
case IBS_ADS_TX_S:
|
||||
(bb->set)(0, !!(bb->data[bb->index] & 0x80));
|
||||
bb->state = IBS_ADS_TX_H;
|
||||
break;
|
||||
case IBS_ADS_TX_H:
|
||||
(bb->set)(1, !!(bb->data[bb->index] & 0x80));
|
||||
bb->state = IBS_ADS_TX_L;
|
||||
break;
|
||||
case IBS_ADS_TX_L:
|
||||
(bb->set)(0, !!(bb->data[bb->index] & 0x80));
|
||||
bb->data[bb->index] <<= 1;
|
||||
bb->count--;
|
||||
if (bb->count) {
|
||||
bb->state = IBS_ADS_TX_S;
|
||||
break;
|
||||
}
|
||||
|
||||
(bb->set)(0, 1);
|
||||
bb->state = IBS_ADS_TX_ACK_H;
|
||||
break;
|
||||
|
||||
case IBS_ADS_TX_ACK_H:
|
||||
/* we finished... we expect an ack now */
|
||||
if ((bb->read_sda)())
|
||||
return -1;
|
||||
|
||||
(bb->set)(1, 1);
|
||||
bb->state = IBS_ADS_TX_ACK_L;
|
||||
break;
|
||||
|
||||
case IBS_ADS_TX_ACK_L:
|
||||
(bb->set)(0, 1);
|
||||
|
||||
bb->count = 8;
|
||||
bb->index++;
|
||||
switch (bb->data[bb->index]) {
|
||||
case IBCONTROL_DO_START:
|
||||
bb->state = IBS_START1;
|
||||
bb->index++;
|
||||
break;
|
||||
case IBCONTROL_DO_STOP:
|
||||
bb->state = IBS_STOP1;
|
||||
bb->index++;
|
||||
break;
|
||||
case IBCONTROL_DO_READ:
|
||||
bb->data[bb->index_read] = 0;
|
||||
bb->state = IBS_DATA_RX_S;
|
||||
break;
|
||||
case IBCONTROL_COMPLETE:
|
||||
return 1;
|
||||
default:
|
||||
bb->state = IBS_ADS_TX_S; /* write it out */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
/* receive data */
|
||||
case IBS_DATA_RX_S:
|
||||
(bb->set)(0, 1);
|
||||
bb->state = IBS_DATA_RX_H;
|
||||
break;
|
||||
|
||||
case IBS_DATA_RX_H:
|
||||
(bb->set)(1, 1);
|
||||
bb->state = IBS_DATA_RX_L;
|
||||
break;
|
||||
|
||||
case IBS_DATA_RX_L:
|
||||
bb->data[bb->index_read] <<= 1;
|
||||
bb->data[bb->index_read] |= !!(bb->read_sda)();
|
||||
bb->count--;
|
||||
if (bb->count) {
|
||||
(bb->set)(0, 1);
|
||||
bb->state = IBS_DATA_RX_S;
|
||||
break;
|
||||
}
|
||||
|
||||
/* slave has released SDA now, bang down ACK */
|
||||
if (bb->data[bb->index + 1] != IBCONTROL_DO_READ)
|
||||
(bb->set)(0, 1);
|
||||
else
|
||||
(bb->set)(0, 0);
|
||||
bb->state = IBS_DATA_RX_ACK_H;
|
||||
break;
|
||||
|
||||
case IBS_DATA_RX_ACK_H:
|
||||
if (bb->data[bb->index + 1] != IBCONTROL_DO_READ)
|
||||
(bb->set)(1, 1); /* NAK */
|
||||
else
|
||||
(bb->set)(1, 0); /* ACK */
|
||||
bb->state = IBS_DATA_RX_ACK_L;
|
||||
break;
|
||||
|
||||
case IBS_DATA_RX_ACK_L:
|
||||
if (bb->data[bb->index + 1] != IBCONTROL_DO_READ)
|
||||
(bb->set)(0, 1); /* NAK */
|
||||
else
|
||||
(bb->set)(0, 0); /* ACK */
|
||||
bb->index_read++;
|
||||
bb->index++;
|
||||
switch (bb->data[bb->index]) {
|
||||
case IBCONTROL_DO_START:
|
||||
bb->state = IBS_START1;
|
||||
bb->index++;
|
||||
break;
|
||||
case IBCONTROL_DO_STOP:
|
||||
bb->state = IBS_STOP1;
|
||||
bb->index++;
|
||||
break;
|
||||
case IBCONTROL_DO_READ:
|
||||
bb->state = IBS_DATA_RX_S;
|
||||
bb->data[bb->index_read] = 0;
|
||||
break;
|
||||
case IBCONTROL_COMPLETE:
|
||||
return 1;
|
||||
default:
|
||||
bb->state = IBS_ADS_TX_S; /* write it out */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case IBS_STOP1:
|
||||
(bb->set)(0, 0);
|
||||
bb->state = IBS_STOP2;
|
||||
break;
|
||||
|
||||
case IBS_STOP2:
|
||||
(bb->set)(1, 0);
|
||||
bb->state = IBS_STOP3;
|
||||
break;
|
||||
|
||||
case IBS_STOP3:
|
||||
(bb->set)(1, 1);
|
||||
bb->state = IBS_STOP4;
|
||||
break;
|
||||
|
||||
case IBS_STOP4:
|
||||
(bb->set)(1, 1);
|
||||
return 1; /* done */
|
||||
}
|
||||
|
||||
return 0; /* keep going */
|
||||
}
|
||||
|
||||
static int i2c_complete_synchronously(struct i2c_bitbang * bb)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
while (!ret) {
|
||||
ret = i2c_next_state(bb);
|
||||
(bb->spin)();
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
puts("i2c transaction failed ");
|
||||
printdec(ret);
|
||||
puts("\n");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int i2c_read_sync(struct i2c_bitbang * bb, unsigned char ads7,
|
||||
unsigned char reg)
|
||||
{
|
||||
i2c_read(bb, ads7, reg);
|
||||
if (i2c_complete_synchronously(bb) < 0)
|
||||
return -1;
|
||||
|
||||
return bb->data[0];
|
||||
}
|
||||
|
||||
void i2c_write_sync(struct i2c_bitbang * bb, unsigned char ads7,
|
||||
unsigned char reg, unsigned char b)
|
||||
{
|
||||
i2c_write(bb, ads7, reg, b);
|
||||
i2c_complete_synchronously(bb);
|
||||
}
|
133
qiboot/src/fs/dev.c
Normal file
133
qiboot/src/fs/dev.c
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* (C) Copyright 2004
|
||||
* esd gmbh <www.esd-electronics.com>
|
||||
* Reinhard Arlt <reinhard.arlt@esd-electronics.com>
|
||||
*
|
||||
* based on code of fs/reiserfs/dev.c by
|
||||
*
|
||||
* (C) Copyright 2003 - 2004
|
||||
* Sysgo AG, <www.elinos.com>, Pavel Bartusek <pba@sysgo.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include <qi.h>
|
||||
#include <ext2.h>
|
||||
#include <string.h>
|
||||
|
||||
extern unsigned long partition_offset_blocks;
|
||||
extern unsigned long partition_length_blocks;
|
||||
|
||||
|
||||
int ext2fs_devread(int sector, int filesystem_block_log2, int byte_offset, int byte_len, u8 *buf)
|
||||
{
|
||||
unsigned char sec_buf[SECTOR_SIZE];
|
||||
unsigned block_len;
|
||||
|
||||
sector = sector << filesystem_block_log2;
|
||||
|
||||
|
||||
/*
|
||||
* Check partition boundaries
|
||||
*/
|
||||
if ((sector < 0)
|
||||
|| ((sector + ((byte_offset + byte_len - 1) >> SECTOR_BITS)) >=
|
||||
partition_length_blocks)) {
|
||||
/* errnum = ERR_OUTSIDE_PART; */
|
||||
puts(" ** ext2fs_devread() read outside partition sector ");
|
||||
printdec(sector);
|
||||
puts("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (this_board->get_ui_keys)
|
||||
if ((this_board->get_ui_keys)() & UI_ACTION_SKIPKERNEL) {
|
||||
puts(" ** skipping \n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the read to the beginning of a partition.
|
||||
*/
|
||||
sector += byte_offset >> SECTOR_BITS;
|
||||
byte_offset &= SECTOR_SIZE - 1;
|
||||
|
||||
if (byte_offset) {
|
||||
int minimum = SECTOR_SIZE - byte_offset;
|
||||
|
||||
if (byte_len < minimum)
|
||||
minimum = byte_len;
|
||||
|
||||
/* read first part which isn't aligned with start of sector */
|
||||
if ((this_kernel->block_read)(sec_buf,
|
||||
partition_offset_blocks + sector, 1) < 0) {
|
||||
puts(" ** ext2fs_devread() read error **\n");
|
||||
return 0;
|
||||
}
|
||||
memcpy(buf, sec_buf + byte_offset,
|
||||
minimum);
|
||||
buf += minimum;
|
||||
byte_len -= minimum;
|
||||
sector++;
|
||||
}
|
||||
|
||||
if (!byte_len)
|
||||
return 1;
|
||||
|
||||
/* read sector aligned part */
|
||||
block_len = byte_len & ~(SECTOR_SIZE - 1);
|
||||
|
||||
if (block_len == 0) {
|
||||
u8 p[SECTOR_SIZE];
|
||||
|
||||
block_len = SECTOR_SIZE;
|
||||
this_kernel->block_read(p,partition_offset_blocks + sector, 1);
|
||||
memcpy(buf, p, byte_len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (this_kernel->block_read(buf, partition_offset_blocks + sector,
|
||||
block_len / SECTOR_SIZE) < 0) {
|
||||
puts(" ** ext2fs_devread() read error - block\n");
|
||||
printdec(partition_offset_blocks + sector);
|
||||
puts(" ");
|
||||
print32(block_len);
|
||||
puts(" ");
|
||||
print32(sector);
|
||||
return 0;
|
||||
}
|
||||
block_len = byte_len & ~(SECTOR_SIZE - 1);
|
||||
buf += block_len;
|
||||
byte_len -= block_len;
|
||||
sector += block_len / SECTOR_SIZE;
|
||||
|
||||
if (byte_len) {
|
||||
/* read rest of data which are not in whole sector */
|
||||
if (this_kernel->block_read(sec_buf,
|
||||
partition_offset_blocks + sector, 1) != 1) {
|
||||
puts(" ** ext2fs_devread() read error - last part\n");
|
||||
printdec(partition_offset_blocks + sector);
|
||||
puts(" ");
|
||||
print32(block_len);
|
||||
puts(" ");
|
||||
print32(sector);
|
||||
return 0;
|
||||
}
|
||||
memcpy (buf, sec_buf, byte_len);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
940
qiboot/src/fs/ext2.c
Normal file
940
qiboot/src/fs/ext2.c
Normal file
@ -0,0 +1,940 @@
|
||||
/*
|
||||
*(C) Copyright 2004
|
||||
* esd gmbh <www.esd-electronics.com>
|
||||
* Reinhard Arlt <reinhard.arlt@esd-electronics.com>
|
||||
*
|
||||
* based on code from grub2 fs/ext2.c and fs/fshelp.c by
|
||||
*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright(C) 2003, 2004 Free Software Foundation, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <qi.h>
|
||||
|
||||
#include <ext2.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
|
||||
extern int ext2fs_devread(int sector, int log2blksize, int byte_offset, int byte_len,
|
||||
char *buf);
|
||||
|
||||
/* Magic value used to identify an ext2 filesystem. */
|
||||
#define EXT2_MAGIC 0xEF53
|
||||
/* Amount of indirect blocks in an inode. */
|
||||
#define INDIRECT_BLOCKS 12
|
||||
/* Maximum lenght of a pathname. */
|
||||
#define EXT2_PATH_MAX 4096
|
||||
/* Maximum nesting of symlinks, used to prevent a loop. */
|
||||
#define EXT2_MAX_SYMLINKCNT 8
|
||||
|
||||
/* Filetype used in directory entry. */
|
||||
#define FILETYPE_UNKNOWN 0
|
||||
#define FILETYPE_REG 1
|
||||
#define FILETYPE_DIRECTORY 2
|
||||
#define FILETYPE_SYMLINK 7
|
||||
|
||||
/* Filetype information as used in inodes. */
|
||||
#define FILETYPE_INO_MASK 0170000
|
||||
#define FILETYPE_INO_REG 0100000
|
||||
#define FILETYPE_INO_DIRECTORY 0040000
|
||||
#define FILETYPE_INO_SYMLINK 0120000
|
||||
|
||||
/* Bits used as offset in sector */
|
||||
#define DISK_SECTOR_BITS 9
|
||||
|
||||
/* Log2 size of ext2 block in 512 blocks. */
|
||||
#define LOG2_EXT2_BLOCK_SIZE(data)(__le32_to_cpu(data->sblock.log2_block_size) + 1)
|
||||
|
||||
/* Log2 size of ext2 block in bytes. */
|
||||
#define LOG2_BLOCK_SIZE(data) (__le32_to_cpu(data->sblock.log2_block_size) + 10)
|
||||
|
||||
/* The size of an ext2 block in bytes. */
|
||||
#define EXT2_BLOCK_SIZE(data) (1 << LOG2_BLOCK_SIZE(data))
|
||||
|
||||
#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */
|
||||
#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */
|
||||
|
||||
#define EXT2_GOOD_OLD_INODE_SIZE 128
|
||||
uint32_t ext2_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
|
||||
|
||||
/* The ext2 superblock. */
|
||||
struct ext2_sblock {
|
||||
uint32_t total_inodes;
|
||||
uint32_t total_blocks;
|
||||
uint32_t reserved_blocks;
|
||||
uint32_t free_blocks;
|
||||
uint32_t free_inodes;
|
||||
uint32_t first_data_block;
|
||||
uint32_t log2_block_size;
|
||||
uint32_t log2_fragment_size;
|
||||
uint32_t blocks_per_group;
|
||||
uint32_t fragments_per_group;
|
||||
uint32_t inodes_per_group;
|
||||
uint32_t mtime;
|
||||
uint32_t utime;
|
||||
uint16_t mnt_count;
|
||||
uint16_t max_mnt_count;
|
||||
uint16_t magic;
|
||||
uint16_t fs_state;
|
||||
uint16_t error_handling;
|
||||
uint16_t minor_revision_level;
|
||||
uint32_t lastcheck;
|
||||
uint32_t checkinterval;
|
||||
uint32_t creator_os;
|
||||
uint32_t revision_level;
|
||||
uint16_t uid_reserved;
|
||||
uint16_t gid_reserved;
|
||||
uint32_t first_inode;
|
||||
uint16_t inode_size;
|
||||
uint16_t block_group_number;
|
||||
uint32_t feature_compatibility;
|
||||
uint32_t feature_incompat;
|
||||
uint32_t feature_ro_compat;
|
||||
uint32_t unique_id[4];
|
||||
char volume_name[16];
|
||||
char last_mounted_on[64];
|
||||
uint32_t compression_info;
|
||||
};
|
||||
|
||||
/* The ext2 blockgroup. */
|
||||
struct ext2_block_group {
|
||||
uint32_t block_id;
|
||||
uint32_t inode_id;
|
||||
uint32_t inode_table_id;
|
||||
uint16_t free_blocks;
|
||||
uint16_t free_inodes;
|
||||
uint16_t pad;
|
||||
uint32_t reserved[3];
|
||||
};
|
||||
|
||||
/* The ext2 inode. */
|
||||
struct ext2_inode {
|
||||
uint16_t mode;
|
||||
uint16_t uid;
|
||||
uint32_t size;
|
||||
uint32_t atime;
|
||||
uint32_t ctime;
|
||||
uint32_t mtime;
|
||||
uint32_t dtime;
|
||||
uint16_t gid;
|
||||
uint16_t nlinks;
|
||||
uint32_t blockcnt; /* Blocks of 512 bytes!! */
|
||||
uint32_t flags;
|
||||
uint32_t osd1;
|
||||
union {
|
||||
struct datablocks {
|
||||
uint32_t dir_blocks[INDIRECT_BLOCKS];
|
||||
uint32_t indir_block;
|
||||
uint32_t double_indir_block;
|
||||
uint32_t tripple_indir_block;
|
||||
} blocks;
|
||||
char symlink[60];
|
||||
} b;
|
||||
uint32_t version;
|
||||
uint32_t acl;
|
||||
uint32_t dir_acl;
|
||||
uint32_t fragment_addr;
|
||||
uint32_t osd2[3];
|
||||
};
|
||||
|
||||
/* The header of an ext2 directory entry. */
|
||||
struct ext2_dirent {
|
||||
uint32_t inode;
|
||||
uint16_t direntlen;
|
||||
uint8_t namelen;
|
||||
uint8_t filetype;
|
||||
};
|
||||
|
||||
struct ext2fs_node {
|
||||
struct ext2_data *data;
|
||||
struct ext2_inode inode;
|
||||
int ino;
|
||||
int inode_read;
|
||||
};
|
||||
|
||||
/* Information about a "mounted" ext2 filesystem. */
|
||||
struct ext2_data {
|
||||
struct ext2_sblock sblock;
|
||||
struct ext2_inode *inode;
|
||||
struct ext2fs_node diropen;
|
||||
};
|
||||
|
||||
|
||||
typedef struct ext2fs_node *ext2fs_node_t;
|
||||
|
||||
struct ext2_data *ext2fs_root = NULL;
|
||||
ext2fs_node_t ext2fs_file = NULL;
|
||||
int symlinknest = 0;
|
||||
uint32_t *indir1_block = NULL;
|
||||
int indir1_size = 0;
|
||||
int indir1_blkno = -1;
|
||||
uint32_t *indir2_block = NULL;
|
||||
int indir2_size = 0;
|
||||
int indir2_blkno = -1;
|
||||
|
||||
|
||||
static int ext2fs_blockgroup
|
||||
(struct ext2_data *data, int group, struct ext2_block_group *blkgrp) {
|
||||
return ext2fs_devread
|
||||
((__le32_to_cpu(data->sblock.first_data_block) +
|
||||
1), LOG2_EXT2_BLOCK_SIZE(data),
|
||||
group * sizeof(struct ext2_block_group),
|
||||
sizeof(struct ext2_block_group),(char *) blkgrp);
|
||||
}
|
||||
|
||||
|
||||
static int ext2fs_read_inode
|
||||
(struct ext2_data *data, int ino, struct ext2_inode *inode) {
|
||||
struct ext2_block_group blkgrp;
|
||||
struct ext2_sblock *sblock = &data->sblock;
|
||||
int inodes_per_block;
|
||||
int status;
|
||||
|
||||
unsigned int blkno;
|
||||
unsigned int blkoff;
|
||||
|
||||
/* It is easier to calculate if the first inode is 0. */
|
||||
ino--;
|
||||
status = ext2fs_blockgroup(data,
|
||||
ino /
|
||||
__le32_to_cpu(sblock->inodes_per_group),
|
||||
&blkgrp);
|
||||
if (status == 0)
|
||||
return 0;
|
||||
|
||||
inodes_per_block = EXT2_BLOCK_SIZE(data) / ext2_inode_size;
|
||||
blkno =(ino % __le32_to_cpu(sblock->inodes_per_group)) /
|
||||
inodes_per_block;
|
||||
blkoff =(ino % __le32_to_cpu(sblock->inodes_per_group)) %
|
||||
inodes_per_block;
|
||||
#ifdef DEBUG
|
||||
puts("ext2fs read inode blkno %d blkoff %d\n", blkno, blkoff);
|
||||
#endif
|
||||
/* Read the inode. */
|
||||
|
||||
status = ext2fs_devread(__le32_to_cpu(blkgrp.inode_table_id) + blkno,
|
||||
LOG2_EXT2_BLOCK_SIZE(data),
|
||||
ext2_inode_size * blkoff,
|
||||
sizeof(struct ext2_inode), (char *)inode);
|
||||
|
||||
return !!status;
|
||||
}
|
||||
|
||||
|
||||
void ext2fs_free_node(ext2fs_node_t node, ext2fs_node_t currroot) {
|
||||
if ((node != &ext2fs_root->diropen) &&(node != currroot)) {
|
||||
free(node);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int ext2fs_read_block(ext2fs_node_t node, int fileblock) {
|
||||
struct ext2_data *data = node->data;
|
||||
struct ext2_inode *inode = &node->inode;
|
||||
int blknr;
|
||||
int blksz = EXT2_BLOCK_SIZE(data);
|
||||
int log2_blksz = LOG2_EXT2_BLOCK_SIZE(data);
|
||||
int status;
|
||||
|
||||
/* Direct blocks. */
|
||||
if (fileblock < INDIRECT_BLOCKS) {
|
||||
blknr = __le32_to_cpu(inode->b.blocks.dir_blocks[fileblock]);
|
||||
}
|
||||
/* Indirect. */
|
||||
else if (fileblock <(INDIRECT_BLOCKS +(blksz / 4))) {
|
||||
if (indir1_block == NULL) {
|
||||
indir1_block =(uint32_t *) malloc(blksz);
|
||||
if (indir1_block == NULL) {
|
||||
puts("** ext2fs read block(indir 1) malloc failed. **\n");
|
||||
return -1;
|
||||
}
|
||||
indir1_size = blksz;
|
||||
indir1_blkno = -1;
|
||||
}
|
||||
if (blksz != indir1_size) {
|
||||
free(indir1_block);
|
||||
indir1_block = NULL;
|
||||
indir1_size = 0;
|
||||
indir1_blkno = -1;
|
||||
indir1_block =(uint32_t *) malloc(blksz);
|
||||
if (indir1_block == NULL) {
|
||||
puts("** ext2fs read block(indir 1) malloc failed. **\n");
|
||||
return -1;
|
||||
}
|
||||
indir1_size = blksz;
|
||||
}
|
||||
if ((__le32_to_cpu(inode->b.blocks.indir_block) <<
|
||||
log2_blksz) != indir1_blkno) {
|
||||
status = ext2fs_devread(__le32_to_cpu(inode->b.blocks.indir_block), log2_blksz,
|
||||
0, blksz,
|
||||
(char *) indir1_block);
|
||||
if (status == 0) {
|
||||
puts("** ext2fs read block(indir 1) failed. **\n");
|
||||
return 0;
|
||||
}
|
||||
indir1_blkno =
|
||||
__le32_to_cpu(inode->b.blocks.
|
||||
indir_block) << log2_blksz;
|
||||
}
|
||||
blknr = __le32_to_cpu(indir1_block
|
||||
[fileblock - INDIRECT_BLOCKS]);
|
||||
}
|
||||
/* Double indirect. */
|
||||
else if (fileblock <
|
||||
(INDIRECT_BLOCKS +(blksz / 4 *(blksz / 4 + 1)))) {
|
||||
unsigned int perblock = blksz / 4;
|
||||
unsigned int rblock = fileblock -(INDIRECT_BLOCKS
|
||||
+ blksz / 4);
|
||||
|
||||
if (indir1_block == NULL) {
|
||||
indir1_block =(uint32_t *) malloc(blksz);
|
||||
if (indir1_block == NULL) {
|
||||
puts("** ext2fs read block(indir 2 1) malloc failed. **\n");
|
||||
return -1;
|
||||
}
|
||||
indir1_size = blksz;
|
||||
indir1_blkno = -1;
|
||||
}
|
||||
if (blksz != indir1_size) {
|
||||
free(indir1_block);
|
||||
indir1_block = NULL;
|
||||
indir1_size = 0;
|
||||
indir1_blkno = -1;
|
||||
indir1_block =(uint32_t *) malloc(blksz);
|
||||
if (indir1_block == NULL) {
|
||||
puts("** ext2fs read block(indir 2 1) malloc failed. **\n");
|
||||
return -1;
|
||||
}
|
||||
indir1_size = blksz;
|
||||
}
|
||||
if ((__le32_to_cpu(inode->b.blocks.double_indir_block) <<
|
||||
log2_blksz) != indir1_blkno) {
|
||||
status = ext2fs_devread(__le32_to_cpu(inode->b.blocks.double_indir_block), log2_blksz,
|
||||
0, blksz,
|
||||
(char *) indir1_block);
|
||||
if (status == 0) {
|
||||
puts("** ext2fs read block(indir 2 1) failed. **\n");
|
||||
return -1;
|
||||
}
|
||||
indir1_blkno =
|
||||
__le32_to_cpu(inode->b.blocks.double_indir_block) << log2_blksz;
|
||||
}
|
||||
|
||||
if (indir2_block == NULL) {
|
||||
indir2_block =(uint32_t *) malloc(blksz);
|
||||
if (indir2_block == NULL) {
|
||||
puts("** ext2fs read block(indir 2 2) malloc failed. **\n");
|
||||
return -1;
|
||||
}
|
||||
indir2_size = blksz;
|
||||
indir2_blkno = -1;
|
||||
}
|
||||
if (blksz != indir2_size) {
|
||||
free(indir2_block);
|
||||
indir2_block = NULL;
|
||||
indir2_size = 0;
|
||||
indir2_blkno = -1;
|
||||
indir2_block =(uint32_t *) malloc(blksz);
|
||||
if (indir2_block == NULL) {
|
||||
puts("** ext2fs read block(indir 2 2) malloc failed. **\n");
|
||||
return -1;
|
||||
}
|
||||
indir2_size = blksz;
|
||||
}
|
||||
if ((__le32_to_cpu(indir1_block[rblock / perblock]) <<
|
||||
log2_blksz) != indir2_blkno) {
|
||||
status = ext2fs_devread(__le32_to_cpu(indir1_block[rblock / perblock]), log2_blksz,
|
||||
0, blksz,
|
||||
(char *) indir2_block);
|
||||
if (status == 0) {
|
||||
puts("** ext2fs read block(indir 2 2) failed. **\n");
|
||||
return -1;
|
||||
}
|
||||
indir2_blkno =
|
||||
__le32_to_cpu(indir1_block[rblock / perblock]) << log2_blksz;
|
||||
}
|
||||
blknr = __le32_to_cpu(indir2_block[rblock % perblock]);
|
||||
}
|
||||
/* Triple indirect. */
|
||||
else {
|
||||
puts("** ext2fs doesn't support triple indirect blocks. **\n");
|
||||
return -1;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("ext2fs_read_block %08x\n", blknr);
|
||||
#endif
|
||||
return blknr;
|
||||
}
|
||||
|
||||
|
||||
int ext2fs_read_file(ext2fs_node_t node, int pos, unsigned int len, char *buf) {
|
||||
int i;
|
||||
int blockcnt;
|
||||
int log2blocksize = LOG2_EXT2_BLOCK_SIZE(node->data);
|
||||
int blocksize = 1 <<(log2blocksize + DISK_SECTOR_BITS);
|
||||
unsigned int filesize = __le32_to_cpu(node->inode.size);
|
||||
int previous_block_number = -1;
|
||||
int delayed_start = 0;
|
||||
int delayed_extent = 0;
|
||||
int delayed_skipfirst = 0;
|
||||
int delayed_next = 0;
|
||||
char * delayed_buf = NULL;
|
||||
int status;
|
||||
|
||||
/* Adjust len so it we can't read past the end of the file. */
|
||||
if (len > filesize) {
|
||||
len = filesize;
|
||||
}
|
||||
blockcnt = ((len + pos) + blocksize - 1) / blocksize;
|
||||
|
||||
for(i = pos / blocksize; i < blockcnt; i++) {
|
||||
int blknr;
|
||||
int blockoff = pos % blocksize;
|
||||
int blockend = blocksize;
|
||||
|
||||
int skipfirst = 0;
|
||||
|
||||
blknr = ext2fs_read_block(node, i);
|
||||
if (blknr < 0)
|
||||
return -1;
|
||||
|
||||
blknr = blknr << log2blocksize;
|
||||
|
||||
/* Last block. */
|
||||
if (i == blockcnt - 1) {
|
||||
blockend =(len + pos) % blocksize;
|
||||
|
||||
/* The last portion is exactly blocksize. */
|
||||
if (!blockend) {
|
||||
blockend = blocksize;
|
||||
}
|
||||
}
|
||||
|
||||
/* First block. */
|
||||
if (i == pos / blocksize) {
|
||||
skipfirst = blockoff;
|
||||
blockend -= skipfirst;
|
||||
}
|
||||
|
||||
/* If the block number is 0 this block is not stored on disk but
|
||||
is zero filled instead. */
|
||||
if (blknr) {
|
||||
int status;
|
||||
|
||||
if (previous_block_number != -1) {
|
||||
if (delayed_next == blknr) {
|
||||
delayed_extent += blockend;
|
||||
delayed_next += blockend >> SECTOR_BITS;
|
||||
} else { /* spill */
|
||||
status = ext2fs_devread(delayed_start,
|
||||
0, delayed_skipfirst,
|
||||
delayed_extent, delayed_buf);
|
||||
if (status == 0)
|
||||
return -1;
|
||||
previous_block_number = blknr;
|
||||
delayed_start = blknr;
|
||||
delayed_extent = blockend;
|
||||
delayed_skipfirst = skipfirst;
|
||||
delayed_buf = buf;
|
||||
delayed_next = blknr + (blockend >> SECTOR_BITS);
|
||||
}
|
||||
} else {
|
||||
previous_block_number = blknr;
|
||||
delayed_start = blknr;
|
||||
delayed_extent = blockend;
|
||||
delayed_skipfirst = skipfirst;
|
||||
delayed_buf = buf;
|
||||
delayed_next = blknr + (blockend >> SECTOR_BITS);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (previous_block_number != -1) {
|
||||
/* spill */
|
||||
status = ext2fs_devread(delayed_start,
|
||||
0, delayed_skipfirst,
|
||||
delayed_extent, delayed_buf);
|
||||
if (status == 0)
|
||||
return -1;
|
||||
previous_block_number = -1;
|
||||
}
|
||||
memset(buf, 0, blocksize - skipfirst);
|
||||
}
|
||||
buf += blocksize - skipfirst;
|
||||
}
|
||||
|
||||
if (previous_block_number != -1) {
|
||||
/* spill */
|
||||
status = ext2fs_devread(delayed_start,
|
||||
0, delayed_skipfirst,
|
||||
delayed_extent, delayed_buf);
|
||||
if (status == 0)
|
||||
return -1;
|
||||
previous_block_number = -1;
|
||||
}
|
||||
|
||||
return(len);
|
||||
}
|
||||
|
||||
|
||||
static int ext2fs_iterate_dir(ext2fs_node_t dir, char *name, ext2fs_node_t * fnode, int *ftype)
|
||||
{
|
||||
unsigned int fpos = 0;
|
||||
int status;
|
||||
struct ext2fs_node *diro =(struct ext2fs_node *) dir;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (name != NULL)
|
||||
printf("Iterate dir %s\n", name);
|
||||
#endif /* of DEBUG */
|
||||
if (!diro->inode_read) {
|
||||
status = ext2fs_read_inode(diro->data, diro->ino,
|
||||
&diro->inode);
|
||||
if (status == 0) {
|
||||
printdec(diro->ino);
|
||||
puts("failed to read inode\n");
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Search the file. */
|
||||
while (fpos < __le32_to_cpu(diro->inode.size)) {
|
||||
struct ext2_dirent dirent;
|
||||
|
||||
status = ext2fs_read_file(diro, fpos,
|
||||
sizeof(struct ext2_dirent),
|
||||
(char *) &dirent);
|
||||
if (status < 1) {
|
||||
puts("ext2fs_read_file ret < 1\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dirent.namelen != 0) {
|
||||
char filename[256];
|
||||
ext2fs_node_t fdiro;
|
||||
int type = FILETYPE_UNKNOWN;
|
||||
|
||||
status = ext2fs_read_file(diro,
|
||||
fpos + sizeof(struct ext2_dirent),
|
||||
dirent.namelen, filename);
|
||||
if (status < 1) {
|
||||
puts("ext2fs_read_file fail 2\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
fdiro = malloc(sizeof(struct ext2fs_node));
|
||||
if (!fdiro) {
|
||||
puts("malloc fail\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
fdiro->data = diro->data;
|
||||
fdiro->ino = __le32_to_cpu(dirent.inode);
|
||||
|
||||
filename[dirent.namelen] = '\0';
|
||||
|
||||
if (dirent.filetype != FILETYPE_UNKNOWN) {
|
||||
fdiro->inode_read = 0;
|
||||
|
||||
if (dirent.filetype == FILETYPE_DIRECTORY) {
|
||||
type = FILETYPE_DIRECTORY;
|
||||
} else if (dirent.filetype ==
|
||||
FILETYPE_SYMLINK) {
|
||||
type = FILETYPE_SYMLINK;
|
||||
} else if (dirent.filetype == FILETYPE_REG) {
|
||||
type = FILETYPE_REG;
|
||||
}
|
||||
} else {
|
||||
/* The filetype can not be read from the dirent, get it from inode */
|
||||
|
||||
status = ext2fs_read_inode(diro->data,
|
||||
__le32_to_cpu(dirent.inode),
|
||||
&fdiro->inode);
|
||||
if (status == 0) {
|
||||
puts("inner ext2fs_read_inode fail\n");
|
||||
free(fdiro);
|
||||
return(0);
|
||||
}
|
||||
fdiro->inode_read = 1;
|
||||
|
||||
if ((__le16_to_cpu(fdiro->inode.mode) &
|
||||
FILETYPE_INO_MASK) ==
|
||||
FILETYPE_INO_DIRECTORY) {
|
||||
type = FILETYPE_DIRECTORY;
|
||||
} else if ((__le16_to_cpu(fdiro->inode.mode)
|
||||
& FILETYPE_INO_MASK) ==
|
||||
FILETYPE_INO_SYMLINK) {
|
||||
type = FILETYPE_SYMLINK;
|
||||
} else if ((__le16_to_cpu(fdiro->inode.mode)
|
||||
& FILETYPE_INO_MASK) ==
|
||||
FILETYPE_INO_REG) {
|
||||
type = FILETYPE_REG;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("iterate >%s<\n", filename);
|
||||
#endif /* of DEBUG */
|
||||
if ((name != NULL) &&(fnode != NULL)
|
||||
&&(ftype != NULL)) {
|
||||
if (strcmp(filename, name) == 0) {
|
||||
*ftype = type;
|
||||
*fnode = fdiro;
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if (fdiro->inode_read == 0) {
|
||||
status = ext2fs_read_inode(diro->data,
|
||||
__le32_to_cpu(dirent.inode),
|
||||
&fdiro->inode);
|
||||
if (status == 0) {
|
||||
puts("ext2fs_read_inode 3 fail\n");
|
||||
free(fdiro);
|
||||
return(0);
|
||||
}
|
||||
fdiro->inode_read = 1;
|
||||
}
|
||||
switch(type) {
|
||||
case FILETYPE_DIRECTORY:
|
||||
puts("<DIR> ");
|
||||
break;
|
||||
case FILETYPE_SYMLINK:
|
||||
puts("<SYM> ");
|
||||
break;
|
||||
case FILETYPE_REG:
|
||||
puts(" ");
|
||||
break;
|
||||
default:
|
||||
puts("< ? > ");
|
||||
break;
|
||||
}
|
||||
printdec(__le32_to_cpu(fdiro->inode.size));
|
||||
puts(" ");
|
||||
puts(filename);
|
||||
puts("\n");
|
||||
}
|
||||
free(fdiro);
|
||||
}
|
||||
fpos += __le16_to_cpu(dirent.direntlen);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static char *ext2fs_read_symlink(ext2fs_node_t node) {
|
||||
char *symlink;
|
||||
struct ext2fs_node *diro = node;
|
||||
int status;
|
||||
|
||||
if (!diro->inode_read) {
|
||||
status = ext2fs_read_inode(diro->data, diro->ino,
|
||||
&diro->inode);
|
||||
if (status == 0) {
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
symlink = malloc(__le32_to_cpu(diro->inode.size) + 1);
|
||||
if (!symlink)
|
||||
return(0);
|
||||
|
||||
/* If the filesize of the symlink is bigger than
|
||||
60 the symlink is stored in a separate block,
|
||||
otherwise it is stored in the inode. */
|
||||
if (__le32_to_cpu(diro->inode.size) < 60) {
|
||||
strncpy(symlink, diro->inode.b.symlink,
|
||||
__le32_to_cpu(diro->inode.size));
|
||||
} else {
|
||||
status = ext2fs_read_file(diro, 0,
|
||||
__le32_to_cpu(diro->inode.size),
|
||||
symlink);
|
||||
if (status == 0) {
|
||||
free(symlink);
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
symlink[__le32_to_cpu(diro->inode.size)] = '\0';
|
||||
return(symlink);
|
||||
}
|
||||
|
||||
|
||||
int ext2fs_find_file1
|
||||
(const char *currpath,
|
||||
ext2fs_node_t currroot, ext2fs_node_t * currfound, int *foundtype) {
|
||||
char fpath[strlen(currpath) + 1];
|
||||
char *name = fpath;
|
||||
char *next;
|
||||
int status;
|
||||
int type = FILETYPE_DIRECTORY;
|
||||
ext2fs_node_t currnode = currroot;
|
||||
ext2fs_node_t oldnode = currroot;
|
||||
|
||||
strncpy(fpath, currpath, strlen(currpath) + 1);
|
||||
|
||||
/* Remove all leading slashes. */
|
||||
while (*name == '/')
|
||||
name++;
|
||||
|
||||
if (!*name) {
|
||||
*currfound = currnode;
|
||||
return 1;
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
int found;
|
||||
|
||||
/* Extract the actual part from the pathname. */
|
||||
next = strchr(name, '/');
|
||||
if (next) {
|
||||
/* Remove all leading slashes. */
|
||||
while (*next == '/') {
|
||||
*(next++) = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/* At this point it is expected that the current node is a directory, check if this is true. */
|
||||
if (type != FILETYPE_DIRECTORY) {
|
||||
ext2fs_free_node(currnode, currroot);
|
||||
return(0);
|
||||
}
|
||||
|
||||
oldnode = currnode;
|
||||
|
||||
/* Iterate over the directory. */
|
||||
found = ext2fs_iterate_dir(currnode, name, &currnode, &type);
|
||||
if (found == 0)
|
||||
return(0);
|
||||
|
||||
if (found == -1)
|
||||
break;
|
||||
|
||||
/* Read in the symlink and follow it. */
|
||||
if (type == FILETYPE_SYMLINK) {
|
||||
char *symlink;
|
||||
|
||||
/* Test if the symlink does not loop. */
|
||||
if (++symlinknest == 8) {
|
||||
ext2fs_free_node(currnode, currroot);
|
||||
ext2fs_free_node(oldnode, currroot);
|
||||
return(0);
|
||||
}
|
||||
|
||||
symlink = ext2fs_read_symlink(currnode);
|
||||
ext2fs_free_node(currnode, currroot);
|
||||
|
||||
if (!symlink) {
|
||||
ext2fs_free_node(oldnode, currroot);
|
||||
return(0);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("Got symlink >%s<\n", symlink);
|
||||
#endif /* of DEBUG */
|
||||
/* The symlink is an absolute path, go back to the root inode. */
|
||||
if (symlink[0] == '/') {
|
||||
ext2fs_free_node(oldnode, currroot);
|
||||
oldnode = &ext2fs_root->diropen;
|
||||
}
|
||||
|
||||
/* Lookup the node the symlink points to. */
|
||||
status = ext2fs_find_file1(symlink, oldnode,
|
||||
&currnode, &type);
|
||||
|
||||
free(symlink);
|
||||
|
||||
if (status == 0) {
|
||||
ext2fs_free_node(oldnode, currroot);
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
ext2fs_free_node(oldnode, currroot);
|
||||
|
||||
/* Found the node! */
|
||||
if (!next || *next == '\0') {
|
||||
*currfound = currnode;
|
||||
*foundtype = type;
|
||||
return(1);
|
||||
}
|
||||
name = next;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int ext2fs_find_file
|
||||
(const char *path,
|
||||
ext2fs_node_t rootnode, ext2fs_node_t * foundnode, int expecttype) {
|
||||
int status;
|
||||
int foundtype = FILETYPE_DIRECTORY;
|
||||
|
||||
|
||||
symlinknest = 0;
|
||||
if (!path)
|
||||
return 0;
|
||||
|
||||
status = ext2fs_find_file1(path, rootnode, foundnode, &foundtype);
|
||||
if (status == 0)
|
||||
return 0;
|
||||
|
||||
/* Check if the node that was found was of the expected type. */
|
||||
if ((expecttype == FILETYPE_REG) &&(foundtype != expecttype)) {
|
||||
return 0;
|
||||
} else if ((expecttype == FILETYPE_DIRECTORY)
|
||||
&&(foundtype != expecttype)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int ext2fs_ls(char *dirname) {
|
||||
ext2fs_node_t dirnode;
|
||||
int status;
|
||||
|
||||
if (ext2fs_root == NULL)
|
||||
return 0;
|
||||
|
||||
status = ext2fs_find_file(dirname, &ext2fs_root->diropen, &dirnode,
|
||||
FILETYPE_DIRECTORY);
|
||||
if (status != 1) {
|
||||
puts("** Can not find directory. **\n");
|
||||
return 1;
|
||||
}
|
||||
ext2fs_iterate_dir(dirnode, NULL, NULL, NULL);
|
||||
ext2fs_free_node(dirnode, &ext2fs_root->diropen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int ext2fs_open(const char *filename) {
|
||||
ext2fs_node_t fdiro = NULL;
|
||||
int status;
|
||||
int len;
|
||||
int ret = -1;
|
||||
|
||||
if (ext2fs_root == NULL)
|
||||
goto fail;
|
||||
|
||||
ext2fs_file = NULL;
|
||||
status = ext2fs_find_file(filename, &ext2fs_root->diropen, &fdiro,
|
||||
FILETYPE_REG);
|
||||
if (status == 0) {
|
||||
ret = -2;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!fdiro->inode_read) {
|
||||
status = ext2fs_read_inode(fdiro->data, fdiro->ino,
|
||||
&fdiro->inode);
|
||||
if (status == 0) {
|
||||
ret = -3;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
len = __le32_to_cpu(fdiro->inode.size);
|
||||
ext2fs_file = fdiro;
|
||||
|
||||
return(len);
|
||||
|
||||
fail:
|
||||
ext2fs_free_node(fdiro, &ext2fs_root->diropen);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int ext2fs_close(void
|
||||
) {
|
||||
if ((ext2fs_file != NULL) &&(ext2fs_root != NULL)) {
|
||||
ext2fs_free_node(ext2fs_file, &ext2fs_root->diropen);
|
||||
ext2fs_file = NULL;
|
||||
}
|
||||
if (ext2fs_root != NULL) {
|
||||
free(ext2fs_root);
|
||||
ext2fs_root = NULL;
|
||||
}
|
||||
if (indir1_block != NULL) {
|
||||
free(indir1_block);
|
||||
indir1_block = NULL;
|
||||
indir1_size = 0;
|
||||
indir1_blkno = -1;
|
||||
}
|
||||
if (indir2_block != NULL) {
|
||||
free(indir2_block);
|
||||
indir2_block = NULL;
|
||||
indir2_size = 0;
|
||||
indir2_blkno = -1;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int ext2fs_read(char *buf, unsigned len) {
|
||||
int status;
|
||||
|
||||
if (ext2fs_root == NULL)
|
||||
return 0;
|
||||
|
||||
if (ext2fs_file == NULL)
|
||||
return 0;
|
||||
|
||||
status = ext2fs_read_file(ext2fs_file, 0, len, buf);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
int ext2fs_mount(void) {
|
||||
struct ext2_data *data;
|
||||
int status;
|
||||
|
||||
data = malloc(sizeof(struct ext2_data));
|
||||
if (!data)
|
||||
return 0;
|
||||
|
||||
/* Read the superblock. */
|
||||
status = ext2fs_devread(1 * 2, 0, 0, sizeof(struct ext2_sblock),
|
||||
(char *) &data->sblock);
|
||||
if (!status)
|
||||
goto fail;
|
||||
|
||||
/* Make sure this is an ext2 filesystem. */
|
||||
if (__le16_to_cpu(data->sblock.magic) != EXT2_MAGIC)
|
||||
goto fail;
|
||||
|
||||
if (__le32_to_cpu(data->sblock.revision_level) == EXT2_GOOD_OLD_REV)
|
||||
ext2_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
|
||||
else
|
||||
ext2_inode_size = __le16_to_cpu (data->sblock.inode_size);
|
||||
|
||||
data->diropen.data = data;
|
||||
data->diropen.ino = 2;
|
||||
data->diropen.inode_read = 1;
|
||||
data->inode = &data->diropen.inode;
|
||||
|
||||
status = ext2fs_read_inode(data, 2, data->inode);
|
||||
if (status == 0)
|
||||
goto fail;
|
||||
|
||||
ext2fs_root = data;
|
||||
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
puts("Failed to mount ext2 filesystem...\n");
|
||||
free(data);
|
||||
ext2fs_root = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
337
qiboot/src/io.h
Normal file
337
qiboot/src/io.h
Normal file
@ -0,0 +1,337 @@
|
||||
/*
|
||||
* linux/include/asm-arm/io.h
|
||||
*
|
||||
* Copyright (C) 1996-2000 Russell King
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Modifications:
|
||||
* 16-Sep-1996 RMK Inlined the inx/outx functions & optimised for both
|
||||
* constant addresses and variable addresses.
|
||||
* 04-Dec-1997 RMK Moved a lot of this stuff to the new architecture
|
||||
* specific IO header files.
|
||||
* 27-Mar-1999 PJB Second parameter of memcpy_toio is const..
|
||||
* 04-Apr-1999 PJB Added check_signature.
|
||||
* 12-Dec-1999 RMK More cleanups
|
||||
* 18-Jun-2000 RMK Removed virt_to_* and friends definitions
|
||||
*/
|
||||
#ifndef __ASM_ARM_IO_H
|
||||
#define __ASM_ARM_IO_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/memory.h>
|
||||
#if 0 /* XXX###XXX */
|
||||
#include <asm/arch/hardware.h>
|
||||
#endif /* XXX###XXX */
|
||||
|
||||
static inline void sync(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a physical address and a length, return a virtual address
|
||||
* that can be used to access the memory range with the caching
|
||||
* properties specified by "flags".
|
||||
*/
|
||||
typedef unsigned long phys_addr_t;
|
||||
|
||||
#define MAP_NOCACHE (0)
|
||||
#define MAP_WRCOMBINE (0)
|
||||
#define MAP_WRBACK (0)
|
||||
#define MAP_WRTHROUGH (0)
|
||||
|
||||
static inline void *
|
||||
map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)
|
||||
{
|
||||
return (void *)paddr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Take down a mapping set up by map_physmem().
|
||||
*/
|
||||
static inline void unmap_physmem(void *vaddr, unsigned long flags)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic virtual read/write. Note that we don't support half-word
|
||||
* read/writes. We define __arch_*[bl] here, and leave __arch_*w
|
||||
* to the architecture specific code.
|
||||
*/
|
||||
#define __arch_getb(a) (*(volatile unsigned char *)(a))
|
||||
#define __arch_getw(a) (*(volatile unsigned short *)(a))
|
||||
#define __arch_getl(a) (*(volatile unsigned int *)(a))
|
||||
|
||||
#define __arch_putb(v,a) (*(volatile unsigned char *)(a) = (v))
|
||||
#define __arch_putw(v,a) (*(volatile unsigned short *)(a) = (v))
|
||||
#define __arch_putl(v,a) (*(volatile unsigned int *)(a) = (v))
|
||||
|
||||
extern void __raw_writesb(unsigned int addr, const void *data, int bytelen);
|
||||
extern void __raw_writesw(unsigned int addr, const void *data, int wordlen);
|
||||
extern void __raw_writesl(unsigned int addr, const void *data, int longlen);
|
||||
|
||||
extern void __raw_readsb(unsigned int addr, void *data, int bytelen);
|
||||
extern void __raw_readsw(unsigned int addr, void *data, int wordlen);
|
||||
extern void __raw_readsl(unsigned int addr, void *data, int longlen);
|
||||
|
||||
#define __raw_writeb(v,a) __arch_putb(v,a)
|
||||
#define __raw_writew(v,a) __arch_putw(v,a)
|
||||
#define __raw_writel(v,a) __arch_putl(v,a)
|
||||
|
||||
#define __raw_readb(a) __arch_getb(a)
|
||||
#define __raw_readw(a) __arch_getw(a)
|
||||
#define __raw_readl(a) __arch_getl(a)
|
||||
|
||||
#define writeb(v,a) __arch_putb(v,a)
|
||||
#define writew(v,a) __arch_putw(v,a)
|
||||
#define writel(v,a) __arch_putl(v,a)
|
||||
|
||||
#define readb(a) __arch_getb(a)
|
||||
#define readw(a) __arch_getw(a)
|
||||
#define readl(a) __arch_getl(a)
|
||||
|
||||
/*
|
||||
* The compiler seems to be incapable of optimising constants
|
||||
* properly. Spell it out to the compiler in some cases.
|
||||
* These are only valid for small values of "off" (< 1<<12)
|
||||
*/
|
||||
#define __raw_base_writeb(val,base,off) __arch_base_putb(val,base,off)
|
||||
#define __raw_base_writew(val,base,off) __arch_base_putw(val,base,off)
|
||||
#define __raw_base_writel(val,base,off) __arch_base_putl(val,base,off)
|
||||
|
||||
#define __raw_base_readb(base,off) __arch_base_getb(base,off)
|
||||
#define __raw_base_readw(base,off) __arch_base_getw(base,off)
|
||||
#define __raw_base_readl(base,off) __arch_base_getl(base,off)
|
||||
|
||||
/*
|
||||
* Now, pick up the machine-defined IO definitions
|
||||
*/
|
||||
#if 0 /* XXX###XXX */
|
||||
#include <asm/arch/io.h>
|
||||
#endif /* XXX###XXX */
|
||||
|
||||
/*
|
||||
* IO port access primitives
|
||||
* -------------------------
|
||||
*
|
||||
* The ARM doesn't have special IO access instructions; all IO is memory
|
||||
* mapped. Note that these are defined to perform little endian accesses
|
||||
* only. Their primary purpose is to access PCI and ISA peripherals.
|
||||
*
|
||||
* Note that for a big endian machine, this implies that the following
|
||||
* big endian mode connectivity is in place, as described by numerious
|
||||
* ARM documents:
|
||||
*
|
||||
* PCI: D0-D7 D8-D15 D16-D23 D24-D31
|
||||
* ARM: D24-D31 D16-D23 D8-D15 D0-D7
|
||||
*
|
||||
* The machine specific io.h include defines __io to translate an "IO"
|
||||
* address to a memory address.
|
||||
*
|
||||
* Note that we prevent GCC re-ordering or caching values in expressions
|
||||
* by introducing sequence points into the in*() definitions. Note that
|
||||
* __raw_* do not guarantee this behaviour.
|
||||
*
|
||||
* The {in,out}[bwl] macros are for emulating x86-style PCI/ISA IO space.
|
||||
*/
|
||||
#ifdef __io
|
||||
#define outb(v,p) __raw_writeb(v,__io(p))
|
||||
#define outw(v,p) __raw_writew(cpu_to_le16(v),__io(p))
|
||||
#define outl(v,p) __raw_writel(cpu_to_le32(v),__io(p))
|
||||
|
||||
#define inb(p) ({ unsigned int __v = __raw_readb(__io(p)); __v; })
|
||||
#define inw(p) ({ unsigned int __v = le16_to_cpu(__raw_readw(__io(p))); __v; })
|
||||
#define inl(p) ({ unsigned int __v = le32_to_cpu(__raw_readl(__io(p))); __v; })
|
||||
|
||||
#define outsb(p,d,l) __raw_writesb(__io(p),d,l)
|
||||
#define outsw(p,d,l) __raw_writesw(__io(p),d,l)
|
||||
#define outsl(p,d,l) __raw_writesl(__io(p),d,l)
|
||||
|
||||
#define insb(p,d,l) __raw_readsb(__io(p),d,l)
|
||||
#define insw(p,d,l) __raw_readsw(__io(p),d,l)
|
||||
#define insl(p,d,l) __raw_readsl(__io(p),d,l)
|
||||
#endif
|
||||
|
||||
#define outb_p(val,port) outb((val),(port))
|
||||
#define outw_p(val,port) outw((val),(port))
|
||||
#define outl_p(val,port) outl((val),(port))
|
||||
#define inb_p(port) inb((port))
|
||||
#define inw_p(port) inw((port))
|
||||
#define inl_p(port) inl((port))
|
||||
|
||||
#define outsb_p(port,from,len) outsb(port,from,len)
|
||||
#define outsw_p(port,from,len) outsw(port,from,len)
|
||||
#define outsl_p(port,from,len) outsl(port,from,len)
|
||||
#define insb_p(port,to,len) insb(port,to,len)
|
||||
#define insw_p(port,to,len) insw(port,to,len)
|
||||
#define insl_p(port,to,len) insl(port,to,len)
|
||||
|
||||
/*
|
||||
* ioremap and friends.
|
||||
*
|
||||
* ioremap takes a PCI memory address, as specified in
|
||||
* linux/Documentation/IO-mapping.txt. If you want a
|
||||
* physical address, use __ioremap instead.
|
||||
*/
|
||||
extern void * __ioremap(unsigned long offset, size_t size, unsigned long flags);
|
||||
extern void __iounmap(void *addr);
|
||||
|
||||
/*
|
||||
* Generic ioremap support.
|
||||
*
|
||||
* Define:
|
||||
* iomem_valid_addr(off,size)
|
||||
* iomem_to_phys(off)
|
||||
*/
|
||||
#ifdef iomem_valid_addr
|
||||
#define __arch_ioremap(off,sz,nocache) \
|
||||
({ \
|
||||
unsigned long _off = (off), _size = (sz); \
|
||||
void *_ret = (void *)0; \
|
||||
if (iomem_valid_addr(_off, _size)) \
|
||||
_ret = __ioremap(iomem_to_phys(_off),_size,0); \
|
||||
_ret; \
|
||||
})
|
||||
|
||||
#define __arch_iounmap __iounmap
|
||||
#endif
|
||||
|
||||
#define ioremap(off,sz) __arch_ioremap((off),(sz),0)
|
||||
#define ioremap_nocache(off,sz) __arch_ioremap((off),(sz),1)
|
||||
#define iounmap(_addr) __arch_iounmap(_addr)
|
||||
|
||||
/*
|
||||
* DMA-consistent mapping functions. These allocate/free a region of
|
||||
* uncached, unwrite-buffered mapped memory space for use with DMA
|
||||
* devices. This is the "generic" version. The PCI specific version
|
||||
* is in pci.h
|
||||
*/
|
||||
extern void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle);
|
||||
extern void consistent_free(void *vaddr, size_t size, dma_addr_t handle);
|
||||
extern void consistent_sync(void *vaddr, size_t size, int rw);
|
||||
|
||||
/*
|
||||
* String version of IO memory access ops:
|
||||
*/
|
||||
extern void _memcpy_fromio(void *, unsigned long, size_t);
|
||||
extern void _memcpy_toio(unsigned long, const void *, size_t);
|
||||
extern void _memset_io(unsigned long, int, size_t);
|
||||
|
||||
extern void __readwrite_bug(const char *fn);
|
||||
|
||||
/*
|
||||
* If this architecture has PCI memory IO, then define the read/write
|
||||
* macros. These should only be used with the cookie passed from
|
||||
* ioremap.
|
||||
*/
|
||||
#ifdef __mem_pci
|
||||
|
||||
#define readb(c) ({ unsigned int __v = __raw_readb(__mem_pci(c)); __v; })
|
||||
#define readw(c) ({ unsigned int __v = le16_to_cpu(__raw_readw(__mem_pci(c))); __v; })
|
||||
#define readl(c) ({ unsigned int __v = le32_to_cpu(__raw_readl(__mem_pci(c))); __v; })
|
||||
|
||||
#define writeb(v,c) __raw_writeb(v,__mem_pci(c))
|
||||
#define writew(v,c) __raw_writew(cpu_to_le16(v),__mem_pci(c))
|
||||
#define writel(v,c) __raw_writel(cpu_to_le32(v),__mem_pci(c))
|
||||
|
||||
#define memset_io(c,v,l) _memset_io(__mem_pci(c),(v),(l))
|
||||
#define memcpy_fromio(a,c,l) _memcpy_fromio((a),__mem_pci(c),(l))
|
||||
#define memcpy_toio(c,a,l) _memcpy_toio(__mem_pci(c),(a),(l))
|
||||
|
||||
#define eth_io_copy_and_sum(s,c,l,b) \
|
||||
eth_copy_and_sum((s),__mem_pci(c),(l),(b))
|
||||
|
||||
static inline int
|
||||
check_signature(unsigned long io_addr, const unsigned char *signature,
|
||||
int length)
|
||||
{
|
||||
int retval = 0;
|
||||
do {
|
||||
if (readb(io_addr) != *signature)
|
||||
goto out;
|
||||
io_addr++;
|
||||
signature++;
|
||||
length--;
|
||||
} while (length);
|
||||
retval = 1;
|
||||
out:
|
||||
return retval;
|
||||
}
|
||||
|
||||
#elif !defined(readb)
|
||||
|
||||
#define readb(addr) (__readwrite_bug("readb"),0)
|
||||
#define readw(addr) (__readwrite_bug("readw"),0)
|
||||
#define readl(addr) (__readwrite_bug("readl"),0)
|
||||
#define writeb(v,addr) __readwrite_bug("writeb")
|
||||
#define writew(v,addr) __readwrite_bug("writew")
|
||||
#define writel(v,addr) __readwrite_bug("writel")
|
||||
|
||||
#define eth_io_copy_and_sum(a,b,c,d) __readwrite_bug("eth_io_copy_and_sum")
|
||||
|
||||
#define check_signature(io,sig,len) (0)
|
||||
|
||||
#endif /* __mem_pci */
|
||||
|
||||
/*
|
||||
* If this architecture has ISA IO, then define the isa_read/isa_write
|
||||
* macros.
|
||||
*/
|
||||
#ifdef __mem_isa
|
||||
|
||||
#define isa_readb(addr) __raw_readb(__mem_isa(addr))
|
||||
#define isa_readw(addr) __raw_readw(__mem_isa(addr))
|
||||
#define isa_readl(addr) __raw_readl(__mem_isa(addr))
|
||||
#define isa_writeb(val,addr) __raw_writeb(val,__mem_isa(addr))
|
||||
#define isa_writew(val,addr) __raw_writew(val,__mem_isa(addr))
|
||||
#define isa_writel(val,addr) __raw_writel(val,__mem_isa(addr))
|
||||
#define isa_memset_io(a,b,c) _memset_io(__mem_isa(a),(b),(c))
|
||||
#define isa_memcpy_fromio(a,b,c) _memcpy_fromio((a),__mem_isa(b),(c))
|
||||
#define isa_memcpy_toio(a,b,c) _memcpy_toio(__mem_isa((a)),(b),(c))
|
||||
|
||||
#define isa_eth_io_copy_and_sum(a,b,c,d) \
|
||||
eth_copy_and_sum((a),__mem_isa(b),(c),(d))
|
||||
|
||||
static inline int
|
||||
isa_check_signature(unsigned long io_addr, const unsigned char *signature,
|
||||
int length)
|
||||
{
|
||||
int retval = 0;
|
||||
do {
|
||||
if (isa_readb(io_addr) != *signature)
|
||||
goto out;
|
||||
io_addr++;
|
||||
signature++;
|
||||
length--;
|
||||
} while (length);
|
||||
retval = 1;
|
||||
out:
|
||||
return retval;
|
||||
}
|
||||
|
||||
#else /* __mem_isa */
|
||||
|
||||
#define isa_readb(addr) (__readwrite_bug("isa_readb"),0)
|
||||
#define isa_readw(addr) (__readwrite_bug("isa_readw"),0)
|
||||
#define isa_readl(addr) (__readwrite_bug("isa_readl"),0)
|
||||
#define isa_writeb(val,addr) __readwrite_bug("isa_writeb")
|
||||
#define isa_writew(val,addr) __readwrite_bug("isa_writew")
|
||||
#define isa_writel(val,addr) __readwrite_bug("isa_writel")
|
||||
#define isa_memset_io(a,b,c) __readwrite_bug("isa_memset_io")
|
||||
#define isa_memcpy_fromio(a,b,c) __readwrite_bug("isa_memcpy_fromio")
|
||||
#define isa_memcpy_toio(a,b,c) __readwrite_bug("isa_memcpy_toio")
|
||||
|
||||
#define isa_eth_io_copy_and_sum(a,b,c,d) \
|
||||
__readwrite_bug("isa_eth_io_copy_and_sum")
|
||||
|
||||
#define isa_check_signature(io,sig,len) (0)
|
||||
|
||||
#endif /* __mem_isa */
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* __ASM_ARM_IO_H */
|
145
qiboot/src/memory-test.c
Normal file
145
qiboot/src/memory-test.c
Normal file
@ -0,0 +1,145 @@
|
||||
#include <qi.h>
|
||||
#include <string.h>
|
||||
|
||||
int memory_test_const32(void * start, unsigned int length, u32 value)
|
||||
{
|
||||
int errors = 0;
|
||||
u32 * p = (u32 *)start;
|
||||
u32 * pend = (u32 *)(start + length);
|
||||
int count = length >> 2;
|
||||
|
||||
puts(".");
|
||||
|
||||
while (p < pend)
|
||||
*p++ = value;
|
||||
|
||||
p = (u32 *)start;
|
||||
count = length >> 2;
|
||||
|
||||
while (count--)
|
||||
if (*p++ != value) {
|
||||
puts("*** Error ");
|
||||
print32((long)p - 4);
|
||||
errors++;
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int memory_test_ads(void * start, unsigned int length, u32 mask)
|
||||
{
|
||||
int errors = 0;
|
||||
u32 * p = (u32 *)start;
|
||||
u32 * pend = (u32 *)(start + length);
|
||||
|
||||
puts(".");
|
||||
|
||||
while (p < pend)
|
||||
if ((u32)p & mask)
|
||||
*p++ = 0xffffffff;
|
||||
else
|
||||
*p++ = 0;
|
||||
|
||||
p = (u32 *)start;
|
||||
|
||||
while (p < pend) {
|
||||
if ((u32)p & mask) {
|
||||
if (*p++ != 0xffffffff) {
|
||||
puts("*** Error ");
|
||||
print32((long)p - 4);
|
||||
errors++;
|
||||
}
|
||||
} else {
|
||||
if (*p++) {
|
||||
puts("*** Error ");
|
||||
print32((long)p - 4);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
int memory_test_walking1(void * start, unsigned int length)
|
||||
{
|
||||
int errors = 0;
|
||||
u32 value = 1;
|
||||
|
||||
while (value) {
|
||||
errors += memory_test_const32(start, length, value);
|
||||
value <<= 1;
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
/* negative runs == run forever */
|
||||
|
||||
void __memory_test(void * start, unsigned int length)
|
||||
{
|
||||
int errors = 0;
|
||||
int series = 0;
|
||||
int mask;
|
||||
|
||||
puts("\nMemory Testing 0x");
|
||||
print32((u32)start);
|
||||
puts(" length ");
|
||||
printdec(length >> 20);
|
||||
puts(" MB\n");
|
||||
|
||||
while (1) {
|
||||
puts(" Test series ");
|
||||
printdec(series + 1);
|
||||
puts(" ");
|
||||
|
||||
/* these are looking at data issues, they flood the whole
|
||||
* array with the same data
|
||||
*/
|
||||
|
||||
errors += memory_test_const32(start, length, 0x55555555);
|
||||
errors += memory_test_const32(start, length, 0xaaaaaaaa);
|
||||
errors += memory_test_const32(start, length, 0x55aa55aa);
|
||||
errors += memory_test_const32(start, length, 0xaa55aa55);
|
||||
errors += memory_test_const32(start, length, 0x00ff00ff);
|
||||
errors += memory_test_const32(start, length, 0xff00ff00);
|
||||
errors += memory_test_walking1(start, length);
|
||||
|
||||
/* this is looking at addressing issues, it floods only
|
||||
* addresses meeting a walking mask with 0xffffffff (the rest
|
||||
* is zeroed), and makes sure all the bits are only seen where
|
||||
* they were placed
|
||||
*/
|
||||
|
||||
mask = 1;
|
||||
while (! (length & mask)) {
|
||||
errors += memory_test_ads(start, length, mask);
|
||||
mask = mask << 1;
|
||||
}
|
||||
|
||||
puts(" Total errors: ");
|
||||
printdec(errors);
|
||||
puts("\n");
|
||||
|
||||
series++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void memory_test(void * start, unsigned int length)
|
||||
{
|
||||
/* it's a small steppingstone stack from start.S */
|
||||
extern int _ss_stack;
|
||||
|
||||
/*
|
||||
* we won't be coming back from this, so just force our local stack to
|
||||
* steppingstone out of the way of main memory test action
|
||||
*
|
||||
* then jump into the actual test
|
||||
*/
|
||||
asm volatile (
|
||||
"mov sp, %0\n"
|
||||
: : "r" (&_ss_stack)
|
||||
);
|
||||
|
||||
__memory_test(start, length);
|
||||
}
|
138
qiboot/src/part.h
Normal file
138
qiboot/src/part.h
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* (C) Copyright 2000-2004
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef _PART_H
|
||||
#define _PART_H
|
||||
|
||||
#include <ide.h>
|
||||
|
||||
typedef struct block_dev_desc {
|
||||
int if_type; /* type of the interface */
|
||||
int dev; /* device number */
|
||||
unsigned char part_type; /* partition type */
|
||||
unsigned char target; /* target SCSI ID */
|
||||
unsigned char lun; /* target LUN */
|
||||
unsigned char type; /* device type */
|
||||
unsigned char removable; /* removable device */
|
||||
#ifdef CONFIG_LBA48
|
||||
unsigned char lba48; /* device can use 48bit addr (ATA/ATAPI v7) */
|
||||
#endif
|
||||
lbaint_t lba; /* number of blocks */
|
||||
unsigned long blksz; /* block size */
|
||||
char vendor [40+1]; /* IDE model, SCSI Vendor */
|
||||
char product[20+1]; /* IDE Serial no, SCSI product */
|
||||
char revision[8+1]; /* firmware revision */
|
||||
unsigned long (*block_read)(int dev,
|
||||
unsigned long start,
|
||||
lbaint_t blkcnt,
|
||||
void *buffer);
|
||||
unsigned long (*block_write)(int dev,
|
||||
unsigned long start,
|
||||
lbaint_t blkcnt,
|
||||
const void *buffer);
|
||||
void *priv; /* driver private struct pointer */
|
||||
}block_dev_desc_t;
|
||||
|
||||
/* Interface types: */
|
||||
#define IF_TYPE_UNKNOWN 0
|
||||
#define IF_TYPE_IDE 1
|
||||
#define IF_TYPE_SCSI 2
|
||||
#define IF_TYPE_ATAPI 3
|
||||
#define IF_TYPE_USB 4
|
||||
#define IF_TYPE_DOC 5
|
||||
#define IF_TYPE_MMC 6
|
||||
#define IF_TYPE_SD 7
|
||||
#define IF_TYPE_SATA 8
|
||||
|
||||
/* Part types */
|
||||
#define PART_TYPE_UNKNOWN 0x00
|
||||
#define PART_TYPE_MAC 0x01
|
||||
#define PART_TYPE_DOS 0x02
|
||||
#define PART_TYPE_ISO 0x03
|
||||
#define PART_TYPE_AMIGA 0x04
|
||||
|
||||
/*
|
||||
* Type string for U-Boot bootable partitions
|
||||
*/
|
||||
#define BOOT_PART_TYPE "U-Boot" /* primary boot partition type */
|
||||
#define BOOT_PART_COMP "PPCBoot" /* PPCBoot compatibility type */
|
||||
|
||||
/* device types */
|
||||
#define DEV_TYPE_UNKNOWN 0xff /* not connected */
|
||||
#define DEV_TYPE_HARDDISK 0x00 /* harddisk */
|
||||
#define DEV_TYPE_TAPE 0x01 /* Tape */
|
||||
#define DEV_TYPE_CDROM 0x05 /* CD-ROM */
|
||||
#define DEV_TYPE_OPDISK 0x07 /* optical disk */
|
||||
|
||||
typedef struct disk_partition {
|
||||
ulong start; /* # of first block in partition */
|
||||
ulong size; /* number of blocks in partition */
|
||||
ulong blksz; /* block size in bytes */
|
||||
uchar name[32]; /* partition name */
|
||||
uchar type[32]; /* string type description */
|
||||
} disk_partition_t;
|
||||
|
||||
/* Misc _get_dev functions */
|
||||
block_dev_desc_t* get_dev(char* ifname, int dev);
|
||||
block_dev_desc_t* ide_get_dev(int dev);
|
||||
block_dev_desc_t* sata_get_dev(int dev);
|
||||
block_dev_desc_t* scsi_get_dev(int dev);
|
||||
block_dev_desc_t* usb_stor_get_dev(int dev);
|
||||
block_dev_desc_t* mmc_get_dev(int dev);
|
||||
block_dev_desc_t* systemace_get_dev(int dev);
|
||||
|
||||
/* disk/part.c */
|
||||
int get_partition_info (block_dev_desc_t * dev_desc, int part, disk_partition_t *info);
|
||||
void print_part (block_dev_desc_t *dev_desc);
|
||||
void init_part (block_dev_desc_t *dev_desc);
|
||||
void dev_print(block_dev_desc_t *dev_desc);
|
||||
|
||||
|
||||
#ifdef CONFIG_MAC_PARTITION
|
||||
/* disk/part_mac.c */
|
||||
int get_partition_info_mac (block_dev_desc_t * dev_desc, int part, disk_partition_t *info);
|
||||
void print_part_mac (block_dev_desc_t *dev_desc);
|
||||
int test_part_mac (block_dev_desc_t *dev_desc);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DOS_PARTITION
|
||||
/* disk/part_dos.c */
|
||||
int get_partition_info_dos (block_dev_desc_t * dev_desc, int part, disk_partition_t *info);
|
||||
void print_part_dos (block_dev_desc_t *dev_desc);
|
||||
int test_part_dos (block_dev_desc_t *dev_desc);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ISO_PARTITION
|
||||
/* disk/part_iso.c */
|
||||
int get_partition_info_iso (block_dev_desc_t * dev_desc, int part, disk_partition_t *info);
|
||||
void print_part_iso (block_dev_desc_t *dev_desc);
|
||||
int test_part_iso (block_dev_desc_t *dev_desc);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AMIGA_PARTITION
|
||||
/* disk/part_amiga.c */
|
||||
int get_partition_info_amiga (block_dev_desc_t * dev_desc, int part, disk_partition_t *info);
|
||||
void print_part_amiga (block_dev_desc_t *dev_desc);
|
||||
int test_part_amiga (block_dev_desc_t *dev_desc);
|
||||
#endif
|
||||
|
||||
#endif /* _PART_H */
|
495
qiboot/src/phase2.c
Normal file
495
qiboot/src/phase2.c
Normal file
@ -0,0 +1,495 @@
|
||||
/*
|
||||
* (C) Copyright 2008 Openmoko, Inc.
|
||||
* Author: Andy Green <andy@openmoko.org>
|
||||
*
|
||||
* Parse the U-Boot header and Boot Linux
|
||||
* based on various code from U-Boot
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <qi.h>
|
||||
#include <neo_gta02.h>
|
||||
#include "blink_led.h"
|
||||
#include <string.h>
|
||||
#define __ARM__
|
||||
#include <image.h>
|
||||
#include <setup.h>
|
||||
#include <ext2.h>
|
||||
|
||||
|
||||
typedef void (*the_kernel_fn)(int zero, int arch, uint params);
|
||||
|
||||
unsigned long partition_offset_blocks = 0;
|
||||
unsigned long partition_length_blocks = 0;
|
||||
|
||||
struct kernel_source const * this_kernel = 0;
|
||||
|
||||
static const int INITRD_OFFSET = (8 * 1024 * 1024);
|
||||
|
||||
|
||||
int raise(int n)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void indicate(enum ui_indication ui_indication)
|
||||
{
|
||||
if (this_board->set_ui_indication)
|
||||
(this_board->set_ui_indication)(ui_indication);
|
||||
}
|
||||
|
||||
static int read_file(const char * filepath, u8 * destination, int size)
|
||||
{
|
||||
int len = size;
|
||||
int ret;
|
||||
|
||||
switch (this_kernel->filesystem) {
|
||||
case FS_EXT2:
|
||||
if (!ext2fs_mount()) {
|
||||
puts("Unable to mount ext2 filesystem\n");
|
||||
indicate(UI_IND_MOUNT_FAIL);
|
||||
return -2; /* death */
|
||||
}
|
||||
puts(" EXT2 open: ");
|
||||
puts(filepath);
|
||||
len = ext2fs_open(filepath);
|
||||
if (len < 0) {
|
||||
puts(" Open failed\n");
|
||||
return -1;
|
||||
}
|
||||
puts(" OK\n");
|
||||
ret = ext2fs_read((char *)destination, size);
|
||||
if (ret < 0) {
|
||||
puts(" Read failed\n");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case FS_FAT:
|
||||
/* FIXME */
|
||||
case FS_RAW:
|
||||
/* any filename-related request in raw filesystem will fail */
|
||||
if (filepath)
|
||||
return -1;
|
||||
puts(" RAW open: +");
|
||||
printdec(partition_offset_blocks);
|
||||
puts(" 512-byte blocks\n");
|
||||
if (this_kernel->block_read(destination,
|
||||
partition_offset_blocks, size >> 9) < 0) {
|
||||
puts("Bad kernel header\n");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int do_block_init(void)
|
||||
{
|
||||
static void * last_block_init = NULL;
|
||||
static int last_block_init_result = 0;
|
||||
int fresh = 0;
|
||||
|
||||
/* if this device needs initializing, try to init it */
|
||||
if (!this_kernel->block_init)
|
||||
return 1; /* happy */
|
||||
|
||||
/*
|
||||
* cache result to limit attempts for same
|
||||
* block device to one time
|
||||
*/
|
||||
if (this_kernel->block_init != last_block_init) {
|
||||
last_block_init = this_kernel->block_init;
|
||||
last_block_init_result = (this_kernel->block_init)();
|
||||
fresh = 1;
|
||||
}
|
||||
|
||||
if (last_block_init_result) {
|
||||
puts("block device init failed\n");
|
||||
if (fresh)
|
||||
indicate(UI_IND_MOUNT_FAIL);
|
||||
|
||||
return 0; /* failed */
|
||||
}
|
||||
last_block_init = this_kernel->block_init;
|
||||
|
||||
return 1; /* happy */
|
||||
}
|
||||
|
||||
static int do_partitions(void *kernel_dram)
|
||||
{
|
||||
unsigned char *p = kernel_dram;
|
||||
|
||||
/* if there's a partition table implied, parse it, otherwise
|
||||
* just use a fixed offset
|
||||
*/
|
||||
if (!this_kernel->partition_index) {
|
||||
partition_offset_blocks =
|
||||
this_kernel->offset_blocks512_if_no_partition;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((int)this_kernel->block_read(kernel_dram, 0, 4) < 0) {
|
||||
puts("Bad partition read\n");
|
||||
indicate(UI_IND_MOUNT_FAIL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((p[0x1fe] != 0x55) || (p[0x1ff] != 0xaa)) {
|
||||
puts("partition signature missing\n");
|
||||
indicate(UI_IND_MOUNT_FAIL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
p += 0x1be + 8 + (0x10 * (this_kernel->partition_index - 1));
|
||||
|
||||
partition_offset_blocks = (((u32)p[3]) << 24) |
|
||||
(((u32)p[2]) << 16) |
|
||||
(((u32)p[1]) << 8) |
|
||||
p[0];
|
||||
partition_length_blocks = (((u32)p[7]) << 24) |
|
||||
(((u32)p[6]) << 16) |
|
||||
(((u32)p[5]) << 8) |
|
||||
p[4];
|
||||
|
||||
puts(" Partition: ");
|
||||
printdec(this_kernel->partition_index);
|
||||
puts(" start +");
|
||||
printdec(partition_offset_blocks);
|
||||
puts(" 512-byte blocks, size ");
|
||||
printdec(partition_length_blocks / 2048);
|
||||
puts(" MiB\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void do_params(unsigned initramfs_len,
|
||||
const char *commandline_rootfs_append)
|
||||
{
|
||||
const struct board_variant * board_variant =
|
||||
(this_board->get_board_variant)();
|
||||
const char *p;
|
||||
char * cmdline;
|
||||
struct tag *params = (struct tag *)this_board->linux_tag_placement;
|
||||
|
||||
/* eat leading white space */
|
||||
for (p = this_board->commandline_board; *p == ' '; p++);
|
||||
|
||||
/* first tag */
|
||||
params->hdr.tag = ATAG_CORE;
|
||||
params->hdr.size = tag_size(tag_core);
|
||||
params->u.core.flags = 0;
|
||||
params->u.core.pagesize = 0;
|
||||
params->u.core.rootdev = 0;
|
||||
params = tag_next(params);
|
||||
|
||||
/* revision tag */
|
||||
params->hdr.tag = ATAG_REVISION;
|
||||
params->hdr.size = tag_size(tag_revision);
|
||||
params->u.revision.rev = board_variant->machine_revision;
|
||||
params = tag_next(params);
|
||||
|
||||
/* memory tags */
|
||||
params->hdr.tag = ATAG_MEM;
|
||||
params->hdr.size = tag_size(tag_mem32);
|
||||
params->u.mem.start = this_board->linux_mem_start;
|
||||
params->u.mem.size = this_board->linux_mem_size;
|
||||
params = tag_next(params);
|
||||
|
||||
if (this_kernel->initramfs_filepath) {
|
||||
/* INITRD2 tag */
|
||||
params->hdr.tag = ATAG_INITRD2;
|
||||
params->hdr.size = tag_size(tag_initrd);
|
||||
params->u.initrd.start = this_board->linux_mem_start +
|
||||
INITRD_OFFSET;
|
||||
params->u.initrd.size = initramfs_len;
|
||||
params = tag_next(params);
|
||||
}
|
||||
|
||||
/* kernel commandline */
|
||||
|
||||
cmdline = params->u.cmdline.cmdline;
|
||||
|
||||
/* start with the fixed device part of the commandline */
|
||||
|
||||
cmdline += strlen(strcpy(cmdline, p));
|
||||
|
||||
/* if the board itself needs a computed commandline, add it now */
|
||||
|
||||
if (this_board->append_device_specific_cmdline)
|
||||
cmdline = (this_board->append_device_specific_cmdline)(cmdline);
|
||||
|
||||
/* If he is giving an append commandline for this rootfs, apply that */
|
||||
|
||||
if (this_kernel->commandline_append)
|
||||
cmdline += strlen(strcpy(cmdline,
|
||||
this_kernel->commandline_append));
|
||||
if (commandline_rootfs_append[0])
|
||||
cmdline += strlen(strcpy(cmdline,
|
||||
commandline_rootfs_append));
|
||||
|
||||
/* deal with any trailing newlines that hitched a ride */
|
||||
|
||||
while (*(cmdline - 1) == '\n')
|
||||
cmdline--;
|
||||
|
||||
*cmdline = '\0';
|
||||
|
||||
/*
|
||||
* if he's still holding down the UI_ACTION_SKIPKERNEL key
|
||||
* now we finished loading the kernel, take it to mean he wants
|
||||
* to have the debugging options added to the commandline
|
||||
*/
|
||||
|
||||
if (this_board->commandline_board_debug && this_board->get_ui_debug)
|
||||
if ((this_board->get_ui_debug)())
|
||||
cmdline += strlen(strcpy(cmdline, this_board->
|
||||
commandline_board_debug));
|
||||
|
||||
params->hdr.tag = ATAG_CMDLINE;
|
||||
params->hdr.size = (sizeof(struct tag_header) +
|
||||
strlen(params->u.cmdline.cmdline) + 1 + 4) >> 2;
|
||||
|
||||
puts(" Cmdline: ");
|
||||
puts(params->u.cmdline.cmdline);
|
||||
puts("\n");
|
||||
|
||||
params = tag_next(params);
|
||||
|
||||
/* needs to always be the last tag */
|
||||
params->hdr.tag = ATAG_NONE;
|
||||
params->hdr.size = 0;
|
||||
}
|
||||
|
||||
static int do_crc(const image_header_t *hdr, const void *kernel_dram)
|
||||
{
|
||||
unsigned long crc;
|
||||
|
||||
/*
|
||||
* It's good for now to know that our kernel is intact from
|
||||
* the storage before we jump into it and maybe crash silently
|
||||
* even though it costs us some time
|
||||
*/
|
||||
crc = crc32(0, kernel_dram + sizeof(image_header_t),
|
||||
__be32_to_cpu(hdr->ih_size));
|
||||
if (crc == __be32_to_cpu(hdr->ih_dcrc))
|
||||
return 1;
|
||||
|
||||
puts("\nKernel CRC ERROR: read 0x");
|
||||
print32(crc);
|
||||
puts(" vs hdr CRC 0x");
|
||||
print32(__be32_to_cpu(hdr->ih_dcrc));
|
||||
puts("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static the_kernel_fn load_uimage(void *kernel_dram)
|
||||
{
|
||||
image_header_t *hdr;
|
||||
u32 kernel_size;
|
||||
|
||||
hdr = (image_header_t *)kernel_dram;
|
||||
|
||||
if (__be32_to_cpu(hdr->ih_magic) != IH_MAGIC) {
|
||||
puts("bad magic ");
|
||||
print32(hdr->ih_magic);
|
||||
puts("\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
puts(" Found: \"");
|
||||
puts((const char *)hdr->ih_name);
|
||||
puts("\"\n Size: ");
|
||||
printdec(__be32_to_cpu(hdr->ih_size) >> 10);
|
||||
puts(" KiB\n");
|
||||
|
||||
kernel_size = ((__be32_to_cpu(hdr->ih_size) +
|
||||
sizeof(image_header_t) + 2048) & ~(2048 - 1));
|
||||
|
||||
if (read_file(this_kernel->filepath, kernel_dram, kernel_size) < 0) {
|
||||
indicate(UI_IND_KERNEL_PULL_FAIL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
indicate(UI_IND_KERNEL_PULL_OK);
|
||||
|
||||
if (!do_crc(hdr, kernel_dram))
|
||||
return NULL;
|
||||
|
||||
return (the_kernel_fn) (((char *)hdr) + sizeof(image_header_t));
|
||||
}
|
||||
|
||||
static the_kernel_fn load_zimage(void *kernel_dram)
|
||||
{
|
||||
u32 magic = *(u32 *) (kernel_dram + 0x24);
|
||||
u32 size = *(u32 *) (kernel_dram + 0x2c);
|
||||
int got;
|
||||
|
||||
if (magic != 0x016f2818) {
|
||||
puts("bad magic ");
|
||||
print32(magic);
|
||||
puts("\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
puts(" Size: ");
|
||||
printdec(size >> 10);
|
||||
puts(" KiB\n");
|
||||
|
||||
got = read_file(this_kernel->filepath, kernel_dram, size);
|
||||
if (got < 0) {
|
||||
indicate(UI_IND_KERNEL_PULL_FAIL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (got != size) {
|
||||
puts("short kernel\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
indicate(UI_IND_KERNEL_PULL_OK);
|
||||
|
||||
return (the_kernel_fn) kernel_dram;
|
||||
}
|
||||
|
||||
static void try_this_kernel(void)
|
||||
{
|
||||
the_kernel_fn the_kernel;
|
||||
unsigned int initramfs_len = 0;
|
||||
static char commandline_rootfs_append[512] = "";
|
||||
int ret;
|
||||
void * kernel_dram = (void *)this_board->linux_mem_start + 0x8000;
|
||||
|
||||
partition_offset_blocks = 0;
|
||||
partition_length_blocks = 0;
|
||||
|
||||
puts("\nTrying kernel: ");
|
||||
puts(this_kernel->name);
|
||||
puts("\n");
|
||||
|
||||
indicate(UI_IND_MOUNT_PART);
|
||||
|
||||
if (!do_block_init())
|
||||
return;
|
||||
|
||||
if (!do_partitions(kernel_dram))
|
||||
return;
|
||||
|
||||
/* does he want us to skip this? */
|
||||
|
||||
ret = read_file(this_board->noboot, kernel_dram, 512);
|
||||
if (ret != -1) {
|
||||
/* -2 (mount fail) should make us give up too */
|
||||
if (ret >= 0) {
|
||||
puts(" (Skipping on finding ");
|
||||
puts(this_board->noboot);
|
||||
puts(")\n");
|
||||
indicate(UI_IND_SKIPPING);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* is there a commandline append file? */
|
||||
|
||||
commandline_rootfs_append[0] = '\0';
|
||||
read_file(this_board->append, (u8 *)commandline_rootfs_append, 512);
|
||||
|
||||
indicate(UI_IND_KERNEL_PULL);
|
||||
|
||||
/* pull the kernel image */
|
||||
|
||||
if (read_file(this_kernel->filepath, kernel_dram, 4096) < 0)
|
||||
return;
|
||||
|
||||
the_kernel = load_uimage(kernel_dram);
|
||||
if (!the_kernel)
|
||||
the_kernel = load_zimage(kernel_dram);
|
||||
if (!the_kernel)
|
||||
return;
|
||||
|
||||
/* initramfs if needed */
|
||||
|
||||
if (this_kernel->initramfs_filepath) {
|
||||
indicate(UI_IND_INITRAMFS_PULL);
|
||||
initramfs_len = read_file(this_kernel->initramfs_filepath,
|
||||
(u8 *)this_board->linux_mem_start + INITRD_OFFSET,
|
||||
16 * 1024 * 1024);
|
||||
if (initramfs_len < 0) {
|
||||
puts("initramfs load failed\n");
|
||||
indicate(UI_IND_INITRAMFS_PULL_FAIL);
|
||||
return;
|
||||
}
|
||||
indicate(UI_IND_INITRAMFS_PULL_OK);
|
||||
}
|
||||
|
||||
do_params(initramfs_len, commandline_rootfs_append);
|
||||
|
||||
/* give board implementation a chance to shut down
|
||||
* anything it may have going on, leave GPIO set for Linux
|
||||
*/
|
||||
if (this_board->close)
|
||||
(this_board->close)();
|
||||
|
||||
puts("Starting --->\n\n");
|
||||
indicate(UI_IND_KERNEL_START);
|
||||
|
||||
/*
|
||||
* ooh that's it, we're gonna try boot this image!
|
||||
* never mind the cache, Linux will take care of it
|
||||
*/
|
||||
the_kernel(0, this_board->linux_machine_id,
|
||||
this_board->linux_tag_placement);
|
||||
|
||||
/* we won't come back here no matter what */
|
||||
}
|
||||
|
||||
void bootloader_second_phase(void)
|
||||
{
|
||||
/* give device a chance to print device-specific things */
|
||||
|
||||
if (this_board->post_serial_init)
|
||||
(this_board->post_serial_init)();
|
||||
|
||||
/* we try the possible kernels for this board in order */
|
||||
|
||||
for (this_kernel = this_board->kernel_source; this_kernel->name;
|
||||
this_kernel++)
|
||||
try_this_kernel();
|
||||
|
||||
/* none of the kernels worked out */
|
||||
|
||||
puts("\nNo usable kernel image found\n");
|
||||
|
||||
/*
|
||||
* sit there doing a memory test in this case.
|
||||
*
|
||||
* This phase 2 code will get destroyed but it's OK, we won't be
|
||||
* coming back and the whole memory test and dependency functions are
|
||||
* in phase 1 / steppingstone, so we can test entire memory range.
|
||||
*
|
||||
* It means we just boot with SD Card with kernel(s) renamed or removed
|
||||
* to provoke memory test.
|
||||
*/
|
||||
|
||||
indicate(UI_IND_MEM_TEST);
|
||||
|
||||
memory_test((void *)this_board->linux_mem_start,
|
||||
this_board->linux_mem_size);
|
||||
|
||||
}
|
112
qiboot/src/serial.h
Normal file
112
qiboot/src/serial.h
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
* Author: xiangfu liu <xiangfu@openmoko.org>
|
||||
*
|
||||
* Configuation settings for the FIC Neo GTA02 Linux GSM phone
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __SERIAL_H__
|
||||
#define __SERIAL_H__
|
||||
|
||||
#define UART0 0
|
||||
#define UART1 1
|
||||
#define UART2 2
|
||||
|
||||
#define rGPHCON (*(volatile unsigned *)0x56000070) /*UART 0 Line control*/
|
||||
|
||||
#define rULCON0 (*(volatile unsigned *)0x50000000) /*UART 0 Line control*/
|
||||
#define rUCON0 (*(volatile unsigned *)0x50000004) /*UART 0 Control*/
|
||||
#define rUFCON0 (*(volatile unsigned *)0x50000008) /*UART 0 FIFO control*/
|
||||
#define rUMCON0 (*(volatile unsigned *)0x5000000c) /*UART 0 Modem control*/
|
||||
#define rUTRSTAT0 (*(volatile unsigned *)0x50000010) /*UART 0 Tx/Rx status*/
|
||||
#define rUERSTAT0 (*(volatile unsigned *)0x50000014) /*UART 0 Rx error status*/
|
||||
#define rUFSTAT0 (*(volatile unsigned *)0x50000018) /*UART 0 FIFO status*/
|
||||
#define rUMSTAT0 (*(volatile unsigned *)0x5000001c) /*UART 0 Modem status*/
|
||||
#define rUBRDIV0 (*(volatile unsigned *)0x50000028) /*UART 0 Baud rate divisor*/
|
||||
|
||||
#define rULCON1 (*(volatile unsigned *)0x50004000) /*UART 1 Line control*/
|
||||
#define rUCON1 (*(volatile unsigned *)0x50004004) /*UART 1 Control*/
|
||||
#define rUFCON1 (*(volatile unsigned *)0x50004008) /*UART 1 FIFO control*/
|
||||
#define rUMCON1 (*(volatile unsigned *)0x5000400c) /*UART 1 Modem control*/
|
||||
#define rUTRSTAT1 (*(volatile unsigned *)0x50004010) /*UART 1 Tx/Rx status*/
|
||||
#define rUERSTAT1 (*(volatile unsigned *)0x50004014) /*UART 1 Rx error status*/
|
||||
#define rUFSTAT1 (*(volatile unsigned *)0x50004018) /*UART 1 FIFO status*/
|
||||
#define rUMSTAT1 (*(volatile unsigned *)0x5000401c) /*UART 1 Modem status*/
|
||||
#define rUBRDIV1 (*(volatile unsigned *)0x50004028) /*UART 1 Baud rate divisor*/
|
||||
|
||||
#define rULCON2 (*(volatile unsigned *)0x50008000) /*UART 2 Line control*/
|
||||
#define rUCON2 (*(volatile unsigned *)0x50008004) /*UART 2 Control*/
|
||||
#define rUFCON2 (*(volatile unsigned *)0x50008008) /*UART 2 FIFO control*/
|
||||
#define rUTRSTAT2 (*(volatile unsigned *)0x50008010) /*UART 2 Tx/Rx status*/
|
||||
#define rUERSTAT2 (*(volatile unsigned *)0x50008014) /*UART 2 Rx error status*/
|
||||
#define rUFSTAT2 (*(volatile unsigned *)0x50008018) /*UART 2 FIFO status*/
|
||||
#define rUBRDIV2 (*(volatile unsigned *)0x50008028) /*UART 2 Baud rate divisor*/
|
||||
|
||||
#define WrUTXH0(ch) (*(volatile unsigned char *)0x50000020)=(unsigned char)(ch)
|
||||
#define RdURXH0() (*(volatile unsigned char *)0x50000024)
|
||||
#define WrUTXH1(ch) (*(volatile unsigned char *)0x50004020)=(unsigned char)(ch)
|
||||
#define RdURXH1() (*(volatile unsigned char *)0x50004024)
|
||||
#define WrUTXH2(ch) (*(volatile unsigned char *)0x50008020)=(unsigned char)(ch)
|
||||
#define RdURXH2() (*(volatile unsigned char *)0x50008024)
|
||||
|
||||
|
||||
|
||||
// I/O PORT
|
||||
#define rGPACON (*(volatile unsigned *)0x56000000)
|
||||
#define rGPADAT (*(volatile unsigned *)0x56000004)
|
||||
|
||||
#define rGPBCON (*(volatile unsigned *)0x56000010)
|
||||
#define rGPBDAT (*(volatile unsigned *)0x56000014)
|
||||
#define rGPBUP (*(volatile unsigned *)0x56000018)
|
||||
|
||||
#define rGPCCON (*(volatile unsigned *)0x56000020)
|
||||
#define rGPCDAT (*(volatile unsigned *)0x56000024)
|
||||
#define rGPCUP (*(volatile unsigned *)0x56000028)
|
||||
|
||||
#define rGPDCON (*(volatile unsigned *)0x56000030)
|
||||
#define rGPDDAT (*(volatile unsigned *)0x56000034)
|
||||
#define rGPDUP (*(volatile unsigned *)0x56000038)
|
||||
|
||||
#define rGPECON (*(volatile unsigned *)0x56000040)
|
||||
#define rGPEDAT (*(volatile unsigned *)0x56000044)
|
||||
#define rGPEUP (*(volatile unsigned *)0x56000048)
|
||||
|
||||
#define rGPFCON (*(volatile unsigned *)0x56000050)
|
||||
#define rGPFDAT (*(volatile unsigned *)0x56000054)
|
||||
#define rGPFUP (*(volatile unsigned *)0x56000058)
|
||||
|
||||
#define rGPGCON (*(volatile unsigned *)0x56000060)
|
||||
#define rGPGDAT (*(volatile unsigned *)0x56000064)
|
||||
#define rGPGUP (*(volatile unsigned *)0x56000068)
|
||||
|
||||
#define rGPHCON (*(volatile unsigned *)0x56000070)
|
||||
#define rGPHDAT (*(volatile unsigned *)0x56000074)
|
||||
#define rGPHUP (*(volatile unsigned *)0x56000078)
|
||||
|
||||
#define rGPJCON (*(volatile unsigned *)0x560000d0) //Port J control
|
||||
#define rGPJDAT (*(volatile unsigned *)0x560000d4) //Port J data
|
||||
#define rGPJUP (*(volatile unsigned *)0x560000d8) //Port J data
|
||||
|
||||
void port_init(void);
|
||||
void serial_init (const int uart);
|
||||
void serial_putc (const int uart,const char c);
|
||||
int printk(const char *fmt, ...);
|
||||
int puts(const char *string);
|
||||
|
||||
#endif
|
332
qiboot/src/start.S
Normal file
332
qiboot/src/start.S
Normal file
@ -0,0 +1,332 @@
|
||||
/*
|
||||
* (C) Copyright 2007 OpenMoko, Inc.
|
||||
*
|
||||
* Configuation settings for the OPENMOKO Neo GTA02 Linux GSM phone
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#define __ASM_MODE__
|
||||
#include <neo_gta02.h>
|
||||
|
||||
#define S3C2410_MISCCR_nEN_SCLK0 (1 << 17)
|
||||
#define S3C2410_MISCCR_nEN_SCLK1 (1 << 18)
|
||||
#define S3C2410_MISCCR_nEN_SCLKE (1 << 19)
|
||||
|
||||
|
||||
|
||||
.globl _start, processor_id, is_jtag
|
||||
|
||||
_start: b start_code
|
||||
/* if we are injected by JTAG, the script sets _istag content to nonzero */
|
||||
is_jtag:
|
||||
.word 0
|
||||
|
||||
/* it's at a fixed address (+0x8) so we can breakpoint it in the JTAG script
|
||||
* we need to go through this hassle because before this moment, SDRAM is not
|
||||
* working so we can't prep it from JTAG
|
||||
*/
|
||||
|
||||
_steppingstone_done:
|
||||
ldr pc, _start_armboot
|
||||
|
||||
_start_armboot:
|
||||
.word start_qi
|
||||
|
||||
_TEXT_BASE:
|
||||
.word TEXT_BASE
|
||||
|
||||
processor_id:
|
||||
.word 0
|
||||
.word 0x41129200 /* s3c2442 ID */
|
||||
.word 0x410fb760 /* s3c6410 ID */
|
||||
|
||||
/*
|
||||
* These are defined in the board-specific linker script.
|
||||
*/
|
||||
.globl _bss_start
|
||||
_bss_start:
|
||||
.word __bss_start
|
||||
|
||||
.globl _bss_end
|
||||
_bss_end:
|
||||
.word _end
|
||||
|
||||
start_code:
|
||||
/*
|
||||
* set the cpu to SVC32 mode
|
||||
*/
|
||||
mrs r0,cpsr
|
||||
bic r0,r0,#0x1f
|
||||
orr r0,r0,#0xd3
|
||||
msr cpsr,r0
|
||||
|
||||
/*
|
||||
* detect processor we are running on
|
||||
* s3c2442: 0x4112920x
|
||||
* s3c6410: 0x410fb76x
|
||||
*/
|
||||
MRC p15, 0 ,r0, c0, c0, 0
|
||||
ldr r1, =processor_id
|
||||
str r0, [r1]
|
||||
ldr r2, [r1, #4]
|
||||
|
||||
and r0, #0xfffffff0
|
||||
cmp r0, r2
|
||||
beq startup_2442
|
||||
|
||||
/* 6410 startup */
|
||||
startup_6410:
|
||||
|
||||
mov r0, #0
|
||||
str r0, [r1]
|
||||
|
||||
/* 2442 startup */
|
||||
startup_2442:
|
||||
# define pWTCON 0x53000000
|
||||
|
||||
ldr r0, =pWTCON
|
||||
mov r1, #0x0
|
||||
str r1, [r0]
|
||||
|
||||
/*
|
||||
* mask all IRQs by setting all bits in the INTMR - default
|
||||
*/
|
||||
# define INTMSK 0x4A000008 /* Interupt-Controller base addresses */
|
||||
# define INTSUBMSK 0x4A00001C
|
||||
# define INTSUBMSK_val 0x0000ffff
|
||||
|
||||
mov r1, #0xffffffff
|
||||
ldr r0, =INTMSK
|
||||
str r1, [r0]
|
||||
|
||||
ldr r1, =INTSUBMSK_val
|
||||
ldr r0, =INTSUBMSK
|
||||
str r1, [r0]
|
||||
|
||||
|
||||
/* Make sure we get FCLK:HCLK:PCLK = 1:3:6 */
|
||||
# define CAMDIVN 0x4C000018
|
||||
|
||||
ldr r0, =CAMDIVN
|
||||
mov r1, #0
|
||||
str r1, [r0]
|
||||
|
||||
/* Clock asynchronous mode */
|
||||
mrc p15, 0, r1, c1, c0, 0
|
||||
orr r1, r1, #0xc0000000
|
||||
mcr p15, 0, r1, c1, c0, 0
|
||||
|
||||
#define LOCKTIME 0x4c000000
|
||||
|
||||
ldr r0, =LOCKTIME
|
||||
mov r1, #0xffffff
|
||||
str r1, [r0]
|
||||
|
||||
# define UPLLCON 0x4c000008
|
||||
# define MPLLCON_val ((142 << 12) + (7 << 4) + 1)
|
||||
# define UPLLCON_val (( 88 << 12) + (8 << 4) + 2)
|
||||
|
||||
ldr r0, =UPLLCON
|
||||
ldr r1, =UPLLCON_val
|
||||
str r1, [r0]
|
||||
|
||||
/* Page 7-19, seven nops between UPLL and MPLL */
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
ldr r1, =MPLLCON_val
|
||||
str r1, [r0, #-4] /* MPLLCON */
|
||||
|
||||
# define CLKDIVN 0x4C000014 /* clock divisor register */
|
||||
# define CLKDIVN_val 7 /* FCLK:HCLK:PCLK = 1:3:6 */
|
||||
|
||||
/* FCLK:HCLK:PCLK = 1:3:6 */
|
||||
ldr r0, =CLKDIVN
|
||||
mov r1, #CLKDIVN_val
|
||||
str r1, [r0]
|
||||
|
||||
/* enable only CPU peripheral block clocks we actually use */
|
||||
ldr r0, =0x4c00000c /* clkcon */
|
||||
ldr r1, =0x3f10 /* uart, pwm, gpio, nand, sdi clocks on */
|
||||
str r1, [r0]
|
||||
|
||||
/* gpio UART2 init, H port */
|
||||
ldr r0, =0x56000070
|
||||
ldr r1, =0x001AAAAA
|
||||
str r1, [r0]
|
||||
|
||||
/* enable KEEPACT(GPJ8) to make sure PMU keeps us alive */
|
||||
ldr r0, =0x56000000 /* GPJ base */
|
||||
ldr r1, [r0, #0xd0] /* GPJCON */
|
||||
orr r1, r1, #(1 << 16)
|
||||
str r1, [r0, #0xd0]
|
||||
|
||||
ldr r1, [r0, #0xd4] /* GPJDAT */
|
||||
orr r1, r1, #(1 << 8)
|
||||
str r1, [r0, #0xd4]
|
||||
|
||||
|
||||
/* init uart2 */
|
||||
ldr r0, =0x50008000
|
||||
mov r1, #0x03
|
||||
str r1, [r0]
|
||||
ldr r1, =0x245
|
||||
str r1, [r0, #0x04]
|
||||
mov r1, #0x00
|
||||
str r1, [r0, #0x08]
|
||||
mov r1, #0x00
|
||||
str r1, [r0, #0x0c]
|
||||
mov r1, #0x11
|
||||
str r1, [r0, #0x28]
|
||||
|
||||
ldr r0, =0x50008000
|
||||
ldr r1, =0x54
|
||||
str r1, [r0, #0x20]
|
||||
|
||||
/* reset nand controller, or it is dead to us */
|
||||
|
||||
mov r1, #0x4E000000
|
||||
ldr r2, =0xfff0 @ initial value tacls=3,rph0=7,rph1=7
|
||||
ldr r3, [r1, #0]
|
||||
orr r3, r3, r2
|
||||
str r3, [r1, #0]
|
||||
|
||||
ldr r3, [r1, #4]
|
||||
orr r3, r3, #1 @ enable nand controller
|
||||
str r3, [r1, #4]
|
||||
|
||||
|
||||
/* take sdram out of power down */
|
||||
ldr r0, =0x56000080 /* misccr */
|
||||
ldr r1, [ r0 ]
|
||||
bic r1, r1, #(S3C2410_MISCCR_nEN_SCLK0 | S3C2410_MISCCR_nEN_SCLK1 | S3C2410_MISCCR_nEN_SCLKE)
|
||||
str r1, [ r0 ]
|
||||
|
||||
/* ensure signals stabalise */
|
||||
mov r1, #128
|
||||
1: subs r1, r1, #1
|
||||
bpl 1b
|
||||
|
||||
bl cpu_init_crit
|
||||
|
||||
/* ensure some refresh has happened */
|
||||
ldr r1, =0xfffff
|
||||
1: subs r1, r1, #1
|
||||
bpl 1b
|
||||
|
||||
/* capture full EINT situation into gstatus 4 */
|
||||
|
||||
ldr r0, =0x4A000000 /* SRCPND */
|
||||
ldr r1, [ r0 ]
|
||||
and r1, r1, #0xf
|
||||
|
||||
ldr r0, =0x560000BC /* gstatus4 */
|
||||
str r1, [ r0 ]
|
||||
|
||||
ldr r0, =0x560000A8 /* EINTPEND */
|
||||
ldr r1, [ r0 ]
|
||||
ldr r0, =0xfff0
|
||||
and r1, r1, r0
|
||||
ldr r0, =0x560000BC /* gstatus4 */
|
||||
ldr r0, [ r0 ]
|
||||
orr r1, r1, r0
|
||||
ldr r0, =0x560000BC /* gstatus4 */
|
||||
str r1, [ r0 ]
|
||||
|
||||
/* test for resume */
|
||||
|
||||
ldr r1, =0x560000B4 /* gstatus2 */
|
||||
ldr r0, [ r1 ]
|
||||
tst r0, #0x02 /* is this resume from power down */
|
||||
/* well, if it was, we are going to jump to
|
||||
* whatever address we stashed in gstatus3,
|
||||
* and gstatus4 will hold the wake interrupt
|
||||
* source for the OS to look at
|
||||
*/
|
||||
ldrne pc, [r1, #4]
|
||||
|
||||
|
||||
/* >> CFG_VIDEO_LOGO_MAX_SIZE */
|
||||
#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
|
||||
|
||||
stack_setup:
|
||||
ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
|
||||
sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */
|
||||
sub sp, r0, #12 /* leave 3 words for abort-stack */
|
||||
|
||||
clear_bss:
|
||||
ldr r0, _bss_start /* find start of bss segment */
|
||||
ldr r1, _bss_end /* stop here */
|
||||
mov r2, #0x00000000 /* clear */
|
||||
|
||||
clbss_l:
|
||||
str r2, [r0] /* clear loop... */
|
||||
add r0, r0, #4
|
||||
cmp r0, r1
|
||||
ble clbss_l
|
||||
|
||||
/* we are going to jump into the C part of the init now */
|
||||
spin:
|
||||
b _steppingstone_done
|
||||
|
||||
/*
|
||||
*************************************************************************
|
||||
*
|
||||
* CPU_init_critical registers
|
||||
*
|
||||
* setup important registers
|
||||
* setup memory timing
|
||||
*
|
||||
*************************************************************************
|
||||
*/
|
||||
|
||||
cpu_init_crit:
|
||||
|
||||
/*
|
||||
* flush v4 I/D caches
|
||||
*/
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
|
||||
mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
|
||||
|
||||
/*
|
||||
* disable MMU stuff and caches
|
||||
*/
|
||||
mrc p15, 0, r0, c1, c0, 0
|
||||
bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
|
||||
bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
|
||||
orr r0, r0, #0x00000002 @ set bit 2 (A) Align
|
||||
orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
|
||||
mcr p15, 0, r0, c1, c0, 0
|
||||
|
||||
/*
|
||||
* before relocating, we have to setup RAM timing
|
||||
* because memory timing is board-dependend, you will
|
||||
* find a lowlevel_init.S in your board directory.
|
||||
*/
|
||||
mov ip, lr
|
||||
|
||||
bl lowlevel_init
|
||||
|
||||
mov lr, ip
|
||||
mov pc, lr
|
||||
|
134
qiboot/src/utils-phase2.c
Normal file
134
qiboot/src/utils-phase2.c
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* (C) Copyright 2008 Openmoko, Inc.
|
||||
* Author: Andy Green <andy@openmoko.org>
|
||||
*
|
||||
* Little utils for print and strings
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <qi.h>
|
||||
#include <string.h>
|
||||
|
||||
extern void (*putc_func)(char);
|
||||
|
||||
/*
|
||||
* malloc pool needs to be in phase 2 bss section, we have phase 1 bss in
|
||||
* steppingstone to allow full memory range testing in C
|
||||
*/
|
||||
u8 malloc_pool[MALLOC_POOL_EXTENT];
|
||||
void * malloc_pointer = &malloc_pool[0];
|
||||
|
||||
|
||||
/* improbably simple malloc and free for small and non-intense allocation
|
||||
* just moves the allocation ptr forward each time and ignores free
|
||||
*/
|
||||
|
||||
void *malloc(size_t size)
|
||||
{
|
||||
void *p = malloc_pointer;
|
||||
|
||||
malloc_pointer += (size & ~3) + 4;
|
||||
|
||||
if (((u8 *)malloc_pointer - &malloc_pool[0]) > sizeof(malloc_pool)) {
|
||||
puts("Ran out of malloc pool\n");
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void free(void *ptr)
|
||||
{
|
||||
}
|
||||
|
||||
char *strncpy(char *dest, const char *src, size_t n)
|
||||
{
|
||||
char * dest_orig = dest;
|
||||
|
||||
while (*src && n--)
|
||||
*dest++ = *src++;
|
||||
|
||||
if (n)
|
||||
*dest = '\0';
|
||||
|
||||
return dest_orig;
|
||||
}
|
||||
|
||||
|
||||
int strcmp(const char *s1, const char *s2)
|
||||
{
|
||||
while (1) {
|
||||
if (*s1 != *s2)
|
||||
return *s1 - *s2;
|
||||
if (!*s1)
|
||||
return 0;
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
}
|
||||
|
||||
char *strchr(const char *s, int c)
|
||||
{
|
||||
while ((*s) && (*s != c))
|
||||
s++;
|
||||
|
||||
if (*s == c)
|
||||
return (char *)s;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void hexdump(unsigned char *start, int len)
|
||||
{
|
||||
int n;
|
||||
|
||||
while (len > 0) {
|
||||
print32((int)start);
|
||||
(putc_func)(':');
|
||||
(putc_func)(' ');
|
||||
for (n = 0; n < 16; n++) {
|
||||
print8(*start++);
|
||||
(putc_func)(' ');
|
||||
}
|
||||
(putc_func)('\n');
|
||||
len -= 16;
|
||||
}
|
||||
}
|
||||
|
||||
void setnybble(char *p, unsigned char n)
|
||||
{
|
||||
if (n < 10)
|
||||
*p = '0' + n;
|
||||
else
|
||||
*p = 'a' + n - 10;
|
||||
}
|
||||
|
||||
void set8(char *p, unsigned char n)
|
||||
{
|
||||
setnybble(p, (n >> 4) & 15);
|
||||
setnybble(p + 1, n & 15);
|
||||
}
|
||||
|
||||
void set32(char *p, unsigned int u)
|
||||
{
|
||||
set8(p, u >> 24);
|
||||
set8(p + 2, u >> 16);
|
||||
set8(p + 4, u >> 8);
|
||||
set8(p + 6, u);
|
||||
}
|
||||
|
150
qiboot/src/utils.c
Normal file
150
qiboot/src/utils.c
Normal file
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* (C) Copyright 2008 Openmoko, Inc.
|
||||
* Author: Andy Green <andy@openmoko.org>
|
||||
*
|
||||
* Little utils for print and strings
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <qi.h>
|
||||
#include <string.h>
|
||||
|
||||
void (*putc_func)(char) = NULL;
|
||||
|
||||
|
||||
void set_putc_func(void (*p)(char))
|
||||
{
|
||||
putc_func = p;
|
||||
}
|
||||
|
||||
size_t strlen(const char *s)
|
||||
{
|
||||
size_t n = 0;
|
||||
|
||||
while (*s++)
|
||||
n++;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
char *strcpy(char *dest, const char *src)
|
||||
{
|
||||
char * dest_orig = dest;
|
||||
|
||||
while (*src)
|
||||
*dest++ = *src++;
|
||||
*dest = '\0';
|
||||
|
||||
return dest_orig;
|
||||
}
|
||||
|
||||
int puts(const char *string)
|
||||
{
|
||||
while (*string)
|
||||
(putc_func)(*string++);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* done like this to avoid needing statics in steppingstone */
|
||||
void printnybble(unsigned char n)
|
||||
{
|
||||
if (n < 10)
|
||||
(putc_func)('0' + n);
|
||||
else
|
||||
(putc_func)('a' + n - 10);
|
||||
}
|
||||
|
||||
void print8(unsigned char n)
|
||||
{
|
||||
printnybble((n >> 4) & 15);
|
||||
printnybble(n & 15);
|
||||
}
|
||||
|
||||
void print32(unsigned int u)
|
||||
{
|
||||
print8(u >> 24);
|
||||
print8(u >> 16);
|
||||
print8(u >> 8);
|
||||
print8(u);
|
||||
}
|
||||
|
||||
void printdec(int n)
|
||||
{
|
||||
int d[] = {
|
||||
1 * 1000 * 1000 * 1000,
|
||||
100 * 1000 * 1000,
|
||||
10 * 1000 * 1000,
|
||||
1 * 1000 * 1000,
|
||||
100 * 1000,
|
||||
10 * 1000,
|
||||
1 * 1000,
|
||||
100,
|
||||
10,
|
||||
1,
|
||||
0
|
||||
};
|
||||
int flag = 0;
|
||||
int div = 0;
|
||||
|
||||
if (n < 0) {
|
||||
(putc_func)('-');
|
||||
n = -n;
|
||||
}
|
||||
|
||||
while (d[div]) {
|
||||
int r = 0;
|
||||
while (n >= d[div]) {
|
||||
r++;
|
||||
n -= d[div];
|
||||
}
|
||||
if (r || flag || (d[div] == 1)) {
|
||||
(putc_func)('0' + r);
|
||||
flag = 1;
|
||||
}
|
||||
div++;
|
||||
}
|
||||
}
|
||||
|
||||
void *memcpy(void *dest, const void *src, size_t n)
|
||||
{
|
||||
u8 const * ps = src;
|
||||
u8 * pd = dest;
|
||||
|
||||
while (n--)
|
||||
*pd++ = *ps++;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
void *memset(void *s, int c, size_t n)
|
||||
{
|
||||
u8 * p = s;
|
||||
|
||||
while (n--)
|
||||
*p++ = c;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int q;
|
||||
|
||||
void udelay(int n)
|
||||
{
|
||||
while (n--)
|
||||
q+=n * q;
|
||||
}
|
39
qiboot/tools/Makefile
Normal file
39
qiboot/tools/Makefile
Normal file
@ -0,0 +1,39 @@
|
||||
#(C) Copyright 2007 OpenMoko, Inc.
|
||||
# Author: xiangfu liu <xiangfu@openmoko.org>
|
||||
#
|
||||
# Configuation settings for the OPENMOKO Neo GTA02 Linux GSM phone
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 2 of
|
||||
# the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
# MA 02111-1307 USA
|
||||
#
|
||||
include ../config.mk
|
||||
|
||||
CC = ${HOSTCC}
|
||||
CFLAGS = -Wall
|
||||
C_SRCS = $(wildcard *.c)
|
||||
C_OBJS = $(patsubst %.c,%.o, $(C_SRCS))
|
||||
SRCS = ${C_SRCS}
|
||||
OBJS = ${C_OBJS}
|
||||
TARGET = mkudfu
|
||||
|
||||
%.o: %.c
|
||||
CC $(CFLAGS) -o $@ $<
|
||||
|
||||
all:${TARGET}
|
||||
|
||||
${TARGET}:${SRCS}
|
||||
|
||||
clean:
|
||||
@rm -f *.o *~ ${TARGET}
|
314
qiboot/tools/mkudfu.c
Normal file
314
qiboot/tools/mkudfu.c
Normal file
@ -0,0 +1,314 @@
|
||||
/*
|
||||
* USB DFU file trailer tool
|
||||
* (C) Copyright by OpenMoko, Inc.
|
||||
* Author: Harald Welte <laforge@openmoko.org>
|
||||
*
|
||||
* based on mkimage.c, copyright information as follows:
|
||||
*
|
||||
* (C) Copyright 2000-2004
|
||||
* DENX Software Engineering
|
||||
* Wolfgang Denk, wd@denx.de
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifndef __WIN32__
|
||||
#include <netinet/in.h> /* for host / network byte order conversions */
|
||||
#endif
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if defined(__BEOS__) || defined(__NetBSD__) || defined(__APPLE__)
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#ifdef __WIN32__
|
||||
typedef unsigned int __u32;
|
||||
|
||||
#define SWAP_LONG(x) \
|
||||
((__u32)( \
|
||||
(((__u32)(x) & (__u32)0x000000ffUL) << 24) | \
|
||||
(((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \
|
||||
(((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \
|
||||
(((__u32)(x) & (__u32)0xff000000UL) >> 24) ))
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
|
||||
#define ntohl(a) SWAP_LONG(a)
|
||||
#define htonl(a) SWAP_LONG(a)
|
||||
#endif /* __WIN32__ */
|
||||
|
||||
#ifndef O_BINARY /* should be define'd on __WIN32__ */
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
#include "usb_dfu_trailer.h"
|
||||
|
||||
extern int errno;
|
||||
|
||||
#ifndef MAP_FAILED
|
||||
#define MAP_FAILED (-1)
|
||||
#endif
|
||||
|
||||
static char *cmdname;
|
||||
|
||||
static char *datafile;
|
||||
static char *imagefile;
|
||||
|
||||
|
||||
static void usage()
|
||||
{
|
||||
fprintf (stderr, "%s - create / display u-boot DFU trailer\n", cmdname);
|
||||
fprintf (stderr, "Usage: %s -l image\n"
|
||||
" -l ==> list image header information\n"
|
||||
" %s -v VID -p PID -r REV -d data_file image\n",
|
||||
cmdname, cmdname);
|
||||
fprintf (stderr, " -v ==> set vendor ID to 'VID'\n"
|
||||
" -p ==> set product ID system to 'PID'\n"
|
||||
" -r ==> set hardware revision to 'REV'\n"
|
||||
" -d ==> use 'data_file' as input file\n"
|
||||
);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void print_trailer(struct uboot_dfu_trailer *trailer)
|
||||
{
|
||||
printf("===> DFU Trailer information:\n");
|
||||
printf("Trailer Vers.: %d\n", trailer->version);
|
||||
printf("Trailer Length: %d\n", trailer->length);
|
||||
printf("VendorID: 0x%04x\n", trailer->vendor);
|
||||
printf("ProductID: 0x%04x\n", trailer->product);
|
||||
printf("HW Revision: 0x%04x\n", trailer->revision);
|
||||
}
|
||||
|
||||
static void copy_file (int ifd, const char *datafile, int pad)
|
||||
{
|
||||
int dfd;
|
||||
struct stat sbuf;
|
||||
unsigned char *ptr;
|
||||
int tail;
|
||||
int zero = 0;
|
||||
int offset = 0;
|
||||
int size;
|
||||
|
||||
if ((dfd = open(datafile, O_RDONLY|O_BINARY)) < 0) {
|
||||
fprintf (stderr, "%s: Can't open %s: %s\n",
|
||||
cmdname, datafile, strerror(errno));
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (fstat(dfd, &sbuf) < 0) {
|
||||
fprintf (stderr, "%s: Can't stat %s: %s\n",
|
||||
cmdname, datafile, strerror(errno));
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ptr = (unsigned char *)mmap(0, sbuf.st_size,
|
||||
PROT_READ, MAP_SHARED, dfd, 0);
|
||||
if (ptr == (unsigned char *)MAP_FAILED) {
|
||||
fprintf (stderr, "%s: Can't read %s: %s\n",
|
||||
cmdname, datafile, strerror(errno));
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
size = sbuf.st_size - offset;
|
||||
if (write(ifd, ptr + offset, size) != size) {
|
||||
fprintf (stderr, "%s: Write error on %s: %s\n",
|
||||
cmdname, imagefile, strerror(errno));
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (pad && ((tail = size % 4) != 0)) {
|
||||
|
||||
if (write(ifd, (char *)&zero, 4-tail) != 4-tail) {
|
||||
fprintf (stderr, "%s: Write error on %s: %s\n",
|
||||
cmdname, imagefile, strerror(errno));
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
(void) munmap((void *)ptr, sbuf.st_size);
|
||||
(void) close (dfd);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ifd;
|
||||
int lflag = 0;
|
||||
struct stat sbuf;
|
||||
u_int16_t opt_vendor, opt_product, opt_revision;
|
||||
struct uboot_dfu_trailer _hdr, _mirror, *hdr = &_hdr;
|
||||
|
||||
opt_vendor = opt_product = opt_revision = 0;
|
||||
|
||||
cmdname = *argv;
|
||||
|
||||
while (--argc > 0 && **++argv == '-') {
|
||||
while (*++*argv) {
|
||||
switch (**argv) {
|
||||
case 'l':
|
||||
lflag = 1;
|
||||
break;
|
||||
case 'v':
|
||||
if (--argc <= 0)
|
||||
usage ();
|
||||
opt_vendor = strtoul(*++argv, NULL, 16);
|
||||
goto NXTARG;
|
||||
case 'p':
|
||||
if (--argc <= 0)
|
||||
usage ();
|
||||
opt_product = strtoul(*++argv, NULL, 16);
|
||||
goto NXTARG;
|
||||
case 'r':
|
||||
if (--argc <= 0)
|
||||
usage ();
|
||||
opt_revision = strtoul(*++argv, NULL, 16);
|
||||
goto NXTARG;
|
||||
case 'd':
|
||||
if (--argc <= 0)
|
||||
usage ();
|
||||
datafile = *++argv;
|
||||
goto NXTARG;
|
||||
case 'h':
|
||||
usage();
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
NXTARG: ;
|
||||
}
|
||||
|
||||
if (argc != 1)
|
||||
usage();
|
||||
|
||||
imagefile = *argv;
|
||||
|
||||
if (lflag)
|
||||
ifd = open(imagefile, O_RDONLY|O_BINARY);
|
||||
else
|
||||
ifd = open(imagefile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0666);
|
||||
|
||||
if (ifd < 0) {
|
||||
fprintf (stderr, "%s: Can't open %s: %s\n",
|
||||
cmdname, imagefile, strerror(errno));
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (lflag) {
|
||||
unsigned char *ptr;
|
||||
/* list header information of existing image */
|
||||
if (fstat(ifd, &sbuf) < 0) {
|
||||
fprintf (stderr, "%s: Can't stat %s: %s\n",
|
||||
cmdname, imagefile, strerror(errno));
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if ((unsigned)sbuf.st_size < sizeof(struct uboot_dfu_trailer)) {
|
||||
fprintf (stderr,
|
||||
"%s: Bad size: \"%s\" is no valid image\n",
|
||||
cmdname, imagefile);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ptr = (unsigned char *)mmap(0, sbuf.st_size,
|
||||
PROT_READ, MAP_SHARED, ifd, 0);
|
||||
if ((caddr_t)ptr == (caddr_t)-1) {
|
||||
fprintf (stderr, "%s: Can't read %s: %s\n",
|
||||
cmdname, imagefile, strerror(errno));
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
dfu_trailer_mirror(hdr, ptr+sbuf.st_size);
|
||||
|
||||
if (hdr->magic != UBOOT_DFU_TRAILER_MAGIC) {
|
||||
fprintf (stderr,
|
||||
"%s: Bad Magic Number: \"%s\" is no valid image\n",
|
||||
cmdname, imagefile);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* for multi-file images we need the data part, too */
|
||||
print_trailer(hdr);
|
||||
|
||||
(void) munmap((void *)ptr, sbuf.st_size);
|
||||
(void) close (ifd);
|
||||
|
||||
exit (EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/* if we're not listing: */
|
||||
|
||||
copy_file (ifd, datafile, 0);
|
||||
|
||||
memset (hdr, 0, sizeof(struct uboot_dfu_trailer));
|
||||
|
||||
/* Build new header */
|
||||
hdr->version = UBOOT_DFU_TRAILER_V1;
|
||||
hdr->magic = UBOOT_DFU_TRAILER_MAGIC;
|
||||
hdr->length = sizeof(struct uboot_dfu_trailer);
|
||||
hdr->vendor = opt_vendor;
|
||||
hdr->product = opt_product;
|
||||
hdr->revision = opt_revision;
|
||||
|
||||
print_trailer(hdr);
|
||||
dfu_trailer_mirror(&_mirror, (unsigned char *)hdr+sizeof(*hdr));
|
||||
|
||||
if (write(ifd, &_mirror, sizeof(struct uboot_dfu_trailer))
|
||||
!= sizeof(struct uboot_dfu_trailer)) {
|
||||
fprintf (stderr, "%s: Write error on %s: %s\n",
|
||||
cmdname, imagefile, strerror(errno));
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* We're a bit of paranoid */
|
||||
#if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__)
|
||||
(void) fdatasync (ifd);
|
||||
#else
|
||||
(void) fsync (ifd);
|
||||
#endif
|
||||
|
||||
if (fstat(ifd, &sbuf) < 0) {
|
||||
fprintf (stderr, "%s: Can't stat %s: %s\n",
|
||||
cmdname, imagefile, strerror(errno));
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* We're a bit of paranoid */
|
||||
#if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__)
|
||||
(void) fdatasync (ifd);
|
||||
#else
|
||||
(void) fsync (ifd);
|
||||
#endif
|
||||
|
||||
if (close(ifd)) {
|
||||
fprintf (stderr, "%s: Write error on %s: %s\n",
|
||||
cmdname, imagefile, strerror(errno));
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
exit (EXIT_SUCCESS);
|
||||
}
|
31
qiboot/tools/usb_dfu_trailer.h
Normal file
31
qiboot/tools/usb_dfu_trailer.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef _USB_DFU_TRAILER_H
|
||||
#define _USB_DFU_TRAILER_H
|
||||
|
||||
/* trailer handling for DFU files */
|
||||
|
||||
#define UBOOT_DFU_TRAILER_V1 1
|
||||
#define UBOOT_DFU_TRAILER_MAGIC 0x19731978
|
||||
struct uboot_dfu_trailer {
|
||||
u_int32_t magic;
|
||||
u_int16_t version;
|
||||
u_int16_t length;
|
||||
u_int16_t vendor;
|
||||
u_int16_t product;
|
||||
u_int32_t revision;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* we mirror the trailer because we want it to be longer in later versions
|
||||
* while keeping backwards compatibility */
|
||||
static inline void dfu_trailer_mirror(struct uboot_dfu_trailer *trailer,
|
||||
unsigned char *eof)
|
||||
{
|
||||
int i;
|
||||
int len = sizeof(struct uboot_dfu_trailer);
|
||||
unsigned char *src = eof - len;
|
||||
unsigned char *dst = (unsigned char *) trailer;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
dst[len-1-i] = src[i];
|
||||
}
|
||||
|
||||
#endif /* _USB_DFU_TRAILER_H */
|
Loading…
Reference in New Issue
Block a user