Esempio n. 1
0
int funcmux_select(enum periph_id id, int config)
{
	int bad_config = config != FUNCMUX_DEFAULT;

	switch (id) {
	case PERIPH_ID_UART1:
		switch (config) {
		case FUNCMUX_UART1_ULPI:
			pinmux_set_func(PINGRP_ULPI_DATA0, PMUX_FUNC_UARTA);
			pinmux_set_func(PINGRP_ULPI_DATA1, PMUX_FUNC_UARTA);
			pinmux_set_func(PINGRP_ULPI_DATA2, PMUX_FUNC_UARTA);
			pinmux_set_func(PINGRP_ULPI_DATA3, PMUX_FUNC_UARTA);
			pinmux_tristate_disable(PINGRP_ULPI_DATA0);
			pinmux_tristate_disable(PINGRP_ULPI_DATA1);
			pinmux_tristate_disable(PINGRP_ULPI_DATA2);
			pinmux_tristate_disable(PINGRP_ULPI_DATA3);
			break;
		}
		break;

	/* Add other periph IDs here as needed */

	default:
		debug("%s: invalid periph_id %d", __func__, id);
		return -1;
	}

	if (bad_config) {
		debug("%s: invalid config %d for periph_id %d", __func__,
		      config, id);
		return -1;
	}
	return 0;
}
Esempio n. 2
0
void pinmux_config_pingroup(const struct pingroup_config *config)
{
	enum pmux_pingrp pin = config->pingroup;

	pinmux_set_func(pin, config->func);
	pinmux_set_pullupdown(pin, config->pull);
	pinmux_set_tristate(pin, config->tristate);
}
Esempio n. 3
0
void pin_mux_usb(void)
{
	funcmux_select(PERIPH_ID_USB2, FUNCMUX_USB2_ULPI);
	pinmux_set_func(PINGRP_CDEV2, PMUX_FUNC_PLLP_OUT4);
	pinmux_tristate_disable(PINGRP_CDEV2);
	/* USB2 PHY reset GPIO */
	pinmux_tristate_disable(PINGRP_UAC);
}
Esempio n. 4
0
/**
 * Handle the next stage of device init
 */
static int handle_stage(const void *blob, struct tegra_lcd_priv *priv)
{
    debug("%s: stage %d\n", __func__, priv->stage);

    /* do the things for this stage */
    switch (priv->stage) {
    case STAGE_START:
        /*
         * It is possible that the FDT has requested that the LCD be
         * disabled. We currently don't support this. It would require
         * changes to U-Boot LCD subsystem to have LCD support
         * compiled in but not used. An easier option might be to
         * still have a frame buffer, but leave the backlight off and
         * remove all mention of lcd in the stdout environment
         * variable.
         */

        funcmux_select(PERIPH_ID_DISP1, FUNCMUX_DEFAULT);
        break;
    case STAGE_PANEL_VDD:
        if (dm_gpio_is_valid(&priv->panel_vdd))
            dm_gpio_set_value(&priv->panel_vdd, 1);
        break;
    case STAGE_LVDS:
        if (dm_gpio_is_valid(&priv->lvds_shutdown))
            dm_gpio_set_value(&priv->lvds_shutdown, 1);
        break;
    case STAGE_BACKLIGHT_VDD:
        if (dm_gpio_is_valid(&priv->backlight_vdd))
            dm_gpio_set_value(&priv->backlight_vdd, 1);
        break;
    case STAGE_PWM:
        /* Enable PWM at 15/16 high, 32768 Hz with divider 1 */
        pinmux_set_func(PMUX_PINGRP_GPU, PMUX_FUNC_PWM);
        pinmux_tristate_disable(PMUX_PINGRP_GPU);

        pwm_set_config(priv->pwm, priv->pwm_channel, 0xdf, 0xff);
        pwm_set_enable(priv->pwm, priv->pwm_channel, true);
        break;
    case STAGE_BACKLIGHT_EN:
        if (dm_gpio_is_valid(&priv->backlight_en))
            dm_gpio_set_value(&priv->backlight_en, 1);
        break;
    case STAGE_DONE:
        break;
    }

    /* set up timer for next stage */
    priv->timer_next = timer_get_us();
    if (priv->stage < FDT_LCD_TIMINGS)
        priv->timer_next += priv->panel_timings[priv->stage] * 1000;

    /* move to next stage */
    priv->stage++;
    return 0;
}
Esempio n. 5
0
void pin_mux_usb(void)
{
	/* For USB0's GPIO PD0. For now, since we have no pinmux in fdt */
	pinmux_tristate_disable(PMUX_PINGRP_SLXK);
	/* For USB1's ULPI signals */
	funcmux_select(PERIPH_ID_USB2, FUNCMUX_USB2_ULPI);
	pinmux_set_func(PMUX_PINGRP_CDEV2, PMUX_FUNC_PLLP_OUT4);
	pinmux_tristate_disable(PMUX_PINGRP_CDEV2);
	/* USB1 PHY reset GPIO */
	pinmux_tristate_disable(PMUX_PINGRP_UAC);
}
Esempio n. 6
0
/*
 * Routine: pin_mux_mmc
 * Description: setup the pin muxes/tristate values for the SDMMC(s)
 */
