/* * (C) Copyright 2010-2012 * NVIDIA Corporation * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ #include #include #include #include "pinmux-config-cardhu.h" #include #include #include #include #include #include #include #include /* * Routine: pinmux_init * Description: Do individual peripheral pinmux configs */ void pinmux_init(void) { pinmux_config_table(tegra3_pinmux_common, ARRAY_SIZE(tegra3_pinmux_common)); pinmux_config_table(unused_pins_lowpower, ARRAY_SIZE(unused_pins_lowpower)); } #if defined(CONFIG_MMC) /* * Routine: pin_mux_mmc * Description: setup the pin muxes/tristate values for the SDMMC(s) */ static void pin_mux_mmc(void) { } /* Do I2C/PMU writes to bring up SD card bus power */ static void board_sdmmc_voltage_init(void) { uchar reg, data_buffer[1]; int i; i2c_set_bus_num(0); /* PMU is on bus 0 */ data_buffer[0] = 0x65; reg = 0x32; for (i = 0; i < MAX_I2C_RETRY; ++i) { if (i2c_write(PMU_I2C_ADDRESS, reg, 1, data_buffer, 1)) udelay(100); } data_buffer[0] = 0x09; reg = 0x67; for (i = 0; i < MAX_I2C_RETRY; ++i) { if (i2c_write(PMU_I2C_ADDRESS, reg, 1, data_buffer, 1)) udelay(100); } } static void pad_init_mmc(struct tegra_mmc *reg) { struct apb_misc_gp_ctlr *const gpc = (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE; struct sdmmc_ctlr *const sdmmc = (struct sdmmc_ctlr *)reg; u32 val, offset = (unsigned int)reg; u32 padcfg, padmask; debug("%s: sdmmc address = %08x\n", __func__, (unsigned int)sdmmc); /* Set the pad drive strength for SDMMC1 or 3 only */ if (offset != TEGRA_SDMMC1_BASE && offset != TEGRA_SDMMC3_BASE) { debug("%s: settings are only valid for SDMMC1/SDMMC3!\n", __func__); return; } /* Set pads as per T30 TRM, section 24.6.1.2 */ padcfg = (GP_SDIOCFG_DRVUP_SLWF | GP_SDIOCFG_DRVDN_SLWR | \ GP_SDIOCFG_DRVUP | GP_SDIOCFG_DRVDN); padmask = 0x00000FFF; if (offset == TEGRA_SDMMC1_BASE) { val = readl(&gpc->sdio1cfg); val &= padmask; val |= padcfg; writel(val, &gpc->sdio1cfg); } else { /* SDMMC3 */ val = readl(&gpc->sdio3cfg); val &= padmask; val |= padcfg; writel(val, &gpc->sdio3cfg); } val = readl(&sdmmc->sdmmc_sdmemcomp_pad_ctrl); val &= 0xFFFFFFF0; val |= MEMCOMP_PADCTRL_VREF; writel(val, &sdmmc->sdmmc_sdmemcomp_pad_ctrl); val = readl(&sdmmc->sdmmc_auto_cal_config); val &= 0xFFFF0000; val |= AUTO_CAL_PU_OFFSET | AUTO_CAL_PD_OFFSET | AUTO_CAL_ENABLED; writel(val, &sdmmc->sdmmc_auto_cal_config); } /* this is a weak define that we are overriding */ int board_mmc_init(bd_t *bd) { debug("board_mmc_init called\n"); /* Turn on SD-card bus power */ board_sdmmc_voltage_init(); /* Set up the SDMMC pads as per the TRM */ pad_init_mmc((struct tegra_mmc *)TEGRA_SDMMC1_BASE); /* Enable muxes, etc. for SDMMC controllers */ pin_mux_mmc(); /* init dev 0 (SDMMC4), ("HSMMC") with 8-bit bus */ tegra_mmc_init(0, 8, -1, -1); /* init dev 1 (SDMMC0), ("SDIO") with 8-bit bus */ tegra_mmc_init(1, 8, -1, -1); return 0; } #endif /* MMC */