blob: 8d76a55569aca794e00f8480d3f209bc78e0eaac [file] [log] [blame]
/*
* diags/test_pcie.c
*
* Copyright (C) 2004,2005 Mindspeed Technologies, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <types.h>
#include <common.h>
#include <asm/io.h>
#include <mach/comcerto-2000.h>
#include <mach/pcie.h>
#include <mach/serdes.h>
#include <mach/clkcore.h>
#include <mach/gpio.h>
#include <diags.h>
#include "test_pcie.h"
#include "tests.h"
#include "dump.h"
#include "common_func.h"
#include "serdes_common.h"
#define U8 u8
#define PCI_VENDOR_ID 0x00 /* 16 bits */
#define PCI_DEVICE_ID 0x02 /* 16 bits */
#define PCI_STATUS_CMD 0x04
#define PCI_CLASS_REV 0x08
#define PCI_BIST_HDR_TMR_CSZ 0x0c
#define PCI_SUBSYS_ID 0x2c /* 16 bits */
#define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */
/*** from kernel: ~/arm/mach-comcerto/include/mach/reset.h ***/
#define SERDES_PCIE0_RESET_BIT 0x00000003
#define SERDES_PCIE1_RESET_BIT 0x0000000c
/* DWC PCIEe configuration register offsets on APB */
struct pcie_app_reg app_regs[NUM_PCIE_PORTS] = {
//PCIe0
{ 0x00000000, // cfg0
0x00000004,
0x00000008,
0x0000000C,
0x00000010,
0x00000014,
0x00000018,
0x00000040, // sts0
0x00000044,
0x00000048,
0x00000058,
0x00000080, // pwr_cfg_bdgt_data
0x00000084,
0x000000C0, // radm_sts
0x000000C4, // pwr_sts_bdgt
0x00000100, // intr_sts
0x00000104, // intr_en
0x00000108, // intr_msi_sts
0x0000010C // intr_msi_en
},
//PCIe1
{ 0x00000020, // cfg0
0x00000024,
0x00000028,
0x0000002C,
0x00000030,
0x00000034,
0x00000038,
0x0000004C, // sts0
0x00000050,
0x00000054,
0x0000005C,
0x00000088, // pwr_cfg_bdgt_data
0x0000008C,
0x000000C8, // radm_sts
0x000000CC, // pwr_stst_bdgt
0x00000110,
0x00000114,
0x00000118,
0x0000011C
}
};
/* Keeping all DDR area of 256MB accesible for inbound transaction */
#define INBOUND_ADDR_MASK 0xFFFFFFF
#define PCIE_SETUP_iATU_IB_ENTRY( _pp, _view_port, _base, _limit, _ctl1, _ctl2, _target ) \
{\
comcerto_dbi_write_reg(_pp, PCIE_iATU_VIEW_PORT, 4, (u32)(_view_port|iATU_VIEW_PORT_IN_BOUND)); \
comcerto_dbi_write_reg(_pp, PCIE_iATU_CTRL2, 4, 0); \
comcerto_dbi_write_reg(_pp, PCIE_iATU_SRC_LOW, 4, (u32)_base); \
comcerto_dbi_write_reg(_pp, PCIE_iATU_SRC_HIGH, 4, 0); \
comcerto_dbi_write_reg(_pp, PCIE_iATU_LIMIT, 4, (u32)_limit); \
comcerto_dbi_write_reg(_pp, PCIE_iATU_TRGT_LOW, 4, (u32)_target); \
comcerto_dbi_write_reg(_pp, PCIE_iATU_TRGT_HIGH, 4, (u32)0); \
comcerto_dbi_write_reg(_pp, PCIE_iATU_CTRL1, 4, (u32)_ctl1); \
comcerto_dbi_write_reg(_pp, PCIE_iATU_CTRL2, 4, (u32)(_ctl2 |iATU_CTRL2_ID_EN) ); \
}
#define PCIE_SETUP_iATU_OB_ENTRY( _pp, _view_port, _base, _limit, _ctl1, _ctl2, _target ) \
{\
comcerto_dbi_write_reg(_pp, PCIE_iATU_VIEW_PORT, 4, (u32)_view_port); \
comcerto_dbi_write_reg(_pp, PCIE_iATU_CTRL2, 4, 0); \
comcerto_dbi_write_reg(_pp, PCIE_iATU_SRC_LOW, 4, (u32)_base); \
comcerto_dbi_write_reg(_pp, PCIE_iATU_SRC_HIGH, 4, (u32)0); \
comcerto_dbi_write_reg(_pp, PCIE_iATU_LIMIT, 4, (u32)_limit); \
comcerto_dbi_write_reg(_pp, PCIE_iATU_TRGT_LOW, 4, (u32)_target); \
comcerto_dbi_write_reg(_pp, PCIE_iATU_TRGT_HIGH, 4, (u32)0); \
comcerto_dbi_write_reg(_pp, PCIE_iATU_CTRL1, 4, (u32)_ctl1); \
comcerto_dbi_write_reg(_pp, PCIE_iATU_CTRL2, 4, (u32)(_ctl2 |iATU_CTRL2_ID_EN) ); \
}
//#define MAX_LINK_UP_WAIT_JIFFIES 100
#define MAX_LINK_UP_WAIT_JIFFIES 0xfff
#define PCI_SLOT(d) (((d) >> 3) & 0x1f)
#define PCI_FUNC(d) (((d) >> 8) & 0x7)
#define GPIO_MISC_PIN_SELECT (GPIO_BASE + 0x60)
#define GPIO_63_32_PIN_OUTPUT (GPIO_BASE + 0xd0)
#define GPIO_63_32_PIN_OUTPUT_EN (GPIO_BASE + 0xd4)
/*** 0x9800_0000, 0x9900_0000 ***/
static unsigned long pcie_cnf_base_addr[NUM_PCIE_PORTS] =
{ COMCERTO_AXI_PCIe0_CFG_BASE, COMCERTO_AXI_PCIe1_CFG_BASE };
/*** 0xA000_0000, 0xB000_0000 ***/
static unsigned long pcie_remote_base_addr[NUM_PCIE_PORTS] =
{ COMCERTO_AXI_PCIe0_SLV_BASE, COMCERTO_AXI_PCIe1_SLV_BASE };
static struct pcie_port pcie_port[NUM_PCIE_PORTS];
static int initialized[NUM_PCIE_PORTS] = {0, 0};
static void __init pcie_port_init_rc(int port);
void pcie_wEnable (int enable)
{
int gpio_reg = GPIO_BASE + 0xd0;
unsigned long gpio_mask = 0x00006000;
unsigned int rdata, wdata;
rdata = readl(GPIO_63_32_PIN_OUTPUT_EN);
wdata = rdata | gpio_mask;
#ifdef PCIE_DEBUG_LOOPBACK
printf("pcie: enReg:0x%x 0x%x: 0x0000-6000 ! \n", GPIO_63_32_PIN_OUTPUT_EN, wdata);
#endif
writel(rdata, GPIO_63_32_PIN_OUTPUT_EN);
rdata = readl(gpio_reg);
wdata = enable ? rdata | gpio_mask : rdata & ~gpio_mask;
#ifdef PCIE_DEBUG_LOOPBACK
printf("pcie: W-46 & W-45 Reg:0x%x to get Data=0x%x ! \n", gpio_reg, wdata);
#endif
writel(wdata, GPIO_63_32_PIN_OUTPUT);
rdata = readl(GPIO_63_32_PIN_OUTPUT);
#ifdef PCIE_DEBUG_LOOPBACK
printf("pcie_wEnable GPIO-46-45:0x%x 0x%x:0x0000-6000 atEnd! \n",
GPIO_63_32_PIN_OUTPUT, rdata);
#endif
}
void pcie0_reset (int reset)
{
int gpio_reg = GPIO_BASE + 0xd0;
int misc_reg = GPIO_BASE + 0x60;
unsigned long misc_mask = 0x00000030;
unsigned long misc_gpio = 0x00000020;
unsigned long gpio_mask = 0x40000000;
unsigned int rdata, wdata;
rdata = readl(misc_reg);
#ifdef PCIE_DEBUG_LOOPBACK
printf("pcie0: select miscSel62 Reg:0x%x to read Data=0x%x ! \n", misc_reg, rdata);
#endif
rdata = readl(GPIO_MISC_PIN_SELECT);
rdata &= ~misc_mask;
rdata |= misc_gpio;
#ifdef PCIE_DEBUG_LOOPBACK
printf("pcie0: set miscSel62 Reg:0x%x to Data=0x%x ! \n", GPIO_MISC_PIN_SELECT, rdata);
#endif
writel(rdata, GPIO_MISC_PIN_SELECT);
rdata = readl(GPIO_63_32_PIN_OUTPUT_EN);
rdata |= gpio_mask;
#ifdef PCIE_DEBUG_LOOPBACK
printf("pcie0: Enable GPIO62_Reg:0x%x 0x%x ! \n", GPIO_63_32_PIN_OUTPUT_EN, rdata);
#endif
writel(rdata, GPIO_63_32_PIN_OUTPUT_EN);
rdata = readl(gpio_reg);
#ifdef PCIE_DEBUG_LOOPBACK
printf("pcie0: read GPIO-62:0x%x: 0x%x ! \n", GPIO_63_32_PIN_OUTPUT, rdata);
#endif
if (reset)
{
wdata = rdata & ~gpio_mask;
writel(wdata, GPIO_63_32_PIN_OUTPUT);
#ifdef PCIE_DEBUG_LOOPBACK
printf("pcie0: set GPIO-62:0x%x: 0x%x > 0x%x, LOW Reset ! \n",
GPIO_63_32_PIN_OUTPUT, rdata, wdata);
#endif
}
else
{
wdata = rdata | gpio_mask;
#ifdef PCIE_DEBUG_LOOPBACK
printf("pcie0: set GPIO-62:0x%x: 0x%x > 0x%x, HIGH Normal! \n",
GPIO_63_32_PIN_OUTPUT, rdata, wdata);
#endif
}
writel(wdata, GPIO_63_32_PIN_OUTPUT);
rdata = readl(GPIO_BASE + 0xd0);
#ifdef PCIE_DEBUG_LOOPBACK
printf("pcie0: GPIO-62: Data=0x%x, mask:0x4000-0000 at END ! \n", rdata);
#endif
}
void pcie1_reset (int reset)
{
int gpio_reg = GPIO_BASE + 0x00;
unsigned long gpio_mask = 0x08000000;
unsigned int rdata, wdata;
rdata = readl(gpio_reg);
#ifdef PCIE_DEBUG_LOOPBACK
printf("pcie1: read GPIO-27: 0x%x, Data=0x%x ! \n", gpio_reg, rdata);
#endif
// output enable
wdata = readl(gpio_reg + 4) | gpio_mask;
writel(wdata, gpio_reg + 4);
if (reset)
{
reg_rmw((GPIO_BASE+ 0x0),0x08000000, 0x0);
}
else
{
reg_rmw((GPIO_BASE+ 0x0),0x08000000, 0x08000000);
}
rdata = readl(gpio_reg);
#ifdef PCIE_DEBUG_LOOPBACK
printf("pcie1: GPIO-27: Data=0x%x, mask:0x0800-0000 at END! \n", rdata);
#endif
}
#define PCIE_PL_REG 0x700
#define PCIE_AFL0L1_REG (PCIE_PL_REG + 0xc)
#define PCIE_PLCTL_REG (PCIE_PL_REG + 0x10)
#define PCIE_SYMNUM (PCIE_PL_REG + 0x18)
#define PCIE_G2CTRL_REG (PCIE_PL_REG + 0x10c)
#define PCIE_CAP_BASE 0x70
#define PCIE_LCAP_REG (PCIE_CAP_BASE + 0x0C)
#define PCIE_LCNT2_REG (PCIE_CAP_BASE + 0x30)
#define PCIE_LOOP_DEST 0x70000000
static void pcie_loopback(int port)
{
struct pcie_port *pp = &pcie_port[port];
writel((readl(pp->base + PCIE_PLCTL_REG)) | 0x4, pp->base + PCIE_PLCTL_REG);
printf("Enabling Loopback: PCIE_PLCTL_REG 0x%x\n",readl(pp->base + PCIE_PLCTL_REG));
}
static void comcerto_pcie_LTSon (int port)
{
struct pcie_port *pp = &pcie_port[port];
int app_cfg5 = pp->app_base + pp->app_regs->cfg5;
unsigned int reg_data;
reg_data = readl(app_cfg5) & ~CFG5_LTSSM_ENABLE;
writel(reg_data, app_cfg5);
printf("%s : PCIe-%d app_cfg5 0x%x data=0x%x, CFG5_LTSSM: held ! \n",
__func__, port, app_cfg5, reg_data);
pcie_port_init_rc(port);
pcie_loopback(port);
reg_data = readl(app_cfg5) | (CFG5_APP_INIT_RST | CFG5_LTSSM_ENABLE);
writel(reg_data, app_cfg5);
printf("%s : PCIe-%d app_cfg5:0x%x data=0x%x LTSSM Enabling! \n",
__func__, port, app_cfg5, reg_data);
}
static void comcerto_serdes_set_polarity(int current_polarity)
{
struct serdes_regs_s *p_pcie_phy_reg_file_24 = &pcie_phy_reg_file_24[0];
printf ("%s: polarity=%d \n", __func__, current_polarity);
switch(current_polarity)
{
case 0:
p_pcie_phy_reg_file_24[0x73].val = 0x0;
p_pcie_phy_reg_file_24[0x75].val = 0x0;
break;
case 1:
p_pcie_phy_reg_file_24[0x73].val = 0x8;
p_pcie_phy_reg_file_24[0x75].val = 0x2;
break;
case 2:
p_pcie_phy_reg_file_24[0x73].val = 0x0;
p_pcie_phy_reg_file_24[0x75].val = 0x2;
break;
case 3:
p_pcie_phy_reg_file_24[0x73].val = 0x8;
p_pcie_phy_reg_file_24[0x75].val = 0x0;
break;
}
}
/**
* This function checks whether link is up or not.
* Returns true if link is up otherwise returns false.
* @param pp Pointer to PCIe Port control block.
*/
static int comcerto_pcie_link_up( struct pcie_port *pp )
{
int abase = pp->app_base;
int sts0 = pp->app_regs->sts0;
int link_reg = abase + sts0;
int link_stat;
unsigned long timeout = MAX_LINK_UP_WAIT_JIFFIES;
printf("comcerto_pcie_link_up: pcie_port->0x%x, abase=0x%x sts0=0x%x \n", link_reg, abase, sts0);
do {
if (readl( pp->app_base + pp->app_regs->sts0 ) & STS0_RDLH_LINK_UP) {
printf("PCIe Link up: Ok\n");
return 1;
}
mdelay(1);
} while (timeout--);
link_stat = readl( pp->app_base + pp->app_regs->sts0 );
printf("PCIe Link up: failed link_stat= 0x%x, STS0_RDLH_LINK_UP=0x%x \n",
link_stat, STS0_RDLH_LINK_UP);
return 0;
}
/**
* This function is used to read DBI registers.
*/
static void comcerto_dbi_read_reg(struct pcie_port *pp, int where, int size,
u32 *val)
{
u32 address;
address = (u32)pp->base + (where & ~0x3);
*val = readl(address);
if (size == 1)
*val = (*val >> (8 * (where & 3))) & 0xff;
else if (size == 2)
*val = (*val >> (8 * (where & 3))) & 0xffff;
}
/**
* This function is used to write into DBI registers.
*/
static void comcerto_dbi_write_reg(struct pcie_port *pp, int where, int size,
u32 val)
{
u32 address;
int pos, val1, mask = 0;
//printk("%s: start\n", __func__);
address = (u32)pp->base + (where & ~0x3);
pos = (where & 0x3) << 3;
if (size == 4)
val1 = val;
else
{
if (size == 2)
mask = 0xffff;
else if (size == 1)
mask = 0xff;
val1 = readl(address);
val1 = ( val1 & ~( mask << pos ) ) | ( (val & mask) << pos );
}
#ifdef PCIE_DEBUG_LOOPBACK
printk("%s: address: %08x, val: %08x\n", __func__, address, val1);
#endif
writel(val1, address);
//printk("%s: done\n", __func__);
}
static int comcerto_pcie_rd_conf(struct pcie_port *pp, int bus_nr,
u32 devfn, int where, int size, u32 *val)
{
u32 address;
u32 target_address = (u32)(bus_nr << 24) | (PCI_SLOT(devfn) << 19) | (PCI_FUNC(devfn) << 16);
//Initialize iATU
if (bus_nr != pp->root_bus_nr) {
/* Type1 configuration request */
PCIE_SETUP_iATU_OB_ENTRY( pp, iATU_ENTRY_CNF1, (u32)pp->cfg1_base,
((u32)(pp->cfg1_base + (iATU_CFG1_SIZE - 1))),
(AXI_OP_TYPE_CONFIG_RDRW_TYPE1 & iATU_CTRL1_TYPE_MASK),
0, target_address );
address = (u32)pp->cfg1_base |(where & 0xFFFC);
} else {
/* +0x0904: AXI_OP_TYPE_CONFIG_RDRW_TYPE0 = 4 */
PCIE_SETUP_iATU_OB_ENTRY( pp, iATU_ENTRY_CNF0, (u32)pp->cfg0_base,
((u32)(pp->cfg0_base + (iATU_CFG0_SIZE - 1))),
(AXI_OP_TYPE_CONFIG_RDRW_TYPE0 & iATU_CTRL1_TYPE_MASK),
0, target_address );
address = (u32)((pp->cfg0_base)|(where & 0xFFFC));
}
*val = readl(address);
printf("%s: root_bus-%d readl<address->%08x> = 0x%08x devfn=%d iATUtarget=0x%08x \n",
__func__, pp->root_bus_nr, address, *val, devfn, target_address);
if (size == 1)
*val = (*val >> (8 * (where & 3))) & 0xff;
else if (size == 2)
*val = (*val >> (8 * (where & 3))) & 0xffff;
return 0;
}
static int pcie_read_conf(struct pcie_port *pp, int bus_nr, u32 devfn, int where, int size, u32 *val)
{
int ret;
/* Make sure that link is up.
* Filter device numbers, unless it's a type1 access
*/
if ( (!pp->link_state)||
((bus_nr == pp->root_bus_nr) && (PCI_SLOT(devfn) > 0)) ) {
*val = 0xffffffff;
return -1;
}
BUG_ON (((where & 0x3) + size) > 4);
ret = comcerto_pcie_rd_conf(pp, bus_nr, devfn, where, size, val);
return ret;
}
static int comcerto_pcie_wr_conf(struct pcie_port *pp, int bus_nr,
u32 devfn, int where, int size, u32 val)
{
int ret = 0;
u32 address;
u32 target_address = (u32)(bus_nr << 24) | (PCI_SLOT(devfn) << 19) | (PCI_FUNC(devfn) << 16);
//Initialize iATU
if (bus_nr != pp->root_bus_nr) {
/* Type1 configuration request */
PCIE_SETUP_iATU_OB_ENTRY( pp, iATU_ENTRY_CNF1, (u32)pp->cfg1_base,
((u32)(pp->cfg1_base + (iATU_CFG1_SIZE - 1))),
(AXI_OP_TYPE_CONFIG_RDRW_TYPE1 & iATU_CTRL1_TYPE_MASK),
0, target_address );
address = (u32)pp->cfg1_base |(where & 0xFFFC);
} else {
/* Type0 configuration request */
PCIE_SETUP_iATU_OB_ENTRY( pp, iATU_ENTRY_CNF0, (u32)pp->cfg0_base,
((u32)(pp->cfg0_base + (iATU_CFG0_SIZE - 1))),
(AXI_OP_TYPE_CONFIG_RDRW_TYPE0 & iATU_CTRL1_TYPE_MASK),
0, target_address );
address = (u32)pp->cfg0_base |(where & 0xFFFC);
}
if (size == 4)
writel(val, address);
else if (size == 2)
writew(val, address + (where & 2));
else if (size == 1)
writeb(val, address + (where & 3));
else
ret = -1;
return ret;
}
static int pcie_write_conf(struct pcie_port *pp, int bus_nr, u32 devfn, int where, int size, u32 val)
{
int ret;
/* Make sure that link is up.
* Filter device numbers, unless it's a type1 access
*/
if ( (!pp->link_state)||
((bus_nr == pp->root_bus_nr) && (PCI_SLOT(devfn) > 0)) ) {
return -1;
}
BUG_ON (((where & 0x3) + size) > 4);
ret = comcerto_pcie_wr_conf(pp, bus_nr, devfn, where, size, val);
return ret;
}
static int pcie_read_subsysid(struct pcie_port *pp, u32 devfn, u32 *val)
{
unsigned int subid;
(void)comcerto_pcie_rd_conf (pp, pp->root_bus_nr, devfn, PCI_SUBSYS_ID, 4, val);
if(*val != 0xffffffff)
{
subid = *val;
printf("PCIe-%d: subSYS_VENDOR: 0x%04X subSYS_ID: 0x%04X !\n",
pp->root_bus_nr, (subid & 0x0000FFFF), ((subid >> 16) & 0xFFFF));
}
else
{
printf("PCIe-%d: SubSytem & Vendor IDs failed to access ? \n", pp->root_bus_nr);
return 1;
}
return 0;
}
/**********************************************************************************************/
static void __init pcie_port_init_rc(int port)
{
struct pcie_port *pp = &pcie_port[port];
#ifdef PCIE_DEBUG_LOOPBACK
printf("\n*>> %s: start pcie_port-%d base=0x%x \n", __func__, port, (unsigned int)pp->base);
printf(" >> pcie_port-%d base+cfg0=0x%x \n", port, pp->app_regs->cfg0);
#endif
writel(readl(pp->app_base + pp->app_regs->cfg0) | 0x08007FF0,
pp->app_base + pp->app_regs->cfg0);
#ifdef PCIE_DEBUG_LOOPBACK
printf(" >> pcie_port-%d base+cfg4=0x%x \n", port, pp->app_regs->cfg4);
#endif
writel(readl(pp->app_base + pp->app_regs->cfg4) | 0x00008000,
pp->app_base + pp->app_regs->cfg4);
#ifdef PCIE_DEBUG_LOOPBACK
printf(" >> pcie_port-%d base+PCIE_AFL0L1_REG at 0x70C synopsis dbi access \n", port);
#endif
writel((readl(pp->base + 0x70C) & ~(0x00ffff00))| 0x00F1F100, pp->base + 0x70C);
#ifdef PCIE_DEBUG_LOOPBACK
printf(" >> pcie_port-%d base+PCIE_G2CTRL_REG at 0x80C synopsis dbi access \n", port);
#endif
writel(readl(pp->base + 0x80C) & ~(0xff) | 0xF1, pp->base + 0x80C);
writel(readl(pp->base + 0x80C) | (1 << 17), pp->base + 0x80C);
#if 0
printf(" >> pcie_port-%d: iATU_IB_ENTRY View-0 MEM base=0 DDR *->0x%x mskSize=0x%x \n",
port, COMCERTO_AXI_DDR_BASE, INBOUND_ADDR_MASK);
{
PCIE_SETUP_iATU_IB_ENTRY( pp, 0,
0, INBOUND_ADDR_MASK, /* 0xfff_ffff */
0, 0, COMCERTO_AXI_DDR_BASE); /* 0x0000_0000 */
}
printf(" >> pcie_port-%d: iATU_OB_ENTRY View-0 MEM base=0x%x *->0x%x mskSize=0x%x \n",
port, iATU_GET_MEM_BASE(pp->remote_mem_baseaddr),
pp->remote_mem_baseaddr, iATU_MEM_SIZE - 1);
{
PCIE_SETUP_iATU_OB_ENTRY( pp, iATU_ENTRY_MEM,
iATU_GET_MEM_BASE(pp->remote_mem_baseaddr), iATU_MEM_SIZE - 1,
0, 0, pp->remote_mem_baseaddr );
}
printf(" >> pcie_port-%d: iATU_OB_ENTRY View-1 IO base=0x%x *->0x%x mskSize=0x%x \n",
port, iATU_GET_IO_BASE(pp->remote_mem_baseaddr),
iATU_GET_IO_BASE(pp->remote_mem_baseaddr), iATU_IO_SIZE - 1);
{
PCIE_SETUP_iATU_OB_ENTRY( pp, iATU_ENTRY_IO,
iATU_GET_IO_BASE(pp->remote_mem_baseaddr), iATU_IO_SIZE - 1,
(AXI_OP_TYPE_IO_RDRW & iATU_CTRL1_TYPE_MASK), 0,
iATU_GET_IO_BASE(pp->remote_mem_baseaddr) );
}
printf(" >> pcie_port-%d: iATU_MSG_ENTRY View-4 MSG base=0x%x *->0x%x mskSize=0x%x \n",
port, iATU_GET_MSG_BASE(pp->remote_mem_baseaddr),
iATU_GET_MSG_BASE(pp->remote_mem_baseaddr), iATU_MSG_SIZE - 1);
{
PCIE_SETUP_iATU_OB_ENTRY( pp, iATU_ENTRY_MSG,
iATU_GET_MSG_BASE(pp->remote_mem_baseaddr), iATU_MSG_SIZE - 1,
(AXI_OP_TYPE_MSG_REQ & iATU_CTRL1_TYPE_MASK), 0,
iATU_GET_MSG_BASE(pp->remote_mem_baseaddr) );
}
#else
//Register Initialization (MEM_SPACE_EN_Enable + BUS_MASTER_EN_Enable + CAP_LIST_Enable)
writel(0x00100006, pp->base + 0x4);
//Set iATU Registers (Outbound)
comcerto_dbi_write_reg(pp, PCIE_iATU_VIEW_PORT, 4, port);
comcerto_dbi_write_reg(pp, PCIE_iATU_SRC_LOW, 4, pcie_remote_base_addr[port]);
comcerto_dbi_write_reg(pp, PCIE_iATU_LIMIT, 4, pcie_remote_base_addr[port] + 0xFFFF);
comcerto_dbi_write_reg(pp, PCIE_iATU_TRGT_LOW, 4, pcie_remote_base_addr[port]);
comcerto_dbi_write_reg(pp, PCIE_iATU_CTRL1, 4, 0x0);
comcerto_dbi_write_reg(pp, PCIE_iATU_CTRL2, 4, 0x80000000);
//Set iATU Registers (Inbound))
comcerto_dbi_write_reg(pp, PCIE_iATU_VIEW_PORT, 4, 0x80000000 + port);
comcerto_dbi_write_reg(pp, PCIE_iATU_TRGT_LOW, 4, PCIE_LOOP_DEST);
comcerto_dbi_write_reg(pp, PCIE_iATU_CTRL1, 4, 0x0);
comcerto_dbi_write_reg(pp, PCIE_iATU_CTRL2, 4, 0xc0000000);
//Register Initialization (MEM_SPACE_EN_Enable + BUS_MASTER_EN_Enable + CAP_LIST_Enable)
writel(0x00100006, pp->base + 0x4);
printf("%s: MEM_SPACE_EN_Enable + BUS_MASTER_EN_Enable + CAP_LIST_Enable\n",__func__);
//writel(0xa0000000, pp->base + 0x10);
writel(pcie_remote_base_addr[port], pp->base + 0x10);
#endif
}
static int comcerto_pcie_init( struct pcie_port *pp, int nr)
{
int ctrl_reg;
if (nr >= NUM_PCIE_PORTS) {
printf("%s : Invalid PCIe port number\n", __func__);
return 1;
}
memset(pp, 0, sizeof(struct pcie_port));
pp->app_regs = &app_regs[nr];
pp->root_bus_nr = nr;
pp->base = pcie_cnf_base_addr[nr];
pp->app_base = (unsigned long)COMCERTO_PCIE_SATA_USB_CTRL_BASE;
pp->remote_mem_baseaddr = pcie_remote_base_addr[nr];
pp->cfg0_base = iATU_GET_CFG0_BASE(pp->remote_mem_baseaddr);
pp->cfg1_base = iATU_GET_CFG1_BASE(pp->remote_mem_baseaddr);
printf("%s : PCIe-%d remote_mem->0x%08x, cfg0_base->0x%08x cfg1_base->0x%08x \n",
__func__, nr, pp->remote_mem_baseaddr, pp->cfg0_base, pp->cfg1_base);
comcerto_serdes_set_polarity(0);
if (!nr) {
#ifdef PCIE_DEBUG_LOOPBACK
printf("%s PCIe-%d: releaseing AXI_RESET_2 & SERDES_RST_CNTRL\n", __func__, nr);
#endif
writel( readl( AXI_RESET_2 ) & ~PCIE0_AXI_RST, AXI_RESET_2 );
writel( readl( SERDES_RST_CNTRL ) & ~(SERDES0_RST), SERDES_RST_CNTRL );
/* Configure PCIe0 to Root complex mode */
writel( (readl(pp->app_base + pp->app_regs->cfg0) &
~DWC_CFG0_DEV_TYPE_MASK) | PCIE_PORT_MODE_RC,
pp->app_base + pp->app_regs->cfg0);
/* Enable clocks */
ctrl_reg = COMCERTO_SERDES_DWC_CFG_REG( 0, SD_PHY_CTRL3_REG_OFST );
#ifdef PCIE_DEBUG_LOOPBACK
printf("%s: PCIe0 CTRL3_reg->0x%x \n",__func__, ctrl_reg);
#endif
writel(0xFF3C, ctrl_reg);
ctrl_reg = COMCERTO_SERDES_DWC_CFG_REG( 1, SD_PHY_CTRL2_REG_OFST );
writel(readl(ctrl_reg) & ~0x3, ctrl_reg);
writel( readl( AXI_CLK_CNTRL_2 )| AXI_PCIE0_CLK_EN, AXI_CLK_CNTRL_2);
/* Put COMPONENT_SERDES_PCIe0: the PCIe0 SERDES controller in Normal state */
#ifdef PCIE_DEBUG_LOOPBACK
printf("%s PCIe-0: PCIe_SATA_RST_CNTRL->0x%x, mask=0x0000-0003 \n",
__func__, PCIe_SATA_RST_CNTRL);
#endif
writel(readl(PCIe_SATA_RST_CNTRL) & ~SERDES_PCIE0_RESET_BIT, PCIe_SATA_RST_CNTRL);
pp->port_mode = PCIE_PORT_MODE_RC;
printf("%s: PCIe-%d Set to PCIE_PORT_MODE_RC \n",__func__, nr);
}
else if (nr == (int)1)
{
#ifdef PCIE_DEBUG_LOOPBACK
printf("%s PCIe-%d: releasing AXI_RESET_2 & SERDES_RST_CNTRL\n", __func__, nr);
#endif
writel( readl( AXI_RESET_2 ) & ~PCIE1_AXI_RST, AXI_RESET_2 );
writel( readl( SERDES_RST_CNTRL ) & ~(SERDES1_RST), SERDES_RST_CNTRL );
/* Configure PCIe1 to Root complex mode */
writel( (readl(pp->app_base + pp->app_regs->cfg0) &
~DWC_CFG0_DEV_TYPE_MASK) | PCIE_PORT_MODE_RC,
pp->app_base + pp->app_regs->cfg0);
ctrl_reg = COMCERTO_SERDES_DWC_CFG_REG( 1, SD_PHY_CTRL3_REG_OFST );
#ifdef PCIE_DEBUG_LOOPBACK
printf("%s: PCIe1 CTRL3_reg->0x%x \n",__func__, ctrl_reg);
#endif
writel(0xFF3C, ctrl_reg);
ctrl_reg = COMCERTO_SERDES_DWC_CFG_REG( 1, SD_PHY_CTRL2_REG_OFST );
writel(readl(ctrl_reg) & ~0x3, ctrl_reg);
writel( readl( AXI_CLK_CNTRL_2 )| AXI_PCIE1_CLK_EN, AXI_CLK_CNTRL_2);
/* Put COMPONENT_SERDES_PCIe1: the PCIe1 SERDES controller in Normal state */
#ifdef PCIE_DEBUG_LOOPBACK
printf("%s PCIe1: PCIe_SATA_RST_CNTRL->0x%x, mask=0x0000-000c \n",
__func__, PCIe_SATA_RST_CNTRL);
#endif
writel(readl(PCIe_SATA_RST_CNTRL) & ~SERDES_PCIE1_RESET_BIT, PCIe_SATA_RST_CNTRL);
pp->port_mode = PCIE_PORT_MODE_RC;
printf("%s: PCIe-%d Set to PCIE_PORT_MODE_RC \n",__func__, nr);
}
else {
pp->port_mode = PCIE_PORT_MODE_NONE;
return 1;
}
//Serdes Initialization.
if( serdes_phy_init(nr, pcie_phy_reg_file_24,
sizeof(pcie_phy_reg_file_24) / sizeof(serdes_regs_t),
SD_DEV_TYPE_PCIE) )
{
pp->port_mode = PCIE_PORT_MODE_NONE;
pr_err("%s: Failed to initialize serdes (%d), set back to MODE_NONE ?\n", __func__, nr );
return 1;
}
printf("%s : PCIe-%d completed serdes_phy_init! \n", __func__, nr);
mdelay(3);
comcerto_pcie_LTSon (nr);
pp->link_state = comcerto_pcie_link_up( &pcie_port[nr] );
if (pp->link_state)
{
#ifdef PCIE_DEBUG_LOOPBACK
printf("%%%%%%%%%%%% %s : PCIe-%d LINKUP PASS %%%%%%%%%%%%%%\n", __func__, nr);
#endif
}
else
{
printf("!!!!!!!!!!! %s : PCIe-%d LINKUP FAIL !!!!!!!!!!!!!\n", __func__, nr);
return -1;
}
return 0;
}
u32 data_patterns[] = {0x11111111,0x22222222,0x33333333,0x44444444,0x55555555};
int comcerto_pcie_port_test (unsigned int pcie_host_nr)
{
u32 value;
struct pcie_port *pp;
unsigned int addr = PCI_VENDOR_ID;
unsigned int devfn = 0;
int loopback_stat = 0;
int i;
if (pcie_host_nr >= NUM_PCIE_PORTS) {
printf("%s : Invalid port number (%d)\n", __func__, pcie_host_nr);
return 1;
}
value = 0xffffffff;
printf("\nPCIe%d Root complex test:\n", pcie_host_nr);
pp = &pcie_port[pcie_host_nr];
if ( comcerto_pcie_init(pp, pcie_host_nr) ) {
printf("comcerto_pcie_init failed\n");
return 1;
}
/***
if (!initialized[pcie_host_nr])
{
if ( comcerto_pcie_init(pp, pcie_host_nr) ) {
printf("comcerto_pcie_init failed\n");
return 1;
}
initialized[pcie_host_nr] = 1;
}
***/
if ( pp->port_mode == PCIE_PORT_MODE_NONE ) {
printf("PCIe%d controller is not enabled.........!!!\n", pcie_host_nr);
return 1;
}
#if 0
printf(">>> PCIe-%d RComplex is enabled to read Device, devfn=%d ... \n", pcie_host_nr, devfn);
if ( ( pp->port_mode == PCIE_PORT_MODE_RC ) && ( pp->link_state ) )
{
pcie_read_conf(pp, pcie_host_nr, devfn, addr, 0x4, &value);
if(value != 0xffffffff)
{
printf("PCIe-%d: Device Vendor_ID: 0x%04X Device_ID: 0x%04X, PASSed! \n",
pcie_host_nr, (value & 0xFFFF), ((value >> 16) & 0xFFFF));
}
else
{
printf("PCIe Lane %d: Vendor Device Id not found for the device...TEST FAIL\n",
pcie_host_nr);
return 1;
}
unsigned int subsys_id;
int retcode = pcie_read_subsysid (pp, 0, &subsys_id);
if(retcode)
{
printf("PCIe-%d: SubSytem & Vendor IDs failed to access ? \n", pcie_host_nr);
return 1;
}
}
else
{
printf("PCIe-%d: RComplex and LINKDOWN !... TEST FAIL\n", pcie_host_nr);
return 1;
}
#else
//////Test the Loopback////////
//set the dest addr to 0
for (i = 0 ; i < ARRAY_SIZE(data_patterns) ; i++)
{
writel(0, PCIE_LOOP_DEST + i * 4);
}
//write the data to the PCIe mem space
for (i = 0 ; i < ARRAY_SIZE(data_patterns) ; i++)
{
writel(data_patterns[i], pp->remote_mem_baseaddr + i * 4);
}
//Verify the data in dest addr if it gets loopbacked
for (i = 0 ; i < ARRAY_SIZE(data_patterns) ; i++)
{
value = readl(PCIE_LOOP_DEST + i * 4);
if(value != data_patterns[i])
{
loopback_stat = -1;
printf("Expected value at addr 0x%x: 0x%x, but got value 0x%x\n",PCIE_LOOP_DEST + i * 4, data_patterns[i], value);
}
}
printf("PCIE%d Loopback Test Result : ", pcie_host_nr);
if(loopback_stat == -1)
printf("Loopback Failed\n");
else
printf("Loopback Passed\n");
#endif
return 0;
}
static int wEnable = 0;
int comcerto_pcie_rc_test (struct diags_test_param *p)
{
int rc0, rc1;
wEnable = 1;
pcie0_reset (wEnable);
pcie1_reset (wEnable);
printf("\n>>> PCIe toggle Reset <<<\n");
pcie0_reset ((int)0);
pcie1_reset ((int)0);
printf("\n>>> PCIe Normal & Wifi Enable = %d <<<\n", wEnable);
pcie_wEnable (wEnable);
rc0 = comcerto_pcie_port_test (0);
rc1 = comcerto_pcie_port_test (1);
return rc0 | rc1;
}
/*********************************************************************************/
int comcerto_pcie_ep_test (struct diags_test_param *p)
{
printf("\n PCIE endpoint diags is not yet supported ....\n");
return 0;
}
int comcerto_pcie_perf_test (struct diags_test_param *p)
{
printf("\n PCIE perf diags is not yet supported ....\n");
return 0;
}