static void pin_mux_mmc(void)
{
	/* SDMMC4: config 3, x8 on 2nd set of pins */
	pinmux_set_func(PINGRP_ATB, PMUX_FUNC_SDIO4);
	pinmux_set_func(PINGRP_GMA, PMUX_FUNC_SDIO4);
	pinmux_set_func(PINGRP_GME, PMUX_FUNC_SDIO4);

	pinmux_tristate_disable(PINGRP_ATB);
	pinmux_tristate_disable(PINGRP_GMA);
	pinmux_tristate_disable(PINGRP_GME);

	/* SDMMC1: SDIO1_CLK, SDIO1_CMD, SDIO1_DAT[3:0] */
	pinmux_set_func(PINGRP_SDMMC1, PMUX_FUNC_SDIO1);

	pinmux_tristate_disable(PINGRP_SDMMC1);

	/* For power GPIO PV1 */
	pinmux_tristate_disable(PINGRP_UAC);
	/* For CD GPIO PI5 */
	pinmux_tristate_disable(PINGRP_ATC);
}
Esempio n. 7
0
void pinmux_config_pingroup(struct pingroup_config *config)
{
	enum pmux_pingrp pin = config->pingroup;

	pinmux_set_func(pin, config->func);
	pinmux_set_pullupdown(pin, config->pull);
	pinmux_set_tristate(pin, config->tristate);
	pinmux_set_io(pin, config->io);
	pinmux_set_lock(pin, config->lock);
	pinmux_set_od(pin, config->od);
	pinmux_set_ioreset(pin, config->ioreset);
}
void colibri_t20_common_pin_mux_usb(void)
{
	/* module internal USB bus to connect ethernet chipset */
	funcmux_select(PERIPH_ID_USB2, FUNCMUX_USB2_ULPI);
	/* ULPI reference clock output */
	pinmux_set_func(PMUX_PINGRP_CDEV2, PMUX_FUNC_PLLP_OUT4);
	pinmux_tristate_disable(PMUX_PINGRP_CDEV2);
	/* PHY reset GPIO */
	pinmux_tristate_disable(PMUX_PINGRP_UAC);
	/* VBus GPIO */
	pinmux_tristate_disable(PMUX_PINGRP_DTE);
}
Esempio n. 9
0
int funcmux_select(enum periph_id id, int config)
{
	int bad_config = config != FUNCMUX_DEFAULT;

	switch (id) {
	case PERIPH_ID_UART4:
		switch (config) {
		case FUNCMUX_UART4_GMI:
			pinmux_set_func(PINGRP_GMI_A16, PMUX_FUNC_UARTD);
			pinmux_set_func(PINGRP_GMI_A17, PMUX_FUNC_UARTD);
			pinmux_set_func(PINGRP_GMI_A18, PMUX_FUNC_UARTD);
			pinmux_set_func(PINGRP_GMI_A19, PMUX_FUNC_UARTD);

			pinmux_set_io(PINGRP_GMI_A16, PMUX_PIN_OUTPUT);
			pinmux_set_io(PINGRP_GMI_A17, PMUX_PIN_INPUT);
			pinmux_set_io(PINGRP_GMI_A18, PMUX_PIN_INPUT);
			pinmux_set_io(PINGRP_GMI_A19, PMUX_PIN_OUTPUT);

			pinmux_tristate_disable(PINGRP_GMI_A16);
			pinmux_tristate_disable(PINGRP_GMI_A17);
			pinmux_tristate_disable(PINGRP_GMI_A18);
			pinmux_tristate_disable(PINGRP_GMI_A19);
			break;
		}
		break;

	/* Add other periph IDs here as needed */

	default:
		debug("%s: invalid periph_id %d", __func__, id);
		return -1;
	}

	if (bad_config) {
		debug("%s: invalid config %d for periph_id %d", __func__,
		      config, id);
		return -1;
	}
	return 0;
}
Esempio n. 10
0
static int tegra20_sflash_claim_bus(struct udevice *dev)
{
	struct udevice *bus = dev->parent;
	struct tegra20_sflash_priv *priv = dev_get_priv(bus);
	struct spi_regs *regs = priv->regs;
	u32 reg;

	/* Change SPI clock to correct frequency, PLLP_OUT0 source */
	clock_start_periph_pll(priv->periph_id, CLOCK_ID_PERIPH,
			       priv->freq);

	/* Clear stale status here */
	reg = SPI_STAT_RDY | SPI_STAT_RXF_FLUSH | SPI_STAT_TXF_FLUSH | \
		SPI_STAT_RXF_UNR | SPI_STAT_TXF_OVF;
	writel(reg, &regs->status);
	debug("%s: STATUS = %08x\n", __func__, readl(&regs->status));

	/*
	 * Use sw-controlled CS, so we can clock in data after ReadID, etc.
	 */
	reg = (priv->mode & 1) << SPI_CMD_ACTIVE_SDA_SHIFT;
	if (priv->mode & 2)
		reg |= 1 << SPI_CMD_ACTIVE_SCLK_SHIFT;
	clrsetbits_le32(&regs->command, SPI_CMD_ACTIVE_SCLK_MASK |
		SPI_CMD_ACTIVE_SDA_MASK, SPI_CMD_CS_SOFT | reg);
	debug("%s: COMMAND = %08x\n", __func__, readl(&regs->command));

	/*
	 * SPI pins on Tegra20 are muxed - change pinmux later due to UART
	 * issue.
	 */
	pinmux_set_func(PMUX_PINGRP_GMD, PMUX_FUNC_SFLASH);
	pinmux_tristate_disable(PMUX_PINGRP_LSPI);
	pinmux_set_func(PMUX_PINGRP_GMC, PMUX_FUNC_SFLASH);

	return 0;
}
Esempio n. 11
0
int funcmux_select(enum periph_id id, int config)
{
	int bad_config = config != FUNCMUX_DEFAULT;

	switch (id) {
	case PERIPH_ID_UART4:
		switch (config) {
		case FUNCMUX_UART4_GPIO: /* TXD,RXD,CTS,RTS */
			pinmux_set_func(PMUX_PINGRP_PJ7, PMUX_FUNC_UARTD);
			pinmux_set_func(PMUX_PINGRP_PB0, PMUX_FUNC_UARTD);
			pinmux_set_func(PMUX_PINGRP_PB1, PMUX_FUNC_UARTD);
			pinmux_set_func(PMUX_PINGRP_PK7, PMUX_FUNC_UARTD);

			pinmux_set_io(PMUX_PINGRP_PJ7, PMUX_PIN_OUTPUT);
			pinmux_set_io(PMUX_PINGRP_PB0, PMUX_PIN_INPUT);
			pinmux_set_io(PMUX_PINGRP_PB1, PMUX_PIN_INPUT);
			pinmux_set_io(PMUX_PINGRP_PK7, PMUX_PIN_OUTPUT);

			pinmux_tristate_disable(PMUX_PINGRP_PJ7);
			pinmux_tristate_disable(PMUX_PINGRP_PB0);
			pinmux_tristate_disable(PMUX_PINGRP_PB1);
			pinmux_tristate_disable(PMUX_PINGRP_PK7);
			break;
		}
		break;

	case PERIPH_ID_UART1:
		switch (config) {
		case FUNCMUX_UART1_KBC:
			pinmux_set_func(PMUX_PINGRP_KB_ROW9_PS1,
					PMUX_FUNC_UARTA);
			pinmux_set_func(PMUX_PINGRP_KB_ROW10_PS2,
					PMUX_FUNC_UARTA);

			pinmux_set_io(PMUX_PINGRP_KB_ROW9_PS1, PMUX_PIN_OUTPUT);
			pinmux_set_io(PMUX_PINGRP_KB_ROW10_PS2, PMUX_PIN_INPUT);

			pinmux_tristate_disable(PMUX_PINGRP_KB_ROW9_PS1);
			pinmux_tristate_disable(PMUX_PINGRP_KB_ROW10_PS2);
			break;
		}
		break;

	/* Add other periph IDs here as needed */

	default:
		debug("%s: invalid periph_id %d", __func__, id);
		return -1;
	}

	if (bad_config) {
		debug("%s: invalid config %d for periph_id %d", __func__,
		      config, id);
		return -1;
	}
	return 0;
}
Esempio n. 12
0
int arch_misc_init(void)
{
	/* Disable PMIC sleep mode on low supply voltage */
	struct udevice *dev;
	u8 addr, data[1];
	int err;

	err = i2c_get_chip_for_busnum(0, PMU_I2C_ADDRESS, 1, &dev);
	if (err) {
		debug("%s: Cannot find PMIC I2C chip\n", __func__);
		return err;
	}

	addr = PMU_SUPPLYENE;

	err = dm_i2c_read(dev, addr, data, 1);
	if (err) {
		debug("failed to get PMU_SUPPLYENE\n");
		return err;
	}

	data[0] &= ~PMU_SUPPLYENE_SYSINEN;
	data[0] |= PMU_SUPPLYENE_EXITSLREQ;

	err = dm_i2c_write(dev, addr, data, 1);
	if (err) {
		debug("failed to set PMU_SUPPLYENE\n");
		return err;
	}

	/* make sure SODIMM pin 87 nRESET_OUT is released properly */
	pinmux_set_func(PMUX_PINGRP_ATA, PMUX_FUNC_GMI);

	if (readl(NV_PA_BASE_SRAM + NVBOOTINFOTABLE_BOOTTYPE) ==
	    NVBOOTTYPE_RECOVERY)
		printf("USB recovery mode\n");

	return 0;
}
Esempio n. 13
0
static void i2c_pin_mux_select(struct i2c_bus *i2c_bus, int pinmux_config)
{
	switch (i2c_bus->periph_id) {
	case PERIPH_ID_DVC_I2C:	/* DVC I2C (I2CP) */
		/* there is only one selection, pinmux_config is ignored */
		pinmux_set_func(PINGRP_I2CP, PMUX_FUNC_I2C);
		break;
	case PERIPH_ID_I2C1: /* I2C1 */
		/* support pinmux_config of 1 for now, */
		pinmux_set_func(PINGRP_RM, PMUX_FUNC_I2C);
		break;
	case PERIPH_ID_I2C2: /* I2C2 */
		switch (pinmux_config) {
		case 1:	/* DDC pin group, select I2C2 */
			pinmux_set_func(PINGRP_DDC, PMUX_FUNC_I2C2);
			/* PTA to HDMI */
			pinmux_set_func(PINGRP_PTA, PMUX_FUNC_HDMI);
			break;
		case 2:	/* PTA pin group, select I2C2 */
			pinmux_set_func(PINGRP_PTA, PMUX_FUNC_I2C2);
			/* set DDC_SEL to RSVDx (RSVD2 works for now) */
			pinmux_set_func(PINGRP_DDC, PMUX_FUNC_RSVD2);
			break;
		default:
			printf("bad pinmux_config(%d): pinmux select ignored\n",
			       pinmux_config);
			break;
		}
		break;
	case PERIPH_ID_I2C3: /* I2C3 */
		/* support pinmux_config of 1 for now */
		pinmux_set_func(PINGRP_DTF, PMUX_FUNC_I2C3);
		break;
	default:
		break;
	}
}
Esempio n. 14
0
File: tegra.c Progetto: JamesAng/ub
/**
 * Handle the next stage of device init
 */
