static int awin_com_match(device_t parent, cfdata_t cf, void *aux) { struct awinio_attach_args * const aio = aux; const struct awin_locators * const loc = &aio->aio_loc; bus_space_tag_t iot = aio->aio_core_a4x_bst; bus_space_handle_t bsh; const struct awin_gpio_pinset *pinset; if (awin_chip_id() == AWIN_CHIP_ID_A31) { pinset = awin_com_pinsets_a31; } else if (awin_chip_id() == AWIN_CHIP_ID_A80) { pinset = awin_com_pinsets_a80; } else { pinset = loc->loc_port + ((cf->cf_flags & 1) ? awin_com_alt_pinsets : awin_com_pinsets); } KASSERT(!strcmp(cf->cf_name, loc->loc_name)); #if defined(ALLWINNER_A80) KASSERT(loc->loc_offset >= AWIN_A80_UART0_OFFSET); KASSERT(loc->loc_offset <= AWIN_A80_UART5_OFFSET); #else KASSERT(loc->loc_offset >= AWIN_UART0_OFFSET); KASSERT(loc->loc_offset <= AWIN_UART7_OFFSET); #endif KASSERT((loc->loc_offset & 0x3ff) == 0); KASSERT((awin_com_ports & __BIT(loc->loc_port)) == 0); KASSERT(cf->cf_loc[AWINIOCF_PORT] == AWINIOCF_PORT_DEFAULT || cf->cf_loc[AWINIOCF_PORT] == loc->loc_port); if (!awin_gpio_pinset_available(pinset)) return 0; if (com_is_console(iot, AWIN_CORE_PBASE + loc->loc_offset, NULL)) return 1; awin_gpio_pinset_acquire(pinset); bus_space_subregion(iot, aio->aio_core_bsh, loc->loc_offset, loc->loc_size, &bsh); const int rv = comprobe1(iot, bsh); awin_gpio_pinset_release(pinset); return rv; }
static void awin_gige_pmu_init(device_t dev) { if (awin_chip_id() == AWIN_CHIP_ID_A80) { #if NAXP806PM > 0 device_t axp806 = device_find_by_driver_unit("axp806pm", 0); if (axp806) { struct axp806_ctrl *c = axp806_lookup(axp806, "CLDO1"); if (c) { axp806_set_voltage(c, 3000, 3000); axp806_enable(c); delay(3000); } } #endif #if NAXP809PM > 0 device_t axp809 = device_find_by_driver_unit("axp809pm", 0); if (axp809) { struct axp809_ctrl *c = axp809_lookup(axp809, "GPIO1"); if (c) { axp809_enable(c); delay(3000); } } #endif delay(100000); } }
static void awin_com_attach(device_t parent, device_t self, void *aux) { cfdata_t cf = device_cfdata(self); struct awin_com_softc * const asc = device_private(self); struct com_softc * const sc = &asc->asc_sc; struct awinio_attach_args * const aio = aux; const struct awin_locators * const loc = &aio->aio_loc; bus_space_tag_t iot = aio->aio_core_a4x_bst; const bus_addr_t iobase = AWIN_CORE_PBASE + loc->loc_offset; const struct awin_gpio_pinset *pinset; bus_space_handle_t ioh; if (awin_chip_id() == AWIN_CHIP_ID_A31) { pinset = awin_com_pinsets_a31; } else if (awin_chip_id() == AWIN_CHIP_ID_A80) { pinset = awin_com_pinsets_a80; } else { pinset = loc->loc_port + ((cf->cf_flags & 1) ? awin_com_alt_pinsets : awin_com_pinsets); } awin_com_ports |= __BIT(loc->loc_port); awin_gpio_pinset_acquire(pinset); sc->sc_dev = self; sc->sc_frequency = AWIN_UART_FREQ; sc->sc_type = COM_TYPE_NORMAL; if (com_is_console(iot, iobase, &ioh) == 0 && bus_space_subregion(iot, aio->aio_core_bsh, loc->loc_offset / 4, loc->loc_size, &ioh)) { panic(": can't map registers"); } COM_INIT_REGS(sc->sc_regs, iot, ioh, iobase); com_attach_subr(sc); aprint_naive("\n"); KASSERT(loc->loc_intr != AWINIO_INTR_DEFAULT); asc->asc_ih = intr_establish(loc->loc_intr, IPL_SERIAL, IST_EDGE | IST_MPSAFE, comintr, sc); if (asc->asc_ih == NULL) panic("%s: failed to establish interrupt %d", device_xname(self), loc->loc_intr); }
static void awin_otg_attach(device_t parent, device_t self, void *aux) { struct awin_otg_softc *sc = device_private(self); struct awinio_attach_args * const aio = aux; const struct awin_locators * const loc = &aio->aio_loc; aprint_naive("\n"); aprint_normal(": OTG\n"); if (awin_chip_id() == AWIN_CHIP_ID_A31) { awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh, AWIN_USB_CLK_REG, AWIN_A31_USB_CLK_USBPHY0_ENABLE | AWIN_A31_USB_CLK_PHY0_ENABLE, 0); awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh, AWIN_AHB_GATING0_REG, AWIN_A31_AHB_GATING0_USB0, 0); awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh, AWIN_A31_AHB_RESET0_REG, AWIN_A31_AHB_RESET0_USBOTG_RST, 0); } else { awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh, AWIN_AHB_GATING0_REG, AWIN_AHB_GATING0_USB0, 0); awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh, AWIN_USB_CLK_REG, AWIN_USB_CLK_USBPHY_ENABLE|AWIN_USB_CLK_PHY0_ENABLE, 0); awin_reg_set_clear(aio->aio_core_bst, aio->aio_core_bsh, AWIN_SRAM_OFFSET + AWIN_SRAM_CTL1_REG, __SHIFTIN(AWIN_SRAM_CTL1_SRAMD_MAP_USB0, AWIN_SRAM_CTL1_SRAMD_MAP), 0); } sc->sc_motg.sc_dev = self; sc->sc_motg.sc_bus.dmatag = aio->aio_dmat; sc->sc_motg.sc_iot = aio->aio_core_bst; bus_space_subregion(sc->sc_motg.sc_iot, aio->aio_core_bsh, loc->loc_offset, loc->loc_size, &sc->sc_motg.sc_ioh); sc->sc_motg.sc_size = loc->loc_size; sc->sc_motg.sc_intr_poll = awin_otg_poll; sc->sc_motg.sc_intr_poll_arg = sc; sc->sc_motg.sc_mode = MOTG_MODE_HOST; sc->sc_motg.sc_ep_max = 5; sc->sc_motg.sc_ep_fifosize = 512; sc->sc_ih = intr_establish(loc->loc_intr, IPL_USB, IST_LEVEL, awin_otg_intr, sc); if (sc->sc_ih == NULL) { aprint_error_dev(self, "couldn't establish interrupt %d\n", loc->loc_intr); return; } device_printf(self, "interrupting at irq %d\n", loc->loc_intr); awin_otg_init(sc); motg_init(&sc->sc_motg); }
static void ehci_awinusb_attach(device_t parent, device_t self, void *aux) { struct awinusb_softc * const usbsc = device_private(parent); struct ehci_softc * const sc = device_private(self); struct awinusb_attach_args * const usbaa = aux; int irq; sc->sc_dev = self; sc->iot = usbaa->usbaa_bst; sc->ioh = usbaa->usbaa_bsh; sc->sc_size = usbaa->usbaa_size; sc->sc_bus.dmatag = usbaa->usbaa_dmat; sc->sc_bus.hci_private = sc; sc->sc_bus.usbrev = USBREV_2_0; sc->sc_ncomp = 0; if (usbsc->usbsc_ohci_dev != NULL) { sc->sc_comps[sc->sc_ncomp++] = usbsc->usbsc_ohci_dev; } //sc->sc_id_vendor = PCI_VENDOR_ALLWINNER; strlcpy(sc->sc_vendor, "Allwinner", sizeof(sc->sc_vendor)); aprint_naive(": EHCI USB controller\n"); aprint_normal(": EHCI USB controller\n"); int error = ehci_init(sc); if (error != USBD_NORMAL_COMPLETION) { aprint_error_dev(self, "init failed, error=%d\n", error); return; } /* Attach usb device. */ sc->sc_child = config_found(self, &sc->sc_bus, usbctlprint); switch (awin_chip_id()) { case AWIN_CHIP_ID_A80: irq = awinusb_ehci_irqs_a80[usbaa->usbaa_port]; break; case AWIN_CHIP_ID_A31: irq = awinusb_ehci_irqs_a31[usbaa->usbaa_port]; break; default: irq = awinusb_ehci_irqs[usbaa->usbaa_port]; break; } usbsc->usbsc_ehci_ih = intr_establish(irq, IPL_VM, IST_LEVEL, ehci_intr, sc); if (usbsc->usbsc_ehci_ih == NULL) { aprint_error_dev(self, "failed to establish interrupt %d\n", irq); return; } aprint_normal_dev(self, "interrupting on irq %d\n", irq); }
static void awin_hdmi_enable(struct awin_hdmi_softc *sc) { HDMI_WRITE(sc, AWIN_HDMI_CTRL_REG, AWIN_HDMI_CTRL_MODULE_EN); if (awin_chip_id() == AWIN_CHIP_ID_A20) { HDMI_WRITE(sc, AWIN_HDMI_PAD_CTRL0_REG, 0xfe800000); HDMI_WRITE(sc, AWIN_HDMI_PAD_CTRL1_REG, 0x00d8c830); } else if (awin_chip_id() == AWIN_CHIP_ID_A31) { HDMI_WRITE(sc, AWIN_HDMI_PAD_CTRL0_REG, 0x7e80000f); HDMI_WRITE(sc, AWIN_HDMI_PAD_CTRL1_REG, 0x01ded030); } #if AWIN_HDMI_PLL == 7 HDMI_WRITE(sc, AWIN_HDMI_PLL_DBG0_REG, (1<<21)); #elif AWIN_HDMI_PLL == 3 HDMI_WRITE(sc, AWIN_HDMI_PLL_DBG0_REG, (0<<21)); #endif delay(1000); }
static void awin_p2wi_attach(device_t parent, device_t self, void *aux) { struct awin_p2wi_softc *sc = device_private(self); struct awinio_attach_args * const aio = aux; const struct awin_locators * const loc = &aio->aio_loc; struct i2cbus_attach_args iba; sc->sc_dev = self; sc->sc_bst = aio->aio_core_bst; sc->sc_rsb_p = awin_chip_id() == AWIN_CHIP_ID_A80; mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SCHED); cv_init(&sc->sc_cv, "awinp2wi"); bus_space_subregion(sc->sc_bst, sc->sc_rsb_p ? aio->aio_a80_rcpus_bsh : aio->aio_core_bsh, loc->loc_offset, loc->loc_size, &sc->sc_bsh); aprint_naive("\n"); aprint_normal(": %s\n", sc->sc_rsb_p ? "RSB" : "P2WI"); sc->sc_ih = intr_establish(loc->loc_intr, IPL_SCHED, IST_LEVEL, awin_p2wi_intr, sc); if (sc->sc_ih == NULL) { aprint_error_dev(self, "couldn't establish interrupt %d\n", loc->loc_intr); return; } aprint_normal_dev(self, "interrupting on irq %d\n", loc->loc_intr); /* Enable interrupts */ P2WI_WRITE(sc, AWIN_A31_P2WI_INTE_REG, AWIN_A31_P2WI_INTE_LOAD_BSY_ENB | AWIN_A31_P2WI_INTE_TRANS_ERR_ENB | AWIN_A31_P2WI_INTE_TRANS_OVER_ENB); P2WI_WRITE(sc, AWIN_A31_P2WI_CTRL_REG, AWIN_A31_P2WI_CTRL_GLOBAL_INT_ENB); sc->sc_ic.ic_cookie = sc; sc->sc_ic.ic_acquire_bus = awin_p2wi_acquire_bus; sc->sc_ic.ic_release_bus = awin_p2wi_release_bus; sc->sc_ic.ic_exec = awin_p2wi_exec; memset(&iba, 0, sizeof(iba)); iba.iba_tag = &sc->sc_ic; sc->sc_i2cdev = config_found_ia(self, "i2cbus", &iba, iicbus_print); }
static void awin_tcon_clear_reset(struct awinio_attach_args * const aio, int unit) { KASSERT(unit == 0 || unit == 1); if (awin_chip_id() == AWIN_CHIP_ID_A31) { awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh, AWIN_A31_AHB_RESET1_REG, AWIN_A31_AHB_RESET1_LCD0_RST << unit, 0); } else { awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh, AWIN_LCD0_CH0_CLK_REG + (unit * 4), AWIN_LCDx_CH0_CLK_LCDx_RST, 0); } awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh, AWIN_AHB_GATING1_REG, AWIN_AHB_GATING1_LCD0 << unit, 0); }
static int awin_gige_match(device_t parent, cfdata_t cf, void *aux) { const struct awin_gpio_pinset *pinset = awin_chip_id() == AWIN_CHIP_ID_A31 ? &awin_gige_gpio_pinset_a31 : &awin_gige_gpio_pinset; struct awinio_attach_args * const aio __diagused = aux; const struct awin_locators * const loc __diagused = &aio->aio_loc; if (cf->cf_flags & 1) return 0; KASSERT(!strcmp(cf->cf_name, loc->loc_name)); KASSERT(cf->cf_loc[AWINIOCF_PORT] == AWINIOCF_PORT_DEFAULT || cf->cf_loc[AWINIOCF_PORT] == loc->loc_port); if (!awin_gpio_pinset_available(pinset)) return 0; return 1; }
static void awin_hdmi_set_audiomode(struct awin_hdmi_softc *sc, const struct videomode *mode, u_int display_mode) { uint32_t cts, n, val; /* * Before changing audio parameters, disable and reset the * audio module. Wait for the soft reset bit to clear before * configuring the audio parameters. */ val = HDMI_READ(sc, AWIN_HDMI_AUD_CTRL_REG); val &= ~AWIN_HDMI_AUD_CTRL_EN; val |= AWIN_HDMI_AUD_CTRL_RST; HDMI_WRITE(sc, AWIN_HDMI_AUD_CTRL_REG, val); do { val = HDMI_READ(sc, AWIN_HDMI_AUD_CTRL_REG); } while (val & AWIN_HDMI_AUD_CTRL_RST); /* No audio support in DVI mode */ if (display_mode != DISPLAY_MODE_HDMI) { return; } /* DMA & FIFO control */ val = HDMI_READ(sc, AWIN_HDMI_ADMA_CTRL_REG); if (awin_chip_id() == AWIN_CHIP_ID_A31) { val |= AWIN_HDMI_ADMA_CTRL_SRC_DMA_MODE; /* NDMA */ } else { val &= ~AWIN_HDMI_ADMA_CTRL_SRC_DMA_MODE; /* DDMA */ } val &= ~AWIN_HDMI_ADMA_CTRL_SRC_DMA_SAMPLE_RATE; val &= ~AWIN_HDMI_ADMA_CTRL_SRC_SAMPLE_LAYOUT; val &= ~AWIN_HDMI_ADMA_CTRL_SRC_WORD_LEN; val &= ~AWIN_HDMI_ADMA_CTRL_DATA_SEL; HDMI_WRITE(sc, AWIN_HDMI_ADMA_CTRL_REG, val); /* Audio format control */ val = HDMI_READ(sc, AWIN_HDMI_AUD_FMT_REG); val &= ~AWIN_HDMI_AUD_FMT_SRC_SEL; val &= ~AWIN_HDMI_AUD_FMT_SEL; val &= ~AWIN_HDMI_AUD_FMT_DSD_FMT; val &= ~AWIN_HDMI_AUD_FMT_LAYOUT; val &= ~AWIN_HDMI_AUD_FMT_SRC_CH_CFG; val |= __SHIFTIN(1, AWIN_HDMI_AUD_FMT_SRC_CH_CFG); HDMI_WRITE(sc, AWIN_HDMI_AUD_FMT_REG, val); /* PCM control (channel map) */ HDMI_WRITE(sc, AWIN_HDMI_AUD_PCM_CTRL_REG, 0x76543210); /* Clock setup */ n = 6144; /* 48 kHz */ cts = ((mode->dot_clock * 10) * (n / 128)) / 480; HDMI_WRITE(sc, AWIN_HDMI_AUD_CTS_REG, cts); HDMI_WRITE(sc, AWIN_HDMI_AUD_N_REG, n); /* Audio PCM channel status 0 */ val = __SHIFTIN(AWIN_HDMI_AUD_CH_STATUS0_FS_FREQ_48, AWIN_HDMI_AUD_CH_STATUS0_FS_FREQ); HDMI_WRITE(sc, AWIN_HDMI_AUD_CH_STATUS0_REG, val); /* Audio PCM channel status 1 */ val = HDMI_READ(sc, AWIN_HDMI_AUD_CH_STATUS1_REG); val &= ~AWIN_HDMI_AUD_CH_STATUS1_CGMS_A; val &= ~AWIN_HDMI_AUD_CH_STATUS1_ORIGINAL_FS; val &= ~AWIN_HDMI_AUD_CH_STATUS1_WORD_LEN; val |= __SHIFTIN(5, AWIN_HDMI_AUD_CH_STATUS1_WORD_LEN); val |= AWIN_HDMI_AUD_CH_STATUS1_WORD_LEN_MAX; HDMI_WRITE(sc, AWIN_HDMI_AUD_CH_STATUS1_REG, val); /* Re-enable */ val = HDMI_READ(sc, AWIN_HDMI_AUD_CTRL_REG); val |= AWIN_HDMI_AUD_CTRL_EN; HDMI_WRITE(sc, AWIN_HDMI_AUD_CTRL_REG, val); #if defined(AWIN_HDMI_DEBUG) && defined(DDB) awin_hdmi_dump_regs(); #endif }
static void awin_hdmi_attach(device_t parent, device_t self, void *aux) { struct awin_hdmi_softc *sc = device_private(self); struct awinio_attach_args * const aio = aux; const struct awin_locators * const loc = &aio->aio_loc; prop_dictionary_t cfg = device_properties(self); uint32_t ver, clk; sc->sc_dev = self; sc->sc_bst = aio->aio_core_bst; bus_space_subregion(sc->sc_bst, aio->aio_core_bsh, loc->loc_offset, loc->loc_size, &sc->sc_bsh); #if AWIN_HDMI_PLL == 3 awin_pll3_enable(); #elif AWIN_HDMI_PLL == 7 awin_pll7_enable(); #else #error AWIN_HDMI_PLL must be 3 or 7 #endif if (awin_chip_id() == AWIN_CHIP_ID_A31) { awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh, AWIN_A31_AHB_RESET1_REG, AWIN_A31_AHB_RESET1_HDMI_RST, 0); } #if AWIN_HDMI_PLL == 3 clk = __SHIFTIN(AWIN_HDMI_CLK_SRC_SEL_PLL3, AWIN_HDMI_CLK_SRC_SEL); #else clk = __SHIFTIN(AWIN_HDMI_CLK_SRC_SEL_PLL7, AWIN_HDMI_CLK_SRC_SEL); #endif clk |= AWIN_CLK_ENABLE; if (awin_chip_id() == AWIN_CHIP_ID_A31) { clk |= AWIN_A31_HDMI_CLK_DDC_GATING; } awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh, AWIN_HDMI_CLK_REG, clk, AWIN_HDMI_CLK_SRC_SEL); awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh, AWIN_AHB_GATING1_REG, AWIN_AHB_GATING1_HDMI, 0); ver = HDMI_READ(sc, AWIN_HDMI_VERSION_ID_REG); const int vmaj = __SHIFTOUT(ver, AWIN_HDMI_VERSION_ID_H); const int vmin = __SHIFTOUT(ver, AWIN_HDMI_VERSION_ID_L); aprint_naive("\n"); aprint_normal(": HDMI %d.%d\n", vmaj, vmin); sc->sc_ver = ver; sc->sc_i2c_blklen = 16; const char *display_mode = NULL; prop_dictionary_get_cstring_nocopy(cfg, "display-mode", &display_mode); if (display_mode) { if (strcasecmp(display_mode, "hdmi") == 0) sc->sc_display_mode = DISPLAY_MODE_HDMI; else if (strcasecmp(display_mode, "dvi") == 0) sc->sc_display_mode = DISPLAY_MODE_DVI; } #if 0 sc->sc_ih = intr_establish(loc->loc_intr, IPL_SCHED, IST_LEVEL, awin_hdmi_intr, sc); if (sc->sc_ih == NULL) { aprint_error_dev(self, "couldn't establish interrupt %d\n", loc->loc_intr); return; } aprint_normal_dev(self, "interrupting on irq %d\n", loc->loc_intr); #endif awin_hdmi_i2c_init(sc); awin_hdmi_enable(sc); delay(50000); awin_hdmi_hpd(sc); kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL, awin_hdmi_thread, sc, &sc->sc_thread, "%s", device_xname(sc->sc_dev)); }
static void awinio_attach(device_t parent, device_t self, void *aux) { struct awinio_softc * const sc = &awinio_sc; uint16_t chip_id = awin_chip_id(); const char *chip_name = awin_chip_name(); const bool a10_p = chip_id == AWIN_CHIP_ID_A10; const bool a20_p = chip_id == AWIN_CHIP_ID_A20; const bool a31_p = chip_id == AWIN_CHIP_ID_A31; const bool a80_p = chip_id == AWIN_CHIP_ID_A80; prop_dictionary_t dict = device_properties(self); sc->sc_dev = self; sc->sc_bst = &armv7_generic_bs_tag; sc->sc_a4x_bst = &armv7_generic_a4x_bs_tag; sc->sc_bsh = awin_core_bsh; sc->sc_dmat = &awin_dma_tag; sc->sc_coherent_dmat = &awin_coherent_dma_tag; switch (awin_chip_id()) { #ifdef ALLWINNER_A80 case AWIN_CHIP_ID_A80: sc->sc_a80_core2_bsh = awin_core2_bsh; sc->sc_a80_rcpus_bsh = awin_rcpus_bsh; bus_space_subregion(sc->sc_bst, sc->sc_bsh, AWIN_A80_CCU_SCLK_OFFSET, 0x1000, &sc->sc_ccm_bsh); bus_space_map(sc->sc_bst, AWIN_A80_USB_PBASE, AWIN_A80_USB_SIZE, 0, &sc->sc_a80_usb_bsh); break; #endif default: bus_space_subregion(sc->sc_bst, sc->sc_bsh, AWIN_CCM_OFFSET, 0x1000, &sc->sc_ccm_bsh); break; } aprint_naive("\n"); aprint_normal(": %s (0x%04x)\n", chip_name, chip_id); const struct awin_locators * const eloc = awin_locators + __arraycount(awin_locators); for (const struct awin_locators *loc = awin_locators; loc < eloc; loc++) { char prop_name[31]; bool skip; if (loc->loc_port == AWINIOCF_PORT_DEFAULT) { snprintf(prop_name, sizeof(prop_name), "no-%s", loc->loc_name); } else { snprintf(prop_name, sizeof(prop_name), "no-%s-%d", loc->loc_name, loc->loc_port); } if (prop_dictionary_get_bool(dict, prop_name, &skip) && skip) continue; if (loc->loc_flags & AWINIO_ONLY) { if (a10_p && !(loc->loc_flags & AWINIO_ONLY_A10)) continue; if (a20_p && !(loc->loc_flags & AWINIO_ONLY_A20)) continue; if (a31_p && !(loc->loc_flags & AWINIO_ONLY_A31)) continue; if (a80_p && !(loc->loc_flags & AWINIO_ONLY_A80)) continue; } struct awinio_attach_args aio = { .aio_loc = *loc, .aio_core_bst = sc->sc_bst, .aio_core_a4x_bst = sc->sc_a4x_bst, .aio_core_bsh = sc->sc_bsh, .aio_ccm_bsh = sc->sc_ccm_bsh, .aio_a80_usb_bsh = sc->sc_a80_usb_bsh, .aio_a80_core2_bsh = sc->sc_a80_core2_bsh, .aio_a80_rcpus_bsh = sc->sc_a80_rcpus_bsh, .aio_dmat = sc->sc_dmat, .aio_coherent_dmat = sc->sc_coherent_dmat, }; cfdata_t cf = config_search_ia(awinio_find, sc->sc_dev, "awinio", &aio); if (cf == NULL) { if (loc->loc_flags & AWINIO_REQUIRED) panic("%s: failed to find %s!", __func__, loc->loc_name); continue; } config_attach(sc->sc_dev, cf, &aio, awinio_print); } }
void awinusb_attach(device_t parent, device_t self, void *aux) { struct awinusb_softc * const usbsc = device_private(self); const struct awinio_attach_args * const aio = aux; const struct awin_locators * const loc = &aio->aio_loc; bus_space_handle_t usb_bsh; bool has_ohci = true; awinusb_ports |= __BIT(loc->loc_port); usbsc->usbsc_bst = aio->aio_core_bst; usbsc->usbsc_dmat = aio->aio_dmat; usbsc->usbsc_number = loc->loc_port + 1; usb_bsh = awin_chip_id() == AWIN_CHIP_ID_A80 ? aio->aio_a80_usb_bsh : aio->aio_core_bsh; bus_space_subregion(usbsc->usbsc_bst, usb_bsh, loc->loc_offset + AWIN_EHCI_OFFSET, AWIN_EHCI_SIZE, &usbsc->usbsc_ehci_bsh); bus_space_subregion(usbsc->usbsc_bst, usb_bsh, loc->loc_offset + AWIN_OHCI_OFFSET, AWIN_OHCI_SIZE, &usbsc->usbsc_ohci_bsh); if (awin_chip_id() != AWIN_CHIP_ID_A80) { bus_space_subregion(usbsc->usbsc_bst, usb_bsh, AWIN_USB0_OFFSET + AWIN_USB0_PHY_CTL_REG, 4, &usbsc->usbsc_usb0_phy_csr_bsh); } if (awin_chip_id() == AWIN_CHIP_ID_A80 && loc->loc_port == 1) { has_ohci = false; } aprint_naive("\n"); aprint_normal("\n"); if (awin_chip_id() == AWIN_CHIP_ID_A31) { /* Enable USB PHY */ awin_reg_set_clear(usbsc->usbsc_bst, aio->aio_ccm_bsh, AWIN_USB_CLK_REG, awinusb_usb_clk_set_a31[loc->loc_port], 0); /* AHB gate enable */ awin_reg_set_clear(usbsc->usbsc_bst, aio->aio_ccm_bsh, AWIN_AHB_GATING0_REG, AWIN_A31_AHB_GATING0_USB0 | awinusb_ahb_gating_a31[loc->loc_port], 0); /* Soft reset */ awin_reg_set_clear(usbsc->usbsc_bst, aio->aio_ccm_bsh, AWIN_A31_AHB_RESET0_REG, awinusb_usb_ahb_reset_a31[loc->loc_port], 0); } else if (awin_chip_id() == AWIN_CHIP_ID_A80) { /* Gate enable */ awin_reg_set_clear(usbsc->usbsc_bst, aio->aio_ccm_bsh, AWIN_A80_CCU_SCLK_BUS_CLK_GATING1_REG, AWIN_A80_CCU_SCLK_BUS_CLK_GATING1_USB_HOST, 0); /* Enable USB PHY */ awin_reg_set_clear(usbsc->usbsc_bst, usb_bsh, AWIN_A80_USBPHY_OFFSET + AWIN_A80_USBPHY_HCI_PCR_REG, awinusb_usb_pcr_a80[loc->loc_port], 0); awin_reg_set_clear(usbsc->usbsc_bst, usb_bsh, AWIN_A80_USBPHY_OFFSET + AWIN_A80_USBPHY_HCI_SCR_REG, awinusb_usb_scr_a80[loc->loc_port], 0); if (!has_ohci) { /* No OHCI for USB1, force EHCI mode */ awin_reg_set_clear(usbsc->usbsc_bst, usb_bsh, loc->loc_offset + AWIN_USB_PMU_IRQ_REG, AWIN_USB_PMU_IRQ_EHCI_HS_FORCE | AWIN_USB_PMU_IRQ_HSIC_CONNECT_DET | AWIN_USB_PMU_IRQ_HSIC, 0); } } else { /* * Access to the USB phy is off USB0 so make sure it's on. */ awin_reg_set_clear(usbsc->usbsc_bst, aio->aio_ccm_bsh, AWIN_AHB_GATING0_REG, AWIN_AHB_GATING0_USB0 | awinusb_ahb_gating[loc->loc_port], 0); /* * Enable the USB phy for this port. */ awin_reg_set_clear(usbsc->usbsc_bst, aio->aio_ccm_bsh, AWIN_USB_CLK_REG, awinusb_usb_clk_set[loc->loc_port], 0); } /* * Allow USB DMA engine access to the DRAM. */ awin_reg_set_clear(usbsc->usbsc_bst, usb_bsh, loc->loc_offset + AWIN_USB_PMU_IRQ_REG, AWIN_USB_PMU_IRQ_AHB_INCR8 | AWIN_USB_PMU_IRQ_AHB_INCR4 | AWIN_USB_PMU_IRQ_AHB_INCRX | AWIN_USB_PMU_IRQ_ULPI_BYPASS, 0); if (awin_chip_id() == AWIN_CHIP_ID_A20) { awin_reg_set_clear(usbsc->usbsc_bst, aio->aio_core_bsh, AWIN_DRAM_OFFSET + awinusb_dram_hpcr_regs[loc->loc_port], AWIN_DRAM_HPCR_ACCESS_EN, 0); } /* initialize the USB phy */ if (awin_chip_id() != AWIN_CHIP_ID_A80) { awin_usb_phy_write(usbsc, 0x20, 0x14, 5); awin_usb_phy_write(usbsc, 0x2a, 0x03, 2); } /* * Now get the GPIO that enables the power to the port and * turn it on. */ if (awin_gpio_pin_reserve(awinusb_drvpin_names[loc->loc_port], &usbsc->usbsc_drv_pin)) { awin_gpio_pindata_write(&usbsc->usbsc_drv_pin, 1); } else { aprint_error_dev(self, "no power gpio found\n"); } if (awin_gpio_pin_reserve(awinusb_restrictpin_names[loc->loc_port], &usbsc->usbsc_restrict_pin)) { awin_gpio_pindata_write(&usbsc->usbsc_restrict_pin, 1); } else { aprint_debug_dev(self, "no restrict gpio found\n"); } /* * Disable interrupts */ #if NOHCI > 0 if (has_ohci) { bus_space_write_4(usbsc->usbsc_bst, usbsc->usbsc_ohci_bsh, OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS); } #endif #if NEHCI > 0 bus_size_t caplength = bus_space_read_1(usbsc->usbsc_bst, usbsc->usbsc_ehci_bsh, EHCI_CAPLENGTH); bus_space_write_4(usbsc->usbsc_bst, usbsc->usbsc_ehci_bsh, caplength + EHCI_USBINTR, 0); #endif #if NOHCI > 0 if (has_ohci) { struct awinusb_attach_args usbaa_ohci = { .usbaa_name = "ohci", .usbaa_dmat = usbsc->usbsc_dmat, .usbaa_bst = usbsc->usbsc_bst, .usbaa_bsh = usbsc->usbsc_ohci_bsh, .usbaa_ccm_bsh = aio->aio_ccm_bsh, .usbaa_size = AWIN_OHCI_SIZE, .usbaa_port = loc->loc_port, }; usbsc->usbsc_ohci_dev = config_found(self, &usbaa_ohci, NULL); } #endif #if NEHCI > 0 struct awinusb_attach_args usbaa_ehci = { .usbaa_name = "ehci", .usbaa_dmat = usbsc->usbsc_dmat, .usbaa_bst = usbsc->usbsc_bst, .usbaa_bsh = usbsc->usbsc_ehci_bsh, .usbaa_ccm_bsh = aio->aio_ccm_bsh, .usbaa_size = AWIN_EHCI_SIZE, .usbaa_port = loc->loc_port, }; config_found(self, &usbaa_ehci, NULL); #endif }
static void awin_gige_attach(device_t parent, device_t self, void *aux) { struct awin_gige_softc * const sc = device_private(self); struct awinio_attach_args * const aio = aux; const struct awin_locators * const loc = &aio->aio_loc; struct awin_gpio_pinset pinset; prop_dictionary_t cfg = device_properties(self); uint32_t clkreg; const char *phy_type, *pin_name; bus_space_handle_t bsh; switch (awin_chip_id()) { case AWIN_CHIP_ID_A80: bsh = aio->aio_a80_core2_bsh; pinset = awin_gige_gpio_pinset_a80; break; case AWIN_CHIP_ID_A31: bsh = aio->aio_core_bsh; pinset = awin_gige_gpio_pinset_a31; break; default: bsh = aio->aio_core_bsh; pinset = awin_gige_gpio_pinset; break; } sc->sc_core.sc_dev = self; prop_dictionary_get_uint8(cfg, "pinset-func", &pinset.pinset_func); awin_gpio_pinset_acquire(&pinset); sc->sc_core.sc_bst = aio->aio_core_bst; sc->sc_core.sc_dmat = aio->aio_dmat; bus_space_subregion(sc->sc_core.sc_bst, bsh, loc->loc_offset, loc->loc_size, &sc->sc_core.sc_bsh); aprint_naive("\n"); aprint_normal(": Gigabit Ethernet Controller\n"); awin_gige_pmu_init(self); /* * Interrupt handler */ sc->sc_ih = intr_establish(loc->loc_intr, IPL_NET, IST_LEVEL, awin_gige_intr, sc); if (sc->sc_ih == NULL) { aprint_error_dev(self, "failed to establish interrupt %d\n", loc->loc_intr); return; } aprint_normal_dev(self, "interrupting on irq %d\n", loc->loc_intr); if (prop_dictionary_get_cstring_nocopy(cfg, "phy-power", &pin_name)) { if (awin_gpio_pin_reserve(pin_name, &sc->sc_power_pin)) { awin_gpio_pindata_write(&sc->sc_power_pin, 1); } else { aprint_error_dev(self, "failed to reserve GPIO \"%s\"\n", pin_name); } } /* * Enable GMAC clock */ if (awin_chip_id() == AWIN_CHIP_ID_A80) { awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh, AWIN_A80_CCU_SCLK_BUS_CLK_GATING1_REG, AWIN_A80_CCU_SCLK_BUS_CLK_GATING1_GMAC, 0); } else if (awin_chip_id() == AWIN_CHIP_ID_A31) { awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh, AWIN_AHB_GATING0_REG, AWIN_A31_AHB_GATING0_GMAC, 0); } else if (awin_chip_id() == AWIN_CHIP_ID_A20) { awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh, AWIN_AHB_GATING1_REG, AWIN_AHB_GATING1_GMAC, 0); } /* * Soft reset */ if (awin_chip_id() == AWIN_CHIP_ID_A80) { awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh, AWIN_A80_CCU_SCLK_BUS_SOFT_RST1_REG, AWIN_A80_CCU_SCLK_BUS_SOFT_RST1_GMAC, 0); } else if (awin_chip_id() == AWIN_CHIP_ID_A31) { awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh, AWIN_A31_AHB_RESET0_REG, AWIN_A31_AHB_RESET0_GMAC_RST, 0); } /* * PHY clock setup */ if (!prop_dictionary_get_cstring_nocopy(cfg, "phy-type", &phy_type)) phy_type = "rgmii"; if (strcmp(phy_type, "rgmii") == 0) { clkreg = AWIN_GMAC_CLK_PIT | AWIN_GMAC_CLK_TCS_INT_RGMII; } else if (strcmp(phy_type, "rgmii-bpi") == 0) { clkreg = AWIN_GMAC_CLK_PIT | AWIN_GMAC_CLK_TCS_INT_RGMII; /* * These magic bits seem to be necessary for RGMII at gigabit * speeds on Banana Pi. */ clkreg |= __BITS(11,10); } else if (strcmp(phy_type, "gmii") == 0) { clkreg = AWIN_GMAC_CLK_TCS_INT_RGMII; } else if (strcmp(phy_type, "mii") == 0) { clkreg = AWIN_GMAC_CLK_TCS_MII; } else { panic("unknown phy type '%s'", phy_type); } if (awin_chip_id() == AWIN_CHIP_ID_A80) { awin_reg_set_clear(aio->aio_core_bst, aio->aio_a80_core2_bsh, AWIN_A80_SYS_CTRL_OFFSET + AWIN_A80_SYS_CTRL_EMAC_CLK_REG, clkreg, AWIN_GMAC_CLK_PIT|AWIN_GMAC_CLK_TCS); } else if (awin_chip_id() == AWIN_CHIP_ID_A31) { awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh, AWIN_A31_GMAC_CLK_REG, clkreg, AWIN_GMAC_CLK_PIT|AWIN_GMAC_CLK_TCS); } else { awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh, AWIN_GMAC_CLK_REG, clkreg, AWIN_GMAC_CLK_PIT|AWIN_GMAC_CLK_TCS); } dwc_gmac_attach(&sc->sc_core, GMAC_MII_CLK_150_250M_DIV102); }