From: Grant Likely <hidden> Date: 2007-09-30 22:57:10
Here is a set of rework patches on the Xilinx SystemACE driver which ends
in the addition of an of_platform bus binding. The of_platform bus binding
is needed to use the driver from arch/powerpc. SystemACE is most commonly
used in Xilinx Virtex system (ppc405).
Jens, I'm hoping I can get these changes in for 2.6.24. Assuming nobody
raises any issues, can you please merge these into your tree?
Thanks,
g.
Grant Likely (6):
Add Xilinx SystemACE entry to maintainers
Sysace: Use the established platform bus api
Sysace: Move structure allocation from bus binding into common code
Sysace: minor rework and cleanup changes
Sysace: Move IRQ handler registration to occur after FSM is initialized
Sysace: Add of_platform_bus binding
MAINTAINERS | 7 ++
drivers/block/xsysace.c | 249 +++++++++++++++++++++++++++++++++++-----------
2 files changed, 196 insertions(+), 60 deletions(-)
--
Grant Likely, B.Sc. P.Eng.
Secret Lab Technologies Ltd.
From: Grant Likely <hidden> Date: 2007-09-30 22:57:37
From: Grant Likely <redacted>
Split the determination of device registers/irqs/etc from the actual
allocation and initialization of the device structure. This cleans
up the code a bit in preparation to add an of_platform bus binding
Signed-off-by: Grant Likely <redacted>
---
drivers/block/xsysace.c | 99 +++++++++++++++++++++++++++++------------------
1 files changed, 61 insertions(+), 38 deletions(-)
@@ -1033,7 +1033,7 @@ static int __devinit ace_setup(struct ace_device *ace)if(ace->irq!=NO_IRQ)free_irq(ace->irq,ace);err_ioremap:-printk(KERN_INFO"xsysace: error initializing device at 0x%lx\n",+dev_info(ace->dev,"xsysace: error initializing device at 0x%lx\n",ace->physaddr);return-ENOMEM;}
@@ -1056,68 +1056,91 @@ static void __devexit ace_teardown(struct ace_device *ace)iounmap(ace->baseaddr);}-/* ----------------------------------------------------------------------*PlatformBusSupport-*/--staticint__devinitace_probe(structplatform_device*dev)+staticint__devinit+ace_alloc(structdevice*dev,intid,unsignedlongphysaddr,+intirq,intbus_width){structace_device*ace;-inti;+intrc;+dev_dbg(dev,"ace_alloc(%p)\n",dev);-dev_dbg(&dev->dev,"ace_probe(%p)\n",dev);+if(!physaddr){+rc=-ENODEV;+gotoerr_noreg;+}-/*-*Allocatetheacedevicestructure-*/+/* Allocate and initialize the ace device structure */ace=kzalloc(sizeof(structace_device),GFP_KERNEL);-if(!ace)+if(!ace){+rc=-ENOMEM;gotoerr_alloc;--ace->dev=&dev->dev;-ace->id=dev->id;-ace->irq=NO_IRQ;--for(i=0;i<dev->num_resources;i++){-if(dev->resource[i].flags&IORESOURCE_MEM)-ace->physaddr=dev->resource[i].start;-if(dev->resource[i].flags&IORESOURCE_IRQ)-ace->irq=dev->resource[i].start;}-/* FIXME: Should get bus_width from the platform_device struct */-ace->bus_width=1;--platform_set_drvdata(dev,ace);+ace->dev=dev;+ace->id=id;+ace->physaddr=physaddr;+ace->irq=irq;+ace->bus_width=bus_width;-/* Call the bus-independant setup code */-if(ace_setup(ace)!=0)+/* Call the setup code */+if((rc=ace_setup(ace))!=0)gotoerr_setup;+dev_set_drvdata(dev,ace);return0;err_setup:-platform_set_drvdata(dev,NULL);+dev_set_drvdata(dev,NULL);kfree(ace);err_alloc:-printk(KERN_ERR"xsysace: could not initialize device\n");-return-ENOMEM;+err_noreg:+dev_err(dev,"could not initialize device, err=%i\n",rc);+returnrc;}-/*-*Platformbusremove()method-*/-staticint__devexitace_remove(structplatform_device*dev)+staticvoid__devexitace_free(structdevice*dev){-structace_device*ace=platform_get_drvdata(dev);-dev_dbg(&dev->dev,"ace_remove(%p)\n",dev);+structace_device*ace=dev_get_drvdata(dev);+dev_dbg(dev,"ace_free(%p)\n",dev);if(ace){ace_teardown(ace);-platform_set_drvdata(dev,NULL);+dev_set_drvdata(dev,NULL);kfree(ace);}+}++/* ---------------------------------------------------------------------+*PlatformBusSupport+*/++staticint__devinitace_probe(structplatform_device*dev)+{+unsignedlongphysaddr=0;+intbus_width=1;/* FIXME: should not be hard coded */+intid=dev->id;+intirq=NO_IRQ;+inti;++dev_dbg(&dev->dev,"ace_probe(%p)\n",dev);++for(i=0;i<dev->num_resources;i++){+if(dev->resource[i].flags&IORESOURCE_MEM)+physaddr=dev->resource[i].start;+if(dev->resource[i].flags&IORESOURCE_IRQ)+irq=dev->resource[i].start;+}++/* Call the bus-independant setup code */+returnace_alloc(&dev->dev,id,physaddr,irq,bus_width);+}+/*+*Platformbusremove()method+*/+staticint__devexitace_remove(structplatform_device*dev)+{+ace_free(&dev->dev);return0;}
From: Grant Likely <hidden> Date: 2007-09-30 22:57:55
From: Grant Likely <redacted>
The FSM needs to be initialized before it is safe to call the ISR
Signed-off-by: Grant Likely <redacted>
---
drivers/block/xsysace.c | 21 ++++++++++-----------
1 files changed, 10 insertions(+), 11 deletions(-)
@@ -949,15 +949,6 @@ static int __devinit ace_setup(struct ace_device *ace)if(!ace->baseaddr)gotoerr_ioremap;-if(ace->irq!=NO_IRQ){-rc=request_irq(ace->irq,ace_interrupt,0,"systemace",ace);-if(rc){-/* Failure - fall back to polled mode */-dev_err(ace->dev,"request_irq failed\n");-ace->irq=NO_IRQ;-}-}-/**Initializethestatemachinetaskletandstalltimer*/
@@ -1015,6 +1006,16 @@ static int __devinit ace_setup(struct ace_device *ace)val|=ACE_CTRL_DATABUFRDYIRQ|ACE_CTRL_ERRORIRQ;ace_out(ace,ACE_CTRL,val);+/* Now we can hook up the irq handler */+if(ace->irq!=NO_IRQ){+rc=request_irq(ace->irq,ace_interrupt,0,"systemace",ace);+if(rc){+/* Failure - fall back to polled mode */+dev_err(ace->dev,"request_irq failed\n");+ace->irq=NO_IRQ;+}+}+/* Print the identification */dev_info(ace->dev,"Xilinx SystemACE revision %i.%i.%i\n",(version>>12)&0xf,(version>>8)&0x0f,version&0xff);
@@ -1035,8 +1036,6 @@ static int __devinit ace_setup(struct ace_device *ace)blk_cleanup_queue(ace->queue);err_blk_initq:iounmap(ace->baseaddr);-if(ace->irq!=NO_IRQ)-free_irq(ace->irq,ace);err_ioremap:dev_info(ace->dev,"xsysace: error initializing device at 0x%lx\n",ace->physaddr);
From: Grant Likely <hidden> Date: 2007-09-30 22:58:18
From: Grant Likely <redacted>
The of_platform bus binding is needed to make the device driver usable
under arch/powerpc.
Signed-off-by: Grant Likely <redacted>
---
drivers/block/xsysace.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 89 insertions(+), 0 deletions(-)
@@ -1158,6 +1162,85 @@ static struct platform_driver ace_platform_driver = {};/* ---------------------------------------------------------------------+*OF_PlatformBusSupport+*/++#if defined(CONFIG_OF)+staticint__devinit+ace_of_probe(structof_device*op,conststructof_device_id*match)+{+structresourceres;+unsignedlongphysaddr;+constu32*id;+intirq,bus_width,rc;++dev_dbg(&op->dev,"ace_of_probe(%p, %p)\n",op,match);++/* device id */+id=of_get_property(op->node,"port-number",NULL);++/* physaddr */+rc=of_address_to_resource(op->node,0,&res);+if(rc){+dev_err(&op->dev,"invalid address\n");+returnrc;+}+physaddr=res.start;++/* irq */+irq=irq_of_parse_and_map(op->node,0);++/* bus width */+bus_width=ACE_BUS_WIDTH_16;+if(of_find_property(op->node,"8-bit",NULL))+bus_width=ACE_BUS_WIDTH_8;++/* Call the bus-independant setup code */+returnace_alloc(&op->dev,id?*id:0,physaddr,irq,bus_width);+}++staticint__devexitace_of_remove(structof_device*op)+{+ace_free(&op->dev);+return0;+}++/* Match table for of_platform binding */+staticstructof_device_id__devinitace_of_match[]={+{.compatible="xilinx,xsysace",},+{},+};+MODULE_DEVICE_TABLE(of,ace_of_match);++staticstructof_platform_driverace_of_driver={+.owner=THIS_MODULE,+.name="xsysace",+.match_table=ace_of_match,+.probe=ace_of_probe,+.remove=__devexit_p(ace_of_remove),+.driver={+.name="xsysace",+},+};++/* Registration helpers to keep the number of #ifdefs to a minimum */+staticinlineint__initace_of_register(void)+{+pr_debug("xsysace: registering OF binding\n");+returnof_register_platform_driver(&ace_of_driver);+}++staticinlinevoid__exitace_of_unregister(void)+{+of_unregister_platform_driver(&ace_of_driver);+}+#else /* CONFIG_OF */+/* CONFIG_OF not enabled; do nothing helpers */+staticinlineint__initace_of_register(void){return0;}+staticinlinevoid__exitace_of_unregister(void){}+#endif /* CONFIG_OF */++/* ---------------------------------------------------------------------*Moduleinit/exitroutines*/staticint__initace_init(void)
From: Grant Likely <hidden> Date: 2007-09-30 22:58:34
From: Grant Likely <redacted>
Miscellanious rework to the sysace driver; Not critical, but makes the
subsequent addition of the of_platform bus binding a wee bit cleaner
Signed-off-by: Grant Likely <redacted>
---
drivers/block/xsysace.c | 12 +++++++++---
1 files changed, 9 insertions(+), 3 deletions(-)
@@ -982,7 +987,7 @@ static int __devinit ace_setup(struct ace_device *ace)snprintf(ace->gd->disk_name,32,"xs%c",ace->id+'a');/* set bus width */-if(ace->bus_width==1){+if(ace->bus_width==ACE_BUS_WIDTH_16){/* 0x0101 should work regardless of endianess */ace_out_le16(ace,ACE_BUSMODE,0x0101);
@@ -1117,7 +1122,7 @@ static void __devexit ace_free(struct device *dev)staticint__devinitace_probe(structplatform_device*dev){unsignedlongphysaddr=0;-intbus_width=1;/* FIXME: should not be hard coded */+intbus_width=ACE_BUS_WIDTH_16;/* FIXME: should not be hard coded */intid=dev->id;intirq=NO_IRQ;inti;
From: Grant Likely <hidden> Date: 2007-09-30 22:59:14
From: Grant Likely <redacted>
SystemACE uses the platform bus binding, but it doesn't use the
platform bus API. Move to using the correct API for consistency
sake and future proofing against platform bus changes.
Signed-off-by: Grant Likely <redacted>
---
drivers/block/xsysace.c | 48 +++++++++++++++++++++++++++++------------------
1 files changed, 30 insertions(+), 18 deletions(-)
@@ -1075,7 +1074,7 @@ static int __devinit ace_probe(struct device *device)if(!ace)gotoerr_alloc;-ace->dev=device;+ace->dev=&dev->dev;ace->id=dev->id;ace->irq=NO_IRQ;
@@ -1089,7 +1088,7 @@ static int __devinit ace_probe(struct device *device)/* FIXME: Should get bus_width from the platform_device struct */ace->bus_width=1;-dev_set_drvdata(&dev->dev,ace);+platform_set_drvdata(dev,ace);/* Call the bus-independant setup code */if(ace_setup(ace)!=0)
@@ -1098,7 +1097,7 @@ static int __devinit ace_probe(struct device *device)return0;err_setup:-dev_set_drvdata(&dev->dev,NULL);+platform_set_drvdata(dev,NULL);kfree(ace);err_alloc:printk(KERN_ERR"xsysace: could not initialize device\n");
labels should be indented zero or one space, but not more.
scripts/Lindent does this. Originally, I *didn't* have my labels
indented. :-) Does Lindent need to be fixed?
Cheers,
g.
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195
labels should be indented zero or one space, but not more.
scripts/Lindent does this. Originally, I *didn't* have my labels
indented. :-) Does Lindent need to be fixed?
Seems so, if it idents labels.
Just send a fixup patch for that, I'll add your series to the block tree
for 2.6.24.
Cool, thanks Jens. I'll generate a patch to unindent the labels this afternoon.
Cheers,
g.
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195
From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: 2007-10-02 05:55:56
On Sun, 2007-09-30 at 16:57 -0600, Grant Likely wrote:
val |= ACE_CTRL_DATABUFRDYIRQ | ACE_CTRL_ERRORIRQ;
ace_out(ace, ACE_CTRL, val);
+ /* Now we can hook up the irq handler */
+ if (ace->irq != NO_IRQ) {
+ rc = request_irq(ace->irq, ace_interrupt, 0,
"systemace", ace);
+ if (rc) {
+ /* Failure - fall back to polled mode */
+ dev_err(ace->dev, "request_irq failed\n");
+ ace->irq = NO_IRQ;
+ }
+ }
+
I don't know the HW but from the above, it looks like you enable
interrupt emission on the HW before you register the handler, which is
wrong. You should make sure on the contrary that IRQs on the HW are
disabled until after you have registered a handler.
Only really a problem if you have shared interrupts but still...
Ben.
labels should be indented zero or one space, but not more.
scripts/Lindent does this. Originally, I *didn't* have my labels
indented. :-) Does Lindent need to be fixed?
Seems so, if it idents labels.
Just send a fixup patch for that, I'll add your series to the block tree
for 2.6.24.
It's actually better off living in the powerpc tree I think as it's
really about adding support for a new powerpc platform and somewhat
needs to sync with other things in there. Unless you really want the
whole thing in your tree :-)
Cheers
Ben.
labels should be indented zero or one space, but not more.
scripts/Lindent does this. Originally, I *didn't* have my labels
indented. :-) Does Lindent need to be fixed?
Seems so, if it idents labels.
Just send a fixup patch for that, I'll add your series to the block tree
for 2.6.24.
It's actually better off living in the powerpc tree I think as it's
really about adding support for a new powerpc platform and somewhat
needs to sync with other things in there. Unless you really want the
whole thing in your tree :-)
I already included it yesterday, it'll go up once 2.6.24 opens. Let me
know if you want me to rip it out, though.
--
Jens Axboe
From: Grant Likely <hidden> Date: 2007-10-02 13:52:24
On 10/2/07, Jens Axboe [off-list ref] wrote:
On Tue, Oct 02 2007, Benjamin Herrenschmidt wrote:
quoted
On Mon, 2007-10-01 at 13:59 +0200, Jens Axboe wrote:
quoted
Just send a fixup patch for that, I'll add your series to the block tree
for 2.6.24.
It's actually better off living in the powerpc tree I think as it's
really about adding support for a new powerpc platform and somewhat
needs to sync with other things in there. Unless you really want the
whole thing in your tree :-)
I already included it yesterday, it'll go up once 2.6.24 opens. Let me
know if you want me to rip it out, though.
No, it's safe. Nothing will break if one goes in before the other.
Please keep it in.
g.
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195
From: Grant Likely <hidden> Date: 2007-10-02 13:57:25
On 10/1/07, Benjamin Herrenschmidt [off-list ref] wrote:
On Sun, 2007-09-30 at 16:57 -0600, Grant Likely wrote:
quoted
val |= ACE_CTRL_DATABUFRDYIRQ | ACE_CTRL_ERRORIRQ;
ace_out(ace, ACE_CTRL, val);
+ /* Now we can hook up the irq handler */
+ if (ace->irq != NO_IRQ) {
+ rc = request_irq(ace->irq, ace_interrupt, 0,
"systemace", ace);
+ if (rc) {
+ /* Failure - fall back to polled mode */
+ dev_err(ace->dev, "request_irq failed\n");
+ ace->irq = NO_IRQ;
+ }
+ }
+
I don't know the HW but from the above, it looks like you enable
interrupt emission on the HW before you register the handler, which is
wrong. You should make sure on the contrary that IRQs on the HW are
disabled until after you have registered a handler.
Only really a problem if you have shared interrupts but still...
Yeah, you're right. Fortunately all current in-tree platforms which
use this do not have shared interrupts, but I'd like to be correct on
this.
I'll tidy this up and send a fixup patch.
Thanks,
g.
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195