mirror of
https://github.com/Ysurac/openmptcprouter.git
synced 2025-03-09 15:40:20 +00:00
Fix for RUTX platform
This commit is contained in:
parent
ccdb64ad45
commit
59bc57d5d5
7254 changed files with 1810270 additions and 7 deletions
2
root/package/utils/sysupgrade-helper/src/examples/api/.gitignore
vendored
Normal file
2
root/package/utils/sysupgrade-helper/src/examples/api/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
demo
|
||||
demo.bin
|
|
@ -0,0 +1,90 @@
|
|||
#
|
||||
# (C) Copyright 2007 Semihalf
|
||||
#
|
||||
# See file CREDITS for list of people who contributed to this
|
||||
# project.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundatio; either version 2 of
|
||||
# the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
# MA 02111-1307 USA
|
||||
#
|
||||
|
||||
ifeq ($(ARCH),powerpc)
|
||||
LOAD_ADDR = 0x40000
|
||||
endif
|
||||
ifeq ($(ARCH),arm)
|
||||
LOAD_ADDR = 0x1000000
|
||||
endif
|
||||
|
||||
include $(TOPDIR)/config.mk
|
||||
|
||||
# Resulting ELF and binary exectuables will be named demo and demo.bin
|
||||
OUTPUT-$(CONFIG_API) = $(obj)demo
|
||||
OUTPUT = $(OUTPUT-y)
|
||||
|
||||
# Source files located in the examples/api directory
|
||||
SOBJ_FILES-$(CONFIG_API) += crt0.o
|
||||
COBJ_FILES-$(CONFIG_API) += demo.o
|
||||
COBJ_FILES-$(CONFIG_API) += glue.o
|
||||
COBJ_FILES-$(CONFIG_API) += libgenwrap.o
|
||||
|
||||
# Source files which exist outside the examples/api directory
|
||||
EXT_COBJ_FILES-$(CONFIG_API) += lib/crc32.o
|
||||
EXT_COBJ_FILES-$(CONFIG_API) += lib/ctype.o
|
||||
EXT_COBJ_FILES-$(CONFIG_API) += lib/div64.o
|
||||
EXT_COBJ_FILES-$(CONFIG_API) += lib/string.o
|
||||
EXT_COBJ_FILES-$(CONFIG_API) += lib/time.o
|
||||
EXT_COBJ_FILES-$(CONFIG_API) += lib/vsprintf.o
|
||||
ifeq ($(ARCH),powerpc)
|
||||
EXT_SOBJ_FILES-$(CONFIG_API) += arch/powerpc/lib/ppcstring.o
|
||||
endif
|
||||
|
||||
# Create a list of source files so their dependencies can be auto-generated
|
||||
SRCS += $(addprefix $(SRCTREE)/,$(EXT_COBJ_FILES-y:.o=.c))
|
||||
SRCS += $(addprefix $(SRCTREE)/,$(EXT_SOBJ_FILES-y:.o=.S))
|
||||
SRCS += $(addprefix $(SRCTREE)/examples/api/,$(COBJ_FILES-y:.o=.c))
|
||||
SRCS += $(addprefix $(SRCTREE)/examples/api/,$(SOBJ_FILES-y:.o=.S))
|
||||
|
||||
# Create a list of object files to be compiled
|
||||
OBJS += $(addprefix $(obj),$(SOBJ_FILES-y))
|
||||
OBJS += $(addprefix $(obj),$(COBJ_FILES-y))
|
||||
OBJS += $(addprefix $(obj),$(notdir $(EXT_COBJ_FILES-y)))
|
||||
OBJS += $(addprefix $(obj),$(notdir $(EXT_SOBJ_FILES-y)))
|
||||
|
||||
CPPFLAGS += -I..
|
||||
|
||||
all: $(obj).depend $(OUTPUT)
|
||||
|
||||
#########################################################################
|
||||
|
||||
$(OUTPUT): $(OBJS)
|
||||
$(LD) -Ttext $(LOAD_ADDR) -o $@ $^ $(PLATFORM_LIBS)
|
||||
$(OBJCOPY) -O binary $@ $(OUTPUT).bin 2>/dev/null
|
||||
|
||||
# Rule to build generic library C files
|
||||
$(obj)%.o: $(SRCTREE)/lib/%.c
|
||||
$(CC) -g $(CFLAGS) -c -o $@ $<
|
||||
|
||||
# Rule to build architecture-specific library assembly files
|
||||
$(obj)%.o: $(SRCTREE)/arch/$(ARCH)/lib/%.S
|
||||
$(CC) -g $(CFLAGS) -c -o $@ $<
|
||||
|
||||
#########################################################################
|
||||
|
||||
# defines $(obj).depend target
|
||||
include $(SRCTREE)/rules.mk
|
||||
|
||||
sinclude $(obj).depend
|
||||
|
||||
#########################################################################
|
71
root/package/utils/sysupgrade-helper/src/examples/api/crt0.S
Normal file
71
root/package/utils/sysupgrade-helper/src/examples/api/crt0.S
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* (C) Copyright 2007 Semihalf
|
||||
*
|
||||
* Written by: Rafal Jaworowski <raj@semihalf.com>
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_PPC)
|
||||
|
||||
.text
|
||||
.globl _start
|
||||
_start:
|
||||
lis %r11, search_hint@ha
|
||||
addi %r11, %r11, search_hint@l
|
||||
stw %r1, 0(%r11)
|
||||
b main
|
||||
|
||||
|
||||
.globl syscall
|
||||
syscall:
|
||||
lis %r11, syscall_ptr@ha
|
||||
addi %r11, %r11, syscall_ptr@l
|
||||
lwz %r11, 0(%r11)
|
||||
mtctr %r11
|
||||
bctr
|
||||
|
||||
#elif defined(CONFIG_ARM)
|
||||
|
||||
.text
|
||||
.globl _start
|
||||
_start:
|
||||
ldr ip, =search_hint
|
||||
str sp, [ip]
|
||||
b main
|
||||
|
||||
|
||||
.globl syscall
|
||||
syscall:
|
||||
ldr ip, =syscall_ptr
|
||||
ldr pc, [ip]
|
||||
|
||||
#else
|
||||
#error No support for this arch!
|
||||
#endif
|
||||
|
||||
.globl syscall_ptr
|
||||
syscall_ptr:
|
||||
.align 4
|
||||
.long 0
|
||||
|
||||
.globl search_hint
|
||||
search_hint:
|
||||
.long 0
|
331
root/package/utils/sysupgrade-helper/src/examples/api/demo.c
Normal file
331
root/package/utils/sysupgrade-helper/src/examples/api/demo.c
Normal file
|
@ -0,0 +1,331 @@
|
|||
/*
|
||||
* (C) Copyright 2007-2008 Semihalf
|
||||
*
|
||||
* Written by: Rafal Jaworowski <raj@semihalf.com>
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <linux/types.h>
|
||||
#include <api_public.h>
|
||||
|
||||
#include "glue.h"
|
||||
|
||||
#define errf(fmt, args...) do { printf("ERROR @ %s(): ", __func__); printf(fmt, ##args); } while (0)
|
||||
|
||||
#define BUF_SZ 2048
|
||||
#define WAIT_SECS 5
|
||||
|
||||
void test_dump_buf(void *, int);
|
||||
void test_dump_di(int);
|
||||
void test_dump_si(struct sys_info *);
|
||||
void test_dump_sig(struct api_signature *);
|
||||
|
||||
static char buf[BUF_SZ];
|
||||
|
||||
int main(int argc, char * const argv[])
|
||||
{
|
||||
int rv = 0, h, i, j, devs_no;
|
||||
struct api_signature *sig = NULL;
|
||||
ulong start, now;
|
||||
struct device_info *di;
|
||||
lbasize_t rlen;
|
||||
struct display_info disinfo;
|
||||
|
||||
if (!api_search_sig(&sig))
|
||||
return -1;
|
||||
|
||||
syscall_ptr = sig->syscall;
|
||||
if (syscall_ptr == NULL)
|
||||
return -2;
|
||||
|
||||
if (sig->version > API_SIG_VERSION)
|
||||
return -3;
|
||||
|
||||
printf("API signature found @%x\n", (unsigned int)sig);
|
||||
test_dump_sig(sig);
|
||||
|
||||
printf("\n*** Consumer API test ***\n");
|
||||
printf("syscall ptr 0x%08x@%08x\n", (unsigned int)syscall_ptr,
|
||||
(unsigned int)&syscall_ptr);
|
||||
|
||||
/* console activities */
|
||||
ub_putc('B');
|
||||
|
||||
printf("*** Press any key to continue ***\n");
|
||||
printf("got char 0x%x\n", ub_getc());
|
||||
|
||||
/* system info */
|
||||
test_dump_si(ub_get_sys_info());
|
||||
|
||||
/* timing */
|
||||
printf("\n*** Timing - wait a couple of secs ***\n");
|
||||
start = ub_get_timer(0);
|
||||
printf("\ntime: start %lu\n\n", start);
|
||||
for (i = 0; i < WAIT_SECS; i++)
|
||||
for (j = 0; j < 1000; j++)
|
||||
ub_udelay(1000); /* wait 1 ms */
|
||||
|
||||
/* this is the number of milliseconds that passed from ub_get_timer(0) */
|
||||
now = ub_get_timer(start);
|
||||
printf("\ntime: now %lu\n\n", now);
|
||||
|
||||
/* enumerate devices */
|
||||
printf("\n*** Enumerate devices ***\n");
|
||||
devs_no = ub_dev_enum();
|
||||
|
||||
printf("Number of devices found: %d\n", devs_no);
|
||||
if (devs_no == 0)
|
||||
return -1;
|
||||
|
||||
printf("\n*** Show devices ***\n");
|
||||
for (i = 0; i < devs_no; i++) {
|
||||
test_dump_di(i);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
printf("\n*** Operations on devices ***\n");
|
||||
|
||||
/* test opening a device already opened */
|
||||
h = 0;
|
||||
if ((rv = ub_dev_open(h)) != 0) {
|
||||
errf("open device %d error %d\n", h, rv);
|
||||
return -1;
|
||||
}
|
||||
if ((rv = ub_dev_open(h)) != 0)
|
||||
errf("open device %d error %d\n", h, rv);
|
||||
|
||||
ub_dev_close(h);
|
||||
|
||||
/* test storage */
|
||||
printf("Trying storage devices...\n");
|
||||
for (i = 0; i < devs_no; i++) {
|
||||
di = ub_dev_get(i);
|
||||
|
||||
if (di->type & DEV_TYP_STOR)
|
||||
break;
|
||||
|
||||
}
|
||||
if (i == devs_no)
|
||||
printf("No storage devices available\n");
|
||||
else {
|
||||
memset(buf, 0, BUF_SZ);
|
||||
|
||||
if ((rv = ub_dev_open(i)) != 0)
|
||||
errf("open device %d error %d\n", i, rv);
|
||||
|
||||
else if ((rv = ub_dev_read(i, buf, 1, 0, &rlen)) != 0)
|
||||
errf("could not read from device %d, error %d\n", i, rv);
|
||||
else {
|
||||
printf("Sector 0 dump (512B):\n");
|
||||
test_dump_buf(buf, 512);
|
||||
}
|
||||
|
||||
ub_dev_close(i);
|
||||
}
|
||||
|
||||
/* test networking */
|
||||
printf("Trying network devices...\n");
|
||||
for (i = 0; i < devs_no; i++) {
|
||||
di = ub_dev_get(i);
|
||||
|
||||
if (di->type == DEV_TYP_NET)
|
||||
break;
|
||||
|
||||
}
|
||||
if (i == devs_no)
|
||||
printf("No network devices available\n");
|
||||
else {
|
||||
if ((rv = ub_dev_open(i)) != 0)
|
||||
errf("open device %d error %d\n", i, rv);
|
||||
else if ((rv = ub_dev_send(i, &buf, 2048)) != 0)
|
||||
errf("could not send to device %d, error %d\n", i, rv);
|
||||
|
||||
ub_dev_close(i);
|
||||
}
|
||||
|
||||
if (ub_dev_close(h) != 0)
|
||||
errf("could not close device %d\n", h);
|
||||
|
||||
printf("\n*** Env vars ***\n");
|
||||
|
||||
printf("ethact = %s\n", ub_env_get("ethact"));
|
||||
printf("old fileaddr = %s\n", ub_env_get("fileaddr"));
|
||||
ub_env_set("fileaddr", "deadbeef");
|
||||
printf("new fileaddr = %s\n", ub_env_get("fileaddr"));
|
||||
|
||||
const char *env = NULL;
|
||||
|
||||
while ((env = ub_env_enum(env)) != NULL)
|
||||
printf("%s = %s\n", env, ub_env_get(env));
|
||||
|
||||
printf("\n*** Display ***\n");
|
||||
|
||||
if (ub_display_get_info(DISPLAY_TYPE_LCD, &disinfo)) {
|
||||
printf("LCD info: failed\n");
|
||||
} else {
|
||||
printf("LCD info:\n");
|
||||
printf(" pixel width: %d\n", disinfo.pixel_width);
|
||||
printf(" pixel height: %d\n", disinfo.pixel_height);
|
||||
printf(" screen rows: %d\n", disinfo.screen_rows);
|
||||
printf(" screen cols: %d\n", disinfo.screen_cols);
|
||||
}
|
||||
if (ub_display_get_info(DISPLAY_TYPE_VIDEO, &disinfo)) {
|
||||
printf("video info: failed\n");
|
||||
} else {
|
||||
printf("video info:\n");
|
||||
printf(" pixel width: %d\n", disinfo.pixel_width);
|
||||
printf(" pixel height: %d\n", disinfo.pixel_height);
|
||||
printf(" screen rows: %d\n", disinfo.screen_rows);
|
||||
printf(" screen cols: %d\n", disinfo.screen_cols);
|
||||
}
|
||||
|
||||
printf("*** Press any key to continue ***\n");
|
||||
printf("got char 0x%x\n", ub_getc());
|
||||
|
||||
/*
|
||||
* This only clears messages on screen, not on serial port. It is
|
||||
* equivalent to a no-op if no display is available.
|
||||
*/
|
||||
ub_display_clear();
|
||||
|
||||
/* reset */
|
||||
printf("\n*** Resetting board ***\n");
|
||||
ub_reset();
|
||||
printf("\nHmm, reset returned...?!\n");
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void test_dump_sig(struct api_signature *sig)
|
||||
{
|
||||
printf("signature:\n");
|
||||
printf(" version\t= %d\n", sig->version);
|
||||
printf(" checksum\t= 0x%08x\n", sig->checksum);
|
||||
printf(" sc entry\t= 0x%08x\n", (unsigned int)sig->syscall);
|
||||
}
|
||||
|
||||
void test_dump_si(struct sys_info *si)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("sys info:\n");
|
||||
printf(" clkbus\t= 0x%08x\n", (unsigned int)si->clk_bus);
|
||||
printf(" clkcpu\t= 0x%08x\n", (unsigned int)si->clk_cpu);
|
||||
printf(" bar\t\t= 0x%08x\n", (unsigned int)si->bar);
|
||||
|
||||
printf("---\n");
|
||||
for (i = 0; i < si->mr_no; i++) {
|
||||
if (si->mr[i].flags == 0)
|
||||
break;
|
||||
|
||||
printf(" start\t= 0x%08lx\n", si->mr[i].start);
|
||||
printf(" size\t= 0x%08lx\n", si->mr[i].size);
|
||||
|
||||
switch(si->mr[i].flags & 0x000F) {
|
||||
case MR_ATTR_FLASH:
|
||||
printf(" type FLASH\n");
|
||||
break;
|
||||
case MR_ATTR_DRAM:
|
||||
printf(" type DRAM\n");
|
||||
break;
|
||||
case MR_ATTR_SRAM:
|
||||
printf(" type SRAM\n");
|
||||
break;
|
||||
default:
|
||||
printf(" type UNKNOWN\n");
|
||||
}
|
||||
printf("---\n");
|
||||
}
|
||||
}
|
||||
|
||||
static char *test_stor_typ(int type)
|
||||
{
|
||||
if (type & DT_STOR_IDE)
|
||||
return "IDE";
|
||||
|
||||
if (type & DT_STOR_MMC)
|
||||
return "MMC";
|
||||
|
||||
if (type & DT_STOR_SATA)
|
||||
return "SATA";
|
||||
|
||||
if (type & DT_STOR_SCSI)
|
||||
return "SCSI";
|
||||
|
||||
if (type & DT_STOR_USB)
|
||||
return "USB";
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
void test_dump_buf(void *buf, int len)
|
||||
{
|
||||
int i;
|
||||
int line_counter = 0;
|
||||
int sep_flag = 0;
|
||||
int addr = 0;
|
||||
|
||||
printf("%07x:\t", addr);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (line_counter++ > 15) {
|
||||
line_counter = 0;
|
||||
sep_flag = 0;
|
||||
addr += 16;
|
||||
i--;
|
||||
printf("\n%07x:\t", addr);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sep_flag++ > 1) {
|
||||
sep_flag = 1;
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
printf("%02x", *((char *)buf++));
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void test_dump_di(int handle)
|
||||
{
|
||||
int i;
|
||||
struct device_info *di = ub_dev_get(handle);
|
||||
|
||||
printf("device info (%d):\n", handle);
|
||||
printf(" cookie\t= 0x%08x\n", (uint32_t)di->cookie);
|
||||
printf(" type\t\t= 0x%08x\n", di->type);
|
||||
|
||||
if (di->type == DEV_TYP_NET) {
|
||||
printf(" hwaddr\t= ");
|
||||
for (i = 0; i < 6; i++)
|
||||
printf("%02x ", di->di_net.hwaddr[i]);
|
||||
|
||||
printf("\n");
|
||||
|
||||
} else if (di->type & DEV_TYP_STOR) {
|
||||
printf(" type\t\t= %s\n", test_stor_typ(di->type));
|
||||
printf(" blk size\t\t= %d\n", (unsigned int)di->di_stor.block_size);
|
||||
printf(" blk count\t\t= %d\n", (unsigned int)di->di_stor.block_count);
|
||||
}
|
||||
}
|
435
root/package/utils/sysupgrade-helper/src/examples/api/glue.c
Normal file
435
root/package/utils/sysupgrade-helper/src/examples/api/glue.c
Normal file
|
@ -0,0 +1,435 @@
|
|||
/*
|
||||
* (C) Copyright 2007-2008 Semihalf, Rafal Jaworowski <raj@semihalf.com>
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <linux/types.h>
|
||||
#include <api_public.h>
|
||||
|
||||
#include "glue.h"
|
||||
|
||||
static int valid_sig(struct api_signature *sig)
|
||||
{
|
||||
uint32_t checksum;
|
||||
struct api_signature s;
|
||||
|
||||
if (sig == NULL)
|
||||
return 0;
|
||||
/*
|
||||
* Clear the checksum field (in the local copy) so as to calculate the
|
||||
* CRC with the same initial contents as at the time when the sig was
|
||||
* produced
|
||||
*/
|
||||
s = *sig;
|
||||
s.checksum = 0;
|
||||
|
||||
checksum = crc32(0, (unsigned char *)&s, sizeof(struct api_signature));
|
||||
|
||||
if (checksum != sig->checksum)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Searches for the U-Boot API signature
|
||||
*
|
||||
* returns 1/0 depending on found/not found result
|
||||
*/
|
||||
int api_search_sig(struct api_signature **sig)
|
||||
{
|
||||
unsigned char *sp;
|
||||
uint32_t search_start = 0;
|
||||
uint32_t search_end = 0;
|
||||
|
||||
if (sig == NULL)
|
||||
return 0;
|
||||
|
||||
if (search_hint == 0)
|
||||
search_hint = 255 * 1024 * 1024;
|
||||
|
||||
search_start = search_hint & ~0x000fffff;
|
||||
search_end = search_start + API_SEARCH_LEN - API_SIG_MAGLEN;
|
||||
|
||||
sp = (unsigned char *)search_start;
|
||||
while ((sp + API_SIG_MAGLEN) < (unsigned char *)search_end) {
|
||||
if (!memcmp(sp, API_SIG_MAGIC, API_SIG_MAGLEN)) {
|
||||
*sig = (struct api_signature *)sp;
|
||||
if (valid_sig(*sig))
|
||||
return 1;
|
||||
}
|
||||
sp += API_SIG_MAGLEN;
|
||||
}
|
||||
|
||||
*sig = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************
|
||||
*
|
||||
* console
|
||||
*
|
||||
****************************************/
|
||||
|
||||
int ub_getc(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
if (!syscall(API_GETC, NULL, (uint32_t)&c))
|
||||
return -1;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
int ub_tstc(void)
|
||||
{
|
||||
int t;
|
||||
|
||||
if (!syscall(API_TSTC, NULL, (uint32_t)&t))
|
||||
return -1;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
void ub_putc(char c)
|
||||
{
|
||||
syscall(API_PUTC, NULL, (uint32_t)&c);
|
||||
}
|
||||
|
||||
void ub_puts(const char *s)
|
||||
{
|
||||
syscall(API_PUTS, NULL, (uint32_t)s);
|
||||
}
|
||||
|
||||
/****************************************
|
||||
*
|
||||
* system
|
||||
*
|
||||
****************************************/
|
||||
|
||||
void ub_reset(void)
|
||||
{
|
||||
syscall(API_RESET, NULL);
|
||||
}
|
||||
|
||||
static struct mem_region mr[UB_MAX_MR];
|
||||
static struct sys_info si;
|
||||
|
||||
struct sys_info * ub_get_sys_info(void)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
memset(&si, 0, sizeof(struct sys_info));
|
||||
si.mr = mr;
|
||||
si.mr_no = UB_MAX_MR;
|
||||
memset(&mr, 0, sizeof(mr));
|
||||
|
||||
if (!syscall(API_GET_SYS_INFO, &err, (u_int32_t)&si))
|
||||
return NULL;
|
||||
|
||||
return ((err) ? NULL : &si);
|
||||
}
|
||||
|
||||
/****************************************
|
||||
*
|
||||
* timing
|
||||
*
|
||||
****************************************/
|
||||
|
||||
void ub_udelay(unsigned long usec)
|
||||
{
|
||||
syscall(API_UDELAY, NULL, &usec);
|
||||
}
|
||||
|
||||
unsigned long ub_get_timer(unsigned long base)
|
||||
{
|
||||
unsigned long cur;
|
||||
|
||||
if (!syscall(API_GET_TIMER, NULL, &cur, &base))
|
||||
return 0;
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* devices
|
||||
*
|
||||
* Devices are identified by handles: numbers 0, 1, 2, ..., UB_MAX_DEV-1
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
static struct device_info devices[UB_MAX_DEV];
|
||||
|
||||
struct device_info * ub_dev_get(int i)
|
||||
{
|
||||
return ((i < 0 || i >= UB_MAX_DEV) ? NULL : &devices[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enumerates the devices: fills out device_info elements in the devices[]
|
||||
* array.
|
||||
*
|
||||
* returns: number of devices found
|
||||
*/
|
||||
int ub_dev_enum(void)
|
||||
{
|
||||
struct device_info *di;
|
||||
int n = 0;
|
||||
|
||||
memset(&devices, 0, sizeof(struct device_info) * UB_MAX_DEV);
|
||||
di = &devices[0];
|
||||
|
||||
if (!syscall(API_DEV_ENUM, NULL, di))
|
||||
return 0;
|
||||
|
||||
while (di->cookie != NULL) {
|
||||
|
||||
if (++n >= UB_MAX_DEV)
|
||||
break;
|
||||
|
||||
/* take another device_info */
|
||||
di++;
|
||||
|
||||
/* pass on the previous cookie */
|
||||
di->cookie = devices[n - 1].cookie;
|
||||
|
||||
if (!syscall(API_DEV_ENUM, NULL, di))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
* handle: 0-based id of the device
|
||||
*
|
||||
* returns: 0 when OK, err otherwise
|
||||
*/
|
||||
int ub_dev_open(int handle)
|
||||
{
|
||||
struct device_info *di;
|
||||
int err = 0;
|
||||
|
||||
if (handle < 0 || handle >= UB_MAX_DEV)
|
||||
return API_EINVAL;
|
||||
|
||||
di = &devices[handle];
|
||||
|
||||
if (!syscall(API_DEV_OPEN, &err, di))
|
||||
return -1;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int ub_dev_close(int handle)
|
||||
{
|
||||
struct device_info *di;
|
||||
|
||||
if (handle < 0 || handle >= UB_MAX_DEV)
|
||||
return API_EINVAL;
|
||||
|
||||
di = &devices[handle];
|
||||
if (!syscall(API_DEV_CLOSE, NULL, di))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Validates device for read/write, it has to:
|
||||
*
|
||||
* - have sane handle
|
||||
* - be opened
|
||||
*
|
||||
* returns: 0/1 accordingly
|
||||
*/
|
||||
static int dev_valid(int handle)
|
||||
{
|
||||
if (handle < 0 || handle >= UB_MAX_DEV)
|
||||
return 0;
|
||||
|
||||
if (devices[handle].state != DEV_STA_OPEN)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dev_stor_valid(int handle)
|
||||
{
|
||||
if (!dev_valid(handle))
|
||||
return 0;
|
||||
|
||||
if (!(devices[handle].type & DEV_TYP_STOR))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ub_dev_read(int handle, void *buf, lbasize_t len, lbastart_t start,
|
||||
lbasize_t *rlen)
|
||||
{
|
||||
struct device_info *di;
|
||||
lbasize_t act_len;
|
||||
int err = 0;
|
||||
|
||||
if (!dev_stor_valid(handle))
|
||||
return API_ENODEV;
|
||||
|
||||
di = &devices[handle];
|
||||
if (!syscall(API_DEV_READ, &err, di, buf, &len, &start, &act_len))
|
||||
return API_ESYSC;
|
||||
|
||||
if (!err && rlen)
|
||||
*rlen = act_len;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int dev_net_valid(int handle)
|
||||
{
|
||||
if (!dev_valid(handle))
|
||||
return 0;
|
||||
|
||||
if (devices[handle].type != DEV_TYP_NET)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ub_dev_recv(int handle, void *buf, int len, int *rlen)
|
||||
{
|
||||
struct device_info *di;
|
||||
int err = 0, act_len;
|
||||
|
||||
if (!dev_net_valid(handle))
|
||||
return API_ENODEV;
|
||||
|
||||
di = &devices[handle];
|
||||
if (!syscall(API_DEV_READ, &err, di, buf, &len, &act_len))
|
||||
return API_ESYSC;
|
||||
|
||||
if (!err && rlen)
|
||||
*rlen = act_len;
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
int ub_dev_send(int handle, void *buf, int len)
|
||||
{
|
||||
struct device_info *di;
|
||||
int err = 0;
|
||||
|
||||
if (!dev_net_valid(handle))
|
||||
return API_ENODEV;
|
||||
|
||||
di = &devices[handle];
|
||||
if (!syscall(API_DEV_WRITE, &err, di, buf, &len))
|
||||
return API_ESYSC;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/****************************************
|
||||
*
|
||||
* env vars
|
||||
*
|
||||
****************************************/
|
||||
|
||||
char * ub_env_get(const char *name)
|
||||
{
|
||||
char *value;
|
||||
|
||||
if (!syscall(API_ENV_GET, NULL, (uint32_t)name, (uint32_t)&value))
|
||||
return NULL;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void ub_env_set(const char *name, char *value)
|
||||
{
|
||||
syscall(API_ENV_SET, NULL, (uint32_t)name, (uint32_t)value);
|
||||
}
|
||||
|
||||
static char env_name[256];
|
||||
|
||||
const char * ub_env_enum(const char *last)
|
||||
{
|
||||
const char *env, *str;
|
||||
int i;
|
||||
|
||||
env = NULL;
|
||||
|
||||
/*
|
||||
* It's OK to pass only the name piece as last (and not the whole
|
||||
* 'name=val' string), since the API_ENUM_ENV call uses envmatch()
|
||||
* internally, which handles such case
|
||||
*/
|
||||
if (!syscall(API_ENV_ENUM, NULL, (uint32_t)last, (uint32_t)&env))
|
||||
return NULL;
|
||||
|
||||
if (!env)
|
||||
/* no more env. variables to enumerate */
|
||||
return NULL;
|
||||
|
||||
/* next enumerated env var */
|
||||
memset(env_name, 0, 256);
|
||||
for (i = 0, str = env; *str != '=' && *str != '\0';)
|
||||
env_name[i++] = *str++;
|
||||
|
||||
env_name[i] = '\0';
|
||||
|
||||
return env_name;
|
||||
}
|
||||
|
||||
/****************************************
|
||||
*
|
||||
* display
|
||||
*
|
||||
****************************************/
|
||||
|
||||
int ub_display_get_info(int type, struct display_info *di)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (!syscall(API_DISPLAY_GET_INFO, &err, (uint32_t)type, (uint32_t)di))
|
||||
return API_ESYSC;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int ub_display_draw_bitmap(ulong bitmap, int x, int y)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (!syscall(API_DISPLAY_DRAW_BITMAP, &err, bitmap, x, y))
|
||||
return API_ESYSC;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void ub_display_clear(void)
|
||||
{
|
||||
syscall(API_DISPLAY_CLEAR, NULL);
|
||||
}
|
85
root/package/utils/sysupgrade-helper/src/examples/api/glue.h
Normal file
85
root/package/utils/sysupgrade-helper/src/examples/api/glue.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* (C) Copyright 2007 Semihalf
|
||||
*
|
||||
* Written by: Rafal Jaworowski <raj@semihalf.com>
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is the header file for conveniency wrapper routines (API glue)
|
||||
*/
|
||||
|
||||
#ifndef _API_GLUE_H_
|
||||
#define _API_GLUE_H_
|
||||
|
||||
#define API_SEARCH_LEN (3 * 1024 * 1024) /* 3MB search range */
|
||||
|
||||
#define UB_MAX_MR 5 /* max mem regions number */
|
||||
#define UB_MAX_DEV 6 /* max devices number */
|
||||
|
||||
extern void *syscall_ptr;
|
||||
extern uint32_t search_hint;
|
||||
|
||||
int syscall(int, int *, ...);
|
||||
int api_search_sig(struct api_signature **sig);
|
||||
|
||||
/*
|
||||
* The ub_ library calls are part of the application, not U-Boot code! They
|
||||
* are front-end wrappers that are used by the consumer application: they
|
||||
* prepare arguments for particular syscall and jump to the low level
|
||||
* syscall()
|
||||
*/
|
||||
|
||||
/* console */
|
||||
int ub_getc(void);
|
||||
int ub_tstc(void);
|
||||
void ub_putc(char c);
|
||||
void ub_puts(const char *s);
|
||||
|
||||
/* system */
|
||||
void ub_reset(void);
|
||||
struct sys_info * ub_get_sys_info(void);
|
||||
|
||||
/* time */
|
||||
void ub_udelay(unsigned long);
|
||||
unsigned long ub_get_timer(unsigned long);
|
||||
|
||||
/* env vars */
|
||||
char * ub_env_get(const char *name);
|
||||
void ub_env_set(const char *name, char *value);
|
||||
const char * ub_env_enum(const char *last);
|
||||
|
||||
/* devices */
|
||||
int ub_dev_enum(void);
|
||||
int ub_dev_open(int handle);
|
||||
int ub_dev_close(int handle);
|
||||
int ub_dev_read(int handle, void *buf, lbasize_t len,
|
||||
lbastart_t start, lbasize_t *rlen);
|
||||
int ub_dev_send(int handle, void *buf, int len);
|
||||
int ub_dev_recv(int handle, void *buf, int len, int *rlen);
|
||||
struct device_info * ub_dev_get(int);
|
||||
|
||||
/* display */
|
||||
int ub_display_get_info(int type, struct display_info *di);
|
||||
int ub_display_draw_bitmap(ulong bitmap, int x, int y);
|
||||
void ub_display_clear(void);
|
||||
|
||||
#endif /* _API_GLUE_H_ */
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* (C) Copyright 2007 Semihalf
|
||||
*
|
||||
* Written by: Rafal Jaworowski <raj@semihalf.com>
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
*
|
||||
* This is is a set of wrappers/stubs that allow to use certain routines from
|
||||
* U-Boot's lib in the standalone app. This way way we can re-use
|
||||
* existing code e.g. operations on strings and similar.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <linux/types.h>
|
||||
#include <api_public.h>
|
||||
|
||||
#include "glue.h"
|
||||
|
||||
/*
|
||||
* printf() and vprintf() are stolen from u-boot/common/console.c
|
||||
*/
|
||||
int printf (const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
uint i;
|
||||
char printbuffer[256];
|
||||
|
||||
va_start (args, fmt);
|
||||
|
||||
/* For this to work, printbuffer must be larger than
|
||||
* anything we ever want to print.
|
||||
*/
|
||||
i = vsprintf (printbuffer, fmt, args);
|
||||
va_end (args);
|
||||
|
||||
/* Print the string */
|
||||
ub_puts (printbuffer);
|
||||
return i;
|
||||
}
|
||||
|
||||
int vprintf (const char *fmt, va_list args)
|
||||
{
|
||||
uint i;
|
||||
char printbuffer[256];
|
||||
|
||||
/* For this to work, printbuffer must be larger than
|
||||
* anything we ever want to print.
|
||||
*/
|
||||
i = vsprintf (printbuffer, fmt, args);
|
||||
|
||||
/* Print the string */
|
||||
ub_puts (printbuffer);
|
||||
return i;
|
||||
}
|
||||
|
||||
void putc (const char c)
|
||||
{
|
||||
ub_putc(c);
|
||||
}
|
||||
|
||||
void __udelay(unsigned long usec)
|
||||
{
|
||||
ub_udelay(usec);
|
||||
}
|
||||
|
||||
int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
ub_reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *malloc (size_t len)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void hang (void)
|
||||
{
|
||||
while (1) ;
|
||||
}
|
13
root/package/utils/sysupgrade-helper/src/examples/standalone/.gitignore
vendored
Normal file
13
root/package/utils/sysupgrade-helper/src/examples/standalone/.gitignore
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
/82559_eeprom
|
||||
/atmel_df_pow2
|
||||
/eepro100_eeprom
|
||||
/hello_world
|
||||
/interrupt
|
||||
/mem_to_mem_idma2intr
|
||||
/sched
|
||||
/smc91111_eeprom
|
||||
/smc911x_eeprom
|
||||
/test_burst
|
||||
/timer
|
||||
*.bin
|
||||
*.srec
|
|
@ -0,0 +1,357 @@
|
|||
|
||||
/*
|
||||
* Copyright 1998-2001 by Donald Becker.
|
||||
* This software may be used and distributed according to the terms of
|
||||
* the GNU General Public License (GPL), incorporated herein by reference.
|
||||
* Contact the author for use under other terms.
|
||||
*
|
||||
* This program must be compiled with "-O"!
|
||||
* See the bottom of this file for the suggested compile-command.
|
||||
*
|
||||
* The author may be reached as becker@scyld.com, or C/O
|
||||
* Scyld Computing Corporation
|
||||
* 410 Severn Ave., Suite 210
|
||||
* Annapolis MD 21403
|
||||
*
|
||||
* Common-sense licensing statement: Using any portion of this program in
|
||||
* your own program means that you must give credit to the original author
|
||||
* and release the resulting code under the GPL.
|
||||
*/
|
||||
|
||||
#define _PPC_STRING_H_ /* avoid unnecessary str/mem functions */
|
||||
|
||||
#include <common.h>
|
||||
#include <exports.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
|
||||
/* Default EEPROM for i82559 */
|
||||
static unsigned short default_eeprom[64] = {
|
||||
0x0100, 0x0302, 0x0504, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0x40c0, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
|
||||
};
|
||||
|
||||
static unsigned short eeprom[256];
|
||||
|
||||
static int eeprom_size = 64;
|
||||
static int eeprom_addr_size = 6;
|
||||
|
||||
static int debug = 0;
|
||||
|
||||
static inline unsigned short swap16(unsigned short x)
|
||||
{
|
||||
return (((x & 0xff) << 8) | ((x & 0xff00) >> 8));
|
||||
}
|
||||
|
||||
|
||||
void * memcpy(void * dest,const void *src,size_t count)
|
||||
{
|
||||
char *tmp = (char *) dest, *s = (char *) src;
|
||||
|
||||
while (count--)
|
||||
*tmp++ = *s++;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
/* The EEPROM commands include the alway-set leading bit. */
|
||||
#define EE_WRITE_CMD (5)
|
||||
#define EE_READ_CMD (6)
|
||||
#define EE_ERASE_CMD (7)
|
||||
|
||||
/* Serial EEPROM section. */
|
||||
#define EE_SHIFT_CLK 0x01 /* EEPROM shift clock. */
|
||||
#define EE_CS 0x02 /* EEPROM chip select. */
|
||||
#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */
|
||||
#define EE_DATA_READ 0x08 /* EEPROM chip data out. */
|
||||
#define EE_ENB (0x4800 | EE_CS)
|
||||
#define EE_WRITE_0 0x4802
|
||||
#define EE_WRITE_1 0x4806
|
||||
#define EE_OFFSET 14
|
||||
|
||||
/* Delay between EEPROM clock transitions. */
|
||||
#define eeprom_delay(ee_addr) inw(ee_addr)
|
||||
|
||||
/* Wait for the EEPROM to finish the previous operation. */
|
||||
static int eeprom_busy_poll(long ee_ioaddr)
|
||||
{
|
||||
int i;
|
||||
outw(EE_ENB, ee_ioaddr);
|
||||
for (i = 0; i < 10000; i++) /* Typical 2000 ticks */
|
||||
if (inw(ee_ioaddr) & EE_DATA_READ)
|
||||
break;
|
||||
return i;
|
||||
}
|
||||
|
||||
/* This executes a generic EEPROM command, typically a write or write enable.
|
||||
It returns the data output from the EEPROM, and thus may also be used for
|
||||
reads. */
|
||||
static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len)
|
||||
{
|
||||
unsigned retval = 0;
|
||||
long ee_addr = ioaddr + EE_OFFSET;
|
||||
|
||||
if (debug > 1)
|
||||
printf(" EEPROM op 0x%x: ", cmd);
|
||||
|
||||
outw(EE_ENB | EE_SHIFT_CLK, ee_addr);
|
||||
|
||||
/* Shift the command bits out. */
|
||||
do {
|
||||
short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0;
|
||||
outw(dataval, ee_addr);
|
||||
eeprom_delay(ee_addr);
|
||||
if (debug > 2)
|
||||
printf("%X", inw(ee_addr) & 15);
|
||||
outw(dataval | EE_SHIFT_CLK, ee_addr);
|
||||
eeprom_delay(ee_addr);
|
||||
retval = (retval << 1) | ((inw(ee_addr) & EE_DATA_READ) ? 1 : 0);
|
||||
} while (--cmd_len >= 0);
|
||||
#if 0
|
||||
outw(EE_ENB, ee_addr);
|
||||
#endif
|
||||
/* Terminate the EEPROM access. */
|
||||
outw(EE_ENB & ~EE_CS, ee_addr);
|
||||
if (debug > 1)
|
||||
printf(" EEPROM result is 0x%5.5x.\n", retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int read_eeprom(long ioaddr, int location, int addr_len)
|
||||
{
|
||||
return do_eeprom_cmd(ioaddr, ((EE_READ_CMD << addr_len) | location)
|
||||
<< 16 , 3 + addr_len + 16) & 0xffff;
|
||||
}
|
||||
|
||||
static void write_eeprom(long ioaddr, int index, int value, int addr_len)
|
||||
{
|
||||
long ee_ioaddr = ioaddr + EE_OFFSET;
|
||||
int i;
|
||||
|
||||
/* Poll for previous op finished. */
|
||||
eeprom_busy_poll(ee_ioaddr); /* Typical 0 ticks */
|
||||
/* Enable programming modes. */
|
||||
do_eeprom_cmd(ioaddr, (0x4f << (addr_len-4)), 3 + addr_len);
|
||||
/* Do the actual write. */
|
||||
do_eeprom_cmd(ioaddr,
|
||||
(((EE_WRITE_CMD<<addr_len) | index)<<16) | (value & 0xffff),
|
||||
3 + addr_len + 16);
|
||||
/* Poll for write finished. */
|
||||
i = eeprom_busy_poll(ee_ioaddr); /* Typical 2000 ticks */
|
||||
if (debug)
|
||||
printf(" Write finished after %d ticks.\n", i);
|
||||
/* Disable programming. This command is not instantaneous, so we check
|
||||
for busy before the next op. */
|
||||
do_eeprom_cmd(ioaddr, (0x40 << (addr_len-4)), 3 + addr_len);
|
||||
eeprom_busy_poll(ee_ioaddr);
|
||||
}
|
||||
|
||||
static int reset_eeprom(unsigned long ioaddr, unsigned char *hwaddr)
|
||||
{
|
||||
unsigned short checksum = 0;
|
||||
int size_test;
|
||||
int i;
|
||||
|
||||
printf("Resetting i82559 EEPROM @ 0x%08lx ... ", ioaddr);
|
||||
|
||||
size_test = do_eeprom_cmd(ioaddr, (EE_READ_CMD << 8) << 16, 27);
|
||||
eeprom_addr_size = (size_test & 0xffe0000) == 0xffe0000 ? 8 : 6;
|
||||
eeprom_size = 1 << eeprom_addr_size;
|
||||
|
||||
memcpy(eeprom, default_eeprom, sizeof default_eeprom);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
eeprom[i] = (hwaddr[i*2+1]<<8) + hwaddr[i*2];
|
||||
|
||||
/* Recalculate the checksum. */
|
||||
for (i = 0; i < eeprom_size - 1; i++)
|
||||
checksum += eeprom[i];
|
||||
eeprom[i] = 0xBABA - checksum;
|
||||
|
||||
for (i = 0; i < eeprom_size; i++)
|
||||
write_eeprom(ioaddr, i, eeprom[i], eeprom_addr_size);
|
||||
|
||||
for (i = 0; i < eeprom_size; i++)
|
||||
if (read_eeprom(ioaddr, i, eeprom_addr_size) != eeprom[i]) {
|
||||
printf("failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("done\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int hatoi(char *p, char **errp)
|
||||
{
|
||||
unsigned int res = 0;
|
||||
|
||||
while (1) {
|
||||
switch (*p) {
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
res |= (*p - 'a' + 10);
|
||||
break;
|
||||
case 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F':
|
||||
res |= (*p - 'A' + 10);
|
||||
break;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
res |= (*p - '0');
|
||||
break;
|
||||
default:
|
||||
if (errp) {
|
||||
*errp = p;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
p++;
|
||||
if (*p == 0) {
|
||||
break;
|
||||
}
|
||||
res <<= 4;
|
||||
}
|
||||
|
||||
if (errp) {
|
||||
*errp = NULL;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static unsigned char *gethwaddr(char *in, unsigned char *out)
|
||||
{
|
||||
char tmp[3];
|
||||
int i;
|
||||
char *err;
|
||||
|
||||
for (i=0;i<6;i++) {
|
||||
if (in[i*3+2] == 0 && i == 5) {
|
||||
out[i] = hatoi(&in[i*3], &err);
|
||||
if (err) {
|
||||
return NULL;
|
||||
}
|
||||
} else if (in[i*3+2] == ':' && i < 5) {
|
||||
tmp[0] = in[i*3];
|
||||
tmp[1] = in[i*3+1];
|
||||
tmp[2] = 0;
|
||||
out[i] = hatoi(tmp, &err);
|
||||
if (err) {
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static u32
|
||||
read_config_dword(int bus, int dev, int func, int reg)
|
||||
{
|
||||
u32 res;
|
||||
|
||||
outl(0x80000000|(bus&0xff)<<16|(dev&0x1f)<<11|(func&7)<<8|(reg&0xfc),
|
||||
0xcf8);
|
||||
res = inl(0xcfc);
|
||||
outl(0, 0xcf8);
|
||||
return res;
|
||||
}
|
||||
|
||||
static u16
|
||||
read_config_word(int bus, int dev, int func, int reg)
|
||||
{
|
||||
u32 res;
|
||||
|
||||
outl(0x80000000|(bus&0xff)<<16|(dev&0x1f)<<11|(func&7)<<8|(reg&0xfc),
|
||||
0xcf8);
|
||||
res = inw(0xcfc + (reg & 2));
|
||||
outl(0, 0xcf8);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
write_config_word(int bus, int dev, int func, int reg, u16 data)
|
||||
{
|
||||
|
||||
outl(0x80000000|(bus&0xff)<<16|(dev&0x1f)<<11|(func&7)<<8|(reg&0xfc),
|
||||
0xcf8);
|
||||
outw(data, 0xcfc + (reg & 2));
|
||||
outl(0, 0xcf8);
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char * const argv[])
|
||||
{
|
||||
unsigned char *eth_addr;
|
||||
uchar buf[6];
|
||||
int instance;
|
||||
|
||||
app_startup(argv);
|
||||
if (argc != 2) {
|
||||
printf ("call with base Ethernet address\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
eth_addr = gethwaddr(argv[1], buf);
|
||||
if (NULL == eth_addr) {
|
||||
printf ("Can not parse ethernet address\n");
|
||||
return 1;
|
||||
}
|
||||
if (eth_addr[5] & 0x01) {
|
||||
printf("Base Ethernet address must be even\n");
|
||||
}
|
||||
|
||||
|
||||
for (instance = 0; instance < 2; instance ++) {
|
||||
unsigned int io_addr;
|
||||
unsigned char mac[6];
|
||||
int bar1 = read_config_dword(0, 6+instance, 0, 0x14);
|
||||
if (! (bar1 & 1)) {
|
||||
printf("ETH%d is disabled %x\n", instance, bar1);
|
||||
} else {
|
||||
printf("ETH%d IO=0x%04x\n", instance, bar1 & ~3);
|
||||
}
|
||||
io_addr = (bar1 & (~3L));
|
||||
|
||||
|
||||
write_config_word(0, 6+instance, 0, 4,
|
||||
read_config_word(0, 6+instance, 0, 4) | 1);
|
||||
printf("ETH%d CMD %04x\n", instance,
|
||||
read_config_word(0, 6+instance, 0, 4));
|
||||
|
||||
memcpy(mac, eth_addr, 6);
|
||||
mac[5] += instance;
|
||||
|
||||
printf("got io=%04x, ha=%02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
io_addr, mac[0], mac[1], mac[2],
|
||||
mac[3], mac[4], mac[5]);
|
||||
reset_eeprom(io_addr, mac);
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
#
|
||||
# (C) Copyright 2000-2006
|
||||
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
#
|
||||
# See file CREDITS for list of people who contributed to this
|
||||
# project.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 2 of
|
||||
# the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
# MA 02111-1307 USA
|
||||
#
|
||||
|
||||
include $(TOPDIR)/config.mk
|
||||
|
||||
ELF-$(ARCH) :=
|
||||
ELF-$(BOARD) :=
|
||||
ELF-$(CPU) :=
|
||||
ELF-y := hello_world
|
||||
|
||||
ELF-$(CONFIG_SMC91111) += smc91111_eeprom
|
||||
ELF-$(CONFIG_SMC911X) += smc911x_eeprom
|
||||
ELF-$(CONFIG_SPI_FLASH_ATMEL) += atmel_df_pow2
|
||||
ELF-i386 += 82559_eeprom
|
||||
ELF-mpc5xxx += interrupt
|
||||
ELF-mpc8xx += test_burst timer
|
||||
ELF-mpc8260 += mem_to_mem_idma2intr
|
||||
ELF-ppc += sched
|
||||
ELF-oxc += eepro100_eeprom
|
||||
|
||||
#
|
||||
# Some versions of make do not handle trailing white spaces properly;
|
||||
# leading to build failures. The problem was found with GNU Make 3.80.
|
||||
# Using 'strip' as a workaround for the problem.
|
||||
#
|
||||
ELF := $(strip $(ELF-y) $(ELF-$(ARCH)) $(ELF-$(BOARD)) $(ELF-$(CPU)))
|
||||
|
||||
SREC := $(addsuffix .srec,$(ELF))
|
||||
BIN := $(addsuffix .bin,$(ELF))
|
||||
|
||||
COBJS := $(ELF:=.o)
|
||||
|
||||
LIB = $(obj)libstubs.o
|
||||
|
||||
LIBAOBJS-$(ARCH) :=
|
||||
LIBAOBJS-$(CPU) :=
|
||||
LIBAOBJS-ppc += $(ARCH)_longjmp.o $(ARCH)_setjmp.o
|
||||
LIBAOBJS-mpc8xx += test_burst_lib.o
|
||||
LIBAOBJS := $(LIBAOBJS-$(ARCH)) $(LIBAOBJS-$(CPU))
|
||||
|
||||
LIBCOBJS = stubs.o
|
||||
|
||||
LIBOBJS = $(addprefix $(obj),$(LIBAOBJS) $(LIBCOBJS))
|
||||
|
||||
SRCS := $(COBJS:.o=.c) $(LIBCOBJS:.o=.c) $(LIBAOBJS:.o=.S)
|
||||
OBJS := $(addprefix $(obj),$(COBJS))
|
||||
ELF := $(addprefix $(obj),$(ELF))
|
||||
BIN := $(addprefix $(obj),$(BIN))
|
||||
SREC := $(addprefix $(obj),$(SREC))
|
||||
|
||||
gcclibdir := $(shell dirname `$(CC) -print-libgcc-file-name`)
|
||||
|
||||
CPPFLAGS += -I..
|
||||
|
||||
# For PowerPC there's no need to compile standalone applications as a
|
||||
# relocatable executable. The relocation data is not needed, and
|
||||
# also causes the entry point of the standalone application to be
|
||||
# inconsistent.
|
||||
ifeq ($(ARCH),powerpc)
|
||||
AFLAGS := $(filter-out $(RELFLAGS),$(AFLAGS))
|
||||
CFLAGS := $(filter-out $(RELFLAGS),$(CFLAGS))
|
||||
CPPFLAGS := $(filter-out $(RELFLAGS),$(CPPFLAGS))
|
||||
endif
|
||||
|
||||
# We don't want gcc reordering functions if possible. This ensures that an
|
||||
# application's entry point will be the first function in the application's
|
||||
# source file.
|
||||
CFLAGS_NTR := $(call cc-option,-fno-toplevel-reorder)
|
||||
CFLAGS += $(CFLAGS_NTR)
|
||||
|
||||
all: $(obj).depend $(OBJS) $(LIB) $(SREC) $(BIN) $(ELF)
|
||||
|
||||
#########################################################################
|
||||
$(LIB): $(obj).depend $(LIBOBJS)
|
||||
$(call cmd_link_o_target, $(LIBOBJS))
|
||||
|
||||
$(ELF):
|
||||
$(obj)%: $(obj)%.o $(LIB)
|
||||
$(LD) $(LDFLAGS) -g -Ttext $(CONFIG_STANDALONE_LOAD_ADDR) \
|
||||
-o $@ -e $(SYM_PREFIX)$(notdir $(<:.o=)) $< $(LIB) \
|
||||
-L$(gcclibdir) -lgcc
|
||||
|
||||
$(SREC):
|
||||
$(obj)%.srec: $(obj)%
|
||||
$(OBJCOPY) -O srec $< $@ 2>/dev/null
|
||||
|
||||
$(BIN):
|
||||
$(obj)%.bin: $(obj)%
|
||||
$(OBJCOPY) -O binary $< $@ 2>/dev/null
|
||||
|
||||
#########################################################################
|
||||
|
||||
# defines $(obj).depend target
|
||||
include $(SRCTREE)/rules.mk
|
||||
|
||||
sinclude $(obj).depend
|
||||
|
||||
#########################################################################
|
|
@ -0,0 +1,246 @@
|
|||
This is the readme for the Das U-Boot standalone program smc91111
|
||||
|
||||
The main purpose of this is to manage MAC addresses on platforms
|
||||
which include the SMC91111 integrated 10/100 MAC Phy, with attached
|
||||
EEPROMs.
|
||||
|
||||
|
||||
Contents:
|
||||
------------------------
|
||||
1. Ensuring U-boot's MAC address can be set in hardware
|
||||
2. Running the smc91111_eeprom program
|
||||
3. Setting MAC addresses
|
||||
4. Other things you can do with this
|
||||
5. Things to be done.
|
||||
|
||||
|
||||
1. Ensuring U-boot's MAC address can be set in hardware
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
On the Internet - MAC addresses are very important. Short for Media
|
||||
Access Control address, a hardware address that uniquely identifies
|
||||
each node of a network. When things are not unique - bad things
|
||||
can happen. This is why U-Boot makes it difficult to change MAC
|
||||
addresses.
|
||||
|
||||
To find out who has a MAC address, or to purchase MAC addresses, goto
|
||||
the IEEE, at:
|
||||
http://standards.ieee.org/regauth/oui/index.shtml
|
||||
|
||||
To change your MAC address, there can not be a MAC address predefined in
|
||||
U-Boot. To ensure that this does not occur, check your
|
||||
include/configs/<board_name>.h file, and check to see that the following
|
||||
settings are _not_ or commented out there.
|
||||
|
||||
#define HARDCODE_MAC 1
|
||||
#define CONFIG_ETHADDR 02:80:ad:20:31:b8
|
||||
|
||||
The purpose of HARDCODE_MAC is to hardcode the MAC address in software,
|
||||
(not what we want), or to preset it to 02:80:ad:20:31:b8 (not what we
|
||||
want either).
|
||||
|
||||
You can check this in a running U-Boot, by doing a power cycle, then
|
||||
before U-Boot tries to do any networking, running the 'printenv' command
|
||||
|
||||
BOOT> printenv
|
||||
|
||||
ethaddr=02:80:ad:20:31:b8
|
||||
|
||||
If you see the 'ethaddr' variable show up, like the above, you need to
|
||||
recompile U-Boot, with the above settings commented out of the
|
||||
include/configs/<board_name>.h file.
|
||||
|
||||
2. Running the smc91111_eeprom program
|
||||
---------------------------------------------------------------------
|
||||
|
||||
After Uboot is compiled, there should be three files of interest:
|
||||
-rwxr-xr-x 1 8806 2004-10-11 14:00 smc91111_eeprom <- ELF
|
||||
-rwxr-xr-x 1 3440 2004-10-11 14:00 smc91111_eeprom.bin <- BIN
|
||||
-rwxr-xr-x 1 9524 2004-10-11 14:00 smc91111_eeprom.srec <- SREC
|
||||
|
||||
if there is not, check the examples/Makefile, and ensure there is something
|
||||
like for your architecture:
|
||||
|
||||
ifeq ($(ARCH),blackfin)
|
||||
SREC += smc91111_eeprom.srec
|
||||
BIN += smc91111_eeprom.bin smc91111_eeprom
|
||||
endif
|
||||
|
||||
To load the files: there are two methods: a) serial or b) network. Since
|
||||
it is not a good idea to start doing things on the network before the
|
||||
MAC address is set, this example will do things over serial.
|
||||
|
||||
a) Loading the elf file via the serial port
|
||||
--------------------------------------------
|
||||
Loading the elf is very easy - just ensure that the location
|
||||
you specify things to load as is not the load address specified
|
||||
in the Makefile.
|
||||
|
||||
BOOT> loadb 0x1000000
|
||||
|
||||
## Ready for binary (kermit) download to 0x01000000 at 57600 bps...
|
||||
|
||||
(type CNTL-\ then C)
|
||||
(Back at local machine)
|
||||
----------------------------------------------------
|
||||
Kermit>send ~/u-boot_1.1.1/examples/smc91111_eeprom
|
||||
Kermit>connect
|
||||
|
||||
Connecting to /dev/ttyS0, speed 57600
|
||||
Escape character: Ctrl-\ (ASCII 28, FS): enabled
|
||||
Type the escape character followed by C to get back,
|
||||
or followed by ? to see other options.
|
||||
----------------------------------------------------
|
||||
## Total Size = 0x00002266 = 8806 Bytes
|
||||
## Start Addr = 0x01000000
|
||||
|
||||
BOOT> bootelf 0x1000000
|
||||
|
||||
Loading .text @ 0x00001000 (3440 bytes)
|
||||
## Starting application at 0x000010d8 ...
|
||||
|
||||
SMC91111>
|
||||
|
||||
b) Loading the binary file via the serial port
|
||||
-----------------------------------------------
|
||||
For many toolchains, the entry point is not the load point.
|
||||
The Load point is a hard coded address from the
|
||||
examples/Makefile. The entry point can be found by doing something
|
||||
like:
|
||||
|
||||
u-boot_1.1.1/examples> bfin-elf-objdump -d smc91111_eeprom |less
|
||||
|
||||
smc91111_eeprom: file format elf32-bfin
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
00001000 <smc91111_eeprom-0xd8>:
|
||||
1000:
|
||||
000010d8 <smc91111_eeprom>:
|
||||
|
||||
You can see that the entry point (or the address that should be
|
||||
jumped to is 0x10d8). This is also the same as the entry point
|
||||
of the elf file.
|
||||
|
||||
Now we load it to the actual load location:
|
||||
|
||||
BOOT> loadb 0x1000
|
||||
|
||||
## Ready for binary (kermit) download to 0x00001000 at 57600 bps...
|
||||
|
||||
(Back at pinky.dsl-only.net)
|
||||
----------------------------------------------------
|
||||
Kermit>send /tftpboot/eeprom.bin
|
||||
Kermit>connect
|
||||
|
||||
Connecting to /dev/ttyS0, speed 57600
|
||||
Escape character: Ctrl-\ (ASCII 28, FS): enabled
|
||||
Type the escape character followed by C to get back,
|
||||
or followed by ? to see other options.
|
||||
----------------------------------------------------
|
||||
## Total Size = 0x00000d70 = 3440 Bytes
|
||||
## Start Addr = 0x00001000
|
||||
|
||||
BOOT> go 0x10D8
|
||||
|
||||
## Starting application at 0x000010D8 ...
|
||||
|
||||
SMC91111>
|
||||
|
||||
3. Setting MAC addresses
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
The MAC address can be stored in four locations:
|
||||
|
||||
-Boot environmental variable in Flash <- can not change, without
|
||||
re-flashing U-boot.
|
||||
U-Boot environental variable <- can not change, without
|
||||
resetting board/U-Boot
|
||||
LAN91C111 Registers <- volitle
|
||||
LAN91C111 EEPROM <- Non Volitle
|
||||
|
||||
If you have not activated the network, and do not have a hardcoded
|
||||
or pre-assigned MAC address in U-boot, the environmental variables
|
||||
should be blank, and allow you to set things one time.
|
||||
|
||||
To set the EEPROM MAC address to 12:34:56:78:9A:BC
|
||||
|
||||
SMC91111> W E 20 3412
|
||||
|
||||
Writing EEPROM register 20 with 3412
|
||||
SMC91111> W E 21 7856
|
||||
|
||||
Writing EEPROM register 21 with 7856
|
||||
SMC91111> W E 22 BC9A
|
||||
|
||||
Writing EEPROM register 22 with bc9a
|
||||
EEPROM contents copied to MAC
|
||||
SMC91111> P
|
||||
|
||||
Current MAC Address in SMSC91111 12:34:56:78:9a:bc
|
||||
Current MAC Address in EEPROM 12:34:56:78:9a:bc
|
||||
|
||||
(CNTRL-C to exit)
|
||||
SMC91111> ## Application terminated, rc = 0x0
|
||||
|
||||
BOOT> reset
|
||||
U-Boot 1.1.1 (gcc version: 3.3.3)
|
||||
Release Version Beta released on Oct 10 2004 - 00:34:35
|
||||
Blackfin support by LG Soft India
|
||||
For further information please check this link http://www.blackfin.uclinux.org
|
||||
BOOT> ping 192.168.0.4
|
||||
|
||||
Using MAC Address 12:34:56:78:9A:BC
|
||||
host 192.168.0.4 is alive
|
||||
|
||||
|
||||
4. Other things that you can do
|
||||
--------------------------------------------------------------------------
|
||||
After the stand alone application is running, there are a few options:
|
||||
- P : Print the MAC
|
||||
- D : Dump the LAN91C111 EEPROM contents
|
||||
- M : Dump the LAN91C111 MAC contents
|
||||
- C : Copies the MAC address from the EEPROM to the LAN91C111
|
||||
- W : Write a register in the EEPROM or in the MAC
|
||||
|
||||
SMC91111> P
|
||||
|
||||
Current MAC Address in SMSC91111 12:34:56:78:9a:bc
|
||||
Current MAC Address in EEPROM 12:34:56:78:9a:bc
|
||||
|
||||
SMC91111> D
|
||||
|
||||
IOS2-0 000 001 002 003 004 005 006 007
|
||||
CONFIG 00:ffff 04:ffff 08:ffff 0c:ffff 10:ffff 14:ffff 18:ffff 1c:ffff
|
||||
BASE 01:ffff 05:ffff 09:ffff 0d:ffff 11:ffff 15:ffff 19:ffff 1d:ffff
|
||||
02:ffff 06:ffff 0a:ffff 0e:0020 12:ffff 16:ffff 1a:ffff 1e:ffff
|
||||
03:ffff 07:ffff 0b:ffff 0f:ffff 13:ffff 17:ffff 1b:ffff 1f:ffff
|
||||
|
||||
20:3412 21:7856 22:bc9a 23:ffff 24:ffff 25:ffff 26:ffff 27:ffff
|
||||
28:ffff 29:ffff 2a:ffff 2b:ffff 2c:ffff 2d:ffff 2e:ffff 2f:ffff
|
||||
30:ffff 31:ffff 32:ffff 33:ffff 34:ffff 35:ffff 36:ffff 37:ffff
|
||||
38:ffff 39:ffff 3a:ffff 3b:ffff 3c:ffff 3d:ffff 3e:ffff 3f:ffff
|
||||
|
||||
SMC91111> M
|
||||
|
||||
Bank0 Bank1 Bank2 Bank3
|
||||
00 0000 a0b1 3332 0000
|
||||
02 0000 1801 8000 0000
|
||||
04 0000 3412 8080 0000
|
||||
06 0000 7856 003f 0000
|
||||
08 0404 bc9a 02df 3332
|
||||
0a 0000 ffff 02df 3391
|
||||
0c 0000 1214 0004 001f
|
||||
0e 3300 3301 3302 3303
|
||||
|
||||
SMC91111> C
|
||||
|
||||
EEPROM contents copied to MAC
|
||||
|
||||
SMC91111> W E 2A ABCD
|
||||
|
||||
Writing EEPROM register 2a with abcd
|
||||
|
||||
SMC91111> W M 14 FF00
|
||||
|
||||
Writing MAC register bank 1, reg 04 with ff00
|
|
@ -0,0 +1,210 @@
|
|||
/*
|
||||
* atmel_df_pow2.c - convert Atmel Dataflashes to Power of 2 mode
|
||||
*
|
||||
* Copyright 2009 Analog Devices Inc.
|
||||
*
|
||||
* Licensed under the 2-clause BSD.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <exports.h>
|
||||
#include <spi.h>
|
||||
|
||||
#define CMD_ID 0x9f
|
||||
#define CMD_STAT 0xd7
|
||||
#define CMD_CFG 0x3d
|
||||
|
||||
static int flash_cmd(struct spi_slave *slave, uchar cmd, uchar *buf, int len)
|
||||
{
|
||||
buf[0] = cmd;
|
||||
return spi_xfer(slave, 8 * len, buf, buf, SPI_XFER_BEGIN | SPI_XFER_END);
|
||||
}
|
||||
|
||||
static int flash_status(struct spi_slave *slave)
|
||||
{
|
||||
uchar buf[2];
|
||||
if (flash_cmd(slave, CMD_STAT, buf, sizeof(buf)))
|
||||
return -1;
|
||||
return buf[1];
|
||||
}
|
||||
|
||||
static int flash_set_pow2(struct spi_slave *slave)
|
||||
{
|
||||
int ret;
|
||||
uchar buf[4];
|
||||
|
||||
buf[1] = 0x2a;
|
||||
buf[2] = 0x80;
|
||||
buf[3] = 0xa6;
|
||||
|
||||
ret = flash_cmd(slave, CMD_CFG, buf, sizeof(buf));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* wait Tp, or 6 msec */
|
||||
udelay(6000);
|
||||
|
||||
ret = flash_status(slave);
|
||||
if (ret == -1)
|
||||
return 1;
|
||||
|
||||
return ret & 0x1 ? 0 : 1;
|
||||
}
|
||||
|
||||
static int flash_check(struct spi_slave *slave)
|
||||
{
|
||||
int ret;
|
||||
uchar buf[4];
|
||||
|
||||
ret = flash_cmd(slave, CMD_ID, buf, sizeof(buf));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (buf[1] != 0x1F) {
|
||||
printf("atmel flash not found (id[0] = %#x)\n", buf[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((buf[2] >> 5) != 0x1) {
|
||||
printf("AT45 flash not found (id[0] = %#x)\n", buf[2]);
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *getline(void)
|
||||
{
|
||||
static char buffer[100];
|
||||
char c;
|
||||
size_t i;
|
||||
|
||||
i = 0;
|
||||
while (1) {
|
||||
buffer[i] = '\0';
|
||||
|
||||
c = getc();
|
||||
|
||||
switch (c) {
|
||||
case '\r': /* Enter/Return key */
|
||||
case '\n':
|
||||
puts("\n");
|
||||
return buffer;
|
||||
|
||||
case 0x03: /* ^C - break */
|
||||
return NULL;
|
||||
|
||||
case 0x5F:
|
||||
case 0x08: /* ^H - backspace */
|
||||
case 0x7F: /* DEL - backspace */
|
||||
if (i) {
|
||||
puts("\b \b");
|
||||
i--;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Ignore control characters */
|
||||
if (c < 0x20)
|
||||
break;
|
||||
/* Queue up all other characters */
|
||||
buffer[i++] = c;
|
||||
printf("%c", c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int atmel_df_pow2(int argc, char * const argv[])
|
||||
{
|
||||
/* Print the ABI version */
|
||||
app_startup(argv);
|
||||
if (XF_VERSION != get_version()) {
|
||||
printf("Expects ABI version %d\n", XF_VERSION);
|
||||
printf("Actual U-Boot ABI version %lu\n", get_version());
|
||||
printf("Can't run\n\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
spi_init();
|
||||
|
||||
while (1) {
|
||||
struct spi_slave *slave;
|
||||
char *line, *p;
|
||||
int bus, cs, status;
|
||||
|
||||
puts("\nenter the [BUS:]CS of the SPI flash: ");
|
||||
line = getline();
|
||||
|
||||
/* CTRL+C */
|
||||
if (!line)
|
||||
return 0;
|
||||
if (line[0] == '\0')
|
||||
continue;
|
||||
|
||||
bus = cs = simple_strtoul(line, &p, 10);
|
||||
if (*p) {
|
||||
if (*p == ':') {
|
||||
++p;
|
||||
cs = simple_strtoul(p, &p, 10);
|
||||
}
|
||||
if (*p) {
|
||||
puts("invalid format, please try again\n");
|
||||
continue;
|
||||
}
|
||||
} else
|
||||
bus = 0;
|
||||
|
||||
printf("\ngoing to work with dataflash at %i:%i\n", bus, cs);
|
||||
|
||||
/* use a low speed -- it'll work with all devices, and
|
||||
* speed here doesn't really matter.
|
||||
*/
|
||||
slave = spi_setup_slave(bus, cs, 1000, SPI_MODE_3);
|
||||
if (!slave) {
|
||||
puts("unable to setup slave\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (spi_claim_bus(slave)) {
|
||||
spi_free_slave(slave);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (flash_check(slave)) {
|
||||
puts("no flash found\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
status = flash_status(slave);
|
||||
if (status == -1) {
|
||||
puts("unable to read status register\n");
|
||||
goto done;
|
||||
}
|
||||
if (status & 0x1) {
|
||||
puts("flash is already in power-of-2 mode!\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
puts("are you sure you wish to set power-of-2 mode?\n");
|
||||
puts("this operation is permanent and irreversible\n");
|
||||
printf("enter YES to continue: ");
|
||||
line = getline();
|
||||
if (!line || strcmp(line, "YES"))
|
||||
goto done;
|
||||
|
||||
if (flash_set_pow2(slave)) {
|
||||
puts("setting pow2 mode failed\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
puts(
|
||||
"Configuration should be updated now. You will have to\n"
|
||||
"power cycle the part in order to finish the conversion.\n"
|
||||
);
|
||||
|
||||
done:
|
||||
spi_release_bus(slave);
|
||||
spi_free_slave(slave);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
* Copyright 1998-2001 by Donald Becker.
|
||||
* This software may be used and distributed according to the terms of
|
||||
* the GNU General Public License (GPL), incorporated herein by reference.
|
||||
* Contact the author for use under other terms.
|
||||
*
|
||||
* This program must be compiled with "-O"!
|
||||
* See the bottom of this file for the suggested compile-command.
|
||||
*
|
||||
* The author may be reached as becker@scyld.com, or C/O
|
||||
* Scyld Computing Corporation
|
||||
* 410 Severn Ave., Suite 210
|
||||
* Annapolis MD 21403
|
||||
*
|
||||
* Common-sense licensing statement: Using any portion of this program in
|
||||
* your own program means that you must give credit to the original author
|
||||
* and release the resulting code under the GPL.
|
||||
*/
|
||||
|
||||
/* avoid unnecessary memcpy function */
|
||||
#define _PPC_STRING_H_
|
||||
|
||||
#include <common.h>
|
||||
#include <exports.h>
|
||||
|
||||
static int reset_eeprom(unsigned long ioaddr, unsigned char *hwaddr);
|
||||
|
||||
int eepro100_eeprom(int argc, char * const argv[])
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
unsigned char hwaddr1[6] = { 0x00, 0x00, 0x02, 0x03, 0x04, 0x05 };
|
||||
unsigned char hwaddr2[6] = { 0x00, 0x00, 0x02, 0x03, 0x04, 0x06 };
|
||||
|
||||
app_startup(argv);
|
||||
|
||||
#if defined(CONFIG_OXC)
|
||||
ret |= reset_eeprom(0x80000000, hwaddr1);
|
||||
ret |= reset_eeprom(0x81000000, hwaddr2);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Default EEPROM for i82559 */
|
||||
static unsigned short default_eeprom[64] = {
|
||||
0x0100, 0x0302, 0x0504, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0x40c0, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
|
||||
};
|
||||
|
||||
static unsigned short eeprom[256];
|
||||
|
||||
static int eeprom_size = 64;
|
||||
static int eeprom_addr_size = 6;
|
||||
|
||||
static int debug = 0;
|
||||
|
||||
static inline unsigned short swap16(unsigned short x)
|
||||
{
|
||||
return (((x & 0xff) << 8) | ((x & 0xff00) >> 8));
|
||||
}
|
||||
|
||||
static inline void outw(short data, long addr)
|
||||
{
|
||||
*(volatile short *)(addr) = swap16(data);
|
||||
}
|
||||
|
||||
static inline short inw(long addr)
|
||||
{
|
||||
return swap16(*(volatile short *)(addr));
|
||||
}
|
||||
|
||||
void *memcpy(void *dst, const void *src, unsigned int len)
|
||||
{
|
||||
char *ret = dst;
|
||||
while (len-- > 0) {
|
||||
*ret++ = *((char *)src);
|
||||
src++;
|
||||
}
|
||||
return (void *)ret;
|
||||
}
|
||||
|
||||
/* The EEPROM commands include the alway-set leading bit. */
|
||||
#define EE_WRITE_CMD (5)
|
||||
#define EE_READ_CMD (6)
|
||||
#define EE_ERASE_CMD (7)
|
||||
|
||||
/* Serial EEPROM section. */
|
||||
#define EE_SHIFT_CLK 0x01 /* EEPROM shift clock. */
|
||||
#define EE_CS 0x02 /* EEPROM chip select. */
|
||||
#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */
|
||||
#define EE_DATA_READ 0x08 /* EEPROM chip data out. */
|
||||
#define EE_ENB (0x4800 | EE_CS)
|
||||
#define EE_WRITE_0 0x4802
|
||||
#define EE_WRITE_1 0x4806
|
||||
#define EE_OFFSET 14
|
||||
|
||||
/* Delay between EEPROM clock transitions. */
|
||||
#define eeprom_delay(ee_addr) inw(ee_addr)
|
||||
|
||||
/* Wait for the EEPROM to finish the previous operation. */
|
||||
static int eeprom_busy_poll(long ee_ioaddr)
|
||||
{
|
||||
int i;
|
||||
outw(EE_ENB, ee_ioaddr);
|
||||
for (i = 0; i < 10000; i++) /* Typical 2000 ticks */
|
||||
if (inw(ee_ioaddr) & EE_DATA_READ)
|
||||
break;
|
||||
return i;
|
||||
}
|
||||
|
||||
/* This executes a generic EEPROM command, typically a write or write enable.
|
||||
It returns the data output from the EEPROM, and thus may also be used for
|
||||
reads. */
|
||||
static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len)
|
||||
{
|
||||
unsigned retval = 0;
|
||||
long ee_addr = ioaddr + EE_OFFSET;
|
||||
|
||||
if (debug > 1)
|
||||
printf(" EEPROM op 0x%x: ", cmd);
|
||||
|
||||
outw(EE_ENB | EE_SHIFT_CLK, ee_addr);
|
||||
|
||||
/* Shift the command bits out. */
|
||||
do {
|
||||
short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0;
|
||||
outw(dataval, ee_addr);
|
||||
eeprom_delay(ee_addr);
|
||||
if (debug > 2)
|
||||
printf("%X", inw(ee_addr) & 15);
|
||||
outw(dataval | EE_SHIFT_CLK, ee_addr);
|
||||
eeprom_delay(ee_addr);
|
||||
retval = (retval << 1) | ((inw(ee_addr) & EE_DATA_READ) ? 1 : 0);
|
||||
} while (--cmd_len >= 0);
|
||||
#if 0
|
||||
outw(EE_ENB, ee_addr);
|
||||
#endif
|
||||
/* Terminate the EEPROM access. */
|
||||
outw(EE_ENB & ~EE_CS, ee_addr);
|
||||
if (debug > 1)
|
||||
printf(" EEPROM result is 0x%5.5x.\n", retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int read_eeprom(long ioaddr, int location, int addr_len)
|
||||
{
|
||||
return do_eeprom_cmd(ioaddr, ((EE_READ_CMD << addr_len) | location)
|
||||
<< 16 , 3 + addr_len + 16) & 0xffff;
|
||||
}
|
||||
|
||||
static void write_eeprom(long ioaddr, int index, int value, int addr_len)
|
||||
{
|
||||
long ee_ioaddr = ioaddr + EE_OFFSET;
|
||||
int i;
|
||||
|
||||
/* Poll for previous op finished. */
|
||||
eeprom_busy_poll(ee_ioaddr); /* Typical 0 ticks */
|
||||
/* Enable programming modes. */
|
||||
do_eeprom_cmd(ioaddr, (0x4f << (addr_len-4)), 3 + addr_len);
|
||||
/* Do the actual write. */
|
||||
do_eeprom_cmd(ioaddr,
|
||||
(((EE_WRITE_CMD<<addr_len) | index)<<16) | (value & 0xffff),
|
||||
3 + addr_len + 16);
|
||||
/* Poll for write finished. */
|
||||
i = eeprom_busy_poll(ee_ioaddr); /* Typical 2000 ticks */
|
||||
if (debug)
|
||||
printf(" Write finished after %d ticks.\n", i);
|
||||
/* Disable programming. This command is not instantaneous, so we check
|
||||
for busy before the next op. */
|
||||
do_eeprom_cmd(ioaddr, (0x40 << (addr_len-4)), 3 + addr_len);
|
||||
eeprom_busy_poll(ee_ioaddr);
|
||||
}
|
||||
|
||||
static int reset_eeprom(unsigned long ioaddr, unsigned char *hwaddr)
|
||||
{
|
||||
unsigned short checksum = 0;
|
||||
int size_test;
|
||||
int i;
|
||||
|
||||
printf("Resetting i82559 EEPROM @ 0x%08lX ... ", ioaddr);
|
||||
|
||||
size_test = do_eeprom_cmd(ioaddr, (EE_READ_CMD << 8) << 16, 27);
|
||||
eeprom_addr_size = (size_test & 0xffe0000) == 0xffe0000 ? 8 : 6;
|
||||
eeprom_size = 1 << eeprom_addr_size;
|
||||
|
||||
memcpy(eeprom, default_eeprom, sizeof default_eeprom);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
eeprom[i] = (hwaddr[i*2+1]<<8) + hwaddr[i*2];
|
||||
|
||||
/* Recalculate the checksum. */
|
||||
for (i = 0; i < eeprom_size - 1; i++)
|
||||
checksum += eeprom[i];
|
||||
eeprom[i] = 0xBABA - checksum;
|
||||
|
||||
for (i = 0; i < eeprom_size; i++)
|
||||
write_eeprom(ioaddr, i, eeprom[i], eeprom_addr_size);
|
||||
|
||||
for (i = 0; i < eeprom_size; i++)
|
||||
if (read_eeprom(ioaddr, i, eeprom_addr_size) != eeprom[i]) {
|
||||
printf("failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("done\n");
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* (C) Copyright 2000
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <exports.h>
|
||||
|
||||
int hello_world (int argc, char * const argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Print the ABI version */
|
||||
app_startup(argv);
|
||||
printf ("Example expects ABI version %d\n", XF_VERSION);
|
||||
printf ("Actual U-Boot ABI version %d\n", (int)get_version());
|
||||
|
||||
printf ("Hello World\n");
|
||||
|
||||
printf ("argc = %d\n", argc);
|
||||
|
||||
for (i=0; i<=argc; ++i) {
|
||||
printf ("argv[%d] = \"%s\"\n",
|
||||
i,
|
||||
argv[i] ? argv[i] : "<NULL>");
|
||||
}
|
||||
|
||||
printf ("Hit any key to exit ... ");
|
||||
while (!tstc())
|
||||
;
|
||||
/* consume input */
|
||||
(void) getc();
|
||||
|
||||
printf ("\n\n");
|
||||
return (0);
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* (C) Copyright 2006
|
||||
* Detlev Zundel, DENX Software Engineering, dzu@denx.de.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* This is a very simple standalone application demonstrating
|
||||
* catching IRQs on the MPC52xx architecture.
|
||||
*
|
||||
* The interrupt to be intercepted can be specified as an argument
|
||||
* to the application. Specifying nothing will intercept IRQ1 on the
|
||||
* MPC5200 platform. On the CR825 carrier board from MicroSys this
|
||||
* maps to the ABORT switch :)
|
||||
*
|
||||
* Note that the specified vector is only a logical number specified
|
||||
* by the respective header file.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <exports.h>
|
||||
#include <config.h>
|
||||
|
||||
#if defined(CONFIG_MPC5xxx)
|
||||
#define DFL_IRQ MPC5XXX_IRQ1
|
||||
#else
|
||||
#define DFL_IRQ 0
|
||||
#endif
|
||||
|
||||
static void irq_handler (void *arg);
|
||||
|
||||
int interrupt (int argc, char * const argv[])
|
||||
{
|
||||
int c, irq = -1;
|
||||
|
||||
app_startup (argv);
|
||||
|
||||
if (argc > 1)
|
||||
irq = simple_strtoul (argv[1], NULL, 0);
|
||||
if ((irq < 0) || (irq > NR_IRQS))
|
||||
irq = DFL_IRQ;
|
||||
|
||||
printf ("Installing handler for irq vector %d and doing busy wait\n",
|
||||
irq);
|
||||
printf ("Press 'q' to quit\n");
|
||||
|
||||
/* Install interrupt handler */
|
||||
install_hdlr (irq, irq_handler, NULL);
|
||||
while ((c = getc ()) != 'q') {
|
||||
printf ("Ok, ok, I am still alive!\n");
|
||||
}
|
||||
|
||||
free_hdlr (irq);
|
||||
printf ("\nInterrupt handler has been uninstalled\n");
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handler for interrupt
|
||||
*/
|
||||
static void irq_handler (void *arg)
|
||||
{
|
||||
/* just for demonstration */
|
||||
printf ("+");
|
||||
}
|
|
@ -0,0 +1,384 @@
|
|||
/* The dpalloc function used and implemented in this file was derieved
|
||||
* from PPCBoot/U-Boot file "arch/powerpc/cpu/mpc8260/commproc.c".
|
||||
*/
|
||||
|
||||
/* Author: Arun Dharankar <ADharankar@ATTBI.Com>
|
||||
* This example is meant to only demonstrate how the IDMA could be used.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on "arch/powerpc/8260_io/commproc.c" - here is it's
|
||||
* copyright notice:
|
||||
*
|
||||
* General Purpose functions for the global management of the
|
||||
* 8260 Communication Processor Module.
|
||||
* Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
|
||||
* Copyright (c) 2000 MontaVista Software, Inc (source@mvista.com)
|
||||
* 2.3.99 Updates
|
||||
*
|
||||
* In addition to the individual control of the communication
|
||||
* channels, there are a few functions that globally affect the
|
||||
* communication processor.
|
||||
*
|
||||
* Buffer descriptors must be allocated from the dual ported memory
|
||||
* space. The allocator for that is here. When the communication
|
||||
* process is reset, we reclaim the memory available. There is
|
||||
* currently no deallocator for this memory.
|
||||
*/
|
||||
|
||||
|
||||
#include <common.h>
|
||||
#include <exports.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#define STANDALONE
|
||||
|
||||
#ifndef STANDALONE /* Linked into/Part of PPCBoot */
|
||||
#include <command.h>
|
||||
#include <watchdog.h>
|
||||
#else /* Standalone app of PPCBoot */
|
||||
#define WATCHDOG_RESET() { \
|
||||
*(ushort *)(CONFIG_SYS_IMMR + 0x1000E) = 0x556c; \
|
||||
*(ushort *)(CONFIG_SYS_IMMR + 0x1000E) = 0xaa39; \
|
||||
}
|
||||
#endif /* STANDALONE */
|
||||
|
||||
static int debug = 1;
|
||||
|
||||
#define DEBUG(fmt, args...) { \
|
||||
if(debug != 0) { \
|
||||
printf("[%s %d %s]: ",__FILE__,__LINE__,__FUNCTION__); \
|
||||
printf(fmt, ##args); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CPM_CR_IDMA1_SBLOCK (0x14)
|
||||
#define CPM_CR_IDMA2_SBLOCK (0x15)
|
||||
#define CPM_CR_IDMA3_SBLOCK (0x16)
|
||||
#define CPM_CR_IDMA4_SBLOCK (0x17)
|
||||
#define CPM_CR_IDMA1_PAGE (0x07)
|
||||
#define CPM_CR_IDMA2_PAGE (0x08)
|
||||
#define CPM_CR_IDMA3_PAGE (0x09)
|
||||
#define CPM_CR_IDMA4_PAGE (0x0a)
|
||||
#define PROFF_IDMA1_BASE ((uint)0x87fe)
|
||||
#define PROFF_IDMA2_BASE ((uint)0x88fe)
|
||||
#define PROFF_IDMA3_BASE ((uint)0x89fe)
|
||||
#define PROFF_IDMA4_BASE ((uint)0x8afe)
|
||||
|
||||
#define CPM_CR_INIT_TRX ((ushort)0x0000)
|
||||
#define CPM_CR_FLG ((ushort)0x0001)
|
||||
|
||||
#define mk_cr_cmd(PG, SBC, MCN, OP) \
|
||||
((PG << 26) | (SBC << 21) | (MCN << 6) | OP)
|
||||
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct ibdbits {
|
||||
unsigned b_valid:1;
|
||||
unsigned b_resv1:1;
|
||||
unsigned b_wrap:1;
|
||||
unsigned b_interrupt:1;
|
||||
unsigned b_last:1;
|
||||
unsigned b_resv2:1;
|
||||
unsigned b_cm:1;
|
||||
unsigned b_resv3:2;
|
||||
unsigned b_sdn:1;
|
||||
unsigned b_ddn:1;
|
||||
unsigned b_dgbl:1;
|
||||
unsigned b_dbo:2;
|
||||
unsigned b_resv4:1;
|
||||
unsigned b_ddtb:1;
|
||||
unsigned b_resv5:2;
|
||||
unsigned b_sgbl:1;
|
||||
unsigned b_sbo:2;
|
||||
unsigned b_resv6:1;
|
||||
unsigned b_sdtb:1;
|
||||
unsigned b_resv7:9;
|
||||
} ibdbits_t;
|
||||
|
||||
#pragma pack(1)
|
||||
typedef union ibdbitsu {
|
||||
ibdbits_t b;
|
||||
uint i;
|
||||
} ibdbitsu_t;
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct idma_buf_desc {
|
||||
ibdbitsu_t ibd_bits; /* Status and Control */
|
||||
uint ibd_datlen; /* Data length in buffer */
|
||||
uint ibd_sbuf; /* Source buffer addr in host mem */
|
||||
uint ibd_dbuf; /* Destination buffer addr in host mem */
|
||||
} ibd_t;
|
||||
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct dcmbits {
|
||||
unsigned b_fb:1;
|
||||
unsigned b_lp:1;
|
||||
unsigned b_resv1:3;
|
||||
unsigned b_tc2:1;
|
||||
unsigned b_resv2:1;
|
||||
unsigned b_wrap:3;
|
||||
unsigned b_sinc:1;
|
||||
unsigned b_dinc:1;
|
||||
unsigned b_erm:1;
|
||||
unsigned b_dt:1;
|
||||
unsigned b_sd:2;
|
||||
} dcmbits_t;
|
||||
|
||||
#pragma pack(1)
|
||||
typedef union dcmbitsu {
|
||||
dcmbits_t b;
|
||||
ushort i;
|
||||
} dcmbitsu_t;
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct pram_idma {
|
||||
ushort pi_ibase;
|
||||
dcmbitsu_t pi_dcmbits;
|
||||
ushort pi_ibdptr;
|
||||
ushort pi_dprbuf;
|
||||
ushort pi_bufinv; /* internal to CPM */
|
||||
ushort pi_ssmax;
|
||||
ushort pi_dprinptr; /* internal to CPM */
|
||||
ushort pi_sts;
|
||||
ushort pi_dproutptr; /* internal to CPM */
|
||||
ushort pi_seob;
|
||||
ushort pi_deob;
|
||||
ushort pi_dts;
|
||||
ushort pi_retadd;
|
||||
ushort pi_resv1; /* internal to CPM */
|
||||
uint pi_bdcnt;
|
||||
uint pi_sptr;
|
||||
uint pi_dptr;
|
||||
uint pi_istate;
|
||||
} pram_idma_t;
|
||||
|
||||
|
||||
volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
|
||||
volatile ibd_t *bdf;
|
||||
volatile pram_idma_t *piptr;
|
||||
|
||||
volatile int dmadone;
|
||||
volatile int *dmadonep = &dmadone;
|
||||
void dmadone_handler (void *);
|
||||
|
||||
int idma_init (void);
|
||||
void idma_start (int, int, int, uint, uint, int);
|
||||
uint dpalloc (uint, uint);
|
||||
|
||||
|
||||
uint dpinit_done = 0;
|
||||
|
||||
|
||||
#ifdef STANDALONE
|
||||
int ctrlc (void)
|
||||
{
|
||||
if (tstc()) {
|
||||
switch (getc ()) {
|
||||
case 0x03: /* ^C - Control C */
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void * memset(void * s,int c,size_t count)
|
||||
{
|
||||
char *xs = (char *) s;
|
||||
while (count--)
|
||||
*xs++ = c;
|
||||
return s;
|
||||
}
|
||||
int memcmp(const void * cs,const void * ct,size_t count)
|
||||
{
|
||||
const unsigned char *su1, *su2;
|
||||
int res = 0;
|
||||
for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
|
||||
if ((res = *su1 - *su2) != 0)
|
||||
break;
|
||||
return res;
|
||||
}
|
||||
#endif /* STANDALONE */
|
||||
|
||||
#ifdef STANDALONE
|
||||
int mem_to_mem_idma2intr (int argc, char * const argv[])
|
||||
#else
|
||||
int do_idma (bd_t * bd, int argc, char * const argv[])
|
||||
#endif /* STANDALONE */
|
||||
{
|
||||
int i;
|
||||
|
||||
app_startup(argv);
|
||||
dpinit_done = 0;
|
||||
|
||||
idma_init ();
|
||||
|
||||
DEBUG ("Installing dma handler\n");
|
||||
install_hdlr (7, dmadone_handler, (void *) bdf);
|
||||
|
||||
memset ((void *) 0x100000, 'a', 512);
|
||||
memset ((void *) 0x200000, 'b', 512);
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
printf ("Startin IDMA, iteration=%d\n", i);
|
||||
idma_start (1, 1, 512, 0x100000, 0x200000, 3);
|
||||
}
|
||||
|
||||
DEBUG ("Uninstalling dma handler\n");
|
||||
free_hdlr (7);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
idma_start (int sinc, int dinc, int sz, uint sbuf, uint dbuf, int ttype)
|
||||
{
|
||||
/* ttype is for M-M, M-P, P-M or P-P: not used for now */
|
||||
|
||||
piptr->pi_istate = 0; /* manual says: clear it before every START_IDMA */
|
||||
piptr->pi_dcmbits.b.b_resv1 = 0;
|
||||
|
||||
if (sinc == 1)
|
||||
piptr->pi_dcmbits.b.b_sinc = 1;
|
||||
else
|
||||
piptr->pi_dcmbits.b.b_sinc = 0;
|
||||
|
||||
if (dinc == 1)
|
||||
piptr->pi_dcmbits.b.b_dinc = 1;
|
||||
else
|
||||
piptr->pi_dcmbits.b.b_dinc = 0;
|
||||
|
||||
piptr->pi_dcmbits.b.b_erm = 0;
|
||||
piptr->pi_dcmbits.b.b_sd = 0x00; /* M-M */
|
||||
|
||||
bdf->ibd_sbuf = sbuf;
|
||||
bdf->ibd_dbuf = dbuf;
|
||||
bdf->ibd_bits.b.b_cm = 0;
|
||||
bdf->ibd_bits.b.b_interrupt = 1;
|
||||
bdf->ibd_bits.b.b_wrap = 1;
|
||||
bdf->ibd_bits.b.b_last = 1;
|
||||
bdf->ibd_bits.b.b_sdn = 0;
|
||||
bdf->ibd_bits.b.b_ddn = 0;
|
||||
bdf->ibd_bits.b.b_dgbl = 0;
|
||||
bdf->ibd_bits.b.b_ddtb = 0;
|
||||
bdf->ibd_bits.b.b_sgbl = 0;
|
||||
bdf->ibd_bits.b.b_sdtb = 0;
|
||||
bdf->ibd_bits.b.b_dbo = 1;
|
||||
bdf->ibd_bits.b.b_sbo = 1;
|
||||
bdf->ibd_bits.b.b_valid = 1;
|
||||
bdf->ibd_datlen = 512;
|
||||
|
||||
*dmadonep = 0;
|
||||
|
||||
immap->im_sdma.sdma_idmr2 = (uchar) 0xf;
|
||||
|
||||
immap->im_cpm.cp_cpcr = mk_cr_cmd (CPM_CR_IDMA2_PAGE,
|
||||
CPM_CR_IDMA2_SBLOCK, 0x0,
|
||||
0x9) | 0x00010000;
|
||||
|
||||
while (*dmadonep != 1) {
|
||||
if (ctrlc ()) {
|
||||
DEBUG ("\nInterrupted waiting for DMA interrupt.\n");
|
||||
goto done;
|
||||
}
|
||||
printf ("Waiting for DMA interrupt (dmadone=%d b_valid = %d)...\n",
|
||||
dmadone, bdf->ibd_bits.b.b_valid);
|
||||
udelay (1000000);
|
||||
}
|
||||
printf ("DMA complete notification received!\n");
|
||||
|
||||
done:
|
||||
DEBUG ("memcmp(0x%08x, 0x%08x, 512) = %d\n",
|
||||
sbuf, dbuf, memcmp ((void *) sbuf, (void *) dbuf, 512));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#define MAX_INT_BUFSZ 64
|
||||
#define DCM_WRAP 0 /* MUST be consistant with MAX_INT_BUFSZ */
|
||||
|
||||
int idma_init (void)
|
||||
{
|
||||
uint memaddr;
|
||||
|
||||
immap->im_cpm.cp_rccr &= ~0x00F3FFFF;
|
||||
immap->im_cpm.cp_rccr |= 0x00A00A00;
|
||||
|
||||
memaddr = dpalloc (sizeof (pram_idma_t), 64);
|
||||
|
||||
*(volatile ushort *) &immap->im_dprambase[PROFF_IDMA2_BASE] = memaddr;
|
||||
piptr = (volatile pram_idma_t *) ((uint) (immap) + memaddr);
|
||||
|
||||
piptr->pi_resv1 = 0; /* manual says: clear it */
|
||||
piptr->pi_dcmbits.b.b_fb = 0;
|
||||
piptr->pi_dcmbits.b.b_lp = 1;
|
||||
piptr->pi_dcmbits.b.b_erm = 0;
|
||||
piptr->pi_dcmbits.b.b_dt = 0;
|
||||
|
||||
memaddr = (uint) dpalloc (sizeof (ibd_t), 64);
|
||||
piptr->pi_ibase = piptr->pi_ibdptr = (volatile short) memaddr;
|
||||
bdf = (volatile ibd_t *) ((uint) (immap) + memaddr);
|
||||
bdf->ibd_bits.b.b_valid = 0;
|
||||
|
||||
memaddr = (uint) dpalloc (64, 64);
|
||||
piptr->pi_dprbuf = (volatile ushort) memaddr;
|
||||
piptr->pi_dcmbits.b.b_wrap = 4;
|
||||
piptr->pi_ssmax = 32;
|
||||
|
||||
piptr->pi_sts = piptr->pi_ssmax;
|
||||
piptr->pi_dts = piptr->pi_ssmax;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void dmadone_handler (void *arg)
|
||||
{
|
||||
immap->im_sdma.sdma_idmr2 = (uchar) 0x0;
|
||||
|
||||
*dmadonep = 1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static uint dpbase = 0;
|
||||
|
||||
uint dpalloc (uint size, uint align)
|
||||
{
|
||||
volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
|
||||
uint retloc;
|
||||
uint align_mask, off;
|
||||
uint savebase;
|
||||
|
||||
/* Pointer to initial global data area */
|
||||
|
||||
if (dpinit_done == 0) {
|
||||
dpbase = gd->dp_alloc_base;
|
||||
dpinit_done = 1;
|
||||
}
|
||||
|
||||
align_mask = align - 1;
|
||||
savebase = dpbase;
|
||||
|
||||
if ((off = (dpbase & align_mask)) != 0)
|
||||
dpbase += (align - off);
|
||||
|
||||
if ((off = size & align_mask) != 0)
|
||||
size += align - off;
|
||||
|
||||
if ((dpbase + size) >= gd->dp_alloc_top) {
|
||||
dpbase = savebase;
|
||||
printf ("dpalloc: ran out of dual port ram!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
retloc = dpbase;
|
||||
dpbase += size;
|
||||
|
||||
memset ((void *) &immr->im_dprambase[retloc], 0, size);
|
||||
|
||||
return (retloc);
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* (C) Copyright 2003
|
||||
* Wolfgang Denk Engineering, <wd@denx.de>
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-bigmips")
|
||||
*/
|
||||
OUTPUT_FORMAT("elf32-tradbigmips", "elf32-tradbigmips", "elf32-tradlittlemips")
|
||||
OUTPUT_ARCH(mips)
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
*(.text*)
|
||||
}
|
||||
|
||||
. = ALIGN(4);
|
||||
.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
|
||||
|
||||
. = ALIGN(4);
|
||||
.data : { *(.data*) }
|
||||
|
||||
. = .;
|
||||
_gp = ALIGN(16) + 0x7ff0;
|
||||
|
||||
.got : {
|
||||
__got_start = .;
|
||||
*(.got)
|
||||
__got_end = .;
|
||||
}
|
||||
|
||||
.sdata : { *(.sdata*) }
|
||||
|
||||
. = ALIGN(4);
|
||||
__bss_start = .;
|
||||
.sbss (NOLOAD) : { *(.sbss*) }
|
||||
.bss (NOLOAD) : { *(.bss*) . = ALIGN(4); }
|
||||
|
||||
_end = .;
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (C) 2011 Andes Technology Corporation
|
||||
* Shawn Lin, Andes Technology Corporation <nobuhiro@andestech.com>
|
||||
* Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com>
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
OUTPUT_FORMAT("elf32-nds32", "elf32-nds32", "elf32-nds32")
|
||||
OUTPUT_ARCH(nds32)
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = ALIGN(4);
|
||||
.text :
|
||||
{
|
||||
*(.text)
|
||||
}
|
||||
|
||||
. = ALIGN(4);
|
||||
.data : { *(.data) }
|
||||
|
||||
. = ALIGN(4);
|
||||
|
||||
.got : {
|
||||
__got_start = .;
|
||||
*(.got)
|
||||
__got_end = .;
|
||||
}
|
||||
|
||||
. = ALIGN(4);
|
||||
__bss_start = .;
|
||||
.bss : { *(.bss) }
|
||||
__bss_end = .;
|
||||
|
||||
. = ALIGN(4);
|
||||
.rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
|
||||
|
||||
_end = .;
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/* longjmp for PowerPC.
|
||||
Copyright (C) 1995, 1996, 1997, 1999, 2000 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <ppc_asm.tmpl>
|
||||
|
||||
# define JB_GPR1 0 /* Also known as the stack pointer */
|
||||
# define JB_GPR2 1
|
||||
# define JB_LR 2 /* The address we will return to */
|
||||
# define JB_GPRS 3 /* GPRs 14 through 31 are saved, 18 in total */
|
||||
# define JB_CR 21 /* Condition code registers. */
|
||||
# define JB_FPRS 22 /* FPRs 14 through 31 are saved, 18*2 words total */
|
||||
# define JB_SIZE (58*4)
|
||||
|
||||
#define FP(x...) x
|
||||
#define FP(x...) x
|
||||
|
||||
.globl ppc_longjmp;
|
||||
|
||||
ppc_longjmp:
|
||||
lwz r1,(JB_GPR1*4)(r3)
|
||||
lwz r2,(JB_GPR2*4)(r3)
|
||||
lwz r0,(JB_LR*4)(r3)
|
||||
lwz r14,((JB_GPRS+0)*4)(r3)
|
||||
FP( lfd 14,((JB_FPRS+0*2)*4)(r3))
|
||||
lwz r15,((JB_GPRS+1)*4)(r3)
|
||||
FP( lfd 15,((JB_FPRS+1*2)*4)(r3))
|
||||
lwz r16,((JB_GPRS+2)*4)(r3)
|
||||
FP( lfd 16,((JB_FPRS+2*2)*4)(r3))
|
||||
lwz r17,((JB_GPRS+3)*4)(r3)
|
||||
FP( lfd 17,((JB_FPRS+3*2)*4)(r3))
|
||||
lwz r18,((JB_GPRS+4)*4)(r3)
|
||||
FP( lfd 18,((JB_FPRS+4*2)*4)(r3))
|
||||
lwz r19,((JB_GPRS+5)*4)(r3)
|
||||
FP( lfd 19,((JB_FPRS+5*2)*4)(r3))
|
||||
lwz r20,((JB_GPRS+6)*4)(r3)
|
||||
FP( lfd 20,((JB_FPRS+6*2)*4)(r3))
|
||||
mtlr r0
|
||||
lwz r21,((JB_GPRS+7)*4)(r3)
|
||||
FP( lfd 21,((JB_FPRS+7*2)*4)(r3))
|
||||
lwz r22,((JB_GPRS+8)*4)(r3)
|
||||
FP( lfd 22,((JB_FPRS+8*2)*4)(r3))
|
||||
lwz r0,(JB_CR*4)(r3)
|
||||
lwz r23,((JB_GPRS+9)*4)(r3)
|
||||
FP( lfd 23,((JB_FPRS+9*2)*4)(r3))
|
||||
lwz r24,((JB_GPRS+10)*4)(r3)
|
||||
FP( lfd 24,((JB_FPRS+10*2)*4)(r3))
|
||||
lwz r25,((JB_GPRS+11)*4)(r3)
|
||||
FP( lfd 25,((JB_FPRS+11*2)*4)(r3))
|
||||
mtcrf 0xFF,r0
|
||||
lwz r26,((JB_GPRS+12)*4)(r3)
|
||||
FP( lfd 26,((JB_FPRS+12*2)*4)(r3))
|
||||
lwz r27,((JB_GPRS+13)*4)(r3)
|
||||
FP( lfd 27,((JB_FPRS+13*2)*4)(r3))
|
||||
lwz r28,((JB_GPRS+14)*4)(r3)
|
||||
FP( lfd 28,((JB_FPRS+14*2)*4)(r3))
|
||||
lwz r29,((JB_GPRS+15)*4)(r3)
|
||||
FP( lfd 29,((JB_FPRS+15*2)*4)(r3))
|
||||
lwz r30,((JB_GPRS+16)*4)(r3)
|
||||
FP( lfd 30,((JB_FPRS+16*2)*4)(r3))
|
||||
lwz r31,((JB_GPRS+17)*4)(r3)
|
||||
FP( lfd 31,((JB_FPRS+17*2)*4)(r3))
|
||||
mr r3,r4
|
||||
blr
|
|
@ -0,0 +1,83 @@
|
|||
/* setjmp for PowerPC.
|
||||
Copyright (C) 1995, 1996, 1997, 1999, 2000 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <ppc_asm.tmpl>
|
||||
|
||||
# define JB_GPR1 0 /* Also known as the stack pointer */
|
||||
# define JB_GPR2 1
|
||||
# define JB_LR 2 /* The address we will return to */
|
||||
# define JB_GPRS 3 /* GPRs 14 through 31 are saved, 18 in total */
|
||||
# define JB_CR 21 /* Condition code registers. */
|
||||
# define JB_FPRS 22 /* FPRs 14 through 31 are saved, 18*2 words total */
|
||||
# define JB_SIZE (58*4)
|
||||
|
||||
#define FP(x...) x
|
||||
|
||||
.globl setctxsp;
|
||||
setctxsp:
|
||||
mr r1, r3
|
||||
blr
|
||||
|
||||
.globl ppc_setjmp;
|
||||
ppc_setjmp:
|
||||
stw r1,(JB_GPR1*4)(3)
|
||||
mflr r0
|
||||
stw r2,(JB_GPR2*4)(3)
|
||||
stw r14,((JB_GPRS+0)*4)(3)
|
||||
FP( stfd 14,((JB_FPRS+0*2)*4)(3))
|
||||
stw r0,(JB_LR*4)(3)
|
||||
stw r15,((JB_GPRS+1)*4)(3)
|
||||
FP( stfd 15,((JB_FPRS+1*2)*4)(3))
|
||||
mfcr r0
|
||||
stw r16,((JB_GPRS+2)*4)(3)
|
||||
FP( stfd 16,((JB_FPRS+2*2)*4)(3))
|
||||
stw r0,(JB_CR*4)(3)
|
||||
stw r17,((JB_GPRS+3)*4)(3)
|
||||
FP( stfd 17,((JB_FPRS+3*2)*4)(3))
|
||||
stw r18,((JB_GPRS+4)*4)(3)
|
||||
FP( stfd 18,((JB_FPRS+4*2)*4)(3))
|
||||
stw r19,((JB_GPRS+5)*4)(3)
|
||||
FP( stfd 19,((JB_FPRS+5*2)*4)(3))
|
||||
stw r20,((JB_GPRS+6)*4)(3)
|
||||
FP( stfd 20,((JB_FPRS+6*2)*4)(3))
|
||||
stw r21,((JB_GPRS+7)*4)(3)
|
||||
FP( stfd 21,((JB_FPRS+7*2)*4)(3))
|
||||
stw r22,((JB_GPRS+8)*4)(3)
|
||||
FP( stfd 22,((JB_FPRS+8*2)*4)(3))
|
||||
stw r23,((JB_GPRS+9)*4)(3)
|
||||
FP( stfd 23,((JB_FPRS+9*2)*4)(3))
|
||||
stw r24,((JB_GPRS+10)*4)(3)
|
||||
FP( stfd 24,((JB_FPRS+10*2)*4)(3))
|
||||
stw r25,((JB_GPRS+11)*4)(3)
|
||||
FP( stfd 25,((JB_FPRS+11*2)*4)(3))
|
||||
stw r26,((JB_GPRS+12)*4)(3)
|
||||
FP( stfd 26,((JB_FPRS+12*2)*4)(3))
|
||||
stw r27,((JB_GPRS+13)*4)(3)
|
||||
FP( stfd 27,((JB_FPRS+13*2)*4)(3))
|
||||
stw r28,((JB_GPRS+14)*4)(3)
|
||||
FP( stfd 28,((JB_FPRS+14*2)*4)(3))
|
||||
stw r29,((JB_GPRS+15)*4)(3)
|
||||
FP( stfd 29,((JB_FPRS+15*2)*4)(3))
|
||||
stw r30,((JB_GPRS+16)*4)(3)
|
||||
FP( stfd 30,((JB_FPRS+16*2)*4)(3))
|
||||
stw r31,((JB_GPRS+17)*4)(3)
|
||||
FP( stfd 31,((JB_FPRS+17*2)*4)(3))
|
||||
|
||||
li 3, 0
|
||||
blr
|
|
@ -0,0 +1,369 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <exports.h>
|
||||
|
||||
/*
|
||||
* Author: Arun Dharankar <ADharankar@ATTBI.Com>
|
||||
*
|
||||
* A very simple thread/schedular model:
|
||||
* - only one master thread, and no parent child relation maintained
|
||||
* - parent thread cannot be stopped or deleted
|
||||
* - no permissions or credentials
|
||||
* - no elaborate safety checks
|
||||
* - cooperative multi threading
|
||||
* - Simple round-robin scheduleing with no priorities
|
||||
* - no metering/statistics collection
|
||||
*
|
||||
* Basic idea of implementing this is to allow more than one tests to
|
||||
* execute "simultaneously".
|
||||
*
|
||||
* This may be modified such thread_yield may be called in syscalls, and
|
||||
* timer interrupts.
|
||||
*/
|
||||
|
||||
|
||||
#define MAX_THREADS 8
|
||||
|
||||
#define CTX_SIZE 512
|
||||
#define STK_SIZE 8*1024
|
||||
|
||||
#define STATE_EMPTY 0
|
||||
#define STATE_RUNNABLE 1
|
||||
#define STATE_STOPPED 2
|
||||
#define STATE_TERMINATED 2
|
||||
|
||||
#define MASTER_THREAD 0
|
||||
|
||||
#define RC_FAILURE (-1)
|
||||
#define RC_SUCCESS (0)
|
||||
|
||||
typedef vu_char *jmp_ctx;
|
||||
unsigned long setctxsp (vu_char *sp);
|
||||
int ppc_setjmp(jmp_ctx env);
|
||||
void ppc_longjmp(jmp_ctx env, int val);
|
||||
#define setjmp ppc_setjmp
|
||||
#define longjmp ppc_longjmp
|
||||
|
||||
struct lthread {
|
||||
int state;
|
||||
int retval;
|
||||
char stack[STK_SIZE];
|
||||
uchar context[CTX_SIZE];
|
||||
int (*func) (void *);
|
||||
void *arg;
|
||||
};
|
||||
static volatile struct lthread lthreads[MAX_THREADS];
|
||||
static volatile int current_tid = MASTER_THREAD;
|
||||
|
||||
|
||||
static uchar dbg = 0;
|
||||
|
||||
#define PDEBUG(fmt, args...) { \
|
||||
if(dbg != 0) { \
|
||||
printf("[%s %d %s]: ",__FILE__,__LINE__,__FUNCTION__);\
|
||||
printf(fmt, ##args); \
|
||||
printf("\n"); \
|
||||
} \
|
||||
}
|
||||
|
||||
static int testthread (void *);
|
||||
static void sched_init (void);
|
||||
static int thread_create (int (*func) (void *), void *arg);
|
||||
static int thread_start (int id);
|
||||
static void thread_yield (void);
|
||||
static int thread_delete (int id);
|
||||
static int thread_join (int *ret);
|
||||
|
||||
#if 0 /* not used yet */
|
||||
static int thread_stop (int id);
|
||||
#endif /* not used yet */
|
||||
|
||||
/* An example of schedular test */
|
||||
|
||||
#define NUMTHREADS 7
|
||||
int sched (int ac, char *av[])
|
||||
{
|
||||
int i, j;
|
||||
int tid[NUMTHREADS];
|
||||
int names[NUMTHREADS];
|
||||
|
||||
app_startup(av);
|
||||
|
||||
sched_init ();
|
||||
|
||||
for (i = 0; i < NUMTHREADS; i++) {
|
||||
names[i] = i;
|
||||
j = thread_create (testthread, (void *) &names[i]);
|
||||
if (j == RC_FAILURE)
|
||||
printf ("schedtest: Failed to create thread %d\n", i);
|
||||
if (j > 0) {
|
||||
printf ("schedtest: Created thread with id %d, name %d\n",
|
||||
j, i);
|
||||
tid[i] = j;
|
||||
}
|
||||
}
|
||||
printf ("schedtest: Threads created\n");
|
||||
|
||||
printf ("sched_test: function=0x%08x\n", (unsigned)testthread);
|
||||
for (i = 0; i < NUMTHREADS; i++) {
|
||||
printf ("schedtest: Setting thread %d runnable\n", tid[i]);
|
||||
thread_start (tid[i]);
|
||||
thread_yield ();
|
||||
}
|
||||
printf ("schedtest: Started %d threads\n", NUMTHREADS);
|
||||
|
||||
while (1) {
|
||||
printf ("schedtest: Waiting for threads to complete\n");
|
||||
if (tstc () && getc () == 0x3) {
|
||||
printf ("schedtest: Aborting threads...\n");
|
||||
for (i = 0; i < NUMTHREADS; i++) {
|
||||
printf ("schedtest: Deleting thread %d\n", tid[i]);
|
||||
thread_delete (tid[i]);
|
||||
}
|
||||
return RC_SUCCESS;
|
||||
}
|
||||
j = -1;
|
||||
i = thread_join (&j);
|
||||
if (i == RC_FAILURE) {
|
||||
printf ("schedtest: No threads pending, "
|
||||
"exiting schedular test\n");
|
||||
return RC_SUCCESS;
|
||||
}
|
||||
printf ("schedtest: thread is %d returned %d\n", i, j);
|
||||
thread_yield ();
|
||||
}
|
||||
|
||||
return RC_SUCCESS;
|
||||
}
|
||||
|
||||
static int testthread (void *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf ("testthread: Begin executing thread, myname %d, &i=0x%08x\n",
|
||||
*(int *) name, (unsigned)&i);
|
||||
|
||||
printf ("Thread %02d, i=%d\n", *(int *) name, i);
|
||||
|
||||
for (i = 0; i < 0xffff * (*(int *) name + 1); i++) {
|
||||
if (tstc () && getc () == 0x3) {
|
||||
printf ("testthread: myname %d terminating.\n",
|
||||
*(int *) name);
|
||||
return *(int *) name + 1;
|
||||
}
|
||||
|
||||
if (i % 100 == 0)
|
||||
thread_yield ();
|
||||
}
|
||||
|
||||
printf ("testthread: returning %d, i=0x%x\n",
|
||||
*(int *) name + 1, i);
|
||||
|
||||
return *(int *) name + 1;
|
||||
}
|
||||
|
||||
|
||||
static void sched_init (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = MASTER_THREAD + 1; i < MAX_THREADS; i++)
|
||||
lthreads[i].state = STATE_EMPTY;
|
||||
|
||||
current_tid = MASTER_THREAD;
|
||||
lthreads[current_tid].state = STATE_RUNNABLE;
|
||||
PDEBUG ("sched_init: master context = 0x%08x",
|
||||
(unsigned)lthreads[current_tid].context);
|
||||
return;
|
||||
}
|
||||
|
||||
static void thread_yield (void)
|
||||
{
|
||||
static int i;
|
||||
|
||||
PDEBUG ("thread_yield: current tid=%d", current_tid);
|
||||
|
||||
#define SWITCH(new) \
|
||||
if(lthreads[new].state == STATE_RUNNABLE) { \
|
||||
PDEBUG("thread_yield: %d match, ctx=0x%08x", \
|
||||
new, \
|
||||
(unsigned)lthreads[current_tid].context); \
|
||||
if(setjmp(lthreads[current_tid].context) == 0) { \
|
||||
current_tid = new; \
|
||||
PDEBUG("thread_yield: tid %d returns 0", \
|
||||
new); \
|
||||
longjmp(lthreads[new].context, 1); \
|
||||
} else { \
|
||||
PDEBUG("thread_yield: tid %d returns 1", \
|
||||
new); \
|
||||
return; \
|
||||
} \
|
||||
}
|
||||
|
||||
for (i = current_tid + 1; i < MAX_THREADS; i++) {
|
||||
SWITCH (i);
|
||||
}
|
||||
|
||||
if (current_tid != 0) {
|
||||
for (i = 0; i <= current_tid; i++) {
|
||||
SWITCH (i);
|
||||
}
|
||||
}
|
||||
|
||||
PDEBUG ("thread_yield: returning from thread_yield");
|
||||
return;
|
||||
}
|
||||
|
||||
static int thread_create (int (*func) (void *), void *arg)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = MASTER_THREAD + 1; i < MAX_THREADS; i++) {
|
||||
if (lthreads[i].state == STATE_EMPTY) {
|
||||
lthreads[i].state = STATE_STOPPED;
|
||||
lthreads[i].func = func;
|
||||
lthreads[i].arg = arg;
|
||||
PDEBUG ("thread_create: returns new tid %d", i);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
PDEBUG ("thread_create: returns failure");
|
||||
return RC_FAILURE;
|
||||
}
|
||||
|
||||
static int thread_delete (int id)
|
||||
{
|
||||
if (id <= MASTER_THREAD || id > MAX_THREADS)
|
||||
return RC_FAILURE;
|
||||
|
||||
if (current_tid == id)
|
||||
return RC_FAILURE;
|
||||
|
||||
lthreads[id].state = STATE_EMPTY;
|
||||
return RC_SUCCESS;
|
||||
}
|
||||
|
||||
static void thread_launcher (void)
|
||||
{
|
||||
PDEBUG ("thread_launcher: invoking func=0x%08x",
|
||||
(unsigned)lthreads[current_tid].func);
|
||||
|
||||
lthreads[current_tid].retval =
|
||||
lthreads[current_tid].func (lthreads[current_tid].arg);
|
||||
|
||||
PDEBUG ("thread_launcher: tid %d terminated", current_tid);
|
||||
|
||||
lthreads[current_tid].state = STATE_TERMINATED;
|
||||
thread_yield ();
|
||||
printf ("thread_launcher: should NEVER get here!\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int thread_start (int id)
|
||||
{
|
||||
PDEBUG ("thread_start: id=%d", id);
|
||||
if (id <= MASTER_THREAD || id > MAX_THREADS) {
|
||||
return RC_FAILURE;
|
||||
}
|
||||
|
||||
if (lthreads[id].state != STATE_STOPPED)
|
||||
return RC_FAILURE;
|
||||
|
||||
if (setjmp (lthreads[current_tid].context) == 0) {
|
||||
lthreads[id].state = STATE_RUNNABLE;
|
||||
current_tid = id;
|
||||
PDEBUG ("thread_start: to be stack=0%08x",
|
||||
(unsigned)lthreads[id].stack);
|
||||
setctxsp ((vu_char *)<hreads[id].stack[STK_SIZE]);
|
||||
thread_launcher ();
|
||||
}
|
||||
|
||||
PDEBUG ("thread_start: Thread id=%d started, parent returns", id);
|
||||
|
||||
return RC_SUCCESS;
|
||||
}
|
||||
|
||||
#if 0 /* not used so far */
|
||||
static int thread_stop (int id)
|
||||
{
|
||||
if (id <= MASTER_THREAD || id >= MAX_THREADS)
|
||||
return RC_FAILURE;
|
||||
|
||||
if (current_tid == id)
|
||||
return RC_FAILURE;
|
||||
|
||||
lthreads[id].state = STATE_STOPPED;
|
||||
return RC_SUCCESS;
|
||||
}
|
||||
#endif /* not used so far */
|
||||
|
||||
static int thread_join (int *ret)
|
||||
{
|
||||
int i, j = 0;
|
||||
|
||||
PDEBUG ("thread_join: *ret = %d", *ret);
|
||||
|
||||
if (!(*ret == -1 || *ret > MASTER_THREAD || *ret < MAX_THREADS)) {
|
||||
PDEBUG ("thread_join: invalid tid %d", *ret);
|
||||
return RC_FAILURE;
|
||||
}
|
||||
|
||||
if (*ret == -1) {
|
||||
PDEBUG ("Checking for tid = -1");
|
||||
while (1) {
|
||||
/* PDEBUG("thread_join: start while-loopn"); */
|
||||
j = 0;
|
||||
for (i = MASTER_THREAD + 1; i < MAX_THREADS; i++) {
|
||||
if (lthreads[i].state == STATE_TERMINATED) {
|
||||
*ret = lthreads[i].retval;
|
||||
lthreads[i].state = STATE_EMPTY;
|
||||
/* PDEBUG("thread_join: returning retval %d of tid %d",
|
||||
ret, i); */
|
||||
return RC_SUCCESS;
|
||||
}
|
||||
|
||||
if (lthreads[i].state != STATE_EMPTY) {
|
||||
PDEBUG ("thread_join: %d used slots tid %d state=%d",
|
||||
j, i, lthreads[i].state);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
if (j == 0) {
|
||||
PDEBUG ("thread_join: all slots empty!");
|
||||
return RC_FAILURE;
|
||||
}
|
||||
/* PDEBUG("thread_join: yielding"); */
|
||||
thread_yield ();
|
||||
/* PDEBUG("thread_join: back from yield"); */
|
||||
}
|
||||
}
|
||||
|
||||
if (lthreads[*ret].state == STATE_TERMINATED) {
|
||||
i = *ret;
|
||||
*ret = lthreads[*ret].retval;
|
||||
lthreads[*ret].state = STATE_EMPTY;
|
||||
PDEBUG ("thread_join: returing %d for tid %d", *ret, i);
|
||||
return RC_SUCCESS;
|
||||
}
|
||||
|
||||
PDEBUG ("thread_join: thread %d is not terminated!", *ret);
|
||||
return RC_FAILURE;
|
||||
}
|
|
@ -0,0 +1,388 @@
|
|||
/*
|
||||
* (C) Copyright 2004
|
||||
* Robin Getz rgetz@blacfin.uclinux.org
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Heavily borrowed from the following peoples GPL'ed software:
|
||||
* - Wolfgang Denk, DENX Software Engineering, wd@denx.de
|
||||
* Das U-boot
|
||||
* - Ladislav Michl ladis@linux-mips.org
|
||||
* A rejected patch on the U-Boot mailing list
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <exports.h>
|
||||
#include "../drivers/net/smc91111.h"
|
||||
|
||||
#ifndef SMC91111_EEPROM_INIT
|
||||
# define SMC91111_EEPROM_INIT()
|
||||
#endif
|
||||
|
||||
#define SMC_BASE_ADDRESS CONFIG_SMC91111_BASE
|
||||
#define EEPROM 0x1
|
||||
#define MAC 0x2
|
||||
#define UNKNOWN 0x4
|
||||
|
||||
void dump_reg (struct eth_device *dev);
|
||||
void dump_eeprom (struct eth_device *dev);
|
||||
int write_eeprom_reg (struct eth_device *dev, int value, int reg);
|
||||
void copy_from_eeprom (struct eth_device *dev);
|
||||
void print_MAC (struct eth_device *dev);
|
||||
int read_eeprom_reg (struct eth_device *dev, int reg);
|
||||
void print_macaddr (struct eth_device *dev);
|
||||
|
||||
int smc91111_eeprom (int argc, char * const argv[])
|
||||
{
|
||||
int c, i, j, done, line, reg, value, start, what;
|
||||
char input[50];
|
||||
|
||||
struct eth_device dev;
|
||||
dev.iobase = CONFIG_SMC91111_BASE;
|
||||
|
||||
/* Print the ABI version */
|
||||
app_startup (argv);
|
||||
if (XF_VERSION != (int) get_version ()) {
|
||||
printf ("Expects ABI version %d\n", XF_VERSION);
|
||||
printf ("Actual U-Boot ABI version %d\n",
|
||||
(int) get_version ());
|
||||
printf ("Can't run\n\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
SMC91111_EEPROM_INIT();
|
||||
|
||||
if ((SMC_inw (&dev, BANK_SELECT) & 0xFF00) != 0x3300) {
|
||||
printf ("Can't find SMSC91111\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
done = 0;
|
||||
what = UNKNOWN;
|
||||
printf ("\n");
|
||||
while (!done) {
|
||||
/* print the prompt */
|
||||
printf ("SMC91111> ");
|
||||
line = 0;
|
||||
i = 0;
|
||||
start = 1;
|
||||
while (!line) {
|
||||
/* Wait for a keystroke */
|
||||
while (!tstc ());
|
||||
|
||||
c = getc ();
|
||||
/* Make Uppercase */
|
||||
if (c >= 'Z')
|
||||
c -= ('a' - 'A');
|
||||
/* printf(" |%02x| ",c); */
|
||||
|
||||
switch (c) {
|
||||
case '\r': /* Enter */
|
||||
case '\n':
|
||||
input[i] = 0;
|
||||
puts ("\r\n");
|
||||
line = 1;
|
||||
break;
|
||||
case '\0': /* nul */
|
||||
continue;
|
||||
|
||||
case 0x03: /* ^C - break */
|
||||
input[0] = 0;
|
||||
i = 0;
|
||||
line = 1;
|
||||
done = 1;
|
||||
break;
|
||||
|
||||
case 0x5F:
|
||||
case 0x08: /* ^H - backspace */
|
||||
case 0x7F: /* DEL - backspace */
|
||||
if (i > 0) {
|
||||
puts ("\b \b");
|
||||
i--;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (start) {
|
||||
if ((c == 'W') || (c == 'D')
|
||||
|| (c == 'M') || (c == 'C')
|
||||
|| (c == 'P')) {
|
||||
putc (c);
|
||||
input[i] = c;
|
||||
if (i <= 45)
|
||||
i++;
|
||||
start = 0;
|
||||
}
|
||||
} else {
|
||||
if ((c >= '0' && c <= '9')
|
||||
|| (c >= 'A' && c <= 'F')
|
||||
|| (c == 'E') || (c == 'M')
|
||||
|| (c == ' ')) {
|
||||
putc (c);
|
||||
input[i] = c;
|
||||
if (i <= 45)
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (; i < 49; i++)
|
||||
input[i] = 0;
|
||||
|
||||
switch (input[0]) {
|
||||
case ('W'):
|
||||
/* Line should be w reg value */
|
||||
i = 0;
|
||||
reg = 0;
|
||||
value = 0;
|
||||
/* Skip to the next space or end) */
|
||||
while ((input[i] != ' ') && (input[i] != 0))
|
||||
i++;
|
||||
|
||||
if (input[i] != 0)
|
||||
i++;
|
||||
|
||||
/* Are we writing to EEPROM or MAC */
|
||||
switch (input[i]) {
|
||||
case ('E'):
|
||||
what = EEPROM;
|
||||
break;
|
||||
case ('M'):
|
||||
what = MAC;
|
||||
break;
|
||||
default:
|
||||
what = UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
/* skip to the next space or end */
|
||||
while ((input[i] != ' ') && (input[i] != 0))
|
||||
i++;
|
||||
if (input[i] != 0)
|
||||
i++;
|
||||
|
||||
/* Find register to write into */
|
||||
j = 0;
|
||||
while ((input[i] != ' ') && (input[i] != 0)) {
|
||||
j = input[i] - 0x30;
|
||||
if (j >= 0xA) {
|
||||
j -= 0x07;
|
||||
}
|
||||
reg = (reg * 0x10) + j;
|
||||
i++;
|
||||
}
|
||||
|
||||
while ((input[i] != ' ') && (input[i] != 0))
|
||||
i++;
|
||||
|
||||
if (input[i] != 0)
|
||||
i++;
|
||||
else
|
||||
what = UNKNOWN;
|
||||
|
||||
/* Get the value to write */
|
||||
j = 0;
|
||||
while ((input[i] != ' ') && (input[i] != 0)) {
|
||||
j = input[i] - 0x30;
|
||||
if (j >= 0xA) {
|
||||
j -= 0x07;
|
||||
}
|
||||
value = (value * 0x10) + j;
|
||||
i++;
|
||||
}
|
||||
|
||||
switch (what) {
|
||||
case 1:
|
||||
printf ("Writing EEPROM register %02x with %04x\n", reg, value);
|
||||
write_eeprom_reg (&dev, value, reg);
|
||||
break;
|
||||
case 2:
|
||||
printf ("Writing MAC register bank %i, reg %02x with %04x\n", reg >> 4, reg & 0xE, value);
|
||||
SMC_SELECT_BANK (&dev, reg >> 4);
|
||||
SMC_outw (&dev, value, reg & 0xE);
|
||||
break;
|
||||
default:
|
||||
printf ("Wrong\n");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ('D'):
|
||||
dump_eeprom (&dev);
|
||||
break;
|
||||
case ('M'):
|
||||
dump_reg (&dev);
|
||||
break;
|
||||
case ('C'):
|
||||
copy_from_eeprom (&dev);
|
||||
break;
|
||||
case ('P'):
|
||||
print_macaddr (&dev);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void copy_from_eeprom (struct eth_device *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
SMC_SELECT_BANK (dev, 1);
|
||||
SMC_outw (dev, (SMC_inw (dev, CTL_REG) & !CTL_EEPROM_SELECT) |
|
||||
CTL_RELOAD, CTL_REG);
|
||||
i = 100;
|
||||
while ((SMC_inw (dev, CTL_REG) & CTL_RELOAD) && --i)
|
||||
udelay (100);
|
||||
if (i == 0) {
|
||||
printf ("Timeout Refreshing EEPROM registers\n");
|
||||
} else {
|
||||
printf ("EEPROM contents copied to MAC\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void print_macaddr (struct eth_device *dev)
|
||||
{
|
||||
int i, j, k, mac[6];
|
||||
|
||||
printf ("Current MAC Address in SMSC91111 ");
|
||||
SMC_SELECT_BANK (dev, 1);
|
||||
for (i = 0; i < 5; i++) {
|
||||
printf ("%02x:", SMC_inb (dev, ADDR0_REG + i));
|
||||
}
|
||||
|
||||
printf ("%02x\n", SMC_inb (dev, ADDR0_REG + 5));
|
||||
|
||||
i = 0;
|
||||
for (j = 0x20; j < 0x23; j++) {
|
||||
k = read_eeprom_reg (dev, j);
|
||||
mac[i] = k & 0xFF;
|
||||
i++;
|
||||
mac[i] = k >> 8;
|
||||
i++;
|
||||
}
|
||||
|
||||
printf ("Current MAC Address in EEPROM ");
|
||||
for (i = 0; i < 5; i++)
|
||||
printf ("%02x:", mac[i]);
|
||||
printf ("%02x\n", mac[5]);
|
||||
|
||||
}
|
||||
void dump_eeprom (struct eth_device *dev)
|
||||
{
|
||||
int j, k;
|
||||
|
||||
printf ("IOS2-0 ");
|
||||
for (j = 0; j < 8; j++) {
|
||||
printf ("%03x ", j);
|
||||
}
|
||||
printf ("\n");
|
||||
|
||||
for (k = 0; k < 4; k++) {
|
||||
if (k == 0)
|
||||
printf ("CONFIG ");
|
||||
if (k == 1)
|
||||
printf ("BASE ");
|
||||
if ((k == 2) || (k == 3))
|
||||
printf (" ");
|
||||
for (j = 0; j < 0x20; j += 4) {
|
||||
printf ("%02x:%04x ", j + k,
|
||||
read_eeprom_reg (dev, j + k));
|
||||
}
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
for (j = 0x20; j < 0x40; j++) {
|
||||
if ((j & 0x07) == 0)
|
||||
printf ("\n");
|
||||
printf ("%02x:%04x ", j, read_eeprom_reg (dev, j));
|
||||
}
|
||||
printf ("\n");
|
||||
|
||||
}
|
||||
|
||||
int read_eeprom_reg (struct eth_device *dev, int reg)
|
||||
{
|
||||
int timeout;
|
||||
|
||||
SMC_SELECT_BANK (dev, 2);
|
||||
SMC_outw (dev, reg, PTR_REG);
|
||||
|
||||
SMC_SELECT_BANK (dev, 1);
|
||||
SMC_outw (dev, SMC_inw (dev, CTL_REG) | CTL_EEPROM_SELECT |
|
||||
CTL_RELOAD, CTL_REG);
|
||||
timeout = 100;
|
||||
while ((SMC_inw (dev, CTL_REG) & CTL_RELOAD) && --timeout)
|
||||
udelay (100);
|
||||
if (timeout == 0) {
|
||||
printf ("Timeout Reading EEPROM register %02x\n", reg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return SMC_inw (dev, GP_REG);
|
||||
|
||||
}
|
||||
|
||||
int write_eeprom_reg (struct eth_device *dev, int value, int reg)
|
||||
{
|
||||
int timeout;
|
||||
|
||||
SMC_SELECT_BANK (dev, 2);
|
||||
SMC_outw (dev, reg, PTR_REG);
|
||||
|
||||
SMC_SELECT_BANK (dev, 1);
|
||||
SMC_outw (dev, value, GP_REG);
|
||||
SMC_outw (dev, SMC_inw (dev, CTL_REG) | CTL_EEPROM_SELECT |
|
||||
CTL_STORE, CTL_REG);
|
||||
timeout = 100;
|
||||
while ((SMC_inw (dev, CTL_REG) & CTL_STORE) && --timeout)
|
||||
udelay (100);
|
||||
if (timeout == 0) {
|
||||
printf ("Timeout Writing EEPROM register %02x\n", reg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
void dump_reg (struct eth_device *dev)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
printf (" ");
|
||||
for (j = 0; j < 4; j++) {
|
||||
printf ("Bank%i ", j);
|
||||
}
|
||||
printf ("\n");
|
||||
for (i = 0; i < 0xF; i += 2) {
|
||||
printf ("%02x ", i);
|
||||
for (j = 0; j < 4; j++) {
|
||||
SMC_SELECT_BANK (dev, j);
|
||||
printf ("%04x ", SMC_inw (dev, i));
|
||||
}
|
||||
printf ("\n");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,378 @@
|
|||
/*
|
||||
* smc911x_eeprom.c - EEPROM interface to SMC911x parts.
|
||||
* Only tested on SMSC9118 though ...
|
||||
*
|
||||
* Copyright 2004-2009 Analog Devices Inc.
|
||||
*
|
||||
* Licensed under the GPL-2 or later.
|
||||
*
|
||||
* Based on smc91111_eeprom.c which:
|
||||
* Heavily borrowed from the following peoples GPL'ed software:
|
||||
* - Wolfgang Denk, DENX Software Engineering, wd@denx.de
|
||||
* Das U-boot
|
||||
* - Ladislav Michl ladis@linux-mips.org
|
||||
* A rejected patch on the U-Boot mailing list
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <exports.h>
|
||||
#include <linux/ctype.h>
|
||||
#include "../drivers/net/smc911x.h"
|
||||
|
||||
/**
|
||||
* smsc_ctrlc - detect press of CTRL+C (common ctrlc() isnt exported!?)
|
||||
*/
|
||||
static int smsc_ctrlc(void)
|
||||
{
|
||||
return (tstc() && getc() == 0x03);
|
||||
}
|
||||
|
||||
/**
|
||||
* usage - dump usage information
|
||||
*/
|
||||
static void usage(void)
|
||||
{
|
||||
puts(
|
||||
"MAC/EEPROM Commands:\n"
|
||||
" P : Print the MAC addresses\n"
|
||||
" D : Dump the EEPROM contents\n"
|
||||
" M : Dump the MAC contents\n"
|
||||
" C : Copy the MAC address from the EEPROM to the MAC\n"
|
||||
" W : Write a register in the EEPROM or in the MAC\n"
|
||||
" Q : Quit\n"
|
||||
"\n"
|
||||
"Some commands take arguments:\n"
|
||||
" W <E|M> <register> <value>\n"
|
||||
" E: EEPROM M: MAC\n"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* dump_regs - dump the MAC registers
|
||||
*
|
||||
* Registers 0x00 - 0x50 are FIFOs. The 0x50+ are the control registers
|
||||
* and they're all 32bits long. 0xB8+ are reserved, so don't bother.
|
||||
*/
|
||||
static void dump_regs(struct eth_device *dev)
|
||||
{
|
||||
u8 i, j = 0;
|
||||
for (i = 0x50; i < 0xB8; i += sizeof(u32))
|
||||
printf("%02x: 0x%08x %c", i,
|
||||
smc911x_reg_read(dev, i),
|
||||
(j++ % 2 ? '\n' : ' '));
|
||||
}
|
||||
|
||||
/**
|
||||
* do_eeprom_cmd - handle eeprom communication
|
||||
*/
|
||||
static int do_eeprom_cmd(struct eth_device *dev, int cmd, u8 reg)
|
||||
{
|
||||
if (smc911x_reg_read(dev, E2P_CMD) & E2P_CMD_EPC_BUSY) {
|
||||
printf("eeprom_cmd: busy at start (E2P_CMD = 0x%08x)\n",
|
||||
smc911x_reg_read(dev, E2P_CMD));
|
||||
return -1;
|
||||
}
|
||||
|
||||
smc911x_reg_write(dev, E2P_CMD, E2P_CMD_EPC_BUSY | cmd | reg);
|
||||
|
||||
while (smc911x_reg_read(dev, E2P_CMD) & E2P_CMD_EPC_BUSY)
|
||||
if (smsc_ctrlc()) {
|
||||
printf("eeprom_cmd: timeout (E2P_CMD = 0x%08x)\n",
|
||||
smc911x_reg_read(dev, E2P_CMD));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* read_eeprom_reg - read specified register in EEPROM
|
||||
*/
|
||||
static u8 read_eeprom_reg(struct eth_device *dev, u8 reg)
|
||||
{
|
||||
int ret = do_eeprom_cmd(dev, E2P_CMD_EPC_CMD_READ, reg);
|
||||
return (ret ? : smc911x_reg_read(dev, E2P_DATA));
|
||||
}
|
||||
|
||||
/**
|
||||
* write_eeprom_reg - write specified value into specified register in EEPROM
|
||||
*/
|
||||
static int write_eeprom_reg(struct eth_device *dev, u8 value, u8 reg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* enable erasing/writing */
|
||||
ret = do_eeprom_cmd(dev, E2P_CMD_EPC_CMD_EWEN, reg);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
/* erase the eeprom reg */
|
||||
ret = do_eeprom_cmd(dev, E2P_CMD_EPC_CMD_ERASE, reg);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
/* write the eeprom reg */
|
||||
smc911x_reg_write(dev, E2P_DATA, value);
|
||||
ret = do_eeprom_cmd(dev, E2P_CMD_EPC_CMD_WRITE, reg);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
/* disable erasing/writing */
|
||||
ret = do_eeprom_cmd(dev, E2P_CMD_EPC_CMD_EWDS, reg);
|
||||
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* skip_space - find first non-whitespace in given pointer
|
||||
*/
|
||||
static char *skip_space(char *buf)
|
||||
{
|
||||
while (isblank(buf[0]))
|
||||
++buf;
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* write_stuff - handle writing of MAC registers / eeprom
|
||||
*/
|
||||
static void write_stuff(struct eth_device *dev, char *line)
|
||||
{
|
||||
char dest;
|
||||
char *endp;
|
||||
u8 reg;
|
||||
u32 value;
|
||||
|
||||
/* Skip over the "W " part of the command */
|
||||
line = skip_space(line + 1);
|
||||
|
||||
/* Figure out destination */
|
||||
switch (line[0]) {
|
||||
case 'E':
|
||||
case 'M':
|
||||
dest = line[0];
|
||||
break;
|
||||
default:
|
||||
invalid_usage:
|
||||
printf("ERROR: Invalid write usage\n");
|
||||
usage();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the register to write */
|
||||
line = skip_space(line + 1);
|
||||
reg = simple_strtoul(line, &endp, 16);
|
||||
if (line == endp)
|
||||
goto invalid_usage;
|
||||
|
||||
/* Get the value to write */
|
||||
line = skip_space(endp);
|
||||
value = simple_strtoul(line, &endp, 16);
|
||||
if (line == endp)
|
||||
goto invalid_usage;
|
||||
|
||||
/* Check for trailing cruft */
|
||||
line = skip_space(endp);
|
||||
if (line[0])
|
||||
goto invalid_usage;
|
||||
|
||||
/* Finally, execute the command */
|
||||
if (dest == 'E') {
|
||||
printf("Writing EEPROM register %02x with %02x\n", reg, value);
|
||||
write_eeprom_reg(dev, value, reg);
|
||||
} else {
|
||||
printf("Writing MAC register %02x with %08x\n", reg, value);
|
||||
smc911x_reg_write(dev, reg, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* copy_from_eeprom - copy MAC address in eeprom to address registers
|
||||
*/
|
||||
static void copy_from_eeprom(struct eth_device *dev)
|
||||
{
|
||||
ulong addrl =
|
||||
read_eeprom_reg(dev, 0x01) |
|
||||
read_eeprom_reg(dev, 0x02) << 8 |
|
||||
read_eeprom_reg(dev, 0x03) << 16 |
|
||||
read_eeprom_reg(dev, 0x04) << 24;
|
||||
ulong addrh =
|
||||
read_eeprom_reg(dev, 0x05) |
|
||||
read_eeprom_reg(dev, 0x06) << 8;
|
||||
smc911x_set_mac_csr(dev, ADDRL, addrl);
|
||||
smc911x_set_mac_csr(dev, ADDRH, addrh);
|
||||
puts("EEPROM contents copied to MAC\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* print_macaddr - print MAC address registers and MAC address in eeprom
|
||||
*/
|
||||
static void print_macaddr(struct eth_device *dev)
|
||||
{
|
||||
puts("Current MAC Address in MAC: ");
|
||||
ulong addrl = smc911x_get_mac_csr(dev, ADDRL);
|
||||
ulong addrh = smc911x_get_mac_csr(dev, ADDRH);
|
||||
printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
(u8)(addrl), (u8)(addrl >> 8), (u8)(addrl >> 16),
|
||||
(u8)(addrl >> 24), (u8)(addrh), (u8)(addrh >> 8));
|
||||
|
||||
puts("Current MAC Address in EEPROM: ");
|
||||
int i;
|
||||
for (i = 1; i < 6; ++i)
|
||||
printf("%02x:", read_eeprom_reg(dev, i));
|
||||
printf("%02x\n", read_eeprom_reg(dev, i));
|
||||
}
|
||||
|
||||
/**
|
||||
* dump_eeprom - dump the whole content of the EEPROM
|
||||
*/
|
||||
static void dump_eeprom(struct eth_device *dev)
|
||||
{
|
||||
int i;
|
||||
puts("EEPROM:\n");
|
||||
for (i = 0; i < 7; ++i)
|
||||
printf("%02x: 0x%02x\n", i, read_eeprom_reg(dev, i));
|
||||
}
|
||||
|
||||
/**
|
||||
* smc911x_init - get the MAC/EEPROM up and ready for use
|
||||
*/
|
||||
static int smc911x_init(struct eth_device *dev)
|
||||
{
|
||||
/* See if there is anything there */
|
||||
if (smc911x_detect_chip(dev))
|
||||
return 1;
|
||||
|
||||
smc911x_reset(dev);
|
||||
|
||||
/* Make sure we set EEDIO/EECLK to the EEPROM */
|
||||
if (smc911x_reg_read(dev, GPIO_CFG) & GPIO_CFG_EEPR_EN) {
|
||||
while (smc911x_reg_read(dev, E2P_CMD) & E2P_CMD_EPC_BUSY)
|
||||
if (smsc_ctrlc()) {
|
||||
printf("init: timeout (E2P_CMD = 0x%08x)\n",
|
||||
smc911x_reg_read(dev, E2P_CMD));
|
||||
return 1;
|
||||
}
|
||||
smc911x_reg_write(dev, GPIO_CFG,
|
||||
smc911x_reg_read(dev, GPIO_CFG) & ~GPIO_CFG_EEPR_EN);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* getline - consume a line of input and handle some escape sequences
|
||||
*/
|
||||
static char *getline(void)
|
||||
{
|
||||
static char buffer[100];
|
||||
char c;
|
||||
size_t i;
|
||||
|
||||
i = 0;
|
||||
while (1) {
|
||||
buffer[i] = '\0';
|
||||
while (!tstc())
|
||||
continue;
|
||||
|
||||
c = getc();
|
||||
/* Convert to uppercase */
|
||||
if (c >= 'a' && c <= 'z')
|
||||
c -= ('a' - 'A');
|
||||
|
||||
switch (c) {
|
||||
case '\r': /* Enter/Return key */
|
||||
case '\n':
|
||||
puts("\n");
|
||||
return buffer;
|
||||
|
||||
case 0x03: /* ^C - break */
|
||||
return NULL;
|
||||
|
||||
case 0x5F:
|
||||
case 0x08: /* ^H - backspace */
|
||||
case 0x7F: /* DEL - backspace */
|
||||
if (i) {
|
||||
puts("\b \b");
|
||||
i--;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Ignore control characters */
|
||||
if (c < 0x20)
|
||||
break;
|
||||
/* Queue up all other characters */
|
||||
buffer[i++] = c;
|
||||
printf("%c", c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* smc911x_eeprom - our application's main() function
|
||||
*/
|
||||
int smc911x_eeprom(int argc, char * const argv[])
|
||||
{
|
||||
/* Avoid initializing on stack as gcc likes to call memset() */
|
||||
struct eth_device dev;
|
||||
dev.iobase = CONFIG_SMC911X_BASE;
|
||||
|
||||
/* Print the ABI version */
|
||||
app_startup(argv);
|
||||
if (XF_VERSION != get_version()) {
|
||||
printf("Expects ABI version %d\n", XF_VERSION);
|
||||
printf("Actual U-Boot ABI version %lu\n", get_version());
|
||||
printf("Can't run\n\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Initialize the MAC/EEPROM somewhat */
|
||||
puts("\n");
|
||||
if (smc911x_init(&dev))
|
||||
return 1;
|
||||
|
||||
/* Dump helpful usage information */
|
||||
puts("\n");
|
||||
usage();
|
||||
puts("\n");
|
||||
|
||||
while (1) {
|
||||
char *line;
|
||||
|
||||
/* Send the prompt and wait for a line */
|
||||
puts("eeprom> ");
|
||||
line = getline();
|
||||
|
||||
/* Got a ctrl+c */
|
||||
if (!line)
|
||||
return 0;
|
||||
|
||||
/* Eat leading space */
|
||||
line = skip_space(line);
|
||||
|
||||
/* Empty line, try again */
|
||||
if (!line[0])
|
||||
continue;
|
||||
|
||||
/* Only accept 1 letter commands */
|
||||
if (line[0] && line[1] && !isblank(line[1]))
|
||||
goto unknown_cmd;
|
||||
|
||||
/* Now parse the command */
|
||||
switch (line[0]) {
|
||||
case 'W': write_stuff(&dev, line); break;
|
||||
case 'D': dump_eeprom(&dev); break;
|
||||
case 'M': dump_regs(&dev); break;
|
||||
case 'C': copy_from_eeprom(&dev); break;
|
||||
case 'P': print_macaddr(&dev); break;
|
||||
unknown_cmd:
|
||||
default: puts("ERROR: Unknown command!\n\n");
|
||||
case '?':
|
||||
case 'H': usage(); break;
|
||||
case 'Q': return 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* (C) Copyright 2003, Psyent Corporation <www.psyent.com>
|
||||
* Scott McNutt <smcnutt@psyent.com>
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
OUTPUT_FORMAT("elf32-sparc", "elf32-sparc", "elf32-sparc")
|
||||
OUTPUT_ARCH(sparc)
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
*(.text)
|
||||
}
|
||||
__text_end = .;
|
||||
|
||||
. = ALIGN(4);
|
||||
.rodata :
|
||||
{
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
|
||||
}
|
||||
__rodata_end = .;
|
||||
|
||||
. = ALIGN(4);
|
||||
.data :
|
||||
{
|
||||
*(.data)
|
||||
}
|
||||
. = ALIGN(4);
|
||||
__data_end = .;
|
||||
|
||||
__bss_start = .;
|
||||
. = ALIGN(4);
|
||||
.bss :
|
||||
{
|
||||
*(.bss)
|
||||
}
|
||||
. = ALIGN(4);
|
||||
__bss_end = .;
|
||||
_end = .;
|
||||
}
|
|
@ -0,0 +1,238 @@
|
|||
#include <common.h>
|
||||
#include <exports.h>
|
||||
|
||||
#ifndef GCC_VERSION
|
||||
#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
|
||||
#endif /* GCC_VERSION */
|
||||
|
||||
#if defined(CONFIG_X86)
|
||||
/*
|
||||
* x86 does not have a dedicated register to store the pointer to
|
||||
* the global_data. Thus the jump table address is stored in a
|
||||
* global variable, but such approach does not allow for execution
|
||||
* from flash memory. The global_data address is passed as argv[-1]
|
||||
* to the application program.
|
||||
*/
|
||||
static void **jt;
|
||||
gd_t *global_data;
|
||||
|
||||
#define EXPORT_FUNC(x) \
|
||||
asm volatile ( \
|
||||
" .globl " #x "\n" \
|
||||
#x ":\n" \
|
||||
" movl %0, %%eax\n" \
|
||||
" movl jt, %%ecx\n" \
|
||||
" jmp *(%%ecx, %%eax)\n" \
|
||||
: : "i"(XF_ ## x * sizeof(void *)) : "eax", "ecx");
|
||||
#elif defined(CONFIG_PPC)
|
||||
/*
|
||||
* r2 holds the pointer to the global_data, r11 is a call-clobbered
|
||||
* register
|
||||
*/
|
||||
#define EXPORT_FUNC(x) \
|
||||
asm volatile ( \
|
||||
" .globl " #x "\n" \
|
||||
#x ":\n" \
|
||||
" lwz %%r11, %0(%%r2)\n" \
|
||||
" lwz %%r11, %1(%%r11)\n" \
|
||||
" mtctr %%r11\n" \
|
||||
" bctr\n" \
|
||||
: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "r11");
|
||||
#elif defined(CONFIG_ARM)
|
||||
/*
|
||||
* r8 holds the pointer to the global_data, ip is a call-clobbered
|
||||
* register
|
||||
*/
|
||||
#define EXPORT_FUNC(x) \
|
||||
asm volatile ( \
|
||||
" .globl " #x "\n" \
|
||||
#x ":\n" \
|
||||
" ldr ip, [r8, %0]\n" \
|
||||
" ldr pc, [ip, %1]\n" \
|
||||
: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "ip");
|
||||
#elif defined(CONFIG_MIPS)
|
||||
/*
|
||||
* k0 ($26) holds the pointer to the global_data; t9 ($25) is a call-
|
||||
* clobbered register that is also used to set gp ($26). Note that the
|
||||
* jr instruction also executes the instruction immediately following
|
||||
* it; however, GCC/mips generates an additional `nop' after each asm
|
||||
* statement
|
||||
*/
|
||||
#define EXPORT_FUNC(x) \
|
||||
asm volatile ( \
|
||||
" .globl " #x "\n" \
|
||||
#x ":\n" \
|
||||
" lw $25, %0($26)\n" \
|
||||
" lw $25, %1($25)\n" \
|
||||
" jr $25\n" \
|
||||
: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "t9");
|
||||
#elif defined(CONFIG_NIOS2)
|
||||
/*
|
||||
* gp holds the pointer to the global_data, r8 is call-clobbered
|
||||
*/
|
||||
#define EXPORT_FUNC(x) \
|
||||
asm volatile ( \
|
||||
" .globl " #x "\n" \
|
||||
#x ":\n" \
|
||||
" movhi r8, %%hi(%0)\n" \
|
||||
" ori r8, r0, %%lo(%0)\n" \
|
||||
" add r8, r8, gp\n" \
|
||||
" ldw r8, 0(r8)\n" \
|
||||
" ldw r8, %1(r8)\n" \
|
||||
" jmp r8\n" \
|
||||
: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "gp");
|
||||
#elif defined(CONFIG_M68K)
|
||||
/*
|
||||
* d7 holds the pointer to the global_data, a0 is a call-clobbered
|
||||
* register
|
||||
*/
|
||||
#define EXPORT_FUNC(x) \
|
||||
asm volatile ( \
|
||||
" .globl " #x "\n" \
|
||||
#x ":\n" \
|
||||
" move.l %%d7, %%a0\n" \
|
||||
" adda.l %0, %%a0\n" \
|
||||
" move.l (%%a0), %%a0\n" \
|
||||
" adda.l %1, %%a0\n" \
|
||||
" move.l (%%a0), %%a0\n" \
|
||||
" jmp (%%a0)\n" \
|
||||
: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "a0");
|
||||
#elif defined(CONFIG_MICROBLAZE)
|
||||
/*
|
||||
* r31 holds the pointer to the global_data. r5 is a call-clobbered.
|
||||
*/
|
||||
#define EXPORT_FUNC(x) \
|
||||
asm volatile ( \
|
||||
" .globl " #x "\n" \
|
||||
#x ":\n" \
|
||||
" lwi r5, r31, %0\n" \
|
||||
" lwi r5, r5, %1\n" \
|
||||
" bra r5\n" \
|
||||
: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "r5");
|
||||
#elif defined(CONFIG_BLACKFIN)
|
||||
/*
|
||||
* P3 holds the pointer to the global_data, P0 is a call-clobbered
|
||||
* register
|
||||
*/
|
||||
#define EXPORT_FUNC(x) \
|
||||
asm volatile ( \
|
||||
" .globl _" #x "\n_" \
|
||||
#x ":\n" \
|
||||
" P0 = [P3 + %0]\n" \
|
||||
" P0 = [P0 + %1]\n" \
|
||||
" JUMP (P0)\n" \
|
||||
: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "P0");
|
||||
#elif defined(CONFIG_AVR32)
|
||||
/*
|
||||
* r6 holds the pointer to the global_data. r8 is call clobbered.
|
||||
*/
|
||||
#define EXPORT_FUNC(x) \
|
||||
asm volatile( \
|
||||
" .globl\t" #x "\n" \
|
||||
#x ":\n" \
|
||||
" ld.w r8, r6[%0]\n" \
|
||||
" ld.w pc, r8[%1]\n" \
|
||||
: \
|
||||
: "i"(offsetof(gd_t, jt)), "i"(XF_ ##x) \
|
||||
: "r8");
|
||||
#elif defined(CONFIG_SH)
|
||||
/*
|
||||
* r13 holds the pointer to the global_data. r1 is a call clobbered.
|
||||
*/
|
||||
#define EXPORT_FUNC(x) \
|
||||
asm volatile ( \
|
||||
" .align 2\n" \
|
||||
" .globl " #x "\n" \
|
||||
#x ":\n" \
|
||||
" mov r13, r1\n" \
|
||||
" add %0, r1\n" \
|
||||
" mov.l @r1, r2\n" \
|
||||
" add %1, r2\n" \
|
||||
" mov.l @r2, r1\n" \
|
||||
" jmp @r1\n" \
|
||||
" nop\n" \
|
||||
" nop\n" \
|
||||
: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "r1", "r2");
|
||||
#elif defined(CONFIG_SPARC)
|
||||
/*
|
||||
* g7 holds the pointer to the global_data. g1 is call clobbered.
|
||||
*/
|
||||
#define EXPORT_FUNC(x) \
|
||||
asm volatile( \
|
||||
" .globl\t" #x "\n" \
|
||||
#x ":\n" \
|
||||
" set %0, %%g1\n" \
|
||||
" or %%g1, %%g7, %%g1\n" \
|
||||
" ld [%%g1], %%g1\n" \
|
||||
" ld [%%g1 + %1], %%g1\n" \
|
||||
" jmp %%g1\n" \
|
||||
" nop\n" \
|
||||
: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "g1" );
|
||||
#elif defined(CONFIG_NDS32)
|
||||
/*
|
||||
* r16 holds the pointer to the global_data. gp is call clobbered.
|
||||
* not support reduced register (16 GPR).
|
||||
*/
|
||||
#define EXPORT_FUNC(x) \
|
||||
asm volatile ( \
|
||||
" .globl " #x "\n" \
|
||||
#x ":\n" \
|
||||
" lwi $r16, [$gp + (%0)]\n" \
|
||||
" lwi $r16, [$r16 + (%1)]\n" \
|
||||
" jr $r16\n" \
|
||||
: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "$r16");
|
||||
#elif defined(CONFIG_OPENRISC)
|
||||
/*
|
||||
* r10 holds the pointer to the global_data, r13 is a call-clobbered
|
||||
* register
|
||||
*/
|
||||
#define EXPORT_FUNC(x) \
|
||||
asm volatile ( \
|
||||
" .globl " #x "\n" \
|
||||
#x ":\n" \
|
||||
" l.lwz r13, %0(r10)\n" \
|
||||
" l.lwz r13, %1(r13)\n" \
|
||||
" l.jr r13\n" \
|
||||
" l.nop\n" \
|
||||
: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "r13");
|
||||
#else
|
||||
/*" addi $sp, $sp, -24\n" \
|
||||
" br $r16\n" \*/
|
||||
|
||||
#error stubs definition missing for this architecture
|
||||
#endif
|
||||
|
||||
/* This function is necessary to prevent the compiler from
|
||||
* generating prologue/epilogue, preparing stack frame etc.
|
||||
* The stub functions are special, they do not use the stack
|
||||
* frame passed to them, but pass it intact to the actual
|
||||
* implementation. On the other hand, asm() statements with
|
||||
* arguments can be used only inside the functions (gcc limitation)
|
||||
*/
|
||||
#if GCC_VERSION < 3004
|
||||
static
|
||||
#endif /* GCC_VERSION */
|
||||
void __attribute__((unused)) dummy(void)
|
||||
{
|
||||
#include <_exports.h>
|
||||
}
|
||||
|
||||
extern unsigned long __bss_start, _end;
|
||||
|
||||
void app_startup(char * const *argv)
|
||||
{
|
||||
unsigned char * cp = (unsigned char *) &__bss_start;
|
||||
|
||||
/* Zero out BSS */
|
||||
while (cp < (unsigned char *)&_end) {
|
||||
*cp++ = 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_X86)
|
||||
/* x86 does not have a dedicated register for passing global_data */
|
||||
global_data = (gd_t *)argv[-1];
|
||||
jt = global_data->jt;
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef EXPORT_FUNC
|
|
@ -0,0 +1,319 @@
|
|||
/*
|
||||
* (C) Copyright 2005
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* The test exercises SDRAM accesses in burst mode
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <exports.h>
|
||||
|
||||
#include <commproc.h>
|
||||
#include <asm/mmu.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
#include <serial.h>
|
||||
#include <watchdog.h>
|
||||
|
||||
#include "test_burst.h"
|
||||
|
||||
/* 8 MB test region of physical RAM */
|
||||
#define TEST_PADDR 0x00800000
|
||||
/* The uncached virtual region */
|
||||
#define TEST_VADDR_NC 0x00800000
|
||||
/* The cached virtual region */
|
||||
#define TEST_VADDR_C 0x01000000
|
||||
/* When an error is detected, the address where the error has been found,
|
||||
and also the current and the expected data will be written to
|
||||
the following flash address
|
||||
*/
|
||||
#define TEST_FLASH_ADDR 0x40100000
|
||||
|
||||
/* Define GPIO ports to signal start of burst transfers and errors */
|
||||
#ifdef CONFIG_LWMON
|
||||
/* Use PD.8 to signal start of burst transfers */
|
||||
#define GPIO1_DAT (((volatile immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pddat)
|
||||
#define GPIO1_BIT 0x0080
|
||||
/* Configure PD.8 as general purpose output */
|
||||
#define GPIO1_INIT \
|
||||
((volatile immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pdpar &= ~GPIO1_BIT; \
|
||||
((volatile immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pddir |= GPIO1_BIT;
|
||||
/* Use PD.9 to signal error */
|
||||
#define GPIO2_DAT (((volatile immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pddat)
|
||||
#define GPIO2_BIT 0x0040
|
||||
/* Configure PD.9 as general purpose output */
|
||||
#define GPIO2_INIT \
|
||||
((volatile immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pdpar &= ~GPIO2_BIT; \
|
||||
((volatile immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pddir |= GPIO2_BIT;
|
||||
#endif /* CONFIG_LWMON */
|
||||
|
||||
|
||||
static void test_prepare (void);
|
||||
static int test_burst_start (unsigned long size, unsigned long pattern);
|
||||
static void test_map_8M (unsigned long paddr, unsigned long vaddr, int cached);
|
||||
static int test_mmu_is_on(void);
|
||||
static void test_desc(unsigned long size);
|
||||
static void test_error(char * step, volatile void * addr, unsigned long val, unsigned long pattern);
|
||||
static void signal_init(void);
|
||||
static void signal_start(void);
|
||||
static void signal_error(void);
|
||||
static void test_usage(void);
|
||||
|
||||
static unsigned long test_pattern [] = {
|
||||
0x00000000,
|
||||
0xffffffff,
|
||||
0x55555555,
|
||||
0xaaaaaaaa,
|
||||
};
|
||||
|
||||
|
||||
int test_burst (int argc, char * const argv[])
|
||||
{
|
||||
unsigned long size = CACHE_LINE_SIZE;
|
||||
unsigned int pass = 0;
|
||||
int res = 0;
|
||||
int i, j;
|
||||
|
||||
if (argc == 3) {
|
||||
char * d;
|
||||
for (size = 0, d = argv[1]; *d >= '0' && *d <= '9'; d++) {
|
||||
size *= 10;
|
||||
size += *d - '0';
|
||||
}
|
||||
if (size == 0 || *d) {
|
||||
test_usage();
|
||||
return 1;
|
||||
}
|
||||
for (d = argv[2]; *d >= '0' && *d <= '9'; d++) {
|
||||
pass *= 10;
|
||||
pass += *d - '0';
|
||||
}
|
||||
if (*d) {
|
||||
test_usage();
|
||||
return 1;
|
||||
}
|
||||
} else if (argc > 3) {
|
||||
test_usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
size += (CACHE_LINE_SIZE - 1);
|
||||
size &= ~(CACHE_LINE_SIZE - 1);
|
||||
|
||||
if (!test_mmu_is_on()) {
|
||||
test_prepare();
|
||||
}
|
||||
|
||||
test_desc(size);
|
||||
|
||||
for (j = 0; !pass || j < pass; j++) {
|
||||
for (i = 0; i < sizeof(test_pattern) / sizeof(test_pattern[0]);
|
||||
i++) {
|
||||
res = test_burst_start(size, test_pattern[i]);
|
||||
if (res != 0) {
|
||||
goto Done;
|
||||
}
|
||||
}
|
||||
|
||||
printf ("Iteration #%d passed\n", j + 1);
|
||||
|
||||
if (tstc() && 0x03 == getc())
|
||||
break;
|
||||
}
|
||||
Done:
|
||||
return res;
|
||||
}
|
||||
|
||||
static void test_prepare (void)
|
||||
{
|
||||
printf ("\n");
|
||||
|
||||
caches_init();
|
||||
disable_interrupts();
|
||||
mmu_init();
|
||||
|
||||
printf ("Interrupts are disabled\n");
|
||||
printf ("I-Cache is ON\n");
|
||||
printf ("D-Cache is ON\n");
|
||||
printf ("MMU is ON\n");
|
||||
|
||||
printf ("\n");
|
||||
|
||||
test_map_8M (TEST_PADDR, TEST_VADDR_NC, 0);
|
||||
test_map_8M (TEST_PADDR, TEST_VADDR_C, 1);
|
||||
|
||||
test_map_8M (TEST_FLASH_ADDR & 0xFF800000, TEST_FLASH_ADDR & 0xFF800000, 0);
|
||||
|
||||
/* Configure GPIO ports */
|
||||
signal_init();
|
||||
}
|
||||
|
||||
static int test_burst_start (unsigned long size, unsigned long pattern)
|
||||
{
|
||||
volatile unsigned long * vaddr_c = (unsigned long *)TEST_VADDR_C;
|
||||
volatile unsigned long * vaddr_nc = (unsigned long *)TEST_VADDR_NC;
|
||||
int i, n;
|
||||
int res = 1;
|
||||
|
||||
printf ("Test pattern %08lx ...", pattern);
|
||||
|
||||
n = size / 4;
|
||||
|
||||
for (i = 0; i < n; i ++) {
|
||||
vaddr_c [i] = pattern;
|
||||
}
|
||||
signal_start();
|
||||
flush_dcache_range((unsigned long)vaddr_c, (unsigned long)(vaddr_c + n) - 1);
|
||||
|
||||
for (i = 0; i < n; i ++) {
|
||||
register unsigned long tmp = vaddr_nc [i];
|
||||
if (tmp != pattern) {
|
||||
test_error("2a", vaddr_nc + i, tmp, pattern);
|
||||
goto Done;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i ++) {
|
||||
register unsigned long tmp = vaddr_c [i];
|
||||
if (tmp != pattern) {
|
||||
test_error("2b", vaddr_c + i, tmp, pattern);
|
||||
goto Done;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i ++) {
|
||||
vaddr_nc [i] = pattern;
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i ++) {
|
||||
register unsigned long tmp = vaddr_nc [i];
|
||||
if (tmp != pattern) {
|
||||
test_error("3a", vaddr_nc + i, tmp, pattern);
|
||||
goto Done;
|
||||
}
|
||||
}
|
||||
|
||||
signal_start();
|
||||
for (i = 0; i < n; i ++) {
|
||||
register unsigned long tmp = vaddr_c [i];
|
||||
if (tmp != pattern) {
|
||||
test_error("3b", vaddr_c + i, tmp, pattern);
|
||||
goto Done;
|
||||
}
|
||||
}
|
||||
|
||||
res = 0;
|
||||
Done:
|
||||
printf(" %s\n", res == 0 ? "OK" : "");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void test_map_8M (unsigned long paddr, unsigned long vaddr, int cached)
|
||||
{
|
||||
mtspr (MD_EPN, (vaddr & 0xFFFFFC00) | MI_EVALID);
|
||||
mtspr (MD_TWC, MI_PS8MEG | MI_SVALID);
|
||||
mtspr (MD_RPN, (paddr & 0xFFFFF000) | MI_BOOTINIT | (cached ? 0 : 2));
|
||||
mtspr (MD_AP, MI_Kp);
|
||||
}
|
||||
|
||||
static int test_mmu_is_on(void)
|
||||
{
|
||||
unsigned long msr;
|
||||
|
||||
asm volatile("mfmsr %0" : "=r" (msr) :);
|
||||
|
||||
return msr & MSR_DR;
|
||||
}
|
||||
|
||||
static void test_desc(unsigned long size)
|
||||
{
|
||||
printf(
|
||||
"The following tests will be conducted:\n"
|
||||
"1) Map %ld-byte region of physical RAM at 0x%08x\n"
|
||||
" into two virtual regions:\n"
|
||||
" one cached at 0x%08x and\n"
|
||||
" the the other uncached at 0x%08x.\n",
|
||||
size, TEST_PADDR, TEST_VADDR_NC, TEST_VADDR_C);
|
||||
|
||||
puts(
|
||||
"2) Fill the cached region with a pattern, and flush the cache\n"
|
||||
"2a) Check the uncached region to match the pattern\n"
|
||||
"2b) Check the cached region to match the pattern\n"
|
||||
"3) Fill the uncached region with a pattern\n"
|
||||
"3a) Check the cached region to match the pattern\n"
|
||||
"3b) Check the uncached region to match the pattern\n"
|
||||
"2b) Change the patterns and go to step 2\n"
|
||||
"\n"
|
||||
);
|
||||
}
|
||||
|
||||
static void test_error(
|
||||
char * step, volatile void * addr, unsigned long val, unsigned long pattern)
|
||||
{
|
||||
volatile unsigned long * p = (void *)TEST_FLASH_ADDR;
|
||||
|
||||
signal_error();
|
||||
|
||||
p[0] = (unsigned long)addr;
|
||||
p[1] = val;
|
||||
p[2] = pattern;
|
||||
|
||||
printf ("\nError at step %s, addr %08lx: read %08lx, pattern %08lx",
|
||||
step, (unsigned long)addr, val, pattern);
|
||||
}
|
||||
|
||||
static void signal_init(void)
|
||||
{
|
||||
#if defined(GPIO1_INIT)
|
||||
GPIO1_INIT;
|
||||
#endif
|
||||
#if defined(GPIO2_INIT)
|
||||
GPIO2_INIT;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void signal_start(void)
|
||||
{
|
||||
#if defined(GPIO1_INIT)
|
||||
if (GPIO1_DAT & GPIO1_BIT) {
|
||||
GPIO1_DAT &= ~GPIO1_BIT;
|
||||
} else {
|
||||
GPIO1_DAT |= GPIO1_BIT;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void signal_error(void)
|
||||
{
|
||||
#if defined(GPIO2_INIT)
|
||||
if (GPIO2_DAT & GPIO2_BIT) {
|
||||
GPIO2_DAT &= ~GPIO2_BIT;
|
||||
} else {
|
||||
GPIO2_DAT |= GPIO2_BIT;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void test_usage(void)
|
||||
{
|
||||
printf("Usage: go 0x40004 [size] [count]\n");
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* (C) Copyright 2005
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _TEST_BURST_H
|
||||
#define _TEST_BURST_H
|
||||
|
||||
/* Cache line size */
|
||||
#define CACHE_LINE_SIZE 16
|
||||
/* Binary logarithm of the cache line size */
|
||||
#define LG_CACHE_LINE_SIZE 4
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
extern void mmu_init(void);
|
||||
extern void caches_init(void);
|
||||
extern void flush_dcache_range(unsigned long start, unsigned long stop);
|
||||
#endif
|
||||
|
||||
#endif /* _TEST_BURST_H */
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
* (C) Copyright 2005
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <ppc_asm.tmpl>
|
||||
#include <ppc_defs.h>
|
||||
#include <asm/cache.h>
|
||||
#include <asm/mmu.h>
|
||||
#include "test_burst.h"
|
||||
|
||||
.text
|
||||
/*
|
||||
* void mmu_init(void);
|
||||
*
|
||||
* This function turns the MMU on
|
||||
*
|
||||
* Three 8 MByte regions are mapped 1:1, uncached
|
||||
* - SDRAM lower 8 MByte
|
||||
* - SDRAM higher 8 MByte
|
||||
* - IMMR
|
||||
*/
|
||||
.global mmu_init
|
||||
mmu_init:
|
||||
tlbia /* Invalidate all TLB entries */
|
||||
li r8, 0
|
||||
mtspr MI_CTR, r8 /* Set instruction control to zero */
|
||||
lis r8, MD_RESETVAL@h
|
||||
mtspr MD_CTR, r8 /* Set data TLB control */
|
||||
|
||||
/* Now map the lower 8 Meg into the TLBs. For this quick hack,
|
||||
* we can load the instruction and data TLB registers with the
|
||||
* same values.
|
||||
*/
|
||||
li r8, MI_EVALID /* Create EPN for address 0 */
|
||||
mtspr MI_EPN, r8
|
||||
mtspr MD_EPN, r8
|
||||
li r8, MI_PS8MEG /* Set 8M byte page */
|
||||
ori r8, r8, MI_SVALID /* Make it valid */
|
||||
mtspr MI_TWC, r8
|
||||
mtspr MD_TWC, r8
|
||||
li r8, MI_BOOTINIT|0x2 /* Create RPN for address 0 */
|
||||
mtspr MI_RPN, r8 /* Store TLB entry */
|
||||
mtspr MD_RPN, r8
|
||||
lis r8, MI_Kp@h /* Set the protection mode */
|
||||
mtspr MI_AP, r8
|
||||
mtspr MD_AP, r8
|
||||
|
||||
/* Now map the higher 8 Meg into the TLBs. For this quick hack,
|
||||
* we can load the instruction and data TLB registers with the
|
||||
* same values.
|
||||
*/
|
||||
lwz r9,20(r2) /* gd->ram_size */
|
||||
addis r9,r9,-0x80
|
||||
|
||||
mr r8, r9 /* Higher 8 Meg in SDRAM */
|
||||
ori r8, r8, MI_EVALID /* Mark page valid */
|
||||
mtspr MI_EPN, r8
|
||||
mtspr MD_EPN, r8
|
||||
li r8, MI_PS8MEG /* Set 8M byte page */
|
||||
ori r8, r8, MI_SVALID /* Make it valid */
|
||||
mtspr MI_TWC, r8
|
||||
mtspr MD_TWC, r8
|
||||
mr r8, r9
|
||||
ori r8, r8, MI_BOOTINIT|0x2
|
||||
mtspr MI_RPN, r8 /* Store TLB entry */
|
||||
mtspr MD_RPN, r8
|
||||
lis r8, MI_Kp@h /* Set the protection mode */
|
||||
mtspr MI_AP, r8
|
||||
mtspr MD_AP, r8
|
||||
|
||||
/* Map another 8 MByte at the IMMR to get the processor
|
||||
* internal registers (among other things).
|
||||
*/
|
||||
mfspr r9, 638 /* Get current IMMR */
|
||||
andis. r9, r9, 0xff80 /* Get 8Mbyte boundary */
|
||||
|
||||
mr r8, r9 /* Create vaddr for TLB */
|
||||
ori r8, r8, MD_EVALID /* Mark it valid */
|
||||
mtspr MD_EPN, r8
|
||||
li r8, MD_PS8MEG /* Set 8M byte page */
|
||||
ori r8, r8, MD_SVALID /* Make it valid */
|
||||
mtspr MD_TWC, r8
|
||||
mr r8, r9 /* Create paddr for TLB */
|
||||
ori r8, r8, MI_BOOTINIT|0x2 /* Inhibit cache -- Cort */
|
||||
mtspr MD_RPN, r8
|
||||
|
||||
/* We now have the lower and higher 8 Meg mapped into TLB entries,
|
||||
* and the caches ready to work.
|
||||
*/
|
||||
mfmsr r0
|
||||
ori r0,r0,MSR_DR|MSR_IR
|
||||
mtspr SRR1,r0
|
||||
mflr r0
|
||||
mtspr SRR0,r0
|
||||
SYNC
|
||||
rfi /* enables MMU */
|
||||
|
||||
/*
|
||||
* void caches_init(void);
|
||||
*/
|
||||
.globl caches_init
|
||||
caches_init:
|
||||
sync
|
||||
|
||||
mfspr r3, IC_CST /* Clear error bits */
|
||||
mfspr r3, DC_CST
|
||||
|
||||
lis r3, IDC_UNALL@h /* Unlock all */
|
||||
mtspr IC_CST, r3
|
||||
mtspr DC_CST, r3
|
||||
|
||||
lis r3, IDC_INVALL@h /* Invalidate all */
|
||||
mtspr IC_CST, r3
|
||||
mtspr DC_CST, r3
|
||||
|
||||
lis r3, IDC_ENABLE@h /* Enable all */
|
||||
mtspr IC_CST, r3
|
||||
mtspr DC_CST, r3
|
||||
|
||||
blr
|
||||
|
||||
/*
|
||||
* void flush_dcache_range(unsigned long start, unsigned long stop);
|
||||
*/
|
||||
.global flush_dcache_range
|
||||
flush_dcache_range:
|
||||
li r5,CACHE_LINE_SIZE-1
|
||||
andc r3,r3,r5
|
||||
subf r4,r3,r4
|
||||
add r4,r4,r5
|
||||
srwi. r4,r4,LG_CACHE_LINE_SIZE
|
||||
beqlr
|
||||
mtctr r4
|
||||
|
||||
1: dcbf 0,r3
|
||||
addi r3,r3,CACHE_LINE_SIZE
|
||||
bdnz 1b
|
||||
sync /* wait for dcbf's to get to ram */
|
||||
blr
|
||||
|
||||
/*
|
||||
* void disable_interrupts(void);
|
||||
*/
|
||||
.global disable_interrupts
|
||||
disable_interrupts:
|
||||
mfmsr r0
|
||||
rlwinm r0,r0,0,17,15
|
||||
mtmsr r0
|
||||
blr
|
|
@ -0,0 +1,349 @@
|
|||
/*
|
||||
* (C) Copyright 2000
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <commproc.h>
|
||||
#include <mpc8xx_irq.h>
|
||||
#include <exports.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
#define TIMER_PERIOD 1000000 /* 1 second clock */
|
||||
|
||||
static void timer_handler (void *arg);
|
||||
|
||||
|
||||
/* Access functions for the Machine State Register */
|
||||
static __inline__ unsigned long get_msr(void)
|
||||
{
|
||||
unsigned long msr;
|
||||
|
||||
asm volatile("mfmsr %0" : "=r" (msr) :);
|
||||
return msr;
|
||||
}
|
||||
|
||||
static __inline__ void set_msr(unsigned long msr)
|
||||
{
|
||||
asm volatile("mtmsr %0" : : "r" (msr));
|
||||
}
|
||||
|
||||
/*
|
||||
* Definitions to access the CPM Timer registers
|
||||
* See 8xx_immap.h for Internal Memory Map layout,
|
||||
* and commproc.h for CPM Interrupt vectors (aka "IRQ"s)
|
||||
*/
|
||||
|
||||
typedef struct tid_8xx_cpmtimer_s {
|
||||
int cpm_vec; /* CPM Interrupt Vector for this timer */
|
||||
ushort *tgcrp; /* Pointer to Timer Global Config Reg. */
|
||||
ushort *tmrp; /* Pointer to Timer Mode Register */
|
||||
ushort *trrp; /* Pointer to Timer Reference Register */
|
||||
ushort *tcrp; /* Pointer to Timer Capture Register */
|
||||
ushort *tcnp; /* Pointer to Timer Counter Register */
|
||||
ushort *terp; /* Pointer to Timer Event Register */
|
||||
} tid_8xx_cpmtimer_t;
|
||||
|
||||
#ifndef CLOCKRATE
|
||||
# define CLOCKRATE 64
|
||||
#endif
|
||||
|
||||
#define CPMT_CLOCK_DIV 16
|
||||
#define CPMT_MAX_PRESCALER 256
|
||||
#define CPMT_MAX_REFERENCE 65535 /* max. unsigned short */
|
||||
|
||||
#define CPMT_MAX_TICKS (CPMT_MAX_REFERENCE * CPMT_MAX_PRESCALER)
|
||||
#define CPMT_MAX_TICKS_WITH_DIV (CPMT_MAX_REFERENCE * CPMT_MAX_PRESCALER * CPMT_CLOCK_DIV)
|
||||
#define CPMT_MAX_INTERVAL (CPMT_MAX_TICKS_WITH_DIV / CLOCKRATE)
|
||||
|
||||
/* For now: always use max. prescaler value */
|
||||
#define CPMT_PRESCALER (CPMT_MAX_PRESCALER)
|
||||
|
||||
/* CPM Timer Event Register Bits */
|
||||
#define CPMT_EVENT_CAP 0x0001 /* Capture Event */
|
||||
#define CPMT_EVENT_REF 0x0002 /* Reference Counter Event */
|
||||
|
||||
/* CPM Timer Global Config Register */
|
||||
#define CPMT_GCR_RST 0x0001 /* Reset Timer */
|
||||
#define CPMT_GCR_STP 0x0002 /* Stop Timer */
|
||||
#define CPMT_GCR_FRZ 0x0004 /* Freeze Timer */
|
||||
#define CPMT_GCR_GM_CAS 0x0008 /* Gate Mode / Cascade Timers */
|
||||
#define CPMT_GCR_MASK (CPMT_GCR_RST|CPMT_GCR_STP|CPMT_GCR_FRZ|CPMT_GCR_GM_CAS)
|
||||
|
||||
/* CPM Timer Mode register */
|
||||
#define CPMT_MR_GE 0x0001 /* Gate Enable */
|
||||
#define CPMT_MR_ICLK_CASC 0x0000 /* Clock internally cascaded */
|
||||
#define CPMT_MR_ICLK_CLK 0x0002 /* Clock = system clock */
|
||||
#define CPMT_MR_ICLK_CLKDIV 0x0004 /* Clock = system clock / 16 */
|
||||
#define CPMT_MR_ICLK_TIN 0x0006 /* Clock = TINx signal */
|
||||
#define CPMT_MR_FRR 0x0008 /* Free Run / Restart */
|
||||
#define CPMT_MR_ORI 0x0010 /* Out. Reference Interrupt En. */
|
||||
#define CPMT_MR_OM 0x0020 /* Output Mode */
|
||||
#define CPMT_MR_CE_DIS 0x0000 /* Capture/Interrupt disabled */
|
||||
#define CPMT_MR_CE_RISE 0x0040 /* Capt./Interr. on rising TIN */
|
||||
#define CPMT_MR_CE_FALL 0x0080 /* Capt./Interr. on falling TIN */
|
||||
#define CPMT_MR_CE_ANY 0x00C0 /* Capt./Interr. on any TIN edge*/
|
||||
|
||||
|
||||
/*
|
||||
* which CPM timer to use - index starts at 0 (= timer 1)
|
||||
*/
|
||||
#define TID_TIMER_ID 0 /* use CPM timer 1 */
|
||||
|
||||
void setPeriod (tid_8xx_cpmtimer_t *hwp, ulong interval);
|
||||
|
||||
static const char usage[] = "\n[q, b, e, ?] ";
|
||||
|
||||
int timer (int argc, char * const argv[])
|
||||
{
|
||||
cpmtimer8xx_t *cpmtimerp; /* Pointer to the CPM Timer structure */
|
||||
tid_8xx_cpmtimer_t hw;
|
||||
tid_8xx_cpmtimer_t *hwp = &hw;
|
||||
int c;
|
||||
int running;
|
||||
|
||||
app_startup(argv);
|
||||
|
||||
/* Pointer to CPM Timer structure */
|
||||
cpmtimerp = &((immap_t *) gd->bd->bi_immr_base)->im_cpmtimer;
|
||||
|
||||
printf ("TIMERS=0x%x\n", (unsigned) cpmtimerp);
|
||||
|
||||
/* Initialize pointers depending on which timer we use */
|
||||
switch (TID_TIMER_ID) {
|
||||
case 0:
|
||||
hwp->tmrp = &(cpmtimerp->cpmt_tmr1);
|
||||
hwp->trrp = &(cpmtimerp->cpmt_trr1);
|
||||
hwp->tcrp = &(cpmtimerp->cpmt_tcr1);
|
||||
hwp->tcnp = &(cpmtimerp->cpmt_tcn1);
|
||||
hwp->terp = &(cpmtimerp->cpmt_ter1);
|
||||
hwp->cpm_vec = CPMVEC_TIMER1;
|
||||
break;
|
||||
case 1:
|
||||
hwp->tmrp = &(cpmtimerp->cpmt_tmr2);
|
||||
hwp->trrp = &(cpmtimerp->cpmt_trr2);
|
||||
hwp->tcrp = &(cpmtimerp->cpmt_tcr2);
|
||||
hwp->tcnp = &(cpmtimerp->cpmt_tcn2);
|
||||
hwp->terp = &(cpmtimerp->cpmt_ter2);
|
||||
hwp->cpm_vec = CPMVEC_TIMER2;
|
||||
break;
|
||||
case 2:
|
||||
hwp->tmrp = &(cpmtimerp->cpmt_tmr3);
|
||||
hwp->trrp = &(cpmtimerp->cpmt_trr3);
|
||||
hwp->tcrp = &(cpmtimerp->cpmt_tcr3);
|
||||
hwp->tcnp = &(cpmtimerp->cpmt_tcn3);
|
||||
hwp->terp = &(cpmtimerp->cpmt_ter3);
|
||||
hwp->cpm_vec = CPMVEC_TIMER3;
|
||||
break;
|
||||
case 3:
|
||||
hwp->tmrp = &(cpmtimerp->cpmt_tmr4);
|
||||
hwp->trrp = &(cpmtimerp->cpmt_trr4);
|
||||
hwp->tcrp = &(cpmtimerp->cpmt_tcr4);
|
||||
hwp->tcnp = &(cpmtimerp->cpmt_tcn4);
|
||||
hwp->terp = &(cpmtimerp->cpmt_ter4);
|
||||
hwp->cpm_vec = CPMVEC_TIMER4;
|
||||
break;
|
||||
}
|
||||
|
||||
hwp->tgcrp = &cpmtimerp->cpmt_tgcr;
|
||||
|
||||
printf ("Using timer %d\n"
|
||||
"tgcr @ 0x%x, tmr @ 0x%x, trr @ 0x%x,"
|
||||
" tcr @ 0x%x, tcn @ 0x%x, ter @ 0x%x\n",
|
||||
TID_TIMER_ID + 1,
|
||||
(unsigned) hwp->tgcrp,
|
||||
(unsigned) hwp->tmrp,
|
||||
(unsigned) hwp->trrp,
|
||||
(unsigned) hwp->tcrp,
|
||||
(unsigned) hwp->tcnp,
|
||||
(unsigned) hwp->terp
|
||||
);
|
||||
|
||||
/* reset timer */
|
||||
*hwp->tgcrp &= ~(CPMT_GCR_MASK << TID_TIMER_ID);
|
||||
|
||||
/* clear all events */
|
||||
*hwp->terp = (CPMT_EVENT_CAP | CPMT_EVENT_REF);
|
||||
|
||||
puts(usage);
|
||||
running = 0;
|
||||
while ((c = getc()) != 'q') {
|
||||
if (c == 'b') {
|
||||
|
||||
setPeriod (hwp, TIMER_PERIOD); /* Set period and start ticking */
|
||||
|
||||
/* Install interrupt handler (enable timer in CIMR) */
|
||||
install_hdlr (hwp->cpm_vec, timer_handler, hwp);
|
||||
|
||||
printf ("Enabling timer\n");
|
||||
|
||||
/* enable timer */
|
||||
*hwp->tgcrp |= (CPMT_GCR_RST << TID_TIMER_ID);
|
||||
running = 1;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("tgcr=0x%x, tmr=0x%x, trr=0x%x,"
|
||||
" tcr=0x%x, tcn=0x%x, ter=0x%x\n",
|
||||
*hwp->tgcrp, *hwp->tmrp, *hwp->trrp,
|
||||
*hwp->tcrp, *hwp->tcnp, *hwp->terp
|
||||
);
|
||||
#endif
|
||||
} else if (c == 'e') {
|
||||
|
||||
printf ("Stopping timer\n");
|
||||
|
||||
*hwp->tgcrp &= ~(CPMT_GCR_MASK << TID_TIMER_ID);
|
||||
running = 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("tgcr=0x%x, tmr=0x%x, trr=0x%x,"
|
||||
" tcr=0x%x, tcn=0x%x, ter=0x%x\n",
|
||||
*hwp->tgcrp, *hwp->tmrp, *hwp->trrp,
|
||||
*hwp->tcrp, *hwp->tcnp, *hwp->terp
|
||||
);
|
||||
#endif
|
||||
/* Uninstall interrupt handler */
|
||||
free_hdlr (hwp->cpm_vec);
|
||||
|
||||
} else if (c == '?') {
|
||||
#ifdef DEBUG
|
||||
cpic8xx_t *cpm_icp = &((immap_t *) gd->bd->bi_immr_base)->im_cpic;
|
||||
sysconf8xx_t *siup = &((immap_t *) gd->bd->bi_immr_base)->im_siu_conf;
|
||||
#endif
|
||||
|
||||
printf ("\ntgcr=0x%x, tmr=0x%x, trr=0x%x,"
|
||||
" tcr=0x%x, tcn=0x%x, ter=0x%x\n",
|
||||
*hwp->tgcrp, *hwp->tmrp, *hwp->trrp,
|
||||
*hwp->tcrp, *hwp->tcnp, *hwp->terp
|
||||
);
|
||||
#ifdef DEBUG
|
||||
printf ("SIUMCR=0x%08lx, SYPCR=0x%08lx,"
|
||||
" SIMASK=0x%08lx, SIPEND=0x%08lx\n",
|
||||
siup->sc_siumcr,
|
||||
siup->sc_sypcr,
|
||||
siup->sc_simask,
|
||||
siup->sc_sipend
|
||||
);
|
||||
|
||||
printf ("CIMR=0x%08lx, CICR=0x%08lx, CIPR=0x%08lx\n",
|
||||
cpm_icp->cpic_cimr,
|
||||
cpm_icp->cpic_cicr,
|
||||
cpm_icp->cpic_cipr
|
||||
);
|
||||
#endif
|
||||
} else {
|
||||
printf ("\nEnter: q - quit, b - start timer, e - stop timer, ? - get status\n");
|
||||
}
|
||||
puts(usage);
|
||||
}
|
||||
if (running) {
|
||||
printf ("Stopping timer\n");
|
||||
*hwp->tgcrp &= ~(CPMT_GCR_MASK << TID_TIMER_ID);
|
||||
free_hdlr (hwp->cpm_vec);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/* Set period in microseconds and start.
|
||||
* Truncate to maximum period if more than this is requested - but warn about it.
|
||||
*/
|
||||
|
||||
void setPeriod (tid_8xx_cpmtimer_t *hwp, ulong interval)
|
||||
{
|
||||
unsigned short prescaler;
|
||||
unsigned long ticks;
|
||||
|
||||
printf ("Set interval %ld us\n", interval);
|
||||
|
||||
/* Warn if requesting longer period than possible */
|
||||
if (interval > CPMT_MAX_INTERVAL) {
|
||||
printf ("Truncate interval %ld to maximum (%d)\n",
|
||||
interval, CPMT_MAX_INTERVAL);
|
||||
interval = CPMT_MAX_INTERVAL;
|
||||
}
|
||||
/*
|
||||
* Check if we want to use clock divider:
|
||||
* Since the reference counter can be incremented only in integer steps,
|
||||
* we try to keep it as big as possible to allow the resulting period to be
|
||||
* as precise as possible.
|
||||
*/
|
||||
/* prescaler, enable interrupt, restart after ref count is reached */
|
||||
prescaler = (ushort) ((CPMT_PRESCALER - 1) << 8) |
|
||||
CPMT_MR_ORI |
|
||||
CPMT_MR_FRR;
|
||||
|
||||
ticks = ((ulong) CLOCKRATE * interval);
|
||||
|
||||
if (ticks > CPMT_MAX_TICKS) {
|
||||
ticks /= CPMT_CLOCK_DIV;
|
||||
prescaler |= CPMT_MR_ICLK_CLKDIV; /* use system clock divided by 16 */
|
||||
} else {
|
||||
prescaler |= CPMT_MR_ICLK_CLK; /* use system clock without divider */
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("clock/%d, prescale factor %d, reference %ld, ticks %ld\n",
|
||||
(ticks > CPMT_MAX_TICKS) ? CPMT_CLOCK_DIV : 1,
|
||||
CPMT_PRESCALER,
|
||||
(ticks / CPMT_PRESCALER),
|
||||
ticks
|
||||
);
|
||||
#endif
|
||||
|
||||
/* set prescaler register */
|
||||
*hwp->tmrp = prescaler;
|
||||
|
||||
/* clear timer counter */
|
||||
*hwp->tcnp = 0;
|
||||
|
||||
/* set reference register */
|
||||
*hwp->trrp = (unsigned short) (ticks / CPMT_PRESCALER);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("tgcr=0x%x, tmr=0x%x, trr=0x%x,"
|
||||
" tcr=0x%x, tcn=0x%x, ter=0x%x\n",
|
||||
*hwp->tgcrp, *hwp->tmrp, *hwp->trrp,
|
||||
*hwp->tcrp, *hwp->tcnp, *hwp->terp
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Handler for CPMVEC_TIMER1 interrupt
|
||||
*/
|
||||
static
|
||||
void timer_handler (void *arg)
|
||||
{
|
||||
tid_8xx_cpmtimer_t *hwp = (tid_8xx_cpmtimer_t *)arg;
|
||||
|
||||
/* printf ("** TER1=%04x ** ", *hwp->terp); */
|
||||
|
||||
/* just for demonstration */
|
||||
printf (".");
|
||||
|
||||
/* clear all possible events: Ref. and Cap. */
|
||||
*hwp->terp = (CPMT_EVENT_CAP | CPMT_EVENT_REF);
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
void *func[8], **pfunc;
|
||||
|
||||
typedef struct xxx xxx_t;
|
||||
struct xxx {
|
||||
int dummy;
|
||||
void **pfunc;
|
||||
} q;
|
||||
|
||||
#define XF_strcpy 3
|
||||
#define XF_printf 4
|
||||
|
||||
#define LABEL(x) \
|
||||
asm volatile ( \
|
||||
|
||||
#if defined(__i386__)
|
||||
#define EXPORT_FUNC(x) \
|
||||
asm volatile ( \
|
||||
" .globl mon_" #x "\n" \
|
||||
"mon_" #x ":\n" \
|
||||
" movl %0, %%eax\n" \
|
||||
" movl pfunc, %%ecx\n" \
|
||||
" jmp *(%%ecx,%%eax)\n" \
|
||||
: : "i"(XF_ ## x * sizeof(void *)) : "eax", "ecx");
|
||||
#elif defined(__powerpc__)
|
||||
#define EXPORT_FUNC(x) \
|
||||
asm volatile ( \
|
||||
" .globl mon_" #x "\n" \
|
||||
"mon_" #x ":\n" \
|
||||
" lwz %%r11, %0(%%r2)\n" \
|
||||
" lwz %%r11, %1(%%r11)\n" \
|
||||
" mtctr %%r11\n" \
|
||||
" bctr\n" \
|
||||
: : "i"(offsetof(xxx_t, pfunc)), "i"(XF_ ## x * sizeof(void *)) : "r11", "r2");
|
||||
#elif defined(__arm__)
|
||||
#define EXPORT_FUNC(x) \
|
||||
asm volatile ( \
|
||||
" .globl mon_" #x "\n" \
|
||||
"mon_" #x ":\n" \
|
||||
" ldr ip, [r8, %0]\n" \
|
||||
" ldr pc, [ip, %1]\n" \
|
||||
: : "i"(offsetof(xxx_t, pfunc)), "i"(XF_ ## x * sizeof(void *)) : "ip");
|
||||
#elif defined(__mips__)
|
||||
#define EXPORT_FUNC(x) \
|
||||
asm volatile ( \
|
||||
" .globl mon_" #x "\n" \
|
||||
"mon_" #x ":\n" \
|
||||
" lw $25, %0($26)\n" \
|
||||
" lw $25, %1($25)\n" \
|
||||
" jr $25\n" \
|
||||
: : "i"(offsetof(xxx_t, pfunc)), "i"(XF_ ## x * sizeof(void *)) : "t9");
|
||||
#elif defined(__nds32__)
|
||||
#define EXPORT_FUNC(x) \
|
||||
asm volatile ( \
|
||||
" .globl mon_" #x "\n" \
|
||||
"mon_" #x ":\n" \
|
||||
" lwi $r16, [$gp + (%0)]\n" \
|
||||
" lwi $r16, [$r16 + (%1)]\n" \
|
||||
" jr $r16\n" \
|
||||
: : "i"(offsetof(xxx_t, pfunc)), \
|
||||
"i"(XF_ ## x * sizeof(void *)) : "$r16");
|
||||
|
||||
#else
|
||||
#error [No stub code for this arch]
|
||||
#endif
|
||||
|
||||
void dummy(void)
|
||||
{
|
||||
EXPORT_FUNC(printf)
|
||||
EXPORT_FUNC(strcpy)
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
#if defined(__i386__)
|
||||
xxx_t *pq;
|
||||
#elif defined(__powerpc__)
|
||||
register volatile xxx_t *pq asm("r2");
|
||||
#elif defined(__arm__)
|
||||
register volatile xxx_t *pq asm("r8");
|
||||
#elif defined(__mips__)
|
||||
register volatile xxx_t *pq asm("k0");
|
||||
#elif defined(__nds32__)
|
||||
register volatile xxx_t *pq asm("$r16");
|
||||
#endif
|
||||
char buf[32];
|
||||
|
||||
func[XF_strcpy] = strcpy;
|
||||
func[XF_printf] = printf;
|
||||
pq = &q;
|
||||
pq->pfunc = pfunc = func;
|
||||
|
||||
mon_strcpy(buf, "test");
|
||||
mon_printf("hi %s %d z\n", buf, 444);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue