Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 15 May 2015 18:25:49 +0000 (UTC)
From:      Zbigniew Bodek <zbb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r282985 - in head/sys: arm/annapurna arm/annapurna/alpine arm/annapurna/alpine/hal arm/conf boot/fdt/dts/arm
Message-ID:  <201505151825.t4FIPnxJ099637@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: zbb
Date: Fri May 15 18:25:48 2015
New Revision: 282985
URL: https://svnweb.freebsd.org/changeset/base/282985

Log:
  Introduce support for the Alpine PoC from Annapurna Labs
  
  The Alpine Platform-On-Chip offers multicore processing
  (quad ARM Cortex-A15), 1/10Gb Ethernet, SATA 3, PCI-E 3,
  DMA engines, Virtualization, Advanced Power Management and other.
  
  This code drop involves basic platform support including:
  SMP, IRQs, SerDes, SATA. As of now it is missing the PCIe support.
  Part of the functionality is provided by the low-level code (HAL)
  delivered by the chip vendor (Annapurna Labs) and is a subject to
  change in the future (is planned to be moved to sys/contrib directory).
  
  The review log for this commit is available here:
  https://reviews.freebsd.org/D2340
  
  Reviewed by:    andrew, ian, imp
  Obtained from:  Semihalf
  Sponsored by:   Annapurna Labs

Added:
  head/sys/arm/annapurna/
  head/sys/arm/annapurna/alpine/
  head/sys/arm/annapurna/alpine/alpine_machdep.c   (contents, props changed)
  head/sys/arm/annapurna/alpine/alpine_machdep_mp.c   (contents, props changed)
  head/sys/arm/annapurna/alpine/common.c   (contents, props changed)
  head/sys/arm/annapurna/alpine/files.alpine   (contents, props changed)
  head/sys/arm/annapurna/alpine/hal/
  head/sys/arm/annapurna/alpine/hal/al_hal_common.h   (contents, props changed)
  head/sys/arm/annapurna/alpine/hal/al_hal_iofic.h   (contents, props changed)
  head/sys/arm/annapurna/alpine/hal/al_hal_iofic_regs.h   (contents, props changed)
  head/sys/arm/annapurna/alpine/hal/al_hal_nb_regs.h   (contents, props changed)
  head/sys/arm/annapurna/alpine/hal/al_hal_pbs_regs.h   (contents, props changed)
  head/sys/arm/annapurna/alpine/hal/al_hal_pcie.c   (contents, props changed)
  head/sys/arm/annapurna/alpine/hal/al_hal_pcie.h   (contents, props changed)
  head/sys/arm/annapurna/alpine/hal/al_hal_pcie_axi_reg.h   (contents, props changed)
  head/sys/arm/annapurna/alpine/hal/al_hal_pcie_interrupts.h   (contents, props changed)
  head/sys/arm/annapurna/alpine/hal/al_hal_pcie_regs.h   (contents, props changed)
  head/sys/arm/annapurna/alpine/hal/al_hal_pcie_w_reg.h   (contents, props changed)
  head/sys/arm/annapurna/alpine/hal/al_hal_plat_services.h   (contents, props changed)
  head/sys/arm/annapurna/alpine/hal/al_hal_plat_types.h   (contents, props changed)
  head/sys/arm/annapurna/alpine/hal/al_hal_reg_utils.h   (contents, props changed)
  head/sys/arm/annapurna/alpine/hal/al_hal_types.h   (contents, props changed)
  head/sys/arm/annapurna/alpine/hal/al_hal_unit_adapter_regs.h   (contents, props changed)
  head/sys/arm/annapurna/alpine/std.alpine   (contents, props changed)
  head/sys/arm/conf/ALPINE   (contents, props changed)
  head/sys/boot/fdt/dts/arm/annapurna-alpine.dts   (contents, props changed)

