/* * Copyright (C) ST-Ericsson SA 2009 * * SPDX-License-Identifier: GPL-2.0+ */ #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CONFIG_MMC #include "../../../drivers/mmc/arm_pl180_mmci.h" #endif #include "db8500_pins.h" /* * Get a global data pointer */ DECLARE_GLOBAL_DATA_PTR; /* * Memory controller register */ #define DMC_BASE_ADDR 0x80156000 #define DMC_CTL_97 (DMC_BASE_ADDR + 0x184) /* * GPIO pin config common for MOP500/HREF boards */ unsigned long gpio_cfg_common[] = { /* I2C */ GPIO147_I2C0_SCL, GPIO148_I2C0_SDA, GPIO16_I2C1_SCL, GPIO17_I2C1_SDA, GPIO10_I2C2_SDA, GPIO11_I2C2_SCL, GPIO229_I2C3_SDA, GPIO230_I2C3_SCL, /* SSP0, to AB8500 */ GPIO143_SSP0_CLK, GPIO144_SSP0_FRM, GPIO145_SSP0_RXD | PIN_PULL_DOWN, GPIO146_SSP0_TXD, /* MMC0 (MicroSD card) */ GPIO18_MC0_CMDDIR | PIN_OUTPUT_HIGH, GPIO19_MC0_DAT0DIR | PIN_OUTPUT_HIGH, GPIO20_MC0_DAT2DIR | PIN_OUTPUT_HIGH, GPIO21_MC0_DAT31DIR | PIN_OUTPUT_HIGH, GPIO22_MC0_FBCLK | PIN_INPUT_NOPULL, GPIO23_MC0_CLK | PIN_OUTPUT_LOW, GPIO24_MC0_CMD | PIN_INPUT_PULLUP, GPIO25_MC0_DAT0 | PIN_INPUT_PULLUP, GPIO26_MC0_DAT1 | PIN_INPUT_PULLUP, GPIO27_MC0_DAT2 | PIN_INPUT_PULLUP, GPIO28_MC0_DAT3 | PIN_INPUT_PULLUP, /* MMC4 (On-board eMMC) */ GPIO197_MC4_DAT3 | PIN_INPUT_PULLUP, GPIO198_MC4_DAT2 | PIN_INPUT_PULLUP, GPIO199_MC4_DAT1 | PIN_INPUT_PULLUP, GPIO200_MC4_DAT0 | PIN_INPUT_PULLUP, GPIO201_MC4_CMD | PIN_INPUT_PULLUP, GPIO202_MC4_FBCLK | PIN_INPUT_NOPULL, GPIO203_MC4_CLK | PIN_OUTPUT_LOW, GPIO204_MC4_DAT7 | PIN_INPUT_PULLUP, GPIO205_MC4_DAT6 | PIN_INPUT_PULLUP, GPIO206_MC4_DAT5 | PIN_INPUT_PULLUP, GPIO207_MC4_DAT4 | PIN_INPUT_PULLUP, /* UART2, console */ GPIO29_U2_RXD | PIN_INPUT_PULLUP, GPIO30_U2_TXD | PIN_OUTPUT_HIGH, GPIO31_U2_CTSn | PIN_INPUT_PULLUP, GPIO32_U2_RTSn | PIN_OUTPUT_HIGH, /* * USB, pin 256-267 USB, Is probably already setup correctly from * BootROM/boot stages, but we don't trust that and set it up anyway */ GPIO256_USB_NXT, GPIO257_USB_STP, GPIO258_USB_XCLK, GPIO259_USB_DIR, GPIO260_USB_DAT7, GPIO261_USB_DAT6, GPIO262_USB_DAT5, GPIO263_USB_DAT4, GPIO264_USB_DAT3, GPIO265_USB_DAT2, GPIO266_USB_DAT1, GPIO267_USB_DAT0, }; unsigned long gpio_cfg_snowball[] = { /* MMC0 (MicroSD card) */ GPIO217_GPIO | PIN_OUTPUT_HIGH, /* MMC_EN */ GPIO218_GPIO | PIN_INPUT_NOPULL, /* MMC_CD */ GPIO228_GPIO | PIN_OUTPUT_HIGH, /* SD_SEL */ /* eMMC */ GPIO167_GPIO | PIN_OUTPUT_HIGH, /* RSTn_MLC */ /* LAN */ GPIO131_SM_ADQ8, GPIO132_SM_ADQ9, GPIO133_SM_ADQ10, GPIO134_SM_ADQ11, GPIO135_SM_ADQ12, GPIO136_SM_ADQ13, GPIO137_SM_ADQ14, GPIO138_SM_ADQ15, /* RSTn_LAN */ GPIO141_GPIO | PIN_OUTPUT_HIGH, }; /* * Miscellaneous platform dependent initialisations */ int board_init(void) { /* * Setup board (bd) and board-info (bi). * bi_arch_number: Unique id for this board. It will passed in r1 to * Linux startup code and is the machine_id. * bi_boot_params: Where this board expects params. */ gd->bd->bi_arch_number = MACH_TYPE_SNOWBALL; gd->bd->bi_boot_params = 0x00000100; /* Configure GPIO pins needed by U-boot */ db8500_gpio_config_pins(gpio_cfg_common, ARRAY_SIZE(gpio_cfg_common)); db8500_gpio_config_pins(gpio_cfg_snowball, ARRAY_SIZE(gpio_cfg_snowball)); return 0; } int dram_init(void) { gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; gd->ram_size = gd->bd->bi_dram[0].size = get_ram_size(CONFIG_SYS_SDRAM_BASE, CONFIG_SYS_MAX_RAM_SIZE); return 0; } static int raise_ab8500_gpio16(void) { int ret; /* selection */ ret = ab8500_read(AB8500_MISC, AB8500_GPIO_SEL2_REG); if (ret < 0) goto out; ret |= 0x80; ret = ab8500_write(AB8500_MISC, AB8500_GPIO_SEL2_REG, ret); if (ret < 0) goto out; /* direction */ ret = ab8500_read(AB8500_MISC, AB8500_GPIO_DIR2_REG); if (ret < 0) goto out; ret |= 0x80; ret = ab8500_write(AB8500_MISC, AB8500_GPIO_DIR2_REG, ret); if (ret < 0) goto out; /* out */ ret = ab8500_read(AB8500_MISC, AB8500_GPIO_OUT2_REG); if (ret < 0) goto out; ret |= 0x80; ret = ab8500_write(AB8500_MISC, AB8500_GPIO_OUT2_REG, ret); out: return ret; } static int raise_ab8500_gpio26(void) { int ret; /* selection */ ret = ab8500_read(AB8500_MISC, AB8500_GPIO_DIR4_REG); if (ret < 0) goto out; ret |= 0x2; ret = ab8500_write(AB8500_MISC, AB8500_GPIO_DIR4_REG, ret); if (ret < 0) goto out; /* out */ ret = ab8500_read(AB8500_MISC, AB8500_GPIO_OUT4_REG); if (ret < 0) goto out; ret |= 0x2; ret = ab8500_write(AB8500_MISC, AB8500_GPIO_OUT4_REG, ret); out: return ret; } int board_late_init(void) { /* enable 3V3 for LAN controller */ if (raise_ab8500_gpio26() >= 0) { /* Turn on FSMC device */ writel(0x1, 0x8000f000); writel(0x1, 0x8000f008); /* setup FSMC for LAN controler */ writel(0x305b, 0x80000000); /* run at the highest possible speed */ writel(0x01010210, 0x80000004); } else printf("error: can't raise GPIO26\n"); /* enable 3v6 for GBF chip */ if ((raise_ab8500_gpio16() < 0)) printf("error: cant' raise GPIO16\n"); /* empty UART RX FIFO */ while (tstc()) (void) getc(); return 0; } #ifdef CONFIG_MMC /* * emmc_host_init - initialize the emmc controller. * Configure GPIO settings, set initial clock and power for emmc slot. * Initialize mmc struct and register with mmc framework. */ static int emmc_host_init(void) { struct pl180_mmc_host *host; host = malloc(sizeof(struct pl180_mmc_host)); if (!host) return -ENOMEM; memset(host, 0, sizeof(*host)); host->base = (struct sdi_registers *)CFG_EMMC_BASE; host->pwr_init = SDI_PWR_OPD | SDI_PWR_PWRCTRL_ON; host->clkdiv_init = SDI_CLKCR_CLKDIV_INIT_V2 | SDI_CLKCR_CLKEN | SDI_CLKCR_HWFC_EN; strcpy(host->name, "EMMC"); host->caps = MMC_MODE_8BIT | MMC_MODE_HS | MMC_MODE_HS_52MHz; host->voltages = VOLTAGE_WINDOW_MMC; host->clock_min = ARM_MCLK / (2 + SDI_CLKCR_CLKDIV_INIT_V2); host->clock_max = ARM_MCLK / 2; host->clock_in = ARM_MCLK; host->version2 = 1; return arm_pl180_mmci_init(host); } /* * mmc_host_init - initialize the external mmc controller. * Configure GPIO settings, set initial clock and power for mmc slot. * Initialize mmc struct and register with mmc framework. */ static int mmc_host_init(void) { struct pl180_mmc_host *host; u32 sdi_u32; host = malloc(sizeof(struct pl180_mmc_host)); if (!host) return -ENOMEM; memset(host, 0, sizeof(*host)); host->base = (struct sdi_registers *)CFG_MMC_BASE; sdi_u32 = 0xBF; writel(sdi_u32, &host->base->power); host->pwr_init = 0xBF; host->clkdiv_init = SDI_CLKCR_CLKDIV_INIT_V2 | SDI_CLKCR_CLKEN | SDI_CLKCR_HWFC_EN; strcpy(host->name, "MMC"); host->caps = MMC_MODE_8BIT; host->b_max = 0; host->voltages = VOLTAGE_WINDOW_SD; host->clock_min = ARM_MCLK / (2 + SDI_CLKCR_CLKDIV_INIT_V2); host->clock_max = ARM_MCLK / 2; host->clock_in = ARM_MCLK; host->version2 = 1; return arm_pl180_mmci_init(host); } /* * board_mmc_init - initialize all the mmc/sd host controllers. * Called by generic mmc framework. */ int board_mmc_init(bd_t *bis) { int error; (void) bis; error = emmc_host_init(); if (error) { printf("emmc_host_init() %d\n", error); return -1; } u8500_mmc_power_init(); error = mmc_host_init(); if (error) { printf("mmc_host_init() %d\n", error); return -1; } return 0; } #endif /* CONFIG_MMC */