Remove sys/boot/arm/at91 and ixp425

Remove at91 bootloader. It only worked on AT91RM9200, and only
specific boards that were all EOLd 10 years ago.

Remove ixp425. It doesn't build anymore and is for boards that were
EOLd 8 years ago.

Sponsored by: Netflix
This commit is contained in:
Warner Losh 2017-10-25 15:28:05 +00:00
parent b533f63ed0
commit e1b6a0cd96
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=324982
72 changed files with 0 additions and 10845 deletions

View File

@ -1,5 +0,0 @@
# $FreeBSD$
SUBDIR= libat91 boot0 boot0iic boot0spi boot2 bootiic bootspi
.include <bsd.subdir.mk>

View File

@ -1,57 +0,0 @@
# $FreeBSD$
.if !target(__at91_boot_Makefile.inc__)
.PATH: ${.CURDIR}/../../../../libkern ${.CURDIR}/../../../../libkern/arm
__at91_boot_Makefile.inc__:
# tsc, bwct, kb920x, centipad are the supported flavors
BOOT_FLAVOR?=kb920x
CFLAGS=-Os -mcpu=arm9 -ffreestanding \
-I${.CURDIR}/../libat91 \
-I${.CURDIR}/../../../.. \
-I${.CURDIR}/../../../../arm \
-D_KERNEL \
-Wall -Waggregate-return \
-Wnested-externs \
-Wpointer-arith -Wshadow -Wwrite-strings \
-Werror \
-Wmissing-prototypes \
-Wmissing-declarations
# -Wstrict-prototypes
CFLAGS+=-DBOOT_${BOOT_FLAVOR:tu}
LIBAT91=${.OBJDIR}/../libat91/libat91.a
LD ?= ld
OBJCOPY ?= objcopy
.if defined(P)
${P}: ${P}.out
${OBJCOPY} -S -O binary ${P}.out ${.TARGET}
@set -- `ls -l ${.TARGET}`; x=$$((12288-$$5)); \
echo "$$x bytes available"; test $$x -ge 0
${P}.out: ${OBJS}
${LD} ${LDFLAGS} -o ${.TARGET} ${OBJS} ${LIBAT91}
CLEANFILES+= ${P} ${P}.out
.endif
.if defined(WITH_TAG_LIST)
MK_TAG_LIST:=yes
.else
MK_TAG_LIST:=no
.endif
.if defined(WITH_FPGA)
MK_FPGA:=yes
.else
MK_FPGA:=no
.endif
.endif
.include "../Makefile.inc"

View File

@ -1,14 +0,0 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../libat91
P=boot0
FILES=${P}
SRCS=arm_init.S main.c
MAN=
LDFLAGS=-e 0 -T ${.CURDIR}/linker.cfg
OBJS+= ${SRCS:N*.h:R:S/$/.o/g}
.include <bsd.prog.mk>
CFLAGS+=-DBOOT_BOOT0

View File

@ -1,7 +0,0 @@
This is a bootstrap bootloader. It is intended to be used when the
AT91RM9200 is running xmodem over DBGU. It will download the next stage
of the booting process (or the recovery program) and jump to it. It loads
the program at a 1MB offset into SDRAM. Programs are expected to be
smaller than this and copy themselves to the right location.
$FreeBSD$

View File

@ -1,84 +0,0 @@
/*******************************************************************************
*
* Filename: linker.cfg
*
* linker config file used for internal RAM or eeprom images at address 0.
*
* Revision information:
*
* 20AUG2004 kb_admin initial creation
* 12JAN2005 kb_admin move data to SDRAM
*
* BEGIN_KBDD_BLOCK
* No warranty, expressed or implied, is included with this software. It is
* provided "AS IS" and no warranty of any kind including statutory or aspects
* relating to merchantability or fitness for any purpose is provided. All
* intellectual property rights of others is maintained with the respective
* owners. This software is not copyrighted and is intended for reference
* only.
* END_BLOCK
*
* $FreeBSD$
******************************************************************************/
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm",
"elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(start)
SECTIONS
{
/* Read-only sections, merged into text segment: */
. = 0;
.text :
{
*(.text)
*(.text.*)
*(.stub)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
*(.gnu.linkonce.t.*)
*(.glue_7t) *(.glue_7)
}
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.data :
{
__data_start = . ;
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
}
_edata = .;
PROVIDE (edata = .);
__bss_start = .;
__bss_start__ = .;
.sbss :
{
PROVIDE (__sbss_start = .);
PROVIDE (___sbss_start = .);
*(.dynsbss)
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
*(.scommon)
PROVIDE (__sbss_end = .);
PROVIDE (___sbss_end = .);
}
.bss :
{
*(.dynbss)
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections. */
. = ALIGN(32 / 8);
}
. = ALIGN(32 / 8);
_end = .;
_bss_end__ = . ; __bss_end__ = . ; __end__ = . ;
PROVIDE (end = .);
}

View File

@ -1,45 +0,0 @@
/*-
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#include "at91rm9200.h"
#include "lib.h"
#include "at91rm9200_lowlevel.h"
typedef void fn_t(void);
int main(void);
int
main(void)
{
char *addr = (char *)SDRAM_BASE + (1 << 20); /* Load to base + 1MB */
fn_t *fn = (fn_t *)(SDRAM_BASE + (1 << 20)); /* Load to base + 1MB */
while (xmodem_rx(addr) == -1)
continue;
fn();
return (0);
}

View File

@ -1,14 +0,0 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../libat91
P=boot0iic
FILES=${P}
SRCS=arm_init.S main.c
MAN=
LDFLAGS=-e 0 -T ${.CURDIR}/../linker.cfg
OBJS+= ${SRCS:N*.h:R:S/$/.o/g}
.include <bsd.prog.mk>
CFLAGS+=-DBOOT_BOOT0

View File

@ -1,52 +0,0 @@
/*-
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#include "at91rm9200.h"
#include "lib.h"
#include "at91rm9200_lowlevel.h"
int main(void);
int
main(void)
{
char *addr = (char *)SDRAM_BASE + (1 << 20); /* Load to base + 1MB */
int len, sec;
printf("\nSend data to be written into EEPROM\n");
while ((len = xmodem_rx(addr)) == -1)
continue;
sec = GetSeconds() + 1;
while (sec >= GetSeconds())
continue;
printf("\nWriting EEPROM from 0x%x to addr 0, 0x%x bytes\n", addr,
len);
InitEEPROM();
printf("init done\n");
WriteEEPROM(0, addr, len);
printf("\nWrote %d bytes. Press reset\n", len);
return (1);
}

View File

@ -1,14 +0,0 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../libat91
P=boot0spi
FILES=${P}
SRCS=arm_init.S main.c
MAN=
LDFLAGS=-e 0 -T ${.CURDIR}/../linker.cfg
OBJS+= ${SRCS:N*.h:R:S/$/.o/g}
.include <bsd.prog.mk>
CFLAGS+=-DBOOT_BOOT0

View File

@ -1,65 +0,0 @@
/*-
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#include "at91rm9200.h"
#include "lib.h"
#include "at91rm9200_lowlevel.h"
#include "spi_flash.h"
#define OFFSET 0
int main(void);
int
main(void)
{
int len, i, j, off, sec;
char *addr = (char *)SDRAM_BASE + (1 << 20); /* download at + 1MB */
char *addr2 = (char *)SDRAM_BASE + (2 << 20); /* readback to + 2MB */
SPI_InitFlash();
printf("Waiting for data\n");
while ((len = xmodem_rx(addr)) == -1)
continue;
printf("Writing %u bytes at %u\n", len, OFFSET);
for (i = 0; i < len; i+= FLASH_PAGE_SIZE) {
off = i + OFFSET;
for (j = 0; j < 10; j++) {
SPI_WriteFlash(off, addr + i, FLASH_PAGE_SIZE);
SPI_ReadFlash(off, addr2 + i, FLASH_PAGE_SIZE);
if (p_memcmp(addr + i, addr2 + i, FLASH_PAGE_SIZE) == 0)
break;
}
if (j >= 10)
printf("Bad Readback at %u\n", i);
}
sec = GetSeconds() + 2;
while (sec <= GetSeconds())
continue;
printf("Done\n");
reset();
return (1);
}

View File

@ -1,22 +0,0 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../libat91 ${.CURDIR}/../bootspi
P=boot2
FILES=${P}
SRCS=arm_init.S boot2.c ${BOOT_FLAVOR:tl}_board.c
MAN=
LDFLAGS=-e 0 -T ${.CURDIR}/../linker.cfg
OBJS+= ${SRCS:N*.h:R:S/$/.o/g}
.include <bsd.prog.mk>
.if ${BOOT_FLAVOR} == "kb920x"
CFLAGS+=-DBOOT_IIC
.endif
CFLAGS+= \
-I${.CURDIR}/../bootspi \
-I${.CURDIR}/../../../common \
-I${.CURDIR}/../../../.. \
-D_KERNEL \
-DUFS1_ONLY

View File

@ -1,29 +0,0 @@
/*-
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
void Update(void);
void board_init(void);
int drvread(void *, unsigned, unsigned);

View File

@ -1,368 +0,0 @@
/*-
* Copyright (c) 2008 John Hay
* Copyright (c) 2006 M Warner Losh <imp@freebsd.org>
* Copyright (c) 1998 Robert Nordier
* All rights reserved.
*
* Redistribution and use in source and binary forms are freely
* permitted provided that the above copyright notice and this
* paragraph and the following disclaimer are duplicated in all
* such forms.
*
* This software is provided "AS IS" and without any express or
* implied warranties, including, without limitation, the implied
* warranties of merchantability and fitness for a particular
* purpose.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/disklabel.h>
#include <sys/diskmbr.h>
#include <sys/dirent.h>
#include <sys/reboot.h>
#include <machine/elf.h>
#include <stdarg.h>
#include "lib.h"
#include "board.h"
#include "paths.h"
#include "rbx.h"
#undef PATH_KERNEL
#define PATH_KERNEL "/boot/kernel/kernel.gz.tramp"
extern uint32_t _end;
#define NOPT 6
static const char optstr[NOPT] = "agnrsv";
static const unsigned char bootflags[NOPT] = {
RBX_ASKNAME,
RBX_GDB,
RBX_NOINTR,
RBX_DFLTROOT,
RBX_SINGLE,
RBX_VERBOSE
};
unsigned board_id; /* board type to pass to kernel, if set by board_* code */
unsigned dsk_start;
static char cmd[512];
static char kname[1024];
uint32_t opts;
static uint8_t dsk_meta;
int main(void);
static void load(void);
static int parse(void);
static int dskread(void *, unsigned, unsigned);
#ifdef FIXUP_BOOT_DRV
static void fixup_boot_drv(caddr_t, int, int, int);
#endif
#define UFS_SMALL_CGBASE
#include "ufsread.c"
#ifdef DEBUG
#define DPRINTF(fmt, ...) printf(fmt, __VA_ARGS__)
#else
#define DPRINTF(fmt, ...)
#endif
static inline int
xfsread(ufs_ino_t inode, void *buf, size_t nbyte)
{
if ((size_t)fsread(inode, buf, nbyte) != nbyte)
return -1;
return 0;
}
static inline void
getstr(int c)
{
char *s;
s = cmd;
if (c == 0)
c = getc(10000);
for (;;) {
switch (c) {
case 0:
break;
case '\177':
case '\b':
if (s > cmd) {
s--;
printf("\b \b");
}
break;
case '\n':
case '\r':
*s = 0;
return;
default:
if (s - cmd < sizeof(cmd) - 1)
*s++ = c;
xputchar(c);
}
c = getc(10000);
}
}
int
main(void)
{
int autoboot, c = 0;
ufs_ino_t ino;
dmadat = (void *)(0x20000000 + (16 << 20));
board_init();
autoboot = 1;
/* Process configuration file */
if ((ino = lookup(PATH_CONFIG)) ||
(ino = lookup(PATH_DOTCONFIG)))
fsread(ino, cmd, sizeof(cmd));
if (*cmd) {
if (parse())
autoboot = 0;
printf("%s: %s\n", PATH_CONFIG, cmd);
/* Do not process this command twice */
*cmd = 0;
}
if (*kname == '\0')
strcpy(kname, PATH_KERNEL);
/* Present the user with the boot2 prompt. */
for (;;) {
printf("\nDefault: %s\nboot: ", kname);
if (!autoboot ||
(OPT_CHECK(RBX_NOINTR) == 0 && (c = getc(2)) != 0))
getstr(c);
xputchar('\n');
autoboot = 0;
c = 0;
if (parse())
xputchar('\a');
else
load();
}
return (1);
}
static void
load(void)
{
Elf32_Ehdr eh;
static Elf32_Phdr ep[2];
caddr_t p;
ufs_ino_t ino;
uint32_t addr;
int i, j;
#ifdef FIXUP_BOOT_DRV
caddr_t staddr;
int klen;
staddr = (caddr_t)0xffffffff;
klen = 0;
#endif
if (!(ino = lookup(kname))) {
if (!ls)
printf("No %s\n", kname);
return;
}
if (xfsread(ino, &eh, sizeof(eh)))
return;
if (!IS_ELF(eh)) {
printf("Invalid %s\n", "format");
return;
}
fs_off = eh.e_phoff;
for (j = i = 0; i < eh.e_phnum && j < 2; i++) {
if (xfsread(ino, ep + j, sizeof(ep[0])))
return;
if (ep[j].p_type == PT_LOAD)
j++;
}
for (i = 0; i < 2; i++) {
p = (caddr_t)ep[i].p_paddr;
fs_off = ep[i].p_offset;
#ifdef FIXUP_BOOT_DRV
if (staddr == (caddr_t)0xffffffff)
staddr = p;
klen += ep[i].p_filesz;
#endif
if (xfsread(ino, p, ep[i].p_filesz))
return;
}
addr = eh.e_entry;
#ifdef FIXUP_BOOT_DRV
fixup_boot_drv(staddr, klen, bootslice, bootpart);
#endif
((void(*)(int, int, int, int))addr)(opts & RBX_MASK, board_id, 0, 0);
}
static int
parse()
{
char *arg = cmd;
char *ep, *p;
int c, i;
while ((c = *arg++)) {
if (c == ' ' || c == '\t' || c == '\n')
continue;
for (p = arg; *p && *p != '\n' && *p != ' ' && *p != '\t'; p++);
ep = p;
if (*p)
*p++ = 0;
if (c == '-') {
while ((c = *arg++)) {
for (i = 0; c != optstr[i]; i++)
if (i == NOPT - 1)
return -1;
opts ^= OPT_SET(bootflags[i]);
}
} else {
arg--;
if ((i = ep - arg)) {
if ((size_t)i >= sizeof(kname))
return -1;
memcpy(kname, arg, i + 1);
}
}
arg = p;
}
return 0;
}
static int
dskread(void *buf, unsigned lba, unsigned nblk)
{
struct dos_partition *dp;
struct disklabel *d;
char *sec;
int i;
if (!dsk_meta) {
sec = dmadat->secbuf;
dsk_start = 0;
if (drvread(sec, DOSBBSECTOR, 1))
return -1;
dp = (void *)(sec + DOSPARTOFF);
for (i = 0; i < NDOSPART; i++) {
if (dp[i].dp_typ == DOSPTYP_386BSD)
break;
}
if (i == NDOSPART)
return -1;
/*
* Although dp_start is aligned within the disk
* partition structure, DOSPARTOFF is 446, which is
* only word (2) aligned, not longword (4) aligned.
* Cope by using memcpy to fetch the start of this
* partition.
*/
memcpy(&dsk_start, &dp[1].dp_start, 4);
if (drvread(sec, dsk_start + LABELSECTOR, 1))
return -1;
d = (void *)(sec + LABELOFFSET);
if (d->d_magic != DISKMAGIC || d->d_magic2 != DISKMAGIC) {
printf("Invalid %s\n", "label");
return -1;
}
if (!d->d_partitions[0].p_size) {
printf("Invalid %s\n", "partition");
return -1;
}
dsk_start += d->d_partitions[0].p_offset;
dsk_start -= d->d_partitions[RAW_PART].p_offset;
dsk_meta++;
}
return drvread(buf, dsk_start + lba, nblk);
}
#ifdef FIXUP_BOOT_DRV
/*
* fixup_boot_drv() will try to find the ROOTDEVNAME spec in the kernel
* and change it to what was specified on the comandline or /boot.conf
* file or to what was encountered on the disk. It will try to handle 3
* different disk layouts, raw (dangerously dedicated), slice only and
* slice + partition. It will look for the following strings in the
* kernel, but if it is one of the first three, the string in the kernel
* must use the correct form to match the actual disk layout:
* - ufs:ad0a
* - ufs:ad0s1
* - ufs:ad0s1a
* - ufs:ROOTDEVNAME
* In the case of the first three strings, only the "a" at the end and
* the "1" after the "s" will be modified, if they exist. The string
* length will not be changed. In the case of the last string, the
* whole string will be built up and nul, '\0' terminated.
*/
static void
fixup_boot_drv(caddr_t addr, int klen, int bs, int bp)
{
const u_int8_t op[] = "ufs:ROOTDEVNAME";
const u_int8_t op2[] = "ufs:ad0";
u_int8_t *p, *ps;
DPRINTF("fixup_boot_drv: 0x%x, %d, slice %d, partition %d\n",
(int)addr, klen, bs, bp);
if (bs > 4)
return;
if (bp > 7)
return;
ps = memmem(addr, klen, op, sizeof(op));
if (ps != NULL) {
p = ps + 4; /* past ufs: */
DPRINTF("Found it at 0x%x\n", (int)ps);
p[0] = 'a'; p[1] = 'd'; p[2] = '0'; /* ad0 */
p += 3;
if (bs > 0) {
/* append slice */
*p++ = 's';
*p++ = bs + '0';
}
if (disk_layout != DL_SLICE) {
/* append partition */
*p++ = bp + 'a';
}
*p = '\0';
} else {
ps = memmem(addr, klen, op2, sizeof(op2) - 1);
if (ps != NULL) {
p = ps + sizeof(op2) - 1;
DPRINTF("Found it at 0x%x\n", (int)ps);
if (*p == 's') {
/* fix slice */
p++;
*p++ = bs + '0';
}
if (*p == 'a')
*p = bp + 'a';
}
}
if (ps == NULL) {
printf("Could not locate \"%s\" to fix kernel boot device, "
"check ROOTDEVNAME is set\n", op);
return;
}
DPRINTF("Changed boot device to %s\n", ps);
}
#endif
/* Arm EABIs */
void __aeabi_unwind_cpp_pr0(void);
void
__aeabi_unwind_cpp_pr0(void)
{
}

View File

@ -1,125 +0,0 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include "at91rm9200_lowlevel.h"
#include "at91rm9200.h"
#include "emac.h"
#include "lib.h"
#include "ee.h"
#include "board.h"
#include "sd-card.h"
unsigned char mac[6] = { 0x00, 0x0e, 0x42, 0x02, 0x00, 0x28 };
static void USART0_Init();
static void USART1_Init();
static void USART2_Init();
static void USART3_Init();
static void DS1672_Init();
static void
DS1672_Init() {
char buf[] = {0x00, 0xa9};
EEWrite(0xd0, buf, sizeof(buf));
}
static void
USART0_Init() {
AT91PS_PIO pPio = (AT91PS_PIO)AT91C_BASE_PIOA;
AT91PS_PMC pPMC = (AT91PS_PMC)AT91C_BASE_PMC;
// setup GPIO
pPio->PIO_ASR = AT91C_PA17_TXD0 | AT91C_PA18_RXD0;
pPio->PIO_PDR = AT91C_PA17_TXD0 | AT91C_PA18_RXD0;
// enable power
pPMC->PMC_PCER = 1u << AT91C_ID_US0;
}
static void
USART1_Init() {
AT91PS_PIO pPio = (AT91PS_PIO)AT91C_BASE_PIOA;
AT91PS_PMC pPMC = (AT91PS_PMC)AT91C_BASE_PMC;
// setup GPIO
pPio->PIO_ASR = AT91C_PB20_TXD1 | AT91C_PB21_RXD1;
pPio->PIO_PDR = AT91C_PB20_TXD1 | AT91C_PB21_RXD1;
// enable power
pPMC->PMC_PCER = 1u << AT91C_ID_US1;
}
static void
USART2_Init() {
AT91PS_PIO pPio = (AT91PS_PIO)AT91C_BASE_PIOA;
AT91PS_PMC pPMC = (AT91PS_PMC)AT91C_BASE_PMC;
// setup GPIO
pPio->PIO_ASR = AT91C_PA23_TXD2 | AT91C_PA22_RXD2;
pPio->PIO_PDR = AT91C_PA23_TXD2 | AT91C_PA22_RXD2;
// enable power
pPMC->PMC_PCER = 1u << AT91C_ID_US2;
}
static void
USART3_Init() {
AT91PS_PIO pPio = (AT91PS_PIO)AT91C_BASE_PIOA;
AT91PS_PMC pPMC = (AT91PS_PMC)AT91C_BASE_PMC;
// setup GPIO
pPio->PIO_BSR = AT91C_PA5_TXD3 | AT91C_PA6_RXD3;
pPio->PIO_PDR = AT91C_PA5_TXD3 | AT91C_PA6_RXD3;
// enable power
pPMC->PMC_PCER = 1u << AT91C_ID_US3;
}
void
board_init(void)
{
printf("\n\n");
printf("BWCT FSB-A920-1\n");
printf("http://www.bwct.de\n");
printf("\n");
#if defined(SDRAM_128M)
printf("AT92RM9200 180MHz 128MB\n");
#else
printf("AT92RM9200 180MHz 64MB\n");
#endif
printf("Initialising USART0\n");
USART0_Init();
printf("Initialising USART1\n");
USART1_Init();
printf("Initialising USART2\n");
USART2_Init();
printf("Initialising USART3\n");
USART3_Init();
printf("Initialising TWI\n");
EEInit();
printf("Initialising DS1672\n");
DS1672_Init();
printf("Initialising Ethernet\n");
printf("MAC %x:%x:%x:%x:%x:%x\n", mac[0],
mac[1], mac[2], mac[3], mac[4], mac[5]);
EMAC_Init();
EMAC_SetMACAddress(mac);
printf("Initialising SD-card\n");
sdcard_init();
}
#include "../bootspi/ee.c"
int
drvread(void *buf, unsigned lba, unsigned nblk)
{
return (MCI_read((char *)buf, lba << 9, nblk << 9));
}

View File

@ -1,68 +0,0 @@
/*-
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include "emac.h"
#include "lib.h"
#include "board.h"
#include "sd-card.h"
unsigned char mac[6] = { 0x42, 0x53, 0x44, 0, 1, 1 };
static void
MacFromEE()
{
#if 0
uint32_t sig;
sig = 0;
ReadEEPROM(12 * 1024, (uint8_t *)&sig, sizeof(sig));
if (sig != 0x92021054)
return;
ReadEEPROM(12 * 1024 + 4, mac, 6);
#endif
printf("MAC %x:%x:%x:%x:%x:%x\n", mac[0],
mac[1], mac[2], mac[3], mac[4], mac[5]);
}
void
board_init(void)
{
InitEEPROM();
MacFromEE();
EMAC_Init();
EMAC_SetMACAddress(mac);
while (sdcard_init() == 0)
printf("Looking for SD card\n");
}
int
drvread(void *buf, unsigned lba, unsigned nblk)
{
return (MCI_read((char *)buf, lba << 9, nblk << 9));
}

View File

@ -1,66 +0,0 @@
/*-
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include "emac.h"
#include "lib.h"
#include "board.h"
#include "sd-card.h"
unsigned char mac[6] = { 0x42, 0x53, 0x44, 0, 0, 1 };
static void
MacFromEE()
{
uint32_t sig;
sig = 0;
ReadEEPROM(12 * 1024, (uint8_t *)&sig, sizeof(sig));
if (sig != 0x92021054)
return;
ReadEEPROM(12 * 1024 + 4, mac, 6);
printf("MAC %x:%x:%x:%x:%x:%x\n", mac[0],
mac[1], mac[2], mac[3], mac[4], mac[5]);
}
void
board_init(void)
{
InitEEPROM();
MacFromEE();
EMAC_Init();
EMAC_SetMACAddress(mac);
while (sdcard_init() == 0)
printf("Looking for SD card\n");
}
int
drvread(void *buf, unsigned lba, unsigned nblk)
{
return (MCI_read((char *)buf, lba << 9, nblk << 9));
}

View File

@ -1,14 +0,0 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../libat91
P=bootiic
FILES=${P}
SRCS=arm_init.S main.c loader_prompt.c env_vars.c
MAN=
LDFLAGS=-e 0 -T ${.CURDIR}/../linker.cfg
OBJS+= ${SRCS:N*.h:R:S/$/.o/g}
.include <bsd.prog.mk>
CFLAGS += -DBOOT_IIC -DBOOT_COMMANDS

View File

@ -1,35 +0,0 @@
$FreeBSD$
This image is intended to be programmed into boot EEPROM. The image is nearly
0x4000 so it will not fit in KB9200's 0x2000. It is intended for KB9201 or
later. Alternatively, the KB9200 can be upgraded with larger EEPROM.
It performs basic functions prior to executing an image at a
specified address. The pre-boot functions can be modified and saved back into
EEPROM.
The MAC address is set with 0.0.0.0.0.0 by default. This is an invalid address
and must be changed to a valid value in order to use the ethernet interface.
Memory usage:
EEPROM = 0x4000
SDRAM =
run stack = 0x21800000
variables = 0x21200000
ethernet = 0x21000000 (buffers and descriptors)
Functions supported:
c - copy
d - display auto command table (in RAM)
e - execute image
? - help
ip - set local ip
m - set mac
server_ip - set server ip
s - set auto command entry
t - create linux boot tag list
tftp - download image via tftp
w - update auto command table
x - download image via xmodem

View File

@ -1,207 +0,0 @@
/******************************************************************************
*
* Filename: env_vars.c
*
* Instantiation of environment variables, structures, and other globals.
*
* Revision information:
*
* 20AUG2004 kb_admin initial creation
*
* BEGIN_KBDD_BLOCK
* No warranty, expressed or implied, is included with this software. It is
* provided "AS IS" and no warranty of any kind including statutory or aspects
* relating to merchantability or fitness for any purpose is provided. All
* intellectual property rights of others is maintained with the respective
* owners. This software is not copyrighted and is intended for reference
* only.
* END_BLOCK
*
* $FreeBSD$
*****************************************************************************/
#include "env_vars.h"
#include "loader_prompt.h"
#include "lib.h"
/******************************* GLOBALS *************************************/
char boot_commands[MAX_BOOT_COMMANDS][MAX_INPUT_SIZE];
char env_table[MAX_ENV_SIZE_BYTES];
extern char BootCommandSection;
/************************** PRIVATE FUNCTIONS ********************************/
static int currentIndex;
static int currentOffset;
/*
* .KB_C_FN_DEFINITION_START
* int ReadCharFromEnvironment(char *)
* This private function reads characters from the environment variables
* to service the command prompt during auto-boot or just to setup the
* default environment. Returns positive value if valid character was
* set in the pointer. Returns negative value to signal input stream
* terminated. Returns 0 to indicate _wait_ condition.
* .KB_C_FN_DEFINITION_END
*/
static int
ReadCharFromEnvironment(int timeout)
{
int ch;
if (currentIndex < MAX_BOOT_COMMANDS) {
ch = boot_commands[currentIndex][currentOffset++];
if (ch == '\0' || (currentOffset >= MAX_INPUT_SIZE)) {
currentOffset = 0;
++currentIndex;
ch = '\r';
}
return (ch);
}
return (-1);
}
/*************************** GLOBAL FUNCTIONS ********************************/
/*
* .KB_C_FN_DEFINITION_START
* void WriteCommandTable(void)
* This global function write the current command table to the non-volatile
* memory.
* .KB_C_FN_DEFINITION_END
*/
void
WriteCommandTable(void)
{
int i, size = MAX_ENV_SIZE_BYTES, copySize;
char *cPtr = env_table;
p_memset(env_table, 0, sizeof(env_table));
for (i = 0; i < MAX_BOOT_COMMANDS; ++i) {
copySize = p_strlen(boot_commands[i]);
size -= copySize + 1;
if (size < 0) {
continue;
}
memcpy(cPtr, boot_commands[i], copySize);
cPtr += copySize;
*cPtr++ = 0;
}
/* We're executing in low RAM so addr in ram == offset in eeprom */
WriteEEPROM((unsigned)&BootCommandSection, env_table,
sizeof(env_table));
}
/*
* .KB_C_FN_DEFINITION_START
* void SetBootCommand(int index, char *command)
* This global function replaces the specified index with the string residing
* at command. Execute this function with a NULL string to clear the
* associated command index.
* .KB_C_FN_DEFINITION_END
*/
void
SetBootCommand(int index, char *command)
{
int i;
if ((unsigned)index < MAX_BOOT_COMMANDS) {
p_memset(boot_commands[index], 0, MAX_INPUT_SIZE);
if (!command)
return ;
for (i = 0; i < MAX_INPUT_SIZE; ++i) {
boot_commands[index][i] = command[i];
if (!(boot_commands[index][i]))
return;
}
}
}
/*
* .KB_C_FN_DEFINITION_START
* void DumpBootCommands(void)
* This global function displays the current boot commands.
* .KB_C_FN_DEFINITION_END
*/
void
DumpBootCommands(void)
{
int i, j;
for (i = 0; i < MAX_BOOT_COMMANDS; ++i) {
printf("0x%x : ", i);
for (j = 0; j < MAX_INPUT_SIZE; ++j) {
putchar(boot_commands[i][j]);
if (!(boot_commands[i][j]))
break;
}
printf("[E]\n\r");
}
}
/*
* .KB_C_FN_DEFINITION_START
* void LoadBootCommands(void)
* This global function loads the existing boot commands from raw format and
* coverts it to the standard, command-index format. Notice, the processed
* boot command table has much more space allocated than the actual table
* stored in non-volatile memory. This is because the processed table
* exists in RAM which is larger than the non-volatile space.
* .KB_C_FN_DEFINITION_END
*/
void
LoadBootCommands(void)
{
int index, j, size;
char *cPtr;
p_memset((char*)boot_commands, 0, sizeof(boot_commands));
cPtr = &BootCommandSection;
size = MAX_ENV_SIZE_BYTES;
for (index = 0; (index < MAX_BOOT_COMMANDS) && size; ++index) {
for (j = 0; (j < MAX_INPUT_SIZE) && size; ++j) {
size--;
boot_commands[index][j] = *cPtr++;
if (!(boot_commands[index][j])) {
break;
}
}
}
}
/*
* .KB_C_FN_DEFINITION_START
* void ExecuteEnvironmentFunctions(void)
* This global function executes applicable entries in the environment.
* .KB_C_FN_DEFINITION_END
*/
void
ExecuteEnvironmentFunctions(void)
{
currentIndex = 0;
currentOffset = 0;
DumpBootCommands();
Bootloader(ReadCharFromEnvironment);
}

