Module Name:    src
Committed By:   jmcneill
Date:           Fri Aug 25 00:07:03 UTC 2017

Modified Files:
        src/sys/arch/arm/fdt: fdt_intr.h
        src/sys/arch/arm/sunxi: files.sunxi sunxi_ccu.h sunxi_ccu_div.c
            sunxi_ccu_prediv.c sunxi_gpio.c sunxi_gpio.h sunxi_mmc.c
            sunxi_platform.c sunxi_twi.c sunxi_usbphy.c
        src/sys/arch/evbarm/conf: SUNXI std.sunxi
Added Files:
        src/sys/arch/arm/sunxi: sun5i_a13_ccu.c sun5i_a13_ccu.h
            sun5i_a13_gpio.c sunxi_intc.c sunxi_timer.c

Log Message:
Add initial support for Allwinner A13 and R8 SoCs.


To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/fdt/fdt_intr.h
cvs rdiff -u -r1.16 -r1.17 src/sys/arch/arm/sunxi/files.sunxi
cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/sunxi/sun5i_a13_ccu.c \
    src/sys/arch/arm/sunxi/sun5i_a13_ccu.h \
    src/sys/arch/arm/sunxi/sun5i_a13_gpio.c \
    src/sys/arch/arm/sunxi/sunxi_intc.c src/sys/arch/arm/sunxi/sunxi_timer.c
cvs rdiff -u -r1.9 -r1.10 src/sys/arch/arm/sunxi/sunxi_ccu.h
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/sunxi/sunxi_ccu_div.c
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/sunxi/sunxi_ccu_prediv.c \
    src/sys/arch/arm/sunxi/sunxi_twi.c
