blob: d1ed273a0831c5acf1a8768fbf5f2b136456005e [file] [log] [blame]
Dirk Eibach50dcf892014-11-13 19:21:18 +01001/*
2 * (C) Copyright 2014
Mario Sixd38826a2018-03-06 08:04:58 +01003 * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
Dirk Eibach50dcf892014-11-13 19:21:18 +01004 *
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>
Masahiro Yamadab08c8c42018-03-05 01:20:11 +090012#include <linux/libfdt.h>
Dirk Eibach50dcf892014-11-13 19:21:18 +010013#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
Dirk Eibachd4e58882015-10-28 11:46:33 +010025#include "../common/ioep-fpga.h"
Dirk Eibach50dcf892014-11-13 19:21:18 +010026#include "../common/osd.h"
27#include "../common/mclink.h"
28#include "../common/phy.h"
Dirk Eibach5c3b6dc2015-10-28 11:46:36 +010029#include "../common/fanctrl.h"
Dirk Eibach50dcf892014-11-13 19:21:18 +010030
31#include <pca953x.h>
32#include <pca9698.h>
33
34#include <miiphy.h>
35
Dirk Eibach50dcf892014-11-13 19:21:18 +010036#define MAX_MUX_CHANNELS 2
37
38enum {
Dirk Eibach50dcf892014-11-13 19:21:18 +010039 MCFPGA_DONE = 1 << 0,
40 MCFPGA_INIT_N = 1 << 1,
41 MCFPGA_PROGRAM_N = 1 << 2,
42 MCFPGA_UPDATE_ENABLE_N = 1 << 3,
43 MCFPGA_RESET_N = 1 << 4,
44};
45
46enum {
47 GPIO_MDC = 1 << 14,
48 GPIO_MDIO = 1 << 15,
49};
50
51unsigned int mclink_fpgacount;
52struct ihs_fpga *fpga_ptr[] = CONFIG_SYS_FPGA_PTR;
53
Dirk Eibach5c3b6dc2015-10-28 11:46:36 +010054struct {
55 u8 bus;
56 u8 addr;
57} hrcon_fans[] = CONFIG_HRCON_FANS;
58
Dirk Eibach50dcf892014-11-13 19:21:18 +010059int fpga_set_reg(u32 fpga, u16 *reg, off_t regoff, u16 data)
60{
61 int res;
62
63 switch (fpga) {
64 case 0:
65 out_le16(reg, data);
66 break;
67 default:
68 res = mclink_send(fpga - 1, regoff, data);
69 if (res < 0) {
70 printf("mclink_send reg %02lx data %04x returned %d\n",
71 regoff, data, res);
72 return res;
73 }
74 break;
75 }
76
77 return 0;
78}
79
80int fpga_get_reg(u32 fpga, u16 *reg, off_t regoff, u16 *data)
81{
82 int res;
83
84 switch (fpga) {
85 case 0:
86 *data = in_le16(reg);
87 break;
88 default:
89 if (fpga > mclink_fpgacount)
90 return -EINVAL;
91 res = mclink_receive(fpga - 1, regoff, data);
92 if (res < 0) {
93 printf("mclink_receive reg %02lx returned %d\n",
94 regoff, res);
95 return res;
96 }
97 }
98
99 return 0;
100}
101
102int checkboard(void)
103{
Simon Glass00caae62017-08-03 12:22:12 -0600104 char *s = env_get("serial#");
Dirk Eibach50dcf892014-11-13 19:21:18 +0100105 bool hw_type_cat = pca9698_get_value(0x20, 20);
106
107 puts("Board: ");
108
109 printf("HRCon %s", hw_type_cat ? "CAT" : "Fiber");
110
111 if (s != NULL) {
112 puts(", serial# ");
113 puts(s);
114 }
115
116 puts("\n");
117
118 return 0;
119}
120
Dirk Eibach50dcf892014-11-13 19:21:18 +0100121int last_stage_init(void)
122{
123 int slaves;
124 unsigned int k;
125 unsigned int mux_ch;
Dirk Eibachb847f5b2015-10-28 11:46:34 +0100126 unsigned char mclink_controllers[] = { 0x3c, 0x3d, 0x3e };
Dirk Eibach50dcf892014-11-13 19:21:18 +0100127 u16 fpga_features;
128 bool hw_type_cat = pca9698_get_value(0x20, 20);
129 bool ch0_rgmii2_present = false;
130
131 FPGA_GET_REG(0, fpga_features, &fpga_features);
132
133 /* Turn on Parade DP501 */
134 pca9698_direction_output(0x20, 10, 1);
Dirk Eibach7ed45d32015-10-28 11:46:35 +0100135 pca9698_direction_output(0x20, 11, 1);
Dirk Eibach50dcf892014-11-13 19:21:18 +0100136
137 ch0_rgmii2_present = !pca9698_get_value(0x20, 30);
138
Dirk Eibachb847f5b2015-10-28 11:46:34 +0100139 /* wait for FPGA done, then reset FPGA */
Dirk Eibach50dcf892014-11-13 19:21:18 +0100140 for (k = 0; k < ARRAY_SIZE(mclink_controllers); ++k) {
141 unsigned int ctr = 0;
142
143 if (i2c_probe(mclink_controllers[k]))
144 continue;
145
146 while (!(pca953x_get_val(mclink_controllers[k])
147 & MCFPGA_DONE)) {
148 udelay(100000);
149 if (ctr++ > 5) {
150 printf("no done for mclink_controller %d\n", k);
151 break;
152 }
153 }
Dirk Eibachb847f5b2015-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 Eibach50dcf892014-11-13 19:21:18 +0100160 }
161
162 if (hw_type_cat) {
Joe Hershberger5a49f172016-08-08 11:28:38 -0500163 int retval;
164 struct mii_dev *mdiodev = mdio_alloc();
165 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 Eibach50dcf892014-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 */
183 udelay(500000);
184
185 mclink_fpgacount = CONFIG_SYS_MCLINK_MAX;
186 slaves = mclink_probe();
187 mclink_fpgacount = 0;
188
Dirk Eibachd4e58882015-10-28 11:46:33 +0100189 ioep_fpga_print_info(0);
Dirk Eibach50dcf892014-11-13 19:21:18 +0100190 osd_probe(0);
Dirk Eibach7ed45d32015-10-28 11:46:35 +0100191#ifdef CONFIG_SYS_OSD_DH
192 osd_probe(4);
193#endif
Dirk Eibach50dcf892014-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 Eibachd4e58882015-10-28 11:46:33 +0100203 ioep_fpga_print_info(k);
Dirk Eibach50dcf892014-11-13 19:21:18 +0100204 osd_probe(k);
Dirk Eibach7ed45d32015-10-28 11:46:35 +0100205#ifdef CONFIG_SYS_OSD_DH
206 osd_probe(k + 4);
207#endif
Dirk Eibach50dcf892014-11-13 19:21:18 +0100208 if (hw_type_cat) {
Joe Hershberger5a49f172016-08-08 11:28:38 -0500209 int retval;
210 struct mii_dev *mdiodev = mdio_alloc();
211 if (!mdiodev)
212 return -ENOMEM;
213 strncpy(mdiodev->name, bb_miiphy_buses[k].name,
214 MDIO_NAME_LEN);
215 mdiodev->read = bb_miiphy_read;
216 mdiodev->write = bb_miiphy_write;
217
218 retval = mdio_register(mdiodev);
219 if (retval < 0)
220 return retval;
Dirk Eibach50dcf892014-11-13 19:21:18 +0100221 setup_88e1514(bb_miiphy_buses[k].name, 0);
222 }
223 }
224
Dirk Eibach5c3b6dc2015-10-28 11:46:36 +0100225 for (k = 0; k < ARRAY_SIZE(hrcon_fans); ++k) {
226 i2c_set_bus_num(hrcon_fans[k].bus);
227 init_fan_controller(hrcon_fans[k].addr);
228 }
229
Dirk Eibach50dcf892014-11-13 19:21:18 +0100230 return 0;
231}
232
233/*
Dirk Eibach7ed45d32015-10-28 11:46:35 +0100234 * provide access to fpga gpios and controls (for I2C bitbang)
Dirk Eibach50dcf892014-11-13 19:21:18 +0100235 * (these may look all too simple but make iocon.h much more readable)
236 */
237void fpga_gpio_set(unsigned int bus, int pin)
238{
Dirk Eibach7ed45d32015-10-28 11:46:35 +0100239 FPGA_SET_REG(bus >= 4 ? (bus - 4) : bus, gpio.set, pin);
Dirk Eibach50dcf892014-11-13 19:21:18 +0100240}
241
242void fpga_gpio_clear(unsigned int bus, int pin)
243{
Dirk Eibach7ed45d32015-10-28 11:46:35 +0100244 FPGA_SET_REG(bus >= 4 ? (bus - 4) : bus, gpio.clear, pin);
Dirk Eibach50dcf892014-11-13 19:21:18 +0100245}
246
247int fpga_gpio_get(unsigned int bus, int pin)
248{
249 u16 val;
250
Dirk Eibach7ed45d32015-10-28 11:46:35 +0100251 FPGA_GET_REG(bus >= 4 ? (bus - 4) : bus, gpio.read, &val);
Dirk Eibach50dcf892014-11-13 19:21:18 +0100252
253 return val & pin;
254}
255
Dirk Eibach7ed45d32015-10-28 11:46:35 +0100256void fpga_control_set(unsigned int bus, int pin)
257{
258 u16 val;
259
260 FPGA_GET_REG(bus >= 4 ? (bus - 4) : bus, control, &val);
261 FPGA_SET_REG(bus >= 4 ? (bus - 4) : bus, control, val | pin);
262}
263
264void fpga_control_clear(unsigned int bus, int pin)
265{
266 u16 val;
267
268 FPGA_GET_REG(bus >= 4 ? (bus - 4) : bus, control, &val);
269 FPGA_SET_REG(bus >= 4 ? (bus - 4) : bus, control, val & ~pin);
270}
271
Dirk Eibach50dcf892014-11-13 19:21:18 +0100272void mpc8308_init(void)
273{
274 pca9698_direction_output(0x20, 4, 1);
275}
276
277void mpc8308_set_fpga_reset(unsigned state)
278{
279 pca9698_set_value(0x20, 4, state ? 0 : 1);
280}
281
282void mpc8308_setup_hw(void)
283{
284 immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
285
286 /*
287 * set "startup-finished"-gpios
288 */
289 setbits_be32(&immr->gpio[0].dir, (1 << (31-11)) | (1 << (31-12)));
290 setbits_be32(&immr->gpio[0].dat, 1 << (31-12));
291}
292
293int mpc8308_get_fpga_done(unsigned fpga)
294{
295 return pca9698_get_value(0x20, 19);
296}
297
298#ifdef CONFIG_FSL_ESDHC
299int board_mmc_init(bd_t *bd)
300{
301 immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
302 sysconf83xx_t *sysconf = &immr->sysconf;
303
304 /* Enable cache snooping in eSDHC system configuration register */
305 out_be32(&sysconf->sdhccr, 0x02000000);
306
307 return fsl_esdhc_mmc_init(bd);
308}
309#endif
310
311static struct pci_region pcie_regions_0[] = {
312 {
313 .bus_start = CONFIG_SYS_PCIE1_MEM_BASE,
314 .phys_start = CONFIG_SYS_PCIE1_MEM_PHYS,
315 .size = CONFIG_SYS_PCIE1_MEM_SIZE,
316 .flags = PCI_REGION_MEM,
317 },
318 {
319 .bus_start = CONFIG_SYS_PCIE1_IO_BASE,
320 .phys_start = CONFIG_SYS_PCIE1_IO_PHYS,
321 .size = CONFIG_SYS_PCIE1_IO_SIZE,
322 .flags = PCI_REGION_IO,
323 },
324};
325
326void pci_init_board(void)
327{
328 immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
329 sysconf83xx_t *sysconf = &immr->sysconf;
330 law83xx_t *pcie_law = sysconf->pcielaw;
331 struct pci_region *pcie_reg[] = { pcie_regions_0 };
332
333 fsl_setup_serdes(CONFIG_FSL_SERDES1, FSL_SERDES_PROTO_PEX,
334 FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V);
335
336 /* Deassert the resets in the control register */
337 out_be32(&sysconf->pecr1, 0xE0008000);
338 udelay(2000);
339
340 /* Configure PCI Express Local Access Windows */
341 out_be32(&pcie_law[0].bar, CONFIG_SYS_PCIE1_BASE & LAWBAR_BAR);
342 out_be32(&pcie_law[0].ar, LBLAWAR_EN | LBLAWAR_512MB);
343
344 mpc83xx_pcie_init(1, pcie_reg);
345}
346
347ulong board_flash_get_legacy(ulong base, int banknum, flash_info_t *info)
348{
349 info->portwidth = FLASH_CFI_16BIT;
350 info->chipwidth = FLASH_CFI_BY16;
351 info->interface = FLASH_CFI_X16;
352 return 1;
353}
354
355#if defined(CONFIG_OF_BOARD_SETUP)
Simon Glasse895a4b2014-10-23 18:58:47 -0600356int ft_board_setup(void *blob, bd_t *bd)
Dirk Eibach50dcf892014-11-13 19:21:18 +0100357{
358 ft_cpu_setup(blob, bd);
Sriram Dasha5c289b2016-09-16 17:12:15 +0530359 fsl_fdt_fixup_dr_usb(blob, bd);
Dirk Eibach50dcf892014-11-13 19:21:18 +0100360 fdt_fixup_esdhc(blob, bd);
Simon Glasse895a4b2014-10-23 18:58:47 -0600361
362 return 0;
Dirk Eibach50dcf892014-11-13 19:21:18 +0100363}
364#endif
365
366/*
367 * FPGA MII bitbang implementation
368 */
369
370struct fpga_mii {
371 unsigned fpga;
372 int mdio;
373} fpga_mii[] = {
374 { 0, 1},
375 { 1, 1},
376 { 2, 1},
377 { 3, 1},
378};
379
380static int mii_dummy_init(struct bb_miiphy_bus *bus)
381{
382 return 0;
383}
384
385static int mii_mdio_active(struct bb_miiphy_bus *bus)
386{
387 struct fpga_mii *fpga_mii = bus->priv;
388
389 if (fpga_mii->mdio)
390 FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDIO);
391 else
392 FPGA_SET_REG(fpga_mii->fpga, gpio.clear, GPIO_MDIO);
393
394 return 0;
395}
396
397static int mii_mdio_tristate(struct bb_miiphy_bus *bus)
398{
399 struct fpga_mii *fpga_mii = bus->priv;
400
401 FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDIO);
402
403 return 0;
404}
405
406static int mii_set_mdio(struct bb_miiphy_bus *bus, int v)
407{
408 struct fpga_mii *fpga_mii = bus->priv;
409
410 if (v)
411 FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDIO);
412 else
413 FPGA_SET_REG(fpga_mii->fpga, gpio.clear, GPIO_MDIO);
414
415 fpga_mii->mdio = v;
416
417 return 0;
418}
419
420static int mii_get_mdio(struct bb_miiphy_bus *bus, int *v)
421{
422 u16 gpio;
423 struct fpga_mii *fpga_mii = bus->priv;
424
425 FPGA_GET_REG(fpga_mii->fpga, gpio.read, &gpio);
426
427 *v = ((gpio & GPIO_MDIO) != 0);
428
429 return 0;
430}
431
432static int mii_set_mdc(struct bb_miiphy_bus *bus, int v)
433{
434 struct fpga_mii *fpga_mii = bus->priv;
435
436 if (v)
437 FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDC);
438 else
439 FPGA_SET_REG(fpga_mii->fpga, gpio.clear, GPIO_MDC);
440
441 return 0;
442}
443
444static int mii_delay(struct bb_miiphy_bus *bus)
445{
446 udelay(1);
447
448 return 0;
449}
450
451struct bb_miiphy_bus bb_miiphy_buses[] = {
452 {
453 .name = "board0",
454 .init = mii_dummy_init,
455 .mdio_active = mii_mdio_active,
456 .mdio_tristate = mii_mdio_tristate,
457 .set_mdio = mii_set_mdio,
458 .get_mdio = mii_get_mdio,
459 .set_mdc = mii_set_mdc,
460 .delay = mii_delay,
461 .priv = &fpga_mii[0],
462 },
463 {
464 .name = "board1",
465 .init = mii_dummy_init,
466 .mdio_active = mii_mdio_active,
467 .mdio_tristate = mii_mdio_tristate,
468 .set_mdio = mii_set_mdio,
469 .get_mdio = mii_get_mdio,
470 .set_mdc = mii_set_mdc,
471 .delay = mii_delay,
472 .priv = &fpga_mii[1],
473 },
474 {
475 .name = "board2",
476 .init = mii_dummy_init,
477 .mdio_active = mii_mdio_active,
478 .mdio_tristate = mii_mdio_tristate,
479 .set_mdio = mii_set_mdio,
480 .get_mdio = mii_get_mdio,
481 .set_mdc = mii_set_mdc,
482 .delay = mii_delay,
483 .priv = &fpga_mii[2],
484 },
485 {
486 .name = "board3",
487 .init = mii_dummy_init,
488 .mdio_active = mii_mdio_active,
489 .mdio_tristate = mii_mdio_tristate,
490 .set_mdio = mii_set_mdio,
491 .get_mdio = mii_get_mdio,
492 .set_mdc = mii_set_mdc,
493 .delay = mii_delay,
494 .priv = &fpga_mii[3],
495 },
496};
497
498int bb_miiphy_buses_num = sizeof(bb_miiphy_buses) /
499 sizeof(bb_miiphy_buses[0]);