View File

@ -1,54 +0,0 @@
/******************************************************************************
*
* Filename: env_vars.h
*
* Definition of environment variables, structures, and other globals.
*
* Revision information:
*
* 20AUG2004 kb_admin initial creation
*
* BEGIN_KBDD_BLOCK
* No warranty, expressed or implied, is included with this software. It is
* provided "AS IS" and no warranty of any kind including statutory or aspects
* relating to merchantability or fitness for any purpose is provided. All
* intellectual property rights of others is maintained with the respective
* owners. This software is not copyrighted and is intended for reference
* only.
* END_BLOCK
*
* $FreeBSD$
*****************************************************************************/
#ifndef _ENV_VARS_H_
#define _ENV_VARS_H_
/* each environment variable is a string following the standard command */
/* definition used by the interactive loader in the following format: */
/* <command> <parm1> <parm2> ... */
/* all environment variables (or commands) are stored in a string */
/* format: NULL-terminated. */
/* this implies that commands can never utilize 0-values: actual 0, not */
/* the string '0'. this is not an issue as the string '0' is handled */
/* by the command parse routine. */
/* the following defines the maximum size of the environment for */
/* including variables. */
/* this value must match that declared in the low-level file that */
/* actually reserves the space for the non-volatile environment. */
#define MAX_ENV_SIZE_BYTES 0x100
#define MAX_BOOT_COMMANDS 10
/* C-style reference section */
#ifndef __ASSEMBLY__
extern void WriteCommandTable(void);
extern void SetBootCommand(int index, char *command);
extern void DumpBootCommands(void);
extern void LoadBootCommands(void);
extern void ExecuteEnvironmentFunctions(void);
#endif /* !__ASSEMBLY__ */
#endif /* _ENV_VARS_H_ */

View File

@ -1,387 +0,0 @@
/******************************************************************************
*
* Filename: loader_prompt.c
*
* Instantiation of the interactive loader functions.
*
* Revision information:
*
* 20AUG2004 kb_admin initial creation
* 12JAN2005 kb_admin massive changes for tftp, strings, and more
* 05JUL2005 kb_admin save tag address, and set registers on boot
*
* BEGIN_KBDD_BLOCK
* No warranty, expressed or implied, is included with this software. It is
* provided "AS IS" and no warranty of any kind including statutory or aspects
* relating to merchantability or fitness for any purpose is provided. All
* intellectual property rights of others is maintained with the respective
* owners. This software is not copyrighted and is intended for reference
* only.
* END_BLOCK
*
* $FreeBSD$
*****************************************************************************/
#include "at91rm9200_lowlevel.h"
#ifdef SUPPORT_TAG_LIST
#include "tag_list.h"
#endif
#include "emac.h"
#include "loader_prompt.h"
#include "env_vars.h"
#include "lib.h"
/******************************* GLOBALS *************************************/
/*********************** PRIVATE FUNCTIONS/DATA ******************************/
static char inputBuffer[MAX_INPUT_SIZE];
static int buffCount;
// argv pointer are either NULL or point to locations in inputBuffer
static char *argv[MAX_COMMAND_PARAMS];
static const char *backspaceString = "\010 \010";
static const command_entry_t CommandTable[] = {
{COMMAND_COPY, "c"},
{COMMAND_DUMP, "d"},
{COMMAND_EXEC, "e"},
{COMMAND_HELP, "?"},
{COMMAND_LOCAL_IP, "ip"},
{COMMAND_MAC, "m"},
{COMMAND_SERVER_IP, "server_ip"},
{COMMAND_SET, "s"},
#ifdef SUPPORT_TAG_LIST
{COMMAND_TAG, "t"},
#endif
{COMMAND_TFTP, "tftp"},
{COMMAND_WRITE, "w"},
{COMMAND_XMODEM, "x"},
{COMMAND_FINAL_FLAG, 0}
};
static unsigned tagAddress;
/*
* .KB_C_FN_DEFINITION_START
* unsigned BuildIP(void)
* This private function packs the test IP info to an unsigned value.
* .KB_C_FN_DEFINITION_END
*/
static unsigned
BuildIP(void)
{
return ((p_ASCIIToDec(argv[1]) << 24) |
(p_ASCIIToDec(argv[2]) << 16) |
(p_ASCIIToDec(argv[3]) << 8) |
p_ASCIIToDec(argv[4]));
}
/*
* .KB_C_FN_DEFINITION_START
* int StringToCommand(char *cPtr)
* This private function converts a command string to a command code.
* .KB_C_FN_DEFINITION_END
*/
static int
StringToCommand(char *cPtr)
{
int i;
for (i = 0; CommandTable[i].command != COMMAND_FINAL_FLAG; ++i)
if (!strcmp(CommandTable[i].c_string, cPtr))
return (CommandTable[i].command);
return (COMMAND_INVALID);
}
/*
* .KB_C_FN_DEFINITION_START
* void RestoreSpace(int)
* This private function restores NULL characters to spaces in order to
* process the remaining args as a string. The number passed is the argc
* of the first entry to begin restoring space in the inputBuffer.
* .KB_C_FN_DEFINITION_END
*/
static void
RestoreSpace(int startArgc)
{
char *cPtr;
for (startArgc++; startArgc < MAX_COMMAND_PARAMS; startArgc++) {
if ((cPtr = argv[startArgc]))
*(cPtr - 1) = ' ';
}
}
/*
* .KB_C_FN_DEFINITION_START
* int BreakCommand(char *)
* This private function splits the buffer into separate strings as pointed
* by argv and returns the number of parameters (< 0 on failure).
* .KB_C_FN_DEFINITION_END
*/
static int
BreakCommand(char *buffer)
{
int pCount, cCount, state;
state = pCount = 0;
p_memset((char*)argv, 0, sizeof(argv));
for (cCount = 0; cCount < MAX_INPUT_SIZE; ++cCount) {
if (!state) {
/* look for next command */
if (!p_IsWhiteSpace(buffer[cCount])) {
argv[pCount++] = &buffer[cCount];
state = 1;
} else {
buffer[cCount] = 0;
}
} else {
/* in command, find next white space */
if (p_IsWhiteSpace(buffer[cCount])) {
buffer[cCount] = 0;
state = 0;
}
}
if (pCount >= MAX_COMMAND_PARAMS) {
return (-1);
}
}
return (pCount);
}
/*
* .KB_C_FN_DEFINITION_START
* void ParseCommand(char *)
* This private function executes matching functions.
* .KB_C_FN_DEFINITION_END
*/
static void
ParseCommand(char *buffer)
{
int argc, i;
if ((argc = BreakCommand(buffer)) < 1)
return;
switch (StringToCommand(argv[0])) {
case COMMAND_COPY:
{
// "c <to> <from> <size in bytes>"
// copy memory
char *to, *from;
unsigned size;
if (argc > 3) {
to = (char *)p_ASCIIToHex(argv[1]);
from = (char *)p_ASCIIToHex(argv[2]);
size = p_ASCIIToHex(argv[3]);
memcpy(to, from, size);
}
break;
}
case COMMAND_DUMP:
// display boot commands
DumpBootCommands();
break;
case COMMAND_EXEC:
{
// "e <address>"
// execute at address
void (*execAddr)(unsigned, unsigned, unsigned);
if (argc > 1) {
/* in future, include machtypes (MACH_KB9200 = 612) */
execAddr = (void (*)(unsigned, unsigned, unsigned))
p_ASCIIToHex(argv[1]);
(*execAddr)(0, 612, tagAddress);
}
break;
}
case COMMAND_TFTP:
{
// "tftp <local_dest_addr filename>"
// tftp download
unsigned address = 0;
if (argc > 2)
address = p_ASCIIToHex(argv[1]);
TFTP_Download(address, argv[2]);
break;
}
case COMMAND_SERVER_IP:
// "server_ip <server IP 192 200 1 20>"
// set download server address
if (argc > 4)
SetServerIPAddress(BuildIP());
break;
case COMMAND_HELP:
// dump command info
printf("Commands:\n"
"\tc\n"
"\td\n"
"\te\n"
"\tip\n"
"\tserver_ip\n"
"\tm\n"
"\ttftp\n"
"\ts\n"
#ifdef SUPPORT_TAG_LIST
"\tt\n"
#endif
"\tw\n"
"\tx\n");
break;
case COMMAND_LOCAL_IP:
// "local_ip <local IP 192 200 1 21>
// set ip of this module
if (argc > 4)
SetLocalIPAddress(BuildIP());
break;
case COMMAND_MAC:
{
// "m <mac address 12 34 56 78 9a bc>
// set mac address using 6 byte values
unsigned char mac[6];
if (argc > 6) {
for (i = 0; i < 6; i++)
mac[i] = p_ASCIIToHex(argv[i + 1]);
EMAC_SetMACAddress(mac);
}
break;
}
case COMMAND_SET:
{
// s <index> <new boot command>
// set the boot command at index (0-based)
unsigned index;
if (argc > 1) {
RestoreSpace(2);
index = p_ASCIIToHex(argv[1]);
SetBootCommand(index, argv[2]);
}
break;
}
#ifdef SUPPORT_TAG_LIST
case COMMAND_TAG:
// t <address> <boot command line>
// create tag-list for linux boot
if (argc > 2) {
RestoreSpace(2);
tagAddress = p_ASCIIToHex(argv[1]);
InitTagList(argv[2], (void*)tagAddress);
}
break;
#endif
case COMMAND_WRITE:
// write the command table to non-volatile
WriteCommandTable();
break;
case COMMAND_XMODEM:
{
// "x <address>"
// download X-modem record at address
if (argc > 1)
xmodem_rx((char *)p_ASCIIToHex(argv[1]));
break;
}
default:
break;
}
printf("\n");
}
/*
* .KB_C_FN_DEFINITION_START
* void ServicePrompt(char)
* This private function process each character checking for valid commands.
* This function is only executed if the character is considered valid.
* Each command is terminated with NULL (0) or ''.
* .KB_C_FN_DEFINITION_END
*/
static void
ServicePrompt(char p_char)
{
if (p_char == '\r')
p_char = 0;
if (p_char == '\010') {
if (buffCount) {
/* handle backspace BS */
inputBuffer[--buffCount] = 0;
printf(backspaceString);
}
return;
}
if (buffCount < MAX_INPUT_SIZE - 1) {
inputBuffer[buffCount++] = p_char;
putchar(p_char);
}
if (!p_char) {
printf("\n");
ParseCommand(inputBuffer);
p_memset(inputBuffer, 0, MAX_INPUT_SIZE);
buffCount = 0;
printf("\n>");
}
}
/* ************************** GLOBAL FUNCTIONS ********************************/
/*
* .KB_C_FN_DEFINITION_START
* void Bootloader(void *inputFunction)
* This global function is the entry point for the bootloader. If the
* inputFunction pointer is NULL, the loader input will be serviced from
* the uart. Otherwise, inputFunction is called to get characters which
* the loader will parse.
* .KB_C_FN_DEFINITION_END
*/
void
Bootloader(int(*inputFunction)(int))
{
int ch = 0;
p_memset((void*)inputBuffer, 0, sizeof(inputBuffer));
buffCount = 0;
if (!inputFunction) {
inputFunction = getc;
}
printf("\n>");
while (1)
if ((ch = ((*inputFunction)(0))) > 0)
ServicePrompt(ch);
}

View File

@ -1,55 +0,0 @@
/******************************************************************************
*
* Filename: loader_prompt.h
*
* Definition of the interactive loader functions.
*
* Revision information:
*
* 20AUG2004 kb_admin initial creation
*
* BEGIN_KBDD_BLOCK
* No warranty, expressed or implied, is included with this software. It is
* provided "AS IS" and no warranty of any kind including statutory or aspects
* relating to merchantability or fitness for any purpose is provided. All
* intellectual property rights of others is maintained with the respective
* owners. This software is not copyrighted and is intended for reference
* only.
* END_BLOCK
*
* $FreeBSD$
*****************************************************************************/
#ifndef _LOADER_PROMPT_H_
#define _LOADER_PROMPT_H_
#define MAX_INPUT_SIZE 256
#define MAX_COMMAND_PARAMS 10
enum {
COMMAND_INVALID = 0,
COMMAND_COPY,
COMMAND_DUMP,
COMMAND_EXEC,
COMMAND_HELP,
COMMAND_LOCAL_IP,
COMMAND_MAC,
COMMAND_SERVER_IP,
COMMAND_SET,
COMMAND_TAG,
COMMAND_TFTP,
COMMAND_WRITE,
COMMAND_XMODEM,
COMMAND_FINAL_FLAG
} e_cmd_t;
typedef struct {
int command;
const char *c_string;
} command_entry_t;
void EnterInteractiveBootloader(int(*inputFunction)(int));
void Bootloader(int(*inputFunction)(int));
#endif /* _LOADER_PROMPT_H_ */

View File

@ -1,55 +0,0 @@
/*******************************************************************************
*
* Filename: main.c
*
* Basic entry points for top-level functions
*
* Revision information:
*
* 20AUG2004 kb_admin initial creation
* 12JAN2005 kb_admin cosmetic changes
* 29APR2005 kb_admin modified boot delay
*
* BEGIN_KBDD_BLOCK
* No warranty, expressed or implied, is included with this software. It is
* provided "AS IS" and no warranty of any kind including statutory or aspects
* relating to merchantability or fitness for any purpose is provided. All
* intellectual property rights of others is maintained with the respective
* owners. This software is not copyrighted and is intended for reference
* only.
* END_BLOCK
*
* $FreeBSD$
******************************************************************************/
#include "env_vars.h"
#include "at91rm9200_lowlevel.h"
#include "loader_prompt.h"
#include "emac.h"
#include "lib.h"
int main(void);
/*
* .KB_C_FN_DEFINITION_START
* int main(void)
* This global function waits at least one second, but not more than two
* seconds, for input from the serial port. If no response is recognized,
* it acts according to the parameters specified by the environment. For
* example, the function might boot an operating system. Do not return
* from this function.
* .KB_C_FN_DEFINITION_END
*/
int
main(void)
{
InitEEPROM();
EMAC_Init();
LoadBootCommands();
printf("\n\rKB9202(www.kwikbyte.com)\n\rAuto boot..\n\r");
if (getc(1) == -1)
ExecuteEnvironmentFunctions();
Bootloader(0);
return (1);
}

View File

@ -1,19 +0,0 @@
# $FreeBSD$
.include <src.opts.mk>
.PATH: ${.CURDIR}/../libat91
P=bootspi
FILES=${P}
SRCS=arm_init.S main.c loader_prompt.c env_vars.c ee.c
MAN=
LDFLAGS=-e 0 -T ${.CURDIR}/../linker.cfg
OBJS+= ${SRCS:N*.h:R:S/$/.o/g}
.include <bsd.prog.mk>
.if ${MK_FPGA} == "yes"
CFLAGS += -DTSC_FPGA
.endif
CFLAGS += -DBOOT_COMMANDS

View File

@ -1,34 +0,0 @@
$FreeBSD$
This image is intended to be programmed into boot EEPROM. The image is nearly
0x4000 so it will not fit in KB9200's 0x2000. It is intended for KB9201 or
later. Alternatively, the KB9200 can be upgraded with larger EEPROM.
It performs basic functions prior to executing an image at a
specified address. The pre-boot functions can be modified and saved back into
EEPROM.
The MAC address is set with 0.0.0.0.0.0 by default. This is an invalid address
and must be changed to a valid value in order to use the ethernet interface.
Memory usage:
EEPROM = 0x4000
SDRAM =
run stack = 0x21800000
variables = 0x21200000
ethernet = 0x21000000 (buffers and descriptors)
Functions supported:
c - copy
d - display auto command table (in RAM)
e - execute image
? - help
ip - set local ip
m - set mac
server_ip - set server ip
s - set auto command entry
t - create linux boot tag list
tftp - download image via tftp
w - update auto command table
x - download image via xmodem

View File

@ -1,160 +0,0 @@
/******************************************************************************
*
* Filename: eeprom.c
*
* Instantiation of eeprom routines
*
* Revision information:
*
* 28AUG2004 kb_admin initial creation - adapted from Atmel sources
* 12JAN2005 kb_admin fixed clock generation, write polling, init
*
* BEGIN_KBDD_BLOCK
* No warranty, expressed or implied, is included with this software. It is
* provided "AS IS" and no warranty of any kind including statutory or aspects
* relating to merchantability or fitness for any purpose is provided. All
* intellectual property rights of others is maintained with the respective
* owners. This software is not copyrighted and is intended for reference
* only.
* END_BLOCK
*
* $FreeBSD$
*****************************************************************************/
#include "at91rm9200_lowlevel.h"
#include "at91rm9200.h"
#include "lib.h"
#include "ee.h"
/******************************* GLOBALS *************************************/
/*********************** PRIVATE FUNCTIONS/DATA ******************************/
/* Use a macro to calculate the TWI clock generator value to save code space. */
#define AT91C_TWSI_CLOCK 100000
#define TWSI_EEPROM_ADDRESS 0x40
#define TWI_CLK_BASE_DIV ((AT91C_MASTER_CLOCK/(4*AT91C_TWSI_CLOCK)) - 2)
#define SET_TWI_CLOCK ((0x00010000) | (TWI_CLK_BASE_DIV) | (TWI_CLK_BASE_DIV << 8))
/*************************** GLOBAL FUNCTIONS ********************************/
/*
* .KB_C_FN_DEFINITION_START
* void InitEEPROM(void)
* This global function initializes the EEPROM interface (TWI). Intended
* to be called a single time.
* .KB_C_FN_DEFINITION_END
*/
void
EEInit(void)
{
AT91PS_TWI twiPtr = (AT91PS_TWI)AT91C_BASE_TWI;
AT91PS_PIO pPio = (AT91PS_PIO)AT91C_BASE_PIOA;
AT91PS_PMC pPMC = (AT91PS_PMC)AT91C_BASE_PMC;
pPio->PIO_ASR = AT91C_PIO_PA25 | AT91C_PIO_PA26;
pPio->PIO_PDR = AT91C_PIO_PA25 | AT91C_PIO_PA26;
pPio->PIO_MDDR = ~AT91C_PIO_PA25;
pPio->PIO_MDER = AT91C_PIO_PA25;
pPMC->PMC_PCER = 1u << AT91C_ID_TWI;
twiPtr->TWI_IDR = 0xffffffffu;
twiPtr->TWI_CR = AT91C_TWI_SWRST;
twiPtr->TWI_CR = AT91C_TWI_MSEN | AT91C_TWI_SVDIS;
twiPtr->TWI_CWGR = SET_TWI_CLOCK;
}
static inline unsigned
iicaddr(unsigned ee_off)
{
return (TWSI_EEPROM_ADDRESS | ((ee_off >> 8) & 0x7));
}
/*
* .KB_C_FN_DEFINITION_START
* void ReadEEPROM(unsigned ee_addr, char *data_addr, unsigned size)
* This global function reads data from the eeprom at ee_addr storing data
* to data_addr for size bytes. Assume the TWI has been initialized.
* This function does not utilize the page read mode to simplify the code.
* .KB_C_FN_DEFINITION_END
*/
void
EERead(unsigned ee_off, char *data_addr, unsigned size)
{
const AT91PS_TWI twiPtr = AT91C_BASE_TWI;
unsigned int status;
if ((ee_off & ~0xff) != ((ee_off + size) & ~0xff)) {
printf("Crosses page boundary: 0x%x 0x%x\n", ee_off, size);
return;
}
status = twiPtr->TWI_SR;
status = twiPtr->TWI_RHR;
twiPtr->TWI_MMR = (iicaddr(ee_off) << 16) | AT91C_TWI_IADRSZ_1_BYTE |
AT91C_TWI_MREAD;
twiPtr->TWI_IADR = ee_off & 0xff;
twiPtr->TWI_CR = AT91C_TWI_START;
while (size-- > 1) {
while (!(twiPtr->TWI_SR & AT91C_TWI_RXRDY))
continue;
*(data_addr++) = twiPtr->TWI_RHR;
}
twiPtr->TWI_CR = AT91C_TWI_STOP;
status = twiPtr->TWI_SR;
while (!(twiPtr->TWI_SR & AT91C_TWI_TXCOMP))
continue;
*data_addr = twiPtr->TWI_RHR;
}
/*
* .KB_C_FN_DEFINITION_START
* void WriteEEPROM(unsigned ee_off, char *data_addr, unsigned size)
* This global function writes data to the eeprom at ee_off using data
* from data_addr for size bytes. Assume the TWI has been initialized.
* This function does not utilize the page write mode as the write time is
* much greater than the time required to access the device for byte-write
* functionality. This allows the function to be much simpler.
* .KB_C_FN_DEFINITION_END
*/
void
EEWrite(unsigned ee_off, const char *data_addr, unsigned size)
{
const AT91PS_TWI twiPtr = AT91C_BASE_TWI;
unsigned status;
char test_data;
while (size--) {
// Set the TWI Master Mode Register
twiPtr->TWI_MMR = (iicaddr(ee_off) << 16) |
AT91C_TWI_IADRSZ_1_BYTE;
twiPtr->TWI_IADR = ee_off++;
status = twiPtr->TWI_SR;
// Load one data byte
twiPtr->TWI_THR = *(data_addr++);
twiPtr->TWI_CR = AT91C_TWI_START;
while (!(twiPtr->TWI_SR & AT91C_TWI_TXRDY))
continue;
twiPtr->TWI_CR = AT91C_TWI_STOP;
status = twiPtr->TWI_SR;
while (!(twiPtr->TWI_SR & AT91C_TWI_TXCOMP))
continue;
// wait for write operation to complete, it is done once
// we can read it back...
EERead(ee_off, &test_data, 1);
}
}

View File

@ -1,6 +0,0 @@
/* $FreeBSD$ */
void EEInit(void);
void EERead(unsigned ee_off, char *data_addr, unsigned size);
void EEWrite(unsigned ee_off, const char *data_addr, unsigned size);

View File

@ -1,130 +0,0 @@
/******************************************************************************
*
* Filename: env_vars.c
*
* Instantiation of environment variables, structures, and other globals.
*
* Revision information:
*
* 20AUG2004 kb_admin initial creation
*
* BEGIN_KBDD_BLOCK
* No warranty, expressed or implied, is included with this software. It is
* provided "AS IS" and no warranty of any kind including statutory or aspects
* relating to merchantability or fitness for any purpose is provided. All
* intellectual property rights of others is maintained with the respective
* owners. This software is not copyrighted and is intended for reference
* only.
* END_BLOCK
*
* $FreeBSD$
*****************************************************************************/
#include "env_vars.h"
#include "loader_prompt.h"
#include "lib.h"
/******************************* GLOBALS *************************************/
char boot_commands[MAX_BOOT_COMMANDS][MAX_INPUT_SIZE];
char env_table[MAX_ENV_SIZE_BYTES];
extern char BootCommandSection;
/************************** PRIVATE FUNCTIONS ********************************/
static int currentIndex;
static int currentOffset;
/*
* .KB_C_FN_DEFINITION_START
* int ReadCharFromEnvironment(char *)
* This private function reads characters from the environment variables
* to service the command prompt during auto-boot or just to setup the
* default environment. Returns positive value if valid character was
* set in the pointer. Returns negative value to signal input stream
* terminated. Returns 0 to indicate _wait_ condition.
* .KB_C_FN_DEFINITION_END
*/
static int
ReadCharFromEnvironment(int timeout)
{
int ch;
if (currentIndex < MAX_BOOT_COMMANDS) {
ch = boot_commands[currentIndex][currentOffset++];
if (ch == '\0' || (currentOffset >= MAX_INPUT_SIZE)) {
currentOffset = 0;
++currentIndex;
ch = '\r';
}
return (ch);
}
return (-1);
}
/*************************** GLOBAL FUNCTIONS ********************************/
/*
* .KB_C_FN_DEFINITION_START
* void DumpBootCommands(void)
* This global function displays the current boot commands.
* .KB_C_FN_DEFINITION_END
*/
void
DumpBootCommands(void)
{
int i;
for (i = 0; boot_commands[i][0]; i++)
printf("0x%x : %s[E]\n", i, boot_commands[i]);
}
/*
* .KB_C_FN_DEFINITION_START
* void LoadBootCommands(void)
* This global function loads the existing boot commands from raw format and
* coverts it to the standard, command-index format. Notice, the processed
* boot command table has much more space allocated than the actual table
* stored in non-volatile memory. This is because the processed table
* exists in RAM which is larger than the non-volatile space.
* .KB_C_FN_DEFINITION_END
*/
void
LoadBootCommands(void)
{
int index, j;
char *cptr;
p_memset((char*)boot_commands, 0, sizeof(boot_commands));
cptr = &BootCommandSection;
for (index = 0; *cptr; index++) {
for (j = 0; *cptr; j++)
boot_commands[index][j] = *cptr++;
cptr++;
}
}
/*
* .KB_C_FN_DEFINITION_START
* void ExecuteEnvironmentFunctions(void)
* This global function executes applicable entries in the environment.
* .KB_C_FN_DEFINITION_END
*/
void
ExecuteEnvironmentFunctions(void)
{
currentIndex = 0;
currentOffset = 0;
DumpBootCommands();
printf("Autoboot...\n");
Bootloader(ReadCharFromEnvironment);
}

View File

@ -1,54 +0,0 @@
/******************************************************************************
*
* Filename: env_vars.h
*
* Definition of environment variables, structures, and other globals.
*
* Revision information:
*
* 20AUG2004 kb_admin initial creation
*
* BEGIN_KBDD_BLOCK
* No warranty, expressed or implied, is included with this software. It is
* provided "AS IS" and no warranty of any kind including statutory or aspects
* relating to merchantability or fitness for any purpose is provided. All
* intellectual property rights of others is maintained with the respective
* owners. This software is not copyrighted and is intended for reference
* only.
* END_BLOCK
*
* $FreeBSD$
*****************************************************************************/
#ifndef _ENV_VARS_H_
#define _ENV_VARS_H_
/* each environment variable is a string following the standard command */
/* definition used by the interactive loader in the following format: */
/* <command> <parm1> <parm2> ... */
/* all environment variables (or commands) are stored in a string */
/* format: NULL-terminated. */
/* this implies that commands can never utilize 0-values: actual 0, not */
/* the string '0'. this is not an issue as the string '0' is handled */
/* by the command parse routine. */
/* the following defines the maximum size of the environment for */
/* including variables. */
/* this value must match that declared in the low-level file that */
/* actually reserves the space for the non-volatile environment. */
#define MAX_ENV_SIZE_BYTES 0x100
#define MAX_BOOT_COMMANDS 10
/* C-style reference section */
#ifndef __ASSEMBLY__
extern void WriteCommandTable(void);
extern void SetBootCommand(int index, char *command);
extern void DumpBootCommands(void);
extern void LoadBootCommands(void);
extern void ExecuteEnvironmentFunctions(void);
#endif /* !__ASSEMBLY__ */
#endif /* _ENV_VARS_H_ */

View File

