/* * Copyright (c) 2019 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #ifdef CONFIG_PCIE_MSI #include #endif /* * The Configuration Mechanism (previously, Configuration Mechanism #1) * uses two 32-bit ports in the I/O space, here called CAP and CDP. * * N.B.: this code relies on the fact that the PCIE_BDF() format (as * defined in dt-bindings/pcie/pcie.h) and the CAP agree on the bus/dev/func * bitfield positions and sizes. */ #define PCIE_X86_CAP 0xCF8U /* Configuration Address Port */ #define PCIE_X86_CAP_BDF_MASK 0x00FFFF00U /* b/d/f bits */ #define PCIE_X86_CAP_EN 0x80000000U /* enable bit */ #define PCIE_X86_CAP_WORD_MASK 0x3FU /* 6-bit word index .. */ #define PCIE_X86_CAP_WORD_SHIFT 2U /* .. is in CAP[7:2] */ #define PCIE_X86_CDP 0xCFCU /* Configuration Data Port */ /* * Helper function for exported configuration functions. Configuration access * ain't atomic, so spinlock to keep drivers from clobbering each other. */ static void pcie_conf(pcie_bdf_t bdf, unsigned int reg, bool write, u32_t *data) { static struct k_spinlock lock; k_spinlock_key_t k; bdf &= PCIE_X86_CAP_BDF_MASK; bdf |= PCIE_X86_CAP_EN; bdf |= (reg & PCIE_X86_CAP_WORD_MASK) << PCIE_X86_CAP_WORD_SHIFT; k = k_spin_lock(&lock); sys_out32(bdf, PCIE_X86_CAP); if (write) { sys_out32(*data, PCIE_X86_CDP); } else { *data = sys_in32(PCIE_X86_CDP); } sys_out32(0U, PCIE_X86_CAP); k_spin_unlock(&lock, k); } /* these functions are explained in include/drivers/pcie/pcie.h */ u32_t pcie_conf_read(pcie_bdf_t bdf, unsigned int reg) { u32_t data; pcie_conf(bdf, reg, false, &data); return data; } void pcie_conf_write(pcie_bdf_t bdf, unsigned int reg, u32_t data) { pcie_conf(bdf, reg, true, &data); } #ifdef CONFIG_PCIE_MSI /* these functions are explained in include/drivers/pcie/msi.h */ u32_t pcie_msi_map(unsigned int irq) { ARG_UNUSED(irq); return 0xFEE00000U; /* standard delivery to BSP local APIC */ } u16_t pcie_msi_mdr(unsigned int irq) { unsigned char vector = _irq_to_interrupt_vector[irq]; return 0x4000U | vector; /* edge triggered */ } #endif