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