static int handle_stage(const void *blob)
{
	debug("%s: stage %d\n", __func__, stage);

	/* do the things for this stage */
	switch (stage) {
	case STAGE_START:
		/* Initialize the Tegra display controller */
		if (tegra_display_probe(gd->fdt_blob, (void *)gd->fb_base)) {
			printf("%s: Failed to probe display driver\n",
			__func__);
			return -1;
		}

		/* get panel details */
		if (fdt_decode_lcd(blob, &config)) {
			printf("No valid LCD information in device tree\n");
			return -1;
		}

		/*
		 * It is possible that the FDT has requested that the LCD be
		 * disabled. We currently don't support this. It would require
		 * changes to U-Boot LCD subsystem to have LCD support
		 * compiled in but not used. An easier option might be to
		 * still have a frame buffer, but leave the backlight off and
		 * remove all mention of lcd in the stdout environment
		 * variable.
		 */

		funcmux_select(PERIPH_ID_DISP1, FUNCMUX_DEFAULT);

		fdtdec_setup_gpio(&config.panel_vdd);
		fdtdec_setup_gpio(&config.lvds_shutdown);
		fdtdec_setup_gpio(&config.backlight_vdd);
		fdtdec_setup_gpio(&config.backlight_en);

		/*
		 * TODO: If fdt includes output flag we can omit this code
		 * since fdtdec_setup_gpio will do it for us.
		 */
		if (fdt_gpio_isvalid(&config.panel_vdd))
			gpio_direction_output(config.panel_vdd.gpio, 0);
		if (fdt_gpio_isvalid(&config.lvds_shutdown))
			gpio_direction_output(config.lvds_shutdown.gpio, 0);
		if (fdt_gpio_isvalid(&config.backlight_vdd))
			gpio_direction_output(config.backlight_vdd.gpio, 0);
		if (fdt_gpio_isvalid(&config.backlight_en))
			gpio_direction_output(config.backlight_en.gpio, 0);
		break;
	case STAGE_PANEL_VDD:
		if (fdt_gpio_isvalid(&config.panel_vdd))
			gpio_direction_output(config.panel_vdd.gpio, 1);
		break;
	case STAGE_LVDS:
		if (fdt_gpio_isvalid(&config.lvds_shutdown))
			gpio_set_value(config.lvds_shutdown.gpio, 1);
		break;
	case STAGE_BACKLIGHT_VDD:
		if (fdt_gpio_isvalid(&config.backlight_vdd))
			gpio_set_value(config.backlight_vdd.gpio, 1);
		break;
	case STAGE_PWM:
		/* Enable PWM at 15/16 high, 32768 Hz with divider 1 */
		pinmux_set_func(PINGRP_GPU, PMUX_FUNC_PWM);
		pinmux_tristate_disable(PINGRP_GPU);

		pwm_enable(config.pwm_channel, 32768, 0xdf, 1);
		break;
	case STAGE_BACKLIGHT_EN:
		if (fdt_gpio_isvalid(&config.backlight_en))
			gpio_set_value(config.backlight_en.gpio, 1);
		break;
	case STAGE_DONE:
		break;
	}

	/* set up timer for next stage */
	timer_next = timer_get_us();
	if (stage < FDT_LCD_TIMINGS)
		timer_next += config.panel_timings[stage] * 1000;

	/* move to next stage */
	stage++;
	return 0;
}
Esempio n. 15
0
void pin_mux_display(void)
{
	pinmux_set_func(PINGRP_SDC, PMUX_FUNC_PWM);
	pinmux_tristate_disable(PINGRP_SDC);
}
Esempio n. 16
0
int funcmux_select(enum periph_id id, int config)
{
    int bad_config = config != FUNCMUX_DEFAULT;

    switch (id) {
    case PERIPH_ID_UART1:
        if (config == FUNCMUX_UART1_IRRX_IRTX) {
            pinmux_set_func(PINGRP_IRRX, PMUX_FUNC_UARTA);
            pinmux_set_func(PINGRP_IRTX, PMUX_FUNC_UARTA);
            pinmux_tristate_disable(PINGRP_IRRX);
            pinmux_tristate_disable(PINGRP_IRTX);
            /*
             * Tegra appears to boot with function UARTA pre-
             * selected on mux group SDB. If two mux groups are
             * both set to the same function, it's unclear which
             * group's pins drive the RX signals into the HW.
             * For UARTA, SDB certainly overrides group IRTX in
             * practice. To solve this, configure some alternative
             * function on SDB to avoid the conflict. Also, tri-
             * state the group to avoid driving any signal onto it
             * until we know what's connected.
             */
            pinmux_tristate_enable(PINGRP_SDB);
            pinmux_set_func(PINGRP_SDB,  PMUX_FUNC_SDIO3);
        }
        break;

    case PERIPH_ID_UART2:
        if (config == FUNCMUX_UART2_IRDA) {
            pinmux_set_func(PINGRP_UAD, PMUX_FUNC_IRDA);
            pinmux_tristate_disable(PINGRP_UAD);
        }
        break;

    case PERIPH_ID_UART4:
        if (config == FUNCMUX_UART4_GMC) {
            pinmux_set_func(PINGRP_GMC, PMUX_FUNC_UARTD);
            pinmux_tristate_disable(PINGRP_GMC);
        }
        break;

    case PERIPH_ID_DVC_I2C:
        /* there is only one selection, pinmux_config is ignored */
        if (config == FUNCMUX_DVC_I2CP) {
            pinmux_set_func(PINGRP_I2CP, PMUX_FUNC_I2C);
            pinmux_tristate_disable(PINGRP_I2CP);
        }
        break;

    case PERIPH_ID_I2C1:
        /* support pinmux_config of 0 for now, */
        if (config == FUNCMUX_I2C1_RM) {
            pinmux_set_func(PINGRP_RM, PMUX_FUNC_I2C);
            pinmux_tristate_disable(PINGRP_RM);
        }
        break;
    case PERIPH_ID_I2C2: /* I2C2 */
        switch (config) {
        case FUNCMUX_I2C2_DDC:	/* DDC pin group, select I2C2 */
            pinmux_set_func(PINGRP_DDC, PMUX_FUNC_I2C2);
            /* PTA to HDMI */
            pinmux_set_func(PINGRP_PTA, PMUX_FUNC_HDMI);
            pinmux_tristate_disable(PINGRP_DDC);
            break;
        case FUNCMUX_I2C2_PTA:	/* PTA pin group, select I2C2 */
            pinmux_set_func(PINGRP_PTA, PMUX_FUNC_I2C2);
            /* set DDC_SEL to RSVDx (RSVD2 works for now) */
            pinmux_set_func(PINGRP_DDC, PMUX_FUNC_RSVD2);
            pinmux_tristate_disable(PINGRP_PTA);
            bad_config = 0;
            break;
        }
        break;
    case PERIPH_ID_I2C3: /* I2C3 */
        /* support pinmux_config of 0 for now */
        if (config == FUNCMUX_I2C3_DTF) {
            pinmux_set_func(PINGRP_DTF, PMUX_FUNC_I2C3);
            pinmux_tristate_disable(PINGRP_DTF);
        }
        break;

    case PERIPH_ID_SDMMC2:
        if (config == FUNCMUX_SDMMC2_DTA_DTD_8BIT) {
            pinmux_set_func(PINGRP_DTA, PMUX_FUNC_SDIO2);
            pinmux_set_func(PINGRP_DTD, PMUX_FUNC_SDIO2);

            pinmux_tristate_disable(PINGRP_DTA);
            pinmux_tristate_disable(PINGRP_DTD);
        }
        break;

    case PERIPH_ID_SDMMC3:
        switch (config) {
        case FUNCMUX_SDMMC3_SDB_SLXA_8BIT:
            pinmux_set_func(PINGRP_SLXA, PMUX_FUNC_SDIO3);
            pinmux_set_func(PINGRP_SLXC, PMUX_FUNC_SDIO3);
            pinmux_set_func(PINGRP_SLXD, PMUX_FUNC_SDIO3);
            pinmux_set_func(PINGRP_SLXK, PMUX_FUNC_SDIO3);

            pinmux_tristate_disable(PINGRP_SLXA);
            pinmux_tristate_disable(PINGRP_SLXC);
            pinmux_tristate_disable(PINGRP_SLXD);
            pinmux_tristate_disable(PINGRP_SLXK);
        /* fall through */

        case FUNCMUX_SDMMC3_SDB_4BIT:
            pinmux_set_func(PINGRP_SDB, PMUX_FUNC_SDIO3);
            pinmux_set_func(PINGRP_SDC, PMUX_FUNC_SDIO3);
            pinmux_set_func(PINGRP_SDD, PMUX_FUNC_SDIO3);

            pinmux_tristate_disable(PINGRP_SDB);
            pinmux_tristate_disable(PINGRP_SDC);
            pinmux_tristate_disable(PINGRP_SDD);
            bad_config = 0;
            break;
        }
        break;

    case PERIPH_ID_SDMMC4:
        switch (config) {
        case FUNCMUX_SDMMC4_ATC_ATD_8BIT:
            pinmux_set_func(PINGRP_ATC, PMUX_FUNC_SDIO4);
            pinmux_set_func(PINGRP_ATD, PMUX_FUNC_SDIO4);

            pinmux_tristate_disable(PINGRP_ATC);
            pinmux_tristate_disable(PINGRP_ATD);
            break;

        case FUNCMUX_SDMMC4_ATB_GMA_GME_8_BIT:
            pinmux_set_func(PINGRP_GME, PMUX_FUNC_SDIO4);
            pinmux_tristate_disable(PINGRP_GME);
        /* fall through */

        case FUNCMUX_SDMMC4_ATB_GMA_4_BIT:
            pinmux_set_func(PINGRP_ATB, PMUX_FUNC_SDIO4);
            pinmux_set_func(PINGRP_GMA, PMUX_FUNC_SDIO4);

            pinmux_tristate_disable(PINGRP_ATB);
            pinmux_tristate_disable(PINGRP_GMA);
            bad_config = 0;
            break;
        }
        break;

    case PERIPH_ID_KBC:
        if (config == FUNCMUX_DEFAULT) {
            enum pmux_pingrp grp[] = {PINGRP_KBCA, PINGRP_KBCB,
                                      PINGRP_KBCC, PINGRP_KBCD, PINGRP_KBCE,
                                      PINGRP_KBCF
                                     };
            int i;

            for (i = 0; i < ARRAY_SIZE(grp); i++) {
                pinmux_tristate_disable(grp[i]);
                pinmux_set_func(grp[i], PMUX_FUNC_KBC);
                pinmux_set_pullupdown(grp[i], PMUX_PULL_UP);
            }

            break;
        }

    default:
        debug("%s: invalid periph_id %d", __func__, id);
        return -1;
    }

    if (bad_config) {
        debug("%s: invalid config %d for periph_id %d", __func__,
              config, id);
        return -1;
    }

    return 0;
}