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