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_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);
}
示例#3
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;

	sc->sc_dev = self;

	awin_gpio_pinset_acquire(&awin_gige_pinset);

	sc->sc_bst = aio->aio_core_bst;
	sc->sc_dmat = aio->aio_dmat;
	bus_space_subregion(sc->sc_bst, aio->aio_core_bsh,
	    loc->loc_offset, loc->loc_size, &sc->sc_bsh);

	aprint_naive("\n");
	aprint_normal(": Gigabit Ethernet Controller\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);
	}
}
示例#5
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);
}