Skip to content

Commit cad73ba

Browse files
committed
wiiu: Add GPIO support
1 parent 57f698d commit cad73ba

2 files changed

Lines changed: 109 additions & 24 deletions

File tree

sys/arch/evbppc/conf/NINTENDO

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# $NetBSD: NINTENDO,v 1.1 2026/01/09 22:54:27 jmcneill Exp $
1+
# $NetBSD: NINTENDO,v 1.2 2026/01/23 09:58:55 jmcneill Exp $
22
#
33
# Nintendo Wii
44
#
@@ -144,6 +144,8 @@ gpio0 at hwgpio0
144144
gpioiic0 at gpio0 offset 0 mask 0xc000 flag 1
145145
iic0 at gpioiic0
146146
avenc0 at iic0 addr 0x70 # A/V Encoder
147+
hwgpio1 at ahb0 addr 0x0d000520 irq 11 # GPIO (Wii U)
148+
gpio1 at hwgpio1
147149

148150
resetbtn0 at ahb0 irq 17 # Reset button
149151

sys/arch/evbppc/nintendo/dev/hwgpio.c

Lines changed: 106 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
/* $NetBSD: hwgpio.c,v 1.1 2026/01/09 22:54:30 jmcneill Exp $ */
1+
/* $NetBSD: hwgpio.c,v 1.2 2026/01/23 09:58:55 jmcneill Exp $ */
22

33
/*-
4-
* Copyright (c) 2024 Jared McNeill <jmcneill@invisible.ca>
4+
* Copyright (c) 2024-2026 Jared McNeill <jmcneill@invisible.ca>
55
* All rights reserved.
66
*
77
* Redistribution and use in source and binary forms, with or without
@@ -27,7 +27,7 @@
2727
*/
2828

2929
#include <sys/cdefs.h>
30-
__KERNEL_RCSID(0, "$NetBSD: hwgpio.c,v 1.1 2026/01/09 22:54:30 jmcneill Exp $");
30+
__KERNEL_RCSID(0, "$NetBSD: hwgpio.c,v 1.2 2026/01/23 09:58:55 jmcneill Exp $");
3131

3232
#include <sys/param.h>
3333
#include <sys/bus.h>
@@ -42,13 +42,15 @@ __KERNEL_RCSID(0, "$NetBSD: hwgpio.c,v 1.1 2026/01/09 22:54:30 jmcneill Exp $");
4242

4343
#include <machine/wii.h>
4444
#include <machine/wiiu.h>
45+
#include "ahb.h"
4546

