]> git.ipfire.org Git - people/ms/u-boot.git/blob - board/Marvell/mvebu_armada-37xx/board.c
mvebu: usb: xhci: Add VBUS regulator supply to the host driver
[people/ms/u-boot.git] / board / Marvell / mvebu_armada-37xx / board.c
1 /*
2 * Copyright (C) 2016 Stefan Roese <sr@denx.de>
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6
7 #include <common.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 /* IO expander I2C device */
16 #define I2C_IO_EXP_ADDR 0x22
17 #define I2C_IO_CFG_REG_0 0x6
18 #define I2C_IO_DATA_OUT_REG_0 0x2
19 #define I2C_IO_REG_0_SATA_OFF 2
20 #define I2C_IO_REG_0_USB_H_OFF 1
21
22 int board_early_init_f(void)
23 {
24 /* Nothing to do (yet), perhaps later some pin-muxing etc */
25
26 return 0;
27 }
28
29 int board_init(void)
30 {
31 /* adress of boot parameters */
32 gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
33
34 return 0;
35 }
36
37 /* Board specific AHCI / SATA enable code */
38 int board_ahci_enable(void)
39 {
40 struct udevice *dev;
41 int ret;
42 u8 buf[8];
43
44 /* Configure IO exander PCA9555: 7bit address 0x22 */
45 ret = i2c_get_chip_for_busnum(0, I2C_IO_EXP_ADDR, 1, &dev);
46 if (ret) {
47 printf("Cannot find PCA9555: %d\n", ret);
48 return 0;
49 }
50
51 ret = dm_i2c_read(dev, I2C_IO_CFG_REG_0, buf, 1);
52 if (ret) {
53 printf("Failed to read IO expander value via I2C\n");
54 return -EIO;
55 }
56
57 /*
58 * Enable SATA power via IO expander connected via I2C by setting
59 * the corresponding bit to output mode to enable power for SATA
60 */
61 buf[0] &= ~(1 << I2C_IO_REG_0_SATA_OFF);
62 ret = dm_i2c_write(dev, I2C_IO_CFG_REG_0, buf, 1);
63 if (ret) {
64 printf("Failed to set IO expander via I2C\n");
65 return -EIO;
66 }
67
68 return 0;
69 }
70
71 /* Board specific xHCI enable code */
72 int board_xhci_enable(void)
73 {
74 struct udevice *dev;
75 int ret;
76 u8 buf[8];
77
78 /* Configure IO exander PCA9555: 7bit address 0x22 */
79 ret = i2c_get_chip_for_busnum(0, I2C_IO_EXP_ADDR, 1, &dev);
80 if (ret) {
81 printf("Cannot find PCA9555: %d\n", ret);
82 return 0;
83 }
84
85 printf("Enable USB VBUS\n");
86
87 /*
88 * Read configuration (direction) and set VBUS pin as output
89 * (reset pin = output)
90 */
91 ret = dm_i2c_read(dev, I2C_IO_CFG_REG_0, buf, 1);
92 if (ret) {
93 printf("Failed to read IO expander value via I2C\n");
94 return -EIO;
95 }
96 buf[0] &= ~(1 << I2C_IO_REG_0_USB_H_OFF);
97 ret = dm_i2c_write(dev, I2C_IO_CFG_REG_0, buf, 1);
98 if (ret) {
99 printf("Failed to set IO expander via I2C\n");
100 return -EIO;
101 }
102
103 /* Read VBUS output value and disable it */
104 ret = dm_i2c_read(dev, I2C_IO_DATA_OUT_REG_0, buf, 1);
105 if (ret) {
106 printf("Failed to read IO expander value via I2C\n");
107 return -EIO;
108 }
109 buf[0] &= ~(1 << I2C_IO_REG_0_USB_H_OFF);
110 ret = dm_i2c_write(dev, I2C_IO_DATA_OUT_REG_0, buf, 1);
111 if (ret) {
112 printf("Failed to set IO expander via I2C\n");
113 return -EIO;
114 }
115
116 /*
117 * Required delay for configuration to settle - must wait for
118 * power on port is disabled in case VBUS signal was high,
119 * required 3 seconds delay to let VBUS signal fully settle down
120 */
121 mdelay(3000);
122
123 /* Enable VBUS power: Set output value of VBUS pin as enabled */
124 buf[0] |= (1 << I2C_IO_REG_0_USB_H_OFF);
125 ret = dm_i2c_write(dev, I2C_IO_DATA_OUT_REG_0, buf, 1);
126 if (ret) {
127 printf("Failed to set IO expander via I2C\n");
128 return -EIO;
129 }
130
131 mdelay(500); /* required delay to let output value settle */
132
133 return 0;
134 }