Module Name:    src
Committed By:   jmcneill
Date:           Sun Jul  2 00:14:09 UTC 2017

Modified Files:
        src/sys/arch/arm/sunxi: files.sunxi sunxi_ccu.c sunxi_ccu.h
            sunxi_ccu_nkmp.c sunxi_platform.c sunxi_usbphy.c
        src/sys/arch/evbarm/conf: SUNXI
Added Files:
        src/sys/arch/arm/sunxi: sun6i_a31_ccu.c sun6i_a31_ccu.h sunxi_ccu_div.c

Log Message:
Add basic support for Allwinner A31.


To generate a diff of this commit:
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/arm/sunxi/files.sunxi
cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/sunxi/sun6i_a31_ccu.c \
    src/sys/arch/arm/sunxi/sun6i_a31_ccu.h \
    src/sys/arch/arm/sunxi/sunxi_ccu_div.c
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/arm/sunxi/sunxi_ccu.c \
    src/sys/arch/arm/sunxi/sunxi_ccu.h
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/sunxi/sunxi_ccu_nkmp.c \
    src/sys/arch/arm/sunxi/sunxi_platform.c \
    src/sys/arch/arm/sunxi/sunxi_usbphy.c
cvs rdiff -u -r1.7 -r1.8 src/sys/arch/evbarm/conf/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/sunxi/files.sunxi
diff -u src/sys/arch/arm/sunxi/files.sunxi:1.6 src/sys/arch/arm/sunxi/files.sunxi:1.7
--- src/sys/arch/arm/sunxi/files.sunxi:1.6	Sat Jul  1 16:25:16 2017
+++ src/sys/arch/arm/sunxi/files.sunxi	Sun Jul  2 00:14:09 2017
@@ -1,4 +1,4 @@
-#	$NetBSD: files.sunxi,v 1.6 2017/07/01 16:25:16 jmcneill Exp $
+#	$NetBSD: files.sunxi,v 1.7 2017/07/02 00:14:09 jmcneill Exp $
 #
 # Configuration info for Allwinner sunxi family SoCs
 #
@@ -20,11 +20,17 @@ file	arch/arm/sunxi/sunxi_platform.c		so
 # CCU
 define	sunxi_ccu
 file	arch/arm/sunxi/sunxi_ccu.c		sunxi_ccu
+file	arch/arm/sunxi/sunxi_ccu_div.c		sunxi_ccu
 file	arch/arm/sunxi/sunxi_ccu_gate.c		sunxi_ccu
 file	arch/arm/sunxi/sunxi_ccu_nm.c		sunxi_ccu
 file	arch/arm/sunxi/sunxi_ccu_nkmp.c		sunxi_ccu
 file	arch/arm/sunxi/sunxi_ccu_prediv.c	sunxi_ccu
 
+# CCU (A31)
+device	sun6ia31ccu: sunxi_ccu
+attach	sun6ia31ccu at fdt with sunxi_a31_ccu
+file	arch/arm/sunxi/sun6i_a31_ccu.c		sunxi_a31_ccu
+
 # CCU (H3)
 device	sun8ih3ccu: sunxi_ccu
 attach	sun8ih3ccu at fdt with sunxi_h3_ccu
@@ -71,3 +77,5 @@ file	arch/arm/sunxi/sunxi_emac.c		sunxi_
 defflag	opt_soc.h			SOC_SUNXI
 defflag	opt_soc.h			SOC_SUN8I: SOC_SUNXI
 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

