xref: /rk3399_rockchip-uboot/board/gdsys/mpc8308/hrcon.c (revision d4e58888014135e429bb8c7b39655106e99b6477)
1 /*
2  * (C) Copyright 2014
3  * Dirk Eibach,  Guntermann & Drunck GmbH, eibach@gdsys.de
4  *
5  * SPDX-License-Identifier:	GPL-2.0+
6  */
7 
8 #include <common.h>
9 #include <hwconfig.h>
10 #include <i2c.h>
11 #include <spi.h>
12 #include <libfdt.h>
13 #include <fdt_support.h>
14 #include <pci.h>
15 #include <mpc83xx.h>
16 #include <fsl_esdhc.h>
17 #include <asm/io.h>
18 #include <asm/fsl_serdes.h>
19 #include <asm/fsl_mpc83xx_serdes.h>
20 
21 #include "mpc8308.h"
22 
23 #include <gdsys_fpga.h>
24 
25 #include "../common/ioep-fpga.h"
26 #include "../common/osd.h"
27 #include "../common/mclink.h"
28 #include "../common/phy.h"
29 
30 #include <pca953x.h>
31 #include <pca9698.h>
32 
33 #include <miiphy.h>
34 
35 DECLARE_GLOBAL_DATA_PTR;
36 
37 #define MAX_MUX_CHANNELS 2
38 
39 enum {
40 	MCFPGA_DONE = 1 << 0,
41 	MCFPGA_INIT_N = 1 << 1,
42 	MCFPGA_PROGRAM_N = 1 << 2,
43 	MCFPGA_UPDATE_ENABLE_N = 1 << 3,
44 	MCFPGA_RESET_N = 1 << 4,
45 };
46 
47 enum {
48 	GPIO_MDC = 1 << 14,
49 	GPIO_MDIO = 1 << 15,
50 };
51 
52 unsigned int mclink_fpgacount;
53 struct ihs_fpga *fpga_ptr[] = CONFIG_SYS_FPGA_PTR;
54 
55 int fpga_set_reg(u32 fpga, u16 *reg, off_t regoff, u16 data)
56 {
57 	int res;
58 
59 	switch (fpga) {
60 	case 0:
61 		out_le16(reg, data);
62 		break;
63 	default:
64 		res = mclink_send(fpga - 1, regoff, data);
65 		if (res < 0) {
66 			printf("mclink_send reg %02lx data %04x returned %d\n",
67 			       regoff, data, res);
68 			return res;
69 		}
70 		break;
71 	}
72 
73 	return 0;
74 }
75 
76 int fpga_get_reg(u32 fpga, u16 *reg, off_t regoff, u16 *data)
77 {
78 	int res;
79 
80 	switch (fpga) {
81 	case 0:
82 		*data = in_le16(reg);
83 		break;
84 	default:
85 		if (fpga > mclink_fpgacount)
86 			return -EINVAL;
87 		res = mclink_receive(fpga - 1, regoff, data);
88 		if (res < 0) {
89 			printf("mclink_receive reg %02lx returned %d\n",
90 			       regoff, res);
91 			return res;
92 		}
93 	}
94 
95 	return 0;
96 }
97 
98 int checkboard(void)
99 {
100 	char *s = getenv("serial#");
101 	bool hw_type_cat = pca9698_get_value(0x20, 20);
102 
103 	puts("Board: ");
104 
105 	printf("HRCon %s", hw_type_cat ? "CAT" : "Fiber");
106 
107 	if (s != NULL) {
108 		puts(", serial# ");
109 		puts(s);
110 	}
111 
112 	puts("\n");
113 
114 	return 0;
115 }
116 
117 int last_stage_init(void)
118 {
119 	int slaves;
120 	unsigned int k;
121 	unsigned int mux_ch;
122 	unsigned char mclink_controllers[] = { 0x24, 0x25, 0x26 };
123 	u16 fpga_features;
124 	bool hw_type_cat = pca9698_get_value(0x20, 20);
125 	bool ch0_rgmii2_present = false;
126 
127 	FPGA_GET_REG(0, fpga_features, &fpga_features);
128 
129 	/* Turn on Parade DP501 */
130 	pca9698_direction_output(0x20, 10, 1);
131 
132 	ch0_rgmii2_present = !pca9698_get_value(0x20, 30);
133 
134 	/* wait for FPGA done */
135 	for (k = 0; k < ARRAY_SIZE(mclink_controllers); ++k) {
136 		unsigned int ctr = 0;
137 
138 		if (i2c_probe(mclink_controllers[k]))
139 			continue;
140 
141 		while (!(pca953x_get_val(mclink_controllers[k])
142 		       & MCFPGA_DONE)) {
143 			udelay(100000);
144 			if (ctr++ > 5) {
145 				printf("no done for mclink_controller %d\n", k);
146 				break;
147 			}
148 		}
149 	}
150 
151 	if (hw_type_cat) {
152 		miiphy_register(bb_miiphy_buses[0].name, bb_miiphy_read,
153 				bb_miiphy_write);
154 		for (mux_ch = 0; mux_ch < MAX_MUX_CHANNELS; ++mux_ch) {
155 			if ((mux_ch == 1) && !ch0_rgmii2_present)
156 				continue;
157 
158 			setup_88e1514(bb_miiphy_buses[0].name, mux_ch);
159 		}
160 	}
161 
162 	/* give slave-PLLs and Parade DP501 some time to be up and running */
163 	udelay(500000);
164 
165 	mclink_fpgacount = CONFIG_SYS_MCLINK_MAX;
166 	slaves = mclink_probe();
167 	mclink_fpgacount = 0;
168 
169 	ioep_fpga_print_info(0);
170 	osd_probe(0);
171 
172 	if (slaves <= 0)
173 		return 0;
174 
175 	mclink_fpgacount = slaves;
176 
177 	for (k = 1; k <= slaves; ++k) {
178 		FPGA_GET_REG(k, fpga_features, &fpga_features);
179 
180 		ioep_fpga_print_info(k);
181 		osd_probe(k);
182 		if (hw_type_cat) {
183 			miiphy_register(bb_miiphy_buses[k].name,
184 					bb_miiphy_read, bb_miiphy_write);
185 			setup_88e1514(bb_miiphy_buses[k].name, 0);
186 		}
187 	}
188 
189 	return 0;
190 }
191 
192 /*
193  * provide access to fpga gpios (for I2C bitbang)
194  * (these may look all too simple but make iocon.h much more readable)
195  */
196 void fpga_gpio_set(unsigned int bus, int pin)
197 {
198 	FPGA_SET_REG(bus, gpio.set, pin);
199 }
200 
201 void fpga_gpio_clear(unsigned int bus, int pin)
202 {
203 	FPGA_SET_REG(bus, gpio.clear, pin);
204 }
205 
206 int fpga_gpio_get(unsigned int bus, int pin)
207 {
208 	u16 val;
209 
210 	FPGA_GET_REG(bus, gpio.read, &val);
211 
212 	return val & pin;
213 }
214 
215 void mpc8308_init(void)
216 {
217 	pca9698_direction_output(0x20, 4, 1);
218 }
219 
220 void mpc8308_set_fpga_reset(unsigned state)
221 {
222 	pca9698_set_value(0x20, 4, state ? 0 : 1);
223 }
224 
225 void mpc8308_setup_hw(void)
226 {
227 	immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
228 
229 	/*
230 	 * set "startup-finished"-gpios
231 	 */
232 	setbits_be32(&immr->gpio[0].dir, (1 << (31-11)) | (1 << (31-12)));
233 	setbits_be32(&immr->gpio[0].dat, 1 << (31-12));
234 }
235 
236 int mpc8308_get_fpga_done(unsigned fpga)
237 {
238 	return pca9698_get_value(0x20, 19);
239 }
240 
241 #ifdef CONFIG_FSL_ESDHC
242 int board_mmc_init(bd_t *bd)
243 {
244 	immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
245 	sysconf83xx_t *sysconf = &immr->sysconf;
246 
247 	/* Enable cache snooping in eSDHC system configuration register */
248 	out_be32(&sysconf->sdhccr, 0x02000000);
249 
250 	return fsl_esdhc_mmc_init(bd);
251 }
252 #endif
253 
254 static struct pci_region pcie_regions_0[] = {
255 	{
256 		.bus_start = CONFIG_SYS_PCIE1_MEM_BASE,
257 		.phys_start = CONFIG_SYS_PCIE1_MEM_PHYS,
258 		.size = CONFIG_SYS_PCIE1_MEM_SIZE,
259 		.flags = PCI_REGION_MEM,
260 	},
261 	{
262 		.bus_start = CONFIG_SYS_PCIE1_IO_BASE,
263 		.phys_start = CONFIG_SYS_PCIE1_IO_PHYS,
264 		.size = CONFIG_SYS_PCIE1_IO_SIZE,
265 		.flags = PCI_REGION_IO,
266 	},
267 };
268 
269 void pci_init_board(void)
270 {
271 	immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
272 	sysconf83xx_t *sysconf = &immr->sysconf;
273 	law83xx_t *pcie_law = sysconf->pcielaw;
274 	struct pci_region *pcie_reg[] = { pcie_regions_0 };
275 
276 	fsl_setup_serdes(CONFIG_FSL_SERDES1, FSL_SERDES_PROTO_PEX,
277 			 FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V);
278 
279 	/* Deassert the resets in the control register */
280 	out_be32(&sysconf->pecr1, 0xE0008000);
281 	udelay(2000);
282 
283 	/* Configure PCI Express Local Access Windows */
284 	out_be32(&pcie_law[0].bar, CONFIG_SYS_PCIE1_BASE & LAWBAR_BAR);
285 	out_be32(&pcie_law[0].ar, LBLAWAR_EN | LBLAWAR_512MB);
286 
287 	mpc83xx_pcie_init(1, pcie_reg);
288 }
289 
290 ulong board_flash_get_legacy(ulong base, int banknum, flash_info_t *info)
291 {
292 	info->portwidth = FLASH_CFI_16BIT;
293 	info->chipwidth = FLASH_CFI_BY16;
294 	info->interface = FLASH_CFI_X16;
295 	return 1;
296 }
297 
298 #if defined(CONFIG_OF_BOARD_SETUP)
299 int ft_board_setup(void *blob, bd_t *bd)
300 {
301 	ft_cpu_setup(blob, bd);
302 	fdt_fixup_dr_usb(blob, bd);
303 	fdt_fixup_esdhc(blob, bd);
304 
305 	return 0;
306 }
307 #endif
308 
309 /*
310  * FPGA MII bitbang implementation
311  */
312 
313 struct fpga_mii {
314 	unsigned fpga;
315 	int mdio;
316 } fpga_mii[] = {
317 	{ 0, 1},
318 	{ 1, 1},
319 	{ 2, 1},
320 	{ 3, 1},
321 };
322 
323 static int mii_dummy_init(struct bb_miiphy_bus *bus)
324 {
325 	return 0;
326 }
327 
328 static int mii_mdio_active(struct bb_miiphy_bus *bus)
329 {
330 	struct fpga_mii *fpga_mii = bus->priv;
331 
332 	if (fpga_mii->mdio)
333 		FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDIO);
334 	else
335 		FPGA_SET_REG(fpga_mii->fpga, gpio.clear, GPIO_MDIO);
336 
337 	return 0;
338 }
339 
340 static int mii_mdio_tristate(struct bb_miiphy_bus *bus)
341 {
342 	struct fpga_mii *fpga_mii = bus->priv;
343 
344 	FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDIO);
345 
346 	return 0;
347 }
348 
349 static int mii_set_mdio(struct bb_miiphy_bus *bus, int v)
350 {
351 	struct fpga_mii *fpga_mii = bus->priv;
352 
353 	if (v)
354 		FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDIO);
355 	else
356 		FPGA_SET_REG(fpga_mii->fpga, gpio.clear, GPIO_MDIO);
357 
358 	fpga_mii->mdio = v;
359 
360 	return 0;
361 }
362 
363 static int mii_get_mdio(struct bb_miiphy_bus *bus, int *v)
364 {
365 	u16 gpio;
366 	struct fpga_mii *fpga_mii = bus->priv;
367 
368 	FPGA_GET_REG(fpga_mii->fpga, gpio.read, &gpio);
369 
370 	*v = ((gpio & GPIO_MDIO) != 0);
371 
372 	return 0;
373 }
374 
375 static int mii_set_mdc(struct bb_miiphy_bus *bus, int v)
376 {
377 	struct fpga_mii *fpga_mii = bus->priv;
378 
379 	if (v)
380 		FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDC);
381 	else
382 		FPGA_SET_REG(fpga_mii->fpga, gpio.clear, GPIO_MDC);
383 
384 	return 0;
385 }
386 
387 static int mii_delay(struct bb_miiphy_bus *bus)
388 {
389 	udelay(1);
390 
391 	return 0;
392 }
393 
394 struct bb_miiphy_bus bb_miiphy_buses[] = {
395 	{
396 		.name = "board0",
397 		.init = mii_dummy_init,
398 		.mdio_active = mii_mdio_active,
399 		.mdio_tristate = mii_mdio_tristate,
400 		.set_mdio = mii_set_mdio,
401 		.get_mdio = mii_get_mdio,
402 		.set_mdc = mii_set_mdc,
403 		.delay = mii_delay,
404 		.priv = &fpga_mii[0],
405 	},
406 	{
407 		.name = "board1",
408 		.init = mii_dummy_init,
409 		.mdio_active = mii_mdio_active,
410 		.mdio_tristate = mii_mdio_tristate,
411 		.set_mdio = mii_set_mdio,
412 		.get_mdio = mii_get_mdio,
413 		.set_mdc = mii_set_mdc,
414 		.delay = mii_delay,
415 		.priv = &fpga_mii[1],
416 	},
417 	{
418 		.name = "board2",
419 		.init = mii_dummy_init,
420 		.mdio_active = mii_mdio_active,
421 		.mdio_tristate = mii_mdio_tristate,
422 		.set_mdio = mii_set_mdio,
423 		.get_mdio = mii_get_mdio,
424 		.set_mdc = mii_set_mdc,
425 		.delay = mii_delay,
426 		.priv = &fpga_mii[2],
427 	},
428 	{
429 		.name = "board3",
430 		.init = mii_dummy_init,
431 		.mdio_active = mii_mdio_active,
432 		.mdio_tristate = mii_mdio_tristate,
433 		.set_mdio = mii_set_mdio,
434 		.get_mdio = mii_get_mdio,
435 		.set_mdc = mii_set_mdc,
436 		.delay = mii_delay,
437 		.priv = &fpga_mii[3],
438 	},
439 };
440 
441 int bb_miiphy_buses_num = sizeof(bb_miiphy_buses) /
442 			  sizeof(bb_miiphy_buses[0]);
443