@ -1,363 +0,0 @@
/******************************************************************************
*
* Filename: loader_prompt.c
*
* Instantiation of the interactive loader functions.
*
* Revision information:
*
* 20AUG2004 kb_admin initial creation
* 12JAN2005 kb_admin massive changes for tftp, strings, and more
* 05JUL2005 kb_admin save tag address, and set registers on boot
*
* BEGIN_KBDD_BLOCK
* No warranty, expressed or implied, is included with this software. It is
* provided "AS IS" and no warranty of any kind including statutory or aspects
* relating to merchantability or fitness for any purpose is provided. All
* intellectual property rights of others is maintained with the respective
* owners. This software is not copyrighted and is intended for reference
* only.
* END_BLOCK
*
* $FreeBSD$
*****************************************************************************/
#include "at91rm9200_lowlevel.h"
#include "at91rm9200.h"
#include "emac.h"
#include "loader_prompt.h"
#include "env_vars.h"
#include "lib.h"
#include "spi_flash.h"
#include "ee.h"
/******************************* GLOBALS *************************************/
/*********************** PRIVATE FUNCTIONS/DATA ******************************/
static char inputBuffer[MAX_INPUT_SIZE];
static int buffCount;
// argv pointer are either NULL or point to locations in inputBuffer
static char *argv[MAX_COMMAND_PARAMS];
#define FLASH_OFFSET (0 * FLASH_PAGE_SIZE)
#define KERNEL_OFFSET (220 * FLASH_PAGE_SIZE)
#define KERNEL_LEN (6 * 1024 * FLASH_PAGE_SIZE)
static const char *backspaceString = "\010 \010";
static const command_entry_t CommandTable[] = {
{COMMAND_DUMP, "d"},
{COMMAND_EXEC, "e"},
{COMMAND_LOCAL_IP, "ip"},
{COMMAND_MAC, "m"},
{COMMAND_SERVER_IP, "server_ip"},
{COMMAND_TFTP, "tftp"},
{COMMAND_XMODEM, "x"},
{COMMAND_RESET, "R"},
{COMMAND_LOAD_SPI_KERNEL, "k"},
{COMMAND_REPLACE_KERNEL_VIA_XMODEM, "K"},
{COMMAND_REPLACE_FLASH_VIA_XMODEM, "I"},
{COMMAND_REPLACE_ID_EEPROM, "E"},
{COMMAND_FINAL_FLAG, 0}
};
/*
* .KB_C_FN_DEFINITION_START
* unsigned BuildIP(void)
* This private function packs the test IP info to an unsigned value.
* .KB_C_FN_DEFINITION_END
*/
static unsigned
BuildIP(void)
{
return ((p_ASCIIToDec(argv[1]) << 24) |
(p_ASCIIToDec(argv[2]) << 16) |
(p_ASCIIToDec(argv[3]) << 8) |
p_ASCIIToDec(argv[4]));
}
/*
* .KB_C_FN_DEFINITION_START
* int StringToCommand(char *cPtr)
* This private function converts a command string to a command code.
* .KB_C_FN_DEFINITION_END
*/
static int
StringToCommand(char *cPtr)
{
int i;
for (i = 0; CommandTable[i].command != COMMAND_FINAL_FLAG; ++i)
if (!strcmp(CommandTable[i].c_string, cPtr))
return (CommandTable[i].command);
return (COMMAND_INVALID);
}
/*
* .KB_C_FN_DEFINITION_START
* int BreakCommand(char *)
* This private function splits the buffer into separate strings as pointed
* by argv and returns the number of parameters (< 0 on failure).
* .KB_C_FN_DEFINITION_END
*/
static int
BreakCommand(char *buffer)
{
int pCount, cCount, state;
state = pCount = 0;
p_memset((char*)argv, 0, sizeof(argv));
for (cCount = 0; cCount < MAX_INPUT_SIZE; ++cCount) {
if (!state) {
/* look for next command */
if (!p_IsWhiteSpace(buffer[cCount])) {
argv[pCount++] = &buffer[cCount];
state = 1;
} else {
buffer[cCount] = 0;
}
} else {
/* in command, find next white space */
if (p_IsWhiteSpace(buffer[cCount])) {
buffer[cCount] = 0;
state = 0;
}
}
if (pCount >= MAX_COMMAND_PARAMS) {
return (-1);
}
}
return (pCount);
}
#if 0
static void
UpdateEEProm(int eeaddr)
{
char *addr = (char *)SDRAM_BASE + (1 << 20); /* Load to base + 1MB */
int len;
while ((len = xmodem_rx(addr)) == -1)
continue;
printf("\nDownloaded %u bytes.\n", len);
WriteEEPROM(eeaddr, 0, addr, len);
}
#endif
static void
UpdateFlash(int offset)
{
char *addr = (char *)SDRAM_BASE + (1 << 20); /* Load to base + 1MB */
int len, i, off;
while ((len = xmodem_rx(addr)) == -1)
continue;
printf("\nDownloaded %u bytes.\n", len);
for (i = 0; i < len; i+= FLASH_PAGE_SIZE) {
off = i + offset;
SPI_WriteFlash(off, addr + i, FLASH_PAGE_SIZE);
}
}
static void
LoadKernelFromSpi(char *addr)
{
int i, off;
for (i = 0; i < KERNEL_LEN; i+= FLASH_PAGE_SIZE) {
off = i + KERNEL_OFFSET;
SPI_ReadFlash(off, addr + i, FLASH_PAGE_SIZE);
}
}
/*
* .KB_C_FN_DEFINITION_START
* void ParseCommand(char *)
* This private function executes matching functions.
* .KB_C_FN_DEFINITION_END
*/
static void
ParseCommand(char *buffer)
{
int argc, i;
if ((argc = BreakCommand(buffer)) < 1)
return;
switch (StringToCommand(argv[0])) {
case COMMAND_DUMP:
// display boot commands
DumpBootCommands();
break;
case COMMAND_EXEC:
{
// "e <address>"
// execute at address
void (*execAddr)(unsigned, unsigned);
if (argc > 1) {
/* in future, include machtypes (MACH_KB9200 = 612) */
execAddr = (void (*)(unsigned, unsigned))
p_ASCIIToHex(argv[1]);
(*execAddr)(0, 612);
}
break;
}
case COMMAND_TFTP:
{
// "tftp <local_dest_addr filename>"
// tftp download
unsigned address = 0;
if (argc > 2)
address = p_ASCIIToHex(argv[1]);
TFTP_Download(address, argv[2]);
break;
}
case COMMAND_SERVER_IP:
// "server_ip <server IP 192 200 1 20>"
// set download server address
if (argc > 4)
SetServerIPAddress(BuildIP());
break;
case COMMAND_LOCAL_IP:
// "local_ip <local IP 192 200 1 21>
// set ip of this module
if (argc > 4)
SetLocalIPAddress(BuildIP());
break;
case COMMAND_MAC:
{
// "m <mac address 12 34 56 78 9a bc>
// set mac address using 6 byte values
unsigned char mac[6];
if (argc > 6) {
for (i = 0; i < 6; i++)
mac[i] = p_ASCIIToHex(argv[i + 1]);
EMAC_SetMACAddress(mac);
}
break;
}
case COMMAND_LOAD_SPI_KERNEL:
// "k <address>"
if (argc > 1)
LoadKernelFromSpi((char *)p_ASCIIToHex(argv[1]));
break;
case COMMAND_XMODEM:
// "x <address>"
// download X-modem record at address
if (argc > 1)
xmodem_rx((char *)p_ASCIIToHex(argv[1]));
break;
case COMMAND_RESET:
printf("Reset\n");
reset();
while (1) continue;
break;
case COMMAND_REPLACE_KERNEL_VIA_XMODEM:
printf("Updating KERNEL image\n");
UpdateFlash(KERNEL_OFFSET);
break;
case COMMAND_REPLACE_FLASH_VIA_XMODEM:
printf("Updating FLASH image\n");
UpdateFlash(FLASH_OFFSET);
break;
case COMMAND_REPLACE_ID_EEPROM:
{
char buf[25];
printf("Testing Config EEPROM\n");
EEWrite(0, "This is a test", 15);
EERead(0, buf, 15);
printf("Found '%s'\n", buf);
break;
}
default:
break;
}
printf("\n");
}
/*
* .KB_C_FN_DEFINITION_START
* void ServicePrompt(char)
* This private function process each character checking for valid commands.
* This function is only executed if the character is considered valid.
* Each command is terminated with NULL (0) or ''.
* .KB_C_FN_DEFINITION_END
*/
static void
ServicePrompt(char p_char)
{
if (p_char == '\r')
p_char = 0;
if (p_char == '\010') {
if (buffCount) {
/* handle backspace BS */
inputBuffer[--buffCount] = 0;
printf(backspaceString);
}
return;
}
if (buffCount < MAX_INPUT_SIZE - 1) {
inputBuffer[buffCount++] = p_char;
putchar(p_char);
}
if (!p_char) {
printf("\n");
ParseCommand(inputBuffer);
p_memset(inputBuffer, 0, MAX_INPUT_SIZE);
buffCount = 0;
printf("\n>");
}
}
/* ************************** GLOBAL FUNCTIONS ********************************/
/*
* .KB_C_FN_DEFINITION_START
* void Bootloader(void *inputFunction)
* This global function is the entry point for the bootloader. If the
* inputFunction pointer is NULL, the loader input will be serviced from
* the uart. Otherwise, inputFunction is called to get characters which
* the loader will parse.
* .KB_C_FN_DEFINITION_END
*/
void
Bootloader(int(*inputFunction)(int))
{
int ch = 0;
p_memset((void*)inputBuffer, 0, sizeof(inputBuffer));
buffCount = 0;
printf("\n>");
while (1)
if ((ch = ((*inputFunction)(0))) > 0)
ServicePrompt(ch);
}

View File

@ -1,62 +0,0 @@
/******************************************************************************
*
* Filename: loader_prompt.h
*
* Definition of the interactive loader functions.
*
* Revision information:
*
* 20AUG2004 kb_admin initial creation
*
* BEGIN_KBDD_BLOCK
* No warranty, expressed or implied, is included with this software. It is
* provided "AS IS" and no warranty of any kind including statutory or aspects
* relating to merchantability or fitness for any purpose is provided. All
* intellectual property rights of others is maintained with the respective
* owners. This software is not copyrighted and is intended for reference
* only.
* END_BLOCK
*
* $FreeBSD$
*****************************************************************************/
#ifndef _LOADER_PROMPT_H_
#define _LOADER_PROMPT_H_
#define MAX_INPUT_SIZE 256
#define MAX_COMMAND_PARAMS 10
enum {
COMMAND_INVALID = 0,
COMMAND_COPY,
COMMAND_DUMP,
COMMAND_EXEC,
COMMAND_HELP,
COMMAND_LOCAL_IP,
COMMAND_MAC,
COMMAND_SERVER_IP,
COMMAND_SET,
COMMAND_TAG,
COMMAND_TFTP,
COMMAND_WRITE,
COMMAND_XMODEM,
COMMAND_RESET,
COMMAND_LOAD_SPI_KERNEL,
COMMAND_REPLACE_KERNEL_VIA_XMODEM,
COMMAND_REPLACE_FLASH_VIA_XMODEM,
COMMAND_REPLACE_FPGA_VIA_XMODEM,
COMMAND_REPLACE_ID_EEPROM,
COMMAND_FINAL_FLAG
} e_cmd_t;
typedef struct {
int command;
const char *c_string;
} command_entry_t;
void EnterInteractiveBootloader(int(*inputFunction)(int));
void Bootloader(int(*inputFunction)(int));
void fpga_load(void);
#endif /* _LOADER_PROMPT_H_ */

View File

@ -1,65 +0,0 @@
/*-
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software is derived from software provided by kwikbyte without
* copyright as follows:
*
* No warranty, expressed or implied, is included with this software. It is
* provided "AS IS" and no warranty of any kind including statutory or aspects
* relating to merchantability or fitness for any purpose is provided. All
* intellectual property rights of others is maintained with the respective
* owners. This software is not copyrighted and is intended for reference
* only.
*
* $FreeBSD$
*/
#include "env_vars.h"
#include "at91rm9200.h"
#include "at91rm9200_lowlevel.h"
#include "loader_prompt.h"
#include "emac.h"
#include "lib.h"
#include "spi_flash.h"
#include "ee.h"
int main(void);
int
main(void)
{
printf("\nBoot\n");
EEInit();
SPI_InitFlash();
#ifdef TSC_FPGA
fpga_load();
#endif
EMAC_Init();
LoadBootCommands();
if (getc(1) == -1) {
start_wdog(30);
ExecuteEnvironmentFunctions();
}
Bootloader(getc);
return (1);
}

View File

@ -1,22 +0,0 @@
# $FreeBSD$
.include <src.opts.mk>
.include "${.CURDIR}/../Makefile.inc"
SOC?=at91rm9200
LIB= at91
INTERNALLIB=
SRCS=${SOC}_lowlevel.c delay.c eeprom.c emac.c emac_init.c getc.c \
putchar.c printf.c reset.c spi_flash.c xmodem.c \
sd-card.c strcvt.c strlen.c strcmp.c memcpy.c strcpy.c \
memset.c memcmp.c
SRCS+=ashldi3.c divsi3.S
MAN=
.if ${MK_TAG_LIST} != "no"
CFLAGS += -I${.CURDIR}/.. -DSUPPORT_TAG_LIST
SRCS+=tag_list.c
.endif
.include <bsd.lib.mk>

View File

@ -1,129 +0,0 @@
/*******************************************************************************
*
* Filename: arm_init.s
*
* Initialization for C-environment and basic operation. Adapted from
* ATMEL cstartup.s.
*
* Revision information:
*
* 20AUG2004 kb_admin initial creation
* 12JAN2005 kb_admin updated for 16KB eeprom
* Atmel stack prevents loading full size at once
*
* BEGIN_KBDD_BLOCK
* No warranty, expressed or implied, is included with this software. It is
* provided "AS IS" and no warranty of any kind including statutory or aspects
* relating to merchantability or fitness for any purpose is provided. All
* intellectual property rights of others is maintained with the respective
* owners. This software is not copyrighted and is intended for reference
* only.
* END_BLOCK
*
* $FreeBSD$
******************************************************************************/
.equ TWI_EEPROM_SIZE, 0x3000
.equ ARM_MODE_USER, 0x10
.equ ARM_MODE_FIQ, 0x11
.equ ARM_MODE_IRQ, 0x12
.equ ARM_MODE_SVC, 0x13
.equ ARM_MODE_ABORT, 0x17
.equ ARM_MODE_UNDEF, 0x1B
.equ ARM_MODE_SYS, 0x1F
.equ I_BIT, 0x80
.equ F_BIT, 0x40
.equ T_BIT, 0x20
/*
* Stack definitions
*
* Start near top of internal RAM.
*/
.equ END_INT_SRAM, 0x4000
.equ SVC_STACK_START, (END_INT_SRAM - 0x4)
.equ SVC_STACK_USE, 0x21800000
start:
/* vectors - must reside at address 0 */
/* the format of this table is defined in the datasheet */
B InitReset @; reset
undefvec:
B undefvec @; Undefined Instruction
swivec:
B swivec @; Software Interrupt
pabtvec:
B pabtvec @; Prefetch Abort
dabtvec:
B dabtvec @; Data Abort
rsvdvec:
#ifdef BOOT_IIC
.long (TWI_EEPROM_SIZE >> 9)
#else
#ifdef BOOT_BWCT
.long ((528 << 17) | (13 << 13) | (12 * 2))
#else
.long ((1056 << 17) | (13 << 13) | (12 * 2))
#endif
#endif
irqvec:
ldr pc, [pc,#-0xF20] @; IRQ : read the AIC
fiqvec:
B fiqvec @; FIQ
InitReset:
/* Set stack and init for SVC */
ldr r1, = SVC_STACK_START
mov sp, r1 @; Init stack SYS
msr cpsr_c, #(ARM_MODE_SVC | I_BIT | F_BIT)
mov sp, r1 @ ; Init stack SYS
/* Perform system initialization */
.extern _init
bl _init
#ifndef BOOT_BOOT0
ldr r1, = SVC_STACK_USE
mov sp, r1 @ ; Move the stack to SDRAM
#endif
/* Start execution at main */
.extern main
_main:
__main:
bl main
/* main should not return. If it does, spin forever */
infiniteLoop:
b infiniteLoop
#ifdef BOOT_COMMANDS
/* the following section is used to store boot commands in */
/* non-volatile memory. */
.global BootCommandSection
BootCommandSection:
#ifdef SUPPORT_LINUX
.string "Bootloader for KB9202 Evaluation Board."
.string "c 0x20210000 0x10100000 0x80000 "
.string "m 0 0 0 0 0 0 "
.string "t 0x20000100 console=ttyS0,115200 root=/dev/ram rw initrd=0x20210000,654933"
.string "e 0x10000000 "
.string " "
#else
#if 1
.string "m 42 53 44 0 0 1"
.string "ip 206 168 13 194"
.string "server_ip 206 168 13 207"
.string "tftp 0x20000000 kernel.bin"
.string "e 0x20000000"
#else
.string "m 42 53 44 0 0 1"
.string "k 0x20000000"
.string "e 0x20000000"
#endif
.word 0
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,223 +0,0 @@
/*-
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software is derived from software provide by Kwikbyte who specifically
* disclaimed copyright on the code.
*
* $FreeBSD$
*/
#include "at91rm9200.h"
#include "at91rm9200_lowlevel.h"
extern int __bss_start__[];
extern int __bss_end__[];
#define BAUD 115200
#define AT91C_US_ASYNC_MODE (AT91C_US_USMODE_NORMAL | AT91C_US_NBSTOP_1_BIT | \
AT91C_US_PAR_NONE | AT91C_US_CHRL_8_BITS | AT91C_US_CLKS_CLOCK)
/*
* void DefaultSystemInit(void)
* Load the system with sane values based on how the system is configured.
* at91rm9200_lowlevel.h is expected to define the necessary parameters.
*/
void
_init(void)
{
int *i;
AT91PS_USART pUSART = (AT91PS_USART)AT91C_BASE_DBGU;
AT91PS_PDC pPDC = (AT91PS_PDC)&(pUSART->US_RPR);
register unsigned value;
volatile sdram_size_t *p = (sdram_size_t *)SDRAM_BASE;
AT91C_BASE_ST->ST_RTMR = 1;
#ifdef BOOT_TSC
// For the TSC board, we turn ON the one LED we have while
// early in boot.
AT91C_BASE_PIOC->PIO_PER = AT91C_PIO_PC10;
AT91C_BASE_PIOC->PIO_OER = AT91C_PIO_PC10;
AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC10;
#endif
#if defined(BOOT_KB920X)
AT91C_BASE_PIOC->PIO_PER = AT91C_PIO_PC18 | AT91C_PIO_PC19 |
AT91C_PIO_PC20;
AT91C_BASE_PIOC->PIO_OER = AT91C_PIO_PC18 | AT91C_PIO_PC19 |
AT91C_PIO_PC20;
AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC18 | AT91C_PIO_PC19 |
AT91C_PIO_PC20;
AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC18;
#endif
// configure clocks
// assume:
// main osc = 10Mhz
// PLLB configured for 96MHz (48MHz after div)
// CSS = PLLB
// set PLLA = 180MHz
// assume main osc = 10Mhz
// div = 5 , out = 2 (150MHz = 240MHz)
value = AT91C_BASE_CKGR->CKGR_PLLAR;
value &= ~(AT91C_CKGR_DIVA | AT91C_CKGR_OUTA | AT91C_CKGR_MULA);
value |= OSC_MAIN_FREQ_DIV | AT91C_CKGR_OUTA_2 | AT91C_CKGR_SRCA |
((OSC_MAIN_MULT - 1) << 16);
AT91C_BASE_CKGR->CKGR_PLLAR = value;
// wait for lock
while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCKA))
continue;
// change divider = 3, pres = 1
value = AT91C_BASE_PMC->PMC_MCKR;
value &= ~(AT91C_PMC_MDIV | AT91C_PMC_PRES);
value |= AT91C_PMC_MDIV_3 | AT91C_PMC_PRES_CLK;
AT91C_BASE_PMC->PMC_MCKR = value;
// wait for update
while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY))
continue;
// change CSS = PLLA
value &= ~AT91C_PMC_CSS;
value |= AT91C_PMC_CSS_PLLA_CLK;
AT91C_BASE_PMC->PMC_MCKR = value;
// wait for update
while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY))
continue;
#ifdef BOOT_KB920X
// setup flash access (allow ample margin)
// 9 wait states, 1 setup, 1 hold, 1 float for 8-bit device
((AT91PS_SMC2)AT91C_BASE_SMC2)->SMC2_CSR[0] =
AT91C_SMC2_WSEN |
(9 & AT91C_SMC2_NWS) |
((1 << 8) & AT91C_SMC2_TDF) |
AT91C_SMC2_DBW_8 |
((1 << 24) & AT91C_SMC2_RWSETUP) |
((1 << 29) & AT91C_SMC2_RWHOLD);
#endif
// setup SDRAM access
// EBI chip-select register (CS1 = SDRAM controller)
// 9 col, 13row, 4 bank, CAS2
// write recovery = 2 (Twr)
// row cycle = 5 (Trc)
// precharge delay = 2 (Trp)
// row to col delay 2 (Trcd)
// active to precharge = 4 (Tras)
// exit self refresh to active = 6 (Txsr)
value = ((AT91PS_EBI)AT91C_BASE_EBI)->EBI_CSA;
value &= ~AT91C_EBI_CS1A;
value |= AT91C_EBI_CS1A_SDRAMC;
AT91C_BASE_EBI->EBI_CSA = value;
AT91C_BASE_SDRC->SDRC_CR =
#if defined(KB9202_B) || defined(SDRAM_128M)
AT91C_SDRC_NC_10 |
#else
AT91C_SDRC_NC_9 |
#endif
AT91C_SDRC_NR_13 |
AT91C_SDRC_NB_4_BANKS |
AT91C_SDRC_CAS_2 |
((2 << 7) & AT91C_SDRC_TWR) |
((5 << 11) & AT91C_SDRC_TRC) |
((2 << 15) & AT91C_SDRC_TRP) |
((2 << 19) & AT91C_SDRC_TRCD) |
((4 << 23) & AT91C_SDRC_TRAS) |
((6 << 27) & AT91C_SDRC_TXSR);
// Step 1: We assume 200us of idle time.
// Step 2: Issue an all banks precharge command
AT91C_BASE_SDRC->SDRC_MR = SDRAM_WIDTH | AT91C_SDRC_MODE_PRCGALL_CMD;
*p = 0;
// Step 3: Issue 8 Auto-refresh (CBR) cycles
AT91C_BASE_SDRC->SDRC_MR = SDRAM_WIDTH | AT91C_SDRC_MODE_RFSH_CMD;
*p = 0;
*p = 0;
*p = 0;
*p = 0;
*p = 0;
*p = 0;
*p = 0;
*p = 0;
// Step 4: Issue an Mode Set Register (MRS) cycle to program in
// the parameters that we setup in the SDRC_CR register above.
AT91C_BASE_SDRC->SDRC_MR = SDRAM_WIDTH | AT91C_SDRC_MODE_LMR_CMD;
*p = 0;
// Step 5: set the refresh timer and access memory to start it
// running. We have to wait 3 clocks after the LMR_CMD above,
// and this fits the bill nicely.
AT91C_BASE_SDRC->SDRC_TR = 7 * AT91C_MASTER_CLOCK / 1000000;
*p = 0;
// Step 6: Set normal mode.
AT91C_BASE_SDRC->SDRC_MR = SDRAM_WIDTH | AT91C_SDRC_MODE_NORMAL_CMD;
*p = 0;
#if SDRAM_WIDTH == AT91C_SDRC_DBW_32_BITS
// Turn on the upper 16 bits on the SDRAM bus.
AT91C_BASE_PIOC->PIO_ASR = 0xffff0000;
AT91C_BASE_PIOC->PIO_PDR = 0xffff0000;
#endif
// Configure DBGU -use local routine optimized for space
AT91C_BASE_PIOA->PIO_ASR = AT91C_PIO_PA31 | AT91C_PIO_PA30;
AT91C_BASE_PIOA->PIO_PDR = AT91C_PIO_PA31 | AT91C_PIO_PA30;
pUSART->US_IDR = (unsigned int) -1;
pUSART->US_CR =
AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RXDIS | AT91C_US_TXDIS;
pUSART->US_BRGR = ((((AT91C_MASTER_CLOCK*10)/(BAUD*16))+5)/10);
pUSART->US_TTGR = 0;
pPDC->PDC_PTCR = AT91C_PDC_RXTDIS;
pPDC->PDC_PTCR = AT91C_PDC_TXTDIS;
pPDC->PDC_TNPR = 0;
pPDC->PDC_TNCR = 0;
pPDC->PDC_RNPR = 0;
pPDC->PDC_RNCR = 0;
pPDC->PDC_TPR = 0;
pPDC->PDC_TCR = 0;
pPDC->PDC_RPR = 0;
pPDC->PDC_RCR = 0;
pPDC->PDC_PTCR = AT91C_PDC_RXTEN;
pPDC->PDC_PTCR = AT91C_PDC_TXTEN;
pUSART->US_MR = AT91C_US_ASYNC_MODE;
pUSART->US_CR = AT91C_US_TXEN;
pUSART->US_CR = AT91C_US_RXEN;
/* Zero BSS now that we have memory setup */
i = (int *)__bss_start__;
while (i < (int *)__bss_end__)
*i++ = 0;
}

View File

@ -1,74 +0,0 @@
/*-
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _AT91RM9200_LOWLEVEL_H_
#define _AT91RM9200_LOWLEVEL_H_
/* default system config parameters */
#define SDRAM_BASE 0x20000000
#ifdef BOOT_KB920X
/* The following divisor sets PLLA frequency: e.g. 10/5 * 90 = 180MHz */
#define OSC_MAIN_FREQ_DIV 5 /* for 10MHz osc */
#define SDRAM_WIDTH AT91C_SDRC_DBW_16_BITS
typedef unsigned short sdram_size_t;
#define OSC_MAIN_MULT 90
#endif
#ifdef BOOT_CENTIPAD
/* The following divisor sets PLLA frequency: e.g. 10/5 * 90 = 180MHz */
#define OSC_MAIN_FREQ_DIV 5 /* for 10MHz osc */
#define SDRAM_WIDTH AT91C_SDRC_DBW_16_BITS
typedef unsigned short sdram_size_t;
#define OSC_MAIN_MULT 90
#endif
#ifdef BOOT_BWCT
/* The following divisor sets PLLA frequency: e.g. 16/4 * 45 = 180MHz */
#define OSC_MAIN_FREQ_DIV 4 /* for 16MHz osc */
#define SDRAM_WIDTH AT91C_SDRC_DBW_32_BITS
typedef unsigned int sdram_size_t;
#define OSC_MAIN_MULT 45
#endif
#ifdef BOOT_TSC
/* The following divisor sets PLLA frequency: e.g. 16/4 * 45 = 180MHz */
#define OSC_MAIN_FREQ_DIV 4 /* for 16MHz osc */
#define SDRAM_WIDTH AT91C_SDRC_DBW_32_BITS
typedef unsigned int sdram_size_t;
#define OSC_MAIN_MULT 45
#endif
/* Master clock frequency at power-up */
#define AT91C_MASTER_CLOCK 60000000
/* #define GetSeconds() (AT91C_BASE_RTC->RTC_TIMR & AT91C_RTC_SEC) */
#define GetSeconds() (AT91C_BASE_ST->ST_CRTR >> 15)
extern void _init(void);
#endif /* _AT91RM9200_LOWLEVEL_H_ */

View File

@ -1,43 +0,0 @@
/*-
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software is derived from software provide by Kwikbyte who specifically
* disclaimed copyright on the code.
*
* $FreeBSD$
*/
#include "at91rm9200.h"
#include "spi_flash.h"
#include "lib.h"
void
Delay(int us)
{
unsigned later, now;
now = AT91C_BASE_ST->ST_CRTR;
later = (now + us / 25 + 1) & AT91C_ST_CRTV;
while (later != AT91C_BASE_ST->ST_CRTR)
continue;
}

View File

@ -1,185 +0,0 @@
/******************************************************************************
*
* Filename: eeprom.c
*
* Instantiation of eeprom routines
*
* Revision information:
*
* 28AUG2004 kb_admin initial creation - adapted from Atmel sources
* 12JAN2005 kb_admin fixed clock generation, write polling, init
*
* BEGIN_KBDD_BLOCK
* No warranty, expressed or implied, is included with this software. It is
* provided "AS IS" and no warranty of any kind including statutory or aspects
* relating to merchantability or fitness for any purpose is provided. All
* intellectual property rights of others is maintained with the respective
* owners. This software is not copyrighted and is intended for reference
* only.
* END_BLOCK
*
* $FreeBSD$
*****************************************************************************/
#include "at91rm9200_lowlevel.h"
#include "at91rm9200.h"
#include "lib.h"
/******************************* GLOBALS *************************************/
/*********************** PRIVATE FUNCTIONS/DATA ******************************/
/* Use a macro to calculate the TWI clock generator value to save code space. */
#define AT91C_TWSI_CLOCK 100000
#define TWSI_EEPROM_ADDRESS 0x50
#define TWI_CLK_BASE_DIV ((AT91C_MASTER_CLOCK/(4*AT91C_TWSI_CLOCK)) - 2)
#define SET_TWI_CLOCK ((0x00010000) | (TWI_CLK_BASE_DIV) | (TWI_CLK_BASE_DIV << 8))
/*************************** GLOBAL FUNCTIONS ********************************/
/*
* .KB_C_FN_DEFINITION_START
* void InitEEPROM(void)
* This global function initializes the EEPROM interface (TWI). Intended
* to be called a single time.
* .KB_C_FN_DEFINITION_END
*/
void
InitEEPROM(void)
{
AT91PS_TWI twiPtr = (AT91PS_TWI)AT91C_BASE_TWI;
AT91PS_PIO pPio = (AT91PS_PIO)AT91C_BASE_PIOA;
AT91PS_PMC pPMC = (AT91PS_PMC)AT91C_BASE_PMC;
pPio->PIO_ASR = AT91C_PIO_PA25 | AT91C_PIO_PA26;
pPio->PIO_PDR = AT91C_PIO_PA25 | AT91C_PIO_PA26;
pPio->PIO_MDDR = ~AT91C_PIO_PA25;
pPio->PIO_MDER = AT91C_PIO_PA25;
pPMC->PMC_PCER = 1u << AT91C_ID_TWI;
twiPtr->TWI_IDR = 0xffffffffu;
twiPtr->TWI_CR = AT91C_TWI_SWRST;
twiPtr->TWI_CR = AT91C_TWI_MSEN | AT91C_TWI_SVDIS;
twiPtr->TWI_CWGR = SET_TWI_CLOCK;
}
/*
* .KB_C_FN_DEFINITION_START
* void ReadEEPROM(unsigned ee_addr, char *data_addr, unsigned size)
* This global function reads data from the eeprom at ee_addr storing data
* to data_addr for size bytes. Assume the TWI has been initialized.
* This function does not utilize the page read mode to simplify the code.
* .KB_C_FN_DEFINITION_END
*/
int
ReadEEPROM(unsigned ee_off, unsigned char *data_addr, unsigned size)
{
const AT91PS_TWI twiPtr = AT91C_BASE_TWI;
unsigned int status;
unsigned int count;
status = twiPtr->TWI_SR;
status = twiPtr->TWI_RHR;
// Set the TWI Master Mode Register
twiPtr->TWI_MMR = (TWSI_EEPROM_ADDRESS << 16) |
AT91C_TWI_IADRSZ_2_BYTE | AT91C_TWI_MREAD;
// Set TWI Internal Address Register
twiPtr->TWI_IADR = ee_off;
// Start transfer
twiPtr->TWI_CR = AT91C_TWI_START;
status = twiPtr->TWI_SR;
while (size-- > 1){
// Wait RHR Holding register is full
count = 1000000;
while (!(twiPtr->TWI_SR & AT91C_TWI_RXRDY) && --count > 0)
continue;
if (count <= 0)
return -1;
// Read byte
*(data_addr++) = twiPtr->TWI_RHR;
}
twiPtr->TWI_CR = AT91C_TWI_STOP;
status = twiPtr->TWI_SR;
// Wait transfer is finished
while (!(twiPtr->TWI_SR & AT91C_TWI_TXCOMP))
continue;
// Read last byte
*data_addr = twiPtr->TWI_RHR;
return 0;
}
/*
* .KB_C_FN_DEFINITION_START
* void WriteEEPROM(unsigned ee_off, char *data_addr, unsigned size)
* This global function writes data to the eeprom at ee_off using data
* from data_addr for size bytes. Assume the TWI has been initialized.
* This function does not utilize the page write mode as the write time is
* much greater than the time required to access the device for byte-write
* functionality. This allows the function to be much simpler.
* .KB_C_FN_DEFINITION_END
*/
void
WriteEEPROM(unsigned ee_off, char *data_addr, unsigned size)
{
const AT91PS_TWI twiPtr = AT91C_BASE_TWI;
unsigned status;
unsigned char test_data;
while (size--) {
if (!(ee_off & 0x3f))
putchar('.');
// Set the TWI Master Mode Register
twiPtr->TWI_MMR = ((TWSI_EEPROM_ADDRESS << 16) |
AT91C_TWI_IADRSZ_2_BYTE) & ~AT91C_TWI_MREAD;
// Set TWI Internal Address Register
twiPtr->TWI_IADR = ee_off++;
status = twiPtr->TWI_SR;
twiPtr->TWI_THR = *(data_addr++);
twiPtr->TWI_CR = AT91C_TWI_START;
// Wait transfer is finished
while (!(twiPtr->TWI_SR & AT91C_TWI_TXRDY))
continue;
twiPtr->TWI_CR = AT91C_TWI_STOP;
status = twiPtr->TWI_SR;
// Wait transfer is finished
while (!(twiPtr->TWI_SR & AT91C_TWI_TXCOMP))
continue;
// wait for write operation to complete
ReadEEPROM(ee_off, &test_data, 1);
}
putchar('\r');
putchar('\n');
}

