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 <[email protected]>
@@ -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 <[email protected]>
+ * 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 <[email protected]>
+ * 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 <[email protected]>
+ * 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);