A port of NetBSD to the Linksys NSLU2 (a.k.a. "Slug").

The NSLU2 (Network Storage Link for USB 2.0 Disk Drives) is a small, *cheap*
NAS device consisting of an Intel IXP420 (Xscale) CPU, a 10/100mbit Ethernet
port, and two USB 2.0 ports. It has 32MB of SDRAM and 8MB of Flash memory,
and runs RedBoot/Linux out of the box. Now it can also run NetBSD.
This commit is contained in:
scw 2006-02-28 20:40:33 +00:00
parent c40da0c0a2
commit 6f6167730e
13 changed files with 2620 additions and 0 deletions

244
sys/arch/evbarm/conf/NSLU2 Normal file
View File

@ -0,0 +1,244 @@
# $NetBSD: NSLU2,v 1.1 2006/02/28 20:40:33 scw Exp $
#
# Linksys NSLU2 "Slug" NAS Device
#
include "arch/evbarm/conf/std.nslu2"
# estimated number of users
maxusers 8
# Feeling bloated? These might help...
#options MALLOC_NOINLINE
#options VNODE_OP_NOINLINE
#options EVBARM_SPL_NOINLINE
#makeoptions COPTS="-Os"
# Standard system options
options RTC_OFFSET=0 # hardware clock is this many mins. west of GMT
options NTP # NTP phase/frequency locked loop
# CPU options
# For XScale systems
options CPU_XSCALE_IXP425 # Support the XScale core
makeoptions CPUFLAGS="-mcpu=xscale -mbig-endian"
# Architecture options
options XSCALE_CACHE_READ_WRITE_ALLOCATE
#options HZ=512
# Board Type
makeoptions BOARDTYPE="nslu2"
# File systems
file-system FFS # UFS
#file-system LFS # log-structured file system
file-system MFS # memory file system
file-system NFS # Network file system
#file-system ADOSFS # AmigaDOS-compatible file system
#file-system EXT2FS # second extended file system (linux)
#file-system CD9660 # ISO 9660 + Rock Ridge file system
#file-system MSDOSFS # MS-DOS file system
#file-system FDESC # /dev/fd
#file-system KERNFS # /kern
#file-system NULLFS # loopback file system
#file-system PORTAL # portal filesystem (still experimental)
#file-system PROCFS # /proc
#file-system UMAPFS # NULLFS + uid and gid remapping
#file-system UNION # union file system
# File system options
#options QUOTA # UFS quotas
#options FFS_EI # FFS Endian Independant support
#options NFSSERVER
#options SOFTDEP
# Networking options
#options GATEWAY # packet forwarding
options INET # IP + ICMP + TCP + UDP
options INET6 # IPV6
#options IPSEC # IP security
#options IPSEC_ESP # IP security (encryption part; define w/ IPSEC)
#options IPSEC_DEBUG # debug for IP security
#options MROUTING # IP multicast routing
#options NS # XNS
#options NSIP # XNS tunneling over IP
#options ISO,TPIP # OSI
#options EON # OSI tunneling over IP
#options CCITT,LLC,HDLC # X.25
#options NETATALK # AppleTalk networking
options PFIL_HOOKS # pfil(9) packet filter hooks
#options PPP_BSDCOMP # BSD-Compress compression support for PPP
#options PPP_DEFLATE # Deflate compression support for PPP
#options PPP_FILTER # Active filter support for PPP (requires bpf)
#options IPFILTER_LOG # ipmon(8) log support
#options TCP_DEBUG # Record last TCP_NDEBUG packets with SO_DEBUG
#options NFS_BOOT_BOOTP
options NFS_BOOT_DHCP
#options NFS_BOOT_BOOTPARAM
# Compatibility options
#options COMPAT_43 # 4.3BSD compatibility.
#options COMPAT_30 # NetBSD 3.0 compatibility.
#options COMPAT_20 # NetBSD 2.0 compatibility.
#options COMPAT_16 # NetBSD 1.5 compatibility.
#options COMPAT_15 # NetBSD 1.6 compatibility.
#options COMPAT_14 # NetBSD 1.4 compatibility.
#options COMPAT_13 # NetBSD 1.3 compatibility.
#options COMPAT_12 # NetBSD 1.2 compatibility.
#options COMPAT_11 # NetBSD 1.1 compatibility.
#options COMPAT_10 # NetBSD 1.0 compatibility.
#options COMPAT_09 # NetBSD 0.9 compatibility.
#options TCP_COMPAT_42 # 4.2BSD TCP/IP bug compat. Not recommended.
options COMPAT_BSDPTY # /dev/[pt]ty?? ptys.
# Shared memory options
#options SYSVMSG # System V-like message queues
#options SYSVSEM # System V-like semaphores
#options SEMMNI=10 # number of semaphore identifiers
#options SEMMNS=60 # number of semaphores in system
#options SEMUME=10 # max number of undo entries per process
#options SEMMNU=30 # number of undo structures in system
#options SYSVSHM # System V-like memory sharing
#options SHMMAXPGS=1024 # 1024 pages is the default
# Device options
#options MEMORY_DISK_HOOKS # boottime setup of ramdisk
#options MEMORY_DISK_ROOT_SIZE=3400 # Size in blocks
#options MEMORY_DISK_IS_ROOT # use memory disk as root
# Console options. The default console is speed is 115200 baud.
options CONSPEED=115200 # Console speed
options CONUNIT=0 # Console port number
# Miscellaneous kernel options
#options KTRACE # system call tracing, a la ktrace(1)
#options IRQSTATS # manage IRQ statistics
#options LKM # loadable kernel modules
#options KMEMSTATS # kernel memory statistics
#options SCSIVERBOSE # Verbose SCSI errors
#options PCIVERBOSE # Verbose PCI descriptions
#options MIIVERBOSE # Verbose MII autoconfuration messages
#options PCI_CONFIG_DUMP # verbosely dump PCI config space
#options DDB_KEYCODE=0x40
#options USERCONF # userconf(4) support
#options PIPE_SOCKETPAIR # smaller, but slower pipe(2)
# Development and Debugging options
#options PERFCTRS # performance counters
options DIAGNOSTIC # internally consistency checks
options DEBUG
#options PMAP_DEBUG # Enable pmap_debug_level code
#options IPKDB # remote kernel debugging
#options VERBOSE_INIT_ARM # verbose bootstraping messages
options DDB # in-kernel debugger
options DDB_HISTORY_SIZE=100 # Enable history editing in DDB
#makeoptions DEBUG="-g" # compile full symbol table
options SYMTAB_SPACE=260000
config netbsd root on ? type ?
# The main bus device
mainbus0 at root
# The boot cpu
cpu0 at mainbus?
# IXP425 slow peripheral
ixpsip0 at mainbus?
#Timer
ixpclk* at ixpsip? addr 0xc8005000 size 0x30
# On-board device support
com0 at ixpsip? addr 0xc8000000 size 0x1000 index 0
options COM_PXA2X0
# I2C bus (using bit-banged GPIO pins)
slugiic0 at ixpsip?
iic0 at slugiic0
xrtc0 at iic0 addr 0x6f
# Power/Reset button support (via sysmon)
slugbutt0 at ixpsip?
# Disk activity and ready/status LED support
slugled0 at ixpsip?
# Buzzer support (not supported yet)
#slugbuzz0 at ixpsip?
# IXP425 fast bus
ixpio0 at mainbus?
# PCI bus
pci0 at ixpio? bus ?
# USB devices
ehci* at pci? dev ? function ?
ohci* at pci? dev ? function ?
usb* at ehci?
usb* at ohci?
uhub* at usb?
uhub* at uhub? port ? configuration ? interface ?
# USB Mass Storage Devices
umass* at uhub? port ? configuration ? interface ?
wd* at umass?
scsibus* at umass? channel ?
sd* at scsibus? target ? lun ? # SCSI disk drives
# USB Ethernet adapters
aue* at uhub? port ? # ADMtek AN986 Pegasus based adapters
axe* at uhub? port ? # ASIX AX88172 based adapters
cdce* at uhub? port ? # CDC, Ethernet Networking Control Model
cue* at uhub? port ? # CATC USB-EL1201A based adapters
kue* at uhub? port ? # Kawasaki LSI KL5KUSB101B based adapters
udav* at uhub? port ? # Davicom DM9601 based adapters
url* at uhub? port ? # Realtek RTL8150L based adapters
# MII/PHY support
ukphy* at mii? phy ? # Generic/Unknown PHY
# USB 802.11 adapters
atu* at uhub? port ? # Atmel AT76C50XX based adapters
ral* at uhub? port ? # Ralink Technology RT25x0 802.11a/b/g
# USB Generic driver
ugen* at uhub? port ? configuration ? interface ?
# Pseudo-Devices
# disk/mass storage pseudo-devices
#pseudo-device md 1 # memory disk device (ramdisk)
#pseudo-device vnd 4 # disk-like interface to files
# network pseudo-devices
pseudo-device bpfilter 4 # Berkeley packet filter
#pseudo-device ipfilter # IP filter (firewall) and NAT
pseudo-device loop # network loopback
#pseudo-device ppp 2 # Point-to-Point Protocol
#pseudo-device kttcp # network loopback
#pseudo-device tun 2 # network tunneling over tty
#pseudo-device vlan
#pseudo-device bridge
# miscellaneous pseudo-devices
pseudo-device pty # pseudo-terminals
pseudo-device rnd # /dev/random and in-kernel generator
pseudo-device clockctl # user control of clock subsystem
pseudo-device ksyms # /dev/ksyms
#pseudo-device crypto # opencrypto framework
# data mover pseudo-devices
#pseudo-device swdmover # softare dmover(9) back-end
#pseudo-device dmoverio # /dev/dmover dmover(9) interface

View File

