Import the initial CPU support for the MIPS RALink RT305x SoC.

This is a MIPS4KC CPU with various embedded peripherals, including
wireless and ethernet support.

This commit includes the platform, UART, ethernet MAC and GPIO support.
The interrupt-driven GPIO code is disabled for now pending GPIO changes
from the submitter.

Submitted by:	Aleksandr Rybalko <ray@dlink.ua>
This commit is contained in:
Adrian Chadd 2011-04-03 14:39:55 +00:00
parent 77ae677e4a
commit f7a5c9d346
21 changed files with 4031 additions and 0 deletions

134
sys/mips/conf/RT305X Normal file
View File

@ -0,0 +1,134 @@
# RT305X -- Kernel configuration file for FreeBSD/mips for Ralink RT305xF systems
#
# For more information on this file, please read the handbook section on
# Kernel Configuration Files:
#
# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
#
# The handbook is also available locally in /usr/share/doc/handbook
# if you've installed the doc distribution, otherwise always see the
# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
# latest information.
#
# An exhaustive list of options and more detailed explanations of the
# device lines is also present in the ../../conf/NOTES and NOTES files.
# If you are in doubt as to the purpose or necessity of a line, check first
# in NOTES.
#
# $FreeBSD$
ident RT305X
machine mips mipsel
makeoptions MIPS_LITTLE_ENDIAN=defined
makeoptions KERNLOADADDR=0x80001000
# Don't build any modules yet.
makeoptions MODULES_OVERRIDE="wlan_xauth wlan_wep wlan_tkip wlan_acl wlan_amrr wlan_ccmp wlan_rssadapt random if_bridge bridgestp msdosfs md ipfw dummynet libalias geom/geom_label ufs usb/uplcom usb/u3g usb/umodem usb/umass usb/ucom cam zlib"
makeoptions RT3052F
include "../rt305x/std.rt305x"
hints "RT305X.hints" #Default places to look for devices.
#makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols
# Debugging for use in -current
#options DEADLKRES #Enable the deadlock resolver
#options INVARIANTS #Enable calls of extra sanity checking
#options INVARIANT_SUPPORT #Extra sanity checks of internal structures, required by INVARIANTS
#options WITNESS #Enable checks to detect deadlocks and cycles
#options WITNESS_SKIPSPIN #Don't run witness on spinlocks for speed
#options DIAGNOSTIC
#options DEBUG_LOCKS
#options DEBUG_VFS_LOCKS
#options GDB
options DDB
options KDB
options SCHED_ULE
#options SCHED_4BSD #4BSD scheduler
#options COMPAT_43
options INET #InterNETworking
options NFSCLIENT #Network Filesystem Client
options NFS_ROOT #NFS usable as /, requires NFSCLIENT
options PSEUDOFS #Pseudo-filesystem framework
#options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions
options BOOTP
#options BOOTP_NFSROOT
options BOOTP_NFSV3
options BOOTP_WIRED_TO=rt0
options BOOTP_COMPAT
options CD9660 # ISO 9660 Filesystem
options ROOTDEVNAME=\"cd9660:/dev/map/rootfs.uncompress\"
options TMPFS # TMP Memory Filesystem
#options FFS #Berkeley Fast Filesystem
#options SOFTUPDATES #Enable FFS soft updates support
#options UFS_ACL #Support for access control lists
#options UFS_DIRHASH #Improve performance on big directories
#options ROOTDEVNAME=\"nfs:10.0.0.1:/mnt/bsd\"
# Options for making kernel less hangry
makeoptions INLINE_LIMIT=1024
options MAXUSERS=3
options MAXFILES=512
options NSFBUFS=256
options SHMALL=128
options MSGBUF_SIZE=65536
# Options for making kernel smallest
options NO_SYSCTL_DESCR # No description string of sysctl
#options NO_FFS_SNAPSHOT # Disable Snapshot supporting
options SCSI_NO_SENSE_STRINGS
options SCSI_NO_OP_STRINGS
options RWLOCK_NOINLINE
options SX_NOINLINE
options NO_SWAPPING
options ZERO_COPY_SOCKETS
options MROUTING # Multicast routing
options IPFIREWALL_DEFAULT_TO_ACCEPT
device random
device loop
# RT3050F, RT3052F have only pseudo PHYs
#device mii
#device miibus
device pty # Pseudo-ttys (telnet etc)
device ether
device bpf # Berkeley packet filter
device vlan
#device lagg
#device if_bridge
device uart
nodevice uart_ns8250
device tun # Packet tunnel.
device wlan
device gpio
device gpioled
device cfi # Detect Flash memmory
device cfid
device nvram2env
device usb
#device dotg # DWC like USB OTG Controller driver
#device u3g
#device umodem
#device uplcom
#device umass
#device da
#device pass
#device scbus
options SCSI_DELAY=1000 # Delay (in ms) before probing SCSI
#options USB_EHCI_BIG_ENDIAN_DESC # handle big-endian byte order
#options USB_DEBUG
#options USB_REQ_DEBUG

136
sys/mips/conf/RT305X.hints Normal file
View File

@ -0,0 +1,136 @@
# $FreeBSD$
# device.hints
hint.obio.0.at="nexus0"
hint.obio.0.maddr=0x10000000
hint.obio.0.msize=0x10000000
hint.nvram.0.sig=0xe5e60a74
hint.nvram.0.base=0x1f030000
hint.nvram.0.maxsize=0x2000
hint.nvram.0.flags=3 # 1 = No check, 2 = Format Generic
hint.nvram.1.sig=0x5a045e94
hint.nvram.1.base=0x1f032000
hint.nvram.1.maxsize=0x4000
hint.nvram.1.flags=3 # 1 = No check, 2 = Format Generic
# on-board Ralink Frame Engine
#hint.rt.0.at="nexus0"
#hint.rt.0.maddr=0x12000000
#hint.rt.0.msize=0x200000
#hint.rt.0.irq=9
hint.rt.0.macaddr="00:18:e7:d5:83:90"
# on-board Ralink 2872 802.11n core
hint.rt2860.0.at="nexus0"
hint.rt2860.0.maddr=0x10180000
hint.rt2860.0.msize=0x40000
hint.rt2860.0.irq=4
# uart0
#hint.uart.0.at="obio0"
#hint.uart.0.maddr=0x10000C00
#hint.uart.0.msize=0x100
#hint.uart.0.irq=12
#hint.uart.0.flags="0x30"
# uart1
#hint.uart.1.at="obio0"
#hint.uart.1.maddr=0x10000500
#hint.uart.1.msize=0x100
#hint.uart.1.irq=5
#hint.uart.1.flags="0x30"
# gpio
# GPIO0 - WPS BTN IN II IO
hint.gpiobutton.0.at="gpiobus0"
hint.gpiobutton.0.pins="0x01"
hint.gpiobutton.0.name="wps"
hint.gpiobutton.0.flags="0x0581"
# GPIO7 - MODE SW AP IN II IO
hint.gpiobutton.1.at="gpiobus0"
hint.gpiobutton.1.pins="0x80"
hint.gpiobutton.1.name="mode_ap"
hint.gpiobutton.1.flags="0x0581"
# GPIO8 - ST LEDRED OUT /* 2pin BiDir RED/BLUE LED */
# GPIO9 - ST LEDBLUE OUT
hint.gpioled.0.at="gpiobus0"
hint.gpioled.0.pins="0x100"
hint.gpioled.0.name="status_red"
hint.gpioled.0.flags="0x0002"
hint.gpioled.1.at="gpiobus0"
hint.gpioled.1.pins="0x200"
#hint.gpioled.1.name="status_blue"
hint.gpioled.1.name="status"
hint.gpioled.1.flags="0x0002"
# GPIO10 - RST BTN IN II IO
hint.gpiobutton.2.at="gpiobus0"
hint.gpiobutton.2.pins="0x400"
hint.gpiobutton.2.name="reset"
hint.gpiobutton.2.flags="0x0581"
# GPIO11 - MODE SW CL IN II IO
hint.gpiobutton.3.at="gpiobus0"
hint.gpiobutton.3.pins="0x800"
hint.gpiobutton.3.name="mode_wlan_client"
hint.gpiobutton.3.flags="0x0581"
# GPIO14 - WPS LED OUT II IO
hint.gpioled.2.at="gpiobus0"
hint.gpioled.2.pins="0x4000"
hint.gpioled.2.name="wps"
hint.gpioled.2.flags="0x0182"
#0x00000000-0x00030000 : "Bootloader"
#0x00030000-0x00040000 : "Factory"
#0x00040000-0x00070000 : "Config"
#0x00070000-0x000b0000 : "Language"
#0x000b0000-0x001a0000 : "Kernel"
#0x001a0000-0x01000000 : "RootFS"
hint.map.0.at="cfid0"
hint.map.0.start=0x00000000
hint.map.0.end=0x00030000
hint.map.0.name="bootloader"
hint.map.0.readonly=1
hint.map.1.at="cfid0"
hint.map.1.start=0x00030000
hint.map.1.end=0x00040000
hint.map.1.name="factory"
hint.map.2.at="cfid0"
hint.map.2.start=0x00040000
hint.map.2.end=0x00800000
hint.map.2.name="upgrade"
hint.map.3.at="cfid0"
hint.map.3.start=0x00040000
hint.map.3.end=0x00050000
hint.map.3.name="config"
hint.map.4.at="cfid0"
hint.map.4.start=0x00000000
hint.map.4.end=0x00000000
hint.map.4.name="language"
hint.map.5.at="cfid0"
hint.map.5.start=0x00050000
hint.map.5.end=0x00150000
hint.map.5.name="kernel"
hint.map.6.at="cfid0"
hint.map.6.start=0x00150000
hint.map.6.end=0x00800000
hint.map.6.name="rootfs"
hint.rt.0.phymask=0x1f
hint.rt.0.media=100
hint.rt.0.fduplex=1

View File

@ -0,0 +1,13 @@
# $FreeBSD$
# RT305X on-board devices
mips/rt305x/rt305x_machdep.c standard
mips/rt305x/obio.c standard
mips/rt305x/rt305x_sysctl.c standard
mips/rt305x/rt305x_ic.c standard
mips/rt305x/rt305x_gpio.c optional gpio
mips/rt305x/uart_bus_rt305x.c optional uart
mips/rt305x/uart_cpu_rt305x.c optional uart
mips/rt305x/uart_dev_rt305x.c optional uart
mips/mips/intr_machdep.c standard
mips/mips/tick.c standard

627
sys/mips/rt305x/obio.c Normal file
View File

