Module Name: src Committed By: skrll Date: Thu Jan 18 07:48:57 UTC 2024
Modified Files: src/sys/arch/riscv/conf: GENERIC64 src/sys/arch/riscv/starfive: files.starfive src/sys/dev/fdt: files.fdt Added Files: src/sys/arch/riscv/starfive: jh71x0_usb.c src/sys/dev/fdt: cdns3_fdt.c Log Message: risc-v: attach the Cadence XHCI usb controller on the JH7100 SoC To generate a diff of this commit: cvs rdiff -u -r1.3 -r1.4 src/sys/arch/riscv/conf/GENERIC64 cvs rdiff -u -r1.1 -r1.2 src/sys/arch/riscv/starfive/files.starfive cvs rdiff -u -r0 -r1.1 src/sys/arch/riscv/starfive/jh71x0_usb.c cvs rdiff -u -r0 -r1.1 src/sys/dev/fdt/cdns3_fdt.c cvs rdiff -u -r1.71 -r1.72 src/sys/dev/fdt/files.fdt 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/riscv/conf/GENERIC64 diff -u src/sys/arch/riscv/conf/GENERIC64:1.3 src/sys/arch/riscv/conf/GENERIC64:1.4 --- src/sys/arch/riscv/conf/GENERIC64:1.3 Tue Jan 16 09:06:46 2024 +++ src/sys/arch/riscv/conf/GENERIC64 Thu Jan 18 07:48:56 2024 @@ -1,4 +1,4 @@ -# $NetBSD: GENERIC64,v 1.3 2024/01/16 09:06:46 skrll Exp $ +# $NetBSD: GENERIC64,v 1.4 2024/01/18 07:48:56 skrll Exp $ # # GENERIC machine description file # @@ -52,5 +52,14 @@ ccache* at fdt? # SiFive FU[57]40 L2 # Clock controller jh7100clkc* at fdt? pass 2 # StarFive JH7100 clock controller +# USB +jh71x0usb* at fdt? # StarFive JH71x0 usb + +# USB +xhci* at fdt? # XHCI +usb* at usbus? +include "dev/usb/usbdevices.config" +midi* at midibus? + # Pull in optional local configuration - always at end cinclude "arch/riscv/conf/GENERIC64.local" Index: src/sys/arch/riscv/starfive/files.starfive diff -u src/sys/arch/riscv/starfive/files.starfive:1.1 src/sys/arch/riscv/starfive/files.starfive:1.2 --- src/sys/arch/riscv/starfive/files.starfive:1.1 Tue Jan 16 09:06:46 2024 +++ src/sys/arch/riscv/starfive/files.starfive Thu Jan 18 07:48:57 2024 @@ -1,4 +1,4 @@ -# $NetBSD: files.starfive,v 1.1 2024/01/16 09:06:46 skrll Exp $ +# $NetBSD: files.starfive,v 1.2 2024/01/18 07:48:57 skrll Exp $ # # Configuration info for StarFive SoCs # @@ -8,3 +8,7 @@ device jh7100clkc attach jh7100clkc at fdt with jh7100_clkc file arch/riscv/starfive/jh7100_clkc.c jh7100_clkc +# JH71x0 USB +device jh71x0usb +attach jh71x0usb at fdt with jh71x0_usb +file arch/riscv/starfive/jh71x0_usb.c jh71x0_usb Index: src/sys/dev/fdt/files.fdt diff -u src/sys/dev/fdt/files.fdt:1.71 src/sys/dev/fdt/files.fdt:1.72 --- src/sys/dev/fdt/files.fdt:1.71 Fri Dec 29 23:31:44 2023 +++ src/sys/dev/fdt/files.fdt Thu Jan 18 07:48:57 2024 @@ -1,4 +1,4 @@ -# $NetBSD: files.fdt,v 1.71 2023/12/29 23:31:44 thorpej Exp $ +# $NetBSD: files.fdt,v 1.72 2024/01/18 07:48:57 skrll Exp $ include "external/bsd/libfdt/conf/files.libfdt" @@ -150,6 +150,10 @@ file dev/fdt/ehci_fdt.c ehci_fdt attach ohci at fdt with ohci_fdt file dev/fdt/ohci_fdt.c ohci_fdt +# Cadence USB3 XHCI +attach xhci at fdt with cdns3_fdt +file dev/fdt/cdns3_fdt.c cdns3_fdt + # Designware USB2 OTG attach dwctwo at fdt with dwc2_fdt file dev/fdt/dwc2_fdt.c dwc2_fdt Added files: Index: src/sys/arch/riscv/starfive/jh71x0_usb.c diff -u /dev/null src/sys/arch/riscv/starfive/jh71x0_usb.c:1.1 --- /dev/null Thu Jan 18 07:48:57 2024 +++ src/sys/arch/riscv/starfive/jh71x0_usb.c Thu Jan 18 07:48:57 2024 @@ -0,0 +1,247 @@ +/* $NetBSD: jh71x0_usb.c,v 1.1 2024/01/18 07:48:57 skrll Exp $ */ + +/*- + * Copyright (c) 2023 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nick Hudson + * + * 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: jh71x0_usb.c,v 1.1 2024/01/18 07:48:57 skrll Exp $"); + +#include <sys/param.h> + + +#include <dev/fdt/fdtvar.h> +#include <dev/fdt/syscon.h> + +struct jh71x0_usb_softc { + device_t sc_dev; + bus_space_tag_t sc_bst; + bus_space_handle_t sc_bsh; + int sc_phandle; + + int sc_syscon_phandle; + const struct syscon *sc_syscon; +}; + + +#define RD4(sc, reg) \ + bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) +#define WR4(sc, reg, val) \ + bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) + + +/* Register definitions */ + +#define JH7100_USB0 0x20 +#define JH7100_USB0_MODE_STRAP_MASK __BITS(2, 0) +#define JH7100_USB0_MODE_STRAP_HOST 2 + +#define JH7100_USB3 0x2c +#define JH7100_USB3_UTMI_IDDIG __BIT(21) + +#define JH7100_USB7 0x3c +#define JH7100_USB7_SSRX_SEL __BIT(18) +#define JH7100_USB7_SSTX_SEL __BIT(19) +#define JH7100_USB7_PLL_EN __BIT(23) +#define JH7100_USB7_EQ_EN __BIT(25) + +#define JH7110_STRAP_HOST __BIT(17) +#define JH7110_STRAP_DEVICE __BIT(18) +#define JH7110_STRAP_MASK __BITS(18, 16) + +#define JH7110_SUSPENDM_HOST __BIT(19) +#define JH7110_SUSPENDM_MASK __BIT(19) + +#define JH7110_MISC_CFG_MASK __BITS(23, 20) +#define JH7110_SUSPENDM_BYPS __BIT(20) +#define JH7110_PLL_EN __BIT(22) +#define JH7110_REFCLK_MODE __BIT(23) + + + +enum usb_dr_mode { + USB_DR_MODE_UNKNOWN, + USB_DR_MODE_HOST, + USB_DR_MODE_PERIPHERAL, + USB_DR_MODE_OTG, +}; + +static inline void +jh71x0_syscon_update(struct jh71x0_usb_softc *sc, bus_size_t off, + uint32_t clr, uint32_t set) +{ + syscon_lock(sc->sc_syscon); + const uint32_t old = syscon_read_4(sc->sc_syscon, off); + const uint32_t new = (old & ~clr) | set; + if (old != new) { + syscon_write_4(sc->sc_syscon, off, new); + } + syscon_unlock(sc->sc_syscon); +} + +static int +jh7100_usb_init(struct jh71x0_usb_softc *sc, const u_int *syscon_data ) +{ + enum usb_dr_mode mode = USB_DR_MODE_HOST; + + switch (mode) { + case USB_DR_MODE_HOST: + jh71x0_syscon_update(sc, JH7100_USB0, + JH7100_USB0_MODE_STRAP_MASK, JH7100_USB0_MODE_STRAP_HOST); + jh71x0_syscon_update(sc, JH7100_USB7, + JH7100_USB7_PLL_EN, JH7100_USB7_PLL_EN); + jh71x0_syscon_update(sc, JH7100_USB7, + JH7100_USB7_EQ_EN, JH7100_USB7_EQ_EN); + jh71x0_syscon_update(sc, JH7100_USB7, + JH7100_USB7_SSRX_SEL, JH7100_USB7_SSRX_SEL); + jh71x0_syscon_update(sc, JH7100_USB7, + JH7100_USB7_SSTX_SEL, JH7100_USB7_SSTX_SEL); + jh71x0_syscon_update(sc, JH7100_USB3, + JH7100_USB3_UTMI_IDDIG, JH7100_USB3_UTMI_IDDIG); + break; + default: + break; + } + + return 0; +} + +static int +jh7110_usb_init(struct jh71x0_usb_softc *sc, const u_int *syscon_data) +{ + enum usb_dr_mode mode = USB_DR_MODE_HOST; + bus_size_t usb_mode = be32dec(&syscon_data[1]); + + jh71x0_syscon_update(sc, usb_mode, JH7110_MISC_CFG_MASK, + JH7110_SUSPENDM_BYPS | JH7110_PLL_EN | JH7110_REFCLK_MODE); + + switch (mode) { + case USB_DR_MODE_HOST: + jh71x0_syscon_update(sc, usb_mode, JH7110_STRAP_MASK, JH7110_STRAP_HOST); + jh71x0_syscon_update(sc, usb_mode, JH7110_SUSPENDM_MASK, JH7110_SUSPENDM_HOST); + break; + + case USB_DR_MODE_PERIPHERAL: + jh71x0_syscon_update(sc, usb_mode, JH7110_STRAP_MASK, JH7110_STRAP_DEVICE); + jh71x0_syscon_update(sc, usb_mode, JH7110_SUSPENDM_MASK, 0); + break; + default: + break; + } + + return 0; +} + +struct jh71x0_usb_config { + int (*jhuc_init)(struct jh71x0_usb_softc *, const u_int *); + const char *jhuc_syscon; + size_t jhuc_sclen; +}; + +struct jh71x0_usb_config jh7100_usb_data = { + .jhuc_init = jh7100_usb_init, + .jhuc_syscon = "starfive,syscon", + .jhuc_sclen = 1 * sizeof(uint32_t), +}; + +struct jh71x0_usb_config jh7110_usb_data = { + .jhuc_init = jh7110_usb_init, + .jhuc_syscon = "starfive,stg-syscon", + .jhuc_sclen = 2 * sizeof(uint32_t), +}; + +/* Compat string(s) */ +static const struct device_compatible_entry compat_data[] = { + { .compat = "starfive,jh7100-usb", .data = &jh7100_usb_data }, + { .compat = "starfive,jh7110-usb", .data = &jh7110_usb_data }, + DEVICE_COMPAT_EOL +}; + +static int +jh71x0_usb_match(device_t parent, cfdata_t cf, void *aux) +{ + struct fdt_attach_args * const faa = aux; + + return of_compatible_match(faa->faa_phandle, compat_data); +} + +static void +jh71x0_usb_attach(device_t parent, device_t self, void *aux) +{ + struct jh71x0_usb_softc *sc = device_private(self); + struct fdt_attach_args * const faa = aux; + const int phandle = faa->faa_phandle; + + sc->sc_dev = self; + sc->sc_phandle = phandle; + sc->sc_bst = faa->faa_bst; + + const struct jh71x0_usb_config *jhuc = + of_compatible_lookup(sc->sc_phandle, compat_data)->data; + + int len; + const u_int *syscon_data = + fdtbus_get_prop(phandle, jhuc->jhuc_syscon, &len); + if (syscon_data == NULL) { + aprint_error(": couldn't get '%s' property\n", + jhuc->jhuc_syscon); + return; + } + if (len != jhuc->jhuc_sclen) { + aprint_error(": incorrect syscon data (len = %u)\n", + len); + return; + } + + int syscon_phandle = + fdtbus_get_phandle_from_native(be32dec(&syscon_data[0])); + + sc->sc_syscon = fdtbus_syscon_lookup(syscon_phandle); + if (sc->sc_syscon == NULL) { + aprint_error(": couldn't get syscon\n"); + return; + } + + jhuc->jhuc_init(sc, syscon_data); + + aprint_naive("\n"); + aprint_normal(": USB\n"); + + for (int child = OF_child(phandle); child; child = OF_peer(child)) { + if (!fdtbus_status_okay(child)) + continue; + fdt_add_child(parent, child, faa, 0); + } + + //fdtbus_register_phy_controller(self, phandle, &XXX_usbphy_funcs); + +} + + +CFATTACH_DECL_NEW(jh71x0_usb, sizeof(struct jh71x0_usb_softc), + jh71x0_usb_match, jh71x0_usb_attach, NULL, NULL); Index: src/sys/dev/fdt/cdns3_fdt.c diff -u /dev/null src/sys/dev/fdt/cdns3_fdt.c:1.1 --- /dev/null Thu Jan 18 07:48:57 2024 +++ src/sys/dev/fdt/cdns3_fdt.c Thu Jan 18 07:48:57 2024 @@ -0,0 +1,210 @@ +/* $NetBSD: cdns3_fdt.c,v 1.1 2024/01/18 07:48:57 skrll Exp $ */ + +/*- + * Copyright (c) 2023 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nick Hudson + * + * 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: cdns3_fdt.c,v 1.1 2024/01/18 07:48:57 skrll Exp $"); + +#include <sys/param.h> + +#include <sys/bus.h> +#include <sys/device.h> +#include <sys/intr.h> + +#include <dev/usb/xhcireg.h> +#include <dev/usb/xhcivar.h> + +#include <dev/fdt/fdtvar.h> + +struct cdns3_fdt_softc { + struct xhci_softc sc_xhci; + bus_space_tag_t sc_otg_bst; + bus_space_handle_t sc_otg_bsh; + void *sc_ih; +}; + +#define OTGRD4(sc, reg) \ + bus_space_read_4((sc)->sc_otg_bst, (sc)->sc_otg_bsh, (reg)) +#define OTGWR4(sc, reg, val) \ + bus_space_write_4((sc)->sc_otg_bst, (sc)->sc_otg_bsh, (reg), (val)) + + +/* + * Cadence USB3 controller. + */ + +#define OTG_DID 0x0000 +#define OTG_DID_V1 0x4024e +#define OTG_CMD 0x10 +#define OTG_CMD_HOST_BUS_REQ __BIT(1) +#define OTG_CMD_OTG_DIS __BIT(3) +#define OTG_STS 0x14 +#define OTG_STS_XHCI_READY __BIT(26) + + +static const struct device_compatible_entry compat_data[] = { + { .compat = "cdns,usb3" }, + DEVICE_COMPAT_EOL +}; + +static int +cdns3_fdt_match(device_t parent, cfdata_t cf, void *aux) +{ + struct fdt_attach_args * const faa = aux; + + return of_compatible_match(faa->faa_phandle, compat_data); +} + +static void +cdns3_fdt_attach(device_t parent, device_t self, void *aux) +{ + struct cdns3_fdt_softc * const cfsc = device_private(self); + struct xhci_softc * const sc = &cfsc->sc_xhci; + struct fdt_attach_args * const faa = aux; + const int phandle = faa->faa_phandle; + + struct fdtbus_phy *phy; + char intrstr[128]; + bus_addr_t addr; + bus_size_t size; + int error; + + /* + * Only host mode is supported, but this includes otg devices + * that have 'usb-role-switch' and 'role-switch-default-mode' of + * 'host' + */ + const char *dr_mode = fdtbus_get_string(phandle, "dr_mode"); + if (dr_mode == NULL || strcmp(dr_mode, "otg") == 0) { + bool ok = false; + if (of_hasprop(phandle, "usb-role-switch")) { + const char *rsdm = fdtbus_get_string(phandle, + "role-switch-default-mode"); + if (rsdm != NULL && strcmp(rsdm, "host") == 0) + ok = true; + + if (!ok) { + aprint_error(": host is not default mode\n"); + return; + } + } + if (!ok) { + aprint_error(": cannot switch 'otg' mode to host\n"); + return; + } + } else if (strcmp(dr_mode, "host") != 0) { + aprint_error(": '%s' not supported\n", dr_mode); + return; + } + + sc->sc_dev = self; + sc->sc_bus.ub_hcpriv = sc; + sc->sc_bus.ub_dmatag = faa->faa_dmat; + sc->sc_iot = faa->faa_bst; + + bus_space_handle_t bsh; + if (fdtbus_get_reg_byname(phandle, "otg", &addr, &size) != 0 || + bus_space_map(faa->faa_bst, addr, size, 0, &bsh) != 0) { + aprint_error(": couldn't map otg registers\n"); + return; + } + cfsc->sc_otg_bst = faa->faa_bst; + cfsc->sc_otg_bsh = bsh; + + if (fdtbus_get_reg_byname(phandle, "xhci", &addr, &size) != 0 || + bus_space_map(faa->faa_bst, addr, size, 0, &bsh) != 0) { + aprint_error(": couldn't map xhci registers\n"); + return; + } + + sc->sc_ios = size; + sc->sc_ioh = bsh; + + uint32_t did = OTGRD4(cfsc, OTG_DID); + if (did != OTG_DID_V1) { + aprint_error(": unsupported IP (%#x)\n", did); + return; + } + OTGWR4(cfsc, OTG_CMD, OTG_CMD_HOST_BUS_REQ | OTG_CMD_OTG_DIS); + int tries; + uint32_t sts; + for (tries = 100; tries > 0; tries--) { + sts = OTGRD4(cfsc, OTG_STS); + if (sts & OTG_STS_XHCI_READY) + break; + delay(1000); + } + if (tries == 0) { + aprint_error(": not ready (%#x)\n", sts); + return; + } + + aprint_naive("\n"); + aprint_normal(": Cadence USB3 XHCI\n"); + + /* Enable PHY devices */ + for (u_int i = 0; ; i++) { + phy = fdtbus_phy_get_index(phandle, i); + if (phy == NULL) + break; + if (fdtbus_phy_enable(phy, true) != 0) + aprint_error_dev(self, "couldn't enable phy #%d\n", i); + } + + if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) { + aprint_error_dev(self, "failed to decode interrupt\n"); + return; + } + + void *ih = fdtbus_intr_establish_xname(phandle, 0, IPL_USB, + FDT_INTR_MPSAFE, xhci_intr, sc, device_xname(self)); + if (ih == NULL) { + aprint_error_dev(self, "couldn't establish interrupt on %s\n", + intrstr); + return; + } + aprint_normal_dev(self, "interrupting on %s\n", intrstr); + + sc->sc_bus.ub_revision = USBREV_3_0; + error = xhci_init(sc); + if (error) { + aprint_error_dev(self, "init failed, error = %d\n", error); + return; + } + + sc->sc_child = config_found(self, &sc->sc_bus, usbctlprint, CFARGS_NONE); + sc->sc_child2 = config_found(self, &sc->sc_bus2, usbctlprint, + CFARGS_NONE); +} + + +CFATTACH_DECL2_NEW(cdns3_fdt, sizeof(struct cdns3_fdt_softc), + cdns3_fdt_match, cdns3_fdt_attach, NULL, + xhci_activate, NULL, xhci_childdet);