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