diff --git a/sys/arm/allwinner/clk/aw_cpuclk.c b/sys/arm/allwinner/clk/aw_cpuclk.c index d6ae4584039b..86d071efeba4 100644 --- a/sys/arm/allwinner/clk/aw_cpuclk.c +++ b/sys/arm/allwinner/clk/aw_cpuclk.c @@ -47,8 +47,42 @@ __FBSDID("$FreeBSD$"); #include -#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) { diff --git a/sys/arm/allwinner/clk/aw_pll.c b/sys/arm/allwinner/clk/aw_pll.c index 8936c913f371..7a17f0f1ceaf 100644 --- a/sys/arm/allwinner/clk/aw_pll.c +++ b/sys/arm/allwinner/clk/aw_pll.c @@ -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_t reg, struct clknode_init_def *def) 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_data[] = { { "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 }, diff --git a/sys/boot/fdt/dts/arm/a83t.dtsi b/sys/boot/fdt/dts/arm/a83t.dtsi index 1ff4d182c755..52a3b3fc641a 100644 --- a/sys/boot/fdt/dts/arm/a83t.dtsi +++ b/sys/boot/fdt/dts/arm/a83t.dtsi @@ -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"; diff --git a/sys/boot/fdt/dts/arm/sinovoip-bpi-m3.dts b/sys/boot/fdt/dts/arm/sinovoip-bpi-m3.dts index 5d4d0666b577..b88ef52ff22d 100644 --- a/sys/boot/fdt/dts/arm/sinovoip-bpi-m3.dts +++ b/sys/boot/fdt/dts/arm/sinovoip-bpi-m3.dts @@ -29,6 +29,32 @@ #include "sun8i-a83t-sinovoip-bpi-m3.dts" #include "a83t.dtsi" +/ { + cpus { + cpu@0 { + cpu-supply = <®_dcdc2>; + operating-points = < + /* kHz uV */ + 1200000 840000 + 1008000 840000 + 648000 840000 + 408000 840000 + >; + }; + + cpu@100 { + cpu-supply = <®_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"; + }; + }; }; };