@ -0,0 +1,40 @@
# $NetBSD%
#
# Linksys NSLU2 "Slug" configuration info
#
# Use the generic ARM soft interrupt code.
file arch/arm/arm/softintr.c
file arch/evbarm/nslu2/nslu2_machdep.c
# IXP425 Network Processor CPU support
include "arch/arm/xscale/files.ixp425"
# IXP425 PCI bus support
attach ixpio at mainbus with ixpio_mainbus
file arch/evbarm/nslu2/nslu2_mainbus.c ixpio_mainbus
file arch/evbarm/nslu2/nslu2_pci.c ixpio
# IXP425 slow peripheral bus support
attach ixpsip at mainbus
# Bitbang I2C bus (using two GPIO pins)
# (Attached to ixpsip for want of a better place)
device slugiic: i2cbus, i2c_bitbang
attach slugiic at ixpsip
file arch/evbarm/nslu2/nslu2_iic.c slugiic
# Power/Reset button support
device slugbutt: sysmon_power, sysmon_taskq
attach slugbutt at ixpsip
file arch/evbarm/nslu2/nslu2_buttons.c slugbutt
# Disk activity and status LED support
device slugled
attach slugled at ixpsip
file arch/evbarm/nslu2/nslu2_leds.c slugled
# Buzzer support
#device slugbuzz
#attach slugbuzz at ixpsip
#file arch/evbarm/nslu2/nslu2_slugbuzz.c slugbuzz

View File

@ -0,0 +1,14 @@
# $NetBSD: mk.nslu2,v 1.1 2006/02/28 20:40:33 scw Exp $
SYSTEM_FIRST_OBJ= nslu2_start.o
SYSTEM_FIRST_SFILE= ${THISARM}/nslu2/nslu2_start.S
SYSTEM_OBJ= ${MD_OBJS} ${MI_OBJS} ${OBJS} ${SYSLIBCOMPAT} ${LIBKERN}
KERNEL_BASE_PHYS?=0x10200000
KERNEL_BASE_VIRT=0xc0200000
SYSTEM_LD_TAIL_EXTRA+=; \
echo ${OBJCOPY} -S -O binary $@ $@.bin; \
${OBJCOPY} -S -O binary $@ $@.bin
EXTRA_KERNELS+= ${KERNELS:@.KERNEL.@${.KERNEL.}.bin@}

View File

@ -0,0 +1,23 @@
# $NetBSD: std.nslu2,v 1.1 2006/02/28 20:40:33 scw Exp $
#
# Standard NetBSD/evbarm options for Linksys NSLU2
machine evbarm arm
include "conf/std" # MI standard options
# Pull in NSLU2 config definitions.
include "arch/evbarm/conf/files.nslu2"
options EXEC_ELF32
options EXEC_AOUT
options EXEC_SCRIPT
options ARM32
makeoptions LOADADDRESS="0xc0200000"
makeoptions BOARDMKFRAG="${THISARM}/conf/mk.nslu2"
options ARM_INTR_IMPL="<arch/arm/xscale/ixp425_intr.h>"
options __BUS_SPACE_HAS_STREAM_METHODS
# We need to configure the PCI bus.
options PCI_NETBSD_CONFIGURE

View File

@ -0,0 +1,125 @@
$NetBSD: README,v 1.1 2006/02/28 20:40:33 scw Exp $
NetBSD for the Linksys NSLU2 (a.k.a. "Slug")
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The NSLU2 (Network Storage Link for USB 2.0 Disk Drives) is a small, cheap
NAS device consisting of an Intel IXP420 (Xscale) CPU, a 10/100mbit Ethernet
port, and two USB 2.0 ports. It has 32MB of SDRAM and 8MB of Flash memory,
and runs RedBoot/Linux out of the box.
It is eminently hackable.
The guys over at http://www.nslu2-linux.org/ have done a good job of
documenting just about every aspect of the hardware and original firmware.
They also provide a custom "Unslung" Linux distribution to replace the
original hobbled kernel/userland.
Because of the amount of documentation available, and the fact that Slugs
are available so cheaply (I paid just over UKP 50 for mine, brand new) I
decided to buy one and port NetBSD to it.
This is the result of that effort.
Note: The Slug's IXP420 CPU runs in big-endian mode, so when building a
cross toolchain you must pass "-m evbarm -a armeb" to build.sh.
Current status
==============
The following bits of Slug hardware are not (yet?) supported:
- NPE Ethernet
Someone will have to port Intel's IXP425 access library before this can
be made to work. If that someone is you, the source code is available
online here:
http://www.intel.com/design/network/products/npfamily/ixp425.htm
Look under "Tools & Software", then select "Register/Login" to download
"Intel(R) IXP400 Software". Documentation is available in the
"Technical Documents" section.
The easiest option will be to download the non-crypto version of the
Access Library. The crypto-enabled version requires a lot more form
filling. The Slug's IXP420 has no crypto capabilities anyway.
- Flash ROM
You can write gzboot kernels (when support is added) to Flash using
RedBoot, so all is not lost.
- Buzzer
In the absence of a decent API to expose the onboard buzzer to userland,
this is not yet supported. I envisage using timer1 to generate an
interrupt at the required rate (1-2KHz). The handler will toggle the
buzzer GPIO pin. Obviously timer1 will be configured only when necessary
as a 1-2KHz interrupt rate will sap a fair bit of CPU horsepower.
Everything else is fully supported, including the power/reset buttons and
disk activity/status LEDs.
Non-hardware items on the TODO list include:
- gzboot support.
This needs to emulate a "vmlinuz" compressed Linux kernel image so that
RedBoot will invoke the kernel from Flash at power-up.
- Move the kernel link address closer to the start of SDRAM. We waste a
little under 2MB with the current setup.
- The clock runs slow. In ixp425_timer.c, COUNTS_PER_SEC is defined as
66666600 instead of 66666667. This, together with rounding errors, is
almost certainly the cause.
Getting NetBSD onto the NSLU2
=============================
Thanks to the efforts of the guys over at www.nslu2-linux.org, hacking the
Slug is a pretty easy proposition, but some soldering skills are essential.
For a first-time install of NetBSD (at least until someone comes up with a
nice easy binary install image) you will almost certainly require access to
the serial console. This means firing up your trusty soldering iron and
hooking up a MAX3232 chip to your Slug. While your soldering iron is hot,
you should seriously consider de-restricting your Slug's CPU core clock
speed (133MHz stock, 266MHz de-restricted) by removing a single surface-
mount resistor. Full instructions for both the these mods are on the above
website.
Once you have console access you can interrupt RedBoot's auto-boot process
using CTRL-C. You are now in a position to download a NetBSD kernel into
SDRAM.
You will have to configure a TFTP server on a machine hooked up to the same
Ethernet segment as the Slug. This machine's Ethernet interface must also
be configured to have an address in the 192.168.0.0/24 subnet since the
Slug's Ethernet *always* defaults to 192.168.0.1 when running RedBoot.
There seems to be no way to alter this, so the best course of action will
probably be to set up an alias on the server's interface. 192.168.0.2 is
a good choice.
Assuming you've done all that and have dropped a suitable kernel image
into the TFTP directory, the following commands will load and run the
kernel.
redboot> ip_address -h 192.168.0.2
redboot> load -r -b 0x200000 netbsd.bin
redboot> go
At this point your only real option is to mount the root filesystem from
a USB disk device as the onboard Ethernet is not (yet?) supported. However,
there's nothing to stop you using a USB-Ethernet interface...
Note that the kernel will always report the CPU core clock speed as 266MHz
even if your Slug's CPU clock is running at a stock 133MHz.
Burning a NetBSD kernel into Flash
==================================
TBD (waiting for gzboot support).

View File

