blob: 80f604602783468bdb7f26959fd7822ca007c202 [file] [log] [blame]
Bjorn Helgaas8cfab3c2018-01-26 12:50:27 -06001// SPDX-License-Identifier: GPL-2.0
Sean Crossbb389192013-09-26 11:24:47 +08002/*
3 * PCIe host controller driver for Freescale i.MX6 SoCs
4 *
5 * Copyright (C) 2013 Kosagi
6 * http://www.kosagi.com
7 *
8 * Author: Sean Cross <xobs@kosagi.com>
Sean Crossbb389192013-09-26 11:24:47 +08009 */
10
11#include <linux/clk.h>
12#include <linux/delay.h>
13#include <linux/gpio.h>
14#include <linux/kernel.h>
15#include <linux/mfd/syscon.h>
16#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
Andrey Smirnov9b3fe672017-03-28 08:42:49 -070017#include <linux/mfd/syscon/imx7-iomuxc-gpr.h>
Sean Crossbb389192013-09-26 11:24:47 +080018#include <linux/module.h>
19#include <linux/of_gpio.h>
Andrey Smirnove6f1fef2016-05-02 14:08:21 -050020#include <linux/of_device.h>
Sean Crossbb389192013-09-26 11:24:47 +080021#include <linux/pci.h>
22#include <linux/platform_device.h>
23#include <linux/regmap.h>
Quentin Schulzc26ebe92017-06-08 10:07:42 +020024#include <linux/regulator/consumer.h>
Sean Crossbb389192013-09-26 11:24:47 +080025#include <linux/resource.h>
26#include <linux/signal.h>
27#include <linux/types.h>
Lucas Stachd1dc9742014-03-28 17:52:59 +010028#include <linux/interrupt.h>
Andrey Smirnov9b3fe672017-03-28 08:42:49 -070029#include <linux/reset.h>
Sean Crossbb389192013-09-26 11:24:47 +080030
31#include "pcie-designware.h"
32
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +053033#define to_imx6_pcie(x) dev_get_drvdata((x)->dev)
Sean Crossbb389192013-09-26 11:24:47 +080034
Andrey Smirnove6f1fef2016-05-02 14:08:21 -050035enum imx6_pcie_variants {
36 IMX6Q,
Andrey Smirnov4d31c612016-05-02 14:09:10 -050037 IMX6SX,
38 IMX6QP,
Andrey Smirnov9b3fe672017-03-28 08:42:49 -070039 IMX7D,
Andrey Smirnove6f1fef2016-05-02 14:08:21 -050040};
41
Sean Crossbb389192013-09-26 11:24:47 +080042struct imx6_pcie {
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +053043 struct dw_pcie *pci;
Fabio Estevamb2d7a9c2016-03-28 18:45:36 -030044 int reset_gpio;
Petr Štetiar3ea8529a2016-04-19 19:42:07 -050045 bool gpio_active_high;
Lucas Stach57526132014-03-28 17:52:55 +010046 struct clk *pcie_bus;
47 struct clk *pcie_phy;
Christoph Fritze3c06cd2016-04-05 16:53:27 -050048 struct clk *pcie_inbound_axi;
Lucas Stach57526132014-03-28 17:52:55 +010049 struct clk *pcie;
Sean Crossbb389192013-09-26 11:24:47 +080050 struct regmap *iomuxc_gpr;
Andrey Smirnov9b3fe672017-03-28 08:42:49 -070051 struct reset_control *pciephy_reset;
52 struct reset_control *apps_reset;
Andrey Smirnove6f1fef2016-05-02 14:08:21 -050053 enum imx6_pcie_variants variant;
Justin Waters28e3abe2016-01-15 10:24:35 -050054 u32 tx_deemph_gen1;
55 u32 tx_deemph_gen2_3p5db;
56 u32 tx_deemph_gen2_6db;
57 u32 tx_swing_full;
58 u32 tx_swing_low;
Tim Harveya5fcec42016-04-19 19:52:44 -050059 int link_gen;
Quentin Schulzc26ebe92017-06-08 10:07:42 +020060 struct regulator *vpcie;
Sean Crossbb389192013-09-26 11:24:47 +080061};
62
Andrey Smirnov9b3fe672017-03-28 08:42:49 -070063/* Parameters for the waiting for PCIe PHY PLL to lock on i.MX7 */
64#define PHY_PLL_LOCK_WAIT_MAX_RETRIES 2000
65#define PHY_PLL_LOCK_WAIT_USLEEP_MIN 50
66#define PHY_PLL_LOCK_WAIT_USLEEP_MAX 200
67
Marek Vasutfa33a6d2013-12-12 22:50:02 +010068/* PCIe Root Complex registers (memory-mapped) */
69#define PCIE_RC_LCR 0x7c
70#define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1 0x1
71#define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2 0x2
72#define PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK 0xf
73
Bjorn Helgaas2393f792015-06-12 17:27:43 -050074#define PCIE_RC_LCSR 0x80
75
Sean Crossbb389192013-09-26 11:24:47 +080076/* PCIe Port Logic registers (memory-mapped) */
77#define PL_OFFSET 0x700
Lucas Stach3e3e4062014-07-31 20:16:05 +020078#define PCIE_PL_PFLR (PL_OFFSET + 0x08)
79#define PCIE_PL_PFLR_LINK_STATE_MASK (0x3f << 16)
80#define PCIE_PL_PFLR_FORCE_LINK (1 << 15)
Sean Crossbb389192013-09-26 11:24:47 +080081#define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28)
82#define PCIE_PHY_DEBUG_R1 (PL_OFFSET + 0x2c)
Marek Vasut7f9f40c2013-12-12 22:49:59 +010083#define PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING (1 << 29)
84#define PCIE_PHY_DEBUG_R1_XMLH_LINK_UP (1 << 4)
Sean Crossbb389192013-09-26 11:24:47 +080085
86#define PCIE_PHY_CTRL (PL_OFFSET + 0x114)
87#define PCIE_PHY_CTRL_DATA_LOC 0
88#define PCIE_PHY_CTRL_CAP_ADR_LOC 16
89#define PCIE_PHY_CTRL_CAP_DAT_LOC 17
90#define PCIE_PHY_CTRL_WR_LOC 18
91#define PCIE_PHY_CTRL_RD_LOC 19
92
93#define PCIE_PHY_STAT (PL_OFFSET + 0x110)
94#define PCIE_PHY_STAT_ACK_LOC 16
95
Marek Vasutfa33a6d2013-12-12 22:50:02 +010096#define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C
97#define PORT_LOGIC_SPEED_CHANGE (0x1 << 17)
98
Sean Crossbb389192013-09-26 11:24:47 +080099/* PHY registers (not memory-mapped) */
100#define PCIE_PHY_RX_ASIC_OUT 0x100D
Fabio Estevam111feb72015-09-11 09:08:53 -0300101#define PCIE_PHY_RX_ASIC_OUT_VALID (1 << 0)
Sean Crossbb389192013-09-26 11:24:47 +0800102
103#define PHY_RX_OVRD_IN_LO 0x1005
104#define PHY_RX_OVRD_IN_LO_RX_DATA_EN (1 << 5)
105#define PHY_RX_OVRD_IN_LO_RX_PLL_EN (1 << 3)
106
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500107static int pcie_phy_poll_ack(struct imx6_pcie *imx6_pcie, int exp_val)
Sean Crossbb389192013-09-26 11:24:47 +0800108{
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530109 struct dw_pcie *pci = imx6_pcie->pci;
Sean Crossbb389192013-09-26 11:24:47 +0800110 u32 val;
111 u32 max_iterations = 10;
112 u32 wait_counter = 0;
113
114 do {
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530115 val = dw_pcie_readl_dbi(pci, PCIE_PHY_STAT);
Sean Crossbb389192013-09-26 11:24:47 +0800116 val = (val >> PCIE_PHY_STAT_ACK_LOC) & 0x1;
117 wait_counter++;
118
119 if (val == exp_val)
120 return 0;
121
122 udelay(1);
123 } while (wait_counter < max_iterations);
124
125 return -ETIMEDOUT;
126}
127
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500128static int pcie_phy_wait_ack(struct imx6_pcie *imx6_pcie, int addr)
Sean Crossbb389192013-09-26 11:24:47 +0800129{
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530130 struct dw_pcie *pci = imx6_pcie->pci;
Sean Crossbb389192013-09-26 11:24:47 +0800131 u32 val;
132 int ret;
133
134 val = addr << PCIE_PHY_CTRL_DATA_LOC;
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530135 dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, val);
Sean Crossbb389192013-09-26 11:24:47 +0800136
137 val |= (0x1 << PCIE_PHY_CTRL_CAP_ADR_LOC);
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530138 dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, val);
Sean Crossbb389192013-09-26 11:24:47 +0800139
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500140 ret = pcie_phy_poll_ack(imx6_pcie, 1);
Sean Crossbb389192013-09-26 11:24:47 +0800141 if (ret)
142 return ret;
143
144 val = addr << PCIE_PHY_CTRL_DATA_LOC;
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530145 dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, val);
Sean Crossbb389192013-09-26 11:24:47 +0800146
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500147 return pcie_phy_poll_ack(imx6_pcie, 0);
Sean Crossbb389192013-09-26 11:24:47 +0800148}
149
150/* Read from the 16-bit PCIe PHY control registers (not memory-mapped) */
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500151static int pcie_phy_read(struct imx6_pcie *imx6_pcie, int addr, int *data)
Sean Crossbb389192013-09-26 11:24:47 +0800152{
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530153 struct dw_pcie *pci = imx6_pcie->pci;
Sean Crossbb389192013-09-26 11:24:47 +0800154 u32 val, phy_ctl;
155 int ret;
156
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500157 ret = pcie_phy_wait_ack(imx6_pcie, addr);
Sean Crossbb389192013-09-26 11:24:47 +0800158 if (ret)
159 return ret;
160
161 /* assert Read signal */
162 phy_ctl = 0x1 << PCIE_PHY_CTRL_RD_LOC;
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530163 dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, phy_ctl);
Sean Crossbb389192013-09-26 11:24:47 +0800164
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500165 ret = pcie_phy_poll_ack(imx6_pcie, 1);
Sean Crossbb389192013-09-26 11:24:47 +0800166 if (ret)
167 return ret;
168
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530169 val = dw_pcie_readl_dbi(pci, PCIE_PHY_STAT);
Sean Crossbb389192013-09-26 11:24:47 +0800170 *data = val & 0xffff;
171
172 /* deassert Read signal */
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530173 dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, 0x00);
Sean Crossbb389192013-09-26 11:24:47 +0800174
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500175 return pcie_phy_poll_ack(imx6_pcie, 0);
Sean Crossbb389192013-09-26 11:24:47 +0800176}
177
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500178static int pcie_phy_write(struct imx6_pcie *imx6_pcie, int addr, int data)
Sean Crossbb389192013-09-26 11:24:47 +0800179{
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530180 struct dw_pcie *pci = imx6_pcie->pci;
Sean Crossbb389192013-09-26 11:24:47 +0800181 u32 var;
182 int ret;
183
184 /* write addr */
185 /* cap addr */
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500186 ret = pcie_phy_wait_ack(imx6_pcie, addr);
Sean Crossbb389192013-09-26 11:24:47 +0800187 if (ret)
188 return ret;
189
190 var = data << PCIE_PHY_CTRL_DATA_LOC;
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530191 dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var);
Sean Crossbb389192013-09-26 11:24:47 +0800192
193 /* capture data */
194 var |= (0x1 << PCIE_PHY_CTRL_CAP_DAT_LOC);
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530195 dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var);
Sean Crossbb389192013-09-26 11:24:47 +0800196
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500197 ret = pcie_phy_poll_ack(imx6_pcie, 1);
Sean Crossbb389192013-09-26 11:24:47 +0800198 if (ret)
199 return ret;
200
201 /* deassert cap data */
202 var = data << PCIE_PHY_CTRL_DATA_LOC;
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530203 dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var);
Sean Crossbb389192013-09-26 11:24:47 +0800204
205 /* wait for ack de-assertion */
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500206 ret = pcie_phy_poll_ack(imx6_pcie, 0);
Sean Crossbb389192013-09-26 11:24:47 +0800207 if (ret)
208 return ret;
209
210 /* assert wr signal */
211 var = 0x1 << PCIE_PHY_CTRL_WR_LOC;
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530212 dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var);
Sean Crossbb389192013-09-26 11:24:47 +0800213
214 /* wait for ack */
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500215 ret = pcie_phy_poll_ack(imx6_pcie, 1);
Sean Crossbb389192013-09-26 11:24:47 +0800216 if (ret)
217 return ret;
218
219 /* deassert wr signal */
220 var = data << PCIE_PHY_CTRL_DATA_LOC;
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530221 dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var);
Sean Crossbb389192013-09-26 11:24:47 +0800222
223 /* wait for ack de-assertion */
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500224 ret = pcie_phy_poll_ack(imx6_pcie, 0);
Sean Crossbb389192013-09-26 11:24:47 +0800225 if (ret)
226 return ret;
227
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530228 dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, 0x0);
Sean Crossbb389192013-09-26 11:24:47 +0800229
230 return 0;
231}
232
Bjorn Helgaase7d77052016-10-11 22:06:47 -0500233static void imx6_pcie_reset_phy(struct imx6_pcie *imx6_pcie)
Lucas Stach53eeb482016-01-15 19:56:47 +0100234{
235 u32 tmp;
236
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500237 pcie_phy_read(imx6_pcie, PHY_RX_OVRD_IN_LO, &tmp);
Lucas Stach53eeb482016-01-15 19:56:47 +0100238 tmp |= (PHY_RX_OVRD_IN_LO_RX_DATA_EN |
239 PHY_RX_OVRD_IN_LO_RX_PLL_EN);
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500240 pcie_phy_write(imx6_pcie, PHY_RX_OVRD_IN_LO, tmp);
Lucas Stach53eeb482016-01-15 19:56:47 +0100241
242 usleep_range(2000, 3000);
243
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500244 pcie_phy_read(imx6_pcie, PHY_RX_OVRD_IN_LO, &tmp);
Lucas Stach53eeb482016-01-15 19:56:47 +0100245 tmp &= ~(PHY_RX_OVRD_IN_LO_RX_DATA_EN |
246 PHY_RX_OVRD_IN_LO_RX_PLL_EN);
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500247 pcie_phy_write(imx6_pcie, PHY_RX_OVRD_IN_LO, tmp);
Lucas Stach53eeb482016-01-15 19:56:47 +0100248}
249
Sean Crossbb389192013-09-26 11:24:47 +0800250/* Added for PCI abort handling */
251static int imx6q_pcie_abort_handler(unsigned long addr,
252 unsigned int fsr, struct pt_regs *regs)
253{
Lucas Stach415b6182017-05-22 17:06:30 -0500254 unsigned long pc = instruction_pointer(regs);
255 unsigned long instr = *(unsigned long *)pc;
256 int reg = (instr >> 12) & 15;
257
258 /*
259 * If the instruction being executed was a read,
260 * make it look like it read all-ones.
261 */
262 if ((instr & 0x0c100000) == 0x04100000) {
263 unsigned long val;
264
265 if (instr & 0x00400000)
266 val = 255;
267 else
268 val = -1;
269
270 regs->uregs[reg] = val;
271 regs->ARM_pc += 4;
272 return 0;
273 }
274
275 if ((instr & 0x0e100090) == 0x00100090) {
276 regs->uregs[reg] = -1;
277 regs->ARM_pc += 4;
278 return 0;
279 }
280
281 return 1;
Sean Crossbb389192013-09-26 11:24:47 +0800282}
283
Bjorn Helgaas9ab021b2016-10-06 13:35:17 -0500284static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
Sean Crossbb389192013-09-26 11:24:47 +0800285{
Quentin Schulzc26ebe92017-06-08 10:07:42 +0200286 struct device *dev = imx6_pcie->pci->dev;
287
Andrey Smirnove6f1fef2016-05-02 14:08:21 -0500288 switch (imx6_pcie->variant) {
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700289 case IMX7D:
290 reset_control_assert(imx6_pcie->pciephy_reset);
291 reset_control_assert(imx6_pcie->apps_reset);
292 break;
Andrey Smirnove6f1fef2016-05-02 14:08:21 -0500293 case IMX6SX:
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500294 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
295 IMX6SX_GPR12_PCIE_TEST_POWERDOWN,
296 IMX6SX_GPR12_PCIE_TEST_POWERDOWN);
297 /* Force PCIe PHY reset */
298 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR5,
299 IMX6SX_GPR5_PCIE_BTNRST_RESET,
300 IMX6SX_GPR5_PCIE_BTNRST_RESET);
Andrey Smirnove6f1fef2016-05-02 14:08:21 -0500301 break;
Andrey Smirnov4d31c612016-05-02 14:09:10 -0500302 case IMX6QP:
303 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
304 IMX6Q_GPR1_PCIE_SW_RST,
305 IMX6Q_GPR1_PCIE_SW_RST);
306 break;
Andrey Smirnove6f1fef2016-05-02 14:08:21 -0500307 case IMX6Q:
Andrey Smirnove6f1fef2016-05-02 14:08:21 -0500308 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
309 IMX6Q_GPR1_PCIE_TEST_PD, 1 << 18);
310 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
311 IMX6Q_GPR1_PCIE_REF_CLK_EN, 0 << 16);
312 break;
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500313 }
Quentin Schulzc26ebe92017-06-08 10:07:42 +0200314
315 if (imx6_pcie->vpcie && regulator_is_enabled(imx6_pcie->vpcie) > 0) {
316 int ret = regulator_disable(imx6_pcie->vpcie);
317
318 if (ret)
319 dev_err(dev, "failed to disable vpcie regulator: %d\n",
320 ret);
321 }
Sean Crossbb389192013-09-26 11:24:47 +0800322}
323
Bjorn Helgaas4d1821e2016-03-14 00:30:55 +0100324static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)
325{
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530326 struct dw_pcie *pci = imx6_pcie->pci;
327 struct device *dev = pci->dev;
Andrey Smirnove6f1fef2016-05-02 14:08:21 -0500328 int ret = 0;
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500329
Andrey Smirnove6f1fef2016-05-02 14:08:21 -0500330 switch (imx6_pcie->variant) {
331 case IMX6SX:
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500332 ret = clk_prepare_enable(imx6_pcie->pcie_inbound_axi);
333 if (ret) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500334 dev_err(dev, "unable to enable pcie_axi clock\n");
Andrey Smirnove6f1fef2016-05-02 14:08:21 -0500335 break;
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500336 }
337
338 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
339 IMX6SX_GPR12_PCIE_TEST_POWERDOWN, 0);
Andrey Smirnove6f1fef2016-05-02 14:08:21 -0500340 break;
Fabio Estevamc27fd682018-05-09 14:01:48 -0300341 case IMX6QP: /* FALLTHROUGH */
Andrey Smirnove6f1fef2016-05-02 14:08:21 -0500342 case IMX6Q:
343 /* power up core phy and enable ref clock */
344 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
345 IMX6Q_GPR1_PCIE_TEST_PD, 0 << 18);
346 /*
347 * the async reset input need ref clock to sync internally,
348 * when the ref clock comes after reset, internal synced
349 * reset time is too short, cannot meet the requirement.
350 * add one ~10us delay here.
351 */
352 udelay(10);
353 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
354 IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16);
355 break;
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700356 case IMX7D:
357 break;
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500358 }
359
Andrey Smirnove6f1fef2016-05-02 14:08:21 -0500360 return ret;
Bjorn Helgaas4d1821e2016-03-14 00:30:55 +0100361}
362
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700363static void imx7d_pcie_wait_for_phy_pll_lock(struct imx6_pcie *imx6_pcie)
364{
365 u32 val;
366 unsigned int retries;
367 struct device *dev = imx6_pcie->pci->dev;
368
369 for (retries = 0; retries < PHY_PLL_LOCK_WAIT_MAX_RETRIES; retries++) {
370 regmap_read(imx6_pcie->iomuxc_gpr, IOMUXC_GPR22, &val);
371
372 if (val & IMX7D_GPR22_PCIE_PHY_PLL_LOCKED)
373 return;
374
375 usleep_range(PHY_PLL_LOCK_WAIT_USLEEP_MIN,
376 PHY_PLL_LOCK_WAIT_USLEEP_MAX);
377 }
378
379 dev_err(dev, "PCIe PLL lock timeout\n");
380}
381
Bjorn Helgaas9ab021b2016-10-06 13:35:17 -0500382static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
Sean Crossbb389192013-09-26 11:24:47 +0800383{
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530384 struct dw_pcie *pci = imx6_pcie->pci;
385 struct device *dev = pci->dev;
Sean Crossbb389192013-09-26 11:24:47 +0800386 int ret;
387
Quentin Schulzc26ebe92017-06-08 10:07:42 +0200388 if (imx6_pcie->vpcie && !regulator_is_enabled(imx6_pcie->vpcie)) {
389 ret = regulator_enable(imx6_pcie->vpcie);
390 if (ret) {
391 dev_err(dev, "failed to enable vpcie regulator: %d\n",
392 ret);
393 return;
394 }
395 }
396
Lucas Stach57526132014-03-28 17:52:55 +0100397 ret = clk_prepare_enable(imx6_pcie->pcie_phy);
Sean Crossbb389192013-09-26 11:24:47 +0800398 if (ret) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500399 dev_err(dev, "unable to enable pcie_phy clock\n");
Quentin Schulzc26ebe92017-06-08 10:07:42 +0200400 goto err_pcie_phy;
Sean Crossbb389192013-09-26 11:24:47 +0800401 }
402
Lucas Stach57526132014-03-28 17:52:55 +0100403 ret = clk_prepare_enable(imx6_pcie->pcie_bus);
Sean Crossbb389192013-09-26 11:24:47 +0800404 if (ret) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500405 dev_err(dev, "unable to enable pcie_bus clock\n");
Lucas Stach57526132014-03-28 17:52:55 +0100406 goto err_pcie_bus;
Sean Crossbb389192013-09-26 11:24:47 +0800407 }
408
Lucas Stach57526132014-03-28 17:52:55 +0100409 ret = clk_prepare_enable(imx6_pcie->pcie);
Sean Crossbb389192013-09-26 11:24:47 +0800410 if (ret) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500411 dev_err(dev, "unable to enable pcie clock\n");
Lucas Stach57526132014-03-28 17:52:55 +0100412 goto err_pcie;
Sean Crossbb389192013-09-26 11:24:47 +0800413 }
414
Bjorn Helgaas4d1821e2016-03-14 00:30:55 +0100415 ret = imx6_pcie_enable_ref_clk(imx6_pcie);
416 if (ret) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500417 dev_err(dev, "unable to enable pcie ref clock\n");
Bjorn Helgaas4d1821e2016-03-14 00:30:55 +0100418 goto err_ref_clk;
419 }
Tim Harvey3fce0e82014-08-07 23:36:40 -0700420
Richard Zhua2fa6f62014-10-27 13:17:32 +0800421 /* allow the clocks to stabilize */
422 usleep_range(200, 500);
423
Richard Zhubc9ef772013-12-12 22:50:03 +0100424 /* Some boards don't have PCIe reset GPIO. */
Fabio Estevamb2d7a9c2016-03-28 18:45:36 -0300425 if (gpio_is_valid(imx6_pcie->reset_gpio)) {
Petr Štetiar3ea8529a2016-04-19 19:42:07 -0500426 gpio_set_value_cansleep(imx6_pcie->reset_gpio,
427 imx6_pcie->gpio_active_high);
Richard Zhubc9ef772013-12-12 22:50:03 +0100428 msleep(100);
Petr Štetiar3ea8529a2016-04-19 19:42:07 -0500429 gpio_set_value_cansleep(imx6_pcie->reset_gpio,
430 !imx6_pcie->gpio_active_high);
Richard Zhubc9ef772013-12-12 22:50:03 +0100431 }
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500432
Andrey Smirnov4d31c612016-05-02 14:09:10 -0500433 switch (imx6_pcie->variant) {
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700434 case IMX7D:
435 reset_control_deassert(imx6_pcie->pciephy_reset);
436 imx7d_pcie_wait_for_phy_pll_lock(imx6_pcie);
437 break;
Andrey Smirnov4d31c612016-05-02 14:09:10 -0500438 case IMX6SX:
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500439 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR5,
440 IMX6SX_GPR5_PCIE_BTNRST_RESET, 0);
Andrey Smirnov4d31c612016-05-02 14:09:10 -0500441 break;
442 case IMX6QP:
443 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
444 IMX6Q_GPR1_PCIE_SW_RST, 0);
445
446 usleep_range(200, 500);
447 break;
448 case IMX6Q: /* Nothing to do */
449 break;
450 }
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500451
Bjorn Helgaas9ab021b2016-10-06 13:35:17 -0500452 return;
Sean Crossbb389192013-09-26 11:24:47 +0800453
Bjorn Helgaas4d1821e2016-03-14 00:30:55 +0100454err_ref_clk:
455 clk_disable_unprepare(imx6_pcie->pcie);
Lucas Stach57526132014-03-28 17:52:55 +0100456err_pcie:
457 clk_disable_unprepare(imx6_pcie->pcie_bus);
458err_pcie_bus:
459 clk_disable_unprepare(imx6_pcie->pcie_phy);
Quentin Schulzc26ebe92017-06-08 10:07:42 +0200460err_pcie_phy:
461 if (imx6_pcie->vpcie && regulator_is_enabled(imx6_pcie->vpcie) > 0) {
462 ret = regulator_disable(imx6_pcie->vpcie);
463 if (ret)
464 dev_err(dev, "failed to disable vpcie regulator: %d\n",
465 ret);
466 }
Sean Crossbb389192013-09-26 11:24:47 +0800467}
468
Bjorn Helgaase7d77052016-10-11 22:06:47 -0500469static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie)
Sean Crossbb389192013-09-26 11:24:47 +0800470{
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700471 switch (imx6_pcie->variant) {
472 case IMX7D:
473 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
474 IMX7D_GPR12_PCIE_PHY_REFCLK_SEL, 0);
475 break;
476 case IMX6SX:
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500477 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
478 IMX6SX_GPR12_PCIE_RX_EQ_MASK,
479 IMX6SX_GPR12_PCIE_RX_EQ_2);
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700480 /* FALLTHROUGH */
481 default:
482 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
483 IMX6Q_GPR12_PCIE_CTL_2, 0 << 10);
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500484
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700485 /* configure constant input signal to the pcie ctrl and phy */
486 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
487 IMX6Q_GPR12_LOS_LEVEL, 9 << 4);
Sean Crossbb389192013-09-26 11:24:47 +0800488
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700489 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
490 IMX6Q_GPR8_TX_DEEMPH_GEN1,
491 imx6_pcie->tx_deemph_gen1 << 0);
492 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
493 IMX6Q_GPR8_TX_DEEMPH_GEN2_3P5DB,
494 imx6_pcie->tx_deemph_gen2_3p5db << 6);
495 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
496 IMX6Q_GPR8_TX_DEEMPH_GEN2_6DB,
497 imx6_pcie->tx_deemph_gen2_6db << 12);
498 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
499 IMX6Q_GPR8_TX_SWING_FULL,
500 imx6_pcie->tx_swing_full << 18);
501 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
502 IMX6Q_GPR8_TX_SWING_LOW,
503 imx6_pcie->tx_swing_low << 25);
504 break;
505 }
506
Sean Crossbb389192013-09-26 11:24:47 +0800507 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
508 IMX6Q_GPR12_DEVICE_TYPE, PCI_EXP_TYPE_ROOT_PORT << 12);
Sean Crossbb389192013-09-26 11:24:47 +0800509}
510
Bjorn Helgaase7d77052016-10-11 22:06:47 -0500511static int imx6_pcie_wait_for_link(struct imx6_pcie *imx6_pcie)
Marek Vasut66a60f92013-12-12 22:50:01 +0100512{
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530513 struct dw_pcie *pci = imx6_pcie->pci;
514 struct device *dev = pci->dev;
Bjorn Helgaas13957652016-10-06 13:35:18 -0500515
Joao Pinto886bc5c2016-03-10 14:44:35 -0600516 /* check if the link is up or not */
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530517 if (!dw_pcie_wait_for_link(pci))
Joao Pinto886bc5c2016-03-10 14:44:35 -0600518 return 0;
Marek Vasut66a60f92013-12-12 22:50:01 +0100519
Bjorn Helgaas13957652016-10-06 13:35:18 -0500520 dev_dbg(dev, "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n",
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530521 dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R0),
522 dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R1));
Joao Pinto886bc5c2016-03-10 14:44:35 -0600523 return -ETIMEDOUT;
Marek Vasut66a60f92013-12-12 22:50:01 +0100524}
525
Bjorn Helgaase7d77052016-10-11 22:06:47 -0500526static int imx6_pcie_wait_for_speed_change(struct imx6_pcie *imx6_pcie)
Troy Kiskya0427462015-06-12 14:30:16 -0500527{
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530528 struct dw_pcie *pci = imx6_pcie->pci;
529 struct device *dev = pci->dev;
Bjorn Helgaas1c7fae12015-06-12 15:02:49 -0500530 u32 tmp;
Troy Kiskya0427462015-06-12 14:30:16 -0500531 unsigned int retries;
532
533 for (retries = 0; retries < 200; retries++) {
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530534 tmp = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL);
Troy Kiskya0427462015-06-12 14:30:16 -0500535 /* Test if the speed change finished. */
536 if (!(tmp & PORT_LOGIC_SPEED_CHANGE))
537 return 0;
538 usleep_range(100, 1000);
539 }
540
Bjorn Helgaas13957652016-10-06 13:35:18 -0500541 dev_err(dev, "Speed change timeout\n");
Troy Kiskya0427462015-06-12 14:30:16 -0500542 return -EINVAL;
Sean Crossbb389192013-09-26 11:24:47 +0800543}
544
Bjorn Helgaase7d77052016-10-11 22:06:47 -0500545static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)
Marek Vasutfa33a6d2013-12-12 22:50:02 +0100546{
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530547 struct dw_pcie *pci = imx6_pcie->pci;
548 struct device *dev = pci->dev;
Bjorn Helgaas1c7fae12015-06-12 15:02:49 -0500549 u32 tmp;
Troy Kiskya0427462015-06-12 14:30:16 -0500550 int ret;
Marek Vasutfa33a6d2013-12-12 22:50:02 +0100551
552 /*
553 * Force Gen1 operation when starting the link. In case the link is
554 * started in Gen2 mode, there is a possibility the devices on the
555 * bus will not be detected at all. This happens with PCIe switches.
556 */
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530557 tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCR);
Marek Vasutfa33a6d2013-12-12 22:50:02 +0100558 tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK;
559 tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1;
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530560 dw_pcie_writel_dbi(pci, PCIE_RC_LCR, tmp);
Marek Vasutfa33a6d2013-12-12 22:50:02 +0100561
562 /* Start LTSSM. */
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700563 if (imx6_pcie->variant == IMX7D)
564 reset_control_deassert(imx6_pcie->apps_reset);
565 else
566 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
567 IMX6Q_GPR12_PCIE_CTL_2, 1 << 10);
Marek Vasutfa33a6d2013-12-12 22:50:02 +0100568
Bjorn Helgaase7d77052016-10-11 22:06:47 -0500569 ret = imx6_pcie_wait_for_link(imx6_pcie);
Fabio Estevamcaf3f562016-12-27 12:40:43 -0200570 if (ret)
Lucas Stach54a47a82016-01-25 16:49:53 -0600571 goto err_reset_phy;
Marek Vasutfa33a6d2013-12-12 22:50:02 +0100572
Tim Harveya5fcec42016-04-19 19:52:44 -0500573 if (imx6_pcie->link_gen == 2) {
574 /* Allow Gen2 mode after the link is up. */
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530575 tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCR);
Tim Harveya5fcec42016-04-19 19:52:44 -0500576 tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK;
577 tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2;
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530578 dw_pcie_writel_dbi(pci, PCIE_RC_LCR, tmp);
Marek Vasutfa33a6d2013-12-12 22:50:02 +0100579
Andrey Smirnove6dcd872017-03-28 08:42:51 -0700580 /*
Andrey Smirnov93b226f2017-03-28 08:42:52 -0700581 * Start Directed Speed Change so the best possible
582 * speed both link partners support can be negotiated.
Andrey Smirnove6dcd872017-03-28 08:42:51 -0700583 */
Andrey Smirnov93b226f2017-03-28 08:42:52 -0700584 tmp = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL);
585 tmp |= PORT_LOGIC_SPEED_CHANGE;
586 dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp);
Andrey Smirnove6dcd872017-03-28 08:42:51 -0700587
Andrey Smirnov93b226f2017-03-28 08:42:52 -0700588 if (imx6_pcie->variant != IMX7D) {
589 /*
590 * On i.MX7, DIRECT_SPEED_CHANGE behaves differently
591 * from i.MX6 family when no link speed transition
592 * occurs and we go Gen1 -> yep, Gen1. The difference
593 * is that, in such case, it will not be cleared by HW
594 * which will cause the following code to report false
595 * failure.
596 */
597
598 ret = imx6_pcie_wait_for_speed_change(imx6_pcie);
599 if (ret) {
600 dev_err(dev, "Failed to bring link up!\n");
601 goto err_reset_phy;
602 }
603 }
604
605 /* Make sure link training is finished as well! */
606 ret = imx6_pcie_wait_for_link(imx6_pcie);
Andrey Smirnove6dcd872017-03-28 08:42:51 -0700607 if (ret) {
608 dev_err(dev, "Failed to bring link up!\n");
609 goto err_reset_phy;
610 }
Andrey Smirnov93b226f2017-03-28 08:42:52 -0700611 } else {
612 dev_info(dev, "Link: Gen2 disabled\n");
Marek Vasutfa33a6d2013-12-12 22:50:02 +0100613 }
614
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530615 tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCSR);
Bjorn Helgaas13957652016-10-06 13:35:18 -0500616 dev_info(dev, "Link up, Gen%i\n", (tmp >> 16) & 0xf);
Troy Kiskya0427462015-06-12 14:30:16 -0500617 return 0;
Lucas Stach54a47a82016-01-25 16:49:53 -0600618
619err_reset_phy:
Bjorn Helgaas13957652016-10-06 13:35:18 -0500620 dev_dbg(dev, "PHY DEBUG_R0=0x%08x DEBUG_R1=0x%08x\n",
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530621 dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R0),
622 dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R1));
Bjorn Helgaas2a6a85d2016-10-11 22:18:26 -0500623 imx6_pcie_reset_phy(imx6_pcie);
Lucas Stach54a47a82016-01-25 16:49:53 -0600624 return ret;
Marek Vasutfa33a6d2013-12-12 22:50:02 +0100625}
626
Bjorn Andersson4a301762017-07-15 23:39:45 -0700627static int imx6_pcie_host_init(struct pcie_port *pp)
Sean Crossbb389192013-09-26 11:24:47 +0800628{
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530629 struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
630 struct imx6_pcie *imx6_pcie = to_imx6_pcie(pci);
Sean Crossbb389192013-09-26 11:24:47 +0800631
Bjorn Helgaase7d77052016-10-11 22:06:47 -0500632 imx6_pcie_assert_core_reset(imx6_pcie);
633 imx6_pcie_init_phy(imx6_pcie);
634 imx6_pcie_deassert_core_reset(imx6_pcie);
Sean Crossbb389192013-09-26 11:24:47 +0800635 dw_pcie_setup_rc(pp);
Bjorn Helgaase7d77052016-10-11 22:06:47 -0500636 imx6_pcie_establish_link(imx6_pcie);
Lucas Stachd1dc9742014-03-28 17:52:59 +0100637
638 if (IS_ENABLED(CONFIG_PCI_MSI))
639 dw_pcie_msi_init(pp);
Bjorn Andersson4a301762017-07-15 23:39:45 -0700640
641 return 0;
Sean Crossbb389192013-09-26 11:24:47 +0800642}
643
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530644static int imx6_pcie_link_up(struct dw_pcie *pci)
Sean Crossbb389192013-09-26 11:24:47 +0800645{
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530646 return dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R1) &
Lucas Stach4d107d32016-01-25 16:50:02 -0600647 PCIE_PHY_DEBUG_R1_XMLH_LINK_UP;
Sean Crossbb389192013-09-26 11:24:47 +0800648}
649
Jisheng Zhang4ab2e7c2017-06-05 16:53:46 +0800650static const struct dw_pcie_host_ops imx6_pcie_host_ops = {
Sean Crossbb389192013-09-26 11:24:47 +0800651 .host_init = imx6_pcie_host_init,
652};
653
Andrey Smirnovbde4a5a2017-03-28 08:42:50 -0700654static int imx6_add_pcie_port(struct imx6_pcie *imx6_pcie,
655 struct platform_device *pdev)
Sean Crossbb389192013-09-26 11:24:47 +0800656{
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530657 struct dw_pcie *pci = imx6_pcie->pci;
658 struct pcie_port *pp = &pci->pp;
659 struct device *dev = &pdev->dev;
Sean Crossbb389192013-09-26 11:24:47 +0800660 int ret;
661
Lucas Stachd1dc9742014-03-28 17:52:59 +0100662 if (IS_ENABLED(CONFIG_PCI_MSI)) {
663 pp->msi_irq = platform_get_irq_byname(pdev, "msi");
664 if (pp->msi_irq <= 0) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500665 dev_err(dev, "failed to get MSI irq\n");
Lucas Stachd1dc9742014-03-28 17:52:59 +0100666 return -ENODEV;
667 }
Lucas Stachd1dc9742014-03-28 17:52:59 +0100668 }
669
Sean Crossbb389192013-09-26 11:24:47 +0800670 pp->root_bus_nr = -1;
671 pp->ops = &imx6_pcie_host_ops;
672
Sean Crossbb389192013-09-26 11:24:47 +0800673 ret = dw_pcie_host_init(pp);
674 if (ret) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500675 dev_err(dev, "failed to initialize host\n");
Sean Crossbb389192013-09-26 11:24:47 +0800676 return ret;
677 }
678
679 return 0;
680}
681
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530682static const struct dw_pcie_ops dw_pcie_ops = {
683 .link_up = imx6_pcie_link_up,
684};
685
Andrey Smirnovbde4a5a2017-03-28 08:42:50 -0700686static int imx6_pcie_probe(struct platform_device *pdev)
Sean Crossbb389192013-09-26 11:24:47 +0800687{
Bjorn Helgaas13957652016-10-06 13:35:18 -0500688 struct device *dev = &pdev->dev;
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530689 struct dw_pcie *pci;
Sean Crossbb389192013-09-26 11:24:47 +0800690 struct imx6_pcie *imx6_pcie;
Sean Crossbb389192013-09-26 11:24:47 +0800691 struct resource *dbi_base;
Bjorn Helgaas13957652016-10-06 13:35:18 -0500692 struct device_node *node = dev->of_node;
Sean Crossbb389192013-09-26 11:24:47 +0800693 int ret;
694
Bjorn Helgaas13957652016-10-06 13:35:18 -0500695 imx6_pcie = devm_kzalloc(dev, sizeof(*imx6_pcie), GFP_KERNEL);
Sean Crossbb389192013-09-26 11:24:47 +0800696 if (!imx6_pcie)
697 return -ENOMEM;
698
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530699 pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
700 if (!pci)
701 return -ENOMEM;
702
703 pci->dev = dev;
704 pci->ops = &dw_pcie_ops;
Sean Crossbb389192013-09-26 11:24:47 +0800705
Guenter Roeckc0464062017-02-25 02:08:12 -0800706 imx6_pcie->pci = pci;
Andrey Smirnove6f1fef2016-05-02 14:08:21 -0500707 imx6_pcie->variant =
Bjorn Helgaas13957652016-10-06 13:35:18 -0500708 (enum imx6_pcie_variants)of_device_get_match_data(dev);
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500709
Sean Crossbb389192013-09-26 11:24:47 +0800710 dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530711 pci->dbi_base = devm_ioremap_resource(dev, dbi_base);
712 if (IS_ERR(pci->dbi_base))
713 return PTR_ERR(pci->dbi_base);
Sean Crossbb389192013-09-26 11:24:47 +0800714
715 /* Fetch GPIOs */
Bjorn Helgaasc5af4072016-10-06 13:35:18 -0500716 imx6_pcie->reset_gpio = of_get_named_gpio(node, "reset-gpio", 0);
717 imx6_pcie->gpio_active_high = of_property_read_bool(node,
Petr Štetiar3ea8529a2016-04-19 19:42:07 -0500718 "reset-gpio-active-high");
Fabio Estevamb2d7a9c2016-03-28 18:45:36 -0300719 if (gpio_is_valid(imx6_pcie->reset_gpio)) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500720 ret = devm_gpio_request_one(dev, imx6_pcie->reset_gpio,
Petr Štetiar3ea8529a2016-04-19 19:42:07 -0500721 imx6_pcie->gpio_active_high ?
722 GPIOF_OUT_INIT_HIGH :
723 GPIOF_OUT_INIT_LOW,
724 "PCIe reset");
Fabio Estevamb2d7a9c2016-03-28 18:45:36 -0300725 if (ret) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500726 dev_err(dev, "unable to get reset gpio\n");
Fabio Estevamb2d7a9c2016-03-28 18:45:36 -0300727 return ret;
728 }
Andrey Smirnovbde4a5a2017-03-28 08:42:50 -0700729 } else if (imx6_pcie->reset_gpio == -EPROBE_DEFER) {
730 return imx6_pcie->reset_gpio;
Fabio Estevamb2d7a9c2016-03-28 18:45:36 -0300731 }
Sean Crossbb389192013-09-26 11:24:47 +0800732
Sean Crossbb389192013-09-26 11:24:47 +0800733 /* Fetch clocks */
Bjorn Helgaas13957652016-10-06 13:35:18 -0500734 imx6_pcie->pcie_phy = devm_clk_get(dev, "pcie_phy");
Lucas Stach57526132014-03-28 17:52:55 +0100735 if (IS_ERR(imx6_pcie->pcie_phy)) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500736 dev_err(dev, "pcie_phy clock source missing or invalid\n");
Lucas Stach57526132014-03-28 17:52:55 +0100737 return PTR_ERR(imx6_pcie->pcie_phy);
Sean Crossbb389192013-09-26 11:24:47 +0800738 }
739
Bjorn Helgaas13957652016-10-06 13:35:18 -0500740 imx6_pcie->pcie_bus = devm_clk_get(dev, "pcie_bus");
Lucas Stach57526132014-03-28 17:52:55 +0100741 if (IS_ERR(imx6_pcie->pcie_bus)) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500742 dev_err(dev, "pcie_bus clock source missing or invalid\n");
Lucas Stach57526132014-03-28 17:52:55 +0100743 return PTR_ERR(imx6_pcie->pcie_bus);
Sean Crossbb389192013-09-26 11:24:47 +0800744 }
745
Bjorn Helgaas13957652016-10-06 13:35:18 -0500746 imx6_pcie->pcie = devm_clk_get(dev, "pcie");
Lucas Stach57526132014-03-28 17:52:55 +0100747 if (IS_ERR(imx6_pcie->pcie)) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500748 dev_err(dev, "pcie clock source missing or invalid\n");
Lucas Stach57526132014-03-28 17:52:55 +0100749 return PTR_ERR(imx6_pcie->pcie);
Sean Crossbb389192013-09-26 11:24:47 +0800750 }
751
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700752 switch (imx6_pcie->variant) {
753 case IMX6SX:
Bjorn Helgaas13957652016-10-06 13:35:18 -0500754 imx6_pcie->pcie_inbound_axi = devm_clk_get(dev,
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500755 "pcie_inbound_axi");
756 if (IS_ERR(imx6_pcie->pcie_inbound_axi)) {
Andrey Smirnov21b72452017-02-07 07:50:25 -0800757 dev_err(dev, "pcie_inbound_axi clock missing or invalid\n");
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500758 return PTR_ERR(imx6_pcie->pcie_inbound_axi);
759 }
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700760 break;
761 case IMX7D:
Philipp Zabel7c180582017-07-19 17:25:56 +0200762 imx6_pcie->pciephy_reset = devm_reset_control_get_exclusive(dev,
763 "pciephy");
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700764 if (IS_ERR(imx6_pcie->pciephy_reset)) {
Colin Ian King72215472017-04-21 08:02:30 +0100765 dev_err(dev, "Failed to get PCIEPHY reset control\n");
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700766 return PTR_ERR(imx6_pcie->pciephy_reset);
767 }
768
Philipp Zabel7c180582017-07-19 17:25:56 +0200769 imx6_pcie->apps_reset = devm_reset_control_get_exclusive(dev,
770 "apps");
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700771 if (IS_ERR(imx6_pcie->apps_reset)) {
Colin Ian King72215472017-04-21 08:02:30 +0100772 dev_err(dev, "Failed to get PCIE APPS reset control\n");
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700773 return PTR_ERR(imx6_pcie->apps_reset);
774 }
775 break;
776 default:
777 break;
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500778 }
779
Sean Crossbb389192013-09-26 11:24:47 +0800780 /* Grab GPR config register range */
781 imx6_pcie->iomuxc_gpr =
782 syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
783 if (IS_ERR(imx6_pcie->iomuxc_gpr)) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500784 dev_err(dev, "unable to find iomuxc registers\n");
Fabio Estevamb391bf32013-12-02 01:39:35 -0200785 return PTR_ERR(imx6_pcie->iomuxc_gpr);
Sean Crossbb389192013-09-26 11:24:47 +0800786 }
787
Justin Waters28e3abe2016-01-15 10:24:35 -0500788 /* Grab PCIe PHY Tx Settings */
789 if (of_property_read_u32(node, "fsl,tx-deemph-gen1",
790 &imx6_pcie->tx_deemph_gen1))
791 imx6_pcie->tx_deemph_gen1 = 0;
792
793 if (of_property_read_u32(node, "fsl,tx-deemph-gen2-3p5db",
794 &imx6_pcie->tx_deemph_gen2_3p5db))
795 imx6_pcie->tx_deemph_gen2_3p5db = 0;
796
797 if (of_property_read_u32(node, "fsl,tx-deemph-gen2-6db",
798 &imx6_pcie->tx_deemph_gen2_6db))
799 imx6_pcie->tx_deemph_gen2_6db = 20;
800
801 if (of_property_read_u32(node, "fsl,tx-swing-full",
802 &imx6_pcie->tx_swing_full))
803 imx6_pcie->tx_swing_full = 127;
804
805 if (of_property_read_u32(node, "fsl,tx-swing-low",
806 &imx6_pcie->tx_swing_low))
807 imx6_pcie->tx_swing_low = 127;
808
Tim Harveya5fcec42016-04-19 19:52:44 -0500809 /* Limit link speed */
Bjorn Helgaasc5af4072016-10-06 13:35:18 -0500810 ret = of_property_read_u32(node, "fsl,max-link-speed",
Tim Harveya5fcec42016-04-19 19:52:44 -0500811 &imx6_pcie->link_gen);
812 if (ret)
813 imx6_pcie->link_gen = 1;
814
Quentin Schulzc26ebe92017-06-08 10:07:42 +0200815 imx6_pcie->vpcie = devm_regulator_get_optional(&pdev->dev, "vpcie");
816 if (IS_ERR(imx6_pcie->vpcie)) {
817 if (PTR_ERR(imx6_pcie->vpcie) == -EPROBE_DEFER)
818 return -EPROBE_DEFER;
819 imx6_pcie->vpcie = NULL;
820 }
821
Kishon Vijay Abraham I9bcf0a62017-02-15 18:48:11 +0530822 platform_set_drvdata(pdev, imx6_pcie);
823
Bjorn Helgaase7d77052016-10-11 22:06:47 -0500824 ret = imx6_add_pcie_port(imx6_pcie, pdev);
Sean Crossbb389192013-09-26 11:24:47 +0800825 if (ret < 0)
Fabio Estevamb391bf32013-12-02 01:39:35 -0200826 return ret;
Sean Crossbb389192013-09-26 11:24:47 +0800827
Sean Crossbb389192013-09-26 11:24:47 +0800828 return 0;
Sean Crossbb389192013-09-26 11:24:47 +0800829}
830
Lucas Stach3e3e4062014-07-31 20:16:05 +0200831static void imx6_pcie_shutdown(struct platform_device *pdev)
832{
833 struct imx6_pcie *imx6_pcie = platform_get_drvdata(pdev);
834
835 /* bring down link, so bootloader gets clean state in case of reboot */
Bjorn Helgaase7d77052016-10-11 22:06:47 -0500836 imx6_pcie_assert_core_reset(imx6_pcie);
Lucas Stach3e3e4062014-07-31 20:16:05 +0200837}
838
Sean Crossbb389192013-09-26 11:24:47 +0800839static const struct of_device_id imx6_pcie_of_match[] = {
Andrey Smirnove6f1fef2016-05-02 14:08:21 -0500840 { .compatible = "fsl,imx6q-pcie", .data = (void *)IMX6Q, },
841 { .compatible = "fsl,imx6sx-pcie", .data = (void *)IMX6SX, },
Andrey Smirnov4d31c612016-05-02 14:09:10 -0500842 { .compatible = "fsl,imx6qp-pcie", .data = (void *)IMX6QP, },
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700843 { .compatible = "fsl,imx7d-pcie", .data = (void *)IMX7D, },
Sean Crossbb389192013-09-26 11:24:47 +0800844 {},
845};
Sean Crossbb389192013-09-26 11:24:47 +0800846
847static struct platform_driver imx6_pcie_driver = {
848 .driver = {
849 .name = "imx6q-pcie",
Sachin Kamat8bcadbe2013-10-21 14:36:41 +0530850 .of_match_table = imx6_pcie_of_match,
Brian Norrisa5f40e82017-04-20 15:36:25 -0500851 .suppress_bind_attrs = true,
Sean Crossbb389192013-09-26 11:24:47 +0800852 },
Andrey Smirnovbde4a5a2017-03-28 08:42:50 -0700853 .probe = imx6_pcie_probe,
Lucas Stach3e3e4062014-07-31 20:16:05 +0200854 .shutdown = imx6_pcie_shutdown,
Sean Crossbb389192013-09-26 11:24:47 +0800855};
856
Sean Crossbb389192013-09-26 11:24:47 +0800857static int __init imx6_pcie_init(void)
858{
Andrey Smirnovbde4a5a2017-03-28 08:42:50 -0700859 /*
860 * Since probe() can be deferred we need to make sure that
861 * hook_fault_code is not called after __init memory is freed
862 * by kernel and since imx6q_pcie_abort_handler() is a no-op,
863 * we can install the handler here without risking it
864 * accessing some uninitialized driver state.
865 */
Lucas Stach415b6182017-05-22 17:06:30 -0500866 hook_fault_code(8, imx6q_pcie_abort_handler, SIGBUS, 0,
867 "external abort on non-linefetch");
Andrey Smirnovbde4a5a2017-03-28 08:42:50 -0700868
869 return platform_driver_register(&imx6_pcie_driver);
Sean Crossbb389192013-09-26 11:24:47 +0800870}
Paul Gortmakerf90d8e82016-08-22 17:59:43 -0400871device_initcall(imx6_pcie_init);