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-designware-plat.c (4507B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * PCIe RC driver for Synopsys DesignWare Core
      4 *
      5 * Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
      6 *
      7 * Authors: Joao Pinto <Joao.Pinto@synopsys.com>
      8 */
      9#include <linux/clk.h>
     10#include <linux/delay.h>
     11#include <linux/gpio.h>
     12#include <linux/interrupt.h>
     13#include <linux/kernel.h>
     14#include <linux/init.h>
     15#include <linux/of_device.h>
     16#include <linux/pci.h>
     17#include <linux/platform_device.h>
     18#include <linux/resource.h>
     19#include <linux/types.h>
     20#include <linux/regmap.h>
     21
     22#include "pcie-designware.h"
     23
     24struct dw_plat_pcie {
     25	struct dw_pcie			*pci;
     26	struct regmap			*regmap;
     27	enum dw_pcie_device_mode	mode;
     28};
     29
     30struct dw_plat_pcie_of_data {
     31	enum dw_pcie_device_mode	mode;
     32};
     33
     34static const struct of_device_id dw_plat_pcie_of_match[];
     35
     36static const struct dw_pcie_host_ops dw_plat_pcie_host_ops = {
     37};
     38
     39static int dw_plat_pcie_establish_link(struct dw_pcie *pci)
     40{
     41	return 0;
     42}
     43
     44static const struct dw_pcie_ops dw_pcie_ops = {
     45	.start_link = dw_plat_pcie_establish_link,
     46};
     47
     48static void dw_plat_pcie_ep_init(struct dw_pcie_ep *ep)
     49{
     50	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
     51	enum pci_barno bar;
     52
     53	for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)
     54		dw_pcie_ep_reset_bar(pci, bar);
     55}
     56
     57static int dw_plat_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
     58				     enum pci_epc_irq_type type,
     59				     u16 interrupt_num)
     60{
     61	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
     62
     63	switch (type) {
     64	case PCI_EPC_IRQ_LEGACY:
     65		return dw_pcie_ep_raise_legacy_irq(ep, func_no);
     66	case PCI_EPC_IRQ_MSI:
     67		return dw_pcie_ep_raise_msi_irq(ep, func_no, interrupt_num);
     68	case PCI_EPC_IRQ_MSIX:
     69		return dw_pcie_ep_raise_msix_irq(ep, func_no, interrupt_num);
     70	default:
     71		dev_err(pci->dev, "UNKNOWN IRQ type\n");
     72	}
     73
     74	return 0;
     75}
     76
     77static const struct pci_epc_features dw_plat_pcie_epc_features = {
     78	.linkup_notifier = false,
     79	.msi_capable = true,
     80	.msix_capable = true,
     81};
     82
     83static const struct pci_epc_features*
     84dw_plat_pcie_get_features(struct dw_pcie_ep *ep)
     85{
     86	return &dw_plat_pcie_epc_features;
     87}
     88
     89static const struct dw_pcie_ep_ops pcie_ep_ops = {
     90	.ep_init = dw_plat_pcie_ep_init,
     91	.raise_irq = dw_plat_pcie_ep_raise_irq,
     92	.get_features = dw_plat_pcie_get_features,
     93};
     94
     95static int dw_plat_add_pcie_port(struct dw_plat_pcie *dw_plat_pcie,
     96				 struct platform_device *pdev)
     97{
     98	struct dw_pcie *pci = dw_plat_pcie->pci;
     99	struct pcie_port *pp = &pci->pp;
    100	struct device *dev = &pdev->dev;
    101	int ret;
    102
    103	pp->irq = platform_get_irq(pdev, 1);
    104	if (pp->irq < 0)
    105		return pp->irq;
    106
    107	pp->num_vectors = MAX_MSI_IRQS;
    108	pp->ops = &dw_plat_pcie_host_ops;
    109
    110	ret = dw_pcie_host_init(pp);
    111	if (ret) {
    112		dev_err(dev, "Failed to initialize host\n");
    113		return ret;
    114	}
    115
    116	return 0;
    117}
    118
    119static int dw_plat_pcie_probe(struct platform_device *pdev)
    120{
    121	struct device *dev = &pdev->dev;
    122	struct dw_plat_pcie *dw_plat_pcie;
    123	struct dw_pcie *pci;
    124	int ret;
    125	const struct dw_plat_pcie_of_data *data;
    126	enum dw_pcie_device_mode mode;
    127
    128	data = of_device_get_match_data(dev);
    129	if (!data)
    130		return -EINVAL;
    131
    132	mode = (enum dw_pcie_device_mode)data->mode;
    133
    134	dw_plat_pcie = devm_kzalloc(dev, sizeof(*dw_plat_pcie), GFP_KERNEL);
    135	if (!dw_plat_pcie)
    136		return -ENOMEM;
    137
    138	pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
    139	if (!pci)
    140		return -ENOMEM;
    141
    142	pci->dev = dev;
    143	pci->ops = &dw_pcie_ops;
    144
    145	dw_plat_pcie->pci = pci;
    146	dw_plat_pcie->mode = mode;
    147
    148	platform_set_drvdata(pdev, dw_plat_pcie);
    149
    150	switch (dw_plat_pcie->mode) {
    151	case DW_PCIE_RC_TYPE:
    152		if (!IS_ENABLED(CONFIG_PCIE_DW_PLAT_HOST))
    153			return -ENODEV;
    154
    155		ret = dw_plat_add_pcie_port(dw_plat_pcie, pdev);
    156		if (ret < 0)
    157			return ret;
    158		break;
    159	case DW_PCIE_EP_TYPE:
    160		if (!IS_ENABLED(CONFIG_PCIE_DW_PLAT_EP))
    161			return -ENODEV;
    162
    163		pci->ep.ops = &pcie_ep_ops;
    164		return dw_pcie_ep_init(&pci->ep);
    165	default:
    166		dev_err(dev, "INVALID device type %d\n", dw_plat_pcie->mode);
    167	}
    168
    169	return 0;
    170}
    171
    172static const struct dw_plat_pcie_of_data dw_plat_pcie_rc_of_data = {
    173	.mode = DW_PCIE_RC_TYPE,
    174};
    175
    176static const struct dw_plat_pcie_of_data dw_plat_pcie_ep_of_data = {
    177	.mode = DW_PCIE_EP_TYPE,
    178};
    179
    180static const struct of_device_id dw_plat_pcie_of_match[] = {
    181	{
    182		.compatible = "snps,dw-pcie",
    183		.data = &dw_plat_pcie_rc_of_data,
    184	},
    185	{
    186		.compatible = "snps,dw-pcie-ep",
    187		.data = &dw_plat_pcie_ep_of_data,
    188	},
    189	{},
    190};
    191
    192static struct platform_driver dw_plat_pcie_driver = {
    193	.driver = {
    194		.name	= "dw-pcie",
    195		.of_match_table = dw_plat_pcie_of_match,
    196		.suppress_bind_attrs = true,
    197	},
    198	.probe = dw_plat_pcie_probe,
    199};
    200builtin_platform_driver(dw_plat_pcie_driver);