@ -0,0 +1,187 @@
/* $NetBSD: nslu2_buttons.c,v 1.1 2006/02/28 20:40:33 scw Exp $ */
/*-
* Copyright (c) 2006 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Steve C. Woodford.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: nslu2_buttons.c,v 1.1 2006/02/28 20:40:33 scw Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <dev/sysmon/sysmonvar.h>
#include <dev/sysmon/sysmon_taskq.h>
#include <arm/xscale/ixp425reg.h>
#include <arm/xscale/ixp425var.h>
#include <evbarm/nslu2/nslu2reg.h>
struct slugbutt_softc {
struct device sc_dev;
struct sysmon_pswitch sc_smpwr;
struct sysmon_pswitch sc_smrst;
};
static int slugbutt_attached;
static void
power_event(void *arg)
{
struct slugbutt_softc *sc = arg;
sysmon_pswitch_event(&sc->sc_smpwr, PSWITCH_EVENT_PRESSED);
}
static int
power_intr(void *arg)
{
struct slugbutt_softc *sc = arg;
int rv;
GPIO_CONF_WRITE_4(ixp425_softc, IXP425_GPIO_GPISR,
1u << GPIO_BUTTON_PWR);
rv = sysmon_task_queue_sched(0, power_event, sc);
if (rv) {
printf("%s: WARNING: unable to queue power button "
"callback: %d\n", sc->sc_dev.dv_xname, rv);
}
return (1);
}
static void
reset_event(void *arg)
{
struct slugbutt_softc *sc = arg;
sysmon_pswitch_event(&sc->sc_smrst, PSWITCH_EVENT_PRESSED);
}
static int
reset_intr(void *arg)
{
struct slugbutt_softc *sc = arg;
int rv;
GPIO_CONF_WRITE_4(ixp425_softc, IXP425_GPIO_GPISR,
1u << GPIO_BUTTON_RST);
rv = sysmon_task_queue_sched(0, reset_event, sc);
if (rv) {
printf("%s: WARNING: unable to queue reset button "
"callback: %d\n", sc->sc_dev.dv_xname, rv);
}
return (1);
}
static void
slugbutt_deferred(struct device *self)
{
struct slugbutt_softc *sc = (struct slugbutt_softc *) self;
struct ixp425_softc *ixsc = ixp425_softc;
uint32_t reg;
/* Configure the GPIO pins as inputs */
reg = GPIO_CONF_READ_4(ixsc, IXP425_GPIO_GPOER);
reg |= GPIO_BUTTON_PWR | GPIO_BUTTON_RST;
GPIO_CONF_WRITE_4(ixsc, IXP425_GPIO_GPOER, reg);
/* Configure the input type: Falling edge */
reg = GPIO_CONF_READ_4(ixsc, GPIO_TYPE_REG(GPIO_BUTTON_PWR));
reg &= ~GPIO_TYPE(GPIO_BUTTON_PWR, GPIO_TYPE_MASK);
reg |= GPIO_TYPE(GPIO_BUTTON_PWR, GPIO_TYPE_EDG_FALLING);
GPIO_CONF_WRITE_4(ixsc, GPIO_TYPE_REG(GPIO_BUTTON_PWR), reg);
reg = GPIO_CONF_READ_4(ixsc, GPIO_TYPE_REG(GPIO_BUTTON_RST));
reg &= ~GPIO_TYPE(GPIO_BUTTON_RST, GPIO_TYPE_MASK);
reg |= GPIO_TYPE(GPIO_BUTTON_RST, GPIO_TYPE_EDG_FALLING);
GPIO_CONF_WRITE_4(ixsc, GPIO_TYPE_REG(GPIO_BUTTON_RST), reg);
/* Clear any existing interrupt */
GPIO_CONF_WRITE_4(ixsc, IXP425_GPIO_GPISR, (1u << GPIO_BUTTON_PWR) |
(1u << GPIO_BUTTON_RST));
sysmon_task_queue_init();
sc->sc_smpwr.smpsw_name = sc->sc_dev.dv_xname;
sc->sc_smpwr.smpsw_type = PSWITCH_TYPE_POWER;
if (sysmon_pswitch_register(&sc->sc_smpwr) != 0) {
printf("%s: unable to register power button with sysmon\n",
sc->sc_dev.dv_xname);
return;
}
sc->sc_smrst.smpsw_name = sc->sc_dev.dv_xname;
sc->sc_smrst.smpsw_type = PSWITCH_TYPE_RESET;
if (sysmon_pswitch_register(&sc->sc_smrst) != 0) {
printf("%s: unable to register reset button with sysmon\n",
sc->sc_dev.dv_xname);
return;
}
/* Hook the interrupts */
ixp425_intr_establish(BUTTON_PWR_INT, IPL_TTY, power_intr, sc);
ixp425_intr_establish(BUTTON_RST_INT, IPL_TTY, reset_intr, sc);
}
static int
slugbutt_match(struct device *parent, struct cfdata *cf, void *arg)
{
return (slugbutt_attached == 0);
}
static void
slugbutt_attach(struct device *parent, struct device *self, void *arg)
{
slugbutt_attached = 1;
aprint_normal(": Power and Reset buttons\n");
/* Defer, to ensure ixp425_softc has been initialised */
config_interrupts(self, slugbutt_deferred);
}
CFATTACH_DECL(slugbutt, sizeof(struct slugbutt_softc),
slugbutt_match, slugbutt_attach, NULL, NULL);

View File

@ -0,0 +1,239 @@
/* $NetBSD: nslu2_iic.c,v 1.1 2006/02/28 20:40:33 scw Exp $ */
/*-
* Copyright (c) 2006 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Steve C. Woodford.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/device.h>
#include <sys/lock.h>
#include <machine/bus.h>
#include <dev/i2c/i2cvar.h>
#include <dev/i2c/i2c_bitbang.h>
#include <arm/xscale/ixp425reg.h>
#include <arm/xscale/ixp425var.h>
#include <evbarm/nslu2/nslu2reg.h>
struct slugiic_softc {
struct device sc_dev;
struct i2c_controller sc_ic;
struct i2c_bitbang_ops sc_ibo;
struct lock sc_lock;
uint32_t sc_dirout;
};
static int
slugiic_acquire_bus(void *arg, int flags)
{
struct slugiic_softc *sc = arg;
if (flags & I2C_F_POLL)
return (0);
return (lockmgr(&sc->sc_lock, LK_EXCLUSIVE, NULL));
}
static void
slugiic_release_bus(void *arg, int flags)
{
struct slugiic_softc *sc = arg;
if (flags & I2C_F_POLL)
return;
(void) lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
}
static int
slugiic_send_start(void *arg, int flags)
{
struct slugiic_softc *sc = arg;
return (i2c_bitbang_send_start(sc, flags, &sc->sc_ibo));
}
static int
slugiic_send_stop(void *arg, int flags)
{
struct slugiic_softc *sc = arg;
return (i2c_bitbang_send_stop(sc, flags, &sc->sc_ibo));
}
static int
slugiic_initiate_xfer(void *arg, i2c_addr_t addr, int flags)
{
struct slugiic_softc *sc = arg;
return (i2c_bitbang_initiate_xfer(sc, addr, flags, &sc->sc_ibo));
}
static int
slugiic_read_byte(void *arg, uint8_t *vp, int flags)
{
struct slugiic_softc *sc = arg;
return (i2c_bitbang_read_byte(sc, vp, flags, &sc->sc_ibo));
}
static int
slugiic_write_byte(void *arg, uint8_t v, int flags)
{
struct slugiic_softc *sc = arg;
return (i2c_bitbang_write_byte(sc, v, flags, &sc->sc_ibo));
}
static void
slugiic_set_dir(void *arg, uint32_t bits)
{
struct slugiic_softc *sc = arg;
uint32_t reg;
int s;
if (sc->sc_dirout == (bits ^ GPIO_I2C_SDA_BIT))
return;
s = splhigh();
sc->sc_dirout = bits ^ GPIO_I2C_SDA_BIT;
reg = GPIO_CONF_READ_4(ixp425_softc, IXP425_GPIO_GPOER);
reg &= ~GPIO_I2C_SDA_BIT;
GPIO_CONF_WRITE_4(ixp425_softc, IXP425_GPIO_GPOER, reg | bits);
splx(s);
}
static void
slugiic_set_bits(void *arg, uint32_t bits)
{
struct slugiic_softc *sc = arg;
uint32_t reg;
int s;
if (sc->sc_dirout == 0 && !(bits & GPIO_I2C_SDA_BIT))
bits |= GPIO_I2C_SDA_BIT;
s = splhigh();
reg = GPIO_CONF_READ_4(ixp425_softc, IXP425_GPIO_GPOUTR);
reg &= ~(GPIO_I2C_SDA_BIT | GPIO_I2C_SCL_BIT);
GPIO_CONF_WRITE_4(ixp425_softc, IXP425_GPIO_GPOUTR, reg | bits);
splx(s);
}
static uint32_t
slugiic_read_bits(void *arg)
{
uint32_t reg;
reg = GPIO_CONF_READ_4(ixp425_softc, IXP425_GPIO_GPINR);
return (reg & (GPIO_I2C_SDA_BIT | GPIO_I2C_SCL_BIT));
}
static void
slugiic_deferred_attach(struct device *device)
{
struct slugiic_softc *sc = (struct slugiic_softc *)device;
struct i2cbus_attach_args iba;
uint32_t reg;
reg = GPIO_CONF_READ_4(ixp425_softc, IXP425_GPIO_GPOUTR);
reg |= GPIO_I2C_SDA_BIT | GPIO_I2C_SCL_BIT;
GPIO_CONF_WRITE_4(ixp425_softc, IXP425_GPIO_GPOUTR, reg);
reg = GPIO_CONF_READ_4(ixp425_softc, IXP425_GPIO_GPOER);
reg &= ~GPIO_I2C_SCL_BIT;
reg |= GPIO_I2C_SDA_BIT;
GPIO_CONF_WRITE_4(ixp425_softc, IXP425_GPIO_GPOER, reg);
iba.iba_name = "iic";
iba.iba_tag = &sc->sc_ic;
(void) config_found(&sc->sc_dev, &iba, iicbus_print);
}
static int
slugiic_match(struct device *parent, struct cfdata *cf, void *arg)
{
return (1);
}
static void
slugiic_attach(struct device *parent, struct device *self, void *arg)
{
struct slugiic_softc *sc = (struct slugiic_softc *)self;
aprint_naive("\n");
aprint_normal(": I2C bus\n");
sc->sc_ic.ic_cookie = sc;
sc->sc_ic.ic_acquire_bus = slugiic_acquire_bus;
sc->sc_ic.ic_release_bus = slugiic_release_bus;
sc->sc_ic.ic_exec = NULL;
sc->sc_ic.ic_send_start = slugiic_send_start;
sc->sc_ic.ic_send_stop = slugiic_send_stop;
sc->sc_ic.ic_initiate_xfer = slugiic_initiate_xfer;
sc->sc_ic.ic_read_byte = slugiic_read_byte;
sc->sc_ic.ic_write_byte = slugiic_write_byte;
sc->sc_ibo.ibo_set_dir = slugiic_set_dir;
sc->sc_ibo.ibo_set_bits = slugiic_set_bits;
sc->sc_ibo.ibo_read_bits = slugiic_read_bits;
sc->sc_ibo.ibo_bits[I2C_BIT_SDA] = GPIO_I2C_SDA_BIT;
sc->sc_ibo.ibo_bits[I2C_BIT_SCL] = GPIO_I2C_SCL_BIT;
sc->sc_ibo.ibo_bits[I2C_BIT_OUTPUT] = 0;
sc->sc_ibo.ibo_bits[I2C_BIT_INPUT] = GPIO_I2C_SDA_BIT;
lockinit(&sc->sc_lock, PRIBIO|PCATCH, "slugiiclk", 0, 0);
sc->sc_dirout = 0;
/*
* Defer until ixp425_softc has been initialised
*/
config_interrupts(self, slugiic_deferred_attach);
}
CFATTACH_DECL(slugiic, sizeof(struct slugiic_softc),
slugiic_match, slugiic_attach, NULL, NULL);

