Module Name:    src
Committed By:   jmcneill
Date:           Tue Jan 23 21:48:12 UTC 2024

Modified Files:
        src/sys/arch/evbppc/conf: WII files.wii
        src/sys/arch/evbppc/include: wii.h
Added Files:
        src/sys/arch/evbppc/wii/dev: avenc.c avenc.h hwgpio.c

Log Message:
wii: Add GPIO, I2C, and basic A/V encoder driver.


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/evbppc/conf/WII \
    src/sys/arch/evbppc/conf/files.wii
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/evbppc/include/wii.h
cvs rdiff -u -r0 -r1.1 src/sys/arch/evbppc/wii/dev/avenc.c \
    src/sys/arch/evbppc/wii/dev/avenc.h src/sys/arch/evbppc/wii/dev/hwgpio.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/evbppc/conf/WII
diff -u src/sys/arch/evbppc/conf/WII:1.2 src/sys/arch/evbppc/conf/WII:1.3
--- src/sys/arch/evbppc/conf/WII:1.2	Mon Jan 22 21:28:15 2024
+++ src/sys/arch/evbppc/conf/WII	Tue Jan 23 21:48:12 2024
@@ -1,4 +1,4 @@
-#	$NetBSD: WII,v 1.2 2024/01/22 21:28:15 jmcneill Exp $
+#	$NetBSD: WII,v 1.3 2024/01/23 21:48:12 jmcneill Exp $
 #
 #	Nintendo Wii
 #
@@ -131,6 +131,12 @@ hollywood0 	at mainbus0 irq 14
 bwai0		at mainbus0 addr 0x0d006c00 irq 5	# Audio interface
 bwdsp0		at mainbus0 addr 0x0c005000 irq 6	# DSP
 
+hwgpio0		at hollywood0 addr 0x0d0000c0 irq 10	# GPIO
+gpio0		at hwgpio0
+gpioiic0	at gpio0 offset 0 mask 0xc000 flag 1
+iic0		at gpioiic0
+avenc0		at iic0 addr 0x70			# A/V Encoder
+
 #iosipc0 	at hollywood0 addr 0x0d000000 irq 30	# IOS IPC
 resetbtn0	at hollywood0 irq 17			# Reset button
 
Index: src/sys/arch/evbppc/conf/files.wii
diff -u src/sys/arch/evbppc/conf/files.wii:1.2 src/sys/arch/evbppc/conf/files.wii:1.3
--- src/sys/arch/evbppc/conf/files.wii:1.2	Mon Jan 22 21:28:15 2024
+++ src/sys/arch/evbppc/conf/files.wii	Tue Jan 23 21:48:12 2024
@@ -1,4 +1,4 @@
-#	$NetBSD: files.wii,v 1.2 2024/01/22 21:28:15 jmcneill Exp $
+#	$NetBSD: files.wii,v 1.3 2024/01/23 21:48:12 jmcneill Exp $
 #
 #
 maxpartitions 16
@@ -56,6 +56,10 @@ device	resetbtn
 attach	resetbtn at hollywood
 file	arch/evbppc/wii/dev/resetbtn.c		resetbtn
 
+device	hwgpio: gpiobus
+attach	hwgpio at hollywood
+file	arch/evbppc/wii/dev/hwgpio.c		hwgpio
+
 attach	ehci at hollywood with ehci_hollywood
 file	arch/evbppc/wii/dev/ehci_hollywood.c	ehci_hollywood
 
@@ -64,3 +68,7 @@ file	arch/evbppc/wii/dev/ohci_hollywood.
 
 attach	sdhc at hollywood with sdhc_hollywood
 file	arch/evbppc/wii/dev/sdhc_hollywood.c	sdhc_hollywood
+
+device	avenc
+attach	avenc at iic
+file	arch/evbppc/wii/dev/avenc.c		avenc