4647
#define PIN(_num, _name, _caps) \
4748
{ .pin_num = (_num), \
4849
.pin_caps = (_caps), \
4950
.pin_defname = (_name), \
5051
}
51-
static gpio_pin_t hwgpio_pins[] = {
52+
53+
static gpio_pin_t hwgpio0_pins_wii[] = {
5254
PIN( 0, "POWER", GPIO_PIN_INPUT),
5355
PIN( 1, "SHUTDOWN", GPIO_PIN_OUTPUT),
5456
PIN( 2, "FAN", GPIO_PIN_OUTPUT),
@@ -74,20 +76,69 @@ static gpio_pin_t hwgpio_pins[] = {
7476
PIN(22, "DEBUG6", GPIO_PIN_INPUT | GPIO_PIN_OUTPUT),
7577
PIN(23, "DEBUG7", GPIO_PIN_INPUT | GPIO_PIN_OUTPUT),
7678
};
79+
80+
static gpio_pin_t hwgpio0_pins_wiiu[] = {
81+
PIN( 0, "RtcSysInt", GPIO_PIN_INPUT),
82+
PIN( 1, "DwifiMode", GPIO_PIN_OUTPUT),
83+
PIN( 2, "FanPower", GPIO_PIN_OUTPUT),
84+
PIN( 3, "DcdcPowerControl", GPIO_PIN_OUTPUT),
85+
PIN( 5, "Esp10Workaround", GPIO_PIN_OUTPUT),
86+
PIN( 6, "DRCPWRREQ", GPIO_PIN_OUTPUT),
87+
PIN( 7, "JIG", GPIO_PIN_INPUT),
88+
PIN( 8, "PadPd", GPIO_PIN_OUTPUT),
89+
PIN(10, "EepromCs", GPIO_PIN_OUTPUT),
90+
PIN(11, "EepromSk", GPIO_PIN_OUTPUT),
91+
PIN(12, "EepromDo", GPIO_PIN_OUTPUT),
92+
PIN(13, "EepromDi", GPIO_PIN_INPUT),
93+
PIN(14, "Av0I2cClock", GPIO_PIN_OUTPUT),
94+
PIN(15, "Av0I2cData", GPIO_PIN_INPUT | GPIO_PIN_OUTPUT),
95+
PIN(24, "Av1I2cClock", GPIO_PIN_OUTPUT),
96+
PIN(25, "Av1I2cData", GPIO_PIN_INPUT | GPIO_PIN_OUTPUT),
97+
PIN(26, "MuteLamp", GPIO_PIN_OUTPUT),
98+
PIN(27, "BluetoothMode", GPIO_PIN_OUTPUT),
99+
PIN(28, "CcrhReset", GPIO_PIN_OUTPUT),
100+
PIN(29, "WifiMode", GPIO_PIN_OUTPUT),
101+
PIN(30, "Sdcc0s0Power", GPIO_PIN_OUTPUT),
102+
};
103+
104+
static gpio_pin_t hwgpio1_pins_wiiu[] = {
105+
PIN( 0, "FanSpeed", GPIO_PIN_OUTPUT),
106+
PIN( 1, "SmcScl", GPIO_PIN_OUTPUT),
107+
PIN( 2, "SmcSda", GPIO_PIN_INPUT | GPIO_PIN_OUTPUT),
108+
PIN( 3, "DcdcPowerControl2", GPIO_PIN_OUTPUT),
109+
PIN( 4, "AvInt", GPIO_PIN_INPUT),
110+
PIN( 5, "Ccrhlo12", GPIO_PIN_OUTPUT),
111+
PIN( 6, "AvReset", GPIO_PIN_OUTPUT),
112+
};
113+
77114
#undef PIN
78115

79116
struct hwgpio_softc {
80117
struct gpio_chipset_tag sc_gp;
118+
bus_space_tag_t sc_bst;
119+
bus_space_handle_t sc_bsh;
81120
kmutex_t sc_lock;
82121
};
83122

84-
#define RD4(reg) in32(reg)
85-
#define WR4(reg, val) out32((reg), (val))
123+
#define GPIO0_ADDR 0x0d0000c0
124+
#define GPIO1_ADDR 0x0d000520
125+
#define GPIO_SIZE 0x40
126+
127+
#define GPIOB_OUT 0x00
128+
#define GPIOB_DIR 0x04
129+
#define GPIOB_IN 0x08
130+
131+
#define RD4(sc, reg) \
132+
bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
133+
#define WR4(sc, reg, val) \
134+
bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
86135

87136
static int
88137
hwgpio_pin_read(void *priv, int pin)
89138
{
90-
return (RD4(HW_GPIOB_IN) & __BIT(pin)) != 0;
139+
struct hwgpio_softc * const sc = priv;
140+
141+
return (RD4(sc, GPIOB_IN) & __BIT(pin)) != 0;
91142
}
92143

93144
static void
@@ -97,13 +148,13 @@ hwgpio_pin_write(void *priv, int pin, int value)
97148
uint32_t out;
98149

99150
mutex_enter(&sc->sc_lock);
100-
out = RD4(HW_GPIOB_OUT);
151+
out = RD4(sc, GPIOB_OUT);
101152
if (value) {
102153
out |= __BIT(pin);
103154
} else {
104155
out &= ~__BIT(pin);
105156
}
106-
WR4(HW_GPIOB_OUT, out);
157+
WR4(sc, GPIOB_OUT, out);
107158
mutex_exit(&sc->sc_lock);
108159
}
109160

@@ -114,31 +165,48 @@ hwgpio_pin_ctl(void *priv, int pin, int flags)
114165
uint32_t dir;
115166

116167
mutex_enter(&sc->sc_lock);
117-
dir = RD4(HW_GPIOB_DIR);
168+
dir = RD4(sc, GPIOB_DIR);
118169
if (flags & GPIO_PIN_OUTPUT) {
119170
dir |= __BIT(pin);
120171
} else {
121172
dir &= ~__BIT(pin);
122173
}
123-
WR4(HW_GPIOB_DIR, dir);
174+
WR4(sc, GPIOB_DIR, dir);
124175
mutex_exit(&sc->sc_lock);
125176
}
126177