View File

@ -0,0 +1,224 @@
/* $NetBSD: nslu2_leds.c,v 1.1 2006/02/28 20:40:33 scw Exp $ */
/*-
* Copyright (c) 2006 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Steve C. Woodford.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: nslu2_leds.c,v 1.1 2006/02/28 20:40:33 scw Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/device.h>
#include <sys/callout.h>
#include <sys/disk.h>
#include <arm/xscale/ixp425var.h>
#include <evbarm/nslu2/nslu2reg.h>
#define SLUGLED_NLEDS 2
#define SLUGLED_DISKNAMES "sd%d" /* XXX: Make this configurable! */
#define SLUGLED_POLL (hz/10) /* Poll disks 10 times per second */
#define SLUGLED_FLASH_LEN 2 /* How long, in terms of SLUGLED_POLL,
to light up an LED */
#define SLUGLED_READY_FLASH 3 /* Ditto for flashing Ready LED */
#define LEDBITS_DISK0 (1u << GPIO_LED_DISK1)
#define LEDBITS_DISK1 (1u << GPIO_LED_DISK2)
/*
* The Ready/Status bits control a tricolour LED.
* Ready is green, status is red.
*/
#define LEDBITS_READY (1u << GPIO_LED_READY)
#define LEDBITS_STATUS (1u << GPIO_LED_STATUS)
struct slugled_softc {
struct device sc_dev;
struct callout sc_co;
struct {
char sc_dk_name[DK_DISKNAMELEN];
struct timeval sc_dk_time;
int sc_dk_flash; /* Countdown to LED clear */
} sc_dk[SLUGLED_NLEDS];
uint32_t sc_state;
int sc_count;
};
static int slugled_attached;
static void
slugled_callout(void *arg)
{
struct slugled_softc *sc = arg;
struct timeval t;
struct disk *dk;
uint32_t reg, bit, new_state;
int s, i, dkbusy;
new_state = sc->sc_state;
for (i = 0; i < SLUGLED_NLEDS; i++) {
bit = i ? LEDBITS_DISK1 : LEDBITS_DISK0;
s = splbio();
if ((dk = disk_find(sc->sc_dk[i].sc_dk_name)) == NULL) {
splx(s);
if (sc->sc_dk[i].sc_dk_flash > 0) {
new_state |= bit;
sc->sc_dk[i].sc_dk_flash = 0;
sc->sc_dk[i].sc_dk_time = mono_time;
}
continue;
}
dkbusy = dk->dk_busy;
t = dk->dk_timestamp;
splx(s);
if (dkbusy || t.tv_sec != sc->sc_dk[i].sc_dk_time.tv_sec ||
t.tv_usec != sc->sc_dk[i].sc_dk_time.tv_usec) {
sc->sc_dk[i].sc_dk_flash = SLUGLED_FLASH_LEN;
sc->sc_dk[i].sc_dk_time = t;
new_state &= ~bit;
} else
if (sc->sc_dk[i].sc_dk_flash > 0 &&
--(sc->sc_dk[i].sc_dk_flash) == 0)
new_state |= bit;
}
if ((++(sc->sc_count) % SLUGLED_READY_FLASH) == 0)
new_state ^= LEDBITS_READY;
if (sc->sc_state != new_state) {
sc->sc_state = new_state;
s = splhigh();
reg = GPIO_CONF_READ_4(ixp425_softc, IXP425_GPIO_GPOUTR);
reg &= ~(LEDBITS_DISK0 | LEDBITS_DISK1 | LEDBITS_READY);
reg |= new_state;
GPIO_CONF_WRITE_4(ixp425_softc, IXP425_GPIO_GPOUTR, reg);
splx(s);
}
callout_schedule(&sc->sc_co, SLUGLED_POLL);
}
static void
slugled_shutdown(void *arg)
{
struct slugled_softc *sc = arg;
uint32_t reg;
int s;
/* Cancel the disk activity callout */
s = splsoftclock();
callout_stop(&sc->sc_co);
splx(s);
/* Turn off the disk LEDs, and set Ready/Status to red */
s = splhigh();
reg = GPIO_CONF_READ_4(ixp425_softc,IXP425_GPIO_GPOUTR);
reg &= ~LEDBITS_READY;
reg |= LEDBITS_DISK0 | LEDBITS_DISK1 | LEDBITS_STATUS;
GPIO_CONF_WRITE_4(ixp425_softc,IXP425_GPIO_GPOUTR, reg);
splx(s);
}
static void
slugled_defer(struct device *self)
{
struct slugled_softc *sc = (struct slugled_softc *) self;
struct ixp425_softc *ixsc = ixp425_softc;
uint32_t reg;
int i, s;
s = splhigh();
/* Configure LED GPIO pins as output */
reg = GPIO_CONF_READ_4(ixsc, IXP425_GPIO_GPOER);
reg &= ~(LEDBITS_DISK0 | LEDBITS_DISK1);
reg &= ~(LEDBITS_READY | LEDBITS_STATUS);
GPIO_CONF_WRITE_4(ixsc, IXP425_GPIO_GPOER, reg);
/* All LEDs off, except Ready LED */
reg = GPIO_CONF_READ_4(ixsc, IXP425_GPIO_GPOUTR);
reg |= LEDBITS_DISK0 | LEDBITS_DISK1 | LEDBITS_READY;
reg &= ~LEDBITS_STATUS;
GPIO_CONF_WRITE_4(ixsc, IXP425_GPIO_GPOUTR, reg);
splx(s);
for (i = 0; i < SLUGLED_NLEDS; i++) {
sprintf(sc->sc_dk[i].sc_dk_name, SLUGLED_DISKNAMES, i);
sc->sc_dk[i].sc_dk_flash = 0;
sc->sc_dk[i].sc_dk_time = mono_time;
}
sc->sc_state = LEDBITS_DISK0 | LEDBITS_DISK1 | LEDBITS_READY;
sc->sc_count = 0;
if (shutdownhook_establish(slugled_shutdown, sc) == NULL)
aprint_error("%s: WARNING - Failed to register shutdown hook\n",
sc->sc_dev.dv_xname);
callout_init(&sc->sc_co);
callout_setfunc(&sc->sc_co, slugled_callout, sc);
callout_schedule(&sc->sc_co, SLUGLED_POLL);
}
static int
slugled_match(struct device *parent, struct cfdata *match, void *aux)
{
return (slugled_attached == 0);
}
static void
slugled_attach(struct device *parent, struct device *self, void *aux)
{
aprint_normal(": LED support\n");
slugled_attached = 1;
config_interrupts(self, slugled_defer);
}
CFATTACH_DECL(slugled, sizeof(struct slugled_softc),
slugled_match, slugled_attach, NULL, NULL);

View File

