blob: d0a98836e2b8155be41eb6664d75ef52191575a2 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Wang Huanf0ce7d62014-09-05 13:52:44 +08002/*
3 * Copyright 2014 Freescale Semiconductor, Inc.
4 *
Wang Huanf0ce7d62014-09-05 13:52:44 +08005 * 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
33struct ls1021a_mdio {
34 struct mii_dev *realbus;
35};
36
37static 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
68static 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
78static 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
88static 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
95static 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;
Ben Whitten34fd6c92015-12-30 13:05:58 +0000115 strcpy(bus->name, fakebusname);
Wang Huanf0ce7d62014-09-05 13:52:44 +0800116
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
131int 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}