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
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
79116struct 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
87136static int
88137hwgpio_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
93144static 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
127178static int
128179hwgpio_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
133191static void
134192hwgpio_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