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;
}
Beispiel #2
0
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);
}
Beispiel #4
0
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);
}
Beispiel #5
0
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);
}
Beispiel #6
0
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);
}
Beispiel #8
0
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);
}
Beispiel #9
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;
}
Beispiel #10
0
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
}
Beispiel #11
0
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));
}
Beispiel #12
0
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);
	}
}
Beispiel #13
0
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
}
Beispiel #14
0
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);
}