Index: src/sys/arch/arm/sunxi/sunxi_ccu.c
diff -u src/sys/arch/arm/sunxi/sunxi_ccu.c:1.4 src/sys/arch/arm/sunxi/sunxi_ccu.c:1.5
--- src/sys/arch/arm/sunxi/sunxi_ccu.c:1.4	Thu Jun 29 21:34:50 2017
+++ src/sys/arch/arm/sunxi/sunxi_ccu.c	Sun Jul  2 00:14:09 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_ccu.c,v 1.4 2017/06/29 21:34:50 jmcneill Exp $ */
+/* $NetBSD: sunxi_ccu.c,v 1.5 2017/07/02 00:14:09 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_ccu.c,v 1.4 2017/06/29 21:34:50 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_ccu.c,v 1.5 2017/07/02 00:14:09 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -328,16 +328,17 @@ sunxi_ccu_print(struct sunxi_ccu_softc *
 		case SUNXI_CCU_NM:	type = "nm"; break;
 		case SUNXI_CCU_NKMP:	type = "nkmp"; break;
 		case SUNXI_CCU_PREDIV:	type = "prediv"; break;
+		case SUNXI_CCU_DIV:	type = "div"; break;
 		default:		type = "???"; break;
 		}
 
         	aprint_debug_dev(sc->sc_dev,
-		    "%3d %-12s %2s %-12s %-7s %10d Hz\n",
+		    "%3d %-12s %2s %-12s %-7s ",
 		    i,
         	    clk->base.name,
         	    clkp_parent ? "<-" : "",
         	    clkp_parent ? clkp_parent->name : "",
-        	    type,
-		    clk_get_rate(&clk->base));
+        	    type);
+		aprint_debug("%10d Hz\n", clk_get_rate(&clk->base));
 	}
 }
Index: src/sys/arch/arm/sunxi/sunxi_ccu.h
diff -u src/sys/arch/arm/sunxi/sunxi_ccu.h:1.4 src/sys/arch/arm/sunxi/sunxi_ccu.h:1.5
--- src/sys/arch/arm/sunxi/sunxi_ccu.h:1.4	Thu Jun 29 17:08:52 2017
+++ src/sys/arch/arm/sunxi/sunxi_ccu.h	Sun Jul  2 00:14:09 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_ccu.h,v 1.4 2017/06/29 17:08:52 jmcneill Exp $ */
+/* $NetBSD: sunxi_ccu.h,v 1.5 2017/07/02 00:14:09 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca>
@@ -60,6 +60,7 @@ enum sunxi_ccu_clktype {
 	SUNXI_CCU_NM,
 	SUNXI_CCU_NKMP,
 	SUNXI_CCU_PREDIV,
+	SUNXI_CCU_DIV,
 };
 
 struct sunxi_ccu_gate {
@@ -170,6 +171,44 @@ const char *sunxi_ccu_nm_get_parent(stru
 		.get_parent = sunxi_ccu_nm_get_parent,		\
 	}
 
+struct sunxi_ccu_div {
+	bus_size_t	reg;
+	const char	**parents;
+	u_int		nparents;
+	uint32_t	div;
+	uint32_t	sel;
+	uint32_t	flags;
+#define	SUNXI_CCU_DIV_POWER_OF_TWO	__BIT(0)
+#define	SUNXI_CCU_DIV_ZERO_IS_ONE	__BIT(1)
+};
+
+u_int	sunxi_ccu_div_get_rate(struct sunxi_ccu_softc *,
+			       struct sunxi_ccu_clk *);
+int	sunxi_ccu_div_set_rate(struct sunxi_ccu_softc *,
+			       struct sunxi_ccu_clk *, u_int);
+int	sunxi_ccu_div_set_parent(struct sunxi_ccu_softc *,
+			         struct sunxi_ccu_clk *,
+			         const char *);
+const char *sunxi_ccu_div_get_parent(struct sunxi_ccu_softc *,
+				     struct sunxi_ccu_clk *);
+
+#define	SUNXI_CCU_DIV(_id, _name, _parents, _reg, _div,		\
+		      _sel, _flags)				\
+	[_id] = {						\
+		.type = SUNXI_CCU_DIV,				\
+		.base.name = (_name),				\
+		.u.div.reg = (_reg),				\
+		.u.div.parents = (_parents),			\
+		.u.div.nparents = __arraycount(_parents),	\
+		.u.div.div = (_div),				\
+		.u.div.sel = (_sel),				\
+		.u.div.flags = (_flags),			\
+		.get_rate = sunxi_ccu_div_get_rate,		\
+		.set_rate = sunxi_ccu_div_set_rate,		\
+		.set_parent = sunxi_ccu_div_set_parent,		\
+		.get_parent = sunxi_ccu_div_get_parent,		\
+	}
+
 struct sunxi_ccu_prediv {
 	bus_size_t	reg;
 	const char	**parents;
@@ -220,6 +259,7 @@ struct sunxi_ccu_clk {
 		struct sunxi_ccu_nm nm;
 		struct sunxi_ccu_nkmp nkmp;
 		struct sunxi_ccu_prediv prediv;
+		struct sunxi_ccu_div div;
 	} u;
 
 	int		(*enable)(struct sunxi_ccu_softc *,

Index: src/sys/arch/arm/sunxi/sunxi_ccu_nkmp.c
diff -u src/sys/arch/arm/sunxi/sunxi_ccu_nkmp.c:1.2 src/sys/arch/arm/sunxi/sunxi_ccu_nkmp.c:1.3
--- src/sys/arch/arm/sunxi/sunxi_ccu_nkmp.c:1.2	Thu Jun 29 10:53:59 2017
+++ src/sys/arch/arm/sunxi/sunxi_ccu_nkmp.c	Sun Jul  2 00:14:09 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_ccu_nkmp.c,v 1.2 2017/06/29 10:53:59 jmcneill Exp $ */
+/* $NetBSD: sunxi_ccu_nkmp.c,v 1.3 2017/07/02 00:14:09 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunxi_ccu_nkmp.c,v 1.2 2017/06/29 10:53:59 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_ccu_nkmp.c,v 1.3 2017/07/02 00:14:09 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -85,7 +85,10 @@ sunxi_ccu_nkmp_get_rate(struct sunxi_ccu
 		m = __SHIFTOUT(val, nkmp->m);
 	else
 		m = 0;
-	p = __SHIFTOUT(val, nkmp->p);
+	if (nkmp->p)
+		p = __SHIFTOUT(val, nkmp->p);
+	else
+		p = 0;
 
 	if (nkmp->enable && !(val & nkmp->enable))
 		return 0;
Index: src/sys/arch/arm/sunxi/sunxi_platform.c
diff -u src/sys/arch/arm/sunxi/sunxi_platform.c:1.2 src/sys/arch/arm/sunxi/sunxi_platform.c:1.3
--- src/sys/arch/arm/sunxi/sunxi_platform.c:1.2	Fri Jun 30 09:05:52 2017
+++ src/sys/arch/arm/sunxi/sunxi_platform.c	Sun Jul  2 00:14:09 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_platform.c,v 1.2 2017/06/30 09:05:52 jmcneill Exp $ */
+/* $NetBSD: sunxi_platform.c,v 1.3 2017/07/02 00:14:09 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.2 2017/06/30 09:05:52 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_platform.c,v 1.3 2017/07/02 00:14:09 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -60,12 +60,12 @@ __KERNEL_RCSID(0, "$NetBSD: sunxi_platfo
 
 #define	SUNXI_REF_FREQ	24000000
 
-#define	SUN8I_WDT_BASE		0x01c20ca0
-#define	SUN8I_WDT_SIZE		0x20
-#define	SUN8I_WDT_CFG		0x14
-#define	 SUN8I_WDT_CFG_SYS	1
-#define	SUN8I_WDT_MODE		0x18
-#define	 SUN8I_WDT_MODE_EN	1
+#define	SUN6I_WDT_BASE		0x01c20ca0
+#define	SUN6I_WDT_SIZE		0x20
+#define	SUN6I_WDT_CFG		0x14
+#define	 SUN6I_WDT_CFG_SYS	1
+#define	SUN6I_WDT_MODE		0x18
+#define	 SUN6I_WDT_MODE_EN	1
 
 
 #define	DEVMAP_ALIGN(a)	((a) & ~L1_S_OFFSET)
@@ -124,33 +124,46 @@ sunxi_platform_device_register(device_t 
 {
 }
 
+static u_int
+sunxi_platform_uart_freq(void)
+{
+	return SUNXI_REF_FREQ;
+}
+
 static void
-sun8i_platform_reset(void)
+sun6i_platform_reset(void)
 {
 	bus_space_tag_t bst = &armv7_generic_bs_tag;
 	bus_space_handle_t bsh;
 
-	bus_space_map(bst, SUN8I_WDT_BASE, SUN8I_WDT_SIZE, 0, &bsh);
+	bus_space_map(bst, SUN6I_WDT_BASE, SUN6I_WDT_SIZE, 0, &bsh);
 
-	bus_space_write_4(bst, bsh, SUN8I_WDT_CFG, SUN8I_WDT_CFG_SYS);
-	bus_space_write_4(bst, bsh, SUN8I_WDT_MODE, SUN8I_WDT_MODE_EN);
+	bus_space_write_4(bst, bsh, SUN6I_WDT_CFG, SUN6I_WDT_CFG_SYS);
+	bus_space_write_4(bst, bsh, SUN6I_WDT_MODE, SUN6I_WDT_MODE_EN);
 }
 
-static u_int
-sunxi_platform_uart_freq(void)
-{
-	return SUNXI_REF_FREQ;
-}
+static const struct arm_platform sun8i_platform = {
+	.devmap = sunxi_platform_devmap,
+	.bootstrap = psci_fdt_bootstrap,
+	.init_attach_args = sunxi_platform_init_attach_args,
+	.early_putchar = sunxi_platform_early_putchar,
+	.device_register = sunxi_platform_device_register,
+	.reset = sun6i_platform_reset,
+	.delay = gtmr_delay,
+	.uart_freq = sunxi_platform_uart_freq,
+};
+
+ARM_PLATFORM(sun8i_h3, "allwinner,sun8i-h3", &sun8i_platform);
 
-static const struct arm_platform sun8i_h3_platform = {
+static const struct arm_platform sun6i_platform = {
 	.devmap = sunxi_platform_devmap,
 	.bootstrap = psci_fdt_bootstrap,
 	.init_attach_args = sunxi_platform_init_attach_args,
 	.early_putchar = sunxi_platform_early_putchar,
 	.device_register = sunxi_platform_device_register,
-	.reset = sun8i_platform_reset,
+	.reset = sun6i_platform_reset,
 	.delay = gtmr_delay,
 	.uart_freq = sunxi_platform_uart_freq,
 };
 
-ARM_PLATFORM(sun8i_h3, "allwinner,sun8i-h3", &sun8i_h3_platform);
+ARM_PLATFORM(sun6i_a31, "allwinner,sun6i-a31", &sun6i_platform);
Index: src/sys/arch/arm/sunxi/sunxi_usbphy.c
diff -u src/sys/arch/arm/sunxi/sunxi_usbphy.c:1.2 src/sys/arch/arm/sunxi/sunxi_usbphy.c:1.3
--- src/sys/arch/arm/sunxi/sunxi_usbphy.c:1.2	Thu Jun 29 20:54:03 2017
+++ src/sys/arch/arm/sunxi/sunxi_usbphy.c	Sun Jul  2 00:14:09 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_usbphy.c,v 1.2 2017/06/29 20:54:03 jmcneill Exp $ */
+/* $NetBSD: sunxi_usbphy.c,v 1.3 2017/07/02 00:14:09 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.2 2017/06/29 20:54:03 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_usbphy.c,v 1.3 2017/07/02 00:14:09 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -53,9 +53,15 @@ __KERNEL_RCSID(0, "$NetBSD: sunxi_usbphy
 static int sunxi_usbphy_match(device_t, cfdata_t, void *);
 static void sunxi_usbphy_attach(device_t, device_t, void *);
 
-static const char * const compatible[] = {
-	"allwinner,sun8i-h3-usb-phy",
-	NULL
+enum sunxi_usbphy_type {
+	USBPHY_A31,
+	USBPHY_H3,
+};
+
+static const struct of_compat_data compat_data[] = {
+	{ "allwinner,sun6i-a31-usb-phy",	USBPHY_A31 },
+	{ "allwinner,sun8i-h3-usb-phy",		USBPHY_H3 },
+	{ NULL }
 };
 
 #define	SUNXI_MAXUSBPHY		4
@@ -70,6 +76,7 @@ struct sunxi_usbphy_softc {
 	device_t		sc_dev;
 	bus_space_tag_t		sc_bst;
 	bus_space_handle_t	sc_bsh_phy_ctrl;
+	enum sunxi_usbphy_type	sc_type;
 
 	struct sunxi_usbphy	sc_phys[SUNXI_MAXUSBPHY];
 	u_int			sc_nphys;
@@ -133,10 +140,12 @@ sunxi_usbphy_enable(device_t dev, void *
 		USBPHY_WRITE(sc, phy->phy_index, HCI_ICR, val);
 	}
 
-	/* H3-specific */
-	val = USBPHY_READ(sc, phy->phy_index, PMU_UNK_H3);
-	val &= ~PMU_UNK_H3_CLR;
-	USBPHY_WRITE(sc, phy->phy_index, PMU_UNK_H3, val);
+	if (sc->sc_type == USBPHY_H3) {
+		/* H3-specific */
+		val = USBPHY_READ(sc, phy->phy_index, PMU_UNK_H3);
+		val &= ~PMU_UNK_H3_CLR;
+		USBPHY_WRITE(sc, phy->phy_index, PMU_UNK_H3, val);
+	}
 
 	if (phy->phy_reg == NULL)
 		return 0;
