summaryrefslogtreecommitdiffstats
path: root/sys/mips
diff options
context:
space:
mode:
authoradrian <adrian@FreeBSD.org>2011-04-03 14:39:55 +0000
committeradrian <adrian@FreeBSD.org>2011-04-03 14:39:55 +0000
commit61d2d8df78a6c6c7bb247c3b7bf476a582353076 (patch)
treef957f43b8c7b23471ccb48b181d64c4ed2469bb0 /sys/mips
parentda1c5bb338f5a97dfcde8d738f3df9d9977baa57 (diff)
downloadFreeBSD-src-61d2d8df78a6c6c7bb247c3b7bf476a582353076.zip
FreeBSD-src-61d2d8df78a6c6c7bb247c3b7bf476a582353076.tar.gz
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>
Diffstat (limited to 'sys/mips')
-rw-r--r--sys/mips/conf/RT305X134
-rw-r--r--sys/mips/conf/RT305X.hints136
-rw-r--r--sys/mips/rt305x/files.rt305x13
-rw-r--r--sys/mips/rt305x/obio.c627
-rw-r--r--sys/mips/rt305x/obiovar.h58
-rw-r--r--sys/mips/rt305x/rt305x_dotg.c247
-rw-r--r--sys/mips/rt305x/rt305x_gpio.c619
-rw-r--r--sys/mips/rt305x/rt305x_gpio.h111
-rw-r--r--sys/mips/rt305x/rt305x_gpiovar.h48
-rw-r--r--sys/mips/rt305x/rt305x_ic.c141
-rw-r--r--sys/mips/rt305x/rt305x_icvar.h42
-rw-r--r--sys/mips/rt305x/rt305x_machdep.c217
-rw-r--r--sys/mips/rt305x/rt305x_sysctl.c240
-rw-r--r--sys/mips/rt305x/rt305x_sysctlvar.h45
-rw-r--r--sys/mips/rt305x/rt305xreg.h368
-rw-r--r--sys/mips/rt305x/rt_swreg.h160
-rw-r--r--sys/mips/rt305x/std.rt305x8
-rw-r--r--sys/mips/rt305x/uart_bus_rt305x.c102
-rw-r--r--sys/mips/rt305x/uart_cpu_rt305x.c82
-rw-r--r--sys/mips/rt305x/uart_dev_rt305x.c507
-rw-r--r--sys/mips/rt305x/uart_dev_rt305x.h126
21 files changed, 4031 insertions, 0 deletions
diff --git a/sys/mips/conf/RT305X b/sys/mips/conf/RT305X
new file mode 100644
index 0000000..50ed9c4
--- /dev/null
+++ b/sys/mips/conf/RT305X
@@ -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
+
+
diff --git a/sys/mips/conf/RT305X.hints b/sys/mips/conf/RT305X.hints
new file mode 100644
index 0000000..3c8b6cb
--- /dev/null
+++ b/sys/mips/conf/RT305X.hints
@@ -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
+
diff --git a/sys/mips/rt305x/files.rt305x b/sys/mips/rt305x/files.rt305x
new file mode 100644
index 0000000..caf4c3d
--- /dev/null
+++ b/sys/mips/rt305x/files.rt305x
@@ -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
diff --git a/sys/mips/rt305x/obio.c b/sys/mips/rt305x/obio.c
new file mode 100644
index 0000000..870afea
--- /dev/null
+++ b/sys/mips/rt305x/obio.c
@@ -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);
diff --git a/sys/mips/rt305x/obiovar.h b/sys/mips/rt305x/obiovar.h
new file mode 100644
index 0000000..e1742e8
--- /dev/null
+++ b/sys/mips/rt305x/obiovar.h
@@ -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_ */
diff --git a/sys/mips/rt305x/rt305x_dotg.c b/sys/mips/rt305x/rt305x_dotg.c
new file mode 100644
index 0000000..32ebbfe
--- /dev/null
+++ b/sys/mips/rt305x/rt305x_dotg.c
@@ -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);
diff --git a/sys/mips/rt305x/rt305x_gpio.c b/sys/mips/rt305x/rt305x_gpio.c
new file mode 100644
index 0000000..a570889
--- /dev/null
+++ b/sys/mips/rt305x/rt305x_gpio.c
@@ -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);
diff --git a/sys/mips/rt305x/rt305x_gpio.h b/sys/mips/rt305x/rt305x_gpio.h
new file mode 100644
index 0000000..8ce3ab5
--- /dev/null
+++ b/sys/mips/rt305x/rt305x_gpio.h
@@ -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_ */
+
diff --git a/sys/mips/rt305x/rt305x_gpiovar.h b/sys/mips/rt305x/rt305x_gpiovar.h
new file mode 100644
index 0000000..ed79e2d
--- /dev/null
+++ b/sys/mips/rt305x/rt305x_gpiovar.h
@@ -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_ */
+
+
diff --git a/sys/mips/rt305x/rt305x_ic.c b/sys/mips/rt305x/rt305x_ic.c
new file mode 100644
index 0000000..8bddd41
--- /dev/null
+++ b/sys/mips/rt305x/rt305x_ic.c
@@ -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);
diff --git a/sys/mips/rt305x/rt305x_icvar.h b/sys/mips/rt305x/rt305x_icvar.h
new file mode 100644
index 0000000..4d969c8
--- /dev/null
+++ b/sys/mips/rt305x/rt305x_icvar.h
@@ -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_ */
+
diff --git a/sys/mips/rt305x/rt305x_machdep.c b/sys/mips/rt305x/rt305x_machdep.c
new file mode 100644
index 0000000..a388b4f
--- /dev/null
+++ b/sys/mips/rt305x/rt305x_machdep.c
@@ -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);
+}
diff --git a/sys/mips/rt305x/rt305x_sysctl.c b/sys/mips/rt305x/rt305x_sysctl.c
new file mode 100644
index 0000000..7a3b0c2
--- /dev/null
+++ b/sys/mips/rt305x/rt305x_sysctl.c
@@ -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);
diff --git a/sys/mips/rt305x/rt305x_sysctlvar.h b/sys/mips/rt305x/rt305x_sysctlvar.h
new file mode 100644
index 0000000..91a5282
--- /dev/null
+++ b/sys/mips/rt305x/rt305x_sysctlvar.h
@@ -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_ */
+
diff --git a/sys/mips/rt305x/rt305xreg.h b/sys/mips/rt305x/rt305xreg.h
new file mode 100644
index 0000000..42a6c86
--- /dev/null
+++ b/sys/mips/rt305x/rt305xreg.h
@@ -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_ */
diff --git a/sys/mips/rt305x/rt_swreg.h b/sys/mips/rt305x/rt_swreg.h
new file mode 100644
index 0000000..ab382b9
--- /dev/null
+++ b/sys/mips/rt305x/rt_swreg.h
@@ -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_ */
diff --git a/sys/mips/rt305x/std.rt305x b/sys/mips/rt305x/std.rt305x
new file mode 100644
index 0000000..6c56e15
--- /dev/null
+++ b/sys/mips/rt305x/std.rt305x
@@ -0,0 +1,8 @@
+# $FreeBSD$
+# Standard include file for RT305XF SoC
+
+files "../rt305x/files.rt305x"
+
+cpu CPU_MIPS4KC
+options ISA_MIPS32
+
diff --git a/sys/mips/rt305x/uart_bus_rt305x.c b/sys/mips/rt305x/uart_bus_rt305x.c
new file mode 100644
index 0000000..9cd1df7
--- /dev/null
+++ b/sys/mips/rt305x/uart_bus_rt305x.c
@@ -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);
+
diff --git a/sys/mips/rt305x/uart_cpu_rt305x.c b/sys/mips/rt305x/uart_cpu_rt305x.c
new file mode 100644
index 0000000..b9225a1
--- /dev/null
+++ b/sys/mips/rt305x/uart_cpu_rt305x.c
@@ -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);
+}
diff --git a/sys/mips/rt305x/uart_dev_rt305x.c b/sys/mips/rt305x/uart_dev_rt305x.c
new file mode 100644
index 0000000..677c0c6
--- /dev/null
+++ b/sys/mips/rt305x/uart_dev_rt305x.c
@@ -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);
+}
diff --git a/sys/mips/rt305x/uart_dev_rt305x.h b/sys/mips/rt305x/uart_dev_rt305x.h
new file mode 100644
index 0000000..c24b339
--- /dev/null
+++ b/sys/mips/rt305x/uart_dev_rt305x.h
@@ -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 */
OpenPOWER on IntegriCloud