[PATCH 4/4] Add support for Xilinx Versal APAC
Kinsey Moore
kinsey.moore at oarcorp.com
Wed Oct 20 13:42:32 UTC 2021
Looks good.
On 10/19/2021 22:16, chrisj at rtems.org wrote:
> From: Chris Johns <chrisj at rtems.org>
>
> ---
> libbsd.py | 1 +
> rtemsbsd/include/bsp/nexus-devices.h | 9 +
> .../include/machine/rtems-bsd-nexus-bus.h | 28 +++
> rtemsbsd/sys/arm64/xilinx/versal_slcr.c | 223 ++++++++++++++++++
> rtemsbsd/sys/arm64/xilinx/versal_slcr.h | 86 +++++++
> 5 files changed, 347 insertions(+)
> create mode 100644 rtemsbsd/sys/arm64/xilinx/versal_slcr.c
> create mode 100644 rtemsbsd/sys/arm64/xilinx/versal_slcr.h
>
> diff --git a/libbsd.py b/libbsd.py
> index b27b95d8..7593e9ba 100644
> --- a/libbsd.py
> +++ b/libbsd.py
> @@ -1478,6 +1478,7 @@ class dev_net(builder.Module):
> self.addRTEMSKernelSourceFiles(
> [
> 'sys/dev/mii/ksz8091rnb_50MHz.c',
> + 'sys/arm64/xilinx/versal_slcr.c',
> 'sys/arm64/xilinx/zynqmp_slcr.c',
> ],
> mm.generator['source']()
> diff --git a/rtemsbsd/include/bsp/nexus-devices.h b/rtemsbsd/include/bsp/nexus-devices.h
> index 4c13e868..46df17b4 100644
> --- a/rtemsbsd/include/bsp/nexus-devices.h
> +++ b/rtemsbsd/include/bsp/nexus-devices.h
> @@ -126,6 +126,15 @@ RTEMS_BSD_DRIVER_XILINX_ZYNQMP_SDHCI0;
> RTEMS_BSD_DRIVER_XILINX_ZYNQMP_SDHCI1;
> RTEMS_BSD_DRIVER_MMC;
>
> +#elif defined(LIBBSP_AARCH64_XILINX_VERSAL_BSP_H)
> +
> +#include <bsp/irq.h>
> +
> +RTEMS_BSD_DRIVER_XILINX_VERSAL_SLCR;
> +RTEMS_BSD_DRIVER_XILINX_VERSAL_CGEM0(VERSAL_IRQ_ETHERNET_0);
> +RTEMS_BSD_DRIVER_XILINX_VERSAL_CGEM1(VERSAL_IRQ_ETHERNET_1);
> +RTEMS_BSD_DRIVER_UKPHY;
> +
> #elif defined(LIBBSP_ARM_ATSAM_BSP_H)
>
> RTEMS_BSD_DRIVER_USB;
> diff --git a/rtemsbsd/include/machine/rtems-bsd-nexus-bus.h b/rtemsbsd/include/machine/rtems-bsd-nexus-bus.h
> index f0987513..9e1e725a 100644
> --- a/rtemsbsd/include/machine/rtems-bsd-nexus-bus.h
> +++ b/rtemsbsd/include/machine/rtems-bsd-nexus-bus.h
> @@ -139,6 +139,26 @@ extern "C" {
> &zynqmp_slcr_res[0])
> #endif /* RTEMS_BSD_DRIVER_XILINX_ZYNQMP_SLCR */
>
> +/*
> + * Xilinx Versal System Level Control Registers (SLCR).
> + */
> +#if !defined(RTEMS_BSD_DRIVER_XILINX_VERSAL_SLCR)
> + /*
> + * Hard IP part of the Versal so a fixed address.
> + */
> + #define RTEMS_BSD_DRIVER_XILINX_VERSAL_SLCR \
> + static const rtems_bsd_device_resource versal_slcr_res[] = { \
> + { \
> + .type = RTEMS_BSD_RES_MEMORY, \
> + .start_request = 0, \
> + .start_actual = 0xf0000000 \
> + } \
> + }; \
> + RTEMS_BSD_DEFINE_NEXUS_DEVICE(versal_slcr, 0, \
> + RTEMS_ARRAY_SIZE(versal_slcr_res), \
> + &versal_slcr_res[0])
> +#endif /* RTEMS_BSD_DRIVER_XILINX_VERSAL_SLCR */
> +
> /*
> * Xilinx ZynqMP Arasan SDIO Driver.
> */
> @@ -489,6 +509,14 @@ extern "C" {
> #define RTEMS_BSD_DRIVER_XILINX_ZYNQMP_CGEM3(_irq) \
> RTEMS_BSD_DRIVER_XILINX_ZYNQ_CGEM(3, 0xff0e0000, _irq)
> #endif /* RTEMS_BSD_DRIVER_XILINX_ZYNQMP_CGEM3 */
> +#if !defined(RTEMS_BSD_DRIVER_XILINX_VERSAL_CGEM0)
> + #define RTEMS_BSD_DRIVER_XILINX_VERSAL_CGEM0(_irq) \
> + RTEMS_BSD_DRIVER_XILINX_ZYNQ_CGEM(0, 0xff0c0000, _irq)
> +#endif /* RTEMS_BSD_DRIVER_XILINX_VERSAL_CGEM0 */
> +#if !defined(RTEMS_BSD_DRIVER_XILINX_VERSAL_CGEM1)
> + #define RTEMS_BSD_DRIVER_XILINX_VERSAL_CGEM1(_irq) \
> + RTEMS_BSD_DRIVER_XILINX_ZYNQ_CGEM(1, 0xff0d0000, _irq)
> +#endif /* RTEMS_BSD_DRIVER_XILINX_VERSAL_CGEM1 */
>
> /*
> * Designware/Synopsys Ethernet MAC Controller.
> diff --git a/rtemsbsd/sys/arm64/xilinx/versal_slcr.c b/rtemsbsd/sys/arm64/xilinx/versal_slcr.c
> new file mode 100644
> index 00000000..74ebde91
> --- /dev/null
> +++ b/rtemsbsd/sys/arm64/xilinx/versal_slcr.c
> @@ -0,0 +1,223 @@
> +#include <machine/rtems-bsd-kernel-space.h>
> +
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2021 Chris Johns <chrisj at rtems.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.
> + */
> +
> +/*
> + * Versal ACAP SLCR driver. Provides hook for CGEM clocks.
> + *
> + * Reference:
> + * https://www.xilinx.com/html_docs/registers/am012/mod___crl.html
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#include <bsp.h>
> +#include <sys/param.h>
> +#include <sys/systm.h>
> +#include <sys/bus.h>
> +#include <sys/conf.h>
> +#include <sys/kernel.h>
> +#include <sys/module.h>
> +#include <sys/lock.h>
> +#include <sys/mutex.h>
> +#include <rtems/bsd/sys/resource.h>
> +#include <sys/sysctl.h>
> +#include <sys/rman.h>
> +
> +#include <machine/bus.h>
> +#include <machine/resource.h>
> +#include <machine/stdarg.h>
> +
> +#include <arm64/xilinx/versal_slcr.h>
> +
> +struct versal_slcr_softc {
> + device_t dev;
> + struct mtx sc_mtx;
> + struct resource *mem_res;
> +};
> +
> +static struct versal_slcr_softc *versal_slcr_softc_p;
> +
> +#define RD4(sc, off) (bus_read_4((sc)->mem_res, (off)))
> +#define WR4(sc, off, val) (bus_write_4((sc)->mem_res, (off), (val)))
> +
> +SYSCTL_NODE(_hw, OID_AUTO, versal, CTLFLAG_RD, 0, "Xilinx Versal ACAP SLCR");
> +
> +#if defined(LIBBSP_AARCH64_XILINX_VERSAL_BSP_H)
> +/* Override cgem_set_refclk() in gigabit ethernet driver
> + * (sys/dev/cadence/if_cgem.c). This function is called to
> + * request a change in the gem's reference clock speed.
> + */
> +int
> +cgem_set_ref_clk(int unit, int frequency)
> +{
> + struct versal_slcr_softc *sc = versal_slcr_softc_p;
> + int div, last_error = 0;
> + uint64_t clk_ctrl, pll_ctrl;
> + uint32_t clk_ctrl_val, pll_ctrl_val, pll_freq, pll_reset, pll_bypass;
> +
> + if (!sc)
> + return (-1);
> +
> + switch (unit) {
> + case 0:
> + clk_ctrl = VERSAL_SLCR_GEM0_CLK_CTRL;
> + break;
> + case 1:
> + clk_ctrl = VERSAL_SLCR_GEM1_CLK_CTRL;
> + break;
> + default:
> + return (-1);
> + }
> +
> + clk_ctrl_val = RD4(sc, clk_ctrl);
> + switch (clk_ctrl_val & VERSAL_SLCR_GEM_CLK_CTRL_SRCSEL_MASK) {
> + case VERSAL_SLCR_GEM_CLK_CTRL_SRCSEL_P_PLL:
> + pll_ctrl = VERSAL_SLCR_P_PLL_CTRL;
> + break;
> + case VERSAL_SLCR_GEM_CLK_CTRL_SRCSEL_R_PLL:
> + pll_ctrl = VERSAL_SLCR_R_PLL_CTRL;
> + break;
> + case VERSAL_SLCR_GEM_CLK_CTRL_SRCSEL_N_PLL:
> + pll_ctrl = VERSAL_SLCR_N_PLL_CTRL;
> + break;
> + default:
> + return (-1);
> + }
> +
> + /* Get PLL frequency */
> + pll_ctrl_val = RD4(sc, pll_ctrl);
> + pll_reset = (pll_ctrl_val & VERSAL_SLCR_PLL_CTRL_RESET) != 0;
> + pll_bypass = (pll_ctrl_val & VERSAL_SLCR_PLL_CTRL_BYPASS) != 0;
> + if (pll_reset && !pll_bypass) {
> + return 0;
> + }
> +
> + pll_freq = VERSAL_DEFAULT_PS_CLK_FREQUENCY;
> + if (!pll_bypass) {
> + pll_freq *= (pll_ctrl_val & VERSAL_SLCR_PLL_CTRL_FBDIV_MASK) >> VERSAL_SLCR_PLL_CTRL_FBDIV_SHIFT;
> + }
> +
> + /* Apply divider */
> + pll_freq >>= (pll_ctrl_val & VERSAL_SLCR_PLL_CTRL_DIV_MASK) >> VERSAL_SLCR_PLL_CTRL_DIV_SHIFT;
> +
> + /* Find suitable divisor. Linear search, not the fastest method but hey.
> + */
> + for (div = 1; div <= VERSAL_SLCR_GEM_CLK_CTRL_DIVISOR_MAX; div++) {
> + int div_freq = pll_freq / div;
> + int error = abs(frequency - div_freq);
> + if (error >= last_error && last_error != 0) {
> + div--;
> + break;
> + }
> + last_error = error;
> + }
> +
> + if (div > VERSAL_SLCR_GEM_CLK_CTRL_DIVISOR_MAX)
> + return (-1);
> +
> + /* Modify GEM reference clock. */
> + clk_ctrl_val &= ~VERSAL_SLCR_GEM_CLK_CTRL_DIVISOR_MASK;
> + clk_ctrl_val |= div << VERSAL_SLCR_GEM_CLK_CTRL_DIVISOR_SHIFT;
> + WR4(sc, clk_ctrl, clk_ctrl_val);
> +
> + return (0);
> +}
> +#endif
> +
> +static int
> +versal_slcr_probe(device_t dev)
> +{
> + device_set_desc(dev, "Versal ACAP SLCR block");
> + return (0);
> +}
> +
> +static int
> +versal_slcr_attach(device_t dev)
> +{
> + struct versal_slcr_softc *sc = device_get_softc(dev);
> + int rid;
> +
> + /* Allow only one attach. */
> + if (versal_slcr_softc_p != NULL)
> + return (ENXIO);
> +
> + sc->dev = dev;
> +
> + /* Get memory resource. */
> + rid = 0;
> + sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
> + RF_ACTIVE);
> + if (sc->mem_res == NULL) {
> + device_printf(dev, "could not allocate memory resources.\n");
> + return (ENOMEM);
> + }
> +
> + /* For use with CGEM clock setting */
> + versal_slcr_softc_p = sc;
> +
> + return (0);
> +}
> +
> +static int
> +versal_slcr_detach(device_t dev)
> +{
> + struct versal_slcr_softc *sc = device_get_softc(dev);
> +
> + bus_generic_detach(dev);
> +
> + /* Release memory resource. */
> + if (sc->mem_res != NULL)
> + bus_release_resource(dev, SYS_RES_MEMORY,
> + rman_get_rid(sc->mem_res), sc->mem_res);
> +
> + versal_slcr_softc_p = NULL;
> +
> + return (0);
> +}
> +
> +static device_method_t versal_slcr_methods[] = {
> + /* device_if */
> + DEVMETHOD(device_probe, versal_slcr_probe),
> + DEVMETHOD(device_attach, versal_slcr_attach),
> + DEVMETHOD(device_detach, versal_slcr_detach),
> +
> + DEVMETHOD_END
> +};
> +
> +static driver_t versal_slcr_driver = {
> + "versal_slcr",
> + versal_slcr_methods,
> + sizeof(struct versal_slcr_softc),
> +};
> +static devclass_t versal_slcr_devclass;
> +
> +DRIVER_MODULE(versal_slcr, nexus, versal_slcr_driver, versal_slcr_devclass, 0, 0);
> +MODULE_VERSION(versal_slcr, 1);
> diff --git a/rtemsbsd/sys/arm64/xilinx/versal_slcr.h b/rtemsbsd/sys/arm64/xilinx/versal_slcr.h
> new file mode 100644
> index 00000000..e1c967ac
> --- /dev/null
> +++ b/rtemsbsd/sys/arm64/xilinx/versal_slcr.h
> @@ -0,0 +1,86 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2021 Chris Johns <chrisj at rtems.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.
> + */
> +
> +/*
> + * Defines for Xilinx Versal ACAP SLCR registers.
> + *
> + * Reference:
> + * https://www.xilinx.com/html_docs/registers/am012/mod___crl.html
> + */
> +
> +#ifndef _VERSAL_SLCR_H_
> +#define _VERSAL_SLCR_H_
> +
> +#define VERSAL_SLCR_CRF_OFFSET 0x01260000
> +#define VERSAL_SLCR_CRL_OFFSET 0x0f5e0000
> +
> +/*
> + * PLL controls
> + *
> + * P = PPLL = PMCPLL = PMCPLL_CTRL : PMC PLL Clock
> + * N = NPLL = NOCPLL = NOCPLL_CTRL : NOC PLL Clock
> + * R = RPLL = RPLL_CTRL : Low Power Domain clock
> + */
> +#define VERSAL_SLCR_P_PLL_CTRL (VERSAL_SLCR_CRF_OFFSET + 0x40)
> +#define VERSAL_SLCR_N_PLL_CTRL (VERSAL_SLCR_CRF_OFFSET + 0x50)
> +#define VERSAL_SLCR_R_PLL_CTRL (VERSAL_SLCR_CRL_OFFSET + 0x40)
> +#define VERSAL_SLCR_PLL_CTRL_RESET (1<<0)
> +#define VERSAL_SLCR_PLL_CTRL_BYPASS (1<<3)
> +#define VERSAL_SLCR_PLL_CTRL_FBDIV_SHIFT 8
> +#define VERSAL_SLCR_PLL_CTRL_FBDIV_MAX 0xff
> +#define VERSAL_SLCR_PLL_CTRL_FBDIV_MASK (VERSAL_SLCR_PLL_CTRL_FBDIV_MAX<<8)
> +#define VERSAL_SLCR_PLL_CTRL_DIV_SHIFT (16)
> +#define VERSAL_SLCR_PLL_CTRL_DIV_MASK (0x3<<16)
> +#define VERSAL_SLCR_PLL_CTRL_PRE_SRC_SHIFT 20
> +#define VERSAL_SLCR_PLL_CTRL_PRE_SRC_MASK (0x7<<20)
> +#define VERSAL_SLCR_PLL_CTRL_POST_SRC_SHIFT 24
> +#define VERSAL_SLCR_PLL_CTRL_POST_SRC_MASK (0x7<<24)
> +#define VERSAL_SLCR_PLL_CTRL_SRC_REF_CLK 0x0
> +#define VERSAL_SLCR_PLL_CTRL_SRC_REF_CLK_MASK 0x2
> +#define VERSAL_SLCR_PLL_CTRL_SRC_PL_PMC_ALT_REF_CLK_MASK 0x3
> +
> +/* Clock controls. */
> +#define VERSAL_SLCR_GEM0_CLK_CTRL (VERSAL_SLCR_CRL_OFFSET + 0x118)
> +#define VERSAL_SLCR_GEM1_CLK_CTRL (VERSAL_SLCR_CRL_OFFSET + 0x11c)
> +#define VERSAL_SLCR_GEM_CLK_CTRL_CLKACT_RX (1<<27)
> +#define VERSAL_SLCR_GEM_CLK_CTRL_CLKACT_TX (1<<26)
> +#define VERSAL_SLCR_GEM_CLK_CTRL_CLKACT (1<<25)
> +#define VERSAL_SLCR_GEM_CLK_CTRL_DIVISOR_MAX 0x3ff
> +#define VERSAL_SLCR_GEM_CLK_CTRL_DIVISOR_MASK (VERSAL_SLCR_GEM_CLK_CTRL_DIVISOR_MAX<<8)
> +#define VERSAL_SLCR_GEM_CLK_CTRL_DIVISOR_SHIFT 8
> +#define VERSAL_SLCR_GEM_CLK_CTRL_SRCSEL_MASK (7<<0)
> +#define VERSAL_SLCR_GEM_CLK_CTRL_SRCSEL_P_PLL (0<<0)
> +#define VERSAL_SLCR_GEM_CLK_CTRL_SRCSEL_R_PLL (1<<0)
> +#define VERSAL_SLCR_GEM_CLK_CTRL_SRCSEL_N_PLL (3<<0)
> +
> +#define VERSAL_DEFAULT_PS_CLK_FREQUENCY 33333333
> +
> +#ifdef _KERNEL
> +extern int cgem_set_ref_clk(int unit, int frequency);
> +#endif
> +#endif /* _VERSAL_SLCR_H_ */
More information about the devel
mailing list