uboot/board/Marvell/mvebu_armada-8k/board.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2016 Stefan Roese <sr@denx.de>
   4 */
   5
   6#include <common.h>
   7#include <dm.h>
   8#include <i2c.h>
   9#include <init.h>
  10#include <asm/global_data.h>
  11#include <asm/io.h>
  12#include <asm/arch/cpu.h>
  13#include <asm/arch/soc.h>
  14#include <linux/delay.h>
  15
  16DECLARE_GLOBAL_DATA_PTR;
  17
  18/*
  19 * Information specific to the DB-88F7040 eval board. We strive to use
  20 * DT for such platform specfic configurations. At some point, this
  21 * might be removed here and implemented via DT.
  22 */
  23/* IO expander I2C device */
  24#define I2C_IO_EXP_ADDR         0x21
  25#define I2C_IO_CFG_REG_0        0x6
  26#define I2C_IO_DATA_OUT_REG_0   0x2
  27/* VBus enable */
  28#define I2C_IO_REG_0_USB_H0_OFF 0
  29#define I2C_IO_REG_0_USB_H1_OFF 1
  30#define I2C_IO_REG_VBUS         ((1 << I2C_IO_REG_0_USB_H0_OFF) | \
  31                                 (1 << I2C_IO_REG_0_USB_H1_OFF))
  32/* Current limit */
  33#define I2C_IO_REG_0_USB_H0_CL  4
  34#define I2C_IO_REG_0_USB_H1_CL  5
  35#define I2C_IO_REG_CL           ((1 << I2C_IO_REG_0_USB_H0_CL) | \
  36                                 (1 << I2C_IO_REG_0_USB_H1_CL))
  37
  38static int usb_enabled = 0;
  39
  40/* Board specific xHCI dis-/enable code */
  41
  42/*
  43 * Set USB VBUS signals (via I2C IO expander/GPIO) as output and set
  44 * output value as disabled
  45 *
  46 * Set USB Current Limit signals (via I2C IO expander/GPIO) as output
  47 * and set output value as enabled
  48 */
  49int board_xhci_config(void)
  50{
  51        struct udevice *dev;
  52        int ret;
  53        u8 buf[8];
  54
  55        if (of_machine_is_compatible("marvell,armada7040-db")) {
  56                /* Configure IO exander PCA9555: 7bit address 0x21 */
  57                ret = i2c_get_chip_for_busnum(0, I2C_IO_EXP_ADDR, 1, &dev);
  58                if (ret) {
  59                        printf("Cannot find PCA9555: %d\n", ret);
  60                        return 0;
  61                }
  62
  63                /*
  64                 * Read configuration (direction) and set VBUS pin as output
  65                 * (reset pin = output)
  66                 */
  67                ret = dm_i2c_read(dev, I2C_IO_CFG_REG_0, buf, 1);
  68                if (ret) {
  69                        printf("Failed to read IO expander value via I2C\n");
  70                        return -EIO;
  71                }
  72                buf[0] &= ~I2C_IO_REG_VBUS;
  73                buf[0] &= ~I2C_IO_REG_CL;
  74                ret = dm_i2c_write(dev, I2C_IO_CFG_REG_0, buf, 1);
  75                if (ret) {
  76                        printf("Failed to set IO expander via I2C\n");
  77                        return -EIO;
  78                }
  79
  80                /* Read output value and configure it */
  81                ret = dm_i2c_read(dev, I2C_IO_DATA_OUT_REG_0, buf, 1);
  82                if (ret) {
  83                        printf("Failed to read IO expander value via I2C\n");
  84                        return -EIO;
  85                }
  86                buf[0] &= ~I2C_IO_REG_VBUS;
  87                buf[0] |= I2C_IO_REG_CL;
  88                ret = dm_i2c_write(dev, I2C_IO_DATA_OUT_REG_0, buf, 1);
  89                if (ret) {
  90                        printf("Failed to set IO expander via I2C\n");
  91                        return -EIO;
  92                }
  93
  94                mdelay(500); /* required delay to let output value settle */
  95        }
  96
  97        return 0;
  98}
  99
 100int board_xhci_enable(fdt_addr_t base)
 101{
 102        struct udevice *dev;
 103        int ret;
 104        u8 buf[8];
 105
 106        if (of_machine_is_compatible("marvell,armada7040-db")) {
 107                /*
 108                 * This function enables all USB ports simultaniously,
 109                 * it only needs to get called once
 110                 */
 111                if (usb_enabled)
 112                        return 0;
 113
 114                /* Configure IO exander PCA9555: 7bit address 0x21 */
 115                ret = i2c_get_chip_for_busnum(0, I2C_IO_EXP_ADDR, 1, &dev);
 116                if (ret) {
 117                        printf("Cannot find PCA9555: %d\n", ret);
 118                        return 0;
 119                }
 120
 121                /* Read VBUS output value */
 122                ret = dm_i2c_read(dev, I2C_IO_DATA_OUT_REG_0, buf, 1);
 123                if (ret) {
 124                        printf("Failed to read IO expander value via I2C\n");
 125                        return -EIO;
 126                }
 127
 128                /* Enable VBUS power: Set output value of VBUS pin as enabled */
 129                buf[0] |= I2C_IO_REG_VBUS;
 130                ret = dm_i2c_write(dev, I2C_IO_DATA_OUT_REG_0, buf, 1);
 131                if (ret) {
 132                        printf("Failed to set IO expander via I2C\n");
 133                        return -EIO;
 134                }
 135
 136                mdelay(500); /* required delay to let output value settle */
 137                usb_enabled = 1;
 138        }
 139
 140        return 0;
 141}
 142
 143int board_early_init_f(void)
 144{
 145        /* Nothing to do yet */
 146
 147        return 0;
 148}
 149
 150int board_init(void)
 151{
 152        /* adress of boot parameters */
 153        gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
 154
 155        return 0;
 156}
 157
 158int board_late_init(void)
 159{
 160        /* Pre-configure the USB ports (overcurrent, VBus) */
 161        board_xhci_config();
 162
 163        return 0;
 164}
 165