Index: sys/arm/allwinner/a10_ehci.c =================================================================== --- sys/arm/allwinner/a10_ehci.c +++ sys/arm/allwinner/a10_ehci.c @@ -59,9 +59,11 @@ #include #include -#include "gpio_if.h" +#include +#include +#include -#include "a10_clk.h" +#include "gpio_if.h" #define EHCI_HC_DEVSTR "Allwinner Integrated USB 2.0 controller" @@ -92,6 +94,7 @@ static struct ofw_compat_data compat_data[] = { {"allwinner,sun4i-a10-ehci", 1}, + {"allwinner,sun6i-a31-ehci", 1}, {"allwinner,sun7i-a20-ehci", 1}, {NULL, 0} }; @@ -188,7 +191,24 @@ sc->sc_flags |= EHCI_SCFLG_DONTRESET; /* Enable clock for USB */ - a10_clk_usb_activate(); + switch (allwinner_soc_type()) { +#if defined(SOC_ALLWINNER_A10) || defined(SOC_ALLWINNER_A20) + case ALLWINNERSOC_A10: + case ALLWINNERSOC_A10S: + case ALLWINNERSOC_A20: + a10_clk_usb_activate(); + break; +#endif +#if defined(SOC_ALLWINNER_A31) || defined(SOC_ALLWINNER_A31S) + case ALLWINNERSOC_A31: + case ALLWINNERSOC_A31S: + a31_clk_usb_activate(); + break; +#endif + default: + device_printf(self, "Could not activate clock\n"); + goto error; + } /* Give power to USB */ GPIO_PIN_SETFLAGS(sc_gpio_dev, GPIO_USB2_PWR, GPIO_PIN_OUTPUT); @@ -207,9 +227,12 @@ A10_WRITE_4(sc, SW_USB_PMU_IRQ_ENABLE, reg_value); /* Configure port */ - reg_value = A10_READ_4(sc, SW_SDRAM_REG_HPCR_USB2); - reg_value |= SW_SDRAM_BP_HPCR_ACCESS; - A10_WRITE_4(sc, SW_SDRAM_REG_HPCR_USB2, reg_value); + if (ofw_bus_is_compatible(self, "allwinner,sun4i-a10-ehci") || + ofw_bus_is_compatible(self, "allwinner,sun7i-a20-ehci")) { + reg_value = A10_READ_4(sc, SW_SDRAM_REG_HPCR_USB2); + reg_value |= SW_SDRAM_BP_HPCR_ACCESS; + A10_WRITE_4(sc, SW_SDRAM_REG_HPCR_USB2, reg_value); + } err = ehci_init(sc); if (!err) { Index: sys/arm/allwinner/a31/a31_clk.h =================================================================== --- sys/arm/allwinner/a31/a31_clk.h +++ sys/arm/allwinner/a31/a31_clk.h @@ -134,8 +134,14 @@ #define A31_CCM_PLL6_CFG_REG_LOCK (1 << 28) /* AHB_GATING_REG0 */ -#define A31_CCM_AHB_GATING_SDMMC0 (1 << 8) +#define A31_CCM_AHB_GATING_OHCI2 (1 << 31) +#define A31_CCM_AHB_GATING_OHCI1 (1 << 30) +#define A31_CCM_AHB_GATING_OHCI0 (1 << 29) +#define A31_CCM_AHB_GATING_EHCI1 (1 << 27) +#define A31_CCM_AHB_GATING_EHCI0 (1 << 26) +#define A31_CCM_AHB_GATING_USBDRD (1 << 24) #define A31_CCM_AHB_GATING_GMAC (1 << 17) +#define A31_CCM_AHB_GATING_SDMMC0 (1 << 8) #define A31_CCM_PLL_CFG_ENABLE (1U << 31) #define A31_CCM_PLL_CFG_BYPASS (1U << 30) @@ -151,6 +157,11 @@ #define A31_CCM_APB2_GATING_TWI (1 << 0) /* AHB1_RST_REG0 */ +#define A31_CCM_AHB1_RST_REG0_OHCI2 (1 << 31) +#define A31_CCM_AHB1_RST_REG0_OHCI1 (1 << 30) +#define A31_CCM_AHB1_RST_REG0_OHCI0 (1 << 29) +#define A31_CCM_AHB1_RST_REG0_EHCI1 (1 << 27) +#define A31_CCM_AHB1_RST_REG0_EHCI0 (1 << 26) #define A31_CCM_AHB1_RST_REG0_GMAC (1 << 17) #define A31_CCM_AHB1_RST_REG0_SDMMC (1 << 8) @@ -179,11 +190,23 @@ #define A31_CCM_SD_CLK_OPHASE_CTR_SHIFT 8 #define A31_CCM_SD_CLK_DIV_RATIO_M 0xf +/* USB */ +#define A31_CCM_USBPHY_CLK_GATING_OHCI2 (1 << 18) +#define A31_CCM_USBPHY_CLK_GATING_OHCI1 (1 << 17) +#define A31_CCM_USBPHY_CLK_GATING_OHCI0 (1 << 16) +#define A31_CCM_USBPHY_CLK_GATING_USBPHY2 (1 << 10) +#define A31_CCM_USBPHY_CLK_GATING_USBPHY1 (1 << 9) +#define A31_CCM_USBPHY_CLK_GATING_USBPHY0 (1 << 8) +#define A31_CCM_USBPHY_CLK_USBPHY2_RST (1 << 2) +#define A31_CCM_USBPHY_CLK_USBPHY1_RST (1 << 1) +#define A31_CCM_USBPHY_CLK_USBPHY0_RST (1 << 0) + #define A31_CCM_CLK_REF_FREQ 24000000U int a31_clk_gmac_activate(phandle_t); int a31_clk_mmc_activate(int); int a31_clk_mmc_cfg(int, int); int a31_clk_i2c_activate(int); +int a31_clk_usb_activate(void); #endif /* _A31_CLK_H_ */ Index: sys/arm/allwinner/a31/a31_clk.c =================================================================== --- sys/arm/allwinner/a31/a31_clk.c +++ sys/arm/allwinner/a31/a31_clk.c @@ -49,6 +49,7 @@ struct a31_ccm_softc { struct resource *res; int pll6_enabled; + int usb_enabled; }; static struct a31_ccm_softc *a31_ccm_sc = NULL; @@ -293,3 +294,48 @@ return (0); } + +int +a31_clk_usb_activate(void) +{ + struct a31_ccm_softc *sc; + uint32_t reg_value; + + sc = a31_ccm_sc; + if (sc == NULL) + return (ENXIO); + if (sc->usb_enabled) + return (0); + + /* Enable USB PHY */ + reg_value = ccm_read_4(sc, A31_CCM_USBPHY_CLK); + reg_value |= A31_CCM_USBPHY_CLK_GATING_OHCI0; + reg_value |= A31_CCM_USBPHY_CLK_GATING_OHCI1; + reg_value |= A31_CCM_USBPHY_CLK_GATING_USBPHY0; + reg_value |= A31_CCM_USBPHY_CLK_GATING_USBPHY1; + reg_value |= A31_CCM_USBPHY_CLK_GATING_USBPHY2; + reg_value |= A31_CCM_USBPHY_CLK_USBPHY1_RST; + reg_value |= A31_CCM_USBPHY_CLK_USBPHY2_RST; + ccm_write_4(sc, A31_CCM_USBPHY_CLK, reg_value); + + /* Gating AHB clock for USB */ + reg_value = ccm_read_4(sc, A31_CCM_AHB_GATING0); + reg_value |= A31_CCM_AHB_GATING_USBDRD; + reg_value |= A31_CCM_AHB_GATING_EHCI0; + reg_value |= A31_CCM_AHB_GATING_EHCI1; + reg_value |= A31_CCM_AHB_GATING_OHCI0; + reg_value |= A31_CCM_AHB_GATING_OHCI1; + ccm_write_4(sc, A31_CCM_AHB_GATING0, reg_value); + + /* De-assert reset */ + reg_value = ccm_read_4(sc, A31_CCM_AHB1_RST_REG0); + reg_value |= A31_CCM_AHB1_RST_REG0_OHCI0; + reg_value |= A31_CCM_AHB1_RST_REG0_OHCI1; + reg_value |= A31_CCM_AHB1_RST_REG0_EHCI0; + reg_value |= A31_CCM_AHB1_RST_REG0_EHCI1; + ccm_write_4(sc, A31_CCM_AHB1_RST_REG0, reg_value); + + sc->usb_enabled = 1; + + return (0); +}