Added: head/sys/arm/annapurna/alpine/alpine_machdep.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/arm/annapurna/alpine/alpine_machdep.c	Fri May 15 18:25:48 2015	(r282985)
@@ -0,0 +1,148 @@
+/*-
+ * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.com>
+ * Copyright (c) 2015 Semihalf
+ * 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$");
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/frame.h> /* For trapframe_t, used in <machine/machdep.h> */
+#include <machine/machdep.h>
+#include <machine/pmap.h>
+#include <machine/devmap.h>
+#include <machine/platform.h>
+#include <machine/fdt.h>
+
+#include <dev/fdt/fdt_common.h>
+
+#include "opt_ddb.h"
+#include "opt_platform.h"
+
+struct mtx al_dbg_lock;
+
+#define	DEVMAP_MAX_VA_ADDRESS		0xF0000000
+bus_addr_t al_devmap_pa;
+bus_addr_t al_devmap_size;
+
+#define	AL_NB_SERVICE_OFFSET		0x70000
+#define	AL_NB_CCU_OFFSET			0x90000
+#define	AL_CCU_SNOOP_CONTROL_IOFAB_0_OFFSET	0x4000
+#define	AL_CCU_SNOOP_CONTROL_IOFAB_1_OFFSET	0x5000
+#define	AL_CCU_SPECULATION_CONTROL_OFFSET	0x4
+
+#define	AL_NB_ACF_MISC_OFFSET			0xD0
+#define	AL_NB_ACF_MISC_READ_BYPASS 		(1 << 30)
+
+int alpine_get_devmap_base(bus_addr_t *pa, bus_addr_t *size);
+
+vm_offset_t
+platform_lastaddr(void)
+{
+
+	return (DEVMAP_MAX_VA_ADDRESS);
+}
+
+void
+platform_probe_and_attach(void)
+{
+
+}
+
+void
+platform_gpio_init(void)
+{
+
+}
+
+void
+platform_late_init(void)
+{
+	bus_addr_t reg_baddr;
+	uint32_t val;
+
+	if (!mtx_initialized(&al_dbg_lock))
+		mtx_init(&al_dbg_lock, "ALDBG", "ALDBG", MTX_SPIN);
+
+	/* configure system fabric */
+	if (bus_space_map(fdtbus_bs_tag, al_devmap_pa, al_devmap_size, 0,
+	    &reg_baddr))
+		panic("Couldn't map Register Space area");
+
+	/* do not allow reads to bypass writes to different addresses */
+	val = bus_space_read_4(fdtbus_bs_tag, reg_baddr,
+	    AL_NB_SERVICE_OFFSET + AL_NB_ACF_MISC_OFFSET);
+	val &= ~AL_NB_ACF_MISC_READ_BYPASS;
+	bus_space_write_4(fdtbus_bs_tag, reg_baddr,
+	    AL_NB_SERVICE_OFFSET + AL_NB_ACF_MISC_OFFSET, val);
+
+	/* enable cache snoop */
+	bus_space_write_4(fdtbus_bs_tag, reg_baddr,
+	    AL_NB_CCU_OFFSET + AL_CCU_SNOOP_CONTROL_IOFAB_0_OFFSET, 1);
+	bus_space_write_4(fdtbus_bs_tag, reg_baddr,
+	    AL_NB_CCU_OFFSET + AL_CCU_SNOOP_CONTROL_IOFAB_1_OFFSET, 1);
+
+	/* disable speculative fetches from masters */
+	bus_space_write_4(fdtbus_bs_tag, reg_baddr,
+	    AL_NB_CCU_OFFSET + AL_CCU_SPECULATION_CONTROL_OFFSET, 7);
+
+	bus_space_unmap(fdtbus_bs_tag, reg_baddr, al_devmap_size);
+}
+
+/*
+ * Construct pmap_devmap[] with DT-derived config data.
+ */
+int
+platform_devmap_init(void)
+{
+	alpine_get_devmap_base(&al_devmap_pa, &al_devmap_size);
+	arm_devmap_add_entry(al_devmap_pa, al_devmap_size);
+	return (0);
+}
+
+struct arm32_dma_range *
+bus_dma_get_range(void)
+{
+
+	return (NULL);
+}
+
+int
+bus_dma_get_range_nb(void)
+{
+
+	return (0);
+}

