| Bjorn Helgaas | 8cfab3c | 2018-01-26 12:50:27 -0600 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0 | 
| Minghuan Lian | 62d0ff83 | 2014-11-05 16:45:11 +0800 | [diff] [blame] | 2 | /* | 
 | 3 |  * PCIe host controller driver for Freescale Layerscape SoCs | 
 | 4 |  * | 
 | 5 |  * Copyright (C) 2014 Freescale Semiconductor. | 
 | 6 |  * | 
| Minghuan Lian | 5192ec7 | 2015-10-16 15:19:19 +0800 | [diff] [blame] | 7 |  * Author: Minghuan Lian <Minghuan.Lian@freescale.com> | 
| Minghuan Lian | 62d0ff83 | 2014-11-05 16:45:11 +0800 | [diff] [blame] | 8 |  */ | 
 | 9 |  | 
 | 10 | #include <linux/kernel.h> | 
| Minghuan Lian | 62d0ff83 | 2014-11-05 16:45:11 +0800 | [diff] [blame] | 11 | #include <linux/interrupt.h> | 
| Paul Gortmaker | 154fb60 | 2016-07-02 19:13:27 -0400 | [diff] [blame] | 12 | #include <linux/init.h> | 
| Minghuan Lian | 62d0ff83 | 2014-11-05 16:45:11 +0800 | [diff] [blame] | 13 | #include <linux/of_pci.h> | 
 | 14 | #include <linux/of_platform.h> | 
 | 15 | #include <linux/of_irq.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 | /* PEX1/2 Misc Ports Status Register */ | 
 | 26 | #define SCFG_PEXMSCPORTSR(pex_idx)	(0x94 + (pex_idx) * 4) | 
 | 27 | #define LTSSM_STATE_SHIFT	20 | 
 | 28 | #define LTSSM_STATE_MASK	0x3f | 
 | 29 | #define LTSSM_PCIE_L0		0x11 /* L0 state */ | 
 | 30 |  | 
| Minghuan Lian | 5192ec7 | 2015-10-16 15:19:19 +0800 | [diff] [blame] | 31 | /* PEX Internal Configuration Registers */ | 
 | 32 | #define PCIE_STRFMR1		0x71c /* Symbol Timer & Filter Mask Register1 */ | 
| Minghuan Lian | 84d897d | 2017-10-12 17:44:48 +0800 | [diff] [blame] | 33 | #define PCIE_ABSERR		0x8d0 /* Bridge Slave Error Response Register */ | 
 | 34 | #define PCIE_ABSERR_SETTING	0x9401 /* Forward error of non-posted request */ | 
| Minghuan Lian | 5192ec7 | 2015-10-16 15:19:19 +0800 | [diff] [blame] | 35 |  | 
| Hou Zhiqiang | 4a2745d | 2017-08-28 18:52:58 +0800 | [diff] [blame] | 36 | #define PCIE_IATU_NUM		6 | 
 | 37 |  | 
| Minghuan Lian | d646334 | 2015-10-16 15:19:17 +0800 | [diff] [blame] | 38 | struct ls_pcie_drvdata { | 
| Minghuan Lian | 5192ec7 | 2015-10-16 15:19:19 +0800 | [diff] [blame] | 39 | 	u32 lut_offset; | 
 | 40 | 	u32 ltssm_shift; | 
| Mingkai Hu | 1d77040 | 2016-10-25 20:36:56 +0800 | [diff] [blame] | 41 | 	u32 lut_dbg; | 
| Jisheng Zhang | 4ab2e7c | 2017-06-05 16:53:46 +0800 | [diff] [blame] | 42 | 	const struct dw_pcie_host_ops *ops; | 
| Kishon Vijay Abraham I | 442ec4c | 2017-02-15 18:48:14 +0530 | [diff] [blame] | 43 | 	const struct dw_pcie_ops *dw_pcie_ops; | 
| Minghuan Lian | d646334 | 2015-10-16 15:19:17 +0800 | [diff] [blame] | 44 | }; | 
 | 45 |  | 
