Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * PCIe host controller driver for Freescale Layerscape SoCs
  4 *
  5 * Copyright (C) 2014 Freescale Semiconductor.
  6 * Copyright 2021 NXP
  7 *
  8 * Author: Minghuan Lian <Minghuan.Lian@freescale.com>
  9 */
 10
 11#include <linux/kernel.h>
 12#include <linux/interrupt.h>
 13#include <linux/init.h>
 14#include <linux/of_pci.h>
 15#include <linux/of_platform.h>
 16#include <linux/of_address.h>
 17#include <linux/pci.h>
 18#include <linux/platform_device.h>
 19#include <linux/resource.h>
 20#include <linux/mfd/syscon.h>
 21#include <linux/regmap.h>
 22
 23#include "pcie-designware.h"
 24
 25/* PEX Internal Configuration Registers */
 26#define PCIE_STRFMR1		0x71c /* Symbol Timer & Filter Mask Register1 */
 27#define PCIE_ABSERR		0x8d0 /* Bridge Slave Error Response Register */
 28#define PCIE_ABSERR_SETTING	0x9401 /* Forward error of non-posted request */
 29
 30#define PCIE_IATU_NUM		6
 31
 32struct ls_pcie {
 33	struct dw_pcie *pci;
 34};
 35
 36#define to_ls_pcie(x)	dev_get_drvdata((x)->dev)
 37
 38static bool ls_pcie_is_bridge(struct ls_pcie *pcie)
 39{
 40	struct dw_pcie *pci = pcie->pci;
 41	u32 header_type;
 42
 43	header_type = ioread8(pci->dbi_base + PCI_HEADER_TYPE);
 44	header_type &= 0x7f;
 45
 46	return header_type == PCI_HEADER_TYPE_BRIDGE;
 47}
 48
 49/* Clear multi-function bit */
 50static void ls_pcie_clear_multifunction(struct ls_pcie *pcie)
 51{
 52	struct dw_pcie *pci = pcie->pci;
 53
 54	iowrite8(PCI_HEADER_TYPE_BRIDGE, pci->dbi_base + PCI_HEADER_TYPE);
 55}
 56
 57/* Drop MSG TLP except for Vendor MSG */
 58static void ls_pcie_drop_msg_tlp(struct ls_pcie *pcie)
 59{
 60	u32 val;
 61	struct dw_pcie *pci = pcie->pci;
 62
 63	val = ioread32(pci->dbi_base + PCIE_STRFMR1);
 64	val &= 0xDFFFFFFF;
 65	iowrite32(val, pci->dbi_base + PCIE_STRFMR1);
 66}
 67
 68/* Forward error response of outbound non-posted requests */
 69static void ls_pcie_fix_error_response(struct ls_pcie *pcie)
 70{
 71	struct dw_pcie *pci = pcie->pci;
 72
 73	iowrite32(PCIE_ABSERR_SETTING, pci->dbi_base + PCIE_ABSERR);
 74}
 75
 76static int ls_pcie_host_init(struct dw_pcie_rp *pp)
 77{
 78	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
 79	struct ls_pcie *pcie = to_ls_pcie(pci);
 80
 81	ls_pcie_fix_error_response(pcie);
 82
 83	dw_pcie_dbi_ro_wr_en(pci);
 84	ls_pcie_clear_multifunction(pcie);
 85	dw_pcie_dbi_ro_wr_dis(pci);
 86
 87	ls_pcie_drop_msg_tlp(pcie);
 88
 89	return 0;
 90}
 91
 92static const struct dw_pcie_host_ops ls_pcie_host_ops = {
 93	.host_init = ls_pcie_host_init,
 94};
 95
 96static const struct of_device_id ls_pcie_of_match[] = {
 97	{ .compatible = "fsl,ls1012a-pcie", },
 98	{ .compatible = "fsl,ls1021a-pcie", },
 99	{ .compatible = "fsl,ls1028a-pcie", },
100	{ .compatible = "fsl,ls1043a-pcie", },
101	{ .compatible = "fsl,ls1046a-pcie", },
102	{ .compatible = "fsl,ls2080a-pcie", },
103	{ .compatible = "fsl,ls2085a-pcie", },
104	{ .compatible = "fsl,ls2088a-pcie", },
105	{ .compatible = "fsl,ls1088a-pcie", },
106	{ },
107};
108
109static int ls_pcie_probe(struct platform_device *pdev)
110{
111	struct device *dev = &pdev->dev;
112	struct dw_pcie *pci;
113	struct ls_pcie *pcie;
114	struct resource *dbi_base;
115
116	pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
117	if (!pcie)
118		return -ENOMEM;
119
120	pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
121	if (!pci)
122		return -ENOMEM;
123
124	pci->dev = dev;
125	pci->pp.ops = &ls_pcie_host_ops;
126
127	pcie->pci = pci;
128
129	dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
130	pci->dbi_base = devm_pci_remap_cfg_resource(dev, dbi_base);
131	if (IS_ERR(pci->dbi_base))
132		return PTR_ERR(pci->dbi_base);
133
134	if (!ls_pcie_is_bridge(pcie))
135		return -ENODEV;
136
137	platform_set_drvdata(pdev, pcie);
138
139	return dw_pcie_host_init(&pci->pp);
140}
141
142static struct platform_driver ls_pcie_driver = {
143	.probe = ls_pcie_probe,
144	.driver = {
145		.name = "layerscape-pcie",
146		.of_match_table = ls_pcie_of_match,
147		.suppress_bind_attrs = true,
148	},
149};
150builtin_platform_driver(ls_pcie_driver);