View File

@ -1,575 +0,0 @@
/*******************************************************************************
*
* Filename: emac.c
*
* Instantiation of routines for MAC/ethernet functions supporting tftp.
*
* Revision information:
*
* 28AUG2004 kb_admin initial creation
* 08JAN2005 kb_admin added tftp download
* also adapted from external sources
*
* BEGIN_KBDD_BLOCK
* No warranty, expressed or implied, is included with this software. It is
* provided "AS IS" and no warranty of any kind including statutory or aspects
* relating to merchantability or fitness for any purpose is provided. All
* intellectual property rights of others is maintained with the respective
* owners. This software is not copyrighted and is intended for reference
* only.
* END_BLOCK
*
* $FreeBSD$
******************************************************************************/
#include "at91rm9200.h"
#include "at91rm9200_lowlevel.h"
#include "emac.h"
#include "lib.h"
/* ****************************** GLOBALS *************************************/
/* ********************** PRIVATE FUNCTIONS/DATA ******************************/
static receive_descriptor_t *p_rxBD;
static unsigned short localPort;
static unsigned short serverPort;
static unsigned serverMACSet;
static unsigned localIPSet, serverIPSet;
static unsigned lastSize;
static unsigned char serverMACAddr[6];
static unsigned char localIPAddr[4], serverIPAddr[4];
static int ackBlock;
static char *dlAddress;
static unsigned transmitBuffer[1024 / sizeof(unsigned)];
static unsigned tftpSendPacket[256 / sizeof(unsigned)];
/*
* .KB_C_FN_DEFINITION_START
* unsigned short IP_checksum(unsigned short *p, int len)
* This private function calculates the IP checksum for various headers.
* .KB_C_FN_DEFINITION_END
*/
static unsigned short
IP_checksum(unsigned short *p, int len)
{
unsigned i, t;
len &= ~1;
for (i=0,t=0; i<len; i+=2, ++p)
t += SWAP16(*p);
t = (t & 0xffff) + (t >> 16);
return (~t);
}
/*
* .KB_C_FN_DEFINITION_START
* void GetServerAddress(void)
* This private function sends an ARP request to determine the server MAC.
* .KB_C_FN_DEFINITION_END
*/
static void
GetServerAddress(void)
{
arp_header_t *p_ARP;
p_ARP = (arp_header_t*)transmitBuffer;
p_memset((char*)p_ARP->dest_mac, 0xFF, 6);
memcpy(p_ARP->src_mac, localMACAddr, 6);
p_ARP->frame_type = SWAP16(PROTOCOL_ARP);
p_ARP->hard_type = SWAP16(1);
p_ARP->prot_type = SWAP16(PROTOCOL_IP);
p_ARP->hard_size = 6;
p_ARP->prot_size = 4;
p_ARP->operation = SWAP16(ARP_REQUEST);
memcpy(p_ARP->sender_mac, localMACAddr, 6);
memcpy(p_ARP->sender_ip, localIPAddr, 4);
p_memset((char*)p_ARP->target_mac, 0, 6);
memcpy(p_ARP->target_ip, serverIPAddr, 4);
// wait until transmit is available
while (!(*AT91C_EMAC_TSR & AT91C_EMAC_BNQ))
continue;
*AT91C_EMAC_TSR |= AT91C_EMAC_COMP;
*AT91C_EMAC_TAR = (unsigned)transmitBuffer;
*AT91C_EMAC_TCR = 0x40;
}
/*
* .KB_C_FN_DEFINITION_START
* void Send_TFTP_Packet(char *tftpData, unsigned tftpLength)
* This private function initializes and send a TFTP packet.
* .KB_C_FN_DEFINITION_END
*/
static void
Send_TFTP_Packet(char *tftpData, unsigned tftpLength)
{
transmit_header_t *macHdr = (transmit_header_t*)tftpSendPacket;
ip_header_t *ipHdr;
udp_header_t *udpHdr;
unsigned t_checksum;
memcpy(macHdr->dest_mac, serverMACAddr, 6);
memcpy(macHdr->src_mac, localMACAddr, 6);
macHdr->proto_mac = SWAP16(PROTOCOL_IP);
ipHdr = (ip_header_t*)&macHdr->packet_length;
ipHdr->ip_v_hl = 0x45;
ipHdr->ip_tos = 0;
ipHdr->ip_len = SWAP16(28 + tftpLength);
ipHdr->ip_id = 0;
ipHdr->ip_off = SWAP16(0x4000);
ipHdr->ip_ttl = 64;
ipHdr->ip_p = PROTOCOL_UDP;
ipHdr->ip_sum = 0;
memcpy(ipHdr->ip_src, localIPAddr, 4);
memcpy(ipHdr->ip_dst, serverIPAddr, 4);
ipHdr->ip_sum = SWAP16(IP_checksum((unsigned short*)ipHdr, 20));
udpHdr = (udp_header_t*)(ipHdr + 1);
udpHdr->src_port = localPort;
udpHdr->dst_port = serverPort;
udpHdr->udp_len = SWAP16(8 + tftpLength);
udpHdr->udp_cksum = 0;
memcpy((char *)udpHdr+8, tftpData, tftpLength);
t_checksum = IP_checksum((unsigned short*)ipHdr + 6, (16 + tftpLength));
t_checksum = (~t_checksum) & 0xFFFF;
t_checksum += 25 + tftpLength;
t_checksum = (t_checksum & 0xffff) + (t_checksum >> 16);
t_checksum = (~t_checksum) & 0xFFFF;
udpHdr->udp_cksum = SWAP16(t_checksum);
while (!(*AT91C_EMAC_TSR & AT91C_EMAC_BNQ))
continue;
*AT91C_EMAC_TSR |= AT91C_EMAC_COMP;
*AT91C_EMAC_TAR = (unsigned)tftpSendPacket;
*AT91C_EMAC_TCR = 42 + tftpLength;
}
/*
* .KB_C_FN_DEFINITION_START
* void TFTP_RequestFile(char *filename)
* This private function sends a RRQ packet to the server.
* .KB_C_FN_DEFINITION_END
*/
static void
TFTP_RequestFile(char *filename)
{
tftp_header_t tftpHeader;
char *cPtr, *ePtr, *mPtr;
unsigned length;
tftpHeader.opcode = TFTP_RRQ_OPCODE;
cPtr = (char*)&(tftpHeader.block_num);
ePtr = strcpy(cPtr, filename);
mPtr = strcpy(ePtr, "octet");
length = mPtr - cPtr;
length += 2;
Send_TFTP_Packet((char*)&tftpHeader, length);
}
/*
* .KB_C_FN_DEFINITION_START
* void TFTP_ACK_Data(char *data, unsigned short block_num, unsigned short len)
* This private function sends an ACK packet to the server.
* .KB_C_FN_DEFINITION_END
*/
static void
TFTP_ACK_Data(unsigned char *data, unsigned short block_num, unsigned short len)
{
tftp_header_t tftpHeader;
if (block_num == (ackBlock + 1)) {
++ackBlock;
memcpy(dlAddress, data, len);
dlAddress += len;
lastSize += len;
if (ackBlock % 128 == 0)
printf("tftp: %u kB\r", lastSize / 1024);
}
tftpHeader.opcode = TFTP_ACK_OPCODE;
tftpHeader.block_num = SWAP16(ackBlock);
Send_TFTP_Packet((char*)&tftpHeader, 4);
if (len < 512) {
ackBlock = -2;
printf("tftp: %u byte\n", lastSize);
}
}
/*
* .KB_C_FN_DEFINITION_START
* void CheckForNewPacket(ip_header_t *pHeader)
* This private function polls for received ethernet packets and handles
* any here.
* .KB_C_FN_DEFINITION_END
*/
static int
CheckForNewPacket(ip_header_t *pHeader)
{
unsigned short *pFrameType;
unsigned i;
char *pData;
ip_header_t *pIpHeader;
arp_header_t *p_ARP;
int process = 0;
process = 0;
for (i = 0; i < MAX_RX_PACKETS; ++i) {
if(p_rxBD[i].address & 0x1) {
process = 1;
(*AT91C_EMAC_RSR) |= (*AT91C_EMAC_RSR);
break;
}
}
if (!process)
return (0);
process = i;
pFrameType = (unsigned short *)((p_rxBD[i].address & 0xFFFFFFFC) + 12);
pData = (char *)(p_rxBD[i].address & 0xFFFFFFFC);
switch (*pFrameType) {
case SWAP16(PROTOCOL_ARP):
p_ARP = (arp_header_t*)pData;
if (p_ARP->operation == SWAP16(ARP_REPLY)) {
// check if new server info is available
if ((!serverMACSet) &&
(!(p_memcmp((char*)p_ARP->sender_ip,
(char*)serverIPAddr, 4)))) {
serverMACSet = 1;
memcpy(serverMACAddr, p_ARP->sender_mac, 6);
}
} else if (p_ARP->operation == SWAP16(ARP_REQUEST)) {
// ARP REPLY operation
p_ARP->operation = SWAP16(ARP_REPLY);
// Fill the dest address and src address
for (i = 0; i <6; i++) {
// swap ethernet dest address and ethernet src address
pData[i] = pData[i+6];
pData[i+6] = localMACAddr[i];
// swap sender ethernet address and target ethernet address
pData[i+22] = localMACAddr[i];
pData[i+32] = pData[i+6];
}
// swap sender IP address and target IP address
for (i = 0; i<4; i++) {
pData[i+38] = pData[i+28];
pData[i+28] = localIPAddr[i];
}
if (!(*AT91C_EMAC_TSR & AT91C_EMAC_BNQ)) break;
*AT91C_EMAC_TSR |= AT91C_EMAC_COMP;
*AT91C_EMAC_TAR = (unsigned)pData;
*AT91C_EMAC_TCR = 0x40;
}
break;
case SWAP16(PROTOCOL_IP):
pIpHeader = (ip_header_t*)(pData + 14);
memcpy(pHeader, pIpHeader, sizeof(ip_header_t));
if (pIpHeader->ip_p == PROTOCOL_UDP) {
udp_header_t *udpHdr;
tftp_header_t *tftpHdr;
udpHdr = (udp_header_t*)((char*)pIpHeader+20);
tftpHdr = (tftp_header_t*)((char*)udpHdr + 8);
if (udpHdr->dst_port != localPort)
break;
if (tftpHdr->opcode != TFTP_DATA_OPCODE)
break;
if (ackBlock == -1) {
if (tftpHdr->block_num != SWAP16(1))
break;
serverPort = udpHdr->src_port;
ackBlock = 0;
}
if (serverPort != udpHdr->src_port)
break;
TFTP_ACK_Data(tftpHdr->data,
SWAP16(tftpHdr->block_num),
SWAP16(udpHdr->udp_len) - 12);
}
}
p_rxBD[process].address &= ~0x01;
return (1);
}
/*
* .KB_C_FN_DEFINITION_START
* unsigned short AT91F_MII_ReadPhy (AT91PS_EMAC pEmac, unsigned char addr)
* This private function reads the PHY device.
* .KB_C_FN_DEFINITION_END
*/
#ifndef BOOT_BWCT
static unsigned short
AT91F_MII_ReadPhy (AT91PS_EMAC pEmac, unsigned char addr)
{
unsigned value = 0x60020000 | (addr << 18);
pEmac->EMAC_CTL |= AT91C_EMAC_MPE;
pEmac->EMAC_MAN = value;
while(!((pEmac->EMAC_SR) & AT91C_EMAC_IDLE));
pEmac->EMAC_CTL &= ~AT91C_EMAC_MPE;
return (pEmac->EMAC_MAN & 0x0000ffff);
}
#endif
/*
* .KB_C_FN_DEFINITION_START
* unsigned short AT91F_MII_WritePhy (AT91PS_EMAC pEmac, unsigned char addr, unsigned short s)
* This private function writes the PHY device.
* .KB_C_FN_DEFINITION_END
*/
#ifdef BOOT_TSC
static unsigned short
AT91F_MII_WritePhy (AT91PS_EMAC pEmac, unsigned char addr, unsigned short s)
{
unsigned value = 0x50020000 | (addr << 18) | s;
pEmac->EMAC_CTL |= AT91C_EMAC_MPE;
pEmac->EMAC_MAN = value;
while(!((pEmac->EMAC_SR) & AT91C_EMAC_IDLE));
pEmac->EMAC_CTL &= ~AT91C_EMAC_MPE;
return (pEmac->EMAC_MAN & 0x0000ffff);
}
#endif
/*
* .KB_C_FN_DEFINITION_START
* void MII_GetLinkSpeed(AT91PS_EMAC pEmac)
* This private function determines the link speed set by the PHY.
* .KB_C_FN_DEFINITION_END
*/
static void
MII_GetLinkSpeed(AT91PS_EMAC pEmac)
{
#if defined(BOOT_TSC) || defined(BOOT_KB920X) || defined(BOOT_CENTIPAD)
unsigned short stat2;
#endif
unsigned update;
#ifdef BOOT_TSC
unsigned sec;
int i;
#endif
#ifdef BOOT_BWCT
/* hardcoded link speed since we connect a switch via MII */
update = pEmac->EMAC_CFG & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
update |= AT91C_EMAC_SPD;
update |= AT91C_EMAC_FD;
#endif
#if defined(BOOT_KB920X) || defined(BOOT_CENTIPAD)
stat2 = AT91F_MII_ReadPhy(pEmac, MII_STS2_REG);
if (!(stat2 & MII_STS2_LINK))
return ;
update = pEmac->EMAC_CFG & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
if (stat2 & MII_STS2_100TX)
update |= AT91C_EMAC_SPD;
if (stat2 & MII_STS2_FDX)
update |= AT91C_EMAC_FD;
#endif
#ifdef BOOT_TSC
while (1) {
for (i = 0; i < 10; i++) {
stat2 = AT91F_MII_ReadPhy(pEmac, MII_STS_REG);
if (stat2 & MII_STS_LINK_STAT)
break;
printf(".");
sec = GetSeconds();
while (GetSeconds() == sec)
continue;
}
if (stat2 & MII_STS_LINK_STAT)
break;
printf("Resetting MII...");
AT91F_MII_WritePhy(pEmac, 0x0, 0x8000);
while (AT91F_MII_ReadPhy(pEmac, 0x0) & 0x8000) continue;
}
printf("emac: link");
stat2 = AT91F_MII_ReadPhy(pEmac, MII_SPEC_STS_REG);
update = pEmac->EMAC_CFG & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
if (stat2 & (MII_SSTS_100FDX | MII_SSTS_100HDX)) {
printf(" 100TX");
update |= AT91C_EMAC_SPD;
}
if (stat2 & (MII_SSTS_100FDX | MII_SSTS_10FDX)) {
printf(" FDX");
update |= AT91C_EMAC_FD;
}
printf("\n");
#endif
pEmac->EMAC_CFG = update;
}
/*
* .KB_C_FN_DEFINITION_START
* void AT91F_EmacEntry(void)
* This private function initializes the EMAC on the chip.
* .KB_C_FN_DEFINITION_END
*/
static void
AT91F_EmacEntry(void)
{
unsigned i;
char *pRxPacket = (char*)RX_DATA_START;
AT91PS_EMAC pEmac = AT91C_BASE_EMAC;
p_rxBD = (receive_descriptor_t*)RX_BUFFER_START;
localPort = SWAP16(0x8002);
for (i = 0; i < MAX_RX_PACKETS; ++i) {
p_rxBD[i].address = (unsigned)pRxPacket;
p_rxBD[i].size = 0;
pRxPacket += RX_PACKET_SIZE;
}
// Set the WRAP bit at the end of the list descriptor
p_rxBD[MAX_RX_PACKETS-1].address |= 0x02;
if (!(pEmac->EMAC_SR & AT91C_EMAC_LINK))
MII_GetLinkSpeed(pEmac);
pEmac->EMAC_RBQP = (unsigned) p_rxBD;
pEmac->EMAC_RSR |= (AT91C_EMAC_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA);
pEmac->EMAC_CTL = AT91C_EMAC_TE | AT91C_EMAC_RE;
pEmac->EMAC_TAR = (unsigned)transmitBuffer;
}
/* ************************** GLOBAL FUNCTIONS ********************************/
/*
* .KB_C_FN_DEFINITION_START
* void SetServerIPAddress(unsigned address)
* This global function sets the IP of the TFTP download server.
* .KB_C_FN_DEFINITION_END
*/
void
SetServerIPAddress(unsigned address)
{
// force update in case the IP has changed
serverMACSet = 0;
serverIPAddr[0] = (address >> 24) & 0xFF;
serverIPAddr[1] = (address >> 16) & 0xFF;
serverIPAddr[2] = (address >> 8) & 0xFF;
serverIPAddr[3] = (address >> 0) & 0xFF;
serverIPSet = 1;
}
/*
* .KB_C_FN_DEFINITION_START
* void SetLocalIPAddress(unsigned address)
* This global function sets the IP of this module.
* .KB_C_FN_DEFINITION_END
*/
void
SetLocalIPAddress(unsigned address)
{
// force update in case the IP has changed
serverMACSet = 0;
localIPAddr[0] = (address >> 24) & 0xFF;
localIPAddr[1] = (address >> 16) & 0xFF;
localIPAddr[2] = (address >> 8) & 0xFF;
localIPAddr[3] = (address >> 0) & 0xFF;
localIPSet = 1;
}
/*
* .KB_C_FN_DEFINITION_START
* void TFTP_Download(unsigned address, char *filename)
* This global function initiates and processes a tftp download request.
* The server IP, local IP, local MAC must be set before this function is
* executed.
* .KB_C_FN_DEFINITION_END
*/
void
TFTP_Download(unsigned address, char *filename)
{
ip_header_t IpHeader;
unsigned thisSeconds;
int timeout;
if ((!localMACSet) || (!localIPSet) || (!serverIPSet))
return ;
AT91F_EmacEntry();
GetServerAddress();
dlAddress = (char*)address;
lastSize = 0;
timeout = 10;
thisSeconds = (GetSeconds() + 2) % 32;
serverPort = SWAP16(69);
++localPort;
ackBlock = -1;
while (timeout) {
if (CheckForNewPacket(&IpHeader)) {
if (ackBlock == -2)
break;
timeout = 10;
thisSeconds = (GetSeconds() + 2) % 32;
} else if (GetSeconds() == thisSeconds) {
--timeout;
thisSeconds = (GetSeconds() + 2) % 32;
if (!serverMACSet)
GetServerAddress();
else if (ackBlock == -1)
TFTP_RequestFile(filename);
else {
// Be sure to send a NAK, which is done by
// ACKing the last block we got.
TFTP_ACK_Data(0, ackBlock, 512);
printf("\nNAK %u\n", ackBlock);
}
}
}
if (timeout == 0)
printf("TFTP TIMEOUT!\n");
}

View File

@ -1,135 +0,0 @@
/******************************************************************************
*
* Filename: emac.h
*
* Definition of routine to set the MAC address.
*
* Revision information:
*
* 28AUG2004 kb_admin initial creation
*
* BEGIN_KBDD_BLOCK
* No warranty, expressed or implied, is included with this software. It is
* provided "AS IS" and no warranty of any kind including statutory or aspects
* relating to merchantability or fitness for any purpose is provided. All
* intellectual property rights of others is maintained with the respective
* owners. This software is not copyrighted and is intended for reference
* only.
* END_BLOCK
*
* $FreeBSD$
*****************************************************************************/
#ifndef _EMAC_H_
#define _EMAC_H_
extern void EMAC_SetMACAddress(unsigned char addr[6]);
extern void SetServerIPAddress(unsigned address);
extern void SetLocalIPAddress(unsigned address);
extern void EMAC_Init(void);
extern void TFTP_Download(unsigned address, char *filename);
#define MAX_RX_PACKETS 8
#define RX_PACKET_SIZE 1536
#define RX_BUFFER_START 0x21000000
#define RX_DATA_START (RX_BUFFER_START + (8 * MAX_RX_PACKETS))
#define ARP_REQUEST 0x0001
#define ARP_REPLY 0x0002
#define PROTOCOL_ARP 0x0806
#define PROTOCOL_IP 0x0800
#define PROTOCOL_UDP 0x11
#define SWAP16(x) ((((x) & 0xff) << 8) | ((x) >> 8))
typedef struct {
unsigned address;
unsigned size;
} receive_descriptor_t;
typedef struct {
unsigned char dest_mac[6];
unsigned char src_mac[6];
unsigned short frame_type;
unsigned short hard_type;
unsigned short prot_type;
unsigned char hard_size;
unsigned char prot_size;
unsigned short operation;
unsigned char sender_mac[6];
unsigned char sender_ip[4];
unsigned char target_mac[6];
unsigned char target_ip[4];
} __attribute__((__packed__)) arp_header_t;
typedef struct {
unsigned char ip_v_hl;
unsigned char ip_tos;
unsigned short ip_len;
unsigned short ip_id;
unsigned short ip_off;
unsigned char ip_ttl;
unsigned char ip_p;
unsigned short ip_sum;
unsigned char ip_src[4];
unsigned char ip_dst[4];
} __attribute__((__packed__)) ip_header_t;
typedef struct {
unsigned char dest_mac[6];
unsigned char src_mac[6];
unsigned short proto_mac;
unsigned short packet_length;
ip_header_t iphdr;
} __attribute__((__packed__)) transmit_header_t;
typedef struct {
unsigned short src_port;
unsigned short dst_port;
unsigned short udp_len;
unsigned short udp_cksum;
} __attribute__((__packed__)) udp_header_t;
typedef struct {
unsigned short opcode;
unsigned short block_num;
unsigned char data[512];
} __attribute__((__packed__)) tftp_header_t;
// Preswap bytes
#define TFTP_RRQ_OPCODE 0x0100
#define TFTP_WRQ_OPCODE 0x0200
#define TFTP_DATA_OPCODE 0x0300
#define TFTP_ACK_OPCODE 0x0400
#define TFTP_ERROR_OPCODE 0x0500
/* MII registers definition */
#define MII_STS_REG 0x01
#define MII_STS_LINK_STAT 0x04
#if defined(BOOT_KB920X) || defined(BOOT_CENTIPAD)
#define MII_STS2_REG 0x11
#define MII_STS2_LINK 0x400
#define MII_STS2_100TX 0x4000
#define MII_STS2_FDX 0x200
#else
#define MII_SPEC_STS_REG 0x11
#define MII_SSTS_100FDX 0x8000
#define MII_SSTS_100HDX 0x4000
#define MII_SSTS_10FDX 0x2000
#define MII_SSTS_10HDX 0x1000
#endif
extern unsigned char localMACAddr[6];
extern unsigned localMAClow, localMAChigh;
extern unsigned localMACSet;
#define EMAC_Init()
#endif /* _EMAC_H_ */

View File

@ -1,117 +0,0 @@
/*-
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software is derived from software provide by Kwikbyte who specifically
* disclaimed copyright on the code.
*
* $FreeBSD$
*/
/******************************************************************************
*
* Filename: emac.c
*
* Instantiation of routines for MAC/ethernet functions supporting tftp.
*
* Revision information:
*
* 28AUG2004 kb_admin initial creation
* 08JAN2005 kb_admin added tftp download
* also adapted from external sources
*
* BEGIN_KBDD_BLOCK
* No warranty, expressed or implied, is included with this software. It is
* provided "AS IS" and no warranty of any kind including statutory or aspects
* relating to merchantability or fitness for any purpose is provided. All
* intellectual property rights of others is maintained with the respective
* owners. This software is not copyrighted and is intended for reference
* only.
* END_BLOCK
******************************************************************************/
#include "at91rm9200.h"
#include "at91rm9200_lowlevel.h"
#include "emac.h"
#include "lib.h"
/* ****************************** GLOBALS *************************************/
unsigned localMACSet;
unsigned char localMACAddr[6];
unsigned localMAClow, localMAChigh;
/* ********************** PRIVATE FUNCTIONS/DATA ******************************/
/*
* .KB_C_FN_DEFINITION_START
* void EMAC_SetMACAddress(unsigned low_address, unsigned high_address)
* This global function sets the MAC address. low_address is the first
* four bytes while high_address is the last 2 bytes of the 48-bit value.
* .KB_C_FN_DEFINITION_END
*/
void
EMAC_SetMACAddress(unsigned char mac[6])
{
AT91PS_PMC pPMC = AT91C_BASE_PMC;
AT91PS_EMAC pEmac = AT91C_BASE_EMAC;
/* enable the peripheral clock before using EMAC */
pPMC->PMC_PCER = ((unsigned) 1 << AT91C_ID_EMAC);
memcpy(localMACAddr, mac, 6);
localMAClow = (mac[3] << 24) | (mac[2] << 16) | (mac[1] << 8) | mac[0];
localMAChigh = (mac[5] << 8) | mac[4];
localMACSet = 1;
AT91C_BASE_PMC->PMC_PCER = 1u << AT91C_ID_EMAC;
AT91C_BASE_PIOA->PIO_ASR =
AT91C_PIO_PA14 | AT91C_PIO_PA12 | AT91C_PIO_PA13 |
AT91C_PIO_PA8 | AT91C_PIO_PA16 | AT91C_PIO_PA9 |
AT91C_PIO_PA10 | AT91C_PIO_PA11 | AT91C_PIO_PA15 |
AT91C_PIO_PA7;
AT91C_BASE_PIOA->PIO_PDR =
AT91C_PIO_PA14 | AT91C_PIO_PA12 | AT91C_PIO_PA13 |
AT91C_PIO_PA8 | AT91C_PIO_PA16 | AT91C_PIO_PA9 |
AT91C_PIO_PA10 | AT91C_PIO_PA11 | AT91C_PIO_PA15 |
AT91C_PIO_PA7;
#if defined(BOOT_KB920X) | defined(BOOT_BWCT) /* Really !RMII */
AT91C_BASE_PIOB->PIO_BSR =
AT91C_PIO_PB12 | AT91C_PIO_PB13 | AT91C_PIO_PB14 |
AT91C_PIO_PB15 | AT91C_PIO_PB16 | AT91C_PIO_PB17 |
AT91C_PIO_PB18 | AT91C_PIO_PB19;
AT91C_BASE_PIOB->PIO_PDR =
AT91C_PIO_PB12 | AT91C_PIO_PB13 | AT91C_PIO_PB14 |
AT91C_PIO_PB15 | AT91C_PIO_PB16 | AT91C_PIO_PB17 |
AT91C_PIO_PB18 | AT91C_PIO_PB19;
#endif
pEmac->EMAC_CTL = 0;
pEmac->EMAC_CFG = (pEmac->EMAC_CFG & ~(AT91C_EMAC_CLK)) |
#ifdef BOOT_TSC
AT91C_EMAC_RMII |
#endif
AT91C_EMAC_CLK_HCLK_32 | AT91C_EMAC_CAF;
// the sequence write EMAC_SA1L and write EMAC_SA1H must be respected
pEmac->EMAC_SA1L = localMAClow;
pEmac->EMAC_SA1H = localMAChigh;
}

View File

@ -1,64 +0,0 @@
/*-
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software is derived from software provided by kwikbyte without
* copyright as follows:
*
* No warranty, expressed or implied, is included with this software. It is
* provided "AS IS" and no warranty of any kind including statutory or aspects
* relating to merchantability or fitness for any purpose is provided. All
* intellectual property rights of others is maintained with the respective
* owners. This software is not copyrighted and is intended for reference
* only.
*
* $FreeBSD$
*/
#include "at91rm9200.h"
#include "at91rm9200_lowlevel.h"
#include "lib.h"
/*
* int getc(int seconds)
*
* Reads a character from the DBGU port, if one is available within about
* seconds seconds. It assumes that DBGU has already been initialized.
*/
int
getc(int seconds)
{
AT91PS_USART pUSART = (AT91PS_USART)AT91C_BASE_DBGU;
unsigned thisSecond;
// Clamp to 20s
if (seconds > 20)
seconds = 20;
thisSecond = GetSeconds();
seconds = thisSecond + seconds;
do {
if ((pUSART->US_CSR & AT91C_US_RXRDY))
return (pUSART->US_RHR & 0xFF);
thisSecond = GetSeconds();
} while (thisSecond != seconds);
return (-1);
}

