ramips: add v4.9 support
[librecmc/librecmc.git] / target / linux / ramips / files-4.9 / drivers / net / ethernet / mtk / mdio_rt2880.c
1 /*   This program is free software; you can redistribute it and/or modify
2  *   it under the terms of the GNU General Public License as published by
3  *   the Free Software Foundation; version 2 of the License
4  *
5  *   This program is distributed in the hope that it will be useful,
6  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
7  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
8  *   GNU General Public License for more details.
9  *
10  *   Copyright (C) 2009-2015 John Crispin <blogic@openwrt.org>
11  *   Copyright (C) 2009-2015 Felix Fietkau <nbd@nbd.name>
12  *   Copyright (C) 2013-2015 Michael Lee <igvtee@gmail.com>
13  */
14
15 #include <linux/module.h>
16 #include <linux/kernel.h>
17 #include <linux/types.h>
18 #include <linux/of_net.h>
19 #include <linux/of_mdio.h>
20
21 #include "mtk_eth_soc.h"
22 #include "mdio_rt2880.h"
23 #include "mdio.h"
24
25 #define FE_MDIO_RETRY   1000
26
27 static unsigned char *rt2880_speed_str(struct fe_priv *priv)
28 {
29         switch (priv->phy->speed[0]) {
30         case SPEED_1000:
31                 return "1000";
32         case SPEED_100:
33                 return "100";
34         case SPEED_10:
35                 return "10";
36         }
37
38         return "?";
39 }
40
41 void rt2880_mdio_link_adjust(struct fe_priv *priv, int port)
42 {
43         u32 mdio_cfg;
44
45         if (!priv->link[0]) {
46                 netif_carrier_off(priv->netdev);
47                 netdev_info(priv->netdev, "link down\n");
48                 return;
49         }
50
51         mdio_cfg = FE_MDIO_CFG_TX_CLK_SKEW_200 |
52                    FE_MDIO_CFG_RX_CLK_SKEW_200 |
53                    FE_MDIO_CFG_GP1_FRC_EN;
54
55         if (priv->phy->duplex[0] == DUPLEX_FULL)
56                 mdio_cfg |= FE_MDIO_CFG_GP1_DUPLEX;
57
58         if (priv->phy->tx_fc[0])
59                 mdio_cfg |= FE_MDIO_CFG_GP1_FC_TX;
60
61         if (priv->phy->rx_fc[0])
62                 mdio_cfg |= FE_MDIO_CFG_GP1_FC_RX;
63
64         switch (priv->phy->speed[0]) {
65         case SPEED_10:
66                 mdio_cfg |= FE_MDIO_CFG_GP1_SPEED_10;
67                 break;
68         case SPEED_100:
69                 mdio_cfg |= FE_MDIO_CFG_GP1_SPEED_100;
70                 break;
71         case SPEED_1000:
72                 mdio_cfg |= FE_MDIO_CFG_GP1_SPEED_1000;
73                 break;
74         default:
75                 BUG();
76         }
77
78         fe_w32(mdio_cfg, FE_MDIO_CFG);
79
80         netif_carrier_on(priv->netdev);
81         netdev_info(priv->netdev, "link up (%sMbps/%s duplex)\n",
82                     rt2880_speed_str(priv),
83                     (priv->phy->duplex[0] == DUPLEX_FULL) ? "Full" : "Half");
84 }
85
86 static int rt2880_mdio_wait_ready(struct fe_priv *priv)
87 {
88         int retries;
89
90         retries = FE_MDIO_RETRY;
91         while (1) {
92                 u32 t;
93
94                 t = fe_r32(FE_MDIO_ACCESS);
95                 if ((t & BIT(31)) == 0)
96                         return 0;
97
98                 if (retries-- == 0)
99                         break;
100
101                 udelay(1);
102         }
103
104         dev_err(priv->device, "MDIO operation timed out\n");
105         return -ETIMEDOUT;
106 }
107
108 int rt2880_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg)
109 {
110         struct fe_priv *priv = bus->priv;
111         int err;
112         u32 t;
113
114         err = rt2880_mdio_wait_ready(priv);
115         if (err)
116                 return 0xffff;
117
118         t = (phy_addr << 24) | (phy_reg << 16);
119         fe_w32(t, FE_MDIO_ACCESS);
120         t |= BIT(31);
121         fe_w32(t, FE_MDIO_ACCESS);
122
123         err = rt2880_mdio_wait_ready(priv);
124         if (err)
125                 return 0xffff;
126
127         pr_debug("%s: addr=%04x, reg=%04x, value=%04x\n", __func__,
128                  phy_addr, phy_reg, fe_r32(FE_MDIO_ACCESS) & 0xffff);
129
130         return fe_r32(FE_MDIO_ACCESS) & 0xffff;
131 }
132
133 int rt2880_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val)
134 {
135         struct fe_priv *priv = bus->priv;
136         int err;
137         u32 t;
138
139         pr_debug("%s: addr=%04x, reg=%04x, value=%04x\n", __func__,
140                  phy_addr, phy_reg, fe_r32(FE_MDIO_ACCESS) & 0xffff);
141
142         err = rt2880_mdio_wait_ready(priv);
143         if (err)
144                 return err;
145
146         t = (1 << 30) | (phy_addr << 24) | (phy_reg << 16) | val;
147         fe_w32(t, FE_MDIO_ACCESS);
148         t |= BIT(31);
149         fe_w32(t, FE_MDIO_ACCESS);
150
151         return rt2880_mdio_wait_ready(priv);
152 }
153
154 void rt2880_port_init(struct fe_priv *priv, struct device_node *np)
155 {
156         const __be32 *id = of_get_property(np, "reg", NULL);
157         const __be32 *link;
158         int size;
159         int phy_mode;
160
161         if (!id || (be32_to_cpu(*id) != 0)) {
162                 pr_err("%s: invalid port id\n", np->name);
163                 return;
164         }
165
166         priv->phy->phy_fixed[0] = of_get_property(np,
167                                                   "mediatek,fixed-link", &size);
168         if (priv->phy->phy_fixed[0] &&
169             (size != (4 * sizeof(*priv->phy->phy_fixed[0])))) {
170                 pr_err("%s: invalid fixed link property\n", np->name);
171                 priv->phy->phy_fixed[0] = NULL;
172                 return;
173         }
174
175         phy_mode = of_get_phy_mode(np);
176         switch (phy_mode) {
177         case PHY_INTERFACE_MODE_RGMII:
178                 break;
179         case PHY_INTERFACE_MODE_MII:
180                 break;
181         case PHY_INTERFACE_MODE_RMII:
182                 break;
183         default:
184                 if (!priv->phy->phy_fixed[0])
185                         dev_err(priv->device, "port %d - invalid phy mode\n",
186                                 priv->phy->speed[0]);
187                 break;
188         }
189
190         priv->phy->phy_node[0] = of_parse_phandle(np, "phy-handle", 0);
191         if (!priv->phy->phy_node[0] && !priv->phy->phy_fixed[0])
192                 return;
193
194         if (priv->phy->phy_fixed[0]) {
195                 link = priv->phy->phy_fixed[0];
196                 priv->phy->speed[0] = be32_to_cpup(link++);
197                 priv->phy->duplex[0] = be32_to_cpup(link++);
198                 priv->phy->tx_fc[0] = be32_to_cpup(link++);
199                 priv->phy->rx_fc[0] = be32_to_cpup(link++);
200
201                 priv->link[0] = 1;
202                 switch (priv->phy->speed[0]) {
203                 case SPEED_10:
204                         break;
205                 case SPEED_100:
206                         break;
207                 case SPEED_1000:
208                         break;
209                 default:
210                         dev_err(priv->device, "invalid link speed: %d\n",
211                                 priv->phy->speed[0]);
212                         priv->phy->phy_fixed[0] = 0;
213                         return;
214                 }
215                 dev_info(priv->device, "using fixed link parameters\n");
216                 rt2880_mdio_link_adjust(priv, 0);
217                 return;
218         }
219
220         if (priv->phy->phy_node[0] && mdiobus_get_phy(priv->mii_bus, 0))
221                 fe_connect_phy_node(priv, priv->phy->phy_node[0]);
222 }