diff --git a/rescue/list b/rescue/list
index aab8604..fbd3673 100644
--- a/rescue/list
+++ b/rescue/list
@@ -148,4 +148,4 @@ SRCDIRS	libexec
 PROG	lfs_cleanerd
 
 LIBS	liboverride.o
-LIBS	-lbz2 -llzma -lcrypt -ledit -lipsec -lkvm -ll -lm -lrmt -lcurses -lterminfo -lutil -lz -levent -lprop
+LIBS	-lc -lbz2 -llzma -lcrypt -ledit -lipsec -lkvm -ll -lm -lrmt -lcurses -lterminfo -lutil -lz -levent -lprop
diff --git a/sys/arch/evbmips/conf/Makefile.evbmips.inc b/sys/arch/evbmips/conf/Makefile.evbmips.inc
index 15d4234..8683780 100644
--- a/sys/arch/evbmips/conf/Makefile.evbmips.inc
+++ b/sys/arch/evbmips/conf/Makefile.evbmips.inc
@@ -4,3 +4,7 @@ SYSTEM_LD_TAIL_EXTRA=; \
 	echo ${STRIP} -O srec -o $@.srec $@; \
 	${STRIP} -O srec -o $@.srec $@
 EXTRA_KERNELS+= ${KERNELS:@.KERNEL.@${.KERNEL.}.srec@}
+
+.if defined(BOARDMKFRAG)
+.include "${BOARDMKFRAG}"
+.endif
diff --git a/sys/arch/evbmips/conf/PAVO b/sys/arch/evbmips/conf/PAVO
new file mode 100644
index 0000000..760cc7a
--- /dev/null
+++ b/sys/arch/evbmips/conf/PAVO
@@ -0,0 +1,278 @@
+#	$NetBSD: $
+
+include 	"arch/evbmips/conf/std.pavo"
+
+#options 	INCLUDE_CONFIG_FILE	# embed config file in kernel binary
+
+#ident 		"PAVO-$Revision: $"
+
+maxusers	32
+
+makeoptions	COPTS="-Os"
+
+options 	MIPS32
+options 	NOFPU		# No FPU
+#options 	FPEMUL		# emulate FPU insn
+
+options		JZ4740
+options		MIPS_PAVO
+options		JZ_EXTAL=12000000	# 12Mhz extal clock in PAVO board
+options		MEMSIZE=64		# RAM memory size in megabytes
+
+# Options for necessary to use MD
+options 	MEMORY_DISK_HOOKS
+options 	MEMORY_DISK_IS_ROOT		# force root on memory disk
+options 	MEMORY_DISK_SERVER=1		# no userspace memory disk support
+options 	MEMORY_DISK_ROOT_SIZE=5120	# size of memory disk, in blocks
+#options 	MEMORY_DISK_ROOT_SIZE=16384	# size of memory disk, in blocks
+
+# Standard system options
+options 	KTRACE		# system call tracing support
+options 	SYSVMSG		# System V message queues
+options 	SYSVSEM		# System V semaphores
+options 	SYSVSHM		# System V shared memory
+
+options		RTC_OFFSET=0	# hardware clock is this many mins. west of GMT
+#options 	NTP		# network time protocol
+
+# Debugging options
+#options 	DIAGNOSTIC		# extra kernel sanity checking
+#options	PARANOIA
+#options 	DEBUG			# extra kernel debugging support
+#makeoptions 	DEBUG="-g3 -ggdb"	# compile full symbol table
+#options	PMAP_DEBUG		# enable pmap_debug_level code
+#options 	SYSCALL_DEBUG		# symbolic syscall names
+#options 	KMEMSTATS		# kernel memory statistics (vmstat -m)
+options 	USERCONF		# userconf(4) support
+#options 	SYSCTL_INCLUDE_DESCR	# Include sysctl descriptions in kernel
+options 	DDB			# kernel dynamic debugger
+options 	DDB_HISTORY_SIZE=100 	# enable history editing in DDB
+options 	SYMTAB_SPACE=430000	# size for embedded symbol table
+
+# Compatibility options
+#options 	COMPAT_43	# compatibility with 4.3BSD binaries
+#options 	COMPAT_09	# NetBSD 0.9 binary compatibility
+#options 	COMPAT_10	# NetBSD 1.0 binary compatibility
+#options 	COMPAT_11	# NetBSD 1.1 binary compatibility
+#options 	COMPAT_12	# NetBSD 1.2 binary compatibility
+#options 	COMPAT_13	# NetBSD 1.3 binary compatibility
+#options 	COMPAT_14	# NetBSD 1.4 binary compatibility
+#options 	COMPAT_15	# NetBSD 1.5 binary compatibility
+#options 	COMPAT_16	# NetBSD 1.6 binary compatibility
+#options 	COMPAT_20	# NetBSD 2.0 binary compatibility
+#options 	COMPAT_30	# NetBSD 3.0 compatibility.
+#options 	COMPAT_40	# NetBSD 4.0 compatibility.
+#options 	COMPAT_50	# NetBSD 5.0 compatibility.
+#options 	EXEC_ECOFF	# exec ECOFF binaries
+#options 	COMPAT_ULTRIX	# binary compatibility with Ultrix
+options 	COMPAT_BSDPTY	# /dev/[pt]ty?? ptys.
+
+# File systems
+file-system	FFS		# Berkeley Fast Filesystem
+#file-system	MFS		# memory-based filesystem
+#file-system 	EXT2FS		# second extended file system (linux)
+#file-system	NFS		# Sun NFS-compatible filesystem client
+file-system	KERNFS		# kernel data-structure filesystem
+#file-system	NULLFS		# NULL layered filesystem
+#file-system 	OVERLAY		# overlay file system
+#file-system	FDESC		# user file descriptor filesystem
+#file-system	UMAPFS		# uid/gid remapping filesystem
+#file-system	LFS		# Log-based filesystem (still experimental)
+file-system	PROCFS		# /proc
+#file-system	CD9660		# ISO 9660 + Rock Ridge file system
+file-system	TMPFS		# Efficient memory file system
+#file-system	UNION		# union file system
+#file-system	MSDOSFS		# MS-DOS FAT filesystem(s).
+#file-system 	CODA		# Coda File System; also needs vcoda (below)
+#file-system	PTYFS		# /dev/pts/N support
+
+# File system options
+#options 	NFSSERVER	# Sun NFS-compatible filesystem server
+#options 	QUOTA		# legacy UFS quotas
+#options 	QUOTA2		# new, in-filesystem UFS quotas
+#options 	FFS_EI		# FFS Endian Independant support
+#options 	WAPBL		# File system journaling support - Experimental
+options 	FFS_NO_SNAPSHOT	# No FFS snapshot support
+#options 	EXT2FS_SYSTEM_FLAGS # makes ext2fs file flags (append and
+				# immutable) behave as system flags.
+
+# Networking options
+#options 	GATEWAY		# IP packet forwarding
+options 	INET		# Internet protocols
+#options 	INET6		# IPV6
+#options 	IPSEC		# IP security
+#options 	IPSEC_ESP	# IP security (encryption part; define w/IPSEC)
+#options 	IPSEC_NAT_T	# IPsec NAT traversal (NAT-T)
+#options 	IPSEC_DEBUG	# debug for IP security
+#options 	MROUTING	# packet forwarding of multicast packets
+#options 	PIM		# Protocol Independent Multicast
+#options 	ISO,TPIP	# OSI networking
+#options 	EON		# OSI tunneling over IP
+#options 	NETATALK	# AppleTalk (over Ethernet) protocol
+#options 	PPP_BSDCOMP	# BSD-Compress compression support for PPP
+#options 	PPP_DEFLATE	# Deflate compression support for PPP
+#options 	PPP_FILTER	# Active filter support for PPP (requires bpf)
+#options 	PFIL_HOOKS	# pfil(9) packet filter hooks
+#options 	IPFILTER_LOG	# ipmon(8) log support
+#options 	IPFILTER_LOOKUP	# ippool(8) support
+#options 	IPFILTER_COMPAT # Compat for IP-Filter
+#options 	IPFILTER_DEFAULT_BLOCK	# block all packets by default
+
+# Compatibility with 4.2BSD implementation of TCP/IP.  Not recommended.
+#options 	TCP_COMPAT_42
+
+# These options enable verbose messages for several subsystems.
+# Warning, these may compile large string tables into the kernel!
+#options 	MIIVERBOSE	# verbose PHY autoconfig messages
+
+options 	NFS_BOOT_DHCP
+
+config		netbsd	root on ? type ?
+
+# The main bus device
+mainbus0 	at root
+
+# XBurst CPU core
+cpu0 		at mainbus0
+
+# JzRISC AHB/ABP bus
+jzbus0	        at mainbus0
+
+# Watchdog timer
+wdog0		at mainbus0
+
+# Power Management Unit
+jzpm0		at jzbus0 addr 0x10000000 size 0x80
+
+# Interrupt controller
+#jzicu0		at jzbus0 addr ? size ?
+
+# On-Chip timers
+jztcu0		at jzbus0 addr 0x10002000 size 0xc0
+jztimer0	at jztcu0 intr 23 function ?
+jztimer1	at jztcu0 intr 22 function ?
+jztimer2	at jztcu0 intr 21 function ?
+
+# On-board 16550 UART(s)
+com*		at jzbus0 addr 0x10030000 size 0x3030 intr 9
+options		CONSPEED=115200
+
+# Real Time Clock
+jzrtc*		at jzbus0 addr 0x10003000 size 0x10
+
+# Framebuffer
+#jzfb*		at jzbus0 addr 0x13050000 size 0x60
+
+# make sure the console display is always wsdisplay0
+#wsdisplay0	at wsemuldisplaydev? console 1
+#wsdisplay*	at wsemuldisplaydev?
+#wsdisplay*	at jzfb? console ?
+
+# various options for wscons - we try to look as much like a standard
+# sun console as possible
+options 	WSEMUL_VT100		# sun terminal emulation
+options 	WS_DEFAULT_FG=WSCOL_LIGHT_WHITE
+options 	WS_DEFAULT_BG=WSCOL_BLACK
+options		WS_KERNEL_FG=WSCOL_GREEN
+options		WS_KERNEL_BG=WSCOL_BLACK
+options 	WSDISPLAY_COMPAT_USL		# VT handling
+options 	WSDISPLAY_COMPAT_RAWKBD		# can get raw scancodes
+options 	WSDISPLAY_DEFAULTSCREENS=4
+#options	FONT_VT220L8x8
+#options	FONT_VT220L8x10
+options		FONT_VT220L8x16
+#options	FONT_QVSS8x15
+
+#pseudo-device	wsmux			# mouse & keyboard multiplexor
+#pseudo-device	wsfont
+
+# wscons
+#wsdisplay*	at vga? console ?
+#pckbc*		at isa?				# PC keyboard controller
+#pckbd*		at pckbc?			# PC keyboard (kbd port)
+#pms*		at pckbc?			# PS/2-style mouse (aux port)
+#wskbd*		at pckbd?
+#wsmouse*	at pms?
+
+# MII/PHY support
+#acphy*		at mii? phy ?		# DAltima AC101 and AMD Am79c874 PHYs
+#amhphy* 	at mii? phy ?		# AMD 79c901 Ethernet PHYs
+#bmtphy* 	at mii? phy ?		# Broadcom BCM5201 and BCM5202 PHYs
+#brgphy* 	at mii? phy ?		# Broadcom BCM5400-family PHYs
+#dmphy*		at mii? phy ?		# Davicom DM9101 PHYs
+#exphy*		at mii? phy ?		# 3Com internal PHYs
+#glxtphy*	at mii? phy ?		# Level One LXT-1000 PHYs
+#gphyter*	at mii? phy ?		# NS83861 Gig-E PHY
+#icsphy* 	at mii? phy ?		# Integrated Circuit Systems ICS1890
+#inphy*		at mii? phy ?		# Intel 82555 PHYs
+#iophy*		at mii? phy ?		# Intel 82553 PHYs
+#lxtphy* 	at mii? phy ?		# Level One LXT-970 PHYs
+#makphy* 	at mii? phy ?		# Marvell Semiconductor 88E1000 PHYs
+#nsphy*		at mii? phy ?		# NS83840 PHYs
+#nsphyter*	at mii? phy ?		# NS83843 PHYs
+#pnaphy* 	at mii? phy ?		# generic HomePNA PHYs
+#qsphy*		at mii? phy ?		# Quality Semiconductor QS6612 PHYs
+#sqphy*		at mii? phy ?		# Seeq 80220/80221/80223 PHYs
+#tlphy*		at mii? phy ?		# ThunderLAN PHYs
+#tqphy*		at mii? phy ?		# TDK Semiconductor PHYs
+#ukphy*		at mii? phy ?		# generic unknown PHYs
+
+
+# USB
+#ohci*		at pci? dev ? function ?	# USB Open Host Controller
+#uhci*		at pci? dev ? function ?	# USB Univ. Host Controller
+
+# USB bus support
+#usb*		at uhci?
+#usb*		at ohci?
+
+# USB Hubs
+#uhub*		at usb?
+#uhub*		at uhub? port ?
+
+# ....
+
+# USB Generic driver
+#ugen*		at uhub? port ?
+
+# Audio Devices
+
+# Audio support
+#audio*		at clct?
+
+# Pseudo-devices
+
+# Disk/mass storage pseudo-devices
+#pseudo-device	ccd		4		# concatenated disk devices
+#pseudo-device	raid		4		# RAIDframe disk driver
+#options 	RAID_AUTOCONFIG			# auto-configuration of RAID
+#pseudo-device	fss				# file system snapshot device
+pseudo-device	md				# memory disk device (ramdisk)
+#pseudo-device	vnd				# disk-like interface to files
+
+# Network pseudo-devices
+#pseudo-device	bpfilter			# Berkeley packet filter
+#pseudo-device	ipfilter			# IP filter (firewall) and NAT
+pseudo-device	loop				# network loopback
+#pseudo-device	ppp				# Point-to-Point Protocol
+#pseudo-device	sl				# Serial Line IP
+#pseudo-device	strip				# Starmode Radio IP (Metricom)
+#pseudo-device	tun				# network tunneling over tty
+#pseudo-device	tap				# virtual Ethernet
+#pseudo-device	gre				# generic L3 over IP tunnel
+#pseudo-device	ipip		2		# RFC 2003 IP Encapsulation
+#pseudo-device	gif				# RFC1933 tunnel
+#pseudo-device	faith				# IPv[46] tcp relay translation
+#pseudo-device	stf				# 6to4 IPv6 over IPv4 encapsulation
+#pseudo-device	vlan				# IEEE 802.1q encapsulation
+#pseudo-device	bridge				# simple inter-network bridging
+
+# Miscellaneous pseudo-devices
+pseudo-device	pty				# pseudo-terminals
+#pseudo-device	sequencer	1		# MIDI sequencer
+pseudo-device	rnd				# /dev/random & kernel generator
+pseudo-device	clockctl			# user control of clock subsystem
+pseudo-device	ksyms				# /dev/ksyms
+
+# A pseudo device needed for Coda		# also needs CODA (above)
+#pseudo-device	vcoda		4		# coda minicache <-> venus comm.
diff --git a/sys/arch/evbmips/conf/PAVO_DEBUG b/sys/arch/evbmips/conf/PAVO_DEBUG
new file mode 100644
index 0000000..f225924
--- /dev/null
+++ b/sys/arch/evbmips/conf/PAVO_DEBUG
@@ -0,0 +1,10 @@
+#	$NetBSD: $
+
+include		"arch/evbmips/conf/PAVO"
+
+options 	DIAGNOSTIC		# extra kernel sanity checking
+options		PARANOIA
+options 	DEBUG			# extra kernel debugging support
+makeoptions 	DEBUG="-g3 -ggdb"	# compile full symbol table
+options		PMAP_DEBUG		# enable pmap_debug_level code
+#options 	SYSCALL_DEBUG		# symbolic syscall names
diff --git a/sys/arch/evbmips/conf/files.pavo b/sys/arch/evbmips/conf/files.pavo
new file mode 100644
index 0000000..6d39425
--- /dev/null
+++ b/sys/arch/evbmips/conf/files.pavo
@@ -0,0 +1,34 @@
+#	$NetBSD: $
+
+file	arch/evbmips/ingenic/autoconf.c
+file	arch/evbmips/ingenic/machdep.c
+file	arch/evbmips/ingenic/interrupt.c
+
+file	arch/mips/mips/bus_dma.c
+
+# System bus
+device	mainbus { }
+attach	mainbus at root
+file	arch/evbmips/ingenic/mainbus.c	mainbus
+
+# CPU
+device	cpu
+attach	cpu at mainbus
+file	arch/evbmips/evbmips/cpu.c		cpu
+
+# Watchdog
+device	wdog: sysmon_wdog
+attach	wdog at mainbus
+file	arch/evbmips/ingenic/wdog.c		wdog
+
+# Machine-independent I2O drivers.
+#include "dev/i2o/files.i2o"
+
+# Machine-independent PC-style keyboard controller drivers
+#include "dev/pckbport/files.pckbport"
+
+# Machine-independent USB device support
+#include "dev/usb/files.usb"
+
+# Memory Disk
+file	dev/md_root.c				memory_disk_hooks
diff --git a/sys/arch/evbmips/conf/mk.pavo b/sys/arch/evbmips/conf/mk.pavo
new file mode 100644
index 0000000..9a43e3c
--- /dev/null
+++ b/sys/arch/evbmips/conf/mk.pavo
@@ -0,0 +1,24 @@
+#	$NetBSD: $
+
+_OSRELEASE !=	${HOST_SH} $S/conf/osrelease.sh
+
+MKUBOOTIMAGEARGS=	-A mips -T kernel
+MKUBOOTIMAGEARGS+=	-a $(DEFTEXTADDR)
+MKUBOOTIMAGEARGS+=	-n "NetBSD/$(BOARDTYPE) $(_OSRELEASE)"
+MKUBOOTIMAGEARGS_NONE=	${MKUBOOTIMAGEARGS} -C none
+MKUBOOTIMAGEARGS_GZ=	${MKUBOOTIMAGEARGS} -C gz
+
+SYSTEM_LD_TAIL_EXTRA+=; \
+	echo ${OBJCOPY} -S -O binary $@ $@.bin; \
+	${OBJCOPY} -S -O binary $@ $@.bin; \
+	echo ${TOOL_MKUBOOTIMAGE} ${MKUBOOTIMAGEARGS_NONE} $@.bin $@.ub; \
+	${TOOL_MKUBOOTIMAGE} ${MKUBOOTIMAGEARGS_NONE} $@.bin $@.ub; \
+	echo gzip -c $@.bin > $@.bin.gz; \
+	gzip -c $@.bin > $@.bin.gz; \
+	echo ${TOOL_MKUBOOTIMAGE} ${MKUBOOTIMAGEARGS_GZ} $@.bin.gz $@.bz.ub; \
+	${TOOL_MKUBOOTIMAGE} ${MKUBOOTIMAGEARGS_GZ} $@.bin.gz $@.gz.ub
+
+EXTRA_KERNELS+=	${KERNELS:@.KERNEL.@${.KERNEL.}.bin@}
+EXTRA_KERNELS+=	${KERNELS:@.KERNEL.@${.KERNEL.}.bin.gz@}
+EXTRA_KERNELS+=	${KERNELS:@.KERNEL.@${.KERNEL.}.ub@}
+EXTRA_KERNELS+=	${KERNELS:@.KERNEL.@${.KERNEL.}.ub.gz@}
diff --git a/sys/arch/evbmips/conf/std.pavo b/sys/arch/evbmips/conf/std.pavo
new file mode 100644
index 0000000..d561990
--- /dev/null
+++ b/sys/arch/evbmips/conf/std.pavo
@@ -0,0 +1,26 @@
+# $NetBSD: $
+
+machine evbmips mips
+include		"conf/std"	# MI standard options
+
+# Platform support
+options JZRISC
+
+# JZRISC cpus don't have cp0 counter, but without this options
+# some PARANOIA asserts fail. Enabling this options seems to
+# be the best workaround for now.
+options MIPS3_ENABLE_CLOCK_INTR
+
+options	EXEC_ELF32	# exec ELF32 binaries
+options	EXEC_SCRIPT	# exec #! scripts
+
+makeoptions	CFLAGS+="-mips32"
+makeoptions	AFLAGS+="-mips32"
+makeoptions	DEFTEXTADDR="0x80100000"
+makeoptions	BOARDTYPE="pavo"
+makeoptions	BOARDMKFRAG="${THISMIPS}/conf/mk.pavo"
+
+include "arch/evbmips/conf/files.pavo"
+include "arch/mips/conf/files.ingenic"
+
+file	arch/evbmips/ingenic/pavo_lcd.c	jzfb
diff --git a/sys/arch/evbmips/ingenic/autoconf.c b/sys/arch/evbmips/ingenic/autoconf.c
new file mode 100644
index 0000000..20e8a70
--- /dev/null
+++ b/sys/arch/evbmips/ingenic/autoconf.c
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 2011, Peter Tworek
+ * 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. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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>
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+#include <sys/bus.h>
+
+/*
+ * Configure all devices on system
+ */
+void
+cpu_configure(void)
+{
+	intr_init();
+
+	/* Kick off autoconfiguration. */
+	(void)splhigh();
+	if (config_rootfound("mainbus", NULL) == NULL)
+		panic("no mainbus found");
+}
+
+void
+cpu_rootconf(void)
+{
+
+	setroot(booted_device, booted_partition);
+}
diff --git a/sys/arch/evbmips/ingenic/interrupt.c b/sys/arch/evbmips/ingenic/interrupt.c
new file mode 100644
index 0000000..90761b7
--- /dev/null
+++ b/sys/arch/evbmips/ingenic/interrupt.c
@@ -0,0 +1,105 @@
+/*-
+ * Copyright (c) 2011 Peter Tworek
+ * 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. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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>
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/cpu.h>
+#include <sys/intr.h>
+
+#include <machine/locore.h>
+
+#include <mips/ingenic/include/jz47xxvar.h>
+#include <mips/ingenic/include/jz47xxreg.h>
+
+void
+intr_init(void)
+{
+        jz47xx_intr_init();
+}
+
+void
+cpu_intr(int ppl, vaddr_t pc, uint32_t status)
+{
+	struct cpu_info * const ci = curcpu();
+	struct clockframe cf;
+	uint32_t pending;
+#if 0
+        uint32_t vector;
+#endif
+	int ipl;
+
+	cf.pc = pc;
+	cf.sr = status;
+	cf.intr = (ci->ci_idepth > 1);
+
+	KASSERT(ci->ci_cpl == IPL_HIGH);
+
+	ci->ci_data.cpu_nintr++;
+
+	while (ppl < (ipl = splintr(&pending))) {
+		splx(ipl);	/* lower to interrupt level */
+
+		KASSERTMSG(ci->ci_cpl == ipl,
+		    ("%s: cpl (%d) != ipl (%d)",
+		    __func__, ci->ci_cpl, ipl));
+		KASSERT(pending != 0);
+                KASSERT(pending & MIPS_INT_MASK_0);
+
+#if 0
+		vector = INTC_GET_REG(INTC_PENDING);
+                if (vector & (1 << INTC_IRQ_TCU0)) {
+			struct clockframe cf;
+			KASSERT(ipl == IPL_SCHED);
+			cf.pc = pc;
+			cf.sr = status;
+			cf.intr = (ci->ci_idepth > 1);
+
+                        /* Clear pending status */
+			INTC_PUT_REG(INTC_PENDING, (1 << INTC_IRQ_TCU0));
+                        vector ^= (1 << INTC_IRQ_TCU0);
+
+                        hardclock(&cf);
+                }
+#endif
+		jz47xx_intr(&cf);
+		pending ^= MIPS_INT_MASK_0;
+
+		/*
+		 * If even our spl is higher now (due to interrupting while
+		 * spin-lock is held and higher IPL spin-lock is locked, it
+		 * can no longer be locked so it's safe to lower IPL back
+		 * to ppl.
+		 */
+		(void) splhigh();	/* disable interrupts */
+	}
+
+	KASSERT(ci->ci_cpl == IPL_HIGH);
+}
diff --git a/sys/arch/evbmips/ingenic/machdep.c b/sys/arch/evbmips/ingenic/machdep.c
new file mode 100644
index 0000000..23eee46
--- /dev/null
+++ b/sys/arch/evbmips/ingenic/machdep.c
@@ -0,0 +1,307 @@
+/*-
+ * Copyright (c) 2011 Peter Tworek
+ * 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. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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>
+
+#include "opt_ddb.h"
+#include "opt_execfmt.h"
+#include "opt_modular.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/buf.h>
+#include <sys/reboot.h>
+#include <sys/mount.h>
+#include <sys/kcore.h>
+#include <sys/boot_flag.h>
+#include <sys/termios.h>
+#include <sys/ksyms.h>
+#include <sys/device.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <dev/cons.h>
+
+#include "ksyms.h"
+#include "com.h"
+
+#if NKSYMS || defined(DDB) || defined(MODULAR)
+#include <machine/db_machdep.h>
+#include <ddb/db_extern.h>
+#endif
+
+#include <machine/cpu.h>
+#include <machine/psl.h>
+
+#include <mips/locore.h>
+#include <mips/cache.h>
+
+#include <mips/ingenic/include/jz47xx_clk.h>
+#include <mips/ingenic/include/jz47xxreg.h>
+#include <mips/ingenic/include/jz47xxvar.h>
+
+#ifndef MEMSIZE
+#define MEMSIZE	(64)
+#endif /* MEMSIZE */
+
+
+/* Maps for VM objects. */
+struct vm_map *phys_map = NULL;
+
+int	physmem;		/* Total physical memory */
+
+int mem_cluster_cnt;
+phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX];
+
+void	mach_init(void);
+
+static void
+cal_timer(void)
+{
+        uint32_t	cntfreq;
+
+        cntfreq = curcpu()->ci_cpu_freq = jz47xx_clk_get(JZ_CCLK);
+
+        curcpu()->ci_cctr_freq = 0;
+        curcpu()->ci_cycles_per_hz = (cntfreq + hz / 2) / hz;
+
+	/* Compute number of cycles per 1us (1/MHz). 0.5MHz is for roundup. */
+	curcpu()->ci_divisor_delay = ((cntfreq + 500000) / 1000000);
+}
+
+/*
+ * Do all the stuff that locore normally does before calling main().
+ *
+ * TODO: parse u-boot boot params
+ */
+void
+mach_init(void)
+{
+	void *kernend;
+        uint32_t memsize;
+
+	extern char edata[], end[];
+
+	/*
+	 * Clear the BSS segment.
+	 */
+	kernend = (void *)mips_round_page(end);
+	memset(edata, 0, (char *)kernend - edata);
+
+#if NCOM > 0
+        /* setup early console */
+        jz47xx_early_console();
+#endif /* NCOM > 0 */
+
+#ifdef DIAGNOSTIC
+	printf("cclk = %d Hz\nhclk = %d Hz\npclk = %d Hz\nmclk = %d Hz\n",
+	       jz47xx_clk_get(JZ_CCLK), jz47xx_clk_get(JZ_HCLK),
+	       jz47xx_clk_get(JZ_PCLK), jz47xx_clk_get(JZ_MCLK));
+#endif /* DIAGNOSTIC */
+
+	/*
+	 * Set up the exception vectors and CPU-specific function
+	 * vectors early on.  We need the wbflush() vector set up
+	 * before comcnattach() is called (or at least before the
+	 * first printf() after that is called).
+	 * Also clears the I+D caches.
+	 */
+	mips_vector_init(NULL, false);
+
+        /*
+         * Calibrate timers.
+         */
+        cal_timer();
+
+	/* set the VM page size */
+	uvm_setpagesize();
+
+	/*
+	 * Look at arguments passed to us and compute boothowto.
+	 */
+	boothowto = RB_AUTOBOOT;
+#ifdef KADB
+	boothowto |= RB_KDB;
+#endif
+
+	/*
+	 * Determine the memory size.
+	 *
+	 * Note: Reserve the first page!  That's where the trap
+	 * vectors are located.
+	 */
+	memsize = JZ_SRAM_SIZE + (MEMSIZE * 1024 * 1024);
+	printf("Memory size: 0x%08x\n", memsize);
+	physmem = btoc(memsize);
+
+	mem_clusters[mem_cluster_cnt].start = PAGE_SIZE;
+	mem_clusters[mem_cluster_cnt].size =
+	    memsize - mem_clusters[mem_cluster_cnt].start;
+	mem_cluster_cnt++;
+
+	/*
+	 * Load the available pages into the VM system.
+	 */
+	mips_page_physload(MIPS_KSEG0_START, (vaddr_t)kernend,
+	    mem_clusters, mem_cluster_cnt, NULL, 0);
+
+	/*
+	 * Initialize message buffer (at end of core).
+	 */
+	mips_init_msgbuf();
+
+	/*
+	 * Initialize the virtual memory system.
+	 */
+	pmap_bootstrap();
+
+	/*
+	 * Allocate uarea page for lwp0 and set it.
+	 */
+	mips_init_lwp0_uarea();
+
+        /*
+         * Initalize watchdog timer. This should set up
+         * all the registers. And leaves it in disabled state
+         */
+        jz47xx_wdog_init();
+
+	/*
+	 * Initialize debuggers, and break into them, if appropriate.
+	 */
+#if defined(DDB)
+	if (boothowto & RB_KDB)
+	        Debugger();
+#endif
+}
+
+void
+consinit(void)
+{
+
+	/*
+	 * Everything related to console initialization is done
+	 * in mach_init().
+	 */
+}
+
+/*
+ * Allocate memory for variable-sized tables,
+ */
+void
+cpu_startup(void)
+{
+	char pbuf[9];
+        vaddr_t minaddr, maxaddr;
+
+	printf("%s%s", copyright, version);
+	format_bytes(pbuf, sizeof(pbuf), ctob(physmem));
+        printf("total memory = %s\n", pbuf);
+
+	minaddr = 0;
+	/*
+	 * Allocate a submap for physio
+	 */
+	phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
+            VM_PHYS_SIZE, 0, FALSE, NULL);
+
+	/*
+	 * No need to allocate an mbuf cluster submap.  Mbuf clusters
+	 * are allocated via the pool allocator, and we use KSEG to
+	 * map those pages.
+	 */
+
+        format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free));
+        printf("avail memory = %s\n", pbuf);
+}
+
+void
+cpu_reboot(int howto, char *bootstr)
+{
+	static int waittime = -1;
+	/* Take a snapshot before clobbering any registers. */
+	savectx(curpcb);
+
+	/* If "always halt" was specified as a boot flag, obey. */
+	if (boothowto & RB_HALT)
+		howto |= RB_HALT;
+
+	boothowto = howto;
+
+	/* If system is cold, just halt. */
+	if (cold) {
+		howto |= RB_HALT;
+		goto haltsys;
+	}
+
+	if ((howto & RB_NOSYNC) == 0 && (waittime < 0)) {
+		waittime = 0;
+
+		/*
+		 * Synchronize the disks....
+		 */
+		vfs_shutdown();
+
+		/*
+		 * If we've been adjusting the clock, the todr
+		 * will be out of synch; adjust it now.
+		 */
+		resettodr();
+	}
+
+	/* Disable interrupts. */
+	splhigh();
+
+	if (howto & RB_DUMP)
+		dumpsys();
+
+haltsys:
+	doshutdownhooks();
+
+	pmf_system_shutdown(boothowto);
+
+	if (howto & RB_HALT) {
+		printf("\n");
+		printf("The operating system has halted.\n");
+		printf("Please press any key to reboot.\n\n");
+		cnpollc(1);	/* For proper keyboard command handling */
+		cngetc();
+		cnpollc(0);
+	}
+
+	printf("reseting board...\n\n");
+
+	mips_icache_sync_all();
+	mips_dcache_wbinv_all();
+        jz47xx_wdog_reload(10);
+
+	for (;;);
+	/*NOTREACHED*/
+}
diff --git a/sys/arch/evbmips/ingenic/mainbus.c b/sys/arch/evbmips/ingenic/mainbus.c
new file mode 100644
index 0000000..add9f91
--- /dev/null
+++ b/sys/arch/evbmips/ingenic/mainbus.c
@@ -0,0 +1,91 @@
+/*-
+ * Copyright (c) 2011, Peter Tworek
+ * 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. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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>
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <mips/cache.h>
+#include <mips/cpuregs.h>
+
+#include "locators.h"
+
+static int	mainbus_match(device_t, cfdata_t, void *);
+static void	mainbus_attach(device_t, device_t, void *);
+static int	mainbus_print(void *, const char *);
+
+CFATTACH_DECL_NEW(mainbus, 0,
+    mainbus_match, mainbus_attach, NULL, NULL);
+
+/* There can be only one. */
+int	mainbus_found;
+
+struct mainbusdev {
+	const char *md_name;
+};
+
+struct mainbusdev mainbusdevs[] = {
+	{ "cpu",	},
+	{ "wdog",	},
+	{ "jzbus",	},
+	{ NULL,		}
+};
+
+static int
+mainbus_match(device_t parent, cfdata_t match, void *aux)
+{
+
+	if (mainbus_found)
+		return (0);
+
+	return (1);
+}
+
+static void
+mainbus_attach(device_t parent, device_t self, void *aux)
+{
+	const struct mainbusdev *md;
+
+	mainbus_found = 1;
+	printf("\n");
+
+	for (md = mainbusdevs; md->md_name != NULL; md++) {
+		struct mainbusdev ma = *md;
+		config_found_ia(self, "mainbus", &ma, mainbus_print);
+	}
+}
+
+static int
+mainbus_print(void *aux, const char *pnp)
+{
+
+	return (QUIET);
+}
diff --git a/sys/arch/evbmips/ingenic/nanonote_lcd.c b/sys/arch/evbmips/ingenic/nanonote_lcd.c
new file mode 100644
index 0000000..ad5dbdd
--- /dev/null
+++ b/sys/arch/evbmips/ingenic/nanonote_lcd.c
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 2011, Peter Tworek
+ * 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. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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>
+
+#include <mips/ingenic/dev/jzfb_var.h>
+
+struct lcd_panel_info jz47xx_lcd_panel_info = {
+	.lcd_mode = JZ_LCD_MODE_8BIT_SERIAL,
+	.cfg_base = (JZ_LCD_CFG_VSYNC_ACTIVE_LOW |
+	             JZ_LCD_CFG_HSYNC_ACTIVE_LOW |
+	             JZ_LCD_CFG_PCLK_FALLING_EDGE),
+	.xres = 320,
+	.yres = 240,
+	.bpp = 24,
+	.refresh = 30,
+	.hds = 141,
+	.vds = 21,
+	.hde = 461,
+	.vde = 261,
+	.ht = 734,
+	.vt = 263,
+	.hsync = 1,
+	.vsync = 1
+};
+
diff --git a/sys/arch/evbmips/ingenic/pavo_lcd.c b/sys/arch/evbmips/ingenic/pavo_lcd.c
new file mode 100644
index 0000000..79a1b1a
--- /dev/null
+++ b/sys/arch/evbmips/ingenic/pavo_lcd.c
@@ -0,0 +1,50 @@
+/*-
+ * Copyright (c) 2011, Peter Tworek
+ * 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. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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>
+
+#include <mips/ingenic/dev/jzfb_var.h>
+
+struct lcd_panel_info jz47xx_lcd_panel_info = {
+	.lcd_mode = JZ_LCD_MODE_GENERIC_18_BIT,
+	.cfg_base = (JZ_LCD_CFG_VSYNC_ACTIVE_LOW |
+	             JZ_LCD_CFG_HSYNC_ACTIVE_LOW),
+	.xres = 480,
+	.yres = 272,
+	.bpp = 32,
+	.refresh = 30,
+	.hds = 43,
+	.vds = 12,
+	.hde = 523,
+	.vde = 284,
+	.ht = 525,
+	.vt = 286,
+	.hsync = 41,
+	.vsync = 10
+};
diff --git a/sys/arch/evbmips/ingenic/wdog.c b/sys/arch/evbmips/ingenic/wdog.c
new file mode 100644
index 0000000..4c840ec
--- /dev/null
+++ b/sys/arch/evbmips/ingenic/wdog.c
@@ -0,0 +1,127 @@
+/*-
+ * Copyright (c) 2011, Peter Tworek
+ * 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. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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.
+ */
+
+/*
+ * Watchdog timer support for Ingenic JZ47xx familly of SOCs
+ */
+
+#include <sys/cdefs.h>
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/wdog.h>
+
+#include <machine/cpu.h>
+
+#include <mips/ingenic/include/jz47xxvar.h>
+
+#include <dev/sysmon/sysmonvar.h>
+
+#ifndef WDOG_DEFAULT_PERIOD
+#define WDOG_DEFAULT_PERIOD	10
+#endif
+
+static int  wdog_match(device_t, struct cfdata *, void *);
+static void wdog_attach(device_t, device_t, void *);
+static int  wdog_tickle(struct sysmon_wdog *);
+static int  wdog_setmode(struct sysmon_wdog *);
+
+struct wdog_softc {
+	struct sysmon_wdog  sc_smw;
+	uint32_t            sc_wdog_period;
+	uint32_t            sc_wdog_reload;
+	uint32_t            sc_wdog_max;
+	uint32_t            sc_wdog_mult;
+};
+
+CFATTACH_DECL_NEW(wdog, sizeof(struct wdog_softc),
+	wdog_match, wdog_attach, NULL, NULL);
+
+static int
+wdog_match(device_t parent, struct cfdata *cf, void *aux)
+{
+
+	return (1);
+}
+
+static void
+wdog_attach(device_t parent, device_t self, void *aux)
+{
+	struct wdog_softc *sc = device_private(self);
+
+	sc->sc_wdog_mult = jz47xx_wdog_freq();
+	sc->sc_wdog_period = WDOG_DEFAULT_PERIOD;
+	sc->sc_wdog_reload = sc->sc_wdog_period * sc->sc_wdog_mult;
+	sc->sc_wdog_max = 0x0000ffffU / sc->sc_wdog_mult;
+	aprint_normal(": %d second period\n", sc->sc_wdog_period);
+
+	sc->sc_smw.smw_name = device_xname(self);
+	sc->sc_smw.smw_cookie = sc;
+	sc->sc_smw.smw_setmode = wdog_setmode;
+	sc->sc_smw.smw_tickle = wdog_tickle;
+	sc->sc_smw.smw_period = sc->sc_wdog_period;
+
+	if (sysmon_wdog_register(&sc->sc_smw) != 0) {
+		aprint_error_dev(self, "unable to register with sysmon\n");
+	}
+}
+
+static int
+wdog_tickle(struct sysmon_wdog *smw)
+{
+	struct wdog_softc *sc = smw->smw_cookie;
+
+	jz47xx_wdog_reload(sc->sc_wdog_reload);
+	return (0);
+}
+
+static int
+wdog_setmode(struct sysmon_wdog *smw)
+{
+	struct wdog_softc *sc = smw->smw_cookie;
+
+	if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) {
+		jz47xx_wdog_reload(0);
+	} else {
+		if (smw->smw_period == WDOG_PERIOD_DEFAULT) {
+			smw->smw_period = sc->sc_wdog_period;
+		} else if (smw->smw_period != sc->sc_wdog_period) {
+			if (smw->smw_period > sc->sc_wdog_max) {
+				return EOPNOTSUPP;
+			}
+			sc->sc_wdog_period = smw->smw_period;
+			sc->sc_wdog_reload = sc->sc_wdog_period * sc->sc_wdog_mult;
+		}
+
+		jz47xx_wdog_reload(sc->sc_wdog_reload);
+	}
+
+	return (0);
+}
diff --git a/sys/arch/mips/conf/files.ingenic b/sys/arch/mips/conf/files.ingenic
new file mode 100644
index 0000000..6c539ce
--- /dev/null
+++ b/sys/arch/mips/conf/files.ingenic
@@ -0,0 +1,64 @@
+#	$NetBSD: $
+
+defflag	opt_jzsoc.h	JZ4740
+
+#file	arch/mips/ingenic/jz4740_cpm.c		jz4740
+
+#file	arch/mips/ingenic/jz47xx_cpm.c
+
+file	arch/mips/ingenic/jz4740_clk.c		jz4740
+
+file	arch/mips/ingenic/jz47xx_wdog.c
+file	arch/mips/ingenic/jz47xx_intr.c
+file	arch/mips/ingenic/jz47xx_gpio.c
+file	arch/mips/ingenic/jz47xx_console.c
+
+# On-chip ABP/AHB system bus
+device	jzbus { [addr=-1], [size=0], [intr=-1], [function=0] }
+attach	jzbus at mainbus
+file	arch/mips/ingenic/dev/jzbus.c		jzbus
+
+# Clock and Power Management unit
+device	jzpm
+attach	jzpm at jzbus
+file	arch/mips/ingenic/dev/jzpm.c		jzpm
+
+# On-chip timer controller
+device	jztcu { [intr=-1], [function=0] }
+attach	jztcu at jzbus
+file	arch/mips/ingenic/dev/jztcu.c		jztcu
+
+# Actual timers
+device	jztimer
+attach	jztimer at jztcu
+file	arch/mips/ingenic/dev/jztimer.c		jztimer
+
+# On-chip UART
+attach	com at jzbus with com_jzbus
+file	arch/mips/ingenic/dev/com_jzbus.c	com_jzbus
+options	COM_REGMAP
+
+# On-chip real time clock
+device	jzrtc
+attach	jzrtc at jzbus
+file	arch/mips/ingenic/dev/jzrtc.c		jzrtc
+
+# Framebuffer
+device	jzfb: rasops32, rasops24, rasops16, rasops8, wsemuldisplaydev, vcons
+attach	jzfb at jzbus
+file	arch/mips/ingenic/dev/jzfb.c		jzfb
+
+# On-board flash memory
+#device	athflash
+#attach	athflash at arbus
+#file	arch/mips/atheros/dev/athflash.c	athflash
+
+# On-chip GPIO
+#device	argpio: gpiobus, sysmon_power, sysmon_taskq
+#attach	argpio at arbus
+#file	arch/mips/atheros/dev/argpio.c		argpio
+
+# On-board SPI controller
+#device	arspi: spibus
+#attach	arspi at arbus
+#file	arch/mips/atheros/dev/arspi.c		arspi
diff --git a/sys/arch/mips/include/cpu.h b/sys/arch/mips/include/cpu.h
index ed75c44..6da80a4 100644
--- a/sys/arch/mips/include/cpu.h
+++ b/sys/arch/mips/include/cpu.h
@@ -280,6 +280,7 @@ extern struct mips_options mips_options;
 #define	CPU_MIPS_I_D_CACHE_COHERENT	0x0800	/* I-cache funcs don't need to flush the D-cache */
 #define	CPU_MIPS_NO_LLADDR		0x1000
 #define	CPU_MIPS_HAVE_MxCR		0x2000	/* have mfcr, mtcr insns */
