| /* |
| * Copyright (c) 2019 Intel Corporation |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <stdbool.h> |
| #include <drivers/pcie/pcie.h> |
| #include <drivers/pcie/msi.h> |
| |
| /* functions documented in include/drivers/pcie/msi.h */ |
| |
| u32_t pcie_get_cap(pcie_bdf_t bdf, u32_t cap_id) |
| { |
| u32_t reg = 0U; |
| u32_t data; |
| |
| data = pcie_conf_read(bdf, PCIE_CONF_CMDSTAT); |
| if (data & PCIE_CONF_CMDSTAT_CAPS) { |
| data = pcie_conf_read(bdf, PCIE_CONF_CAPPTR); |
| reg = PCIE_CONF_CAPPTR_FIRST(data); |
| } |
| |
| while (reg) { |
| data = pcie_conf_read(bdf, reg); |
| |
| if (PCIE_CONF_CAP_ID(data) == cap_id) { |
| break; |
| } |
| |
| reg = PCIE_CONF_CAP_NEXT(data); |
| } |
| |
| return reg; |
| } |
| |
| bool pcie_set_msi(pcie_bdf_t bdf, unsigned int irq) |
| { |
| bool success = false; /* keepin' the MISRA peeps employed */ |
| u32_t base; |
| u32_t mcr; |
| u32_t map; |
| u32_t mdr; |
| |
| map = pcie_msi_map(irq); |
| mdr = pcie_msi_mdr(irq); |
| base = pcie_get_cap(bdf, PCIE_MSI_CAP_ID); |
| |
| if (base != 0U) { |
| mcr = pcie_conf_read(bdf, base + PCIE_MSI_MCR); |
| pcie_conf_write(bdf, base + PCIE_MSI_MAP0, map); |
| |
| if (mcr & PCIE_MSI_MCR_64) { |
| pcie_conf_write(bdf, base + PCIE_MSI_MAP1_64, 0U); |
| pcie_conf_write(bdf, base + PCIE_MSI_MDR_64, mdr); |
| } else { |
| pcie_conf_write(bdf, base + PCIE_MSI_MDR_32, mdr); |
| } |
| |
| mcr |= PCIE_MSI_MCR_EN; |
| mcr &= ~PCIE_MSI_MCR_MME; /* only 1 IRQ please */ |
| pcie_conf_write(bdf, base + PCIE_MSI_MCR, mcr); |
| pcie_set_cmd(bdf, PCIE_CONF_CMDSTAT_MASTER, true); |
| success = true; |
| } |
| |
| return success; |
| } |