1126596Sbms// SPDX-License-Identifier: GPL-2.0+
2127655Sbms/*
3127655Sbms * Copyright 2018, 2020 NXP
4127655Sbms *
5126596Sbms */
6126596Sbms
7126596Sbms#include <common.h>
8126596Sbms#include <netdev.h>
9126596Sbms#include <exports.h>
10126596Sbms#include <fsl-mc/fsl_mc.h>
11126596Sbms#include "lx2160a.h"
12126596Sbms
13126596SbmsDECLARE_GLOBAL_DATA_PTR;
14126596Sbms
15126596Sbmsint board_eth_init(struct bd_info *bis)
16126596Sbms{
17126596Sbms#ifdef CONFIG_PHY_AQUANTIA
18126596Sbms	/*
19126596Sbms	 * Export functions to be used by AQ firmware
20126596Sbms	 * upload application
21126596Sbms	 */
22126596Sbms	gd->jt->strcpy = strcpy;
23126596Sbms	gd->jt->mdelay = mdelay;
24126596Sbms	gd->jt->mdio_get_current_dev = mdio_get_current_dev;
25126596Sbms	gd->jt->phy_find_by_mask = phy_find_by_mask;
26126596Sbms	gd->jt->mdio_phydev_for_ethname = mdio_phydev_for_ethname;
27126596Sbms	gd->jt->miiphy_set_current_dev = miiphy_set_current_dev;
28126596Sbms#endif
29126596Sbms	return pci_eth_init(bis);
30196155Ssam}
31131738Sru
32126596Sbms#if defined(CONFIG_RESET_PHY_R)
33126596Sbmsvoid reset_phy(void)
34126596Sbms{
35196155Ssam#if defined(CONFIG_FSL_MC_ENET)
36126596Sbms	mc_env_boot();
37126596Sbms#endif
38126596Sbms}
39196155Ssam#endif /* CONFIG_RESET_PHY_R */
40196155Ssam
41196155Ssamstatic int fdt_get_dpmac_node(void *fdt, int dpmac_id)
42196155Ssam{
43196155Ssam	char dpmac_str[11] = "dpmacs@00";
44196155Ssam	int offset, dpmacs_offset;
45196155Ssam
46196155Ssam	/* get the dpmac offset */
47196155Ssam	dpmacs_offset = fdt_path_offset(fdt, "/soc/fsl-mc/dpmacs");
48196155Ssam	if (dpmacs_offset < 0)
49196155Ssam		dpmacs_offset = fdt_path_offset(fdt, "/fsl-mc/dpmacs");
50196155Ssam
51196155Ssam	if (dpmacs_offset < 0) {
52196155Ssam		printf("dpmacs node not found in device tree\n");
53196155Ssam		return dpmacs_offset;
54196155Ssam	}
55196155Ssam
56196155Ssam	sprintf(dpmac_str, "dpmac@%x", dpmac_id);
57196155Ssam	offset = fdt_subnode_offset(fdt, dpmacs_offset, dpmac_str);
58196155Ssam	if (offset < 0) {
59126596Sbms		sprintf(dpmac_str, "ethernet@%x", dpmac_id);
60126596Sbms		offset = fdt_subnode_offset(fdt, dpmacs_offset, dpmac_str);
61196155Ssam		if (offset < 0) {
62196155Ssam			printf("dpmac@%x/ethernet@%x node not found in device tree\n",
63196155Ssam			       dpmac_id, dpmac_id);
64237216Seadler			return offset;
65196155Ssam		}
66196155Ssam	}
67196155Ssam
68196155Ssam	return offset;
69126596Sbms}
70196155Ssam
71196155Ssamstatic int fdt_update_phy_addr(void *fdt, int dpmac_id, int phy_addr)
72196155Ssam{
73196155Ssam	char dpmac_str[] = "dpmacs@00";
74127655Sbms	const u32 *phyhandle;
75127655Sbms	int offset;
76196155Ssam	int err;
77196155Ssam
78196155Ssam	/* get the dpmac offset */
79196155Ssam	offset = fdt_get_dpmac_node(fdt, dpmac_id);
80196155Ssam	if (offset < 0)
81196155Ssam		return offset;
82196155Ssam
83196155Ssam	/* get dpmac phy-handle */
84196155Ssam	sprintf(dpmac_str, "dpmac@%x", dpmac_id);
85196155Ssam	phyhandle = (u32 *)fdt_getprop(fdt, offset, "phy-handle", NULL);
86196155Ssam	if (!phyhandle) {
87196155Ssam		printf("%s node not found in device tree\n", dpmac_str);
88196155Ssam		return offset;
89196155Ssam	}
90196155Ssam
91196155Ssam	offset = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*phyhandle));
92196155Ssam	if (offset < 0) {
93196155Ssam		printf("Could not get the ph node offset for dpmac %d\n",
94127655Sbms		       dpmac_id);
95196155Ssam		return offset;
96196155Ssam	}
97196155Ssam
98196155Ssam	phy_addr = cpu_to_fdt32(phy_addr);
99196155Ssam	err = fdt_setprop(fdt, offset, "reg", &phy_addr, sizeof(phy_addr));
100196155Ssam	if (err < 0) {
101196155Ssam		printf("Could not set phy node's reg for dpmac %d: %s.\n",
102196155Ssam		       dpmac_id, fdt_strerror(err));
103196155Ssam		return err;
104196155Ssam	}
105196155Ssam
106196155Ssam	return 0;
107126596Sbms}
108196155Ssam
109196155Ssamstatic int fdt_delete_phy_handle(void *fdt, int dpmac_id)
110196155Ssam{
111196155Ssam	const u32 *phyhandle;
112126596Sbms	int offset;
113126596Sbms
114196155Ssam	/* get the dpmac offset */
115196155Ssam	offset = fdt_get_dpmac_node(fdt, dpmac_id);
116196155Ssam	if (offset < 0)
117196155Ssam		return offset;
118196155Ssam
119196155Ssam	/* verify if the node has a phy-handle */
120196155Ssam	phyhandle = (u32 *)fdt_getprop(fdt, offset, "phy-handle", NULL);
121196155Ssam	if (!phyhandle)
122196155Ssam		return 0;
123196155Ssam
124126596Sbms	return fdt_delprop(fdt, offset, "phy-handle");
125126596Sbms}
126196155Ssam
127126596Sbmsint fdt_fixup_board_phy_revc(void *fdt)
128196155Ssam{
129196155Ssam	int ret;
130196155Ssam
131131738Sru	if (get_board_rev() < 'C')
132126596Sbms		return 0;
133126596Sbms
134196155Ssam	/* DPMACs 3,4 have their Aquantia PHYs at new addresses */
135196155Ssam	ret = fdt_update_phy_addr(fdt, 3, AQR113C_PHY_ADDR1);
136126596Sbms	if (ret)
137196155Ssam		return ret;
138196155Ssam
139126596Sbms	ret = fdt_update_phy_addr(fdt, 4, AQR113C_PHY_ADDR2);
140196155Ssam	if (ret)
141196155Ssam		return ret;
142196155Ssam
143196155Ssam	/* There is no PHY for the DPMAC2, so remove the phy-handle */
144196155Ssam	return fdt_delete_phy_handle(fdt, 2);
145196155Ssam}
146196155Ssam