dm: treewide: Rename auto_alloc_size members to be shorter
[platform/kernel/u-boot.git] / drivers / net / octeontx2 / cgx.c
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 <linux/list.h>
13 #include <asm/arch/board.h>
14 #include <asm/arch/csrs/csrs-cgx.h>
15 #include <asm/io.h>
16
17 #include "cgx.h"
18
19 char lmac_type_to_str[][8] = {
20         "SGMII",
21         "XAUI",
22         "RXAUI",
23         "10G_R",
24         "40G_R",
25         "RGMII",
26         "QSGMII",
27         "25G_R",
28         "50G_R",
29         "100G_R",
30         "USXGMII",
31 };
32
33 char lmac_speed_to_str[][8] = {
34         "0",
35         "10M",
36         "100M",
37         "1G",
38         "2.5G",
39         "5G",
40         "10G",
41         "20G",
42         "25G",
43         "40G",
44         "50G",
45         "80G",
46         "100G",
47 };
48
49 /**
50  * Given an LMAC/PF instance number, return the lmac
51  * Per design, each PF has only one LMAC mapped.
52  *
53  * @param instance      instance to find
54  *
55  * @return      pointer to lmac data structure or NULL if not found
56  */
57 struct lmac *nix_get_cgx_lmac(int lmac_instance)
58 {
59         struct cgx *cgx;
60         struct udevice *dev;
61         int i, idx, err;
62
63         for (i = 0; i < CGX_PER_NODE; i++) {
64                 err = dm_pci_find_device(PCI_VENDOR_ID_CAVIUM,
65                                          PCI_DEVICE_ID_OCTEONTX2_CGX, i,
66                                          &dev);
67                 if (err)
68                         continue;
69
70                 cgx = dev_get_priv(dev);
71                 debug("%s udev %p cgx %p instance %d\n", __func__, dev, cgx,
72                       lmac_instance);
73                 for (idx = 0; idx < cgx->lmac_count; idx++) {
74                         if (cgx->lmac[idx]->instance == lmac_instance)
75                                 return cgx->lmac[idx];
76                 }
77         }
78         return NULL;
79 }
80
81 void cgx_lmac_mac_filter_clear(struct lmac *lmac)
82 {
83         union cgxx_cmrx_rx_dmac_ctl0 dmac_ctl0;
84         union cgxx_cmr_rx_dmacx_cam0 dmac_cam0;
85         void *reg_addr;
86
87         dmac_cam0.u = 0x0;
88         reg_addr = lmac->cgx->reg_base +
89                         CGXX_CMR_RX_DMACX_CAM0(lmac->lmac_id * 8);
90         writeq(dmac_cam0.u, reg_addr);
91         debug("%s: reg %p dmac_cam0 %llx\n", __func__, reg_addr, dmac_cam0.u);
92
93         dmac_ctl0.u = 0x0;
94         dmac_ctl0.s.bcst_accept = 1;
95         dmac_ctl0.s.mcst_mode = 1;
96         dmac_ctl0.s.cam_accept = 0;
97         reg_addr = lmac->cgx->reg_base +
98                         CGXX_CMRX_RX_DMAC_CTL0(lmac->lmac_id);
99         writeq(dmac_ctl0.u, reg_addr);
100         debug("%s: reg %p dmac_ctl0 %llx\n", __func__, reg_addr, dmac_ctl0.u);
101 }
102
103 void cgx_lmac_mac_filter_setup(struct lmac *lmac)
104 {
105         union cgxx_cmrx_rx_dmac_ctl0 dmac_ctl0;
106         union cgxx_cmr_rx_dmacx_cam0 dmac_cam0;
107         u64 mac, tmp;
108         void *reg_addr;
109
110         memcpy((void *)&tmp, lmac->mac_addr, 6);
111         debug("%s: tmp %llx\n", __func__, tmp);
112         debug("%s: swab tmp %llx\n", __func__, swab64(tmp));
113         mac = swab64(tmp) >> 16;
114         debug("%s: mac %llx\n", __func__, mac);
115         dmac_cam0.u = 0x0;
116         dmac_cam0.s.id = lmac->lmac_id;
117         dmac_cam0.s.adr = mac;
118         dmac_cam0.s.en = 1;
119         reg_addr = lmac->cgx->reg_base +
120                         CGXX_CMR_RX_DMACX_CAM0(lmac->lmac_id * 8);
121         writeq(dmac_cam0.u, reg_addr);
122         debug("%s: reg %p dmac_cam0 %llx\n", __func__, reg_addr, dmac_cam0.u);
123         dmac_ctl0.u = 0x0;
124         dmac_ctl0.s.bcst_accept = 1;
125         dmac_ctl0.s.mcst_mode = 0;
126         dmac_ctl0.s.cam_accept = 1;
127         reg_addr = lmac->cgx->reg_base +
128                         CGXX_CMRX_RX_DMAC_CTL0(lmac->lmac_id);
129         writeq(dmac_ctl0.u, reg_addr);
130         debug("%s: reg %p dmac_ctl0 %llx\n", __func__, reg_addr, dmac_ctl0.u);
131 }
132
133 int cgx_lmac_set_pkind(struct lmac *lmac, u8 lmac_id, int pkind)
134 {
135         cgx_write(lmac->cgx, lmac_id, CGXX_CMRX_RX_ID_MAP(0),
136                   (pkind & 0x3f));
137         return 0;
138 }
139
140 int cgx_lmac_link_status(struct lmac *lmac, int lmac_id, u64 *status)
141 {
142         int ret = 0;
143
144         ret = cgx_intf_get_link_sts(lmac->cgx->cgx_id, lmac_id, status);
145         if (ret) {
146                 debug("%s request failed for cgx%d lmac%d\n",
147                       __func__, lmac->cgx->cgx_id, lmac->lmac_id);
148                 ret = -1;
149         }
150         return ret;
151 }
152
153 int cgx_lmac_rx_tx_enable(struct lmac *lmac, int lmac_id, bool enable)
154 {
155         struct cgx *cgx = lmac->cgx;
156         union cgxx_cmrx_config cmrx_config;
157
158         if (!cgx || lmac_id >= cgx->lmac_count)
159                 return -ENODEV;
160
161         cmrx_config.u = cgx_read(cgx, lmac_id, CGXX_CMRX_CONFIG(0));
162         cmrx_config.s.data_pkt_rx_en =
163         cmrx_config.s.data_pkt_tx_en = enable ? 1 : 0;
164         cgx_write(cgx, lmac_id, CGXX_CMRX_CONFIG(0), cmrx_config.u);
165         return 0;
166 }
167
168 int cgx_lmac_link_enable(struct lmac *lmac, int lmac_id, bool enable,
169                          u64 *status)
170 {
171         int ret = 0;
172
173         ret = cgx_intf_link_up_dwn(lmac->cgx->cgx_id, lmac_id, enable,
174                                    status);
175         if (ret) {
176                 debug("%s request failed for cgx%d lmac%d\n",
177                       __func__, lmac->cgx->cgx_id, lmac->lmac_id);
178                 ret = -1;
179         }
180         return ret;
181 }
182
183 int cgx_lmac_internal_loopback(struct lmac *lmac, int lmac_id, bool enable)
184 {
185         struct cgx *cgx = lmac->cgx;
186         union cgxx_cmrx_config cmrx_cfg;
187         union cgxx_gmp_pcs_mrx_control mrx_control;
188         union cgxx_spux_control1 spux_control1;
189         enum lmac_type lmac_type;
190
191         if (!cgx || lmac_id >= cgx->lmac_count)
192                 return -ENODEV;
193
194         cmrx_cfg.u = cgx_read(cgx, lmac_id, CGXX_CMRX_CONFIG(0));
195         lmac_type = cmrx_cfg.s.lmac_type;
196         if (lmac_type == LMAC_MODE_SGMII || lmac_type == LMAC_MODE_QSGMII) {
197                 mrx_control.u = cgx_read(cgx, lmac_id,
198                                          CGXX_GMP_PCS_MRX_CONTROL(0));
199                 mrx_control.s.loopbck1 = enable ? 1 : 0;
200                 cgx_write(cgx, lmac_id, CGXX_GMP_PCS_MRX_CONTROL(0),
201                           mrx_control.u);
202         } else {
203                 spux_control1.u = cgx_read(cgx, lmac_id,
204                                            CGXX_SPUX_CONTROL1(0));
205                 spux_control1.s.loopbck = enable ? 1 : 0;
206                 cgx_write(cgx, lmac_id, CGXX_SPUX_CONTROL1(0),
207                           spux_control1.u);
208         }
209         return 0;
210 }
211
212 static int cgx_lmac_init(struct cgx *cgx)
213 {
214         struct lmac *lmac;
215         union cgxx_cmrx_config cmrx_cfg;
216         static int instance = 1;
217         int i;
218
219         cgx->lmac_count = cgx_read(cgx, 0, CGXX_CMR_RX_LMACS());
220         debug("%s: Found %d lmacs for cgx %d@%p\n", __func__, cgx->lmac_count,
221               cgx->cgx_id, cgx->reg_base);
222
223         for (i = 0; i < cgx->lmac_count; i++) {
224                 lmac = calloc(1, sizeof(*lmac));
225                 if (!lmac)
226                         return -ENOMEM;
227                 lmac->instance = instance++;
228                 snprintf(lmac->name, sizeof(lmac->name), "cgx_fwi_%d_%d",
229                          cgx->cgx_id, i);
230                 /* Get LMAC type */
231                 cmrx_cfg.u = cgx_read(cgx, i, CGXX_CMRX_CONFIG(0));
232                 lmac->lmac_type = cmrx_cfg.s.lmac_type;
233
234                 lmac->lmac_id = i;
235                 lmac->cgx = cgx;
236                 cgx->lmac[i] = lmac;
237                 debug("%s: map id %d to lmac %p (%s), type:%d instance %d\n",
238                       __func__, i, lmac, lmac->name, lmac->lmac_type,
239                       lmac->instance);
240                 lmac->init_pend = 1;
241                 printf("CGX%d LMAC%d [%s]\n", lmac->cgx->cgx_id,
242                        lmac->lmac_id, lmac_type_to_str[lmac->lmac_type]);
243                 octeontx2_board_get_mac_addr((lmac->instance - 1),
244                                              lmac->mac_addr);
245                 debug("%s: MAC %pM\n", __func__, lmac->mac_addr);
246                 cgx_lmac_mac_filter_setup(lmac);
247         }
248         return 0;
249 }
250
251 int cgx_probe(struct udevice *dev)
252 {
253         struct cgx *cgx = dev_get_priv(dev);
254         int err;
255
256         cgx->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0,
257                                        PCI_REGION_MEM);
258         cgx->dev = dev;
259         cgx->cgx_id = ((u64)(cgx->reg_base) >> 24) & 0x7;
260
261         debug("%s CGX BAR %p, id: %d\n", __func__, cgx->reg_base,
262               cgx->cgx_id);
263         debug("%s CGX %p, udev: %p\n", __func__, cgx, dev);
264
265         err = cgx_lmac_init(cgx);
266
267         return err;
268 }
269
270 int cgx_remove(struct udevice *dev)
271 {
272         struct cgx *cgx = dev_get_priv(dev);
273         int i;
274
275         debug("%s: cgx remove reg_base %p cgx_id %d",
276               __func__, cgx->reg_base, cgx->cgx_id);
277         for (i = 0; i < cgx->lmac_count; i++)
278                 cgx_lmac_mac_filter_clear(cgx->lmac[i]);
279
280         return 0;
281 }
282
283 U_BOOT_DRIVER(cgx) = {
284         .name   = "cgx",
285         .id     = UCLASS_MISC,
286         .probe  = cgx_probe,
287         .remove = cgx_remove,
288         .priv_auto      = sizeof(struct cgx),
289 };
290
291 static struct pci_device_id cgx_supported[] = {
292         {PCI_VDEVICE(CAVIUM, PCI_DEVICE_ID_CAVIUM_CGX) },
293         {}
294 };
295
296 U_BOOT_PCI_DEVICE(cgx, cgx_supported);