summaryrefslogtreecommitdiffstats
path: root/sys/boot/arm
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2008-12-13 02:56:08 +0000
committersam <sam@FreeBSD.org>2008-12-13 02:56:08 +0000
commit9b4882f3e4ed33f2f9065745f61d5993ec10dfd2 (patch)
tree13d152f305ef35cd438da30b033381e07af83218 /sys/boot/arm
parent0dbf5fcc92f10566d3c5fda7d452a81cf1f0e0fe (diff)
downloadFreeBSD-src-9b4882f3e4ed33f2f9065745f61d5993ec10dfd2.zip
FreeBSD-src-9b4882f3e4ed33f2f9065745f61d5993ec10dfd2.tar.gz
merge WIP multi-board support; tested on Avila and Cambria, still
needs Proghorn testing
Diffstat (limited to 'sys/boot/arm')
-rw-r--r--sys/boot/arm/ixp425/boot2/arm_init.S8
-rw-r--r--sys/boot/arm/ixp425/boot2/boot2.c2
-rw-r--r--sys/boot/arm/ixp425/boot2/ixp425_board.c218
-rw-r--r--sys/boot/arm/ixp425/boot2/lib.h1
4 files changed, 154 insertions, 75 deletions
diff --git a/sys/boot/arm/ixp425/boot2/arm_init.S b/sys/boot/arm/ixp425/boot2/arm_init.S
index 088f23d..9ede9fc 100644
--- a/sys/boot/arm/ixp425/boot2/arm_init.S
+++ b/sys/boot/arm/ixp425/boot2/arm_init.S
@@ -24,8 +24,9 @@
* $FreeBSD$
*/
-start:
+#include <machine/asm.h>
+ASENTRY_NP(start)
/* Initialise bss and sp */
nop
adr r1, .Lstart
@@ -47,4 +48,9 @@ infiniteLoop:
.word _edata
.word _end
.word BOOT_STACK
+
+ENTRY(cpu_id)
+ mrc p15, 0, r0, c0, c0, 0
+ RET
+
/* End */
diff --git a/sys/boot/arm/ixp425/boot2/boot2.c b/sys/boot/arm/ixp425/boot2/boot2.c
index 2cab16a..8f99e0d 100644
--- a/sys/boot/arm/ixp425/boot2/boot2.c
+++ b/sys/boot/arm/ixp425/boot2/boot2.c
@@ -163,7 +163,7 @@ main(void)
p_memset((char *)dmadat, 0, 32 * 1024);
bt = board_init();
- printf("FreeBSD ARM (%s) boot2 v%d.%d\n", bt, 0, 3);
+ printf("FreeBSD ARM (%s) boot2 v%d.%d\n", bt, 0, 4);
autoboot = 1;
diff --git a/sys/boot/arm/ixp425/boot2/ixp425_board.c b/sys/boot/arm/ixp425/boot2/ixp425_board.c
index 985c0a5..5c8d54c 100644
--- a/sys/boot/arm/ixp425/boot2/ixp425_board.c
+++ b/sys/boot/arm/ixp425/boot2/ixp425_board.c
@@ -27,21 +27,36 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/ata.h>
+#include <sys/linker_set.h>
#include <stdarg.h>
#include "lib.h"
#include "cf_ata.h"
+#include <machine/armreg.h>
#include <arm/xscale/ixp425/ixp425reg.h>
#include <dev/ic/ns16550.h>
+struct board_config {
+ const char *desc;
+ int (*probe)(int boardtype_hint);
+ void (*init)(void);
+};
+/* set of registered boards */
+SET_DECLARE(boards, struct board_config);
+#define BOARD_CONFIG(name, _desc) \
+static struct board_config name##config = { \
+ .desc = _desc, \
+ .probe = name##_probe, \
+ .init = name##_init, \
+}; \
+DATA_SET(boards, name##config)
+
+static u_int cputype;
+#define cpu_is_ixp43x() (cputype == CPU_ID_IXP435)
static u_int8_t *ubase;
-#define BOARD_AVILA 0
-#define BOARD_PRONGHORN 1
-static int board;
-
static u_int8_t uart_getreg(u_int8_t *, int);
static void uart_setreg(u_int8_t *, int, u_int8_t);
@@ -57,32 +72,18 @@ static void cf_clr(void);
const char *
board_init(void)
{
- volatile u_int32_t *cs;
- const char *bt = NULL;
-
- /*
- * Redboot only configure the chip selects that are needed, so
- * use that to figure out if it is an Avila or ADI board. The
- * Avila boards use CS2 and ADI does not.
- */
- cs = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS2_OFFSET);
- if (*cs != 0) {
- board = BOARD_AVILA;
- bt = "Avila";
- } else {
- board = BOARD_PRONGHORN;
- bt = "Pronghorn Metro";
- }
+ struct board_config **pbp;
- /* Config the serial port. RedBoot should do the rest. */
- if (board == BOARD_AVILA)
- ubase = (u_int8_t *)(IXP425_UART0_HWBASE);
- else
- ubase = (u_int8_t *)(IXP425_UART1_HWBASE);
+ cputype = cpu_id() & CPU_ID_CPU_MASK;
- cf_init();
-
- return bt;
+ SET_FOREACH(pbp, boards)
+ /* XXX pass down redboot board type */
+ if ((*pbp)->probe(0)) {
+ (*pbp)->init();
+ return (*pbp)->desc;
+ }
+ /* XXX panic, unknown board type */
+ return "???";
}
/*
@@ -228,6 +229,9 @@ struct {
u_int8_t sectors;
u_int32_t cylinders;
+ u_int32_t *cs1to;
+ u_int32_t *cs2to;
+
u_int8_t *cs1;
u_int8_t *cs2;
@@ -265,38 +269,21 @@ cf_init(void)
#ifdef DEBUG
int rval;
#endif
- volatile u_int32_t *cs;
-
- /* Setup the CF select timeing. Maybe already done by RedBoot? */
- if (board == BOARD_AVILA) {
- cs = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS1_OFFSET);
- *cs |= (EXP_BYTE_EN | EXP_WR_EN | EXP_BYTE_RD16 | EXP_CS_EN);
- DPRINTF("t1 %x, ", *cs);
-
- cs = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS2_OFFSET);
- *cs |= (EXP_BYTE_EN | EXP_WR_EN | EXP_BYTE_RD16 | EXP_CS_EN);
- DPRINTF("t2 %x\n", *cs);
-
- dskinf.cs1 = (u_int8_t *)IXP425_EXP_BUS_CS1_HWBASE;
- dskinf.cs2 = (u_int8_t *)IXP425_EXP_BUS_CS2_HWBASE;
- } else {
- cs = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS3_OFFSET);
- *cs |= (EXP_BYTE_EN | EXP_WR_EN | EXP_BYTE_RD16 | EXP_CS_EN);
- DPRINTF("t1 %x, ", *cs);
-
- cs = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS4_OFFSET);
- *cs |= (EXP_BYTE_EN | EXP_WR_EN | EXP_BYTE_RD16 | EXP_CS_EN);
- DPRINTF("t2 %x\n", *cs);
-
- dskinf.cs1 = (u_int8_t *)IXP425_EXP_BUS_CS3_HWBASE;
- dskinf.cs2 = (u_int8_t *)IXP425_EXP_BUS_CS4_HWBASE;
- }
- DPRINTF("cs1 %x, cs2 %x\n", dskinf.cs1, dskinf.cs2);
+ /* NB: board init routines setup other parts of dskinf */
dskinf.use_stream8 = 0;
dskinf.use_lba = 0;
dskinf.debug = 1;
+ DPRINTF("cs1 %x, cs2 %x\n", dskinf.cs1, dskinf.cs2);
+
+ /* Setup the CF window */
+ *dskinf.cs1to |= (EXP_BYTE_EN | EXP_WR_EN | EXP_BYTE_RD16 | EXP_CS_EN);
+ DPRINTF("t1 %x, ", *dskinf.cs1to);
+
+ *dskinf.cs2to |= (EXP_BYTE_EN | EXP_WR_EN | EXP_BYTE_RD16 | EXP_CS_EN);
+ DPRINTF("t2 %x\n", *dskinf.cs2to);
+
/* Detect if there is a disk. */
cfwrite8(CF_DRV_HEAD, CF_D_IBM);
DELAY(1000);
@@ -340,29 +327,24 @@ static void
cfenable16(void)
{
u_int32_t val;
- volatile u_int32_t *cs;
- if (board == BOARD_AVILA)
- cs = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS1_OFFSET);
- else
- cs = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS3_OFFSET);
- val = *cs;
- *cs = val & (~1);
- DPRINTF("cfenable16: cs1 timing reg %x\n", *cs);
+ val = *dskinf.cs1to;
+ *dskinf.cs1to = val &~ EXP_BYTE_EN;
+#if 0
+ DPRINTF("%s: cs1 timing reg %x\n", *dskinf.cs1to, __func__);
+#endif
}
static void
cfdisable16(void)
{
u_int32_t val;
- volatile u_int32_t *cs;
- if (board == BOARD_AVILA)
- cs = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS1_OFFSET);
- else
- cs = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS3_OFFSET);
- val = *cs;
- *cs = val | 1;
+ val = *dskinf.cs1to;
+ *dskinf.cs1to = val | EXP_BYTE_EN;
+#if 0
+ DPRINTF("%s: cs1 timing reg %x\n", *dskinf.cs1to, __func__);
+#endif
}
static u_int8_t
@@ -478,7 +460,8 @@ cfwait(u_int8_t mask)
while (tout <= 5000000) {
status = cfread8(CF_STATUS);
if (status == 0xff) {
- printf("cfwait: master: no status, reselecting\n");
+ printf("%s: master: no status, reselecting\n",
+ __func__);
cfwrite8(CF_DRV_HEAD, CF_D_IBM);
DELAY(1);
status = cfread8(CF_STATUS);
@@ -487,10 +470,14 @@ cfwait(u_int8_t mask)
return -1;
dskinf.status = status;
if (!(status & CF_S_BUSY)) {
- if (status & CF_S_ERROR)
+ if (status & CF_S_ERROR) {
dskinf.error = cfread8(CF_ERROR);
+ printf("%s: error, status 0x%x error 0x%x\n",
+ __func__, status, dskinf.error);
+ }
if ((status & mask) == mask) {
- DPRINTF("cfwait: tout %u\n", tout);
+ DPRINTF("%s: status 0x%x mask 0x%x tout %u\n",
+ __func__, status, mask, tout);
return (status & CF_S_ERROR);
}
}
@@ -695,3 +682,88 @@ avila_read(char *dest, unsigned source, unsigned length)
return 0;
}
+/*
+ * Gateworks Avila Support.
+ */
+static int
+avila_probe(int boardtype_hint)
+{
+ volatile u_int32_t *cs;
+ /*
+ * Redboot only configure the chip selects that are needed, so
+ * use that to figure out if it is an Avila or ADI board. The
+ * Avila boards use CS2 and ADI does not.
+ */
+ cs = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS2_OFFSET);
+ return (*cs != 0);
+}
+
+static void
+avila_init(void)
+{
+ /* Config the serial port. RedBoot should do the rest. */
+ ubase = (u_int8_t *)(IXP425_UART0_HWBASE);
+
+ dskinf.cs1to = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS1_OFFSET);
+ dskinf.cs2to = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS2_OFFSET);
+ dskinf.cs1 = (u_int8_t *)IXP425_EXP_BUS_CS1_HWBASE;
+ dskinf.cs2 = (u_int8_t *)IXP425_EXP_BUS_CS2_HWBASE;
+
+ cf_init();
+}
+BOARD_CONFIG(avila, "Gateworks Avila");
+
+/*
+ * Gateworks Cambria Support.
+ */
+static int
+cambria_probe(int boardtype_hint)
+{
+ return cpu_is_ixp43x();
+}
+
+static void
+cambria_init(void)
+{
+ /* Config the serial port. RedBoot should do the rest. */
+ ubase = (u_int8_t *)(IXP425_UART0_HWBASE);
+
+ dskinf.cs1to = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS3_OFFSET);
+ dskinf.cs2to = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS4_OFFSET);
+ dskinf.cs1 = (u_int8_t *)CAMBRIA_CFSEL0_HWBASE;
+ dskinf.cs2 = (u_int8_t *)CAMBRIA_CFSEL1_HWBASE;
+
+ cf_init();
+}
+BOARD_CONFIG(cambria, "Gateworks Cambria");
+
+/*
+ * Pronghorn Metro Support.
+ */
+static int
+pronghorn_probe(int boardtype_hint)
+{
+ volatile u_int32_t *cs;
+ /*
+ * Redboot only configure the chip selects that are needed, so
+ * use that to figure out if it is an Avila or ADI board. The
+ * Avila boards use CS2 and ADI does not.
+ */
+ cs = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS2_OFFSET);
+ return (*cs == 0);
+}
+
+static void
+pronghorn_init(void)
+{
+ /* Config the serial port. RedBoot should do the rest. */
+ ubase = (u_int8_t *)(IXP425_UART1_HWBASE);
+
+ dskinf.cs1to = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS3_OFFSET);
+ dskinf.cs2to = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS4_OFFSET);
+ dskinf.cs1 = (u_int8_t *)IXP425_EXP_BUS_CS3_HWBASE;
+ dskinf.cs2 = (u_int8_t *)IXP425_EXP_BUS_CS4_HWBASE;
+
+ cf_init();
+}
+BOARD_CONFIG(pronghorn, "Pronghorn Metro");
diff --git a/sys/boot/arm/ixp425/boot2/lib.h b/sys/boot/arm/ixp425/boot2/lib.h
index 7b39028..1679e96 100644
--- a/sys/boot/arm/ixp425/boot2/lib.h
+++ b/sys/boot/arm/ixp425/boot2/lib.h
@@ -60,5 +60,6 @@ u_int32_t swap32(u_int32_t);
const char *board_init(void);
void clr_board(void);
int avila_read(char*, unsigned, unsigned);
+u_int cpu_id(void);
#endif /* !ARM_BOOT_LIB_H */
OpenPOWER on IntegriCloud