162306a36Sopenharmony_ci/**********************************************************************
262306a36Sopenharmony_ci * Author: Cavium, Inc.
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Contact: support@cavium.com
562306a36Sopenharmony_ci *          Please include "LiquidIO" in the subject.
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Copyright (c) 2003-2016 Cavium, Inc.
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * This file is free software; you can redistribute it and/or modify
1062306a36Sopenharmony_ci * it under the terms of the GNU General Public License, Version 2, as
1162306a36Sopenharmony_ci * published by the Free Software Foundation.
1262306a36Sopenharmony_ci *
1362306a36Sopenharmony_ci * This file is distributed in the hope that it will be useful, but
1462306a36Sopenharmony_ci * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
1562306a36Sopenharmony_ci * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
1662306a36Sopenharmony_ci * NONINFRINGEMENT.  See the GNU General Public License for more details.
1762306a36Sopenharmony_ci ***********************************************************************/
1862306a36Sopenharmony_ci#include <linux/pci.h>
1962306a36Sopenharmony_ci#include <linux/netdevice.h>
2062306a36Sopenharmony_ci#include "liquidio_common.h"
2162306a36Sopenharmony_ci#include "octeon_droq.h"
2262306a36Sopenharmony_ci#include "octeon_iq.h"
2362306a36Sopenharmony_ci#include "response_manager.h"
2462306a36Sopenharmony_ci#include "octeon_device.h"
2562306a36Sopenharmony_ci#include "octeon_main.h"
2662306a36Sopenharmony_ci#include "cn66xx_regs.h"
2762306a36Sopenharmony_ci#include "cn66xx_device.h"
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ciint lio_cn6xxx_soft_reset(struct octeon_device *oct)
3062306a36Sopenharmony_ci{
3162306a36Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_WIN_WR_MASK_REG, 0xFF);
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	dev_dbg(&oct->pci_dev->dev, "BIST enabled for soft reset\n");
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	lio_pci_writeq(oct, 1, CN6XXX_CIU_SOFT_BIST);
3662306a36Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_SLI_SCRATCH1, 0x1234ULL);
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	lio_pci_readq(oct, CN6XXX_CIU_SOFT_RST);
3962306a36Sopenharmony_ci	lio_pci_writeq(oct, 1, CN6XXX_CIU_SOFT_RST);
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	/* Wait for 10ms as Octeon resets. */
4262306a36Sopenharmony_ci	mdelay(100);
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	if (octeon_read_csr64(oct, CN6XXX_SLI_SCRATCH1)) {
4562306a36Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "Soft reset failed\n");
4662306a36Sopenharmony_ci		return 1;
4762306a36Sopenharmony_ci	}
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	dev_dbg(&oct->pci_dev->dev, "Reset completed\n");
5062306a36Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_WIN_WR_MASK_REG, 0xFF);
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	return 0;
5362306a36Sopenharmony_ci}
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_civoid lio_cn6xxx_enable_error_reporting(struct octeon_device *oct)
5662306a36Sopenharmony_ci{
5762306a36Sopenharmony_ci	u32 val;
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	pci_read_config_dword(oct->pci_dev, CN6XXX_PCIE_DEVCTL, &val);
6062306a36Sopenharmony_ci	if (val & 0x000c0000) {
6162306a36Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "PCI-E Link error detected: 0x%08x\n",
6262306a36Sopenharmony_ci			val & 0x000c0000);
6362306a36Sopenharmony_ci	}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	val |= 0xf;          /* Enable Link error reporting */
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	dev_dbg(&oct->pci_dev->dev, "Enabling PCI-E error reporting..\n");
6862306a36Sopenharmony_ci	pci_write_config_dword(oct->pci_dev, CN6XXX_PCIE_DEVCTL, val);
6962306a36Sopenharmony_ci}
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_civoid lio_cn6xxx_setup_pcie_mps(struct octeon_device *oct,
7262306a36Sopenharmony_ci			       enum octeon_pcie_mps mps)
7362306a36Sopenharmony_ci{
7462306a36Sopenharmony_ci	u32 val;
7562306a36Sopenharmony_ci	u64 r64;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	/* Read config register for MPS */
7862306a36Sopenharmony_ci	pci_read_config_dword(oct->pci_dev, CN6XXX_PCIE_DEVCTL, &val);
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	if (mps == PCIE_MPS_DEFAULT) {
8162306a36Sopenharmony_ci		mps = ((val & (0x7 << 5)) >> 5);
8262306a36Sopenharmony_ci	} else {
8362306a36Sopenharmony_ci		val &= ~(0x7 << 5);  /* Turn off any MPS bits */
8462306a36Sopenharmony_ci		val |= (mps << 5);   /* Set MPS */
8562306a36Sopenharmony_ci		pci_write_config_dword(oct->pci_dev, CN6XXX_PCIE_DEVCTL, val);
8662306a36Sopenharmony_ci	}
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	/* Set MPS in DPI_SLI_PRT0_CFG to the same value. */
8962306a36Sopenharmony_ci	r64 = lio_pci_readq(oct, CN6XXX_DPI_SLI_PRTX_CFG(oct->pcie_port));
9062306a36Sopenharmony_ci	r64 |= (mps << 4);
9162306a36Sopenharmony_ci	lio_pci_writeq(oct, r64, CN6XXX_DPI_SLI_PRTX_CFG(oct->pcie_port));
9262306a36Sopenharmony_ci}
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_civoid lio_cn6xxx_setup_pcie_mrrs(struct octeon_device *oct,
9562306a36Sopenharmony_ci				enum octeon_pcie_mrrs mrrs)
9662306a36Sopenharmony_ci{
9762306a36Sopenharmony_ci	u32 val;
9862306a36Sopenharmony_ci	u64 r64;
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	/* Read config register for MRRS */
10162306a36Sopenharmony_ci	pci_read_config_dword(oct->pci_dev, CN6XXX_PCIE_DEVCTL, &val);
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	if (mrrs == PCIE_MRRS_DEFAULT) {
10462306a36Sopenharmony_ci		mrrs = ((val & (0x7 << 12)) >> 12);
10562306a36Sopenharmony_ci	} else {
10662306a36Sopenharmony_ci		val &= ~(0x7 << 12); /* Turn off any MRRS bits */
10762306a36Sopenharmony_ci		val |= (mrrs << 12); /* Set MRRS */
10862306a36Sopenharmony_ci		pci_write_config_dword(oct->pci_dev, CN6XXX_PCIE_DEVCTL, val);
10962306a36Sopenharmony_ci	}
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	/* Set MRRS in SLI_S2M_PORT0_CTL to the same value. */
11262306a36Sopenharmony_ci	r64 = octeon_read_csr64(oct, CN6XXX_SLI_S2M_PORTX_CTL(oct->pcie_port));
11362306a36Sopenharmony_ci	r64 |= mrrs;
11462306a36Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_SLI_S2M_PORTX_CTL(oct->pcie_port), r64);
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	/* Set MRRS in DPI_SLI_PRT0_CFG to the same value. */
11762306a36Sopenharmony_ci	r64 = lio_pci_readq(oct, CN6XXX_DPI_SLI_PRTX_CFG(oct->pcie_port));
11862306a36Sopenharmony_ci	r64 |= mrrs;
11962306a36Sopenharmony_ci	lio_pci_writeq(oct, r64, CN6XXX_DPI_SLI_PRTX_CFG(oct->pcie_port));
12062306a36Sopenharmony_ci}
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ciu32 lio_cn6xxx_coprocessor_clock(struct octeon_device *oct)
12362306a36Sopenharmony_ci{
12462306a36Sopenharmony_ci	/* Bits 29:24 of MIO_RST_BOOT holds the ref. clock multiplier
12562306a36Sopenharmony_ci	 * for SLI.
12662306a36Sopenharmony_ci	 */
12762306a36Sopenharmony_ci	return ((lio_pci_readq(oct, CN6XXX_MIO_RST_BOOT) >> 24) & 0x3f) * 50;
12862306a36Sopenharmony_ci}
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ciu32 lio_cn6xxx_get_oq_ticks(struct octeon_device *oct,
13162306a36Sopenharmony_ci			    u32 time_intr_in_us)
13262306a36Sopenharmony_ci{
13362306a36Sopenharmony_ci	/* This gives the SLI clock per microsec */
13462306a36Sopenharmony_ci	u32 oqticks_per_us = lio_cn6xxx_coprocessor_clock(oct);
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci	/* core clock per us / oq ticks will be fractional. TO avoid that
13762306a36Sopenharmony_ci	 * we use the method below.
13862306a36Sopenharmony_ci	 */
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci	/* This gives the clock cycles per millisecond */
14162306a36Sopenharmony_ci	oqticks_per_us *= 1000;
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	/* This gives the oq ticks (1024 core clock cycles) per millisecond */
14462306a36Sopenharmony_ci	oqticks_per_us /= 1024;
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	/* time_intr is in microseconds. The next 2 steps gives the oq ticks
14762306a36Sopenharmony_ci	 * corressponding to time_intr.
14862306a36Sopenharmony_ci	 */
14962306a36Sopenharmony_ci	oqticks_per_us *= time_intr_in_us;
15062306a36Sopenharmony_ci	oqticks_per_us /= 1000;
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	return oqticks_per_us;
15362306a36Sopenharmony_ci}
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_civoid lio_cn6xxx_setup_global_input_regs(struct octeon_device *oct)
15662306a36Sopenharmony_ci{
15762306a36Sopenharmony_ci	/* Select Round-Robin Arb, ES, RO, NS for Input Queues */
15862306a36Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_PKT_INPUT_CONTROL,
15962306a36Sopenharmony_ci			 CN6XXX_INPUT_CTL_MASK);
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	/* Instruction Read Size - Max 4 instructions per PCIE Read */
16262306a36Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_SLI_PKT_INSTR_RD_SIZE,
16362306a36Sopenharmony_ci			   0xFFFFFFFFFFFFFFFFULL);
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	/* Select PCIE Port for all Input rings. */
16662306a36Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_SLI_IN_PCIE_PORT,
16762306a36Sopenharmony_ci			   (oct->pcie_port * 0x5555555555555555ULL));
16862306a36Sopenharmony_ci}
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_cistatic void lio_cn66xx_setup_pkt_ctl_regs(struct octeon_device *oct)
17162306a36Sopenharmony_ci{
17262306a36Sopenharmony_ci	u64 pktctl;
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	struct octeon_cn6xxx *cn6xxx = (struct octeon_cn6xxx *)oct->chip;
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	pktctl = octeon_read_csr64(oct, CN6XXX_SLI_PKT_CTL);
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci	/* 66XX SPECIFIC */
17962306a36Sopenharmony_ci	if (CFG_GET_OQ_MAX_Q(cn6xxx->conf) <= 4)
18062306a36Sopenharmony_ci		/* Disable RING_EN if only upto 4 rings are used. */
18162306a36Sopenharmony_ci		pktctl &= ~(1 << 4);
18262306a36Sopenharmony_ci	else
18362306a36Sopenharmony_ci		pktctl |= (1 << 4);
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	if (CFG_GET_IS_SLI_BP_ON(cn6xxx->conf))
18662306a36Sopenharmony_ci		pktctl |= 0xF;
18762306a36Sopenharmony_ci	else
18862306a36Sopenharmony_ci		/* Disable per-port backpressure. */
18962306a36Sopenharmony_ci		pktctl &= ~0xF;
19062306a36Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_SLI_PKT_CTL, pktctl);
19162306a36Sopenharmony_ci}
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_civoid lio_cn6xxx_setup_global_output_regs(struct octeon_device *oct)
19462306a36Sopenharmony_ci{
19562306a36Sopenharmony_ci	u32 time_threshold;
19662306a36Sopenharmony_ci	struct octeon_cn6xxx *cn6xxx = (struct octeon_cn6xxx *)oct->chip;
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	/* / Select PCI-E Port for all Output queues */
19962306a36Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_SLI_PKT_PCIE_PORT64,
20062306a36Sopenharmony_ci			   (oct->pcie_port * 0x5555555555555555ULL));
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	if (CFG_GET_IS_SLI_BP_ON(cn6xxx->conf)) {
20362306a36Sopenharmony_ci		octeon_write_csr64(oct, CN6XXX_SLI_OQ_WMARK, 32);
20462306a36Sopenharmony_ci	} else {
20562306a36Sopenharmony_ci		/* / Set Output queue watermark to 0 to disable backpressure */
20662306a36Sopenharmony_ci		octeon_write_csr64(oct, CN6XXX_SLI_OQ_WMARK, 0);
20762306a36Sopenharmony_ci	}
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	/* / Select Packet count instead of bytes for SLI_PKTi_CNTS[CNT] */
21062306a36Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_PKT_OUT_BMODE, 0);
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	/* Select ES, RO, NS setting from register for Output Queue Packet
21362306a36Sopenharmony_ci	 * Address
21462306a36Sopenharmony_ci	 */
21562306a36Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_PKT_DPADDR, 0xFFFFFFFF);
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	/* No Relaxed Ordering, No Snoop, 64-bit swap for Output
21862306a36Sopenharmony_ci	 * Queue ScatterList
21962306a36Sopenharmony_ci	 */
22062306a36Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_PKT_SLIST_ROR, 0);
22162306a36Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_PKT_SLIST_NS, 0);
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci	/* / ENDIAN_SPECIFIC CHANGES - 0 works for LE. */
22462306a36Sopenharmony_ci#ifdef __BIG_ENDIAN_BITFIELD
22562306a36Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_SLI_PKT_SLIST_ES64,
22662306a36Sopenharmony_ci			   0x5555555555555555ULL);
22762306a36Sopenharmony_ci#else
22862306a36Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_SLI_PKT_SLIST_ES64, 0ULL);
22962306a36Sopenharmony_ci#endif
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	/* / No Relaxed Ordering, No Snoop, 64-bit swap for Output Queue Data */
23262306a36Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_PKT_DATA_OUT_ROR, 0);
23362306a36Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_PKT_DATA_OUT_NS, 0);
23462306a36Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_SLI_PKT_DATA_OUT_ES64,
23562306a36Sopenharmony_ci			   0x5555555555555555ULL);
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	/* / Set up interrupt packet and time threshold */
23862306a36Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_OQ_INT_LEVEL_PKTS,
23962306a36Sopenharmony_ci			 (u32)CFG_GET_OQ_INTR_PKT(cn6xxx->conf));
24062306a36Sopenharmony_ci	time_threshold =
24162306a36Sopenharmony_ci		lio_cn6xxx_get_oq_ticks(oct, (u32)
24262306a36Sopenharmony_ci					CFG_GET_OQ_INTR_TIME(cn6xxx->conf));
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_OQ_INT_LEVEL_TIME, time_threshold);
24562306a36Sopenharmony_ci}
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_cistatic int lio_cn6xxx_setup_device_regs(struct octeon_device *oct)
24862306a36Sopenharmony_ci{
24962306a36Sopenharmony_ci	lio_cn6xxx_setup_pcie_mps(oct, PCIE_MPS_DEFAULT);
25062306a36Sopenharmony_ci	lio_cn6xxx_setup_pcie_mrrs(oct, PCIE_MRRS_512B);
25162306a36Sopenharmony_ci	lio_cn6xxx_enable_error_reporting(oct);
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci	lio_cn6xxx_setup_global_input_regs(oct);
25462306a36Sopenharmony_ci	lio_cn66xx_setup_pkt_ctl_regs(oct);
25562306a36Sopenharmony_ci	lio_cn6xxx_setup_global_output_regs(oct);
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	/* Default error timeout value should be 0x200000 to avoid host hang
25862306a36Sopenharmony_ci	 * when reads invalid register
25962306a36Sopenharmony_ci	 */
26062306a36Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_SLI_WINDOW_CTL, 0x200000ULL);
26162306a36Sopenharmony_ci	return 0;
26262306a36Sopenharmony_ci}
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_civoid lio_cn6xxx_setup_iq_regs(struct octeon_device *oct, u32 iq_no)
26562306a36Sopenharmony_ci{
26662306a36Sopenharmony_ci	struct octeon_instr_queue *iq = oct->instr_queue[iq_no];
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_SLI_IQ_PKT_INSTR_HDR64(iq_no), 0);
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	/* Write the start of the input queue's ring and its size  */
27162306a36Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_SLI_IQ_BASE_ADDR64(iq_no),
27262306a36Sopenharmony_ci			   iq->base_addr_dma);
27362306a36Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_IQ_SIZE(iq_no), iq->max_count);
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci	/* Remember the doorbell & instruction count register addr for this
27662306a36Sopenharmony_ci	 * queue
27762306a36Sopenharmony_ci	 */
27862306a36Sopenharmony_ci	iq->doorbell_reg = oct->mmio[0].hw_addr + CN6XXX_SLI_IQ_DOORBELL(iq_no);
27962306a36Sopenharmony_ci	iq->inst_cnt_reg = oct->mmio[0].hw_addr
28062306a36Sopenharmony_ci			   + CN6XXX_SLI_IQ_INSTR_COUNT(iq_no);
28162306a36Sopenharmony_ci	dev_dbg(&oct->pci_dev->dev, "InstQ[%d]:dbell reg @ 0x%p instcnt_reg @ 0x%p\n",
28262306a36Sopenharmony_ci		iq_no, iq->doorbell_reg, iq->inst_cnt_reg);
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	/* Store the current instruction counter
28562306a36Sopenharmony_ci	 * (used in flush_iq calculation)
28662306a36Sopenharmony_ci	 */
28762306a36Sopenharmony_ci	iq->reset_instr_cnt = readl(iq->inst_cnt_reg);
28862306a36Sopenharmony_ci}
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_cistatic void lio_cn66xx_setup_iq_regs(struct octeon_device *oct, u32 iq_no)
29162306a36Sopenharmony_ci{
29262306a36Sopenharmony_ci	lio_cn6xxx_setup_iq_regs(oct, iq_no);
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	/* Backpressure for this queue - WMARK set to all F's. This effectively
29562306a36Sopenharmony_ci	 * disables the backpressure mechanism.
29662306a36Sopenharmony_ci	 */
29762306a36Sopenharmony_ci	octeon_write_csr64(oct, CN66XX_SLI_IQ_BP64(iq_no),
29862306a36Sopenharmony_ci			   (0xFFFFFFFFULL << 32));
29962306a36Sopenharmony_ci}
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_civoid lio_cn6xxx_setup_oq_regs(struct octeon_device *oct, u32 oq_no)
30262306a36Sopenharmony_ci{
30362306a36Sopenharmony_ci	u32 intr;
30462306a36Sopenharmony_ci	struct octeon_droq *droq = oct->droq[oq_no];
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	octeon_write_csr64(oct, CN6XXX_SLI_OQ_BASE_ADDR64(oq_no),
30762306a36Sopenharmony_ci			   droq->desc_ring_dma);
30862306a36Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_OQ_SIZE(oq_no), droq->max_count);
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_OQ_BUFF_INFO_SIZE(oq_no),
31162306a36Sopenharmony_ci			 droq->buffer_size);
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	/* Get the mapped address of the pkt_sent and pkts_credit regs */
31462306a36Sopenharmony_ci	droq->pkts_sent_reg =
31562306a36Sopenharmony_ci		oct->mmio[0].hw_addr + CN6XXX_SLI_OQ_PKTS_SENT(oq_no);
31662306a36Sopenharmony_ci	droq->pkts_credit_reg =
31762306a36Sopenharmony_ci		oct->mmio[0].hw_addr + CN6XXX_SLI_OQ_PKTS_CREDIT(oq_no);
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci	/* Enable this output queue to generate Packet Timer Interrupt */
32062306a36Sopenharmony_ci	intr = octeon_read_csr(oct, CN6XXX_SLI_PKT_TIME_INT_ENB);
32162306a36Sopenharmony_ci	intr |= (1 << oq_no);
32262306a36Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_PKT_TIME_INT_ENB, intr);
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	/* Enable this output queue to generate Packet Timer Interrupt */
32562306a36Sopenharmony_ci	intr = octeon_read_csr(oct, CN6XXX_SLI_PKT_CNT_INT_ENB);
32662306a36Sopenharmony_ci	intr |= (1 << oq_no);
32762306a36Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_PKT_CNT_INT_ENB, intr);
32862306a36Sopenharmony_ci}
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ciint lio_cn6xxx_enable_io_queues(struct octeon_device *oct)
33162306a36Sopenharmony_ci{
33262306a36Sopenharmony_ci	u32 mask;
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	mask = octeon_read_csr(oct, CN6XXX_SLI_PKT_INSTR_SIZE);
33562306a36Sopenharmony_ci	mask |= oct->io_qmask.iq64B;
33662306a36Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_PKT_INSTR_SIZE, mask);
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci	mask = octeon_read_csr(oct, CN6XXX_SLI_PKT_INSTR_ENB);
33962306a36Sopenharmony_ci	mask |= oct->io_qmask.iq;
34062306a36Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_PKT_INSTR_ENB, mask);
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci	mask = octeon_read_csr(oct, CN6XXX_SLI_PKT_OUT_ENB);
34362306a36Sopenharmony_ci	mask |= oct->io_qmask.oq;
34462306a36Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_PKT_OUT_ENB, mask);
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci	return 0;
34762306a36Sopenharmony_ci}
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_civoid lio_cn6xxx_disable_io_queues(struct octeon_device *oct)
35062306a36Sopenharmony_ci{
35162306a36Sopenharmony_ci	int i;
35262306a36Sopenharmony_ci	u32 mask, loop = HZ;
35362306a36Sopenharmony_ci	u32 d32;
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	/* Reset the Enable bits for Input Queues. */
35662306a36Sopenharmony_ci	mask = octeon_read_csr(oct, CN6XXX_SLI_PKT_INSTR_ENB);
35762306a36Sopenharmony_ci	mask ^= oct->io_qmask.iq;
35862306a36Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_PKT_INSTR_ENB, mask);
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	/* Wait until hardware indicates that the queues are out of reset. */
36162306a36Sopenharmony_ci	mask = (u32)oct->io_qmask.iq;
36262306a36Sopenharmony_ci	d32 = octeon_read_csr(oct, CN6XXX_SLI_PORT_IN_RST_IQ);
36362306a36Sopenharmony_ci	while (((d32 & mask) != mask) && loop--) {
36462306a36Sopenharmony_ci		d32 = octeon_read_csr(oct, CN6XXX_SLI_PORT_IN_RST_IQ);
36562306a36Sopenharmony_ci		schedule_timeout_uninterruptible(1);
36662306a36Sopenharmony_ci	}
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci	/* Reset the doorbell register for each Input queue. */
36962306a36Sopenharmony_ci	for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) {
37062306a36Sopenharmony_ci		if (!(oct->io_qmask.iq & BIT_ULL(i)))
37162306a36Sopenharmony_ci			continue;
37262306a36Sopenharmony_ci		octeon_write_csr(oct, CN6XXX_SLI_IQ_DOORBELL(i), 0xFFFFFFFF);
37362306a36Sopenharmony_ci		d32 = octeon_read_csr(oct, CN6XXX_SLI_IQ_DOORBELL(i));
37462306a36Sopenharmony_ci	}
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci	/* Reset the Enable bits for Output Queues. */
37762306a36Sopenharmony_ci	mask = octeon_read_csr(oct, CN6XXX_SLI_PKT_OUT_ENB);
37862306a36Sopenharmony_ci	mask ^= oct->io_qmask.oq;
37962306a36Sopenharmony_ci	octeon_write_csr(oct, CN6XXX_SLI_PKT_OUT_ENB, mask);
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci	/* Wait until hardware indicates that the queues are out of reset. */
38262306a36Sopenharmony_ci	loop = HZ;
38362306a36Sopenharmony_ci	mask = (u32)oct->io_qmask.oq;
38462306a36Sopenharmony_ci	d32 = octeon_read_csr(oct, CN6XXX_SLI_PORT_IN_RST_OQ);
38562306a36Sopenharmony_ci	while (((d32 & mask) != mask) && loop--) {
38662306a36Sopenharmony_ci		d32 = octeon_read_csr(oct, CN6XXX_SLI_PORT_IN_RST_OQ);
38762306a36Sopenharmony_ci		schedule_timeout_uninterruptible(1);
38862306a36Sopenharmony_ci	}
38962306a36Sopenharmony_ci	;
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci	/* Reset the doorbell register for each Output queue. */
39262306a36Sopenharmony_ci	for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct); i++) {
39362306a36Sopenharmony_ci		if (!(oct->io_qmask.oq & BIT_ULL(i)))
39462306a36Sopenharmony_ci			continue;
39562306a36Sopenharmony_ci		octeon_write_csr(oct, CN6XXX_SLI_OQ_PKTS_CREDIT(i), 0xFFFFFFFF);
39662306a36Sopenharmony_ci		d32 = octeon_read_csr(oct, CN6XXX_SLI_OQ_PKTS_CREDIT(i));
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_ci		d32 = octeon_read_csr(oct, CN6XXX_SLI_OQ_PKTS_SENT(i));
39962306a36Sopenharmony_ci		octeon_write_csr(oct, CN6XXX_SLI_OQ_PKTS_SENT(i), d32);
40062306a36Sopenharmony_ci	}
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci	d32 = octeon_read_csr(oct, CN6XXX_SLI_PKT_CNT_INT);
40362306a36Sopenharmony_ci	if (d32)
40462306a36Sopenharmony_ci		octeon_write_csr(oct, CN6XXX_SLI_PKT_CNT_INT, d32);
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci	d32 = octeon_read_csr(oct, CN6XXX_SLI_PKT_TIME_INT);
40762306a36Sopenharmony_ci	if (d32)
40862306a36Sopenharmony_ci		octeon_write_csr(oct, CN6XXX_SLI_PKT_TIME_INT, d32);
40962306a36Sopenharmony_ci}
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_civoid
41262306a36Sopenharmony_cilio_cn6xxx_bar1_idx_setup(struct octeon_device *oct,
41362306a36Sopenharmony_ci			  u64 core_addr,
41462306a36Sopenharmony_ci			  u32 idx,
41562306a36Sopenharmony_ci			  int valid)
41662306a36Sopenharmony_ci{
41762306a36Sopenharmony_ci	u64 bar1;
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci	if (valid == 0) {
42062306a36Sopenharmony_ci		bar1 = lio_pci_readq(oct, CN6XXX_BAR1_REG(idx, oct->pcie_port));
42162306a36Sopenharmony_ci		lio_pci_writeq(oct, (bar1 & 0xFFFFFFFEULL),
42262306a36Sopenharmony_ci			       CN6XXX_BAR1_REG(idx, oct->pcie_port));
42362306a36Sopenharmony_ci		bar1 = lio_pci_readq(oct, CN6XXX_BAR1_REG(idx, oct->pcie_port));
42462306a36Sopenharmony_ci		return;
42562306a36Sopenharmony_ci	}
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ci	/* Bits 17:4 of the PCI_BAR1_INDEXx stores bits 35:22 of
42862306a36Sopenharmony_ci	 * the Core Addr
42962306a36Sopenharmony_ci	 */
43062306a36Sopenharmony_ci	lio_pci_writeq(oct, (((core_addr >> 22) << 4) | PCI_BAR1_MASK),
43162306a36Sopenharmony_ci		       CN6XXX_BAR1_REG(idx, oct->pcie_port));
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci	bar1 = lio_pci_readq(oct, CN6XXX_BAR1_REG(idx, oct->pcie_port));
43462306a36Sopenharmony_ci}
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_civoid lio_cn6xxx_bar1_idx_write(struct octeon_device *oct,
43762306a36Sopenharmony_ci			       u32 idx,
43862306a36Sopenharmony_ci			       u32 mask)
43962306a36Sopenharmony_ci{
44062306a36Sopenharmony_ci	lio_pci_writeq(oct, mask, CN6XXX_BAR1_REG(idx, oct->pcie_port));
44162306a36Sopenharmony_ci}
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ciu32 lio_cn6xxx_bar1_idx_read(struct octeon_device *oct, u32 idx)
44462306a36Sopenharmony_ci{
44562306a36Sopenharmony_ci	return (u32)lio_pci_readq(oct, CN6XXX_BAR1_REG(idx, oct->pcie_port));
44662306a36Sopenharmony_ci}
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ciu32
44962306a36Sopenharmony_cilio_cn6xxx_update_read_index(struct octeon_instr_queue *iq)
45062306a36Sopenharmony_ci{
45162306a36Sopenharmony_ci	u32 new_idx = readl(iq->inst_cnt_reg);
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci	/* The new instr cnt reg is a 32-bit counter that can roll over. We have
45462306a36Sopenharmony_ci	 * noted the counter's initial value at init time into
45562306a36Sopenharmony_ci	 * reset_instr_cnt
45662306a36Sopenharmony_ci	 */
45762306a36Sopenharmony_ci	if (iq->reset_instr_cnt < new_idx)
45862306a36Sopenharmony_ci		new_idx -= iq->reset_instr_cnt;
45962306a36Sopenharmony_ci	else
46062306a36Sopenharmony_ci		new_idx += (0xffffffff - iq->reset_instr_cnt) + 1;
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ci	/* Modulo of the new index with the IQ size will give us
46362306a36Sopenharmony_ci	 * the new index.
46462306a36Sopenharmony_ci	 */
46562306a36Sopenharmony_ci	new_idx %= iq->max_count;
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci	return new_idx;
46862306a36Sopenharmony_ci}
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_civoid lio_cn6xxx_enable_interrupt(struct octeon_device *oct,
47162306a36Sopenharmony_ci				 u8 unused __attribute__((unused)))
47262306a36Sopenharmony_ci{
47362306a36Sopenharmony_ci	struct octeon_cn6xxx *cn6xxx = (struct octeon_cn6xxx *)oct->chip;
47462306a36Sopenharmony_ci	u64 mask = cn6xxx->intr_mask64 | CN6XXX_INTR_DMA0_FORCE;
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci	/* Enable Interrupt */
47762306a36Sopenharmony_ci	writeq(mask, cn6xxx->intr_enb_reg64);
47862306a36Sopenharmony_ci}
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_civoid lio_cn6xxx_disable_interrupt(struct octeon_device *oct,
48162306a36Sopenharmony_ci				  u8 unused __attribute__((unused)))
48262306a36Sopenharmony_ci{
48362306a36Sopenharmony_ci	struct octeon_cn6xxx *cn6xxx = (struct octeon_cn6xxx *)oct->chip;
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci	/* Disable Interrupts */
48662306a36Sopenharmony_ci	writeq(0, cn6xxx->intr_enb_reg64);
48762306a36Sopenharmony_ci}
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_cistatic void lio_cn6xxx_get_pcie_qlmport(struct octeon_device *oct)
49062306a36Sopenharmony_ci{
49162306a36Sopenharmony_ci	/* CN63xx Pass2 and newer parts implements the SLI_MAC_NUMBER register
49262306a36Sopenharmony_ci	 * to determine the PCIE port #
49362306a36Sopenharmony_ci	 */
49462306a36Sopenharmony_ci	oct->pcie_port = octeon_read_csr(oct, CN6XXX_SLI_MAC_NUMBER) & 0xff;
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci	dev_dbg(&oct->pci_dev->dev, "Using PCIE Port %d\n", oct->pcie_port);
49762306a36Sopenharmony_ci}
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_cistatic void
50062306a36Sopenharmony_cilio_cn6xxx_process_pcie_error_intr(struct octeon_device *oct, u64 intr64)
50162306a36Sopenharmony_ci{
50262306a36Sopenharmony_ci	dev_err(&oct->pci_dev->dev, "Error Intr: 0x%016llx\n",
50362306a36Sopenharmony_ci		CVM_CAST64(intr64));
50462306a36Sopenharmony_ci}
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_cistatic int lio_cn6xxx_process_droq_intr_regs(struct octeon_device *oct)
50762306a36Sopenharmony_ci{
50862306a36Sopenharmony_ci	struct octeon_droq *droq;
50962306a36Sopenharmony_ci	int oq_no;
51062306a36Sopenharmony_ci	u32 pkt_count, droq_time_mask, droq_mask, droq_int_enb;
51162306a36Sopenharmony_ci	u32 droq_cnt_enb, droq_cnt_mask;
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci	droq_cnt_enb = octeon_read_csr(oct, CN6XXX_SLI_PKT_CNT_INT_ENB);
51462306a36Sopenharmony_ci	droq_cnt_mask = octeon_read_csr(oct, CN6XXX_SLI_PKT_CNT_INT);
51562306a36Sopenharmony_ci	droq_mask = droq_cnt_mask & droq_cnt_enb;
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci	droq_time_mask = octeon_read_csr(oct, CN6XXX_SLI_PKT_TIME_INT);
51862306a36Sopenharmony_ci	droq_int_enb = octeon_read_csr(oct, CN6XXX_SLI_PKT_TIME_INT_ENB);
51962306a36Sopenharmony_ci	droq_mask |= (droq_time_mask & droq_int_enb);
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_ci	droq_mask &= oct->io_qmask.oq;
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci	oct->droq_intr = 0;
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_ci	for (oq_no = 0; oq_no < MAX_OCTEON_OUTPUT_QUEUES(oct); oq_no++) {
52662306a36Sopenharmony_ci		if (!(droq_mask & BIT_ULL(oq_no)))
52762306a36Sopenharmony_ci			continue;
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci		droq = oct->droq[oq_no];
53062306a36Sopenharmony_ci		pkt_count = octeon_droq_check_hw_for_pkts(droq);
53162306a36Sopenharmony_ci		if (pkt_count) {
53262306a36Sopenharmony_ci			oct->droq_intr |= BIT_ULL(oq_no);
53362306a36Sopenharmony_ci			if (droq->ops.poll_mode) {
53462306a36Sopenharmony_ci				u32 value;
53562306a36Sopenharmony_ci				u32 reg;
53662306a36Sopenharmony_ci
53762306a36Sopenharmony_ci				struct octeon_cn6xxx *cn6xxx =
53862306a36Sopenharmony_ci					(struct octeon_cn6xxx *)oct->chip;
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ci				/* disable interrupts for this droq */
54162306a36Sopenharmony_ci				spin_lock
54262306a36Sopenharmony_ci					(&cn6xxx->lock_for_droq_int_enb_reg);
54362306a36Sopenharmony_ci				reg = CN6XXX_SLI_PKT_TIME_INT_ENB;
54462306a36Sopenharmony_ci				value = octeon_read_csr(oct, reg);
54562306a36Sopenharmony_ci				value &= ~(1 << oq_no);
54662306a36Sopenharmony_ci				octeon_write_csr(oct, reg, value);
54762306a36Sopenharmony_ci				reg = CN6XXX_SLI_PKT_CNT_INT_ENB;
54862306a36Sopenharmony_ci				value = octeon_read_csr(oct, reg);
54962306a36Sopenharmony_ci				value &= ~(1 << oq_no);
55062306a36Sopenharmony_ci				octeon_write_csr(oct, reg, value);
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci				spin_unlock(&cn6xxx->lock_for_droq_int_enb_reg);
55362306a36Sopenharmony_ci			}
55462306a36Sopenharmony_ci		}
55562306a36Sopenharmony_ci	}
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci	droq_time_mask &= oct->io_qmask.oq;
55862306a36Sopenharmony_ci	droq_cnt_mask &= oct->io_qmask.oq;
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_ci	/* Reset the PKT_CNT/TIME_INT registers. */
56162306a36Sopenharmony_ci	if (droq_time_mask)
56262306a36Sopenharmony_ci		octeon_write_csr(oct, CN6XXX_SLI_PKT_TIME_INT, droq_time_mask);
56362306a36Sopenharmony_ci
56462306a36Sopenharmony_ci	if (droq_cnt_mask)      /* reset PKT_CNT register:66xx */
56562306a36Sopenharmony_ci		octeon_write_csr(oct, CN6XXX_SLI_PKT_CNT_INT, droq_cnt_mask);
56662306a36Sopenharmony_ci
56762306a36Sopenharmony_ci	return 0;
56862306a36Sopenharmony_ci}
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_ciirqreturn_t lio_cn6xxx_process_interrupt_regs(void *dev)
57162306a36Sopenharmony_ci{
57262306a36Sopenharmony_ci	struct octeon_device *oct = (struct octeon_device *)dev;
57362306a36Sopenharmony_ci	struct octeon_cn6xxx *cn6xxx = (struct octeon_cn6xxx *)oct->chip;
57462306a36Sopenharmony_ci	u64 intr64;
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci	intr64 = readq(cn6xxx->intr_sum_reg64);
57762306a36Sopenharmony_ci
57862306a36Sopenharmony_ci	/* If our device has interrupted, then proceed.
57962306a36Sopenharmony_ci	 * Also check for all f's if interrupt was triggered on an error
58062306a36Sopenharmony_ci	 * and the PCI read fails.
58162306a36Sopenharmony_ci	 */
58262306a36Sopenharmony_ci	if (!intr64 || (intr64 == 0xFFFFFFFFFFFFFFFFULL))
58362306a36Sopenharmony_ci		return IRQ_NONE;
58462306a36Sopenharmony_ci
58562306a36Sopenharmony_ci	oct->int_status = 0;
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ci	if (intr64 & CN6XXX_INTR_ERR)
58862306a36Sopenharmony_ci		lio_cn6xxx_process_pcie_error_intr(oct, intr64);
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_ci	if (intr64 & CN6XXX_INTR_PKT_DATA) {
59162306a36Sopenharmony_ci		lio_cn6xxx_process_droq_intr_regs(oct);
59262306a36Sopenharmony_ci		oct->int_status |= OCT_DEV_INTR_PKT_DATA;
59362306a36Sopenharmony_ci	}
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_ci	if (intr64 & CN6XXX_INTR_DMA0_FORCE)
59662306a36Sopenharmony_ci		oct->int_status |= OCT_DEV_INTR_DMA0_FORCE;
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_ci	if (intr64 & CN6XXX_INTR_DMA1_FORCE)
59962306a36Sopenharmony_ci		oct->int_status |= OCT_DEV_INTR_DMA1_FORCE;
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_ci	/* Clear the current interrupts */
60262306a36Sopenharmony_ci	writeq(intr64, cn6xxx->intr_sum_reg64);
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci	return IRQ_HANDLED;
60562306a36Sopenharmony_ci}
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_civoid lio_cn6xxx_setup_reg_address(struct octeon_device *oct,
60862306a36Sopenharmony_ci				  void *chip,
60962306a36Sopenharmony_ci				  struct octeon_reg_list *reg_list)
61062306a36Sopenharmony_ci{
61162306a36Sopenharmony_ci	u8 __iomem *bar0_pciaddr = oct->mmio[0].hw_addr;
61262306a36Sopenharmony_ci	struct octeon_cn6xxx *cn6xxx = (struct octeon_cn6xxx *)chip;
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci	reg_list->pci_win_wr_addr_hi =
61562306a36Sopenharmony_ci		(u32 __iomem *)(bar0_pciaddr + CN6XXX_WIN_WR_ADDR_HI);
61662306a36Sopenharmony_ci	reg_list->pci_win_wr_addr_lo =
61762306a36Sopenharmony_ci		(u32 __iomem *)(bar0_pciaddr + CN6XXX_WIN_WR_ADDR_LO);
61862306a36Sopenharmony_ci	reg_list->pci_win_wr_addr =
61962306a36Sopenharmony_ci		(u64 __iomem *)(bar0_pciaddr + CN6XXX_WIN_WR_ADDR64);
62062306a36Sopenharmony_ci
62162306a36Sopenharmony_ci	reg_list->pci_win_rd_addr_hi =
62262306a36Sopenharmony_ci		(u32 __iomem *)(bar0_pciaddr + CN6XXX_WIN_RD_ADDR_HI);
62362306a36Sopenharmony_ci	reg_list->pci_win_rd_addr_lo =
62462306a36Sopenharmony_ci		(u32 __iomem *)(bar0_pciaddr + CN6XXX_WIN_RD_ADDR_LO);
62562306a36Sopenharmony_ci	reg_list->pci_win_rd_addr =
62662306a36Sopenharmony_ci		(u64 __iomem *)(bar0_pciaddr + CN6XXX_WIN_RD_ADDR64);
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci	reg_list->pci_win_wr_data_hi =
62962306a36Sopenharmony_ci		(u32 __iomem *)(bar0_pciaddr + CN6XXX_WIN_WR_DATA_HI);
63062306a36Sopenharmony_ci	reg_list->pci_win_wr_data_lo =
63162306a36Sopenharmony_ci		(u32 __iomem *)(bar0_pciaddr + CN6XXX_WIN_WR_DATA_LO);
63262306a36Sopenharmony_ci	reg_list->pci_win_wr_data =
63362306a36Sopenharmony_ci		(u64 __iomem *)(bar0_pciaddr + CN6XXX_WIN_WR_DATA64);
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_ci	reg_list->pci_win_rd_data_hi =
63662306a36Sopenharmony_ci		(u32 __iomem *)(bar0_pciaddr + CN6XXX_WIN_RD_DATA_HI);
63762306a36Sopenharmony_ci	reg_list->pci_win_rd_data_lo =
63862306a36Sopenharmony_ci		(u32 __iomem *)(bar0_pciaddr + CN6XXX_WIN_RD_DATA_LO);
63962306a36Sopenharmony_ci	reg_list->pci_win_rd_data =
64062306a36Sopenharmony_ci		(u64 __iomem *)(bar0_pciaddr + CN6XXX_WIN_RD_DATA64);
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_ci	lio_cn6xxx_get_pcie_qlmport(oct);
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	cn6xxx->intr_sum_reg64 = bar0_pciaddr + CN6XXX_SLI_INT_SUM64;
64562306a36Sopenharmony_ci	cn6xxx->intr_mask64 = CN6XXX_INTR_MASK;
64662306a36Sopenharmony_ci	cn6xxx->intr_enb_reg64 =
64762306a36Sopenharmony_ci		bar0_pciaddr + CN6XXX_SLI_INT_ENB64(oct->pcie_port);
64862306a36Sopenharmony_ci}
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ciint lio_setup_cn66xx_octeon_device(struct octeon_device *oct)
65162306a36Sopenharmony_ci{
65262306a36Sopenharmony_ci	struct octeon_cn6xxx *cn6xxx = (struct octeon_cn6xxx *)oct->chip;
65362306a36Sopenharmony_ci
65462306a36Sopenharmony_ci	if (octeon_map_pci_barx(oct, 0, 0))
65562306a36Sopenharmony_ci		return 1;
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci	if (octeon_map_pci_barx(oct, 1, MAX_BAR1_IOREMAP_SIZE)) {
65862306a36Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "%s CN66XX BAR1 map failed\n",
65962306a36Sopenharmony_ci			__func__);
66062306a36Sopenharmony_ci		octeon_unmap_pci_barx(oct, 0);
66162306a36Sopenharmony_ci		return 1;
66262306a36Sopenharmony_ci	}
66362306a36Sopenharmony_ci
66462306a36Sopenharmony_ci	spin_lock_init(&cn6xxx->lock_for_droq_int_enb_reg);
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci	oct->fn_list.setup_iq_regs = lio_cn66xx_setup_iq_regs;
66762306a36Sopenharmony_ci	oct->fn_list.setup_oq_regs = lio_cn6xxx_setup_oq_regs;
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ci	oct->fn_list.soft_reset = lio_cn6xxx_soft_reset;
67062306a36Sopenharmony_ci	oct->fn_list.setup_device_regs = lio_cn6xxx_setup_device_regs;
67162306a36Sopenharmony_ci	oct->fn_list.update_iq_read_idx = lio_cn6xxx_update_read_index;
67262306a36Sopenharmony_ci
67362306a36Sopenharmony_ci	oct->fn_list.bar1_idx_setup = lio_cn6xxx_bar1_idx_setup;
67462306a36Sopenharmony_ci	oct->fn_list.bar1_idx_write = lio_cn6xxx_bar1_idx_write;
67562306a36Sopenharmony_ci	oct->fn_list.bar1_idx_read = lio_cn6xxx_bar1_idx_read;
67662306a36Sopenharmony_ci
67762306a36Sopenharmony_ci	oct->fn_list.process_interrupt_regs = lio_cn6xxx_process_interrupt_regs;
67862306a36Sopenharmony_ci	oct->fn_list.enable_interrupt = lio_cn6xxx_enable_interrupt;
67962306a36Sopenharmony_ci	oct->fn_list.disable_interrupt = lio_cn6xxx_disable_interrupt;
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ci	oct->fn_list.enable_io_queues = lio_cn6xxx_enable_io_queues;
68262306a36Sopenharmony_ci	oct->fn_list.disable_io_queues = lio_cn6xxx_disable_io_queues;
68362306a36Sopenharmony_ci
68462306a36Sopenharmony_ci	lio_cn6xxx_setup_reg_address(oct, oct->chip, &oct->reg_list);
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_ci	cn6xxx->conf = (struct octeon_config *)
68762306a36Sopenharmony_ci		       oct_get_config_info(oct, LIO_210SV);
68862306a36Sopenharmony_ci	if (!cn6xxx->conf) {
68962306a36Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "%s No Config found for CN66XX\n",
69062306a36Sopenharmony_ci			__func__);
69162306a36Sopenharmony_ci		octeon_unmap_pci_barx(oct, 0);
69262306a36Sopenharmony_ci		octeon_unmap_pci_barx(oct, 1);
69362306a36Sopenharmony_ci		return 1;
69462306a36Sopenharmony_ci	}
69562306a36Sopenharmony_ci
69662306a36Sopenharmony_ci	oct->coproc_clock_rate = 1000000ULL * lio_cn6xxx_coprocessor_clock(oct);
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci	return 0;
69962306a36Sopenharmony_ci}
70062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(lio_setup_cn66xx_octeon_device);
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_ciint lio_validate_cn6xxx_config_info(struct octeon_device *oct,
70362306a36Sopenharmony_ci				    struct octeon_config *conf6xxx)
70462306a36Sopenharmony_ci{
70562306a36Sopenharmony_ci	if (CFG_GET_IQ_MAX_Q(conf6xxx) > CN6XXX_MAX_INPUT_QUEUES) {
70662306a36Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "%s: Num IQ (%d) exceeds Max (%d)\n",
70762306a36Sopenharmony_ci			__func__, CFG_GET_IQ_MAX_Q(conf6xxx),
70862306a36Sopenharmony_ci			CN6XXX_MAX_INPUT_QUEUES);
70962306a36Sopenharmony_ci		return 1;
71062306a36Sopenharmony_ci	}
71162306a36Sopenharmony_ci
71262306a36Sopenharmony_ci	if (CFG_GET_OQ_MAX_Q(conf6xxx) > CN6XXX_MAX_OUTPUT_QUEUES) {
71362306a36Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "%s: Num OQ (%d) exceeds Max (%d)\n",
71462306a36Sopenharmony_ci			__func__, CFG_GET_OQ_MAX_Q(conf6xxx),
71562306a36Sopenharmony_ci			CN6XXX_MAX_OUTPUT_QUEUES);
71662306a36Sopenharmony_ci		return 1;
71762306a36Sopenharmony_ci	}
71862306a36Sopenharmony_ci
71962306a36Sopenharmony_ci	if (CFG_GET_IQ_INSTR_TYPE(conf6xxx) != OCTEON_32BYTE_INSTR &&
72062306a36Sopenharmony_ci	    CFG_GET_IQ_INSTR_TYPE(conf6xxx) != OCTEON_64BYTE_INSTR) {
72162306a36Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "%s: Invalid instr type for IQ\n",
72262306a36Sopenharmony_ci			__func__);
72362306a36Sopenharmony_ci		return 1;
72462306a36Sopenharmony_ci	}
72562306a36Sopenharmony_ci	if (!CFG_GET_OQ_REFILL_THRESHOLD(conf6xxx)) {
72662306a36Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "%s: Invalid parameter for OQ\n",
72762306a36Sopenharmony_ci			__func__);
72862306a36Sopenharmony_ci		return 1;
72962306a36Sopenharmony_ci	}
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	if (!(CFG_GET_OQ_INTR_TIME(conf6xxx))) {
73262306a36Sopenharmony_ci		dev_err(&oct->pci_dev->dev, "%s: No Time Interrupt for OQ\n",
73362306a36Sopenharmony_ci			__func__);
73462306a36Sopenharmony_ci		return 1;
73562306a36Sopenharmony_ci	}
73662306a36Sopenharmony_ci
73762306a36Sopenharmony_ci	return 0;
73862306a36Sopenharmony_ci}
739