18c2ecf20Sopenharmony_ci/**********************************************************************
28c2ecf20Sopenharmony_ci * Author: Cavium, Inc.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Contact: support@cavium.com
58c2ecf20Sopenharmony_ci *          Please include "LiquidIO" in the subject.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Copyright (c) 2003-2016 Cavium, Inc.
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * This file is free software; you can redistribute it and/or modify
108c2ecf20Sopenharmony_ci * it under the terms of the GNU General Public License, Version 2, as
118c2ecf20Sopenharmony_ci * published by the Free Software Foundation.
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci * This file is distributed in the hope that it will be useful, but
148c2ecf20Sopenharmony_ci * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
158c2ecf20Sopenharmony_ci * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
168c2ecf20Sopenharmony_ci * NONINFRINGEMENT.  See the GNU General Public License for more details.
178c2ecf20Sopenharmony_ci ***********************************************************************/
188c2ecf20Sopenharmony_ci#include <linux/pci.h>
198c2ecf20Sopenharmony_ci#include <linux/netdevice.h>
208c2ecf20Sopenharmony_ci#include "liquidio_common.h"
218c2ecf20Sopenharmony_ci#include "octeon_droq.h"
228c2ecf20Sopenharmony_ci#include "octeon_iq.h"
238c2ecf20Sopenharmony_ci#include "response_manager.h"
248c2ecf20Sopenharmony_ci#include "octeon_device.h"
258c2ecf20Sopenharmony_ci#include "octeon_main.h"
268c2ecf20Sopenharmony_ci#include "cn66xx_regs.h"
278c2ecf20Sopenharmony_ci#include "cn66xx_device.h"
288c2ecf20Sopenharmony_ci#include "cn68xx_device.h"
298c2ecf20Sopenharmony_ci#include "cn68xx_regs.h"
308c2ecf20Sopenharmony_ci#include "cn68xx_device.h"
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_cistatic void lio_cn68xx_set_dpi_regs(struct octeon_device *oct)
338c2ecf20Sopenharmony_ci{
348c2ecf20Sopenharmony_ci	u32 i;
358c2ecf20Sopenharmony_ci	u32 fifo_sizes[6] = { 3, 3, 1, 1, 1, 8 };
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci	lio_pci_writeq(oct, CN6XXX_DPI_DMA_CTL_MASK, CN6XXX_DPI_DMA_CONTROL);
388c2ecf20Sopenharmony_ci	dev_dbg(&oct->pci_dev->dev, "DPI_DMA_CONTROL: 0x%016llx\n",
398c2ecf20Sopenharmony_ci		lio_pci_readq(oct, CN6XXX_DPI_DMA_CONTROL));
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci	for (i = 0; i < 6; i++) {
428c2ecf20Sopenharmony_ci		/* Prevent service of instruction queue for all DMA engines
438c2ecf20Sopenharmony_ci		 * Engine 5 will remain 0. Engines 0 - 4 will be setup by
448c2ecf20Sopenharmony_ci		 * core.
458c2ecf20Sopenharmony_ci		 */
468c2ecf20Sopenharmony_ci		lio_pci_writeq(oct, 0, CN6XXX_DPI_DMA_ENG_ENB(i));
478c2ecf20Sopenharmony_ci		lio_pci_writeq(oct, fifo_sizes[i], CN6XXX_DPI_DMA_ENG_BUF(i));
488c2ecf20Sopenharmony_ci		dev_dbg(&oct->pci_dev->dev, "DPI_ENG_BUF%d: 0x%016llx\n", i,
498c2ecf20Sopenharmony_ci			lio_pci_readq(oct, CN6XXX_DPI_DMA_ENG_BUF(i)));
508c2ecf20Sopenharmony_ci	}
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci	/* DPI_SLI_PRT_CFG has MPS and MRRS settings that will be set
538c2ecf20Sopenharmony_ci	 * separately.
548c2ecf20Sopenharmony_ci	 */
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	lio_pci_writeq(oct, 1, CN6XXX_DPI_CTL);
578c2ecf20Sopenharmony_ci	dev_dbg(&oct->pci_dev->dev, "DPI_CTL: 0x%016llx\n",
588c2ecf20Sopenharmony_ci		lio_pci_readq(oct, CN6XXX_DPI_CTL));
598c2ecf20Sopenharmony_ci}
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_cistatic int lio_cn68xx_soft_reset(struct octeon_device *oct)
628c2ecf20Sopenharmony_ci{
638c2ecf20Sopenharmony_ci	lio_cn6xxx_soft_reset(oct);
648c2ecf20Sopenharmony_ci	lio_cn68xx_set_dpi_regs(oct);
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	return 0;
678c2ecf20Sopenharmony_ci}
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_cistatic void lio_cn68xx_setup_pkt_ctl_regs(struct octeon_device *oct)
708c2ecf20Sopenharmony_ci{
718c2ecf20Sopenharmony_ci	struct octeon_cn6xxx *cn68xx = (struct octeon_cn6xxx *)oct->chip;
728c2ecf20Sopenharmony_ci	u64 pktctl, tx_pipe, max_oqs;
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	pktctl = octeon_read_csr64(oct, CN6XXX_SLI_PKT_CTL);
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	/* 68XX specific */
778c2ecf20Sopenharmony_ci	max_oqs = CFG_GET_OQ_MAX_Q(CHIP_CONF(oct, cn6xxx));
788c2ecf20Sopenharmony_ci	tx_pipe  = octeon_read_csr64(oct, CN68XX_SLI_TX_PIPE);
798c2ecf20Sopenharmony_ci	tx_pipe &= 0xffffffffff00ffffULL; /* clear out NUMP field */
808c2ecf20Sopenharmony_ci	tx_pipe |= max_oqs << 16; /* put max_oqs in NUMP field */
818c2ecf20Sopenharmony_ci	octeon_write_csr64(oct, CN68XX_SLI_TX_PIPE, tx_pipe);
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	if (CFG_GET_IS_SLI_BP_ON(cn68xx->conf))
848c2ecf20Sopenharmony_ci		pktctl |= 0xF;
858c2ecf20Sopenharmony_ci	else
868c2ecf20Sopenharmony_ci		/* Disable per-port backpressure. */
878c2ecf20Sopenharmony_ci		pktctl &= ~0xF;
888c2ecf20Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_SLI_PKT_CTL, pktctl);
898c2ecf20Sopenharmony_ci}
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_cistatic int lio_cn68xx_setup_device_regs(struct octeon_device *oct)
928c2ecf20Sopenharmony_ci{
938c2ecf20Sopenharmony_ci	lio_cn6xxx_setup_pcie_mps(oct, PCIE_MPS_DEFAULT);
948c2ecf20Sopenharmony_ci	lio_cn6xxx_setup_pcie_mrrs(oct, PCIE_MRRS_256B);
958c2ecf20Sopenharmony_ci	lio_cn6xxx_enable_error_reporting(oct);
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	lio_cn6xxx_setup_global_input_regs(oct);
988c2ecf20Sopenharmony_ci	lio_cn68xx_setup_pkt_ctl_regs(oct);
998c2ecf20Sopenharmony_ci	lio_cn6xxx_setup_global_output_regs(oct);
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	/* Default error timeout value should be 0x200000 to avoid host hang
1028c2ecf20Sopenharmony_ci	 * when reads invalid register
1038c2ecf20Sopenharmony_ci	 */
1048c2ecf20Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_SLI_WINDOW_CTL, 0x200000ULL);
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci	return 0;
1078c2ecf20Sopenharmony_ci}
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_cistatic inline void lio_cn68xx_vendor_message_fix(struct octeon_device *oct)
1108c2ecf20Sopenharmony_ci{
1118c2ecf20Sopenharmony_ci	u32 val = 0;
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci	/* Set M_VEND1_DRP and M_VEND0_DRP bits */
1148c2ecf20Sopenharmony_ci	pci_read_config_dword(oct->pci_dev, CN6XXX_PCIE_FLTMSK, &val);
1158c2ecf20Sopenharmony_ci	val |= 0x3;
1168c2ecf20Sopenharmony_ci	pci_write_config_dword(oct->pci_dev, CN6XXX_PCIE_FLTMSK, val);
1178c2ecf20Sopenharmony_ci}
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_cistatic int lio_is_210nv(struct octeon_device *oct)
1208c2ecf20Sopenharmony_ci{
1218c2ecf20Sopenharmony_ci	u64 mio_qlm4_cfg = lio_pci_readq(oct, CN6XXX_MIO_QLM4_CFG);
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	return ((mio_qlm4_cfg & CN6XXX_MIO_QLM_CFG_MASK) == 0);
1248c2ecf20Sopenharmony_ci}
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ciint lio_setup_cn68xx_octeon_device(struct octeon_device *oct)
1278c2ecf20Sopenharmony_ci{
1288c2ecf20Sopenharmony_ci	struct octeon_cn6xxx *cn68xx = (struct octeon_cn6xxx *)oct->chip;
1298c2ecf20Sopenharmony_ci	u16 card_type = LIO_410NV;
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	if (octeon_map_pci_barx(oct, 0, 0))
1328c2ecf20Sopenharmony_ci		return 1;
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	if (octeon_map_pci_barx(oct, 1, MAX_BAR1_IOREMAP_SIZE)) {
1358c2ecf20Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "%s CN68XX BAR1 map failed\n",
1368c2ecf20Sopenharmony_ci			__func__);
1378c2ecf20Sopenharmony_ci		octeon_unmap_pci_barx(oct, 0);
1388c2ecf20Sopenharmony_ci		return 1;
1398c2ecf20Sopenharmony_ci	}
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	spin_lock_init(&cn68xx->lock_for_droq_int_enb_reg);
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	oct->fn_list.setup_iq_regs = lio_cn6xxx_setup_iq_regs;
1448c2ecf20Sopenharmony_ci	oct->fn_list.setup_oq_regs = lio_cn6xxx_setup_oq_regs;
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	oct->fn_list.process_interrupt_regs = lio_cn6xxx_process_interrupt_regs;
1478c2ecf20Sopenharmony_ci	oct->fn_list.soft_reset = lio_cn68xx_soft_reset;
1488c2ecf20Sopenharmony_ci	oct->fn_list.setup_device_regs = lio_cn68xx_setup_device_regs;
1498c2ecf20Sopenharmony_ci	oct->fn_list.update_iq_read_idx = lio_cn6xxx_update_read_index;
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	oct->fn_list.bar1_idx_setup = lio_cn6xxx_bar1_idx_setup;
1528c2ecf20Sopenharmony_ci	oct->fn_list.bar1_idx_write = lio_cn6xxx_bar1_idx_write;
1538c2ecf20Sopenharmony_ci	oct->fn_list.bar1_idx_read = lio_cn6xxx_bar1_idx_read;
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	oct->fn_list.enable_interrupt = lio_cn6xxx_enable_interrupt;
1568c2ecf20Sopenharmony_ci	oct->fn_list.disable_interrupt = lio_cn6xxx_disable_interrupt;
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci	oct->fn_list.enable_io_queues = lio_cn6xxx_enable_io_queues;
1598c2ecf20Sopenharmony_ci	oct->fn_list.disable_io_queues = lio_cn6xxx_disable_io_queues;
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	lio_cn6xxx_setup_reg_address(oct, oct->chip, &oct->reg_list);
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	/* Determine variant of card */
1648c2ecf20Sopenharmony_ci	if (lio_is_210nv(oct))
1658c2ecf20Sopenharmony_ci		card_type = LIO_210NV;
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	cn68xx->conf = (struct octeon_config *)
1688c2ecf20Sopenharmony_ci		       oct_get_config_info(oct, card_type);
1698c2ecf20Sopenharmony_ci	if (!cn68xx->conf) {
1708c2ecf20Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "%s No Config found for CN68XX %s\n",
1718c2ecf20Sopenharmony_ci			__func__,
1728c2ecf20Sopenharmony_ci			(card_type == LIO_410NV) ? LIO_410NV_NAME :
1738c2ecf20Sopenharmony_ci			LIO_210NV_NAME);
1748c2ecf20Sopenharmony_ci		octeon_unmap_pci_barx(oct, 0);
1758c2ecf20Sopenharmony_ci		octeon_unmap_pci_barx(oct, 1);
1768c2ecf20Sopenharmony_ci		return 1;
1778c2ecf20Sopenharmony_ci	}
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci	oct->coproc_clock_rate = 1000000ULL * lio_cn6xxx_coprocessor_clock(oct);
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci	lio_cn68xx_vendor_message_fix(oct);
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci	return 0;
1848c2ecf20Sopenharmony_ci}
185