]> Pileus Git - ~andy/linux/blob - drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
Merge branch 'liblockdep-fixes' of https://github.com/sashalevin/liblockdep into...
[~andy/linux] / drivers / net / ethernet / stmicro / stmmac / dwmac-sti.c
1 /**
2  * dwmac-sti.c - STMicroelectronics DWMAC Specific Glue layer
3  *
4  * Copyright (C) 2003-2014 STMicroelectronics (R&D) Limited
5  * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
6  *
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  */
13
14 #include <linux/kernel.h>
15 #include <linux/slab.h>
16 #include <linux/platform_device.h>
17 #include <linux/stmmac.h>
18 #include <linux/phy.h>
19 #include <linux/mfd/syscon.h>
20 #include <linux/regmap.h>
21 #include <linux/clk.h>
22 #include <linux/of.h>
23 #include <linux/of_net.h>
24
25 /**
26  *                      STi GMAC glue logic.
27  *                      --------------------
28  *
29  *               _
30  *              |  \
31  *      --------|0  \ ETH_SEL_INTERNAL_NOTEXT_PHYCLK
32  * phyclk       |    |___________________________________________
33  *              |    |  |                       (phyclk-in)
34  *      --------|1  /   |
35  * int-clk      |_ /    |
36  *                      |        _
37  *                      |       |  \
38  *                      |_______|1  \ ETH_SEL_TX_RETIME_CLK
39  *                              |    |___________________________
40  *                              |    |          (tx-retime-clk)
41  *                       _______|0  /
42  *                      |       |_ /
43  *               _      |
44  *              |  \    |
45  *      --------|0  \   |
46  * clk_125      |    |__|
47  *              |    |  ETH_SEL_TXCLK_NOT_CLK125
48  *      --------|1  /
49  * txclk        |_ /
50  *
51  *
52  * ETH_SEL_INTERNAL_NOTEXT_PHYCLK is valid only for RMII where PHY can
53  * generate 50MHz clock or MAC can generate it.
54  * This bit is configured by "st,ext-phyclk" property.
55  *
56  * ETH_SEL_TXCLK_NOT_CLK125 is only valid for gigabit modes, where the 125Mhz
57  * clock either comes from clk-125 pin or txclk pin. This configuration is
58  * totally driven by the board wiring. This bit is configured by
59  * "st,tx-retime-src" property.
60  *
61  * TXCLK configuration is different for different phy interface modes
62  * and changes according to link speed in modes like RGMII.
63  *
64  * Below table summarizes the clock requirement and clock sources for
65  * supported phy interface modes with link speeds.
66  * ________________________________________________
67  *|  PHY_MODE   | 1000 Mbit Link | 100 Mbit Link   |
68  * ------------------------------------------------
69  *|     MII     |       n/a      |      25Mhz      |
70  *|             |                |      txclk      |
71  * ------------------------------------------------
72  *|     GMII    |     125Mhz     |      25Mhz      |
73  *|             |  clk-125/txclk |      txclk      |
74  * ------------------------------------------------
75  *|     RGMII   |     125Mhz     |      25Mhz      |
76  *|             |  clk-125/txclk |      clkgen     |
77  * ------------------------------------------------
78  *|     RMII    |       n/a      |      25Mhz      |
79  *|             |                |clkgen/phyclk-in |
80  * ------------------------------------------------
81  *
82  * TX lines are always retimed with a clk, which can vary depending
83  * on the board configuration. Below is the table of these bits
84  * in eth configuration register depending on source of retime clk.
85  *
86  *---------------------------------------------------------------
87  * src   | tx_rt_clk    | int_not_ext_phyclk    | txclk_n_clk125|
88  *---------------------------------------------------------------
89  * txclk |      0       |       n/a             |       1       |
90  *---------------------------------------------------------------
91  * ck_125|      0       |       n/a             |       0       |
92  *---------------------------------------------------------------
93  * phyclk|      1       |       0               |       n/a     |
94  *---------------------------------------------------------------
95  * clkgen|      1       |       1               |       n/a     |
96  *---------------------------------------------------------------
97  */
98
99  /* Register definition */
100
101  /* 3 bits [8:6]
102   *  [6:6]      ETH_SEL_TXCLK_NOT_CLK125
103   *  [7:7]      ETH_SEL_INTERNAL_NOTEXT_PHYCLK
104   *  [8:8]      ETH_SEL_TX_RETIME_CLK
105   *
106   */
107
108 #define TX_RETIME_SRC_MASK              GENMASK(8, 6)
109 #define ETH_SEL_TX_RETIME_CLK           BIT(8)
110 #define ETH_SEL_INTERNAL_NOTEXT_PHYCLK  BIT(7)
111 #define ETH_SEL_TXCLK_NOT_CLK125        BIT(6)
112
113 #define ENMII_MASK                      GENMASK(5, 5)
114 #define ENMII                           BIT(5)
115
116 /**
117  * 3 bits [4:2]
118  *      000-GMII/MII
119  *      001-RGMII
120  *      010-SGMII
121  *      100-RMII
122 */
123 #define MII_PHY_SEL_MASK                GENMASK(4, 2)
124 #define ETH_PHY_SEL_RMII                BIT(4)
125 #define ETH_PHY_SEL_SGMII               BIT(3)
126 #define ETH_PHY_SEL_RGMII               BIT(2)
127 #define ETH_PHY_SEL_GMII                0x0
128 #define ETH_PHY_SEL_MII                 0x0
129
130 #define IS_PHY_IF_MODE_RGMII(iface)     (iface == PHY_INTERFACE_MODE_RGMII || \
131                         iface == PHY_INTERFACE_MODE_RGMII_ID || \
132                         iface == PHY_INTERFACE_MODE_RGMII_RXID || \
133                         iface == PHY_INTERFACE_MODE_RGMII_TXID)
134
135 #define IS_PHY_IF_MODE_GBIT(iface)      (IS_PHY_IF_MODE_RGMII(iface) || \
136                         iface == PHY_INTERFACE_MODE_GMII)
137
138 struct sti_dwmac {
139         int interface;
140         bool ext_phyclk;
141         bool is_tx_retime_src_clk_125;
142         struct clk *clk;
143         int reg;
144         struct device *dev;
145         struct regmap *regmap;
146 };
147
148 static u32 phy_intf_sels[] = {
149         [PHY_INTERFACE_MODE_MII] = ETH_PHY_SEL_MII,
150         [PHY_INTERFACE_MODE_GMII] = ETH_PHY_SEL_GMII,
151         [PHY_INTERFACE_MODE_RGMII] = ETH_PHY_SEL_RGMII,
152         [PHY_INTERFACE_MODE_RGMII_ID] = ETH_PHY_SEL_RGMII,
153         [PHY_INTERFACE_MODE_SGMII] = ETH_PHY_SEL_SGMII,
154         [PHY_INTERFACE_MODE_RMII] = ETH_PHY_SEL_RMII,
155 };
156
157 enum {
158         TX_RETIME_SRC_NA = 0,
159         TX_RETIME_SRC_TXCLK = 1,
160         TX_RETIME_SRC_CLK_125,
161         TX_RETIME_SRC_PHYCLK,
162         TX_RETIME_SRC_CLKGEN,
163 };
164
165 static const char *const tx_retime_srcs[] = {
166         [TX_RETIME_SRC_NA] = "",
167         [TX_RETIME_SRC_TXCLK] = "txclk",
168         [TX_RETIME_SRC_CLK_125] = "clk_125",
169         [TX_RETIME_SRC_PHYCLK] = "phyclk",
170         [TX_RETIME_SRC_CLKGEN] = "clkgen",
171 };
172
173 static u32 tx_retime_val[] = {
174         [TX_RETIME_SRC_TXCLK] = ETH_SEL_TXCLK_NOT_CLK125,
175         [TX_RETIME_SRC_CLK_125] = 0x0,
176         [TX_RETIME_SRC_PHYCLK] = ETH_SEL_TX_RETIME_CLK,
177         [TX_RETIME_SRC_CLKGEN] = ETH_SEL_TX_RETIME_CLK |
178             ETH_SEL_INTERNAL_NOTEXT_PHYCLK,
179 };
180
181 static void setup_retime_src(struct sti_dwmac *dwmac, u32 spd)
182 {
183         u32 src = 0, freq = 0;
184
185         if (spd == SPEED_100) {
186                 if (dwmac->interface == PHY_INTERFACE_MODE_MII ||
187                     dwmac->interface == PHY_INTERFACE_MODE_GMII) {
188                         src = TX_RETIME_SRC_TXCLK;
189                 } else if (dwmac->interface == PHY_INTERFACE_MODE_RMII) {
190                         if (dwmac->ext_phyclk) {
191                                 src = TX_RETIME_SRC_PHYCLK;
192                         } else {
193                                 src = TX_RETIME_SRC_CLKGEN;
194                                 freq = 50000000;
195                         }
196
197                 } else if (IS_PHY_IF_MODE_RGMII(dwmac->interface)) {
198                         src = TX_RETIME_SRC_CLKGEN;
199                         freq = 25000000;
200                 }
201
202                 if (src == TX_RETIME_SRC_CLKGEN && dwmac->clk)
203                         clk_set_rate(dwmac->clk, freq);
204
205         } else if (spd == SPEED_1000) {
206                 if (dwmac->is_tx_retime_src_clk_125)
207                         src = TX_RETIME_SRC_CLK_125;
208                 else
209                         src = TX_RETIME_SRC_TXCLK;
210         }
211
212         regmap_update_bits(dwmac->regmap, dwmac->reg,
213                            TX_RETIME_SRC_MASK, tx_retime_val[src]);
214 }
215
216 static void sti_dwmac_exit(struct platform_device *pdev, void *priv)
217 {
218         struct sti_dwmac *dwmac = priv;
219
220         if (dwmac->clk)
221                 clk_disable_unprepare(dwmac->clk);
222 }
223
224 static void sti_fix_mac_speed(void *priv, unsigned int spd)
225 {
226         struct sti_dwmac *dwmac = priv;
227
228         setup_retime_src(dwmac, spd);
229
230         return;
231 }
232
233 static int sti_dwmac_parse_data(struct sti_dwmac *dwmac,
234                                 struct platform_device *pdev)
235 {
236         struct resource *res;
237         struct device *dev = &pdev->dev;
238         struct device_node *np = dev->of_node;
239         struct regmap *regmap;
240         int err;
241
242         if (!np)
243                 return -EINVAL;
244
245         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sti-ethconf");
246         if (!res)
247                 return -ENODATA;
248
249         regmap = syscon_regmap_lookup_by_phandle(np, "st,syscon");
250         if (IS_ERR(regmap))
251                 return PTR_ERR(regmap);
252
253         dwmac->dev = dev;
254         dwmac->interface = of_get_phy_mode(np);
255         dwmac->regmap = regmap;
256         dwmac->reg = res->start;
257         dwmac->ext_phyclk = of_property_read_bool(np, "st,ext-phyclk");
258         dwmac->is_tx_retime_src_clk_125 = false;
259
260         if (IS_PHY_IF_MODE_GBIT(dwmac->interface)) {
261                 const char *rs;
262
263                 err = of_property_read_string(np, "st,tx-retime-src", &rs);
264                 if (err < 0) {
265                         dev_err(dev, "st,tx-retime-src not specified\n");
266                         return err;
267                 }
268
269                 if (!strcasecmp(rs, "clk_125"))
270                         dwmac->is_tx_retime_src_clk_125 = true;
271         }
272
273         dwmac->clk = devm_clk_get(dev, "sti-ethclk");
274
275         if (IS_ERR(dwmac->clk))
276                 dwmac->clk = NULL;
277
278         return 0;
279 }
280
281 static int sti_dwmac_init(struct platform_device *pdev, void *priv)
282 {
283         struct sti_dwmac *dwmac = priv;
284         struct regmap *regmap = dwmac->regmap;
285         int iface = dwmac->interface;
286         u32 reg = dwmac->reg;
287         u32 val, spd;
288
289         if (dwmac->clk)
290                 clk_prepare_enable(dwmac->clk);
291
292         regmap_update_bits(regmap, reg, MII_PHY_SEL_MASK, phy_intf_sels[iface]);
293
294         val = (iface == PHY_INTERFACE_MODE_REVMII) ? 0 : ENMII;
295         regmap_update_bits(regmap, reg, ENMII_MASK, val);
296
297         if (IS_PHY_IF_MODE_GBIT(iface))
298                 spd = SPEED_1000;
299         else
300                 spd = SPEED_100;
301
302         setup_retime_src(dwmac, spd);
303
304         return 0;
305 }
306
307 static void *sti_dwmac_setup(struct platform_device *pdev)
308 {
309         struct sti_dwmac *dwmac;
310         int ret;
311
312         dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
313         if (!dwmac)
314                 return ERR_PTR(-ENOMEM);
315
316         ret = sti_dwmac_parse_data(dwmac, pdev);
317         if (ret) {
318                 dev_err(&pdev->dev, "Unable to parse OF data\n");
319                 return ERR_PTR(ret);
320         }
321
322         return dwmac;
323 }
324
325 const struct stmmac_of_data sti_gmac_data = {
326         .fix_mac_speed = sti_fix_mac_speed,
327         .setup = sti_dwmac_setup,
328         .init = sti_dwmac_init,
329         .exit = sti_dwmac_exit,
330 };