| Minghuan Lian | 62d0ff83 | 2014-11-05 16:45:11 +0800 | [diff] [blame] | 46 | struct ls_pcie { | 
| Kishon Vijay Abraham I | 442ec4c | 2017-02-15 18:48:14 +0530 | [diff] [blame] | 47 | 	struct dw_pcie *pci; | 
| Minghuan Lian | 5192ec7 | 2015-10-16 15:19:19 +0800 | [diff] [blame] | 48 | 	void __iomem *lut; | 
| Minghuan Lian | 62d0ff83 | 2014-11-05 16:45:11 +0800 | [diff] [blame] | 49 | 	struct regmap *scfg; | 
| Minghuan Lian | d646334 | 2015-10-16 15:19:17 +0800 | [diff] [blame] | 50 | 	const struct ls_pcie_drvdata *drvdata; | 
| Minghuan Lian | 62d0ff83 | 2014-11-05 16:45:11 +0800 | [diff] [blame] | 51 | 	int index; | 
| Minghuan Lian | 62d0ff83 | 2014-11-05 16:45:11 +0800 | [diff] [blame] | 52 | }; | 
 | 53 |  | 
| Kishon Vijay Abraham I | 442ec4c | 2017-02-15 18:48:14 +0530 | [diff] [blame] | 54 | #define to_ls_pcie(x)	dev_get_drvdata((x)->dev) | 
| Minghuan Lian | 62d0ff83 | 2014-11-05 16:45:11 +0800 | [diff] [blame] | 55 |  | 
| Minghuan Lian | 7af4ce3 | 2015-10-16 15:19:16 +0800 | [diff] [blame] | 56 | static bool ls_pcie_is_bridge(struct ls_pcie *pcie) | 
 | 57 | { | 
| Kishon Vijay Abraham I | 442ec4c | 2017-02-15 18:48:14 +0530 | [diff] [blame] | 58 | 	struct dw_pcie *pci = pcie->pci; | 
| Minghuan Lian | 7af4ce3 | 2015-10-16 15:19:16 +0800 | [diff] [blame] | 59 | 	u32 header_type; | 
 | 60 |  | 
| Kishon Vijay Abraham I | 442ec4c | 2017-02-15 18:48:14 +0530 | [diff] [blame] | 61 | 	header_type = ioread8(pci->dbi_base + PCI_HEADER_TYPE); | 
| Minghuan Lian | 7af4ce3 | 2015-10-16 15:19:16 +0800 | [diff] [blame] | 62 | 	header_type &= 0x7f; | 
 | 63 |  | 
 | 64 | 	return header_type == PCI_HEADER_TYPE_BRIDGE; | 
 | 65 | } | 
 | 66 |  | 
| Minghuan Lian | 5192ec7 | 2015-10-16 15:19:19 +0800 | [diff] [blame] | 67 | /* Clear multi-function bit */ | 
 | 68 | static void ls_pcie_clear_multifunction(struct ls_pcie *pcie) | 
 | 69 | { | 
| Kishon Vijay Abraham I | 442ec4c | 2017-02-15 18:48:14 +0530 | [diff] [blame] | 70 | 	struct dw_pcie *pci = pcie->pci; | 
 | 71 |  | 
 | 72 | 	iowrite8(PCI_HEADER_TYPE_BRIDGE, pci->dbi_base + PCI_HEADER_TYPE); | 
| Minghuan Lian | 5192ec7 | 2015-10-16 15:19:19 +0800 | [diff] [blame] | 73 | } | 
 | 74 |  | 
| Minghuan Lian | 1195c10 | 2016-02-29 17:24:15 -0600 | [diff] [blame] | 75 | /* Drop MSG TLP except for Vendor MSG */ | 
 | 76 | static void ls_pcie_drop_msg_tlp(struct ls_pcie *pcie) | 
 | 77 | { | 
 | 78 | 	u32 val; | 
| Kishon Vijay Abraham I | 442ec4c | 2017-02-15 18:48:14 +0530 | [diff] [blame] | 79 | 	struct dw_pcie *pci = pcie->pci; | 
| Minghuan Lian | 1195c10 | 2016-02-29 17:24:15 -0600 | [diff] [blame] | 80 |  | 
| Kishon Vijay Abraham I | 442ec4c | 2017-02-15 18:48:14 +0530 | [diff] [blame] | 81 | 	val = ioread32(pci->dbi_base + PCIE_STRFMR1); | 
| Minghuan Lian | 1195c10 | 2016-02-29 17:24:15 -0600 | [diff] [blame] | 82 | 	val &= 0xDFFFFFFF; | 
| Kishon Vijay Abraham I | 442ec4c | 2017-02-15 18:48:14 +0530 | [diff] [blame] | 83 | 	iowrite32(val, pci->dbi_base + PCIE_STRFMR1); | 
| Minghuan Lian | 1195c10 | 2016-02-29 17:24:15 -0600 | [diff] [blame] | 84 | } | 
 | 85 |  | 