View File

@ -1,65 +0,0 @@
/*-
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef ARM_BOOT_LIB_H
#define ARM_BOOT_LIB_H
int getc(int);
void putchar(int);
void xputchar(int);
void printf(const char *fmt,...);
/* The following function write eeprom at ee_addr using data */
/* from data_add for size bytes. */
int ReadEEPROM(unsigned eeoff, unsigned char *data_addr, unsigned size);
void WriteEEPROM(unsigned eeoff, char *data_addr, unsigned size);
void InitEEPROM(void);
/* XMODEM protocol */
int xmodem_rx(char *dst);
/* */
void start_wdog(int n);
void reset(void);
/* Delay us */
void Delay(int us);
#define ToASCII(x) ((x > 9) ? (x + 'A' - 0xa) : (x + '0'))
int p_IsWhiteSpace(char cValue);
unsigned p_HexCharValue(char cValue);
unsigned p_ASCIIToHex(const char *buf);
unsigned p_ASCIIToDec(const char *buf);
void p_memset(char *buffer, char value, int size);
int p_strlen(const char *buffer);
char *strcpy(char *to, const char *from);
void memcpy(void *to, const void *from, unsigned size);
int p_memcmp(const char *to, const char *from, unsigned size);
int strcmp(const char *to, const char *from);
#endif

View File