@@ -162,7 +171,7 @@ sunxi_usbphy_match(device_t parent, cfda
 {
 	struct fdt_attach_args * const faa = aux;
 
-	return of_match_compatible(faa->faa_phandle, compatible);
+	return of_match_compat_data(faa->faa_phandle, compat_data);
 }
 
 static void
@@ -181,6 +190,7 @@ sunxi_usbphy_attach(device_t parent, dev
 
 	sc->sc_dev = self;
 	sc->sc_bst = faa->faa_bst;
+	sc->sc_type = of_search_compatible(phandle, compat_data)->data;
 
 	if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
 		aprint_error(": couldn't get phy ctrl registers\n");

Index: src/sys/arch/evbarm/conf/SUNXI
diff -u src/sys/arch/evbarm/conf/SUNXI:1.7 src/sys/arch/evbarm/conf/SUNXI:1.8
--- src/sys/arch/evbarm/conf/SUNXI:1.7	Sat Jul  1 16:25:15 2017
+++ src/sys/arch/evbarm/conf/SUNXI	Sun Jul  2 00:14:09 2017
@@ -1,5 +1,5 @@
 #
-#	$NetBSD: SUNXI,v 1.7 2017/07/01 16:25:15 jmcneill Exp $
+#	$NetBSD: SUNXI,v 1.8 2017/07/02 00:14:09 jmcneill Exp $
 #
 #	Allwinner sunxi family
 #
@@ -8,6 +8,13 @@ include	"arch/evbarm/conf/std.sunxi"
 include	"arch/evbarm/conf/GENERIC.common"
 
 makeoptions	DTS="
+	sun6i-a31-app4-evb1.dts
+	sun6i-a31-colombus.dts
+	sun6i-a31-hummingbird.dts
+	sun6i-a31-i7.dts
+	sun6i-a31-m9.dts
+	sun6i-a31-mele-a1000g-quad.dts
+
 	sun8i-h3-bananapi-m2-plus.dts
 	sun8i-h3-beelink-x2.dts
 	sun8i-h3-nanopi-m1.dts
@@ -21,6 +28,7 @@ makeoptions	DTS="
 "
 
 options 	CPU_CORTEXA7
+options 	SOC_SUN6I_A31
 options 	SOC_SUN8I_H3
 options 	MULTIPROCESSOR
 
@@ -52,9 +60,10 @@ cpu*		at cpus?
 psci*		at fdt?
 
 # Clock and reset controllers
+sun6ia31ccu*	at fdt? pass 4		# A31 CCU
 sun8ih3ccu*	at fdt? pass 4		# H3 CCU
 
-fclock*		at fdt? pass 4
+fclock*		at fdt? pass 3
 fregulator*	at fdt? pass 4
 gpiokeys*	at fdt?
 

Added files:

Index: src/sys/arch/arm/sunxi/sun6i_a31_ccu.c
diff -u /dev/null src/sys/arch/arm/sunxi/sun6i_a31_ccu.c:1.1
--- /dev/null	Sun Jul  2 00:14:09 2017
+++ src/sys/arch/arm/sunxi/sun6i_a31_ccu.c	Sun Jul  2 00:14:09 2017
@@ -0,0 +1,277 @@
+/* $NetBSD: sun6i_a31_ccu.c,v 1.1 2017/07/02 00:14:09 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca>
+ * Copyright (c) 2017 Emmanuel Vadot <m...@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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: sun6i_a31_ccu.c,v 1.1 2017/07/02 00:14:09 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/sun6i_a31_ccu.h>
+
+#define	PLL_PERIPH_CTRL_REG	0x028
+#define	AHB1_APB1_CFG_REG	0x054
+#define	APB2_CLK_DIV_REG	0x058
+#define	AHB1_GATING_REG0	0x060
+#define	AHB1_GATING_REG1	0x064
+#define	APB1_GATING_REG		0x068
+#define	APB2_GATING_REG		0x06c
+#define	SD0_CLK_REG		0x088
+#define	SD1_CLK_REG		0x08c
+#define	SD2_CLK_REG		0x090
+#define	SD3_CLK_REG		0x094
+#define	USBPHY_CFG_REG		0x0cc
+#define	BUS_SOFT_RST_REG0	0x2c0
+#define	BUS_SOFT_RST_REG1	0x2c4
+#define	BUS_SOFT_RST_REG2	0x2c8
+#define	BUS_SOFT_RST_REG3	0x2d0
+#define	BUS_SOFT_RST_REG4	0x2d8
+
+static int sun6i_a31_ccu_match(device_t, cfdata_t, void *);
+static void sun6i_a31_ccu_attach(device_t, device_t, void *);
+
+static const char * const compatible[] = {
+	"allwinner,sun6i-a31-ccu",
+	NULL
+};
+
+CFATTACH_DECL_NEW(sunxi_a31_ccu, sizeof(struct sunxi_ccu_softc),
+	sun6i_a31_ccu_match, sun6i_a31_ccu_attach, NULL, NULL);
+
+static struct sunxi_ccu_reset sun6i_a31_ccu_resets[] = {
+	SUNXI_CCU_RESET(A31_RST_USB_PHY0, USBPHY_CFG_REG, 0),
+	SUNXI_CCU_RESET(A31_RST_USB_PHY1, USBPHY_CFG_REG, 1),
+	SUNXI_CCU_RESET(A31_RST_USB_PHY2, USBPHY_CFG_REG, 2),
+
+	SUNXI_CCU_RESET(A31_RST_AHB1_MIPI_DSI, BUS_SOFT_RST_REG0, 1),
+	SUNXI_CCU_RESET(A31_RST_AHB1_SS, BUS_SOFT_RST_REG0, 5),
+	SUNXI_CCU_RESET(A31_RST_AHB1_DMA, BUS_SOFT_RST_REG0, 6),
+	SUNXI_CCU_RESET(A31_RST_AHB1_MMC0, BUS_SOFT_RST_REG0, 8),
+	SUNXI_CCU_RESET(A31_RST_AHB1_MMC1, BUS_SOFT_RST_REG0, 9),
+	SUNXI_CCU_RESET(A31_RST_AHB1_MMC2, BUS_SOFT_RST_REG0, 10),
+	SUNXI_CCU_RESET(A31_RST_AHB1_MMC3, BUS_SOFT_RST_REG0, 11),
+	SUNXI_CCU_RESET(A31_RST_AHB1_NAND1, BUS_SOFT_RST_REG0, 12),
+	SUNXI_CCU_RESET(A31_RST_AHB1_NAND0, BUS_SOFT_RST_REG0, 13),
+	SUNXI_CCU_RESET(A31_RST_AHB1_SDRAM, BUS_SOFT_RST_REG0, 14),
+	SUNXI_CCU_RESET(A31_RST_AHB1_EMAC, BUS_SOFT_RST_REG0, 17),
+	SUNXI_CCU_RESET(A31_RST_AHB1_TS, BUS_SOFT_RST_REG0, 18),
+	SUNXI_CCU_RESET(A31_RST_AHB1_HSTIMER, BUS_SOFT_RST_REG0, 19),
+	SUNXI_CCU_RESET(A31_RST_AHB1_SPI0, BUS_SOFT_RST_REG0, 20),
+	SUNXI_CCU_RESET(A31_RST_AHB1_SPI1, BUS_SOFT_RST_REG0, 21),
+	SUNXI_CCU_RESET(A31_RST_AHB1_SPI2, BUS_SOFT_RST_REG0, 22),
+	SUNXI_CCU_RESET(A31_RST_AHB1_SPI3, BUS_SOFT_RST_REG0, 23),
+	SUNXI_CCU_RESET(A31_RST_AHB1_OTG, BUS_SOFT_RST_REG0, 24),
+	SUNXI_CCU_RESET(A31_RST_AHB1_EHCI0, BUS_SOFT_RST_REG0, 26),
+	SUNXI_CCU_RESET(A31_RST_AHB1_EHCI1, BUS_SOFT_RST_REG0, 27),
+	SUNXI_CCU_RESET(A31_RST_AHB1_OHCI0, BUS_SOFT_RST_REG0, 29),
+	SUNXI_CCU_RESET(A31_RST_AHB1_OHCI1, BUS_SOFT_RST_REG0, 30),
+	SUNXI_CCU_RESET(A31_RST_AHB1_OHCI2, BUS_SOFT_RST_REG0, 31),
+        
+	SUNXI_CCU_RESET(A31_RST_AHB1_VE, BUS_SOFT_RST_REG1, 0),
+	SUNXI_CCU_RESET(A31_RST_AHB1_LCD0, BUS_SOFT_RST_REG1, 4),
+	SUNXI_CCU_RESET(A31_RST_AHB1_LCD1, BUS_SOFT_RST_REG1, 5),
+	SUNXI_CCU_RESET(A31_RST_AHB1_CSI, BUS_SOFT_RST_REG1, 8),
+	SUNXI_CCU_RESET(A31_RST_AHB1_HDMI, BUS_SOFT_RST_REG1, 11),
+	SUNXI_CCU_RESET(A31_RST_AHB1_BE0, BUS_SOFT_RST_REG1, 12),
+	SUNXI_CCU_RESET(A31_RST_AHB1_BE1, BUS_SOFT_RST_REG1, 13),
+	SUNXI_CCU_RESET(A31_RST_AHB1_FE0, BUS_SOFT_RST_REG1, 14),
+	SUNXI_CCU_RESET(A31_RST_AHB1_FE1, BUS_SOFT_RST_REG1, 15),
+	SUNXI_CCU_RESET(A31_RST_AHB1_MP, BUS_SOFT_RST_REG1, 16),
+	SUNXI_CCU_RESET(A31_RST_AHB1_GPU, BUS_SOFT_RST_REG1, 20),
+	SUNXI_CCU_RESET(A31_RST_AHB1_DEU0, BUS_SOFT_RST_REG1, 23),
+	SUNXI_CCU_RESET(A31_RST_AHB1_DEU1, BUS_SOFT_RST_REG1, 24),
+	SUNXI_CCU_RESET(A31_RST_AHB1_DRC0, BUS_SOFT_RST_REG1, 25),
+	SUNXI_CCU_RESET(A31_RST_AHB1_DRC1, BUS_SOFT_RST_REG1, 26),
+
+	SUNXI_CCU_RESET(A31_RST_AHB1_LVDS, BUS_SOFT_RST_REG2, 0),
+
+	SUNXI_CCU_RESET(A31_RST_APB1_CODEC, BUS_SOFT_RST_REG3, 0),
+	SUNXI_CCU_RESET(A31_RST_APB1_SPDIF, BUS_SOFT_RST_REG3, 1),
+	SUNXI_CCU_RESET(A31_RST_APB1_DIGITAL_MIC, BUS_SOFT_RST_REG3, 4),
+	SUNXI_CCU_RESET(A31_RST_APB1_DAUDIO0, BUS_SOFT_RST_REG3, 12),
+	SUNXI_CCU_RESET(A31_RST_APB1_DAUDIO1, BUS_SOFT_RST_REG3, 13),
+
+	SUNXI_CCU_RESET(A31_RST_APB2_I2C0, BUS_SOFT_RST_REG4, 0),
+	SUNXI_CCU_RESET(A31_RST_APB2_I2C1, BUS_SOFT_RST_REG4, 1),
+	SUNXI_CCU_RESET(A31_RST_APB2_I2C2, BUS_SOFT_RST_REG4, 2),
+	SUNXI_CCU_RESET(A31_RST_APB2_I2C3, BUS_SOFT_RST_REG4, 3),
+	SUNXI_CCU_RESET(A31_RST_APB2_UART0, BUS_SOFT_RST_REG4, 16),
+	SUNXI_CCU_RESET(A31_RST_APB2_UART1, BUS_SOFT_RST_REG4, 17),
+	SUNXI_CCU_RESET(A31_RST_APB2_UART2, BUS_SOFT_RST_REG4, 18),
+	SUNXI_CCU_RESET(A31_RST_APB2_UART3, BUS_SOFT_RST_REG4, 19),
+	SUNXI_CCU_RESET(A31_RST_APB2_UART4, BUS_SOFT_RST_REG4, 20),
+	SUNXI_CCU_RESET(A31_RST_APB2_UART5, BUS_SOFT_RST_REG4, 21),
+};
+
+static const char *ahb1_parents[] = { "losc", "hosc", "axi", "pll_periph" };
+static const char *apb1_parents[] = { "ahb1" };
+static const char *apb2_parents[] = { "losc", "hosc", "pll_periph", "pll_periph" };
+static const char *mod_parents[] = { "hosc", "pll_periph" };
+
+static struct sunxi_ccu_clk sun6i_a31_ccu_clks[] = {
+	SUNXI_CCU_NKMP(A31_CLK_PLL_PERIPH, "pll_periph", "hosc",
+	    PLL_PERIPH_CTRL_REG,	/* reg */
+	    __BITS(12,8),		/* n */
+	    __BITS(5,4), 		/* k */
+	    0,				/* m */
+	    0,				/* p */
+	    __BIT(31),			/* enable */
+	    SUNXI_CCU_NKMP_DIVIDE_BY_TWO),
+
+	SUNXI_CCU_DIV(A31_CLK_APB1, "apb1", apb1_parents,
+	    AHB1_APB1_CFG_REG,	/* reg */
+	    __BITS(9,8),	/* div */
+	    0,			/* sel */
+	    SUNXI_CCU_DIV_POWER_OF_TWO|SUNXI_CCU_DIV_ZERO_IS_ONE),
+
+	SUNXI_CCU_PREDIV(A31_CLK_AHB1, "ahb1", ahb1_parents,
+	    AHB1_APB1_CFG_REG,	/* reg */
+	    __BITS(7,6),	/* prediv */
+	    __BIT(3),		/* prediv_sel */
+	    __BITS(5,4),	/* div */
+	    __BITS(13,12),	/* sel */
+	    SUNXI_CCU_PREDIV_POWER_OF_TWO),
+
+	SUNXI_CCU_NM(A31_CLK_APB2, "apb2", apb2_parents,
+	    APB2_CLK_DIV_REG,	/* reg */
+	    __BITS(17,16),	/* n */
+	    __BITS(4,0),	/* m */
+	    __BITS(25,24),	/* sel */
+	    0,			/* enable */
+	    SUNXI_CCU_NM_POWER_OF_TWO),
+
+	SUNXI_CCU_NM(A31_CLK_MMC0, "mmc0", mod_parents,
+	    SD0_CLK_REG, __BITS(17, 16), __BITS(3,0), __BITS(25, 24), __BIT(31),
+	    SUNXI_CCU_NM_POWER_OF_TWO|SUNXI_CCU_NM_ROUND_DOWN),
+	SUNXI_CCU_NM(A31_CLK_MMC1, "mmc1", mod_parents,
+	    SD1_CLK_REG, __BITS(17, 16), __BITS(3,0), __BITS(25, 24), __BIT(31),
+	    SUNXI_CCU_NM_POWER_OF_TWO|SUNXI_CCU_NM_ROUND_DOWN),
+	SUNXI_CCU_NM(A31_CLK_MMC2, "mmc2", mod_parents,
+	    SD2_CLK_REG, __BITS(17, 16), __BITS(3,0), __BITS(25, 24), __BIT(31),
+	    SUNXI_CCU_NM_POWER_OF_TWO|SUNXI_CCU_NM_ROUND_DOWN),
+	SUNXI_CCU_NM(A31_CLK_MMC3, "mmc3", mod_parents,
+	    SD3_CLK_REG, __BITS(17, 16), __BITS(3,0), __BITS(25, 24), __BIT(31),
+	    SUNXI_CCU_NM_POWER_OF_TWO|SUNXI_CCU_NM_ROUND_DOWN),
+
+	SUNXI_CCU_GATE(A31_CLK_AHB1_MMC0, "ahb1-mmc0", "ahb1",
+	    AHB1_GATING_REG0, 8),
+	SUNXI_CCU_GATE(A31_CLK_AHB1_MMC1, "ahb1-mmc1", "ahb1",
+	    AHB1_GATING_REG0, 9),
+	SUNXI_CCU_GATE(A31_CLK_AHB1_MMC2, "ahb1-mmc2", "ahb1",
+	    AHB1_GATING_REG0, 10),
+	SUNXI_CCU_GATE(A31_CLK_AHB1_MMC3, "ahb1-mmc3", "ahb1",
+	    AHB1_GATING_REG0, 11),
+	SUNXI_CCU_GATE(A31_CLK_AHB1_EMAC, "ahb1-emac", "ahb1",
+	    AHB1_GATING_REG0, 17),
+	SUNXI_CCU_GATE(A31_CLK_AHB1_OTG, "ahb1-otg", "ahb1",
+	    AHB1_GATING_REG0, 24),
+	SUNXI_CCU_GATE(A31_CLK_AHB1_EHCI0, "ahb1-ehci0", "ahb1",
+	    AHB1_GATING_REG0, 26),
+	SUNXI_CCU_GATE(A31_CLK_AHB1_EHCI1, "ahb1-ehci1", "ahb1",
+	    AHB1_GATING_REG0, 27),
+	SUNXI_CCU_GATE(A31_CLK_AHB1_OHCI0, "ahb1-ohci0", "ahb1",
+	    AHB1_GATING_REG0, 29),
+	SUNXI_CCU_GATE(A31_CLK_AHB1_OHCI1, "ahb1-ohci1", "ahb1",
+	    AHB1_GATING_REG0, 30),
+	SUNXI_CCU_GATE(A31_CLK_AHB1_OHCI2, "ahb1-ohci2", "ahb1",
+	    AHB1_GATING_REG0, 31),
+
+	SUNXI_CCU_GATE(A31_CLK_APB2_I2C0, "apb2-i2c0", "apb2",
+	    APB2_GATING_REG, 0),
+	SUNXI_CCU_GATE(A31_CLK_APB2_I2C1, "apb2-i2c1", "apb2",
+	    APB2_GATING_REG, 1),
+	SUNXI_CCU_GATE(A31_CLK_APB2_I2C2, "apb2-i2c2", "apb2",
+	    APB2_GATING_REG, 2),
+	SUNXI_CCU_GATE(A31_CLK_APB2_I2C3, "apb2-i2c3", "apb2",
+	    APB2_GATING_REG, 3),
+	SUNXI_CCU_GATE(A31_CLK_APB2_UART0, "apb2-uart0", "apb2",
+	    APB2_GATING_REG, 16),
+	SUNXI_CCU_GATE(A31_CLK_APB2_UART1, "apb2-uart1", "apb2",
+	    APB2_GATING_REG, 17),
+	SUNXI_CCU_GATE(A31_CLK_APB2_UART2, "apb2-uart2", "apb2",
+	    APB2_GATING_REG, 18),
+	SUNXI_CCU_GATE(A31_CLK_APB2_UART3, "apb2-uart3", "apb2",
+	    APB2_GATING_REG, 19),
+	SUNXI_CCU_GATE(A31_CLK_APB2_UART4, "apb2-uart4", "apb2",
+	    APB2_GATING_REG, 20),
+	SUNXI_CCU_GATE(A31_CLK_APB2_UART5, "apb2-uart5", "apb2",
+	    APB2_GATING_REG, 21),
+
+	SUNXI_CCU_GATE(A31_CLK_USB_PHY0, "usb-phy0", "hosc",
+	    USBPHY_CFG_REG, 8),
+	SUNXI_CCU_GATE(A31_CLK_USB_PHY1, "usb-phy1", "hosc",
+	    USBPHY_CFG_REG, 9),
+	SUNXI_CCU_GATE(A31_CLK_USB_PHY2, "usb-phy2", "hosc",
+	    USBPHY_CFG_REG, 10),
+	SUNXI_CCU_GATE(A31_CLK_USB_OHCI0, "usb-ohci0", "hosc",
+	    USBPHY_CFG_REG, 16),
+	SUNXI_CCU_GATE(A31_CLK_USB_OHCI1, "usb-ohci1", "hosc",
+	    USBPHY_CFG_REG, 17),
+	SUNXI_CCU_GATE(A31_CLK_USB_OHCI2, "usb-ohci2", "hosc",
+	    USBPHY_CFG_REG, 18),
+};
+
+static int
+sun6i_a31_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
+sun6i_a31_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 = sun6i_a31_ccu_resets;
+	sc->sc_nresets = __arraycount(sun6i_a31_ccu_resets);
+
+	sc->sc_clks = sun6i_a31_ccu_clks;
+	sc->sc_nclks = __arraycount(sun6i_a31_ccu_clks);
+
+	if (sunxi_ccu_attach(sc) != 0)
+		return;
+
+	aprint_naive("\n");
+	aprint_normal(": A31 CCU\n");
+
+	sunxi_ccu_print(sc);
+}
Index: src/sys/arch/arm/sunxi/sun6i_a31_ccu.h
diff -u /dev/null src/sys/arch/arm/sunxi/sun6i_a31_ccu.h:1.1
--- /dev/null	Sun Jul  2 00:14:09 2017
+++ src/sys/arch/arm/sunxi/sun6i_a31_ccu.h	Sun Jul  2 00:14:09 2017
@@ -0,0 +1,250 @@
+/* $NetBSD: sun6i_a31_ccu.h,v 1.1 2017/07/02 00:14:09 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2017 Emmanuel Vadot <m...@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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$
+ */
+
+#ifndef __CCU_A31_H__
+#define __CCU_A31_H__
+
+#define	A31_RST_USB_PHY0		0
+#define	A31_RST_USB_PHY1		1
+#define	A31_RST_USB_PHY2		2
+#define	A31_RST_AHB1_MIPI_DSI		3
+#define	A31_RST_AHB1_SS			4
+#define	A31_RST_AHB1_DMA		5
+#define	A31_RST_AHB1_MMC0		6
+#define	A31_RST_AHB1_MMC1		7
+#define	A31_RST_AHB1_MMC2		8
+#define	A31_RST_AHB1_MMC3		9
+#define	A31_RST_AHB1_NAND1		10
+#define	A31_RST_AHB1_NAND0		11
+#define	A31_RST_AHB1_SDRAM		12
+#define	A31_RST_AHB1_EMAC		13
+#define	A31_RST_AHB1_TS			14
+#define	A31_RST_AHB1_HSTIMER		15
+#define	A31_RST_AHB1_SPI0		16
+#define	A31_RST_AHB1_SPI1		17
+#define	A31_RST_AHB1_SPI2		18
+#define	A31_RST_AHB1_SPI3		19
+#define	A31_RST_AHB1_OTG		20
+#define	A31_RST_AHB1_EHCI0		21
+#define	A31_RST_AHB1_EHCI1		22
+#define	A31_RST_AHB1_OHCI0		23
+#define	A31_RST_AHB1_OHCI1		24
+#define	A31_RST_AHB1_OHCI2		25
+#define	A31_RST_AHB1_VE			26
+#define	A31_RST_AHB1_LCD0		27
+#define	A31_RST_AHB1_LCD1		28
+#define	A31_RST_AHB1_CSI		29
+#define	A31_RST_AHB1_HDMI		30
+#define	A31_RST_AHB1_BE0		31
+#define	A31_RST_AHB1_BE1		32
+#define	A31_RST_AHB1_FE0		33
+#define	A31_RST_AHB1_FE1		34
+#define	A31_RST_AHB1_MP			35
+#define	A31_RST_AHB1_GPU		36
+#define	A31_RST_AHB1_DEU0		37
+#define	A31_RST_AHB1_DEU1		38
+#define	A31_RST_AHB1_DRC0		39
+#define	A31_RST_AHB1_DRC1		40
+#define	A31_RST_AHB1_LVDS		41
+#define	A31_RST_APB1_CODEC		42
+#define	A31_RST_APB1_SPDIF		43
+#define	A31_RST_APB1_DIGITAL_MIC	44
+#define	A31_RST_APB1_DAUDIO0		45
+#define	A31_RST_APB1_DAUDIO1		46
+#define	A31_RST_APB2_I2C0		47
+#define	A31_RST_APB2_I2C1		48
+#define	A31_RST_APB2_I2C2		49
+#define	A31_RST_APB2_I2C3		50
+#define	A31_RST_APB2_UART0		51
+#define	A31_RST_APB2_UART1		52
+#define	A31_RST_APB2_UART2		53
+#define	A31_RST_APB2_UART3		54
+#define	A31_RST_APB2_UART4		55
+#define	A31_RST_APB2_UART5		56
+
+#define	A31_CLK_PLL_CPU			0
+#define	A31_CLK_PLL_AUDIO_BASE		1
+#define	A31_CLK_PLL_AUDIO		2
+#define	A31_CLK_PLL_AUDIO_2X		3
+#define	A31_CLK_PLL_AUDIO_4X		4
+#define	A31_CLK_PLL_AUDIO_8X		5
+#define	A31_CLK_PLL_VIDEO0		6
+#define	A31_CLK_PLL_VIDEO0_2X		7
+#define	A31_CLK_PLL_VE			8
+#define	A31_CLK_PLL_DDR			9
+#define	A31_CLK_PLL_PERIPH		10
+#define	A31_CLK_PLL_PERIPH_2X		11
+#define	A31_CLK_PLL_VIDEO1		12
+#define	A31_CLK_PLL_VIDEO1_2X		13
+#define	A31_CLK_PLL_GPU			14
+#define	A31_CLK_PLL_MIPI		15
+#define	A31_CLK_PLL9			16
+#define	A31_CLK_PLL10			17
+#define	A31_CLK_CPU			18
+#define	A31_CLK_AXI			19
+#define	A31_CLK_AHB1			20
+#define	A31_CLK_APB1			21
+#define	A31_CLK_APB2			22
+#define	A31_CLK_AHB1_MIPIDSI		23
+#define	A31_CLK_AHB1_SS			24
+#define	A31_CLK_AHB1_DMA		25
+#define	A31_CLK_AHB1_MMC0		26
+#define	A31_CLK_AHB1_MMC1		27
+#define	A31_CLK_AHB1_MMC2		28
+#define	A31_CLK_AHB1_MMC3		29
+#define	A31_CLK_AHB1_NAND1		30
+#define	A31_CLK_AHB1_NAND0		31
+#define	A31_CLK_AHB1_SDRAM		32
+#define	A31_CLK_AHB1_EMAC		33
+#define	A31_CLK_AHB1_TS			34
+#define	A31_CLK_AHB1_HSTIMER		35
+#define	A31_CLK_AHB1_SPI0		36
+#define	A31_CLK_AHB1_SPI1		37
+#define	A31_CLK_AHB1_SPI2		38
+#define	A31_CLK_AHB1_SPI3		39
+#define	A31_CLK_AHB1_OTG		40
+#define	A31_CLK_AHB1_EHCI0		41
+#define	A31_CLK_AHB1_EHCI1		42
+#define	A31_CLK_AHB1_OHCI0		43
+#define	A31_CLK_AHB1_OHCI1		44
+#define	A31_CLK_AHB1_OHCI2		45
+#define	A31_CLK_AHB1_VE			46
+#define	A31_CLK_AHB1_LCD0		47
+#define	A31_CLK_AHB1_LCD1		48
+#define	A31_CLK_AHB1_CSI		49
+#define	A31_CLK_AHB1_HDMI		50
+#define	A31_CLK_AHB1_BE0		51
+#define	A31_CLK_AHB1_BE1		52
+#define	A31_CLK_AHB1_FE0		53
+#define	A31_CLK_AHB1_FE1		54
+#define	A31_CLK_AHB1_MP			55
+#define	A31_CLK_AHB1_GPU		56
+#define	A31_CLK_AHB1_DEU0		57
+#define	A31_CLK_AHB1_DEU1		58
+#define	A31_CLK_AHB1_DRC0		59
+#define	A31_CLK_AHB1_DRC1		60
+#define	A31_CLK_APB1_CODEC		61
+#define	A31_CLK_APB1_SPDIF		62
+#define	A31_CLK_APB1_DIGITAL_MIC	63
+#define	A31_CLK_APB1_PIO		64
+#define	A31_CLK_APB1_DAUDIO0		65
+#define	A31_CLK_APB1_DAUDIO1		66
+#define	A31_CLK_APB2_I2C0		67
+#define	A31_CLK_APB2_I2C1		68
+#define	A31_CLK_APB2_I2C2		69
+#define	A31_CLK_APB2_I2C3		70
+#define	A31_CLK_APB2_UART0		71
+#define	A31_CLK_APB2_UART1		72
+#define	A31_CLK_APB2_UART2		73
+#define	A31_CLK_APB2_UART3		74
+#define	A31_CLK_APB2_UART4		75
+#define	A31_CLK_APB2_UART5		76
+#define	A31_CLK_NAND0			77
+#define	A31_CLK_NAND1			78
+#define	A31_CLK_MMC0			79
+#define	A31_CLK_MMC0_SAMPLE		80
+#define	A31_CLK_MMC0_OUTPUT		81
+#define	A31_CLK_MMC1			82
+#define	A31_CLK_MMC1_SAMPLE		83
+#define	A31_CLK_MMC1_OUTPUT		84
+#define	A31_CLK_MMC2			85
+#define	A31_CLK_MMC2_SAMPLE		86
+#define	A31_CLK_MMC2_OUTPUT		87
+#define	A31_CLK_MMC3			88
+#define	A31_CLK_MMC3_SAMPLE		89
+#define	A31_CLK_MMC3_OUTPUT		90
+#define	A31_CLK_TS			91
+#define	A31_CLK_SS			92
+#define	A31_CLK_SPI0			93
+#define	A31_CLK_SPI1			94
+#define	A31_CLK_SPI2			95
+#define	A31_CLK_SPI3			96
+#define	A31_CLK_DAUDIO0			97
+#define	A31_CLK_DAUDIO1			98
+#define	A31_CLK_SPDIF			99
+#define	A31_CLK_USB_PHY0		100
+#define	A31_CLK_USB_PHY1		101
+#define	A31_CLK_USB_PHY2		102
+#define	A31_CLK_USB_OHCI0		103
+#define	A31_CLK_USB_OHCI1		104
+#define	A31_CLK_USB_OHCI2		105
+#define	A31_CLK_MDFS			107
+#define	A31_CLK_SDRAM0			108
+#define	A31_CLK_SDRAM1			109
+#define	A31_CLK_DRAM_VE			110
+#define	A31_CLK_DRAM_CSI_ISP		111
+#define	A31_CLK_DRAM_TS			112
+#define	A31_CLK_DRAM_DRC0		113
+#define	A31_CLK_DRAM_DRC1		114
+#define	A31_CLK_DRAM_DEU0		115
+#define	A31_CLK_DRAM_DEU1		116
+#define	A31_CLK_DRAM_FE0		117
+#define	A31_CLK_DRAM_FE1		118
+#define	A31_CLK_DRAM_BE0		119
+#define	A31_CLK_DRAM_BE1		120
+#define	A31_CLK_DRAM_MP			121
+#define	A31_CLK_BE0			122
+#define	A31_CLK_BE1			123
+#define	A31_CLK_FE0			124
+#define	A31_CLK_FE1			125
+#define	A31_CLK_MP			126
+#define	A31_CLK_LCD0_CH0		127
+#define	A31_CLK_LCD1_CH0		128
+#define	A31_CLK_LCD0_CH1		129
+#define	A31_CLK_LCD1_CH1		130
+#define	A31_CLK_CSI0_SCLK		131
+#define	A31_CLK_CSI0_MCLK		132
+#define	A31_CLK_CSI1_MCLK		133
+#define	A31_CLK_VE			134
+#define	A31_CLK_CODEC			135
+#define	A31_CLK_AVS			136
+#define	A31_CLK_DIGITAL_MIC		137
+#define	A31_CLK_HDMI			138
+#define	A31_CLK_HDMI_DDC		139
+#define	A31_CLK_PS			140
+#define	A31_CLK_MBUS0			141
+#define	A31_CLK_MBUS1			142
+#define	A31_CLK_MIPI_DSI		143
+#define	A31_CLK_MIPI_DSI_DPHY		144
+#define	A31_CLK_MIPI_CSI_DPHY		145
+#define	A31_CLK_IEP_DRC0		146
+#define	A31_CLK_IEP_DRC1		147
+#define	A31_CLK_IEP_DEU0		148
+#define	A31_CLK_IEP_DEU1		149
+#define	A31_CLK_GPU_CORE		150
+#define	A31_CLK_GPU_MEMORY		151
+#define	A31_CLK_GPU_HYD			152
+#define	A31_CLK_ATS			153
+#define	A31_CLK_TRACE			154
+#define	A31_CLK_OUT_A			155
+#define	A31_CLK_OUT_B			156
+#define	A31_CLK_OUT_C			157
+
+#endif	/* __CCU_A31		H__ */
Index: src/sys/arch/arm/sunxi/sunxi_ccu_div.c
diff -u /dev/null src/sys/arch/arm/sunxi/sunxi_ccu_div.c:1.1
--- /dev/null	Sun Jul  2 00:14:09 2017
+++ src/sys/arch/arm/sunxi/sunxi_ccu_div.c	Sun Jul  2 00:14:09 2017
@@ -0,0 +1,124 @@
+/* $NetBSD: sunxi_ccu_div.c,v 1.1 2017/07/02 00:14:09 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_ccu_div.c,v 1.1 2017/07/02 00:14:09 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+
+#include <dev/clk/clk_backend.h>
+
+#include <arm/sunxi/sunxi_ccu.h>
+
+u_int
+sunxi_ccu_div_get_rate(struct sunxi_ccu_softc *sc,
+    struct sunxi_ccu_clk *clk)
+{
+	struct sunxi_ccu_div *div = &clk->u.div;
+	struct clk *clkp, *clkp_parent;
+	u_int rate, ratio;
+	uint32_t val;
+
+	KASSERT(clk->type == SUNXI_CCU_DIV);
+
+	clkp = &clk->base;
+	clkp_parent = clk_get_parent(clkp);
+	if (clkp_parent == NULL)
+		return 0;
+
+	rate = clk_get_rate(clkp_parent);
+	if (rate == 0)
+		return 0;
+
+	val = CCU_READ(sc, div->reg);
+	ratio = __SHIFTOUT(val, div->div);
+	if ((div->flags & SUNXI_CCU_DIV_ZERO_IS_ONE) != 0 && ratio == 0)
+		ratio = 1;
+	if (div->flags & SUNXI_CCU_DIV_POWER_OF_TWO)
+		ratio = 1 << ratio;
+	else
+		ratio++;
+
+	return rate / ratio;
+}
+
+int
+sunxi_ccu_div_set_rate(struct sunxi_ccu_softc *sc,
+    struct sunxi_ccu_clk *clk, u_int new_rate)
+{
+	return EINVAL;
+}
+
+int
+sunxi_ccu_div_set_parent(struct sunxi_ccu_softc *sc,
+    struct sunxi_ccu_clk *clk, const char *name)
+{
+	struct sunxi_ccu_div *div = &clk->u.div;
+	uint32_t val;
+	u_int index;
+
+	KASSERT(clk->type == SUNXI_CCU_DIV);
+
+	if (div->sel == 0)
+		return ENODEV;
+
+	for (index = 0; index < div->nparents; index++) {
+		if (div->parents[index] != NULL &&
+		    strcmp(div->parents[index], name) == 0)
+			break;
+	}
+	if (index == div->nparents)
+		return EINVAL;
+
+	val = CCU_READ(sc, div->reg);
+	val &= ~div->sel;
+	val |= __SHIFTIN(index, div->sel);
+	CCU_WRITE(sc, div->reg, val);
+
+	return 0;
+}
+
+const char *
+sunxi_ccu_div_get_parent(struct sunxi_ccu_softc *sc,
+    struct sunxi_ccu_clk *clk)
+{
+	struct sunxi_ccu_div *div = &clk->u.div;
+	u_int index;
+	uint32_t val;
+
+	KASSERT(clk->type == SUNXI_CCU_DIV);
+
+	if (div->sel == 0)
+		return div->parents[0];
+
+	val = CCU_READ(sc, div->reg);
+	index = __SHIFTOUT(val, div->sel);
+
+	return div->parents[index];
+}

Reply via email to