@ -0,0 +1,893 @@
/* $NetBSD: nslu2_machdep.c,v 1.1 2006/02/28 20:40:33 scw Exp $ */
/*-
* Copyright (c) 2006 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Steve C. Woodford.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 2003
* Ichiro FUKUHARA <ichiro@ichiro.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Ichiro FUKUHARA.
* 4. The name of the company nor the name of the author may be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY ICHIRO FUKUHARA ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL ICHIRO FUKUHARA OR THE VOICES IN HIS HEAD BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Copyright (c) 1997,1998 Mark Brinicombe.
* Copyright (c) 1997,1998 Causality Limited.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Mark Brinicombe
* for the NetBSD Project.
* 4. The name of the company nor the name of the author may be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Machine dependant functions for kernel setup for Linksys NSLU2
* using RedBoot firmware.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: nslu2_machdep.c,v 1.1 2006/02/28 20:40:33 scw Exp $");
#include "opt_ddb.h"
#include "opt_kgdb.h"
#include "opt_pmap_debug.h"
#include <sys/param.h>
#include <sys/device.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/exec.h>
#include <sys/proc.h>
#include <sys/msgbuf.h>
#include <sys/reboot.h>
#include <sys/termios.h>
#include <sys/ksyms.h>
#include <uvm/uvm_extern.h>
#include <dev/cons.h>
#include <machine/db_machdep.h>
#include <ddb/db_sym.h>
#include <ddb/db_extern.h>
#include <machine/bootconfig.h>
#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/frame.h>
#include <arm/undefined.h>
#include <arm/arm32/machdep.h>
#include <arm/xscale/ixp425reg.h>
#include <arm/xscale/ixp425var.h>
#include <arm/xscale/ixp425_sipvar.h>
#include <evbarm/nslu2/nslu2reg.h>
#include "com.h"
#if NCOM > 0
#include <dev/ic/comreg.h>
#include <dev/ic/comvar.h>
#endif
#include "opt_ipkdb.h"
#include "ksyms.h"
/* Kernel text starts 2MB in from the bottom of the kernel address space. */
#define KERNEL_TEXT_BASE (KERNEL_BASE + 0x00200000)
#define KERNEL_VM_BASE (KERNEL_BASE + 0x01000000)
/*
* The range 0xc1000000 - 0xccffffff is available for kernel VM space
* Core-logic registers and I/O mappings occupy 0xfd000000 - 0xffffffff
*/
#define KERNEL_VM_SIZE 0x0C000000
/*
* Address to call from cpu_reset() to reset the machine.
* This is machine architecture dependant as it varies depending
* on where the ROM appears when you turn the MMU off.
*/
u_int cpu_reset_address = 0x00000000;
/* Define various stack sizes in pages */
#define IRQ_STACK_SIZE 1
#define ABT_STACK_SIZE 1
#ifdef IPKDB
#define UND_STACK_SIZE 2
#else
#define UND_STACK_SIZE 1
#endif
BootConfig bootconfig; /* Boot config storage */
char *boot_args = NULL;
char *boot_file = NULL;
vm_offset_t physical_start;
vm_offset_t physical_freestart;
vm_offset_t physical_freeend;
vm_offset_t physical_end;
u_int free_pages;
vm_offset_t pagetables_start;
int physmem = 0;
/* Physical and virtual addresses for some global pages */
pv_addr_t systempage;
pv_addr_t irqstack;
pv_addr_t undstack;
pv_addr_t abtstack;
pv_addr_t kernelstack;
pv_addr_t minidataclean;
vm_offset_t msgbufphys;
extern u_int data_abort_handler_address;
extern u_int prefetch_abort_handler_address;
extern u_int undefined_handler_address;
extern int end;
#ifdef PMAP_DEBUG
extern int pmap_debug_level;
#endif
#define KERNEL_PT_SYS 0 /* L2 table for mapping zero page */
#define KERNEL_PT_KERNEL 1 /* L2 table for mapping kernel */
#define KERNEL_PT_KERNEL_NUM 4
#define KERNEL_PT_IO (KERNEL_PT_KERNEL + KERNEL_PT_KERNEL_NUM)
/* L2 tables for mapping kernel VM */
#define KERNEL_PT_VMDATA (KERNEL_PT_IO + 1)
#define KERNEL_PT_VMDATA_NUM 4 /* start with 16MB of KVM */
#define NUM_KERNEL_PTS (KERNEL_PT_VMDATA + KERNEL_PT_VMDATA_NUM)
pv_addr_t kernel_pt_table[NUM_KERNEL_PTS];
struct user *proc0paddr;
/* Prototypes */
void consinit(void);
u_int cpu_get_control __P((void));
/*
* Define the default console speed for the board. This is generally
* what the firmware provided with the board defaults to.
*/
#ifndef CONSPEED
#define CONSPEED B115200
#endif /* ! CONSPEED */
#ifndef CONUNIT
#define CONUNIT 0
#endif
#ifndef CONMODE
#define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB)) | CS8) /* 8N1 */
#endif
int comcnspeed = CONSPEED;
int comcnmode = CONMODE;
int comcnunit = CONUNIT;
#if KGDB
#ifndef KGDB_DEVNAME
#error Must define KGDB_DEVNAME
#endif
const char kgdb_devname[] = KGDB_DEVNAME;
#ifndef KGDB_DEVADDR
#error Must define KGDB_DEVADDR
#endif
unsigned long kgdb_devaddr = KGDB_DEVADDR;
#ifndef KGDB_DEVRATE
#define KGDB_DEVRATE CONSPEED
#endif
int kgdb_devrate = KGDB_DEVRATE;
#ifndef KGDB_DEVMODE
#define KGDB_DEVMODE CONMODE
#endif
int kgdb_devmode = KGDB_DEVMODE;
#endif /* KGDB */
/*
* void cpu_reboot(int howto, char *bootstr)
*
* Reboots the system
*
* Deal with any syncing, unmounting, dumping and shutdown hooks,
* then reset the CPU.
*/
void
cpu_reboot(int howto, char *bootstr)
{
#ifdef DIAGNOSTIC
/* info */
printf("boot: howto=%08x curproc=%p\n", howto, curproc);
#endif
/*
* If we are still cold then hit the air brakes
* and crash to earth fast
*/
if (cold) {
doshutdownhooks();
printf("The operating system has halted.\n");
printf("Please press any key to reboot.\n\n");
cngetc();
goto reset;
}
/* Disable console buffering */
/*
* If RB_NOSYNC was not specified sync the discs.
* Note: Unless cold is set to 1 here, syslogd will die during the
* unmount. It looks like syslogd is getting woken up only to find
* that it cannot page part of the binary in as the filesystem has
* been unmounted.
*/
if (!(howto & RB_NOSYNC))
bootsync();
/* Say NO to interrupts */
splhigh();
/* Do a dump if requested. */
if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP)
dumpsys();
/* Run any shutdown hooks */
doshutdownhooks();
/* Make sure IRQ's are disabled */
IRQdisable;
if (howto & RB_HALT) {
printf("The operating system has halted.\n");
printf("Please press any key to %s.\n\n",
(howto & RB_POWERDOWN) ? "power down" : "reboot");
cngetc();
}
reset:
/*
* Make really really sure that all interrupts are disabled,
*/
(void) disable_interrupts(I32_bit | F32_bit);
if (howto & RB_POWERDOWN) {
uint32_t reg;
printf("powering down...\n\r");
/* Delay to allow the UART's Tx FIFO to drain */
delay(50000);
#define GPRD(r) *((volatile uint32_t *)(IXP425_GPIO_VBASE+(r)))
#define GPWR(r,v) *((volatile uint32_t *)(IXP425_GPIO_VBASE+(r))) = (v)
/*
* Power-down pin requires a short pulse
*/
reg = GPRD(IXP425_GPIO_GPOUTR);
reg |= 1u << GPIO_POWER_OFF;
GPWR(IXP425_GPIO_GPOUTR, reg);
delay(1000);
reg = GPRD(IXP425_GPIO_GPOUTR);
reg &= ~(1u << GPIO_POWER_OFF);
GPWR(IXP425_GPIO_GPOUTR, reg);
delay(500000);
printf("POWER OFF FAILED! TRYING TO REBOOT INSTEAD\n\r");
}
printf("rebooting...\n\r");
#define WDWR(r,v) *((volatile uint32_t *)(IXP425_TIMER_VBASE+(r))) = (v)
/* Force a watchdog reset */
WDWR(IXP425_OST_WDOG_KEY, OST_WDOG_KEY_MAJICK);
WDWR(IXP425_OST_WDOG_ENAB, OST_WDOG_ENAB_RST_ENA);
WDWR(IXP425_OST_WDOG, 0x1000);
WDWR(IXP425_OST_WDOG_ENAB,
OST_WDOG_ENAB_RST_ENA | OST_WDOG_ENAB_CNT_ENA);
delay(500000);
/* ...and if that didn't work, just croak. */
printf("RESET FAILED!\n");
for (;;);
}
/* Static device mappings. */
static const struct pmap_devmap nslu2_devmap[] = {
/* Physical/Virtual address for I/O space */
{
IXP425_IO_VBASE,
IXP425_IO_HWBASE,
IXP425_IO_SIZE,
VM_PROT_READ|VM_PROT_WRITE,
PTE_NOCACHE,
},
/* Expansion Bus */
{
IXP425_EXP_VBASE,
IXP425_EXP_HWBASE,
IXP425_EXP_SIZE,
VM_PROT_READ|VM_PROT_WRITE,
PTE_NOCACHE,
},
/* IXP425 PCI Configuration */
{
IXP425_PCI_VBASE,
IXP425_PCI_HWBASE,
IXP425_PCI_SIZE,
VM_PROT_READ|VM_PROT_WRITE,
PTE_NOCACHE,
},
/* SDRAM Controller */
{
IXP425_MCU_VBASE,
IXP425_MCU_HWBASE,
IXP425_MCU_SIZE,
VM_PROT_READ|VM_PROT_WRITE,
PTE_NOCACHE,
},
/* PCI Memory Space */
{
IXP425_PCI_MEM_VBASE,
IXP425_PCI_MEM_HWBASE,
IXP425_PCI_MEM_SIZE,
VM_PROT_READ|VM_PROT_WRITE,
PTE_NOCACHE,
},
/* Flash memory */
{
NSLU2_FLASH_VBASE,
NSLU2_FLASH_HWBASE,
NSLU2_FLASH_SIZE,
VM_PROT_READ|VM_PROT_WRITE,
PTE_NOCACHE,
},
{
0,
0,
0,
0,
0,
}
};
/*
* u_int initarm(...)
*
* Initial entry point on startup. This gets called before main() is
* entered.
* It should be responsible for setting up everything that must be
* in place when main is called.
* This includes
* Taking a copy of the boot configuration structure.
* Initialising the physical console so characters can be printed.
* Setting up page tables for the kernel
* Relocating the kernel to the bottom of physical memory
*/
u_int
initarm(void *arg)
{
extern vaddr_t xscale_cache_clean_addr;
#ifdef DIAGNOSTIC
extern vsize_t xscale_minidata_clean_size;
#endif
int loop;
int loop1;
u_int kerneldatasize;
u_int l1pagetable;
u_int freemempos;
pv_addr_t kernel_l1pt;
uint32_t reg;
/*
* Make sure the power-down GPIO pin is configured correctly, as
* cpu_reboot() may be called early on (e.g. from within ddb(9)).
*/
/* Pin is active-high, so make sure it's driven low */
reg = GPRD(IXP425_GPIO_GPOUTR);
reg &= ~(1u << GPIO_POWER_OFF);
GPWR(IXP425_GPIO_GPOUTR, reg);
/* Set as output */
reg = GPRD(IXP425_GPIO_GPOER);
reg &= ~(1u << GPIO_POWER_OFF);
GPWR(IXP425_GPIO_GPOER, reg);
/*
* Since we map v0xf0000000 == p0xc8000000, it's possible for
* us to initialize the console now.
*/
consinit();
#ifdef VERBOSE_INIT_ARM
/* Talk to the user */
printf("\nNetBSD/evbarm (Linksys NSLU2) booting ...\n");
#endif
/*
* Heads up ... Setup the CPU / MMU / TLB functions
*/
if (set_cpufuncs())
panic("cpu not recognized!");
/* XXX overwrite bootconfig to hardcoded values */
bootconfig.dramblocks = 1;
bootconfig.dram[0].address = 0x10000000;
bootconfig.dram[0].pages = ixp425_sdram_size() / PAGE_SIZE;
kerneldatasize = (u_int32_t)&end - (u_int32_t)KERNEL_TEXT_BASE;
#ifdef VERBOSE_INIT_ARM
printf("kernsize=0x%x\n", kerneldatasize);
#endif
kerneldatasize = ((kerneldatasize - 1) & ~(PAGE_SIZE * 4 - 1)) + PAGE_SIZE * 8;
/*
* Set up the variables that define the availablilty of
* physical memory. For now, we're going to set
* physical_freestart to 0x10200000 (where the kernel
* was loaded), and allocate the memory we need downwards.
* If we get too close to the L1 table that we set up, we
* will panic. We will update physical_freestart and
* physical_freeend later to reflect what pmap_bootstrap()
* wants to see.
*
* XXX pmap_bootstrap() needs an enema.
*/
physical_start = bootconfig.dram[0].address;
physical_end = physical_start + (bootconfig.dram[0].pages * PAGE_SIZE);
physical_freestart = physical_start
+ (KERNEL_TEXT_BASE - KERNEL_BASE) + kerneldatasize;
physical_freeend = physical_end;
physmem = (physical_end - physical_start) / PAGE_SIZE;
/* Tell the user about the memory */
#ifdef VERBOSE_INIT_ARM
printf("physmemory: %d pages at 0x%08lx -> 0x%08lx\n", physmem,
physical_start, physical_end - 1);
printf("Allocating page tables\n");
#endif
free_pages = (physical_freeend - physical_freestart) / PAGE_SIZE;
freemempos = 0x10000000;
#ifdef VERBOSE_INIT_ARM
printf("physical_start = 0x%08lx, physical_end = 0x%08lx\n",
physical_start, physical_end);
#endif
/* Define a macro to simplify memory allocation */
#define valloc_pages(var, np) \
alloc_pages((var).pv_pa, (np)); \
(var).pv_va = KERNEL_BASE + (var).pv_pa - physical_start;
#if 0
#define alloc_pages(var, np) \
physical_freeend -= ((np) * PAGE_SIZE); \
if (physical_freeend < physical_freestart) \
panic("initarm: out of memory"); \
(var) = physical_freeend; \
free_pages -= (np); \
memset((char *)(var), 0, ((np) * PAGE_SIZE));
#else
#define alloc_pages(var, np) \
(var) = freemempos; \
memset((char *)(var), 0, ((np) * PAGE_SIZE)); \
freemempos += (np) * PAGE_SIZE;
#endif
loop1 = 0;
kernel_l1pt.pv_pa = 0;
for (loop = 0; loop <= NUM_KERNEL_PTS; ++loop) {
/* Are we 16KB aligned for an L1 ? */
if (((physical_freeend - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) == 0
&& kernel_l1pt.pv_pa == 0) {
valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE);
} else {
valloc_pages(kernel_pt_table[loop1],
L2_TABLE_SIZE / PAGE_SIZE);
++loop1;
}
}
/* This should never be able to happen but better confirm that. */
if (!kernel_l1pt.pv_pa || (kernel_l1pt.pv_pa & (L1_TABLE_SIZE-1)) != 0)
panic("initarm: Failed to align the kernel page directory");
/*
* Allocate a page for the system page.
* This page will just contain the system vectors and can be
* shared by all processes.
*/
alloc_pages(systempage.pv_pa, 1);
/* Allocate stacks for all modes */
valloc_pages(irqstack, IRQ_STACK_SIZE);
valloc_pages(abtstack, ABT_STACK_SIZE);
valloc_pages(undstack, UND_STACK_SIZE);
valloc_pages(kernelstack, UPAGES);
/* Allocate enough pages for cleaning the Mini-Data cache. */
KASSERT(xscale_minidata_clean_size <= PAGE_SIZE);
valloc_pages(minidataclean, 1);
#ifdef VERBOSE_INIT_ARM
printf("IRQ stack: p0x%08lx v0x%08lx\n", irqstack.pv_pa,
irqstack.pv_va);
printf("ABT stack: p0x%08lx v0x%08lx\n", abtstack.pv_pa,
abtstack.pv_va);
printf("UND stack: p0x%08lx v0x%08lx\n", undstack.pv_pa,
undstack.pv_va);
printf("SVC stack: p0x%08lx v0x%08lx\n", kernelstack.pv_pa,
kernelstack.pv_va);
#endif
/*
* XXX Defer this to later so that we can reclaim the memory
* XXX used by the RedBoot page tables.
*/
alloc_pages(msgbufphys, round_page(MSGBUFSIZE) / PAGE_SIZE);
/*
* Ok we have allocated physical pages for the primary kernel
* page tables
*/
#ifdef VERBOSE_INIT_ARM
printf("Creating L1 page table at 0x%08lx\n", kernel_l1pt.pv_pa);
#endif
/*
* Now we start construction of the L1 page table
* We start by mapping the L2 page tables into the L1.
* This means that we can replace L1 mappings later on if necessary
*/
l1pagetable = kernel_l1pt.pv_pa;
/* Map the L2 pages tables in the L1 page table */
pmap_link_l2pt(l1pagetable, ARM_VECTORS_HIGH & ~(0x00400000 - 1),
&kernel_pt_table[KERNEL_PT_SYS]);
for (loop = 0; loop < KERNEL_PT_KERNEL_NUM; loop++)
pmap_link_l2pt(l1pagetable, KERNEL_BASE + loop * 0x00400000,
&kernel_pt_table[KERNEL_PT_KERNEL + loop]);
for (loop = 0; loop < KERNEL_PT_VMDATA_NUM; loop++)
pmap_link_l2pt(l1pagetable, KERNEL_VM_BASE + loop * 0x00400000,
&kernel_pt_table[KERNEL_PT_VMDATA + loop]);
/* update the top of the kernel VM */
pmap_curmaxkvaddr =
KERNEL_VM_BASE + (KERNEL_PT_VMDATA_NUM * 0x00400000);
pmap_link_l2pt(l1pagetable, IXP425_IO_VBASE,
&kernel_pt_table[KERNEL_PT_IO]);
#ifdef VERBOSE_INIT_ARM
printf("Mapping kernel\n");
#endif
/* Now we fill in the L2 pagetable for the kernel static code/data */
{
extern char etext[], _end[];
size_t textsize = (uintptr_t) etext - KERNEL_TEXT_BASE;
size_t totalsize = (uintptr_t) _end - KERNEL_TEXT_BASE;
u_int logical;
textsize = (textsize + PGOFSET) & ~PGOFSET;
totalsize = (totalsize + PGOFSET) & ~PGOFSET;
logical = 0x00200000; /* offset of kernel in RAM */
logical += pmap_map_chunk(l1pagetable, KERNEL_BASE + logical,
physical_start + logical, textsize,
VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
logical += pmap_map_chunk(l1pagetable, KERNEL_BASE + logical,
physical_start + logical, totalsize - textsize,
VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
}
#ifdef VERBOSE_INIT_ARM
printf("Constructing L2 page tables\n");
#endif
/* Map the stack pages */
pmap_map_chunk(l1pagetable, irqstack.pv_va, irqstack.pv_pa,
IRQ_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
pmap_map_chunk(l1pagetable, abtstack.pv_va, abtstack.pv_pa,
ABT_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
pmap_map_chunk(l1pagetable, undstack.pv_va, undstack.pv_pa,
UND_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
pmap_map_chunk(l1pagetable, kernelstack.pv_va, kernelstack.pv_pa,
UPAGES * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
pmap_map_chunk(l1pagetable, kernel_l1pt.pv_va, kernel_l1pt.pv_pa,
L1_TABLE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE);
for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) {
pmap_map_chunk(l1pagetable, kernel_pt_table[loop].pv_va,
kernel_pt_table[loop].pv_pa, L2_TABLE_SIZE,
VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE);
}
/* Map the Mini-Data cache clean area. */
xscale_setup_minidata(l1pagetable, minidataclean.pv_va,
minidataclean.pv_pa);
/* Map the vector page. */
pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa,
VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
/*
* Map the IXP425 registers
*/
pmap_devmap_bootstrap(l1pagetable, nslu2_devmap);
/*
* Give the XScale global cache clean code an appropriately
* sized chunk of unmapped VA space starting at 0xff000000
* (our device mappings end before this address).
*/
xscale_cache_clean_addr = 0xff000000U;
/*
* Now we have the real page tables in place so we can switch to them.
* Once this is done we will be running with the REAL kernel page
* tables.
*/
/*
* Update the physical_freestart/physical_freeend/free_pages
* variables.
*/
{
extern char _end[];
physical_freestart = physical_start +
(((((uintptr_t) _end) + PGOFSET) & ~PGOFSET) -
KERNEL_BASE);
physical_freeend = physical_end;
free_pages =
(physical_freeend - physical_freestart) / PAGE_SIZE;
}
/* Switch tables */
#ifdef VERBOSE_INIT_ARM
printf("freestart = 0x%08lx, free_pages = %d (0x%x)\n",
physical_freestart, free_pages, free_pages);
printf("switching to new L1 page table @%#lx...", kernel_l1pt.pv_pa);
#endif
cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT);
setttb(kernel_l1pt.pv_pa);
cpu_tlb_flushID();
cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2));
/*
* Moved from cpu_startup() as data_abort_handler() references
* this during uvm init
*/
proc0paddr = (struct user *)kernelstack.pv_va;
lwp0.l_addr = proc0paddr;
#ifdef VERBOSE_INIT_ARM
printf("bootstrap done.\n");
#endif
arm32_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL);
/*
* Pages were allocated during the secondary bootstrap for the
* stacks for different CPU modes.
* We must now set the r13 registers in the different CPU modes to
* point to these stacks.
* Since the ARM stacks use STMFD etc. we must set r13 to the top end
* of the stack memory.
*/
#ifdef VERBOSE_INIT_ARM
printf("init subsystems: stacks ");
#endif
set_stackptr(PSR_IRQ32_MODE,
irqstack.pv_va + IRQ_STACK_SIZE * PAGE_SIZE);
set_stackptr(PSR_ABT32_MODE,
abtstack.pv_va + ABT_STACK_SIZE * PAGE_SIZE);
set_stackptr(PSR_UND32_MODE,
undstack.pv_va + UND_STACK_SIZE * PAGE_SIZE);
/*
* Well we should set a data abort handler.
* Once things get going this will change as we will need a proper
* handler.
* Until then we will use a handler that just panics but tells us
* why.
* Initialisation of the vectors will just panic on a data abort.
* This just fills in a slightly better one.
*/
#ifdef VERBOSE_INIT_ARM
printf("vectors ");
#endif
data_abort_handler_address = (u_int)data_abort_handler;
prefetch_abort_handler_address = (u_int)prefetch_abort_handler;
undefined_handler_address = (u_int)undefinedinstruction_bounce;
/* Initialise the undefined instruction handlers */
#ifdef VERBOSE_INIT_ARM
printf("undefined ");
#endif
undefined_init();
/* Load memory into UVM. */
#ifdef VERBOSE_INIT_ARM
printf("page ");
#endif
uvm_setpagesize(); /* initialize PAGE_SIZE-dependent variables */
uvm_page_physload(atop(physical_freestart), atop(physical_freeend),
atop(physical_freestart), atop(physical_freeend),
VM_FREELIST_DEFAULT);
/* Boot strap pmap telling it where the kernel page table is */
#ifdef VERBOSE_INIT_ARM
printf("pmap ");
#endif
pmap_bootstrap((pd_entry_t *)kernel_l1pt.pv_va, KERNEL_VM_BASE,
KERNEL_VM_BASE + KERNEL_VM_SIZE);
/* Setup the IRQ system */
#ifdef VERBOSE_INIT_ARM
printf("irq ");
#endif
ixp425_intr_init();
#ifdef VERBOSE_INIT_ARM
printf("\nAll initialize done!\nNow Starting NetBSD, Hear we go!\n");
#endif
#ifdef BOOTHOWTO
boothowto = BOOTHOWTO;
#endif
#ifdef IPKDB
/* Initialise ipkdb */
ipkdb_init();
if (boothowto & RB_KDB)
ipkdb_connect(0);
#endif
#if NKSYMS || defined(DDB) || defined(LKM)
/* Firmware doesn't load symbols. */
ksyms_init(0, NULL, NULL);
#endif
#ifdef DDB
db_machine_init();
if (boothowto & RB_KDB)
Debugger();
#endif
/* We return the new stack pointer address */
return(kernelstack.pv_va + USPACE_SVC_STACK_TOP);
}
/*
* consinit
*/
void
consinit(void)
{
static int consinit_called;
static const bus_addr_t addrs[2] = {
IXP425_UART0_HWBASE, IXP425_UART1_HWBASE
};
if (consinit_called != 0)
return;
consinit_called = 1;
pmap_devmap_register(nslu2_devmap);
if (comcnattach(&ixp425_a4x_bs_tag, addrs[comcnunit],
comcnspeed, IXP425_UART_FREQ, COM_TYPE_PXA2x0, comcnmode))
panic("can't init serial console (UART%d)", comcnunit);
}

View File

@ -0,0 +1,66 @@
/* $NetBSD: nslu2_mainbus.c,v 1.1 2006/02/28 20:40:33 scw Exp $ */
/*-
* Copyright (c) 2006 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Steve C. Woodford.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: nslu2_mainbus.c,v 1.1 2006/02/28 20:40:33 scw Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <machine/autoconf.h>
#include <arm/xscale/ixp425reg.h>
#include <arm/xscale/ixp425var.h>
static int
ixp425_mainbus_match(struct device *parent, struct cfdata *cf, void *arg)
{
return (1);
}
static void
ixp425_mainbus_attach(struct device *parent, struct device *self, void *arg)
{
ixp425_attach((struct ixp425_softc *) self);
}
CFATTACH_DECL(ixpio_mainbus, sizeof(struct ixp425_softc),
ixp425_mainbus_match, ixp425_mainbus_attach, NULL, NULL);

View File

@ -0,0 +1,294 @@
/* $NetBSD: nslu2_pci.c,v 1.1 2006/02/28 20:40:33 scw Exp $ */
/*-
* Copyright (c) 2006 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Steve C. Woodford.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 2003
* Ichiro FUKUHARA <ichiro@ichiro.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Ichiro FUKUHARA.
* 4. The name of the company nor the name of the author may be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY ICHIRO FUKUHARA ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL ICHIRO FUKUHARA OR THE VOICES IN HIS HEAD BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: nslu2_pci.c,v 1.1 2006/02/28 20:40:33 scw Exp $");
/*
* Linksys NSLU2 PCI support.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <arm/xscale/ixp425reg.h>
#include <arm/xscale/ixp425var.h>
#include <dev/pci/pcivar.h>
#include <evbarm/nslu2/nslu2reg.h>
static int
nslu2_pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
{
KASSERT(pa->pa_bus == 0 && pa->pa_device == 1);
switch (pa->pa_function) {
case 0:
*ihp = PCI_INT_A;
break;
case 1:
*ihp = PCI_INT_B;
break;
case 2:
*ihp = PCI_INT_C;
break;
default:
return (1);
}
return (0);
}
static const char *
nslu2_pci_intr_string(void *v, pci_intr_handle_t ih)
{
switch (ih) {
case PCI_INT_A:
return ("INTA");
case PCI_INT_B:
return ("INTB");
case PCI_INT_C:
return ("INTC");
}
return (NULL);
}
static const struct evcnt *
nslu2_pci_intr_evcnt(void *v, pci_intr_handle_t ih)
{
return (NULL);
}
static void *
nslu2_pci_intr_establish(void *v, pci_intr_handle_t ih, int ipl,
int (*func)(void *), void *arg)
{
return (ixp425_intr_establish(ih, ipl, func, arg));
}
static void
nslu2_pci_intr_disestablish(void *v, void *cookie)
{
ixp425_intr_disestablish(cookie);
}
void
ixp425_md_pci_conf_interrupt(pci_chipset_tag_t pc, int bus, int dev, int pin,
int swiz, int *ilinep)
{
KASSERT(bus == 0 && dev == 1);
*ilinep = ((swiz + pin - 1) & 3);
}
void
ixp425_md_pci_init(struct ixp425_softc *sc)
{
pci_chipset_tag_t pc = &sc->ia_pci_chipset;
u_int32_t reg;
pc->pc_intr_v = sc;
pc->pc_intr_map = nslu2_pci_intr_map;
pc->pc_intr_string = nslu2_pci_intr_string;
pc->pc_intr_evcnt = nslu2_pci_intr_evcnt;
pc->pc_intr_establish = nslu2_pci_intr_establish;
pc->pc_intr_disestablish = nslu2_pci_intr_disestablish;
/* PCI Reset Assert */
reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPOUTR);
reg &= ~(1u << GPIO_PCI_RESET);
GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPOUTR, reg);
/* PCI Clock Disable */
reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPCLKR);
reg &= ~GPCLKR_MUX14;
GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPCLKR, reg);
/*
* Set GPIO Direction
* Output: PCI_CLK, PCI_RESET
* Input: PCI_INTA, PCI_INTB, PCI_INTC
*/
reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPOER);
reg &= ~((1u << GPIO_PCI_CLK) | (1u << GPIO_PCI_RESET));
reg |= (1u << GPIO_PCI_INTA) | (1u << GPIO_PCI_INTB) |
(1u << GPIO_PCI_INTC);
GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPOER, reg);
/*
* Set GPIO interrupt type
* PCI_INT_A, PCI_INTB, PCI_INT_C: Active Low
*/
reg = GPIO_CONF_READ_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTA));
reg &= ~GPIO_TYPE(GPIO_PCI_INTA, GPIO_TYPE_MASK);
reg |= GPIO_TYPE(GPIO_PCI_INTA, GPIO_TYPE_ACT_LOW);
GPIO_CONF_WRITE_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTA), reg);
reg = GPIO_CONF_READ_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTB));
reg &= ~GPIO_TYPE(GPIO_PCI_INTB, GPIO_TYPE_MASK);
reg |= GPIO_TYPE(GPIO_PCI_INTB, GPIO_TYPE_ACT_LOW);
GPIO_CONF_WRITE_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTB), reg);
reg = GPIO_CONF_READ_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTC));
reg &= ~GPIO_TYPE(GPIO_PCI_INTC, GPIO_TYPE_MASK);
reg |= GPIO_TYPE(GPIO_PCI_INTC, GPIO_TYPE_ACT_LOW);
GPIO_CONF_WRITE_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTC), reg);
/* Clear ISR */
GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPISR, (1u << GPIO_PCI_INTA) |
(1u << GPIO_PCI_INTB) | (1u << GPIO_PCI_INTC));
/* Wait 1ms to satisfy "minimum reset assertion time" of the PCI spec */
DELAY(1000);
reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPCLKR);
reg |= (0xf << GPCLKR_CLK0DC_SHIFT) | (0xf << GPCLKR_CLK0TC_SHIFT);
GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPCLKR, reg);
/* PCI Clock Enable */
reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPCLKR);
reg |= GPCLKR_MUX14;
GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPCLKR, reg);
/*
* Wait 100us to satisfy "minimum reset assertion time from clock stable
* requirement of the PCI spec
*/
DELAY(100);
/* PCI Reset deassert */
reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPOUTR);
reg |= 1u << GPIO_PCI_RESET;
GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPOUTR, reg);
/*
* AHB->PCI address translation
* PCI Memory Map allocation in 0x48000000 (64MB)
* see. IXP425_PCI_MEM_HWBASE
*/
PCI_CSR_WRITE_4(sc, PCI_PCIMEMBASE, 0x48494a4b);
/*
* PCI->AHB address translation
* begin at the physical memory start + OFFSET
*/
#define AHB_OFFSET 0x10000000UL
reg = (AHB_OFFSET + 0x00000000) >> 0;
reg |= (AHB_OFFSET + 0x01000000) >> 8;
reg |= (AHB_OFFSET + 0x02000000) >> 16;
reg |= (AHB_OFFSET + 0x03000000) >> 24;
PCI_CSR_WRITE_4(sc, PCI_AHBMEMBASE, reg);
/* Write Mapping registers PCI Configuration Registers */
/* Base Address 0 - 3 */
ixp425_pci_conf_reg_write(sc, PCI_MAPREG_BAR0, AHB_OFFSET + 0x00000000);
ixp425_pci_conf_reg_write(sc, PCI_MAPREG_BAR1, AHB_OFFSET + 0x01000000);
ixp425_pci_conf_reg_write(sc, PCI_MAPREG_BAR2, AHB_OFFSET + 0x02000000);
ixp425_pci_conf_reg_write(sc, PCI_MAPREG_BAR3, AHB_OFFSET + 0x03000000);
/* Base Address 4 */
ixp425_pci_conf_reg_write(sc, PCI_MAPREG_BAR4, 0xffffffff);
/* Base Address 5 */
ixp425_pci_conf_reg_write(sc, PCI_MAPREG_BAR5, 0x00000000);
/* Assert some PCI errors */
PCI_CSR_WRITE_4(sc, PCI_ISR, ISR_AHBE | ISR_PPE | ISR_PFE | ISR_PSE);
/*
* Set up byte lane swapping between little-endian PCI
* and the big-endian AHB bus
*/
PCI_CSR_WRITE_4(sc, PCI_CSR, CSR_IC | CSR_ABE | CSR_PDS);
/*
* Enable bus mastering and I/O,memory access
*/
ixp425_pci_conf_reg_write(sc, PCI_COMMAND_STATUS_REG,
PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
PCI_COMMAND_MASTER_ENABLE);
/*
* Wait some more to ensure PCI devices have stabilised.
*/
DELAY(50000);
}

