From ef4d11362e803920611230e0b83f58d16b13a317 Mon Sep 17 00:00:00 2001 From: Manikanta Maddireddy Date: Tue, 14 Mar 2023 14:57:38 +0530 Subject: [PATCH] PCI: tegra264: Move driver file to new dir t264 nvidia-t264 drivers are copied to nvidia-oot path and compile them to create out-of-the-tree driver modules. Create new directory to avoid replacing exisiting Makefile in out-of-the-tree repo. Bug 4000789 Signed-off-by: Manikanta Maddireddy Change-Id: I8040a86102b164feae6e1fd2251c69d3dc039dde Reviewed-on: https://git-master.nvidia.com/r/c/linux-t264/+/2870776 Reviewed-by: Laxman Dewangan GVS: Gerrit_Virtual_Submit --- drivers/pci/controller/private-soc/Makefile | 8 + .../controller/private-soc/pcie-tegra264.c | 231 ++++++++++++++++++ 2 files changed, 239 insertions(+) create mode 100644 drivers/pci/controller/private-soc/Makefile create mode 100644 drivers/pci/controller/private-soc/pcie-tegra264.c diff --git a/drivers/pci/controller/private-soc/Makefile b/drivers/pci/controller/private-soc/Makefile new file mode 100644 index 00000000..5f8346b9 --- /dev/null +++ b/drivers/pci/controller/private-soc/Makefile @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0 + +# Set config when build as OOT module. +ifeq ($(CONFIG_TEGRA_OOT_MODULE),m) +CONFIG_PCIE_TEGRA264 := m +endif + +obj-$(CONFIG_PCIE_TEGRA264) += pcie-tegra264.o diff --git a/drivers/pci/controller/private-soc/pcie-tegra264.c b/drivers/pci/controller/private-soc/pcie-tegra264.c new file mode 100644 index 00000000..c2886be6 --- /dev/null +++ b/drivers/pci/controller/private-soc/pcie-tegra264.c @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * PCIe host controller driver for Tegra264 SoC + * + * Copyright (c) 2022-2023, NVIDIA CORPORATION. All rights reserved. + * + * Author: Manikanta Maddireddy + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) +#include +#else +#include +#endif + +/* XAL registers */ +#define XAL_RC_MEM_32BIT_BASE_HI 0x1c +#define XAL_RC_MEM_32BIT_BASE_LO 0x20 +#define XAL_RC_MEM_32BIT_LIMIT_HI 0x24 +#define XAL_RC_MEM_32BIT_LIMIT_LO 0x28 +#define XAL_RC_MEM_64BIT_BASE_HI 0x2c +#define XAL_RC_MEM_64BIT_BASE_LO 0x30 +#define XAL_RC_MEM_64BIT_LIMIT_HI 0x34 +#define XAL_RC_MEM_64BIT_LIMIT_LO 0x38 +#define XAL_RC_BAR_CNTL_STANDARD 0x40 +#define XAL_RC_BAR_CNTL_STANDARD_IOBAR_EN BIT(0) +#define XAL_RC_BAR_CNTL_STANDARD_32B_BAR_EN BIT(1) +#define XAL_RC_BAR_CNTL_STANDARD_64B_BAR_EN BIT(2) + +/* XTL registers */ +#define XTL_RC_PCIE_CFG_LINK_CONTROL_STATUS 0x58 +#define XTL_RC_PCIE_CFG_LINK_CONTROL_STATUS_DLL_ACTIVE BIT(29) + +#define XTL_RC_MGMT_PERST_CONTROL 0x218 +#define XTL_RC_MGMT_PERST_CONTROL_PERST_O_N BIT(0) + +struct tegra264_pcie { + struct device *dev; + struct pci_config_window *cfg; + void __iomem *xal_base; + void __iomem *xtl_pri_base; + void __iomem *ecam_base; + u64 prefetch_mem_base; + u64 prefetch_mem_limit; + u64 mem_base; + u64 mem_limit; + u32 ctl_id; +}; + +static void tegra264_pcie_init(struct tegra264_pcie *pcie) +{ + u32 val; + + /* Program XAL */ + writel(upper_32_bits(pcie->mem_base), pcie->xal_base + XAL_RC_MEM_32BIT_BASE_HI); + writel(lower_32_bits(pcie->mem_base), pcie->xal_base + XAL_RC_MEM_32BIT_BASE_LO); + + writel(upper_32_bits(pcie->mem_limit), pcie->xal_base + XAL_RC_MEM_32BIT_LIMIT_HI); + writel(lower_32_bits(pcie->mem_limit), pcie->xal_base + XAL_RC_MEM_32BIT_LIMIT_LO); + + writel(upper_32_bits(pcie->prefetch_mem_base), pcie->xal_base + XAL_RC_MEM_64BIT_BASE_HI); + writel(lower_32_bits(pcie->prefetch_mem_base), pcie->xal_base + XAL_RC_MEM_64BIT_BASE_LO); + + writel(upper_32_bits(pcie->prefetch_mem_limit), pcie->xal_base + XAL_RC_MEM_64BIT_LIMIT_HI); + writel(lower_32_bits(pcie->prefetch_mem_limit), pcie->xal_base + XAL_RC_MEM_64BIT_LIMIT_LO); + + val = XAL_RC_BAR_CNTL_STANDARD_IOBAR_EN | XAL_RC_BAR_CNTL_STANDARD_32B_BAR_EN | + XAL_RC_BAR_CNTL_STANDARD_64B_BAR_EN; + writel(val, pcie->xal_base + XAL_RC_BAR_CNTL_STANDARD); + + /* Setup bus numbers */ + val = readl(pcie->ecam_base + PCI_PRIMARY_BUS); + val &= 0xff000000; + val |= 0x00ff0100; + writel(val, pcie->ecam_base + PCI_PRIMARY_BUS); + + /* Setup command register */ + val = readl(pcie->ecam_base + PCI_COMMAND); + val &= 0xffff0000; + val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_SERR; + writel(val, pcie->ecam_base + PCI_COMMAND); + + val = readl(pcie->xtl_pri_base + XTL_RC_MGMT_PERST_CONTROL); + val |= XTL_RC_MGMT_PERST_CONTROL_PERST_O_N; + writel(val, pcie->xtl_pri_base + XTL_RC_MGMT_PERST_CONTROL); +} + +static int tegra264_pcie_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct tegra264_pcie *pcie; + struct pci_host_bridge *bridge; + struct resource_entry *bus; + struct resource_entry *entry; + struct resource *res; + u32 val, count; + int ret = 0; + + bridge = devm_pci_alloc_host_bridge(dev, sizeof(struct tegra264_pcie)); + if (!bridge) { + dev_err(dev, "failed to allocate host bridge\n"); + return -ENOMEM; + } + + pcie = pci_host_bridge_priv(bridge); + pcie->dev = dev; + platform_set_drvdata(pdev, pcie); + + resource_list_for_each_entry(entry, &bridge->windows) { + struct resource *res = entry->res; + + if (resource_type(res) != IORESOURCE_MEM) + continue; + + if (res->flags & IORESOURCE_PREFETCH) { + pcie->prefetch_mem_base = res->start; + pcie->prefetch_mem_limit = res->end; + } else { + pcie->mem_base = res->start; + pcie->mem_limit = res->end; + } + } + + ret = of_get_pci_domain_nr(pcie->dev->of_node); + if (ret < 0) { + dev_err(dev, "failed to get domain number: %d\n", ret); + return ret; + } + pcie->ctl_id = ret; + + pcie->xal_base = devm_platform_ioremap_resource_byname(pdev, "xal"); + if (IS_ERR(pcie->xal_base)) { + ret = PTR_ERR(pcie->xal_base); + dev_err(dev, "failed to map xal memory: %d\n", ret); + return ret; + } + + pcie->xtl_pri_base = devm_platform_ioremap_resource_byname(pdev, "xtl-pri"); + if (IS_ERR(pcie->xtl_pri_base)) { + ret = PTR_ERR(pcie->xtl_pri_base); + dev_err(dev, "failed to map xtl-pri memory: %d\n", ret); + return ret; + } + + bus = resource_list_first_type(&bridge->windows, IORESOURCE_BUS); + if (!bus) { + dev_err(dev, "failed to get bus resource\n"); + return -ENODEV; + } + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ecam"); + if (!res) { + dev_err(dev, "failed to get ecam resource\n"); + return -ENXIO; + } + + pcie->cfg = pci_ecam_create(dev, res, bus->res, &pci_generic_ecam_ops); + if (IS_ERR(pcie->cfg)) { + dev_err(dev, "failed to create ecam config window\n"); + return PTR_ERR(pcie->cfg); + } + + bridge->ops = (struct pci_ops *)&pci_generic_ecam_ops.pci_ops; + bridge->sysdata = pcie->cfg; + pcie->ecam_base = pcie->cfg->win; + + tegra264_pcie_init(pcie); + + msleep(100); + + /* Wait for link up */ + count = 0; + do { + usleep_range(10, 20); + val = readl(pcie->ecam_base + XTL_RC_PCIE_CFG_LINK_CONTROL_STATUS); + if (val & XTL_RC_PCIE_CFG_LINK_CONTROL_STATUS_DLL_ACTIVE) { + dev_info(dev, "PCIe Controller-%d Link is UP (Speed: %d)\n", + pcie->ctl_id, (val & 0xf0000) >> 16); + break; + } + + count++; + } while (count < 10000); + + if (!(val & XTL_RC_PCIE_CFG_LINK_CONTROL_STATUS_DLL_ACTIVE)) + dev_info(dev, "PCIe Controller-%d Link is DOWN\r\n", pcie->ctl_id); + + ret = pci_host_probe(bridge); + if (ret < 0) { + dev_err(dev, "failed to register host: %d\n", ret); + pci_ecam_free(pcie->cfg); + return ret; + } + + return ret; +} + +static const struct of_device_id tegra264_pcie_of_match[] = { + { + .compatible = "nvidia,tegra264-pcie", + }, + {}, +}; + +static struct platform_driver tegra264_pcie_driver = { + .probe = tegra264_pcie_probe, + .driver = { + .name = "tegra264-pcie", + .of_match_table = tegra264_pcie_of_match, + }, +}; + +module_platform_driver(tegra264_pcie_driver); + +MODULE_DEVICE_TABLE(of, tegra264_pcie_of_match); + +MODULE_AUTHOR("Manikanta Maddireddy "); +MODULE_DESCRIPTION("NVIDIA Tegra264 PCIe host controller driver"); +MODULE_LICENSE("GPL v2");