11.2Sskrll/*	$NetBSD: usbnode.c,v 1.3 2026/01/17 05:45:17 skrll Exp $	*/
21.1Sskrll
31.1Sskrll/*-
41.1Sskrll * Copyright (c) 2025 The NetBSD Foundation, Inc.
51.1Sskrll * All rights reserved.
61.1Sskrll *
71.1Sskrll * This code is derived from software contributed to The NetBSD Foundation
81.1Sskrll * by Nick Hudson
91.1Sskrll *
101.1Sskrll * Redistribution and use in source and binary forms, with or without
111.1Sskrll * modification, are permitted provided that the following conditions
121.1Sskrll * are met:
131.1Sskrll * 1. Redistributions of source code must retain the above copyright
141.1Sskrll *    notice, this list of conditions and the following disclaimer.
151.1Sskrll * 2. Redistributions in binary form must reproduce the above copyright
161.1Sskrll *    notice, this list of conditions and the following disclaimer in the
171.1Sskrll *    documentation and/or other materials provided with the distribution.
181.1Sskrll *
191.1Sskrll * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
201.1Sskrll * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
211.1Sskrll * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
221.1Sskrll * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
231.1Sskrll * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
241.1Sskrll * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
251.1Sskrll * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
261.1Sskrll * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
271.1Sskrll * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
281.1Sskrll * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
291.1Sskrll * POSSIBILITY OF SUCH DAMAGE.
301.1Sskrll */
311.1Sskrll
321.1Sskrll#include <sys/cdefs.h>
331.2Sskrll__KERNEL_RCSID(0, "$NetBSD: usbnode.c,v 1.3 2026/01/17 05:45:17 skrll Exp $");
341.1Sskrll
351.1Sskrll#include <sys/param.h>
361.1Sskrll#include <sys/device.h>
371.1Sskrll
381.1Sskrll#include <dev/fdt/fdtvar.h>
391.1Sskrll
401.1Sskrllstruct usbnode_softc {
411.1Sskrll	device_t			sc_dev;
421.1Sskrll	int				sc_phandle;
431.1Sskrll
441.1Sskrll	struct fdtbus_gpio_pin *	sc_pin_reset;
451.1Sskrll	u_int				sc_resetdelay;
461.1Sskrll};
471.1Sskrll
481.1Sskrllstruct usbnode_data {
491.1Sskrll	const char *	und_desc;
501.1Sskrll	u_int		und_resetdelay;
511.1Sskrll};
521.1Sskrll
531.1Sskrll/* Genesys Logic GL852G usb hub */
541.1Sskrllstatic struct usbnode_data genesys_gl852g_data = {
551.1Sskrll	.und_desc = "Genesys Logic GL852G usb hub",
561.1Sskrll	.und_resetdelay = 50,
571.1Sskrll};
581.1Sskrll
591.1Sskrllstatic const struct device_compatible_entry compat_data[] = {
601.1Sskrll	{ .compat = "usb5e3,610", .data = &genesys_gl852g_data },
611.1Sskrll	DEVICE_COMPAT_EOL
621.1Sskrll};
631.1Sskrll
641.1Sskrllstatic void
651.1Sskrllusbnode_enable(struct usbnode_softc *sc,bool enable)
661.1Sskrll{
671.1Sskrll
681.1Sskrll	if (enable) {
691.1Sskrll		fdtbus_gpio_write(sc->sc_pin_reset, 1);
701.1Sskrll		delay(sc->sc_resetdelay);
711.1Sskrll	}
721.1Sskrll
731.1Sskrll	fdtbus_gpio_write(sc->sc_pin_reset, enable ? 0 : 1);
741.1Sskrll}
751.1Sskrll
761.1Sskrllstatic int
771.1Sskrllusbnode_match(device_t parent, cfdata_t cf, void *aux)
781.1Sskrll{
791.1Sskrll	struct fdt_attach_args * const faa = aux;
801.1Sskrll
811.1Sskrll	return of_compatible_match(faa->faa_phandle, compat_data);
821.1Sskrll}
831.1Sskrll
841.1Sskrllstatic int
851.1Sskrllusbnode_detach(device_t self, int flags)
861.1Sskrll{
871.1Sskrll	struct usbnode_softc * const sc = device_private(self);
881.1Sskrll
891.1Sskrll	usbnode_enable(sc, false);
901.1Sskrll
911.1Sskrll	return 0;
921.1Sskrll}
931.1Sskrll
941.1Sskrllstatic void
951.1Sskrllusbnode_attach(device_t parent, device_t self, void *aux)
961.1Sskrll{
971.1Sskrll	struct usbnode_softc * const sc = device_private(self);
981.1Sskrll	struct fdt_attach_args * const faa = aux;
991.1Sskrll	const int phandle = faa->faa_phandle;
1001.1Sskrll
1011.1Sskrll	sc->sc_dev = self;
1021.1Sskrll
1031.1Sskrll	const struct device_compatible_entry * const dce =
1041.1Sskrll	    of_compatible_lookup(phandle, compat_data);
1051.1Sskrll
1061.1Sskrll	const struct usbnode_data *und = dce->data;
1071.1Sskrll
1081.1Sskrll	/* reset gpio is ... */
1091.1Sskrll	sc->sc_pin_reset =
1101.1Sskrll	    fdtbus_gpio_acquire(phandle, "reset-gpio", GPIO_PIN_OUTPUT);
1111.1Sskrll	if (sc->sc_pin_reset == NULL) {
1121.1Sskrll		aprint_error(": couldn't acquire reset gpio\n");
1131.1Sskrll	}
1141.1Sskrll
1151.1Sskrll	usbnode_enable(sc, true);
1161.1Sskrll
1171.1Sskrll	aprint_naive("\n");
1181.1Sskrll	aprint_normal(": USB node '%s'\n", und->und_desc);
1191.1Sskrll}
1201.1Sskrll
1211.1SskrllCFATTACH_DECL_NEW(usbnode, sizeof(struct usbnode_softc),
1221.1Sskrll	usbnode_match, usbnode_attach, usbnode_detach, NULL);
123