blob: 4fddbd08b08911fdf88771bea5ee8ac036214b8f [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;
Andrey Smirnov4d31c612016-05-02 14:09:10 -0500341 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
Lucas Stachd1dc9742014-03-28 17:52:59 +0100545static irqreturn_t imx6_pcie_msi_handler(int irq, void *arg)
546{
Bjorn Helgaase7d77052016-10-11 22:06:47 -0500547 struct imx6_pcie *imx6_pcie = arg;
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530548 struct dw_pcie *pci = imx6_pcie->pci;
549 struct pcie_port *pp = &pci->pp;
Lucas Stachd1dc9742014-03-28 17:52:59 +0100550
551 return dw_handle_msi_irq(pp);
552}
553
Bjorn Helgaase7d77052016-10-11 22:06:47 -0500554static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)
Marek Vasutfa33a6d2013-12-12 22:50:02 +0100555{
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530556 struct dw_pcie *pci = imx6_pcie->pci;
557 struct device *dev = pci->dev;
Bjorn Helgaas1c7fae12015-06-12 15:02:49 -0500558 u32 tmp;
Troy Kiskya0427462015-06-12 14:30:16 -0500559 int ret;
Marek Vasutfa33a6d2013-12-12 22:50:02 +0100560
561 /*
562 * Force Gen1 operation when starting the link. In case the link is
563 * started in Gen2 mode, there is a possibility the devices on the
564 * bus will not be detected at all. This happens with PCIe switches.
565 */
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530566 tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCR);
Marek Vasutfa33a6d2013-12-12 22:50:02 +0100567 tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK;
568 tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1;
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530569 dw_pcie_writel_dbi(pci, PCIE_RC_LCR, tmp);
Marek Vasutfa33a6d2013-12-12 22:50:02 +0100570
571 /* Start LTSSM. */
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700572 if (imx6_pcie->variant == IMX7D)
573 reset_control_deassert(imx6_pcie->apps_reset);
574 else
575 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
576 IMX6Q_GPR12_PCIE_CTL_2, 1 << 10);
Marek Vasutfa33a6d2013-12-12 22:50:02 +0100577
Bjorn Helgaase7d77052016-10-11 22:06:47 -0500578 ret = imx6_pcie_wait_for_link(imx6_pcie);
Fabio Estevamcaf3f562016-12-27 12:40:43 -0200579 if (ret)
Lucas Stach54a47a82016-01-25 16:49:53 -0600580 goto err_reset_phy;
Marek Vasutfa33a6d2013-12-12 22:50:02 +0100581
Tim Harveya5fcec42016-04-19 19:52:44 -0500582 if (imx6_pcie->link_gen == 2) {
583 /* Allow Gen2 mode after the link is up. */
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530584 tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCR);
Tim Harveya5fcec42016-04-19 19:52:44 -0500585 tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK;
586 tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2;
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530587 dw_pcie_writel_dbi(pci, PCIE_RC_LCR, tmp);
Marek Vasutfa33a6d2013-12-12 22:50:02 +0100588
Andrey Smirnove6dcd872017-03-28 08:42:51 -0700589 /*
Andrey Smirnov93b226f2017-03-28 08:42:52 -0700590 * Start Directed Speed Change so the best possible
591 * speed both link partners support can be negotiated.
Andrey Smirnove6dcd872017-03-28 08:42:51 -0700592 */
Andrey Smirnov93b226f2017-03-28 08:42:52 -0700593 tmp = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL);
594 tmp |= PORT_LOGIC_SPEED_CHANGE;
595 dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp);
Andrey Smirnove6dcd872017-03-28 08:42:51 -0700596
Andrey Smirnov93b226f2017-03-28 08:42:52 -0700597 if (imx6_pcie->variant != IMX7D) {
598 /*
599 * On i.MX7, DIRECT_SPEED_CHANGE behaves differently
600 * from i.MX6 family when no link speed transition
601 * occurs and we go Gen1 -> yep, Gen1. The difference
602 * is that, in such case, it will not be cleared by HW
603 * which will cause the following code to report false
604 * failure.
605 */
606
607 ret = imx6_pcie_wait_for_speed_change(imx6_pcie);
608 if (ret) {
609 dev_err(dev, "Failed to bring link up!\n");
610 goto err_reset_phy;
611 }
612 }
613
614 /* Make sure link training is finished as well! */
615 ret = imx6_pcie_wait_for_link(imx6_pcie);
Andrey Smirnove6dcd872017-03-28 08:42:51 -0700616 if (ret) {
617 dev_err(dev, "Failed to bring link up!\n");
618 goto err_reset_phy;
619 }
Andrey Smirnov93b226f2017-03-28 08:42:52 -0700620 } else {
621 dev_info(dev, "Link: Gen2 disabled\n");
Marek Vasutfa33a6d2013-12-12 22:50:02 +0100622 }
623
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530624 tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCSR);
Bjorn Helgaas13957652016-10-06 13:35:18 -0500625 dev_info(dev, "Link up, Gen%i\n", (tmp >> 16) & 0xf);
Troy Kiskya0427462015-06-12 14:30:16 -0500626 return 0;
Lucas Stach54a47a82016-01-25 16:49:53 -0600627
628err_reset_phy:
Bjorn Helgaas13957652016-10-06 13:35:18 -0500629 dev_dbg(dev, "PHY DEBUG_R0=0x%08x DEBUG_R1=0x%08x\n",
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530630 dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R0),
631 dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R1));
Bjorn Helgaas2a6a85d2016-10-11 22:18:26 -0500632 imx6_pcie_reset_phy(imx6_pcie);
Lucas Stach54a47a82016-01-25 16:49:53 -0600633 return ret;
Marek Vasutfa33a6d2013-12-12 22:50:02 +0100634}
635
Bjorn Andersson4a301762017-07-15 23:39:45 -0700636static int imx6_pcie_host_init(struct pcie_port *pp)
Sean Crossbb389192013-09-26 11:24:47 +0800637{
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530638 struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
639 struct imx6_pcie *imx6_pcie = to_imx6_pcie(pci);
Sean Crossbb389192013-09-26 11:24:47 +0800640
Bjorn Helgaase7d77052016-10-11 22:06:47 -0500641 imx6_pcie_assert_core_reset(imx6_pcie);
642 imx6_pcie_init_phy(imx6_pcie);
643 imx6_pcie_deassert_core_reset(imx6_pcie);
Sean Crossbb389192013-09-26 11:24:47 +0800644 dw_pcie_setup_rc(pp);
Bjorn Helgaase7d77052016-10-11 22:06:47 -0500645 imx6_pcie_establish_link(imx6_pcie);
Lucas Stachd1dc9742014-03-28 17:52:59 +0100646
647 if (IS_ENABLED(CONFIG_PCI_MSI))
648 dw_pcie_msi_init(pp);
Bjorn Andersson4a301762017-07-15 23:39:45 -0700649
650 return 0;
Sean Crossbb389192013-09-26 11:24:47 +0800651}
652
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530653static int imx6_pcie_link_up(struct dw_pcie *pci)
Sean Crossbb389192013-09-26 11:24:47 +0800654{
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530655 return dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R1) &
Lucas Stach4d107d32016-01-25 16:50:02 -0600656 PCIE_PHY_DEBUG_R1_XMLH_LINK_UP;
Sean Crossbb389192013-09-26 11:24:47 +0800657}
658
Jisheng Zhang4ab2e7c2017-06-05 16:53:46 +0800659static const struct dw_pcie_host_ops imx6_pcie_host_ops = {
Sean Crossbb389192013-09-26 11:24:47 +0800660 .host_init = imx6_pcie_host_init,
661};
662
Andrey Smirnovbde4a5a2017-03-28 08:42:50 -0700663static int imx6_add_pcie_port(struct imx6_pcie *imx6_pcie,
664 struct platform_device *pdev)
Sean Crossbb389192013-09-26 11:24:47 +0800665{
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530666 struct dw_pcie *pci = imx6_pcie->pci;
667 struct pcie_port *pp = &pci->pp;
668 struct device *dev = &pdev->dev;
Sean Crossbb389192013-09-26 11:24:47 +0800669 int ret;
670
Lucas Stachd1dc9742014-03-28 17:52:59 +0100671 if (IS_ENABLED(CONFIG_PCI_MSI)) {
672 pp->msi_irq = platform_get_irq_byname(pdev, "msi");
673 if (pp->msi_irq <= 0) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500674 dev_err(dev, "failed to get MSI irq\n");
Lucas Stachd1dc9742014-03-28 17:52:59 +0100675 return -ENODEV;
676 }
677
Bjorn Helgaas13957652016-10-06 13:35:18 -0500678 ret = devm_request_irq(dev, pp->msi_irq,
Jingoo Hand88a7ef2014-11-12 12:25:09 +0900679 imx6_pcie_msi_handler,
Grygorii Strashko8ff0ef92015-12-10 21:18:20 +0200680 IRQF_SHARED | IRQF_NO_THREAD,
Bjorn Helgaase7d77052016-10-11 22:06:47 -0500681 "mx6-pcie-msi", imx6_pcie);
Lucas Stachd1dc9742014-03-28 17:52:59 +0100682 if (ret) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500683 dev_err(dev, "failed to request MSI irq\n");
Fabio Estevam89b2d4f2015-09-11 09:08:52 -0300684 return ret;
Lucas Stachd1dc9742014-03-28 17:52:59 +0100685 }
686 }
687
Sean Crossbb389192013-09-26 11:24:47 +0800688 pp->root_bus_nr = -1;
689 pp->ops = &imx6_pcie_host_ops;
690
Sean Crossbb389192013-09-26 11:24:47 +0800691 ret = dw_pcie_host_init(pp);
692 if (ret) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500693 dev_err(dev, "failed to initialize host\n");
Sean Crossbb389192013-09-26 11:24:47 +0800694 return ret;
695 }
696
697 return 0;
698}
699
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530700static const struct dw_pcie_ops dw_pcie_ops = {
701 .link_up = imx6_pcie_link_up,
702};
703
Andrey Smirnovbde4a5a2017-03-28 08:42:50 -0700704static int imx6_pcie_probe(struct platform_device *pdev)
Sean Crossbb389192013-09-26 11:24:47 +0800705{
Bjorn Helgaas13957652016-10-06 13:35:18 -0500706 struct device *dev = &pdev->dev;
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530707 struct dw_pcie *pci;
Sean Crossbb389192013-09-26 11:24:47 +0800708 struct imx6_pcie *imx6_pcie;
Sean Crossbb389192013-09-26 11:24:47 +0800709 struct resource *dbi_base;
Bjorn Helgaas13957652016-10-06 13:35:18 -0500710 struct device_node *node = dev->of_node;
Sean Crossbb389192013-09-26 11:24:47 +0800711 int ret;
712
Bjorn Helgaas13957652016-10-06 13:35:18 -0500713 imx6_pcie = devm_kzalloc(dev, sizeof(*imx6_pcie), GFP_KERNEL);
Sean Crossbb389192013-09-26 11:24:47 +0800714 if (!imx6_pcie)
715 return -ENOMEM;
716
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530717 pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
718 if (!pci)
719 return -ENOMEM;
720
721 pci->dev = dev;
722 pci->ops = &dw_pcie_ops;
Sean Crossbb389192013-09-26 11:24:47 +0800723
Guenter Roeckc0464062017-02-25 02:08:12 -0800724 imx6_pcie->pci = pci;
Andrey Smirnove6f1fef2016-05-02 14:08:21 -0500725 imx6_pcie->variant =
Bjorn Helgaas13957652016-10-06 13:35:18 -0500726 (enum imx6_pcie_variants)of_device_get_match_data(dev);
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500727
Sean Crossbb389192013-09-26 11:24:47 +0800728 dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Kishon Vijay Abraham I442ec4c2017-02-15 18:48:14 +0530729 pci->dbi_base = devm_ioremap_resource(dev, dbi_base);
730 if (IS_ERR(pci->dbi_base))
731 return PTR_ERR(pci->dbi_base);
Sean Crossbb389192013-09-26 11:24:47 +0800732
733 /* Fetch GPIOs */
Bjorn Helgaasc5af4072016-10-06 13:35:18 -0500734 imx6_pcie->reset_gpio = of_get_named_gpio(node, "reset-gpio", 0);
735 imx6_pcie->gpio_active_high = of_property_read_bool(node,
Petr Štetiar3ea8529a2016-04-19 19:42:07 -0500736 "reset-gpio-active-high");
Fabio Estevamb2d7a9c2016-03-28 18:45:36 -0300737 if (gpio_is_valid(imx6_pcie->reset_gpio)) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500738 ret = devm_gpio_request_one(dev, imx6_pcie->reset_gpio,
Petr Štetiar3ea8529a2016-04-19 19:42:07 -0500739 imx6_pcie->gpio_active_high ?
740 GPIOF_OUT_INIT_HIGH :
741 GPIOF_OUT_INIT_LOW,
742 "PCIe reset");
Fabio Estevamb2d7a9c2016-03-28 18:45:36 -0300743 if (ret) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500744 dev_err(dev, "unable to get reset gpio\n");
Fabio Estevamb2d7a9c2016-03-28 18:45:36 -0300745 return ret;
746 }
Andrey Smirnovbde4a5a2017-03-28 08:42:50 -0700747 } else if (imx6_pcie->reset_gpio == -EPROBE_DEFER) {
748 return imx6_pcie->reset_gpio;
Fabio Estevamb2d7a9c2016-03-28 18:45:36 -0300749 }
Sean Crossbb389192013-09-26 11:24:47 +0800750
Sean Crossbb389192013-09-26 11:24:47 +0800751 /* Fetch clocks */
Bjorn Helgaas13957652016-10-06 13:35:18 -0500752 imx6_pcie->pcie_phy = devm_clk_get(dev, "pcie_phy");
Lucas Stach57526132014-03-28 17:52:55 +0100753 if (IS_ERR(imx6_pcie->pcie_phy)) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500754 dev_err(dev, "pcie_phy clock source missing or invalid\n");
Lucas Stach57526132014-03-28 17:52:55 +0100755 return PTR_ERR(imx6_pcie->pcie_phy);
Sean Crossbb389192013-09-26 11:24:47 +0800756 }
757
Bjorn Helgaas13957652016-10-06 13:35:18 -0500758 imx6_pcie->pcie_bus = devm_clk_get(dev, "pcie_bus");
Lucas Stach57526132014-03-28 17:52:55 +0100759 if (IS_ERR(imx6_pcie->pcie_bus)) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500760 dev_err(dev, "pcie_bus clock source missing or invalid\n");
Lucas Stach57526132014-03-28 17:52:55 +0100761 return PTR_ERR(imx6_pcie->pcie_bus);
Sean Crossbb389192013-09-26 11:24:47 +0800762 }
763
Bjorn Helgaas13957652016-10-06 13:35:18 -0500764 imx6_pcie->pcie = devm_clk_get(dev, "pcie");
Lucas Stach57526132014-03-28 17:52:55 +0100765 if (IS_ERR(imx6_pcie->pcie)) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500766 dev_err(dev, "pcie clock source missing or invalid\n");
Lucas Stach57526132014-03-28 17:52:55 +0100767 return PTR_ERR(imx6_pcie->pcie);
Sean Crossbb389192013-09-26 11:24:47 +0800768 }
769
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700770 switch (imx6_pcie->variant) {
771 case IMX6SX:
Bjorn Helgaas13957652016-10-06 13:35:18 -0500772 imx6_pcie->pcie_inbound_axi = devm_clk_get(dev,
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500773 "pcie_inbound_axi");
774 if (IS_ERR(imx6_pcie->pcie_inbound_axi)) {
Andrey Smirnov21b72452017-02-07 07:50:25 -0800775 dev_err(dev, "pcie_inbound_axi clock missing or invalid\n");
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500776 return PTR_ERR(imx6_pcie->pcie_inbound_axi);
777 }
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700778 break;
779 case IMX7D:
Philipp Zabel7c180582017-07-19 17:25:56 +0200780 imx6_pcie->pciephy_reset = devm_reset_control_get_exclusive(dev,
781 "pciephy");
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700782 if (IS_ERR(imx6_pcie->pciephy_reset)) {
Colin Ian King72215472017-04-21 08:02:30 +0100783 dev_err(dev, "Failed to get PCIEPHY reset control\n");
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700784 return PTR_ERR(imx6_pcie->pciephy_reset);
785 }
786
Philipp Zabel7c180582017-07-19 17:25:56 +0200787 imx6_pcie->apps_reset = devm_reset_control_get_exclusive(dev,
788 "apps");
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700789 if (IS_ERR(imx6_pcie->apps_reset)) {
Colin Ian King72215472017-04-21 08:02:30 +0100790 dev_err(dev, "Failed to get PCIE APPS reset control\n");
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700791 return PTR_ERR(imx6_pcie->apps_reset);
792 }
793 break;
794 default:
795 break;
Christoph Fritze3c06cd2016-04-05 16:53:27 -0500796 }
797
Sean Crossbb389192013-09-26 11:24:47 +0800798 /* Grab GPR config register range */
799 imx6_pcie->iomuxc_gpr =
800 syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
801 if (IS_ERR(imx6_pcie->iomuxc_gpr)) {
Bjorn Helgaas13957652016-10-06 13:35:18 -0500802 dev_err(dev, "unable to find iomuxc registers\n");
Fabio Estevamb391bf32013-12-02 01:39:35 -0200803 return PTR_ERR(imx6_pcie->iomuxc_gpr);
Sean Crossbb389192013-09-26 11:24:47 +0800804 }
805
Justin Waters28e3abe2016-01-15 10:24:35 -0500806 /* Grab PCIe PHY Tx Settings */
807 if (of_property_read_u32(node, "fsl,tx-deemph-gen1",
808 &imx6_pcie->tx_deemph_gen1))
809 imx6_pcie->tx_deemph_gen1 = 0;
810
811 if (of_property_read_u32(node, "fsl,tx-deemph-gen2-3p5db",
812 &imx6_pcie->tx_deemph_gen2_3p5db))
813 imx6_pcie->tx_deemph_gen2_3p5db = 0;
814
815 if (of_property_read_u32(node, "fsl,tx-deemph-gen2-6db",
816 &imx6_pcie->tx_deemph_gen2_6db))
817 imx6_pcie->tx_deemph_gen2_6db = 20;
818
819 if (of_property_read_u32(node, "fsl,tx-swing-full",
820 &imx6_pcie->tx_swing_full))
821 imx6_pcie->tx_swing_full = 127;
822
823 if (of_property_read_u32(node, "fsl,tx-swing-low",
824 &imx6_pcie->tx_swing_low))
825 imx6_pcie->tx_swing_low = 127;
826
Tim Harveya5fcec42016-04-19 19:52:44 -0500827 /* Limit link speed */
Bjorn Helgaasc5af4072016-10-06 13:35:18 -0500828 ret = of_property_read_u32(node, "fsl,max-link-speed",
Tim Harveya5fcec42016-04-19 19:52:44 -0500829 &imx6_pcie->link_gen);
830 if (ret)
831 imx6_pcie->link_gen = 1;
832
Quentin Schulzc26ebe92017-06-08 10:07:42 +0200833 imx6_pcie->vpcie = devm_regulator_get_optional(&pdev->dev, "vpcie");
834 if (IS_ERR(imx6_pcie->vpcie)) {
835 if (PTR_ERR(imx6_pcie->vpcie) == -EPROBE_DEFER)
836 return -EPROBE_DEFER;
837 imx6_pcie->vpcie = NULL;
838 }
839
Kishon Vijay Abraham I9bcf0a62017-02-15 18:48:11 +0530840 platform_set_drvdata(pdev, imx6_pcie);
841
Bjorn Helgaase7d77052016-10-11 22:06:47 -0500842 ret = imx6_add_pcie_port(imx6_pcie, pdev);
Sean Crossbb389192013-09-26 11:24:47 +0800843 if (ret < 0)
Fabio Estevamb391bf32013-12-02 01:39:35 -0200844 return ret;
Sean Crossbb389192013-09-26 11:24:47 +0800845
Sean Crossbb389192013-09-26 11:24:47 +0800846 return 0;
Sean Crossbb389192013-09-26 11:24:47 +0800847}
848
Lucas Stach3e3e4062014-07-31 20:16:05 +0200849static void imx6_pcie_shutdown(struct platform_device *pdev)
850{
851 struct imx6_pcie *imx6_pcie = platform_get_drvdata(pdev);
852
853 /* bring down link, so bootloader gets clean state in case of reboot */
Bjorn Helgaase7d77052016-10-11 22:06:47 -0500854 imx6_pcie_assert_core_reset(imx6_pcie);
Lucas Stach3e3e4062014-07-31 20:16:05 +0200855}
856
Sean Crossbb389192013-09-26 11:24:47 +0800857static const struct of_device_id imx6_pcie_of_match[] = {
Andrey Smirnove6f1fef2016-05-02 14:08:21 -0500858 { .compatible = "fsl,imx6q-pcie", .data = (void *)IMX6Q, },
859 { .compatible = "fsl,imx6sx-pcie", .data = (void *)IMX6SX, },
Andrey Smirnov4d31c612016-05-02 14:09:10 -0500860 { .compatible = "fsl,imx6qp-pcie", .data = (void *)IMX6QP, },
Andrey Smirnov9b3fe672017-03-28 08:42:49 -0700861 { .compatible = "fsl,imx7d-pcie", .data = (void *)IMX7D, },
Sean Crossbb389192013-09-26 11:24:47 +0800862 {},
863};
Sean Crossbb389192013-09-26 11:24:47 +0800864
865static struct platform_driver imx6_pcie_driver = {
866 .driver = {
867 .name = "imx6q-pcie",
Sachin Kamat8bcadbe2013-10-21 14:36:41 +0530868 .of_match_table = imx6_pcie_of_match,
Brian Norrisa5f40e82017-04-20 15:36:25 -0500869 .suppress_bind_attrs = true,
Sean Crossbb389192013-09-26 11:24:47 +0800870 },
Andrey Smirnovbde4a5a2017-03-28 08:42:50 -0700871 .probe = imx6_pcie_probe,
Lucas Stach3e3e4062014-07-31 20:16:05 +0200872 .shutdown = imx6_pcie_shutdown,
Sean Crossbb389192013-09-26 11:24:47 +0800873};
874
Sean Crossbb389192013-09-26 11:24:47 +0800875static int __init imx6_pcie_init(void)
876{
Andrey Smirnovbde4a5a2017-03-28 08:42:50 -0700877 /*
878 * Since probe() can be deferred we need to make sure that
879 * hook_fault_code is not called after __init memory is freed
880 * by kernel and since imx6q_pcie_abort_handler() is a no-op,
881 * we can install the handler here without risking it
882 * accessing some uninitialized driver state.
883 */
Lucas Stach415b6182017-05-22 17:06:30 -0500884 hook_fault_code(8, imx6q_pcie_abort_handler, SIGBUS, 0,
885 "external abort on non-linefetch");
Andrey Smirnovbde4a5a2017-03-28 08:42:50 -0700886
887 return platform_driver_register(&imx6_pcie_driver);
Sean Crossbb389192013-09-26 11:24:47 +0800888}
Paul Gortmakerf90d8e82016-08-22 17:59:43 -0400889device_initcall(imx6_pcie_init);