svn commit: r282985 - in head/sys: arm/annapurna arm/annapurna/alpine arm/annapurna/alpine/hal arm/conf boot/fdt/dts/arm
Zbigniew Bodek
zbb at FreeBSD.org
Fri May 15 18:25:51 UTC 2015
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 at 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,
+ ®_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 at 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 at 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 ***
More information about the svn-src-head
mailing list