| Hou Zhiqiang | 4a2745d | 2017-08-28 18:52:58 +0800 | [diff] [blame] | 86 | static void ls_pcie_disable_outbound_atus(struct ls_pcie *pcie) | 
 | 87 | { | 
 | 88 | 	int i; | 
 | 89 |  | 
 | 90 | 	for (i = 0; i < PCIE_IATU_NUM; i++) | 
 | 91 | 		dw_pcie_disable_atu(pcie->pci, DW_PCIE_REGION_OUTBOUND, i); | 
 | 92 | } | 
 | 93 |  | 
| Kishon Vijay Abraham I | 442ec4c | 2017-02-15 18:48:14 +0530 | [diff] [blame] | 94 | static int ls1021_pcie_link_up(struct dw_pcie *pci) | 
| Minghuan Lian | 62d0ff83 | 2014-11-05 16:45:11 +0800 | [diff] [blame] | 95 | { | 
 | 96 | 	u32 state; | 
| Kishon Vijay Abraham I | 442ec4c | 2017-02-15 18:48:14 +0530 | [diff] [blame] | 97 | 	struct ls_pcie *pcie = to_ls_pcie(pci); | 
| Minghuan Lian | 62d0ff83 | 2014-11-05 16:45:11 +0800 | [diff] [blame] | 98 |  | 
| Minghuan Lian | d646334 | 2015-10-16 15:19:17 +0800 | [diff] [blame] | 99 | 	if (!pcie->scfg) | 
 | 100 | 		return 0; | 
 | 101 |  | 
| Minghuan Lian | 62d0ff83 | 2014-11-05 16:45:11 +0800 | [diff] [blame] | 102 | 	regmap_read(pcie->scfg, SCFG_PEXMSCPORTSR(pcie->index), &state); | 
 | 103 | 	state = (state >> LTSSM_STATE_SHIFT) & LTSSM_STATE_MASK; | 
 | 104 |  | 
 | 105 | 	if (state < LTSSM_PCIE_L0) | 
 | 106 | 		return 0; | 
 | 107 |  | 
 | 108 | 	return 1; | 
 | 109 | } | 
 | 110 |  | 
| Hou Zhiqiang | ba95a82 | 2017-08-28 18:52:56 +0800 | [diff] [blame] | 111 | static int ls_pcie_link_up(struct dw_pcie *pci) | 
 | 112 | { | 
 | 113 | 	struct ls_pcie *pcie = to_ls_pcie(pci); | 
 | 114 | 	u32 state; | 
 | 115 |  | 
 | 116 | 	state = (ioread32(pcie->lut + pcie->drvdata->lut_dbg) >> | 
 | 117 | 		 pcie->drvdata->ltssm_shift) & | 
 | 118 | 		 LTSSM_STATE_MASK; | 
 | 119 |  | 
 | 120 | 	if (state < LTSSM_PCIE_L0) | 
 | 121 | 		return 0; | 
 | 122 |  | 
 | 123 | 	return 1; | 
 | 124 | } | 
 | 125 |  | 
| Minghuan Lian | 84d897d | 2017-10-12 17:44:48 +0800 | [diff] [blame] | 126 | /* Forward error response of outbound non-posted requests */ | 
 | 127 | static void ls_pcie_fix_error_response(struct ls_pcie *pcie) | 
 | 128 | { | 
 | 129 | 	struct dw_pcie *pci = pcie->pci; | 
 | 130 |  | 
 | 131 | 	iowrite32(PCIE_ABSERR_SETTING, pci->dbi_base + PCIE_ABSERR); | 
 | 132 | } | 
 | 133 |  | 
| Hou Zhiqiang | ba95a82 | 2017-08-28 18:52:56 +0800 | [diff] [blame] | 134 | static int ls_pcie_host_init(struct pcie_port *pp) | 
 | 135 | { | 
 | 136 | 	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); | 
 | 137 | 	struct ls_pcie *pcie = to_ls_pcie(pci); | 
 | 138 |  | 
| Hou Zhiqiang | 4a2745d | 2017-08-28 18:52:58 +0800 | [diff] [blame] | 139 | 	/* | 
 | 140 | 	 * Disable outbound windows configured by the bootloader to avoid | 
 | 141 | 	 * one transaction hitting multiple outbound windows. | 
 | 142 | 	 * dw_pcie_setup_rc() will reconfigure the outbound windows. | 
 | 143 | 	 */ | 
 | 144 | 	ls_pcie_disable_outbound_atus(pcie); | 
