1/*- 2 * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.com> 3 * Copyright (c) 2015 Semihalf 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 */ 28 29#include "opt_ddb.h" 30#include "opt_platform.h" 31 32#include <sys/cdefs.h> 33__FBSDID("$FreeBSD$"); 34 35#include <sys/param.h> 36#include <sys/systm.h> 37#include <sys/bus.h> 38#include <sys/devmap.h> 39 40#include <vm/vm.h> 41#include <vm/pmap.h> 42 43#include <machine/bus.h> 44#include <machine/fdt.h> 45#include <machine/platformvar.h> 46 47#include <dev/fdt/fdt_common.h> 48#include <dev/ofw/openfirm.h> 49 50#include <arm/annapurna/alpine/alpine_mp.h> 51 52#include "platform_if.h" 53 54#define WDTLOAD 0x000 55#define LOAD_MIN 0x00000001 56#define LOAD_MAX 0xFFFFFFFF 57#define WDTVALUE 0x004 58#define WDTCONTROL 0x008 59/* control register masks */ 60#define INT_ENABLE (1 << 0) 61#define RESET_ENABLE (1 << 1) 62#define WDTLOCK 0xC00 63#define UNLOCK 0x1ACCE551 64#define LOCK 0x00000001 65 66bus_addr_t al_devmap_pa; 67bus_addr_t al_devmap_size; 68 69static int 70alpine_get_devmap_base(bus_addr_t *pa, bus_addr_t *size) 71{ 72 phandle_t node; 73 74 if ((node = OF_finddevice("/")) == -1) 75 return (ENXIO); 76 77 if ((node = fdt_find_compatible(node, "simple-bus", 1)) == 0) 78 return (ENXIO); 79 80 return fdt_get_range(node, 0, pa, size); 81} 82 83static int 84alpine_get_wdt_base(uint32_t *pbase, uint32_t *psize) 85{ 86 phandle_t node; 87 u_long base = 0; 88 u_long size = 0; 89 90 if (pbase == NULL || psize == NULL) 91 return (EINVAL); 92 93 if ((node = OF_finddevice("/")) == -1) 94 return (EFAULT); 95 96 if ((node = fdt_find_compatible(node, "simple-bus", 1)) == 0) 97 return (EFAULT); 98 99 if ((node = 100 fdt_find_compatible(node, "arm,sp805", 1)) == 0) 101 return (EFAULT); 102 103 if (fdt_regsize(node, &base, &size)) 104 return (EFAULT); 105 106 *pbase = base; 107 *psize = size; 108 109 return (0); 110} 111 112/* 113 * Construct devmap table with DT-derived config data. 114 */ 115static int 116alpine_devmap_init(platform_t plat) 117{ 118 alpine_get_devmap_base(&al_devmap_pa, &al_devmap_size); 119 devmap_add_entry(al_devmap_pa, al_devmap_size); 120 return (0); 121} 122 123static void 124alpine_cpu_reset(platform_t plat) 125{ 126 uint32_t wdbase, wdsize; 127 bus_addr_t wdbaddr; 128 int ret; 129 130 ret = alpine_get_wdt_base(&wdbase, &wdsize); 131 if (ret) { 132 printf("Unable to get WDT base, do power down manually..."); 133 goto infinite; 134 } 135 136 ret = bus_space_map(fdtbus_bs_tag, al_devmap_pa + wdbase, 137 wdsize, 0, &wdbaddr); 138 if (ret) { 139 printf("Unable to map WDT base, do power down manually..."); 140 goto infinite; 141 } 142 143 bus_space_write_4(fdtbus_bs_tag, wdbaddr, WDTLOCK, UNLOCK); 144 bus_space_write_4(fdtbus_bs_tag, wdbaddr, WDTLOAD, LOAD_MIN); 145 bus_space_write_4(fdtbus_bs_tag, wdbaddr, WDTCONTROL, 146 INT_ENABLE | RESET_ENABLE); 147 148infinite: 149 while (1) {} 150} 151 152static platform_method_t alpine_methods[] = { 153 PLATFORMMETHOD(platform_devmap_init, alpine_devmap_init), 154 PLATFORMMETHOD(platform_cpu_reset, alpine_cpu_reset), 155 156#ifdef SMP 157 PLATFORMMETHOD(platform_mp_start_ap, alpine_mp_start_ap), 158 PLATFORMMETHOD(platform_mp_setmaxid, alpine_mp_setmaxid), 159#endif 160 PLATFORMMETHOD_END, 161}; 162FDT_PLATFORM_DEF(alpine, "alpine", 0, "annapurna,alpine", 200); 163