xref: /rk3399_rockchip-uboot/board/gdsys/mpc8308/hrcon.c (revision 0e00a84cdedf7a1949486746225b35984b351eca)
150dcf89dSDirk Eibach /*
250dcf89dSDirk Eibach  * (C) Copyright 2014
350dcf89dSDirk Eibach  * Dirk Eibach,  Guntermann & Drunck GmbH, eibach@gdsys.de
450dcf89dSDirk Eibach  *
550dcf89dSDirk Eibach  * SPDX-License-Identifier:	GPL-2.0+
650dcf89dSDirk Eibach  */
750dcf89dSDirk Eibach 
850dcf89dSDirk Eibach #include <common.h>
950dcf89dSDirk Eibach #include <hwconfig.h>
1050dcf89dSDirk Eibach #include <i2c.h>
1150dcf89dSDirk Eibach #include <spi.h>
12*0e00a84cSMasahiro Yamada #include <linux/libfdt.h>
1350dcf89dSDirk Eibach #include <fdt_support.h>
1450dcf89dSDirk Eibach #include <pci.h>
1550dcf89dSDirk Eibach #include <mpc83xx.h>
1650dcf89dSDirk Eibach #include <fsl_esdhc.h>
1750dcf89dSDirk Eibach #include <asm/io.h>
1850dcf89dSDirk Eibach #include <asm/fsl_serdes.h>
1950dcf89dSDirk Eibach #include <asm/fsl_mpc83xx_serdes.h>
2050dcf89dSDirk Eibach 
2150dcf89dSDirk Eibach #include "mpc8308.h"
2250dcf89dSDirk Eibach 
2350dcf89dSDirk Eibach #include <gdsys_fpga.h>
2450dcf89dSDirk Eibach 
25d4e58888SDirk Eibach #include "../common/ioep-fpga.h"
2650dcf89dSDirk Eibach #include "../common/osd.h"
2750dcf89dSDirk Eibach #include "../common/mclink.h"
2850dcf89dSDirk Eibach #include "../common/phy.h"
295c3b6dc1SDirk Eibach #include "../common/fanctrl.h"
3050dcf89dSDirk Eibach 
3150dcf89dSDirk Eibach #include <pca953x.h>
3250dcf89dSDirk Eibach #include <pca9698.h>
3350dcf89dSDirk Eibach 
3450dcf89dSDirk Eibach #include <miiphy.h>
3550dcf89dSDirk Eibach 
3650dcf89dSDirk Eibach DECLARE_GLOBAL_DATA_PTR;
3750dcf89dSDirk Eibach 
3850dcf89dSDirk Eibach #define MAX_MUX_CHANNELS 2
3950dcf89dSDirk Eibach 
4050dcf89dSDirk Eibach enum {
4150dcf89dSDirk Eibach 	MCFPGA_DONE = 1 << 0,
4250dcf89dSDirk Eibach 	MCFPGA_INIT_N = 1 << 1,
4350dcf89dSDirk Eibach 	MCFPGA_PROGRAM_N = 1 << 2,
4450dcf89dSDirk Eibach 	MCFPGA_UPDATE_ENABLE_N = 1 << 3,
4550dcf89dSDirk Eibach 	MCFPGA_RESET_N = 1 << 4,
4650dcf89dSDirk Eibach };
4750dcf89dSDirk Eibach 
4850dcf89dSDirk Eibach enum {
4950dcf89dSDirk Eibach 	GPIO_MDC = 1 << 14,
5050dcf89dSDirk Eibach 	GPIO_MDIO = 1 << 15,
5150dcf89dSDirk Eibach };
5250dcf89dSDirk Eibach 
5350dcf89dSDirk Eibach unsigned int mclink_fpgacount;
5450dcf89dSDirk Eibach struct ihs_fpga *fpga_ptr[] = CONFIG_SYS_FPGA_PTR;
5550dcf89dSDirk Eibach 
565c3b6dc1SDirk Eibach struct {
575c3b6dc1SDirk Eibach 	u8 bus;
585c3b6dc1SDirk Eibach 	u8 addr;
595c3b6dc1SDirk Eibach } hrcon_fans[] = CONFIG_HRCON_FANS;
605c3b6dc1SDirk Eibach 
fpga_set_reg(u32 fpga,u16 * reg,off_t regoff,u16 data)6150dcf89dSDirk Eibach int fpga_set_reg(u32 fpga, u16 *reg, off_t regoff, u16 data)
6250dcf89dSDirk Eibach {
6350dcf89dSDirk Eibach 	int res;
6450dcf89dSDirk Eibach 
6550dcf89dSDirk Eibach 	switch (fpga) {
6650dcf89dSDirk Eibach 	case 0:
6750dcf89dSDirk Eibach 		out_le16(reg, data);
6850dcf89dSDirk Eibach 		break;
6950dcf89dSDirk Eibach 	default:
7050dcf89dSDirk Eibach 		res = mclink_send(fpga - 1, regoff, data);
7150dcf89dSDirk Eibach 		if (res < 0) {
7250dcf89dSDirk Eibach 			printf("mclink_send reg %02lx data %04x returned %d\n",
7350dcf89dSDirk Eibach 			       regoff, data, res);
7450dcf89dSDirk Eibach 			return res;
7550dcf89dSDirk Eibach 		}
7650dcf89dSDirk Eibach 		break;
7750dcf89dSDirk Eibach 	}
7850dcf89dSDirk Eibach 
7950dcf89dSDirk Eibach 	return 0;
8050dcf89dSDirk Eibach }
8150dcf89dSDirk Eibach 
fpga_get_reg(u32 fpga,u16 * reg,off_t regoff,u16 * data)8250dcf89dSDirk Eibach int fpga_get_reg(u32 fpga, u16 *reg, off_t regoff, u16 *data)
8350dcf89dSDirk Eibach {
8450dcf89dSDirk Eibach 	int res;
8550dcf89dSDirk Eibach 
8650dcf89dSDirk Eibach 	switch (fpga) {
8750dcf89dSDirk Eibach 	case 0:
8850dcf89dSDirk Eibach 		*data = in_le16(reg);
8950dcf89dSDirk Eibach 		break;
9050dcf89dSDirk Eibach 	default:
9150dcf89dSDirk Eibach 		if (fpga > mclink_fpgacount)
9250dcf89dSDirk Eibach 			return -EINVAL;
9350dcf89dSDirk Eibach 		res = mclink_receive(fpga - 1, regoff, data);
9450dcf89dSDirk Eibach 		if (res < 0) {
9550dcf89dSDirk Eibach 			printf("mclink_receive reg %02lx returned %d\n",
9650dcf89dSDirk Eibach 			       regoff, res);
9750dcf89dSDirk Eibach 			return res;
9850dcf89dSDirk Eibach 		}
9950dcf89dSDirk Eibach 	}
10050dcf89dSDirk Eibach 
10150dcf89dSDirk Eibach 	return 0;
10250dcf89dSDirk Eibach }
10350dcf89dSDirk Eibach 
checkboard(void)10450dcf89dSDirk Eibach int checkboard(void)
10550dcf89dSDirk Eibach {
10600caae6dSSimon Glass 	char *s = env_get("serial#");
10750dcf89dSDirk Eibach 	bool hw_type_cat = pca9698_get_value(0x20, 20);
10850dcf89dSDirk Eibach 
10950dcf89dSDirk Eibach 	puts("Board: ");
11050dcf89dSDirk Eibach 
11150dcf89dSDirk Eibach 	printf("HRCon %s", hw_type_cat ? "CAT" : "Fiber");
11250dcf89dSDirk Eibach 
11350dcf89dSDirk Eibach 	if (s != NULL) {
11450dcf89dSDirk Eibach 		puts(", serial# ");
11550dcf89dSDirk Eibach 		puts(s);
11650dcf89dSDirk Eibach 	}
11750dcf89dSDirk Eibach 
11850dcf89dSDirk Eibach 	puts("\n");
11950dcf89dSDirk Eibach 
12050dcf89dSDirk Eibach 	return 0;
12150dcf89dSDirk Eibach }
12250dcf89dSDirk Eibach 
last_stage_init(void)12350dcf89dSDirk Eibach int last_stage_init(void)
12450dcf89dSDirk Eibach {
12550dcf89dSDirk Eibach 	int slaves;
12650dcf89dSDirk Eibach 	unsigned int k;
12750dcf89dSDirk Eibach 	unsigned int mux_ch;
128b847f5b6SDirk Eibach 	unsigned char mclink_controllers[] = { 0x3c, 0x3d, 0x3e };
12950dcf89dSDirk Eibach 	u16 fpga_features;
13050dcf89dSDirk Eibach 	bool hw_type_cat = pca9698_get_value(0x20, 20);
13150dcf89dSDirk Eibach 	bool ch0_rgmii2_present = false;
13250dcf89dSDirk Eibach 
13350dcf89dSDirk Eibach 	FPGA_GET_REG(0, fpga_features, &fpga_features);
13450dcf89dSDirk Eibach 
13550dcf89dSDirk Eibach 	/* Turn on Parade DP501 */
13650dcf89dSDirk Eibach 	pca9698_direction_output(0x20, 10, 1);
1377ed45d3dSDirk Eibach 	pca9698_direction_output(0x20, 11, 1);
13850dcf89dSDirk Eibach 
13950dcf89dSDirk Eibach 	ch0_rgmii2_present = !pca9698_get_value(0x20, 30);
14050dcf89dSDirk Eibach 
141b847f5b6SDirk Eibach 	/* wait for FPGA done, then reset FPGA */
14250dcf89dSDirk Eibach 	for (k = 0; k < ARRAY_SIZE(mclink_controllers); ++k) {
14350dcf89dSDirk Eibach 		unsigned int ctr = 0;
14450dcf89dSDirk Eibach 
14550dcf89dSDirk Eibach 		if (i2c_probe(mclink_controllers[k]))
14650dcf89dSDirk Eibach 			continue;
14750dcf89dSDirk Eibach 
14850dcf89dSDirk Eibach 		while (!(pca953x_get_val(mclink_controllers[k])
14950dcf89dSDirk Eibach 		       & MCFPGA_DONE)) {
15050dcf89dSDirk Eibach 			udelay(100000);
15150dcf89dSDirk Eibach 			if (ctr++ > 5) {
15250dcf89dSDirk Eibach 				printf("no done for mclink_controller %d\n", k);
15350dcf89dSDirk Eibach 				break;
15450dcf89dSDirk Eibach 			}
15550dcf89dSDirk Eibach 		}
156b847f5b6SDirk Eibach 
157b847f5b6SDirk Eibach 		pca953x_set_dir(mclink_controllers[k], MCFPGA_RESET_N, 0);
158b847f5b6SDirk Eibach 		pca953x_set_val(mclink_controllers[k], MCFPGA_RESET_N, 0);
159b847f5b6SDirk Eibach 		udelay(10);
160b847f5b6SDirk Eibach 		pca953x_set_val(mclink_controllers[k], MCFPGA_RESET_N,
161b847f5b6SDirk Eibach 				MCFPGA_RESET_N);
16250dcf89dSDirk Eibach 	}
16350dcf89dSDirk Eibach 
16450dcf89dSDirk Eibach 	if (hw_type_cat) {
1655a49f174SJoe Hershberger 		int retval;
1665a49f174SJoe Hershberger 		struct mii_dev *mdiodev = mdio_alloc();
1675a49f174SJoe Hershberger 		if (!mdiodev)
1685a49f174SJoe Hershberger 			return -ENOMEM;
1695a49f174SJoe Hershberger 		strncpy(mdiodev->name, bb_miiphy_buses[0].name, MDIO_NAME_LEN);
1705a49f174SJoe Hershberger 		mdiodev->read = bb_miiphy_read;
1715a49f174SJoe Hershberger 		mdiodev->write = bb_miiphy_write;
1725a49f174SJoe Hershberger 
1735a49f174SJoe Hershberger 		retval = mdio_register(mdiodev);
1745a49f174SJoe Hershberger 		if (retval < 0)
1755a49f174SJoe Hershberger 			return retval;
17650dcf89dSDirk Eibach 		for (mux_ch = 0; mux_ch < MAX_MUX_CHANNELS; ++mux_ch) {
17750dcf89dSDirk Eibach 			if ((mux_ch == 1) && !ch0_rgmii2_present)
17850dcf89dSDirk Eibach 				continue;
17950dcf89dSDirk Eibach 
18050dcf89dSDirk Eibach 			setup_88e1514(bb_miiphy_buses[0].name, mux_ch);
18150dcf89dSDirk Eibach 		}
18250dcf89dSDirk Eibach 	}
18350dcf89dSDirk Eibach 
18450dcf89dSDirk Eibach 	/* give slave-PLLs and Parade DP501 some time to be up and running */
18550dcf89dSDirk Eibach 	udelay(500000);
18650dcf89dSDirk Eibach 
18750dcf89dSDirk Eibach 	mclink_fpgacount = CONFIG_SYS_MCLINK_MAX;
18850dcf89dSDirk Eibach 	slaves = mclink_probe();
18950dcf89dSDirk Eibach 	mclink_fpgacount = 0;
19050dcf89dSDirk Eibach 
191d4e58888SDirk Eibach 	ioep_fpga_print_info(0);
19250dcf89dSDirk Eibach 	osd_probe(0);
1937ed45d3dSDirk Eibach #ifdef CONFIG_SYS_OSD_DH
1947ed45d3dSDirk Eibach 	osd_probe(4);
1957ed45d3dSDirk Eibach #endif
19650dcf89dSDirk Eibach 
19750dcf89dSDirk Eibach 	if (slaves <= 0)
19850dcf89dSDirk Eibach 		return 0;
19950dcf89dSDirk Eibach 
20050dcf89dSDirk Eibach 	mclink_fpgacount = slaves;
20150dcf89dSDirk Eibach 
20250dcf89dSDirk Eibach 	for (k = 1; k <= slaves; ++k) {
20350dcf89dSDirk Eibach 		FPGA_GET_REG(k, fpga_features, &fpga_features);
20450dcf89dSDirk Eibach 
205d4e58888SDirk Eibach 		ioep_fpga_print_info(k);
20650dcf89dSDirk Eibach 		osd_probe(k);
2077ed45d3dSDirk Eibach #ifdef CONFIG_SYS_OSD_DH
2087ed45d3dSDirk Eibach 		osd_probe(k + 4);
2097ed45d3dSDirk Eibach #endif
21050dcf89dSDirk Eibach 		if (hw_type_cat) {
2115a49f174SJoe Hershberger 			int retval;
2125a49f174SJoe Hershberger 			struct mii_dev *mdiodev = mdio_alloc();
2135a49f174SJoe Hershberger 			if (!mdiodev)
2145a49f174SJoe Hershberger 				return -ENOMEM;
2155a49f174SJoe Hershberger 			strncpy(mdiodev->name, bb_miiphy_buses[k].name,
2165a49f174SJoe Hershberger 				MDIO_NAME_LEN);
2175a49f174SJoe Hershberger 			mdiodev->read = bb_miiphy_read;
2185a49f174SJoe Hershberger 			mdiodev->write = bb_miiphy_write;
2195a49f174SJoe Hershberger 
2205a49f174SJoe Hershberger 			retval = mdio_register(mdiodev);
2215a49f174SJoe Hershberger 			if (retval < 0)
2225a49f174SJoe Hershberger 				return retval;
22350dcf89dSDirk Eibach 			setup_88e1514(bb_miiphy_buses[k].name, 0);
22450dcf89dSDirk Eibach 		}
22550dcf89dSDirk Eibach 	}
22650dcf89dSDirk Eibach 
2275c3b6dc1SDirk Eibach 	for (k = 0; k < ARRAY_SIZE(hrcon_fans); ++k) {
2285c3b6dc1SDirk Eibach 		i2c_set_bus_num(hrcon_fans[k].bus);
2295c3b6dc1SDirk Eibach 		init_fan_controller(hrcon_fans[k].addr);
2305c3b6dc1SDirk Eibach 	}
2315c3b6dc1SDirk Eibach 
23250dcf89dSDirk Eibach 	return 0;
23350dcf89dSDirk Eibach }
23450dcf89dSDirk Eibach 
23550dcf89dSDirk Eibach /*
2367ed45d3dSDirk Eibach  * provide access to fpga gpios and controls (for I2C bitbang)
23750dcf89dSDirk Eibach  * (these may look all too simple but make iocon.h much more readable)
23850dcf89dSDirk Eibach  */
fpga_gpio_set(unsigned int bus,int pin)23950dcf89dSDirk Eibach void fpga_gpio_set(unsigned int bus, int pin)
24050dcf89dSDirk Eibach {
2417ed45d3dSDirk Eibach 	FPGA_SET_REG(bus >= 4 ? (bus - 4) : bus, gpio.set, pin);
24250dcf89dSDirk Eibach }
24350dcf89dSDirk Eibach 
fpga_gpio_clear(unsigned int bus,int pin)24450dcf89dSDirk Eibach void fpga_gpio_clear(unsigned int bus, int pin)
24550dcf89dSDirk Eibach {
2467ed45d3dSDirk Eibach 	FPGA_SET_REG(bus >= 4 ? (bus - 4) : bus, gpio.clear, pin);
24750dcf89dSDirk Eibach }
24850dcf89dSDirk Eibach 
fpga_gpio_get(unsigned int bus,int pin)24950dcf89dSDirk Eibach int fpga_gpio_get(unsigned int bus, int pin)
25050dcf89dSDirk Eibach {
25150dcf89dSDirk Eibach 	u16 val;
25250dcf89dSDirk Eibach 
2537ed45d3dSDirk Eibach 	FPGA_GET_REG(bus >= 4 ? (bus - 4) : bus, gpio.read, &val);
25450dcf89dSDirk Eibach 
25550dcf89dSDirk Eibach 	return val & pin;
25650dcf89dSDirk Eibach }
25750dcf89dSDirk Eibach 
fpga_control_set(unsigned int bus,int pin)2587ed45d3dSDirk Eibach void fpga_control_set(unsigned int bus, int pin)
2597ed45d3dSDirk Eibach {
2607ed45d3dSDirk Eibach 	u16 val;
2617ed45d3dSDirk Eibach 
2627ed45d3dSDirk Eibach 	FPGA_GET_REG(bus >= 4 ? (bus - 4) : bus, control, &val);
2637ed45d3dSDirk Eibach 	FPGA_SET_REG(bus >= 4 ? (bus - 4) : bus, control, val | pin);
2647ed45d3dSDirk Eibach }
2657ed45d3dSDirk Eibach 
fpga_control_clear(unsigned int bus,int pin)2667ed45d3dSDirk Eibach void fpga_control_clear(unsigned int bus, int pin)
2677ed45d3dSDirk Eibach {
2687ed45d3dSDirk Eibach 	u16 val;
2697ed45d3dSDirk Eibach 
2707ed45d3dSDirk Eibach 	FPGA_GET_REG(bus >= 4 ? (bus - 4) : bus, control, &val);
2717ed45d3dSDirk Eibach 	FPGA_SET_REG(bus >= 4 ? (bus - 4) : bus, control, val & ~pin);
2727ed45d3dSDirk Eibach }
2737ed45d3dSDirk Eibach 
mpc8308_init(void)27450dcf89dSDirk Eibach void mpc8308_init(void)
27550dcf89dSDirk Eibach {
27650dcf89dSDirk Eibach 	pca9698_direction_output(0x20, 4, 1);
27750dcf89dSDirk Eibach }
27850dcf89dSDirk Eibach 
mpc8308_set_fpga_reset(unsigned state)27950dcf89dSDirk Eibach void mpc8308_set_fpga_reset(unsigned state)
28050dcf89dSDirk Eibach {
28150dcf89dSDirk Eibach 	pca9698_set_value(0x20, 4, state ? 0 : 1);
28250dcf89dSDirk Eibach }
28350dcf89dSDirk Eibach 
mpc8308_setup_hw(void)28450dcf89dSDirk Eibach void mpc8308_setup_hw(void)
28550dcf89dSDirk Eibach {
28650dcf89dSDirk Eibach 	immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
28750dcf89dSDirk Eibach 
28850dcf89dSDirk Eibach 	/*
28950dcf89dSDirk Eibach 	 * set "startup-finished"-gpios
29050dcf89dSDirk Eibach 	 */
29150dcf89dSDirk Eibach 	setbits_be32(&immr->gpio[0].dir, (1 << (31-11)) | (1 << (31-12)));
29250dcf89dSDirk Eibach 	setbits_be32(&immr->gpio[0].dat, 1 << (31-12));
29350dcf89dSDirk Eibach }
29450dcf89dSDirk Eibach 
mpc8308_get_fpga_done(unsigned fpga)29550dcf89dSDirk Eibach int mpc8308_get_fpga_done(unsigned fpga)
29650dcf89dSDirk Eibach {
29750dcf89dSDirk Eibach 	return pca9698_get_value(0x20, 19);
29850dcf89dSDirk Eibach }
29950dcf89dSDirk Eibach 
30050dcf89dSDirk Eibach #ifdef CONFIG_FSL_ESDHC
board_mmc_init(bd_t * bd)30150dcf89dSDirk Eibach int board_mmc_init(bd_t *bd)
30250dcf89dSDirk Eibach {
30350dcf89dSDirk Eibach 	immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
30450dcf89dSDirk Eibach 	sysconf83xx_t *sysconf = &immr->sysconf;
30550dcf89dSDirk Eibach 
30650dcf89dSDirk Eibach 	/* Enable cache snooping in eSDHC system configuration register */
30750dcf89dSDirk Eibach 	out_be32(&sysconf->sdhccr, 0x02000000);
30850dcf89dSDirk Eibach 
30950dcf89dSDirk Eibach 	return fsl_esdhc_mmc_init(bd);
31050dcf89dSDirk Eibach }
31150dcf89dSDirk Eibach #endif
31250dcf89dSDirk Eibach 
31350dcf89dSDirk Eibach static struct pci_region pcie_regions_0[] = {
31450dcf89dSDirk Eibach 	{
31550dcf89dSDirk Eibach 		.bus_start = CONFIG_SYS_PCIE1_MEM_BASE,
31650dcf89dSDirk Eibach 		.phys_start = CONFIG_SYS_PCIE1_MEM_PHYS,
31750dcf89dSDirk Eibach 		.size = CONFIG_SYS_PCIE1_MEM_SIZE,
31850dcf89dSDirk Eibach 		.flags = PCI_REGION_MEM,
31950dcf89dSDirk Eibach 	},
32050dcf89dSDirk Eibach 	{
32150dcf89dSDirk Eibach 		.bus_start = CONFIG_SYS_PCIE1_IO_BASE,
32250dcf89dSDirk Eibach 		.phys_start = CONFIG_SYS_PCIE1_IO_PHYS,
32350dcf89dSDirk Eibach 		.size = CONFIG_SYS_PCIE1_IO_SIZE,
32450dcf89dSDirk Eibach 		.flags = PCI_REGION_IO,
32550dcf89dSDirk Eibach 	},
32650dcf89dSDirk Eibach };
32750dcf89dSDirk Eibach 
pci_init_board(void)32850dcf89dSDirk Eibach void pci_init_board(void)
32950dcf89dSDirk Eibach {
33050dcf89dSDirk Eibach 	immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
33150dcf89dSDirk Eibach 	sysconf83xx_t *sysconf = &immr->sysconf;
33250dcf89dSDirk Eibach 	law83xx_t *pcie_law = sysconf->pcielaw;
33350dcf89dSDirk Eibach 	struct pci_region *pcie_reg[] = { pcie_regions_0 };
33450dcf89dSDirk Eibach 
33550dcf89dSDirk Eibach 	fsl_setup_serdes(CONFIG_FSL_SERDES1, FSL_SERDES_PROTO_PEX,
33650dcf89dSDirk Eibach 			 FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V);
33750dcf89dSDirk Eibach 
33850dcf89dSDirk Eibach 	/* Deassert the resets in the control register */
33950dcf89dSDirk Eibach 	out_be32(&sysconf->pecr1, 0xE0008000);
34050dcf89dSDirk Eibach 	udelay(2000);
34150dcf89dSDirk Eibach 
34250dcf89dSDirk Eibach 	/* Configure PCI Express Local Access Windows */
34350dcf89dSDirk Eibach 	out_be32(&pcie_law[0].bar, CONFIG_SYS_PCIE1_BASE & LAWBAR_BAR);
34450dcf89dSDirk Eibach 	out_be32(&pcie_law[0].ar, LBLAWAR_EN | LBLAWAR_512MB);
34550dcf89dSDirk Eibach 
34650dcf89dSDirk Eibach 	mpc83xx_pcie_init(1, pcie_reg);
34750dcf89dSDirk Eibach }
34850dcf89dSDirk Eibach 
board_flash_get_legacy(ulong base,int banknum,flash_info_t * info)34950dcf89dSDirk Eibach ulong board_flash_get_legacy(ulong base, int banknum, flash_info_t *info)
35050dcf89dSDirk Eibach {
35150dcf89dSDirk Eibach 	info->portwidth = FLASH_CFI_16BIT;
35250dcf89dSDirk Eibach 	info->chipwidth = FLASH_CFI_BY16;
35350dcf89dSDirk Eibach 	info->interface = FLASH_CFI_X16;
35450dcf89dSDirk Eibach 	return 1;
35550dcf89dSDirk Eibach }
35650dcf89dSDirk Eibach 
35750dcf89dSDirk Eibach #if defined(CONFIG_OF_BOARD_SETUP)
ft_board_setup(void * blob,bd_t * bd)358e895a4b0SSimon Glass int ft_board_setup(void *blob, bd_t *bd)
35950dcf89dSDirk Eibach {
36050dcf89dSDirk Eibach 	ft_cpu_setup(blob, bd);
361a5c289b9SSriram Dash 	fsl_fdt_fixup_dr_usb(blob, bd);
36250dcf89dSDirk Eibach 	fdt_fixup_esdhc(blob, bd);
363e895a4b0SSimon Glass 
364e895a4b0SSimon Glass 	return 0;
36550dcf89dSDirk Eibach }
36650dcf89dSDirk Eibach #endif
36750dcf89dSDirk Eibach 
36850dcf89dSDirk Eibach /*
36950dcf89dSDirk Eibach  * FPGA MII bitbang implementation
37050dcf89dSDirk Eibach  */
37150dcf89dSDirk Eibach 
37250dcf89dSDirk Eibach struct fpga_mii {
37350dcf89dSDirk Eibach 	unsigned fpga;
37450dcf89dSDirk Eibach 	int mdio;
37550dcf89dSDirk Eibach } fpga_mii[] = {
37650dcf89dSDirk Eibach 	{ 0, 1},
37750dcf89dSDirk Eibach 	{ 1, 1},
37850dcf89dSDirk Eibach 	{ 2, 1},
37950dcf89dSDirk Eibach 	{ 3, 1},
38050dcf89dSDirk Eibach };
38150dcf89dSDirk Eibach 
mii_dummy_init(struct bb_miiphy_bus * bus)38250dcf89dSDirk Eibach static int mii_dummy_init(struct bb_miiphy_bus *bus)
38350dcf89dSDirk Eibach {
38450dcf89dSDirk Eibach 	return 0;
38550dcf89dSDirk Eibach }
38650dcf89dSDirk Eibach 
mii_mdio_active(struct bb_miiphy_bus * bus)38750dcf89dSDirk Eibach static int mii_mdio_active(struct bb_miiphy_bus *bus)
38850dcf89dSDirk Eibach {
38950dcf89dSDirk Eibach 	struct fpga_mii *fpga_mii = bus->priv;
39050dcf89dSDirk Eibach 
39150dcf89dSDirk Eibach 	if (fpga_mii->mdio)
39250dcf89dSDirk Eibach 		FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDIO);
39350dcf89dSDirk Eibach 	else
39450dcf89dSDirk Eibach 		FPGA_SET_REG(fpga_mii->fpga, gpio.clear, GPIO_MDIO);
39550dcf89dSDirk Eibach 
39650dcf89dSDirk Eibach 	return 0;
39750dcf89dSDirk Eibach }
39850dcf89dSDirk Eibach 
mii_mdio_tristate(struct bb_miiphy_bus * bus)39950dcf89dSDirk Eibach static int mii_mdio_tristate(struct bb_miiphy_bus *bus)
40050dcf89dSDirk Eibach {
40150dcf89dSDirk Eibach 	struct fpga_mii *fpga_mii = bus->priv;
40250dcf89dSDirk Eibach 
40350dcf89dSDirk Eibach 	FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDIO);
40450dcf89dSDirk Eibach 
40550dcf89dSDirk Eibach 	return 0;
40650dcf89dSDirk Eibach }
40750dcf89dSDirk Eibach 
mii_set_mdio(struct bb_miiphy_bus * bus,int v)40850dcf89dSDirk Eibach static int mii_set_mdio(struct bb_miiphy_bus *bus, int v)
40950dcf89dSDirk Eibach {
41050dcf89dSDirk Eibach 	struct fpga_mii *fpga_mii = bus->priv;
41150dcf89dSDirk Eibach 
41250dcf89dSDirk Eibach 	if (v)
41350dcf89dSDirk Eibach 		FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDIO);
41450dcf89dSDirk Eibach 	else
41550dcf89dSDirk Eibach 		FPGA_SET_REG(fpga_mii->fpga, gpio.clear, GPIO_MDIO);
41650dcf89dSDirk Eibach 
41750dcf89dSDirk Eibach 	fpga_mii->mdio = v;
41850dcf89dSDirk Eibach 
41950dcf89dSDirk Eibach 	return 0;
42050dcf89dSDirk Eibach }
42150dcf89dSDirk Eibach 
mii_get_mdio(struct bb_miiphy_bus * bus,int * v)42250dcf89dSDirk Eibach static int mii_get_mdio(struct bb_miiphy_bus *bus, int *v)
42350dcf89dSDirk Eibach {
42450dcf89dSDirk Eibach 	u16 gpio;
42550dcf89dSDirk Eibach 	struct fpga_mii *fpga_mii = bus->priv;
42650dcf89dSDirk Eibach 
42750dcf89dSDirk Eibach 	FPGA_GET_REG(fpga_mii->fpga, gpio.read, &gpio);
42850dcf89dSDirk Eibach 
42950dcf89dSDirk Eibach 	*v = ((gpio & GPIO_MDIO) != 0);
43050dcf89dSDirk Eibach 
43150dcf89dSDirk Eibach 	return 0;
43250dcf89dSDirk Eibach }
43350dcf89dSDirk Eibach 
mii_set_mdc(struct bb_miiphy_bus * bus,int v)43450dcf89dSDirk Eibach static int mii_set_mdc(struct bb_miiphy_bus *bus, int v)
43550dcf89dSDirk Eibach {
43650dcf89dSDirk Eibach 	struct fpga_mii *fpga_mii = bus->priv;
43750dcf89dSDirk Eibach 
43850dcf89dSDirk Eibach 	if (v)
43950dcf89dSDirk Eibach 		FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDC);
44050dcf89dSDirk Eibach 	else
44150dcf89dSDirk Eibach 		FPGA_SET_REG(fpga_mii->fpga, gpio.clear, GPIO_MDC);
44250dcf89dSDirk Eibach 
44350dcf89dSDirk Eibach 	return 0;
44450dcf89dSDirk Eibach }
44550dcf89dSDirk Eibach 
mii_delay(struct bb_miiphy_bus * bus)44650dcf89dSDirk Eibach static int mii_delay(struct bb_miiphy_bus *bus)
44750dcf89dSDirk Eibach {
44850dcf89dSDirk Eibach 	udelay(1);
44950dcf89dSDirk Eibach 
45050dcf89dSDirk Eibach 	return 0;
45150dcf89dSDirk Eibach }
45250dcf89dSDirk Eibach 
45350dcf89dSDirk Eibach struct bb_miiphy_bus bb_miiphy_buses[] = {
45450dcf89dSDirk Eibach 	{
45550dcf89dSDirk Eibach 		.name = "board0",
45650dcf89dSDirk Eibach 		.init = mii_dummy_init,
45750dcf89dSDirk Eibach 		.mdio_active = mii_mdio_active,
45850dcf89dSDirk Eibach 		.mdio_tristate = mii_mdio_tristate,
45950dcf89dSDirk Eibach 		.set_mdio = mii_set_mdio,
46050dcf89dSDirk Eibach 		.get_mdio = mii_get_mdio,
46150dcf89dSDirk Eibach 		.set_mdc = mii_set_mdc,
46250dcf89dSDirk Eibach 		.delay = mii_delay,
46350dcf89dSDirk Eibach 		.priv = &fpga_mii[0],
46450dcf89dSDirk Eibach 	},
46550dcf89dSDirk Eibach 	{
46650dcf89dSDirk Eibach 		.name = "board1",
46750dcf89dSDirk Eibach 		.init = mii_dummy_init,
46850dcf89dSDirk Eibach 		.mdio_active = mii_mdio_active,
46950dcf89dSDirk Eibach 		.mdio_tristate = mii_mdio_tristate,
47050dcf89dSDirk Eibach 		.set_mdio = mii_set_mdio,
47150dcf89dSDirk Eibach 		.get_mdio = mii_get_mdio,
47250dcf89dSDirk Eibach 		.set_mdc = mii_set_mdc,
47350dcf89dSDirk Eibach 		.delay = mii_delay,
47450dcf89dSDirk Eibach 		.priv = &fpga_mii[1],
47550dcf89dSDirk Eibach 	},
47650dcf89dSDirk Eibach 	{
47750dcf89dSDirk Eibach 		.name = "board2",
47850dcf89dSDirk Eibach 		.init = mii_dummy_init,
47950dcf89dSDirk Eibach 		.mdio_active = mii_mdio_active,
48050dcf89dSDirk Eibach 		.mdio_tristate = mii_mdio_tristate,
48150dcf89dSDirk Eibach 		.set_mdio = mii_set_mdio,
48250dcf89dSDirk Eibach 		.get_mdio = mii_get_mdio,
48350dcf89dSDirk Eibach 		.set_mdc = mii_set_mdc,
48450dcf89dSDirk Eibach 		.delay = mii_delay,
48550dcf89dSDirk Eibach 		.priv = &fpga_mii[2],
48650dcf89dSDirk Eibach 	},
48750dcf89dSDirk Eibach 	{
48850dcf89dSDirk Eibach 		.name = "board3",
48950dcf89dSDirk Eibach 		.init = mii_dummy_init,
49050dcf89dSDirk Eibach 		.mdio_active = mii_mdio_active,
49150dcf89dSDirk Eibach 		.mdio_tristate = mii_mdio_tristate,
49250dcf89dSDirk Eibach 		.set_mdio = mii_set_mdio,
49350dcf89dSDirk Eibach 		.get_mdio = mii_get_mdio,
49450dcf89dSDirk Eibach 		.set_mdc = mii_set_mdc,
49550dcf89dSDirk Eibach 		.delay = mii_delay,
49650dcf89dSDirk Eibach 		.priv = &fpga_mii[3],
49750dcf89dSDirk Eibach 	},
49850dcf89dSDirk Eibach };
49950dcf89dSDirk Eibach 
50050dcf89dSDirk Eibach int bb_miiphy_buses_num = sizeof(bb_miiphy_buses) /
50150dcf89dSDirk Eibach 			  sizeof(bb_miiphy_buses[0]);
502