xref: /linux/arch/powerpc/platforms/embedded6xx/wii.c (revision 5a7ee3198dfade8eaea260399fd168e4e9c1a3a9)
1*5a7ee319SAlbert Herranz /*
2*5a7ee319SAlbert Herranz  * arch/powerpc/platforms/embedded6xx/wii.c
3*5a7ee319SAlbert Herranz  *
4*5a7ee319SAlbert Herranz  * Nintendo Wii board-specific support
5*5a7ee319SAlbert Herranz  * Copyright (C) 2008-2009 The GameCube Linux Team
6*5a7ee319SAlbert Herranz  * Copyright (C) 2008,2009 Albert Herranz
7*5a7ee319SAlbert Herranz  *
8*5a7ee319SAlbert Herranz  * This program is free software; you can redistribute it and/or
9*5a7ee319SAlbert Herranz  * modify it under the terms of the GNU General Public License
10*5a7ee319SAlbert Herranz  * as published by the Free Software Foundation; either version 2
11*5a7ee319SAlbert Herranz  * of the License, or (at your option) any later version.
12*5a7ee319SAlbert Herranz  *
13*5a7ee319SAlbert Herranz  */
14*5a7ee319SAlbert Herranz #define DRV_MODULE_NAME "wii"
15*5a7ee319SAlbert Herranz #define pr_fmt(fmt) DRV_MODULE_NAME ": " fmt
16*5a7ee319SAlbert Herranz 
17*5a7ee319SAlbert Herranz #include <linux/kernel.h>
18*5a7ee319SAlbert Herranz #include <linux/init.h>
19*5a7ee319SAlbert Herranz #include <linux/irq.h>
20*5a7ee319SAlbert Herranz #include <linux/seq_file.h>
21*5a7ee319SAlbert Herranz #include <linux/kexec.h>
22*5a7ee319SAlbert Herranz #include <linux/of_platform.h>
23*5a7ee319SAlbert Herranz 
24*5a7ee319SAlbert Herranz #include <asm/io.h>
25*5a7ee319SAlbert Herranz #include <asm/machdep.h>
26*5a7ee319SAlbert Herranz #include <asm/prom.h>
27*5a7ee319SAlbert Herranz #include <asm/time.h>
28*5a7ee319SAlbert Herranz #include <asm/udbg.h>
29*5a7ee319SAlbert Herranz 
30*5a7ee319SAlbert Herranz #include "flipper-pic.h"
31*5a7ee319SAlbert Herranz #include "hlwd-pic.h"
32*5a7ee319SAlbert Herranz #include "usbgecko_udbg.h"
33*5a7ee319SAlbert Herranz 
34*5a7ee319SAlbert Herranz /* control block */
35*5a7ee319SAlbert Herranz #define HW_CTRL_COMPATIBLE	"nintendo,hollywood-control"
36*5a7ee319SAlbert Herranz 
37*5a7ee319SAlbert Herranz #define HW_CTRL_RESETS		0x94
38*5a7ee319SAlbert Herranz #define HW_CTRL_RESETS_SYS	(1<<0)
39*5a7ee319SAlbert Herranz 
40*5a7ee319SAlbert Herranz /* gpio */
41*5a7ee319SAlbert Herranz #define HW_GPIO_COMPATIBLE	"nintendo,hollywood-gpio"
42*5a7ee319SAlbert Herranz 
43*5a7ee319SAlbert Herranz #define HW_GPIO_BASE(idx)	(idx * 0x20)
44*5a7ee319SAlbert Herranz #define HW_GPIO_OUT(idx)	(HW_GPIO_BASE(idx) + 0)
45*5a7ee319SAlbert Herranz #define HW_GPIO_DIR(idx)	(HW_GPIO_BASE(idx) + 4)
46*5a7ee319SAlbert Herranz 
47*5a7ee319SAlbert Herranz #define HW_GPIO_SHUTDOWN	(1<<1)
48*5a7ee319SAlbert Herranz #define HW_GPIO_SLOT_LED	(1<<5)
49*5a7ee319SAlbert Herranz #define HW_GPIO_SENSOR_BAR	(1<<8)
50*5a7ee319SAlbert Herranz 
51*5a7ee319SAlbert Herranz 
52*5a7ee319SAlbert Herranz static void __iomem *hw_ctrl;
53*5a7ee319SAlbert Herranz static void __iomem *hw_gpio;
54*5a7ee319SAlbert Herranz 
55*5a7ee319SAlbert Herranz static void wii_spin(void)
56*5a7ee319SAlbert Herranz {
57*5a7ee319SAlbert Herranz 	local_irq_disable();
58*5a7ee319SAlbert Herranz 	for (;;)
59*5a7ee319SAlbert Herranz 		cpu_relax();
60*5a7ee319SAlbert Herranz }
61*5a7ee319SAlbert Herranz 
62*5a7ee319SAlbert Herranz static void __iomem *wii_ioremap_hw_regs(char *name, char *compatible)
63*5a7ee319SAlbert Herranz {
64*5a7ee319SAlbert Herranz 	void __iomem *hw_regs = NULL;
65*5a7ee319SAlbert Herranz 	struct device_node *np;
66*5a7ee319SAlbert Herranz 	struct resource res;
67*5a7ee319SAlbert Herranz 	int error = -ENODEV;
68*5a7ee319SAlbert Herranz 
69*5a7ee319SAlbert Herranz 	np = of_find_compatible_node(NULL, NULL, compatible);
70*5a7ee319SAlbert Herranz 	if (!np) {
71*5a7ee319SAlbert Herranz 		pr_err("no compatible node found for %s\n", compatible);
72*5a7ee319SAlbert Herranz 		goto out;
73*5a7ee319SAlbert Herranz 	}
74*5a7ee319SAlbert Herranz 	error = of_address_to_resource(np, 0, &res);
75*5a7ee319SAlbert Herranz 	if (error) {
76*5a7ee319SAlbert Herranz 		pr_err("no valid reg found for %s\n", np->name);
77*5a7ee319SAlbert Herranz 		goto out_put;
78*5a7ee319SAlbert Herranz 	}
79*5a7ee319SAlbert Herranz 
80*5a7ee319SAlbert Herranz 	hw_regs = ioremap(res.start, resource_size(&res));
81*5a7ee319SAlbert Herranz 	if (hw_regs) {
82*5a7ee319SAlbert Herranz 		pr_info("%s at 0x%08x mapped to 0x%p\n", name,
83*5a7ee319SAlbert Herranz 			res.start, hw_regs);
84*5a7ee319SAlbert Herranz 	}
85*5a7ee319SAlbert Herranz 
86*5a7ee319SAlbert Herranz out_put:
87*5a7ee319SAlbert Herranz 	of_node_put(np);
88*5a7ee319SAlbert Herranz out:
89*5a7ee319SAlbert Herranz 	return hw_regs;
90*5a7ee319SAlbert Herranz }
91*5a7ee319SAlbert Herranz 
92*5a7ee319SAlbert Herranz static void __init wii_setup_arch(void)
93*5a7ee319SAlbert Herranz {
94*5a7ee319SAlbert Herranz 	hw_ctrl = wii_ioremap_hw_regs("hw_ctrl", HW_CTRL_COMPATIBLE);
95*5a7ee319SAlbert Herranz 	hw_gpio = wii_ioremap_hw_regs("hw_gpio", HW_GPIO_COMPATIBLE);
96*5a7ee319SAlbert Herranz 	if (hw_gpio) {
97*5a7ee319SAlbert Herranz 		/* turn off the front blue led and IR light */
98*5a7ee319SAlbert Herranz 		clrbits32(hw_gpio + HW_GPIO_OUT(0),
99*5a7ee319SAlbert Herranz 			  HW_GPIO_SLOT_LED | HW_GPIO_SENSOR_BAR);
100*5a7ee319SAlbert Herranz 	}
101*5a7ee319SAlbert Herranz }
102*5a7ee319SAlbert Herranz 
103*5a7ee319SAlbert Herranz static void wii_restart(char *cmd)
104*5a7ee319SAlbert Herranz {
105*5a7ee319SAlbert Herranz 	local_irq_disable();
106*5a7ee319SAlbert Herranz 
107*5a7ee319SAlbert Herranz 	if (hw_ctrl) {
108*5a7ee319SAlbert Herranz 		/* clear the system reset pin to cause a reset */
109*5a7ee319SAlbert Herranz 		clrbits32(hw_ctrl + HW_CTRL_RESETS, HW_CTRL_RESETS_SYS);
110*5a7ee319SAlbert Herranz 	}
111*5a7ee319SAlbert Herranz 	wii_spin();
112*5a7ee319SAlbert Herranz }
113*5a7ee319SAlbert Herranz 
114*5a7ee319SAlbert Herranz static void wii_power_off(void)
115*5a7ee319SAlbert Herranz {
116*5a7ee319SAlbert Herranz 	local_irq_disable();
117*5a7ee319SAlbert Herranz 
118*5a7ee319SAlbert Herranz 	if (hw_gpio) {
119*5a7ee319SAlbert Herranz 		/* make sure that the poweroff GPIO is configured as output */
120*5a7ee319SAlbert Herranz 		setbits32(hw_gpio + HW_GPIO_DIR(1), HW_GPIO_SHUTDOWN);
121*5a7ee319SAlbert Herranz 
122*5a7ee319SAlbert Herranz 		/* drive the poweroff GPIO high */
123*5a7ee319SAlbert Herranz 		setbits32(hw_gpio + HW_GPIO_OUT(1), HW_GPIO_SHUTDOWN);
124*5a7ee319SAlbert Herranz 	}
125*5a7ee319SAlbert Herranz 	wii_spin();
126*5a7ee319SAlbert Herranz }
127*5a7ee319SAlbert Herranz 
128*5a7ee319SAlbert Herranz static void wii_halt(void)
129*5a7ee319SAlbert Herranz {
130*5a7ee319SAlbert Herranz 	if (ppc_md.restart)
131*5a7ee319SAlbert Herranz 		ppc_md.restart(NULL);
132*5a7ee319SAlbert Herranz 	wii_spin();
133*5a7ee319SAlbert Herranz }
134*5a7ee319SAlbert Herranz 
135*5a7ee319SAlbert Herranz static void __init wii_init_early(void)
136*5a7ee319SAlbert Herranz {
137*5a7ee319SAlbert Herranz 	ug_udbg_init();
138*5a7ee319SAlbert Herranz }
139*5a7ee319SAlbert Herranz 
140*5a7ee319SAlbert Herranz static void __init wii_pic_probe(void)
141*5a7ee319SAlbert Herranz {
142*5a7ee319SAlbert Herranz 	flipper_pic_probe();
143*5a7ee319SAlbert Herranz 	hlwd_pic_probe();
144*5a7ee319SAlbert Herranz }
145*5a7ee319SAlbert Herranz 
146*5a7ee319SAlbert Herranz static int __init wii_probe(void)
147*5a7ee319SAlbert Herranz {
148*5a7ee319SAlbert Herranz 	unsigned long dt_root;
149*5a7ee319SAlbert Herranz 
150*5a7ee319SAlbert Herranz 	dt_root = of_get_flat_dt_root();
151*5a7ee319SAlbert Herranz 	if (!of_flat_dt_is_compatible(dt_root, "nintendo,wii"))
152*5a7ee319SAlbert Herranz 		return 0;
153*5a7ee319SAlbert Herranz 
154*5a7ee319SAlbert Herranz 	return 1;
155*5a7ee319SAlbert Herranz }
156*5a7ee319SAlbert Herranz 
157*5a7ee319SAlbert Herranz static void wii_shutdown(void)
158*5a7ee319SAlbert Herranz {
159*5a7ee319SAlbert Herranz 	hlwd_quiesce();
160*5a7ee319SAlbert Herranz 	flipper_quiesce();
161*5a7ee319SAlbert Herranz }
162*5a7ee319SAlbert Herranz 
163*5a7ee319SAlbert Herranz #ifdef CONFIG_KEXEC
164*5a7ee319SAlbert Herranz static int wii_machine_kexec_prepare(struct kimage *image)
165*5a7ee319SAlbert Herranz {
166*5a7ee319SAlbert Herranz 	return 0;
167*5a7ee319SAlbert Herranz }
168*5a7ee319SAlbert Herranz #endif /* CONFIG_KEXEC */
169*5a7ee319SAlbert Herranz 
170*5a7ee319SAlbert Herranz define_machine(wii) {
171*5a7ee319SAlbert Herranz 	.name			= "wii",
172*5a7ee319SAlbert Herranz 	.probe			= wii_probe,
173*5a7ee319SAlbert Herranz 	.init_early		= wii_init_early,
174*5a7ee319SAlbert Herranz 	.setup_arch		= wii_setup_arch,
175*5a7ee319SAlbert Herranz 	.restart		= wii_restart,
176*5a7ee319SAlbert Herranz 	.power_off		= wii_power_off,
177*5a7ee319SAlbert Herranz 	.halt			= wii_halt,
178*5a7ee319SAlbert Herranz 	.init_IRQ		= wii_pic_probe,
179*5a7ee319SAlbert Herranz 	.get_irq		= flipper_pic_get_irq,
180*5a7ee319SAlbert Herranz 	.calibrate_decr		= generic_calibrate_decr,
181*5a7ee319SAlbert Herranz 	.progress		= udbg_progress,
182*5a7ee319SAlbert Herranz 	.machine_shutdown	= wii_shutdown,
183*5a7ee319SAlbert Herranz #ifdef CONFIG_KEXEC
184*5a7ee319SAlbert Herranz 	.machine_kexec_prepare	= wii_machine_kexec_prepare,
185*5a7ee319SAlbert Herranz #endif
186*5a7ee319SAlbert Herranz };
187*5a7ee319SAlbert Herranz 
188*5a7ee319SAlbert Herranz static struct of_device_id wii_of_bus[] = {
189*5a7ee319SAlbert Herranz 	{ .compatible = "nintendo,hollywood", },
190*5a7ee319SAlbert Herranz 	{ },
191*5a7ee319SAlbert Herranz };
192*5a7ee319SAlbert Herranz 
193*5a7ee319SAlbert Herranz static int __init wii_device_probe(void)
194*5a7ee319SAlbert Herranz {
195*5a7ee319SAlbert Herranz 	if (!machine_is(wii))
196*5a7ee319SAlbert Herranz 		return 0;
197*5a7ee319SAlbert Herranz 
198*5a7ee319SAlbert Herranz 	of_platform_bus_probe(NULL, wii_of_bus, NULL);
199*5a7ee319SAlbert Herranz 	return 0;
200*5a7ee319SAlbert Herranz }
201*5a7ee319SAlbert Herranz device_initcall(wii_device_probe);
202*5a7ee319SAlbert Herranz 
203