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