Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch Add support for the DE0 NanoSoC board.



details:   https://anonhg.NetBSD.org/src/rev/7197591541ea
branches:  trunk
changeset: 433535:7197591541ea
user:      aymeric <aymeric%NetBSD.org@localhost>
date:      Wed Sep 19 17:31:38 2018 +0000

description:
Add support for the DE0 NanoSoC board.

It's Cyclone V based and thus includes a dual-core Cortex A9 @925MHz.
Most standard peripherals are supported (USB, SDCard, Ethernet) and
no unusual peripheral is supported yet (FPGA, GPIO, ...)

diffstat:

 sys/arch/arm/altera/cycv_clkmgr.c                |  660 +++++++++++++++++++++++
 sys/arch/arm/altera/cycv_dwcmmc.c                |  163 +++++
 sys/arch/arm/altera/cycv_gmac.c                  |  143 ++++
 sys/arch/arm/altera/cycv_intr.h                  |    5 +
 sys/arch/arm/altera/cycv_platform.c              |  145 +++++
 sys/arch/arm/altera/cycv_reg.h                   |  117 ++++
 sys/arch/arm/altera/cycv_rstmgr.c                |  147 +++++
 sys/arch/arm/altera/cycv_var.h                   |   18 +
 sys/arch/arm/altera/files.altera                 |   37 +
 sys/arch/arm/dts/socfpga_cyclone5_de0_sockit.dts |   17 +
 sys/arch/evbarm/altera/altera_start.S            |  126 ++++
 sys/arch/evbarm/altera/genassym.cf               |    7 +
 sys/arch/evbarm/altera/platform.h                |    4 +
 sys/arch/evbarm/conf/NANOSOC                     |   65 ++
 sys/arch/evbarm/conf/files.altera                |    9 +
 sys/arch/evbarm/conf/mk.altera                   |   30 +
 sys/arch/evbarm/conf/std.altera                  |   28 +
 17 files changed, 1721 insertions(+), 0 deletions(-)

diffs (truncated from 1789 to 300 lines):

