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 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/bus.h> 36 #include <sys/devmap.h> 37 38 #include <vm/vm.h> 39 #include <vm/pmap.h> 40 41 #include <machine/bus.h> 42 #include <machine/fdt.h> 43 #include <machine/platformvar.h> 44 45 #include <dev/fdt/fdt_common.h> 46 #include <dev/ofw/openfirm.h> 47 48 #include <arm/annapurna/alpine/alpine_mp.h> 49 50 #include "platform_if.h" 51 52 #define WDTLOAD 0x000 53 #define LOAD_MIN 0x00000001 54 #define LOAD_MAX 0xFFFFFFFF 55 #define WDTVALUE 0x004 56 #define WDTCONTROL 0x008 57 /* control register masks */ 58 #define INT_ENABLE (1 << 0) 59 #define RESET_ENABLE (1 << 1) 60 #define WDTLOCK 0xC00 61 #define UNLOCK 0x1ACCE551 62 #define LOCK 0x00000001 63 64 bus_addr_t al_devmap_pa; 65 bus_addr_t al_devmap_size; 66 67 static int 68 alpine_get_devmap_base(bus_addr_t *pa, bus_addr_t *size) 69 { 70 phandle_t node; 71 72 if ((node = OF_finddevice("/")) == -1) 73 return (ENXIO); 74 75 if ((node = fdt_find_compatible(node, "simple-bus", 1)) == 0) 76 return (ENXIO); 77 78 return fdt_get_range(node, 0, pa, size); 79 } 80 81 static int 82 alpine_get_wdt_base(uint32_t *pbase, uint32_t *psize) 83 { 84 phandle_t node; 85 u_long base = 0; 86 u_long size = 0; 87 88 if (pbase == NULL || psize == NULL) 89 return (EINVAL); 90 91 if ((node = OF_finddevice("/")) == -1) 92 return (EFAULT); 93 94 if ((node = fdt_find_compatible(node, "simple-bus", 1)) == 0) 95 return (EFAULT); 96 97 if ((node = 98 fdt_find_compatible(node, "arm,sp805", 1)) == 0) 99 return (EFAULT); 100 101 if (fdt_regsize(node, &base, &size)) 102 return (EFAULT); 103 104 *pbase = base; 105 *psize = size; 106 107 return (0); 108 } 109 110 /* 111 * Construct devmap table with DT-derived config data. 112 */ 113 static int 114 alpine_devmap_init(platform_t plat) 115 { 116 alpine_get_devmap_base(&al_devmap_pa, &al_devmap_size); 117 devmap_add_entry(al_devmap_pa, al_devmap_size); 118 return (0); 119 } 120 121 static void 122 alpine_cpu_reset(platform_t plat) 123 { 124 uint32_t wdbase, wdsize; 125 bus_addr_t wdbaddr; 126 int ret; 127 128 ret = alpine_get_wdt_base(&wdbase, &wdsize); 129 if (ret) { 130 printf("Unable to get WDT base, do power down manually..."); 131 goto infinite; 132 } 133 134 ret = bus_space_map(fdtbus_bs_tag, al_devmap_pa + wdbase, 135 wdsize, 0, &wdbaddr); 136 if (ret) { 137 printf("Unable to map WDT base, do power down manually..."); 138 goto infinite; 139 } 140 141 bus_space_write_4(fdtbus_bs_tag, wdbaddr, WDTLOCK, UNLOCK); 142 bus_space_write_4(fdtbus_bs_tag, wdbaddr, WDTLOAD, LOAD_MIN); 143 bus_space_write_4(fdtbus_bs_tag, wdbaddr, WDTCONTROL, 144 INT_ENABLE | RESET_ENABLE); 145 146 infinite: 147 while (1) {} 148 } 149 150 static platform_method_t alpine_methods[] = { 151 PLATFORMMETHOD(platform_devmap_init, alpine_devmap_init), 152 PLATFORMMETHOD(platform_cpu_reset, alpine_cpu_reset), 153 154 #ifdef SMP 155 PLATFORMMETHOD(platform_mp_start_ap, alpine_mp_start_ap), 156 PLATFORMMETHOD(platform_mp_setmaxid, alpine_mp_setmaxid), 157 #endif 158 PLATFORMMETHOD_END, 159 }; 160 FDT_PLATFORM_DEF(alpine, "alpine", 0, "annapurna,alpine", 200); 161