Ejemplo n.º 1
0
static void 
awin_tcon0_enable(struct awin_tcon_softc *sc, bool enable) {
	uint32_t val;

	/* turn on/off backlight */
	if (sc->sc_lcdblk_pin_name != NULL) {
		awin_gpio_pindata_write(&sc->sc_lcdblk_pin, enable ? 1 : 0);
	}
	/* turn on/off LCD */
	if (sc->sc_lcdpwr_pin_name != NULL) {
		awin_gpio_pindata_write(&sc->sc_lcdpwr_pin, enable ? 1 : 0);
	}
	/* and finally disable of enable the tcon */
	KASSERT(sc->sc_output_type != OUTPUT_HDMI);

	awin_debe_enable(device_unit(sc->sc_dev), enable);
	delay(20000);
	if (enable) {
		val = TCON_READ(sc, AWIN_TCON_GCTL_REG);
		val |= AWIN_TCON_GCTL_EN;
		TCON_WRITE(sc, AWIN_TCON_GCTL_REG, val);
		val = TCON_READ(sc, AWIN_TCON0_CTL_REG);
		val |= AWIN_TCONx_CTL_EN;
		TCON_WRITE(sc, AWIN_TCON0_CTL_REG, val);
		val = TCON_READ(sc, AWIN_TCON0_LVDS_IF_REG);
		val |= AWIN_TCON0_LVDS_IF_EN;
		TCON_WRITE(sc, AWIN_TCON0_LVDS_IF_REG, val);
		TCON_WRITE(sc, AWIN_TCON0_IO_TRI_REG, 0);
	} else {
		TCON_WRITE(sc, AWIN_TCON0_IO_TRI_REG, 0xffffffff);
		val = TCON_READ(sc, AWIN_TCON0_LVDS_IF_REG);
		val &= ~AWIN_TCON0_LVDS_IF_EN;
		TCON_WRITE(sc, AWIN_TCON0_LVDS_IF_REG, val);
		val = TCON_READ(sc, AWIN_TCON0_CTL_REG);
		val &= ~AWIN_TCONx_CTL_EN;
		TCON_WRITE(sc, AWIN_TCON0_CTL_REG, val);
		val = TCON_READ(sc, AWIN_TCON_GCTL_REG);
		val &= ~AWIN_TCON_GCTL_EN;
		TCON_WRITE(sc, AWIN_TCON_GCTL_REG, val);
	}
}
Ejemplo n.º 2
0
static void
awin_otg_init(struct awin_otg_softc *sc)
{
	uint32_t val;

	/* initialize the USB phy */
	awin_otg_phy_write(sc, 0x0c, 0x01, 1);
	awin_otg_phy_write(sc, 0x20, 0x14, 5);
	awin_otg_phy_write(sc, 0x2a, 0x03, 2);

	if (awin_gpio_pin_reserve("usb0drv", &sc->sc_drv_pin)) {
		awin_gpio_pindata_write(&sc->sc_drv_pin, 1);
	} else {
		aprint_error_dev(sc->sc_motg.sc_dev, "no power gpio found\n");
	}
	if (awin_gpio_pin_reserve("usb0restrict", &sc->sc_restrict_pin)) {
		awin_gpio_pindata_write(&sc->sc_restrict_pin, 1);
	} else {
		aprint_error_dev(sc->sc_motg.sc_dev, "no restrict gpio found\n");
	}

	val = OTG_READ4(sc, AWIN_USB0_PHY_CSR_REG);
	val &= ~AWIN_USB0_PHY_CSR_VBUS_CHANGE_DET;
	val &= ~AWIN_USB0_PHY_CSR_ID_CHANGE_DET;
	val &= ~AWIN_USB0_PHY_CSR_DPDM_CHANGE_DET;
	val |= AWIN_USB0_PHY_CSR_DPDM_PULLUP_EN;
	val |= AWIN_USB0_PHY_CSR_ID_PULLUP_EN;
	val &= ~AWIN_USB0_PHY_CSR_FORCE_ID;
	val |= __SHIFTIN(AWIN_USB0_PHY_CSR_FORCE_ID_LOW,
			 AWIN_USB0_PHY_CSR_FORCE_ID);
	val &= ~AWIN_USB0_PHY_CSR_FORCE_VBUS_VALID;
	val |= __SHIFTIN(AWIN_USB0_PHY_CSR_FORCE_VBUS_VALID_HIGH,
			 AWIN_USB0_PHY_CSR_FORCE_VBUS_VALID);
	OTG_WRITE4(sc, AWIN_USB0_PHY_CSR_REG, val);

	OTG_WRITE1(sc, MUSB2_REG_AWIN_VEND0, 0);
}
static void
awin_ahci_attach(device_t parent, device_t self, void *aux)
{
	struct awin_ahci_softc * const asc = device_private(self);
	struct ahci_softc * const sc = &asc->asc_sc;
	struct awinio_attach_args * const aio = aux;
	const struct awin_locators * const loc = &aio->aio_loc;

	awin_ahci_enable(aio->aio_core_bst, aio->aio_ccm_bsh);

        sc->sc_atac.atac_dev = self;
	sc->sc_dmat = aio->aio_dmat;
	sc->sc_ahcit = aio->aio_core_bst;
	sc->sc_ahcis = loc->loc_size;
	sc->sc_ahci_ports = 1;
	sc->sc_ahci_quirks = AHCI_QUIRK_BADPMP;
	sc->sc_save_init_data = true;
	sc->sc_channel_start = awin_ahci_channel_start;

	bus_space_subregion(aio->aio_core_bst, aio->aio_core_bsh,
	    loc->loc_offset, loc->loc_size, &sc->sc_ahcih);

	aprint_naive(": AHCI SATA controller\n");
	aprint_normal(": AHCI SATA controller\n");

	/*
	 * Bring up the PHY.
	 */
	awin_ahci_phy_init(asc);

	/*
	 * If there is a GPIO to turn on power, do it now.
	 */
	const char *pin_name;
	prop_dictionary_t dict = device_properties(self);
	if (prop_dictionary_get_cstring_nocopy(dict, "power-gpio", &pin_name)) {
		if (awin_gpio_pin_reserve(pin_name, &asc->asc_gpio_pin)) {
			awin_gpio_pindata_write(&asc->asc_gpio_pin, 1);
		} else {
			aprint_error_dev(self,
			    "failed to reserve GPIO \"%s\"\n", pin_name);
		}
	}

	/*
	 * Establish the interrupt
	 */
	asc->asc_ih = intr_establish(loc->loc_intr, IPL_BIO, IST_LEVEL,
	    ahci_intr, sc);
	if (asc->asc_ih == NULL) {
		aprint_error_dev(self, "failed to establish interrupt %d\n",
		     loc->loc_intr);
		goto fail;
	}
	aprint_normal_dev(self, "interrupting on irq %d\n", loc->loc_intr);

	ahci_attach(sc);

	return;

fail:
	if (asc->asc_ih) {
		intr_disestablish(asc->asc_ih);
		asc->asc_ih = NULL;
	}
}
Ejemplo n.º 4
0
static void
awin_tcon0_set_video(struct awin_tcon_softc *sc)
{
	int32_t lcd_x, lcd_y, lcd_dclk_freq;
	int32_t lcd_hbp, lcd_ht, lcd_vbp, lcd_vt;
	int32_t lcd_hspw, lcd_vspw, lcd_io_cfg0;
	uint32_t vblk, start_delay;
	prop_dictionary_t cfg = device_properties(sc->sc_dev);
	uint32_t val;
	bool propb;
	bool dualchan = false;
	static struct videomode mode;

	if (!prop_dictionary_get_int32(cfg, "lcd_x", &lcd_x)) {
		aprint_error_dev(sc->sc_dev, ": can't read lcd_x\n");
		return;
	}
	if (!prop_dictionary_get_int32(cfg, "lcd_y", &lcd_y)) {
		aprint_error_dev(sc->sc_dev, ": can't read lcd_y\n");
		return;
	}
	if (!prop_dictionary_get_int32(cfg, "lcd_dclk_freq", &lcd_dclk_freq)) {
		aprint_error_dev(sc->sc_dev, ": can't read lcd_dclk_freq\n");
		return;
	}
	if (!prop_dictionary_get_int32(cfg, "lcd_hbp", &lcd_hbp)) {
		aprint_error_dev(sc->sc_dev, ": can't read lcd_hbp\n");
		return;
	}
	if (!prop_dictionary_get_int32(cfg, "lcd_ht", &lcd_ht)) {
		aprint_error_dev(sc->sc_dev, ": can't read lcd_ht\n");
		return;
	}
	if (!prop_dictionary_get_int32(cfg, "lcd_vbp", &lcd_vbp)) {
		aprint_error_dev(sc->sc_dev, ": can't read lcd_vbp\n");
		return;
	}
	if (!prop_dictionary_get_int32(cfg, "lcd_vt", &lcd_vt)) {
		aprint_error_dev(sc->sc_dev, ": can't read lcd_vt\n");
		return;
	}
	if (!prop_dictionary_get_int32(cfg, "lcd_hspw", &lcd_hspw)) {
		aprint_error_dev(sc->sc_dev, ": can't read lcd_hspw\n");
		return;
	}
	if (!prop_dictionary_get_int32(cfg, "lcd_vspw", &lcd_vspw)) {
		aprint_error_dev(sc->sc_dev, ": can't read lcd_vspw\n");
		return;
	}
	if (!prop_dictionary_get_int32(cfg, "lcd_io_cfg0", &lcd_io_cfg0)) {
		aprint_error_dev(sc->sc_dev, ": can't read lcd_io_cfg0\n");
		return;
	}

	if (prop_dictionary_get_bool(cfg, "lvds_dual", &propb) && propb)
		dualchan = true;
	if (!awin_gpio_pinset_available(&awin_lvds0_pinset)) {
		aprint_error_dev(sc->sc_dev, "lvds0 pins not available\n");
		return;
	}
	if (dualchan && !awin_gpio_pinset_available(&awin_lvds1_pinset)) {
		aprint_error_dev(sc->sc_dev, "lvds1 pins not available\n");
		return;
	}
	awin_gpio_pinset_acquire(&awin_lvds0_pinset);
	if (dualchan) {
		awin_gpio_pinset_acquire(&awin_lvds1_pinset);
	}
	prop_dictionary_get_cstring_nocopy(cfg, "lcd_power_en",
	    &sc->sc_lcdpwr_pin_name);
	if (sc->sc_lcdpwr_pin_name != NULL) {
		if (!awin_gpio_pin_reserve(
		    sc->sc_lcdpwr_pin_name, &sc->sc_lcdpwr_pin)) {
			aprint_error_dev(sc->sc_dev,
			    "failed to reserve GPIO \"%s\" for LCD power\n",
			    sc->sc_lcdpwr_pin_name);
			sc->sc_lcdpwr_pin_name = NULL;
		} else {
			aprint_verbose_dev(sc->sc_dev,
			    ": using GPIO \"%s\" for LCD power\n", 
			    sc->sc_lcdpwr_pin_name);
		}
	}
	prop_dictionary_get_cstring_nocopy(cfg, "lcd_bl_en",
	    &sc->sc_lcdblk_pin_name);
	if (sc->sc_lcdblk_pin_name != NULL) {
		if (!awin_gpio_pin_reserve(
		    sc->sc_lcdblk_pin_name, &sc->sc_lcdblk_pin)) {
			aprint_error_dev(sc->sc_dev,
			    "failed to reserve GPIO \"%s\" for backlight\n",
			    sc->sc_lcdblk_pin_name);
			sc->sc_lcdblk_pin_name = NULL;
		} else {
			if (sc->sc_lcdpwr_pin_name == NULL) {
				aprint_verbose_dev(sc->sc_dev,
				    ": using GPIO \"%s\" for backlight\n", 
				    sc->sc_lcdblk_pin_name);
			} else {
				aprint_verbose(
				    ", GPIO \"%s\" for backlight\n", 
				    sc->sc_lcdblk_pin_name);
			}
		}
	}

	if (sc->sc_lcdpwr_pin_name != NULL) {
		awin_gpio_pindata_write(&sc->sc_lcdpwr_pin, 1);
	}

	vblk = (lcd_vt / 2) - lcd_y;
	start_delay = (vblk >= 32) ? 30 : (vblk - 2);

	if (lcd_dclk_freq > 150) /* hardware limit ? */
		lcd_dclk_freq = 150;
	awin_tcon_set_pll(sc, lcd_dclk_freq * 1000, 7);

	val = AWIN_TCONx_CTL_EN;
	val |= __SHIFTIN(start_delay, AWIN_TCONx_CTL_START_DELAY);
	/*
	 * the DE selector selects the primary DEBE for this tcon:
	 * 0 selects debe0 for tcon0 and debe1 for tcon1
	 */
	val |= __SHIFTIN(AWIN_TCONx_CTL_SRC_SEL_DE0,
			 AWIN_TCONx_CTL_SRC_SEL);
	TCON_WRITE(sc, AWIN_TCON0_CTL_REG, val);

	val =  (lcd_x - 1) << 16 |  (lcd_y - 1);
	TCON_WRITE(sc, AWIN_TCON0_BASIC0_REG, val);
	val = (lcd_ht - 1) << 16 | (lcd_hbp - 1);
	TCON_WRITE(sc, AWIN_TCON0_BASIC1_REG, val);
	val = (lcd_vt) << 16 | (lcd_vbp - 1);
	TCON_WRITE(sc, AWIN_TCON0_BASIC2_REG, val);
	val =  ((lcd_hspw > 0) ? (lcd_hspw - 1) : 0) << 16;
	val |= ((lcd_vspw > 0) ? (lcd_vspw - 1) : 0);
	TCON_WRITE(sc, AWIN_TCON0_BASIC3_REG, val);

	val = 0;
	if (dualchan)
		val |= AWIN_TCON0_LVDS_IF_DUALCHAN;
	if (prop_dictionary_get_bool(cfg, "lvds_mode_jeida", &propb) && propb)
		val |= AWIN_TCON0_LVDS_IF_MODE_JEIDA;
	if (prop_dictionary_get_bool(cfg, "lvds_18bits", &propb) && propb)
		val |= AWIN_TCON0_LVDS_IF_18BITS;
	TCON_WRITE(sc, AWIN_TCON0_LVDS_IF_REG, val);


	TCON_WRITE(sc, AWIN_TCON0_IO_POL_REG, lcd_io_cfg0);
	TCON_WRITE(sc, AWIN_TCON0_IO_TRI_REG, 0);
	TCON_WRITE(sc, AWIN_TCON_GINT1_REG,
	    __SHIFTIN(start_delay + 2, AWIN_TCON_GINT1_TCON0_LINENO));

	val = 0xf0000000;
	val &= ~AWIN_TCON0_DCLK_DIV;
	val |= __SHIFTIN(sc->sc_clk_div, AWIN_TCON0_DCLK_DIV);
	TCON_WRITE(sc, AWIN_TCON0_DCLK_REG, val);

	mode.dot_clock = lcd_dclk_freq;
	mode.hdisplay = lcd_x;
	mode.hsync_start = lcd_ht - lcd_hbp;
	mode.hsync_end = lcd_hspw + mode.hsync_start;
	mode.htotal = lcd_ht;
	mode.vdisplay = lcd_y;
	mode.vsync_start = lcd_vt - lcd_vbp;
	mode.vsync_end = lcd_vspw + mode.vsync_start;
	mode.vtotal = lcd_vt;
	mode.flags = 0;
	mode.name = NULL;

	awin_debe_set_videomode(sc->sc_debe_unit, &mode);

	/* and finally, enable it */
	awin_debe_enable(sc->sc_debe_unit, true);
	delay(20000);

	val = TCON_READ(sc, AWIN_TCON_GCTL_REG);
	val |= AWIN_TCON_GCTL_EN;
	TCON_WRITE(sc, AWIN_TCON_GCTL_REG, val);
	delay(20000);


	val = TCON_READ(sc, AWIN_TCON0_LVDS_IF_REG);
	val |= AWIN_TCON0_LVDS_IF_EN;
	TCON_WRITE(sc, AWIN_TCON0_LVDS_IF_REG, val);

	/* XXX
	 * magic values here from linux. these are not documented
	 * in the A20 user manual, and other Allwiner LVDS-capable SoC
	 * documentation don't make sense with these values
	 */
	val = TCON_READ(sc, AWIN_TCON_LVDS_ANA0);
	val |= 0x3F310000;
	TCON_WRITE(sc, AWIN_TCON_LVDS_ANA0, val);
	val = TCON_READ(sc, AWIN_TCON_LVDS_ANA0);
	val |= 1 << 22;
	TCON_WRITE(sc, AWIN_TCON_LVDS_ANA0, val);
	delay(2);
	val = TCON_READ(sc, AWIN_TCON_LVDS_ANA1);
	val |= (0x1f << 26 | 0x1f << 10);
	TCON_WRITE(sc, AWIN_TCON_LVDS_ANA1, val);
	delay(2);
	val = TCON_READ(sc, AWIN_TCON_LVDS_ANA1);
	val |= (0x1f << 16 | 0x1f << 0);
	TCON_WRITE(sc, AWIN_TCON_LVDS_ANA1, val);
	val = TCON_READ(sc, AWIN_TCON_LVDS_ANA0);
	val |= 1 << 22;
	TCON_WRITE(sc, AWIN_TCON_LVDS_ANA0, val);

	if (sc->sc_lcdblk_pin_name != NULL) {
		awin_gpio_pindata_write(&sc->sc_lcdblk_pin, 1);
	}
}
Ejemplo n.º 5
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
}
Ejemplo n.º 6
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);
}