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
298c2ecf20Sopenharmony_ciint lio_cn6xxx_soft_reset(struct octeon_device *oct)
308c2ecf20Sopenharmony_ci{
318c2ecf20Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_WIN_WR_MASK_REG, 0xFF);
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	dev_dbg(&oct->pci_dev->dev, "BIST enabled for soft reset\n");
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	lio_pci_writeq(oct, 1, CN6XXX_CIU_SOFT_BIST);
368c2ecf20Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_SLI_SCRATCH1, 0x1234ULL);
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	lio_pci_readq(oct, CN6XXX_CIU_SOFT_RST);
398c2ecf20Sopenharmony_ci	lio_pci_writeq(oct, 1, CN6XXX_CIU_SOFT_RST);
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci	/* Wait for 10ms as Octeon resets. */
428c2ecf20Sopenharmony_ci	mdelay(100);
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	if (octeon_read_csr64(oct, CN6XXX_SLI_SCRATCH1)) {
458c2ecf20Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "Soft reset failed\n");
468c2ecf20Sopenharmony_ci		return 1;
478c2ecf20Sopenharmony_ci	}
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	dev_dbg(&oct->pci_dev->dev, "Reset completed\n");
508c2ecf20Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_WIN_WR_MASK_REG, 0xFF);
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci	return 0;
538c2ecf20Sopenharmony_ci}
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_civoid lio_cn6xxx_enable_error_reporting(struct octeon_device *oct)
568c2ecf20Sopenharmony_ci{
578c2ecf20Sopenharmony_ci	u32 val;
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	pci_read_config_dword(oct->pci_dev, CN6XXX_PCIE_DEVCTL, &val);
608c2ecf20Sopenharmony_ci	if (val & 0x000c0000) {
618c2ecf20Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "PCI-E Link error detected: 0x%08x\n",
628c2ecf20Sopenharmony_ci			val & 0x000c0000);
638c2ecf20Sopenharmony_ci	}
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	val |= 0xf;          /* Enable Link error reporting */
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	dev_dbg(&oct->pci_dev->dev, "Enabling PCI-E error reporting..\n");
688c2ecf20Sopenharmony_ci	pci_write_config_dword(oct->pci_dev, CN6XXX_PCIE_DEVCTL, val);
698c2ecf20Sopenharmony_ci}
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_civoid lio_cn6xxx_setup_pcie_mps(struct octeon_device *oct,
728c2ecf20Sopenharmony_ci			       enum octeon_pcie_mps mps)
738c2ecf20Sopenharmony_ci{
748c2ecf20Sopenharmony_ci	u32 val;
758c2ecf20Sopenharmony_ci	u64 r64;
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	/* Read config register for MPS */
788c2ecf20Sopenharmony_ci	pci_read_config_dword(oct->pci_dev, CN6XXX_PCIE_DEVCTL, &val);
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	if (mps == PCIE_MPS_DEFAULT) {
818c2ecf20Sopenharmony_ci		mps = ((val & (0x7 << 5)) >> 5);
828c2ecf20Sopenharmony_ci	} else {
838c2ecf20Sopenharmony_ci		val &= ~(0x7 << 5);  /* Turn off any MPS bits */
848c2ecf20Sopenharmony_ci		val |= (mps << 5);   /* Set MPS */
858c2ecf20Sopenharmony_ci		pci_write_config_dword(oct->pci_dev, CN6XXX_PCIE_DEVCTL, val);
868c2ecf20Sopenharmony_ci	}
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	/* Set MPS in DPI_SLI_PRT0_CFG to the same value. */
898c2ecf20Sopenharmony_ci	r64 = lio_pci_readq(oct, CN6XXX_DPI_SLI_PRTX_CFG(oct->pcie_port));
908c2ecf20Sopenharmony_ci	r64 |= (mps << 4);
918c2ecf20Sopenharmony_ci	lio_pci_writeq(oct, r64, CN6XXX_DPI_SLI_PRTX_CFG(oct->pcie_port));
928c2ecf20Sopenharmony_ci}
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_civoid lio_cn6xxx_setup_pcie_mrrs(struct octeon_device *oct,
958c2ecf20Sopenharmony_ci				enum octeon_pcie_mrrs mrrs)
968c2ecf20Sopenharmony_ci{
978c2ecf20Sopenharmony_ci	u32 val;
988c2ecf20Sopenharmony_ci	u64 r64;
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci	/* Read config register for MRRS */
1018c2ecf20Sopenharmony_ci	pci_read_config_dword(oct->pci_dev, CN6XXX_PCIE_DEVCTL, &val);
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	if (mrrs == PCIE_MRRS_DEFAULT) {
1048c2ecf20Sopenharmony_ci		mrrs = ((val & (0x7 << 12)) >> 12);
1058c2ecf20Sopenharmony_ci	} else {
1068c2ecf20Sopenharmony_ci		val &= ~(0x7 << 12); /* Turn off any MRRS bits */
1078c2ecf20Sopenharmony_ci		val |= (mrrs << 12); /* Set MRRS */
1088c2ecf20Sopenharmony_ci		pci_write_config_dword(oct->pci_dev, CN6XXX_PCIE_DEVCTL, val);
1098c2ecf20Sopenharmony_ci	}
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	/* Set MRRS in SLI_S2M_PORT0_CTL to the same value. */
1128c2ecf20Sopenharmony_ci	r64 = octeon_read_csr64(oct, CN6XXX_SLI_S2M_PORTX_CTL(oct->pcie_port));
1138c2ecf20Sopenharmony_ci	r64 |= mrrs;
1148c2ecf20Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_SLI_S2M_PORTX_CTL(oct->pcie_port), r64);
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	/* Set MRRS in DPI_SLI_PRT0_CFG to the same value. */
1178c2ecf20Sopenharmony_ci	r64 = lio_pci_readq(oct, CN6XXX_DPI_SLI_PRTX_CFG(oct->pcie_port));
1188c2ecf20Sopenharmony_ci	r64 |= mrrs;
1198c2ecf20Sopenharmony_ci	lio_pci_writeq(oct, r64, CN6XXX_DPI_SLI_PRTX_CFG(oct->pcie_port));
1208c2ecf20Sopenharmony_ci}
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ciu32 lio_cn6xxx_coprocessor_clock(struct octeon_device *oct)
1238c2ecf20Sopenharmony_ci{
1248c2ecf20Sopenharmony_ci	/* Bits 29:24 of MIO_RST_BOOT holds the ref. clock multiplier
1258c2ecf20Sopenharmony_ci	 * for SLI.
1268c2ecf20Sopenharmony_ci	 */
1278c2ecf20Sopenharmony_ci	return ((lio_pci_readq(oct, CN6XXX_MIO_RST_BOOT) >> 24) & 0x3f) * 50;
1288c2ecf20Sopenharmony_ci}
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ciu32 lio_cn6xxx_get_oq_ticks(struct octeon_device *oct,
1318c2ecf20Sopenharmony_ci			    u32 time_intr_in_us)
1328c2ecf20Sopenharmony_ci{
1338c2ecf20Sopenharmony_ci	/* This gives the SLI clock per microsec */
1348c2ecf20Sopenharmony_ci	u32 oqticks_per_us = lio_cn6xxx_coprocessor_clock(oct);
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci	/* core clock per us / oq ticks will be fractional. TO avoid that
1378c2ecf20Sopenharmony_ci	 * we use the method below.
1388c2ecf20Sopenharmony_ci	 */
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	/* This gives the clock cycles per millisecond */
1418c2ecf20Sopenharmony_ci	oqticks_per_us *= 1000;
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	/* This gives the oq ticks (1024 core clock cycles) per millisecond */
1448c2ecf20Sopenharmony_ci	oqticks_per_us /= 1024;
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	/* time_intr is in microseconds. The next 2 steps gives the oq ticks
1478c2ecf20Sopenharmony_ci	 * corressponding to time_intr.
1488c2ecf20Sopenharmony_ci	 */
1498c2ecf20Sopenharmony_ci	oqticks_per_us *= time_intr_in_us;
1508c2ecf20Sopenharmony_ci	oqticks_per_us /= 1000;
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	return oqticks_per_us;
1538c2ecf20Sopenharmony_ci}
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_civoid lio_cn6xxx_setup_global_input_regs(struct octeon_device *oct)
1568c2ecf20Sopenharmony_ci{
1578c2ecf20Sopenharmony_ci	/* Select Round-Robin Arb, ES, RO, NS for Input Queues */
1588c2ecf20Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_PKT_INPUT_CONTROL,
1598c2ecf20Sopenharmony_ci			 CN6XXX_INPUT_CTL_MASK);
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	/* Instruction Read Size - Max 4 instructions per PCIE Read */
1628c2ecf20Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_SLI_PKT_INSTR_RD_SIZE,
1638c2ecf20Sopenharmony_ci			   0xFFFFFFFFFFFFFFFFULL);
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	/* Select PCIE Port for all Input rings. */
1668c2ecf20Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_SLI_IN_PCIE_PORT,
1678c2ecf20Sopenharmony_ci			   (oct->pcie_port * 0x5555555555555555ULL));
1688c2ecf20Sopenharmony_ci}
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_cistatic void lio_cn66xx_setup_pkt_ctl_regs(struct octeon_device *oct)
1718c2ecf20Sopenharmony_ci{
1728c2ecf20Sopenharmony_ci	u64 pktctl;
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	struct octeon_cn6xxx *cn6xxx = (struct octeon_cn6xxx *)oct->chip;
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	pktctl = octeon_read_csr64(oct, CN6XXX_SLI_PKT_CTL);
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci	/* 66XX SPECIFIC */
1798c2ecf20Sopenharmony_ci	if (CFG_GET_OQ_MAX_Q(cn6xxx->conf) <= 4)
1808c2ecf20Sopenharmony_ci		/* Disable RING_EN if only upto 4 rings are used. */
1818c2ecf20Sopenharmony_ci		pktctl &= ~(1 << 4);
1828c2ecf20Sopenharmony_ci	else
1838c2ecf20Sopenharmony_ci		pktctl |= (1 << 4);
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci	if (CFG_GET_IS_SLI_BP_ON(cn6xxx->conf))
1868c2ecf20Sopenharmony_ci		pktctl |= 0xF;
1878c2ecf20Sopenharmony_ci	else
1888c2ecf20Sopenharmony_ci		/* Disable per-port backpressure. */
1898c2ecf20Sopenharmony_ci		pktctl &= ~0xF;
1908c2ecf20Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_SLI_PKT_CTL, pktctl);
1918c2ecf20Sopenharmony_ci}
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_civoid lio_cn6xxx_setup_global_output_regs(struct octeon_device *oct)
1948c2ecf20Sopenharmony_ci{
1958c2ecf20Sopenharmony_ci	u32 time_threshold;
1968c2ecf20Sopenharmony_ci	struct octeon_cn6xxx *cn6xxx = (struct octeon_cn6xxx *)oct->chip;
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	/* / Select PCI-E Port for all Output queues */
1998c2ecf20Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_SLI_PKT_PCIE_PORT64,
2008c2ecf20Sopenharmony_ci			   (oct->pcie_port * 0x5555555555555555ULL));
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci	if (CFG_GET_IS_SLI_BP_ON(cn6xxx->conf)) {
2038c2ecf20Sopenharmony_ci		octeon_write_csr64(oct, CN6XXX_SLI_OQ_WMARK, 32);
2048c2ecf20Sopenharmony_ci	} else {
2058c2ecf20Sopenharmony_ci		/* / Set Output queue watermark to 0 to disable backpressure */
2068c2ecf20Sopenharmony_ci		octeon_write_csr64(oct, CN6XXX_SLI_OQ_WMARK, 0);
2078c2ecf20Sopenharmony_ci	}
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	/* / Select Packet count instead of bytes for SLI_PKTi_CNTS[CNT] */
2108c2ecf20Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_PKT_OUT_BMODE, 0);
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	/* Select ES, RO, NS setting from register for Output Queue Packet
2138c2ecf20Sopenharmony_ci	 * Address
2148c2ecf20Sopenharmony_ci	 */
2158c2ecf20Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_PKT_DPADDR, 0xFFFFFFFF);
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	/* No Relaxed Ordering, No Snoop, 64-bit swap for Output
2188c2ecf20Sopenharmony_ci	 * Queue ScatterList
2198c2ecf20Sopenharmony_ci	 */
2208c2ecf20Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_PKT_SLIST_ROR, 0);
2218c2ecf20Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_PKT_SLIST_NS, 0);
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci	/* / ENDIAN_SPECIFIC CHANGES - 0 works for LE. */
2248c2ecf20Sopenharmony_ci#ifdef __BIG_ENDIAN_BITFIELD
2258c2ecf20Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_SLI_PKT_SLIST_ES64,
2268c2ecf20Sopenharmony_ci			   0x5555555555555555ULL);
2278c2ecf20Sopenharmony_ci#else
2288c2ecf20Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_SLI_PKT_SLIST_ES64, 0ULL);
2298c2ecf20Sopenharmony_ci#endif
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	/* / No Relaxed Ordering, No Snoop, 64-bit swap for Output Queue Data */
2328c2ecf20Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_PKT_DATA_OUT_ROR, 0);
2338c2ecf20Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_PKT_DATA_OUT_NS, 0);
2348c2ecf20Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_SLI_PKT_DATA_OUT_ES64,
2358c2ecf20Sopenharmony_ci			   0x5555555555555555ULL);
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci	/* / Set up interrupt packet and time threshold */
2388c2ecf20Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_OQ_INT_LEVEL_PKTS,
2398c2ecf20Sopenharmony_ci			 (u32)CFG_GET_OQ_INTR_PKT(cn6xxx->conf));
2408c2ecf20Sopenharmony_ci	time_threshold =
2418c2ecf20Sopenharmony_ci		lio_cn6xxx_get_oq_ticks(oct, (u32)
2428c2ecf20Sopenharmony_ci					CFG_GET_OQ_INTR_TIME(cn6xxx->conf));
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_OQ_INT_LEVEL_TIME, time_threshold);
2458c2ecf20Sopenharmony_ci}
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_cistatic int lio_cn6xxx_setup_device_regs(struct octeon_device *oct)
2488c2ecf20Sopenharmony_ci{
2498c2ecf20Sopenharmony_ci	lio_cn6xxx_setup_pcie_mps(oct, PCIE_MPS_DEFAULT);
2508c2ecf20Sopenharmony_ci	lio_cn6xxx_setup_pcie_mrrs(oct, PCIE_MRRS_512B);
2518c2ecf20Sopenharmony_ci	lio_cn6xxx_enable_error_reporting(oct);
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	lio_cn6xxx_setup_global_input_regs(oct);
2548c2ecf20Sopenharmony_ci	lio_cn66xx_setup_pkt_ctl_regs(oct);
2558c2ecf20Sopenharmony_ci	lio_cn6xxx_setup_global_output_regs(oct);
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	/* Default error timeout value should be 0x200000 to avoid host hang
2588c2ecf20Sopenharmony_ci	 * when reads invalid register
2598c2ecf20Sopenharmony_ci	 */
2608c2ecf20Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_SLI_WINDOW_CTL, 0x200000ULL);
2618c2ecf20Sopenharmony_ci	return 0;
2628c2ecf20Sopenharmony_ci}
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_civoid lio_cn6xxx_setup_iq_regs(struct octeon_device *oct, u32 iq_no)
2658c2ecf20Sopenharmony_ci{
2668c2ecf20Sopenharmony_ci	struct octeon_instr_queue *iq = oct->instr_queue[iq_no];
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_SLI_IQ_PKT_INSTR_HDR64(iq_no), 0);
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	/* Write the start of the input queue's ring and its size  */
2718c2ecf20Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_SLI_IQ_BASE_ADDR64(iq_no),
2728c2ecf20Sopenharmony_ci			   iq->base_addr_dma);
2738c2ecf20Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_IQ_SIZE(iq_no), iq->max_count);
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci	/* Remember the doorbell & instruction count register addr for this
2768c2ecf20Sopenharmony_ci	 * queue
2778c2ecf20Sopenharmony_ci	 */
2788c2ecf20Sopenharmony_ci	iq->doorbell_reg = oct->mmio[0].hw_addr + CN6XXX_SLI_IQ_DOORBELL(iq_no);
2798c2ecf20Sopenharmony_ci	iq->inst_cnt_reg = oct->mmio[0].hw_addr
2808c2ecf20Sopenharmony_ci			   + CN6XXX_SLI_IQ_INSTR_COUNT(iq_no);
2818c2ecf20Sopenharmony_ci	dev_dbg(&oct->pci_dev->dev, "InstQ[%d]:dbell reg @ 0x%p instcnt_reg @ 0x%p\n",
2828c2ecf20Sopenharmony_ci		iq_no, iq->doorbell_reg, iq->inst_cnt_reg);
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	/* Store the current instruction counter
2858c2ecf20Sopenharmony_ci	 * (used in flush_iq calculation)
2868c2ecf20Sopenharmony_ci	 */
2878c2ecf20Sopenharmony_ci	iq->reset_instr_cnt = readl(iq->inst_cnt_reg);
2888c2ecf20Sopenharmony_ci}
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_cistatic void lio_cn66xx_setup_iq_regs(struct octeon_device *oct, u32 iq_no)
2918c2ecf20Sopenharmony_ci{
2928c2ecf20Sopenharmony_ci	lio_cn6xxx_setup_iq_regs(oct, iq_no);
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	/* Backpressure for this queue - WMARK set to all F's. This effectively
2958c2ecf20Sopenharmony_ci	 * disables the backpressure mechanism.
2968c2ecf20Sopenharmony_ci	 */
2978c2ecf20Sopenharmony_ci	octeon_write_csr64(oct, CN66XX_SLI_IQ_BP64(iq_no),
2988c2ecf20Sopenharmony_ci			   (0xFFFFFFFFULL << 32));
2998c2ecf20Sopenharmony_ci}
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_civoid lio_cn6xxx_setup_oq_regs(struct octeon_device *oct, u32 oq_no)
3028c2ecf20Sopenharmony_ci{
3038c2ecf20Sopenharmony_ci	u32 intr;
3048c2ecf20Sopenharmony_ci	struct octeon_droq *droq = oct->droq[oq_no];
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_SLI_OQ_BASE_ADDR64(oq_no),
3078c2ecf20Sopenharmony_ci			   droq->desc_ring_dma);
3088c2ecf20Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_OQ_SIZE(oq_no), droq->max_count);
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_OQ_BUFF_INFO_SIZE(oq_no),
3118c2ecf20Sopenharmony_ci			 droq->buffer_size);
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci	/* Get the mapped address of the pkt_sent and pkts_credit regs */
3148c2ecf20Sopenharmony_ci	droq->pkts_sent_reg =
3158c2ecf20Sopenharmony_ci		oct->mmio[0].hw_addr + CN6XXX_SLI_OQ_PKTS_SENT(oq_no);
3168c2ecf20Sopenharmony_ci	droq->pkts_credit_reg =
3178c2ecf20Sopenharmony_ci		oct->mmio[0].hw_addr + CN6XXX_SLI_OQ_PKTS_CREDIT(oq_no);
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci	/* Enable this output queue to generate Packet Timer Interrupt */
3208c2ecf20Sopenharmony_ci	intr = octeon_read_csr(oct, CN6XXX_SLI_PKT_TIME_INT_ENB);
3218c2ecf20Sopenharmony_ci	intr |= (1 << oq_no);
3228c2ecf20Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_PKT_TIME_INT_ENB, intr);
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	/* Enable this output queue to generate Packet Timer Interrupt */
3258c2ecf20Sopenharmony_ci	intr = octeon_read_csr(oct, CN6XXX_SLI_PKT_CNT_INT_ENB);
3268c2ecf20Sopenharmony_ci	intr |= (1 << oq_no);
3278c2ecf20Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_PKT_CNT_INT_ENB, intr);
3288c2ecf20Sopenharmony_ci}
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ciint lio_cn6xxx_enable_io_queues(struct octeon_device *oct)
3318c2ecf20Sopenharmony_ci{
3328c2ecf20Sopenharmony_ci	u32 mask;
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci	mask = octeon_read_csr(oct, CN6XXX_SLI_PKT_INSTR_SIZE);
3358c2ecf20Sopenharmony_ci	mask |= oct->io_qmask.iq64B;
3368c2ecf20Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_PKT_INSTR_SIZE, mask);
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_ci	mask = octeon_read_csr(oct, CN6XXX_SLI_PKT_INSTR_ENB);
3398c2ecf20Sopenharmony_ci	mask |= oct->io_qmask.iq;
3408c2ecf20Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_PKT_INSTR_ENB, mask);
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	mask = octeon_read_csr(oct, CN6XXX_SLI_PKT_OUT_ENB);
3438c2ecf20Sopenharmony_ci	mask |= oct->io_qmask.oq;
3448c2ecf20Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_PKT_OUT_ENB, mask);
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci	return 0;
3478c2ecf20Sopenharmony_ci}
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_civoid lio_cn6xxx_disable_io_queues(struct octeon_device *oct)
3508c2ecf20Sopenharmony_ci{
3518c2ecf20Sopenharmony_ci	int i;
3528c2ecf20Sopenharmony_ci	u32 mask, loop = HZ;
3538c2ecf20Sopenharmony_ci	u32 d32;
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci	/* Reset the Enable bits for Input Queues. */
3568c2ecf20Sopenharmony_ci	mask = octeon_read_csr(oct, CN6XXX_SLI_PKT_INSTR_ENB);
3578c2ecf20Sopenharmony_ci	mask ^= oct->io_qmask.iq;
3588c2ecf20Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_PKT_INSTR_ENB, mask);
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci	/* Wait until hardware indicates that the queues are out of reset. */
3618c2ecf20Sopenharmony_ci	mask = (u32)oct->io_qmask.iq;
3628c2ecf20Sopenharmony_ci	d32 = octeon_read_csr(oct, CN6XXX_SLI_PORT_IN_RST_IQ);
3638c2ecf20Sopenharmony_ci	while (((d32 & mask) != mask) && loop--) {
3648c2ecf20Sopenharmony_ci		d32 = octeon_read_csr(oct, CN6XXX_SLI_PORT_IN_RST_IQ);
3658c2ecf20Sopenharmony_ci		schedule_timeout_uninterruptible(1);
3668c2ecf20Sopenharmony_ci	}
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci	/* Reset the doorbell register for each Input queue. */
3698c2ecf20Sopenharmony_ci	for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) {
3708c2ecf20Sopenharmony_ci		if (!(oct->io_qmask.iq & BIT_ULL(i)))
3718c2ecf20Sopenharmony_ci			continue;
3728c2ecf20Sopenharmony_ci		octeon_write_csr(oct, CN6XXX_SLI_IQ_DOORBELL(i), 0xFFFFFFFF);
3738c2ecf20Sopenharmony_ci		d32 = octeon_read_csr(oct, CN6XXX_SLI_IQ_DOORBELL(i));
3748c2ecf20Sopenharmony_ci	}
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci	/* Reset the Enable bits for Output Queues. */
3778c2ecf20Sopenharmony_ci	mask = octeon_read_csr(oct, CN6XXX_SLI_PKT_OUT_ENB);
3788c2ecf20Sopenharmony_ci	mask ^= oct->io_qmask.oq;
3798c2ecf20Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_PKT_OUT_ENB, mask);
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci	/* Wait until hardware indicates that the queues are out of reset. */
3828c2ecf20Sopenharmony_ci	loop = HZ;
3838c2ecf20Sopenharmony_ci	mask = (u32)oct->io_qmask.oq;
3848c2ecf20Sopenharmony_ci	d32 = octeon_read_csr(oct, CN6XXX_SLI_PORT_IN_RST_OQ);
3858c2ecf20Sopenharmony_ci	while (((d32 & mask) != mask) && loop--) {
3868c2ecf20Sopenharmony_ci		d32 = octeon_read_csr(oct, CN6XXX_SLI_PORT_IN_RST_OQ);
3878c2ecf20Sopenharmony_ci		schedule_timeout_uninterruptible(1);
3888c2ecf20Sopenharmony_ci	}
3898c2ecf20Sopenharmony_ci	;
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci	/* Reset the doorbell register for each Output queue. */
3928c2ecf20Sopenharmony_ci	for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct); i++) {
3938c2ecf20Sopenharmony_ci		if (!(oct->io_qmask.oq & BIT_ULL(i)))
3948c2ecf20Sopenharmony_ci			continue;
3958c2ecf20Sopenharmony_ci		octeon_write_csr(oct, CN6XXX_SLI_OQ_PKTS_CREDIT(i), 0xFFFFFFFF);
3968c2ecf20Sopenharmony_ci		d32 = octeon_read_csr(oct, CN6XXX_SLI_OQ_PKTS_CREDIT(i));
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci		d32 = octeon_read_csr(oct, CN6XXX_SLI_OQ_PKTS_SENT(i));
3998c2ecf20Sopenharmony_ci		octeon_write_csr(oct, CN6XXX_SLI_OQ_PKTS_SENT(i), d32);
4008c2ecf20Sopenharmony_ci	}
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	d32 = octeon_read_csr(oct, CN6XXX_SLI_PKT_CNT_INT);
4038c2ecf20Sopenharmony_ci	if (d32)
4048c2ecf20Sopenharmony_ci		octeon_write_csr(oct, CN6XXX_SLI_PKT_CNT_INT, d32);
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci	d32 = octeon_read_csr(oct, CN6XXX_SLI_PKT_TIME_INT);
4078c2ecf20Sopenharmony_ci	if (d32)
4088c2ecf20Sopenharmony_ci		octeon_write_csr(oct, CN6XXX_SLI_PKT_TIME_INT, d32);
4098c2ecf20Sopenharmony_ci}
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_civoid
4128c2ecf20Sopenharmony_cilio_cn6xxx_bar1_idx_setup(struct octeon_device *oct,
4138c2ecf20Sopenharmony_ci			  u64 core_addr,
4148c2ecf20Sopenharmony_ci			  u32 idx,
4158c2ecf20Sopenharmony_ci			  int valid)
4168c2ecf20Sopenharmony_ci{
4178c2ecf20Sopenharmony_ci	u64 bar1;
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	if (valid == 0) {
4208c2ecf20Sopenharmony_ci		bar1 = lio_pci_readq(oct, CN6XXX_BAR1_REG(idx, oct->pcie_port));
4218c2ecf20Sopenharmony_ci		lio_pci_writeq(oct, (bar1 & 0xFFFFFFFEULL),
4228c2ecf20Sopenharmony_ci			       CN6XXX_BAR1_REG(idx, oct->pcie_port));
4238c2ecf20Sopenharmony_ci		bar1 = lio_pci_readq(oct, CN6XXX_BAR1_REG(idx, oct->pcie_port));
4248c2ecf20Sopenharmony_ci		return;
4258c2ecf20Sopenharmony_ci	}
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci	/* Bits 17:4 of the PCI_BAR1_INDEXx stores bits 35:22 of
4288c2ecf20Sopenharmony_ci	 * the Core Addr
4298c2ecf20Sopenharmony_ci	 */
4308c2ecf20Sopenharmony_ci	lio_pci_writeq(oct, (((core_addr >> 22) << 4) | PCI_BAR1_MASK),
4318c2ecf20Sopenharmony_ci		       CN6XXX_BAR1_REG(idx, oct->pcie_port));
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci	bar1 = lio_pci_readq(oct, CN6XXX_BAR1_REG(idx, oct->pcie_port));
4348c2ecf20Sopenharmony_ci}
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_civoid lio_cn6xxx_bar1_idx_write(struct octeon_device *oct,
4378c2ecf20Sopenharmony_ci			       u32 idx,
4388c2ecf20Sopenharmony_ci			       u32 mask)
4398c2ecf20Sopenharmony_ci{
4408c2ecf20Sopenharmony_ci	lio_pci_writeq(oct, mask, CN6XXX_BAR1_REG(idx, oct->pcie_port));
4418c2ecf20Sopenharmony_ci}
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ciu32 lio_cn6xxx_bar1_idx_read(struct octeon_device *oct, u32 idx)
4448c2ecf20Sopenharmony_ci{
4458c2ecf20Sopenharmony_ci	return (u32)lio_pci_readq(oct, CN6XXX_BAR1_REG(idx, oct->pcie_port));
4468c2ecf20Sopenharmony_ci}
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ciu32
4498c2ecf20Sopenharmony_cilio_cn6xxx_update_read_index(struct octeon_instr_queue *iq)
4508c2ecf20Sopenharmony_ci{
4518c2ecf20Sopenharmony_ci	u32 new_idx = readl(iq->inst_cnt_reg);
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	/* The new instr cnt reg is a 32-bit counter that can roll over. We have
4548c2ecf20Sopenharmony_ci	 * noted the counter's initial value at init time into
4558c2ecf20Sopenharmony_ci	 * reset_instr_cnt
4568c2ecf20Sopenharmony_ci	 */
4578c2ecf20Sopenharmony_ci	if (iq->reset_instr_cnt < new_idx)
4588c2ecf20Sopenharmony_ci		new_idx -= iq->reset_instr_cnt;
4598c2ecf20Sopenharmony_ci	else
4608c2ecf20Sopenharmony_ci		new_idx += (0xffffffff - iq->reset_instr_cnt) + 1;
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	/* Modulo of the new index with the IQ size will give us
4638c2ecf20Sopenharmony_ci	 * the new index.
4648c2ecf20Sopenharmony_ci	 */
4658c2ecf20Sopenharmony_ci	new_idx %= iq->max_count;
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci	return new_idx;
4688c2ecf20Sopenharmony_ci}
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_civoid lio_cn6xxx_enable_interrupt(struct octeon_device *oct,
4718c2ecf20Sopenharmony_ci				 u8 unused __attribute__((unused)))
4728c2ecf20Sopenharmony_ci{
4738c2ecf20Sopenharmony_ci	struct octeon_cn6xxx *cn6xxx = (struct octeon_cn6xxx *)oct->chip;
4748c2ecf20Sopenharmony_ci	u64 mask = cn6xxx->intr_mask64 | CN6XXX_INTR_DMA0_FORCE;
4758c2ecf20Sopenharmony_ci
4768c2ecf20Sopenharmony_ci	/* Enable Interrupt */
4778c2ecf20Sopenharmony_ci	writeq(mask, cn6xxx->intr_enb_reg64);
4788c2ecf20Sopenharmony_ci}
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_civoid lio_cn6xxx_disable_interrupt(struct octeon_device *oct,
4818c2ecf20Sopenharmony_ci				  u8 unused __attribute__((unused)))
4828c2ecf20Sopenharmony_ci{
4838c2ecf20Sopenharmony_ci	struct octeon_cn6xxx *cn6xxx = (struct octeon_cn6xxx *)oct->chip;
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ci	/* Disable Interrupts */
4868c2ecf20Sopenharmony_ci	writeq(0, cn6xxx->intr_enb_reg64);
4878c2ecf20Sopenharmony_ci}
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_cistatic void lio_cn6xxx_get_pcie_qlmport(struct octeon_device *oct)
4908c2ecf20Sopenharmony_ci{
4918c2ecf20Sopenharmony_ci	/* CN63xx Pass2 and newer parts implements the SLI_MAC_NUMBER register
4928c2ecf20Sopenharmony_ci	 * to determine the PCIE port #
4938c2ecf20Sopenharmony_ci	 */
4948c2ecf20Sopenharmony_ci	oct->pcie_port = octeon_read_csr(oct, CN6XXX_SLI_MAC_NUMBER) & 0xff;
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	dev_dbg(&oct->pci_dev->dev, "Using PCIE Port %d\n", oct->pcie_port);
4978c2ecf20Sopenharmony_ci}
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_cistatic void
5008c2ecf20Sopenharmony_cilio_cn6xxx_process_pcie_error_intr(struct octeon_device *oct, u64 intr64)
5018c2ecf20Sopenharmony_ci{
5028c2ecf20Sopenharmony_ci	dev_err(&oct->pci_dev->dev, "Error Intr: 0x%016llx\n",
5038c2ecf20Sopenharmony_ci		CVM_CAST64(intr64));
5048c2ecf20Sopenharmony_ci}
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_cistatic int lio_cn6xxx_process_droq_intr_regs(struct octeon_device *oct)
5078c2ecf20Sopenharmony_ci{
5088c2ecf20Sopenharmony_ci	struct octeon_droq *droq;
5098c2ecf20Sopenharmony_ci	int oq_no;
5108c2ecf20Sopenharmony_ci	u32 pkt_count, droq_time_mask, droq_mask, droq_int_enb;
5118c2ecf20Sopenharmony_ci	u32 droq_cnt_enb, droq_cnt_mask;
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_ci	droq_cnt_enb = octeon_read_csr(oct, CN6XXX_SLI_PKT_CNT_INT_ENB);
5148c2ecf20Sopenharmony_ci	droq_cnt_mask = octeon_read_csr(oct, CN6XXX_SLI_PKT_CNT_INT);
5158c2ecf20Sopenharmony_ci	droq_mask = droq_cnt_mask & droq_cnt_enb;
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci	droq_time_mask = octeon_read_csr(oct, CN6XXX_SLI_PKT_TIME_INT);
5188c2ecf20Sopenharmony_ci	droq_int_enb = octeon_read_csr(oct, CN6XXX_SLI_PKT_TIME_INT_ENB);
5198c2ecf20Sopenharmony_ci	droq_mask |= (droq_time_mask & droq_int_enb);
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci	droq_mask &= oct->io_qmask.oq;
5228c2ecf20Sopenharmony_ci
5238c2ecf20Sopenharmony_ci	oct->droq_intr = 0;
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci	for (oq_no = 0; oq_no < MAX_OCTEON_OUTPUT_QUEUES(oct); oq_no++) {
5268c2ecf20Sopenharmony_ci		if (!(droq_mask & BIT_ULL(oq_no)))
5278c2ecf20Sopenharmony_ci			continue;
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci		droq = oct->droq[oq_no];
5308c2ecf20Sopenharmony_ci		pkt_count = octeon_droq_check_hw_for_pkts(droq);
5318c2ecf20Sopenharmony_ci		if (pkt_count) {
5328c2ecf20Sopenharmony_ci			oct->droq_intr |= BIT_ULL(oq_no);
5338c2ecf20Sopenharmony_ci			if (droq->ops.poll_mode) {
5348c2ecf20Sopenharmony_ci				u32 value;
5358c2ecf20Sopenharmony_ci				u32 reg;
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci				struct octeon_cn6xxx *cn6xxx =
5388c2ecf20Sopenharmony_ci					(struct octeon_cn6xxx *)oct->chip;
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci				/* disable interrupts for this droq */
5418c2ecf20Sopenharmony_ci				spin_lock
5428c2ecf20Sopenharmony_ci					(&cn6xxx->lock_for_droq_int_enb_reg);
5438c2ecf20Sopenharmony_ci				reg = CN6XXX_SLI_PKT_TIME_INT_ENB;
5448c2ecf20Sopenharmony_ci				value = octeon_read_csr(oct, reg);
5458c2ecf20Sopenharmony_ci				value &= ~(1 << oq_no);
5468c2ecf20Sopenharmony_ci				octeon_write_csr(oct, reg, value);
5478c2ecf20Sopenharmony_ci				reg = CN6XXX_SLI_PKT_CNT_INT_ENB;
5488c2ecf20Sopenharmony_ci				value = octeon_read_csr(oct, reg);
5498c2ecf20Sopenharmony_ci				value &= ~(1 << oq_no);
5508c2ecf20Sopenharmony_ci				octeon_write_csr(oct, reg, value);
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci				spin_unlock(&cn6xxx->lock_for_droq_int_enb_reg);
5538c2ecf20Sopenharmony_ci			}
5548c2ecf20Sopenharmony_ci		}
5558c2ecf20Sopenharmony_ci	}
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	droq_time_mask &= oct->io_qmask.oq;
5588c2ecf20Sopenharmony_ci	droq_cnt_mask &= oct->io_qmask.oq;
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_ci	/* Reset the PKT_CNT/TIME_INT registers. */
5618c2ecf20Sopenharmony_ci	if (droq_time_mask)
5628c2ecf20Sopenharmony_ci		octeon_write_csr(oct, CN6XXX_SLI_PKT_TIME_INT, droq_time_mask);
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci	if (droq_cnt_mask)      /* reset PKT_CNT register:66xx */
5658c2ecf20Sopenharmony_ci		octeon_write_csr(oct, CN6XXX_SLI_PKT_CNT_INT, droq_cnt_mask);
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_ci	return 0;
5688c2ecf20Sopenharmony_ci}
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ciirqreturn_t lio_cn6xxx_process_interrupt_regs(void *dev)
5718c2ecf20Sopenharmony_ci{
5728c2ecf20Sopenharmony_ci	struct octeon_device *oct = (struct octeon_device *)dev;
5738c2ecf20Sopenharmony_ci	struct octeon_cn6xxx *cn6xxx = (struct octeon_cn6xxx *)oct->chip;
5748c2ecf20Sopenharmony_ci	u64 intr64;
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_ci	intr64 = readq(cn6xxx->intr_sum_reg64);
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_ci	/* If our device has interrupted, then proceed.
5798c2ecf20Sopenharmony_ci	 * Also check for all f's if interrupt was triggered on an error
5808c2ecf20Sopenharmony_ci	 * and the PCI read fails.
5818c2ecf20Sopenharmony_ci	 */
5828c2ecf20Sopenharmony_ci	if (!intr64 || (intr64 == 0xFFFFFFFFFFFFFFFFULL))
5838c2ecf20Sopenharmony_ci		return IRQ_NONE;
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ci	oct->int_status = 0;
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_ci	if (intr64 & CN6XXX_INTR_ERR)
5888c2ecf20Sopenharmony_ci		lio_cn6xxx_process_pcie_error_intr(oct, intr64);
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	if (intr64 & CN6XXX_INTR_PKT_DATA) {
5918c2ecf20Sopenharmony_ci		lio_cn6xxx_process_droq_intr_regs(oct);
5928c2ecf20Sopenharmony_ci		oct->int_status |= OCT_DEV_INTR_PKT_DATA;
5938c2ecf20Sopenharmony_ci	}
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	if (intr64 & CN6XXX_INTR_DMA0_FORCE)
5968c2ecf20Sopenharmony_ci		oct->int_status |= OCT_DEV_INTR_DMA0_FORCE;
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci	if (intr64 & CN6XXX_INTR_DMA1_FORCE)
5998c2ecf20Sopenharmony_ci		oct->int_status |= OCT_DEV_INTR_DMA1_FORCE;
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_ci	/* Clear the current interrupts */
6028c2ecf20Sopenharmony_ci	writeq(intr64, cn6xxx->intr_sum_reg64);
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
6058c2ecf20Sopenharmony_ci}
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_civoid lio_cn6xxx_setup_reg_address(struct octeon_device *oct,
6088c2ecf20Sopenharmony_ci				  void *chip,
6098c2ecf20Sopenharmony_ci				  struct octeon_reg_list *reg_list)
6108c2ecf20Sopenharmony_ci{
6118c2ecf20Sopenharmony_ci	u8 __iomem *bar0_pciaddr = oct->mmio[0].hw_addr;
6128c2ecf20Sopenharmony_ci	struct octeon_cn6xxx *cn6xxx = (struct octeon_cn6xxx *)chip;
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci	reg_list->pci_win_wr_addr_hi =
6158c2ecf20Sopenharmony_ci		(u32 __iomem *)(bar0_pciaddr + CN6XXX_WIN_WR_ADDR_HI);
6168c2ecf20Sopenharmony_ci	reg_list->pci_win_wr_addr_lo =
6178c2ecf20Sopenharmony_ci		(u32 __iomem *)(bar0_pciaddr + CN6XXX_WIN_WR_ADDR_LO);
6188c2ecf20Sopenharmony_ci	reg_list->pci_win_wr_addr =
6198c2ecf20Sopenharmony_ci		(u64 __iomem *)(bar0_pciaddr + CN6XXX_WIN_WR_ADDR64);
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci	reg_list->pci_win_rd_addr_hi =
6228c2ecf20Sopenharmony_ci		(u32 __iomem *)(bar0_pciaddr + CN6XXX_WIN_RD_ADDR_HI);
6238c2ecf20Sopenharmony_ci	reg_list->pci_win_rd_addr_lo =
6248c2ecf20Sopenharmony_ci		(u32 __iomem *)(bar0_pciaddr + CN6XXX_WIN_RD_ADDR_LO);
6258c2ecf20Sopenharmony_ci	reg_list->pci_win_rd_addr =
6268c2ecf20Sopenharmony_ci		(u64 __iomem *)(bar0_pciaddr + CN6XXX_WIN_RD_ADDR64);
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci	reg_list->pci_win_wr_data_hi =
6298c2ecf20Sopenharmony_ci		(u32 __iomem *)(bar0_pciaddr + CN6XXX_WIN_WR_DATA_HI);
6308c2ecf20Sopenharmony_ci	reg_list->pci_win_wr_data_lo =
6318c2ecf20Sopenharmony_ci		(u32 __iomem *)(bar0_pciaddr + CN6XXX_WIN_WR_DATA_LO);
6328c2ecf20Sopenharmony_ci	reg_list->pci_win_wr_data =
6338c2ecf20Sopenharmony_ci		(u64 __iomem *)(bar0_pciaddr + CN6XXX_WIN_WR_DATA64);
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ci	reg_list->pci_win_rd_data_hi =
6368c2ecf20Sopenharmony_ci		(u32 __iomem *)(bar0_pciaddr + CN6XXX_WIN_RD_DATA_HI);
6378c2ecf20Sopenharmony_ci	reg_list->pci_win_rd_data_lo =
6388c2ecf20Sopenharmony_ci		(u32 __iomem *)(bar0_pciaddr + CN6XXX_WIN_RD_DATA_LO);
6398c2ecf20Sopenharmony_ci	reg_list->pci_win_rd_data =
6408c2ecf20Sopenharmony_ci		(u64 __iomem *)(bar0_pciaddr + CN6XXX_WIN_RD_DATA64);
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_ci	lio_cn6xxx_get_pcie_qlmport(oct);
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_ci	cn6xxx->intr_sum_reg64 = bar0_pciaddr + CN6XXX_SLI_INT_SUM64;
6458c2ecf20Sopenharmony_ci	cn6xxx->intr_mask64 = CN6XXX_INTR_MASK;
6468c2ecf20Sopenharmony_ci	cn6xxx->intr_enb_reg64 =
6478c2ecf20Sopenharmony_ci		bar0_pciaddr + CN6XXX_SLI_INT_ENB64(oct->pcie_port);
6488c2ecf20Sopenharmony_ci}
6498c2ecf20Sopenharmony_ci
6508c2ecf20Sopenharmony_ciint lio_setup_cn66xx_octeon_device(struct octeon_device *oct)
6518c2ecf20Sopenharmony_ci{
6528c2ecf20Sopenharmony_ci	struct octeon_cn6xxx *cn6xxx = (struct octeon_cn6xxx *)oct->chip;
6538c2ecf20Sopenharmony_ci
6548c2ecf20Sopenharmony_ci	if (octeon_map_pci_barx(oct, 0, 0))
6558c2ecf20Sopenharmony_ci		return 1;
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_ci	if (octeon_map_pci_barx(oct, 1, MAX_BAR1_IOREMAP_SIZE)) {
6588c2ecf20Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "%s CN66XX BAR1 map failed\n",
6598c2ecf20Sopenharmony_ci			__func__);
6608c2ecf20Sopenharmony_ci		octeon_unmap_pci_barx(oct, 0);
6618c2ecf20Sopenharmony_ci		return 1;
6628c2ecf20Sopenharmony_ci	}
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_ci	spin_lock_init(&cn6xxx->lock_for_droq_int_enb_reg);
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci	oct->fn_list.setup_iq_regs = lio_cn66xx_setup_iq_regs;
6678c2ecf20Sopenharmony_ci	oct->fn_list.setup_oq_regs = lio_cn6xxx_setup_oq_regs;
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci	oct->fn_list.soft_reset = lio_cn6xxx_soft_reset;
6708c2ecf20Sopenharmony_ci	oct->fn_list.setup_device_regs = lio_cn6xxx_setup_device_regs;
6718c2ecf20Sopenharmony_ci	oct->fn_list.update_iq_read_idx = lio_cn6xxx_update_read_index;
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_ci	oct->fn_list.bar1_idx_setup = lio_cn6xxx_bar1_idx_setup;
6748c2ecf20Sopenharmony_ci	oct->fn_list.bar1_idx_write = lio_cn6xxx_bar1_idx_write;
6758c2ecf20Sopenharmony_ci	oct->fn_list.bar1_idx_read = lio_cn6xxx_bar1_idx_read;
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_ci	oct->fn_list.process_interrupt_regs = lio_cn6xxx_process_interrupt_regs;
6788c2ecf20Sopenharmony_ci	oct->fn_list.enable_interrupt = lio_cn6xxx_enable_interrupt;
6798c2ecf20Sopenharmony_ci	oct->fn_list.disable_interrupt = lio_cn6xxx_disable_interrupt;
6808c2ecf20Sopenharmony_ci
6818c2ecf20Sopenharmony_ci	oct->fn_list.enable_io_queues = lio_cn6xxx_enable_io_queues;
6828c2ecf20Sopenharmony_ci	oct->fn_list.disable_io_queues = lio_cn6xxx_disable_io_queues;
6838c2ecf20Sopenharmony_ci
6848c2ecf20Sopenharmony_ci	lio_cn6xxx_setup_reg_address(oct, oct->chip, &oct->reg_list);
6858c2ecf20Sopenharmony_ci
6868c2ecf20Sopenharmony_ci	cn6xxx->conf = (struct octeon_config *)
6878c2ecf20Sopenharmony_ci		       oct_get_config_info(oct, LIO_210SV);
6888c2ecf20Sopenharmony_ci	if (!cn6xxx->conf) {
6898c2ecf20Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "%s No Config found for CN66XX\n",
6908c2ecf20Sopenharmony_ci			__func__);
6918c2ecf20Sopenharmony_ci		octeon_unmap_pci_barx(oct, 0);
6928c2ecf20Sopenharmony_ci		octeon_unmap_pci_barx(oct, 1);
6938c2ecf20Sopenharmony_ci		return 1;
6948c2ecf20Sopenharmony_ci	}
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_ci	oct->coproc_clock_rate = 1000000ULL * lio_cn6xxx_coprocessor_clock(oct);
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_ci	return 0;
6998c2ecf20Sopenharmony_ci}
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_ciint lio_validate_cn6xxx_config_info(struct octeon_device *oct,
7028c2ecf20Sopenharmony_ci				    struct octeon_config *conf6xxx)
7038c2ecf20Sopenharmony_ci{
7048c2ecf20Sopenharmony_ci	if (CFG_GET_IQ_MAX_Q(conf6xxx) > CN6XXX_MAX_INPUT_QUEUES) {
7058c2ecf20Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "%s: Num IQ (%d) exceeds Max (%d)\n",
7068c2ecf20Sopenharmony_ci			__func__, CFG_GET_IQ_MAX_Q(conf6xxx),
7078c2ecf20Sopenharmony_ci			CN6XXX_MAX_INPUT_QUEUES);
7088c2ecf20Sopenharmony_ci		return 1;
7098c2ecf20Sopenharmony_ci	}
7108c2ecf20Sopenharmony_ci
7118c2ecf20Sopenharmony_ci	if (CFG_GET_OQ_MAX_Q(conf6xxx) > CN6XXX_MAX_OUTPUT_QUEUES) {
7128c2ecf20Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "%s: Num OQ (%d) exceeds Max (%d)\n",
7138c2ecf20Sopenharmony_ci			__func__, CFG_GET_OQ_MAX_Q(conf6xxx),
7148c2ecf20Sopenharmony_ci			CN6XXX_MAX_OUTPUT_QUEUES);
7158c2ecf20Sopenharmony_ci		return 1;
7168c2ecf20Sopenharmony_ci	}
7178c2ecf20Sopenharmony_ci
7188c2ecf20Sopenharmony_ci	if (CFG_GET_IQ_INSTR_TYPE(conf6xxx) != OCTEON_32BYTE_INSTR &&
7198c2ecf20Sopenharmony_ci	    CFG_GET_IQ_INSTR_TYPE(conf6xxx) != OCTEON_64BYTE_INSTR) {
7208c2ecf20Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "%s: Invalid instr type for IQ\n",
7218c2ecf20Sopenharmony_ci			__func__);
7228c2ecf20Sopenharmony_ci		return 1;
7238c2ecf20Sopenharmony_ci	}
7248c2ecf20Sopenharmony_ci	if (!CFG_GET_OQ_REFILL_THRESHOLD(conf6xxx)) {
7258c2ecf20Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "%s: Invalid parameter for OQ\n",
7268c2ecf20Sopenharmony_ci			__func__);
7278c2ecf20Sopenharmony_ci		return 1;
7288c2ecf20Sopenharmony_ci	}
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_ci	if (!(CFG_GET_OQ_INTR_TIME(conf6xxx))) {
7318c2ecf20Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "%s: No Time Interrupt for OQ\n",
7328c2ecf20Sopenharmony_ci			__func__);
7338c2ecf20Sopenharmony_ci		return 1;
7348c2ecf20Sopenharmony_ci	}
7358c2ecf20Sopenharmony_ci
7368c2ecf20Sopenharmony_ci	return 0;
7378c2ecf20Sopenharmony_ci}
738