View File

@ -0,0 +1,173 @@
/* $NetBSD: nslu2_start.S,v 1.1 2006/02/28 20:40:33 scw Exp $ */
/*
* Copyright (c) 2006 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Ichiro FUKUHARA, Jason R. Thorpe, and Steve C. Woodford.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <machine/asm.h>
#include <arm/armreg.h>
#include <arm/arm32/pte.h>
#include <arm/xscale/ixp425reg.h>
.section .start,"ax",%progbits
.global _C_LABEL(nslu2_start)
_C_LABEL(nslu2_start):
/*
* We will go ahead and disable the MMU here so that we don't
* have to worry about flushing caches, etc.
*
* Note that we may not currently be running VA==PA, which means
* we'll need to leap to the next insn after disabing the MMU.
*/
adr r8, Lunmapped
bic r8, r8, #0xff000000 /* clear upper 8 bits */
orr r8, r8, #0x10000000 /* OR in physical base address */
mrc p15, 0, r2, c1, c0, 0
bic r2, r2, #CPU_CONTROL_MMU_ENABLE
orr r2, r2, #CPU_CONTROL_BEND_ENABLE
mcr p15, 0, r2, c1, c0, 0
nop
nop
nop
mov pc, r8 /* Heave-ho! */
Lunmapped:
/*
* We want to construct a memory map that maps us
* VA==PA (SDRAM at 0x10000000). We create these
* mappings uncached and unbuffered to be safe.
*/
/*
* Step 1: Map the entire address space VA==PA.
*/
adr r0, Ltable
ldr r0, [r0] /* r0 = &l1table */
mov r1, #(L1_TABLE_SIZE / 4) /* 4096 entry */
mov r2, #(L1_S_SIZE) /* 1MB / section */
mov r3, #(L1_S_AP(AP_KRW)) /* kernel read/write */
orr r3, r3, #(L1_TYPE_S) /* L1 entry is section */
1:
str r3, [r0], #0x04
add r3, r3, r2
subs r1, r1, #1
bgt 1b
/*
* Step 2: Map VA 0xc0000000->0xc3ffffff to PA 0x10000000->0x13ffffff.
*/
adr r0, Ltable /* r0 = &l1table */
ldr r0, [r0]
mov r3, #(L1_S_AP(AP_KRW))
orr r3, r3, #(L1_TYPE_S)
orr r3, r3, #0x10000000
add r0, r0, #(0xc00 * 4) /* offset to 0xc00xxxxx */
mov r1, #0x40 /* 64MB */
1:
str r3, [r0], #0x04
add r3, r3, r2
subs r1, r1, #1
bgt 1b
/*
* Step 3: Map VA 0xf0000000->0xf0100000 to PA 0xc8000000->0xc8100000.
*/
adr r0, Ltable /* r0 = &l1table */
ldr r0, [r0]
add r0, r0, #(0xf00 * 4) /* offset to 0xf0000000 */
mov r3, #0xc8000000
add r3, r3, #0x00100000
orr r3, r3, #(L1_S_AP(AP_KRW))
orr r3, r3, #(L1_TYPE_S)
str r3, [r0]
/*
* Step 4: Map VA 0xf0200000->0xf0300000 to PA 0xcc000000->0xcc100000.
*/
adr r0, Ltable /* r0 = &l1table */
ldr r0, [r0]
add r0, r0, #(0xf00 * 4) /* offset to 0xf0200000 */
add r0, r0, #(0x002 * 4)
mov r3, #0xcc000000
add r3, r3, #0x00100000
orr r3, r3, #(L1_S_AP(AP_KRW))
orr r3, r3, #(L1_TYPE_S)
str r3, [r0]
/* OK! Page table is set up. Give it to the CPU. */
adr r0, Ltable
ldr r0, [r0]
mcr p15, 0, r0, c2, c0, 0
/* Flush the old TLBs, just in case. */
mcr p15, 0, r0, c8, c7, 0
/* Set the Domain Access register. Very important! */
mov r0, #1
mcr p15, 0, r0, c3, c0, 0
/* Get ready to jump to the "real" kernel entry point... */
ldr r1, Lstart
mov r1, r1 /* Make sure the load completes! */
/* OK, let's enable the MMU. */
mrc p15, 0, r2, c1, c0, 0
orr r2, r2, #CPU_CONTROL_MMU_ENABLE
orr r2, r2, #CPU_CONTROL_BEND_ENABLE
mcr p15, 0, r2, c1, c0, 0
nop
nop
nop
/* CPWAIT sequence to make sure the MMU is on... */
mrc p15, 0, r2, c2, c0, 0 /* arbitrary read of CP15 */
mov r2, r2 /* force it to complete */
mov pc, r1 /* leap to kernel entry point! */
Ltable:
.word 0x10200000 - 0x4000
Lstart:
.word start

