14d892e4fSZbigniew Bodek /*-
24d892e4fSZbigniew Bodek * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.com>
34d892e4fSZbigniew Bodek * Copyright (c) 2015 Semihalf
44d892e4fSZbigniew Bodek * All rights reserved.
54d892e4fSZbigniew Bodek *
64d892e4fSZbigniew Bodek * Redistribution and use in source and binary forms, with or without
74d892e4fSZbigniew Bodek * modification, are permitted provided that the following conditions
84d892e4fSZbigniew Bodek * are met:
94d892e4fSZbigniew Bodek * 1. Redistributions of source code must retain the above copyright
104d892e4fSZbigniew Bodek * notice, this list of conditions and the following disclaimer.
114d892e4fSZbigniew Bodek * 2. Redistributions in binary form must reproduce the above copyright
124d892e4fSZbigniew Bodek * notice, this list of conditions and the following disclaimer in the
134d892e4fSZbigniew Bodek * documentation and/or other materials provided with the distribution.
144d892e4fSZbigniew Bodek *
154d892e4fSZbigniew Bodek * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
164d892e4fSZbigniew Bodek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
174d892e4fSZbigniew Bodek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
184d892e4fSZbigniew Bodek * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
194d892e4fSZbigniew Bodek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
204d892e4fSZbigniew Bodek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
214d892e4fSZbigniew Bodek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
224d892e4fSZbigniew Bodek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
234d892e4fSZbigniew Bodek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
244d892e4fSZbigniew Bodek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
254d892e4fSZbigniew Bodek * SUCH DAMAGE.
264d892e4fSZbigniew Bodek *
274d892e4fSZbigniew Bodek */
284d892e4fSZbigniew Bodek
29c20963adSAndrew Turner #include "opt_ddb.h"
30c20963adSAndrew Turner #include "opt_platform.h"
31c20963adSAndrew Turner
324d892e4fSZbigniew Bodek #include <sys/param.h>
334d892e4fSZbigniew Bodek #include <sys/systm.h>
344d892e4fSZbigniew Bodek #include <sys/bus.h>
35*781a630dSOskar Holmlund #include <sys/devmap.h>
364d892e4fSZbigniew Bodek
374d892e4fSZbigniew Bodek #include <vm/vm.h>
384d892e4fSZbigniew Bodek #include <vm/pmap.h>
394d892e4fSZbigniew Bodek
404d892e4fSZbigniew Bodek #include <machine/bus.h>
414d892e4fSZbigniew Bodek #include <machine/fdt.h>
42c20963adSAndrew Turner #include <machine/platformvar.h>
434d892e4fSZbigniew Bodek
44c20963adSAndrew Turner #include <dev/fdt/fdt_common.h>
45c20963adSAndrew Turner #include <dev/ofw/openfirm.h>
464d892e4fSZbigniew Bodek
47c20963adSAndrew Turner #include <arm/annapurna/alpine/alpine_mp.h>
48c20963adSAndrew Turner
49c20963adSAndrew Turner #include "platform_if.h"
50c20963adSAndrew Turner
51c20963adSAndrew Turner #define WDTLOAD 0x000
52c20963adSAndrew Turner #define LOAD_MIN 0x00000001
53c20963adSAndrew Turner #define LOAD_MAX 0xFFFFFFFF
54c20963adSAndrew Turner #define WDTVALUE 0x004
55c20963adSAndrew Turner #define WDTCONTROL 0x008
56c20963adSAndrew Turner /* control register masks */
57c20963adSAndrew Turner #define INT_ENABLE (1 << 0)
58c20963adSAndrew Turner #define RESET_ENABLE (1 << 1)
59c20963adSAndrew Turner #define WDTLOCK 0xC00
60c20963adSAndrew Turner #define UNLOCK 0x1ACCE551
61c20963adSAndrew Turner #define LOCK 0x00000001
62c20963adSAndrew Turner
634d892e4fSZbigniew Bodek bus_addr_t al_devmap_pa;
644d892e4fSZbigniew Bodek bus_addr_t al_devmap_size;
654d892e4fSZbigniew Bodek
66c20963adSAndrew Turner static int
alpine_get_devmap_base(bus_addr_t * pa,bus_addr_t * size)67c20963adSAndrew Turner alpine_get_devmap_base(bus_addr_t *pa, bus_addr_t *size)
684d892e4fSZbigniew Bodek {
69c20963adSAndrew Turner phandle_t node;
704d892e4fSZbigniew Bodek
71108117ccSOleksandr Tymoshenko if ((node = OF_finddevice("/")) == -1)
72c20963adSAndrew Turner return (ENXIO);
73c20963adSAndrew Turner
74c20963adSAndrew Turner if ((node = fdt_find_compatible(node, "simple-bus", 1)) == 0)
75c20963adSAndrew Turner return (ENXIO);
76c20963adSAndrew Turner
77c20963adSAndrew Turner return fdt_get_range(node, 0, pa, size);
784d892e4fSZbigniew Bodek }
794d892e4fSZbigniew Bodek
80c20963adSAndrew Turner static int
alpine_get_wdt_base(uint32_t * pbase,uint32_t * psize)81c20963adSAndrew Turner alpine_get_wdt_base(uint32_t *pbase, uint32_t *psize)
824d892e4fSZbigniew Bodek {
83c20963adSAndrew Turner phandle_t node;
84c20963adSAndrew Turner u_long base = 0;
85c20963adSAndrew Turner u_long size = 0;
864d892e4fSZbigniew Bodek
87c20963adSAndrew Turner if (pbase == NULL || psize == NULL)
88c20963adSAndrew Turner return (EINVAL);
894d892e4fSZbigniew Bodek
90c20963adSAndrew Turner if ((node = OF_finddevice("/")) == -1)
91c20963adSAndrew Turner return (EFAULT);
924d892e4fSZbigniew Bodek
93c20963adSAndrew Turner if ((node = fdt_find_compatible(node, "simple-bus", 1)) == 0)
94c20963adSAndrew Turner return (EFAULT);
954d892e4fSZbigniew Bodek
96c20963adSAndrew Turner if ((node =
97c20963adSAndrew Turner fdt_find_compatible(node, "arm,sp805", 1)) == 0)
98c20963adSAndrew Turner return (EFAULT);
994d892e4fSZbigniew Bodek
100c20963adSAndrew Turner if (fdt_regsize(node, &base, &size))
101c20963adSAndrew Turner return (EFAULT);
102c20963adSAndrew Turner
103c20963adSAndrew Turner *pbase = base;
104c20963adSAndrew Turner *psize = size;
105c20963adSAndrew Turner
106c20963adSAndrew Turner return (0);
1074d892e4fSZbigniew Bodek }
1084d892e4fSZbigniew Bodek
1094d892e4fSZbigniew Bodek /*
110e81df523SSvatopluk Kraus * Construct devmap table with DT-derived config data.
1114d892e4fSZbigniew Bodek */
112c20963adSAndrew Turner static int
alpine_devmap_init(platform_t plat)113c20963adSAndrew Turner alpine_devmap_init(platform_t plat)
1144d892e4fSZbigniew Bodek {
1154d892e4fSZbigniew Bodek alpine_get_devmap_base(&al_devmap_pa, &al_devmap_size);
11630b72b68SRuslan Bukin devmap_add_entry(al_devmap_pa, al_devmap_size);
1174d892e4fSZbigniew Bodek return (0);
1184d892e4fSZbigniew Bodek }
119c20963adSAndrew Turner
120c20963adSAndrew Turner static void
alpine_cpu_reset(platform_t plat)121c20963adSAndrew Turner alpine_cpu_reset(platform_t plat)
122c20963adSAndrew Turner {
123c20963adSAndrew Turner uint32_t wdbase, wdsize;
124c20963adSAndrew Turner bus_addr_t wdbaddr;
125c20963adSAndrew Turner int ret;
126c20963adSAndrew Turner
127c20963adSAndrew Turner ret = alpine_get_wdt_base(&wdbase, &wdsize);
128c20963adSAndrew Turner if (ret) {
129c20963adSAndrew Turner printf("Unable to get WDT base, do power down manually...");
130c20963adSAndrew Turner goto infinite;
131c20963adSAndrew Turner }
132c20963adSAndrew Turner
133c20963adSAndrew Turner ret = bus_space_map(fdtbus_bs_tag, al_devmap_pa + wdbase,
134c20963adSAndrew Turner wdsize, 0, &wdbaddr);
135c20963adSAndrew Turner if (ret) {
136c20963adSAndrew Turner printf("Unable to map WDT base, do power down manually...");
137c20963adSAndrew Turner goto infinite;
138c20963adSAndrew Turner }
139c20963adSAndrew Turner
140c20963adSAndrew Turner bus_space_write_4(fdtbus_bs_tag, wdbaddr, WDTLOCK, UNLOCK);
141c20963adSAndrew Turner bus_space_write_4(fdtbus_bs_tag, wdbaddr, WDTLOAD, LOAD_MIN);
142c20963adSAndrew Turner bus_space_write_4(fdtbus_bs_tag, wdbaddr, WDTCONTROL,
143c20963adSAndrew Turner INT_ENABLE | RESET_ENABLE);
144c20963adSAndrew Turner
145c20963adSAndrew Turner infinite:
146c20963adSAndrew Turner while (1) {}
147c20963adSAndrew Turner }
148c20963adSAndrew Turner
149c20963adSAndrew Turner static platform_method_t alpine_methods[] = {
150c20963adSAndrew Turner PLATFORMMETHOD(platform_devmap_init, alpine_devmap_init),
151c20963adSAndrew Turner PLATFORMMETHOD(platform_cpu_reset, alpine_cpu_reset),
152c20963adSAndrew Turner
153c20963adSAndrew Turner #ifdef SMP
154c20963adSAndrew Turner PLATFORMMETHOD(platform_mp_start_ap, alpine_mp_start_ap),
155c20963adSAndrew Turner PLATFORMMETHOD(platform_mp_setmaxid, alpine_mp_setmaxid),
156c20963adSAndrew Turner #endif
157c20963adSAndrew Turner PLATFORMMETHOD_END,
158c20963adSAndrew Turner };
159c20963adSAndrew Turner FDT_PLATFORM_DEF(alpine, "alpine", 0, "annapurna,alpine", 200);
160