merge WIP multi-board support; tested on Avila and Cambria, still

needs Proghorn testing
This commit is contained in:
Sam Leffler 2008-12-13 02:56:08 +00:00
parent 1020645aae
commit 4173c22644
4 changed files with 154 additions and 75 deletions

View File

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

View File

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

View File

@ -27,20 +27,35 @@
__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>
static u_int8_t *ubase;
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)
#define BOARD_AVILA 0
#define BOARD_PRONGHORN 1
static int board;
static u_int cputype;
#define cpu_is_ixp43x() (cputype == CPU_ID_IXP435)
static u_int8_t *ubase;
static u_int8_t uart_getreg(u_int8_t *, int);
static void uart_setreg(u_int8_t *, int, u_int8_t);
@ -57,32 +72,18 @@ static void cf_clr(void);
const char *
board_init(void)
{
volatile u_int32_t *cs;
const char *bt = NULL;
struct board_config **pbp;
/*
* 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";
}
cputype = cpu_id() & CPU_ID_CPU_MASK;
/* 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);
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");

View File

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