blob: d1110157a2efbfacc5eb3b8c4d8bb20036404fa4 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Dirk Eibachf74a0272014-11-13 19:21:18 +01002/*
3 * (C) Copyright 2014
Mario Sixb4893582018-03-06 08:04:58 +01004 * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
Dirk Eibachf74a0272014-11-13 19:21:18 +01005 */
6
7#include <common.h>
Simon Glass0af6e2d2019-08-01 09:46:52 -06008#include <env.h>
Dirk Eibachf74a0272014-11-13 19:21:18 +01009#include <hwconfig.h>
10#include <i2c.h>
Simon Glass18afe102019-11-14 12:57:47 -070011#include <init.h>
Dirk Eibachf74a0272014-11-13 19:21:18 +010012#include <spi.h>
Masahiro Yamada75f82d02018-03-05 01:20:11 +090013#include <linux/libfdt.h>
Dirk Eibachf74a0272014-11-13 19:21:18 +010014#include <fdt_support.h>
15#include <pci.h>
16#include <mpc83xx.h>
17#include <fsl_esdhc.h>
18#include <asm/io.h>
19#include <asm/fsl_serdes.h>
20#include <asm/fsl_mpc83xx_serdes.h>
21
22#include "mpc8308.h"
23
24#include <gdsys_fpga.h>
25
Dirk Eibach30d07bb2015-10-28 11:46:33 +010026#include "../common/ioep-fpga.h"
Dirk Eibachf74a0272014-11-13 19:21:18 +010027#include "../common/osd.h"
28#include "../common/mclink.h"
29#include "../common/phy.h"
Dirk Eibach94594332015-10-28 11:46:36 +010030#include "../common/fanctrl.h"
Dirk Eibachf74a0272014-11-13 19:21:18 +010031
32#include <pca953x.h>
33#include <pca9698.h>
34
35#include <miiphy.h>
36
Dirk Eibachf74a0272014-11-13 19:21:18 +010037#define MAX_MUX_CHANNELS 2
38
39enum {
Mario Six3809c472019-03-29 10:18:06 +010040 MCFPGA_DONE = BIT(0),
41 MCFPGA_INIT_N = BIT(1),
42 MCFPGA_PROGRAM_N = BIT(2),
43 MCFPGA_UPDATE_ENABLE_N = BIT(3),
44 MCFPGA_RESET_N = BIT(4),
Dirk Eibachf74a0272014-11-13 19:21:18 +010045};
46
47enum {
48 GPIO_MDC = 1 << 14,
49 GPIO_MDIO = 1 << 15,
50};
51
Mario Six3809c472019-03-29 10:18:06 +010052uint mclink_fpgacount;
Dirk Eibachf74a0272014-11-13 19:21:18 +010053struct ihs_fpga *fpga_ptr[] = CONFIG_SYS_FPGA_PTR;
54
Dirk Eibach94594332015-10-28 11:46:36 +010055struct {
56 u8 bus;
57 u8 addr;
58} hrcon_fans[] = CONFIG_HRCON_FANS;
59
Dirk Eibachf74a0272014-11-13 19:21:18 +010060int fpga_set_reg(u32 fpga, u16 *reg, off_t regoff, u16 data)
61{
62 int res;
63
64 switch (fpga) {
65 case 0:
66 out_le16(reg, data);
67 break;
68 default:
69 res = mclink_send(fpga - 1, regoff, data);
70 if (res < 0) {
71 printf("mclink_send reg %02lx data %04x returned %d\n",
72 regoff, data, res);
73 return res;
74 }
75 break;
76 }
77
78 return 0;
79}
80
81int fpga_get_reg(u32 fpga, u16 *reg, off_t regoff, u16 *data)
82{
83 int res;
84
85 switch (fpga) {
86 case 0:
87 *data = in_le16(reg);
88 break;
89 default:
90 if (fpga > mclink_fpgacount)
91 return -EINVAL;
92 res = mclink_receive(fpga - 1, regoff, data);
93 if (res < 0) {
94 printf("mclink_receive reg %02lx returned %d\n",
95 regoff, res);
96 return res;
97 }
98 }
99
100 return 0;
101}
102
103int checkboard(void)
104{
Simon Glass64b723f2017-08-03 12:22:12 -0600105 char *s = env_get("serial#");
Dirk Eibachf74a0272014-11-13 19:21:18 +0100106 bool hw_type_cat = pca9698_get_value(0x20, 20);
107
108 puts("Board: ");
109
110 printf("HRCon %s", hw_type_cat ? "CAT" : "Fiber");
111
Mario Six3809c472019-03-29 10:18:06 +0100112 if (s) {
Dirk Eibachf74a0272014-11-13 19:21:18 +0100113 puts(", serial# ");
114 puts(s);
115 }
116
117 puts("\n");
118
119 return 0;
120}
121
Dirk Eibachf74a0272014-11-13 19:21:18 +0100122int last_stage_init(void)
123{
124 int slaves;
Mario Six3809c472019-03-29 10:18:06 +0100125 uint k;
126 uchar mclink_controllers[] = { 0x3c, 0x3d, 0x3e };
Dirk Eibachf74a0272014-11-13 19:21:18 +0100127 u16 fpga_features;
128 bool hw_type_cat = pca9698_get_value(0x20, 20);
Mario Six3809c472019-03-29 10:18:06 +0100129 bool ch0_rgmii2_present;
Dirk Eibachf74a0272014-11-13 19:21:18 +0100130
131 FPGA_GET_REG(0, fpga_features, &fpga_features);
132
133 /* Turn on Parade DP501 */
134 pca9698_direction_output(0x20, 10, 1);
Dirk Eibach981bacd2015-10-28 11:46:35 +0100135 pca9698_direction_output(0x20, 11, 1);
Dirk Eibachf74a0272014-11-13 19:21:18 +0100136
137 ch0_rgmii2_present = !pca9698_get_value(0x20, 30);
138
Dirk Eibach9806a8e2015-10-28 11:46:34 +0100139 /* wait for FPGA done, then reset FPGA */
Dirk Eibachf74a0272014-11-13 19:21:18 +0100140 for (k = 0; k < ARRAY_SIZE(mclink_controllers); ++k) {
Mario Six3809c472019-03-29 10:18:06 +0100141 uint ctr = 0;
Dirk Eibachf74a0272014-11-13 19:21:18 +0100142
143 if (i2c_probe(mclink_controllers[k]))
144 continue;
145
146 while (!(pca953x_get_val(mclink_controllers[k])
147 & MCFPGA_DONE)) {
Mario Six3809c472019-03-29 10:18:06 +0100148 mdelay(100);
Dirk Eibachf74a0272014-11-13 19:21:18 +0100149 if (ctr++ > 5) {
Mario Six3809c472019-03-29 10:18:06 +0100150 printf("no done for mclink_controller %u\n", k);
Dirk Eibachf74a0272014-11-13 19:21:18 +0100151 break;
152 }
153 }
Dirk Eibach9806a8e2015-10-28 11:46:34 +0100154
155 pca953x_set_dir(mclink_controllers[k], MCFPGA_RESET_N, 0);
156 pca953x_set_val(mclink_controllers[k], MCFPGA_RESET_N, 0);
157 udelay(10);
158 pca953x_set_val(mclink_controllers[k], MCFPGA_RESET_N,
159 MCFPGA_RESET_N);
Dirk Eibachf74a0272014-11-13 19:21:18 +0100160 }
161
162 if (hw_type_cat) {
Mario Six3809c472019-03-29 10:18:06 +0100163 uint mux_ch;
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500164 int retval;
165 struct mii_dev *mdiodev = mdio_alloc();
Mario Six3809c472019-03-29 10:18:06 +0100166
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500167 if (!mdiodev)
168 return -ENOMEM;
169 strncpy(mdiodev->name, bb_miiphy_buses[0].name, MDIO_NAME_LEN);
170 mdiodev->read = bb_miiphy_read;
171 mdiodev->write = bb_miiphy_write;
172
173 retval = mdio_register(mdiodev);
174 if (retval < 0)
175 return retval;
Dirk Eibachf74a0272014-11-13 19:21:18 +0100176 for (mux_ch = 0; mux_ch < MAX_MUX_CHANNELS; ++mux_ch) {
177 if ((mux_ch == 1) && !ch0_rgmii2_present)
178 continue;
179
180 setup_88e1514(bb_miiphy_buses[0].name, mux_ch);
181 }
182 }
183
184 /* give slave-PLLs and Parade DP501 some time to be up and running */
Mario Six3809c472019-03-29 10:18:06 +0100185 mdelay(500);
Dirk Eibachf74a0272014-11-13 19:21:18 +0100186
187 mclink_fpgacount = CONFIG_SYS_MCLINK_MAX;
188 slaves = mclink_probe();
189 mclink_fpgacount = 0;
190
Dirk Eibach30d07bb2015-10-28 11:46:33 +0100191 ioep_fpga_print_info(0);
Dirk Eibachf74a0272014-11-13 19:21:18 +0100192 osd_probe(0);
Dirk Eibach981bacd2015-10-28 11:46:35 +0100193#ifdef CONFIG_SYS_OSD_DH
194 osd_probe(4);
195#endif
Dirk Eibachf74a0272014-11-13 19:21:18 +0100196
197 if (slaves <= 0)
198 return 0;
199
200 mclink_fpgacount = slaves;
201
202 for (k = 1; k <= slaves; ++k) {
203 FPGA_GET_REG(k, fpga_features, &fpga_features);
204
Dirk Eibach30d07bb2015-10-28 11:46:33 +0100205 ioep_fpga_print_info(k);
Dirk Eibachf74a0272014-11-13 19:21:18 +0100206 osd_probe(k);
Dirk Eibach981bacd2015-10-28 11:46:35 +0100207#ifdef CONFIG_SYS_OSD_DH
208 osd_probe(k + 4);
209#endif
Dirk Eibachf74a0272014-11-13 19:21:18 +0100210 if (hw_type_cat) {
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500211 int retval;
212 struct mii_dev *mdiodev = mdio_alloc();
Mario Six3809c472019-03-29 10:18:06 +0100213
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500214 if (!mdiodev)
215 return -ENOMEM;
216 strncpy(mdiodev->name, bb_miiphy_buses[k].name,
217 MDIO_NAME_LEN);
218 mdiodev->read = bb_miiphy_read;
219 mdiodev->write = bb_miiphy_write;
220
221 retval = mdio_register(mdiodev);
222 if (retval < 0)
223 return retval;
Dirk Eibachf74a0272014-11-13 19:21:18 +0100224 setup_88e1514(bb_miiphy_buses[k].name, 0);
225 }
226 }
227
Dirk Eibach94594332015-10-28 11:46:36 +0100228 for (k = 0; k < ARRAY_SIZE(hrcon_fans); ++k) {
229 i2c_set_bus_num(hrcon_fans[k].bus);
230 init_fan_controller(hrcon_fans[k].addr);
231 }
232
Dirk Eibachf74a0272014-11-13 19:21:18 +0100233 return 0;
234}
235
236/*
Dirk Eibach981bacd2015-10-28 11:46:35 +0100237 * provide access to fpga gpios and controls (for I2C bitbang)
Dirk Eibachf74a0272014-11-13 19:21:18 +0100238 * (these may look all too simple but make iocon.h much more readable)
239 */
Mario Six3809c472019-03-29 10:18:06 +0100240void fpga_gpio_set(uint bus, int pin)
Dirk Eibachf74a0272014-11-13 19:21:18 +0100241{
Dirk Eibach981bacd2015-10-28 11:46:35 +0100242 FPGA_SET_REG(bus >= 4 ? (bus - 4) : bus, gpio.set, pin);
Dirk Eibachf74a0272014-11-13 19:21:18 +0100243}
244
Mario Six3809c472019-03-29 10:18:06 +0100245void fpga_gpio_clear(uint bus, int pin)
Dirk Eibachf74a0272014-11-13 19:21:18 +0100246{
Dirk Eibach981bacd2015-10-28 11:46:35 +0100247 FPGA_SET_REG(bus >= 4 ? (bus - 4) : bus, gpio.clear, pin);
Dirk Eibachf74a0272014-11-13 19:21:18 +0100248}
249
Mario Six3809c472019-03-29 10:18:06 +0100250int fpga_gpio_get(uint bus, int pin)
Dirk Eibachf74a0272014-11-13 19:21:18 +0100251{
252 u16 val;
253
Dirk Eibach981bacd2015-10-28 11:46:35 +0100254 FPGA_GET_REG(bus >= 4 ? (bus - 4) : bus, gpio.read, &val);
Dirk Eibachf74a0272014-11-13 19:21:18 +0100255
256 return val & pin;
257}
258
Mario Six3809c472019-03-29 10:18:06 +0100259void fpga_control_set(uint bus, int pin)
Dirk Eibach981bacd2015-10-28 11:46:35 +0100260{
261 u16 val;
262
263 FPGA_GET_REG(bus >= 4 ? (bus - 4) : bus, control, &val);
264 FPGA_SET_REG(bus >= 4 ? (bus - 4) : bus, control, val | pin);
265}
266
Mario Six3809c472019-03-29 10:18:06 +0100267void fpga_control_clear(uint bus, int pin)
Dirk Eibach981bacd2015-10-28 11:46:35 +0100268{
269 u16 val;
270
271 FPGA_GET_REG(bus >= 4 ? (bus - 4) : bus, control, &val);
272 FPGA_SET_REG(bus >= 4 ? (bus - 4) : bus, control, val & ~pin);
273}
274
Dirk Eibachf74a0272014-11-13 19:21:18 +0100275void mpc8308_init(void)
276{
277 pca9698_direction_output(0x20, 4, 1);
278}
279
Mario Six3809c472019-03-29 10:18:06 +0100280void mpc8308_set_fpga_reset(uint state)
Dirk Eibachf74a0272014-11-13 19:21:18 +0100281{
282 pca9698_set_value(0x20, 4, state ? 0 : 1);
283}
284
285void mpc8308_setup_hw(void)
286{
287 immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
288
289 /*
290 * set "startup-finished"-gpios
291 */
Mario Sixae0feaa2019-03-29 10:18:07 +0100292 setbits_be32(&immr->gpio[0].dir, BIT(31 - 11) | BIT(31 - 12));
293 setbits_gpio0_out(BIT(31 - 12));
Dirk Eibachf74a0272014-11-13 19:21:18 +0100294}
295
Mario Six3809c472019-03-29 10:18:06 +0100296int mpc8308_get_fpga_done(uint fpga)
Dirk Eibachf74a0272014-11-13 19:21:18 +0100297{
298 return pca9698_get_value(0x20, 19);
299}
300
301#ifdef CONFIG_FSL_ESDHC
302int board_mmc_init(bd_t *bd)
303{
304 immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
305 sysconf83xx_t *sysconf = &immr->sysconf;
306
307 /* Enable cache snooping in eSDHC system configuration register */
308 out_be32(&sysconf->sdhccr, 0x02000000);
309
310 return fsl_esdhc_mmc_init(bd);
311}
312#endif
313
314static struct pci_region pcie_regions_0[] = {
315 {
316 .bus_start = CONFIG_SYS_PCIE1_MEM_BASE,
317 .phys_start = CONFIG_SYS_PCIE1_MEM_PHYS,
318 .size = CONFIG_SYS_PCIE1_MEM_SIZE,
319 .flags = PCI_REGION_MEM,
320 },
321 {
322 .bus_start = CONFIG_SYS_PCIE1_IO_BASE,
323 .phys_start = CONFIG_SYS_PCIE1_IO_PHYS,
324 .size = CONFIG_SYS_PCIE1_IO_SIZE,
325 .flags = PCI_REGION_IO,
326 },
327};
328
329void pci_init_board(void)
330{
331 immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
332 sysconf83xx_t *sysconf = &immr->sysconf;
333 law83xx_t *pcie_law = sysconf->pcielaw;
334 struct pci_region *pcie_reg[] = { pcie_regions_0 };
335
336 fsl_setup_serdes(CONFIG_FSL_SERDES1, FSL_SERDES_PROTO_PEX,
337 FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V);
338
339 /* Deassert the resets in the control register */
340 out_be32(&sysconf->pecr1, 0xE0008000);
341 udelay(2000);
342
343 /* Configure PCI Express Local Access Windows */
344 out_be32(&pcie_law[0].bar, CONFIG_SYS_PCIE1_BASE & LAWBAR_BAR);
345 out_be32(&pcie_law[0].ar, LBLAWAR_EN | LBLAWAR_512MB);
346
347 mpc83xx_pcie_init(1, pcie_reg);
348}
349
350ulong board_flash_get_legacy(ulong base, int banknum, flash_info_t *info)
351{
352 info->portwidth = FLASH_CFI_16BIT;
353 info->chipwidth = FLASH_CFI_BY16;
354 info->interface = FLASH_CFI_X16;
355 return 1;
356}
357
358#if defined(CONFIG_OF_BOARD_SETUP)
Simon Glass2aec3cc2014-10-23 18:58:47 -0600359int ft_board_setup(void *blob, bd_t *bd)
Dirk Eibachf74a0272014-11-13 19:21:18 +0100360{
361 ft_cpu_setup(blob, bd);
Sriram Dash9fd465c2016-09-16 17:12:15 +0530362 fsl_fdt_fixup_dr_usb(blob, bd);
Dirk Eibachf74a0272014-11-13 19:21:18 +0100363 fdt_fixup_esdhc(blob, bd);
Simon Glass2aec3cc2014-10-23 18:58:47 -0600364
365 return 0;
Dirk Eibachf74a0272014-11-13 19:21:18 +0100366}
367#endif
368
369/*
370 * FPGA MII bitbang implementation
371 */
372
373struct fpga_mii {
Mario Six3809c472019-03-29 10:18:06 +0100374 uint fpga;
Dirk Eibachf74a0272014-11-13 19:21:18 +0100375 int mdio;
376} fpga_mii[] = {
377 { 0, 1},
378 { 1, 1},
379 { 2, 1},
380 { 3, 1},
381};
382
383static int mii_dummy_init(struct bb_miiphy_bus *bus)
384{
385 return 0;
386}
387
388static int mii_mdio_active(struct bb_miiphy_bus *bus)
389{
390 struct fpga_mii *fpga_mii = bus->priv;
391
392 if (fpga_mii->mdio)
393 FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDIO);
394 else
395 FPGA_SET_REG(fpga_mii->fpga, gpio.clear, GPIO_MDIO);
396
397 return 0;
398}
399
400static int mii_mdio_tristate(struct bb_miiphy_bus *bus)
401{
402 struct fpga_mii *fpga_mii = bus->priv;
403
404 FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDIO);
405
406 return 0;
407}
408
409static int mii_set_mdio(struct bb_miiphy_bus *bus, int v)
410{
411 struct fpga_mii *fpga_mii = bus->priv;
412
413 if (v)
414 FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDIO);
415 else
416 FPGA_SET_REG(fpga_mii->fpga, gpio.clear, GPIO_MDIO);
417
418 fpga_mii->mdio = v;
419
420 return 0;
421}
422
423static int mii_get_mdio(struct bb_miiphy_bus *bus, int *v)
424{
425 u16 gpio;
426 struct fpga_mii *fpga_mii = bus->priv;
427
428 FPGA_GET_REG(fpga_mii->fpga, gpio.read, &gpio);
429
430 *v = ((gpio & GPIO_MDIO) != 0);
431
432 return 0;
433}
434
435static int mii_set_mdc(struct bb_miiphy_bus *bus, int v)
436{
437 struct fpga_mii *fpga_mii = bus->priv;
438
439 if (v)
440 FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDC);
441 else
442 FPGA_SET_REG(fpga_mii->fpga, gpio.clear, GPIO_MDC);
443
444 return 0;
445}
446
447static int mii_delay(struct bb_miiphy_bus *bus)
448{
449 udelay(1);
450
451 return 0;
452}
453
454struct bb_miiphy_bus bb_miiphy_buses[] = {
455 {
456 .name = "board0",
457 .init = mii_dummy_init,
458 .mdio_active = mii_mdio_active,
459 .mdio_tristate = mii_mdio_tristate,
460 .set_mdio = mii_set_mdio,
461 .get_mdio = mii_get_mdio,
462 .set_mdc = mii_set_mdc,
463 .delay = mii_delay,
464 .priv = &fpga_mii[0],
465 },
466 {
467 .name = "board1",
468 .init = mii_dummy_init,
469 .mdio_active = mii_mdio_active,
470 .mdio_tristate = mii_mdio_tristate,
471 .set_mdio = mii_set_mdio,
472 .get_mdio = mii_get_mdio,
473 .set_mdc = mii_set_mdc,
474 .delay = mii_delay,
475 .priv = &fpga_mii[1],
476 },
477 {
478 .name = "board2",
479 .init = mii_dummy_init,
480 .mdio_active = mii_mdio_active,
481 .mdio_tristate = mii_mdio_tristate,
482 .set_mdio = mii_set_mdio,
483 .get_mdio = mii_get_mdio,
484 .set_mdc = mii_set_mdc,
485 .delay = mii_delay,
486 .priv = &fpga_mii[2],
487 },
488 {
489 .name = "board3",
490 .init = mii_dummy_init,
491 .mdio_active = mii_mdio_active,
492 .mdio_tristate = mii_mdio_tristate,
493 .set_mdio = mii_set_mdio,
494 .get_mdio = mii_get_mdio,
495 .set_mdc = mii_set_mdc,
496 .delay = mii_delay,
497 .priv = &fpga_mii[3],
498 },
499};
500
Mario Six3809c472019-03-29 10:18:06 +0100501int bb_miiphy_buses_num = ARRAY_SIZE(bb_miiphy_buses);