@ -0,0 +1,627 @@
/* $NetBSD: obio.c,v 1.11 2003/07/15 00:25:05 lukem Exp $ */
/*-
* Copyright (c) 2001, 2002, 2003 Wasabi Systems, Inc.
* All rights reserved.
*
* Written by Jason R. Thorpe for Wasabi Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/interrupt.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/rman.h>
#include <sys/malloc.h>
#include <machine/bus.h>
#include <mips/rt305x/rt305xreg.h>
#include <mips/rt305x/obiovar.h>
#include <mips/rt305x/rt305x_icvar.h>
/* MIPS HW interrupts of IRQ/FIQ respectively */
#define RT305X_INTR 0
#define RT305X_FAST_INTR 1
/* Interrupt levels */
#define INTR_IRQ 0
#define INTR_FIQ 1
int irq_priorities[NIRQS] = {
INTR_IRQ, /* SYSCTL */
INTR_FIQ, /* TIMER0 */
INTR_FIQ, /* WDTIMER */
INTR_IRQ, /* Illegal Access */
INTR_IRQ, /* PCM */
INTR_IRQ, /* UART */
INTR_IRQ, /* GPIO */
INTR_FIQ, /* GDMA */
INTR_IRQ, /* NAND */
INTR_IRQ, /* Perfomance Counter */
INTR_IRQ, /* I2S */
INTR_IRQ, /* unknown */
INTR_IRQ, /* UARTLITE */
INTR_IRQ, /* unknown */
INTR_IRQ, /* unknown */
INTR_IRQ, /* unknown */
INTR_IRQ, /* unknown */
INTR_IRQ, /* EtherNet Switch */
INTR_FIQ, /* OTG */
INTR_IRQ, /* unknown */
INTR_IRQ, /* unknown */
INTR_IRQ, /* unknown */
INTR_IRQ, /* unknown */
INTR_IRQ, /* unknown */
INTR_IRQ, /* unknown */
INTR_IRQ, /* unknown */
INTR_IRQ, /* unknown */
INTR_IRQ, /* unknown */
INTR_IRQ, /* unknown */
INTR_IRQ, /* unknown */
INTR_IRQ, /* unknown */
INTR_IRQ, /* unknown */
};
#define REG_READ(o) *((volatile uint32_t *)MIPS_PHYS_TO_KSEG1(INTCTL_BASE + (o)))
#define REG_WRITE(o,v) (REG_READ(o)) = (v)
static int obio_activate_resource(device_t, device_t, int, int,
struct resource *);
static device_t obio_add_child(device_t, u_int, const char *, int);
static struct resource *
obio_alloc_resource(device_t, device_t, int, int *, u_long,
u_long, u_long, u_int);
static int obio_attach(device_t);
static int obio_deactivate_resource(device_t, device_t, int, int,
struct resource *);
static struct resource_list *
obio_get_resource_list(device_t, device_t);
static void obio_add_res_child(device_t, const char *, int, long, int, int);
static void obio_hinted_child(device_t, const char *, int);
static int obio_intr(void *);
static int obio_probe(device_t);
static int obio_release_resource(device_t, device_t, int, int,
struct resource *);
static int obio_setup_intr(device_t, device_t, struct resource *, int,
driver_filter_t *, driver_intr_t *, void *, void **);
static int obio_teardown_intr(device_t, device_t, struct resource *,
void *);
static void
obio_mask_irq(void *source)
{
int irq;
uint32_t irqmask;
irq = (int)source;
irqmask = 1 << irq;
/* disable IRQ */
rt305x_ic_set(IC_INT_DIS, irqmask);
}
static void
obio_unmask_irq(void *source)
{
int irq;
uint32_t irqmask;
irq = (int)source;
irqmask = 1 << irq;
/* enable IRQ */
rt305x_ic_set(IC_INT_ENA, irqmask);
}
static int
obio_probe(device_t dev)
{
return (0);
}
static int
obio_attach(device_t dev)
{
struct obio_softc *sc = device_get_softc(dev);
int rid;
sc->oba_mem_rman.rm_type = RMAN_ARRAY;
sc->oba_mem_rman.rm_descr = "OBIO memory";
if (rman_init(&sc->oba_mem_rman) != 0 ||
rman_manage_region(&sc->oba_mem_rman, OBIO_MEM_START,
OBIO_MEM_END) != 0)
panic("obio_attach: failed to set up I/O rman");
sc->oba_irq_rman.rm_type = RMAN_ARRAY;
sc->oba_irq_rman.rm_descr = "OBIO IRQ";
if (rman_init(&sc->oba_irq_rman) != 0 ||
rman_manage_region(&sc->oba_irq_rman, 0, NIRQS-1) != 0)
panic("obio_attach: failed to set up IRQ rman");
/* Hook up our interrupt handler. */
if ((sc->sc_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
RT305X_INTR, RT305X_INTR, 1,
RF_SHAREABLE | RF_ACTIVE)) == NULL) {
device_printf(dev, "unable to allocate IRQ resource\n");
return (ENXIO);
}
if ((bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_MISC, obio_intr, NULL,
sc, &sc->sc_ih))) {
device_printf(dev,
"WARNING: unable to register interrupt handler\n");
return (ENXIO);
}
/* Hook up our FAST interrupt handler. */
if ((sc->sc_fast_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
RT305X_FAST_INTR, RT305X_FAST_INTR, 1,
RF_SHAREABLE | RF_ACTIVE)) == NULL) {
device_printf(dev, "unable to allocate IRQ resource\n");
return (ENXIO);
}
if ((bus_setup_intr(dev, sc->sc_fast_irq, INTR_TYPE_MISC, obio_intr,
NULL, sc, &sc->sc_fast_ih))) {
device_printf(dev,
"WARNING: unable to register interrupt handler\n");
return (ENXIO);
}
/* disable all interrupts */
rt305x_ic_set(IC_INT_DIS, IC_INT_MASK|IC_LINE_GLOBAL);
bus_generic_probe(dev);
obio_add_res_child(dev, "rt305x_sysctl", 0,
SYSCTL_BASE, (SYSCTL_END - SYSCTL_BASE + 1),
IC_SYSCTL);
obio_add_res_child(dev, "rt305x_ic", 0,
INTCTL_BASE, (INTCTL_END - INTCTL_BASE + 1),
-1);
#ifdef notyet
obio_add_res_child(dev, "timer",0,
TIMER_BASE, (TIMER_END - TIMER_BASE + 1),
IC_TIMER0);
obio_add_res_child(dev, "rt305x_memc", 0,
MEMCTRL_BASE, (MEMCTRL_END - MEMCTRL_BASE + 1),
-1);
obio_add_res_child(dev, "pcm", 0,
PCM_BASE, (PCM_END - PCM_BASE + 1),
IC_PCM);
obio_add_res_child(dev, "uart", 0,
UART_BASE, (UART_END - UART_BASE + 1),
IC_UART);
#endif
obio_add_res_child(dev, "gpio", 0,
PIO_BASE, (PIO_END - PIO_BASE + 1),
IC_PIO);
#ifdef notyet
obio_add_res_child(dev, "rt305x_dma", 0,
GDMA_BASE, (GDMA_END - GDMA_BASE + 1),
IC_DMA);
obio_add_res_child(dev, "rt305x_nandc", 0,
NANDFC_BASE, (NANDFC_END - NANDFC_BASE + 1),
IC_NAND);
obio_add_res_child(dev, "i2c", 0,
I2C_BASE, (I2C_END - I2C_BASE + 1),
-1);
obio_add_res_child(dev, "i2s", 0,
I2S_BASE, (I2S_END - I2S_BASE + 1),
IC_I2S);
obio_add_res_child(dev, "spi", 0,
SPI_BASE, (SPI_END - SPI_BASE + 1),
-1);
#endif
obio_add_res_child(dev, "uart", 1,
UARTLITE_BASE, (UARTLITE_END - UARTLITE_BASE + 1),
IC_UARTLITE);
obio_add_res_child(dev, "cfi", 0,
FLASH_BASE, (FLASH_END - FLASH_BASE + 1),
-1);
obio_add_res_child(dev, "dotg", 0,
USB_OTG_BASE, (USB_OTG_END - USB_OTG_BASE + 1),
IC_OTG);
obio_add_res_child(dev, "switch", 0,
ETHSW_BASE, (ETHSW_END - ETHSW_BASE + 1),
IC_ETHSW);
bus_enumerate_hinted_children(dev);
bus_generic_attach(dev);
/* enable IC */
rt305x_ic_set(IC_INT_ENA, IC_LINE_GLOBAL);
return (0);
}
static struct resource *
obio_alloc_resource(device_t bus, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
{
struct obio_softc *sc = device_get_softc(bus);
struct obio_ivar *ivar = device_get_ivars(child);
struct resource *rv;
struct resource_list_entry *rle;
struct rman *rm;
int isdefault, needactivate, passthrough;
isdefault = (start == 0UL && end == ~0UL && count == 1);
needactivate = flags & RF_ACTIVE;
passthrough = (device_get_parent(child) != bus);
rle = NULL;
if (passthrough)
return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child, type,
rid, start, end, count, flags));
/*
* If this is an allocation of the "default" range for a given RID,
* and we know what the resources for this device are (ie. they aren't
* maintained by a child bus), then work out the start/end values.
*/
if (isdefault) {
rle = resource_list_find(&ivar->resources, type, *rid);
if (rle == NULL)
return (NULL);
if (rle->res != NULL) {
panic("%s: resource entry is busy", __func__);
}
start = rle->start;
end = rle->end;
count = rle->count;
}
switch (type) {
case SYS_RES_IRQ:
rm = &sc->oba_irq_rman;
break;
case SYS_RES_MEMORY:
rm = &sc->oba_mem_rman;
break;
default:
printf("%s: unknown resource type %d\n", __func__, type);
return (0);
}
rv = rman_reserve_resource(rm, start, end, count, flags, child);
if (rv == 0) {
printf("%s: could not reserve resource\n", __func__);
return (0);
}
rman_set_rid(rv, *rid);
if (needactivate) {
if (bus_activate_resource(child, type, *rid, rv)) {
printf("%s: could not activate resource\n", __func__);
rman_release_resource(rv);
return (0);
}
}
return (rv);
}
static int
obio_activate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
/*
* If this is a memory resource, track the direct mapping
* in the uncached MIPS KSEG1 segment.
*/
if (type == SYS_RES_MEMORY) {
void *vaddr;
vaddr = (void *)MIPS_PHYS_TO_KSEG1((intptr_t)rman_get_start(r));
rman_set_virtual(r, vaddr);
rman_set_bustag(r, mips_bus_space_generic);
rman_set_bushandle(r, (bus_space_handle_t)vaddr);
}
return (rman_activate_resource(r));
}
static int
obio_deactivate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
return (rman_deactivate_resource(r));
}
static int
obio_release_resource(device_t dev, device_t child, int type,
int rid, struct resource *r)
{
struct resource_list *rl;
struct resource_list_entry *rle;
rl = obio_get_resource_list(dev, child);
if (rl == NULL)
return (EINVAL);
rle = resource_list_find(rl, type, rid);
if (rle == NULL)
return (EINVAL);
rman_release_resource(r);
rle->res = NULL;
return (0);
}
static int
obio_setup_intr(device_t dev, device_t child, struct resource *ires,
int flags, driver_filter_t *filt, driver_intr_t *handler,
void *arg, void **cookiep)
{
struct obio_softc *sc = device_get_softc(dev);
struct intr_event *event;
int irq, error, priority;
uint32_t irqmask;
irq = rman_get_start(ires);
if (irq >= NIRQS)
panic("%s: bad irq %d", __func__, irq);
event = sc->sc_eventstab[irq];
if (event == NULL) {
error = intr_event_create(&event, (void *)irq, 0, irq,
obio_mask_irq, obio_unmask_irq,
NULL, NULL, "obio intr%d:", irq);
sc->sc_eventstab[irq] = event;
}
else
panic("obio: Can't share IRQs");
intr_event_add_handler(event, device_get_nameunit(child), filt,
handler, arg, intr_priority(flags), flags, cookiep);
irqmask = 1 << irq;
priority = irq_priorities[irq];
if (priority == INTR_FIQ)
rt305x_ic_set(IC_INTTYPE, rt305x_ic_get(IC_INTTYPE) | irqmask);
else
rt305x_ic_set(IC_INTTYPE, rt305x_ic_get(IC_INTTYPE) & ~irqmask);
/* enable */
obio_unmask_irq((void*)irq);
return (0);
}
static int
obio_teardown_intr(device_t dev, device_t child, struct resource *ires,
void *cookie)
{
struct obio_softc *sc = device_get_softc(dev);
int irq, result, priority;
uint32_t irqmask;
irq = rman_get_start(ires);
if (irq >= NIRQS)
panic("%s: bad irq %d", __func__, irq);
if (sc->sc_eventstab[irq] == NULL)
panic("Trying to teardown unoccupied IRQ");
irqmask = (1 << irq);
priority = irq_priorities[irq];
if (priority == INTR_FIQ)
rt305x_ic_set(IC_INTTYPE, rt305x_ic_get(IC_INTTYPE) & ~irqmask);
else
rt305x_ic_set(IC_INTTYPE, rt305x_ic_get(IC_INTTYPE) | irqmask);
/* disable */
obio_mask_irq((void*)irq);
result = intr_event_remove_handler(cookie);
if (!result) {
sc->sc_eventstab[irq] = NULL;
}
return (result);
}
static int
obio_intr(void *arg)
{
struct obio_softc *sc = arg;
struct intr_event *event;
uint32_t irqstat;
int irq;
irqstat = rt305x_ic_get(IC_IRQ0STAT);
irqstat |= rt305x_ic_get(IC_IRQ1STAT);
irq = 0;
while (irqstat != 0) {
if ((irqstat & 1) == 1) {
event = sc->sc_eventstab[irq];
if (!event || TAILQ_EMPTY(&event->ie_handlers))
continue;
/* TODO: pass frame as an argument*/
/* TODO: log stray interrupt */
intr_event_handle(event, NULL);
}
irq++;
irqstat >>= 1;
}
return (FILTER_HANDLED);
}
static void
obio_add_res_child(device_t bus, const char *dname, int dunit,
long maddr, int msize, int irq)
{
device_t child;
int result;
child = BUS_ADD_CHILD(bus, 0, dname, dunit);
result = bus_set_resource(child, SYS_RES_MEMORY, 0,
maddr, msize);
if (result != 0)
device_printf(bus, "warning: bus_set_resource() failed\n");
if (irq != -1) {
result = bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1);
if (result != 0)
device_printf(bus,
"warning: bus_set_resource() failed\n");
}
}
static void
obio_hinted_child(device_t bus, const char *dname, int dunit)
{
long maddr;
int msize;
int irq;
/*
* Set hard-wired resources for hinted child using
* specific RIDs.
*/
resource_long_value(dname, dunit, "maddr", &maddr);
resource_int_value(dname, dunit, "msize", &msize);
if (resource_int_value(dname, dunit, "irq", &irq) == 0) irq = -1;
obio_add_res_child(bus, dname, dunit, maddr, msize, irq);
}
static device_t
obio_add_child(device_t bus, u_int order, const char *name, int unit)
{
device_t child;
struct obio_ivar *ivar;
ivar = malloc(sizeof(struct obio_ivar), M_DEVBUF, M_WAITOK | M_ZERO);
if (ivar == NULL) {
printf("Failed to allocate ivar\n");
return (0);
}
resource_list_init(&ivar->resources);
child = device_add_child_ordered(bus, order, name, unit);
if (child == NULL) {
printf("Can't add child %s%d ordered\n", name, unit);
return (0);
}
device_set_ivars(child, ivar);
return (child);
}
/*
* Helper routine for bus_generic_rl_get_resource/bus_generic_rl_set_resource
* Provides pointer to resource_list for these routines
*/
static struct resource_list *
obio_get_resource_list(device_t dev, device_t child)
{
struct obio_ivar *ivar;
ivar = device_get_ivars(child);
return (&(ivar->resources));
}
static int
obio_print_all_resources(device_t dev)
{
struct obio_ivar *ivar = device_get_ivars(dev);
struct resource_list *rl = &ivar->resources;
int retval = 0;
if (STAILQ_FIRST(rl))
retval += printf(" at");
retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
return (retval);
}
static int
obio_print_child(device_t bus, device_t child)
{
int retval = 0;
retval += bus_print_child_header(bus, child);
retval += obio_print_all_resources(child);
if (device_get_flags(child))
retval += printf(" flags %#x", device_get_flags(child));
retval += printf(" on %s\n", device_get_nameunit(bus));
return (retval);
}
static device_method_t obio_methods[] = {
DEVMETHOD(bus_activate_resource, obio_activate_resource),
DEVMETHOD(bus_add_child, obio_add_child),
DEVMETHOD(bus_alloc_resource, obio_alloc_resource),
DEVMETHOD(bus_deactivate_resource, obio_deactivate_resource),
DEVMETHOD(bus_get_resource_list, obio_get_resource_list),
DEVMETHOD(bus_hinted_child, obio_hinted_child),
DEVMETHOD(bus_print_child, obio_print_child),
DEVMETHOD(bus_release_resource, obio_release_resource),
DEVMETHOD(bus_setup_intr, obio_setup_intr),
DEVMETHOD(bus_teardown_intr, obio_teardown_intr),
DEVMETHOD(device_attach, obio_attach),
DEVMETHOD(device_probe, obio_probe),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
{0, 0},
};
static driver_t obio_driver = {
"obio",
obio_methods,
sizeof(struct obio_softc),
};
static devclass_t obio_devclass;
DRIVER_MODULE(obio, nexus, obio_driver, obio_devclass, 0, 0);

58
sys/mips/rt305x/obiovar.h Normal file
View File

@ -0,0 +1,58 @@
/* $NetBSD: obiovar.h,v 1.4 2003/06/16 17:40:53 thorpej Exp $ */
/*-
* Copyright (c) 2002, 2003 Wasabi Systems, Inc.
* All rights reserved.
*
* Written by Jason R. Thorpe for Wasabi Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*
*/
#ifndef _RT305X_OBIOVAR_H_
#define _RT305X_OBIOVAR_H_
#include <sys/rman.h>
/* Number of IRQs */
#define NIRQS 32
struct obio_softc {
struct rman oba_mem_rman;
struct rman oba_irq_rman;
struct rman oba_gpio_rman;
struct intr_event *sc_eventstab[NIRQS]; /* IRQ events structs */
struct resource *sc_irq; /* IRQ resource */
void *sc_ih; /* interrupt cookie */
struct resource *sc_fast_irq; /* IRQ resource */
void *sc_fast_ih; /* interrupt cookie */
};
struct obio_ivar {
struct resource_list resources;
};
#endif /* _RT305X_OBIOVAR_H_ */

View File