diff -r 1570bee09e3e -r 7197591541ea sys/arch/arm/altera/cycv_clkmgr.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/arm/altera/cycv_clkmgr.c Wed Sep 19 17:31:38 2018 +0000
@@ -0,0 +1,660 @@
+/* $NetBSD: cycv_clkmgr.c,v 1.1 2018/09/19 17:31:38 aymeric Exp $ */
+
+/* This file is in the public domain. */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: cycv_clkmgr.c,v 1.1 2018/09/19 17:31:38 aymeric Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/intr.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/atomic.h>
+#include <sys/kmem.h>
+
+#include <dev/clk/clk_backend.h>
+
+#include <arm/altera/cycv_reg.h>
+#include <arm/altera/cycv_var.h>
+
+#include <dev/fdt/fdtvar.h>
+
+#define CYCV_CLOCK_OSC1                25000000
+
+static int cycv_clkmgr_match(device_t, cfdata_t, void *);
+static void cycv_clkmgr_attach(device_t, device_t, void *);
+
+static struct clk *cycv_clkmgr_clock_decode(device_t, int, const void *,
+                                           size_t);
+
+static const struct fdtbus_clock_controller_func cycv_clkmgr_fdtclock_funcs = {
+       .decode = cycv_clkmgr_clock_decode
+};
+
+static struct clk *cycv_clkmgr_clock_get(void *, const char *);
+static void cycv_clkmgr_clock_put(void *, struct clk *);
+static u_int cycv_clkmgr_clock_get_rate(void *, struct clk *);
+static int cycv_clkmgr_clock_set_rate(void *, struct clk *, u_int);
+static int cycv_clkmgr_clock_enable(void *, struct clk *);
+static int cycv_clkmgr_clock_disable(void *, struct clk *);
+static int cycv_clkmgr_clock_set_parent(void *, struct clk *, struct clk *);
+static struct clk *cycv_clkmgr_clock_get_parent(void *, struct clk *);
+
+static const struct clk_funcs cycv_clkmgr_clock_funcs = {
+       .get = cycv_clkmgr_clock_get,
+       .put = cycv_clkmgr_clock_put,
+       .get_rate = cycv_clkmgr_clock_get_rate,
+       .set_rate = cycv_clkmgr_clock_set_rate,
+       .enable = cycv_clkmgr_clock_enable,
+       .disable = cycv_clkmgr_clock_disable,
+       .get_parent = cycv_clkmgr_clock_get_parent,
+       .set_parent = cycv_clkmgr_clock_set_parent,
+};
+
+struct cycv_clk {
+       struct clk base;
+
+       int id;
+       u_int refcnt;
+
+       struct cycv_clk *parent;        /* cached and valid if not NULL */
+       /* parent_id is not zero and filled with dtb if only one parent clock */
+       int parent_id;
+
+       int type;
+#define CYCV_CLK_TYPE_PLL      0x0001
+#define CYCV_CLK_TYPE_FIXED    0x0002
+#define CYCV_CLK_TYPE_FIXED_DIV        0x0003
+#define CYCV_CLK_TYPE_DIV      0x0004
+
+       int flags;
+#define CYCV_CLK_FLAG_HAVE_GATE        0x0001
+#define CYCV_CLK_FLAG_IS_AVAIL 0x0002
+
+       union {
+               bus_addr_t pll_addr;
+               uint32_t fixed_freq;
+               uint32_t fixed_div;
+               struct {
+                       bus_addr_t addr;
+                       uint32_t mask;
+                       int shift;
+               } div;
+       } u;
+
+       bus_addr_t gate_addr;
+       int gate_shift;
+};
+
+struct cycv_clkmgr_softc {
+       device_t sc_dev;
+       struct clk_domain sc_clkdom;
+
+       bus_space_tag_t sc_bst;
+       bus_space_handle_t sc_bsh;
+
+       struct cycv_clk *sc_clocks;
+       u_int sc_nclocks;
+};
+
+static void cycv_clkmgr_init(struct cycv_clkmgr_softc *, int);
+static void cycv_clkmgr_clock_parse(struct cycv_clkmgr_softc *, int, u_int);
+static u_int cycv_clkmgr_clocks_traverse(struct cycv_clkmgr_softc *, int,
+       void (*)(struct cycv_clkmgr_softc *, int, u_int), u_int);
+static struct cycv_clk_mux_info *cycv_clkmgr_get_mux_info(const char *);
+static void cycv_clkmgr_clock_print(struct cycv_clkmgr_softc *,
+       struct cycv_clk *);
+
+CFATTACH_DECL_NEW(cycvclkmgr, sizeof (struct cycv_clkmgr_softc),
+       cycv_clkmgr_match, cycv_clkmgr_attach, NULL, NULL);
+
+static int
+cycv_clkmgr_match(device_t parent, cfdata_t cf, void *aux)
+{
+       const char *compatible[] = { "altr,clk-mgr", NULL };
+       struct fdt_attach_args *faa = aux;
+
+       return of_match_compatible(faa->faa_phandle, compatible);
+}
+
+static void
+cycv_clkmgr_attach(device_t parent, device_t self, void *aux)
+{
+       struct cycv_clkmgr_softc *sc = device_private(self);
+       struct fdt_attach_args *faa = aux;
+       int phandle = faa->faa_phandle;
+       bus_addr_t addr;
+       bus_size_t size;
+       int error;
+
+       if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
+               aprint_error(": couldn't get registers\n");
+               return;
+       }
+
+       sc->sc_dev = self;
+       sc->sc_bst = faa->faa_bst;
+       error = bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh);
+       if (error) {
+               aprint_error(": couldn't map %#llx: %d",
+                            (uint64_t) addr, error);
+               return;
+       }
+
+       aprint_normal(": clock manager\n");
+
+       sc->sc_clkdom.funcs = &cycv_clkmgr_clock_funcs;
+       sc->sc_clkdom.priv = sc;
+
+       cycv_clkmgr_init(sc, phandle);
+}
+
+static void
+cycv_clkmgr_init(struct cycv_clkmgr_softc *sc, int clkmgr_handle)
+{
+       int clocks_handle;
+
+       clocks_handle = of_find_firstchild_byname(clkmgr_handle, "clocks");
+       if (clocks_handle == -1) {
+               aprint_error_dev(sc->sc_dev, "no clocks property\n");
+               return;
+       }
+
+       sc->sc_nclocks = cycv_clkmgr_clocks_traverse(sc, clocks_handle, NULL,
+                                                    0);
+
+       sc->sc_clocks = kmem_zalloc(sc->sc_nclocks * sizeof *sc->sc_clocks,
+                                   KM_NOSLEEP);
+       if (sc->sc_clocks == NULL) {
+               aprint_error_dev(sc->sc_dev, "no memory\n");
+               sc->sc_nclocks = 0;
+               return;
+       }
+
+       cycv_clkmgr_clocks_traverse(sc, clocks_handle, cycv_clkmgr_clock_parse,
+                                   0);
+
+#if 1
+       for (int i = 0; i < sc->sc_nclocks; i++)
+               cycv_clkmgr_clock_print(sc, &sc->sc_clocks[i]);
+#else
+       (void) cycv_clkmgr_clock_print;
+#endif
+}
+
+#define CYCV_CLK_MAX_PARENTS 3
+
+static struct cycv_clk_mux_info {
+       const char *name;
+       const char *parents[CYCV_CLK_MAX_PARENTS];
+       int nparents;
+       bus_addr_t addr;
+       uint32_t mask;
+} cycv_clk_mux_tree[] = {
+       { "periph_pll", { "osc1", "osc2", "f2s_periph_ref_clk" }, 3,
+               0x80, 0x00c00000 },
+       { "sdram_pll", { "osc1", "osc2", "f2s_sdram_ref_clk" }, 3,
+               0xc0, 0x00c00000 },
+       { "l4_mp_clk", { "mainclk", "per_base_clk" }, 2, 0x70, 0x00000001 },
+       { "l4_sp_clk", { "mainclk", "per_base_clk" }, 2, 0x70, 0x00000002 },
+       { "sdmmc_clk",
+           { "f2s_periph_ref_clk", "main_nand_sdmmc_clk", "per_nand_mmc_clk" },
+           3, 0xac, 0x00000003 },
+       { "nand_x_clk",
+           { "f2s_periph_ref_clk", "main_nand_sdmmc_clk", "per_nand_mmc_clk" },
+           3, 0xac, 0x0000000c },
+       { "qspi_clk", { "f2s_periph_ref_clk", "main_qspi_clk", "per_qsi_clk" },
+           3, 0xac, 0x00000030 },
+
+       /* Don't special case bypass */
+       { "dbg_base_clk", { "main_pll" }, 1, 0, 0 },
+       /* Bug in dtb */
+       { "nand_clk", { "nand_x_clk" }, 1, 0, 0 },
+};
+
+static const char * const cycv_clkmgr_compat_fixed[] = { "fixed-clock", NULL };
+static const char * const cycv_clkmgr_compat_pll[] = { "altr,socfpga-pll-clock",
+       NULL };
+static const char * const cycv_clkmgr_compat_perip[] = {
+       "altr,socfpga-perip-clk",
+       "altr,socfpga-gate-clk",
+       NULL
+};
+
+static void
+cycv_clkmgr_clock_parse(struct cycv_clkmgr_softc *sc, int handle, u_int clkno)
+{
+       struct cycv_clk *clk = &sc->sc_clocks[clkno];
+       int flags = 0;
+       const uint8_t *buf;
+       int len;
+
+       clk->base.domain = &sc->sc_clkdom;
+       clk->base.name = fdtbus_get_string(handle, "name");
+       clk->base.flags = 0;
+
+       clk->id = handle;
+       clk->parent = NULL;
+       clk->parent_id = 0;
+       clk->refcnt = 0;
+
+       if (of_compatible(handle, cycv_clkmgr_compat_fixed) != -1) {
+               clk->type = CYCV_CLK_TYPE_FIXED;
+               if (of_getprop_uint32(handle, "clock-frequency",
+                                     &clk->u.fixed_freq) == 0) {
+                       flags |= CYCV_CLK_FLAG_IS_AVAIL;
+               }
+       } else if (of_compatible(handle, cycv_clkmgr_compat_pll) != -1) {
+               if (fdtbus_get_reg(handle, 0, &clk->u.pll_addr, NULL) != 0)
+                       goto err;
+               clk->type = CYCV_CLK_TYPE_PLL;
+               flags |= CYCV_CLK_FLAG_IS_AVAIL;
+       } else if (of_compatible(handle, cycv_clkmgr_compat_perip) != -1) {
+               if (of_getprop_uint32(handle, "fixed-divider",
+                                     &clk->u.fixed_div) == 0) {
+                       clk->type = CYCV_CLK_TYPE_FIXED_DIV;
+               } else if (fdtbus_get_reg(handle, 0, &clk->u.div.addr, NULL) ==
+                               0) {
+                       clk->type = CYCV_CLK_TYPE_DIV;
+                       clk->u.div.shift = 0;
+                       clk->u.div.mask = 0xff;
+               } else if ((buf = fdtbus_get_prop(handle, "div-reg", &len)) !=
+                               NULL) {
+                       if (len != 3 * 4)
+                               goto err;
+
+                       clk->type = CYCV_CLK_TYPE_DIV;
+                       clk->u.div.addr = of_decode_int(buf);
+                       clk->u.div.shift = of_decode_int(buf + 4);
+                       clk->u.div.mask = ((1 << of_decode_int(buf + 8)) - 1) <<
+                               clk->u.div.shift;
+               } else {
+                       /* Simply a gate and/or a mux */
+                       clk->type = CYCV_CLK_TYPE_FIXED_DIV;
+                       clk->u.fixed_div = 1;
+               }
+               flags |= CYCV_CLK_FLAG_IS_AVAIL;
+       } else
+               goto err;
+
+       if ((buf = fdtbus_get_prop(handle, "clk-gate", &len)) != NULL) {
+               clk->gate_addr = of_decode_int(buf);
+               clk->gate_shift = of_decode_int(buf + 4);
+               flags |= CYCV_CLK_FLAG_HAVE_GATE;
+       }
+
+       buf = fdtbus_get_prop(handle, "clocks", &len);
+       if (buf != NULL && len == sizeof (uint32_t)) {
+               clk->parent_id =
+                       fdtbus_get_phandle_from_native(of_decode_int(buf));
+       }
+
+       clk->flags = flags;
+
+       fdtbus_register_clock_controller(sc->sc_dev, handle,



Home | Main Index | Thread Index | Old Index