uboot/board/tqc/tqma6/tqma6.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2012 Freescale Semiconductor, Inc.
   3 * Author: Fabio Estevam <fabio.estevam@freescale.com>
   4 *
   5 * Copyright (C) 2013, 2014 TQ Systems (ported SabreSD to TQMa6x)
   6 * Author: Markus Niebel <markus.niebel@tq-group.com>
   7 *
   8 * SPDX-License-Identifier:     GPL-2.0+
   9 */
  10
  11#include <asm/arch/clock.h>
  12#include <asm/arch/mx6-pins.h>
  13#include <asm/arch/imx-regs.h>
  14#include <asm/arch/iomux.h>
  15#include <asm/arch/sys_proto.h>
  16#include <asm/errno.h>
  17#include <asm/gpio.h>
  18#include <asm/io.h>
  19#include <asm/imx-common/mxc_i2c.h>
  20#include <asm/imx-common/spi.h>
  21#include <common.h>
  22#include <fsl_esdhc.h>
  23#include <libfdt.h>
  24#include <i2c.h>
  25#include <mmc.h>
  26#include <power/pfuze100_pmic.h>
  27#include <power/pmic.h>
  28
  29#include "tqma6_bb.h"
  30
  31DECLARE_GLOBAL_DATA_PTR;
  32
  33#define USDHC_CLK_PAD_CTRL (PAD_CTL_PUS_47K_UP  | PAD_CTL_SPEED_LOW | \
  34        PAD_CTL_DSE_40ohm   | PAD_CTL_SRE_FAST  | PAD_CTL_HYS)
  35
  36#define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP  | PAD_CTL_SPEED_LOW | \
  37        PAD_CTL_DSE_80ohm   | PAD_CTL_SRE_FAST  | PAD_CTL_HYS)
  38
  39#define GPIO_OUT_PAD_CTRL  (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_LOW | \
  40        PAD_CTL_DSE_40ohm   | PAD_CTL_HYS)
  41
  42#define GPIO_IN_PAD_CTRL  (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_LOW | \
  43        PAD_CTL_DSE_40ohm   | PAD_CTL_HYS)
  44
  45#define SPI_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \
  46        PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS)
  47
  48#define I2C_PAD_CTRL    (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \
  49        PAD_CTL_DSE_40ohm | PAD_CTL_HYS |                       \
  50        PAD_CTL_ODE | PAD_CTL_SRE_FAST)
  51
  52int dram_init(void)
  53{
  54        gd->ram_size = imx_ddr_size();
  55
  56        return 0;
  57}
  58
  59static const uint16_t tqma6_emmc_dsr = 0x0100;
  60
  61/* eMMC on USDHCI3 always present */
  62static iomux_v3_cfg_t const tqma6_usdhc3_pads[] = {
  63        NEW_PAD_CTRL(MX6_PAD_SD3_CLK__SD3_CLK,          USDHC_PAD_CTRL),
  64        NEW_PAD_CTRL(MX6_PAD_SD3_CMD__SD3_CMD,          USDHC_PAD_CTRL),
  65        NEW_PAD_CTRL(MX6_PAD_SD3_DAT0__SD3_DATA0,       USDHC_PAD_CTRL),
  66        NEW_PAD_CTRL(MX6_PAD_SD3_DAT1__SD3_DATA1,       USDHC_PAD_CTRL),
  67        NEW_PAD_CTRL(MX6_PAD_SD3_DAT2__SD3_DATA2,       USDHC_PAD_CTRL),
  68        NEW_PAD_CTRL(MX6_PAD_SD3_DAT3__SD3_DATA3,       USDHC_PAD_CTRL),
  69        NEW_PAD_CTRL(MX6_PAD_SD3_DAT4__SD3_DATA4,       USDHC_PAD_CTRL),
  70        NEW_PAD_CTRL(MX6_PAD_SD3_DAT5__SD3_DATA5,       USDHC_PAD_CTRL),
  71        NEW_PAD_CTRL(MX6_PAD_SD3_DAT6__SD3_DATA6,       USDHC_PAD_CTRL),
  72        NEW_PAD_CTRL(MX6_PAD_SD3_DAT7__SD3_DATA7,       USDHC_PAD_CTRL),
  73        /* eMMC reset */
  74        NEW_PAD_CTRL(MX6_PAD_SD3_RST__SD3_RESET,        GPIO_OUT_PAD_CTRL),
  75};
  76
  77/*
  78 * According to board_mmc_init() the following map is done:
  79 * (U-boot device node)    (Physical Port)
  80 * mmc0                    eMMC (SD3) on TQMa6
  81 * mmc1 .. n               optional slots used on baseboard
  82 */
  83struct fsl_esdhc_cfg tqma6_usdhc_cfg = {
  84        .esdhc_base = USDHC3_BASE_ADDR,
  85        .max_bus_width = 8,
  86};
  87
  88int board_mmc_getcd(struct mmc *mmc)
  89{
  90        struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
  91        int ret = 0;
  92
  93        if (cfg->esdhc_base == USDHC3_BASE_ADDR)
  94                /* eMMC/uSDHC3 is always present */
  95                ret = 1;
  96        else
  97                ret = tqma6_bb_board_mmc_getcd(mmc);
  98
  99        return ret;
 100}
 101
 102int board_mmc_getwp(struct mmc *mmc)
 103{
 104        struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
 105        int ret = 0;
 106
 107        if (cfg->esdhc_base == USDHC3_BASE_ADDR)
 108                /* eMMC/uSDHC3 is always present */
 109                ret = 0;
 110        else
 111                ret = tqma6_bb_board_mmc_getwp(mmc);
 112
 113        return ret;
 114}
 115
 116int board_mmc_init(bd_t *bis)
 117{
 118        imx_iomux_v3_setup_multiple_pads(tqma6_usdhc3_pads,
 119                                         ARRAY_SIZE(tqma6_usdhc3_pads));
 120        tqma6_usdhc_cfg.sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
 121        if (fsl_esdhc_initialize(bis, &tqma6_usdhc_cfg)) {
 122                puts("Warning: failed to initialize eMMC dev\n");
 123        } else {
 124                struct mmc *mmc = find_mmc_device(0);
 125                if (mmc)
 126                        mmc_set_dsr(mmc, tqma6_emmc_dsr);
 127        }
 128
 129        tqma6_bb_board_mmc_init(bis);
 130
 131        return 0;
 132}
 133
 134static iomux_v3_cfg_t const tqma6_ecspi1_pads[] = {
 135        /* SS1 */
 136        NEW_PAD_CTRL(MX6_PAD_EIM_D19__GPIO3_IO19, SPI_PAD_CTRL),
 137        NEW_PAD_CTRL(MX6_PAD_EIM_D16__ECSPI1_SCLK, SPI_PAD_CTRL),
 138        NEW_PAD_CTRL(MX6_PAD_EIM_D17__ECSPI1_MISO, SPI_PAD_CTRL),
 139        NEW_PAD_CTRL(MX6_PAD_EIM_D18__ECSPI1_MOSI, SPI_PAD_CTRL),
 140};
 141
 142#define TQMA6_SF_CS_GPIO IMX_GPIO_NR(3, 19)
 143
 144static unsigned const tqma6_ecspi1_cs[] = {
 145        TQMA6_SF_CS_GPIO,
 146};
 147
 148static void tqma6_iomuxc_spi(void)
 149{
 150        unsigned i;
 151
 152        for (i = 0; i < ARRAY_SIZE(tqma6_ecspi1_cs); ++i)
 153                gpio_direction_output(tqma6_ecspi1_cs[i], 1);
 154        imx_iomux_v3_setup_multiple_pads(tqma6_ecspi1_pads,
 155                                         ARRAY_SIZE(tqma6_ecspi1_pads));
 156}
 157
 158int board_spi_cs_gpio(unsigned bus, unsigned cs)
 159{
 160        return ((bus == CONFIG_SF_DEFAULT_BUS) &&
 161                (cs == CONFIG_SF_DEFAULT_CS)) ? TQMA6_SF_CS_GPIO : -1;
 162}
 163
 164static struct i2c_pads_info tqma6_i2c3_pads = {
 165        /* I2C3: on board LM75, M24C64,  */
 166        .scl = {
 167                .i2c_mode = NEW_PAD_CTRL(MX6_PAD_GPIO_5__I2C3_SCL,
 168                                         I2C_PAD_CTRL),
 169                .gpio_mode = NEW_PAD_CTRL(MX6_PAD_GPIO_5__GPIO1_IO05,
 170                                          I2C_PAD_CTRL),
 171                .gp = IMX_GPIO_NR(1, 5)
 172        },
 173        .sda = {
 174                .i2c_mode = NEW_PAD_CTRL(MX6_PAD_GPIO_6__I2C3_SDA,
 175                                         I2C_PAD_CTRL),
 176                .gpio_mode = NEW_PAD_CTRL(MX6_PAD_GPIO_6__GPIO1_IO06,
 177                                          I2C_PAD_CTRL),
 178                .gp = IMX_GPIO_NR(1, 6)
 179        }
 180};
 181
 182static void tqma6_setup_i2c(void)
 183{
 184        int ret;
 185        /*
 186         * use logical index for bus, e.g. I2C1 -> 0
 187         * warn on error
 188         */
 189        ret = setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &tqma6_i2c3_pads);
 190        if (ret)
 191                printf("setup I2C3 failed: %d\n", ret);
 192}
 193
 194int board_early_init_f(void)
 195{
 196        return tqma6_bb_board_early_init_f();
 197}
 198
 199int board_init(void)
 200{
 201        /* address of boot parameters */
 202        gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
 203
 204        tqma6_iomuxc_spi();
 205        tqma6_setup_i2c();
 206
 207        tqma6_bb_board_init();
 208
 209        return 0;
 210}
 211
 212static const char *tqma6_get_boardname(void)
 213{
 214        u32 cpurev = get_cpu_rev();
 215
 216        switch ((cpurev & 0xFF000) >> 12) {
 217        case MXC_CPU_MX6SOLO:
 218                return "TQMa6S";
 219                break;
 220        case MXC_CPU_MX6DL:
 221                return "TQMa6DL";
 222                break;
 223        case MXC_CPU_MX6D:
 224                return "TQMa6D";
 225                break;
 226        case MXC_CPU_MX6Q:
 227                return "TQMa6Q";
 228                break;
 229        default:
 230                return "??";
 231        };
 232}
 233
 234int board_late_init(void)
 235{
 236        struct pmic *p;
 237        u32 reg;
 238
 239        setenv("board_name", tqma6_get_boardname());
 240
 241        /*
 242         * configure PFUZE100 PMIC:
 243         * TODO: should go to power_init_board if bus switching is
 244         * fixed in generic power code
 245         */
 246        power_pfuze100_init(TQMA6_PFUZE100_I2C_BUS);
 247        p = pmic_get("PFUZE100");
 248        if (p && !pmic_probe(p)) {
 249                pmic_reg_read(p, PFUZE100_DEVICEID, &reg);
 250                printf("PMIC: PFUZE100 ID=0x%02x\n", reg);
 251        }
 252
 253        tqma6_bb_board_late_init();
 254
 255        return 0;
 256}
 257
 258int checkboard(void)
 259{
 260        printf("Board: %s on a %s\n", tqma6_get_boardname(),
 261               tqma6_bb_get_boardname());
 262        return 0;
 263}
 264
 265/*
 266 * Device Tree Support
 267 */
 268#if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT)
 269int ft_board_setup(void *blob, bd_t *bd)
 270{
 271        /* bring in eMMC dsr settings */
 272        do_fixup_by_path_u32(blob,
 273                             "/soc/aips-bus@02100000/usdhc@02198000",
 274                             "dsr", tqma6_emmc_dsr, 2);
 275        tqma6_bb_ft_board_setup(blob, bd);
 276
 277        return 0;
 278}
 279#endif /* defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT) */
 280