Added: head/sys/arm/annapurna/alpine/alpine_machdep_mp.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/arm/annapurna/alpine/alpine_machdep_mp.c	Fri May 15 18:25:48 2015	(r282985)
@@ -0,0 +1,335 @@
+/*-
+ * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.com>
+ * Copyright (c) 2015 Semihalf
+ * 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 <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/smp.h>
+#include <sys/cpuset.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/smp.h>
+#include <machine/fdt.h>
+#include <machine/intr.h>
+#include <machine/cpu-v6.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_cpu.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#define AL_CPU_RESUME_WATERMARK_REG		0x00
+#define AL_CPU_RESUME_FLAGS_REG			0x04
+#define AL_CPU_RESUME_PCPU_RADDR_REG(cpu)	(0x08 + 0x04 + 8*(cpu))
+#define AL_CPU_RESUME_PCPU_FLAGS(cpu)		(0x08 + 8*(cpu))
+
+/* Per-CPU flags */
+#define AL_CPU_RESUME_FLG_PERCPU_DONT_RESUME	(1 << 2)
+
+/* The expected magic number for validating the resume addresses */
+#define AL_CPU_RESUME_MAGIC_NUM			0xf0e1d200
+#define AL_CPU_RESUME_MAGIC_NUM_MASK		0xffffff00
+
+/* The expected minimal version number for validating the capabilities */
+#define AL_CPU_RESUME_MIN_VER			0x000000c3
+#define AL_CPU_RESUME_MIN_VER_MASK		0x000000ff
+
+/* Field controlling the boot-up of companion cores */
+#define AL_NB_INIT_CONTROL		(0x8)
+#define AL_NB_CONFIG_STATUS_PWR_CTRL(cpu)	(0x2020 + (cpu)*0x100)
+
+#define SERDES_NUM_GROUPS	4
+#define SERDES_GROUP_SIZE	0x400
+
+extern bus_addr_t al_devmap_pa;
+extern bus_addr_t al_devmap_size;
+
+extern void mpentry(void);
+
+int alpine_serdes_resource_get(uint32_t group, bus_space_tag_t *tag,
+    bus_addr_t *baddr);
+static int platform_mp_get_core_cnt(void);
+static int alpine_get_cpu_resume_base(u_long *pbase, u_long *psize);
+static int alpine_get_nb_base(u_long *pbase, u_long *psize);
+static int alpine_get_serdes_base(u_long *pbase, u_long *psize);
+int alpine_serdes_resource_get(uint32_t group, bus_space_tag_t *tag,
+    bus_addr_t *baddr);
+static boolean_t alpine_validate_cpu(u_int, phandle_t, u_int, pcell_t *);
+
+static boolean_t
+alpine_validate_cpu(u_int id, phandle_t child, u_int addr_cell, pcell_t *reg)
+{
+	return fdt_is_compatible(child, "arm,cortex-a15");
+}
+
+static int
+platform_mp_get_core_cnt(void)
+{
+	static int ncores = 0;
+	int nchilds;
+	uint32_t reg;
+
+	/* Calculate ncores value only once */
+	if (ncores)
+		return (ncores);
+
+	reg = cp15_l2ctlr_get();
+	ncores = CPUV7_L2CTLR_NPROC(reg);
+
+	nchilds = ofw_cpu_early_foreach(alpine_validate_cpu, false);
+
+	/* Limit CPUs if DTS has configured less than available */
+	if ((nchilds > 0) && (nchilds < ncores)) {
+		printf("SMP: limiting number of active CPUs to %d out of %d\n",
+		    nchilds, ncores);
+		ncores = nchilds;
+	}
+
+	return (ncores);
+}
+
+void
+platform_mp_init_secondary(void)
+{
+
+	arm_init_secondary_ic();
+}
+
+void
+platform_mp_setmaxid(void)
+{
+	int core_cnt;
+
+	core_cnt = platform_mp_get_core_cnt();
+	mp_maxid = core_cnt - 1;
+}
+
+int
+platform_mp_probe(void)
+{
+	mp_ncpus = platform_mp_get_core_cnt();
+	return (1);
+}
+
+static int
+alpine_get_cpu_resume_base(u_long *pbase, u_long *psize)
+{
+	phandle_t node;
+	u_long base = 0;
+	u_long size = 0;
+
+	if (pbase == NULL || psize == NULL)
+		return (EINVAL);
+
+	if ((node = OF_finddevice("/")) == -1)
+		return (EFAULT);
+
+	if ((node =
+	    ofw_bus_find_compatible(node, "annapurna-labs,al-cpu-resume")) == 0)
+		return (EFAULT);
+
+	if (fdt_regsize(node, &base, &size))
+		return (EFAULT);
+
+	*pbase = base;
+	*psize = size;
+
+	return (0);
+}
+
+static int
+alpine_get_nb_base(u_long *pbase, u_long *psize)
+{
+	phandle_t node;
+	u_long base = 0;
+	u_long size = 0;
+
+	if (pbase == NULL || psize == NULL)
+		return (EINVAL);
+
+	if ((node = OF_finddevice("/")) == -1)
+		return (EFAULT);
+
+	if ((node =
+	    ofw_bus_find_compatible(node, "annapurna-labs,al-nb-service")) == 0)
+		return (EFAULT);
+
+	if (fdt_regsize(node, &base, &size))
+		return (EFAULT);
+
+	*pbase = base;
+	*psize = size;
+
+	return (0);
+}
+
+void
+platform_mp_start_ap(void)
+{
+	uint32_t physaddr;
+	vm_offset_t vaddr;
+	uint32_t val;
+	uint32_t start_mask;
+	u_long cpu_resume_base;
+	u_long nb_base;
+	u_long cpu_resume_size;
+	u_long nb_size;
+	bus_addr_t cpu_resume_baddr;
+	bus_addr_t nb_baddr;
+	int a;
+
+	if (alpine_get_cpu_resume_base(&cpu_resume_base, &cpu_resume_size))
+		panic("Couldn't resolve cpu_resume_base address\n");
+
+	if (alpine_get_nb_base(&nb_base, &nb_size))
+		panic("Couldn't resolve_nb_base address\n");
+
+	/* Proceed with start addresses for additional CPUs */
+	if (bus_space_map(fdtbus_bs_tag, al_devmap_pa + cpu_resume_base,
+	    cpu_resume_size, 0, &cpu_resume_baddr))
+		panic("Couldn't map CPU-resume area");
+	if (bus_space_map(fdtbus_bs_tag, al_devmap_pa + nb_base,
+	    nb_size, 0, &nb_baddr))
+		panic("Couldn't map NB-service area");
+
+	/* Proceed with start addresses for additional CPUs */
+	val = bus_space_read_4(fdtbus_bs_tag, cpu_resume_baddr,
+	    AL_CPU_RESUME_WATERMARK_REG);
+	if (((val & AL_CPU_RESUME_MAGIC_NUM_MASK) != AL_CPU_RESUME_MAGIC_NUM) ||
+	    ((val & AL_CPU_RESUME_MIN_VER_MASK) < AL_CPU_RESUME_MIN_VER)) {
+		panic("CPU-resume device is not compatible");
+	}
+
+	vaddr = (vm_offset_t)mpentry;
+	physaddr = pmap_kextract(vaddr);
+
+	for (a = 1; a < platform_mp_get_core_cnt(); a++) {
+		/* Power up the core */
+		bus_space_write_4(fdtbus_bs_tag, nb_baddr,
+		    AL_NB_CONFIG_STATUS_PWR_CTRL(a), 0);
+		mb();
+
+		/* Enable resume */
+		val = bus_space_read_4(fdtbus_bs_tag, cpu_resume_baddr,
+		    AL_CPU_RESUME_PCPU_FLAGS(a));
+		val &= ~AL_CPU_RESUME_FLG_PERCPU_DONT_RESUME;
+		bus_space_write_4(fdtbus_bs_tag, cpu_resume_baddr,
+		    AL_CPU_RESUME_PCPU_FLAGS(a), val);
+		mb();
+
+		/* Set resume physical address */
+		bus_space_write_4(fdtbus_bs_tag, cpu_resume_baddr,
+		    AL_CPU_RESUME_PCPU_RADDR_REG(a), physaddr);
+		mb();
+	}
+
+	/* Release cores from reset */
+	if (bus_space_map(fdtbus_bs_tag, al_devmap_pa + nb_base,
+	    nb_size, 0, &nb_baddr))
+		panic("Couldn't map NB-service area");
+
+	start_mask = (1 << platform_mp_get_core_cnt()) - 1;
+
+	/* Release cores from reset */
+	val = bus_space_read_4(fdtbus_bs_tag, nb_baddr, AL_NB_INIT_CONTROL);
+	val |= start_mask;
+	bus_space_write_4(fdtbus_bs_tag, nb_baddr, AL_NB_INIT_CONTROL, val);
+	dsb();
+
+	bus_space_unmap(fdtbus_bs_tag, nb_baddr, nb_size);
+	bus_space_unmap(fdtbus_bs_tag, cpu_resume_baddr, cpu_resume_size);
+}
+
+static int
+alpine_get_serdes_base(u_long *pbase, u_long *psize)
+{
+	phandle_t node;
+	u_long base = 0;
+	u_long size = 0;
+
+	if (pbase == NULL || psize == NULL)
+		return (EINVAL);
+
+	if ((node = OF_finddevice("/")) == -1)
+		return (EFAULT);
+
+	if ((node =
+	    ofw_bus_find_compatible(node, "annapurna-labs,al-serdes")) == 0)
+		return (EFAULT);
+
+	if (fdt_regsize(node, &base, &size))
+		return (EFAULT);
+
+	*pbase = base;
+	*psize = size;
+
+	return (0);
+}
+
+int
+alpine_serdes_resource_get(uint32_t group, bus_space_tag_t *tag, bus_addr_t *baddr)
+{
+	u_long serdes_base, serdes_size;
+	int ret;
+	static bus_addr_t baddr_mapped[SERDES_NUM_GROUPS];
+
+	if (group >= SERDES_NUM_GROUPS)
+		return (EINVAL);
+
+	if (baddr_mapped[group]) {
+		*tag = fdtbus_bs_tag;
+		*baddr = baddr_mapped[group];
+		return (0);
+	}
+
+	ret = alpine_get_serdes_base(&serdes_base, &serdes_size);
+	if (ret)
+		return (ret);
+
+	ret = bus_space_map(fdtbus_bs_tag,
+	    al_devmap_pa + serdes_base + group * SERDES_GROUP_SIZE,
+	    (SERDES_NUM_GROUPS - group) * SERDES_GROUP_SIZE, 0, baddr);
+	if (ret)
+		return (ret);
+
+	baddr_mapped[group] = *baddr;
+
+	return (0);
+}
+
+void
+platform_ipi_send(cpuset_t cpus, u_int ipi)
+{
+
+	pic_ipi_send(cpus, ipi);
+}

