Page MenuHomeFreeBSD

D25274.id73181.diff
No OneTemporary

D25274.id73181.diff

Index: sys/arm/freescale/imx/imx_gpio.c
===================================================================
--- sys/arm/freescale/imx/imx_gpio.c
+++ sys/arm/freescale/imx/imx_gpio.c
@@ -57,6 +57,14 @@
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
+#if defined(EXT_RESOURCES) && defined(__aarch64__)
+#define IMX_ENABLE_CLOCKS
+#endif
+
+#ifdef IMX_ENABLE_CLOCKS
+#include <dev/extres/clk/clk.h>
+#endif
+
#include "gpio_if.h"
#ifdef INTRNG
@@ -119,13 +127,17 @@
#ifdef INTRNG
struct gpio_irqsrc gpio_pic_irqsrc[NGPIO];
#endif
+#ifdef IMX_ENABLE_CLOCKS
+ clk_t clk;
+#endif
};
static struct ofw_compat_data compat_data[] = {
- {"fsl,imx6q-gpio", 1},
- {"fsl,imx53-gpio", 1},
- {"fsl,imx51-gpio", 1},
- {NULL, 0}
+ {"fsl,imx8mq-gpio", 1},
+ {"fsl,imx6q-gpio", 1},
+ {"fsl,imx53-gpio", 1},
+ {"fsl,imx51-gpio", 1},
+ {NULL, 0}
};
static struct resource_spec imx_gpio_spec[] = {
@@ -788,6 +800,9 @@
{
struct imx51_gpio_softc *sc;
int i, irq, unit;
+#ifdef IMX_ENABLE_CLOCKS
+ int err;
+#endif
sc = device_get_softc(dev);
sc->dev = dev;
@@ -795,6 +810,19 @@
mtx_init(&sc->sc_mtx, device_get_nameunit(sc->dev), NULL, MTX_SPIN);
+#ifdef IMX_ENABLE_CLOCKS
+ if (clk_get_by_ofw_index(sc->dev, 0, 0, &sc->clk) != 0) {
+ device_printf(dev, "could not get clock");
+ return (ENOENT);
+ }
+
+ err = clk_enable(sc->clk);
+ if (err != 0) {
+ device_printf(sc->dev, "could not enable ipg clock\n");
+ return (err);
+ }
+#endif
+
if (bus_alloc_resources(dev, imx_gpio_spec, sc->sc_res)) {
device_printf(dev, "could not allocate resources\n");
bus_release_resources(dev, imx_gpio_spec, sc->sc_res);
@@ -850,9 +878,20 @@
{
int irq;
struct imx51_gpio_softc *sc;
+#ifdef IMX_ENABLE_CLOCKS
+ int error;
+#endif
sc = device_get_softc(dev);
+#ifdef IMX_ENABLE_CLOCKS
+ error = clk_disable(sc->clk);
+ if (error != 0) {
+ device_printf(sc->dev, "could not disable ipg clock\n");
+ return (error);
+ }
+#endif
+
gpiobus_detach_bus(dev);
for (irq = 0; irq < NUM_IRQRES; irq++) {
if (sc->gpio_ih[irq])
Index: sys/arm/freescale/imx/imx_i2c.c
===================================================================
--- sys/arm/freescale/imx/imx_i2c.c
+++ sys/arm/freescale/imx/imx_i2c.c
@@ -73,6 +73,14 @@
#include <dev/fdt/fdt_pinctrl.h>
#include <dev/gpio/gpiobusvar.h>
+#if defined(EXT_RESOURCES) && defined(__aarch64__)
+#define IMX_ENABLE_CLOCKS
+#endif
+
+#ifdef IMX_ENABLE_CLOCKS
+#include <dev/extres/clk/clk.h>
+#endif
+
#define I2C_ADDR_REG 0x00 /* I2C slave address register */
#define I2C_FDR_REG 0x04 /* I2C frequency divider register */
#define I2C_CONTROL_REG 0x08 /* I2C control register */
@@ -125,6 +133,7 @@
};
static struct ofw_compat_data compat_data[] = {
+ {"fsl,imx21-i2c", 1},
{"fsl,imx6q-i2c", 1},
{"fsl,imx-i2c", 1},
{NULL, 0}
@@ -141,6 +150,9 @@
gpio_pin_t rb_sdapin;
u_int debug;
u_int slave;
+#ifdef IMX_ENABLE_CLOCKS
+ clk_t ipgclk;
+#endif
};
#define DEVICE_DEBUGF(sc, lvl, fmt, args...) \
@@ -385,6 +397,19 @@
sc->dev = dev;
sc->rid = 0;
+#ifdef IMX_ENABLE_CLOCKS
+ if (clk_get_by_ofw_index(sc->dev, 0, 0, &sc->ipgclk) != 0) {
+ device_printf(dev, "could not get ipg clock");
+ return (ENOENT);
+ }
+
+ err = clk_enable(sc->ipgclk);
+ if (err != 0) {
+ device_printf(sc->dev, "could not enable ipg clock\n");
+ return (err);
+ }
+#endif
+
sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid,
RF_ACTIVE);
if (sc->res == NULL) {
@@ -459,6 +484,14 @@
sc = device_get_softc(dev);
+#ifdef IMX_ENABLE_CLOCKS
+ error = clk_disable(sc->ipgclk);
+ if (error != 0) {
+ device_printf(sc->dev, "could not disable ipg clock\n");
+ return (error);
+ }
+#endif
+
if ((error = bus_generic_detach(sc->dev)) != 0) {
device_printf(sc->dev, "cannot detach child devices\n");
return (error);
@@ -571,6 +604,10 @@
{
struct i2c_softc *sc;
u_int busfreq, div, i, ipgfreq;
+#ifdef IMX_ENABLE_CLOCKS
+ int err;
+ uint64_t freq;
+#endif
sc = device_get_softc(dev);
@@ -580,7 +617,16 @@
* Look up the divisor that gives the nearest speed that doesn't exceed
* the configured value for the bus.
*/
+#ifdef IMX_ENABLE_CLOCKS
+ err = clk_get_freq(sc->ipgclk, &freq);
+ if (err != 0) {
+ device_printf(sc->dev, "cannot get frequency\n");
+ return (err);
+ }
+ ipgfreq = (int32_t)freq;
+#else
ipgfreq = imx_ccm_ipg_hz();
+#endif
busfreq = IICBUS_GET_FREQUENCY(sc->iicbus, speed);
div = howmany(ipgfreq, busfreq);
for (i = 0; i < nitems(clkdiv_table); i++) {
Index: sys/arm/freescale/imx/imx_iomux.c
===================================================================
--- sys/arm/freescale/imx/imx_iomux.c
+++ sys/arm/freescale/imx/imx_iomux.c
@@ -76,6 +76,7 @@
static struct iomux_softc *iomux_sc;
static struct ofw_compat_data compat_data[] = {
+ {"fsl,imx8mq-iomuxc", true},
{"fsl,imx6dl-iomuxc", true},
{"fsl,imx6q-iomuxc", true},
{"fsl,imx6sl-iomuxc", true},
Index: sys/arm64/conf/GENERIC
===================================================================
--- sys/arm64/conf/GENERIC
+++ sys/arm64/conf/GENERIC
@@ -113,6 +113,7 @@
options SOC_ALLWINNER_H5
options SOC_ALLWINNER_H6
options SOC_CAVM_THUNDERX
+options SOC_FREESCALE_IMX8
options SOC_HISI_HI6220
options SOC_INTEL_STRATIX10
options SOC_BRCM_BCM2837
@@ -172,6 +173,7 @@
device dwc_rk # Rockchip Designware
device dwc_socfpga # Altera SOCFPGA Ethernet MAC
device genet # Broadcom on RPi4
+device ffec # iMX FFEC
# Etherswitch devices
device etherswitch # Enable etherswitch support
@@ -205,6 +207,7 @@
# Serial (COM) ports
device uart # Generic UART driver
+device uart_imx # iMX8 UART
device uart_msm # Qualcomm MSM UART driver
device uart_mu # RPI3 aux port
device uart_mvebu # Armada 3700 UART driver
@@ -265,6 +268,7 @@
device syr827 # Silergy SYR827 PMIC
device sy8106a # SY8106A Buck Regulator
device vf_i2c # Freescale Vybrid I2C controller
+device fsliic # Freescale iMX I2C controller
# Clock and reset controllers
device aw_ccu # Allwinner clock controller
@@ -352,4 +356,4 @@
device acpi
# DTBs
-makeoptions MODULES_EXTRA="dtb/allwinner dtb/mv dtb/rockchip dtb/rpi"
+makeoptions MODULES_EXTRA="dtb/allwinner dtb/imx8 dtb/mv dtb/rockchip dtb/rpi"
Index: sys/arm64/freescale/imx/clk/imx_clk_composite.h
===================================================================
--- /dev/null
+++ sys/arm64/freescale/imx/clk/imx_clk_composite.h
@@ -0,0 +1,45 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright 2018 Emmanuel Vadot <manu@FreeBSD.org>
+ *
+ * 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 _IMX_CLK_COMPOSITE_H_
+#define _IMX_CLK_COMPOSITE_H_
+
+#include <dev/extres/clk/clk.h>
+
+struct imx_clk_composite_def {
+ struct clknode_init_def clkdef;
+
+ uint32_t offset;
+ uint32_t flags;
+};
+
+int imx_clk_composite_register(struct clkdom *clkdom,
+ struct imx_clk_composite_def *clkdef);
+
+#endif /* _IMX_CLK_COMPOSITE_H_ */
Index: sys/arm64/freescale/imx/clk/imx_clk_composite.c
===================================================================
--- /dev/null
+++ sys/arm64/freescale/imx/clk/imx_clk_composite.c
@@ -0,0 +1,309 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2018 Emmanuel Vadot <manu@freebsd.org>
+ *
+ * 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>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <dev/extres/clk/clk.h>
+
+#include <arm64/freescale/imx/clk/imx_clk_composite.h>
+
+#include "clkdev_if.h"
+
+#define TARGET_ROOT_ENABLE (1 << 28)
+#define TARGET_ROOT_MUX(n) ((n) << 24)
+#define TARGET_ROOT_MUX_MASK (7 << 24)
+#define TARGET_ROOT_MUX_SHIFT 24
+#define TARGET_ROOT_PRE_PODF(n) ((((n) - 1) & 0x7) << 16)
+#define TARGET_ROOT_PRE_PODF_MASK (0x7 << 16)
+#define TARGET_ROOT_PRE_PODF_SHIFT 16
+#define TARGET_ROOT_PRE_PODF_MAX 7
+#define TARGET_ROOT_POST_PODF(n) ((((n) - 1) & 0x3f) << 0)
+#define TARGET_ROOT_POST_PODF_MASK (0x3f << 0)
+#define TARGET_ROOT_POST_PODF_SHIFT 0
+#define TARGET_ROOT_POST_PODF_MAX 0x3f
+
+struct imx_clk_composite_sc {
+ uint32_t offset;
+ uint32_t flags;
+};
+
+#define WRITE4(_clk, off, val) \
+ CLKDEV_WRITE_4(clknode_get_device(_clk), off, val)
+#define READ4(_clk, off, val) \
+ CLKDEV_READ_4(clknode_get_device(_clk), off, val)
+#define DEVICE_LOCK(_clk) \
+ CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))
+#define DEVICE_UNLOCK(_clk) \
+ CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
+
+#define IMX_CLK_COMPOSITE_MASK_SHIFT 16
+
+#if 0
+#define dprintf(format, arg...) \
+ printf("%s:(%s)" format, __func__, clknode_get_name(clk), arg)
+#else
+#define dprintf(format, arg...)
+#endif
+
+static int
+imx_clk_composite_init(struct clknode *clk, device_t dev)
+{
+ struct imx_clk_composite_sc *sc;
+ uint32_t val, idx;
+
+ sc = clknode_get_softc(clk);
+
+ DEVICE_LOCK(clk);
+ READ4(clk, sc->offset, &val);
+ DEVICE_UNLOCK(clk);
+ idx = (val & TARGET_ROOT_MUX_MASK) >> TARGET_ROOT_MUX_SHIFT;
+
+ clknode_init_parent_idx(clk, idx);
+
+ return (0);
+}
+
+static int
+imx_clk_composite_set_gate(struct clknode *clk, bool enable)
+{
+ struct imx_clk_composite_sc *sc;
+ uint32_t val = 0;
+
+ sc = clknode_get_softc(clk);
+
+ dprintf("%sabling gate\n", enable ? "En" : "Dis");
+ DEVICE_LOCK(clk);
+ READ4(clk, sc->offset, &val);
+ if (enable)
+ val |= TARGET_ROOT_ENABLE;
+ else
+ val &= ~(TARGET_ROOT_ENABLE);
+ WRITE4(clk, sc->offset, val);
+ DEVICE_UNLOCK(clk);
+
+ return (0);
+}
+
+static int
+imx_clk_composite_set_mux(struct clknode *clk, int index)
+{
+ struct imx_clk_composite_sc *sc;
+ uint32_t val = 0;
+
+ sc = clknode_get_softc(clk);
+
+ dprintf("Set mux to %d\n", index);
+ DEVICE_LOCK(clk);
+ READ4(clk, sc->offset, &val);
+ val &= ~(TARGET_ROOT_MUX_MASK);
+ val |= TARGET_ROOT_MUX(index);
+ WRITE4(clk, sc->offset, val);
+ DEVICE_UNLOCK(clk);
+
+ return (0);
+}
+
+static int
+imx_clk_composite_recalc(struct clknode *clk, uint64_t *freq)
+{
+ struct imx_clk_composite_sc *sc;
+ uint32_t reg, pre_div, post_div;
+
+ sc = clknode_get_softc(clk);
+
+ DEVICE_LOCK(clk);
+ READ4(clk, sc->offset, &reg);
+ DEVICE_UNLOCK(clk);
+
+ pre_div = ((reg & TARGET_ROOT_PRE_PODF_MASK)
+ >> TARGET_ROOT_PRE_PODF_SHIFT) + 1;
+ post_div = ((reg & TARGET_ROOT_POST_PODF_MASK)
+ >> TARGET_ROOT_POST_PODF_SHIFT) + 1;
+
+ dprintf("parent_freq=%ju, div=%u\n", *freq, div);
+ *freq = *freq / pre_div / post_div;
+ dprintf("Final freq=%ju\n", *freq);
+ return (0);
+}
+
+static int
+imx_clk_composite_find_best(uint64_t fparent, uint64_t ftarget,
+ uint32_t *pre_div, uint32_t *post_div, int flags)
+{
+ uint32_t prediv, postdiv, best_prediv, best_postdiv;
+ int64_t diff, best_diff;
+ uint64_t cur;
+
+ best_diff = INT64_MAX;
+ for (prediv = 1; prediv <= TARGET_ROOT_PRE_PODF_MAX + 1; prediv++) {
+ for (postdiv = 1; postdiv <= TARGET_ROOT_POST_PODF_MAX + 1; postdiv++) {
+ cur= fparent / prediv / postdiv;
+ diff = (int64_t)ftarget - (int64_t)cur;
+ if (flags & CLK_SET_ROUND_DOWN) {
+ if (diff >= 0 && diff < best_diff) {
+ best_diff = diff;
+ best_prediv = prediv;
+ best_postdiv = postdiv;
+ }
+ }
+ else if (flags & CLK_SET_ROUND_UP) {
+ if (diff <= 0 && abs(diff) < best_diff) {
+ best_diff = diff;
+ best_prediv = prediv;
+ best_postdiv = postdiv;
+ }
+ }
+ else {
+ if (abs(diff) < best_diff) {
+ best_diff = abs(diff);
+ best_prediv = prediv;
+ best_postdiv = postdiv;
+ }
+ }
+ }
+ }
+
+ if (best_diff == INT64_MAX)
+ return (ERANGE);
+
+ *pre_div = best_prediv;
+ *post_div = best_postdiv;
+
+ return (0);
+}
+
+static int
+imx_clk_composite_set_freq(struct clknode *clk, uint64_t fparent, uint64_t *fout,
+ int flags, int *stop)
+{
+ struct imx_clk_composite_sc *sc;
+ struct clknode *p_clk;
+ const char **p_names;
+ int p_idx, best_parent;
+ int64_t best_diff, diff;
+ int32_t best_pre_div, best_post_div, pre_div, post_div;
+ uint64_t cur, best;
+ uint32_t val;
+
+ sc = clknode_get_softc(clk);
+ dprintf("Finding best parent/div for target freq of %ju\n", *fout);
+ p_names = clknode_get_parent_names(clk);
+
+ best_diff = 0;
+
+ for (p_idx = 0; p_idx != clknode_get_parents_num(clk); p_idx++) {
+ p_clk = clknode_find_by_name(p_names[p_idx]);
+ clknode_get_freq(p_clk, &fparent);
+ dprintf("Testing with parent %s (%d) at freq %ju\n",
+ clknode_get_name(p_clk), p_idx, fparent);
+
+ if (!imx_clk_composite_find_best(fparent, *fout, &pre_div, &post_div, sc->flags))
+ continue;
+ cur = fparent / pre_div / post_div;
+ diff = abs((int64_t)*fout - (int64_t)cur);
+ if (diff < best_diff) {
+ best = cur;
+ best_diff = diff;
+ best_pre_div = pre_div;
+ best_post_div = pre_div;
+ best_parent = p_idx;
+ dprintf("Best parent so far %s (%d) with best freq at "
+ "%ju\n", clknode_get_name(p_clk), p_idx, best);
+ }
+ }
+
+ *stop = 1;
+ if (best_diff == INT64_MAX)
+ return (ERANGE);
+
+ if ((flags & CLK_SET_DRYRUN) != 0) {
+ *fout = best;
+ return (0);
+ }
+
+ p_idx = clknode_get_parent_idx(clk);
+ if (p_idx != best_parent) {
+ dprintf("Switching parent index from %d to %d\n", p_idx,
+ best_parent);
+ clknode_set_parent_by_idx(clk, best_parent);
+ }
+
+ dprintf("Setting dividers to pre=%d, post=%d\n", best_pre_div, best_post_div);
+
+ DEVICE_LOCK(clk);
+ READ4(clk, sc->offset, &val);
+ val &= ~(TARGET_ROOT_PRE_PODF_MASK | TARGET_ROOT_POST_PODF_MASK);
+ val |= TARGET_ROOT_PRE_PODF(pre_div);
+ val |= TARGET_ROOT_POST_PODF(post_div);
+ DEVICE_UNLOCK(clk);
+
+ *fout = best;
+ return (0);
+}
+
+static clknode_method_t imx_clk_composite_clknode_methods[] = {
+ /* Device interface */
+ CLKNODEMETHOD(clknode_init, imx_clk_composite_init),
+ CLKNODEMETHOD(clknode_set_gate, imx_clk_composite_set_gate),
+ CLKNODEMETHOD(clknode_set_mux, imx_clk_composite_set_mux),
+ CLKNODEMETHOD(clknode_recalc_freq, imx_clk_composite_recalc),
+ CLKNODEMETHOD(clknode_set_freq, imx_clk_composite_set_freq),
+ CLKNODEMETHOD_END
+};
+
+DEFINE_CLASS_1(imx_clk_composite_clknode, imx_clk_composite_clknode_class,
+ imx_clk_composite_clknode_methods, sizeof(struct imx_clk_composite_sc),
+ clknode_class);
+
+int
+imx_clk_composite_register(struct clkdom *clkdom,
+ struct imx_clk_composite_def *clkdef)
+{
+ struct clknode *clk;
+ struct imx_clk_composite_sc *sc;
+
+ clk = clknode_create(clkdom, &imx_clk_composite_clknode_class,
+ &clkdef->clkdef);
+ if (clk == NULL)
+ return (1);
+
+ sc = clknode_get_softc(clk);
+
+ sc->offset = clkdef->offset;
+ sc->flags = clkdef->flags;
+
+ clknode_register(clkdom, clk);
+
+ return (0);
+}
Index: sys/arm64/freescale/imx/clk/imx_clk_frac_pll.h
===================================================================
--- /dev/null
+++ sys/arm64/freescale/imx/clk/imx_clk_frac_pll.h
@@ -0,0 +1,42 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Oleksandr Tymoshenko <gonzo@FreeBSD.org>
+ *
+ * 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 _IMX_CLK_FRAC_PLL_H_
+#define _IMX_CLK_FRAC_PLL_H_
+
+#include <dev/extres/clk/clk.h>
+
+struct imx_clk_frac_pll_def {
+ struct clknode_init_def clkdef;
+ uint32_t offset;
+};
+
+int imx_clk_frac_pll_register(struct clkdom *clkdom, struct imx_clk_frac_pll_def *clkdef);
+
+#endif /* _IMX_CLK_FRAC_PLL_H_ */
Index: sys/arm64/freescale/imx/clk/imx_clk_frac_pll.c
===================================================================
--- /dev/null
+++ sys/arm64/freescale/imx/clk/imx_clk_frac_pll.c
@@ -0,0 +1,177 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Oleksandr Tymoshenko <gonzo@FreeBSD.org>
+ *
+ * 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>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <dev/extres/clk/clk.h>
+
+#include <arm64/freescale/imx/clk/imx_clk_frac_pll.h>
+
+#include "clkdev_if.h"
+
+struct imx_clk_frac_pll_sc {
+ uint32_t offset;
+};
+
+#define WRITE4(_clk, off, val) \
+ CLKDEV_WRITE_4(clknode_get_device(_clk), off, val)
+#define READ4(_clk, off, val) \
+ CLKDEV_READ_4(clknode_get_device(_clk), off, val)
+#define DEVICE_LOCK(_clk) \
+ CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))
+#define DEVICE_UNLOCK(_clk) \
+ CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
+
+#define CFG0 0
+#define CFG0_PLL_LOCK (1 << 31)
+#define CFG0_PD (1 << 19)
+#define CFG0_BYPASS (1 << 14)
+#define CFG0_NEWDIV_VAL (1 << 12)
+#define CFG0_NEWDIV_ACK (1 << 11)
+#define CFG0_OUTPUT_DIV_MASK (0x1f << 0)
+#define CFG0_OUTPUT_DIV_SHIFT 0
+#define CFG1 4
+#define CFG1_FRAC_DIV_MASK (0xffffff << 7)
+#define CFG1_FRAC_DIV_SHIFT 7
+#define CFG1_INT_DIV_MASK (0x7f << 0)
+#define CFG1_INT_DIV_SHIFT 0
+
+#if 0
+#define dprintf(format, arg...) \
+ printf("%s:(%s)" format, __func__, clknode_get_name(clk), arg)
+#else
+#define dprintf(format, arg...)
+#endif
+
+static int
+imx_clk_frac_pll_init(struct clknode *clk, device_t dev)
+{
+
+ clknode_init_parent_idx(clk, 0);
+ return (0);
+}
+
+static int
+imx_clk_frac_pll_set_gate(struct clknode *clk, bool enable)
+{
+ struct imx_clk_frac_pll_sc *sc;
+ uint32_t cfg0;
+ int timeout;
+
+ sc = clknode_get_softc(clk);
+
+ DEVICE_LOCK(clk);
+ READ4(clk, sc->offset + CFG0, &cfg0);
+ if (enable)
+ cfg0 &= ~(CFG0_PD);
+ else
+ cfg0 |= CFG0_PD;
+ WRITE4(clk, sc->offset + CFG0, cfg0);
+
+ /* Wait for PLL to lock */
+ if (enable && ((cfg0 & CFG0_BYPASS) == 0)) {
+ for (timeout = 1000; timeout; timeout--) {
+ READ4(clk, sc->offset + CFG0, &cfg0);
+ if (cfg0 & CFG0_PLL_LOCK)
+ break;
+ DELAY(1);
+ }
+ }
+
+ DEVICE_UNLOCK(clk);
+
+ return (0);
+}
+
+static int
+imx_clk_frac_pll_recalc(struct clknode *clk, uint64_t *freq)
+{
+ struct imx_clk_frac_pll_sc *sc;
+ uint32_t cfg0, cfg1;
+ uint64_t div, divfi, divff, divf_val;
+
+ sc = clknode_get_softc(clk);
+
+ DEVICE_LOCK(clk);
+ READ4(clk, sc->offset + CFG0, &cfg0);
+ READ4(clk, sc->offset + CFG1, &cfg1);
+ DEVICE_UNLOCK(clk);
+
+ div = (cfg0 & CFG0_OUTPUT_DIV_MASK) >> CFG0_OUTPUT_DIV_SHIFT;
+ div = (div + 1) * 2;
+ divff = (cfg1 & CFG1_FRAC_DIV_MASK) >> CFG1_FRAC_DIV_SHIFT;
+ divfi = (cfg1 & CFG1_INT_DIV_MASK) >> CFG1_INT_DIV_SHIFT;
+
+ /* PLL is bypassed */
+ if (cfg0 & CFG0_BYPASS)
+ return (0);
+
+ divf_val = 1 + divfi + (divff/0x1000000);
+ *freq = *freq * 8 * divf_val / div;
+
+ return (0);
+}
+
+static clknode_method_t imx_clk_frac_pll_clknode_methods[] = {
+ /* Device interface */
+ CLKNODEMETHOD(clknode_init, imx_clk_frac_pll_init),
+ CLKNODEMETHOD(clknode_set_gate, imx_clk_frac_pll_set_gate),
+ CLKNODEMETHOD(clknode_recalc_freq, imx_clk_frac_pll_recalc),
+ CLKNODEMETHOD_END
+};
+
+DEFINE_CLASS_1(imx_clk_frac_pll_clknode, imx_clk_frac_pll_clknode_class,
+ imx_clk_frac_pll_clknode_methods, sizeof(struct imx_clk_frac_pll_sc),
+ clknode_class);
+
+int
+imx_clk_frac_pll_register(struct clkdom *clkdom,
+ struct imx_clk_frac_pll_def *clkdef)
+{
+ struct clknode *clk;
+ struct imx_clk_frac_pll_sc *sc;
+
+ clk = clknode_create(clkdom, &imx_clk_frac_pll_clknode_class,
+ &clkdef->clkdef);
+ if (clk == NULL)
+ return (1);
+
+ sc = clknode_get_softc(clk);
+
+ sc->offset = clkdef->offset;
+
+ clknode_register(clkdom, clk);
+
+ return (0);
+}
Index: sys/arm64/freescale/imx/clk/imx_clk_gate.h
===================================================================
--- /dev/null
+++ sys/arm64/freescale/imx/clk/imx_clk_gate.h
@@ -0,0 +1,45 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright 2018 Emmanuel Vadot <manu@FreeBSD.org>
+ *
+ * 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 _IMX_CLK_GATE_H_
+#define _IMX_CLK_GATE_H_
+
+#include <dev/extres/clk/clk.h>
+
+struct imx_clk_gate_def {
+ struct clknode_init_def clkdef;
+ uint32_t offset;
+ uint32_t shift;
+ uint32_t mask;
+ int gate_flags;
+};
+
+int imx_clk_gate_register(struct clkdom *clkdom, struct imx_clk_gate_def *clkdef);
+
+#endif /* _IMX_CLK_GATE_H_ */
Index: sys/arm64/freescale/imx/clk/imx_clk_gate.c
===================================================================
--- /dev/null
+++ sys/arm64/freescale/imx/clk/imx_clk_gate.c
@@ -0,0 +1,117 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright 2016 Michal Meloun <mmel@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 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/systm.h>
+#include <sys/bus.h>
+
+#include <dev/extres/clk/clk.h>
+
+#include <arm64/freescale/imx/clk/imx_clk_gate.h>
+
+#include "clkdev_if.h"
+
+#define WR4(_clk, off, val) \
+ CLKDEV_WRITE_4(clknode_get_device(_clk), off, val)
+#define RD4(_clk, off, val) \
+ CLKDEV_READ_4(clknode_get_device(_clk), off, val)
+#define MD4(_clk, off, clr, set ) \
+ CLKDEV_MODIFY_4(clknode_get_device(_clk), off, clr, set)
+#define DEVICE_LOCK(_clk) \
+ CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))
+#define DEVICE_UNLOCK(_clk) \
+ CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
+
+static int imx_clk_gate_init(struct clknode *clk, device_t dev);
+static int imx_clk_gate_set_gate(struct clknode *clk, bool enable);
+struct imx_clk_gate_sc {
+ uint32_t offset;
+ uint32_t shift;
+ uint32_t mask;
+ int gate_flags;
+};
+
+static clknode_method_t imx_clk_gate_methods[] = {
+ /* Device interface */
+ CLKNODEMETHOD(clknode_init, imx_clk_gate_init),
+ CLKNODEMETHOD(clknode_set_gate, imx_clk_gate_set_gate),
+ CLKNODEMETHOD_END
+};
+DEFINE_CLASS_1(imx_clk_gate, imx_clk_gate_class, imx_clk_gate_methods,
+ sizeof(struct imx_clk_gate_sc), clknode_class);
+
+static int
+imx_clk_gate_init(struct clknode *clk, device_t dev)
+{
+
+ clknode_init_parent_idx(clk, 0);
+ return(0);
+}
+
+static int
+imx_clk_gate_set_gate(struct clknode *clk, bool enable)
+{
+ uint32_t reg;
+ struct imx_clk_gate_sc *sc;
+ int rv;
+
+ sc = clknode_get_softc(clk);
+ DEVICE_LOCK(clk);
+ rv = MD4(clk, sc->offset, sc->mask << sc->shift,
+ (enable ? sc->mask : 0) << sc->shift);
+ if (rv != 0) {
+ DEVICE_UNLOCK(clk);
+ return (rv);
+ }
+ RD4(clk, sc->offset, &reg);
+ DEVICE_UNLOCK(clk);
+ return(0);
+}
+
+int
+imx_clk_gate_register(struct clkdom *clkdom, struct imx_clk_gate_def *clkdef)
+{
+ struct clknode *clk;
+ struct imx_clk_gate_sc *sc;
+
+ clk = clknode_create(clkdom, &imx_clk_gate_class, &clkdef->clkdef);
+ if (clk == NULL)
+ return (1);
+
+ sc = clknode_get_softc(clk);
+ sc->offset = clkdef->offset;
+ sc->shift = clkdef->shift;
+ sc->mask = clkdef->mask;
+ sc->gate_flags = clkdef->gate_flags;
+
+ clknode_register(clkdom, clk);
+ return (0);
+}
Index: sys/arm64/freescale/imx/clk/imx_clk_mux.h
===================================================================
--- /dev/null
+++ sys/arm64/freescale/imx/clk/imx_clk_mux.h
@@ -0,0 +1,45 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright 2016 Michal Meloun <mmel@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 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 _IMX_CLK_MUX_H_
+#define _IMX_CLK_MUX_H_
+
+#include <dev/extres/clk/clk.h>
+
+struct imx_clk_mux_def {
+ struct clknode_init_def clkdef;
+ uint32_t offset;
+ uint32_t shift;
+ uint32_t width;
+ int mux_flags;
+};
+
+int imx_clk_mux_register(struct clkdom *clkdom, struct imx_clk_mux_def *clkdef);
+
+#endif /* _IMX_CLK_MUX_H_ */
Index: sys/arm64/freescale/imx/clk/imx_clk_mux.c
===================================================================
--- /dev/null
+++ sys/arm64/freescale/imx/clk/imx_clk_mux.c
@@ -0,0 +1,138 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright 2016 Michal Meloun <mmel@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 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/conf.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+
+#include <machine/bus.h>
+
+#include <dev/extres/clk/clk.h>
+
+#include <arm64/freescale/imx/clk/imx_clk_mux.h>
+
+#include "clkdev_if.h"
+
+#define WR4(_clk, off, val) \
+ CLKDEV_WRITE_4(clknode_get_device(_clk), off, val)
+#define RD4(_clk, off, val) \
+ CLKDEV_READ_4(clknode_get_device(_clk), off, val)
+#define MD4(_clk, off, clr, set ) \
+ CLKDEV_MODIFY_4(clknode_get_device(_clk), off, clr, set)
+#define DEVICE_LOCK(_clk) \
+ CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))
+#define DEVICE_UNLOCK(_clk) \
+ CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
+
+static int imx_clk_mux_init(struct clknode *clk, device_t dev);
+static int imx_clk_mux_set_mux(struct clknode *clk, int idx);
+
+struct imx_clk_mux_sc {
+ uint32_t offset;
+ uint32_t shift;
+ uint32_t mask;
+ int mux_flags;
+};
+
+static clknode_method_t imx_clk_mux_methods[] = {
+ /* Device interface */
+ CLKNODEMETHOD(clknode_init, imx_clk_mux_init),
+ CLKNODEMETHOD(clknode_set_mux, imx_clk_mux_set_mux),
+ CLKNODEMETHOD_END
+};
+DEFINE_CLASS_1(imx_clk_mux, imx_clk_mux_class, imx_clk_mux_methods,
+ sizeof(struct imx_clk_mux_sc), clknode_class);
+
+
+static int
+imx_clk_mux_init(struct clknode *clk, device_t dev)
+{
+ uint32_t reg;
+ struct imx_clk_mux_sc *sc;
+ int rv;
+
+ sc = clknode_get_softc(clk);
+
+ DEVICE_LOCK(clk);
+ rv = RD4(clk, sc->offset, &reg);
+ DEVICE_UNLOCK(clk);
+ if (rv != 0) {
+ return (rv);
+ }
+ reg = (reg >> sc->shift) & sc->mask;
+ clknode_init_parent_idx(clk, reg);
+ return(0);
+}
+
+static int
+imx_clk_mux_set_mux(struct clknode *clk, int idx)
+{
+ uint32_t reg;
+ struct imx_clk_mux_sc *sc;
+ int rv;
+
+ sc = clknode_get_softc(clk);
+
+ DEVICE_LOCK(clk);
+ rv = MD4(clk, sc->offset, sc->mask << sc->shift,
+ ((idx & sc->mask) << sc->shift));
+ if (rv != 0) {
+ DEVICE_UNLOCK(clk);
+ return (rv);
+ }
+ RD4(clk, sc->offset, &reg);
+ DEVICE_UNLOCK(clk);
+
+ return(0);
+}
+
+int
+imx_clk_mux_register(struct clkdom *clkdom, struct imx_clk_mux_def *clkdef)
+{
+ struct clknode *clk;
+ struct imx_clk_mux_sc *sc;
+
+ clk = clknode_create(clkdom, &imx_clk_mux_class, &clkdef->clkdef);
+ if (clk == NULL)
+ return (1);
+
+ sc = clknode_get_softc(clk);
+ sc->offset = clkdef->offset;
+ sc->shift = clkdef->shift;
+ sc->mask = (1 << clkdef->width) - 1;
+ sc->mux_flags = clkdef->mux_flags;
+
+ clknode_register(clkdom, clk);
+ return (0);
+}
Index: sys/arm64/freescale/imx/clk/imx_clk_sscg_pll.h
===================================================================
--- /dev/null
+++ sys/arm64/freescale/imx/clk/imx_clk_sscg_pll.h
@@ -0,0 +1,42 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Oleksandr Tymoshenko <gonzo@FreeBSD.org>
+ *
+ * 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 _IMX_CLK_SSCG_PLL_H_
+#define _IMX_CLK_SSCG_PLL_H_
+
+#include <dev/extres/clk/clk.h>
+
+struct imx_clk_sscg_pll_def {
+ struct clknode_init_def clkdef;
+ uint32_t offset;
+};
+
+int imx_clk_sscg_pll_register(struct clkdom *clkdom, struct imx_clk_sscg_pll_def *clkdef);
+
+#endif /* _IMX_CLK_SSCG_PLL_H_ */
Index: sys/arm64/freescale/imx/clk/imx_clk_sscg_pll.c
===================================================================
--- /dev/null
+++ sys/arm64/freescale/imx/clk/imx_clk_sscg_pll.c
@@ -0,0 +1,195 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Oleksandr Tymoshenko <gonzo@FreeBSD.org>
+ *
+ * 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>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <dev/extres/clk/clk.h>
+
+#include <arm64/freescale/imx/clk/imx_clk_sscg_pll.h>
+
+#include "clkdev_if.h"
+
+struct imx_clk_sscg_pll_sc {
+ uint32_t offset;
+};
+
+#define WRITE4(_clk, off, val) \
+ CLKDEV_WRITE_4(clknode_get_device(_clk), off, val)
+#define READ4(_clk, off, val) \
+ CLKDEV_READ_4(clknode_get_device(_clk), off, val)
+#define DEVICE_LOCK(_clk) \
+ CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))
+#define DEVICE_UNLOCK(_clk) \
+ CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
+
+#define CFG0 0x00
+#define CFG0_PLL_LOCK (1 << 31)
+#define CFG0_PD (1 << 7)
+#define CFG0_BYPASS2 (1 << 5)
+#define CFG0_BYPASS1 (1 << 4)
+#define CFG1 0x04
+#define CFG2 0x08
+#define CFG2_DIVR1_MASK (7 << 25)
+#define CFG2_DIVR1_SHIFT 25
+#define CFG2_DIVR2_MASK (0x3f << 19)
+#define CFG2_DIVR2_SHIFT 19
+#define CFG2_DIVF1_MASK (0x3f << 13)
+#define CFG2_DIVF1_SHIFT 13
+#define CFG2_DIVF2_MASK (0x3f << 7)
+#define CFG2_DIVF2_SHIFT 7
+#define CFG2_DIV_MASK (0x3f << 1)
+#define CFG2_DIV_SHIFT 1
+
+#if 0
+#define dprintf(format, arg...) \
+ printf("%s:(%s)" format, __func__, clknode_get_name(clk), arg)
+#else
+#define dprintf(format, arg...)
+#endif
+
+static int
+imx_clk_sscg_pll_init(struct clknode *clk, device_t dev)
+{
+ struct imx_clk_sscg_pll_sc *sc;
+
+ sc = clknode_get_softc(clk);
+ if (clknode_get_parents_num(clk) > 1) {
+ device_printf(clknode_get_device(clk),
+ "error: SSCG PLL does not support more than one parent yet\n");
+ return (EINVAL);
+ }
+ clknode_init_parent_idx(clk, 0);
+
+ return (0);
+}
+
+static int
+imx_clk_sscg_pll_set_gate(struct clknode *clk, bool enable)
+{
+ struct imx_clk_sscg_pll_sc *sc;
+ uint32_t cfg0;
+ int timeout;
+
+ sc = clknode_get_softc(clk);
+
+ DEVICE_LOCK(clk);
+ READ4(clk, sc->offset + CFG0, &cfg0);
+ if (enable)
+ cfg0 &= ~(CFG0_PD);
+ else
+ cfg0 |= CFG0_PD;
+ WRITE4(clk, sc->offset + CFG0, cfg0);
+
+ /* Reading lock */
+ if (enable) {
+ for (timeout = 1000; timeout; timeout--) {
+ READ4(clk, sc->offset + CFG0, &cfg0);
+ if (cfg0 & CFG0_PLL_LOCK)
+ break;
+ DELAY(1);
+ }
+ }
+
+ DEVICE_UNLOCK(clk);
+
+ return (0);
+}
+
+static int
+imx_clk_sscg_pll_recalc(struct clknode *clk, uint64_t *freq)
+{
+ struct imx_clk_sscg_pll_sc *sc;
+ uint32_t cfg0, cfg2;
+ int divr1, divr2, divf1, divf2, div;
+
+ sc = clknode_get_softc(clk);
+
+ DEVICE_LOCK(clk);
+ READ4(clk, sc->offset + CFG0, &cfg0);
+ READ4(clk, sc->offset + CFG2, &cfg2);
+ DEVICE_UNLOCK(clk);
+
+ /* PLL is bypassed */
+ if (cfg0 & CFG0_BYPASS2)
+ return (0);
+
+ divr1 = (cfg2 & CFG2_DIVR1_MASK) >> CFG2_DIVR1_SHIFT;
+ divr2 = (cfg2 & CFG2_DIVR2_MASK) >> CFG2_DIVR2_SHIFT;
+ divf1 = (cfg2 & CFG2_DIVF1_MASK) >> CFG2_DIVF1_SHIFT;
+ divf2 = (cfg2 & CFG2_DIVF2_MASK) >> CFG2_DIVF2_SHIFT;
+ div = (cfg2 & CFG2_DIV_MASK) >> CFG2_DIV_SHIFT;
+
+ if (cfg0 & CFG0_BYPASS1) {
+ *freq = *freq / ((divr2 + 1) * (div + 1));
+ return (0);
+ }
+
+ *freq *= 2 * (divf1 + 1) * (divf2 + 1);
+ *freq /= (divr1 + 1) * (divr2 + 1) * (div + 1);
+
+ return (0);
+}
+
+static clknode_method_t imx_clk_sscg_pll_clknode_methods[] = {
+ /* Device interface */
+ CLKNODEMETHOD(clknode_init, imx_clk_sscg_pll_init),
+ CLKNODEMETHOD(clknode_set_gate, imx_clk_sscg_pll_set_gate),
+ CLKNODEMETHOD(clknode_recalc_freq, imx_clk_sscg_pll_recalc),
+ CLKNODEMETHOD_END
+};
+
+DEFINE_CLASS_1(imx_clk_sscg_pll_clknode, imx_clk_sscg_pll_clknode_class,
+ imx_clk_sscg_pll_clknode_methods, sizeof(struct imx_clk_sscg_pll_sc),
+ clknode_class);
+
+int
+imx_clk_sscg_pll_register(struct clkdom *clkdom,
+ struct imx_clk_sscg_pll_def *clkdef)
+{
+ struct clknode *clk;
+ struct imx_clk_sscg_pll_sc *sc;
+
+ clk = clknode_create(clkdom, &imx_clk_sscg_pll_clknode_class,
+ &clkdef->clkdef);
+ if (clk == NULL)
+ return (1);
+
+ sc = clknode_get_softc(clk);
+
+ sc->offset = clkdef->offset;
+
+ clknode_register(clkdom, clk);
+
+ return (0);
+}
Index: sys/arm64/freescale/imx/imx7gpc.c
===================================================================
--- /dev/null
+++ sys/arm64/freescale/imx/imx7gpc.c
@@ -0,0 +1,263 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Oleksandr Tymoshenko <gonzo@FreeBSD.org>
+ *
+ * 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/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/proc.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "pic_if.h"
+
+struct imx7gpc_softc {
+ device_t dev;
+ struct resource *memres;
+ device_t parent;
+};
+
+static struct ofw_compat_data compat_data[] = {
+ { "fsl,imx7gpc", 1},
+ { "fsl,imx8mq-gpc", 1},
+ { NULL, 0}
+};
+
+static inline uint32_t
+imx7gpc_read_4(struct imx7gpc_softc *sc, int reg)
+{
+
+ return (bus_read_4(sc->memres, reg));
+}
+
+static inline void
+imx7gpc_write_4(struct imx7gpc_softc *sc, int reg, uint32_t val)
+{
+
+ bus_write_4(sc->memres, reg, val);
+}
+
+static int
+imx7gpc_activate_intr(device_t dev, struct intr_irqsrc *isrc,
+ struct resource *res, struct intr_map_data *data)
+{
+ struct imx7gpc_softc *sc = device_get_softc(dev);
+
+ return (PIC_ACTIVATE_INTR(sc->parent, isrc, res, data));
+}
+
+static void
+imx7gpc_disable_intr(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct imx7gpc_softc *sc = device_get_softc(dev);
+
+ PIC_DISABLE_INTR(sc->parent, isrc);
+}
+
+static void
+imx7gpc_enable_intr(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct imx7gpc_softc *sc = device_get_softc(dev);
+
+ PIC_ENABLE_INTR(sc->parent, isrc);
+}
+
+static int
+imx7gpc_map_intr(device_t dev, struct intr_map_data *data,
+ struct intr_irqsrc **isrcp)
+{
+ struct imx7gpc_softc *sc = device_get_softc(dev);
+
+ return (PIC_MAP_INTR(sc->parent, data, isrcp));
+}
+
+static int
+imx7gpc_deactivate_intr(device_t dev, struct intr_irqsrc *isrc,
+ struct resource *res, struct intr_map_data *data)
+{
+ struct imx7gpc_softc *sc = device_get_softc(dev);
+
+ return (PIC_DEACTIVATE_INTR(sc->parent, isrc, res, data));
+}
+
+static int
+imx7gpc_setup_intr(device_t dev, struct intr_irqsrc *isrc,
+ struct resource *res, struct intr_map_data *data)
+{
+ struct imx7gpc_softc *sc = device_get_softc(dev);
+
+ return (PIC_SETUP_INTR(sc->parent, isrc, res, data));
+}
+
+static int
+imx7gpc_teardown_intr(device_t dev, struct intr_irqsrc *isrc,
+ struct resource *res, struct intr_map_data *data)
+{
+ struct imx7gpc_softc *sc = device_get_softc(dev);
+
+ return (PIC_TEARDOWN_INTR(sc->parent, isrc, res, data));
+}
+
+static void
+imx7gpc_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct imx7gpc_softc *sc = device_get_softc(dev);
+
+ PIC_PRE_ITHREAD(sc->parent, isrc);
+}
+
+
+static void
+imx7gpc_post_ithread(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct imx7gpc_softc *sc = device_get_softc(dev);
+
+ PIC_POST_ITHREAD(sc->parent, isrc);
+}
+
+static void
+imx7gpc_post_filter(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct imx7gpc_softc *sc = device_get_softc(dev);
+
+ PIC_POST_FILTER(sc->parent, isrc);
+}
+
+#ifdef SMP
+static int
+imx7gpc_bind_intr(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct imx7gpc_softc *sc = device_get_softc(dev);
+
+ return (PIC_BIND_INTR(sc->parent, isrc));
+}
+#endif
+
+static int
+imx7gpc_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "General Power Controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+imx7gpc_attach(device_t dev)
+{
+ struct imx7gpc_softc *sc = device_get_softc(dev);
+ phandle_t node;
+ phandle_t parent_xref;
+ int i, rv;
+
+ sc->dev = dev;
+
+ node = ofw_bus_get_node(dev);
+
+ rv = OF_getencprop(node, "interrupt-parent", &parent_xref,
+ sizeof(parent_xref));
+ if (rv <= 0) {
+ device_printf(dev, "Can't read parent node property\n");
+ return (ENXIO);
+ }
+ sc->parent = OF_device_from_xref(parent_xref);
+ if (sc->parent == NULL) {
+ device_printf(dev, "Can't find parent controller\n");
+ return (ENXIO);
+ }
+
+
+ i = 0;
+ sc->memres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &i,
+ RF_ACTIVE);
+ if (sc->memres == NULL) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ /* TODO: power up OTG domain and unmask all interrupts */
+
+ if (intr_pic_register(dev, OF_xref_from_node(node)) == NULL) {
+ bus_release_resource(dev, SYS_RES_MEMORY, i, sc->memres);
+ device_printf(dev, "Cannot register PIC\n");
+ return (ENXIO);
+ }
+
+ return (0);
+}
+
+static device_method_t imx7gpc_methods[] = {
+ DEVMETHOD(device_probe, imx7gpc_probe),
+ DEVMETHOD(device_attach, imx7gpc_attach),
+
+ /* Interrupt controller interface */
+ DEVMETHOD(pic_activate_intr, imx7gpc_activate_intr),
+ DEVMETHOD(pic_disable_intr, imx7gpc_disable_intr),
+ DEVMETHOD(pic_enable_intr, imx7gpc_enable_intr),
+ DEVMETHOD(pic_map_intr, imx7gpc_map_intr),
+ DEVMETHOD(pic_deactivate_intr, imx7gpc_deactivate_intr),
+ DEVMETHOD(pic_setup_intr, imx7gpc_setup_intr),
+ DEVMETHOD(pic_teardown_intr, imx7gpc_teardown_intr),
+ DEVMETHOD(pic_pre_ithread, imx7gpc_pre_ithread),
+ DEVMETHOD(pic_post_ithread, imx7gpc_post_ithread),
+ DEVMETHOD(pic_post_filter, imx7gpc_post_filter),
+#ifdef SMP
+ DEVMETHOD(pic_bind_intr, imx7gpc_bind_intr),
+#endif
+
+ DEVMETHOD_END
+};
+
+static driver_t imx7gpc_driver = {
+ "imx7gpc",
+ imx7gpc_methods,
+ sizeof(struct imx7gpc_softc),
+};
+
+static devclass_t imx7gpc_devclass;
+
+EARLY_DRIVER_MODULE(imx7gpc, ofwbus, imx7gpc_driver, imx7gpc_devclass, 0, 0,
+ BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
+EARLY_DRIVER_MODULE(imx7gpc, simplebus, imx7gpc_driver, imx7gpc_devclass, 0, 0,
+ BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
Index: sys/arm64/freescale/imx/imx8mq_ccm.h
===================================================================
--- /dev/null
+++ sys/arm64/freescale/imx/imx8mq_ccm.h
@@ -0,0 +1,173 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Oleksandr Tymoshenko <gonzo@FreeBSD.org>
+ *
+ * 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 __IMX8MQ_CCM_H__
+#define __IMX8MQ_CCM_H__
+
+#define IMX8MQ_CLK_DUMMY 0
+#define IMX8MQ_CLK_32K 1
+#define IMX8MQ_CLK_25M 2
+#define IMX8MQ_CLK_27M 3
+#define IMX8MQ_CLK_EXT1 4
+#define IMX8MQ_CLK_EXT2 5
+#define IMX8MQ_CLK_EXT3 6
+#define IMX8MQ_CLK_EXT4 7
+
+#define IMX8MQ_ARM_PLL_REF_SEL 8
+#define IMX8MQ_ARM_PLL_REF_DIV 9
+#define IMX8MQ_ARM_PLL 10
+#define IMX8MQ_ARM_PLL_BYPASS 11
+#define IMX8MQ_ARM_PLL_OUT 12
+
+#define IMX8MQ_GPU_PLL_REF_SEL 13
+#define IMX8MQ_GPU_PLL_REF_DIV 14
+#define IMX8MQ_GPU_PLL 15
+#define IMX8MQ_GPU_PLL_BYPASS 16
+#define IMX8MQ_GPU_PLL_OUT 17
+
+#define IMX8MQ_VPU_PLL_REF_SEL 18
+#define IMX8MQ_VPU_PLL_REF_DIV 19
+#define IMX8MQ_VPU_PLL 20
+#define IMX8MQ_VPU_PLL_BYPASS 21
+#define IMX8MQ_VPU_PLL_OUT 22
+
+#define IMX8MQ_AUDIO_PLL1_REF_SEL 23
+#define IMX8MQ_AUDIO_PLL1_REF_DIV 24
+#define IMX8MQ_AUDIO_PLL1 25
+#define IMX8MQ_AUDIO_PLL1_BYPASS 26
+#define IMX8MQ_AUDIO_PLL1_OUT 27
+
+#define IMX8MQ_AUDIO_PLL2_REF_SEL 28
+#define IMX8MQ_AUDIO_PLL2_REF_DIV 29
+#define IMX8MQ_AUDIO_PLL2 30
+#define IMX8MQ_AUDIO_PLL2_BYPASS 31
+#define IMX8MQ_AUDIO_PLL2_OUT 32
+
+#define IMX8MQ_VIDEO_PLL1_REF_SEL 33
+#define IMX8MQ_VIDEO_PLL1_REF_DIV 34
+#define IMX8MQ_VIDEO_PLL1 35
+#define IMX8MQ_VIDEO_PLL1_BYPASS 36
+#define IMX8MQ_VIDEO_PLL1_OUT 37
+
+#define IMX8MQ_SYS3_PLL1_REF_SEL 54
+#define IMX8MQ_SYS3_PLL1 56
+
+#define IMX8MQ_DRAM_PLL1_REF_SEL 62
+
+#define IMX8MQ_SYS1_PLL_40M 70
+#define IMX8MQ_SYS1_PLL_80M 71
+#define IMX8MQ_SYS1_PLL_100M 72
+#define IMX8MQ_SYS1_PLL_133M 73
+#define IMX8MQ_SYS1_PLL_160M 74
+#define IMX8MQ_SYS1_PLL_200M 75
+#define IMX8MQ_SYS1_PLL_266M 76
+#define IMX8MQ_SYS1_PLL_400M 77
+#define IMX8MQ_SYS1_PLL_800M 78
+
+#define IMX8MQ_SYS2_PLL_50M 79
+#define IMX8MQ_SYS2_PLL_100M 80
+#define IMX8MQ_SYS2_PLL_125M 81
+#define IMX8MQ_SYS2_PLL_166M 82
+#define IMX8MQ_SYS2_PLL_200M 83
+#define IMX8MQ_SYS2_PLL_250M 84
+#define IMX8MQ_SYS2_PLL_333M 85
+#define IMX8MQ_SYS2_PLL_500M 86
+#define IMX8MQ_SYS2_PLL_1000M 87
+
+#define IMX8MQ_CLK_ENET_AXI 104
+#define IMX8MQ_CLK_USB_BUS 110
+
+#define IMX8MQ_CLK_AHB 116
+
+#define IMX8MQ_CLK_ENET_REF 137
+#define IMX8MQ_CLK_ENET_TIMER 138
+#define IMX8MQ_CLK_ENET_PHY_REF 139
+#define IMX8MQ_CLK_USDHC1 142
+#define IMX8MQ_CLK_USDHC2 143
+#define IMX8MQ_CLK_I2C1 144
+#define IMX8MQ_CLK_I2C2 145
+#define IMX8MQ_CLK_I2C3 146
+#define IMX8MQ_CLK_I2C4 147
+#define IMX8MQ_CLK_UART1 148
+#define IMX8MQ_CLK_UART2 149
+#define IMX8MQ_CLK_UART3 150
+#define IMX8MQ_CLK_UART4 151
+#define IMX8MQ_CLK_USB_CORE_REF 152
+#define IMX8MQ_CLK_USB_PHY_REF 153
+
+#define IMX8MQ_CLK_ENET1_ROOT 182
+#define IMX8MQ_CLK_I2C1_ROOT 184
+#define IMX8MQ_CLK_I2C2_ROOT 185
+#define IMX8MQ_CLK_I2C3_ROOT 186
+#define IMX8MQ_CLK_I2C4_ROOT 187
+#define IMX8MQ_CLK_UART1_ROOT 202
+#define IMX8MQ_CLK_UART2_ROOT 203
+#define IMX8MQ_CLK_UART3_ROOT 204
+#define IMX8MQ_CLK_UART4_ROOT 205
+#define IMX8MQ_CLK_USB1_CTRL_ROOT 206
+#define IMX8MQ_CLK_USB2_CTRL_ROOT 207
+#define IMX8MQ_CLK_USB1_PHY_ROOT 208
+#define IMX8MQ_CLK_USB2_PHY_ROOT 209
+#define IMX8MQ_CLK_USDHC1_ROOT 210
+#define IMX8MQ_CLK_USDHC2_ROOT 211
+
+#define IMX8MQ_SYS1_PLL_OUT 231
+#define IMX8MQ_SYS2_PLL_OUT 232
+#define IMX8MQ_SYS3_PLL_OUT 233
+
+#define IMX8MQ_CLK_IPG_ROOT 236
+
+#define IMX8MQ_CLK_GPIO1_ROOT 259
+#define IMX8MQ_CLK_GPIO2_ROOT 260
+#define IMX8MQ_CLK_GPIO3_ROOT 261
+#define IMX8MQ_CLK_GPIO4_ROOT 262
+#define IMX8MQ_CLK_GPIO5_ROOT 263
+
+#define IMX8MQ_VIDEO2_PLL1_REF_SEL 266
+
+#define IMX8MQ_SYS1_PLL_40M_CG 267
+#define IMX8MQ_SYS1_PLL_80M_CG 268
+#define IMX8MQ_SYS1_PLL_100M_CG 269
+#define IMX8MQ_SYS1_PLL_133M_CG 270
+#define IMX8MQ_SYS1_PLL_160M_CG 271
+#define IMX8MQ_SYS1_PLL_200M_CG 272
+#define IMX8MQ_SYS1_PLL_266M_CG 273
+#define IMX8MQ_SYS1_PLL_400M_CG 274
+#define IMX8MQ_SYS1_PLL_800M_CG 275
+#define IMX8MQ_SYS2_PLL_50M_CG 276
+#define IMX8MQ_SYS2_PLL_100M_CG 277
+#define IMX8MQ_SYS2_PLL_125M_CG 278
+#define IMX8MQ_SYS2_PLL_166M_CG 279
+#define IMX8MQ_SYS2_PLL_200M_CG 280
+#define IMX8MQ_SYS2_PLL_250M_CG 281
+#define IMX8MQ_SYS2_PLL_333M_CG 282
+#define IMX8MQ_SYS2_PLL_500M_CG 283
+#define IMX8MQ_SYS2_PLL_1000M_CG 284
+
+#endif
Index: sys/arm64/freescale/imx/imx8mq_ccm.c
===================================================================
--- /dev/null
+++ sys/arm64/freescale/imx/imx8mq_ccm.c
@@ -0,0 +1,484 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Oleksandr Tymoshenko <gonzo@FreeBSD.org>
+ *
+ * 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$");
+
+/*
+ * Clocks driver for Freescale i.MX8MQ SoC
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <machine/bus.h>
+
+#include <arm64/freescale/imx/imx_ccm_clk.h>
+#include <arm64/freescale/imx/imx8mq_ccm.h>
+#include <arm64/freescale/imx/clk/imx_clk_gate.h>
+#include <arm64/freescale/imx/clk/imx_clk_mux.h>
+#include <arm64/freescale/imx/clk/imx_clk_composite.h>
+#include <arm64/freescale/imx/clk/imx_clk_sscg_pll.h>
+#include <arm64/freescale/imx/clk/imx_clk_frac_pll.h>
+
+#include "clkdev_if.h"
+
+static const char *pll_ref_p[] = {
+ "osc_25m", "osc_27m", "dummy", "dummy"
+};
+static const char *sys3_pll_out_p[] = {
+ "sys3_pll1_ref_sel"
+};
+static const char * arm_pll_bypass_p[] = {
+ "arm_pll", "arm_pll_ref_sel"
+};
+static const char * gpu_pll_bypass_p[] = {
+ "gpu_pll", "gpu_pll_ref_sel"
+};
+static const char * vpu_pll_bypass_p[] = {
+ "vpu_pll", "vpu_pll_ref_sel"
+};
+static const char * audio_pll1_bypass_p[] = {
+ "audio_pll1", "audio_pll1_ref_sel"
+};
+static const char * audio_pll2_bypass_p[] = {
+ "audio_pll2", "audio_pll2_ref_sel"
+};
+static const char * video_pll1_bypass_p[] = {
+ "video_pll1", "video_pll1_ref_sel"
+};
+static const char *uart_p[] = {
+ "osc_25m", "sys1_pll_80m", "sys2_pll_200m", "sys2_pll_100m", "sys3_pll_out",
+ "clk_ext2", "clk_ext4", "audio_pll2_out"
+};
+static const char *usdhc_p[] = {
+ "osc_25m", "sys1_pll_400m", "sys1_pll_800m", "sys2_pll_500m", "audio_pll2_out",
+ "sys1_pll_266m", "sys3_pll_out", "sys1_pll_100m"
+};
+static const char *enet_axi_p[] = {
+ "osc_25m", "sys1_pll_266m", "sys1_pll_800m", "sys2_pll_250m", "sys2_pll_200m",
+ "audio_pll1_out", "video_pll1_out", "sys3_pll_out"
+};
+static const char *enet_ref_p[] = {
+ "osc_25m", "sys2_pll_125m", "sys2_pll_500m", "sys2_pll_100m", "sys1_pll_160m",
+ "audio_pll1_out", "video_pll1_out", "clk_ext4"
+};
+static const char *enet_timer_p[] = {
+ "osc_25m", "sys2_pll_100m", "audio_pll1_out", "clk_ext1", "clk_ext2", "clk_ext3",
+ "clk_ext4", "video_pll1_out"
+};
+static const char *enet_phy_ref_p[] = {
+ "osc_25m", "sys2_pll_50m", "sys2_pll_125m", "sys2_pll_500m", "audio_pll1_out",
+ "video_pll1_out", "audio_pll2_out"
+};
+static const char *usb_bus_p[] = {
+ "osc_25m", "sys2_pll_500m", "sys1_pll_800m", "sys2_pll_100m", "sys2_pll_200m",
+ "clk_ext2", "clk_ext4", "audio_pll2_out"
+};
+static const char *usb_core_phy_p[] = {
+ "osc_25m", "sys1_pll_100m", "sys1_pll_40m", "sys2_pll_100m", "sys2_pll_200m",
+ "clk_ext2", "clk_ext3", "audio_pll2_out"
+};
+static const char *i2c_p[] = {
+ "osc_25m", "sys1_pll_160m", "sys2_pll_50m", "sys3_pll_out", "audio_pll1_out",
+ "video_pll1_out", "audio_pll2_out", "sys1_pll_133m"
+};
+static const char *ahb_p[] = {
+ "osc_25m", "sys1_pll_133m", "sys1_pll_800m", "sys1_pll_400m", "sys2_pll_125m",
+ "sys3_pll_out", "audio_pll1_out", "video_pll1_out"
+};
+
+static struct imx_clk imx_clks[] = {
+ FIXED(IMX8MQ_CLK_DUMMY, "dummy", 0),
+
+ LINK(IMX8MQ_CLK_32K, "ckil"),
+ LINK(IMX8MQ_CLK_25M, "osc_25m"),
+ LINK(IMX8MQ_CLK_27M, "osc_27m"),
+ LINK(IMX8MQ_CLK_EXT1, "clk_ext1"),
+ LINK(IMX8MQ_CLK_EXT2, "clk_ext2"),
+ LINK(IMX8MQ_CLK_EXT3, "clk_ext3"),
+ LINK(IMX8MQ_CLK_EXT4, "clk_ext4"),
+
+ FIXED(IMX8MQ_SYS1_PLL_OUT, "sys1_pll_out", 800000000),
+ FIXED(IMX8MQ_SYS2_PLL_OUT, "sys2_pll_out", 1000000000),
+ SSCG_PLL(IMX8MQ_SYS3_PLL_OUT, "sys3_pll_out", sys3_pll_out_p, 0x48),
+
+ MUX(IMX8MQ_ARM_PLL_REF_SEL, "arm_pll_ref_sel", pll_ref_p, 0, 0x28, 16, 2),
+ MUX(IMX8MQ_GPU_PLL_REF_SEL, "gpu_pll_ref_sel", pll_ref_p, 0, 0x18, 16, 2),
+ MUX(IMX8MQ_VPU_PLL_REF_SEL, "vpu_pll_ref_sel", pll_ref_p, 0, 0x20, 16, 2),
+ MUX(IMX8MQ_AUDIO_PLL1_REF_SEL, "audio_pll1_ref_sel", pll_ref_p, 0, 0x0, 16, 2),
+ MUX(IMX8MQ_AUDIO_PLL2_REF_SEL, "audio_pll2_ref_sel", pll_ref_p, 0, 0x8, 16, 2),
+ MUX(IMX8MQ_VIDEO_PLL1_REF_SEL, "video_pll1_ref_sel", pll_ref_p, 0, 0x10, 16, 2),
+ MUX(IMX8MQ_SYS3_PLL1_REF_SEL, "sys3_pll1_ref_sel", pll_ref_p, 0, 0x48, 0, 2),
+ MUX(IMX8MQ_DRAM_PLL1_REF_SEL, "dram_pll1_ref_sel", pll_ref_p, 0, 0x60, 0, 2),
+ MUX(IMX8MQ_VIDEO2_PLL1_REF_SEL, "video2_pll1_ref_sel", pll_ref_p, 0, 0x54, 0, 2),
+
+ DIV(IMX8MQ_ARM_PLL_REF_DIV, "arm_pll_ref_div", "arm_pll_ref_sel", 0x28, 5, 6),
+ DIV(IMX8MQ_GPU_PLL_REF_DIV, "gpu_pll_ref_div", "gpu_pll_ref_sel", 0x18, 5, 6),
+ DIV(IMX8MQ_VPU_PLL_REF_DIV, "vpu_pll_ref_div", "vpu_pll_ref_sel", 0x20, 5, 6),
+ DIV(IMX8MQ_AUDIO_PLL1_REF_DIV, "audio_pll1_ref_div", "audio_pll1_ref_sel", 0x0, 5, 6),
+ DIV(IMX8MQ_AUDIO_PLL2_REF_DIV, "audio_pll2_ref_div", "audio_pll2_ref_sel", 0x8, 5, 6),
+ DIV(IMX8MQ_VIDEO_PLL1_REF_DIV, "video_pll1_ref_div", "video_pll1_ref_sel", 0x10, 5, 6),
+
+ FRAC_PLL(IMX8MQ_ARM_PLL, "arm_pll", "arm_pll_ref_div", 0x28),
+ FRAC_PLL(IMX8MQ_GPU_PLL, "gpu_pll", "gpu_pll_ref_div", 0x18),
+ FRAC_PLL(IMX8MQ_VPU_PLL, "vpu_pll", "vpu_pll_ref_div", 0x20),
+ FRAC_PLL(IMX8MQ_AUDIO_PLL1, "audio_pll1", "audio_pll1_ref_div", 0x0),
+ FRAC_PLL(IMX8MQ_AUDIO_PLL2, "audio_pll2", "audio_pll2_ref_div", 0x8),
+ FRAC_PLL(IMX8MQ_VIDEO_PLL1, "video_pll1", "video_pll1_ref_div", 0x10),
+
+ /* ARM_PLL needs SET_PARENT flag */
+ MUX(IMX8MQ_ARM_PLL_BYPASS, "arm_pll_bypass", arm_pll_bypass_p, 0, 0x28, 14, 1),
+ MUX(IMX8MQ_GPU_PLL_BYPASS, "gpu_pll_bypass", gpu_pll_bypass_p, 0, 0x18, 14, 1),
+ MUX(IMX8MQ_VPU_PLL_BYPASS, "vpu_pll_bypass", vpu_pll_bypass_p, 0, 0x20, 14, 1),
+ MUX(IMX8MQ_AUDIO_PLL1_BYPASS, "audio_pll1_bypass", audio_pll1_bypass_p, 0, 0x0, 14, 1),
+ MUX(IMX8MQ_AUDIO_PLL2_BYPASS, "audio_pll2_bypass", audio_pll2_bypass_p, 0, 0x8, 14, 1),
+ MUX(IMX8MQ_VIDEO_PLL1_BYPASS, "video_pll1_bypass", video_pll1_bypass_p, 0, 0x10, 14, 1),
+
+ GATE(IMX8MQ_ARM_PLL_OUT, "arm_pll_out", "arm_pll_bypass", 0x28, 21),
+ GATE(IMX8MQ_GPU_PLL_OUT, "gpu_pll_out", "gpu_pll_bypass", 0x18, 21),
+ GATE(IMX8MQ_VPU_PLL_OUT, "vpu_pll_out", "vpu_pll_bypass", 0x20, 21),
+ GATE(IMX8MQ_AUDIO_PLL1_OUT, "audio_pll1_out", "audio_pll1_bypass", 0x0, 21),
+ GATE(IMX8MQ_AUDIO_PLL2_OUT, "audio_pll2_out", "audio_pll2_bypass", 0x8, 21),
+ GATE(IMX8MQ_VIDEO_PLL1_OUT, "video_pll1_out", "video_pll1_bypass", 0x10, 21),
+
+ GATE(IMX8MQ_SYS1_PLL_40M_CG, "sys1_pll_40m_cg", "sys1_pll_out", 0x30, 9),
+ GATE(IMX8MQ_SYS1_PLL_80M_CG, "sys1_pll_80m_cg", "sys1_pll_out", 0x30, 11),
+ GATE(IMX8MQ_SYS1_PLL_100M_CG, "sys1_pll_100m_cg", "sys1_pll_out", 0x30, 13),
+ GATE(IMX8MQ_SYS1_PLL_133M_CG, "sys1_pll_133m_cg", "sys1_pll_out", 0x30, 15),
+ GATE(IMX8MQ_SYS1_PLL_160M_CG, "sys1_pll_160m_cg", "sys1_pll_out", 0x30, 17),
+ GATE(IMX8MQ_SYS1_PLL_200M_CG, "sys1_pll_200m_cg", "sys1_pll_out", 0x30, 19),
+ GATE(IMX8MQ_SYS1_PLL_266M_CG, "sys1_pll_266m_cg", "sys1_pll_out", 0x30, 21),
+ GATE(IMX8MQ_SYS1_PLL_400M_CG, "sys1_pll_400m_cg", "sys1_pll_out", 0x30, 23),
+ GATE(IMX8MQ_SYS1_PLL_800M_CG, "sys1_pll_800m_cg", "sys1_pll_out", 0x30, 25),
+
+ FFACT(IMX8MQ_SYS1_PLL_40M, "sys1_pll_40m", "sys1_pll_40m_cg", 1, 20),
+ FFACT(IMX8MQ_SYS1_PLL_80M, "sys1_pll_80m", "sys1_pll_80m_cg", 1, 10),
+ FFACT(IMX8MQ_SYS1_PLL_100M, "sys1_pll_100m", "sys1_pll_100m_cg", 1, 8),
+ FFACT(IMX8MQ_SYS1_PLL_133M, "sys1_pll_133m", "sys1_pll_133m_cg", 1, 6),
+ FFACT(IMX8MQ_SYS1_PLL_160M, "sys1_pll_160m", "sys1_pll_160m_cg", 1, 5),
+ FFACT(IMX8MQ_SYS1_PLL_200M, "sys1_pll_200m", "sys1_pll_200m_cg", 1, 4),
+ FFACT(IMX8MQ_SYS1_PLL_266M, "sys1_pll_266m", "sys1_pll_266m_cg", 1, 3),
+ FFACT(IMX8MQ_SYS1_PLL_400M, "sys1_pll_400m", "sys1_pll_400m_cg", 1, 2),
+ FFACT(IMX8MQ_SYS1_PLL_800M, "sys1_pll_800m", "sys1_pll_800m_cg", 1, 1),
+
+ GATE(IMX8MQ_SYS2_PLL_50M_CG, "sys2_pll_50m_cg", "sys2_pll_out", 0x3c, 9),
+ GATE(IMX8MQ_SYS2_PLL_100M_CG, "sys2_pll_100m_cg", "sys2_pll_out", 0x3c, 11),
+ GATE(IMX8MQ_SYS2_PLL_125M_CG, "sys2_pll_125m_cg", "sys2_pll_out", 0x3c, 13),
+ GATE(IMX8MQ_SYS2_PLL_166M_CG, "sys2_pll_166m_cg", "sys2_pll_out", 0x3c, 15),
+ GATE(IMX8MQ_SYS2_PLL_200M_CG, "sys2_pll_200m_cg", "sys2_pll_out", 0x3c, 17),
+ GATE(IMX8MQ_SYS2_PLL_250M_CG, "sys2_pll_250m_cg", "sys2_pll_out", 0x3c, 19),
+ GATE(IMX8MQ_SYS2_PLL_333M_CG, "sys2_pll_333m_cg", "sys2_pll_out", 0x3c, 21),
+ GATE(IMX8MQ_SYS2_PLL_500M_CG, "sys2_pll_500m_cg", "sys2_pll_out", 0x3c, 23),
+ GATE(IMX8MQ_SYS2_PLL_1000M_CG, "sys2_pll_1000m_cg", "sys2_pll_out", 0x3c, 25),
+
+ FFACT(IMX8MQ_SYS2_PLL_50M, "sys2_pll_50m", "sys2_pll_50m_cg", 1, 20),
+ FFACT(IMX8MQ_SYS2_PLL_100M, "sys2_pll_100m", "sys2_pll_100m_cg", 1, 10),
+ FFACT(IMX8MQ_SYS2_PLL_125M, "sys2_pll_125m", "sys2_pll_125m_cg", 1, 8),
+ FFACT(IMX8MQ_SYS2_PLL_166M, "sys2_pll_166m", "sys2_pll_166m_cg", 1, 6),
+ FFACT(IMX8MQ_SYS2_PLL_200M, "sys2_pll_200m", "sys2_pll_200m_cg", 1, 5),
+ FFACT(IMX8MQ_SYS2_PLL_250M, "sys2_pll_250m", "sys2_pll_250m_cg", 1, 4),
+ FFACT(IMX8MQ_SYS2_PLL_333M, "sys2_pll_333m", "sys2_pll_333m_cg", 1, 3),
+ FFACT(IMX8MQ_SYS2_PLL_500M, "sys2_pll_500m", "sys2_pll_500m_cg", 1, 2),
+ FFACT(IMX8MQ_SYS2_PLL_1000M, "sys2_pll_1000m", "sys2_pll_1000m_cg", 1, 1),
+
+ COMPOSITE(IMX8MQ_CLK_AHB, "ahb", ahb_p, 0x9000, 0),
+ DIV(IMX8MQ_CLK_IPG_ROOT, "ipg_root", "ahb", 0x9080, 0, 1),
+
+ COMPOSITE(IMX8MQ_CLK_UART1, "uart1", uart_p, 0xaf00, 0),
+ COMPOSITE(IMX8MQ_CLK_UART2, "uart2", uart_p, 0xaf80, 0),
+ COMPOSITE(IMX8MQ_CLK_UART3, "uart3", uart_p, 0xb000, 0),
+ COMPOSITE(IMX8MQ_CLK_UART4, "uart4", uart_p, 0xb080, 0),
+
+ ROOT_GATE(IMX8MQ_CLK_UART1_ROOT, "uart1_root_clk", "uart1", 0x4490),
+ ROOT_GATE(IMX8MQ_CLK_UART2_ROOT, "uart2_root_clk", "uart2", 0x44a0),
+ ROOT_GATE(IMX8MQ_CLK_UART3_ROOT, "uart3_root_clk", "uart3", 0x44b0),
+ ROOT_GATE(IMX8MQ_CLK_UART4_ROOT, "uart4_root_clk", "uart4", 0x44c0),
+
+ COMPOSITE(IMX8MQ_CLK_USDHC1, "usdhc1", usdhc_p, 0xac00, CLK_SET_ROUND_DOWN),
+ COMPOSITE(IMX8MQ_CLK_USDHC2, "usdhc2", usdhc_p, 0xac80, CLK_SET_ROUND_DOWN),
+
+ ROOT_GATE(IMX8MQ_CLK_USDHC1_ROOT, "usdhc1_root_clk", "usdhc1", 0x4510),
+ ROOT_GATE(IMX8MQ_CLK_USDHC2_ROOT, "usdhc2_root_clk", "usdhc2", 0x4520),
+
+ COMPOSITE(IMX8MQ_CLK_ENET_AXI, "enet_axi", enet_axi_p, 0x8800, 0),
+ COMPOSITE(IMX8MQ_CLK_ENET_REF, "enet_ref", enet_ref_p, 0xa980, 0),
+ COMPOSITE(IMX8MQ_CLK_ENET_TIMER, "enet_timer", enet_timer_p, 0xaa00, 0),
+ COMPOSITE(IMX8MQ_CLK_ENET_PHY_REF, "enet_phy_ref", enet_phy_ref_p, 0xaa80, 0),
+
+ ROOT_GATE(IMX8MQ_CLK_ENET1_ROOT, "enet1_root_clk", "enet_axi", 0x40a0),
+
+ COMPOSITE(IMX8MQ_CLK_USB_BUS, "usb_bus", usb_bus_p, 0x8b80, 0),
+ COMPOSITE(IMX8MQ_CLK_USB_CORE_REF, "usb_core_ref", usb_core_phy_p, 0xb100, 0),
+ COMPOSITE(IMX8MQ_CLK_USB_PHY_REF, "usb_phy_ref", usb_core_phy_p, 0xb180, 0),
+
+ ROOT_GATE(IMX8MQ_CLK_USB1_CTRL_ROOT, "usb1_ctrl_root_clk", "usb_bus", 0x44d0),
+ ROOT_GATE(IMX8MQ_CLK_USB2_CTRL_ROOT, "usb2_ctrl_root_clk", "usb_bus", 0x44e0),
+ ROOT_GATE(IMX8MQ_CLK_USB1_PHY_ROOT, "usb1_phy_root_clk", "usb_phy_ref", 0x44f0),
+ ROOT_GATE(IMX8MQ_CLK_USB2_PHY_ROOT, "usb2_phy_root_clk", "usb_phy_ref", 0x4500),
+
+ COMPOSITE(IMX8MQ_CLK_I2C1, "i2c1", i2c_p, 0xad00, 0),
+ COMPOSITE(IMX8MQ_CLK_I2C2, "i2c2", i2c_p, 0xad80, 0),
+ COMPOSITE(IMX8MQ_CLK_I2C3, "i2c3", i2c_p, 0xae00, 0),
+ COMPOSITE(IMX8MQ_CLK_I2C4, "i2c4", i2c_p, 0xae80, 0),
+
+ ROOT_GATE(IMX8MQ_CLK_I2C1_ROOT, "i2c1_root_clk", "i2c1", 0x4170),
+ ROOT_GATE(IMX8MQ_CLK_I2C2_ROOT, "i2c2_root_clk", "i2c2", 0x4180),
+ ROOT_GATE(IMX8MQ_CLK_I2C3_ROOT, "i2c3_root_clk", "i2c3", 0x4190),
+ ROOT_GATE(IMX8MQ_CLK_I2C4_ROOT, "i2c4_root_clk", "i2c4", 0x41a0),
+
+ ROOT_GATE(IMX8MQ_CLK_GPIO1_ROOT, "gpio1_root_clk", "ipg_root", 0x40b0),
+ ROOT_GATE(IMX8MQ_CLK_GPIO2_ROOT, "gpio2_root_clk", "ipg_root", 0x40c0),
+ ROOT_GATE(IMX8MQ_CLK_GPIO3_ROOT, "gpio3_root_clk", "ipg_root", 0x40d0),
+ ROOT_GATE(IMX8MQ_CLK_GPIO4_ROOT, "gpio4_root_clk", "ipg_root", 0x40e0),
+ ROOT_GATE(IMX8MQ_CLK_GPIO5_ROOT, "gpio5_root_clk", "ipg_root", 0x40f0),
+};
+
+struct ccm_softc {
+ device_t dev;
+ struct resource *mem_res;
+ struct clkdom *clkdom;
+ struct mtx mtx;
+ struct imx_clk *clks;
+ int nclks;
+};
+
+static inline uint32_t
+CCU_READ4(struct ccm_softc *sc, bus_size_t off)
+{
+
+ return (bus_read_4(sc->mem_res, off));
+}
+
+static inline void
+CCU_WRITE4(struct ccm_softc *sc, bus_size_t off, uint32_t val)
+{
+
+ bus_write_4(sc->mem_res, off, val);
+}
+
+static int
+ccm_detach(device_t dev)
+{
+ struct ccm_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ if (sc->mem_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
+
+ return (0);
+}
+
+static int
+ccm_attach(device_t dev)
+{
+ struct ccm_softc *sc;
+ int err, rid;
+ phandle_t node;
+ int i;
+
+ sc = device_get_softc(dev);
+ err = 0;
+
+ /* Allocate bus_space resources. */
+ rid = 0;
+ sc->clks = imx_clks;
+ sc->nclks = nitems(imx_clks);
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev, "Cannot allocate memory resources\n");
+ err = ENXIO;
+ goto out;
+ }
+
+ mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+
+ sc->clkdom = clkdom_create(dev);
+ if (sc->clkdom == NULL)
+ panic("Cannot create clkdom\n");
+
+ for (i = 0; i < sc->nclks; i++) {
+ switch (sc->clks[i].type) {
+ case IMX_CLK_UNDEFINED:
+ break;
+ case IMX_CLK_LINK:
+ clknode_link_register(sc->clkdom,
+ sc->clks[i].clk.link);
+ break;
+ case IMX_CLK_FIXED:
+ clknode_fixed_register(sc->clkdom,
+ sc->clks[i].clk.fixed);
+ break;
+ case IMX_CLK_MUX:
+ imx_clk_mux_register(sc->clkdom, sc->clks[i].clk.mux);
+ break;
+ case IMX_CLK_GATE:
+ imx_clk_gate_register(sc->clkdom, sc->clks[i].clk.gate);
+ break;
+ case IMX_CLK_COMPOSITE:
+ imx_clk_composite_register(sc->clkdom, sc->clks[i].clk.composite);
+ break;
+ case IMX_CLK_SSCG_PLL:
+ imx_clk_sscg_pll_register(sc->clkdom, sc->clks[i].clk.sscg_pll);
+ break;
+ case IMX_CLK_FRAC_PLL:
+ imx_clk_frac_pll_register(sc->clkdom, sc->clks[i].clk.frac_pll);
+ break;
+ case IMX_CLK_DIV:
+ clknode_div_register(sc->clkdom, sc->clks[i].clk.div);
+ break;
+ default:
+ device_printf(dev, "Unknown clock type %d\n", sc->clks[i].type);
+ return (ENXIO);
+ }
+ }
+
+ if (clkdom_finit(sc->clkdom) != 0)
+ panic("cannot finalize clkdom initialization\n");
+
+ if (bootverbose)
+ clkdom_dump(sc->clkdom);
+
+ node = ofw_bus_get_node(dev);
+ clk_set_assigned(dev, node);
+
+ err = 0;
+
+out:
+
+ if (err != 0)
+ ccm_detach(dev);
+
+ return (err);
+}
+
+static int
+ccm_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_is_compatible(dev, "fsl,imx8mq-ccm") == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "Freescale i.MX8 Clock Control Module");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+imx_ccm_write_4(device_t dev, bus_addr_t addr, uint32_t val)
+{
+ struct ccm_softc *sc;
+
+ sc = device_get_softc(dev);
+ CCU_WRITE4(sc, addr, val);
+ return (0);
+}
+
+static int
+imx_ccm_read_4(device_t dev, bus_addr_t addr, uint32_t *val)
+{
+ struct ccm_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ *val = CCU_READ4(sc, addr);
+ return (0);
+}
+
+static int
+imx_ccm_modify_4(device_t dev, bus_addr_t addr, uint32_t clr, uint32_t set)
+{
+ struct ccm_softc *sc;
+ uint32_t reg;
+
+ sc = device_get_softc(dev);
+
+ reg = CCU_READ4(sc, addr);
+ reg &= ~clr;
+ reg |= set;
+ CCU_WRITE4(sc, addr, reg);
+
+ return (0);
+}
+
+static void
+imx_ccm_device_lock(device_t dev)
+{
+ struct ccm_softc *sc;
+
+ sc = device_get_softc(dev);
+ mtx_lock(&sc->mtx);
+}
+
+static void
+imx_ccm_device_unlock(device_t dev)
+{
+ struct ccm_softc *sc;
+
+ sc = device_get_softc(dev);
+ mtx_unlock(&sc->mtx);
+}
+
+static device_method_t ccm_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ccm_probe),
+ DEVMETHOD(device_attach, ccm_attach),
+ DEVMETHOD(device_detach, ccm_detach),
+
+ /* clkdev interface */
+ DEVMETHOD(clkdev_write_4, imx_ccm_write_4),
+ DEVMETHOD(clkdev_read_4, imx_ccm_read_4),
+ DEVMETHOD(clkdev_modify_4, imx_ccm_modify_4),
+ DEVMETHOD(clkdev_device_lock, imx_ccm_device_lock),
+ DEVMETHOD(clkdev_device_unlock, imx_ccm_device_unlock),
+
+ DEVMETHOD_END
+};
+
+static driver_t ccm_driver = {
+ "ccm",
+ ccm_methods,
+ sizeof(struct ccm_softc)
+};
+
+static devclass_t ccm_devclass;
+
+EARLY_DRIVER_MODULE(ccm, simplebus, ccm_driver, ccm_devclass, 0, 0,
+ BUS_PASS_CPU + BUS_PASS_ORDER_EARLY);
Index: sys/arm64/freescale/imx/imx_ccm_clk.h
===================================================================
--- /dev/null
+++ sys/arm64/freescale/imx/imx_ccm_clk.h
@@ -0,0 +1,212 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Oleksandr Tymoshenko <gonzo@FreeBSD.org>
+ *
+ * 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 IMX6_CCM_CLK_H
+#define IMX6_CCM_CLK_H
+
+#include <dev/extres/clk/clk.h>
+#include <dev/extres/clk/clk_div.h>
+#include <dev/extres/clk/clk_fixed.h>
+#include <dev/extres/clk/clk_gate.h>
+#include <dev/extres/clk/clk_link.h>
+
+enum imx_clk_type {
+ IMX_CLK_UNDEFINED = 0,
+ IMX_CLK_FIXED,
+ IMX_CLK_LINK,
+ IMX_CLK_MUX,
+ IMX_CLK_GATE,
+ IMX_CLK_COMPOSITE,
+ IMX_CLK_SSCG_PLL,
+ IMX_CLK_FRAC_PLL,
+ IMX_CLK_DIV,
+};
+
+struct imx_clk {
+ enum imx_clk_type type;
+ union {
+ struct clk_fixed_def *fixed;
+ struct clk_link_def *link;
+ struct imx_clk_mux_def *mux;
+ struct imx_clk_gate_def *gate;
+ struct imx_clk_composite_def *composite;
+ struct imx_clk_sscg_pll_def *sscg_pll;
+ struct imx_clk_frac_pll_def *frac_pll;
+ struct clk_div_def *div;
+ } clk;
+};
+
+/* Linked clock. */
+#define LINK(_id, _name) \
+{ \
+ .type = IMX_CLK_LINK, \
+ .clk.link = &(struct clk_link_def) { \
+ .clkdef.id = _id, \
+ .clkdef.name = _name, \
+ .clkdef.parent_names = NULL, \
+ .clkdef.parent_cnt = 0, \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
+ }, \
+}
+
+/* Complex clock without divider (multiplexer only). */
+#define MUX(_id, _name, _pn, _f, _mo, _ms, _mw) \
+{ \
+ .type = IMX_CLK_MUX, \
+ .clk.mux = &(struct imx_clk_mux_def) { \
+ .clkdef.id = _id, \
+ .clkdef.name = _name, \
+ .clkdef.parent_names = _pn, \
+ .clkdef.parent_cnt = nitems(_pn), \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
+ .offset = _mo, \
+ .shift = _ms, \
+ .width = _mw, \
+ .mux_flags = _f, \
+ }, \
+}
+
+/* Fixed frequency clock */
+#define FIXED(_id, _name, _freq) \
+{ \
+ .type = IMX_CLK_FIXED, \
+ .clk.fixed = &(struct clk_fixed_def) { \
+ .clkdef.id = _id, \
+ .clkdef.name = _name, \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
+ .freq = _freq, \
+ }, \
+}
+
+/* Fixed factor multipier/divider. */
+#define FFACT(_id, _name, _pname, _mult, _div) \
+{ \
+ .type = IMX_CLK_FIXED, \
+ .clk.fixed = &(struct clk_fixed_def) { \
+ .clkdef.id = _id, \
+ .clkdef.name = _name, \
+ .clkdef.parent_names = (const char *[]){_pname}, \
+ .clkdef.parent_cnt = 1, \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
+ .mult = _mult, \
+ .div = _div, \
+ }, \
+}
+
+/* Clock gate */
+#define GATE(_id, _name, _pname, _o, _shift) \
+{ \
+ .type = IMX_CLK_GATE, \
+ .clk.gate = &(struct imx_clk_gate_def) { \
+ .clkdef.id = _id, \
+ .clkdef.name = _name, \
+ .clkdef.parent_names = (const char *[]){_pname}, \
+ .clkdef.parent_cnt = 1, \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
+ .offset = _o, \
+ .shift = _shift, \
+ .mask = 1, \
+ }, \
+}
+
+/* Root clock gate */
+#define ROOT_GATE(_id, _name, _pname, _reg) \
+{ \
+ .type = IMX_CLK_GATE, \
+ .clk.gate = &(struct imx_clk_gate_def) { \
+ .clkdef.id = _id, \
+ .clkdef.name = _name, \
+ .clkdef.parent_names = (const char *[]){_pname}, \
+ .clkdef.parent_cnt = 1, \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
+ .offset = _reg, \
+ .shift = 0, \
+ .mask = 3, \
+ }, \
+}
+
+/* Composite clock with GATE, MUX, PRE_DIV, and POST_DIV */
+#define COMPOSITE(_id, _name, _pn, _o, _flags) \
+{ \
+ .type = IMX_CLK_COMPOSITE, \
+ .clk.composite = &(struct imx_clk_composite_def) { \
+ .clkdef.id = _id, \
+ .clkdef.name = _name, \
+ .clkdef.parent_names = _pn, \
+ .clkdef.parent_cnt = nitems(_pn), \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
+ .offset = _o, \
+ .flags = _flags, \
+ }, \
+}
+
+/* SSCG PLL */
+#define SSCG_PLL(_id, _name, _pn, _o) \
+{ \
+ .type = IMX_CLK_SSCG_PLL, \
+ .clk.composite = &(struct imx_clk_composite_def) { \
+ .clkdef.id = _id, \
+ .clkdef.name = _name, \
+ .clkdef.parent_names = _pn, \
+ .clkdef.parent_cnt = nitems(_pn), \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
+ .offset = _o, \
+ }, \
+}
+
+/* Fractional PLL */
+#define FRAC_PLL(_id, _name, _pname, _o) \
+{ \
+ .type = IMX_CLK_FRAC_PLL, \
+ .clk.frac_pll = &(struct imx_clk_frac_pll_def) { \
+ .clkdef.id = _id, \
+ .clkdef.name = _name, \
+ .clkdef.parent_names = (const char *[]){_pname}, \
+ .clkdef.parent_cnt = 1, \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
+ .offset = _o, \
+ }, \
+}
+
+#define DIV(_id, _name, _pname, _o, _shift, _width) \
+{ \
+ .type = IMX_CLK_DIV, \
+ .clk.div = &(struct clk_div_def) { \
+ .clkdef.id = _id, \
+ .clkdef.name = _name, \
+ .clkdef.parent_names = (const char *[]){_pname}, \
+ .clkdef.parent_cnt = 1, \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
+ .offset = _o, \
+ .i_shift = _shift, \
+ .i_width = _width, \
+ }, \
+}
+
+#endif
Index: sys/conf/files
===================================================================
--- sys/conf/files
+++ sys/conf/files
@@ -3172,6 +3172,7 @@
dev/uart/uart_core.c optional uart
dev/uart/uart_cpu_acpi.c optional uart acpi
dev/uart/uart_dbg.c optional uart gdb
+dev/uart/uart_dev_imx.c optional uart uart_imx fdt
dev/uart/uart_dev_msm.c optional uart uart_msm fdt
dev/uart/uart_dev_mvebu.c optional uart uart_mvebu
dev/uart/uart_dev_ns8250.c optional uart uart_ns8250 | uart uart_snps
Index: sys/conf/files.arm64
===================================================================
--- sys/conf/files.arm64
+++ sys/conf/files.arm64
@@ -388,3 +388,18 @@
arm64/rockchip/clk/rk3328_cru.c optional fdt soc_rockchip_rk3328
arm64/rockchip/clk/rk3399_cru.c optional fdt soc_rockchip_rk3399
arm64/rockchip/clk/rk3399_pmucru.c optional fdt soc_rockchip_rk3399
+
+# i.MX8 Clock support
+arm64/freescale/imx/imx8mq_ccm.c optional fdt soc_freescale_imx8
+arm64/freescale/imx/clk/imx_clk_gate.c optional fdt soc_freescale_imx8
+arm64/freescale/imx/clk/imx_clk_mux.c optional fdt soc_freescale_imx8
+arm64/freescale/imx/clk/imx_clk_composite.c optional fdt soc_freescale_imx8
+arm64/freescale/imx/clk/imx_clk_sscg_pll.c optional fdt soc_freescale_imx8
+arm64/freescale/imx/clk/imx_clk_frac_pll.c optional fdt soc_freescale_imx8
+
+# iMX drivers
+arm/freescale/imx/imx_gpio.c optional gpio
+arm/freescale/imx/imx_i2c.c optional fsliic
+arm/freescale/imx/imx_machdep.c standard
+arm64/freescale/imx/imx7gpc.c optional fdt soc_freescale_imx8
+dev/ffec/if_ffec.c optional ffec
Index: sys/conf/options.arm64
===================================================================
--- sys/conf/options.arm64
+++ sys/conf/options.arm64
@@ -22,6 +22,7 @@
SOC_BRCM_BCM2837 opt_soc.h
SOC_BRCM_BCM2838 opt_soc.h
SOC_CAVM_THUNDERX opt_soc.h
+SOC_FREESCALE_IMX8 opt_soc.h
SOC_HISI_HI6220 opt_soc.h
SOC_INTEL_STRATIX10 opt_soc.h
SOC_MARVELL_8K opt_soc.h
Index: sys/dev/ffec/if_ffec.c
===================================================================
--- sys/dev/ffec/if_ffec.c
+++ sys/dev/ffec/if_ffec.c
@@ -123,6 +123,7 @@
{"fsl,imx53-fec", FECTYPE_IMX53},
{"fsl,imx6q-fec", FECTYPE_IMX6 | FECFLAG_RACC | FECFLAG_GBE },
{"fsl,imx6ul-fec", FECTYPE_IMX6 | FECFLAG_RACC },
+ {"fsl,imx6sx-fec", FECTYPE_IMX6 | FECFLAG_RACC },
{"fsl,imx7d-fec", FECTYPE_IMX6 | FECFLAG_RACC | FECFLAG_GBE |
FECFLAG_AVB },
{"fsl,mvf600-fec", FECTYPE_MVF | FECFLAG_RACC },
Index: sys/dev/uart/uart_dev_imx.c
===================================================================
--- sys/dev/uart/uart_dev_imx.c
+++ sys/dev/uart/uart_dev_imx.c
@@ -40,13 +40,21 @@
#include <sys/conf.h>
#include <sys/kdb.h>
#include <machine/bus.h>
-#include <machine/fdt.h>
#include <dev/uart/uart.h>
#include <dev/uart/uart_cpu.h>
#include <dev/uart/uart_cpu_fdt.h>
#include <dev/uart/uart_bus.h>
#include <dev/uart/uart_dev_imx.h>
+
+#if defined(EXT_RESOURCES) && defined(__aarch64__)
+#define IMX_ENABLE_CLOCKS
+#endif
+
+#ifdef IMX_ENABLE_CLOCKS
+#include <dev/extres/clk/clk.h>
+#endif
+
#include "uart_if.h"
#include <arm/freescale/imx/imx_ccmvar.h>
@@ -125,7 +133,7 @@
*/
i = (GETREG(bas, REG(UFCR)) & IMXUART_UFCR_RFDIV_MASK) >>
IMXUART_UFCR_RFDIV_SHIFT;
- rate = imx_ccm_uart_hz() / predivs[i];
+ rate = bas->rclk / predivs[i];
ubir = GETREG(bas, REG(UBIR)) + 1;
ubmr = GETREG(bas, REG(UBMR)) + 1;
baud = ((rate / 16 ) * ubir) / ubmr;
@@ -193,8 +201,8 @@
* Note that a quirk of the hardware requires that both UBIR and UBMR be
* set back to back in order for the change to take effect.
*/
- if (baudrate > 0) {
- baseclk = imx_ccm_uart_hz();
+ if ((baudrate > 0) && (bas->rclk != 0)) {
+ baseclk = bas->rclk;
reg = GETREG(bas, REG(UFCR));
reg = (reg & ~IMXUART_UFCR_RFDIV_MASK) | IMXUART_UFCR_RFDIV_DIV1;
SETREG(bas, REG(UFCR), reg);
@@ -323,6 +331,42 @@
i = (i & s) ? (i & ~s) | d : i; \
}
+#ifdef IMX_ENABLE_CLOCKS
+static int
+imx_uart_setup_clocks(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+ clk_t ipgclk, perclk;
+ uint64_t freq;
+ int error;
+
+ bas = &sc->sc_bas;
+
+ if (clk_get_by_ofw_name(sc->sc_dev, 0, "ipg", &ipgclk) != 0)
+ return (ENOENT);
+
+ if (clk_get_by_ofw_name(sc->sc_dev, 0, "per", &perclk) != 0) {
+ return (ENOENT);
+ }
+
+ error = clk_enable(ipgclk);
+ if (error != 0) {
+ device_printf(sc->sc_dev, "cannot enable ipg clock\n");
+ return (error);
+ }
+
+ error = clk_get_freq(perclk, &freq);
+ if (error != 0) {
+ device_printf(sc->sc_dev, "cannot get frequency\n");
+ return (error);
+ }
+
+ bas->rclk = (uint32_t)freq;
+
+ return (0);
+}
+#endif
+
static int
imx_uart_bus_attach(struct uart_softc *sc)
{
@@ -330,6 +374,15 @@
struct uart_devinfo *di;
bas = &sc->sc_bas;
+
+#ifdef IMX_ENABLE_CLOCKS
+ int error = imx_uart_setup_clocks(sc);
+ if (error)
+ return (error);
+#else
+ bas->rclk = imx_ccm_uart_hz();
+#endif
+
if (sc->sc_sysdev != NULL) {
di = sc->sc_sysdev;
imx_uart_init(bas, di->baudrate, di->databits, di->stopbits,
Index: sys/modules/dtb/imx8/Makefile
===================================================================
--- /dev/null
+++ sys/modules/dtb/imx8/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+# All the dts files for imx8 systems we support.
+DTS= \
+ freescale/imx8mq-evk.dts \
+ freescale/imx8mq-nitrogen.dts
+
+.include <bsd.dtb.mk>

File Metadata

Mime Type
text/plain
Expires
Wed, Oct 8, 10:19 PM (12 h, 1 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
23475602
Default Alt Text
D25274.id73181.diff (85 KB)

Event Timeline