From owner-svn-src-head@FreeBSD.ORG Fri May 15 18:25:51 2015 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 5F764507; Fri, 15 May 2015 18:25:51 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 4C3D810DC; Fri, 15 May 2015 18:25:51 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t4FIPp1j099650; Fri, 15 May 2015 18:25:51 GMT (envelope-from zbb@FreeBSD.org) Received: (from zbb@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t4FIPnxJ099637; Fri, 15 May 2015 18:25:49 GMT (envelope-from zbb@FreeBSD.org) Message-Id: <201505151825.t4FIPnxJ099637@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: zbb set sender to zbb@FreeBSD.org using -f From: Zbigniew Bodek Date: Fri, 15 May 2015 18:25:49 +0000 (UTC) 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 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 15 May 2015 18:25:51 -0000 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 + * 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 +__FBSDID("$FreeBSD$"); + +#define _ARM32_BUS_DMA_PRIVATE +#include +#include +#include +#include +#include + +#include +#include + +#include +#include /* For trapframe_t, used in */ +#include +#include +#include +#include +#include + +#include + +#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 + * 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 +__FBSDID("$FreeBSD$"); +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#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 + * 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#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 + +/* *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 ***