Added: head/sys/arm/annapurna/alpine/common.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/arm/annapurna/alpine/common.c	Fri May 15 18:25:48 2015	(r282985)
@@ -0,0 +1,158 @@
+/*-
+ * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.com>
+ * Copyright (c) 2015 Semihalf.
+ * 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 <sys/kernel.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/intr.h>
+
+#define WDTLOAD		0x000
+#define LOAD_MIN	0x00000001
+#define LOAD_MAX	0xFFFFFFFF
+#define WDTVALUE	0x004
+#define WDTCONTROL	0x008
+/* control register masks */
+#define INT_ENABLE	(1 << 0)
+#define RESET_ENABLE	(1 << 1)
+#define WDTLOCK		0xC00
+#define UNLOCK		0x1ACCE551
+#define LOCK		0x00000001
+
+extern bus_addr_t  al_devmap_pa;
+struct fdt_fixup_entry fdt_fixup_table[] = {
+	{ NULL, NULL }
+};
+
+static int alpine_get_wdt_base(uint32_t *pbase, uint32_t *psize);
+static int alpine_pic_decode_fdt(uint32_t iparent, uint32_t *intr,
+    int *interrupt, int *trig, int *pol);
+
+int alpine_get_devmap_base(bus_addr_t *pa, bus_addr_t *size);
+
+int alpine_get_devmap_base(bus_addr_t *pa, bus_addr_t *size)
+{
+	phandle_t node;
+
+	if ((node = OF_finddevice("/")) == 0)
+		return (ENXIO);
+
+	if ((node = fdt_find_compatible(node, "simple-bus", 1)) == 0)
+		return (ENXIO);
+
+	return fdt_get_range(node, 0, pa, size);
+}
+
+static int
+alpine_get_wdt_base(uint32_t *pbase, uint32_t *psize)
+{
+	phandle_t node;
+	u_long base = 0;
+	u_long size = 0;
+
+	if (pbase == NULL || psize == NULL)
+		return (EINVAL);
+
+	if ((node = OF_finddevice("/")) == -1)
+		return (EFAULT);
+
+	if ((node = fdt_find_compatible(node, "simple-bus", 1)) == 0)
+		return (EFAULT);
+
+	if ((node =
+	    fdt_find_compatible(node, "arm,sp805", 1)) == 0)
+		return (EFAULT);
+
+	if (fdt_regsize(node, &base, &size))
+		return (EFAULT);
+
+	*pbase = base;
+	*psize = size;
+
+	return (0);
+}
+
+void
+cpu_reset(void)
+{
+	uint32_t wdbase, wdsize;
+	bus_addr_t wdbaddr;
+	int ret;
+
+	ret = alpine_get_wdt_base(&wdbase, &wdsize);
+	if (ret) {
+		printf("Unable to get WDT base, do power down manually...");
+		goto infinite;
+	}
+
+	ret = bus_space_map(fdtbus_bs_tag, al_devmap_pa + wdbase,
+	    wdsize, 0, &wdbaddr);
+	if (ret) {
+		printf("Unable to map WDT base, do power down manually...");
+		goto infinite;
+	}
+
+	bus_space_write_4(fdtbus_bs_tag, wdbaddr, WDTLOCK, UNLOCK);
+	bus_space_write_4(fdtbus_bs_tag, wdbaddr, WDTLOAD, LOAD_MIN);
+	bus_space_write_4(fdtbus_bs_tag, wdbaddr, WDTCONTROL, INT_ENABLE | RESET_ENABLE);
+
+infinite:
+	while (1) {}
+}
+
+static int
+alpine_pic_decode_fdt(uint32_t iparent, uint32_t *intr, int *interrupt,
+    int *trig, int *pol)
+{
+	int rv = 0;
+
+	rv = gic_decode_fdt(iparent, intr, interrupt, trig, pol);
+	if (rv == 0) {
+		/* This was recognized as our PIC and decoded. */
+		interrupt = FDT_MAP_IRQ(iparent, interrupt);
+
+		/* Configure the interrupt if callback provided */
+		if (arm_config_irq)
+			(*arm_config_irq)(*interrupt, *trig, *pol);
+	}
+	return (rv);
+}
+
+fdt_pic_decode_t fdt_pic_table[] = {
+	&alpine_pic_decode_fdt,
+	NULL
+};

