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 /* List of multicast addresses */
36 struct list_head mc_addr_list;
37 struct platform_device *eth_dev;
38 u16 speed;
39 };
40
41 struct mac_address {
42 u8 addr[ETH_ALEN];
43 struct list_head list;
44 };
45
mac_exception(struct mac_device * mac_dev,enum fman_mac_exceptions ex)46 static void mac_exception(struct mac_device *mac_dev,
47 enum fman_mac_exceptions ex)
48 {
49 if (ex == FM_MAC_EX_10G_RX_FIFO_OVFL) {
50 /* don't flag RX FIFO after the first */
51 mac_dev->set_exception(mac_dev->fman_mac,
52 FM_MAC_EX_10G_RX_FIFO_OVFL, false);
53 dev_err(mac_dev->dev, "10G MAC got RX FIFO Error = %x\n", ex);
54 }
55
56 dev_dbg(mac_dev->dev, "%s:%s() -> %d\n", KBUILD_BASENAME ".c",
57 __func__, ex);
58 }
59
fman_set_multi(struct net_device * net_dev,struct mac_device * mac_dev)60 int fman_set_multi(struct net_device *net_dev, struct mac_device *mac_dev)
61 {
62 struct mac_priv_s *priv;
63 struct mac_address *old_addr, *tmp;
64 struct netdev_hw_addr *ha;
65 int err;
66 enet_addr_t *addr;
67
68 priv = mac_dev->priv;
69
70 /* Clear previous address list */
71 list_for_each_entry_safe(old_addr, tmp, &priv->mc_addr_list, list) {
72 addr = (enet_addr_t *)old_addr->addr;
73 err = mac_dev->remove_hash_mac_addr(mac_dev->fman_mac, addr);
74 if (err < 0)
75 return err;
76
77 list_del(&old_addr->list);
78 kfree(old_addr);
79 }
80
81 /* Add all the addresses from the new list */
82 netdev_for_each_mc_addr(ha, net_dev) {
83 addr = (enet_addr_t *)ha->addr;
84 err = mac_dev->add_hash_mac_addr(mac_dev->fman_mac, addr);
85 if (err < 0)
86 return err;
87
88 tmp = kmalloc(sizeof(*tmp), GFP_ATOMIC);
89 if (!tmp)
90 return -ENOMEM;
91
92 ether_addr_copy(tmp->addr, ha->addr);
93 list_add(&tmp->list, &priv->mc_addr_list);
94 }
95 return 0;
96 }
97
98 static DEFINE_MUTEX(eth_lock);
99
dpaa_eth_add_device(int fman_id,struct mac_device * mac_dev)100 static struct platform_device *dpaa_eth_add_device(int fman_id,
101 struct mac_device *mac_dev)
102 {
103 struct platform_device *pdev;
104 struct dpaa_eth_data data;
105 struct mac_priv_s *priv;
106 static int dpaa_eth_dev_cnt;
107 int ret;
108
109 priv = mac_dev->priv;
110
111 data.mac_dev = mac_dev;
112 data.mac_hw_id = priv->cell_index;
113 data.fman_hw_id = fman_id;
114
115 mutex_lock(ð_lock);
116 pdev = platform_device_alloc("dpaa-ethernet", dpaa_eth_dev_cnt);
117 if (!pdev) {
118 ret = -ENOMEM;
119 goto no_mem;
120 }
121
122 pdev->dev.parent = mac_dev->dev;
123
124 ret = platform_device_add_data(pdev, &data, sizeof(data));
125 if (ret)
126 goto err;
127
128 ret = platform_device_add(pdev);
129 if (ret)
130 goto err;
131
132 dpaa_eth_dev_cnt++;
133 mutex_unlock(ð_lock);
134
135 return pdev;
136
137 err:
138 platform_device_put(pdev);
139 no_mem:
140 mutex_unlock(ð_lock);
141
142 return ERR_PTR(ret);
143 }
144
145 static const struct of_device_id mac_match[] = {
146 { .compatible = "fsl,fman-dtsec", .data = dtsec_initialization },
147 { .compatible = "fsl,fman-xgec", .data = tgec_initialization },
148 { .compatible = "fsl,fman-memac", .data = memac_initialization },
149 {}
150 };
151 MODULE_DEVICE_TABLE(of, mac_match);
152
mac_probe(struct platform_device * _of_dev)153 static int mac_probe(struct platform_device *_of_dev)
154 {
155 int err, i, nph;
156 int (*init)(struct mac_device *mac_dev, struct device_node *mac_node,
157 struct fman_mac_params *params);
158 struct device *dev;
159 struct device_node *mac_node, *dev_node;
160 struct mac_device *mac_dev;
161 struct platform_device *of_dev;
162 struct mac_priv_s *priv;
163 struct fman_mac_params params;
164 u32 val;
165 u8 fman_id;
166 phy_interface_t phy_if;
167
168 dev = &_of_dev->dev;
169 mac_node = dev->of_node;
170 init = of_device_get_match_data(dev);
171
172 mac_dev = devm_kzalloc(dev, sizeof(*mac_dev), GFP_KERNEL);
173 if (!mac_dev)
174 return -ENOMEM;
175 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
176 if (!priv)
177 return -ENOMEM;
178 platform_set_drvdata(_of_dev, mac_dev);
179
180 /* Save private information */
181 mac_dev->priv = priv;
182 mac_dev->dev = dev;
183
184 INIT_LIST_HEAD(&priv->mc_addr_list);
185
186 /* Get the FM node */
187 dev_node = of_get_parent(mac_node);
188 if (!dev_node) {
189 dev_err(dev, "of_get_parent(%pOF) failed\n",
190 mac_node);
191 return -EINVAL;
192 }
193
194 of_dev = of_find_device_by_node(dev_node);
195 if (!of_dev) {
196 dev_err(dev, "of_find_device_by_node(%pOF) failed\n", dev_node);
197 err = -EINVAL;
198 goto _return_of_node_put;
199 }
200 mac_dev->fman_dev = &of_dev->dev;
201
202 /* Get the FMan cell-index */
203 err = of_property_read_u32(dev_node, "cell-index", &val);
204 if (err) {
205 dev_err(dev, "failed to read cell-index for %pOF\n", dev_node);
206 err = -EINVAL;
207 goto _return_dev_put;
208 }
209 /* cell-index 0 => FMan id 1 */
210 fman_id = (u8)(val + 1);
211
212 priv->fman = fman_bind(mac_dev->fman_dev);
213 if (!priv->fman) {
214 dev_err(dev, "fman_bind(%pOF) failed\n", dev_node);
215 err = -ENODEV;
216 goto _return_dev_put;
217 }
218
219 /* Two references have been taken in of_find_device_by_node()
220 * and fman_bind(). Release one of them here. The second one
221 * will be released in mac_remove().
222 */
223 put_device(mac_dev->fman_dev);
224 of_node_put(dev_node);
225 dev_node = NULL;
226
227 /* Get the address of the memory mapped registers */
228 mac_dev->res = platform_get_mem_or_io(_of_dev, 0);
229 if (!mac_dev->res) {
230 dev_err(dev, "could not get registers\n");
231 err = -EINVAL;
232 goto _return_dev_put;
233 }
234
235 err = devm_request_resource(dev, fman_get_mem_region(priv->fman),
236 mac_dev->res);
237 if (err) {
238 dev_err_probe(dev, err, "could not request resource\n");
239 goto _return_dev_put;
240 }
241
242 mac_dev->vaddr = devm_ioremap(dev, mac_dev->res->start,
243 resource_size(mac_dev->res));
244 if (!mac_dev->vaddr) {
245 dev_err(dev, "devm_ioremap() failed\n");
246 err = -EIO;
247 goto _return_dev_put;
248 }
249
250 if (!of_device_is_available(mac_node)) {
251 err = -ENODEV;
252 goto _return_dev_put;
253 }
254
255 /* Get the cell-index */
256 err = of_property_read_u32(mac_node, "cell-index", &val);
257 if (err) {
258 dev_err(dev, "failed to read cell-index for %pOF\n", mac_node);
259 err = -EINVAL;
260 goto _return_dev_put;
261 }
262 priv->cell_index = (u8)val;
263
264 /* Get the MAC address */
265 err = of_get_mac_address(mac_node, mac_dev->addr);
266 if (err)
267 dev_warn(dev, "of_get_mac_address(%pOF) failed\n", mac_node);
268
269 /* Get the port handles */
270 nph = of_count_phandle_with_args(mac_node, "fsl,fman-ports", NULL);
271 if (unlikely(nph < 0)) {
272 dev_err(dev, "of_count_phandle_with_args(%pOF, fsl,fman-ports) failed\n",
273 mac_node);
274 err = nph;
275 goto _return_dev_put;
276 }
277
278 if (nph != ARRAY_SIZE(mac_dev->port)) {
279 dev_err(dev, "Not supported number of fman-ports handles of mac node %pOF from device tree\n",
280 mac_node);
281 err = -EINVAL;
282 goto _return_dev_put;
283 }
284
285 /* PORT_NUM determines the size of the port array */
286 for (i = 0; i < PORT_NUM; i++) {
287 /* Find the port node */
288 dev_node = of_parse_phandle(mac_node, "fsl,fman-ports", i);
289 if (!dev_node) {
290 dev_err(dev, "of_parse_phandle(%pOF, fsl,fman-ports) failed\n",
291 mac_node);
292 err = -EINVAL;
293 goto _return_dev_arr_put;
294 }
295
296 of_dev = of_find_device_by_node(dev_node);
297 if (!of_dev) {
298 dev_err(dev, "of_find_device_by_node(%pOF) failed\n",
299 dev_node);
300 err = -EINVAL;
301 goto _return_dev_arr_put;
302 }
303 mac_dev->fman_port_devs[i] = &of_dev->dev;
304
305 mac_dev->port[i] = fman_port_bind(mac_dev->fman_port_devs[i]);
306 if (!mac_dev->port[i]) {
307 dev_err(dev, "dev_get_drvdata(%pOF) failed\n",
308 dev_node);
309 err = -EINVAL;
310 goto _return_dev_arr_put;
311 }
312 /* Two references have been taken in of_find_device_by_node()
313 * and fman_port_bind(). Release one of them here. The second
314 * one will be released in mac_remove().
315 */
316 put_device(mac_dev->fman_port_devs[i]);
317 of_node_put(dev_node);
318 dev_node = NULL;
319 }
320
321 /* Get the PHY connection type */
322 err = of_get_phy_mode(mac_node, &phy_if);
323 if (err) {
324 dev_warn(dev,
325 "of_get_phy_mode() for %pOF failed. Defaulting to SGMII\n",
326 mac_node);
327 phy_if = PHY_INTERFACE_MODE_SGMII;
328 }
329 mac_dev->phy_if = phy_if;
330
331 params.mac_id = priv->cell_index;
332 params.fm = (void *)priv->fman;
333 params.exception_cb = mac_exception;
334 params.event_cb = mac_exception;
335
336 err = init(mac_dev, mac_node, ¶ms);
337 if (err < 0)
338 goto _return_dev_arr_put;
339
340 if (!is_zero_ether_addr(mac_dev->addr))
341 dev_info(dev, "FMan MAC address: %pM\n", mac_dev->addr);
342
343 priv->eth_dev = dpaa_eth_add_device(fman_id, mac_dev);
344 if (IS_ERR(priv->eth_dev)) {
345 err = PTR_ERR(priv->eth_dev);
346 dev_err(dev, "failed to add Ethernet platform device for MAC %d\n",
347 priv->cell_index);
348 priv->eth_dev = NULL;
349 }
350
351 return err;
352
353 _return_dev_arr_put:
354 /* mac_dev is kzalloc'ed */
355 for (i = 0; i < PORT_NUM; i++)
356 put_device(mac_dev->fman_port_devs[i]);
357 _return_dev_put:
358 put_device(mac_dev->fman_dev);
359 _return_of_node_put:
360 of_node_put(dev_node);
361 return err;
362 }
363
mac_remove(struct platform_device * pdev)364 static void mac_remove(struct platform_device *pdev)
365 {
366 struct mac_device *mac_dev = platform_get_drvdata(pdev);
367 int i;
368
369 for (i = 0; i < PORT_NUM; i++)
370 put_device(mac_dev->fman_port_devs[i]);
371 put_device(mac_dev->fman_dev);
372
373 platform_device_unregister(mac_dev->priv->eth_dev);
374 }
375
376 static struct platform_driver mac_driver = {
377 .driver = {
378 .name = KBUILD_MODNAME,
379 .of_match_table = mac_match,
380 },
381 .probe = mac_probe,
382 .remove_new = mac_remove,
383 };
384
385 builtin_platform_driver(mac_driver);
386