* [PATCH] 4xx: Add check_link to struct ppc4xx_pciex_hwops
@ 2011-07-01 6:44 Tony Breeds
2011-07-12 17:40 ` Ayman El-Khashab
0 siblings, 1 reply; 6+ messages in thread
From: Tony Breeds @ 2011-07-01 6:44 UTC (permalink / raw)
To: LinuxPPC-dev, Benjamin Herrenschmidt; +Cc: Ayman El-Khashab
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>
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c
index 156aa7d..ad330fe 100644
--- a/arch/powerpc/sysdev/ppc4xx_pci.c
+++ b/arch/powerpc/sysdev/ppc4xx_pci.c
@@ -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)
{
@@ -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)
@@ -856,6 +919,7 @@ 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 =
@@ -863,6 +927,7 @@ 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)
@@ -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)
@@ -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)
@@ -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)
@@ -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 */
@@ -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)
@@ -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)
{
@@ -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;
@@ -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
@@ -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;
Yours Tony
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH] 4xx: Add check_link to struct ppc4xx_pciex_hwops
2011-07-01 6:44 [PATCH] 4xx: Add check_link to struct ppc4xx_pciex_hwops Tony Breeds
@ 2011-07-12 17:40 ` Ayman El-Khashab
2011-07-12 18:04 ` Josh Boyer
0 siblings, 1 reply; 6+ messages in thread
From: Ayman El-Khashab @ 2011-07-12 17:40 UTC (permalink / raw)
To: LinuxPPC-dev, Benjamin Herrenschmidt, Josh Boyer
On Fri, Jul 01, 2011 at 04:44:24PM +1000, Tony Breeds wrote:
> All current pcie controllers unconditionally use SDR to check the link and
> poll for reset.
I was able to apply this patch and then modify the 460SX to
work correctly, so I think it is fine. There is only 1
comment below. So how does one supply a patch atop another
patch?
Best,
Ayman
> +static int __init ppc4xx_pciex_port_reset_sdr(struct ppc4xx_pciex_port *port)
> +{
> + printk(KERN_INFO "PCIE%d: Checking link...\n",
> + port->index);
Its not a functional problem, but this printk belongs in the
check link if anywhere rather than the reset.
> +
> + /* 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;
> +}
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] 4xx: Add check_link to struct ppc4xx_pciex_hwops
2011-07-12 17:40 ` Ayman El-Khashab
@ 2011-07-12 18:04 ` Josh Boyer
2011-07-12 22:13 ` Ayman El-Khashab
2011-07-13 0:42 ` Tony Breeds
0 siblings, 2 replies; 6+ messages in thread
From: Josh Boyer @ 2011-07-12 18:04 UTC (permalink / raw)
To: Ayman El-Khashab; +Cc: LinuxPPC-dev
On Tue, Jul 12, 2011 at 12:40:07PM -0500, Ayman El-Khashab wrote:
>On Fri, Jul 01, 2011 at 04:44:24PM +1000, Tony Breeds wrote:
>> All current pcie controllers unconditionally use SDR to check the link and
>> poll for reset.
>
>I was able to apply this patch and then modify the 460SX to
>work correctly, so I think it is fine. There is only 1
>comment below. So how does one supply a patch atop another
>patch?
>
>Best,
>Ayman
>
>> +static int __init ppc4xx_pciex_port_reset_sdr(struct ppc4xx_pciex_port *port)
>> +{
>> + printk(KERN_INFO "PCIE%d: Checking link...\n",
>> + port->index);
>
>Its not a functional problem, but this printk belongs in the
>check link if anywhere rather than the reset.
I've got this queued in my tree locally. I can make that change before
I push it out.
josh
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] 4xx: Add check_link to struct ppc4xx_pciex_hwops
2011-07-12 18:04 ` Josh Boyer
@ 2011-07-12 22:13 ` Ayman El-Khashab
2011-07-13 0:41 ` Tony Breeds
2011-07-13 0:42 ` Tony Breeds
1 sibling, 1 reply; 6+ messages in thread
From: Ayman El-Khashab @ 2011-07-12 22:13 UTC (permalink / raw)
To: Josh Boyer; +Cc: LinuxPPC-dev
On Tue, Jul 12, 2011 at 02:04:04PM -0400, Josh Boyer wrote:
> On Tue, Jul 12, 2011 at 12:40:07PM -0500, Ayman El-Khashab wrote:
> >On Fri, Jul 01, 2011 at 04:44:24PM +1000, Tony Breeds wrote:
> >> All current pcie controllers unconditionally use SDR to check the link and
> >> poll for reset.
> >
> >I was able to apply this patch and then modify the 460SX to
> >work correctly, so I think it is fine. There is only 1
> >comment below. So how does one supply a patch atop another
> >patch?
> >
> >Best,
> >Ayman
> >
> >> +static int __init ppc4xx_pciex_port_reset_sdr(struct ppc4xx_pciex_port *port)
> >> +{
> >> + printk(KERN_INFO "PCIE%d: Checking link...\n",
> >> + port->index);
> >
> >Its not a functional problem, but this printk belongs in the
> >check link if anywhere rather than the reset.
>
> I've got this queued in my tree locally. I can make that change before
> I push it out.
>
Ok, so let me ask the following ... will it cause trouble if
I swap the sequence of the calls to the following in xxx_port_init
ppc4xx_pciex_port_init_mapping(...)
and
if (ppc4xx_pciex_hwops->check_link)...
The reason is that at least on the 460SX, the link check is
done via registers in the config space. But the init_mapping is
needed to setup some of the DCRs to make the config space work.
In my check_link, i map the config space do the link checks
and then unmap since a superset of the space could be mapped
later.
Thanks,
ayman
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] 4xx: Add check_link to struct ppc4xx_pciex_hwops
2011-07-12 22:13 ` Ayman El-Khashab
@ 2011-07-13 0:41 ` Tony Breeds
0 siblings, 0 replies; 6+ messages in thread
From: Tony Breeds @ 2011-07-13 0:41 UTC (permalink / raw)
To: Ayman El-Khashab; +Cc: LinuxPPC-dev, Josh Boyer
On Tue, Jul 12, 2011 at 05:13:38PM -0500, Ayman El-Khashab wrote:
> Ok, so let me ask the following ... will it cause trouble if
> I swap the sequence of the calls to the following in xxx_port_init
>
> ppc4xx_pciex_port_init_mapping(...)
>
> and
>
> if (ppc4xx_pciex_hwops->check_link)...
>
> The reason is that at least on the 460SX, the link check is
> done via registers in the config space. But the init_mapping is
> needed to setup some of the DCRs to make the config space work.
> In my check_link, i map the config space do the link checks
> and then unmap since a superset of the space could be mapped
> later.
This is also what I do. IIRC ppc4xx_pciex_port_init_mapping() required
things that are setup between the 2 calls.
The double Mapping is fugly but I think it should be safe.
Yours Tony
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] 4xx: Add check_link to struct ppc4xx_pciex_hwops
2011-07-12 18:04 ` Josh Boyer
2011-07-12 22:13 ` Ayman El-Khashab
@ 2011-07-13 0:42 ` Tony Breeds
1 sibling, 0 replies; 6+ messages in thread
From: Tony Breeds @ 2011-07-13 0:42 UTC (permalink / raw)
To: Josh Boyer; +Cc: Ayman El-Khashab, LinuxPPC-dev
On Tue, Jul 12, 2011 at 02:04:04PM -0400, Josh Boyer wrote:
> On Tue, Jul 12, 2011 at 12:40:07PM -0500, Ayman El-Khashab wrote:
> >On Fri, Jul 01, 2011 at 04:44:24PM +1000, Tony Breeds wrote:
> >> All current pcie controllers unconditionally use SDR to check the link and
> >> poll for reset.
> >
> >I was able to apply this patch and then modify the 460SX to
> >work correctly, so I think it is fine. There is only 1
> >comment below. So how does one supply a patch atop another
> >patch?
> >
> >Best,
> >Ayman
> >
> >> +static int __init ppc4xx_pciex_port_reset_sdr(struct ppc4xx_pciex_port *port)
> >> +{
> >> + printk(KERN_INFO "PCIE%d: Checking link...\n",
> >> + port->index);
> >
> >Its not a functional problem, but this printk belongs in the
> >check link if anywhere rather than the reset.
>
> I've got this queued in my tree locally. I can make that change before
> I push it out.
Thanks Josh. I really thought I'd fixed that before posting.
Yours Tony
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2011-07-13 0:42 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-07-01 6:44 [PATCH] 4xx: Add check_link to struct ppc4xx_pciex_hwops Tony Breeds
2011-07-12 17:40 ` Ayman El-Khashab
2011-07-12 18:04 ` Josh Boyer
2011-07-12 22:13 ` Ayman El-Khashab
2011-07-13 0:41 ` Tony Breeds
2011-07-13 0:42 ` Tony Breeds
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).