Path: blob/master/drivers/accel/habanalabs/common/pci/pci.c
26488 views
// SPDX-License-Identifier: GPL-2.012/*3* Copyright 2016-2019 HabanaLabs, Ltd.4* All Rights Reserved.5*/67#include "../habanalabs.h"8#include "../../include/hw_ip/pci/pci_general.h"910#include <linux/pci.h>1112#include <trace/events/habanalabs.h>1314#define HL_PLDM_PCI_ELBI_TIMEOUT_MSEC (HL_PCI_ELBI_TIMEOUT_MSEC * 100)1516#define IATU_REGION_CTRL_REGION_EN_MASK BIT(31)17#define IATU_REGION_CTRL_MATCH_MODE_MASK BIT(30)18#define IATU_REGION_CTRL_NUM_MATCH_EN_MASK BIT(19)19#define IATU_REGION_CTRL_BAR_NUM_MASK GENMASK(10, 8)2021/**22* hl_pci_bars_map() - Map PCI BARs.23* @hdev: Pointer to hl_device structure.24* @name: Array of BAR names.25* @is_wc: Array with flag per BAR whether a write-combined mapping is needed.26*27* Request PCI regions and map them to kernel virtual addresses.28*29* Return: 0 on success, non-zero for failure.30*/31int hl_pci_bars_map(struct hl_device *hdev, const char * const name[3],32bool is_wc[3])33{34struct pci_dev *pdev = hdev->pdev;35int rc, i, bar;3637rc = pci_request_regions(pdev, HL_NAME);38if (rc) {39dev_err(hdev->dev, "Cannot obtain PCI resources\n");40return rc;41}4243for (i = 0 ; i < 3 ; i++) {44bar = i * 2; /* 64-bit BARs */45hdev->pcie_bar[bar] = is_wc[i] ?46pci_ioremap_wc_bar(pdev, bar) :47pci_ioremap_bar(pdev, bar);48if (!hdev->pcie_bar[bar]) {49dev_err(hdev->dev, "pci_ioremap%s_bar failed for %s\n",50is_wc[i] ? "_wc" : "", name[i]);51rc = -ENODEV;52goto err;53}54}5556return 0;5758err:59for (i = 2 ; i >= 0 ; i--) {60bar = i * 2; /* 64-bit BARs */61if (hdev->pcie_bar[bar])62iounmap(hdev->pcie_bar[bar]);63}6465pci_release_regions(pdev);6667return rc;68}6970/**71* hl_pci_bars_unmap() - Unmap PCI BARS.72* @hdev: Pointer to hl_device structure.73*74* Release all PCI BARs and unmap their virtual addresses.75*/76static void hl_pci_bars_unmap(struct hl_device *hdev)77{78struct pci_dev *pdev = hdev->pdev;79int i, bar;8081for (i = 2 ; i >= 0 ; i--) {82bar = i * 2; /* 64-bit BARs */83iounmap(hdev->pcie_bar[bar]);84}8586pci_release_regions(pdev);87}8889int hl_pci_elbi_read(struct hl_device *hdev, u64 addr, u32 *data)90{91struct pci_dev *pdev = hdev->pdev;92ktime_t timeout;93u64 msec;94u32 val;9596if (hdev->pldm)97msec = HL_PLDM_PCI_ELBI_TIMEOUT_MSEC;98else99msec = HL_PCI_ELBI_TIMEOUT_MSEC;100101/* Clear previous status */102pci_write_config_dword(pdev, mmPCI_CONFIG_ELBI_STS, 0);103104pci_write_config_dword(pdev, mmPCI_CONFIG_ELBI_ADDR, (u32) addr);105pci_write_config_dword(pdev, mmPCI_CONFIG_ELBI_CTRL, 0);106107timeout = ktime_add_ms(ktime_get(), msec);108for (;;) {109pci_read_config_dword(pdev, mmPCI_CONFIG_ELBI_STS, &val);110if (val & PCI_CONFIG_ELBI_STS_MASK)111break;112if (ktime_compare(ktime_get(), timeout) > 0) {113pci_read_config_dword(pdev, mmPCI_CONFIG_ELBI_STS,114&val);115break;116}117118usleep_range(300, 500);119}120121if ((val & PCI_CONFIG_ELBI_STS_MASK) == PCI_CONFIG_ELBI_STS_DONE) {122pci_read_config_dword(pdev, mmPCI_CONFIG_ELBI_DATA, data);123124if (unlikely(trace_habanalabs_elbi_read_enabled()))125trace_habanalabs_elbi_read(&hdev->pdev->dev, (u32) addr, val);126127return 0;128}129130if (val & PCI_CONFIG_ELBI_STS_ERR) {131dev_err(hdev->dev, "Error reading from ELBI\n");132return -EIO;133}134135if (!(val & PCI_CONFIG_ELBI_STS_MASK)) {136dev_err(hdev->dev, "ELBI read didn't finish in time\n");137return -EIO;138}139140dev_err(hdev->dev, "ELBI read has undefined bits in status\n");141return -EIO;142}143144/**145* hl_pci_elbi_write() - Write through the ELBI interface.146* @hdev: Pointer to hl_device structure.147* @addr: Address to write to148* @data: Data to write149*150* Return: 0 on success, negative value for failure.151*/152static int hl_pci_elbi_write(struct hl_device *hdev, u64 addr, u32 data)153{154struct pci_dev *pdev = hdev->pdev;155ktime_t timeout;156u64 msec;157u32 val;158159if (hdev->pldm)160msec = HL_PLDM_PCI_ELBI_TIMEOUT_MSEC;161else162msec = HL_PCI_ELBI_TIMEOUT_MSEC;163164/* Clear previous status */165pci_write_config_dword(pdev, mmPCI_CONFIG_ELBI_STS, 0);166167pci_write_config_dword(pdev, mmPCI_CONFIG_ELBI_ADDR, (u32) addr);168pci_write_config_dword(pdev, mmPCI_CONFIG_ELBI_DATA, data);169pci_write_config_dword(pdev, mmPCI_CONFIG_ELBI_CTRL,170PCI_CONFIG_ELBI_CTRL_WRITE);171172timeout = ktime_add_ms(ktime_get(), msec);173for (;;) {174pci_read_config_dword(pdev, mmPCI_CONFIG_ELBI_STS, &val);175if (val & PCI_CONFIG_ELBI_STS_MASK)176break;177if (ktime_compare(ktime_get(), timeout) > 0) {178pci_read_config_dword(pdev, mmPCI_CONFIG_ELBI_STS,179&val);180break;181}182183usleep_range(300, 500);184}185186if ((val & PCI_CONFIG_ELBI_STS_MASK) == PCI_CONFIG_ELBI_STS_DONE) {187if (unlikely(trace_habanalabs_elbi_write_enabled()))188trace_habanalabs_elbi_write(&hdev->pdev->dev, (u32) addr, val);189return 0;190}191192if (val & PCI_CONFIG_ELBI_STS_ERR)193return -EIO;194195if (!(val & PCI_CONFIG_ELBI_STS_MASK)) {196dev_err(hdev->dev, "ELBI write didn't finish in time\n");197return -EIO;198}199200dev_err(hdev->dev, "ELBI write has undefined bits in status\n");201return -EIO;202}203204/**205* hl_pci_iatu_write() - iatu write routine.206* @hdev: Pointer to hl_device structure.207* @addr: Address to write to208* @data: Data to write209*210* Return: 0 on success, negative value for failure.211*/212int hl_pci_iatu_write(struct hl_device *hdev, u32 addr, u32 data)213{214struct asic_fixed_properties *prop = &hdev->asic_prop;215u32 dbi_offset;216int rc;217218dbi_offset = addr & 0xFFF;219220/* Ignore result of writing to pcie_aux_dbi_reg_addr as it could fail221* in case the firmware security is enabled222*/223hl_pci_elbi_write(hdev, prop->pcie_aux_dbi_reg_addr, 0x00300000);224225rc = hl_pci_elbi_write(hdev, prop->pcie_dbi_base_address + dbi_offset,226data);227228if (rc)229return -EIO;230231return 0;232}233234/**235* hl_pci_set_inbound_region() - Configure inbound region236* @hdev: Pointer to hl_device structure.237* @region: Inbound region number.238* @pci_region: Inbound region parameters.239*240* Configure the iATU inbound region.241*242* Return: 0 on success, negative value for failure.243*/244int hl_pci_set_inbound_region(struct hl_device *hdev, u8 region,245struct hl_inbound_pci_region *pci_region)246{247struct asic_fixed_properties *prop = &hdev->asic_prop;248u64 bar_phys_base, region_base, region_end_address;249u32 offset, ctrl_reg_val;250int rc = 0;251252/* region offset */253offset = (0x200 * region) + 0x100;254255if (pci_region->mode == PCI_ADDRESS_MATCH_MODE) {256bar_phys_base = hdev->pcie_bar_phys[pci_region->bar];257region_base = bar_phys_base + pci_region->offset_in_bar;258region_end_address = region_base + pci_region->size - 1;259260rc |= hl_pci_iatu_write(hdev, offset + 0x8,261lower_32_bits(region_base));262rc |= hl_pci_iatu_write(hdev, offset + 0xC,263upper_32_bits(region_base));264rc |= hl_pci_iatu_write(hdev, offset + 0x10,265lower_32_bits(region_end_address));266}267268/* Point to the specified address */269rc |= hl_pci_iatu_write(hdev, offset + 0x14, lower_32_bits(pci_region->addr));270rc |= hl_pci_iatu_write(hdev, offset + 0x18, upper_32_bits(pci_region->addr));271272/* Set bar type as memory */273rc |= hl_pci_iatu_write(hdev, offset + 0x0, 0);274275/* Enable + bar/address match + match enable + bar number */276ctrl_reg_val = FIELD_PREP(IATU_REGION_CTRL_REGION_EN_MASK, 1);277ctrl_reg_val |= FIELD_PREP(IATU_REGION_CTRL_MATCH_MODE_MASK, pci_region->mode);278ctrl_reg_val |= FIELD_PREP(IATU_REGION_CTRL_NUM_MATCH_EN_MASK, 1);279280if (pci_region->mode == PCI_BAR_MATCH_MODE)281ctrl_reg_val |= FIELD_PREP(IATU_REGION_CTRL_BAR_NUM_MASK, pci_region->bar);282283rc |= hl_pci_iatu_write(hdev, offset + 0x4, ctrl_reg_val);284285/* Return the DBI window to the default location286* Ignore result of writing to pcie_aux_dbi_reg_addr as it could fail287* in case the firmware security is enabled288*/289hl_pci_elbi_write(hdev, prop->pcie_aux_dbi_reg_addr, 0);290291if (rc)292dev_err(hdev->dev, "failed to map bar %u to 0x%08llx\n",293pci_region->bar, pci_region->addr);294295return rc;296}297298/**299* hl_pci_set_outbound_region() - Configure outbound region 0300* @hdev: Pointer to hl_device structure.301* @pci_region: Outbound region parameters.302*303* Configure the iATU outbound region 0.304*305* Return: 0 on success, negative value for failure.306*/307int hl_pci_set_outbound_region(struct hl_device *hdev,308struct hl_outbound_pci_region *pci_region)309{310struct asic_fixed_properties *prop = &hdev->asic_prop;311u64 outbound_region_end_address;312int rc = 0;313314/* Outbound Region 0 */315outbound_region_end_address =316pci_region->addr + pci_region->size - 1;317rc |= hl_pci_iatu_write(hdev, 0x008,318lower_32_bits(pci_region->addr));319rc |= hl_pci_iatu_write(hdev, 0x00C,320upper_32_bits(pci_region->addr));321rc |= hl_pci_iatu_write(hdev, 0x010,322lower_32_bits(outbound_region_end_address));323rc |= hl_pci_iatu_write(hdev, 0x014, 0);324325rc |= hl_pci_iatu_write(hdev, 0x018, 0);326327rc |= hl_pci_iatu_write(hdev, 0x020,328upper_32_bits(outbound_region_end_address));329/* Increase region size */330rc |= hl_pci_iatu_write(hdev, 0x000, 0x00002000);331/* Enable */332rc |= hl_pci_iatu_write(hdev, 0x004, 0x80000000);333334/* Return the DBI window to the default location335* Ignore result of writing to pcie_aux_dbi_reg_addr as it could fail336* in case the firmware security is enabled337*/338hl_pci_elbi_write(hdev, prop->pcie_aux_dbi_reg_addr, 0);339340return rc;341}342343/**344* hl_get_pci_memory_region() - get PCI region for given address345* @hdev: Pointer to hl_device structure.346* @addr: device address347*348* @return region index on success, otherwise PCI_REGION_NUMBER (invalid349* region index)350*/351enum pci_region hl_get_pci_memory_region(struct hl_device *hdev, u64 addr)352{353int i;354355for (i = 0 ; i < PCI_REGION_NUMBER ; i++) {356struct pci_mem_region *region = &hdev->pci_mem_region[i];357358if (!region->used)359continue;360361if ((addr >= region->region_base) &&362(addr < region->region_base + region->region_size))363return i;364}365366return PCI_REGION_NUMBER;367}368369/**370* hl_pci_init() - PCI initialization code.371* @hdev: Pointer to hl_device structure.372*373* Set DMA masks, initialize the PCI controller and map the PCI BARs.374*375* Return: 0 on success, non-zero for failure.376*/377int hl_pci_init(struct hl_device *hdev)378{379struct asic_fixed_properties *prop = &hdev->asic_prop;380struct pci_dev *pdev = hdev->pdev;381int rc;382383rc = pci_enable_device_mem(pdev);384if (rc) {385dev_err(hdev->dev, "can't enable PCI device\n");386return rc;387}388389pci_set_master(pdev);390391rc = hdev->asic_funcs->pci_bars_map(hdev);392if (rc) {393dev_err(hdev->dev, "Failed to map PCI BAR addresses\n");394goto disable_device;395}396397rc = hdev->asic_funcs->init_iatu(hdev);398if (rc) {399dev_err(hdev->dev, "PCI controller was not initialized successfully\n");400goto unmap_pci_bars;401}402403/* Driver must sleep in order for FW to finish the iATU configuration */404if (hdev->asic_prop.iatu_done_by_fw)405usleep_range(2000, 3000);406407rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(prop->dma_mask));408if (rc) {409dev_err(hdev->dev,410"Failed to set dma mask to %d bits, error %d\n",411prop->dma_mask, rc);412goto unmap_pci_bars;413}414415dma_set_max_seg_size(&pdev->dev, U32_MAX);416417return 0;418419unmap_pci_bars:420hl_pci_bars_unmap(hdev);421disable_device:422pci_disable_device(pdev);423424return rc;425}426427/**428* hl_pci_fini() - PCI finalization code.429* @hdev: Pointer to hl_device structure430*431* Unmap PCI bars and disable PCI device.432*/433void hl_pci_fini(struct hl_device *hdev)434{435hl_pci_bars_unmap(hdev);436437pci_disable_device(hdev->pdev);438}439440441