mediatek: add mt7531 DSA support
[oweals/openwrt.git] / target / linux / mediatek / patches-5.4 / 0600-2-6-net-dsa-mt7530-Extend-device-data-ready-for-adding-a-new-hardware.patch
1 From patchwork Tue Dec 10 08:14:38 2019
2 Content-Type: text/plain; charset="utf-8"
3 MIME-Version: 1.0
4 Content-Transfer-Encoding: 7bit
5 X-Patchwork-Submitter: Landen Chao <landen.chao@mediatek.com>
6 X-Patchwork-Id: 1206963
7 X-Patchwork-Delegate: davem@davemloft.net
8 Return-Path: <netdev-owner@vger.kernel.org>
9 X-Original-To: patchwork-incoming-netdev@ozlabs.org
10 Delivered-To: patchwork-incoming-netdev@ozlabs.org
11 Authentication-Results: ozlabs.org; spf=none (no SPF record)
12  smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67;
13  helo=vger.kernel.org;
14  envelope-from=netdev-owner@vger.kernel.org;
15  receiver=<UNKNOWN>)
16 Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none)
17  header.from=mediatek.com
18 Authentication-Results: ozlabs.org; dkim=pass (1024-bit key;
19  unprotected) header.d=mediatek.com header.i=@mediatek.com
20  header.b="UJ5NATux"; dkim-atps=neutral
21 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67])
22  by ozlabs.org (Postfix) with ESMTP id 47XCY92tBkz9sR7
23  for <patchwork-incoming-netdev@ozlabs.org>;
24  Tue, 10 Dec 2019 19:15:25 +1100 (AEDT)
25 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
26  id S1727003AbfLJIO4 (ORCPT
27  <rfc822;patchwork-incoming-netdev@ozlabs.org>);
28  Tue, 10 Dec 2019 03:14:56 -0500
29 Received: from mailgw02.mediatek.com ([210.61.82.184]:45567 "EHLO
30  mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by
31  vger.kernel.org with ESMTP id S1726071AbfLJIOy (ORCPT
32  <rfc822;netdev@vger.kernel.org>); Tue, 10 Dec 2019 03:14:54 -0500
33 X-UUID: a18674d7b33c423e9e67b7440f4771cf-20191210
34 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;
35  d=mediatek.com; s=dk; 
36  h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From;
37  bh=c2C/fEHYw/8uqadmiP2m2xa2hsUpAd52urXVJTPlYck=; 
38  b=UJ5NATuxMtqHln5i6BTpWiLnxGKgWvp4DpRsKVO2xdnz2cJaT4XL8F/T5fK3CTF4nAai0EKPAcqp+rr8eCLq7uURJv5e5h+ZIzKLSAB4zgnchXesQLo0uFS8vs5w2yp49j6bez1z3v/uN+1+Lpq0uYid9awCqzvbnovrooEysu4=;
39 X-UUID: a18674d7b33c423e9e67b7440f4771cf-20191210
40 Received: from mtkcas09.mediatek.inc [(172.21.101.178)] by
41  mailgw02.mediatek.com (envelope-from <landen.chao@mediatek.com>)
42  (Cellopoint E-mail Firewall v4.1.10 Build 0809 with TLS)
43  with ESMTP id 1965641267; Tue, 10 Dec 2019 16:14:46 +0800
44 Received: from mtkcas08.mediatek.inc (172.21.101.126) by
45  mtkmbs07n2.mediatek.inc (172.21.101.141) with Microsoft SMTP Server
46  (TLS) id 15.0.1395.4; Tue, 10 Dec 2019 16:14:31 +0800
47 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkcas08.mediatek.inc
48  (172.21.101.73) with Microsoft SMTP Server id 15.0.1395.4 via
49  Frontend Transport; Tue, 10 Dec 2019 16:14:26 +0800
50 From: Landen Chao <landen.chao@mediatek.com>
51 To: <andrew@lunn.ch>, <f.fainelli@gmail.com>,
52  <vivien.didelot@savoirfairelinux.com>, <matthias.bgg@gmail.com>,
53  <robh+dt@kernel.org>, <mark.rutland@arm.com>
54 CC: <devicetree@vger.kernel.org>, <netdev@vger.kernel.org>,
55  <linux-kernel@vger.kernel.org>,
56  <linux-mediatek@lists.infradead.org>, <davem@davemloft.net>,
57  <sean.wang@mediatek.com>, <opensource@vdorst.com>,
58  <frank-w@public-files.de>, Landen Chao <landen.chao@mediatek.com>
59 Subject: [PATCH net-next 2/6] net: dsa: mt7530: Extend device data ready for
60  adding a new hardware
61 Date: Tue, 10 Dec 2019 16:14:38 +0800
62 Message-ID: <2d546d6bb15ff8b4b75af2220e20db4e634f4145.1575914275.git.landen.chao@mediatek.com>
63 X-Mailer: git-send-email 2.18.0
64 In-Reply-To: <cover.1575914275.git.landen.chao@mediatek.com>
65 References: <cover.1575914275.git.landen.chao@mediatek.com>
66 MIME-Version: 1.0
67 X-MTK: N
68 Sender: netdev-owner@vger.kernel.org
69 Precedence: bulk
70 List-ID: <netdev.vger.kernel.org>
71 X-Mailing-List: netdev@vger.kernel.org
72
73 Add a structure holding required operations for each device such as device
74 initialization, PHY port read or write, a checker whether PHY interface is
75 supported on a certain port, MAC port setup for either bus pad or a
76 specific PHY interface.
77
78 The patch is done for ready adding a new hardware MT7531.
79
80 Signed-off-by: Landen Chao <landen.chao@mediatek.com>
81 Signed-off-by: Sean Wang <sean.wang@mediatek.com>
82 ---
83  drivers/net/dsa/mt7530.c | 231 +++++++++++++++++++++++++++++----------
84  drivers/net/dsa/mt7530.h |  29 ++++-
85  2 files changed, 203 insertions(+), 57 deletions(-)
86
87 Index: linux-5.4.43/drivers/net/dsa/mt7530.c
88 ===================================================================
89 --- linux-5.4.43.orig/drivers/net/dsa/mt7530.c
90 +++ linux-5.4.43/drivers/net/dsa/mt7530.c
91 @@ -373,7 +373,7 @@ mt7530_fdb_write(struct mt7530_priv *pri
92  }
93  
94  static int
95 -mt7530_pad_clk_setup(struct dsa_switch *ds, int mode)
96 +mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t mode)
97  {
98         struct mt7530_priv *priv = ds->priv;
99         u32 ncpo1, ssc_delta, trgint, i, xtal;
100 @@ -1355,13 +1355,111 @@ mt7530_setup(struct dsa_switch *ds)
101         return 0;
102  }
103  
104 -static void mt7530_phylink_mac_config(struct dsa_switch *ds, int port,
105 +static bool mt7530_phy_supported(struct dsa_switch *ds, int port,
106 +                                const struct phylink_link_state *state)
107 +{
108 +       struct mt7530_priv *priv = ds->priv;
109 +
110 +       switch (port) {
111 +       case 0: /* Internal phy */
112 +       case 1:
113 +       case 2:
114 +       case 3:
115 +       case 4:
116 +               if (state->interface != PHY_INTERFACE_MODE_GMII)
117 +                       goto unsupported;
118 +               break;
119 +       case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */
120 +               if (!phy_interface_mode_is_rgmii(state->interface) &&
121 +                   state->interface != PHY_INTERFACE_MODE_MII &&
122 +                   state->interface != PHY_INTERFACE_MODE_GMII)
123 +                       goto unsupported;
124 +               break;
125 +       case 6: /* 1st cpu port */
126 +               if (state->interface != PHY_INTERFACE_MODE_RGMII &&
127 +                   state->interface != PHY_INTERFACE_MODE_TRGMII)
128 +                       goto unsupported;
129 +               break;
130 +       default:
131 +               dev_err(priv->dev, "%s: unsupported port: %i\n", __func__,
132 +                       port);
133 +               goto unsupported;
134 +       }
135 +
136 +       return true;
137 +
138 +unsupported:
139 +       return false;
140 +}
141 +
142 +static bool mt753x_phy_supported(struct dsa_switch *ds, int port,
143 +                                const struct phylink_link_state *state)
144 +{
145 +       struct mt7530_priv *priv = ds->priv;
146 +
147 +       return priv->info->phy_supported(ds, port, state);
148 +}
149 +
150 +static int
151 +mt7530_pad_setup(struct dsa_switch *ds, const struct phylink_link_state *state)
152 +{
153 +       struct mt7530_priv *priv = ds->priv;
154 +
155 +       /* Setup TX circuit incluing relevant PAD and driving */
156 +       mt7530_pad_clk_setup(ds, state->interface);
157 +
158 +       if (priv->id == ID_MT7530) {
159 +               /* Setup RX circuit, relevant PAD and driving on the
160 +                * host which must be placed after the setup on the
161 +                * device side is all finished.
162 +                */
163 +               mt7623_pad_clk_setup(ds);
164 +       }
165 +
166 +       return 0;
167 +}
168 +
169 +static int
170 +mt753x_pad_setup(struct dsa_switch *ds, const struct phylink_link_state *state)
171 +{
172 +       struct mt7530_priv *priv = ds->priv;
173 +
174 +       return priv->info->pad_setup(ds, state);
175 +}
176 +
177 +static int
178 +mt7530_mac_setup(struct dsa_switch *ds, int port, unsigned int mode,
179 +                const struct phylink_link_state *state)
180 +{
181 +       struct mt7530_priv *priv = ds->priv;
182 +
183 +       /* Only need to setup port5. */
184 +       if (port != 5)
185 +               return 0;
186 +
187 +       mt7530_setup_port5(priv->ds, state->interface);
188 +
189 +       return 0;
190 +}
191 +
192 +static int mt753x_mac_setup(struct dsa_switch *ds, int port, unsigned int mode,
193 +                           const struct phylink_link_state *state)
194 +{
195 +       struct mt7530_priv *priv = ds->priv;
196 +
197 +       return priv->info->mac_setup(ds, port, mode, state);
198 +}
199 +
200 +static void mt753x_phylink_mac_config(struct dsa_switch *ds, int port,
201                                       unsigned int mode,
202                                       const struct phylink_link_state *state)
203  {
204         struct mt7530_priv *priv = ds->priv;
205         u32 mcr_cur, mcr_new;
206  
207 +       if (!mt753x_phy_supported(ds, port, state))
208 +               return;
209 +
210         switch (port) {
211         case 0: /* Internal phy */
212         case 1:
213 @@ -1374,24 +1472,15 @@ static void mt7530_phylink_mac_config(st
214         case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */
215                 if (priv->p5_interface == state->interface)
216                         break;
217 -               if (!phy_interface_mode_is_rgmii(state->interface) &&
218 -                   state->interface != PHY_INTERFACE_MODE_MII &&
219 -                   state->interface != PHY_INTERFACE_MODE_GMII)
220 -                       return;
221 -
222 -               mt7530_setup_port5(ds, state->interface);
223 +               if (mt753x_mac_setup(ds, port, mode, state) < 0)
224 +                       goto unsupported;
225                 break;
226         case 6: /* 1st cpu port */
227                 if (priv->p6_interface == state->interface)
228                         break;
229 -
230 -               if (state->interface != PHY_INTERFACE_MODE_RGMII &&
231 -                   state->interface != PHY_INTERFACE_MODE_TRGMII)
232 -                       return;
233 -
234 -               /* Setup TX circuit incluing relevant PAD and driving */
235 -               mt7530_pad_clk_setup(ds, state->interface);
236 -
237 +               mt753x_pad_setup(ds, state);
238 +               if (mt753x_mac_setup(ds, port, mode, state) < 0)
239 +                       goto unsupported;
240                 priv->p6_interface = state->interface;
241                 break;
242         default:
243 @@ -1459,38 +1548,14 @@ static void mt7530_phylink_mac_link_up(s
244         mt7530_port_set_status(priv, port, 1);
245  }
246  
247 -static void mt7530_phylink_validate(struct dsa_switch *ds, int port,
248 +static void mt753x_phylink_validate(struct dsa_switch *ds, int port,
249                                     unsigned long *supported,
250                                     struct phylink_link_state *state)
251  {
252         __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
253  
254 -       switch (port) {
255 -       case 0: /* Internal phy */
256 -       case 1:
257 -       case 2:
258 -       case 3:
259 -       case 4:
260 -               if (state->interface != PHY_INTERFACE_MODE_NA &&
261 -                   state->interface != PHY_INTERFACE_MODE_GMII)
262 -                       goto unsupported;
263 -               break;
264 -       case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */
265 -               if (state->interface != PHY_INTERFACE_MODE_NA &&
266 -                   !phy_interface_mode_is_rgmii(state->interface) &&
267 -                   state->interface != PHY_INTERFACE_MODE_MII &&
268 -                   state->interface != PHY_INTERFACE_MODE_GMII)
269 -                       goto unsupported;
270 -               break;
271 -       case 6: /* 1st cpu port */
272 -               if (state->interface != PHY_INTERFACE_MODE_NA &&
273 -                   state->interface != PHY_INTERFACE_MODE_RGMII &&
274 -                   state->interface != PHY_INTERFACE_MODE_TRGMII)
275 -                       goto unsupported;
276 -               break;
277 -       default:
278 -               dev_err(ds->dev, "%s: unsupported port: %i\n", __func__, port);
279 -unsupported:
280 +       if (state->interface != PHY_INTERFACE_MODE_NA &&
281 +           !mt753x_phy_supported(ds, port, state)) {
282                 linkmode_zero(supported);
283                 return;
284         }
285 @@ -1609,12 +1674,36 @@ static int mt7530_set_mac_eee(struct dsa
286         return 0;
287  }
288  
289 +static int
290 +mt753x_setup(struct dsa_switch *ds)
291 +{
292 +       struct mt7530_priv *priv = ds->priv;
293 +
294 +       return priv->info->setup(ds);
295 +}
296 +
297 +static int
298 +mt753x_phy_read(struct dsa_switch *ds, int port, int regnum)
299 +{
300 +       struct mt7530_priv *priv = ds->priv;
301 +
302 +       return priv->info->phy_read(ds, port, regnum);
303 +}
304 +
305 +static int
306 +mt753x_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
307 +{
308 +       struct mt7530_priv *priv = ds->priv;
309 +
310 +       return priv->info->phy_write(ds, port, regnum, val);
311 +}
312 +
313  static const struct dsa_switch_ops mt7530_switch_ops = {
314         .get_tag_protocol       = mtk_get_tag_protocol,
315 -       .setup                  = mt7530_setup,
316 +       .setup                  = mt753x_setup,
317         .get_strings            = mt7530_get_strings,
318 -       .phy_read               = mt7530_phy_read,
319 -       .phy_write              = mt7530_phy_write,
320 +       .phy_read               = mt753x_phy_read,
321 +       .phy_write              = mt753x_phy_write,
322         .get_ethtool_stats      = mt7530_get_ethtool_stats,
323         .get_sset_count         = mt7530_get_sset_count,
324         .port_enable            = mt7530_port_enable,
325 @@ -1631,18 +1720,39 @@ static const struct dsa_switch_ops mt753
326         .port_vlan_del          = mt7530_port_vlan_del,
327         .port_mirror_add        = mt7530_port_mirror_add,
328         .port_mirror_del        = mt7530_port_mirror_del,
329 -       .phylink_validate       = mt7530_phylink_validate,
330 +       .phylink_validate       = mt753x_phylink_validate,
331         .phylink_mac_link_state = mt7530_phylink_mac_link_state,
332 -       .phylink_mac_config     = mt7530_phylink_mac_config,
333 +       .phylink_mac_config     = mt753x_phylink_mac_config,
334         .phylink_mac_link_down  = mt7530_phylink_mac_link_down,
335         .phylink_mac_link_up    = mt7530_phylink_mac_link_up,
336         .get_mac_eee            = mt7530_get_mac_eee,
337         .set_mac_eee            = mt7530_set_mac_eee,
338  };
339  
340 -static const struct of_device_id mt7530_of_match[] = {
341 -       { .compatible = "mediatek,mt7621", .data = (void *)ID_MT7621, },
342 -       { .compatible = "mediatek,mt7530", .data = (void *)ID_MT7530, },
343 +static const struct mt753x_info mt753x_table[] = {
344 +       [ID_MT7621] = {
345 +               .id = ID_MT7621,
346 +               .setup = mt7530_setup,
347 +               .phy_read = mt7530_phy_read,
348 +               .phy_write = mt7530_phy_write,
349 +               .phy_supported = mt7530_phy_supported,
350 +               .pad_setup = mt7530_pad_setup,
351 +               .mac_setup = mt7530_mac_setup,
352 +       },
353 +       [ID_MT7530] = {
354 +               .id = ID_MT7530,
355 +               .setup = mt7530_setup,
356 +               .phy_read = mt7530_phy_read,
357 +               .phy_write = mt7530_phy_write,
358 +               .phy_supported = mt7530_phy_supported,
359 +               .pad_setup = mt7530_pad_setup,
360 +               .mac_setup = mt7530_mac_setup,
361 +       },
362 +};
363 +
364 + static const struct of_device_id mt7530_of_match[] = {
365 +       { .compatible = "mediatek,mt7621", .data = &mt753x_table[ID_MT7621], },
366 +       { .compatible = "mediatek,mt7530", .data = &mt753x_table[ID_MT7530], },
367         { /* sentinel */ },
368  };
369  MODULE_DEVICE_TABLE(of, mt7530_of_match);
370 @@ -1680,8 +1790,19 @@ mt7530_probe(struct mdio_device *mdiodev
371         /* Get the hardware identifier from the devicetree node.
372          * We will need it for some of the clock and regulator setup.
373          */
374 -       priv->id = (unsigned int)(unsigned long)
375 -               of_device_get_match_data(&mdiodev->dev);
376 +       priv->info = of_device_get_match_data(&mdiodev->dev);
377 +       if (!priv->info)
378 +               return -EINVAL;
379 +
380 +       /* Sanity check if these required device operstaions are filled
381 +        * properly.
382 +        */
383 +       if (!priv->info->setup || !priv->info->phy_read ||
384 +           !priv->info->phy_write || !priv->info->phy_supported ||
385 +           !priv->info->pad_setup || !priv->info->mac_setup)
386 +               return -EINVAL;
387 +
388 +       priv->id = priv->info->id;
389  
390         if (priv->id == ID_MT7530) {
391                 priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core");
392 Index: linux-5.4.43/drivers/net/dsa/mt7530.h
393 ===================================================================
394 --- linux-5.4.43.orig/drivers/net/dsa/mt7530.h
395 +++ linux-5.4.43/drivers/net/dsa/mt7530.h
396 @@ -11,7 +11,7 @@
397  #define MT7530_NUM_FDB_RECORDS         2048
398  #define MT7530_ALL_MEMBERS             0xff
399  
400 -enum {
401 +enum mt753x_id {
402         ID_MT7530 = 0,
403         ID_MT7621 = 1,
404  };
405 @@ -447,6 +447,32 @@ static const char *p5_intf_modes(unsigne
406         }
407  }
408  
409 +/* struct mt753x_info -        This is the main data structure for holding the specific
410 + *                     part for each supported device
411 + * @setup:             Holding the handler to a device initialization
412 + * @phy_read:          Holding the way reading PHY port
413 + * @phy_write:         Holding the way writing PHY port
414 + * @phy_supported:     Check if the PHY type is being supported on a certain
415 + *                     port
416 + * @pad_setup:         Holding the way setting up the bus pad for a certain MAC
417 + *                     port
418 + * @mac_setup:         Holding the way setting up the PHY attribute for a
419 + *                     certain MAC port
420 + */
421 +struct mt753x_info {
422 +       enum mt753x_id id;
423 +
424 +       int (*setup)(struct dsa_switch *ds);
425 +       int (*phy_read)(struct dsa_switch *ds, int port, int regnum);
426 +       int (*phy_write)(struct dsa_switch *ds, int port, int regnum, u16 val);
427 +       bool (*phy_supported)(struct dsa_switch *ds, int port,
428 +                             const struct phylink_link_state *state);
429 +       int (*pad_setup)(struct dsa_switch *ds,
430 +                        const struct phylink_link_state *state);
431 +       int (*mac_setup)(struct dsa_switch *ds, int port, unsigned int mode,
432 +                        const struct phylink_link_state *state);
433 +};
434 +
435  /* struct mt7530_priv -        This is the main data structure for holding the state
436   *                     of the driver
437   * @dev:               The device pointer
438 @@ -472,6 +498,7 @@ struct mt7530_priv {
439         struct regulator        *core_pwr;
440         struct regulator        *io_pwr;
441         struct gpio_desc        *reset;
442 +       const struct mt753x_info *info;
443         unsigned int            id;
444         bool                    mcm;
445         phy_interface_t         p6_interface;