2018-01-26 12:50:27 -06:00
// SPDX-License-Identifier: GPL-2.0
2013-09-26 11:24:47 +08:00
/*
* PCIe host controller driver for Freescale i . MX6 SoCs
*
* Copyright ( C ) 2013 Kosagi
* http : //www.kosagi.com
*
* Author : Sean Cross < xobs @ kosagi . com >
*/
# include <linux/clk.h>
# include <linux/delay.h>
# include <linux/gpio.h>
# include <linux/kernel.h>
# include <linux/mfd/syscon.h>
# include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
2017-03-28 08:42:49 -07:00
# include <linux/mfd/syscon/imx7-iomuxc-gpr.h>
2013-09-26 11:24:47 +08:00
# include <linux/module.h>
# include <linux/of_gpio.h>
2016-05-02 14:08:21 -05:00
# include <linux/of_device.h>
2013-09-26 11:24:47 +08:00
# include <linux/pci.h>
# include <linux/platform_device.h>
# include <linux/regmap.h>
2017-06-08 10:07:42 +02:00
# include <linux/regulator/consumer.h>
2013-09-26 11:24:47 +08:00
# include <linux/resource.h>
# include <linux/signal.h>
# include <linux/types.h>
2014-03-28 17:52:59 +01:00
# include <linux/interrupt.h>
2017-03-28 08:42:49 -07:00
# include <linux/reset.h>
2013-09-26 11:24:47 +08:00
# include "pcie-designware.h"
2017-02-15 18:48:14 +05:30
# define to_imx6_pcie(x) dev_get_drvdata((x)->dev)
2013-09-26 11:24:47 +08:00
2016-05-02 14:08:21 -05:00
enum imx6_pcie_variants {
IMX6Q ,
2016-05-02 14:09:10 -05:00
IMX6SX ,
IMX6QP ,
2017-03-28 08:42:49 -07:00
IMX7D ,
2016-05-02 14:08:21 -05:00
} ;
2013-09-26 11:24:47 +08:00
struct imx6_pcie {
2017-02-15 18:48:14 +05:30
struct dw_pcie * pci ;
2016-03-28 18:45:36 -03:00
int reset_gpio ;
PCI: imx6: Add reset-gpio-active-high boolean property to DT
Currently the reset-gpio DT property which controls the PCI bus device
reset signal defaults to active-low reset sequence (L=reset state,
H=operation state) plus the code in reset function isn't GPIO polarity
aware - it doesn't matter if the defined reset-gpio is active-low or
active-high, it will always result into active-low reset sequence.
I've tried to fix it properly and change the reset-gpio reset sequence to
be polarity-aware, but this patch has been accepted and then reverted as it
has introduced few backward incompatible issues:
1. Some DTBs, for example, imx6qdl-sabresd, don't define reset-gpio
polarity correctly:
reset-gpio = <&gpio7 12 0>;
which means that it's defined as active-high, but in reality it's
active-low; thus it wouldn't work without a DTS fix.
2. The logic in the reset function is inverted:
gpio_set_value_cansleep(imx6_pcie->reset_gpio, 0)
msleep(100);
gpio_set_value_cansleep(imx6_pcie->reset_gpio, 1);
so even if some of the i.MX6 boards had reset-gpio polarity defined
correctly in their DTSes, they would stop working.
As we can't break old DTBs, we can't fix them, so we need to introduce this
new DT reset-gpio-active-high boolean property so we can support boards
with active-high reset sequence.
This active-high reset sequence is for example needed on Apalis SoMs, where
GPIO1_IO28, used to PCIe reset is not connected directly to PERST# PCIe
signal, but it's ORed with RESETBMCU coming off the PMIC, and thus is
inverted, active-high.
Tested-by: Tim Harvey <tharvey@gateworks.com> # Gateworks Ventana boards (which have active-low PERST#)
Signed-off-by: Petr Štetiar <ynezz@true.cz>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Lucas Stach <l.stach@pengutronix.de>
Acked-by: Rob Herring <robh@kernel.org>
2016-04-19 19:42:07 -05:00
bool gpio_active_high ;
2014-03-28 17:52:55 +01:00
struct clk * pcie_bus ;
struct clk * pcie_phy ;
2016-04-05 16:53:27 -05:00
struct clk * pcie_inbound_axi ;
2014-03-28 17:52:55 +01:00
struct clk * pcie ;
2013-09-26 11:24:47 +08:00
struct regmap * iomuxc_gpr ;
2017-03-28 08:42:49 -07:00
struct reset_control * pciephy_reset ;
struct reset_control * apps_reset ;
2016-05-02 14:08:21 -05:00
enum imx6_pcie_variants variant ;
2016-01-15 10:24:35 -05:00
u32 tx_deemph_gen1 ;
u32 tx_deemph_gen2_3p5db ;
u32 tx_deemph_gen2_6db ;
u32 tx_swing_full ;
u32 tx_swing_low ;
2016-04-19 19:52:44 -05:00
int link_gen ;
2017-06-08 10:07:42 +02:00
struct regulator * vpcie ;
2013-09-26 11:24:47 +08:00
} ;
2017-03-28 08:42:49 -07:00
/* Parameters for the waiting for PCIe PHY PLL to lock on i.MX7 */
# define PHY_PLL_LOCK_WAIT_MAX_RETRIES 2000
# define PHY_PLL_LOCK_WAIT_USLEEP_MIN 50
# define PHY_PLL_LOCK_WAIT_USLEEP_MAX 200
2013-12-12 22:50:02 +01:00
/* PCIe Root Complex registers (memory-mapped) */
# define PCIE_RC_LCR 0x7c
# define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1 0x1
# define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2 0x2
# define PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK 0xf
2015-06-12 17:27:43 -05:00
# define PCIE_RC_LCSR 0x80
2013-09-26 11:24:47 +08:00
/* PCIe Port Logic registers (memory-mapped) */
# define PL_OFFSET 0x700
2014-07-31 20:16:05 +02:00
# define PCIE_PL_PFLR (PL_OFFSET + 0x08)
# define PCIE_PL_PFLR_LINK_STATE_MASK (0x3f << 16)
# define PCIE_PL_PFLR_FORCE_LINK (1 << 15)
2013-09-26 11:24:47 +08:00
# define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28)
# define PCIE_PHY_DEBUG_R1 (PL_OFFSET + 0x2c)
2013-12-12 22:49:59 +01:00
# define PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING (1 << 29)
# define PCIE_PHY_DEBUG_R1_XMLH_LINK_UP (1 << 4)
2013-09-26 11:24:47 +08:00
# define PCIE_PHY_CTRL (PL_OFFSET + 0x114)
# define PCIE_PHY_CTRL_DATA_LOC 0
# define PCIE_PHY_CTRL_CAP_ADR_LOC 16
# define PCIE_PHY_CTRL_CAP_DAT_LOC 17
# define PCIE_PHY_CTRL_WR_LOC 18
# define PCIE_PHY_CTRL_RD_LOC 19
# define PCIE_PHY_STAT (PL_OFFSET + 0x110)
# define PCIE_PHY_STAT_ACK_LOC 16
2013-12-12 22:50:02 +01:00
# define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C
# define PORT_LOGIC_SPEED_CHANGE (0x1 << 17)
2013-09-26 11:24:47 +08:00
/* PHY registers (not memory-mapped) */
# define PCIE_PHY_RX_ASIC_OUT 0x100D
2015-09-11 09:08:53 -03:00
# define PCIE_PHY_RX_ASIC_OUT_VALID (1 << 0)
2013-09-26 11:24:47 +08:00
# define PHY_RX_OVRD_IN_LO 0x1005
# define PHY_RX_OVRD_IN_LO_RX_DATA_EN (1 << 5)
# define PHY_RX_OVRD_IN_LO_RX_PLL_EN (1 << 3)
2016-10-11 22:09:32 -05:00
static int pcie_phy_poll_ack ( struct imx6_pcie * imx6_pcie , int exp_val )
2013-09-26 11:24:47 +08:00
{
2017-02-15 18:48:14 +05:30
struct dw_pcie * pci = imx6_pcie - > pci ;
2013-09-26 11:24:47 +08:00
u32 val ;
u32 max_iterations = 10 ;
u32 wait_counter = 0 ;
do {
2017-02-15 18:48:14 +05:30
val = dw_pcie_readl_dbi ( pci , PCIE_PHY_STAT ) ;
2013-09-26 11:24:47 +08:00
val = ( val > > PCIE_PHY_STAT_ACK_LOC ) & 0x1 ;
wait_counter + + ;
if ( val = = exp_val )
return 0 ;
udelay ( 1 ) ;
} while ( wait_counter < max_iterations ) ;
return - ETIMEDOUT ;
}
2016-10-11 22:09:32 -05:00
static int pcie_phy_wait_ack ( struct imx6_pcie * imx6_pcie , int addr )
2013-09-26 11:24:47 +08:00
{
2017-02-15 18:48:14 +05:30
struct dw_pcie * pci = imx6_pcie - > pci ;
2013-09-26 11:24:47 +08:00
u32 val ;
int ret ;
val = addr < < PCIE_PHY_CTRL_DATA_LOC ;
2017-02-15 18:48:14 +05:30
dw_pcie_writel_dbi ( pci , PCIE_PHY_CTRL , val ) ;
2013-09-26 11:24:47 +08:00
val | = ( 0x1 < < PCIE_PHY_CTRL_CAP_ADR_LOC ) ;
2017-02-15 18:48:14 +05:30
dw_pcie_writel_dbi ( pci , PCIE_PHY_CTRL , val ) ;
2013-09-26 11:24:47 +08:00
2016-10-11 22:09:32 -05:00
ret = pcie_phy_poll_ack ( imx6_pcie , 1 ) ;
2013-09-26 11:24:47 +08:00
if ( ret )
return ret ;
val = addr < < PCIE_PHY_CTRL_DATA_LOC ;
2017-02-15 18:48:14 +05:30
dw_pcie_writel_dbi ( pci , PCIE_PHY_CTRL , val ) ;
2013-09-26 11:24:47 +08:00
2016-10-11 22:09:32 -05:00
return pcie_phy_poll_ack ( imx6_pcie , 0 ) ;
2013-09-26 11:24:47 +08:00
}
/* Read from the 16-bit PCIe PHY control registers (not memory-mapped) */
2016-10-11 22:09:32 -05:00
static int pcie_phy_read ( struct imx6_pcie * imx6_pcie , int addr , int * data )
2013-09-26 11:24:47 +08:00
{
2017-02-15 18:48:14 +05:30
struct dw_pcie * pci = imx6_pcie - > pci ;
2013-09-26 11:24:47 +08:00
u32 val , phy_ctl ;
int ret ;
2016-10-11 22:09:32 -05:00
ret = pcie_phy_wait_ack ( imx6_pcie , addr ) ;
2013-09-26 11:24:47 +08:00
if ( ret )
return ret ;
/* assert Read signal */
phy_ctl = 0x1 < < PCIE_PHY_CTRL_RD_LOC ;
2017-02-15 18:48:14 +05:30
dw_pcie_writel_dbi ( pci , PCIE_PHY_CTRL , phy_ctl ) ;
2013-09-26 11:24:47 +08:00
2016-10-11 22:09:32 -05:00
ret = pcie_phy_poll_ack ( imx6_pcie , 1 ) ;
2013-09-26 11:24:47 +08:00
if ( ret )
return ret ;
2017-02-15 18:48:14 +05:30
val = dw_pcie_readl_dbi ( pci , PCIE_PHY_STAT ) ;
2013-09-26 11:24:47 +08:00
* data = val & 0xffff ;
/* deassert Read signal */
2017-02-15 18:48:14 +05:30
dw_pcie_writel_dbi ( pci , PCIE_PHY_CTRL , 0x00 ) ;
2013-09-26 11:24:47 +08:00
2016-10-11 22:09:32 -05:00
return pcie_phy_poll_ack ( imx6_pcie , 0 ) ;
2013-09-26 11:24:47 +08:00
}
2016-10-11 22:09:32 -05:00
static int pcie_phy_write ( struct imx6_pcie * imx6_pcie , int addr , int data )
2013-09-26 11:24:47 +08:00
{
2017-02-15 18:48:14 +05:30
struct dw_pcie * pci = imx6_pcie - > pci ;
2013-09-26 11:24:47 +08:00
u32 var ;
int ret ;
/* write addr */
/* cap addr */
2016-10-11 22:09:32 -05:00
ret = pcie_phy_wait_ack ( imx6_pcie , addr ) ;
2013-09-26 11:24:47 +08:00
if ( ret )
return ret ;
var = data < < PCIE_PHY_CTRL_DATA_LOC ;
2017-02-15 18:48:14 +05:30
dw_pcie_writel_dbi ( pci , PCIE_PHY_CTRL , var ) ;
2013-09-26 11:24:47 +08:00
/* capture data */
var | = ( 0x1 < < PCIE_PHY_CTRL_CAP_DAT_LOC ) ;
2017-02-15 18:48:14 +05:30
dw_pcie_writel_dbi ( pci , PCIE_PHY_CTRL , var ) ;
2013-09-26 11:24:47 +08:00
2016-10-11 22:09:32 -05:00
ret = pcie_phy_poll_ack ( imx6_pcie , 1 ) ;
2013-09-26 11:24:47 +08:00
if ( ret )
return ret ;
/* deassert cap data */
var = data < < PCIE_PHY_CTRL_DATA_LOC ;
2017-02-15 18:48:14 +05:30
dw_pcie_writel_dbi ( pci , PCIE_PHY_CTRL , var ) ;
2013-09-26 11:24:47 +08:00
/* wait for ack de-assertion */
2016-10-11 22:09:32 -05:00
ret = pcie_phy_poll_ack ( imx6_pcie , 0 ) ;
2013-09-26 11:24:47 +08:00
if ( ret )
return ret ;
/* assert wr signal */
var = 0x1 < < PCIE_PHY_CTRL_WR_LOC ;
2017-02-15 18:48:14 +05:30
dw_pcie_writel_dbi ( pci , PCIE_PHY_CTRL , var ) ;
2013-09-26 11:24:47 +08:00
/* wait for ack */
2016-10-11 22:09:32 -05:00
ret = pcie_phy_poll_ack ( imx6_pcie , 1 ) ;
2013-09-26 11:24:47 +08:00
if ( ret )
return ret ;
/* deassert wr signal */
var = data < < PCIE_PHY_CTRL_DATA_LOC ;
2017-02-15 18:48:14 +05:30
dw_pcie_writel_dbi ( pci , PCIE_PHY_CTRL , var ) ;
2013-09-26 11:24:47 +08:00
/* wait for ack de-assertion */
2016-10-11 22:09:32 -05:00
ret = pcie_phy_poll_ack ( imx6_pcie , 0 ) ;
2013-09-26 11:24:47 +08:00
if ( ret )
return ret ;
2017-02-15 18:48:14 +05:30
dw_pcie_writel_dbi ( pci , PCIE_PHY_CTRL , 0x0 ) ;
2013-09-26 11:24:47 +08:00
return 0 ;
}
2016-10-11 22:06:47 -05:00
static void imx6_pcie_reset_phy ( struct imx6_pcie * imx6_pcie )
2016-01-15 19:56:47 +01:00
{
u32 tmp ;
2016-10-11 22:09:32 -05:00
pcie_phy_read ( imx6_pcie , PHY_RX_OVRD_IN_LO , & tmp ) ;
2016-01-15 19:56:47 +01:00
tmp | = ( PHY_RX_OVRD_IN_LO_RX_DATA_EN |
PHY_RX_OVRD_IN_LO_RX_PLL_EN ) ;
2016-10-11 22:09:32 -05:00
pcie_phy_write ( imx6_pcie , PHY_RX_OVRD_IN_LO , tmp ) ;
2016-01-15 19:56:47 +01:00
usleep_range ( 2000 , 3000 ) ;
2016-10-11 22:09:32 -05:00
pcie_phy_read ( imx6_pcie , PHY_RX_OVRD_IN_LO , & tmp ) ;
2016-01-15 19:56:47 +01:00
tmp & = ~ ( PHY_RX_OVRD_IN_LO_RX_DATA_EN |
PHY_RX_OVRD_IN_LO_RX_PLL_EN ) ;
2016-10-11 22:09:32 -05:00
pcie_phy_write ( imx6_pcie , PHY_RX_OVRD_IN_LO , tmp ) ;
2016-01-15 19:56:47 +01:00
}
2013-09-26 11:24:47 +08:00
/* Added for PCI abort handling */
static int imx6q_pcie_abort_handler ( unsigned long addr ,
unsigned int fsr , struct pt_regs * regs )
{
2017-05-22 17:06:30 -05:00
unsigned long pc = instruction_pointer ( regs ) ;
unsigned long instr = * ( unsigned long * ) pc ;
int reg = ( instr > > 12 ) & 15 ;
/*
* If the instruction being executed was a read ,
* make it look like it read all - ones .
*/
if ( ( instr & 0x0c100000 ) = = 0x04100000 ) {
unsigned long val ;
if ( instr & 0x00400000 )
val = 255 ;
else
val = - 1 ;
regs - > uregs [ reg ] = val ;
regs - > ARM_pc + = 4 ;
return 0 ;
}
if ( ( instr & 0x0e100090 ) = = 0x00100090 ) {
regs - > uregs [ reg ] = - 1 ;
regs - > ARM_pc + = 4 ;
return 0 ;
}
return 1 ;
2013-09-26 11:24:47 +08:00
}
2016-10-06 13:35:17 -05:00
static void imx6_pcie_assert_core_reset ( struct imx6_pcie * imx6_pcie )
2013-09-26 11:24:47 +08:00
{
2017-06-08 10:07:42 +02:00
struct device * dev = imx6_pcie - > pci - > dev ;
2016-05-02 14:08:21 -05:00
switch ( imx6_pcie - > variant ) {
2017-03-28 08:42:49 -07:00
case IMX7D :
reset_control_assert ( imx6_pcie - > pciephy_reset ) ;
reset_control_assert ( imx6_pcie - > apps_reset ) ;
break ;
2016-05-02 14:08:21 -05:00
case IMX6SX :
2016-04-05 16:53:27 -05:00
regmap_update_bits ( imx6_pcie - > iomuxc_gpr , IOMUXC_GPR12 ,
IMX6SX_GPR12_PCIE_TEST_POWERDOWN ,
IMX6SX_GPR12_PCIE_TEST_POWERDOWN ) ;
/* Force PCIe PHY reset */
regmap_update_bits ( imx6_pcie - > iomuxc_gpr , IOMUXC_GPR5 ,
IMX6SX_GPR5_PCIE_BTNRST_RESET ,
IMX6SX_GPR5_PCIE_BTNRST_RESET ) ;
2016-05-02 14:08:21 -05:00
break ;
2016-05-02 14:09:10 -05:00
case IMX6QP :
regmap_update_bits ( imx6_pcie - > iomuxc_gpr , IOMUXC_GPR1 ,
IMX6Q_GPR1_PCIE_SW_RST ,
IMX6Q_GPR1_PCIE_SW_RST ) ;
break ;
2016-05-02 14:08:21 -05:00
case IMX6Q :
regmap_update_bits ( imx6_pcie - > iomuxc_gpr , IOMUXC_GPR1 ,
IMX6Q_GPR1_PCIE_TEST_PD , 1 < < 18 ) ;
regmap_update_bits ( imx6_pcie - > iomuxc_gpr , IOMUXC_GPR1 ,
IMX6Q_GPR1_PCIE_REF_CLK_EN , 0 < < 16 ) ;
break ;
2014-07-31 20:16:05 +02:00
}
2017-06-08 10:07:42 +02:00
if ( imx6_pcie - > vpcie & & regulator_is_enabled ( imx6_pcie - > vpcie ) > 0 ) {
int ret = regulator_disable ( imx6_pcie - > vpcie ) ;
if ( ret )
dev_err ( dev , " failed to disable vpcie regulator: %d \n " ,
ret ) ;
}
2013-09-26 11:24:47 +08:00
}
2016-03-14 00:30:55 +01:00
static int imx6_pcie_enable_ref_clk ( struct imx6_pcie * imx6_pcie )
{
2017-02-15 18:48:14 +05:30
struct dw_pcie * pci = imx6_pcie - > pci ;
struct device * dev = pci - > dev ;
2016-05-02 14:08:21 -05:00
int ret = 0 ;
2016-04-05 16:53:27 -05:00
2016-05-02 14:08:21 -05:00
switch ( imx6_pcie - > variant ) {
case IMX6SX :
2016-04-05 16:53:27 -05:00
ret = clk_prepare_enable ( imx6_pcie - > pcie_inbound_axi ) ;
if ( ret ) {
2016-10-06 13:35:18 -05:00
dev_err ( dev , " unable to enable pcie_axi clock \n " ) ;
2016-05-02 14:08:21 -05:00
break ;
2016-04-05 16:53:27 -05:00
}
regmap_update_bits ( imx6_pcie - > iomuxc_gpr , IOMUXC_GPR12 ,
IMX6SX_GPR12_PCIE_TEST_POWERDOWN , 0 ) ;
2016-05-02 14:08:21 -05:00
break ;
2016-05-02 14:09:10 -05:00
case IMX6QP : /* FALLTHROUGH */
2016-05-02 14:08:21 -05:00
case IMX6Q :
/* power up core phy and enable ref clock */
regmap_update_bits ( imx6_pcie - > iomuxc_gpr , IOMUXC_GPR1 ,
IMX6Q_GPR1_PCIE_TEST_PD , 0 < < 18 ) ;
/*
* the async reset input need ref clock to sync internally ,
* when the ref clock comes after reset , internal synced
* reset time is too short , cannot meet the requirement .
* add one ~ 10u s delay here .
*/
udelay ( 10 ) ;
regmap_update_bits ( imx6_pcie - > iomuxc_gpr , IOMUXC_GPR1 ,
IMX6Q_GPR1_PCIE_REF_CLK_EN , 1 < < 16 ) ;
break ;
2017-03-28 08:42:49 -07:00
case IMX7D :
break ;
2016-04-05 16:53:27 -05:00
}
2016-05-02 14:08:21 -05:00
return ret ;
2016-03-14 00:30:55 +01:00
}
2017-03-28 08:42:49 -07:00
static void imx7d_pcie_wait_for_phy_pll_lock ( struct imx6_pcie * imx6_pcie )
{
u32 val ;
unsigned int retries ;
struct device * dev = imx6_pcie - > pci - > dev ;
for ( retries = 0 ; retries < PHY_PLL_LOCK_WAIT_MAX_RETRIES ; retries + + ) {
regmap_read ( imx6_pcie - > iomuxc_gpr , IOMUXC_GPR22 , & val ) ;
if ( val & IMX7D_GPR22_PCIE_PHY_PLL_LOCKED )
return ;
usleep_range ( PHY_PLL_LOCK_WAIT_USLEEP_MIN ,
PHY_PLL_LOCK_WAIT_USLEEP_MAX ) ;
}
dev_err ( dev , " PCIe PLL lock timeout \n " ) ;
}
2016-10-06 13:35:17 -05:00
static void imx6_pcie_deassert_core_reset ( struct imx6_pcie * imx6_pcie )
2013-09-26 11:24:47 +08:00
{
2017-02-15 18:48:14 +05:30
struct dw_pcie * pci = imx6_pcie - > pci ;
struct device * dev = pci - > dev ;
2013-09-26 11:24:47 +08:00
int ret ;
2017-06-08 10:07:42 +02:00
if ( imx6_pcie - > vpcie & & ! regulator_is_enabled ( imx6_pcie - > vpcie ) ) {
ret = regulator_enable ( imx6_pcie - > vpcie ) ;
if ( ret ) {
dev_err ( dev , " failed to enable vpcie regulator: %d \n " ,
ret ) ;
return ;
}
}
2014-03-28 17:52:55 +01:00
ret = clk_prepare_enable ( imx6_pcie - > pcie_phy ) ;
2013-09-26 11:24:47 +08:00
if ( ret ) {
2016-10-06 13:35:18 -05:00
dev_err ( dev , " unable to enable pcie_phy clock \n " ) ;
2017-06-08 10:07:42 +02:00
goto err_pcie_phy ;
2013-09-26 11:24:47 +08:00
}
2014-03-28 17:52:55 +01:00
ret = clk_prepare_enable ( imx6_pcie - > pcie_bus ) ;
2013-09-26 11:24:47 +08:00
if ( ret ) {
2016-10-06 13:35:18 -05:00
dev_err ( dev , " unable to enable pcie_bus clock \n " ) ;
2014-03-28 17:52:55 +01:00
goto err_pcie_bus ;
2013-09-26 11:24:47 +08:00
}
2014-03-28 17:52:55 +01:00
ret = clk_prepare_enable ( imx6_pcie - > pcie ) ;
2013-09-26 11:24:47 +08:00
if ( ret ) {
2016-10-06 13:35:18 -05:00
dev_err ( dev , " unable to enable pcie clock \n " ) ;
2014-03-28 17:52:55 +01:00
goto err_pcie ;
2013-09-26 11:24:47 +08:00
}
2016-03-14 00:30:55 +01:00
ret = imx6_pcie_enable_ref_clk ( imx6_pcie ) ;
if ( ret ) {
2016-10-06 13:35:18 -05:00
dev_err ( dev , " unable to enable pcie ref clock \n " ) ;
2016-03-14 00:30:55 +01:00
goto err_ref_clk ;
}
2014-08-07 23:36:40 -07:00
2014-10-27 13:17:32 +08:00
/* allow the clocks to stabilize */
usleep_range ( 200 , 500 ) ;
2013-12-12 22:50:03 +01:00
/* Some boards don't have PCIe reset GPIO. */
2016-03-28 18:45:36 -03:00
if ( gpio_is_valid ( imx6_pcie - > reset_gpio ) ) {
PCI: imx6: Add reset-gpio-active-high boolean property to DT
Currently the reset-gpio DT property which controls the PCI bus device
reset signal defaults to active-low reset sequence (L=reset state,
H=operation state) plus the code in reset function isn't GPIO polarity
aware - it doesn't matter if the defined reset-gpio is active-low or
active-high, it will always result into active-low reset sequence.
I've tried to fix it properly and change the reset-gpio reset sequence to
be polarity-aware, but this patch has been accepted and then reverted as it
has introduced few backward incompatible issues:
1. Some DTBs, for example, imx6qdl-sabresd, don't define reset-gpio
polarity correctly:
reset-gpio = <&gpio7 12 0>;
which means that it's defined as active-high, but in reality it's
active-low; thus it wouldn't work without a DTS fix.
2. The logic in the reset function is inverted:
gpio_set_value_cansleep(imx6_pcie->reset_gpio, 0)
msleep(100);
gpio_set_value_cansleep(imx6_pcie->reset_gpio, 1);
so even if some of the i.MX6 boards had reset-gpio polarity defined
correctly in their DTSes, they would stop working.
As we can't break old DTBs, we can't fix them, so we need to introduce this
new DT reset-gpio-active-high boolean property so we can support boards
with active-high reset sequence.
This active-high reset sequence is for example needed on Apalis SoMs, where
GPIO1_IO28, used to PCIe reset is not connected directly to PERST# PCIe
signal, but it's ORed with RESETBMCU coming off the PMIC, and thus is
inverted, active-high.
Tested-by: Tim Harvey <tharvey@gateworks.com> # Gateworks Ventana boards (which have active-low PERST#)
Signed-off-by: Petr Štetiar <ynezz@true.cz>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Lucas Stach <l.stach@pengutronix.de>
Acked-by: Rob Herring <robh@kernel.org>
2016-04-19 19:42:07 -05:00
gpio_set_value_cansleep ( imx6_pcie - > reset_gpio ,
imx6_pcie - > gpio_active_high ) ;
2013-12-12 22:50:03 +01:00
msleep ( 100 ) ;
PCI: imx6: Add reset-gpio-active-high boolean property to DT
Currently the reset-gpio DT property which controls the PCI bus device
reset signal defaults to active-low reset sequence (L=reset state,
H=operation state) plus the code in reset function isn't GPIO polarity
aware - it doesn't matter if the defined reset-gpio is active-low or
active-high, it will always result into active-low reset sequence.
I've tried to fix it properly and change the reset-gpio reset sequence to
be polarity-aware, but this patch has been accepted and then reverted as it
has introduced few backward incompatible issues:
1. Some DTBs, for example, imx6qdl-sabresd, don't define reset-gpio
polarity correctly:
reset-gpio = <&gpio7 12 0>;
which means that it's defined as active-high, but in reality it's
active-low; thus it wouldn't work without a DTS fix.
2. The logic in the reset function is inverted:
gpio_set_value_cansleep(imx6_pcie->reset_gpio, 0)
msleep(100);
gpio_set_value_cansleep(imx6_pcie->reset_gpio, 1);
so even if some of the i.MX6 boards had reset-gpio polarity defined
correctly in their DTSes, they would stop working.
As we can't break old DTBs, we can't fix them, so we need to introduce this
new DT reset-gpio-active-high boolean property so we can support boards
with active-high reset sequence.
This active-high reset sequence is for example needed on Apalis SoMs, where
GPIO1_IO28, used to PCIe reset is not connected directly to PERST# PCIe
signal, but it's ORed with RESETBMCU coming off the PMIC, and thus is
inverted, active-high.
Tested-by: Tim Harvey <tharvey@gateworks.com> # Gateworks Ventana boards (which have active-low PERST#)
Signed-off-by: Petr Štetiar <ynezz@true.cz>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Lucas Stach <l.stach@pengutronix.de>
Acked-by: Rob Herring <robh@kernel.org>
2016-04-19 19:42:07 -05:00
gpio_set_value_cansleep ( imx6_pcie - > reset_gpio ,
! imx6_pcie - > gpio_active_high ) ;
2013-12-12 22:50:03 +01:00
}
2016-04-05 16:53:27 -05:00
2016-05-02 14:09:10 -05:00
switch ( imx6_pcie - > variant ) {
2017-03-28 08:42:49 -07:00
case IMX7D :
reset_control_deassert ( imx6_pcie - > pciephy_reset ) ;
imx7d_pcie_wait_for_phy_pll_lock ( imx6_pcie ) ;
break ;
2016-05-02 14:09:10 -05:00
case IMX6SX :
2016-04-05 16:53:27 -05:00
regmap_update_bits ( imx6_pcie - > iomuxc_gpr , IOMUXC_GPR5 ,
IMX6SX_GPR5_PCIE_BTNRST_RESET , 0 ) ;
2016-05-02 14:09:10 -05:00
break ;
case IMX6QP :
regmap_update_bits ( imx6_pcie - > iomuxc_gpr , IOMUXC_GPR1 ,
IMX6Q_GPR1_PCIE_SW_RST , 0 ) ;
usleep_range ( 200 , 500 ) ;
break ;
case IMX6Q : /* Nothing to do */
break ;
}
2016-04-05 16:53:27 -05:00
2016-10-06 13:35:17 -05:00
return ;
2013-09-26 11:24:47 +08:00
2016-03-14 00:30:55 +01:00
err_ref_clk :
clk_disable_unprepare ( imx6_pcie - > pcie ) ;
2014-03-28 17:52:55 +01:00
err_pcie :
clk_disable_unprepare ( imx6_pcie - > pcie_bus ) ;
err_pcie_bus :
clk_disable_unprepare ( imx6_pcie - > pcie_phy ) ;
2017-06-08 10:07:42 +02:00
err_pcie_phy :
if ( imx6_pcie - > vpcie & & regulator_is_enabled ( imx6_pcie - > vpcie ) > 0 ) {
ret = regulator_disable ( imx6_pcie - > vpcie ) ;
if ( ret )
dev_err ( dev , " failed to disable vpcie regulator: %d \n " ,
ret ) ;
}
2013-09-26 11:24:47 +08:00
}
2016-10-11 22:06:47 -05:00
static void imx6_pcie_init_phy ( struct imx6_pcie * imx6_pcie )
2013-09-26 11:24:47 +08:00
{
2017-03-28 08:42:49 -07:00
switch ( imx6_pcie - > variant ) {
case IMX7D :
regmap_update_bits ( imx6_pcie - > iomuxc_gpr , IOMUXC_GPR12 ,
IMX7D_GPR12_PCIE_PHY_REFCLK_SEL , 0 ) ;
break ;
case IMX6SX :
2016-04-05 16:53:27 -05:00
regmap_update_bits ( imx6_pcie - > iomuxc_gpr , IOMUXC_GPR12 ,
IMX6SX_GPR12_PCIE_RX_EQ_MASK ,
IMX6SX_GPR12_PCIE_RX_EQ_2 ) ;
2017-03-28 08:42:49 -07:00
/* FALLTHROUGH */
default :
regmap_update_bits ( imx6_pcie - > iomuxc_gpr , IOMUXC_GPR12 ,
IMX6Q_GPR12_PCIE_CTL_2 , 0 < < 10 ) ;
2016-04-05 16:53:27 -05:00
2017-03-28 08:42:49 -07:00
/* configure constant input signal to the pcie ctrl and phy */
regmap_update_bits ( imx6_pcie - > iomuxc_gpr , IOMUXC_GPR12 ,
IMX6Q_GPR12_LOS_LEVEL , 9 < < 4 ) ;
regmap_update_bits ( imx6_pcie - > iomuxc_gpr , IOMUXC_GPR8 ,
IMX6Q_GPR8_TX_DEEMPH_GEN1 ,
imx6_pcie - > tx_deemph_gen1 < < 0 ) ;
regmap_update_bits ( imx6_pcie - > iomuxc_gpr , IOMUXC_GPR8 ,
IMX6Q_GPR8_TX_DEEMPH_GEN2_3P5DB ,
imx6_pcie - > tx_deemph_gen2_3p5db < < 6 ) ;
regmap_update_bits ( imx6_pcie - > iomuxc_gpr , IOMUXC_GPR8 ,
IMX6Q_GPR8_TX_DEEMPH_GEN2_6DB ,
imx6_pcie - > tx_deemph_gen2_6db < < 12 ) ;
regmap_update_bits ( imx6_pcie - > iomuxc_gpr , IOMUXC_GPR8 ,
IMX6Q_GPR8_TX_SWING_FULL ,
imx6_pcie - > tx_swing_full < < 18 ) ;
regmap_update_bits ( imx6_pcie - > iomuxc_gpr , IOMUXC_GPR8 ,
IMX6Q_GPR8_TX_SWING_LOW ,
imx6_pcie - > tx_swing_low < < 25 ) ;
break ;
}
2013-09-26 11:24:47 +08:00
regmap_update_bits ( imx6_pcie - > iomuxc_gpr , IOMUXC_GPR12 ,
IMX6Q_GPR12_DEVICE_TYPE , PCI_EXP_TYPE_ROOT_PORT < < 12 ) ;
}
2016-10-11 22:06:47 -05:00
static int imx6_pcie_wait_for_link ( struct imx6_pcie * imx6_pcie )
2013-12-12 22:50:01 +01:00
{
2017-02-15 18:48:14 +05:30
struct dw_pcie * pci = imx6_pcie - > pci ;
struct device * dev = pci - > dev ;
2016-10-06 13:35:18 -05:00
PCI: designware: Add generic dw_pcie_wait_for_link()
Several DesignWare-based drivers (dra7xx, exynos, imx6, keystone, qcom, and
spear13xx) had similar loops waiting for the link to come up.
Add a generic dw_pcie_wait_for_link() for use by all these drivers so the
waiting is done consistently, e.g., always using usleep_range() rather than
mdelay() and using similar timeouts and retry counts.
Note that this changes the Keystone link training/wait for link strategy,
so we initiate link training, then wait longer for the link to come up
before re-initiating link training.
[bhelgaas: changelog, split into its own patch, update pci-keystone.c, pcie-qcom.c]
Signed-off-by: Joao Pinto <jpinto@synopsys.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Acked-by: Pratyush Anand <pratyush.anand@gmail.com>
2016-03-10 14:44:35 -06:00
/* check if the link is up or not */
2017-02-15 18:48:14 +05:30
if ( ! dw_pcie_wait_for_link ( pci ) )
PCI: designware: Add generic dw_pcie_wait_for_link()
Several DesignWare-based drivers (dra7xx, exynos, imx6, keystone, qcom, and
spear13xx) had similar loops waiting for the link to come up.
Add a generic dw_pcie_wait_for_link() for use by all these drivers so the
waiting is done consistently, e.g., always using usleep_range() rather than
mdelay() and using similar timeouts and retry counts.
Note that this changes the Keystone link training/wait for link strategy,
so we initiate link training, then wait longer for the link to come up
before re-initiating link training.
[bhelgaas: changelog, split into its own patch, update pci-keystone.c, pcie-qcom.c]
Signed-off-by: Joao Pinto <jpinto@synopsys.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Acked-by: Pratyush Anand <pratyush.anand@gmail.com>
2016-03-10 14:44:35 -06:00
return 0 ;
2013-12-12 22:50:01 +01:00
2016-10-06 13:35:18 -05:00
dev_dbg ( dev , " DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x \n " ,
2017-02-15 18:48:14 +05:30
dw_pcie_readl_dbi ( pci , PCIE_PHY_DEBUG_R0 ) ,
dw_pcie_readl_dbi ( pci , PCIE_PHY_DEBUG_R1 ) ) ;
PCI: designware: Add generic dw_pcie_wait_for_link()
Several DesignWare-based drivers (dra7xx, exynos, imx6, keystone, qcom, and
spear13xx) had similar loops waiting for the link to come up.
Add a generic dw_pcie_wait_for_link() for use by all these drivers so the
waiting is done consistently, e.g., always using usleep_range() rather than
mdelay() and using similar timeouts and retry counts.
Note that this changes the Keystone link training/wait for link strategy,
so we initiate link training, then wait longer for the link to come up
before re-initiating link training.
[bhelgaas: changelog, split into its own patch, update pci-keystone.c, pcie-qcom.c]
Signed-off-by: Joao Pinto <jpinto@synopsys.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Acked-by: Pratyush Anand <pratyush.anand@gmail.com>
2016-03-10 14:44:35 -06:00
return - ETIMEDOUT ;
2013-12-12 22:50:01 +01:00
}
2016-10-11 22:06:47 -05:00
static int imx6_pcie_wait_for_speed_change ( struct imx6_pcie * imx6_pcie )
2015-06-12 14:30:16 -05:00
{
2017-02-15 18:48:14 +05:30
struct dw_pcie * pci = imx6_pcie - > pci ;
struct device * dev = pci - > dev ;
2015-06-12 15:02:49 -05:00
u32 tmp ;
2015-06-12 14:30:16 -05:00
unsigned int retries ;
for ( retries = 0 ; retries < 200 ; retries + + ) {
2017-02-15 18:48:14 +05:30
tmp = dw_pcie_readl_dbi ( pci , PCIE_LINK_WIDTH_SPEED_CONTROL ) ;
2015-06-12 14:30:16 -05:00
/* Test if the speed change finished. */
if ( ! ( tmp & PORT_LOGIC_SPEED_CHANGE ) )
return 0 ;
usleep_range ( 100 , 1000 ) ;
}
2016-10-06 13:35:18 -05:00
dev_err ( dev , " Speed change timeout \n " ) ;
2015-06-12 14:30:16 -05:00
return - EINVAL ;
2013-12-12 22:50:01 +01:00
}
2014-03-28 17:52:59 +01:00
static irqreturn_t imx6_pcie_msi_handler ( int irq , void * arg )
{
2016-10-11 22:06:47 -05:00
struct imx6_pcie * imx6_pcie = arg ;
2017-02-15 18:48:14 +05:30
struct dw_pcie * pci = imx6_pcie - > pci ;
struct pcie_port * pp = & pci - > pp ;
2014-03-28 17:52:59 +01:00
return dw_handle_msi_irq ( pp ) ;
}
2016-10-11 22:06:47 -05:00
static int imx6_pcie_establish_link ( struct imx6_pcie * imx6_pcie )
2013-09-26 11:24:47 +08:00
{
2017-02-15 18:48:14 +05:30
struct dw_pcie * pci = imx6_pcie - > pci ;
struct device * dev = pci - > dev ;
2015-06-12 15:02:49 -05:00
u32 tmp ;
2015-06-12 14:30:16 -05:00
int ret ;
2013-12-12 22:50:02 +01:00
/*
* Force Gen1 operation when starting the link . In case the link is
* started in Gen2 mode , there is a possibility the devices on the
* bus will not be detected at all . This happens with PCIe switches .
*/
2017-02-15 18:48:14 +05:30
tmp = dw_pcie_readl_dbi ( pci , PCIE_RC_LCR ) ;
2013-12-12 22:50:02 +01:00
tmp & = ~ PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK ;
tmp | = PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1 ;
2017-02-15 18:48:14 +05:30
dw_pcie_writel_dbi ( pci , PCIE_RC_LCR , tmp ) ;
2013-12-12 22:50:02 +01:00
/* Start LTSSM. */
2017-03-28 08:42:49 -07:00
if ( imx6_pcie - > variant = = IMX7D )
reset_control_deassert ( imx6_pcie - > apps_reset ) ;
else
regmap_update_bits ( imx6_pcie - > iomuxc_gpr , IOMUXC_GPR12 ,
IMX6Q_GPR12_PCIE_CTL_2 , 1 < < 10 ) ;
2013-12-12 22:50:02 +01:00
2016-10-11 22:06:47 -05:00
ret = imx6_pcie_wait_for_link ( imx6_pcie ) ;
2016-12-27 12:40:43 -02:00
if ( ret )
2016-01-25 16:49:53 -06:00
goto err_reset_phy ;
2013-12-12 22:50:02 +01:00
2016-04-19 19:52:44 -05:00
if ( imx6_pcie - > link_gen = = 2 ) {
/* Allow Gen2 mode after the link is up. */
2017-02-15 18:48:14 +05:30
tmp = dw_pcie_readl_dbi ( pci , PCIE_RC_LCR ) ;
2016-04-19 19:52:44 -05:00
tmp & = ~ PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK ;
tmp | = PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2 ;
2017-02-15 18:48:14 +05:30
dw_pcie_writel_dbi ( pci , PCIE_RC_LCR , tmp ) ;
2013-12-12 22:50:02 +01:00
2017-03-28 08:42:51 -07:00
/*
2017-03-28 08:42:52 -07:00
* Start Directed Speed Change so the best possible
* speed both link partners support can be negotiated .
2017-03-28 08:42:51 -07:00
*/
2017-03-28 08:42:52 -07:00
tmp = dw_pcie_readl_dbi ( pci , PCIE_LINK_WIDTH_SPEED_CONTROL ) ;
tmp | = PORT_LOGIC_SPEED_CHANGE ;
dw_pcie_writel_dbi ( pci , PCIE_LINK_WIDTH_SPEED_CONTROL , tmp ) ;
if ( imx6_pcie - > variant ! = IMX7D ) {
/*
* On i . MX7 , DIRECT_SPEED_CHANGE behaves differently
* from i . MX6 family when no link speed transition
* occurs and we go Gen1 - > yep , Gen1 . The difference
* is that , in such case , it will not be cleared by HW
* which will cause the following code to report false
* failure .
*/
ret = imx6_pcie_wait_for_speed_change ( imx6_pcie ) ;
if ( ret ) {
dev_err ( dev , " Failed to bring link up! \n " ) ;
goto err_reset_phy ;
}
}
2017-03-28 08:42:51 -07:00
2017-03-28 08:42:52 -07:00
/* Make sure link training is finished as well! */
ret = imx6_pcie_wait_for_link ( imx6_pcie ) ;
2017-03-28 08:42:51 -07:00
if ( ret ) {
dev_err ( dev , " Failed to bring link up! \n " ) ;
goto err_reset_phy ;
}
2017-03-28 08:42:52 -07:00
} else {
dev_info ( dev , " Link: Gen2 disabled \n " ) ;
2013-12-12 22:50:02 +01:00
}
2017-02-15 18:48:14 +05:30
tmp = dw_pcie_readl_dbi ( pci , PCIE_RC_LCSR ) ;
2016-10-06 13:35:18 -05:00
dev_info ( dev , " Link up, Gen%i \n " , ( tmp > > 16 ) & 0xf ) ;
2015-06-12 14:30:16 -05:00
return 0 ;
2016-01-25 16:49:53 -06:00
err_reset_phy :
2016-10-06 13:35:18 -05:00
dev_dbg ( dev , " PHY DEBUG_R0=0x%08x DEBUG_R1=0x%08x \n " ,
2017-02-15 18:48:14 +05:30
dw_pcie_readl_dbi ( pci , PCIE_PHY_DEBUG_R0 ) ,
dw_pcie_readl_dbi ( pci , PCIE_PHY_DEBUG_R1 ) ) ;
2016-10-11 22:18:26 -05:00
imx6_pcie_reset_phy ( imx6_pcie ) ;
2016-01-25 16:49:53 -06:00
return ret ;
2013-12-12 22:50:02 +01:00
}
2017-07-15 23:39:45 -07:00
static int imx6_pcie_host_init ( struct pcie_port * pp )
2013-12-12 22:50:02 +01:00
{
2017-02-15 18:48:14 +05:30
struct dw_pcie * pci = to_dw_pcie_from_pp ( pp ) ;
struct imx6_pcie * imx6_pcie = to_imx6_pcie ( pci ) ;
2013-09-26 11:24:47 +08:00
2016-10-11 22:06:47 -05:00
imx6_pcie_assert_core_reset ( imx6_pcie ) ;
imx6_pcie_init_phy ( imx6_pcie ) ;
imx6_pcie_deassert_core_reset ( imx6_pcie ) ;
2013-09-26 11:24:47 +08:00
dw_pcie_setup_rc ( pp ) ;
2016-10-11 22:06:47 -05:00
imx6_pcie_establish_link ( imx6_pcie ) ;
2014-03-28 17:52:59 +01:00
if ( IS_ENABLED ( CONFIG_PCI_MSI ) )
dw_pcie_msi_init ( pp ) ;
2017-07-15 23:39:45 -07:00
return 0 ;
2013-09-26 11:24:47 +08:00
}
2017-02-15 18:48:14 +05:30
static int imx6_pcie_link_up ( struct dw_pcie * pci )
2013-09-26 11:24:47 +08:00
{
2017-02-15 18:48:14 +05:30
return dw_pcie_readl_dbi ( pci , PCIE_PHY_DEBUG_R1 ) &
2016-01-25 16:50:02 -06:00
PCIE_PHY_DEBUG_R1_XMLH_LINK_UP ;
2013-09-26 11:24:47 +08:00
}
2017-06-05 16:53:46 +08:00
static const struct dw_pcie_host_ops imx6_pcie_host_ops = {
2013-09-26 11:24:47 +08:00
. host_init = imx6_pcie_host_init ,
} ;
2017-03-28 08:42:50 -07:00
static int imx6_add_pcie_port ( struct imx6_pcie * imx6_pcie ,
struct platform_device * pdev )
2013-09-26 11:24:47 +08:00
{
2017-02-15 18:48:14 +05:30
struct dw_pcie * pci = imx6_pcie - > pci ;
struct pcie_port * pp = & pci - > pp ;
struct device * dev = & pdev - > dev ;
2013-09-26 11:24:47 +08:00
int ret ;
2014-03-28 17:52:59 +01:00
if ( IS_ENABLED ( CONFIG_PCI_MSI ) ) {
pp - > msi_irq = platform_get_irq_byname ( pdev , " msi " ) ;
if ( pp - > msi_irq < = 0 ) {
2016-10-06 13:35:18 -05:00
dev_err ( dev , " failed to get MSI irq \n " ) ;
2014-03-28 17:52:59 +01:00
return - ENODEV ;
}
2016-10-06 13:35:18 -05:00
ret = devm_request_irq ( dev , pp - > msi_irq ,
2014-11-12 12:25:09 +09:00
imx6_pcie_msi_handler ,
2015-12-10 21:18:20 +02:00
IRQF_SHARED | IRQF_NO_THREAD ,
2016-10-11 22:06:47 -05:00
" mx6-pcie-msi " , imx6_pcie ) ;
2014-03-28 17:52:59 +01:00
if ( ret ) {
2016-10-06 13:35:18 -05:00
dev_err ( dev , " failed to request MSI irq \n " ) ;
2015-09-11 09:08:52 -03:00
return ret ;
2014-03-28 17:52:59 +01:00
}
}
2013-09-26 11:24:47 +08:00
pp - > root_bus_nr = - 1 ;
pp - > ops = & imx6_pcie_host_ops ;
ret = dw_pcie_host_init ( pp ) ;
if ( ret ) {
2016-10-06 13:35:18 -05:00
dev_err ( dev , " failed to initialize host \n " ) ;
2013-09-26 11:24:47 +08:00
return ret ;
}
return 0 ;
}
2017-02-15 18:48:14 +05:30
static const struct dw_pcie_ops dw_pcie_ops = {
. link_up = imx6_pcie_link_up ,
} ;
2017-03-28 08:42:50 -07:00
static int imx6_pcie_probe ( struct platform_device * pdev )
2013-09-26 11:24:47 +08:00
{
2016-10-06 13:35:18 -05:00
struct device * dev = & pdev - > dev ;
2017-02-15 18:48:14 +05:30
struct dw_pcie * pci ;
2013-09-26 11:24:47 +08:00
struct imx6_pcie * imx6_pcie ;
struct resource * dbi_base ;
2016-10-06 13:35:18 -05:00
struct device_node * node = dev - > of_node ;
2013-09-26 11:24:47 +08:00
int ret ;
2016-10-06 13:35:18 -05:00
imx6_pcie = devm_kzalloc ( dev , sizeof ( * imx6_pcie ) , GFP_KERNEL ) ;
2013-09-26 11:24:47 +08:00
if ( ! imx6_pcie )
return - ENOMEM ;
2017-02-15 18:48:14 +05:30
pci = devm_kzalloc ( dev , sizeof ( * pci ) , GFP_KERNEL ) ;
if ( ! pci )
return - ENOMEM ;
pci - > dev = dev ;
pci - > ops = & dw_pcie_ops ;
2013-09-26 11:24:47 +08:00
2017-02-25 02:08:12 -08:00
imx6_pcie - > pci = pci ;
2016-05-02 14:08:21 -05:00
imx6_pcie - > variant =
2016-10-06 13:35:18 -05:00
( enum imx6_pcie_variants ) of_device_get_match_data ( dev ) ;
2016-04-05 16:53:27 -05:00
2013-09-26 11:24:47 +08:00
dbi_base = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
2017-02-15 18:48:14 +05:30
pci - > dbi_base = devm_ioremap_resource ( dev , dbi_base ) ;
if ( IS_ERR ( pci - > dbi_base ) )
return PTR_ERR ( pci - > dbi_base ) ;
2013-09-26 11:24:47 +08:00
/* Fetch GPIOs */
2016-10-06 13:35:18 -05:00
imx6_pcie - > reset_gpio = of_get_named_gpio ( node , " reset-gpio " , 0 ) ;
imx6_pcie - > gpio_active_high = of_property_read_bool ( node ,
PCI: imx6: Add reset-gpio-active-high boolean property to DT
Currently the reset-gpio DT property which controls the PCI bus device
reset signal defaults to active-low reset sequence (L=reset state,
H=operation state) plus the code in reset function isn't GPIO polarity
aware - it doesn't matter if the defined reset-gpio is active-low or
active-high, it will always result into active-low reset sequence.
I've tried to fix it properly and change the reset-gpio reset sequence to
be polarity-aware, but this patch has been accepted and then reverted as it
has introduced few backward incompatible issues:
1. Some DTBs, for example, imx6qdl-sabresd, don't define reset-gpio
polarity correctly:
reset-gpio = <&gpio7 12 0>;
which means that it's defined as active-high, but in reality it's
active-low; thus it wouldn't work without a DTS fix.
2. The logic in the reset function is inverted:
gpio_set_value_cansleep(imx6_pcie->reset_gpio, 0)
msleep(100);
gpio_set_value_cansleep(imx6_pcie->reset_gpio, 1);
so even if some of the i.MX6 boards had reset-gpio polarity defined
correctly in their DTSes, they would stop working.
As we can't break old DTBs, we can't fix them, so we need to introduce this
new DT reset-gpio-active-high boolean property so we can support boards
with active-high reset sequence.
This active-high reset sequence is for example needed on Apalis SoMs, where
GPIO1_IO28, used to PCIe reset is not connected directly to PERST# PCIe
signal, but it's ORed with RESETBMCU coming off the PMIC, and thus is
inverted, active-high.
Tested-by: Tim Harvey <tharvey@gateworks.com> # Gateworks Ventana boards (which have active-low PERST#)
Signed-off-by: Petr Štetiar <ynezz@true.cz>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Lucas Stach <l.stach@pengutronix.de>
Acked-by: Rob Herring <robh@kernel.org>
2016-04-19 19:42:07 -05:00
" reset-gpio-active-high " ) ;
2016-03-28 18:45:36 -03:00
if ( gpio_is_valid ( imx6_pcie - > reset_gpio ) ) {
2016-10-06 13:35:18 -05:00
ret = devm_gpio_request_one ( dev , imx6_pcie - > reset_gpio ,
PCI: imx6: Add reset-gpio-active-high boolean property to DT
Currently the reset-gpio DT property which controls the PCI bus device
reset signal defaults to active-low reset sequence (L=reset state,
H=operation state) plus the code in reset function isn't GPIO polarity
aware - it doesn't matter if the defined reset-gpio is active-low or
active-high, it will always result into active-low reset sequence.
I've tried to fix it properly and change the reset-gpio reset sequence to
be polarity-aware, but this patch has been accepted and then reverted as it
has introduced few backward incompatible issues:
1. Some DTBs, for example, imx6qdl-sabresd, don't define reset-gpio
polarity correctly:
reset-gpio = <&gpio7 12 0>;
which means that it's defined as active-high, but in reality it's
active-low; thus it wouldn't work without a DTS fix.
2. The logic in the reset function is inverted:
gpio_set_value_cansleep(imx6_pcie->reset_gpio, 0)
msleep(100);
gpio_set_value_cansleep(imx6_pcie->reset_gpio, 1);
so even if some of the i.MX6 boards had reset-gpio polarity defined
correctly in their DTSes, they would stop working.
As we can't break old DTBs, we can't fix them, so we need to introduce this
new DT reset-gpio-active-high boolean property so we can support boards
with active-high reset sequence.
This active-high reset sequence is for example needed on Apalis SoMs, where
GPIO1_IO28, used to PCIe reset is not connected directly to PERST# PCIe
signal, but it's ORed with RESETBMCU coming off the PMIC, and thus is
inverted, active-high.
Tested-by: Tim Harvey <tharvey@gateworks.com> # Gateworks Ventana boards (which have active-low PERST#)
Signed-off-by: Petr Štetiar <ynezz@true.cz>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Lucas Stach <l.stach@pengutronix.de>
Acked-by: Rob Herring <robh@kernel.org>
2016-04-19 19:42:07 -05:00
imx6_pcie - > gpio_active_high ?
GPIOF_OUT_INIT_HIGH :
GPIOF_OUT_INIT_LOW ,
" PCIe reset " ) ;
2016-03-28 18:45:36 -03:00
if ( ret ) {
2016-10-06 13:35:18 -05:00
dev_err ( dev , " unable to get reset gpio \n " ) ;
2016-03-28 18:45:36 -03:00
return ret ;
}
2017-03-28 08:42:50 -07:00
} else if ( imx6_pcie - > reset_gpio = = - EPROBE_DEFER ) {
return imx6_pcie - > reset_gpio ;
2016-03-28 18:45:36 -03:00
}
2013-09-26 11:24:47 +08:00
/* Fetch clocks */
2016-10-06 13:35:18 -05:00
imx6_pcie - > pcie_phy = devm_clk_get ( dev , " pcie_phy " ) ;
2014-03-28 17:52:55 +01:00
if ( IS_ERR ( imx6_pcie - > pcie_phy ) ) {
2016-10-06 13:35:18 -05:00
dev_err ( dev , " pcie_phy clock source missing or invalid \n " ) ;
2014-03-28 17:52:55 +01:00
return PTR_ERR ( imx6_pcie - > pcie_phy ) ;
2013-09-26 11:24:47 +08:00
}
2016-10-06 13:35:18 -05:00
imx6_pcie - > pcie_bus = devm_clk_get ( dev , " pcie_bus " ) ;
2014-03-28 17:52:55 +01:00
if ( IS_ERR ( imx6_pcie - > pcie_bus ) ) {
2016-10-06 13:35:18 -05:00
dev_err ( dev , " pcie_bus clock source missing or invalid \n " ) ;
2014-03-28 17:52:55 +01:00
return PTR_ERR ( imx6_pcie - > pcie_bus ) ;
2013-09-26 11:24:47 +08:00
}
2016-10-06 13:35:18 -05:00
imx6_pcie - > pcie = devm_clk_get ( dev , " pcie " ) ;
2014-03-28 17:52:55 +01:00
if ( IS_ERR ( imx6_pcie - > pcie ) ) {
2016-10-06 13:35:18 -05:00
dev_err ( dev , " pcie clock source missing or invalid \n " ) ;
2014-03-28 17:52:55 +01:00
return PTR_ERR ( imx6_pcie - > pcie ) ;
2013-09-26 11:24:47 +08:00
}
2017-03-28 08:42:49 -07:00
switch ( imx6_pcie - > variant ) {
case IMX6SX :
2016-10-06 13:35:18 -05:00
imx6_pcie - > pcie_inbound_axi = devm_clk_get ( dev ,
2016-04-05 16:53:27 -05:00
" pcie_inbound_axi " ) ;
if ( IS_ERR ( imx6_pcie - > pcie_inbound_axi ) ) {
2017-02-07 07:50:25 -08:00
dev_err ( dev , " pcie_inbound_axi clock missing or invalid \n " ) ;
2016-04-05 16:53:27 -05:00
return PTR_ERR ( imx6_pcie - > pcie_inbound_axi ) ;
}
2017-03-28 08:42:49 -07:00
break ;
case IMX7D :
2017-07-19 17:25:56 +02:00
imx6_pcie - > pciephy_reset = devm_reset_control_get_exclusive ( dev ,
" pciephy " ) ;
2017-03-28 08:42:49 -07:00
if ( IS_ERR ( imx6_pcie - > pciephy_reset ) ) {
2017-04-21 08:02:30 +01:00
dev_err ( dev , " Failed to get PCIEPHY reset control \n " ) ;
2017-03-28 08:42:49 -07:00
return PTR_ERR ( imx6_pcie - > pciephy_reset ) ;
}
2017-07-19 17:25:56 +02:00
imx6_pcie - > apps_reset = devm_reset_control_get_exclusive ( dev ,
" apps " ) ;
2017-03-28 08:42:49 -07:00
if ( IS_ERR ( imx6_pcie - > apps_reset ) ) {
2017-04-21 08:02:30 +01:00
dev_err ( dev , " Failed to get PCIE APPS reset control \n " ) ;
2017-03-28 08:42:49 -07:00
return PTR_ERR ( imx6_pcie - > apps_reset ) ;
}
break ;
default :
break ;
2016-04-05 16:53:27 -05:00
}
2013-09-26 11:24:47 +08:00
/* Grab GPR config register range */
imx6_pcie - > iomuxc_gpr =
syscon_regmap_lookup_by_compatible ( " fsl,imx6q-iomuxc-gpr " ) ;
if ( IS_ERR ( imx6_pcie - > iomuxc_gpr ) ) {
2016-10-06 13:35:18 -05:00
dev_err ( dev , " unable to find iomuxc registers \n " ) ;
2013-12-02 01:39:35 -02:00
return PTR_ERR ( imx6_pcie - > iomuxc_gpr ) ;
2013-09-26 11:24:47 +08:00
}
2016-01-15 10:24:35 -05:00
/* Grab PCIe PHY Tx Settings */
if ( of_property_read_u32 ( node , " fsl,tx-deemph-gen1 " ,
& imx6_pcie - > tx_deemph_gen1 ) )
imx6_pcie - > tx_deemph_gen1 = 0 ;
if ( of_property_read_u32 ( node , " fsl,tx-deemph-gen2-3p5db " ,
& imx6_pcie - > tx_deemph_gen2_3p5db ) )
imx6_pcie - > tx_deemph_gen2_3p5db = 0 ;
if ( of_property_read_u32 ( node , " fsl,tx-deemph-gen2-6db " ,
& imx6_pcie - > tx_deemph_gen2_6db ) )
imx6_pcie - > tx_deemph_gen2_6db = 20 ;
if ( of_property_read_u32 ( node , " fsl,tx-swing-full " ,
& imx6_pcie - > tx_swing_full ) )
imx6_pcie - > tx_swing_full = 127 ;
if ( of_property_read_u32 ( node , " fsl,tx-swing-low " ,
& imx6_pcie - > tx_swing_low ) )
imx6_pcie - > tx_swing_low = 127 ;
2013-09-26 11:24:47 +08:00
2016-04-19 19:52:44 -05:00
/* Limit link speed */
2016-10-06 13:35:18 -05:00
ret = of_property_read_u32 ( node , " fsl,max-link-speed " ,
2016-04-19 19:52:44 -05:00
& imx6_pcie - > link_gen ) ;
if ( ret )
imx6_pcie - > link_gen = 1 ;
2017-06-08 10:07:42 +02:00
imx6_pcie - > vpcie = devm_regulator_get_optional ( & pdev - > dev , " vpcie " ) ;
if ( IS_ERR ( imx6_pcie - > vpcie ) ) {
if ( PTR_ERR ( imx6_pcie - > vpcie ) = = - EPROBE_DEFER )
return - EPROBE_DEFER ;
imx6_pcie - > vpcie = NULL ;
}
2017-02-15 18:48:11 +05:30
platform_set_drvdata ( pdev , imx6_pcie ) ;
2016-10-11 22:06:47 -05:00
ret = imx6_add_pcie_port ( imx6_pcie , pdev ) ;
2013-09-26 11:24:47 +08:00
if ( ret < 0 )
2013-12-02 01:39:35 -02:00
return ret ;
2013-09-26 11:24:47 +08:00
return 0 ;
}
2014-07-31 20:16:05 +02:00
static void imx6_pcie_shutdown ( struct platform_device * pdev )
{
struct imx6_pcie * imx6_pcie = platform_get_drvdata ( pdev ) ;
/* bring down link, so bootloader gets clean state in case of reboot */
2016-10-11 22:06:47 -05:00
imx6_pcie_assert_core_reset ( imx6_pcie ) ;
2014-07-31 20:16:05 +02:00
}
2013-09-26 11:24:47 +08:00
static const struct of_device_id imx6_pcie_of_match [ ] = {
2016-05-02 14:08:21 -05:00
{ . compatible = " fsl,imx6q-pcie " , . data = ( void * ) IMX6Q , } ,
{ . compatible = " fsl,imx6sx-pcie " , . data = ( void * ) IMX6SX , } ,
2016-05-02 14:09:10 -05:00
{ . compatible = " fsl,imx6qp-pcie " , . data = ( void * ) IMX6QP , } ,
2017-03-28 08:42:49 -07:00
{ . compatible = " fsl,imx7d-pcie " , . data = ( void * ) IMX7D , } ,
2013-09-26 11:24:47 +08:00
{ } ,
} ;
static struct platform_driver imx6_pcie_driver = {
. driver = {
. name = " imx6q-pcie " ,
2013-10-21 14:36:41 +05:30
. of_match_table = imx6_pcie_of_match ,
2017-04-20 15:36:25 -05:00
. suppress_bind_attrs = true ,
2013-09-26 11:24:47 +08:00
} ,
2017-03-28 08:42:50 -07:00
. probe = imx6_pcie_probe ,
2014-07-31 20:16:05 +02:00
. shutdown = imx6_pcie_shutdown ,
2013-09-26 11:24:47 +08:00
} ;
static int __init imx6_pcie_init ( void )
{
2017-03-28 08:42:50 -07:00
/*
* Since probe ( ) can be deferred we need to make sure that
* hook_fault_code is not called after __init memory is freed
* by kernel and since imx6q_pcie_abort_handler ( ) is a no - op ,
* we can install the handler here without risking it
* accessing some uninitialized driver state .
*/
2017-05-22 17:06:30 -05:00
hook_fault_code ( 8 , imx6q_pcie_abort_handler , SIGBUS , 0 ,
" external abort on non-linefetch " ) ;
2017-03-28 08:42:50 -07:00
return platform_driver_register ( & imx6_pcie_driver ) ;
2013-09-26 11:24:47 +08:00
}
2016-08-22 17:59:43 -04:00
device_initcall ( imx6_pcie_init ) ;