Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/powerpc/platforms/embedded6xx/wii.c
10818 views
1
/*
2
* arch/powerpc/platforms/embedded6xx/wii.c
3
*
4
* Nintendo Wii board-specific support
5
* Copyright (C) 2008-2009 The GameCube Linux Team
6
* Copyright (C) 2008,2009 Albert Herranz
7
*
8
* This program is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU General Public License
10
* as published by the Free Software Foundation; either version 2
11
* of the License, or (at your option) any later version.
12
*
13
*/
14
#define DRV_MODULE_NAME "wii"
15
#define pr_fmt(fmt) DRV_MODULE_NAME ": " fmt
16
17
#include <linux/kernel.h>
18
#include <linux/init.h>
19
#include <linux/irq.h>
20
#include <linux/seq_file.h>
21
#include <linux/of_platform.h>
22
#include <linux/memblock.h>
23
#include <mm/mmu_decl.h>
24
25
#include <asm/io.h>
26
#include <asm/machdep.h>
27
#include <asm/prom.h>
28
#include <asm/time.h>
29
#include <asm/udbg.h>
30
31
#include "flipper-pic.h"
32
#include "hlwd-pic.h"
33
#include "usbgecko_udbg.h"
34
35
/* control block */
36
#define HW_CTRL_COMPATIBLE "nintendo,hollywood-control"
37
38
#define HW_CTRL_RESETS 0x94
39
#define HW_CTRL_RESETS_SYS (1<<0)
40
41
/* gpio */
42
#define HW_GPIO_COMPATIBLE "nintendo,hollywood-gpio"
43
44
#define HW_GPIO_BASE(idx) (idx * 0x20)
45
#define HW_GPIO_OUT(idx) (HW_GPIO_BASE(idx) + 0)
46
#define HW_GPIO_DIR(idx) (HW_GPIO_BASE(idx) + 4)
47
48
#define HW_GPIO_SHUTDOWN (1<<1)
49
#define HW_GPIO_SLOT_LED (1<<5)
50
#define HW_GPIO_SENSOR_BAR (1<<8)
51
52
53
static void __iomem *hw_ctrl;
54
static void __iomem *hw_gpio;
55
56
unsigned long wii_hole_start;
57
unsigned long wii_hole_size;
58
59
60
static int __init page_aligned(unsigned long x)
61
{
62
return !(x & (PAGE_SIZE-1));
63
}
64
65
void __init wii_memory_fixups(void)
66
{
67
struct memblock_region *p = memblock.memory.regions;
68
69
/*
70
* This is part of a workaround to allow the use of two
71
* discontinuous RAM ranges on the Wii, even if this is
72
* currently unsupported on 32-bit PowerPC Linux.
73
*
74
* We coalesce the two memory ranges of the Wii into a
75
* single range, then create a reservation for the "hole"
76
* between both ranges.
77
*/
78
79
BUG_ON(memblock.memory.cnt != 2);
80
BUG_ON(!page_aligned(p[0].base) || !page_aligned(p[1].base));
81
82
p[0].size = _ALIGN_DOWN(p[0].size, PAGE_SIZE);
83
p[1].size = _ALIGN_DOWN(p[1].size, PAGE_SIZE);
84
85
wii_hole_start = p[0].base + p[0].size;
86
wii_hole_size = p[1].base - wii_hole_start;
87
88
pr_info("MEM1: <%08llx %08llx>\n", p[0].base, p[0].size);
89
pr_info("HOLE: <%08lx %08lx>\n", wii_hole_start, wii_hole_size);
90
pr_info("MEM2: <%08llx %08llx>\n", p[1].base, p[1].size);
91
92
p[0].size += wii_hole_size + p[1].size;
93
94
memblock.memory.cnt = 1;
95
memblock_analyze();
96
97
/* reserve the hole */
98
memblock_reserve(wii_hole_start, wii_hole_size);
99
100
/* allow ioremapping the address space in the hole */
101
__allow_ioremap_reserved = 1;
102
}
103
104
unsigned long __init wii_mmu_mapin_mem2(unsigned long top)
105
{
106
unsigned long delta, size, bl;
107
unsigned long max_size = (256<<20);
108
109
/* MEM2 64MB@0x10000000 */
110
delta = wii_hole_start + wii_hole_size;
111
size = top - delta;
112
for (bl = 128<<10; bl < max_size; bl <<= 1) {
113
if (bl * 2 > size)
114
break;
115
}
116
setbat(4, PAGE_OFFSET+delta, delta, bl, PAGE_KERNEL_X);
117
return delta + bl;
118
}
119
120
static void wii_spin(void)
121
{
122
local_irq_disable();
123
for (;;)
124
cpu_relax();
125
}
126
127
static void __iomem *wii_ioremap_hw_regs(char *name, char *compatible)
128
{
129
void __iomem *hw_regs = NULL;
130
struct device_node *np;
131
struct resource res;
132
int error = -ENODEV;
133
134
np = of_find_compatible_node(NULL, NULL, compatible);
135
if (!np) {
136
pr_err("no compatible node found for %s\n", compatible);
137
goto out;
138
}
139
error = of_address_to_resource(np, 0, &res);
140
if (error) {
141
pr_err("no valid reg found for %s\n", np->name);
142
goto out_put;
143
}
144
145
hw_regs = ioremap(res.start, resource_size(&res));
146
if (hw_regs) {
147
pr_info("%s at 0x%08x mapped to 0x%p\n", name,
148
res.start, hw_regs);
149
}
150
151
out_put:
152
of_node_put(np);
153
out:
154
return hw_regs;
155
}
156
157
static void __init wii_setup_arch(void)
158
{
159
hw_ctrl = wii_ioremap_hw_regs("hw_ctrl", HW_CTRL_COMPATIBLE);
160
hw_gpio = wii_ioremap_hw_regs("hw_gpio", HW_GPIO_COMPATIBLE);
161
if (hw_gpio) {
162
/* turn off the front blue led and IR light */
163
clrbits32(hw_gpio + HW_GPIO_OUT(0),
164
HW_GPIO_SLOT_LED | HW_GPIO_SENSOR_BAR);
165
}
166
}
167
168
static void wii_restart(char *cmd)
169
{
170
local_irq_disable();
171
172
if (hw_ctrl) {
173
/* clear the system reset pin to cause a reset */
174
clrbits32(hw_ctrl + HW_CTRL_RESETS, HW_CTRL_RESETS_SYS);
175
}
176
wii_spin();
177
}
178
179
static void wii_power_off(void)
180
{
181
local_irq_disable();
182
183
if (hw_gpio) {
184
/* make sure that the poweroff GPIO is configured as output */
185
setbits32(hw_gpio + HW_GPIO_DIR(1), HW_GPIO_SHUTDOWN);
186
187
/* drive the poweroff GPIO high */
188
setbits32(hw_gpio + HW_GPIO_OUT(1), HW_GPIO_SHUTDOWN);
189
}
190
wii_spin();
191
}
192
193
static void wii_halt(void)
194
{
195
if (ppc_md.restart)
196
ppc_md.restart(NULL);
197
wii_spin();
198
}
199
200
static void __init wii_init_early(void)
201
{
202
ug_udbg_init();
203
}
204
205
static void __init wii_pic_probe(void)
206
{
207
flipper_pic_probe();
208
hlwd_pic_probe();
209
}
210
211
static int __init wii_probe(void)
212
{
213
unsigned long dt_root;
214
215
dt_root = of_get_flat_dt_root();
216
if (!of_flat_dt_is_compatible(dt_root, "nintendo,wii"))
217
return 0;
218
219
return 1;
220
}
221
222
static void wii_shutdown(void)
223
{
224
hlwd_quiesce();
225
flipper_quiesce();
226
}
227
228
define_machine(wii) {
229
.name = "wii",
230
.probe = wii_probe,
231
.init_early = wii_init_early,
232
.setup_arch = wii_setup_arch,
233
.restart = wii_restart,
234
.power_off = wii_power_off,
235
.halt = wii_halt,
236
.init_IRQ = wii_pic_probe,
237
.get_irq = flipper_pic_get_irq,
238
.calibrate_decr = generic_calibrate_decr,
239
.progress = udbg_progress,
240
.machine_shutdown = wii_shutdown,
241
};
242
243
static struct of_device_id wii_of_bus[] = {
244
{ .compatible = "nintendo,hollywood", },
245
{ },
246
};
247
248
static int __init wii_device_probe(void)
249
{
250
if (!machine_is(wii))
251
return 0;
252
253
of_platform_bus_probe(NULL, wii_of_bus, NULL);
254
return 0;
255
}
256
device_initcall(wii_device_probe);
257
258
259