u-boot-brain/board/genesi/mx51_efikamx/efikamx.c
Matt Sealey fdd63c9352 efikamx: update to Efika MX Smarttop and Smartbook boards
This is a rework of a previously submitted patchset and bundles the
main board support and USB support into a single commit.

It requires the patch "mx5: add iomux-mx51.h include"

* Use iomux-mx51.h include to simplify board configuration.
* Simplify LED support (remove efikamx_toggle_led, change lit LEDs).
* Simplify MMC support for CD and WP pin differences.
* Fix broken CPU voltage setting - comment said 1.1V but the code set to
  1.2V. It should never have been set to 1.2V even on i.MX51 TO2 and
  all available Linux kernels would drop the voltage to 1.1V anyway and
  work reliably. This should lower power consumption during the boot
  process.
* Function renames for readability.
* Some board identification string changes to match actual product names.
* Passes checkpatch (v2)

Signed-off-by: Matt Sealey <matt@genesi-usa.com>
Cc: Stefano Babic <sbabic@denx.de>
2012-09-01 14:58:30 +02:00

513 lines
13 KiB
C

/*
* Copyright (C) 2009 Freescale Semiconductor, Inc.
* Copyright (C) 2010 Marek Vasut <marek.vasut@gmail.com>
* Copyright (C) 2009-2012 Genesi USA, Inc.
*
* 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 <common.h>
#include <asm/io.h>
#include <asm/arch/iomux-mx51.h>
#include <asm/gpio.h>
#include <asm/errno.h>
#include <asm/arch/sys_proto.h>
#include <asm/arch/crm_regs.h>
#include <i2c.h>
#include <mmc.h>
#include <fsl_esdhc.h>
#include <pmic.h>
#include <fsl_pmic.h>
#include <mc13892.h>
DECLARE_GLOBAL_DATA_PTR;
/*
* Compile-time error checking
*/
#ifndef CONFIG_MXC_SPI
#error "CONFIG_MXC_SPI not set, this is essential for board's operation!"
#endif
/*
* Board revisions
*
* Note that we get these revisions here for convenience, but we only set
* up for the production model Smarttop (1.3) and Smartbook (2.0).
*
*/
#define EFIKAMX_BOARD_REV_11 0x1
#define EFIKAMX_BOARD_REV_12 0x2
#define EFIKAMX_BOARD_REV_13 0x3
#define EFIKAMX_BOARD_REV_14 0x4
#define EFIKASB_BOARD_REV_13 0x1
#define EFIKASB_BOARD_REV_20 0x2
/*
* Board identification
*/
static u32 get_mx_rev(void)
{
u32 rev = 0;
/*
* Retrieve board ID:
*
* gpio: 16 17 11
* ==============
* r1.1: 1+ 1 1
* r1.2: 1 1 0
* r1.3: 1 0 1
* r1.4: 1 0 0
*
* + note: r1.1 does not strap this pin properly so it needs to
* be hacked or ignored.
*/
/* set to 1 in order to get correct value on board rev 1.1 */
gpio_direction_output(GPIO_NUMBER(3, 16), 1);
gpio_direction_input(GPIO_NUMBER(3, 11));
gpio_direction_input(GPIO_NUMBER(3, 16));
gpio_direction_input(GPIO_NUMBER(3, 17));
rev |= (!!gpio_get_value(GPIO_NUMBER(3, 16))) << 0;
rev |= (!!gpio_get_value(GPIO_NUMBER(3, 17))) << 1;
rev |= (!!gpio_get_value(GPIO_NUMBER(3, 11))) << 2;
return (~rev & 0x7) + 1;
}
static iomux_v3_cfg_t efikasb_revision_pads[] = {
MX51_PAD_EIM_CS3__GPIO2_28,
MX51_PAD_EIM_CS4__GPIO2_29,
};
static inline u32 get_sb_rev(void)
{
u32 rev = 0;
imx_iomux_v3_setup_multiple_pads(efikasb_revision_pads,
ARRAY_SIZE(efikasb_revision_pads));
gpio_direction_input(GPIO_NUMBER(2, 28));
gpio_direction_input(GPIO_NUMBER(2, 29));
rev |= (!!gpio_get_value(GPIO_NUMBER(2, 28))) << 0;
rev |= (!!gpio_get_value(GPIO_NUMBER(2, 29))) << 1;
return rev;
}
inline uint32_t get_efikamx_rev(void)
{
if (machine_is_efikamx())
return get_mx_rev();
else if (machine_is_efikasb())
return get_sb_rev();
}
u32 get_board_rev(void)
{
return get_cpu_rev() | (get_efikamx_rev() << 8);
}
/*
* DRAM initialization
*/
int dram_init(void)
{
/* dram_init must store complete ramsize in gd->ram_size */
gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE,
PHYS_SDRAM_1_SIZE);
return 0;
}
/*
* UART configuration
*/
static iomux_v3_cfg_t efikamx_uart_pads[] = {
MX51_PAD_UART1_RXD__UART1_RXD,
MX51_PAD_UART1_TXD__UART1_TXD,
MX51_PAD_UART1_RTS__UART1_RTS,
MX51_PAD_UART1_CTS__UART1_CTS,
};
/*
* SPI configuration
*/
static iomux_v3_cfg_t efikamx_spi_pads[] = {
MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
MX51_PAD_CSPI1_SS0__GPIO4_24,
MX51_PAD_CSPI1_SS1__GPIO4_25,
MX51_PAD_GPIO1_6__GPIO1_6,
};
#define EFIKAMX_SPI_SS0 GPIO_NUMBER(4, 24)
#define EFIKAMX_SPI_SS1 GPIO_NUMBER(4, 25)
#define EFIKAMX_PMIC_IRQ GPIO_NUMBER(1, 6)
/*
* PMIC configuration
*/
#ifdef CONFIG_MXC_SPI
static void power_init(void)
{
unsigned int val;
struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)MXC_CCM_BASE;
struct pmic *p;
pmic_init();
p = get_pmic();
/* Write needed to Power Gate 2 register */
pmic_reg_read(p, REG_POWER_MISC, &val);
val &= ~PWGT2SPIEN;
pmic_reg_write(p, REG_POWER_MISC, val);
/* Externally powered */
pmic_reg_read(p, REG_CHARGE, &val);
val |= ICHRG0 | ICHRG1 | ICHRG2 | ICHRG3 | CHGAUTOB;
pmic_reg_write(p, REG_CHARGE, val);
/* power up the system first */
pmic_reg_write(p, REG_POWER_MISC, PWUP);
/* Set core voltage to 1.1V */
pmic_reg_read(p, REG_SW_0, &val);
val = (val & ~SWx_VOLT_MASK) | SWx_1_100V;
pmic_reg_write(p, REG_SW_0, val);
/* Setup VCC (SW2) to 1.25 */
pmic_reg_read(p, REG_SW_1, &val);
val = (val & ~SWx_VOLT_MASK) | SWx_1_250V;
pmic_reg_write(p, REG_SW_1, val);
/* Setup 1V2_DIG1 (SW3) to 1.25 */
pmic_reg_read(p, REG_SW_2, &val);
val = (val & ~SWx_VOLT_MASK) | SWx_1_250V;
pmic_reg_write(p, REG_SW_2, val);
udelay(50);
/* Raise the core frequency to 800MHz */
writel(0x0, &mxc_ccm->cacrr);
/* Set switchers in Auto in NORMAL mode & STANDBY mode */
/* Setup the switcher mode for SW1 & SW2*/
pmic_reg_read(p, REG_SW_4, &val);
val = (val & ~((SWMODE_MASK << SWMODE1_SHIFT) |
(SWMODE_MASK << SWMODE2_SHIFT)));
val |= (SWMODE_AUTO_AUTO << SWMODE1_SHIFT) |
(SWMODE_AUTO_AUTO << SWMODE2_SHIFT);
pmic_reg_write(p, REG_SW_4, val);
/* Setup the switcher mode for SW3 & SW4 */
pmic_reg_read(p, REG_SW_5, &val);
val = (val & ~((SWMODE_MASK << SWMODE3_SHIFT) |
(SWMODE_MASK << SWMODE4_SHIFT)));
val |= (SWMODE_AUTO_AUTO << SWMODE3_SHIFT) |
(SWMODE_AUTO_AUTO << SWMODE4_SHIFT);
pmic_reg_write(p, REG_SW_5, val);
/* Set VDIG to 1.8V, VGEN3 to 1.8V, VCAM to 2.6V */
pmic_reg_read(p, REG_SETTING_0, &val);
val &= ~(VCAM_MASK | VGEN3_MASK | VDIG_MASK);
val |= VDIG_1_8 | VGEN3_1_8 | VCAM_2_6;
pmic_reg_write(p, REG_SETTING_0, val);
/* Set VVIDEO to 2.775V, VAUDIO to 3V, VSD to 3.15V */
pmic_reg_read(p, REG_SETTING_1, &val);
val &= ~(VVIDEO_MASK | VSD_MASK | VAUDIO_MASK);
val |= VSD_3_15 | VAUDIO_3_0 | VVIDEO_2_775 | VGEN1_1_2 | VGEN2_3_15;
pmic_reg_write(p, REG_SETTING_1, val);
/* Enable VGEN1, VGEN2, VDIG, VPLL */
pmic_reg_read(p, REG_MODE_0, &val);
val |= VGEN1EN | VDIGEN | VGEN2EN | VPLLEN;
pmic_reg_write(p, REG_MODE_0, val);
/* Configure VGEN3 and VCAM regulators to use external PNP */
val = VGEN3CONFIG | VCAMCONFIG;
pmic_reg_write(p, REG_MODE_1, val);
udelay(200);
/* Enable VGEN3, VCAM, VAUDIO, VVIDEO, VSD regulators */
val = VGEN3EN | VGEN3CONFIG | VCAMEN | VCAMCONFIG |
VVIDEOEN | VAUDIOEN | VSDEN;
pmic_reg_write(p, REG_MODE_1, val);
pmic_reg_read(p, REG_POWER_CTL2, &val);
val |= WDIRESET;
pmic_reg_write(p, REG_POWER_CTL2, val);
udelay(2500);
}
#else
static inline void power_init(void) { }
#endif
/*
* MMC configuration
*/
#ifdef CONFIG_FSL_ESDHC
struct fsl_esdhc_cfg esdhc_cfg[2] = {
{MMC_SDHC1_BASE_ADDR, 1},
{MMC_SDHC2_BASE_ADDR, 1},
};
static iomux_v3_cfg_t efikamx_sdhc1_pads[] = {
MX51_PAD_SD1_CMD__SD1_CMD,
MX51_PAD_SD1_CLK__SD1_CLK,
MX51_PAD_SD1_DATA0__SD1_DATA0,
MX51_PAD_SD1_DATA1__SD1_DATA1,
MX51_PAD_SD1_DATA2__SD1_DATA2,
MX51_PAD_SD1_DATA3__SD1_DATA3,
MX51_PAD_GPIO1_1__SD1_WP,
};
#define EFIKAMX_SDHC1_WP GPIO_NUMBER(1, 1)
static iomux_v3_cfg_t efikamx_sdhc1_cd_pads[] = {
MX51_PAD_GPIO1_0__SD1_CD,
MX51_PAD_EIM_CS2__SD1_CD,
};
#define EFIKAMX_SDHC1_CD GPIO_NUMBER(1, 0)
#define EFIKASB_SDHC1_CD GPIO_NUMBER(2, 27)
static iomux_v3_cfg_t efikasb_sdhc2_pads[] = {
MX51_PAD_SD2_CMD__SD2_CMD,
MX51_PAD_SD2_CLK__SD2_CLK,
MX51_PAD_SD2_DATA0__SD2_DATA0,
MX51_PAD_SD2_DATA1__SD2_DATA1,
MX51_PAD_SD2_DATA2__SD2_DATA2,
MX51_PAD_SD2_DATA3__SD2_DATA3,
MX51_PAD_GPIO1_7__SD2_WP,
MX51_PAD_GPIO1_8__SD2_CD,
};
#define EFIKASB_SDHC2_CD GPIO_NUMBER(1, 8)
#define EFIKASB_SDHC2_WP GPIO_NUMBER(1, 7)
static inline uint32_t efikamx_mmc_getcd(u32 base)
{
if (base == MMC_SDHC1_BASE_ADDR)
if (machine_is_efikamx())
return EFIKAMX_SDHC1_CD;
else
return EFIKASB_SDHC1_CD;
else
return EFIKASB_SDHC2_CD;
}
int board_mmc_getcd(struct mmc *mmc)
{
struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
uint32_t cd = efikamx_mmc_getcd(cfg->esdhc_base);
int ret = !gpio_get_value(cd);
return ret;
}
int board_mmc_init(bd_t *bis)
{
int ret;
/*
* All Efika MX boards use eSDHC1 with a common write-protect GPIO
*/
imx_iomux_v3_setup_multiple_pads(efikamx_sdhc1_pads,
ARRAY_SIZE(efikamx_sdhc1_pads));
gpio_direction_input(EFIKAMX_SDHC1_WP);
/*
* Smartbook and Smarttop differ on the location of eSDHC1
* carrier-detect GPIO
*/
if (machine_is_efikamx()) {
imx_iomux_v3_setup_pad(efikamx_sdhc1_cd_pads[0]);
gpio_direction_input(EFIKAMX_SDHC1_CD);
} else if (machine_is_efikasb()) {
imx_iomux_v3_setup_pad(efikamx_sdhc1_cd_pads[1]);
gpio_direction_input(EFIKASB_SDHC1_CD);
}
ret = fsl_esdhc_initialize(bis, &esdhc_cfg[0]);
if (machine_is_efikasb()) {
imx_iomux_v3_setup_multiple_pads(efikasb_sdhc2_pads,
ARRAY_SIZE(efikasb_sdhc2_pads));
gpio_direction_input(EFIKASB_SDHC2_CD);
gpio_direction_input(EFIKASB_SDHC2_WP);
if (!ret)
ret = fsl_esdhc_initialize(bis, &esdhc_cfg[1]);
}
return ret;
}
#endif
/*
* PATA
*/
static iomux_v3_cfg_t efikamx_pata_pads[] = {
MX51_PAD_NANDF_WE_B__PATA_DIOW,
MX51_PAD_NANDF_RE_B__PATA_DIOR,
MX51_PAD_NANDF_ALE__PATA_BUFFER_EN,
MX51_PAD_NANDF_CLE__PATA_RESET_B,
MX51_PAD_NANDF_WP_B__PATA_DMACK,
MX51_PAD_NANDF_RB0__PATA_DMARQ,
MX51_PAD_NANDF_RB1__PATA_IORDY,
MX51_PAD_GPIO_NAND__PATA_INTRQ,
MX51_PAD_NANDF_CS2__PATA_CS_0,
MX51_PAD_NANDF_CS3__PATA_CS_1,
MX51_PAD_NANDF_CS4__PATA_DA_0,
MX51_PAD_NANDF_CS5__PATA_DA_1,
MX51_PAD_NANDF_CS6__PATA_DA_2,
MX51_PAD_NANDF_D15__PATA_DATA15,
MX51_PAD_NANDF_D14__PATA_DATA14,
MX51_PAD_NANDF_D13__PATA_DATA13,
MX51_PAD_NANDF_D12__PATA_DATA12,
MX51_PAD_NANDF_D11__PATA_DATA11,
MX51_PAD_NANDF_D10__PATA_DATA10,
MX51_PAD_NANDF_D9__PATA_DATA9,
MX51_PAD_NANDF_D8__PATA_DATA8,
MX51_PAD_NANDF_D7__PATA_DATA7,
MX51_PAD_NANDF_D6__PATA_DATA6,
MX51_PAD_NANDF_D5__PATA_DATA5,
MX51_PAD_NANDF_D4__PATA_DATA4,
MX51_PAD_NANDF_D3__PATA_DATA3,
MX51_PAD_NANDF_D2__PATA_DATA2,
MX51_PAD_NANDF_D1__PATA_DATA1,
MX51_PAD_NANDF_D0__PATA_DATA0,
};
/*
* EHCI USB
*/
#ifdef CONFIG_CMD_USB
extern void setup_iomux_usb(void);
#else
static inline void setup_iomux_usb(void) { }
#endif
/*
* LED configuration
*
* Smarttop LED pad config is done in the DCD
*
*/
#define EFIKAMX_LED_BLUE GPIO_NUMBER(3, 13)
#define EFIKAMX_LED_GREEN GPIO_NUMBER(3, 14)
#define EFIKAMX_LED_RED GPIO_NUMBER(3, 15)
static iomux_v3_cfg_t efikasb_led_pads[] = {
MX51_PAD_GPIO1_3__GPIO1_3,
MX51_PAD_EIM_CS0__GPIO2_25,
};
#define EFIKASB_CAPSLOCK_LED GPIO_NUMBER(2, 25)
#define EFIKASB_MESSAGE_LED GPIO_NUMBER(1, 3) /* Note: active low */
/*
* Board initialization
*/
int board_early_init_f(void)
{
if (machine_is_efikasb()) {
imx_iomux_v3_setup_multiple_pads(efikasb_led_pads,
ARRAY_SIZE(efikasb_led_pads));
gpio_direction_output(EFIKASB_CAPSLOCK_LED, 0);
gpio_direction_output(EFIKASB_MESSAGE_LED, 1);
} else if (machine_is_efikamx()) {
/*
* Set up GPIO directions for LEDs.
* IOMUX has been done in the DCD already.
* Turn the red LED on for pre-relocation code.
*/
gpio_direction_output(EFIKAMX_LED_BLUE, 0);
gpio_direction_output(EFIKAMX_LED_GREEN, 0);
gpio_direction_output(EFIKAMX_LED_RED, 1);
}
/*
* Both these pad configurations for UART and SPI are kind of redundant
* since they are the Power-On Defaults for the i.MX51. But, it seems we
* should make absolutely sure that they are set up correctly.
*/
imx_iomux_v3_setup_multiple_pads(efikamx_uart_pads,
ARRAY_SIZE(efikamx_uart_pads));
imx_iomux_v3_setup_multiple_pads(efikamx_spi_pads,
ARRAY_SIZE(efikamx_spi_pads));
/* not technically required for U-Boot operation but do it anyway. */
gpio_direction_input(EFIKAMX_PMIC_IRQ);
/* Deselect both CS for now, otherwise NOR doesn't probe properly. */
gpio_direction_output(EFIKAMX_SPI_SS0, 0);
gpio_direction_output(EFIKAMX_SPI_SS1, 1);
return 0;
}
int board_init(void)
{
gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
return 0;
}
int board_late_init(void)
{
if (machine_is_efikamx()) {
/*
* Set up Blue LED for "In U-Boot" status.
* We're all relocated and ready to U-Boot!
*/
gpio_set_value(EFIKAMX_LED_RED, 0);
gpio_set_value(EFIKAMX_LED_GREEN, 0);
gpio_set_value(EFIKAMX_LED_BLUE, 1);
}
power_init();
imx_iomux_v3_setup_multiple_pads(efikamx_pata_pads,
ARRAY_SIZE(efikamx_pata_pads));
setup_iomux_usb();
if (machine_is_efikasb())
setenv("preboot", "usb reset ; setenv stdin usbkbd\0");
return 0;
}
int checkboard(void)
{
u32 rev = get_efikamx_rev();
printf("Board: Genesi Efika MX ");
if (machine_is_efikamx())
printf("Smarttop (1.%i)\n", rev & 0xf);
else if (machine_is_efikasb())
printf("Smartbook\n");
return 0;
}