Skip to content

Commit

Permalink
powerpc/4xx: Add check_link to struct ppc4xx_pciex_hwops
Browse files Browse the repository at this point in the history
All current pcie controllers unconditionally use SDR to check the link and
poll for reset.  Refactor the code to include device reset in the
port_init_hw() op and add a new check_link() op.

This will make room fro new controllers that do not use SDR for these
operations.

Tested on 460ex.

Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
  • Loading branch information
Tony Breeds authored and Josh Boyer committed Jul 12, 2011
1 parent af9719c commit 112d1fe
Showing 1 changed file with 83 additions and 65 deletions.
148 changes: 83 additions & 65 deletions arch/powerpc/sysdev/ppc4xx_pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -650,12 +650,75 @@ struct ppc4xx_pciex_hwops
int (*core_init)(struct device_node *np);
int (*port_init_hw)(struct ppc4xx_pciex_port *port);
int (*setup_utl)(struct ppc4xx_pciex_port *port);
void (*check_link)(struct ppc4xx_pciex_port *port);
};

static struct ppc4xx_pciex_hwops *ppc4xx_pciex_hwops;

#ifdef CONFIG_44x

static int __init ppc4xx_pciex_wait_on_sdr(struct ppc4xx_pciex_port *port,
unsigned int sdr_offset,
unsigned int mask,
unsigned int value,
int timeout_ms)
{
u32 val;

while(timeout_ms--) {
val = mfdcri(SDR0, port->sdr_base + sdr_offset);
if ((val & mask) == value) {
pr_debug("PCIE%d: Wait on SDR %x success with tm %d (%08x)\n",
port->index, sdr_offset, timeout_ms, val);
return 0;
}
msleep(1);
}
return -1;
}

static int __init ppc4xx_pciex_port_reset_sdr(struct ppc4xx_pciex_port *port)
{
printk(KERN_INFO "PCIE%d: Checking link...\n",
port->index);

/* Wait for reset to complete */
if (ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS, 1 << 20, 0, 10)) {
printk(KERN_WARNING "PCIE%d: PGRST failed\n",
port->index);
return -1;
}
return 0;
}

static void __init ppc4xx_pciex_check_link_sdr(struct ppc4xx_pciex_port *port)
{
/* Check for card presence detect if supported, if not, just wait for
* link unconditionally.
*
* note that we don't fail if there is no link, we just filter out
* config space accesses. That way, it will be easier to implement
* hotplug later on.
*/
if (!port->has_ibpre ||
!ppc4xx_pciex_wait_on_sdr(port, PESDRn_LOOP,
1 << 28, 1 << 28, 100)) {
printk(KERN_INFO
"PCIE%d: Device detected, waiting for link...\n",
port->index);
if (ppc4xx_pciex_wait_on_sdr(port, PESDRn_LOOP,
0x1000, 0x1000, 2000))
printk(KERN_WARNING
"PCIE%d: Link up failed\n", port->index);
else {
printk(KERN_INFO
"PCIE%d: link is up !\n", port->index);
port->link = 1;
}
} else
printk(KERN_INFO "PCIE%d: No device detected.\n", port->index);
}

/* Check various reset bits of the 440SPe PCIe core */
static int __init ppc440spe_pciex_check_reset(struct device_node *np)
{
Expand Down Expand Up @@ -806,7 +869,7 @@ static int ppc440spe_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET,
(1 << 24) | (1 << 16), 1 << 12);

return 0;
return ppc4xx_pciex_port_reset_sdr(port);
}

static int ppc440speA_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
Expand Down Expand Up @@ -856,13 +919,15 @@ static struct ppc4xx_pciex_hwops ppc440speA_pcie_hwops __initdata =
.core_init = ppc440spe_pciex_core_init,
.port_init_hw = ppc440speA_pciex_init_port_hw,
.setup_utl = ppc440speA_pciex_init_utl,
.check_link = ppc4xx_pciex_check_link_sdr,
};

static struct ppc4xx_pciex_hwops ppc440speB_pcie_hwops __initdata =
{
.core_init = ppc440spe_pciex_core_init,
.port_init_hw = ppc440speB_pciex_init_port_hw,
.setup_utl = ppc440speB_pciex_init_utl,
.check_link = ppc4xx_pciex_check_link_sdr,
};

static int __init ppc460ex_pciex_core_init(struct device_node *np)
Expand Down Expand Up @@ -944,7 +1009,7 @@ static int ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)

port->has_ibpre = 1;

return 0;
return ppc4xx_pciex_port_reset_sdr(port);
}

static int ppc460ex_pciex_init_utl(struct ppc4xx_pciex_port *port)
Expand Down Expand Up @@ -972,6 +1037,7 @@ static struct ppc4xx_pciex_hwops ppc460ex_pcie_hwops __initdata =
.core_init = ppc460ex_pciex_core_init,
.port_init_hw = ppc460ex_pciex_init_port_hw,
.setup_utl = ppc460ex_pciex_init_utl,
.check_link = ppc4xx_pciex_check_link_sdr,
};

