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 <b...@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 <b...@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 <b...@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 ***
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to