]> Git Repo - linux.git/blob - drivers/net/ethernet/mediatek/mtk_eth_path.c
Merge tag 'drm-msm-next-2023-08-20' of https://gitlab.freedesktop.org/drm/msm into...
[linux.git] / drivers / net / ethernet / mediatek / mtk_eth_path.c
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2018-2019 MediaTek Inc.
3
4 /* A library for configuring path from GMAC/GDM to target PHY
5  *
6  * Author: Sean Wang <[email protected]>
7  *
8  */
9
10 #include <linux/phy.h>
11 #include <linux/regmap.h>
12
13 #include "mtk_eth_soc.h"
14
15 struct mtk_eth_muxc {
16         const char      *name;
17         int             cap_bit;
18         int             (*set_path)(struct mtk_eth *eth, int path);
19 };
20
21 static const char *mtk_eth_path_name(int path)
22 {
23         switch (path) {
24         case MTK_ETH_PATH_GMAC1_RGMII:
25                 return "gmac1_rgmii";
26         case MTK_ETH_PATH_GMAC1_TRGMII:
27                 return "gmac1_trgmii";
28         case MTK_ETH_PATH_GMAC1_SGMII:
29                 return "gmac1_sgmii";
30         case MTK_ETH_PATH_GMAC2_RGMII:
31                 return "gmac2_rgmii";
32         case MTK_ETH_PATH_GMAC2_SGMII:
33                 return "gmac2_sgmii";
34         case MTK_ETH_PATH_GMAC2_GEPHY:
35                 return "gmac2_gephy";
36         case MTK_ETH_PATH_GDM1_ESW:
37                 return "gdm1_esw";
38         default:
39                 return "unknown path";
40         }
41 }
42
43 static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, int path)
44 {
45         bool updated = true;
46         u32 val, mask, set;
47
48         switch (path) {
49         case MTK_ETH_PATH_GMAC1_SGMII:
50                 mask = ~(u32)MTK_MUX_TO_ESW;
51                 set = 0;
52                 break;
53         case MTK_ETH_PATH_GDM1_ESW:
54                 mask = ~(u32)MTK_MUX_TO_ESW;
55                 set = MTK_MUX_TO_ESW;
56                 break;
57         default:
58                 updated = false;
59                 break;
60         }
61
62         if (updated) {
63                 val = mtk_r32(eth, MTK_MAC_MISC);
64                 val = (val & mask) | set;
65                 mtk_w32(eth, val, MTK_MAC_MISC);
66         }
67
68         dev_dbg(eth->dev, "path %s in %s updated = %d\n",
69                 mtk_eth_path_name(path), __func__, updated);
70
71         return 0;
72 }
73
74 static int set_mux_gmac2_gmac0_to_gephy(struct mtk_eth *eth, int path)
75 {
76         unsigned int val = 0;
77         bool updated = true;
78
79         switch (path) {
80         case MTK_ETH_PATH_GMAC2_GEPHY:
81                 val = ~(u32)GEPHY_MAC_SEL;
82                 break;
83         default:
84                 updated = false;
85                 break;
86         }
87
88         if (updated)
89                 regmap_update_bits(eth->infra, INFRA_MISC2, GEPHY_MAC_SEL, val);
90
91         dev_dbg(eth->dev, "path %s in %s updated = %d\n",
92                 mtk_eth_path_name(path), __func__, updated);
93
94         return 0;
95 }
96
97 static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, int path)
98 {
99         unsigned int val = 0, mask = 0, reg = 0;
100         bool updated = true;
101
102         switch (path) {
103         case MTK_ETH_PATH_GMAC2_SGMII:
104                 if (MTK_HAS_CAPS(eth->soc->caps, MTK_U3_COPHY_V2)) {
105                         reg = USB_PHY_SWITCH_REG;
106                         val = SGMII_QPHY_SEL;
107                         mask = QPHY_SEL_MASK;
108                 } else {
109                         reg = INFRA_MISC2;
110                         val = CO_QPHY_SEL;
111                         mask = val;
112                 }
113                 break;
114         default:
115                 updated = false;
116                 break;
117         }
118
119         if (updated)
120                 regmap_update_bits(eth->infra, reg, mask, val);
121
122         dev_dbg(eth->dev, "path %s in %s updated = %d\n",
123                 mtk_eth_path_name(path), __func__, updated);
124
125         return 0;
126 }
127
128 static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, int path)
129 {
130         unsigned int val = 0;
131         bool updated = true;
132
133         switch (path) {
134         case MTK_ETH_PATH_GMAC1_SGMII:
135                 val = SYSCFG0_SGMII_GMAC1;
136                 break;
137         case MTK_ETH_PATH_GMAC2_SGMII:
138                 val = SYSCFG0_SGMII_GMAC2;
139                 break;
140         case MTK_ETH_PATH_GMAC1_RGMII:
141         case MTK_ETH_PATH_GMAC2_RGMII:
142                 regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
143                 val &= SYSCFG0_SGMII_MASK;
144
145                 if ((path == MTK_GMAC1_RGMII && val == SYSCFG0_SGMII_GMAC1) ||
146                     (path == MTK_GMAC2_RGMII && val == SYSCFG0_SGMII_GMAC2))
147                         val = 0;
148                 else
149                         updated = false;
150                 break;
151         default:
152                 updated = false;
153                 break;
154         }
155
156         if (updated)
157                 regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
158                                    SYSCFG0_SGMII_MASK, val);
159
160         dev_dbg(eth->dev, "path %s in %s updated = %d\n",
161                 mtk_eth_path_name(path), __func__, updated);
162
163         return 0;
164 }
165
166 static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth *eth, int path)
167 {
168         unsigned int val = 0;
169         bool updated = true;
170
171         regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
172
173         switch (path) {
174         case MTK_ETH_PATH_GMAC1_SGMII:
175                 val |= SYSCFG0_SGMII_GMAC1_V2;
176                 break;
177         case MTK_ETH_PATH_GMAC2_GEPHY:
178                 val &= ~(u32)SYSCFG0_SGMII_GMAC2_V2;
179                 break;
180         case MTK_ETH_PATH_GMAC2_SGMII:
181                 val |= SYSCFG0_SGMII_GMAC2_V2;
182                 break;
183         default:
184                 updated = false;
185         }
186
187         if (updated)
188                 regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
189                                    SYSCFG0_SGMII_MASK, val);
190
191         dev_dbg(eth->dev, "path %s in %s updated = %d\n",
192                 mtk_eth_path_name(path), __func__, updated);
193
194         return 0;
195 }
196
197 static const struct mtk_eth_muxc mtk_eth_muxc[] = {
198         {
199                 .name = "mux_gdm1_to_gmac1_esw",
200                 .cap_bit = MTK_ETH_MUX_GDM1_TO_GMAC1_ESW,
201                 .set_path = set_mux_gdm1_to_gmac1_esw,
202         }, {
203                 .name = "mux_gmac2_gmac0_to_gephy",
204                 .cap_bit = MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY,
205                 .set_path = set_mux_gmac2_gmac0_to_gephy,
206         }, {
207                 .name = "mux_u3_gmac2_to_qphy",
208                 .cap_bit = MTK_ETH_MUX_U3_GMAC2_TO_QPHY,
209                 .set_path = set_mux_u3_gmac2_to_qphy,
210         }, {
211                 .name = "mux_gmac1_gmac2_to_sgmii_rgmii",
212                 .cap_bit = MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII,
213                 .set_path = set_mux_gmac1_gmac2_to_sgmii_rgmii,
214         }, {
215                 .name = "mux_gmac12_to_gephy_sgmii",
216                 .cap_bit = MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII,
217                 .set_path = set_mux_gmac12_to_gephy_sgmii,
218         },
219 };
220
221 static int mtk_eth_mux_setup(struct mtk_eth *eth, int path)
222 {
223         int i, err = 0;
224
225         if (!MTK_HAS_CAPS(eth->soc->caps, path)) {
226                 dev_err(eth->dev, "path %s isn't support on the SoC\n",
227                         mtk_eth_path_name(path));
228                 return -EINVAL;
229         }
230
231         if (!MTK_HAS_CAPS(eth->soc->caps, MTK_MUX))
232                 return 0;
233
234         /* Setup MUX in path fabric */
235         for (i = 0; i < ARRAY_SIZE(mtk_eth_muxc); i++) {
236                 if (MTK_HAS_CAPS(eth->soc->caps, mtk_eth_muxc[i].cap_bit)) {
237                         err = mtk_eth_muxc[i].set_path(eth, path);
238                         if (err)
239                                 goto out;
240                 } else {
241                         dev_dbg(eth->dev, "mux %s isn't present on the SoC\n",
242                                 mtk_eth_muxc[i].name);
243                 }
244         }
245
246 out:
247         return err;
248 }
249
250 int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id)
251 {
252         int path;
253
254         path = (mac_id == 0) ?  MTK_ETH_PATH_GMAC1_SGMII :
255                                 MTK_ETH_PATH_GMAC2_SGMII;
256
257         /* Setup proper MUXes along the path */
258         return mtk_eth_mux_setup(eth, path);
259 }
260
261 int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id)
262 {
263         int path = 0;
264
265         if (mac_id == 1)
266                 path = MTK_ETH_PATH_GMAC2_GEPHY;
267
268         if (!path)
269                 return -EINVAL;
270
271         /* Setup proper MUXes along the path */
272         return mtk_eth_mux_setup(eth, path);
273 }
274
275 int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id)
276 {
277         int path;
278
279         path = (mac_id == 0) ?  MTK_ETH_PATH_GMAC1_RGMII :
280                                 MTK_ETH_PATH_GMAC2_RGMII;
281
282         /* Setup proper MUXes along the path */
283         return mtk_eth_mux_setup(eth, path);
284 }
285
This page took 0.053485 seconds and 4 git commands to generate.