| Minghuan Lian | 84d897d | 2017-10-12 17:44:48 +0800 | [diff] [blame] | 145 | 	ls_pcie_fix_error_response(pcie); | 
| Hou Zhiqiang | 4a2745d | 2017-08-28 18:52:58 +0800 | [diff] [blame] | 146 |  | 
| Hou Zhiqiang | e44abfe | 2017-08-28 18:52:59 +0800 | [diff] [blame] | 147 | 	dw_pcie_dbi_ro_wr_en(pci); | 
| Hou Zhiqiang | ba95a82 | 2017-08-28 18:52:56 +0800 | [diff] [blame] | 148 | 	ls_pcie_clear_multifunction(pcie); | 
| Hou Zhiqiang | e44abfe | 2017-08-28 18:52:59 +0800 | [diff] [blame] | 149 | 	dw_pcie_dbi_ro_wr_dis(pci); | 
| Hou Zhiqiang | ba95a82 | 2017-08-28 18:52:56 +0800 | [diff] [blame] | 150 |  | 
 | 151 | 	ls_pcie_drop_msg_tlp(pcie); | 
 | 152 |  | 
 | 153 | 	dw_pcie_setup_rc(pp); | 
 | 154 |  | 
 | 155 | 	return 0; | 
 | 156 | } | 
 | 157 |  | 
| Bjorn Andersson | 4a30176 | 2017-07-15 23:39:45 -0700 | [diff] [blame] | 158 | static int ls1021_pcie_host_init(struct pcie_port *pp) | 
| Bjorn Helgaas | 1d3f9ba | 2015-06-02 16:24:25 -0500 | [diff] [blame] | 159 | { | 
| Kishon Vijay Abraham I | 442ec4c | 2017-02-15 18:48:14 +0530 | [diff] [blame] | 160 | 	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); | 
 | 161 | 	struct ls_pcie *pcie = to_ls_pcie(pci); | 
 | 162 | 	struct device *dev = pci->dev; | 
| Minghuan Lian | 1195c10 | 2016-02-29 17:24:15 -0600 | [diff] [blame] | 163 | 	u32 index[2]; | 
| Bjorn Andersson | 4a30176 | 2017-07-15 23:39:45 -0700 | [diff] [blame] | 164 | 	int ret; | 
| Minghuan Lian | d646334 | 2015-10-16 15:19:17 +0800 | [diff] [blame] | 165 |  | 
| Bjorn Helgaas | c11125e | 2016-10-06 13:38:05 -0500 | [diff] [blame] | 166 | 	pcie->scfg = syscon_regmap_lookup_by_phandle(dev->of_node, | 
| Minghuan Lian | d646334 | 2015-10-16 15:19:17 +0800 | [diff] [blame] | 167 | 						     "fsl,pcie-scfg"); | 
 | 168 | 	if (IS_ERR(pcie->scfg)) { | 
| Bjorn Andersson | 4a30176 | 2017-07-15 23:39:45 -0700 | [diff] [blame] | 169 | 		ret = PTR_ERR(pcie->scfg); | 
| Bjorn Helgaas | c11125e | 2016-10-06 13:38:05 -0500 | [diff] [blame] | 170 | 		dev_err(dev, "No syscfg phandle specified\n"); | 
| Minghuan Lian | d646334 | 2015-10-16 15:19:17 +0800 | [diff] [blame] | 171 | 		pcie->scfg = NULL; | 
| Bjorn Andersson | 4a30176 | 2017-07-15 23:39:45 -0700 | [diff] [blame] | 172 | 		return ret; | 
| Minghuan Lian | d646334 | 2015-10-16 15:19:17 +0800 | [diff] [blame] | 173 | 	} | 
 | 174 |  | 
| Bjorn Helgaas | c11125e | 2016-10-06 13:38:05 -0500 | [diff] [blame] | 175 | 	if (of_property_read_u32_array(dev->of_node, | 
| Minghuan Lian | d646334 | 2015-10-16 15:19:17 +0800 | [diff] [blame] | 176 | 				       "fsl,pcie-scfg", index, 2)) { | 
 | 177 | 		pcie->scfg = NULL; | 
| Bjorn Andersson | 4a30176 | 2017-07-15 23:39:45 -0700 | [diff] [blame] | 178 | 		return -EINVAL; | 
| Minghuan Lian | d646334 | 2015-10-16 15:19:17 +0800 | [diff] [blame] | 179 | 	} | 
 | 180 | 	pcie->index = index[1]; | 
