svn commit: r362817 - in head/sys: arm/freescale/imx arm64/conf arm64/freescale arm64/freescale/imx arm64/freescale/imx/clk conf dev/ffec dev/uart modules/dtb/imx8
Oleksandr Tymoshenko
gonzo at FreeBSD.org
Wed Jul 1 00:33:18 UTC 2020
Author: gonzo
Date: Wed Jul 1 00:33:16 2020
New Revision: 362817
URL: https://svnweb.freebsd.org/changeset/base/362817
Log:
Add i.MX 8M Quad support
- Add CCM driver and clocks implementations for i.MX 8M
- Add GPC driver for iMX8
- Add clock tree for i.MX 8M Quad
- Add clocks support and new compat strings (where required) for existing i.MX 6 UART, I2C, and GPIO drivers
- Enable aarch64-compatible drivers form i.MX 6 in arm64 GENERIC kernel config
- Add dtb/imx8 kernel module with DTBs for Nitrogen8M and iMX8MQ EVK
With this patch both Nitrogen8M and iMX8MQ EVK boot with NFS root up to multiuser login prompt
Reviewed by: manu
Differential Revision: https://reviews.freebsd.org/D25274
Added:
head/sys/arm64/freescale/
head/sys/arm64/freescale/imx/
head/sys/arm64/freescale/imx/clk/
head/sys/arm64/freescale/imx/clk/imx_clk_composite.c (contents, props changed)
head/sys/arm64/freescale/imx/clk/imx_clk_composite.h (contents, props changed)
head/sys/arm64/freescale/imx/clk/imx_clk_frac_pll.c (contents, props changed)
head/sys/arm64/freescale/imx/clk/imx_clk_frac_pll.h (contents, props changed)
head/sys/arm64/freescale/imx/clk/imx_clk_gate.c (contents, props changed)
head/sys/arm64/freescale/imx/clk/imx_clk_gate.h (contents, props changed)
head/sys/arm64/freescale/imx/clk/imx_clk_mux.c (contents, props changed)
head/sys/arm64/freescale/imx/clk/imx_clk_mux.h (contents, props changed)
head/sys/arm64/freescale/imx/clk/imx_clk_sscg_pll.c (contents, props changed)
head/sys/arm64/freescale/imx/clk/imx_clk_sscg_pll.h (contents, props changed)
head/sys/arm64/freescale/imx/imx7gpc.c (contents, props changed)
head/sys/arm64/freescale/imx/imx8mq_ccm.c (contents, props changed)
head/sys/arm64/freescale/imx/imx8mq_ccm.h (contents, props changed)
head/sys/arm64/freescale/imx/imx_ccm_clk.h (contents, props changed)
head/sys/modules/dtb/imx8/
head/sys/modules/dtb/imx8/Makefile (contents, props changed)
Modified:
head/sys/arm/freescale/imx/imx_gpio.c
head/sys/arm/freescale/imx/imx_i2c.c
head/sys/arm/freescale/imx/imx_iomux.c
head/sys/arm64/conf/GENERIC
head/sys/conf/files
head/sys/conf/files.arm64
head/sys/conf/options.arm64
head/sys/dev/ffec/if_ffec.c
head/sys/dev/uart/uart_dev_imx.c
Modified: head/sys/arm/freescale/imx/imx_gpio.c
==============================================================================
--- head/sys/arm/freescale/imx/imx_gpio.c Wed Jul 1 00:24:55 2020 (r362816)
+++ head/sys/arm/freescale/imx/imx_gpio.c Wed Jul 1 00:33:16 2020 (r362817)
@@ -57,6 +57,14 @@ __FBSDID("$FreeBSD$");
#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 @@ struct imx51_gpio_softc {
#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 @@ imx51_gpio_attach(device_t dev)
{
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 @@ imx51_gpio_attach(device_t dev)
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,8 +878,19 @@ imx51_gpio_detach(device_t dev)
{
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++) {
Modified: head/sys/arm/freescale/imx/imx_i2c.c
==============================================================================
--- head/sys/arm/freescale/imx/imx_i2c.c Wed Jul 1 00:24:55 2020 (r362816)
+++ head/sys/arm/freescale/imx/imx_i2c.c Wed Jul 1 00:33:16 2020 (r362817)
@@ -73,6 +73,14 @@ __FBSDID("$FreeBSD$");
#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 clkdiv clkdiv_table[] = {
};
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 @@ struct i2c_softc {
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 @@ i2c_attach(device_t dev)
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 @@ i2c_detach(device_t dev)
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 @@ i2c_reset(device_t dev, u_char speed, u_char addr, u_c
{
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 @@ i2c_reset(device_t dev, u_char speed, u_char addr, u_c
* 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++) {
Modified: head/sys/arm/freescale/imx/imx_iomux.c
==============================================================================
--- head/sys/arm/freescale/imx/imx_iomux.c Wed Jul 1 00:24:55 2020 (r362816)
+++ head/sys/arm/freescale/imx/imx_iomux.c Wed Jul 1 00:33:16 2020 (r362817)
@@ -76,6 +76,7 @@ struct iomux_softc {
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},
Modified: head/sys/arm64/conf/GENERIC
==============================================================================
--- head/sys/arm64/conf/GENERIC Wed Jul 1 00:24:55 2020 (r362816)
+++ head/sys/arm64/conf/GENERIC Wed Jul 1 00:33:16 2020 (r362817)
@@ -113,6 +113,7 @@ options SOC_ALLWINNER_A64
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 al_eth # Annapurna Alpine Ethernet NIC
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 @@ device rk_emmcphy
# 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 rk_i2c # RockChip I2C controller
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 @@ options FDT
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"
Added: head/sys/arm64/freescale/imx/clk/imx_clk_composite.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/sys/arm64/freescale/imx/clk/imx_clk_composite.c Wed Jul 1 00:33:16 2020 (r362817)
@@ -0,0 +1,309 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2018 Emmanuel Vadot <manu at 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, ®);
+ 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);
+}
Added: head/sys/arm64/freescale/imx/clk/imx_clk_composite.h
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/sys/arm64/freescale/imx/clk/imx_clk_composite.h Wed Jul 1 00:33:16 2020 (r362817)
@@ -0,0 +1,45 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright 2018 Emmanuel Vadot <manu at 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_ */
Added: head/sys/arm64/freescale/imx/clk/imx_clk_frac_pll.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/sys/arm64/freescale/imx/clk/imx_clk_frac_pll.c Wed Jul 1 00:33:16 2020 (r362817)
@@ -0,0 +1,177 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Oleksandr Tymoshenko <gonzo at 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);
+}
Added: head/sys/arm64/freescale/imx/clk/imx_clk_frac_pll.h
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/sys/arm64/freescale/imx/clk/imx_clk_frac_pll.h Wed Jul 1 00:33:16 2020 (r362817)
@@ -0,0 +1,42 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Oleksandr Tymoshenko <gonzo at 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_ */
Added: head/sys/arm64/freescale/imx/clk/imx_clk_gate.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/sys/arm64/freescale/imx/clk/imx_clk_gate.c Wed Jul 1 00:33:16 2020 (r362817)
@@ -0,0 +1,117 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright 2016 Michal Meloun <mmel at 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, ®);
+ 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);
+}
Added: head/sys/arm64/freescale/imx/clk/imx_clk_gate.h
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/sys/arm64/freescale/imx/clk/imx_clk_gate.h Wed Jul 1 00:33:16 2020 (r362817)
@@ -0,0 +1,45 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright 2018 Emmanuel Vadot <manu at 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_ */
Added: head/sys/arm64/freescale/imx/clk/imx_clk_mux.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/sys/arm64/freescale/imx/clk/imx_clk_mux.c Wed Jul 1 00:33:16 2020 (r362817)
@@ -0,0 +1,138 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright 2016 Michal Meloun <mmel at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-head
mailing list