Module Name: src Committed By: jmcneill Date: Thu Jun 29 17:08:52 UTC 2017
Modified Files: src/sys/arch/arm/sunxi: files.sunxi sun8i_h3_ccu.c sunxi_ccu.h sunxi_ccu_prediv.c src/sys/arch/evbarm/conf: SUNXI Added Files: src/sys/arch/arm/sunxi: sunxi_usbphy.c Log Message: Add USB stuff. Doesn't quite work yet. To generate a diff of this commit: cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/sunxi/files.sunxi cvs rdiff -u -r1.3 -r1.4 src/sys/arch/arm/sunxi/sun8i_h3_ccu.c \ src/sys/arch/arm/sunxi/sunxi_ccu.h cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/sunxi/sunxi_ccu_prediv.c cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/sunxi/sunxi_usbphy.c cvs rdiff -u -r1.2 -r1.3 src/sys/arch/evbarm/conf/SUNXI 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/arm/sunxi/files.sunxi diff -u src/sys/arch/arm/sunxi/files.sunxi:1.2 src/sys/arch/arm/sunxi/files.sunxi:1.3 --- src/sys/arch/arm/sunxi/files.sunxi:1.2 Thu Jun 29 09:26:06 2017 +++ src/sys/arch/arm/sunxi/files.sunxi Thu Jun 29 17:08:52 2017 @@ -1,4 +1,4 @@ -# $NetBSD: files.sunxi,v 1.2 2017/06/29 09:26:06 jmcneill Exp $ +# $NetBSD: files.sunxi,v 1.3 2017/06/29 17:08:52 jmcneill Exp $ # # Configuration info for Allwinner sunxi family SoCs # @@ -39,6 +39,19 @@ device sunximmc: sdmmcbus attach sunximmc at fdt with sunxi_mmc file arch/arm/sunxi/sunxi_mmc.c sunxi_mmc +# USB PHY +device sunxiusbphy +attach sunxiusbphy at fdt with sunxi_usbphy +file arch/arm/sunxi/sunxi_usbphy.c sunxi_usbphy + +# EHCI +attach ehci at fdt with ehci_fdt +file dev/fdt/ehci_fdt.c ehci_fdt + +# OHCI +attach ohci at fdt with ohci_fdt +file dev/fdt/ohci_fdt.c ohci_fdt + # SOC parameters defflag opt_soc.h SOC_SUNXI defflag opt_soc.h SOC_SUN8I: SOC_SUNXI Index: src/sys/arch/arm/sunxi/sun8i_h3_ccu.c diff -u src/sys/arch/arm/sunxi/sun8i_h3_ccu.c:1.3 src/sys/arch/arm/sunxi/sun8i_h3_ccu.c:1.4 --- src/sys/arch/arm/sunxi/sun8i_h3_ccu.c:1.3 Thu Jun 29 10:53:59 2017 +++ src/sys/arch/arm/sunxi/sun8i_h3_ccu.c Thu Jun 29 17:08:52 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: sun8i_h3_ccu.c,v 1.3 2017/06/29 10:53:59 jmcneill Exp $ */ +/* $NetBSD: sun8i_h3_ccu.c,v 1.4 2017/06/29 17:08:52 jmcneill Exp $ */ /*- * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca> @@ -29,7 +29,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(1, "$NetBSD: sun8i_h3_ccu.c,v 1.3 2017/06/29 10:53:59 jmcneill Exp $"); +__KERNEL_RCSID(1, "$NetBSD: sun8i_h3_ccu.c,v 1.4 2017/06/29 17:08:52 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -41,14 +41,6 @@ __KERNEL_RCSID(1, "$NetBSD: sun8i_h3_ccu #include <arm/sunxi/sunxi_ccu.h> #include <arm/sunxi/sun8i_h3_ccu.h> -#define USBPHY_CFG_REG 0x0cc -#define MBUS_RST_REG 0x0fc -#define BUS_SOFT_RST_REG0 0x2c0 -#define BUS_SOFT_RST_REG1 0x2c4 -#define BUS_SOFT_RST_REG2 0x2c8 -#define BUS_SOFT_RST_REG3 0x2d0 -#define BUS_SOFT_RST_REG4 0x2d8 - #define PLL_PERIPH0_CTRL_REG 0x028 #define AHB1_APB1_CFG_REG 0x054 #define APB2_CFG_REG 0x058 @@ -57,6 +49,13 @@ __KERNEL_RCSID(1, "$NetBSD: sun8i_h3_ccu #define SDMMC0_CLK_REG 0x088 #define SDMMC1_CLK_REG 0x08c #define SDMMC2_CLK_REG 0x090 +#define USBPHY_CFG_REG 0x0cc +#define MBUS_RST_REG 0x0fc +#define BUS_SOFT_RST_REG0 0x2c0 +#define BUS_SOFT_RST_REG1 0x2c4 +#define BUS_SOFT_RST_REG2 0x2c8 +#define BUS_SOFT_RST_REG3 0x2d0 +#define BUS_SOFT_RST_REG4 0x2d8 static int sun8i_h3_ccu_match(device_t, cfdata_t, void *); static void sun8i_h3_ccu_attach(device_t, device_t, void *); @@ -133,6 +132,7 @@ static struct sunxi_ccu_reset sun8i_h3_c }; static const char *ahb1_parents[] = { "losc", "hosc", "axi", "pll_periph0" }; +static const char *ahb2_parents[] = { "ahb1", "pll_periph0" }; static const char *apb2_parents[] = { "losc", "hosc", "pll_periph0" }; static const char *mod_parents[] = { "hosc", "pll_periph0", "pll_periph1" }; @@ -153,6 +153,13 @@ static struct sunxi_ccu_clk sun8i_h3_ccu __BITS(5,4), /* div */ __BITS(13,12), /* sel */ SUNXI_CCU_PREDIV_POWER_OF_TWO), + SUNXI_CCU_PREDIV(H3_CLK_AHB2, "ahb2", ahb2_parents, + APB2_CFG_REG, /* reg */ + 0, /* prediv */ + __BIT(1), /* prediv_sel */ + 0, /* div */ + __BITS(1,0), /* sel */ + SUNXI_CCU_PREDIV_DIVIDE_BY_TWO), SUNXI_CCU_NM(H3_CLK_APB2, "apb2", apb2_parents, APB2_CFG_REG, /* reg */ @@ -178,9 +185,56 @@ static struct sunxi_ccu_clk sun8i_h3_ccu BUS_CLK_GATING_REG0, 9), SUNXI_CCU_GATE(H3_CLK_BUS_MMC2, "bus-mmc2", "ahb1", BUS_CLK_GATING_REG0, 10), - + SUNXI_CCU_GATE(H3_CLK_BUS_OTG, "bus-otg", "ahb1", + BUS_CLK_GATING_REG0, 23), + SUNXI_CCU_GATE(H3_CLK_BUS_EHCI0, "bus-ehci0", "ahb1", + BUS_CLK_GATING_REG0, 24), + SUNXI_CCU_GATE(H3_CLK_BUS_EHCI1, "bus-ehci1", "ahb2", + BUS_CLK_GATING_REG0, 25), + SUNXI_CCU_GATE(H3_CLK_BUS_EHCI2, "bus-ehci2", "ahb2", + BUS_CLK_GATING_REG0, 26), + SUNXI_CCU_GATE(H3_CLK_BUS_EHCI3, "bus-ehci3", "ahb2", + BUS_CLK_GATING_REG0, 27), + SUNXI_CCU_GATE(H3_CLK_BUS_OHCI0, "bus-ohci0", "ahb1", + BUS_CLK_GATING_REG0, 28), + SUNXI_CCU_GATE(H3_CLK_BUS_OHCI1, "bus-ohci1", "ahb2", + BUS_CLK_GATING_REG0, 29), + SUNXI_CCU_GATE(H3_CLK_BUS_OHCI2, "bus-ohci2", "ahb2", + BUS_CLK_GATING_REG0, 30), + SUNXI_CCU_GATE(H3_CLK_BUS_OHCI3, "bus-ohci3", "ahb2", + BUS_CLK_GATING_REG0, 31), + + SUNXI_CCU_GATE(H3_CLK_BUS_I2C0, "bus-i2c0", "apb2", + BUS_CLK_GATING_REG3, 0), + SUNXI_CCU_GATE(H3_CLK_BUS_I2C1, "bus-i2c1", "apb2", + BUS_CLK_GATING_REG3, 1), + SUNXI_CCU_GATE(H3_CLK_BUS_I2C2, "bus-i2c2", "apb2", + BUS_CLK_GATING_REG3, 2), SUNXI_CCU_GATE(H3_CLK_BUS_UART0, "bus-uart0", "apb2", + BUS_CLK_GATING_REG3, 16), + SUNXI_CCU_GATE(H3_CLK_BUS_UART1, "bus-uart1", "apb2", + BUS_CLK_GATING_REG3, 17), + SUNXI_CCU_GATE(H3_CLK_BUS_UART2, "bus-uart2", "apb2", + BUS_CLK_GATING_REG3, 18), + SUNXI_CCU_GATE(H3_CLK_BUS_UART3, "bus-uart3", "apb2", BUS_CLK_GATING_REG3, 19), + + SUNXI_CCU_GATE(H3_CLK_USBPHY0, "usb-phy0", "hosc", + USBPHY_CFG_REG, 8), + SUNXI_CCU_GATE(H3_CLK_USBPHY1, "usb-phy1", "hosc", + USBPHY_CFG_REG, 9), + SUNXI_CCU_GATE(H3_CLK_USBPHY2, "usb-phy2", "hosc", + USBPHY_CFG_REG, 10), + SUNXI_CCU_GATE(H3_CLK_USBPHY3, "usb-phy3", "hosc", + USBPHY_CFG_REG, 11), + SUNXI_CCU_GATE(H3_CLK_USBOHCI0, "usb-ohci0", "hosc", + USBPHY_CFG_REG, 16), + SUNXI_CCU_GATE(H3_CLK_USBOHCI1, "usb-ohci1", "hosc", + USBPHY_CFG_REG, 17), + SUNXI_CCU_GATE(H3_CLK_USBOHCI2, "usb-ohci2", "hosc", + USBPHY_CFG_REG, 18), + SUNXI_CCU_GATE(H3_CLK_USBOHCI3, "usb-ohci3", "hosc", + USBPHY_CFG_REG, 19), }; static int Index: src/sys/arch/arm/sunxi/sunxi_ccu.h diff -u src/sys/arch/arm/sunxi/sunxi_ccu.h:1.3 src/sys/arch/arm/sunxi/sunxi_ccu.h:1.4 --- src/sys/arch/arm/sunxi/sunxi_ccu.h:1.3 Thu Jun 29 10:53:59 2017 +++ src/sys/arch/arm/sunxi/sunxi_ccu.h Thu Jun 29 17:08:52 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: sunxi_ccu.h,v 1.3 2017/06/29 10:53:59 jmcneill Exp $ */ +/* $NetBSD: sunxi_ccu.h,v 1.4 2017/06/29 17:08:52 jmcneill Exp $ */ /*- * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca> @@ -180,6 +180,7 @@ struct sunxi_ccu_prediv { uint32_t sel; uint32_t flags; #define SUNXI_CCU_PREDIV_POWER_OF_TWO __BIT(0) +#define SUNXI_CCU_PREDIV_DIVIDE_BY_TWO __BIT(1) }; u_int sunxi_ccu_prediv_get_rate(struct sunxi_ccu_softc *, Index: src/sys/arch/arm/sunxi/sunxi_ccu_prediv.c diff -u src/sys/arch/arm/sunxi/sunxi_ccu_prediv.c:1.1 src/sys/arch/arm/sunxi/sunxi_ccu_prediv.c:1.2 --- src/sys/arch/arm/sunxi/sunxi_ccu_prediv.c:1.1 Thu Jun 29 09:26:06 2017 +++ src/sys/arch/arm/sunxi/sunxi_ccu_prediv.c Thu Jun 29 17:08:52 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: sunxi_ccu_prediv.c,v 1.1 2017/06/29 09:26:06 jmcneill Exp $ */ +/* $NetBSD: sunxi_ccu_prediv.c,v 1.2 2017/06/29 17:08:52 jmcneill Exp $ */ /*- * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca> @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sunxi_ccu_prediv.c,v 1.1 2017/06/29 09:26:06 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sunxi_ccu_prediv.c,v 1.2 2017/06/29 17:08:52 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -57,8 +57,14 @@ sunxi_ccu_prediv_get_rate(struct sunxi_c return 0; val = CCU_READ(sc, prediv->reg); - pre = __SHIFTOUT(val, prediv->prediv); - div = __SHIFTOUT(val, prediv->div); + if (prediv->prediv) + pre = __SHIFTOUT(val, prediv->prediv); + else + pre = 0; + if (prediv->div) + div = __SHIFTOUT(val, prediv->div); + else + div = 0; sel = __SHIFTOUT(val, prediv->sel); if (prediv->flags & SUNXI_CCU_PREDIV_POWER_OF_TWO) @@ -68,6 +74,9 @@ sunxi_ccu_prediv_get_rate(struct sunxi_c pre++; + if (prediv->flags & SUNXI_CCU_PREDIV_DIVIDE_BY_TWO) + pre *= 2; + if (prediv->prediv_sel & __BIT(sel)) return rate / pre / div; else Index: src/sys/arch/evbarm/conf/SUNXI diff -u src/sys/arch/evbarm/conf/SUNXI:1.2 src/sys/arch/evbarm/conf/SUNXI:1.3 --- src/sys/arch/evbarm/conf/SUNXI:1.2 Thu Jun 29 09:26:06 2017 +++ src/sys/arch/evbarm/conf/SUNXI Thu Jun 29 17:08:52 2017 @@ -1,5 +1,5 @@ # -# $NetBSD: SUNXI,v 1.2 2017/06/29 09:26:06 jmcneill Exp $ +# $NetBSD: SUNXI,v 1.3 2017/06/29 17:08:52 jmcneill Exp $ # # Allwinner sunxi family # @@ -99,11 +99,13 @@ ld3 at sdmmc3 ld* at sdmmc? # USB 2.0 -#sunxiusbphy* at fdt? # USB PHY -#ehci* at fdt? # USB -#usb* at ehci? +sunxiusbphy* at fdt? pass 5 # USB PHY +ehci* at fdt? pass 9 # EHCI +ohci* at fdt? pass 8 # OHCI +usb* at ehci? +usb* at ohci? -#include "dev/usb/usbdevices.config" -#midi* at midibus? +include "dev/usb/usbdevices.config" +midi* at midibus? cinclude "arch/evbarm/conf/SUNXI.local" Added files: Index: src/sys/arch/arm/sunxi/sunxi_usbphy.c diff -u /dev/null src/sys/arch/arm/sunxi/sunxi_usbphy.c:1.1 --- /dev/null Thu Jun 29 17:08:52 2017 +++ src/sys/arch/arm/sunxi/sunxi_usbphy.c Thu Jun 29 17:08:52 2017 @@ -0,0 +1,215 @@ +/* $NetBSD: sunxi_usbphy.c,v 1.1 2017/06/29 17:08:52 jmcneill Exp $ */ + +/*- + * Copyright (c) 2017 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: sunxi_usbphy.c,v 1.1 2017/06/29 17:08:52 jmcneill Exp $"); + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/device.h> +#include <sys/intr.h> +#include <sys/systm.h> +#include <sys/time.h> + +#include <dev/fdt/fdtvar.h> + +#define OTG_PHY_CFG 0x20 +#define OTG_PHY_ROUTE_OTG __BIT(0) + +#define HCI_ICR 0x00 +#define HCI_AHB_INCR8 __BIT(10) +#define HCI_AHB_INCR4 __BIT(9) +#define HCI_AHB_INCRX_ALIGN __BIT(8) +#define HCI_ULPI_BYPASS __BIT(0) +#define PMU_UNK_H3 0x10 +#define PMU_UNK_H3_CLR __BIT(1) + +static int sunxi_usbphy_match(device_t, cfdata_t, void *); +static void sunxi_usbphy_attach(device_t, device_t, void *); + +static const char * const compatible[] = { + "allwinner,sun8i-h3-usb-phy", + NULL +}; + +#define SUNXI_MAXUSBPHY 5 + +struct sunxi_usbphy { + u_int phy_index; + bus_space_handle_t phy_bsh; + struct fdtbus_regulator *phy_reg; +}; + +struct sunxi_usbphy_softc { + device_t sc_dev; + bus_space_tag_t sc_bst; + + struct sunxi_usbphy sc_phys[SUNXI_MAXUSBPHY]; + u_int sc_nphys; + + struct fdtbus_gpio_pin *sc_gpio_id_det; + struct fdtbus_gpio_pin *sc_gpio_vbus_det; +}; + +#define USBPHY_READ(sc, id, reg) \ + bus_space_read_4((sc)->sc_bst, \ + (sc)->sc_phys[(id)].phy_bsh, (reg)) +#define USBPHY_WRITE(sc, id, reg, val) \ + bus_space_write_4((sc)->sc_bst, \ + (sc)->sc_phys[(id)].phy_bsh, (reg), (val)) + +CFATTACH_DECL_NEW(sunxi_usbphy, sizeof(struct sunxi_usbphy_softc), + sunxi_usbphy_match, sunxi_usbphy_attach, NULL, NULL); + +static bool +sunxi_usbphy_vbus_detect(struct sunxi_usbphy_softc *sc) +{ + if (sc->sc_gpio_vbus_det) + return fdtbus_gpio_read(sc->sc_gpio_vbus_det); + return 1; +} + +static void * +sunxi_usbphy_acquire(device_t dev, const void *data, size_t len) +{ + struct sunxi_usbphy_softc * const sc = device_private(dev); + + if (len != 4) + return NULL; + + const int phy_id = be32dec(data); + if (phy_id >= sc->sc_nphys) + return NULL; + + return &sc->sc_phys[phy_id]; +} + +static void +sunxi_usbphy_release(device_t dev, void *priv) +{ +} + +static int +sunxi_usbphy_enable(device_t dev, void *priv, bool enable) +{ + struct sunxi_usbphy_softc * const sc = device_private(dev); + struct sunxi_usbphy * const phy = priv; + uint32_t val; + + if (phy->phy_index > 0) { + /* Enable passby */ + val = USBPHY_READ(sc, phy->phy_index, HCI_ICR); + val |= HCI_ULPI_BYPASS; + val |= HCI_AHB_INCR8; + val |= HCI_AHB_INCR4; + val |= HCI_AHB_INCRX_ALIGN; + USBPHY_WRITE(sc, phy->phy_index, HCI_ICR, val); + } + + /* H3-specific */ + val = USBPHY_READ(sc, phy->phy_index, PMU_UNK_H3); + val &= ~PMU_UNK_H3_CLR; + USBPHY_WRITE(sc, phy->phy_index, PMU_UNK_H3, val); + + if (phy->phy_reg == NULL) + return 0; + + if (enable) { + /* If an external vbus is detected, do not enable phy 0 */ + if (phy->phy_index == 0 && sunxi_usbphy_vbus_detect(sc)) + return 0; + return fdtbus_regulator_enable(phy->phy_reg); + } else { + return fdtbus_regulator_disable(phy->phy_reg); + } +} + +const struct fdtbus_phy_controller_func sunxi_usbphy_funcs = { + .acquire = sunxi_usbphy_acquire, + .release = sunxi_usbphy_release, + .enable = sunxi_usbphy_enable, +}; + +static int +sunxi_usbphy_match(device_t parent, cfdata_t cf, void *aux) +{ + struct fdt_attach_args * const faa = aux; + + return of_match_compatible(faa->faa_phandle, compatible); +} + +static void +sunxi_usbphy_attach(device_t parent, device_t self, void *aux) +{ + struct sunxi_usbphy_softc * const sc = device_private(self); + struct fdt_attach_args * const faa = aux; + const int phandle = faa->faa_phandle; + struct fdtbus_reset *rst; + struct sunxi_usbphy *phy; + struct clk *clk; + bus_addr_t addr; + bus_size_t size; + char pname[20]; + u_int n; + + sc->sc_dev = self; + sc->sc_bst = faa->faa_bst; + + for (sc->sc_nphys = 0; sc->sc_nphys < SUNXI_MAXUSBPHY; sc->sc_nphys++) { + if (fdtbus_get_reg(phandle, sc->sc_nphys, &addr, &size) != 0) + break; + phy = &sc->sc_phys[sc->sc_nphys]; + phy->phy_index = sc->sc_nphys; + if (bus_space_map(sc->sc_bst, addr, size, 0, &phy->phy_bsh) != 0) { + aprint_error(": failed to map reg #%d\n", sc->sc_nphys); + return; + } + /* Get optional regulator */ + snprintf(pname, sizeof(pname), "usb%d_vbus-supply", sc->sc_nphys); + phy->phy_reg = fdtbus_regulator_acquire(phandle, pname); + } + + /* Enable clocks */ + for (n = 0; (clk = fdtbus_clock_get_index(phandle, n)) != NULL; n++) + if (clk_enable(clk) != 0) { + aprint_error(": couldn't enable clock #%d\n", n); + return; + } + /* De-assert resets */ + for (n = 0; (rst = fdtbus_reset_get_index(phandle, n)) != NULL; n++) + if (fdtbus_reset_deassert(rst) != 0) { + aprint_error(": couldn't de-assert reset #%d\n", n); + return; + } + + aprint_naive("\n"); + aprint_normal(": USB PHY\n"); + + fdtbus_register_phy_controller(self, phandle, &sunxi_usbphy_funcs); +}