]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/freescale/ls1021aqds/eth.c
Merge branch 'u-boot-ti/master' into 'u-boot-arm/master'
[karo-tx-uboot.git] / board / freescale / ls1021aqds / eth.c
1 /*
2  * Copyright 2014 Freescale Semiconductor, Inc.
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  *
6  * This file handles the board muxing between the RGMII/SGMII PHYs on
7  * Freescale LS1021AQDS board. The RGMII PHYs are the three on-board 1Gb
8  * ports. The SGMII PHYs are provided by the standard Freescale four-port
9  * SGMII riser card.
10  *
11  * Muxing is handled via the PIXIS BRDCFG4 register. The EMI1 bits control
12  * muxing among the RGMII PHYs and the SGMII PHYs. The value for RGMII depends
13  * on which port is used. The value for SGMII depends on which slot the riser
14  * is inserted in.
15  */
16
17 #include <common.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
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
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
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
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
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         sprintf(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
132 int board_eth_init(bd_t *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 }