uboot/board/samtec/vining_2000/vining_2000.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2016 samtec automotive software & electronics gmbh
   4 *
   5 * Author: Christoph Fritz <chf.fritz@googlemail.com>
   6 */
   7
   8#include <asm/arch/clock.h>
   9#include <asm/arch/crm_regs.h>
  10#include <asm/arch/iomux.h>
  11#include <asm/arch/imx-regs.h>
  12#include <asm/arch/mx6-pins.h>
  13#include <asm/arch/sys_proto.h>
  14#include <asm/gpio.h>
  15#include <asm/mach-imx/iomux-v3.h>
  16#include <asm/io.h>
  17#include <asm/mach-imx/mxc_i2c.h>
  18#include <linux/sizes.h>
  19#include <common.h>
  20#include <environment.h>
  21#include <fsl_esdhc.h>
  22#include <mmc.h>
  23#include <i2c.h>
  24#include <miiphy.h>
  25#include <netdev.h>
  26#include <power/pmic.h>
  27#include <power/pfuze100_pmic.h>
  28#include <usb.h>
  29#include <usb/ehci-ci.h>
  30#include <pwm.h>
  31#include <wait_bit.h>
  32
  33DECLARE_GLOBAL_DATA_PTR;
  34
  35#define UART_PAD_CTRL  (PAD_CTL_HYS | PAD_CTL_PUS_100K_UP |     \
  36        PAD_CTL_PKE | PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm |   \
  37        PAD_CTL_SRE_FAST)
  38
  39#define ENET_PAD_CTRL  (PAD_CTL_PUS_100K_UP | PAD_CTL_PKE |     \
  40        PAD_CTL_SPEED_HIGH | PAD_CTL_DSE_48ohm |                \
  41        PAD_CTL_SRE_FAST)
  42
  43#define ENET_CLK_PAD_CTRL  PAD_CTL_DSE_34ohm
  44
  45#define ENET_RX_PAD_CTRL  (PAD_CTL_PKE |                        \
  46        PAD_CTL_PUS_100K_DOWN | PAD_CTL_SPEED_HIGH |            \
  47        PAD_CTL_SRE_FAST)
  48
  49#define I2C_PAD_CTRL  (PAD_CTL_HYS | PAD_CTL_PUS_100K_UP |      \
  50        PAD_CTL_PKE | PAD_CTL_ODE | PAD_CTL_SPEED_MED |         \
  51        PAD_CTL_DSE_40ohm)
  52
  53#define USDHC_CLK_PAD_CTRL  (PAD_CTL_HYS | PAD_CTL_SPEED_MED |  \
  54        PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST)
  55
  56#define USDHC_PAD_CTRL  (PAD_CTL_HYS | PAD_CTL_PUS_47K_UP |     \
  57        PAD_CTL_PKE |  PAD_CTL_SPEED_MED | PAD_CTL_DSE_80ohm |  \
  58        PAD_CTL_SRE_FAST)
  59
  60#define GPIO_PAD_CTRL  (PAD_CTL_HYS | PAD_CTL_PUS_100K_UP |     \
  61        PAD_CTL_PKE)
  62
  63int dram_init(void)
  64{
  65        gd->ram_size = imx_ddr_size();
  66
  67        return 0;
  68}
  69
  70static iomux_v3_cfg_t const uart1_pads[] = {
  71        MX6_PAD_GPIO1_IO04__UART1_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
  72        MX6_PAD_GPIO1_IO05__UART1_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
  73};
  74
  75static iomux_v3_cfg_t const usdhc2_pads[] = {
  76        MX6_PAD_SD2_CLK__USDHC2_CLK | MUX_PAD_CTRL(USDHC_CLK_PAD_CTRL),
  77        MX6_PAD_SD2_CMD__USDHC2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  78        MX6_PAD_SD2_DATA0__USDHC2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  79        MX6_PAD_SD2_DATA1__USDHC2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  80        MX6_PAD_SD2_DATA2__USDHC2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  81        MX6_PAD_SD2_DATA3__USDHC2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  82        MX6_PAD_LCD1_VSYNC__GPIO3_IO_28 | MUX_PAD_CTRL(GPIO_PAD_CTRL),
  83};
  84
  85static iomux_v3_cfg_t const usdhc4_pads[] = {
  86        MX6_PAD_SD4_CLK__USDHC4_CLK | MUX_PAD_CTRL(USDHC_CLK_PAD_CTRL),
  87        MX6_PAD_SD4_CMD__USDHC4_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  88        MX6_PAD_SD4_DATA0__USDHC4_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  89        MX6_PAD_SD4_DATA1__USDHC4_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  90        MX6_PAD_SD4_DATA2__USDHC4_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  91        MX6_PAD_SD4_DATA3__USDHC4_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  92        MX6_PAD_SD4_DATA4__USDHC4_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  93        MX6_PAD_SD4_DATA5__USDHC4_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  94        MX6_PAD_SD4_DATA6__USDHC4_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  95        MX6_PAD_SD4_DATA7__USDHC4_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
  96};
  97
  98static iomux_v3_cfg_t const fec1_pads[] = {
  99        MX6_PAD_ENET1_MDC__ENET1_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
 100        MX6_PAD_ENET1_MDIO__ENET1_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL),
 101        MX6_PAD_RGMII1_RD0__ENET1_RX_DATA_0 | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
 102        MX6_PAD_RGMII1_RD1__ENET1_RX_DATA_1 | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
 103        MX6_PAD_RGMII1_TD0__ENET1_TX_DATA_0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
 104        MX6_PAD_RGMII1_TD1__ENET1_TX_DATA_1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
 105        MX6_PAD_RGMII1_RX_CTL__ENET1_RX_EN | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
 106        MX6_PAD_RGMII1_TX_CTL__ENET1_TX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),
 107        MX6_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 | MUX_PAD_CTRL(ENET_CLK_PAD_CTRL) |
 108                MUX_MODE_SION,
 109        /* LAN8720 PHY Reset */
 110        MX6_PAD_RGMII1_TD3__GPIO5_IO_9 | MUX_PAD_CTRL(NO_PAD_CTRL),
 111};
 112
 113static iomux_v3_cfg_t const pwm_led_pads[] = {
 114        MX6_PAD_RGMII2_RD2__PWM2_OUT | MUX_PAD_CTRL(NO_PAD_CTRL), /* green */
 115        MX6_PAD_RGMII2_TD2__PWM6_OUT | MUX_PAD_CTRL(NO_PAD_CTRL), /* red */
 116        MX6_PAD_RGMII2_RD3__PWM1_OUT | MUX_PAD_CTRL(NO_PAD_CTRL), /* blue */
 117};
 118
 119static void setup_iomux_uart(void)
 120{
 121        imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads));
 122}
 123
 124#define PHY_RESET IMX_GPIO_NR(5, 9)
 125
 126int board_eth_init(bd_t *bis)
 127{
 128        struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
 129        int ret;
 130        unsigned char eth1addr[6];
 131
 132        /* just to get secound mac address */
 133        imx_get_mac_from_fuse(1, eth1addr);
 134        if (!env_get("eth1addr") && is_valid_ethaddr(eth1addr))
 135                eth_env_set_enetaddr("eth1addr", eth1addr);
 136
 137        imx_iomux_v3_setup_multiple_pads(fec1_pads, ARRAY_SIZE(fec1_pads));
 138
 139        /*
 140         * Generate phy reference clock via pin IOMUX ENET_REF_CLK1/2 by erasing
 141         * ENET1/2_TX_CLK_DIR gpr1[14:13], so that reference clock is driven by
 142         * ref_enetpll0/1 and enable ENET1/2_TX_CLK output driver.
 143         */
 144        clrsetbits_le32(&iomuxc_regs->gpr[1],
 145                        IOMUX_GPR1_FEC1_CLOCK_MUX2_SEL_MASK |
 146                        IOMUX_GPR1_FEC2_CLOCK_MUX2_SEL_MASK,
 147                        IOMUX_GPR1_FEC1_CLOCK_MUX1_SEL_MASK |
 148                        IOMUX_GPR1_FEC2_CLOCK_MUX1_SEL_MASK);
 149
 150        ret = enable_fec_anatop_clock(0, ENET_50MHZ);
 151        if (ret)
 152                goto eth_fail;
 153
 154        /* reset phy */
 155        gpio_direction_output(PHY_RESET, 0);
 156        mdelay(16);
 157        gpio_set_value(PHY_RESET, 1);
 158        mdelay(1);
 159
 160        ret = fecmxc_initialize_multi(bis, 0, CONFIG_FEC_MXC_PHYADDR,
 161                                        IMX_FEC_BASE);
 162        if (ret)
 163                goto eth_fail;
 164
 165        return ret;
 166
 167eth_fail:
 168        printf("FEC MXC: %s:failed (%i)\n", __func__, ret);
 169        gpio_set_value(PHY_RESET, 0);
 170        return ret;
 171}
 172
 173#define PC MUX_PAD_CTRL(I2C_PAD_CTRL)
 174/* I2C1 for PMIC */
 175static struct i2c_pads_info i2c_pad_info1 = {
 176        .scl = {
 177                .i2c_mode = MX6_PAD_GPIO1_IO00__I2C1_SCL | PC,
 178                .gpio_mode = MX6_PAD_GPIO1_IO00__GPIO1_IO_0 | PC,
 179                .gp = IMX_GPIO_NR(1, 0),
 180        },
 181        .sda = {
 182                .i2c_mode = MX6_PAD_GPIO1_IO01__I2C1_SDA | PC,
 183                .gpio_mode = MX6_PAD_GPIO1_IO01__GPIO1_IO_1 | PC,
 184                .gp = IMX_GPIO_NR(1, 1),
 185        },
 186};
 187
 188static struct pmic *pfuze_init(unsigned char i2cbus)
 189{
 190        struct pmic *p;
 191        int ret;
 192        u32 reg;
 193
 194        ret = power_pfuze100_init(i2cbus);
 195        if (ret)
 196                return NULL;
 197
 198        p = pmic_get("PFUZE100");
 199        ret = pmic_probe(p);
 200        if (ret)
 201                return NULL;
 202
 203        pmic_reg_read(p, PFUZE100_DEVICEID, &reg);
 204        printf("PMIC:  PFUZE100 ID=0x%02x\n", reg);
 205
 206        /* Set SW1AB stanby volage to 0.975V */
 207        pmic_reg_read(p, PFUZE100_SW1ABSTBY, &reg);
 208        reg &= ~SW1x_STBY_MASK;
 209        reg |= SW1x_0_975V;
 210        pmic_reg_write(p, PFUZE100_SW1ABSTBY, reg);
 211
 212        /* Set SW1AB/VDDARM step ramp up time from 16us to 4us/25mV */
 213        pmic_reg_read(p, PFUZE100_SW1ABCONF, &reg);
 214        reg &= ~SW1xCONF_DVSSPEED_MASK;
 215        reg |= SW1xCONF_DVSSPEED_4US;
 216        pmic_reg_write(p, PFUZE100_SW1ABCONF, reg);
 217
 218        /* Set SW1C standby voltage to 0.975V */
 219        pmic_reg_read(p, PFUZE100_SW1CSTBY, &reg);
 220        reg &= ~SW1x_STBY_MASK;
 221        reg |= SW1x_0_975V;
 222        pmic_reg_write(p, PFUZE100_SW1CSTBY, reg);
 223
 224        /* Set SW1C/VDDSOC step ramp up time from 16us to 4us/25mV */
 225        pmic_reg_read(p, PFUZE100_SW1CCONF, &reg);
 226        reg &= ~SW1xCONF_DVSSPEED_MASK;
 227        reg |= SW1xCONF_DVSSPEED_4US;
 228        pmic_reg_write(p, PFUZE100_SW1CCONF, reg);
 229
 230        return p;
 231}
 232
 233static int pfuze_mode_init(struct pmic *p, u32 mode)
 234{
 235        unsigned char offset, i, switch_num;
 236        u32 id;
 237        int ret;
 238
 239        pmic_reg_read(p, PFUZE100_DEVICEID, &id);
 240        id = id & 0xf;
 241
 242        if (id == 0) {
 243                switch_num = 6;
 244                offset = PFUZE100_SW1CMODE;
 245        } else if (id == 1) {
 246                switch_num = 4;
 247                offset = PFUZE100_SW2MODE;
 248        } else {
 249                printf("Not supported, id=%d\n", id);
 250                return -EINVAL;
 251        }
 252
 253        ret = pmic_reg_write(p, PFUZE100_SW1ABMODE, mode);
 254        if (ret < 0) {
 255                printf("Set SW1AB mode error!\n");
 256                return ret;
 257        }
 258
 259        for (i = 0; i < switch_num - 1; i++) {
 260                ret = pmic_reg_write(p, offset + i * SWITCH_SIZE, mode);
 261                if (ret < 0) {
 262                        printf("Set switch 0x%x mode error!\n",
 263                               offset + i * SWITCH_SIZE);
 264                        return ret;
 265                }
 266        }
 267
 268        return ret;
 269}
 270
 271int power_init_board(void)
 272{
 273        struct pmic *p;
 274        int ret;
 275
 276        p = pfuze_init(I2C_PMIC);
 277        if (!p)
 278                return -ENODEV;
 279
 280        ret = pfuze_mode_init(p, APS_PFM);
 281        if (ret < 0)
 282                return ret;
 283
 284        return 0;
 285}
 286
 287#ifdef CONFIG_USB_EHCI_MX6
 288static iomux_v3_cfg_t const usb_otg_pads[] = {
 289        /* OGT1 */
 290        MX6_PAD_GPIO1_IO09__USB_OTG1_PWR | MUX_PAD_CTRL(NO_PAD_CTRL),
 291        MX6_PAD_GPIO1_IO10__ANATOP_OTG1_ID | MUX_PAD_CTRL(NO_PAD_CTRL),
 292        /* OTG2 */
 293        MX6_PAD_GPIO1_IO12__USB_OTG2_PWR | MUX_PAD_CTRL(NO_PAD_CTRL)
 294};
 295
 296static void setup_iomux_usb(void)
 297{
 298        imx_iomux_v3_setup_multiple_pads(usb_otg_pads,
 299                                         ARRAY_SIZE(usb_otg_pads));
 300}
 301
 302int board_usb_phy_mode(int port)
 303{
 304        if (port == 1)
 305                return USB_INIT_HOST;
 306        else
 307                return usb_phy_mode(port);
 308}
 309#endif
 310
 311#ifdef CONFIG_PWM_IMX
 312static int set_pwm_leds(void)
 313{
 314        int ret;
 315
 316        imx_iomux_v3_setup_multiple_pads(pwm_led_pads,
 317                                         ARRAY_SIZE(pwm_led_pads));
 318        /* enable backlight PWM 2, green LED */
 319        ret = pwm_init(1, 0, 0);
 320        if (ret)
 321                goto error;
 322        /* duty cycle 200ns, period: 8000ns */
 323        ret = pwm_config(1, 200, 8000);
 324        if (ret)
 325                goto error;
 326        ret = pwm_enable(1);
 327        if (ret)
 328                goto error;
 329
 330        /* enable backlight PWM 1, blue LED */
 331        ret = pwm_init(0, 0, 0);
 332        if (ret)
 333                goto error;
 334        /* duty cycle 200ns, period: 8000ns */
 335        ret = pwm_config(0, 200, 8000);
 336        if (ret)
 337                goto error;
 338        ret = pwm_enable(0);
 339        if (ret)
 340                goto error;
 341
 342        /* enable backlight PWM 6, red LED */
 343        ret = pwm_init(5, 0, 0);
 344        if (ret)
 345                goto error;
 346        /* duty cycle 200ns, period: 8000ns */
 347        ret = pwm_config(5, 200, 8000);
 348        if (ret)
 349                goto error;
 350        ret = pwm_enable(5);
 351
 352error:
 353        return ret;
 354}
 355#else
 356static int set_pwm_leds(void)
 357{
 358        return 0;
 359}
 360#endif
 361
 362#define ADCx_HC0        0x00
 363#define ADCx_HS         0x08
 364#define ADCx_HS_C0      BIT(0)
 365#define ADCx_R0         0x0c
 366#define ADCx_CFG        0x14
 367#define ADCx_CFG_SWMODE 0x308
 368#define ADCx_GC         0x18
 369#define ADCx_GC_CAL     BIT(7)
 370
 371static int read_adc(u32 *val)
 372{
 373        int ret;
 374        void __iomem *b = map_physmem(ADC1_BASE_ADDR, 0x100, MAP_NOCACHE);
 375
 376        /* use software mode */
 377        writel(ADCx_CFG_SWMODE, b + ADCx_CFG);
 378
 379        /* start auto calibration */
 380        setbits_le32(b + ADCx_GC, ADCx_GC_CAL);
 381        ret = wait_for_bit_le32(b + ADCx_GC, ADCx_GC_CAL, ADCx_GC_CAL, 10, 0);
 382        if (ret)
 383                goto adc_exit;
 384
 385        /* start conversion */
 386        writel(0, b + ADCx_HC0);
 387
 388        /* wait for conversion */
 389        ret = wait_for_bit_le32(b + ADCx_HS, ADCx_HS_C0, ADCx_HS_C0, 10, 0);
 390        if (ret)
 391                goto adc_exit;
 392
 393        /* read result */
 394        *val = readl(b + ADCx_R0);
 395
 396adc_exit:
 397        if (ret)
 398                printf("ADC failure (ret=%i)\n", ret);
 399        unmap_physmem(b, MAP_NOCACHE);
 400        return ret;
 401}
 402
 403#define VAL_UPPER       2498
 404#define VAL_LOWER       1550
 405
 406static int set_pin_state(void)
 407{
 408        u32 val;
 409        int ret;
 410
 411        ret = read_adc(&val);
 412        if (ret)
 413                return ret;
 414
 415        if (val >= VAL_UPPER)
 416                env_set("pin_state", "connected");
 417        else if (val < VAL_UPPER && val > VAL_LOWER)
 418                env_set("pin_state", "open");
 419        else
 420                env_set("pin_state", "button");
 421
 422        return ret;
 423}
 424
 425int board_late_init(void)
 426{
 427        int ret;
 428
 429        ret = set_pwm_leds();
 430        if (ret)
 431                return ret;
 432
 433        ret = set_pin_state();
 434
 435        return ret;
 436}
 437
 438int board_early_init_f(void)
 439{
 440        setup_iomux_uart();
 441
 442        setup_iomux_usb();
 443
 444        return 0;
 445}
 446
 447static struct fsl_esdhc_cfg usdhc_cfg[2] = {
 448        {USDHC4_BASE_ADDR, 0, 8},
 449        {USDHC2_BASE_ADDR, 0, 4},
 450};
 451
 452#define USDHC2_CD_GPIO IMX_GPIO_NR(3, 28)
 453
 454int board_mmc_getcd(struct mmc *mmc)
 455{
 456        struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
 457
 458        if (cfg->esdhc_base == USDHC4_BASE_ADDR)
 459                return 1;
 460        if (cfg->esdhc_base == USDHC2_BASE_ADDR)
 461                return !gpio_get_value(USDHC2_CD_GPIO);
 462
 463        return -EINVAL;
 464}
 465
 466int board_mmc_init(bd_t *bis)
 467{
 468        int ret;
 469
 470        /*
 471         * According to the board_mmc_init() the following map is done:
 472         * (U-Boot device node)    (Physical Port)
 473         * mmc0                    USDHC4
 474         * mmc1                    USDHC2
 475         */
 476        imx_iomux_v3_setup_multiple_pads(
 477                usdhc4_pads, ARRAY_SIZE(usdhc4_pads));
 478        usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK);
 479
 480        imx_iomux_v3_setup_multiple_pads(
 481                usdhc2_pads, ARRAY_SIZE(usdhc2_pads));
 482        gpio_direction_input(USDHC2_CD_GPIO);
 483        usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
 484
 485        ret = fsl_esdhc_initialize(bis, &usdhc_cfg[0]);
 486        if (ret) {
 487                printf("Warning: failed to initialize USDHC4\n");
 488                return ret;
 489        }
 490
 491        ret = fsl_esdhc_initialize(bis, &usdhc_cfg[1]);
 492        if (ret) {
 493                printf("Warning: failed to initialize USDHC2\n");
 494                return ret;
 495        }
 496
 497        return 0;
 498}
 499
 500int board_init(void)
 501{
 502        /* Address of boot parameters */
 503        gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
 504
 505#ifdef CONFIG_SYS_I2C_MXC
 506        setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);
 507#endif
 508
 509        return 0;
 510}
 511
 512int checkboard(void)
 513{
 514        puts("Board: VIN|ING 2000\n");
 515
 516        return 0;
 517}
 518