@ -0,0 +1,247 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*-
* Copyright (c) 2010,2011 Aleksandr Rybalko. All rights reserved.
* Copyright (c) 2007-2008 Hans Petter Selasky. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 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.
*/
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/types.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/module.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/condvar.h>
#include <sys/sysctl.h>
#include <sys/sx.h>
#include <sys/unistd.h>
#include <sys/callout.h>
#include <sys/malloc.h>
#include <sys/priv.h>
#include <sys/rman.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usb_core.h>
#include <dev/usb/usb_busdma.h>
#include <dev/usb/usb_process.h>
#include <dev/usb/usb_util.h>
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
#include <dev/usb/controller/dotg.h>
#include <mips/rt305x/rt305xreg.h>
#include <mips/rt305x/rt305x_sysctlvar.h>
#define MEM_RID 0
static device_probe_t dotg_obio_probe;
static device_attach_t dotg_obio_attach;
static device_detach_t dotg_obio_detach;
static device_shutdown_t dotg_obio_shutdown;
struct dotg_obio_softc {
struct dotg_softc sc_dci; /* must be first */
};
static int
dotg_obio_probe(device_t dev)
{
device_set_desc(dev, "DWC like USB OTG controller");
return (0);
}
static int
dotg_obio_attach(device_t dev)
{
struct dotg_obio_softc *sc = device_get_softc(dev);
int err;
/* setup controller interface softc */
/* initialise some bus fields */
sc->sc_dci.sc_dev = dev;
sc->sc_dci.sc_bus.parent = dev;
sc->sc_dci.sc_bus.devices = sc->sc_dci.sc_devices;
sc->sc_dci.sc_bus.devices_max = DOTG_MAX_DEVICES;
/* get all DMA memory */
if (usb_bus_mem_alloc_all(&sc->sc_dci.sc_bus,
USB_GET_DMA_TAG(dev), NULL)) {
printf("No mem\n");
return (ENOMEM);
}
sc->sc_dci.sc_mem_rid = 0;
sc->sc_dci.sc_mem_res =
bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_dci.sc_irq_rid,
RF_ACTIVE);
if (!(sc->sc_dci.sc_mem_res)) {
printf("Can`t alloc MEM\n");
goto error;
}
sc->sc_dci.sc_bst = rman_get_bustag(sc->sc_dci.sc_mem_res);
sc->sc_dci.sc_bsh = rman_get_bushandle(sc->sc_dci.sc_mem_res);
sc->sc_dci.sc_irq_rid = 0;
sc->sc_dci.sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
&sc->sc_dci.sc_irq_rid, RF_SHAREABLE| RF_ACTIVE);
if (!(sc->sc_dci.sc_irq_res)) {
printf("Can`t alloc IRQ\n");
goto error;
}
sc->sc_dci.sc_bus.bdev = device_add_child(dev, "usbus", -1);
if (!(sc->sc_dci.sc_bus.bdev)) {
printf("Can`t add usbus\n");
goto error;
}
device_set_ivars(sc->sc_dci.sc_bus.bdev, &sc->sc_dci.sc_bus);
#if (__FreeBSD_version >= 700031)
err = bus_setup_intr(dev, sc->sc_dci.sc_irq_res,
INTR_TYPE_BIO | INTR_MPSAFE, NULL, (driver_intr_t *)dotg_interrupt,
sc, &sc->sc_dci.sc_intr_hdl);
#else
err = bus_setup_intr(dev, sc->sc_dci.sc_irq_res,
INTR_TYPE_BIO | INTR_MPSAFE, (driver_intr_t *)dotg_interrupt,
sc, &sc->sc_dci.sc_intr_hdl);
#endif
if (err) {
sc->sc_dci.sc_intr_hdl = NULL;
printf("Can`t set IRQ handle\n");
goto error;
}
/* Run clock for OTG core */
rt305x_sysctl_set(SYSCTL_CLKCFG1, rt305x_sysctl_get(SYSCTL_CLKCFG1) |
SYSCTL_CLKCFG1_OTG_CLK_EN);
rt305x_sysctl_set(SYSCTL_RSTCTRL, SYSCTL_RSTCTRL_OTG);
DELAY(100);
err = dotg_init(&sc->sc_dci);
if (err) printf("dotg_init fail\n");
if (!err) {
err = device_probe_and_attach(sc->sc_dci.sc_bus.bdev);
if (err) printf("device_probe_and_attach fail\n");
}
if (err) {
goto error;
}
return (0);
error:
dotg_obio_detach(dev);
return (ENXIO);
}
static int
dotg_obio_detach(device_t dev)
{
struct dotg_obio_softc *sc = device_get_softc(dev);
device_t bdev;
int err;
if (sc->sc_dci.sc_bus.bdev) {
bdev = sc->sc_dci.sc_bus.bdev;
device_detach(bdev);
device_delete_child(dev, bdev);
}
/* during module unload there are lots of children leftover */
device_delete_all_children(dev);
if (sc->sc_dci.sc_irq_res && sc->sc_dci.sc_intr_hdl) {
/*
* only call dotg_obio_uninit() after dotg_obio_init()
*/
dotg_uninit(&sc->sc_dci);
/* Stop OTG clock */
rt305x_sysctl_set(SYSCTL_CLKCFG1,
rt305x_sysctl_get(SYSCTL_CLKCFG1) &
~SYSCTL_CLKCFG1_OTG_CLK_EN);
err = bus_teardown_intr(dev, sc->sc_dci.sc_irq_res,
sc->sc_dci.sc_intr_hdl);
sc->sc_dci.sc_intr_hdl = NULL;
}
if (sc->sc_dci.sc_irq_res) {
bus_release_resource(dev, SYS_RES_IRQ, 0,
sc->sc_dci.sc_irq_res);
sc->sc_dci.sc_irq_res = NULL;
}
if (sc->sc_dci.sc_mem_res) {
bus_release_resource(dev, SYS_RES_MEMORY, 0,
sc->sc_dci.sc_mem_res);
sc->sc_dci.sc_mem_res = NULL;
}
usb_bus_mem_free_all(&sc->sc_dci.sc_bus, NULL);
return (0);
}
static int
dotg_obio_shutdown(device_t dev)
{
struct dotg_obio_softc *sc = device_get_softc(dev);
int err;
err = bus_generic_shutdown(dev);
if (err)
return (err);
dotg_uninit(&sc->sc_dci);
return (0);
}
static device_method_t dotg_obio_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, dotg_obio_probe),
DEVMETHOD(device_attach, dotg_obio_attach),
DEVMETHOD(device_detach, dotg_obio_detach),
DEVMETHOD(device_shutdown, dotg_obio_shutdown),
/* Bus interface */
DEVMETHOD(bus_print_child, bus_generic_print_child),
{0, 0}
};
static driver_t dotg_obio_driver = {
"dotg",
dotg_obio_methods,
sizeof(struct dotg_obio_softc),
};
static devclass_t dotg_obio_devclass;
DRIVER_MODULE(dotg, obio, dotg_obio_driver, dotg_obio_devclass, 0, 0);

View File

@ -0,0 +1,619 @@
/*-
* Copyright (c) 2010-2011, Aleksandr Rybalko <ray@ddteam.net>
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
* Copyright (c) 2009, Luiz Otavio O Souza.
* 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 unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 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.
*/
/*
* GPIO driver for RT305X SoC.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/rman.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/gpio.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <mips/rt305x/rt305xreg.h>
#include <mips/rt305x/rt305x_gpio.h>
#include <mips/rt305x/rt305x_gpiovar.h>
#include <mips/rt305x/rt305x_sysctlvar.h>
#include "gpio_if.h"
#ifdef notyet
#define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_INVIN | \
GPIO_PIN_INVOUT | GPIO_PIN_REPORT )
#else
#define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_INVIN | \
GPIO_PIN_INVOUT )
#endif
/*
* Helpers
*/
static void rt305x_gpio_pin_configure(struct rt305x_gpio_softc *sc,
struct gpio_pin *pin, uint32_t flags);
/*
* Driver stuff
*/
static int rt305x_gpio_probe(device_t dev);
static int rt305x_gpio_attach(device_t dev);
static int rt305x_gpio_detach(device_t dev);
static int rt305x_gpio_intr(void *arg);
int rt305x_get_int_mask (device_t);
void rt305x_set_int_mask (device_t, uint32_t);
int rt305x_get_int_status(device_t);
void rt305x_set_int_status(device_t, uint32_t);
/*
* GPIO interface
*/
static int rt305x_gpio_pin_max(device_t dev, int *maxpin);
static int rt305x_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps);
static int rt305x_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t
*flags);
static int rt305x_gpio_pin_getname(device_t dev, uint32_t pin, char *name);
static int rt305x_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags);
static int rt305x_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value);
static int rt305x_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val);
static int rt305x_gpio_pin_toggle(device_t dev, uint32_t pin);
static void
rt305x_gpio_pin_configure(struct rt305x_gpio_softc *sc, struct gpio_pin *pin,
unsigned int flags)
{
GPIO_LOCK(sc);
/*
* Manage input/output
*/
if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) {
pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT);
if (flags & GPIO_PIN_OUTPUT) {
pin->gp_flags |= GPIO_PIN_OUTPUT;
GPIO_BIT_SET(sc, pin->gp_pin, DIR);
}
else {
pin->gp_flags |= GPIO_PIN_INPUT;
GPIO_BIT_CLR(sc, pin->gp_pin, DIR);
}
}
if (flags & GPIO_PIN_INVOUT) {
pin->gp_flags |= GPIO_PIN_INVOUT;
GPIO_BIT_SET(sc, pin->gp_pin, POL);
}
else {
pin->gp_flags &= ~GPIO_PIN_INVOUT;
GPIO_BIT_CLR(sc, pin->gp_pin, POL);
}
if (flags & GPIO_PIN_INVIN) {
pin->gp_flags |= GPIO_PIN_INVIN;
GPIO_BIT_SET(sc, pin->gp_pin, POL);
}
else {
pin->gp_flags &= ~GPIO_PIN_INVIN;
GPIO_BIT_CLR(sc, pin->gp_pin, POL);
}
#ifdef notyet
/* Enable interrupt bits for rising/falling transitions */
if (flags & GPIO_PIN_REPORT) {
pin->gp_flags |= GPIO_PIN_REPORT;
GPIO_BIT_SET(sc, pin->gp_pin, RENA);
GPIO_BIT_SET(sc, pin->gp_pin, FENA);
device_printf(sc->dev, "Will report interrupt on pin %d\n",
pin->gp_pin);
}
else {
pin->gp_flags &= ~GPIO_PIN_REPORT;
GPIO_BIT_CLR(sc, pin->gp_pin, RENA);
GPIO_BIT_CLR(sc, pin->gp_pin, FENA);
}
#else
/* Disable generating interrupts for now */
GPIO_BIT_CLR(sc, pin->gp_pin, RENA);
GPIO_BIT_CLR(sc, pin->gp_pin, FENA);
#endif
GPIO_UNLOCK(sc);
}
static int
rt305x_gpio_pin_max(device_t dev, int *maxpin)
{
*maxpin = NGPIO - 1;
return (0);
}
static int
rt305x_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
{
struct rt305x_gpio_softc *sc = device_get_softc(dev);
int i;
for (i = 0; i < sc->gpio_npins; i++) {
if (sc->gpio_pins[i].gp_pin == pin)
break;
}
if (i >= sc->gpio_npins)
return (EINVAL);
GPIO_LOCK(sc);
*caps = sc->gpio_pins[i].gp_caps;
GPIO_UNLOCK(sc);
return (0);
}
static int
rt305x_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
{
struct rt305x_gpio_softc *sc = device_get_softc(dev);
int i;
for (i = 0; i < sc->gpio_npins; i++) {
if (sc->gpio_pins[i].gp_pin == pin)
break;
}
if (i >= sc->gpio_npins)
return (EINVAL);
GPIO_LOCK(sc);
*flags = sc->gpio_pins[i].gp_flags;
GPIO_UNLOCK(sc);
return (0);
}
static int
rt305x_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
{
struct rt305x_gpio_softc *sc = device_get_softc(dev);
int i;
for (i = 0; i < sc->gpio_npins; i++) {
if (sc->gpio_pins[i].gp_pin == pin)
break;
}
if (i >= sc->gpio_npins)
return (EINVAL);
GPIO_LOCK(sc);
memcpy(name, sc->gpio_pins[i].gp_name, GPIOMAXNAME);
GPIO_UNLOCK(sc);
return (0);
}
static int
rt305x_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
{
int i;
struct rt305x_gpio_softc *sc = device_get_softc(dev);
for (i = 0; i < sc->gpio_npins; i++) {
if (sc->gpio_pins[i].gp_pin == pin)
break;
}
if (i >= sc->gpio_npins)
return (EINVAL);
/* Filter out unwanted flags */
if ((flags &= sc->gpio_pins[i].gp_caps) != flags)
return (EINVAL);
/* Can't mix input/output together */
if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) ==
(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT))
return (EINVAL);
rt305x_gpio_pin_configure(sc, &sc->gpio_pins[i], flags);
return (0);
}
static int
rt305x_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
{
struct rt305x_gpio_softc *sc = device_get_softc(dev);
int i;
for (i = 0; i < sc->gpio_npins; i++) {
if (sc->gpio_pins[i].gp_pin == pin)
break;
}
if (i >= sc->gpio_npins)
return (EINVAL);
GPIO_LOCK(sc);
if (value) GPIO_BIT_SET(sc, i, DATA);
else GPIO_BIT_CLR(sc, i, DATA);
GPIO_UNLOCK(sc);
return (0);
}
static int
rt305x_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
{
struct rt305x_gpio_softc *sc = device_get_softc(dev);
int i;
for (i = 0; i < sc->gpio_npins; i++) {
if (sc->gpio_pins[i].gp_pin == pin)
break;
}
if (i >= sc->gpio_npins)
return (EINVAL);
GPIO_LOCK(sc);
*val = GPIO_BIT_GET(sc, i, DATA);
GPIO_UNLOCK(sc);
return (0);
}
static int
rt305x_gpio_pin_toggle(device_t dev, uint32_t pin)
{
int i;
struct rt305x_gpio_softc *sc = device_get_softc(dev);
for (i = 0; i < sc->gpio_npins; i++) {
if (sc->gpio_pins[i].gp_pin == pin)
break;
}
if (i >= sc->gpio_npins)
return (EINVAL);
GPIO_LOCK(sc);
GPIO_BIT_SET(sc, i, TOG);
GPIO_UNLOCK(sc);
return (0);
}
static int
rt305x_gpio_intr(void *arg)
{
struct rt305x_gpio_softc *sc = arg;
#ifdef notyet
uint32_t i;
#endif
uint64_t input, value;
#ifdef notyet
uint64_t reset_pin;
char notify[16];
char pinname[6];
#endif
/* Read all reported pins */
input = GPIO_READ_ALL(sc, INT);
/* Clear int status */
GPIO_WRITE_ALL(sc, INT, input);
/* Clear report for OUTs */
input &= ~GPIO_READ_ALL(sc, DIR);
value = input & GPIO_READ_ALL(sc, DATA);
if (!input) goto intr_done;
#ifdef notyet
/* if reset_gpio and this pin is input */
if (sc->reset_gpio >= 0 && (input & (1 << sc->reset_gpio))) {
/* get reset_gpio pin value */
reset_pin = (value & (1 << sc->reset_gpio))?1:0;
if ( sc->reset_gpio_last != reset_pin ) {
/*
* if now reset is high, check how long
* and do reset if less than 2 seconds
*/
if ( reset_pin &&
(time_uptime - sc->reset_gpio_ontime) < 2 )
shutdown_nice(0);
sc->reset_gpio_last = reset_pin;
sc->reset_gpio_ontime = time_uptime;
}
}
for ( i = 0; i < NGPIO; i ++ )
{
/* Next if output pin */
if ( !(( input >> i) & 1) ) continue;
if ( (((value & input) >> i) & 1) != sc->gpio_pins[i].gp_last )
{
/* !system=GPIO subsystem=pin7 type=PIN_HIGH period=3 */
snprintf(notify , sizeof(notify ), "period=%d",
(uint32_t)time_uptime - sc->gpio_pins[i].gp_time);
snprintf(pinname, sizeof(pinname), "pin%02d", i);
devctl_notify("GPIO", pinname,
(((value & input) >> i) & 1)?"PIN_HIGH":"PIN_LOW",
notify);
printf("GPIO[%s] %s %s\n", pinname,
(((value & input) >> i) & 1)?"PIN_HIGH":"PIN_LOW",
notify);
sc->gpio_pins[i].gp_last = ((value & input) >> i) & 1;
sc->gpio_pins[i].gp_time = time_uptime;
}
}
#endif
intr_done:
return (FILTER_HANDLED);
}
static int
rt305x_gpio_probe(device_t dev)
{
device_set_desc(dev, "RT305X GPIO driver");
return (0);
}
static uint64_t
rt305x_gpio_init(device_t dev)
{
uint64_t avl = ~0ULL;
uint32_t gmode = rt305x_sysctl_get(SYSCTL_GPIOMODE);
if (!(gmode & SYSCTL_GPIOMODE_RGMII_GPIO_MODE))
avl &= ~RGMII_GPIO_MODE_MASK;
if (!(gmode & SYSCTL_GPIOMODE_SDRAM_GPIO_MODE))
avl &= ~SDRAM_GPIO_MODE_MASK;
if (!(gmode & SYSCTL_GPIOMODE_MDIO_GPIO_MODE))
avl &= ~MDIO_GPIO_MODE_MASK;
if (!(gmode & SYSCTL_GPIOMODE_JTAG_GPIO_MODE))
avl &= ~JTAG_GPIO_MODE_MASK;
if (!(gmode & SYSCTL_GPIOMODE_UARTL_GPIO_MODE))
avl &= ~UARTL_GPIO_MODE_MASK;
if (!(gmode & SYSCTL_GPIOMODE_SPI_GPIO_MODE))
avl &= ~SPI_GPIO_MODE_MASK;
if (!(gmode & SYSCTL_GPIOMODE_I2C_GPIO_MODE))
avl &= ~I2C_GPIO_MODE_MASK;
if ((gmode & SYSCTL_GPIOMODE_UARTF_SHARE_MODE_GPIO) !=
SYSCTL_GPIOMODE_UARTF_SHARE_MODE_GPIO)
avl &= ~I2C_GPIO_MODE_MASK;
/* D-Link DAP-1350 Board have
* MDIO_GPIO_MODE
* UARTF_GPIO_MODE
* SPI_GPIO_MODE
* I2C_GPIO_MODE
* So we have
* 00000001 10000000 01111111 11111110
*/
return (avl);
}
#define DAP1350_RESET_GPIO 10
static int
rt305x_gpio_attach(device_t dev)
{
struct rt305x_gpio_softc *sc = device_get_softc(dev);
int error = 0, i;
uint64_t avlpins = 0;
sc->reset_gpio = DAP1350_RESET_GPIO;
KASSERT((device_get_unit(dev) == 0),
("rt305x_gpio_gpio: Only one gpio module supported"));
mtx_init(&sc->gpio_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
MTX_DEF);
/* Map control/status registers. */
sc->gpio_mem_rid = 0;
sc->gpio_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
&sc->gpio_mem_rid, RF_ACTIVE);
if (sc->gpio_mem_res == NULL) {
device_printf(dev, "couldn't map memory\n");
error = ENXIO;
rt305x_gpio_detach(dev);
return(error);
}
if ((sc->gpio_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
&sc->gpio_irq_rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
device_printf(dev, "unable to allocate IRQ resource\n");
return (ENXIO);
}
if ((bus_setup_intr(dev, sc->gpio_irq_res, INTR_TYPE_MISC,
/* rt305x_gpio_filter, */
rt305x_gpio_intr, NULL, sc, &sc->gpio_ih))) {
device_printf(dev,
"WARNING: unable to register interrupt handler\n");
return (ENXIO);
}
sc->dev = dev;
avlpins = rt305x_gpio_init(dev);
/* Configure all pins as input */
/* disable interrupts for all pins */
/* TODO */
sc->gpio_npins = NGPIO;
resource_int_value(device_get_name(dev), device_get_unit(dev),
"pins", &sc->gpio_npins);
for (i = 0; i < sc->gpio_npins; i++) {
sc->gpio_pins[i].gp_pin = i;
sc->gpio_pins[i].gp_caps = DEFAULT_CAPS;
sc->gpio_pins[i].gp_flags = 0;
}
/* Setup reset pin interrupt */
if (TUNABLE_INT_FETCH("reset_gpio", &sc->reset_gpio)) {
device_printf(dev, "\tHinted reset_gpio %d\n", sc->reset_gpio);
}
#ifdef notyet
if (sc->reset_gpio != -1) {
rt305x_gpio_pin_setflags(dev, sc->reset_gpio,
GPIO_PIN_INPUT|GPIO_PIN_INVOUT|
GPIO_PIN_INVOUT|GPIO_PIN_REPORT);
device_printf(dev, "\tUse reset_gpio %d\n", sc->reset_gpio);
}
#else
if (sc->reset_gpio != -1) {
rt305x_gpio_pin_setflags(dev, sc->reset_gpio,
GPIO_PIN_INPUT|GPIO_PIN_INVOUT);
device_printf(dev, "\tUse reset_gpio %d\n", sc->reset_gpio);
}
#endif
device_add_child(dev, "gpioc", device_get_unit(dev));
device_add_child(dev, "gpiobus", device_get_unit(dev));
return (bus_generic_attach(dev));
}
static int
rt305x_gpio_detach(device_t dev)
{
struct rt305x_gpio_softc *sc = device_get_softc(dev);
KASSERT(mtx_initialized(&sc->gpio_mtx), ("gpio mutex not initialized"));
bus_generic_detach(dev);
if (sc->gpio_mem_res)
bus_release_resource(dev, SYS_RES_MEMORY, sc->gpio_mem_rid,
sc->gpio_mem_res);
mtx_destroy(&sc->gpio_mtx);
return(0);
}
#ifdef notyet
static struct resource *
rt305x_gpio_alloc_resource(device_t bus, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
{
struct obio_softc *sc = device_get_softc(bus);
struct resource *rv;
struct rman *rm;
switch (type) {
case SYS_RES_GPIO:
rm = &sc->gpio_rman;
break;
default:
printf("%s: unknown resource type %d\n", __func__, type);
return (0);
}
rv = rman_reserve_resource(rm, start, end, count, flags, child);
if (rv == 0) {
printf("%s: could not reserve resource\n", __func__);
return (0);
}
rman_set_rid(rv, *rid);
return (rv);
}
static int
rt305x_gpio_activate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
return (rman_activate_resource(r));
}
static int
rt305x_gpio_deactivate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
return (rman_deactivate_resource(r));
}
static int
rt305x_gpio_release_resource(device_t dev, device_t child, int type,
int rid, struct resource *r)
{
rman_release_resource(r);
return (0);
}
#endif
static device_method_t rt305x_gpio_methods[] = {
DEVMETHOD(device_probe, rt305x_gpio_probe),
DEVMETHOD(device_attach, rt305x_gpio_attach),
DEVMETHOD(device_detach, rt305x_gpio_detach),
/* GPIO protocol */
DEVMETHOD(gpio_pin_max, rt305x_gpio_pin_max),
DEVMETHOD(gpio_pin_getname, rt305x_gpio_pin_getname),
DEVMETHOD(gpio_pin_getflags, rt305x_gpio_pin_getflags),
DEVMETHOD(gpio_pin_getcaps, rt305x_gpio_pin_getcaps),
DEVMETHOD(gpio_pin_setflags, rt305x_gpio_pin_setflags),
DEVMETHOD(gpio_pin_get, rt305x_gpio_pin_get),
DEVMETHOD(gpio_pin_set, rt305x_gpio_pin_set),
DEVMETHOD(gpio_pin_toggle, rt305x_gpio_pin_toggle),
{0, 0},
};
static driver_t rt305x_gpio_driver = {
"gpio",
rt305x_gpio_methods,
sizeof(struct rt305x_gpio_softc),
};
static devclass_t rt305x_gpio_devclass;
DRIVER_MODULE(rt305x_gpio, obio, rt305x_gpio_driver,
rt305x_gpio_devclass, 0, 0);