+#define	CPU_MIPS_NO_COUNTER		0x4000
 #define	MIPS_NOT_SUPP			0x8000
 
 #endif	/* !_LOCORE */
@@ -332,7 +333,7 @@ extern struct mips_options mips_options;
 # define CPUISMIPS64R2		0
 # define CPUISMIPSNN		1
 # define MIPS_HAS_R4K_MMU	1
-# define MIPS_HAS_CLOCK		1
+# define MIPS_HAS_CLOCK		((mips_options.mips_cpu_flags & CPU_MIPS_NO_COUNTER) == 0)
 # define MIPS_HAS_LLSC		1
 # define MIPS_HAS_LLADDR	((mips_options.mips_cpu_flags & CPU_MIPS_NO_LLADDR) == 0)
 
diff --git a/sys/arch/mips/include/cpuregs.h b/sys/arch/mips/include/cpuregs.h
index 3165026..c90442e 100644
--- a/sys/arch/mips/include/cpuregs.h
+++ b/sys/arch/mips/include/cpuregs.h
@@ -943,6 +943,11 @@
 #define	MIPS_eMIPS	0x04	/* MSR's eMIPS */
 
 /*
+ * CPU processor revision IDs for Ingenic
+ */
+#define MIPS_JZRISC	0x02
+
+/*
  * FPU processor revision ID
  */
 #define	MIPS_SOFT	0x00	/* Software emulation		ISA I	*/
