net: Add MSCC ServalT network driver.
[oweals/u-boot.git] / drivers / net / pfe_eth / pfe_mdio.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2015-2016 Freescale Semiconductor, Inc.
4  * Copyright 2017 NXP
5  */
6 #include <common.h>
7 #include <dm.h>
8 #include <dm/platform_data/pfe_dm_eth.h>
9 #include <net.h>
10 #include <net/pfe_eth/pfe_eth.h>
11
12 extern struct gemac_s gem_info[];
13 #if defined(CONFIG_PHYLIB)
14
15 #define MDIO_TIMEOUT    5000
16 static int pfe_write_addr(struct mii_dev *bus, int phy_addr, int dev_addr,
17                           int reg_addr)
18 {
19         void *reg_base = bus->priv;
20         u32 devadr;
21         u32 phy;
22         u32 reg_data;
23         int timeout = MDIO_TIMEOUT;
24
25         devadr = ((dev_addr & EMAC_MII_DATA_RA_MASK) << EMAC_MII_DATA_RA_SHIFT);
26         phy = ((phy_addr & EMAC_MII_DATA_PA_MASK) << EMAC_MII_DATA_PA_SHIFT);
27
28         reg_data = (EMAC_MII_DATA_TA | phy | devadr | reg_addr);
29
30         writel(reg_data, reg_base + EMAC_MII_DATA_REG);
31
32         /*
33          * wait for the MII interrupt
34          */
35         while (!(readl(reg_base + EMAC_IEVENT_REG) & EMAC_IEVENT_MII)) {
36                 if (timeout-- <= 0) {
37                         printf("Phy MDIO read/write timeout\n");
38                         return -1;
39                 }
40         }
41
42         /*
43          * clear MII interrupt
44          */
45         writel(EMAC_IEVENT_MII, reg_base + EMAC_IEVENT_REG);
46
47         return 0;
48 }
49
50 static int pfe_phy_read(struct mii_dev *bus, int phy_addr, int dev_addr,
51                         int reg_addr)
52 {
53         void *reg_base = bus->priv;
54         u32 reg;
55         u32 phy;
56         u32 reg_data;
57         u16 val;
58         int timeout = MDIO_TIMEOUT;
59
60         if (dev_addr == MDIO_DEVAD_NONE) {
61                 reg = ((reg_addr & EMAC_MII_DATA_RA_MASK) <<
62                         EMAC_MII_DATA_RA_SHIFT);
63         } else {
64                 pfe_write_addr(bus, phy_addr, dev_addr, reg_addr);
65                 reg = ((dev_addr & EMAC_MII_DATA_RA_MASK) <<
66                        EMAC_MII_DATA_RA_SHIFT);
67         }
68
69         phy = ((phy_addr & EMAC_MII_DATA_PA_MASK) << EMAC_MII_DATA_PA_SHIFT);
70
71         if (dev_addr == MDIO_DEVAD_NONE)
72                 reg_data = (EMAC_MII_DATA_ST | EMAC_MII_DATA_OP_RD |
73                             EMAC_MII_DATA_TA | phy | reg);
74         else
75                 reg_data = (EMAC_MII_DATA_OP_CL45_RD | EMAC_MII_DATA_TA |
76                             phy | reg);
77
78         writel(reg_data, reg_base + EMAC_MII_DATA_REG);
79
80         /*
81          * wait for the MII interrupt
82          */
83         while (!(readl(reg_base + EMAC_IEVENT_REG) & EMAC_IEVENT_MII)) {
84                 if (timeout-- <= 0) {
85                         printf("Phy MDIO read/write timeout\n");
86                         return -1;
87                 }
88         }
89
90         /*
91          * clear MII interrupt
92          */
93         writel(EMAC_IEVENT_MII, reg_base + EMAC_IEVENT_REG);
94
95         /*
96          * it's now safe to read the PHY's register
97          */
98         val = (u16)readl(reg_base + EMAC_MII_DATA_REG);
99         debug("%s: %p phy: 0x%x reg:0x%08x val:%#x\n", __func__, reg_base,
100               phy_addr, reg_addr, val);
101
102         return val;
103 }
104
105 static int pfe_phy_write(struct mii_dev *bus, int phy_addr, int dev_addr,
106                          int reg_addr, u16 data)
107 {
108         void *reg_base = bus->priv;
109         u32 reg;
110         u32 phy;
111         u32 reg_data;
112         int timeout = MDIO_TIMEOUT;
113         int val;
114
115         if (dev_addr == MDIO_DEVAD_NONE) {
116                 reg = ((reg_addr & EMAC_MII_DATA_RA_MASK) <<
117                        EMAC_MII_DATA_RA_SHIFT);
118         } else {
119                 pfe_write_addr(bus, phy_addr, dev_addr, reg_addr);
120                 reg = ((dev_addr & EMAC_MII_DATA_RA_MASK) <<
121                        EMAC_MII_DATA_RA_SHIFT);
122         }
123
124         phy = ((phy_addr & EMAC_MII_DATA_PA_MASK) << EMAC_MII_DATA_PA_SHIFT);
125
126         if (dev_addr == MDIO_DEVAD_NONE)
127                 reg_data = (EMAC_MII_DATA_ST | EMAC_MII_DATA_OP_WR |
128                             EMAC_MII_DATA_TA | phy | reg | data);
129         else
130                 reg_data = (EMAC_MII_DATA_OP_CL45_WR | EMAC_MII_DATA_TA |
131                             phy | reg | data);
132
133         writel(reg_data, reg_base + EMAC_MII_DATA_REG);
134
135         /*
136          * wait for the MII interrupt
137          */
138         while (!(readl(reg_base + EMAC_IEVENT_REG) & EMAC_IEVENT_MII)) {
139                 if (timeout-- <= 0) {
140                         printf("Phy MDIO read/write timeout\n");
141                         return -1;
142                 }
143         }
144
145         /*
146          * clear MII interrupt
147          */
148         writel(EMAC_IEVENT_MII, reg_base + EMAC_IEVENT_REG);
149
150         debug("%s: phy: %02x reg:%02x val:%#x\n", __func__, phy_addr,
151               reg_addr, data);
152
153         return val;
154 }
155
156 static void pfe_configure_serdes(struct pfe_eth_dev *priv)
157 {
158         struct mii_dev bus;
159         int value, sgmii_2500 = 0;
160         struct gemac_s *gem = priv->gem;
161
162         if (gem->phy_mode == PHY_INTERFACE_MODE_SGMII_2500)
163                 sgmii_2500 = 1;
164
165
166         /* PCS configuration done with corresponding GEMAC */
167         bus.priv = gem_info[priv->gemac_port].gemac_base;
168
169         pfe_phy_read(&bus, 0, MDIO_DEVAD_NONE, 0x0);
170         pfe_phy_read(&bus, 0, MDIO_DEVAD_NONE, 0x1);
171         pfe_phy_read(&bus, 0, MDIO_DEVAD_NONE, 0x2);
172         pfe_phy_read(&bus, 0, MDIO_DEVAD_NONE, 0x3);
173
174         /* Reset serdes */
175         pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x0, 0x8000);
176
177         /* SGMII IF mode + AN enable only for 1G SGMII, not for 2.5G */
178         value = PHY_SGMII_IF_MODE_SGMII;
179         if (!sgmii_2500)
180                 value |= PHY_SGMII_IF_MODE_AN;
181         else
182                 value |= PHY_SGMII_IF_MODE_SGMII_GBT;
183
184         pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x14, value);
185
186         /* Dev ability according to SGMII specification */
187         value = PHY_SGMII_DEV_ABILITY_SGMII;
188         pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x4, value);
189
190         /* These values taken from validation team */
191         if (!sgmii_2500) {
192                 pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x13, 0x0);
193                 pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x12, 0x400);
194         } else {
195                 pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x13, 0x7);
196                 pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x12, 0xa120);
197         }
198
199         /* Restart AN */
200         value = PHY_SGMII_CR_DEF_VAL;
201         if (!sgmii_2500)
202                 value |= PHY_SGMII_CR_RESET_AN;
203         /* Disable Auto neg for 2.5G SGMII as it doesn't support auto neg*/
204         if (sgmii_2500)
205                 value &= ~PHY_SGMII_ENABLE_AN;
206         pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0, value);
207 }
208
209 int pfe_phy_configure(struct pfe_eth_dev *priv, int dev_id, int phy_id)
210 {
211         struct phy_device *phydev = NULL;
212         struct udevice *dev = priv->dev;
213         struct gemac_s *gem = priv->gem;
214         struct ccsr_scfg *scfg = (struct ccsr_scfg *)CONFIG_SYS_FSL_SCFG_ADDR;
215
216         if (!gem->bus)
217                 return -1;
218
219         /* Configure SGMII  PCS */
220         if (gem->phy_mode == PHY_INTERFACE_MODE_SGMII ||
221             gem->phy_mode == PHY_INTERFACE_MODE_SGMII_2500) {
222                 out_be32(&scfg->mdioselcr, 0x00000000);
223                 pfe_configure_serdes(priv);
224         }
225
226         mdelay(100);
227
228         /* By this time on-chip SGMII initialization is done
229          * we can switch mdio interface to external PHYs
230          */
231         out_be32(&scfg->mdioselcr, 0x80000000);
232
233         phydev = phy_connect(gem->bus, phy_id, dev, gem->phy_mode);
234         if (!phydev) {
235                 printf("phy_connect failed\n");
236                 return -ENODEV;
237         }
238
239         phy_config(phydev);
240
241         priv->phydev = phydev;
242
243         return 0;
244 }
245 #endif
246
247 struct mii_dev *pfe_mdio_init(struct pfe_mdio_info *mdio_info)
248 {
249         struct mii_dev *bus;
250         int ret;
251         u32 mdio_speed;
252         u32 pclk = 250000000;
253
254         bus = mdio_alloc();
255         if (!bus) {
256                 printf("mdio_alloc failed\n");
257                 return NULL;
258         }
259         bus->read = pfe_phy_read;
260         bus->write = pfe_phy_write;
261
262         /* MAC1 MDIO used to communicate with external PHYS */
263         bus->priv = mdio_info->reg_base;
264         sprintf(bus->name, mdio_info->name);
265
266         /* configure mdio speed */
267         mdio_speed = (DIV_ROUND_UP(pclk, 4000000) << EMAC_MII_SPEED_SHIFT);
268         mdio_speed |= EMAC_HOLDTIME(0x5);
269         writel(mdio_speed, mdio_info->reg_base + EMAC_MII_CTRL_REG);
270
271         ret = mdio_register(bus);
272         if (ret) {
273                 printf("mdio_register failed\n");
274                 free(bus);
275                 return NULL;
276         }
277         return bus;
278 }
279
280 void pfe_set_mdio(int dev_id, struct mii_dev *bus)
281 {
282         gem_info[dev_id].bus = bus;
283 }
284
285 void pfe_set_phy_address_mode(int dev_id, int phy_id, int phy_mode)
286 {
287         gem_info[dev_id].phy_address = phy_id;
288         gem_info[dev_id].phy_mode  = phy_mode;
289 }