@ -1,277 +0,0 @@
/*-
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software is derived from software provide by Kwikbyte who specifically
* disclaimed copyright on the code.
*
* $FreeBSD$
*/
#ifndef __LIBAT91RM9200_H
#define __LIBAT91RM9200_H
#include "at91rm9200.h"
//*----------------------------------------------------------------------------
//* \fn AT91F_PMC_EnablePeriphClock
//* \brief Enable peripheral clock
//*----------------------------------------------------------------------------
static inline void
AT91F_PMC_EnablePeriphClock (
AT91PS_PMC pPMC, // \arg pointer to PMC controller
unsigned int periphIds) // \arg IDs of peripherals to enable
{
pPMC->PMC_PCER = periphIds;
}
/* *****************************************************************************
SOFTWARE API FOR PIO
***************************************************************************** */
//*----------------------------------------------------------------------------
//* \fn AT91F_PIO_CfgPeriph
//* \brief Enable pins to be drived by peripheral
//*----------------------------------------------------------------------------
static inline
void AT91F_PIO_CfgPeriph(
AT91PS_PIO pPio, // \arg pointer to a PIO controller
unsigned int periphAEnable, // \arg PERIPH A to enable
unsigned int periphBEnable) // \arg PERIPH B to enable
{
if (periphAEnable)
pPio->PIO_ASR = periphAEnable;
if (periphBEnable)
pPio->PIO_BSR = periphBEnable;
pPio->PIO_PDR = (periphAEnable | periphBEnable); // Set in Periph mode
}
/* *****************************************************************************
SOFTWARE API FOR MCI
***************************************************************************** */
//* Classic MCI Data Timeout Register Configuration with 1048576 MCK cycles between 2 data transfer
#define AT91C_MCI_DTOR_1MEGA_CYCLES (AT91C_MCI_DTOCYC | AT91C_MCI_DTOMUL)
//* Classic MCI SDCard Register Configuration with 1-bit data bus on slot A
#define AT91C_MCI_MMC_SLOTA (AT91C_MCI_SCDSEL & 0x0)
//* Classic MCI SDCard Register Configuration with 1-bit data bus on slot B
#define AT91C_MCI_MMC_SLOTB (AT91C_MCI_SCDSEL)
//* Classic MCI SDCard Register Configuration with 4-bit data bus on slot A
#define AT91C_MCI_SDCARD_4BITS_SLOTA ( (AT91C_MCI_SCDSEL & 0x0) | AT91C_MCI_SCDBUS )
//* Classic MCI SDCard Register Configuration with 4-bit data bus on slot B
#define AT91C_MCI_SDCARD_4BITS_SLOTB (AT91C_MCI_SCDSEL | AT91C_MCI_SCDBUS)
//*----------------------------------------------------------------------------
//* \fn AT91F_MCI_Configure
//* \brief Configure the MCI
//*----------------------------------------------------------------------------
static inline
void AT91F_MCI_Configure(
AT91PS_MCI pMCI, // \arg pointer to a MCI controller
unsigned int DTOR_register, // \arg Data Timeout Register to be programmed
unsigned int MR_register, // \arg Mode Register to be programmed
unsigned int SDCR_register) // \arg SDCard Register to be programmed
{
//* Reset the MCI
pMCI->MCI_CR = AT91C_MCI_MCIEN | AT91C_MCI_PWSEN;
//* Disable all the interrupts
pMCI->MCI_IDR = 0xFFFFFFFF;
//* Set the Data Timeout Register
pMCI->MCI_DTOR = DTOR_register;
//* Set the Mode Register
pMCI->MCI_MR = MR_register;
//* Set the SDCard Register
pMCI->MCI_SDCR = SDCR_register;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_MCI_CfgPMC
//* \brief Enable Peripheral clock in PMC for MCI
//*----------------------------------------------------------------------------
static inline void
AT91F_MCI_CfgPMC(void)
{
AT91F_PMC_EnablePeriphClock(
AT91C_BASE_PMC, // PIO controller base address
((unsigned int) 1 << AT91C_ID_MCI));
}
//*----------------------------------------------------------------------------
//* \fn AT91F_MCI_CfgPIO
//* \brief Configure PIO controllers to drive MCI signals
//*----------------------------------------------------------------------------
static inline void
AT91F_MCI_CfgPIO(void)
{
// Configure PIO controllers to periph mode
AT91F_PIO_CfgPeriph(
AT91C_BASE_PIOA, // PIO controller base address
((unsigned int) AT91C_PIO_PA28 ) |
((unsigned int) AT91C_PIO_PA29 ) |
((unsigned int) AT91C_PIO_PA27 ), // Peripheral A
0); // Peripheral B
// Configure PIO controllers to periph mode
AT91F_PIO_CfgPeriph(
AT91C_BASE_PIOB, // PIO controller base address
0, // Peripheral A
((unsigned int) AT91C_PIO_PB5 ) |
((unsigned int) AT91C_PIO_PB3 ) |
((unsigned int) AT91C_PIO_PB4 )); // Peripheral B
}
/* *****************************************************************************
SOFTWARE API FOR PDC
***************************************************************************** */
//*----------------------------------------------------------------------------
//* \fn AT91F_PDC_SetNextRx
//* \brief Set the next receive transfer descriptor
//*----------------------------------------------------------------------------
static inline void
AT91F_PDC_SetNextRx (
AT91PS_PDC pPDC, // \arg pointer to a PDC controller
char *address, // \arg address to the next bloc to be received
unsigned int bytes) // \arg number of bytes to be received
{
pPDC->PDC_RNPR = (unsigned int) address;
pPDC->PDC_RNCR = bytes;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_PDC_SetNextTx
//* \brief Set the next transmit transfer descriptor
//*----------------------------------------------------------------------------
static inline void
AT91F_PDC_SetNextTx(
AT91PS_PDC pPDC, // \arg pointer to a PDC controller
char *address, // \arg address to the next bloc to be transmitted
unsigned int bytes) // \arg number of bytes to be transmitted
{
pPDC->PDC_TNPR = (unsigned int) address;
pPDC->PDC_TNCR = bytes;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_PDC_SetRx
//* \brief Set the receive transfer descriptor
//*----------------------------------------------------------------------------
static inline void
AT91F_PDC_SetRx(
AT91PS_PDC pPDC, // \arg pointer to a PDC controller
char *address, // \arg address to the next bloc to be received
unsigned int bytes) // \arg number of bytes to be received
{
pPDC->PDC_RPR = (unsigned int) address;
pPDC->PDC_RCR = bytes;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_PDC_SetTx
//* \brief Set the transmit transfer descriptor
//*----------------------------------------------------------------------------
static inline void
AT91F_PDC_SetTx(
AT91PS_PDC pPDC, // \arg pointer to a PDC controller
char *address, // \arg address to the next bloc to be transmitted
unsigned int bytes) // \arg number of bytes to be transmitted
{
pPDC->PDC_TPR = (unsigned int) address;
pPDC->PDC_TCR = bytes;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_PDC_EnableTx
//* \brief Enable transmit
//*----------------------------------------------------------------------------
static inline void
AT91F_PDC_EnableTx(
AT91PS_PDC pPDC ) // \arg pointer to a PDC controller
{
pPDC->PDC_PTCR = AT91C_PDC_TXTEN;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_PDC_EnableRx
//* \brief Enable receive
//*----------------------------------------------------------------------------
static inline void
AT91F_PDC_EnableRx(
AT91PS_PDC pPDC ) // \arg pointer to a PDC controller
{
pPDC->PDC_PTCR = AT91C_PDC_RXTEN;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_PDC_DisableTx
//* \brief Disable transmit
//*----------------------------------------------------------------------------
static inline void
AT91F_PDC_DisableTx(
AT91PS_PDC pPDC ) // \arg pointer to a PDC controller
{
pPDC->PDC_PTCR = AT91C_PDC_TXTDIS;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_PDC_DisableRx
//* \brief Disable receive
//*----------------------------------------------------------------------------
static inline void
AT91F_PDC_DisableRx(
AT91PS_PDC pPDC ) // \arg pointer to a PDC controller
{
pPDC->PDC_PTCR = AT91C_PDC_RXTDIS;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_PDC_Open
//* \brief Open PDC: disable TX and RX reset transfer descriptors, re-enable RX and TX
//*----------------------------------------------------------------------------
static inline void
AT91F_PDC_Open(
AT91PS_PDC pPDC) // \arg pointer to a PDC controller
{
//* Disable the RX and TX PDC transfer requests
AT91F_PDC_DisableRx(pPDC);
AT91F_PDC_DisableTx(pPDC);
//* Reset all Counter register Next buffer first
AT91F_PDC_SetNextTx(pPDC, (char *) 0, 0);
AT91F_PDC_SetNextRx(pPDC, (char *) 0, 0);
AT91F_PDC_SetTx(pPDC, (char *) 0, 0);
AT91F_PDC_SetRx(pPDC, (char *) 0, 0);
//* Enable the RX and TX PDC transfer requests
AT91F_PDC_EnableRx(pPDC);
AT91F_PDC_EnableTx(pPDC);
}
#endif

View File

@ -1,434 +0,0 @@
/*-
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software is derived from software provide by Kwikbyte who specifically
* disclaimed copyright on the code.
*
* $FreeBSD$
*/
//*---------------------------------------------------------------------------
//* ATMEL Microcontroller Software Support - ROUSSET -
//*---------------------------------------------------------------------------
//* The software is delivered "AS IS" without warranty or condition of any
//* kind, either express, implied or statutory. This includes without
//* limitation any warranty or condition with respect to merchantability or
//* fitness for any particular purpose, or against the infringements of
//* intellectual property rights of others.
//*---------------------------------------------------------------------------
//* File Name : AT91C_MCI_Device.h
//* Object : Data Flash Atmel Description File
//* Translator :
//*
//* 1.0 26/11/02 FB : Creation
//*---------------------------------------------------------------------------
#ifndef __MCI_Device_h
#define __MCI_Device_h
#include <sys/types.h>
typedef unsigned int AT91S_MCIDeviceStatus;
///////////////////////////////////////////////////////////////////////////////
#define AT91C_CARD_REMOVED 0
#define AT91C_MMC_CARD_INSERTED 1
#define AT91C_SD_CARD_INSERTED 2
#define AT91C_NO_ARGUMENT 0x0
#define AT91C_FIRST_RCA 0xCAFE
#define AT91C_MAX_MCI_CARDS 10
#define AT91C_BUS_WIDTH_1BIT 0x00
#define AT91C_BUS_WIDTH_4BITS 0x02
/* Driver State */
#define AT91C_MCI_IDLE 0x0
#define AT91C_MCI_TIMEOUT_ERROR 0x1
#define AT91C_MCI_RX_SINGLE_BLOCK 0x2
#define AT91C_MCI_RX_MULTIPLE_BLOCK 0x3
#define AT91C_MCI_RX_STREAM 0x4
#define AT91C_MCI_TX_SINGLE_BLOCK 0x5
#define AT91C_MCI_TX_MULTIPLE_BLOCK 0x6
#define AT91C_MCI_TX_STREAM 0x7
/* TimeOut */
#define AT91C_TIMEOUT_CMDRDY 30
///////////////////////////////////////////////////////////////////////////////
// MMC & SDCard Structures
///////////////////////////////////////////////////////////////////////////////
/*---------------------------------------------*/
/* MCI Device Structure Definition */
/*---------------------------------------------*/
typedef struct _AT91S_MciDevice
{
volatile unsigned char state;
unsigned char SDCard_bus_width;
unsigned char IsSDv2;
unsigned char IsSDHC;
unsigned int RCA; // RCA
unsigned int READ_BL_LEN;
#ifdef REPORT_SIZE
unsigned int Memory_Capacity;
#endif
} AT91S_MciDevice;
#include <dev/mmc/mmcreg.h>
///////////////////////////////////////////////////////////////////////////////
// Functions returnals
///////////////////////////////////////////////////////////////////////////////
#define AT91C_CMD_SEND_OK 0 // Command ok
#define AT91C_CMD_SEND_ERROR -1 // Command failed
#define AT91C_INIT_OK 2 // Init Successful
#define AT91C_INIT_ERROR 3 // Init Failed
#define AT91C_READ_OK 4 // Read Successful
#define AT91C_READ_ERROR 5 // Read Failed
#define AT91C_WRITE_OK 6 // Write Successful
#define AT91C_WRITE_ERROR 7 // Write Failed
#define AT91C_ERASE_OK 8 // Erase Successful
#define AT91C_ERASE_ERROR 9 // Erase Failed
#define AT91C_CARD_SELECTED_OK 10 // Card Selection Successful
#define AT91C_CARD_SELECTED_ERROR 11 // Card Selection Failed
#define AT91C_MCI_SR_ERROR (AT91C_MCI_UNRE | AT91C_MCI_OVRE | AT91C_MCI_DTOE | \
AT91C_MCI_DCRCE | AT91C_MCI_RTOE | AT91C_MCI_RENDE | AT91C_MCI_RCRCE | \
AT91C_MCI_RDIRE | AT91C_MCI_RINDE)
#define MMC_CMDNB (0x1Fu << 0) // Command Number
#define MMC_RSPTYP (0x3u << 6) // Response Type
#define MMC_RSPTYP_NO (0x0u << 6) // No response
#define MMC_RSPTYP_48 (0x1u << 6) // 48-bit response
#define MMC_RSPTYP_136 (0x2u << 6) // 136-bit response
#define MMC_SPCMD (0x7u << 8) // Special CMD
#define MMC_SPCMD_NONE (0x0u << 8) // Not a special CMD
#define MMC_SPCMD_INIT (0x1u << 8) // Initialization CMD
#define MMC_SPCMD_SYNC (0x2u << 8) // Synchronized CMD
#define MMC_SPCMD_IT_CMD (0x4u << 8) // Interrupt command
#define MMC_SPCMD_IT_REP (0x5u << 8) // Interrupt response
#define MMC_OPDCMD (0x1u << 11) // Open Drain Command
#define MMC_MAXLAT (0x1u << 12) // Maximum Latency for Command to respond
#define MMC_TRCMD (0x3u << 16) // Transfer CMD
#define MMC_TRCMD_NO (0x0u << 16) // No transfer
#define MMC_TRCMD_START (0x1u << 16) // Start transfer
#define MMC_TRCMD_STOP (0x2u << 16) // Stop transfer
#define MMC_TRDIR (0x1u << 18) // Transfer Direction
#define MMC_TRTYP (0x3u << 19) // Transfer Type
#define MMC_TRTYP_BLOCK (0x0u << 19) // Block Transfer type
#define MMC_TRTYP_MULTIPLE (0x1u << 19) // Multiple Block transfer type
#define MMC_TRTYP_STREAM (0x2u << 19) // Stream transfer type
///////////////////////////////////////////////////////////////////////////////
// MCI_CMD Register Value
///////////////////////////////////////////////////////////////////////////////
#define POWER_ON_INIT \
(0 | MMC_TRCMD_NO | MMC_SPCMD_INIT | MMC_OPDCMD)
/////////////////////////////////////////////////////////////////
// Class 0 & 1 commands: Basic commands and Read Stream commands
/////////////////////////////////////////////////////////////////
#define GO_IDLE_STATE_CMD \
(0 | MMC_TRCMD_NO | MMC_SPCMD_NONE )
#define MMC_GO_IDLE_STATE_CMD \
(0 | MMC_TRCMD_NO | MMC_SPCMD_NONE | MMC_OPDCMD)
#define MMC_SEND_OP_COND_CMD \
(1 | MMC_TRCMD_NO | MMC_SPCMD_NONE | MMC_RSPTYP_48 | \
MMC_OPDCMD)
#define ALL_SEND_CID_CMD \
(2 | MMC_TRCMD_NO | MMC_SPCMD_NONE | MMC_RSPTYP_136)
#define MMC_ALL_SEND_CID_CMD \
(2 | MMC_TRCMD_NO | MMC_SPCMD_NONE | MMC_RSPTYP_136 | \
MMC_OPDCMD)
#define SET_RELATIVE_ADDR_CMD \
(3 | MMC_TRCMD_NO | MMC_SPCMD_NONE | MMC_RSPTYP_48 | \
MMC_MAXLAT)
#define MMC_SET_RELATIVE_ADDR_CMD \
(3 | MMC_TRCMD_NO | MMC_SPCMD_NONE | MMC_RSPTYP_48 | \
MMC_MAXLAT | MMC_OPDCMD)
#define SET_DSR_CMD \
(4 | MMC_TRCMD_NO | MMC_SPCMD_NONE | MMC_RSPTYP_NO | \
MMC_MAXLAT) // no tested
#define SEL_DESEL_CARD_CMD \
(7 | MMC_TRCMD_NO | MMC_SPCMD_NONE | MMC_RSPTYP_48 | \
MMC_MAXLAT)
#define SEND_CSD_CMD \
(9 | MMC_TRCMD_NO | MMC_SPCMD_NONE | MMC_RSPTYP_136 | \
MMC_MAXLAT)
#define SEND_CID_CMD \
(10 | MMC_TRCMD_NO | MMC_SPCMD_NONE | MMC_RSPTYP_136 | \
MMC_MAXLAT)
#define MMC_READ_DAT_UNTIL_STOP_CMD \
(11 | MMC_TRTYP_STREAM | MMC_SPCMD_NONE | \
MMC_RSPTYP_48 | MMC_TRDIR | MMC_TRCMD_START | \
MMC_MAXLAT)
#define STOP_TRANSMISSION_CMD \
(12 | MMC_TRCMD_STOP | MMC_SPCMD_NONE | MMC_RSPTYP_48 | \
MMC_MAXLAT)
#define STOP_TRANSMISSION_SYNC_CMD \
(12 | MMC_TRCMD_STOP | MMC_SPCMD_SYNC | MMC_RSPTYP_48 | \
MMC_MAXLAT)
#define SEND_STATUS_CMD \
(13 | MMC_TRCMD_NO | MMC_SPCMD_NONE | MMC_RSPTYP_48 | \
MMC_MAXLAT)
#define GO_INACTIVE_STATE_CMD \
(15 | MMC_RSPTYP_NO)
#define SD_SEND_IF_COND_CMD \
(8 | MMC_TRCMD_NO | MMC_SPCMD_NONE | MMC_RSPTYP_48 | \
MMC_MAXLAT)
//*------------------------------------------------
//* Class 2 commands: Block oriented Read commands
//*------------------------------------------------
#define SET_BLOCKLEN_CMD (16 | MMC_TRCMD_NO | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_MAXLAT )
#define READ_SINGLE_BLOCK_CMD (17 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_START | MMC_TRTYP_BLOCK | MMC_TRDIR | MMC_MAXLAT)
#define READ_MULTIPLE_BLOCK_CMD (18 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_START | MMC_TRTYP_MULTIPLE | MMC_TRDIR | MMC_MAXLAT)
//*--------------------------------------------
//* Class 3 commands: Sequential write commands
//*--------------------------------------------
#define MMC_WRITE_DAT_UNTIL_STOP_CMD (20 | MMC_TRTYP_STREAM| MMC_SPCMD_NONE | MMC_RSPTYP_48 & ~(MMC_TRDIR) | MMC_TRCMD_START | MMC_MAXLAT ) // MMC
//*------------------------------------------------
//* Class 4 commands: Block oriented write commands
//*------------------------------------------------
#define WRITE_BLOCK_CMD (24 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_START | (MMC_TRTYP_BLOCK & ~(MMC_TRDIR)) | MMC_MAXLAT)
#define WRITE_MULTIPLE_BLOCK_CMD (25 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_START | (MMC_TRTYP_MULTIPLE & ~(MMC_TRDIR)) | MMC_MAXLAT)
#define PROGRAM_CSD_CMD (27 | MMC_RSPTYP_48 )
//*----------------------------------------
//* Class 6 commands: Group Write protect
//*----------------------------------------
#define SET_WRITE_PROT_CMD (28 | MMC_RSPTYP_48 )
#define CLR_WRITE_PROT_CMD (29 | MMC_RSPTYP_48 )
#define SEND_WRITE_PROT_CMD (30 | MMC_RSPTYP_48 )
//*----------------------------------------
//* Class 5 commands: Erase commands
//*----------------------------------------
#define TAG_SECTOR_START_CMD (32 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_NO | MMC_MAXLAT)
#define TAG_SECTOR_END_CMD (33 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_NO | MMC_MAXLAT)
#define MMC_UNTAG_SECTOR_CMD (34 | MMC_RSPTYP_48 )
#define MMC_TAG_ERASE_GROUP_START_CMD (35 | MMC_RSPTYP_48 )
#define MMC_TAG_ERASE_GROUP_END_CMD (36 | MMC_RSPTYP_48 )
#define MMC_UNTAG_ERASE_GROUP_CMD (37 | MMC_RSPTYP_48 )
#define ERASE_CMD (38 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_NO | MMC_MAXLAT )
//*----------------------------------------
//* Class 7 commands: Lock commands
//*----------------------------------------
#define LOCK_UNLOCK (42 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_NO | MMC_MAXLAT) // no tested
//*-----------------------------------------------
// Class 8 commands: Application specific commands
//*-----------------------------------------------
#define APP_CMD (55 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_NO | MMC_MAXLAT)
#define GEN_CMD (56 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_NO | MMC_MAXLAT) // no tested
#define SDCARD_SET_BUS_WIDTH_CMD (6 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_NO | MMC_MAXLAT)
#define SDCARD_STATUS_CMD (13 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_NO | MMC_MAXLAT)
#define SDCARD_SEND_NUM_WR_BLOCKS_CMD (22 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_NO | MMC_MAXLAT)
#define SDCARD_SET_WR_BLK_ERASE_COUNT_CMD (23 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_NO | MMC_MAXLAT)
#define SDCARD_APP_OP_COND_CMD (41 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_NO | MMC_MAXLAT)
#define SDCARD_SET_CLR_CARD_DETECT_CMD (42 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_NO | MMC_MAXLAT)
#define SDCARD_SEND_SCR_CMD (51 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_NO | MMC_MAXLAT)
#define SDCARD_APP_ALL_CMD (SDCARD_SET_BUS_WIDTH_CMD +\
SDCARD_STATUS_CMD +\
SDCARD_SEND_NUM_WR_BLOCKS_CMD +\
SDCARD_SET_WR_BLK_ERASE_COUNT_CMD +\
SDCARD_APP_OP_COND_CMD +\
SDCARD_SET_CLR_CARD_DETECT_CMD +\
SDCARD_SEND_SCR_CMD)
//*----------------------------------------
//* Class 9 commands: IO Mode commands
//*----------------------------------------
#define MMC_FAST_IO_CMD (39 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_MAXLAT)
#define MMC_GO_IRQ_STATE_CMD (40 | MMC_SPCMD_NONE | MMC_RSPTYP_48 | MMC_TRCMD_NO | MMC_MAXLAT)
///////////////////////////////////////////////////////////////////////////////
// OCR Register
///////////////////////////////////////////////////////////////////////////////
#define AT91C_VDD_16_17 (1 << 4)
#define AT91C_VDD_17_18 (1 << 5)
#define AT91C_VDD_18_19 (1 << 6)
#define AT91C_VDD_19_20 (1 << 7)
#define AT91C_VDD_20_21 (1 << 8)
#define AT91C_VDD_21_22 (1 << 9)
#define AT91C_VDD_22_23 (1 << 10)
#define AT91C_VDD_23_24 (1 << 11)
#define AT91C_VDD_24_25 (1 << 12)
#define AT91C_VDD_25_26 (1 << 13)
#define AT91C_VDD_26_27 (1 << 14)
#define AT91C_VDD_27_28 (1 << 15)
#define AT91C_VDD_28_29 (1 << 16)
#define AT91C_VDD_29_30 (1 << 17)
#define AT91C_VDD_30_31 (1 << 18)
#define AT91C_VDD_31_32 (1 << 19)
#define AT91C_VDD_32_33 (1 << 20)
#define AT91C_VDD_33_34 (1 << 21)
#define AT91C_VDD_34_35 (1 << 22)
#define AT91C_VDD_35_36 (1 << 23)
#define AT91C_CCS (1 << 30)
#define AT91C_CARD_POWER_UP_DONE (1U << 31)
#define AT91C_MMC_HOST_VOLTAGE_RANGE (AT91C_VDD_27_28 | AT91C_VDD_28_29 | \
AT91C_VDD_29_30 | AT91C_VDD_30_31 | AT91C_VDD_31_32 | AT91C_VDD_32_33)
///////////////////////////////////////////////////////////////////////////////
// CURRENT_STATE & READY_FOR_DATA in SDCard Status Register definition (response type R1)
///////////////////////////////////////////////////////////////////////////////
#define AT91C_SR_READY_FOR_DATA (1 << 8) // corresponds to buffer empty signalling on the bus
#define AT91C_SR_IDLE (0 << 9)
#define AT91C_SR_READY (1 << 9)
#define AT91C_SR_IDENT (2 << 9)
#define AT91C_SR_STBY (3 << 9)
#define AT91C_SR_TRAN (4 << 9)
#define AT91C_SR_DATA (5 << 9)
#define AT91C_SR_RCV (6 << 9)
#define AT91C_SR_PRG (7 << 9)
#define AT91C_SR_DIS (8 << 9)
#define AT91C_SR_CARD_SELECTED (AT91C_SR_READY_FOR_DATA + AT91C_SR_TRAN)
#define MMC_FIRST_RCA 0xCAFE
///////////////////////////////////////////////////////////////////////////////
// MMC CSD register header File
// CSD_x_xxx_S for shift value for word x
// CSD_x_xxx_M for mask value for word x
///////////////////////////////////////////////////////////////////////////////
// First Response INT <=> CSD[3] : bits 0 to 31
#define CSD_3_BIT0_S 0 // [0:0]
#define CSD_3_BIT0_M 0x01
#define CSD_3_CRC_S 1 // [7:1]
#define CSD_3_CRC_M 0x7F
#define CSD_3_MMC_ECC_S 8 // [9:8] reserved for MMC compatibility
#define CSD_3_MMC_ECC_M 0x03
#define CSD_3_FILE_FMT_S 10 // [11:10]
#define CSD_3_FILE_FMT_M 0x03
#define CSD_3_TMP_WP_S 12 // [12:12]
#define CSD_3_TMP_WP_M 0x01
#define CSD_3_PERM_WP_S 13 // [13:13]
#define CSD_3_PERM_WP_M 0x01
#define CSD_3_COPY_S 14 // [14:14]
#define CSD_3_COPY_M 0x01
#define CSD_3_FILE_FMT_GRP_S 15 // [15:15]
#define CSD_3_FILE_FMT_GRP_M 0x01
// reserved 16 // [20:16]
// reserved 0x1F
#define CSD_3_WBLOCK_P_S 21 // [21:21]
#define CSD_3_WBLOCK_P_M 0x01
#define CSD_3_WBLEN_S 22 // [25:22]
#define CSD_3_WBLEN_M 0x0F
#define CSD_3_R2W_F_S 26 // [28:26]
#define CSD_3_R2W_F_M 0x07
#define CSD_3_MMC_DEF_ECC_S 29 // [30:29] reserved for MMC compatibility
#define CSD_3_MMC_DEF_ECC_M 0x03
#define CSD_3_WP_GRP_EN_S 31 // [31:31]
#define CSD_3_WP_GRP_EN_M 0x01
// Seconde Response INT <=> CSD[2] : bits 32 to 63
#define CSD_2_v21_WP_GRP_SIZE_S 0 // [38:32]
#define CSD_2_v21_WP_GRP_SIZE_M 0x7F
#define CSD_2_v21_SECT_SIZE_S 7 // [45:39]
#define CSD_2_v21_SECT_SIZE_M 0x7F
#define CSD_2_v21_ER_BLEN_EN_S 14 // [46:46]
#define CSD_2_v21_ER_BLEN_EN_M 0x01
#define CSD_2_v22_WP_GRP_SIZE_S 0 // [36:32]
#define CSD_2_v22_WP_GRP_SIZE_M 0x1F
#define CSD_2_v22_ER_GRP_SIZE_S 5 // [41:37]
#define CSD_2_v22_ER_GRP_SIZE_M 0x1F
#define CSD_2_v22_SECT_SIZE_S 10 // [46:42]
#define CSD_2_v22_SECT_SIZE_M 0x1F
#define CSD_2_C_SIZE_M_S 15 // [49:47]
#define CSD_2_C_SIZE_M_M 0x07
#define CSD_2_VDD_WMAX_S 18 // [52:50]
#define CSD_2_VDD_WMAX_M 0x07
#define CSD_2_VDD_WMIN_S 21 // [55:53]
#define CSD_2_VDD_WMIN_M 0x07
#define CSD_2_RCUR_MAX_S 24 // [58:56]
#define CSD_2_RCUR_MAX_M 0x07
#define CSD_2_RCUR_MIN_S 27 // [61:59]
#define CSD_2_RCUR_MIN_M 0x07
#define CSD_2_CSIZE_L_S 30 // [63:62] <=> 2 LSB of CSIZE
#define CSD_2_CSIZE_L_M 0x03
// Third Response INT <=> CSD[1] : bits 64 to 95
#define CSD_1_CSIZE_H_S 0 // [73:64] <=> 10 MSB of CSIZE
#define CSD_1_CSIZE_H_M 0x03FF
// reserved 10 // [75:74]
// reserved 0x03
#define CSD_1_DSR_I_S 12 // [76:76]
#define CSD_1_DSR_I_M 0x01
#define CSD_1_RD_B_MIS_S 13 // [77:77]
#define CSD_1_RD_B_MIS_M 0x01
#define CSD_1_WR_B_MIS_S 14 // [78:78]
#define CSD_1_WR_B_MIS_M 0x01
#define CSD_1_RD_B_PAR_S 15 // [79:79]
#define CSD_1_RD_B_PAR_M 0x01
#define CSD_1_RD_B_LEN_S 16 // [83:80]
#define CSD_1_RD_B_LEN_M 0x0F
#define CSD_1_CCC_S 20 // [95:84]
#define CSD_1_CCC_M 0x0FFF
// Fourth Response INT <=> CSD[0] : bits 96 to 127
#define CSD_0_TRANS_SPEED_S 0 // [103:96]
#define CSD_0_TRANS_SPEED_M 0xFF
#define CSD_0_NSAC_S 8 // [111:104]
#define CSD_0_NSAC_M 0xFF
#define CSD_0_TAAC_S 16 // [119:112]
#define CSD_0_TAAC_M 0xFF
// reserved 24 // [121:120]
// reserved 0x03
#define CSD_0_MMC_SPEC_VERS_S 26 // [125:122] reserved for MMC compatibility
#define CSD_0_MMC_SPEC_VERS_M 0x0F
#define CSD_0_STRUCT_S 30 // [127:126]
#define CSD_0_STRUCT_M 0x03
///////////////////////////////////////////////////////////////////////////////
#endif

View File

@ -1,38 +0,0 @@
/*-
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "lib.h"
int
p_memcmp(const char *to, const char *from, unsigned size)
{
while ((--size) && (*to++ == *from++))
continue;
return (size || (*to != *from));
}

View File

@ -1,39 +0,0 @@
/*-
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "lib.h"
void
memcpy(void *dst, const void *src, unsigned len)
{
const char *s = src;
char *d = dst;
while (len--)
*d++ = *s++;
}

View File

@ -1,36 +0,0 @@
/*-
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "lib.h"
void
p_memset(char *buffer, char value, int size)
{
while (size--)
*buffer++ = value;
}

View File

@ -1,57 +0,0 @@
/******************************************************************************
*
* Filename: p_string.c
*
* Instantiation of basic string operations to prevent inclusion of full
* string library. These are simple implementations not necessarily optimized
* for speed, but rather to show intent.
*
* Revision information:
*
* 20AUG2004 kb_admin initial creation
* 12JAN2005 kb_admin minor updates
*
* BEGIN_KBDD_BLOCK
* No warranty, expressed or implied, is included with this software. It is
* provided "AS IS" and no warranty of any kind including statutory or aspects
* relating to merchantability or fitness for any purpose is provided. All
* intellectual property rights of others is maintained with the respective
* owners. This software is not copyrighted and is intended for reference
* only.
* END_BLOCK
*
* $FreeBSD$
*****************************************************************************/
#include "lib.h"
/*
* .KB_C_FN_DEFINITION_START
* void p_memset(char *buffer, char value, int size)
* This global function sets memory at the pointer for the specified
* number of bytes to value.
* .KB_C_FN_DEFINITION_END
*/
void
p_memset(char *buffer, char value, int size)
{
while (size--)
*buffer++ = value;
}
/*
* .KB_C_FN_DEFINITION_START
* int p_memcmp(char *to, char *from, unsigned size)
* This global function compares data at to against data at from for
* size bytes. Returns 0 if the locations are equal. size must be
* greater than 0.
* .KB_C_FN_DEFINITION_END
*/
int
p_memcmp(const char *to, const char *from, unsigned size)
{
while ((--size) && (*to++ == *from++))
continue;
return (*to != *from);
}

View File

@ -1,70 +0,0 @@
/*-
* Copyright (c) 1998 Robert Nordier
* All rights reserved.
* Copyright (c) 2006 M. Warner Losh
* All rights reserved.
*
* Redistribution and use in source and binary forms are freely
* permitted provided that the above copyright notice and this
* paragraph and the following disclaimer are duplicated in all
* such forms.
*
* This software is provided "AS IS" and without any express or
* implied warranties, including, without limitation, the implied
* warranties of merchantability and fitness for a particular
* purpose.
*
* $FreeBSD$
*/
#include <stdarg.h>
#include "lib.h"
void
printf(const char *fmt,...)
{
va_list ap;
const char *hex = "0123456789abcdef";
char buf[10];
char *s;
unsigned u;
int c;
va_start(ap, fmt);
while ((c = *fmt++)) {
if (c == '%') {
c = *fmt++;
switch (c) {
case 'c':
xputchar(va_arg(ap, int));
continue;
case 's':
for (s = va_arg(ap, char *); *s; s++)
xputchar(*s);
continue;
case 'd': /* A lie, always prints unsigned */
case 'u':
u = va_arg(ap, unsigned);
s = buf;
do
*s++ = '0' + u % 10U;
while (u /= 10U);
dumpbuf:;
while (--s >= buf)
xputchar(*s);
continue;
case 'x':
u = va_arg(ap, unsigned);
s = buf;
do
*s++ = hex[u & 0xfu];
while (u >>= 4);
goto dumpbuf;
}
}
xputchar(c);
}
va_end(ap);
return;
}

View File

@ -1,62 +0,0 @@
/*-
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software is derived from software provided by kwikbyte without
* copyright as follows:
*
* No warranty, expressed or implied, is included with this software. It is
* provided "AS IS" and no warranty of any kind including statutory or aspects
* relating to merchantability or fitness for any purpose is provided. All
* intellectual property rights of others is maintained with the respective
* owners. This software is not copyrighted and is intended for reference
* only.
*
* $FreeBSD$
*/
#include "at91rm9200.h"
#include "at91rm9200_lowlevel.h"
#include "lib.h"
/*
* void putchar(int ch)
* Writes a character to the DBGU port. It assumes that DBGU has
* already been initialized.
*/
void
putchar(int ch)
{
AT91PS_USART pUSART = (AT91PS_USART)AT91C_BASE_DBGU;
while (!(pUSART->US_CSR & AT91C_US_TXRDY))
continue;
pUSART->US_THR = (ch & 0xFF);
}
void
xputchar(int ch)
{
if (ch == '\n')
putchar('\r');
putchar(ch);
}

View File

@ -1,57 +0,0 @@
/*-
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#include "at91rm9200.h"
#include "lib.h"
/*
* void reset()
*
* Forces a reset of the system. Uses watchdog timer of '1', which
* corresponds to 128 / SLCK seconds (SLCK is 32,768 Hz, so 128/32768 is
* 1 / 256 ~= 5.4ms
*/
void
reset(void)
{
// The following should effect a reset.
AT91C_BASE_ST->ST_WDMR = 1 | AT91C_ST_RSTEN;
AT91C_BASE_ST->ST_CR = AT91C_ST_WDRST;
}
/*
* void start_wdog()
*
* Starts a watchdog timer. We force the boot process to get to the point
* it can kick the watch dog part of the ST part for the OS's driver.
*/
void
start_wdog(int n)
{
// The following should effect a reset after N seconds.
AT91C_BASE_ST->ST_WDMR = (n * (32768 / 128)) | AT91C_ST_RSTEN;
AT91C_BASE_ST->ST_CR = AT91C_ST_WDRST;
}

View File

@ -1,517 +0,0 @@
/*-
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software is derived from software provide by Kwikbyte who specifically
* disclaimed copyright on the code.
*
* $FreeBSD$
*/
//*----------------------------------------------------------------------------
//* ATMEL Microcontroller Software Support - ROUSSET -
//*----------------------------------------------------------------------------
//* The software is delivered "AS IS" without warranty or condition of any
//* kind, either express, implied or statutory. This includes without
//* limitation any warranty or condition with respect to merchantability or
//* fitness for any particular purpose, or against the infringements of
//* intellectual property rights of others.
//*----------------------------------------------------------------------------
//* File Name : main.c
//* Object : main application written in C
//* Creation : FB 21/11/2002
//*
//*----------------------------------------------------------------------------
#include "at91rm9200.h"
#include "lib_AT91RM9200.h"
#include "mci_device.h"
#include "lib.h"
#include "sd-card.h"
#define AT91C_MCI_TIMEOUT 1000000 /* For AT91F_MCIDeviceWaitReady */
#define SD_BLOCK_SIZE 512
//* Global Variables
static AT91S_MciDevice MCI_Device;
/******************************************************************************
**Error return codes
******************************************************************************/
#define MCI_UNSUPP_SIZE_ERROR 5
#define MCI_UNSUPP_OFFSET_ERROR 6
//*----------------------------------------------------------------------------
//* \fn MCIDeviceWaitReady
//* \brief Wait for MCI Device ready
//*----------------------------------------------------------------------------
static unsigned int
MCIDeviceWaitReady(unsigned int timeout)
{
volatile unsigned int status;
int waitfor;
if (MCI_Device.state == AT91C_MCI_RX_SINGLE_BLOCK)
waitfor = AT91C_MCI_RXBUFF;
else
waitfor = AT91C_MCI_NOTBUSY;
do
{
status = AT91C_BASE_MCI->MCI_SR;
timeout--;
}
while( !(status & waitfor) && (timeout>0) );
status = AT91C_BASE_MCI->MCI_SR;
// If End of Tx Buffer Empty interrupt occurred
if (MCI_Device.state == AT91C_MCI_TX_SINGLE_BLOCK && status & AT91C_MCI_TXBUFE) {
AT91C_BASE_MCI->MCI_IDR = AT91C_MCI_TXBUFE;
AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_TXTDIS;
MCI_Device.state = AT91C_MCI_IDLE;
} // End of if AT91C_MCI_TXBUFF
// If End of Rx Buffer Full interrupt occurred
if (MCI_Device.state == AT91C_MCI_RX_SINGLE_BLOCK && status & AT91C_MCI_RXBUFF) {
AT91C_BASE_MCI->MCI_IDR = AT91C_MCI_RXBUFF;
AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_RXTDIS;
MCI_Device.state = AT91C_MCI_IDLE;
} // End of if AT91C_MCI_RXBUFF
//printf("WaitReady returning status %x\n", status);
return status;
}
static inline unsigned int
swap(unsigned int v)
{
unsigned int t1;
__asm __volatile("eor %1, %0, %0, ror #16\n"
"bic %1, %1, #0x00ff0000\n"
"mov %0, %0, ror #8\n"
"eor %0, %0, %1, lsr #8\n"
: "+r" (v), "=r" (t1));
return (v);
}
inline static unsigned int
wait_ready()
{
int status;
int timeout = AT91C_MCI_TIMEOUT;
// wait for CMDRDY Status flag to read the response
do
{
status = AT91C_BASE_MCI->MCI_SR;
} while( !(status & AT91C_MCI_CMDRDY) && (--timeout > 0) );
return status;
}
//*----------------------------------------------------------------------------
//* \fn MCI_SendCommand
//* \brief Generic function to send a command to the MMC or SDCard
//*----------------------------------------------------------------------------
static int
MCI_SendCommand(
unsigned int Cmd,
unsigned int Arg)
{
unsigned int error;
unsigned int errorMask = AT91C_MCI_SR_ERROR;
unsigned int opcode = Cmd & 0x3F;
//printf("SendCmd %d (%x) arg %x\n", opcode, Cmd, Arg);
// Don't check response CRC on ACMD41 (R3 response type).
if (opcode == 41)
errorMask &= ~AT91C_MCI_RCRCE;
AT91C_BASE_MCI->MCI_ARGR = Arg;
AT91C_BASE_MCI->MCI_CMDR = Cmd;
error = wait_ready();
if ((error & errorMask) != 0) {
return (1);
}
return 0;
}
//*----------------------------------------------------------------------------
//* \fn MCI_GetStatus
//* \brief Addressed card sends its status register
//*----------------------------------------------------------------------------
static unsigned int
MCI_GetStatus()
{
if (MCI_SendCommand(SEND_STATUS_CMD, MCI_Device.RCA << 16))
return 0;
return (AT91C_BASE_MCI->MCI_RSPR[0]);
}
//*----------------------------------------------------------------------------
//* \fn MCI_ReadBlock
//* \brief Start the read for a single 512-byte block
//*----------------------------------------------------------------------------
static int
MCI_StartReadBlock(unsigned blknum, void *dataBuffer)
{
// Init Mode Register
AT91C_BASE_MCI->MCI_MR |= ((SD_BLOCK_SIZE << 16) | AT91C_MCI_PDCMODE);
// (PDC) Receiver Transfer Enable
AT91C_BASE_PDC_MCI->PDC_PTCR = (AT91C_PDC_TXTDIS | AT91C_PDC_RXTDIS);
AT91C_BASE_PDC_MCI->PDC_RPR = (unsigned int)dataBuffer;
AT91C_BASE_PDC_MCI->PDC_RCR = SD_BLOCK_SIZE / 4;
AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_RXTEN;
// SDHC wants block offset, non-HC wants byte offset.
if (!MCI_Device.IsSDHC)
blknum *= SD_BLOCK_SIZE;
// Send the Read single block command
if (MCI_SendCommand(READ_SINGLE_BLOCK_CMD, blknum)) {
return AT91C_READ_ERROR;
}
MCI_Device.state = AT91C_MCI_RX_SINGLE_BLOCK;
return 0;
}
//*----------------------------------------------------------------------------
//* \fn MCI_readblocks
//* \brief Read one or more blocks
//*----------------------------------------------------------------------------
int
MCI_readblocks(char* dest, unsigned blknum, unsigned blkcount)
{
unsigned int status;
unsigned int *walker;
if (MCI_Device.state != AT91C_MCI_IDLE) {
return 1;
}
if ((MCI_GetStatus() & AT91C_SR_READY_FOR_DATA) == 0) {
return 1;
}
// As long as there is data to read
while (blkcount)
{
//Do the reading
if (MCI_StartReadBlock(blknum, dest))
return -1;
// Wait MCI Device Ready
status = MCIDeviceWaitReady(AT91C_MCI_TIMEOUT);
if (status & AT91C_MCI_SR_ERROR)
return 1;
// Fix erratum in MCI part - endian-swap all data.
for (walker = (unsigned int *)dest;
walker < (unsigned int *)(dest + SD_BLOCK_SIZE); walker++)
*walker = swap(*walker);
// Update counters & pointers
++blknum;
--blkcount;
dest += SD_BLOCK_SIZE;
}
return 0;
}
//*----------------------------------------------------------------------------
//* \fn MCI_read
//* \brief Legacy read function, takes byte offset and length but was always
//* used to read full blocks; interface preserved for existing boot code.
//*----------------------------------------------------------------------------
int
MCI_read(char* dest, unsigned byteoffset, unsigned length)
{
return MCI_readblocks(dest,
byteoffset/SD_BLOCK_SIZE, length/SD_BLOCK_SIZE);
}
//*----------------------------------------------------------------------------
//* \fn MCI_SDCard_SendAppCommand
//* \brief Specific function to send a specific command to the SDCard
//*----------------------------------------------------------------------------
static int
MCI_SDCard_SendAppCommand(
unsigned int Cmd_App,
unsigned int Arg)
{
int status;
if ((status = MCI_SendCommand(APP_CMD, (MCI_Device.RCA << 16))) == 0)
status = MCI_SendCommand(Cmd_App,Arg);
return status;
}
//*----------------------------------------------------------------------------
//* \fn MCI_GetCSD
//* \brief Asks to the specified card to send its CSD
//*----------------------------------------------------------------------------
static int
MCI_GetCSD(unsigned int rca, unsigned int *response)
{
if (MCI_SendCommand(SEND_CSD_CMD, (rca << 16)))
return 1;
response[0] = AT91C_BASE_MCI->MCI_RSPR[0];
response[1] = AT91C_BASE_MCI->MCI_RSPR[1];
response[2] = AT91C_BASE_MCI->MCI_RSPR[2];
response[3] = AT91C_BASE_MCI->MCI_RSPR[3];
return 0;
}
//*----------------------------------------------------------------------------
//* \fn MCI_SDCard_GetOCR
//* \brief Wait for card to power up and determine whether it's SDHC or not.
//*----------------------------------------------------------------------------
static int
MCI_SDCard_GetOCR()
{
unsigned int response;
unsigned int arg = AT91C_MMC_HOST_VOLTAGE_RANGE;
int timeout = AT91C_MCI_TIMEOUT;
// Force card to idle state.
MCI_SendCommand(GO_IDLE_STATE_CMD, AT91C_NO_ARGUMENT);
// Begin probe for SDHC by sending CMD8; only v2.0 cards respond to it.
//
// Arg is vvpp where vv is voltage range and pp is an arbitrary bit
// pattern that gets echoed back in the response. The only voltage
// ranges defined are:
// 0x01 = 2.7 - 3.6
// 0x02 = "reserved for low voltage" whatever that means.
//
// If the card fails to respond then it's not v2.0. If it responds by
// echoing back exactly the arg we sent, then it's a v2.0 card and can
// run at our voltage. That means that when we send the ACMD41 (in
// MCI_SDCard_GetOCR) we can include the HCS bit to inquire about SDHC.
if (MCI_SendCommand(SD_SEND_IF_COND_CMD, 0x01AA) == 0) {
MCI_Device.IsSDv2 = (AT91C_BASE_MCI->MCI_RSPR[0] == 0x01AA);
}
// If we've determined the card supports v2.0 functionality, set the
// HCS/CCS bit to indicate that we support SDHC. This will cause a
// v2.0 card to report whether it is SDHC in the ACMD41 response.
if (MCI_Device.IsSDv2) {
arg |= AT91C_CCS;
}
// The RCA to be used for CMD55 in Idle state shall be the card's
// default RCA=0x0000.
MCI_Device.RCA = 0x0;
// Repeat ACMD41 until the card comes out of power-up-busy state.
do {
if (MCI_SDCard_SendAppCommand(SDCARD_APP_OP_COND_CMD, arg)) {
return 1;
}
response = AT91C_BASE_MCI->MCI_RSPR[0];
} while (!(response & AT91C_CARD_POWER_UP_DONE) && (--timeout > 0));
// A v2.0 card sets CCS (card capacity status) in the response if it's SDHC.
if (MCI_Device.IsSDv2) {
MCI_Device.IsSDHC = ((response & AT91C_CCS) == AT91C_CCS);
}
return (0);
}
//*----------------------------------------------------------------------------
//* \fn MCI_SDCard_GetCID
//* \brief Asks to the SDCard on the chosen slot to send its CID
//*----------------------------------------------------------------------------
static int
MCI_SDCard_GetCID(unsigned int *response)
{
if (MCI_SendCommand(ALL_SEND_CID_CMD, AT91C_NO_ARGUMENT))
return 1;
response[0] = AT91C_BASE_MCI->MCI_RSPR[0];
response[1] = AT91C_BASE_MCI->MCI_RSPR[1];
response[2] = AT91C_BASE_MCI->MCI_RSPR[2];
response[3] = AT91C_BASE_MCI->MCI_RSPR[3];
return 0;
}
//*----------------------------------------------------------------------------
//* \fn sdcard_4wire
//* \brief Set bus width to 1-bit or 4-bit according to the parm.
//*
//* Unlike most functions in this file, the return value from this one is
//* bool-ish; returns 0 on failure, 1 on success.
//*----------------------------------------------------------------------------
int
sdcard_use4wire(int use4wire)
{
volatile int ret_value;
do {
ret_value=MCI_GetStatus();
}
while((ret_value > 0) && ((ret_value & AT91C_SR_READY_FOR_DATA) == 0));
// If going to 4-wire mode, ask the card to turn off the DAT3 card detect
// pullup resistor, if going to 1-wire ask it to turn it back on.
ret_value = MCI_SDCard_SendAppCommand(SDCARD_SET_CLR_CARD_DETECT_CMD,
use4wire ? 0 : 1);
if (ret_value != AT91C_CMD_SEND_OK)
return 0;
// Ask the card to go into the requested mode.
ret_value = MCI_SDCard_SendAppCommand(SDCARD_SET_BUS_WIDTH_CMD,
use4wire ? AT91C_BUS_WIDTH_4BITS :
AT91C_BUS_WIDTH_1BIT);
if (ret_value != AT91C_CMD_SEND_OK)
return 0;
// Set the MCI device to match the mode we set in the card.
if (use4wire) {
MCI_Device.SDCard_bus_width = AT91C_BUS_WIDTH_4BITS;
AT91C_BASE_MCI->MCI_SDCR |= AT91C_MCI_SCDBUS;
} else {
MCI_Device.SDCard_bus_width = AT91C_BUS_WIDTH_1BIT;
AT91C_BASE_MCI->MCI_SDCR &= ~AT91C_MCI_SCDBUS;
}
return 1;
}
//*----------------------------------------------------------------------------
//* \fn sdcard_init
//* \brief get the mci device ready to read from an SD or SDHC card.
//*
//* Unlike most functions in this file, the return value from this one is
//* bool-ish; returns 0 on failure, 1 on success.
//*----------------------------------------------------------------------------
int
sdcard_init(void)
{
unsigned int tab_response[4];
int i;
// Init MCI for MMC and SDCard interface
AT91F_MCI_CfgPIO();
AT91F_MCI_CfgPMC();
AT91F_PDC_Open(AT91C_BASE_PDC_MCI);
// Init Device Structure
MCI_Device.state = AT91C_MCI_IDLE;
MCI_Device.SDCard_bus_width = 0;
MCI_Device.IsSDv2 = 0;
MCI_Device.IsSDHC = 0;
// Reset the MCI and set the bus speed.
// Using MCK/230 gives a legal (under 400khz) bus speed for the card id
// sequence for all reasonable master clock speeds.
AT91C_BASE_MCI->MCI_CR = AT91C_MCI_MCIDIS | 0x80;
AT91C_BASE_MCI->MCI_IDR = 0xFFFFFFFF;
AT91C_BASE_MCI->MCI_DTOR = AT91C_MCI_DTOR_1MEGA_CYCLES;
AT91C_BASE_MCI->MCI_MR = AT91C_MCI_PDCMODE | 114; /* clkdiv 114 = MCK/230 */
AT91C_BASE_MCI->MCI_SDCR = AT91C_MCI_MMC_SLOTA;
AT91C_BASE_MCI->MCI_CR = AT91C_MCI_MCIEN|AT91C_MCI_PWSEN;
// Wait for the card to come out of power-up-busy state by repeatedly
// sending ACMD41. This also probes for SDHC versus standard cards.
for (i = 0; i < 100; i++) {
if (MCI_SDCard_GetOCR() == 0)
break;
if ((i & 0x01) == 0) {
printf(".");
}
}
if (i >= 100)
return 0;
if (MCI_SDCard_GetCID(tab_response))
return 0;
// Tell the card to set its address, and remember the result.
if (MCI_SendCommand(SET_RELATIVE_ADDR_CMD, 0))
return 0;
MCI_Device.RCA = (AT91C_BASE_MCI->MCI_RSPR[0] >> 16);
// After sending CMD3 (set addr) we can increase the clock to full speed.
// Using MCK/4 gives a legal (under 25mhz) bus speed for all reasonable
// master clock speeds.
AT91C_BASE_MCI->MCI_MR = AT91C_MCI_PDCMODE | 1; /* clkdiv 1 = MCK/4 */
if (MCI_GetCSD(MCI_Device.RCA,tab_response))
return 0;
MCI_Device.READ_BL_LEN = (tab_response[1] >> CSD_1_RD_B_LEN_S) &
CSD_1_RD_B_LEN_M;
#ifdef REPORT_SIZE
{
unsigned int mult,blocknr;
// compute MULT
mult = 1 << ( ((tab_response[2] >> CSD_2_C_SIZE_M_S) &
CSD_2_C_SIZE_M_M) + 2 );
// compute MSB of C_SIZE
blocknr = ((tab_response[1] >> CSD_1_CSIZE_H_S) &
CSD_1_CSIZE_H_M) << 2;
// compute MULT * (LSB of C-SIZE + MSB already computed + 1) = BLOCKNR
blocknr = mult * ((blocknr + ((tab_response[2] >> CSD_2_CSIZE_L_S) &
CSD_2_CSIZE_L_M)) + 1);
MCI_Device.Memory_Capacity = (1 << MCI_Device.READ_BL_LEN) * blocknr;
printf("Found SD card %u bytes\n", MCI_Device.Memory_Capacity);
}
#endif
// Select card and set block length for following transfers.
if (MCI_SendCommand(SEL_DESEL_CARD_CMD, (MCI_Device.RCA)<<16))
return 0;
if (MCI_SendCommand(SET_BLOCKLEN_CMD, SD_BLOCK_SIZE))
return 0;
return 1;
}

View File

@ -1,64 +0,0 @@
/*-
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software is derived from software provide by Kwikbyte who specifically
* disclaimed copyright on the code.
*
* $FreeBSD$
*/
#ifndef __SD_CARD_H
#define __SD_CARD_H
/* MCI_read() is the original read function, taking a byte offset and byte
* count. It is preserved to support existing customized boot code that still
* refers to it; it will work fine even on SDHC cards as long as the kernel and
* the metadata for locating it all exist within the first 4GB of the card.
*
* MCI_readblocks() is the new read function, taking offset and length in terms
* of block counts (where the SD spec defines a block as 512 bytes), allowing
* the kernel and filesystem metadata to be located anywhere on an SDHC card.
*
* Returns 0 on success, non-zero on failure.
*/
int MCI_read (char* dest, unsigned bytenum, unsigned length);
int MCI_readblocks (char* dest, unsigned blknum, unsigned blkcount);
/* sdcard_init() - get things set up to read from an SD or SDHC card.
*
* Returns 0 on failure, non-zero on success.
*/
int sdcard_init(void);
/* By default sdcard_init() sets things up for a 1-wire interface to the
* SD card. Calling sdcard_4wire(true) after sdcard_init() allows customized
* boot code to change to 4-bit transfers when the hardware supports it.
*
* Returns 0 on failure, non-zero on success.
*/
int sdcard_use4wire(int use4wire);
#endif

View File

@ -1,267 +0,0 @@
/******************************************************************************
*
* Filename: spi_flash.c
*
* Instantiation of SPI flash control routines supporting AT45DB161B
*
* Revision information:
*
* 17JAN2005 kb_admin initial creation
* adapted from external sources
* tested for basic operation only!!!
*
* BEGIN_KBDD_BLOCK
* No warranty, expressed or implied, is included with this software. It is
* provided "AS IS" and no warranty of any kind including statutory or aspects
* relating to merchantability or fitness for any purpose is provided. All
* intellectual property rights of others is maintained with the respective
* owners. This software is not copyrighted and is intended for reference
* only.
* END_BLOCK
*
* $FreeBSD$
*****************************************************************************/
#include "at91rm9200.h"
#include "spi_flash.h"
#include "lib.h"
/*********************** PRIVATE FUNCTIONS/DATA ******************************/
static spiCommand_t spi_command;
static char tx_commandBuffer[8], rx_commandBuffer[8];
/*
* .KB_C_FN_DEFINITION_START
* void SendCommand(spiCommand_t *pCommand)
* Private function sends 8-bit value to the device and returns the 8-bit
* value in response.
* .KB_C_FN_DEFINITION_END
*/
static void
SendCommand(spiCommand_t *pCommand)
{
AT91PS_SPI pSPI = AT91C_BASE_SPI;
pSPI->SPI_PTCR = AT91C_PDC_TXTDIS | AT91C_PDC_RXTDIS;
pSPI->SPI_RPR = (unsigned)pCommand->rx_cmd;
pSPI->SPI_RCR = pCommand->rx_cmd_size;
pSPI->SPI_TPR = (unsigned)pCommand->tx_cmd;
pSPI->SPI_TCR = pCommand->tx_cmd_size;
pSPI->SPI_TNPR = (unsigned)pCommand->tx_data;
pSPI->SPI_TNCR = pCommand->tx_data_size;
pSPI->SPI_RNPR = (unsigned)pCommand->rx_data;
pSPI->SPI_RNCR = pCommand->rx_data_size;
pSPI->SPI_PTCR = AT91C_PDC_TXTEN | AT91C_PDC_RXTEN;
// wait for completion
while (!(pSPI->SPI_SR & AT91C_SPI_SPENDRX))
Delay(700);
}
/*
* .KB_C_FN_DEFINITION_START
* char GetFlashStatus(void)
* Private function to return device status.
* .KB_C_FN_DEFINITION_END
*/
static char
GetFlashStatus(void)
{
p_memset((char *)&spi_command, 0, sizeof(spi_command));
p_memset(tx_commandBuffer, 0, 8);
tx_commandBuffer[0] = STATUS_REGISTER_READ;
p_memset(rx_commandBuffer, 0, 8);
spi_command.tx_cmd = tx_commandBuffer;
spi_command.rx_cmd = rx_commandBuffer;
spi_command.rx_cmd_size = 2;
spi_command.tx_cmd_size = 2;
SendCommand(&spi_command);
return (rx_commandBuffer[1]);
}
/*
* .KB_C_FN_DEFINITION_START
* void WaitForDeviceReady(void)
* Private function to poll until the device is ready for next operation.
* .KB_C_FN_DEFINITION_END
*/
static void
WaitForDeviceReady(void)
{
while (!(GetFlashStatus() & 0x80)) ;
}
/*************************** GLOBAL FUNCTIONS ********************************/
/*
* .KB_C_FN_DEFINITION_START
* void SPI_ReadFlash(unsigned flash_addr, unsigned dest_addr, unsigned size)
* Global function to read the SPI flash device using the continuous read
* array command.
* .KB_C_FN_DEFINITION_END
*/
void
SPI_ReadFlash(unsigned flash_addr, char *dest_addr, unsigned size)
{
unsigned pageAddress, byteAddress;
// determine page address
pageAddress = flash_addr / FLASH_PAGE_SIZE;
// determine byte address
byteAddress = flash_addr % FLASH_PAGE_SIZE;
p_memset(tx_commandBuffer, 0, 8);
#ifdef BOOT_BWCT
tx_commandBuffer[0] = 0xd2;
tx_commandBuffer[1] = ((pageAddress >> 6) & 0xFF);
tx_commandBuffer[2] = ((pageAddress << 2) & 0xFC) |
((byteAddress >> 8) & 0x3);
tx_commandBuffer[3] = byteAddress & 0xFF;
spi_command.tx_cmd = tx_commandBuffer;
spi_command.tx_cmd_size = 8;
spi_command.tx_data_size = size;
spi_command.tx_data = dest_addr;
p_memset(rx_commandBuffer, 0, 8);
spi_command.rx_cmd = rx_commandBuffer;
spi_command.rx_cmd_size = 8;
spi_command.rx_data_size = size;
spi_command.rx_data = dest_addr;
#else
tx_commandBuffer[0] = CONTINUOUS_ARRAY_READ_HF;
tx_commandBuffer[1] = ((pageAddress >> 5) & 0xFF);
tx_commandBuffer[2] = ((pageAddress << 3) & 0xF8) |
((byteAddress >> 8) & 0x7);
tx_commandBuffer[3] = byteAddress & 0xFF;
spi_command.tx_cmd = tx_commandBuffer;
spi_command.tx_cmd_size = 5;
spi_command.tx_data_size = size;
spi_command.tx_data = dest_addr;
p_memset(rx_commandBuffer, 0, 8);
spi_command.rx_cmd = rx_commandBuffer;
spi_command.rx_cmd_size = 5;
spi_command.rx_data_size = size;
spi_command.rx_data = dest_addr;
#endif
SendCommand(&spi_command);
}
/*
* .KB_C_FN_DEFINITION_START
* void SPI_WriteFlash(unsigned flash_addr, unsigned src_addr, unsigned size)
* Global function to program the SPI flash device. Notice the warning
* provided in lower-level functions regarding corruption of data in non-
* page aligned write operations.
* .KB_C_FN_DEFINITION_END
*/
void
SPI_WriteFlash(unsigned flash_addr, char *src_addr, unsigned size)
{
unsigned pageAddress, byteAddress;
// determine page address
pageAddress = flash_addr / FLASH_PAGE_SIZE;
// determine byte address
byteAddress = flash_addr % FLASH_PAGE_SIZE;
p_memset(tx_commandBuffer, 0, 8);
#ifdef BOOT_BWCT
tx_commandBuffer[0] = 0x82;
tx_commandBuffer[1] = ((pageAddress >> 6) & 0xFF);
tx_commandBuffer[2] = ((pageAddress << 2) & 0xFC) |
((byteAddress >> 8) & 0x3);
tx_commandBuffer[3] = (byteAddress & 0xFF);
#else
tx_commandBuffer[0] = PROGRAM_THROUGH_BUFFER;
tx_commandBuffer[1] = ((pageAddress >> 5) & 0xFF);
tx_commandBuffer[2] = ((pageAddress << 3) & 0xF8) |
((byteAddress >> 8) & 0x7);
tx_commandBuffer[3] = (byteAddress & 0xFF);
#endif
p_memset(rx_commandBuffer, 0, 8);
spi_command.tx_cmd = tx_commandBuffer;
spi_command.rx_cmd = rx_commandBuffer;
spi_command.rx_cmd_size = 4;
spi_command.tx_cmd_size = 4;
spi_command.tx_data_size = size;
spi_command.tx_data = src_addr;
spi_command.rx_data_size = size;
spi_command.rx_data = src_addr;
SendCommand(&spi_command);
WaitForDeviceReady();
}
/*
* .KB_C_FN_DEFINITION_START
* void SPI_InitFlash(void)
* Global function to initialize the SPI flash device/accessor functions.
* .KB_C_FN_DEFINITION_END
*/
void
SPI_InitFlash(void)
{
AT91PS_PIO pPio;
AT91PS_SPI pSPI = AT91C_BASE_SPI;
unsigned value;
// enable CS0, CLK, MOSI, MISO
pPio = (AT91PS_PIO)AT91C_BASE_PIOA;
pPio->PIO_ASR = AT91C_PIO_PA3 | AT91C_PIO_PA1 | AT91C_PIO_PA0 |
AT91C_PIO_PA2;
pPio->PIO_PDR = AT91C_PIO_PA3 | AT91C_PIO_PA1 | AT91C_PIO_PA0 |
AT91C_PIO_PA2;
// enable clocks to SPI
AT91C_BASE_PMC->PMC_PCER = 1u << AT91C_ID_SPI;
// reset the SPI
pSPI->SPI_CR = AT91C_SPI_SWRST;
pSPI->SPI_MR = (0xf << 24) | AT91C_SPI_MSTR | AT91C_SPI_MODFDIS |
(0xE << 16);
pSPI->SPI_CSR[0] = AT91C_SPI_CPOL | (4 << 16) | (2 << 8);
pSPI->SPI_CR = AT91C_SPI_SPIEN;
pSPI->SPI_PTCR = AT91C_PDC_TXTDIS;
pSPI->SPI_PTCR = AT91C_PDC_RXTDIS;
pSPI->SPI_RNPR = 0;
pSPI->SPI_RNCR = 0;
pSPI->SPI_TNPR = 0;
pSPI->SPI_TNCR = 0;
pSPI->SPI_RPR = 0;
pSPI->SPI_RCR = 0;
pSPI->SPI_TPR = 0;
pSPI->SPI_TCR = 0;
pSPI->SPI_PTCR = AT91C_PDC_RXTEN;
pSPI->SPI_PTCR = AT91C_PDC_TXTEN;
value = pSPI->SPI_RDR;
value = pSPI->SPI_SR;
value = GetFlashStatus() & 0xFC;
#ifdef BOOT_BWCT
if (value != 0xB4 && value != 0xAC)
printf(" Bad SPI status: 0x%x\n", value);
#else
if (value != 0xBC)
printf(" Bad SPI status: 0x%x\n", value);
#endif
}

View File

@ -1,58 +0,0 @@
/*******************************************************************************
*
* Filename: spi_flash.h
*
* Definition of flash control routines supporting AT45DB161B
*
* Revision information:
*
* 17JAN2005 kb_admin initial creation
*
* BEGIN_KBDD_BLOCK
* No warranty, expressed or implied, is included with this software. It is
* provided "AS IS" and no warranty of any kind including statutory or aspects
* relating to merchantability or fitness for any purpose is provided. All
* intellectual property rights of others is maintained with the respective
* owners. This software is not copyrighted and is intended for reference
* only.
* END_BLOCK
*
* $FreeBSD$
******************************************************************************/
#ifndef _SPI_FLASH_H_
#define _SPI_FLASH_H_
typedef struct {
char *tx_cmd;
unsigned tx_cmd_size;
char *rx_cmd;
unsigned rx_cmd_size;
char *tx_data;
unsigned tx_data_size;
char *rx_data;
unsigned rx_data_size;
} spiCommand_t;
void SPI_ReadFlash(unsigned flash_addr, char *dest_addr, unsigned size);
void SPI_WriteFlash(unsigned flash_addr, char *dest_addr, unsigned size);
void SPI_InitFlash(void);
void SPI_GetId(unsigned *id);
#ifdef BOOT_BWCT
#define FLASH_PAGE_SIZE 528
#else
#define FLASH_PAGE_SIZE 1056
#endif
// Flash commands
#define CONTINUOUS_ARRAY_READ 0xE8
#define CONTINUOUS_ARRAY_READ_HF 0x0B
#define CONTINUOUS_ARRAY_READ_LF 0x03
#define STATUS_REGISTER_READ 0xD7
#define PROGRAM_THROUGH_BUFFER 0x82
#define MANUFACTURER_ID 0x9F
#endif

View File

@ -1,36 +0,0 @@
/*-
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "lib.h"
int
strcmp(const char *s1, const char *s2)
{
for (; *s1 == *s2 && *s1; s1++, s2++);
return (unsigned char)*s1 - (unsigned char)*s2;
}

View File

@ -1,38 +0,0 @@
/*-
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "lib.h"
char *
strcpy(char *to, const char *from)
{
while (*from)
*to++ = *from++;
*to++ = '\0';
return (to);
}

View File

@ -1,132 +0,0 @@
/*-
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/******************************************************************************
*
* Filename: p_string.c
*
* Instantiation of basic string operations to prevent inclusion of full
* string library. These are simple implementations not necessarily optimized
* for speed, but rather to show intent.
*
* Revision information:
*
* 20AUG2004 kb_admin initial creation
* 12JAN2005 kb_admin minor updates
*
* BEGIN_KBDD_BLOCK
* No warranty, expressed or implied, is included with this software. It is
* provided "AS IS" and no warranty of any kind including statutory or aspects
* relating to merchantability or fitness for any purpose is provided. All
* intellectual property rights of others is maintained with the respective
* owners. This software is not copyrighted and is intended for reference
* only.
* END_BLOCK
*****************************************************************************/
#include "lib.h"
/*
* .KB_C_FN_DEFINITION_START
* int p_IsWhiteSpace(char)
* This global function returns true if the character is not considered
* a non-space character.
* .KB_C_FN_DEFINITION_END
*/
int
p_IsWhiteSpace(char cValue)
{
return ((cValue == ' ') ||
(cValue == '\t') ||
(cValue == 0) ||
(cValue == '\r') ||
(cValue == '\n'));
}
/*
* .KB_C_FN_DEFINITION_START
* unsigned p_HexCharValue(char)
* This global function returns the decimal value of the validated hex char.
* .KB_C_FN_DEFINITION_END
*/
unsigned
p_HexCharValue(char cValue)
{
if (cValue < ('9' + 1))
return (cValue - '0');
if (cValue < ('F' + 1))
return (cValue - 'A' + 10);
return (cValue - 'a' + 10);
}
/*
* .KB_C_FN_DEFINITION_START
* unsigned p_ASCIIToHex(char *)
* This global function set the unsigned value equal to the converted
* hex number passed as a string. No error checking is performed; the
* string must be valid hex value, point at the start of string, and be
* NULL-terminated.
* .KB_C_FN_DEFINITION_END
*/
unsigned
p_ASCIIToHex(const char *buf)
{
unsigned lValue = 0;
if ((*buf == '0') && ((buf[1] == 'x') || (buf[1] == 'X')))
buf += 2;
while (*buf) {
lValue <<= 4;
lValue += p_HexCharValue(*buf++);
}
return (lValue);
}
/*
* .KB_C_FN_DEFINITION_START
* unsigned p_ASCIIToDec(char *)
* This global function set the unsigned value equal to the converted
* decimal number passed as a string. No error checking is performed; the
* string must be valid decimal value, point at the start of string, and be
* NULL-terminated.
* .KB_C_FN_DEFINITION_END
*/
unsigned
p_ASCIIToDec(const char *buf)
{
unsigned v = 0;
while (*buf) {
v *= 10;
v += (*buf++) - '0';
}
return (v);
}

View File

@ -1,68 +0,0 @@
/*-
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/******************************************************************************
*
* Filename: p_string.c
*
* Instantiation of basic string operations to prevent inclusion of full
* string library. These are simple implementations not necessarily optimized
* for speed, but rather to show intent.
*
* Revision information:
*
* 20AUG2004 kb_admin initial creation
* 12JAN2005 kb_admin minor updates
*
* BEGIN_KBDD_BLOCK
* No warranty, expressed or implied, is included with this software. It is
* provided "AS IS" and no warranty of any kind including statutory or aspects
* relating to merchantability or fitness for any purpose is provided. All
* intellectual property rights of others is maintained with the respective
* owners. This software is not copyrighted and is intended for reference
* only.
* END_BLOCK
*****************************************************************************/
#include "lib.h"
/*
* .KB_C_FN_DEFINITION_START
* int p_strlen(char *)
* This global function returns the number of bytes starting at the pointer
* before (not including) the string termination character ('/0').
* .KB_C_FN_DEFINITION_END
*/
int
p_strlen(const char *buffer)
{
const char *ptr = buffer;
while (*ptr++)
continue;
return (ptr - buffer - 1);
}

View File

@ -1,81 +0,0 @@
/******************************************************************************
*
* Filename: tag_list.c
*
* Instantiation of basic routines that create linux-boot tag list.
*
* Revision information:
*
* 22AUG2004 kb_admin initial creation
*
* BEGIN_KBDD_BLOCK
* No warranty, expressed or implied, is included with this software. It is
* provided "AS IS" and no warranty of any kind including statutory or aspects
* relating to merchantability or fitness for any purpose is provided. All
* intellectual property rights of others is maintained with the respective
* owners. This software is not copyrighted and is intended for reference
* only.
* END_BLOCK
*
* $FreeBSD$
*****************************************************************************/
/******************************* GLOBALS *************************************/
/********************** PRIVATE FUNCTIONS/DATA/DEFINES ***********************/
#define u32 unsigned
#define u16 unsigned short
#define u8 unsigned char
// #include "/usr/src/arm/linux/include/asm/setup.h"
#include <linux/asm/setup.h>
#include "tag_list.h"
#define PAGE_SIZE 0x1000
#define MEM_SIZE 0x2000000
#define PHYS_OFFSET 0x20000000
/*************************** GLOBAL FUNCTIONS ********************************/
/*
* .KB_C_FN_DEFINITION_START
* void InitTagList(char*, void *)
* This global function populates a linux-boot style tag list from the
* string passed in the pointer at the location specified.
* .KB_C_FN_DEFINITION_END
*/
void InitTagList(char *parms, void *output) {
char *src, *dst;
struct tag *tagList = (struct tag*)output;
tagList->hdr.size = tag_size(tag_core);
tagList->hdr.tag = ATAG_CORE;
tagList->u.core.flags = 1;
tagList->u.core.pagesize = PAGE_SIZE;
tagList->u.core.rootdev = 0xff;
tagList = tag_next(tagList);
tagList->hdr.size = tag_size(tag_mem32);
tagList->hdr.tag = ATAG_MEM;
tagList->u.mem.size = MEM_SIZE;
tagList->u.mem.start = PHYS_OFFSET;
tagList = tag_next(tagList);
tagList->hdr.size = tag_size(tag_cmdline);
tagList->hdr.tag = ATAG_CMDLINE;
src = parms;
dst = tagList->u.cmdline.cmdline;
while (*src) {
*dst++ = *src++;
}
*dst = 0;
tagList->hdr.size += ((unsigned)(src - parms) + 1) / sizeof(unsigned);
tagList = tag_next(tagList);
tagList->hdr.size = 0;
tagList->hdr.tag = ATAG_NONE;
}

View File

@ -1,28 +0,0 @@
/*****************************************************************************
*
* Filename: tag_list.h
*
* Definition of basic routines that create linux-boot tag list.
*
* Revision information:
*
* 22AUG2004 kb_admin initial creation
*
* BEGIN_KBDD_BLOCK
* No warranty, expressed or implied, is included with this software. It is
* provided "AS IS" and no warranty of any kind including statutory or aspects
* relating to merchantability or fitness for any purpose is provided. All
* intellectual property rights of others is maintained with the respective
* owners. This software is not copyrighted and is intended for reference
* only.
* END_BLOCK
*
* $FreeBSD$
****************************************************************************/
#ifndef _TAG_LIST_H_
#define _TAG_LIST_H_
extern void InitTagList(char *parms, void*);
#endif /* _TAG_LIST_H_ */

View File

@ -1,128 +0,0 @@
/*-
* Copyright (c) 2006 M. Warner Losh. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software is derived from software provide by Kwikbyte who specifically
* disclaimed copyright on the code. This version of xmodem has been nearly
* completely rewritten, but the CRC is from the original.
*
* $FreeBSD$
*/
#include "lib.h"
#define PACKET_SIZE 128
/* Line control codes */
#define SOH 0x01 /* start of header */
#define ACK 0x06 /* Acknowledge */
#define NAK 0x15 /* Negative acknowledge */
#define CAN 0x18 /* Cancel */
#define EOT 0x04 /* end of text */
#define TO 10
/*
* int GetRecord(char , char *)
* This private function receives a x-modem record to the pointer and
* returns non-zero on success.
*/
static int
GetRecord(char blocknum, char *dest)
{
int size;
int ch;
unsigned chk, j;
chk = 0;
if ((ch = getc(TO)) == -1)
goto err;
if (ch != blocknum)
goto err;
if ((ch = getc(TO)) == -1)
goto err;
if (ch != (~blocknum & 0xff))
goto err;
for (size = 0; size < PACKET_SIZE; ++size) {
if ((ch = getc(TO)) == -1)
goto err;
chk = chk ^ ch << 8;
for (j = 0; j < 8; ++j) {
if (chk & 0x8000)
chk = chk << 1 ^ 0x1021;
else
chk = chk << 1;
}
*dest++ = ch;
}
chk &= 0xFFFF;
if (((ch = getc(TO)) == -1) || ((ch & 0xff) != ((chk >> 8) & 0xFF)))
goto err;
if (((ch = getc(TO)) == -1) || ((ch & 0xff) != (chk & 0xFF)))
goto err;
putchar(ACK);
return (1);
err:;
putchar(CAN);
// We should allow for resend, but we don't.
return (0);
}
/*
* int xmodem_rx(char *)
* This global function receives a x-modem transmission consisting of
* (potentially) several blocks. Returns the number of bytes received or
* -1 on error.
*/
int
xmodem_rx(char *dest)
{
int starting, ch;
char packetNumber, *startAddress = dest;
packetNumber = 1;
starting = 1;
while (1) {
if (starting)
putchar('C');
if (((ch = getc(1)) == -1) || (ch != SOH && ch != EOT))
continue;
if (ch == EOT) {
putchar(ACK);
return (dest - startAddress);
}
starting = 0;
// Xmodem packets: SOH PKT# ~PKT# 128-bytes CRC16
if (!GetRecord(packetNumber, dest))
return (-1);
dest += PACKET_SIZE;
packetNumber++;
}
// the loop above should return in all cases
return (-1);
}

View File

@ -1,56 +0,0 @@
/*******************************************************************************
*
* Filename: linker.cfg
*
* linker config file used for internal RAM or eeprom images at address 0.
*
* Revision information:
*
* 20AUG2004 kb_admin initial creation
* 12JAN2005 kb_admin move data to SDRAM
*
* BEGIN_KBDD_BLOCK
* No warranty, expressed or implied, is included with this software. It is
* provided "AS IS" and no warranty of any kind including statutory or aspects
* relating to merchantability or fitness for any purpose is provided. All
* intellectual property rights of others is maintained with the respective
* owners. This software is not copyrighted and is intended for reference
* only.
* END_BLOCK
*
* $FreeBSD$
******************************************************************************/
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm",
"elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(start)
SECTIONS
{
/* Read-only sections, merged into text segment: */
. = 0;
.text :
{
*(.text)
}
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.data :
{
__data_start = . ;
*(.data)
}
_edata = .;
PROVIDE (edata = .);
__bss_start = .;
__bss_start__ = .;
.bss :
{
*(.bss)
. = ALIGN(32 / 8);
}
. = ALIGN(32 / 8);
_end = .;
_bss_end__ = . ; __bss_end__ = . ; __end__ = . ;
PROVIDE (end = .);
}

View File

@ -1,42 +0,0 @@
# $FreeBSD$
.if !target(__ixp425_boot_Makefile.inc__)
.PATH: ${.CURDIR}/../../../../libkern ${.CURDIR}/../../../../libkern/arm
__ixp425_boot_Makefile.inc__:
# Both Avila and Pronghorn Metro are supported by ixp425
BOOT_FLAVOR=ixp425
CFLAGS+=-Os -ffreestanding \
-I${.CURDIR}/../../../.. \
-I${.CURDIR}/../../../../arm \
-DCPU_XSCALE_IXP425 \
-Wall -Waggregate-return \
-Werror \
-Wnested-externs \
-Wpointer-arith -Wshadow -Wwrite-strings \
-Wmissing-prototypes \
-Wmissing-declarations
# -Wstrict-prototypes
CFLAGS+=-DBOOT_${BOOT_FLAVOR:tu}
LD ?= ld
OBJCOPY ?= objcopy
.if defined(P)
${P}: ${OBJS}
${LD} ${LDFLAGS} -o ${.TARGET} ${OBJS}
CLEANFILES+= ${P}
.endif
.if defined(WITH_TAG_LIST)
MK_TAG_LIST:=yes
.else
MK_TAG_LIST:=no
.endif
.endif

View File

@ -1,78 +0,0 @@
# $FreeBSD$
.include <src.opts.mk>
# We get a lot of the std lib functions from here.
.PATH: ${.CURDIR}/../../at91/libat91
# Enable to get debug msgs
#DEBUG=yes
# Hack to search through the kernel for ufs:ad0s1a and replace it with
# the correct one for the active slice/partition.
FIXUP_BOOT_DRV=yes
P=boot2
FILES=${P}
SRCS=arm_init.S boot2.c ${BOOT_FLAVOR:tl}_board.c
SRCS+=memchr.c memcmp.c memcpy.c memmem.c memset.c printf.c strcmp.c strcpy.c
SRCS+=strlen.c ashldi3.c divsi3.S muldi3.c
SRCS+=aeabi_unwind.c
MAN=
KERNPHYSADDR=0x180000
KERNVIRTADDR=${KERNPHYSADDR}
BOOT_STACK=0x200000-4
M=${MACHINE}
LDFLAGS=-e ${KERNPHYSADDR} -EB -T ldscript.${M}
OBJS+= ${SRCS:N*.h:R:S/$/.o/g}
S=${.CURDIR}/../../../..
CFLAGS+= \
-DBOOT_STACK=${BOOT_STACK} \
-I${.CURDIR}/../../../common \
-I${.CURDIR}
.if defined(FIXUP_BOOT_DRV)
CFLAGS+=-DFIXUP_BOOT_DRV
.endif
.if defined(DEBUG)
CFLAGS+=-DDEBUG
.endif
ldscript.$M: $S/conf/ldscript.$M
cat $S/conf/ldscript.$M|sed s/KERNPHYSADDR/${KERNPHYSADDR}/g| \
sed s/KERNVIRTADDR/${KERNVIRTADDR}/g | \
sed s/" + SIZEOF_HEADERS"// > ldscript.$M
${P}: ldscript.$M
CLEANFILES+=ldscript.$M
memchr.c: $S/../lib/libc/string/memchr.c
sed -e 's/string\.h/lib.h/' < $S/../lib/libc/string/memchr.c > \
${.TARGET}
memmem.c: $S/../lib/libc/string/memmem.c
sed -e 's/string\.h/lib.h/' < $S/../lib/libc/string/memmem.c > \
${.TARGET}
CLEANFILES+=memchr.c memmem.c
ashldi3.o: $S/libkern/ashldi3.c
${CC} -c ${CFLAGS} -D_KERNEL -o ${.TARGET} ${.IMPSRC}
divsi3.o: $S/libkern/${M}/divsi3.S
${CC} -c ${CFLAGS} -D_KERNEL -o ${.TARGET} ${.IMPSRC}
muldi3.o: $S/libkern/${M}/muldi3.c
${CC} -c ${CFLAGS} -D_KERNEL -o ${.TARGET} ${.IMPSRC}
inflate.c: $S/kern/inflate.c
sed -e 's/extern void putstr (char/extern void putstr (const char/' < \
$S/kern/inflate.c > ${.TARGET}
CLEANFILES+=inflate.c
.include <bsd.prog.mk>

View File

@ -1,58 +0,0 @@
/*-
* Copyright (c) 2008 John Hay. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <machine/asm.h>
ASENTRY_NP(start)
/* Initialise bss and sp */
nop
adr r1, .Lstart
ldmia r1, {r1, r2, sp} /* Set initial stack and */
sub r2, r2, r1 /* get zero init data */
mov r3, #0
.L1:
str r3, [r1], #0x0004 /* get zero init data */
subs r2, r2, #4
bgt .L1
.extern main
bl main
/* main should not return. If it does, spin forever */
infiniteLoop:
b infiniteLoop
END(start)
.Lstart:
.word _edata
.word _end
.word BOOT_STACK
ENTRY(cpu_id)
mrc p15, 0, r0, c0, c0, 0
RET
END(cpu_id)
/* End */

View File

@ -1,446 +0,0 @@
/*-
* Copyright (c) 2008 John Hay
* Copyright (c) 1998 Robert Nordier
* All rights reserved.
*
* Redistribution and use in source and binary forms are freely
* permitted provided that the above copyright notice and this
* paragraph and the following disclaimer are duplicated in all
* such forms.
*
* This software is provided "AS IS" and without any express or
* implied warranties, including, without limitation, the implied
* warranties of merchantability and fitness for a particular
* purpose.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/disklabel.h>
#include <sys/diskmbr.h>
#include <sys/dirent.h>
#include <sys/reboot.h>
#include <machine/elf.h>
#include <stdarg.h>
#include "lib.h"
#include "paths.h"
#include "rbx.h"
extern uint32_t _end;
#define NOPT 6
static const char optstr[NOPT] = "agnrsv";
static const unsigned char flags[NOPT] = {
RBX_ASKNAME,
RBX_GDB,
RBX_NOINTR,
RBX_DFLTROOT,
RBX_SINGLE,
RBX_VERBOSE
};
static unsigned dsk_start;
static char cmd[512];
static char kname[1024];
static uint32_t opts;
static uint8_t dsk_meta;
static int bootslice;
static int bootpart;
static int disk_layout;
#define DL_UNKNOWN 0
#define DL_RAW 1 /* Dangerously dedicated */
#define DL_SLICE 2 /* Use only slices (DOS partitions) */
#define DL_SLICEPART 3 /* Use slices and partitions */
static void load(void);
static int parse(void);
static int dskread(void *, unsigned, unsigned);
static int drvread(void *, unsigned, unsigned);
#ifdef FIXUP_BOOT_DRV
static void fixup_boot_drv(caddr_t, int, int, int);
#endif
#include "ufsread.c"
#ifdef DEBUG
#define DPRINTF(fmt, ...) printf(fmt, __VA_ARGS__)
#else
#define DPRINTF(fmt, ...)
#endif
static inline int
xfsread(ufs_ino_t inode, void *buf, size_t nbyte)
{
if ((size_t)fsread(inode, buf, nbyte) != nbyte)
return -1;
return 0;
}
static inline void
getstr(int c)
{
char *s;
s = cmd;
if (c == 0)
c = getc(10000);
for (;;) {
switch (c) {
case 0:
break;
case '\177':
case '\b':
if (s > cmd) {
s--;
printf("\b \b");
}
break;
case '\n':
case '\r':
*s = 0;
return;
default:
if (s - cmd < sizeof(cmd) - 1)
*s++ = c;
xputchar(c);
}
c = getc(10000);
}
}
int
main(void)
{
const char *bt;
int autoboot, c = 0;
ufs_ino_t ino;
dmadat = (void *)(0x1c0000);
p_memset((char *)dmadat, 0, 32 * 1024);
bt = board_init();
printf("FreeBSD ARM (%s) boot2 v%d.%d\n", bt, 0, 4);
autoboot = 1;
/* Process configuration file */
if ((ino = lookup(PATH_CONFIG)) ||
(ino = lookup(PATH_DOTCONFIG)))
fsread(ino, cmd, sizeof(cmd));
if (*cmd) {
if (parse())
autoboot = 0;
printf("%s: %s\n", PATH_CONFIG, cmd);
/* Do not process this command twice */
*cmd = 0;
}
if (*kname == '\0')
strcpy(kname, PATH_KERNEL);
/* Present the user with the boot2 prompt. */
for (;;) {
printf("\nDefault: %s\nboot: ", kname);
if (!autoboot ||
(OPT_CHECK(RBX_NOINTR) == 0 && (c = getc(2)) != 0))
getstr(c);
xputchar('\n');
autoboot = 0;
c = 0;
DPRINTF("cmd is '%s'\n", cmd);
if (parse())
xputchar('\a');
else
load();
}
}
static void
load(void)
{
Elf32_Ehdr eh;
static Elf32_Phdr ep[2];
caddr_t p;
ufs_ino_t ino;
uint32_t addr;
int i, j;
#ifdef FIXUP_BOOT_DRV
caddr_t staddr;
int klen;
staddr = (caddr_t)0xffffffff;
klen = 0;
#endif
if (!(ino = lookup(kname))) {
if (!ls)
printf("No %s\n", kname);
return;
}
DPRINTF("Found %s\n", kname);
if (xfsread(ino, &eh, sizeof(eh)))
return;
if (!IS_ELF(eh)) {
printf("Invalid %s\n", "format");
return;
}
fs_off = eh.e_phoff;
for (j = i = 0; i < eh.e_phnum && j < 2; i++) {
if (xfsread(ino, ep + j, sizeof(ep[0])))
return;
if (ep[j].p_type == PT_LOAD)
j++;
}
for (i = 0; i < 2; i++) {
p = (caddr_t)(ep[i].p_paddr & 0x0fffffff);
fs_off = ep[i].p_offset;
#ifdef FIXUP_BOOT_DRV
if (staddr == (caddr_t)0xffffffff)
staddr = p;
klen += ep[i].p_filesz;
#endif
if (xfsread(ino, p, ep[i].p_filesz))
return;
}
addr = eh.e_entry & 0x0fffffff;
DPRINTF("Entry point %x for %s\n", addr, kname);
clr_board();
#ifdef FIXUP_BOOT_DRV
fixup_boot_drv(staddr, klen, bootslice, bootpart);
#endif
((void(*)(int))addr)(RB_BOOTINFO /* XXX | (opts & RBX_MASK) */);
}
static int
parse()
{
char *arg = cmd;
char *ep, *p;
int c, i;
while ((c = *arg++)) {
if (c == ' ' || c == '\t' || c == '\n')
continue;
for (p = arg; *p && *p != '\n' && *p != ' ' && *p != '\t'; p++);
ep = p;
if (*p)
*p++ = 0;
if (c == '-') {
while ((c = *arg++)) {
for (i = 0; c != optstr[i]; i++)
if (i == NOPT - 1)
return -1;
opts ^= OPT_SET(flags[i]);
}
} else {
arg--;
/* look for ad0s1a:... | ad0s1:... */
if (strlen(arg) > 6 && arg[0] == 'a' &&
arg[1] == 'd' && arg[3] == 's' &&
(arg[5] == ':' || arg[6] == ':')) {
/* XXX Should also handle disk. */
bootslice = arg[4] - '0';
if (bootslice < 1 || bootslice > 4)
return (-1);
bootpart = 0;
if (arg[5] != ':')
bootpart = arg[5] - 'a';
if (bootpart < 0 || bootpart > 7)
return (-1);
dsk_meta = 0;
if (arg[5] == ':')
arg += 6;
else
arg += 7;
/* look for ad0a:... */
} else if (strlen(arg) > 4 && arg[0] == 'a' &&
arg[1] == 'd' && arg[2] == '0' && arg[4] == ':') {
bootslice = 0;
bootpart = arg[3] - 'a';
if (bootpart < 0 || bootpart > 7)
return (-1);
dsk_meta = 0;
arg += 5;
}
if ((i = ep - arg)) {
if ((size_t)i >= sizeof(kname))
return -1;
memcpy(kname, arg, i + 1);
}
}
arg = p;
}
return 0;
}
/*
* dskread() will try to handle the disk layouts that are typically
* encountered.
* - raw or "Dangerously Dedicated" mode. No real slice table, just the
* default one that is included with bsdlabel -B. Typically this is
* used with ROOTDEVNAME=\"ufs:ad0a\".
* - slice only. Only a slice table is installed with no bsd label or
* bsd partition table. This is typically used with
* ROOTDEVNAME=\"ufs:ad0s1\".
* - slice + bsd label + partition table. This is typically done with
* with fdisk + bsdlabel and is used with ROOTDEVNAME=\"ufs:ad0s1a\".
*/
static int
dskread(void *buf, unsigned lba, unsigned nblk)
{
struct dos_partition *dp;
struct disklabel *d;
char *sec;
int i;
if (!dsk_meta) {
sec = dmadat->secbuf;
dsk_start = 0;
if (drvread(sec, DOSBBSECTOR, 1))
return -1;
dp = (void *)(sec + DOSPARTOFF);
if (bootslice != 0) {
i = bootslice - 1;
if (dp[i].dp_typ != DOSPTYP_386BSD)
return -1;
} else {
for (i = 0; i < NDOSPART; i++) {
if ((dp[i].dp_typ == DOSPTYP_386BSD) &&
(dp[i].dp_flag == 0x80))
break;
}
}
if (i != NDOSPART) {
bootslice = i + 1;
DPRINTF("Found an active fbsd slice. (%d)\n", i + 1);
/*
* Although dp_start is aligned within the disk
* partition structure, DOSPARTOFF is 446, which
* is only word (2) aligned, not longword (4)
* aligned. Cope by using memcpy to fetch the
* start of this partition.
*/
memcpy(&dsk_start, &dp[i].dp_start, 4);
dsk_start = swap32(dsk_start);
DPRINTF("dsk_start %x\n", dsk_start);
if ((bootslice == 4) && (dsk_start == 0)) {
disk_layout = DL_RAW;
bootslice = 0;
}
}
if (drvread(sec, dsk_start + LABELSECTOR, 1))
return -1;
d = (void *)(sec + LABELOFFSET);
if ((d->d_magic == DISKMAGIC && d->d_magic2 == DISKMAGIC) ||
(swap32(d->d_magic) == DISKMAGIC &&
swap32(d->d_magic2) == DISKMAGIC)) {
DPRINTF("p_size = %x\n",
!d->d_partitions[bootpart].p_size);
if (!d->d_partitions[bootpart].p_size) {
printf("Invalid partition\n");
return -1;
}
DPRINTF("p_offset %x, RAW %x\n",
swap32(d->d_partitions[bootpart].p_offset),
swap32(d->d_partitions[RAW_PART].p_offset));
dsk_start += swap32(d->d_partitions[bootpart].p_offset);
dsk_start -= swap32(d->d_partitions[RAW_PART].p_offset);
if ((disk_layout == DL_UNKNOWN) && (bootslice == 0))
disk_layout = DL_RAW;
else if (disk_layout == DL_UNKNOWN)
disk_layout = DL_SLICEPART;
} else {
disk_layout = DL_SLICE;
DPRINTF("Invalid %s\n", "label");
}
DPRINTF("bootslice %d, bootpart %d, dsk_start %u\n", bootslice,
bootpart, dsk_start);
dsk_meta++;
}
return drvread(buf, dsk_start + lba, nblk);
}
static int
drvread(void *buf, unsigned lba, unsigned nblk)
{
static unsigned c = 0x2d5c7c2f;
printf("%c\b", c = c << 8 | c >> 24);
return (avila_read((char *)buf, lba, nblk));
}
#ifdef FIXUP_BOOT_DRV
/*
* fixup_boot_drv() will try to find the ROOTDEVNAME spec in the kernel
* and change it to what was specified on the comandline or /boot.conf
* file or to what was encountered on the disk. It will try to handle 3
* different disk layouts, raw (dangerously dedicated), slice only and
* slice + partition. It will look for the following strings in the
* kernel, but if it is one of the first three, the string in the kernel
* must use the correct form to match the actual disk layout:
* - ufs:ad0a
* - ufs:ad0s1
* - ufs:ad0s1a
* - ufs:ROOTDEVNAME
* In the case of the first three strings, only the "a" at the end and
* the "1" after the "s" will be modified, if they exist. The string
* length will not be changed. In the case of the last string, the
* whole string will be built up and nul, '\0' terminated.
*/
static void
fixup_boot_drv(caddr_t addr, int klen, int bs, int bp)
{
const u_int8_t op[] = "ufs:ROOTDEVNAME";
const u_int8_t op2[] = "ufs:ad0";
u_int8_t *p, *ps;
DPRINTF("fixup_boot_drv: 0x%x, %d, slice %d, partition %d\n",
(int)addr, klen, bs, bp);
if (bs > 4)
return;
if (bp > 7)
return;
ps = memmem(addr, klen, op, sizeof(op));
if (ps != NULL) {
p = ps + 4; /* past ufs: */
DPRINTF("Found it at 0x%x\n", (int)ps);
p[0] = 'a'; p[1] = 'd'; p[2] = '0'; /* ad0 */
p += 3;
if (bs > 0) {
/* append slice */
*p++ = 's';
*p++ = bs + '0';
}
if (disk_layout != DL_SLICE) {
/* append partition */
*p++ = bp + 'a';
}
*p = '\0';
} else {
ps = memmem(addr, klen, op2, sizeof(op2) - 1);
if (ps != NULL) {
p = ps + sizeof(op2) - 1;
DPRINTF("Found it at 0x%x\n", (int)ps);
if (*p == 's') {
/* fix slice */
p++;
*p++ = bs + '0';
}
if (*p == 'a')
*p = bp + 'a';
}
}
if (ps == NULL) {
printf("Could not locate \"%s\" to fix kernel boot device, "
"check ROOTDEVNAME is set\n", op);
return;
}
DPRINTF("Changed boot device to %s\n", ps);
}
#endif

View File

@ -1,62 +0,0 @@
/*-
* Copyright (c) 2008 John Hay. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef ARM_BOOT_CF_ATA_H
#define ARM_BOOT_CF_ATA_H
#define CF_DATA 0x00
#define CF_ERROR 0x01
#define CF_FEATURE 0x01
#define CF_SECT_CNT 0x02
#define CF_SECT_NUM 0x03
#define CF_CYL_L 0x04
#define CF_CYL_H 0x05
#define CF_DRV_HEAD 0x06
#define CF_D_MASTER 0x00
#define CF_D_LBA 0x40
#define CF_D_IBM 0xa0
#define CF_STATUS 0x07
#define CF_S_ERROR 0x01
#define CF_S_INDEX 0x02
#define CF_S_CORR 0x04
#define CF_S_DRQ 0x08
#define CF_S_DSC 0x10
#define CF_S_DWF 0x20
#define CF_S_READY 0x40
#define CF_S_BUSY 0x80
#define CF_COMMAND 0x07
/* This is according to the appnote, but Sam use 0x1e in avila_ata.c */
#define CF_ALT_STATUS 0x16
#define CF_ALT_DEV_CTR 0x16
#define CF_ALT_DEV_CTR2 0x1e
#define CF_A_IDS 0x02
#define CF_A_RESET 0x04
#define CF_A_4BIT 0x08
#define AVILA_IDE_GPIN 12
#endif /* !ARM_BOOT_CF_ATA_H */

View File

@ -1,771 +0,0 @@
/*-
* Copyright (c) 2008 John Hay. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/ata.h>
#include <sys/linker_set.h>
#include <stdarg.h>
#include "lib.h"
#include "cf_ata.h"
#include <machine/armreg.h>
#include <arm/xscale/ixp425/ixp425reg.h>
#include <dev/ic/ns16550.h>
struct board_config {
const char *desc;
int (*probe)(int boardtype_hint);
void (*init)(void);
};
/* set of registered boards */
SET_DECLARE(boards, struct board_config);
#define BOARD_CONFIG(name, _desc) \
static struct board_config name##config = { \
.desc = _desc, \
.probe = name##_probe, \
.init = name##_init, \
}; \
DATA_SET(boards, name##config)
static u_int cputype;
#define cpu_is_ixp43x() (cputype == CPU_ID_IXP435)
static u_int8_t *ubase;
static u_int8_t uart_getreg(u_int8_t *, int);
static void uart_setreg(u_int8_t *, int, u_int8_t);
static void cf_init(void);
static void cf_clr(void);
#ifdef DEBUG
#define DPRINTF(fmt, ...) printf(fmt, __VA_ARGS__)
#else
#define DPRINTF(fmt, ...)
#endif
const char *
board_init(void)
{
struct board_config **pbp;
cputype = cpu_id() & CPU_ID_CPU_MASK;
SET_FOREACH(pbp, boards)
/* XXX pass down redboot board type */
if ((*pbp)->probe(0)) {
(*pbp)->init();
return (*pbp)->desc;
}
/* XXX panic, unknown board type */
return "???";
}
/*
* This should be called just before starting the kernel. This is so
* that one can undo incompatible hardware settings.
*/
void
clr_board(void)
{
cf_clr();
}
/*
* General support functions.
*/
/*
* DELAY should delay for the number of microseconds.
* The idea is that the inner loop should take 1us, so val is the
* number of usecs to delay.
*/
void
DELAY(int val)
{
volatile int sub;
volatile int subsub;
sub = val;
while(sub) {
subsub = 3;
while(subsub)
subsub--;
sub--;
}
}
u_int32_t
swap32(u_int32_t a)
{
return (((a & 0xff) << 24) | ((a & 0xff00) << 8) |
((a & 0xff0000) >> 8) | ((a & 0xff000000) >> 24));
}
u_int16_t
swap16(u_int16_t val)
{
return (val << 8) | (val >> 8);
}
/*
* uart related funcs
*/
static u_int8_t
uart_getreg(u_int8_t *bas, int off)
{
return *((volatile u_int32_t *)(bas + (off << 2))) & 0xff;
}
static void
uart_setreg(u_int8_t *bas, int off, u_int8_t val)
{
*((volatile u_int32_t *)(bas + (off << 2))) = (u_int32_t)val;
}
int
getc(int seconds)
{
int c, delay, limit;
c = 0;
delay = 10000;
limit = seconds * 1000000/10000;
while ((uart_getreg(ubase, REG_LSR) & LSR_RXRDY) == 0 && --limit)
DELAY(delay);
if ((uart_getreg(ubase, REG_LSR) & LSR_RXRDY) == LSR_RXRDY)
c = uart_getreg(ubase, REG_DATA);
return c;
}
void
putchar(int ch)
{
int delay, limit;
delay = 500;
limit = 20;
while ((uart_getreg(ubase, REG_LSR) & LSR_THRE) == 0 && --limit)
DELAY(delay);
uart_setreg(ubase, REG_DATA, ch);
limit = 40;
while ((uart_getreg(ubase, REG_LSR) & LSR_TEMT) == 0 && --limit)
DELAY(delay);
}
void
xputchar(int ch)
{
if (ch == '\n')
putchar('\r');
putchar(ch);
}
void
putstr(const char *str)
{
while(*str)
xputchar(*str++);
}
void
puthex8(u_int8_t ch)
{
const char *hex = "0123456789abcdef";
putchar(hex[ch >> 4]);
putchar(hex[ch & 0xf]);
}
void
puthexlist(const u_int8_t *str, int length)
{
while(length) {
puthex8(*str);
putchar(' ');
str++;
length--;
}
}
/*
*
* CF/IDE functions.
*
*/
struct {
u_int64_t dsize;
u_int64_t total_secs;
u_int8_t heads;
u_int8_t sectors;
u_int32_t cylinders;
u_int32_t *cs1to;
u_int32_t *cs2to;
u_int8_t *cs1;
u_int8_t *cs2;
u_int32_t use_lba;
u_int32_t use_stream8;
u_int32_t debug;
u_int8_t status;
u_int8_t error;
} dskinf;
static void cfenable16(void);
static void cfdisable16(void);
static u_int8_t cfread8(u_int32_t off);
static u_int16_t cfread16(u_int32_t off);
static void cfreadstream8(void *buf, int length);
static void cfreadstream16(void *buf, int length);
static void cfwrite8(u_int32_t off, u_int8_t val);
static u_int8_t cfaltread8(u_int32_t off);
static void cfaltwrite8(u_int32_t off, u_int8_t val);
static int cfwait(u_int8_t mask);
static int cfaltwait(u_int8_t mask);
static int cfcmd(u_int32_t cmd, u_int32_t cylinder, u_int32_t head,
u_int32_t sector, u_int32_t count, u_int32_t feature);
static void cfreset(void);
#ifdef DEBUG
static int cfgetparams(void);
#endif
static void cfprintregs(void);
static void
cf_init(void)
{
u_int8_t status;
#ifdef DEBUG
int rval;
#endif
/* NB: board init routines setup other parts of dskinf */
dskinf.use_stream8 = 0;
dskinf.use_lba = 0;
dskinf.debug = 1;
DPRINTF("cs1 %x, cs2 %x\n", dskinf.cs1, dskinf.cs2);
/* Setup the CF window */
*dskinf.cs1to |= (EXP_BYTE_EN | EXP_WR_EN | EXP_BYTE_RD16 | EXP_CS_EN);
DPRINTF("t1 %x, ", *dskinf.cs1to);
*dskinf.cs2to |= (EXP_BYTE_EN | EXP_WR_EN | EXP_BYTE_RD16 | EXP_CS_EN);
DPRINTF("t2 %x\n", *dskinf.cs2to);
/* Detect if there is a disk. */
cfwrite8(CF_DRV_HEAD, CF_D_IBM);
DELAY(1000);
status = cfread8(CF_STATUS);
if (status != 0x50)
printf("cf-ata0 %x\n", (u_int32_t)status);
if (status == 0xff) {
printf("cf_ata0: No disk!\n");
return;
}
cfreset();
if (dskinf.use_stream8) {
DPRINTF("setting %d bit mode.\n", 8);
cfwrite8(CF_FEATURE, 0x01); /* Enable 8 bit transfers */
cfwrite8(CF_COMMAND, ATA_SETFEATURES);
cfaltwait(CF_S_READY);
}
#ifdef DEBUG
rval = cfgetparams();
if (rval)
return;
#endif
dskinf.use_lba = 1;
dskinf.debug = 0;
}
static void
cf_clr(void)
{
cfwrite8(CF_DRV_HEAD, CF_D_IBM);
cfaltwait(CF_S_READY);
cfwrite8(CF_FEATURE, 0x81); /* Enable 8 bit transfers */
cfwrite8(CF_COMMAND, ATA_SETFEATURES);
cfaltwait(CF_S_READY);
}
static void
cfenable16(void)
{
u_int32_t val;
val = *dskinf.cs1to;
*dskinf.cs1to = val &~ EXP_BYTE_EN;
DELAY(100);
#if 0
DPRINTF("%s: cs1 timing reg %x\n", *dskinf.cs1to, __func__);
#endif
}
static void
cfdisable16(void)
{
u_int32_t val;
DELAY(100);
val = *dskinf.cs1to;
*dskinf.cs1to = val | EXP_BYTE_EN;
#if 0
DPRINTF("%s: cs1 timing reg %x\n", *dskinf.cs1to, __func__);
#endif
}
static u_int8_t
cfread8(u_int32_t off)
{
volatile u_int8_t *vp;
vp = (volatile u_int8_t *)(dskinf.cs1 + off);
return *vp;
}
static void
cfreadstream8(void *buf, int length)
{
u_int8_t *lbuf;
u_int8_t tmp;
lbuf = buf;
while (length) {
tmp = cfread8(CF_DATA);
*lbuf = tmp;
#ifdef DEBUG
if (dskinf.debug && (length > (512 - 32))) {
if ((length % 16) == 0)
xputchar('\n');
puthex8(tmp);
putchar(' ');
}
#endif
lbuf++;
length--;
}
#ifdef DEBUG
if (dskinf.debug)
xputchar('\n');
#endif
}
static u_int16_t
cfread16(u_int32_t off)
{
volatile u_int16_t *vp;
vp = (volatile u_int16_t *)(dskinf.cs1 + off);
return swap16(*vp);
}
static void
cfreadstream16(void *buf, int length)
{
u_int16_t *lbuf;
length = length / 2;
cfenable16();
lbuf = buf;
while (length--) {
*lbuf = cfread16(CF_DATA);
lbuf++;
}
cfdisable16();
}
static void
cfwrite8(u_int32_t off, u_int8_t val)
{
volatile u_int8_t *vp;
vp = (volatile u_int8_t *)(dskinf.cs1 + off);
*vp = val;
}
#if 0
static void
cfwrite16(u_int32_t off, u_int16_t val)
{
volatile u_int16_t *vp;
vp = (volatile u_int16_t *)(dskinf.cs1 + off);
*vp = val;
}
#endif
static u_int8_t
cfaltread8(u_int32_t off)
{
volatile u_int8_t *vp;
off &= 0x0f;
vp = (volatile u_int8_t *)(dskinf.cs2 + off);
return *vp;
}
static void
cfaltwrite8(u_int32_t off, u_int8_t val)
{
volatile u_int8_t *vp;
/*
* This is documented in the Intel appnote 302456.
*/
off &= 0x0f;
vp = (volatile u_int8_t *)(dskinf.cs2 + off);
*vp = val;
}
static int
cfwait(u_int8_t mask)
{
u_int8_t status;
u_int32_t tout;
tout = 0;
while (tout <= 5000000) {
status = cfread8(CF_STATUS);
if (status == 0xff) {
printf("%s: master: no status, reselecting\n",
__func__);
cfwrite8(CF_DRV_HEAD, CF_D_IBM);
DELAY(1);
status = cfread8(CF_STATUS);
}
if (status == 0xff)
return -1;
dskinf.status = status;
if (!(status & CF_S_BUSY)) {
if (status & CF_S_ERROR) {
dskinf.error = cfread8(CF_ERROR);
printf("%s: error, status 0x%x error 0x%x\n",
__func__, status, dskinf.error);
}
if ((status & mask) == mask) {
DPRINTF("%s: status 0x%x mask 0x%x tout %u\n",
__func__, status, mask, tout);
return (status & CF_S_ERROR);
}
}
if (tout > 1000) {
tout += 1000;
DELAY(1000);
} else {
tout += 10;
DELAY(10);
}
}
return -1;
}
static int
cfaltwait(u_int8_t mask)
{
u_int8_t status;
u_int32_t tout;
tout = 0;
while (tout <= 5000000) {
status = cfaltread8(CF_ALT_STATUS);
if (status == 0xff) {
printf("cfaltwait: master: no status, reselecting\n");
cfwrite8(CF_DRV_HEAD, CF_D_IBM);
DELAY(1);
status = cfread8(CF_STATUS);
}
if (status == 0xff)
return -1;
dskinf.status = status;
if (!(status & CF_S_BUSY)) {
if (status & CF_S_ERROR)
dskinf.error = cfread8(CF_ERROR);
if ((status & mask) == mask) {
DPRINTF("cfaltwait: tout %u\n", tout);
return (status & CF_S_ERROR);
}
}
if (tout > 1000) {
tout += 1000;
DELAY(1000);
} else {
tout += 10;
DELAY(10);
}
}
return -1;
}
static int
cfcmd(u_int32_t cmd, u_int32_t cylinder, u_int32_t head, u_int32_t sector,
u_int32_t count, u_int32_t feature)
{
if (cfwait(0) < 0) {
printf("cfcmd: timeout\n");
return -1;
}
cfwrite8(CF_FEATURE, feature);
cfwrite8(CF_CYL_L, cylinder);
cfwrite8(CF_CYL_H, cylinder >> 8);
if (dskinf.use_lba)
cfwrite8(CF_DRV_HEAD, CF_D_IBM | CF_D_LBA | head);
else
cfwrite8(CF_DRV_HEAD, CF_D_IBM | head);
cfwrite8(CF_SECT_NUM, sector);
cfwrite8(CF_SECT_CNT, count);
cfwrite8(CF_COMMAND, cmd);
return 0;
}
static void
cfreset(void)
{
u_int8_t status;
u_int32_t tout;
cfwrite8(CF_DRV_HEAD, CF_D_IBM);
DELAY(1);
#ifdef DEBUG
cfprintregs();
#endif
cfread8(CF_STATUS);
cfaltwrite8(CF_ALT_DEV_CTR, CF_A_IDS | CF_A_RESET);
DELAY(10000);
cfaltwrite8(CF_ALT_DEV_CTR, CF_A_IDS);
DELAY(10000);
cfread8(CF_ERROR);
DELAY(3000);
for (tout = 0; tout < 310000; tout++) {
cfwrite8(CF_DRV_HEAD, CF_D_IBM);
DELAY(1);
status = cfread8(CF_STATUS);
if (!(status & CF_S_BUSY))
break;
DELAY(100);
}
DELAY(1);
if (status & CF_S_BUSY) {
cfprintregs();
printf("cfreset: Status stayed busy after reset.\n");
}
DPRINTF("cfreset: finished, tout %u\n", tout);
}
#ifdef DEBUG
static int
cfgetparams(void)
{
u_int8_t *buf;
buf = (u_int8_t *)(0x170000);
p_memset((char *)buf, 0, 1024);
/* Select the drive. */
cfwrite8(CF_DRV_HEAD, CF_D_IBM);
DELAY(1);
cfcmd(ATA_ATA_IDENTIFY, 0, 0, 0, 0, 0);
if (cfaltwait(CF_S_READY | CF_S_DSC | CF_S_DRQ)) {
printf("cfgetparams: ATA_IDENTIFY failed.\n");
return -1;
}
if (dskinf.use_stream8)
cfreadstream8(buf, 512);
else
cfreadstream16(buf, 512);
if (dskinf.debug)
cfprintregs();
#if 0
memcpy(&dskinf.ata_params, buf, sizeof(struct ata_params));
dskinf.cylinders = dskinf.ata_params.cylinders;
dskinf.heads = dskinf.ata_params.heads;
dskinf.sectors = dskinf.ata_params.sectors;
printf("dsk0: sec %x, hd %x, cyl %x, stat %x, err %x\n",
(u_int32_t)dskinf.ata_params.sectors,
(u_int32_t)dskinf.ata_params.heads,
(u_int32_t)dskinf.ata_params.cylinders,
(u_int32_t)dskinf.status,
(u_int32_t)dskinf.error);
#endif
dskinf.status = cfread8(CF_STATUS);
if (dskinf.debug)
printf("cfgetparams: ata_params * %x, stat %x\n",
(u_int32_t)buf, (u_int32_t)dskinf.status);
return 0;
}
#endif /* DEBUG */
static void
cfprintregs(void)
{
u_int8_t rv;
putstr("cfprintregs: regs error ");
rv = cfread8(CF_ERROR);
puthex8(rv);
putstr(", count ");
rv = cfread8(CF_SECT_CNT);
puthex8(rv);
putstr(", sect ");
rv = cfread8(CF_SECT_NUM);
puthex8(rv);
putstr(", cyl low ");
rv = cfread8(CF_CYL_L);
puthex8(rv);
putstr(", cyl high ");
rv = cfread8(CF_CYL_H);
puthex8(rv);
putstr(", drv head ");
rv = cfread8(CF_DRV_HEAD);
puthex8(rv);
putstr(", status ");
rv = cfread8(CF_STATUS);
puthex8(rv);
putstr("\n");
}
int
avila_read(char *dest, unsigned source, unsigned length)
{
if (dskinf.use_lba == 0 && source == 0)
source++;
if (dskinf.debug)
printf("avila_read: 0x%x, sect %d num secs %d\n",
(u_int32_t)dest, source, length);
while (length) {
cfwait(CF_S_READY);
/* cmd, cyl, head, sect, count, feature */
cfcmd(ATA_READ, (source >> 8) & 0xffff, source >> 24,
source & 0xff, 1, 0);
cfwait(CF_S_READY | CF_S_DRQ | CF_S_DSC);
if (dskinf.use_stream8)
cfreadstream8(dest, 512);
else
cfreadstream16(dest, 512);
length--;
source++;
dest += 512;
}
return 0;
}
/*
* Gateworks Avila Support.
*/
static int
avila_probe(int boardtype_hint)
{
volatile u_int32_t *cs;
/*
* Redboot only configure the chip selects that are needed, so
* use that to figure out if it is an Avila or ADI board. The
* Avila boards use CS2 and ADI does not.
*/
cs = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS2_OFFSET);
return (*cs != 0);
}
static void
avila_init(void)
{
/* Config the serial port. RedBoot should do the rest. */
ubase = (u_int8_t *)(IXP425_UART0_HWBASE);
dskinf.cs1to = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS1_OFFSET);
dskinf.cs2to = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS2_OFFSET);
dskinf.cs1 = (u_int8_t *)IXP425_EXP_BUS_CS1_HWBASE;
dskinf.cs2 = (u_int8_t *)IXP425_EXP_BUS_CS2_HWBASE;
cf_init();
}
BOARD_CONFIG(avila, "Gateworks Avila");
/*
* Gateworks Cambria Support.
*/
static int
cambria_probe(int boardtype_hint)
{
return cpu_is_ixp43x();
}
static void
cambria_init(void)
{
/* Config the serial port. RedBoot should do the rest. */
ubase = (u_int8_t *)(IXP425_UART0_HWBASE);
dskinf.cs1to = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS3_OFFSET);
dskinf.cs2to = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS4_OFFSET);
dskinf.cs1 = (u_int8_t *)CAMBRIA_CFSEL0_HWBASE;
dskinf.cs2 = (u_int8_t *)CAMBRIA_CFSEL1_HWBASE;
cf_init();
}
BOARD_CONFIG(cambria, "Gateworks Cambria");
/*
* Pronghorn Metro Support.
*/
static int
pronghorn_probe(int boardtype_hint)
{
volatile u_int32_t *cs;
/*
* Redboot only configure the chip selects that are needed, so
* use that to figure out if it is an Avila or ADI board. The
* Avila boards use CS2 and ADI does not.
*/
cs = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS2_OFFSET);
return (*cs == 0);
}
static void
pronghorn_init(void)
{
/* Config the serial port. RedBoot should do the rest. */
ubase = (u_int8_t *)(IXP425_UART1_HWBASE);
dskinf.cs1to = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS3_OFFSET);
dskinf.cs2to = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS4_OFFSET);
dskinf.cs1 = (u_int8_t *)IXP425_EXP_BUS_CS3_HWBASE;
dskinf.cs2 = (u_int8_t *)IXP425_EXP_BUS_CS4_HWBASE;
cf_init();
}
BOARD_CONFIG(pronghorn, "Pronghorn Metro");

View File

@ -1,67 +0,0 @@
/*-
* Copyright (c) 2008 John Hay. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef ARM_BOOT_LIB_H
#define ARM_BOOT_LIB_H
#include <sys/cdefs.h>
#include <sys/param.h>
int main(void);
void DELAY(int);
int getc(int);
void putchar(int);
void xputchar(int);
void putstr(const char *);
void puthex8(u_int8_t);
void puthexlist(const u_int8_t *, int);
void printf(const char *fmt,...);
void bzero(void *, size_t);
char *strcpy(char *to, const char *from);
int strcmp(const char *to, const char *from);
int p_strlen(const char *);
int p_memcmp(const char *, const char *, unsigned);
void *memchr(const void *, int, size_t);
void memcpy(void *to, const void *from, unsigned size);
void *memmem(const void *, size_t, const void *, size_t);
void p_memset(char *buffer, char value, int size);
#define strlen p_strlen
#define memcmp p_memcmp
#define memset p_memset
u_int16_t swap16(u_int16_t);
u_int32_t swap32(u_int32_t);
const char *board_init(void);
void clr_board(void);
int avila_read(char*, unsigned, unsigned);
u_int cpu_id(void);
#endif /* !ARM_BOOT_LIB_H */