1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
/*
* xen/arch/arm/platforms/brcm-raspberry-pi.c
*
* Raspberry Pi 4 Platform specific settings.
*
* Stewart Hildebrand <stewart.hildebrand@dornerworks.com>
* Copyright (c) 2019 DornerWorks, Ltd
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <xen/delay.h>
#include <xen/mm.h>
#include <xen/vmap.h>
#include <asm/io.h>
#include <asm/platform.h>
static const char *const rpi4_dt_compat[] __initconst =
{
"brcm,bcm2711",
NULL
};
static const struct dt_device_match rpi4_blacklist_dev[] __initconst =
{
/*
* The aux SPIs share an IRQ and a page with the aux UART.
* If the same page gets mapped to dom0 and Xen, there is risk of
* dom0 writing to the UART that Xen controls.
*/
DT_MATCH_COMPATIBLE("brcm,bcm2835-aux-spi"),
/*
* The aux peripheral also shares a page with the aux UART.
*/
DT_MATCH_COMPATIBLE("brcm,bcm2835-aux"),
/* Special device used for rebooting */
DT_MATCH_COMPATIBLE("brcm,bcm2835-pm"),
{ /* sentinel */ },
};
#define PM_PASSWORD 0x5a000000
#define PM_RSTC 0x1c
#define PM_WDOG 0x24
#define PM_RSTC_WRCFG_FULL_RESET 0x00000020
#define PM_RSTC_WRCFG_CLR 0xffffffcf
static void __iomem *rpi4_map_watchdog(void)
{
void __iomem *base;
struct dt_device_node *node;
paddr_t start, len;
int ret;
node = dt_find_compatible_node(NULL, NULL, "brcm,bcm2835-pm");
if ( !node )
return NULL;
ret = dt_device_get_address(node, 0, &start, &len);
if ( ret )
{
printk("Cannot read watchdog register address\n");
return NULL;
}
base = ioremap_nocache(start & PAGE_MASK, PAGE_SIZE);
if ( !base )
{
printk("Unable to map watchdog register!\n");
return NULL;
}
return base;
}
static void rpi4_reset(void)
{
uint32_t val;
void __iomem *base = rpi4_map_watchdog();
if ( !base )
return;
/* use a timeout of 10 ticks (~150us) */
writel(10 | PM_PASSWORD, base + PM_WDOG);
val = readl(base + PM_RSTC);
val &= PM_RSTC_WRCFG_CLR;
val |= PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET;
writel(val, base + PM_RSTC);
/* No sleeping, possibly atomic. */
mdelay(1);
}
PLATFORM_START(rpi4, "Raspberry Pi 4")
.compatible = rpi4_dt_compat,
.blacklist_dev = rpi4_blacklist_dev,
.reset = rpi4_reset,
.dma_bitsize = 30,
PLATFORM_END
/*
* Local variables:
* mode: C
* c-file-style: "BSD"
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*/
|