1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2014 Freescale Semiconductor, Inc.
4  *
5  * This file handles the board muxing between the RGMII/SGMII PHYs on
6  * Freescale LS1021AQDS board. The RGMII PHYs are the three on-board 1Gb
7  * ports. The SGMII PHYs are provided by the standard Freescale four-port
8  * SGMII riser card.
9  *
10  * Muxing is handled via the PIXIS BRDCFG4 register. The EMI1 bits control
11  * muxing among the RGMII PHYs and the SGMII PHYs. The value for RGMII depends
12  * on which port is used. The value for SGMII depends on which slot the riser
13  * is inserted in.
14  */
15 
16 #include <common.h>
17 #include <netdev.h>
18 #include <asm/arch/fsl_serdes.h>
19 #include <fsl_mdio.h>
20 #include <tsec.h>
21 #include <malloc.h>
22 
23 #include "../common/sgmii_riser.h"
24 #include "../common/qixis.h"
25 
26 #define EMI1_MASK       0x1f
27 #define EMI1_RGMII0     1
28 #define EMI1_RGMII1     2
29 #define EMI1_RGMII2     3
30 #define EMI1_SGMII1     0x1c
31 #define EMI1_SGMII2     0x1d
32 
33 struct ls1021a_mdio {
34 	struct mii_dev *realbus;
35 };
36 
37 static void ls1021a_mux_mdio(int addr)
38 {
39 	u8 brdcfg4;
40 
41 	brdcfg4 = QIXIS_READ(brdcfg[4]);
42 	brdcfg4 &= EMI1_MASK;
43 
44 	switch (addr) {
45 	case EMI1_RGMII0:
46 		brdcfg4 |= 0;
47 		break;
48 	case EMI1_RGMII1:
49 		brdcfg4 |= 0x20;
50 		break;
51 	case EMI1_RGMII2:
52 		brdcfg4 |= 0x40;
53 		break;
54 	case EMI1_SGMII1:
55 		brdcfg4 |= 0x60;
56 		break;
57 	case EMI1_SGMII2:
58 		brdcfg4 |= 0x80;
59 		break;
60 	default:
61 		brdcfg4 |= 0xa0;
62 		break;
63 	}
64 
65 	QIXIS_WRITE(brdcfg[4], brdcfg4);
66 }
67 
68 static int ls1021a_mdio_read(struct mii_dev *bus, int addr, int devad,
69 			     int regnum)
70 {
71 	struct ls1021a_mdio *priv = bus->priv;
72 
73 	ls1021a_mux_mdio(addr);
74 
75 	return priv->realbus->read(priv->realbus, addr, devad, regnum);
76 }
77 
78 static int ls1021a_mdio_write(struct mii_dev *bus, int addr, int devad,
79 			      int regnum, u16 value)
80 {
81 	struct ls1021a_mdio *priv = bus->priv;
82 
83 	ls1021a_mux_mdio(addr);
84 
85 	return priv->realbus->write(priv->realbus, addr, devad, regnum, value);
86 }
87 
88 static int ls1021a_mdio_reset(struct mii_dev *bus)
89 {
90 	struct ls1021a_mdio *priv = bus->priv;
91 
92 	return priv->realbus->reset(priv->realbus);
93 }
94 
95 static int ls1021a_mdio_init(char *realbusname, char *fakebusname)
96 {
97 	struct ls1021a_mdio *lsmdio;
98 	struct mii_dev *bus = mdio_alloc();
99 
100 	if (!bus) {
101 		printf("Failed to allocate LS102xA MDIO bus\n");
102 		return -1;
103 	}
104 
105 	lsmdio = malloc(sizeof(*lsmdio));
106 	if (!lsmdio) {
107 		printf("Failed to allocate LS102xA private data\n");
108 		free(bus);
109 		return -1;
110 	}
111 
112 	bus->read = ls1021a_mdio_read;
113 	bus->write = ls1021a_mdio_write;
114 	bus->reset = ls1021a_mdio_reset;
115 	strcpy(bus->name, fakebusname);
116 
117 	lsmdio->realbus = miiphy_get_dev_by_name(realbusname);
118 
119 	if (!lsmdio->realbus) {
120 		printf("No bus with name %s\n", realbusname);
121 		free(bus);
122 		free(lsmdio);
123 		return -1;
124 	}
125 
126 	bus->priv = lsmdio;
127 
128 	return mdio_register(bus);
129 }
130 
131 int board_eth_init(bd_t *bis)
132 {
133 	struct fsl_pq_mdio_info mdio_info;
134 	struct tsec_info_struct tsec_info[3];
135 	int num = 0;
136 
137 #ifdef CONFIG_TSEC1
138 	SET_STD_TSEC_INFO(tsec_info[num], 1);
139 	if (is_serdes_configured(SGMII_TSEC1)) {
140 		puts("eTSEC1 is in sgmii mode\n");
141 		tsec_info[num].flags |= TSEC_SGMII;
142 		tsec_info[num].mii_devname = "LS1021A_SGMII_MDIO";
143 	} else {
144 		tsec_info[num].mii_devname = "LS1021A_RGMII_MDIO";
145 	}
146 	num++;
147 #endif
148 #ifdef CONFIG_TSEC2
149 	SET_STD_TSEC_INFO(tsec_info[num], 2);
150 	if (is_serdes_configured(SGMII_TSEC2)) {
151 		puts("eTSEC2 is in sgmii mode\n");
152 		tsec_info[num].flags |= TSEC_SGMII;
153 		tsec_info[num].mii_devname = "LS1021A_SGMII_MDIO";
154 	} else {
155 		tsec_info[num].mii_devname = "LS1021A_RGMII_MDIO";
156 	}
157 	num++;
158 #endif
159 #ifdef CONFIG_TSEC3
160 	SET_STD_TSEC_INFO(tsec_info[num], 3);
161 	tsec_info[num].mii_devname = "LS1021A_RGMII_MDIO";
162 	num++;
163 #endif
164 	if (!num) {
165 		printf("No TSECs initialized\n");
166 		return 0;
167 	}
168 
169 #ifdef CONFIG_FSL_SGMII_RISER
170 	fsl_sgmii_riser_init(tsec_info, num);
171 #endif
172 
173 	mdio_info.regs = (struct tsec_mii_mng *)CONFIG_SYS_MDIO_BASE_ADDR;
174 	mdio_info.name = DEFAULT_MII_NAME;
175 
176 	fsl_pq_mdio_init(bis, &mdio_info);
177 
178 	/* Register the virtual MDIO front-ends */
179 	ls1021a_mdio_init(DEFAULT_MII_NAME, "LS1021A_RGMII_MDIO");
180 	ls1021a_mdio_init(DEFAULT_MII_NAME, "LS1021A_SGMII_MDIO");
181 
182 	tsec_eth_init(bis, tsec_info, num);
183 
184 	return pci_eth_init(bis);
185 }
186