blob: 88af6bff945f36cbb9b746bb92775a9b8ca073d0 [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;
Leonard Crestezf4e833b2018-07-19 17:02:10 +030053 struct reset_control *turnoff_reset;
Andrey Smirnove6f1fef2016-05-02 14:08:21 -050054 enum imx6_pcie_variants variant;
Justin Waters28e3abe2016-01-15 10:24:35 -050055 u32 tx_deemph_gen1;
56 u32 tx_deemph_gen2_3p5db;
57 u32 tx_deemph_gen2_6db;
58 u32 tx_swing_full;
59 u32 tx_swing_low;
Tim Harveya5fcec42016-04-19 19:52:44 -050060 int link_gen;
Quentin Schulzc26ebe92017-06-08 10:07:42 +020061 struct regulator *vpcie;
Sean Crossbb389192013-09-26 11:24:47 +080062};
63
Andrey Smirnov9b3fe672017-03-28 08:42:49 -070064/* Parameters for the waiting for PCIe PHY PLL to lock on i.MX7 */
65#define PHY_PLL_LOCK_WAIT_MAX_RETRIES 2000
66#define PHY_PLL_LOCK_WAIT_USLEEP_MIN 50
67#define PHY_PLL_LOCK_WAIT_USLEEP_MAX 200
68
Marek Vasutfa33a6d2013-12-12 22:50:02 +010069/* PCIe Root Complex registers (memory-mapped) */
70#define PCIE_RC_LCR 0x7c
71#define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1 0x1
72#define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2 0x2
73#define PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK 0xf
74
Bjorn Helgaas2393f792015-06-12 17:27:43 -050075#define PCIE_RC_LCSR 0x80
76
Sean Crossbb389192013-09-26 11:24:47 +080077/* PCIe Port Logic registers (memory-mapped) */
78#define PL_OFFSET 0x700
Lucas Stach3e3e4062014-07-31 20:16:05 +020079#define PCIE_PL_PFLR (PL_OFFSET + 0x08)
80#define PCIE_PL_PFLR_LINK_STATE_MASK (0x3f << 16)
81#define PCIE_PL_PFLR_FORCE_LINK (1 << 15)
Sean Crossbb389192013-09-26 11:24:47 +080082#define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28)
83#define PCIE_PHY_DEBUG_R1 (PL_OFFSET + 0x2c)
84
85#define PCIE_PHY_CTRL (PL_OFFSET + 0x114)
86#define PCIE_PHY_CTRL_DATA_LOC 0
87#define PCIE_PHY_CTRL_CAP_ADR_LOC 16
88#define PCIE_PHY_CTRL_CAP_DAT_LOC 17
89#define PCIE_PHY_CTRL_WR_LOC 18
90#define PCIE_PHY_CTRL_RD_LOC 19
91
92#define PCIE_PHY_STAT (PL_OFFSET + 0x110)
93#define PCIE_PHY_STAT_ACK_LOC 16
94
Marek Vasutfa33a6d2013-12-12 22:50:02 +010095#define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C
96#define PORT_LOGIC_SPEED_CHANGE (0x1 << 17)
97
Sean Crossbb389192013-09-26 11:24:47 +080098/* PHY registers (not memory-mapped) */
Lucas Stachf18f42d2018-07-31 12:21:49 +020099#define PCIE_PHY_ATEOVRD 0x10
100#define PCIE_PHY_ATEOVRD_EN (0x1 << 2)
101#define PCIE_PHY_ATEOVRD_REF_CLKDIV_SHIFT 0
102#define PCIE_PHY_ATEOVRD_REF_CLKDIV_MASK 0x1
103
104#define PCIE_PHY_MPLL_OVRD_IN_LO 0x11
105#define PCIE_PHY_MPLL_MULTIPLIER_SHIFT 2
106#define PCIE_PHY_MPLL_MULTIPLIER_MASK 0x7f
107#define PCIE_PHY_MPLL_MULTIPLIER_OVRD (0x1 << 9)
108
Sean Crossbb389192013-09-26 11:24:47 +0800109#define PCIE_PHY_RX_ASIC_OUT 0x100D
Fabio Estevam111feb72015-09-11 09:08:53 -0300110#define PCIE_PHY_RX_ASIC_OUT_VALID (1 << 0)
Sean Crossbb389192013-09-26 11:24:47 +0800111
112#define PHY_RX_OVRD_IN_LO 0x1005
113#define PHY_RX_OVRD_IN_LO_RX_DATA_EN (1 << 5)
114#define PHY_RX_OVRD_IN_LO_RX_PLL_EN (1 << 3)
115
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500116static int pcie_phy_poll_ack(struct imx6_pcie *imx6_pcie, int exp_val)
Sean Crossbb389192013-09-26 11:24:47 +0800117{
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530118 struct dw_pcie *pci = imx6_pcie->pci;
Sean Crossbb389192013-09-26 11:24:47 +0800119 u32 val;
120 u32 max_iterations = 10;
121 u32 wait_counter = 0;
122
123 do {
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530124 val = dw_pcie_readl_dbi(pci, PCIE_PHY_STAT);
Sean Crossbb389192013-09-26 11:24:47 +0800125 val = (val >> PCIE_PHY_STAT_ACK_LOC) & 0x1;
126 wait_counter++;
127
128 if (val == exp_val)
129 return 0;
130
131 udelay(1);
132 } while (wait_counter < max_iterations);
133
134 return -ETIMEDOUT;
135}
136
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500137static int pcie_phy_wait_ack(struct imx6_pcie *imx6_pcie, int addr)
Sean Crossbb389192013-09-26 11:24:47 +0800138{
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530139 struct dw_pcie *pci = imx6_pcie->pci;
Sean Crossbb389192013-09-26 11:24:47 +0800140 u32 val;
141 int ret;
142
143 val = addr << PCIE_PHY_CTRL_DATA_LOC;
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530144 dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, val);
Sean Crossbb389192013-09-26 11:24:47 +0800145
146 val |= (0x1 << PCIE_PHY_CTRL_CAP_ADR_LOC);
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530147 dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, val);
Sean Crossbb389192013-09-26 11:24:47 +0800148
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500149 ret = pcie_phy_poll_ack(imx6_pcie, 1);
Sean Crossbb389192013-09-26 11:24:47 +0800150 if (ret)
151 return ret;
152
153 val = addr << PCIE_PHY_CTRL_DATA_LOC;
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530154 dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, val);
Sean Crossbb389192013-09-26 11:24:47 +0800155
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500156 return pcie_phy_poll_ack(imx6_pcie, 0);
Sean Crossbb389192013-09-26 11:24:47 +0800157}
158
159/* Read from the 16-bit PCIe PHY control registers (not memory-mapped) */
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500160static int pcie_phy_read(struct imx6_pcie *imx6_pcie, int addr, int *data)
Sean Crossbb389192013-09-26 11:24:47 +0800161{
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530162 struct dw_pcie *pci = imx6_pcie->pci;
Sean Crossbb389192013-09-26 11:24:47 +0800163 u32 val, phy_ctl;
164 int ret;
165
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500166 ret = pcie_phy_wait_ack(imx6_pcie, addr);
Sean Crossbb389192013-09-26 11:24:47 +0800167 if (ret)
168 return ret;
169
170 /* assert Read signal */
171 phy_ctl = 0x1 << PCIE_PHY_CTRL_RD_LOC;
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530172 dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, phy_ctl);
Sean Crossbb389192013-09-26 11:24:47 +0800173
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500174 ret = pcie_phy_poll_ack(imx6_pcie, 1);
Sean Crossbb389192013-09-26 11:24:47 +0800175 if (ret)
176 return ret;
177
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530178 val = dw_pcie_readl_dbi(pci, PCIE_PHY_STAT);
Sean Crossbb389192013-09-26 11:24:47 +0800179 *data = val & 0xffff;
180
181 /* deassert Read signal */
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530182 dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, 0x00);
Sean Crossbb389192013-09-26 11:24:47 +0800183
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500184 return pcie_phy_poll_ack(imx6_pcie, 0);
Sean Crossbb389192013-09-26 11:24:47 +0800185}
186
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500187static int pcie_phy_write(struct imx6_pcie *imx6_pcie, int addr, int data)
Sean Crossbb389192013-09-26 11:24:47 +0800188{
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530189 struct dw_pcie *pci = imx6_pcie->pci;
Sean Crossbb389192013-09-26 11:24:47 +0800190 u32 var;
191 int ret;
192
193 /* write addr */
194 /* cap addr */
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500195 ret = pcie_phy_wait_ack(imx6_pcie, addr);
Sean Crossbb389192013-09-26 11:24:47 +0800196 if (ret)
197 return ret;
198
199 var = data << PCIE_PHY_CTRL_DATA_LOC;
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530200 dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var);
Sean Crossbb389192013-09-26 11:24:47 +0800201
202 /* capture data */
203 var |= (0x1 << PCIE_PHY_CTRL_CAP_DAT_LOC);
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530204 dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var);
Sean Crossbb389192013-09-26 11:24:47 +0800205
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500206 ret = pcie_phy_poll_ack(imx6_pcie, 1);
Sean Crossbb389192013-09-26 11:24:47 +0800207 if (ret)
208 return ret;
209
210 /* deassert cap data */
211 var = data << PCIE_PHY_CTRL_DATA_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 de-assertion */
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500215 ret = pcie_phy_poll_ack(imx6_pcie, 0);
Sean Crossbb389192013-09-26 11:24:47 +0800216 if (ret)
217 return ret;
218
219 /* assert wr signal */
220 var = 0x1 << PCIE_PHY_CTRL_WR_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 */
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500224 ret = pcie_phy_poll_ack(imx6_pcie, 1);
Sean Crossbb389192013-09-26 11:24:47 +0800225 if (ret)
226 return ret;
227
228 /* deassert wr signal */
229 var = data << PCIE_PHY_CTRL_DATA_LOC;
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530230 dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var);
Sean Crossbb389192013-09-26 11:24:47 +0800231
232 /* wait for ack de-assertion */
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500233 ret = pcie_phy_poll_ack(imx6_pcie, 0);
Sean Crossbb389192013-09-26 11:24:47 +0800234 if (ret)
235 return ret;
236
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530237 dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, 0x0);
Sean Crossbb389192013-09-26 11:24:47 +0800238
239 return 0;
240}
241
Bjorn Helgaase7d77052016-10-11 22:06:47 -0500242static void imx6_pcie_reset_phy(struct imx6_pcie *imx6_pcie)
Lucas Stach53eeb482016-01-15 19:56:47 +0100243{
244 u32 tmp;
245
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500246 pcie_phy_read(imx6_pcie, PHY_RX_OVRD_IN_LO, &tmp);
Lucas Stach53eeb482016-01-15 19:56:47 +0100247 tmp |= (PHY_RX_OVRD_IN_LO_RX_DATA_EN |
248 PHY_RX_OVRD_IN_LO_RX_PLL_EN);
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500249 pcie_phy_write(imx6_pcie, PHY_RX_OVRD_IN_LO, tmp);
Lucas Stach53eeb482016-01-15 19:56:47 +0100250
251 usleep_range(2000, 3000);
252
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500253 pcie_phy_read(imx6_pcie, PHY_RX_OVRD_IN_LO, &tmp);
Lucas Stach53eeb482016-01-15 19:56:47 +0100254 tmp &= ~(PHY_RX_OVRD_IN_LO_RX_DATA_EN |
255 PHY_RX_OVRD_IN_LO_RX_PLL_EN);
Bjorn Helgaas8bad7f22016-10-11 22:09:32 -0500256 pcie_phy_write(imx6_pcie, PHY_RX_OVRD_IN_LO, tmp);
Lucas Stach53eeb482016-01-15 19:56:47 +0100257}
258
Sean Crossbb389192013-09-26 11:24:47 +0800259/* Added for PCI abort handling */
260static int imx6q_pcie_abort_handler(unsigned long addr,
261 unsigned int fsr, struct pt_regs *regs)
262{
Lucas Stach415b6182017-05-22 17:06:30 -0500263 unsigned long pc = instruction_pointer(regs);
264 unsigned long instr = *(unsigned long *)pc;
265 int reg = (instr >> 12) & 15;
266
267 /*
268 * If the instruction being executed was a read,
269 * make it look like it read all-ones.
270 */
271 if ((instr & 0x0c100000) == 0x04100000) {
272 unsigned long val;
273
274 if (instr & 0x00400000)
275 val = 255;
276 else
277 val = -1;
278
279 regs->uregs[reg] = val;
280 regs->ARM_pc += 4;
281 return 0;
282 }
283
284 if ((instr & 0x0e100090) == 0x00100090) {
285 regs->uregs[reg] = -1;
286 regs->ARM_pc += 4;
287 return 0;
288 }
289
290 return 1;
Sean Crossbb389192013-09-26 11:24:47 +0800291}
292
Bjorn Helgaas9ab021b2016-10-06 13:35:17 -0500293static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
Sean Crossbb389192013-09-26 11:24:47 +0800294{
Quentin Schulzc26ebe92017-06-08 10:07:42 +0200295 struct device *dev = imx6_pcie->pci->dev;
296
Andrey Smirnove6f1fef2016-05-02 14:08:21 -0500297 switch (imx6_pcie->variant) {
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700298 case IMX7D:
299 reset_control_assert(imx6_pcie->pciephy_reset);
300 reset_control_assert(imx6_pcie->apps_reset);
301 break;
Andrey Smirnove6f1fef2016-05-02 14:08:21 -0500302 case IMX6SX:
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500303 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
304 IMX6SX_GPR12_PCIE_TEST_POWERDOWN,
305 IMX6SX_GPR12_PCIE_TEST_POWERDOWN);
306 /* Force PCIe PHY reset */
307 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR5,
308 IMX6SX_GPR5_PCIE_BTNRST_RESET,
309 IMX6SX_GPR5_PCIE_BTNRST_RESET);
Andrey Smirnove6f1fef2016-05-02 14:08:21 -0500310 break;
Andrey Smirnov4d31c612016-05-02 14:09:10 -0500311 case IMX6QP:
312 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
313 IMX6Q_GPR1_PCIE_SW_RST,
314 IMX6Q_GPR1_PCIE_SW_RST);
315 break;
Andrey Smirnove6f1fef2016-05-02 14:08:21 -0500316 case IMX6Q:
Andrey Smirnove6f1fef2016-05-02 14:08:21 -0500317 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
318 IMX6Q_GPR1_PCIE_TEST_PD, 1 << 18);
319 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
320 IMX6Q_GPR1_PCIE_REF_CLK_EN, 0 << 16);
321 break;
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500322 }
Quentin Schulzc26ebe92017-06-08 10:07:42 +0200323
324 if (imx6_pcie->vpcie && regulator_is_enabled(imx6_pcie->vpcie) > 0) {
325 int ret = regulator_disable(imx6_pcie->vpcie);
326
327 if (ret)
328 dev_err(dev, "failed to disable vpcie regulator: %d\n",
329 ret);
330 }
Sean Crossbb389192013-09-26 11:24:47 +0800331}
332
Bjorn Helgaas4d1821e2016-03-14 00:30:55 +0100333static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)
334{
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530335 struct dw_pcie *pci = imx6_pcie->pci;
336 struct device *dev = pci->dev;
Andrey Smirnove6f1fef2016-05-02 14:08:21 -0500337 int ret = 0;
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500338
Andrey Smirnove6f1fef2016-05-02 14:08:21 -0500339 switch (imx6_pcie->variant) {
340 case IMX6SX:
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500341 ret = clk_prepare_enable(imx6_pcie->pcie_inbound_axi);
342 if (ret) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500343 dev_err(dev, "unable to enable pcie_axi clock\n");
Andrey Smirnove6f1fef2016-05-02 14:08:21 -0500344 break;
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500345 }
346
347 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
348 IMX6SX_GPR12_PCIE_TEST_POWERDOWN, 0);
Andrey Smirnove6f1fef2016-05-02 14:08:21 -0500349 break;
Fabio Estevamc27fd682018-05-09 14:01:48 -0300350 case IMX6QP: /* FALLTHROUGH */
Andrey Smirnove6f1fef2016-05-02 14:08:21 -0500351 case IMX6Q:
352 /* power up core phy and enable ref clock */
353 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
354 IMX6Q_GPR1_PCIE_TEST_PD, 0 << 18);
355 /*
356 * the async reset input need ref clock to sync internally,
357 * when the ref clock comes after reset, internal synced
358 * reset time is too short, cannot meet the requirement.
359 * add one ~10us delay here.
360 */
361 udelay(10);
362 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
363 IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16);
364 break;
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700365 case IMX7D:
366 break;
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500367 }
368
Andrey Smirnove6f1fef2016-05-02 14:08:21 -0500369 return ret;
Bjorn Helgaas4d1821e2016-03-14 00:30:55 +0100370}
371
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700372static void imx7d_pcie_wait_for_phy_pll_lock(struct imx6_pcie *imx6_pcie)
373{
374 u32 val;
375 unsigned int retries;
376 struct device *dev = imx6_pcie->pci->dev;
377
378 for (retries = 0; retries < PHY_PLL_LOCK_WAIT_MAX_RETRIES; retries++) {
379 regmap_read(imx6_pcie->iomuxc_gpr, IOMUXC_GPR22, &val);
380
381 if (val & IMX7D_GPR22_PCIE_PHY_PLL_LOCKED)
382 return;
383
384 usleep_range(PHY_PLL_LOCK_WAIT_USLEEP_MIN,
385 PHY_PLL_LOCK_WAIT_USLEEP_MAX);
386 }
387
388 dev_err(dev, "PCIe PLL lock timeout\n");
389}
390
Bjorn Helgaas9ab021b2016-10-06 13:35:17 -0500391static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
Sean Crossbb389192013-09-26 11:24:47 +0800392{
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530393 struct dw_pcie *pci = imx6_pcie->pci;
394 struct device *dev = pci->dev;
Sean Crossbb389192013-09-26 11:24:47 +0800395 int ret;
396
Quentin Schulzc26ebe92017-06-08 10:07:42 +0200397 if (imx6_pcie->vpcie && !regulator_is_enabled(imx6_pcie->vpcie)) {
398 ret = regulator_enable(imx6_pcie->vpcie);
399 if (ret) {
400 dev_err(dev, "failed to enable vpcie regulator: %d\n",
401 ret);
402 return;
403 }
404 }
405
Lucas Stach57526132014-03-28 17:52:55 +0100406 ret = clk_prepare_enable(imx6_pcie->pcie_phy);
Sean Crossbb389192013-09-26 11:24:47 +0800407 if (ret) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500408 dev_err(dev, "unable to enable pcie_phy clock\n");
Quentin Schulzc26ebe92017-06-08 10:07:42 +0200409 goto err_pcie_phy;
Sean Crossbb389192013-09-26 11:24:47 +0800410 }
411
Lucas Stach57526132014-03-28 17:52:55 +0100412 ret = clk_prepare_enable(imx6_pcie->pcie_bus);
Sean Crossbb389192013-09-26 11:24:47 +0800413 if (ret) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500414 dev_err(dev, "unable to enable pcie_bus clock\n");
Lucas Stach57526132014-03-28 17:52:55 +0100415 goto err_pcie_bus;
Sean Crossbb389192013-09-26 11:24:47 +0800416 }
417
Lucas Stach57526132014-03-28 17:52:55 +0100418 ret = clk_prepare_enable(imx6_pcie->pcie);
Sean Crossbb389192013-09-26 11:24:47 +0800419 if (ret) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500420 dev_err(dev, "unable to enable pcie clock\n");
Lucas Stach57526132014-03-28 17:52:55 +0100421 goto err_pcie;
Sean Crossbb389192013-09-26 11:24:47 +0800422 }
423
Bjorn Helgaas4d1821e2016-03-14 00:30:55 +0100424 ret = imx6_pcie_enable_ref_clk(imx6_pcie);
425 if (ret) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500426 dev_err(dev, "unable to enable pcie ref clock\n");
Bjorn Helgaas4d1821e2016-03-14 00:30:55 +0100427 goto err_ref_clk;
428 }
Tim Harvey3fce0e82014-08-07 23:36:40 -0700429
Richard Zhua2fa6f62014-10-27 13:17:32 +0800430 /* allow the clocks to stabilize */
431 usleep_range(200, 500);
432
Richard Zhubc9ef772013-12-12 22:50:03 +0100433 /* Some boards don't have PCIe reset GPIO. */
Fabio Estevamb2d7a9c2016-03-28 18:45:36 -0300434 if (gpio_is_valid(imx6_pcie->reset_gpio)) {
Petr Štetiar3ea8529a2016-04-19 19:42:07 -0500435 gpio_set_value_cansleep(imx6_pcie->reset_gpio,
436 imx6_pcie->gpio_active_high);
Richard Zhubc9ef772013-12-12 22:50:03 +0100437 msleep(100);
Petr Štetiar3ea8529a2016-04-19 19:42:07 -0500438 gpio_set_value_cansleep(imx6_pcie->reset_gpio,
439 !imx6_pcie->gpio_active_high);
Richard Zhubc9ef772013-12-12 22:50:03 +0100440 }
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500441
Andrey Smirnov4d31c612016-05-02 14:09:10 -0500442 switch (imx6_pcie->variant) {
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700443 case IMX7D:
444 reset_control_deassert(imx6_pcie->pciephy_reset);
445 imx7d_pcie_wait_for_phy_pll_lock(imx6_pcie);
446 break;
Andrey Smirnov4d31c612016-05-02 14:09:10 -0500447 case IMX6SX:
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500448 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR5,
449 IMX6SX_GPR5_PCIE_BTNRST_RESET, 0);
Andrey Smirnov4d31c612016-05-02 14:09:10 -0500450 break;
451 case IMX6QP:
452 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
453 IMX6Q_GPR1_PCIE_SW_RST, 0);
454
455 usleep_range(200, 500);
456 break;
457 case IMX6Q: /* Nothing to do */
458 break;
459 }
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500460
Bjorn Helgaas9ab021b2016-10-06 13:35:17 -0500461 return;
Sean Crossbb389192013-09-26 11:24:47 +0800462
Bjorn Helgaas4d1821e2016-03-14 00:30:55 +0100463err_ref_clk:
464 clk_disable_unprepare(imx6_pcie->pcie);
Lucas Stach57526132014-03-28 17:52:55 +0100465err_pcie:
466 clk_disable_unprepare(imx6_pcie->pcie_bus);
467err_pcie_bus:
468 clk_disable_unprepare(imx6_pcie->pcie_phy);
Quentin Schulzc26ebe92017-06-08 10:07:42 +0200469err_pcie_phy:
470 if (imx6_pcie->vpcie && regulator_is_enabled(imx6_pcie->vpcie) > 0) {
471 ret = regulator_disable(imx6_pcie->vpcie);
472 if (ret)
473 dev_err(dev, "failed to disable vpcie regulator: %d\n",
474 ret);
475 }
Sean Crossbb389192013-09-26 11:24:47 +0800476}
477
Bjorn Helgaase7d77052016-10-11 22:06:47 -0500478static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie)
Sean Crossbb389192013-09-26 11:24:47 +0800479{
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700480 switch (imx6_pcie->variant) {
481 case IMX7D:
482 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
483 IMX7D_GPR12_PCIE_PHY_REFCLK_SEL, 0);
484 break;
485 case IMX6SX:
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500486 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
487 IMX6SX_GPR12_PCIE_RX_EQ_MASK,
488 IMX6SX_GPR12_PCIE_RX_EQ_2);
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700489 /* FALLTHROUGH */
490 default:
491 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
492 IMX6Q_GPR12_PCIE_CTL_2, 0 << 10);
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500493
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700494 /* configure constant input signal to the pcie ctrl and phy */
495 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
496 IMX6Q_GPR12_LOS_LEVEL, 9 << 4);
Sean Crossbb389192013-09-26 11:24:47 +0800497
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700498 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
499 IMX6Q_GPR8_TX_DEEMPH_GEN1,
500 imx6_pcie->tx_deemph_gen1 << 0);
501 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
502 IMX6Q_GPR8_TX_DEEMPH_GEN2_3P5DB,
503 imx6_pcie->tx_deemph_gen2_3p5db << 6);
504 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
505 IMX6Q_GPR8_TX_DEEMPH_GEN2_6DB,
506 imx6_pcie->tx_deemph_gen2_6db << 12);
507 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
508 IMX6Q_GPR8_TX_SWING_FULL,
509 imx6_pcie->tx_swing_full << 18);
510 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
511 IMX6Q_GPR8_TX_SWING_LOW,
512 imx6_pcie->tx_swing_low << 25);
513 break;
514 }
515
Sean Crossbb389192013-09-26 11:24:47 +0800516 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
517 IMX6Q_GPR12_DEVICE_TYPE, PCI_EXP_TYPE_ROOT_PORT << 12);
Sean Crossbb389192013-09-26 11:24:47 +0800518}
519
Lucas Stachf18f42d2018-07-31 12:21:49 +0200520static int imx6_setup_phy_mpll(struct imx6_pcie *imx6_pcie)
521{
522 unsigned long phy_rate = clk_get_rate(imx6_pcie->pcie_phy);
523 int mult, div;
524 u32 val;
525
526 switch (phy_rate) {
527 case 125000000:
528 /*
529 * The default settings of the MPLL are for a 125MHz input
530 * clock, so no need to reconfigure anything in that case.
531 */
532 return 0;
533 case 100000000:
534 mult = 25;
535 div = 0;
536 break;
537 case 200000000:
538 mult = 25;
539 div = 1;
540 break;
541 default:
542 dev_err(imx6_pcie->pci->dev,
543 "Unsupported PHY reference clock rate %lu\n", phy_rate);
544 return -EINVAL;
545 }
546
547 pcie_phy_read(imx6_pcie, PCIE_PHY_MPLL_OVRD_IN_LO, &val);
548 val &= ~(PCIE_PHY_MPLL_MULTIPLIER_MASK <<
549 PCIE_PHY_MPLL_MULTIPLIER_SHIFT);
550 val |= mult << PCIE_PHY_MPLL_MULTIPLIER_SHIFT;
551 val |= PCIE_PHY_MPLL_MULTIPLIER_OVRD;
552 pcie_phy_write(imx6_pcie, PCIE_PHY_MPLL_OVRD_IN_LO, val);
553
554 pcie_phy_read(imx6_pcie, PCIE_PHY_ATEOVRD, &val);
555 val &= ~(PCIE_PHY_ATEOVRD_REF_CLKDIV_MASK <<
556 PCIE_PHY_ATEOVRD_REF_CLKDIV_SHIFT);
557 val |= div << PCIE_PHY_ATEOVRD_REF_CLKDIV_SHIFT;
558 val |= PCIE_PHY_ATEOVRD_EN;
559 pcie_phy_write(imx6_pcie, PCIE_PHY_ATEOVRD, val);
560
561 return 0;
562}
563
Bjorn Helgaase7d77052016-10-11 22:06:47 -0500564static int imx6_pcie_wait_for_link(struct imx6_pcie *imx6_pcie)
Marek Vasut66a60f92013-12-12 22:50:01 +0100565{
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530566 struct dw_pcie *pci = imx6_pcie->pci;
567 struct device *dev = pci->dev;
Bjorn Helgaas13957652016-10-06 13:35:18 -0500568
Joao Pinto886bc5c2016-03-10 14:44:35 -0600569 /* check if the link is up or not */
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530570 if (!dw_pcie_wait_for_link(pci))
Joao Pinto886bc5c2016-03-10 14:44:35 -0600571 return 0;
Marek Vasut66a60f92013-12-12 22:50:01 +0100572
Bjorn Helgaas13957652016-10-06 13:35:18 -0500573 dev_dbg(dev, "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n",
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530574 dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R0),
575 dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R1));
Joao Pinto886bc5c2016-03-10 14:44:35 -0600576 return -ETIMEDOUT;
Marek Vasut66a60f92013-12-12 22:50:01 +0100577}
578
Bjorn Helgaase7d77052016-10-11 22:06:47 -0500579static int imx6_pcie_wait_for_speed_change(struct imx6_pcie *imx6_pcie)
Troy Kiskya0427462015-06-12 14:30:16 -0500580{
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530581 struct dw_pcie *pci = imx6_pcie->pci;
582 struct device *dev = pci->dev;
Bjorn Helgaas1c7fae12015-06-12 15:02:49 -0500583 u32 tmp;
Troy Kiskya0427462015-06-12 14:30:16 -0500584 unsigned int retries;
585
586 for (retries = 0; retries < 200; retries++) {
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530587 tmp = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL);
Troy Kiskya0427462015-06-12 14:30:16 -0500588 /* Test if the speed change finished. */
589 if (!(tmp & PORT_LOGIC_SPEED_CHANGE))
590 return 0;
591 usleep_range(100, 1000);
592 }
593
Bjorn Helgaas13957652016-10-06 13:35:18 -0500594 dev_err(dev, "Speed change timeout\n");
Troy Kiskya0427462015-06-12 14:30:16 -0500595 return -EINVAL;
Sean Crossbb389192013-09-26 11:24:47 +0800596}
597
Leonard Crestez0ee2c1f2018-08-27 14:28:37 +0300598static void imx6_pcie_ltssm_enable(struct device *dev)
599{
600 struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
601
602 switch (imx6_pcie->variant) {
603 case IMX6Q:
604 case IMX6SX:
605 case IMX6QP:
606 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
607 IMX6Q_GPR12_PCIE_CTL_2,
608 IMX6Q_GPR12_PCIE_CTL_2);
609 break;
610 case IMX7D:
611 reset_control_deassert(imx6_pcie->apps_reset);
612 break;
613 }
614}
615
Bjorn Helgaase7d77052016-10-11 22:06:47 -0500616static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)
Marek Vasutfa33a6d2013-12-12 22:50:02 +0100617{
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530618 struct dw_pcie *pci = imx6_pcie->pci;
619 struct device *dev = pci->dev;
Bjorn Helgaas1c7fae12015-06-12 15:02:49 -0500620 u32 tmp;
Troy Kiskya0427462015-06-12 14:30:16 -0500621 int ret;
Marek Vasutfa33a6d2013-12-12 22:50:02 +0100622
623 /*
624 * Force Gen1 operation when starting the link. In case the link is
625 * started in Gen2 mode, there is a possibility the devices on the
626 * bus will not be detected at all. This happens with PCIe switches.
627 */
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530628 tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCR);
Marek Vasutfa33a6d2013-12-12 22:50:02 +0100629 tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK;
630 tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1;
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530631 dw_pcie_writel_dbi(pci, PCIE_RC_LCR, tmp);
Marek Vasutfa33a6d2013-12-12 22:50:02 +0100632
633 /* Start LTSSM. */
Leonard Crestez0ee2c1f2018-08-27 14:28:37 +0300634 imx6_pcie_ltssm_enable(dev);
Marek Vasutfa33a6d2013-12-12 22:50:02 +0100635
Bjorn Helgaase7d77052016-10-11 22:06:47 -0500636 ret = imx6_pcie_wait_for_link(imx6_pcie);
Fabio Estevamcaf3f562016-12-27 12:40:43 -0200637 if (ret)
Lucas Stach54a47a82016-01-25 16:49:53 -0600638 goto err_reset_phy;
Marek Vasutfa33a6d2013-12-12 22:50:02 +0100639
Tim Harveya5fcec42016-04-19 19:52:44 -0500640 if (imx6_pcie->link_gen == 2) {
641 /* Allow Gen2 mode after the link is up. */
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530642 tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCR);
Tim Harveya5fcec42016-04-19 19:52:44 -0500643 tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK;
644 tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2;
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530645 dw_pcie_writel_dbi(pci, PCIE_RC_LCR, tmp);
Marek Vasutfa33a6d2013-12-12 22:50:02 +0100646
Andrey Smirnove6dcd872017-03-28 08:42:51 -0700647 /*
Andrey Smirnov93b226f2017-03-28 08:42:52 -0700648 * Start Directed Speed Change so the best possible
649 * speed both link partners support can be negotiated.
Andrey Smirnove6dcd872017-03-28 08:42:51 -0700650 */
Andrey Smirnov93b226f2017-03-28 08:42:52 -0700651 tmp = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL);
652 tmp |= PORT_LOGIC_SPEED_CHANGE;
653 dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp);
Andrey Smirnove6dcd872017-03-28 08:42:51 -0700654
Andrey Smirnov93b226f2017-03-28 08:42:52 -0700655 if (imx6_pcie->variant != IMX7D) {
656 /*
657 * On i.MX7, DIRECT_SPEED_CHANGE behaves differently
658 * from i.MX6 family when no link speed transition
659 * occurs and we go Gen1 -> yep, Gen1. The difference
660 * is that, in such case, it will not be cleared by HW
661 * which will cause the following code to report false
662 * failure.
663 */
664
665 ret = imx6_pcie_wait_for_speed_change(imx6_pcie);
666 if (ret) {
667 dev_err(dev, "Failed to bring link up!\n");
668 goto err_reset_phy;
669 }
670 }
671
672 /* Make sure link training is finished as well! */
673 ret = imx6_pcie_wait_for_link(imx6_pcie);
Andrey Smirnove6dcd872017-03-28 08:42:51 -0700674 if (ret) {
675 dev_err(dev, "Failed to bring link up!\n");
676 goto err_reset_phy;
677 }
Andrey Smirnov93b226f2017-03-28 08:42:52 -0700678 } else {
679 dev_info(dev, "Link: Gen2 disabled\n");
Marek Vasutfa33a6d2013-12-12 22:50:02 +0100680 }
681
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530682 tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCSR);
Bjorn Helgaas13957652016-10-06 13:35:18 -0500683 dev_info(dev, "Link up, Gen%i\n", (tmp >> 16) & 0xf);
Troy Kiskya0427462015-06-12 14:30:16 -0500684 return 0;
Lucas Stach54a47a82016-01-25 16:49:53 -0600685
686err_reset_phy:
Bjorn Helgaas13957652016-10-06 13:35:18 -0500687 dev_dbg(dev, "PHY DEBUG_R0=0x%08x DEBUG_R1=0x%08x\n",
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530688 dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R0),
689 dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R1));
Bjorn Helgaas2a6a85d2016-10-11 22:18:26 -0500690 imx6_pcie_reset_phy(imx6_pcie);
Lucas Stach54a47a82016-01-25 16:49:53 -0600691 return ret;
Marek Vasutfa33a6d2013-12-12 22:50:02 +0100692}
693
Bjorn Andersson4a301762017-07-15 23:39:45 -0700694static int imx6_pcie_host_init(struct pcie_port *pp)
Sean Crossbb389192013-09-26 11:24:47 +0800695{
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530696 struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
697 struct imx6_pcie *imx6_pcie = to_imx6_pcie(pci);
Sean Crossbb389192013-09-26 11:24:47 +0800698
Bjorn Helgaase7d77052016-10-11 22:06:47 -0500699 imx6_pcie_assert_core_reset(imx6_pcie);
700 imx6_pcie_init_phy(imx6_pcie);
701 imx6_pcie_deassert_core_reset(imx6_pcie);
Lucas Stachf18f42d2018-07-31 12:21:49 +0200702 imx6_setup_phy_mpll(imx6_pcie);
Sean Crossbb389192013-09-26 11:24:47 +0800703 dw_pcie_setup_rc(pp);
Bjorn Helgaase7d77052016-10-11 22:06:47 -0500704 imx6_pcie_establish_link(imx6_pcie);
Lucas Stachd1dc9742014-03-28 17:52:59 +0100705
706 if (IS_ENABLED(CONFIG_PCI_MSI))
707 dw_pcie_msi_init(pp);
Bjorn Andersson4a301762017-07-15 23:39:45 -0700708
709 return 0;
Sean Crossbb389192013-09-26 11:24:47 +0800710}
711
Jisheng Zhang4ab2e7c2017-06-05 16:53:46 +0800712static const struct dw_pcie_host_ops imx6_pcie_host_ops = {
Sean Crossbb389192013-09-26 11:24:47 +0800713 .host_init = imx6_pcie_host_init,
714};
715
Andrey Smirnovbde4a5a2017-03-28 08:42:50 -0700716static int imx6_add_pcie_port(struct imx6_pcie *imx6_pcie,
717 struct platform_device *pdev)
Sean Crossbb389192013-09-26 11:24:47 +0800718{
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530719 struct dw_pcie *pci = imx6_pcie->pci;
720 struct pcie_port *pp = &pci->pp;
721 struct device *dev = &pdev->dev;
Sean Crossbb389192013-09-26 11:24:47 +0800722 int ret;
723
Lucas Stachd1dc9742014-03-28 17:52:59 +0100724 if (IS_ENABLED(CONFIG_PCI_MSI)) {
725 pp->msi_irq = platform_get_irq_byname(pdev, "msi");
726 if (pp->msi_irq <= 0) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500727 dev_err(dev, "failed to get MSI irq\n");
Lucas Stachd1dc9742014-03-28 17:52:59 +0100728 return -ENODEV;
729 }
Lucas Stachd1dc9742014-03-28 17:52:59 +0100730 }
731
Sean Crossbb389192013-09-26 11:24:47 +0800732 pp->ops = &imx6_pcie_host_ops;
733
Sean Crossbb389192013-09-26 11:24:47 +0800734 ret = dw_pcie_host_init(pp);
735 if (ret) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500736 dev_err(dev, "failed to initialize host\n");
Sean Crossbb389192013-09-26 11:24:47 +0800737 return ret;
738 }
739
740 return 0;
741}
742
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530743static const struct dw_pcie_ops dw_pcie_ops = {
Trent Piepho68bc10b2018-11-05 18:11:36 +0000744 /* No special ops needed, but pcie-designware still expects this struct */
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530745};
746
Leonard Crestez0ee2c1f2018-08-27 14:28:37 +0300747#ifdef CONFIG_PM_SLEEP
748static void imx6_pcie_ltssm_disable(struct device *dev)
749{
750 struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
751
752 switch (imx6_pcie->variant) {
753 case IMX6SX:
754 case IMX6QP:
755 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
756 IMX6Q_GPR12_PCIE_CTL_2, 0);
757 break;
758 case IMX7D:
759 reset_control_assert(imx6_pcie->apps_reset);
760 break;
761 default:
762 dev_err(dev, "ltssm_disable not supported\n");
763 }
764}
765
Leonard Crestezf4e833b2018-07-19 17:02:10 +0300766static void imx6_pcie_pm_turnoff(struct imx6_pcie *imx6_pcie)
767{
768 reset_control_assert(imx6_pcie->turnoff_reset);
769 reset_control_deassert(imx6_pcie->turnoff_reset);
770
771 /*
772 * Components with an upstream port must respond to
773 * PME_Turn_Off with PME_TO_Ack but we can't check.
774 *
775 * The standard recommends a 1-10ms timeout after which to
776 * proceed anyway as if acks were received.
777 */
778 usleep_range(1000, 10000);
779}
780
Leonard Crestez0ee2c1f2018-08-27 14:28:37 +0300781static void imx6_pcie_clk_disable(struct imx6_pcie *imx6_pcie)
782{
783 clk_disable_unprepare(imx6_pcie->pcie);
784 clk_disable_unprepare(imx6_pcie->pcie_phy);
785 clk_disable_unprepare(imx6_pcie->pcie_bus);
786
787 if (imx6_pcie->variant == IMX7D) {
788 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
789 IMX7D_GPR12_PCIE_PHY_REFCLK_SEL,
790 IMX7D_GPR12_PCIE_PHY_REFCLK_SEL);
791 }
792}
793
794static int imx6_pcie_suspend_noirq(struct device *dev)
795{
796 struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
797
798 if (imx6_pcie->variant != IMX7D)
799 return 0;
800
Leonard Crestezf4e833b2018-07-19 17:02:10 +0300801 imx6_pcie_pm_turnoff(imx6_pcie);
Leonard Crestez0ee2c1f2018-08-27 14:28:37 +0300802 imx6_pcie_clk_disable(imx6_pcie);
803 imx6_pcie_ltssm_disable(dev);
804
805 return 0;
806}
807
808static int imx6_pcie_resume_noirq(struct device *dev)
809{
810 int ret;
811 struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
812 struct pcie_port *pp = &imx6_pcie->pci->pp;
813
814 if (imx6_pcie->variant != IMX7D)
815 return 0;
816
817 imx6_pcie_assert_core_reset(imx6_pcie);
818 imx6_pcie_init_phy(imx6_pcie);
819 imx6_pcie_deassert_core_reset(imx6_pcie);
820 dw_pcie_setup_rc(pp);
821
822 ret = imx6_pcie_establish_link(imx6_pcie);
823 if (ret < 0)
824 dev_info(dev, "pcie link is down after resume.\n");
825
826 return 0;
827}
828#endif
829
830static const struct dev_pm_ops imx6_pcie_pm_ops = {
831 SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx6_pcie_suspend_noirq,
832 imx6_pcie_resume_noirq)
833};
834
Andrey Smirnovbde4a5a2017-03-28 08:42:50 -0700835static int imx6_pcie_probe(struct platform_device *pdev)
Sean Crossbb389192013-09-26 11:24:47 +0800836{
Bjorn Helgaas13957652016-10-06 13:35:18 -0500837 struct device *dev = &pdev->dev;
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530838 struct dw_pcie *pci;
Sean Crossbb389192013-09-26 11:24:47 +0800839 struct imx6_pcie *imx6_pcie;
Sean Crossbb389192013-09-26 11:24:47 +0800840 struct resource *dbi_base;
Bjorn Helgaas13957652016-10-06 13:35:18 -0500841 struct device_node *node = dev->of_node;
Sean Crossbb389192013-09-26 11:24:47 +0800842 int ret;
843
Bjorn Helgaas13957652016-10-06 13:35:18 -0500844 imx6_pcie = devm_kzalloc(dev, sizeof(*imx6_pcie), GFP_KERNEL);
Sean Crossbb389192013-09-26 11:24:47 +0800845 if (!imx6_pcie)
846 return -ENOMEM;
847
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530848 pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
849 if (!pci)
850 return -ENOMEM;
851
852 pci->dev = dev;
853 pci->ops = &dw_pcie_ops;
Sean Crossbb389192013-09-26 11:24:47 +0800854
Guenter Roeckc0464062017-02-25 02:08:12 -0800855 imx6_pcie->pci = pci;
Andrey Smirnove6f1fef2016-05-02 14:08:21 -0500856 imx6_pcie->variant =
Bjorn Helgaas13957652016-10-06 13:35:18 -0500857 (enum imx6_pcie_variants)of_device_get_match_data(dev);
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500858
Sean Crossbb389192013-09-26 11:24:47 +0800859 dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530860 pci->dbi_base = devm_ioremap_resource(dev, dbi_base);
861 if (IS_ERR(pci->dbi_base))
862 return PTR_ERR(pci->dbi_base);
Sean Crossbb389192013-09-26 11:24:47 +0800863
864 /* Fetch GPIOs */
Bjorn Helgaasc5af4072016-10-06 13:35:18 -0500865 imx6_pcie->reset_gpio = of_get_named_gpio(node, "reset-gpio", 0);
866 imx6_pcie->gpio_active_high = of_property_read_bool(node,
Petr Štetiar3ea8529a2016-04-19 19:42:07 -0500867 "reset-gpio-active-high");
Fabio Estevamb2d7a9c2016-03-28 18:45:36 -0300868 if (gpio_is_valid(imx6_pcie->reset_gpio)) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500869 ret = devm_gpio_request_one(dev, imx6_pcie->reset_gpio,
Petr Štetiar3ea8529a2016-04-19 19:42:07 -0500870 imx6_pcie->gpio_active_high ?
871 GPIOF_OUT_INIT_HIGH :
872 GPIOF_OUT_INIT_LOW,
873 "PCIe reset");
Fabio Estevamb2d7a9c2016-03-28 18:45:36 -0300874 if (ret) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500875 dev_err(dev, "unable to get reset gpio\n");
Fabio Estevamb2d7a9c2016-03-28 18:45:36 -0300876 return ret;
877 }
Andrey Smirnovbde4a5a2017-03-28 08:42:50 -0700878 } else if (imx6_pcie->reset_gpio == -EPROBE_DEFER) {
879 return imx6_pcie->reset_gpio;
Fabio Estevamb2d7a9c2016-03-28 18:45:36 -0300880 }
Sean Crossbb389192013-09-26 11:24:47 +0800881
Sean Crossbb389192013-09-26 11:24:47 +0800882 /* Fetch clocks */
Bjorn Helgaas13957652016-10-06 13:35:18 -0500883 imx6_pcie->pcie_phy = devm_clk_get(dev, "pcie_phy");
Lucas Stach57526132014-03-28 17:52:55 +0100884 if (IS_ERR(imx6_pcie->pcie_phy)) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500885 dev_err(dev, "pcie_phy clock source missing or invalid\n");
Lucas Stach57526132014-03-28 17:52:55 +0100886 return PTR_ERR(imx6_pcie->pcie_phy);
Sean Crossbb389192013-09-26 11:24:47 +0800887 }
888
Bjorn Helgaas13957652016-10-06 13:35:18 -0500889 imx6_pcie->pcie_bus = devm_clk_get(dev, "pcie_bus");
Lucas Stach57526132014-03-28 17:52:55 +0100890 if (IS_ERR(imx6_pcie->pcie_bus)) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500891 dev_err(dev, "pcie_bus clock source missing or invalid\n");
Lucas Stach57526132014-03-28 17:52:55 +0100892 return PTR_ERR(imx6_pcie->pcie_bus);
Sean Crossbb389192013-09-26 11:24:47 +0800893 }
894
Bjorn Helgaas13957652016-10-06 13:35:18 -0500895 imx6_pcie->pcie = devm_clk_get(dev, "pcie");
Lucas Stach57526132014-03-28 17:52:55 +0100896 if (IS_ERR(imx6_pcie->pcie)) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500897 dev_err(dev, "pcie clock source missing or invalid\n");
Lucas Stach57526132014-03-28 17:52:55 +0100898 return PTR_ERR(imx6_pcie->pcie);
Sean Crossbb389192013-09-26 11:24:47 +0800899 }
900
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700901 switch (imx6_pcie->variant) {
902 case IMX6SX:
Bjorn Helgaas13957652016-10-06 13:35:18 -0500903 imx6_pcie->pcie_inbound_axi = devm_clk_get(dev,
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500904 "pcie_inbound_axi");
905 if (IS_ERR(imx6_pcie->pcie_inbound_axi)) {
Andrey Smirnov21b72452017-02-07 07:50:25 -0800906 dev_err(dev, "pcie_inbound_axi clock missing or invalid\n");
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500907 return PTR_ERR(imx6_pcie->pcie_inbound_axi);
908 }
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700909 break;
910 case IMX7D:
Philipp Zabel7c180582017-07-19 17:25:56 +0200911 imx6_pcie->pciephy_reset = devm_reset_control_get_exclusive(dev,
912 "pciephy");
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700913 if (IS_ERR(imx6_pcie->pciephy_reset)) {
Colin Ian King72215472017-04-21 08:02:30 +0100914 dev_err(dev, "Failed to get PCIEPHY reset control\n");
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700915 return PTR_ERR(imx6_pcie->pciephy_reset);
916 }
917
Philipp Zabel7c180582017-07-19 17:25:56 +0200918 imx6_pcie->apps_reset = devm_reset_control_get_exclusive(dev,
919 "apps");
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700920 if (IS_ERR(imx6_pcie->apps_reset)) {
Colin Ian King72215472017-04-21 08:02:30 +0100921 dev_err(dev, "Failed to get PCIE APPS reset control\n");
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700922 return PTR_ERR(imx6_pcie->apps_reset);
923 }
924 break;
925 default:
926 break;
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500927 }
928
Leonard Crestezf4e833b2018-07-19 17:02:10 +0300929 /* Grab turnoff reset */
930 imx6_pcie->turnoff_reset = devm_reset_control_get_optional_exclusive(dev, "turnoff");
931 if (IS_ERR(imx6_pcie->turnoff_reset)) {
932 dev_err(dev, "Failed to get TURNOFF reset control\n");
933 return PTR_ERR(imx6_pcie->turnoff_reset);
934 }
935
Sean Crossbb389192013-09-26 11:24:47 +0800936 /* Grab GPR config register range */
937 imx6_pcie->iomuxc_gpr =
938 syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
939 if (IS_ERR(imx6_pcie->iomuxc_gpr)) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500940 dev_err(dev, "unable to find iomuxc registers\n");
Fabio Estevamb391bf32013-12-02 01:39:35 -0200941 return PTR_ERR(imx6_pcie->iomuxc_gpr);
Sean Crossbb389192013-09-26 11:24:47 +0800942 }
943
Justin Waters28e3abe2016-01-15 10:24:35 -0500944 /* Grab PCIe PHY Tx Settings */
945 if (of_property_read_u32(node, "fsl,tx-deemph-gen1",
946 &imx6_pcie->tx_deemph_gen1))
947 imx6_pcie->tx_deemph_gen1 = 0;
948
949 if (of_property_read_u32(node, "fsl,tx-deemph-gen2-3p5db",
950 &imx6_pcie->tx_deemph_gen2_3p5db))
951 imx6_pcie->tx_deemph_gen2_3p5db = 0;
952
953 if (of_property_read_u32(node, "fsl,tx-deemph-gen2-6db",
954 &imx6_pcie->tx_deemph_gen2_6db))
955 imx6_pcie->tx_deemph_gen2_6db = 20;
956
957 if (of_property_read_u32(node, "fsl,tx-swing-full",
958 &imx6_pcie->tx_swing_full))
959 imx6_pcie->tx_swing_full = 127;
960
961 if (of_property_read_u32(node, "fsl,tx-swing-low",
962 &imx6_pcie->tx_swing_low))
963 imx6_pcie->tx_swing_low = 127;
964
Tim Harveya5fcec42016-04-19 19:52:44 -0500965 /* Limit link speed */
Bjorn Helgaasc5af4072016-10-06 13:35:18 -0500966 ret = of_property_read_u32(node, "fsl,max-link-speed",
Tim Harveya5fcec42016-04-19 19:52:44 -0500967 &imx6_pcie->link_gen);
968 if (ret)
969 imx6_pcie->link_gen = 1;
970
Quentin Schulzc26ebe92017-06-08 10:07:42 +0200971 imx6_pcie->vpcie = devm_regulator_get_optional(&pdev->dev, "vpcie");
972 if (IS_ERR(imx6_pcie->vpcie)) {
973 if (PTR_ERR(imx6_pcie->vpcie) == -EPROBE_DEFER)
974 return -EPROBE_DEFER;
975 imx6_pcie->vpcie = NULL;
976 }
977
Kishon Vijay Abraham I9bcf0a62017-02-15 18:48:11 +0530978 platform_set_drvdata(pdev, imx6_pcie);
979
Bjorn Helgaase7d77052016-10-11 22:06:47 -0500980 ret = imx6_add_pcie_port(imx6_pcie, pdev);
Sean Crossbb389192013-09-26 11:24:47 +0800981 if (ret < 0)
Fabio Estevamb391bf32013-12-02 01:39:35 -0200982 return ret;
Sean Crossbb389192013-09-26 11:24:47 +0800983
Sean Crossbb389192013-09-26 11:24:47 +0800984 return 0;
Sean Crossbb389192013-09-26 11:24:47 +0800985}
986
Lucas Stach3e3e4062014-07-31 20:16:05 +0200987static void imx6_pcie_shutdown(struct platform_device *pdev)
988{
989 struct imx6_pcie *imx6_pcie = platform_get_drvdata(pdev);
990
991 /* bring down link, so bootloader gets clean state in case of reboot */
Bjorn Helgaase7d77052016-10-11 22:06:47 -0500992 imx6_pcie_assert_core_reset(imx6_pcie);
Lucas Stach3e3e4062014-07-31 20:16:05 +0200993}
994
Sean Crossbb389192013-09-26 11:24:47 +0800995static const struct of_device_id imx6_pcie_of_match[] = {
Andrey Smirnove6f1fef2016-05-02 14:08:21 -0500996 { .compatible = "fsl,imx6q-pcie", .data = (void *)IMX6Q, },
997 { .compatible = "fsl,imx6sx-pcie", .data = (void *)IMX6SX, },
Andrey Smirnov4d31c612016-05-02 14:09:10 -0500998 { .compatible = "fsl,imx6qp-pcie", .data = (void *)IMX6QP, },
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700999 { .compatible = "fsl,imx7d-pcie", .data = (void *)IMX7D, },
Sean Crossbb389192013-09-26 11:24:47 +08001000 {},
1001};
Sean Crossbb389192013-09-26 11:24:47 +08001002
1003static struct platform_driver imx6_pcie_driver = {
1004 .driver = {
1005 .name = "imx6q-pcie",
Sachin Kamat8bcadbe2013-10-21 14:36:41 +05301006 .of_match_table = imx6_pcie_of_match,
Brian Norrisa5f40e82017-04-20 15:36:25 -05001007 .suppress_bind_attrs = true,
Leonard Crestez0ee2c1f2018-08-27 14:28:37 +03001008 .pm = &imx6_pcie_pm_ops,
Sean Crossbb389192013-09-26 11:24:47 +08001009 },
Andrey Smirnovbde4a5a2017-03-28 08:42:50 -07001010 .probe = imx6_pcie_probe,
Lucas Stach3e3e4062014-07-31 20:16:05 +02001011 .shutdown = imx6_pcie_shutdown,
Sean Crossbb389192013-09-26 11:24:47 +08001012};
1013
Sean Crossbb389192013-09-26 11:24:47 +08001014static int __init imx6_pcie_init(void)
1015{
Andrey Smirnovbde4a5a2017-03-28 08:42:50 -07001016 /*
1017 * Since probe() can be deferred we need to make sure that
1018 * hook_fault_code is not called after __init memory is freed
1019 * by kernel and since imx6q_pcie_abort_handler() is a no-op,
1020 * we can install the handler here without risking it
1021 * accessing some uninitialized driver state.
1022 */
Lucas Stach415b6182017-05-22 17:06:30 -05001023 hook_fault_code(8, imx6q_pcie_abort_handler, SIGBUS, 0,
1024 "external abort on non-linefetch");
Andrey Smirnovbde4a5a2017-03-28 08:42:50 -07001025
1026 return platform_driver_register(&imx6_pcie_driver);
Sean Crossbb389192013-09-26 11:24:47 +08001027}
Paul Gortmakerf90d8e82016-08-22 17:59:43 -04001028device_initcall(imx6_pcie_init);