| Bjorn Helgaas | 1d3f9ba | 2015-06-02 16:24:25 -0500 | [diff] [blame] | 181 |  | 
| Hou Zhiqiang | fa92dba | 2017-08-28 18:52:57 +0800 | [diff] [blame] | 182 | 	return ls_pcie_host_init(pp); | 
| Minghuan Lian | 62d0ff83 | 2014-11-05 16:45:11 +0800 | [diff] [blame] | 183 | } | 
 | 184 |  | 
| Gustavo Pimentel | 3f43ccc | 2018-03-06 11:54:54 +0000 | [diff] [blame] | 185 | static int ls_pcie_msi_host_init(struct pcie_port *pp) | 
| Minghuan Lian | bd33b87 | 2015-10-16 15:19:20 +0800 | [diff] [blame] | 186 | { | 
| Kishon Vijay Abraham I | 442ec4c | 2017-02-15 18:48:14 +0530 | [diff] [blame] | 187 | 	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); | 
 | 188 | 	struct device *dev = pci->dev; | 
| Bjorn Helgaas | c11125e | 2016-10-06 13:38:05 -0500 | [diff] [blame] | 189 | 	struct device_node *np = dev->of_node; | 
| Minghuan Lian | bd33b87 | 2015-10-16 15:19:20 +0800 | [diff] [blame] | 190 | 	struct device_node *msi_node; | 
| Minghuan Lian | bd33b87 | 2015-10-16 15:19:20 +0800 | [diff] [blame] | 191 |  | 
 | 192 | 	/* | 
 | 193 | 	 * The MSI domain is set by the generic of_msi_configure().  This | 
 | 194 | 	 * .msi_host_init() function keeps us from doing the default MSI | 
 | 195 | 	 * domain setup in dw_pcie_host_init() and also enforces the | 
 | 196 | 	 * requirement that "msi-parent" exists. | 
 | 197 | 	 */ | 
 | 198 | 	msi_node = of_parse_phandle(np, "msi-parent", 0); | 
 | 199 | 	if (!msi_node) { | 
| Bjorn Helgaas | c11125e | 2016-10-06 13:38:05 -0500 | [diff] [blame] | 200 | 		dev_err(dev, "failed to find msi-parent\n"); | 
| Minghuan Lian | bd33b87 | 2015-10-16 15:19:20 +0800 | [diff] [blame] | 201 | 		return -EINVAL; | 
 | 202 | 	} | 
 | 203 |  | 
 | 204 | 	return 0; | 
 | 205 | } | 
 | 206 |  | 
| Jisheng Zhang | 4ab2e7c | 2017-06-05 16:53:46 +0800 | [diff] [blame] | 207 | static const struct dw_pcie_host_ops ls1021_pcie_host_ops = { | 
| Minghuan Lian | d646334 | 2015-10-16 15:19:17 +0800 | [diff] [blame] | 208 | 	.host_init = ls1021_pcie_host_init, | 
| Minghuan Lian | bd33b87 | 2015-10-16 15:19:20 +0800 | [diff] [blame] | 209 | 	.msi_host_init = ls_pcie_msi_host_init, | 
| Minghuan Lian | 62d0ff83 | 2014-11-05 16:45:11 +0800 | [diff] [blame] | 210 | }; | 
 | 211 |  | 
| Jisheng Zhang | 4ab2e7c | 2017-06-05 16:53:46 +0800 | [diff] [blame] | 212 | static const struct dw_pcie_host_ops ls_pcie_host_ops = { | 
| Minghuan Lian | 5192ec7 | 2015-10-16 15:19:19 +0800 | [diff] [blame] | 213 | 	.host_init = ls_pcie_host_init, | 
| Minghuan Lian | bd33b87 | 2015-10-16 15:19:20 +0800 | [diff] [blame] | 214 | 	.msi_host_init = ls_pcie_msi_host_init, | 
| Minghuan Lian | 5192ec7 | 2015-10-16 15:19:19 +0800 | [diff] [blame] | 215 | }; | 
 | 216 |  | 
| Kishon Vijay Abraham I | 442ec4c | 2017-02-15 18:48:14 +0530 | [diff] [blame] | 217 | static const struct dw_pcie_ops dw_ls1021_pcie_ops = { | 
 | 218 | 	.link_up = ls1021_pcie_link_up, | 
 | 219 | }; | 
 | 220 |  | 
 | 221 | static const struct dw_pcie_ops dw_ls_pcie_ops = { | 
 | 222 | 	.link_up = ls_pcie_link_up, | 
 | 223 | }; | 
 | 224 |  | 
