Commit | Line | Data |
---|---|---|
2874c5fd | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
5a7ee319 AH |
2 | /* |
3 | * arch/powerpc/platforms/embedded6xx/wii.c | |
4 | * | |
5 | * Nintendo Wii board-specific support | |
6 | * Copyright (C) 2008-2009 The GameCube Linux Team | |
7 | * Copyright (C) 2008,2009 Albert Herranz | |
5a7ee319 AH |
8 | */ |
9 | #define DRV_MODULE_NAME "wii" | |
10 | #define pr_fmt(fmt) DRV_MODULE_NAME ": " fmt | |
11 | ||
12 | #include <linux/kernel.h> | |
13 | #include <linux/init.h> | |
14 | #include <linux/irq.h> | |
15 | #include <linux/seq_file.h> | |
e6f6390a | 16 | #include <linux/of_address.h> |
5a7ee319 AH |
17 | #include <linux/of_platform.h> |
18 | ||
19 | #include <asm/io.h> | |
20 | #include <asm/machdep.h> | |
5a7ee319 AH |
21 | #include <asm/time.h> |
22 | #include <asm/udbg.h> | |
23 | ||
24 | #include "flipper-pic.h" | |
25 | #include "hlwd-pic.h" | |
26 | #include "usbgecko_udbg.h" | |
27 | ||
28 | /* control block */ | |
29 | #define HW_CTRL_COMPATIBLE "nintendo,hollywood-control" | |
30 | ||
31 | #define HW_CTRL_RESETS 0x94 | |
32 | #define HW_CTRL_RESETS_SYS (1<<0) | |
33 | ||
34 | /* gpio */ | |
35 | #define HW_GPIO_COMPATIBLE "nintendo,hollywood-gpio" | |
36 | ||
37 | #define HW_GPIO_BASE(idx) (idx * 0x20) | |
38 | #define HW_GPIO_OUT(idx) (HW_GPIO_BASE(idx) + 0) | |
39 | #define HW_GPIO_DIR(idx) (HW_GPIO_BASE(idx) + 4) | |
9cbaaec1 | 40 | #define HW_GPIO_OWNER (HW_GPIO_BASE(1) + 0x1c) |
5a7ee319 AH |
41 | |
42 | #define HW_GPIO_SHUTDOWN (1<<1) | |
43 | #define HW_GPIO_SLOT_LED (1<<5) | |
44 | #define HW_GPIO_SENSOR_BAR (1<<8) | |
45 | ||
46 | ||
47 | static void __iomem *hw_ctrl; | |
48 | static void __iomem *hw_gpio; | |
49 | ||
95ec77c0 | 50 | static void __noreturn wii_spin(void) |
5a7ee319 AH |
51 | { |
52 | local_irq_disable(); | |
53 | for (;;) | |
54 | cpu_relax(); | |
55 | } | |
56 | ||
c0dc225a | 57 | static void __iomem *__init wii_ioremap_hw_regs(char *name, char *compatible) |
5a7ee319 AH |
58 | { |
59 | void __iomem *hw_regs = NULL; | |
60 | struct device_node *np; | |
61 | struct resource res; | |
62 | int error = -ENODEV; | |
63 | ||
64 | np = of_find_compatible_node(NULL, NULL, compatible); | |
65 | if (!np) { | |
66 | pr_err("no compatible node found for %s\n", compatible); | |
67 | goto out; | |
68 | } | |
69 | error = of_address_to_resource(np, 0, &res); | |
70 | if (error) { | |
b9ef7b4b | 71 | pr_err("no valid reg found for %pOFn\n", np); |
5a7ee319 AH |
72 | goto out_put; |
73 | } | |
74 | ||
75 | hw_regs = ioremap(res.start, resource_size(&res)); | |
76 | if (hw_regs) { | |
7b69600d RD |
77 | pr_info("%s at 0x%pa mapped to 0x%p\n", name, |
78 | &res.start, hw_regs); | |
5a7ee319 AH |
79 | } |
80 | ||
81 | out_put: | |
82 | of_node_put(np); | |
83 | out: | |
84 | return hw_regs; | |
85 | } | |
86 | ||
87 | static void __init wii_setup_arch(void) | |
88 | { | |
89 | hw_ctrl = wii_ioremap_hw_regs("hw_ctrl", HW_CTRL_COMPATIBLE); | |
90 | hw_gpio = wii_ioremap_hw_regs("hw_gpio", HW_GPIO_COMPATIBLE); | |
91 | if (hw_gpio) { | |
92 | /* turn off the front blue led and IR light */ | |
93 | clrbits32(hw_gpio + HW_GPIO_OUT(0), | |
94 | HW_GPIO_SLOT_LED | HW_GPIO_SENSOR_BAR); | |
95 | } | |
96 | } | |
97 | ||
95ec77c0 | 98 | static void __noreturn wii_restart(char *cmd) |
5a7ee319 AH |
99 | { |
100 | local_irq_disable(); | |
101 | ||
102 | if (hw_ctrl) { | |
103 | /* clear the system reset pin to cause a reset */ | |
104 | clrbits32(hw_ctrl + HW_CTRL_RESETS, HW_CTRL_RESETS_SYS); | |
105 | } | |
106 | wii_spin(); | |
107 | } | |
108 | ||
109 | static void wii_power_off(void) | |
110 | { | |
111 | local_irq_disable(); | |
112 | ||
113 | if (hw_gpio) { | |
9cbaaec1 JN |
114 | /* |
115 | * set the owner of the shutdown pin to ARM, because it is | |
116 | * accessed through the registers for the ARM, below | |
117 | */ | |
118 | clrbits32(hw_gpio + HW_GPIO_OWNER, HW_GPIO_SHUTDOWN); | |
119 | ||
5a7ee319 AH |
120 | /* make sure that the poweroff GPIO is configured as output */ |
121 | setbits32(hw_gpio + HW_GPIO_DIR(1), HW_GPIO_SHUTDOWN); | |
122 | ||
123 | /* drive the poweroff GPIO high */ | |
124 | setbits32(hw_gpio + HW_GPIO_OUT(1), HW_GPIO_SHUTDOWN); | |
125 | } | |
126 | wii_spin(); | |
127 | } | |
128 | ||
95ec77c0 | 129 | static void __noreturn wii_halt(void) |
5a7ee319 AH |
130 | { |
131 | if (ppc_md.restart) | |
132 | ppc_md.restart(NULL); | |
133 | wii_spin(); | |
134 | } | |
135 | ||
5a7ee319 AH |
136 | static void __init wii_pic_probe(void) |
137 | { | |
138 | flipper_pic_probe(); | |
139 | hlwd_pic_probe(); | |
140 | } | |
141 | ||
142 | static int __init wii_probe(void) | |
143 | { | |
9178ba29 AG |
144 | pm_power_off = wii_power_off; |
145 | ||
f2d57694 BH |
146 | ug_udbg_init(); |
147 | ||
5a7ee319 AH |
148 | return 1; |
149 | } | |
150 | ||
151 | static void wii_shutdown(void) | |
152 | { | |
153 | hlwd_quiesce(); | |
154 | flipper_quiesce(); | |
155 | } | |
156 | ||
ce6d73c9 | 157 | static const struct of_device_id wii_of_bus[] = { |
5a7ee319 AH |
158 | { .compatible = "nintendo,hollywood", }, |
159 | { }, | |
160 | }; | |
161 | ||
162 | static int __init wii_device_probe(void) | |
163 | { | |
7ab96c0a | 164 | of_platform_populate(NULL, wii_of_bus, NULL, NULL); |
5a7ee319 AH |
165 | return 0; |
166 | } | |
f47b17d5 | 167 | machine_device_initcall(wii, wii_device_probe); |
5a7ee319 | 168 | |
91ffeaa7 NC |
169 | define_machine(wii) { |
170 | .name = "wii", | |
1c96fcde | 171 | .compatible = "nintendo,wii", |
91ffeaa7 NC |
172 | .probe = wii_probe, |
173 | .setup_arch = wii_setup_arch, | |
174 | .restart = wii_restart, | |
175 | .halt = wii_halt, | |
176 | .init_IRQ = wii_pic_probe, | |
177 | .get_irq = flipper_pic_get_irq, | |
91ffeaa7 NC |
178 | .progress = udbg_progress, |
179 | .machine_shutdown = wii_shutdown, | |
180 | }; |