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