Added: head/sys/arm/annapurna/alpine/files.alpine
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/arm/annapurna/alpine/files.alpine	Fri May 15 18:25:48 2015	(r282985)
@@ -0,0 +1,16 @@
+# $FreeBSD$
+
+kern/kern_clocksource.c					standard
+
+arm/arm/bus_space_base.c				standard
+arm/arm/bus_space_generic.c				standard
+arm/arm/bus_space_asm_generic.S			standard
+
+arm/versatile/sp804.c					standard
+arm/versatile/versatile_timer.c			standard
+dev/uart/uart_dev_ns8250.c				optional	uart
+dev/ofw/ofw_cpu.c				standard
+
+arm/annapurna/alpine/common.c			standard
+arm/annapurna/alpine/alpine_machdep.c		standard
+arm/annapurna/alpine/alpine_machdep_mp.c	optional	smp

Added: head/sys/arm/annapurna/alpine/hal/al_hal_common.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/arm/annapurna/alpine/hal/al_hal_common.h	Fri May 15 18:25:48 2015	(r282985)
@@ -0,0 +1,70 @@
+/*-
+********************************************************************************
+Copyright (C) 2015 Annapurna Labs Ltd.
+
+This file may be licensed under the terms of the Annapurna Labs Commercial
+License Agreement.
+
+Alternatively, this file can be distributed under the terms of the GNU General
+Public License V2 as published by the Free Software Foundation and can be
+found at http://www.gnu.org/licenses/gpl-2.0.html
+
+Alternatively, redistribution and use in source and binary forms, with or
+without modification, are permitted provided that the following conditions are
+met:
+
+    *     Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+    *     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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+
+*******************************************************************************/
+
+/**
+ * @defgroup group_common HAL Common Layer
+ * Includes all common header files used by HAL
+ *  @{
+ * @file   al_hal_common.h
+ *
+ */
+
+#ifndef __AL_HAL_COMMON_H__
+#define __AL_HAL_COMMON_H__
+
+#include "al_hal_plat_types.h"
+#include "al_hal_plat_services.h"
+
+#include "al_hal_types.h"
+#include "al_hal_reg_utils.h"
+
+/* Get the maximal value out of two typed values */
+#define al_max_t(type, x, y) ({		\
+	type __max1 = (x);			\
+	type __max2 = (y);			\
+	__max1 > __max2 ? __max1 : __max2; })
+
+/* Get the minimal value out of two typed values */
+#define al_min_t(type, x, y) ({		\
+	type __min1 = (x);			\
+	type __min2 = (y);			\
+	__min1 < __min2 ? __min1 : __min2; })
+
+/* Get the number of elements in an array */
+#define AL_ARR_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+/** @} end of Common group */
+#endif				/* __AL_HAL_COMMON_H__ */