Index: src/sys/arch/evbppc/include/wii.h
diff -u src/sys/arch/evbppc/include/wii.h:1.4 src/sys/arch/evbppc/include/wii.h:1.5
--- src/sys/arch/evbppc/include/wii.h:1.4	Tue Jan 23 00:13:37 2024
+++ src/sys/arch/evbppc/include/wii.h	Tue Jan 23 21:48:12 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: wii.h,v 1.4 2024/01/23 00:13:37 jmcneill Exp $ */
+/* $NetBSD: wii.h,v 1.5 2024/01/23 21:48:12 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2024 Jared McNeill <jmcne...@invisible.ca>
@@ -111,6 +111,8 @@
 #define HW_ARMIRQMASK			(HOLLYWOOD_PRIV_BASE + 0x03c)
 #define HW_AHBPROT			(HOLLYWOOD_PRIV_BASE + 0x064)
 #define HW_GPIOB_OUT			(HOLLYWOOD_BASE + 0x0c0)
+#define HW_GPIOB_DIR			(HOLLYWOOD_BASE + 0x0c4)
+#define HW_GPIOB_IN			(HOLLYWOOD_BASE + 0x0c8)
 #define HW_GPIO_OWNER			(HOLLYWOOD_PRIV_BASE + 0x0fc)
 #define HW_RESETS			(HOLLYWOOD_PRIV_BASE + 0x194)
 #define  RSTB_IOP			__BIT(23)

Added files:

Index: src/sys/arch/evbppc/wii/dev/avenc.c
diff -u /dev/null src/sys/arch/evbppc/wii/dev/avenc.c:1.1
--- /dev/null	Tue Jan 23 21:48:12 2024
+++ src/sys/arch/evbppc/wii/dev/avenc.c	Tue Jan 23 21:48:12 2024
@@ -0,0 +1,171 @@
+/* $NetBSD: avenc.c,v 1.1 2024/01/23 21:48:12 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2024 Jared McNeill <jmcne...@invisible.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: avenc.c,v 1.1 2024/01/23 21:48:12 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/conf.h>
+#include <sys/bus.h>
+#include <sys/kmem.h>
+
+#include <lib/libkern/libkern.h>	/* hexdump */
+
+#include <dev/i2c/i2cvar.h>
+
+#include "avenc.h"
+
+#define AVENC_DEBUG		0
+
+#define AVENC_ADDR		0x70
+
+#define AVENC_VOLUME		0x71
+#define  AVENC_VOLUME_RIGHT	__BITS(15,8)
+#define  AVENC_VOLUME_LEFT	__BITS(7,0)
+
+#define RD1			avenc_read_1
+#define RD2			avenc_read_2
+#define WR2			avenc_write_2
+
+static i2c_tag_t avenc_tag;
+static i2c_addr_t avenc_addr;
+
+static uint8_t
+avenc_read_1(i2c_tag_t tag, i2c_addr_t addr, uint8_t reg)
+{
+	uint8_t val;
+
+	if (iic_smbus_read_byte(tag, addr, reg, &val, 0) != 0) {
+		val = 0xff;
+	}
+
+	return val;
+}
+
+static uint16_t
+avenc_read_2(i2c_tag_t tag, i2c_addr_t addr, uint8_t reg)
+{
+	uint16_t val;
+
+	if (iic_smbus_read_word(tag, addr, reg, &val, 0) != 0) {
+		val = 0xffff;
+	}
+
+	return val;
+}
+
+static void
+avenc_write_2(i2c_tag_t tag, i2c_addr_t addr, uint8_t reg, uint16_t val)
+{
+	iic_smbus_write_word(tag, addr, reg, val, 0);
+}
+
+void
+avenc_get_volume(uint8_t *left, uint8_t *right)
+{
+	uint16_t val;
+
+	if (avenc_addr == 0) {
+		*left = *right = 0;
+		return;
+	}
+
+	iic_acquire_bus(avenc_tag, 0);
+	val = RD2(avenc_tag, avenc_addr, AVENC_VOLUME);
+	iic_release_bus(avenc_tag, 0);
+
+	*left = __SHIFTOUT(val, AVENC_VOLUME_LEFT);
+	*right = __SHIFTOUT(val, AVENC_VOLUME_RIGHT);
+}
+
+void
+avenc_set_volume(uint8_t left, uint8_t right)
+{
+	uint16_t val;
+
+	if (avenc_addr == 0) {
+		return;
+	}
+
+	val = __SHIFTIN(left, AVENC_VOLUME_LEFT) |
+	      __SHIFTIN(right, AVENC_VOLUME_RIGHT);
+
+	iic_acquire_bus(avenc_tag, 0);
+	WR2(avenc_tag, avenc_addr, AVENC_VOLUME, val);
+	iic_release_bus(avenc_tag, 0);
+}
+
+static void
+avenc_dump_regs(i2c_tag_t tag, i2c_addr_t addr)
+{
+	uint8_t regdump[0x100];
+	unsigned int reg;
+
+	iic_acquire_bus(tag, 0);
+
+	for (reg = 0; reg < sizeof(regdump); reg++) {
+		regdump[reg] = RD1(tag, addr, reg);
+	}
+
+	iic_release_bus(tag, 0);
+
+	hexdump(printf, "avenc0", regdump, sizeof(regdump));
+}
+
+static int
+avenc_match(device_t parent, cfdata_t match, void *aux)
+{
+	struct i2c_attach_args *ia = aux;
+
+	return ia->ia_addr == AVENC_ADDR;
+}
+
+static void
+avenc_attach(device_t parent, device_t self, void *aux)
+{
+	struct i2c_attach_args *ia = aux;
+	i2c_tag_t tag = ia->ia_tag;
+	i2c_addr_t addr = ia->ia_addr;
+
+	KASSERT(device_unit(self) == 0);
+
+	aprint_naive("\n");
+	aprint_normal(": A/V Encoder\n");
+
+	if (AVENC_DEBUG) {
+		avenc_dump_regs(tag, addr);
+	}
+
+	avenc_tag = tag;
+	avenc_addr = addr;
+}
+
+CFATTACH_DECL_NEW(avenc, 0, avenc_match, avenc_attach, NULL, NULL);
Index: src/sys/arch/evbppc/wii/dev/avenc.h
diff -u /dev/null src/sys/arch/evbppc/wii/dev/avenc.h:1.1
--- /dev/null	Tue Jan 23 21:48:12 2024
+++ src/sys/arch/evbppc/wii/dev/avenc.h	Tue Jan 23 21:48:12 2024
@@ -0,0 +1,35 @@
+/* $NetBSD: avenc.h,v 1.1 2024/01/23 21:48:12 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2024 Jared McNeill <jmcne...@invisible.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _WII_DEV_AVENC_H_
+#define _WII_DEV_AVENC_H_
+
+void avenc_get_volume(uint8_t *, uint8_t *);
+void avenc_set_volume(uint8_t, uint8_t);
+
+#endif /* _WII_DEV_AVENC_H_ */
Index: src/sys/arch/evbppc/wii/dev/hwgpio.c
diff -u /dev/null src/sys/arch/evbppc/wii/dev/hwgpio.c:1.1
--- /dev/null	Tue Jan 23 21:48:12 2024
+++ src/sys/arch/evbppc/wii/dev/hwgpio.c	Tue Jan 23 21:48:12 2024
@@ -0,0 +1,168 @@
+/* $NetBSD: hwgpio.c,v 1.1 2024/01/23 21:48:12 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2024 Jared McNeill <jmcne...@invisible.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: hwgpio.c,v 1.1 2024/01/23 21:48:12 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/cpu.h>
+#include <sys/device.h>
+#include <sys/kmem.h>
+#include <sys/bitops.h>
+#include <sys/gpio.h>
+
+#include <dev/gpio/gpiovar.h>
+
+#include <machine/wii.h>
+
+#include "hollywood.h"
+
+#define PIN(_num, _name, _caps)		\
+	{ .pin_num = (_num), 		\
+	  .pin_caps = (_caps),		\
+	  .pin_defname = (_name),	\
+	}
+static gpio_pin_t hwgpio_pins[] = {
+	PIN( 0, "POWER",	GPIO_PIN_INPUT),
+	PIN( 1, "SHUTDOWN",	GPIO_PIN_OUTPUT),
+	PIN( 2, "FAN",		GPIO_PIN_OUTPUT),
+	PIN( 3, "DC_DC",	GPIO_PIN_OUTPUT),
+	PIN( 4, "DI_SPIN",	GPIO_PIN_OUTPUT),
+	PIN( 5, "SLOT_LED",	GPIO_PIN_OUTPUT),
+	PIN( 6, "EJECT_BTN",	GPIO_PIN_INPUT),
+	PIN( 7, "SLOT_IN",	GPIO_PIN_INPUT),
+	PIN( 8, "SENSOR_BAR",	GPIO_PIN_OUTPUT),
+	PIN( 9, "DO_EJECT",	GPIO_PIN_OUTPUT),
+	PIN(10, "EEP_CS",	GPIO_PIN_OUTPUT),
+	PIN(11, "EEP_CLK",	GPIO_PIN_OUTPUT),
+	PIN(12, "EEP_MOSI",	GPIO_PIN_OUTPUT),
+	PIN(13, "EEP_MISO",	GPIO_PIN_INPUT),
+	PIN(14, "AVE_SCL",	GPIO_PIN_OUTPUT),
+	PIN(15, "AVE_SDA",	GPIO_PIN_INPUT | GPIO_PIN_OUTPUT),
+	PIN(16, "DEBUG0",	GPIO_PIN_INPUT | GPIO_PIN_OUTPUT),
+	PIN(17, "DEBUG1",	GPIO_PIN_INPUT | GPIO_PIN_OUTPUT),
+	PIN(18, "DEBUG2",	GPIO_PIN_INPUT | GPIO_PIN_OUTPUT),
+	PIN(19, "DEBUG3",	GPIO_PIN_INPUT | GPIO_PIN_OUTPUT),
+	PIN(20, "DEBUG4",	GPIO_PIN_INPUT | GPIO_PIN_OUTPUT),
+	PIN(21, "DEBUG5",	GPIO_PIN_INPUT | GPIO_PIN_OUTPUT),
+	PIN(22, "DEBUG6",	GPIO_PIN_INPUT | GPIO_PIN_OUTPUT),
+	PIN(23, "DEBUG7",	GPIO_PIN_INPUT | GPIO_PIN_OUTPUT),
+};
+#undef PIN
+
+struct hwgpio_softc {
+	struct gpio_chipset_tag	sc_gp;
+};
+
+#define	RD4(reg)		in32(reg)
+#define	WR4(reg, val)		out32((reg), (val))
+
+static int
+hwgpio_pin_read(void *priv, int pin)
+{
+	return (RD4(HW_GPIOB_IN) & __BIT(pin)) != 0;
+}
+
+static void
+hwgpio_pin_write(void *priv, int pin, int value)
+{
+	uint32_t out;
+	int s;
+
+	s = splhigh();
+	out = RD4(HW_GPIOB_OUT);
+	if (value) {
+		out |= __BIT(pin);
+	} else {
+		out &= ~__BIT(pin);
+	}
+	WR4(HW_GPIOB_OUT, out);
+	splx(s);
+}
+
+static void
+hwgpio_pin_ctl(void *priv, int pin, int flags)
+{
+	uint32_t dir;
+	int s;
+
+	s = splhigh();
+	dir = RD4(HW_GPIOB_DIR);
+	if (flags & GPIO_PIN_OUTPUT) {
+		dir |= __BIT(pin);
+	} else {
+		dir &= ~__BIT(pin);
+	}
+	WR4(HW_GPIOB_DIR, dir);
+	splx(s);
+}
+
+static int
+hwgpio_match(device_t parent, cfdata_t cf, void *aux)
+{
+	return 1;
+}
+
+static void
+hwgpio_attach(device_t parent, device_t self, void *aux)
+{
+	struct hwgpio_softc * const sc = device_private(self);
+	struct gpio_chipset_tag *gp = &sc->sc_gp;
+	struct gpiobus_attach_args gba = {};
+	uint32_t in, out, dir;
+	u_int n;
+
+	gp->gp_cookie = sc;
+	gp->gp_pin_read = hwgpio_pin_read;
+	gp->gp_pin_write = hwgpio_pin_write;
+	gp->gp_pin_ctl = hwgpio_pin_ctl;
+
+	aprint_naive("\n");
+	aprint_normal(": GPIO\n");
+
+	in = RD4(HW_GPIOB_IN);
+	out = RD4(HW_GPIOB_OUT);
+	dir = RD4(HW_GPIOB_DIR);
+	for (n = 0; n < __arraycount(hwgpio_pins); n++) {
+		const uint32_t mask = __BIT(hwgpio_pins[n].pin_num);
+		if (dir & mask) {
+			hwgpio_pins[n].pin_state = (out & mask) != 0;
+		} else {
+			hwgpio_pins[n].pin_state = (in & mask) != 0;
+		}
+	}
+
+	gba.gba_gc = &sc->sc_gp;
+	gba.gba_pins = hwgpio_pins;
+	gba.gba_npins = __arraycount(hwgpio_pins);
+	config_found(self, &gba, NULL, CFARGS_NONE);
+}
+
+CFATTACH_DECL_NEW(hwgpio, sizeof(struct hwgpio_softc),
+    hwgpio_match, hwgpio_attach, NULL, NULL);

Reply via email to