View File

@ -0,0 +1,98 @@
/* $NetBSD: nslu2reg.h,v 1.1 2006/02/28 20:40:33 scw Exp $ */
/*-
* Copyright (c) 2006 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Steve C. Woodford.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _NSLU2REG_H_
#define _NSLU2REG_H_
/*
* PCI GPIO Assignments
*/
#define GPIO_PCI_INTC 9 /* GPIO[9]: PCI INTC [Input] */
#define PCI_INT_C IXP425_INT_GPIO_9
#define GPIO_PCI_INTB 10 /* GPIO[10]: PCI INTB [Input] */
#define PCI_INT_B IXP425_INT_GPIO_10
#define GPIO_PCI_INTA 11 /* GPIO[11]: PCI INTA [Input] */
#define PCI_INT_A IXP425_INT_GPIO_11
#define GPIO_PCI_RESET 13 /* GPIO[13]: PCI Reset [Output] */
#define GPIO_PCI_CLK 14 /* GPIO[14]: 33MHz PCI Clock [Output] */
/*
* I2C Bus GPIO Assignments
*/
#define GPIO_I2C_SCL 6 /* GPIO[6]: I2c Clock [Output] */
#define GPIO_I2C_SCL_BIT (1u << 6)
#define GPIO_I2C_SDA 7 /* GPIO[7]: I2C Data [Tristate] */
#define GPIO_I2C_SDA_BIT (1u << 7)
/*
* LED GPIO Assignments
*/
#define GPIO_LED_STATUS 0 /* GPIO[0]: Status LED [Output, active high] */
#define GPIO_LED_READY 1 /* GPIO[1]: Ready LED [Output, active high] */
#define GPIO_LED_DISK2 2 /* GPIO[2]: Disk 2 LED [Output, active low] */
#define GPIO_LED_DISK1 3 /* GPIO[3]: Disk 1 LED [Output, active low] */
/*
* Button GPIO Assignments
*/
#define GPIO_BUTTON_PWR 5 /* GPIO[5]: Power button [Input, pulsed] */
#define BUTTON_PWR_INT IXP425_INT_GPIO_5
#define GPIO_BUTTON_RST 12 /* GPIO[12]: Reset button [Input, active low] */
#define BUTTON_RST_INT IXP425_INT_GPIO_12
/*
* Miscellaneous GPIO Assignments
*/
#define GPIO_BUZZER 4 /* GPIO[4]: Buzzer [Output] */
#define GPIO_POWER_OFF 8 /* GPIO[8]: Power Off [Output, Active high] */
#define GPIO_EXP_CLOCK 15 /* GPIO[15]: Expandion bus clock [Output] */
/*
* Flash memory
*/
#define NSLU2_FLASH_HWBASE 0x50000000
#define NSLU2_FLASH_VBASE 0xfc000000
#define NSLU2_FLASH_SIZE 0x00800000
/*
* Interesting locations in Flash
*/
#define NSLU2_FLASH_ETHERNET_MAC (NSLU2_FLASH_VBASE + 0x3ffb0)
#endif /* _NSLU2REG_H_ */