Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 7 Sep 2016 01:10:17 +0000 (UTC)
From:      Jared McNeill <jmcneill@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r305512 - in head/sys: arm/allwinner/clk boot/fdt/dts/arm
Message-ID:  <201609070110.u871AHoH017384@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jmcneill
Date: Wed Sep  7 01:10:16 2016
New Revision: 305512
URL: https://svnweb.freebsd.org/changeset/base/305512

Log:
  Add support for Allwinner A83T CPU frequency scaling.

Modified:
  head/sys/arm/allwinner/clk/aw_cpuclk.c
  head/sys/arm/allwinner/clk/aw_pll.c
  head/sys/boot/fdt/dts/arm/a83t.dtsi
  head/sys/boot/fdt/dts/arm/sinovoip-bpi-m3.dts

Modified: head/sys/arm/allwinner/clk/aw_cpuclk.c
==============================================================================
--- head/sys/arm/allwinner/clk/aw_cpuclk.c	Wed Sep  7 01:09:25 2016	(r305511)
+++ head/sys/arm/allwinner/clk/aw_cpuclk.c	Wed Sep  7 01:10:16 2016	(r305512)
@@ -47,8 +47,42 @@ __FBSDID("$FreeBSD$");
 
 #include <dev/extres/clk/clk_mux.h>
 
-#define	CPU_CLK_SRC_SEL_WIDTH	2
-#define	CPU_CLK_SRC_SEL_SHIFT	16
+#define	A10_CPU_CLK_SRC_SEL_WIDTH	2
+#define	A10_CPU_CLK_SRC_SEL_SHIFT	16
+
+#define	A83T_Cx_CLK_SRC_SEL_WIDTH	1
+#define	A83T_C0_CLK_SRC_SEL_SHIFT	12
+#define	A83T_C1_CLK_SRC_SEL_SHIFT	28
+
+struct aw_cpuclk_config {
+	u_int		width;
+	u_int		shift;
+};
+
+static struct aw_cpuclk_config a10_config = {
+	.width = A10_CPU_CLK_SRC_SEL_WIDTH,
+	.shift = A10_CPU_CLK_SRC_SEL_SHIFT,
+};
+
+static struct aw_cpuclk_config a83t_c0_config = {
+	.width = A83T_Cx_CLK_SRC_SEL_WIDTH,
+	.shift = A83T_C0_CLK_SRC_SEL_SHIFT,
+};
+
+static struct aw_cpuclk_config a83t_c1_config = {
+	.width = A83T_Cx_CLK_SRC_SEL_WIDTH,
+	.shift = A83T_C1_CLK_SRC_SEL_SHIFT,
+};
+
+static struct ofw_compat_data compat_data[] = {
+	{ "allwinner,sun4i-a10-cpu-clk",	(uintptr_t)&a10_config },
+	{ "allwinner,sun8i-a83t-c0cpu-clk",	(uintptr_t)&a83t_c0_config },
+	{ "allwinner,sun8i-a83t-c1cpu-clk",	(uintptr_t)&a83t_c1_config },
+	{ NULL,					(uintptr_t)NULL }
+};
+
+#define	CPUCLK_CONF(d)		\
+	(void *)ofw_bus_search_compatible((d), compat_data)->ocd_data
 
 static int
 aw_cpuclk_probe(device_t dev)
@@ -56,7 +90,7 @@ aw_cpuclk_probe(device_t dev)
 	if (!ofw_bus_status_okay(dev))
 		return (ENXIO);
 
-	if (!ofw_bus_is_compatible(dev, "allwinner,sun4i-a10-cpu-clk"))
+	if (CPUCLK_CONF(dev) == NULL)
 		return (ENXIO);
 
 	device_set_desc(dev, "Allwinner CPU Clock");