| Minghuan Lian | d646334 | 2015-10-16 15:19:17 +0800 | [diff] [blame] | 225 | static struct ls_pcie_drvdata ls1021_drvdata = { | 
 | 226 | 	.ops = &ls1021_pcie_host_ops, | 
| Kishon Vijay Abraham I | 442ec4c | 2017-02-15 18:48:14 +0530 | [diff] [blame] | 227 | 	.dw_pcie_ops = &dw_ls1021_pcie_ops, | 
| Minghuan Lian | d646334 | 2015-10-16 15:19:17 +0800 | [diff] [blame] | 228 | }; | 
 | 229 |  | 
| Minghuan Lian | 5192ec7 | 2015-10-16 15:19:19 +0800 | [diff] [blame] | 230 | static struct ls_pcie_drvdata ls1043_drvdata = { | 
 | 231 | 	.lut_offset = 0x10000, | 
 | 232 | 	.ltssm_shift = 24, | 
| Mingkai Hu | 1d77040 | 2016-10-25 20:36:56 +0800 | [diff] [blame] | 233 | 	.lut_dbg = 0x7fc, | 
 | 234 | 	.ops = &ls_pcie_host_ops, | 
| Kishon Vijay Abraham I | 442ec4c | 2017-02-15 18:48:14 +0530 | [diff] [blame] | 235 | 	.dw_pcie_ops = &dw_ls_pcie_ops, | 
| Mingkai Hu | 1d77040 | 2016-10-25 20:36:56 +0800 | [diff] [blame] | 236 | }; | 
 | 237 |  | 
 | 238 | static struct ls_pcie_drvdata ls1046_drvdata = { | 
 | 239 | 	.lut_offset = 0x80000, | 
 | 240 | 	.ltssm_shift = 24, | 
 | 241 | 	.lut_dbg = 0x407fc, | 
| Minghuan Lian | 5192ec7 | 2015-10-16 15:19:19 +0800 | [diff] [blame] | 242 | 	.ops = &ls_pcie_host_ops, | 
| Kishon Vijay Abraham I | 442ec4c | 2017-02-15 18:48:14 +0530 | [diff] [blame] | 243 | 	.dw_pcie_ops = &dw_ls_pcie_ops, | 
| Minghuan Lian | 5192ec7 | 2015-10-16 15:19:19 +0800 | [diff] [blame] | 244 | }; | 
 | 245 |  | 
 | 246 | static struct ls_pcie_drvdata ls2080_drvdata = { | 
 | 247 | 	.lut_offset = 0x80000, | 
 | 248 | 	.ltssm_shift = 0, | 
| Mingkai Hu | 1d77040 | 2016-10-25 20:36:56 +0800 | [diff] [blame] | 249 | 	.lut_dbg = 0x7fc, | 
| Minghuan Lian | 5192ec7 | 2015-10-16 15:19:19 +0800 | [diff] [blame] | 250 | 	.ops = &ls_pcie_host_ops, | 
| Kishon Vijay Abraham I | 442ec4c | 2017-02-15 18:48:14 +0530 | [diff] [blame] | 251 | 	.dw_pcie_ops = &dw_ls_pcie_ops, | 
| Minghuan Lian | 5192ec7 | 2015-10-16 15:19:19 +0800 | [diff] [blame] | 252 | }; | 
 | 253 |  | 
| Hou Zhiqiang | 8f89357 | 2017-08-04 14:41:33 +0800 | [diff] [blame] | 254 | static struct ls_pcie_drvdata ls2088_drvdata = { | 
 | 255 | 	.lut_offset = 0x80000, | 
 | 256 | 	.ltssm_shift = 0, | 
 | 257 | 	.lut_dbg = 0x407fc, | 
 | 258 | 	.ops = &ls_pcie_host_ops, | 
 | 259 | 	.dw_pcie_ops = &dw_ls_pcie_ops, | 
 | 260 | }; | 
 | 261 |  | 