127178
static int
128179
hwgpio_match(device_t parent, cfdata_t cf, void *aux)
129180
{
130-
return !wiiu_plat;
181+
struct ahb_attach_args * const aaa = aux;
182+
183+
if (wiiu_plat) {
184+
return aaa->aaa_addr == GPIO0_ADDR ||
185+
aaa->aaa_addr == GPIO1_ADDR;
186+
} else {
187+
return aaa->aaa_addr == GPIO0_ADDR;
188+
}
131189
}
132190

133191
static void
134192
hwgpio_attach(device_t parent, device_t self, void *aux)
135193
{
136194
struct hwgpio_softc * const sc = device_private(self);
195+
struct ahb_attach_args * const aaa = aux;
137196
struct gpio_chipset_tag *gp = &sc->sc_gp;
138197
struct gpiobus_attach_args gba = {};
139198
uint32_t in, out, dir;
140-
u_int n;
141-
199+
gpio_pin_t *pins;
200+
int error;
201+
u_int n, npins;
202+
203+
sc->sc_bst = aaa->aaa_bst;
204+
error = bus_space_map(sc->sc_bst, aaa->aaa_addr, GPIO_SIZE, 0,
205+
&sc->sc_bsh);
206+
if (error != 0) {
207+
aprint_error(": couldn't map registers (%d)\n", error);
208+
return;
209+
}
142210
mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_HIGH);
143211

144212
gp->gp_cookie = sc;
@@ -149,21 +217,36 @@ hwgpio_attach(device_t parent, device_t self, void *aux)
149217
aprint_naive("\n");
150218
aprint_normal(": GPIO\n");
151219

152-
in = RD4(HW_GPIOB_IN);
153-
out = RD4(HW_GPIOB_OUT);
154-
dir = RD4(HW_GPIOB_DIR);
155-
for (n = 0; n < __arraycount(hwgpio_pins); n++) {
156-
const uint32_t mask = __BIT(hwgpio_pins[n].pin_num);
220+
if (wiiu_plat) {
221+
if (aaa->aaa_addr == GPIO0_ADDR) {
222+
pins = hwgpio0_pins_wiiu;
223+
npins = __arraycount(hwgpio0_pins_wiiu);
224+
} else {
225+
KASSERT(aaa->aaa_addr == GPIO1_ADDR);
226+
pins = hwgpio1_pins_wiiu;
227+
npins = __arraycount(hwgpio1_pins_wiiu);
228+
}
229+
} else {
230+
KASSERT(aaa->aaa_addr == GPIO0_ADDR);
231+
pins = hwgpio0_pins_wii;
232+
npins = __arraycount(hwgpio0_pins_wii);
233+
}
234+
235+
in = RD4(sc, GPIOB_IN);
236+
out = RD4(sc, GPIOB_OUT);
237+
dir = RD4(sc, GPIOB_DIR);
238+
for (n = 0; n < npins; n++) {
239+
const uint32_t mask = __BIT(pins[n].pin_num);
157240
if (dir & mask) {
158-
hwgpio_pins[n].pin_state = (out & mask) != 0;
241+
pins[n].pin_state = (out & mask) != 0;
159242
} else {
160-
hwgpio_pins[n].pin_state = (in & mask) != 0;
243+
pins[n].pin_state = (in & mask) != 0;
161244
}
162245
}
163246

164247
gba.gba_gc = &sc->sc_gp;
165-
gba.gba_pins = hwgpio_pins;
166-
gba.gba_npins = __arraycount(hwgpio_pins);
248+
gba.gba_pins = pins;
249+
gba.gba_npins = npins;
167250
config_found(self, &gba, NULL, CFARGS_NONE);
168251
}
169252

0 commit comments

Comments
 (0)