1// SPDX-License-Identifier:    GPL-2.0
2/*
3 * Copyright (C) 2018 Marvell International Ltd.
4 */
5
6#include <dm.h>
7#include <errno.h>
8#include <malloc.h>
9#include <misc.h>
10#include <net.h>
11#include <pci_ids.h>
12#include <asm/io.h>
13#include <asm/types.h>
14#include <asm/arch/board.h>
15#include "cgx.h"
16#include "nix.h"
17
18extern struct udevice *rvu_af_dev;
19
20int rvu_pf_init(struct rvu_pf *rvu)
21{
22	struct nix *nix;
23	struct eth_pdata *pdata = dev_get_plat(rvu->dev);
24
25	debug("%s: Allocating nix lf\n", __func__);
26	nix = nix_lf_alloc(rvu->dev);
27	if (!nix) {
28		printf("%s: Error allocating lf for pf %d\n",
29		       __func__, rvu->pfid);
30		return -1;
31	}
32	rvu->nix = nix;
33
34	/* to make post_probe happy */
35	if (is_valid_ethaddr(nix->lmac->mac_addr)) {
36		memcpy(pdata->enetaddr, nix->lmac->mac_addr, 6);
37		eth_env_set_enetaddr_by_index("eth", dev_seq(rvu->dev),
38					      pdata->enetaddr);
39	}
40
41	return 0;
42}
43
44static const struct eth_ops nix_eth_ops = {
45	.start			= nix_lf_init,
46	.send			= nix_lf_xmit,
47	.recv			= nix_lf_recv,
48	.free_pkt		= nix_lf_free_pkt,
49	.stop			= nix_lf_halt,
50	.write_hwaddr		= nix_lf_setup_mac,
51};
52
53int rvu_pf_probe(struct udevice *dev)
54{
55	struct rvu_pf *rvu = dev_get_priv(dev);
56	int err;
57	char name[16];
58
59	debug("%s: name: %s\n", __func__, dev->name);
60
61	rvu->pf_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_2, 0, 0,
62				      PCI_REGION_TYPE, PCI_REGION_MEM);
63	rvu->pfid = dev_seq(dev) + 1; // RVU PF's start from 1;
64	rvu->dev = dev;
65	if (!rvu_af_dev) {
66		printf("%s: Error: Could not find RVU AF device\n",
67		       __func__);
68		return -1;
69	}
70	rvu->afdev = rvu_af_dev;
71
72	debug("RVU PF %u BAR2 %p\n", rvu->pfid, rvu->pf_base);
73
74	rvu_get_lfid_for_pf(rvu->pfid, &rvu->nix_lfid, &rvu->npa_lfid);
75
76	err = rvu_pf_init(rvu);
77	if (err)
78		printf("%s: Error %d adding nix\n", __func__, err);
79
80	/*
81	 * modify device name to include index/sequence number,
82	 * for better readability, this is 1:1 mapping with eth0/1/2.. names.
83	 */
84	sprintf(name, "rvu_pf#%d", dev_seq(dev));
85	device_set_name(dev, name);
86	debug("%s: name: %s\n", __func__, dev->name);
87	return err;
88}
89
90int rvu_pf_remove(struct udevice *dev)
91{
92	struct rvu_pf *rvu = dev_get_priv(dev);
93
94	nix_lf_shutdown(rvu->nix);
95	npa_lf_shutdown(rvu->nix);
96
97	debug("%s: rvu pf%d down --\n", __func__,  rvu->pfid);
98
99	return 0;
100}
101
102U_BOOT_DRIVER(rvu_pf) = {
103	.name   = "rvu_pf",
104	.id     = UCLASS_ETH,
105	.probe	= rvu_pf_probe,
106	.remove = rvu_pf_remove,
107	.ops    = &nix_eth_ops,
108	.priv_auto	= sizeof(struct rvu_pf),
109	.plat_auto	= sizeof(struct eth_pdata),
110};
111
112static struct pci_device_id rvu_pf_supported[] = {
113	{ PCI_VDEVICE(CAVIUM, PCI_DEVICE_ID_CAVIUM_RVU_PF) },
114	{}
115};
116
117U_BOOT_PCI_DEVICE(rvu_pf, rvu_pf_supported);
118