static int __init ppc460sx_pciex_core_init(struct device_node *np)
Expand Down Expand Up @@ -1075,7 +1141,7 @@ static int ppc460sx_pciex_init_port_hw(struct ppc4xx_pciex_port *port)

port->has_ibpre = 1;

return 0;
return ppc4xx_pciex_port_reset_sdr(port);
}

static int ppc460sx_pciex_init_utl(struct ppc4xx_pciex_port *port)
Expand All @@ -1089,6 +1155,7 @@ static struct ppc4xx_pciex_hwops ppc460sx_pcie_hwops __initdata = {
.core_init = ppc460sx_pciex_core_init,
.port_init_hw = ppc460sx_pciex_init_port_hw,
.setup_utl = ppc460sx_pciex_init_utl,
.check_link = ppc4xx_pciex_check_link_sdr,
};

#endif /* CONFIG_44x */
Expand Down Expand Up @@ -1154,7 +1221,7 @@ static int ppc405ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)

port->has_ibpre = 1;

return 0;
return ppc4xx_pciex_port_reset_sdr(port);
}

static int ppc405ex_pciex_init_utl(struct ppc4xx_pciex_port *port)
Expand Down Expand Up @@ -1183,11 +1250,11 @@ static struct ppc4xx_pciex_hwops ppc405ex_pcie_hwops __initdata =
.core_init = ppc405ex_pciex_core_init,
.port_init_hw = ppc405ex_pciex_init_port_hw,
.setup_utl = ppc405ex_pciex_init_utl,
.check_link = ppc4xx_pciex_check_link_sdr,
};

#endif /* CONFIG_40x */


/* Check that the core has been initied and if not, do it */
static int __init ppc4xx_pciex_check_core_init(struct device_node *np)
{
Expand Down Expand Up @@ -1261,26 +1328,6 @@ static void __init ppc4xx_pciex_port_init_mapping(struct ppc4xx_pciex_port *port
dcr_write(port->dcrs, DCRO_PEGPL_MSGMSK, 0);
}

static int __init ppc4xx_pciex_wait_on_sdr(struct ppc4xx_pciex_port *port,
unsigned int sdr_offset,
unsigned int mask,
unsigned int value,
int timeout_ms)
{
u32 val;

while(timeout_ms--) {
val = mfdcri(SDR0, port->sdr_base + sdr_offset);
if ((val & mask) == value) {
pr_debug("PCIE%d: Wait on SDR %x success with tm %d (%08x)\n",
port->index, sdr_offset, timeout_ms, val);
return 0;
}
msleep(1);
}
return -1;
}

static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port)
{
int rc = 0;
Expand All @@ -1291,40 +1338,8 @@ static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port)
if (rc != 0)
return rc;

printk(KERN_INFO "PCIE%d: Checking link...\n",
port->index);

/* Wait for reset to complete */
if (ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS, 1 << 20, 0, 10)) {
printk(KERN_WARNING "PCIE%d: PGRST failed\n",
port->index);
return -1;
}

/* Check for card presence detect if supported, if not, just wait for
* link unconditionally.
*
* note that we don't fail if there is no link, we just filter out
* config space accesses. That way, it will be easier to implement
* hotplug later on.
*/
if (!port->has_ibpre ||
!ppc4xx_pciex_wait_on_sdr(port, PESDRn_LOOP,
1 << 28, 1 << 28, 100)) {
printk(KERN_INFO
"PCIE%d: Device detected, waiting for link...\n",
port->index);
if (ppc4xx_pciex_wait_on_sdr(port, PESDRn_LOOP,
0x1000, 0x1000, 2000))
printk(KERN_WARNING
"PCIE%d: Link up failed\n", port->index);
else {
printk(KERN_INFO
"PCIE%d: link is up !\n", port->index);
port->link = 1;
}
} else
printk(KERN_INFO "PCIE%d: No device detected.\n", port->index);
if (ppc4xx_pciex_hwops->check_link)
ppc4xx_pciex_hwops->check_link(port);

/*
* Initialize mapping: disable all regions and configure
Expand All @@ -1347,14 +1362,17 @@ static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port)
/*
* Check for VC0 active and assert RDY.
*/
if (port->link &&
ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS,
1 << 16, 1 << 16, 5000)) {
printk(KERN_INFO "PCIE%d: VC0 not active\n", port->index);
port->link = 0;
if (port->sdr_base) {
if (port->link &&
ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS,
1 << 16, 1 << 16, 5000)) {
printk(KERN_INFO "PCIE%d: VC0 not active\n", port->index);
port->link = 0;
}

dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET, 0, 1 << 20);
}

dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET, 0, 1 << 20);
msleep(100);

return 0;
Expand Down

0 comments on commit 112d1fe

Please sign in to comment.