2018-01-26 14:22:04 -06:00
// SPDX-License-Identifier: GPL-2.0+
2014-08-20 21:56:02 +05:30
/*
* PCIe host controller driver for Xilinx AXI PCIe Bridge
*
* Copyright ( c ) 2012 - 2014 Xilinx , Inc .
*
* Based on the Tegra PCIe driver
*
2017-09-01 16:35:50 -05:00
* Bits taken from Synopsys DesignWare Host controller driver and
2014-08-20 21:56:02 +05:30
* ARM PCI Host generic driver .
*/
# include <linux/interrupt.h>
# include <linux/irq.h>
# include <linux/irqdomain.h>
# include <linux/kernel.h>
2016-08-24 16:57:49 -04:00
# include <linux/init.h>
2014-08-20 21:56:02 +05:30
# include <linux/msi.h>
# include <linux/of_address.h>
# include <linux/of_pci.h>
# include <linux/of_platform.h>
# include <linux/of_irq.h>
# include <linux/pci.h>
# include <linux/platform_device.h>
2018-05-11 12:15:30 -05:00
# include "../pci.h"
2014-08-20 21:56:02 +05:30
/* Register definitions */
# define XILINX_PCIE_REG_BIR 0x00000130
# define XILINX_PCIE_REG_IDR 0x00000138
# define XILINX_PCIE_REG_IMR 0x0000013c
# define XILINX_PCIE_REG_PSCR 0x00000144
# define XILINX_PCIE_REG_RPSC 0x00000148
# define XILINX_PCIE_REG_MSIBASE1 0x0000014c
# define XILINX_PCIE_REG_MSIBASE2 0x00000150
# define XILINX_PCIE_REG_RPEFR 0x00000154
# define XILINX_PCIE_REG_RPIFR1 0x00000158
# define XILINX_PCIE_REG_RPIFR2 0x0000015c
/* Interrupt registers definitions */
# define XILINX_PCIE_INTR_LINK_DOWN BIT(0)
# define XILINX_PCIE_INTR_ECRC_ERR BIT(1)
# define XILINX_PCIE_INTR_STR_ERR BIT(2)
# define XILINX_PCIE_INTR_HOT_RESET BIT(3)
# define XILINX_PCIE_INTR_CFG_TIMEOUT BIT(8)
# define XILINX_PCIE_INTR_CORRECTABLE BIT(9)
# define XILINX_PCIE_INTR_NONFATAL BIT(10)
# define XILINX_PCIE_INTR_FATAL BIT(11)
# define XILINX_PCIE_INTR_INTX BIT(16)
# define XILINX_PCIE_INTR_MSI BIT(17)
# define XILINX_PCIE_INTR_SLV_UNSUPP BIT(20)
# define XILINX_PCIE_INTR_SLV_UNEXP BIT(21)
# define XILINX_PCIE_INTR_SLV_COMPL BIT(22)
# define XILINX_PCIE_INTR_SLV_ERRP BIT(23)
# define XILINX_PCIE_INTR_SLV_CMPABT BIT(24)
# define XILINX_PCIE_INTR_SLV_ILLBUR BIT(25)
# define XILINX_PCIE_INTR_MST_DECERR BIT(26)
# define XILINX_PCIE_INTR_MST_SLVERR BIT(27)
# define XILINX_PCIE_INTR_MST_ERRP BIT(28)
# define XILINX_PCIE_IMR_ALL_MASK 0x1FF30FED
2017-08-15 16:25:25 -05:00
# define XILINX_PCIE_IMR_ENABLE_MASK 0x1FF30F0D
2014-08-20 21:56:02 +05:30
# define XILINX_PCIE_IDR_ALL_MASK 0xFFFFFFFF
/* Root Port Error FIFO Read Register definitions */
# define XILINX_PCIE_RPEFR_ERR_VALID BIT(18)
# define XILINX_PCIE_RPEFR_REQ_ID GENMASK(15, 0)
# define XILINX_PCIE_RPEFR_ALL_MASK 0xFFFFFFFF
/* Root Port Interrupt FIFO Read Register 1 definitions */
# define XILINX_PCIE_RPIFR1_INTR_VALID BIT(31)
# define XILINX_PCIE_RPIFR1_MSI_INTR BIT(30)
# define XILINX_PCIE_RPIFR1_INTR_MASK GENMASK(28, 27)
# define XILINX_PCIE_RPIFR1_ALL_MASK 0xFFFFFFFF
# define XILINX_PCIE_RPIFR1_INTR_SHIFT 27
/* Bridge Info Register definitions */
# define XILINX_PCIE_BIR_ECAM_SZ_MASK GENMASK(18, 16)
# define XILINX_PCIE_BIR_ECAM_SZ_SHIFT 16
/* Root Port Interrupt FIFO Read Register 2 definitions */
# define XILINX_PCIE_RPIFR2_MSG_DATA GENMASK(15, 0)
/* Root Port Status/control Register definitions */
# define XILINX_PCIE_REG_RPSC_BEN BIT(0)
/* Phy Status/Control Register definitions */
# define XILINX_PCIE_REG_PSCR_LNKUP BIT(11)
/* ECAM definitions */
# define ECAM_BUS_NUM_SHIFT 20
# define ECAM_DEV_NUM_SHIFT 12
/* Number of MSI IRQs */
# define XILINX_NUM_MSI_IRQS 128
/**
* struct xilinx_pcie_port - PCIe port information
* @ reg_base : IO Mapped Register Base
* @ irq : Interrupt number
* @ msi_pages : MSI pages
* @ root_busno : Root Bus number
* @ dev : Device pointer
2016-09-01 15:44:41 +05:30
* @ msi_domain : MSI IRQ domain pointer
* @ leg_domain : Legacy IRQ domain pointer
2014-08-20 21:56:02 +05:30
* @ resources : Bus Resources
*/
struct xilinx_pcie_port {
void __iomem * reg_base ;
u32 irq ;
unsigned long msi_pages ;
u8 root_busno ;
struct device * dev ;
2016-09-01 15:44:41 +05:30
struct irq_domain * msi_domain ;
struct irq_domain * leg_domain ;
2014-08-20 21:56:02 +05:30
struct list_head resources ;
} ;
static DECLARE_BITMAP ( msi_irq_in_use , XILINX_NUM_MSI_IRQS ) ;
static inline u32 pcie_read ( struct xilinx_pcie_port * port , u32 reg )
{
return readl ( port - > reg_base + reg ) ;
}
static inline void pcie_write ( struct xilinx_pcie_port * port , u32 val , u32 reg )
{
writel ( val , port - > reg_base + reg ) ;
}
2017-11-09 16:19:47 -06:00
static inline bool xilinx_pcie_link_up ( struct xilinx_pcie_port * port )
2014-08-20 21:56:02 +05:30
{
return ( pcie_read ( port , XILINX_PCIE_REG_PSCR ) &
XILINX_PCIE_REG_PSCR_LNKUP ) ? 1 : 0 ;
}
/**
* xilinx_pcie_clear_err_interrupts - Clear Error Interrupts
* @ port : PCIe port information
*/
static void xilinx_pcie_clear_err_interrupts ( struct xilinx_pcie_port * port )
{
2016-10-06 13:44:42 -05:00
struct device * dev = port - > dev ;
2015-01-13 15:20:05 +01:00
unsigned long val = pcie_read ( port , XILINX_PCIE_REG_RPEFR ) ;
2014-08-20 21:56:02 +05:30
if ( val & XILINX_PCIE_RPEFR_ERR_VALID ) {
2016-10-06 13:44:42 -05:00
dev_dbg ( dev , " Requester ID %lu \n " ,
2014-08-20 21:56:02 +05:30
val & XILINX_PCIE_RPEFR_REQ_ID ) ;
pcie_write ( port , XILINX_PCIE_RPEFR_ALL_MASK ,
XILINX_PCIE_REG_RPEFR ) ;
}
}
/**
* xilinx_pcie_valid_device - Check if a valid device is present on bus
* @ bus : PCI Bus structure
* @ devfn : device / function
*
* Return : ' true ' on success and ' false ' if invalid device is found
*/
static bool xilinx_pcie_valid_device ( struct pci_bus * bus , unsigned int devfn )
{
2016-02-11 21:58:08 +05:30
struct xilinx_pcie_port * port = bus - > sysdata ;
2014-08-20 21:56:02 +05:30
/* Check if link is up when trying to access downstream ports */
if ( bus - > number ! = port - > root_busno )
2017-11-09 16:19:47 -06:00
if ( ! xilinx_pcie_link_up ( port ) )
2014-08-20 21:56:02 +05:30
return false ;
/* Only one device down on each root port */
if ( bus - > number = = port - > root_busno & & devfn > 0 )
return false ;
return true ;
}
/**
2015-01-09 20:34:50 -06:00
* xilinx_pcie_map_bus - Get configuration base
2014-08-20 21:56:02 +05:30
* @ bus : PCI Bus structure
* @ devfn : Device / function
* @ where : Offset from base
*
* Return : Base address of the configuration space needed to be
* accessed .
*/
2015-01-09 20:34:50 -06:00
static void __iomem * xilinx_pcie_map_bus ( struct pci_bus * bus ,
unsigned int devfn , int where )
2014-08-20 21:56:02 +05:30
{
2016-02-11 21:58:08 +05:30
struct xilinx_pcie_port * port = bus - > sysdata ;
2014-08-20 21:56:02 +05:30
int relbus ;
2015-01-09 20:34:50 -06:00
if ( ! xilinx_pcie_valid_device ( bus , devfn ) )
return NULL ;
2014-08-20 21:56:02 +05:30
relbus = ( bus - > number < < ECAM_BUS_NUM_SHIFT ) |
( devfn < < ECAM_DEV_NUM_SHIFT ) ;
return port - > reg_base + relbus + where ;
}
/* PCIe operations */
static struct pci_ops xilinx_pcie_ops = {
2015-01-09 20:34:50 -06:00
. map_bus = xilinx_pcie_map_bus ,
. read = pci_generic_config_read ,
. write = pci_generic_config_write ,
2014-08-20 21:56:02 +05:30
} ;
/* MSI functions */
/**
* xilinx_pcie_destroy_msi - Free MSI number
* @ irq : IRQ to be freed
*/
static void xilinx_pcie_destroy_msi ( unsigned int irq )
{
struct msi_desc * msi ;
struct xilinx_pcie_port * port ;
2016-09-01 15:44:43 +05:30
struct irq_data * d = irq_get_irq_data ( irq ) ;
irq_hw_number_t hwirq = irqd_to_hwirq ( d ) ;
2014-08-20 21:56:02 +05:30
2016-09-01 15:44:43 +05:30
if ( ! test_bit ( hwirq , msi_irq_in_use ) ) {
2015-07-09 16:00:43 +08:00
msi = irq_get_msi_desc ( irq ) ;
2016-02-11 21:58:08 +05:30
port = msi_desc_to_pci_sysdata ( msi ) ;
2014-08-20 21:56:02 +05:30
dev_err ( port - > dev , " Trying to free unused MSI#%d \n " , irq ) ;
2015-07-09 16:00:43 +08:00
} else {
2016-09-01 15:44:43 +05:30
clear_bit ( hwirq , msi_irq_in_use ) ;
2015-07-09 16:00:43 +08:00
}
2014-08-20 21:56:02 +05:30
}
/**
* xilinx_pcie_assign_msi - Allocate MSI number
*
* Return : A valid IRQ on success and error value on failure .
*/
2016-10-11 11:36:49 -05:00
static int xilinx_pcie_assign_msi ( void )
2014-08-20 21:56:02 +05:30
{
int pos ;
pos = find_first_zero_bit ( msi_irq_in_use , XILINX_NUM_MSI_IRQS ) ;
if ( pos < XILINX_NUM_MSI_IRQS )
set_bit ( pos , msi_irq_in_use ) ;
else
return - ENOSPC ;
return pos ;
}
/**
* xilinx_msi_teardown_irq - Destroy the MSI
* @ chip : MSI Chip descriptor
* @ irq : MSI IRQ to destroy
*/
2014-11-11 17:45:45 -07:00
static void xilinx_msi_teardown_irq ( struct msi_controller * chip ,
unsigned int irq )
2014-08-20 21:56:02 +05:30
{
xilinx_pcie_destroy_msi ( irq ) ;
2016-09-01 15:44:44 +05:30
irq_dispose_mapping ( irq ) ;
2014-08-20 21:56:02 +05:30
}
/**
* xilinx_pcie_msi_setup_irq - Setup MSI request
* @ chip : MSI chip pointer
* @ pdev : PCIe device pointer
* @ desc : MSI descriptor pointer
*
* Return : ' 0 ' on success and error value on failure
*/
2014-11-11 17:45:45 -07:00
static int xilinx_pcie_msi_setup_irq ( struct msi_controller * chip ,
2014-08-20 21:56:02 +05:30
struct pci_dev * pdev ,
struct msi_desc * desc )
{
2016-02-11 21:58:08 +05:30
struct xilinx_pcie_port * port = pdev - > bus - > sysdata ;
2014-08-20 21:56:02 +05:30
unsigned int irq ;
int hwirq ;
struct msi_msg msg ;
phys_addr_t msg_addr ;
2016-10-11 11:36:49 -05:00
hwirq = xilinx_pcie_assign_msi ( ) ;
2014-09-09 15:11:50 +03:00
if ( hwirq < 0 )
return hwirq ;
2014-08-20 21:56:02 +05:30
2016-09-01 15:44:41 +05:30
irq = irq_create_mapping ( port - > msi_domain , hwirq ) ;
2014-08-20 21:56:02 +05:30
if ( ! irq )
return - EINVAL ;
irq_set_msi_desc ( irq , desc ) ;
msg_addr = virt_to_phys ( ( void * ) port - > msi_pages ) ;
msg . address_hi = 0 ;
msg . address_lo = msg_addr ;
msg . data = irq ;
2014-11-09 23:10:34 +08:00
pci_write_msi_msg ( irq , & msg ) ;
2014-08-20 21:56:02 +05:30
return 0 ;
}
/* MSI Chip Descriptor */
2014-11-11 17:45:45 -07:00
static struct msi_controller xilinx_pcie_msi_chip = {
2014-08-20 21:56:02 +05:30
. setup_irq = xilinx_pcie_msi_setup_irq ,
. teardown_irq = xilinx_msi_teardown_irq ,
} ;
/* HW Interrupt Chip Descriptor */
static struct irq_chip xilinx_msi_irq_chip = {
. name = " Xilinx PCIe MSI " ,
2014-11-23 12:23:20 +01:00
. irq_enable = pci_msi_unmask_irq ,
. irq_disable = pci_msi_mask_irq ,
. irq_mask = pci_msi_mask_irq ,
. irq_unmask = pci_msi_unmask_irq ,
2014-08-20 21:56:02 +05:30
} ;
/**
* xilinx_pcie_msi_map - Set the handler for the MSI and mark IRQ as valid
* @ domain : IRQ domain
* @ irq : Virtual IRQ number
* @ hwirq : HW interrupt number
*
* Return : Always returns 0.
*/
static int xilinx_pcie_msi_map ( struct irq_domain * domain , unsigned int irq ,
irq_hw_number_t hwirq )
{
irq_set_chip_and_handler ( irq , & xilinx_msi_irq_chip , handle_simple_irq ) ;
irq_set_chip_data ( irq , domain - > host_data ) ;
return 0 ;
}
/* IRQ Domain operations */
static const struct irq_domain_ops msi_domain_ops = {
. map = xilinx_pcie_msi_map ,
} ;
/**
* xilinx_pcie_enable_msi - Enable MSI support
* @ port : PCIe port information
*/
static void xilinx_pcie_enable_msi ( struct xilinx_pcie_port * port )
{
phys_addr_t msg_addr ;
port - > msi_pages = __get_free_pages ( GFP_KERNEL , 0 ) ;
msg_addr = virt_to_phys ( ( void * ) port - > msi_pages ) ;
pcie_write ( port , 0x0 , XILINX_PCIE_REG_MSIBASE1 ) ;
pcie_write ( port , msg_addr , XILINX_PCIE_REG_MSIBASE2 ) ;
}
/* INTx Functions */
/**
* xilinx_pcie_intx_map - Set the handler for the INTx and mark IRQ as valid
* @ domain : IRQ domain
* @ irq : Virtual IRQ number
* @ hwirq : HW interrupt number
*
* Return : Always returns 0.
*/
static int xilinx_pcie_intx_map ( struct irq_domain * domain , unsigned int irq ,
irq_hw_number_t hwirq )
{
irq_set_chip_and_handler ( irq , & dummy_irq_chip , handle_simple_irq ) ;
irq_set_chip_data ( irq , domain - > host_data ) ;
return 0 ;
}
/* INTx IRQ Domain operations */
static const struct irq_domain_ops intx_domain_ops = {
. map = xilinx_pcie_intx_map ,
2017-08-15 16:25:08 -05:00
. xlate = pci_irqd_intx_xlate ,
2014-08-20 21:56:02 +05:30
} ;
/* PCIe HW Functions */
/**
* xilinx_pcie_intr_handler - Interrupt Service Handler
* @ irq : IRQ number
* @ data : PCIe port information
*
* Return : IRQ_HANDLED on success and IRQ_NONE on failure
*/
static irqreturn_t xilinx_pcie_intr_handler ( int irq , void * data )
{
struct xilinx_pcie_port * port = ( struct xilinx_pcie_port * ) data ;
2016-10-06 13:44:42 -05:00
struct device * dev = port - > dev ;
2017-08-15 16:25:21 -05:00
u32 val , mask , status ;
2014-08-20 21:56:02 +05:30
/* Read interrupt decode and mask registers */
val = pcie_read ( port , XILINX_PCIE_REG_IDR ) ;
mask = pcie_read ( port , XILINX_PCIE_REG_IMR ) ;
status = val & mask ;
if ( ! status )
return IRQ_NONE ;
if ( status & XILINX_PCIE_INTR_LINK_DOWN )
2016-10-06 13:44:42 -05:00
dev_warn ( dev , " Link Down \n " ) ;
2014-08-20 21:56:02 +05:30
if ( status & XILINX_PCIE_INTR_ECRC_ERR )
2016-10-06 13:44:42 -05:00
dev_warn ( dev , " ECRC failed \n " ) ;
2014-08-20 21:56:02 +05:30
if ( status & XILINX_PCIE_INTR_STR_ERR )
2016-10-06 13:44:42 -05:00
dev_warn ( dev , " Streaming error \n " ) ;
2014-08-20 21:56:02 +05:30
if ( status & XILINX_PCIE_INTR_HOT_RESET )
2016-10-06 13:44:42 -05:00
dev_info ( dev , " Hot reset \n " ) ;
2014-08-20 21:56:02 +05:30
if ( status & XILINX_PCIE_INTR_CFG_TIMEOUT )
2016-10-06 13:44:42 -05:00
dev_warn ( dev , " ECAM access timeout \n " ) ;
2014-08-20 21:56:02 +05:30
if ( status & XILINX_PCIE_INTR_CORRECTABLE ) {
2016-10-06 13:44:42 -05:00
dev_warn ( dev , " Correctable error message \n " ) ;
2014-08-20 21:56:02 +05:30
xilinx_pcie_clear_err_interrupts ( port ) ;
}
if ( status & XILINX_PCIE_INTR_NONFATAL ) {
2016-10-06 13:44:42 -05:00
dev_warn ( dev , " Non fatal error message \n " ) ;
2014-08-20 21:56:02 +05:30
xilinx_pcie_clear_err_interrupts ( port ) ;
}
if ( status & XILINX_PCIE_INTR_FATAL ) {
2016-10-06 13:44:42 -05:00
dev_warn ( dev , " Fatal error message \n " ) ;
2014-08-20 21:56:02 +05:30
xilinx_pcie_clear_err_interrupts ( port ) ;
}
2017-08-15 16:25:21 -05:00
if ( status & ( XILINX_PCIE_INTR_INTX | XILINX_PCIE_INTR_MSI ) ) {
2014-08-20 21:56:02 +05:30
val = pcie_read ( port , XILINX_PCIE_REG_RPIFR1 ) ;
/* Check whether interrupt valid */
if ( ! ( val & XILINX_PCIE_RPIFR1_INTR_VALID ) ) {
2016-10-06 13:44:42 -05:00
dev_warn ( dev , " RP Intr FIFO1 read error \n " ) ;
2016-09-01 15:44:42 +05:30
goto error ;
2014-08-20 21:56:02 +05:30
}
2017-08-15 16:25:21 -05:00
/* Decode the IRQ number */
if ( val & XILINX_PCIE_RPIFR1_MSI_INTR ) {
val = pcie_read ( port , XILINX_PCIE_REG_RPIFR2 ) &
XILINX_PCIE_RPIFR2_MSG_DATA ;
} else {
2017-08-15 16:25:08 -05:00
val = ( val & XILINX_PCIE_RPIFR1_INTR_MASK ) > >
XILINX_PCIE_RPIFR1_INTR_SHIFT ;
2017-08-15 16:25:21 -05:00
val = irq_find_mapping ( port - > leg_domain , val ) ;
2015-07-07 17:54:19 +01:00
}
2014-08-20 21:56:02 +05:30
2017-08-15 16:25:21 -05:00
/* Clear interrupt FIFO register 1 */
pcie_write ( port , XILINX_PCIE_RPIFR1_ALL_MASK ,
XILINX_PCIE_REG_RPIFR1 ) ;
2014-08-20 21:56:02 +05:30
2017-08-15 16:25:21 -05:00
/* Handle the interrupt */
if ( IS_ENABLED ( CONFIG_PCI_MSI ) | |
! ( val & XILINX_PCIE_RPIFR1_MSI_INTR ) )
generic_handle_irq ( val ) ;
2014-08-20 21:56:02 +05:30
}
if ( status & XILINX_PCIE_INTR_SLV_UNSUPP )
2016-10-06 13:44:42 -05:00
dev_warn ( dev , " Slave unsupported request \n " ) ;
2014-08-20 21:56:02 +05:30
if ( status & XILINX_PCIE_INTR_SLV_UNEXP )
2016-10-06 13:44:42 -05:00
dev_warn ( dev , " Slave unexpected completion \n " ) ;
2014-08-20 21:56:02 +05:30
if ( status & XILINX_PCIE_INTR_SLV_COMPL )
2016-10-06 13:44:42 -05:00
dev_warn ( dev , " Slave completion timeout \n " ) ;
2014-08-20 21:56:02 +05:30
if ( status & XILINX_PCIE_INTR_SLV_ERRP )
2016-10-06 13:44:42 -05:00
dev_warn ( dev , " Slave Error Poison \n " ) ;
2014-08-20 21:56:02 +05:30
if ( status & XILINX_PCIE_INTR_SLV_CMPABT )
2016-10-06 13:44:42 -05:00
dev_warn ( dev , " Slave Completer Abort \n " ) ;
2014-08-20 21:56:02 +05:30
if ( status & XILINX_PCIE_INTR_SLV_ILLBUR )
2016-10-06 13:44:42 -05:00
dev_warn ( dev , " Slave Illegal Burst \n " ) ;
2014-08-20 21:56:02 +05:30
if ( status & XILINX_PCIE_INTR_MST_DECERR )
2016-10-06 13:44:42 -05:00
dev_warn ( dev , " Master decode error \n " ) ;
2014-08-20 21:56:02 +05:30
if ( status & XILINX_PCIE_INTR_MST_SLVERR )
2016-10-06 13:44:42 -05:00
dev_warn ( dev , " Master slave error \n " ) ;
2014-08-20 21:56:02 +05:30
if ( status & XILINX_PCIE_INTR_MST_ERRP )
2016-10-06 13:44:42 -05:00
dev_warn ( dev , " Master error poison \n " ) ;
2014-08-20 21:56:02 +05:30
2016-09-01 15:44:42 +05:30
error :
2014-08-20 21:56:02 +05:30
/* Clear the Interrupt Decode register */
pcie_write ( port , status , XILINX_PCIE_REG_IDR ) ;
return IRQ_HANDLED ;
}
/**
* xilinx_pcie_init_irq_domain - Initialize IRQ domain
* @ port : PCIe port information
*
* Return : ' 0 ' on success and error value on failure
*/
static int xilinx_pcie_init_irq_domain ( struct xilinx_pcie_port * port )
{
struct device * dev = port - > dev ;
struct device_node * node = dev - > of_node ;
struct device_node * pcie_intc_node ;
/* Setup INTx */
pcie_intc_node = of_get_next_child ( node , NULL ) ;
if ( ! pcie_intc_node ) {
dev_err ( dev , " No PCIe Intc node found \n " ) ;
2016-07-14 12:10:46 +02:00
return - ENODEV ;
2014-08-20 21:56:02 +05:30
}
2017-08-15 16:25:08 -05:00
port - > leg_domain = irq_domain_add_linear ( pcie_intc_node , PCI_NUM_INTX ,
2014-08-20 21:56:02 +05:30
& intx_domain_ops ,
port ) ;
2018-06-29 13:49:54 -05:00
of_node_put ( pcie_intc_node ) ;
2016-09-01 15:44:41 +05:30
if ( ! port - > leg_domain ) {
2014-08-20 21:56:02 +05:30
dev_err ( dev , " Failed to get a INTx IRQ domain \n " ) ;
2016-07-14 12:10:46 +02:00
return - ENODEV ;
2014-08-20 21:56:02 +05:30
}
/* Setup MSI */
if ( IS_ENABLED ( CONFIG_PCI_MSI ) ) {
2016-09-01 15:44:41 +05:30
port - > msi_domain = irq_domain_add_linear ( node ,
2014-08-20 21:56:02 +05:30
XILINX_NUM_MSI_IRQS ,
& msi_domain_ops ,
& xilinx_pcie_msi_chip ) ;
2016-09-01 15:44:41 +05:30
if ( ! port - > msi_domain ) {
2014-08-20 21:56:02 +05:30
dev_err ( dev , " Failed to get a MSI IRQ domain \n " ) ;
2016-07-14 12:10:46 +02:00
return - ENODEV ;
2014-08-20 21:56:02 +05:30
}
xilinx_pcie_enable_msi ( port ) ;
}
return 0 ;
}
/**
* xilinx_pcie_init_port - Initialize hardware
* @ port : PCIe port information
*/
static void xilinx_pcie_init_port ( struct xilinx_pcie_port * port )
{
2016-10-06 13:44:42 -05:00
struct device * dev = port - > dev ;
2017-11-09 16:19:47 -06:00
if ( xilinx_pcie_link_up ( port ) )
2016-10-06 13:44:42 -05:00
dev_info ( dev , " PCIe Link is UP \n " ) ;
2014-08-20 21:56:02 +05:30
else
2016-10-06 13:44:42 -05:00
dev_info ( dev , " PCIe Link is DOWN \n " ) ;
2014-08-20 21:56:02 +05:30
/* Disable all interrupts */
pcie_write ( port , ~ XILINX_PCIE_IDR_ALL_MASK ,
XILINX_PCIE_REG_IMR ) ;
/* Clear pending interrupts */
pcie_write ( port , pcie_read ( port , XILINX_PCIE_REG_IDR ) &
XILINX_PCIE_IMR_ALL_MASK ,
XILINX_PCIE_REG_IDR ) ;
2017-08-15 16:25:25 -05:00
/* Enable all interrupts we handle */
pcie_write ( port , XILINX_PCIE_IMR_ENABLE_MASK , XILINX_PCIE_REG_IMR ) ;
2014-08-20 21:56:02 +05:30
/* Enable the Bridge enable bit */
pcie_write ( port , pcie_read ( port , XILINX_PCIE_REG_RPSC ) |
XILINX_PCIE_REG_RPSC_BEN ,
XILINX_PCIE_REG_RPSC ) ;
}
/**
* xilinx_pcie_parse_dt - Parse Device tree
* @ port : PCIe port information
*
* Return : ' 0 ' on success and error value on failure
*/
static int xilinx_pcie_parse_dt ( struct xilinx_pcie_port * port )
{
struct device * dev = port - > dev ;
struct device_node * node = dev - > of_node ;
struct resource regs ;
int err ;
err = of_address_to_resource ( node , 0 , & regs ) ;
if ( err ) {
dev_err ( dev , " missing \" reg \" property \n " ) ;
return err ;
}
2017-04-19 17:48:57 +01:00
port - > reg_base = devm_pci_remap_cfg_resource ( dev , & regs ) ;
2014-08-20 21:56:02 +05:30
if ( IS_ERR ( port - > reg_base ) )
return PTR_ERR ( port - > reg_base ) ;
port - > irq = irq_of_parse_and_map ( node , 0 ) ;
err = devm_request_irq ( dev , port - > irq , xilinx_pcie_intr_handler ,
2015-12-10 21:18:20 +02:00
IRQF_SHARED | IRQF_NO_THREAD ,
" xilinx-pcie " , port ) ;
2014-08-20 21:56:02 +05:30
if ( err ) {
dev_err ( dev , " unable to request irq %d \n " , port - > irq ) ;
return err ;
}
return 0 ;
}
/**
* xilinx_pcie_probe - Probe function
* @ pdev : Platform device pointer
*
* Return : ' 0 ' on success and error value on failure
*/
static int xilinx_pcie_probe ( struct platform_device * pdev )
{
struct device * dev = & pdev - > dev ;
2016-10-06 13:44:42 -05:00
struct xilinx_pcie_port * port ;
2017-02-08 15:37:47 -06:00
struct pci_bus * bus , * child ;
2017-06-28 15:13:59 -05:00
struct pci_host_bridge * bridge ;
2014-08-20 21:56:02 +05:30
int err ;
2016-02-11 21:58:07 +05:30
resource_size_t iobase = 0 ;
LIST_HEAD ( res ) ;
2014-08-20 21:56:02 +05:30
if ( ! dev - > of_node )
return - ENODEV ;
2017-06-28 15:13:59 -05:00
bridge = devm_pci_alloc_host_bridge ( dev , sizeof ( * port ) ) ;
if ( ! bridge )
return - ENODEV ;
port = pci_host_bridge_priv ( bridge ) ;
2014-08-20 21:56:02 +05:30
port - > dev = dev ;
err = xilinx_pcie_parse_dt ( port ) ;
if ( err ) {
dev_err ( dev , " Parsing DT failed \n " ) ;
return err ;
}
xilinx_pcie_init_port ( port ) ;
err = xilinx_pcie_init_irq_domain ( port ) ;
if ( err ) {
dev_err ( dev , " Failed creating IRQ Domain \n " ) ;
return err ;
}
2018-05-15 11:07:05 +02:00
err = devm_of_pci_get_host_bridge_resources ( dev , 0 , 0xff , & res ,
2018-05-15 11:07:03 +02:00
& iobase ) ;
2014-08-20 21:56:02 +05:30
if ( err ) {
2016-02-11 21:58:07 +05:30
dev_err ( dev , " Getting bridge resources failed \n " ) ;
2014-08-20 21:56:02 +05:30
return err ;
}
2016-05-28 18:27:03 -05:00
err = devm_request_pci_bus_resources ( dev , & res ) ;
if ( err )
goto error ;
2017-06-28 15:13:59 -05:00
list_splice_init ( & res , & bridge - > windows ) ;
bridge - > dev . parent = dev ;
bridge - > sysdata = port ;
bridge - > busnr = 0 ;
bridge - > ops = & xilinx_pcie_ops ;
2017-06-28 15:14:06 -05:00
bridge - > map_irq = of_irq_parse_and_map_pci ;
bridge - > swizzle_irq = pci_common_swizzle ;
2014-11-11 15:45:31 -07:00
# ifdef CONFIG_PCI_MSI
2016-10-06 13:44:42 -05:00
xilinx_pcie_msi_chip . dev = dev ;
2017-06-28 15:13:59 -05:00
bridge - > msi = & xilinx_pcie_msi_chip ;
2014-11-11 15:45:31 -07:00
# endif
2017-06-28 15:13:59 -05:00
err = pci_scan_root_bus_bridge ( bridge ) ;
if ( err < 0 )
goto error ;
bus = bridge - > bus ;
2016-02-11 21:58:08 +05:30
pci_assign_unassigned_bus_resources ( bus ) ;
2017-02-08 15:37:47 -06:00
list_for_each_entry ( child , & bus - > children , node )
pcie_bus_configure_settings ( child ) ;
2016-02-11 21:58:08 +05:30
pci_bus_add_devices ( bus ) ;
2014-08-20 21:56:02 +05:30
return 0 ;
2016-05-31 11:49:14 -05:00
error :
pci_free_resource_list ( & res ) ;
return err ;
2014-08-20 21:56:02 +05:30
}
2017-06-20 11:17:48 +05:30
static const struct of_device_id xilinx_pcie_of_match [ ] = {
2014-08-20 21:56:02 +05:30
{ . compatible = " xlnx,axi-pcie-host-1.00.a " , } ,
{ }
} ;
static struct platform_driver xilinx_pcie_driver = {
. driver = {
. name = " xilinx-pcie " ,
. of_match_table = xilinx_pcie_of_match ,
. suppress_bind_attrs = true ,
} ,
. probe = xilinx_pcie_probe ,
} ;
2016-08-24 16:57:49 -04:00
builtin_platform_driver ( xilinx_pcie_driver ) ;