1 /*
2 * xen/arch/arm/platform_vexpress.c
3 *
4 * Versatile Express specific settings
5 *
6 * Stefano Stabellini <stefano.stabellini@eu.citrix.com>
7 * Copyright (c) 2013 Citrix Systems.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 */
19
20 #include <asm/platforms/vexpress.h>
21 #include <asm/platform.h>
22 #include <xen/mm.h>
23 #include <xen/vmap.h>
24 #include <asm/io.h>
25
26 #define DCC_SHIFT 26
27 #define FUNCTION_SHIFT 20
28 #define SITE_SHIFT 16
29 #define POSITION_SHIFT 12
30 #define DEVICE_SHIFT 0
31
vexpress_ctrl_start(uint32_t * syscfg,int write,int function,int device)32 static inline int vexpress_ctrl_start(uint32_t *syscfg, int write,
33 int function, int device)
34 {
35 int dcc = 0; /* DCC to access */
36 int site = 0; /* motherboard */
37 int position = 0; /* daughterboard */
38 uint32_t stat;
39
40 /* set control register */
41 syscfg[V2M_SYS_CFGCTRL/4] = V2M_SYS_CFG_START |
42 (write ? V2M_SYS_CFG_WRITE : 0) |
43 (dcc << DCC_SHIFT) | (function << FUNCTION_SHIFT) |
44 (site << SITE_SHIFT) | (position << POSITION_SHIFT) |
45 (device << DEVICE_SHIFT);
46
47 /* wait for complete flag to be set */
48 do {
49 stat = syscfg[V2M_SYS_CFGSTAT/4];
50 dsb(sy);
51 } while ( !(stat & V2M_SYS_CFG_COMPLETE) );
52
53 /* check error status and return error flag if set */
54 if ( stat & V2M_SYS_CFG_ERROR )
55 {
56 printk(KERN_ERR "V2M SYS_CFGSTAT reported a configuration error\n");
57 return -1;
58 }
59 return 0;
60 }
61
62 /*
63 * TODO: Get base address from the device tree
64 * See arm,vexpress-reset node
65 */
vexpress_reset(void)66 static void vexpress_reset(void)
67 {
68 void __iomem *sp810;
69
70 /* Use the SP810 system controller to force a reset */
71 sp810 = ioremap_nocache(SP810_ADDRESS, PAGE_SIZE);
72
73 if ( !sp810 )
74 {
75 dprintk(XENLOG_ERR, "Unable to map SP810\n");
76 return;
77 }
78
79 /* switch to slow mode */
80 writel(0x3, sp810);
81 dsb(sy); isb();
82 /* writing any value to SCSYSSTAT reg will reset the system */
83 writel(0x1, sp810 + 4);
84 dsb(sy); isb();
85
86 iounmap(sp810);
87 }
88
89 #ifdef CONFIG_ARM_32
90
vexpress_smp_init(void)91 static int __init vexpress_smp_init(void)
92 {
93 void __iomem *sysflags;
94
95 sysflags = ioremap_nocache(V2M_SYS_MMIO_BASE, PAGE_SIZE);
96 if ( !sysflags )
97 {
98 dprintk(XENLOG_ERR, "Unable to map vexpress MMIO\n");
99 return -EFAULT;
100 }
101
102 printk("Set SYS_FLAGS to %"PRIpaddr" (%p)\n",
103 __pa(init_secondary), init_secondary);
104 writel(~0, sysflags + V2M_SYS_FLAGSCLR);
105 writel(__pa(init_secondary), sysflags + V2M_SYS_FLAGSSET);
106
107 iounmap(sysflags);
108
109 return 0;
110 }
111
112 #endif
113
114 static const char * const vexpress_dt_compat[] __initconst =
115 {
116 "arm,vexpress",
117 NULL
118 };
119
120 static const struct dt_device_match vexpress_blacklist_dev[] __initconst =
121 {
122 /* Cache Coherent Interconnect */
123 DT_MATCH_COMPATIBLE("arm,cci-400"),
124 DT_MATCH_COMPATIBLE("arm,cci-400-pmu"),
125 /* Video device
126 * TODO: remove it once memreserve is handled properly by Xen
127 */
128 DT_MATCH_COMPATIBLE("arm,hdlcd"),
129 /* Hardware power management */
130 DT_MATCH_COMPATIBLE("arm,vexpress-reset"),
131 DT_MATCH_COMPATIBLE("arm,vexpress-reboot"),
132 DT_MATCH_COMPATIBLE("arm,vexpress-shutdown"),
133 { /* sentinel */ },
134 };
135
136 PLATFORM_START(vexpress, "VERSATILE EXPRESS")
137 .compatible = vexpress_dt_compat,
138 #ifdef CONFIG_ARM_32
139 .smp_init = vexpress_smp_init,
140 .cpu_up = cpu_up_send_sgi,
141 #endif
142 .reset = vexpress_reset,
143 .blacklist_dev = vexpress_blacklist_dev,
144 PLATFORM_END
145
146 /*
147 * Local variables:
148 * mode: C
149 * c-file-style: "BSD"
150 * c-basic-offset: 4
151 * indent-tabs-mode: nil
152 * End:
153 */
154