net/pfe: add MAC and host interface initialisation
[dpdk.git] / drivers / net / pfe / pfe_ethdev.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2019 NXP
3  */
4
5 #include <rte_kvargs.h>
6 #include <rte_ethdev_vdev.h>
7 #include <rte_bus_vdev.h>
8 #include <dpaa_of.h>
9
10 #include "pfe_logs.h"
11 #include "pfe_mod.h"
12
13 #define PFE_MAX_MACS 1 /*we can support upto 4 MACs per IF*/
14 #define PFE_VDEV_GEM_ID_ARG     "intf"
15
16 struct pfe_vdev_init_params {
17         int8_t  gem_id;
18 };
19 static struct pfe *g_pfe;
20
21 /* TODO: make pfe_svr a runtime option.
22  * Driver should be able to get the SVR
23  * information from HW.
24  */
25 unsigned int pfe_svr = SVR_LS1012A_REV1;
26 static void *cbus_emac_base[3];
27 static void *cbus_gpi_base[3];
28
29 int pfe_logtype_pmd;
30
31 /* pfe_gemac_init
32  */
33 static int
34 pfe_gemac_init(struct pfe_eth_priv_s *priv)
35 {
36         struct gemac_cfg cfg;
37
38         cfg.speed = SPEED_1000M;
39         cfg.duplex = DUPLEX_FULL;
40
41         gemac_set_config(priv->EMAC_baseaddr, &cfg);
42         gemac_allow_broadcast(priv->EMAC_baseaddr);
43         gemac_enable_1536_rx(priv->EMAC_baseaddr);
44         gemac_enable_stacked_vlan(priv->EMAC_baseaddr);
45         gemac_enable_pause_rx(priv->EMAC_baseaddr);
46         gemac_set_bus_width(priv->EMAC_baseaddr, 64);
47         gemac_enable_rx_checksum_offload(priv->EMAC_baseaddr);
48
49         return 0;
50 }
51
52 static void
53 pfe_soc_version_get(void)
54 {
55         FILE *svr_file = NULL;
56         unsigned int svr_ver = 0;
57
58         PMD_INIT_FUNC_TRACE();
59
60         svr_file = fopen(PFE_SOC_ID_FILE, "r");
61         if (!svr_file) {
62                 PFE_PMD_ERR("Unable to open SoC device");
63                 return; /* Not supported on this infra */
64         }
65
66         if (fscanf(svr_file, "svr:%x", &svr_ver) > 0)
67                 pfe_svr = svr_ver;
68         else
69                 PFE_PMD_ERR("Unable to read SoC device");
70
71         fclose(svr_file);
72 }
73
74 static int
75 pfe_eth_open_cdev(struct pfe_eth_priv_s *priv)
76 {
77         int pfe_cdev_fd;
78
79         if (priv == NULL)
80                 return -1;
81
82         pfe_cdev_fd = open(PFE_CDEV_PATH, O_RDONLY);
83         if (pfe_cdev_fd < 0) {
84                 PFE_PMD_WARN("Unable to open PFE device file (%s).\n",
85                              PFE_CDEV_PATH);
86                 PFE_PMD_WARN("Link status update will not be available.\n");
87                 priv->link_fd = PFE_CDEV_INVALID_FD;
88                 return -1;
89         }
90
91         priv->link_fd = pfe_cdev_fd;
92
93         return 0;
94 }
95
96 static void
97 pfe_eth_close_cdev(struct pfe_eth_priv_s *priv)
98 {
99         if (priv == NULL)
100                 return;
101
102         if (priv->link_fd != PFE_CDEV_INVALID_FD) {
103                 close(priv->link_fd);
104                 priv->link_fd = PFE_CDEV_INVALID_FD;
105         }
106 }
107
108 static void
109 pfe_eth_exit(struct rte_eth_dev *dev, struct pfe *pfe)
110 {
111         PMD_INIT_FUNC_TRACE();
112
113         /* Close the device file for link status */
114         pfe_eth_close_cdev(dev->data->dev_private);
115
116         rte_free(dev->data->mac_addrs);
117         rte_eth_dev_release_port(dev);
118         pfe->nb_devs--;
119 }
120
121 static int
122 pfe_eth_init(struct rte_vdev_device *vdev, struct pfe *pfe, int id)
123 {
124         struct rte_eth_dev *eth_dev = NULL;
125         struct pfe_eth_priv_s *priv = NULL;
126         struct ls1012a_eth_platform_data *einfo;
127         struct ls1012a_pfe_platform_data *pfe_info;
128         int err;
129
130         eth_dev = rte_eth_vdev_allocate(vdev, sizeof(*priv));
131         if (eth_dev == NULL)
132                 return -ENOMEM;
133
134         /* Extract pltform data */
135         pfe_info = (struct ls1012a_pfe_platform_data *)&pfe->platform_data;
136         if (!pfe_info) {
137                 PFE_PMD_ERR("pfe missing additional platform data");
138                 err = -ENODEV;
139                 goto err0;
140         }
141
142         einfo = (struct ls1012a_eth_platform_data *)pfe_info->ls1012a_eth_pdata;
143
144         /* einfo never be NULL, but no harm in having this check */
145         if (!einfo) {
146                 PFE_PMD_ERR("pfe missing additional gemacs platform data");
147                 err = -ENODEV;
148                 goto err0;
149         }
150
151         priv = eth_dev->data->dev_private;
152         priv->ndev = eth_dev;
153         priv->id = einfo[id].gem_id;
154         priv->pfe = pfe;
155
156         pfe->eth.eth_priv[id] = priv;
157
158         /* Set the info in the priv to the current info */
159         priv->einfo = &einfo[id];
160         priv->EMAC_baseaddr = cbus_emac_base[id];
161         priv->PHY_baseaddr = cbus_emac_base[id];
162         priv->GPI_baseaddr = cbus_gpi_base[id];
163
164 #define HIF_GEMAC_TMUQ_BASE     6
165         priv->low_tmu_q = HIF_GEMAC_TMUQ_BASE + (id * 2);
166         priv->high_tmu_q = priv->low_tmu_q + 1;
167
168         rte_spinlock_init(&priv->lock);
169
170         /* Copy the station address into the dev structure, */
171         eth_dev->data->mac_addrs = rte_zmalloc("mac_addr",
172                         ETHER_ADDR_LEN * PFE_MAX_MACS, 0);
173         if (eth_dev->data->mac_addrs == NULL) {
174                 PFE_PMD_ERR("Failed to allocate mem %d to store MAC addresses",
175                         ETHER_ADDR_LEN * PFE_MAX_MACS);
176                 err = -ENOMEM;
177                 goto err0;
178         }
179
180         eth_dev->data->mtu = 1500;
181         pfe_gemac_init(priv);
182
183         eth_dev->data->nb_rx_queues = 1;
184         eth_dev->data->nb_tx_queues = 1;
185
186         /* For link status, open the PFE CDEV; Error from this function
187          * is silently ignored; In case of error, the link status will not
188          * be available.
189          */
190         pfe_eth_open_cdev(priv);
191         rte_eth_dev_probing_finish(eth_dev);
192
193         return 0;
194 err0:
195         rte_eth_dev_release_port(eth_dev);
196         return err;
197 }
198
199 static int
200 pfe_get_gemac_if_proprties(struct pfe *pfe,
201                 __rte_unused const struct device_node *parent,
202                 unsigned int port, unsigned int if_cnt,
203                 struct ls1012a_pfe_platform_data *pdata)
204 {
205         const struct device_node *gem = NULL;
206         size_t size;
207         unsigned int ii = 0, phy_id = 0;
208         const u32 *addr;
209         const void *mac_addr;
210
211         for (ii = 0; ii < if_cnt; ii++) {
212                 gem = of_get_next_child(parent, gem);
213                 if (!gem)
214                         goto err;
215                 addr = of_get_property(gem, "reg", &size);
216                 if (addr && (rte_be_to_cpu_32((unsigned int)*addr) == port))
217                         break;
218         }
219
220         if (ii >= if_cnt) {
221                 PFE_PMD_ERR("Failed to find interface = %d", if_cnt);
222                 goto err;
223         }
224
225         pdata->ls1012a_eth_pdata[port].gem_id = port;
226
227         mac_addr = of_get_mac_address(gem);
228
229         if (mac_addr) {
230                 memcpy(pdata->ls1012a_eth_pdata[port].mac_addr, mac_addr,
231                        ETH_ALEN);
232         }
233
234         addr = of_get_property(gem, "fsl,mdio-mux-val", &size);
235         if (!addr) {
236                 PFE_PMD_ERR("Invalid mdio-mux-val....");
237         } else {
238                 phy_id = rte_be_to_cpu_32((unsigned int)*addr);
239                 pdata->ls1012a_eth_pdata[port].mdio_muxval = phy_id;
240         }
241         if (pdata->ls1012a_eth_pdata[port].phy_id < 32)
242                 pfe->mdio_muxval[pdata->ls1012a_eth_pdata[port].phy_id] =
243                          pdata->ls1012a_eth_pdata[port].mdio_muxval;
244
245         return 0;
246
247 err:
248         return -1;
249 }
250
251 /* Parse integer from integer argument */
252 static int
253 parse_integer_arg(const char *key __rte_unused,
254                 const char *value, void *extra_args)
255 {
256         int i;
257         char *end;
258         errno = 0;
259
260         i = strtol(value, &end, 10);
261         if (*end != 0 || errno != 0 || i < 0 || i > 1) {
262                 PFE_PMD_ERR("Supported Port IDS are 0 and 1");
263                 return -EINVAL;
264         }
265
266         *((uint32_t *)extra_args) = i;
267
268         return 0;
269 }
270
271 static int
272 pfe_parse_vdev_init_params(struct pfe_vdev_init_params *params,
273                            struct rte_vdev_device *dev)
274 {
275         struct rte_kvargs *kvlist = NULL;
276         int ret = 0;
277
278         static const char * const pfe_vdev_valid_params[] = {
279                 PFE_VDEV_GEM_ID_ARG,
280                 NULL
281         };
282
283         const char *input_args = rte_vdev_device_args(dev);
284
285         if (!input_args)
286                 return -1;
287
288         kvlist = rte_kvargs_parse(input_args, pfe_vdev_valid_params);
289         if (kvlist == NULL)
290                 return -1;
291
292         ret = rte_kvargs_process(kvlist,
293                                 PFE_VDEV_GEM_ID_ARG,
294                                 &parse_integer_arg,
295                                 &params->gem_id);
296         rte_kvargs_free(kvlist);
297         return ret;
298 }
299
300 static int
301 pmd_pfe_probe(struct rte_vdev_device *vdev)
302 {
303         const u32 *prop;
304         const struct device_node *np;
305         const char *name;
306         const uint32_t *addr;
307         uint64_t cbus_addr, ddr_size, cbus_size;
308         int rc = -1, fd = -1, gem_id;
309         unsigned int ii, interface_count = 0;
310         size_t size = 0;
311         struct pfe_vdev_init_params init_params = {
312                 .gem_id = -1
313         };
314
315         name = rte_vdev_device_name(vdev);
316         rc = pfe_parse_vdev_init_params(&init_params, vdev);
317         if (rc < 0)
318                 return -EINVAL;
319
320         RTE_LOG(INFO, PMD, "Initializing pmd_pfe for %s Given gem-id %d\n",
321                 name, init_params.gem_id);
322
323         if (g_pfe) {
324                 if (g_pfe->nb_devs >= g_pfe->max_intf) {
325                         PFE_PMD_ERR("PFE %d dev already created Max is %d",
326                                 g_pfe->nb_devs, g_pfe->max_intf);
327                         return -EINVAL;
328                 }
329                 goto eth_init;
330         }
331
332         g_pfe = rte_zmalloc(NULL, sizeof(*g_pfe), RTE_CACHE_LINE_SIZE);
333         if (g_pfe == NULL)
334                 return  -EINVAL;
335
336         /* Load the device-tree driver */
337         rc = of_init();
338         if (rc) {
339                 PFE_PMD_ERR("of_init failed with ret: %d", rc);
340                 goto err;
341         }
342
343         np = of_find_compatible_node(NULL, NULL, "fsl,pfe");
344         if (!np) {
345                 PFE_PMD_ERR("Invalid device node");
346                 rc = -EINVAL;
347                 goto err;
348         }
349
350         addr = of_get_address(np, 0, &cbus_size, NULL);
351         if (!addr) {
352                 PFE_PMD_ERR("of_get_address cannot return qman address\n");
353                 goto err;
354         }
355         cbus_addr = of_translate_address(np, addr);
356         if (!cbus_addr) {
357                 PFE_PMD_ERR("of_translate_address failed\n");
358                 goto err;
359         }
360
361         addr = of_get_address(np, 1, &ddr_size, NULL);
362         if (!addr) {
363                 PFE_PMD_ERR("of_get_address cannot return qman address\n");
364                 goto err;
365         }
366
367         g_pfe->ddr_phys_baseaddr = of_translate_address(np, addr);
368         if (!g_pfe->ddr_phys_baseaddr) {
369                 PFE_PMD_ERR("of_translate_address failed\n");
370                 goto err;
371         }
372
373         g_pfe->ddr_baseaddr = pfe_mem_ptov(g_pfe->ddr_phys_baseaddr);
374         g_pfe->ddr_size = ddr_size;
375         g_pfe->cbus_size = cbus_size;
376
377         fd = open("/dev/mem", O_RDWR);
378         g_pfe->cbus_baseaddr = mmap(NULL, cbus_size, PROT_READ | PROT_WRITE,
379                                         MAP_SHARED, fd, cbus_addr);
380         close(fd);
381         if (g_pfe->cbus_baseaddr == MAP_FAILED) {
382                 PFE_PMD_ERR("Can not map cbus base");
383                 rc = -EINVAL;
384                 goto err;
385         }
386
387         /* Read interface count */
388         prop = of_get_property(np, "fsl,pfe-num-interfaces", &size);
389         if (!prop) {
390                 PFE_PMD_ERR("Failed to read number of interfaces");
391                 rc = -ENXIO;
392                 goto err_prop;
393         }
394
395         interface_count = rte_be_to_cpu_32((unsigned int)*prop);
396         if (interface_count <= 0) {
397                 PFE_PMD_ERR("No ethernet interface count : %d",
398                                 interface_count);
399                 rc = -ENXIO;
400                 goto err_prop;
401         }
402         PFE_PMD_INFO("num interfaces = %d ", interface_count);
403
404         g_pfe->max_intf  = interface_count;
405         g_pfe->platform_data.ls1012a_mdio_pdata[0].phy_mask = 0xffffffff;
406
407         for (ii = 0; ii < interface_count; ii++) {
408                 pfe_get_gemac_if_proprties(g_pfe, np, ii, interface_count,
409                                            &g_pfe->platform_data);
410         }
411
412         pfe_lib_init(g_pfe->cbus_baseaddr, g_pfe->ddr_baseaddr,
413                      g_pfe->ddr_phys_baseaddr, g_pfe->ddr_size);
414
415         PFE_PMD_INFO("CLASS version: %x", readl(CLASS_VERSION));
416         PFE_PMD_INFO("TMU version: %x", readl(TMU_VERSION));
417
418         PFE_PMD_INFO("BMU1 version: %x", readl(BMU1_BASE_ADDR + BMU_VERSION));
419         PFE_PMD_INFO("BMU2 version: %x", readl(BMU2_BASE_ADDR + BMU_VERSION));
420
421         PFE_PMD_INFO("EGPI1 version: %x", readl(EGPI1_BASE_ADDR + GPI_VERSION));
422         PFE_PMD_INFO("EGPI2 version: %x", readl(EGPI2_BASE_ADDR + GPI_VERSION));
423         PFE_PMD_INFO("HGPI version: %x", readl(HGPI_BASE_ADDR + GPI_VERSION));
424
425         PFE_PMD_INFO("HIF version: %x", readl(HIF_VERSION));
426         PFE_PMD_INFO("HIF NOPCY version: %x", readl(HIF_NOCPY_VERSION));
427
428         cbus_emac_base[0] = EMAC1_BASE_ADDR;
429         cbus_emac_base[1] = EMAC2_BASE_ADDR;
430
431         cbus_gpi_base[0] = EGPI1_BASE_ADDR;
432         cbus_gpi_base[1] = EGPI2_BASE_ADDR;
433
434         rc = pfe_hif_lib_init(g_pfe);
435         if (rc < 0)
436                 goto err_hif_lib;
437
438         rc = pfe_hif_init(g_pfe);
439         if (rc < 0)
440                 goto err_hif;
441         pfe_soc_version_get();
442 eth_init:
443         if (init_params.gem_id < 0)
444                 gem_id = g_pfe->nb_devs;
445         else
446                 gem_id = init_params.gem_id;
447
448         RTE_LOG(INFO, PMD, "Init pmd_pfe for %s gem-id %d(given =%d)\n",
449                 name, gem_id, init_params.gem_id);
450
451         rc = pfe_eth_init(vdev, g_pfe, gem_id);
452         if (rc < 0)
453                 goto err_eth;
454         else
455                 g_pfe->nb_devs++;
456
457         return 0;
458
459 err_eth:
460         pfe_hif_exit(g_pfe);
461
462 err_hif:
463         pfe_hif_lib_exit(g_pfe);
464
465 err_hif_lib:
466 err_prop:
467         munmap(g_pfe->cbus_baseaddr, cbus_size);
468 err:
469         rte_free(g_pfe);
470         return rc;
471 }
472
473 static int
474 pmd_pfe_remove(struct rte_vdev_device *vdev)
475 {
476         const char *name;
477         struct rte_eth_dev *eth_dev = NULL;
478
479         name = rte_vdev_device_name(vdev);
480         if (name == NULL)
481                 return -EINVAL;
482
483         PFE_PMD_INFO("Closing eventdev sw device %s", name);
484
485         if (!g_pfe)
486                 return 0;
487
488         eth_dev = rte_eth_dev_allocated(name);
489         if (eth_dev == NULL)
490                 return -ENODEV;
491
492         pfe_eth_exit(eth_dev, g_pfe);
493         munmap(g_pfe->cbus_baseaddr, g_pfe->cbus_size);
494
495         if (g_pfe->nb_devs == 0) {
496                 pfe_hif_exit(g_pfe);
497                 pfe_hif_lib_exit(g_pfe);
498                 rte_free(g_pfe);
499                 g_pfe = NULL;
500         }
501         return 0;
502 }
503
504 static
505 struct rte_vdev_driver pmd_pfe_drv = {
506         .probe = pmd_pfe_probe,
507         .remove = pmd_pfe_remove,
508 };
509
510 RTE_PMD_REGISTER_VDEV(PFE_NAME_PMD, pmd_pfe_drv);
511 RTE_PMD_REGISTER_PARAM_STRING(PFE_NAME_PMD, PFE_VDEV_GEM_ID_ARG "=<int> ");
512
513 RTE_INIT(pfe_pmd_init_log)
514 {
515         pfe_logtype_pmd = rte_log_register("pmd.net.pfe");
516         if (pfe_logtype_pmd >= 0)
517                 rte_log_set_level(pfe_logtype_pmd, RTE_LOG_NOTICE);
518 }