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