Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F111101835
D32293.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
13 KB
Referenced Files
None
Subscribers
None
D32293.diff
View Options
diff --git a/sys/arm/mv/clk/a37x0_tbg.c b/sys/arm/mv/clk/a37x0_tbg.c
new file mode 100644
--- /dev/null
+++ b/sys/arm/mv/clk/a37x0_tbg.c
@@ -0,0 +1,226 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2021 Semihalf.
+ *
+ * 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 AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <machine/bus.h>
+
+#include <dev/extres/clk/clk.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "clkdev_if.h"
+
+#include "a37x0_tbg_pll.h"
+
+#define NUM_TBG 4
+
+#define TBG_CTRL0 0x4
+#define TBG_CTRL1 0x8
+#define TBG_CTRL7 0x20
+#define TBG_CTRL8 0x30
+
+#define TBG_MASK 0x1FF
+
+#define TBG_A_REFDIV 0
+#define TBG_B_REFDIV 16
+
+#define TBG_A_FBDIV 2
+#define TBG_B_FBDIV 18
+
+#define TBG_A_VCODIV_SEL 0
+#define TBG_B_VCODIV_SEL 16
+
+#define TBG_A_VCODIV_DIFF 1
+#define TBG_B_VCODIV_DIFF 17
+
+struct a37x0_tbg_softc {
+ device_t dev;
+ struct clkdom *clkdom;
+ struct resource *res;
+};
+
+static struct resource_spec a37x0_tbg_clk_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+struct a37x0_tbg_def {
+ char *name;
+ uint32_t refdiv_shift;
+ uint32_t fbdiv_shift;
+ uint32_t vcodiv_offset;
+ uint32_t vcodiv_shift;
+ uint32_t tbg_bypass_en;
+};
+
+static const struct a37x0_tbg_def tbg[NUM_TBG] = {
+ {"TBG-A-P", TBG_A_REFDIV, TBG_A_FBDIV, TBG_CTRL8, TBG_A_VCODIV_DIFF, 9},
+ {"TBG-B-P", TBG_B_REFDIV, TBG_B_FBDIV, TBG_CTRL8,
+ TBG_B_VCODIV_DIFF, 25},
+ {"TBG-A-S", TBG_A_REFDIV, TBG_A_FBDIV, TBG_CTRL1, TBG_A_VCODIV_SEL, 9},
+ {"TBG-B-S", TBG_B_REFDIV, TBG_B_FBDIV, TBG_CTRL1, TBG_B_VCODIV_SEL, 25}
+};
+
+static devclass_t a37x0_tbg_devclass;
+
+static int a37x0_tbg_read_4(device_t, bus_addr_t, uint32_t *);
+static int a37x0_tbg_attach(device_t);
+static int a37x0_tbg_detach(device_t);
+static int a37x0_tbg_probe(device_t);
+
+static device_method_t a37x0_tbg_methods [] = {
+ DEVMETHOD(device_attach, a37x0_tbg_attach),
+ DEVMETHOD(device_detach, a37x0_tbg_detach),
+ DEVMETHOD(device_probe, a37x0_tbg_probe),
+
+ DEVMETHOD(clkdev_read_4, a37x0_tbg_read_4),
+
+ DEVMETHOD_END
+};
+
+static driver_t a37x0_tbg_driver = {
+ "a37x0_tbg",
+ a37x0_tbg_methods,
+ sizeof(struct a37x0_tbg_softc)
+};
+
+EARLY_DRIVER_MODULE(a37x0_tbg, simplebus, a37x0_tbg_driver,
+ a37x0_tbg_devclass, 0, 0, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE);
+
+static int
+a37x0_tbg_read_4(device_t dev, bus_addr_t offset, uint32_t *val)
+{
+ struct a37x0_tbg_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ *val = bus_read_4(sc->res, offset);
+
+ return (0);
+}
+
+static int
+a37x0_tbg_attach(device_t dev)
+{
+ struct a37x0_tbg_pll_clk_def def;
+ struct a37x0_tbg_softc *sc;
+ const char *clkname;
+ int error, i;
+ phandle_t node;
+ clk_t clock;
+
+ sc = device_get_softc(dev);
+ node = ofw_bus_get_node(dev);
+ sc->dev = dev;
+
+ if (bus_alloc_resources(dev, a37x0_tbg_clk_spec, &sc->res) != 0) {
+ device_printf(dev, "Cannot allocate resources\n");
+ return (ENXIO);
+ }
+
+ sc->clkdom = clkdom_create(dev);
+ if (sc->clkdom == NULL) {
+ device_printf(dev, "Cannot create clock domain.\n");
+ return (ENXIO);
+ }
+
+ error = clk_get_by_ofw_index(dev, node, 0, &clock);
+ if (error != 0) {
+ device_printf(dev, "Cannot find clock parent\n");
+ bus_release_resources(dev, a37x0_tbg_clk_spec, &sc->res);
+ return (error);
+ }
+
+ clkname = clk_get_name(clock);
+
+ for (i = 0; i < NUM_TBG; i++) {
+ def.clkdef.parent_names = &clkname;
+ def.clkdef.parent_cnt = 1;
+ def.clkdef.id = i;
+ def.clkdef.name = tbg[i].name;
+
+ def.vcodiv.offset = tbg[i].vcodiv_offset;
+ def.vcodiv.shift = tbg[i].vcodiv_shift;
+ def.refdiv.offset = TBG_CTRL7;
+ def.refdiv.shift = tbg[i].refdiv_shift;
+ def.fbdiv.offset = TBG_CTRL0;
+ def.fbdiv.shift = tbg[i].fbdiv_shift;
+ def.vcodiv.mask = def.refdiv.mask = def.fbdiv.mask = TBG_MASK;
+ def.tbg_bypass.offset = TBG_CTRL1;
+ def.tbg_bypass.shift = tbg[i].tbg_bypass_en;
+ def.tbg_bypass.mask = 0x1;
+
+ error = a37x0_tbg_pll_clk_register(sc->clkdom, &def);
+
+ if (error) {
+ device_printf(dev, "Cannot register clock node\n");
+ bus_release_resources(dev, a37x0_tbg_clk_spec,
+ &sc->res);
+ return (ENXIO);
+ }
+ }
+
+ error = clkdom_finit(sc->clkdom);
+ if (error) {
+ device_printf(dev,
+ "Cannot finalize clock domain intialization\n");
+ bus_release_resources(dev, a37x0_tbg_clk_spec, &sc->res);
+ return (ENXIO);
+ }
+
+ if (bootverbose)
+ clkdom_dump(sc->clkdom);
+
+ return (0);
+}
+
+static int
+a37x0_tbg_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "marvell,armada-3700-tbg-clock"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Marvell Armada 3700 time base generators");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+a37x0_tbg_detach(device_t dev)
+{
+
+ return (EBUSY);
+}
diff --git a/sys/arm/mv/clk/a37x0_tbg_pll.h b/sys/arm/mv/clk/a37x0_tbg_pll.h
new file mode 100644
--- /dev/null
+++ b/sys/arm/mv/clk/a37x0_tbg_pll.h
@@ -0,0 +1,54 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2021 Semihalf.
+ *
+ * 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 AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ *
+ */
+
+#ifndef _TBG_CLK_PLL_H_
+#define _TBG_CLK_PLL_H_
+
+#include <dev/extres/clk/clk.h>
+
+struct a37x0_tbg_pll_reg_def {
+ uint32_t offset;
+ uint32_t shift;
+ uint32_t mask;
+};
+
+struct a37x0_tbg_pll_clk_def {
+ struct clknode_init_def clkdef;
+
+ struct a37x0_tbg_pll_reg_def vcodiv;
+ struct a37x0_tbg_pll_reg_def refdiv;
+ struct a37x0_tbg_pll_reg_def fbdiv;
+
+ struct a37x0_tbg_pll_reg_def tbg_bypass;
+};
+
+int a37x0_tbg_pll_clk_register(struct clkdom *,
+ const struct a37x0_tbg_pll_clk_def *);
+#endif
diff --git a/sys/arm/mv/clk/a37x0_tbg_pll.c b/sys/arm/mv/clk/a37x0_tbg_pll.c
new file mode 100644
--- /dev/null
+++ b/sys/arm/mv/clk/a37x0_tbg_pll.c
@@ -0,0 +1,130 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2021 Semihalf.
+ *
+ * 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 AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <machine/bus.h>
+
+#include <dev/extres/clk/clk.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "clkdev_if.h"
+
+#include "a37x0_tbg_pll.h"
+
+#define RD4(_clk, offset, val) \
+ CLKDEV_READ_4(clknode_get_device(_clk), offset, val)
+
+struct a37x0_tbg_pll_softc {
+ struct a37x0_tbg_pll_reg_def vcodiv;
+ struct a37x0_tbg_pll_reg_def refdiv;
+ struct a37x0_tbg_pll_reg_def fbdiv;
+ struct a37x0_tbg_pll_reg_def tbg_bypass;
+};
+
+static int
+a37x0_tbg_pll_recalc_freq(struct clknode *clk, uint64_t *freq)
+{
+ struct a37x0_tbg_pll_softc *sc;
+ uint32_t vcodiv, fbdiv, refdiv;
+ unsigned int val;
+
+ sc = clknode_get_softc(clk);
+
+ RD4(clk, sc->tbg_bypass.offset, &val);
+ if ((val >> sc->tbg_bypass.shift) & sc->tbg_bypass.mask)
+ return 0;
+
+ RD4(clk, sc->vcodiv.offset, &val);
+ vcodiv = 1 << ((val >> sc->vcodiv.shift) & sc->vcodiv.mask);
+
+ RD4(clk, sc->refdiv.offset, &val);
+ refdiv = (val >> sc->refdiv.shift) & sc->refdiv.mask;
+
+ RD4(clk, sc->fbdiv.offset, &val);
+ fbdiv = (val >> sc->fbdiv.shift) & sc->fbdiv.mask;
+
+ if (refdiv == 0)
+ refdiv = 1;
+
+ *freq = *freq * (fbdiv / refdiv) * 4;
+ *freq /= vcodiv;
+
+ return (0);
+}
+
+static int
+a37x0_tbg_pll_init(struct clknode *clk, device_t dev)
+{
+
+ clknode_init_parent_idx(clk, 0);
+
+ return (0);
+}
+
+static clknode_method_t a37x0_tbg_pll_clknode_methods[] = {
+ CLKNODEMETHOD(clknode_recalc_freq, a37x0_tbg_pll_recalc_freq),
+ CLKNODEMETHOD(clknode_init, a37x0_tbg_pll_init),
+
+ CLKNODEMETHOD_END
+};
+
+DEFINE_CLASS_1(a37x0_tbg_pll__clknode, a37x0_tbg_pll_clknode_class,
+ a37x0_tbg_pll_clknode_methods, sizeof(struct a37x0_tbg_pll_softc),
+ clknode_class);
+
+int
+a37x0_tbg_pll_clk_register(struct clkdom *clkdom,
+ const struct a37x0_tbg_pll_clk_def *clkdef)
+{
+ struct a37x0_tbg_pll_softc *sc;
+ struct clknode *clk;
+
+ clk = clknode_create(clkdom, &a37x0_tbg_pll_clknode_class,
+ &clkdef->clkdef);
+
+ if (clk == NULL)
+ return (1);
+
+ sc = clknode_get_softc(clk);
+
+ sc->vcodiv = clkdef->vcodiv;
+ sc->refdiv = clkdef->refdiv;
+ sc->fbdiv = clkdef->fbdiv;
+ sc->tbg_bypass = clkdef->tbg_bypass;
+
+ if (clknode_register(clkdom, clk) == NULL)
+ return (1);
+
+ return (0);
+}
diff --git a/sys/arm64/conf/std.marvell b/sys/arm64/conf/std.marvell
--- a/sys/arm64/conf/std.marvell
+++ b/sys/arm64/conf/std.marvell
@@ -55,6 +55,7 @@
# Clocks
device a37x0_xtal # Marvell xtal-clock
+device a37x0_tbg # Marvell tbg-clock
# DTBs
makeoptions MODULES_EXTRA+="dtb/mv"
diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64
--- a/sys/conf/files.arm64
+++ b/sys/conf/files.arm64
@@ -456,6 +456,7 @@
arm/mv/a37x0_gpio.c optional a37x0_gpio gpio fdt
arm/mv/a37x0_iic.c optional a37x0_iic iicbus fdt
arm/mv/a37x0_spi.c optional a37x0_spi spibus fdt
+arm/mv/clk/a37x0_tbg.c optional a37x0_tbg clk fdt syscon
arm/mv/clk/a37x0_xtal.c optional a37x0_xtal clk fdt syscon
arm/mv/armada38x/armada38x_rtc.c optional mv_rtc fdt
arm/mv/gpio.c optional mv_gpio fdt
@@ -468,6 +469,7 @@
arm/mv/mv_cp110_icu.c optional mv_cp110_icu fdt
arm/mv/mv_cp110_icu_bus.c optional mv_cp110_icu fdt
arm/mv/mv_thermal.c optional SOC_MARVELL_8K mv_thermal fdt
+arm/mv/clk/a37x0_tbg_pll.c optional a37x0_tbg clk fdt syscon
# NVidia
arm/nvidia/tegra_abpmisc.c optional fdt soc_nvidia_tegra210
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Feb 28, 10:58 AM (20 h, 11 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16884480
Default Alt Text
D32293.diff (13 KB)
Attached To
Mode
D32293: Add driver for armada, 37x0-tbg-clock
Attached
Detach File
Event Timeline
Log In to Comment