~funderscore blog cgit wiki get in touch
aboutsummaryrefslogtreecommitdiff
blob: c5dfefe1f3425a6b1a22faf1b071d16271aa63be (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright 2018, 2020 NXP
 *
 */

#include <common.h>
#include <netdev.h>
#include <exports.h>
#include <fsl-mc/fsl_mc.h>
#include "lx2160a.h"

DECLARE_GLOBAL_DATA_PTR;

int board_eth_init(struct bd_info *bis)
{
#ifdef CONFIG_PHY_AQUANTIA
	/*
	 * Export functions to be used by AQ firmware
	 * upload application
	 */
	gd->jt->strcpy = strcpy;
	gd->jt->mdelay = mdelay;
	gd->jt->mdio_get_current_dev = mdio_get_current_dev;
	gd->jt->phy_find_by_mask = phy_find_by_mask;
	gd->jt->mdio_phydev_for_ethname = mdio_phydev_for_ethname;
	gd->jt->miiphy_set_current_dev = miiphy_set_current_dev;
#endif
	return pci_eth_init(bis);
}

#if defined(CONFIG_RESET_PHY_R)
void reset_phy(void)
{
#if defined(CONFIG_FSL_MC_ENET)
	mc_env_boot();
#endif
}
#endif /* CONFIG_RESET_PHY_R */

static int fdt_get_dpmac_node(void *fdt, int dpmac_id)
{
	char dpmac_str[11] = "dpmacs@00";
	int offset, dpmacs_offset;

	/* get the dpmac offset */
	dpmacs_offset = fdt_path_offset(fdt, "/soc/fsl-mc/dpmacs");
	if (dpmacs_offset < 0)
		dpmacs_offset = fdt_path_offset(fdt, "/fsl-mc/dpmacs");

	if (dpmacs_offset < 0) {
		printf("dpmacs node not found in device tree\n");
		return dpmacs_offset;
	}

	sprintf(dpmac_str, "dpmac@%x", dpmac_id);
	offset = fdt_subnode_offset(fdt, dpmacs_offset, dpmac_str);
	if (offset < 0) {
		sprintf(dpmac_str, "ethernet@%x", dpmac_id);
		offset = fdt_subnode_offset(fdt, dpmacs_offset, dpmac_str);
		if (offset < 0) {
			printf("dpmac@%x/ethernet@%x node not found in device tree\n",
			       dpmac_id, dpmac_id);
			return offset;
		}
	}

	return offset;
}

static int fdt_update_phy_addr(void *fdt, int dpmac_id, int phy_addr)
{
	char dpmac_str[] = "dpmacs@00";
	const u32 *phyhandle;
	int offset;
	int err;

	/* get the dpmac offset */
	offset = fdt_get_dpmac_node(fdt, dpmac_id);
	if (offset < 0)
		return offset;

	/* get dpmac phy-handle */
	sprintf(dpmac_str, "dpmac@%x", dpmac_id);
	phyhandle = (u32 *)fdt_getprop(fdt, offset, "phy-handle", NULL);
	if (!phyhandle) {
		printf("%s node not found in device tree\n", dpmac_str);
		return offset;
	}

	offset = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*phyhandle));
	if (offset < 0) {
		printf("Could not get the ph node offset for dpmac %d\n",
		       dpmac_id);
		return offset;
	}

	phy_addr = cpu_to_fdt32(phy_addr);
	err = fdt_setprop(fdt, offset, "reg", &phy_addr, sizeof(phy_addr));
	if (err < 0) {
		printf("Could not set phy node's reg for dpmac %d: %s.\n",
		       dpmac_id, fdt_strerror(err));
		return err;
	}

	return 0;
}

static int fdt_delete_phy_handle(void *fdt, int dpmac_id)
{
	const u32 *phyhandle;
	int offset;

	/* get the dpmac offset */
	offset = fdt_get_dpmac_node(fdt, dpmac_id);
	if (offset < 0)
		return offset;

	/* verify if the node has a phy-handle */
	phyhandle = (u32 *)fdt_getprop(fdt, offset, "phy-handle", NULL);
	if (!phyhandle)
		return 0;

	return fdt_delprop(fdt, offset, "phy-handle");
}

int fdt_fixup_board_phy_revc(void *fdt)
{
	int ret;

	if (get_board_rev() < 'C')
		return 0;

	/* DPMACs 3,4 have their Aquantia PHYs at new addresses */
	ret = fdt_update_phy_addr(fdt, 3, AQR113C_PHY_ADDR1);
	if (ret)
		return ret;

	ret = fdt_update_phy_addr(fdt, 4, AQR113C_PHY_ADDR2);
	if (ret)
		return ret;

	/* There is no PHY for the DPMAC2, so remove the phy-handle */
	return fdt_delete_phy_handle(fdt, 2);
}