xref: /rk3399_rockchip-uboot/board/Marvell/mvebu_armada-8k/board.c (revision 1a4f6af8bfd44c8ae6e87a81ff125eed47042cc5)
1633fa0e7SStefan Roese /*
2633fa0e7SStefan Roese  * Copyright (C) 2016 Stefan Roese <sr@denx.de>
3633fa0e7SStefan Roese  *
4633fa0e7SStefan Roese  * SPDX-License-Identifier:	GPL-2.0+
5633fa0e7SStefan Roese  */
6633fa0e7SStefan Roese 
7633fa0e7SStefan Roese #include <common.h>
8acd3b076SStefan Roese #include <dm.h>
9633fa0e7SStefan Roese #include <i2c.h>
10633fa0e7SStefan Roese #include <asm/io.h>
11633fa0e7SStefan Roese #include <asm/arch/cpu.h>
12633fa0e7SStefan Roese #include <asm/arch/soc.h>
13633fa0e7SStefan Roese 
14633fa0e7SStefan Roese DECLARE_GLOBAL_DATA_PTR;
15633fa0e7SStefan Roese 
16acd3b076SStefan Roese /*
17acd3b076SStefan Roese  * Information specific to the DB-88F7040 eval board. We strive to use
18acd3b076SStefan Roese  * DT for such platform specfic configurations. At some point, this
19acd3b076SStefan Roese  * might be removed here and implemented via DT.
20acd3b076SStefan Roese  */
21633fa0e7SStefan Roese /* IO expander I2C device */
22633fa0e7SStefan Roese #define I2C_IO_EXP_ADDR		0x21
23633fa0e7SStefan Roese #define I2C_IO_CFG_REG_0	0x6
24633fa0e7SStefan Roese #define I2C_IO_DATA_OUT_REG_0	0x2
25633fa0e7SStefan Roese /* VBus enable */
26633fa0e7SStefan Roese #define I2C_IO_REG_0_USB_H0_OFF	0
27633fa0e7SStefan Roese #define I2C_IO_REG_0_USB_H1_OFF	1
28633fa0e7SStefan Roese #define I2C_IO_REG_VBUS		((1 << I2C_IO_REG_0_USB_H0_OFF) | \
29633fa0e7SStefan Roese 				 (1 << I2C_IO_REG_0_USB_H1_OFF))
30633fa0e7SStefan Roese /* Current limit */
31633fa0e7SStefan Roese #define I2C_IO_REG_0_USB_H0_CL	4
32633fa0e7SStefan Roese #define I2C_IO_REG_0_USB_H1_CL	5
33633fa0e7SStefan Roese #define I2C_IO_REG_CL		((1 << I2C_IO_REG_0_USB_H0_CL) | \
34633fa0e7SStefan Roese 				 (1 << I2C_IO_REG_0_USB_H1_CL))
35633fa0e7SStefan Roese 
36633fa0e7SStefan Roese static int usb_enabled = 0;
37633fa0e7SStefan Roese 
38633fa0e7SStefan Roese /* Board specific xHCI dis-/enable code */
39633fa0e7SStefan Roese 
40633fa0e7SStefan Roese /*
41633fa0e7SStefan Roese  * Set USB VBUS signals (via I2C IO expander/GPIO) as output and set
42633fa0e7SStefan Roese  * output value as disabled
43633fa0e7SStefan Roese  *
44633fa0e7SStefan Roese  * Set USB Current Limit signals (via I2C IO expander/GPIO) as output
45633fa0e7SStefan Roese  * and set output value as enabled
46633fa0e7SStefan Roese  */
board_xhci_config(void)47633fa0e7SStefan Roese int board_xhci_config(void)
48633fa0e7SStefan Roese {
49633fa0e7SStefan Roese 	struct udevice *dev;
50633fa0e7SStefan Roese 	int ret;
51633fa0e7SStefan Roese 	u8 buf[8];
52633fa0e7SStefan Roese 
53acd3b076SStefan Roese 	if (of_machine_is_compatible("marvell,armada7040-db")) {
54633fa0e7SStefan Roese 		/* Configure IO exander PCA9555: 7bit address 0x21 */
55633fa0e7SStefan Roese 		ret = i2c_get_chip_for_busnum(0, I2C_IO_EXP_ADDR, 1, &dev);
56633fa0e7SStefan Roese 		if (ret) {
57633fa0e7SStefan Roese 			printf("Cannot find PCA9555: %d\n", ret);
58633fa0e7SStefan Roese 			return 0;
59633fa0e7SStefan Roese 		}
60633fa0e7SStefan Roese 
61633fa0e7SStefan Roese 		/*
62633fa0e7SStefan Roese 		 * Read configuration (direction) and set VBUS pin as output
63633fa0e7SStefan Roese 		 * (reset pin = output)
64633fa0e7SStefan Roese 		 */
65633fa0e7SStefan Roese 		ret = dm_i2c_read(dev, I2C_IO_CFG_REG_0, buf, 1);
66633fa0e7SStefan Roese 		if (ret) {
67633fa0e7SStefan Roese 			printf("Failed to read IO expander value via I2C\n");
68633fa0e7SStefan Roese 			return -EIO;
69633fa0e7SStefan Roese 		}
70633fa0e7SStefan Roese 		buf[0] &= ~I2C_IO_REG_VBUS;
71633fa0e7SStefan Roese 		buf[0] &= ~I2C_IO_REG_CL;
72633fa0e7SStefan Roese 		ret = dm_i2c_write(dev, I2C_IO_CFG_REG_0, buf, 1);
73633fa0e7SStefan Roese 		if (ret) {
74633fa0e7SStefan Roese 			printf("Failed to set IO expander via I2C\n");
75633fa0e7SStefan Roese 			return -EIO;
76633fa0e7SStefan Roese 		}
77633fa0e7SStefan Roese 
78633fa0e7SStefan Roese 		/* Read output value and configure it */
79633fa0e7SStefan Roese 		ret = dm_i2c_read(dev, I2C_IO_DATA_OUT_REG_0, buf, 1);
80633fa0e7SStefan Roese 		if (ret) {
81633fa0e7SStefan Roese 			printf("Failed to read IO expander value via I2C\n");
82633fa0e7SStefan Roese 			return -EIO;
83633fa0e7SStefan Roese 		}
84633fa0e7SStefan Roese 		buf[0] &= ~I2C_IO_REG_VBUS;
85633fa0e7SStefan Roese 		buf[0] |= I2C_IO_REG_CL;
86633fa0e7SStefan Roese 		ret = dm_i2c_write(dev, I2C_IO_DATA_OUT_REG_0, buf, 1);
87633fa0e7SStefan Roese 		if (ret) {
88633fa0e7SStefan Roese 			printf("Failed to set IO expander via I2C\n");
89633fa0e7SStefan Roese 			return -EIO;
90633fa0e7SStefan Roese 		}
91633fa0e7SStefan Roese 
92633fa0e7SStefan Roese 		mdelay(500); /* required delay to let output value settle */
93acd3b076SStefan Roese 	}
94633fa0e7SStefan Roese 
95633fa0e7SStefan Roese 	return 0;
96633fa0e7SStefan Roese }
97633fa0e7SStefan Roese 
board_xhci_enable(fdt_addr_t base)98*0e266cadSJon Nettleton int board_xhci_enable(fdt_addr_t base)
99633fa0e7SStefan Roese {
100633fa0e7SStefan Roese 	struct udevice *dev;
101633fa0e7SStefan Roese 	int ret;
102633fa0e7SStefan Roese 	u8 buf[8];
103633fa0e7SStefan Roese 
104acd3b076SStefan Roese 	if (of_machine_is_compatible("marvell,armada7040-db")) {
105633fa0e7SStefan Roese 		/*
106633fa0e7SStefan Roese 		 * This function enables all USB ports simultaniously,
107633fa0e7SStefan Roese 		 * it only needs to get called once
108633fa0e7SStefan Roese 		 */
109633fa0e7SStefan Roese 		if (usb_enabled)
110633fa0e7SStefan Roese 			return 0;
111633fa0e7SStefan Roese 
112633fa0e7SStefan Roese 		/* Configure IO exander PCA9555: 7bit address 0x21 */
113633fa0e7SStefan Roese 		ret = i2c_get_chip_for_busnum(0, I2C_IO_EXP_ADDR, 1, &dev);
114633fa0e7SStefan Roese 		if (ret) {
115633fa0e7SStefan Roese 			printf("Cannot find PCA9555: %d\n", ret);
116633fa0e7SStefan Roese 			return 0;
117633fa0e7SStefan Roese 		}
118633fa0e7SStefan Roese 
119633fa0e7SStefan Roese 		/* Read VBUS output value */
120633fa0e7SStefan Roese 		ret = dm_i2c_read(dev, I2C_IO_DATA_OUT_REG_0, buf, 1);
121633fa0e7SStefan Roese 		if (ret) {
122633fa0e7SStefan Roese 			printf("Failed to read IO expander value via I2C\n");
123633fa0e7SStefan Roese 			return -EIO;
124633fa0e7SStefan Roese 		}
125633fa0e7SStefan Roese 
126633fa0e7SStefan Roese 		/* Enable VBUS power: Set output value of VBUS pin as enabled */
127633fa0e7SStefan Roese 		buf[0] |= I2C_IO_REG_VBUS;
128633fa0e7SStefan Roese 		ret = dm_i2c_write(dev, I2C_IO_DATA_OUT_REG_0, buf, 1);
129633fa0e7SStefan Roese 		if (ret) {
130633fa0e7SStefan Roese 			printf("Failed to set IO expander via I2C\n");
131633fa0e7SStefan Roese 			return -EIO;
132633fa0e7SStefan Roese 		}
133633fa0e7SStefan Roese 
134633fa0e7SStefan Roese 		mdelay(500); /* required delay to let output value settle */
135633fa0e7SStefan Roese 		usb_enabled = 1;
136acd3b076SStefan Roese 	}
137633fa0e7SStefan Roese 
138633fa0e7SStefan Roese 	return 0;
139633fa0e7SStefan Roese }
140633fa0e7SStefan Roese 
board_early_init_f(void)141633fa0e7SStefan Roese int board_early_init_f(void)
142633fa0e7SStefan Roese {
143633fa0e7SStefan Roese 	/* Nothing to do (yet), perhaps later some pin-muxing etc */
144633fa0e7SStefan Roese 
145633fa0e7SStefan Roese 	return 0;
146633fa0e7SStefan Roese }
147633fa0e7SStefan Roese 
board_init(void)148633fa0e7SStefan Roese int board_init(void)
149633fa0e7SStefan Roese {
150633fa0e7SStefan Roese 	/* adress of boot parameters */
151633fa0e7SStefan Roese 	gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
152633fa0e7SStefan Roese 
153633fa0e7SStefan Roese 	return 0;
154633fa0e7SStefan Roese }
155633fa0e7SStefan Roese 
board_late_init(void)156633fa0e7SStefan Roese int board_late_init(void)
157633fa0e7SStefan Roese {
158633fa0e7SStefan Roese 	/* Pre-configure the USB ports (overcurrent, VBus) */
159633fa0e7SStefan Roese 	board_xhci_config();
160633fa0e7SStefan Roese 
161633fa0e7SStefan Roese 	return 0;
162633fa0e7SStefan Roese }
163