1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2018 Marvell International Ltd.
12 #include <linux/list.h>
13 #include <asm/arch/board.h>
14 #include <asm/arch/csrs/csrs-cgx.h>
19 char lmac_type_to_str[][8] = {
33 char lmac_speed_to_str[][8] = {
50 * Given an LMAC/PF instance number, return the lmac
51 * Per design, each PF has only one LMAC mapped.
53 * @param instance instance to find
55 * @return pointer to lmac data structure or NULL if not found
57 struct lmac *nix_get_cgx_lmac(int lmac_instance)
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,
70 cgx = dev_get_priv(dev);
71 debug("%s udev %p cgx %p instance %d\n", __func__, dev, cgx,
73 for (idx = 0; idx < cgx->lmac_count; idx++) {
74 if (cgx->lmac[idx]->instance == lmac_instance)
75 return cgx->lmac[idx];
81 void cgx_lmac_mac_filter_clear(struct lmac *lmac)
83 union cgxx_cmrx_rx_dmac_ctl0 dmac_ctl0;
84 union cgxx_cmr_rx_dmacx_cam0 dmac_cam0;
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);
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);
103 void cgx_lmac_mac_filter_setup(struct lmac *lmac)
105 union cgxx_cmrx_rx_dmac_ctl0 dmac_ctl0;
106 union cgxx_cmr_rx_dmacx_cam0 dmac_cam0;
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);
116 dmac_cam0.s.id = lmac->lmac_id;
117 dmac_cam0.s.adr = mac;
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);
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);
133 int cgx_lmac_set_pkind(struct lmac *lmac, u8 lmac_id, int pkind)
135 cgx_write(lmac->cgx, lmac_id, CGXX_CMRX_RX_ID_MAP(0),
140 int cgx_lmac_link_status(struct lmac *lmac, int lmac_id, u64 *status)
144 ret = cgx_intf_get_link_sts(lmac->cgx->cgx_id, lmac_id, status);
146 debug("%s request failed for cgx%d lmac%d\n",
147 __func__, lmac->cgx->cgx_id, lmac->lmac_id);
153 int cgx_lmac_rx_tx_enable(struct lmac *lmac, int lmac_id, bool enable)
155 struct cgx *cgx = lmac->cgx;
156 union cgxx_cmrx_config cmrx_config;
158 if (!cgx || lmac_id >= cgx->lmac_count)
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);
168 int cgx_lmac_link_enable(struct lmac *lmac, int lmac_id, bool enable,
173 ret = cgx_intf_link_up_dwn(lmac->cgx->cgx_id, lmac_id, enable,
176 debug("%s request failed for cgx%d lmac%d\n",
177 __func__, lmac->cgx->cgx_id, lmac->lmac_id);
183 int cgx_lmac_internal_loopback(struct lmac *lmac, int lmac_id, bool enable)
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;
191 if (!cgx || lmac_id >= cgx->lmac_count)
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),
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),
212 static int cgx_lmac_init(struct cgx *cgx)
215 union cgxx_cmrx_config cmrx_cfg;
216 static int instance = 1;
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);
223 for (i = 0; i < cgx->lmac_count; i++) {
224 lmac = calloc(1, sizeof(*lmac));
227 lmac->instance = instance++;
228 snprintf(lmac->name, sizeof(lmac->name), "cgx_fwi_%d_%d",
231 cmrx_cfg.u = cgx_read(cgx, i, CGXX_CMRX_CONFIG(0));
232 lmac->lmac_type = cmrx_cfg.s.lmac_type;
237 debug("%s: map id %d to lmac %p (%s), type:%d instance %d\n",
238 __func__, i, lmac, lmac->name, lmac->lmac_type,
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),
245 debug("%s: MAC %pM\n", __func__, lmac->mac_addr);
246 cgx_lmac_mac_filter_setup(lmac);
251 int cgx_probe(struct udevice *dev)
253 struct cgx *cgx = dev_get_priv(dev);
256 cgx->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0,
259 cgx->cgx_id = ((u64)(cgx->reg_base) >> 24) & 0x7;
261 debug("%s CGX BAR %p, id: %d\n", __func__, cgx->reg_base,
263 debug("%s CGX %p, udev: %p\n", __func__, cgx, dev);
265 err = cgx_lmac_init(cgx);
270 int cgx_remove(struct udevice *dev)
272 struct cgx *cgx = dev_get_priv(dev);
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]);
283 U_BOOT_DRIVER(cgx) = {
287 .remove = cgx_remove,
288 .priv_auto = sizeof(struct cgx),
291 static struct pci_device_id cgx_supported[] = {
292 {PCI_VDEVICE(CAVIUM, PCI_DEVICE_ID_CAVIUM_CGX) },
296 U_BOOT_PCI_DEVICE(cgx, cgx_supported);