cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pcie-tegra194-acpi.c (2780B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * ACPI quirks for Tegra194 PCIe host controller
      4 *
      5 * Copyright (C) 2021 NVIDIA Corporation.
      6 *
      7 * Author: Vidya Sagar <vidyas@nvidia.com>
      8 */
      9
     10#include <linux/pci.h>
     11#include <linux/pci-acpi.h>
     12#include <linux/pci-ecam.h>
     13
     14#include "pcie-designware.h"
     15
     16struct tegra194_pcie_ecam  {
     17	void __iomem *config_base;
     18	void __iomem *iatu_base;
     19	void __iomem *dbi_base;
     20};
     21
     22static int tegra194_acpi_init(struct pci_config_window *cfg)
     23{
     24	struct device *dev = cfg->parent;
     25	struct tegra194_pcie_ecam *pcie_ecam;
     26
     27	pcie_ecam = devm_kzalloc(dev, sizeof(*pcie_ecam), GFP_KERNEL);
     28	if (!pcie_ecam)
     29		return -ENOMEM;
     30
     31	pcie_ecam->config_base = cfg->win;
     32	pcie_ecam->iatu_base = cfg->win + SZ_256K;
     33	pcie_ecam->dbi_base = cfg->win + SZ_512K;
     34	cfg->priv = pcie_ecam;
     35
     36	return 0;
     37}
     38
     39static void atu_reg_write(struct tegra194_pcie_ecam *pcie_ecam, int index,
     40			  u32 val, u32 reg)
     41{
     42	u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
     43
     44	writel(val, pcie_ecam->iatu_base + offset + reg);
     45}
     46
     47static void program_outbound_atu(struct tegra194_pcie_ecam *pcie_ecam,
     48				 int index, int type, u64 cpu_addr,
     49				 u64 pci_addr, u64 size)
     50{
     51	atu_reg_write(pcie_ecam, index, lower_32_bits(cpu_addr),
     52		      PCIE_ATU_LOWER_BASE);
     53	atu_reg_write(pcie_ecam, index, upper_32_bits(cpu_addr),
     54		      PCIE_ATU_UPPER_BASE);
     55	atu_reg_write(pcie_ecam, index, lower_32_bits(pci_addr),
     56		      PCIE_ATU_LOWER_TARGET);
     57	atu_reg_write(pcie_ecam, index, lower_32_bits(cpu_addr + size - 1),
     58		      PCIE_ATU_LIMIT);
     59	atu_reg_write(pcie_ecam, index, upper_32_bits(pci_addr),
     60		      PCIE_ATU_UPPER_TARGET);
     61	atu_reg_write(pcie_ecam, index, type, PCIE_ATU_CR1);
     62	atu_reg_write(pcie_ecam, index, PCIE_ATU_ENABLE, PCIE_ATU_CR2);
     63}
     64
     65static void __iomem *tegra194_map_bus(struct pci_bus *bus,
     66				      unsigned int devfn, int where)
     67{
     68	struct pci_config_window *cfg = bus->sysdata;
     69	struct tegra194_pcie_ecam *pcie_ecam = cfg->priv;
     70	u32 busdev;
     71	int type;
     72
     73	if (bus->number < cfg->busr.start || bus->number > cfg->busr.end)
     74		return NULL;
     75
     76	if (bus->number == cfg->busr.start) {
     77		if (PCI_SLOT(devfn) == 0)
     78			return pcie_ecam->dbi_base + where;
     79		else
     80			return NULL;
     81	}
     82
     83	busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) |
     84		 PCIE_ATU_FUNC(PCI_FUNC(devfn));
     85
     86	if (bus->parent->number == cfg->busr.start) {
     87		if (PCI_SLOT(devfn) == 0)
     88			type = PCIE_ATU_TYPE_CFG0;
     89		else
     90			return NULL;
     91	} else {
     92		type = PCIE_ATU_TYPE_CFG1;
     93	}
     94
     95	program_outbound_atu(pcie_ecam, 0, type, cfg->res.start, busdev,
     96			     SZ_256K);
     97
     98	return pcie_ecam->config_base + where;
     99}
    100
    101const struct pci_ecam_ops tegra194_pcie_ops = {
    102	.init		= tegra194_acpi_init,
    103	.pci_ops	= {
    104		.map_bus	= tegra194_map_bus,
    105		.read		= pci_generic_config_read,
    106		.write		= pci_generic_config_write,
    107	}
    108};