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 66 bus_addr_t al_devmap_pa; 67 bus_addr_t al_devmap_size; 68 69 static int 70 alpine_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 83 static int 84 alpine_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 */ 115 static int 116 alpine_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 123 static void 124 alpine_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 148 infinite: 149 while (1) {} 150 } 151 152 static 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 }; 162 FDT_PLATFORM_DEF(alpine, "alpine", 0, "annapurna,alpine", 200); 163