cvs rdiff -u -r1.10 -r1.11 src/sys/arch/arm/sunxi/sunxi_gpio.c
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/arm/sunxi/sunxi_gpio.h
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/arm/sunxi/sunxi_mmc.c \
    src/sys/arch/arm/sunxi/sunxi_usbphy.c
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/arm/sunxi/sunxi_platform.c
cvs rdiff -u -r1.22 -r1.23 src/sys/arch/evbarm/conf/SUNXI
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/evbarm/conf/std.sunxi

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/arm/fdt/fdt_intr.h
diff -u src/sys/arch/arm/fdt/fdt_intr.h:1.1 src/sys/arch/arm/fdt/fdt_intr.h:1.2
--- src/sys/arch/arm/fdt/fdt_intr.h:1.1	Tue May 30 22:00:25 2017
+++ src/sys/arch/arm/fdt/fdt_intr.h	Fri Aug 25 00:07:02 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: fdt_intr.h,v 1.1 2017/05/30 22:00:25 jmcneill Exp $ */
+/* $NetBSD: fdt_intr.h,v 1.2 2017/08/25 00:07:02 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca>
@@ -34,6 +34,7 @@
 #ifndef _LOCORE
 
 #define	__HAVE_PIC_SET_PRIORITY
+#define	__HAVE_PIC_PENDING_INTRS
 
 #define	PIC_MAXSOURCES		256
 #define	PIC_MAXMAXSOURCES	(PIC_MAXSOURCES + 32)

Index: src/sys/arch/arm/sunxi/files.sunxi
diff -u src/sys/arch/arm/sunxi/files.sunxi:1.16 src/sys/arch/arm/sunxi/files.sunxi:1.17
--- src/sys/arch/arm/sunxi/files.sunxi:1.16	Sun Aug  6 17:15:45 2017
+++ src/sys/arch/arm/sunxi/files.sunxi	Fri Aug 25 00:07:03 2017
@@ -1,4 +1,4 @@
-#	$NetBSD: files.sunxi,v 1.16 2017/08/06 17:15:45 jmcneill Exp $
+#	$NetBSD: files.sunxi,v 1.17 2017/08/25 00:07:03 jmcneill Exp $
 #
 # Configuration info for Allwinner sunxi family SoCs
 #
@@ -27,6 +27,11 @@ file	arch/arm/sunxi/sunxi_ccu_nkmp.c		su
 file	arch/arm/sunxi/sunxi_ccu_phase.c	sunxi_ccu
 file	arch/arm/sunxi/sunxi_ccu_prediv.c	sunxi_ccu
 
+# CCU (A13)
+device	sun5ia13ccu: sunxi_ccu
+attach	sun5ia13ccu at fdt with sunxi_a13_ccu
+file	arch/arm/sunxi/sun5i_a13_ccu.c		sunxi_a13_ccu
+
 # CCU (A31)
 device	sun6ia31ccu: sunxi_ccu
 attach	sun6ia31ccu at fdt with sunxi_a31_ccu
@@ -52,10 +57,16 @@ device	sunxigates
 attach	sunxigates at fdt with sunxi_gates
 file	arch/arm/sunxi/sunxi_gates.c		sunxi_gates
 
+# Interrupt controller
+device	sunxiintc: pic, pic_splfuncs
+attach	sunxiintc at fdt with sunxi_intc
+file	arch/arm/sunxi/sunxi_intc.c		sunxi_intc
+
 # GPIO
 device	sunxigpio: gpiobus
 attach	sunxigpio at fdt with sunxi_gpio
 file	arch/arm/sunxi/sunxi_gpio.c		sunxi_gpio
+file	arch/arm/sunxi/sun5i_a13_gpio.c		sunxi_gpio & soc_sun5i_a13
 file	arch/arm/sunxi/sun6i_a31_gpio.c		sunxi_gpio & soc_sun6i_a31
 file	arch/arm/sunxi/sun8i_a83t_gpio.c	sunxi_gpio & soc_sun8i_a83t
 file	arch/arm/sunxi/sun8i_h3_gpio.c		sunxi_gpio & soc_sun8i_h3
@@ -103,6 +114,11 @@ device	sunxiemac: arp, ether, ifnet, mii
 attach	sunxiemac at fdt with sunxi_emac
 file	arch/arm/sunxi/sunxi_emac.c		sunxi_emac
 
+# Timer
+device	sunxitimer
+attach	sunxitimer at fdt with sunxi_timer
+file	arch/arm/sunxi/sunxi_timer.c		sunxi_timer
+
 # Watchdog
 device	sunxiwdt: sysmon_wdog
 attach	sunxiwdt at fdt with sunxi_wdt
@@ -125,10 +141,12 @@ file	arch/arm/sunxi/sun8i_h3_codec.c		h3
 
 # SOC parameters
 defflag	opt_soc.h			SOC_SUNXI
+defflag	opt_soc.h			SOC_SUN5I: SOC_SUNXI
+defflag	opt_soc.h			SOC_SUN5I_A13: SOC_SUN5I
+defflag	opt_soc.h			SOC_SUN6I: SOC_SUNXI
+defflag	opt_soc.h			SOC_SUN6I_A31: SOC_SUN6I
 defflag	opt_soc.h			SOC_SUN8I: SOC_SUNXI
 defflag	opt_soc.h			SOC_SUN8I_A83T: SOC_SUN8I
 defflag	opt_soc.h			SOC_SUN8I_H3: SOC_SUN8I
-defflag	opt_soc.h			SOC_SUN6I: SOC_SUNXI
-defflag	opt_soc.h			SOC_SUN6I_A31: SOC_SUN6I
 defflag	opt_soc.h			SOC_SUN50I: SOC_SUNXI
 defflag	opt_soc.h			SOC_SUN50I_A64: SOC_SUN50I

Index: src/sys/arch/arm/sunxi/sunxi_ccu.h
diff -u src/sys/arch/arm/sunxi/sunxi_ccu.h:1.9 src/sys/arch/arm/sunxi/sunxi_ccu.h:1.10
--- src/sys/arch/arm/sunxi/sunxi_ccu.h:1.9	Sun Aug 13 19:18:08 2017
+++ src/sys/arch/arm/sunxi/sunxi_ccu.h	Fri Aug 25 00:07:03 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_ccu.h,v 1.9 2017/08/13 19:18:08 jmcneill Exp $ */
+/* $NetBSD: sunxi_ccu.h,v 1.10 2017/08/25 00:07:03 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca>
@@ -237,6 +237,7 @@ struct sunxi_ccu_prediv {
 	u_int		nparents;
 	uint32_t	prediv;
 	uint32_t	prediv_sel;
+	uint32_t	prediv_fixed;
 	uint32_t	div;
 	uint32_t	sel;
 	uint32_t	flags;
@@ -256,6 +257,11 @@ const char *sunxi_ccu_prediv_get_parent(
 
 #define	SUNXI_CCU_PREDIV(_id, _name, _parents, _reg, _prediv,	\
 		     _prediv_sel, _div, _sel, _flags)		\
+	SUNXI_CCU_PREDIV_FIXED(_id, _name, _parents, _reg, _prediv, \
+		     _prediv_sel, 0, _div, _sel, _flags)
+
+#define	SUNXI_CCU_PREDIV_FIXED(_id, _name, _parents, _reg, _prediv, \
+		     _prediv_sel, _prediv_fixed, _div, _sel, _flags) \
 	[_id] = {						\
 		.type = SUNXI_CCU_PREDIV,			\
 		.base.name = (_name),				\
@@ -264,6 +270,7 @@ const char *sunxi_ccu_prediv_get_parent(
 		.u.prediv.nparents = __arraycount(_parents),	\
 		.u.prediv.prediv = (_prediv),			\
 		.u.prediv.prediv_sel = (_prediv_sel),		\
+		.u.prediv.prediv_fixed = (_prediv_fixed),	\
 		.u.prediv.div = (_div),				\
 		.u.prediv.sel = (_sel),				\
 		.u.prediv.flags = (_flags),			\

Index: src/sys/arch/arm/sunxi/sunxi_ccu_div.c
diff -u src/sys/arch/arm/sunxi/sunxi_ccu_div.c:1.1 src/sys/arch/arm/sunxi/sunxi_ccu_div.c:1.2
--- src/sys/arch/arm/sunxi/sunxi_ccu_div.c:1.1	Sun Jul  2 00:14:09 2017
+++ src/sys/arch/arm/sunxi/sunxi_ccu_div.c	Fri Aug 25 00:07:03 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_ccu_div.c,v 1.1 2017/07/02 00:14:09 jmcneill Exp $ */
+/* $NetBSD: sunxi_ccu_div.c,v 1.2 2017/08/25 00:07:03 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunxi_ccu_div.c,v 1.1 2017/07/02 00:14:09 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_ccu_div.c,v 1.2 2017/08/25 00:07:03 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -57,7 +57,11 @@ sunxi_ccu_div_get_rate(struct sunxi_ccu_
 		return 0;
 
 	val = CCU_READ(sc, div->reg);
-	ratio = __SHIFTOUT(val, div->div);
+	if (div->div)
+		ratio = __SHIFTOUT(val, div->div);
+	else
+		ratio = 0;
+
 	if ((div->flags & SUNXI_CCU_DIV_ZERO_IS_ONE) != 0 && ratio == 0)
 		ratio = 1;
 	if (div->flags & SUNXI_CCU_DIV_POWER_OF_TWO)

Index: src/sys/arch/arm/sunxi/sunxi_ccu_prediv.c
diff -u src/sys/arch/arm/sunxi/sunxi_ccu_prediv.c:1.2 src/sys/arch/arm/sunxi/sunxi_ccu_prediv.c:1.3
--- src/sys/arch/arm/sunxi/sunxi_ccu_prediv.c:1.2	Thu Jun 29 17:08:52 2017
+++ src/sys/arch/arm/sunxi/sunxi_ccu_prediv.c	Fri Aug 25 00:07:03 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_ccu_prediv.c,v 1.2 2017/06/29 17:08:52 jmcneill Exp $ */
+/* $NetBSD: sunxi_ccu_prediv.c,v 1.3 2017/08/25 00:07:03 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunxi_ccu_prediv.c,v 1.2 2017/06/29 17:08:52 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_ccu_prediv.c,v 1.3 2017/08/25 00:07:03 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -72,7 +72,10 @@ sunxi_ccu_prediv_get_rate(struct sunxi_c
 	else
 		div++;
 
-	pre++;
+	if (prediv->prediv_fixed)
+		pre = prediv->prediv_fixed;
+	else
+		pre++;
 
 	if (prediv->flags & SUNXI_CCU_PREDIV_DIVIDE_BY_TWO)
 		pre *= 2;
Index: src/sys/arch/arm/sunxi/sunxi_twi.c
diff -u src/sys/arch/arm/sunxi/sunxi_twi.c:1.2 src/sys/arch/arm/sunxi/sunxi_twi.c:1.3
--- src/sys/arch/arm/sunxi/sunxi_twi.c:1.2	Sat Jul  1 22:49:09 2017
+++ src/sys/arch/arm/sunxi/sunxi_twi.c	Fri Aug 25 00:07:03 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_twi.c,v 1.2 2017/07/01 22:49:09 jmcneill Exp $ */
+/* $NetBSD: sunxi_twi.c,v 1.3 2017/08/25 00:07:03 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca>
@@ -28,7 +28,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(0, "$NetBSD: sunxi_twi.c,v 1.2 2017/07/01 22:49:09 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_twi.c,v 1.3 2017/08/25 00:07:03 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -46,6 +46,7 @@ static int sunxi_twi_match(device_t, cfd
 static void sunxi_twi_attach(device_t, device_t, void *);
 
 static const char * const compatible[] = {
+	"allwinner,sun4i-a10-i2c",
 	"allwinner,sun6i-a31-i2c",
 	NULL
 };

Index: src/sys/arch/arm/sunxi/sunxi_gpio.c
diff -u src/sys/arch/arm/sunxi/sunxi_gpio.c:1.10 src/sys/arch/arm/sunxi/sunxi_gpio.c:1.11
--- src/sys/arch/arm/sunxi/sunxi_gpio.c:1.10	Sat Aug 12 23:42:52 2017
+++ src/sys/arch/arm/sunxi/sunxi_gpio.c	Fri Aug 25 00:07:03 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_gpio.c,v 1.10 2017/08/12 23:42:52 jmcneill Exp $ */
+/* $NetBSD: sunxi_gpio.c,v 1.11 2017/08/25 00:07:03 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca>
@@ -29,7 +29,7 @@
 #include "opt_soc.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunxi_gpio.c,v 1.10 2017/08/12 23:42:52 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_gpio.c,v 1.11 2017/08/25 00:07:03 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -58,6 +58,9 @@ __KERNEL_RCSID(0, "$NetBSD: sunxi_gpio.c
 #define  SUNXI_GPIO_PULL_PINMASK(pin)	(0x3 << (((pin) % 16) * 2))
 
 static const struct of_compat_data compat_data[] = {
+#ifdef SOC_SUN5I_A13
+	{ "allwinner,sun5i-a13-pinctrl",	(uintptr_t)&sun5i_a13_padconf },
+#endif
 #ifdef SOC_SUN6I_A31
 	{ "allwinner,sun6i-a31-pinctrl",	(uintptr_t)&sun6i_a31_padconf },
 	{ "allwinner,sun6i-a31-r-pinctrl",	(uintptr_t)&sun6i_a31_r_padconf },

Index: src/sys/arch/arm/sunxi/sunxi_gpio.h
diff -u src/sys/arch/arm/sunxi/sunxi_gpio.h:1.4 src/sys/arch/arm/sunxi/sunxi_gpio.h:1.5
--- src/sys/arch/arm/sunxi/sunxi_gpio.h:1.4	Sun Jul 23 10:16:08 2017
+++ src/sys/arch/arm/sunxi/sunxi_gpio.h	Fri Aug 25 00:07:03 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_gpio.h,v 1.4 2017/07/23 10:16:08 jmcneill Exp $ */
+/* $NetBSD: sunxi_gpio.h,v 1.5 2017/08/25 00:07:03 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca>
@@ -50,6 +50,10 @@ struct sunxi_gpio_padconf {
 	const struct sunxi_gpio_pins *pins;
 };
 
+#ifdef SOC_SUN5I_A13
+extern const struct sunxi_gpio_padconf sun5i_a13_padconf;
+#endif
+
 #ifdef SOC_SUN6I_A31
 extern const struct sunxi_gpio_padconf sun6i_a31_padconf;
 extern const struct sunxi_gpio_padconf sun6i_a31_r_padconf;

Index: src/sys/arch/arm/sunxi/sunxi_mmc.c
diff -u src/sys/arch/arm/sunxi/sunxi_mmc.c:1.3 src/sys/arch/arm/sunxi/sunxi_mmc.c:1.4
--- src/sys/arch/arm/sunxi/sunxi_mmc.c:1.3	Mon Jul 17 23:31:05 2017
+++ src/sys/arch/arm/sunxi/sunxi_mmc.c	Fri Aug 25 00:07:03 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_mmc.c,v 1.3 2017/07/17 23:31:05 jmcneill Exp $ */
+/* $NetBSD: sunxi_mmc.c,v 1.4 2017/08/25 00:07:03 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2014-2017 Jared McNeill <jmcne...@invisible.ca>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunxi_mmc.c,v 1.3 2017/07/17 23:31:05 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_mmc.c,v 1.4 2017/08/25 00:07:03 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -165,6 +165,7 @@ CFATTACH_DECL_NEW(sunxi_mmc, sizeof(stru
 	bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
 
 static const char * const compatible[] = {
+	"allwinner,sun5i-a13-mmc",
 	"allwinner,sun7i-a20-mmc",
 	NULL
 };
Index: src/sys/arch/arm/sunxi/sunxi_usbphy.c
diff -u src/sys/arch/arm/sunxi/sunxi_usbphy.c:1.3 src/sys/arch/arm/sunxi/sunxi_usbphy.c:1.4
--- src/sys/arch/arm/sunxi/sunxi_usbphy.c:1.3	Sun Jul  2 00:14:09 2017
+++ src/sys/arch/arm/sunxi/sunxi_usbphy.c	Fri Aug 25 00:07:03 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_usbphy.c,v 1.3 2017/07/02 00:14:09 jmcneill Exp $ */
+/* $NetBSD: sunxi_usbphy.c,v 1.4 2017/08/25 00:07:03 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca>
@@ -28,7 +28,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(0, "$NetBSD: sunxi_usbphy.c,v 1.3 2017/07/02 00:14:09 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_usbphy.c,v 1.4 2017/08/25 00:07:03 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -54,11 +54,13 @@ static int sunxi_usbphy_match(device_t, 
 static void sunxi_usbphy_attach(device_t, device_t, void *);
 
 enum sunxi_usbphy_type {
+	USBPHY_A13,
 	USBPHY_A31,
 	USBPHY_H3,
 };
 
 static const struct of_compat_data compat_data[] = {
+	{ "allwinner,sun5i-a13-usb-phy",	USBPHY_A13 },
 	{ "allwinner,sun6i-a31-usb-phy",	USBPHY_A31 },
 	{ "allwinner,sun8i-h3-usb-phy",		USBPHY_H3 },
 	{ NULL }

Index: src/sys/arch/arm/sunxi/sunxi_platform.c
diff -u src/sys/arch/arm/sunxi/sunxi_platform.c:1.6 src/sys/arch/arm/sunxi/sunxi_platform.c:1.7
--- src/sys/arch/arm/sunxi/sunxi_platform.c:1.6	Sun Jul 23 10:16:08 2017
+++ src/sys/arch/arm/sunxi/sunxi_platform.c	Fri Aug 25 00:07:03 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_platform.c,v 1.6 2017/07/23 10:16:08 jmcneill Exp $ */
+/* $NetBSD: sunxi_platform.c,v 1.7 2017/08/25 00:07:03 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca>
@@ -31,7 +31,7 @@
 #include "opt_fdt_arm.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunxi_platform.c,v 1.6 2017/07/23 10:16:08 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_platform.c,v 1.7 2017/08/25 00:07:03 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -60,12 +60,25 @@ __KERNEL_RCSID(0, "$NetBSD: sunxi_platfo
 
 #define	SUNXI_REF_FREQ	24000000
 
+#define	SUN4I_TIMER_BASE	0x01c20c00
+#define	SUN4I_TIMER_SIZE	0x90
+#define	SUN4I_TIMER_0_VAL	0x18
+
+#define	SUN4I_WDT_BASE		0x01c20c90
+#define	SUN4I_WDT_SIZE		0x10
+#define	SUN4I_WDT_CTRL		0x00
+#define	 SUN4I_WDT_CTRL_KEY	(0x333 << 1)
+#define	 SUN4I_WDT_CTRL_RESTART	__BIT(0)
+#define	SUN4I_WDT_MODE		0x04
+#define	 SUN4I_WDT_MODE_RST_EN	__BIT(1)
+#define	 SUN4I_WDT_MODE_EN	__BIT(0)
+
 #define	SUN6I_WDT_BASE		0x01c20ca0
 #define	SUN6I_WDT_SIZE		0x20
 #define	SUN6I_WDT_CFG		0x14
-#define	 SUN6I_WDT_CFG_SYS	1
+#define	 SUN6I_WDT_CFG_SYS	__BIT(0)
 #define	SUN6I_WDT_MODE		0x18
-#define	 SUN6I_WDT_MODE_EN	1
+#define	 SUN6I_WDT_MODE_EN	__BIT(0)
 
 
 #define	DEVMAP_ALIGN(a)	((a) & ~L1_S_OFFSET)
@@ -131,6 +144,49 @@ sunxi_platform_uart_freq(void)
 }
 
 static void
+sunxi_platform_null_bootstrap(void)
+{
+}
+
+static void
+sun4i_platform_reset(void)
+{
+	bus_space_tag_t bst = &armv7_generic_bs_tag;
+	bus_space_handle_t bsh;
+
+	bus_space_map(bst, SUN4I_WDT_BASE, SUN4I_WDT_SIZE, 0, &bsh);
+
+	bus_space_write_4(bst, bsh, SUN4I_WDT_CTRL,
+	    SUN4I_WDT_CTRL_KEY | SUN4I_WDT_CTRL_RESTART);
+	for (;;) {
+		bus_space_write_4(bst, bsh, SUN4I_WDT_MODE,
+		    SUN4I_WDT_MODE_EN | SUN4I_WDT_MODE_RST_EN);
+	}
+}
+
+static void
+sun4i_platform_delay(u_int n)
+{
+	static bus_space_tag_t bst = &armv7_generic_bs_tag;
+	static bus_space_handle_t bsh = 0;
+	uint32_t cur, prev;
+	long ticks = n;
+
+	if (bsh == 0)
+		bus_space_map(bst, SUN4I_TIMER_BASE, SUN4I_TIMER_SIZE, 0, &bsh);
+
+	prev = ~bus_space_read_4(bst, bsh, SUN4I_TIMER_0_VAL);
+	while (ticks > 0) {
+		cur = ~bus_space_read_4(bst, bsh, SUN4I_TIMER_0_VAL);
+		if (cur > prev)
+			ticks -= (cur - prev);
+		else
+			ticks -= (~0U - cur + prev);
+		prev = cur;
+	}
+}
+
+static void
 sun6i_platform_reset(void)
 {
 	bus_space_tag_t bst = &armv7_generic_bs_tag;
@@ -142,14 +198,18 @@ sun6i_platform_reset(void)
 	bus_space_write_4(bst, bsh, SUN6I_WDT_MODE, SUN6I_WDT_MODE_EN);
 }
 
-static void
-sun50i_platform_bootstrap(void)
-{
-	/* XXX
-  	 * This should use psci_fdt_bootstrap, but it hangs
-  	 * (at least in aarch32 mode)
-  	 */
-}
+static const struct arm_platform sun5i_platform = {
+	.devmap = sunxi_platform_devmap,
+	.bootstrap = sunxi_platform_null_bootstrap,
+	.init_attach_args = sunxi_platform_init_attach_args,
+	.early_putchar = sunxi_platform_early_putchar,
+	.device_register = sunxi_platform_device_register,
+	.reset = sun4i_platform_reset,
+	.delay = sun4i_platform_delay,
+	.uart_freq = sunxi_platform_uart_freq,
+};
+
+ARM_PLATFORM(sun5i_a13, "allwinner,sun5i-a13", &sun5i_platform);
 
 static const struct arm_platform sun6i_platform = {
 	.devmap = sunxi_platform_devmap,
@@ -181,7 +241,7 @@ ARM_PLATFORM(sun8i_a83t, "allwinner,sun8
 
 static const struct arm_platform sun50i_platform = {
 	.devmap = sunxi_platform_devmap,
-	.bootstrap = sun50i_platform_bootstrap,
+	.bootstrap = sunxi_platform_null_bootstrap,
 	.init_attach_args = sunxi_platform_init_attach_args,
 	.early_putchar = sunxi_platform_early_putchar,
 	.device_register = sunxi_platform_device_register,

Index: src/sys/arch/evbarm/conf/SUNXI
diff -u src/sys/arch/evbarm/conf/SUNXI:1.22 src/sys/arch/evbarm/conf/SUNXI:1.23
--- src/sys/arch/evbarm/conf/SUNXI:1.22	Sun Aug 13 18:27:48 2017
+++ src/sys/arch/evbarm/conf/SUNXI	Fri Aug 25 00:07:03 2017
@@ -1,5 +1,5 @@
 #
-#	$NetBSD: SUNXI,v 1.22 2017/08/13 18:27:48 jmcneill Exp $
+#	$NetBSD: SUNXI,v 1.23 2017/08/25 00:07:03 jmcneill Exp $
 #
 #	Allwinner sunxi family
 #
@@ -8,6 +8,22 @@ include	"arch/evbarm/conf/std.sunxi"
 include	"arch/evbarm/conf/GENERIC.common"
 
 makeoptions	DTS="
+	sun5i-a13-difrnce-dit4350.dts
+	sun5i-a13-empire-electronix-d709.dts
+	sun5i-a13-empire-electronix-m712.dts
+	sun5i-a13-hsg-h702.dts
+	sun5i-a13-inet-98v-rev2.dts
+	sun5i-a13-licheepi-one.dts
+	sun5i-a13-olinuxino-micro.dts
+	sun5i-a13-olinuxino.dts
+	sun5i-a13-q8-tablet.dts
+	sun5i-a13-utoo-p66.dts
+
+	sun5i-gr8-evb.dts
+	sun5i-gr8-chip-pro.dts
+
+	sun5i-r8-chip.dts
+
 	sun6i-a31-app4-evb1.dts
 	sun6i-a31-colombus.dts
 	sun6i-a31-hummingbird.dts
@@ -32,6 +48,8 @@ makeoptions	DTS="
 "
 
 options 	CPU_CORTEXA7
+options 	CPU_CORTEXA8
+options 	SOC_SUN5I_A13
 options 	SOC_SUN6I_A31
 options 	SOC_SUN8I_A83T
 options 	SOC_SUN8I_H3
@@ -65,6 +83,7 @@ cpu*		at cpus?
 psci*		at fdt?
 
 # Clock and reset controllers
+sun5ia13ccu*	at fdt? pass 4		# A13 CCU
 sun6ia31ccu*	at fdt? pass 4		# A31 CCU
 sun8ia83tccu*	at fdt? pass 4		# A83T CCU
 sun8ih3ccu*	at fdt? pass 4		# H3 CCU
@@ -81,6 +100,7 @@ gpioleds*	at fdt?
 # Timer
 gtmr*		at fdt? pass 1		# ARM Generic Timer
 armgtmr0	at gtmr?
+sunxitimer*	at fdt? 		# Allwinner async timer
 
 # Watchdog
 sunxiwdt*	at fdt?			# Allwinner watchdog
@@ -88,6 +108,7 @@ sunxiwdt*	at fdt?			# Allwinner watchdog
 # Interrupt controller
 gic*		at fdt? pass 1		# GIC
 armgic0		at gic?
+sunxiintc*	at fdt? pass 1		# Allwinner INTC
 
 # Memory controller
 

Index: src/sys/arch/evbarm/conf/std.sunxi
diff -u src/sys/arch/evbarm/conf/std.sunxi:1.3 src/sys/arch/evbarm/conf/std.sunxi:1.4
--- src/sys/arch/evbarm/conf/std.sunxi:1.3	Wed Jul  5 01:08:44 2017
+++ src/sys/arch/evbarm/conf/std.sunxi	Fri Aug 25 00:07:03 2017
@@ -1,4 +1,4 @@
-#	$NetBSD: std.sunxi,v 1.3 2017/07/05 01:08:44 jmcneill Exp $
+#	$NetBSD: std.sunxi,v 1.4 2017/08/25 00:07:03 jmcneill Exp $
 #
 
 machine	evbarm arm
@@ -20,6 +20,7 @@ options 	TPIDRPRW_IS_CURCPU
 options 	KERNEL_BASE_EXT=0x80000000
 options 	FPU_VFP
 options 	__BUS_SPACE_HAS_STREAM_METHODS
+options 	__HAVE_GENERIC_CPU_INITCLOCKS
 
 makeoptions	KERNEL_BASE_PHYS="0x40008000"
 makeoptions	KERNEL_BASE_VIRT="0x80008000"

Added files:

Index: src/sys/arch/arm/sunxi/sun5i_a13_ccu.c
diff -u /dev/null src/sys/arch/arm/sunxi/sun5i_a13_ccu.c:1.1
--- /dev/null	Fri Aug 25 00:07:03 2017
+++ src/sys/arch/arm/sunxi/sun5i_a13_ccu.c	Fri Aug 25 00:07:03 2017
@@ -0,0 +1,263 @@
+/* $NetBSD: sun5i_a13_ccu.c,v 1.1 2017/08/25 00:07:03 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+__KERNEL_RCSID(1, "$NetBSD: sun5i_a13_ccu.c,v 1.1 2017/08/25 00:07:03 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+
+#include <dev/fdt/fdtvar.h>
+
+#include <arm/sunxi/sunxi_ccu.h>
+#include <arm/sunxi/sun5i_a13_ccu.h>
+
+#define	PLL1_CFG_REG		0x000
+#define	PLL6_CFG_REG		0x028
+#define	OSC24M_CFG_REG		0x050
+#define	CPU_AHB_APB0_CFG_REG	0x054
+#define	APB1_CLK_DIV_REG	0x058
+#define	AHB_GATING_REG0		0x060
+#define	AHB_GATING_REG1		0x064
+#define	APB0_GATING_REG		0x068
+#define	APB1_GATING_REG		0x06c
+#define	USBPHY_CFG_REG		0x0cc
+#define	BE_CFG_REG		0x104
+#define	FE_CFG_REG		0x10c
+#define	CSI_CFG_REG		0x134
+#define	VE_CFG_REG		0x13c
+#define	MALI_CLOCK_CFG_REG	0x154
+#define	IEP_SCLK_CFG_REG	0x160
+
+static int sun5i_a13_ccu_match(device_t, cfdata_t, void *);
+static void sun5i_a13_ccu_attach(device_t, device_t, void *);
+
+static const char * const compatible[] = {
+	"allwinner,sun5i-a13-ccu",
+	NULL
+};
+
+CFATTACH_DECL_NEW(sunxi_a13_ccu, sizeof(struct sunxi_ccu_softc),
+	sun5i_a13_ccu_match, sun5i_a13_ccu_attach, NULL, NULL);
+
+static struct sunxi_ccu_reset sun5i_a13_ccu_resets[] = {
+	SUNXI_CCU_RESET(A13_RST_USB_PHY0, USBPHY_CFG_REG, 0),
+	SUNXI_CCU_RESET(A13_RST_USB_PHY1, USBPHY_CFG_REG, 1),
+
+	/* Missing: GPS */
+
+	SUNXI_CCU_RESET(A13_RST_DE_BE, BE_CFG_REG, 30),
+
+	SUNXI_CCU_RESET(A13_RST_DE_FE, FE_CFG_REG, 30),
+
+	/* Missing: TVE */
+
+	/* Missing: LCD */
+
+	SUNXI_CCU_RESET(A13_RST_CSI, CSI_CFG_REG, 30),
+
+	SUNXI_CCU_RESET(A13_RST_VE, VE_CFG_REG, 0),
+
+	SUNXI_CCU_RESET(A13_RST_GPU, MALI_CLOCK_CFG_REG, 30),
+
+	SUNXI_CCU_RESET(A13_RST_IEP, IEP_SCLK_CFG_REG, 30),
+};
+
+static const char *cpu_parents[] = { "losc", "osc24m", "pll_core", "pll_periph" };
+static const char *axi_parents[] = { "cpu" };
+static const char *ahb_parents[] = { "axi", "cpu", "pll_periph", NULL };
+static const char *apb0_parents[] = { "ahb" };
+static const char *apb1_parents[] = { "osc24m", "pll_periph", "losc", NULL };
+
+static struct sunxi_ccu_clk sun5i_a13_ccu_clks[] = {
+	SUNXI_CCU_GATE(A13_CLK_HOSC, "osc24m", "hosc",
+	    OSC24M_CFG_REG, 0),
+
+	SUNXI_CCU_NKMP(A13_CLK_PLL_CORE, "pll_core", "osc24m",
+	    PLL1_CFG_REG,		/* reg */
+	    __BITS(12,8),		/* n */
+	    __BITS(5,4), 		/* k */
+	    __BITS(1,0),		/* m */
+	    __BITS(17,16),		/* p */
+	    __BIT(31),			/* enable */
+	    SUNXI_CCU_NKMP_FACTOR_P_POW2 | SUNXI_CCU_NKMP_FACTOR_N_EXACT),
+
+	SUNXI_CCU_NKMP(A13_CLK_PERIPH, "pll_periph", "osc24m",
+	    PLL6_CFG_REG,		/* reg */
+	    __BITS(12,8),		/* n */
+	    __BITS(5,4), 		/* k */
+	    __BITS(1,0),		/* m */
+	    0,				/* p */
+	    __BIT(31),			/* enable */
+	    SUNXI_CCU_NKMP_DIVIDE_BY_TWO | SUNXI_CCU_NKMP_FACTOR_N_EXACT),
+
+	SUNXI_CCU_PREDIV_FIXED(A13_CLK_CPU, "cpu", cpu_parents,
+	    CPU_AHB_APB0_CFG_REG,	/* reg */
+	    0,				/* prediv */
+	    __BIT(3),			/* prediv_sel */
+	    6,				/* prediv_fixed */
+	    0,				/* div */
+	    __BITS(17,16),		/* sel */
+	    0),
+
+	SUNXI_CCU_DIV(A13_CLK_AXI, "axi", axi_parents,
+	    CPU_AHB_APB0_CFG_REG,	/* reg */
+	    __BITS(1,0),		/* div */
+	    0,				/* sel */
+	    0),
+
+	SUNXI_CCU_DIV(A13_CLK_AHB, "ahb", ahb_parents,
+	    CPU_AHB_APB0_CFG_REG,	/* reg */
+	    0,				/* div */
+	    __BITS(5,4),		/* sel */
+	    SUNXI_CCU_DIV_POWER_OF_TWO),
+
+	SUNXI_CCU_DIV(A13_CLK_APB0, "apb0", apb0_parents,
+	    CPU_AHB_APB0_CFG_REG,	/* reg */
+	    __BITS(9,8),		/* div */
+	    0,				/* sel */
+	    SUNXI_CCU_DIV_ZERO_IS_ONE | SUNXI_CCU_DIV_POWER_OF_TWO),
+
+	SUNXI_CCU_NM(A13_CLK_APB1, "apb1", apb1_parents,
+	    APB1_CLK_DIV_REG,		/* reg */
+	    __BITS(17,16),		/* n */
+	    __BITS(4,0),		/* m */
+	    __BITS(25,24),		/* sel */
+	    0,				/* enable */
+	    SUNXI_CCU_NM_POWER_OF_TWO),
+
+	/* AHB_GATING_REG0. Missing: SS, EMAC, TS, GPS */
+	SUNXI_CCU_GATE(A13_CLK_AHB_OTG, "ahb-otg", "ahb",
+	    AHB_GATING_REG0, 0),
+	SUNXI_CCU_GATE(A13_CLK_AHB_EHCI, "ahb-ehci", "ahb",
+	    AHB_GATING_REG0, 1),
+	SUNXI_CCU_GATE(A13_CLK_AHB_OHCI, "ahb-ohci", "ahb",
+	    AHB_GATING_REG0, 2),
+	SUNXI_CCU_GATE(A13_CLK_AHB_DMA, "ahb-dma", "ahb",
+	    AHB_GATING_REG0, 6),
+	SUNXI_CCU_GATE(A13_CLK_AHB_BIST, "ahb-bist", "ahb",
+	    AHB_GATING_REG0, 7),
+	SUNXI_CCU_GATE(A13_CLK_AHB_MMC0, "ahb-mmc0", "ahb",
+	    AHB_GATING_REG0, 8),
+	SUNXI_CCU_GATE(A13_CLK_AHB_MMC1, "ahb-mmc1", "ahb",
+	    AHB_GATING_REG0, 9),
+	SUNXI_CCU_GATE(A13_CLK_AHB_MMC2, "ahb-mmc2", "ahb",
+	    AHB_GATING_REG0, 10),
+	SUNXI_CCU_GATE(A13_CLK_AHB_NAND, "ahb-nand", "ahb",
+	    AHB_GATING_REG0, 13),
+	SUNXI_CCU_GATE(A13_CLK_AHB_SDRAM, "ahb-sdram", "ahb",
+	    AHB_GATING_REG0, 14),
+	SUNXI_CCU_GATE(A13_CLK_AHB_SPI0, "ahb-spi0", "ahb",
+	    AHB_GATING_REG0, 20),
+	SUNXI_CCU_GATE(A13_CLK_AHB_SPI1, "ahb-spi1", "ahb",
+	    AHB_GATING_REG0, 21),
+	SUNXI_CCU_GATE(A13_CLK_AHB_SPI2, "ahb-spi2", "ahb",
+	    AHB_GATING_REG0, 22),
+	SUNXI_CCU_GATE(A13_CLK_AHB_HSTIMER, "ahb-hstimer", "ahb",
+	    AHB_GATING_REG0, 28),
+
+	/* AHB_GATING_REG1. Missing: TVE, HDMI */
+	SUNXI_CCU_GATE(A13_CLK_AHB_VE, "ahb-ve", "ahb",
+	    AHB_GATING_REG1, 0),
+	SUNXI_CCU_GATE(A13_CLK_AHB_LCD, "ahb-lcd", "ahb",
+	    AHB_GATING_REG1, 4),
+	SUNXI_CCU_GATE(A13_CLK_AHB_CSI, "ahb-csi", "ahb",
+	    AHB_GATING_REG1, 8),
+	SUNXI_CCU_GATE(A13_CLK_AHB_DE_BE, "ahb-de_be", "ahb",
+	    AHB_GATING_REG1, 12),
+	SUNXI_CCU_GATE(A13_CLK_AHB_DE_FE, "ahb-de_fe", "ahb",
+	    AHB_GATING_REG1, 14),
+	SUNXI_CCU_GATE(A13_CLK_AHB_IEP, "ahb-iep", "ahb",
+	    AHB_GATING_REG1, 19),
+	SUNXI_CCU_GATE(A13_CLK_AHB_GPU, "ahb-gpu", "ahb",
+	    AHB_GATING_REG1, 20),
+
+	/* APB0_GATING_REG. Missing: SPDIF, I2S, KEYPAD */
+	SUNXI_CCU_GATE(A13_CLK_APB0_CODEC, "apb0-codec", "apb0",
+	    APB0_GATING_REG, 0),
+	SUNXI_CCU_GATE(A13_CLK_APB0_PIO, "apb0-pio", "apb0",
+	    APB0_GATING_REG, 5),
+	SUNXI_CCU_GATE(A13_CLK_APB0_IR, "apb0-ir", "apb0",
+	    APB0_GATING_REG, 6),
+
+	/* APB1_GATING_REG. Missing: UART0, UART2 */
+	SUNXI_CCU_GATE(A13_CLK_APB1_I2C0, "apb1-i2c0", "apb1",
+	    APB1_GATING_REG, 0),
+	SUNXI_CCU_GATE(A13_CLK_APB1_I2C1, "apb1-i2c1", "apb1",
+	    APB1_GATING_REG, 1),
+	SUNXI_CCU_GATE(A13_CLK_APB1_I2C2, "apb1-i2c2", "apb1",
+	    APB1_GATING_REG, 2),
+	SUNXI_CCU_GATE(A13_CLK_APB1_UART1, "apb1-uart1", "apb1",
+	    APB1_GATING_REG, 17),
+	SUNXI_CCU_GATE(A13_CLK_APB1_UART3, "apb1-uart3", "apb1",
+	    APB1_GATING_REG, 19),
+
+	/* USBPHY_CFG_REG */
+	SUNXI_CCU_GATE(A13_CLK_USB_OHCI, "usb-ohci", "osc24m",
+	    USBPHY_CFG_REG, 6),
+	SUNXI_CCU_GATE(A13_CLK_USB_PHY0, "usb-phy0", "osc24m",
+	    USBPHY_CFG_REG, 8),
+	SUNXI_CCU_GATE(A13_CLK_USB_PHY1, "usb-phy1", "osc24m",
+	    USBPHY_CFG_REG, 9),
+};
+
+static int
+sun5i_a13_ccu_match(device_t parent, cfdata_t cf, void *aux)
+{
+	struct fdt_attach_args * const faa = aux;
+
+	return of_match_compatible(faa->faa_phandle, compatible);
+}
+
+static void
+sun5i_a13_ccu_attach(device_t parent, device_t self, void *aux)
+{
+	struct sunxi_ccu_softc * const sc = device_private(self);
+	struct fdt_attach_args * const faa = aux;
+
+	sc->sc_dev = self;
+	sc->sc_phandle = faa->faa_phandle;
+	sc->sc_bst = faa->faa_bst;
+
+	sc->sc_resets = sun5i_a13_ccu_resets;
+	sc->sc_nresets = __arraycount(sun5i_a13_ccu_resets);
+
+	sc->sc_clks = sun5i_a13_ccu_clks;
+	sc->sc_nclks = __arraycount(sun5i_a13_ccu_clks);
+
+	if (sunxi_ccu_attach(sc) != 0)
+		return;
+
+	aprint_naive("\n");
+	aprint_normal(": A13 CCU\n");
+
+	sunxi_ccu_print(sc);
+}
Index: src/sys/arch/arm/sunxi/sun5i_a13_ccu.h
diff -u /dev/null src/sys/arch/arm/sunxi/sun5i_a13_ccu.h:1.1
--- /dev/null	Fri Aug 25 00:07:03 2017
+++ src/sys/arch/arm/sunxi/sun5i_a13_ccu.h	Fri Aug 25 00:07:03 2017
@@ -0,0 +1,145 @@
+/* $NetBSD: sun5i_a13_ccu.h,v 1.1 2017/08/25 00:07:03 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR 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 _SUN5I_A13_CCU_H
+#define _SUN5I_A13_CCU_H
+
+#define	A13_RST_USB_PHY0	0
+#define	A13_RST_USB_PHY1	1
+#define	A13_RST_GPS		2
+#define	A13_RST_DE_BE		3
+#define	A13_RST_DE_FE		4
+#define	A13_RST_TVE		5
+#define	A13_RST_LCD		6
+#define	A13_RST_CSI		7
+#define	A13_RST_VE		8
+#define	A13_RST_GPU		9
+#define	A13_RST_IEP		10
+
+#define	A13_CLK_HOSC		1
+#define	A13_CLK_PLL_CORE	2
+#define	A13_CLK_PLL_AUDIO_BASE	3
+#define	A13_CLK_PLL_AUDIO	4
+#define	A13_CLK_PLL_AUDIO_2X	5
+#define	A13_CLK_PLL_AUDIO_4X	6
+#define	A13_CLK_PLL_AUDIO_8X	7
+#define	A13_CLK_PLL_VIDEO0	8
+#define	A13_CLK_PLL_VIDEO0_2X	9
+#define	A13_CLK_PLL_VE		10
+#define	A13_CLK_PLL_DDR_BASE	11
+#define	A13_CLK_PLL_DDR		12
+#define	A13_CLK_PLL_DDR_OTHER	13
+#define	A13_CLK_PERIPH		14
+#define	A13_CLK_VIDEO1		15
+#define	A13_CLK_VIDEO1_2X	16
+#define	A13_CLK_CPU		17
+#define	A13_CLK_AXI		18
+#define	A13_CLK_AHB		19
+#define	A13_CLK_APB0		20
+#define	A13_CLK_APB1		21
+#define	A13_CLK_DRAM_AXI	22
+#define	A13_CLK_AHB_OTG		23
+#define	A13_CLK_AHB_EHCI	24
+#define	A13_CLK_AHB_OHCI	25
+#define	A13_CLK_AHB_SS		26
+#define	A13_CLK_AHB_DMA		27
+#define	A13_CLK_AHB_BIST	28
+#define	A13_CLK_AHB_MMC0	29
+#define	A13_CLK_AHB_MMC1	30
+#define	A13_CLK_AHB_MMC2	31
+#define	A13_CLK_AHB_NAND	32
+#define	A13_CLK_AHB_SDRAM	33
+#define	A13_CLK_AHB_EMAC	34
+#define	A13_CLK_AHB_TS		35
+#define	A13_CLK_AHB_SPI0	36
+#define	A13_CLK_AHB_SPI1	37
+#define	A13_CLK_AHB_SPI2	38
+#define	A13_CLK_AHB_GPS		39
+#define	A13_CLK_AHB_HSTIMER	40
+#define	A13_CLK_AHB_VE		41
+#define	A13_CLK_AHB_TVE		42
+#define	A13_CLK_AHB_LCD		43
+#define	A13_CLK_AHB_CSI		44
+#define	A13_CLK_AHB_HDMI	45
+#define	A13_CLK_AHB_DE_BE	46
+#define	A13_CLK_AHB_DE_FE	47
+#define	A13_CLK_AHB_IEP		48
+#define	A13_CLK_AHB_GPU		49
+#define	A13_CLK_APB0_CODEC	50
+#define	A13_CLK_APB0_SPDIF	51
+#define	A13_CLK_APB0_I2S	52
+#define	A13_CLK_APB0_PIO	53
+#define	A13_CLK_APB0_IR		54
+#define	A13_CLK_APB0_KEYPAD	55
+#define	A13_CLK_APB1_I2C0	56
+#define	A13_CLK_APB1_I2C1	57
+#define	A13_CLK_APB1_I2C2	58
+#define	A13_CLK_APB1_UART0	59
+#define	A13_CLK_APB1_UART1	60
+#define	A13_CLK_APB1_UART2	61
+#define	A13_CLK_APB1_UART3	62
+#define	A13_CLK_NAND		63
+#define	A13_CLK_MMC0		64
+#define	A13_CLK_MMC1		65
+#define	A13_CLK_MMC2		66
+#define	A13_CLK_TS		67
+#define	A13_CLK_SS		68
+#define	A13_CLK_SPI0		69
+#define	A13_CLK_SPI1		70
+#define	A13_CLK_SPI2		71
+#define	A13_CLK_IR		72
+#define	A13_CLK_I2S		73
+#define	A13_CLK_SPDIF		74
+#define	A13_CLK_KEYPAD		75
+#define	A13_CLK_USB_OHCI	76
+#define	A13_CLK_USB_PHY0	77
+#define	A13_CLK_USB_PHY1	78
+#define	A13_CLK_GPS		79
+#define	A13_CLK_DRAM_VE		80
+#define	A13_CLK_DRAM_CSI	81
+#define	A13_CLK_DRAM_TS		82
+#define	A13_CLK_DRAM_TVE	83
+#define	A13_CLK_DRAM_DE_FE	84
+#define	A13_CLK_DRAM_DE_BE	85
+#define	A13_CLK_DRAM_ACE	86
+#define	A13_CLK_DRAM_IEP	87
+#define	A13_CLK_DE_BE		88
+#define	A13_CLK_DE_FE		89
+#define	A13_CLK_TCON_CH0	90
+#define	A13_CLK_TCON_CH1_SCLK	91
+#define	A13_CLK_TCON_CH1	92
+#define	A13_CLK_CSI		93
+#define	A13_CLK_VE		94
+#define	A13_CLK_CODEC		95
+#define	A13_CLK_AVS		96
+#define	A13_CLK_HDMI		97
+#define	A13_CLK_GPU		98
+#define	A13_CLK_MBUS		99
+#define	A13_CLK_IEP		100
+
+#endif /* !_SUN5I_A13_CCU_H */
Index: src/sys/arch/arm/sunxi/sun5i_a13_gpio.c
diff -u /dev/null src/sys/arch/arm/sunxi/sun5i_a13_gpio.c:1.1
--- /dev/null	Fri Aug 25 00:07:03 2017
+++ src/sys/arch/arm/sunxi/sun5i_a13_gpio.c	Fri Aug 25 00:07:03 2017
@@ -0,0 +1,128 @@
+/* $NetBSD: sun5i_a13_gpio.c,v 1.1 2017/08/25 00:07:03 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: sun5i_a13_gpio.c,v 1.1 2017/08/25 00:07:03 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/types.h>
+
+#include <arm/sunxi/sunxi_gpio.h>
+
+static const struct sunxi_gpio_pins a13_pins[] = {
+	{ "PB0",  1, 0,   { "gpio_in", "gpio_out", "i2c0" } },
+	{ "PB1",  1, 1,   { "gpio_in", "gpio_out", "i2c0" } },
+	{ "PB2",  1, 2,   { "gpio_in", "gpio_out", "pwm", NULL, NULL, NULL, "eint" } },
+	{ "PB3",  1, 3,   { "gpio_in", "gpio_out", "ir0", NULL, NULL, NULL, "eint" } },
+	{ "PB4",  1, 4,   { "gpio_in", "gpio_out", "ir0", NULL, NULL, NULL, "eint" } },
+	{ "PB10", 1, 10,  { "gpio_in", "gpio_out", "spi2", NULL, NULL, NULL, "eint" } },
+	{ "PB15", 1, 15,  { "gpio_in", "gpio_out", "i2c1" } },
+	{ "PB16", 1, 16,  { "gpio_in", "gpio_out", "i2c1" } },
+	{ "PB17", 1, 17,  { "gpio_in", "gpio_out", "i2c2" } },
+	{ "PB18", 1, 18,  { "gpio_in", "gpio_out", "i2c2" } },
+
+	{ "PC0",  2, 0,   { "gpio_in", "gpio_out", "nand0", "spi0" } },
+	{ "PC1",  2, 1,   { "gpio_in", "gpio_out", "nand0", "spi0" } },
+	{ "PC2",  2, 2,   { "gpio_in", "gpio_out", "nand0", "spi0" } },
+	{ "PC3",  2, 3,   { "gpio_in", "gpio_out", "nand0", "spi0" } },
+	{ "PC4",  2, 4,   { "gpio_in", "gpio_out", "nand0" } },
+	{ "PC5",  2, 5,   { "gpio_in", "gpio_out", "nand0" } },
+	{ "PC6",  2, 6,   { "gpio_in", "gpio_out", "nand0", "mmc2" } },
+	{ "PC7",  2, 7,   { "gpio_in", "gpio_out", "nand0", "mmc2" } },
+	{ "PC8",  2, 8,   { "gpio_in", "gpio_out", "nand0", "mmc2" } },
+	{ "PC9",  2, 9,   { "gpio_in", "gpio_out", "nand0", "mmc2" } },
+	{ "PC10", 2, 10,  { "gpio_in", "gpio_out", "nand0", "mmc2" } },
+	{ "PC11", 2, 11,  { "gpio_in", "gpio_out", "nand0", "mmc2" } },
+	{ "PC12", 2, 12,  { "gpio_in", "gpio_out", "nand0", "mmc2" } },
+	{ "PC13", 2, 13,  { "gpio_in", "gpio_out", "nand0", "mmc2" } },
+	{ "PC14", 2, 14,  { "gpio_in", "gpio_out", "nand0", "mmc2" } },
+	{ "PC15", 2, 15,  { "gpio_in", "gpio_out", "nand0", "mmc2" } },
+	{ "PC19", 2, 19,  { "gpio_in", "gpio_out", "nand0" } },
+
+	{ "PD2",  3, 2,   { "gpio_in", "gpio_out", "lcd0", "uart2" } },
+	{ "PD3",  3, 3,   { "gpio_in", "gpio_out", "lcd0", "uart2" } },
+	{ "PD4",  3, 4,   { "gpio_in", "gpio_out", "lcd0", "uart2" } },
+	{ "PD5",  3, 5,   { "gpio_in", "gpio_out", "lcd0", "uart2" } },
+	{ "PD6",  3, 6,   { "gpio_in", "gpio_out", "lcd0", "emac" } },
+	{ "PD7",  3, 7,   { "gpio_in", "gpio_out", "lcd0", "emac" } },
+	{ "PD10", 3, 10,  { "gpio_in", "gpio_out", "lcd0", "emac" } },
+	{ "PD11", 3, 11,  { "gpio_in", "gpio_out", "lcd0", "emac" } },
+	{ "PD12", 3, 12,  { "gpio_in", "gpio_out", "lcd0", "emac" } },
+	{ "PD13", 3, 13,  { "gpio_in", "gpio_out", "lcd0", "emac" } },
+	{ "PD14", 3, 14,  { "gpio_in", "gpio_out", "lcd0", "emac" } },
+	{ "PD15", 3, 15,  { "gpio_in", "gpio_out", "lcd0", "emac" } },
+	{ "PD18", 3, 18,  { "gpio_in", "gpio_out", "lcd0", "emac" } },
+	{ "PD19", 3, 19,  { "gpio_in", "gpio_out", "lcd0", "emac" } },
+	{ "PD20", 3, 20,  { "gpio_in", "gpio_out", "lcd0", "emac" } },
+	{ "PD21", 3, 21,  { "gpio_in", "gpio_out", "lcd0", "emac" } },
+	{ "PD22", 3, 22,  { "gpio_in", "gpio_out", "lcd0", "emac" } },
+	{ "PD23", 3, 23,  { "gpio_in", "gpio_out", "lcd0", "emac" } },
+	{ "PD24", 3, 24,  { "gpio_in", "gpio_out", "lcd0", "emac" } },
+	{ "PD25", 3, 25,  { "gpio_in", "gpio_out", "lcd0", "emac" } },
+	{ "PD26", 3, 26,  { "gpio_in", "gpio_out", "lcd0", "emac" } },
+	{ "PD27", 3, 27,  { "gpio_in", "gpio_out", "lcd0", "emac" } },
+
+	{ "PE0",  4, 0,   { "gpio_in", NULL, "ts0", "csi0", "spi2", NULL, "eint" } },
+	{ "PE1",  4, 1,   { "gpio_in", NULL, "ts0", "csi0", "spi2", NULL, "eint" } },
+	{ "PE2",  4, 2,   { "gpio_in", NULL, "ts0", "csi0", "spi2" } },
+	{ "PE3",  4, 3,   { "gpio_in", "gpio_out", "ts0", "csi0", "spi2" } },
+	{ "PE4",  4, 4,   { "gpio_in", "gpio_out", "ts0", "csi0", "mmc2" } },
+	{ "PE5",  4, 5,   { "gpio_in", "gpio_out", "ts0", "csi0", "mmc2" } },
+	{ "PE6",  4, 6,   { "gpio_in", "gpio_out", "ts0", "csi0", "mmc2" } },
+	{ "PE7",  4, 7,   { "gpio_in", "gpio_out", "ts0", "csi0", "mmc2" } },
+	{ "PE8",  4, 8,   { "gpio_in", "gpio_out", "ts0", "csi0", "mmc2" } },
+	{ "PE9",  4, 9,   { "gpio_in", "gpio_out", "ts0", "csi0", "mmc2" } },
+	{ "PE10", 4, 10,  { "gpio_in", "gpio_out", "ts0", "csi0", "uart1" } },
+	{ "PE11", 4, 11,  { "gpio_in", "gpio_out", "ts0", "csi0", "uart1" } },
+
+	{ "PF0",  5, 0,   { "gpio_in", "gpio_out", "mmc0", "jtag" } },
+	{ "PF1",  5, 1,   { "gpio_in", "gpio_out", "mmc0", "jtag" } },
+	{ "PF2",  5, 2,   { "gpio_in", "gpio_out", "mmc0", "uart0" } },
+	{ "PF3",  5, 3,   { "gpio_in", "gpio_out", "mmc0", "jtag" } },
+	{ "PF4",  5, 4,   { "gpio_in", "gpio_out", "mmc0", "uart0" } },
+	{ "PF5",  5, 5,   { "gpio_in", "gpio_out", "mmc0", "jtag" } },
+
+	{ "PG0",  6, 0,   { "gpio_in", NULL, "gps", NULL, NULL, NULL, "eint" } },
+	{ "PG1",  6, 1,   { "gpio_in", NULL, "gps", NULL, NULL, NULL, "eint" } },
+	{ "PG2",  6, 2,   { "gpio_in", NULL, "gps", NULL, NULL, NULL, "eint" } },
+	{ "PG3",  6, 3,   { "gpio_in", "gpio_out", NULL, NULL, "uart1", NULL, "eint" } },
+	{ "PG4",  6, 4,   { "gpio_in", "gpio_out", NULL, NULL, "uart1", NULL, "eint" } },
+	{ "PG9",  6, 9,   { "gpio_in", "gpio_out", "spi1", "uart3", NULL, NULL, "eint" } },
+	{ "PG10", 6, 10,  { "gpio_in", "gpio_out", "spi1", "uart3", NULL, NULL, "eint" } },
+	{ "PG11", 6, 11,  { "gpio_in", "gpio_out", "spi1", "uart3", NULL, NULL, "eint" } },
+	{ "PG12", 6, 12,  { "gpio_in", "gpio_out", "spi1", "uart3", NULL, NULL, "eint" } },
+};
+
+const struct sunxi_gpio_padconf sun5i_a13_padconf = {
+	.npins = __arraycount(a13_pins),
+	.pins = a13_pins,
+};
Index: src/sys/arch/arm/sunxi/sunxi_intc.c
diff -u /dev/null src/sys/arch/arm/sunxi/sunxi_intc.c:1.1
--- /dev/null	Fri Aug 25 00:07:03 2017
+++ src/sys/arch/arm/sunxi/sunxi_intc.c	Fri Aug 25 00:07:03 2017
@@ -0,0 +1,272 @@
+/* $NetBSD: sunxi_intc.c,v 1.1 2017/08/25 00:07:03 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR 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.
+ */
+
+#define	_INTR_PRIVATE
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: sunxi_intc.c,v 1.1 2017/08/25 00:07:03 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/intr.h>
+#include <sys/systm.h>
+
+#include <dev/fdt/fdtvar.h>
+
+#include <arm/cpu.h>
+#include <arm/pic/picvar.h>
+#include <arm/fdt/arm_fdtvar.h>
+
+#define	INTC_MAX_SOURCES	96
+#define	INTC_MAX_GROUPS		3
+
+#define	INTC_VECTOR_REG		0x00
+#define	INTC_BASE_ADDR_REG	0x04
+#define	INTC_PROTECT_REG	0x08
+#define	 INTC_PROTECT_EN	__BIT(0)
+#define	INTC_NMII_CTRL_REG	0x0c
+#define	INTC_IRQ_PEND_REG(n)	(0x10 + ((n) * 4))
+#define	INTC_FIQ_PEND_REG(n)	(0x20 + ((n) * 4))
+#define	INTC_SEL_REG(n)		(0x30 + ((n) * 4))
+#define	INTC_EN_REG(n)		(0x40 + ((n) * 4))
+#define	INTC_MASK_REG(n)	(0x50 + ((n) * 4))
+#define	INTC_RESP_REG(n)	(0x60 + ((n) * 4))
+#define	INTC_FORCE_REG(n)	(0x70 + ((n) * 4))
+#define	INTC_SRC_PRIO_REG(n)	(0x80 + ((n) * 4))
+
+static const char * const compatible[] = {
+	"allwinner,sun4i-a10-ic",
+	NULL
+};
+
+struct sunxi_intc_softc {
+	device_t sc_dev;
+	bus_space_tag_t sc_bst;
+	bus_space_handle_t sc_bsh;
+	int sc_phandle;
+
+	uint32_t sc_enabled_irqs[INTC_MAX_GROUPS];
+
+	struct pic_softc sc_pic;
+};
+
+static struct sunxi_intc_softc *intc_softc;
+
+#define	PICTOSOFTC(pic)	\
+	((void *)((uintptr_t)(pic) - offsetof(struct sunxi_intc_softc, sc_pic)))
+
+#define INTC_READ(sc, reg) \
+	bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
+#define INTC_WRITE(sc, reg, val) \
+	bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
+
+static void
+sunxi_intc_unblock_irqs(struct pic_softc *pic, size_t irqbase, uint32_t mask)
+{
+	struct sunxi_intc_softc * const sc = PICTOSOFTC(pic);
+	const u_int group = irqbase / 32;
+
+	KASSERT((mask & sc->sc_enabled_irqs[group]) == 0);
+	sc->sc_enabled_irqs[group] |= mask;
+	INTC_WRITE(sc, INTC_EN_REG(group), sc->sc_enabled_irqs[group]);
+}
+
+static void
+sunxi_intc_block_irqs(struct pic_softc *pic, size_t irqbase, uint32_t mask)
+{
+	struct sunxi_intc_softc * const sc = PICTOSOFTC(pic);
+	const u_int group = irqbase / 32;
+
+	sc->sc_enabled_irqs[group] &= ~mask;
+	INTC_WRITE(sc, INTC_EN_REG(group), sc->sc_enabled_irqs[group]);
+}
+
+static void
+sunxi_intc_establish_irq(struct pic_softc *pic, struct intrsource *is)
+{
+	KASSERT(is->is_irq < INTC_MAX_SOURCES);
+	KASSERT(is->is_type == IST_LEVEL);
+}
+
+static void
+sunxi_intc_set_priority(struct pic_softc *pic, int ipl)
+{
+}
+
+static const struct pic_ops sunxi_intc_picops = {
+	.pic_unblock_irqs = sunxi_intc_unblock_irqs,
+	.pic_block_irqs = sunxi_intc_block_irqs,
+	.pic_establish_irq = sunxi_intc_establish_irq,
+	.pic_set_priority = sunxi_intc_set_priority,
+};
+
+static void *
+sunxi_intc_fdt_establish(device_t dev, u_int *specifier, int ipl, int flags,
+    int (*func)(void *), void *arg)
+{
+	/* 1st cell is the interrupt number */
+	const u_int irq = be32toh(specifier[0]);
+
+	if (irq >= INTC_MAX_SOURCES) {
+#ifdef DIAGNOSTIC
+		device_printf(dev, "IRQ %u is invalid\n", irq);
+#endif
+		return NULL;
+	}
+
+	const u_int mpsafe = (flags & FDT_INTR_MPSAFE) ? IST_MPSAFE : 0;
+
+	return intr_establish(irq, ipl, IST_LEVEL | mpsafe, func, arg);
+}
+
+static void
+sunxi_intc_fdt_disestablish(device_t dev, void *ih)
+{
+	intr_disestablish(ih);
+}
+
+static bool
+sunxi_intc_fdt_intrstr(device_t dev, u_int *specifier, char *buf, size_t buflen)
+{
+	/* 1st cell is the interrupt number */
+	if (!specifier)
+		return false;
+	const u_int irq = be32toh(specifier[0]);
+
+	snprintf(buf, buflen, "INTC irq %d", irq);
+
+	return true;
+}
+
+static const struct fdtbus_interrupt_controller_func sunxi_intc_fdt_funcs = {
+	.establish = sunxi_intc_fdt_establish,
+	.disestablish = sunxi_intc_fdt_disestablish,
+	.intrstr = sunxi_intc_fdt_intrstr,
+};
+
+static int
+sunxi_intc_find_pending_irqs(struct sunxi_intc_softc *sc, u_int group)
+{
+	uint32_t pend;
+
+	pend = INTC_READ(sc, INTC_IRQ_PEND_REG(group));
+
+	KASSERT((sc->sc_enabled_irqs[group] & pend) == pend);
+
+	if (pend == 0)
+		return 0;
+
+	return pic_mark_pending_sources(&sc->sc_pic, group * 32, pend);
+}
+
+static void
+sunxi_intc_irq_handler(void *frame)
+{
+	struct cpu_info * const ci = curcpu();
+	struct sunxi_intc_softc * const sc = intc_softc;
+	const int oldipl = ci->ci_cpl;
+	const uint32_t oldipl_mask = __BIT(oldipl);
+	int ipl_mask = 0;
+
+	ci->ci_data.cpu_nintr++;
+
+	if (sc->sc_enabled_irqs[0])
+		ipl_mask |= sunxi_intc_find_pending_irqs(sc, 0);
+	if (sc->sc_enabled_irqs[1])
+		ipl_mask |= sunxi_intc_find_pending_irqs(sc, 1);
+	if (sc->sc_enabled_irqs[2])
+		ipl_mask |= sunxi_intc_find_pending_irqs(sc, 2);
+
+	if ((ipl_mask & ~oldipl_mask) > oldipl_mask)
+		pic_do_pending_ints(I32_bit, oldipl, frame);
+}
+
+static int
+sunxi_intc_match(device_t parent, cfdata_t cf, void *aux)
+{
+	struct fdt_attach_args * const faa = aux;
+
+	return of_match_compatible(faa->faa_phandle, compatible);
+}
+
+static void
+sunxi_intc_attach(device_t parent, device_t self, void *aux)
+{
+	struct sunxi_intc_softc * const sc = device_private(self);
+	struct fdt_attach_args * const faa = aux;
+	const int phandle = faa->faa_phandle;
+	bus_addr_t addr;
+	bus_size_t size;
+	int error, i;
+
+	if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
+		aprint_error(": couldn't get registers\n");
+		return;
+	}
+
+	sc->sc_dev = self;
+	sc->sc_phandle = phandle;
+	sc->sc_bst = faa->faa_bst;
+	if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
+		aprint_error(": couldn't map registers\n");
+		return;
+	}
+
+	aprint_naive("\n");
+	aprint_normal(": Interrupt Controller\n");
+
+	/* Disable IRQs */
+	for (i = 0; i < INTC_MAX_GROUPS; i++) {
+		INTC_WRITE(sc, INTC_EN_REG(i), 0);
+		INTC_WRITE(sc, INTC_MASK_REG(i), 0);
+	}
+	/* Disable user mode access to intc registers */
+	INTC_WRITE(sc, INTC_PROTECT_REG, INTC_PROTECT_EN);
+
+	sc->sc_pic.pic_ops = &sunxi_intc_picops;
+	sc->sc_pic.pic_maxsources = INTC_MAX_SOURCES;
+	snprintf(sc->sc_pic.pic_name, sizeof(sc->sc_pic.pic_name), "intc");
+	pic_add(&sc->sc_pic, 0);
+
+	error = fdtbus_register_interrupt_controller(self, phandle,
+	    &sunxi_intc_fdt_funcs);
+	if (error) {
+		aprint_error_dev(self, "couldn't register with fdtbus: %d\n",
+		    error);
+		return;
+	}
+
+	KASSERT(intc_softc == NULL);
+	intc_softc = sc;
+	arm_fdt_irq_set_handler(sunxi_intc_irq_handler);
+}
+
+CFATTACH_DECL_NEW(sunxi_intc, sizeof(struct sunxi_intc_softc),
+	sunxi_intc_match, sunxi_intc_attach, NULL, NULL);
Index: src/sys/arch/arm/sunxi/sunxi_timer.c
diff -u /dev/null src/sys/arch/arm/sunxi/sunxi_timer.c:1.1
--- /dev/null	Fri Aug 25 00:07:03 2017
+++ src/sys/arch/arm/sunxi/sunxi_timer.c	Fri Aug 25 00:07:03 2017
@@ -0,0 +1,200 @@
+/* $NetBSD: sunxi_timer.c,v 1.1 2017/08/25 00:07:03 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: sunxi_timer.c,v 1.1 2017/08/25 00:07:03 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/intr.h>
+#include <sys/systm.h>
+#include <sys/timetc.h>
+
+#include <arm/locore.h>
+
+#include <dev/fdt/fdtvar.h>
+
+#include <arm/fdt/arm_fdtvar.h>
+
+#define	TMR_IRQ_EN_REG		0x00
+#define	 TMR_IRQ_EN(n)		__BIT(n)
+#define	TMR_IRQ_STAS_REG	0x04
+#define	 TMR_IRQ_STAS_PEND(n)	__BIT(n)
+#define	TMR0_CTRL_REG		0x10
+#define	 TMR0_CTRL_MODE		__BIT(7)
+#define	 TMR0_CTRL_CLK_PRESCALE	__BITS(6,4)
+#define	 TMR0_CTRL_CLK_SRC	__BITS(3,2)
+#define	  TMR0_CTRL_CLK_SRC_OSC24M	1
+#define	  TMR0_CTRL_CLK_SRC_PLL6_6	2
+#define	 TMR0_CTRL_RELOAD	__BIT(1)
+#define	 TMR0_CTRL_EN		__BIT(0)
+#define	TMR0_INTV_VALUE_REG	0x14
+#define	TMR0_CURNT_VALUE_REG	0x18
+
+static const char * const compatible[] = {
+	"allwinner,sun4i-a10-timer",
+	NULL
+};
+
+struct sunxi_timer_softc {
+	device_t sc_dev;
+	bus_space_tag_t sc_bst;
+	bus_space_handle_t sc_bsh;
+	int sc_phandle;
+	struct clk *sc_clk;
+
+	struct timecounter sc_tc;
+};
+
+#define TIMER_READ(sc, reg) \
+    bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
+#define TIMER_WRITE(sc, reg, val) \
+    bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
+
+static struct sunxi_timer_softc *timer_softc;
+
+static int
+sunxi_timer_intr(void *arg)
+{
+	struct sunxi_timer_softc * const sc = timer_softc;
+	struct clockframe *frame = arg;
+	uint32_t stas;
+
+	stas = TIMER_READ(sc, TMR_IRQ_STAS_REG);
+	if (stas == 0)
+		return 0;
+	TIMER_WRITE(sc, TMR_IRQ_STAS_REG, stas);
+
+	if ((stas & TMR_IRQ_STAS_PEND(0)) != 0)
+		hardclock(frame);
+
+	return 1;
+}
+
+static void
+sunxi_timer_cpu_initclocks(void)
+{
+	struct sunxi_timer_softc * const sc = timer_softc;
+	char intrstr[128];
+	void *ih;
+
+	KASSERT(sc != NULL);
+
+	if (!fdtbus_intr_str(sc->sc_phandle, 0, intrstr, sizeof(intrstr)))
+		panic("%s: failed to decode interrupt", __func__);
+
+	ih = fdtbus_intr_establish(sc->sc_phandle, 0, IPL_CLOCK,
+	    FDT_INTR_MPSAFE, sunxi_timer_intr, NULL);
+	if (ih == NULL)
+		panic("%s: failed to establish timer interrupt", __func__);
+
+	aprint_normal_dev(sc->sc_dev, "interrupting on %s\n", intrstr);
+
+	/* Enable Timer 0 IRQ */
+	const uint32_t irq_en = TIMER_READ(sc, TMR_IRQ_EN_REG);
+	TIMER_WRITE(sc, TMR_IRQ_EN_REG, irq_en | TMR_IRQ_EN(0));
+}
+
+static u_int
+sunxi_timer_get_timecount(struct timecounter *tc)
+{
+	struct sunxi_timer_softc * const sc = tc->tc_priv;
+
+	return ~TIMER_READ(sc, TMR0_CURNT_VALUE_REG);
+}
+
+static int
+sunxi_timer_match(device_t parent, cfdata_t cf, void *aux)
+{
+	struct fdt_attach_args * const faa = aux;
+
+	return of_match_compatible(faa->faa_phandle, compatible);
+}
+
+static void
+sunxi_timer_attach(device_t parent, device_t self, void *aux)
+{
+	struct sunxi_timer_softc * const sc = device_private(self);
+	struct fdt_attach_args * const faa = aux;
+	struct timecounter *tc = &sc->sc_tc;
+	const int phandle = faa->faa_phandle;
+	bus_addr_t addr;
+	bus_size_t size;
+
+	if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
+		aprint_error(": couldn't get registers\n");
+		return;
+	}
+
+	if ((sc->sc_clk = fdtbus_clock_get_index(phandle, 0)) == NULL) {
+		aprint_error(": couldn't get clock\n");
+		return;
+	}
+
+	sc->sc_dev = self;
+	sc->sc_phandle = phandle;
+	sc->sc_bst = faa->faa_bst;
+	if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
+		aprint_error(": couldn't map registers\n");
+		return;
+	}
+
+	aprint_naive("\n");
+	aprint_normal(": Timer\n");
+
+	const u_int rate = clk_get_rate(sc->sc_clk);
+
+	/* Disable IRQs and all timers */
+	TIMER_WRITE(sc, TMR_IRQ_EN_REG, 0);
+	TIMER_WRITE(sc, TMR_IRQ_STAS_REG, TIMER_READ(sc, TMR_IRQ_STAS_REG));
+	/* Enable Timer 0 */
+	TIMER_WRITE(sc, TMR0_INTV_VALUE_REG, rate / hz);
+	TIMER_WRITE(sc, TMR0_CTRL_REG,
+	    __SHIFTIN(TMR0_CTRL_CLK_SRC_OSC24M, TMR0_CTRL_CLK_SRC) |
+	    TMR0_CTRL_RELOAD | TMR0_CTRL_EN);
+
+	/* Timecounter setup */
+	tc->tc_get_timecount = sunxi_timer_get_timecount;
+	tc->tc_counter_mask = ~0u,
+	tc->tc_frequency = clk_get_rate(sc->sc_clk);
+	tc->tc_name = device_xname(self);
+	tc->tc_quality = 100;
+	tc->tc_priv = sc;
+	tc_init(tc);
+
+	/* Use this as the OS timer in UP configurations */
+	if (!arm_has_mpext_p) {
+		timer_softc = sc;
+		arm_fdt_timer_register(sunxi_timer_cpu_initclocks);
+	}
+}
+
+CFATTACH_DECL_NEW(sunxi_timer, sizeof(struct sunxi_timer_softc),
+	sunxi_timer_match, sunxi_timer_attach, NULL, NULL);

Reply via email to