@@ -68,6 +102,7 @@ aw_cpuclk_attach(device_t dev)
 {
 	struct clk_mux_def def;
 	struct clkdom *clkdom;
+	struct aw_cpuclk_config *conf;
 	bus_addr_t paddr;
 	bus_size_t psize;
 	phandle_t node;
@@ -75,6 +110,7 @@ aw_cpuclk_attach(device_t dev)
 	clk_t clk;
 
 	node = ofw_bus_get_node(dev);
+	conf = CPUCLK_CONF(dev);
 
 	if (ofw_reg_to_paddr(node, 0, &paddr, &psize, NULL) != 0) {
 		device_printf(dev, "cannot parse 'reg' property\n");
@@ -105,8 +141,8 @@ aw_cpuclk_attach(device_t dev)
 	}
 	def.clkdef.parent_cnt = ncells;
 	def.offset = paddr;
-	def.shift = CPU_CLK_SRC_SEL_SHIFT;
-	def.width = CPU_CLK_SRC_SEL_WIDTH;
+	def.shift = conf->shift;
+	def.width = conf->width;
 
 	error = clk_parse_ofw_clk_name(dev, node, &def.clkdef.name);
 	if (error != 0) {

Modified: head/sys/arm/allwinner/clk/aw_pll.c
==============================================================================
--- head/sys/arm/allwinner/clk/aw_pll.c	Wed Sep  7 01:09:25 2016	(r305511)
+++ head/sys/arm/allwinner/clk/aw_pll.c	Wed Sep  7 01:10:16 2016	(r305512)
@@ -157,6 +157,17 @@ __FBSDID("$FreeBSD$");
 #define	A80_PLL4_FACTOR_N		(0xff << 8)
 #define	A80_PLL4_FACTOR_N_SHIFT		8
 
+#define	A83T_PLLCPUX_LOCK_TIME		(0x7 << 24)
+#define	A83T_PLLCPUX_LOCK_TIME_SHIFT	24
+#define	A83T_PLLCPUX_CLOCK_OUTPUT_DIS	(1 << 20)
+#define	A83T_PLLCPUX_OUT_EXT_DIVP	(1 << 16)
+#define	A83T_PLLCPUX_FACTOR_N		(0xff << 8)
+#define	A83T_PLLCPUX_FACTOR_N_SHIFT	8
+#define	A83T_PLLCPUX_FACTOR_N_MIN	12
+#define	A83T_PLLCPUX_FACTOR_N_MAX	125
+#define	A83T_PLLCPUX_POSTDIV_M		(0x3 << 0)
+#define	A83T_PLLCPUX_POSTDIV_M_SHIFT	0
+
 #define	CLKID_A10_PLL3_1X		0
 #define	CLKID_A10_PLL3_2X		1
 
@@ -202,6 +213,7 @@ enum aw_pll_type {
 	AWPLL_A31_PLL6,
 	AWPLL_A64_PLLHSIC,
 	AWPLL_A80_PLL4,
+	AWPLL_A83T_PLLCPUX,
 	AWPLL_H3_PLL1,
 };
 
@@ -824,6 +836,46 @@ a64_pllhsic_init(device_t dev, bus_addr_
 	return (0);
 }
 
+static int
+a83t_pllcpux_recalc(struct aw_pll_sc *sc, uint64_t *freq)
+{
+	uint32_t val, n, p;
+
+	DEVICE_LOCK(sc);
+	PLL_READ(sc, &val);
+	DEVICE_UNLOCK(sc);
+
+	n = (val & A83T_PLLCPUX_FACTOR_N) >> A83T_PLLCPUX_FACTOR_N_SHIFT;
+	p = (val & A83T_PLLCPUX_OUT_EXT_DIVP) ? 4 : 1;
+
+	*freq = (*freq * n) / p;
+
+	return (0);
+}
+
+static int
+a83t_pllcpux_set_freq(struct aw_pll_sc *sc, uint64_t fin, uint64_t *fout,
+    int flags)
+{
+	uint32_t val;
+	u_int n;
+
+	n = *fout / fin;
+
+	if (n < A83T_PLLCPUX_FACTOR_N_MIN || n > A83T_PLLCPUX_FACTOR_N_MAX)
+		return (EINVAL);
+
+	DEVICE_LOCK(sc);
+	PLL_READ(sc, &val);
+	val &= ~A83T_PLLCPUX_FACTOR_N;
+	val |= (n << A83T_PLLCPUX_FACTOR_N_SHIFT);
+	val &= ~A83T_PLLCPUX_CLOCK_OUTPUT_DIS;
+	PLL_WRITE(sc, val);
+	DEVICE_UNLOCK(sc);
+
+	return (0);
+}
+
 #define	PLL(_type, _recalc, _set_freq, _init)	\
 	[(_type)] = {				\
 		.recalc = (_recalc),		\
@@ -842,6 +894,7 @@ static struct aw_pll_funcs aw_pll_func[]
 	PLL(AWPLL_A31_PLL1, a31_pll1_recalc, NULL, NULL),
 	PLL(AWPLL_A31_PLL6, a31_pll6_recalc, NULL, a31_pll6_init),
 	PLL(AWPLL_A80_PLL4, a80_pll4_recalc, NULL, NULL),
+	PLL(AWPLL_A83T_PLLCPUX, a83t_pllcpux_recalc, a83t_pllcpux_set_freq, NULL),
 	PLL(AWPLL_A64_PLLHSIC, a64_pllhsic_recalc, NULL, a64_pllhsic_init),
 	PLL(AWPLL_H3_PLL1, a23_pll1_recalc, h3_pll1_set_freq, NULL),
 };
@@ -856,6 +909,7 @@ static struct ofw_compat_data compat_dat
 	{ "allwinner,sun6i-a31-pll1-clk",	AWPLL_A31_PLL1 },
 	{ "allwinner,sun6i-a31-pll6-clk",	AWPLL_A31_PLL6 },
 	{ "allwinner,sun8i-a23-pll1-clk",	AWPLL_A23_PLL1 },
+	{ "allwinner,sun8i-a83t-pllcpux-clk",	AWPLL_A83T_PLLCPUX },
 	{ "allwinner,sun8i-h3-pll1-clk",	AWPLL_H3_PLL1 },
 	{ "allwinner,sun9i-a80-pll4-clk",	AWPLL_A80_PLL4 },
 	{ "allwinner,sun50i-a64-pllhsic-clk",	AWPLL_A64_PLLHSIC },

Modified: head/sys/boot/fdt/dts/arm/a83t.dtsi
==============================================================================
--- head/sys/boot/fdt/dts/arm/a83t.dtsi	Wed Sep  7 01:09:25 2016	(r305511)
+++ head/sys/boot/fdt/dts/arm/a83t.dtsi	Wed Sep  7 01:10:16 2016	(r305512)
@@ -27,6 +27,18 @@
  */
 
 / {
+	cpus {
+		cpu@0 {
+			clocks = <&c0_cpux_clk>;
+			clock-latency = <2000000>;
+		};
+
+		cpu@100 {
+			clocks = <&c1_cpux_clk>;
+			clock-latency = <2000000>;
+		};
+	};
+
 	pmu {
 		compatible = "arm,cortex-a7-pmu", "arm,cortex-a15-pmu";
 
@@ -38,6 +50,38 @@
 	};
 
 	clocks {
+		pll_c0cpux: clk@01c20000 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun8i-a83t-pllcpux-clk";
+			reg = <0x01c20000 0x4>;
+			clocks = <&osc24M>;
+			clock-output-names = "pll_c0cpux";
+		};
+
+		pll_c1cpux: clk@01c20004 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun8i-a83t-pllcpux-clk";
+			reg = <0x01c20004 0x4>;
+			clocks = <&osc24M>;
+			clock-output-names = "pll_c1cpux";
+		};
+
+		c0_cpux_clk: c0clk@01c20050 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun8i-a83t-c0cpu-clk";
+			reg = <0x01c20050 0x4>;
+			clocks = <&osc24M>, <&pll_c0cpux>;
+			clock-output-names = "c0_cpux";
+		};
+
+		c1_cpux_clk: c1clk@01c20050 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun8i-a83t-c1cpu-clk";
+			reg = <0x01c20050 0x4>;
+			clocks = <&osc24M>, <&pll_c1cpux>;
+			clock-output-names = "c1_cpux";
+		};
+
 		/* cpus_clk compatible in gnu dt is incorrect */
 		cpus_clk: clk@01f01400 {
                         compatible = "allwinner,sun8i-a83t-cpus-clk";

Modified: head/sys/boot/fdt/dts/arm/sinovoip-bpi-m3.dts
==============================================================================
--- head/sys/boot/fdt/dts/arm/sinovoip-bpi-m3.dts	Wed Sep  7 01:09:25 2016	(r305511)
+++ head/sys/boot/fdt/dts/arm/sinovoip-bpi-m3.dts	Wed Sep  7 01:10:16 2016	(r305512)
@@ -29,6 +29,32 @@
 #include "sun8i-a83t-sinovoip-bpi-m3.dts"
 #include "a83t.dtsi"
 
+/ {
+	cpus {
+		cpu@0 {
+			cpu-supply = <&reg_dcdc2>;
+			operating-points = <
+				/* kHz    uV */
+				1200000	840000
+				1008000	840000
+				648000	840000
+				408000	840000
+				>;
+		};
+
+		cpu@100 {
+			cpu-supply = <&reg_dcdc3>;
+			operating-points = <
+				/* kHz    uV */
+				1200000	840000
+				1008000	840000
+				648000	840000
+				408000	840000
+				>;
+		};
+	};
+};
+
 &ehci0 {
 	status = "okay";
 };
@@ -115,6 +141,16 @@
 		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
 		gpio-controller;
 		#gpio-cells = <1>;
+
+		regulators {
+			reg_dcdc2: dcdc2 {
+				regulator-name = "dcdc2";
+			};
+
+			reg_dcdc3: dcdc3 {
+				regulator-name = "dcdc3";
+			};
+		};
 	};
 };
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201609070110.u871AHoH017384>