xref: /rk3399_rockchip-uboot/board/freescale/ls1021aqds/eth.c (revision 192bc6948b02ff4168cab16162fffb507946dc2b)
1550e3dc0SWang Huan /*
2550e3dc0SWang Huan  * Copyright 2014 Freescale Semiconductor, Inc.
3550e3dc0SWang Huan  *
4550e3dc0SWang Huan  * SPDX-License-Identifier:	GPL-2.0+
5550e3dc0SWang Huan  *
6550e3dc0SWang Huan  * This file handles the board muxing between the RGMII/SGMII PHYs on
7550e3dc0SWang Huan  * Freescale LS1021AQDS board. The RGMII PHYs are the three on-board 1Gb
8550e3dc0SWang Huan  * ports. The SGMII PHYs are provided by the standard Freescale four-port
9550e3dc0SWang Huan  * SGMII riser card.
10550e3dc0SWang Huan  *
11550e3dc0SWang Huan  * Muxing is handled via the PIXIS BRDCFG4 register. The EMI1 bits control
12550e3dc0SWang Huan  * muxing among the RGMII PHYs and the SGMII PHYs. The value for RGMII depends
13550e3dc0SWang Huan  * on which port is used. The value for SGMII depends on which slot the riser
14550e3dc0SWang Huan  * is inserted in.
15550e3dc0SWang Huan  */
16550e3dc0SWang Huan 
17550e3dc0SWang Huan #include <common.h>
18550e3dc0SWang Huan #include <netdev.h>
19550e3dc0SWang Huan #include <asm/arch/fsl_serdes.h>
20550e3dc0SWang Huan #include <fsl_mdio.h>
21550e3dc0SWang Huan #include <tsec.h>
22550e3dc0SWang Huan #include <malloc.h>
23550e3dc0SWang Huan 
24550e3dc0SWang Huan #include "../common/sgmii_riser.h"
25550e3dc0SWang Huan #include "../common/qixis.h"
26550e3dc0SWang Huan 
27550e3dc0SWang Huan #define EMI1_MASK       0x1f
28550e3dc0SWang Huan #define EMI1_RGMII0     1
29550e3dc0SWang Huan #define EMI1_RGMII1     2
30550e3dc0SWang Huan #define EMI1_RGMII2     3
31550e3dc0SWang Huan #define EMI1_SGMII1     0x1c
32550e3dc0SWang Huan #define EMI1_SGMII2     0x1d
33550e3dc0SWang Huan 
34550e3dc0SWang Huan struct ls1021a_mdio {
35550e3dc0SWang Huan 	struct mii_dev *realbus;
36550e3dc0SWang Huan };
37550e3dc0SWang Huan 
ls1021a_mux_mdio(int addr)38550e3dc0SWang Huan static void ls1021a_mux_mdio(int addr)
39550e3dc0SWang Huan {
40550e3dc0SWang Huan 	u8 brdcfg4;
41550e3dc0SWang Huan 
42550e3dc0SWang Huan 	brdcfg4 = QIXIS_READ(brdcfg[4]);
43550e3dc0SWang Huan 	brdcfg4 &= EMI1_MASK;
44550e3dc0SWang Huan 
45550e3dc0SWang Huan 	switch (addr) {
46550e3dc0SWang Huan 	case EMI1_RGMII0:
47550e3dc0SWang Huan 		brdcfg4 |= 0;
48550e3dc0SWang Huan 		break;
49550e3dc0SWang Huan 	case EMI1_RGMII1:
50550e3dc0SWang Huan 		brdcfg4 |= 0x20;
51550e3dc0SWang Huan 		break;
52550e3dc0SWang Huan 	case EMI1_RGMII2:
53550e3dc0SWang Huan 		brdcfg4 |= 0x40;
54550e3dc0SWang Huan 		break;
55550e3dc0SWang Huan 	case EMI1_SGMII1:
56550e3dc0SWang Huan 		brdcfg4 |= 0x60;
57550e3dc0SWang Huan 		break;
58550e3dc0SWang Huan 	case EMI1_SGMII2:
59550e3dc0SWang Huan 		brdcfg4 |= 0x80;
60550e3dc0SWang Huan 		break;
61550e3dc0SWang Huan 	default:
62550e3dc0SWang Huan 		brdcfg4 |= 0xa0;
63550e3dc0SWang Huan 		break;
64550e3dc0SWang Huan 	}
65550e3dc0SWang Huan 
66550e3dc0SWang Huan 	QIXIS_WRITE(brdcfg[4], brdcfg4);
67550e3dc0SWang Huan }
68550e3dc0SWang Huan 
ls1021a_mdio_read(struct mii_dev * bus,int addr,int devad,int regnum)69550e3dc0SWang Huan static int ls1021a_mdio_read(struct mii_dev *bus, int addr, int devad,
70550e3dc0SWang Huan 			     int regnum)
71550e3dc0SWang Huan {
72550e3dc0SWang Huan 	struct ls1021a_mdio *priv = bus->priv;
73550e3dc0SWang Huan 
74550e3dc0SWang Huan 	ls1021a_mux_mdio(addr);
75550e3dc0SWang Huan 
76550e3dc0SWang Huan 	return priv->realbus->read(priv->realbus, addr, devad, regnum);
77550e3dc0SWang Huan }
78550e3dc0SWang Huan 
ls1021a_mdio_write(struct mii_dev * bus,int addr,int devad,int regnum,u16 value)79550e3dc0SWang Huan static int ls1021a_mdio_write(struct mii_dev *bus, int addr, int devad,
80550e3dc0SWang Huan 			      int regnum, u16 value)
81550e3dc0SWang Huan {
82550e3dc0SWang Huan 	struct ls1021a_mdio *priv = bus->priv;
83550e3dc0SWang Huan 
84550e3dc0SWang Huan 	ls1021a_mux_mdio(addr);
85550e3dc0SWang Huan 
86550e3dc0SWang Huan 	return priv->realbus->write(priv->realbus, addr, devad, regnum, value);
87550e3dc0SWang Huan }
88550e3dc0SWang Huan 
ls1021a_mdio_reset(struct mii_dev * bus)89550e3dc0SWang Huan static int ls1021a_mdio_reset(struct mii_dev *bus)
90550e3dc0SWang Huan {
91550e3dc0SWang Huan 	struct ls1021a_mdio *priv = bus->priv;
92550e3dc0SWang Huan 
93550e3dc0SWang Huan 	return priv->realbus->reset(priv->realbus);
94550e3dc0SWang Huan }
95550e3dc0SWang Huan 
ls1021a_mdio_init(char * realbusname,char * fakebusname)96550e3dc0SWang Huan static int ls1021a_mdio_init(char *realbusname, char *fakebusname)
97550e3dc0SWang Huan {
98550e3dc0SWang Huan 	struct ls1021a_mdio *lsmdio;
99550e3dc0SWang Huan 	struct mii_dev *bus = mdio_alloc();
100550e3dc0SWang Huan 
101550e3dc0SWang Huan 	if (!bus) {
102550e3dc0SWang Huan 		printf("Failed to allocate LS102xA MDIO bus\n");
103550e3dc0SWang Huan 		return -1;
104550e3dc0SWang Huan 	}
105550e3dc0SWang Huan 
106550e3dc0SWang Huan 	lsmdio = malloc(sizeof(*lsmdio));
107550e3dc0SWang Huan 	if (!lsmdio) {
108550e3dc0SWang Huan 		printf("Failed to allocate LS102xA private data\n");
109550e3dc0SWang Huan 		free(bus);
110550e3dc0SWang Huan 		return -1;
111550e3dc0SWang Huan 	}
112550e3dc0SWang Huan 
113550e3dc0SWang Huan 	bus->read = ls1021a_mdio_read;
114550e3dc0SWang Huan 	bus->write = ls1021a_mdio_write;
115550e3dc0SWang Huan 	bus->reset = ls1021a_mdio_reset;
116*192bc694SBen Whitten 	strcpy(bus->name, fakebusname);
117550e3dc0SWang Huan 
118550e3dc0SWang Huan 	lsmdio->realbus = miiphy_get_dev_by_name(realbusname);
119550e3dc0SWang Huan 
120550e3dc0SWang Huan 	if (!lsmdio->realbus) {
121550e3dc0SWang Huan 		printf("No bus with name %s\n", realbusname);
122550e3dc0SWang Huan 		free(bus);
123550e3dc0SWang Huan 		free(lsmdio);
124550e3dc0SWang Huan 		return -1;
125550e3dc0SWang Huan 	}
126550e3dc0SWang Huan 
127550e3dc0SWang Huan 	bus->priv = lsmdio;
128550e3dc0SWang Huan 
129550e3dc0SWang Huan 	return mdio_register(bus);
130550e3dc0SWang Huan }
131550e3dc0SWang Huan 
board_eth_init(bd_t * bis)132550e3dc0SWang Huan int board_eth_init(bd_t *bis)
133550e3dc0SWang Huan {
134550e3dc0SWang Huan 	struct fsl_pq_mdio_info mdio_info;
135550e3dc0SWang Huan 	struct tsec_info_struct tsec_info[3];
136550e3dc0SWang Huan 	int num = 0;
137550e3dc0SWang Huan 
138550e3dc0SWang Huan #ifdef CONFIG_TSEC1
139550e3dc0SWang Huan 	SET_STD_TSEC_INFO(tsec_info[num], 1);
140550e3dc0SWang Huan 	if (is_serdes_configured(SGMII_TSEC1)) {
141550e3dc0SWang Huan 		puts("eTSEC1 is in sgmii mode\n");
142550e3dc0SWang Huan 		tsec_info[num].flags |= TSEC_SGMII;
143550e3dc0SWang Huan 		tsec_info[num].mii_devname = "LS1021A_SGMII_MDIO";
144550e3dc0SWang Huan 	} else {
145550e3dc0SWang Huan 		tsec_info[num].mii_devname = "LS1021A_RGMII_MDIO";
146550e3dc0SWang Huan 	}
147550e3dc0SWang Huan 	num++;
148550e3dc0SWang Huan #endif
149550e3dc0SWang Huan #ifdef CONFIG_TSEC2
150550e3dc0SWang Huan 	SET_STD_TSEC_INFO(tsec_info[num], 2);
151550e3dc0SWang Huan 	if (is_serdes_configured(SGMII_TSEC2)) {
152550e3dc0SWang Huan 		puts("eTSEC2 is in sgmii mode\n");
153550e3dc0SWang Huan 		tsec_info[num].flags |= TSEC_SGMII;
154550e3dc0SWang Huan 		tsec_info[num].mii_devname = "LS1021A_SGMII_MDIO";
155550e3dc0SWang Huan 	} else {
156550e3dc0SWang Huan 		tsec_info[num].mii_devname = "LS1021A_RGMII_MDIO";
157550e3dc0SWang Huan 	}
158550e3dc0SWang Huan 	num++;
159550e3dc0SWang Huan #endif
160550e3dc0SWang Huan #ifdef CONFIG_TSEC3
161550e3dc0SWang Huan 	SET_STD_TSEC_INFO(tsec_info[num], 3);
162550e3dc0SWang Huan 	tsec_info[num].mii_devname = "LS1021A_RGMII_MDIO";
163550e3dc0SWang Huan 	num++;
164550e3dc0SWang Huan #endif
165550e3dc0SWang Huan 	if (!num) {
166550e3dc0SWang Huan 		printf("No TSECs initialized\n");
167550e3dc0SWang Huan 		return 0;
168550e3dc0SWang Huan 	}
169550e3dc0SWang Huan 
170550e3dc0SWang Huan #ifdef CONFIG_FSL_SGMII_RISER
171550e3dc0SWang Huan 	fsl_sgmii_riser_init(tsec_info, num);
172550e3dc0SWang Huan #endif
173550e3dc0SWang Huan 
174550e3dc0SWang Huan 	mdio_info.regs = (struct tsec_mii_mng *)CONFIG_SYS_MDIO_BASE_ADDR;
175550e3dc0SWang Huan 	mdio_info.name = DEFAULT_MII_NAME;
176550e3dc0SWang Huan 
177550e3dc0SWang Huan 	fsl_pq_mdio_init(bis, &mdio_info);
178550e3dc0SWang Huan 
179550e3dc0SWang Huan 	/* Register the virtual MDIO front-ends */
180550e3dc0SWang Huan 	ls1021a_mdio_init(DEFAULT_MII_NAME, "LS1021A_RGMII_MDIO");
181550e3dc0SWang Huan 	ls1021a_mdio_init(DEFAULT_MII_NAME, "LS1021A_SGMII_MDIO");
182550e3dc0SWang Huan 
183550e3dc0SWang Huan 	tsec_eth_init(bis, tsec_info, num);
184550e3dc0SWang Huan 
185550e3dc0SWang Huan 	return pci_eth_init(bis);
186550e3dc0SWang Huan }
187