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