diff --git a/sys/arch/mips/include/locore.h b/sys/arch/mips/include/locore.h
index ecbec6c..6ee2c55 100644
--- a/sys/arch/mips/include/locore.h
+++ b/sys/arch/mips/include/locore.h
@@ -420,6 +420,7 @@ void	mips_page_physload(vaddr_t, vaddr_t,
 				/*	0x0a	unannounced */
 #define     MIPS_PRID_CID_LEXRA		0x0b	/* Lexra */
 #define     MIPS_PRID_CID_RMI		0x0c	/* RMI / NetLogic */
+#define     MIPS_PRID_CID_INGENIC	0xd0    /* Ingenic Semiconductor*/
 #define MIPS_PRID_COPTS(x)	(((x) >> 24) & 0x00ff)	/* Company Options */
 
 #ifdef _KERNEL
diff --git a/sys/arch/mips/ingenic/dev/com_jzbus.c b/sys/arch/mips/ingenic/dev/com_jzbus.c
new file mode 100644
index 0000000..7194123
--- /dev/null
+++ b/sys/arch/mips/ingenic/dev/com_jzbus.c
@@ -0,0 +1,149 @@
+/*-
+ * Copyright (c) 2011, Peter Tworek
+ * 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. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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>
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/termios.h>
+#include <sys/ttydefaults.h>
+#include <sys/types.h>
+
+#include <machine/bus.h>
+
+#include <dev/cons.h>
+#include <dev/ic/comreg.h>
+#include <dev/ic/comvar.h>
+
+#include <mips/cpuregs.h>
+
+#include <mips/ingenic/dev/jzbus_var.h>
+#include <mips/ingenic/include/jz47xxvar.h>
+#include <mips/ingenic/include/jz47xx_clk.h>
+
+#include "opt_com.h"
+
+struct com_jzbus_softc {
+	struct com_softc sc_com;
+};
+
+static void com_jzbus_initmap(struct com_regs *);
+static int  com_jzbus_match(device_t, cfdata_t, void *);
+static void com_jzbus_attach(device_t, device_t, void *);
+
+CFATTACH_DECL_NEW(com_jzbus, sizeof(struct com_jzbus_softc),
+    com_jzbus_match, com_jzbus_attach, NULL, NULL);
+
+#ifdef	TTYDEF_SPEED
+#define	COM_JZBUS_BAUD	TTYDEF_SPEED
+#else
+#define	COM_JZBUS_BAUD	115200
+#endif
+
+#ifndef COM_JZBUS_BAUD
+#define	COM_JZBUS_BAUD	115200
+#endif
+
+#define CONMODE	((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
+
+#ifndef	COM_REGMAP
+#error	COM_REGMAP not defined!
+#endif
+
+int
+com_jzbus_match(device_t parent, cfdata_t cf, void *aux)
+{
+	struct jzbus_attach_args	*aa = aux;
+	struct com_regs			regs;
+	int				rv;
+
+	if (strncmp(cf->cf_name, "com", 3) != 0)
+		return 0;
+
+	if (com_is_console(aa->aa_bst, aa->aa_addr, &regs.cr_ioh))
+		return 1;
+
+	if (bus_space_map(aa->aa_bst, aa->aa_addr, aa->aa_size,
+		0, &regs.cr_ioh))
+		return 0;
+
+	regs.cr_iot = aa->aa_bst;
+	regs.cr_iobase = aa->aa_addr;
+	regs.cr_nports = aa->aa_size;
+	com_jzbus_initmap(&regs);
+
+	rv = com_probe_subr(&regs);
+
+	bus_space_unmap(aa->aa_bst, regs.cr_ioh, aa->aa_size);
+
+	return rv;
+}
+
+void
+com_jzbus_attach(device_t parent, device_t self, void *aux)
+{
+	struct com_jzbus_softc *arsc = device_private(self);
+	struct com_softc *sc = &arsc->sc_com;
+	struct jzbus_attach_args *aa = aux;
+	bus_space_handle_t ioh;
+
+	sc->sc_dev = self;
+	sc->sc_frequency = jz47xx_clk_get(JZ_HCLK);
+
+	if (!com_is_console(aa->aa_bst, aa->aa_addr, &ioh) &&
+	    bus_space_map(aa->aa_bst, aa->aa_addr, aa->aa_size, 0, &ioh) != 0) {
+		aprint_error(": can't map registers\n");
+		return;
+	}
+
+	COM_INIT_REGS(sc->sc_regs, aa->aa_bst, ioh, aa->aa_addr);
+	sc->sc_regs.cr_nports = aa->aa_size;
+	com_jzbus_initmap(&sc->sc_regs);
+
+	comcnattach1(&sc->sc_regs, COM_JZBUS_BAUD, sc->sc_frequency,
+	             COM_TYPE_NORMAL, CONMODE);
+
+	com_attach_subr(sc);
+
+	jzbus_intr_establish(aa->aa_intr, comintr, sc);
+}
+
+void
+com_jzbus_initmap(struct com_regs *regsp)
+{
+	int	i;
+
+	/* rewrite the map to shift for alignment */
+	for (i = 0;
+	     i < (sizeof (regsp->cr_map) / sizeof (regsp->cr_map[0])); i++) {
+		regsp->cr_map[i] = (com_std_map[i] * 4) + 3;
+	}
+}
diff --git a/sys/arch/mips/ingenic/dev/jzbus.c b/sys/arch/mips/ingenic/dev/jzbus.c
new file mode 100644
index 0000000..5caac0b
--- /dev/null
+++ b/sys/arch/mips/ingenic/dev/jzbus.c
@@ -0,0 +1,246 @@
+/*-
+ * Copyright (c) 2011, Peter Tworek
+ * 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. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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>
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/extent.h>
+#include <sys/malloc.h>
+
+#define	_MIPS_BUS_DMA_PRIVATE
+#include <machine/bus.h>
+
+#include <mips/ingenic/include/jz47xx_gpio_var.h>
+#include <mips/ingenic/include/jz47xxreg.h>
+#include <mips/ingenic/include/jz47xxvar.h>
+#include <mips/ingenic/dev/jzbus_var.h>
+
+#include "locators.h"
+
+static int  jzbus_match(device_t, struct cfdata *, void *);
+static void jzbus_attach(device_t, device_t, void *);
+static int  jzbus_search(device_t, cfdata_t, const int *, void *);
+static int  jzbus_find(device_t, cfdata_t, const int *, void *);
+static int  jzbus_print(void *, const char *);
+static void jzbus_attach_critical(struct jzbus_softc *);
+
+static void jzbus_bus_mem_init(bus_space_tag_t, void *);
+
+struct jzbus_intrhand {
+	int		ih_intr;
+	void		*ih_cookie;
+};
+
+CFATTACH_DECL_NEW(jzbus, sizeof(struct jzbus_softc),
+	jzbus_match, jzbus_attach, NULL, NULL);
+
+/* FIXME: cpm, icu */
+static const struct {
+	const char *name;
+	bus_addr_t addr;
+} critical_devs[] = {
+	{ .name = "jzcpm0",	.addr = JZ_CPM_BASE },
+#if 0
+	{ .name = "jzintc0",	.addr = JZ_INTC_BASE },
+#endif
+	{ .name = "jztcu0",	.addr = JZ_TCU_BASE }
+};
+
+int
+jzbus_match(device_t parent, cfdata_t match, void *aux)
+{
+
+	return (1);
+}
+
+void
+jzbus_attach(device_t parent, device_t self, void *aux)
+{
+	struct jzbus_softc * const sc = device_private(self);
+
+	aprint_normal(": Ingenic JzSOC AHB/APB bus\n");
+
+	sc->sc_dev = self;
+
+	/*
+	 * Initialize BUS DMA.
+	 */
+	jzbus_bus_mem_init(&sc->sc_bst, NULL);
+	sc->sc_dmat._dmamap_ops = mips_bus_dmamap_ops;
+	sc->sc_dmat._dmamem_ops = mips_bus_dmamem_ops;
+	sc->sc_dmat._dmatag_ops = mips_bus_dmatag_ops;
+
+	/*
+	 * Initialize GPIO controller.
+	 */
+	jz47xx_gpio_init(self, &sc->sc_bst);
+
+	/*
+	 * Attach critical devices.
+	 */
+	jzbus_attach_critical(sc);
+
+	/*
+	 * Attach the rest JzSOC devices.
+	 */
+	config_search_ia(jzbus_search, self, "jzbus", NULL);
+}
+
+static int
+jzbus_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux)
+{
+	struct jzbus_softc * const sc = device_private(parent);
+
+	struct jzbus_attach_args aa;
+
+	aa.aa_bst  = &sc->sc_bst;
+	aa.aa_dmat = &sc->sc_dmat;
+	aa.aa_addr = cf->cf_loc[JZBUSCF_ADDR];
+	aa.aa_size = cf->cf_loc[JZBUSCF_SIZE];
+	aa.aa_intr = cf->cf_loc[JZBUSCF_INTR];
+	aa.aa_unit = cf->cf_unit;
+
+	if (config_match(parent, cf, &aa)) {
+		config_attach(parent, cf, &aa, jzbus_print);
+		return (0);
+	}
+
+	return (UNCONF);
+}
+
+static int
+jzbus_find(device_t parent, cfdata_t cf, const int *ldesc, void *aux)
+{
+	struct jzbus_attach_args * const aa = aux;
+
+	if (aa->aa_addr != JZBUSCF_ADDR_DEFAULT &&
+	    aa->aa_addr != cf->cf_loc[JZBUSCF_ADDR])
+		return (0);
+	if (aa->aa_size != JZBUSCF_SIZE_DEFAULT &&
+	    aa->aa_size != cf->cf_loc[JZBUSCF_SIZE])
+		return (0);
+	if (aa->aa_intr != JZBUSCF_INTR_DEFAULT &&
+	    aa->aa_intr != cf->cf_loc[JZBUSCF_INTR])
+		return (0);
+
+	aa->aa_addr = cf->cf_loc[JZBUSCF_ADDR];
+	aa->aa_size = cf->cf_loc[JZBUSCF_SIZE];
+	aa->aa_intr = cf->cf_loc[JZBUSCF_INTR];
+	aa->aa_unit = cf->cf_unit;
+
+	return config_match(parent, cf, aa);
+}
+
+int
+jzbus_print(void *aux, const char *pnp)
+{
+	struct jzbus_attach_args *aa = aux;
+
+	if (aa->aa_addr)
+		aprint_normal(": addr 0x%" PRIxBUSADDR, aa->aa_addr);
+
+	if (aa->aa_intr >= 0)
+		aprint_normal(" intr %d", aa->aa_intr);
+
+	return (UNCONF);
+}
+
+static void
+jzbus_attach_critical(struct jzbus_softc *sc)
+{
+	struct jzbus_attach_args aa;
+	cfdata_t cf;
+	int i;
+
+	for (i = 0; i < __arraycount(critical_devs); i++) {
+		aa.aa_addr = critical_devs[i].addr;
+		aa.aa_size = JZBUSCF_SIZE_DEFAULT;
+		aa.aa_intr = JZBUSCF_INTR_DEFAULT;
+		aa.aa_dmat = &sc->sc_dmat;
+		aa.aa_bst  = &sc->sc_bst;
+
+		cf = config_search_ia(jzbus_find, sc->sc_dev, "jzbus", &aa);
+		if (cf == NULL)
+			panic("jzbus0: failed to find %s!\n", critical_devs[i].name);
+
+		aa.aa_addr = cf->cf_loc[JZBUSCF_ADDR];
+		aa.aa_size = cf->cf_loc[JZBUSCF_SIZE];
+		aa.aa_intr = cf->cf_loc[JZBUSCF_INTR];
+		aa.aa_unit = cf->cf_unit;
+		config_attach(sc->sc_dev, cf, &aa, jzbus_print);
+	}
+}
+
+void *
+jzbus_intr_establish(int intr, int (*handler)(void *), void *arg)
+{
+	struct jzbus_intrhand	*ih;
+
+	ih = malloc(sizeof(*ih), M_DEVBUF, M_NOWAIT);
+	if (ih == NULL)
+		return (NULL);
+
+	ih->ih_intr = -1;
+	ih->ih_cookie = NULL;
+
+	if (intr >= 0) {
+		ih->ih_intr = intr;
+		ih->ih_cookie = jz47xx_intr_establish(intr, handler, arg);
+	} else
+		return (ih);
+
+	if (ih->ih_cookie == NULL) {
+		free(ih, M_DEVBUF);
+		return (NULL);
+	}
+	return (ih);
+}
+
+void
+jzbus_intr_disestablish(void *arg)
+{
+	struct jzbus_intrhand	*ih = arg;
+	if (ih->ih_intr >= 0)
+		jz47xx_intr_disestablish(ih->ih_cookie);
+	free(ih, M_DEVBUF);
+}
+
+/*
+ * CPU memory/register stuff
+ */
+#define	CHIP	   		jzbus
+#define	CHIP_MEM		/* defined */
+#define	CHIP_W1_BUS_START(v)	0x00000000UL
+#define	CHIP_W1_BUS_END(v)	0x1fffffffUL
+#define	CHIP_W1_SYS_START(v)	CHIP_W1_BUS_START(v)
+#define	CHIP_W1_SYS_END(v)	CHIP_W1_BUS_END(v)
+
+#include <mips/mips/bus_space_alignstride_chipdep.c>
diff --git a/sys/arch/mips/ingenic/dev/jzbus_var.h b/sys/arch/mips/ingenic/dev/jzbus_var.h
new file mode 100644
index 0000000..69003f2
--- /dev/null
+++ b/sys/arch/mips/ingenic/dev/jzbus_var.h
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 2011, Peter Tworek
+ * 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. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef	_MIPS_JZ47XX_JZBUS_VAR_H_
+#define	_MIPS_JZ47XX_JZBUS_VAR_H_
+
+#include <machine/bus.h>
+#include <sys/device.h>
+
+struct jzbus_softc {
+	device_t 		sc_dev;
+	struct mips_bus_space 	sc_bst;
+	struct mips_bus_dma_tag	sc_dmat;
+};
+
+struct jzbus_attach_args {
+	bus_space_tag_t	aa_bst;
+	bus_dma_tag_t	aa_dmat;
+	bus_addr_t	aa_addr;
+	bus_size_t	aa_size;
+	int		aa_intr;
+	int		aa_unit;
+};
+
+void* jzbus_intr_establish(int, int (*)(void *), void *);
+void  jzbus_intr_disestablish(void *);
+
+#endif /* _MIPS_JZ47XX_JZBUS_VAR_H_ */
diff --git a/sys/arch/mips/ingenic/dev/jzfb.c b/sys/arch/mips/ingenic/dev/jzfb.c
new file mode 100644
index 0000000..dbeb72b
--- /dev/null
+++ b/sys/arch/mips/ingenic/dev/jzfb.c
@@ -0,0 +1,730 @@
+/*-
+ * Copyright (c) 2011, Peter Tworek
+ * 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. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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.
+ */
+
+/*
+ * Framebuffer driver for JZ47XX SOCs.
+ *
+ * TODO:
+ *  - multiple screens,
+ *  - power management,
+ */
+
+#include <sys/cdefs.h>
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+
+#include <dev/wscons/wsdisplayvar.h>
+#include <dev/wscons/wsconsio.h>
+#include <dev/wsfont/wsfont.h>
+#include <dev/rasops/rasops.h>
+#include <dev/wscons/wsdisplay_vconsvar.h>
+
+#include <mips/ingenic/dev/jzfb_var.h>
+#include <mips/ingenic/include/jzbus_var.h>
+#include <mips/ingenic/include/jz47xxreg.h>
+#include <mips/ingenic/include/jz47xxvar.h>
+#include <mips/ingenic/include/jz47xx_gpio_var.h>
+#include <mips/ingenic/include/jz47xx_gpio_reg.h>
+
+#include "mips/vmparam.h"
+
+#define JZ_REG_LCD_CFG      0x00
+#define JZ_REG_LCD_VSYNC    0x04
+#define JZ_REG_LCD_HSYNC    0x08
+#define JZ_REG_LCD_VAT      0x0C
+#define JZ_REG_LCD_DAH      0x10
+#define JZ_REG_LCD_DAV      0x14
+#define JZ_REG_LCD_PS       0x18
+#define JZ_REG_LCD_CLS      0x1C
+#define JZ_REG_LCD_SPL      0x20
+#define JZ_REG_LCD_REV      0x24
+#define JZ_REG_LCD_CTRL     0x30
+#define JZ_REG_LCD_STATE    0x34
+#define JZ_REG_LCD_IID      0x38
+#define JZ_REG_LCD_DA0      0x40
+#define JZ_REG_LCD_SA0      0x44
+#define JZ_REG_LCD_FID0     0x48
+#define JZ_REG_LCD_CMD0     0x4C
+#define JZ_REG_LCD_DA1      0x50
+#define JZ_REG_LCD_SA1      0x54
+#define JZ_REG_LCD_FID1     0x58
+#define JZ_REG_LCD_CMD1     0x5C
+
+#define JZ_LCD_CFG_SLCD               (1 << 31)
+#define JZ_LCD_CFG_PS_DISABLE         (1 << 23)
+#define JZ_LCD_CFG_CLS_DISABLE        (1 << 22)
+#define JZ_LCD_CFG_SPL_DISABLE        (1 << 21)
+#define JZ_LCD_CFG_REV_DISABLE        (1 << 20)
+#define JZ_LCD_CFG_HSYNCM             (1 << 19)
+#define JZ_LCD_CFG_PCLKM              (1 << 18)
+#define JZ_LCD_CFG_INV                (1 << 17)
+#define JZ_LCD_CFG_SYNC_DIR           (1 << 16)
+#define JZ_LCD_CFG_PS_POLARITY        (1 << 15)
+#define JZ_LCD_CFG_CLS_POLARITY       (1 << 14)
+#define JZ_LCD_CFG_SPL_POLARITY       (1 << 13)
+#define JZ_LCD_CFG_REV_POLARITY       (1 << 12)
+#define JZ_LCD_CFG_HSYNC_ACTIVE_LOW   (1 << 11)
+#define JZ_LCD_CFG_PCLK_FALLING_EDGE  (1 << 10)
+#define JZ_LCD_CFG_DE_ACTIVE_LOW      (1 << 9)
+#define JZ_LCD_CFG_VSYNC_ACTIVE_LOW   (1 << 8)
+#define JZ_LCD_CFG_18_BIT             (1 << 7)
+#define JZ_LCD_CFG_PDW                ((1 << 5) | (1 << 4))
+#define JZ_LCD_CFG_MODE_MASK          0xf
+
+#define JZ_LCD_CTRL_BURST_4           (0x0 << 28)
+#define JZ_LCD_CTRL_BURST_8           (0x1 << 28)
+#define JZ_LCD_CTRL_BURST_16          (0x2 << 28)
+#define JZ_LCD_CTRL_RGB555            (1 << 27)
+#define JZ_LCD_CTRL_OFUP              (1 << 26)
+#define JZ_LCD_CTRL_FRC_GRAYSCALE_16  (0x0 << 24)
+#define JZ_LCD_CTRL_FRC_GRAYSCALE_4   (0x1 << 24)
+#define JZ_LCD_CTRL_FRC_GRAYSCALE_2   (0x2 << 24)
+#define JZ_LCD_CTRL_PDD_MASK          (0xff << 16)
+#define JZ_LCD_CTRL_EOF_IRQ           (1 << 13)
+#define JZ_LCD_CTRL_SOF_IRQ           (1 << 12)
+#define JZ_LCD_CTRL_OFU_IRQ           (1 << 11)
+#define JZ_LCD_CTRL_IFU0_IRQ          (1 << 10)
+#define JZ_LCD_CTRL_IFU1_IRQ          (1 << 9)
+#define JZ_LCD_CTRL_DD_IRQ            (1 << 8)
+#define JZ_LCD_CTRL_QDD_IRQ           (1 << 7)
+#define JZ_LCD_CTRL_REVERSE_ENDIAN    (1 << 6)
+#define JZ_LCD_CTRL_LSB_FISRT         (1 << 5)
+#define JZ_LCD_CTRL_DISABLE           (1 << 4)
+#define JZ_LCD_CTRL_ENABLE            (1 << 3)
+#define JZ_LCD_CTRL_BPP_1             0x0
+#define JZ_LCD_CTRL_BPP_2             0x1
+#define JZ_LCD_CTRL_BPP_4             0x2
+#define JZ_LCD_CTRL_BPP_8             0x3
+#define JZ_LCD_CTRL_BPP_15_16         0x4
+#define JZ_LCD_CTRL_BPP_18_24         0x5
+
+#define JZ_LCD_CMD_SOF_IRQ            (1 << 15)
+#define JZ_LCD_CMD_EOF_IRQ            (1 << 16)
+#define JZ_LCD_CMD_ENABLE_PAL         (1 << 12)
+
+#define JZ_LCD_SYNC_MASK              0x3ff
+
+#define JZ_LCD_STATE_DISABLED         (0)
+
+struct jzfb_framedesc {
+	uint32_t next;
+	uint32_t addr;
+	uint32_t id;
+	uint32_t cmd;
+};
+
+struct jzfb_softc {
+	device_t           sc_dev;
+
+	bus_space_tag_t    sc_bst;
+	bus_dma_tag_t      sc_dmat;
+	bus_space_handle_t sc_regh;
+	bus_dmamap_t       sc_dmamap;
+	bus_dma_segment_t  sc_dmamem[1];
+
+	uint32_t sc_enabled;
+	uint32_t sc_mode;
+
+	uint32_t sc_stride;
+	uint32_t sc_depth;
+	size_t   sc_vramsize, sc_fbsize;
+	void    *sc_vramaddr, *sc_fbaddr;
+
+	struct jzfb_framedesc       *sc_framedesc;
+	struct vcons_screen          sc_console_screen;
+	struct wsscreen_descr        sc_defaultscreen_descr;
+	const struct wsscreen_descr *sc_screens[1];
+	struct wsscreen_list         sc_screenlist;
+	struct vcons_data            vd;
+
+	const struct lcd_panel_info* sc_panel_info;
+};
+
+struct lcdc_gpio {
+	int port;
+	int func;
+};
+
+#define _s(pin) {.port = JZ_GPIO_ ## pin, .func = JZ_GPIO_FUNC_ ## pin}
+const struct lcdc_gpio jzfb_lcdc_ctrl_gpio[] = {
+	_s(LCD_PCLK), _s(LCD_HSYNC), _s(LCD_VSYNC),
+	_s(LCD_DE), _s(LCD_PS), _s(LCD_REV)
+};
+
+const struct lcdc_gpio jzfb_lcdc_data_gpio[] = {
+	_s(LCD_DATA0), _s(LCD_DATA1), _s(LCD_DATA2),
+	_s(LCD_DATA3), _s(LCD_DATA4), _s(LCD_DATA5),
+	_s(LCD_DATA6), _s(LCD_DATA7), _s(LCD_DATA8),
+	_s(LCD_DATA9), _s(LCD_DATA10), _s(LCD_DATA11),
+	_s(LCD_DATA12), _s(LCD_DATA13), _s(LCD_DATA14),
+	_s(LCD_DATA15), _s(LCD_DATA16), _s(LCD_DATA17)
+};
+#undef _s
+
+static int  jzfb_match(device_t, cfdata_t, void *);
+static void jzfb_attach(device_t, device_t, void *);
+
+CFATTACH_DECL_NEW(jzfb, sizeof(struct jzfb_softc),
+	jzfb_match, jzfb_attach, NULL, NULL);
+
+int  jzfb_init_dma_mem(struct jzfb_softc *);
+int  jzfb_init_lcdc(struct jzfb_softc *);
+void jzfb_lcdc_enable(struct jzfb_softc *);
+void jzfb_lcdc_disable(struct jzfb_softc *);
+void jzfb_gpio_enable(struct jzfb_softc *);
+void jzfb_gpio_disable(struct jzfb_softc *);
+int  jzfb_gpio_ctrl_pins_no(const struct lcd_panel_info *);
+int  jzfb_gpio_data_pins_no(const struct lcd_panel_info *);
+
+static int     jzfb_ioctl(void *, void *, u_long, void *, int, struct lwp *);
+static paddr_t jzfb_mmap(void *, void *, off_t, int);
+static void    jzfb_init_screen(void *, struct vcons_screen *, int, long *);
+
+#define LCDC_PUT_REG(s, r, v) bus_space_write_4(s->sc_bst, s->sc_regh, r, v)
+#define LCDC_GET_REG(s, r)    bus_space_read_4(s->sc_bst, s->sc_regh, r)
+#if 0
+void jzfb_dump_regs(struct jzfb_softc *sc);
+#endif
+
+struct wsdisplay_accessops jzfb_accessops = {
+	jzfb_ioctl,
+	jzfb_mmap,
+	NULL,	/* alloc_screen */
+	NULL,	/* free_screen */
+	NULL,	/* show_screen */
+	NULL, 	/* load_font */
+	NULL,	/* pollc */
+	NULL	/* scroll */
+};
+
+static int
+jzfb_match(device_t parent, cfdata_t cf, void *aux)
+{
+	/*struct jzbus_attach_args *aa = aux;*/
+
+	if (strncmp(cf->cf_name, "jzfb", 4) == 0) {
+		return (1);
+	}
+
+	return (0);
+}
+
+static void
+jzfb_attach(device_t parent, device_t self, void *aux)
+{
+	const struct lcd_panel_info* info;
+	struct wsemuldisplaydev_attach_args aa;
+	struct jzfb_softc        *sc = device_private(self);
+	struct jzbus_attach_args *jzb = aux;
+	struct rasops_info       *ri;
+	unsigned long            defattr;
+	bool                     is_console = 1; /* XXX */
+
+	aprint_normal("\n");
+
+	/* Get pointer to platform specific lcd panel info */
+	sc->sc_panel_info = info = &jz47xx_lcd_panel_info;
+
+	sc->sc_bst = jzb->aa_bst;
+	sc->sc_dev = self;
+	sc->sc_dmat = jzb->aa_dmat;
+
+	if (bus_space_map(jzb->aa_bst, jzb->aa_addr, jzb->aa_size, 0,
+		&sc->sc_regh)) {
+		aprint_error(": couldn't map register space\n");
+		return;
+	}
+
+	if ((info->bpp > 0) && (info->bpp <= 8)) {
+		sc->sc_depth = 8;
+		sc->sc_stride = info->xres;
+	} else if ((info->bpp > 8) && (info->bpp <= 16)) {
+		sc->sc_depth = 16;
+		sc->sc_stride = info->xres << 1;
+	} else if ((info->bpp > 16) && (info->bpp <= 32)) {
+		sc->sc_depth = 32;
+		sc->sc_stride = info->xres << 2;
+	} else {
+		aprint_error_dev(sc->sc_dev, "invalid depth!\n");
+		return;
+	}
+
+	sc->sc_fbsize = (info->xres * info->yres) * (sc->sc_depth >> 3);
+        sc->sc_vramsize = sc->sc_fbsize + PAGE_SIZE; /* fb + framedesc */
+
+	if (jzfb_init_dma_mem(sc))
+            return;
+
+	sc->sc_defaultscreen_descr = (struct wsscreen_descr) {
+		"default",
+		0, 0,
+		NULL,
+		8, 16,
+		WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
+		NULL
+	};
+	sc->sc_screens[0] = &sc->sc_defaultscreen_descr;
+	sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens};
+	sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
+	sc->sc_enabled = 0;
+
+	vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr, &jzfb_accessops);
+	sc->vd.init_screen = jzfb_init_screen;
+
+	jzfb_init_lcdc(sc);
+
+	ri = &sc->sc_console_screen.scr_ri;
+
+	if (is_console) {
+		vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1, &defattr);
+		sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
+
+		sc->sc_defaultscreen_descr.textops = &ri->ri_ops;
+		sc->sc_defaultscreen_descr.capabilities = ri->ri_caps;
+		sc->sc_defaultscreen_descr.nrows = ri->ri_rows;
+		sc->sc_defaultscreen_descr.ncols = ri->ri_cols;
+		wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0,
+		                   defattr);
+		vcons_replay_msgbuf(&sc->sc_console_screen);
+	} else {
+		/*
+		 * since we're not the console we can postpone the rest
+		 * until someone actually allocates a screen for us
+		 */
+		(*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
+	}
+
+	aa.console = is_console;
+	aa.scrdata = &sc->sc_screenlist;
+	aa.accessops = &jzfb_accessops;
+	aa.accesscookie = &sc->vd;
+
+	aprint_normal_dev(sc->sc_dev, "%dx%d@%d\n", info->xres,
+	                  info->yres, sc->sc_depth);
+
+	/* Enable LCD controller output */
+	jzfb_lcdc_enable(sc);
+
+	config_found(sc->sc_dev, &aa, wsemuldisplaydevprint);
+}
+
+int
+jzfb_init_dma_mem(struct jzfb_softc *sc)
+{
+	int segs;
+
+	if (bus_dmamem_alloc(sc->sc_dmat, sc->sc_vramsize, 0, 0,
+	    sc->sc_dmamem, 1, &segs, BUS_DMA_NOWAIT) != 0) {
+		aprint_error_dev(sc->sc_dev,
+		                 "failed to allocate video memory!\n");
+		return (1);
+	}
+
+	if (bus_dmamem_map(sc->sc_dmat, sc->sc_dmamem, 1, sc->sc_vramsize,
+	                   &sc->sc_vramaddr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT) != 0) {
+		aprint_error_dev(sc->sc_dev, "failed to map video RAM!\n");
+		goto fail_dmamem_map;
+	}
+
+	if (bus_dmamap_create(sc->sc_dmat, sc->sc_vramsize, 1, sc->sc_vramsize,
+	                      0, BUS_DMA_NOWAIT, &sc->sc_dmamap) != 0) {
+		aprint_error_dev(sc->sc_dev, "failed to create DMA map!\n");
+		goto fail_dmamem_create;
+	}
+
+	if (bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, sc->sc_vramaddr,
+	                    sc->sc_vramsize, NULL, BUS_DMA_NOWAIT) != 0) {
+		aprint_error_dev(sc->sc_dev, "failed to load DMA map!\n");
+		goto fail_dmamem_load;
+	}
+
+	sc->sc_fbaddr = (uint8_t *)sc->sc_vramaddr + PAGE_SIZE;
+        sc->sc_framedesc = (struct jzfb_framedesc *)(sc->sc_vramaddr);
+
+	sc->sc_framedesc->next = sc->sc_dmamem->ds_addr;
+	sc->sc_framedesc->addr = sc->sc_dmamem->ds_addr + PAGE_SIZE;
+	sc->sc_framedesc->id = 0xcafebabe;
+	sc->sc_framedesc->cmd = 0;
+	sc->sc_framedesc->cmd |= sc->sc_fbsize / 4;
+
+	return (0);
+
+fail_dmamem_load:
+	bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmamap);
+fail_dmamem_create:
+	bus_dmamem_unmap(sc->sc_dmat, sc->sc_vramaddr, sc->sc_vramsize);
+fail_dmamem_map:
+	bus_dmamem_free(sc->sc_dmat, sc->sc_dmamem, 1);
+
+	return (1);
+}
+
+int
+jzfb_init_lcdc(struct jzfb_softc *sc)
+{
+	const struct lcd_panel_info *info = sc->sc_panel_info;
+	uint32_t ctrl = 0;
+	uint32_t cfg = info->cfg_base;
+	unsigned long rate;
+
+	ctrl = JZ_LCD_CTRL_OFUP | JZ_LCD_CTRL_BURST_16;
+	switch (info->bpp) {
+		case 1:
+			ctrl |= JZ_LCD_CTRL_BPP_1;
+			break;
+
+		case 2:
+			ctrl |= JZ_LCD_CTRL_BPP_2;
+			break;
+
+		case 4:
+			ctrl |= JZ_LCD_CTRL_BPP_4;
+			break;
+
+		case 8:
+			ctrl |= JZ_LCD_CTRL_BPP_8;
+			break;
+
+		case 15:
+			ctrl |= JZ_LCD_CTRL_RGB555;
+		case 16:
+			ctrl |= JZ_LCD_CTRL_BPP_15_16;
+			break;
+
+		case 18:
+		case 24:
+		case 32:
+			ctrl |= JZ_LCD_CTRL_BPP_18_24;
+			break;
+
+		default:
+			break;
+	}
+
+	/*
+	 * TODO: This should probably be configured depending on
+	 *       LCD panel mode in info->lcd_mode
+	 */
+	cfg |= JZ_LCD_CFG_PS_DISABLE | JZ_LCD_CFG_CLS_DISABLE |
+	       JZ_LCD_CFG_SPL_DISABLE | JZ_LCD_CFG_REV_DISABLE;
+
+	if (info->lcd_mode == JZ_LCD_MODE_GENERIC_18_BIT)
+		cfg |= JZ_LCD_CFG_18_BIT;
+
+	cfg |= info->lcd_mode & 0xf;
+
+	if (info->lcd_mode == JZ_LCD_MODE_8BIT_SERIAL) {
+		rate = info->refresh * (info->vt + 2 * info->xres) * info->ht;
+	} else {
+		rate = info->refresh * info->vt * info->ht;
+	}
+
+	ctrl |= JZ_LCD_CTRL_ENABLE;
+	LCDC_PUT_REG(sc, JZ_REG_LCD_HSYNC, info->hsync);
+	LCDC_PUT_REG(sc, JZ_REG_LCD_VSYNC, info->vsync);
+	LCDC_PUT_REG(sc, JZ_REG_LCD_VAT, (info->ht << 16) | info->vt);
+	LCDC_PUT_REG(sc, JZ_REG_LCD_DAH, (info->hds << 16) | info->hde);
+	LCDC_PUT_REG(sc, JZ_REG_LCD_DAV, (info->vds << 16) | info->vde);
+	LCDC_PUT_REG(sc, JZ_REG_LCD_CFG, cfg);
+	LCDC_PUT_REG(sc, JZ_REG_LCD_CTRL, ctrl);
+
+	jz47xx_cpm_set_pixclk(rate);
+	jz47xx_cpm_set_lcdclk(rate * 3);
+
+	return (0);
+}
+
+void
+jzfb_lcdc_enable(struct jzfb_softc *sc)
+{
+	uint32_t ctrl;
+#if 0
+	clk_enable(jzfb->ldclk);
+#endif
+	if (sc->sc_enabled)
+		return;
+
+	jzfb_gpio_enable(sc);
+
+	LCDC_PUT_REG(sc, JZ_REG_LCD_STATE, 0);
+	LCDC_PUT_REG(sc, JZ_REG_LCD_DA0, sc->sc_framedesc->next);
+
+	ctrl = LCDC_GET_REG(sc, JZ_REG_LCD_CTRL);
+	ctrl |= JZ_LCD_CTRL_ENABLE;
+	ctrl &= ~JZ_LCD_CTRL_DISABLE;
+	LCDC_PUT_REG(sc, JZ_REG_LCD_CTRL, ctrl);
+
+	sc->sc_enabled = 1;
+}
+
+void
+jzfb_lcdc_disable(struct jzfb_softc *sc)
+{
+	uint32_t ctrl, state;
+
+	if (!sc->sc_enabled)
+		return;
+
+	ctrl = LCDC_GET_REG(sc, JZ_REG_LCD_CTRL);
+	ctrl |= JZ_LCD_CTRL_DISABLE;
+	LCDC_PUT_REG(sc, JZ_REG_LCD_CTRL, ctrl);
+	do {
+		state = LCDC_GET_REG(sc, JZ_REG_LCD_STATE);
+	} while (!(state & JZ_LCD_STATE_DISABLED));
+
+	jzfb_gpio_disable(sc);
+#if 0
+	clk_disable(jzfb->ldclk);
+#endif
+	sc->sc_enabled = 0;
+}
+
+void
+jzfb_gpio_enable(struct jzfb_softc *sc)
+{
+	int ctrl_pin_no = jzfb_gpio_ctrl_pins_no(sc->sc_panel_info);
+	int data_pin_no = jzfb_gpio_data_pins_no(sc->sc_panel_info);
+	const struct lcdc_gpio *lg;
+	int i;
+
+	for (i = 0; i < ctrl_pin_no; i++) {
+		lg = &jzfb_lcdc_ctrl_gpio[i];
+		jz47xx_gpio_config_func(lg->port, lg->func);
+	}
+
+	for (i = 0; i < data_pin_no; i++) {
+		lg = &jzfb_lcdc_data_gpio[i];
+		jz47xx_gpio_config_func(lg->port, lg->func);
+	}
+}
+
+void
+jzfb_gpio_disable(struct jzfb_softc *sc)
+{
+	int ctrl_pin_no = jzfb_gpio_ctrl_pins_no(sc->sc_panel_info);
+	int data_pin_no = jzfb_gpio_data_pins_no(sc->sc_panel_info);
+	const struct lcdc_gpio *lg;
+	int i;
+
+	for (i = 0; i < ctrl_pin_no; i++) {
+		lg = &jzfb_lcdc_ctrl_gpio[i];
+		jz47xx_gpio_config_func(lg->port, JZ_GPIO_FUNC_NONE);
+		jz47xx_gpio_config_pull(lg->port, false);
+	}
+
+	for (i = 0; i < data_pin_no; i++) {
+		lg = &jzfb_lcdc_data_gpio[i];
+		jz47xx_gpio_config_func(lg->port, JZ_GPIO_FUNC_NONE);
+		jz47xx_gpio_config_pull(lg->port, false);
+	}
+}
+
+int
+jzfb_gpio_ctrl_pins_no(const struct lcd_panel_info *info)
+{
+        switch (info->lcd_mode)
+        {
+	        case JZ_LCD_MODE_GENERIC_16_BIT:
+	        case JZ_LCD_MODE_GENERIC_18_BIT:
+	        case JZ_LCD_MODE_8BIT_SERIAL:
+			return (4);
+
+	        case JZ_LCD_MODE_SPECIAL_TFT_1:
+	        case JZ_LCD_MODE_SPECIAL_TFT_2:
+	        case JZ_LCD_MODE_SPECIAL_TFT_3:
+	                return (3);
+
+	        default:
+	                return (0);
+        }
+}
+
+int
+jzfb_gpio_data_pins_no(const struct lcd_panel_info *info)
+{
+        switch (info->lcd_mode)
+        {
+		case JZ_LCD_MODE_SPECIAL_TFT_1:
+		case JZ_LCD_MODE_SPECIAL_TFT_2:
+		case JZ_LCD_MODE_SPECIAL_TFT_3:
+		case JZ_LCD_MODE_GENERIC_16_BIT:
+			return (16);
+
+		case JZ_LCD_MODE_GENERIC_18_BIT:
+			return (18);
+
+		case JZ_LCD_MODE_8BIT_SERIAL:
+			return (8);
+
+		default:
+		        return (0);
+        }
+}
+
+static int
+jzfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
+{
+	struct vcons_data       *vd = v;
+	struct jzfb_softc       *sc = vd->cookie;
+	struct wsdisplay_fbinfo *wdf;
+	struct vcons_screen     *ms = vd->active;
+	int data_int;
+
+	switch (cmd) {
+		case WSDISPLAYIO_GTYPE:
+			*(u_int *)data = WSDISPLAY_TYPE_PCIMISC;
+			return (0);
+
+		case WSDISPLAYIO_GINFO:
+			if (ms == NULL)
+				return (ENODEV);
+			wdf = (void *)data;
+			wdf->height = ms->scr_ri.ri_height;
+			wdf->width = ms->scr_ri.ri_width;
+			wdf->depth = ms->scr_ri.ri_depth;
+			wdf->cmsize = 0;
+			return (0);
+
+		case WSDISPLAYIO_LINEBYTES:
+			*(u_int *)data = sc->sc_stride;
+			return (0);
+
+		case WSDISPLAYIO_GMODE:
+			*(u_int *)data = sc->sc_mode;
+			return (0);
+
+		case WSDISPLAYIO_SMODE:
+			data_int = *(int*)data;
+			/* notify the bus backend */
+			if (data_int != sc->sc_mode) {
+				sc->sc_mode = data_int;
+				if(data_int == WSDISPLAYIO_MODE_EMUL) {
+					vcons_redraw_screen(ms);
+				}
+			}
+			return (0);
+
+		case WSDISPLAYIO_GVIDEO:
+			*(u_int *)data = sc->sc_enabled ?
+				WSDISPLAYIO_VIDEO_ON : WSDISPLAYIO_VIDEO_OFF;
+			return (0);
+
+		case WSDISPLAYIO_SVIDEO:
+			data_int = *(int*)data;
+			if (data_int == WSDISPLAYIO_VIDEO_ON) {
+				jzfb_lcdc_enable(sc);
+			} else if (data_int == WSDISPLAYIO_VIDEO_OFF) {
+				jzfb_lcdc_disable(sc);
+			}
+			return (0);
+        }
+
+        return (EPASSTHROUGH);
+}
+
+static paddr_t
+jzfb_mmap(void *v, void *vs, off_t offset, int prot)
+{
+	paddr_t pa = -1;
+
+	printf("TODO %s\n", __FUNCTION__);
+
+	return (pa);
+}
+
+static void
+jzfb_init_screen(void *cookie, struct vcons_screen *scr, int existing, long *defattr)
+{
+	struct jzfb_softc  *sc = cookie;
+	const struct lcd_panel_info *info = sc->sc_panel_info;
+	struct rasops_info *ri = &scr->scr_ri;
+
+	ri->ri_width = info->xres;
+	ri->ri_height = info->yres;
+	ri->ri_depth = sc->sc_depth;
+	ri->ri_stride = sc->sc_stride;
+	ri->ri_flg = RI_CENTER | RI_FULLCLEAR;
+
+	ri->ri_bits = (char *)sc->sc_fbaddr;
+
+	scr->scr_flags |= VCONS_DONT_READ;
+
+	if (existing) {
+		ri->ri_flg |= RI_CLEAR;
+	}
+
+	rasops_init(ri, info->yres / 8, info->xres / 8);
+	ri->ri_caps = WSSCREEN_WSCOLORS;
+
+	rasops_reconfig(ri, info->yres / ri->ri_font->fontheight,
+	                info->xres / ri->ri_font->fontwidth);
+
+	ri->ri_hw = scr;
+}
+
+#if 0
+void jzfb_dump_regs(struct jzfb_softc *sc)
+{
+        uint32_t hsync, vsync, ht, vt, hds, vds, hde, vde, cfg, ctrl;
+        uint32_t tmp;
+
+        hsync = bus_space_read_4(sc->sc_bst, sc->sc_regh, JZ_REG_LCD_HSYNC);
+        vsync = bus_space_read_4(sc->sc_bst, sc->sc_regh, JZ_REG_LCD_VSYNC);
+
+        tmp = bus_space_read_4(sc->sc_bst, sc->sc_regh, JZ_REG_LCD_VAT);
+        ht = tmp >> 16;
+        vt = tmp & 0xffff;
+
+        tmp = bus_space_read_4(sc->sc_bst, sc->sc_regh, JZ_REG_LCD_DAH);
+        hds = tmp >> 16;
+        hde = tmp & 0xffff;
+
+        tmp = bus_space_read_4(sc->sc_bst, sc->sc_regh, JZ_REG_LCD_DAV);
+        vds = tmp >> 16;
+        vde = tmp & 0xffff;
+
+        cfg = bus_space_read_4(sc->sc_bst, sc->sc_regh, JZ_REG_LCD_CFG);
+        ctrl = bus_space_read_4(sc->sc_bst, sc->sc_regh, JZ_REG_LCD_CTRL);
+
+        printf("\n==[JZ47XX LCD controler register dump]==\n");
+        printf("HSYNC = %d\n", hsync);
+        printf("VSYNC = %d\n", vsync);
+        printf("HT = %d, VT = %d\n", ht, vt);
+        printf("HDS = %d, HDE = %d\n", hds, hde);
+        printf("VDS = %d, VDE = %d\n", vds, vde);
+        printf("CFG = 0x%x\n", cfg);
+        printf("CTRL = 0x%x\n", ctrl);
+        printf("LCD clk = %d, PIX clk = %d\n",
+                jz47xx_cpm_get_lcdclk(), jz47xx_cpm_get_pixclk());
+}
+#endif
diff --git a/sys/arch/mips/ingenic/dev/jzfb_var.h b/sys/arch/mips/ingenic/dev/jzfb_var.h
new file mode 100644
index 0000000..09600d0
--- /dev/null
+++ b/sys/arch/mips/ingenic/dev/jzfb_var.h
@@ -0,0 +1,97 @@
+/*-
+ * Copyright (c) 2011, Peter Tworek
+ * 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. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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.
+ */
+
+/*
+ * Platform specific bits for JZ47XX LCD controller driver.
+ */
+
+#ifndef _JZFB_VAR_H_
+#define _JZFB_VAR_H_
+
+#include <sys/types.h>
+
+#define JZ_LCD_CFG_SLCD               (1 << 31)
+#define JZ_LCD_CFG_PS_DISABLE         (1 << 23)
+#define JZ_LCD_CFG_CLS_DISABLE        (1 << 22)
+#define JZ_LCD_CFG_SPL_DISABLE        (1 << 21)
+#define JZ_LCD_CFG_REV_DISABLE        (1 << 20)
+#define JZ_LCD_CFG_HSYNCM             (1 << 19)
+#define JZ_LCD_CFG_PCLKM              (1 << 18)
+#define JZ_LCD_CFG_INV                (1 << 17)
+#define JZ_LCD_CFG_SYNC_DIR           (1 << 16)
+#define JZ_LCD_CFG_PS_POLARITY        (1 << 15)
+#define JZ_LCD_CFG_CLS_POLARITY       (1 << 14)
+#define JZ_LCD_CFG_SPL_POLARITY       (1 << 13)
+#define JZ_LCD_CFG_REV_POLARITY       (1 << 12)
+#define JZ_LCD_CFG_HSYNC_ACTIVE_LOW   (1 << 11)
+#define JZ_LCD_CFG_PCLK_FALLING_EDGE  (1 << 10)
+#define JZ_LCD_CFG_DE_ACTIVE_LOW      (1 << 9)
+#define JZ_LCD_CFG_VSYNC_ACTIVE_LOW   (1 << 8)
+#define JZ_LCD_CFG_18_BIT             (1 << 7)
+#define JZ_LCD_CFG_PDW                ((1 << 5) | (1 << 4))
+#define JZ_LCD_CFG_MODE_MASK          0xf
+
+#define JZ_LCD_MODE_GENERIC_16_BIT        0
+#define JZ_LCD_MODE_GENERIC_18_BIT        (1 << 4)
+#define JZ_LCD_MODE_SPECIAL_TFT_1         1
+#define JZ_LCD_MODE_SPECIAL_TFT_2         2
+#define JZ_LCD_MODE_SPECIAL_TFT_3         3
+#define JZ_LCD_MODE_NON_INTERLACED_CCI656 5
+#define JZ_LCD_MODE_INTERLACED_CCIR656    7
+#define JZ_LCD_MODE_SINGLE_COLOR_STN      8
+#define JZ_LCD_MODE_SINGLE_MONOCHROME_STN 9
+#define JZ_LCD_MODE_DUAL_COLOR_STN        10
+#define JZ_LCD_MODE_DUAL_MONOCHROME_STN   11
+#define JZ_LCD_MODE_8BIT_SERIAL           12
+
+/*
+ * LCD panel info that needs to be provided by the platform.
+ */
+struct lcd_panel_info {
+        uint32_t lcd_mode;
+        uint32_t cfg_base;
+
+        uint32_t xres;
+        uint32_t yres;
+        uint32_t bpp;   /* < 1...32 > */
+        uint32_t refresh;
+
+        uint32_t hds;
+        uint32_t vds;
+        uint32_t hde;
+        uint32_t vde;
+        uint32_t ht;
+        uint32_t vt;
+        uint32_t hsync;
+        uint32_t vsync;
+};
+
+extern struct lcd_panel_info jz47xx_lcd_panel_info;
+
+#endif /* !_JZFB_VAR_H_ */
diff --git a/sys/arch/mips/ingenic/dev/jzpm.c b/sys/arch/mips/ingenic/dev/jzpm.c
new file mode 100644
index 0000000..a3c2f42
--- /dev/null
+++ b/sys/arch/mips/ingenic/dev/jzpm.c
@@ -0,0 +1,127 @@
+/*-
+ * Copyright (c) 2011, Peter Tworek
+ * 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. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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.
+ */
+
+/*
+ * Power Management Unit driver for Jz47xx SOCs.
+ */
+
+#include <sys/cdefs.h>
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <mips/ingenic/dev/jzbus_var.h>
+#include <mips/ingenic/dev/jzpm_var.h>
+
+#include "locators.h"
+
+/*
+ * Clock reset and power controller registers.
+ */
+#define	CPM_REG_CLK_CTRL          0x00
+#define	CPM_REG_LOW_PWR_CTRL      0x04
+#define	CPM_REG_CLK_GATE          0x20
+#define	CPM_REG_SLEEP_CTRL        0x24
+
+#define CPM_READ32(sc, reg)       bus_space_read_4(sc->sc_bst, sc->sc_regh, (reg))
+#define CPM_WRITE32(sc, reg, val) bus_space_write_4(sc->sc_bst, sc->sc_regh, (reg), (val))
+
+struct jzpm_softc {
+	device_t		sc_dev;
+	bus_space_tag_t		sc_bst;
+	bus_space_handle_t	sc_regh;
+	bus_addr_t		sc_addr;
+	bus_size_t		sc_size;
+};
+
+static int  jzpm_match(device_t, struct cfdata *, void *);
+static void jzpm_attach(device_t, device_t, void *);
+
+CFATTACH_DECL_NEW(jzpm, sizeof(struct jzpm_softc),
+	jzpm_match, jzpm_attach, NULL, NULL);
+
+static struct jzpm_softc * sc_jzpm;
+
+int
+jzpm_match(device_t parent, struct cfdata *cf, void *aux)
+{
+	struct jzbus_attach_args *aa = aux;
+
+	if (strncmp(cf->cf_name, "jzpm", 4) != 0)
+		return (0);
+
+	if (cf->cf_unit != 0)
+		return (0);
+
+	if (aa->aa_addr == JZBUSCF_ADDR_DEFAULT ||
+	    aa->aa_size == JZBUSCF_SIZE_DEFAULT) {
+		printf("%s: addr and size have to be set in config!\n", cf->cf_name);
+		return (0);
+	}
+
+	return (1);
+}
+
+void
+jzpm_attach(device_t parent, device_t self, void *aux)
+{
+	struct jzpm_softc * const sc = device_private(self);
+	struct jzbus_attach_args *aa = aux;
+
+	aprint_normal("\n");
+
+	sc->sc_dev = self;
+	sc->sc_bst = aa->aa_bst;
+	sc->sc_addr = aa->aa_addr;
+	sc->sc_size = aa->aa_size;
+
+	sc_jzpm = sc;
+
+	if (bus_space_map(sc->sc_bst, sc->sc_addr, sc->sc_size, 0, &sc->sc_regh))
+		panic("%s: Cannot map registers", device_xname(self));
+
+	aprint_normal_dev(sc->sc_dev, "JzSOC Power Management Unit\n");
+}
+
+void
+jz47xx_dev_clk_set(jz_dev_clk_t clk, bool on)
+{
+	struct jzpm_softc * const sc = sc_jzpm;
+	uint32_t clk_gate = CPM_READ32(sc, CPM_REG_CLK_GATE);
+
+	KASSERT(sc);
+
+	if (on)
+		clk_gate &= ~(1 << clk);
+	else
+		clk_gate |= (1 << clk);
+
+	CPM_WRITE32(sc, CPM_REG_CLK_GATE, clk_gate);
+}
diff --git a/sys/arch/mips/ingenic/dev/jzpm_var.h b/sys/arch/mips/ingenic/dev/jzpm_var.h
new file mode 100644
index 0000000..9a3de5d
--- /dev/null
+++ b/sys/arch/mips/ingenic/dev/jzpm_var.h
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 2011, Peter Tworek
+ * 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. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _JZPM_VAR_H_
+#define _JZPM_VAR_H_
+
+typedef enum jz_dev_clk {
+	JZ_CLK_UART0		= 0,
+	JZ_CLK_TCU		= 1,
+	JZ_CLK_RTC		= 2,
+	JZ_CLK_I2C		= 3,
+	JZ_CLK_SSI		= 4,
+	JZ_CLK_AIC_pclk 	= 5,
+	JZ_CLK_AIC_bit_i2s 	= 6,
+	JZ_CLK_MSC		= 7,
+	JZ_CLK_SADC		= 8,
+	JZ_CLK_CIM		= 9,
+	JZ_CLK_LCD		= 10,
+	JZ_CLK_UDC		= 11,
+	JZ_CLK_DMAC		= 12,
+	JZ_CLK_IPU		= 13,
+	JZ_CLK_UHC		= 14,
+	JZ_CLK_UART1		= 15
+} jz_dev_clk_t;
+
+#define jz47xx_dev_clk_enable(clk)  jz47xx_dev_clk_set(clk, true)
+#define jz47xx_dev_clk_disable(clk) jz47xx_dev_clk_set(clk, false)
+
+void     jz47xx_dev_clk_set(jz_dev_clk_t, bool);
+
+#endif /* !_JZPM_VAR_H_ */
diff --git a/sys/arch/mips/ingenic/dev/jzrtc.c b/sys/arch/mips/ingenic/dev/jzrtc.c
new file mode 100644
index 0000000..0be3bb5
--- /dev/null
+++ b/sys/arch/mips/ingenic/dev/jzrtc.c
@@ -0,0 +1,153 @@
+/*-
+ * Copyright (c) 2011, Peter Tworek
+ * 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. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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>
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <dev/clock_subr.h>
+
+#include <mips/cpuregs.h>
+
+#include <mips/ingenic/include/jz47xxreg.h>
+#include <mips/ingenic/dev/jzbus_var.h>
+#include <mips/ingenic/dev/jzpm_var.h>
+
+/*
+ * Real time clock registets
+ */
+#define RTC_CTRL      0x00
+#define RTC_SEC       0x04
+#define RTC_SEC_ALARM 0x08
+#define RTC_REG       0x0c
+
+/*
+ * RTC control register bits
+ */
+#define RTC_CTRL_WRDY   (1 << 7)
+#define RTC_CTRL_1HZ    (1 << 6)
+#define RTC_CTRL_1HZIE  (1 << 5)
+#define RTC_CTRL_AF     (1 << 4)
+#define RTC_CTRL_AIE    (1 << 3)
+#define RTC_CTRL_AE     (1 << 2)
+#define RTC_CTRL_RTCE   (1 << 0)
+
+#define REGVAL(x)         *((volatile uint32_t *)(MIPS_PHYS_TO_KSEG1((x))))
+#define RTC_GET_REG(x)    REGVAL((x) + JZ_RTC_BASE)
+#define RTC_PUT_REG(x,v)  (REGVAL((x) + JZ_RTC_BASE)) = (v)
+
+struct jzrtc_softc {
+        struct device	        sc_dev;
+        struct todr_chip_handle sc_tch;
+        void                    *sc_shutdownhook;
+};
+
+static int  jzrtc_match(device_t, struct cfdata *, void *);
+static void jzrtc_attach(device_t, device_t, void *);
+static int  jzrtc_gettime(todr_chip_handle_t, struct timeval *);
+static int  jzrtc_settime(todr_chip_handle_t, struct timeval *);
+static void jzrtc_shutdown(void *);
+
+CFATTACH_DECL(jzrtc, sizeof(struct jzrtc_softc),
+	jzrtc_match, jzrtc_attach, NULL, NULL);
+
+
+static int
+jzrtc_match(device_t parent, struct cfdata *cf, void *aux)
+{
+	/* struct jzbus_attach_args *aa = aux; */
+
+	if (strncmp(cf->cf_name, "jzrtc", 5) == 0) {
+		return (1);
+	}
+
+	return (0);
+}
+
+static void
+jzrtc_attach(device_t parent, device_t self, void *aux)
+{
+	struct jzrtc_softc * const sc = device_private(self);
+
+	sc->sc_tch.cookie = sc;
+	sc->sc_tch.bus_cookie = NULL;
+	sc->sc_tch.todr_gettime = jzrtc_gettime;
+	sc->sc_tch.todr_settime = jzrtc_settime;
+	sc->sc_tch.todr_setwen = NULL;
+
+	/* Enable device clock */
+	jz47xx_dev_clk_enable(JZ_CLK_RTC);
+
+	sc->sc_shutdownhook = shutdownhook_establish(jzrtc_shutdown, NULL);
+	aprint_normal("\n");
+
+	todr_attach(&sc->sc_tch);
+}
+
+static int
+jzrtc_gettime(todr_chip_handle_t hnd, struct timeval *tv)
+{
+	int s = splclock();
+
+	/* Wait until RTC is ready */
+	while (!(RTC_GET_REG(RTC_CTRL) & RTC_CTRL_WRDY));
+
+	tv->tv_sec = RTC_GET_REG(RTC_SEC);
+
+	splx(s);
+
+	return (0);
+}
+
+static int
+jzrtc_settime(todr_chip_handle_t hnd, struct timeval *tvp)
+{
+	struct timeval tv;
+	int	s;
+
+	s = splclock();
+	tv = *tvp;
+	splx(s);
+
+	/* Wait until we can actually write to RTC registers */
+	while (!(RTC_GET_REG(RTC_CTRL) & RTC_CTRL_WRDY));
+
+	RTC_PUT_REG(RTC_SEC, tv.tv_sec);
+
+	return (0);
+}
+
+static void
+jzrtc_shutdown(void *arg)
+{
+	/* Disable device clock */
+	jz47xx_dev_clk_disable(JZ_CLK_RTC);
+}
diff --git a/sys/arch/mips/ingenic/dev/jztcu.c b/sys/arch/mips/ingenic/dev/jztcu.c
new file mode 100644
index 0000000..5a4bfe7
--- /dev/null
+++ b/sys/arch/mips/ingenic/dev/jztcu.c
@@ -0,0 +1,346 @@
+/*-
+ * Copyright (c) 2011, Peter Tworek
+ * 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. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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.
+ */
+
+/*
+ * Timer Control Unit for Jz47xx SOCs.
+ */
+
+#include <sys/cdefs.h>
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <mips/ingenic/dev/jzbus_var.h>
+#include <mips/ingenic/dev/jztcu_var.h>
+#include <mips/ingenic/dev/jzpm_var.h>
+
+#include "locators.h"
+
+/*
+ * Total number of possible timers.
+ */
+#define TCU_TIMER_NO	8
+
+/*
+ * TCU registers.
+ */
+#define	TCU_REG_STOP          0x1C
+#define	TCU_REG_STOP_SET      0x2C
+#define	TCU_REG_STOP_CLR      0x3C
+#define	TCU_REG_ENABLE        0x10
+#define	TCU_REG_ENABLE_SET    0x14
+#define	TCU_REG_ENABLE_CLR    0x18
+#define	TCU_REG_FLAG          0x20
+#define	TCU_REG_FLAG_SET      0x24
+#define	TCU_REG_FLAG_CLR      0x28
+#define	TCU_REG_MASK          0x30
+#define	TCU_REG_MASK_SET      0x34
+#define	TCU_REG_MASK_CLR      0x38
+#define TCU_REG_DATA_FULL(x)  ((x * 0x10) + 0x40)
+#define TCU_REG_DATA_HALF(x)  ((x * 0x10) + 0x44)
+#define TCU_REG_COUNT(x)      ((x * 0x10) + 0x48)
+#define TCU_REG_CTRL(x)       ((x * 0x10) + 0x4C)
+
+/*
+ * CTRL register bits.
+ */
+#define	TCU_CTRL_PCK_EN         (1 << 0)
+#define	TCU_CTRL_RTC_EN         (1 << 1)
+#define	TCU_CTRL_EXT_EN         (1 << 2)
+#define	TCU_CTRL_PWM_EN         (1 << 7)
+#define	TCU_CTRL_INITL          (1 << 8)
+#define	TCU_CTRL_SD             (1 << 9)
+#define	TCU_CTRL_PRESCALE_MASK  0x38
+#define	TCU_CTRL_PRESCALE_SHIFT 3
+
+#define TCU_READ8(sc, reg) bus_space_read_1(sc->sc_bst, sc->sc_regh, (reg))
+#define TCU_READ16(sc, reg) bus_space_read_2(sc->sc_bst, sc->sc_regh, (reg))
+#define TCU_READ32(sc, reg) bus_space_read_4(sc->sc_bst, sc->sc_regh, (reg))
+#define TCU_WRITE8(sc, reg, val) bus_space_write_1(sc->sc_bst, sc->sc_regh, (reg), (val))
+#define TCU_WRITE16(sc, reg, val) bus_space_write_2(sc->sc_bst, sc->sc_regh, (reg), (val))
+#define TCU_WRITE32(sc, reg, val) bus_space_write_4(sc->sc_bst, sc->sc_regh, (reg), (val))
+
+struct jztcu_softc {
+	device_t		sc_dev;
+	bus_space_tag_t		sc_bst;
+	bus_space_handle_t	sc_regh;
+	bus_addr_t		sc_addr;
+	bus_size_t		sc_size;
+};
+
+static int  jztcu_match(device_t, struct cfdata *, void *);
+static void jztcu_attach(device_t, device_t, void *);
+static int  jztcu_find(device_t, cfdata_t, const int *, void *);
+static int  jztcu_print(void *, const char *);
+
+CFATTACH_DECL_NEW(jztcu, sizeof(struct jztcu_softc),
+	jztcu_match, jztcu_attach, NULL, NULL);
+
+int
+jztcu_match(device_t parent, struct cfdata *cf, void *aux)
+{
+	struct jzbus_attach_args *aa = aux;
+
+	if (strncmp(cf->cf_name, "jztcu", 5) != 0)
+		return (0);
+
+	if (cf->cf_unit != 0)
+		return (0);
+
+	if (aa->aa_addr == JZBUSCF_ADDR_DEFAULT ||
+	    aa->aa_size == JZBUSCF_SIZE_DEFAULT) {
+		printf("%s: addr and size have to be set in config!\n", cf->cf_name);
+		return (0);
+	}
+
+	return (1);
+}
+
+void
+jztcu_attach(device_t parent, device_t self, void *aux)
+{
+	struct jztcu_softc * const sc = device_private(self);
+	struct jzbus_attach_args *aa = aux;
+	struct jztcu_attach_args taa;
+	cfdata_t cf;
+	int i;
+
+	sc->sc_dev = self;
+	sc->sc_bst = aa->aa_bst;
+	sc->sc_addr = aa->aa_addr;
+	sc->sc_size = aa->aa_size;
+
+	if (bus_space_map(sc->sc_bst, sc->sc_addr, sc->sc_size, 0, &sc->sc_regh))
+		panic("%s: Cannot map registers", device_xname(self));
+
+	aprint_normal("\n");
+
+	/* Enable TCU module in clock gate register */
+	jz47xx_dev_clk_enable(JZ_CLK_TCU);
+
+	/* Attach sub timers */
+	for (i = 0; i < TCU_TIMER_NO; i++) {
+		taa.aa_intr = JZTCUCF_INTR_DEFAULT;
+		taa.aa_unit = i;
+		taa.aa_func = JZTCUCF_FUNCTION_DEFAULT;
+
+		cf = config_search_ia(jztcu_find, sc->sc_dev, "jztcu", &taa);
+		if (cf == NULL) {
+			continue;
+		}
+
+		config_attach(sc->sc_dev, cf, &taa, jztcu_print);
+	}
+}
+
+int
+jztcu_find(device_t parent, cfdata_t cf, const int *ldesc, void *aux)
+{
+	struct jztcu_attach_args *aa = aux;
+
+	if (aa->aa_intr != JZTCUCF_INTR_DEFAULT &&
+	    aa->aa_intr != cf->cf_loc[JZTCUCF_INTR])
+		return (0);
+
+	if (aa->aa_func != JZTCUCF_FUNCTION_DEFAULT &&
+	    aa->aa_func != cf->cf_loc[JZTCUCF_FUNCTION])
+		return (0);
+
+	aa->aa_intr = cf->cf_loc[JZTCUCF_INTR];
+	aa->aa_unit = cf->cf_unit;
+	aa->aa_func = cf->cf_loc[JZTCUCF_FUNCTION];
+
+	return config_match(parent, cf, aa);
+}
+
+int
+jztcu_print(void *aux, const char *pnp)
+{
+	struct jztcu_attach_args *aa = aux;
+
+	switch (aa->aa_func) {
+
+		case JZTIMER_FUNCTION_OST:
+			aprint_normal(": OS Timer");
+			break;
+
+		case JZTIMER_FUNCTION_STAT:
+			aprint_normal(": Statistics Timer");
+			break;
+
+		case JZTIMER_FUNCTION_REF:
+			aprint_normal(": Reference Timer");
+			break;
+
+		default:
+			aprint_normal(": not configured");
+			break;
+
+	}
+
+	return (UNCONF);
+}
+
+void
+jztcu_timer_select_source(device_t self, int tmr, jztimer_source_t src)
+{
+	struct jztcu_softc * const sc = device_private(self);
+	uint16_t tmp16 = TCU_READ16(sc, TCU_REG_CTRL(tmr));
+	tmp16 &= ~(TCU_CTRL_PWM_EN | TCU_CTRL_RTC_EN | TCU_CTRL_PCK_EN | TCU_CTRL_EXT_EN);
+	switch (src) {
+
+		case JZTIMER_SOURCE_EXTAL:
+			tmp16 |= TCU_CTRL_EXT_EN;
+			break;
+
+		case JZTIMER_SOURCE_RTC:
+			tmp16 |= TCU_CTRL_RTC_EN;
+			break;
+
+		case JZTIMER_SOURCE_PCLK:
+			tmp16 |= TCU_CTRL_PCK_EN;
+			break;
+
+	}
+	TCU_WRITE16(sc, TCU_REG_CTRL(tmr), tmp16);
+}
+
+void
+jztcu_timer_set_match(device_t self, int tmr, jztimer_match_t mt)
+{
+	struct jztcu_softc * const sc = device_private(self);
+
+	switch (mt) {
+
+		case JZTIMER_MATCH_NONE:
+			TCU_WRITE32(sc, TCU_REG_MASK_SET, (1 << tmr) | (1 << (tmr +16)));
+			break;
+
+		case JZTIMER_MATCH_FULL:
+			TCU_WRITE32(sc, TCU_REG_MASK_CLR, (1 << tmr));
+			TCU_WRITE32(sc, TCU_REG_FLAG_CLR, (1 << tmr));
+			TCU_WRITE32(sc, TCU_REG_MASK_SET, (1 << (tmr + 16)));
+			break;
+
+		case JZTIMER_MATCH_BOTH:
+			TCU_WRITE32(sc, TCU_REG_MASK_CLR, (1 << tmr) | (1 << (tmr + 16)));
+			TCU_WRITE32(sc, TCU_REG_FLAG_CLR, (1 << tmr) | (1 << (tmr + 16)));
+			break;
+
+	}
+}
+
+void
+jztcu_timer_set_prescale(device_t self, int tmr, int value)
+{
+	struct jztcu_softc * const sc = device_private(self);
+	uint16_t tmp16 = TCU_READ16(sc, TCU_REG_CTRL(tmr));
+	tmp16 &= ~TCU_CTRL_PRESCALE_MASK;
+	switch (value) {
+
+		case 1:
+			break;
+		case 4:
+			tmp16 |= (1 << TCU_CTRL_PRESCALE_SHIFT);
+			break;
+		case 16:
+			tmp16 |= (2 << TCU_CTRL_PRESCALE_SHIFT);
+			break;
+		case 64:
+			tmp16 |= (3 << TCU_CTRL_PRESCALE_SHIFT);
+			break;
+		case 256:
+			tmp16 |= (4 << TCU_CTRL_PRESCALE_SHIFT);
+			break;
+		case 1024:
+			tmp16 |= (5 << TCU_CTRL_PRESCALE_SHIFT);
+			break;
+		default:
+			panic("Invalid presale value!");
+
+	}
+	TCU_WRITE16(sc, TCU_REG_CTRL(tmr), tmp16);
+}
+
+void
+jztcu_timer_set_full(device_t self, int tmr, uint16_t value)
+{
+	struct jztcu_softc * const sc = device_private(self);
+	TCU_WRITE16(sc, TCU_REG_DATA_FULL(tmr), value);
+}
+
+void
+jztcu_timer_set_half(device_t self, int tmr, uint16_t value)
+{
+	struct jztcu_softc * const sc = device_private(self);
+	TCU_WRITE16(sc, TCU_REG_DATA_HALF(tmr), value);
+}
+
+void
+jztcu_timer_clear(device_t self, int tmr)
+{
+	struct jztcu_softc * const sc = device_private(self);
+	TCU_WRITE16(sc, TCU_REG_COUNT(tmr), 0);
+}
+
+void
+jztcu_timer_start(device_t self, int tmr)
+{
+	struct jztcu_softc * const sc = device_private(self);
+	TCU_WRITE8(sc, TCU_REG_ENABLE_SET, (1 << tmr));
+}
+
+void
+jztcu_timer_stop(device_t self, int tmr)
+{
+	struct jztcu_softc * const sc = device_private(self);
+	TCU_WRITE8(sc, TCU_REG_ENABLE_CLR, (1 << tmr));
+}
+
+uint16_t
+jztcu_timer_read(device_t self, int tmr)
+{
+	struct jztcu_softc * const sc = device_private(self);
+	return TCU_READ16(sc, TCU_REG_COUNT(tmr));
+}
+
+void*
+jztcu_intr_establish(int intr, int (*handler)(void *), void *arg)
+{
+
+	return jzbus_intr_establish(intr, handler, arg);
+}
+
+void
+jztcu_intr_disestablish(void *arg)
+{
+
+	jzbus_intr_disestablish(arg);
+}
diff --git a/sys/arch/mips/ingenic/dev/jztcu_var.h b/sys/arch/mips/ingenic/dev/jztcu_var.h
new file mode 100644
index 0000000..961248e
--- /dev/null
+++ b/sys/arch/mips/ingenic/dev/jztcu_var.h
@@ -0,0 +1,72 @@
+/*-
+ * Copyright (c) 2011, Peter Tworek
+ * 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. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _JZTCU_VAR_H_
+#define _JZTCU_VAR_H_
+
+#include <sys/cdefs.h>
+
+typedef enum jztimer_function {
+	JZTIMER_FUNCTION_NONE = 0,
+	JZTIMER_FUNCTION_OST  = 1,
+	JZTIMER_FUNCTION_STAT = 2,
+	JZTIMER_FUNCTION_REF  = 3
+} jztimer_function_t;
+
+struct jztcu_attach_args {
+	int			aa_intr;
+	int			aa_unit;
+	jztimer_function_t	aa_func;
+};
+
+typedef enum jztimer_source {
+	JZTIMER_SOURCE_EXTAL,
+	JZTIMER_SOURCE_RTC,
+	JZTIMER_SOURCE_PCLK
+} jztimer_source_t;
+
+typedef enum jztimer_match {
+	JZTIMER_MATCH_NONE,
+	JZTIMER_MATCH_FULL,
+	JZTIMER_MATCH_BOTH
+} jztimer_match_t;
+
+inline void     jztcu_timer_select_source(device_t, int, jztimer_source_t);
+inline void     jztcu_timer_set_match(device_t, int, jztimer_match_t);
+inline void     jztcu_timer_set_prescale(device_t, int, int);
+inline void     jztcu_timer_set_full(device_t, int, uint16_t);
+inline void     jztcu_timer_set_half(device_t, int, uint16_t);
+inline void     jztcu_timer_clear(device_t, int);
+inline void     jztcu_timer_start(device_t, int);
+inline void     jztcu_timer_stop(device_t, int);
+inline uint16_t jztcu_timer_read(device_t, int);
+inline void*    jztcu_intr_establish(int, int (*)(void *), void *);
+inline void     jztcu_intr_disestablish(void *);
+
+#endif /* !_JZTCU_VAR_H_ */
diff --git a/sys/arch/mips/ingenic/dev/jztimer.c b/sys/arch/mips/ingenic/dev/jztimer.c
new file mode 100644
index 0000000..f2e9a14
--- /dev/null
+++ b/sys/arch/mips/ingenic/dev/jztimer.c
@@ -0,0 +1,333 @@
+/*-
+ * Copyright (c) 2011, Peter Tworek
+ * 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. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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>
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/timetc.h>
+#include <sys/device.h>
+
+#include <mips/ingenic/dev/jztcu_var.h>
+#include <mips/ingenic/include/jz47xxreg.h>
+#include <mips/ingenic/include/jz47xx_clk.h>
+
+#include "locators.h"
+
+#define JZTIMER_MAX_VAL UINT16_MAX
+
+struct jztimer_cfg {
+	jztimer_source_t	tcf_src;
+	jztimer_match_t		tcf_match;
+	int			tcf_div;
+	int			tcf_half_div;
+	void			*tcf_ih;
+};
+
+struct jztimer_softc {
+	device_t           		sc_dev;
+	device_t			sc_tcu;
+	uint32_t			sc_tmr;
+	uint32_t			sc_freq;
+	int				sc_intr;
+	const struct jztimer_cfg	*sc_cfg;
+	void				*sc_ih_cookie;
+};
+
+static int  jztimer_match(device_t, struct cfdata *, void *);
+static void jztimer_attach(device_t, device_t, void *);
+
+CFATTACH_DECL_NEW(jztimer, sizeof(struct jztimer_softc),
+	jztimer_match, jztimer_attach, NULL, NULL);
+
+jztimer_function_t jztimer_function_find(struct jztcu_attach_args *);
+static void        jztimer_init(struct jztimer_softc *, int);
+static uint32_t    jztimer_read_ost(void);
+static int         jztimer_intr_ost(void *);
+static int         jztimer_intr_stat(void *);
+
+static struct jztimer_softc * ost_sc;
+static struct jztimer_softc * ref_sc;
+static struct jztimer_softc * stat_sc;
+
+const static struct jztimer_cfg ost_cfg = {
+	.tcf_src	= JZTIMER_SOURCE_EXTAL,
+	.tcf_match	= JZTIMER_MATCH_FULL,
+	.tcf_div	= 4,
+	.tcf_half_div	= 0,
+	.tcf_ih		= jztimer_intr_ost
+};
+
+const static struct jztimer_cfg ref_cfg = {
+	.tcf_src	= JZTIMER_SOURCE_PCLK,
+	.tcf_match	= JZTIMER_MATCH_NONE,
+	.tcf_div	= 16,
+	.tcf_half_div	= 0,
+	.tcf_ih		= NULL
+};
+
+const static struct jztimer_cfg stat_cfg = {
+	.tcf_src	= JZTIMER_SOURCE_EXTAL,
+	.tcf_match	= JZTIMER_MATCH_FULL,
+	.tcf_div	= 4,
+	.tcf_half_div	= 0,
+	.tcf_ih		= jztimer_intr_stat
+};
+
+static struct timecounter ost_tc = {
+	(timecounter_get_t *)jztimer_read_ost,	/* get_timecount */
+	0,					/* no poll_pps */
+	0x0000ffff,				/* counter_mask */
+	JZ_EXTAL/4,				/* frequency */
+	"ost",					/* name*/
+	100,					/* quality */
+};
+
+static int
+jztimer_match(device_t parent, struct cfdata *cf, void *aux)
+{
+	struct jztcu_attach_args *aa = aux;
+
+	if (strncmp(cf->cf_name, "jztimer", 7) != 0)
+		return (0);
+
+	if (cf->cf_loc[JZTCUCF_FUNCTION] == JZTCUCF_FUNCTION_DEFAULT)
+		aa->aa_func = jztimer_function_find(aa);
+
+	return (1);
+}
+
+void
+jztimer_attach(device_t parent, device_t self, void *aux)
+{
+	struct jztimer_softc * const sc = device_private(self);
+	struct jztcu_attach_args *aa = aux;
+
+	sc->sc_dev = self;
+	sc->sc_tcu = parent;
+	sc->sc_tmr = aa->aa_unit;
+	sc->sc_intr = aa->aa_intr;
+
+	aprint_normal("\n");
+
+	switch (aa->aa_func) {
+
+		case JZTIMER_FUNCTION_OST:
+			KASSERT(!ost_sc);
+			sc->sc_cfg = &ost_cfg;
+			ost_sc = sc;
+			jztimer_init(sc, hz);
+			tc_init(&ost_tc);
+			break;
+
+		case JZTIMER_FUNCTION_STAT:
+			KASSERT(!stat_sc);
+			sc->sc_cfg = &stat_cfg;
+			stat_sc = sc;
+			stathz = hz;
+			jztimer_init(sc, stathz);
+			break;
+
+		case JZTIMER_FUNCTION_REF:
+			KASSERT(!ref_sc);
+			sc->sc_cfg = &ref_cfg;
+			ref_sc = sc;
+			jztimer_init(sc, 0);
+			break;
+
+		default:
+			break;
+
+	}
+}
+
+jztimer_function_t
+jztimer_function_find(struct jztcu_attach_args *aa)
+{
+	if (aa->aa_intr > 0) {
+		if (ost_sc == NULL)
+			return (JZTIMER_FUNCTION_OST);
+		else if (ref_sc == NULL)
+			return (JZTIMER_FUNCTION_REF);
+		else if (stat_sc == NULL)
+			return (JZTIMER_FUNCTION_STAT);
+		else
+			return (JZTIMER_FUNCTION_NONE);
+	} else if (ref_sc == NULL) {
+		return (JZTIMER_FUNCTION_REF);
+	}
+
+	return (JZTIMER_FUNCTION_NONE);
+}
+
+void
+jztimer_init(struct jztimer_softc *sc, int ahz)
+{
+	uint16_t full = JZTIMER_MAX_VAL;
+	uint16_t half = 0;
+
+	switch (sc->sc_cfg->tcf_src) {
+
+		case JZTIMER_SOURCE_EXTAL:
+			aprint_normal_dev(sc->sc_dev, "clkin EXTAL");
+			sc->sc_freq = JZ_EXTAL / sc->sc_cfg->tcf_div;
+			break;
+
+		case JZTIMER_SOURCE_RTC:
+			aprint_normal_dev(sc->sc_dev, "clkin RTC");
+			sc->sc_freq = JZ_RTCCLK / sc->sc_cfg->tcf_div;
+			break;
+
+		case JZTIMER_SOURCE_PCLK:
+			aprint_normal_dev(sc->sc_dev, "clkin PCLK");
+			sc->sc_freq = jz47xx_clk_get(JZ_PCLK) / sc->sc_cfg->tcf_div;
+			break;
+	}
+	aprint_normal(", freq %dMHz", sc->sc_freq / 1000000);
+
+	if (ahz > 0) {
+		full = sc->sc_freq / ahz;
+		if (sc->sc_cfg->tcf_half_div > 0) {
+			KASSERT(sc->sc_cfg->tcf_match == JZTIMER_MATCH_BOTH);
+			half = full / sc->sc_cfg->tcf_half_div;
+		} else {
+			KASSERT(sc->sc_cfg->tcf_match == JZTIMER_MATCH_FULL);
+		}
+	} else {
+		KASSERT(sc->sc_cfg->tcf_match == JZTIMER_MATCH_NONE);
+	}
+
+	jztcu_timer_stop(sc->sc_tcu, sc->sc_tmr);
+	jztcu_timer_select_source(sc->sc_tcu, sc->sc_tmr, sc->sc_cfg->tcf_src);
+	jztcu_timer_set_prescale(sc->sc_tcu, sc->sc_tmr, sc->sc_cfg->tcf_div);
+	jztcu_timer_set_match(sc->sc_tcu, sc->sc_tmr, sc->sc_cfg->tcf_match);
+	jztcu_timer_set_full(sc->sc_tcu, sc->sc_tmr, full);
+	jztcu_timer_set_half(sc->sc_tcu, sc->sc_tmr, half);
+	jztcu_timer_clear(sc->sc_tcu, sc->sc_tmr);
+
+	if (sc->sc_intr > 0 && sc->sc_cfg->tcf_ih != NULL) {
+		aprint_normal(", intr %d", sc->sc_intr);
+		if (sc->sc_ih_cookie == NULL) {
+			sc->sc_ih_cookie = jztcu_intr_establish(sc->sc_intr,
+				                                sc->sc_cfg->tcf_ih,
+				                                NULL);
+		}
+	}
+
+	jztcu_timer_start(sc->sc_tcu, sc->sc_tmr);
+	aprint_normal("\n");
+}
+
+uint32_t jztimer_read_ost(void)
+{
+	KASSERT(ost_sc);
+	return jztcu_timer_read(ost_sc->sc_tcu, ost_sc->sc_tmr);
+}
+__weak_alias(cpu_counter32, jztimer_read_ost);
+
+int
+jztimer_intr_ost(void *frame)
+{
+	KASSERT(frame);
+	hardclock(frame);
+	return (1);
+}
+
+int
+jztimer_intr_stat(void *frame)
+{
+	KASSERT(frame);
+	statclock(frame);
+	return (1);
+}
+
+void
+setstatclockrate(int newhz)
+{
+	KASSERT(newhz > 0);
+	if (stat_sc) {
+		if (stathz != newhz) {
+			stathz = newhz;
+			jztimer_init(stat_sc, stathz);
+		}
+	} else {
+		printf("Statistics timer was not configured!\n");
+	}
+}
+
+void
+delay(int n)
+{
+	uint16_t divisor_delay;
+	uint16_t cur, last, delta, usecs;
+
+	KASSERT(ref_sc);
+
+	last = jztcu_timer_read(ref_sc->sc_tcu, ref_sc->sc_tmr);
+	delta = usecs = 0;
+
+	divisor_delay = ref_sc->sc_freq / 1000000;
+
+	while (n > usecs) {
+		cur = jztcu_timer_read(ref_sc->sc_tcu, ref_sc->sc_tmr);
+
+		/* Handle overflow case */
+		if (cur < last) {
+			delta += (JZTIMER_MAX_VAL - last) + cur;
+		} else {
+			delta += (cur - last);
+		}
+		last = cur;
+
+		while (delta >= divisor_delay) {
+			/*
+			 * delta is not so larger than divisor_delay here,
+			 * and using DIV/DIVU ops could be much slower.
+			 * (though longer delay may be harmless)
+			 */
+			usecs++;
+			delta -= divisor_delay;
+		}
+	}
+}
+
+void
+cpu_initclocks(void)
+{
+	/*
+	 * By the time this function is called at least OST and REF
+	 * timers should be initialized. All that is left to do is
+	 * unmasking the interrupts.
+	 */
+	KASSERT(ost_sc);
+	KASSERT(ref_sc);
+	spl0();
+}
diff --git a/sys/arch/mips/ingenic/include/jz47xx_clk.h b/sys/arch/mips/ingenic/include/jz47xx_clk.h
new file mode 100644
index 0000000..fbc4f69
--- /dev/null
+++ b/sys/arch/mips/ingenic/include/jz47xx_clk.h
@@ -0,0 +1,55 @@
+/*-
+ * Copyright (c) 2011, Peter Tworek
+ * 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. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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.
+ */
+
+/*
+ * Clock frequency related routines for Ingenic JZ47xx SOCs.
+ */
+
+#ifndef _JZ47XX_CLK_H_
+#define _JZ47XX_CLK_H_
+
+#include <sys/types.h>
+
+typedef enum jzclk {
+	JZ_CCLK = 0,
+	JZ_HCLK,
+	JZ_PCLK,
+	JZ_MCLK,
+	JZ_CKO,
+	JZ_LCDCLK,
+	JZ_PIXCLK,
+	JZ_I2SCLK,
+	JZ_MSCCLK,
+	JZ_12M
+} jzclk_t;
+
+uint32_t jz47xx_clk_get(jzclk_t);
+void     jz47xx_clk_set(jzclk_t, uint32_t);
+
+#endif /* _JZ47XX_CLK_H */
diff --git a/sys/arch/mips/ingenic/include/jz47xx_gpio_reg.h b/sys/arch/mips/ingenic/include/jz47xx_gpio_reg.h
new file mode 100644
index 0000000..6c0578c
--- /dev/null
+++ b/sys/arch/mips/ingenic/include/jz47xx_gpio_reg.h
@@ -0,0 +1,359 @@
+/*-
+ * Copyright (c) 2011, Peter Tworek
+ * 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. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _JZ47XX_GPIO_REG_H_
+#define _JZ47XX_GPIO_REG_H_
+
+#define JZ_GPIO_PORTA(x) ((x) + 32 * 0)
+#define JZ_GPIO_PORTB(x) ((x) + 32 * 1)
+#define JZ_GPIO_PORTC(x) ((x) + 32 * 2)
+#define JZ_GPIO_PORTD(x) ((x) + 32 * 3)
+
+#define JZ_GPIO_FUNC_NONE  0
+#define JZ_GPIO_FUNC_1	   1
+#define JZ_GPIO_FUNC_2     2
+#define JZ_GPIO_FUNC_3     3
+
+/*
+ * Port A function pins
+ */
+#define JZ_GPIO_MEM_DATA0		JZ_GPIO_PORTA(0)
+#define JZ_GPIO_MEM_DATA1		JZ_GPIO_PORTA(1)
+#define JZ_GPIO_MEM_DATA2		JZ_GPIO_PORTA(2)
+#define JZ_GPIO_MEM_DATA3		JZ_GPIO_PORTA(3)
+#define JZ_GPIO_MEM_DATA4		JZ_GPIO_PORTA(4)
+#define JZ_GPIO_MEM_DATA5		JZ_GPIO_PORTA(5)
+#define JZ_GPIO_MEM_DATA6		JZ_GPIO_PORTA(6)
+#define JZ_GPIO_MEM_DATA7		JZ_GPIO_PORTA(7)
+#define JZ_GPIO_MEM_DATA8		JZ_GPIO_PORTA(8)
+#define JZ_GPIO_MEM_DATA9		JZ_GPIO_PORTA(9)
+#define JZ_GPIO_MEM_DATA10		JZ_GPIO_PORTA(10)
+#define JZ_GPIO_MEM_DATA11		JZ_GPIO_PORTA(11)
+#define JZ_GPIO_MEM_DATA12		JZ_GPIO_PORTA(12)
+#define JZ_GPIO_MEM_DATA13		JZ_GPIO_PORTA(13)
+#define JZ_GPIO_MEM_DATA14		JZ_GPIO_PORTA(14)
+#define JZ_GPIO_MEM_DATA15		JZ_GPIO_PORTA(15)
+#define JZ_GPIO_MEM_DATA16		JZ_GPIO_PORTA(16)
+#define JZ_GPIO_MEM_DATA17		JZ_GPIO_PORTA(17)
+#define JZ_GPIO_MEM_DATA18		JZ_GPIO_PORTA(18)
+#define JZ_GPIO_MEM_DATA19		JZ_GPIO_PORTA(19)
+#define JZ_GPIO_MEM_DATA20		JZ_GPIO_PORTA(20)
+#define JZ_GPIO_MEM_DATA21		JZ_GPIO_PORTA(21)
+#define JZ_GPIO_MEM_DATA22		JZ_GPIO_PORTA(22)
+#define JZ_GPIO_MEM_DATA23		JZ_GPIO_PORTA(23)
+#define JZ_GPIO_MEM_DATA24		JZ_GPIO_PORTA(24)
+#define JZ_GPIO_MEM_DATA25		JZ_GPIO_PORTA(25)
+#define JZ_GPIO_MEM_DATA26		JZ_GPIO_PORTA(26)
+#define JZ_GPIO_MEM_DATA27		JZ_GPIO_PORTA(27)
+#define JZ_GPIO_MEM_DATA28		JZ_GPIO_PORTA(28)
+#define JZ_GPIO_MEM_DATA29		JZ_GPIO_PORTA(29)
+#define JZ_GPIO_MEM_DATA30		JZ_GPIO_PORTA(30)
+#define JZ_GPIO_MEM_DATA31		JZ_GPIO_PORTA(31)
+
+#define JZ_GPIO_FUNC_MEM_DATA0		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA1		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA2		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA3		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA4		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA5		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA6		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA7		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA8		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA9		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA10		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA11		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA12		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA13		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA14		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA15		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA16		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA17		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA18		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA19		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA20		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA21		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA22		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA23		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA24		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA25		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA26		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA27		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA28		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA29		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA30		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DATA31		JZ_GPIO_FUNC_1
+
+/*
+ * Port B function pins
+ */
+#define JZ_GPIO_MEM_ADDR0		JZ_GPIO_PORTB(0)
+#define JZ_GPIO_MEM_ADDR1		JZ_GPIO_PORTB(1)
+#define JZ_GPIO_MEM_ADDR2		JZ_GPIO_PORTB(2)
+#define JZ_GPIO_MEM_ADDR3		JZ_GPIO_PORTB(3)
+#define JZ_GPIO_MEM_ADDR4		JZ_GPIO_PORTB(4)
+#define JZ_GPIO_MEM_ADDR5		JZ_GPIO_PORTB(5)
+#define JZ_GPIO_MEM_ADDR6		JZ_GPIO_PORTB(6)
+#define JZ_GPIO_MEM_ADDR7		JZ_GPIO_PORTB(7)
+#define JZ_GPIO_MEM_ADDR8		JZ_GPIO_PORTB(8)
+#define JZ_GPIO_MEM_ADDR9		JZ_GPIO_PORTB(9)
+#define JZ_GPIO_MEM_ADDR10		JZ_GPIO_PORTB(10)
+#define JZ_GPIO_MEM_ADDR11		JZ_GPIO_PORTB(11)
+#define JZ_GPIO_MEM_ADDR12		JZ_GPIO_PORTB(12)
+#define JZ_GPIO_MEM_ADDR13		JZ_GPIO_PORTB(13)
+#define JZ_GPIO_MEM_ADDR14		JZ_GPIO_PORTB(14)
+#define JZ_GPIO_MEM_ADDR15		JZ_GPIO_PORTB(15)
+#define JZ_GPIO_MEM_ADDR16		JZ_GPIO_PORTB(16)
+#define JZ_GPIO_MEM_CLS			JZ_GPIO_PORTB(17)
+#define JZ_GPIO_MEM_SPL			JZ_GPIO_PORTB(18)
+#define JZ_GPIO_MEM_DCS			JZ_GPIO_PORTB(19)
+#define JZ_GPIO_MEM_RAS			JZ_GPIO_PORTB(20)
+#define JZ_GPIO_MEM_CAS			JZ_GPIO_PORTB(21)
+#define JZ_GPIO_MEM_SDWE		JZ_GPIO_PORTB(22)
+#define JZ_GPIO_MEM_CKE			JZ_GPIO_PORTB(23)
+#define JZ_GPIO_MEM_CKO			JZ_GPIO_PORTB(24)
+#define JZ_GPIO_MEM_CS0			JZ_GPIO_PORTB(25)
+#define JZ_GPIO_MEM_CS1			JZ_GPIO_PORTB(26)
+#define JZ_GPIO_MEM_CS2			JZ_GPIO_PORTB(27)
+#define JZ_GPIO_MEM_CS3			JZ_GPIO_PORTB(28)
+#define JZ_GPIO_MEM_RD			JZ_GPIO_PORTB(29)
+#define JZ_GPIO_MEM_WR			JZ_GPIO_PORTB(30)
+#define JZ_GPIO_MEM_WE0			JZ_GPIO_PORTB(31)
+
+#define JZ_GPIO_FUNC_MEM_ADDR0		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_ADDR1		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_ADDR2		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_ADDR3		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_ADDR4		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_ADDR5		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_ADDR6		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_ADDR7		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_ADDR8		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_ADDR9		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_ADDR10		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_ADDR11		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_ADDR12		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_ADDR13		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_ADDR14		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_ADDR15		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_ADDR16		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_CLS	        JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_SPL		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_DCS		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_RAS		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_CAS		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_SDWE		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_CKE		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_CKO		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_CS0		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_CS1		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_CS2		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_CS3		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_RD		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_WR		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_WE0		JZ_GPIO_FUNC_1
+
+
+#define JZ_GPIO_MEM_ADDR21		JZ_GPIO_PORTB(17)
+#define JZ_GPIO_MEM_ADDR22		JZ_GPIO_PORTB(18)
+
+#define JZ_GPIO_FUNC_MEM_ADDR21		JZ_GPIO_FUNC_2
+#define JZ_GPIO_FUNC_MEM_ADDR22		JZ_GPIO_FUNC_2
+
+/*
+ * Port C function pins
+ */
+#define JZ_GPIO_LCD_DATA0		JZ_GPIO_PORTC(0)
+#define JZ_GPIO_LCD_DATA1		JZ_GPIO_PORTC(1)
+#define JZ_GPIO_LCD_DATA2		JZ_GPIO_PORTC(2)
+#define JZ_GPIO_LCD_DATA3		JZ_GPIO_PORTC(3)
+#define JZ_GPIO_LCD_DATA4		JZ_GPIO_PORTC(4)
+#define JZ_GPIO_LCD_DATA5		JZ_GPIO_PORTC(5)
+#define JZ_GPIO_LCD_DATA6		JZ_GPIO_PORTC(6)
+#define JZ_GPIO_LCD_DATA7		JZ_GPIO_PORTC(7)
+#define JZ_GPIO_LCD_DATA8		JZ_GPIO_PORTC(8)
+#define JZ_GPIO_LCD_DATA9		JZ_GPIO_PORTC(9)
+#define JZ_GPIO_LCD_DATA10		JZ_GPIO_PORTC(10)
+#define JZ_GPIO_LCD_DATA11		JZ_GPIO_PORTC(11)
+#define JZ_GPIO_LCD_DATA12		JZ_GPIO_PORTC(12)
+#define JZ_GPIO_LCD_DATA13		JZ_GPIO_PORTC(13)
+#define JZ_GPIO_LCD_DATA14		JZ_GPIO_PORTC(14)
+#define JZ_GPIO_LCD_DATA15		JZ_GPIO_PORTC(15)
+#define JZ_GPIO_LCD_DATA16		JZ_GPIO_PORTC(16)
+#define JZ_GPIO_LCD_DATA17		JZ_GPIO_PORTC(17)
+#define JZ_GPIO_LCD_PCLK		JZ_GPIO_PORTC(18)
+#define JZ_GPIO_LCD_HSYNC		JZ_GPIO_PORTC(19)
+#define JZ_GPIO_LCD_VSYNC		JZ_GPIO_PORTC(20)
+#define JZ_GPIO_LCD_DE			JZ_GPIO_PORTC(21)
+#define JZ_GPIO_LCD_PS			JZ_GPIO_PORTC(22)
+#define JZ_GPIO_LCD_REV			JZ_GPIO_PORTC(23)
+#define JZ_GPIO_MEM_WE1			JZ_GPIO_PORTC(24)
+#define JZ_GPIO_MEM_WE2			JZ_GPIO_PORTC(25)
+#define JZ_GPIO_MEM_WE3			JZ_GPIO_PORTC(26)
+#define JZ_GPIO_MEM_WAIT		JZ_GPIO_PORTC(27)
+#define JZ_GPIO_MEM_FRE			JZ_GPIO_PORTC(28)
+#define JZ_GPIO_MEM_FWE			JZ_GPIO_PORTC(29)
+
+#define JZ_GPIO_FUNC_LCD_DATA0		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_LCD_DATA1		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_LCD_DATA2		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_LCD_DATA3		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_LCD_DATA4		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_LCD_DATA5		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_LCD_DATA6		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_LCD_DATA7		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_LCD_DATA8		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_LCD_DATA9		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_LCD_DATA10		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_LCD_DATA11		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_LCD_DATA12		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_LCD_DATA13		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_LCD_DATA14		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_LCD_DATA15		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_LCD_DATA16		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_LCD_DATA17		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_LCD_PCLK		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_LCD_VSYNC		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_LCD_HSYNC		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_LCD_DE		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_LCD_PS		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_LCD_REV		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_WE1		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_WE2		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_WE3		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_WAIT		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_FRE		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MEM_FWE		JZ_GPIO_FUNC_1
+
+
+#define JZ_GPIO_MEM_ADDR19		JZ_GPIO_PORTB(22)
+#define JZ_GPIO_MEM_ADDR20		JZ_GPIO_PORTB(23)
+
+#define JZ_GPIO_FUNC_MEM_ADDR19		JZ_GPIO_FUNC_2
+#define JZ_GPIO_FUNC_MEM_ADDR20		JZ_GPIO_FUNC_2
+
+/* Port D function pins */
+#define JZ_GPIO_CIM_DATA0		JZ_GPIO_PORTD(0)
+#define JZ_GPIO_CIM_DATA1		JZ_GPIO_PORTD(1)
+#define JZ_GPIO_CIM_DATA2		JZ_GPIO_PORTD(2)
+#define JZ_GPIO_CIM_DATA3		JZ_GPIO_PORTD(3)
+#define JZ_GPIO_CIM_DATA4		JZ_GPIO_PORTD(4)
+#define JZ_GPIO_CIM_DATA5		JZ_GPIO_PORTD(5)
+#define JZ_GPIO_CIM_DATA6		JZ_GPIO_PORTD(6)
+#define JZ_GPIO_CIM_DATA7		JZ_GPIO_PORTD(7)
+#define JZ_GPIO_MSC_CMD			JZ_GPIO_PORTD(8)
+#define JZ_GPIO_MSC_CLK			JZ_GPIO_PORTD(9)
+#define JZ_GPIO_MSC_DATA0		JZ_GPIO_PORTD(10)
+#define JZ_GPIO_MSC_DATA1		JZ_GPIO_PORTD(11)
+#define JZ_GPIO_MSC_DATA2		JZ_GPIO_PORTD(12)
+#define JZ_GPIO_MSC_DATA3		JZ_GPIO_PORTD(13)
+#define JZ_GPIO_CIM_MCLK		JZ_GPIO_PORTD(14)
+#define JZ_GPIO_CIM_PCLK		JZ_GPIO_PORTD(15)
+#define JZ_GPIO_CIM_VSYNC		JZ_GPIO_PORTD(16)
+#define JZ_GPIO_CIM_HSYNC		JZ_GPIO_PORTD(17)
+#define JZ_GPIO_SPI_CLK			JZ_GPIO_PORTD(18)
+#define JZ_GPIO_SPI_CE0			JZ_GPIO_PORTD(19)
+#define JZ_GPIO_SPI_DT			JZ_GPIO_PORTD(20)
+#define JZ_GPIO_SPI_DR			JZ_GPIO_PORTD(21)
+#define JZ_GPIO_SPI_CE1			JZ_GPIO_PORTD(22)
+#define JZ_GPIO_PWM0			JZ_GPIO_PORTD(23)
+#define JZ_GPIO_PWM1			JZ_GPIO_PORTD(24)
+#define JZ_GPIO_PWM2			JZ_GPIO_PORTD(25)
+#define JZ_GPIO_PWM3			JZ_GPIO_PORTD(26)
+#define JZ_GPIO_PWM4			JZ_GPIO_PORTD(27)
+#define JZ_GPIO_PWM5			JZ_GPIO_PORTD(28)
+#define JZ_GPIO_PWM6			JZ_GPIO_PORTD(30)
+#define JZ_GPIO_PWM7			JZ_GPIO_PORTD(31)
+
+#define JZ_GPIO_FUNC_CIM_DATA0		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_CIM_DATA1		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_CIM_DATA2		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_CIM_DATA3		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_CIM_DATA4		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_CIM_DATA5		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_CIM_DATA6		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_CIM_DATA7		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MSC_CMD		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MSC_CLK		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MSC_DATA0		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MSC_DATA1		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MSC_DATA2		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_MSC_DATA3		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_CIM_MCLK		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_CIM_PCLK		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_CIM_VSYNC		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_CIM_HSYNC		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_SPI_CLK		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_SPI_CE0		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_SPI_DT		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_SPI_DR		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_SPI_CE1		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_PWM0		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_PWM1		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_PWM2		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_PWM3		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_PWM4		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_PWM5		JZ_GPIO_FUNC_1
+#define JZ_GPIO_FUNC_PWM6		JZ_GPIO_FUNC_1
+
+#define JZ_GPIO_MEM_SCLK_RSTN		JZ_GPIO_PORTD(18)
+#define JZ_GPIO_MEM_BCLK		JZ_GPIO_PORTD(19)
+#define JZ_GPIO_MEM_SDATO		JZ_GPIO_PORTD(20)
+#define JZ_GPIO_MEM_SDATI		JZ_GPIO_PORTD(21)
+#define JZ_GPIO_MEM_SYNC		JZ_GPIO_PORTD(22)
+#define JZ_GPIO_I2C_SDA			JZ_GPIO_PORTD(23)
+#define JZ_GPIO_I2C_SCK			JZ_GPIO_PORTD(24)
+#define JZ_GPIO_UART0_TXD		JZ_GPIO_PORTD(25)
+#define JZ_GPIO_UART0_RXD		JZ_GPIO_PORTD(26)
+#define JZ_GPIO_MEM_ADDR17		JZ_GPIO_PORTD(27)
+#define JZ_GPIO_MEM_ADDR18		JZ_GPIO_PORTD(28)
+#define JZ_GPIO_UART0_CTS		JZ_GPIO_PORTD(30)
+#define JZ_GPIO_UART0_RTS		JZ_GPIO_PORTD(31)
+
+#define JZ_GPIO_FUNC_MEM_SCLK_RSTN	JZ_GPIO_FUNC_2
+#define JZ_GPIO_FUNC_MEM_BCLK		JZ_GPIO_FUNC_2
+#define JZ_GPIO_FUNC_MEM_SDATO		JZ_GPIO_FUNC_2
+#define JZ_GPIO_FUNC_MEM_SDATI		JZ_GPIO_FUNC_2
+#define JZ_GPIO_FUNC_MEM_SYNC		JZ_GPIO_FUNC_2
+#define JZ_GPIO_FUNC_I2C_SDA		JZ_GPIO_FUNC_2
+#define JZ_GPIO_FUNC_I2C_SCK		JZ_GPIO_FUNC_2
+#define JZ_GPIO_FUNC_UART0_TXD		JZ_GPIO_FUNC_2
+#define JZ_GPIO_FUNC_UART0_RXD		JZ_GPIO_FUNC_2
+#define JZ_GPIO_FUNC_MEM_ADDR17		JZ_GPIO_FUNC_2
+#define JZ_GPIO_FUNC_MEM_ADDR18		JZ_GPIO_FUNC_2
+#define JZ_GPIO_FUNC_UART0_CTS		JZ_GPIO_FUNC_2
+#define JZ_GPIO_FUNC_UART0_RTS		JZ_GPIO_FUNC_2
+
+#define JZ_GPIO_UART1_RXD		JZ_GPIO_PORTD(30)
+#define JZ_GPIO_UART1_TXD		JZ_GPIO_PORTD(31)
+
+#define JZ_GPIO_FUNC_UART1_RXD		JZ_GPIO_FUNC_3
+#define JZ_GPIO_FUNC_UART1_TXD		JZ_GPIO_FUNC_3
+
+#endif /* !_JZ47XX_GPIO_REG_H_ */
+
diff --git a/sys/arch/mips/ingenic/include/jz47xx_gpio_var.h b/sys/arch/mips/ingenic/include/jz47xx_gpio_var.h
new file mode 100644
index 0000000..ebf0be8
--- /dev/null
+++ b/sys/arch/mips/ingenic/include/jz47xx_gpio_var.h
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2011, Peter Tworek
+ * 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. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef _JZ47XX_GPIO_VAR_H_
+#define _JZ47XX_GPIO_VAR_H_
+
+#include <sys/cdefs.h>
+#include <sys/device.h>
+
+#define jz47xx_gpio_func_set(pin) \
+    jz47xx_gpio_config_func(JZ_GPIO_ ## pin, JZ_GPIO_FUNC_ ## pin)
+
+#define jz47xx_gpio_func_clear(pin) \
+    jz47xx_gpio_config_func(JZ_GPIO_ ## pin, JZ_GPIO_FUNC_NONE);
+
+void jz47xx_gpio_init(device_t jzbus, bus_space_tag_t bst);
+void jz47xx_gpio_config_func(int gpio, int function);
+void jz47xx_gpio_config_pull(int gpio, bool enable);
+
+#endif /* !_JZ47XX_GPIO_VAR_H_ */
diff --git a/sys/arch/mips/ingenic/include/jz47xxreg.h b/sys/arch/mips/ingenic/include/jz47xxreg.h
new file mode 100644
index 0000000..14edfac
--- /dev/null
+++ b/sys/arch/mips/ingenic/include/jz47xxreg.h
@@ -0,0 +1,105 @@
+/*-
+ * Copyright (c) 2011, Peter Tworek
+ * 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. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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.
+ */
+
+/*
+ * Register definitions for Ingenic JZ47XX SOC.
+ */
+
+#ifndef	_MIPS_INGENIC_JZ47XXREG_H_
+#define	_MIPS_INGENIC_JZ47XXREG_H_
+
+#include <mips/cpuregs.h>
+
+/* Size of builtin SRAM memory. */
+#define JZ_SRAM_SIZE	0x4000
+
+/* Default EXTAL frequency */
+#ifndef JZ_EXTAL
+#define JZ_EXTAL	3686400
+#endif
+
+/* Default RTC clock frequency */
+#ifndef JZ_RTCCLK
+#define JZ_RTCCLK       32768
+#endif
+
+/*
+ * Base physical adresses of JZ47XX peripherials.
+ */
+#define	JZ_CPM_BASE     0x10000000
+#define JZ_INTC_BASE	0x10001000
+#define JZ_TCU_BASE     0x10002000
+#define JZ_WDT_BASE     0x10002000
+#define JZ_RTC_BASE     0x10003000
+#define JZ_GPIO_BASE    0x10010000
+#define JZ_UART_BASE	0x10030000
+#define JZ_LCDC_BASE    0x13050000
+
+/*
+ * Interrupt controller registers.
+ */
+#define	INTC_SOURCE      0x00
+#define	INTC_MASK        0x04
+#define	INTC_MASK_SET    0x08
+#define	INTC_MASK_CLR    0x0C
+#define	INTC_PENDING     0x10
+
+/*
+ * Interrupt controller bits
+ */
+#define	INTC_IRQ_I2C     1
+#define	INTC_IRQ_EMC     2
+#define	INTC_IRQ_UHC     3
+#define	INTC_IRQ_UART0   9
+#define	INTC_IRQ_SADC    12
+#define	INTC_IRQ_MSC     14
+#define	INTC_IRQ_RTC     15
+#define	INTC_IRQ_SSI     16
+#define	INTC_IRQ_CIM     17
+#define	INTC_IRQ_AIC     18
+#define	INTC_IRQ_DMA     20
+#define	INTC_IRQ_TCU2    21
+#define	INTC_IRQ_TCU1    22
+#define	INTC_IRQ_TCU0    23
+#define	INTC_IRQ_UDC     24
+#define	INTC_IRQ_GPIO3   25
+#define	INTC_IRQ_GPIO2   26
+#define	INTC_IRQ_GPIO1   27
+#define	INTC_IRQ_GPIO0   28
+#define	INTC_IRQ_IPU     29
+#define	INTC_IRQ_LCD     30
+
+/*
+ * Helper macros for accessing registers
+ */
+#define REGVAL32(x)         *((volatile uint32_t *)(MIPS_PHYS_TO_KSEG1((x))))
+#define INTC_GET_REG(x)     REGVAL32((x) + JZ_INTC_BASE)
+#define INTC_PUT_REG(x,v)   (REGVAL32((x) + JZ_INTC_BASE)) = (v)
+
+#endif /* _MIPS_INGENIC_JZ47XXREG_H_ */
diff --git a/sys/arch/mips/ingenic/include/jz47xxvar.h b/sys/arch/mips/ingenic/include/jz47xxvar.h
new file mode 100644
index 0000000..4b7eb78
--- /dev/null
+++ b/sys/arch/mips/ingenic/include/jz47xxvar.h
@@ -0,0 +1,55 @@
+/*-
+ * Copyright (c) 2011, Peter Tworek
+ * 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. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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.
+ */
+
+#ifndef	_MIPS_INGENIC_JZ47XXVAR_H_
+#define	_MIPS_INGENIC_JZ47XXVAR_H_
+
+#include <sys/systm.h>
+
+/*
+ * Console.
+ */
+void jz47xx_early_console(void);
+
+/*
+ * Interrupts.
+ */
+void  jz47xx_intr_init(void);
+void* jz47xx_intr_establish(int, int (*)(void *), void *);
+void  jz47xx_intr_disestablish(void *);
+void  jz47xx_intr(struct clockframe *);
+
+/*
+ * Watchdog.
+ */
+void     jz47xx_wdog_init(void);
+uint32_t jz47xx_wdog_freq(void);
+void     jz47xx_wdog_reload(uint32_t period);
+
+#endif /* _MIPS_INGENIC_JZ47XXVAR_H_ */
diff --git a/sys/arch/mips/ingenic/jz4740_clk.c b/sys/arch/mips/ingenic/jz4740_clk.c
new file mode 100644
index 0000000..f433755
--- /dev/null
+++ b/sys/arch/mips/ingenic/jz4740_clk.c
@@ -0,0 +1,188 @@
+/*-
+ * Copyright (c) 2011, Peter Tworek
+ * 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. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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.
+ */
+
+/*
+ * Implementation of clock frequency routines for JZ4740 SOC.
+ */
+
+#include <sys/cdefs.h>
+
+#include <sys/types.h>
+#include <sys/systm.h>
+
+#include <mips/cpuregs.h>
+
+#include <mips/ingenic/include/jz47xxreg.h>
+#include <mips/ingenic/include/jz47xx_clk.h>
+
+/*
+ * Clock reset and power controller registers.
+ */
+#define	CPM_REG_CLK_CTRL          0x00
+#define	CPM_REG_PLL_CTRL          0x10
+#define	CPM_REG_I2S_CLK_DIV       0x60
+#define	CPM_REG_LCD_PIX_CLK_DIV   0x64
+#define	CPM_REG_MSC_CLK_DIV       0x68
+#define	CPM_REG_UHC_CLK_DIV       0x6C
+#define	CPM_REG_SSI_CLK_DIV       0x74
+
+/*
+ * PLL control register bits/masks/shifts
+ */
+#define CPM_PLL_CTRL_M_SHIFT   23
+#define CPM_PLL_CTRL_M_MASK    (0x1ff << CPM_PLL_CTRL_M_SHIFT)
+#define CPM_PLL_CTRL_N_SHIFT   18
+#define CPM_PLL_CTRL_N_MASK    (0x1f << CPM_PLL_CTRL_N_SHIFT)
+#define CPM_PLL_CTRL_OD_SHIFT  16
+#define CPM_PLL_CTRL_OD_MASK   (0x03 << CPM_PLL_CTRL_OD_SHIFT)
+#define CPM_PLL_CTRL_S         (1 << 10)
+#define CPM_PLL_CTRL_BP        (1 << 9)
+#define CPM_PLL_CTRL_EN        (1 << 8)
+#define CPM_PLL_CTRL_ST_MASK   0x000000ff
+
+/*
+ * Clock control register bits/masks/shifts
+ */
+#define CPM_CLK_CTRL_I2CS        (1 << 31)
+#define CPM_CLK_CTRL_CLKOEN      (1 << 30)
+#define CPM_CLK_CTRL_UCS         (1 << 29)
+#define CPM_CLK_CTRL_UDIV_SHIFT  23
+#define CPM_CLK_CTRL_UDIV_MASK   (0x3f << CPM_CLK_CTRL_UDIV_SHIFT)
+#define CPM_CLK_CTRL_CE          (1 << 22)
+#define CPM_CLK_CTRL_PCS         (1 << 21)
+#define CPM_CLK_CTRL_LDIV_SHIFT  16
+#define CPM_CLK_CTRL_LDIV_MASK   (0x1f << CPM_CLK_CTRL_LDIV_SHIFT)
+#define CPM_CLK_CTRL_MDIV_SHIFT  12
+#define CPM_CLK_CTRL_MDIV_MASK   (0x0f << CPM_CLK_CTRL_MDIV_SHIFT)
+#define CPM_CLK_CTRL_PDIV_SHIFT  8
+#define CPM_CLK_CTRL_PDIV_MASK   (0x0f << CPM_CLK_CTRL_PDIV_SHIFT)
+#define CPM_CLK_CTRL_HDIV_SHIFT  4
+#define CPM_CLK_CTRL_HDIV_MASK	 (0x0f << CPM_CLK_CTRL_HDIV_SHIFT)
+#define CPM_CLK_CTRL_CDIV_SHIFT	 0
+#define CPM_CLK_CTRL_CDIV_MASK	 (0x0f << CPM_CLK_CTRL_CDIV_SHIFT)
+
+#define REGVAL32(x)         *((volatile uint32_t *)(MIPS_PHYS_TO_KSEG1((x))))
+#define CPM_GET_REG(x)     REGVAL32((x) + JZ_CPM_BASE)
+#define CPM_PUT_REG(x,v)   (REGVAL32((x) + JZ_CPM_BASE)) = (v)
+
+/* Forward declarations */
+uint32_t jz4740_pllout_get(void);
+uint32_t jz4740_pllout2_get(void);
+uint32_t jz4740_clk_get(jzclk_t);
+void     jz4740_clk_set(jzclk_t, uint32_t);
+
+uint32_t
+jz4740_pllout_get(void)
+{
+	static uint32_t od[4] = {1, 2, 2, 4};
+	uint32_t m, n, no, pllout;
+	uint32_t ctrl = CPM_GET_REG(CPM_REG_PLL_CTRL);
+
+	if ((ctrl & CPM_PLL_CTRL_EN) && !(ctrl & CPM_PLL_CTRL_BP)) {
+		m = ((ctrl & CPM_PLL_CTRL_M_MASK) >> CPM_PLL_CTRL_M_SHIFT) + 2;
+		n = ((ctrl & CPM_PLL_CTRL_N_MASK) >> CPM_PLL_CTRL_N_SHIFT) + 2;
+		no = od[(ctrl & CPM_PLL_CTRL_OD_MASK) >> CPM_PLL_CTRL_OD_SHIFT];
+		pllout = ((JZ_EXTAL) / (n * no)) * m;
+	} else {
+		pllout = JZ_EXTAL;
+	}
+	return pllout;
+}
+
+uint32_t
+jz4740_pllout2_get(void)
+{
+	uint32_t ctrl = CPM_GET_REG(CPM_REG_CLK_CTRL);
+	if (ctrl & CPM_CLK_CTRL_PCS) {
+		return jz4740_pllout_get();
+	} else {
+		return jz4740_pllout_get() / 2;
+	}
+}
+
+uint32_t
+jz4740_clk_get(jzclk_t clk)
+{
+	static int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
+	uint32_t ctrl;
+	uint32_t tmp = 0;
+
+	ctrl = CPM_GET_REG(CPM_REG_CLK_CTRL);
+
+	switch (clk) {
+
+		case JZ_CCLK:
+			tmp = ((ctrl & CPM_CLK_CTRL_CDIV_MASK) >>
+					CPM_CLK_CTRL_CDIV_SHIFT);
+			break;
+
+		case JZ_HCLK:
+			tmp = ((ctrl & CPM_CLK_CTRL_HDIV_MASK) >>
+					CPM_CLK_CTRL_HDIV_SHIFT);
+			break;
+
+		case JZ_PCLK:
+			tmp = ((ctrl & CPM_CLK_CTRL_PDIV_MASK) >>
+					CPM_CLK_CTRL_PDIV_SHIFT);
+			break;
+
+		case JZ_MCLK:
+			tmp = ((ctrl & CPM_CLK_CTRL_MDIV_MASK) >>
+					CPM_CLK_CTRL_MDIV_SHIFT);
+			break;
+
+		case JZ_LCDCLK:
+			tmp = ((ctrl & CPM_CLK_CTRL_LDIV_MASK) >>
+					CPM_CLK_CTRL_LDIV_SHIFT) + 1;
+			return jz4740_pllout2_get() / tmp;
+
+		case JZ_PIXCLK:
+			tmp = CPM_GET_REG(CPM_REG_LCD_PIX_CLK_DIV) + 1;
+			return jz4740_pllout2_get() / tmp;
+
+		case JZ_CKO:
+		case JZ_I2SCLK:
+		case JZ_MSCCLK:
+		case JZ_12M:
+			panic("Unimplemented clock getter!");
+			return 0;
+	}
+
+	KASSERT(tmp < sizeof(div)/4);
+
+	return (jz4740_pllout_get() / div[tmp]);
+}
+__weak_alias(jz47xx_clk_get, jz4740_clk_get);
+
+void
+jz4740_clk_set(jzclk_t clk, uint32_t freq)
+{
+	panic("Unimplemented clock setter!");
+}
+__weak_alias(jz47xx_clk_set, jz4740_clk_set);
diff --git a/sys/arch/mips/ingenic/jz47xx_console.c b/sys/arch/mips/ingenic/jz47xx_console.c
new file mode 100644
index 0000000..5e97f28
--- /dev/null
+++ b/sys/arch/mips/ingenic/jz47xx_console.c
@@ -0,0 +1,117 @@
+/*-
+ * Copyright (c) 2011, Peter Tworek
+ * 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. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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.
+ */
+
+/*
+ * This file includes a implementation specific console for JZ47XX SOC.
+ */
+
+#include <sys/cdefs.h>
+
+#include "opt_ddb.h"
+#include "opt_kgdb.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+
+#include <dev/cons.h>
+
+#include <mips/cpuregs.h>
+
+#include <mips/ingenic/include/jz47xxreg.h>
+#include <mips/ingenic/include/jz47xxvar.h>
+#include <mips/ingenic/dev/jzbus_var.h>
+
+#include "com.h"
+
+/*
+ * Early console support.
+ */
+#define	STRIDE(x)	((x*4) + MIPS_PHYS_TO_KSEG1(JZ_UART_BASE))
+#define	THR		STRIDE(0)
+#define	RHR		STRIDE(0)
+#define	LSR		STRIDE(5)
+#define	INB(x)		(*(volatile char *)(x))
+#define	OUTB(x, v)	(*(volatile char *)(x) = (v))
+
+/* line status register */
+#define LSR_DRY         (1 << 0)
+#define LSR_TDRQ        (1 << 5)
+#define LSR_TEMP        (1 << 6)
+
+static void
+jz47xx_putc(dev_t dev, int c)
+{
+	unsigned char	lsr = 0;
+
+	while (!(lsr & LSR_TDRQ)) {
+		lsr = INB(LSR);
+	}
+	OUTB(THR, (char)c);
+}
+
+static int
+jz47xx_getc(dev_t dev)
+{
+	unsigned char	lsr = 0, dat;
+
+	while (!(lsr & LSR_DRY)) {
+		lsr = INB(LSR);
+	}
+	dat = INB(RHR);
+	return (dat);
+}
+
+static void
+jz47xx_flush(dev_t dev)
+{
+	unsigned char	lsr = 0;
+	while (!(lsr & LSR_TEMP)) {
+		lsr = INB(LSR);
+	}
+}
+
+void
+jz47xx_early_console(void)
+{
+	static struct consdev promcn = {
+		.cn_probe = NULL,
+		.cn_init = NULL,
+		.cn_getc = jz47xx_getc,
+		.cn_putc = jz47xx_putc,
+		.cn_pollc = nullcnpollc,
+		.cn_bell = NULL,
+		.cn_halt = NULL,
+		.cn_flush = jz47xx_flush,
+		.cn_dev = makedev(0, 0),
+		.cn_pri = CN_DEAD,
+	};
+
+	cn_tab = &promcn;
+}
diff --git a/sys/arch/mips/ingenic/jz47xx_gpio.c b/sys/arch/mips/ingenic/jz47xx_gpio.c
new file mode 100644
index 0000000..d72c93d
--- /dev/null
+++ b/sys/arch/mips/ingenic/jz47xx_gpio.c
@@ -0,0 +1,131 @@
+/*-
+ * Copyright (c) 2011, Peter Tworek
+ * 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. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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>
+
+#include <machine/bus.h>
+
+#include <sys/systm.h>
+
+#include <mips/ingenic/include/jz47xx_gpio_var.h>
+#include <mips/ingenic/include/jz47xx_gpio_reg.h>
+#include <mips/ingenic/include/jz47xxreg.h>
+#include <mips/ingenic/dev/jzbus_var.h>
+
+/*
+ * GPIO controller registers
+ */
+#define JZ_GPIO_PIN                0x00
+#define JZ_GPIO_DATA               0x10
+#define JZ_GPIO_DATA_SET           0x14
+#define JZ_GPIO_DATA_CLEAR         0x18
+#define JZ_GPIO_MASK               0x20
+#define JZ_GPIO_MASK_SET           0x24
+#define JZ_GPIO_MASK_CLEAR         0x28
+#define JZ_GPIO_PULL               0x30
+#define JZ_GPIO_PULL_SET           0x34
+#define JZ_GPIO_PULL_CLEAR         0x38
+#define JZ_GPIO_FUNC               0x40
+#define JZ_GPIO_FUNC_SET           0x44
+#define JZ_GPIO_FUNC_CLEAR         0x48
+#define JZ_GPIO_SELECT             0x50
+#define JZ_GPIO_SELECT_SET         0x54
+#define JZ_GPIO_SELECT_CLEAR       0x58
+#define JZ_GPIO_DIRECTION          0x60
+#define JZ_GPIO_DIRECTION_SET      0x64
+#define JZ_GPIO_DIRECTION_CLEAR    0x68
+#define JZ_GPIO_TRIGGER            0x70
+#define JZ_GPIO_TRIGGER_SET        0x74
+#define JZ_GPIO_TRIGGER_CLEAR      0x78
+#define JZ_GPIO_FLAG               0x80
+#define JZ_GPIO_FLAG_CLEAR         0x14
+
+#define GPIO_2_BIT(g)         (1 << (g & 0x1f))
+#define GPIO_2_REG(g, reg)    (((g >> 5) << 8) + reg)
+#define GPIO_REG_WRITE(g, r) \
+    bus_space_write_4(bus_bst, gpio_bsh, GPIO_2_REG(g, r), GPIO_2_BIT(g))
+
+
+/* XXX */
+#define JZ_GPIO_SIZE    0x1000
+
+static bus_space_tag_t    bus_bst;
+static bus_space_handle_t gpio_bsh;
+
+void
+jz47xx_gpio_init(device_t jzbus, bus_space_tag_t bst)
+{
+	bus_bst = bst;
+
+	if (bus_space_map(bus_bst, JZ_GPIO_BASE, JZ_GPIO_SIZE, 0, &gpio_bsh)) {
+		panic("Failed to map GPIO controler memory!\n");
+	}
+
+	aprint_normal_dev(jzbus, "GPIO initialized\n");
+}
+
+void
+jz47xx_gpio_config_func(int gpio, int function)
+{
+	switch (function) {
+		case JZ_GPIO_FUNC_1:
+			GPIO_REG_WRITE(gpio, JZ_GPIO_FUNC_SET);
+			GPIO_REG_WRITE(gpio, JZ_GPIO_TRIGGER_CLEAR);
+			GPIO_REG_WRITE(gpio, JZ_GPIO_SELECT_CLEAR);
+			break;
+
+		case JZ_GPIO_FUNC_2:
+			GPIO_REG_WRITE(gpio, JZ_GPIO_FUNC_SET);
+			GPIO_REG_WRITE(gpio, JZ_GPIO_TRIGGER_CLEAR);
+			GPIO_REG_WRITE(gpio, JZ_GPIO_SELECT_SET);
+			break;
+
+		case JZ_GPIO_FUNC_3:
+			GPIO_REG_WRITE(gpio, JZ_GPIO_FUNC_SET);
+			/*GPIO_REG_WRITE(gpio, JZ_GPIO_TRIGGER_CLEAR);*/
+			GPIO_REG_WRITE(gpio, JZ_GPIO_TRIGGER_SET);
+			GPIO_REG_WRITE(gpio, JZ_GPIO_SELECT_SET);
+			break;
+
+		default:
+			GPIO_REG_WRITE(gpio, JZ_GPIO_FUNC_CLEAR);
+			GPIO_REG_WRITE(gpio, JZ_GPIO_SELECT_CLEAR);
+			GPIO_REG_WRITE(gpio, JZ_GPIO_TRIGGER_CLEAR);
+	}
+}
+
+void
+jz47xx_gpio_config_pull(int gpio, bool enable)
+{
+	if (enable) {
+		GPIO_REG_WRITE(gpio, JZ_GPIO_PULL_CLEAR);
+	} else {
+		GPIO_REG_WRITE(gpio, JZ_GPIO_PULL_SET);
+	}
+}
diff --git a/sys/arch/mips/ingenic/jz47xx_intr.c b/sys/arch/mips/ingenic/jz47xx_intr.c
new file mode 100644
index 0000000..db45fce
--- /dev/null
+++ b/sys/arch/mips/ingenic/jz47xx_intr.c
@@ -0,0 +1,226 @@
+/*-
+ * Copyright (c) 2011, Peter Tworek
+ * 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. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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.
+ */
+
+/*
+ * Low level interrupt handler for JZ47XX SOCs
+ */
+
+#include <sys/cdefs.h>
+
+#define __INTR_PRIVATE
+
+#include <sys/queue.h>
+#include <sys/systm.h>
+#include <sys/param.h>
+#include <sys/malloc.h>
+
+#include <machine/intr.h>
+
+#include <mips/ingenic/include/jz47xxvar.h>
+#include <mips/ingenic/include/jz47xxreg.h>
+
+/* Total number of JzSOC interrupts */
+#define NIRQS	32
+
+
+struct jz47xx_intrhand {
+	LIST_ENTRY(jz47xx_intrhand) ih_q;
+	int  (*ih_func)(void *);
+	void *ih_arg;
+	int  ih_irq;
+};
+
+struct jz47xx_intr {
+	LIST_HEAD(, jz47xx_intrhand) intr_l;
+	struct evcnt	intr_count;
+};
+
+/*
+ * This is a mask of bits to clear in the SR when we go to a
+ * given hardware interrupt priority level.
+ */
+static const struct ipl_sr_map jz47xx_ipl_sr_map = {
+	.sr_bits = {
+		[IPL_NONE]       = 0,
+		[IPL_SOFTCLOCK]  = MIPS_SOFT_INT_MASK_0,
+		[IPL_SOFTBIO]    = MIPS_SOFT_INT_MASK_0,
+		[IPL_SOFTNET]    = MIPS_SOFT_INT_MASK,
+		[IPL_SOFTSERIAL] = MIPS_SOFT_INT_MASK,
+		[IPL_VM]         = MIPS_SOFT_INT_MASK,
+		[IPL_SCHED]      = MIPS_INT_MASK,
+		[IPL_HIGH]       = MIPS_INT_MASK,
+	},
+};
+
+static const char * const jz47xx_intrnames[NIRQS] = {
+	"(reserved-0)",
+	"int 1 (i2c)",
+	"int 2 (emc)",
+	"int 3 (uhc)",
+	"(reserved-4)",
+	"(reserved-5)",
+	"(reserved-6)",
+	"(reserved-7)",
+	"(reserved-8)",
+	"int 9 (uart0)",
+	"(reserved-10)",
+	"(reserved-11)",
+	"int 12 (sadc)",
+	"(reserved-12)",
+	"int 14 (msc)",
+	"int 15 (rtc)",
+	"int 16 (ssi)",
+	"int 17 (cim)",
+	"int 18 (aic)",
+	"(reserved-19)",
+	"int 20 (dma)",
+	"int 21 (tcu2)",
+	"int 22 (tcu1)",
+	"int 23 (tcu0)",
+	"int 24 (udc)",
+	"int 25 (gpio3)",
+	"int 26 (gpio2)",
+	"int 27 (gpio1)",
+	"int 28 (gpio0)",
+	"int 29 (ipu)",
+	"int 30 (lcd)",
+	"(reserved-31)",
+};
+
+static struct jz47xx_intr jz47xx_intrs[NIRQS];
+
+void jz47xx_intr_init(void)
+{
+	ipl_sr_map = jz47xx_ipl_sr_map;
+
+	for (size_t i = 0; i < NIRQS; i++) {
+		LIST_INIT(&jz47xx_intrs[i].intr_l);
+		evcnt_attach_dynamic(&jz47xx_intrs[i].intr_count,
+		EVCNT_TYPE_INTR, NULL, "jz47xx", jz47xx_intrnames[i]);
+	}
+
+	/* Mask all peripherial interrupts */
+	INTC_PUT_REG(INTC_MASK_SET, 0xffffffff);
+
+	/* Clear all pending interrupts */
+	INTC_PUT_REG(INTC_PENDING, 0xffffffff);
+}
+
+void *
+jz47xx_intr_establish(int irq, int (*func)(void *), void *arg)
+{
+	struct jz47xx_intrhand	*ih;
+	uint32_t		irqmask;
+	int			s, first;
+
+	KASSERT((irq > 0) && (irq < NIRQS));
+
+	if ((ih = malloc(sizeof(*ih), M_DEVBUF, M_NOWAIT)) == NULL)
+		return NULL;
+
+	ih->ih_func = func;
+	ih->ih_arg = arg;
+	ih->ih_irq = irq;
+
+	s = splhigh();
+
+	first = LIST_EMPTY(&jz47xx_intrs[irq].intr_l);
+
+	LIST_INSERT_HEAD(&jz47xx_intrs[irq].intr_l, ih, ih_q);
+
+	/*
+	 * Now enable it
+	 */
+	if (first) {
+		irqmask = (1 << irq);
+		/* Clear it */
+		INTC_PUT_REG(INTC_PENDING, irqmask);
+		/* Unmask it */
+		INTC_PUT_REG(INTC_MASK_CLR, irqmask);
+	}
+	splx(s);
+
+	return (ih);
+}
+
+void
+jz47xx_intr_disestablish(void *arg)
+{
+	struct jz47xx_intrhand	*ih = arg;
+	uint32_t		irqmask;
+	int			irq, s;
+
+	irq = ih->ih_irq;
+
+	s = splhigh();
+
+	/*
+	 * First, remove it from the list
+	 */
+	LIST_REMOVE(ih, ih_q);
+
+	/*
+	 * If nothing is remaining on the list, disable it
+	 */
+	if (LIST_EMPTY(&jz47xx_intrs[irq].intr_l)) {
+		irqmask = (1 << irq);
+		/* Mask it */
+		INTC_PUT_REG(INTC_MASK_SET, irqmask);
+	}
+
+	splx(s);
+
+	free(ih, M_DEVBUF);
+}
+
+void
+jz47xx_intr(struct clockframe *frame)
+{
+	uint32_t mask;
+	uint32_t pending;
+	int      index;
+	struct jz47xx_intrhand *ih;
+
+	pending = INTC_GET_REG(INTC_PENDING);
+	mask = ~(INTC_GET_REG(INTC_MASK));
+
+	for (index = 0; index < NIRQS; index++) {
+		if (pending & mask & (1 << index)) {
+			jz47xx_intrs[index].intr_count.ev_count++;
+			LIST_FOREACH(ih, &jz47xx_intrs[index].intr_l, ih_q) {
+				if (ih->ih_arg != NULL)
+					(*ih->ih_func)(ih->ih_arg);
+				else
+					(*ih->ih_func)(frame);
+			}
+			/* Clear pending */
+			INTC_PUT_REG(INTC_PENDING, (1 << index));
+		}
+	}
+}
diff --git a/sys/arch/mips/ingenic/jz47xx_wdog.c b/sys/arch/mips/ingenic/jz47xx_wdog.c
new file mode 100644
index 0000000..a76b9f6
--- /dev/null
+++ b/sys/arch/mips/ingenic/jz47xx_wdog.c
@@ -0,0 +1,92 @@
+/*-
+ * Copyright (c) 2011, Peter Tworek
+ * 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. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * 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.
+ */
+
+/*
+ * Low level routines for watchdog handling on JZ47xx SOCs
+ */
+
+#include <sys/cdefs.h>
+
+#include <mips/ingenic/include/jz47xxvar.h>
+#include <mips/ingenic/include/jz47xxreg.h>
+
+#define REGVAL16(x)         *((volatile uint16_t *)(MIPS_PHYS_TO_KSEG1((x))))
+#define REGVAL8(x)          *((volatile uint8_t *)(MIPS_PHYS_TO_KSEG1((x))))
+
+#define WDT_GET_REG8(x)     REGVAL8((x) + JZ_WDT_BASE)
+#define WDT_PUT_REG8(x,v)   (REGVAL8((x) + JZ_WDT_BASE)) = (v)
+#define WDT_GET_REG16(x)    REGVAL16((x) + JZ_WDT_BASE)
+#define WDT_PUT_REG16(x,v)  (REGVAL16((x) + JZ_WDT_BASE)) = (v)
+
+/*
+ * Watchdog timer registers
+ */
+#define WDT_DATA                  0x00
+#define WDT_EN                    0x04
+#define WDT_CNT                   0x08
+#define WDT_CTRL                  0x0C
+
+/*
+ * Watchdog control register bits
+ */
+#define WDT_CTRL_PRESCALE_SHIFT   3
+#define WDT_CTRL_PRESCALE_MASK    (0x07 << WDT_CTRL_PRESCALE_SHIFT)
+#define WDT_CTRL_EXT_EN           0x0004
+#define WDT_CTRL_RTC_EN           0x0002
+#define WDT_CTRL_PCK_EN           0x0001
+
+void
+jz47xx_wdog_init()
+{
+	/* CLK = RTCCLK/64 */
+	WDT_PUT_REG16(WDT_CTRL, 0x1A);
+	/* Stop watchdog clock */
+	WDT_PUT_REG8(WDT_EN, 0);
+}
+
+uint32_t
+jz47xx_wdog_freq()
+{
+
+	return (JZ_RTCCLK / 64);
+}
+
+void
+jz47xx_wdog_reload(uint32_t period)
+{
+	if (period == 0) {
+		/* Stop watchdog clock */
+		WDT_PUT_REG8(WDT_EN, 0);
+	} else {
+		WDT_PUT_REG8(WDT_EN, 0);
+		WDT_PUT_REG16(WDT_CNT, 0);
+		WDT_PUT_REG16(WDT_DATA, period);
+		WDT_PUT_REG8(WDT_EN, 1);
+	}
+}
diff --git a/sys/arch/mips/mips/locore_mips3.S b/sys/arch/mips/mips/locore_mips3.S
index 12bb01c..1379f70 100644
--- a/sys/arch/mips/mips/locore_mips3.S
+++ b/sys/arch/mips/mips/locore_mips3.S
@@ -89,6 +89,7 @@
 #include <sys/cdefs.h>
 
 #include <mips/asm.h>
+#include <mips/cpu.h>
 #include <mips/cpuregs.h>
 #include <machine/param.h>
 #include <machine/endian.h>
@@ -422,6 +423,7 @@ END(mipsNN_cp0_userlocal_write)
 	.set	pop
 #endif /* (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0 */
 
+#ifndef JZRISC
 /*
  * uint32_t mips3_cp0_count_read(void)
  *
@@ -443,6 +445,7 @@ LEAF(mips3_cp0_count_write)
 	mtc0	a0, MIPS_COP_0_COUNT
 	JR_HB_RA
 END(mips3_cp0_count_write)
+#endif /* JZRISC */
 
 /*
  * uint32_t mips3_cp0_wired_read(void)
diff --git a/sys/arch/mips/mips/mips_fixup.c b/sys/arch/mips/mips/mips_fixup.c
index 1222a99..b976c57 100644
--- a/sys/arch/mips/mips/mips_fixup.c
+++ b/sys/arch/mips/mips/mips_fixup.c
@@ -233,7 +233,7 @@ mips_fixup_stubs(uint32_t *start, uint32_t *end)
 #ifdef DEBUG
 	size_t fixups_done = 0;
 	uint32_t cycles =
-#if (MIPS3 + MIPS4 + MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0
+#if !defined(JZRISC) && ((MIPS3 + MIPS4 + MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0)
 	    (CPUISMIPS3 ? mips3_cp0_count_read() : 0);
 #else
 	    0;
@@ -334,7 +334,7 @@ mips_fixup_stubs(uint32_t *start, uint32_t *end)
 		    sizeof(uint32_t [end - start]));
 
 #ifdef DEBUG
-#if (MIPS3 + MIPS4 + MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0
+#if !defined(JZRISC) && ((MIPS3 + MIPS4 + MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0)
 	if (CPUISMIPS3)
 		cycles = mips3_cp0_count_read() - cycles;
 #endif
diff --git a/sys/arch/mips/mips/mips_machdep.c b/sys/arch/mips/mips/mips_machdep.c
index edcf1d5..7aa89bf 100644
--- a/sys/arch/mips/mips/mips_machdep.c
+++ b/sys/arch/mips/mips/mips_machdep.c
@@ -278,8 +278,6 @@ char	cpu_model[128];
  *  - All MIPS3+ use the same exception model (cp0 status, cause bits,
  *    etc).  _Many_ assumptions throughout much of the mips code about
  *    this.  Includes overloaded usage of MIPS3_PLUS.
- *  - All MIPS3+ have a count register.  MIPS_HAS_CLOCK in <mips/cpu.h>
- *    will need to be revised if this is false.
  */
 #define	MIPS32_FLAGS	CPU_MIPS_R4K_MMU | CPU_MIPS_CAUSE_IV | CPU_MIPS_USE_WAIT
 #define	MIPS64_FLAGS	MIPS32_FLAGS	/* same as MIPS32 flags (for now) */
@@ -627,6 +625,10 @@ static const struct pridtab cputab[] = {
 	{ MIPS_PRID_CID_MICROSOFT, MIPS_eMIPS, 1, -1, CPU_ARCH_MIPS1, 64,
 	  CPU_MIPS_NO_WAIT, 0, 0,		"eMIPS CPU"		},
 
+	/* Ingenic JZ47xx SOC's */
+	{ MIPS_PRID_CID_INGENIC, MIPS_JZRISC, -1, -1, CPU_ARCH_MIPS32, 32,
+	  MIPS32_FLAGS | CPU_MIPS_NO_COUNTER, 0, 0, "JzRISC" },
+
 	{ 0, 0, 0,				0, 0, 0,
 	  0, 0, 0,				NULL			}
 };
@@ -1321,7 +1323,7 @@ cpu_identify(device_t dev)
 		if (opts->mips_cpu->cpu_cid <= ncidnames)
 			aprint_normal("%s ", cidnames[opts->mips_cpu->cpu_cid]);
 		else {
-			aprint_normal("Unknown Company ID - 0x%x", opts->mips_cpu->cpu_cid);
+			aprint_normal("Unknown Company ID - 0x%x\n", opts->mips_cpu->cpu_cid);
 			aprint_normal_dev(dev, "");
 		}
 	}