View File

@ -0,0 +1,111 @@
/*-
* Copyright (c) 2010 Aleksandr Rybalko.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 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.
*
* $FreeBSD$
*/
#ifndef _RT305X_GPIO_H_
#define _RT305X_GPIO_H_
#define NGPIO 52
#define RGMII_GPIO_MODE_MASK (0x0fffULL<<40)
#define SDRAM_GPIO_MODE_MASK (0xffffULL<<24)
#define MDIO_GPIO_MODE_MASK (0x0003ULL<<22)
#define JTAG_GPIO_MODE_MASK (0x001fULL<<17)
#define UARTL_GPIO_MODE_MASK (0x0003ULL<<15)
#define UARTF_GPIO_MODE_MASK (0x00ffULL<<7)
#define SPI_GPIO_MODE_MASK (0x000fULL<<3)
#define I2C_GPIO_MODE_MASK (0x0003ULL<<1)
#define GPIO23_00_INT 0x00 /* Programmed I/O Int Status */
#define GPIO23_00_EDGE 0x04 /* Programmed I/O Edge Status */
#define GPIO23_00_RENA 0x08 /* Programmed I/O Int on Rising */
#define GPIO23_00_FENA 0x0C /* Programmed I/O Int on Falling */
#define GPIO23_00_DATA 0x20 /* Programmed I/O Data */
#define GPIO23_00_DIR 0x24 /* Programmed I/O Direction */
#define GPIO23_00_POL 0x28 /* Programmed I/O Pin Polarity */
#define GPIO23_00_SET 0x2C /* Set PIO Data Bit */
#define GPIO23_00_RESET 0x30 /* Clear PIO Data bit */
#define GPIO23_00_TOG 0x34 /* Toggle PIO Data bit */
#define GPIO39_24_INT 0x38
#define GPIO39_24_EDGE 0x3c
#define GPIO39_24_RENA 0x40
#define GPIO39_24_FENA 0x44
#define GPIO39_24_DATA 0x48
#define GPIO39_24_DIR 0x4c
#define GPIO39_24_POL 0x50
#define GPIO39_24_SET 0x54
#define GPIO39_24_RESET 0x58
#define GPIO39_24_TOG 0x5c
#define GPIO51_40_INT 0x60
#define GPIO51_40_EDGE 0x64
#define GPIO51_40_RENA 0x68
#define GPIO51_40_FENA 0x6C
#define GPIO51_40_DATA 0x70
#define GPIO51_40_DIR 0x74
#define GPIO51_40_POL 0x78
#define GPIO51_40_SET 0x7C
#define GPIO51_40_RESET 0x80
#define GPIO51_40_TOG 0x84
#define GPIO_REG(g, n) \
((g<24)?(GPIO23_00_##n):(g<40)?(GPIO39_24_##n):(GPIO51_40_##n))
#define GPIO_MASK(g) \
((g<24)?(1<<g):(g<40)?(1<<(g-24)):(1<<(g-40)))
#define GPIO_BIT_SHIFT(g) ((g<24)?(g):(g<40)?(g-24):(g-40))
#define GPIO_READ(r, g, n) \
bus_read_4(r->gpio_mem_res, GPIO_REG(g, n))
#define GPIO_WRITE(r, g, n, v) \
bus_write_4(r->gpio_mem_res, GPIO_REG(g, n), v)
#define GPIO_READ_ALL(r, n) \
(((uint64_t)bus_read_4(r->gpio_mem_res, GPIO23_00_##n)) | \
(((uint64_t)bus_read_4(r->gpio_mem_res, GPIO39_24_##n)) << 24) |\
(((uint64_t)bus_read_4(r->gpio_mem_res, GPIO51_40_##n)) << 40))
#define GPIO_WRITE_ALL(r, n, v) \
{bus_write_4(r->gpio_mem_res,GPIO23_00_##n, v &0x00ffffff);\
bus_write_4(r->gpio_mem_res, GPIO39_24_##n, (v>>24)&0x0000ffff);\
bus_write_4(r->gpio_mem_res, GPIO51_40_##n, (v>>40)&0x00000fff);}
#define GPIO_BIT_CLR(r, g, n) \
bus_write_4(r->gpio_mem_res, GPIO_REG(g, n), \
bus_read_4(r->gpio_mem_res, GPIO_REG(g, n)) & ~GPIO_MASK(g))
#define GPIO_BIT_SET(r, g, n) \
bus_write_4(r->gpio_mem_res, GPIO_REG(g, n), \
bus_read_4(r->gpio_mem_res, GPIO_REG(g, n)) | GPIO_MASK(g))
#define GPIO_BIT_GET(r, g, n) \
((bus_read_4(r->gpio_mem_res, GPIO_REG(g, n)) >> \
GPIO_BIT_SHIFT(g)) & 1)
#define GPIO_LOCK(_sc) mtx_lock(&(_sc)->gpio_mtx)
#define GPIO_UNLOCK(_sc) mtx_unlock(&(_sc)->gpio_mtx)
#define GPIO_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->gpio_mtx, MA_OWNED)
#endif /* _RT305X_GPIO_H_ */

View File

@ -0,0 +1,48 @@
/*-
* Copyright (c) 2010 Aleksandr Rybalko.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 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.
*
* $FreeBSD$
*/
#ifndef _RT305X_GPIOVAR_H_
#define _RT305X_GPIOVAR_H_
struct rt305x_gpio_softc {
device_t dev;
struct mtx gpio_mtx;
struct resource *gpio_mem_res;
int gpio_mem_rid;
struct resource *gpio_irq_res;
int gpio_irq_rid;
void *gpio_ih;
int gpio_npins;
struct gpio_pin gpio_pins[NGPIO];
int reset_gpio;
int reset_gpio_last;
time_t reset_gpio_ontime;
};
#endif /* _RT305X_GPIOVAR_H_ */

141
sys/mips/rt305x/rt305x_ic.c Normal file
View File

@ -0,0 +1,141 @@
/*-
* Copyright (c) 2010 Aleksandr Rybalko.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/interrupt.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/rman.h>
#include <sys/malloc.h>
#include <machine/bus.h>
#include <mips/rt305x/rt305xreg.h>
#include <mips/rt305x/rt305x_icvar.h>
static int rt305x_ic_probe(device_t);
static int rt305x_ic_attach(device_t);
static int rt305x_ic_detach(device_t);
static struct rt305x_ic_softc *rt305x_ic_softc = NULL;
static int
rt305x_ic_probe(device_t dev)
{
device_set_desc(dev, "RT305X Interrupt Controller driver");
return (0);
}
static int
rt305x_ic_attach(device_t dev)
{
struct rt305x_ic_softc *sc = device_get_softc(dev);
int error = 0;
KASSERT((device_get_unit(dev) == 0),
("rt305x_ic: Only one Interrupt Controller module supported"));
if (rt305x_ic_softc != NULL)
return (ENXIO);
rt305x_ic_softc = sc;
/* Map control/status registers. */
sc->mem_rid = 0;
sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
&sc->mem_rid, RF_ACTIVE);
if (sc->mem_res == NULL) {
device_printf(dev, "couldn't map memory\n");
error = ENXIO;
rt305x_ic_detach(dev);
return(error);
}
return (bus_generic_attach(dev));
}
static int
rt305x_ic_detach(device_t dev)
{
struct rt305x_ic_softc *sc = device_get_softc(dev);
bus_generic_detach(dev);
if (sc->mem_res)
bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid,
sc->mem_res);
return(0);
}
uint32_t
rt305x_ic_get(uint32_t reg)
{
struct rt305x_ic_softc *sc = rt305x_ic_softc;
if (!sc)
return (0);
return (bus_read_4(sc->mem_res, reg));
}
void
rt305x_ic_set(uint32_t reg, uint32_t val)
{
struct rt305x_ic_softc *sc = rt305x_ic_softc;
if (!sc)
return;
bus_write_4(sc->mem_res, reg, val);
return;
}
static device_method_t rt305x_ic_methods[] = {
DEVMETHOD(device_probe, rt305x_ic_probe),
DEVMETHOD(device_attach, rt305x_ic_attach),
DEVMETHOD(device_detach, rt305x_ic_detach),
{0, 0},
};
static driver_t rt305x_ic_driver = {
"rt305x_ic",
rt305x_ic_methods,
sizeof(struct rt305x_ic_softc),
};
static devclass_t rt305x_ic_devclass;
DRIVER_MODULE(rt305x_ic, obio, rt305x_ic_driver, rt305x_ic_devclass, 0, 0);

View File

@ -0,0 +1,42 @@
/*-
* Copyright (c) 2010 Aleksandr Rybalko.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 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.
*
* $FreeBSD$
*/
#ifndef _RT305X_ICVAR_H_
#define _RT305X_ICVAR_H_
struct rt305x_ic_softc {
device_t dev;
struct resource *mem_res;
int mem_rid;
};
uint32_t rt305x_ic_get(uint32_t);
void rt305x_ic_set(uint32_t, uint32_t);
#endif /* _RT305X_ICVAR_H_ */

View File

@ -0,0 +1,217 @@
/*-
* Copyright (C) 2010-2011 by Aleksandr Rybalko. All rights reserved.
* Copyright (C) 2007 by Oleksandr Tymoshenko. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES 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 MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/imgact.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/bus.h>
#include <sys/cpu.h>
#include <sys/cons.h>
#include <sys/exec.h>
#include <sys/ucontext.h>
#include <sys/proc.h>
#include <sys/kdb.h>
#include <sys/ptrace.h>
#include <sys/reboot.h>
#include <sys/signalvar.h>
#include <sys/sysent.h>
#include <sys/sysproto.h>
#include <sys/user.h>
#include <vm/vm.h>
#include <vm/vm_object.h>
#include <vm/vm_page.h>
#include <vm/vm_pager.h>
#include <machine/cache.h>
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/cpuinfo.h>
#include <machine/cpufunc.h>
#include <machine/cpuregs.h>
#include <machine/hwfunc.h>
#include <machine/intr_machdep.h>
#include <machine/locore.h>
#include <machine/md_var.h>
#include <machine/pte.h>
#include <machine/sigframe.h>
#include <machine/trap.h>
#include <machine/vmparam.h>
#include <mips/rt305x/rt305xreg.h>
extern int *edata;
extern int *end;
static char boot1_env[0x1000];
void
platform_cpu_init()
{
/* Nothing special */
}
static void
mips_init(void)
{
int i;
printf("entry: mips_init()\n");
bootverbose = 1;
realmem = btoc(32 << 20);
for (i = 0; i < 10; i++) {
phys_avail[i] = 0;
}
/* phys_avail regions are in bytes */
dump_avail[0] = phys_avail[0] = MIPS_KSEG0_TO_PHYS(kernel_kseg0_end);
dump_avail[1] = phys_avail[1] = ctob(realmem);
physmem = realmem;
init_param1();
init_param2(physmem);
mips_cpu_init();
pmap_bootstrap();
mips_proc0_init();
mutex_init();
kdb_init();
#ifdef KDB
if (boothowto & RB_KDB)
kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger");
#endif
}
void
platform_halt(void)
{
}
void
platform_identify(void)
{
}
void
platform_reset(void)
{
__asm __volatile("li $25, 0xbf000000");
__asm __volatile("j $25");
}
void
platform_trap_enter(void)
{
}
void
platform_trap_exit(void)
{
}
void
platform_start(__register_t a0 __unused, __register_t a1 __unused,
__register_t a2 __unused, __register_t a3 __unused)
{
vm_offset_t kernend;
uint64_t platform_counter_freq = PLATFORM_COUNTER_FREQ;
int i;
int argc = a0;
char **argv = (char **)MIPS_PHYS_TO_KSEG0(a1);
char **envp = (char **)MIPS_PHYS_TO_KSEG0(a2);
/* clear the BSS and SBSS segments */
kernend = (vm_offset_t)&end;
memset(&edata, 0, kernend - (vm_offset_t)(&edata));
mips_postboot_fixup();
/* Initialize pcpu stuff */
mips_pcpu0_init();
/* initialize console so that we have printf */
boothowto |= (RB_SERIAL | RB_MULTIPLE); /* Use multiple consoles */
boothowto |= (RB_VERBOSE);
cninit();
init_static_kenv(boot1_env, sizeof(boot1_env));
printf("U-Boot args (from %d args):\n", argc - 1);
if (argc == 1)
printf("\tNone\n");
for (i = 1; i < argc; i++) {
char *n = "argv ", *arg;
if (i > 99)
break;
if (argv[i])
{
arg = (char *)(intptr_t)MIPS_PHYS_TO_KSEG0(argv[i]);
printf("\targv[%d] = %s\n", i, arg);
sprintf(n, "argv%d", i);
setenv(n, arg);
}
}
printf("Environment:\n");
for (i = 0; envp[i] ; i++) {
char *n, *arg;
arg = (char *)(intptr_t)MIPS_PHYS_TO_KSEG0(envp[i]);
printf("\t%s\n", arg);
n = strsep(&arg, "=");
if (arg == NULL)
setenv(n, "1");
else
setenv(n, arg);
}
mips_init();
mips_timer_init_params(platform_counter_freq, 2);
}

View File

@ -0,0 +1,240 @@
/*-
* Copyright (c) 2010 Aleksandr Rybalko.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/interrupt.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/rman.h>
#include <sys/malloc.h>
#include <machine/bus.h>
#include <mips/rt305x/rt305xreg.h>
#include <mips/rt305x/rt305x_sysctlvar.h>
static int rt305x_sysctl_probe(device_t);
static int rt305x_sysctl_attach(device_t);
static int rt305x_sysctl_detach(device_t);
static struct rt305x_sysctl_softc *rt305x_sysctl_softc = NULL;
static void
rt305x_sysctl_dump_config(device_t dev)
{
uint32_t val;
#define DUMPREG(r) \
val = rt305x_sysctl_get(r); printf(" " #r "=%#08x\n", val)
val = rt305x_sysctl_get(SYSCTL_CHIPID0_3);
printf("\tChip ID: \"%c%c%c%c",
(val >> 0 ) & 0xff,
(val >> 8 ) & 0xff,
(val >> 16) & 0xff,
(val >> 24) & 0xff);
val = rt305x_sysctl_get(SYSCTL_CHIPID4_7);
printf("%c%c%c%c\"\n",
(val >> 0 ) & 0xff,
(val >> 8 ) & 0xff,
(val >> 16) & 0xff,
(val >> 24) & 0xff);
DUMPREG(SYSCTL_SYSCFG);
if ( val & SYSCTL_SYSCFG_INIC_EE_SDRAM)
printf("\tGet SDRAM config from EEPROM\n");
if ( val & SYSCTL_SYSCFG_INIC_8MB_SDRAM)
printf("\tBootstrap flag is set\n");
printf("\tGE0 mode %u\n",
((val & SYSCTL_SYSCFG_GE0_MODE_MASK) >>
SYSCTL_SYSCFG_GE0_MODE_SHIFT));
if ( val & SYSCTL_SYSCFG_BOOT_ADDR_1F00)
printf("\tBoot from 0x1f000000\n");
if ( val & SYSCTL_SYSCFG_BYPASS_PLL)
printf("\tBypass PLL\n");
if ( val & SYSCTL_SYSCFG_BIG_ENDIAN)
printf("\tBig Endian\n");
if ( val & SYSCTL_SYSCFG_CPU_CLK_SEL_384MHZ)
printf("\tClock is 384Mhz\n");
printf("\tBoot from %u\n",
((val & SYSCTL_SYSCFG_BOOT_FROM_MASK) >>
SYSCTL_SYSCFG_BOOT_FROM_SHIFT));
printf("\tBootstrap test code %u\n",
((val & SYSCTL_SYSCFG_TEST_CODE_MASK) >>
SYSCTL_SYSCFG_TEST_CODE_SHIFT));
printf("\tSRAM_CS mode %u\n",
((val & SYSCTL_SYSCFG_SRAM_CS_MODE_MASK) >>
SYSCTL_SYSCFG_SRAM_CS_MODE_SHIFT));
printf("\t%umA SDRAM_CLK driving\n",
(val & SYSCTL_SYSCFG_SDRAM_CLK_DRV)?12:8);
DUMPREG(SYSCTL_CLKCFG0);
printf("\tSDRAM_CLK_SKEW %uns\n", (val >> 30) & 0x03);
DUMPREG(SYSCTL_CLKCFG1);
if ( val & SYSCTL_CLKCFG1_PBUS_DIV_CLK_BY2)
printf("\tPbus clock is 1/2 of System clock\n");
if ( val & SYSCTL_CLKCFG1_OTG_CLK_EN)
printf("\tUSB OTG clock is enabled\n");
if ( val & SYSCTL_CLKCFG1_I2S_CLK_EN)
printf("\tI2S clock is enabled\n");
printf("\tI2S clock is %s\n",
(val & SYSCTL_CLKCFG1_I2S_CLK_SEL_EXT)?
"external":"internal 15.625Mhz");
printf("\tI2S clock divider %u\n",
((val & SYSCTL_CLKCFG1_I2S_CLK_DIV_MASK) >>
SYSCTL_CLKCFG1_I2S_CLK_DIV_SHIFT));
if ( val & SYSCTL_CLKCFG1_PCM_CLK_EN)
printf("\tPCM clock is enabled\n");
printf("\tPCM clock is %s\n",
(val & SYSCTL_CLKCFG1_PCM_CLK_SEL_EXT)?
"external":"internal 15.625Mhz");
printf("\tPCM clock divider %u\n",
((val & SYSCTL_CLKCFG1_PCM_CLK_DIV_MASK) >>
SYSCTL_CLKCFG1_PCM_CLK_DIV_SHIFT));
DUMPREG(SYSCTL_GPIOMODE);
#undef DUMPREG
return;
}
static int
rt305x_sysctl_probe(device_t dev)
{
device_set_desc(dev, "RT305X System Control driver");
return (0);
}
static int
rt305x_sysctl_attach(device_t dev)
{
struct rt305x_sysctl_softc *sc = device_get_softc(dev);
int error = 0;
KASSERT((device_get_unit(dev) == 0),
("rt305x_sysctl: Only one sysctl module supported"));
if (rt305x_sysctl_softc != NULL)
return (ENXIO);
rt305x_sysctl_softc = sc;
/* Map control/status registers. */
sc->mem_rid = 0;
sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
&sc->mem_rid, RF_ACTIVE);
if (sc->mem_res == NULL) {
device_printf(dev, "couldn't map memory\n");
error = ENXIO;
rt305x_sysctl_detach(dev);
return(error);
}
#ifdef notyet
sc->irq_rid = 0;
if ((sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
&sc->irq_rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
device_printf(dev, "unable to allocate IRQ resource\n");
return (ENXIO);
}
if ((bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC,
rt305x_sysctl_intr, NULL, sc, &sc->sysctl_ih))) {
device_printf(dev,
"WARNING: unable to register interrupt handler\n");
return (ENXIO);
}
#endif
rt305x_sysctl_dump_config(dev);
return (bus_generic_attach(dev));
}
static int
rt305x_sysctl_detach(device_t dev)
{
struct rt305x_sysctl_softc *sc = device_get_softc(dev);
bus_generic_detach(dev);
if (sc->mem_res)
bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid,
sc->mem_res);
#ifdef notyet
if (sc->irq_res)
bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid,
sc->irq_res);
#endif
return(0);
}
#ifdef notyet
static int
rt305x_sysctl_intr(void *arg)
{
return (FILTER_HANDLED);
}
#endif
uint32_t
rt305x_sysctl_get(uint32_t reg)
{
struct rt305x_sysctl_softc *sc = rt305x_sysctl_softc;
return (bus_read_4(sc->mem_res, reg));
}
void
rt305x_sysctl_set(uint32_t reg, uint32_t val)
{
struct rt305x_sysctl_softc *sc = rt305x_sysctl_softc;
bus_write_4(sc->mem_res, reg, val);
return;
}
static device_method_t rt305x_sysctl_methods[] = {
DEVMETHOD(device_probe, rt305x_sysctl_probe),
DEVMETHOD(device_attach, rt305x_sysctl_attach),
DEVMETHOD(device_detach, rt305x_sysctl_detach),
{0, 0},
};
static driver_t rt305x_sysctl_driver = {
"rt305x_sysctl",
rt305x_sysctl_methods,
sizeof(struct rt305x_sysctl_softc),
};
static devclass_t rt305x_sysctl_devclass;
DRIVER_MODULE(rt305x_sysctl, obio, rt305x_sysctl_driver, rt305x_sysctl_devclass, 0, 0);

View File

@ -0,0 +1,45 @@
/*-
* Copyright (c) 2010 Aleksandr Rybalko.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 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.
*
* $FreeBSD$
*/
#ifndef _RT305X_SYSCTLVAR_H_
#define _RT305X_SYSCTLVAR_H_
struct rt305x_sysctl_softc {
device_t dev;
struct resource *mem_res;
int mem_rid;
struct resource *irq_res;
int irq_rid;
int sysctl_ih;
};
uint32_t rt305x_sysctl_get(uint32_t);
void rt305x_sysctl_set(uint32_t, uint32_t);
#endif /* _RT305X_SYSCTLVAR_H_ */

368
sys/mips/rt305x/rt305xreg.h Normal file
View File

@ -0,0 +1,368 @@
/*-
* Copyright (c) 2010 Aleksandr Rybalko.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 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.
*
* $FreeBSD$
*/
#ifndef _RT305XREG_H_
#define _RT305XREG_H_
/* XXX: must move to config */
#define RT305X 1
#define RT305XF 1
#define RT3052F 1
#define __U_BOOT__ 1
/* XXX: must move to config */
#ifdef RT3052F
#define PLATFORM_COUNTER_FREQ (384 * 1000 * 1000)
#endif
#ifdef RT3050F
#define PLATFORM_COUNTER_FREQ (320 * 1000 * 1000)
#endif
#ifndef PLATFORM_COUNTER_FREQ
#error "Nor RT3052F nor RT3050F defined"
#endif
#define SYSTEM_CLOCK (PLATFORM_COUNTER_FREQ/3)
#define SDRAM_BASE 0x00000000
#define SDRAM_END 0x03FFFFFF
#define SYSCTL_BASE 0x10000000
#define SYSCTL_END 0x100000FF
#define TIMER_BASE 0x10000100
#define TIMER_END 0x100001FF
#define INTCTL_BASE 0x10000200
#define INTCTL_END 0x100002FF
#define MEMCTRL_BASE 0x10000300
#define MEMCTRL_END 0x100003FF /* SDRAM & Flash/SRAM */
#define PCM_BASE 0x10000400
#define PCM_END 0x100004FF
#define UART_BASE 0x10000500
#define UART_END 0x100005FF
#define PIO_BASE 0x10000600
#define PIO_END 0x100006FF
#define GDMA_BASE 0x10000700
#define GDMA_END 0x100007FF /* Generic DMA */
#define NANDFC_BASE 0x10000800
#define NANDFC_END 0x100008FF /* NAND Flash Controller */
#define I2C_BASE 0x10000900
#define I2C_END 0x100009FF
#define I2S_BASE 0x10000A00
#define I2S_END 0x10000AFF
#define SPI_BASE 0x10000B00
#define SPI_END 0x10000BFF
#define UARTLITE_BASE 0x10000C00
#define UARTLITE_END 0x10000CFF
#define FRENG_BASE 0x10100000
#define FRENG_END 0x1010FFFF /* Frame Engine */
#define ETHSW_BASE 0x10110000
#define ETHSW_END 0x10117FFF /* Ethernet Switch */
#define ROM_BASE 0x10118000
#define ROM_END 0x10119FFF
#define WLAN_BASE 0x10180000
#define WLAN_END 0x101BFFFF /* 802.11n MAC/BBP */
#define USB_OTG_BASE 0x101C0000
#define USB_OTG_END 0x101FFFFF
#define EMEM_BASE 0x1B000000
#define EMEM_END 0x1BFFFFFF /* External SRAM/Flash */
#define FLASH_BASE 0x1F000000
#define FLASH_END 0x1FFFFFFF /* Flash window */
#define OBIO_MEM_BASE SYSCTL_BASE
#define OBIO_MEM_START OBIO_MEM_BASE
#define OBIO_MEM_END FLASH_END
/* System Control */
#define SYSCTL_CHIPID0_3 0x00 /* 'R''T''3''0' */
#define SYSCTL_CHIPID4_7 0x04 /* '5''2'' '' ' */
#define SYSCTL_SYSCFG 0x10
#define SYSCTL_SYSCFG_INIC_EE_SDRAM (1<<29)
#define SYSCTL_SYSCFG_INIC_8MB_SDRAM (1<<28)
#define SYSCTL_SYSCFG_GE0_MODE_MASK 0x03000000
#define SYSCTL_SYSCFG_GE0_MODE_SHIFT 24
#define SYSCTL_SYSCFG_GE0_MODE_RGMII 0 /* RGMII Mode */
#define SYSCTL_SYSCFG_GE0_MODE_MII 1 /* MII Mode */
#define SYSCTL_SYSCFG_GE0_MODE_REV_MII 2 /*Reversed MII Mode*/
#define SYSCTL_SYSCFG_BOOT_ADDR_1F00 (1<<22)
#define SYSCTL_SYSCFG_BYPASS_PLL (1<<21)
#define SYSCTL_SYSCFG_BIG_ENDIAN (1<<20)
#define SYSCTL_SYSCFG_CPU_CLK_SEL_384MHZ (1<<18)
#define SYSCTL_SYSCFG_BOOT_FROM_MASK 0x00030000
#define SYSCTL_SYSCFG_BOOT_FROM_SHIFT 16
#define SYSCTL_SYSCFG_BOOT_FROM_FLASH16 0
#define SYSCTL_SYSCFG_BOOT_FROM_FLASH8 1
#define SYSCTL_SYSCFG_BOOT_FROM_NANDFLASH 2
#define SYSCTL_SYSCFG_BOOT_FROM_ROM 3
#define SYSCTL_SYSCFG_TEST_CODE_MASK 0x0000ff00
#define SYSCTL_SYSCFG_TEST_CODE_SHIFT 8
#define SYSCTL_SYSCFG_SRAM_CS_MODE_MASK 0x0000000c
#define SYSCTL_SYSCFG_SRAM_CS_MODE_SHIFT 2
#define SYSCTL_SYSCFG_SRAM_CS_MODE_SRAM 0
#define SYSCTL_SYSCFG_SRAM_CS_MODE_WDOG_RST 1
#define SYSCTL_SYSCFG_SRAM_CS_MODE_BT_COEX 2
#define SYSCTL_SYSCFG_SDRAM_CLK_DRV (1<<0) /* 8mA/12mA */
#define SYSCTL_TESTSTAT 0x18
#define SYSCTL_TESTSTAT2 0x1C
#define SYSCTL_CLKCFG0 0x2C
#define SYSCTL_CLKCFG0_SDRAM_CLK_SKEW_MASK 0xc0000000
#define SYSCTL_CLKCFG0_SDRAM_CLK_SKEW_SHIFT 30
#define SYSCTL_CLKCFG0_SDRAM_CLK_SKEW_ZERO_DELAY 0
#define SYSCTL_CLKCFG0_SDRAM_CLK_SKEW_1NS_DELAY 1
#define SYSCTL_CLKCFG0_SDRAM_CLK_SKEW_2NS_DELAY 2
#define SYSCTL_CLKCFG0_SDRAM_CLK_SKEW_3NS_DELAY 3
#define SYSCTL_CLKCFG1 0x30
#define SYSCTL_CLKCFG1_PBUS_DIV_CLK_BY2 (1<<30)
#define SYSCTL_CLKCFG1_OTG_CLK_EN (1<<18)
#define SYSCTL_CLKCFG1_I2S_CLK_EN (1<<15)
#define SYSCTL_CLKCFG1_I2S_CLK_SEL_EXT (1<<14)
#define SYSCTL_CLKCFG1_I2S_CLK_DIV_MASK 0x00003f00
#define SYSCTL_CLKCFG1_I2S_CLK_DIV_SHIFT 8
#define SYSCTL_CLKCFG1_PCM_CLK_EN (1<<7)
#define SYSCTL_CLKCFG1_PCM_CLK_SEL_EXT (1<<6)
#define SYSCTL_CLKCFG1_PCM_CLK_DIV_MASK 0x0000003f
#define SYSCTL_CLKCFG1_PCM_CLK_DIV_SHIFT 0
#define SYSCTL_RSTCTRL 0x34
#define SYSCTL_RSTCTRL_ETHSW (1<<23)
#define SYSCTL_RSTCTRL_OTG (1<<22)
#define SYSCTL_RSTCTRL_FRENG (1<<21)
#define SYSCTL_RSTCTRL_WLAN (1<<20)
#define SYSCTL_RSTCTRL_UARTL (1<<19)
#define SYSCTL_RSTCTRL_SPI (1<<18)
#define SYSCTL_RSTCTRL_I2S (1<<17)
#define SYSCTL_RSTCTRL_I2C (1<<16)
#define SYSCTL_RSTCTRL_DMA (1<<14)
#define SYSCTL_RSTCTRL_PIO (1<<13)
#define SYSCTL_RSTCTRL_UART (1<<12)
#define SYSCTL_RSTCTRL_PCM (1<<11)
#define SYSCTL_RSTCTRL_MC (1<<10)
#define SYSCTL_RSTCTRL_INTC (1<<9)
#define SYSCTL_RSTCTRL_TIMER (1<<8)
#define SYSCTL_RSTCTRL_SYS (1<<0)
#define SYSCTL_RSTSTAT 0x38
#define SYSCTL_RSTSTAT_SWCPURST (1<<3)
#define SYSCTL_RSTSTAT_SWSYSRST (1<<2)
#define SYSCTL_RSTSTAT_WDRST (1<<1)
#define SYSCTL_GPIOMODE 0x60
#define SYSCTL_GPIOMODE_RGMII_GPIO_MODE (1<<9)
#define SYSCTL_GPIOMODE_SDRAM_GPIO_MODE (1<<8)
#define SYSCTL_GPIOMODE_MDIO_GPIO_MODE (1<<7)
#define SYSCTL_GPIOMODE_JTAG_GPIO_MODE (1<<6)
#define SYSCTL_GPIOMODE_UARTL_GPIO_MODE (1<<5)
#define SYSCTL_GPIOMODE_UARTF_SHARE_MODE_UARTF (0<<2)
#define SYSCTL_GPIOMODE_UARTF_SHARE_MODE_PCM_UARTF (1<<2)
#define SYSCTL_GPIOMODE_UARTF_SHARE_MODE_PCM_I2S (2<<2)
#define SYSCTL_GPIOMODE_UARTF_SHARE_MODE_I2S_UARTF (3<<2)
#define SYSCTL_GPIOMODE_UARTF_SHARE_MODE_PCM_GPIO (4<<2)
#define SYSCTL_GPIOMODE_UARTF_SHARE_MODE_GPIO_UARTF (5<<2)
#define SYSCTL_GPIOMODE_UARTF_SHARE_MODE_GPIO_I2S (6<<2)
#define SYSCTL_GPIOMODE_UARTF_SHARE_MODE_GPIO (7<<2)
#define SYSCTL_GPIOMODE_SPI_GPIO_MODE (1<<1)
#define SYSCTL_GPIOMODE_I2C_GPIO_MODE (1<<0)
#define SYSCTL_MEMO0 0x68
#define SYSCTL_MEMO1 0x6C
/* Timer */
#define TIMER_TMRSTAT 0x00
#define TIMER_TMRSTAT_TMR1RST (1<<5)
#define TIMER_TMRSTAT_TMR0RST (1<<4)
#define TIMER_TMRSTAT_TMR1INT (1<<1)
#define TIMER_TMRSTAT_TMR0INT (1<<0)
#define TIMER_TMR0LOAD 0x10
#define TIMER_TMR0VAL 0x14
#define TIMER_TMR0CTL 0x18
#define TIMER_TMR1LOAD 0x20
#define TIMER_TMR1VAL 0x24
#define TIMER_TMR1CTL 0x28
#define TIMER_TMRLOAD_TMR0LOAD_MASK 0xffff
#define TIMER_TMRVAL_TMR0VAL_MASK 0xffff
#define TIMER_TMRCTL_ENABLE (1<<7)
#define TIMER_TMRCTL_MODE_MASK 0x00000030
#define TIMER_TMRCTL_MODE_SHIFT 4
#define TIMER_TMRCTL_MODE_FREE 0
#define TIMER_TMRCTL_MODE_PERIODIC 1
#define TIMER_TMRCTL_MODE_TIMOUT 2
#define TIMER_TMRCTL_MODE_TIMOUT3 3
#define TIMER_TMRCTL_PRESCALE_MASK 0x0000000f
#define TIMER_TMRCTL_PRESCALE_SHIFT 0
#define TIMER_TMRCTL_PRESCALE_NONE 0
#define TIMER_TMRCTL_PRESCALE_BY_4 1
#define TIMER_TMRCTL_PRESCALE_BY_8 2
#define TIMER_TMRCTL_PRESCALE_BY_16 3
#define TIMER_TMRCTL_PRESCALE_BY_32 4
#define TIMER_TMRCTL_PRESCALE_BY_64 5
#define TIMER_TMRCTL_PRESCALE_BY_128 6
#define TIMER_TMRCTL_PRESCALE_BY_256 7
#define TIMER_TMRCTL_PRESCALE_BY_512 8
#define TIMER_TMRCTL_PRESCALE_BY_1K 9
#define TIMER_TMRCTL_PRESCALE_BY_2K 10
#define TIMER_TMRCTL_PRESCALE_BY_4K 11
#define TIMER_TMRCTL_PRESCALE_BY_8K 12
#define TIMER_TMRCTL_PRESCALE_BY_16K 13
#define TIMER_TMRCTL_PRESCALE_BY_32K 14
#define TIMER_TMRCTL_PRESCALE_BY_64K 15
/* Interrupt Controller */
#define IC_IRQ0STAT 0x00
#define IC_IRQ1STAT 0x04
#define IC_INTTYPE 0x20
#define IC_INTRAW 0x30
#define IC_INT_ENA 0x34
#define IC_INT_DIS 0x38
#define IC_OTG 18
#define IC_ETHSW 17
#define IC_UARTLITE 12
#define IC_I2S 10
#define IC_PERFC 9
#define IC_NAND 8
#define IC_DMA 7
#define IC_PIO 6
#define IC_UART 5
#define IC_PCM 4
#define IC_ILL_ACCESS 3
#define IC_WDTIMER 2
#define IC_TIMER0 1
#define IC_SYSCTL 0
#define IC_LINE_GLOBAL (1<<31) /* Only for DIS/ENA regs */
#define IC_LINE_OTG (1<<18)
#define IC_LINE_ETHSW (1<<17)
#define IC_LINE_UARTLITE (1<<12)
#define IC_LINE_I2S (1<<10)
#define IC_LINE_PERFC (1<<9)
#define IC_LINE_NAND (1<<8)
#define IC_LINE_DMA (1<<7)
#define IC_LINE_PIO (1<<6)
#define IC_LINE_UART (1<<5)
#define IC_LINE_PCM (1<<4)
#define IC_LINE_ILL_ACCESS (1<<3)
#define IC_LINE_WDTIMER (1<<2)
#define IC_LINE_TIMER0 (1<<1)
#define IC_LINE_SYSCTL (1<<0)
#define IC_INT_MASK 0x000617ff
/* GPIO */
#define GPIO23_00_INT 0x00 /* Programmed I/O Int Status */
#define GPIO23_00_EDGE 0x04 /* Programmed I/O Edge Status */
#define GPIO23_00_RENA 0x08 /* Programmed I/O Int on Rising */
#define GPIO23_00_FENA 0x0C /* Programmed I/O Int on Falling */
#define GPIO23_00_DATA 0x20 /* Programmed I/O Data */
#define GPIO23_00_DIR 0x24 /* Programmed I/O Direction */
#define GPIO23_00_POL 0x28 /* Programmed I/O Pin Polarity */
#define GPIO23_00_SET 0x2C /* Set PIO Data Bit */
#define GPIO23_00_RESET 0x30 /* Clear PIO Data bit */
#define GPIO23_00_TOG 0x34 /* Toggle PIO Data bit */
#define GPIO39_24_INT 0x38
#define GPIO39_24_EDGE 0x3c
#define GPIO39_24_RENA 0x40
#define GPIO39_24_FENA 0x44
#define GPIO39_24_DATA 0x48
#define GPIO39_24_DIR 0x4c
#define GPIO39_24_POL 0x50
#define GPIO39_24_SET 0x54
#define GPIO39_24_RESET 0x58
#define GPIO39_24_TOG 0x5c
#define GPIO51_40_INT 0x60
#define GPIO51_40_EDGE 0x64
#define GPIO51_40_RENA 0x68
#define GPIO51_40_FENA 0x6C
#define GPIO51_40_DATA 0x70
#define GPIO51_40_DIR 0x74
#define GPIO51_40_POL 0x78
#define GPIO51_40_SET 0x7C
#define GPIO51_40_RESET 0x80
#define GPIO51_40_TOG 0x84
#define GDMA_CHANNEL_REQ0 0
#define GDMA_CHANNEL_REQ1 1 /* (NAND-flash) */
#define GDMA_CHANNEL_REQ2 2 /* (I2S) */
#define GDMA_CHANNEL_REQ3 3 /* (PCM0-RX) */
#define GDMA_CHANNEL_REQ4 4 /* (PCM1-RX) */
#define GDMA_CHANNEL_REQ5 5 /* (PCM0-TX) */
#define GDMA_CHANNEL_REQ6 6 /* (PCM1-TX) */
#define GDMA_CHANNEL_REQ7 7
#define GDMA_CHANNEL_MEM 8
/* Generic DMA Controller */
/* GDMA Channel n Source Address */
#define GDMASA(n) (0x00 + 0x10*n)
/* GDMA Channel n Destination Address */
#define GDMADA(n) (0x04 + 0x10*n)
/* GDMA Channel n Control Register 0 */
#define GDMACT0(n) (0x08 + 0x10*n)
#define GDMACT0_TR_COUNT_MASK 0x0fff0000
#define GDMACT0_TR_COUNT_SHIFT 16
#define GDMACT0_SRC_CHAN_SHIFT 12
#define GDMACT0_SRC_CHAN_MASK 0x0000f000
#define GDMACT0_DST_CHAN_SHIFT 8
#define GDMACT0_DST_CHAN_MASK 0x00000f00
#define GDMACT0_SRC_BURST_MODE (1<<7)
#define GDMACT0_DST_BURST_MODE (1<<6)
#define GDMACT0_BURST_SIZE_SHIFT 3
#define GDMACT0_BURST_SIZE_MASK 0x00000038
#define GDMACT0_BURST_SIZE_1 0
#define GDMACT0_BURST_SIZE_2 1
#define GDMACT0_BURST_SIZE_4 2
#define GDMACT0_BURST_SIZE_8 3
#define GDMACT0_BURST_SIZE_16 4
#define GDMACT0_DONE_INT_EN (1<<2)
#define GDMACT0_CHAN_EN (1<<1)
/*
* In software mode, the data transfer will start when the Channel Enable bit
* is set.
* In hardware mode, the data transfer will start when the DMA Request is
* asserted.
*/
#define GDMACT0_SWMODE (1<<0)
#endif /* _RT305XREG_H_ */

160
sys/mips/rt305x/rt_swreg.h Normal file
View File

@ -0,0 +1,160 @@
/*-
* Copyright (c) 2010 Aleksandr Rybalko.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 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.
*
* $FreeBSD$
*/
#ifndef _RT_SWREG_H_
#define _RT_SWREG_H_
/* XXX: must move to config */
#define RT3052F
#define RT_SW_BASE 0x10110000
#define RT_SW_ISR 0x00
#define WATCHDOG1_TMR_EXPIRED (1<<29)
#define WATCHDOG0_TMR_EXPIRED (1<<28)
#define HAS_INTRUDER (1<<27)
#define PORT_ST_CHG (1<<26)
#define BC_STORM (1<<25)
#define MUST_DROP_LAN (1<<24)
#define GLOBAL_QUE_FULL (1<<23)
#define LAN_QUE_FULL6 (1<<20)
#define LAN_QUE_FULL5 (1<<19)
#define LAN_QUE_FULL4 (1<<18)
#define LAN_QUE_FULL3 (1<<17)
#define LAN_QUE_FULL2 (1<<16)
#define LAN_QUE_FULL1 (1<<15)
#define LAN_QUE_FULL0 (1<<14)
#define RT_SW_IMR 0x04
#define RT_SW_FCT0 0x08
#define RT_SW_FCT1 0x0c
#define RT_SW_PFC0 0x10
#define RT_SW_PFC1 0x14
#define RT_SW_PFC2 0x18
#define RT_SW_GQS0 0x1c
#define RT_SW_GQS1 0x20
#define RT_SW_ATS 0x24
#define RT_SW_ATS0 0x28
#define RT_SW_ATS1 0x2c
#define RT_SW_ATS2 0x30
#define RT_SW_WMAD0 0x34
#define RT_SW_WMAD1 0x38
#define RT_SW_WMAD2 0x3c
#define RT_SW_PVIDC0 0x40
#define RT_SW_PVIDC1 0x44
#define RT_SW_PVIDC2 0x48
#define RT_SW_PVIDC3 0x4c
#define RT_SW_VID0 0x50
#define RT_SW_VID1 0x54
#define RT_SW_VID2 0x58
#define RT_SW_VID3 0x5c
#define RT_SW_VID4 0x60
#define RT_SW_VID5 0x64
#define RT_SW_VID6 0x68
#define RT_SW_VID7 0x6c
#define RT_SW_VMSC0 0x70
#define RT_SW_VMSC1 0x74
#define RT_SW_VMSC2 0x78
#define RT_SW_VMSC3 0x7c
#define RT_SW_POA 0x80
#define RT_SW_FPA 0x84
#define RT_SW_PTS 0x88
#define RT_SW_SOCPC 0x8c
#define RT_SW_POC0 0x90
#define RT_SW_POC1 0x94
#define RT_SW_POC2 0x98
#define RT_SW_SGC 0x9c
#define RT_SW_STRT 0xa0
#define RT_SW_LEDP0 0xa4
#define RT_SW_LEDP1 0xa8
#define RT_SW_LEDP2 0xac
#define RT_SW_LEDP3 0xb0
#define RT_SW_LEDP4 0xb4
#define RT_SW_WDTR 0xb8
#define RT_SW_DES 0xbc
#define RT_SW_PCR0 0xc0
#define RT_SW_PCR1 0xc4
#define RT_SW_FPA 0xc8
#define RT_SW_FCT2 0xcc
#define RT_SW_QSS0 0xd0
#define RT_SW_QSS1 0xd4
#define RT_SW_DEC 0xd8
#define BRIDGE_IPG_SHIFT 24
#define DEBUG_SW_PORT_SEL_SHIFT 3
#define DEBUG_SW_PORT_SEL_MASK 0x00000038
#define RT_SW_MTI 0xdc
#define SKIP_BLOCKS_SHIFT 7
#define SKIP_BLOCKS_MASK 0x0000ff80
#define SW_RAM_TEST_DONE (1<<6)
#define AT_RAM_TEST_DONE (1<<5)
#define AT_RAM_TEST_FAIL (1<<4)
#define LK_RAM_TEST_DONE (1<<3)
#define LK_RAM_TEST_FAIL (1<<2)
#define DT_RAM_TEST_DONE (1<<1)
#define DT_RAM_TEST_FAIL (1<<0)
#define RT_SW_PPC 0xe0
#define SW2FE_CNT_SHIFT 16
#define FE2SW_CNT_SHIFT 0
#define RT_SW_SGC2 0xe4
#define FE2SW_WL_FC_EN (1<<30)
#define LAN_PMAP_P0_IS_LAN (1<<24)
#define LAN_PMAP_P1_IS_LAN (1<<25)
#define LAN_PMAP_P2_IS_LAN (1<<26)
#define LAN_PMAP_P3_IS_LAN (1<<27)
#define LAN_PMAP_P4_IS_LAN (1<<28)
#define LAN_PMAP_P5_IS_LAN (1<<29)
/* Transmit CPU TPID(810x) port bit map */
#define TX_CPU_TPID_BIT_MAP_SHIFT 16
#define TX_CPU_TPID_BIT_MAP_MASK 0x007f0000
#define ARBITER_LAN_EN (1<<11)
#define CPU_TPID_EN (1<<10)
#define P0_DOUBLE_TAG_EN (1<<0)
#define P1_DOUBLE_TAG_EN (1<<1)
#define P2_DOUBLE_TAG_EN (1<<2)
#define P3_DOUBLE_TAG_EN (1<<3)
#define P4_DOUBLE_TAG_EN (1<<4)
#define P5_DOUBLE_TAG_EN (1<<5)
#define RT_SW_P0PC 0xe8
#define RT_SW_P1PC 0xec
#define RT_SW_P2PC 0xf0
#define RT_SW_P3PC 0xf4
#define RT_SW_P4PC 0xf8
#define RT_SW_P5PC 0xfc
#define BAD_PCOUNT_SHIFT 16
#define BAD_PCOUNT_MASK 0xffff0000
#define GOOD_PCOUNT_SHIFT 0
#define GOOD_PCOUNT_MASK 0x0000ffff
#endif /* _RT_SWREG_H_ */

View File

@ -0,0 +1,8 @@
# $FreeBSD$
# Standard include file for RT305XF SoC
files "../rt305x/files.rt305x"
cpu CPU_MIPS4KC
options ISA_MIPS32

View File

@ -0,0 +1,102 @@
/*-
* Copyright (c) 2007 Bruce M. Simpson.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 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
* $Id$
*/
/*
* Skeleton of this file was based on respective code for ARM
* code written by Olivier Houchard.
*/
/*
* XXXMIPS: This file is hacked from arm/... . XXXMIPS here means this file is
* experimental and was written for MIPS32 port.
*/
#include "opt_uart.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <machine/bus.h>
#include <sys/rman.h>
#include <machine/resource.h>
#include <dev/pci/pcivar.h>
#include <dev/uart/uart.h>
#include <dev/uart/uart_bus.h>
#include <dev/uart/uart_cpu.h>
#include <mips/rt305x/rt305xreg.h>
#include "uart_if.h"
static int uart_rt305x_probe(device_t dev);
extern struct uart_class uart_rt305x_uart_class;
static device_method_t uart_rt305x_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, uart_rt305x_probe),
DEVMETHOD(device_attach, uart_bus_attach),
DEVMETHOD(device_detach, uart_bus_detach),
{ 0, 0 }
};
static driver_t uart_rt305x_driver = {
uart_driver_name,
uart_rt305x_methods,
sizeof(struct uart_softc),
};
extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs;
static int
uart_rt305x_probe(device_t dev)
{
struct uart_softc *sc;
sc = device_get_softc(dev);
sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs);
sc->sc_class = &uart_rt305x_uart_class;
bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas));
sc->sc_sysdev->bas.regshft = 2;
sc->sc_sysdev->bas.bst = mips_bus_space_generic;
sc->sc_sysdev->bas.bsh =
MIPS_PHYS_TO_KSEG1(device_get_unit(dev)?UARTLITE_BASE:UART_BASE);
sc->sc_bas.regshft = 2;
sc->sc_bas.bst = mips_bus_space_generic;
sc->sc_bas.bsh =
MIPS_PHYS_TO_KSEG1(device_get_unit(dev)?UARTLITE_BASE:UART_BASE);
return (uart_bus_probe(dev, 2, SYSTEM_CLOCK, 0, 0));
}
DRIVER_MODULE(uart, obio, uart_rt305x_driver, uart_devclass, 0, 0);

View File

@ -0,0 +1,82 @@
/*-
* Copyright (c) 2006 Wojciech A. Koszek <wkoszek@FreeBSD.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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 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.
*
* $Id$
*/
/*
* Skeleton of this file was based on respective code for ARM
* code written by Olivier Houchard.
*/
/*
* XXXMIPS: This file is hacked from arm/... . XXXMIPS here means this file is
* experimental and was written for MIPS32 port.
*/
#include "opt_uart.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/cons.h>
#include <machine/bus.h>
#include <dev/uart/uart.h>
#include <dev/uart/uart_cpu.h>
#include <mips/rt305x/rt305xreg.h>
extern struct uart_class uart_rt305x_uart_class;
bus_space_tag_t uart_bus_space_io;
bus_space_tag_t uart_bus_space_mem;
int
uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
{
return ((b1->bsh == b2->bsh && b1->bst == b2->bst) ? 1 : 0);
}
int
uart_cpu_getdev(int devtype, struct uart_devinfo *di)
{
di->ops = uart_getops(&uart_rt305x_uart_class);
di->bas.chan = 0;
di->bas.bst = mips_bus_space_generic;
di->bas.regshft = 2;
di->bas.rclk = SYSTEM_CLOCK;
di->baudrate = 115200;
di->databits = 8;
di->stopbits = 1;
di->parity = UART_PARITY_NONE;
uart_bus_space_io = NULL;
uart_bus_space_mem = mips_bus_space_generic;
di->bas.bsh = MIPS_PHYS_TO_KSEG1(UARTLITE_BASE);
return (0);
}

View File

@ -0,0 +1,507 @@
/* $NetBSD: uart.c,v 1.2 2007/03/23 20:05:47 dogcow Exp $ */
/*-
* Copyright (c) 2010 Aleksandr Rybalko.
* Copyright (c) 2007 Ruslan Ermilov and Vsevolod Lobko.
* Copyright (c) 2007 Oleksandr Tymoshenko.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/kdb.h>
#include <sys/reboot.h>
#include <sys/sysctl.h>
#include <sys/kernel.h>
#include <machine/bus.h>
#include <dev/uart/uart.h>
#include <dev/uart/uart_cpu.h>
#include <dev/uart/uart_bus.h>
#include <mips/rt305x/uart_dev_rt305x.h>
#include <mips/rt305x/rt305xreg.h>
#include "uart_if.h"
/*
* Low-level UART interface.
*/
static int rt305x_uart_probe(struct uart_bas *bas);
static void rt305x_uart_init(struct uart_bas *bas, int, int, int, int);
static void rt305x_uart_term(struct uart_bas *bas);
static void rt305x_uart_putc(struct uart_bas *bas, int);
static int rt305x_uart_rxready(struct uart_bas *bas);
static int rt305x_uart_getc(struct uart_bas *bas, struct mtx *);
static struct uart_ops uart_rt305x_uart_ops = {
.probe = rt305x_uart_probe,
.init = rt305x_uart_init,
.term = rt305x_uart_term,
.putc = rt305x_uart_putc,
.rxready = rt305x_uart_rxready,
.getc = rt305x_uart_getc,
};
static int uart_output = 1;
TUNABLE_INT("kern.uart_output", &uart_output);
SYSCTL_INT(_kern, OID_AUTO, uart_output, CTLFLAG_RW,
&uart_output, 0, "UART output enabled.");
static int
rt305x_uart_probe(struct uart_bas *bas)
{
return (0);
}
static void
rt305x_uart_init(struct uart_bas *bas, int baudrate, int databits,
int stopbits, int parity)
{
#ifdef notyet
/* CLKDIV = 384000000/ 3/ 16/ br */
/* for 384MHz CLKDIV = 8000000 / baudrate; */
switch (databits) {
case 5:
databits = UART_LCR_5B;
break;
case 6:
databits = UART_LCR_6B;
break;
case 7:
databits = UART_LCR_7B;
break;
case 8:
databits = UART_LCR_8B;
break;
default:
/* Unsupported */
return;
}
switch (parity) {
case UART_PARITY_EVEN: parity = (UART_LCR_PEN|UART_LCR_EVEN); break;
case UART_PARITY_NONE: parity = (UART_LCR_PEN); break;
case UART_PARITY_ODD: parity = 0; break;
/* Unsupported */
default: return;
}
uart_setreg(bas, UART_CDDL_REG, 8000000/baudrate);
uart_barrier(bas);
uart_setreg(bas, UART_LCR_REG, databits | (stopbits==1?0:4) | parity);
uart_barrier(bas);
#endif
}
static void
rt305x_uart_term(struct uart_bas *bas)
{
uart_setreg(bas, UART_MCR_REG, 0);
uart_barrier(bas);
}
static void
rt305x_uart_putc(struct uart_bas *bas, int c)
{
char chr;
if (!uart_output) return;
chr = c;
while (!(uart_getreg(bas, UART_LSR_REG) & UART_LSR_THRE));
uart_setreg(bas, UART_TX_REG, c);
uart_barrier(bas);
while (!(uart_getreg(bas, UART_LSR_REG) & UART_LSR_THRE));
}
static int
rt305x_uart_rxready(struct uart_bas *bas)
{
#ifdef notyet
if (uart_getreg(bas, UART_LSR_REG) & UART_LSR_DR)
return (1);
return (0);
#else
return (1);
#endif
}
static int
rt305x_uart_getc(struct uart_bas *bas, struct mtx *hwmtx)
{
int c;
uart_lock(hwmtx);
while (!(uart_getreg(bas, UART_LSR_REG) & UART_LSR_DR)) {
uart_unlock(hwmtx);
DELAY(10);
uart_lock(hwmtx);
}
c = uart_getreg(bas, UART_RX_REG);
uart_unlock(hwmtx);
return (c);
}
/*
* High-level UART interface.
*/
struct rt305x_uart_softc {
struct uart_softc base;
};
static int rt305x_uart_bus_attach(struct uart_softc *);
static int rt305x_uart_bus_detach(struct uart_softc *);
static int rt305x_uart_bus_flush(struct uart_softc *, int);
static int rt305x_uart_bus_getsig(struct uart_softc *);
static int rt305x_uart_bus_ioctl(struct uart_softc *, int, intptr_t);
static int rt305x_uart_bus_ipend(struct uart_softc *);
static int rt305x_uart_bus_param(struct uart_softc *, int, int, int, int);
static int rt305x_uart_bus_probe(struct uart_softc *);
static int rt305x_uart_bus_receive(struct uart_softc *);
static int rt305x_uart_bus_setsig(struct uart_softc *, int);
static int rt305x_uart_bus_transmit(struct uart_softc *);
static kobj_method_t rt305x_uart_methods[] = {
KOBJMETHOD(uart_attach, rt305x_uart_bus_attach),
KOBJMETHOD(uart_detach, rt305x_uart_bus_detach),
KOBJMETHOD(uart_flush, rt305x_uart_bus_flush),
KOBJMETHOD(uart_getsig, rt305x_uart_bus_getsig),
KOBJMETHOD(uart_ioctl, rt305x_uart_bus_ioctl),
KOBJMETHOD(uart_ipend, rt305x_uart_bus_ipend),
KOBJMETHOD(uart_param, rt305x_uart_bus_param),
KOBJMETHOD(uart_probe, rt305x_uart_bus_probe),
KOBJMETHOD(uart_receive, rt305x_uart_bus_receive),
KOBJMETHOD(uart_setsig, rt305x_uart_bus_setsig),
KOBJMETHOD(uart_transmit, rt305x_uart_bus_transmit),
{ 0, 0 }
};
struct uart_class uart_rt305x_uart_class = {
"rt305x",
rt305x_uart_methods,
sizeof(struct rt305x_uart_softc),
.uc_ops = &uart_rt305x_uart_ops,
.uc_range = 1, /* use hinted range */
.uc_rclk = SYSTEM_CLOCK
};
#define SIGCHG(c, i, s, d) \
if (c) { \
i |= (i & s) ? s : s | d; \
} else { \
i = (i & s) ? (i & ~s) | d : i; \
}
/*
* Disable TX interrupt. uart should be locked
*/
static __inline void
rt305x_uart_disable_txintr(struct uart_softc *sc)
{
struct uart_bas *bas = &sc->sc_bas;
uint8_t cr;
cr = uart_getreg(bas, UART_IER_REG);
cr &= ~UART_IER_ETBEI;
uart_setreg(bas, UART_IER_REG, cr);
uart_barrier(bas);
}
/*
* Enable TX interrupt. uart should be locked
*/
static __inline void
rt305x_uart_enable_txintr(struct uart_softc *sc)
{
struct uart_bas *bas = &sc->sc_bas;
uint8_t cr;
cr = uart_getreg(bas, UART_IER_REG);
cr |= UART_IER_ETBEI;
uart_setreg(bas, UART_IER_REG, cr);
uart_barrier(bas);
}
static int
rt305x_uart_bus_attach(struct uart_softc *sc)
{
struct uart_bas *bas;
struct uart_devinfo *di;
bas = &sc->sc_bas;
if (sc->sc_sysdev != NULL) {
di = sc->sc_sysdev;
rt305x_uart_init(bas, di->baudrate, di->databits, di->stopbits,
di->parity);
} else {
rt305x_uart_init(bas, 115200, 8, 1, 0);
}
sc->sc_rxfifosz = 16;
sc->sc_txfifosz = 16;
(void)rt305x_uart_bus_getsig(sc);
/* Enable FIFO */
uart_setreg(bas, UART_FCR_REG,
uart_getreg(bas, UART_FCR_REG) |
UART_FCR_FIFOEN | UART_FCR_TXTGR_1 | UART_FCR_RXTGR_1);
uart_barrier(bas);
/* Enable interrupts */
uart_setreg(bas, UART_IER_REG,
UART_IER_EDSSI | UART_IER_ELSI | UART_IER_ERBFI);
uart_barrier(bas);
return (0);
}
static int
rt305x_uart_bus_detach(struct uart_softc *sc)
{
return (0);
}
static int
rt305x_uart_bus_flush(struct uart_softc *sc, int what)
{
struct uart_bas *bas = &sc->sc_bas;
uint32_t fcr = uart_getreg(bas, UART_FCR_REG);
if (what & UART_FLUSH_TRANSMITTER) {
uart_setreg(bas, UART_FCR_REG, fcr|UART_FCR_TXRST);
uart_barrier(bas);
}
if (what & UART_FLUSH_RECEIVER) {
uart_setreg(bas, UART_FCR_REG, fcr|UART_FCR_RXRST);
uart_barrier(bas);
}
uart_setreg(bas, UART_FCR_REG, fcr);
uart_barrier(bas);
return (0);
}
static int
rt305x_uart_bus_getsig(struct uart_softc *sc)
{
uint32_t new, old, sig;
uint8_t bes;
do {
old = sc->sc_hwsig;
sig = old;
uart_lock(sc->sc_hwmtx);
bes = uart_getreg(&sc->sc_bas, UART_MSR_REG);
uart_unlock(sc->sc_hwmtx);
/* XXX: chip can show delta */
SIGCHG(bes & UART_MSR_CTS, sig, SER_CTS, SER_DCTS);
SIGCHG(bes & UART_MSR_DCD, sig, SER_DCD, SER_DDCD);
SIGCHG(bes & UART_MSR_DSR, sig, SER_DSR, SER_DDSR);
new = sig & ~SER_MASK_DELTA;
} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
return (sig);
}
static int
rt305x_uart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
{
struct uart_bas *bas;
int baudrate, divisor, error;
bas = &sc->sc_bas;
error = 0;
uart_lock(sc->sc_hwmtx);
switch (request) {
case UART_IOCTL_BREAK:
/* TODO: Send BREAK */
break;
case UART_IOCTL_BAUD:
divisor = uart_getreg(bas, UART_CDDL_REG);
baudrate = bas->rclk / (divisor * 16);
*(int*)data = baudrate;
break;
default:
error = EINVAL;
break;
}
uart_unlock(sc->sc_hwmtx);
return (error);
}
static int
rt305x_uart_bus_ipend(struct uart_softc *sc)
{
struct uart_bas *bas;
int ipend;
uint8_t iir, lsr, msr;
bas = &sc->sc_bas;
ipend = 0;
uart_lock(sc->sc_hwmtx);
iir = uart_getreg(&sc->sc_bas, UART_IIR_REG);
lsr = uart_getreg(&sc->sc_bas, UART_LSR_REG);
uart_setreg(&sc->sc_bas, UART_LSR_REG, lsr);
msr = uart_getreg(&sc->sc_bas, UART_MSR_REG);
uart_setreg(&sc->sc_bas, UART_MSR_REG, msr);
if (iir & UART_IIR_INTP) {
uart_unlock(sc->sc_hwmtx);
return (0);
}
switch ((iir >> 1) & 0x07) {
case UART_IIR_ID_THRE:
ipend |= SER_INT_TXIDLE;
break;
case UART_IIR_ID_DR2:
rt305x_uart_bus_flush(sc, UART_FLUSH_RECEIVER);
/* passthrough */
case UART_IIR_ID_DR:
ipend |= SER_INT_RXREADY;
break;
case UART_IIR_ID_MST:
case UART_IIR_ID_LINESTATUS:
ipend |= SER_INT_SIGCHG;
if (lsr & UART_LSR_BI)
{
ipend |= SER_INT_BREAK;
#ifdef KDB
breakpoint();
#endif
}
if (lsr & UART_LSR_OE)
ipend |= SER_INT_OVERRUN;
break;
default:
/* XXX: maybe return error here */
break;
}
uart_unlock(sc->sc_hwmtx);
return (ipend);
}
static int
rt305x_uart_bus_param(struct uart_softc *sc, int baudrate, int databits,
int stopbits, int parity)
{
uart_lock(sc->sc_hwmtx);
rt305x_uart_init(&sc->sc_bas, baudrate, databits, stopbits, parity);
uart_unlock(sc->sc_hwmtx);
return (0);
}
static int
rt305x_uart_bus_probe(struct uart_softc *sc)
{
char buf[80];
int error;
error = rt305x_uart_probe(&sc->sc_bas);
if (error)
return (error);
snprintf(buf, sizeof(buf), "rt305x_uart");
device_set_desc_copy(sc->sc_dev, buf);
return (0);
}
static int
rt305x_uart_bus_receive(struct uart_softc *sc)
{
struct uart_bas *bas;
int xc;
uint8_t lsr;
bas = &sc->sc_bas;
uart_lock(sc->sc_hwmtx);
lsr = uart_getreg(bas, UART_LSR_REG);
while ((lsr & UART_LSR_DR)) {
if (uart_rx_full(sc)) {
sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
break;
}
xc = 0;
xc = uart_getreg(bas, UART_RX_REG);
if (lsr & UART_LSR_FE)
xc |= UART_STAT_FRAMERR;
if (lsr & UART_LSR_PE)
xc |= UART_STAT_PARERR;
if (lsr & UART_LSR_OE)
xc |= UART_STAT_OVERRUN;
uart_barrier(bas);
uart_rx_put(sc, xc);
lsr = uart_getreg(bas, UART_LSR_REG);
}
uart_unlock(sc->sc_hwmtx);
return (0);
}
static int
rt305x_uart_bus_setsig(struct uart_softc *sc, int sig)
{
/* TODO: implement (?) */
return (0);
}
static int
rt305x_uart_bus_transmit(struct uart_softc *sc)
{
struct uart_bas *bas = &sc->sc_bas;
int i;
if (!uart_output) return (0);
bas = &sc->sc_bas;
uart_lock(sc->sc_hwmtx);
while ((uart_getreg(bas, UART_LSR_REG) & UART_LSR_THRE) == 0)
;
rt305x_uart_enable_txintr(sc);
for (i = 0; i < sc->sc_txdatasz; i++) {
uart_setreg(bas, UART_TX_REG, sc->sc_txbuf[i]);
uart_barrier(bas);
}
sc->sc_txbusy = 1;
uart_unlock(sc->sc_hwmtx);
return (0);
}

View File

@ -0,0 +1,126 @@
/*-
* Copyright (c) 2010 Aleksandr Rybalko.
* 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. The names of the authors may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _RT305XUART_H
#define _RT305XUART_H
#undef uart_getreg
#undef uart_setreg
#define uart_getreg(bas, reg) \
bus_space_read_4((bas)->bst, (bas)->bsh, reg)
#define uart_setreg(bas, reg, value) \
bus_space_write_4((bas)->bst, (bas)->bsh, reg, value)
/* UART registers */
#define UART_RX_REG 0x00
#define UART_TX_REG 0x04
#define UART_IER_REG 0x08
#define UART_IER_EDSSI (1<<3) /* Only full UART */
#define UART_IER_ELSI (1<<2)
#define UART_IER_ETBEI (1<<1)
#define UART_IER_ERBFI (1<<0)
#define UART_IIR_REG 0x0c
#define UART_IIR_RXFIFO (1<<7)
#define UART_IIR_TXFIFO (1<<6)
#define UART_IIR_ID_MST 0
#define UART_IIR_ID_THRE 1
#define UART_IIR_ID_DR 2
#define UART_IIR_ID_LINESTATUS 3
#define UART_IIR_ID_DR2 6
#define UART_IIR_ID_SHIFT 1
#define UART_IIR_ID_MASK 0x0000000e
#define UART_IIR_INTP (1<<0)
#define UART_FCR_REG 0x10
#define UART_FCR_RXTGR_1 (0<<6)
#define UART_FCR_RXTGR_4 (1<<6)
#define UART_FCR_RXTGR_8 (2<<6)
#define UART_FCR_RXTGR_12 (3<<6)
#define UART_FCR_TXTGR_1 (0<<4)
#define UART_FCR_TXTGR_4 (1<<4)
#define UART_FCR_TXTGR_8 (2<<4)
#define UART_FCR_TXTGR_12 (3<<4)
#define UART_FCR_DMA (1<<3)
#define UART_FCR_TXRST (1<<2)
#define UART_FCR_RXRST (1<<1)
#define UART_FCR_FIFOEN (1<<0)
#define UART_LCR_REG 0x14
#define UART_LCR_DLAB (1<<7)
#define UART_LCR_BRK (1<<6)
#define UART_LCR_FPAR (1<<5)
#define UART_LCR_EVEN (1<<4)
#define UART_LCR_PEN (1<<3)
#define UART_LCR_STB_15 (1<<2)
#define UART_LCR_5B 0
#define UART_LCR_6B 1
#define UART_LCR_7B 2
#define UART_LCR_8B 3
#define UART_MCR_REG 0x18
#define UART_MCR_LOOP (1<<4)
#define UART_MCR_OUT2_L (1<<3) /* Only full UART */
#define UART_MCR_OUT1_L (1<<2) /* Only full UART */
#define UART_MCR_RTS_L (1<<1) /* Only full UART */
#define UART_MCR_DTR_L (1<<0) /* Only full UART */
#define UART_LSR_REG 0x1c
#define UART_LSR_ERINF (1<<7)
#define UART_LSR_TEMT (1<<6)
#define UART_LSR_THRE (1<<5)
#define UART_LSR_BI (1<<4)
#define UART_LSR_FE (1<<3)
#define UART_LSR_PE (1<<2)
#define UART_LSR_OE (1<<1)
#define UART_LSR_DR (1<<0)
#define UART_MSR_REG 0x20 /* Only full UART */
#define UART_MSR_DCD (1<<7) /* Only full UART */
#define UART_MSR_RI (1<<6) /* Only full UART */
#define UART_MSR_DSR (1<<5) /* Only full UART */
#define UART_MSR_CTS (1<<4) /* Only full UART */
#define UART_MSR_DDCD (1<<3) /* Only full UART */
#define UART_MSR_TERI (1<<2) /* Only full UART */
#define UART_MSR_DDSR (1<<1) /* Only full UART */
#define UART_MSR_DCTS (1<<0) /* Only full UART */
#define UART_CDDL_REG 0x28
#define UART_CDDLL_REG 0x2c
#define UART_CDDLH_REG 0x30
#define UART_IFCTL_REG 0x34
#define UART_IFCTL_IFCTL (1<<0)
int uart_cnattach(void);
#endif /* _RT305XUART_H */