Merge tag 'xilinx-for-v2021.04-rc3' of https://gitlab.denx.de/u-boot/custodians/u...
[platform/kernel/u-boot.git] / board / Marvell / mvebu_armada-8k / board.c
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
16 DECLARE_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
38 /*
39  * Information specific to the iEi Puzzle-M801 board.
40  */
41
42 /* Internal configuration registers */
43 #define CP1_CONF_REG_BASE 0xf4440000
44 #define CONF_REG_MPP0 0x0
45 #define CONF_REG_MPP1 0x4
46 #define CONF_REG_MPP2 0x8
47 #define CONF_REG_MPP3 0xC
48
49 static int usb_enabled = 0;
50
51 /* Board specific xHCI dis-/enable code */
52
53 /*
54  * Set USB VBUS signals (via I2C IO expander/GPIO) as output and set
55  * output value as disabled
56  *
57  * Set USB Current Limit signals (via I2C IO expander/GPIO) as output
58  * and set output value as enabled
59  */
60 int board_xhci_config(void)
61 {
62         struct udevice *dev;
63         int ret;
64         u8 buf[8];
65
66         if (of_machine_is_compatible("marvell,armada7040-db")) {
67                 /* Configure IO exander PCA9555: 7bit address 0x21 */
68                 ret = i2c_get_chip_for_busnum(0, I2C_IO_EXP_ADDR, 1, &dev);
69                 if (ret) {
70                         printf("Cannot find PCA9555: %d\n", ret);
71                         return 0;
72                 }
73
74                 /*
75                  * Read configuration (direction) and set VBUS pin as output
76                  * (reset pin = output)
77                  */
78                 ret = dm_i2c_read(dev, I2C_IO_CFG_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_CFG_REG_0, buf, 1);
86                 if (ret) {
87                         printf("Failed to set IO expander via I2C\n");
88                         return -EIO;
89                 }
90
91                 /* Read output value and configure it */
92                 ret = dm_i2c_read(dev, I2C_IO_DATA_OUT_REG_0, buf, 1);
93                 if (ret) {
94                         printf("Failed to read IO expander value via I2C\n");
95                         return -EIO;
96                 }
97                 buf[0] &= ~I2C_IO_REG_VBUS;
98                 buf[0] |= I2C_IO_REG_CL;
99                 ret = dm_i2c_write(dev, I2C_IO_DATA_OUT_REG_0, buf, 1);
100                 if (ret) {
101                         printf("Failed to set IO expander via I2C\n");
102                         return -EIO;
103                 }
104
105                 mdelay(500); /* required delay to let output value settle */
106         }
107
108         return 0;
109 }
110
111 int board_xhci_enable(fdt_addr_t base)
112 {
113         struct udevice *dev;
114         int ret;
115         u8 buf[8];
116
117         if (of_machine_is_compatible("marvell,armada7040-db")) {
118                 /*
119                  * This function enables all USB ports simultaniously,
120                  * it only needs to get called once
121                  */
122                 if (usb_enabled)
123                         return 0;
124
125                 /* Configure IO exander PCA9555: 7bit address 0x21 */
126                 ret = i2c_get_chip_for_busnum(0, I2C_IO_EXP_ADDR, 1, &dev);
127                 if (ret) {
128                         printf("Cannot find PCA9555: %d\n", ret);
129                         return 0;
130                 }
131
132                 /* Read VBUS output value */
133                 ret = dm_i2c_read(dev, I2C_IO_DATA_OUT_REG_0, buf, 1);
134                 if (ret) {
135                         printf("Failed to read IO expander value via I2C\n");
136                         return -EIO;
137                 }
138
139                 /* Enable VBUS power: Set output value of VBUS pin as enabled */
140                 buf[0] |= I2C_IO_REG_VBUS;
141                 ret = dm_i2c_write(dev, I2C_IO_DATA_OUT_REG_0, buf, 1);
142                 if (ret) {
143                         printf("Failed to set IO expander via I2C\n");
144                         return -EIO;
145                 }
146
147                 mdelay(500); /* required delay to let output value settle */
148                 usb_enabled = 1;
149         }
150
151         return 0;
152 }
153
154 int board_early_init_f(void)
155 {
156         /* Initialize some platform specific memory locations */
157         if (of_machine_is_compatible("marvell,armada8040-puzzle-m801")) {
158                 /* MPP setup */
159                 writel(0x00444444, CP1_CONF_REG_BASE + CONF_REG_MPP0);
160                 writel(0x00000000, CP1_CONF_REG_BASE + CONF_REG_MPP1);
161                 writel(0x00000000, CP1_CONF_REG_BASE + CONF_REG_MPP2);
162                 writel(0x08888000, CP1_CONF_REG_BASE + CONF_REG_MPP3);
163         }
164
165         return 0;
166 }
167
168 int board_init(void)
169 {
170         /* adress of boot parameters */
171         gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
172
173         return 0;
174 }
175
176 int board_late_init(void)
177 {
178         /* Pre-configure the USB ports (overcurrent, VBus) */
179         board_xhci_config();
180
181         return 0;
182 }