aboutsummaryrefslogtreecommitdiff
path: root/board/st-ericsson/snowball/snowball.c
diff options
context:
space:
mode:
Diffstat (limited to 'board/st-ericsson/snowball/snowball.c')
-rw-r--r--board/st-ericsson/snowball/snowball.c481
1 files changed, 481 insertions, 0 deletions
diff --git a/board/st-ericsson/snowball/snowball.c b/board/st-ericsson/snowball/snowball.c
new file mode 100644
index 000000000..4379b2cb9
--- /dev/null
+++ b/board/st-ericsson/snowball/snowball.c
@@ -0,0 +1,481 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2009
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+#include <common.h>
+#include <i2c.h>
+#include <asm/types.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/ab8500.h>
+#include <asm/arch/prcmu.h>
+#include <asm/arch/common.h>
+
+#include <db8500_pincfg.h>
+
+#include "db8500_pins.h"
+
+#define NOMADIK_PER4_BASE (0x80150000)
+#define NOMADIK_BACKUPRAM0_BASE (NOMADIK_PER4_BASE + 0x00000)
+#define NOMADIK_BACKUPRAM1_BASE (NOMADIK_PER4_BASE + 0x01000)
+
+
+/*
+ * Memory controller register
+ */
+#define DMC_BASE_ADDR 0x80156000
+#define DMC_CTL_97 (DMC_BASE_ADDR + 0x184)
+
+/*
+ * GPIO pin config common for MOP500/HREF boards
+ */
+pin_cfg_t 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,
+};
+
+pin_cfg_t 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,
+};
+
+#define BOARD_ID_MOP500 0
+#define BOARD_ID_HREF 1
+#define BOARD_ID_HREFV60 2
+#define BOARD_ID_SNOWBALL 3
+int board_id; /* set in probe_href() */
+
+DECLARE_GLOBAL_DATA_PTR;
+#if defined(CONFIG_SHOW_BOOT_PROGRESS)
+void show_boot_progress(int progress)
+{
+ printf("Boot reached stage %d\n", progress);
+}
+#endif
+
+/*
+ * 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)
+{
+ uint32_t unused_cols_rows;
+ unsigned int nrows;
+ unsigned int ncols;
+
+ gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
+ gd->ram_size = PHYS_SDRAM_SIZE_1;
+
+ /*
+ * Assumption: 2 CS active, both CS have same layout.
+ * 15 rows max, 11 cols max (controller spec).
+ * memory chip has 8 banks, I/O width 32 bit.
+ * The correct way would be to read MR#8: I/O width and density,
+ * but this requires locking against the PRCMU firmware.
+ * Simplified approach:
+ * Read number of unused rows and columns from mem controller.
+ * size = nCS x 2^(rows+cols) x nbanks x buswidth_bytes
+ */
+ unused_cols_rows = readl(DMC_CTL_97);
+ nrows = 15 - (unused_cols_rows & 0x07);
+ ncols = 11 - ((unused_cols_rows & 0x0700) >> 8);
+ gd->ram_size = gd->bd->bi_dram[0].size = 2 * (1 << (nrows + ncols)) * 8 * 4;
+
+ return 0;
+}
+
+/*
+ * probe_href - set board_id according to HREF version
+ *
+ * side-effect: configures additional GPIO pins if necessary.
+ */
+static void probe_href(void)
+{
+ uchar byte;
+
+ gd->bd->bi_arch_number = MACH_TYPE_SNOWBALL;
+ board_id = BOARD_ID_SNOWBALL;
+}
+
+#define BATT_OK_SEL1_TH_F_MASK 0xF0
+#define BATT_OK_SEL1_TH_F_2V71 0x70
+/*
+ * board_early_access - for functionality that needs to run before
+ * board_late_init but after board_init and emmc init.
+ */
+int board_early_access(block_dev_desc_t *block_dev)
+{
+ int ret;
+ int battok_regval;
+
+ /* set board_id according to HREF version */
+ probe_href();
+
+ /*
+ * In AB8500 rev2.0, the cut-off voltage threshold is set too low
+ * and the AB will power-off when we start with a drained battery
+ * and a charger connected when the backlight is turned on.
+ * Here we will lower the cut-off voltage threshold before
+ * power consumption goes up
+ */
+ ret = ab8500_read(AB8500_SYS_CTRL2_BLOCK, AB8500_BATT_OK_REG);
+ if (ret < 0)
+ return -EINVAL;
+
+ battok_regval = ret;
+
+ /* Mask and set BattOkSel1ThF */
+ ret = ab8500_write(AB8500_SYS_CTRL2_BLOCK, AB8500_BATT_OK_REG,
+ (battok_regval & ~BATT_OK_SEL1_TH_F_MASK) |
+ BATT_OK_SEL1_TH_F_2V71);
+ if (ret < 0)
+ return -EINVAL;
+
+ return 0;
+}
+
+#ifdef BOARD_LATE_INIT
+#ifdef CONFIG_MMC
+
+#define LDO_VAUX3_ENABLE_MASK 0x3
+#define LDO_VAUX3_ENABLE_VAL 0x1
+#define LDO_VAUX3_SEL_MASK 0xf
+#define LDO_VAUX3_SEL_2V9 0xd
+#define LDO_VAUX3_V2_SEL_MASK 0x7
+#define LDO_VAUX3_V2_SEL_2V91 0x7
+
+static int hrefplus_mmc_power_init(void)
+{
+ int ret;
+ int voltage_regval;
+ int enable_regval;
+ int ab8500_revision;
+
+ if (!cpu_is_u8500v11() && !cpu_is_u8500v2())
+ return 0;
+
+ /* Get AB8500 revision */
+ ret = ab8500_read(AB8500_MISC, AB8500_REV_REG);
+ if (ret < 0)
+ goto out;
+
+ ab8500_revision = ret;
+
+ /*
+ * On v1.1 HREF boards (HREF+) and v2 boards, Vaux3 needs to be
+ * enabled for the SD card to work. This is done by enabling
+ * the regulators in the AB8500 via PRCMU I2C transactions.
+ *
+ * This code is derived from the handling of AB8500_LDO_VAUX3 in
+ * ab8500_ldo_enable() and ab8500_ldo_disable() in Linux.
+ *
+ * Turn off and delay is required to have it work across soft reboots.
+ */
+
+ /* Turn off (read-modify-write) */
+ ret = ab8500_read(AB8500_REGU_CTRL2, AB8500_REGU_VRF1VAUX3_REGU_REG);
+ if (ret < 0)
+ goto out;
+
+ enable_regval = ret;
+
+ ret = ab8500_write(AB8500_REGU_CTRL2, AB8500_REGU_VRF1VAUX3_REGU_REG,
+ enable_regval & ~LDO_VAUX3_ENABLE_MASK);
+ if (ret < 0)
+ goto out;
+
+ /* Delay */
+ udelay(10 * 1000);
+
+ /* Set the voltage to 2.91 V or 2.9 V without overriding VRF1 value */
+ ret = ab8500_read(AB8500_REGU_CTRL2, AB8500_REGU_VRF1VAUX3_SEL_REG);
+ if (ret < 0)
+ goto out;
+
+ voltage_regval = ret;
+
+ if (ab8500_revision < 0x20) {
+ voltage_regval &= ~LDO_VAUX3_SEL_MASK;
+ voltage_regval |= LDO_VAUX3_SEL_2V9;
+ } else {
+ voltage_regval &= ~LDO_VAUX3_V2_SEL_MASK;
+ voltage_regval |= LDO_VAUX3_V2_SEL_2V91;
+ }
+
+ ret = ab8500_write(AB8500_REGU_CTRL2, AB8500_REGU_VRF1VAUX3_SEL_REG,
+ voltage_regval);
+ if (ret < 0)
+ goto out;
+
+ /* Turn on the supply */
+ enable_regval &= ~LDO_VAUX3_ENABLE_MASK;
+ enable_regval |= LDO_VAUX3_ENABLE_VAL;
+
+ ret = ab8500_write(AB8500_REGU_CTRL2, AB8500_REGU_VRF1VAUX3_REGU_REG,
+ enable_regval);
+
+out:
+ return ret;
+}
+#endif
+
+static int snowball_raise_ab8500_gpio26(void)
+{
+ int ret;
+
+ /* For snowball (aka "minikit") we need to raise AB8500's GPIO26 */
+ ret = ab8500_read(AB8500_MISC, AB8500_GPIO_DIR4_REG);
+ if (ret < 0) {
+ printf("error at %s:%i\n", __func__, __LINE__);
+ goto out;
+ }
+
+ ret |= 0x2;
+ ret = ab8500_write(AB8500_MISC, AB8500_GPIO_DIR4_REG, ret);
+ if (ret < 0) {
+ printf("error at %s:%i\n", __func__, __LINE__);
+ goto out;
+ }
+
+ ret = ab8500_read(AB8500_MISC, AB8500_GPIO_OUT4_REG);
+ if (ret < 0) {
+ printf("error at %s:%i\n", __func__, __LINE__);
+ goto out;
+ }
+
+ ret |= 0x2;
+ ret = ab8500_write(AB8500_MISC, AB8500_GPIO_OUT4_REG, ret);
+ if (ret < 0) {
+ printf("error at %s:%i\n", __func__, __LINE__);
+ }
+
+out:
+ return ret;
+}
+
+
+static int snowball_raise_ab8500_gpio16(void)
+{
+ int ret;
+
+ /* selection */
+ ret = ab8500_read(AB8500_MISC, AB8500_GPIO_SEL2_REG);
+ if (ret < 0) {
+ printf("error at %s:%i\n", __func__, __LINE__);
+ goto out;
+ }
+
+ ret |= 0x80;
+ ret = ab8500_write(AB8500_MISC, AB8500_GPIO_SEL2_REG, ret);
+ if (ret < 0) {
+ printf("error at %s:%i\n", __func__, __LINE__);
+ goto out;
+ }
+
+ /* direction */
+ ret = ab8500_read(AB8500_MISC, AB8500_GPIO_DIR2_REG);
+ if (ret < 0) {
+ printf("error at %s:%i\n", __func__, __LINE__);
+ goto out;
+ }
+
+ ret |= 0x80;
+ ret = ab8500_write(AB8500_MISC, AB8500_GPIO_DIR2_REG, ret);
+ if (ret < 0) {
+ printf("error at %s:%i\n", __func__, __LINE__);
+ goto out;
+ }
+
+ /* out */
+ ret = ab8500_read(AB8500_MISC, AB8500_GPIO_OUT2_REG);
+ if (ret < 0) {
+ printf("error at %s:%i\n", __func__, __LINE__);
+ goto out;
+ }
+
+ ret |= 0x80;
+ ret = ab8500_write(AB8500_MISC, AB8500_GPIO_OUT2_REG, ret);
+ if (ret < 0) {
+ printf("error at %s:%i\n", __func__, __LINE__);
+ goto out;
+ }
+
+out:
+ return ret;
+}
+
+
+/*
+ * called after all initialisation were done, but before the generic
+ * mmc_initialize().
+ */
+int board_late_init(void)
+{
+ uchar byte;
+#ifdef CONFIG_MMC
+ uchar byte_array[] = {0x06, 0x06};
+#endif
+ char strbuf[80];
+
+ /*
+ * The board_id environment variable is needed for the Linux bootargs.
+ */
+ if (board_id == 0)
+ setenv("board_id", "0");
+ else
+ setenv("board_id", "1");
+
+ if (u8500_is_snowball()) {
+ /* enable 3V3 for LAN controller */
+ if(snowball_raise_ab8500_gpio26() >= 0) {
+
+ /* Turn on FSMC device */
+ writel(0x1, 0x8000f000);
+ writel(0x1, 0x8000f008);
+
+ /* setup FSMC for LAN controler */
+ writel(0x305b, 0x80000000);
+ /* the default is too slow */
+ writel(0x01010110, 0x80000004);
+ }
+
+ /* enable 3V6 for GBF chip */
+ snowball_raise_ab8500_gpio16();
+ }
+
+#ifdef CONFIG_MMC
+ hrefplus_mmc_power_init();
+
+ /*
+ * config extended GPIO pins for level shifter and
+ * SDMMC_ENABLE
+ */
+ /* HREF V60 and later */
+ /* enable SDMMC */
+ db8500_gpio_set_output(GPIO169_GPIO, 1);
+#endif /* CONFIG_MMC */
+
+ return (0);
+}
+#endif /* BOARD_LATE_INIT */
+