Added: head/sys/arm/annapurna/alpine/hal/al_hal_iofic.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/arm/annapurna/alpine/hal/al_hal_iofic.h	Fri May 15 18:25:48 2015	(r282985)
@@ -0,0 +1,222 @@
+/*-
+********************************************************************************
+Copyright (C) 2015 Annapurna Labs Ltd.
+
+This file may be licensed under the terms of the Annapurna Labs Commercial
+License Agreement.
+
+Alternatively, this file can be distributed under the terms of the GNU General
+Public License V2 as published by the Free Software Foundation and can be
+found at http://www.gnu.org/licenses/gpl-2.0.html
+
+Alternatively, redistribution and use in source and binary forms, with or
+without modification, are permitted provided that the following conditions are
+met:
+
+    *     Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+    *     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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+
+*******************************************************************************/
+
+/**
+ * @defgroup group_interrupts Common I/O Fabric Interrupt Controller
+ * This HAL provides the API for programming the Common I/O Fabric Interrupt
+ * Controller (IOFIC) found in most of the units attached to the I/O Fabric of
+ * Alpine platform
+ *  @{
+ * @file   al_hal_iofic.h
+ *
+ * @brief Header file for the interrupt controller that's embedded in various units
+ *
+ */
+
+#ifndef __AL_HAL_IOFIC_H__
+#define __AL_HAL_IOFIC_H__
+
+#include <al_hal_common.h>
+
+/* *INDENT-OFF* */
+#ifdef __cplusplus
+extern "C" {
+#endif
+/* *INDENT-ON* */
+
+#define AL_IOFIC_MAX_GROUPS	4
+
+/*
+ * Configurations
+ */
+
+/**
+ * Configure the interrupt controller registers, actual interrupts are still
+ * masked at this stage.
+ *
+ * @param regs_base regs pointer to interrupt controller registers
+ * @param group the interrupt group.
+ * @param flags flags of Interrupt Control Register
+ *
+ * @return 0 on success. -EINVAL otherwise.
+ */
+int al_iofic_config(void __iomem *regs_base, int group,
+		   uint32_t flags);
+
+/**
+ * configure the moderation timer resolution for a given group
+ * Applies for both msix and legacy mode.
+ *
+ * @param regs_base pointer to unit registers
+ * @param group the interrupt group
+ * @param resolution resolution of the timer interval, the resolution determines the rate
+ * of decrementing the interval timer, setting value N means that the interval
+ * timer will be decremented each (N+1) * (0.68) micro seconds.
+ *
+ * @return 0 on success. -EINVAL otherwise.
+ */
+int al_iofic_moder_res_config(void __iomem *regs_base, int group,
+			     uint8_t resolution);
+
+/**
+ * configure the moderation timer interval for a given legacy interrupt group
+ *
+ * @param regs_base regs pointer to unit registers
+ * @param group the interrupt group
+ * @param interval between interrupts in resolution units. 0 disable
+ *
+ * @return 0 on success. -EINVAL otherwise.
+ */
+int al_iofic_legacy_moder_interval_config(void __iomem *regs_base, int group,
+					 uint8_t interval);
+
+/**
+ * configure the moderation timer interval for a given msix vector
+ *
+ * @param regs_base pointer to unit registers
+ * @param group the interrupt group
+ * @param vector vector index
+ * @param interval interval between interrupts, 0 disable
+ *
+ * @return 0 on success. -EINVAL otherwise.
+ */
+int al_iofic_msix_moder_interval_config(void __iomem *regs_base, int group,
+				       uint8_t vector, uint8_t interval);
+
+/**
+* configure the vmid attributes for a given msix vector.
+*
+* @param group the interrupt group
+* @param vector index
+* @param vmid the vmid value
+* @param vmid_en take vmid from the intc
+*
+* @return 0 on success. -EINVAL otherwise.
+*/
+int al_iofic_msix_vmid_attributes_config(void __iomem *regs_base, int group,
+				       uint8_t vector, uint32_t vmid, uint8_t vmid_en);
+
+/**
+ * return the offset of the unmask register for a given group.
+ * this function can be used when the upper layer wants to directly
+ * access the unmask regiter and bypass the al_iofic_unmask() API.
+ *
+ * @param regs_base regs pointer to unit registers
+ * @param group the interrupt group
+ * @return the offset of the unmask register.
+ */
+uint32_t __iomem * al_iofic_unmask_offset_get(void __iomem *regs_base, int group);
+
+/**
+ * unmask specific interrupts for a given group
+ * this functions guarantees atomic operations, it is performance optimized as
+ * it will not require read-modify-write. The unmask done using the interrupt
+ * mask clear register, so it's safe to call it while the mask is changed by
+ * the HW (auto mask) or another core.
+ *
+ * @param regs_base pointer to unit registers
+ * @param group the interrupt group
+ * @param mask bitwise of interrupts to unmask, set bits will be unmasked.
+ */
+void al_iofic_unmask(void __iomem *regs_base, int group, uint32_t mask);
+
+/**
+ * mask specific interrupts for a given group
+ * this functions modifies interrupt mask register, the callee must make sure
+ * the mask is not changed by another cpu.
+ *
+ * @param regs_base pointer to unit registers
+ * @param group the interrupt group
+ * @param mask bitwise of interrupts to mask, set bits will be masked.
+ */
+void al_iofic_mask(void __iomem *regs_base, int group, uint32_t mask);
+
+/**
+ * read the mask register for a given group
+ * this functions return the interrupt mask register
+ *
+ * @param regs_base pointer to unit registers
+ * @param group the interrupt group
+ */
+uint32_t al_iofic_read_mask(void __iomem *regs_base, int group);
+
+/**
+ * read interrupt cause register for a given group
+ * this will clear the set bits if the Clear on Read mode enabled.
+ * @param regs_base pointer to unit registers
+ * @param group the interrupt group
+ */
+uint32_t al_iofic_read_cause(void __iomem *regs_base, int group);
+
+/**
+ * clear bits in the interrupt cause register for a given group
+ *
+ * @param regs_base pointer to unit registers
+ * @param group the interrupt group
+ * @param mask bitwise of bits to be cleared, set bits will be cleared.
+ */
+void al_iofic_clear_cause(void __iomem *regs_base, int group, uint32_t mask);
+
+/**
+ * set the cause register for a given group
+ * this function set the cause register. It will generate an interrupt (if
+ * the the interrupt isn't masked )
+ *
+ * @param regs_base pointer to unit registers
+ * @param group the interrupt group
+ * @param mask bitwise of bits to be set.
+ */
+void al_iofic_set_cause(void __iomem *regs_base, int group, uint32_t mask);
+
+/**
+ * unmask specific interrupts from aborting the udma a given group
+ *
+ * @param regs_base pointer to unit registers
+ * @param group the interrupt group
+ * @param mask bitwise of interrupts to mask
+ */
+void al_iofic_abort_mask(void __iomem *regs_base, int group, uint32_t mask);
+
+/**
+ * trigger all interrupts that are waiting for moderation timers to expire
+ *
+ * @param regs_base pointer to unit registers
+ * @param group the interrupt group
+ */
+void al_iofic_interrupt_moderation_reset(void __iomem *regs_base, int group);
+
+#endif
+/** @} end of interrupt controller group */

Added: head/sys/arm/annapurna/alpine/hal/al_hal_iofic_regs.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/arm/annapurna/alpine/hal/al_hal_iofic_regs.h	Fri May 15 18:25:48 2015	(r282985)
@@ -0,0 +1,127 @@
+/*_
+********************************************************************************
+Copyright (C) 2015 Annapurna Labs Ltd.
+
+This file may be licensed under the terms of the Annapurna Labs Commercial
+License Agreement.
+
+Alternatively, this file can be distributed under the terms of the GNU General
+Public License V2 as published by the Free Software Foundation and can be
+found at http://www.gnu.org/licenses/gpl-2.0.html
+
+Alternatively, redistribution and use in source and binary forms, with or
+without modification, are permitted provided that the following conditions are
+met:
+
+    *     Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+    *     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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201505151825.t4FIPnxJ099637>