diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2006-01-17 16:24:56 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-01-17 16:24:56 -0800 |
commit | f798688c84f02fc1a9906c55e0df434125c6f5a7 (patch) | |
tree | 5a315d8d4123aba5e166f6357243133de84d74a6 /driver | |
parent | d59834c175c575a67ac84f03777ea6bd35815022 (diff) | |
download | patches-f798688c84f02fc1a9906c55e0df434125c6f5a7.tar.gz |
deleted patches that have already been applied
Diffstat (limited to 'driver')
46 files changed, 0 insertions, 9189 deletions
diff --git a/driver/add-bttv-sub-bus_type-probe-and-remove-methods.patch b/driver/add-bttv-sub-bus_type-probe-and-remove-methods.patch deleted file mode 100644 index 436bb0c003329..0000000000000 --- a/driver/add-bttv-sub-bus_type-probe-and-remove-methods.patch +++ /dev/null @@ -1,114 +0,0 @@ -From rmk+greg=kroah.com@arm.linux.org.uk Fri Jan 6 03:42:47 2006 -From: Russell King <rmk@arm.linux.org.uk> -CC: Greg K-H <greg@kroah.com>, V4L <video4linux-list@redhat.com> -Subject: [CFT 3/3] Add bttv sub bus_type probe and remove methods -Date: Fri, 06 Jan 2006 11:42:03 +0000 -Message-ID: <20060106114059.13.32@flint.arm.linux.org.uk> - -Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - - ---- - drivers/media/dvb/bt8xx/dvb-bt8xx.c | 23 +++++++++++------------ - drivers/media/video/bttv-gpio.c | 24 ++++++++++++++++++++++-- - drivers/media/video/bttv.h | 2 ++ - 3 files changed, 35 insertions(+), 14 deletions(-) - ---- gregkh-2.6.orig/drivers/media/dvb/bt8xx/dvb-bt8xx.c -+++ gregkh-2.6/drivers/media/dvb/bt8xx/dvb-bt8xx.c -@@ -779,9 +779,8 @@ static int __init dvb_bt8xx_load_card(st - return 0; - } - --static int dvb_bt8xx_probe(struct device *dev) -+static int dvb_bt8xx_probe(struct bttv_sub_device *sub) - { -- struct bttv_sub_device *sub = to_bttv_sub_dev(dev); - struct dvb_bt8xx_card *card; - struct pci_dev* bttv_pci_dev; - int ret; -@@ -890,13 +889,13 @@ static int dvb_bt8xx_probe(struct device - return ret; - } - -- dev_set_drvdata(dev, card); -+ dev_set_drvdata(&sub->dev, card); - return 0; - } - --static int dvb_bt8xx_remove(struct device *dev) -+static int dvb_bt8xx_remove(struct bttv_sub_device *sub) - { -- struct dvb_bt8xx_card *card = dev_get_drvdata(dev); -+ struct dvb_bt8xx_card *card = dev_get_drvdata(&sub->dev); - - dprintk("dvb_bt8xx: unloading card%d\n", card->bttv_nr); - -@@ -919,14 +918,14 @@ static int dvb_bt8xx_remove(struct devic - static struct bttv_sub_driver driver = { - .drv = { - .name = "dvb-bt8xx", -- .probe = dvb_bt8xx_probe, -- .remove = dvb_bt8xx_remove, -- /* FIXME: -- * .shutdown = dvb_bt8xx_shutdown, -- * .suspend = dvb_bt8xx_suspend, -- * .resume = dvb_bt8xx_resume, -- */ - }, -+ .probe = dvb_bt8xx_probe, -+ .remove = dvb_bt8xx_remove, -+ /* FIXME: -+ * .shutdown = dvb_bt8xx_shutdown, -+ * .suspend = dvb_bt8xx_suspend, -+ * .resume = dvb_bt8xx_resume, -+ */ - }; - - static int __init dvb_bt8xx_init(void) ---- gregkh-2.6.orig/drivers/media/video/bttv-gpio.c -+++ gregkh-2.6/drivers/media/video/bttv-gpio.c -@@ -47,9 +47,29 @@ static int bttv_sub_bus_match(struct dev - return 0; - } - -+static int bttv_sub_probe(struct device *dev) -+{ -+ struct bttv_sub_device *sdev = to_bttv_sub_dev(dev); -+ struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver); -+ -+ return sub->probe ? sub->probe(sdev) : -ENODEV; -+} -+ -+static int bttv_sub_remove(struct device *dev) -+{ -+ struct bttv_sub_device *sdev = to_bttv_sub_dev(dev); -+ struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver); -+ -+ if (sub->remove) -+ sub->remove(sdev); -+ return 0; -+} -+ - struct bus_type bttv_sub_bus_type = { -- .name = "bttv-sub", -- .match = &bttv_sub_bus_match, -+ .name = "bttv-sub", -+ .match = &bttv_sub_bus_match, -+ .probe = bttv_sub_probe, -+ .remove = bttv_sub_remove, - }; - EXPORT_SYMBOL(bttv_sub_bus_type); - ---- gregkh-2.6.orig/drivers/media/video/bttv.h -+++ gregkh-2.6/drivers/media/video/bttv.h -@@ -365,6 +365,8 @@ struct bttv_sub_device { - struct bttv_sub_driver { - struct device_driver drv; - char wanted[BUS_ID_SIZE]; -+ int (*probe)(struct bttv_sub_device *sub); -+ void (*remove)(struct bttv_sub_device *sub); - void (*gpio_irq)(struct bttv_sub_device *sub); - }; - #define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv) diff --git a/driver/add-bus_type-probe-remove-shutdown-methods.patch b/driver/add-bus_type-probe-remove-shutdown-methods.patch deleted file mode 100644 index d46f6a99a048b..0000000000000 --- a/driver/add-bus_type-probe-remove-shutdown-methods.patch +++ /dev/null @@ -1,95 +0,0 @@ -From rmk+greg=kroah.com@arm.linux.org.uk Thu Jan 5 06:31:35 2006 -From: Russell King <rmk@arm.linux.org.uk> -CC: Greg K-H <greg@kroah.com> -Subject: [CFT 1/29] Add bus_type probe, remove, shutdown methods. -Date: Thu, 05 Jan 2006 14:29:51 +0000 -Message-ID: <20060105142951.13.01@flint.arm.linux.org.uk> - -Add bus_type probe, remove and shutdown methods to replace the -corresponding methods in struct device_driver. This matches -the way we handle the suspend/resume methods. - -Since the bus methods override the device_driver methods, warn -if a device driver is registered whose methods will not be -called. - -The long-term idea is to remove the device_driver methods entirely. - -Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/base/dd.c | 12 ++++++++++-- - drivers/base/driver.c | 5 +++++ - drivers/base/power/shutdown.c | 5 ++++- - include/linux/device.h | 3 +++ - 4 files changed, 22 insertions(+), 3 deletions(-) - ---- gregkh-2.6.orig/drivers/base/dd.c -+++ gregkh-2.6/drivers/base/dd.c -@@ -78,7 +78,13 @@ int driver_probe_device(struct device_dr - pr_debug("%s: Matched Device %s with Driver %s\n", - drv->bus->name, dev->bus_id, drv->name); - dev->driver = drv; -- if (drv->probe) { -+ if (dev->bus->probe) { -+ ret = dev->bus->probe(dev); -+ if (ret) { -+ dev->driver = NULL; -+ goto ProbeFailed; -+ } -+ } else if (drv->probe) { - ret = drv->probe(dev); - if (ret) { - dev->driver = NULL; -@@ -203,7 +209,9 @@ static void __device_release_driver(stru - sysfs_remove_link(&dev->kobj, "driver"); - klist_remove(&dev->knode_driver); - -- if (drv->remove) -+ if (dev->bus->remove) -+ dev->bus->remove(dev); -+ else if (drv->remove) - drv->remove(dev); - dev->driver = NULL; - put_driver(drv); ---- gregkh-2.6.orig/drivers/base/driver.c -+++ gregkh-2.6/drivers/base/driver.c -@@ -171,6 +171,11 @@ static void klist_devices_put(struct kli - */ - int driver_register(struct device_driver * drv) - { -+ if ((drv->bus->probe && drv->probe) || -+ (drv->bus->remove && drv->remove) || -+ (drv->bus->shutdown && drv->shutdown)) { -+ printk(KERN_WARNING "Driver '%s' needs updating - please use bus_type methods\n", drv->name); -+ } - klist_init(&drv->klist_devices, klist_devices_get, klist_devices_put); - init_completion(&drv->unloaded); - return bus_add_driver(drv); ---- gregkh-2.6.orig/drivers/base/power/shutdown.c -+++ gregkh-2.6/drivers/base/power/shutdown.c -@@ -40,7 +40,10 @@ void device_shutdown(void) - down_write(&devices_subsys.rwsem); - list_for_each_entry_reverse(dev, &devices_subsys.kset.list, - kobj.entry) { -- if (dev->driver && dev->driver->shutdown) { -+ if (dev->bus && dev->bus->shutdown) { -+ dev_dbg(dev, "shutdown\n"); -+ dev->bus->shutdown(dev); -+ } else if (dev->driver && dev->driver->shutdown) { - dev_dbg(dev, "shutdown\n"); - dev->driver->shutdown(dev); - } ---- gregkh-2.6.orig/include/linux/device.h -+++ gregkh-2.6/include/linux/device.h -@@ -49,6 +49,9 @@ struct bus_type { - int (*match)(struct device * dev, struct device_driver * drv); - int (*uevent)(struct device *dev, char **envp, - int num_envp, char *buffer, int buffer_size); -+ int (*probe)(struct device * dev); -+ int (*remove)(struct device * dev); -+ void (*shutdown)(struct device * dev); - int (*suspend)(struct device * dev, pm_message_t state); - int (*resume)(struct device * dev); - }; diff --git a/driver/add-ccwgroup_bus_type-probe-and-remove-methods.patch b/driver/add-ccwgroup_bus_type-probe-and-remove-methods.patch deleted file mode 100644 index ad44ae2dcbd09..0000000000000 --- a/driver/add-ccwgroup_bus_type-probe-and-remove-methods.patch +++ /dev/null @@ -1,53 +0,0 @@ -From rmk+greg=kroah.com@arm.linux.org.uk Thu Jan 5 06:43:22 2006 -From: Russell King <rmk@arm.linux.org.uk> -CC: Greg K-H <greg@kroah.com>, S390 <linux-390@vm.marist.edu> -Subject: [CFT 24/29] Add ccwgroup_bus_type probe and remove methods -Date: Thu, 05 Jan 2006 14:42:09 +0000 -Message-ID: <20060105142951.13.24@flint.arm.linux.org.uk> - -Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/s390/cio/ccwgroup.c | 16 +++++++++------- - 1 file changed, 9 insertions(+), 7 deletions(-) - ---- gregkh-2.6.orig/drivers/s390/cio/ccwgroup.c -+++ gregkh-2.6/drivers/s390/cio/ccwgroup.c -@@ -52,11 +52,7 @@ ccwgroup_uevent (struct device *dev, cha - return 0; - } - --static struct bus_type ccwgroup_bus_type = { -- .name = "ccwgroup", -- .match = ccwgroup_bus_match, -- .uevent = ccwgroup_uevent, --}; -+static struct bus_type ccwgroup_bus_type; - - static inline void - __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev) -@@ -389,6 +385,14 @@ ccwgroup_remove (struct device *dev) - return 0; - } - -+static struct bus_type ccwgroup_bus_type = { -+ .name = "ccwgroup", -+ .match = ccwgroup_bus_match, -+ .uevent = ccwgroup_uevent, -+ .probe = ccwgroup_probe, -+ .remove = ccwgroup_remove, -+}; -+ - int - ccwgroup_driver_register (struct ccwgroup_driver *cdriver) - { -@@ -396,8 +400,6 @@ ccwgroup_driver_register (struct ccwgrou - cdriver->driver = (struct device_driver) { - .bus = &ccwgroup_bus_type, - .name = cdriver->name, -- .probe = ccwgroup_probe, -- .remove = ccwgroup_remove, - }; - - return driver_register(&cdriver->driver); diff --git a/driver/add-css-ccw-_bus_type-probe-remove-shutdown-methods.patch b/driver/add-css-ccw-_bus_type-probe-remove-shutdown-methods.patch deleted file mode 100644 index f0a1fc69d7c14..0000000000000 --- a/driver/add-css-ccw-_bus_type-probe-remove-shutdown-methods.patch +++ /dev/null @@ -1,228 +0,0 @@ -From huckc@de.ibm.com Wed Jan 11 16:58:29 2006 -Date: Wed, 11 Jan 2006 10:56:22 +0100 -From: Cornelia Huck <huckc@de.ibm.com> -To: Cornelia Huck <cornelia.huck@gmail.com> -Cc: <schwidefsky@de.ibm.com>, Greg K-H <greg@kroah.com> -Subject: Add {css,ccw}_bus_type probe, remove, shutdown methods. -Message-ID: <20060111105622.7cba9de6@gondolin.boeblingen.de.ibm.com> - -The following patch converts css_bus_type and ccw_bus_type to use -the new bus_type methods. - -Signed-off-by: Cornelia Huck <huckc@de.ibm.com> -CC: Martin Schwidefsky <schwidefsky@de.ibm.com> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - - ---- - drivers/s390/cio/css.c | 36 +++++++++++++++++++++++++++++++-- - drivers/s390/cio/css.h | 4 +++ - drivers/s390/cio/device.c | 50 ++++++++++++++++++++++------------------------ - 3 files changed, 62 insertions(+), 28 deletions(-) - ---- gregkh-2.6.orig/drivers/s390/cio/css.c -+++ gregkh-2.6/drivers/s390/cio/css.c -@@ -542,9 +542,41 @@ css_bus_match (struct device *dev, struc - return 0; - } - -+static int -+css_probe (struct device *dev) -+{ -+ struct subchannel *sch; -+ -+ sch = to_subchannel(dev); -+ sch->driver = container_of (dev->driver, struct css_driver, drv); -+ return (sch->driver->probe ? sch->driver->probe(sch) : 0); -+} -+ -+static int -+css_remove (struct device *dev) -+{ -+ struct subchannel *sch; -+ -+ sch = to_subchannel(dev); -+ return (sch->driver->remove ? sch->driver->remove(sch) : 0); -+} -+ -+static void -+css_shutdown (struct device *dev) -+{ -+ struct subchannel *sch; -+ -+ sch = to_subchannel(dev); -+ if (sch->driver->shutdown) -+ sch->driver->shutdown(sch); -+} -+ - struct bus_type css_bus_type = { -- .name = "css", -- .match = &css_bus_match, -+ .name = "css", -+ .match = css_bus_match, -+ .probe = css_probe, -+ .remove = css_remove, -+ .shutdown = css_shutdown, - }; - - subsys_initcall(init_channel_subsystem); ---- gregkh-2.6.orig/drivers/s390/cio/css.h -+++ gregkh-2.6/drivers/s390/cio/css.h -@@ -115,6 +115,7 @@ struct ccw_device_private { - * Currently, we only care about I/O subchannels (type 0), these - * have a ccw_device connected to them. - */ -+struct subchannel; - struct css_driver { - unsigned int subchannel_type; - struct device_driver drv; -@@ -122,6 +123,9 @@ struct css_driver { - int (*notify)(struct device *, int); - void (*verify)(struct device *); - void (*termination)(struct device *); -+ int (*probe)(struct subchannel *); -+ int (*remove)(struct subchannel *); -+ void (*shutdown)(struct subchannel *); - }; - - /* ---- gregkh-2.6.orig/drivers/s390/cio/device.c -+++ gregkh-2.6/drivers/s390/cio/device.c -@@ -107,33 +107,29 @@ ccw_uevent (struct device *dev, char **e - return 0; - } - --struct bus_type ccw_bus_type = { -- .name = "ccw", -- .match = &ccw_bus_match, -- .uevent = &ccw_uevent, --}; -+struct bus_type ccw_bus_type; - --static int io_subchannel_probe (struct device *); --static int io_subchannel_remove (struct device *); -+static int io_subchannel_probe (struct subchannel *); -+static int io_subchannel_remove (struct subchannel *); - void io_subchannel_irq (struct device *); - static int io_subchannel_notify(struct device *, int); - static void io_subchannel_verify(struct device *); - static void io_subchannel_ioterm(struct device *); --static void io_subchannel_shutdown(struct device *); -+static void io_subchannel_shutdown(struct subchannel *); - - struct css_driver io_subchannel_driver = { - .subchannel_type = SUBCHANNEL_TYPE_IO, - .drv = { - .name = "io_subchannel", - .bus = &css_bus_type, -- .probe = &io_subchannel_probe, -- .remove = &io_subchannel_remove, -- .shutdown = &io_subchannel_shutdown, - }, - .irq = io_subchannel_irq, - .notify = io_subchannel_notify, - .verify = io_subchannel_verify, - .termination = io_subchannel_ioterm, -+ .probe = io_subchannel_probe, -+ .remove = io_subchannel_remove, -+ .shutdown = io_subchannel_shutdown, - }; - - struct workqueue_struct *ccw_device_work; -@@ -803,14 +799,12 @@ io_subchannel_recog(struct ccw_device *c - } - - static int --io_subchannel_probe (struct device *pdev) -+io_subchannel_probe (struct subchannel *sch) - { -- struct subchannel *sch; - struct ccw_device *cdev; - int rc; - unsigned long flags; - -- sch = to_subchannel(pdev); - if (sch->dev.driver_data) { - /* - * This subchannel already has an associated ccw_device. -@@ -846,7 +840,7 @@ io_subchannel_probe (struct device *pdev - memset(cdev->private, 0, sizeof(struct ccw_device_private)); - atomic_set(&cdev->private->onoff, 0); - cdev->dev = (struct device) { -- .parent = pdev, -+ .parent = &sch->dev, - .release = ccw_device_release, - }; - INIT_LIST_HEAD(&cdev->private->kick_work.entry); -@@ -859,7 +853,7 @@ io_subchannel_probe (struct device *pdev - return -ENODEV; - } - -- rc = io_subchannel_recog(cdev, to_subchannel(pdev)); -+ rc = io_subchannel_recog(cdev, sch); - if (rc) { - spin_lock_irqsave(&sch->lock, flags); - sch->dev.driver_data = NULL; -@@ -883,17 +877,17 @@ ccw_device_unregister(void *data) - } - - static int --io_subchannel_remove (struct device *dev) -+io_subchannel_remove (struct subchannel *sch) - { - struct ccw_device *cdev; - unsigned long flags; - -- if (!dev->driver_data) -+ if (!sch->dev.driver_data) - return 0; -- cdev = dev->driver_data; -+ cdev = sch->dev.driver_data; - /* Set ccw device to not operational and drop reference. */ - spin_lock_irqsave(cdev->ccwlock, flags); -- dev->driver_data = NULL; -+ sch->dev.driver_data = NULL; - cdev->private->state = DEV_STATE_NOT_OPER; - spin_unlock_irqrestore(cdev->ccwlock, flags); - /* -@@ -948,14 +942,12 @@ io_subchannel_ioterm(struct device *dev) - } - - static void --io_subchannel_shutdown(struct device *dev) -+io_subchannel_shutdown(struct subchannel *sch) - { -- struct subchannel *sch; - struct ccw_device *cdev; - int ret; - -- sch = to_subchannel(dev); -- cdev = dev->driver_data; -+ cdev = sch->dev.driver_data; - - if (cio_is_console(sch->schid)) - return; -@@ -1129,6 +1121,14 @@ ccw_device_remove (struct device *dev) - return 0; - } - -+struct bus_type ccw_bus_type = { -+ .name = "ccw", -+ .match = ccw_bus_match, -+ .uevent = ccw_uevent, -+ .probe = ccw_device_probe, -+ .remove = ccw_device_remove, -+}; -+ - int - ccw_driver_register (struct ccw_driver *cdriver) - { -@@ -1136,8 +1136,6 @@ ccw_driver_register (struct ccw_driver * - - drv->bus = &ccw_bus_type; - drv->name = cdriver->name; -- drv->probe = ccw_device_probe; -- drv->remove = ccw_device_remove; - - return driver_register(drv); - } diff --git a/driver/add-dio_bus_type-probe-and-remove-methods.patch b/driver/add-dio_bus_type-probe-and-remove-methods.patch deleted file mode 100644 index 75678a73db761..0000000000000 --- a/driver/add-dio_bus_type-probe-and-remove-methods.patch +++ /dev/null @@ -1,34 +0,0 @@ -From rmk+greg=kroah.com@arm.linux.org.uk Thu Jan 5 06:42:39 2006 -From: Russell King <rmk@arm.linux.org.uk> -CC: Greg K-H <greg@kroah.com> -Subject: [CFT 15/29] Add dio_bus_type probe and remove methods -Date: Thu, 05 Jan 2006 14:37:18 +0000 -Message-ID: <20060105142951.13.15@flint.arm.linux.org.uk> - -Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/dio/dio-driver.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- gregkh-2.6.orig/drivers/dio/dio-driver.c -+++ gregkh-2.6/drivers/dio/dio-driver.c -@@ -83,7 +83,6 @@ int dio_register_driver(struct dio_drive - /* initialize common driver fields */ - drv->driver.name = drv->name; - drv->driver.bus = &dio_bus_type; -- drv->driver.probe = dio_device_probe; - - /* register with core */ - count = driver_register(&drv->driver); -@@ -145,7 +144,8 @@ static int dio_bus_match(struct device * - - struct bus_type dio_bus_type = { - .name = "dio", -- .match = dio_bus_match -+ .match = dio_bus_match, -+ .probe = dio_device_probe, - }; - - diff --git a/driver/add-ecard_bus_type-probe-remove-shutdown-methods.patch b/driver/add-ecard_bus_type-probe-remove-shutdown-methods.patch deleted file mode 100644 index a47da3be0956e..0000000000000 --- a/driver/add-ecard_bus_type-probe-remove-shutdown-methods.patch +++ /dev/null @@ -1,51 +0,0 @@ -From rmk+greg=kroah.com@arm.linux.org.uk Thu Jan 5 06:31:53 2006 -From: Russell King <rmk@arm.linux.org.uk> -CC: Greg K-H <greg@kroah.com> -Subject: [CFT 3/29] Add ecard_bus_type probe/remove/shutdown methods -Date: Thu, 05 Jan 2006 14:30:57 +0000 -Message-ID: <20060105142951.13.03@flint.arm.linux.org.uk> - -Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - arch/arm/kernel/ecard.c | 14 ++++++++------ - 1 file changed, 8 insertions(+), 6 deletions(-) - ---- gregkh-2.6.orig/arch/arm/kernel/ecard.c -+++ gregkh-2.6/arch/arm/kernel/ecard.c -@@ -1147,9 +1147,11 @@ static void ecard_drv_shutdown(struct de - struct ecard_driver *drv = ECARD_DRV(dev->driver); - struct ecard_request req; - -- if (drv->shutdown) -- drv->shutdown(ec); -- ecard_release(ec); -+ if (dev->driver) { -+ if (drv->shutdown) -+ drv->shutdown(ec); -+ ecard_release(ec); -+ } - - /* - * If this card has a loader, call the reset handler. -@@ -1164,9 +1166,6 @@ static void ecard_drv_shutdown(struct de - int ecard_register_driver(struct ecard_driver *drv) - { - drv->drv.bus = &ecard_bus_type; -- drv->drv.probe = ecard_drv_probe; -- drv->drv.remove = ecard_drv_remove; -- drv->drv.shutdown = ecard_drv_shutdown; - - return driver_register(&drv->drv); - } -@@ -1195,6 +1194,9 @@ struct bus_type ecard_bus_type = { - .name = "ecard", - .dev_attrs = ecard_dev_attrs, - .match = ecard_match, -+ .probe = ecard_drv_probe, -+ .remove = ecard_drv_remove, -+ .shutdown = ecard_drv_shutdown, - }; - - static int ecard_bus_init(void) diff --git a/driver/add-gameport-bus_type-probe-and-remove-methods.patch b/driver/add-gameport-bus_type-probe-and-remove-methods.patch deleted file mode 100644 index e37a68978572b..0000000000000 --- a/driver/add-gameport-bus_type-probe-and-remove-methods.patch +++ /dev/null @@ -1,45 +0,0 @@ -From rmk+greg=kroah.com@arm.linux.org.uk Thu Jan 5 06:42:51 2006 -From: Russell King <rmk@arm.linux.org.uk> -CC: Greg K-H <greg@kroah.com>, INPUT <linux-input@atrey.karlin.mff.cuni.cz> -Subject: [CFT 17/29] Add gameport bus_type probe and remove methods -Date: Thu, 05 Jan 2006 14:38:22 +0000 -Message-ID: <20060105142951.13.17@flint.arm.linux.org.uk> - -Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/input/gameport/gameport.c | 12 +++++++----- - 1 file changed, 7 insertions(+), 5 deletions(-) - ---- gregkh-2.6.orig/drivers/input/gameport/gameport.c -+++ gregkh-2.6/drivers/input/gameport/gameport.c -@@ -50,9 +50,7 @@ static DECLARE_MUTEX(gameport_sem); - - static LIST_HEAD(gameport_list); - --static struct bus_type gameport_bus = { -- .name = "gameport", --}; -+static struct bus_type gameport_bus; - - static void gameport_add_port(struct gameport *gameport); - static void gameport_destroy_port(struct gameport *gameport); -@@ -703,11 +701,15 @@ static int gameport_driver_remove(struct - return 0; - } - -+static struct bus_type gameport_bus = { -+ .name = "gameport", -+ .probe = gameport_driver_probe, -+ .remove = gameport_driver_remove, -+}; -+ - void __gameport_register_driver(struct gameport_driver *drv, struct module *owner) - { - drv->driver.bus = &gameport_bus; -- drv->driver.probe = gameport_driver_probe; -- drv->driver.remove = gameport_driver_remove; - gameport_queue_event(drv, owner, GAMEPORT_REGISTER_DRIVER); - } - diff --git a/driver/add-i2c_bus_type-probe-and-remove-methods.patch b/driver/add-i2c_bus_type-probe-and-remove-methods.patch deleted file mode 100644 index a3b736312e432..0000000000000 --- a/driver/add-i2c_bus_type-probe-and-remove-methods.patch +++ /dev/null @@ -1,64 +0,0 @@ -From rmk+greg=kroah.com@arm.linux.org.uk Thu Jan 5 06:42:43 2006 -From: Russell King <rmk@arm.linux.org.uk> -CC: Greg K-H <greg@kroah.com>, I2C <lm-sensors@lm-sensors.org> -Subject: [CFT 16/29] Add i2c_bus_type probe and remove methods -Date: Thu, 05 Jan 2006 14:37:50 +0000 -Message-ID: <20060105142951.13.16@flint.arm.linux.org.uk> - -Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/i2c/i2c-core.c | 20 +++++++++----------- - 1 file changed, 9 insertions(+), 11 deletions(-) - ---- gregkh-2.6.orig/drivers/i2c/i2c-core.c -+++ gregkh-2.6/drivers/i2c/i2c-core.c -@@ -63,13 +63,6 @@ static int i2c_bus_resume(struct device - return rc; - } - --struct bus_type i2c_bus_type = { -- .name = "i2c", -- .match = i2c_device_match, -- .suspend = i2c_bus_suspend, -- .resume = i2c_bus_resume, --}; -- - static int i2c_device_probe(struct device *dev) - { - return -ENODEV; -@@ -80,6 +73,15 @@ static int i2c_device_remove(struct devi - return 0; - } - -+struct bus_type i2c_bus_type = { -+ .name = "i2c", -+ .match = i2c_device_match, -+ .probe = i2c_device_probe, -+ .remove = i2c_device_remove, -+ .suspend = i2c_bus_suspend, -+ .resume = i2c_bus_resume, -+}; -+ - void i2c_adapter_dev_release(struct device *dev) - { - struct i2c_adapter *adap = dev_to_i2c_adapter(dev); -@@ -90,8 +92,6 @@ struct device_driver i2c_adapter_driver - .owner = THIS_MODULE, - .name = "i2c_adapter", - .bus = &i2c_bus_type, -- .probe = i2c_device_probe, -- .remove = i2c_device_remove, - }; - - static void i2c_adapter_class_dev_release(struct class_device *dev) -@@ -294,8 +294,6 @@ int i2c_register_driver(struct module *o - /* add the driver to the list of i2c drivers in the driver core */ - driver->driver.owner = owner; - driver->driver.bus = &i2c_bus_type; -- driver->driver.probe = i2c_device_probe; -- driver->driver.remove = i2c_device_remove; - - res = driver_register(&driver->driver); - if (res) diff --git a/driver/add-ide_bus_type-probe-and-remove-methods.patch b/driver/add-ide_bus_type-probe-and-remove-methods.patch deleted file mode 100644 index c5b2ec674b067..0000000000000 --- a/driver/add-ide_bus_type-probe-and-remove-methods.patch +++ /dev/null @@ -1,323 +0,0 @@ -From rmk+greg=kroah.com@arm.linux.org.uk Fri Jan 6 03:42:40 2006 -From: Russell King <rmk@arm.linux.org.uk> -CC: Greg K-H <greg@kroah.com>, IDE <linux-ide@vger.kernel.org> -Subject: [CFT 1/3] Add ide_bus_type probe and remove methods -Date: Fri, 06 Jan 2006 11:41:00 +0000 -Message-ID: <20060106114059.13.30@flint.arm.linux.org.uk> - -Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - - ---- - drivers/ide/ide-cd.c | 14 +++++--------- - drivers/ide/ide-disk.c | 22 ++++++++-------------- - drivers/ide/ide-floppy.c | 14 +++++--------- - drivers/ide/ide-tape.c | 18 +++++++----------- - drivers/ide/ide.c | 31 +++++++++++++++++++++++++++++++ - include/linux/ide.h | 5 +++++ - 6 files changed, 61 insertions(+), 43 deletions(-) - ---- gregkh-2.6.orig/drivers/ide/ide-cd.c -+++ gregkh-2.6/drivers/ide/ide-cd.c -@@ -3256,9 +3256,8 @@ sector_t ide_cdrom_capacity (ide_drive_t - } - #endif - --static int ide_cd_remove(struct device *dev) -+static void ide_cd_remove(ide_drive_t *drive) - { -- ide_drive_t *drive = to_ide_device(dev); - struct cdrom_info *info = drive->driver_data; - - ide_unregister_subdriver(drive, info->driver); -@@ -3266,8 +3265,6 @@ static int ide_cd_remove(struct device * - del_gendisk(info->disk); - - ide_cd_put(info); -- -- return 0; - } - - static void ide_cd_release(struct kref *kref) -@@ -3291,7 +3288,7 @@ static void ide_cd_release(struct kref * - kfree(info); - } - --static int ide_cd_probe(struct device *); -+static int ide_cd_probe(ide_drive_t *); - - #ifdef CONFIG_PROC_FS - static int proc_idecd_read_capacity -@@ -3317,9 +3314,9 @@ static ide_driver_t ide_cdrom_driver = { - .owner = THIS_MODULE, - .name = "ide-cdrom", - .bus = &ide_bus_type, -- .probe = ide_cd_probe, -- .remove = ide_cd_remove, - }, -+ .probe = ide_cd_probe, -+ .remove = ide_cd_remove, - .version = IDECD_VERSION, - .media = ide_cdrom, - .supports_dsc_overlap = 1, -@@ -3413,9 +3410,8 @@ static char *ignore = NULL; - module_param(ignore, charp, 0400); - MODULE_DESCRIPTION("ATAPI CD-ROM Driver"); - --static int ide_cd_probe(struct device *dev) -+static int ide_cd_probe(ide_drive_t *drive) - { -- ide_drive_t *drive = to_ide_device(dev); - struct cdrom_info *info; - struct gendisk *g; - struct request_sense sense; ---- gregkh-2.6.orig/drivers/ide/ide-disk.c -+++ gregkh-2.6/drivers/ide/ide-disk.c -@@ -997,9 +997,8 @@ static void ide_cacheflush_p(ide_drive_t - printk(KERN_INFO "%s: wcache flush failed!\n", drive->name); - } - --static int ide_disk_remove(struct device *dev) -+static void ide_disk_remove(ide_drive_t *drive) - { -- ide_drive_t *drive = to_ide_device(dev); - struct ide_disk_obj *idkp = drive->driver_data; - struct gendisk *g = idkp->disk; - -@@ -1010,8 +1009,6 @@ static int ide_disk_remove(struct device - ide_cacheflush_p(drive); - - ide_disk_put(idkp); -- -- return 0; - } - - static void ide_disk_release(struct kref *kref) -@@ -1027,12 +1024,10 @@ static void ide_disk_release(struct kref - kfree(idkp); - } - --static int ide_disk_probe(struct device *dev); -+static int ide_disk_probe(ide_drive_t *drive); - --static void ide_device_shutdown(struct device *dev) -+static void ide_device_shutdown(ide_drive_t *drive) - { -- ide_drive_t *drive = container_of(dev, ide_drive_t, gendev); -- - #ifdef CONFIG_ALPHA - /* On Alpha, halt(8) doesn't actually turn the machine off, - it puts you into the sort of firmware monitor. Typically, -@@ -1054,7 +1049,7 @@ static void ide_device_shutdown(struct d - } - - printk("Shutdown: %s\n", drive->name); -- dev->bus->suspend(dev, PMSG_SUSPEND); -+ drive->gendev.bus->suspend(&drive->gendev, PMSG_SUSPEND); - } - - static ide_driver_t idedisk_driver = { -@@ -1062,10 +1057,10 @@ static ide_driver_t idedisk_driver = { - .owner = THIS_MODULE, - .name = "ide-disk", - .bus = &ide_bus_type, -- .probe = ide_disk_probe, -- .remove = ide_disk_remove, -- .shutdown = ide_device_shutdown, - }, -+ .probe = ide_disk_probe, -+ .remove = ide_disk_remove, -+ .shutdown = ide_device_shutdown, - .version = IDEDISK_VERSION, - .media = ide_disk, - .supports_dsc_overlap = 0, -@@ -1182,9 +1177,8 @@ static struct block_device_operations id - - MODULE_DESCRIPTION("ATA DISK Driver"); - --static int ide_disk_probe(struct device *dev) -+static int ide_disk_probe(ide_drive_t *drive) - { -- ide_drive_t *drive = to_ide_device(dev); - struct ide_disk_obj *idkp; - struct gendisk *g; - ---- gregkh-2.6.orig/drivers/ide/ide-floppy.c -+++ gregkh-2.6/drivers/ide/ide-floppy.c -@@ -1871,9 +1871,8 @@ static void idefloppy_setup (ide_drive_t - idefloppy_add_settings(drive); - } - --static int ide_floppy_remove(struct device *dev) -+static void ide_floppy_remove(ide_drive_t *drive) - { -- ide_drive_t *drive = to_ide_device(dev); - idefloppy_floppy_t *floppy = drive->driver_data; - struct gendisk *g = floppy->disk; - -@@ -1882,8 +1881,6 @@ static int ide_floppy_remove(struct devi - del_gendisk(g); - - ide_floppy_put(floppy); -- -- return 0; - } - - static void ide_floppy_release(struct kref *kref) -@@ -1922,16 +1919,16 @@ static ide_proc_entry_t idefloppy_proc[] - - #endif /* CONFIG_PROC_FS */ - --static int ide_floppy_probe(struct device *); -+static int ide_floppy_probe(ide_drive_t *); - - static ide_driver_t idefloppy_driver = { - .gen_driver = { - .owner = THIS_MODULE, - .name = "ide-floppy", - .bus = &ide_bus_type, -- .probe = ide_floppy_probe, -- .remove = ide_floppy_remove, - }, -+ .probe = ide_floppy_probe, -+ .remove = ide_floppy_remove, - .version = IDEFLOPPY_VERSION, - .media = ide_floppy, - .supports_dsc_overlap = 0, -@@ -2136,9 +2133,8 @@ static struct block_device_operations id - .revalidate_disk= idefloppy_revalidate_disk - }; - --static int ide_floppy_probe(struct device *dev) -+static int ide_floppy_probe(ide_drive_t *drive) - { -- ide_drive_t *drive = to_ide_device(dev); - idefloppy_floppy_t *floppy; - struct gendisk *g; - ---- gregkh-2.6.orig/drivers/ide/ide-tape.c -+++ gregkh-2.6/drivers/ide/ide-tape.c -@@ -4682,9 +4682,8 @@ static void idetape_setup (ide_drive_t * - idetape_add_settings(drive); - } - --static int ide_tape_remove(struct device *dev) -+static void ide_tape_remove(ide_drive_t *drive) - { -- ide_drive_t *drive = to_ide_device(dev); - idetape_tape_t *tape = drive->driver_data; - - ide_unregister_subdriver(drive, tape->driver); -@@ -4692,8 +4691,6 @@ static int ide_tape_remove(struct device - ide_unregister_region(tape->disk); - - ide_tape_put(tape); -- -- return 0; - } - - static void ide_tape_release(struct kref *kref) -@@ -4745,16 +4742,16 @@ static ide_proc_entry_t idetape_proc[] = - - #endif - --static int ide_tape_probe(struct device *); -+static int ide_tape_probe(ide_drive_t *); - - static ide_driver_t idetape_driver = { - .gen_driver = { - .owner = THIS_MODULE, - .name = "ide-tape", - .bus = &ide_bus_type, -- .probe = ide_tape_probe, -- .remove = ide_tape_remove, - }, -+ .probe = ide_tape_probe, -+ .remove = ide_tape_remove, - .version = IDETAPE_VERSION, - .media = ide_tape, - .supports_dsc_overlap = 1, -@@ -4825,9 +4822,8 @@ static struct block_device_operations id - .ioctl = idetape_ioctl, - }; - --static int ide_tape_probe(struct device *dev) -+static int ide_tape_probe(ide_drive_t *drive) - { -- ide_drive_t *drive = to_ide_device(dev); - idetape_tape_t *tape; - struct gendisk *g; - int minor; -@@ -4883,9 +4879,9 @@ static int ide_tape_probe(struct device - idetape_setup(drive, tape, minor); - - class_device_create(idetape_sysfs_class, NULL, -- MKDEV(IDETAPE_MAJOR, minor), dev, "%s", tape->name); -+ MKDEV(IDETAPE_MAJOR, minor), &drive->gendev, "%s", tape->name); - class_device_create(idetape_sysfs_class, NULL, -- MKDEV(IDETAPE_MAJOR, minor + 128), dev, "n%s", tape->name); -+ MKDEV(IDETAPE_MAJOR, minor + 128), &drive->gendev, "n%s", tape->name); - - devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor), - S_IFCHR | S_IRUGO | S_IWUGO, ---- gregkh-2.6.orig/drivers/ide/ide.c -+++ gregkh-2.6/drivers/ide/ide.c -@@ -1949,10 +1949,41 @@ static int ide_uevent(struct device *dev - return 0; - } - -+static int generic_ide_probe(struct device *dev) -+{ -+ ide_drive_t *drive = to_ide_device(dev); -+ ide_driver_t *drv = to_ide_driver(dev->driver); -+ -+ return drv->probe ? drv->probe(drive) : -ENODEV; -+} -+ -+static int generic_ide_remove(struct device *dev) -+{ -+ ide_drive_t *drive = to_ide_device(dev); -+ ide_driver_t *drv = to_ide_driver(dev->driver); -+ -+ if (drv->remove) -+ drv->remove(drive); -+ -+ return 0; -+} -+ -+static void generic_ide_shutdown(struct device *dev) -+{ -+ ide_drive_t *drive = to_ide_device(dev); -+ ide_driver_t *drv = to_ide_driver(dev->driver); -+ -+ if (dev->driver && drv->shutdown) -+ drv->shutdown(drive); -+} -+ - struct bus_type ide_bus_type = { - .name = "ide", - .match = ide_bus_match, - .uevent = ide_uevent, -+ .probe = generic_ide_probe, -+ .remove = generic_ide_remove, -+ .shutdown = generic_ide_shutdown, - .dev_attrs = ide_dev_attrs, - .suspend = generic_ide_suspend, - .resume = generic_ide_resume, ---- gregkh-2.6.orig/include/linux/ide.h -+++ gregkh-2.6/include/linux/ide.h -@@ -983,8 +983,13 @@ typedef struct ide_driver_s { - ide_startstop_t (*abort)(ide_drive_t *, struct request *rq); - ide_proc_entry_t *proc; - struct device_driver gen_driver; -+ int (*probe)(ide_drive_t *); -+ void (*remove)(ide_drive_t *); -+ void (*shutdown)(ide_drive_t *); - } ide_driver_t; - -+#define to_ide_driver(drv) container_of(drv, ide_driver_t, gen_driver) -+ - int generic_ide_ioctl(ide_drive_t *, struct file *, struct block_device *, unsigned, unsigned long); - - /* diff --git a/driver/add-locomo-bus_type-probe-remove-methods.patch b/driver/add-locomo-bus_type-probe-remove-methods.patch deleted file mode 100644 index 53cee7d77c21e..0000000000000 --- a/driver/add-locomo-bus_type-probe-remove-methods.patch +++ /dev/null @@ -1,34 +0,0 @@ -From rmk+greg=kroah.com@arm.linux.org.uk Thu Jan 5 06:37:08 2006 -From: Russell King <rmk@arm.linux.org.uk> -CC: Greg K-H <greg@kroah.com>, Richard Purdie <rpurdie@rpsys.net> -Subject: [CFT 7/29] Add locomo bus_type probe/remove methods -Date: Thu, 05 Jan 2006 14:33:04 +0000 -Message-ID: <20060105142951.13.07@flint.arm.linux.org.uk> - -Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> -Signed-off-by: Richard Purdie <rpurdie@rpsys.net> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - arch/arm/common/locomo.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- gregkh-2.6.orig/arch/arm/common/locomo.c -+++ gregkh-2.6/arch/arm/common/locomo.c -@@ -1103,14 +1103,14 @@ static int locomo_bus_remove(struct devi - struct bus_type locomo_bus_type = { - .name = "locomo-bus", - .match = locomo_match, -+ .probe = locomo_bus_probe, -+ .remove = locomo_bus_remove, - .suspend = locomo_bus_suspend, - .resume = locomo_bus_resume, - }; - - int locomo_driver_register(struct locomo_driver *driver) - { -- driver->drv.probe = locomo_bus_probe; -- driver->drv.remove = locomo_bus_remove; - driver->drv.bus = &locomo_bus_type; - return driver_register(&driver->drv); - } diff --git a/driver/add-logic-module-bus_type-probe-remove-methods.patch b/driver/add-logic-module-bus_type-probe-remove-methods.patch deleted file mode 100644 index 40422071dc36b..0000000000000 --- a/driver/add-logic-module-bus_type-probe-remove-methods.patch +++ /dev/null @@ -1,72 +0,0 @@ -From rmk+greg=kroah.com@arm.linux.org.uk Thu Jan 5 06:37:10 2006 -From: Russell King <rmk@arm.linux.org.uk> -CC: Greg K-H <greg@kroah.com> -Subject: [CFT 8/29] Add logic module bus_type probe/remove methods -Date: Thu, 05 Jan 2006 14:33:35 +0000 -Message-ID: <20060105142951.13.08@flint.arm.linux.org.uk> - -Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - arch/arm/mach-integrator/lm.c | 36 ++++++++++++++++++------------------ - 1 file changed, 18 insertions(+), 18 deletions(-) - ---- gregkh-2.6.orig/arch/arm/mach-integrator/lm.c -+++ gregkh-2.6/arch/arm/mach-integrator/lm.c -@@ -22,20 +22,6 @@ static int lm_match(struct device *dev, - return 1; - } - --static struct bus_type lm_bustype = { -- .name = "logicmodule", -- .match = lm_match, --// .suspend = lm_suspend, --// .resume = lm_resume, --}; -- --static int __init lm_init(void) --{ -- return bus_register(&lm_bustype); --} -- --postcore_initcall(lm_init); -- - static int lm_bus_probe(struct device *dev) - { - struct lm_device *lmdev = to_lm_device(dev); -@@ -49,16 +35,30 @@ static int lm_bus_remove(struct device * - struct lm_device *lmdev = to_lm_device(dev); - struct lm_driver *lmdrv = to_lm_driver(dev->driver); - -- lmdrv->remove(lmdev); -+ if (lmdrv->remove) -+ lmdrv->remove(lmdev); - return 0; - } - -+static struct bus_type lm_bustype = { -+ .name = "logicmodule", -+ .match = lm_match, -+ .probe = lm_bus_probe, -+ .remove = lm_bus_remove, -+// .suspend = lm_bus_suspend, -+// .resume = lm_bus_resume, -+}; -+ -+static int __init lm_init(void) -+{ -+ return bus_register(&lm_bustype); -+} -+ -+postcore_initcall(lm_init); -+ - int lm_driver_register(struct lm_driver *drv) - { - drv->drv.bus = &lm_bustype; -- drv->drv.probe = lm_bus_probe; -- drv->drv.remove = lm_bus_remove; -- - return driver_register(&drv->drv); - } - diff --git a/driver/add-macio_bus_type-probe-and-remove-methods.patch b/driver/add-macio_bus_type-probe-and-remove-methods.patch deleted file mode 100644 index 190296ecc8b73..0000000000000 --- a/driver/add-macio_bus_type-probe-and-remove-methods.patch +++ /dev/null @@ -1,37 +0,0 @@ -From rmk+greg=kroah.com@arm.linux.org.uk Thu Jan 5 06:42:59 2006 -From: Russell King <rmk@arm.linux.org.uk> -CC: Greg K-H <greg@kroah.com>, MAC <linuxppc-dev@ozlabs.org> -Subject: [CFT 19/29] Add macio_bus_type probe and remove methods -Date: Thu, 05 Jan 2006 14:39:24 +0000 -Message-ID: <20060105142951.13.19@flint.arm.linux.org.uk> - -Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> -Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/macintosh/macio_asic.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- gregkh-2.6.orig/drivers/macintosh/macio_asic.c -+++ gregkh-2.6/drivers/macintosh/macio_asic.c -@@ -211,6 +211,9 @@ struct bus_type macio_bus_type = { - .name = "macio", - .match = macio_bus_match, - .uevent = macio_uevent, -+ .probe = macio_device_probe, -+ .remove = macio_device_remove, -+ .shutdown = macio_device_shutdown, - .suspend = macio_device_suspend, - .resume = macio_device_resume, - .dev_attrs = macio_dev_attrs, -@@ -528,9 +531,6 @@ int macio_register_driver(struct macio_d - /* initialize common driver fields */ - drv->driver.name = drv->name; - drv->driver.bus = &macio_bus_type; -- drv->driver.probe = macio_device_probe; -- drv->driver.remove = macio_device_remove; -- drv->driver.shutdown = macio_device_shutdown; - - /* register with core */ - count = driver_register(&drv->driver); diff --git a/driver/add-mcp-bus_type-probe-and-remove-methods.patch b/driver/add-mcp-bus_type-probe-and-remove-methods.patch deleted file mode 100644 index 4e41bc94e83c8..0000000000000 --- a/driver/add-mcp-bus_type-probe-and-remove-methods.patch +++ /dev/null @@ -1,34 +0,0 @@ -From rmk+greg=kroah.com@arm.linux.org.uk Thu Jan 5 06:43:06 2006 -From: Russell King <rmk@arm.linux.org.uk> -CC: Greg K-H <greg@kroah.com> -Subject: [CFT 20/29] Add MCP bus_type probe and remove methods -Date: Thu, 05 Jan 2006 14:39:56 +0000 -Message-ID: <20060105142951.13.20@flint.arm.linux.org.uk> - -Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/mfd/mcp-core.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- gregkh-2.6.orig/drivers/mfd/mcp-core.c -+++ gregkh-2.6/drivers/mfd/mcp-core.c -@@ -77,6 +77,8 @@ static int mcp_bus_resume(struct device - static struct bus_type mcp_bus_type = { - .name = "mcp", - .match = mcp_bus_match, -+ .probe = mcp_bus_probe, -+ .remove = mcp_bus_remove, - .suspend = mcp_bus_suspend, - .resume = mcp_bus_resume, - }; -@@ -227,8 +229,6 @@ EXPORT_SYMBOL(mcp_host_unregister); - int mcp_driver_register(struct mcp_driver *mcpdrv) - { - mcpdrv->drv.bus = &mcp_bus_type; -- mcpdrv->drv.probe = mcp_bus_probe; -- mcpdrv->drv.remove = mcp_bus_remove; - return driver_register(&mcpdrv->drv); - } - EXPORT_SYMBOL(mcp_driver_register); diff --git a/driver/add-mmc_bus_type-probe-and-remove-methods.patch b/driver/add-mmc_bus_type-probe-and-remove-methods.patch deleted file mode 100644 index ac9575da92393..0000000000000 --- a/driver/add-mmc_bus_type-probe-and-remove-methods.patch +++ /dev/null @@ -1,70 +0,0 @@ -From rmk+greg=kroah.com@arm.linux.org.uk Thu Jan 5 06:43:10 2006 -From: Russell King <rmk@arm.linux.org.uk> -CC: Greg K-H <greg@kroah.com> -Subject: [CFT 21/29] Add mmc_bus_type probe and remove methods -Date: Thu, 05 Jan 2006 14:40:27 +0000 -Message-ID: <20060105142951.13.21@flint.arm.linux.org.uk> - -Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/mmc/mmc_sysfs.c | 26 ++++++++++++-------------- - 1 file changed, 12 insertions(+), 14 deletions(-) - ---- gregkh-2.6.orig/drivers/mmc/mmc_sysfs.c -+++ gregkh-2.6/drivers/mmc/mmc_sysfs.c -@@ -136,17 +136,7 @@ static int mmc_bus_resume(struct device - return ret; - } - --static struct bus_type mmc_bus_type = { -- .name = "mmc", -- .dev_attrs = mmc_dev_attrs, -- .match = mmc_bus_match, -- .uevent = mmc_bus_uevent, -- .suspend = mmc_bus_suspend, -- .resume = mmc_bus_resume, --}; -- -- --static int mmc_drv_probe(struct device *dev) -+static int mmc_bus_probe(struct device *dev) - { - struct mmc_driver *drv = to_mmc_driver(dev->driver); - struct mmc_card *card = dev_to_mmc_card(dev); -@@ -154,7 +144,7 @@ static int mmc_drv_probe(struct device * - return drv->probe(card); - } - --static int mmc_drv_remove(struct device *dev) -+static int mmc_bus_remove(struct device *dev) - { - struct mmc_driver *drv = to_mmc_driver(dev->driver); - struct mmc_card *card = dev_to_mmc_card(dev); -@@ -164,6 +154,16 @@ static int mmc_drv_remove(struct device - return 0; - } - -+static struct bus_type mmc_bus_type = { -+ .name = "mmc", -+ .dev_attrs = mmc_dev_attrs, -+ .match = mmc_bus_match, -+ .uevent = mmc_bus_uevent, -+ .probe = mmc_bus_probe, -+ .remove = mmc_bus_remove, -+ .suspend = mmc_bus_suspend, -+ .resume = mmc_bus_resume, -+}; - - /** - * mmc_register_driver - register a media driver -@@ -172,8 +172,6 @@ static int mmc_drv_remove(struct device - int mmc_register_driver(struct mmc_driver *drv) - { - drv->drv.bus = &mmc_bus_type; -- drv->drv.probe = mmc_drv_probe; -- drv->drv.remove = mmc_drv_remove; - return driver_register(&drv->drv); - } - diff --git a/driver/add-ocp_bus_type-probe-and-remove-methods.patch b/driver/add-ocp_bus_type-probe-and-remove-methods.patch deleted file mode 100644 index 4a86bfa2751a0..0000000000000 --- a/driver/add-ocp_bus_type-probe-and-remove-methods.patch +++ /dev/null @@ -1,34 +0,0 @@ -From rmk+greg=kroah.com@arm.linux.org.uk Thu Jan 5 06:37:18 2006 -From: Russell King <rmk@arm.linux.org.uk> -CC: Greg K-H <greg@kroah.com>, Matt Porter <mporter@kernel.crashing.org> -Subject: [CFT 11/29] Add ocp_bus_type probe and remove methods -Date: Thu, 05 Jan 2006 14:35:09 +0000 -Message-ID: <20060105142951.13.11@flint.arm.linux.org.uk> - -Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - arch/ppc/syslib/ocp.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- gregkh-2.6.orig/arch/ppc/syslib/ocp.c -+++ gregkh-2.6/arch/ppc/syslib/ocp.c -@@ -189,6 +189,8 @@ ocp_device_resume(struct device *dev) - struct bus_type ocp_bus_type = { - .name = "ocp", - .match = ocp_device_match, -+ .probe = ocp_driver_probe, -+ .remove = ocp_driver_remove, - .suspend = ocp_device_suspend, - .resume = ocp_device_resume, - }; -@@ -210,8 +212,6 @@ ocp_register_driver(struct ocp_driver *d - /* initialize common driver fields */ - drv->driver.name = drv->name; - drv->driver.bus = &ocp_bus_type; -- drv->driver.probe = ocp_device_probe; -- drv->driver.remove = ocp_device_remove; - - /* register with core */ - return driver_register(&drv->driver); diff --git a/driver/add-of_platform_bus_type-probe-and-remove-methods.patch b/driver/add-of_platform_bus_type-probe-and-remove-methods.patch deleted file mode 100644 index 8ce5ece8285bf..0000000000000 --- a/driver/add-of_platform_bus_type-probe-and-remove-methods.patch +++ /dev/null @@ -1,34 +0,0 @@ -From rmk+greg=kroah.com@arm.linux.org.uk Thu Jan 5 06:37:22 2006 -From: Russell King <rmk@arm.linux.org.uk> -CC: Greg K-H <greg@kroah.com>, PowerPC <linuxppc-embedded@ozlabs.org> -Subject: [CFT 13/29] Add of_platform_bus_type probe and remove methods -Date: Thu, 05 Jan 2006 14:36:16 +0000 -Message-ID: <20060105142951.13.13@flint.arm.linux.org.uk> - -Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - arch/powerpc/kernel/of_device.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- gregkh-2.6.orig/arch/powerpc/kernel/of_device.c -+++ gregkh-2.6/arch/powerpc/kernel/of_device.c -@@ -132,6 +132,8 @@ static int of_device_resume(struct devic - struct bus_type of_platform_bus_type = { - .name = "of_platform", - .match = of_platform_bus_match, -+ .probe = of_device_probe, -+ .remove = of_device_remove, - .suspend = of_device_suspend, - .resume = of_device_resume, - }; -@@ -150,8 +152,6 @@ int of_register_driver(struct of_platfor - /* initialize common driver fields */ - drv->driver.name = drv->name; - drv->driver.bus = &of_platform_bus_type; -- drv->driver.probe = of_device_probe; -- drv->driver.remove = of_device_remove; - - /* register with core */ - count = driver_register(&drv->driver); diff --git a/driver/add-parisc_bus_type-probe-and-remove-methods.patch b/driver/add-parisc_bus_type-probe-and-remove-methods.patch deleted file mode 100644 index ea325da67991f..0000000000000 --- a/driver/add-parisc_bus_type-probe-and-remove-methods.patch +++ /dev/null @@ -1,35 +0,0 @@ -From rmk+greg=kroah.com@arm.linux.org.uk Thu Jan 5 06:37:17 2006 -From: Russell King <rmk@arm.linux.org.uk> -CC: Greg K-H <greg@kroah.com>, parisc <parisc-linux@parisc-linux.org> -Subject: [CFT 10/29] Add parisc_bus_type probe and remove methods -Date: Thu, 05 Jan 2006 14:34:38 +0000 -Message-ID: <20060105142951.13.10@flint.arm.linux.org.uk> - -Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> -Acked-by: Matthew Wilcox <matthew@wil.cx> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - arch/parisc/kernel/drivers.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- gregkh-2.6.orig/arch/parisc/kernel/drivers.c -+++ gregkh-2.6/arch/parisc/kernel/drivers.c -@@ -173,8 +173,6 @@ int register_parisc_driver(struct parisc - WARN_ON(driver->drv.probe != NULL); - WARN_ON(driver->drv.remove != NULL); - -- driver->drv.probe = parisc_driver_probe; -- driver->drv.remove = parisc_driver_remove; - driver->drv.name = driver->name; - - return driver_register(&driver->drv); -@@ -575,6 +573,8 @@ struct bus_type parisc_bus_type = { - .name = "parisc", - .match = parisc_generic_match, - .dev_attrs = parisc_device_attrs, -+ .probe = parisc_driver_probe, -+ .remove = parisc_driver_remove, - }; - - /** diff --git a/driver/add-pci_bus_type-probe-and-remove-methods.patch b/driver/add-pci_bus_type-probe-and-remove-methods.patch deleted file mode 100644 index 6caa333779bfa..0000000000000 --- a/driver/add-pci_bus_type-probe-and-remove-methods.patch +++ /dev/null @@ -1,38 +0,0 @@ -From rmk+greg=kroah.com@arm.linux.org.uk Thu Jan 5 06:31:48 2006 -From: Russell King <rmk@arm.linux.org.uk> -CC: Greg K-H <greg@kroah.com> -Subject: [CFT 2/29] Add pci_bus_type probe and remove methods -Date: Thu, 05 Jan 2006 14:30:22 +0000 -Message-ID: <20060105142951.13.02@flint.arm.linux.org.uk> - -Move the PCI bus device probe/remove methods to the bus_type -structure. We leave the shutdown method alone since there -are compatibility issues with that. - -Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/pci/pci-driver.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- gregkh-2.6.orig/drivers/pci/pci-driver.c -+++ gregkh-2.6/drivers/pci/pci-driver.c -@@ -380,8 +380,6 @@ int __pci_register_driver(struct pci_dri - /* initialize common driver fields */ - drv->driver.name = drv->name; - drv->driver.bus = &pci_bus_type; -- drv->driver.probe = pci_device_probe; -- drv->driver.remove = pci_device_remove; - /* FIXME, once all of the existing PCI drivers have been fixed to set - * the pci shutdown function, this test can go away. */ - if (!drv->driver.shutdown) -@@ -513,6 +511,8 @@ struct bus_type pci_bus_type = { - .name = "pci", - .match = pci_bus_match, - .uevent = pci_uevent, -+ .probe = pci_device_probe, -+ .remove = pci_device_remove, - .suspend = pci_device_suspend, - .resume = pci_device_resume, - .dev_attrs = pci_dev_attrs, diff --git a/driver/add-pcmcia_bus_type-probe-and-remove-methods.patch b/driver/add-pcmcia_bus_type-probe-and-remove-methods.patch deleted file mode 100644 index 946ba675edff7..0000000000000 --- a/driver/add-pcmcia_bus_type-probe-and-remove-methods.patch +++ /dev/null @@ -1,34 +0,0 @@ -From rmk+greg=kroah.com@arm.linux.org.uk Thu Jan 5 06:43:14 2006 -From: Russell King <rmk@arm.linux.org.uk> -CC: Greg K-H <greg@kroah.com>, PCMCIA <linux-pcmcia@lists.infradead.org> -Subject: [CFT 22/29] Add pcmcia_bus_type probe and remove methods -Date: Thu, 05 Jan 2006 14:40:58 +0000 -Message-ID: <20060105142951.13.22@flint.arm.linux.org.uk> - -Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/pcmcia/ds.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- gregkh-2.6.orig/drivers/pcmcia/ds.c -+++ gregkh-2.6/drivers/pcmcia/ds.c -@@ -311,8 +311,6 @@ int pcmcia_register_driver(struct pcmcia - /* initialize common fields */ - driver->drv.bus = &pcmcia_bus_type; - driver->drv.owner = driver->owner; -- driver->drv.probe = pcmcia_device_probe; -- driver->drv.remove = pcmcia_device_remove; - - return driver_register(&driver->drv); - } -@@ -1200,6 +1198,8 @@ struct bus_type pcmcia_bus_type = { - .uevent = pcmcia_bus_uevent, - .match = pcmcia_bus_match, - .dev_attrs = pcmcia_dev_attrs, -+ .probe = pcmcia_device_probe, -+ .remove = pcmcia_device_remove, - .suspend = pcmcia_dev_suspend, - .resume = pcmcia_dev_resume, - }; diff --git a/driver/add-pnp_bus_type-probe-and-remove-methods.patch b/driver/add-pnp_bus_type-probe-and-remove-methods.patch deleted file mode 100644 index c2b9ce6d1e4d0..0000000000000 --- a/driver/add-pnp_bus_type-probe-and-remove-methods.patch +++ /dev/null @@ -1,34 +0,0 @@ -From rmk+greg=kroah.com@arm.linux.org.uk Thu Jan 5 06:43:18 2006 -From: Russell King <rmk@arm.linux.org.uk> -CC: Greg K-H <greg@kroah.com>, Adam Belay <ambx1@neo.rr.com> -Subject: [CFT 23/29] Add pnp_bus_type probe and remove methods -Date: Thu, 05 Jan 2006 14:41:37 +0000 -Message-ID: <20060105142951.13.23@flint.arm.linux.org.uk> - -Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/pnp/driver.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- gregkh-2.6.orig/drivers/pnp/driver.c -+++ gregkh-2.6/drivers/pnp/driver.c -@@ -195,6 +195,8 @@ static int pnp_bus_resume(struct device - struct bus_type pnp_bus_type = { - .name = "pnp", - .match = pnp_bus_match, -+ .probe = pnp_device_probe, -+ .remove = pnp_device_remove, - .suspend = pnp_bus_suspend, - .resume = pnp_bus_resume, - }; -@@ -215,8 +217,6 @@ int pnp_register_driver(struct pnp_drive - - drv->driver.name = drv->name; - drv->driver.bus = &pnp_bus_type; -- drv->driver.probe = pnp_device_probe; -- drv->driver.remove = pnp_device_remove; - - count = driver_register(&drv->driver); - diff --git a/driver/add-pseudo-lld-bus_type-probe-and-remove-methods.patch b/driver/add-pseudo-lld-bus_type-probe-and-remove-methods.patch deleted file mode 100644 index 7261b561f3bb6..0000000000000 --- a/driver/add-pseudo-lld-bus_type-probe-and-remove-methods.patch +++ /dev/null @@ -1,34 +0,0 @@ -From rmk+greg=kroah.com@arm.linux.org.uk Thu Jan 5 06:49:11 2006 -From: Russell King <rmk@arm.linux.org.uk> -CC: Greg K-H <greg@kroah.com>, SCSI <linux-scsi@vger.kernel.org> -Subject: [CFT 29/29] Add Pseudo LLD bus_type probe and remove methods -Date: Thu, 05 Jan 2006 14:44:46 +0000 -Message-ID: <20060105142951.13.29@flint.arm.linux.org.uk> - -Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/scsi/scsi_debug.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- gregkh-2.6.orig/drivers/scsi/scsi_debug.c -+++ gregkh-2.6/drivers/scsi/scsi_debug.c -@@ -221,8 +221,6 @@ static struct bus_type pseudo_lld_bus; - static struct device_driver sdebug_driverfs_driver = { - .name = sdebug_proc_name, - .bus = &pseudo_lld_bus, -- .probe = sdebug_driver_probe, -- .remove = sdebug_driver_remove, - }; - - static const int check_condition_result = -@@ -1796,6 +1794,8 @@ static int pseudo_lld_bus_match(struct d - static struct bus_type pseudo_lld_bus = { - .name = "pseudo", - .match = pseudo_lld_bus_match, -+ .probe = sdebug_driver_probe, -+ .remove = sdebug_driver_remove, - }; - - static void sdebug_release_adapter(struct device * dev) diff --git a/driver/add-rio_bus_type-probe-and-remove-methods.patch b/driver/add-rio_bus_type-probe-and-remove-methods.patch deleted file mode 100644 index d1c7482cf487c..0000000000000 --- a/driver/add-rio_bus_type-probe-and-remove-methods.patch +++ /dev/null @@ -1,36 +0,0 @@ -From rmk+greg=kroah.com@arm.linux.org.uk Thu Jan 5 06:49:03 2006 -From: Russell King <rmk@arm.linux.org.uk> -CC: Greg K-H <greg@kroah.com>, Matt Porter <mporter@kernel.crashing.org> -Subject: [CFT 28/29] Add rio_bus_type probe and remove methods -Date: Thu, 05 Jan 2006 14:44:14 +0000 -Message-ID: <20060105142951.13.28@flint.arm.linux.org.uk> - -Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/rapidio/rio-driver.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- gregkh-2.6.orig/drivers/rapidio/rio-driver.c -+++ gregkh-2.6/drivers/rapidio/rio-driver.c -@@ -147,8 +147,6 @@ int rio_register_driver(struct rio_drive - /* initialize common driver fields */ - rdrv->driver.name = rdrv->name; - rdrv->driver.bus = &rio_bus_type; -- rdrv->driver.probe = rio_device_probe; -- rdrv->driver.remove = rio_device_remove; - - /* register with core */ - return driver_register(&rdrv->driver); -@@ -204,7 +202,9 @@ static struct device rio_bus = { - struct bus_type rio_bus_type = { - .name = "rapidio", - .match = rio_match_bus, -- .dev_attrs = rio_dev_attrs -+ .dev_attrs = rio_dev_attrs, -+ .probe = rio_device_probe, -+ .remove = rio_device_remove, - }; - - /** diff --git a/driver/add-sa1111-bus_type-probe-remove-methods.patch b/driver/add-sa1111-bus_type-probe-remove-methods.patch deleted file mode 100644 index 9ac3627d40783..0000000000000 --- a/driver/add-sa1111-bus_type-probe-remove-methods.patch +++ /dev/null @@ -1,33 +0,0 @@ -From rmk+greg=kroah.com@arm.linux.org.uk Thu Jan 5 06:37:05 2006 -From: Russell King <rmk@arm.linux.org.uk> -CC: Greg K-H <greg@kroah.com> -Subject: [CFT 6/29] Add SA1111 bus_type probe/remove methods -Date: Thu, 05 Jan 2006 14:32:32 +0000 -Message-ID: <20060105142951.13.06@flint.arm.linux.org.uk> - -Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - arch/arm/common/sa1111.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- gregkh-2.6.orig/arch/arm/common/sa1111.c -+++ gregkh-2.6/arch/arm/common/sa1111.c -@@ -1247,14 +1247,14 @@ static int sa1111_bus_remove(struct devi - struct bus_type sa1111_bus_type = { - .name = "sa1111-rab", - .match = sa1111_match, -+ .probe = sa1111_bus_probe, -+ .remove = sa1111_bus_remove, - .suspend = sa1111_bus_suspend, - .resume = sa1111_bus_resume, - }; - - int sa1111_driver_register(struct sa1111_driver *driver) - { -- driver->drv.probe = sa1111_bus_probe; -- driver->drv.remove = sa1111_bus_remove; - driver->drv.bus = &sa1111_bus_type; - return driver_register(&driver->drv); - } diff --git a/driver/add-serio-bus_type-probe-and-remove-methods.patch b/driver/add-serio-bus_type-probe-and-remove-methods.patch deleted file mode 100644 index 9206eb4640b2a..0000000000000 --- a/driver/add-serio-bus_type-probe-and-remove-methods.patch +++ /dev/null @@ -1,45 +0,0 @@ -From rmk+greg=kroah.com@arm.linux.org.uk Thu Jan 5 06:42:55 2006 -From: Russell King <rmk@arm.linux.org.uk> -CC: Greg K-H <greg@kroah.com>, INPUT <linux-input@atrey.karlin.mff.cuni.cz> -Subject: [CFT 18/29] Add serio bus_type probe and remove methods -Date: Thu, 05 Jan 2006 14:38:53 +0000 -Message-ID: <20060105142951.13.18@flint.arm.linux.org.uk> - -Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/input/serio/serio.c | 12 +++++++----- - 1 file changed, 7 insertions(+), 5 deletions(-) - ---- gregkh-2.6.orig/drivers/input/serio/serio.c -+++ gregkh-2.6/drivers/input/serio/serio.c -@@ -59,9 +59,7 @@ static DECLARE_MUTEX(serio_sem); - - static LIST_HEAD(serio_list); - --static struct bus_type serio_bus = { -- .name = "serio", --}; -+static struct bus_type serio_bus; - - static void serio_add_port(struct serio *serio); - static void serio_destroy_port(struct serio *serio); -@@ -750,11 +748,15 @@ static int serio_driver_remove(struct de - return 0; - } - -+static struct bus_type serio_bus = { -+ .name = "serio", -+ .probe = serio_driver_probe, -+ .remove = serio_driver_remove, -+}; -+ - void __serio_register_driver(struct serio_driver *drv, struct module *owner) - { - drv->driver.bus = &serio_bus; -- drv->driver.probe = serio_driver_probe; -- drv->driver.remove = serio_driver_remove; - - serio_queue_event(drv, owner, SERIO_REGISTER_DRIVER); - } diff --git a/driver/add-sh_bus_type-probe-and-remove-methods.patch b/driver/add-sh_bus_type-probe-and-remove-methods.patch deleted file mode 100644 index 29ed6b52e624a..0000000000000 --- a/driver/add-sh_bus_type-probe-and-remove-methods.patch +++ /dev/null @@ -1,71 +0,0 @@ -From rmk+greg=kroah.com@arm.linux.org.uk Thu Jan 5 06:37:20 2006 -From: Russell King <rmk@arm.linux.org.uk> -CC: Greg K-H <greg@kroah.com>, SH <linux-sh@m17n.org> -Subject: [CFT 12/29] Add sh_bus_type probe and remove methods -Date: Thu, 05 Jan 2006 14:35:42 +0000 -Message-ID: <20060105142951.13.12@flint.arm.linux.org.uk> - -Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - arch/sh/kernel/cpu/bus.c | 34 +++++++++++++++++----------------- - 1 file changed, 17 insertions(+), 17 deletions(-) - ---- gregkh-2.6.orig/arch/sh/kernel/cpu/bus.c -+++ gregkh-2.6/arch/sh/kernel/cpu/bus.c -@@ -53,21 +53,6 @@ static int sh_bus_resume(struct device * - return 0; - } - --static struct device sh_bus_devices[SH_NR_BUSES] = { -- { -- .bus_id = SH_BUS_NAME_VIRT, -- }, --}; -- --struct bus_type sh_bus_types[SH_NR_BUSES] = { -- { -- .name = SH_BUS_NAME_VIRT, -- .match = sh_bus_match, -- .suspend = sh_bus_suspend, -- .resume = sh_bus_resume, -- }, --}; -- - static int sh_device_probe(struct device *dev) - { - struct sh_dev *shdev = to_sh_dev(dev); -@@ -90,6 +75,23 @@ static int sh_device_remove(struct devic - return 0; - } - -+static struct device sh_bus_devices[SH_NR_BUSES] = { -+ { -+ .bus_id = SH_BUS_NAME_VIRT, -+ }, -+}; -+ -+struct bus_type sh_bus_types[SH_NR_BUSES] = { -+ { -+ .name = SH_BUS_NAME_VIRT, -+ .match = sh_bus_match, -+ .probe = sh_bus_probe, -+ .remove = sh_bus_remove, -+ .suspend = sh_bus_suspend, -+ .resume = sh_bus_resume, -+ }, -+}; -+ - int sh_device_register(struct sh_dev *dev) - { - if (!dev) -@@ -133,8 +135,6 @@ int sh_driver_register(struct sh_driver - return -EINVAL; - } - -- drv->drv.probe = sh_device_probe; -- drv->drv.remove = sh_device_remove; - drv->drv.bus = &sh_bus_types[drv->bus_id]; - - return driver_register(&drv->drv); diff --git a/driver/add-superhyway_bus_type-probe-and-remove-methods.patch b/driver/add-superhyway_bus_type-probe-and-remove-methods.patch deleted file mode 100644 index 32352aaf98ab1..0000000000000 --- a/driver/add-superhyway_bus_type-probe-and-remove-methods.patch +++ /dev/null @@ -1,34 +0,0 @@ -From rmk+greg=kroah.com@arm.linux.org.uk Thu Jan 5 06:48:36 2006 -From: Russell King <rmk@arm.linux.org.uk> -CC: Greg K-H <greg@kroah.com>, SH <linux-sh@m17n.org> -Subject: [CFT 25/29] Add superhyway_bus_type probe and remove methods -Date: Thu, 05 Jan 2006 14:42:40 +0000 -Message-ID: <20060105142951.13.25@flint.arm.linux.org.uk> - -Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/sh/superhyway/superhyway.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- gregkh-2.6.orig/drivers/sh/superhyway/superhyway.c -+++ gregkh-2.6/drivers/sh/superhyway/superhyway.c -@@ -175,8 +175,6 @@ int superhyway_register_driver(struct su - { - drv->drv.name = drv->name; - drv->drv.bus = &superhyway_bus_type; -- drv->drv.probe = superhyway_device_probe; -- drv->drv.remove = superhyway_device_remove; - - return driver_register(&drv->drv); - } -@@ -213,6 +211,8 @@ struct bus_type superhyway_bus_type = { - #ifdef CONFIG_SYSFS - .dev_attrs = superhyway_dev_attrs, - #endif -+ .probe = superhyway_device_probe, -+ .remove = superhyway_device_remove, - }; - - static int __init superhyway_bus_init(void) diff --git a/driver/add-tiocx-bus_type-probe-remove-methods.patch b/driver/add-tiocx-bus_type-probe-remove-methods.patch deleted file mode 100644 index 869aa5a6f380f..0000000000000 --- a/driver/add-tiocx-bus_type-probe-remove-methods.patch +++ /dev/null @@ -1,53 +0,0 @@ -From rmk+greg=kroah.com@arm.linux.org.uk Thu Jan 5 06:37:15 2006 -From: Russell King <rmk@arm.linux.org.uk> -CC: Greg K-H <greg@kroah.com>, IA64 <linux-ia64@vger.kernel.org> -Subject: [CFT 9/29] Add tiocx bus_type probe/remove methods -Date: Thu, 05 Jan 2006 14:34:06 +0000 -Message-ID: <20060105142951.13.09@flint.arm.linux.org.uk> - -Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - arch/ia64/sn/kernel/tiocx.c | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - ---- gregkh-2.6.orig/arch/ia64/sn/kernel/tiocx.c -+++ gregkh-2.6/arch/ia64/sn/kernel/tiocx.c -@@ -77,12 +77,6 @@ static void tiocx_bus_release(struct dev - kfree(to_cx_dev(dev)); - } - --struct bus_type tiocx_bus_type = { -- .name = "tiocx", -- .match = tiocx_match, -- .uevent = tiocx_uevent, --}; -- - /** - * cx_device_match - Find cx_device in the id table. - * @ids: id table from driver -@@ -149,6 +143,14 @@ static int cx_driver_remove(struct devic - return 0; - } - -+struct bus_type tiocx_bus_type = { -+ .name = "tiocx", -+ .match = tiocx_match, -+ .uevent = tiocx_uevent, -+ .probe = cx_device_probe, -+ .remove = cx_driver_remove, -+}; -+ - /** - * cx_driver_register - Register the driver. - * @cx_driver: driver table (cx_drv struct) from driver -@@ -162,8 +164,6 @@ int cx_driver_register(struct cx_drv *cx - { - cx_driver->driver.name = cx_driver->name; - cx_driver->driver.bus = &tiocx_bus_type; -- cx_driver->driver.probe = cx_device_probe; -- cx_driver->driver.remove = cx_driver_remove; - - return driver_register(&cx_driver->driver); - } diff --git a/driver/add-usb_serial_bus_type-probe-and-remove-methods.patch b/driver/add-usb_serial_bus_type-probe-and-remove-methods.patch deleted file mode 100644 index 761ab2d9ead7f..0000000000000 --- a/driver/add-usb_serial_bus_type-probe-and-remove-methods.patch +++ /dev/null @@ -1,50 +0,0 @@ -From rmk+greg=kroah.com@arm.linux.org.uk Thu Jan 5 06:48:39 2006 -From: Russell King <rmk@arm.linux.org.uk> -CC: Greg K-H <greg@kroah.com> -Subject: [CFT 26/29] Add usb_serial_bus_type probe and remove methods -Date: Thu, 05 Jan 2006 14:43:11 +0000 -Message-ID: <20060105142951.13.26@flint.arm.linux.org.uk> - -Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/serial/bus.c | 15 +++++++-------- - 1 file changed, 7 insertions(+), 8 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/serial/bus.c -+++ gregkh-2.6/drivers/usb/serial/bus.c -@@ -37,11 +37,6 @@ static int usb_serial_device_match (stru - return 0; - } - --struct bus_type usb_serial_bus_type = { -- .name = "usb-serial", -- .match = usb_serial_device_match, --}; -- - static int usb_serial_device_probe (struct device *dev) - { - struct usb_serial_driver *driver; -@@ -109,14 +104,18 @@ exit: - return retval; - } - -+struct bus_type usb_serial_bus_type = { -+ .name = "usb-serial", -+ .match = usb_serial_device_match, -+ .probe = usb_serial_device_probe, -+ .remove = usb_serial_device_remove, -+}; -+ - int usb_serial_bus_register(struct usb_serial_driver *driver) - { - int retval; - - driver->driver.bus = &usb_serial_bus_type; -- driver->driver.probe = usb_serial_device_probe; -- driver->driver.remove = usb_serial_device_remove; -- - retval = driver_register(&driver->driver); - - return retval; diff --git a/driver/add-vio_bus_type-probe-and-remove-methods.patch b/driver/add-vio_bus_type-probe-and-remove-methods.patch deleted file mode 100644 index 4bbb81bae13ca..0000000000000 --- a/driver/add-vio_bus_type-probe-and-remove-methods.patch +++ /dev/null @@ -1,43 +0,0 @@ -From rmk+greg=kroah.com@arm.linux.org.uk Thu Jan 5 06:37:30 2006 -From: Russell King <rmk@arm.linux.org.uk> -CC: Greg K-H <greg@kroah.com>, PPC <linuxppc-embedded@ozlabs.org> -Subject: [CFT 14/29] Add vio_bus_type probe and remove methods -Date: Thu, 05 Jan 2006 14:36:47 +0000 -Message-ID: <20060105142951.13.14@flint.arm.linux.org.uk> - -Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - arch/powerpc/kernel/vio.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - ---- gregkh-2.6.orig/arch/powerpc/kernel/vio.c -+++ gregkh-2.6/arch/powerpc/kernel/vio.c -@@ -76,7 +76,7 @@ static void vio_bus_shutdown(struct devi - struct vio_dev *viodev = to_vio_dev(dev); - struct vio_driver *viodrv = to_vio_driver(dev->driver); - -- if (viodrv->shutdown) -+ if (dev->driver && viodrv->shutdown) - viodrv->shutdown(viodev); - } - -@@ -91,9 +91,6 @@ int vio_register_driver(struct vio_drive - - /* fill in 'struct driver' fields */ - viodrv->driver.bus = &vio_bus_type; -- viodrv->driver.probe = vio_bus_probe; -- viodrv->driver.remove = vio_bus_remove; -- viodrv->driver.shutdown = vio_bus_shutdown; - - return driver_register(&viodrv->driver); - } -@@ -295,4 +292,7 @@ struct bus_type vio_bus_type = { - .name = "vio", - .uevent = vio_hotplug, - .match = vio_bus_match, -+ .probe = vio_bus_probe, -+ .remove = vio_bus_remove, -+ .shutdown = vio_bus_shutdown, - }; diff --git a/driver/add-zorro_bus_type-probe-and-remove-methods.patch b/driver/add-zorro_bus_type-probe-and-remove-methods.patch deleted file mode 100644 index c02d397c36243..0000000000000 --- a/driver/add-zorro_bus_type-probe-and-remove-methods.patch +++ /dev/null @@ -1,34 +0,0 @@ -From rmk+greg=kroah.com@arm.linux.org.uk Thu Jan 5 06:48:59 2006 -From: Russell King <rmk@arm.linux.org.uk> -CC: Greg K-H <greg@kroah.com>, M68K <linux-m68k@lists.linux-m68k.org> -Subject: [CFT 27/29] Add zorro_bus_type probe and remove methods -Date: Thu, 05 Jan 2006 14:43:43 +0000 -Message-ID: <20060105142951.13.27@flint.arm.linux.org.uk> - -Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/zorro/zorro-driver.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- gregkh-2.6.orig/drivers/zorro/zorro-driver.c -+++ gregkh-2.6/drivers/zorro/zorro-driver.c -@@ -77,7 +77,6 @@ int zorro_register_driver(struct zorro_d - /* initialize common driver fields */ - drv->driver.name = drv->name; - drv->driver.bus = &zorro_bus_type; -- drv->driver.probe = zorro_device_probe; - - /* register with core */ - count = driver_register(&drv->driver); -@@ -132,7 +131,8 @@ static int zorro_bus_match(struct device - - struct bus_type zorro_bus_type = { - .name = "zorro", -- .match = zorro_bus_match -+ .match = zorro_bus_match, -+ .probe = zorro_device_probe, - }; - - diff --git a/driver/device_shutdown-can-loop-if-the-driver-frees-itself.patch b/driver/device_shutdown-can-loop-if-the-driver-frees-itself.patch deleted file mode 100644 index 13d3972ad4d80..0000000000000 --- a/driver/device_shutdown-can-loop-if-the-driver-frees-itself.patch +++ /dev/null @@ -1,46 +0,0 @@ -From akpm@osdl.org Mon Jan 9 01:09:07 2006 -Message-Id: <200601090905.k09953Iv027215@shell0.pdx.osdl.net> -From: "Michael Richardson" <mcr@sandelman.ottawa.on.ca> -Subject: device_shutdown can loop if the driver frees itself -To: mcr@sandelman.ottawa.on.ca, dhowells@redhat.com, greg@kroah.com, - mcr@marajade.sandelman.ca, mochel@digitalimplant.org, - mm-commits@vger.kernel.org -Date: Mon, 09 Jan 2006 01:04:51 -0800 - - -From: "Michael Richardson" <mcr@sandelman.ottawa.on.ca> - -This patch changes device_shutdown() to use the newly introduced safe -reverse list traversal. We experienced loops on system reboot if we had -removed and re-inserted our device from the device list. - -We noticed this problem on PPC405. Our PCI IDE device comes and goes a lot. - -Our hypothesis was that there was a loop caused by the driver->shutdown -freeing memory. It is possible that we do something wrong as well, but -being unable to reboot is kind of nasty. - -Signed-off-by: Michael Richardson <mcr@marajade.sandelman.ca> -Cc: Patrick Mochel <mochel@digitalimplant.org> -Cc: David Howells <dhowells@redhat.com> -Signed-off-by: Andrew Morton <akpm@osdl.org> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> ---- - drivers/base/power/shutdown.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- gregkh-2.6.orig/drivers/base/power/shutdown.c -+++ gregkh-2.6/drivers/base/power/shutdown.c -@@ -35,10 +35,10 @@ extern int sysdev_shutdown(void); - */ - void device_shutdown(void) - { -- struct device * dev; -+ struct device * dev, *devn; - - down_write(&devices_subsys.rwsem); -- list_for_each_entry_reverse(dev, &devices_subsys.kset.list, -+ list_for_each_entry_safe_reverse(dev, devn, &devices_subsys.kset.list, - kobj.entry) { - if (dev->bus && dev->bus->shutdown) { - dev_dbg(dev, "shutdown\n"); diff --git a/driver/input-MODALIAS-02.patch b/driver/input-MODALIAS-02.patch deleted file mode 100644 index bfae1f5662509..0000000000000 --- a/driver/input-MODALIAS-02.patch +++ /dev/null @@ -1,107 +0,0 @@ -From kay.sievers@vrfy.org Thu Jan 5 04:22:24 2006 -Date: Thu, 5 Jan 2006 13:19:55 +0100 -From: Kay Sievers <kay.sievers@vrfy.org> -To: Greg KH <greg@kroah.com> -Subject: INPUT: add MODALIAS to the event environment -Message-ID: <20060105121955.GA29894@vrfy.org> -Content-Disposition: inline; filename="input-MODALIAS-02.patch" - -From: Kay Sievers <kay.sievers@suse.de> - -input: add MODALIAS to the event environment - -Signed-off-by: Kay Sievers <kay.sievers@suse.de> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> ---- - drivers/input/input.c | 55 +++++++++++++++++++++++++++++++++----------------- - 1 file changed, 37 insertions(+), 18 deletions(-) - ---- gregkh-2.6.orig/drivers/input/input.c -+++ gregkh-2.6/drivers/input/input.c -@@ -528,40 +528,56 @@ INPUT_DEV_STRING_ATTR_SHOW(name); - INPUT_DEV_STRING_ATTR_SHOW(phys); - INPUT_DEV_STRING_ATTR_SHOW(uniq); - --static int print_modalias_bits(char *buf, char prefix, unsigned long *arr, -+static int print_modalias_bits(char *buf, int size, char prefix, unsigned long *arr, - unsigned int min, unsigned int max) - { - int len, i; - -- len = sprintf(buf, "%c", prefix); -+ len = snprintf(buf, size, "%c", prefix); - for (i = min; i < max; i++) - if (arr[LONG(i)] & BIT(i)) -- len += sprintf(buf+len, "%X,", i); -+ len += snprintf(buf + len, size - len, "%X,", i); - return len; - } - --static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf) -+static int print_modalias(char *buf, int size, struct input_dev *id) - { -- struct input_dev *id = to_input_dev(dev); -- ssize_t len = 0; -+ int len; - -- len += sprintf(buf+len, "input:b%04Xv%04Xp%04Xe%04X-", -+ len = snprintf(buf, size, "input:b%04Xv%04Xp%04Xe%04X-", - id->id.bustype, - id->id.vendor, - id->id.product, - id->id.version); - -- len += print_modalias_bits(buf+len, 'e', id->evbit, 0, EV_MAX); -- len += print_modalias_bits(buf+len, 'k', id->keybit, -+ len += print_modalias_bits(buf + len, size - len, 'e', id->evbit, -+ 0, EV_MAX); -+ len += print_modalias_bits(buf + len, size - len, 'k', id->keybit, - KEY_MIN_INTERESTING, KEY_MAX); -- len += print_modalias_bits(buf+len, 'r', id->relbit, 0, REL_MAX); -- len += print_modalias_bits(buf+len, 'a', id->absbit, 0, ABS_MAX); -- len += print_modalias_bits(buf+len, 'm', id->mscbit, 0, MSC_MAX); -- len += print_modalias_bits(buf+len, 'l', id->ledbit, 0, LED_MAX); -- len += print_modalias_bits(buf+len, 's', id->sndbit, 0, SND_MAX); -- len += print_modalias_bits(buf+len, 'f', id->ffbit, 0, FF_MAX); -- len += print_modalias_bits(buf+len, 'w', id->swbit, 0, SW_MAX); -- len += sprintf(buf+len, "\n"); -+ len += print_modalias_bits(buf + len, size - len, 'r', id->relbit, -+ 0, REL_MAX); -+ len += print_modalias_bits(buf + len, size - len, 'a', id->absbit, -+ 0, ABS_MAX); -+ len += print_modalias_bits(buf + len, size - len, 'm', id->mscbit, -+ 0, MSC_MAX); -+ len += print_modalias_bits(buf + len, size - len, 'l', id->ledbit, -+ 0, LED_MAX); -+ len += print_modalias_bits(buf + len, size - len, 's', id->sndbit, -+ 0, SND_MAX); -+ len += print_modalias_bits(buf + len, size - len, 'f', id->ffbit, -+ 0, FF_MAX); -+ len += print_modalias_bits(buf + len, size - len, 'w', id->swbit, -+ 0, SW_MAX); -+ return len; -+} -+ -+static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf) -+{ -+ struct input_dev *id = to_input_dev(dev); -+ ssize_t len; -+ -+ len = print_modalias(buf, PAGE_SIZE, id); -+ len += snprintf(buf + len, PAGE_SIZE-len, "\n"); - return len; - } - static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL); -@@ -728,8 +744,11 @@ static int input_dev_uevent(struct class - if (test_bit(EV_SW, dev->evbit)) - INPUT_ADD_HOTPLUG_BM_VAR("SW=", dev->swbit, SW_MAX); - -- envp[i] = NULL; -+ envp[i++] = buffer + len; -+ len += snprintf(buffer + len, buffer_size - len, "MODALIAS="); -+ len += print_modalias(buffer + len, buffer_size - len, dev) + 1; - -+ envp[i] = NULL; - return 0; - } - diff --git a/driver/platform-device-del-typo-fix.patch b/driver/platform-device-del-typo-fix.patch deleted file mode 100644 index 13deeeb399355..0000000000000 --- a/driver/platform-device-del-typo-fix.patch +++ /dev/null @@ -1,29 +0,0 @@ -From khali@linux-fr.org Thu Dec 29 09:40:13 2005 -Date: Tue, 27 Dec 2005 19:45:58 +0100 -From: Jean Delvare <khali@linux-fr.org> -To: Greg KH <greg@kroah.com> -Cc: Dmitry Torokhov <dtor_core@ameritech.net> -Subject: platform-device-del typo fix -Message-Id: <20051227194558.0db326e3.khali@linux-fr.org> - -Please fold this typo fix into platform-device-del.patch, as was -discussed earlier on LKML: - http://lkml.org/lkml/2005/12/10/76 - -Signed-off-by: Jean Delvare <khali@linux-fr.org> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> ---- - drivers/base/platform.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- gregkh-2.6.orig/drivers/base/platform.c -+++ gregkh-2.6/drivers/base/platform.c -@@ -327,7 +327,7 @@ EXPORT_SYMBOL_GPL(platform_device_regist - * @pdev: platform device we're unregistering - * - * Unregistration is done in 2 steps. Fisrt we release all resources -- * and remove it from the sybsystem, then we drop reference count by -+ * and remove it from the subsystem, then we drop reference count by - * calling platform_device_put(). - */ - void platform_device_unregister(struct platform_device * pdev) diff --git a/driver/remove-usb-gadget-generic-driver-methods.patch b/driver/remove-usb-gadget-generic-driver-methods.patch deleted file mode 100644 index 0d48fc4e5e6e5..0000000000000 --- a/driver/remove-usb-gadget-generic-driver-methods.patch +++ /dev/null @@ -1,69 +0,0 @@ -From rmk+greg=kroah.com@arm.linux.org.uk Fri Jan 6 03:42:45 2006 -From: Russell King <rmk@arm.linux.org.uk> -CC: Greg K-H <greg@kroah.com>, IDE <linux-usb@vger.kernel.org> -Subject: [CFT 2/3] Remove usb gadget generic driver methods -Date: Fri, 06 Jan 2006 11:41:32 +0000 -Message-ID: <20060106114059.13.31@flint.arm.linux.org.uk> - -USB gadget drivers make no use of these, remove the pointless -comments. - -Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - - ---- - drivers/usb/gadget/ether.c | 3 --- - drivers/usb/gadget/inode.c | 3 --- - drivers/usb/gadget/serial.c | 3 --- - drivers/usb/gadget/zero.c | 3 --- - 4 files changed, 12 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/gadget/ether.c -+++ gregkh-2.6/drivers/usb/gadget/ether.c -@@ -2534,9 +2534,6 @@ static struct usb_gadget_driver eth_driv - .driver = { - .name = (char *) shortname, - .owner = THIS_MODULE, -- // .shutdown = ... -- // .suspend = ... -- // .resume = ... - }, - }; - ---- gregkh-2.6.orig/drivers/usb/gadget/inode.c -+++ gregkh-2.6/drivers/usb/gadget/inode.c -@@ -1738,9 +1738,6 @@ static struct usb_gadget_driver gadgetfs - - .driver = { - .name = (char *) shortname, -- // .shutdown = ... -- // .suspend = ... -- // .resume = ... - }, - }; - ---- gregkh-2.6.orig/drivers/usb/gadget/serial.c -+++ gregkh-2.6/drivers/usb/gadget/serial.c -@@ -374,9 +374,6 @@ static struct usb_gadget_driver gs_gadge - .disconnect = gs_disconnect, - .driver = { - .name = GS_SHORT_NAME, -- /* .shutdown = ... */ -- /* .suspend = ... */ -- /* .resume = ... */ - }, - }; - ---- gregkh-2.6.orig/drivers/usb/gadget/zero.c -+++ gregkh-2.6/drivers/usb/gadget/zero.c -@@ -1303,9 +1303,6 @@ static struct usb_gadget_driver zero_dri - .driver = { - .name = (char *) shortname, - .owner = THIS_MODULE, -- // .shutdown = ... -- // .suspend = ... -- // .resume = ... - }, - }; - diff --git a/driver/spi-add-spi_bitbang-driver.patch b/driver/spi-add-spi_bitbang-driver.patch deleted file mode 100644 index 93cc235c3c646..0000000000000 --- a/driver/spi-add-spi_bitbang-driver.patch +++ /dev/null @@ -1,671 +0,0 @@ -From akpm@osdl.org Sun Jan 8 13:38:08 2006 -From: akpm@osdl.org -Message-Id: <200601082134.k08LYcfh004579@shell0.pdx.osdl.net> -Subject: [patch 07/10] spi: add spi_bitbang driver -To: greg@kroah.com -Cc: akpm@osdl.org, david-b@pacbell.net, dbrownell@users.sourceforge.net -Date: Sun, 08 Jan 2006 13:34:26 -0800 - - -From: David Brownell <david-b@pacbell.net> - -This adds a bitbanging spi master, hooking up to board/adapter-specific glue -code which knows how to set and read the signals (gpios etc). - -This code kicks in after the glue code creates a platform_device with the -right platform_data. That data includes I/O loops, which will usually -come from expanding an inline function (provided in the header). One goal -is that the I/O loops should be easily optimized down to a few GPIO register -accesses, in common cases, for speed and minimized overhead. - -This understands all the currently defined protocol tweaking options in the -SPI framework, and might eventually serve as as reference implementation. - - - different word sizes (1..32 bits) - - differing clock rates - - SPI modes differing by CPOL (affecting chip select and I/O loops) - - SPI modes differing by CPHA (affecting I/O loops) - - delays (usecs) after transfers - - temporarily deselecting chips in mid-transfer - -A lot of hardware could work with this framework, though common types of -controller can't reach peak performance without switching to a driver -structure that supports pipelining of transfers (e.g. DMA queues) and maybe -controllers (e.g. IRQ driven). - -Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> -Signed-off-by: Andrew Morton <akpm@osdl.org> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> ---- - drivers/spi/Kconfig | 13 + - drivers/spi/Makefile | 1 - drivers/spi/spi_bitbang.c | 460 ++++++++++++++++++++++++++++++++++++++++ - include/linux/spi/spi_bitbang.h | 128 +++++++++++ - 4 files changed, 602 insertions(+) - ---- gregkh-2.6.orig/drivers/spi/Kconfig -+++ gregkh-2.6/drivers/spi/Kconfig -@@ -51,6 +51,19 @@ config SPI_MASTER - comment "SPI Master Controller Drivers" - depends on SPI_MASTER - -+config SPI_BITBANG -+ tristate "Bitbanging SPI master" -+ depends on SPI_MASTER && EXPERIMENTAL -+ help -+ With a few GPIO pins, your system can bitbang the SPI protocol. -+ Select this to get SPI support through I/O pins (GPIO, parallel -+ port, etc). Or, some systems' SPI master controller drivers use -+ this code to manage the per-word or per-transfer accesses to the -+ hardware shift registers. -+ -+ This is library code, and is automatically selected by drivers that -+ need it. You only need to select this explicitly to support driver -+ modules that aren't part of this kernel tree. - - # - # Add new SPI master controllers in alphabetical order above this line ---- gregkh-2.6.orig/drivers/spi/Makefile -+++ gregkh-2.6/drivers/spi/Makefile -@@ -11,6 +11,7 @@ endif - obj-$(CONFIG_SPI_MASTER) += spi.o - - # SPI master controller drivers (bus) -+obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o - # ... add above this line ... - - # SPI protocol drivers (device/link on bus) ---- /dev/null -+++ gregkh-2.6/drivers/spi/spi_bitbang.c -@@ -0,0 +1,460 @@ -+/* -+ * spi_bitbang.c - polling/bitbanging SPI master controller driver utilities -+ * -+ * 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 <linux/config.h> -+#include <linux/init.h> -+#include <linux/spinlock.h> -+#include <linux/workqueue.h> -+#include <linux/interrupt.h> -+#include <linux/delay.h> -+#include <linux/errno.h> -+#include <linux/platform_device.h> -+ -+#include <linux/spi/spi.h> -+#include <linux/spi/spi_bitbang.h> -+ -+ -+/*----------------------------------------------------------------------*/ -+ -+/* -+ * FIRST PART (OPTIONAL): word-at-a-time spi_transfer support. -+ * Use this for GPIO or shift-register level hardware APIs. -+ * -+ * spi_bitbang_cs is in spi_device->controller_state, which is unavailable -+ * to glue code. These bitbang setup() and cleanup() routines are always -+ * used, though maybe they're called from controller-aware code. -+ * -+ * chipselect() and friends may use use spi_device->controller_data and -+ * controller registers as appropriate. -+ * -+ * -+ * NOTE: SPI controller pins can often be used as GPIO pins instead, -+ * which means you could use a bitbang driver either to get hardware -+ * working quickly, or testing for differences that aren't speed related. -+ */ -+ -+struct spi_bitbang_cs { -+ unsigned nsecs; /* (clock cycle time)/2 */ -+ u32 (*txrx_word)(struct spi_device *spi, unsigned nsecs, -+ u32 word, u8 bits); -+ unsigned (*txrx_bufs)(struct spi_device *, -+ u32 (*txrx_word)( -+ struct spi_device *spi, -+ unsigned nsecs, -+ u32 word, u8 bits), -+ unsigned, struct spi_transfer *); -+}; -+ -+static unsigned bitbang_txrx_8( -+ struct spi_device *spi, -+ u32 (*txrx_word)(struct spi_device *spi, -+ unsigned nsecs, -+ u32 word, u8 bits), -+ unsigned ns, -+ struct spi_transfer *t -+) { -+ unsigned bits = spi->bits_per_word; -+ unsigned count = t->len; -+ const u8 *tx = t->tx_buf; -+ u8 *rx = t->rx_buf; -+ -+ while (likely(count > 0)) { -+ u8 word = 0; -+ -+ if (tx) -+ word = *tx++; -+ word = txrx_word(spi, ns, word, bits); -+ if (rx) -+ *rx++ = word; -+ count -= 1; -+ } -+ return t->len - count; -+} -+ -+static unsigned bitbang_txrx_16( -+ struct spi_device *spi, -+ u32 (*txrx_word)(struct spi_device *spi, -+ unsigned nsecs, -+ u32 word, u8 bits), -+ unsigned ns, -+ struct spi_transfer *t -+) { -+ unsigned bits = spi->bits_per_word; -+ unsigned count = t->len; -+ const u16 *tx = t->tx_buf; -+ u16 *rx = t->rx_buf; -+ -+ while (likely(count > 1)) { -+ u16 word = 0; -+ -+ if (tx) -+ word = *tx++; -+ word = txrx_word(spi, ns, word, bits); -+ if (rx) -+ *rx++ = word; -+ count -= 2; -+ } -+ return t->len - count; -+} -+ -+static unsigned bitbang_txrx_32( -+ struct spi_device *spi, -+ u32 (*txrx_word)(struct spi_device *spi, -+ unsigned nsecs, -+ u32 word, u8 bits), -+ unsigned ns, -+ struct spi_transfer *t -+) { -+ unsigned bits = spi->bits_per_word; -+ unsigned count = t->len; -+ const u32 *tx = t->tx_buf; -+ u32 *rx = t->rx_buf; -+ -+ while (likely(count > 3)) { -+ u32 word = 0; -+ -+ if (tx) -+ word = *tx++; -+ word = txrx_word(spi, ns, word, bits); -+ if (rx) -+ *rx++ = word; -+ count -= 4; -+ } -+ return t->len - count; -+} -+ -+/** -+ * spi_bitbang_setup - default setup for per-word I/O loops -+ */ -+int spi_bitbang_setup(struct spi_device *spi) -+{ -+ struct spi_bitbang_cs *cs = spi->controller_state; -+ struct spi_bitbang *bitbang; -+ -+ if (!cs) { -+ cs = kzalloc(sizeof *cs, SLAB_KERNEL); -+ if (!cs) -+ return -ENOMEM; -+ spi->controller_state = cs; -+ } -+ bitbang = spi_master_get_devdata(spi->master); -+ -+ if (!spi->bits_per_word) -+ spi->bits_per_word = 8; -+ -+ /* spi_transfer level calls that work per-word */ -+ if (spi->bits_per_word <= 8) -+ cs->txrx_bufs = bitbang_txrx_8; -+ else if (spi->bits_per_word <= 16) -+ cs->txrx_bufs = bitbang_txrx_16; -+ else if (spi->bits_per_word <= 32) -+ cs->txrx_bufs = bitbang_txrx_32; -+ else -+ return -EINVAL; -+ -+ /* per-word shift register access, in hardware or bitbanging */ -+ cs->txrx_word = bitbang->txrx_word[spi->mode & (SPI_CPOL|SPI_CPHA)]; -+ if (!cs->txrx_word) -+ return -EINVAL; -+ -+ if (!spi->max_speed_hz) -+ spi->max_speed_hz = 500 * 1000; -+ -+ /* nsecs = max(50, (clock period)/2), be optimistic */ -+ cs->nsecs = (1000000000/2) / (spi->max_speed_hz); -+ if (cs->nsecs < 50) -+ cs->nsecs = 50; -+ if (cs->nsecs > MAX_UDELAY_MS * 1000) -+ return -EINVAL; -+ -+ dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec\n", -+ __FUNCTION__, spi->mode & (SPI_CPOL | SPI_CPHA), -+ spi->bits_per_word, 2 * cs->nsecs); -+ -+ /* NOTE we _need_ to call chipselect() early, ideally with adapter -+ * setup, unless the hardware defaults cooperate to avoid confusion -+ * between normal (active low) and inverted chipselects. -+ */ -+ -+ /* deselect chip (low or high) */ -+ spin_lock(&bitbang->lock); -+ if (!bitbang->busy) { -+ bitbang->chipselect(spi, 0); -+ ndelay(cs->nsecs); -+ } -+ spin_unlock(&bitbang->lock); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(spi_bitbang_setup); -+ -+/** -+ * spi_bitbang_cleanup - default cleanup for per-word I/O loops -+ */ -+void spi_bitbang_cleanup(const struct spi_device *spi) -+{ -+ kfree(spi->controller_state); -+} -+EXPORT_SYMBOL_GPL(spi_bitbang_cleanup); -+ -+static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t) -+{ -+ struct spi_bitbang_cs *cs = spi->controller_state; -+ unsigned nsecs = cs->nsecs; -+ -+ return cs->txrx_bufs(spi, cs->txrx_word, nsecs, t); -+} -+ -+/*----------------------------------------------------------------------*/ -+ -+/* -+ * SECOND PART ... simple transfer queue runner. -+ * -+ * This costs a task context per controller, running the queue by -+ * performing each transfer in sequence. Smarter hardware can queue -+ * several DMA transfers at once, and process several controller queues -+ * in parallel; this driver doesn't match such hardware very well. -+ * -+ * Drivers can provide word-at-a-time i/o primitives, or provide -+ * transfer-at-a-time ones to leverage dma or fifo hardware. -+ */ -+static void bitbang_work(void *_bitbang) -+{ -+ struct spi_bitbang *bitbang = _bitbang; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&bitbang->lock, flags); -+ bitbang->busy = 1; -+ while (!list_empty(&bitbang->queue)) { -+ struct spi_message *m; -+ struct spi_device *spi; -+ unsigned nsecs; -+ struct spi_transfer *t; -+ unsigned tmp; -+ unsigned chipselect; -+ int status; -+ -+ m = container_of(bitbang->queue.next, struct spi_message, -+ queue); -+ list_del_init(&m->queue); -+ spin_unlock_irqrestore(&bitbang->lock, flags); -+ -+// FIXME this is made-up -+nsecs = 100; -+ -+ spi = m->spi; -+ t = m->transfers; -+ tmp = 0; -+ chipselect = 0; -+ status = 0; -+ -+ for (;;t++) { -+ if (bitbang->shutdown) { -+ status = -ESHUTDOWN; -+ break; -+ } -+ -+ /* set up default clock polarity, and activate chip */ -+ if (!chipselect) { -+ bitbang->chipselect(spi, 1); -+ ndelay(nsecs); -+ } -+ if (!t->tx_buf && !t->rx_buf && t->len) { -+ status = -EINVAL; -+ break; -+ } -+ -+ /* transfer data */ -+ if (t->len) { -+ /* FIXME if bitbang->use_dma, dma_map_single() -+ * before the transfer, and dma_unmap_single() -+ * afterwards, for either or both buffers... -+ */ -+ status = bitbang->txrx_bufs(spi, t); -+ } -+ if (status != t->len) { -+ if (status > 0) -+ status = -EMSGSIZE; -+ break; -+ } -+ m->actual_length += status; -+ status = 0; -+ -+ /* protocol tweaks before next transfer */ -+ if (t->delay_usecs) -+ udelay(t->delay_usecs); -+ -+ tmp++; -+ if (tmp >= m->n_transfer) -+ break; -+ -+ chipselect = !t->cs_change; -+ if (chipselect); -+ continue; -+ -+ bitbang->chipselect(spi, 0); -+ -+ /* REVISIT do we want the udelay here instead? */ -+ msleep(1); -+ } -+ -+ tmp = m->n_transfer - 1; -+ tmp = m->transfers[tmp].cs_change; -+ -+ m->status = status; -+ m->complete(m->context); -+ -+ ndelay(2 * nsecs); -+ bitbang->chipselect(spi, status == 0 && tmp); -+ ndelay(nsecs); -+ -+ spin_lock_irqsave(&bitbang->lock, flags); -+ } -+ bitbang->busy = 0; -+ spin_unlock_irqrestore(&bitbang->lock, flags); -+} -+ -+/** -+ * spi_bitbang_transfer - default submit to transfer queue -+ */ -+int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m) -+{ -+ struct spi_bitbang *bitbang; -+ unsigned long flags; -+ -+ m->actual_length = 0; -+ m->status = -EINPROGRESS; -+ -+ bitbang = spi_master_get_devdata(spi->master); -+ if (bitbang->shutdown) -+ return -ESHUTDOWN; -+ -+ spin_lock_irqsave(&bitbang->lock, flags); -+ list_add_tail(&m->queue, &bitbang->queue); -+ queue_work(bitbang->workqueue, &bitbang->work); -+ spin_unlock_irqrestore(&bitbang->lock, flags); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(spi_bitbang_transfer); -+ -+/*----------------------------------------------------------------------*/ -+ -+/** -+ * spi_bitbang_start - start up a polled/bitbanging SPI master driver -+ * @bitbang: driver handle -+ * -+ * Caller should have zero-initialized all parts of the structure, and then -+ * provided callbacks for chip selection and I/O loops. If the master has -+ * a transfer method, its final step should call spi_bitbang_transfer; or, -+ * that's the default if the transfer routine is not initialized. It should -+ * also set up the bus number and number of chipselects. -+ * -+ * For i/o loops, provide callbacks either per-word (for bitbanging, or for -+ * hardware that basically exposes a shift register) or per-spi_transfer -+ * (which takes better advantage of hardware like fifos or DMA engines). -+ * -+ * Drivers using per-word I/O loops should use (or call) spi_bitbang_setup and -+ * spi_bitbang_cleanup to handle those spi master methods. Those methods are -+ * the defaults if the bitbang->txrx_bufs routine isn't initialized. -+ * -+ * This routine registers the spi_master, which will process requests in a -+ * dedicated task, keeping IRQs unblocked most of the time. To stop -+ * processing those requests, call spi_bitbang_stop(). -+ */ -+int spi_bitbang_start(struct spi_bitbang *bitbang) -+{ -+ int status; -+ -+ if (!bitbang->master || !bitbang->chipselect) -+ return -EINVAL; -+ -+ INIT_WORK(&bitbang->work, bitbang_work, bitbang); -+ spin_lock_init(&bitbang->lock); -+ INIT_LIST_HEAD(&bitbang->queue); -+ -+ if (!bitbang->master->transfer) -+ bitbang->master->transfer = spi_bitbang_transfer; -+ if (!bitbang->txrx_bufs) { -+ bitbang->use_dma = 0; -+ bitbang->txrx_bufs = spi_bitbang_bufs; -+ if (!bitbang->master->setup) { -+ bitbang->master->setup = spi_bitbang_setup; -+ bitbang->master->cleanup = spi_bitbang_cleanup; -+ } -+ } else if (!bitbang->master->setup) -+ return -EINVAL; -+ -+ /* this task is the only thing to touch the SPI bits */ -+ bitbang->busy = 0; -+ bitbang->workqueue = create_singlethread_workqueue( -+ bitbang->master->cdev.dev->bus_id); -+ if (bitbang->workqueue == NULL) { -+ status = -EBUSY; -+ goto err1; -+ } -+ -+ /* driver may get busy before register() returns, especially -+ * if someone registered boardinfo for devices -+ */ -+ status = spi_register_master(bitbang->master); -+ if (status < 0) -+ goto err2; -+ -+ return status; -+ -+err2: -+ destroy_workqueue(bitbang->workqueue); -+err1: -+ return status; -+} -+EXPORT_SYMBOL_GPL(spi_bitbang_start); -+ -+/** -+ * spi_bitbang_stop - stops the task providing spi communication -+ */ -+int spi_bitbang_stop(struct spi_bitbang *bitbang) -+{ -+ unsigned limit = 500; -+ -+ spin_lock_irq(&bitbang->lock); -+ bitbang->shutdown = 0; -+ while (!list_empty(&bitbang->queue) && limit--) { -+ spin_unlock_irq(&bitbang->lock); -+ -+ dev_dbg(bitbang->master->cdev.dev, "wait for queue\n"); -+ msleep(10); -+ -+ spin_lock_irq(&bitbang->lock); -+ } -+ spin_unlock_irq(&bitbang->lock); -+ if (!list_empty(&bitbang->queue)) { -+ dev_err(bitbang->master->cdev.dev, "queue didn't empty\n"); -+ return -EBUSY; -+ } -+ -+ destroy_workqueue(bitbang->workqueue); -+ -+ spi_unregister_master(bitbang->master); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(spi_bitbang_stop); -+ -+MODULE_LICENSE("GPL"); -+ ---- /dev/null -+++ gregkh-2.6/include/linux/spi/spi_bitbang.h -@@ -0,0 +1,128 @@ -+#ifndef __SPI_BITBANG_H -+#define __SPI_BITBANG_H -+ -+/* -+ * Mix this utility code with some glue code to get one of several types of -+ * simple SPI master driver. Two do polled word-at-a-time I/O: -+ * -+ * - GPIO/parport bitbangers. Provide chipselect() and txrx_word[](), -+ * expanding the per-word routines from the inline templates below. -+ * -+ * - Drivers for controllers resembling bare shift registers. Provide -+ * chipselect() and txrx_word[](), with custom setup()/cleanup() methods -+ * that use your controller's clock and chipselect registers. -+ * -+ * Some hardware works well with requests at spi_transfer scope: -+ * -+ * - Drivers leveraging smarter hardware, with fifos or DMA; or for half -+ * duplex (MicroWire) controllers. Provide chipslect() and txrx_bufs(), -+ * and custom setup()/cleanup() methods. -+ */ -+struct spi_bitbang { -+ struct workqueue_struct *workqueue; -+ struct work_struct work; -+ -+ spinlock_t lock; -+ struct list_head queue; -+ u8 busy; -+ u8 shutdown; -+ u8 use_dma; -+ -+ struct spi_master *master; -+ -+ void (*chipselect)(struct spi_device *spi, int is_on); -+ -+ int (*txrx_bufs)(struct spi_device *spi, struct spi_transfer *t); -+ u32 (*txrx_word[4])(struct spi_device *spi, -+ unsigned nsecs, -+ u32 word, u8 bits); -+}; -+ -+/* you can call these default bitbang->master methods from your custom -+ * methods, if you like. -+ */ -+extern int spi_bitbang_setup(struct spi_device *spi); -+extern void spi_bitbang_cleanup(const struct spi_device *spi); -+extern int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m); -+ -+/* start or stop queue processing */ -+extern int spi_bitbang_start(struct spi_bitbang *spi); -+extern int spi_bitbang_stop(struct spi_bitbang *spi); -+ -+#endif /* __SPI_BITBANG_H */ -+ -+/*-------------------------------------------------------------------------*/ -+ -+#ifdef EXPAND_BITBANG_TXRX -+ -+/* -+ * The code that knows what GPIO pins do what should have declared four -+ * functions, ideally as inlines, before #defining EXPAND_BITBANG_TXRX -+ * and including this header: -+ * -+ * void setsck(struct spi_device *, int is_on); -+ * void setmosi(struct spi_device *, int is_on); -+ * int getmiso(struct spi_device *); -+ * void spidelay(unsigned); -+ * -+ * A non-inlined routine would call bitbang_txrx_*() routines. The -+ * main loop could easily compile down to a handful of instructions, -+ * especially if the delay is a NOP (to run at peak speed). -+ * -+ * Since this is software, the timings may not be exactly what your board's -+ * chips need ... there may be several reasons you'd need to tweak timings -+ * in these routines, not just make to make it faster or slower to match a -+ * particular CPU clock rate. -+ */ -+ -+static inline u32 -+bitbang_txrx_be_cpha0(struct spi_device *spi, -+ unsigned nsecs, unsigned cpol, -+ u32 word, u8 bits) -+{ -+ /* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */ -+ -+ /* clock starts at inactive polarity */ -+ for (word <<= (32 - bits); likely(bits); bits--) { -+ -+ /* setup MSB (to slave) on trailing edge */ -+ setmosi(spi, word & (1 << 31)); -+ spidelay(nsecs); /* T(setup) */ -+ -+ setsck(spi, !cpol); -+ spidelay(nsecs); -+ -+ /* sample MSB (from slave) on leading edge */ -+ word <<= 1; -+ word |= getmiso(spi); -+ setsck(spi, cpol); -+ } -+ return word; -+} -+ -+static inline u32 -+bitbang_txrx_be_cpha1(struct spi_device *spi, -+ unsigned nsecs, unsigned cpol, -+ u32 word, u8 bits) -+{ -+ /* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */ -+ -+ /* clock starts at inactive polarity */ -+ for (word <<= (32 - bits); likely(bits); bits--) { -+ -+ /* setup MSB (to slave) on leading edge */ -+ setsck(spi, !cpol); -+ setmosi(spi, word & (1 << 31)); -+ spidelay(nsecs); /* T(setup) */ -+ -+ setsck(spi, cpol); -+ spidelay(nsecs); -+ -+ /* sample MSB (from slave) on trailing edge */ -+ word <<= 1; -+ word |= getmiso(spi); -+ } -+ return word; -+} -+ -+#endif /* EXPAND_BITBANG_TXRX */ diff --git a/driver/spi-add-spi_butterfly-driver.patch b/driver/spi-add-spi_butterfly-driver.patch deleted file mode 100644 index 8fb9c9415bc5f..0000000000000 --- a/driver/spi-add-spi_butterfly-driver.patch +++ /dev/null @@ -1,527 +0,0 @@ -From akpm@osdl.org Wed Jan 11 13:11:44 2006 -Message-Id: <200601111924.k0BJO2bx003067@shell0.pdx.osdl.net> -From: David Brownell <david-b@pacbell.net> -Subject: SPI: add spi_butterfly driver -To: greg@kroah.com -Cc: akpm@osdl.org, david-b@pacbell.net -Date: Wed, 11 Jan 2006 11:23:49 -0800 - - -From: David Brownell <david-b@pacbell.net> - -This adds a bitbanging parport based adaptor cable for AVR Butterfly, giving -SPI links to its DataFlash chip and (eventually) firmware running in the card. - -Signed-off-by: Andrew Morton <akpm@osdl.org> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> ---- - Documentation/spi/butterfly | 57 +++++ - drivers/spi/Kconfig | 10 + - drivers/spi/spi_butterfly.c | 423 ++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 490 insertions(+) - ---- /dev/null -+++ gregkh-2.6/Documentation/spi/butterfly -@@ -0,0 +1,57 @@ -+spi_butterfly - parport-to-butterfly adapter driver -+=================================================== -+ -+This is a hardware and software project that includes building and using -+a parallel port adapter cable, together with an "AVR Butterfly" to run -+firmware for user interfacing and/or sensors. A Butterfly is a $US20 -+battery powered card with an AVR microcontroller and lots of goodies: -+sensors, LCD, flash, toggle stick, and more. You can use AVR-GCC to -+develop firmware for this, and flash it using this adapter cable. -+ -+You can make this adapter from an old printer cable and solder things -+directly to the Butterfly. Or (if you have the parts and skills) you -+can come up with something fancier, providing ciruit protection to the -+Butterfly and the printer port, or with a better power supply than two -+signal pins from the printer port. -+ -+ -+The first cable connections will hook Linux up to one SPI bus, with the -+AVR and a DataFlash chip; and to the AVR reset line. This is all you -+need to reflash the firmware, and the pins are the standard Atmel "ISP" -+connector pins (used also on non-Butterfly AVR boards). -+ -+ Signal Butterfly Parport (DB-25) -+ ------ --------- --------------- -+ SCK = J403.PB1/SCK = pin 2/D0 -+ RESET = J403.nRST = pin 3/D1 -+ VCC = J403.VCC_EXT = pin 8/D6 -+ MOSI = J403.PB2/MOSI = pin 9/D7 -+ MISO = J403.PB3/MISO = pin 11/S7,nBUSY -+ GND = J403.GND = pin 23/GND -+ -+Then to let Linux master that bus to talk to the DataFlash chip, you must -+(a) flash new firmware that disables SPI (set PRR.2, and disable pullups -+by clearing PORTB.[0-3]); (b) configure the mtd_dataflash driver; and -+(c) cable in the chipselect. -+ -+ Signal Butterfly Parport (DB-25) -+ ------ --------- --------------- -+ VCC = J400.VCC_EXT = pin 7/D5 -+ SELECT = J400.PB0/nSS = pin 17/C3,nSELECT -+ GND = J400.GND = pin 24/GND -+ -+The "USI" controller, using J405, can be used for a second SPI bus. That -+would let you talk to the AVR over SPI, running firmware that makes it act -+as an SPI slave, while letting either Linux or the AVR use the DataFlash. -+There are plenty of spare parport pins to wire this one up, such as: -+ -+ Signal Butterfly Parport (DB-25) -+ ------ --------- --------------- -+ SCK = J403.PE4/USCK = pin 5/D3 -+ MOSI = J403.PE5/DI = pin 6/D4 -+ MISO = J403.PE6/DO = pin 12/S5,nPAPEROUT -+ GND = J403.GND = pin 22/GND -+ -+ IRQ = J402.PF4 = pin 10/S6,ACK -+ GND = J402.GND(P2) = pin 25/GND -+ ---- gregkh-2.6.orig/drivers/spi/Kconfig -+++ gregkh-2.6/drivers/spi/Kconfig -@@ -75,6 +75,16 @@ config SPI_BUTTERFLY - inexpensive battery powered microcontroller evaluation board. - This same cable can be used to flash new firmware. - -+config SPI_BUTTERFLY -+ tristate "Parallel port adapter for AVR Butterfly (DEVELOPMENT)" -+ depends on SPI_MASTER && PARPORT && EXPERIMENTAL -+ select SPI_BITBANG -+ help -+ This uses a custom parallel port cable to connect to an AVR -+ Butterfly <http://www.atmel.com/products/avr/butterfly>, an -+ inexpensive battery powered microcontroller evaluation board. -+ This same cable can be used to flash new firmware. -+ - # - # Add new SPI master controllers in alphabetical order above this line - # ---- /dev/null -+++ gregkh-2.6/drivers/spi/spi_butterfly.c -@@ -0,0 +1,423 @@ -+/* -+ * spi_butterfly.c - parport-to-butterfly adapter -+ * -+ * Copyright (C) 2005 David Brownell -+ * -+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+#include <linux/config.h> -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/delay.h> -+#include <linux/platform_device.h> -+#include <linux/parport.h> -+ -+#include <linux/spi/spi.h> -+#include <linux/spi/spi_bitbang.h> -+#include <linux/spi/flash.h> -+ -+#include <linux/mtd/partitions.h> -+ -+ -+/* -+ * This uses SPI to talk with an "AVR Butterfly", which is a $US20 card -+ * with a battery powered AVR microcontroller and lots of goodies. You -+ * can use GCC to develop firmware for this. -+ * -+ * See Documentation/spi/butterfly for information about how to build -+ * and use this custom parallel port cable. -+ */ -+ -+#undef HAVE_USI /* nyet */ -+ -+ -+/* DATA output bits (pins 2..9 == D0..D7) */ -+#define butterfly_nreset (1 << 1) /* pin 3 */ -+ -+#define spi_sck_bit (1 << 0) /* pin 2 */ -+#define spi_mosi_bit (1 << 7) /* pin 9 */ -+ -+#define usi_sck_bit (1 << 3) /* pin 5 */ -+#define usi_mosi_bit (1 << 4) /* pin 6 */ -+ -+#define vcc_bits ((1 << 6) | (1 << 5)) /* pins 7, 8 */ -+ -+/* STATUS input bits */ -+#define spi_miso_bit PARPORT_STATUS_BUSY /* pin 11 */ -+ -+#define usi_miso_bit PARPORT_STATUS_PAPEROUT /* pin 12 */ -+ -+/* CONTROL output bits */ -+#define spi_cs_bit PARPORT_CONTROL_SELECT /* pin 17 */ -+/* USI uses no chipselect */ -+ -+ -+ -+static inline struct butterfly *spidev_to_pp(struct spi_device *spi) -+{ -+ return spi->controller_data; -+} -+ -+static inline int is_usidev(struct spi_device *spi) -+{ -+#ifdef HAVE_USI -+ return spi->chip_select != 1; -+#else -+ return 0; -+#endif -+} -+ -+ -+struct butterfly { -+ /* REVISIT ... for now, this must be first */ -+ struct spi_bitbang bitbang; -+ -+ struct parport *port; -+ struct pardevice *pd; -+ -+ u8 lastbyte; -+ -+ struct spi_device *dataflash; -+ struct spi_device *butterfly; -+ struct spi_board_info info[2]; -+ -+}; -+ -+/*----------------------------------------------------------------------*/ -+ -+/* -+ * these routines may be slower than necessary because they're hiding -+ * the fact that there are two different SPI busses on this cable: one -+ * to the DataFlash chip (or AVR SPI controller), the other to the -+ * AVR USI controller. -+ */ -+ -+static inline void -+setsck(struct spi_device *spi, int is_on) -+{ -+ struct butterfly *pp = spidev_to_pp(spi); -+ u8 bit, byte = pp->lastbyte; -+ -+ if (is_usidev(spi)) -+ bit = usi_sck_bit; -+ else -+ bit = spi_sck_bit; -+ -+ if (is_on) -+ byte |= bit; -+ else -+ byte &= ~bit; -+ parport_write_data(pp->port, byte); -+ pp->lastbyte = byte; -+} -+ -+static inline void -+setmosi(struct spi_device *spi, int is_on) -+{ -+ struct butterfly *pp = spidev_to_pp(spi); -+ u8 bit, byte = pp->lastbyte; -+ -+ if (is_usidev(spi)) -+ bit = usi_mosi_bit; -+ else -+ bit = spi_mosi_bit; -+ -+ if (is_on) -+ byte |= bit; -+ else -+ byte &= ~bit; -+ parport_write_data(pp->port, byte); -+ pp->lastbyte = byte; -+} -+ -+static inline int getmiso(struct spi_device *spi) -+{ -+ struct butterfly *pp = spidev_to_pp(spi); -+ int value; -+ u8 bit; -+ -+ if (is_usidev(spi)) -+ bit = usi_miso_bit; -+ else -+ bit = spi_miso_bit; -+ -+ /* only STATUS_BUSY is NOT negated */ -+ value = !(parport_read_status(pp->port) & bit); -+ return (bit == PARPORT_STATUS_BUSY) ? value : !value; -+} -+ -+static void butterfly_chipselect(struct spi_device *spi, int value) -+{ -+ struct butterfly *pp = spidev_to_pp(spi); -+ -+ /* set default clock polarity */ -+ if (value) -+ setsck(spi, spi->mode & SPI_CPOL); -+ -+ /* no chipselect on this USI link config */ -+ if (is_usidev(spi)) -+ return; -+ -+ /* here, value == "activate or not" */ -+ -+ /* most PARPORT_CONTROL_* bits are negated */ -+ if (spi_cs_bit == PARPORT_CONTROL_INIT) -+ value = !value; -+ -+ /* here, value == "bit value to write in control register" */ -+ -+ parport_frob_control(pp->port, spi_cs_bit, value ? spi_cs_bit : 0); -+} -+ -+ -+/* we only needed to implement one mode here, and choose SPI_MODE_0 */ -+ -+#define spidelay(X) do{}while(0) -+//#define spidelay ndelay -+ -+#define EXPAND_BITBANG_TXRX -+#include <linux/spi/spi_bitbang.h> -+ -+static u32 -+butterfly_txrx_word_mode0(struct spi_device *spi, -+ unsigned nsecs, -+ u32 word, u8 bits) -+{ -+ return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits); -+} -+ -+/*----------------------------------------------------------------------*/ -+ -+/* override default partitioning with cmdlinepart */ -+static struct mtd_partition partitions[] = { { -+ /* JFFS2 wants partitions of 4*N blocks for this device ... */ -+ -+ /* sector 0 = 8 pages * 264 bytes/page (1 block) -+ * sector 1 = 248 pages * 264 bytes/page -+ */ -+ .name = "bookkeeping", // 66 KB -+ .offset = 0, -+ .size = (8 + 248) * 264, -+// .mask_flags = MTD_WRITEABLE, -+}, { -+ /* sector 2 = 256 pages * 264 bytes/page -+ * sectors 3-5 = 512 pages * 264 bytes/page -+ */ -+ .name = "filesystem", // 462 KB -+ .offset = MTDPART_OFS_APPEND, -+ .size = MTDPART_SIZ_FULL, -+} }; -+ -+static struct flash_platform_data flash = { -+ .name = "butterflash", -+ .parts = partitions, -+ .nr_parts = ARRAY_SIZE(partitions), -+}; -+ -+ -+/* REVISIT remove this ugly global and its "only one" limitation */ -+static struct butterfly *butterfly; -+ -+static void butterfly_attach(struct parport *p) -+{ -+ struct pardevice *pd; -+ int status; -+ struct butterfly *pp; -+ struct spi_master *master; -+ struct platform_device *pdev; -+ -+ if (butterfly) -+ return; -+ -+ /* REVISIT: this just _assumes_ a butterfly is there ... no probe, -+ * and no way to be selective about what it binds to. -+ */ -+ -+ /* FIXME where should master->cdev.dev come from? -+ * e.g. /sys/bus/pnp0/00:0b, some PCI thing, etc -+ * setting up a platform device like this is an ugly kluge... -+ */ -+ pdev = platform_device_register_simple("butterfly", -1, NULL, 0); -+ -+ master = spi_alloc_master(&pdev->dev, sizeof *pp); -+ if (!master) { -+ status = -ENOMEM; -+ goto done; -+ } -+ pp = spi_master_get_devdata(master); -+ -+ /* -+ * SPI and bitbang hookup -+ * -+ * use default setup(), cleanup(), and transfer() methods; and -+ * only bother implementing mode 0. Start it later. -+ */ -+ master->bus_num = 42; -+ master->num_chipselect = 2; -+ -+ pp->bitbang.master = spi_master_get(master); -+ pp->bitbang.chipselect = butterfly_chipselect; -+ pp->bitbang.txrx_word[SPI_MODE_0] = butterfly_txrx_word_mode0; -+ -+ /* -+ * parport hookup -+ */ -+ pp->port = p; -+ pd = parport_register_device(p, "spi_butterfly", -+ NULL, NULL, NULL, -+ 0 /* FLAGS */, pp); -+ if (!pd) { -+ status = -ENOMEM; -+ goto clean0; -+ } -+ pp->pd = pd; -+ -+ status = parport_claim(pd); -+ if (status < 0) -+ goto clean1; -+ -+ /* -+ * Butterfly reset, powerup, run firmware -+ */ -+ pr_debug("%s: powerup/reset Butterfly\n", p->name); -+ -+ /* nCS for dataflash (this bit is inverted on output) */ -+ parport_frob_control(pp->port, spi_cs_bit, 0); -+ -+ /* stabilize power with chip in reset (nRESET), and -+ * both spi_sck_bit and usi_sck_bit clear (CPOL=0) -+ */ -+ pp->lastbyte |= vcc_bits; -+ parport_write_data(pp->port, pp->lastbyte); -+ msleep(5); -+ -+ /* take it out of reset; assume long reset delay */ -+ pp->lastbyte |= butterfly_nreset; -+ parport_write_data(pp->port, pp->lastbyte); -+ msleep(100); -+ -+ -+ /* -+ * Start SPI ... for now, hide that we're two physical busses. -+ */ -+ status = spi_bitbang_start(&pp->bitbang); -+ if (status < 0) -+ goto clean2; -+ -+ /* Bus 1 lets us talk to at45db041b (firmware disables AVR) -+ * or AVR (firmware resets at45, acts as spi slave) -+ */ -+ pp->info[0].max_speed_hz = 15 * 1000 * 1000; -+ strcpy(pp->info[0].modalias, "mtd_dataflash"); -+ pp->info[0].platform_data = &flash; -+ pp->info[0].chip_select = 1; -+ pp->info[0].controller_data = pp; -+ pp->dataflash = spi_new_device(pp->bitbang.master, &pp->info[0]); -+ if (pp->dataflash) -+ pr_debug("%s: dataflash at %s\n", p->name, -+ pp->dataflash->dev.bus_id); -+ -+#ifdef HAVE_USI -+ /* even more custom AVR firmware */ -+ pp->info[1].max_speed_hz = 10 /* ?? */ * 1000 * 1000; -+ strcpy(pp->info[1].modalias, "butterfly"); -+ // pp->info[1].platform_data = ... TBD ... ; -+ pp->info[1].chip_select = 2, -+ pp->info[1].controller_data = pp; -+ pp->butterfly = spi_new_device(pp->bitbang.master, &pp->info[1]); -+ if (pp->butterfly) -+ pr_debug("%s: butterfly at %s\n", p->name, -+ pp->butterfly->dev.bus_id); -+ -+ /* FIXME setup ACK for the IRQ line ... */ -+#endif -+ -+ // dev_info(_what?_, ...) -+ pr_info("%s: AVR Butterfly\n", p->name); -+ butterfly = pp; -+ return; -+ -+clean2: -+ /* turn off VCC */ -+ parport_write_data(pp->port, 0); -+ -+ parport_release(pp->pd); -+clean1: -+ parport_unregister_device(pd); -+clean0: -+ (void) spi_master_put(pp->bitbang.master); -+done: -+ platform_device_unregister(pdev); -+ pr_debug("%s: butterfly probe, fail %d\n", p->name, status); -+} -+ -+static void butterfly_detach(struct parport *p) -+{ -+ struct butterfly *pp; -+ struct platform_device *pdev; -+ int status; -+ -+ /* FIXME this global is ugly ... but, how to quickly get from -+ * the parport to the "struct butterfly" associated with it? -+ * "old school" driver-internal device lists? -+ */ -+ if (!butterfly || butterfly->port != p) -+ return; -+ pp = butterfly; -+ butterfly = NULL; -+ -+#ifdef HAVE_USI -+ spi_unregister_device(pp->butterfly); -+ pp->butterfly = NULL; -+#endif -+ spi_unregister_device(pp->dataflash); -+ pp->dataflash = NULL; -+ -+ status = spi_bitbang_stop(&pp->bitbang); -+ -+ /* turn off VCC */ -+ parport_write_data(pp->port, 0); -+ msleep(10); -+ -+ parport_release(pp->pd); -+ parport_unregister_device(pp->pd); -+ -+ pdev = to_platform_device(pp->bitbang.master->cdev.dev); -+ -+ (void) spi_master_put(pp->bitbang.master); -+ -+ platform_device_unregister(pdev); -+} -+ -+static struct parport_driver butterfly_driver = { -+ .name = "spi_butterfly", -+ .attach = butterfly_attach, -+ .detach = butterfly_detach, -+}; -+ -+ -+static int __init butterfly_init(void) -+{ -+ return parport_register_driver(&butterfly_driver); -+} -+device_initcall(butterfly_init); -+ -+static void __exit butterfly_exit(void) -+{ -+ parport_unregister_driver(&butterfly_driver); -+} -+module_exit(butterfly_exit); -+ -+MODULE_LICENSE("GPL"); diff --git a/driver/spi-add-spi_driver-to-spi-framework.patch b/driver/spi-add-spi_driver-to-spi-framework.patch deleted file mode 100644 index d9190bb43ff7a..0000000000000 --- a/driver/spi-add-spi_driver-to-spi-framework.patch +++ /dev/null @@ -1,553 +0,0 @@ -From akpm@osdl.org Sun Jan 8 13:37:31 2006 -From: akpm@osdl.org -Message-Id: <200601082134.k08LYZ5W004570@shell0.pdx.osdl.net> -Subject: [patch 04/10] spi: add spi_driver to SPI framework -To: greg@kroah.com -Cc: akpm@osdl.org, david-b@pacbell.net, dbrownell@users.sourceforge.net -Date: Sun, 08 Jan 2006 13:34:23 -0800 - - -From: David Brownell <david-b@pacbell.net> - -This is a refresh of the "Simple SPI Framework" found in 2.6.15-rc3-mm1 -which makes the following changes: - - * There's now a "struct spi_driver". This increase the footprint - of the core a bit, since it now includes code to do what the driver - core was previously handling directly. Documentation and comments - were updated to match. - - * spi_alloc_master() now does class_device_initialize(), so it can - at least be refcounted before spi_register_master(). To match, - spi_register_master() switched over to class_device_add(). - - * States explicitly that after transfer errors, spi_devices will be - deselected. We want fault recovery procedures to work the same - for all controller drivers. - - * Minor tweaks: controller_data no longer points to readonly data; - prevent some potential cast-from-null bugs with container_of calls; - clarifies some existing kerneldoc, - -And a few small cleanups. - -Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> -Signed-off-by: Andrew Morton <akpm@osdl.org> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> ---- - Documentation/spi/spi-summary | 52 +++++++++++------- - drivers/spi/spi.c | 118 ++++++++++++++++++++++++++++++------------ - include/linux/spi/spi.h | 75 ++++++++++++++++++-------- - 3 files changed, 170 insertions(+), 75 deletions(-) - ---- gregkh-2.6.orig/Documentation/spi/spi-summary -+++ gregkh-2.6/Documentation/spi/spi-summary -@@ -1,18 +1,19 @@ - Overview of Linux kernel SPI support - ==================================== - --22-Nov-2005 -+02-Dec-2005 - - What is SPI? - ------------ --The "Serial Peripheral Interface" (SPI) is a four-wire point-to-point --serial link used to connect microcontrollers to sensors and memory. -+The "Serial Peripheral Interface" (SPI) is a synchronous four wire serial -+link used to connect microcontrollers to sensors, memory, and peripherals. - - The three signal wires hold a clock (SCLK, often on the order of 10 MHz), - and parallel data lines with "Master Out, Slave In" (MOSI) or "Master In, - Slave Out" (MISO) signals. (Other names are also used.) There are four - clocking modes through which data is exchanged; mode-0 and mode-3 are most --commonly used. -+commonly used. Each clock cycle shifts data out and data in; the clock -+doesn't cycle except when there is data to shift. - - SPI masters may use a "chip select" line to activate a given SPI slave - device, so those three signal wires may be connected to several chips -@@ -79,11 +80,18 @@ The <linux/spi/spi.h> header file includ - main source code, and you should certainly read that. This is just - an overview, so you get the big picture before the details. - -+SPI requests always go into I/O queues. Requests for a given SPI device -+are always executed in FIFO order, and complete asynchronously through -+completion callbacks. There are also some simple synchronous wrappers -+for those calls, including ones for common transaction types like writing -+a command and then reading its response. -+ - There are two types of SPI driver, here called: - - Controller drivers ... these are often built in to System-On-Chip - processors, and often support both Master and Slave roles. - These drivers touch hardware registers and may use DMA. -+ Or they can be PIO bitbangers, needing just GPIO pins. - - Protocol drivers ... these pass messages through the controller - driver to communicate with a Slave or Master device on the -@@ -116,11 +124,6 @@ shows up in sysfs in several locations: - managing bus "B". All the spiB.* devices share the same - physical SPI bus segment, with SCLK, MOSI, and MISO. - --The basic I/O primitive submits an asynchronous message to an I/O queue --maintained by the controller driver. A completion callback is issued --asynchronously when the data transfer(s) in that message completes. --There are also some simple synchronous wrappers for those calls. -- - - How does board-specific init code declare SPI devices? - ------------------------------------------------------ -@@ -263,33 +266,40 @@ would just be another kernel driver, pro - access through aio_read(), aio_write(), and ioctl() calls and using the - standard userspace sysfs mechanisms to bind to a given SPI device. - --SPI protocol drivers are normal device drivers, with no more wrapper --than needed by platform devices: -+SPI protocol drivers somewhat resemble platform device drivers: -+ -+ static struct spi_driver CHIP_driver = { -+ .driver = { -+ .name = "CHIP", -+ .bus = &spi_bus_type, -+ .owner = THIS_MODULE, -+ }, - -- static struct device_driver CHIP_driver = { -- .name = "CHIP", -- .bus = &spi_bus_type, - .probe = CHIP_probe, -- .remove = __exit_p(CHIP_remove), -+ .remove = __devexit_p(CHIP_remove), - .suspend = CHIP_suspend, - .resume = CHIP_resume, - }; - --The SPI core will autmatically attempt to bind this driver to any SPI -+The driver core will autmatically attempt to bind this driver to any SPI - device whose board_info gave a modalias of "CHIP". Your probe() code - might look like this unless you're creating a class_device: - -- static int __init CHIP_probe(struct device *dev) -+ static int __devinit CHIP_probe(struct spi_device *spi) - { -- struct spi_device *spi = to_spi_device(dev); - struct CHIP *chip; -- struct CHIP_platform_data *pdata = dev->platform_data; -+ struct CHIP_platform_data *pdata; -+ -+ /* assuming the driver requires board-specific data: */ -+ pdata = &spi->dev.platform_data; -+ if (!pdata) -+ return -ENODEV; - - /* get memory for driver's per-chip state */ - chip = kzalloc(sizeof *chip, GFP_KERNEL); - if (!chip) - return -ENOMEM; -- dev_set_drvdata(dev, chip); -+ dev_set_drvdata(&spi->dev, chip); - - ... etc - return 0; -@@ -328,6 +338,8 @@ the driver guarantees that it won't subm - - The basic I/O primitive is spi_async(). Async requests may be - issued in any context (irq handler, task, etc) and completion - is reported using a callback provided with the message. -+ After any detected error, the chip is deselected and processing -+ of that spi_message is aborted. - - - There are also synchronous wrappers like spi_sync(), and wrappers - like spi_read(), spi_write(), and spi_write_then_read(). These ---- gregkh-2.6.orig/drivers/spi/spi.c -+++ gregkh-2.6/drivers/spi/spi.c -@@ -26,13 +26,9 @@ - #include <linux/spi/spi.h> - - --/* SPI bustype and spi_master class are registered during early boot, -- * usually before board init code provides the SPI device tables, and -- * are available later when driver init code needs them. -- * -- * Drivers for SPI devices started out like those for platform bus -- * devices. But both have changed in 2.6.15; maybe this should get -- * an "spi_driver" structure at some point (not currently needed) -+/* SPI bustype and spi_master class are registered after board init code -+ * provides the SPI device tables, ensuring that both are present by the -+ * time controller driver registration causes spi_devices to "enumerate". - */ - static void spidev_release(struct device *dev) - { -@@ -83,10 +79,7 @@ static int spi_uevent(struct device *dev - - #ifdef CONFIG_PM - --/* Suspend/resume in "struct device_driver" don't really need that -- * strange third parameter, so we just make it a constant and expect -- * SPI drivers to ignore it just like most platform drivers do. -- * -+/* - * NOTE: the suspend() method for an spi_master controller driver - * should verify that all its child devices are marked as suspended; - * suspend requests delivered through sysfs power/state files don't -@@ -94,13 +87,14 @@ static int spi_uevent(struct device *dev - */ - static int spi_suspend(struct device *dev, pm_message_t message) - { -- int value; -+ int value; -+ struct spi_driver *drv = to_spi_driver(dev->driver); - -- if (!dev->driver || !dev->driver->suspend) -+ if (!drv || !drv->suspend) - return 0; - - /* suspend will stop irqs and dma; no more i/o */ -- value = dev->driver->suspend(dev, message); -+ value = drv->suspend(to_spi_device(dev), message); - if (value == 0) - dev->power.power_state = message; - return value; -@@ -108,13 +102,14 @@ static int spi_suspend(struct device *de - - static int spi_resume(struct device *dev) - { -- int value; -+ int value; -+ struct spi_driver *drv = to_spi_driver(dev->driver); - -- if (!dev->driver || !dev->driver->resume) -+ if (!drv || !drv->resume) - return 0; - - /* resume may restart the i/o queue */ -- value = dev->driver->resume(dev); -+ value = drv->resume(to_spi_device(dev)); - if (value == 0) - dev->power.power_state = PMSG_ON; - return value; -@@ -135,6 +130,41 @@ struct bus_type spi_bus_type = { - }; - EXPORT_SYMBOL_GPL(spi_bus_type); - -+ -+static int spi_drv_probe(struct device *dev) -+{ -+ const struct spi_driver *sdrv = to_spi_driver(dev->driver); -+ -+ return sdrv->probe(to_spi_device(dev)); -+} -+ -+static int spi_drv_remove(struct device *dev) -+{ -+ const struct spi_driver *sdrv = to_spi_driver(dev->driver); -+ -+ return sdrv->remove(to_spi_device(dev)); -+} -+ -+static void spi_drv_shutdown(struct device *dev) -+{ -+ const struct spi_driver *sdrv = to_spi_driver(dev->driver); -+ -+ sdrv->shutdown(to_spi_device(dev)); -+} -+ -+int spi_register_driver(struct spi_driver *sdrv) -+{ -+ sdrv->driver.bus = &spi_bus_type; -+ if (sdrv->probe) -+ sdrv->driver.probe = spi_drv_probe; -+ if (sdrv->remove) -+ sdrv->driver.remove = spi_drv_remove; -+ if (sdrv->shutdown) -+ sdrv->driver.shutdown = spi_drv_shutdown; -+ return driver_register(&sdrv->driver); -+} -+EXPORT_SYMBOL_GPL(spi_register_driver); -+ - /*-------------------------------------------------------------------------*/ - - /* SPI devices should normally not be created by SPI device drivers; that -@@ -208,13 +238,15 @@ spi_new_device(struct spi_master *master - if (status < 0) { - dev_dbg(dev, "can't %s %s, status %d\n", - "add", proxy->dev.bus_id, status); --fail: -- class_device_put(&master->cdev); -- kfree(proxy); -- return NULL; -+ goto fail; - } - dev_dbg(dev, "registered child %s\n", proxy->dev.bus_id); - return proxy; -+ -+fail: -+ class_device_put(&master->cdev); -+ kfree(proxy); -+ return NULL; - } - EXPORT_SYMBOL_GPL(spi_new_device); - -@@ -237,11 +269,11 @@ spi_register_board_info(struct spi_board - { - struct boardinfo *bi; - -- bi = kmalloc (sizeof (*bi) + n * sizeof (*info), GFP_KERNEL); -+ bi = kmalloc(sizeof(*bi) + n * sizeof *info, GFP_KERNEL); - if (!bi) - return -ENOMEM; - bi->n_board_info = n; -- memcpy(bi->board_info, info, n * sizeof (*info)); -+ memcpy(bi->board_info, info, n * sizeof *info); - - down(&board_lock); - list_add_tail(&bi->list, &board_list); -@@ -330,6 +362,7 @@ spi_alloc_master(struct device *dev, uns - if (!master) - return NULL; - -+ class_device_initialize(&master->cdev); - master->cdev.class = &spi_master_class; - master->cdev.dev = get_device(dev); - class_set_devdata(&master->cdev, &master[1]); -@@ -366,7 +399,7 @@ spi_register_master(struct spi_master *m - /* convention: dynamically assigned bus IDs count down from the max */ - if (master->bus_num == 0) { - master->bus_num = atomic_dec_return(&dyn_bus_id); -- dynamic = 0; -+ dynamic = 1; - } - - /* register the device, then userspace will see it. -@@ -374,11 +407,9 @@ spi_register_master(struct spi_master *m - */ - snprintf(master->cdev.class_id, sizeof master->cdev.class_id, - "spi%u", master->bus_num); -- status = class_device_register(&master->cdev); -- if (status < 0) { -- class_device_put(&master->cdev); -+ status = class_device_add(&master->cdev); -+ if (status < 0) - goto done; -- } - dev_dbg(dev, "registered master %s%s\n", master->cdev.class_id, - dynamic ? " (dynamic)" : ""); - -@@ -491,6 +522,7 @@ static u8 *buf; - * This performs a half duplex MicroWire style transaction with the - * device, sending txbuf and then reading rxbuf. The return value - * is zero for success, else a negative errno status code. -+ * This call may only be used from a context that may sleep. - * - * Parameters to this routine are always copied using a small buffer, - * large transfers should use use spi_{async,sync}() calls with -@@ -553,16 +585,38 @@ EXPORT_SYMBOL_GPL(spi_write_then_read); - - static int __init spi_init(void) - { -+ int status; -+ - buf = kmalloc(SPI_BUFSIZ, SLAB_KERNEL); -- if (!buf) -- return -ENOMEM; -+ if (!buf) { -+ status = -ENOMEM; -+ goto err0; -+ } - -- bus_register(&spi_bus_type); -- class_register(&spi_master_class); -+ status = bus_register(&spi_bus_type); -+ if (status < 0) -+ goto err1; -+ -+ status = class_register(&spi_master_class); -+ if (status < 0) -+ goto err2; - return 0; -+ -+err2: -+ bus_unregister(&spi_bus_type); -+err1: -+ kfree(buf); -+ buf = NULL; -+err0: -+ return status; - } -+ - /* board_info is normally registered in arch_initcall(), - * but even essential drivers wait till later -+ * -+ * REVISIT only boardinfo really needs static linking. the rest (device and -+ * driver registration) _could_ be dynamically linked (modular) ... costs -+ * include needing to have boardinfo data structures be much more public. - */ - subsys_initcall(spi_init); - ---- gregkh-2.6.orig/include/linux/spi/spi.h -+++ gregkh-2.6/include/linux/spi/spi.h -@@ -20,13 +20,8 @@ - #define __LINUX_SPI_H - - /* -- * INTERFACES between SPI master drivers and infrastructure -+ * INTERFACES between SPI master-side drivers and SPI infrastructure. - * (There's no SPI slave support for Linux yet...) -- * -- * A "struct device_driver" for an spi_device uses "spi_bus_type" and -- * needs no special API wrappers (much like platform_bus). These drivers -- * are bound to devices based on their names (much like platform_bus), -- * and are available in dev->driver. - */ - extern struct bus_type spi_bus_type; - -@@ -46,8 +41,8 @@ extern struct bus_type spi_bus_type; - * @irq: Negative, or the number passed to request_irq() to receive - * interrupts from this device. - * @controller_state: Controller's runtime state -- * @controller_data: Static board-specific definitions for controller, such -- * as FIFO initialization parameters; from board_info.controller_data -+ * @controller_data: Board-specific definitions for controller, such as -+ * FIFO initialization parameters; from board_info.controller_data - * - * An spi_device is used to interchange data between an SPI slave - * (usually a discrete chip) and CPU memory. -@@ -63,31 +58,32 @@ struct spi_device { - u32 max_speed_hz; - u8 chip_select; - u8 mode; --#define SPI_CPHA 0x01 /* clock phase */ --#define SPI_CPOL 0x02 /* clock polarity */ -+#define SPI_CPHA 0x01 /* clock phase */ -+#define SPI_CPOL 0x02 /* clock polarity */ - #define SPI_MODE_0 (0|0) --#define SPI_MODE_1 (0|SPI_CPHA) -+#define SPI_MODE_1 (0|SPI_CPHA) /* (original MicroWire) */ - #define SPI_MODE_2 (SPI_CPOL|0) - #define SPI_MODE_3 (SPI_CPOL|SPI_CPHA) --#define SPI_CS_HIGH 0x04 /* chipselect active high? */ -+#define SPI_CS_HIGH 0x04 /* chipselect active high? */ - u8 bits_per_word; - int irq; - void *controller_state; -- const void *controller_data; -+ void *controller_data; - const char *modalias; - - // likely need more hooks for more protocol options affecting how -- // the controller talks to its chips, like: -+ // the controller talks to each chip, like: - // - bit order (default is wordwise msb-first) - // - memory packing (12 bit samples into low bits, others zeroed) - // - priority -+ // - drop chipselect after each word - // - chipselect delays - // - ... - }; - - static inline struct spi_device *to_spi_device(struct device *dev) - { -- return container_of(dev, struct spi_device, dev); -+ return dev ? container_of(dev, struct spi_device, dev) : NULL; - } - - /* most drivers won't need to care about device refcounting */ -@@ -117,12 +113,38 @@ static inline void spi_set_ctldata(struc - struct spi_message; - - -+ -+struct spi_driver { -+ int (*probe)(struct spi_device *spi); -+ int (*remove)(struct spi_device *spi); -+ void (*shutdown)(struct spi_device *spi); -+ int (*suspend)(struct spi_device *spi, pm_message_t mesg); -+ int (*resume)(struct spi_device *spi); -+ struct device_driver driver; -+}; -+ -+static inline struct spi_driver *to_spi_driver(struct device_driver *drv) -+{ -+ return drv ? container_of(drv, struct spi_driver, driver) : NULL; -+} -+ -+extern int spi_register_driver(struct spi_driver *sdrv); -+ -+static inline void spi_unregister_driver(struct spi_driver *sdrv) -+{ -+ if (!sdrv) -+ return; -+ driver_unregister(&sdrv->driver); -+} -+ -+ -+ - /** - * struct spi_master - interface to SPI master controller - * @cdev: class interface to this driver - * @bus_num: board-specific (and often SOC-specific) identifier for a - * given SPI controller. -- * @num_chipselects: chipselects are used to distinguish individual -+ * @num_chipselect: chipselects are used to distinguish individual - * SPI slaves, and are numbered from zero to num_chipselects. - * each slave has a chipselect signal, but it's common that not - * every chipselect is connected to a slave. -@@ -275,7 +297,8 @@ struct spi_transfer { - * addresses for each transfer buffer - * @complete: called to report transaction completions - * @context: the argument to complete() when it's called -- * @actual_length: how many bytes were transferd -+ * @actual_length: the total number of bytes that were transferred in all -+ * successful segments - * @status: zero for success, else negative errno - * @queue: for use by whichever driver currently owns the message - * @state: for use by whichever driver currently owns the message -@@ -295,7 +318,7 @@ struct spi_message { - * - * Some controller drivers (message-at-a-time queue processing) - * could provide that as their default scheduling algorithm. But -- * others (with multi-message pipelines) would need a flag to -+ * others (with multi-message pipelines) could need a flag to - * tell them about such special cases. - */ - -@@ -346,6 +369,13 @@ spi_setup(struct spi_device *spi) - * FIFO order, messages may go to different devices in other orders. - * Some device might be higher priority, or have various "hard" access - * time requirements, for example. -+ * -+ * On detection of any fault during the transfer, processing of -+ * the entire message is aborted, and the device is deselected. -+ * Until returning from the associated message completion callback, -+ * no other spi_message queued to that device will be processed. -+ * (This rule applies equally to all the synchronous transfer calls, -+ * which are wrappers around this core asynchronous primitive.) - */ - static inline int - spi_async(struct spi_device *spi, struct spi_message *message) -@@ -484,12 +514,12 @@ struct spi_board_info { - * "modalias" is normally the driver name. - * - * platform_data goes to spi_device.dev.platform_data, -- * controller_data goes to spi_device.platform_data, -+ * controller_data goes to spi_device.controller_data, - * irq is copied too - */ - char modalias[KOBJ_NAME_LEN]; - const void *platform_data; -- const void *controller_data; -+ void *controller_data; - int irq; - - /* slower signaling on noisy or low voltage boards */ -@@ -525,9 +555,8 @@ spi_register_board_info(struct spi_board - - - /* If you're hotplugging an adapter with devices (parport, usb, etc) -- * use spi_new_device() to describe each device. You can also call -- * spi_unregister_device() to get start making that device vanish, -- * but normally that would be handled by spi_unregister_master(). -+ * use spi_new_device() to describe each device. You would then call -+ * spi_unregister_device() to start making that device vanish. - */ - extern struct spi_device * - spi_new_device(struct spi_master *, struct spi_board_info *); diff --git a/driver/spi-ads7836-uses-spi_driver.patch b/driver/spi-ads7836-uses-spi_driver.patch deleted file mode 100644 index 1571b77b584ed..0000000000000 --- a/driver/spi-ads7836-uses-spi_driver.patch +++ /dev/null @@ -1,237 +0,0 @@ -From akpm@osdl.org Sun Jan 8 13:39:04 2006 -From: akpm@osdl.org -Message-Id: <200601082134.k08LYbkH004576@shell0.pdx.osdl.net> -Subject: [patch 06/10] spi: ads7836 uses spi_driver -To: greg@kroah.com -Cc: akpm@osdl.org, david-b@pacbell.net, dbrownell@users.sourceforge.net -Date: Sun, 08 Jan 2006 13:34:25 -0800 - - -From: David Brownell <david-b@pacbell.net> - -This updates the ads7864 driver to use the new "spi_driver" struct, and -includes some minor unrelated cleanup. - -Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> -Signed-off-by: Andrew Morton <akpm@osdl.org> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> ---- - drivers/input/touchscreen/ads7846.c | 84 ++++++++++++++++++------------------ - include/linux/spi/ads7846.h | 2 - 2 files changed, 43 insertions(+), 43 deletions(-) - ---- gregkh-2.6.orig/drivers/input/touchscreen/ads7846.c -+++ gregkh-2.6/drivers/input/touchscreen/ads7846.c -@@ -345,19 +345,15 @@ static irqreturn_t ads7846_irq(int irq, - - /*--------------------------------------------------------------------------*/ - --/* non-empty "extra" is needed before 2.6.14-git5 or so */ --#define EXTRA // , u32 level --#define EXTRA2 // , 0 -- - static int --ads7846_suspend(struct device *dev, pm_message_t message EXTRA) -+ads7846_suspend(struct spi_device *spi, pm_message_t message) - { -- struct ads7846 *ts = dev_get_drvdata(dev); -+ struct ads7846 *ts = dev_get_drvdata(&spi->dev); - unsigned long flags; - - spin_lock_irqsave(&ts->lock, flags); - -- ts->spi->dev.power.power_state = message; -+ spi->dev.power.power_state = message; - - /* are we waiting for IRQ, or polling? */ - if (!ts->pendown) { -@@ -387,36 +383,35 @@ ads7846_suspend(struct device *dev, pm_m - return 0; - } - --static int ads7846_resume(struct device *dev EXTRA) -+static int ads7846_resume(struct spi_device *spi) - { -- struct ads7846 *ts = dev_get_drvdata(dev); -+ struct ads7846 *ts = dev_get_drvdata(&spi->dev); - - ts->irq_disabled = 0; - enable_irq(ts->spi->irq); -- dev->power.power_state = PMSG_ON; -+ spi->dev.power.power_state = PMSG_ON; - return 0; - } - --static int __init ads7846_probe(struct device *dev) -+static int __devinit ads7846_probe(struct spi_device *spi) - { -- struct spi_device *spi = to_spi_device(dev); - struct ads7846 *ts; -- struct ads7846_platform_data *pdata = dev->platform_data; -+ struct ads7846_platform_data *pdata = spi->dev.platform_data; - struct spi_transfer *x; - - if (!spi->irq) { -- dev_dbg(dev, "no IRQ?\n"); -+ dev_dbg(&spi->dev, "no IRQ?\n"); - return -ENODEV; - } - - if (!pdata) { -- dev_dbg(dev, "no platform data?\n"); -+ dev_dbg(&spi->dev, "no platform data?\n"); - return -ENODEV; - } - - /* don't exceed max specified sample rate */ - if (spi->max_speed_hz > (125000 * 16)) { -- dev_dbg(dev, "f(sample) %d KHz?\n", -+ dev_dbg(&spi->dev, "f(sample) %d KHz?\n", - (spi->max_speed_hz/16)/1000); - return -EINVAL; - } -@@ -430,7 +425,7 @@ static int __init ads7846_probe(struct d - if (!(ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL))) - return -ENOMEM; - -- dev_set_drvdata(dev, ts); -+ dev_set_drvdata(&spi->dev, ts); - - ts->spi = spi; - spi->dev.power.power_state = PMSG_ON; -@@ -445,9 +440,9 @@ static int __init ads7846_probe(struct d - - init_input_dev(&ts->input); - -- ts->input.dev = dev; -+ ts->input.dev = &spi->dev; - ts->input.name = "ADS784x Touchscreen"; -- snprintf(ts->phys, sizeof ts->phys, "%s/input0", dev->bus_id); -+ snprintf(ts->phys, sizeof ts->phys, "%s/input0", spi->dev.bus_id); - ts->input.phys = ts->phys; - - ts->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); -@@ -511,65 +506,68 @@ static int __init ads7846_probe(struct d - ts->msg.context = ts; - - if (request_irq(spi->irq, ads7846_irq, SA_SAMPLE_RANDOM, -- dev->bus_id, ts)) { -- dev_dbg(dev, "irq %d busy?\n", spi->irq); -+ spi->dev.bus_id, ts)) { -+ dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); - input_unregister_device(&ts->input); - kfree(ts); - return -EBUSY; - } - set_irq_type(spi->irq, IRQT_FALLING); - -- dev_info(dev, "touchscreen, irq %d\n", spi->irq); -+ dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq); - - /* take a first sample, leaving nPENIRQ active; avoid - * the touchscreen, in case it's not connected. - */ -- (void) ads7846_read12_ser(dev, -+ (void) ads7846_read12_ser(&spi->dev, - READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON); - - /* ads7843/7845 don't have temperature sensors, and - * use the other sensors a bit differently too - */ - if (ts->model == 7846) { -- device_create_file(dev, &dev_attr_temp0); -- device_create_file(dev, &dev_attr_temp1); -+ device_create_file(&spi->dev, &dev_attr_temp0); -+ device_create_file(&spi->dev, &dev_attr_temp1); - } - if (ts->model != 7845) -- device_create_file(dev, &dev_attr_vbatt); -- device_create_file(dev, &dev_attr_vaux); -+ device_create_file(&spi->dev, &dev_attr_vbatt); -+ device_create_file(&spi->dev, &dev_attr_vaux); - - return 0; - } - --static int __exit ads7846_remove(struct device *dev) -+static int __devexit ads7846_remove(struct spi_device *spi) - { -- struct ads7846 *ts = dev_get_drvdata(dev); -+ struct ads7846 *ts = dev_get_drvdata(&spi->dev); - -- ads7846_suspend(dev, PMSG_SUSPEND EXTRA2); -+ ads7846_suspend(spi, PMSG_SUSPEND); - free_irq(ts->spi->irq, ts); - if (ts->irq_disabled) - enable_irq(ts->spi->irq); - - if (ts->model == 7846) { -- device_remove_file(dev, &dev_attr_temp0); -- device_remove_file(dev, &dev_attr_temp1); -+ device_remove_file(&spi->dev, &dev_attr_temp0); -+ device_remove_file(&spi->dev, &dev_attr_temp1); - } - if (ts->model != 7845) -- device_remove_file(dev, &dev_attr_vbatt); -- device_remove_file(dev, &dev_attr_vaux); -+ device_remove_file(&spi->dev, &dev_attr_vbatt); -+ device_remove_file(&spi->dev, &dev_attr_vaux); - - input_unregister_device(&ts->input); - kfree(ts); - -- dev_dbg(dev, "unregistered touchscreen\n"); -+ dev_dbg(&spi->dev, "unregistered touchscreen\n"); - return 0; - } - --static struct device_driver ads7846_driver = { -- .name = "ads7846", -- .bus = &spi_bus_type, -+static struct spi_driver ads7846_driver = { -+ .driver = { -+ .name = "ads7846", -+ .bus = &spi_bus_type, -+ .owner = THIS_MODULE, -+ }, - .probe = ads7846_probe, -- .remove = __exit_p(ads7846_remove), -+ .remove = __devexit_p(ads7846_remove), - .suspend = ads7846_suspend, - .resume = ads7846_resume, - }; -@@ -594,18 +592,20 @@ static int __init ads7846_init(void) - // PXA: - // also Dell Axim X50 - // also HP iPaq H191x/H192x/H415x/H435x -- // also Intel Lubbock (alternate to UCB1400) -+ // also Intel Lubbock (additional to UCB1400; as temperature sensor) - // also Sharp Zaurus C7xx, C8xx (corgi/sheperd/husky) - -+ // Atmel at91sam9261-EK uses ads7843 -+ - // also various AMD Au1x00 devel boards - -- return driver_register(&ads7846_driver); -+ return spi_register_driver(&ads7846_driver); - } - module_init(ads7846_init); - - static void __exit ads7846_exit(void) - { -- driver_unregister(&ads7846_driver); -+ spi_unregister_driver(&ads7846_driver); - - #ifdef CONFIG_ARCH_OMAP - if (machine_is_omap_osk()) { ---- gregkh-2.6.orig/include/linux/spi/ads7846.h -+++ gregkh-2.6/include/linux/spi/ads7846.h -@@ -1,7 +1,7 @@ - /* linux/spi/ads7846.h */ - - /* Touchscreen characteristics vary between boards and models. The -- * platform_data for the device's "struct device" holts this information. -+ * platform_data for the device's "struct device" holds this information. - * - * It's OK if the min/max values are zero. - */ diff --git a/driver/spi-ads7846-driver.patch b/driver/spi-ads7846-driver.patch deleted file mode 100644 index 7dda097d803f9..0000000000000 --- a/driver/spi-ads7846-driver.patch +++ /dev/null @@ -1,734 +0,0 @@ -From akpm@osdl.org Sun Jan 8 13:37:01 2006 -From: akpm@osdl.org -Message-Id: <200601082134.k08LYWLu004559@shell0.pdx.osdl.net> -Subject: [patch 02/10] spi: ads7846 driver -To: greg@kroah.com -Cc: akpm@osdl.org, david-b@pacbell.net -Date: Sun, 08 Jan 2006 13:34:21 -0800 - - -From: David Brownell <david-b@pacbell.net> - -This is a driver for the ADS7846 touchscreen sensor, derived from -the corgi_ts and omap_ts drivers. Key differences from those two: - - - Uses the new SPI framework (minimalist version) - - <linux/spi/ads7846.h> abstracts board-specific touchscreen info - - Sysfs attributes for the temperature and voltage sensors - - Uses fewer ARM-specific IRQ primitives - -The temperature and voltage sensors show up in sysfs like this: - - $ pwd - /sys/devices/platform/omap-uwire/spi2.0 - $ ls - bus@ input:event0@ power/ temp1 vbatt - driver@ modalias temp0 vaux - $ cat modalias - ads7846 - $ cat temp0 - 991 - $ cat temp1 - 1177 - $ - -So far only basic testing has been done. There's a fair amount of hardware -that uses this sensor, and which also runs Linux, which should eventually -be able to use this driver. - -One portability note may be of special interest. It turns out that not all -SPI controllers are happy issuing requests that do things like "write 8 bit -command, read 12 bit response". Most of them seem happy to handle various -word sizes, so the issue isn't "12 bit response" but rather "different rx -and tx write sizes", despite that being a common MicroWire convention. So -this version of the driver no longer reads 12 bit native-endian words; it -reads 16-bit big-endian responses, then byteswaps them and shifts the -results to discard the noise. - -Signed-off-by: David Brownell <david-b@pacbell.net> -Signed-off-by: Andrew Morton <akpm@osdl.org> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> ---- - drivers/input/touchscreen/Kconfig | 13 - drivers/input/touchscreen/Makefile | 1 - drivers/input/touchscreen/ads7846.c | 621 ++++++++++++++++++++++++++++++++++++ - include/linux/spi/ads7846.h | 18 + - 4 files changed, 653 insertions(+) - ---- /dev/null -+++ gregkh-2.6/drivers/input/touchscreen/ads7846.c -@@ -0,0 +1,621 @@ -+/* -+ * ADS7846 based touchscreen and sensor driver -+ * -+ * Copyright (c) 2005 David Brownell -+ * -+ * Using code from: -+ * - corgi_ts.c -+ * Copyright (C) 2004-2005 Richard Purdie -+ * - omap_ts.[hc], ads7846.h, ts_osk.c -+ * Copyright (C) 2002 MontaVista Software -+ * Copyright (C) 2004 Texas Instruments -+ * Copyright (C) 2005 Dirk Behme -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+#include <linux/device.h> -+#include <linux/init.h> -+#include <linux/delay.h> -+#include <linux/input.h> -+#include <linux/interrupt.h> -+#include <linux/slab.h> -+#include <linux/spi/spi.h> -+#include <linux/spi/ads7846.h> -+ -+#ifdef CONFIG_ARM -+#include <asm/mach-types.h> -+#ifdef CONFIG_ARCH_OMAP -+#include <asm/arch/gpio.h> -+#endif -+ -+#else -+#define set_irq_type(irq,type) do{}while(0) -+#endif -+ -+ -+/* -+ * This code has been lightly tested on an ads7846. -+ * Support for ads7843 and ads7845 has only been stubbed in. -+ * -+ * Not yet done: investigate the values reported. Are x/y/pressure -+ * event values sane enough for X11? How accurate are the temperature -+ * and voltage readings? (System-specific calibration should support -+ * accuracy of 0.3 degrees C; otherwise it's 2.0 degrees.) -+ * -+ * app note sbaa036 talks in more detail about accurate sampling... -+ * that ought to help in situations like LCDs inducing noise (which -+ * can also be helped by using synch signals) and more generally. -+ */ -+ -+#define TS_POLL_PERIOD msecs_to_jiffies(10) -+ -+struct ts_event { -+ /* For portability, we can't read 12 bit values using SPI (which -+ * would make the controller deliver them as native byteorder u16 -+ * with msbs zeroed). Instead, we read them as two 8-byte values, -+ * which need byteswapping then range adjustment. -+ */ -+ __be16 x; -+ __be16 y; -+ __be16 z1, z2; -+}; -+ -+struct ads7846 { -+ struct input_dev input; -+ char phys[32]; -+ -+ struct spi_device *spi; -+ u16 model; -+ u16 vref_delay_usecs; -+ u16 x_plate_ohms; -+ -+ struct ts_event tc; -+ -+ struct spi_transfer xfer[8]; -+ struct spi_message msg; -+ -+ spinlock_t lock; -+ struct timer_list timer; /* P: lock */ -+ unsigned pendown:1; /* P: lock */ -+ unsigned pending:1; /* P: lock */ -+// FIXME remove "irq_disabled" -+ unsigned irq_disabled:1; /* P: lock */ -+}; -+ -+/* leave chip selected when we're done, for quicker re-select? */ -+#if 0 -+#define CS_CHANGE(xfer) ((xfer).cs_change = 1) -+#else -+#define CS_CHANGE(xfer) ((xfer).cs_change = 0) -+#endif -+ -+/*--------------------------------------------------------------------------*/ -+ -+/* The ADS7846 has touchscreen and other sensors. -+ * Earlier ads784x chips are somewhat compatible. -+ */ -+#define ADS_START (1 << 7) -+#define ADS_A2A1A0_d_y (1 << 4) /* differential */ -+#define ADS_A2A1A0_d_z1 (3 << 4) /* differential */ -+#define ADS_A2A1A0_d_z2 (4 << 4) /* differential */ -+#define ADS_A2A1A0_d_x (5 << 4) /* differential */ -+#define ADS_A2A1A0_temp0 (0 << 4) /* non-differential */ -+#define ADS_A2A1A0_vbatt (2 << 4) /* non-differential */ -+#define ADS_A2A1A0_vaux (6 << 4) /* non-differential */ -+#define ADS_A2A1A0_temp1 (7 << 4) /* non-differential */ -+#define ADS_8_BIT (1 << 3) -+#define ADS_12_BIT (0 << 3) -+#define ADS_SER (1 << 2) /* non-differential */ -+#define ADS_DFR (0 << 2) /* differential */ -+#define ADS_PD10_PDOWN (0 << 0) /* lowpower mode + penirq */ -+#define ADS_PD10_ADC_ON (1 << 0) /* ADC on */ -+#define ADS_PD10_REF_ON (2 << 0) /* vREF on + penirq */ -+#define ADS_PD10_ALL_ON (3 << 0) /* ADC + vREF on */ -+ -+#define MAX_12BIT ((1<<12)-1) -+ -+/* leave ADC powered up (disables penirq) between differential samples */ -+#define READ_12BIT_DFR(x) (ADS_START | ADS_A2A1A0_d_ ## x \ -+ | ADS_12_BIT | ADS_DFR) -+ -+static const u8 read_y = READ_12BIT_DFR(y) | ADS_PD10_ADC_ON; -+static const u8 read_z1 = READ_12BIT_DFR(z1) | ADS_PD10_ADC_ON; -+static const u8 read_z2 = READ_12BIT_DFR(z2) | ADS_PD10_ADC_ON; -+static const u8 read_x = READ_12BIT_DFR(x) | ADS_PD10_PDOWN; /* LAST */ -+ -+/* single-ended samples need to first power up reference voltage; -+ * we leave both ADC and VREF powered -+ */ -+#define READ_12BIT_SER(x) (ADS_START | ADS_A2A1A0_ ## x \ -+ | ADS_12_BIT | ADS_SER) -+ -+static const u8 ref_on = READ_12BIT_DFR(x) | ADS_PD10_ALL_ON; -+static const u8 ref_off = READ_12BIT_DFR(y) | ADS_PD10_PDOWN; -+ -+/*--------------------------------------------------------------------------*/ -+ -+/* -+ * Non-touchscreen sensors only use single-ended conversions. -+ */ -+ -+struct ser_req { -+ u8 command; -+ u16 scratch; -+ __be16 sample; -+ struct spi_message msg; -+ struct spi_transfer xfer[6]; -+}; -+ -+static int ads7846_read12_ser(struct device *dev, unsigned command) -+{ -+ struct spi_device *spi = to_spi_device(dev); -+ struct ads7846 *ts = dev_get_drvdata(dev); -+ struct ser_req *req = kzalloc(sizeof *req, SLAB_KERNEL); -+ int status; -+ int sample; -+ -+ if (!req) -+ return -ENOMEM; -+ -+ /* activate reference, so it has time to settle; */ -+ req->xfer[0].tx_buf = &ref_on; -+ req->xfer[0].len = 1; -+ req->xfer[1].rx_buf = &req->scratch; -+ req->xfer[1].len = 2; -+ -+ /* -+ * for external VREF, 0 usec (and assume it's always on); -+ * for 1uF, use 800 usec; -+ * no cap, 100 usec. -+ */ -+ req->xfer[1].delay_usecs = ts->vref_delay_usecs; -+ -+ /* take sample */ -+ req->command = (u8) command; -+ req->xfer[2].tx_buf = &req->command; -+ req->xfer[2].len = 1; -+ req->xfer[3].rx_buf = &req->sample; -+ req->xfer[3].len = 2; -+ -+ /* REVISIT: take a few more samples, and compare ... */ -+ -+ /* turn off reference */ -+ req->xfer[4].tx_buf = &ref_off; -+ req->xfer[4].len = 1; -+ req->xfer[5].rx_buf = &req->scratch; -+ req->xfer[5].len = 2; -+ -+ CS_CHANGE(req->xfer[5]); -+ -+ /* group all the transfers together, so we can't interfere with -+ * reading touchscreen state; disable penirq while sampling -+ */ -+ req->msg.transfers = req->xfer; -+ req->msg.n_transfer = 6; -+ -+ disable_irq(spi->irq); -+ status = spi_sync(spi, &req->msg); -+ enable_irq(spi->irq); -+ -+ if (req->msg.status) -+ status = req->msg.status; -+ sample = be16_to_cpu(req->sample); -+ sample = sample >> 4; -+ kfree(req); -+ -+ return status ? status : sample; -+} -+ -+#define SHOW(name) static ssize_t \ -+name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \ -+{ \ -+ ssize_t v = ads7846_read12_ser(dev, \ -+ READ_12BIT_SER(name) | ADS_PD10_ALL_ON); \ -+ if (v < 0) \ -+ return v; \ -+ return sprintf(buf, "%u\n", (unsigned) v); \ -+} \ -+static DEVICE_ATTR(name, S_IRUGO, name ## _show, NULL); -+ -+SHOW(temp0) -+SHOW(temp1) -+SHOW(vaux) -+SHOW(vbatt) -+ -+/*--------------------------------------------------------------------------*/ -+ -+/* -+ * PENIRQ only kicks the timer. The timer only reissues the SPI transfer, -+ * to retrieve touchscreen status. -+ * -+ * The SPI transfer completion callback does the real work. It reports -+ * touchscreen events and reactivates the timer (or IRQ) as appropriate. -+ */ -+ -+static void ads7846_rx(void *ads) -+{ -+ struct ads7846 *ts = ads; -+ unsigned Rt; -+ unsigned sync = 0; -+ u16 x, y, z1, z2; -+ unsigned long flags; -+ -+ /* adjust: 12 bit samples (left aligned), built from -+ * two 8 bit values writen msb-first. -+ */ -+ x = be16_to_cpu(ts->tc.x) >> 4; -+ y = be16_to_cpu(ts->tc.y) >> 4; -+ z1 = be16_to_cpu(ts->tc.z1) >> 4; -+ z2 = be16_to_cpu(ts->tc.z2) >> 4; -+ -+ /* range filtering */ -+ if (x == MAX_12BIT) -+ x = 0; -+ -+ if (x && z1 && ts->spi->dev.power.power_state.event == PM_EVENT_ON) { -+ /* compute touch pressure resistance using equation #2 */ -+ Rt = z2; -+ Rt -= z1; -+ Rt *= x; -+ Rt *= ts->x_plate_ohms; -+ Rt /= z1; -+ Rt = (Rt + 2047) >> 12; -+ } else -+ Rt = 0; -+ -+ /* NOTE: "pendown" is inferred from pressure; we don't rely on -+ * being able to check nPENIRQ status, or "friendly" trigger modes -+ * (both-edges is much better than just-falling or low-level). -+ * -+ * REVISIT: some boards may require reading nPENIRQ; it's -+ * needed on 7843. and 7845 reads pressure differently... -+ * -+ * REVISIT: the touchscreen might not be connected; this code -+ * won't notice that, even if nPENIRQ never fires ... -+ */ -+ if (!ts->pendown && Rt != 0) { -+ input_report_key(&ts->input, BTN_TOUCH, 1); -+ sync = 1; -+ } else if (ts->pendown && Rt == 0) { -+ input_report_key(&ts->input, BTN_TOUCH, 0); -+ sync = 1; -+ } -+ -+ if (Rt) { -+ input_report_abs(&ts->input, ABS_X, x); -+ input_report_abs(&ts->input, ABS_Y, y); -+ input_report_abs(&ts->input, ABS_PRESSURE, Rt); -+ sync = 1; -+ } -+ if (sync) -+ input_sync(&ts->input); -+ -+#ifdef VERBOSE -+ if (Rt || ts->pendown) -+ pr_debug("%s: %d/%d/%d%s\n", ts->spi->dev.bus_id, -+ x, y, Rt, Rt ? "" : " UP"); -+#endif -+ -+ /* don't retrigger while we're suspended */ -+ spin_lock_irqsave(&ts->lock, flags); -+ -+ ts->pendown = (Rt != 0); -+ ts->pending = 0; -+ -+ if (ts->spi->dev.power.power_state.event == PM_EVENT_ON) { -+ if (ts->pendown) -+ mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD); -+ else if (ts->irq_disabled) { -+ ts->irq_disabled = 0; -+ enable_irq(ts->spi->irq); -+ } -+ } -+ -+ spin_unlock_irqrestore(&ts->lock, flags); -+} -+ -+static void ads7846_timer(unsigned long handle) -+{ -+ struct ads7846 *ts = (void *)handle; -+ int status = 0; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&ts->lock, flags); -+ if (!ts->pending) { -+ ts->pending = 1; -+ if (!ts->irq_disabled) { -+ ts->irq_disabled = 1; -+ disable_irq(ts->spi->irq); -+ } -+ status = spi_async(ts->spi, &ts->msg); -+ if (status) -+ dev_err(&ts->spi->dev, "spi_async --> %d\n", -+ status); -+ } -+ spin_unlock_irqrestore(&ts->lock, flags); -+} -+ -+static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs) -+{ -+ ads7846_timer((unsigned long) handle); -+ return IRQ_HANDLED; -+} -+ -+/*--------------------------------------------------------------------------*/ -+ -+/* non-empty "extra" is needed before 2.6.14-git5 or so */ -+#define EXTRA // , u32 level -+#define EXTRA2 // , 0 -+ -+static int -+ads7846_suspend(struct device *dev, pm_message_t message EXTRA) -+{ -+ struct ads7846 *ts = dev_get_drvdata(dev); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&ts->lock, flags); -+ -+ ts->spi->dev.power.power_state = message; -+ -+ /* are we waiting for IRQ, or polling? */ -+ if (!ts->pendown) { -+ if (!ts->irq_disabled) { -+ ts->irq_disabled = 1; -+ disable_irq(ts->spi->irq); -+ } -+ } else { -+ /* polling; force a final SPI completion; -+ * that will clean things up neatly -+ */ -+ if (!ts->pending) -+ mod_timer(&ts->timer, jiffies); -+ -+ while (ts->pendown || ts->pending) { -+ spin_unlock_irqrestore(&ts->lock, flags); -+ udelay(10); -+ spin_lock_irqsave(&ts->lock, flags); -+ } -+ } -+ -+ /* we know the chip's in lowpower mode since we always -+ * leave it that way after every request -+ */ -+ -+ spin_unlock_irqrestore(&ts->lock, flags); -+ return 0; -+} -+ -+static int ads7846_resume(struct device *dev EXTRA) -+{ -+ struct ads7846 *ts = dev_get_drvdata(dev); -+ -+ ts->irq_disabled = 0; -+ enable_irq(ts->spi->irq); -+ dev->power.power_state = PMSG_ON; -+ return 0; -+} -+ -+static int __init ads7846_probe(struct device *dev) -+{ -+ struct spi_device *spi = to_spi_device(dev); -+ struct ads7846 *ts; -+ struct ads7846_platform_data *pdata = dev->platform_data; -+ struct spi_transfer *x; -+ -+ if (!spi->irq) { -+ dev_dbg(dev, "no IRQ?\n"); -+ return -ENODEV; -+ } -+ -+ if (!pdata) { -+ dev_dbg(dev, "no platform data?\n"); -+ return -ENODEV; -+ } -+ -+ /* don't exceed max specified sample rate */ -+ if (spi->max_speed_hz > (125000 * 16)) { -+ dev_dbg(dev, "f(sample) %d KHz?\n", -+ (spi->max_speed_hz/16)/1000); -+ return -EINVAL; -+ } -+ -+ /* We'd set the wordsize to 12 bits ... except that some controllers -+ * will then treat the 8 bit command words as 12 bits (and drop the -+ * four MSBs of the 12 bit result). Result: inputs must be shifted -+ * to discard the four garbage LSBs. -+ */ -+ -+ if (!(ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL))) -+ return -ENOMEM; -+ -+ dev_set_drvdata(dev, ts); -+ -+ ts->spi = spi; -+ spi->dev.power.power_state = PMSG_ON; -+ -+ init_timer(&ts->timer); -+ ts->timer.data = (unsigned long) ts; -+ ts->timer.function = ads7846_timer; -+ -+ ts->model = pdata->model ? : 7846; -+ ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100; -+ ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; -+ -+ init_input_dev(&ts->input); -+ -+ ts->input.dev = dev; -+ ts->input.name = "ADS784x Touchscreen"; -+ snprintf(ts->phys, sizeof ts->phys, "%s/input0", dev->bus_id); -+ ts->input.phys = ts->phys; -+ -+ ts->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); -+ ts->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); -+ input_set_abs_params(&ts->input, ABS_X, -+ pdata->x_min ? : 0, -+ pdata->x_max ? : MAX_12BIT, -+ 0, 0); -+ input_set_abs_params(&ts->input, ABS_Y, -+ pdata->y_min ? : 0, -+ pdata->y_max ? : MAX_12BIT, -+ 0, 0); -+ input_set_abs_params(&ts->input, ABS_PRESSURE, -+ pdata->pressure_min, pdata->pressure_max, 0, 0); -+ -+ input_register_device(&ts->input); -+ -+ /* set up the transfers to read touchscreen state; this assumes we -+ * use formula #2 for pressure, not #3. -+ */ -+ x = ts->xfer; -+ -+ /* y- still on; turn on only y+ (and ADC) */ -+ x->tx_buf = &read_y; -+ x->len = 1; -+ x++; -+ x->rx_buf = &ts->tc.y; -+ x->len = 2; -+ x++; -+ -+ /* turn y+ off, x- on; we'll use formula #2 */ -+ if (ts->model == 7846) { -+ x->tx_buf = &read_z1; -+ x->len = 1; -+ x++; -+ x->rx_buf = &ts->tc.z1; -+ x->len = 2; -+ x++; -+ -+ x->tx_buf = &read_z2; -+ x->len = 1; -+ x++; -+ x->rx_buf = &ts->tc.z2; -+ x->len = 2; -+ x++; -+ } -+ -+ /* turn y- off, x+ on, then leave in lowpower */ -+ x->tx_buf = &read_x; -+ x->len = 1; -+ x++; -+ x->rx_buf = &ts->tc.x; -+ x->len = 2; -+ x++; -+ -+ CS_CHANGE(x[-1]); -+ -+ ts->msg.transfers = ts->xfer; -+ ts->msg.n_transfer = x - ts->xfer; -+ ts->msg.complete = ads7846_rx; -+ ts->msg.context = ts; -+ -+ if (request_irq(spi->irq, ads7846_irq, SA_SAMPLE_RANDOM, -+ dev->bus_id, ts)) { -+ dev_dbg(dev, "irq %d busy?\n", spi->irq); -+ input_unregister_device(&ts->input); -+ kfree(ts); -+ return -EBUSY; -+ } -+ set_irq_type(spi->irq, IRQT_FALLING); -+ -+ dev_info(dev, "touchscreen, irq %d\n", spi->irq); -+ -+ /* take a first sample, leaving nPENIRQ active; avoid -+ * the touchscreen, in case it's not connected. -+ */ -+ (void) ads7846_read12_ser(dev, -+ READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON); -+ -+ /* ads7843/7845 don't have temperature sensors, and -+ * use the other sensors a bit differently too -+ */ -+ if (ts->model == 7846) { -+ device_create_file(dev, &dev_attr_temp0); -+ device_create_file(dev, &dev_attr_temp1); -+ } -+ if (ts->model != 7845) -+ device_create_file(dev, &dev_attr_vbatt); -+ device_create_file(dev, &dev_attr_vaux); -+ -+ return 0; -+} -+ -+static int __exit ads7846_remove(struct device *dev) -+{ -+ struct ads7846 *ts = dev_get_drvdata(dev); -+ -+ ads7846_suspend(dev, PMSG_SUSPEND EXTRA2); -+ free_irq(ts->spi->irq, ts); -+ if (ts->irq_disabled) -+ enable_irq(ts->spi->irq); -+ -+ if (ts->model == 7846) { -+ device_remove_file(dev, &dev_attr_temp0); -+ device_remove_file(dev, &dev_attr_temp1); -+ } -+ if (ts->model != 7845) -+ device_remove_file(dev, &dev_attr_vbatt); -+ device_remove_file(dev, &dev_attr_vaux); -+ -+ input_unregister_device(&ts->input); -+ kfree(ts); -+ -+ dev_dbg(dev, "unregistered touchscreen\n"); -+ return 0; -+} -+ -+static struct device_driver ads7846_driver = { -+ .name = "ads7846", -+ .bus = &spi_bus_type, -+ .probe = ads7846_probe, -+ .remove = __exit_p(ads7846_remove), -+ .suspend = ads7846_suspend, -+ .resume = ads7846_resume, -+}; -+ -+static int __init ads7846_init(void) -+{ -+ /* grr, board-specific init should stay out of drivers!! */ -+ -+#ifdef CONFIG_ARCH_OMAP -+ if (machine_is_omap_osk()) { -+ /* GPIO4 = PENIRQ; GPIO6 = BUSY */ -+ omap_request_gpio(4); -+ omap_set_gpio_direction(4, 1); -+ omap_request_gpio(6); -+ omap_set_gpio_direction(6, 1); -+ } -+ // also TI 1510 Innovator, bitbanging through FPGA -+ // also Nokia 770 -+ // also Palm Tungsten T2 -+#endif -+ -+ // PXA: -+ // also Dell Axim X50 -+ // also HP iPaq H191x/H192x/H415x/H435x -+ // also Intel Lubbock (alternate to UCB1400) -+ // also Sharp Zaurus C7xx, C8xx (corgi/sheperd/husky) -+ -+ // also various AMD Au1x00 devel boards -+ -+ return driver_register(&ads7846_driver); -+} -+module_init(ads7846_init); -+ -+static void __exit ads7846_exit(void) -+{ -+ driver_unregister(&ads7846_driver); -+ -+#ifdef CONFIG_ARCH_OMAP -+ if (machine_is_omap_osk()) { -+ omap_free_gpio(4); -+ omap_free_gpio(6); -+ } -+#endif -+ -+} -+module_exit(ads7846_exit); -+ -+MODULE_DESCRIPTION("ADS7846 TouchScreen Driver"); -+MODULE_LICENSE("GPL"); ---- gregkh-2.6.orig/drivers/input/touchscreen/Kconfig -+++ gregkh-2.6/drivers/input/touchscreen/Kconfig -@@ -11,6 +11,19 @@ menuconfig INPUT_TOUCHSCREEN - - if INPUT_TOUCHSCREEN - -+config TOUCHSCREEN_ADS7846 -+ tristate "ADS 7846 based touchscreens" -+ depends on SPI_MASTER -+ help -+ Say Y here if you have a touchscreen interface using the -+ ADS7846 controller, and your board-specific initialization -+ code includes that in its table of SPI devices. -+ -+ If unsure, say N (but it's safe to say "Y"). -+ -+ To compile this driver as a module, choose M here: the -+ module will be called ads7846. -+ - config TOUCHSCREEN_BITSY - tristate "Compaq iPAQ H3600 (Bitsy) touchscreen" - depends on SA1100_BITSY ---- gregkh-2.6.orig/drivers/input/touchscreen/Makefile -+++ gregkh-2.6/drivers/input/touchscreen/Makefile -@@ -4,6 +4,7 @@ - - # Each configuration option enables a list of files. - -+obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o - obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o - obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o - obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o ---- /dev/null -+++ gregkh-2.6/include/linux/spi/ads7846.h -@@ -0,0 +1,18 @@ -+/* linux/spi/ads7846.h */ -+ -+/* Touchscreen characteristics vary between boards and models. The -+ * platform_data for the device's "struct device" holts this information. -+ * -+ * It's OK if the min/max values are zero. -+ */ -+struct ads7846_platform_data { -+ u16 model; /* 7843, 7845, 7846. */ -+ u16 vref_delay_usecs; /* 0 for external vref; etc */ -+ u16 x_plate_ohms; -+ u16 y_plate_ohms; -+ -+ u16 x_min, x_max; -+ u16 y_min, y_max; -+ u16 pressure_min, pressure_max; -+}; -+ diff --git a/driver/spi-core-tweaks-bugfix.patch b/driver/spi-core-tweaks-bugfix.patch deleted file mode 100644 index 433ad11e4f2be..0000000000000 --- a/driver/spi-core-tweaks-bugfix.patch +++ /dev/null @@ -1,358 +0,0 @@ -From akpm@osdl.org Sun Jan 8 13:39:08 2006 -From: akpm@osdl.org -Message-Id: <200601082134.k08LYaxO004573@shell0.pdx.osdl.net> -Subject: [patch 05/10] SPI core tweaks, bugfix -To: greg@kroah.com -Cc: akpm@osdl.org, david-b@pacbell.net, dbrownell@users.sourceforge.net -Date: Sun, 08 Jan 2006 13:34:25 -0800 - - -From: David Brownell <david-b@pacbell.net> - -This includes various updates to the SPI core: - - - Fixes a driver model refcount bug in spi_unregister_master() paths. - - - The spi_master structures now have wrappers which help keep drivers - from needing class-level get/put for device data or for refcounts. - - - Check for a few setup errors that would cause oopsing later. - - - Docs say more about memory management. Highlights the use of DMA-safe - i/o buffers, and zero-initializing spi_message and such metadata. - - - Provide a simple alloc/free for spi_message and its spi_transfer; - this is only one of the possible memory management policies. - -Nothing to break code that already works. - -Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> -Signed-off-by: Andrew Morton <akpm@osdl.org> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> ---- - Documentation/spi/spi-summary | 16 ++++++++ - drivers/spi/spi.c | 45 +++++++++++++++---------- - include/linux/spi/spi.h | 75 ++++++++++++++++++++++++++++++++++++++---- - 3 files changed, 113 insertions(+), 23 deletions(-) - ---- gregkh-2.6.orig/Documentation/spi/spi-summary -+++ gregkh-2.6/Documentation/spi/spi-summary -@@ -363,6 +363,22 @@ upper boundaries might include sysfs (es - the input layer, ALSA, networking, MTD, the character device framework, - or other Linux subsystems. - -+Note that there are two types of memory your driver must manage as part -+of interacting with SPI devices. -+ -+ - I/O buffers use the usual Linux rules, and must be DMA-safe. -+ You'd normally allocate them from the heap or free page pool. -+ Don't use the stack, or anything that's declared "static". -+ -+ - The spi_message and spi_transfer metadata used to glue those -+ I/O buffers into a group of protocol transactions. These can -+ be allocated anywhere it's convenient, including as part of -+ other allocate-once driver data structures. Zero-init these. -+ -+If you like, spi_message_alloc() and spi_message_free() convenience -+routines are available to allocate and zero-initialize an spi_message -+with several transfers. -+ - - How do I write an "SPI Master Controller Driver"? - ------------------------------------------------- ---- gregkh-2.6.orig/drivers/spi/spi.c -+++ gregkh-2.6/drivers/spi/spi.c -@@ -38,7 +38,7 @@ static void spidev_release(struct device - if (spi->master->cleanup) - spi->master->cleanup(spi); - -- class_device_put(&spi->master->cdev); -+ spi_master_put(spi->master); - kfree(dev); - } - -@@ -90,7 +90,7 @@ static int spi_suspend(struct device *de - int value; - struct spi_driver *drv = to_spi_driver(dev->driver); - -- if (!drv || !drv->suspend) -+ if (!drv->suspend) - return 0; - - /* suspend will stop irqs and dma; no more i/o */ -@@ -105,7 +105,7 @@ static int spi_resume(struct device *dev - int value; - struct spi_driver *drv = to_spi_driver(dev->driver); - -- if (!drv || !drv->resume) -+ if (!drv->resume) - return 0; - - /* resume may restart the i/o queue */ -@@ -198,7 +198,7 @@ spi_new_device(struct spi_master *master - - /* NOTE: caller did any chip->bus_num checks necessary */ - -- if (!class_device_get(&master->cdev)) -+ if (!spi_master_get(master)) - return NULL; - - proxy = kzalloc(sizeof *proxy, GFP_KERNEL); -@@ -244,7 +244,7 @@ spi_new_device(struct spi_master *master - return proxy; - - fail: -- class_device_put(&master->cdev); -+ spi_master_put(master); - kfree(proxy); - return NULL; - } -@@ -324,8 +324,6 @@ static void spi_master_release(struct cl - struct spi_master *master; - - master = container_of(cdev, struct spi_master, cdev); -- put_device(master->cdev.dev); -- master->cdev.dev = NULL; - kfree(master); - } - -@@ -339,8 +337,9 @@ static struct class spi_master_class = { - /** - * spi_alloc_master - allocate SPI master controller - * @dev: the controller, possibly using the platform_bus -- * @size: how much driver-private data to preallocate; a pointer to this -- * memory in the class_data field of the returned class_device -+ * @size: how much driver-private data to preallocate; the pointer to this -+ * memory is in the class_data field of the returned class_device, -+ * accessible with spi_master_get_devdata(). - * - * This call is used only by SPI master controller drivers, which are the - * only ones directly touching chip registers. It's how they allocate -@@ -350,14 +349,17 @@ static struct class spi_master_class = { - * master structure on success, else NULL. - * - * The caller is responsible for assigning the bus number and initializing -- * the master's methods before calling spi_add_master(), or else (on error) -- * calling class_device_put() to prevent a memory leak. -+ * the master's methods before calling spi_add_master(); and (after errors -+ * adding the device) calling spi_master_put() to prevent a memory leak. - */ - struct spi_master * __init_or_module - spi_alloc_master(struct device *dev, unsigned size) - { - struct spi_master *master; - -+ if (!dev) -+ return NULL; -+ - master = kzalloc(size + sizeof *master, SLAB_KERNEL); - if (!master) - return NULL; -@@ -365,7 +367,7 @@ spi_alloc_master(struct device *dev, uns - class_device_initialize(&master->cdev); - master->cdev.class = &spi_master_class; - master->cdev.dev = get_device(dev); -- class_set_devdata(&master->cdev, &master[1]); -+ spi_master_set_devdata(master, &master[1]); - - return master; - } -@@ -387,6 +389,8 @@ EXPORT_SYMBOL_GPL(spi_alloc_master); - * - * This must be called from context that can sleep. It returns zero on - * success, else a negative error code (dropping the master's refcount). -+ * After a successful return, the caller is responsible for calling -+ * spi_unregister_master(). - */ - int __init_or_module - spi_register_master(struct spi_master *master) -@@ -396,6 +400,9 @@ spi_register_master(struct spi_master *m - int status = -ENODEV; - int dynamic = 0; - -+ if (!dev) -+ return -ENODEV; -+ - /* convention: dynamically assigned bus IDs count down from the max */ - if (master->bus_num == 0) { - master->bus_num = atomic_dec_return(&dyn_bus_id); -@@ -425,7 +432,7 @@ EXPORT_SYMBOL_GPL(spi_register_master); - static int __unregister(struct device *dev, void *unused) - { - /* note: before about 2.6.14-rc1 this would corrupt memory: */ -- device_unregister(dev); -+ spi_unregister_device(to_spi_device(dev)); - return 0; - } - -@@ -440,8 +447,9 @@ static int __unregister(struct device *d - */ - void spi_unregister_master(struct spi_master *master) - { -- class_device_unregister(&master->cdev); - (void) device_for_each_child(master->cdev.dev, NULL, __unregister); -+ class_device_unregister(&master->cdev); -+ master->cdev.dev = NULL; - } - EXPORT_SYMBOL_GPL(spi_unregister_master); - -@@ -487,6 +495,9 @@ EXPORT_SYMBOL_GPL(spi_busnum_to_master); - * by leaving it selected in anticipation that the next message will go - * to the same chip. (That may increase power usage.) - * -+ * Also, the caller is guaranteeing that the memory associated with the -+ * message will not be freed before this call returns. -+ * - * The return value is a negative error code if the message could not be - * submitted, else zero. When the value is zero, then message->status is - * also defined: it's the completion code for the transfer, either zero -@@ -524,9 +535,9 @@ static u8 *buf; - * is zero for success, else a negative errno status code. - * This call may only be used from a context that may sleep. - * -- * Parameters to this routine are always copied using a small buffer, -- * large transfers should use use spi_{async,sync}() calls with -- * dma-safe buffers. -+ * Parameters to this routine are always copied using a small buffer; -+ * performance-sensitive or bulk transfer code should instead use -+ * spi_{async,sync}() calls with dma-safe buffers. - */ - int spi_write_then_read(struct spi_device *spi, - const u8 *txbuf, unsigned n_tx, ---- gregkh-2.6.orig/include/linux/spi/spi.h -+++ gregkh-2.6/include/linux/spi/spi.h -@@ -60,8 +60,8 @@ struct spi_device { - u8 mode; - #define SPI_CPHA 0x01 /* clock phase */ - #define SPI_CPOL 0x02 /* clock polarity */ --#define SPI_MODE_0 (0|0) --#define SPI_MODE_1 (0|SPI_CPHA) /* (original MicroWire) */ -+#define SPI_MODE_0 (0|0) /* (original MicroWire) */ -+#define SPI_MODE_1 (0|SPI_CPHA) - #define SPI_MODE_2 (SPI_CPOL|0) - #define SPI_MODE_3 (SPI_CPOL|SPI_CPHA) - #define SPI_CS_HIGH 0x04 /* chipselect active high? */ -@@ -209,6 +209,30 @@ struct spi_master { - void (*cleanup)(const struct spi_device *spi); - }; - -+static inline void *spi_master_get_devdata(struct spi_master *master) -+{ -+ return class_get_devdata(&master->cdev); -+} -+ -+static inline void spi_master_set_devdata(struct spi_master *master, void *data) -+{ -+ class_set_devdata(&master->cdev, data); -+} -+ -+static inline struct spi_master *spi_master_get(struct spi_master *master) -+{ -+ if (!master || !class_device_get(&master->cdev)) -+ return NULL; -+ return master; -+} -+ -+static inline void spi_master_put(struct spi_master *master) -+{ -+ if (master) -+ class_device_put(&master->cdev); -+} -+ -+ - /* the spi driver core manages memory for the spi_master classdev */ - extern struct spi_master * - spi_alloc_master(struct device *host, unsigned size); -@@ -271,11 +295,17 @@ extern struct spi_master *spi_busnum_to_ - * stay selected until the next transfer. This is purely a performance - * hint; the controller driver may need to select a different device - * for the next message. -+ * -+ * The code that submits an spi_message (and its spi_transfers) -+ * to the lower layers is responsible for managing its memory. -+ * Zero-initialize every field you don't set up explicitly, to -+ * insulate against future API updates. - */ - struct spi_transfer { - /* it's ok if tx_buf == rx_buf (right?) - * for MicroWire, one buffer must be null -- * buffers must work with dma_*map_single() calls -+ * buffers must work with dma_*map_single() calls, unless -+ * spi_message.is_dma_mapped reports a pre-existing mapping - */ - const void *tx_buf; - void *rx_buf; -@@ -302,6 +332,11 @@ struct spi_transfer { - * @status: zero for success, else negative errno - * @queue: for use by whichever driver currently owns the message - * @state: for use by whichever driver currently owns the message -+ * -+ * The code that submits an spi_message (and its spi_transfers) -+ * to the lower layers is responsible for managing its memory. -+ * Zero-initialize every field you don't set up explicitly, to -+ * insulate against future API updates. - */ - struct spi_message { - struct spi_transfer *transfers; -@@ -336,6 +371,29 @@ struct spi_message { - void *state; - }; - -+/* It's fine to embed message and transaction structures in other data -+ * structures so long as you don't free them while they're in use. -+ */ -+ -+static inline struct spi_message *spi_message_alloc(unsigned ntrans, gfp_t flags) -+{ -+ struct spi_message *m; -+ -+ m = kzalloc(sizeof(struct spi_message) -+ + ntrans * sizeof(struct spi_transfer), -+ flags); -+ if (m) { -+ m->transfers = (void *)(m + 1); -+ m->n_transfer = ntrans; -+ } -+ return m; -+} -+ -+static inline void spi_message_free(struct spi_message *m) -+{ -+ kfree(m); -+} -+ - /** - * spi_setup -- setup SPI mode and clock rate - * @spi: the device whose settings are being modified -@@ -363,7 +421,10 @@ spi_setup(struct spi_device *spi) - * The completion callback is invoked in a context which can't sleep. - * Before that invocation, the value of message->status is undefined. - * When the callback is issued, message->status holds either zero (to -- * indicate complete success) or a negative error code. -+ * indicate complete success) or a negative error code. After that -+ * callback returns, the driver which issued the transfer request may -+ * deallocate the associated memory; it's no longer in use by any SPI -+ * core or controller driver code. - * - * Note that although all messages to a spi_device are handled in - * FIFO order, messages may go to different devices in other orders. -@@ -445,6 +506,7 @@ spi_read(struct spi_device *spi, u8 *buf - return spi_sync(spi, &m); - } - -+/* this copies txbuf and rxbuf data; for small transfers only! */ - extern int spi_write_then_read(struct spi_device *spi, - const u8 *txbuf, unsigned n_tx, - u8 *rxbuf, unsigned n_rx); -@@ -555,8 +617,9 @@ spi_register_board_info(struct spi_board - - - /* If you're hotplugging an adapter with devices (parport, usb, etc) -- * use spi_new_device() to describe each device. You would then call -- * spi_unregister_device() to start making that device vanish. -+ * use spi_new_device() to describe each device. You can also call -+ * spi_unregister_device() to start making that device vanish, but -+ * normally that would be handled by spi_unregister_master(). - */ - extern struct spi_device * - spi_new_device(struct spi_master *, struct spi_board_info *); diff --git a/driver/spi-m25-series-spi-flash.patch b/driver/spi-m25-series-spi-flash.patch deleted file mode 100644 index 5f5d0bc0da9a9..0000000000000 --- a/driver/spi-m25-series-spi-flash.patch +++ /dev/null @@ -1,657 +0,0 @@ -From akpm@osdl.org Sun Jan 8 13:38:43 2006 -From: akpm@osdl.org -Message-Id: <200601082134.k08LYd2q004582@shell0.pdx.osdl.net> -Subject: [patch 08/10] spi: M25 series SPI flash -To: greg@kroah.com -Cc: akpm@osdl.org, mike@steroidmicros.com, dbrownell@users.sourceforge.net -Date: Sun, 08 Jan 2006 13:34:27 -0800 - - -From: Mike Lavender <mike@steroidmicros.com> - -This was originally a driver for the ST M25P80 SPI flash. It's been -updated slightly to handle other M25P series chips. - -For many of these chips, the specific type could be probed, but for now -this just requires static setup with flash_platform_data that lists the -chip type (size, format) and any default partitioning to use. - -Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> -Cc: Mike Lavender <mike@steroidmicros.com> -Cc: David Brownell <dbrownell@users.sourceforge.net> -Signed-off-by: Andrew Morton <akpm@osdl.org> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> ---- - drivers/mtd/devices/Kconfig | 8 - drivers/mtd/devices/Makefile | 1 - drivers/mtd/devices/m25p80.c | 580 +++++++++++++++++++++++++++++++++++++++++++ - include/linux/spi/flash.h | 4 - 4 files changed, 593 insertions(+) - ---- gregkh-2.6.orig/drivers/mtd/devices/Kconfig -+++ gregkh-2.6/drivers/mtd/devices/Kconfig -@@ -55,6 +55,14 @@ config MTD_DATAFLASH - Sometimes DataFlash chips are packaged inside MMC-format - cards; at this writing, the MMC stack won't handle those. - -+config MTD_M25P80 -+ tristate "Support for M25 SPI Flash" -+ depends on MTD && SPI_MASTER && EXPERIMENTAL -+ help -+ This enables access to ST M25P80 and similar SPI flash chips, -+ used for program and data storage. Set up your spi devices -+ with the right board-specific platform data. -+ - config MTD_SLRAM - tristate "Uncached system RAM" - depends on MTD ---- /dev/null -+++ gregkh-2.6/drivers/mtd/devices/m25p80.c -@@ -0,0 +1,580 @@ -+/* -+ * MTD SPI driver for ST M25Pxx flash chips -+ * -+ * Author: Mike Lavender, mike@steroidmicros.com -+ * -+ * Copyright (c) 2005, Intec Automation Inc. -+ * -+ * Some parts are based on lart.c by Abraham Van Der Merwe -+ * -+ * Cleaned up and generalized based on mtd_dataflash.c -+ * -+ * This code is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+ -+#include <linux/init.h> -+#include <linux/module.h> -+#include <linux/device.h> -+#include <linux/interrupt.h> -+#include <linux/interrupt.h> -+#include <linux/mtd/mtd.h> -+#include <linux/mtd/partitions.h> -+#include <linux/spi/spi.h> -+#include <linux/spi/flash.h> -+ -+#include <asm/semaphore.h> -+ -+ -+/* NOTE: AT 25F and SST 25LF series are very similar, -+ * but commands for sector erase and chip id differ... -+ */ -+ -+#define FLASH_PAGESIZE 256 -+ -+/* Flash opcodes. */ -+#define OPCODE_WREN 6 /* Write enable */ -+#define OPCODE_RDSR 5 /* Read status register */ -+#define OPCODE_READ 3 /* Read data bytes */ -+#define OPCODE_PP 2 /* Page program */ -+#define OPCODE_SE 0xd8 /* Sector erase */ -+#define OPCODE_RES 0xab /* Read Electronic Signature */ -+#define OPCODE_RDID 0x9f /* Read JEDEC ID */ -+ -+/* Status Register bits. */ -+#define SR_WIP 1 /* Write in progress */ -+#define SR_WEL 2 /* Write enable latch */ -+#define SR_BP0 4 /* Block protect 0 */ -+#define SR_BP1 8 /* Block protect 1 */ -+#define SR_BP2 0x10 /* Block protect 2 */ -+#define SR_SRWD 0x80 /* SR write protect */ -+ -+/* Define max times to check status register before we give up. */ -+#define MAX_READY_WAIT_COUNT 100000 -+ -+ -+#ifdef CONFIG_MTD_PARTITIONS -+#define mtd_has_partitions() (1) -+#else -+#define mtd_has_partitions() (0) -+#endif -+ -+/****************************************************************************/ -+ -+struct m25p { -+ struct spi_device *spi; -+ struct semaphore lock; -+ struct mtd_info mtd; -+ unsigned partitioned; -+ u8 command[4]; -+}; -+ -+static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd) -+{ -+ return container_of(mtd, struct m25p, mtd); -+} -+ -+/****************************************************************************/ -+ -+/* -+ * Internal helper functions -+ */ -+ -+/* -+ * Read the status register, returning its value in the location -+ * Return the status register value. -+ * Returns negative if error occurred. -+ */ -+static int read_sr(struct m25p *flash) -+{ -+ ssize_t retval; -+ u8 code = OPCODE_RDSR; -+ u8 val; -+ -+ retval = spi_write_then_read(flash->spi, &code, 1, &val, 1); -+ -+ if (retval < 0) { -+ dev_err(&flash->spi->dev, "error %d reading SR\n", -+ (int) retval); -+ return retval; -+ } -+ -+ return val; -+} -+ -+ -+/* -+ * Set write enable latch with Write Enable command. -+ * Returns negative if error occurred. -+ */ -+static inline int write_enable(struct m25p *flash) -+{ -+ u8 code = OPCODE_WREN; -+ -+ return spi_write_then_read(flash->spi, &code, 1, NULL, 0); -+} -+ -+ -+/* -+ * Service routine to read status register until ready, or timeout occurs. -+ * Returns non-zero if error. -+ */ -+static int wait_till_ready(struct m25p *flash) -+{ -+ int count; -+ int sr; -+ -+ /* one chip guarantees max 5 msec wait here after page writes, -+ * but potentially three seconds (!) after page erase. -+ */ -+ for (count = 0; count < MAX_READY_WAIT_COUNT; count++) { -+ if ((sr = read_sr(flash)) < 0) -+ break; -+ else if (!(sr & SR_WIP)) -+ return 0; -+ -+ /* REVISIT sometimes sleeping would be best */ -+ } -+ -+ return 1; -+} -+ -+ -+/* -+ * Erase one sector of flash memory at offset ``offset'' which is any -+ * address within the sector which should be erased. -+ * -+ * Returns 0 if successful, non-zero otherwise. -+ */ -+static int erase_sector(struct m25p *flash, u32 offset) -+{ -+ DEBUG(MTD_DEBUG_LEVEL3, "%s: %s at 0x%08x\n", flash->spi->dev.bus_id, -+ __FUNCTION__, offset); -+ -+ /* Wait until finished previous write command. */ -+ if (wait_till_ready(flash)) -+ return 1; -+ -+ /* Send write enable, then erase commands. */ -+ write_enable(flash); -+ -+ /* Set up command buffer. */ -+ flash->command[0] = OPCODE_SE; -+ flash->command[1] = offset >> 16; -+ flash->command[2] = offset >> 8; -+ flash->command[3] = offset; -+ -+ spi_write(flash->spi, flash->command, sizeof(flash->command)); -+ -+ return 0; -+} -+ -+/****************************************************************************/ -+ -+/* -+ * MTD implementation -+ */ -+ -+/* -+ * Erase an address range on the flash chip. The address range may extend -+ * one or more erase sectors. Return an error is there is a problem erasing. -+ */ -+static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr) -+{ -+ struct m25p *flash = mtd_to_m25p(mtd); -+ u32 addr,len; -+ -+ DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", -+ flash->spi->dev.bus_id, __FUNCTION__, "at", -+ (u32)instr->addr, instr->len); -+ -+ /* sanity checks */ -+ if (instr->addr + instr->len > flash->mtd.size) -+ return -EINVAL; -+ if ((instr->addr % mtd->erasesize) != 0 -+ || (instr->len % mtd->erasesize) != 0) { -+ return -EINVAL; -+ } -+ -+ addr = instr->addr; -+ len = instr->len; -+ -+ down(&flash->lock); -+ -+ /* now erase those sectors */ -+ while (len) { -+ if (erase_sector(flash, addr)) { -+ instr->state = MTD_ERASE_FAILED; -+ up(&flash->lock); -+ return -EIO; -+ } -+ -+ addr += mtd->erasesize; -+ len -= mtd->erasesize; -+ } -+ -+ up(&flash->lock); -+ -+ instr->state = MTD_ERASE_DONE; -+ mtd_erase_callback(instr); -+ -+ return 0; -+} -+ -+/* -+ * Read an address range from the flash chip. The address range -+ * may be any size provided it is within the physical boundaries. -+ */ -+static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t *retlen, u_char *buf) -+{ -+ struct m25p *flash = mtd_to_m25p(mtd); -+ struct spi_transfer t[2]; -+ struct spi_message m; -+ -+ DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", -+ flash->spi->dev.bus_id, __FUNCTION__, "from", -+ (u32)from, len); -+ -+ /* sanity checks */ -+ if (!len) -+ return 0; -+ -+ if (from + len > flash->mtd.size) -+ return -EINVAL; -+ -+ down(&flash->lock); -+ -+ /* Wait till previous write/erase is done. */ -+ if (wait_till_ready(flash)) { -+ /* REVISIT status return?? */ -+ up(&flash->lock); -+ return 1; -+ } -+ -+ memset(t, 0, (sizeof t)); -+ -+ /* NOTE: OPCODE_FAST_READ (if available) is faster... */ -+ -+ /* Set up the write data buffer. */ -+ flash->command[0] = OPCODE_READ; -+ flash->command[1] = from >> 16; -+ flash->command[2] = from >> 8; -+ flash->command[3] = from; -+ -+ /* Byte count starts at zero. */ -+ if (retlen) -+ *retlen = 0; -+ -+ t[0].tx_buf = flash->command; -+ t[0].len = sizeof(flash->command); -+ -+ t[1].rx_buf = buf; -+ t[1].len = len; -+ -+ m.transfers = t; -+ m.n_transfer = 2; -+ -+ spi_sync(flash->spi, &m); -+ -+ *retlen = m.actual_length - sizeof(flash->command); -+ -+ up(&flash->lock); -+ -+ return 0; -+} -+ -+/* -+ * Write an address range to the flash chip. Data must be written in -+ * FLASH_PAGESIZE chunks. The address range may be any size provided -+ * it is within the physical boundaries. -+ */ -+static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t *retlen, const u_char *buf) -+{ -+ struct m25p *flash = mtd_to_m25p(mtd); -+ u32 page_offset, page_size; -+ struct spi_transfer t[2]; -+ struct spi_message m; -+ -+ DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", -+ flash->spi->dev.bus_id, __FUNCTION__, "to", -+ (u32)to, len); -+ -+ if (retlen) -+ *retlen = 0; -+ -+ /* sanity checks */ -+ if (!len) -+ return(0); -+ -+ if (to + len > flash->mtd.size) -+ return -EINVAL; -+ -+ down(&flash->lock); -+ -+ /* Wait until finished previous write command. */ -+ if (wait_till_ready(flash)) -+ return 1; -+ -+ write_enable(flash); -+ -+ memset(t, 0, (sizeof t)); -+ -+ /* Set up the opcode in the write buffer. */ -+ flash->command[0] = OPCODE_PP; -+ flash->command[1] = to >> 16; -+ flash->command[2] = to >> 8; -+ flash->command[3] = to; -+ -+ t[0].tx_buf = flash->command; -+ t[0].len = sizeof(flash->command); -+ -+ m.transfers = t; -+ m.n_transfer = 2; -+ -+ /* what page do we start with? */ -+ page_offset = to % FLASH_PAGESIZE; -+ -+ /* do all the bytes fit onto one page? */ -+ if (page_offset + len <= FLASH_PAGESIZE) { -+ t[1].tx_buf = buf; -+ t[1].len = len; -+ -+ spi_sync(flash->spi, &m); -+ -+ *retlen = m.actual_length - sizeof(flash->command); -+ } else { -+ u32 i; -+ -+ /* the size of data remaining on the first page */ -+ page_size = FLASH_PAGESIZE - page_offset; -+ -+ t[1].tx_buf = buf; -+ t[1].len = page_size; -+ spi_sync(flash->spi, &m); -+ -+ *retlen = m.actual_length - sizeof(flash->command); -+ -+ /* write everything in PAGESIZE chunks */ -+ for (i = page_size; i < len; i += page_size) { -+ page_size = len - i; -+ if (page_size > FLASH_PAGESIZE) -+ page_size = FLASH_PAGESIZE; -+ -+ /* write the next page to flash */ -+ flash->command[1] = (to + i) >> 16; -+ flash->command[2] = (to + i) >> 8; -+ flash->command[3] = (to + i); -+ -+ t[1].tx_buf = buf + i; -+ t[1].len = page_size; -+ -+ wait_till_ready(flash); -+ -+ write_enable(flash); -+ -+ spi_sync(flash->spi, &m); -+ -+ *retlen += m.actual_length - sizeof(flash->command); -+ } -+ } -+ -+ up(&flash->lock); -+ -+ return 0; -+} -+ -+ -+/****************************************************************************/ -+ -+/* -+ * SPI device driver setup and teardown -+ */ -+ -+struct flash_info { -+ char *name; -+ u8 id; -+ u16 jedec_id; -+ unsigned sector_size; -+ unsigned n_sectors; -+}; -+ -+static struct flash_info __devinitdata m25p_data [] = { -+ /* REVISIT: fill in JEDEC ids, for parts that have them */ -+ { "m25p05", 0x05, 0x0000, 32 * 1024, 2 }, -+ { "m25p10", 0x10, 0x0000, 32 * 1024, 4 }, -+ { "m25p20", 0x11, 0x0000, 64 * 1024, 4 }, -+ { "m25p40", 0x12, 0x0000, 64 * 1024, 8 }, -+ { "m25p80", 0x13, 0x0000, 64 * 1024, 16 }, -+ { "m25p16", 0x14, 0x0000, 64 * 1024, 32 }, -+ { "m25p32", 0x15, 0x0000, 64 * 1024, 64 }, -+ { "m25p64", 0x16, 0x2017, 64 * 1024, 128 }, -+}; -+ -+/* -+ * board specific setup should have ensured the SPI clock used here -+ * matches what the READ command supports, at least until this driver -+ * understands FAST_READ (for clocks over 25 MHz). -+ */ -+static int __devinit m25p_probe(struct spi_device *spi) -+{ -+ struct flash_platform_data *data; -+ struct m25p *flash; -+ struct flash_info *info; -+ unsigned i; -+ -+ /* Platform data helps sort out which chip type we have, as -+ * well as how this board partitions it. -+ */ -+ data = spi->dev.platform_data; -+ if (!data || !data->type) { -+ /* FIXME some chips can identify themselves with RES -+ * or JEDEC get-id commands. Try them ... -+ */ -+ DEBUG(MTD_DEBUG_LEVEL1, "%s: no chip id\n", -+ flash->spi->dev.bus_id); -+ return -ENODEV; -+ } -+ -+ for (i = 0, info = m25p_data; i < ARRAY_SIZE(m25p_data); i++, info++) { -+ if (strcmp(data->type, info->name) == 0) -+ break; -+ } -+ if (i == ARRAY_SIZE(m25p_data)) { -+ DEBUG(MTD_DEBUG_LEVEL1, "%s: unrecognized id %s\n", -+ flash->spi->dev.bus_id, data->type); -+ return -ENODEV; -+ } -+ -+ flash = kzalloc(sizeof *flash, SLAB_KERNEL); -+ if (!flash) -+ return -ENOMEM; -+ -+ flash->spi = spi; -+ init_MUTEX(&flash->lock); -+ dev_set_drvdata(&spi->dev, flash); -+ -+ if (data->name) -+ flash->mtd.name = data->name; -+ else -+ flash->mtd.name = spi->dev.bus_id; -+ -+ flash->mtd.type = MTD_NORFLASH; -+ flash->mtd.flags = MTD_CAP_NORFLASH; -+ flash->mtd.size = info->sector_size * info->n_sectors; -+ flash->mtd.erasesize = info->sector_size; -+ flash->mtd.erase = m25p80_erase; -+ flash->mtd.read = m25p80_read; -+ flash->mtd.write = m25p80_write; -+ -+ dev_info(&spi->dev, "%s (%d Kbytes)\n", info->name, -+ flash->mtd.size / 1024); -+ -+ DEBUG(MTD_DEBUG_LEVEL2, -+ "mtd .name = %s, .size = 0x%.8x (%uM) " -+ ".erasesize = 0x%.8x (%uK) .numeraseregions = %d\n", -+ flash->mtd.name, -+ flash->mtd.size, flash->mtd.size / (1024*1024), -+ flash->mtd.erasesize, flash->mtd.erasesize / 1024, -+ flash->mtd.numeraseregions); -+ -+ if (flash->mtd.numeraseregions) -+ for (i = 0; i < flash->mtd.numeraseregions; i++) -+ DEBUG(MTD_DEBUG_LEVEL2, -+ "mtd.eraseregions[%d] = { .offset = 0x%.8x, " -+ ".erasesize = 0x%.8x (%uK), " -+ ".numblocks = %d }\n", -+ i, flash->mtd.eraseregions[i].offset, -+ flash->mtd.eraseregions[i].erasesize, -+ flash->mtd.eraseregions[i].erasesize / 1024, -+ flash->mtd.eraseregions[i].numblocks); -+ -+ -+ /* partitions should match sector boundaries; and it may be good to -+ * use readonly partitions for writeprotected sectors (BP2..BP0). -+ */ -+ if (mtd_has_partitions()) { -+ struct mtd_partition *parts = NULL; -+ int nr_parts = 0; -+ -+#ifdef CONFIG_MTD_CMDLINE_PARTS -+ static const char *part_probes[] = { "cmdlinepart", NULL, }; -+ -+ nr_parts = parse_mtd_partitions(&flash->mtd, -+ part_probes, &parts, 0); -+#endif -+ -+ if (nr_parts <= 0 && data && data->parts) { -+ parts = data->parts; -+ nr_parts = data->nr_parts; -+ } -+ -+ if (nr_parts > 0) { -+ for (i = 0; i < data->nr_parts; i++) { -+ DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = " -+ "{.name = %s, .offset = 0x%.8x, " -+ ".size = 0x%.8x (%uK) }\n", -+ i, data->parts[i].name, -+ data->parts[i].offset, -+ data->parts[i].size, -+ data->parts[i].size / 1024); -+ } -+ flash->partitioned = 1; -+ return add_mtd_partitions(&flash->mtd, parts, nr_parts); -+ } -+ } else if (data->nr_parts) -+ dev_warn(&spi->dev, "ignoring %d default partitions on %s\n", -+ data->nr_parts, data->name); -+ -+ return add_mtd_device(&flash->mtd) == 1 ? -ENODEV : 0; -+} -+ -+ -+static int __devexit m25p_remove(struct spi_device *spi) -+{ -+ struct m25p *flash = dev_get_drvdata(&spi->dev); -+ int status; -+ -+ /* Clean up MTD stuff. */ -+ if (mtd_has_partitions() && flash->partitioned) -+ status = del_mtd_partitions(&flash->mtd); -+ else -+ status = del_mtd_device(&flash->mtd); -+ if (status == 0) -+ kfree(flash); -+ return 0; -+} -+ -+ -+static struct spi_driver m25p80_driver = { -+ .driver = { -+ .name = "m25p80", -+ .bus = &spi_bus_type, -+ .owner = THIS_MODULE, -+ }, -+ .probe = m25p_probe, -+ .remove = __devexit_p(m25p_remove), -+}; -+ -+ -+static int m25p80_init(void) -+{ -+ return spi_register_driver(&m25p80_driver); -+} -+ -+ -+static void m25p80_exit(void) -+{ -+ spi_unregister_driver(&m25p80_driver); -+} -+ -+ -+module_init(m25p80_init); -+module_exit(m25p80_exit); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Mike Lavender"); -+MODULE_DESCRIPTION("MTD SPI driver for ST M25Pxx flash chips"); ---- gregkh-2.6.orig/drivers/mtd/devices/Makefile -+++ gregkh-2.6/drivers/mtd/devices/Makefile -@@ -24,3 +24,4 @@ obj-$(CONFIG_MTD_LART) += lart.o - obj-$(CONFIG_MTD_BLKMTD) += blkmtd.o - obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o - obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o -+obj-$(CONFIG_MTD_M25P80) += m25p80.o ---- gregkh-2.6.orig/include/linux/spi/flash.h -+++ gregkh-2.6/include/linux/spi/flash.h -@@ -8,6 +8,8 @@ struct mtd_partition; - * @name: optional flash device name (eg, as used with mtdparts=) - * @parts: optional array of mtd_partitions for static partitioning - * @nr_parts: number of mtd_partitions for static partitoning -+ * @type: optional flash device type (e.g. m25p80 vs m25p64), for use -+ * with chips that can't be queried for JEDEC or other IDs - * - * Board init code (in arch/.../mach-xxx/board-yyy.c files) can - * provide information about SPI flash parts (such as DataFlash) to -@@ -21,6 +23,8 @@ struct flash_platform_data { - struct mtd_partition *parts; - unsigned int nr_parts; - -+ char *type; -+ - /* we'll likely add more ... use JEDEC IDs, etc */ - }; - diff --git a/driver/spi-misc-fixes.patch b/driver/spi-misc-fixes.patch deleted file mode 100644 index 451b2d6afa3b4..0000000000000 --- a/driver/spi-misc-fixes.patch +++ /dev/null @@ -1,118 +0,0 @@ -From akpm@osdl.org Sun Jan 8 13:39:13 2006 -From: akpm@osdl.org -Message-Id: <200601082134.k08LYfjI004588@shell0.pdx.osdl.net> -Subject: [patch 10/10] spi: misc fixes -To: greg@kroah.com -Cc: akpm@osdl.org, david-b@pacbell.net, dbrownell@users.sourceforge.net -Date: Sun, 08 Jan 2006 13:34:29 -0800 - - -From: David Brownell <david-b@pacbell.net> - -This collects some small SPI patches that seem to be missing from the MM tree: - - - spi_butterfly kbuild hooks got dropped somehow; this restores them - - quick fix for a (theoretical?) m25p80_write() oops noted by Andrew - - quick fix for a potential config-specific oops for mtd_dataflash() - - minor doc tweaks - -Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> -Signed-off-by: Andrew Morton <akpm@osdl.org> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> ---- - Documentation/spi/spi-summary | 13 +++++++++++++ - drivers/mtd/devices/m25p80.c | 4 +++- - drivers/mtd/devices/mtd_dataflash.c | 2 +- - drivers/spi/Kconfig | 10 ++++++++++ - drivers/spi/Makefile | 1 + - 5 files changed, 28 insertions(+), 2 deletions(-) - ---- gregkh-2.6.orig/Documentation/spi/spi-summary -+++ gregkh-2.6/Documentation/spi/spi-summary -@@ -115,6 +115,9 @@ shows up in sysfs in several locations: - /sys/devices/.../CTLR/spiB.C ... spi_device for on bus "B", - chipselect C, accessed through CTLR. - -+ /sys/devices/.../CTLR/spiB.C/modalias ... identifies the driver -+ that should be used with this device (for hotplug/coldplug) -+ - /sys/bus/spi/devices/spiB.C ... symlink to the physical - spiB-C device - -@@ -247,6 +250,12 @@ driver is registered: - - Like with other static board-specific setup, you won't unregister those. - -+The widely used "card" style computers bundle memory, cpu, and little else -+onto a card that's maybe just thirty square centimeters. On such systems, -+your arch/.../mach-.../board-*.c file would primarily provide information -+about the devices on the mainboard into which such a card is plugged. That -+certainly includes SPI devices hooked up through the card connectors! -+ - - NON-STATIC CONFIGURATIONS - -@@ -258,6 +267,10 @@ up the spi bus master, and will likely n - board info based on the board that was hotplugged. Of course, you'd later - call at least spi_unregister_device() when that board is removed. - -+When Linux includes support for MMC/SD/SDIO/DataFlash cards through SPI, those -+configurations will also be dynamic. Fortunately, those devices all support -+basic device identification probes, so that support should hotplug normally. -+ - - How do I write an "SPI Protocol Driver"? - ---------------------------------------- ---- gregkh-2.6.orig/drivers/mtd/devices/m25p80.c -+++ gregkh-2.6/drivers/mtd/devices/m25p80.c -@@ -378,7 +378,9 @@ static int m25p80_write(struct mtd_info - - spi_sync(flash->spi, &m); - -- *retlen += m.actual_length - sizeof(flash->command); -+ if (retlen) -+ *retlen += m.actual_length -+ - sizeof(flash->command); - } - } - ---- gregkh-2.6.orig/drivers/mtd/devices/mtd_dataflash.c -+++ gregkh-2.6/drivers/mtd/devices/mtd_dataflash.c -@@ -508,7 +508,7 @@ add_dataflash(struct spi_device *spi, ch - priv->partitioned = 1; - return add_mtd_partitions(device, parts, nr_parts); - } -- } else if (pdata->nr_parts) -+ } else if (pdata && pdata->nr_parts) - dev_warn(&spi->dev, "ignoring %d default partitions on %s\n", - pdata->nr_parts, device->name); - ---- gregkh-2.6.orig/drivers/spi/Kconfig -+++ gregkh-2.6/drivers/spi/Kconfig -@@ -65,6 +65,16 @@ config SPI_BITBANG - need it. You only need to select this explicitly to support driver - modules that aren't part of this kernel tree. - -+config SPI_BUTTERFLY -+ tristate "Parallel port adapter for AVR Butterfly (DEVELOPMENT)" -+ depends on SPI_MASTER && PARPORT && EXPERIMENTAL -+ select SPI_BITBANG -+ help -+ This uses a custom parallel port cable to connect to an AVR -+ Butterfly <http://www.atmel.com/products/avr/butterfly>, an -+ inexpensive battery powered microcontroller evaluation board. -+ This same cable can be used to flash new firmware. -+ - # - # Add new SPI master controllers in alphabetical order above this line - # ---- gregkh-2.6.orig/drivers/spi/Makefile -+++ gregkh-2.6/drivers/spi/Makefile -@@ -12,6 +12,7 @@ obj-$(CONFIG_SPI_MASTER) += spi.o - - # SPI master controller drivers (bus) - obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o -+obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o - # ... add above this line ... - - # SPI protocol drivers (device/link on bus) diff --git a/driver/spi-mtd-dataflash-driver.patch b/driver/spi-mtd-dataflash-driver.patch deleted file mode 100644 index 657bbdd2ecf9f..0000000000000 --- a/driver/spi-mtd-dataflash-driver.patch +++ /dev/null @@ -1,712 +0,0 @@ -From akpm@osdl.org Sun Jan 8 13:38:50 2006 -From: akpm@osdl.org -Message-Id: <200601082134.k08LYX02004567@shell0.pdx.osdl.net> -Subject: [patch 03/10] spi: mtd dataflash driver -To: greg@kroah.com -Cc: akpm@osdl.org, david-b@pacbell.net, dbrownell@users.sourceforge.net -Date: Sun, 08 Jan 2006 13:34:22 -0800 - - -From: David Brownell <david-b@pacbell.net> - -This is a conversion of the AT91rm9200 DataFlash MTD driver to use the -lightweight SPI framework, and no longer be AT91-specific. It compiles -down to less than 3KBytes on ARM. - -The driver allows board-specific init code to provide platform_data with -the relevant MTD partitioning information, and hotplugs. - -This version has been lightly tested. Its parent at91_dataflash driver has -been pretty well banged on, although kernel.org JFFS2 dataflash support was -acting broken the last time I tried it. - -Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> -Signed-off-by: Andrew Morton <akpm@osdl.org> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> ---- - drivers/mtd/devices/Kconfig | 8 - drivers/mtd/devices/Makefile | 1 - drivers/mtd/devices/mtd_dataflash.c | 623 ++++++++++++++++++++++++++++++++++++ - include/linux/spi/flash.h | 27 + - 4 files changed, 659 insertions(+) - ---- gregkh-2.6.orig/drivers/mtd/devices/Kconfig -+++ gregkh-2.6/drivers/mtd/devices/Kconfig -@@ -47,6 +47,14 @@ config MTD_MS02NV - accelerator. Say Y here if you have a DECstation 5000/2x0 or a - DECsystem 5900 equipped with such a module. - -+config MTD_DATAFLASH -+ tristate "Support for AT45xxx DataFlash" -+ depends on MTD && SPI_MASTER && EXPERIMENTAL -+ help -+ This enables access to AT45xxx DataFlash chips, using SPI. -+ Sometimes DataFlash chips are packaged inside MMC-format -+ cards; at this writing, the MMC stack won't handle those. -+ - config MTD_SLRAM - tristate "Uncached system RAM" - depends on MTD ---- gregkh-2.6.orig/drivers/mtd/devices/Makefile -+++ gregkh-2.6/drivers/mtd/devices/Makefile -@@ -23,3 +23,4 @@ obj-$(CONFIG_MTD_MTDRAM) += mtdram.o - obj-$(CONFIG_MTD_LART) += lart.o - obj-$(CONFIG_MTD_BLKMTD) += blkmtd.o - obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o -+obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o ---- /dev/null -+++ gregkh-2.6/drivers/mtd/devices/mtd_dataflash.c -@@ -0,0 +1,623 @@ -+/* -+ * Atmel AT45xxx DataFlash MTD driver for lightweight SPI framework -+ * -+ * Largely derived from at91_dataflash.c: -+ * Copyright (C) 2003-2005 SAN People (Pty) Ltd -+ * -+ * 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. -+*/ -+#include <linux/config.h> -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/slab.h> -+#include <linux/delay.h> -+#include <linux/device.h> -+#include <linux/spi/spi.h> -+#include <linux/spi/flash.h> -+ -+#include <linux/mtd/mtd.h> -+#include <linux/mtd/partitions.h> -+ -+ -+/* -+ * DataFlash is a kind of SPI flash. Most AT45 chips have two buffers in -+ * each chip, which may be used for double buffered I/O; but this driver -+ * doesn't (yet) use these for any kind of i/o overlap or prefetching. -+ * -+ * Sometimes DataFlash is packaged in MMC-format cards, although the -+ * MMC stack can't use SPI (yet), or distinguish between MMC and DataFlash -+ * protocols during enumeration. -+ */ -+ -+#define CONFIG_DATAFLASH_WRITE_VERIFY -+ -+/* reads can bypass the buffers */ -+#define OP_READ_CONTINUOUS 0xE8 -+#define OP_READ_PAGE 0xD2 -+ -+/* group B requests can run even while status reports "busy" */ -+#define OP_READ_STATUS 0xD7 /* group B */ -+ -+/* move data between host and buffer */ -+#define OP_READ_BUFFER1 0xD4 /* group B */ -+#define OP_READ_BUFFER2 0xD6 /* group B */ -+#define OP_WRITE_BUFFER1 0x84 /* group B */ -+#define OP_WRITE_BUFFER2 0x87 /* group B */ -+ -+/* erasing flash */ -+#define OP_ERASE_PAGE 0x81 -+#define OP_ERASE_BLOCK 0x50 -+ -+/* move data between buffer and flash */ -+#define OP_TRANSFER_BUF1 0x53 -+#define OP_TRANSFER_BUF2 0x55 -+#define OP_MREAD_BUFFER1 0xD4 -+#define OP_MREAD_BUFFER2 0xD6 -+#define OP_MWERASE_BUFFER1 0x83 -+#define OP_MWERASE_BUFFER2 0x86 -+#define OP_MWRITE_BUFFER1 0x88 /* sector must be pre-erased */ -+#define OP_MWRITE_BUFFER2 0x89 /* sector must be pre-erased */ -+ -+/* write to buffer, then write-erase to flash */ -+#define OP_PROGRAM_VIA_BUF1 0x82 -+#define OP_PROGRAM_VIA_BUF2 0x85 -+ -+/* compare buffer to flash */ -+#define OP_COMPARE_BUF1 0x60 -+#define OP_COMPARE_BUF2 0x61 -+ -+/* read flash to buffer, then write-erase to flash */ -+#define OP_REWRITE_VIA_BUF1 0x58 -+#define OP_REWRITE_VIA_BUF2 0x59 -+ -+/* newer chips report JEDEC manufacturer and device IDs; chip -+ * serial number and OTP bits; and per-sector writeprotect. -+ */ -+#define OP_READ_ID 0x9F -+#define OP_READ_SECURITY 0x77 -+#define OP_WRITE_SECURITY 0x9A /* OTP bits */ -+ -+ -+struct dataflash { -+ u8 command[4]; -+ char name[24]; -+ -+ unsigned partitioned:1; -+ -+ unsigned short page_offset; /* offset in flash address */ -+ unsigned int page_size; /* of bytes per page */ -+ -+ struct semaphore lock; -+ struct spi_device *spi; -+ -+ struct mtd_info mtd; -+}; -+ -+#ifdef CONFIG_MTD_PARTITIONS -+#define mtd_has_partitions() (1) -+#else -+#define mtd_has_partitions() (0) -+#endif -+ -+/* ......................................................................... */ -+ -+/* -+ * Return the status of the DataFlash device. -+ */ -+static inline int dataflash_status(struct spi_device *spi) -+{ -+ /* NOTE: at45db321c over 25 MHz wants to write -+ * a dummy byte after the opcode... -+ */ -+ return spi_w8r8(spi, OP_READ_STATUS); -+} -+ -+/* -+ * Poll the DataFlash device until it is READY. -+ * This usually takes 5-20 msec or so; more for sector erase. -+ */ -+static int dataflash_waitready(struct spi_device *spi) -+{ -+ int status; -+ -+ for (;;) { -+ status = dataflash_status(spi); -+ if (status < 0) { -+ DEBUG(MTD_DEBUG_LEVEL1, "%s: status %d?\n", -+ spi->dev.bus_id, status); -+ status = 0; -+ } -+ -+ if (status & (1 << 7)) /* RDY/nBSY */ -+ return status; -+ -+ msleep(3); -+ } -+} -+ -+/* ......................................................................... */ -+ -+/* -+ * Erase pages of flash. -+ */ -+static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr) -+{ -+ struct dataflash *priv = (struct dataflash *)mtd->priv; -+ struct spi_device *spi = priv->spi; -+ struct spi_transfer x[1] = { { .tx_dma = 0, }, }; -+ struct spi_message msg; -+ unsigned blocksize = priv->page_size << 3; -+ u8 *command; -+ -+ DEBUG(MTD_DEBUG_LEVEL2, "%s: erase addr=0x%x len 0x%x\n", -+ spi->dev.bus_id, -+ instr->addr, instr->len); -+ -+ /* Sanity checks */ -+ if ((instr->addr + instr->len) > mtd->size -+ || (instr->len % priv->page_size) != 0 -+ || (instr->addr % priv->page_size) != 0) -+ return -EINVAL; -+ -+ x[0].tx_buf = command = priv->command; -+ x[0].len = 4; -+ msg.transfers = x; -+ msg.n_transfer = 1; -+ -+ down(&priv->lock); -+ while (instr->len > 0) { -+ unsigned int pageaddr; -+ int status; -+ int do_block; -+ -+ /* Calculate flash page address; use block erase (for speed) if -+ * we're at a block boundary and need to erase the whole block. -+ */ -+ pageaddr = instr->addr / priv->page_size; -+ do_block = (pageaddr & 0x7) == 0 && instr->len <= blocksize; -+ pageaddr = pageaddr << priv->page_offset; -+ -+ command[0] = do_block ? OP_ERASE_BLOCK : OP_ERASE_PAGE; -+ command[1] = (u8)(pageaddr >> 16); -+ command[2] = (u8)(pageaddr >> 8); -+ command[3] = 0; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "ERASE %s: (%x) %x %x %x [%i]\n", -+ do_block ? "block" : "page", -+ command[0], command[1], command[2], command[3], -+ pageaddr); -+ -+ status = spi_sync(spi, &msg); -+ (void) dataflash_waitready(spi); -+ -+ if (status < 0) { -+ printk(KERN_ERR "%s: erase %x, err %d\n", -+ spi->dev.bus_id, pageaddr, status); -+ /* REVISIT: can retry instr->retries times; or -+ * giveup and instr->fail_addr = instr->addr; -+ */ -+ continue; -+ } -+ -+ if (do_block) { -+ instr->addr += blocksize; -+ instr->len -= blocksize; -+ } else { -+ instr->addr += priv->page_size; -+ instr->len -= priv->page_size; -+ } -+ } -+ up(&priv->lock); -+ -+ /* Inform MTD subsystem that erase is complete */ -+ instr->state = MTD_ERASE_DONE; -+ mtd_erase_callback(instr); -+ -+ return 0; -+} -+ -+/* -+ * Read from the DataFlash device. -+ * from : Start offset in flash device -+ * len : Amount to read -+ * retlen : About of data actually read -+ * buf : Buffer containing the data -+ */ -+static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t *retlen, u_char *buf) -+{ -+ struct dataflash *priv = (struct dataflash *)mtd->priv; -+ struct spi_transfer x[2] = { { .tx_dma = 0, }, }; -+ struct spi_message msg; -+ unsigned int addr; -+ u8 *command; -+ int status; -+ -+ DEBUG(MTD_DEBUG_LEVEL2, "%s: read 0x%x..0x%x\n", -+ priv->spi->dev.bus_id, (unsigned)from, (unsigned)(from + len)); -+ -+ *retlen = 0; -+ -+ /* Sanity checks */ -+ if (!len) -+ return 0; -+ if (from + len > mtd->size) -+ return -EINVAL; -+ -+ /* Calculate flash page/byte address */ -+ addr = (((unsigned)from / priv->page_size) << priv->page_offset) -+ + ((unsigned)from % priv->page_size); -+ -+ command = priv->command; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "READ: (%x) %x %x %x\n", -+ command[0], command[1], command[2], command[3]); -+ -+ x[0].tx_buf = command; -+ x[0].len = 8; -+ x[1].rx_buf = buf; -+ x[1].len = len; -+ msg.transfers = x; -+ msg.n_transfer = 2; -+ -+ down(&priv->lock); -+ -+ /* Continuous read, max clock = f(car) which may be less than -+ * the peak rate available. Some chips support commands with -+ * fewer "don't care" bytes. Both buffers stay unchanged. -+ */ -+ command[0] = OP_READ_CONTINUOUS; -+ command[1] = (u8)(addr >> 16); -+ command[2] = (u8)(addr >> 8); -+ command[3] = (u8)(addr >> 0); -+ /* plus 4 "don't care" bytes */ -+ -+ status = spi_sync(priv->spi, &msg); -+ up(&priv->lock); -+ -+ if (status >= 0) { -+ *retlen = msg.actual_length - 8; -+ status = 0; -+ } else -+ DEBUG(MTD_DEBUG_LEVEL1, "%s: read %x..%x --> %d\n", -+ priv->spi->dev.bus_id, -+ (unsigned)from, (unsigned)(from + len), -+ status); -+ return status; -+} -+ -+/* -+ * Write to the DataFlash device. -+ * to : Start offset in flash device -+ * len : Amount to write -+ * retlen : Amount of data actually written -+ * buf : Buffer containing the data -+ */ -+static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t * retlen, const u_char * buf) -+{ -+ struct dataflash *priv = (struct dataflash *)mtd->priv; -+ struct spi_device *spi = priv->spi; -+ struct spi_transfer x[2] = { { .tx_dma = 0, }, }; -+ struct spi_message msg; -+ unsigned int pageaddr, addr, offset, writelen; -+ size_t remaining = len; -+ u_char *writebuf = (u_char *) buf; -+ int status = -EINVAL; -+ u8 *command; -+ -+ DEBUG(MTD_DEBUG_LEVEL2, "%s: write 0x%x..0x%x\n", -+ spi->dev.bus_id, (unsigned)to, (unsigned)(to + len)); -+ -+ *retlen = 0; -+ -+ /* Sanity checks */ -+ if (!len) -+ return 0; -+ if ((to + len) > mtd->size) -+ return -EINVAL; -+ -+ x[0].tx_buf = command = priv->command; -+ x[0].len = 4; -+ msg.transfers = x; -+ -+ pageaddr = ((unsigned)to / priv->page_size); -+ offset = ((unsigned)to % priv->page_size); -+ if (offset + len > priv->page_size) -+ writelen = priv->page_size - offset; -+ else -+ writelen = len; -+ -+ down(&priv->lock); -+ while (remaining > 0) { -+ DEBUG(MTD_DEBUG_LEVEL3, "write @ %i:%i len=%i\n", -+ pageaddr, offset, writelen); -+ -+ /* REVISIT: -+ * (a) each page in a sector must be rewritten at least -+ * once every 10K sibling erase/program operations. -+ * (b) for pages that are already erased, we could -+ * use WRITE+MWRITE not PROGRAM for ~30% speedup. -+ * (c) WRITE to buffer could be done while waiting for -+ * a previous MWRITE/MWERASE to complete ... -+ * (d) error handling here seems to be mostly missing. -+ * -+ * Two persistent bits per page, plus a per-sector counter, -+ * could support (a) and (b) ... we might consider using -+ * the second half of sector zero, which is just one block, -+ * to track that state. (On AT91, that sector should also -+ * support boot-from-DataFlash.) -+ */ -+ -+ addr = pageaddr << priv->page_offset; -+ -+ /* (1) Maybe transfer partial page to Buffer1 */ -+ if (writelen != priv->page_size) { -+ command[0] = OP_TRANSFER_BUF1; -+ command[1] = (addr & 0x00FF0000) >> 16; -+ command[2] = (addr & 0x0000FF00) >> 8; -+ command[3] = 0; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "TRANSFER: (%x) %x %x %x\n", -+ command[0], command[1], command[2], command[3]); -+ -+ msg.n_transfer = 1; -+ status = spi_sync(spi, &msg); -+ if (status < 0) -+ DEBUG(MTD_DEBUG_LEVEL1, "%s: xfer %u -> %d \n", -+ spi->dev.bus_id, addr, status); -+ -+ (void) dataflash_waitready(priv->spi); -+ } -+ -+ /* (2) Program full page via Buffer1 */ -+ addr += offset; -+ command[0] = OP_PROGRAM_VIA_BUF1; -+ command[1] = (addr & 0x00FF0000) >> 16; -+ command[2] = (addr & 0x0000FF00) >> 8; -+ command[3] = (addr & 0x000000FF); -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "PROGRAM: (%x) %x %x %x\n", -+ command[0], command[1], command[2], command[3]); -+ -+ x[1].tx_buf = writebuf; -+ x[1].len = writelen; -+ msg.n_transfer = 2; -+ status = spi_sync(spi, &msg); -+ if (status < 0) -+ DEBUG(MTD_DEBUG_LEVEL1, "%s: pgm %u/%u -> %d \n", -+ spi->dev.bus_id, addr, writelen, status); -+ -+ (void) dataflash_waitready(priv->spi); -+ -+#ifdef CONFIG_DATAFLASH_WRITE_VERIFY -+ -+ /* (3) Compare to Buffer1 */ -+ addr = pageaddr << priv->page_offset; -+ command[0] = OP_COMPARE_BUF1; -+ command[1] = (addr & 0x00FF0000) >> 16; -+ command[2] = (addr & 0x0000FF00) >> 8; -+ command[3] = 0; -+ -+ DEBUG(MTD_DEBUG_LEVEL3, "COMPARE: (%x) %x %x %x\n", -+ command[0], command[1], command[2], command[3]); -+ -+ msg.n_transfer = 1; -+ status = spi_sync(spi, &msg); -+ if (status < 0) -+ DEBUG(MTD_DEBUG_LEVEL1, "%s: compare %u -> %d \n", -+ spi->dev.bus_id, addr, status); -+ -+ status = dataflash_waitready(priv->spi); -+ -+ /* Check result of the compare operation */ -+ if ((status & (1 << 6)) == 1) { -+ printk(KERN_ERR "%s: compare page %u, err %d\n", -+ spi->dev.bus_id, pageaddr, status); -+ remaining = 0; -+ status = -EIO; -+ break; -+ } else -+ status = 0; -+ -+#endif /* CONFIG_DATAFLASH_WRITE_VERIFY */ -+ -+ remaining = remaining - writelen; -+ pageaddr++; -+ offset = 0; -+ writebuf += writelen; -+ *retlen += writelen; -+ -+ if (remaining > priv->page_size) -+ writelen = priv->page_size; -+ else -+ writelen = remaining; -+ } -+ up(&priv->lock); -+ -+ return status; -+} -+ -+/* ......................................................................... */ -+ -+/* -+ * Register DataFlash device with MTD subsystem. -+ */ -+static int __devinit -+add_dataflash(struct spi_device *spi, char *name, -+ int nr_pages, int pagesize, int pageoffset) -+{ -+ struct dataflash *priv; -+ struct mtd_info *device; -+ struct flash_platform_data *pdata = spi->dev.platform_data; -+ -+ priv = (struct dataflash *) kzalloc(sizeof *priv, GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ init_MUTEX(&priv->lock); -+ priv->spi = spi; -+ priv->page_size = pagesize; -+ priv->page_offset = pageoffset; -+ -+ /* name must be usable with cmdlinepart */ -+ sprintf(priv->name, "spi%d.%d-%s", -+ spi->master->bus_num, spi->chip_select, -+ name); -+ -+ device = &priv->mtd; -+ device->name = (pdata && pdata->name) ? pdata->name : priv->name; -+ device->size = nr_pages * pagesize; -+ device->erasesize = pagesize; -+ device->owner = THIS_MODULE; -+ device->type = MTD_DATAFLASH; -+ device->flags = MTD_CAP_NORFLASH; -+ device->erase = dataflash_erase; -+ device->read = dataflash_read; -+ device->write = dataflash_write; -+ device->priv = priv; -+ -+ dev_info(&spi->dev, "%s (%d KBytes)\n", name, device->size/1024); -+ dev_set_drvdata(&spi->dev, priv); -+ -+ if (mtd_has_partitions()) { -+ struct mtd_partition *parts; -+ int nr_parts = 0; -+ -+#ifdef CONFIG_MTD_CMDLINE_PARTS -+ static const char *part_probes[] = { "cmdlinepart", NULL, }; -+ -+ nr_parts = parse_mtd_partitions(device, part_probes, &parts, 0); -+#endif -+ -+ if (nr_parts <= 0 && pdata && pdata->parts) { -+ parts = pdata->parts; -+ nr_parts = pdata->nr_parts; -+ } -+ -+ if (nr_parts > 0) { -+ priv->partitioned = 1; -+ return add_mtd_partitions(device, parts, nr_parts); -+ } -+ } else if (pdata->nr_parts) -+ dev_warn(&spi->dev, "ignoring %d default partitions on %s\n", -+ pdata->nr_parts, device->name); -+ -+ return add_mtd_device(device) == 1 ? -ENODEV : 0; -+} -+ -+/* -+ * Detect and initialize DataFlash device: -+ * -+ * Device Density ID code #Pages PageSize Offset -+ * AT45DB011B 1Mbit (128K) xx0011xx (0x0c) 512 264 9 -+ * AT45DB021B 2Mbit (256K) xx0101xx (0x14) 1025 264 9 -+ * AT45DB041B 4Mbit (512K) xx0111xx (0x1c) 2048 264 9 -+ * AT45DB081B 8Mbit (1M) xx1001xx (0x24) 4096 264 9 -+ * AT45DB0161B 16Mbit (2M) xx1011xx (0x2c) 4096 528 10 -+ * AT45DB0321B 32Mbit (4M) xx1101xx (0x34) 8192 528 10 -+ * AT45DB0642 64Mbit (8M) xx111xxx (0x3c) 8192 1056 11 -+ * AT45DB1282 128Mbit (16M) xx0100xx (0x10) 16384 1056 11 -+ */ -+static int __devinit dataflash_probe(struct spi_device *spi) -+{ -+ int status; -+ -+ status = dataflash_status(spi); -+ if (status <= 0 || status == 0xff) { -+ DEBUG(MTD_DEBUG_LEVEL1, "%s: status error %d\n", -+ spi->dev.bus_id, status); -+ if (status == 0xff) -+ status = -ENODEV; -+ return status; -+ } -+ -+ /* if there's a device there, assume it's dataflash. -+ * board setup should have set spi->max_speed_max to -+ * match f(car) for continuous reads, mode 0 or 3. -+ */ -+ switch (status & 0x3c) { -+ case 0x0c: /* 0 0 1 1 x x */ -+ status = add_dataflash(spi, "AT45DB011B", 512, 264, 9); -+ break; -+ case 0x14: /* 0 1 0 1 x x */ -+ status = add_dataflash(spi, "AT45DB021B", 1025, 264, 9); -+ break; -+ case 0x1c: /* 0 1 1 1 x x */ -+ status = add_dataflash(spi, "AT45DB041x", 2048, 264, 9); -+ break; -+ case 0x24: /* 1 0 0 1 x x */ -+ status = add_dataflash(spi, "AT45DB081B", 4096, 264, 9); -+ break; -+ case 0x2c: /* 1 0 1 1 x x */ -+ status = add_dataflash(spi, "AT45DB161x", 4096, 528, 10); -+ break; -+ case 0x34: /* 1 1 0 1 x x */ -+ status = add_dataflash(spi, "AT45DB321x", 8192, 528, 10); -+ break; -+ case 0x38: /* 1 1 1 x x x */ -+ case 0x3c: -+ status = add_dataflash(spi, "AT45DB642x", 8192, 1056, 11); -+ break; -+ /* obsolete AT45DB1282 not (yet?) supported */ -+ default: -+ DEBUG(MTD_DEBUG_LEVEL1, "%s: unsupported device (%x)\n", -+ spi->dev.bus_id, status & 0x3c); -+ status = -ENODEV; -+ } -+ -+ if (status < 0) -+ DEBUG(MTD_DEBUG_LEVEL1, "%s: add_dataflash --> %d\n", -+ spi->dev.bus_id, status); -+ -+ return status; -+} -+ -+static int __devexit dataflash_remove(struct spi_device *spi) -+{ -+ struct dataflash *flash = dev_get_drvdata(&spi->dev); -+ int status; -+ -+ DEBUG(MTD_DEBUG_LEVEL1, "%s: remove\n", spi->dev.bus_id); -+ -+ if (mtd_has_partitions() && flash->partitioned) -+ status = del_mtd_partitions(&flash->mtd); -+ else -+ status = del_mtd_device(&flash->mtd); -+ if (status == 0) -+ kfree(flash); -+ return status; -+} -+ -+static struct spi_driver dataflash_driver = { -+ .driver = { -+ .name = "mtd_dataflash", -+ .bus = &spi_bus_type, -+ .owner = THIS_MODULE, -+ }, -+ -+ .probe = dataflash_probe, -+ .remove = __devexit_p(dataflash_remove), -+ -+ /* FIXME: investigate suspend and resume... */ -+}; -+ -+static int __init dataflash_init(void) -+{ -+ return spi_register_driver(&dataflash_driver); -+} -+module_init(dataflash_init); -+ -+static void __exit dataflash_exit(void) -+{ -+ spi_unregister_driver(&dataflash_driver); -+} -+module_exit(dataflash_exit); -+ -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Andrew Victor, David Brownell"); -+MODULE_DESCRIPTION("MTD DataFlash driver"); ---- /dev/null -+++ gregkh-2.6/include/linux/spi/flash.h -@@ -0,0 +1,27 @@ -+#ifndef LINUX_SPI_FLASH_H -+#define LINUX_SPI_FLASH_H -+ -+struct mtd_partition; -+ -+/** -+ * struct flash_platform_data: board-specific flash data -+ * @name: optional flash device name (eg, as used with mtdparts=) -+ * @parts: optional array of mtd_partitions for static partitioning -+ * @nr_parts: number of mtd_partitions for static partitoning -+ * -+ * Board init code (in arch/.../mach-xxx/board-yyy.c files) can -+ * provide information about SPI flash parts (such as DataFlash) to -+ * help set up the device and its appropriate default partitioning. -+ * -+ * Note that for DataFlash, sizes for pages, blocks, and sectors are -+ * rarely powers of two; and partitions should be sector-aligned. -+ */ -+struct flash_platform_data { -+ char *name; -+ struct mtd_partition *parts; -+ unsigned int nr_parts; -+ -+ /* we'll likely add more ... use JEDEC IDs, etc */ -+}; -+ -+#endif diff --git a/driver/spi-remove-fastcall-crap.patch b/driver/spi-remove-fastcall-crap.patch deleted file mode 100644 index 354eeb8711055..0000000000000 --- a/driver/spi-remove-fastcall-crap.patch +++ /dev/null @@ -1,56 +0,0 @@ -From akpm@osdl.org Wed Jan 11 13:10:30 2006 -Message-Id: <200601111924.k0BJO3aA003076@shell0.pdx.osdl.net> -From: Andrew Morton <akpm@osdl.org> -Subject: spi: remove fastcall crap -To: greg@kroah.com -Cc: akpm@osdl.org, david-b@pacbell.net -Date: Wed, 11 Jan 2006 11:23:49 -0800 - - -From: Andrew Morton <akpm@osdl.org> - -gcc4 generates warnings when a non-FASTCALL function pointer is assigned to a -FASTCALL one. Perhaps it has taste. - -Cc: David Brownell <david-b@pacbell.net> -Signed-off-by: Andrew Morton <akpm@osdl.org> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> ---- - drivers/spi/spi.c | 7 ++++++- - include/linux/spi/spi.h | 2 +- - 2 files changed, 7 insertions(+), 2 deletions(-) - ---- gregkh-2.6.orig/include/linux/spi/spi.h -+++ gregkh-2.6/include/linux/spi/spi.h -@@ -374,7 +374,7 @@ struct spi_message { - */ - - /* completion is reported through a callback */ -- void FASTCALL((*complete)(void *context)); -+ void (*complete)(void *context); - void *context; - unsigned actual_length; - int status; ---- gregkh-2.6.orig/drivers/spi/spi.c -+++ gregkh-2.6/drivers/spi/spi.c -@@ -480,6 +480,11 @@ EXPORT_SYMBOL_GPL(spi_busnum_to_master); - - /*-------------------------------------------------------------------------*/ - -+static void spi_complete(void *arg) -+{ -+ complete(arg); -+} -+ - /** - * spi_sync - blocking/synchronous SPI data transfers - * @spi: device with which data will be exchanged -@@ -508,7 +513,7 @@ int spi_sync(struct spi_device *spi, str - DECLARE_COMPLETION(done); - int status; - -- message->complete = (void (*)(void *)) complete; -+ message->complete = spi_complete; - message->context = &done; - status = spi_async(spi, message); - if (status == 0) diff --git a/driver/spi-simple-spi-framework.patch b/driver/spi-simple-spi-framework.patch deleted file mode 100644 index fbd5c86642a59..0000000000000 --- a/driver/spi-simple-spi-framework.patch +++ /dev/null @@ -1,1740 +0,0 @@ -From akpm@osdl.org Sun Jan 8 13:38:03 2006 -From: akpm@osdl.org -Message-Id: <200601082134.k08LYVu1004555@shell0.pdx.osdl.net> -Subject: [patch 01/10] spi: simple SPI framework -To: greg@kroah.com -Cc: akpm@osdl.org, david-b@pacbell.net, basicmark@yahoo.com, dbrownell@users.sourceforge.net -Date: Sun, 08 Jan 2006 13:34:19 -0800 - - -From: David Brownell <david-b@pacbell.net> - -This is the core of a small SPI framework, implementing the model of a -queue of messages which complete asynchronously (with thin synchronous -wrappers on top). - - - It's still less than 2KB of ".text" (ARM). If there's got to be a - mid-layer for something so simple, that's the right size budget. :) - - - The guts use board-specific SPI device tables to build the driver - model tree. (Hardware probing is rarely an option.) - - - This version of Kconfig includes no drivers. At this writing there - are two known master controller drivers (PXA/SSP, OMAP MicroWire) - and three protocol drivers (CS8415a, ADS7846, DataFlash) with LKML - mentions of other drivers in development. - - - No userspace API. There are several implementations to compare. - Implement them like any other driver, and bind them with sysfs. - -The changes from last version posted to LKML (on 11-Nov-2005) are minor, -and include: - - - One bugfix (removes a FIXME), with the visible effect of making device - names be "spiB.C" where B is the bus number and C is the chipselect. - - - The "caller provides DMA mappings" mechanism now has kerneldoc, for - DMA drivers that want to be fancy. - - - Hey, the framework init can be subsys_init. Even though board init - logic fires earlier, at arch_init ... since the framework init is - for driver support, and the board init support uses static init. - - - Various additional spec/doc clarifications based on discussions - with other folk. It adds a brief "thank you" at the end, for folk - who've helped nudge this framework into existence. - -As I've said before, I think that "protocol tweaking" is the main support -that this driver framework will need to evolve. - -From: Mark Underwood <basicmark@yahoo.com> - - Update the SPI framework to remove a potential priority inversion case by - reverting to kmalloc if the pre-allocated DMA-safe buffer isn't available. - -Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> -Signed-off-by: Andrew Morton <akpm@osdl.org> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> ---- - Documentation/spi/spi-summary | 416 ++++++++++++++++++++++++++++++ - arch/arm/Kconfig | 2 - drivers/Kconfig | 2 - drivers/Makefile | 1 - drivers/spi/Kconfig | 76 +++++ - drivers/spi/Makefile | 23 + - drivers/spi/spi.c | 568 ++++++++++++++++++++++++++++++++++++++++++ - include/linux/spi/spi.h | 542 ++++++++++++++++++++++++++++++++++++++++ - 8 files changed, 1630 insertions(+) - ---- gregkh-2.6.orig/arch/arm/Kconfig -+++ gregkh-2.6/arch/arm/Kconfig -@@ -729,6 +729,8 @@ source "drivers/char/Kconfig" - - source "drivers/i2c/Kconfig" - -+source "drivers/spi/Kconfig" -+ - source "drivers/hwmon/Kconfig" - - #source "drivers/l3/Kconfig" ---- /dev/null -+++ gregkh-2.6/Documentation/spi/spi-summary -@@ -0,0 +1,416 @@ -+Overview of Linux kernel SPI support -+==================================== -+ -+22-Nov-2005 -+ -+What is SPI? -+------------ -+The "Serial Peripheral Interface" (SPI) is a four-wire point-to-point -+serial link used to connect microcontrollers to sensors and memory. -+ -+The three signal wires hold a clock (SCLK, often on the order of 10 MHz), -+and parallel data lines with "Master Out, Slave In" (MOSI) or "Master In, -+Slave Out" (MISO) signals. (Other names are also used.) There are four -+clocking modes through which data is exchanged; mode-0 and mode-3 are most -+commonly used. -+ -+SPI masters may use a "chip select" line to activate a given SPI slave -+device, so those three signal wires may be connected to several chips -+in parallel. All SPI slaves support chipselects. Some devices have -+other signals, often including an interrupt to the master. -+ -+Unlike serial busses like USB or SMBUS, even low level protocols for -+SPI slave functions are usually not interoperable between vendors -+(except for cases like SPI memory chips). -+ -+ - SPI may be used for request/response style device protocols, as with -+ touchscreen sensors and memory chips. -+ -+ - It may also be used to stream data in either direction (half duplex), -+ or both of them at the same time (full duplex). -+ -+ - Some devices may use eight bit words. Others may different word -+ lengths, such as streams of 12-bit or 20-bit digital samples. -+ -+In the same way, SPI slaves will only rarely support any kind of automatic -+discovery/enumeration protocol. The tree of slave devices accessible from -+a given SPI master will normally be set up manually, with configuration -+tables. -+ -+SPI is only one of the names used by such four-wire protocols, and -+most controllers have no problem handling "MicroWire" (think of it as -+half-duplex SPI, for request/response protocols), SSP ("Synchronous -+Serial Protocol"), PSP ("Programmable Serial Protocol"), and other -+related protocols. -+ -+Microcontrollers often support both master and slave sides of the SPI -+protocol. This document (and Linux) currently only supports the master -+side of SPI interactions. -+ -+ -+Who uses it? On what kinds of systems? -+--------------------------------------- -+Linux developers using SPI are probably writing device drivers for embedded -+systems boards. SPI is used to control external chips, and it is also a -+protocol supported by every MMC or SD memory card. (The older "DataFlash" -+cards, predating MMC cards but using the same connectors and card shape, -+support only SPI.) Some PC hardware uses SPI flash for BIOS code. -+ -+SPI slave chips range from digital/analog converters used for analog -+sensors and codecs, to memory, to peripherals like USB controllers -+or Ethernet adapters; and more. -+ -+Most systems using SPI will integrate a few devices on a mainboard. -+Some provide SPI links on expansion connectors; in cases where no -+dedicated SPI controller exists, GPIO pins can be used to create a -+low speed "bitbanging" adapter. Very few systems will "hotplug" an SPI -+controller; the reasons to use SPI focus on low cost and simple operation, -+and if dynamic reconfiguration is important, USB will often be a more -+appropriate low-pincount peripheral bus. -+ -+Many microcontrollers that can run Linux integrate one or more I/O -+interfaces with SPI modes. Given SPI support, they could use MMC or SD -+cards without needing a special purpose MMC/SD/SDIO controller. -+ -+ -+How do these driver programming interfaces work? -+------------------------------------------------ -+The <linux/spi/spi.h> header file includes kerneldoc, as does the -+main source code, and you should certainly read that. This is just -+an overview, so you get the big picture before the details. -+ -+There are two types of SPI driver, here called: -+ -+ Controller drivers ... these are often built in to System-On-Chip -+ processors, and often support both Master and Slave roles. -+ These drivers touch hardware registers and may use DMA. -+ -+ Protocol drivers ... these pass messages through the controller -+ driver to communicate with a Slave or Master device on the -+ other side of an SPI link. -+ -+So for example one protocol driver might talk to the MTD layer to export -+data to filesystems stored on SPI flash like DataFlash; and others might -+control audio interfaces, present touchscreen sensors as input interfaces, -+or monitor temperature and voltage levels during industrial processing. -+And those might all be sharing the same controller driver. -+ -+A "struct spi_device" encapsulates the master-side interface between -+those two types of driver. At this writing, Linux has no slave side -+programming interface. -+ -+There is a minimal core of SPI programming interfaces, focussing on -+using driver model to connect controller and protocol drivers using -+device tables provided by board specific initialization code. SPI -+shows up in sysfs in several locations: -+ -+ /sys/devices/.../CTLR/spiB.C ... spi_device for on bus "B", -+ chipselect C, accessed through CTLR. -+ -+ /sys/bus/spi/devices/spiB.C ... symlink to the physical -+ spiB-C device -+ -+ /sys/bus/spi/drivers/D ... driver for one or more spi*.* devices -+ -+ /sys/class/spi_master/spiB ... class device for the controller -+ managing bus "B". All the spiB.* devices share the same -+ physical SPI bus segment, with SCLK, MOSI, and MISO. -+ -+The basic I/O primitive submits an asynchronous message to an I/O queue -+maintained by the controller driver. A completion callback is issued -+asynchronously when the data transfer(s) in that message completes. -+There are also some simple synchronous wrappers for those calls. -+ -+ -+How does board-specific init code declare SPI devices? -+------------------------------------------------------ -+Linux needs several kinds of information to properly configure SPI devices. -+That information is normally provided by board-specific code, even for -+chips that do support some of automated discovery/enumeration. -+ -+DECLARE CONTROLLERS -+ -+The first kind of information is a list of what SPI controllers exist. -+For System-on-Chip (SOC) based boards, these will usually be platform -+devices, and the controller may need some platform_data in order to -+operate properly. The "struct platform_device" will include resources -+like the physical address of the controller's first register and its IRQ. -+ -+Platforms will often abstract the "register SPI controller" operation, -+maybe coupling it with code to initialize pin configurations, so that -+the arch/.../mach-*/board-*.c files for several boards can all share the -+same basic controller setup code. This is because most SOCs have several -+SPI-capable controllers, and only the ones actually usable on a given -+board should normally be set up and registered. -+ -+So for example arch/.../mach-*/board-*.c files might have code like: -+ -+ #include <asm/arch/spi.h> /* for mysoc_spi_data */ -+ -+ /* if your mach-* infrastructure doesn't support kernels that can -+ * run on multiple boards, pdata wouldn't benefit from "__init". -+ */ -+ static struct mysoc_spi_data __init pdata = { ... }; -+ -+ static __init board_init(void) -+ { -+ ... -+ /* this board only uses SPI controller #2 */ -+ mysoc_register_spi(2, &pdata); -+ ... -+ } -+ -+And SOC-specific utility code might look something like: -+ -+ #include <asm/arch/spi.h> -+ -+ static struct platform_device spi2 = { ... }; -+ -+ void mysoc_register_spi(unsigned n, struct mysoc_spi_data *pdata) -+ { -+ struct mysoc_spi_data *pdata2; -+ -+ pdata2 = kmalloc(sizeof *pdata2, GFP_KERNEL); -+ *pdata2 = pdata; -+ ... -+ if (n == 2) { -+ spi2->dev.platform_data = pdata2; -+ register_platform_device(&spi2); -+ -+ /* also: set up pin modes so the spi2 signals are -+ * visible on the relevant pins ... bootloaders on -+ * production boards may already have done this, but -+ * developer boards will often need Linux to do it. -+ */ -+ } -+ ... -+ } -+ -+Notice how the platform_data for boards may be different, even if the -+same SOC controller is used. For example, on one board SPI might use -+an external clock, where another derives the SPI clock from current -+settings of some master clock. -+ -+ -+DECLARE SLAVE DEVICES -+ -+The second kind of information is a list of what SPI slave devices exist -+on the target board, often with some board-specific data needed for the -+driver to work correctly. -+ -+Normally your arch/.../mach-*/board-*.c files would provide a small table -+listing the SPI devices on each board. (This would typically be only a -+small handful.) That might look like: -+ -+ static struct ads7846_platform_data ads_info = { -+ .vref_delay_usecs = 100, -+ .x_plate_ohms = 580, -+ .y_plate_ohms = 410, -+ }; -+ -+ static struct spi_board_info spi_board_info[] __initdata = { -+ { -+ .modalias = "ads7846", -+ .platform_data = &ads_info, -+ .mode = SPI_MODE_0, -+ .irq = GPIO_IRQ(31), -+ .max_speed_hz = 120000 /* max sample rate at 3V */ * 16, -+ .bus_num = 1, -+ .chip_select = 0, -+ }, -+ }; -+ -+Again, notice how board-specific information is provided; each chip may need -+several types. This example shows generic constraints like the fastest SPI -+clock to allow (a function of board voltage in this case) or how an IRQ pin -+is wired, plus chip-specific constraints like an important delay that's -+changed by the capacitance at one pin. -+ -+(There's also "controller_data", information that may be useful to the -+controller driver. An example would be peripheral-specific DMA tuning -+data or chipselect callbacks. This is stored in spi_device later.) -+ -+The board_info should provide enough information to let the system work -+without the chip's driver being loaded. The most troublesome aspect of -+that is likely the SPI_CS_HIGH bit in the spi_device.mode field, since -+sharing a bus with a device that interprets chipselect "backwards" is -+not possible. -+ -+Then your board initialization code would register that table with the SPI -+infrastructure, so that it's available later when the SPI master controller -+driver is registered: -+ -+ spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); -+ -+Like with other static board-specific setup, you won't unregister those. -+ -+ -+NON-STATIC CONFIGURATIONS -+ -+Developer boards often play by different rules than product boards, and one -+example is the potential need to hotplug SPI devices and/or controllers. -+ -+For those cases you might need to use use spi_busnum_to_master() to look -+up the spi bus master, and will likely need spi_new_device() to provide the -+board info based on the board that was hotplugged. Of course, you'd later -+call at least spi_unregister_device() when that board is removed. -+ -+ -+How do I write an "SPI Protocol Driver"? -+---------------------------------------- -+All SPI drivers are currently kernel drivers. A userspace driver API -+would just be another kernel driver, probably offering some lowlevel -+access through aio_read(), aio_write(), and ioctl() calls and using the -+standard userspace sysfs mechanisms to bind to a given SPI device. -+ -+SPI protocol drivers are normal device drivers, with no more wrapper -+than needed by platform devices: -+ -+ static struct device_driver CHIP_driver = { -+ .name = "CHIP", -+ .bus = &spi_bus_type, -+ .probe = CHIP_probe, -+ .remove = __exit_p(CHIP_remove), -+ .suspend = CHIP_suspend, -+ .resume = CHIP_resume, -+ }; -+ -+The SPI core will autmatically attempt to bind this driver to any SPI -+device whose board_info gave a modalias of "CHIP". Your probe() code -+might look like this unless you're creating a class_device: -+ -+ static int __init CHIP_probe(struct device *dev) -+ { -+ struct spi_device *spi = to_spi_device(dev); -+ struct CHIP *chip; -+ struct CHIP_platform_data *pdata = dev->platform_data; -+ -+ /* get memory for driver's per-chip state */ -+ chip = kzalloc(sizeof *chip, GFP_KERNEL); -+ if (!chip) -+ return -ENOMEM; -+ dev_set_drvdata(dev, chip); -+ -+ ... etc -+ return 0; -+ } -+ -+As soon as it enters probe(), the driver may issue I/O requests to -+the SPI device using "struct spi_message". When remove() returns, -+the driver guarantees that it won't submit any more such messages. -+ -+ - An spi_message is a sequence of of protocol operations, executed -+ as one atomic sequence. SPI driver controls include: -+ -+ + when bidirectional reads and writes start ... by how its -+ sequence of spi_transfer requests is arranged; -+ -+ + optionally defining short delays after transfers ... using -+ the spi_transfer.delay_usecs setting; -+ -+ + whether the chipselect becomes inactive after a transfer and -+ any delay ... by using the spi_transfer.cs_change flag; -+ -+ + hinting whether the next message is likely to go to this same -+ device ... using the spi_transfer.cs_change flag on the last -+ transfer in that atomic group, and potentially saving costs -+ for chip deselect and select operations. -+ -+ - Follow standard kernel rules, and provide DMA-safe buffers in -+ your messages. That way controller drivers using DMA aren't forced -+ to make extra copies unless the hardware requires it (e.g. working -+ around hardware errata that force the use of bounce buffering). -+ -+ If standard dma_map_single() handling of these buffers is inappropriate, -+ you can use spi_message.is_dma_mapped to tell the controller driver -+ that you've already provided the relevant DMA addresses. -+ -+ - The basic I/O primitive is spi_async(). Async requests may be -+ issued in any context (irq handler, task, etc) and completion -+ is reported using a callback provided with the message. -+ -+ - There are also synchronous wrappers like spi_sync(), and wrappers -+ like spi_read(), spi_write(), and spi_write_then_read(). These -+ may be issued only in contexts that may sleep, and they're all -+ clean (and small, and "optional") layers over spi_async(). -+ -+ - The spi_write_then_read() call, and convenience wrappers around -+ it, should only be used with small amounts of data where the -+ cost of an extra copy may be ignored. It's designed to support -+ common RPC-style requests, such as writing an eight bit command -+ and reading a sixteen bit response -- spi_w8r16() being one its -+ wrappers, doing exactly that. -+ -+Some drivers may need to modify spi_device characteristics like the -+transfer mode, wordsize, or clock rate. This is done with spi_setup(), -+which would normally be called from probe() before the first I/O is -+done to the device. -+ -+While "spi_device" would be the bottom boundary of the driver, the -+upper boundaries might include sysfs (especially for sensor readings), -+the input layer, ALSA, networking, MTD, the character device framework, -+or other Linux subsystems. -+ -+ -+How do I write an "SPI Master Controller Driver"? -+------------------------------------------------- -+An SPI controller will probably be registered on the platform_bus; write -+a driver to bind to the device, whichever bus is involved. -+ -+The main task of this type of driver is to provide an "spi_master". -+Use spi_alloc_master() to allocate the master, and class_get_devdata() -+to get the driver-private data allocated for that device. -+ -+ struct spi_master *master; -+ struct CONTROLLER *c; -+ -+ master = spi_alloc_master(dev, sizeof *c); -+ if (!master) -+ return -ENODEV; -+ -+ c = class_get_devdata(&master->cdev); -+ -+The driver will initialize the fields of that spi_master, including the -+bus number (maybe the same as the platform device ID) and three methods -+used to interact with the SPI core and SPI protocol drivers. It will -+also initialize its own internal state. -+ -+ master->setup(struct spi_device *spi) -+ This sets up the device clock rate, SPI mode, and word sizes. -+ Drivers may change the defaults provided by board_info, and then -+ call spi_setup(spi) to invoke this routine. It may sleep. -+ -+ master->transfer(struct spi_device *spi, struct spi_message *message) -+ This must not sleep. Its responsibility is arrange that the -+ transfer happens and its complete() callback is issued; the two -+ will normally happen later, after other transfers complete. -+ -+ master->cleanup(struct spi_device *spi) -+ Your controller driver may use spi_device.controller_state to hold -+ state it dynamically associates with that device. If you do that, -+ be sure to provide the cleanup() method to free that state. -+ -+The bulk of the driver will be managing the I/O queue fed by transfer(). -+ -+That queue could be purely conceptual. For example, a driver used only -+for low-frequency sensor acess might be fine using synchronous PIO. -+ -+But the queue will probably be very real, using message->queue, PIO, -+often DMA (especially if the root filesystem is in SPI flash), and -+execution contexts like IRQ handlers, tasklets, or workqueues (such -+as keventd). Your driver can be as fancy, or as simple, as you need. -+ -+ -+THANKS TO -+--------- -+Contributors to Linux-SPI discussions include (in alphabetical order, -+by last name): -+ -+David Brownell -+Russell King -+Dmitry Pervushin -+Stephen Street -+Mark Underwood -+Andrew Victor -+Vitaly Wool -+ ---- gregkh-2.6.orig/drivers/Kconfig -+++ gregkh-2.6/drivers/Kconfig -@@ -44,6 +44,8 @@ source "drivers/char/Kconfig" - - source "drivers/i2c/Kconfig" - -+source "drivers/spi/Kconfig" -+ - source "drivers/w1/Kconfig" - - source "drivers/hwmon/Kconfig" ---- gregkh-2.6.orig/drivers/Makefile -+++ gregkh-2.6/drivers/Makefile -@@ -41,6 +41,7 @@ obj-$(CONFIG_FUSION) += message/ - obj-$(CONFIG_IEEE1394) += ieee1394/ - obj-y += cdrom/ - obj-$(CONFIG_MTD) += mtd/ -+obj-$(CONFIG_SPI) += spi/ - obj-$(CONFIG_PCCARD) += pcmcia/ - obj-$(CONFIG_DIO) += dio/ - obj-$(CONFIG_SBUS) += sbus/ ---- /dev/null -+++ gregkh-2.6/drivers/spi/Kconfig -@@ -0,0 +1,76 @@ -+# -+# SPI driver configuration -+# -+# NOTE: the reason this doesn't show SPI slave support is mostly that -+# nobody's needed a slave side API yet. The master-role API is not -+# fully appropriate there, so it'd need some thought to do well. -+# -+menu "SPI support" -+ -+config SPI -+ bool "SPI support" -+ help -+ The "Serial Peripheral Interface" is a low level synchronous -+ protocol. Chips that support SPI can have data transfer rates -+ up to several tens of Mbit/sec. Chips are addressed with a -+ controller and a chipselect. Most SPI slaves don't support -+ dynamic device discovery; some are even write-only or read-only. -+ -+ SPI is widely used by microcontollers to talk with sensors, -+ eeprom and flash memory, codecs and various other controller -+ chips, analog to digital (and d-to-a) converters, and more. -+ MMC and SD cards can be accessed using SPI protocol; and for -+ DataFlash cards used in MMC sockets, SPI must always be used. -+ -+ SPI is one of a family of similar protocols using a four wire -+ interface (select, clock, data in, data out) including Microwire -+ (half duplex), SSP, SSI, and PSP. This driver framework should -+ work with most such devices and controllers. -+ -+config SPI_DEBUG -+ boolean "Debug support for SPI drivers" -+ depends on SPI && DEBUG_KERNEL -+ help -+ Say "yes" to enable debug messaging (like dev_dbg and pr_debug), -+ sysfs, and debugfs support in SPI controller and protocol drivers. -+ -+# -+# MASTER side ... talking to discrete SPI slave chips including microcontrollers -+# -+ -+config SPI_MASTER -+# boolean "SPI Master Support" -+ boolean -+ default SPI -+ help -+ If your system has an master-capable SPI controller (which -+ provides the clock and chipselect), you can enable that -+ controller and the protocol drivers for the SPI slave chips -+ that are connected. -+ -+comment "SPI Master Controller Drivers" -+ depends on SPI_MASTER -+ -+ -+# -+# Add new SPI master controllers in alphabetical order above this line -+# -+ -+ -+# -+# There are lots of SPI device types, with sensors and memory -+# being probably the most widely used ones. -+# -+comment "SPI Protocol Masters" -+ depends on SPI_MASTER -+ -+ -+# -+# Add new SPI protocol masters in alphabetical order above this line -+# -+ -+ -+# (slave support would go here) -+ -+endmenu # "SPI support" -+ ---- /dev/null -+++ gregkh-2.6/drivers/spi/Makefile -@@ -0,0 +1,23 @@ -+# -+# Makefile for kernel SPI drivers. -+# -+ -+ifeq ($(CONFIG_SPI_DEBUG),y) -+EXTRA_CFLAGS += -DDEBUG -+endif -+ -+# small core, mostly translating board-specific -+# config declarations into driver model code -+obj-$(CONFIG_SPI_MASTER) += spi.o -+ -+# SPI master controller drivers (bus) -+# ... add above this line ... -+ -+# SPI protocol drivers (device/link on bus) -+# ... add above this line ... -+ -+# SPI slave controller drivers (upstream link) -+# ... add above this line ... -+ -+# SPI slave drivers (protocol for that link) -+# ... add above this line ... ---- /dev/null -+++ gregkh-2.6/drivers/spi/spi.c -@@ -0,0 +1,568 @@ -+/* -+ * spi.c - SPI init/core code -+ * -+ * Copyright (C) 2005 David Brownell -+ * -+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#include <linux/autoconf.h> -+#include <linux/kernel.h> -+#include <linux/device.h> -+#include <linux/init.h> -+#include <linux/cache.h> -+#include <linux/spi/spi.h> -+ -+ -+/* SPI bustype and spi_master class are registered during early boot, -+ * usually before board init code provides the SPI device tables, and -+ * are available later when driver init code needs them. -+ * -+ * Drivers for SPI devices started out like those for platform bus -+ * devices. But both have changed in 2.6.15; maybe this should get -+ * an "spi_driver" structure at some point (not currently needed) -+ */ -+static void spidev_release(struct device *dev) -+{ -+ const struct spi_device *spi = to_spi_device(dev); -+ -+ /* spi masters may cleanup for released devices */ -+ if (spi->master->cleanup) -+ spi->master->cleanup(spi); -+ -+ class_device_put(&spi->master->cdev); -+ kfree(dev); -+} -+ -+static ssize_t -+modalias_show(struct device *dev, struct device_attribute *a, char *buf) -+{ -+ const struct spi_device *spi = to_spi_device(dev); -+ -+ return snprintf(buf, BUS_ID_SIZE + 1, "%s\n", spi->modalias); -+} -+ -+static struct device_attribute spi_dev_attrs[] = { -+ __ATTR_RO(modalias), -+ __ATTR_NULL, -+}; -+ -+/* modalias support makes "modprobe $MODALIAS" new-style hotplug work, -+ * and the sysfs version makes coldplug work too. -+ */ -+ -+static int spi_match_device(struct device *dev, struct device_driver *drv) -+{ -+ const struct spi_device *spi = to_spi_device(dev); -+ -+ return strncmp(spi->modalias, drv->name, BUS_ID_SIZE) == 0; -+} -+ -+static int spi_uevent(struct device *dev, char **envp, int num_envp, -+ char *buffer, int buffer_size) -+{ -+ const struct spi_device *spi = to_spi_device(dev); -+ -+ envp[0] = buffer; -+ snprintf(buffer, buffer_size, "MODALIAS=%s", spi->modalias); -+ envp[1] = NULL; -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+ -+/* Suspend/resume in "struct device_driver" don't really need that -+ * strange third parameter, so we just make it a constant and expect -+ * SPI drivers to ignore it just like most platform drivers do. -+ * -+ * NOTE: the suspend() method for an spi_master controller driver -+ * should verify that all its child devices are marked as suspended; -+ * suspend requests delivered through sysfs power/state files don't -+ * enforce such constraints. -+ */ -+static int spi_suspend(struct device *dev, pm_message_t message) -+{ -+ int value; -+ -+ if (!dev->driver || !dev->driver->suspend) -+ return 0; -+ -+ /* suspend will stop irqs and dma; no more i/o */ -+ value = dev->driver->suspend(dev, message); -+ if (value == 0) -+ dev->power.power_state = message; -+ return value; -+} -+ -+static int spi_resume(struct device *dev) -+{ -+ int value; -+ -+ if (!dev->driver || !dev->driver->resume) -+ return 0; -+ -+ /* resume may restart the i/o queue */ -+ value = dev->driver->resume(dev); -+ if (value == 0) -+ dev->power.power_state = PMSG_ON; -+ return value; -+} -+ -+#else -+#define spi_suspend NULL -+#define spi_resume NULL -+#endif -+ -+struct bus_type spi_bus_type = { -+ .name = "spi", -+ .dev_attrs = spi_dev_attrs, -+ .match = spi_match_device, -+ .uevent = spi_uevent, -+ .suspend = spi_suspend, -+ .resume = spi_resume, -+}; -+EXPORT_SYMBOL_GPL(spi_bus_type); -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* SPI devices should normally not be created by SPI device drivers; that -+ * would make them board-specific. Similarly with SPI master drivers. -+ * Device registration normally goes into like arch/.../mach.../board-YYY.c -+ * with other readonly (flashable) information about mainboard devices. -+ */ -+ -+struct boardinfo { -+ struct list_head list; -+ unsigned n_board_info; -+ struct spi_board_info board_info[0]; -+}; -+ -+static LIST_HEAD(board_list); -+static DECLARE_MUTEX(board_lock); -+ -+ -+/* On typical mainboards, this is purely internal; and it's not needed -+ * after board init creates the hard-wired devices. Some development -+ * platforms may not be able to use spi_register_board_info though, and -+ * this is exported so that for example a USB or parport based adapter -+ * driver could add devices (which it would learn about out-of-band). -+ */ -+struct spi_device *__init_or_module -+spi_new_device(struct spi_master *master, struct spi_board_info *chip) -+{ -+ struct spi_device *proxy; -+ struct device *dev = master->cdev.dev; -+ int status; -+ -+ /* NOTE: caller did any chip->bus_num checks necessary */ -+ -+ if (!class_device_get(&master->cdev)) -+ return NULL; -+ -+ proxy = kzalloc(sizeof *proxy, GFP_KERNEL); -+ if (!proxy) { -+ dev_err(dev, "can't alloc dev for cs%d\n", -+ chip->chip_select); -+ goto fail; -+ } -+ proxy->master = master; -+ proxy->chip_select = chip->chip_select; -+ proxy->max_speed_hz = chip->max_speed_hz; -+ proxy->irq = chip->irq; -+ proxy->modalias = chip->modalias; -+ -+ snprintf(proxy->dev.bus_id, sizeof proxy->dev.bus_id, -+ "%s.%u", master->cdev.class_id, -+ chip->chip_select); -+ proxy->dev.parent = dev; -+ proxy->dev.bus = &spi_bus_type; -+ proxy->dev.platform_data = (void *) chip->platform_data; -+ proxy->controller_data = chip->controller_data; -+ proxy->controller_state = NULL; -+ proxy->dev.release = spidev_release; -+ -+ /* drivers may modify this default i/o setup */ -+ status = master->setup(proxy); -+ if (status < 0) { -+ dev_dbg(dev, "can't %s %s, status %d\n", -+ "setup", proxy->dev.bus_id, status); -+ goto fail; -+ } -+ -+ /* driver core catches callers that misbehave by defining -+ * devices that already exist. -+ */ -+ status = device_register(&proxy->dev); -+ if (status < 0) { -+ dev_dbg(dev, "can't %s %s, status %d\n", -+ "add", proxy->dev.bus_id, status); -+fail: -+ class_device_put(&master->cdev); -+ kfree(proxy); -+ return NULL; -+ } -+ dev_dbg(dev, "registered child %s\n", proxy->dev.bus_id); -+ return proxy; -+} -+EXPORT_SYMBOL_GPL(spi_new_device); -+ -+/* -+ * Board-specific early init code calls this (probably during arch_initcall) -+ * with segments of the SPI device table. Any device nodes are created later, -+ * after the relevant parent SPI controller (bus_num) is defined. We keep -+ * this table of devices forever, so that reloading a controller driver will -+ * not make Linux forget about these hard-wired devices. -+ * -+ * Other code can also call this, e.g. a particular add-on board might provide -+ * SPI devices through its expansion connector, so code initializing that board -+ * would naturally declare its SPI devices. -+ * -+ * The board info passed can safely be __initdata ... but be careful of -+ * any embedded pointers (platform_data, etc), they're copied as-is. -+ */ -+int __init -+spi_register_board_info(struct spi_board_info const *info, unsigned n) -+{ -+ struct boardinfo *bi; -+ -+ bi = kmalloc (sizeof (*bi) + n * sizeof (*info), GFP_KERNEL); -+ if (!bi) -+ return -ENOMEM; -+ bi->n_board_info = n; -+ memcpy(bi->board_info, info, n * sizeof (*info)); -+ -+ down(&board_lock); -+ list_add_tail(&bi->list, &board_list); -+ up(&board_lock); -+ return 0; -+} -+EXPORT_SYMBOL_GPL(spi_register_board_info); -+ -+/* FIXME someone should add support for a __setup("spi", ...) that -+ * creates board info from kernel command lines -+ */ -+ -+static void __init_or_module -+scan_boardinfo(struct spi_master *master) -+{ -+ struct boardinfo *bi; -+ struct device *dev = master->cdev.dev; -+ -+ down(&board_lock); -+ list_for_each_entry(bi, &board_list, list) { -+ struct spi_board_info *chip = bi->board_info; -+ unsigned n; -+ -+ for (n = bi->n_board_info; n > 0; n--, chip++) { -+ if (chip->bus_num != master->bus_num) -+ continue; -+ /* some controllers only have one chip, so they -+ * might not use chipselects. otherwise, the -+ * chipselects are numbered 0..max. -+ */ -+ if (chip->chip_select >= master->num_chipselect -+ && master->num_chipselect) { -+ dev_dbg(dev, "cs%d > max %d\n", -+ chip->chip_select, -+ master->num_chipselect); -+ continue; -+ } -+ (void) spi_new_device(master, chip); -+ } -+ } -+ up(&board_lock); -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+static void spi_master_release(struct class_device *cdev) -+{ -+ struct spi_master *master; -+ -+ master = container_of(cdev, struct spi_master, cdev); -+ put_device(master->cdev.dev); -+ master->cdev.dev = NULL; -+ kfree(master); -+} -+ -+static struct class spi_master_class = { -+ .name = "spi_master", -+ .owner = THIS_MODULE, -+ .release = spi_master_release, -+}; -+ -+ -+/** -+ * spi_alloc_master - allocate SPI master controller -+ * @dev: the controller, possibly using the platform_bus -+ * @size: how much driver-private data to preallocate; a pointer to this -+ * memory in the class_data field of the returned class_device -+ * -+ * This call is used only by SPI master controller drivers, which are the -+ * only ones directly touching chip registers. It's how they allocate -+ * an spi_master structure, prior to calling spi_add_master(). -+ * -+ * This must be called from context that can sleep. It returns the SPI -+ * master structure on success, else NULL. -+ * -+ * The caller is responsible for assigning the bus number and initializing -+ * the master's methods before calling spi_add_master(), or else (on error) -+ * calling class_device_put() to prevent a memory leak. -+ */ -+struct spi_master * __init_or_module -+spi_alloc_master(struct device *dev, unsigned size) -+{ -+ struct spi_master *master; -+ -+ master = kzalloc(size + sizeof *master, SLAB_KERNEL); -+ if (!master) -+ return NULL; -+ -+ master->cdev.class = &spi_master_class; -+ master->cdev.dev = get_device(dev); -+ class_set_devdata(&master->cdev, &master[1]); -+ -+ return master; -+} -+EXPORT_SYMBOL_GPL(spi_alloc_master); -+ -+/** -+ * spi_register_master - register SPI master controller -+ * @master: initialized master, originally from spi_alloc_master() -+ * -+ * SPI master controllers connect to their drivers using some non-SPI bus, -+ * such as the platform bus. The final stage of probe() in that code -+ * includes calling spi_register_master() to hook up to this SPI bus glue. -+ * -+ * SPI controllers use board specific (often SOC specific) bus numbers, -+ * and board-specific addressing for SPI devices combines those numbers -+ * with chip select numbers. Since SPI does not directly support dynamic -+ * device identification, boards need configuration tables telling which -+ * chip is at which address. -+ * -+ * This must be called from context that can sleep. It returns zero on -+ * success, else a negative error code (dropping the master's refcount). -+ */ -+int __init_or_module -+spi_register_master(struct spi_master *master) -+{ -+ static atomic_t dyn_bus_id = ATOMIC_INIT(0); -+ struct device *dev = master->cdev.dev; -+ int status = -ENODEV; -+ int dynamic = 0; -+ -+ /* convention: dynamically assigned bus IDs count down from the max */ -+ if (master->bus_num == 0) { -+ master->bus_num = atomic_dec_return(&dyn_bus_id); -+ dynamic = 0; -+ } -+ -+ /* register the device, then userspace will see it. -+ * registration fails if the bus ID is in use. -+ */ -+ snprintf(master->cdev.class_id, sizeof master->cdev.class_id, -+ "spi%u", master->bus_num); -+ status = class_device_register(&master->cdev); -+ if (status < 0) { -+ class_device_put(&master->cdev); -+ goto done; -+ } -+ dev_dbg(dev, "registered master %s%s\n", master->cdev.class_id, -+ dynamic ? " (dynamic)" : ""); -+ -+ /* populate children from any spi device tables */ -+ scan_boardinfo(master); -+ status = 0; -+done: -+ return status; -+} -+EXPORT_SYMBOL_GPL(spi_register_master); -+ -+ -+static int __unregister(struct device *dev, void *unused) -+{ -+ /* note: before about 2.6.14-rc1 this would corrupt memory: */ -+ device_unregister(dev); -+ return 0; -+} -+ -+/** -+ * spi_unregister_master - unregister SPI master controller -+ * @master: the master being unregistered -+ * -+ * This call is used only by SPI master controller drivers, which are the -+ * only ones directly touching chip registers. -+ * -+ * This must be called from context that can sleep. -+ */ -+void spi_unregister_master(struct spi_master *master) -+{ -+ class_device_unregister(&master->cdev); -+ (void) device_for_each_child(master->cdev.dev, NULL, __unregister); -+} -+EXPORT_SYMBOL_GPL(spi_unregister_master); -+ -+/** -+ * spi_busnum_to_master - look up master associated with bus_num -+ * @bus_num: the master's bus number -+ * -+ * This call may be used with devices that are registered after -+ * arch init time. It returns a refcounted pointer to the relevant -+ * spi_master (which the caller must release), or NULL if there is -+ * no such master registered. -+ */ -+struct spi_master *spi_busnum_to_master(u16 bus_num) -+{ -+ if (bus_num) { -+ char name[8]; -+ struct kobject *bus; -+ -+ snprintf(name, sizeof name, "spi%u", bus_num); -+ bus = kset_find_obj(&spi_master_class.subsys.kset, name); -+ if (bus) -+ return container_of(bus, struct spi_master, cdev.kobj); -+ } -+ return NULL; -+} -+EXPORT_SYMBOL_GPL(spi_busnum_to_master); -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+/** -+ * spi_sync - blocking/synchronous SPI data transfers -+ * @spi: device with which data will be exchanged -+ * @message: describes the data transfers -+ * -+ * This call may only be used from a context that may sleep. The sleep -+ * is non-interruptible, and has no timeout. Low-overhead controller -+ * drivers may DMA directly into and out of the message buffers. -+ * -+ * Note that the SPI device's chip select is active during the message, -+ * and then is normally disabled between messages. Drivers for some -+ * frequently-used devices may want to minimize costs of selecting a chip, -+ * by leaving it selected in anticipation that the next message will go -+ * to the same chip. (That may increase power usage.) -+ * -+ * The return value is a negative error code if the message could not be -+ * submitted, else zero. When the value is zero, then message->status is -+ * also defined: it's the completion code for the transfer, either zero -+ * or a negative error code from the controller driver. -+ */ -+int spi_sync(struct spi_device *spi, struct spi_message *message) -+{ -+ DECLARE_COMPLETION(done); -+ int status; -+ -+ message->complete = (void (*)(void *)) complete; -+ message->context = &done; -+ status = spi_async(spi, message); -+ if (status == 0) -+ wait_for_completion(&done); -+ message->context = NULL; -+ return status; -+} -+EXPORT_SYMBOL_GPL(spi_sync); -+ -+#define SPI_BUFSIZ (SMP_CACHE_BYTES) -+ -+static u8 *buf; -+ -+/** -+ * spi_write_then_read - SPI synchronous write followed by read -+ * @spi: device with which data will be exchanged -+ * @txbuf: data to be written (need not be dma-safe) -+ * @n_tx: size of txbuf, in bytes -+ * @rxbuf: buffer into which data will be read -+ * @n_rx: size of rxbuf, in bytes (need not be dma-safe) -+ * -+ * This performs a half duplex MicroWire style transaction with the -+ * device, sending txbuf and then reading rxbuf. The return value -+ * is zero for success, else a negative errno status code. -+ * -+ * Parameters to this routine are always copied using a small buffer, -+ * large transfers should use use spi_{async,sync}() calls with -+ * dma-safe buffers. -+ */ -+int spi_write_then_read(struct spi_device *spi, -+ const u8 *txbuf, unsigned n_tx, -+ u8 *rxbuf, unsigned n_rx) -+{ -+ static DECLARE_MUTEX(lock); -+ -+ int status; -+ struct spi_message message; -+ struct spi_transfer x[2]; -+ u8 *local_buf; -+ -+ /* Use preallocated DMA-safe buffer. We can't avoid copying here, -+ * (as a pure convenience thing), but we can keep heap costs -+ * out of the hot path ... -+ */ -+ if ((n_tx + n_rx) > SPI_BUFSIZ) -+ return -EINVAL; -+ -+ /* ... unless someone else is using the pre-allocated buffer */ -+ if (down_trylock(&lock)) { -+ local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL); -+ if (!local_buf) -+ return -ENOMEM; -+ } else -+ local_buf = buf; -+ -+ memset(x, 0, sizeof x); -+ -+ memcpy(local_buf, txbuf, n_tx); -+ x[0].tx_buf = local_buf; -+ x[0].len = n_tx; -+ -+ x[1].rx_buf = local_buf + n_tx; -+ x[1].len = n_rx; -+ -+ /* do the i/o */ -+ message.transfers = x; -+ message.n_transfer = ARRAY_SIZE(x); -+ status = spi_sync(spi, &message); -+ if (status == 0) { -+ memcpy(rxbuf, x[1].rx_buf, n_rx); -+ status = message.status; -+ } -+ -+ if (x[0].tx_buf == buf) -+ up(&lock); -+ else -+ kfree(local_buf); -+ -+ return status; -+} -+EXPORT_SYMBOL_GPL(spi_write_then_read); -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int __init spi_init(void) -+{ -+ buf = kmalloc(SPI_BUFSIZ, SLAB_KERNEL); -+ if (!buf) -+ return -ENOMEM; -+ -+ bus_register(&spi_bus_type); -+ class_register(&spi_master_class); -+ return 0; -+} -+/* board_info is normally registered in arch_initcall(), -+ * but even essential drivers wait till later -+ */ -+subsys_initcall(spi_init); -+ ---- /dev/null -+++ gregkh-2.6/include/linux/spi/spi.h -@@ -0,0 +1,542 @@ -+/* -+ * Copyright (C) 2005 David Brownell -+ * -+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#ifndef __LINUX_SPI_H -+#define __LINUX_SPI_H -+ -+/* -+ * INTERFACES between SPI master drivers and infrastructure -+ * (There's no SPI slave support for Linux yet...) -+ * -+ * A "struct device_driver" for an spi_device uses "spi_bus_type" and -+ * needs no special API wrappers (much like platform_bus). These drivers -+ * are bound to devices based on their names (much like platform_bus), -+ * and are available in dev->driver. -+ */ -+extern struct bus_type spi_bus_type; -+ -+/** -+ * struct spi_device - Master side proxy for an SPI slave device -+ * @dev: Driver model representation of the device. -+ * @master: SPI controller used with the device. -+ * @max_speed_hz: Maximum clock rate to be used with this chip -+ * (on this board); may be changed by the device's driver. -+ * @chip-select: Chipselect, distinguishing chips handled by "master". -+ * @mode: The spi mode defines how data is clocked out and in. -+ * This may be changed by the device's driver. -+ * @bits_per_word: Data transfers involve one or more words; word sizes -+ * like eight or 12 bits are common. In-memory wordsizes are -+ * powers of two bytes (e.g. 20 bit samples use 32 bits). -+ * This may be changed by the device's driver. -+ * @irq: Negative, or the number passed to request_irq() to receive -+ * interrupts from this device. -+ * @controller_state: Controller's runtime state -+ * @controller_data: Static board-specific definitions for controller, such -+ * as FIFO initialization parameters; from board_info.controller_data -+ * -+ * An spi_device is used to interchange data between an SPI slave -+ * (usually a discrete chip) and CPU memory. -+ * -+ * In "dev", the platform_data is used to hold information about this -+ * device that's meaningful to the device's protocol driver, but not -+ * to its controller. One example might be an identifier for a chip -+ * variant with slightly different functionality. -+ */ -+struct spi_device { -+ struct device dev; -+ struct spi_master *master; -+ u32 max_speed_hz; -+ u8 chip_select; -+ u8 mode; -+#define SPI_CPHA 0x01 /* clock phase */ -+#define SPI_CPOL 0x02 /* clock polarity */ -+#define SPI_MODE_0 (0|0) -+#define SPI_MODE_1 (0|SPI_CPHA) -+#define SPI_MODE_2 (SPI_CPOL|0) -+#define SPI_MODE_3 (SPI_CPOL|SPI_CPHA) -+#define SPI_CS_HIGH 0x04 /* chipselect active high? */ -+ u8 bits_per_word; -+ int irq; -+ void *controller_state; -+ const void *controller_data; -+ const char *modalias; -+ -+ // likely need more hooks for more protocol options affecting how -+ // the controller talks to its chips, like: -+ // - bit order (default is wordwise msb-first) -+ // - memory packing (12 bit samples into low bits, others zeroed) -+ // - priority -+ // - chipselect delays -+ // - ... -+}; -+ -+static inline struct spi_device *to_spi_device(struct device *dev) -+{ -+ return container_of(dev, struct spi_device, dev); -+} -+ -+/* most drivers won't need to care about device refcounting */ -+static inline struct spi_device *spi_dev_get(struct spi_device *spi) -+{ -+ return (spi && get_device(&spi->dev)) ? spi : NULL; -+} -+ -+static inline void spi_dev_put(struct spi_device *spi) -+{ -+ if (spi) -+ put_device(&spi->dev); -+} -+ -+/* ctldata is for the bus_master driver's runtime state */ -+static inline void *spi_get_ctldata(struct spi_device *spi) -+{ -+ return spi->controller_state; -+} -+ -+static inline void spi_set_ctldata(struct spi_device *spi, void *state) -+{ -+ spi->controller_state = state; -+} -+ -+ -+struct spi_message; -+ -+ -+/** -+ * struct spi_master - interface to SPI master controller -+ * @cdev: class interface to this driver -+ * @bus_num: board-specific (and often SOC-specific) identifier for a -+ * given SPI controller. -+ * @num_chipselects: chipselects are used to distinguish individual -+ * SPI slaves, and are numbered from zero to num_chipselects. -+ * each slave has a chipselect signal, but it's common that not -+ * every chipselect is connected to a slave. -+ * @setup: updates the device mode and clocking records used by a -+ * device's SPI controller; protocol code may call this. -+ * @transfer: adds a message to the controller's transfer queue. -+ * @cleanup: frees controller-specific state -+ * -+ * Each SPI master controller can communicate with one or more spi_device -+ * children. These make a small bus, sharing MOSI, MISO and SCK signals -+ * but not chip select signals. Each device may be configured to use a -+ * different clock rate, since those shared signals are ignored unless -+ * the chip is selected. -+ * -+ * The driver for an SPI controller manages access to those devices through -+ * a queue of spi_message transactions, copyin data between CPU memory and -+ * an SPI slave device). For each such message it queues, it calls the -+ * message's completion function when the transaction completes. -+ */ -+struct spi_master { -+ struct class_device cdev; -+ -+ /* other than zero (== assign one dynamically), bus_num is fully -+ * board-specific. usually that simplifies to being SOC-specific. -+ * example: one SOC has three SPI controllers, numbered 1..3, -+ * and one board's schematics might show it using SPI-2. software -+ * would normally use bus_num=2 for that controller. -+ */ -+ u16 bus_num; -+ -+ /* chipselects will be integral to many controllers; some others -+ * might use board-specific GPIOs. -+ */ -+ u16 num_chipselect; -+ -+ /* setup mode and clock, etc (spi driver may call many times) */ -+ int (*setup)(struct spi_device *spi); -+ -+ /* bidirectional bulk transfers -+ * -+ * + The transfer() method may not sleep; its main role is -+ * just to add the message to the queue. -+ * + For now there's no remove-from-queue operation, or -+ * any other request management -+ * + To a given spi_device, message queueing is pure fifo -+ * -+ * + The master's main job is to process its message queue, -+ * selecting a chip then transferring data -+ * + If there are multiple spi_device children, the i/o queue -+ * arbitration algorithm is unspecified (round robin, fifo, -+ * priority, reservations, preemption, etc) -+ * -+ * + Chipselect stays active during the entire message -+ * (unless modified by spi_transfer.cs_change != 0). -+ * + The message transfers use clock and SPI mode parameters -+ * previously established by setup() for this device -+ */ -+ int (*transfer)(struct spi_device *spi, -+ struct spi_message *mesg); -+ -+ /* called on release() to free memory provided by spi_master */ -+ void (*cleanup)(const struct spi_device *spi); -+}; -+ -+/* the spi driver core manages memory for the spi_master classdev */ -+extern struct spi_master * -+spi_alloc_master(struct device *host, unsigned size); -+ -+extern int spi_register_master(struct spi_master *master); -+extern void spi_unregister_master(struct spi_master *master); -+ -+extern struct spi_master *spi_busnum_to_master(u16 busnum); -+ -+/*---------------------------------------------------------------------------*/ -+ -+/* -+ * I/O INTERFACE between SPI controller and protocol drivers -+ * -+ * Protocol drivers use a queue of spi_messages, each transferring data -+ * between the controller and memory buffers. -+ * -+ * The spi_messages themselves consist of a series of read+write transfer -+ * segments. Those segments always read the same number of bits as they -+ * write; but one or the other is easily ignored by passing a null buffer -+ * pointer. (This is unlike most types of I/O API, because SPI hardware -+ * is full duplex.) -+ * -+ * NOTE: Allocation of spi_transfer and spi_message memory is entirely -+ * up to the protocol driver, which guarantees the integrity of both (as -+ * well as the data buffers) for as long as the message is queued. -+ */ -+ -+/** -+ * struct spi_transfer - a read/write buffer pair -+ * @tx_buf: data to be written (dma-safe address), or NULL -+ * @rx_buf: data to be read (dma-safe address), or NULL -+ * @tx_dma: DMA address of buffer, if spi_message.is_dma_mapped -+ * @rx_dma: DMA address of buffer, if spi_message.is_dma_mapped -+ * @len: size of rx and tx buffers (in bytes) -+ * @cs_change: affects chipselect after this transfer completes -+ * @delay_usecs: microseconds to delay after this transfer before -+ * (optionally) changing the chipselect status, then starting -+ * the next transfer or completing this spi_message. -+ * -+ * SPI transfers always write the same number of bytes as they read. -+ * Protocol drivers should always provide rx_buf and/or tx_buf. -+ * In some cases, they may also want to provide DMA addresses for -+ * the data being transferred; that may reduce overhead, when the -+ * underlying driver uses dma. -+ * -+ * All SPI transfers start with the relevant chipselect active. Drivers -+ * can change behavior of the chipselect after the transfer finishes -+ * (including any mandatory delay). The normal behavior is to leave it -+ * selected, except for the last transfer in a message. Setting cs_change -+ * allows two additional behavior options: -+ * -+ * (i) If the transfer isn't the last one in the message, this flag is -+ * used to make the chipselect briefly go inactive in the middle of the -+ * message. Toggling chipselect in this way may be needed to terminate -+ * a chip command, letting a single spi_message perform all of group of -+ * chip transactions together. -+ * -+ * (ii) When the transfer is the last one in the message, the chip may -+ * stay selected until the next transfer. This is purely a performance -+ * hint; the controller driver may need to select a different device -+ * for the next message. -+ */ -+struct spi_transfer { -+ /* it's ok if tx_buf == rx_buf (right?) -+ * for MicroWire, one buffer must be null -+ * buffers must work with dma_*map_single() calls -+ */ -+ const void *tx_buf; -+ void *rx_buf; -+ unsigned len; -+ -+ dma_addr_t tx_dma; -+ dma_addr_t rx_dma; -+ -+ unsigned cs_change:1; -+ u16 delay_usecs; -+}; -+ -+/** -+ * struct spi_message - one multi-segment SPI transaction -+ * @transfers: the segements of the transaction -+ * @n_transfer: how many segments -+ * @spi: SPI device to which the transaction is queued -+ * @is_dma_mapped: if true, the caller provided both dma and cpu virtual -+ * addresses for each transfer buffer -+ * @complete: called to report transaction completions -+ * @context: the argument to complete() when it's called -+ * @actual_length: how many bytes were transferd -+ * @status: zero for success, else negative errno -+ * @queue: for use by whichever driver currently owns the message -+ * @state: for use by whichever driver currently owns the message -+ */ -+struct spi_message { -+ struct spi_transfer *transfers; -+ unsigned n_transfer; -+ -+ struct spi_device *spi; -+ -+ unsigned is_dma_mapped:1; -+ -+ /* REVISIT: we might want a flag affecting the behavior of the -+ * last transfer ... allowing things like "read 16 bit length L" -+ * immediately followed by "read L bytes". Basically imposing -+ * a specific message scheduling algorithm. -+ * -+ * Some controller drivers (message-at-a-time queue processing) -+ * could provide that as their default scheduling algorithm. But -+ * others (with multi-message pipelines) would need a flag to -+ * tell them about such special cases. -+ */ -+ -+ /* completion is reported through a callback */ -+ void FASTCALL((*complete)(void *context)); -+ void *context; -+ unsigned actual_length; -+ int status; -+ -+ /* for optional use by whatever driver currently owns the -+ * spi_message ... between calls to spi_async and then later -+ * complete(), that's the spi_master controller driver. -+ */ -+ struct list_head queue; -+ void *state; -+}; -+ -+/** -+ * spi_setup -- setup SPI mode and clock rate -+ * @spi: the device whose settings are being modified -+ * -+ * SPI protocol drivers may need to update the transfer mode if the -+ * device doesn't work with the mode 0 default. They may likewise need -+ * to update clock rates or word sizes from initial values. This function -+ * changes those settings, and must be called from a context that can sleep. -+ */ -+static inline int -+spi_setup(struct spi_device *spi) -+{ -+ return spi->master->setup(spi); -+} -+ -+ -+/** -+ * spi_async -- asynchronous SPI transfer -+ * @spi: device with which data will be exchanged -+ * @message: describes the data transfers, including completion callback -+ * -+ * This call may be used in_irq and other contexts which can't sleep, -+ * as well as from task contexts which can sleep. -+ * -+ * The completion callback is invoked in a context which can't sleep. -+ * Before that invocation, the value of message->status is undefined. -+ * When the callback is issued, message->status holds either zero (to -+ * indicate complete success) or a negative error code. -+ * -+ * Note that although all messages to a spi_device are handled in -+ * FIFO order, messages may go to different devices in other orders. -+ * Some device might be higher priority, or have various "hard" access -+ * time requirements, for example. -+ */ -+static inline int -+spi_async(struct spi_device *spi, struct spi_message *message) -+{ -+ message->spi = spi; -+ return spi->master->transfer(spi, message); -+} -+ -+/*---------------------------------------------------------------------------*/ -+ -+/* All these synchronous SPI transfer routines are utilities layered -+ * over the core async transfer primitive. Here, "synchronous" means -+ * they will sleep uninterruptibly until the async transfer completes. -+ */ -+ -+extern int spi_sync(struct spi_device *spi, struct spi_message *message); -+ -+/** -+ * spi_write - SPI synchronous write -+ * @spi: device to which data will be written -+ * @buf: data buffer -+ * @len: data buffer size -+ * -+ * This writes the buffer and returns zero or a negative error code. -+ * Callable only from contexts that can sleep. -+ */ -+static inline int -+spi_write(struct spi_device *spi, const u8 *buf, size_t len) -+{ -+ struct spi_transfer t = { -+ .tx_buf = buf, -+ .rx_buf = NULL, -+ .len = len, -+ .cs_change = 0, -+ }; -+ struct spi_message m = { -+ .transfers = &t, -+ .n_transfer = 1, -+ }; -+ -+ return spi_sync(spi, &m); -+} -+ -+/** -+ * spi_read - SPI synchronous read -+ * @spi: device from which data will be read -+ * @buf: data buffer -+ * @len: data buffer size -+ * -+ * This writes the buffer and returns zero or a negative error code. -+ * Callable only from contexts that can sleep. -+ */ -+static inline int -+spi_read(struct spi_device *spi, u8 *buf, size_t len) -+{ -+ struct spi_transfer t = { -+ .tx_buf = NULL, -+ .rx_buf = buf, -+ .len = len, -+ .cs_change = 0, -+ }; -+ struct spi_message m = { -+ .transfers = &t, -+ .n_transfer = 1, -+ }; -+ -+ return spi_sync(spi, &m); -+} -+ -+extern int spi_write_then_read(struct spi_device *spi, -+ const u8 *txbuf, unsigned n_tx, -+ u8 *rxbuf, unsigned n_rx); -+ -+/** -+ * spi_w8r8 - SPI synchronous 8 bit write followed by 8 bit read -+ * @spi: device with which data will be exchanged -+ * @cmd: command to be written before data is read back -+ * -+ * This returns the (unsigned) eight bit number returned by the -+ * device, or else a negative error code. Callable only from -+ * contexts that can sleep. -+ */ -+static inline ssize_t spi_w8r8(struct spi_device *spi, u8 cmd) -+{ -+ ssize_t status; -+ u8 result; -+ -+ status = spi_write_then_read(spi, &cmd, 1, &result, 1); -+ -+ /* return negative errno or unsigned value */ -+ return (status < 0) ? status : result; -+} -+ -+/** -+ * spi_w8r16 - SPI synchronous 8 bit write followed by 16 bit read -+ * @spi: device with which data will be exchanged -+ * @cmd: command to be written before data is read back -+ * -+ * This returns the (unsigned) sixteen bit number returned by the -+ * device, or else a negative error code. Callable only from -+ * contexts that can sleep. -+ * -+ * The number is returned in wire-order, which is at least sometimes -+ * big-endian. -+ */ -+static inline ssize_t spi_w8r16(struct spi_device *spi, u8 cmd) -+{ -+ ssize_t status; -+ u16 result; -+ -+ status = spi_write_then_read(spi, &cmd, 1, (u8 *) &result, 2); -+ -+ /* return negative errno or unsigned value */ -+ return (status < 0) ? status : result; -+} -+ -+/*---------------------------------------------------------------------------*/ -+ -+/* -+ * INTERFACE between board init code and SPI infrastructure. -+ * -+ * No SPI driver ever sees these SPI device table segments, but -+ * it's how the SPI core (or adapters that get hotplugged) grows -+ * the driver model tree. -+ * -+ * As a rule, SPI devices can't be probed. Instead, board init code -+ * provides a table listing the devices which are present, with enough -+ * information to bind and set up the device's driver. There's basic -+ * support for nonstatic configurations too; enough to handle adding -+ * parport adapters, or microcontrollers acting as USB-to-SPI bridges. -+ */ -+ -+/* board-specific information about each SPI device */ -+struct spi_board_info { -+ /* the device name and module name are coupled, like platform_bus; -+ * "modalias" is normally the driver name. -+ * -+ * platform_data goes to spi_device.dev.platform_data, -+ * controller_data goes to spi_device.platform_data, -+ * irq is copied too -+ */ -+ char modalias[KOBJ_NAME_LEN]; -+ const void *platform_data; -+ const void *controller_data; -+ int irq; -+ -+ /* slower signaling on noisy or low voltage boards */ -+ u32 max_speed_hz; -+ -+ -+ /* bus_num is board specific and matches the bus_num of some -+ * spi_master that will probably be registered later. -+ * -+ * chip_select reflects how this chip is wired to that master; -+ * it's less than num_chipselect. -+ */ -+ u16 bus_num; -+ u16 chip_select; -+ -+ /* ... may need additional spi_device chip config data here. -+ * avoid stuff protocol drivers can set; but include stuff -+ * needed to behave without being bound to a driver: -+ * - chipselect polarity -+ * - quirks like clock rate mattering when not selected -+ */ -+}; -+ -+#ifdef CONFIG_SPI -+extern int -+spi_register_board_info(struct spi_board_info const *info, unsigned n); -+#else -+/* board init code may ignore whether SPI is configured or not */ -+static inline int -+spi_register_board_info(struct spi_board_info const *info, unsigned n) -+ { return 0; } -+#endif -+ -+ -+/* If you're hotplugging an adapter with devices (parport, usb, etc) -+ * use spi_new_device() to describe each device. You can also call -+ * spi_unregister_device() to get start making that device vanish, -+ * but normally that would be handled by spi_unregister_master(). -+ */ -+extern struct spi_device * -+spi_new_device(struct spi_master *, struct spi_board_info *); -+ -+static inline void -+spi_unregister_device(struct spi_device *spi) -+{ -+ if (spi) -+ device_unregister(&spi->dev); -+} -+ -+#endif /* __LINUX_SPI_H */ diff --git a/driver/spi-use-linked-lists-rather-than-an-array.patch b/driver/spi-use-linked-lists-rather-than-an-array.patch deleted file mode 100644 index 2df3c2346ed34..0000000000000 --- a/driver/spi-use-linked-lists-rather-than-an-array.patch +++ /dev/null @@ -1,679 +0,0 @@ -From akpm@osdl.org Sun Jan 8 13:38:59 2006 -From: akpm@osdl.org -Message-Id: <200601082134.k08LYe8T004585@shell0.pdx.osdl.net> -Subject: [patch 09/10] spi: use linked lists rather than an array -To: greg@kroah.com -Cc: akpm@osdl.org, vwool@ru.mvista.com, dbrownell@users.sourceforge.net, dpervushin@gmail.com -Date: Sun, 08 Jan 2006 13:34:28 -0800 - - -From: Vitaly Wool <vwool@ru.mvista.com> - -This makes the SPI core and its users access transfers in the SPI message -structure as linked list not as an array, as discussed on LKML. - -From: David Brownell <dbrownell@users.sourceforge.net> - - Updates including doc, bugfixes to the list code, add - spi_message_add_tail(). Plus, initialize things _before_ grabbing the - locks in some cases (in case it grows more expensive). This also merges - some bitbang updates of mine that didn't yet make it into the mm tree. - -Signed-off-by: Vitaly Wool <vwool@ru.mvista.com> -Signed-off-by: Dmitry Pervushin <dpervushin@gmail.com> -Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> -Signed-off-by: Andrew Morton <akpm@osdl.org> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> ---- - drivers/input/touchscreen/ads7846.c | 12 +++- - drivers/mtd/devices/m25p80.c | 50 +++++++++---------- - drivers/mtd/devices/mtd_dataflash.c | 28 ++++++---- - drivers/spi/spi.c | 18 ++++--- - drivers/spi/spi_bitbang.c | 86 +++++++++++++++++++-------------- - include/linux/spi/spi.h | 92 ++++++++++++++++++++++++------------ - include/linux/spi/spi_bitbang.h | 7 ++ - 7 files changed, 180 insertions(+), 113 deletions(-) - ---- gregkh-2.6.orig/drivers/input/touchscreen/ads7846.c -+++ gregkh-2.6/drivers/input/touchscreen/ads7846.c -@@ -155,10 +155,13 @@ static int ads7846_read12_ser(struct dev - struct ser_req *req = kzalloc(sizeof *req, SLAB_KERNEL); - int status; - int sample; -+ int i; - - if (!req) - return -ENOMEM; - -+ INIT_LIST_HEAD(&req->msg.transfers); -+ - /* activate reference, so it has time to settle; */ - req->xfer[0].tx_buf = &ref_on; - req->xfer[0].len = 1; -@@ -192,8 +195,8 @@ static int ads7846_read12_ser(struct dev - /* group all the transfers together, so we can't interfere with - * reading touchscreen state; disable penirq while sampling - */ -- req->msg.transfers = req->xfer; -- req->msg.n_transfer = 6; -+ for (i = 0; i < 6; i++) -+ spi_message_add_tail(&req->xfer[i], &req->msg); - - disable_irq(spi->irq); - status = spi_sync(spi, &req->msg); -@@ -398,6 +401,7 @@ static int __devinit ads7846_probe(struc - struct ads7846 *ts; - struct ads7846_platform_data *pdata = spi->dev.platform_data; - struct spi_transfer *x; -+ int i; - - if (!spi->irq) { - dev_dbg(&spi->dev, "no IRQ?\n"); -@@ -500,8 +504,8 @@ static int __devinit ads7846_probe(struc - - CS_CHANGE(x[-1]); - -- ts->msg.transfers = ts->xfer; -- ts->msg.n_transfer = x - ts->xfer; -+ for (i = 0; i < x - ts->xfer; i++) -+ spi_message_add_tail(&ts->xfer[i], &ts->msg); - ts->msg.complete = ads7846_rx; - ts->msg.context = ts; - ---- gregkh-2.6.orig/drivers/mtd/devices/m25p80.c -+++ gregkh-2.6/drivers/mtd/devices/m25p80.c -@@ -245,6 +245,21 @@ static int m25p80_read(struct mtd_info * - if (from + len > flash->mtd.size) - return -EINVAL; - -+ spi_message_init(&m); -+ memset(t, 0, (sizeof t)); -+ -+ t[0].tx_buf = flash->command; -+ t[0].len = sizeof(flash->command); -+ spi_message_add_tail(&t[0], &m); -+ -+ t[1].rx_buf = buf; -+ t[1].len = len; -+ spi_message_add_tail(&t[1], &m); -+ -+ /* Byte count starts at zero. */ -+ if (retlen) -+ *retlen = 0; -+ - down(&flash->lock); - - /* Wait till previous write/erase is done. */ -@@ -254,8 +269,6 @@ static int m25p80_read(struct mtd_info * - return 1; - } - -- memset(t, 0, (sizeof t)); -- - /* NOTE: OPCODE_FAST_READ (if available) is faster... */ - - /* Set up the write data buffer. */ -@@ -264,19 +277,6 @@ static int m25p80_read(struct mtd_info * - flash->command[2] = from >> 8; - flash->command[3] = from; - -- /* Byte count starts at zero. */ -- if (retlen) -- *retlen = 0; -- -- t[0].tx_buf = flash->command; -- t[0].len = sizeof(flash->command); -- -- t[1].rx_buf = buf; -- t[1].len = len; -- -- m.transfers = t; -- m.n_transfer = 2; -- - spi_sync(flash->spi, &m); - - *retlen = m.actual_length - sizeof(flash->command); -@@ -313,6 +313,16 @@ static int m25p80_write(struct mtd_info - if (to + len > flash->mtd.size) - return -EINVAL; - -+ spi_message_init(&m); -+ memset(t, 0, (sizeof t)); -+ -+ t[0].tx_buf = flash->command; -+ t[0].len = sizeof(flash->command); -+ spi_message_add_tail(&t[0], &m); -+ -+ t[1].tx_buf = buf; -+ spi_message_add_tail(&t[1], &m); -+ - down(&flash->lock); - - /* Wait until finished previous write command. */ -@@ -321,26 +331,17 @@ static int m25p80_write(struct mtd_info - - write_enable(flash); - -- memset(t, 0, (sizeof t)); -- - /* Set up the opcode in the write buffer. */ - flash->command[0] = OPCODE_PP; - flash->command[1] = to >> 16; - flash->command[2] = to >> 8; - flash->command[3] = to; - -- t[0].tx_buf = flash->command; -- t[0].len = sizeof(flash->command); -- -- m.transfers = t; -- m.n_transfer = 2; -- - /* what page do we start with? */ - page_offset = to % FLASH_PAGESIZE; - - /* do all the bytes fit onto one page? */ - if (page_offset + len <= FLASH_PAGESIZE) { -- t[1].tx_buf = buf; - t[1].len = len; - - spi_sync(flash->spi, &m); -@@ -352,7 +353,6 @@ static int m25p80_write(struct mtd_info - /* the size of data remaining on the first page */ - page_size = FLASH_PAGESIZE - page_offset; - -- t[1].tx_buf = buf; - t[1].len = page_size; - spi_sync(flash->spi, &m); - ---- gregkh-2.6.orig/drivers/mtd/devices/mtd_dataflash.c -+++ gregkh-2.6/drivers/mtd/devices/mtd_dataflash.c -@@ -147,7 +147,7 @@ static int dataflash_erase(struct mtd_in - { - struct dataflash *priv = (struct dataflash *)mtd->priv; - struct spi_device *spi = priv->spi; -- struct spi_transfer x[1] = { { .tx_dma = 0, }, }; -+ struct spi_transfer x = { .tx_dma = 0, }; - struct spi_message msg; - unsigned blocksize = priv->page_size << 3; - u8 *command; -@@ -162,10 +162,11 @@ static int dataflash_erase(struct mtd_in - || (instr->addr % priv->page_size) != 0) - return -EINVAL; - -- x[0].tx_buf = command = priv->command; -- x[0].len = 4; -- msg.transfers = x; -- msg.n_transfer = 1; -+ spi_message_init(&msg); -+ -+ x.tx_buf = command = priv->command; -+ x.len = 4; -+ spi_message_add_tail(&x, &msg); - - down(&priv->lock); - while (instr->len > 0) { -@@ -256,12 +257,15 @@ static int dataflash_read(struct mtd_inf - DEBUG(MTD_DEBUG_LEVEL3, "READ: (%x) %x %x %x\n", - command[0], command[1], command[2], command[3]); - -+ spi_message_init(&msg); -+ - x[0].tx_buf = command; - x[0].len = 8; -+ spi_message_add_tail(&x[0], &msg); -+ - x[1].rx_buf = buf; - x[1].len = len; -- msg.transfers = x; -- msg.n_transfer = 2; -+ spi_message_add_tail(&x[1], &msg); - - down(&priv->lock); - -@@ -320,9 +324,11 @@ static int dataflash_write(struct mtd_in - if ((to + len) > mtd->size) - return -EINVAL; - -+ spi_message_init(&msg); -+ - x[0].tx_buf = command = priv->command; - x[0].len = 4; -- msg.transfers = x; -+ spi_message_add_tail(&x[0], &msg); - - pageaddr = ((unsigned)to / priv->page_size); - offset = ((unsigned)to % priv->page_size); -@@ -364,7 +370,6 @@ static int dataflash_write(struct mtd_in - DEBUG(MTD_DEBUG_LEVEL3, "TRANSFER: (%x) %x %x %x\n", - command[0], command[1], command[2], command[3]); - -- msg.n_transfer = 1; - status = spi_sync(spi, &msg); - if (status < 0) - DEBUG(MTD_DEBUG_LEVEL1, "%s: xfer %u -> %d \n", -@@ -385,14 +390,16 @@ static int dataflash_write(struct mtd_in - - x[1].tx_buf = writebuf; - x[1].len = writelen; -- msg.n_transfer = 2; -+ spi_message_add_tail(x + 1, &msg); - status = spi_sync(spi, &msg); -+ spi_transfer_del(x + 1); - if (status < 0) - DEBUG(MTD_DEBUG_LEVEL1, "%s: pgm %u/%u -> %d \n", - spi->dev.bus_id, addr, writelen, status); - - (void) dataflash_waitready(priv->spi); - -+ - #ifdef CONFIG_DATAFLASH_WRITE_VERIFY - - /* (3) Compare to Buffer1 */ -@@ -405,7 +412,6 @@ static int dataflash_write(struct mtd_in - DEBUG(MTD_DEBUG_LEVEL3, "COMPARE: (%x) %x %x %x\n", - command[0], command[1], command[2], command[3]); - -- msg.n_transfer = 1; - status = spi_sync(spi, &msg); - if (status < 0) - DEBUG(MTD_DEBUG_LEVEL1, "%s: compare %u -> %d \n", ---- gregkh-2.6.orig/drivers/spi/spi_bitbang.c -+++ gregkh-2.6/drivers/spi/spi_bitbang.c -@@ -146,6 +146,9 @@ int spi_bitbang_setup(struct spi_device - struct spi_bitbang_cs *cs = spi->controller_state; - struct spi_bitbang *bitbang; - -+ if (!spi->max_speed_hz) -+ return -EINVAL; -+ - if (!cs) { - cs = kzalloc(sizeof *cs, SLAB_KERNEL); - if (!cs) -@@ -172,13 +175,8 @@ int spi_bitbang_setup(struct spi_device - if (!cs->txrx_word) - return -EINVAL; - -- if (!spi->max_speed_hz) -- spi->max_speed_hz = 500 * 1000; -- -- /* nsecs = max(50, (clock period)/2), be optimistic */ -+ /* nsecs = (clock period)/2 */ - cs->nsecs = (1000000000/2) / (spi->max_speed_hz); -- if (cs->nsecs < 50) -- cs->nsecs = 50; - if (cs->nsecs > MAX_UDELAY_MS * 1000) - return -EINVAL; - -@@ -194,7 +192,7 @@ int spi_bitbang_setup(struct spi_device - /* deselect chip (low or high) */ - spin_lock(&bitbang->lock); - if (!bitbang->busy) { -- bitbang->chipselect(spi, 0); -+ bitbang->chipselect(spi, BITBANG_CS_INACTIVE); - ndelay(cs->nsecs); - } - spin_unlock(&bitbang->lock); -@@ -244,9 +242,9 @@ static void bitbang_work(void *_bitbang) - struct spi_message *m; - struct spi_device *spi; - unsigned nsecs; -- struct spi_transfer *t; -+ struct spi_transfer *t = NULL; - unsigned tmp; -- unsigned chipselect; -+ unsigned cs_change; - int status; - - m = container_of(bitbang->queue.next, struct spi_message, -@@ -254,37 +252,49 @@ static void bitbang_work(void *_bitbang) - list_del_init(&m->queue); - spin_unlock_irqrestore(&bitbang->lock, flags); - --// FIXME this is made-up --nsecs = 100; -+ /* FIXME this is made-up ... the correct value is known to -+ * word-at-a-time bitbang code, and presumably chipselect() -+ * should enforce these requirements too? -+ */ -+ nsecs = 100; - - spi = m->spi; -- t = m->transfers; - tmp = 0; -- chipselect = 0; -+ cs_change = 1; - status = 0; - -- for (;;t++) { -+ list_for_each_entry (t, &m->transfers, transfer_list) { - if (bitbang->shutdown) { - status = -ESHUTDOWN; - break; - } - -- /* set up default clock polarity, and activate chip */ -- if (!chipselect) { -- bitbang->chipselect(spi, 1); -+ /* set up default clock polarity, and activate chip; -+ * this implicitly updates clock and spi modes as -+ * previously recorded for this device via setup(). -+ * (and also deselects any other chip that might be -+ * selected ...) -+ */ -+ if (cs_change) { -+ bitbang->chipselect(spi, BITBANG_CS_ACTIVE); - ndelay(nsecs); - } -+ cs_change = t->cs_change; - if (!t->tx_buf && !t->rx_buf && t->len) { - status = -EINVAL; - break; - } - -- /* transfer data */ -+ /* transfer data. the lower level code handles any -+ * new dma mappings it needs. our caller always gave -+ * us dma-safe buffers. -+ */ - if (t->len) { -- /* FIXME if bitbang->use_dma, dma_map_single() -- * before the transfer, and dma_unmap_single() -- * afterwards, for either or both buffers... -+ /* REVISIT dma API still needs a designated -+ * DMA_ADDR_INVALID; ~0 might be better. - */ -+ if (!m->is_dma_mapped) -+ t->rx_dma = t->tx_dma = 0; - status = bitbang->txrx_bufs(spi, t); - } - if (status != t->len) { -@@ -299,29 +309,31 @@ nsecs = 100; - if (t->delay_usecs) - udelay(t->delay_usecs); - -- tmp++; -- if (tmp >= m->n_transfer) -- break; -- -- chipselect = !t->cs_change; -- if (chipselect); -+ if (!cs_change) - continue; -+ if (t->transfer_list.next == &m->transfers) -+ break; - -- bitbang->chipselect(spi, 0); -- -- /* REVISIT do we want the udelay here instead? */ -- msleep(1); -+ /* sometimes a short mid-message deselect of the chip -+ * may be needed to terminate a mode or command -+ */ -+ ndelay(nsecs); -+ bitbang->chipselect(spi, BITBANG_CS_INACTIVE); -+ ndelay(nsecs); - } - -- tmp = m->n_transfer - 1; -- tmp = m->transfers[tmp].cs_change; -- - m->status = status; - m->complete(m->context); - -- ndelay(2 * nsecs); -- bitbang->chipselect(spi, status == 0 && tmp); -- ndelay(nsecs); -+ /* normally deactivate chipselect ... unless no error and -+ * cs_change has hinted that the next message will probably -+ * be for this chip too. -+ */ -+ if (!(status == 0 && cs_change)) { -+ ndelay(nsecs); -+ bitbang->chipselect(spi, BITBANG_CS_INACTIVE); -+ ndelay(nsecs); -+ } - - spin_lock_irqsave(&bitbang->lock, flags); - } ---- gregkh-2.6.orig/drivers/spi/spi.c -+++ gregkh-2.6/drivers/spi/spi.c -@@ -557,6 +557,17 @@ int spi_write_then_read(struct spi_devic - if ((n_tx + n_rx) > SPI_BUFSIZ) - return -EINVAL; - -+ spi_message_init(&message); -+ memset(x, 0, sizeof x); -+ if (n_tx) { -+ x[0].len = n_tx; -+ spi_message_add_tail(&x[0], &message); -+ } -+ if (n_rx) { -+ x[1].len = n_rx; -+ spi_message_add_tail(&x[1], &message); -+ } -+ - /* ... unless someone else is using the pre-allocated buffer */ - if (down_trylock(&lock)) { - local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL); -@@ -565,18 +576,11 @@ int spi_write_then_read(struct spi_devic - } else - local_buf = buf; - -- memset(x, 0, sizeof x); -- - memcpy(local_buf, txbuf, n_tx); - x[0].tx_buf = local_buf; -- x[0].len = n_tx; -- - x[1].rx_buf = local_buf + n_tx; -- x[1].len = n_rx; - - /* do the i/o */ -- message.transfers = x; -- message.n_transfer = ARRAY_SIZE(x); - status = spi_sync(spi, &message); - if (status == 0) { - memcpy(rxbuf, x[1].rx_buf, n_rx); ---- gregkh-2.6.orig/include/linux/spi/spi_bitbang.h -+++ gregkh-2.6/include/linux/spi/spi_bitbang.h -@@ -31,8 +31,15 @@ struct spi_bitbang { - struct spi_master *master; - - void (*chipselect)(struct spi_device *spi, int is_on); -+#define BITBANG_CS_ACTIVE 1 /* normally nCS, active low */ -+#define BITBANG_CS_INACTIVE 0 - -+ /* txrx_bufs() may handle dma mapping for transfers that don't -+ * already have one (transfer.{tx,rx}_dma is zero), or use PIO -+ */ - int (*txrx_bufs)(struct spi_device *spi, struct spi_transfer *t); -+ -+ /* txrx_word[SPI_MODE_*]() just looks like a shift register */ - u32 (*txrx_word[4])(struct spi_device *spi, - unsigned nsecs, - u32 word, u8 bits); ---- gregkh-2.6.orig/include/linux/spi/spi.h -+++ gregkh-2.6/include/linux/spi/spi.h -@@ -263,15 +263,16 @@ extern struct spi_master *spi_busnum_to_ - - /** - * struct spi_transfer - a read/write buffer pair -- * @tx_buf: data to be written (dma-safe address), or NULL -- * @rx_buf: data to be read (dma-safe address), or NULL -- * @tx_dma: DMA address of buffer, if spi_message.is_dma_mapped -- * @rx_dma: DMA address of buffer, if spi_message.is_dma_mapped -+ * @tx_buf: data to be written (dma-safe memory), or NULL -+ * @rx_buf: data to be read (dma-safe memory), or NULL -+ * @tx_dma: DMA address of tx_buf, if spi_message.is_dma_mapped -+ * @rx_dma: DMA address of rx_buf, if spi_message.is_dma_mapped - * @len: size of rx and tx buffers (in bytes) - * @cs_change: affects chipselect after this transfer completes - * @delay_usecs: microseconds to delay after this transfer before - * (optionally) changing the chipselect status, then starting - * the next transfer or completing this spi_message. -+ * @transfer_list: transfers are sequenced through spi_message.transfers - * - * SPI transfers always write the same number of bytes as they read. - * Protocol drivers should always provide rx_buf and/or tx_buf. -@@ -279,11 +280,16 @@ extern struct spi_master *spi_busnum_to_ - * the data being transferred; that may reduce overhead, when the - * underlying driver uses dma. - * -- * All SPI transfers start with the relevant chipselect active. Drivers -- * can change behavior of the chipselect after the transfer finishes -- * (including any mandatory delay). The normal behavior is to leave it -- * selected, except for the last transfer in a message. Setting cs_change -- * allows two additional behavior options: -+ * If the transmit buffer is null, undefined data will be shifted out -+ * while filling rx_buf. If the receive buffer is null, the data -+ * shifted in will be discarded. Only "len" bytes shift out (or in). -+ * It's an error to try to shift out a partial word. (For example, by -+ * shifting out three bytes with word size of sixteen or twenty bits; -+ * the former uses two bytes per word, the latter uses four bytes.) -+ * -+ * All SPI transfers start with the relevant chipselect active. Normally -+ * it stays selected until after the last transfer in a message. Drivers -+ * can affect the chipselect signal using cs_change: - * - * (i) If the transfer isn't the last one in the message, this flag is - * used to make the chipselect briefly go inactive in the middle of the -@@ -299,7 +305,8 @@ extern struct spi_master *spi_busnum_to_ - * The code that submits an spi_message (and its spi_transfers) - * to the lower layers is responsible for managing its memory. - * Zero-initialize every field you don't set up explicitly, to -- * insulate against future API updates. -+ * insulate against future API updates. After you submit a message -+ * and its transfers, ignore them until its completion callback. - */ - struct spi_transfer { - /* it's ok if tx_buf == rx_buf (right?) -@@ -316,12 +323,13 @@ struct spi_transfer { - - unsigned cs_change:1; - u16 delay_usecs; -+ -+ struct list_head transfer_list; - }; - - /** - * struct spi_message - one multi-segment SPI transaction -- * @transfers: the segements of the transaction -- * @n_transfer: how many segments -+ * @transfers: list of transfer segments in this transaction - * @spi: SPI device to which the transaction is queued - * @is_dma_mapped: if true, the caller provided both dma and cpu virtual - * addresses for each transfer buffer -@@ -333,14 +341,22 @@ struct spi_transfer { - * @queue: for use by whichever driver currently owns the message - * @state: for use by whichever driver currently owns the message - * -+ * An spi_message is used to execute an atomic sequence of data transfers, -+ * each represented by a struct spi_transfer. The sequence is "atomic" -+ * in the sense that no other spi_message may use that SPI bus until that -+ * sequence completes. On some systems, many such sequences can execute as -+ * as single programmed DMA transfer. On all systems, these messages are -+ * queued, and might complete after transactions to other devices. Messages -+ * sent to a given spi_device are alway executed in FIFO order. -+ * - * The code that submits an spi_message (and its spi_transfers) - * to the lower layers is responsible for managing its memory. - * Zero-initialize every field you don't set up explicitly, to -- * insulate against future API updates. -+ * insulate against future API updates. After you submit a message -+ * and its transfers, ignore them until its completion callback. - */ - struct spi_message { -- struct spi_transfer *transfers; -- unsigned n_transfer; -+ struct list_head transfers; - - struct spi_device *spi; - -@@ -371,6 +387,24 @@ struct spi_message { - void *state; - }; - -+static inline void spi_message_init(struct spi_message *m) -+{ -+ memset(m, 0, sizeof *m); -+ INIT_LIST_HEAD(&m->transfers); -+} -+ -+static inline void -+spi_message_add_tail(struct spi_transfer *t, struct spi_message *m) -+{ -+ list_add_tail(&t->transfer_list, &m->transfers); -+} -+ -+static inline void -+spi_transfer_del(struct spi_transfer *t) -+{ -+ list_del(&t->transfer_list); -+} -+ - /* It's fine to embed message and transaction structures in other data - * structures so long as you don't free them while they're in use. - */ -@@ -383,8 +417,12 @@ static inline struct spi_message *spi_me - + ntrans * sizeof(struct spi_transfer), - flags); - if (m) { -- m->transfers = (void *)(m + 1); -- m->n_transfer = ntrans; -+ int i; -+ struct spi_transfer *t = (struct spi_transfer *)(m + 1); -+ -+ INIT_LIST_HEAD(&m->transfers); -+ for (i = 0; i < ntrans; i++, t++) -+ spi_message_add_tail(t, m); - } - return m; - } -@@ -402,6 +440,8 @@ static inline void spi_message_free(stru - * device doesn't work with the mode 0 default. They may likewise need - * to update clock rates or word sizes from initial values. This function - * changes those settings, and must be called from a context that can sleep. -+ * The changes take effect the next time the device is selected and data -+ * is transferred to or from it. - */ - static inline int - spi_setup(struct spi_device *spi) -@@ -468,15 +508,12 @@ spi_write(struct spi_device *spi, const - { - struct spi_transfer t = { - .tx_buf = buf, -- .rx_buf = NULL, - .len = len, -- .cs_change = 0, -- }; -- struct spi_message m = { -- .transfers = &t, -- .n_transfer = 1, - }; -+ struct spi_message m; - -+ spi_message_init(&m); -+ spi_message_add_tail(&t, &m); - return spi_sync(spi, &m); - } - -@@ -493,16 +530,13 @@ static inline int - spi_read(struct spi_device *spi, u8 *buf, size_t len) - { - struct spi_transfer t = { -- .tx_buf = NULL, - .rx_buf = buf, - .len = len, -- .cs_change = 0, -- }; -- struct spi_message m = { -- .transfers = &t, -- .n_transfer = 1, - }; -+ struct spi_message m; - -+ spi_message_init(&m); -+ spi_message_add_tail(&t, &m); - return spi_sync(spi, &m); - } - |