| Minghuan Lian | d646334 | 2015-10-16 15:19:17 +0800 | [diff] [blame] | 262 | static const struct of_device_id ls_pcie_of_match[] = { | 
| Hou Zhiqiang | a335b12 | 2017-09-19 17:26:56 +0800 | [diff] [blame] | 263 | 	{ .compatible = "fsl,ls1012a-pcie", .data = &ls1046_drvdata }, | 
| Minghuan Lian | d646334 | 2015-10-16 15:19:17 +0800 | [diff] [blame] | 264 | 	{ .compatible = "fsl,ls1021a-pcie", .data = &ls1021_drvdata }, | 
| Minghuan Lian | 5192ec7 | 2015-10-16 15:19:19 +0800 | [diff] [blame] | 265 | 	{ .compatible = "fsl,ls1043a-pcie", .data = &ls1043_drvdata }, | 
| Mingkai Hu | 1d77040 | 2016-10-25 20:36:56 +0800 | [diff] [blame] | 266 | 	{ .compatible = "fsl,ls1046a-pcie", .data = &ls1046_drvdata }, | 
| Minghuan Lian | 5192ec7 | 2015-10-16 15:19:19 +0800 | [diff] [blame] | 267 | 	{ .compatible = "fsl,ls2080a-pcie", .data = &ls2080_drvdata }, | 
| Yang Shi | dbae40b | 2016-01-27 09:32:05 -0800 | [diff] [blame] | 268 | 	{ .compatible = "fsl,ls2085a-pcie", .data = &ls2080_drvdata }, | 
| Hou Zhiqiang | 8f89357 | 2017-08-04 14:41:33 +0800 | [diff] [blame] | 269 | 	{ .compatible = "fsl,ls2088a-pcie", .data = &ls2088_drvdata }, | 
| Hou Zhiqiang | 03fc613 | 2017-08-04 14:41:34 +0800 | [diff] [blame] | 270 | 	{ .compatible = "fsl,ls1088a-pcie", .data = &ls2088_drvdata }, | 
| Minghuan Lian | d646334 | 2015-10-16 15:19:17 +0800 | [diff] [blame] | 271 | 	{ }, | 
 | 272 | }; | 
| Minghuan Lian | d646334 | 2015-10-16 15:19:17 +0800 | [diff] [blame] | 273 |  | 
| Bjorn Helgaas | 4726a82 | 2016-10-06 13:38:06 -0500 | [diff] [blame] | 274 | static int __init ls_add_pcie_port(struct ls_pcie *pcie) | 
| Minghuan Lian | 62d0ff83 | 2014-11-05 16:45:11 +0800 | [diff] [blame] | 275 | { | 
| Kishon Vijay Abraham I | 442ec4c | 2017-02-15 18:48:14 +0530 | [diff] [blame] | 276 | 	struct dw_pcie *pci = pcie->pci; | 
 | 277 | 	struct pcie_port *pp = &pci->pp; | 
 | 278 | 	struct device *dev = pci->dev; | 
| Minghuan Lian | 62d0ff83 | 2014-11-05 16:45:11 +0800 | [diff] [blame] | 279 | 	int ret; | 
 | 280 |  | 
| Kishon Vijay Abraham I | 442ec4c | 2017-02-15 18:48:14 +0530 | [diff] [blame] | 281 | 	pp->ops = pcie->drvdata->ops; | 
 | 282 |  | 
| Minghuan Lian | 62d0ff83 | 2014-11-05 16:45:11 +0800 | [diff] [blame] | 283 | 	ret = dw_pcie_host_init(pp); | 
 | 284 | 	if (ret) { | 
| Bjorn Helgaas | c11125e | 2016-10-06 13:38:05 -0500 | [diff] [blame] | 285 | 		dev_err(dev, "failed to initialize host\n"); | 
| Minghuan Lian | 62d0ff83 | 2014-11-05 16:45:11 +0800 | [diff] [blame] | 286 | 		return ret; | 
 | 287 | 	} | 
 | 288 |  | 
 | 289 | 	return 0; | 
 | 290 | } | 
 | 291 |  | 
 | 292 | static int __init ls_pcie_probe(struct platform_device *pdev) | 
 | 293 | { | 
| Bjorn Helgaas | c11125e | 2016-10-06 13:38:05 -0500 | [diff] [blame] | 294 | 	struct device *dev = &pdev->dev; | 
| Kishon Vijay Abraham I | 442ec4c | 2017-02-15 18:48:14 +0530 | [diff] [blame] | 295 | 	struct dw_pcie *pci; | 
| Minghuan Lian | 62d0ff83 | 2014-11-05 16:45:11 +0800 | [diff] [blame] | 296 | 	struct ls_pcie *pcie; | 
 | 297 | 	struct resource *dbi_base; | 
| Minghuan Lian | 62d0ff83 | 2014-11-05 16:45:11 +0800 | [diff] [blame] | 298 | 	int ret; | 
 | 299 |  | 
| Bjorn Helgaas | c11125e | 2016-10-06 13:38:05 -0500 | [diff] [blame] | 300 | 	pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); | 
| Minghuan Lian | 62d0ff83 | 2014-11-05 16:45:11 +0800 | [diff] [blame] | 301 | 	if (!pcie) | 
 | 302 | 		return -ENOMEM; | 
 | 303 |  | 
