blob: d14a28ec94d0f6fa1960fb182c71cbbf06c05d4e [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>
8#include <hwconfig.h>
9#include <i2c.h>
10#include <spi.h>
Masahiro Yamada75f82d02018-03-05 01:20:11 +090011#include <linux/libfdt.h>
Dirk Eibachf74a0272014-11-13 19:21:18 +010012#include <fdt_support.h>
13#include <pci.h>
14#include <mpc83xx.h>
15#include <fsl_esdhc.h>
16#include <asm/io.h>
17#include <asm/fsl_serdes.h>
18#include <asm/fsl_mpc83xx_serdes.h>
19
20#include "mpc8308.h"
21
22#include <gdsys_fpga.h>
23
Dirk Eibach30d07bb2015-10-28 11:46:33 +010024#include "../common/ioep-fpga.h"
Dirk Eibachf74a0272014-11-13 19:21:18 +010025#include "../common/osd.h"
26#include "../common/mclink.h"
27#include "../common/phy.h"
Dirk Eibach94594332015-10-28 11:46:36 +010028#include "../common/fanctrl.h"
Dirk Eibachf74a0272014-11-13 19:21:18 +010029
30#include <pca953x.h>
31#include <pca9698.h>
32
33#include <miiphy.h>
34
Dirk Eibachf74a0272014-11-13 19:21:18 +010035#define MAX_MUX_CHANNELS 2
36
37enum {
Mario Six3809c472019-03-29 10:18:06 +010038 MCFPGA_DONE = BIT(0),
39 MCFPGA_INIT_N = BIT(1),
40 MCFPGA_PROGRAM_N = BIT(2),
41 MCFPGA_UPDATE_ENABLE_N = BIT(3),
42 MCFPGA_RESET_N = BIT(4),
Dirk Eibachf74a0272014-11-13 19:21:18 +010043};
44
45enum {
46 GPIO_MDC = 1 << 14,
47 GPIO_MDIO = 1 << 15,
48};
49
Mario Six3809c472019-03-29 10:18:06 +010050uint mclink_fpgacount;
Dirk Eibachf74a0272014-11-13 19:21:18 +010051struct ihs_fpga *fpga_ptr[] = CONFIG_SYS_FPGA_PTR;
52
Dirk Eibach94594332015-10-28 11:46:36 +010053struct {
54 u8 bus;
55 u8 addr;
56} hrcon_fans[] = CONFIG_HRCON_FANS;
57
Dirk Eibachf74a0272014-11-13 19:21:18 +010058int fpga_set_reg(u32 fpga, u16 *reg, off_t regoff, u16 data)
59{
60 int res;
61
62 switch (fpga) {
63 case 0:
64 out_le16(reg, data);
65 break;
66 default:
67 res = mclink_send(fpga - 1, regoff, data);
68 if (res < 0) {
69 printf("mclink_send reg %02lx data %04x returned %d\n",
70 regoff, data, res);
71 return res;
72 }
73 break;
74 }
75
76 return 0;
77}
78
79int fpga_get_reg(u32 fpga, u16 *reg, off_t regoff, u16 *data)
80{
81 int res;
82
83 switch (fpga) {
84 case 0:
85 *data = in_le16(reg);
86 break;
87 default:
88 if (fpga > mclink_fpgacount)
89 return -EINVAL;
90 res = mclink_receive(fpga - 1, regoff, data);
91 if (res < 0) {
92 printf("mclink_receive reg %02lx returned %d\n",
93 regoff, res);
94 return res;
95 }
96 }
97
98 return 0;
99}
100
101int checkboard(void)
102{
Simon Glass64b723f2017-08-03 12:22:12 -0600103 char *s = env_get("serial#");
Dirk Eibachf74a0272014-11-13 19:21:18 +0100104 bool hw_type_cat = pca9698_get_value(0x20, 20);
105
106 puts("Board: ");
107
108 printf("HRCon %s", hw_type_cat ? "CAT" : "Fiber");
109
Mario Six3809c472019-03-29 10:18:06 +0100110 if (s) {
Dirk Eibachf74a0272014-11-13 19:21:18 +0100111 puts(", serial# ");
112 puts(s);
113 }
114
115 puts("\n");
116
117 return 0;
118}
119
Dirk Eibachf74a0272014-11-13 19:21:18 +0100120int last_stage_init(void)
121{
122 int slaves;
Mario Six3809c472019-03-29 10:18:06 +0100123 uint k;
124 uchar mclink_controllers[] = { 0x3c, 0x3d, 0x3e };
Dirk Eibachf74a0272014-11-13 19:21:18 +0100125 u16 fpga_features;
126 bool hw_type_cat = pca9698_get_value(0x20, 20);
Mario Six3809c472019-03-29 10:18:06 +0100127 bool ch0_rgmii2_present;
Dirk Eibachf74a0272014-11-13 19:21:18 +0100128
129 FPGA_GET_REG(0, fpga_features, &fpga_features);
130
131 /* Turn on Parade DP501 */
132 pca9698_direction_output(0x20, 10, 1);
Dirk Eibach981bacd2015-10-28 11:46:35 +0100133 pca9698_direction_output(0x20, 11, 1);
Dirk Eibachf74a0272014-11-13 19:21:18 +0100134
135 ch0_rgmii2_present = !pca9698_get_value(0x20, 30);
136
Dirk Eibach9806a8e2015-10-28 11:46:34 +0100137 /* wait for FPGA done, then reset FPGA */
Dirk Eibachf74a0272014-11-13 19:21:18 +0100138 for (k = 0; k < ARRAY_SIZE(mclink_controllers); ++k) {
Mario Six3809c472019-03-29 10:18:06 +0100139 uint ctr = 0;
Dirk Eibachf74a0272014-11-13 19:21:18 +0100140
141 if (i2c_probe(mclink_controllers[k]))
142 continue;
143
144 while (!(pca953x_get_val(mclink_controllers[k])
145 & MCFPGA_DONE)) {
Mario Six3809c472019-03-29 10:18:06 +0100146 mdelay(100);
Dirk Eibachf74a0272014-11-13 19:21:18 +0100147 if (ctr++ > 5) {
Mario Six3809c472019-03-29 10:18:06 +0100148 printf("no done for mclink_controller %u\n", k);
Dirk Eibachf74a0272014-11-13 19:21:18 +0100149 break;
150 }
151 }
Dirk Eibach9806a8e2015-10-28 11:46:34 +0100152
153 pca953x_set_dir(mclink_controllers[k], MCFPGA_RESET_N, 0);
154 pca953x_set_val(mclink_controllers[k], MCFPGA_RESET_N, 0);
155 udelay(10);
156 pca953x_set_val(mclink_controllers[k], MCFPGA_RESET_N,
157 MCFPGA_RESET_N);
Dirk Eibachf74a0272014-11-13 19:21:18 +0100158 }
159
160 if (hw_type_cat) {
Mario Six3809c472019-03-29 10:18:06 +0100161 uint mux_ch;
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500162 int retval;
163 struct mii_dev *mdiodev = mdio_alloc();
Mario Six3809c472019-03-29 10:18:06 +0100164
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500165 if (!mdiodev)
166 return -ENOMEM;
167 strncpy(mdiodev->name, bb_miiphy_buses[0].name, MDIO_NAME_LEN);
168 mdiodev->read = bb_miiphy_read;
169 mdiodev->write = bb_miiphy_write;
170
171 retval = mdio_register(mdiodev);
172 if (retval < 0)
173 return retval;
Dirk Eibachf74a0272014-11-13 19:21:18 +0100174 for (mux_ch = 0; mux_ch < MAX_MUX_CHANNELS; ++mux_ch) {
175 if ((mux_ch == 1) && !ch0_rgmii2_present)
176 continue;
177
178 setup_88e1514(bb_miiphy_buses[0].name, mux_ch);
179 }
180 }
181
182 /* give slave-PLLs and Parade DP501 some time to be up and running */
Mario Six3809c472019-03-29 10:18:06 +0100183 mdelay(500);
Dirk Eibachf74a0272014-11-13 19:21:18 +0100184
185 mclink_fpgacount = CONFIG_SYS_MCLINK_MAX;
186 slaves = mclink_probe();
187 mclink_fpgacount = 0;
188
Dirk Eibach30d07bb2015-10-28 11:46:33 +0100189 ioep_fpga_print_info(0);
Dirk Eibachf74a0272014-11-13 19:21:18 +0100190 osd_probe(0);
Dirk Eibach981bacd2015-10-28 11:46:35 +0100191#ifdef CONFIG_SYS_OSD_DH
192 osd_probe(4);
193#endif
Dirk Eibachf74a0272014-11-13 19:21:18 +0100194
195 if (slaves <= 0)
196 return 0;
197
198 mclink_fpgacount = slaves;
199
200 for (k = 1; k <= slaves; ++k) {
201 FPGA_GET_REG(k, fpga_features, &fpga_features);
202
Dirk Eibach30d07bb2015-10-28 11:46:33 +0100203 ioep_fpga_print_info(k);
Dirk Eibachf74a0272014-11-13 19:21:18 +0100204 osd_probe(k);
Dirk Eibach981bacd2015-10-28 11:46:35 +0100205#ifdef CONFIG_SYS_OSD_DH
206 osd_probe(k + 4);
207#endif
Dirk Eibachf74a0272014-11-13 19:21:18 +0100208 if (hw_type_cat) {
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500209 int retval;
210 struct mii_dev *mdiodev = mdio_alloc();
Mario Six3809c472019-03-29 10:18:06 +0100211
Joe Hershberger1fbcbed2016-08-08 11:28:38 -0500212 if (!mdiodev)
213 return -ENOMEM;
214 strncpy(mdiodev->name, bb_miiphy_buses[k].name,
215 MDIO_NAME_LEN);
216 mdiodev->read = bb_miiphy_read;
217 mdiodev->write = bb_miiphy_write;
218
219 retval = mdio_register(mdiodev);
220 if (retval < 0)
221 return retval;
Dirk Eibachf74a0272014-11-13 19:21:18 +0100222 setup_88e1514(bb_miiphy_buses[k].name, 0);
223 }
224 }
225
Dirk Eibach94594332015-10-28 11:46:36 +0100226 for (k = 0; k < ARRAY_SIZE(hrcon_fans); ++k) {
227 i2c_set_bus_num(hrcon_fans[k].bus);
228 init_fan_controller(hrcon_fans[k].addr);
229 }
230
Dirk Eibachf74a0272014-11-13 19:21:18 +0100231 return 0;
232}
233
234/*
Dirk Eibach981bacd2015-10-28 11:46:35 +0100235 * provide access to fpga gpios and controls (for I2C bitbang)
Dirk Eibachf74a0272014-11-13 19:21:18 +0100236 * (these may look all too simple but make iocon.h much more readable)
237 */
Mario Six3809c472019-03-29 10:18:06 +0100238void fpga_gpio_set(uint bus, int pin)
Dirk Eibachf74a0272014-11-13 19:21:18 +0100239{
Dirk Eibach981bacd2015-10-28 11:46:35 +0100240 FPGA_SET_REG(bus >= 4 ? (bus - 4) : bus, gpio.set, pin);
Dirk Eibachf74a0272014-11-13 19:21:18 +0100241}
242
Mario Six3809c472019-03-29 10:18:06 +0100243void fpga_gpio_clear(uint bus, int pin)
Dirk Eibachf74a0272014-11-13 19:21:18 +0100244{
Dirk Eibach981bacd2015-10-28 11:46:35 +0100245 FPGA_SET_REG(bus >= 4 ? (bus - 4) : bus, gpio.clear, pin);
Dirk Eibachf74a0272014-11-13 19:21:18 +0100246}
247
Mario Six3809c472019-03-29 10:18:06 +0100248int fpga_gpio_get(uint bus, int pin)
Dirk Eibachf74a0272014-11-13 19:21:18 +0100249{
250 u16 val;
251
Dirk Eibach981bacd2015-10-28 11:46:35 +0100252 FPGA_GET_REG(bus >= 4 ? (bus - 4) : bus, gpio.read, &val);
Dirk Eibachf74a0272014-11-13 19:21:18 +0100253
254 return val & pin;
255}
256
Mario Six3809c472019-03-29 10:18:06 +0100257void fpga_control_set(uint bus, int pin)
Dirk Eibach981bacd2015-10-28 11:46:35 +0100258{
259 u16 val;
260
261 FPGA_GET_REG(bus >= 4 ? (bus - 4) : bus, control, &val);
262 FPGA_SET_REG(bus >= 4 ? (bus - 4) : bus, control, val | pin);
263}
264
Mario Six3809c472019-03-29 10:18:06 +0100265void fpga_control_clear(uint bus, int pin)
Dirk Eibach981bacd2015-10-28 11:46:35 +0100266{
267 u16 val;
268
269 FPGA_GET_REG(bus >= 4 ? (bus - 4) : bus, control, &val);
270 FPGA_SET_REG(bus >= 4 ? (bus - 4) : bus, control, val & ~pin);
271}
272
Dirk Eibachf74a0272014-11-13 19:21:18 +0100273void mpc8308_init(void)
274{
275 pca9698_direction_output(0x20, 4, 1);
276}
277
Mario Six3809c472019-03-29 10:18:06 +0100278void mpc8308_set_fpga_reset(uint state)
Dirk Eibachf74a0272014-11-13 19:21:18 +0100279{
280 pca9698_set_value(0x20, 4, state ? 0 : 1);
281}
282
283void mpc8308_setup_hw(void)
284{
285 immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
286
287 /*
288 * set "startup-finished"-gpios
289 */
Mario Sixae0feaa2019-03-29 10:18:07 +0100290 setbits_be32(&immr->gpio[0].dir, BIT(31 - 11) | BIT(31 - 12));
291 setbits_gpio0_out(BIT(31 - 12));
Dirk Eibachf74a0272014-11-13 19:21:18 +0100292}
293
Mario Six3809c472019-03-29 10:18:06 +0100294int mpc8308_get_fpga_done(uint fpga)
Dirk Eibachf74a0272014-11-13 19:21:18 +0100295{
296 return pca9698_get_value(0x20, 19);
297}
298
299#ifdef CONFIG_FSL_ESDHC
300int board_mmc_init(bd_t *bd)
301{
302 immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
303 sysconf83xx_t *sysconf = &immr->sysconf;
304
305 /* Enable cache snooping in eSDHC system configuration register */
306 out_be32(&sysconf->sdhccr, 0x02000000);
307
308 return fsl_esdhc_mmc_init(bd);
309}
310#endif
311
312static struct pci_region pcie_regions_0[] = {
313 {
314 .bus_start = CONFIG_SYS_PCIE1_MEM_BASE,
315 .phys_start = CONFIG_SYS_PCIE1_MEM_PHYS,
316 .size = CONFIG_SYS_PCIE1_MEM_SIZE,
317 .flags = PCI_REGION_MEM,
318 },
319 {
320 .bus_start = CONFIG_SYS_PCIE1_IO_BASE,
321 .phys_start = CONFIG_SYS_PCIE1_IO_PHYS,
322 .size = CONFIG_SYS_PCIE1_IO_SIZE,
323 .flags = PCI_REGION_IO,
324 },
325};
326
327void pci_init_board(void)
328{
329 immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
330 sysconf83xx_t *sysconf = &immr->sysconf;
331 law83xx_t *pcie_law = sysconf->pcielaw;
332 struct pci_region *pcie_reg[] = { pcie_regions_0 };
333
334 fsl_setup_serdes(CONFIG_FSL_SERDES1, FSL_SERDES_PROTO_PEX,
335 FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V);
336
337 /* Deassert the resets in the control register */
338 out_be32(&sysconf->pecr1, 0xE0008000);
339 udelay(2000);
340
341 /* Configure PCI Express Local Access Windows */
342 out_be32(&pcie_law[0].bar, CONFIG_SYS_PCIE1_BASE & LAWBAR_BAR);
343 out_be32(&pcie_law[0].ar, LBLAWAR_EN | LBLAWAR_512MB);
344
345 mpc83xx_pcie_init(1, pcie_reg);
346}
347
348ulong board_flash_get_legacy(ulong base, int banknum, flash_info_t *info)
349{
350 info->portwidth = FLASH_CFI_16BIT;
351 info->chipwidth = FLASH_CFI_BY16;
352 info->interface = FLASH_CFI_X16;
353 return 1;
354}
355
356#if defined(CONFIG_OF_BOARD_SETUP)
Simon Glass2aec3cc2014-10-23 18:58:47 -0600357int ft_board_setup(void *blob, bd_t *bd)
Dirk Eibachf74a0272014-11-13 19:21:18 +0100358{
359 ft_cpu_setup(blob, bd);
Sriram Dash9fd465c2016-09-16 17:12:15 +0530360 fsl_fdt_fixup_dr_usb(blob, bd);
Dirk Eibachf74a0272014-11-13 19:21:18 +0100361 fdt_fixup_esdhc(blob, bd);
Simon Glass2aec3cc2014-10-23 18:58:47 -0600362
363 return 0;
Dirk Eibachf74a0272014-11-13 19:21:18 +0100364}
365#endif
366
367/*
368 * FPGA MII bitbang implementation
369 */
370
371struct fpga_mii {
Mario Six3809c472019-03-29 10:18:06 +0100372 uint fpga;
Dirk Eibachf74a0272014-11-13 19:21:18 +0100373 int mdio;
374} fpga_mii[] = {
375 { 0, 1},
376 { 1, 1},
377 { 2, 1},
378 { 3, 1},
379};
380
381static int mii_dummy_init(struct bb_miiphy_bus *bus)
382{
383 return 0;
384}
385
386static int mii_mdio_active(struct bb_miiphy_bus *bus)
387{
388 struct fpga_mii *fpga_mii = bus->priv;
389
390 if (fpga_mii->mdio)
391 FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDIO);
392 else
393 FPGA_SET_REG(fpga_mii->fpga, gpio.clear, GPIO_MDIO);
394
395 return 0;
396}
397
398static int mii_mdio_tristate(struct bb_miiphy_bus *bus)
399{
400 struct fpga_mii *fpga_mii = bus->priv;
401
402 FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDIO);
403
404 return 0;
405}
406
407static int mii_set_mdio(struct bb_miiphy_bus *bus, int v)
408{
409 struct fpga_mii *fpga_mii = bus->priv;
410
411 if (v)
412 FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDIO);
413 else
414 FPGA_SET_REG(fpga_mii->fpga, gpio.clear, GPIO_MDIO);
415
416 fpga_mii->mdio = v;
417
418 return 0;
419}
420
421static int mii_get_mdio(struct bb_miiphy_bus *bus, int *v)
422{
423 u16 gpio;
424 struct fpga_mii *fpga_mii = bus->priv;
425
426 FPGA_GET_REG(fpga_mii->fpga, gpio.read, &gpio);
427
428 *v = ((gpio & GPIO_MDIO) != 0);
429
430 return 0;
431}
432
433static int mii_set_mdc(struct bb_miiphy_bus *bus, int v)
434{
435 struct fpga_mii *fpga_mii = bus->priv;
436
437 if (v)
438 FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDC);
439 else
440 FPGA_SET_REG(fpga_mii->fpga, gpio.clear, GPIO_MDC);
441
442 return 0;
443}
444
445static int mii_delay(struct bb_miiphy_bus *bus)
446{
447 udelay(1);
448
449 return 0;
450}
451
452struct bb_miiphy_bus bb_miiphy_buses[] = {
453 {
454 .name = "board0",
455 .init = mii_dummy_init,
456 .mdio_active = mii_mdio_active,
457 .mdio_tristate = mii_mdio_tristate,
458 .set_mdio = mii_set_mdio,
459 .get_mdio = mii_get_mdio,
460 .set_mdc = mii_set_mdc,
461 .delay = mii_delay,
462 .priv = &fpga_mii[0],
463 },
464 {
465 .name = "board1",
466 .init = mii_dummy_init,
467 .mdio_active = mii_mdio_active,
468 .mdio_tristate = mii_mdio_tristate,
469 .set_mdio = mii_set_mdio,
470 .get_mdio = mii_get_mdio,
471 .set_mdc = mii_set_mdc,
472 .delay = mii_delay,
473 .priv = &fpga_mii[1],
474 },
475 {
476 .name = "board2",
477 .init = mii_dummy_init,
478 .mdio_active = mii_mdio_active,
479 .mdio_tristate = mii_mdio_tristate,
480 .set_mdio = mii_set_mdio,
481 .get_mdio = mii_get_mdio,
482 .set_mdc = mii_set_mdc,
483 .delay = mii_delay,
484 .priv = &fpga_mii[2],
485 },
486 {
487 .name = "board3",
488 .init = mii_dummy_init,
489 .mdio_active = mii_mdio_active,
490 .mdio_tristate = mii_mdio_tristate,
491 .set_mdio = mii_set_mdio,
492 .get_mdio = mii_get_mdio,
493 .set_mdc = mii_set_mdc,
494 .delay = mii_delay,
495 .priv = &fpga_mii[3],
496 },
497};
498
Mario Six3809c472019-03-29 10:18:06 +0100499int bb_miiphy_buses_num = ARRAY_SIZE(bb_miiphy_buses);