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