1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later
2 /*
3 * Copyright 2008 - 2015 Freescale Semiconductor Inc.
4 */
5
6 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7
8 #include <linux/init.h>
9 #include <linux/module.h>
10 #include <linux/of_address.h>
11 #include <linux/of_platform.h>
12 #include <linux/of_net.h>
13 #include <linux/of_mdio.h>
14 #include <linux/device.h>
15 #include <linux/phy.h>
16 #include <linux/netdevice.h>
17 #include <linux/phy_fixed.h>
18 #include <linux/phylink.h>
19 #include <linux/etherdevice.h>
20 #include <linux/libfdt_env.h>
21 #include <linux/platform_device.h>
22
23 #include "mac.h"
24 #include "fman_mac.h"
25 #include "fman_dtsec.h"
26 #include "fman_tgec.h"
27 #include "fman_memac.h"
28
29 MODULE_LICENSE("Dual BSD/GPL");
30 MODULE_DESCRIPTION("FSL FMan MAC API based driver");
31
32 struct mac_priv_s {
33 u8 cell_index;
34 struct fman *fman;
35 struct platform_device *eth_dev;
36 u16 speed;
37 };
38
39 struct mac_address {
40 u8 addr[ETH_ALEN];
41 struct list_head list;
42 };
43
mac_exception(struct mac_device * mac_dev,enum fman_mac_exceptions ex)44 static void mac_exception(struct mac_device *mac_dev,
45 enum fman_mac_exceptions ex)
46 {
47 if (ex == FM_MAC_EX_10G_RX_FIFO_OVFL) {
48 /* don't flag RX FIFO after the first */
49 mac_dev->set_exception(mac_dev->fman_mac,
50 FM_MAC_EX_10G_RX_FIFO_OVFL, false);
51 dev_err(mac_dev->dev, "10G MAC got RX FIFO Error = %x\n", ex);
52 }
53
54 dev_dbg(mac_dev->dev, "%s:%s() -> %d\n", KBUILD_BASENAME ".c",
55 __func__, ex);
56 }
57
58 static DEFINE_MUTEX(eth_lock);
59
dpaa_eth_add_device(int fman_id,struct mac_device * mac_dev)60 static struct platform_device *dpaa_eth_add_device(int fman_id,
61 struct mac_device *mac_dev)
62 {
63 struct platform_device *pdev;
64 struct dpaa_eth_data data;
65 struct mac_priv_s *priv;
66 static int dpaa_eth_dev_cnt;
67 int ret;
68
69 priv = mac_dev->priv;
70
71 data.mac_dev = mac_dev;
72 data.mac_hw_id = priv->cell_index;
73 data.fman_hw_id = fman_id;
74
75 mutex_lock(ð_lock);
76 pdev = platform_device_alloc("dpaa-ethernet", dpaa_eth_dev_cnt);
77 if (!pdev) {
78 ret = -ENOMEM;
79 goto no_mem;
80 }
81
82 pdev->dev.parent = mac_dev->dev;
83
84 ret = platform_device_add_data(pdev, &data, sizeof(data));
85 if (ret)
86 goto err;
87
88 ret = platform_device_add(pdev);
89 if (ret)
90 goto err;
91
92 dpaa_eth_dev_cnt++;
93 mutex_unlock(ð_lock);
94
95 return pdev;
96
97 err:
98 platform_device_put(pdev);
99 no_mem:
100 mutex_unlock(ð_lock);
101
102 return ERR_PTR(ret);
103 }
104
105 static const struct of_device_id mac_match[] = {
106 { .compatible = "fsl,fman-dtsec", .data = dtsec_initialization },
107 { .compatible = "fsl,fman-xgec", .data = tgec_initialization },
108 { .compatible = "fsl,fman-memac", .data = memac_initialization },
109 {}
110 };
111 MODULE_DEVICE_TABLE(of, mac_match);
112
mac_probe(struct platform_device * _of_dev)113 static int mac_probe(struct platform_device *_of_dev)
114 {
115 int err, i, nph;
116 int (*init)(struct mac_device *mac_dev, struct device_node *mac_node,
117 struct fman_mac_params *params);
118 struct device *dev;
119 struct device_node *mac_node, *dev_node;
120 struct mac_device *mac_dev;
121 struct platform_device *of_dev;
122 struct mac_priv_s *priv;
123 struct fman_mac_params params;
124 u32 val;
125 u8 fman_id;
126 phy_interface_t phy_if;
127
128 dev = &_of_dev->dev;
129 mac_node = dev->of_node;
130 init = of_device_get_match_data(dev);
131
132 mac_dev = devm_kzalloc(dev, sizeof(*mac_dev), GFP_KERNEL);
133 if (!mac_dev)
134 return -ENOMEM;
135 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
136 if (!priv)
137 return -ENOMEM;
138 platform_set_drvdata(_of_dev, mac_dev);
139
140 /* Save private information */
141 mac_dev->priv = priv;
142 mac_dev->dev = dev;
143
144 /* Get the FM node */
145 dev_node = of_get_parent(mac_node);
146 if (!dev_node) {
147 dev_err(dev, "of_get_parent(%pOF) failed\n",
148 mac_node);
149 return -EINVAL;
150 }
151
152 of_dev = of_find_device_by_node(dev_node);
153 if (!of_dev) {
154 dev_err(dev, "of_find_device_by_node(%pOF) failed\n", dev_node);
155 err = -EINVAL;
156 goto _return_of_node_put;
157 }
158 mac_dev->fman_dev = &of_dev->dev;
159
160 /* Get the FMan cell-index */
161 err = of_property_read_u32(dev_node, "cell-index", &val);
162 if (err) {
163 dev_err(dev, "failed to read cell-index for %pOF\n", dev_node);
164 err = -EINVAL;
165 goto _return_dev_put;
166 }
167 /* cell-index 0 => FMan id 1 */
168 fman_id = (u8)(val + 1);
169
170 priv->fman = fman_bind(mac_dev->fman_dev);
171 if (!priv->fman) {
172 dev_err(dev, "fman_bind(%pOF) failed\n", dev_node);
173 err = -ENODEV;
174 goto _return_dev_put;
175 }
176
177 /* Two references have been taken in of_find_device_by_node()
178 * and fman_bind(). Release one of them here. The second one
179 * will be released in mac_remove().
180 */
181 put_device(mac_dev->fman_dev);
182 of_node_put(dev_node);
183 dev_node = NULL;
184
185 /* Get the address of the memory mapped registers */
186 mac_dev->res = platform_get_mem_or_io(_of_dev, 0);
187 if (!mac_dev->res) {
188 dev_err(dev, "could not get registers\n");
189 err = -EINVAL;
190 goto _return_dev_put;
191 }
192
193 err = devm_request_resource(dev, fman_get_mem_region(priv->fman),
194 mac_dev->res);
195 if (err) {
196 dev_err_probe(dev, err, "could not request resource\n");
197 goto _return_dev_put;
198 }
199
200 mac_dev->vaddr = devm_ioremap(dev, mac_dev->res->start,
201 resource_size(mac_dev->res));
202 if (!mac_dev->vaddr) {
203 dev_err(dev, "devm_ioremap() failed\n");
204 err = -EIO;
205 goto _return_dev_put;
206 }
207
208 if (!of_device_is_available(mac_node)) {
209 err = -ENODEV;
210 goto _return_dev_put;
211 }
212
213 /* Get the cell-index */
214 err = of_property_read_u32(mac_node, "cell-index", &val);
215 if (err) {
216 dev_err(dev, "failed to read cell-index for %pOF\n", mac_node);
217 err = -EINVAL;
218 goto _return_dev_put;
219 }
220 if (val >= MAX_NUM_OF_MACS) {
221 dev_err(dev, "cell-index value is too big for %pOF\n", mac_node);
222 err = -EINVAL;
223 goto _return_dev_put;
224 }
225 priv->cell_index = (u8)val;
226
227 /* Get the MAC address */
228 err = of_get_mac_address(mac_node, mac_dev->addr);
229 if (err)
230 dev_warn(dev, "of_get_mac_address(%pOF) failed\n", mac_node);
231
232 /* Get the port handles */
233 nph = of_count_phandle_with_args(mac_node, "fsl,fman-ports", NULL);
234 if (unlikely(nph < 0)) {
235 dev_err(dev, "of_count_phandle_with_args(%pOF, fsl,fman-ports) failed\n",
236 mac_node);
237 err = nph;
238 goto _return_dev_put;
239 }
240
241 if (nph != ARRAY_SIZE(mac_dev->port)) {
242 dev_err(dev, "Not supported number of fman-ports handles of mac node %pOF from device tree\n",
243 mac_node);
244 err = -EINVAL;
245 goto _return_dev_put;
246 }
247
248 /* PORT_NUM determines the size of the port array */
249 for (i = 0; i < PORT_NUM; i++) {
250 /* Find the port node */
251 dev_node = of_parse_phandle(mac_node, "fsl,fman-ports", i);
252 if (!dev_node) {
253 dev_err(dev, "of_parse_phandle(%pOF, fsl,fman-ports) failed\n",
254 mac_node);
255 err = -EINVAL;
256 goto _return_dev_arr_put;
257 }
258
259 of_dev = of_find_device_by_node(dev_node);
260 if (!of_dev) {
261 dev_err(dev, "of_find_device_by_node(%pOF) failed\n",
262 dev_node);
263 err = -EINVAL;
264 goto _return_dev_arr_put;
265 }
266 mac_dev->fman_port_devs[i] = &of_dev->dev;
267
268 mac_dev->port[i] = fman_port_bind(mac_dev->fman_port_devs[i]);
269 if (!mac_dev->port[i]) {
270 dev_err(dev, "dev_get_drvdata(%pOF) failed\n",
271 dev_node);
272 err = -EINVAL;
273 goto _return_dev_arr_put;
274 }
275 /* Two references have been taken in of_find_device_by_node()
276 * and fman_port_bind(). Release one of them here. The second
277 * one will be released in mac_remove().
278 */
279 put_device(mac_dev->fman_port_devs[i]);
280 of_node_put(dev_node);
281 dev_node = NULL;
282 }
283
284 /* Get the PHY connection type */
285 err = of_get_phy_mode(mac_node, &phy_if);
286 if (err) {
287 dev_warn(dev,
288 "of_get_phy_mode() for %pOF failed. Defaulting to SGMII\n",
289 mac_node);
290 phy_if = PHY_INTERFACE_MODE_SGMII;
291 }
292 mac_dev->phy_if = phy_if;
293
294 params.mac_id = priv->cell_index;
295 params.fm = (void *)priv->fman;
296 params.exception_cb = mac_exception;
297 params.event_cb = mac_exception;
298
299 err = init(mac_dev, mac_node, ¶ms);
300 if (err < 0)
301 goto _return_dev_arr_put;
302
303 if (!is_zero_ether_addr(mac_dev->addr))
304 dev_info(dev, "FMan MAC address: %pM\n", mac_dev->addr);
305
306 priv->eth_dev = dpaa_eth_add_device(fman_id, mac_dev);
307 if (IS_ERR(priv->eth_dev)) {
308 err = PTR_ERR(priv->eth_dev);
309 dev_err(dev, "failed to add Ethernet platform device for MAC %d\n",
310 priv->cell_index);
311 priv->eth_dev = NULL;
312 }
313
314 return err;
315
316 _return_dev_arr_put:
317 /* mac_dev is kzalloc'ed */
318 for (i = 0; i < PORT_NUM; i++)
319 put_device(mac_dev->fman_port_devs[i]);
320 _return_dev_put:
321 put_device(mac_dev->fman_dev);
322 _return_of_node_put:
323 of_node_put(dev_node);
324 return err;
325 }
326
mac_remove(struct platform_device * pdev)327 static void mac_remove(struct platform_device *pdev)
328 {
329 struct mac_device *mac_dev = platform_get_drvdata(pdev);
330 int i;
331
332 for (i = 0; i < PORT_NUM; i++)
333 put_device(mac_dev->fman_port_devs[i]);
334 put_device(mac_dev->fman_dev);
335
336 platform_device_unregister(mac_dev->priv->eth_dev);
337 }
338
339 static struct platform_driver mac_driver = {
340 .driver = {
341 .name = KBUILD_MODNAME,
342 .of_match_table = mac_match,
343 },
344 .probe = mac_probe,
345 .remove = mac_remove,
346 };
347
348 builtin_platform_driver(mac_driver);
349