mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-18 18:59:44 +00:00
e895a4b06f
This function can fail if the device tree runs out of space. Rather than silently booting with an incomplete device tree, allow the failure to be detected. Unfortunately this involves changing a lot of places in the code. I have not changed behvaiour to return an error where one is not currently returned, to avoid unexpected breakage. Eventually it would be nice to allow boards to register functions to be called to update the device tree. This would avoid all the many functions to do this. However it's not clear yet if this should be done using driver model or with a linker list. This work is left for later. Signed-off-by: Simon Glass <sjg@chromium.org> Acked-by: Anatolij Gustschin <agust@denx.de>
272 lines
6.6 KiB
C
272 lines
6.6 KiB
C
/*
|
|
* Copyright (C) 2012 Freescale Semiconductor, Inc.
|
|
* Author: Fabio Estevam <fabio.estevam@freescale.com>
|
|
*
|
|
* Copyright (C) 2013, 2014 TQ Systems (ported SabreSD to TQMa6x)
|
|
* Author: Markus Niebel <markus.niebel@tq-group.com>
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
*/
|
|
|
|
#include <asm/arch/clock.h>
|
|
#include <asm/arch/mx6-pins.h>
|
|
#include <asm/arch/imx-regs.h>
|
|
#include <asm/arch/iomux.h>
|
|
#include <asm/arch/sys_proto.h>
|
|
#include <asm/errno.h>
|
|
#include <asm/gpio.h>
|
|
#include <asm/io.h>
|
|
#include <asm/imx-common/mxc_i2c.h>
|
|
#include <common.h>
|
|
#include <fsl_esdhc.h>
|
|
#include <libfdt.h>
|
|
#include <i2c.h>
|
|
#include <mmc.h>
|
|
#include <power/pfuze100_pmic.h>
|
|
#include <power/pmic.h>
|
|
|
|
#include "tqma6_bb.h"
|
|
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
#define USDHC_CLK_PAD_CTRL (PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_LOW | \
|
|
PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS)
|
|
|
|
#define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_LOW | \
|
|
PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS)
|
|
|
|
#define GPIO_OUT_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_LOW | \
|
|
PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
|
|
|
|
#define GPIO_IN_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_LOW | \
|
|
PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
|
|
|
|
#define SPI_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \
|
|
PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS)
|
|
|
|
#define I2C_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \
|
|
PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \
|
|
PAD_CTL_ODE | PAD_CTL_SRE_FAST)
|
|
|
|
int dram_init(void)
|
|
{
|
|
gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const uint16_t tqma6_emmc_dsr = 0x0100;
|
|
|
|
/* eMMC on USDHCI3 always present */
|
|
static iomux_v3_cfg_t const tqma6_usdhc3_pads[] = {
|
|
NEW_PAD_CTRL(MX6_PAD_SD3_CLK__SD3_CLK, USDHC_PAD_CTRL),
|
|
NEW_PAD_CTRL(MX6_PAD_SD3_CMD__SD3_CMD, USDHC_PAD_CTRL),
|
|
NEW_PAD_CTRL(MX6_PAD_SD3_DAT0__SD3_DATA0, USDHC_PAD_CTRL),
|
|
NEW_PAD_CTRL(MX6_PAD_SD3_DAT1__SD3_DATA1, USDHC_PAD_CTRL),
|
|
NEW_PAD_CTRL(MX6_PAD_SD3_DAT2__SD3_DATA2, USDHC_PAD_CTRL),
|
|
NEW_PAD_CTRL(MX6_PAD_SD3_DAT3__SD3_DATA3, USDHC_PAD_CTRL),
|
|
NEW_PAD_CTRL(MX6_PAD_SD3_DAT4__SD3_DATA4, USDHC_PAD_CTRL),
|
|
NEW_PAD_CTRL(MX6_PAD_SD3_DAT5__SD3_DATA5, USDHC_PAD_CTRL),
|
|
NEW_PAD_CTRL(MX6_PAD_SD3_DAT6__SD3_DATA6, USDHC_PAD_CTRL),
|
|
NEW_PAD_CTRL(MX6_PAD_SD3_DAT7__SD3_DATA7, USDHC_PAD_CTRL),
|
|
/* eMMC reset */
|
|
NEW_PAD_CTRL(MX6_PAD_SD3_RST__SD3_RESET, GPIO_OUT_PAD_CTRL),
|
|
};
|
|
|
|
/*
|
|
* According to board_mmc_init() the following map is done:
|
|
* (U-boot device node) (Physical Port)
|
|
* mmc0 eMMC (SD3) on TQMa6
|
|
* mmc1 .. n optional slots used on baseboard
|
|
*/
|
|
struct fsl_esdhc_cfg tqma6_usdhc_cfg = {
|
|
.esdhc_base = USDHC3_BASE_ADDR,
|
|
.max_bus_width = 8,
|
|
};
|
|
|
|
int board_mmc_getcd(struct mmc *mmc)
|
|
{
|
|
struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
|
|
int ret = 0;
|
|
|
|
if (cfg->esdhc_base == USDHC3_BASE_ADDR)
|
|
/* eMMC/uSDHC3 is always present */
|
|
ret = 1;
|
|
else
|
|
ret = tqma6_bb_board_mmc_getcd(mmc);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int board_mmc_getwp(struct mmc *mmc)
|
|
{
|
|
struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
|
|
int ret = 0;
|
|
|
|
if (cfg->esdhc_base == USDHC3_BASE_ADDR)
|
|
/* eMMC/uSDHC3 is always present */
|
|
ret = 0;
|
|
else
|
|
ret = tqma6_bb_board_mmc_getwp(mmc);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int board_mmc_init(bd_t *bis)
|
|
{
|
|
imx_iomux_v3_setup_multiple_pads(tqma6_usdhc3_pads,
|
|
ARRAY_SIZE(tqma6_usdhc3_pads));
|
|
tqma6_usdhc_cfg.sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
|
|
if (fsl_esdhc_initialize(bis, &tqma6_usdhc_cfg)) {
|
|
puts("Warning: failed to initialize eMMC dev\n");
|
|
} else {
|
|
struct mmc *mmc = find_mmc_device(0);
|
|
if (mmc)
|
|
mmc_set_dsr(mmc, tqma6_emmc_dsr);
|
|
}
|
|
|
|
tqma6_bb_board_mmc_init(bis);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static iomux_v3_cfg_t const tqma6_ecspi1_pads[] = {
|
|
/* SS1 */
|
|
NEW_PAD_CTRL(MX6_PAD_EIM_D19__GPIO3_IO19, SPI_PAD_CTRL),
|
|
NEW_PAD_CTRL(MX6_PAD_EIM_D16__ECSPI1_SCLK, SPI_PAD_CTRL),
|
|
NEW_PAD_CTRL(MX6_PAD_EIM_D17__ECSPI1_MISO, SPI_PAD_CTRL),
|
|
NEW_PAD_CTRL(MX6_PAD_EIM_D18__ECSPI1_MOSI, SPI_PAD_CTRL),
|
|
};
|
|
|
|
#define TQMA6_SF_CS_GPIO IMX_GPIO_NR(3, 19)
|
|
|
|
static unsigned const tqma6_ecspi1_cs[] = {
|
|
TQMA6_SF_CS_GPIO,
|
|
};
|
|
|
|
static void tqma6_iomuxc_spi(void)
|
|
{
|
|
unsigned i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(tqma6_ecspi1_cs); ++i)
|
|
gpio_direction_output(tqma6_ecspi1_cs[i], 1);
|
|
imx_iomux_v3_setup_multiple_pads(tqma6_ecspi1_pads,
|
|
ARRAY_SIZE(tqma6_ecspi1_pads));
|
|
}
|
|
|
|
int board_spi_cs_gpio(unsigned bus, unsigned cs)
|
|
{
|
|
return ((bus == CONFIG_SF_DEFAULT_BUS) &&
|
|
(cs == CONFIG_SF_DEFAULT_CS)) ? TQMA6_SF_CS_GPIO : -1;
|
|
}
|
|
|
|
static struct i2c_pads_info tqma6_i2c3_pads = {
|
|
/* I2C3: on board LM75, M24C64, */
|
|
.scl = {
|
|
.i2c_mode = NEW_PAD_CTRL(MX6_PAD_GPIO_5__I2C3_SCL,
|
|
I2C_PAD_CTRL),
|
|
.gpio_mode = NEW_PAD_CTRL(MX6_PAD_GPIO_5__GPIO1_IO05,
|
|
I2C_PAD_CTRL),
|
|
.gp = IMX_GPIO_NR(1, 5)
|
|
},
|
|
.sda = {
|
|
.i2c_mode = NEW_PAD_CTRL(MX6_PAD_GPIO_6__I2C3_SDA,
|
|
I2C_PAD_CTRL),
|
|
.gpio_mode = NEW_PAD_CTRL(MX6_PAD_GPIO_6__GPIO1_IO06,
|
|
I2C_PAD_CTRL),
|
|
.gp = IMX_GPIO_NR(1, 6)
|
|
}
|
|
};
|
|
|
|
static void tqma6_setup_i2c(void)
|
|
{
|
|
/* use logical index for bus, e.g. I2C1 -> 0 */
|
|
setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &tqma6_i2c3_pads);
|
|
}
|
|
|
|
int board_early_init_f(void)
|
|
{
|
|
return tqma6_bb_board_early_init_f();
|
|
}
|
|
|
|
int board_init(void)
|
|
{
|
|
/* address of boot parameters */
|
|
gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
|
|
|
|
tqma6_iomuxc_spi();
|
|
tqma6_setup_i2c();
|
|
|
|
tqma6_bb_board_init();
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const char *tqma6_get_boardname(void)
|
|
{
|
|
u32 cpurev = get_cpu_rev();
|
|
|
|
switch ((cpurev & 0xFF000) >> 12) {
|
|
case MXC_CPU_MX6SOLO:
|
|
return "TQMa6S";
|
|
break;
|
|
case MXC_CPU_MX6DL:
|
|
return "TQMa6DL";
|
|
break;
|
|
case MXC_CPU_MX6D:
|
|
return "TQMa6D";
|
|
break;
|
|
case MXC_CPU_MX6Q:
|
|
return "TQMa6Q";
|
|
break;
|
|
default:
|
|
return "??";
|
|
};
|
|
}
|
|
|
|
int board_late_init(void)
|
|
{
|
|
struct pmic *p;
|
|
u32 reg;
|
|
|
|
setenv("board_name", tqma6_get_boardname());
|
|
|
|
/*
|
|
* configure PFUZE100 PMIC:
|
|
* TODO: should go to power_init_board if bus switching is
|
|
* fixed in generic power code
|
|
*/
|
|
power_pfuze100_init(TQMA6_PFUZE100_I2C_BUS);
|
|
p = pmic_get("PFUZE100");
|
|
if (p && !pmic_probe(p)) {
|
|
pmic_reg_read(p, PFUZE100_DEVICEID, ®);
|
|
printf("PMIC: PFUZE100 ID=0x%02x\n", reg);
|
|
}
|
|
|
|
tqma6_bb_board_late_init();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int checkboard(void)
|
|
{
|
|
printf("Board: %s on a %s\n", tqma6_get_boardname(),
|
|
tqma6_bb_get_boardname());
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Device Tree Support
|
|
*/
|
|
#if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT)
|
|
int ft_board_setup(void *blob, bd_t *bd)
|
|
{
|
|
/* bring in eMMC dsr settings */
|
|
do_fixup_by_path_u32(blob,
|
|
"/soc/aips-bus@02100000/usdhc@02198000",
|
|
"dsr", tqma6_emmc_dsr, 2);
|
|
tqma6_bb_ft_board_setup(blob, bd);
|
|
|
|
return 0;
|
|
}
|
|
#endif /* defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT) */
|