xref: /openbmc/u-boot/board/Marvell/mvebu_armada-37xx/board.c (revision 9925f1dbc38c0ef7220c6fca5968c708b8e48764)
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 <dm.h>
9 #include <i2c.h>
10 #include <phy.h>
11 #include <asm/io.h>
12 #include <asm/arch/cpu.h>
13 #include <asm/arch/soc.h>
14 
15 DECLARE_GLOBAL_DATA_PTR;
16 
17 /* IO expander I2C device */
18 #define I2C_IO_EXP_ADDR		0x22
19 #define I2C_IO_CFG_REG_0	0x6
20 #define I2C_IO_DATA_OUT_REG_0	0x2
21 #define I2C_IO_REG_0_SATA_OFF	2
22 #define I2C_IO_REG_0_USB_H_OFF	1
23 
24 /* The pin control values are the same for DB and Espressobin */
25 #define PINCTRL_NB_REG_VALUE	0x000173fa
26 #define PINCTRL_SB_REG_VALUE	0x00007a23
27 
28 /* Ethernet switch registers */
29 /* SMI addresses for multi-chip mode */
30 #define MVEBU_PORT_CTRL_SMI_ADDR(p)	(16 + (p))
31 #define MVEBU_SW_G2_SMI_ADDR		(28)
32 
33 /* Multi-chip mode */
34 #define MVEBU_SW_SMI_DATA_REG		(1)
35 #define MVEBU_SW_SMI_CMD_REG		(0)
36  #define SW_SMI_CMD_REG_ADDR_OFF	0
37  #define SW_SMI_CMD_DEV_ADDR_OFF	5
38  #define SW_SMI_CMD_SMI_OP_OFF		10
39  #define SW_SMI_CMD_SMI_MODE_OFF	12
40  #define SW_SMI_CMD_SMI_BUSY_OFF	15
41 
42 /* Single-chip mode */
43 /* Switch Port Registers */
44 #define MVEBU_SW_LINK_CTRL_REG		(1)
45 #define MVEBU_SW_PORT_CTRL_REG		(4)
46 
47 /* Global 2 Registers */
48 #define MVEBU_G2_SMI_PHY_CMD_REG	(24)
49 #define MVEBU_G2_SMI_PHY_DATA_REG	(25)
50 
51 int board_early_init_f(void)
52 {
53 	return 0;
54 }
55 
56 int board_init(void)
57 {
58 	/* adress of boot parameters */
59 	gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
60 
61 	return 0;
62 }
63 
64 /* Board specific AHCI / SATA enable code */
65 int board_ahci_enable(void)
66 {
67 	struct udevice *dev;
68 	int ret;
69 	u8 buf[8];
70 
71 	/* Only DB requres this configuration */
72 	if (!of_machine_is_compatible("marvell,armada-3720-db"))
73 		return 0;
74 
75 	/* Configure IO exander PCA9555: 7bit address 0x22 */
76 	ret = i2c_get_chip_for_busnum(0, I2C_IO_EXP_ADDR, 1, &dev);
77 	if (ret) {
78 		printf("Cannot find PCA9555: %d\n", ret);
79 		return 0;
80 	}
81 
82 	ret = dm_i2c_read(dev, I2C_IO_CFG_REG_0, buf, 1);
83 	if (ret) {
84 		printf("Failed to read IO expander value via I2C\n");
85 		return -EIO;
86 	}
87 
88 	/*
89 	 * Enable SATA power via IO expander connected via I2C by setting
90 	 * the corresponding bit to output mode to enable power for SATA
91 	 */
92 	buf[0] &= ~(1 << I2C_IO_REG_0_SATA_OFF);
93 	ret = dm_i2c_write(dev, I2C_IO_CFG_REG_0, buf, 1);
94 	if (ret) {
95 		printf("Failed to set IO expander via I2C\n");
96 		return -EIO;
97 	}
98 
99 	return 0;
100 }
101 
102 /* Board specific xHCI enable code */
103 int board_xhci_enable(fdt_addr_t base)
104 {
105 	struct udevice *dev;
106 	int ret;
107 	u8 buf[8];
108 
109 	/* Only DB requres this configuration */
110 	if (!of_machine_is_compatible("marvell,armada-3720-db"))
111 		return 0;
112 
113 	/* Configure IO exander PCA9555: 7bit address 0x22 */
114 	ret = i2c_get_chip_for_busnum(0, I2C_IO_EXP_ADDR, 1, &dev);
115 	if (ret) {
116 		printf("Cannot find PCA9555: %d\n", ret);
117 		return 0;
118 	}
119 
120 	printf("Enable USB VBUS\n");
121 
122 	/*
123 	 * Read configuration (direction) and set VBUS pin as output
124 	 * (reset pin = output)
125 	 */
126 	ret = dm_i2c_read(dev, I2C_IO_CFG_REG_0, buf, 1);
127 	if (ret) {
128 		printf("Failed to read IO expander value via I2C\n");
129 		return -EIO;
130 	}
131 	buf[0] &= ~(1 << I2C_IO_REG_0_USB_H_OFF);
132 	ret = dm_i2c_write(dev, I2C_IO_CFG_REG_0, buf, 1);
133 	if (ret) {
134 		printf("Failed to set IO expander via I2C\n");
135 		return -EIO;
136 	}
137 
138 	/* Read VBUS output value and disable it */
139 	ret = dm_i2c_read(dev, I2C_IO_DATA_OUT_REG_0, buf, 1);
140 	if (ret) {
141 		printf("Failed to read IO expander value via I2C\n");
142 		return -EIO;
143 	}
144 	buf[0] &= ~(1 << I2C_IO_REG_0_USB_H_OFF);
145 	ret = dm_i2c_write(dev, I2C_IO_DATA_OUT_REG_0, buf, 1);
146 	if (ret) {
147 		printf("Failed to set IO expander via I2C\n");
148 		return -EIO;
149 	}
150 
151 	/*
152 	 * Required delay for configuration to settle - must wait for
153 	 * power on port is disabled in case VBUS signal was high,
154 	 * required 3 seconds delay to let VBUS signal fully settle down
155 	 */
156 	mdelay(3000);
157 
158 	/* Enable VBUS power: Set output value of VBUS pin as enabled */
159 	buf[0] |= (1 << I2C_IO_REG_0_USB_H_OFF);
160 	ret = dm_i2c_write(dev, I2C_IO_DATA_OUT_REG_0, buf, 1);
161 	if (ret) {
162 		printf("Failed to set IO expander via I2C\n");
163 		return -EIO;
164 	}
165 
166 	mdelay(500); /* required delay to let output value settle */
167 
168 	return 0;
169 }
170 
171 /* Helper function for accessing switch devices in multi-chip connection mode */
172 static int mii_multi_chip_mode_write(struct mii_dev *bus, int dev_smi_addr,
173 				     int smi_addr, int reg, u16 value)
174 {
175 	u16 smi_cmd = 0;
176 
177 	if (bus->write(bus, dev_smi_addr, 0,
178 		       MVEBU_SW_SMI_DATA_REG, value) != 0) {
179 		printf("Error writing to the PHY addr=%02x reg=%02x\n",
180 		       smi_addr, reg);
181 		return -EFAULT;
182 	}
183 
184 	smi_cmd = (1 << SW_SMI_CMD_SMI_BUSY_OFF) |
185 		  (1 << SW_SMI_CMD_SMI_MODE_OFF) |
186 		  (1 << SW_SMI_CMD_SMI_OP_OFF) |
187 		  (smi_addr << SW_SMI_CMD_DEV_ADDR_OFF) |
188 		  (reg << SW_SMI_CMD_REG_ADDR_OFF);
189 	if (bus->write(bus, dev_smi_addr, 0,
190 		       MVEBU_SW_SMI_CMD_REG, smi_cmd) != 0) {
191 		printf("Error writing to the PHY addr=%02x reg=%02x\n",
192 		       smi_addr, reg);
193 		return -EFAULT;
194 	}
195 
196 	return 0;
197 }
198 
199 /* Bring-up board-specific network stuff */
200 int board_network_enable(struct mii_dev *bus)
201 {
202 	if (!of_machine_is_compatible("marvell,armada-3720-espressobin"))
203 		return 0;
204 
205 	/*
206 	 * FIXME: remove this code once Topaz driver gets available
207 	 * A3720 Community Board Only
208 	 * Configure Topaz switch (88E6341)
209 	 * Set port 0,1,2,3 to forwarding Mode (through Switch Port registers)
210 	 */
211 	mii_multi_chip_mode_write(bus, 1, MVEBU_PORT_CTRL_SMI_ADDR(0),
212 				  MVEBU_SW_PORT_CTRL_REG, 0x7f);
213 	mii_multi_chip_mode_write(bus, 1, MVEBU_PORT_CTRL_SMI_ADDR(1),
214 				  MVEBU_SW_PORT_CTRL_REG, 0x7f);
215 	mii_multi_chip_mode_write(bus, 1, MVEBU_PORT_CTRL_SMI_ADDR(2),
216 				  MVEBU_SW_PORT_CTRL_REG, 0x7f);
217 	mii_multi_chip_mode_write(bus, 1, MVEBU_PORT_CTRL_SMI_ADDR(3),
218 				  MVEBU_SW_PORT_CTRL_REG, 0x7f);
219 
220 	/* RGMII Delay on Port 0 (CPU port), force link to 1000Mbps */
221 	mii_multi_chip_mode_write(bus, 1, MVEBU_PORT_CTRL_SMI_ADDR(0),
222 				  MVEBU_SW_LINK_CTRL_REG, 0xe002);
223 
224 	/* Power up PHY 1, 2, 3 (through Global 2 registers) */
225 	mii_multi_chip_mode_write(bus, 1, MVEBU_SW_G2_SMI_ADDR,
226 				  MVEBU_G2_SMI_PHY_DATA_REG, 0x1140);
227 	mii_multi_chip_mode_write(bus, 1, MVEBU_SW_G2_SMI_ADDR,
228 				  MVEBU_G2_SMI_PHY_CMD_REG, 0x9620);
229 	mii_multi_chip_mode_write(bus, 1, MVEBU_SW_G2_SMI_ADDR,
230 				  MVEBU_G2_SMI_PHY_CMD_REG, 0x9640);
231 	mii_multi_chip_mode_write(bus, 1, MVEBU_SW_G2_SMI_ADDR,
232 				  MVEBU_G2_SMI_PHY_CMD_REG, 0x9660);
233 
234 	return 0;
235 }
236