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