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