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);