| Kishon Vijay Abraham I | 442ec4c | 2017-02-15 18:48:14 +0530 | [diff] [blame] | 304 | 	pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); | 
 | 305 | 	if (!pci) | 
 | 306 | 		return -ENOMEM; | 
 | 307 |  | 
| Bjorn Helgaas | 6dc2c04 | 2017-01-31 16:36:11 -0600 | [diff] [blame] | 308 | 	pcie->drvdata = of_device_get_match_data(dev); | 
| Kishon Vijay Abraham I | 442ec4c | 2017-02-15 18:48:14 +0530 | [diff] [blame] | 309 |  | 
 | 310 | 	pci->dev = dev; | 
 | 311 | 	pci->ops = pcie->drvdata->dw_pcie_ops; | 
| Bjorn Helgaas | fefe673 | 2016-10-06 13:38:06 -0500 | [diff] [blame] | 312 |  | 
| Guenter Roeck | c046406 | 2017-02-25 02:08:12 -0800 | [diff] [blame] | 313 | 	pcie->pci = pci; | 
 | 314 |  | 
| Minghuan Lian | 62d0ff83 | 2014-11-05 16:45:11 +0800 | [diff] [blame] | 315 | 	dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); | 
| Lorenzo Pieralisi | 01bd489 | 2017-04-19 17:49:08 +0100 | [diff] [blame] | 316 | 	pci->dbi_base = devm_pci_remap_cfg_resource(dev, dbi_base); | 
| Kishon Vijay Abraham I | 442ec4c | 2017-02-15 18:48:14 +0530 | [diff] [blame] | 317 | 	if (IS_ERR(pci->dbi_base)) | 
 | 318 | 		return PTR_ERR(pci->dbi_base); | 
| Minghuan Lian | 62d0ff83 | 2014-11-05 16:45:11 +0800 | [diff] [blame] | 319 |  | 
| Kishon Vijay Abraham I | 442ec4c | 2017-02-15 18:48:14 +0530 | [diff] [blame] | 320 | 	pcie->lut = pci->dbi_base + pcie->drvdata->lut_offset; | 
| Minghuan Lian | 62d0ff83 | 2014-11-05 16:45:11 +0800 | [diff] [blame] | 321 |  | 
| Minghuan Lian | 7af4ce3 | 2015-10-16 15:19:16 +0800 | [diff] [blame] | 322 | 	if (!ls_pcie_is_bridge(pcie)) | 
 | 323 | 		return -ENODEV; | 
 | 324 |  | 
| Kishon Vijay Abraham I | 9bcf0a6 | 2017-02-15 18:48:11 +0530 | [diff] [blame] | 325 | 	platform_set_drvdata(pdev, pcie); | 
 | 326 |  | 
| Bjorn Helgaas | 4726a82 | 2016-10-06 13:38:06 -0500 | [diff] [blame] | 327 | 	ret = ls_add_pcie_port(pcie); | 
| Minghuan Lian | 62d0ff83 | 2014-11-05 16:45:11 +0800 | [diff] [blame] | 328 | 	if (ret < 0) | 
 | 329 | 		return ret; | 
 | 330 |  | 
| Minghuan Lian | 62d0ff83 | 2014-11-05 16:45:11 +0800 | [diff] [blame] | 331 | 	return 0; | 
 | 332 | } | 
 | 333 |  | 
| Minghuan Lian | 62d0ff83 | 2014-11-05 16:45:11 +0800 | [diff] [blame] | 334 | static struct platform_driver ls_pcie_driver = { | 
 | 335 | 	.driver = { | 
 | 336 | 		.name = "layerscape-pcie", | 
| Minghuan Lian | 62d0ff83 | 2014-11-05 16:45:11 +0800 | [diff] [blame] | 337 | 		.of_match_table = ls_pcie_of_match, | 
| Brian Norris | a5f40e8 | 2017-04-20 15:36:25 -0500 | [diff] [blame] | 338 | 		.suppress_bind_attrs = true, | 
| Minghuan Lian | 62d0ff83 | 2014-11-05 16:45:11 +0800 | [diff] [blame] | 339 | 	}, | 
 | 340 | }; | 
| Paul Gortmaker | 154fb60 | 2016-07-02 19:13:27 -0400 | [diff] [blame] | 341 | builtin_platform_driver_probe(ls_pcie_driver, ls_pcie_probe); |