From 55f9102b7591c4cc057e6aa9e9d1e8df7ab97377 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 25 Nov 2011 11:13:58 +0000 Subject: [PATCH 001/365] gma500: mark staging broken It now clashes with upstream DRM which we don't want to block. We don't want to delete this code just yet as we want to keep it for comparison and reference when debugging, but soon it will be a removal candidate as well Signed-off-by: Alan Cox Cc: linux-next@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gma500/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/gma500/Kconfig b/drivers/staging/gma500/Kconfig index bfe2166acda6..c7a2b3bc0a18 100644 --- a/drivers/staging/gma500/Kconfig +++ b/drivers/staging/gma500/Kconfig @@ -1,6 +1,6 @@ config DRM_PSB tristate "Intel GMA5/600 KMS Framebuffer" - depends on DRM && PCI && X86 + depends on DRM && PCI && X86 && BROKEN select FB_CFB_COPYAREA select FB_CFB_FILLRECT select FB_CFB_IMAGEBLIT From 575c1e43c85307b66625f9d5940302ac10333434 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 23 Oct 2011 18:30:39 +0200 Subject: [PATCH 002/365] staging:mei: wd_ops and wd_info should be static wd_ops and wd_info structures are local to wd.c so mark them static Cc: Oren Weil Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/staging/mei/wd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/mei/wd.c b/drivers/staging/mei/wd.c index ffca7ca32658..cb3f92d221a7 100644 --- a/drivers/staging/mei/wd.c +++ b/drivers/staging/mei/wd.c @@ -331,14 +331,14 @@ static int mei_wd_ops_set_timeout(struct watchdog_device *wd_dev, unsigned int t /* * Watchdog Device structs */ -const struct watchdog_ops wd_ops = { +static const struct watchdog_ops wd_ops = { .owner = THIS_MODULE, .start = mei_wd_ops_start, .stop = mei_wd_ops_stop, .ping = mei_wd_ops_ping, .set_timeout = mei_wd_ops_set_timeout, }; -const struct watchdog_info wd_info = { +static const struct watchdog_info wd_info = { .identity = INTEL_AMT_WATCHDOG_ID, .options = WDIOF_KEEPALIVEPING, }; From 5b881e3c08a8041604bd60117cca22e1ff026e9b Mon Sep 17 00:00:00 2001 From: Oren Weil Date: Sun, 13 Nov 2011 09:41:14 +0200 Subject: [PATCH 003/365] staging: mei: expose misc interface instead of char device Misc device provides everything MEI needs for registration, it doesn't required separate driver class. Signed-off-by: Oren Weil Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/staging/mei/main.c | 530 +++++++++++++--------------------- drivers/staging/mei/mei_dev.h | 7 - 2 files changed, 207 insertions(+), 330 deletions(-) diff --git a/drivers/staging/mei/main.c b/drivers/staging/mei/main.c index eb05c36f45d4..410b5d46b150 100644 --- a/drivers/staging/mei/main.c +++ b/drivers/staging/mei/main.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "mei_dev.h" #include "mei.h" @@ -51,18 +52,10 @@ static char mei_driver_name[] = MEI_DRIVER_NAME; static const char mei_driver_string[] = "Intel(R) Management Engine Interface"; static const char mei_driver_version[] = MEI_DRIVER_VERSION; -/* mei char device for registration */ -static struct cdev mei_cdev; - -/* major number for device */ -static int mei_major; /* The device pointer */ /* Currently this driver works as long as there is only a single AMT device. */ struct pci_dev *mei_device; -static struct class *mei_class; - - /* mei_pci_tbl - PCI Device ID Table */ static DEFINE_PCI_DEVICE_TABLE(mei_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82946GZ)}, @@ -105,173 +98,6 @@ MODULE_DEVICE_TABLE(pci, mei_pci_tbl); static DEFINE_MUTEX(mei_mutex); -/** - * mei_probe - Device Initialization Routine - * - * @pdev: PCI device structure - * @ent: entry in kcs_pci_tbl - * - * returns 0 on success, <0 on failure. - */ -static int __devinit mei_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct mei_device *dev; - int err; - - mutex_lock(&mei_mutex); - if (mei_device) { - err = -EEXIST; - goto end; - } - /* enable pci dev */ - err = pci_enable_device(pdev); - if (err) { - printk(KERN_ERR "mei: Failed to enable pci device.\n"); - goto end; - } - /* set PCI host mastering */ - pci_set_master(pdev); - /* pci request regions for mei driver */ - err = pci_request_regions(pdev, mei_driver_name); - if (err) { - printk(KERN_ERR "mei: Failed to get pci regions.\n"); - goto disable_device; - } - /* allocates and initializes the mei dev structure */ - dev = mei_device_init(pdev); - if (!dev) { - err = -ENOMEM; - goto release_regions; - } - /* mapping IO device memory */ - dev->mem_addr = pci_iomap(pdev, 0, 0); - if (!dev->mem_addr) { - printk(KERN_ERR "mei: mapping I/O device memory failure.\n"); - err = -ENOMEM; - goto free_device; - } - pci_enable_msi(pdev); - - /* request and enable interrupt */ - if (pci_dev_msi_enabled(pdev)) - err = request_threaded_irq(pdev->irq, - NULL, - mei_interrupt_thread_handler, - 0, mei_driver_name, dev); - else - err = request_threaded_irq(pdev->irq, - mei_interrupt_quick_handler, - mei_interrupt_thread_handler, - IRQF_SHARED, mei_driver_name, dev); - - if (err) { - printk(KERN_ERR "mei: request_threaded_irq failure. irq = %d\n", - pdev->irq); - goto unmap_memory; - } - INIT_DELAYED_WORK(&dev->timer_work, mei_timer); - if (mei_hw_init(dev)) { - printk(KERN_ERR "mei: Init hw failure.\n"); - err = -ENODEV; - goto release_irq; - } - mei_device = pdev; - pci_set_drvdata(pdev, dev); - schedule_delayed_work(&dev->timer_work, HZ); - - mutex_unlock(&mei_mutex); - - pr_debug("mei: Driver initialization successful.\n"); - - return 0; - -release_irq: - /* disable interrupts */ - dev->host_hw_state = mei_hcsr_read(dev); - mei_disable_interrupts(dev); - flush_scheduled_work(); - free_irq(pdev->irq, dev); - pci_disable_msi(pdev); -unmap_memory: - pci_iounmap(pdev, dev->mem_addr); -free_device: - kfree(dev); -release_regions: - pci_release_regions(pdev); -disable_device: - pci_disable_device(pdev); -end: - mutex_unlock(&mei_mutex); - printk(KERN_ERR "mei: Driver initialization failed.\n"); - return err; -} - -/** - * mei_remove - Device Removal Routine - * - * @pdev: PCI device structure - * - * mei_remove is called by the PCI subsystem to alert the driver - * that it should release a PCI device. - */ -static void __devexit mei_remove(struct pci_dev *pdev) -{ - struct mei_device *dev; - - if (mei_device != pdev) - return; - - dev = pci_get_drvdata(pdev); - if (!dev) - return; - - mutex_lock(&dev->device_lock); - - mei_wd_stop(dev, false); - - mei_device = NULL; - - if (dev->iamthif_cl.state == MEI_FILE_CONNECTED) { - dev->iamthif_cl.state = MEI_FILE_DISCONNECTING; - mei_disconnect_host_client(dev, &dev->iamthif_cl); - } - if (dev->wd_cl.state == MEI_FILE_CONNECTED) { - dev->wd_cl.state = MEI_FILE_DISCONNECTING; - mei_disconnect_host_client(dev, &dev->wd_cl); - } - - /* Unregistering watchdog device */ - if (dev->wd_interface_reg) - watchdog_unregister_device(&amt_wd_dev); - - /* remove entry if already in list */ - dev_dbg(&pdev->dev, "list del iamthif and wd file list.\n"); - mei_remove_client_from_file_list(dev, dev->wd_cl.host_client_id); - mei_remove_client_from_file_list(dev, dev->iamthif_cl.host_client_id); - - dev->iamthif_current_cb = NULL; - dev->me_clients_num = 0; - - mutex_unlock(&dev->device_lock); - - flush_scheduled_work(); - - /* disable interrupts */ - mei_disable_interrupts(dev); - - free_irq(pdev->irq, dev); - pci_disable_msi(pdev); - pci_set_drvdata(pdev, NULL); - - if (dev->mem_addr) - pci_iounmap(pdev, dev->mem_addr); - - kfree(dev); - - pci_release_regions(pdev); - pci_disable_device(pdev); -} /** * mei_clear_list - removes all callbacks associated with file @@ -402,7 +228,7 @@ static struct mei_cl_cb *find_read_list_entry( static int mei_open(struct inode *inode, struct file *file) { struct mei_cl *cl; - int if_num = iminor(inode), err; + int err; struct mei_device *dev; err = -ENODEV; @@ -410,7 +236,7 @@ static int mei_open(struct inode *inode, struct file *file) goto out; dev = pci_get_drvdata(mei_device); - if (if_num != MEI_MINOR_NUMBER || !dev) + if (!dev) goto out; mutex_lock(&dev->device_lock); @@ -446,7 +272,7 @@ static int mei_open(struct inode *inode, struct file *file) file->private_data = cl; mutex_unlock(&dev->device_lock); - return 0; + return nonseekable_open(inode, file); out_unlock: mutex_unlock(&dev->device_lock); @@ -1090,6 +916,207 @@ out: return mask; } +/* + * file operations structure will be used for mei char device. + */ +static const struct file_operations mei_fops = { + .owner = THIS_MODULE, + .read = mei_read, + .unlocked_ioctl = mei_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = mei_compat_ioctl, +#endif + .open = mei_open, + .release = mei_release, + .write = mei_write, + .poll = mei_poll, + .llseek = no_llseek +}; + + +/* + * Misc Device Struct + */ +static struct miscdevice mei_misc_device = { + .name = MEI_DRIVER_NAME, + .fops = &mei_fops, + .minor = MISC_DYNAMIC_MINOR, +}; + +/** + * mei_probe - Device Initialization Routine + * + * @pdev: PCI device structure + * @ent: entry in kcs_pci_tbl + * + * returns 0 on success, <0 on failure. + */ +static int __devinit mei_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct mei_device *dev; + int err; + + mutex_lock(&mei_mutex); + if (mei_device) { + err = -EEXIST; + goto end; + } + /* enable pci dev */ + err = pci_enable_device(pdev); + if (err) { + printk(KERN_ERR "mei: Failed to enable pci device.\n"); + goto end; + } + /* set PCI host mastering */ + pci_set_master(pdev); + /* pci request regions for mei driver */ + err = pci_request_regions(pdev, mei_driver_name); + if (err) { + printk(KERN_ERR "mei: Failed to get pci regions.\n"); + goto disable_device; + } + /* allocates and initializes the mei dev structure */ + dev = mei_device_init(pdev); + if (!dev) { + err = -ENOMEM; + goto release_regions; + } + /* mapping IO device memory */ + dev->mem_addr = pci_iomap(pdev, 0, 0); + if (!dev->mem_addr) { + printk(KERN_ERR "mei: mapping I/O device memory failure.\n"); + err = -ENOMEM; + goto free_device; + } + pci_enable_msi(pdev); + + /* request and enable interrupt */ + if (pci_dev_msi_enabled(pdev)) + err = request_threaded_irq(pdev->irq, + NULL, + mei_interrupt_thread_handler, + 0, mei_driver_name, dev); + else + err = request_threaded_irq(pdev->irq, + mei_interrupt_quick_handler, + mei_interrupt_thread_handler, + IRQF_SHARED, mei_driver_name, dev); + + if (err) { + printk(KERN_ERR "mei: request_threaded_irq failure. irq = %d\n", + pdev->irq); + goto unmap_memory; + } + INIT_DELAYED_WORK(&dev->timer_work, mei_timer); + if (mei_hw_init(dev)) { + printk(KERN_ERR "mei: Init hw failure.\n"); + err = -ENODEV; + goto release_irq; + } + + err = misc_register(&mei_misc_device); + if (err) + goto release_irq; + + mei_device = pdev; + pci_set_drvdata(pdev, dev); + + + schedule_delayed_work(&dev->timer_work, HZ); + + mutex_unlock(&mei_mutex); + + pr_debug("mei: Driver initialization successful.\n"); + + return 0; + +release_irq: + /* disable interrupts */ + dev->host_hw_state = mei_hcsr_read(dev); + mei_disable_interrupts(dev); + flush_scheduled_work(); + free_irq(pdev->irq, dev); + pci_disable_msi(pdev); +unmap_memory: + pci_iounmap(pdev, dev->mem_addr); +free_device: + kfree(dev); +release_regions: + pci_release_regions(pdev); +disable_device: + pci_disable_device(pdev); +end: + mutex_unlock(&mei_mutex); + printk(KERN_ERR "mei: Driver initialization failed.\n"); + return err; +} + +/** + * mei_remove - Device Removal Routine + * + * @pdev: PCI device structure + * + * mei_remove is called by the PCI subsystem to alert the driver + * that it should release a PCI device. + */ +static void __devexit mei_remove(struct pci_dev *pdev) +{ + struct mei_device *dev; + + if (mei_device != pdev) + return; + + dev = pci_get_drvdata(pdev); + if (!dev) + return; + + mutex_lock(&dev->device_lock); + + mei_wd_stop(dev, false); + + mei_device = NULL; + + if (dev->iamthif_cl.state == MEI_FILE_CONNECTED) { + dev->iamthif_cl.state = MEI_FILE_DISCONNECTING; + mei_disconnect_host_client(dev, &dev->iamthif_cl); + } + if (dev->wd_cl.state == MEI_FILE_CONNECTED) { + dev->wd_cl.state = MEI_FILE_DISCONNECTING; + mei_disconnect_host_client(dev, &dev->wd_cl); + } + + /* Unregistering watchdog device */ + if (dev->wd_interface_reg) + watchdog_unregister_device(&amt_wd_dev); + + /* remove entry if already in list */ + dev_dbg(&pdev->dev, "list del iamthif and wd file list.\n"); + mei_remove_client_from_file_list(dev, dev->wd_cl.host_client_id); + mei_remove_client_from_file_list(dev, dev->iamthif_cl.host_client_id); + + dev->iamthif_current_cb = NULL; + dev->me_clients_num = 0; + + mutex_unlock(&dev->device_lock); + + flush_scheduled_work(); + + /* disable interrupts */ + mei_disable_interrupts(dev); + + free_irq(pdev->irq, dev); + pci_disable_msi(pdev); + pci_set_drvdata(pdev, NULL); + + if (dev->mem_addr) + pci_iounmap(pdev, dev->mem_addr); + + kfree(dev); + + pci_release_regions(pdev); + pci_disable_device(pdev); +} #ifdef CONFIG_PM static int mei_pci_suspend(struct device *device) { @@ -1173,131 +1200,6 @@ static struct pci_driver mei_driver = { .driver.pm = MEI_PM_OPS, }; -/* - * file operations structure will be used for mei char device. - */ -static const struct file_operations mei_fops = { - .owner = THIS_MODULE, - .read = mei_read, - .unlocked_ioctl = mei_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = mei_compat_ioctl, -#endif - .open = mei_open, - .release = mei_release, - .write = mei_write, - .poll = mei_poll, -}; - -/** - * mei_registration_cdev - sets up the cdev structure for mei device. - * - * @dev: char device struct - * @hminor: minor number for registration char device - * @fops: file operations structure - * - * returns 0 on success, <0 on failure. - */ -static int mei_registration_cdev(struct cdev *dev, int hminor, - const struct file_operations *fops) -{ - int ret, devno = MKDEV(mei_major, hminor); - - cdev_init(dev, fops); - dev->owner = THIS_MODULE; - ret = cdev_add(dev, devno, 1); - /* Fail gracefully if need be */ - if (ret) - printk(KERN_ERR "mei: Error %d registering mei device %d\n", - ret, hminor); - return ret; -} - -/** - * mei_register_cdev - registers mei char device - * - * returns 0 on success, <0 on failure. - */ -static int mei_register_cdev(void) -{ - int ret; - dev_t dev; - - /* registration of char devices */ - ret = alloc_chrdev_region(&dev, MEI_MINORS_BASE, MEI_MINORS_COUNT, - MEI_DRIVER_NAME); - if (ret) { - printk(KERN_ERR "mei: Error allocating char device region.\n"); - return ret; - } - - mei_major = MAJOR(dev); - - ret = mei_registration_cdev(&mei_cdev, MEI_MINOR_NUMBER, - &mei_fops); - if (ret) - unregister_chrdev_region(MKDEV(mei_major, MEI_MINORS_BASE), - MEI_MINORS_COUNT); - - return ret; -} - -/** - * mei_unregister_cdev - unregisters mei char device - */ -static void mei_unregister_cdev(void) -{ - cdev_del(&mei_cdev); - unregister_chrdev_region(MKDEV(mei_major, MEI_MINORS_BASE), - MEI_MINORS_COUNT); -} - -/** - * mei_sysfs_device_create - adds device entry to sysfs - * - * returns 0 on success, <0 on failure. - */ -static int mei_sysfs_device_create(void) -{ - struct class *class; - void *tmphdev; - int err; - - class = class_create(THIS_MODULE, MEI_DRIVER_NAME); - if (IS_ERR(class)) { - err = PTR_ERR(class); - printk(KERN_ERR "mei: Error creating mei class.\n"); - goto err_out; - } - - tmphdev = device_create(class, NULL, mei_cdev.dev, NULL, - MEI_DEV_NAME); - if (IS_ERR(tmphdev)) { - err = PTR_ERR(tmphdev); - goto err_destroy; - } - - mei_class = class; - return 0; - -err_destroy: - class_destroy(class); -err_out: - return err; -} - -/** - * mei_sysfs_device_remove - unregisters the device entry on sysfs - */ -static void mei_sysfs_device_remove(void) -{ - if (IS_ERR_OR_NULL(mei_class)) - return; - - device_destroy(mei_class, mei_cdev.dev); - class_destroy(mei_class); -} - /** * mei_init_module - Driver Registration Routine * @@ -1314,26 +1216,9 @@ static int __init mei_init_module(void) mei_driver_string, mei_driver_version); /* init pci module */ ret = pci_register_driver(&mei_driver); - if (ret < 0) { + if (ret < 0) printk(KERN_ERR "mei: Error registering driver.\n"); - goto end; - } - ret = mei_register_cdev(); - if (ret) - goto unregister_pci; - - ret = mei_sysfs_device_create(); - if (ret) - goto unregister_cdev; - - return ret; - -unregister_cdev: - mei_unregister_cdev(); -unregister_pci: - pci_unregister_driver(&mei_driver); -end: return ret; } @@ -1347,8 +1232,7 @@ module_init(mei_init_module); */ static void __exit mei_exit_module(void) { - mei_sysfs_device_remove(); - mei_unregister_cdev(); + misc_deregister(&mei_misc_device); pci_unregister_driver(&mei_driver); pr_debug("mei: Driver unloaded successfully.\n"); diff --git a/drivers/staging/mei/mei_dev.h b/drivers/staging/mei/mei_dev.h index af4b1af9eeac..13c2ba022974 100644 --- a/drivers/staging/mei/mei_dev.h +++ b/drivers/staging/mei/mei_dev.h @@ -22,13 +22,6 @@ #include "mei.h" #include "hw.h" -/* - * MEI Char Driver Minors - */ -#define MEI_MINORS_BASE 1 -#define MEI_MINORS_COUNT 1 -#define MEI_MINOR_NUMBER 1 - /* * watch dog definition */ From 6f37aca827e6d075c9e9d3ab1b233cce2a3bc9f1 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 13 Nov 2011 09:41:15 +0200 Subject: [PATCH 004/365] staging/mei: fix check for allocating host client id MEI_CLIENTS_MAX is 255 and host_client_id is u8 therefore for check to work we need to first assign the return value of find_first_zero_bit to unsigned long variable Fix warning drivers/staging/mei/main.c: In function mei_open drivers/staging/mei/main.c:260:2: warning: comparison is always false due to limited range of data type Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/staging/mei/main.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/staging/mei/main.c b/drivers/staging/mei/main.c index 410b5d46b150..1ea04b31f611 100644 --- a/drivers/staging/mei/main.c +++ b/drivers/staging/mei/main.c @@ -228,8 +228,9 @@ static struct mei_cl_cb *find_read_list_entry( static int mei_open(struct inode *inode, struct file *file) { struct mei_cl *cl; - int err; struct mei_device *dev; + unsigned long cl_id; + int err; err = -ENODEV; if (!mei_device) @@ -255,14 +256,16 @@ static int mei_open(struct inode *inode, struct file *file) if (dev->open_handle_count >= MEI_MAX_OPEN_HANDLE_COUNT) goto out_unlock; - cl->host_client_id = find_first_zero_bit(dev->host_clients_map, - MEI_CLIENTS_MAX); - if (cl->host_client_id > MEI_CLIENTS_MAX) + cl_id = find_first_zero_bit(dev->host_clients_map, MEI_CLIENTS_MAX); + if (cl_id >= MEI_CLIENTS_MAX) goto out_unlock; + cl->host_client_id = cl_id; + dev_dbg(&dev->pdev->dev, "client_id = %d\n", cl->host_client_id); dev->open_handle_count++; + list_add_tail(&cl->link, &dev->file_list); set_bit(cl->host_client_id, dev->host_clients_map); From 982d6ab50115025c63f4b9f7175614008c41d449 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Mon, 24 Oct 2011 23:41:37 +0200 Subject: [PATCH 005/365] line6: fix memory leaks in line6_init_midi() If the first call to line6_midibuf_init() fails we'll leak a little bit of memory. If the second call fails we'll leak a bit more. This happens when we return from the function and the local variable 'line6midi' goes out of scope. Signed-off-by: Jesper Juhl Signed-off-by: Greg Kroah-Hartman --- drivers/staging/line6/midi.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/staging/line6/midi.c b/drivers/staging/line6/midi.c index e554a2da643a..86c50cf9b2a7 100644 --- a/drivers/staging/line6/midi.c +++ b/drivers/staging/line6/midi.c @@ -391,12 +391,17 @@ int line6_init_midi(struct usb_line6 *line6) return -ENOMEM; err = line6_midibuf_init(&line6midi->midibuf_in, MIDI_BUFFER_SIZE, 0); - if (err < 0) + if (err < 0) { + kfree(line6midi); return err; + } err = line6_midibuf_init(&line6midi->midibuf_out, MIDI_BUFFER_SIZE, 1); - if (err < 0) + if (err < 0) { + kfree(line6midi->midibuf_in.buf); + kfree(line6midi); return err; + } line6midi->line6 = line6; line6midi->midi_mask_transmit = 1; From 16dc10401133d16d13a5eea7da2a71d2080e32a1 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 23 Nov 2011 08:20:42 +0000 Subject: [PATCH 006/365] staging: line6: add Pod HD300 support The Pod HD device family uses new MIDI SysEx messages and therefore cannot reuse the existing Pod code. Instead of hardcoding Pod HD MIDI messages into the driver, leave MIDI up to userspace. This driver simply presents MIDI and pcm ALSA devices. This device is similar to the Pod except that it has 48 kHz audio and does not respond to Pod SysEx messages. Signed-off-by: Stefan Hajnoczi Signed-off-by: Greg Kroah-Hartman --- drivers/staging/line6/Makefile | 3 +- drivers/staging/line6/driver.c | 24 ++++- drivers/staging/line6/pcm.c | 1 + drivers/staging/line6/podhd.c | 158 ++++++++++++++++++++++++++++++++ drivers/staging/line6/podhd.h | 30 ++++++ drivers/staging/line6/usbdefs.h | 2 + 6 files changed, 216 insertions(+), 2 deletions(-) create mode 100644 drivers/staging/line6/podhd.c create mode 100644 drivers/staging/line6/podhd.h diff --git a/drivers/staging/line6/Makefile b/drivers/staging/line6/Makefile index de6bd12e9736..34a2ddacc7e9 100644 --- a/drivers/staging/line6/Makefile +++ b/drivers/staging/line6/Makefile @@ -12,4 +12,5 @@ line6usb-y := \ playback.o \ pod.o \ toneport.o \ - variax.o + variax.o \ + podhd.o diff --git a/drivers/staging/line6/driver.c b/drivers/staging/line6/driver.c index 851b762319cf..a71a5af7f8e3 100644 --- a/drivers/staging/line6/driver.c +++ b/drivers/staging/line6/driver.c @@ -21,6 +21,7 @@ #include "midi.h" #include "playback.h" #include "pod.h" +#include "podhd.h" #include "revision.h" #include "toneport.h" #include "usbdefs.h" @@ -49,6 +50,7 @@ static const struct usb_device_id line6_id_table[] = { {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_TONEPORT_UX1)}, {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_TONEPORT_UX2)}, {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_VARIAX)}, + {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODHD300)}, {}, }; @@ -72,7 +74,8 @@ static struct line6_properties line6_properties_table[] = { { "TonePortGX", "TonePort GX", LINE6_BIT_TONEPORT_GX, LINE6_BIT_PCM }, { "TonePortUX1", "TonePort UX1", LINE6_BIT_TONEPORT_UX1, LINE6_BIT_PCM }, { "TonePortUX2", "TonePort UX2", LINE6_BIT_TONEPORT_UX2, LINE6_BIT_PCM }, - { "Variax", "Variax Workbench", LINE6_BIT_VARIAX, LINE6_BIT_CONTROL } + { "Variax", "Variax Workbench", LINE6_BIT_VARIAX, LINE6_BIT_CONTROL }, + { "PODHD300", "POD HD300", LINE6_BIT_PODHD300, LINE6_BIT_CONTROL_PCM_HWMON }, }; /* *INDENT-ON* */ @@ -437,6 +440,9 @@ static void line6_data_received(struct urb *urb) line6); break; + case LINE6_DEVID_PODHD300: + break; /* let userspace handle MIDI */ + case LINE6_DEVID_PODXTLIVE: switch (line6->interface_number) { case PODXTLIVE_INTERFACE_POD: @@ -812,6 +818,7 @@ static int line6_probe(struct usb_interface *interface, case LINE6_DEVID_BASSPODXTPRO: case LINE6_DEVID_PODXT: case LINE6_DEVID_PODXTPRO: + case LINE6_DEVID_PODHD300: alternate = 5; break; @@ -865,6 +872,12 @@ static int line6_probe(struct usb_interface *interface, ep_write = 0x03; break; + case LINE6_DEVID_PODHD300: + size = sizeof(struct usb_line6_podhd); + ep_read = 0x84; + ep_write = 0x03; + break; + case LINE6_DEVID_POCKETPOD: size = sizeof(struct usb_line6_pod); ep_read = 0x82; @@ -1017,6 +1030,11 @@ static int line6_probe(struct usb_interface *interface, ret = line6_pod_init(interface, (struct usb_line6_pod *)line6); break; + case LINE6_DEVID_PODHD300: + ret = line6_podhd_init(interface, + (struct usb_line6_podhd *)line6); + break; + case LINE6_DEVID_PODXTLIVE: switch (interface_number) { case PODXTLIVE_INTERFACE_POD: @@ -1139,6 +1157,10 @@ static void line6_disconnect(struct usb_interface *interface) line6_pod_disconnect(interface); break; + case LINE6_DEVID_PODHD300: + line6_podhd_disconnect(interface); + break; + case LINE6_DEVID_PODXTLIVE: switch (interface_number) { case PODXTLIVE_INTERFACE_POD: diff --git a/drivers/staging/line6/pcm.c b/drivers/staging/line6/pcm.c index 9d4c8a606eea..f56c6427c36e 100644 --- a/drivers/staging/line6/pcm.c +++ b/drivers/staging/line6/pcm.c @@ -403,6 +403,7 @@ int line6_init_pcm(struct usb_line6 *line6, case LINE6_DEVID_PODXT: case LINE6_DEVID_PODXTLIVE: case LINE6_DEVID_PODXTPRO: + case LINE6_DEVID_PODHD300: ep_read = 0x82; ep_write = 0x01; break; diff --git a/drivers/staging/line6/podhd.c b/drivers/staging/line6/podhd.c new file mode 100644 index 000000000000..6c0f7f21c248 --- /dev/null +++ b/drivers/staging/line6/podhd.c @@ -0,0 +1,158 @@ +/* + * Line6 Pod HD + * + * Copyright (C) 2011 Stefan Hajnoczi + * + * 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, version 2. + * + */ + +#include +#include + +#include "audio.h" +#include "driver.h" +#include "pcm.h" +#include "podhd.h" + +#define PODHD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */ + +static struct snd_ratden podhd_ratden = { + .num_min = 48000, + .num_max = 48000, + .num_step = 1, + .den = 1, +}; + +static struct line6_pcm_properties podhd_pcm_properties = { + .snd_line6_playback_hw = { + .info = (SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | +#ifdef CONFIG_PM + SNDRV_PCM_INFO_RESUME | +#endif + SNDRV_PCM_INFO_SYNC_START), + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + .buffer_bytes_max = 60000, + .period_bytes_min = 64, + .period_bytes_max = 8192, + .periods_min = 1, + .periods_max = 1024}, + .snd_line6_capture_hw = { + .info = (SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | +#ifdef CONFIG_PM + SNDRV_PCM_INFO_RESUME | +#endif + SNDRV_PCM_INFO_SYNC_START), + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + .buffer_bytes_max = 60000, + .period_bytes_min = 64, + .period_bytes_max = 8192, + .periods_min = 1, + .periods_max = 1024}, + .snd_line6_rates = { + .nrats = 1, + .rats = &podhd_ratden}, + .bytes_per_frame = PODHD_BYTES_PER_FRAME +}; + +/* + POD HD destructor. +*/ +static void podhd_destruct(struct usb_interface *interface) +{ + struct usb_line6_podhd *podhd = usb_get_intfdata(interface); + struct usb_line6 *line6; + + if (podhd == NULL) + return; + line6 = &podhd->line6; + if (line6 == NULL) + return; + line6_cleanup_audio(line6); +} + +/* + Try to init POD HD device. +*/ +static int podhd_try_init(struct usb_interface *interface, + struct usb_line6_podhd *podhd) +{ + int err; + struct usb_line6 *line6 = &podhd->line6; + + if ((interface == NULL) || (podhd == NULL)) + return -ENODEV; + + /* initialize audio system: */ + err = line6_init_audio(line6); + if (err < 0) + return err; + + /* initialize MIDI subsystem: */ + err = line6_init_midi(line6); + if (err < 0) + return err; + + /* initialize PCM subsystem: */ + err = line6_init_pcm(line6, &podhd_pcm_properties); + if (err < 0) + return err; + + /* register USB audio system: */ + err = line6_register_audio(line6); + return err; +} + +/* + Init POD HD device (and clean up in case of failure). +*/ +int line6_podhd_init(struct usb_interface *interface, + struct usb_line6_podhd *podhd) +{ + int err = podhd_try_init(interface, podhd); + + if (err < 0) + podhd_destruct(interface); + + return err; +} + +/* + POD HD device disconnected. +*/ +void line6_podhd_disconnect(struct usb_interface *interface) +{ + struct usb_line6_podhd *podhd; + + if (interface == NULL) + return; + podhd = usb_get_intfdata(interface); + + if (podhd != NULL) { + struct snd_line6_pcm *line6pcm = podhd->line6.line6pcm; + + if (line6pcm != NULL) + line6_pcm_disconnect(line6pcm); + } + + podhd_destruct(interface); +} diff --git a/drivers/staging/line6/podhd.h b/drivers/staging/line6/podhd.h new file mode 100644 index 000000000000..652f74056bb9 --- /dev/null +++ b/drivers/staging/line6/podhd.h @@ -0,0 +1,30 @@ +/* + * Line6 Pod HD + * + * Copyright (C) 2011 Stefan Hajnoczi + * + * 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, version 2. + * + */ + +#ifndef PODHD_H +#define PODHD_H + +#include + +#include "driver.h" + +struct usb_line6_podhd { + /** + Generic Line6 USB data. + */ + struct usb_line6 line6; +}; + +extern void line6_podhd_disconnect(struct usb_interface *interface); +extern int line6_podhd_init(struct usb_interface *interface, + struct usb_line6_podhd *podhd); + +#endif /* PODHD_H */ diff --git a/drivers/staging/line6/usbdefs.h b/drivers/staging/line6/usbdefs.h index c6dffe6bc1a5..4e133641fa79 100644 --- a/drivers/staging/line6/usbdefs.h +++ b/drivers/staging/line6/usbdefs.h @@ -36,6 +36,7 @@ #define LINE6_DEVID_TONEPORT_UX1 0x4141 #define LINE6_DEVID_TONEPORT_UX2 0x4142 #define LINE6_DEVID_VARIAX 0x534d +#define LINE6_DEVID_PODHD300 0x5057 #define LINE6_BIT_BASSPODXT (1 << 0) #define LINE6_BIT_BASSPODXTLIVE (1 << 1) @@ -54,6 +55,7 @@ #define LINE6_BIT_TONEPORT_UX1 (1 << 14) #define LINE6_BIT_TONEPORT_UX2 (1 << 15) #define LINE6_BIT_VARIAX (1 << 16) +#define LINE6_BIT_PODHD300 (1 << 17) #define LINE6_BITS_PRO (LINE6_BIT_BASSPODXTPRO | \ LINE6_BIT_PODXTPRO) From 1dc403ffecae26ae52414488e326761a9ae10de7 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 23 Nov 2011 08:20:43 +0000 Subject: [PATCH 007/365] staging: line6: add missing MIDI postprocessing case for POD HD300 The driver leaves MIDI processing up to userspace for the POD HD300 device. Add a missing case statement to skip MIDI postprocessing in the driver. This change has no effect other than silencing a printk: line6usb driver bug: missing case in linux/drivers/staging/line6/midi.c:179 Signed-off-by: Stefan Hajnoczi Signed-off-by: Greg Kroah-Hartman --- drivers/staging/line6/midi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/line6/midi.c b/drivers/staging/line6/midi.c index 86c50cf9b2a7..ed5577f25afe 100644 --- a/drivers/staging/line6/midi.c +++ b/drivers/staging/line6/midi.c @@ -173,6 +173,7 @@ static int send_midi_async(struct usb_line6 *line6, unsigned char *data, break; case LINE6_DEVID_VARIAX: + case LINE6_DEVID_PODHD300: break; default: From 3b08db37cb04a80dccac8c2d7b03690b5f179487 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 23 Nov 2011 08:20:44 +0000 Subject: [PATCH 008/365] staging: line6: use smallest iso ep packet size The POD HD300 isochronous endpoints have different max packet sizes for read and write. Using the read endpoint max packet size may be too large for the write endpoint. Instead we should use the minimum of both endpoints to be sure the size is acceptable. In theory we could decouple read and write packet sizes but the driver currently uses a single size which I chose not to mess with since other features like software monitoring may depend on a single packet size for both endpoints. Signed-off-by: Stefan Hajnoczi Signed-off-by: Greg Kroah-Hartman --- drivers/staging/line6/pcm.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/staging/line6/pcm.c b/drivers/staging/line6/pcm.c index f56c6427c36e..ae984344749f 100644 --- a/drivers/staging/line6/pcm.c +++ b/drivers/staging/line6/pcm.c @@ -452,9 +452,14 @@ int line6_init_pcm(struct usb_line6 *line6, line6pcm->line6 = line6; line6pcm->ep_audio_read = ep_read; line6pcm->ep_audio_write = ep_write; - line6pcm->max_packet_size = usb_maxpacket(line6->usbdev, - usb_rcvintpipe(line6->usbdev, - ep_read), 0); + + /* Read and write buffers are sized identically, so choose minimum */ + line6pcm->max_packet_size = min( + usb_maxpacket(line6->usbdev, + usb_rcvisocpipe(line6->usbdev, ep_read), 0), + usb_maxpacket(line6->usbdev, + usb_sndisocpipe(line6->usbdev, ep_write), 1)); + line6pcm->properties = properties; line6->line6pcm = line6pcm; From 140e28b83c4a31831cbf293d9cab20c603821202 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 23 Nov 2011 08:20:45 +0000 Subject: [PATCH 009/365] staging: line6: alloc/free buffers in hw_params/hw_free It is unsafe to free buffers in line6_pcm_stop(), which is not allowed to sleep, since urbs cannot be killed completely there and only unlinked. This means I/O may still be in progress and the URB completion function still gets invoked. This may result in memory corruption when buffer_in is freed but I/O is still pending. Additionally, line6_pcm_start() is not supposed to sleep so it should not use kmalloc(GFP_KERNEL). These issues can be resolved by performing buffer allocation/freeing in the .hw_params/.hw_free callbacks instead. The ALSA documentation also recommends doing buffer allocation/freeing in these callbacks. Signed-off-by: Stefan Hajnoczi Signed-off-by: Greg Kroah-Hartman --- drivers/staging/line6/capture.c | 15 +++++++++++++++ drivers/staging/line6/pcm.c | 24 ------------------------ drivers/staging/line6/playback.c | 15 +++++++++++++++ 3 files changed, 30 insertions(+), 24 deletions(-) diff --git a/drivers/staging/line6/capture.c b/drivers/staging/line6/capture.c index 9647154a4923..d9da7edf1e7a 100644 --- a/drivers/staging/line6/capture.c +++ b/drivers/staging/line6/capture.c @@ -9,6 +9,7 @@ * */ +#include #include #include #include @@ -319,6 +320,15 @@ static int snd_line6_capture_hw_params(struct snd_pcm_substream *substream, } /* -- [FD] end */ + line6pcm->buffer_in = kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS * + line6pcm->max_packet_size, GFP_KERNEL); + + if (!line6pcm->buffer_in) { + dev_err(line6pcm->line6->ifcdev, + "cannot malloc capture buffer\n"); + return -ENOMEM; + } + ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); if (ret < 0) @@ -331,6 +341,11 @@ static int snd_line6_capture_hw_params(struct snd_pcm_substream *substream, /* hw_free capture callback */ static int snd_line6_capture_hw_free(struct snd_pcm_substream *substream) { + struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); + + line6_unlink_wait_clear_audio_in_urbs(line6pcm); + kfree(line6pcm->buffer_in); + line6pcm->buffer_in = NULL; return snd_pcm_lib_free_pages(substream); } diff --git a/drivers/staging/line6/pcm.c b/drivers/staging/line6/pcm.c index ae984344749f..2e4e164e81d8 100644 --- a/drivers/staging/line6/pcm.c +++ b/drivers/staging/line6/pcm.c @@ -119,16 +119,6 @@ int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels) if (line6pcm->active_urb_in | line6pcm->unlink_urb_in) return -EBUSY; - line6pcm->buffer_in = - kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS * - line6pcm->max_packet_size, GFP_KERNEL); - - if (!line6pcm->buffer_in) { - dev_err(line6pcm->line6->ifcdev, - "cannot malloc capture buffer\n"); - return -ENOMEM; - } - line6pcm->count_in = 0; line6pcm->prev_fsize = 0; err = line6_submit_audio_in_all_urbs(line6pcm); @@ -147,16 +137,6 @@ int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels) if (line6pcm->active_urb_out | line6pcm->unlink_urb_out) return -EBUSY; - line6pcm->buffer_out = - kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS * - line6pcm->max_packet_size, GFP_KERNEL); - - if (!line6pcm->buffer_out) { - dev_err(line6pcm->line6->ifcdev, - "cannot malloc playback buffer\n"); - return -ENOMEM; - } - line6pcm->count_out = 0; err = line6_submit_audio_out_all_urbs(line6pcm); @@ -178,15 +158,11 @@ int line6_pcm_stop(struct snd_line6_pcm *line6pcm, int channels) if (((flags_old & MASK_CAPTURE) != 0) && ((flags_new & MASK_CAPTURE) == 0)) { line6_unlink_audio_in_urbs(line6pcm); - kfree(line6pcm->buffer_in); - line6pcm->buffer_in = NULL; } if (((flags_old & MASK_PLAYBACK) != 0) && ((flags_new & MASK_PLAYBACK) == 0)) { line6_unlink_audio_out_urbs(line6pcm); - kfree(line6pcm->buffer_out); - line6pcm->buffer_out = NULL; } #if LINE6_BACKUP_MONITOR_SIGNAL kfree(line6pcm->prev_fbuf); diff --git a/drivers/staging/line6/playback.c b/drivers/staging/line6/playback.c index 10c543836583..b3445274072b 100644 --- a/drivers/staging/line6/playback.c +++ b/drivers/staging/line6/playback.c @@ -9,6 +9,7 @@ * */ +#include #include #include #include @@ -469,6 +470,15 @@ static int snd_line6_playback_hw_params(struct snd_pcm_substream *substream, } /* -- [FD] end */ + line6pcm->buffer_out = kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS * + line6pcm->max_packet_size, GFP_KERNEL); + + if (!line6pcm->buffer_out) { + dev_err(line6pcm->line6->ifcdev, + "cannot malloc playback buffer\n"); + return -ENOMEM; + } + ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); if (ret < 0) @@ -481,6 +491,11 @@ static int snd_line6_playback_hw_params(struct snd_pcm_substream *substream, /* hw_free playback callback */ static int snd_line6_playback_hw_free(struct snd_pcm_substream *substream) { + struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); + + line6_unlink_wait_clear_audio_out_urbs(line6pcm); + kfree(line6pcm->buffer_out); + line6pcm->buffer_out = NULL; return snd_pcm_lib_free_pages(substream); } From cff863871e748d072cae002fb13e692436b0200a Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Tue, 8 Nov 2011 20:40:26 +0100 Subject: [PATCH 010/365] Staging: line6: Use kmemdup rather than duplicating its implementation Use kmemdup rather than duplicating its implementation The semantic patch that makes this change is available in scripts/coccinelle/api/memdup.cocci. More information about semantic patching is available at http://coccinelle.lip6.fr/ Signed-off-by: Thomas Meyer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/line6/midi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/line6/midi.c b/drivers/staging/line6/midi.c index ed5577f25afe..7f1e90e14411 100644 --- a/drivers/staging/line6/midi.c +++ b/drivers/staging/line6/midi.c @@ -135,7 +135,7 @@ static int send_midi_async(struct usb_line6 *line6, unsigned char *data, line6_write_hexdump(line6, 'S', data, length); #endif - transfer_buffer = kmalloc(length, GFP_ATOMIC); + transfer_buffer = kmemdup(data, length, GFP_ATOMIC); if (transfer_buffer == NULL) { usb_free_urb(urb); @@ -143,7 +143,6 @@ static int send_midi_async(struct usb_line6 *line6, unsigned char *data, return -ENOMEM; } - memcpy(transfer_buffer, data, length); usb_fill_int_urb(urb, line6->usbdev, usb_sndbulkpipe(line6->usbdev, line6->ep_control_write), From eb7a6ca618c2348f5753866e74a287841479cf13 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sun, 23 Oct 2011 19:11:02 +0200 Subject: [PATCH 011/365] et131x: add static qualifiers. Signed-off-by: Francois Romieu Acked-by: Mark Einon Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/et131x.c | 119 ++++++++++++++++---------------- 1 file changed, 60 insertions(+), 59 deletions(-) diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c index 0c1c6ca8c379..686bda7d13e0 100644 --- a/drivers/staging/et131x/et131x.c +++ b/drivers/staging/et131x/et131x.c @@ -795,7 +795,7 @@ static int eeprom_read(struct et131x_adapter *adapter, u32 addr, u8 *pdata) return (status & LBCIF_STATUS_ACK_ERROR) ? -EIO : 0; } -int et131x_init_eeprom(struct et131x_adapter *adapter) +static int et131x_init_eeprom(struct et131x_adapter *adapter) { struct pci_dev *pdev = adapter->pdev; u8 eestatus; @@ -868,7 +868,7 @@ int et131x_init_eeprom(struct et131x_adapter *adapter) * et131x_rx_dma_enable - re-start of Rx_DMA on the ET1310. * @adapter: pointer to our adapter structure */ -void et131x_rx_dma_enable(struct et131x_adapter *adapter) +static void et131x_rx_dma_enable(struct et131x_adapter *adapter) { /* Setup the receive dma configuration register for normal operation */ u32 csr = 0x2000; /* FBR1 enable */ @@ -906,7 +906,7 @@ void et131x_rx_dma_enable(struct et131x_adapter *adapter) * et131x_rx_dma_disable - Stop of Rx_DMA on the ET1310 * @adapter: pointer to our adapter structure */ -void et131x_rx_dma_disable(struct et131x_adapter *adapter) +static void et131x_rx_dma_disable(struct et131x_adapter *adapter) { u32 csr; /* Setup the receive dma configuration register */ @@ -928,7 +928,7 @@ void et131x_rx_dma_disable(struct et131x_adapter *adapter) * * Mainly used after a return to the D0 (full-power) state from a lower state. */ -void et131x_tx_dma_enable(struct et131x_adapter *adapter) +static void et131x_tx_dma_enable(struct et131x_adapter *adapter) { /* Setup the transmit dma configuration register for normal * operation @@ -964,7 +964,7 @@ static inline void add_12bit(u32 *v, int n) * et1310_config_mac_regs1 - Initialize the first part of MAC regs * @adapter: pointer to our adapter structure */ -void et1310_config_mac_regs1(struct et131x_adapter *adapter) +static void et1310_config_mac_regs1(struct et131x_adapter *adapter) { struct mac_regs __iomem *macregs = &adapter->regs->mac; u32 station1; @@ -1024,7 +1024,7 @@ void et1310_config_mac_regs1(struct et131x_adapter *adapter) * et1310_config_mac_regs2 - Initialize the second part of MAC regs * @adapter: pointer to our adapter structure */ -void et1310_config_mac_regs2(struct et131x_adapter *adapter) +static void et1310_config_mac_regs2(struct et131x_adapter *adapter) { int32_t delay = 0; struct mac_regs __iomem *mac = &adapter->regs->mac; @@ -1105,7 +1105,7 @@ void et1310_config_mac_regs2(struct et131x_adapter *adapter) * * Returns 0 if the device is not in phy coma, 1 if it is in phy coma */ -int et1310_in_phy_coma(struct et131x_adapter *adapter) +static int et1310_in_phy_coma(struct et131x_adapter *adapter) { u32 pmcsr; @@ -1114,7 +1114,7 @@ int et1310_in_phy_coma(struct et131x_adapter *adapter) return ET_PM_PHY_SW_COMA & pmcsr ? 1 : 0; } -void et1310_setup_device_for_multicast(struct et131x_adapter *adapter) +static void et1310_setup_device_for_multicast(struct et131x_adapter *adapter) { struct rxmac_regs __iomem *rxmac = &adapter->regs->rxmac; uint32_t nIndex; @@ -1163,7 +1163,7 @@ void et1310_setup_device_for_multicast(struct et131x_adapter *adapter) } } -void et1310_setup_device_for_unicast(struct et131x_adapter *adapter) +static void et1310_setup_device_for_unicast(struct et131x_adapter *adapter) { struct rxmac_regs __iomem *rxmac = &adapter->regs->rxmac; u32 uni_pf1; @@ -1203,7 +1203,7 @@ void et1310_setup_device_for_unicast(struct et131x_adapter *adapter) } } -void et1310_config_rxmac_regs(struct et131x_adapter *adapter) +static void et1310_config_rxmac_regs(struct et131x_adapter *adapter) { struct rxmac_regs __iomem *rxmac = &adapter->regs->rxmac; struct phy_device *phydev = adapter->phydev; @@ -1334,7 +1334,7 @@ void et1310_config_rxmac_regs(struct et131x_adapter *adapter) writel(0x9, &rxmac->ctrl); } -void et1310_config_txmac_regs(struct et131x_adapter *adapter) +static void et1310_config_txmac_regs(struct et131x_adapter *adapter) { struct txmac_regs __iomem *txmac = &adapter->regs->txmac; @@ -1348,7 +1348,7 @@ void et1310_config_txmac_regs(struct et131x_adapter *adapter) writel(0x40, &txmac->cf_param); } -void et1310_config_macstat_regs(struct et131x_adapter *adapter) +static void et1310_config_macstat_regs(struct et131x_adapter *adapter) { struct macstat_regs __iomem *macstat = &adapter->regs->macstat; @@ -1422,7 +1422,7 @@ void et1310_config_macstat_regs(struct et131x_adapter *adapter) * * Returns 0 on success, errno on failure (as defined in errno.h) */ -int et131x_phy_mii_read(struct et131x_adapter *adapter, u8 addr, +static int et131x_phy_mii_read(struct et131x_adapter *adapter, u8 addr, u8 reg, u16 *value) { struct mac_regs __iomem *mac = &adapter->regs->mac; @@ -1478,7 +1478,7 @@ int et131x_phy_mii_read(struct et131x_adapter *adapter, u8 addr, return status; } -int et131x_mii_read(struct et131x_adapter *adapter, u8 reg, u16 *value) +static int et131x_mii_read(struct et131x_adapter *adapter, u8 reg, u16 *value) { struct phy_device *phydev = adapter->phydev; @@ -1498,7 +1498,7 @@ int et131x_mii_read(struct et131x_adapter *adapter, u8 reg, u16 *value) * * Return 0 on success, errno on failure (as defined in errno.h) */ -int et131x_mii_write(struct et131x_adapter *adapter, u8 reg, u16 value) +static int et131x_mii_write(struct et131x_adapter *adapter, u8 reg, u16 value) { struct mac_regs __iomem *mac = &adapter->regs->mac; struct phy_device *phydev = adapter->phydev; @@ -1564,8 +1564,9 @@ int et131x_mii_write(struct et131x_adapter *adapter, u8 reg, u16 value) } /* Still used from _mac for BIT_READ */ -void et1310_phy_access_mii_bit(struct et131x_adapter *adapter, u16 action, - u16 regnum, u16 bitnum, u8 *value) +static void et1310_phy_access_mii_bit(struct et131x_adapter *adapter, + u16 action, u16 regnum, u16 bitnum, + u8 *value) { u16 reg; u16 mask = 0x0001 << bitnum; @@ -1591,7 +1592,7 @@ void et1310_phy_access_mii_bit(struct et131x_adapter *adapter, u16 action, } } -void et1310_config_flow_control(struct et131x_adapter *adapter) +static void et1310_config_flow_control(struct et131x_adapter *adapter) { struct phy_device *phydev = adapter->phydev; @@ -1632,7 +1633,7 @@ void et1310_config_flow_control(struct et131x_adapter *adapter) * et1310_update_macstat_host_counters - Update the local copy of the statistics * @adapter: pointer to the adapter structure */ -void et1310_update_macstat_host_counters(struct et131x_adapter *adapter) +static void et1310_update_macstat_host_counters(struct et131x_adapter *adapter) { struct ce_stats *stats = &adapter->stats; struct macstat_regs __iomem *macstat = @@ -1664,7 +1665,7 @@ void et1310_update_macstat_host_counters(struct et131x_adapter *adapter) * the statistics held in the adapter structure, checking the "wrap" * bit for each counter. */ -void et1310_handle_macstat_interrupt(struct et131x_adapter *adapter) +static void et1310_handle_macstat_interrupt(struct et131x_adapter *adapter) { u32 carry_reg1; u32 carry_reg2; @@ -1716,7 +1717,7 @@ void et1310_handle_macstat_interrupt(struct et131x_adapter *adapter) /* PHY functions */ -int et131x_mdio_read(struct mii_bus *bus, int phy_addr, int reg) +static int et131x_mdio_read(struct mii_bus *bus, int phy_addr, int reg) { struct net_device *netdev = bus->priv; struct et131x_adapter *adapter = netdev_priv(netdev); @@ -1731,7 +1732,7 @@ int et131x_mdio_read(struct mii_bus *bus, int phy_addr, int reg) return value; } -int et131x_mdio_write(struct mii_bus *bus, int phy_addr, int reg, u16 value) +static int et131x_mdio_write(struct mii_bus *bus, int phy_addr, int reg, u16 value) { struct net_device *netdev = bus->priv; struct et131x_adapter *adapter = netdev_priv(netdev); @@ -1739,7 +1740,7 @@ int et131x_mdio_write(struct mii_bus *bus, int phy_addr, int reg, u16 value) return et131x_mii_write(adapter, reg, value); } -int et131x_mdio_reset(struct mii_bus *bus) +static int et131x_mdio_reset(struct mii_bus *bus) { struct net_device *netdev = bus->priv; struct et131x_adapter *adapter = netdev_priv(netdev); @@ -1759,7 +1760,7 @@ int et131x_mdio_reset(struct mii_bus *bus) * Can't you see that this code processed * Phy power, phy power.. */ -void et1310_phy_power_down(struct et131x_adapter *adapter, bool down) +static void et1310_phy_power_down(struct et131x_adapter *adapter, bool down) { u16 data; @@ -1775,7 +1776,7 @@ void et1310_phy_power_down(struct et131x_adapter *adapter, bool down) * @adapter: pointer to our private adapter structure * */ -void et131x_xcvr_init(struct et131x_adapter *adapter) +static void et131x_xcvr_init(struct et131x_adapter *adapter) { u16 imr; u16 isr; @@ -1822,7 +1823,7 @@ void et131x_xcvr_init(struct et131x_adapter *adapter) * * Used to configure the global registers on the JAGCore */ -void et131x_configure_global_regs(struct et131x_adapter *adapter) +static void et131x_configure_global_regs(struct et131x_adapter *adapter) { struct global_regs __iomem *regs = &adapter->regs->global; @@ -1869,7 +1870,7 @@ void et131x_configure_global_regs(struct et131x_adapter *adapter) * et131x_config_rx_dma_regs - Start of Rx_DMA init sequence * @adapter: pointer to our adapter structure */ -void et131x_config_rx_dma_regs(struct et131x_adapter *adapter) +static void et131x_config_rx_dma_regs(struct et131x_adapter *adapter) { struct rxdma_regs __iomem *rx_dma = &adapter->regs->rxdma; struct rx_ring *rx_local = &adapter->rx_ring; @@ -1987,7 +1988,7 @@ void et131x_config_rx_dma_regs(struct et131x_adapter *adapter) * Configure the transmit engine with the ring buffers we have created * and prepare it for use. */ -void et131x_config_tx_dma_regs(struct et131x_adapter *adapter) +static void et131x_config_tx_dma_regs(struct et131x_adapter *adapter) { struct txdma_regs __iomem *txdma = &adapter->regs->txdma; @@ -2017,7 +2018,7 @@ void et131x_config_tx_dma_regs(struct et131x_adapter *adapter) * * Returns 0 on success, errno on failure (as defined in errno.h) */ -void et131x_adapter_setup(struct et131x_adapter *adapter) +static void et131x_adapter_setup(struct et131x_adapter *adapter) { /* Configure the JAGCore */ et131x_configure_global_regs(adapter); @@ -2044,7 +2045,7 @@ void et131x_adapter_setup(struct et131x_adapter *adapter) * et131x_soft_reset - Issue a soft reset to the hardware, complete for ET1310 * @adapter: pointer to our private adapter structure */ -void et131x_soft_reset(struct et131x_adapter *adapter) +static void et131x_soft_reset(struct et131x_adapter *adapter) { /* Disable MAC Core */ writel(0xc00f0000, &adapter->regs->mac.cfg1); @@ -2062,7 +2063,7 @@ void et131x_soft_reset(struct et131x_adapter *adapter) * Enable the appropriate interrupts on the ET131x according to our * configuration */ -void et131x_enable_interrupts(struct et131x_adapter *adapter) +static void et131x_enable_interrupts(struct et131x_adapter *adapter) { u32 mask; @@ -2082,7 +2083,7 @@ void et131x_enable_interrupts(struct et131x_adapter *adapter) * * Block all interrupts from the et131x device at the device itself */ -void et131x_disable_interrupts(struct et131x_adapter *adapter) +static void et131x_disable_interrupts(struct et131x_adapter *adapter) { /* Disable all global interrupts */ writel(INT_MASK_DISABLE, &adapter->regs->global.int_mask); @@ -2092,7 +2093,7 @@ void et131x_disable_interrupts(struct et131x_adapter *adapter) * et131x_tx_dma_disable - Stop of Tx_DMA on the ET1310 * @adapter: pointer to our adapter structure */ -void et131x_tx_dma_disable(struct et131x_adapter *adapter) +static void et131x_tx_dma_disable(struct et131x_adapter *adapter) { /* Setup the tramsmit dma configuration register */ writel(ET_TXDMA_CSR_HALT|ET_TXDMA_SNGL_EPKT, @@ -2103,7 +2104,7 @@ void et131x_tx_dma_disable(struct et131x_adapter *adapter) * et131x_enable_txrx - Enable tx/rx queues * @netdev: device to be enabled */ -void et131x_enable_txrx(struct net_device *netdev) +static void et131x_enable_txrx(struct net_device *netdev) { struct et131x_adapter *adapter = netdev_priv(netdev); @@ -2123,7 +2124,7 @@ void et131x_enable_txrx(struct net_device *netdev) * et131x_disable_txrx - Disable tx/rx queues * @netdev: device to be disabled */ -void et131x_disable_txrx(struct net_device *netdev) +static void et131x_disable_txrx(struct net_device *netdev) { struct et131x_adapter *adapter = netdev_priv(netdev); @@ -2142,7 +2143,7 @@ void et131x_disable_txrx(struct net_device *netdev) * et131x_init_send - Initialize send data structures * @adapter: pointer to our private adapter structure */ -void et131x_init_send(struct et131x_adapter *adapter) +static void et131x_init_send(struct et131x_adapter *adapter) { struct tcb *tcb; u32 ct; @@ -2192,7 +2193,7 @@ void et131x_init_send(struct et131x_adapter *adapter) * indicating linkup status, call the MPDisablePhyComa routine to * restore JAGCore and gigE PHY */ -void et1310_enable_phy_coma(struct et131x_adapter *adapter) +static void et1310_enable_phy_coma(struct et131x_adapter *adapter) { unsigned long flags; u32 pmcsr; @@ -2231,7 +2232,7 @@ void et1310_enable_phy_coma(struct et131x_adapter *adapter) * et1310_disable_phy_coma - Disable the Phy Coma Mode * @adapter: pointer to our adapter structure */ -void et1310_disable_phy_coma(struct et131x_adapter *adapter) +static void et1310_disable_phy_coma(struct et131x_adapter *adapter) { u32 pmcsr; @@ -2296,7 +2297,7 @@ static inline u32 bump_free_buff_ring(u32 *free_buff_ring, u32 limit) * @offset: pointer to the offset variable * @mask: correct mask */ -void et131x_align_allocated_memory(struct et131x_adapter *adapter, +static void et131x_align_allocated_memory(struct et131x_adapter *adapter, uint64_t *phys_addr, uint64_t *offset, uint64_t mask) { @@ -2325,7 +2326,7 @@ void et131x_align_allocated_memory(struct et131x_adapter *adapter, * Allocates Free buffer ring 1 for sure, free buffer ring 0 if required, * and the Packet Status Ring. */ -int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) +static int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) { u32 i, j; u32 bufsize; @@ -2629,7 +2630,7 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) * et131x_rx_dma_memory_free - Free all memory allocated within this module. * @adapter: pointer to our private adapter structure */ -void et131x_rx_dma_memory_free(struct et131x_adapter *adapter) +static void et131x_rx_dma_memory_free(struct et131x_adapter *adapter) { u32 index; u32 bufsize; @@ -2774,7 +2775,7 @@ void et131x_rx_dma_memory_free(struct et131x_adapter *adapter) * * Returns 0 on success and errno on failure (as defined in errno.h) */ -int et131x_init_recv(struct et131x_adapter *adapter) +static int et131x_init_recv(struct et131x_adapter *adapter) { int status = -ENOMEM; struct rfd *rfd = NULL; @@ -2824,7 +2825,7 @@ int et131x_init_recv(struct et131x_adapter *adapter) * et131x_set_rx_dma_timer - Set the heartbeat timer according to line rate. * @adapter: pointer to our adapter structure */ -void et131x_set_rx_dma_timer(struct et131x_adapter *adapter) +static void et131x_set_rx_dma_timer(struct et131x_adapter *adapter) { struct phy_device *phydev = adapter->phydev; @@ -3139,7 +3140,7 @@ static struct rfd *nic_rx_pkts(struct et131x_adapter *adapter) * * Assumption, Rcv spinlock has been acquired. */ -void et131x_handle_recv_interrupt(struct et131x_adapter *adapter) +static void et131x_handle_recv_interrupt(struct et131x_adapter *adapter) { struct rfd *rfd = NULL; u32 count = 0; @@ -3202,7 +3203,7 @@ void et131x_handle_recv_interrupt(struct et131x_adapter *adapter) * memory. The device will update the "status" in memory each time it xmits a * packet. */ -int et131x_tx_dma_memory_alloc(struct et131x_adapter *adapter) +static int et131x_tx_dma_memory_alloc(struct et131x_adapter *adapter) { int desc_size = 0; struct tx_ring *tx_ring = &adapter->tx_ring; @@ -3256,7 +3257,7 @@ int et131x_tx_dma_memory_alloc(struct et131x_adapter *adapter) * * Returns 0 on success and errno on failure (as defined in errno.h). */ -void et131x_tx_dma_memory_free(struct et131x_adapter *adapter) +static void et131x_tx_dma_memory_free(struct et131x_adapter *adapter) { int desc_size = 0; @@ -3578,7 +3579,7 @@ static int send_packet(struct sk_buff *skb, struct et131x_adapter *adapter) * * Return 0 in almost all cases; non-zero value in extreme hard failure only */ -int et131x_send_packets(struct sk_buff *skb, struct net_device *netdev) +static int et131x_send_packets(struct sk_buff *skb, struct net_device *netdev) { int status = 0; struct et131x_adapter *adapter = netdev_priv(netdev); @@ -3696,7 +3697,7 @@ static inline void free_send_packet(struct et131x_adapter *adapter, * * Assumption - Send spinlock has been acquired */ -void et131x_free_busy_send_packets(struct et131x_adapter *adapter) +static void et131x_free_busy_send_packets(struct et131x_adapter *adapter) { struct tcb *tcb; unsigned long flags; @@ -3743,7 +3744,7 @@ void et131x_free_busy_send_packets(struct et131x_adapter *adapter) * * Assumption - Send spinlock has been acquired */ -void et131x_handle_send_interrupt(struct et131x_adapter *adapter) +static void et131x_handle_send_interrupt(struct et131x_adapter *adapter) { unsigned long flags; u32 serviced; @@ -3965,7 +3966,7 @@ static struct ethtool_ops et131x_ethtool_ops = { .get_link = ethtool_op_get_link, }; -void et131x_set_ethtool_ops(struct net_device *netdev) +static void et131x_set_ethtool_ops(struct net_device *netdev) { SET_ETHTOOL_OPS(netdev, &et131x_ethtool_ops); } @@ -3976,7 +3977,7 @@ void et131x_set_ethtool_ops(struct net_device *netdev) * et131x_hwaddr_init - set up the MAC Address on the ET1310 * @adapter: pointer to our private adapter structure */ -void et131x_hwaddr_init(struct et131x_adapter *adapter) +static void et131x_hwaddr_init(struct et131x_adapter *adapter) { /* If have our default mac from init and no mac address from * EEPROM then we need to generate the last octet and set it on the @@ -4110,7 +4111,7 @@ static int et131x_pci_init(struct et131x_adapter *adapter, * The routine called when the error timer expires, to track the number of * recurring errors. */ -void et131x_error_timer_handler(unsigned long data) +static void et131x_error_timer_handler(unsigned long data) { struct et131x_adapter *adapter = (struct et131x_adapter *) data; struct phy_device *phydev = adapter->phydev; @@ -4153,7 +4154,7 @@ void et131x_error_timer_handler(unsigned long data) * * Allocate all the memory blocks for send, receive and others. */ -int et131x_adapter_memory_alloc(struct et131x_adapter *adapter) +static int et131x_adapter_memory_alloc(struct et131x_adapter *adapter) { int status; @@ -4188,7 +4189,7 @@ int et131x_adapter_memory_alloc(struct et131x_adapter *adapter) * et131x_adapter_memory_free - Free all memory allocated for use by Tx & Rx * @adapter: pointer to our private adapter structure */ -void et131x_adapter_memory_free(struct et131x_adapter *adapter) +static void et131x_adapter_memory_free(struct et131x_adapter *adapter) { /* Free DMA memory */ et131x_tx_dma_memory_free(adapter); @@ -4417,7 +4418,7 @@ static void __devexit et131x_pci_remove(struct pci_dev *pdev) * et131x_up - Bring up a device for use. * @netdev: device to be opened */ -void et131x_up(struct net_device *netdev) +static void et131x_up(struct net_device *netdev) { struct et131x_adapter *adapter = netdev_priv(netdev); @@ -4429,7 +4430,7 @@ void et131x_up(struct net_device *netdev) * et131x_down - Bring down the device * @netdev: device to be broght down */ -void et131x_down(struct net_device *netdev) +static void et131x_down(struct net_device *netdev) { struct et131x_adapter *adapter = netdev_priv(netdev); @@ -4573,7 +4574,7 @@ out: * scheduled to run in a deferred context by the ISR. This is where the ISR's * work actually gets done. */ -void et131x_isr_handler(struct work_struct *work) +static void et131x_isr_handler(struct work_struct *work) { struct et131x_adapter *adapter = container_of(work, struct et131x_adapter, task); @@ -4829,7 +4830,7 @@ static struct net_device_stats *et131x_stats(struct net_device *netdev) * * Returns 0 on success, errno on failure (as defined in errno.h) */ -int et131x_open(struct net_device *netdev) +static int et131x_open(struct net_device *netdev) { int result = 0; struct et131x_adapter *adapter = netdev_priv(netdev); @@ -4863,7 +4864,7 @@ int et131x_open(struct net_device *netdev) * * Returns 0 on success, errno on failure (as defined in errno.h) */ -int et131x_close(struct net_device *netdev) +static int et131x_close(struct net_device *netdev) { struct et131x_adapter *adapter = netdev_priv(netdev); From 834d0ee317bcc96ab547aaa711545843966da9b6 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sun, 23 Oct 2011 19:11:19 +0200 Subject: [PATCH 012/365] et131x: uintxy_t removal. Signed-off-by: Francois Romieu Acked-by: Mark Einon Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/et131x.c | 53 +++++++++++++++++---------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c index 686bda7d13e0..35270a82923a 100644 --- a/drivers/staging/et131x/et131x.c +++ b/drivers/staging/et131x/et131x.c @@ -303,8 +303,8 @@ struct fbr_lookup { dma_addr_t ring_physaddr; void *mem_virtaddrs[MAX_DESC_PER_RING_RX / FBR_CHUNKS]; dma_addr_t mem_physaddrs[MAX_DESC_PER_RING_RX / FBR_CHUNKS]; - uint64_t real_physaddr; - uint64_t offset; + dma_addr_t real_physaddr; + u32 offset; u32 local_full; u32 num_entries; u32 buffsize; @@ -1117,12 +1117,10 @@ static int et1310_in_phy_coma(struct et131x_adapter *adapter) static void et1310_setup_device_for_multicast(struct et131x_adapter *adapter) { struct rxmac_regs __iomem *rxmac = &adapter->regs->rxmac; - uint32_t nIndex; - uint32_t result; - uint32_t hash1 = 0; - uint32_t hash2 = 0; - uint32_t hash3 = 0; - uint32_t hash4 = 0; + u32 hash1 = 0; + u32 hash2 = 0; + u32 hash3 = 0; + u32 hash4 = 0; u32 pm_csr; /* If ET131X_PACKET_TYPE_MULTICAST is specified, then we provision @@ -1131,10 +1129,13 @@ static void et1310_setup_device_for_multicast(struct et131x_adapter *adapter) * driver. */ if (adapter->packet_filter & ET131X_PACKET_TYPE_MULTICAST) { + int i; + /* Loop through our multicast array and set up the device */ - for (nIndex = 0; nIndex < adapter->multicast_addr_count; - nIndex++) { - result = ether_crc(6, adapter->multicast_list[nIndex]); + for (i = 0; i < adapter->multicast_addr_count; i++) { + u32 result; + + result = ether_crc(6, adapter->multicast_list[i]); result = (result & 0x3F800000) >> 23; @@ -1925,9 +1926,10 @@ static void et131x_config_rx_dma_regs(struct et131x_adapter *adapter) /* Set the address and parameters of Free buffer ring 1 (and 0 if * required) into the 1310's registers */ - writel((u32) (rx_local->fbr[0]->real_physaddr >> 32), + writel(((u64) rx_local->fbr[0]->real_physaddr) >> 32, &rx_dma->fbr1_base_hi); - writel((u32) rx_local->fbr[0]->real_physaddr, &rx_dma->fbr1_base_lo); + writel(((u64) rx_local->fbr[0]->real_physaddr) & DMA_BIT_MASK(32), + &rx_dma->fbr1_base_lo); writel(rx_local->fbr[0]->num_entries - 1, &rx_dma->fbr1_num_des); writel(ET_DMA10_WRAP, &rx_dma->fbr1_full_offset); @@ -1949,9 +1951,10 @@ static void et131x_config_rx_dma_regs(struct et131x_adapter *adapter) fbr_entry++; } - writel((u32) (rx_local->fbr[1]->real_physaddr >> 32), + writel(((u64) rx_local->fbr[1]->real_physaddr) >> 32, &rx_dma->fbr0_base_hi); - writel((u32) rx_local->fbr[1]->real_physaddr, &rx_dma->fbr0_base_lo); + writel(((u64) rx_local->fbr[1]->real_physaddr) & DMA_BIT_MASK(32), + &rx_dma->fbr0_base_lo); writel(rx_local->fbr[1]->num_entries - 1, &rx_dma->fbr0_num_des); writel(ET_DMA10_WRAP, &rx_dma->fbr0_full_offset); @@ -2298,15 +2301,13 @@ static inline u32 bump_free_buff_ring(u32 *free_buff_ring, u32 limit) * @mask: correct mask */ static void et131x_align_allocated_memory(struct et131x_adapter *adapter, - uint64_t *phys_addr, - uint64_t *offset, uint64_t mask) + dma_addr_t *phys_addr, u32 *offset, + u32 mask) { - uint64_t new_addr; + dma_addr_t new_addr = *phys_addr & ~mask; *offset = 0; - new_addr = *phys_addr & ~mask; - if (new_addr != *phys_addr) { /* Move to next aligned block */ new_addr += mask + 1; @@ -2455,8 +2456,8 @@ static int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) rx_ring->fbr[1]->offset); #endif for (i = 0; i < (rx_ring->fbr[0]->num_entries / FBR_CHUNKS); i++) { - u64 fbr1_offset; - u64 fbr1_tmp_physaddr; + dma_addr_t fbr1_tmp_physaddr; + u32 fbr1_offset; u32 fbr1_align; /* This code allocates an area of memory big enough for N @@ -2521,8 +2522,8 @@ static int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter) #ifdef USE_FBR0 /* Same for FBR0 (if in use) */ for (i = 0; i < (rx_ring->fbr[1]->num_entries / FBR_CHUNKS); i++) { - u64 fbr0_offset; - u64 fbr0_tmp_physaddr; + dma_addr_t fbr0_tmp_physaddr; + u32 fbr0_offset; fbr_chunksize = ((FBR_CHUNKS + 1) * rx_ring->fbr[1]->buffsize) - 1; @@ -4906,8 +4907,8 @@ static int et131x_ioctl(struct net_device *netdev, struct ifreq *reqbuf, */ static int et131x_set_packet_filter(struct et131x_adapter *adapter) { + int filter = adapter->packet_filter; int status = 0; - uint32_t filter = adapter->packet_filter; u32 ctrl; u32 pf_ctrl; @@ -4969,7 +4970,7 @@ static int et131x_set_packet_filter(struct et131x_adapter *adapter) static void et131x_multicast(struct net_device *netdev) { struct et131x_adapter *adapter = netdev_priv(netdev); - uint32_t packet_filter = 0; + int packet_filter; unsigned long flags; struct netdev_hw_addr *ha; int i; From fa9f0a657e1474d7b2067fc22bd9a5e94878a40c Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sun, 23 Oct 2011 19:11:35 +0200 Subject: [PATCH 013/365] et131x: fix error paths in et131x_pci_setup. Wrong status code and unbalanced phy_connect. Signed-off-by: Francois Romieu Acked-by: Mark Einon Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/et131x.c | 99 +++++++++++++-------------------- 1 file changed, 38 insertions(+), 61 deletions(-) diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c index 35270a82923a..debc07c52e70 100644 --- a/drivers/staging/et131x/et131x.c +++ b/drivers/staging/et131x/et131x.c @@ -4402,6 +4402,7 @@ static void __devexit et131x_pci_remove(struct pci_dev *pdev) struct et131x_adapter *adapter = netdev_priv(netdev); unregister_netdev(netdev); + phy_disconnect(adapter->phydev); mdiobus_unregister(adapter->mii_bus); kfree(adapter->mii_bus->irq); mdiobus_free(adapter->mii_bus); @@ -5250,40 +5251,6 @@ static const struct net_device_ops et131x_netdev_ops = { .ndo_do_ioctl = et131x_ioctl, }; -/** - * et131x_device_alloc - * - * Returns pointer to the allocated and initialized net_device struct for - * this device. - * - * Create instances of net_device and wl_private for the new adapter and - * register the device's entry points in the net_device structure. - */ -struct net_device *et131x_device_alloc(void) -{ - struct net_device *netdev; - - /* Alloc net_device and adapter structs */ - netdev = alloc_etherdev(sizeof(struct et131x_adapter)); - - if (!netdev) { - printk(KERN_ERR "et131x: Alloc of net_device struct failed\n"); - return NULL; - } - - /* - * Setup the function registration table (and other data) for a - * net_device - */ - netdev->watchdog_timeo = ET131X_TX_TIMEOUT; - netdev->netdev_ops = &et131x_netdev_ops; - - /* Poll? */ - /* netdev->poll = &et131x_poll; */ - /* netdev->poll_controller = &et131x_poll_controller; */ - return netdev; -} - /** * et131x_pci_setup - Perform device initialization * @pdev: a pointer to the device's pci_dev structure @@ -5299,24 +5266,26 @@ struct net_device *et131x_device_alloc(void) static int __devinit et131x_pci_setup(struct pci_dev *pdev, const struct pci_device_id *ent) { - int result; struct net_device *netdev; struct et131x_adapter *adapter; + int rc; int ii; - result = pci_enable_device(pdev); - if (result) { + rc = pci_enable_device(pdev); + if (rc < 0) { dev_err(&pdev->dev, "pci_enable_device() failed\n"); - goto err_out; + goto out; } /* Perform some basic PCI checks */ if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { dev_err(&pdev->dev, "Can't find PCI device's base address\n"); + rc = -ENODEV; goto err_disable; } - if (pci_request_regions(pdev, DRIVER_NAME)) { + rc = pci_request_regions(pdev, DRIVER_NAME); + if (rc < 0) { dev_err(&pdev->dev, "Can't get PCI resources\n"); goto err_disable; } @@ -5325,46 +5294,50 @@ static int __devinit et131x_pci_setup(struct pci_dev *pdev, /* Check the DMA addressing support of this device */ if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) { - result = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); - if (result) { + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); + if (rc < 0) { dev_err(&pdev->dev, "Unable to obtain 64 bit DMA for consistent allocations\n"); goto err_release_res; } } else if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) { - result = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (result) { + rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); + if (rc < 0) { dev_err(&pdev->dev, "Unable to obtain 32 bit DMA for consistent allocations\n"); goto err_release_res; } } else { dev_err(&pdev->dev, "No usable DMA addressing method\n"); - result = -EIO; + rc = -EIO; goto err_release_res; } /* Allocate netdev and private adapter structs */ - netdev = et131x_device_alloc(); + netdev = alloc_etherdev(sizeof(struct et131x_adapter)); if (!netdev) { dev_err(&pdev->dev, "Couldn't alloc netdev struct\n"); - result = -ENOMEM; + rc = -ENOMEM; goto err_release_res; } + netdev->watchdog_timeo = ET131X_TX_TIMEOUT; + netdev->netdev_ops = &et131x_netdev_ops; + SET_NETDEV_DEV(netdev, &pdev->dev); et131x_set_ethtool_ops(netdev); adapter = et131x_adapter_init(netdev, pdev); - /* Initialise the PCI setup for the device */ - et131x_pci_init(adapter, pdev); + rc = et131x_pci_init(adapter, pdev); + if (rc < 0) + goto err_free_dev; /* Map the bus-relative registers to system virtual memory */ adapter->regs = pci_ioremap_bar(pdev, 0); if (!adapter->regs) { dev_err(&pdev->dev, "Cannot map device registers\n"); - result = -ENOMEM; + rc = -ENOMEM; goto err_free_dev; } @@ -5378,8 +5351,8 @@ static int __devinit et131x_pci_setup(struct pci_dev *pdev, et131x_disable_interrupts(adapter); /* Allocate DMA memory */ - result = et131x_adapter_memory_alloc(adapter); - if (result) { + rc = et131x_adapter_memory_alloc(adapter); + if (rc < 0) { dev_err(&pdev->dev, "Could not alloc adapater memory (DMA)\n"); goto err_iounmap; } @@ -5397,6 +5370,8 @@ static int __devinit et131x_pci_setup(struct pci_dev *pdev, adapter->boot_coma = 0; et1310_disable_phy_coma(adapter); + rc = -ENOMEM; + /* Setup the mii_bus struct */ adapter->mii_bus = mdiobus_alloc(); if (!adapter->mii_bus) { @@ -5420,13 +5395,14 @@ static int __devinit et131x_pci_setup(struct pci_dev *pdev, for (ii = 0; ii < PHY_MAX_ADDR; ii++) adapter->mii_bus->irq[ii] = PHY_POLL; - if (mdiobus_register(adapter->mii_bus)) { + rc = mdiobus_register(adapter->mii_bus); + if (rc < 0) { dev_err(&pdev->dev, "failed to register MII bus\n"); - mdiobus_free(adapter->mii_bus); goto err_mdio_free_irq; } - if (et131x_mii_probe(netdev)) { + rc = et131x_mii_probe(netdev); + if (rc < 0) { dev_err(&pdev->dev, "failed to probe MII bus\n"); goto err_mdio_unregister; } @@ -5442,10 +5418,10 @@ static int __devinit et131x_pci_setup(struct pci_dev *pdev, */ /* Register the net_device struct with the Linux network layer */ - result = register_netdev(netdev); - if (result != 0) { + rc = register_netdev(netdev); + if (rc < 0) { dev_err(&pdev->dev, "register_netdev() failed\n"); - goto err_mdio_unregister; + goto err_phy_disconnect; } /* Register the net_device struct with the PCI subsystem. Save a copy @@ -5454,9 +5430,11 @@ static int __devinit et131x_pci_setup(struct pci_dev *pdev, */ pci_set_drvdata(pdev, netdev); pci_save_state(adapter->pdev); +out: + return rc; - return result; - +err_phy_disconnect: + phy_disconnect(adapter->phydev); err_mdio_unregister: mdiobus_unregister(adapter->mii_bus); err_mdio_free_irq: @@ -5474,8 +5452,7 @@ err_release_res: pci_release_regions(pdev); err_disable: pci_disable_device(pdev); -err_out: - return result; + goto out; } static DEFINE_PCI_DEVICE_TABLE(et131x_pci_table) = { From c3abb6871e972f44103401c8430b472212a64417 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sun, 23 Oct 2011 19:11:50 +0200 Subject: [PATCH 014/365] et131x: remove extraneous pci_save_state. pci_{save, restore}_state are balanced in .suspend and .resume. They are not used anywhere else in the driver. Signed-off-by: Francois Romieu Acked-by: Mark Einon Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/et131x.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c index debc07c52e70..063955d52733 100644 --- a/drivers/staging/et131x/et131x.c +++ b/drivers/staging/et131x/et131x.c @@ -5429,7 +5429,6 @@ static int __devinit et131x_pci_setup(struct pci_dev *pdev, * been initialized, just in case it needs to be quickly restored. */ pci_set_drvdata(pdev, netdev); - pci_save_state(adapter->pdev); out: return rc; From 5f3eb881a95b25991105c9263fdcea87d0e5f5ef Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sun, 23 Oct 2011 19:12:01 +0200 Subject: [PATCH 015/365] et131x: kiss netdev.{base_addr, irq} goodbye. Signed-off-by: Francois Romieu Acked-by: Mark Einon Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/et131x.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c index 063955d52733..6bcdd77401f8 100644 --- a/drivers/staging/et131x/et131x.c +++ b/drivers/staging/et131x/et131x.c @@ -4366,10 +4366,6 @@ static struct et131x_adapter *et131x_adapter_init(struct net_device *netdev, adapter->pdev = pci_dev_get(pdev); adapter->netdev = netdev; - /* Do the same for the netdev struct */ - netdev->irq = pdev->irq; - netdev->base_addr = pci_resource_start(pdev, 0); - /* Initialize spinlocks here */ spin_lock_init(&adapter->lock); spin_lock_init(&adapter->tcb_send_qlock); @@ -4834,8 +4830,10 @@ static struct net_device_stats *et131x_stats(struct net_device *netdev) */ static int et131x_open(struct net_device *netdev) { - int result = 0; struct et131x_adapter *adapter = netdev_priv(netdev); + struct pci_dev *pdev = adapter->pdev; + unsigned int irq = pdev->irq; + int result; /* Start the timer to track NIC errors */ init_timer(&adapter->error_timer); @@ -4844,12 +4842,9 @@ static int et131x_open(struct net_device *netdev) adapter->error_timer.data = (unsigned long)adapter; add_timer(&adapter->error_timer); - /* Register our IRQ */ - result = request_irq(netdev->irq, et131x_isr, IRQF_SHARED, - netdev->name, netdev); + result = request_irq(irq, et131x_isr, IRQF_SHARED, netdev->name, netdev); if (result) { - dev_err(&adapter->pdev->dev, "could not register IRQ %d\n", - netdev->irq); + dev_err(&pdev->dev, "could not register IRQ %d\n", irq); return result; } @@ -4873,7 +4868,7 @@ static int et131x_close(struct net_device *netdev) et131x_down(netdev); adapter->flags &= ~fMP_ADAPTER_INTERRUPT_IN_USE; - free_irq(netdev->irq, netdev); + free_irq(adapter->pdev->irq, netdev); /* Stop the error timer */ return del_timer_sync(&adapter->error_timer); From d14e3d05f36960d98712cd8d5144bc21c9c76663 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sun, 23 Oct 2011 19:12:14 +0200 Subject: [PATCH 016/365] et131x: uncloak PCIe capabilities. FIXME: it should be possible to get rid of ET1310_PCI_L0L1LATENCY as well. Signed-off-by: Francois Romieu Acked-by: Mark Einon Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/et131x.c | 49 +++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c index 6bcdd77401f8..819ef10af858 100644 --- a/drivers/staging/et131x/et131x.c +++ b/drivers/staging/et131x/et131x.c @@ -155,7 +155,6 @@ MODULE_DESCRIPTION("10/100/1000 Base-T Ethernet Driver " #define fMP_ADAPTER_FAIL_SEND_MASK 0x3ff00000 /* Some offsets in PCI config space that are actually used. */ -#define ET1310_PCI_MAX_PYLD 0x4C #define ET1310_PCI_MAC_ADDRESS 0xA4 #define ET1310_PCI_EEPROM_STATUS 0xB2 #define ET1310_PCI_ACK_NACK 0xC0 @@ -4024,24 +4023,31 @@ static void et131x_hwaddr_init(struct et131x_adapter *adapter) static int et131x_pci_init(struct et131x_adapter *adapter, struct pci_dev *pdev) { - int i; - u8 max_payload; - u8 read_size_reg; + int cap = pci_pcie_cap(pdev); + u16 max_payload; + u16 ctl; + int i, rc; - if (et131x_init_eeprom(adapter) < 0) - return -EIO; + rc = et131x_init_eeprom(adapter); + if (rc < 0) + goto out; + if (!cap) { + dev_err(&pdev->dev, "Missing PCIe capabilities\n"); + goto err_out; + } + /* Let's set up the PORT LOGIC Register. First we need to know what * the max_payload_size is */ - if (pci_read_config_byte(pdev, ET1310_PCI_MAX_PYLD, &max_payload)) { + if (pci_read_config_word(pdev, cap + PCI_EXP_DEVCAP, &max_payload)) { dev_err(&pdev->dev, "Could not read PCI config space for Max Payload Size\n"); - return -EIO; + goto err_out; } /* Program the Ack/Nak latency and replay timers */ - max_payload &= 0x07; /* Only the lower 3 bits are valid */ + max_payload &= 0x07; if (max_payload < 2) { static const u16 acknak[2] = { 0x76, 0xD0 }; @@ -4051,13 +4057,13 @@ static int et131x_pci_init(struct et131x_adapter *adapter, acknak[max_payload])) { dev_err(&pdev->dev, "Could not write PCI config space for ACK/NAK\n"); - return -EIO; + goto err_out; } if (pci_write_config_word(pdev, ET1310_PCI_REPLAY, replay[max_payload])) { dev_err(&pdev->dev, "Could not write PCI config space for Replay Timer\n"); - return -EIO; + goto err_out; } } @@ -4067,23 +4073,22 @@ static int et131x_pci_init(struct et131x_adapter *adapter, if (pci_write_config_byte(pdev, ET1310_PCI_L0L1LATENCY, 0x11)) { dev_err(&pdev->dev, "Could not write PCI config space for Latency Timers\n"); - return -EIO; + goto err_out; } /* Change the max read size to 2k */ - if (pci_read_config_byte(pdev, 0x51, &read_size_reg)) { + if (pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl)) { dev_err(&pdev->dev, "Could not read PCI config space for Max read size\n"); - return -EIO; + goto err_out; } - read_size_reg &= 0x8f; - read_size_reg |= 0x40; + ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | ( 0x04 << 12); - if (pci_write_config_byte(pdev, 0x51, read_size_reg)) { + if (pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl)) { dev_err(&pdev->dev, "Could not write PCI config space for Max read size\n"); - return -EIO; + goto err_out; } /* Get MAC address from config space if an eeprom exists, otherwise @@ -4098,11 +4103,15 @@ static int et131x_pci_init(struct et131x_adapter *adapter, if (pci_read_config_byte(pdev, ET1310_PCI_MAC_ADDRESS + i, adapter->rom_addr + i)) { dev_err(&pdev->dev, "Could not read PCI config space for MAC address\n"); - return -EIO; + goto err_out; } } memcpy(adapter->addr, adapter->rom_addr, ETH_ALEN); - return 0; +out: + return rc; +err_out: + rc = -EIO; + goto out; } /** From 54dbf04f91ec54621c6cd2dda58b7c77ca25cf1f Mon Sep 17 00:00:00 2001 From: Mark Einon Date: Sun, 13 Nov 2011 19:43:39 +0000 Subject: [PATCH 017/365] staging: et131x: Remove section comments Following the move to put the driver into one file, comments were added to identify which source file each set of functions originated from. These no longer made sense after functions were moved around to remove some forward declarations, so remove them. A function comment was previously not moved along with its function, now they are reunited. Signed-off-by: Mark Einon Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/et131x.c | 46 ++++++++------------------------- 1 file changed, 11 insertions(+), 35 deletions(-) diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c index 819ef10af858..7ae3e53f1d00 100644 --- a/drivers/staging/et131x/et131x.c +++ b/drivers/staging/et131x/et131x.c @@ -177,9 +177,7 @@ MODULE_DESCRIPTION("10/100/1000 Base-T Ethernet Driver " /* RX defines */ #define USE_FBR0 1 - #define FBR_CHUNKS 32 - #define MAX_DESC_PER_RING_RX 1024 /* number of RFDs - default and min */ @@ -194,7 +192,6 @@ MODULE_DESCRIPTION("10/100/1000 Base-T Ethernet Driver " #endif #define NIC_MIN_NUM_RFD 64 - #define NUM_PACKETS_HANDLED 256 #define ALCATEL_MULTICAST_PKT 0x01000000 @@ -426,7 +423,6 @@ struct tx_ring { int since_irq; }; -/* ADAPTER defines */ /* * Do not change these values: if changed, then change also in respective * TXdma and Rxdma engines @@ -575,8 +571,6 @@ struct et131x_adapter { struct net_device_stats net_stats; }; -/* EEPROM functions */ - static int eeprom_wait_ready(struct pci_dev *pdev, u32 *status) { u32 reg; @@ -946,19 +940,6 @@ static inline void add_12bit(u32 *v, int n) *v = INDEX12(*v + n) | (*v & ET_DMA12_WRAP); } -/** - * nic_rx_pkts - Checks the hardware for available packets - * @adapter: pointer to our adapter - * - * Returns rfd, a pointer to our MPRFD. - * - * Checks the hardware for available packets, using completion ring - * If packets are available, it gets an RFD from the recv_list, attaches - * the packet to it, puts the RFD in the RecvPendList, and also returns - * the pointer to the RFD. - */ -/* MAC functions */ - /** * et1310_config_mac_regs1 - Initialize the first part of MAC regs * @adapter: pointer to our adapter structure @@ -1715,8 +1696,6 @@ static void et1310_handle_macstat_interrupt(struct et131x_adapter *adapter) adapter->stats.tx_collisions += COUNTER_WRAP_12_BIT; } -/* PHY functions */ - static int et131x_mdio_read(struct mii_bus *bus, int phy_addr, int reg) { struct net_device *netdev = bus->priv; @@ -1864,8 +1843,6 @@ static void et131x_configure_global_regs(struct et131x_adapter *adapter) writel(0, ®s->watchdog_timer); } -/* PM functions */ - /** * et131x_config_rx_dma_regs - Start of Rx_DMA init sequence * @adapter: pointer to our adapter structure @@ -2272,8 +2249,6 @@ static void et1310_disable_phy_coma(struct et131x_adapter *adapter) et131x_enable_txrx(adapter->netdev); } -/* RX functions */ - static inline u32 bump_free_buff_ring(u32 *free_buff_ring, u32 limit) { u32 tmp_free_buff_ring = *free_buff_ring; @@ -2919,6 +2894,17 @@ static void nic_return_rfd(struct et131x_adapter *adapter, struct rfd *rfd) WARN_ON(rx_local->num_ready_recv > rx_local->num_rfd); } +/** + * nic_rx_pkts - Checks the hardware for available packets + * @adapter: pointer to our adapter + * + * Returns rfd, a pointer to our MPRFD. + * + * Checks the hardware for available packets, using completion ring + * If packets are available, it gets an RFD from the recv_list, attaches + * the packet to it, puts the RFD in the RecvPendList, and also returns + * the pointer to the RFD. + */ static struct rfd *nic_rx_pkts(struct et131x_adapter *adapter) { struct rx_ring *rx_local = &adapter->rx_ring; @@ -3189,8 +3175,6 @@ static void et131x_handle_recv_interrupt(struct et131x_adapter *adapter) adapter->rx_ring.unfinished_receives = false; } -/* TX functions */ - /** * et131x_tx_dma_memory_alloc * @adapter: pointer to our private adapter structure @@ -3799,8 +3783,6 @@ static void et131x_handle_send_interrupt(struct et131x_adapter *adapter) spin_unlock_irqrestore(&adapter->tcb_send_qlock, flags); } -/* ETHTOOL functions */ - static int et131x_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) { @@ -3971,8 +3953,6 @@ static void et131x_set_ethtool_ops(struct net_device *netdev) SET_ETHTOOL_OPS(netdev, &et131x_ethtool_ops); } -/* PCI functions */ - /** * et131x_hwaddr_init - set up the MAC Address on the ET1310 * @adapter: pointer to our private adapter structure @@ -4483,8 +4463,6 @@ static SIMPLE_DEV_PM_OPS(et131x_pm_ops, et131x_suspend, et131x_resume); #define ET131X_PM_OPS NULL #endif -/* ISR functions */ - /** * et131x_isr - The Interrupt Service Routine for the driver. * @irq: the IRQ on which the interrupt was received. @@ -4782,8 +4760,6 @@ static void et131x_isr_handler(struct work_struct *work) et131x_enable_interrupts(adapter); } -/* NETDEV functions */ - /** * et131x_stats - Return the current device statistics. * @netdev: device whose stats are being queried From 0775c98acfdaffd857656bc9a465ad4008e90a9c Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 23 Oct 2011 23:18:04 +0200 Subject: [PATCH 018/365] m68k/serial: Remove obsolete IRQ_FLG_* users The m68k core irq code stopped honoring these flags during the irq restructuring in 2006. Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/staging/serial/68360serial.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/serial/68360serial.c b/drivers/staging/serial/68360serial.c index 0a3e8787ed50..daf0b1d0dc28 100644 --- a/drivers/staging/serial/68360serial.c +++ b/drivers/staging/serial/68360serial.c @@ -2771,8 +2771,8 @@ static int __init rs_360_init(void) */ /* cpm_install_handler(IRQ_MACHSPEC | state->irq, rs_360_interrupt, info); */ /*request_irq(IRQ_MACHSPEC | state->irq, rs_360_interrupt, */ - request_irq(state->irq, rs_360_interrupt, - IRQ_FLG_LOCK, "ttyS", (void *)info); + request_irq(state->irq, rs_360_interrupt, 0, "ttyS", + (void *)info); /* Set up the baud rate generator. */ From 53b99be7647bc1d821a817c58d1504547ca0c75f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 26 Nov 2011 16:25:54 -0800 Subject: [PATCH 019/365] Staging: rtl8192u: remove api.c file It wasn't being used, and had a hacked-up export symbol table which wasn't very nice either. Reported-by: James Morris Cc: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/ieee80211/api.c | 244 ----------------------- 1 file changed, 244 deletions(-) delete mode 100644 drivers/staging/rtl8192u/ieee80211/api.c diff --git a/drivers/staging/rtl8192u/ieee80211/api.c b/drivers/staging/rtl8192u/ieee80211/api.c deleted file mode 100644 index 5f46e50e586e..000000000000 --- a/drivers/staging/rtl8192u/ieee80211/api.c +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Scatterlist Cryptographic API. - * - * Copyright (c) 2002 James Morris - * Copyright (c) 2002 David S. Miller (davem@redhat.com) - * - * Portions derived from Cryptoapi, by Alexander Kjeldaas - * and Nettle, by Niels M鰈ler. - * - * 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 "kmap_types.h" - -#include -#include -//#include -#include "rtl_crypto.h" -#include -#include -#include -#include "internal.h" - -LIST_HEAD(crypto_alg_list); -DECLARE_RWSEM(crypto_alg_sem); - -static inline int crypto_alg_get(struct crypto_alg *alg) -{ - return try_inc_mod_count(alg->cra_module); -} - -static inline void crypto_alg_put(struct crypto_alg *alg) -{ - if (alg->cra_module) - __MOD_DEC_USE_COUNT(alg->cra_module); -} - -struct crypto_alg *crypto_alg_lookup(const char *name) -{ - struct crypto_alg *q, *alg = NULL; - - if (!name) - return NULL; - - down_read(&crypto_alg_sem); - - list_for_each_entry(q, &crypto_alg_list, cra_list) { - if (!(strcmp(q->cra_name, name))) { - if (crypto_alg_get(q)) - alg = q; - break; - } - } - - up_read(&crypto_alg_sem); - return alg; -} - -static int crypto_init_flags(struct crypto_tfm *tfm, u32 flags) -{ - tfm->crt_flags = 0; - - switch (crypto_tfm_alg_type(tfm)) { - case CRYPTO_ALG_TYPE_CIPHER: - return crypto_init_cipher_flags(tfm, flags); - - case CRYPTO_ALG_TYPE_DIGEST: - return crypto_init_digest_flags(tfm, flags); - - case CRYPTO_ALG_TYPE_COMPRESS: - return crypto_init_compress_flags(tfm, flags); - - default: - break; - } - - BUG(); - return -EINVAL; -} - -static int crypto_init_ops(struct crypto_tfm *tfm) -{ - switch (crypto_tfm_alg_type(tfm)) { - case CRYPTO_ALG_TYPE_CIPHER: - return crypto_init_cipher_ops(tfm); - - case CRYPTO_ALG_TYPE_DIGEST: - return crypto_init_digest_ops(tfm); - - case CRYPTO_ALG_TYPE_COMPRESS: - return crypto_init_compress_ops(tfm); - - default: - break; - } - - BUG(); - return -EINVAL; -} - -static void crypto_exit_ops(struct crypto_tfm *tfm) -{ - switch (crypto_tfm_alg_type(tfm)) { - case CRYPTO_ALG_TYPE_CIPHER: - crypto_exit_cipher_ops(tfm); - break; - - case CRYPTO_ALG_TYPE_DIGEST: - crypto_exit_digest_ops(tfm); - break; - - case CRYPTO_ALG_TYPE_COMPRESS: - crypto_exit_compress_ops(tfm); - break; - - default: - BUG(); - - } -} - -struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags) -{ - struct crypto_tfm *tfm = NULL; - struct crypto_alg *alg; - - alg = crypto_alg_mod_lookup(name); - if (alg == NULL) - goto out; - - tfm = kzalloc(sizeof(*tfm) + alg->cra_ctxsize, GFP_KERNEL); - if (tfm == NULL) - goto out_put; - - tfm->__crt_alg = alg; - - if (crypto_init_flags(tfm, flags)) - goto out_free_tfm; - - if (crypto_init_ops(tfm)) { - crypto_exit_ops(tfm); - goto out_free_tfm; - } - - goto out; - -out_free_tfm: - kfree(tfm); - tfm = NULL; -out_put: - crypto_alg_put(alg); -out: - return tfm; -} - -void crypto_free_tfm(struct crypto_tfm *tfm) -{ - struct crypto_alg *alg = tfm->__crt_alg; - int size = sizeof(*tfm) + alg->cra_ctxsize; - - crypto_exit_ops(tfm); - crypto_alg_put(alg); - memset(tfm, 0, size); - kfree(tfm); -} - -int crypto_register_alg(struct crypto_alg *alg) -{ - int ret = 0; - struct crypto_alg *q; - - down_write(&crypto_alg_sem); - - list_for_each_entry(q, &crypto_alg_list, cra_list) { - if (!(strcmp(q->cra_name, alg->cra_name))) { - ret = -EEXIST; - goto out; - } - } - - list_add_tail(&alg->cra_list, &crypto_alg_list); -out: - up_write(&crypto_alg_sem); - return ret; -} - -int crypto_unregister_alg(struct crypto_alg *alg) -{ - int ret = -ENOENT; - struct crypto_alg *q; - - BUG_ON(!alg->cra_module); - - down_write(&crypto_alg_sem); - list_for_each_entry(q, &crypto_alg_list, cra_list) { - if (alg == q) { - list_del(&alg->cra_list); - ret = 0; - goto out; - } - } -out: - up_write(&crypto_alg_sem); - return ret; -} - -int crypto_alg_available(const char *name, u32 flags) -{ - int ret = 0; - struct crypto_alg *alg = crypto_alg_mod_lookup(name); - - if (alg) { - crypto_alg_put(alg); - ret = 1; - } - - return ret; -} - -static int __init init_crypto(void) -{ - printk(KERN_INFO "Initializing Cryptographic API\n"); - crypto_init_proc(); - return 0; -} - -__initcall(init_crypto); - -/* -EXPORT_SYMBOL_GPL(crypto_register_alg); -EXPORT_SYMBOL_GPL(crypto_unregister_alg); -EXPORT_SYMBOL_GPL(crypto_alloc_tfm); -EXPORT_SYMBOL_GPL(crypto_free_tfm); -EXPORT_SYMBOL_GPL(crypto_alg_available); -*/ - -EXPORT_SYMBOL_NOVERS(crypto_register_alg); -EXPORT_SYMBOL_NOVERS(crypto_unregister_alg); -EXPORT_SYMBOL_NOVERS(crypto_alloc_tfm); -EXPORT_SYMBOL_NOVERS(crypto_free_tfm); -EXPORT_SYMBOL_NOVERS(crypto_alg_available); From e15fbc91a4304a977ed99c3eb21bab7015e86c11 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 25 Oct 2011 10:51:04 +0200 Subject: [PATCH 020/365] iio: introduce type casts to avoid __ucmpdi2 calls This patch type casts the switch control variable to 32 bits in order to prevent a call __ucmpdi2 generated by some versions of gcc. This fixes an undefined reference to `__ucmpdi2' when compiled for arch/blackfin Signed-off-by: Michael Hennerich Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/adc/ad7192.c | 2 +- drivers/staging/iio/adc/ad7280a.c | 6 +++--- drivers/staging/iio/dds/ad9832.c | 2 +- drivers/staging/iio/dds/ad9834.c | 4 ++-- drivers/staging/iio/impedance-analyzer/ad5933.c | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 31c376b9d5eb..d8bf559fef87 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -795,7 +795,7 @@ static ssize_t ad7192_set(struct device *dev, return -EBUSY; } - switch (this_attr->address) { + switch ((u32) this_attr->address) { case AD7192_REG_GPOCON: if (val) st->gpocon |= AD7192_GPOCON_BPDSW; diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c index 372d059042f9..0c212e050a8d 100644 --- a/drivers/staging/iio/adc/ad7280a.c +++ b/drivers/staging/iio/adc/ad7280a.c @@ -600,7 +600,7 @@ static ssize_t ad7280_read_channel_config(struct device *dev, struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); unsigned val; - switch (this_attr->address) { + switch ((u32) this_attr->address) { case AD7280A_CELL_OVERVOLTAGE: val = 1000 + (st->cell_threshhigh * 1568) / 100; break; @@ -636,7 +636,7 @@ static ssize_t ad7280_write_channel_config(struct device *dev, if (ret) return ret; - switch (this_attr->address) { + switch ((u32) this_attr->address) { case AD7280A_CELL_OVERVOLTAGE: case AD7280A_CELL_UNDERVOLTAGE: val = ((val - 1000) * 100) / 1568; /* LSB 15.68mV */ @@ -652,7 +652,7 @@ static ssize_t ad7280_write_channel_config(struct device *dev, val = clamp(val, 0L, 0xFFL); mutex_lock(&indio_dev->mlock); - switch (this_attr->address) { + switch ((u32) this_attr->address) { case AD7280A_CELL_OVERVOLTAGE: st->cell_threshhigh = val; break; diff --git a/drivers/staging/iio/dds/ad9832.c b/drivers/staging/iio/dds/ad9832.c index 9b4ff6065359..b58baec4da8e 100644 --- a/drivers/staging/iio/dds/ad9832.c +++ b/drivers/staging/iio/dds/ad9832.c @@ -88,7 +88,7 @@ static ssize_t ad9832_write(struct device *dev, goto error_ret; mutex_lock(&indio_dev->mlock); - switch (this_attr->address) { + switch ((u32) this_attr->address) { case AD9832_FREQ0HM: case AD9832_FREQ1HM: ret = ad9832_write_frequency(st, this_attr->address, val); diff --git a/drivers/staging/iio/dds/ad9834.c b/drivers/staging/iio/dds/ad9834.c index c468f696fe25..2e29f6f1073c 100644 --- a/drivers/staging/iio/dds/ad9834.c +++ b/drivers/staging/iio/dds/ad9834.c @@ -77,7 +77,7 @@ static ssize_t ad9834_write(struct device *dev, goto error_ret; mutex_lock(&indio_dev->mlock); - switch (this_attr->address) { + switch ((u32) this_attr->address) { case AD9834_REG_FREQ0: case AD9834_REG_FREQ1: ret = ad9834_write_frequency(st, this_attr->address, val); @@ -153,7 +153,7 @@ static ssize_t ad9834_store_wavetype(struct device *dev, mutex_lock(&indio_dev->mlock); - switch (this_attr->address) { + switch ((u32) this_attr->address) { case 0: if (sysfs_streq(buf, "sine")) { st->control &= ~AD9834_MODE; diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index 1086e0befc28..ece770766426 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -329,7 +329,7 @@ static ssize_t ad5933_show(struct device *dev, int ret = 0, len = 0; mutex_lock(&indio_dev->mlock); - switch (this_attr->address) { + switch ((u32) this_attr->address) { case AD5933_OUT_RANGE: len = sprintf(buf, "%d\n", st->range_avail[(st->ctrl_hb >> 1) & 0x3]); @@ -380,7 +380,7 @@ static ssize_t ad5933_store(struct device *dev, } mutex_lock(&indio_dev->mlock); - switch (this_attr->address) { + switch ((u32) this_attr->address) { case AD5933_OUT_RANGE: for (i = 0; i < 4; i++) if (val == st->range_avail[i]) { From 703a9ce45abf0ae0221161fbb11952dc528db0b0 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Wed, 26 Oct 2011 13:38:18 +0200 Subject: [PATCH 021/365] iio: adc: ad7280a: Fix memory leak Free channels in case read fails with error. Signed-off-by: Michael Hennerich Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/adc/ad7280a.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c index 0c212e050a8d..f45b66bf6105 100644 --- a/drivers/staging/iio/adc/ad7280a.c +++ b/drivers/staging/iio/adc/ad7280a.c @@ -688,7 +688,7 @@ static irqreturn_t ad7280_event_handler(int irq, void *private) ret = ad7280_read_all_channels(st, st->scan_cnt, channels); if (ret < 0) - return IRQ_HANDLED; + goto out; for (i = 0; i < st->scan_cnt; i++) { if (((channels[i] >> 23) & 0xF) <= AD7280A_CELL_VOLTAGE_6) { @@ -731,6 +731,7 @@ static irqreturn_t ad7280_event_handler(int irq, void *private) } } +out: kfree(channels); return IRQ_HANDLED; From a7e3bd669eb407b4e700a023e502bfc80d814b04 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 26 Oct 2011 17:27:36 +0100 Subject: [PATCH 022/365] staging:iio:light:tsl2563 both intensity channels have same chan_spec. Bug has been fixed for some time in the outofstaging tree, but didn't propogate back to here. Signed-off-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/light/tsl2563.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c index 7e984bcf8d7e..be99925f566b 100644 --- a/drivers/staging/iio/light/tsl2563.c +++ b/drivers/staging/iio/light/tsl2563.c @@ -544,7 +544,7 @@ static const struct iio_chan_spec tsl2563_channels[] = { }, { .type = IIO_INTENSITY, .modified = 1, - .channel2 = IIO_MOD_LIGHT_BOTH, + .channel2 = IIO_MOD_LIGHT_IR, .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE), } }; From 22dc09cafda0d9b31e8f07539535582fb343baf8 Mon Sep 17 00:00:00 2001 From: "Maxin B. John" Date: Wed, 26 Oct 2011 17:27:37 +0100 Subject: [PATCH 023/365] staging:iio:light:tsl2563 missing setting of id in get id function. Signed-off-by: Maxin B. John Reviewed-by: Dan Carpenter Signed-off-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/light/tsl2563.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c index be99925f566b..6a1794508f67 100644 --- a/drivers/staging/iio/light/tsl2563.c +++ b/drivers/staging/iio/light/tsl2563.c @@ -226,6 +226,8 @@ static int tsl2563_read_id(struct tsl2563_chip *chip, u8 *id) if (ret < 0) return ret; + *id = ret; + return 0; } From 67be8e32c9f98453faeb9a992a47bd5910c9fb2e Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 26 Oct 2011 17:27:38 +0100 Subject: [PATCH 024/365] staging:iio:triggers Remove unecessary existence checks and return val Postenable and predisable are called via buffer->ops so don't need to check if buffer exists. The return value of iio_device_register_trigger_consumer is always zero and it isn't checked anyway so get rid of it. Signed-off-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/iio_core_trigger.h | 3 +-- drivers/staging/iio/industrialio-trigger.c | 16 +++++----------- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/drivers/staging/iio/iio_core_trigger.h b/drivers/staging/iio/iio_core_trigger.h index 523c288b776b..6f7c56fcbe78 100644 --- a/drivers/staging/iio/iio_core_trigger.h +++ b/drivers/staging/iio/iio_core_trigger.h @@ -13,8 +13,7 @@ * iio_device_register_trigger_consumer() - set up an iio_dev to use triggers * @indio_dev: iio_dev associated with the device that will consume the trigger **/ - -int iio_device_register_trigger_consumer(struct iio_dev *indio_dev); +void iio_device_register_trigger_consumer(struct iio_dev *indio_dev); /** * iio_device_unregister_trigger_consumer() - reverse the registration process diff --git a/drivers/staging/iio/industrialio-trigger.c b/drivers/staging/iio/industrialio-trigger.c index 2c626e0cb29c..ca4124aa65ee 100644 --- a/drivers/staging/iio/industrialio-trigger.c +++ b/drivers/staging/iio/industrialio-trigger.c @@ -473,12 +473,10 @@ void iio_free_trigger(struct iio_trigger *trig) } EXPORT_SYMBOL(iio_free_trigger); -int iio_device_register_trigger_consumer(struct iio_dev *indio_dev) +void iio_device_register_trigger_consumer(struct iio_dev *indio_dev) { indio_dev->groups[indio_dev->groupcounter++] = &iio_trigger_consumer_attr_group; - - return 0; } void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev) @@ -490,18 +488,14 @@ void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev) int iio_triggered_buffer_postenable(struct iio_dev *indio_dev) { - return indio_dev->trig - ? iio_trigger_attach_poll_func(indio_dev->trig, - indio_dev->pollfunc) - : 0; + return iio_trigger_attach_poll_func(indio_dev->trig, + indio_dev->pollfunc); } EXPORT_SYMBOL(iio_triggered_buffer_postenable); int iio_triggered_buffer_predisable(struct iio_dev *indio_dev) { - return indio_dev->trig - ? iio_trigger_dettach_poll_func(indio_dev->trig, - indio_dev->pollfunc) - : 0; + return iio_trigger_dettach_poll_func(indio_dev->trig, + indio_dev->pollfunc); } EXPORT_SYMBOL(iio_triggered_buffer_predisable); From e69616b1e65cb9d3dcf34399e8fac331911abfe5 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 26 Oct 2011 17:27:39 +0100 Subject: [PATCH 025/365] staging:iio:industrialio-trigger.c Trivial code style brackets fix Signed-off-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/industrialio-trigger.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/staging/iio/industrialio-trigger.c b/drivers/staging/iio/industrialio-trigger.c index ca4124aa65ee..9412013e7459 100644 --- a/drivers/staging/iio/industrialio-trigger.c +++ b/drivers/staging/iio/industrialio-trigger.c @@ -159,13 +159,12 @@ EXPORT_SYMBOL(iio_trigger_generic_data_rdy_poll); void iio_trigger_poll_chained(struct iio_trigger *trig, s64 time) { int i; - if (!trig->use_count) { + if (!trig->use_count) for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) if (trig->subirqs[i].enabled) { trig->use_count++; handle_nested_irq(trig->subirq_base + i); } - } } EXPORT_SYMBOL(iio_trigger_poll_chained); @@ -173,10 +172,9 @@ void iio_trigger_notify_done(struct iio_trigger *trig) { trig->use_count--; if (trig->use_count == 0 && trig->ops && trig->ops->try_reenable) - if (trig->ops->try_reenable(trig)) { + if (trig->ops->try_reenable(trig)) /* Missed and interrupt so launch new poll now */ iio_trigger_poll(trig, 0); - } } EXPORT_SYMBOL(iio_trigger_notify_done); From 4c3d15358a7ffdd587acc02ec91d28989334d4be Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 26 Oct 2011 17:27:40 +0100 Subject: [PATCH 026/365] staging:iio:kfifo remove entirely pointless code. I really don't want to think about how this bit got in there. It allocates some storage - copies something into it then frees it without making use of it. Oops. Signed-off-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/kfifo_buf.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/staging/iio/kfifo_buf.c b/drivers/staging/iio/kfifo_buf.c index e8c234bb18f0..fd98a0ebb5ff 100644 --- a/drivers/staging/iio/kfifo_buf.c +++ b/drivers/staging/iio/kfifo_buf.c @@ -150,16 +150,9 @@ static int iio_store_to_kfifo(struct iio_buffer *r, { int ret; struct iio_kfifo *kf = iio_to_kfifo(r); - u8 *datal = kmalloc(r->bytes_per_datum, GFP_KERNEL); - memcpy(datal, data, r->bytes_per_datum - sizeof(timestamp)); - memcpy(datal + r->bytes_per_datum - sizeof(timestamp), - ×tamp, sizeof(timestamp)); ret = kfifo_in(&kf->kf, data, r->bytes_per_datum); - if (ret != r->bytes_per_datum) { - kfree(datal); + if (ret != r->bytes_per_datum) return -EBUSY; - } - kfree(datal); return 0; } From 5dd72ecb0166498852705939163f375d693d37f3 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 26 Oct 2011 17:27:41 +0100 Subject: [PATCH 027/365] staging:iio: trigger fixes for repeat request of same trigger and allocation failure Both of these are decidedly silly bugs show up whilst testing completely different code paths. Signed-off-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/industrialio-trigger.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/staging/iio/industrialio-trigger.c b/drivers/staging/iio/industrialio-trigger.c index 9412013e7459..20dc8e87d1cd 100644 --- a/drivers/staging/iio/industrialio-trigger.c +++ b/drivers/staging/iio/industrialio-trigger.c @@ -220,8 +220,16 @@ static int iio_trigger_attach_poll_func(struct iio_trigger *trig, ret = request_threaded_irq(pf->irq, pf->h, pf->thread, pf->type, pf->name, pf); - if (trig->ops && trig->ops->set_trigger_state && notinuse) + if (ret < 0) { + module_put(pf->indio_dev->info->driver_module); + return ret; + } + + if (trig->ops && trig->ops->set_trigger_state && notinuse) { ret = trig->ops->set_trigger_state(trig, true); + if (ret < 0) + module_put(pf->indio_dev->info->driver_module); + } return ret; } @@ -334,6 +342,8 @@ static ssize_t iio_trigger_write_current(struct device *dev, mutex_unlock(&indio_dev->mlock); trig = iio_trigger_find_by_name(buf, len); + if (oldtrig == trig) + return len; if (trig && indio_dev->info->validate_trigger) { ret = indio_dev->info->validate_trigger(indio_dev, trig); From 0403e0d643809f1608448ada38a1877f26b7bf5d Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 26 Oct 2011 17:27:42 +0100 Subject: [PATCH 028/365] staging:iio:core shared attrs do not work with modifier. The logic building the name had a small bug where it did not verify if it was generic before applying the modifier. Signed-off-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/industrialio-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c index 26564094e33b..fbf24bdc56d9 100644 --- a/drivers/staging/iio/industrialio-core.c +++ b/drivers/staging/iio/industrialio-core.c @@ -416,7 +416,7 @@ int __iio_device_attr_init(struct device_attribute *dev_attr, sysfs_attr_init(&dev_attr->attr); /* Build up postfix of __postfix */ - if (chan->modified) { + if (chan->modified && !generic) { if (chan->extend_name) full_postfix = kasprintf(GFP_KERNEL, "%s_%s_%s", iio_modifier_names[chan From dc8f52643d494eaa844002ca866d30fda142db4f Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Oct 2011 17:27:43 +0100 Subject: [PATCH 029/365] staging:iio:events: Make sure userspace buffer is large enough Make sure that the userspace buffer is large enough to hold a iio_event_data struct before writing to it. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/industrialio-core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c index fbf24bdc56d9..ee5e0640aa29 100644 --- a/drivers/staging/iio/industrialio-core.c +++ b/drivers/staging/iio/industrialio-core.c @@ -169,8 +169,11 @@ static ssize_t iio_event_chrdev_read(struct file *filep, { struct iio_event_interface *ev_int = filep->private_data; struct iio_detected_event_list *el; + size_t len = sizeof(el->ev); int ret; - size_t len; + + if (count < len) + return -EINVAL; mutex_lock(&ev_int->event_list_lock); if (list_empty(&ev_int->det_events)) { @@ -192,7 +195,6 @@ static ssize_t iio_event_chrdev_read(struct file *filep, el = list_first_entry(&ev_int->det_events, struct iio_detected_event_list, list); - len = sizeof el->ev; if (copy_to_user(buf, &(el->ev), len)) { ret = -EFAULT; goto error_mutex_unlock; From bc9f35db8fed28d8fa1195b3927c8e1e91d64388 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Oct 2011 17:27:44 +0100 Subject: [PATCH 030/365] staging:iio:iio_utils.h: Add missing include iio_utils.h uses opendir and friends which need dirent.h Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/Documentation/iio_utils.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/iio/Documentation/iio_utils.h b/drivers/staging/iio/Documentation/iio_utils.h index 75938b2412ff..dbbad8a16382 100644 --- a/drivers/staging/iio/Documentation/iio_utils.h +++ b/drivers/staging/iio/Documentation/iio_utils.h @@ -13,6 +13,7 @@ #include #include #include +#include #define IIO_MAX_NAME_LENGTH 30 From 96e00f110fae862b61f3db9dc25fe8f0f43f77e9 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 26 Oct 2011 17:27:45 +0100 Subject: [PATCH 031/365] staging:iio: core. Allow for event chrdev obtaining ioctl if no buffer present. Logic bug meant the chrdev would fail to open if there was no buffer support in a driver or in the core. This meant the ioctl to get the event chrdev would fail and hence events were not available. V2: change error to -EINVAL to mark as unsuitable for reading rather than not there. Both are true depending on how you look at it. Signed-off-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/iio_core.h | 2 +- drivers/staging/iio/industrialio-buffer.c | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/staging/iio/iio_core.h b/drivers/staging/iio/iio_core.h index 36159e0dbfc3..ff27f1360d92 100644 --- a/drivers/staging/iio/iio_core.h +++ b/drivers/staging/iio/iio_core.h @@ -49,7 +49,7 @@ ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf, static inline int iio_chrdev_buffer_open(struct iio_dev *indio_dev) { - return -EINVAL; + return 0; } static inline void iio_chrdev_buffer_release(struct iio_dev *indio_dev) diff --git a/drivers/staging/iio/industrialio-buffer.c b/drivers/staging/iio/industrialio-buffer.c index 9df0ce81dade..ecf1e2f6d2dc 100644 --- a/drivers/staging/iio/industrialio-buffer.c +++ b/drivers/staging/iio/industrialio-buffer.c @@ -43,7 +43,7 @@ ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf, struct iio_dev *indio_dev = filp->private_data; struct iio_buffer *rb = indio_dev->buffer; - if (!rb->access->read_first_n) + if (!rb || !rb->access->read_first_n) return -EINVAL; return rb->access->read_first_n(rb, n, buf); } @@ -68,7 +68,7 @@ int iio_chrdev_buffer_open(struct iio_dev *indio_dev) { struct iio_buffer *rb = indio_dev->buffer; if (!rb) - return -EINVAL; + return 0; if (rb->access->mark_in_use) rb->access->mark_in_use(rb); return 0; @@ -78,6 +78,8 @@ void iio_chrdev_buffer_release(struct iio_dev *indio_dev) { struct iio_buffer *rb = indio_dev->buffer; + if (!rb) + return; clear_bit(IIO_BUSY_BIT_POS, &rb->flags); if (rb->access->unmark_in_use) rb->access->unmark_in_use(rb); From f791cec85073298d00f18b8492b79a8b4e9b0580 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 26 Nov 2011 16:31:16 -0800 Subject: [PATCH 032/365] Subject: fix build breakage in drivers/staging/iio/industrialio-core.c This was introduced in commit b46413367961c2e8bd827e067a231be982aaeee2 (iio: fix a leak due to improper use of anon_inode_getfd()) Cc: Al Viro Cc: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/industrialio-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c index ee5e0640aa29..f5c111cb1dba 100644 --- a/drivers/staging/iio/industrialio-core.c +++ b/drivers/staging/iio/industrialio-core.c @@ -261,7 +261,7 @@ static int iio_event_getfd(struct iio_dev *indio_dev) indio_dev->event_interface, O_RDONLY); if (fd < 0) { mutex_lock(&indio_dev->event_interface->event_list_lock); - clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); + clear_bit(IIO_BUSY_BIT_POS, &indio_dev->event_interface->flags); mutex_unlock(&indio_dev->event_interface->event_list_lock); } return fd; From af5046af1c812839f085030f358a01814666fc80 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 26 Oct 2011 17:41:32 +0100 Subject: [PATCH 033/365] staging:iio: header reorganization Issue brought up by Lars-Peter Clausen. This is a varient of what he suggested. io/iio.h for driver stuff (has to include types.h) Sub files for the bits drivers may or may not use iio/sysfs.h iio/buffer.h (contents of current buffer_generic.h) (obviously anything offering events will need events.h as well) iio/types.h for the enums that matter to both iio_chan_type, iio_modifier iio/events.h for the event code stuff IIO_EVENT_CODE and friends. + everything in chrdev.h So this is the stuff that userspace cares about. Also include iio_event_type, iio_event_direction Thus iio drivers include iio.h + as required events.h sysfs.h buffer.h in kernel users (once that interface is merged) will need inkern.h which will pull in types.h Userspace will need just events.h (which pulls in types.h) to get everything they need to know about. Buffer userspace access doesn't currently need any core defines. All information about the data format is passed through sysfs. Signed-off-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/accel/adis16201_core.c | 2 +- drivers/staging/iio/accel/adis16203_core.c | 2 +- drivers/staging/iio/accel/adis16204_core.c | 2 +- drivers/staging/iio/accel/adis16209_core.c | 2 +- drivers/staging/iio/accel/adis16240_core.c | 2 +- drivers/staging/iio/accel/lis3l02dq_core.c | 3 +- drivers/staging/iio/accel/sca3000_core.c | 3 +- drivers/staging/iio/accel/sca3000_ring.c | 2 +- drivers/staging/iio/adc/ad7192.c | 2 +- drivers/staging/iio/adc/ad7280a.c | 1 + drivers/staging/iio/adc/ad7291.c | 1 + drivers/staging/iio/adc/ad7298_core.c | 2 +- drivers/staging/iio/adc/ad7298_ring.c | 2 +- drivers/staging/iio/adc/ad7476_core.c | 2 +- drivers/staging/iio/adc/ad7476_ring.c | 2 +- drivers/staging/iio/adc/ad7606_core.c | 2 +- drivers/staging/iio/adc/ad7606_ring.c | 2 +- drivers/staging/iio/adc/ad7793.c | 2 +- drivers/staging/iio/adc/ad7816.c | 1 + drivers/staging/iio/adc/ad7887_core.c | 2 +- drivers/staging/iio/adc/ad7887_ring.c | 2 +- drivers/staging/iio/adc/ad799x_core.c | 3 +- drivers/staging/iio/adc/ad799x_ring.c | 2 +- drivers/staging/iio/adc/adt7310.c | 2 +- drivers/staging/iio/adc/adt7410.c | 1 + drivers/staging/iio/adc/max1363_core.c | 3 +- drivers/staging/iio/adc/max1363_ring.c | 2 +- drivers/staging/iio/addac/adt7316.c | 1 + .../iio/{buffer_generic.h => buffer.h} | 1 - drivers/staging/iio/cdc/ad7150.c | 2 +- drivers/staging/iio/chrdev.h | 25 ------- drivers/staging/iio/dac/ad5504.c | 1 + drivers/staging/iio/events.h | 72 +++++++++++++++++++ drivers/staging/iio/gyro/adis16260_core.c | 2 +- drivers/staging/iio/iio.h | 39 +--------- drivers/staging/iio/iio_simple_dummy.c | 3 +- drivers/staging/iio/iio_simple_dummy_events.c | 1 + .../staging/iio/impedance-analyzer/ad5933.c | 2 +- drivers/staging/iio/imu/adis16400_core.c | 2 +- drivers/staging/iio/industrialio-buffer.c | 2 +- drivers/staging/iio/industrialio-core.c | 2 +- drivers/staging/iio/kfifo_buf.h | 2 +- drivers/staging/iio/light/tsl2563.c | 1 + drivers/staging/iio/meter/ade7758_core.c | 2 +- drivers/staging/iio/ring_sw.h | 2 +- drivers/staging/iio/sysfs.h | 43 ----------- drivers/staging/iio/types.h | 49 +++++++++++++ 47 files changed, 168 insertions(+), 140 deletions(-) rename drivers/staging/iio/{buffer_generic.h => buffer.h} (99%) delete mode 100644 drivers/staging/iio/chrdev.h create mode 100644 drivers/staging/iio/events.h create mode 100644 drivers/staging/iio/types.h diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c index 1c5dad537844..128351931756 100644 --- a/drivers/staging/iio/accel/adis16201_core.c +++ b/drivers/staging/iio/accel/adis16201_core.c @@ -17,7 +17,7 @@ #include "../iio.h" #include "../sysfs.h" -#include "../buffer_generic.h" +#include "../buffer.h" #include "adis16201.h" diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c index 8a3337442afd..5483b59aea32 100644 --- a/drivers/staging/iio/accel/adis16203_core.c +++ b/drivers/staging/iio/accel/adis16203_core.c @@ -17,7 +17,7 @@ #include "../iio.h" #include "../sysfs.h" -#include "../buffer_generic.h" +#include "../buffer.h" #include "adis16203.h" diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c index 644ac8e4d2aa..462f215f8c8d 100644 --- a/drivers/staging/iio/accel/adis16204_core.c +++ b/drivers/staging/iio/accel/adis16204_core.c @@ -20,7 +20,7 @@ #include "../iio.h" #include "../sysfs.h" -#include "../buffer_generic.h" +#include "../buffer.h" #include "adis16204.h" diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c index 0a8571b18b39..827499f70af6 100644 --- a/drivers/staging/iio/accel/adis16209_core.c +++ b/drivers/staging/iio/accel/adis16209_core.c @@ -18,7 +18,7 @@ #include "../iio.h" #include "../sysfs.h" -#include "../buffer_generic.h" +#include "../buffer.h" #include "adis16209.h" diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c index b8be2925d61c..8123fe3bd227 100644 --- a/drivers/staging/iio/accel/adis16240_core.c +++ b/drivers/staging/iio/accel/adis16240_core.c @@ -21,7 +21,7 @@ #include "../iio.h" #include "../sysfs.h" -#include "../buffer_generic.h" +#include "../buffer.h" #include "adis16240.h" diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c index 559545a42333..358a9f6cbb0a 100644 --- a/drivers/staging/iio/accel/lis3l02dq_core.c +++ b/drivers/staging/iio/accel/lis3l02dq_core.c @@ -25,7 +25,8 @@ #include "../iio.h" #include "../sysfs.h" -#include "../buffer_generic.h" +#include "../events.h" +#include "../buffer.h" #include "lis3l02dq.h" diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c index a44a70589db9..8a46983275bc 100644 --- a/drivers/staging/iio/accel/sca3000_core.c +++ b/drivers/staging/iio/accel/sca3000_core.c @@ -20,7 +20,8 @@ #include #include "../iio.h" #include "../sysfs.h" -#include "../buffer_generic.h" +#include "../events.h" +#include "../buffer.h" #include "sca3000.h" diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c index 4a9a01dccd0c..685ded8fb857 100644 --- a/drivers/staging/iio/accel/sca3000_ring.c +++ b/drivers/staging/iio/accel/sca3000_ring.c @@ -20,7 +20,7 @@ #include "../iio.h" #include "../sysfs.h" -#include "../buffer_generic.h" +#include "../buffer.h" #include "../ring_hw.h" #include "sca3000.h" diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index d8bf559fef87..39ba05db2c02 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -19,7 +19,7 @@ #include "../iio.h" #include "../sysfs.h" -#include "../buffer_generic.h" +#include "../buffer.h" #include "../ring_sw.h" #include "../trigger.h" #include "../trigger_consumer.h" diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c index f45b66bf6105..8f4fac1ce7ae 100644 --- a/drivers/staging/iio/adc/ad7280a.c +++ b/drivers/staging/iio/adc/ad7280a.c @@ -18,6 +18,7 @@ #include "../iio.h" #include "../sysfs.h" +#include "../events.h" #include "ad7280a.h" diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/staging/iio/adc/ad7291.c index 10e79e8ee64d..e5f352bc4368 100644 --- a/drivers/staging/iio/adc/ad7291.c +++ b/drivers/staging/iio/adc/ad7291.c @@ -19,6 +19,7 @@ #include "../iio.h" #include "../sysfs.h" +#include "../events.h" /* * Simplified handling diff --git a/drivers/staging/iio/adc/ad7298_core.c b/drivers/staging/iio/adc/ad7298_core.c index c1de73a1ca91..445b07116d74 100644 --- a/drivers/staging/iio/adc/ad7298_core.c +++ b/drivers/staging/iio/adc/ad7298_core.c @@ -18,7 +18,7 @@ #include "../iio.h" #include "../sysfs.h" -#include "../buffer_generic.h" +#include "../buffer.h" #include "ad7298.h" diff --git a/drivers/staging/iio/adc/ad7298_ring.c b/drivers/staging/iio/adc/ad7298_ring.c index 47630d506a63..192328edeb29 100644 --- a/drivers/staging/iio/adc/ad7298_ring.c +++ b/drivers/staging/iio/adc/ad7298_ring.c @@ -12,7 +12,7 @@ #include #include "../iio.h" -#include "../buffer_generic.h" +#include "../buffer.h" #include "../ring_sw.h" #include "../trigger_consumer.h" diff --git a/drivers/staging/iio/adc/ad7476_core.c b/drivers/staging/iio/adc/ad7476_core.c index fd79facc6cae..13473133bbe2 100644 --- a/drivers/staging/iio/adc/ad7476_core.c +++ b/drivers/staging/iio/adc/ad7476_core.c @@ -17,7 +17,7 @@ #include "../iio.h" #include "../sysfs.h" -#include "../buffer_generic.h" +#include "../buffer.h" #include "ad7476.h" diff --git a/drivers/staging/iio/adc/ad7476_ring.c b/drivers/staging/iio/adc/ad7476_ring.c index e82c1a433f4f..09618873986e 100644 --- a/drivers/staging/iio/adc/ad7476_ring.c +++ b/drivers/staging/iio/adc/ad7476_ring.c @@ -14,7 +14,7 @@ #include #include "../iio.h" -#include "../buffer_generic.h" +#include "../buffer.h" #include "../ring_sw.h" #include "../trigger_consumer.h" diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c index 54423ab196fe..53174831663c 100644 --- a/drivers/staging/iio/adc/ad7606_core.c +++ b/drivers/staging/iio/adc/ad7606_core.c @@ -20,7 +20,7 @@ #include "../iio.h" #include "../sysfs.h" -#include "../buffer_generic.h" +#include "../buffer.h" #include "ad7606.h" diff --git a/drivers/staging/iio/adc/ad7606_ring.c b/drivers/staging/iio/adc/ad7606_ring.c index 20927fd53728..af6780a4fe7d 100644 --- a/drivers/staging/iio/adc/ad7606_ring.c +++ b/drivers/staging/iio/adc/ad7606_ring.c @@ -12,7 +12,7 @@ #include #include "../iio.h" -#include "../buffer_generic.h" +#include "../buffer.h" #include "../ring_sw.h" #include "../trigger_consumer.h" diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c index 999f8f746cff..17fde6669eff 100644 --- a/drivers/staging/iio/adc/ad7793.c +++ b/drivers/staging/iio/adc/ad7793.c @@ -20,7 +20,7 @@ #include "../iio.h" #include "../sysfs.h" -#include "../buffer_generic.h" +#include "../buffer.h" #include "../ring_sw.h" #include "../trigger.h" #include "../trigger_consumer.h" diff --git a/drivers/staging/iio/adc/ad7816.c b/drivers/staging/iio/adc/ad7816.c index bdb90492b8a5..7a344a271615 100644 --- a/drivers/staging/iio/adc/ad7816.c +++ b/drivers/staging/iio/adc/ad7816.c @@ -18,6 +18,7 @@ #include "../iio.h" #include "../sysfs.h" +#include "../events.h" /* * AD7816 config masks diff --git a/drivers/staging/iio/adc/ad7887_core.c b/drivers/staging/iio/adc/ad7887_core.c index 609dcd5f2ddc..a7baa9bb0eaa 100644 --- a/drivers/staging/iio/adc/ad7887_core.c +++ b/drivers/staging/iio/adc/ad7887_core.c @@ -17,7 +17,7 @@ #include "../iio.h" #include "../sysfs.h" -#include "../buffer_generic.h" +#include "../buffer.h" #include "ad7887.h" diff --git a/drivers/staging/iio/adc/ad7887_ring.c b/drivers/staging/iio/adc/ad7887_ring.c index cb74cada5611..fbe21b5bd3dd 100644 --- a/drivers/staging/iio/adc/ad7887_ring.c +++ b/drivers/staging/iio/adc/ad7887_ring.c @@ -13,7 +13,7 @@ #include #include "../iio.h" -#include "../buffer_generic.h" +#include "../buffer.h" #include "../ring_sw.h" #include "../trigger_consumer.h" diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c index ee6cd792bec8..64ac31666739 100644 --- a/drivers/staging/iio/adc/ad799x_core.c +++ b/drivers/staging/iio/adc/ad799x_core.c @@ -35,7 +35,8 @@ #include "../iio.h" #include "../sysfs.h" -#include "../buffer_generic.h" +#include "../events.h" +#include "../buffer.h" #include "ad799x.h" diff --git a/drivers/staging/iio/adc/ad799x_ring.c b/drivers/staging/iio/adc/ad799x_ring.c index e3f4698d7815..b215a1f5a02b 100644 --- a/drivers/staging/iio/adc/ad799x_ring.c +++ b/drivers/staging/iio/adc/ad799x_ring.c @@ -17,7 +17,7 @@ #include #include "../iio.h" -#include "../buffer_generic.h" +#include "../buffer.h" #include "../ring_sw.h" #include "../trigger_consumer.h" diff --git a/drivers/staging/iio/adc/adt7310.c b/drivers/staging/iio/adc/adt7310.c index c9e0be3b1cf3..c937ac1838f2 100644 --- a/drivers/staging/iio/adc/adt7310.c +++ b/drivers/staging/iio/adc/adt7310.c @@ -17,7 +17,7 @@ #include "../iio.h" #include "../sysfs.h" - +#include "../events.h" /* * ADT7310 registers definition */ diff --git a/drivers/staging/iio/adc/adt7410.c b/drivers/staging/iio/adc/adt7410.c index a289e429dc41..16467a7ef4a4 100644 --- a/drivers/staging/iio/adc/adt7410.c +++ b/drivers/staging/iio/adc/adt7410.c @@ -17,6 +17,7 @@ #include "../iio.h" #include "../sysfs.h" +#include "../events.h" /* * ADT7410 registers definition diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c index eb699ade34b0..73b209f23c73 100644 --- a/drivers/staging/iio/adc/max1363_core.c +++ b/drivers/staging/iio/adc/max1363_core.c @@ -34,7 +34,8 @@ #include "../iio.h" #include "../sysfs.h" -#include "../buffer_generic.h" +#include "../events.h" +#include "../buffer.h" #include "max1363.h" diff --git a/drivers/staging/iio/adc/max1363_ring.c b/drivers/staging/iio/adc/max1363_ring.c index df6893e058cc..a87fbe8b0ee9 100644 --- a/drivers/staging/iio/adc/max1363_ring.c +++ b/drivers/staging/iio/adc/max1363_ring.c @@ -15,7 +15,7 @@ #include #include "../iio.h" -#include "../buffer_generic.h" +#include "../buffer.h" #include "../ring_sw.h" #include "../trigger_consumer.h" diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c index 8df24704ff26..13c39292d3f2 100644 --- a/drivers/staging/iio/addac/adt7316.c +++ b/drivers/staging/iio/addac/adt7316.c @@ -20,6 +20,7 @@ #include #include "../iio.h" +#include "../events.h" #include "../sysfs.h" #include "adt7316.h" diff --git a/drivers/staging/iio/buffer_generic.h b/drivers/staging/iio/buffer.h similarity index 99% rename from drivers/staging/iio/buffer_generic.h rename to drivers/staging/iio/buffer.h index 9e8f01009979..9de581e2d764 100644 --- a/drivers/staging/iio/buffer_generic.h +++ b/drivers/staging/iio/buffer.h @@ -11,7 +11,6 @@ #define _IIO_BUFFER_GENERIC_H_ #include #include "iio.h" -#include "chrdev.h" #ifdef CONFIG_IIO_BUFFER diff --git a/drivers/staging/iio/cdc/ad7150.c b/drivers/staging/iio/cdc/ad7150.c index a761ca94a17e..abe65096c110 100644 --- a/drivers/staging/iio/cdc/ad7150.c +++ b/drivers/staging/iio/cdc/ad7150.c @@ -15,7 +15,7 @@ #include "../iio.h" #include "../sysfs.h" - +#include "../events.h" /* * AD7150 registers definition */ diff --git a/drivers/staging/iio/chrdev.h b/drivers/staging/iio/chrdev.h deleted file mode 100644 index d8e736f60522..000000000000 --- a/drivers/staging/iio/chrdev.h +++ /dev/null @@ -1,25 +0,0 @@ -/* The industrial I/O core - character device related - * - * Copyright (c) 2008 Jonathan Cameron - * - * 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. - */ - -#ifndef _IIO_CHRDEV_H_ -#define _IIO_CHRDEV_H_ - -/** - * struct iio_event_data - The actual event being pushed to userspace - * @id: event identifier - * @timestamp: best estimate of time of event occurrence (often from - * the interrupt handler) - */ -struct iio_event_data { - u64 id; - s64 timestamp; -}; - -#define IIO_GET_EVENT_FD_IOCTL _IOR('i', 0x90, int) -#endif diff --git a/drivers/staging/iio/dac/ad5504.c b/drivers/staging/iio/dac/ad5504.c index 60dd6404d689..72040cc73764 100644 --- a/drivers/staging/iio/dac/ad5504.c +++ b/drivers/staging/iio/dac/ad5504.c @@ -18,6 +18,7 @@ #include "../iio.h" #include "../sysfs.h" +#include "../events.h" #include "dac.h" #include "ad5504.h" diff --git a/drivers/staging/iio/events.h b/drivers/staging/iio/events.h new file mode 100644 index 000000000000..08cf3d1a38bf --- /dev/null +++ b/drivers/staging/iio/events.h @@ -0,0 +1,72 @@ +/* The industrial I/O - event passing to userspace + * + * Copyright (c) 2008-2011 Jonathan Cameron + * + * 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. + */ +#ifndef _IIO_EVENTS_H_ +#define _IIO_EVENTS_H_ + +#include +#include "types.h" + +/** + * struct iio_event_data - The actual event being pushed to userspace + * @id: event identifier + * @timestamp: best estimate of time of event occurrence (often from + * the interrupt handler) + */ +struct iio_event_data { + u64 id; + s64 timestamp; +}; + +#define IIO_GET_EVENT_FD_IOCTL _IOR('i', 0x90, int) + +enum iio_event_type { + IIO_EV_TYPE_THRESH, + IIO_EV_TYPE_MAG, + IIO_EV_TYPE_ROC, + IIO_EV_TYPE_THRESH_ADAPTIVE, + IIO_EV_TYPE_MAG_ADAPTIVE, +}; + +enum iio_event_direction { + IIO_EV_DIR_EITHER, + IIO_EV_DIR_RISING, + IIO_EV_DIR_FALLING, +}; + +#define IIO_EVENT_CODE(chan_type, diff, modifier, direction, \ + type, chan, chan1, chan2) \ + (((u64)type << 56) | ((u64)diff << 55) | \ + ((u64)direction << 48) | ((u64)modifier << 40) | \ + ((u64)chan_type << 32) | (chan2 << 16) | chan1 | chan) + + +#define IIO_EV_DIR_MAX 4 +#define IIO_EV_BIT(type, direction) \ + (1 << (type*IIO_EV_DIR_MAX + direction)) + +#define IIO_MOD_EVENT_CODE(channelclass, number, modifier, \ + type, direction) \ + IIO_EVENT_CODE(channelclass, 0, modifier, direction, type, number, 0, 0) + +#define IIO_UNMOD_EVENT_CODE(channelclass, number, type, direction) \ + IIO_EVENT_CODE(channelclass, 0, 0, direction, type, number, 0, 0) + +#define IIO_EVENT_CODE_EXTRACT_TYPE(mask) ((mask >> 56) & 0xFF) + +#define IIO_EVENT_CODE_EXTRACT_DIR(mask) ((mask >> 48) & 0xCF) + +#define IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(mask) ((mask >> 32) & 0xFF) + +/* Event code number extraction depends on which type of event we have. + * Perhaps review this function in the future*/ +#define IIO_EVENT_CODE_EXTRACT_NUM(mask) (mask & 0xFFFF) + +#define IIO_EVENT_CODE_EXTRACT_MODIFIER(mask) ((mask >> 40) & 0xFF) + +#endif diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c index aaa3967f8c03..40da95554fa2 100644 --- a/drivers/staging/iio/gyro/adis16260_core.c +++ b/drivers/staging/iio/gyro/adis16260_core.c @@ -20,7 +20,7 @@ #include "../iio.h" #include "../sysfs.h" -#include "../buffer_generic.h" +#include "../buffer.h" #include "adis16260.h" diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h index f3d88cd7e8a0..cf95f74dc9db 100644 --- a/drivers/staging/iio/iio.h +++ b/drivers/staging/iio/iio.h @@ -7,13 +7,12 @@ * under the terms of the GNU General Public License version 2 as published by * the Free Software Foundation. */ - #ifndef _INDUSTRIAL_IO_H_ #define _INDUSTRIAL_IO_H_ #include #include - +#include "types.h" /* IIO TODO LIST */ /* * Provide means of adjusting timer accuracy. @@ -25,42 +24,6 @@ enum iio_data_type { IIO_PROCESSED, }; -enum iio_chan_type { - /* real channel types */ - IIO_VOLTAGE, - IIO_CURRENT, - IIO_POWER, - IIO_ACCEL, - IIO_ANGL_VEL, - IIO_MAGN, - IIO_LIGHT, - IIO_INTENSITY, - IIO_PROXIMITY, - IIO_TEMP, - IIO_INCLI, - IIO_ROT, - IIO_ANGL, - IIO_TIMESTAMP, - IIO_CAPACITANCE, -}; - -enum iio_modifier { - IIO_NO_MOD, - IIO_MOD_X, - IIO_MOD_Y, - IIO_MOD_Z, - IIO_MOD_X_AND_Y, - IIO_MOD_X_ANX_Z, - IIO_MOD_Y_AND_Z, - IIO_MOD_X_AND_Y_AND_Z, - IIO_MOD_X_OR_Y, - IIO_MOD_X_OR_Z, - IIO_MOD_Y_OR_Z, - IIO_MOD_X_OR_Y_OR_Z, - IIO_MOD_LIGHT_BOTH, - IIO_MOD_LIGHT_IR, -}; - /* Could add the raw attributes as well - allowing buffer only devices */ enum iio_chan_info_enum { IIO_CHAN_INFO_SCALE_SHARED, diff --git a/drivers/staging/iio/iio_simple_dummy.c b/drivers/staging/iio/iio_simple_dummy.c index af0c99236d4f..06c022e20943 100644 --- a/drivers/staging/iio/iio_simple_dummy.c +++ b/drivers/staging/iio/iio_simple_dummy.c @@ -21,7 +21,8 @@ #include "iio.h" #include "sysfs.h" -#include "buffer_generic.h" +#include "events.h" +#include "buffer.h" #include "iio_simple_dummy.h" /* diff --git a/drivers/staging/iio/iio_simple_dummy_events.c b/drivers/staging/iio/iio_simple_dummy_events.c index 9f00cff7ddd5..449c7a5ece80 100644 --- a/drivers/staging/iio/iio_simple_dummy_events.c +++ b/drivers/staging/iio/iio_simple_dummy_events.c @@ -14,6 +14,7 @@ #include "iio.h" #include "sysfs.h" +#include "events.h" #include "iio_simple_dummy.h" /* Evgen 'fakes' interrupt events for this example */ diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index ece770766426..430743dfe9e0 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -21,7 +21,7 @@ #include "../iio.h" #include "../sysfs.h" -#include "../buffer_generic.h" +#include "../buffer.h" #include "../ring_sw.h" #include "ad5933.h" diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c index d082a37c4fb7..e6df4921b55b 100644 --- a/drivers/staging/iio/imu/adis16400_core.c +++ b/drivers/staging/iio/imu/adis16400_core.c @@ -28,7 +28,7 @@ #include "../iio.h" #include "../sysfs.h" -#include "../buffer_generic.h" +#include "../buffer.h" #include "adis16400.h" enum adis16400_chip_variant { diff --git a/drivers/staging/iio/industrialio-buffer.c b/drivers/staging/iio/industrialio-buffer.c index ecf1e2f6d2dc..f757bb78d88e 100644 --- a/drivers/staging/iio/industrialio-buffer.c +++ b/drivers/staging/iio/industrialio-buffer.c @@ -24,7 +24,7 @@ #include "iio.h" #include "iio_core.h" #include "sysfs.h" -#include "buffer_generic.h" +#include "buffer.h" static const char * const iio_endian_prefix[] = { [IIO_BE] = "be", diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c index f5c111cb1dba..1c53b9acae81 100644 --- a/drivers/staging/iio/industrialio-core.c +++ b/drivers/staging/iio/industrialio-core.c @@ -25,8 +25,8 @@ #include "iio.h" #include "iio_core.h" #include "iio_core_trigger.h" -#include "chrdev.h" #include "sysfs.h" +#include "events.h" /* IDA to assign each registered device a unique id*/ static DEFINE_IDA(iio_ida); diff --git a/drivers/staging/iio/kfifo_buf.h b/drivers/staging/iio/kfifo_buf.h index a15598bb9fdb..cc2bd9a1ccfe 100644 --- a/drivers/staging/iio/kfifo_buf.h +++ b/drivers/staging/iio/kfifo_buf.h @@ -1,7 +1,7 @@ #include #include "iio.h" -#include "buffer_generic.h" +#include "buffer.h" extern const struct iio_buffer_access_funcs kfifo_access_funcs; diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c index 6a1794508f67..32dfce0a644f 100644 --- a/drivers/staging/iio/light/tsl2563.c +++ b/drivers/staging/iio/light/tsl2563.c @@ -37,6 +37,7 @@ #include "../iio.h" #include "../sysfs.h" +#include "../events.h" #include "tsl2563.h" /* Use this many bits for fraction part. */ diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c index c5dafbdf3bda..7028e87acb41 100644 --- a/drivers/staging/iio/meter/ade7758_core.c +++ b/drivers/staging/iio/meter/ade7758_core.c @@ -20,7 +20,7 @@ #include "../iio.h" #include "../sysfs.h" -#include "../buffer_generic.h" +#include "../buffer.h" #include "meter.h" #include "ade7758.h" diff --git a/drivers/staging/iio/ring_sw.h b/drivers/staging/iio/ring_sw.h index a3e15784c225..e6a6e2c40960 100644 --- a/drivers/staging/iio/ring_sw.h +++ b/drivers/staging/iio/ring_sw.h @@ -23,7 +23,7 @@ #ifndef _IIO_RING_SW_H_ #define _IIO_RING_SW_H_ -#include "buffer_generic.h" +#include "buffer.h" /** * ring_sw_access_funcs - access functions for a software ring buffer diff --git a/drivers/staging/iio/sysfs.h b/drivers/staging/iio/sysfs.h index 868952b5ba63..bfedb73b850e 100644 --- a/drivers/staging/iio/sysfs.h +++ b/drivers/staging/iio/sysfs.h @@ -114,47 +114,4 @@ struct iio_const_attr { #define IIO_CONST_ATTR_TEMP_SCALE(_string) \ IIO_CONST_ATTR(in_temp_scale, _string) -enum iio_event_type { - IIO_EV_TYPE_THRESH, - IIO_EV_TYPE_MAG, - IIO_EV_TYPE_ROC, - IIO_EV_TYPE_THRESH_ADAPTIVE, - IIO_EV_TYPE_MAG_ADAPTIVE, -}; - -enum iio_event_direction { - IIO_EV_DIR_EITHER, - IIO_EV_DIR_RISING, - IIO_EV_DIR_FALLING, -}; - -#define IIO_EVENT_CODE(chan_type, diff, modifier, direction, \ - type, chan, chan1, chan2) \ - (((u64)type << 56) | ((u64)diff << 55) | \ - ((u64)direction << 48) | ((u64)modifier << 40) | \ - ((u64)chan_type << 32) | (chan2 << 16) | chan1 | chan) - -#define IIO_EV_DIR_MAX 4 -#define IIO_EV_BIT(type, direction) \ - (1 << (type*IIO_EV_DIR_MAX + direction)) - -#define IIO_MOD_EVENT_CODE(channelclass, number, modifier, \ - type, direction) \ - IIO_EVENT_CODE(channelclass, 0, modifier, direction, type, number, 0, 0) - -#define IIO_UNMOD_EVENT_CODE(channelclass, number, type, direction) \ - IIO_EVENT_CODE(channelclass, 0, 0, direction, type, number, 0, 0) - -#define IIO_EVENT_CODE_EXTRACT_TYPE(mask) ((mask >> 56) & 0xFF) - -#define IIO_EVENT_CODE_EXTRACT_DIR(mask) ((mask >> 48) & 0xCF) - -#define IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(mask) ((mask >> 32) & 0xFF) - -/* Event code number extraction depends on which type of event we have. - * Perhaps review this function in the future*/ -#define IIO_EVENT_CODE_EXTRACT_NUM(mask) (mask & 0xFFFF) - -#define IIO_EVENT_CODE_EXTRACT_MODIFIER(mask) ((mask >> 40) & 0xFF) - #endif /* _INDUSTRIAL_IO_SYSFS_H_ */ diff --git a/drivers/staging/iio/types.h b/drivers/staging/iio/types.h new file mode 100644 index 000000000000..f1f5ca2aa385 --- /dev/null +++ b/drivers/staging/iio/types.h @@ -0,0 +1,49 @@ +/* industrial I/O data types needed both in and out of kernel + * + * Copyright (c) 2008 Jonathan Cameron + * + * 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. + */ + +#ifndef _IIO_TYPES_H_ +#define _IIO_TYPES_H_ + +enum iio_chan_type { + /* real channel types */ + IIO_VOLTAGE, + IIO_CURRENT, + IIO_POWER, + IIO_ACCEL, + IIO_ANGL_VEL, + IIO_MAGN, + IIO_LIGHT, + IIO_INTENSITY, + IIO_PROXIMITY, + IIO_TEMP, + IIO_INCLI, + IIO_ROT, + IIO_ANGL, + IIO_TIMESTAMP, + IIO_CAPACITANCE, +}; + +enum iio_modifier { + IIO_NO_MOD, + IIO_MOD_X, + IIO_MOD_Y, + IIO_MOD_Z, + IIO_MOD_X_AND_Y, + IIO_MOD_X_ANX_Z, + IIO_MOD_Y_AND_Z, + IIO_MOD_X_AND_Y_AND_Z, + IIO_MOD_X_OR_Y, + IIO_MOD_X_OR_Z, + IIO_MOD_Y_OR_Z, + IIO_MOD_X_OR_Y_OR_Z, + IIO_MOD_LIGHT_BOTH, + IIO_MOD_LIGHT_IR, +}; + +#endif /* _IIO_TYPES_H_ */ From 65d5ff8d519bb9f994f9376a56816d992a5b53ab Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Oct 2011 17:41:33 +0100 Subject: [PATCH 034/365] staging:iio: Use userspace types for iio_event_data Since we want to export struct iio_event_data to userspace use the userspace integer types. Also add a include to linux/types.h. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/events.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/staging/iio/events.h b/drivers/staging/iio/events.h index 08cf3d1a38bf..389c7810b66b 100644 --- a/drivers/staging/iio/events.h +++ b/drivers/staging/iio/events.h @@ -10,6 +10,7 @@ #define _IIO_EVENTS_H_ #include +#include #include "types.h" /** @@ -19,8 +20,8 @@ * the interrupt handler) */ struct iio_event_data { - u64 id; - s64 timestamp; + __u64 id; + __s64 timestamp; }; #define IIO_GET_EVENT_FD_IOCTL _IOR('i', 0x90, int) From 3014cd97e56d312865d670653adec338a8e5fc0e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Oct 2011 17:41:34 +0100 Subject: [PATCH 035/365] staging:iio: Add documentation for IIO_EVENT_CODE Document the different parameters of the IIO_EVENT_CODE macro and friends. While we are at it standardise the name of channel type parameter. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/events.h | 39 +++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/drivers/staging/iio/events.h b/drivers/staging/iio/events.h index 389c7810b66b..92759547b410 100644 --- a/drivers/staging/iio/events.h +++ b/drivers/staging/iio/events.h @@ -40,6 +40,18 @@ enum iio_event_direction { IIO_EV_DIR_FALLING, }; +/** + * IIO_EVENT_CODE() - create event identifier + * @chan_type: Type of the channel. Should be one of enum iio_chan_type. + * @diff: Whether the event is for an differential channel or not. + * @modifier: Modifier for the channel. Should be one of enum iio_modifier. + * @direction: Direction of the event. One of enum iio_event_direction. + * @type: Type of the event. Should be one enum iio_event_type. + * @chan: Channel number for non-differential channels. + * @chan1: First channel number for differential channels. + * @chan2: Second channel number for differential channels. + */ + #define IIO_EVENT_CODE(chan_type, diff, modifier, direction, \ type, chan, chan1, chan2) \ (((u64)type << 56) | ((u64)diff << 55) | \ @@ -51,12 +63,29 @@ enum iio_event_direction { #define IIO_EV_BIT(type, direction) \ (1 << (type*IIO_EV_DIR_MAX + direction)) -#define IIO_MOD_EVENT_CODE(channelclass, number, modifier, \ - type, direction) \ - IIO_EVENT_CODE(channelclass, 0, modifier, direction, type, number, 0, 0) +/** + * IIO_MOD_EVENT_CODE() - create event identifier for modified channels + * @chan_type: Type of the channel. Should be one of enum iio_chan_type. + * @number: Channel number. + * @modifier: Modifier for the channel. Should be one of enum iio_modifier. + * @type: Type of the event. Should be one enum iio_event_type. + * @direction: Direction of the event. One of enum iio_event_direction. + */ -#define IIO_UNMOD_EVENT_CODE(channelclass, number, type, direction) \ - IIO_EVENT_CODE(channelclass, 0, 0, direction, type, number, 0, 0) +#define IIO_MOD_EVENT_CODE(chan_type, number, modifier, \ + type, direction) \ + IIO_EVENT_CODE(chan_type, 0, modifier, direction, type, number, 0, 0) + +/** + * IIO_UNMOD_EVENT_CODE() - create event identifier for unmodified channels + * @chan_type: Type of the channel. Should be one of enum iio_chan_type. + * @number: Channel number. + * @type: Type of the event. Should be one enum iio_event_type. + * @direction: Direction of the event. One of enum iio_event_direction. + */ + +#define IIO_UNMOD_EVENT_CODE(chan_type, number, type, direction) \ + IIO_EVENT_CODE(chan_type, 0, 0, direction, type, number, 0, 0) #define IIO_EVENT_CODE_EXTRACT_TYPE(mask) ((mask >> 56) & 0xFF) From 924f8a21dd13223cc1493a916c6769cf73e0d45e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Oct 2011 17:41:35 +0100 Subject: [PATCH 036/365] staging:iio: Do not use bitmasks for channel info addresses Currently the iio framework uses bitmasks for the address field of channel info attributes. This is for historical reasons and no longer required since it will only ever query a single info attribute at once. This patch changes the code to use the non-shifted iio_chan_info_enum values for the info attribute address. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/accel/adis16201_core.c | 10 +++++----- drivers/staging/iio/accel/adis16203_core.c | 8 ++++---- drivers/staging/iio/accel/adis16204_core.c | 12 ++++++------ drivers/staging/iio/accel/adis16209_core.c | 10 +++++----- drivers/staging/iio/accel/adis16220_core.c | 6 +++--- drivers/staging/iio/accel/adis16240_core.c | 14 +++++++------- drivers/staging/iio/accel/kxsd9.c | 4 ++-- drivers/staging/iio/accel/lis3l02dq_core.c | 10 +++++----- drivers/staging/iio/accel/sca3000_core.c | 2 +- drivers/staging/iio/adc/ad7192.c | 6 +++--- drivers/staging/iio/adc/ad7280a.c | 2 +- drivers/staging/iio/adc/ad7291.c | 6 +++--- drivers/staging/iio/adc/ad7298_core.c | 4 ++-- drivers/staging/iio/adc/ad7476_core.c | 2 +- drivers/staging/iio/adc/ad7606_core.c | 2 +- drivers/staging/iio/adc/ad7780.c | 2 +- drivers/staging/iio/adc/ad7793.c | 6 +++--- drivers/staging/iio/adc/ad7887_core.c | 2 +- drivers/staging/iio/adc/ad799x_core.c | 2 +- drivers/staging/iio/adc/max1363_core.c | 2 +- drivers/staging/iio/cdc/ad7150.c | 2 +- drivers/staging/iio/cdc/ad7152.c | 14 +++++++------- drivers/staging/iio/cdc/ad7746.c | 14 +++++++------- drivers/staging/iio/dac/ad5064.c | 2 +- drivers/staging/iio/dac/ad5360.c | 14 +++++++------- drivers/staging/iio/dac/ad5686.c | 2 +- drivers/staging/iio/dac/ad5791.c | 4 ++-- drivers/staging/iio/gyro/adis16060_core.c | 4 ++-- drivers/staging/iio/gyro/adis16260_core.c | 14 +++++++------- drivers/staging/iio/gyro/adxrs450_core.c | 4 ++-- drivers/staging/iio/iio.h | 3 ++- drivers/staging/iio/iio_simple_dummy.c | 12 ++++++------ drivers/staging/iio/imu/adis16400_core.c | 10 +++++----- drivers/staging/iio/industrialio-core.c | 2 +- drivers/staging/iio/light/isl29018.c | 4 ++-- drivers/staging/iio/light/tsl2563.c | 2 +- drivers/staging/iio/magnetometer/ak8975.c | 2 +- drivers/staging/iio/magnetometer/hmc5843.c | 2 +- 38 files changed, 112 insertions(+), 111 deletions(-) diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c index 128351931756..f1c06027a422 100644 --- a/drivers/staging/iio/accel/adis16201_core.c +++ b/drivers/staging/iio/accel/adis16201_core.c @@ -322,8 +322,8 @@ static int adis16201_read_raw(struct iio_dev *indio_dev, *val = val16; mutex_unlock(&indio_dev->mlock); return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): - case (1 << IIO_CHAN_INFO_SCALE_SHARED): + case IIO_CHAN_INFO_SCALE_SEPARATE: + case IIO_CHAN_INFO_SCALE_SHARED: switch (chan->type) { case IIO_VOLTAGE: *val = 0; @@ -348,10 +348,10 @@ static int adis16201_read_raw(struct iio_dev *indio_dev, return -EINVAL; } break; - case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE): + case IIO_CHAN_INFO_OFFSET_SEPARATE: *val = 25; return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): + case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: switch (chan->type) { case IIO_ACCEL: bits = 12; @@ -388,7 +388,7 @@ static int adis16201_write_raw(struct iio_dev *indio_dev, s16 val16; u8 addr; switch (mask) { - case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): + case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: switch (chan->type) { case IIO_ACCEL: bits = 12; diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c index 5483b59aea32..5bf944b9ae88 100644 --- a/drivers/staging/iio/accel/adis16203_core.c +++ b/drivers/staging/iio/accel/adis16203_core.c @@ -329,8 +329,8 @@ static int adis16203_read_raw(struct iio_dev *indio_dev, *val = val16; mutex_unlock(&indio_dev->mlock); return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): - case (1 << IIO_CHAN_INFO_SCALE_SHARED): + case IIO_CHAN_INFO_SCALE_SEPARATE: + case IIO_CHAN_INFO_SCALE_SHARED: switch (chan->type) { case IIO_VOLTAGE: *val = 0; @@ -350,10 +350,10 @@ static int adis16203_read_raw(struct iio_dev *indio_dev, default: return -EINVAL; } - case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE): + case IIO_CHAN_INFO_OFFSET_SEPARATE: *val = 25; return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): + case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: bits = 14; mutex_lock(&indio_dev->mlock); addr = adis16203_addresses[chan->address][1]; diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c index 462f215f8c8d..068f543c938f 100644 --- a/drivers/staging/iio/accel/adis16204_core.c +++ b/drivers/staging/iio/accel/adis16204_core.c @@ -366,7 +366,7 @@ static int adis16204_read_raw(struct iio_dev *indio_dev, *val = val16; mutex_unlock(&indio_dev->mlock); return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): + case IIO_CHAN_INFO_SCALE_SEPARATE: switch (chan->type) { case IIO_VOLTAGE: *val = 0; @@ -390,12 +390,12 @@ static int adis16204_read_raw(struct iio_dev *indio_dev, return -EINVAL; } break; - case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE): + case IIO_CHAN_INFO_OFFSET_SEPARATE: *val = 25; return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): - case (1 << IIO_CHAN_INFO_PEAK_SEPARATE): - if (mask == (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE)) { + case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: + case IIO_CHAN_INFO_PEAK_SEPARATE: + if (mask == IIO_CHAN_INFO_CALIBBIAS_SEPARATE) { bits = 12; addrind = 1; } else { /* PEAK_SEPARATE */ @@ -428,7 +428,7 @@ static int adis16204_write_raw(struct iio_dev *indio_dev, s16 val16; u8 addr; switch (mask) { - case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): + case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: switch (chan->type) { case IIO_ACCEL: bits = 12; diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c index 827499f70af6..57540f1058a0 100644 --- a/drivers/staging/iio/accel/adis16209_core.c +++ b/drivers/staging/iio/accel/adis16209_core.c @@ -304,7 +304,7 @@ static int adis16209_write_raw(struct iio_dev *indio_dev, s16 val16; u8 addr; switch (mask) { - case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): + case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: switch (chan->type) { case IIO_ACCEL: case IIO_INCLI: @@ -355,8 +355,8 @@ static int adis16209_read_raw(struct iio_dev *indio_dev, *val = val16; mutex_unlock(&indio_dev->mlock); return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): - case (1 << IIO_CHAN_INFO_SCALE_SHARED): + case IIO_CHAN_INFO_SCALE_SEPARATE: + case IIO_CHAN_INFO_SCALE_SHARED: switch (chan->type) { case IIO_VOLTAGE: *val = 0; @@ -381,10 +381,10 @@ static int adis16209_read_raw(struct iio_dev *indio_dev, return -EINVAL; } break; - case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE): + case IIO_CHAN_INFO_OFFSET_SEPARATE: *val = 25; return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): + case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: switch (chan->type) { case IIO_ACCEL: bits = 14; diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c index 6d4503de192d..284f81078d46 100644 --- a/drivers/staging/iio/accel/adis16220_core.c +++ b/drivers/staging/iio/accel/adis16220_core.c @@ -510,17 +510,17 @@ static int adis16220_read_raw(struct iio_dev *indio_dev, case 0: addrind = 0; break; - case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE): + case IIO_CHAN_INFO_OFFSET_SEPARATE: if (chan->type == IIO_TEMP) { *val = 25; return IIO_VAL_INT; } addrind = 1; break; - case (1 << IIO_CHAN_INFO_PEAK_SEPARATE): + case IIO_CHAN_INFO_PEAK_SEPARATE: addrind = 2; break; - case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): + case IIO_CHAN_INFO_SCALE_SEPARATE: *val = 0; switch (chan->type) { case IIO_TEMP: diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c index 8123fe3bd227..482a762ef1b3 100644 --- a/drivers/staging/iio/accel/adis16240_core.c +++ b/drivers/staging/iio/accel/adis16240_core.c @@ -389,8 +389,8 @@ static int adis16240_read_raw(struct iio_dev *indio_dev, *val = val16; mutex_unlock(&indio_dev->mlock); return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): - case (1 << IIO_CHAN_INFO_SCALE_SHARED): + case IIO_CHAN_INFO_SCALE_SEPARATE: + case IIO_CHAN_INFO_SCALE_SHARED: switch (chan->type) { case IIO_VOLTAGE: *val = 0; @@ -411,14 +411,14 @@ static int adis16240_read_raw(struct iio_dev *indio_dev, return -EINVAL; } break; - case (1 << IIO_CHAN_INFO_PEAK_SCALE_SHARED): + case IIO_CHAN_INFO_PEAK_SCALE_SHARED: *val = 6; *val2 = 629295; return IIO_VAL_INT_PLUS_MICRO; - case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE): + case IIO_CHAN_INFO_OFFSET_SEPARATE: *val = 25; return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): + case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: bits = 10; mutex_lock(&indio_dev->mlock); addr = adis16240_addresses[chan->address][1]; @@ -432,7 +432,7 @@ static int adis16240_read_raw(struct iio_dev *indio_dev, *val = val16; mutex_unlock(&indio_dev->mlock); return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_PEAK_SEPARATE): + case IIO_CHAN_INFO_PEAK_SEPARATE: bits = 10; mutex_lock(&indio_dev->mlock); addr = adis16240_addresses[chan->address][2]; @@ -460,7 +460,7 @@ static int adis16240_write_raw(struct iio_dev *indio_dev, s16 val16; u8 addr; switch (mask) { - case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): + case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: val16 = val & ((1 << bits) - 1); addr = adis16240_addresses[chan->address][1]; return adis16240_spi_write_reg_16(indio_dev, addr, val16); diff --git a/drivers/staging/iio/accel/kxsd9.c b/drivers/staging/iio/accel/kxsd9.c index 5238503f6805..0ea0b5ccd593 100644 --- a/drivers/staging/iio/accel/kxsd9.c +++ b/drivers/staging/iio/accel/kxsd9.c @@ -140,7 +140,7 @@ static int kxsd9_write_raw(struct iio_dev *indio_dev, { int ret = -EINVAL; - if (mask == (1 << IIO_CHAN_INFO_SCALE_SHARED)) { + if (mask == IIO_CHAN_INFO_SCALE_SHARED) { /* Check no integer component */ if (val) return -EINVAL; @@ -164,7 +164,7 @@ static int kxsd9_read_raw(struct iio_dev *indio_dev, goto error_ret; *val = ret; break; - case (1 << IIO_CHAN_INFO_SCALE_SHARED): + case IIO_CHAN_INFO_SCALE_SHARED: ret = spi_w8r8(st->us, KXSD9_READ(KXSD9_REG_CTRL_C)); if (ret) goto error_ret; diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c index 358a9f6cbb0a..d7706ebe8090 100644 --- a/drivers/staging/iio/accel/lis3l02dq_core.c +++ b/drivers/staging/iio/accel/lis3l02dq_core.c @@ -227,14 +227,14 @@ static int lis3l02dq_write_raw(struct iio_dev *indio_dev, u8 uval; s8 sval; switch (mask) { - case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): + case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: if (val > 255 || val < -256) return -EINVAL; sval = val; reg = lis3l02dq_axis_map[LIS3L02DQ_BIAS][chan->address]; ret = lis3l02dq_spi_write_reg_8(indio_dev, reg, sval); break; - case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE): + case IIO_CHAN_INFO_CALIBSCALE_SEPARATE: if (val & ~0xFF) return -EINVAL; uval = val; @@ -272,11 +272,11 @@ static int lis3l02dq_read_raw(struct iio_dev *indio_dev, } mutex_unlock(&indio_dev->mlock); return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_SCALE_SHARED): + case IIO_CHAN_INFO_SCALE_SHARED: *val = 0; *val2 = 9580; return IIO_VAL_INT_PLUS_MICRO; - case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE): + case IIO_CHAN_INFO_CALIBSCALE_SEPARATE: reg = lis3l02dq_axis_map[LIS3L02DQ_GAIN][chan->address]; ret = lis3l02dq_spi_read_reg_8(indio_dev, reg, &utemp); if (ret) @@ -285,7 +285,7 @@ static int lis3l02dq_read_raw(struct iio_dev *indio_dev, *val = utemp; return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): + case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: reg = lis3l02dq_axis_map[LIS3L02DQ_BIAS][chan->address]; ret = lis3l02dq_spi_read_reg_8(indio_dev, reg, (u8 *)&stemp); /* to match with what previous code does */ diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c index 8a46983275bc..1586963f5653 100644 --- a/drivers/staging/iio/accel/sca3000_core.c +++ b/drivers/staging/iio/accel/sca3000_core.c @@ -475,7 +475,7 @@ static int sca3000_read_raw(struct iio_dev *indio_dev, (sizeof(*val)*8 - 13); mutex_unlock(&st->lock); return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_SCALE_SHARED): + case IIO_CHAN_INFO_SCALE_SHARED: *val = 0; if (chan->type == IIO_ACCEL) *val2 = st->info->scale; diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 39ba05db2c02..9416cedcddcb 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -901,7 +901,7 @@ static int ad7192_read_raw(struct iio_dev *indio_dev, } return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_SCALE_SHARED): + case IIO_CHAN_INFO_SCALE_SHARED: mutex_lock(&indio_dev->mlock); *val = st->scale_avail[AD7192_CONF_GAIN(st->conf)][0]; *val2 = st->scale_avail[AD7192_CONF_GAIN(st->conf)][1]; @@ -909,7 +909,7 @@ static int ad7192_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT_PLUS_NANO; - case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): + case IIO_CHAN_INFO_SCALE_SEPARATE: *val = 1000; return IIO_VAL_INT; @@ -935,7 +935,7 @@ static int ad7192_write_raw(struct iio_dev *indio_dev, } switch (mask) { - case (1 << IIO_CHAN_INFO_SCALE_SHARED): + case IIO_CHAN_INFO_SCALE_SHARED: ret = -EINVAL; for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) if (val2 == st->scale_avail[i][1]) { diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c index 8f4fac1ce7ae..7fb60c5a80e5 100644 --- a/drivers/staging/iio/adc/ad7280a.c +++ b/drivers/staging/iio/adc/ad7280a.c @@ -803,7 +803,7 @@ static int ad7280_read_raw(struct iio_dev *indio_dev, *val = ret; return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_SCALE_SHARED): + case IIO_CHAN_INFO_SCALE_SHARED: if ((chan->address & 0xFF) <= AD7280A_CELL_VOLTAGE_6) scale_uv = (4000 * 1000) >> AD7280A_BITS; else diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/staging/iio/adc/ad7291.c index e5f352bc4368..bedd91ad3fdb 100644 --- a/drivers/staging/iio/adc/ad7291.c +++ b/drivers/staging/iio/adc/ad7291.c @@ -501,7 +501,7 @@ static int ad7291_read_raw(struct iio_dev *indio_dev, default: return -EINVAL; } - case (1 << IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE): + case IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE: ret = i2c_smbus_read_word_data(chip->client, AD7291_T_AVERAGE); if (ret < 0) @@ -510,12 +510,12 @@ static int ad7291_read_raw(struct iio_dev *indio_dev, AD7291_VALUE_MASK) << 4) >> 4; *val = signval; return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_SCALE_SHARED): + case IIO_CHAN_INFO_SCALE_SHARED: scale_uv = (chip->int_vref_mv * 1000) >> AD7291_BITS; *val = scale_uv / 1000; *val2 = (scale_uv % 1000) * 1000; return IIO_VAL_INT_PLUS_MICRO; - case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): + case IIO_CHAN_INFO_SCALE_SEPARATE: /* * One LSB of the ADC corresponds to 0.25 deg C. * The temperature reading is in 12-bit twos complement format diff --git a/drivers/staging/iio/adc/ad7298_core.c b/drivers/staging/iio/adc/ad7298_core.c index 445b07116d74..2e3b0d979fc5 100644 --- a/drivers/staging/iio/adc/ad7298_core.c +++ b/drivers/staging/iio/adc/ad7298_core.c @@ -143,12 +143,12 @@ static int ad7298_read_raw(struct iio_dev *indio_dev, *val = ret & RES_MASK(AD7298_BITS); return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_SCALE_SHARED): + case IIO_CHAN_INFO_SCALE_SHARED: scale_uv = (st->int_vref_mv * 1000) >> AD7298_BITS; *val = scale_uv / 1000; *val2 = (scale_uv % 1000) * 1000; return IIO_VAL_INT_PLUS_MICRO; - case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): + case IIO_CHAN_INFO_SCALE_SEPARATE: *val = 1; *val2 = 0; return IIO_VAL_INT_PLUS_MICRO; diff --git a/drivers/staging/iio/adc/ad7476_core.c b/drivers/staging/iio/adc/ad7476_core.c index 13473133bbe2..163a2547a6f6 100644 --- a/drivers/staging/iio/adc/ad7476_core.c +++ b/drivers/staging/iio/adc/ad7476_core.c @@ -56,7 +56,7 @@ static int ad7476_read_raw(struct iio_dev *indio_dev, *val = (ret >> st->chip_info->channel[0].scan_type.shift) & RES_MASK(st->chip_info->channel[0].scan_type.realbits); return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_SCALE_SHARED): + case IIO_CHAN_INFO_SCALE_SHARED: scale_uv = (st->int_vref_mv * 1000) >> st->chip_info->channel[0].scan_type.realbits; *val = scale_uv/1000; diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c index 53174831663c..d58a0e3eee93 100644 --- a/drivers/staging/iio/adc/ad7606_core.c +++ b/drivers/staging/iio/adc/ad7606_core.c @@ -100,7 +100,7 @@ static int ad7606_read_raw(struct iio_dev *indio_dev, return ret; *val = (short) ret; return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_SCALE_SHARED): + case IIO_CHAN_INFO_SCALE_SHARED: scale_uv = (st->range * 1000 * 2) >> st->chip_info->channels[0].scan_type.realbits; *val = scale_uv / 1000; diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c index 7a579a1fd696..b06f9ad48b9a 100644 --- a/drivers/staging/iio/adc/ad7780.c +++ b/drivers/staging/iio/adc/ad7780.c @@ -114,7 +114,7 @@ static int ad7780_read_raw(struct iio_dev *indio_dev, *val *= 128; return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_SCALE_SHARED): + case IIO_CHAN_INFO_SCALE_SHARED: scale_uv = (st->int_vref_mv * 100000) >> (channel.scan_type.realbits - 1); *val = scale_uv / 100000; diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c index 17fde6669eff..c3fdfedfc994 100644 --- a/drivers/staging/iio/adc/ad7793.c +++ b/drivers/staging/iio/adc/ad7793.c @@ -667,13 +667,13 @@ static int ad7793_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_SCALE_SHARED): + case IIO_CHAN_INFO_SCALE_SHARED: *val = st->scale_avail[(st->conf >> 8) & 0x7][0]; *val2 = st->scale_avail[(st->conf >> 8) & 0x7][1]; return IIO_VAL_INT_PLUS_NANO; - case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): + case IIO_CHAN_INFO_SCALE_SEPARATE: switch (chan->type) { case IIO_VOLTAGE: /* 1170mV / 2^23 * 6 */ @@ -716,7 +716,7 @@ static int ad7793_write_raw(struct iio_dev *indio_dev, } switch (mask) { - case (1 << IIO_CHAN_INFO_SCALE_SHARED): + case IIO_CHAN_INFO_SCALE_SHARED: ret = -EINVAL; for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) if (val2 == st->scale_avail[i][1]) { diff --git a/drivers/staging/iio/adc/ad7887_core.c b/drivers/staging/iio/adc/ad7887_core.c index a7baa9bb0eaa..245c9438359b 100644 --- a/drivers/staging/iio/adc/ad7887_core.c +++ b/drivers/staging/iio/adc/ad7887_core.c @@ -55,7 +55,7 @@ static int ad7887_read_raw(struct iio_dev *indio_dev, *val = (ret >> st->chip_info->channel[0].scan_type.shift) & RES_MASK(st->chip_info->channel[0].scan_type.realbits); return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_SCALE_SHARED): + case IIO_CHAN_INFO_SCALE_SHARED: scale_uv = (st->int_vref_mv * 1000) >> st->chip_info->channel[0].scan_type.realbits; *val = scale_uv/1000; diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c index 64ac31666739..60a48a284dd1 100644 --- a/drivers/staging/iio/adc/ad799x_core.c +++ b/drivers/staging/iio/adc/ad799x_core.c @@ -162,7 +162,7 @@ static int ad799x_read_raw(struct iio_dev *indio_dev, *val = (ret >> chan->scan_type.shift) & RES_MASK(chan->scan_type.realbits); return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_SCALE_SHARED): + case IIO_CHAN_INFO_SCALE_SHARED: scale_uv = (st->int_vref_mv * 1000) >> chan->scan_type.realbits; *val = scale_uv / 1000; *val2 = (scale_uv % 1000) * 1000; diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c index 73b209f23c73..6b05e573afc7 100644 --- a/drivers/staging/iio/adc/max1363_core.c +++ b/drivers/staging/iio/adc/max1363_core.c @@ -261,7 +261,7 @@ static int max1363_read_raw(struct iio_dev *indio_dev, if (ret < 0) return ret; return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_SCALE_SHARED): + case IIO_CHAN_INFO_SCALE_SHARED: if ((1 << (st->chip_info->bits + 1)) > st->chip_info->int_vref_mv) { *val = 0; diff --git a/drivers/staging/iio/cdc/ad7150.c b/drivers/staging/iio/cdc/ad7150.c index abe65096c110..10737fae25e1 100644 --- a/drivers/staging/iio/cdc/ad7150.c +++ b/drivers/staging/iio/cdc/ad7150.c @@ -111,7 +111,7 @@ static int ad7150_read_raw(struct iio_dev *indio_dev, return ret; *val = swab16(ret); return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE): + case IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE: ret = i2c_smbus_read_word_data(chip->client, ad7150_addresses[chan->channel][1]); if (ret < 0) diff --git a/drivers/staging/iio/cdc/ad7152.c b/drivers/staging/iio/cdc/ad7152.c index 662584d72a74..e5ca683a7af0 100644 --- a/drivers/staging/iio/cdc/ad7152.c +++ b/drivers/staging/iio/cdc/ad7152.c @@ -259,7 +259,7 @@ static int ad7152_write_raw(struct iio_dev *indio_dev, mutex_lock(&indio_dev->mlock); switch (mask) { - case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE): + case IIO_CHAN_INFO_CALIBSCALE_SEPARATE: if (val != 1) { ret = -EINVAL; goto out; @@ -276,7 +276,7 @@ static int ad7152_write_raw(struct iio_dev *indio_dev, ret = 0; break; - case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): + case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: if ((val < 0) | (val > 0xFFFF)) { ret = -EINVAL; goto out; @@ -289,7 +289,7 @@ static int ad7152_write_raw(struct iio_dev *indio_dev, ret = 0; break; - case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): + case IIO_CHAN_INFO_SCALE_SEPARATE: if (val != 0) { ret = -EINVAL; goto out; @@ -372,7 +372,7 @@ static int ad7152_read_raw(struct iio_dev *indio_dev, ret = IIO_VAL_INT; break; - case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE): + case IIO_CHAN_INFO_CALIBSCALE_SEPARATE: ret = i2c_smbus_read_word_data(chip->client, ad7152_addresses[chan->channel][AD7152_GAIN]); @@ -384,7 +384,7 @@ static int ad7152_read_raw(struct iio_dev *indio_dev, ret = IIO_VAL_INT_PLUS_MICRO; break; - case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): + case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: ret = i2c_smbus_read_word_data(chip->client, ad7152_addresses[chan->channel][AD7152_OFFS]); if (ret < 0) @@ -393,7 +393,7 @@ static int ad7152_read_raw(struct iio_dev *indio_dev, ret = IIO_VAL_INT; break; - case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): + case IIO_CHAN_INFO_SCALE_SEPARATE: ret = i2c_smbus_read_byte_data(chip->client, ad7152_addresses[chan->channel][AD7152_SETUP]); if (ret < 0) @@ -416,7 +416,7 @@ static int ad7152_write_raw_get_fmt(struct iio_dev *indio_dev, long mask) { switch (mask) { - case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): + case IIO_CHAN_INFO_SCALE_SEPARATE: return IIO_VAL_INT_PLUS_NANO; default: return IIO_VAL_INT_PLUS_MICRO; diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c index 2867943309cc..5deaf857d23c 100644 --- a/drivers/staging/iio/cdc/ad7746.c +++ b/drivers/staging/iio/cdc/ad7746.c @@ -477,7 +477,7 @@ static int ad7746_write_raw(struct iio_dev *indio_dev, mutex_lock(&indio_dev->mlock); switch (mask) { - case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE): + case IIO_CHAN_INFO_CALIBSCALE_SEPARATE: if (val != 1) { ret = -EINVAL; goto out; @@ -503,7 +503,7 @@ static int ad7746_write_raw(struct iio_dev *indio_dev, ret = 0; break; - case (1 << IIO_CHAN_INFO_CALIBBIAS_SHARED): + case IIO_CHAN_INFO_CALIBBIAS_SHARED: if ((val < 0) | (val > 0xFFFF)) { ret = -EINVAL; goto out; @@ -515,7 +515,7 @@ static int ad7746_write_raw(struct iio_dev *indio_dev, ret = 0; break; - case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE): + case IIO_CHAN_INFO_OFFSET_SEPARATE: if ((val < 0) | (val > 43008000)) { /* 21pF */ ret = -EINVAL; goto out; @@ -612,7 +612,7 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, ret = IIO_VAL_INT; break; - case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE): + case IIO_CHAN_INFO_CALIBSCALE_SEPARATE: switch (chan->type) { case IIO_CAPACITANCE: reg = AD7746_REG_CAP_GAINH; @@ -634,7 +634,7 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, ret = IIO_VAL_INT_PLUS_MICRO; break; - case (1 << IIO_CHAN_INFO_CALIBBIAS_SHARED): + case IIO_CHAN_INFO_CALIBBIAS_SHARED: ret = i2c_smbus_read_word_data(chip->client, AD7746_REG_CAP_OFFH); if (ret < 0) @@ -643,13 +643,13 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, ret = IIO_VAL_INT; break; - case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE): + case IIO_CHAN_INFO_OFFSET_SEPARATE: *val = AD7746_CAPDAC_DACP(chip->capdac[chan->channel] [chan->differential]) * 338646; ret = IIO_VAL_INT; break; - case (1 << IIO_CHAN_INFO_SCALE_SHARED): + case IIO_CHAN_INFO_SCALE_SHARED: switch (chan->type) { case IIO_CAPACITANCE: /* 8.192pf / 2^24 */ diff --git a/drivers/staging/iio/dac/ad5064.c b/drivers/staging/iio/dac/ad5064.c index 24279f2ae41f..1c25403620ff 100644 --- a/drivers/staging/iio/dac/ad5064.c +++ b/drivers/staging/iio/dac/ad5064.c @@ -287,7 +287,7 @@ static int ad5064_read_raw(struct iio_dev *indio_dev, case 0: *val = st->dac_cache[chan->channel]; return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): + case IIO_CHAN_INFO_SCALE_SEPARATE: vref = st->chip_info->shared_vref ? 0 : chan->channel; scale_uv = regulator_get_voltage(st->vref_reg[vref].consumer); if (scale_uv < 0) diff --git a/drivers/staging/iio/dac/ad5360.c b/drivers/staging/iio/dac/ad5360.c index 72d0f3f0d6ae..7df19586d182 100644 --- a/drivers/staging/iio/dac/ad5360.c +++ b/drivers/staging/iio/dac/ad5360.c @@ -326,21 +326,21 @@ static int ad5360_write_raw(struct iio_dev *indio_dev, return ad5360_write(indio_dev, AD5360_CMD_WRITE_DATA, chan->address, val, chan->scan_type.shift); - case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): + case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: if (val >= max_val || val < 0) return -EINVAL; return ad5360_write(indio_dev, AD5360_CMD_WRITE_OFFSET, chan->address, val, chan->scan_type.shift); - case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE): + case IIO_CHAN_INFO_CALIBSCALE_SEPARATE: if (val >= max_val || val < 0) return -EINVAL; return ad5360_write(indio_dev, AD5360_CMD_WRITE_GAIN, chan->address, val, chan->scan_type.shift); - case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE): + case IIO_CHAN_INFO_OFFSET_SEPARATE: if (val <= -max_val || val > 0) return -EINVAL; @@ -383,7 +383,7 @@ static int ad5360_read_raw(struct iio_dev *indio_dev, return ret; *val = ret >> chan->scan_type.shift; return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): + case IIO_CHAN_INFO_SCALE_SEPARATE: /* vout = 4 * vref * dac_code */ scale_uv = ad5360_get_channel_vref(st, chan->channel) * 4 * 100; if (scale_uv < 0) @@ -393,21 +393,21 @@ static int ad5360_read_raw(struct iio_dev *indio_dev, *val = scale_uv / 100000; *val2 = (scale_uv % 100000) * 10; return IIO_VAL_INT_PLUS_MICRO; - case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): + case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: ret = ad5360_read(indio_dev, AD5360_READBACK_OFFSET, chan->address); if (ret < 0) return ret; *val = ret; return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE): + case IIO_CHAN_INFO_CALIBSCALE_SEPARATE: ret = ad5360_read(indio_dev, AD5360_READBACK_GAIN, chan->address); if (ret < 0) return ret; *val = ret; return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE): + case IIO_CHAN_INFO_OFFSET_SEPARATE: ofs_index = ad5360_get_channel_vref_index(st, chan->channel); ret = ad5360_read(indio_dev, AD5360_READBACK_SF, AD5360_REG_SF_OFS(ofs_index)); diff --git a/drivers/staging/iio/dac/ad5686.c b/drivers/staging/iio/dac/ad5686.c index 974c6f5b60c4..f2332b3f24a7 100644 --- a/drivers/staging/iio/dac/ad5686.c +++ b/drivers/staging/iio/dac/ad5686.c @@ -306,7 +306,7 @@ static int ad5686_read_raw(struct iio_dev *indio_dev, *val = ret; return IIO_VAL_INT; break; - case (1 << IIO_CHAN_INFO_SCALE_SHARED): + case IIO_CHAN_INFO_SCALE_SHARED: scale_uv = (st->vref_mv * 100000) >> (chan->scan_type.realbits); *val = scale_uv / 100000; diff --git a/drivers/staging/iio/dac/ad5791.c b/drivers/staging/iio/dac/ad5791.c index 6fbca8d96153..d3b3b71c87c1 100644 --- a/drivers/staging/iio/dac/ad5791.c +++ b/drivers/staging/iio/dac/ad5791.c @@ -237,11 +237,11 @@ static int ad5791_read_raw(struct iio_dev *indio_dev, *val &= AD5791_DAC_MASK; *val >>= chan->scan_type.shift; return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_SCALE_SHARED): + case IIO_CHAN_INFO_SCALE_SHARED: *val = 0; *val2 = (((u64)st->vref_mv) * 1000000ULL) >> chan->scan_type.realbits; return IIO_VAL_INT_PLUS_MICRO; - case (1 << IIO_CHAN_INFO_OFFSET_SHARED): + case IIO_CHAN_INFO_OFFSET_SHARED: val64 = (((u64)st->vref_neg_mv) << chan->scan_type.realbits); do_div(val64, st->vref_mv); *val = -val64; diff --git a/drivers/staging/iio/gyro/adis16060_core.c b/drivers/staging/iio/gyro/adis16060_core.c index ff1b5a82b3d6..d83c640f4e6b 100644 --- a/drivers/staging/iio/gyro/adis16060_core.c +++ b/drivers/staging/iio/gyro/adis16060_core.c @@ -98,11 +98,11 @@ static int adis16060_read_raw(struct iio_dev *indio_dev, mutex_unlock(&indio_dev->mlock); *val = tval; return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE): + case IIO_CHAN_INFO_OFFSET_SEPARATE: *val = -7; *val2 = 461117; return IIO_VAL_INT_PLUS_MICRO; - case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): + case IIO_CHAN_INFO_SCALE_SEPARATE: *val = 0; *val2 = 34000; return IIO_VAL_INT_PLUS_MICRO; diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c index 40da95554fa2..4f5a7cb3f7e9 100644 --- a/drivers/staging/iio/gyro/adis16260_core.c +++ b/drivers/staging/iio/gyro/adis16260_core.c @@ -464,8 +464,8 @@ static int adis16260_read_raw(struct iio_dev *indio_dev, *val = val16; mutex_unlock(&indio_dev->mlock); return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): - case (1 << IIO_CHAN_INFO_SCALE_SHARED): + case IIO_CHAN_INFO_SCALE_SEPARATE: + case IIO_CHAN_INFO_SCALE_SHARED: switch (chan->type) { case IIO_ANGL_VEL: *val = 0; @@ -489,10 +489,10 @@ static int adis16260_read_raw(struct iio_dev *indio_dev, return -EINVAL; } break; - case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE): + case IIO_CHAN_INFO_OFFSET_SEPARATE: *val = 25; return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): + case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: switch (chan->type) { case IIO_ANGL_VEL: bits = 12; @@ -512,7 +512,7 @@ static int adis16260_read_raw(struct iio_dev *indio_dev, *val = val16; mutex_unlock(&indio_dev->mlock); return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE): + case IIO_CHAN_INFO_CALIBSCALE_SEPARATE: switch (chan->type) { case IIO_ANGL_VEL: bits = 12; @@ -544,11 +544,11 @@ static int adis16260_write_raw(struct iio_dev *indio_dev, s16 val16; u8 addr; switch (mask) { - case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): + case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: val16 = val & ((1 << bits) - 1); addr = adis16260_addresses[chan->address][1]; return adis16260_spi_write_reg_16(indio_dev, addr, val16); - case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE): + case IIO_CHAN_INFO_CALIBSCALE_SEPARATE: val16 = val & ((1 << bits) - 1); addr = adis16260_addresses[chan->address][2]; return adis16260_spi_write_reg_16(indio_dev, addr, val16); diff --git a/drivers/staging/iio/gyro/adxrs450_core.c b/drivers/staging/iio/gyro/adxrs450_core.c index 3c3ef796d48e..18406c7f960f 100644 --- a/drivers/staging/iio/gyro/adxrs450_core.c +++ b/drivers/staging/iio/gyro/adxrs450_core.c @@ -243,7 +243,7 @@ static int adxrs450_write_raw(struct iio_dev *indio_dev, { int ret; switch (mask) { - case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): + case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: ret = adxrs450_spi_write_reg_16(indio_dev, ADXRS450_DNC1, val & 0x3FF); @@ -287,7 +287,7 @@ static int adxrs450_read_raw(struct iio_dev *indio_dev, break; } break; - case (1 << IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE): + case IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE: ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_QUAD1, &t); if (ret) break; diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h index cf95f74dc9db..4fb4cc42399b 100644 --- a/drivers/staging/iio/iio.h +++ b/drivers/staging/iio/iio.h @@ -26,7 +26,8 @@ enum iio_data_type { /* Could add the raw attributes as well - allowing buffer only devices */ enum iio_chan_info_enum { - IIO_CHAN_INFO_SCALE_SHARED, + /* 0 is reserverd for raw attributes */ + IIO_CHAN_INFO_SCALE_SHARED = 2, IIO_CHAN_INFO_SCALE_SEPARATE, IIO_CHAN_INFO_OFFSET_SHARED, IIO_CHAN_INFO_OFFSET_SEPARATE, diff --git a/drivers/staging/iio/iio_simple_dummy.c b/drivers/staging/iio/iio_simple_dummy.c index 06c022e20943..2196ff19f7b4 100644 --- a/drivers/staging/iio/iio_simple_dummy.c +++ b/drivers/staging/iio/iio_simple_dummy.c @@ -229,29 +229,29 @@ static int iio_dummy_read_raw(struct iio_dev *indio_dev, break; } break; - case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE): + case IIO_CHAN_INFO_OFFSET_SEPARATE: /* only single ended adc -> 7 */ *val = 7; ret = IIO_VAL_INT; break; - case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): + case IIO_CHAN_INFO_SCALE_SEPARATE: /* only single ended adc -> 0.001333 */ *val = 0; *val2 = 1333; ret = IIO_VAL_INT_PLUS_MICRO; break; - case (1 << IIO_CHAN_INFO_SCALE_SHARED): + case IIO_CHAN_INFO_SCALE_SHARED: /* all differential adc channels -> 0.000001344 */ *val = 0; *val2 = 1344; ret = IIO_VAL_INT_PLUS_NANO; break; - case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): + case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: /* only the acceleration axis - read from cache */ *val = st->accel_calibbias; ret = IIO_VAL_INT; break; - case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE): + case IIO_CHAN_INFO_CALIBSCALE_SEPARATE: *val = st->accel_calibscale->val; *val2 = st->accel_calibscale->val2; ret = IIO_VAL_INT_PLUS_MICRO; @@ -296,7 +296,7 @@ static int iio_dummy_write_raw(struct iio_dev *indio_dev, st->dac_val = val; mutex_unlock(&st->lock); return 0; - case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): + case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: mutex_lock(&st->lock); /* Compare against table - hard matching here */ for (i = 0; i < ARRAY_SIZE(dummy_scales); i++) diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c index e6df4921b55b..0018272625c3 100644 --- a/drivers/staging/iio/imu/adis16400_core.c +++ b/drivers/staging/iio/imu/adis16400_core.c @@ -464,7 +464,7 @@ static int adis16400_write_raw(struct iio_dev *indio_dev, int ret; switch (mask) { - case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): + case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: mutex_lock(&indio_dev->mlock); ret = adis16400_spi_write_reg_16(indio_dev, adis16400_addresses[chan->address][1], @@ -504,8 +504,8 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, *val = val16; mutex_unlock(&indio_dev->mlock); return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_SCALE_SHARED): - case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): + case IIO_CHAN_INFO_SCALE_SHARED: + case IIO_CHAN_INFO_SCALE_SEPARATE: switch (chan->type) { case IIO_ANGL_VEL: *val = 0; @@ -533,7 +533,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, default: return -EINVAL; } - case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE): + case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: mutex_lock(&indio_dev->mlock); ret = adis16400_spi_read_reg_16(indio_dev, adis16400_addresses[chan->address][1], @@ -544,7 +544,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, val16 = ((val16 & 0xFFF) << 4) >> 4; *val = val16; return IIO_VAL_INT; - case (1 << IIO_CHAN_INFO_OFFSET_SEPARATE): + case IIO_CHAN_INFO_OFFSET_SEPARATE: /* currently only temperature */ *val = 198; *val2 = 160000; diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c index 1c53b9acae81..63681a61d5ca 100644 --- a/drivers/staging/iio/industrialio-core.c +++ b/drivers/staging/iio/industrialio-core.c @@ -603,7 +603,7 @@ static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev, chan, &iio_read_channel_info, &iio_write_channel_info, - (1 << i), + i, !(i%2), &indio_dev->dev, &indio_dev->channel_attr_list); diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index 9dc9e6358394..bed18a74d30c 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -362,7 +362,7 @@ static int isl29018_write_raw(struct iio_dev *indio_dev, int ret = -EINVAL; mutex_lock(&chip->lock); - if (mask == (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) && + if (mask == IIO_CHAN_INFO_CALIBSCALE_SEPARATE && chan->type == IIO_LIGHT) { chip->lux_scale = val; ret = 0; @@ -402,7 +402,7 @@ static int isl29018_read_raw(struct iio_dev *indio_dev, if (!ret) ret = IIO_VAL_INT; break; - case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE): + case IIO_CHAN_INFO_CALIBSCALE_SEPARATE: if (chan->type == IIO_LIGHT) { *val = chip->lux_scale; ret = IIO_VAL_INT; diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c index 32dfce0a644f..45d04a1b1940 100644 --- a/drivers/staging/iio/light/tsl2563.c +++ b/drivers/staging/iio/light/tsl2563.c @@ -513,7 +513,7 @@ static int tsl2563_read_raw(struct iio_dev *indio_dev, } break; - case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE): + case IIO_CHAN_INFO_CALIBSCALE_SEPARATE: if (chan->channel == 0) *val = calib_to_sysfs(chip->calib0); else diff --git a/drivers/staging/iio/magnetometer/ak8975.c b/drivers/staging/iio/magnetometer/ak8975.c index 8b017127fd4d..b7d8cbb58c37 100644 --- a/drivers/staging/iio/magnetometer/ak8975.c +++ b/drivers/staging/iio/magnetometer/ak8975.c @@ -431,7 +431,7 @@ static int ak8975_read_raw(struct iio_dev *indio_dev, switch (mask) { case 0: return ak8975_read_axis(indio_dev, chan->address, val); - case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): + case IIO_CHAN_INFO_SCALE_SEPARATE: *val = data->raw_to_gauss[chan->address]; return IIO_VAL_INT; } diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c index fc9ee970888d..4a42707a20ef 100644 --- a/drivers/staging/iio/magnetometer/hmc5843.c +++ b/drivers/staging/iio/magnetometer/hmc5843.c @@ -463,7 +463,7 @@ static int hmc5843_read_raw(struct iio_dev *indio_dev, return hmc5843_read_measurement(indio_dev, chan->address, val); - case (1 << IIO_CHAN_INFO_SCALE_SHARED): + case IIO_CHAN_INFO_SCALE_SHARED: *val = 0; *val2 = hmc5843_regval_to_nanoscale[data->range]; return IIO_VAL_INT_PLUS_NANO; From c8a9f8056f40f6201b84fdddb49a1c62630902c5 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 26 Oct 2011 17:41:36 +0100 Subject: [PATCH 037/365] staging:iio:treewide only use shared to decide on interfaces Internally the fact that say scale is shared across channels is actually of remarkably little interest. Hence lets not store it. Numerous devices have weird combinations of channels sharing scale anyway so it is not as though this was really telling us much. Note however that we do still use the shared sysfs attrs thus massively reducing the number of attrs in complex drivers. Side effect is that certain drivers that were abusing this (mostly my work) needed to do a few more checks on what the channel they are being queried on actually is. This is also helpful for in kernel interfaces where we just want to query the scale and don't care whether it is shared with other channels or not. Signed-off-by: Jonathan Cameron Acked-by: Lars-Peter Clausen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/accel/adis16201_core.c | 33 ++-- drivers/staging/iio/accel/adis16203_core.c | 21 ++- drivers/staging/iio/accel/adis16204_core.c | 32 ++-- drivers/staging/iio/accel/adis16209_core.c | 29 ++-- drivers/staging/iio/accel/adis16220_core.c | 22 +-- drivers/staging/iio/accel/adis16240_core.c | 29 ++-- drivers/staging/iio/accel/kxsd9.c | 6 +- drivers/staging/iio/accel/lis3l02dq_core.c | 16 +- drivers/staging/iio/accel/sca3000_core.c | 4 +- drivers/staging/iio/adc/ad7192.c | 34 +++-- drivers/staging/iio/adc/ad7280a.c | 6 +- drivers/staging/iio/adc/ad7291.c | 38 +++-- drivers/staging/iio/adc/ad7298_core.c | 41 ++--- drivers/staging/iio/adc/ad7476_core.c | 18 +-- drivers/staging/iio/adc/ad7606_core.c | 2 +- drivers/staging/iio/adc/ad7780.c | 6 +- drivers/staging/iio/adc/ad7793.c | 50 +++--- drivers/staging/iio/adc/ad7887_core.c | 6 +- drivers/staging/iio/adc/ad799x_core.c | 2 +- drivers/staging/iio/adc/max1363_core.c | 4 +- drivers/staging/iio/cdc/ad7150.c | 6 +- drivers/staging/iio/cdc/ad7152.c | 38 ++--- drivers/staging/iio/cdc/ad7746.c | 50 +++--- drivers/staging/iio/dac/ad5064.c | 4 +- drivers/staging/iio/dac/ad5360.c | 22 +-- drivers/staging/iio/dac/ad5686.c | 4 +- drivers/staging/iio/dac/ad5791.c | 8 +- drivers/staging/iio/gyro/adis16060_core.c | 8 +- drivers/staging/iio/gyro/adis16260_core.c | 27 ++-- drivers/staging/iio/gyro/adxrs450_core.c | 8 +- drivers/staging/iio/iio.h | 62 ++++++-- drivers/staging/iio/iio_simple_dummy.c | 43 +++--- .../staging/iio/impedance-analyzer/ad5933.c | 4 +- drivers/staging/iio/imu/adis16400_core.c | 143 +++++++++--------- drivers/staging/iio/industrialio-core.c | 19 ++- drivers/staging/iio/light/isl29018.c | 7 +- drivers/staging/iio/light/tsl2563.c | 6 +- drivers/staging/iio/magnetometer/ak8975.c | 4 +- drivers/staging/iio/magnetometer/hmc5843.c | 4 +- drivers/staging/iio/meter/ade7758_core.c | 30 ++-- 40 files changed, 468 insertions(+), 428 deletions(-) diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c index f1c06027a422..d3d877fc5dc7 100644 --- a/drivers/staging/iio/accel/adis16201_core.c +++ b/drivers/staging/iio/accel/adis16201_core.c @@ -322,8 +322,7 @@ static int adis16201_read_raw(struct iio_dev *indio_dev, *val = val16; mutex_unlock(&indio_dev->mlock); return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE_SEPARATE: - case IIO_CHAN_INFO_SCALE_SHARED: + case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_VOLTAGE: *val = 0; @@ -348,10 +347,10 @@ static int adis16201_read_raw(struct iio_dev *indio_dev, return -EINVAL; } break; - case IIO_CHAN_INFO_OFFSET_SEPARATE: + case IIO_CHAN_INFO_OFFSET: *val = 25; return IIO_VAL_INT; - case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: + case IIO_CHAN_INFO_CALIBBIAS: switch (chan->type) { case IIO_ACCEL: bits = 12; @@ -388,7 +387,7 @@ static int adis16201_write_raw(struct iio_dev *indio_dev, s16 val16; u8 addr; switch (mask) { - case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: + case IIO_CHAN_INFO_CALIBBIAS: switch (chan->type) { case IIO_ACCEL: bits = 12; @@ -408,36 +407,36 @@ static int adis16201_write_raw(struct iio_dev *indio_dev, static struct iio_chan_spec adis16201_channels[] = { IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "supply", 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, in_supply, ADIS16201_SCAN_SUPPLY, IIO_ST('u', 12, 16, 0), 0), IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE) | - (1 << IIO_CHAN_INFO_OFFSET_SEPARATE), + IIO_CHAN_INFO_SCALE_SEPARATE_BIT | + IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, temp, ADIS16201_SCAN_TEMP, IIO_ST('u', 12, 16, 0), 0), IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X, - (1 << IIO_CHAN_INFO_SCALE_SHARED) | - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE), + IIO_CHAN_INFO_SCALE_SHARED_BIT | + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, accel_x, ADIS16201_SCAN_ACC_X, IIO_ST('s', 14, 16, 0), 0), IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y, - (1 << IIO_CHAN_INFO_SCALE_SHARED) | - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE), + IIO_CHAN_INFO_SCALE_SHARED_BIT | + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, accel_y, ADIS16201_SCAN_ACC_Y, IIO_ST('s', 14, 16, 0), 0), IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, in_aux, ADIS16201_SCAN_AUX_ADC, IIO_ST('u', 12, 16, 0), 0), IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_X, - (1 << IIO_CHAN_INFO_SCALE_SHARED) | - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE), + IIO_CHAN_INFO_SCALE_SHARED_BIT | + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, incli_x, ADIS16201_SCAN_INCLI_X, IIO_ST('s', 14, 16, 0), 0), IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_Y, - (1 << IIO_CHAN_INFO_SCALE_SHARED) | - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE), + IIO_CHAN_INFO_SCALE_SHARED_BIT | + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, incli_y, ADIS16201_SCAN_INCLI_Y, IIO_ST('s', 14, 16, 0), 0), IIO_CHAN_SOFT_TIMESTAMP(7) diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c index 5bf944b9ae88..bdc44feaa123 100644 --- a/drivers/staging/iio/accel/adis16203_core.c +++ b/drivers/staging/iio/accel/adis16203_core.c @@ -329,8 +329,7 @@ static int adis16203_read_raw(struct iio_dev *indio_dev, *val = val16; mutex_unlock(&indio_dev->mlock); return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE_SEPARATE: - case IIO_CHAN_INFO_SCALE_SHARED: + case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_VOLTAGE: *val = 0; @@ -350,10 +349,10 @@ static int adis16203_read_raw(struct iio_dev *indio_dev, default: return -EINVAL; } - case IIO_CHAN_INFO_OFFSET_SEPARATE: + case IIO_CHAN_INFO_OFFSET: *val = 25; return IIO_VAL_INT; - case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: + case IIO_CHAN_INFO_CALIBBIAS: bits = 14; mutex_lock(&indio_dev->mlock); addr = adis16203_addresses[chan->address][1]; @@ -374,26 +373,26 @@ static int adis16203_read_raw(struct iio_dev *indio_dev, static struct iio_chan_spec adis16203_channels[] = { IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "supply", 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, in_supply, ADIS16203_SCAN_SUPPLY, IIO_ST('u', 12, 16, 0), 0), IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, in_aux, ADIS16203_SCAN_AUX_ADC, IIO_ST('u', 12, 16, 0), 0), IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_X, - (1 << IIO_CHAN_INFO_SCALE_SHARED) | - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE), + IIO_CHAN_INFO_SCALE_SHARED_BIT | + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, incli_x, ADIS16203_SCAN_INCLI_X, IIO_ST('s', 14, 16, 0), 0), /* Fixme: Not what it appears to be - see data sheet */ IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_Y, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, incli_y, ADIS16203_SCAN_INCLI_Y, IIO_ST('s', 14, 16, 0), 0), IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE) | - (1 << IIO_CHAN_INFO_OFFSET_SEPARATE), + IIO_CHAN_INFO_SCALE_SEPARATE_BIT | + IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, temp, ADIS16203_SCAN_TEMP, IIO_ST('u', 12, 16, 0), 0), IIO_CHAN_SOFT_TIMESTAMP(5), diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c index 068f543c938f..96d8c7b3722e 100644 --- a/drivers/staging/iio/accel/adis16204_core.c +++ b/drivers/staging/iio/accel/adis16204_core.c @@ -366,7 +366,7 @@ static int adis16204_read_raw(struct iio_dev *indio_dev, *val = val16; mutex_unlock(&indio_dev->mlock); return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE_SEPARATE: + case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_VOLTAGE: *val = 0; @@ -390,12 +390,12 @@ static int adis16204_read_raw(struct iio_dev *indio_dev, return -EINVAL; } break; - case IIO_CHAN_INFO_OFFSET_SEPARATE: + case IIO_CHAN_INFO_OFFSET: *val = 25; return IIO_VAL_INT; - case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: - case IIO_CHAN_INFO_PEAK_SEPARATE: - if (mask == IIO_CHAN_INFO_CALIBBIAS_SEPARATE) { + case IIO_CHAN_INFO_CALIBBIAS: + case IIO_CHAN_INFO_PEAK: + if (mask == IIO_CHAN_INFO_CALIBBIAS) { bits = 12; addrind = 1; } else { /* PEAK_SEPARATE */ @@ -428,7 +428,7 @@ static int adis16204_write_raw(struct iio_dev *indio_dev, s16 val16; u8 addr; switch (mask) { - case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: + case IIO_CHAN_INFO_CALIBBIAS: switch (chan->type) { case IIO_ACCEL: bits = 12; @@ -445,28 +445,28 @@ static int adis16204_write_raw(struct iio_dev *indio_dev, static struct iio_chan_spec adis16204_channels[] = { IIO_CHAN(IIO_VOLTAGE, 0, 0, 0, "supply", 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, in_supply, ADIS16204_SCAN_SUPPLY, IIO_ST('u', 12, 16, 0), 0), IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, in_aux, ADIS16204_SCAN_AUX_ADC, IIO_ST('u', 12, 16, 0), 0), IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE) | - (1 << IIO_CHAN_INFO_OFFSET_SEPARATE), + IIO_CHAN_INFO_SCALE_SEPARATE_BIT | + IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, temp, ADIS16204_SCAN_TEMP, IIO_ST('u', 12, 16, 0), 0), IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE) | - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_PEAK_SEPARATE), + IIO_CHAN_INFO_SCALE_SEPARATE_BIT | + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_PEAK_SEPARATE_BIT, accel_x, ADIS16204_SCAN_ACC_X, IIO_ST('s', 14, 16, 0), 0), IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE) | - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_PEAK_SEPARATE), + IIO_CHAN_INFO_SCALE_SEPARATE_BIT | + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_PEAK_SEPARATE_BIT, accel_y, ADIS16204_SCAN_ACC_Y, IIO_ST('s', 14, 16, 0), 0), IIO_CHAN_SOFT_TIMESTAMP(5), diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c index 57540f1058a0..62e6bd8101c4 100644 --- a/drivers/staging/iio/accel/adis16209_core.c +++ b/drivers/staging/iio/accel/adis16209_core.c @@ -304,7 +304,7 @@ static int adis16209_write_raw(struct iio_dev *indio_dev, s16 val16; u8 addr; switch (mask) { - case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: + case IIO_CHAN_INFO_CALIBBIAS: switch (chan->type) { case IIO_ACCEL: case IIO_INCLI: @@ -355,8 +355,7 @@ static int adis16209_read_raw(struct iio_dev *indio_dev, *val = val16; mutex_unlock(&indio_dev->mlock); return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE_SEPARATE: - case IIO_CHAN_INFO_SCALE_SHARED: + case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_VOLTAGE: *val = 0; @@ -381,10 +380,10 @@ static int adis16209_read_raw(struct iio_dev *indio_dev, return -EINVAL; } break; - case IIO_CHAN_INFO_OFFSET_SEPARATE: + case IIO_CHAN_INFO_OFFSET: *val = 25; return IIO_VAL_INT; - case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: + case IIO_CHAN_INFO_CALIBBIAS: switch (chan->type) { case IIO_ACCEL: bits = 14; @@ -410,34 +409,34 @@ static int adis16209_read_raw(struct iio_dev *indio_dev, static struct iio_chan_spec adis16209_channels[] = { IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, in_supply, ADIS16209_SCAN_SUPPLY, IIO_ST('u', 14, 16, 0), 0), IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE) | - (1 << IIO_CHAN_INFO_OFFSET_SEPARATE), + IIO_CHAN_INFO_SCALE_SEPARATE_BIT | + IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, temp, ADIS16209_SCAN_TEMP, IIO_ST('u', 12, 16, 0), 0), IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X, - (1 << IIO_CHAN_INFO_SCALE_SHARED) | - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE), + IIO_CHAN_INFO_SCALE_SHARED_BIT | + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, accel_x, ADIS16209_SCAN_ACC_X, IIO_ST('s', 14, 16, 0), 0), IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y, - (1 << IIO_CHAN_INFO_SCALE_SHARED) | - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE), + IIO_CHAN_INFO_SCALE_SHARED_BIT | + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, accel_y, ADIS16209_SCAN_ACC_Y, IIO_ST('s', 14, 16, 0), 0), IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, in_aux, ADIS16209_SCAN_AUX_ADC, IIO_ST('u', 12, 16, 0), 0), IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_X, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, incli_x, ADIS16209_SCAN_INCLI_X, IIO_ST('s', 14, 16, 0), 0), IIO_CHAN(IIO_INCLI, 1, 0, 0, NULL, 0, IIO_MOD_Y, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, incli_y, ADIS16209_SCAN_INCLI_Y, IIO_ST('s', 14, 16, 0), 0), IIO_CHAN(IIO_ROT, 0, 1, 0, NULL, 0, IIO_MOD_X, diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c index 284f81078d46..ca18f729b5ca 100644 --- a/drivers/staging/iio/accel/adis16220_core.c +++ b/drivers/staging/iio/accel/adis16220_core.c @@ -510,17 +510,17 @@ static int adis16220_read_raw(struct iio_dev *indio_dev, case 0: addrind = 0; break; - case IIO_CHAN_INFO_OFFSET_SEPARATE: + case IIO_CHAN_INFO_OFFSET: if (chan->type == IIO_TEMP) { *val = 25; return IIO_VAL_INT; } addrind = 1; break; - case IIO_CHAN_INFO_PEAK_SEPARATE: + case IIO_CHAN_INFO_PEAK: addrind = 2; break; - case IIO_CHAN_INFO_SCALE_SEPARATE: + case IIO_CHAN_INFO_SCALE: *val = 0; switch (chan->type) { case IIO_TEMP: @@ -575,27 +575,27 @@ static const struct iio_chan_spec adis16220_channels[] = { .indexed = 1, .channel = 0, .extend_name = "supply", - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, .address = in_supply, }, { .type = IIO_ACCEL, - .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SEPARATE) | - (1 << IIO_CHAN_INFO_PEAK_SEPARATE), + .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SEPARATE_BIT | + IIO_CHAN_INFO_PEAK_SEPARATE_BIT, .address = accel, }, { .type = IIO_TEMP, .indexed = 1, .channel = 0, - .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, .address = temp, }, { .type = IIO_VOLTAGE, .indexed = 1, .channel = 1, - .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, .address = in_1, }, { .type = IIO_VOLTAGE, diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c index 482a762ef1b3..134839360d31 100644 --- a/drivers/staging/iio/accel/adis16240_core.c +++ b/drivers/staging/iio/accel/adis16240_core.c @@ -389,8 +389,7 @@ static int adis16240_read_raw(struct iio_dev *indio_dev, *val = val16; mutex_unlock(&indio_dev->mlock); return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE_SEPARATE: - case IIO_CHAN_INFO_SCALE_SHARED: + case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_VOLTAGE: *val = 0; @@ -411,14 +410,14 @@ static int adis16240_read_raw(struct iio_dev *indio_dev, return -EINVAL; } break; - case IIO_CHAN_INFO_PEAK_SCALE_SHARED: + case IIO_CHAN_INFO_PEAK_SCALE: *val = 6; *val2 = 629295; return IIO_VAL_INT_PLUS_MICRO; - case IIO_CHAN_INFO_OFFSET_SEPARATE: + case IIO_CHAN_INFO_OFFSET: *val = 25; return IIO_VAL_INT; - case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: + case IIO_CHAN_INFO_CALIBBIAS: bits = 10; mutex_lock(&indio_dev->mlock); addr = adis16240_addresses[chan->address][1]; @@ -432,7 +431,7 @@ static int adis16240_read_raw(struct iio_dev *indio_dev, *val = val16; mutex_unlock(&indio_dev->mlock); return IIO_VAL_INT; - case IIO_CHAN_INFO_PEAK_SEPARATE: + case IIO_CHAN_INFO_PEAK: bits = 10; mutex_lock(&indio_dev->mlock); addr = adis16240_addresses[chan->address][2]; @@ -460,7 +459,7 @@ static int adis16240_write_raw(struct iio_dev *indio_dev, s16 val16; u8 addr; switch (mask) { - case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: + case IIO_CHAN_INFO_CALIBBIAS: val16 = val & ((1 << bits) - 1); addr = adis16240_addresses[chan->address][1]; return adis16240_spi_write_reg_16(indio_dev, addr, val16); @@ -470,7 +469,7 @@ static int adis16240_write_raw(struct iio_dev *indio_dev, static struct iio_chan_spec adis16240_channels[] = { IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "supply", 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, in_supply, ADIS16240_SCAN_SUPPLY, IIO_ST('u', 10, 16, 0), 0), IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0, @@ -478,22 +477,22 @@ static struct iio_chan_spec adis16240_channels[] = { in_aux, ADIS16240_SCAN_AUX_ADC, IIO_ST('u', 10, 16, 0), 0), IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X, - (1 << IIO_CHAN_INFO_SCALE_SHARED) | - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE), + IIO_CHAN_INFO_SCALE_SHARED_BIT | + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, accel_x, ADIS16240_SCAN_ACC_X, IIO_ST('s', 10, 16, 0), 0), IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y, - (1 << IIO_CHAN_INFO_SCALE_SHARED) | - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE), + IIO_CHAN_INFO_SCALE_SHARED_BIT | + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, accel_y, ADIS16240_SCAN_ACC_Y, IIO_ST('s', 10, 16, 0), 0), IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Z, - (1 << IIO_CHAN_INFO_SCALE_SHARED) | - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE), + IIO_CHAN_INFO_SCALE_SHARED_BIT | + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, accel_z, ADIS16240_SCAN_ACC_Z, IIO_ST('s', 10, 16, 0), 0), IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, temp, ADIS16240_SCAN_TEMP, IIO_ST('u', 10, 16, 0), 0), IIO_CHAN_SOFT_TIMESTAMP(6) diff --git a/drivers/staging/iio/accel/kxsd9.c b/drivers/staging/iio/accel/kxsd9.c index 0ea0b5ccd593..abb6071e1c50 100644 --- a/drivers/staging/iio/accel/kxsd9.c +++ b/drivers/staging/iio/accel/kxsd9.c @@ -140,7 +140,7 @@ static int kxsd9_write_raw(struct iio_dev *indio_dev, { int ret = -EINVAL; - if (mask == IIO_CHAN_INFO_SCALE_SHARED) { + if (mask == IIO_CHAN_INFO_SCALE) { /* Check no integer component */ if (val) return -EINVAL; @@ -164,7 +164,7 @@ static int kxsd9_read_raw(struct iio_dev *indio_dev, goto error_ret; *val = ret; break; - case IIO_CHAN_INFO_SCALE_SHARED: + case IIO_CHAN_INFO_SCALE: ret = spi_w8r8(st->us, KXSD9_READ(KXSD9_REG_CTRL_C)); if (ret) goto error_ret; @@ -181,7 +181,7 @@ error_ret: .type = IIO_ACCEL, \ .modified = 1, \ .channel2 = IIO_MOD_##axis, \ - .info_mask = 1 << IIO_CHAN_INFO_SCALE_SHARED, \ + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \ .address = KXSD9_REG_##axis, \ } diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c index d7706ebe8090..6d715a6e4200 100644 --- a/drivers/staging/iio/accel/lis3l02dq_core.c +++ b/drivers/staging/iio/accel/lis3l02dq_core.c @@ -227,14 +227,14 @@ static int lis3l02dq_write_raw(struct iio_dev *indio_dev, u8 uval; s8 sval; switch (mask) { - case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: + case IIO_CHAN_INFO_CALIBBIAS: if (val > 255 || val < -256) return -EINVAL; sval = val; reg = lis3l02dq_axis_map[LIS3L02DQ_BIAS][chan->address]; ret = lis3l02dq_spi_write_reg_8(indio_dev, reg, sval); break; - case IIO_CHAN_INFO_CALIBSCALE_SEPARATE: + case IIO_CHAN_INFO_CALIBSCALE: if (val & ~0xFF) return -EINVAL; uval = val; @@ -272,11 +272,11 @@ static int lis3l02dq_read_raw(struct iio_dev *indio_dev, } mutex_unlock(&indio_dev->mlock); return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE_SHARED: + case IIO_CHAN_INFO_SCALE: *val = 0; *val2 = 9580; return IIO_VAL_INT_PLUS_MICRO; - case IIO_CHAN_INFO_CALIBSCALE_SEPARATE: + case IIO_CHAN_INFO_CALIBSCALE: reg = lis3l02dq_axis_map[LIS3L02DQ_GAIN][chan->address]; ret = lis3l02dq_spi_read_reg_8(indio_dev, reg, &utemp); if (ret) @@ -285,7 +285,7 @@ static int lis3l02dq_read_raw(struct iio_dev *indio_dev, *val = utemp; return IIO_VAL_INT; - case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: + case IIO_CHAN_INFO_CALIBBIAS: reg = lis3l02dq_axis_map[LIS3L02DQ_BIAS][chan->address]; ret = lis3l02dq_spi_read_reg_8(indio_dev, reg, (u8 *)&stemp); /* to match with what previous code does */ @@ -516,9 +516,9 @@ static irqreturn_t lis3l02dq_event_handler(int irq, void *private) } #define LIS3L02DQ_INFO_MASK \ - ((1 << IIO_CHAN_INFO_SCALE_SHARED) | \ - (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) | \ - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE)) + (IIO_CHAN_INFO_SCALE_SHARED_BIT | \ + IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \ + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT) #define LIS3L02DQ_EVENT_MASK \ (IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) | \ diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c index 1586963f5653..021a08ffb6cc 100644 --- a/drivers/staging/iio/accel/sca3000_core.c +++ b/drivers/staging/iio/accel/sca3000_core.c @@ -425,7 +425,7 @@ static IIO_DEVICE_ATTR(measurement_mode, S_IRUGO | S_IWUSR, static IIO_DEVICE_ATTR(revision, S_IRUGO, sca3000_show_rev, NULL, 0); #define SCA3000_INFO_MASK \ - (1 << IIO_CHAN_INFO_SCALE_SHARED) + IIO_CHAN_INFO_SCALE_SHARED_BIT #define SCA3000_EVENT_MASK \ (IIO_EV_BIT(IIO_EV_TYPE_MAG, IIO_EV_DIR_RISING)) @@ -475,7 +475,7 @@ static int sca3000_read_raw(struct iio_dev *indio_dev, (sizeof(*val)*8 - 13); mutex_unlock(&st->lock); return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE_SHARED: + case IIO_CHAN_INFO_SCALE: *val = 0; if (chan->type == IIO_ACCEL) *val2 = st->info->scale; diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 9416cedcddcb..4e643de45f65 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -901,18 +901,20 @@ static int ad7192_read_raw(struct iio_dev *indio_dev, } return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE_SHARED: - mutex_lock(&indio_dev->mlock); - *val = st->scale_avail[AD7192_CONF_GAIN(st->conf)][0]; - *val2 = st->scale_avail[AD7192_CONF_GAIN(st->conf)][1]; - mutex_unlock(&indio_dev->mlock); - - return IIO_VAL_INT_PLUS_NANO; - - case IIO_CHAN_INFO_SCALE_SEPARATE: - *val = 1000; - - return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_VOLTAGE: + mutex_lock(&indio_dev->mlock); + *val = st->scale_avail[AD7192_CONF_GAIN(st->conf)][0]; + *val2 = st->scale_avail[AD7192_CONF_GAIN(st->conf)][1]; + mutex_unlock(&indio_dev->mlock); + return IIO_VAL_INT_PLUS_NANO; + case IIO_TEMP: + *val = 1000; + return IIO_VAL_INT; + default: + return -EINVAL; + } } return -EINVAL; @@ -935,7 +937,7 @@ static int ad7192_write_raw(struct iio_dev *indio_dev, } switch (mask) { - case IIO_CHAN_INFO_SCALE_SHARED: + case IIO_CHAN_INFO_SCALE: ret = -EINVAL; for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) if (val2 == st->scale_avail[i][1]) { @@ -992,7 +994,7 @@ static const struct iio_info ad7192_info = { .extend_name = _name, \ .channel = _chan, \ .channel2 = _chan2, \ - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), \ + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \ .address = _address, \ .scan_index = _si, \ .scan_type = IIO_ST('s', 24, 32, 0)} @@ -1001,7 +1003,7 @@ static const struct iio_info ad7192_info = { { .type = IIO_VOLTAGE, \ .indexed = 1, \ .channel = _chan, \ - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), \ + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \ .address = _address, \ .scan_index = _si, \ .scan_type = IIO_ST('s', 24, 32, 0)} @@ -1010,7 +1012,7 @@ static const struct iio_info ad7192_info = { { .type = IIO_TEMP, \ .indexed = 1, \ .channel = _chan, \ - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), \ + .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ .address = _address, \ .scan_index = _si, \ .scan_type = IIO_ST('s', 24, 32, 0)} diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c index 7fb60c5a80e5..cd3397f95f80 100644 --- a/drivers/staging/iio/adc/ad7280a.c +++ b/drivers/staging/iio/adc/ad7280a.c @@ -508,7 +508,7 @@ static int ad7280_channel_init(struct ad7280_state *st) } st->channels[cnt].indexed = 1; st->channels[cnt].info_mask = - (1 << IIO_CHAN_INFO_SCALE_SHARED); + IIO_CHAN_INFO_SCALE_SHARED_BIT; st->channels[cnt].address = AD7280A_DEVADDR(dev) << 8 | ch; st->channels[cnt].scan_index = cnt; @@ -524,7 +524,7 @@ static int ad7280_channel_init(struct ad7280_state *st) st->channels[cnt].channel2 = dev * 6; st->channels[cnt].address = AD7280A_ALL_CELLS; st->channels[cnt].indexed = 1; - st->channels[cnt].info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED); + st->channels[cnt].info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT; st->channels[cnt].scan_index = cnt; st->channels[cnt].scan_type.sign = 'u'; st->channels[cnt].scan_type.realbits = 32; @@ -803,7 +803,7 @@ static int ad7280_read_raw(struct iio_dev *indio_dev, *val = ret; return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE_SHARED: + case IIO_CHAN_INFO_SCALE: if ((chan->address & 0xFF) <= AD7280A_CELL_VOLTAGE_6) scale_uv = (4000 * 1000) >> AD7280A_BITS; else diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/staging/iio/adc/ad7291.c index bedd91ad3fdb..c4977a78b429 100644 --- a/drivers/staging/iio/adc/ad7291.c +++ b/drivers/staging/iio/adc/ad7291.c @@ -501,7 +501,7 @@ static int ad7291_read_raw(struct iio_dev *indio_dev, default: return -EINVAL; } - case IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE: + case IIO_CHAN_INFO_AVERAGE_RAW: ret = i2c_smbus_read_word_data(chip->client, AD7291_T_AVERAGE); if (ret < 0) @@ -510,18 +510,24 @@ static int ad7291_read_raw(struct iio_dev *indio_dev, AD7291_VALUE_MASK) << 4) >> 4; *val = signval; return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE_SHARED: - scale_uv = (chip->int_vref_mv * 1000) >> AD7291_BITS; - *val = scale_uv / 1000; - *val2 = (scale_uv % 1000) * 1000; - return IIO_VAL_INT_PLUS_MICRO; - case IIO_CHAN_INFO_SCALE_SEPARATE: - /* - * One LSB of the ADC corresponds to 0.25 deg C. - * The temperature reading is in 12-bit twos complement format - */ - *val = 250; - return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_VOLTAGE: + scale_uv = (chip->int_vref_mv * 1000) >> AD7291_BITS; + *val = scale_uv / 1000; + *val2 = (scale_uv % 1000) * 1000; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_TEMP: + /* + * One LSB of the ADC corresponds to 0.25 deg C. + * The temperature reading is in 12-bit twos + * complement format + */ + *val = 250; + return IIO_VAL_INT; + default: + return -EINVAL; + } default: return -EINVAL; } @@ -530,7 +536,7 @@ static int ad7291_read_raw(struct iio_dev *indio_dev, #define AD7291_VOLTAGE_CHAN(_chan) \ { \ .type = IIO_VOLTAGE, \ - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), \ + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \ .indexed = 1, \ .channel = _chan, \ .event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING)|\ @@ -548,8 +554,8 @@ static const struct iio_chan_spec ad7291_channels[] = { AD7291_VOLTAGE_CHAN(7), { .type = IIO_TEMP, - .info_mask = (1 << IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .info_mask = IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, .indexed = 1, .channel = 0, .event_mask = diff --git a/drivers/staging/iio/adc/ad7298_core.c b/drivers/staging/iio/adc/ad7298_core.c index 2e3b0d979fc5..0be71dfcf115 100644 --- a/drivers/staging/iio/adc/ad7298_core.c +++ b/drivers/staging/iio/adc/ad7298_core.c @@ -24,31 +24,31 @@ static struct iio_chan_spec ad7298_channels[] = { IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, 9, AD7298_CH_TEMP, IIO_ST('s', 32, 32, 0), 0), IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, 0, 0, IIO_ST('u', 12, 16, 0), 0), IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, 1, 1, IIO_ST('u', 12, 16, 0), 0), IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 2, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, 2, 2, IIO_ST('u', 12, 16, 0), 0), IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 3, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, 3, 3, IIO_ST('u', 12, 16, 0), 0), IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 4, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, 4, 4, IIO_ST('u', 12, 16, 0), 0), IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 5, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, 5, 5, IIO_ST('u', 12, 16, 0), 0), IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 6, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, 6, 6, IIO_ST('u', 12, 16, 0), 0), IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 7, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, 7, 7, IIO_ST('u', 12, 16, 0), 0), IIO_CHAN_SOFT_TIMESTAMP(8), }; @@ -143,15 +143,20 @@ static int ad7298_read_raw(struct iio_dev *indio_dev, *val = ret & RES_MASK(AD7298_BITS); return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE_SHARED: - scale_uv = (st->int_vref_mv * 1000) >> AD7298_BITS; - *val = scale_uv / 1000; - *val2 = (scale_uv % 1000) * 1000; - return IIO_VAL_INT_PLUS_MICRO; - case IIO_CHAN_INFO_SCALE_SEPARATE: - *val = 1; - *val2 = 0; - return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_VOLTAGE: + scale_uv = (st->int_vref_mv * 1000) >> AD7298_BITS; + *val = scale_uv / 1000; + *val2 = (scale_uv % 1000) * 1000; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_TEMP: + *val = 1; + *val2 = 0; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } } return -EINVAL; } diff --git a/drivers/staging/iio/adc/ad7476_core.c b/drivers/staging/iio/adc/ad7476_core.c index 163a2547a6f6..a06ae9eec935 100644 --- a/drivers/staging/iio/adc/ad7476_core.c +++ b/drivers/staging/iio/adc/ad7476_core.c @@ -56,7 +56,7 @@ static int ad7476_read_raw(struct iio_dev *indio_dev, *val = (ret >> st->chip_info->channel[0].scan_type.shift) & RES_MASK(st->chip_info->channel[0].scan_type.realbits); return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE_SHARED: + case IIO_CHAN_INFO_SCALE: scale_uv = (st->int_vref_mv * 1000) >> st->chip_info->channel[0].scan_type.realbits; *val = scale_uv/1000; @@ -69,49 +69,49 @@ static int ad7476_read_raw(struct iio_dev *indio_dev, static const struct ad7476_chip_info ad7476_chip_info_tbl[] = { [ID_AD7466] = { .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, 0, 0, IIO_ST('u', 12, 16, 0), 0), .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), }, [ID_AD7467] = { .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, 0, 0, IIO_ST('u', 10, 16, 2), 0), .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), }, [ID_AD7468] = { .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1 , 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, 0, 0, IIO_ST('u', 8, 16, 4), 0), .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), }, [ID_AD7475] = { .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, 0, 0, IIO_ST('u', 12, 16, 0), 0), .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), }, [ID_AD7476] = { .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, 0, 0, IIO_ST('u', 12, 16, 0), 0), .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), }, [ID_AD7477] = { .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, 0, 0, IIO_ST('u', 10, 16, 2), 0), .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), }, [ID_AD7478] = { .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, 0, 0, IIO_ST('u', 8, 16, 4), 0), .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), }, [ID_AD7495] = { .channel[0] = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, 0, 0, IIO_ST('u', 12, 16, 0), 0), .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), .int_vref_mv = 2500, diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c index d58a0e3eee93..a8596b856a3e 100644 --- a/drivers/staging/iio/adc/ad7606_core.c +++ b/drivers/staging/iio/adc/ad7606_core.c @@ -100,7 +100,7 @@ static int ad7606_read_raw(struct iio_dev *indio_dev, return ret; *val = (short) ret; return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE_SHARED: + case IIO_CHAN_INFO_SCALE: scale_uv = (st->range * 1000 * 2) >> st->chip_info->channels[0].scan_type.realbits; *val = scale_uv / 1000; diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c index b06f9ad48b9a..f5f7e76561f5 100644 --- a/drivers/staging/iio/adc/ad7780.c +++ b/drivers/staging/iio/adc/ad7780.c @@ -114,7 +114,7 @@ static int ad7780_read_raw(struct iio_dev *indio_dev, *val *= 128; return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE_SHARED: + case IIO_CHAN_INFO_SCALE: scale_uv = (st->int_vref_mv * 100000) >> (channel.scan_type.realbits - 1); *val = scale_uv / 100000; @@ -127,12 +127,12 @@ static int ad7780_read_raw(struct iio_dev *indio_dev, static const struct ad7780_chip_info ad7780_chip_info_tbl[] = { [ID_AD7780] = { .channel = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, 0, 0, IIO_ST('s', 24, 32, 8), 0), }, [ID_AD7781] = { .channel = IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, 0, 0, IIO_ST('s', 20, 32, 12), 0), }, }; diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c index c3fdfedfc994..803c45ff84b9 100644 --- a/drivers/staging/iio/adc/ad7793.c +++ b/drivers/staging/iio/adc/ad7793.c @@ -667,19 +667,21 @@ static int ad7793_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE_SHARED: - *val = st->scale_avail[(st->conf >> 8) & 0x7][0]; - *val2 = st->scale_avail[(st->conf >> 8) & 0x7][1]; - - return IIO_VAL_INT_PLUS_NANO; - - case IIO_CHAN_INFO_SCALE_SEPARATE: + case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_VOLTAGE: - /* 1170mV / 2^23 * 6 */ - scale_uv = (1170ULL * 100000000ULL * 6ULL) - >> (chan->scan_type.realbits - - (unipolar ? 0 : 1)); + if (chan->differential) { + *val = st-> + scale_avail[(st->conf >> 8) & 0x7][0]; + *val2 = st-> + scale_avail[(st->conf >> 8) & 0x7][1]; + return IIO_VAL_INT_PLUS_NANO; + } else { + /* 1170mV / 2^23 * 6 */ + scale_uv = (1170ULL * 100000000ULL * 6ULL) + >> (chan->scan_type.realbits - + (unipolar ? 0 : 1)); + } break; case IIO_TEMP: /* Always uses unity gain and internal ref */ @@ -716,7 +718,7 @@ static int ad7793_write_raw(struct iio_dev *indio_dev, } switch (mask) { - case IIO_CHAN_INFO_SCALE_SHARED: + case IIO_CHAN_INFO_SCALE: ret = -EINVAL; for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) if (val2 == st->scale_avail[i][1]) { @@ -775,7 +777,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .channel = 0, .channel2 = 0, .address = AD7793_CH_AIN1P_AIN1M, - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, .scan_index = 0, .scan_type = IIO_ST('s', 24, 32, 0) }, @@ -786,7 +788,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .channel = 1, .channel2 = 1, .address = AD7793_CH_AIN2P_AIN2M, - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, .scan_index = 1, .scan_type = IIO_ST('s', 24, 32, 0) }, @@ -797,7 +799,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .channel = 2, .channel2 = 2, .address = AD7793_CH_AIN3P_AIN3M, - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, .scan_index = 2, .scan_type = IIO_ST('s', 24, 32, 0) }, @@ -809,7 +811,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .channel = 2, .channel2 = 2, .address = AD7793_CH_AIN1M_AIN1M, - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, .scan_index = 2, .scan_type = IIO_ST('s', 24, 32, 0) }, @@ -818,7 +820,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .indexed = 1, .channel = 0, .address = AD7793_CH_TEMP, - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, .scan_index = 4, .scan_type = IIO_ST('s', 24, 32, 0), }, @@ -828,7 +830,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .indexed = 1, .channel = 4, .address = AD7793_CH_AVDD_MONITOR, - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, .scan_index = 5, .scan_type = IIO_ST('s', 24, 32, 0), }, @@ -842,7 +844,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .channel = 0, .channel2 = 0, .address = AD7793_CH_AIN1P_AIN1M, - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, .scan_index = 0, .scan_type = IIO_ST('s', 16, 32, 0) }, @@ -853,7 +855,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .channel = 1, .channel2 = 1, .address = AD7793_CH_AIN2P_AIN2M, - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, .scan_index = 1, .scan_type = IIO_ST('s', 16, 32, 0) }, @@ -864,7 +866,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .channel = 2, .channel2 = 2, .address = AD7793_CH_AIN3P_AIN3M, - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, .scan_index = 2, .scan_type = IIO_ST('s', 16, 32, 0) }, @@ -876,7 +878,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .channel = 2, .channel2 = 2, .address = AD7793_CH_AIN1M_AIN1M, - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, .scan_index = 2, .scan_type = IIO_ST('s', 16, 32, 0) }, @@ -885,7 +887,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .indexed = 1, .channel = 0, .address = AD7793_CH_TEMP, - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, .scan_index = 4, .scan_type = IIO_ST('s', 16, 32, 0), }, @@ -895,7 +897,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { .indexed = 1, .channel = 4, .address = AD7793_CH_AVDD_MONITOR, - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, .scan_index = 5, .scan_type = IIO_ST('s', 16, 32, 0), }, diff --git a/drivers/staging/iio/adc/ad7887_core.c b/drivers/staging/iio/adc/ad7887_core.c index 245c9438359b..baa6e6a8c418 100644 --- a/drivers/staging/iio/adc/ad7887_core.c +++ b/drivers/staging/iio/adc/ad7887_core.c @@ -55,7 +55,7 @@ static int ad7887_read_raw(struct iio_dev *indio_dev, *val = (ret >> st->chip_info->channel[0].scan_type.shift) & RES_MASK(st->chip_info->channel[0].scan_type.realbits); return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE_SHARED: + case IIO_CHAN_INFO_SCALE: scale_uv = (st->int_vref_mv * 1000) >> st->chip_info->channel[0].scan_type.realbits; *val = scale_uv/1000; @@ -75,7 +75,7 @@ static const struct ad7887_chip_info ad7887_chip_info_tbl[] = { .type = IIO_VOLTAGE, .indexed = 1, .channel = 1, - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = 1, .scan_index = 1, .scan_type = IIO_ST('u', 12, 16, 0), @@ -84,7 +84,7 @@ static const struct ad7887_chip_info ad7887_chip_info_tbl[] = { .type = IIO_VOLTAGE, .indexed = 1, .channel = 0, - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = 0, .scan_index = 0, .scan_type = IIO_ST('u', 12, 16, 0), diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c index 60a48a284dd1..cdee9b95465f 100644 --- a/drivers/staging/iio/adc/ad799x_core.c +++ b/drivers/staging/iio/adc/ad799x_core.c @@ -162,7 +162,7 @@ static int ad799x_read_raw(struct iio_dev *indio_dev, *val = (ret >> chan->scan_type.shift) & RES_MASK(chan->scan_type.realbits); return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE_SHARED: + case IIO_CHAN_INFO_SCALE: scale_uv = (st->int_vref_mv * 1000) >> chan->scan_type.realbits; *val = scale_uv / 1000; *val2 = (scale_uv % 1000) * 1000; diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c index 6b05e573afc7..c3e28e17838c 100644 --- a/drivers/staging/iio/adc/max1363_core.c +++ b/drivers/staging/iio/adc/max1363_core.c @@ -261,7 +261,7 @@ static int max1363_read_raw(struct iio_dev *indio_dev, if (ret < 0) return ret; return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE_SHARED: + case IIO_CHAN_INFO_SCALE: if ((1 << (st->chip_info->bits + 1)) > st->chip_info->int_vref_mv) { *val = 0; @@ -289,7 +289,7 @@ static const enum max1363_modes max1363_mode_list[] = { #define MAX1363_EV_M \ (IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) \ | IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING)) -#define MAX1363_INFO_MASK (1 << IIO_CHAN_INFO_SCALE_SHARED) +#define MAX1363_INFO_MASK IIO_CHAN_INFO_SCALE_SHARED_BIT #define MAX1363_CHAN_U(num, addr, si, bits, evmask) \ { \ .type = IIO_VOLTAGE, \ diff --git a/drivers/staging/iio/cdc/ad7150.c b/drivers/staging/iio/cdc/ad7150.c index 10737fae25e1..6bcdb147928c 100644 --- a/drivers/staging/iio/cdc/ad7150.c +++ b/drivers/staging/iio/cdc/ad7150.c @@ -111,7 +111,7 @@ static int ad7150_read_raw(struct iio_dev *indio_dev, return ret; *val = swab16(ret); return IIO_VAL_INT; - case IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE: + case IIO_CHAN_INFO_AVERAGE_RAW: ret = i2c_smbus_read_word_data(chip->client, ad7150_addresses[chan->channel][1]); if (ret < 0) @@ -429,7 +429,7 @@ static const struct iio_chan_spec ad7150_channels[] = { .type = IIO_CAPACITANCE, .indexed = 1, .channel = 0, - .info_mask = (1 << IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE), + .info_mask = IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE_BIT, .event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) | IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING) | @@ -441,7 +441,7 @@ static const struct iio_chan_spec ad7150_channels[] = { .type = IIO_CAPACITANCE, .indexed = 1, .channel = 1, - .info_mask = (1 << IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE), + .info_mask = IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE_BIT, .event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) | IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING) | diff --git a/drivers/staging/iio/cdc/ad7152.c b/drivers/staging/iio/cdc/ad7152.c index e5ca683a7af0..29b2dc6e4f85 100644 --- a/drivers/staging/iio/cdc/ad7152.c +++ b/drivers/staging/iio/cdc/ad7152.c @@ -259,7 +259,7 @@ static int ad7152_write_raw(struct iio_dev *indio_dev, mutex_lock(&indio_dev->mlock); switch (mask) { - case IIO_CHAN_INFO_CALIBSCALE_SEPARATE: + case IIO_CHAN_INFO_CALIBSCALE: if (val != 1) { ret = -EINVAL; goto out; @@ -276,7 +276,7 @@ static int ad7152_write_raw(struct iio_dev *indio_dev, ret = 0; break; - case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: + case IIO_CHAN_INFO_CALIBBIAS: if ((val < 0) | (val > 0xFFFF)) { ret = -EINVAL; goto out; @@ -289,7 +289,7 @@ static int ad7152_write_raw(struct iio_dev *indio_dev, ret = 0; break; - case IIO_CHAN_INFO_SCALE_SEPARATE: + case IIO_CHAN_INFO_SCALE: if (val != 0) { ret = -EINVAL; goto out; @@ -372,7 +372,7 @@ static int ad7152_read_raw(struct iio_dev *indio_dev, ret = IIO_VAL_INT; break; - case IIO_CHAN_INFO_CALIBSCALE_SEPARATE: + case IIO_CHAN_INFO_CALIBSCALE: ret = i2c_smbus_read_word_data(chip->client, ad7152_addresses[chan->channel][AD7152_GAIN]); @@ -384,7 +384,7 @@ static int ad7152_read_raw(struct iio_dev *indio_dev, ret = IIO_VAL_INT_PLUS_MICRO; break; - case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: + case IIO_CHAN_INFO_CALIBBIAS: ret = i2c_smbus_read_word_data(chip->client, ad7152_addresses[chan->channel][AD7152_OFFS]); if (ret < 0) @@ -393,7 +393,7 @@ static int ad7152_read_raw(struct iio_dev *indio_dev, ret = IIO_VAL_INT; break; - case IIO_CHAN_INFO_SCALE_SEPARATE: + case IIO_CHAN_INFO_SCALE: ret = i2c_smbus_read_byte_data(chip->client, ad7152_addresses[chan->channel][AD7152_SETUP]); if (ret < 0) @@ -416,7 +416,7 @@ static int ad7152_write_raw_get_fmt(struct iio_dev *indio_dev, long mask) { switch (mask) { - case IIO_CHAN_INFO_SCALE_SEPARATE: + case IIO_CHAN_INFO_SCALE: return IIO_VAL_INT_PLUS_NANO; default: return IIO_VAL_INT_PLUS_MICRO; @@ -436,34 +436,34 @@ static const struct iio_chan_spec ad7152_channels[] = { .type = IIO_CAPACITANCE, .indexed = 1, .channel = 0, - .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) | - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, }, { .type = IIO_CAPACITANCE, .differential = 1, .indexed = 1, .channel = 0, .channel2 = 2, - .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) | - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, }, { .type = IIO_CAPACITANCE, .indexed = 1, .channel = 1, - .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) | - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, }, { .type = IIO_CAPACITANCE, .differential = 1, .indexed = 1, .channel = 1, .channel2 = 3, - .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) | - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, } }; /* diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c index 5deaf857d23c..de8f844dc9fc 100644 --- a/drivers/staging/iio/cdc/ad7746.c +++ b/drivers/staging/iio/cdc/ad7746.c @@ -123,7 +123,7 @@ static const struct iio_chan_spec ad7746_channels[] = { .type = IIO_VOLTAGE, .indexed = 1, .channel = 0, - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = AD7746_REG_VT_DATA_HIGH << 8 | AD7746_VTSETUP_VTMD_EXT_VIN, }, @@ -132,7 +132,7 @@ static const struct iio_chan_spec ad7746_channels[] = { .indexed = 1, .channel = 1, .extend_name = "supply", - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = AD7746_REG_VT_DATA_HIGH << 8 | AD7746_VTSETUP_VTMD_VDD_MON, }, @@ -156,10 +156,10 @@ static const struct iio_chan_spec ad7746_channels[] = { .type = IIO_CAPACITANCE, .indexed = 1, .channel = 0, - .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) | - (1 << IIO_CHAN_INFO_CALIBBIAS_SHARED) | - (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | + IIO_CHAN_INFO_CALIBBIAS_SHARED_BIT | + IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = AD7746_REG_CAP_DATA_HIGH << 8, }, [CIN1_DIFF] = { @@ -168,10 +168,10 @@ static const struct iio_chan_spec ad7746_channels[] = { .indexed = 1, .channel = 0, .channel2 = 2, - .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) | - (1 << IIO_CHAN_INFO_CALIBBIAS_SHARED) | - (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | + IIO_CHAN_INFO_CALIBBIAS_SHARED_BIT | + IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = AD7746_REG_CAP_DATA_HIGH << 8 | AD7746_CAPSETUP_CAPDIFF }, @@ -179,10 +179,10 @@ static const struct iio_chan_spec ad7746_channels[] = { .type = IIO_CAPACITANCE, .indexed = 1, .channel = 1, - .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) | - (1 << IIO_CHAN_INFO_CALIBBIAS_SHARED) | - (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | + IIO_CHAN_INFO_CALIBBIAS_SHARED_BIT | + IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = AD7746_REG_CAP_DATA_HIGH << 8 | AD7746_CAPSETUP_CIN2, }, @@ -192,10 +192,10 @@ static const struct iio_chan_spec ad7746_channels[] = { .indexed = 1, .channel = 1, .channel2 = 3, - .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) | - (1 << IIO_CHAN_INFO_CALIBBIAS_SHARED) | - (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | + IIO_CHAN_INFO_CALIBBIAS_SHARED_BIT | + IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = AD7746_REG_CAP_DATA_HIGH << 8 | AD7746_CAPSETUP_CAPDIFF | AD7746_CAPSETUP_CIN2, } @@ -477,7 +477,7 @@ static int ad7746_write_raw(struct iio_dev *indio_dev, mutex_lock(&indio_dev->mlock); switch (mask) { - case IIO_CHAN_INFO_CALIBSCALE_SEPARATE: + case IIO_CHAN_INFO_CALIBSCALE: if (val != 1) { ret = -EINVAL; goto out; @@ -503,7 +503,7 @@ static int ad7746_write_raw(struct iio_dev *indio_dev, ret = 0; break; - case IIO_CHAN_INFO_CALIBBIAS_SHARED: + case IIO_CHAN_INFO_CALIBBIAS: if ((val < 0) | (val > 0xFFFF)) { ret = -EINVAL; goto out; @@ -515,7 +515,7 @@ static int ad7746_write_raw(struct iio_dev *indio_dev, ret = 0; break; - case IIO_CHAN_INFO_OFFSET_SEPARATE: + case IIO_CHAN_INFO_OFFSET: if ((val < 0) | (val > 43008000)) { /* 21pF */ ret = -EINVAL; goto out; @@ -612,7 +612,7 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, ret = IIO_VAL_INT; break; - case IIO_CHAN_INFO_CALIBSCALE_SEPARATE: + case IIO_CHAN_INFO_CALIBSCALE: switch (chan->type) { case IIO_CAPACITANCE: reg = AD7746_REG_CAP_GAINH; @@ -634,7 +634,7 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, ret = IIO_VAL_INT_PLUS_MICRO; break; - case IIO_CHAN_INFO_CALIBBIAS_SHARED: + case IIO_CHAN_INFO_CALIBBIAS: ret = i2c_smbus_read_word_data(chip->client, AD7746_REG_CAP_OFFH); if (ret < 0) @@ -643,13 +643,13 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, ret = IIO_VAL_INT; break; - case IIO_CHAN_INFO_OFFSET_SEPARATE: + case IIO_CHAN_INFO_OFFSET: *val = AD7746_CAPDAC_DACP(chip->capdac[chan->channel] [chan->differential]) * 338646; ret = IIO_VAL_INT; break; - case IIO_CHAN_INFO_SCALE_SHARED: + case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_CAPACITANCE: /* 8.192pf / 2^24 */ diff --git a/drivers/staging/iio/dac/ad5064.c b/drivers/staging/iio/dac/ad5064.c index 1c25403620ff..a701063a9267 100644 --- a/drivers/staging/iio/dac/ad5064.c +++ b/drivers/staging/iio/dac/ad5064.c @@ -91,7 +91,7 @@ enum ad5064_type { .indexed = 1, \ .output = 1, \ .channel = (chan), \ - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), \ + .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ .address = AD5064_ADDR_DAC(chan), \ .scan_type = IIO_ST('u', (bits), 16, 20 - (bits)) \ } @@ -287,7 +287,7 @@ static int ad5064_read_raw(struct iio_dev *indio_dev, case 0: *val = st->dac_cache[chan->channel]; return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE_SEPARATE: + case IIO_CHAN_INFO_SCALE: vref = st->chip_info->shared_vref ? 0 : chan->channel; scale_uv = regulator_get_voltage(st->vref_reg[vref].consumer); if (scale_uv < 0) diff --git a/drivers/staging/iio/dac/ad5360.c b/drivers/staging/iio/dac/ad5360.c index 7df19586d182..c5bf5827c137 100644 --- a/drivers/staging/iio/dac/ad5360.c +++ b/drivers/staging/iio/dac/ad5360.c @@ -103,10 +103,10 @@ enum ad5360_type { .type = IIO_VOLTAGE, \ .indexed = 1, \ .output = 1, \ - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE) | \ - (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | \ - (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) | \ - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE), \ + .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT | \ + IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | \ + IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \ + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, \ .scan_type = IIO_ST('u', (bits), 16, 16 - (bits)) \ } @@ -326,21 +326,21 @@ static int ad5360_write_raw(struct iio_dev *indio_dev, return ad5360_write(indio_dev, AD5360_CMD_WRITE_DATA, chan->address, val, chan->scan_type.shift); - case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: + case IIO_CHAN_INFO_CALIBBIAS: if (val >= max_val || val < 0) return -EINVAL; return ad5360_write(indio_dev, AD5360_CMD_WRITE_OFFSET, chan->address, val, chan->scan_type.shift); - case IIO_CHAN_INFO_CALIBSCALE_SEPARATE: + case IIO_CHAN_INFO_CALIBSCALE: if (val >= max_val || val < 0) return -EINVAL; return ad5360_write(indio_dev, AD5360_CMD_WRITE_GAIN, chan->address, val, chan->scan_type.shift); - case IIO_CHAN_INFO_OFFSET_SEPARATE: + case IIO_CHAN_INFO_OFFSET: if (val <= -max_val || val > 0) return -EINVAL; @@ -383,7 +383,7 @@ static int ad5360_read_raw(struct iio_dev *indio_dev, return ret; *val = ret >> chan->scan_type.shift; return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE_SEPARATE: + case IIO_CHAN_INFO_SCALE: /* vout = 4 * vref * dac_code */ scale_uv = ad5360_get_channel_vref(st, chan->channel) * 4 * 100; if (scale_uv < 0) @@ -393,21 +393,21 @@ static int ad5360_read_raw(struct iio_dev *indio_dev, *val = scale_uv / 100000; *val2 = (scale_uv % 100000) * 10; return IIO_VAL_INT_PLUS_MICRO; - case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: + case IIO_CHAN_INFO_CALIBBIAS: ret = ad5360_read(indio_dev, AD5360_READBACK_OFFSET, chan->address); if (ret < 0) return ret; *val = ret; return IIO_VAL_INT; - case IIO_CHAN_INFO_CALIBSCALE_SEPARATE: + case IIO_CHAN_INFO_CALIBSCALE: ret = ad5360_read(indio_dev, AD5360_READBACK_GAIN, chan->address); if (ret < 0) return ret; *val = ret; return IIO_VAL_INT; - case IIO_CHAN_INFO_OFFSET_SEPARATE: + case IIO_CHAN_INFO_OFFSET: ofs_index = ad5360_get_channel_vref_index(st, chan->channel); ret = ad5360_read(indio_dev, AD5360_READBACK_SF, AD5360_REG_SF_OFS(ofs_index)); diff --git a/drivers/staging/iio/dac/ad5686.c b/drivers/staging/iio/dac/ad5686.c index f2332b3f24a7..7eaf594a4f64 100644 --- a/drivers/staging/iio/dac/ad5686.c +++ b/drivers/staging/iio/dac/ad5686.c @@ -99,7 +99,7 @@ enum ad5686_supported_device_ids { .indexed = 1, \ .output = 1, \ .channel = chan, \ - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), \ + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \ .address = AD5686_ADDR_DAC(chan), \ .scan_type = IIO_ST('u', bits, 16, shift) \ } @@ -306,7 +306,7 @@ static int ad5686_read_raw(struct iio_dev *indio_dev, *val = ret; return IIO_VAL_INT; break; - case IIO_CHAN_INFO_SCALE_SHARED: + case IIO_CHAN_INFO_SCALE: scale_uv = (st->vref_mv * 100000) >> (chan->scan_type.realbits); *val = scale_uv / 100000; diff --git a/drivers/staging/iio/dac/ad5791.c b/drivers/staging/iio/dac/ad5791.c index d3b3b71c87c1..db0bd1231a35 100644 --- a/drivers/staging/iio/dac/ad5791.c +++ b/drivers/staging/iio/dac/ad5791.c @@ -77,8 +77,8 @@ static int ad5791_spi_read(struct spi_device *spi, u8 addr, u32 *val) .indexed = 1, \ .address = AD5791_ADDR_DAC0, \ .channel = 0, \ - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED) | \ - (1 << IIO_CHAN_INFO_OFFSET_SHARED), \ + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT | \ + IIO_CHAN_INFO_OFFSET_SHARED_BIT, \ .scan_type = IIO_ST('u', bits, 24, shift) \ } @@ -237,11 +237,11 @@ static int ad5791_read_raw(struct iio_dev *indio_dev, *val &= AD5791_DAC_MASK; *val >>= chan->scan_type.shift; return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE_SHARED: + case IIO_CHAN_INFO_SCALE: *val = 0; *val2 = (((u64)st->vref_mv) * 1000000ULL) >> chan->scan_type.realbits; return IIO_VAL_INT_PLUS_MICRO; - case IIO_CHAN_INFO_OFFSET_SHARED: + case IIO_CHAN_INFO_OFFSET: val64 = (((u64)st->vref_neg_mv) << chan->scan_type.realbits); do_div(val64, st->vref_mv); *val = -val64; diff --git a/drivers/staging/iio/gyro/adis16060_core.c b/drivers/staging/iio/gyro/adis16060_core.c index d83c640f4e6b..c0ca7093e0ed 100644 --- a/drivers/staging/iio/gyro/adis16060_core.c +++ b/drivers/staging/iio/gyro/adis16060_core.c @@ -98,11 +98,11 @@ static int adis16060_read_raw(struct iio_dev *indio_dev, mutex_unlock(&indio_dev->mlock); *val = tval; return IIO_VAL_INT; - case IIO_CHAN_INFO_OFFSET_SEPARATE: + case IIO_CHAN_INFO_OFFSET: *val = -7; *val2 = 461117; return IIO_VAL_INT_PLUS_MICRO; - case IIO_CHAN_INFO_SCALE_SEPARATE: + case IIO_CHAN_INFO_SCALE: *val = 0; *val2 = 34000; return IIO_VAL_INT_PLUS_MICRO; @@ -136,8 +136,8 @@ static const struct iio_chan_spec adis16060_channels[] = { .type = IIO_TEMP, .indexed = 1, .channel = 0, - .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, .address = ADIS16060_TEMP_OUT, } }; diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c index 4f5a7cb3f7e9..e86ce6a1611a 100644 --- a/drivers/staging/iio/gyro/adis16260_core.c +++ b/drivers/staging/iio/gyro/adis16260_core.c @@ -390,9 +390,9 @@ enum adis16260_channel { #define ADIS16260_GYRO_CHANNEL_SET(axis, mod) \ struct iio_chan_spec adis16260_channels_##axis[] = { \ IIO_CHAN(IIO_ANGL_VEL, 1, 0, 0, NULL, 0, mod, \ - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | \ - (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) | \ - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), \ + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | \ + IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \ + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ gyro, ADIS16260_SCAN_GYRO, \ IIO_ST('s', 14, 16, 0), 0), \ IIO_CHAN(IIO_ANGL, 1, 0, 0, NULL, 0, mod, \ @@ -400,16 +400,16 @@ enum adis16260_channel { angle, ADIS16260_SCAN_ANGL, \ IIO_ST('u', 14, 16, 0), 0), \ IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0, \ - (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | \ - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), \ + IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | \ + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ temp, ADIS16260_SCAN_TEMP, \ IIO_ST('u', 12, 16, 0), 0), \ IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "supply", 0, 0, \ - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), \ + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ in_supply, ADIS16260_SCAN_SUPPLY, \ IIO_ST('u', 12, 16, 0), 0), \ IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, NULL, 1, 0, \ - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), \ + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ in_aux, ADIS16260_SCAN_AUX_ADC, \ IIO_ST('u', 12, 16, 0), 0), \ IIO_CHAN_SOFT_TIMESTAMP(5) \ @@ -464,8 +464,7 @@ static int adis16260_read_raw(struct iio_dev *indio_dev, *val = val16; mutex_unlock(&indio_dev->mlock); return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE_SEPARATE: - case IIO_CHAN_INFO_SCALE_SHARED: + case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_ANGL_VEL: *val = 0; @@ -489,10 +488,10 @@ static int adis16260_read_raw(struct iio_dev *indio_dev, return -EINVAL; } break; - case IIO_CHAN_INFO_OFFSET_SEPARATE: + case IIO_CHAN_INFO_OFFSET: *val = 25; return IIO_VAL_INT; - case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: + case IIO_CHAN_INFO_CALIBBIAS: switch (chan->type) { case IIO_ANGL_VEL: bits = 12; @@ -512,7 +511,7 @@ static int adis16260_read_raw(struct iio_dev *indio_dev, *val = val16; mutex_unlock(&indio_dev->mlock); return IIO_VAL_INT; - case IIO_CHAN_INFO_CALIBSCALE_SEPARATE: + case IIO_CHAN_INFO_CALIBSCALE: switch (chan->type) { case IIO_ANGL_VEL: bits = 12; @@ -544,11 +543,11 @@ static int adis16260_write_raw(struct iio_dev *indio_dev, s16 val16; u8 addr; switch (mask) { - case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: + case IIO_CHAN_INFO_CALIBBIAS: val16 = val & ((1 << bits) - 1); addr = adis16260_addresses[chan->address][1]; return adis16260_spi_write_reg_16(indio_dev, addr, val16); - case IIO_CHAN_INFO_CALIBSCALE_SEPARATE: + case IIO_CHAN_INFO_CALIBSCALE: val16 = val & ((1 << bits) - 1); addr = adis16260_addresses[chan->address][2]; return adis16260_spi_write_reg_16(indio_dev, addr, val16); diff --git a/drivers/staging/iio/gyro/adxrs450_core.c b/drivers/staging/iio/gyro/adxrs450_core.c index 18406c7f960f..40bfb32d6f16 100644 --- a/drivers/staging/iio/gyro/adxrs450_core.c +++ b/drivers/staging/iio/gyro/adxrs450_core.c @@ -243,7 +243,7 @@ static int adxrs450_write_raw(struct iio_dev *indio_dev, { int ret; switch (mask) { - case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: + case IIO_CHAN_INFO_CALIBBIAS: ret = adxrs450_spi_write_reg_16(indio_dev, ADXRS450_DNC1, val & 0x3FF); @@ -287,7 +287,7 @@ static int adxrs450_read_raw(struct iio_dev *indio_dev, break; } break; - case IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE: + case IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW: ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_QUAD1, &t); if (ret) break; @@ -307,8 +307,8 @@ static const struct iio_chan_spec adxrs450_channels[] = { .type = IIO_ANGL_VEL, .modified = 1, .channel2 = IIO_MOD_Z, - .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE) + .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE_BIT, }, { .type = IIO_TEMP, .indexed = 1, diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h index 4fb4cc42399b..66c2604c92c4 100644 --- a/drivers/staging/iio/iio.h +++ b/drivers/staging/iio/iio.h @@ -27,24 +27,54 @@ enum iio_data_type { /* Could add the raw attributes as well - allowing buffer only devices */ enum iio_chan_info_enum { /* 0 is reserverd for raw attributes */ - IIO_CHAN_INFO_SCALE_SHARED = 2, - IIO_CHAN_INFO_SCALE_SEPARATE, - IIO_CHAN_INFO_OFFSET_SHARED, - IIO_CHAN_INFO_OFFSET_SEPARATE, - IIO_CHAN_INFO_CALIBSCALE_SHARED, - IIO_CHAN_INFO_CALIBSCALE_SEPARATE, - IIO_CHAN_INFO_CALIBBIAS_SHARED, - IIO_CHAN_INFO_CALIBBIAS_SEPARATE, - IIO_CHAN_INFO_PEAK_SHARED, - IIO_CHAN_INFO_PEAK_SEPARATE, - IIO_CHAN_INFO_PEAK_SCALE_SHARED, - IIO_CHAN_INFO_PEAK_SCALE_SEPARATE, - IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SHARED, - IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE, - IIO_CHAN_INFO_AVERAGE_RAW_SHARED, - IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE, + IIO_CHAN_INFO_SCALE = 1, + IIO_CHAN_INFO_OFFSET, + IIO_CHAN_INFO_CALIBSCALE, + IIO_CHAN_INFO_CALIBBIAS, + IIO_CHAN_INFO_PEAK, + IIO_CHAN_INFO_PEAK_SCALE, + IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW, + IIO_CHAN_INFO_AVERAGE_RAW, }; +#define IIO_CHAN_INFO_SHARED_BIT(type) BIT(type*2) +#define IIO_CHAN_INFO_SEPARATE_BIT(type) BIT(type*2 + 1) + +#define IIO_CHAN_INFO_SCALE_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_SCALE) +#define IIO_CHAN_INFO_SCALE_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_SCALE) +#define IIO_CHAN_INFO_OFFSET_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_OFFSET) +#define IIO_CHAN_INFO_OFFSET_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_OFFSET) +#define IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_CALIBSCALE) +#define IIO_CHAN_INFO_CALIBSCALE_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_CALIBSCALE) +#define IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_CALIBBIAS) +#define IIO_CHAN_INFO_CALIBBIAS_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_CALIBBIAS) +#define IIO_CHAN_INFO_PEAK_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_PEAK) +#define IIO_CHAN_INFO_PEAK_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_PEAK) +#define IIO_CHAN_INFO_PEAKSCALE_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_PEAKSCALE) +#define IIO_CHAN_INFO_PEAKSCALE_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_PEAKSCALE) +#define IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT( \ + IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW) +#define IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT( \ + IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW) +#define IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE_BIT \ + IIO_CHAN_INFO_SEPARATE_BIT(IIO_CHAN_INFO_AVERAGE_RAW) +#define IIO_CHAN_INFO_AVERAGE_RAW_SHARED_BIT \ + IIO_CHAN_INFO_SHARED_BIT(IIO_CHAN_INFO_AVERAGE_RAW) + enum iio_endian { IIO_CPU, IIO_BE, diff --git a/drivers/staging/iio/iio_simple_dummy.c b/drivers/staging/iio/iio_simple_dummy.c index 2196ff19f7b4..228f991d40ec 100644 --- a/drivers/staging/iio/iio_simple_dummy.c +++ b/drivers/staging/iio/iio_simple_dummy.c @@ -77,13 +77,13 @@ static struct iio_chan_spec iio_dummy_channels[] = { * Offset for userspace to apply prior to scale * when converting to standard units (microvolts) */ - (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | + IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | /* * in_voltage0_scale * Multipler for userspace to apply post offset * when converting to standard units (microvolts) */ - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, /* The ordering of elements in the buffer via an enum */ .scan_index = voltage0, .scan_type = { /* Description of storage in buffer */ @@ -118,7 +118,7 @@ static struct iio_chan_spec iio_dummy_channels[] = { * Shared version of scale - shared by differential * input channels of type IIO_VOLTAGE. */ - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, .scan_index = diffvoltage1m2, .scan_type = { /* Description of storage in buffer */ .sign = 's', /* signed */ @@ -135,7 +135,7 @@ static struct iio_chan_spec iio_dummy_channels[] = { .channel = 3, .channel2 = 4, .info_mask = - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, .scan_index = diffvoltage3m4, .scan_type = { .sign = 's', @@ -160,7 +160,7 @@ static struct iio_chan_spec iio_dummy_channels[] = { * seeing the readings. Typically part of hardware * calibration. */ - (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE), + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, .scan_index = accelx, .scan_type = { /* Description of storage in buffer */ .sign = 's', /* signed */ @@ -229,29 +229,32 @@ static int iio_dummy_read_raw(struct iio_dev *indio_dev, break; } break; - case IIO_CHAN_INFO_OFFSET_SEPARATE: + case IIO_CHAN_INFO_OFFSET: /* only single ended adc -> 7 */ *val = 7; ret = IIO_VAL_INT; break; - case IIO_CHAN_INFO_SCALE_SEPARATE: - /* only single ended adc -> 0.001333 */ - *val = 0; - *val2 = 1333; - ret = IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_SCALE: + switch (chan->differential) { + case 0: + /* only single ended adc -> 0.001333 */ + *val = 0; + *val2 = 1333; + ret = IIO_VAL_INT_PLUS_MICRO; + break; + case 1: + /* all differential adc channels -> 0.000001344 */ + *val = 0; + *val2 = 1344; + ret = IIO_VAL_INT_PLUS_NANO; + } break; - case IIO_CHAN_INFO_SCALE_SHARED: - /* all differential adc channels -> 0.000001344 */ - *val = 0; - *val2 = 1344; - ret = IIO_VAL_INT_PLUS_NANO; - break; - case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: + case IIO_CHAN_INFO_CALIBBIAS: /* only the acceleration axis - read from cache */ *val = st->accel_calibbias; ret = IIO_VAL_INT; break; - case IIO_CHAN_INFO_CALIBSCALE_SEPARATE: + case IIO_CHAN_INFO_CALIBSCALE: *val = st->accel_calibscale->val; *val2 = st->accel_calibscale->val2; ret = IIO_VAL_INT_PLUS_MICRO; @@ -296,7 +299,7 @@ static int iio_dummy_write_raw(struct iio_dev *indio_dev, st->dac_val = val; mutex_unlock(&st->lock); return 0; - case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: + case IIO_CHAN_INFO_CALIBBIAS: mutex_lock(&st->lock); /* Compare against table - hard matching here */ for (i = 0; i < ARRAY_SIZE(dummy_scales); i++) diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index 430743dfe9e0..966f768819f1 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -113,10 +113,10 @@ static struct iio_chan_spec ad5933_channels[] = { 0, AD5933_REG_TEMP_DATA, IIO_ST('s', 14, 16, 0), 0), /* Ring Channels */ IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "real_raw", 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, AD5933_REG_REAL_DATA, 0, IIO_ST('s', 16, 16, 0), 0), IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "imag_raw", 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, AD5933_REG_IMAG_DATA, 1, IIO_ST('s', 16, 16, 0), 0), }; diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c index 0018272625c3..174454a8294c 100644 --- a/drivers/staging/iio/imu/adis16400_core.c +++ b/drivers/staging/iio/imu/adis16400_core.c @@ -464,7 +464,7 @@ static int adis16400_write_raw(struct iio_dev *indio_dev, int ret; switch (mask) { - case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: + case IIO_CHAN_INFO_CALIBBIAS: mutex_lock(&indio_dev->mlock); ret = adis16400_spi_write_reg_16(indio_dev, adis16400_addresses[chan->address][1], @@ -504,8 +504,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, *val = val16; mutex_unlock(&indio_dev->mlock); return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE_SHARED: - case IIO_CHAN_INFO_SCALE_SEPARATE: + case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_ANGL_VEL: *val = 0; @@ -533,7 +532,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, default: return -EINVAL; } - case IIO_CHAN_INFO_CALIBBIAS_SEPARATE: + case IIO_CHAN_INFO_CALIBBIAS: mutex_lock(&indio_dev->mlock); ret = adis16400_spi_read_reg_16(indio_dev, adis16400_addresses[chan->address][1], @@ -544,7 +543,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, val16 = ((val16 & 0xFFF) << 4) >> 4; *val = val16; return IIO_VAL_INT; - case IIO_CHAN_INFO_OFFSET_SEPARATE: + case IIO_CHAN_INFO_OFFSET: /* currently only temperature */ *val = 198; *val2 = 160000; @@ -560,7 +559,7 @@ static struct iio_chan_spec adis16400_channels[] = { .indexed = 1, .channel = 0, .extend_name = "supply", - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, .address = in_supply, .scan_index = ADIS16400_SCAN_SUPPLY, .scan_type = IIO_ST('u', 14, 16, 0) @@ -568,8 +567,8 @@ static struct iio_chan_spec adis16400_channels[] = { .type = IIO_ANGL_VEL, .modified = 1, .channel2 = IIO_MOD_X, - .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = gyro_x, .scan_index = ADIS16400_SCAN_GYRO_X, .scan_type = IIO_ST('s', 14, 16, 0) @@ -577,8 +576,8 @@ static struct iio_chan_spec adis16400_channels[] = { .type = IIO_ANGL_VEL, .modified = 1, .channel2 = IIO_MOD_Y, - .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = gyro_y, .scan_index = ADIS16400_SCAN_GYRO_Y, .scan_type = IIO_ST('s', 14, 16, 0), @@ -586,8 +585,8 @@ static struct iio_chan_spec adis16400_channels[] = { .type = IIO_ANGL_VEL, .modified = 1, .channel2 = IIO_MOD_Z, - .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = gyro_z, .scan_index = ADIS16400_SCAN_GYRO_Z, .scan_type = IIO_ST('s', 14, 16, 0), @@ -595,8 +594,8 @@ static struct iio_chan_spec adis16400_channels[] = { .type = IIO_ACCEL, .modified = 1, .channel2 = IIO_MOD_X, - .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = accel_x, .scan_index = ADIS16400_SCAN_ACC_X, .scan_type = IIO_ST('s', 14, 16, 0), @@ -604,8 +603,8 @@ static struct iio_chan_spec adis16400_channels[] = { .type = IIO_ACCEL, .modified = 1, .channel2 = IIO_MOD_Y, - .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = accel_y, .scan_index = ADIS16400_SCAN_ACC_Y, .scan_type = IIO_ST('s', 14, 16, 0), @@ -613,8 +612,8 @@ static struct iio_chan_spec adis16400_channels[] = { .type = IIO_ACCEL, .modified = 1, .channel2 = IIO_MOD_Z, - .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = accel_z, .scan_index = ADIS16400_SCAN_ACC_Z, .scan_type = IIO_ST('s', 14, 16, 0), @@ -622,7 +621,7 @@ static struct iio_chan_spec adis16400_channels[] = { .type = IIO_MAGN, .modified = 1, .channel2 = IIO_MOD_X, - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = magn_x, .scan_index = ADIS16400_SCAN_MAGN_X, .scan_type = IIO_ST('s', 14, 16, 0), @@ -630,7 +629,7 @@ static struct iio_chan_spec adis16400_channels[] = { .type = IIO_MAGN, .modified = 1, .channel2 = IIO_MOD_Y, - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = magn_y, .scan_index = ADIS16400_SCAN_MAGN_Y, .scan_type = IIO_ST('s', 14, 16, 0), @@ -638,7 +637,7 @@ static struct iio_chan_spec adis16400_channels[] = { .type = IIO_MAGN, .modified = 1, .channel2 = IIO_MOD_Z, - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = magn_z, .scan_index = ADIS16400_SCAN_MAGN_Z, .scan_type = IIO_ST('s', 14, 16, 0), @@ -646,8 +645,8 @@ static struct iio_chan_spec adis16400_channels[] = { .type = IIO_TEMP, .indexed = 1, .channel = 0, - .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, .address = temp, .scan_index = ADIS16400_SCAN_TEMP, .scan_type = IIO_ST('s', 12, 16, 0), @@ -655,7 +654,7 @@ static struct iio_chan_spec adis16400_channels[] = { .type = IIO_VOLTAGE, .indexed = 1, .channel = 1, - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, .address = in1, .scan_index = ADIS16400_SCAN_ADC_0, .scan_type = IIO_ST('s', 12, 16, 0), @@ -669,7 +668,7 @@ static struct iio_chan_spec adis16350_channels[] = { .indexed = 1, .channel = 0, .extend_name = "supply", - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, .address = in_supply, .scan_index = ADIS16400_SCAN_SUPPLY, .scan_type = IIO_ST('u', 12, 16, 0) @@ -677,8 +676,8 @@ static struct iio_chan_spec adis16350_channels[] = { .type = IIO_ANGL_VEL, .modified = 1, .channel2 = IIO_MOD_X, - .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = gyro_x, .scan_index = ADIS16400_SCAN_GYRO_X, .scan_type = IIO_ST('s', 14, 16, 0) @@ -686,8 +685,8 @@ static struct iio_chan_spec adis16350_channels[] = { .type = IIO_ANGL_VEL, .modified = 1, .channel2 = IIO_MOD_Y, - .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = gyro_y, .scan_index = ADIS16400_SCAN_GYRO_Y, .scan_type = IIO_ST('s', 14, 16, 0), @@ -695,8 +694,8 @@ static struct iio_chan_spec adis16350_channels[] = { .type = IIO_ANGL_VEL, .modified = 1, .channel2 = IIO_MOD_Z, - .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = gyro_z, .scan_index = ADIS16400_SCAN_GYRO_Z, .scan_type = IIO_ST('s', 14, 16, 0), @@ -704,8 +703,8 @@ static struct iio_chan_spec adis16350_channels[] = { .type = IIO_ACCEL, .modified = 1, .channel2 = IIO_MOD_X, - .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = accel_x, .scan_index = ADIS16400_SCAN_ACC_X, .scan_type = IIO_ST('s', 14, 16, 0), @@ -713,8 +712,8 @@ static struct iio_chan_spec adis16350_channels[] = { .type = IIO_ACCEL, .modified = 1, .channel2 = IIO_MOD_Y, - .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = accel_y, .scan_index = ADIS16400_SCAN_ACC_Y, .scan_type = IIO_ST('s', 14, 16, 0), @@ -722,8 +721,8 @@ static struct iio_chan_spec adis16350_channels[] = { .type = IIO_ACCEL, .modified = 1, .channel2 = IIO_MOD_Z, - .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = accel_z, .scan_index = ADIS16400_SCAN_ACC_Z, .scan_type = IIO_ST('s', 14, 16, 0), @@ -732,8 +731,8 @@ static struct iio_chan_spec adis16350_channels[] = { .indexed = 1, .channel = 0, .extend_name = "x", - .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, .address = temp0, .scan_index = ADIS16350_SCAN_TEMP_X, .scan_type = IIO_ST('s', 12, 16, 0), @@ -742,8 +741,8 @@ static struct iio_chan_spec adis16350_channels[] = { .indexed = 1, .channel = 1, .extend_name = "y", - .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, .address = temp1, .scan_index = ADIS16350_SCAN_TEMP_Y, .scan_type = IIO_ST('s', 12, 16, 0), @@ -752,8 +751,8 @@ static struct iio_chan_spec adis16350_channels[] = { .indexed = 1, .channel = 2, .extend_name = "z", - .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, .address = temp2, .scan_index = ADIS16350_SCAN_TEMP_Z, .scan_type = IIO_ST('s', 12, 16, 0), @@ -761,7 +760,7 @@ static struct iio_chan_spec adis16350_channels[] = { .type = IIO_VOLTAGE, .indexed = 1, .channel = 1, - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, .address = in1, .scan_index = ADIS16350_SCAN_ADC_0, .scan_type = IIO_ST('s', 12, 16, 0), @@ -775,7 +774,7 @@ static struct iio_chan_spec adis16300_channels[] = { .indexed = 1, .channel = 0, .extend_name = "supply", - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, .address = in_supply, .scan_index = ADIS16400_SCAN_SUPPLY, .scan_type = IIO_ST('u', 12, 16, 0) @@ -783,8 +782,8 @@ static struct iio_chan_spec adis16300_channels[] = { .type = IIO_ANGL_VEL, .modified = 1, .channel2 = IIO_MOD_X, - .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = gyro_x, .scan_index = ADIS16400_SCAN_GYRO_X, .scan_type = IIO_ST('s', 14, 16, 0), @@ -792,8 +791,8 @@ static struct iio_chan_spec adis16300_channels[] = { .type = IIO_ACCEL, .modified = 1, .channel2 = IIO_MOD_X, - .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = accel_x, .scan_index = ADIS16400_SCAN_ACC_X, .scan_type = IIO_ST('s', 14, 16, 0), @@ -801,8 +800,8 @@ static struct iio_chan_spec adis16300_channels[] = { .type = IIO_ACCEL, .modified = 1, .channel2 = IIO_MOD_Y, - .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = accel_y, .scan_index = ADIS16400_SCAN_ACC_Y, .scan_type = IIO_ST('s', 14, 16, 0), @@ -810,8 +809,8 @@ static struct iio_chan_spec adis16300_channels[] = { .type = IIO_ACCEL, .modified = 1, .channel2 = IIO_MOD_Z, - .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = accel_z, .scan_index = ADIS16400_SCAN_ACC_Z, .scan_type = IIO_ST('s', 14, 16, 0), @@ -819,8 +818,8 @@ static struct iio_chan_spec adis16300_channels[] = { .type = IIO_TEMP, .indexed = 1, .channel = 0, - .info_mask = (1 << IIO_CHAN_INFO_OFFSET_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .info_mask = IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, .address = temp, .scan_index = ADIS16400_SCAN_TEMP, .scan_type = IIO_ST('s', 12, 16, 0), @@ -828,7 +827,7 @@ static struct iio_chan_spec adis16300_channels[] = { .type = IIO_VOLTAGE, .indexed = 1, .channel = 1, - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), + .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, .address = in1, .scan_index = ADIS16350_SCAN_ADC_0, .scan_type = IIO_ST('s', 12, 16, 0), @@ -836,7 +835,7 @@ static struct iio_chan_spec adis16300_channels[] = { .type = IIO_INCLI, .modified = 1, .channel2 = IIO_MOD_X, - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = incli_x, .scan_index = ADIS16300_SCAN_INCLI_X, .scan_type = IIO_ST('s', 13, 16, 0), @@ -844,7 +843,7 @@ static struct iio_chan_spec adis16300_channels[] = { .type = IIO_INCLI, .modified = 1, .channel2 = IIO_MOD_Y, - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = incli_y, .scan_index = ADIS16300_SCAN_INCLI_Y, .scan_type = IIO_ST('s', 13, 16, 0), @@ -857,8 +856,8 @@ static const struct iio_chan_spec adis16334_channels[] = { .type = IIO_ANGL_VEL, .modified = 1, .channel2 = IIO_MOD_X, - .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = gyro_x, .scan_index = ADIS16400_SCAN_GYRO_X, .scan_type = IIO_ST('s', 14, 16, 0), @@ -866,8 +865,8 @@ static const struct iio_chan_spec adis16334_channels[] = { .type = IIO_ANGL_VEL, .modified = 1, .channel2 = IIO_MOD_Y, - .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = gyro_y, .scan_index = ADIS16400_SCAN_GYRO_Y, .scan_type = IIO_ST('s', 14, 16, 0), @@ -875,8 +874,8 @@ static const struct iio_chan_spec adis16334_channels[] = { .type = IIO_ANGL_VEL, .modified = 1, .channel2 = IIO_MOD_Z, - .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = gyro_z, .scan_index = ADIS16400_SCAN_GYRO_Z, .scan_type = IIO_ST('s', 14, 16, 0), @@ -884,8 +883,8 @@ static const struct iio_chan_spec adis16334_channels[] = { .type = IIO_ACCEL, .modified = 1, .channel2 = IIO_MOD_X, - .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = accel_x, .scan_index = ADIS16400_SCAN_ACC_X, .scan_type = IIO_ST('s', 14, 16, 0), @@ -893,8 +892,8 @@ static const struct iio_chan_spec adis16334_channels[] = { .type = IIO_ACCEL, .modified = 1, .channel2 = IIO_MOD_Y, - .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = accel_y, .scan_index = ADIS16400_SCAN_ACC_Y, .scan_type = IIO_ST('s', 14, 16, 0), @@ -902,8 +901,8 @@ static const struct iio_chan_spec adis16334_channels[] = { .type = IIO_ACCEL, .modified = 1, .channel2 = IIO_MOD_Z, - .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = accel_z, .scan_index = ADIS16400_SCAN_ACC_Z, .scan_type = IIO_ST('s', 14, 16, 0), @@ -911,8 +910,8 @@ static const struct iio_chan_spec adis16334_channels[] = { .type = IIO_TEMP, .indexed = 1, .channel = 0, - .info_mask = (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE) | - (1 << IIO_CHAN_INFO_SCALE_SHARED), + .info_mask = IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = accel_z, .scan_index = ADIS16400_SCAN_ACC_Z, .scan_type = IIO_ST('s', 14, 16, 0), diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c index 63681a61d5ca..dc2339ae63d0 100644 --- a/drivers/staging/iio/industrialio-core.c +++ b/drivers/staging/iio/industrialio-core.c @@ -77,15 +77,14 @@ static const char * const iio_modifier_names[] = { /* relies on pairs of these shared then separate */ static const char * const iio_chan_info_postfix[] = { - [IIO_CHAN_INFO_SCALE_SHARED/2] = "scale", - [IIO_CHAN_INFO_OFFSET_SHARED/2] = "offset", - [IIO_CHAN_INFO_CALIBSCALE_SHARED/2] = "calibscale", - [IIO_CHAN_INFO_CALIBBIAS_SHARED/2] = "calibbias", - [IIO_CHAN_INFO_PEAK_SHARED/2] = "peak_raw", - [IIO_CHAN_INFO_PEAK_SCALE_SHARED/2] = "peak_scale", - [IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SHARED/2] - = "quadrature_correction_raw", - [IIO_CHAN_INFO_AVERAGE_RAW_SHARED/2] = "mean_raw", + [IIO_CHAN_INFO_SCALE] = "scale", + [IIO_CHAN_INFO_OFFSET] = "offset", + [IIO_CHAN_INFO_CALIBSCALE] = "calibscale", + [IIO_CHAN_INFO_CALIBBIAS] = "calibbias", + [IIO_CHAN_INFO_PEAK] = "peak_raw", + [IIO_CHAN_INFO_PEAK_SCALE] = "peak_scale", + [IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW] = "quadrature_correction_raw", + [IIO_CHAN_INFO_AVERAGE_RAW] = "mean_raw", }; /** @@ -603,7 +602,7 @@ static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev, chan, &iio_read_channel_info, &iio_write_channel_info, - i, + i/2, !(i%2), &indio_dev->dev, &indio_dev->channel_attr_list); diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index bed18a74d30c..f0c733a2826a 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -362,8 +362,7 @@ static int isl29018_write_raw(struct iio_dev *indio_dev, int ret = -EINVAL; mutex_lock(&chip->lock); - if (mask == IIO_CHAN_INFO_CALIBSCALE_SEPARATE && - chan->type == IIO_LIGHT) { + if (mask == IIO_CHAN_INFO_CALIBSCALE && chan->type == IIO_LIGHT) { chip->lux_scale = val; ret = 0; } @@ -402,7 +401,7 @@ static int isl29018_read_raw(struct iio_dev *indio_dev, if (!ret) ret = IIO_VAL_INT; break; - case IIO_CHAN_INFO_CALIBSCALE_SEPARATE: + case IIO_CHAN_INFO_CALIBSCALE: if (chan->type == IIO_LIGHT) { *val = chip->lux_scale; ret = IIO_VAL_INT; @@ -421,7 +420,7 @@ static const struct iio_chan_spec isl29018_channels[] = { .indexed = 1, .channel = 0, .processed_val = IIO_PROCESSED, - .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE), + .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT, }, { .type = IIO_INTENSITY, .modified = 1, diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c index 45d04a1b1940..9199ea62aef6 100644 --- a/drivers/staging/iio/light/tsl2563.c +++ b/drivers/staging/iio/light/tsl2563.c @@ -513,7 +513,7 @@ static int tsl2563_read_raw(struct iio_dev *indio_dev, } break; - case IIO_CHAN_INFO_CALIBSCALE_SEPARATE: + case IIO_CHAN_INFO_CALIBSCALE: if (chan->channel == 0) *val = calib_to_sysfs(chip->calib0); else @@ -539,7 +539,7 @@ static const struct iio_chan_spec tsl2563_channels[] = { .type = IIO_INTENSITY, .modified = 1, .channel2 = IIO_MOD_LIGHT_BOTH, - .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE), + .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT, .event_mask = (IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) | IIO_EV_BIT(IIO_EV_TYPE_THRESH, @@ -548,7 +548,7 @@ static const struct iio_chan_spec tsl2563_channels[] = { .type = IIO_INTENSITY, .modified = 1, .channel2 = IIO_MOD_LIGHT_IR, - .info_mask = (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE), + .info_mask = IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT, } }; diff --git a/drivers/staging/iio/magnetometer/ak8975.c b/drivers/staging/iio/magnetometer/ak8975.c index b7d8cbb58c37..a2c4d005803d 100644 --- a/drivers/staging/iio/magnetometer/ak8975.c +++ b/drivers/staging/iio/magnetometer/ak8975.c @@ -431,7 +431,7 @@ static int ak8975_read_raw(struct iio_dev *indio_dev, switch (mask) { case 0: return ak8975_read_axis(indio_dev, chan->address, val); - case IIO_CHAN_INFO_SCALE_SEPARATE: + case IIO_CHAN_INFO_SCALE: *val = data->raw_to_gauss[chan->address]; return IIO_VAL_INT; } @@ -443,7 +443,7 @@ static int ak8975_read_raw(struct iio_dev *indio_dev, .type = IIO_MAGN, \ .modified = 1, \ .channel2 = IIO_MOD_##axis, \ - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), \ + .info_mask = IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ .address = index, \ } diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c index 4a42707a20ef..f90d4d124180 100644 --- a/drivers/staging/iio/magnetometer/hmc5843.c +++ b/drivers/staging/iio/magnetometer/hmc5843.c @@ -463,7 +463,7 @@ static int hmc5843_read_raw(struct iio_dev *indio_dev, return hmc5843_read_measurement(indio_dev, chan->address, val); - case IIO_CHAN_INFO_SCALE_SHARED: + case IIO_CHAN_INFO_SCALE: *val = 0; *val2 = hmc5843_regval_to_nanoscale[data->range]; return IIO_VAL_INT_PLUS_NANO; @@ -476,7 +476,7 @@ static int hmc5843_read_raw(struct iio_dev *indio_dev, .type = IIO_MAGN, \ .modified = 1, \ .channel2 = IIO_MOD_##axis, \ - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), \ + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \ .address = add \ } diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c index 7028e87acb41..839b48b1b489 100644 --- a/drivers/staging/iio/meter/ade7758_core.c +++ b/drivers/staging/iio/meter/ade7758_core.c @@ -663,63 +663,63 @@ static const struct attribute_group ade7758_attribute_group = { static struct iio_chan_spec ade7758_channels[] = { IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "raw", 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, AD7758_WT(AD7758_PHASE_A, AD7758_VOLTAGE), 0, IIO_ST('s', 24, 32, 0), 0), IIO_CHAN(IIO_CURRENT, 0, 1, 0, "raw", 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, AD7758_WT(AD7758_PHASE_A, AD7758_CURRENT), 1, IIO_ST('s', 24, 32, 0), 0), IIO_CHAN(IIO_POWER, 0, 1, 0, "apparent_raw", 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, AD7758_WT(AD7758_PHASE_A, AD7758_APP_PWR), 2, IIO_ST('s', 24, 32, 0), 0), IIO_CHAN(IIO_POWER, 0, 1, 0, "active_raw", 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, AD7758_WT(AD7758_PHASE_A, AD7758_ACT_PWR), 3, IIO_ST('s', 24, 32, 0), 0), IIO_CHAN(IIO_POWER, 0, 1, 0, "reactive_raw", 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, AD7758_WT(AD7758_PHASE_A, AD7758_REACT_PWR), 4, IIO_ST('s', 24, 32, 0), 0), IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "raw", 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, AD7758_WT(AD7758_PHASE_B, AD7758_VOLTAGE), 5, IIO_ST('s', 24, 32, 0), 0), IIO_CHAN(IIO_CURRENT, 0, 1, 0, "raw", 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, AD7758_WT(AD7758_PHASE_B, AD7758_CURRENT), 6, IIO_ST('s', 24, 32, 0), 0), IIO_CHAN(IIO_POWER, 0, 1, 0, "apparent_raw", 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, AD7758_WT(AD7758_PHASE_B, AD7758_APP_PWR), 7, IIO_ST('s', 24, 32, 0), 0), IIO_CHAN(IIO_POWER, 0, 1, 0, "active_raw", 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, AD7758_WT(AD7758_PHASE_B, AD7758_ACT_PWR), 8, IIO_ST('s', 24, 32, 0), 0), IIO_CHAN(IIO_POWER, 0, 1, 0, "reactive_raw", 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, AD7758_WT(AD7758_PHASE_B, AD7758_REACT_PWR), 9, IIO_ST('s', 24, 32, 0), 0), IIO_CHAN(IIO_VOLTAGE, 0, 1, 0, "raw", 2, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, AD7758_WT(AD7758_PHASE_C, AD7758_VOLTAGE), 10, IIO_ST('s', 24, 32, 0), 0), IIO_CHAN(IIO_CURRENT, 0, 1, 0, "raw", 2, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, AD7758_WT(AD7758_PHASE_C, AD7758_CURRENT), 11, IIO_ST('s', 24, 32, 0), 0), IIO_CHAN(IIO_POWER, 0, 1, 0, "apparent_raw", 2, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, AD7758_WT(AD7758_PHASE_C, AD7758_APP_PWR), 12, IIO_ST('s', 24, 32, 0), 0), IIO_CHAN(IIO_POWER, 0, 1, 0, "active_raw", 2, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, AD7758_WT(AD7758_PHASE_C, AD7758_ACT_PWR), 13, IIO_ST('s', 24, 32, 0), 0), IIO_CHAN(IIO_POWER, 0, 1, 0, "reactive_raw", 2, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), + IIO_CHAN_INFO_SCALE_SHARED_BIT, AD7758_WT(AD7758_PHASE_C, AD7758_REACT_PWR), 14, IIO_ST('s', 24, 32, 0), 0), IIO_CHAN_SOFT_TIMESTAMP(15), From 23a3b8cc9ce1bec3e21ca6e90566cf30caa760e5 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 29 Oct 2011 10:20:42 +0300 Subject: [PATCH 038/365] Staging: iio/dac/ad5064.c: signedness bug in ad5064_read_raw() regulator_get_voltage() returns an int so "scale_uv" should be an int. Making it unsigned here breaks the error handling. Signed-off-by: Dan Carpenter Acked-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/ad5064.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/dac/ad5064.c b/drivers/staging/iio/dac/ad5064.c index a701063a9267..867e4ab1ff63 100644 --- a/drivers/staging/iio/dac/ad5064.c +++ b/drivers/staging/iio/dac/ad5064.c @@ -280,8 +280,8 @@ static int ad5064_read_raw(struct iio_dev *indio_dev, long m) { struct ad5064_state *st = iio_priv(indio_dev); - unsigned long scale_uv; unsigned int vref; + int scale_uv; switch (m) { case 0: From 685e010748f64a752a981254101e976d7291d16c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 29 Oct 2011 10:21:06 +0300 Subject: [PATCH 039/365] Staging: iio/dac/ad5360.c: signedness bug in ad5360_read_raw() ad5360_get_channel_vref() returns an int and scale_uv should be the same. Making it unsigned here breaks the error handling. Signed-off-by: Dan Carpenter Acked-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/ad5360.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/dac/ad5360.c b/drivers/staging/iio/dac/ad5360.c index c5bf5827c137..012d7147e496 100644 --- a/drivers/staging/iio/dac/ad5360.c +++ b/drivers/staging/iio/dac/ad5360.c @@ -371,8 +371,8 @@ static int ad5360_read_raw(struct iio_dev *indio_dev, long m) { struct ad5360_state *st = iio_priv(indio_dev); - unsigned long scale_uv; unsigned int ofs_index; + int scale_uv; int ret; switch (m) { From 43c0364551d3ca0042f6f6a3da701edf1143d62f Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 2 Nov 2011 09:40:00 +0100 Subject: [PATCH 040/365] staging:iio: Make write_event_value callback optional Some devices have fixed thresholds which can not be modified so make the write_event_value callback optional, so the drivers for these devices do not have to implement a boilerplate no-op callback. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/industrialio-core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c index dc2339ae63d0..0b671663b55d 100644 --- a/drivers/staging/iio/industrialio-core.c +++ b/drivers/staging/iio/industrialio-core.c @@ -790,6 +790,9 @@ static ssize_t iio_ev_value_store(struct device *dev, unsigned long val; int ret; + if (!indio_dev->info->write_event_value) + return -EINVAL; + ret = strict_strtoul(buf, 10, &val); if (ret) return ret; From 19c2aedc54b927ab10d3723038182eedf90438a4 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 2 Nov 2011 09:40:01 +0100 Subject: [PATCH 041/365] staging:iio: IIO_EVENT_CODE: Clamp channel numbers Make sure we only use the allotted space for channel numbers in the event mask and do not let them override other fields. Since negative values are valid channel number, cast the channel number to signed when extracting it from an event mask. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/events.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/staging/iio/events.h b/drivers/staging/iio/events.h index 92759547b410..bfb63400fa60 100644 --- a/drivers/staging/iio/events.h +++ b/drivers/staging/iio/events.h @@ -56,7 +56,8 @@ enum iio_event_direction { type, chan, chan1, chan2) \ (((u64)type << 56) | ((u64)diff << 55) | \ ((u64)direction << 48) | ((u64)modifier << 40) | \ - ((u64)chan_type << 32) | (chan2 << 16) | chan1 | chan) + ((u64)chan_type << 32) | (((u16)chan2) << 16) | ((u16)chan1) | \ + ((u16)chan)) #define IIO_EV_DIR_MAX 4 @@ -95,7 +96,7 @@ enum iio_event_direction { /* Event code number extraction depends on which type of event we have. * Perhaps review this function in the future*/ -#define IIO_EVENT_CODE_EXTRACT_NUM(mask) (mask & 0xFFFF) +#define IIO_EVENT_CODE_EXTRACT_NUM(mask) ((__s16)(mask & 0xFFFF)) #define IIO_EVENT_CODE_EXTRACT_MODIFIER(mask) ((mask >> 40) & 0xFF) From 5691b23489db2b22ea1e87f3d8b1e8260cbb48fc Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 2 Nov 2011 09:40:02 +0100 Subject: [PATCH 042/365] staging:iio:dac: Add AD5421 driver This patch adds support for the Analog Devices AD5421 Loop-Powered, 4mA to 20mA DAC. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/Kconfig | 10 + drivers/staging/iio/dac/Makefile | 1 + drivers/staging/iio/dac/ad5421.c | 555 +++++++++++++++++++++++++++++++ drivers/staging/iio/dac/ad5421.h | 32 ++ 4 files changed, 598 insertions(+) create mode 100644 drivers/staging/iio/dac/ad5421.c create mode 100644 drivers/staging/iio/dac/ad5421.h diff --git a/drivers/staging/iio/dac/Kconfig b/drivers/staging/iio/dac/Kconfig index fac8549dc8e7..0e8983acb361 100644 --- a/drivers/staging/iio/dac/Kconfig +++ b/drivers/staging/iio/dac/Kconfig @@ -24,6 +24,16 @@ config AD5360 To compile this driver as module choose M here: the module will be called ad5360. +config AD5421 + tristate "Analog Devices AD5421 DAC driver" + depends on SPI + help + Say yes here to build support for Analog Devices AD5421 loop-powered + digital-to-analog convertors (DAC). + + To compile this driver as module choose M here: the module will be called + ad5421. + config AD5624R_SPI tristate "Analog Devices AD5624/44/64R DAC spi driver" depends on SPI diff --git a/drivers/staging/iio/dac/Makefile b/drivers/staging/iio/dac/Makefile index 07b6f5ebdb52..e75b0c8d88b1 100644 --- a/drivers/staging/iio/dac/Makefile +++ b/drivers/staging/iio/dac/Makefile @@ -3,6 +3,7 @@ # obj-$(CONFIG_AD5360) += ad5360.o +obj-$(CONFIG_AD5421) += ad5421.o obj-$(CONFIG_AD5624R_SPI) += ad5624r_spi.o obj-$(CONFIG_AD5064) += ad5064.o obj-$(CONFIG_AD5504) += ad5504.o diff --git a/drivers/staging/iio/dac/ad5421.c b/drivers/staging/iio/dac/ad5421.c new file mode 100644 index 000000000000..71ee86824763 --- /dev/null +++ b/drivers/staging/iio/dac/ad5421.c @@ -0,0 +1,555 @@ +/* + * AD5421 Digital to analog converters driver + * + * Copyright 2011 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../iio.h" +#include "../sysfs.h" +#include "../events.h" +#include "dac.h" +#include "ad5421.h" + + +#define AD5421_REG_DAC_DATA 0x1 +#define AD5421_REG_CTRL 0x2 +#define AD5421_REG_OFFSET 0x3 +#define AD5421_REG_GAIN 0x4 +/* load dac and fault shared the same register number. Writing to it will cause + * a dac load command, reading from it will return the fault status register */ +#define AD5421_REG_LOAD_DAC 0x5 +#define AD5421_REG_FAULT 0x5 +#define AD5421_REG_FORCE_ALARM_CURRENT 0x6 +#define AD5421_REG_RESET 0x7 +#define AD5421_REG_START_CONVERSION 0x8 +#define AD5421_REG_NOOP 0x9 + +#define AD5421_CTRL_WATCHDOG_DISABLE BIT(12) +#define AD5421_CTRL_AUTO_FAULT_READBACK BIT(11) +#define AD5421_CTRL_MIN_CURRENT BIT(9) +#define AD5421_CTRL_ADC_SOURCE_TEMP BIT(8) +#define AD5421_CTRL_ADC_ENABLE BIT(7) +#define AD5421_CTRL_PWR_DOWN_INT_VREF BIT(6) + +#define AD5421_FAULT_SPI BIT(15) +#define AD5421_FAULT_PEC BIT(14) +#define AD5421_FAULT_OVER_CURRENT BIT(13) +#define AD5421_FAULT_UNDER_CURRENT BIT(12) +#define AD5421_FAULT_TEMP_OVER_140 BIT(11) +#define AD5421_FAULT_TEMP_OVER_100 BIT(10) +#define AD5421_FAULT_UNDER_VOLTAGE_6V BIT(9) +#define AD5421_FAULT_UNDER_VOLTAGE_12V BIT(8) + +/* These bits will cause the fault pin to go high */ +#define AD5421_FAULT_TRIGGER_IRQ \ + (AD5421_FAULT_SPI | AD5421_FAULT_PEC | AD5421_FAULT_OVER_CURRENT | \ + AD5421_FAULT_UNDER_CURRENT | AD5421_FAULT_TEMP_OVER_140) + +/** + * struct ad5421_state - driver instance specific data + * @spi: spi_device + * @ctrl: control register cache + * @current_range: current range which the device is configured for + * @data: spi transfer buffers + * @fault_mask: software masking of events + */ +struct ad5421_state { + struct spi_device *spi; + unsigned int ctrl; + enum ad5421_current_range current_range; + unsigned int fault_mask; + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + union { + u32 d32; + u8 d8[4]; + } data[2] ____cacheline_aligned; +}; + +static const struct iio_chan_spec ad5421_channels[] = { + { + .type = IIO_CURRENT, + .indexed = 1, + .output = 1, + .channel = 0, + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT | + IIO_CHAN_INFO_OFFSET_SHARED_BIT | + IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | + IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, + .scan_type = IIO_ST('u', 16, 16, 0), + .event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) | + IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING), + }, + { + .type = IIO_TEMP, + .channel = -1, + .event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), + }, +}; + +static int ad5421_write_unlocked(struct iio_dev *indio_dev, + unsigned int reg, unsigned int val) +{ + struct ad5421_state *st = iio_priv(indio_dev); + + st->data[0].d32 = cpu_to_be32((reg << 16) | val); + + return spi_write(st->spi, &st->data[0].d8[1], 3); +} + +static int ad5421_write(struct iio_dev *indio_dev, unsigned int reg, + unsigned int val) +{ + int ret; + + mutex_lock(&indio_dev->mlock); + ret = ad5421_write_unlocked(indio_dev, reg, val); + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static int ad5421_read(struct iio_dev *indio_dev, unsigned int reg) +{ + struct ad5421_state *st = iio_priv(indio_dev); + struct spi_message m; + int ret; + struct spi_transfer t[] = { + { + .tx_buf = &st->data[0].d8[1], + .len = 3, + .cs_change = 1, + }, { + .rx_buf = &st->data[1].d8[1], + .len = 3, + }, + }; + + spi_message_init(&m); + spi_message_add_tail(&t[0], &m); + spi_message_add_tail(&t[1], &m); + + mutex_lock(&indio_dev->mlock); + + st->data[0].d32 = cpu_to_be32((1 << 23) | (reg << 16)); + + ret = spi_sync(st->spi, &m); + if (ret >= 0) + ret = be32_to_cpu(st->data[1].d32) & 0xffff; + + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static int ad5421_update_ctrl(struct iio_dev *indio_dev, unsigned int set, + unsigned int clr) +{ + struct ad5421_state *st = iio_priv(indio_dev); + unsigned int ret; + + mutex_lock(&indio_dev->mlock); + + st->ctrl &= ~clr; + st->ctrl |= set; + + ret = ad5421_write_unlocked(indio_dev, AD5421_REG_CTRL, st->ctrl); + + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static irqreturn_t ad5421_fault_handler(int irq, void *data) +{ + struct iio_dev *indio_dev = data; + struct ad5421_state *st = iio_priv(indio_dev); + unsigned int fault; + unsigned int old_fault = 0; + unsigned int events; + + fault = ad5421_read(indio_dev, AD5421_REG_FAULT); + if (!fault) + return IRQ_NONE; + + /* If we had a fault, this might mean that the DAC has lost its state + * and has been reset. Make sure that the control register actually + * contains what we expect it to contain. Otherwise the watchdog might + * be enabled and we get watchdog timeout faults, which will render the + * DAC unusable. */ + ad5421_update_ctrl(indio_dev, 0, 0); + + + /* The fault pin stays high as long as a fault condition is present and + * it is not possible to mask fault conditions. For certain fault + * conditions for example like over-temperature it takes some time + * until the fault condition disappears. If we would exit the interrupt + * handler immediately after handling the event it would be entered + * again instantly. Thus we fall back to polling in case we detect that + * a interrupt condition is still present. + */ + do { + /* 0xffff is a invalid value for the register and will only be + * read if there has been a communication error */ + if (fault == 0xffff) + fault = 0; + + /* we are only interested in new events */ + events = (old_fault ^ fault) & fault; + events &= st->fault_mask; + + if (events & AD5421_FAULT_OVER_CURRENT) { + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_CURRENT, + 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_RISING), + iio_get_time_ns()); + } + + if (events & AD5421_FAULT_UNDER_CURRENT) { + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_CURRENT, + 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_FALLING), + iio_get_time_ns()); + } + + if (events & AD5421_FAULT_TEMP_OVER_140) { + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_TEMP, + 0, + IIO_EV_TYPE_MAG, + IIO_EV_DIR_RISING), + iio_get_time_ns()); + } + + old_fault = fault; + fault = ad5421_read(indio_dev, AD5421_REG_FAULT); + + /* still active? go to sleep for some time */ + if (fault & AD5421_FAULT_TRIGGER_IRQ) + msleep(1000); + + } while (fault & AD5421_FAULT_TRIGGER_IRQ); + + + return IRQ_HANDLED; +} + +static void ad5421_get_current_min_max(struct ad5421_state *st, + unsigned int *min, unsigned int *max) +{ + /* The current range is configured using external pins, which are + * usually hard-wired and not run-time switchable. */ + switch (st->current_range) { + case AD5421_CURRENT_RANGE_4mA_20mA: + *min = 4000; + *max = 20000; + break; + case AD5421_CURRENT_RANGE_3mA8_21mA: + *min = 3800; + *max = 21000; + break; + case AD5421_CURRENT_RANGE_3mA2_24mA: + *min = 3200; + *max = 24000; + break; + default: + *min = 0; + *max = 1; + break; + } +} + +static inline unsigned int ad5421_get_offset(struct ad5421_state *st) +{ + unsigned int min, max; + + ad5421_get_current_min_max(st, &min, &max); + return (min * (1 << 16)) / (max - min); +} + +static inline unsigned int ad5421_get_scale(struct ad5421_state *st) +{ + unsigned int min, max; + + ad5421_get_current_min_max(st, &min, &max); + return ((max - min) * 1000) / (1 << 16); +} + +static int ad5421_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, int *val2, long m) +{ + struct ad5421_state *st = iio_priv(indio_dev); + int ret; + + if (chan->type != IIO_CURRENT) + return -EINVAL; + + switch (m) { + case 0: + ret = ad5421_read(indio_dev, AD5421_REG_DAC_DATA); + if (ret < 0) + return ret; + *val = ret; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 0; + *val2 = ad5421_get_scale(st); + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_OFFSET: + *val = ad5421_get_offset(st); + return IIO_VAL_INT; + case IIO_CHAN_INFO_CALIBBIAS: + ret = ad5421_read(indio_dev, AD5421_REG_OFFSET); + if (ret < 0) + return ret; + *val = ret - 32768; + return IIO_VAL_INT; + case IIO_CHAN_INFO_CALIBSCALE: + ret = ad5421_read(indio_dev, AD5421_REG_GAIN); + if (ret < 0) + return ret; + *val = ret; + return IIO_VAL_INT; + } + + return -EINVAL; +} + +static int ad5421_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, int val2, long mask) +{ + const unsigned int max_val = 1 << 16; + + switch (mask) { + case 0: + if (val >= max_val || val < 0) + return -EINVAL; + + return ad5421_write(indio_dev, AD5421_REG_DAC_DATA, val); + case IIO_CHAN_INFO_CALIBBIAS: + val += 32768; + if (val >= max_val || val < 0) + return -EINVAL; + + return ad5421_write(indio_dev, AD5421_REG_OFFSET, val); + case IIO_CHAN_INFO_CALIBSCALE: + if (val >= max_val || val < 0) + return -EINVAL; + + return ad5421_write(indio_dev, AD5421_REG_GAIN, val); + default: + break; + } + + return -EINVAL; +} + +static int ad5421_write_event_config(struct iio_dev *indio_dev, + u64 event_code, int state) +{ + struct ad5421_state *st = iio_priv(indio_dev); + unsigned int mask; + + switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) { + case IIO_CURRENT: + if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == + IIO_EV_DIR_RISING) + mask = AD5421_FAULT_OVER_CURRENT; + else + mask = AD5421_FAULT_UNDER_CURRENT; + break; + case IIO_TEMP: + mask = AD5421_FAULT_TEMP_OVER_140; + break; + default: + return -EINVAL; + } + + mutex_lock(&indio_dev->mlock); + if (state) + st->fault_mask |= mask; + else + st->fault_mask &= ~mask; + mutex_unlock(&indio_dev->mlock); + + return 0; +} + +static int ad5421_read_event_config(struct iio_dev *indio_dev, + u64 event_code) +{ + struct ad5421_state *st = iio_priv(indio_dev); + unsigned int mask; + + switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) { + case IIO_CURRENT: + if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == + IIO_EV_DIR_RISING) + mask = AD5421_FAULT_OVER_CURRENT; + else + mask = AD5421_FAULT_UNDER_CURRENT; + break; + case IIO_TEMP: + mask = AD5421_FAULT_TEMP_OVER_140; + break; + default: + return -EINVAL; + } + + return (bool)(st->fault_mask & mask); +} + +static int ad5421_read_event_value(struct iio_dev *indio_dev, u64 event_code, + int *val) +{ + int ret; + + switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) { + case IIO_CURRENT: + ret = ad5421_read(indio_dev, AD5421_REG_DAC_DATA); + if (ret < 0) + return ret; + *val = ret; + break; + case IIO_TEMP: + *val = 140000; + break; + default: + return -EINVAL; + } + + return 0; +} + +static const struct iio_info ad5421_info = { + .read_raw = ad5421_read_raw, + .write_raw = ad5421_write_raw, + .read_event_config = ad5421_read_event_config, + .write_event_config = ad5421_write_event_config, + .read_event_value = ad5421_read_event_value, + .driver_module = THIS_MODULE, +}; + +static int __devinit ad5421_probe(struct spi_device *spi) +{ + struct ad5421_platform_data *pdata = dev_get_platdata(&spi->dev); + struct iio_dev *indio_dev; + struct ad5421_state *st; + int ret; + + indio_dev = iio_allocate_device(sizeof(*st)); + if (indio_dev == NULL) { + dev_err(&spi->dev, "Failed to allocate iio device\n"); + return -ENOMEM; + } + + st = iio_priv(indio_dev); + spi_set_drvdata(spi, indio_dev); + + st->spi = spi; + + indio_dev->dev.parent = &spi->dev; + indio_dev->name = "ad5421"; + indio_dev->info = &ad5421_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = ad5421_channels; + indio_dev->num_channels = ARRAY_SIZE(ad5421_channels); + + st->ctrl = AD5421_CTRL_WATCHDOG_DISABLE | + AD5421_CTRL_AUTO_FAULT_READBACK; + + if (pdata) { + st->current_range = pdata->current_range; + if (pdata->external_vref) + st->ctrl |= AD5421_CTRL_PWR_DOWN_INT_VREF; + } else { + st->current_range = AD5421_CURRENT_RANGE_4mA_20mA; + } + + /* write initial ctrl register value */ + ad5421_update_ctrl(indio_dev, 0, 0); + + if (spi->irq) { + ret = request_threaded_irq(spi->irq, + NULL, + ad5421_fault_handler, + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + "ad5421 fault", + indio_dev); + if (ret) + goto error_free; + } + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(&spi->dev, "Failed to register iio device: %d\n", ret); + goto error_free_irq; + } + + return 0; + +error_free_irq: + if (spi->irq) + free_irq(spi->irq, indio_dev); +error_free: + iio_free_device(indio_dev); + + return ret; +} + +static int __devexit ad5421_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + + iio_device_unregister(indio_dev); + if (spi->irq) + free_irq(spi->irq, indio_dev); + iio_free_device(indio_dev); + + return 0; +} + +static struct spi_driver ad5421_driver = { + .driver = { + .name = "ad5421", + .owner = THIS_MODULE, + }, + .probe = ad5421_probe, + .remove = __devexit_p(ad5421_remove), +}; + +static __init int ad5421_init(void) +{ + return spi_register_driver(&ad5421_driver); +} +module_init(ad5421_init); + +static __exit void ad5421_exit(void) +{ + spi_unregister_driver(&ad5421_driver); +} +module_exit(ad5421_exit); + +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("Analog Devices AD5421 DAC"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("spi:ad5421"); diff --git a/drivers/staging/iio/dac/ad5421.h b/drivers/staging/iio/dac/ad5421.h new file mode 100644 index 000000000000..cd2bb84ff1b0 --- /dev/null +++ b/drivers/staging/iio/dac/ad5421.h @@ -0,0 +1,32 @@ +#ifndef __IIO_DAC_AD5421_H__ +#define __IIO_DAC_AD5421_H__ + +/* + * TODO: This file needs to go into include/linux/iio + */ + +/** + * enum ad5421_current_range - Current range the AD5421 is configured for. + * @AD5421_CURRENT_RANGE_4mA_20mA: 4 mA to 20 mA (RANGE1,0 pins = 00) + * @AD5421_CURRENT_RANGE_3mA8_21mA: 3.8 mA to 21 mA (RANGE1,0 pins = x1) + * @AD5421_CURRENT_RANGE_3mA2_24mA: 3.2 mA to 24 mA (RANGE1,0 pins = 10) + */ + +enum ad5421_current_range { + AD5421_CURRENT_RANGE_4mA_20mA, + AD5421_CURRENT_RANGE_3mA8_21mA, + AD5421_CURRENT_RANGE_3mA2_24mA, +}; + +/** + * struct ad5421_platform_data - AD5421 DAC driver platform data + * @external_vref: whether an external reference voltage is used or not + * @current_range: Current range the AD5421 is configured for + */ + +struct ad5421_platform_data { + bool external_vref; + enum ad5421_current_range current_range; +}; + +#endif From 465825963cabbd2e74a35c0a0f4e5c5f0cc1d1d0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 15 Nov 2011 16:34:50 +0100 Subject: [PATCH 043/365] staging:iio:dac:ad5446: Add support for the AD5662 The AD5662 is compatible to the AD5660, but uses an external reference instead of an internal. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/dac/Kconfig b/drivers/staging/iio/dac/Kconfig index 0e8983acb361..a71defb7f38a 100644 --- a/drivers/staging/iio/dac/Kconfig +++ b/drivers/staging/iio/dac/Kconfig @@ -47,7 +47,7 @@ config AD5446 help Say yes here to build support for Analog Devices AD5444, AD5446, AD5512A, AD5542A, AD5543, AD5553, AD5601, AD5611, AD5620, AD5621, - AD5640, AD5660 DACs. + AD5640, AD5660, AD5662 DACs. To compile this driver as a module, choose M here: the module will be called ad5446. From 73aaf63c5eceae44cda77ce982ec2b140ffbbb02 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Sun, 13 Nov 2011 14:05:45 +0100 Subject: [PATCH 044/365] staging: iio: drop "select IIO_SIMPLE_DUMMY_EVGEN" Commit e6477000fc ("staging:iio:dummy Add event support + fake event generator") added "select IIO_SIMPLE_DUMMY_EVGEN if [...]". But there is no Kconfig symbol named IIO_SIMPLE_DUMMY_EVGEN. The select statement for that symbol is a nop. Drop it. Signed-off-by: Paul Bolle Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/iio/Kconfig b/drivers/staging/iio/Kconfig index 4ec9118955f9..90162aa8b2df 100644 --- a/drivers/staging/iio/Kconfig +++ b/drivers/staging/iio/Kconfig @@ -76,7 +76,6 @@ config IIO_DUMMY_EVGEN config IIO_SIMPLE_DUMMY tristate "An example driver with no hardware requirements" - select IIO_SIMPLE_DUMMY_EVGEN if IIO_SIMPLE_DUMMY_EVENTS help Driver intended mainly as documentation for how to write a driver. May also be useful for testing userspace code From 33ad6b21f6fc8c113532b67856862deeec21e929 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 15 Nov 2011 16:31:22 +0100 Subject: [PATCH 045/365] staging:iio:dac:ad5446: Convert to channel spec Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/ad5446.c | 181 ++++++++++++++----------------- drivers/staging/iio/dac/ad5446.h | 10 +- 2 files changed, 83 insertions(+), 108 deletions(-) diff --git a/drivers/staging/iio/dac/ad5446.c b/drivers/staging/iio/dac/ad5446.c index e1c204d51d8c..a5882b83639a 100644 --- a/drivers/staging/iio/dac/ad5446.c +++ b/drivers/staging/iio/dac/ad5446.c @@ -26,19 +26,17 @@ static void ad5446_store_sample(struct ad5446_state *st, unsigned val) { - st->data.d16 = cpu_to_be16(AD5446_LOAD | - (val << st->chip_info->left_shift)); + st->data.d16 = cpu_to_be16(AD5446_LOAD | val); } static void ad5542_store_sample(struct ad5446_state *st, unsigned val) { - st->data.d16 = cpu_to_be16(val << st->chip_info->left_shift); + st->data.d16 = cpu_to_be16(val); } static void ad5620_store_sample(struct ad5446_state *st, unsigned val) { - st->data.d16 = cpu_to_be16(AD5620_LOAD | - (val << st->chip_info->left_shift)); + st->data.d16 = cpu_to_be16(AD5620_LOAD | val); } static void ad5660_store_sample(struct ad5446_state *st, unsigned val) @@ -63,50 +61,6 @@ static void ad5660_store_pwr_down(struct ad5446_state *st, unsigned mode) st->data.d24[2] = val & 0xFF; } -static ssize_t ad5446_write(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5446_state *st = iio_priv(indio_dev); - int ret; - long val; - - ret = strict_strtol(buf, 10, &val); - if (ret) - goto error_ret; - - if (val > RES_MASK(st->chip_info->bits)) { - ret = -EINVAL; - goto error_ret; - } - - mutex_lock(&indio_dev->mlock); - st->cached_val = val; - st->chip_info->store_sample(st, val); - ret = spi_sync(st->spi, &st->msg); - mutex_unlock(&indio_dev->mlock); - -error_ret: - return ret ? ret : len; -} - -static IIO_DEV_ATTR_OUT_RAW(0, ad5446_write, 0); - -static ssize_t ad5446_show_scale(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5446_state *st = iio_priv(indio_dev); - /* Corresponds to Vref / 2^(bits) */ - unsigned int scale_uv = (st->vref_mv * 1000) >> st->chip_info->bits; - - return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000); -} -static IIO_DEVICE_ATTR(out_voltage_scale, S_IRUGO, ad5446_show_scale, NULL, 0); - static ssize_t ad5446_write_powerdown_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) @@ -189,8 +143,6 @@ static IIO_DEVICE_ATTR(out_voltage0_powerdown, S_IRUGO | S_IWUSR, ad5446_write_dac_powerdown, 0); static struct attribute *ad5446_attributes[] = { - &iio_dev_attr_out_voltage0_raw.dev_attr.attr, - &iio_dev_attr_out_voltage_scale.dev_attr.attr, &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr, &iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr, &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr, @@ -223,121 +175,148 @@ static const struct attribute_group ad5446_attribute_group = { .is_visible = ad5446_attr_is_visible, }; +#define AD5446_CHANNEL(bits, storage, shift) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .output = 1, \ + .channel = 0, \ + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \ + .scan_type = IIO_ST('u', (bits), (storage), (shift)) \ +} + static const struct ad5446_chip_info ad5446_chip_info_tbl[] = { [ID_AD5444] = { - .bits = 12, - .storagebits = 16, - .left_shift = 2, + .channel = AD5446_CHANNEL(12, 16, 2), .store_sample = ad5446_store_sample, }, [ID_AD5446] = { - .bits = 14, - .storagebits = 16, - .left_shift = 0, + .channel = AD5446_CHANNEL(14, 16, 0), .store_sample = ad5446_store_sample, }, [ID_AD5541A] = { - .bits = 16, - .storagebits = 16, - .left_shift = 0, + .channel = AD5446_CHANNEL(16, 16, 0), .store_sample = ad5542_store_sample, }, [ID_AD5542A] = { - .bits = 16, - .storagebits = 16, - .left_shift = 0, + .channel = AD5446_CHANNEL(16, 16, 0), .store_sample = ad5542_store_sample, }, [ID_AD5543] = { - .bits = 16, - .storagebits = 16, - .left_shift = 0, + .channel = AD5446_CHANNEL(16, 16, 0), .store_sample = ad5542_store_sample, }, [ID_AD5512A] = { - .bits = 12, - .storagebits = 16, - .left_shift = 4, + .channel = AD5446_CHANNEL(12, 16, 4), .store_sample = ad5542_store_sample, }, [ID_AD5553] = { - .bits = 14, - .storagebits = 16, - .left_shift = 0, + .channel = AD5446_CHANNEL(14, 16, 0), .store_sample = ad5542_store_sample, }, [ID_AD5601] = { - .bits = 8, - .storagebits = 16, - .left_shift = 6, + .channel = AD5446_CHANNEL(8, 16, 6), .store_sample = ad5542_store_sample, .store_pwr_down = ad5620_store_pwr_down, }, [ID_AD5611] = { - .bits = 10, - .storagebits = 16, - .left_shift = 4, + .channel = AD5446_CHANNEL(10, 16, 4), .store_sample = ad5542_store_sample, .store_pwr_down = ad5620_store_pwr_down, }, [ID_AD5621] = { - .bits = 12, - .storagebits = 16, - .left_shift = 2, + .channel = AD5446_CHANNEL(12, 16, 2), .store_sample = ad5542_store_sample, .store_pwr_down = ad5620_store_pwr_down, }, [ID_AD5620_2500] = { - .bits = 12, - .storagebits = 16, - .left_shift = 2, + .channel = AD5446_CHANNEL(12, 16, 2), .int_vref_mv = 2500, .store_sample = ad5620_store_sample, .store_pwr_down = ad5620_store_pwr_down, }, [ID_AD5620_1250] = { - .bits = 12, - .storagebits = 16, - .left_shift = 2, + .channel = AD5446_CHANNEL(12, 16, 2), .int_vref_mv = 1250, .store_sample = ad5620_store_sample, .store_pwr_down = ad5620_store_pwr_down, }, [ID_AD5640_2500] = { - .bits = 14, - .storagebits = 16, - .left_shift = 0, + .channel = AD5446_CHANNEL(14, 16, 0), .int_vref_mv = 2500, .store_sample = ad5620_store_sample, .store_pwr_down = ad5620_store_pwr_down, }, [ID_AD5640_1250] = { - .bits = 14, - .storagebits = 16, - .left_shift = 0, + .channel = AD5446_CHANNEL(14, 16, 0), .int_vref_mv = 1250, .store_sample = ad5620_store_sample, .store_pwr_down = ad5620_store_pwr_down, }, [ID_AD5660_2500] = { - .bits = 16, - .storagebits = 24, - .left_shift = 0, + .channel = AD5446_CHANNEL(16, 16, 0), .int_vref_mv = 2500, .store_sample = ad5660_store_sample, .store_pwr_down = ad5660_store_pwr_down, }, [ID_AD5660_1250] = { - .bits = 16, - .storagebits = 24, - .left_shift = 0, + .channel = AD5446_CHANNEL(16, 16, 0), .int_vref_mv = 1250, .store_sample = ad5660_store_sample, .store_pwr_down = ad5660_store_pwr_down, }, }; +static int ad5446_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long m) +{ + struct ad5446_state *st = iio_priv(indio_dev); + unsigned long scale_uv; + + switch (m) { + case IIO_CHAN_INFO_SCALE: + scale_uv = (st->vref_mv * 1000) >> chan->scan_type.realbits; + *val = scale_uv / 1000; + *val2 = (scale_uv % 1000) * 1000; + return IIO_VAL_INT_PLUS_MICRO; + + } + return -EINVAL; +} + +static int ad5446_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct ad5446_state *st = iio_priv(indio_dev); + int ret; + + switch (mask) { + case 0: + if (val >= (1 << chan->scan_type.realbits) || val < 0) + return -EINVAL; + + val <<= chan->scan_type.shift; + mutex_lock(&indio_dev->mlock); + st->cached_val = val; + st->chip_info->store_sample(st, val); + ret = spi_sync(st->spi, &st->msg); + mutex_unlock(&indio_dev->mlock); + break; + default: + ret = -EINVAL; + } + + return ret; +} + static const struct iio_info ad5446_info = { + .read_raw = ad5446_read_raw, + .write_raw = ad5446_write_raw, .attrs = &ad5446_attribute_group, .driver_module = THIS_MODULE, }; @@ -376,11 +355,13 @@ static int __devinit ad5446_probe(struct spi_device *spi) indio_dev->name = spi_get_device_id(spi)->name; indio_dev->info = &ad5446_info; indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = &st->chip_info->channel; + indio_dev->num_channels = 1; /* Setup default message */ st->xfer.tx_buf = &st->data; - st->xfer.len = st->chip_info->storagebits / 8; + st->xfer.len = st->chip_info->channel.scan_type.storagebits / 8; spi_message_init(&st->msg); spi_message_add_tail(&st->xfer, &st->msg); diff --git a/drivers/staging/iio/dac/ad5446.h b/drivers/staging/iio/dac/ad5446.h index 7118d653ac3e..4ea3476fb065 100644 --- a/drivers/staging/iio/dac/ad5446.h +++ b/drivers/staging/iio/dac/ad5446.h @@ -25,8 +25,6 @@ #define AD5660_PWRDWN_100k (0x2 << 16) /* Power-down: 100kOhm to GND */ #define AD5660_PWRDWN_TRISTATE (0x3 << 16) /* Power-down: Three-state */ -#define RES_MASK(bits) ((1 << (bits)) - 1) - #define MODE_PWRDWN_1k 0x1 #define MODE_PWRDWN_100k 0x2 #define MODE_PWRDWN_TRISTATE 0x3 @@ -62,18 +60,14 @@ struct ad5446_state { /** * struct ad5446_chip_info - chip specific information - * @bits: accuracy of the DAC in bits - * @storagebits: number of bits written to the DAC - * @left_shift: number of bits the datum must be shifted + * @channel: channel spec for the DAC * @int_vref_mv: AD5620/40/60: the internal reference voltage * @store_sample: chip specific helper function to store the datum * @store_sample: chip specific helper function to store the powerpown cmd */ struct ad5446_chip_info { - u8 bits; - u8 storagebits; - u8 left_shift; + struct iio_chan_spec channel; u16 int_vref_mv; void (*store_sample) (struct ad5446_state *st, unsigned val); void (*store_pwr_down) (struct ad5446_state *st, unsigned mode); From a7b152881cee97c2d9d19a9d2b712ba0bbc96843 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 15 Nov 2011 16:31:23 +0100 Subject: [PATCH 046/365] staging:iio:dac:ad5504: Convert to channel spec Signed-off-by: Lars-Peter Clausen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/ad5504.c | 142 +++++++++++++++++-------------- drivers/staging/iio/dac/ad5504.h | 5 +- 2 files changed, 77 insertions(+), 70 deletions(-) diff --git a/drivers/staging/iio/dac/ad5504.c b/drivers/staging/iio/dac/ad5504.c index 72040cc73764..68a43cbdc60a 100644 --- a/drivers/staging/iio/dac/ad5504.c +++ b/drivers/staging/iio/dac/ad5504.c @@ -22,6 +22,23 @@ #include "dac.h" #include "ad5504.h" +#define AD5504_CHANNEL(_chan) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .output = 1, \ + .channel = (_chan), \ + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \ + .address = AD5504_ADDR_DAC(_chan), \ + .scan_type = IIO_ST('u', 12, 16, 0), \ +} + +static const struct iio_chan_spec ad5504_channels[] = { + AD5504_CHANNEL(0), + AD5504_CHANNEL(1), + AD5504_CHANNEL(2), + AD5504_CHANNEL(3), +}; + static int ad5504_spi_write(struct spi_device *spi, u8 addr, u16 val) { u16 tmp = cpu_to_be16(AD5504_CMD_WRITE | @@ -31,13 +48,14 @@ static int ad5504_spi_write(struct spi_device *spi, u8 addr, u16 val) return spi_write(spi, (u8 *)&tmp, 2); } -static int ad5504_spi_read(struct spi_device *spi, u8 addr, u16 *val) +static int ad5504_spi_read(struct spi_device *spi, u8 addr) { u16 tmp = cpu_to_be16(AD5504_CMD_READ | AD5504_ADDR(addr)); + u16 val; int ret; struct spi_transfer t = { .tx_buf = &tmp, - .rx_buf = val, + .rx_buf = &val, .len = 2, }; struct spi_message m; @@ -46,44 +64,61 @@ static int ad5504_spi_read(struct spi_device *spi, u8 addr, u16 *val) spi_message_add_tail(&t, &m); ret = spi_sync(spi, &m); - *val = be16_to_cpu(*val) & AD5504_RES_MASK; - - return ret; -} - -static ssize_t ad5504_write_dac(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5504_state *st = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - long readin; - int ret; - - ret = strict_strtol(buf, 10, &readin); - if (ret) + if (ret < 0) return ret; - ret = ad5504_spi_write(st->spi, this_attr->address, readin); - return ret ? ret : len; + return be16_to_cpu(val) & AD5504_RES_MASK; } -static ssize_t ad5504_read_dac(struct device *dev, - struct device_attribute *attr, - char *buf) +static int ad5504_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long m) { - struct iio_dev *indio_dev = dev_get_drvdata(dev); struct ad5504_state *st = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + unsigned long scale_uv; int ret; - u16 val; - ret = ad5504_spi_read(st->spi, this_attr->address, &val); - if (ret) - return ret; + switch (m) { + case 0: + ret = ad5504_spi_read(st->spi, chan->address); + if (ret < 0) + return ret; - return sprintf(buf, "%d\n", val); + *val = ret; + + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + scale_uv = (st->vref_mv * 1000) >> chan->scan_type.realbits; + *val = scale_uv / 1000; + *val2 = (scale_uv % 1000) * 1000; + return IIO_VAL_INT_PLUS_MICRO; + + } + return -EINVAL; +} + +static int ad5504_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct ad5504_state *st = iio_priv(indio_dev); + int ret; + + switch (mask) { + case 0: + if (val >= (1 << chan->scan_type.realbits) || val < 0) + return -EINVAL; + + return ad5504_spi_write(st->spi, chan->address, val); + default: + ret = -EINVAL; + } + + return -EINVAL; } static ssize_t ad5504_read_powerdown_mode(struct device *dev, @@ -158,32 +193,6 @@ static ssize_t ad5504_write_dac_powerdown(struct device *dev, return ret ? ret : len; } -static ssize_t ad5504_show_scale(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5504_state *st = iio_priv(indio_dev); - /* Corresponds to Vref / 2^(bits) */ - unsigned int scale_uv = (st->vref_mv * 1000) >> AD5505_BITS; - - return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000); -} -static IIO_DEVICE_ATTR(out_voltage_scale, S_IRUGO, ad5504_show_scale, NULL, 0); - -#define IIO_DEV_ATTR_OUT_RW_RAW(_num, _show, _store, _addr) \ - IIO_DEVICE_ATTR(out_voltage##_num##_raw, \ - S_IRUGO | S_IWUSR, _show, _store, _addr) - -static IIO_DEV_ATTR_OUT_RW_RAW(0, ad5504_read_dac, - ad5504_write_dac, AD5504_ADDR_DAC0); -static IIO_DEV_ATTR_OUT_RW_RAW(1, ad5504_read_dac, - ad5504_write_dac, AD5504_ADDR_DAC1); -static IIO_DEV_ATTR_OUT_RW_RAW(2, ad5504_read_dac, - ad5504_write_dac, AD5504_ADDR_DAC2); -static IIO_DEV_ATTR_OUT_RW_RAW(3, ad5504_read_dac, - ad5504_write_dac, AD5504_ADDR_DAC3); - static IIO_DEVICE_ATTR(out_voltage_powerdown_mode, S_IRUGO | S_IWUSR, ad5504_read_powerdown_mode, ad5504_write_powerdown_mode, 0); @@ -204,17 +213,12 @@ static IIO_DEV_ATTR_DAC_POWERDOWN(3, ad5504_read_dac_powerdown, ad5504_write_dac_powerdown, 3); static struct attribute *ad5504_attributes[] = { - &iio_dev_attr_out_voltage0_raw.dev_attr.attr, - &iio_dev_attr_out_voltage1_raw.dev_attr.attr, - &iio_dev_attr_out_voltage2_raw.dev_attr.attr, - &iio_dev_attr_out_voltage3_raw.dev_attr.attr, &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr, &iio_dev_attr_out_voltage1_powerdown.dev_attr.attr, &iio_dev_attr_out_voltage2_powerdown.dev_attr.attr, &iio_dev_attr_out_voltage3_powerdown.dev_attr.attr, &iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr, &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr, - &iio_dev_attr_out_voltage_scale.dev_attr.attr, NULL, }; @@ -223,11 +227,9 @@ static const struct attribute_group ad5504_attribute_group = { }; static struct attribute *ad5501_attributes[] = { - &iio_dev_attr_out_voltage0_raw.dev_attr.attr, &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr, &iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr, &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr, - &iio_dev_attr_out_voltage_scale.dev_attr.attr, NULL, }; @@ -262,12 +264,16 @@ static irqreturn_t ad5504_event_handler(int irq, void *private) } static const struct iio_info ad5504_info = { + .write_raw = ad5504_write_raw, + .read_raw = ad5504_read_raw, .attrs = &ad5504_attribute_group, .event_attrs = &ad5504_ev_attribute_group, .driver_module = THIS_MODULE, }; static const struct iio_info ad5501_info = { + .write_raw = ad5504_write_raw, + .read_raw = ad5504_read_raw, .attrs = &ad5501_attribute_group, .event_attrs = &ad5504_ev_attribute_group, .driver_module = THIS_MODULE, @@ -308,10 +314,14 @@ static int __devinit ad5504_probe(struct spi_device *spi) st->spi = spi; indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(st->spi)->name; - if (spi_get_device_id(st->spi)->driver_data == ID_AD5501) + if (spi_get_device_id(st->spi)->driver_data == ID_AD5501) { indio_dev->info = &ad5501_info; - else + indio_dev->num_channels = 1; + } else { indio_dev->info = &ad5504_info; + indio_dev->num_channels = 4; + } + indio_dev->channels = ad5504_channels; indio_dev->modes = INDIO_DIRECT_MODE; if (spi->irq) { diff --git a/drivers/staging/iio/dac/ad5504.h b/drivers/staging/iio/dac/ad5504.h index 85beb1dd29b9..afe09522f53c 100644 --- a/drivers/staging/iio/dac/ad5504.h +++ b/drivers/staging/iio/dac/ad5504.h @@ -18,10 +18,7 @@ /* Registers */ #define AD5504_ADDR_NOOP 0 -#define AD5504_ADDR_DAC0 1 -#define AD5504_ADDR_DAC1 2 -#define AD5504_ADDR_DAC2 3 -#define AD5504_ADDR_DAC3 4 +#define AD5504_ADDR_DAC(x) ((x) + 1) #define AD5504_ADDR_ALL_DAC 5 #define AD5504_ADDR_CTRL 7 From 275de9f7a8db332dfbf100bc2c75940070361bc2 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 15 Nov 2011 16:31:24 +0100 Subject: [PATCH 047/365] staging:iio:dac:ad5624r: Convert to channel spec Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/dac/ad5624r.h | 4 +- drivers/staging/iio/dac/ad5624r_spi.c | 126 ++++++++++++++++---------- 2 files changed, 79 insertions(+), 51 deletions(-) diff --git a/drivers/staging/iio/dac/ad5624r.h b/drivers/staging/iio/dac/ad5624r.h index b71c6a03e780..5dca3028cdfd 100644 --- a/drivers/staging/iio/dac/ad5624r.h +++ b/drivers/staging/iio/dac/ad5624r.h @@ -32,12 +32,12 @@ /** * struct ad5624r_chip_info - chip specific information - * @bits: accuracy of the DAC in bits + * @channels: channel spec for the DAC * @int_vref_mv: AD5620/40/60: the internal reference voltage */ struct ad5624r_chip_info { - u8 bits; + const struct iio_chan_spec *channels; u16 int_vref_mv; }; diff --git a/drivers/staging/iio/dac/ad5624r_spi.c b/drivers/staging/iio/dac/ad5624r_spi.c index 284d87900362..2c5524ecc15b 100644 --- a/drivers/staging/iio/dac/ad5624r_spi.c +++ b/drivers/staging/iio/dac/ad5624r_spi.c @@ -21,29 +21,51 @@ #include "dac.h" #include "ad5624r.h" +#define AD5624R_CHANNEL(_chan, _bits) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .output = 1, \ + .channel = (_chan), \ + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \ + .address = (_chan), \ + .scan_type = IIO_ST('u', (_bits), 16, 16 - (_bits)), \ +} + +#define DECLARE_AD5624R_CHANNELS(_name, _bits) \ + const struct iio_chan_spec _name##_channels[] = { \ + AD5624R_CHANNEL(0, _bits), \ + AD5624R_CHANNEL(1, _bits), \ + AD5624R_CHANNEL(2, _bits), \ + AD5624R_CHANNEL(3, _bits), \ +} + +static DECLARE_AD5624R_CHANNELS(ad5624r, 12); +static DECLARE_AD5624R_CHANNELS(ad5644r, 14); +static DECLARE_AD5624R_CHANNELS(ad5664r, 16); + static const struct ad5624r_chip_info ad5624r_chip_info_tbl[] = { [ID_AD5624R3] = { - .bits = 12, - .int_vref_mv = 1250, - }, - [ID_AD5644R3] = { - .bits = 14, - .int_vref_mv = 1250, - }, - [ID_AD5664R3] = { - .bits = 16, + .channels = ad5624r_channels, .int_vref_mv = 1250, }, [ID_AD5624R5] = { - .bits = 12, + .channels = ad5624r_channels, .int_vref_mv = 2500, }, + [ID_AD5644R3] = { + .channels = ad5644r_channels, + .int_vref_mv = 1250, + }, [ID_AD5644R5] = { - .bits = 14, + .channels = ad5644r_channels, .int_vref_mv = 2500, }, + [ID_AD5664R3] = { + .channels = ad5664r_channels, + .int_vref_mv = 1250, + }, [ID_AD5664R5] = { - .bits = 16, + .channels = ad5664r_channels, .int_vref_mv = 2500, }, }; @@ -70,24 +92,49 @@ static int ad5624r_spi_write(struct spi_device *spi, return spi_write(spi, msg, 3); } -static ssize_t ad5624r_write_dac(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) +static int ad5624r_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long m) { - long readin; - int ret; - struct iio_dev *indio_dev = dev_get_drvdata(dev); struct ad5624r_state *st = iio_priv(indio_dev); - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + unsigned long scale_uv; - ret = strict_strtol(buf, 10, &readin); - if (ret) - return ret; + switch (m) { + case IIO_CHAN_INFO_SCALE: + scale_uv = (st->vref_mv * 1000) >> chan->scan_type.realbits; + *val = scale_uv / 1000; + *val2 = (scale_uv % 1000) * 1000; + return IIO_VAL_INT_PLUS_MICRO; - ret = ad5624r_spi_write(st->us, AD5624R_CMD_WRITE_INPUT_N_UPDATE_N, - this_attr->address, readin, - st->chip_info->bits); - return ret ? ret : len; + } + return -EINVAL; +} + +static int ad5624r_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct ad5624r_state *st = iio_priv(indio_dev); + int ret; + + switch (mask) { + case 0: + if (val >= (1 << chan->scan_type.realbits) || val < 0) + return -EINVAL; + + return ad5624r_spi_write(st->us, + AD5624R_CMD_WRITE_INPUT_N_UPDATE_N, + chan->address, val, + chan->scan_type.shift); + default: + ret = -EINVAL; + } + + return -EINVAL; } static ssize_t ad5624r_read_powerdown_mode(struct device *dev, @@ -161,24 +208,6 @@ static ssize_t ad5624r_write_dac_powerdown(struct device *dev, return ret ? ret : len; } -static ssize_t ad5624r_show_scale(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad5624r_state *st = iio_priv(indio_dev); - /* Corresponds to Vref / 2^(bits) */ - unsigned int scale_uv = (st->vref_mv * 1000) >> st->chip_info->bits; - - return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000); -} -static IIO_DEVICE_ATTR(out_voltage_scale, S_IRUGO, ad5624r_show_scale, NULL, 0); - -static IIO_DEV_ATTR_OUT_RAW(0, ad5624r_write_dac, AD5624R_ADDR_DAC0); -static IIO_DEV_ATTR_OUT_RAW(1, ad5624r_write_dac, AD5624R_ADDR_DAC1); -static IIO_DEV_ATTR_OUT_RAW(2, ad5624r_write_dac, AD5624R_ADDR_DAC2); -static IIO_DEV_ATTR_OUT_RAW(3, ad5624r_write_dac, AD5624R_ADDR_DAC3); - static IIO_DEVICE_ATTR(out_voltage_powerdown_mode, S_IRUGO | S_IWUSR, ad5624r_read_powerdown_mode, ad5624r_write_powerdown_mode, 0); @@ -200,17 +229,12 @@ static IIO_DEV_ATTR_DAC_POWERDOWN(3, ad5624r_read_dac_powerdown, ad5624r_write_dac_powerdown, 3); static struct attribute *ad5624r_attributes[] = { - &iio_dev_attr_out_voltage0_raw.dev_attr.attr, - &iio_dev_attr_out_voltage1_raw.dev_attr.attr, - &iio_dev_attr_out_voltage2_raw.dev_attr.attr, - &iio_dev_attr_out_voltage3_raw.dev_attr.attr, &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr, &iio_dev_attr_out_voltage1_powerdown.dev_attr.attr, &iio_dev_attr_out_voltage2_powerdown.dev_attr.attr, &iio_dev_attr_out_voltage3_powerdown.dev_attr.attr, &iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr, &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr, - &iio_dev_attr_out_voltage_scale.dev_attr.attr, NULL, }; @@ -219,6 +243,8 @@ static const struct attribute_group ad5624r_attribute_group = { }; static const struct iio_info ad5624r_info = { + .write_raw = ad5624r_write_raw, + .read_raw = ad5624r_read_raw, .attrs = &ad5624r_attribute_group, .driver_module = THIS_MODULE, }; @@ -259,6 +285,8 @@ static int __devinit ad5624r_probe(struct spi_device *spi) indio_dev->name = spi_get_device_id(spi)->name; indio_dev->info = &ad5624r_info; indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = st->chip_info->channels; + indio_dev->num_channels = AD5624R_DAC_CHANNELS; ret = ad5624r_spi_write(spi, AD5624R_CMD_INTERNAL_REFER_SETUP, 0, !!voltage_uv, 16); From 55e4390cb04e8b0fbae8983c3494c9e24132db1b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 16 Nov 2011 08:53:31 +0100 Subject: [PATCH 048/365] staging:iio: Add missing MODULE_DEVICE_TABLE and MODULE_ALIAS Quite a few iio drivers provide no MODULE_DEVICE_TABLE or MODULE_ALIAS or only provide a MODULE_ALIAS while they have support for multiple device ids. This prevents auto module loading from working correctly. This patch fixes it by adding the missing MODULE_DEVICE_TABLEs and MODULE_ALIAS'. Signed-off-by: Lars-Peter Clausen Acked-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/accel/adis16201_core.c | 1 + drivers/staging/iio/accel/adis16203_core.c | 1 + drivers/staging/iio/accel/adis16204_core.c | 1 + drivers/staging/iio/accel/adis16209_core.c | 1 + drivers/staging/iio/accel/adis16220_core.c | 1 + drivers/staging/iio/accel/adis16240_core.c | 1 + drivers/staging/iio/accel/kxsd9.c | 4 +++- drivers/staging/iio/accel/lis3l02dq_core.c | 1 + drivers/staging/iio/accel/sca3000_core.c | 1 + drivers/staging/iio/adc/ad7192.c | 1 + drivers/staging/iio/adc/ad7280a.c | 1 + drivers/staging/iio/adc/ad7298_core.c | 2 +- drivers/staging/iio/adc/ad7476_core.c | 2 +- drivers/staging/iio/adc/ad7606_par.c | 1 - drivers/staging/iio/adc/ad7606_spi.c | 2 +- drivers/staging/iio/adc/ad7780.c | 1 + drivers/staging/iio/adc/ad7793.c | 1 + drivers/staging/iio/adc/ad7887_core.c | 2 +- drivers/staging/iio/adc/ad799x_core.c | 1 - drivers/staging/iio/dac/ad5446.c | 2 +- drivers/staging/iio/dac/ad5504.c | 1 + drivers/staging/iio/dac/ad5624r_spi.c | 1 + drivers/staging/iio/dac/ad5686.c | 1 + drivers/staging/iio/dac/ad5791.c | 1 + drivers/staging/iio/dds/ad5930.c | 1 + drivers/staging/iio/dds/ad9832.c | 2 +- drivers/staging/iio/dds/ad9834.c | 2 +- drivers/staging/iio/dds/ad9850.c | 1 + drivers/staging/iio/dds/ad9852.c | 1 + drivers/staging/iio/dds/ad9910.c | 1 + drivers/staging/iio/dds/ad9951.c | 1 + drivers/staging/iio/gyro/adis16080_core.c | 1 + drivers/staging/iio/gyro/adis16130_core.c | 1 + drivers/staging/iio/gyro/adis16260_core.c | 1 + drivers/staging/iio/gyro/adxrs450_core.c | 1 + drivers/staging/iio/imu/adis16400_core.c | 1 + drivers/staging/iio/magnetometer/hmc5843.c | 1 + drivers/staging/iio/meter/ade7753.c | 1 + drivers/staging/iio/meter/ade7754.c | 1 + drivers/staging/iio/meter/ade7758_core.c | 1 + drivers/staging/iio/meter/ade7759.c | 1 + drivers/staging/iio/meter/ade7854-spi.c | 1 + drivers/staging/iio/resolver/ad2s1200.c | 1 + drivers/staging/iio/resolver/ad2s1210.c | 1 + drivers/staging/iio/resolver/ad2s90.c | 1 + 45 files changed, 45 insertions(+), 10 deletions(-) diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c index d3d877fc5dc7..ed97da240b0e 100644 --- a/drivers/staging/iio/accel/adis16201_core.c +++ b/drivers/staging/iio/accel/adis16201_core.c @@ -564,3 +564,4 @@ module_exit(adis16201_exit); MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); MODULE_DESCRIPTION("Analog Devices ADIS16201 Programmable Digital Vibration Sensor driver"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("spi:adis16201"); diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c index bdc44feaa123..41fe930c16c2 100644 --- a/drivers/staging/iio/accel/adis16203_core.c +++ b/drivers/staging/iio/accel/adis16203_core.c @@ -519,3 +519,4 @@ module_exit(adis16203_exit); MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); MODULE_DESCRIPTION("Analog Devices ADIS16203 Programmable Digital Vibration Sensor driver"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("spi:adis16203"); diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c index 96d8c7b3722e..fcab806f68f5 100644 --- a/drivers/staging/iio/accel/adis16204_core.c +++ b/drivers/staging/iio/accel/adis16204_core.c @@ -593,3 +593,4 @@ module_exit(adis16204_exit); MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); MODULE_DESCRIPTION("ADIS16204 High-g Digital Impact Sensor and Recorder"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("spi:adis16204"); diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c index 62e6bd8101c4..4ad33ecbc44d 100644 --- a/drivers/staging/iio/accel/adis16209_core.c +++ b/drivers/staging/iio/accel/adis16209_core.c @@ -568,3 +568,4 @@ module_exit(adis16209_exit); MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); MODULE_DESCRIPTION("Analog Devices ADIS16209 Digital Vibration Sensor driver"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("spi:adis16209"); diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c index ca18f729b5ca..4baf02cf96f9 100644 --- a/drivers/staging/iio/accel/adis16220_core.c +++ b/drivers/staging/iio/accel/adis16220_core.c @@ -724,3 +724,4 @@ module_exit(adis16220_exit); MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); MODULE_DESCRIPTION("Analog Devices ADIS16220 Digital Vibration Sensor"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("spi:adis16220"); diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c index 134839360d31..4298c4065c9f 100644 --- a/drivers/staging/iio/accel/adis16240_core.c +++ b/drivers/staging/iio/accel/adis16240_core.c @@ -621,3 +621,4 @@ module_exit(adis16240_exit); MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); MODULE_DESCRIPTION("Analog Devices Programmable Impact Sensor and Recorder"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("spi:adis16240"); diff --git a/drivers/staging/iio/accel/kxsd9.c b/drivers/staging/iio/accel/kxsd9.c index abb6071e1c50..5a543fa55c93 100644 --- a/drivers/staging/iio/accel/kxsd9.c +++ b/drivers/staging/iio/accel/kxsd9.c @@ -268,8 +268,10 @@ static int __devexit kxsd9_remove(struct spi_device *spi) } static const struct spi_device_id kxsd9_id[] = { - {"kxsd9", 0} + {"kxsd9", 0}, + { }, }; +MODULE_DEVICE_TABLE(spi, kxsd9_id); static struct spi_driver kxsd9_driver = { .driver = { diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c index 6d715a6e4200..4dbe4c7d3617 100644 --- a/drivers/staging/iio/accel/lis3l02dq_core.c +++ b/drivers/staging/iio/accel/lis3l02dq_core.c @@ -821,3 +821,4 @@ module_exit(lis3l02dq_exit); MODULE_AUTHOR("Jonathan Cameron "); MODULE_DESCRIPTION("ST LIS3L02DQ Accelerometer SPI driver"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("spi:lis3l02dq"); diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c index 021a08ffb6cc..94bfe05e39f5 100644 --- a/drivers/staging/iio/accel/sca3000_core.c +++ b/drivers/staging/iio/accel/sca3000_core.c @@ -1241,6 +1241,7 @@ static const struct spi_device_id sca3000_id[] = { {"sca3000_e05", e05}, {} }; +MODULE_DEVICE_TABLE(spi, sca3000_id); static struct spi_driver sca3000_driver = { .driver = { diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 4e643de45f65..f48a0d48d152 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -1153,6 +1153,7 @@ static const struct spi_device_id ad7192_id[] = { {"ad7195", ID_AD7195}, {} }; +MODULE_DEVICE_TABLE(spi, ad7192_id); static struct spi_driver ad7192_driver = { .driver = { diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c index cd3397f95f80..1af4194bbd83 100644 --- a/drivers/staging/iio/adc/ad7280a.c +++ b/drivers/staging/iio/adc/ad7280a.c @@ -970,6 +970,7 @@ static const struct spi_device_id ad7280_id[] = { {"ad7280a", 0}, {} }; +MODULE_DEVICE_TABLE(spi, ad7280_id); static struct spi_driver ad7280_driver = { .driver = { diff --git a/drivers/staging/iio/adc/ad7298_core.c b/drivers/staging/iio/adc/ad7298_core.c index 0be71dfcf115..093b2b2c20ea 100644 --- a/drivers/staging/iio/adc/ad7298_core.c +++ b/drivers/staging/iio/adc/ad7298_core.c @@ -270,6 +270,7 @@ static const struct spi_device_id ad7298_id[] = { {"ad7298", 0}, {} }; +MODULE_DEVICE_TABLE(spi, ad7298_id); static struct spi_driver ad7298_driver = { .driver = { @@ -297,4 +298,3 @@ module_exit(ad7298_exit); MODULE_AUTHOR("Michael Hennerich "); MODULE_DESCRIPTION("Analog Devices AD7298 ADC"); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("spi:ad7298"); diff --git a/drivers/staging/iio/adc/ad7476_core.c b/drivers/staging/iio/adc/ad7476_core.c index a06ae9eec935..93b2bef0e5fc 100644 --- a/drivers/staging/iio/adc/ad7476_core.c +++ b/drivers/staging/iio/adc/ad7476_core.c @@ -237,6 +237,7 @@ static const struct spi_device_id ad7476_id[] = { {"ad7495", ID_AD7495}, {} }; +MODULE_DEVICE_TABLE(spi, ad7476_id); static struct spi_driver ad7476_driver = { .driver = { @@ -264,4 +265,3 @@ module_exit(ad7476_exit); MODULE_AUTHOR("Michael Hennerich "); MODULE_DESCRIPTION("Analog Devices AD7475/6/7/8(A) AD7466/7/8 ADC"); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("spi:ad7476"); diff --git a/drivers/staging/iio/adc/ad7606_par.c b/drivers/staging/iio/adc/ad7606_par.c index 688632edd3d7..cff97568189e 100644 --- a/drivers/staging/iio/adc/ad7606_par.c +++ b/drivers/staging/iio/adc/ad7606_par.c @@ -189,4 +189,3 @@ module_exit(ad7606_cleanup); MODULE_AUTHOR("Michael Hennerich "); MODULE_DESCRIPTION("Analog Devices AD7606 ADC"); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:ad7606_par"); diff --git a/drivers/staging/iio/adc/ad7606_spi.c b/drivers/staging/iio/adc/ad7606_spi.c index aede1ba5e041..c88d97afc60d 100644 --- a/drivers/staging/iio/adc/ad7606_spi.c +++ b/drivers/staging/iio/adc/ad7606_spi.c @@ -97,6 +97,7 @@ static const struct spi_device_id ad7606_id[] = { {"ad7606-4", ID_AD7606_4}, {} }; +MODULE_DEVICE_TABLE(spi, ad7606_id); static struct spi_driver ad7606_driver = { .driver = { @@ -125,4 +126,3 @@ module_exit(ad7606_spi_exit); MODULE_AUTHOR("Michael Hennerich "); MODULE_DESCRIPTION("Analog Devices AD7606 ADC"); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("spi:ad7606_spi"); diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c index f5f7e76561f5..635c7bac44b1 100644 --- a/drivers/staging/iio/adc/ad7780.c +++ b/drivers/staging/iio/adc/ad7780.c @@ -272,6 +272,7 @@ static const struct spi_device_id ad7780_id[] = { {"ad7781", ID_AD7781}, {} }; +MODULE_DEVICE_TABLE(spi, ad7780_id); static struct spi_driver ad7780_driver = { .driver = { diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c index 803c45ff84b9..362cc3199291 100644 --- a/drivers/staging/iio/adc/ad7793.c +++ b/drivers/staging/iio/adc/ad7793.c @@ -1036,6 +1036,7 @@ static const struct spi_device_id ad7793_id[] = { {"ad7793", ID_AD7793}, {} }; +MODULE_DEVICE_TABLE(spi, ad7793_id); static struct spi_driver ad7793_driver = { .driver = { diff --git a/drivers/staging/iio/adc/ad7887_core.c b/drivers/staging/iio/adc/ad7887_core.c index baa6e6a8c418..8f4865916369 100644 --- a/drivers/staging/iio/adc/ad7887_core.c +++ b/drivers/staging/iio/adc/ad7887_core.c @@ -246,6 +246,7 @@ static const struct spi_device_id ad7887_id[] = { {"ad7887", ID_AD7887}, {} }; +MODULE_DEVICE_TABLE(spi, ad7887_id); static struct spi_driver ad7887_driver = { .driver = { @@ -273,4 +274,3 @@ module_exit(ad7887_exit); MODULE_AUTHOR("Michael Hennerich "); MODULE_DESCRIPTION("Analog Devices AD7887 ADC"); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("spi:ad7887"); diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c index cdee9b95465f..5bedb19cc72b 100644 --- a/drivers/staging/iio/adc/ad799x_core.c +++ b/drivers/staging/iio/adc/ad799x_core.c @@ -944,7 +944,6 @@ static __exit void ad799x_exit(void) MODULE_AUTHOR("Michael Hennerich "); MODULE_DESCRIPTION("Analog Devices AD799x ADC"); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("i2c:ad799x"); module_init(ad799x_init); module_exit(ad799x_exit); diff --git a/drivers/staging/iio/dac/ad5446.c b/drivers/staging/iio/dac/ad5446.c index a5882b83639a..9d53b1092441 100644 --- a/drivers/staging/iio/dac/ad5446.c +++ b/drivers/staging/iio/dac/ad5446.c @@ -435,6 +435,7 @@ static const struct spi_device_id ad5446_id[] = { {"ad5660-1250", ID_AD5660_1250}, {} }; +MODULE_DEVICE_TABLE(spi, ad5446_id); static struct spi_driver ad5446_driver = { .driver = { @@ -462,4 +463,3 @@ module_exit(ad5446_exit); MODULE_AUTHOR("Michael Hennerich "); MODULE_DESCRIPTION("Analog Devices AD5444/AD5446 DAC"); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("spi:ad5446"); diff --git a/drivers/staging/iio/dac/ad5504.c b/drivers/staging/iio/dac/ad5504.c index 68a43cbdc60a..f20a5dcd3e7d 100644 --- a/drivers/staging/iio/dac/ad5504.c +++ b/drivers/staging/iio/dac/ad5504.c @@ -378,6 +378,7 @@ static const struct spi_device_id ad5504_id[] = { {"ad5501", ID_AD5501}, {} }; +MODULE_DEVICE_TABLE(spi, ad5504_id); static struct spi_driver ad5504_driver = { .driver = { diff --git a/drivers/staging/iio/dac/ad5624r_spi.c b/drivers/staging/iio/dac/ad5624r_spi.c index 2c5524ecc15b..6cb00e14422f 100644 --- a/drivers/staging/iio/dac/ad5624r_spi.c +++ b/drivers/staging/iio/dac/ad5624r_spi.c @@ -335,6 +335,7 @@ static const struct spi_device_id ad5624r_id[] = { {"ad5664r5", ID_AD5664R5}, {} }; +MODULE_DEVICE_TABLE(spi, ad5624r_id); static struct spi_driver ad5624r_driver = { .driver = { diff --git a/drivers/staging/iio/dac/ad5686.c b/drivers/staging/iio/dac/ad5686.c index 7eaf594a4f64..bbaa9281308f 100644 --- a/drivers/staging/iio/dac/ad5686.c +++ b/drivers/staging/iio/dac/ad5686.c @@ -437,6 +437,7 @@ static const struct spi_device_id ad5686_id[] = { {"ad5686", ID_AD5686}, {} }; +MODULE_DEVICE_TABLE(spi, ad5686_id); static struct spi_driver ad5686_driver = { .driver = { diff --git a/drivers/staging/iio/dac/ad5791.c b/drivers/staging/iio/dac/ad5791.c index db0bd1231a35..79c4821a7afc 100644 --- a/drivers/staging/iio/dac/ad5791.c +++ b/drivers/staging/iio/dac/ad5791.c @@ -400,6 +400,7 @@ static const struct spi_device_id ad5791_id[] = { {"ad5791", ID_AD5791}, {} }; +MODULE_DEVICE_TABLE(spi, ad5791_id); static struct spi_driver ad5791_driver = { .driver = { diff --git a/drivers/staging/iio/dds/ad5930.c b/drivers/staging/iio/dds/ad5930.c index f5e368b56650..40807d25855c 100644 --- a/drivers/staging/iio/dds/ad5930.c +++ b/drivers/staging/iio/dds/ad5930.c @@ -159,3 +159,4 @@ module_exit(ad5930_spi_exit); MODULE_AUTHOR("Cliff Cai"); MODULE_DESCRIPTION("Analog Devices ad5930 driver"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("spi:" DRV_NAME); diff --git a/drivers/staging/iio/dds/ad9832.c b/drivers/staging/iio/dds/ad9832.c index b58baec4da8e..1c878207ea87 100644 --- a/drivers/staging/iio/dds/ad9832.c +++ b/drivers/staging/iio/dds/ad9832.c @@ -344,6 +344,7 @@ static const struct spi_device_id ad9832_id[] = { {"ad9835", 0}, {} }; +MODULE_DEVICE_TABLE(spi, ad9832_id); static struct spi_driver ad9832_driver = { .driver = { @@ -371,4 +372,3 @@ module_exit(ad9832_exit); MODULE_AUTHOR("Michael Hennerich "); MODULE_DESCRIPTION("Analog Devices AD9832/AD9835 DDS"); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("spi:ad9832"); diff --git a/drivers/staging/iio/dds/ad9834.c b/drivers/staging/iio/dds/ad9834.c index 2e29f6f1073c..cd10479730eb 100644 --- a/drivers/staging/iio/dds/ad9834.c +++ b/drivers/staging/iio/dds/ad9834.c @@ -435,6 +435,7 @@ static const struct spi_device_id ad9834_id[] = { {"ad9838", ID_AD9838}, {} }; +MODULE_DEVICE_TABLE(spi, ad9834_id); static struct spi_driver ad9834_driver = { .driver = { @@ -462,4 +463,3 @@ module_exit(ad9834_exit); MODULE_AUTHOR("Michael Hennerich "); MODULE_DESCRIPTION("Analog Devices AD9833/AD9834/AD9837/AD9838 DDS"); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("spi:ad9834"); diff --git a/drivers/staging/iio/dds/ad9850.c b/drivers/staging/iio/dds/ad9850.c index a14771b24c50..159f6f274fae 100644 --- a/drivers/staging/iio/dds/ad9850.c +++ b/drivers/staging/iio/dds/ad9850.c @@ -145,3 +145,4 @@ module_exit(ad9850_spi_exit); MODULE_AUTHOR("Cliff Cai"); MODULE_DESCRIPTION("Analog Devices ad9850 driver"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("spi:" DRV_NAME); diff --git a/drivers/staging/iio/dds/ad9852.c b/drivers/staging/iio/dds/ad9852.c index cfceaa64a53a..5a338d2d06f7 100644 --- a/drivers/staging/iio/dds/ad9852.c +++ b/drivers/staging/iio/dds/ad9852.c @@ -296,3 +296,4 @@ module_exit(ad9852_spi_exit); MODULE_AUTHOR("Cliff Cai"); MODULE_DESCRIPTION("Analog Devices ad9852 driver"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("spi:" DRV_NAME); diff --git a/drivers/staging/iio/dds/ad9910.c b/drivers/staging/iio/dds/ad9910.c index da83d2b88c4a..a87ba8481cdf 100644 --- a/drivers/staging/iio/dds/ad9910.c +++ b/drivers/staging/iio/dds/ad9910.c @@ -429,3 +429,4 @@ module_exit(ad9910_spi_exit); MODULE_AUTHOR("Cliff Cai"); MODULE_DESCRIPTION("Analog Devices ad9910 driver"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("spi:" DRV_NAME); diff --git a/drivers/staging/iio/dds/ad9951.c b/drivers/staging/iio/dds/ad9951.c index 20c182576def..42aea1559266 100644 --- a/drivers/staging/iio/dds/ad9951.c +++ b/drivers/staging/iio/dds/ad9951.c @@ -240,3 +240,4 @@ module_exit(ad9951_spi_exit); MODULE_AUTHOR("Cliff Cai"); MODULE_DESCRIPTION("Analog Devices ad9951 driver"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("spi:" DRV_NAME); diff --git a/drivers/staging/iio/gyro/adis16080_core.c b/drivers/staging/iio/gyro/adis16080_core.c index 5d7a906fec78..ed37ef6df3b2 100644 --- a/drivers/staging/iio/gyro/adis16080_core.c +++ b/drivers/staging/iio/gyro/adis16080_core.c @@ -205,3 +205,4 @@ module_exit(adis16080_exit); MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); MODULE_DESCRIPTION("Analog Devices ADIS16080/100 Yaw Rate Gyroscope Driver"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("spi:adis16080"); diff --git a/drivers/staging/iio/gyro/adis16130_core.c b/drivers/staging/iio/gyro/adis16130_core.c index 749240d0d8cb..8c2dd44e45c2 100644 --- a/drivers/staging/iio/gyro/adis16130_core.c +++ b/drivers/staging/iio/gyro/adis16130_core.c @@ -184,3 +184,4 @@ module_exit(adis16130_exit); MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); MODULE_DESCRIPTION("Analog Devices ADIS16130 High Precision Angular Rate"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("spi:adis16130"); diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c index e86ce6a1611a..5614a220f4a2 100644 --- a/drivers/staging/iio/gyro/adis16260_core.c +++ b/drivers/staging/iio/gyro/adis16260_core.c @@ -700,6 +700,7 @@ static const struct spi_device_id adis16260_id[] = { {"adis16251", 1}, {} }; +MODULE_DEVICE_TABLE(spi, adis16260_id); static struct spi_driver adis16260_driver = { .driver = { diff --git a/drivers/staging/iio/gyro/adxrs450_core.c b/drivers/staging/iio/gyro/adxrs450_core.c index 40bfb32d6f16..e832aeabd879 100644 --- a/drivers/staging/iio/gyro/adxrs450_core.c +++ b/drivers/staging/iio/gyro/adxrs450_core.c @@ -397,3 +397,4 @@ module_exit(adxrs450_exit); MODULE_AUTHOR("Cliff Cai "); MODULE_DESCRIPTION("Analog Devices ADXRS450 Gyroscope SPI driver"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("spi:adxrs450"); diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c index 174454a8294c..a6da69f64f26 100644 --- a/drivers/staging/iio/imu/adis16400_core.c +++ b/drivers/staging/iio/imu/adis16400_core.c @@ -1117,6 +1117,7 @@ static const struct spi_device_id adis16400_id[] = { {"adis16405", ADIS16400}, {} }; +MODULE_DEVICE_TABLE(spi, adis16400_id); static struct spi_driver adis16400_driver = { .driver = { diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c index f90d4d124180..b492a0c0b8db 100644 --- a/drivers/staging/iio/magnetometer/hmc5843.c +++ b/drivers/staging/iio/magnetometer/hmc5843.c @@ -605,6 +605,7 @@ static const struct i2c_device_id hmc5843_id[] = { { "hmc5843", 0 }, { } }; +MODULE_DEVICE_TABLE(i2c, hmc5843_id); static struct i2c_driver hmc5843_driver = { .driver = { diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c index 940fef602b18..62a879ce509b 100644 --- a/drivers/staging/iio/meter/ade7753.c +++ b/drivers/staging/iio/meter/ade7753.c @@ -593,3 +593,4 @@ module_exit(ade7753_exit); MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); MODULE_DESCRIPTION("Analog Devices ADE7753/6 Single-Phase Multifunction Meter"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("spi:ade7753"); diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c index 33f0d327c9fa..0111edb1e2af 100644 --- a/drivers/staging/iio/meter/ade7754.c +++ b/drivers/staging/iio/meter/ade7754.c @@ -616,3 +616,4 @@ module_exit(ade7754_exit); MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); MODULE_DESCRIPTION("Analog Devices ADE7754 Polyphase Multifunction Energy Metering IC Driver"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("spi:ad7754"); diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c index 839b48b1b489..348df974dfe9 100644 --- a/drivers/staging/iio/meter/ade7758_core.c +++ b/drivers/staging/iio/meter/ade7758_core.c @@ -843,6 +843,7 @@ static const struct spi_device_id ade7758_id[] = { {"ade7758", 0}, {} }; +MODULE_DEVICE_TABLE(spi, ade7758_id); static struct spi_driver ade7758_driver = { .driver = { diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c index b691f10ce988..e7fcc7df87ee 100644 --- a/drivers/staging/iio/meter/ade7759.c +++ b/drivers/staging/iio/meter/ade7759.c @@ -537,3 +537,4 @@ module_exit(ade7759_exit); MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); MODULE_DESCRIPTION("Analog Devices ADE7759 Active Energy Metering IC Driver"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("spi:ad7759"); diff --git a/drivers/staging/iio/meter/ade7854-spi.c b/drivers/staging/iio/meter/ade7854-spi.c index cfa23ba30efe..50bc5d4153fa 100644 --- a/drivers/staging/iio/meter/ade7854-spi.c +++ b/drivers/staging/iio/meter/ade7854-spi.c @@ -343,6 +343,7 @@ static const struct spi_device_id ade7854_id[] = { { "ade7878", 0 }, { } }; +MODULE_DEVICE_TABLE(spi, ade7854_id); static struct spi_driver ade7854_driver = { .driver = { diff --git a/drivers/staging/iio/resolver/ad2s1200.c b/drivers/staging/iio/resolver/ad2s1200.c index d7ad46aed0ff..fda07d4736ae 100644 --- a/drivers/staging/iio/resolver/ad2s1200.c +++ b/drivers/staging/iio/resolver/ad2s1200.c @@ -160,6 +160,7 @@ static const struct spi_device_id ad2s1200_id[] = { { "ad2s1205" }, {} }; +MODULE_DEVICE_TABLE(spi, ad2s1200_id); static struct spi_driver ad2s1200_driver = { .driver = { diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c index 6401a6273625..8996c98f832a 100644 --- a/drivers/staging/iio/resolver/ad2s1210.c +++ b/drivers/staging/iio/resolver/ad2s1210.c @@ -749,6 +749,7 @@ static const struct spi_device_id ad2s1210_id[] = { { "ad2s1210" }, {} }; +MODULE_DEVICE_TABLE(spi, ad2s1210_id); static struct spi_driver ad2s1210_driver = { .driver = { diff --git a/drivers/staging/iio/resolver/ad2s90.c b/drivers/staging/iio/resolver/ad2s90.c index a9200d949dcd..b988b9272d00 100644 --- a/drivers/staging/iio/resolver/ad2s90.c +++ b/drivers/staging/iio/resolver/ad2s90.c @@ -109,6 +109,7 @@ static const struct spi_device_id ad2s90_id[] = { { "ad2s90" }, {} }; +MODULE_DEVICE_TABLE(spi, ad2s90_id); static struct spi_driver ad2s90_driver = { .driver = { From 5ae8f440909dc7fddccf7f408adbacf308049691 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Tue, 22 Nov 2011 08:02:21 +0200 Subject: [PATCH 049/365] iio: Don't OOPS if dummy evgen failed init If the dummy evgen failed init, the irq allocation functions which assume init succeeded may still be called - causing an OOPS due to wrong assumption. Here's the oops: [ 3.914332] BUG: unable to handle kernel NULL pointer dereference at 0000000000000148 [ 3.915310] IP: [] __lock_acquire+0xac/0xe50 [ 3.915310] PGD 0 [ 3.915310] Oops: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC [ 3.915310] CPU 1 [ 3.915310] Pid: 1, comm: swapper Not tainted 3.2.0-rc2-sasha-00279-gd7bfb12-dirty #20 [ 3.915310] RIP: 0010:[] [] __lock_acquire+0xac/0xe50 [ 3.915310] RSP: 0018:ffff880012499bc0 EFLAGS: 00010046 [ 3.915310] RAX: 0000000000000086 RBX: ffff880012490000 RCX: 0000000000000000 [ 3.915310] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000148 [ 3.915310] RBP: ffff880012499c90 R08: 0000000000000002 R09: 0000000000000000 [ 3.915310] R10: 0000000000000148 R11: 0000000000000000 R12: 0000000000000148 [ 3.915310] R13: 0000000000000002 R14: 0000000000000000 R15: 0000000000000000 [ 3.915310] FS: 0000000000000000(0000) GS:ffff880013c00000(0000) knlGS:0000000000000000 [ 3.915310] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [ 3.915310] CR2: 0000000000000148 CR3: 0000000002605000 CR4: 00000000000406e0 [ 3.915310] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 3.915310] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 3.915310] Process swapper (pid: 1, threadinfo ffff880012498000, task ffff880012490000) [ 3.915310] Stack: [ 3.915310] ffff880012490000 ffffffff81e6fd38 ffffffff00000000 0000000000000000 [ 3.915310] 0000000000000148 0000000012499c08 ffffffff00000000 000000000000002e [ 3.915310] 0000000000000001 ffff880012499ce0 ffffffff8161620e 0000000000000000 [ 3.915310] Call Trace: [ 3.915310] [] ? retint_restore_args+0x13/0x13 [ 3.915310] [] ? trace_hardirqs_on_thunk+0x3a/0x3f [ 3.915310] [] ? retint_restore_args+0x13/0x13 [ 3.915310] [] ? iio_dummy_evgen_get_irq+0x33/0x8a [ 3.915310] [] lock_acquire+0x8a/0xa7 [ 3.915310] [] ? iio_dummy_evgen_get_irq+0x33/0x8a [ 3.915310] [] __mutex_lock_common+0x63/0x491 [ 3.915310] [] ? iio_dummy_evgen_get_irq+0x33/0x8a [ 3.915310] [] ? debug_check_no_locks_freed+0x135/0x14a [ 3.915310] [] ? lock_is_held+0x92/0x9d [ 3.915310] [] mutex_lock_nested+0x36/0x3b [ 3.915310] [] iio_dummy_evgen_get_irq+0x33/0x8a [ 3.915310] [] iio_simple_dummy_events_register+0x1b/0x69 [ 3.915310] [] iio_dummy_init+0x105/0x18d [ 3.915310] [] ? iio_init+0x7d/0x7d [ 3.915310] [] do_one_initcall+0x7a/0x135 [ 3.915310] [] kernel_init+0xea/0x16f [ 3.915310] [] kernel_thread_helper+0x4/0x10 [ 3.915310] [] ? retint_restore_args+0x13/0x13 [ 3.915310] [] ? do_one_initcall+0x135/0x135 [ 3.915310] [] ? gs_change+0x13/0x13 [ 3.915310] Code: 95 50 ff ff ff 74 24 e8 1f 3f 56 00 85 c0 0f 84 4e 0d 00 00 be cf 0b 00 00 83 3d 63 7c 58 02 00 0f 85 3c 0d 00 00 e9 c1 0c 00 00 [ 3.915310] 81 3a a0 17 ca 82 b8 01 00 00 00 44 0f 44 e8 83 fe 01 77 0c [ 3.915310] RIP [] __lock_acquire+0xac/0xe50 [ 3.915310] RSP [ 3.915310] CR2: 0000000000000148 Acked-by: Jonathan Cameron Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/iio_dummy_evgen.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/staging/iio/iio_dummy_evgen.c b/drivers/staging/iio/iio_dummy_evgen.c index da657d10471d..cdbf289bfe2d 100644 --- a/drivers/staging/iio/iio_dummy_evgen.c +++ b/drivers/staging/iio/iio_dummy_evgen.c @@ -102,6 +102,10 @@ static int iio_dummy_evgen_create(void) int iio_dummy_evgen_get_irq(void) { int i, ret = 0; + + if (iio_evgen == NULL) + return -ENODEV; + mutex_lock(&iio_evgen->lock); for (i = 0; i < IIO_EVENTGEN_NO; i++) if (iio_evgen->inuse[i] == false) { From c1a752883dda6287b075215e419a77359f33edff Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 22 Nov 2011 10:39:15 +0300 Subject: [PATCH 050/365] Staging: iio: fix endian conversion in ad7298_scan_direct() "tmp" is used to store the output from cpu_to_be16() so it should be a __be16 bit type. Signed-off-by: Dan Carpenter Acked-by: Michael Hennerich Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/adc/ad7298_core.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/staging/iio/adc/ad7298_core.c b/drivers/staging/iio/adc/ad7298_core.c index 093b2b2c20ea..3ccd4b46dcd1 100644 --- a/drivers/staging/iio/adc/ad7298_core.c +++ b/drivers/staging/iio/adc/ad7298_core.c @@ -69,27 +69,28 @@ static int ad7298_scan_direct(struct ad7298_state *st, unsigned ch) static int ad7298_scan_temp(struct ad7298_state *st, int *val) { int tmp, ret; + __be16 buf; - tmp = cpu_to_be16(AD7298_WRITE | AD7298_TSENSE | + buf = cpu_to_be16(AD7298_WRITE | AD7298_TSENSE | AD7298_TAVG | st->ext_ref); - ret = spi_write(st->spi, (u8 *)&tmp, 2); + ret = spi_write(st->spi, (u8 *)&buf, 2); if (ret) return ret; - tmp = 0; + buf = cpu_to_be16(0); - ret = spi_write(st->spi, (u8 *)&tmp, 2); + ret = spi_write(st->spi, (u8 *)&buf, 2); if (ret) return ret; usleep_range(101, 1000); /* sleep > 100us */ - ret = spi_read(st->spi, (u8 *)&tmp, 2); + ret = spi_read(st->spi, (u8 *)&buf, 2); if (ret) return ret; - tmp = be16_to_cpu(tmp) & RES_MASK(AD7298_BITS); + tmp = be16_to_cpu(buf) & RES_MASK(AD7298_BITS); /* * One LSB of the ADC corresponds to 0.25 deg C. From a1914f5416352b3229abfb1947395844f7ee2321 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 25 Oct 2011 17:19:47 -0700 Subject: [PATCH 051/365] Staging: hv: mousevsc: Make boolean states boolean Make some state that is boolean in nature, a boolean variable. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index ccd39c70c527..15aa2cef3d00 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -148,7 +148,7 @@ struct mousevsc_prt_msg { */ struct mousevsc_dev { struct hv_device *device; - unsigned char init_complete; + bool init_complete; struct mousevsc_prt_msg protocol_req; struct mousevsc_prt_msg protocol_resp; /* Synchronize the request/response if needed */ @@ -159,7 +159,7 @@ struct mousevsc_dev { unsigned char *report_desc; u32 report_desc_size; struct hv_input_dev_info hid_dev_info; - int connected; + bool connected; struct hid_device *hid_device; }; @@ -487,7 +487,7 @@ static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len) if (!hidinput_connect(hid_dev, 0)) { hid_dev->claimed |= HID_CLAIMED_INPUT; - input_device->connected = 1; + input_device->connected = true; } @@ -558,7 +558,7 @@ static int mousevsc_remove(struct hv_device *dev) if (input_dev->connected) { hidinput_disconnect(input_dev->hid_device); - input_dev->connected = 0; + input_dev->connected = false; hid_destroy_device(input_dev->hid_device); } From 5cf06b0de818effa5de24ba5043348a7478f87a1 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 25 Oct 2011 17:19:48 -0700 Subject: [PATCH 052/365] Staging: hv: mousevsc: Inline the code for mousevsc_on_device_add() Inline the code for mousevsc_on_device_add() as this only used from the function mousevsc_probe(). Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 15aa2cef3d00..0a5676c681f4 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -494,7 +494,8 @@ static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len) input_device->hid_device = hid_dev; } -static int mousevsc_on_device_add(struct hv_device *device) +static int mousevsc_probe(struct hv_device *device, + const struct hv_vmbus_device_id *dev_id) { int ret = 0; struct mousevsc_dev *input_dev; @@ -542,13 +543,6 @@ static int mousevsc_on_device_add(struct hv_device *device) return ret; } -static int mousevsc_probe(struct hv_device *dev, - const struct hv_vmbus_device_id *dev_id) -{ - - return mousevsc_on_device_add(dev); - -} static int mousevsc_remove(struct hv_device *dev) { From 32325302aa94e60e843fad263ed8d20d49749f3a Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 25 Oct 2011 17:19:49 -0700 Subject: [PATCH 053/365] Staging: hv: mousevsc: Inline the code for reportdesc_callback() Inline the code for reportdesc_callback() as this function is called from mousevsc_probe(). As part of this, cleanup the code in reportdesc_callback(). Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 93 ++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 40 deletions(-) diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 0a5676c681f4..ed071b808cdd 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -451,54 +451,34 @@ static int mousevsc_hid_open(struct hid_device *hid) return 0; } +static int mousevsc_hid_start(struct hid_device *hid) +{ + return 0; +} + static void mousevsc_hid_close(struct hid_device *hid) { } +static void mousevsc_hid_stop(struct hid_device *hid) +{ +} + static struct hid_ll_driver mousevsc_ll_driver = { .open = mousevsc_hid_open, .close = mousevsc_hid_close, + .start = mousevsc_hid_start, + .stop = mousevsc_hid_stop, }; static struct hid_driver mousevsc_hid_driver; -static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len) -{ - struct hid_device *hid_dev; - struct mousevsc_dev *input_device = hv_get_drvdata(dev); - - hid_dev = hid_allocate_device(); - if (IS_ERR(hid_dev)) - return; - - hid_dev->ll_driver = &mousevsc_ll_driver; - hid_dev->driver = &mousevsc_hid_driver; - - if (hid_parse_report(hid_dev, packet, len)) - return; - - hid_dev->bus = BUS_VIRTUAL; - hid_dev->vendor = input_device->hid_dev_info.vendor; - hid_dev->product = input_device->hid_dev_info.product; - hid_dev->version = input_device->hid_dev_info.version; - - sprintf(hid_dev->name, "%s", "Microsoft Vmbus HID-compliant Mouse"); - - if (!hidinput_connect(hid_dev, 0)) { - hid_dev->claimed |= HID_CLAIMED_INPUT; - - input_device->connected = true; - - } - - input_device->hid_device = hid_dev; -} - static int mousevsc_probe(struct hv_device *device, const struct hv_vmbus_device_id *dev_id) { int ret = 0; struct mousevsc_dev *input_dev; + struct hid_device *hid_dev; input_dev = alloc_input_device(device); @@ -524,23 +504,56 @@ static int mousevsc_probe(struct hv_device *device, ret = mousevsc_connect_to_vsp(device); - if (ret != 0) { - vmbus_close(device->channel); - free_input_device(input_dev); - return ret; - } - + if (ret != 0) + goto probe_err0; /* workaround SA-167 */ if (input_dev->report_desc[14] == 0x25) input_dev->report_desc[14] = 0x29; - reportdesc_callback(device, input_dev->report_desc, - input_dev->report_desc_size); + hid_dev = hid_allocate_device(); + if (IS_ERR(hid_dev)) { + ret = PTR_ERR(hid_dev); + goto probe_err0; + } + hid_dev->ll_driver = &mousevsc_ll_driver; + hid_dev->driver = &mousevsc_hid_driver; + hid_dev->bus = BUS_VIRTUAL; + hid_dev->vendor = input_dev->hid_dev_info.vendor; + hid_dev->product = input_dev->hid_dev_info.product; + hid_dev->version = input_dev->hid_dev_info.version; + input_dev->hid_device = hid_dev; + + sprintf(hid_dev->name, "%s", "Microsoft Vmbus HID-compliant Mouse"); + + ret = hid_parse_report(hid_dev, input_dev->report_desc, + input_dev->report_desc_size); + + if (ret) { + hid_err(hid_dev, "parse failed\n"); + goto probe_err1; + } + + ret = hid_hw_start(hid_dev, HID_CONNECT_HIDINPUT | HID_CONNECT_HIDDEV); + + if (ret) { + hid_err(hid_dev, "hw start failed\n"); + goto probe_err1; + } + + input_dev->connected = true; input_dev->init_complete = true; return ret; + +probe_err1: + hid_destroy_device(hid_dev); + +probe_err0: + vmbus_close(device->channel); + free_input_device(input_dev); + return ret; } From 3b5632efd90a9134bc4e6a83a5e0fa26bdcac861 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 25 Oct 2011 17:19:50 -0700 Subject: [PATCH 054/365] Staging: hv: mousevsc: Cleanup mousevsc_on_channel_callback() Cleanup mousevsc_on_channel_callback(). This is based on the code provided by Joe Perches . Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 79 +++++++++++++++-------------------- 1 file changed, 34 insertions(+), 45 deletions(-) diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index ed071b808cdd..b10466f6605b 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -313,73 +313,62 @@ static void mousevsc_on_receive(struct hv_device *device, static void mousevsc_on_channel_callback(void *context) { - const int packetSize = 0x100; - int ret = 0; - struct hv_device *device = (struct hv_device *)context; - + const int packet_size = 0x100; + int ret; + struct hv_device *device = context; u32 bytes_recvd; u64 req_id; - unsigned char packet[0x100]; struct vmpacket_descriptor *desc; - unsigned char *buffer = packet; - int bufferlen = packetSize; + unsigned char *buffer; + int bufferlen = packet_size; + buffer = kmalloc(bufferlen, GFP_ATOMIC); + if (!buffer) + return; do { ret = vmbus_recvpacket_raw(device->channel, buffer, bufferlen, &bytes_recvd, &req_id); - if (ret == 0) { - if (bytes_recvd > 0) { - desc = (struct vmpacket_descriptor *)buffer; + switch (ret) { + case 0: + if (bytes_recvd <= 0) { + kfree(buffer); + return; + } + desc = (struct vmpacket_descriptor *)buffer; - switch (desc->type) { - case VM_PKT_COMP: - break; + switch (desc->type) { + case VM_PKT_COMP: + break; - case VM_PKT_DATA_INBAND: - mousevsc_on_receive( - device, desc); - break; + case VM_PKT_DATA_INBAND: + mousevsc_on_receive(device, desc); + break; - default: - pr_err("unhandled packet type %d, tid %llx len %d\n", - desc->type, - req_id, - bytes_recvd); - break; - } - - /* reset */ - if (bufferlen > packetSize) { - kfree(buffer); - - buffer = packet; - bufferlen = packetSize; - } - } else { - if (bufferlen > packetSize) { - kfree(buffer); - - buffer = packet; - bufferlen = packetSize; - } + default: + pr_err("unhandled packet type %d, tid %llx len %d\n", + desc->type, + req_id, + bytes_recvd); break; } - } else if (ret == -ENOBUFS) { + + break; + + case -ENOBUFS: + kfree(buffer); /* Handle large packet */ bufferlen = bytes_recvd; - buffer = kzalloc(bytes_recvd, GFP_ATOMIC); + buffer = kmalloc(bytes_recvd, GFP_ATOMIC); if (buffer == NULL) { - buffer = packet; - bufferlen = packetSize; - break; + return; } + break; } } while (1); - return; } static int mousevsc_connect_to_vsp(struct hv_device *device) From f50617fabdecdc61076328b6f25d214410fb4244 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 25 Oct 2011 17:19:51 -0700 Subject: [PATCH 055/365] Staging: hv: mousevsc: Add a new line to a debug string Add a new line to a debug string. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index b10466f6605b..21cd050b6b49 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -411,7 +411,7 @@ static int mousevsc_connect_to_vsp(struct hv_device *device) response = &input_dev->protocol_resp; if (!response->response.approved) { - pr_err("synthhid protocol request failed (version %d)", + pr_err("synthhid protocol request failed (version %d)\n", SYNTHHID_INPUT_VERSION); ret = -ENODEV; goto cleanup; From f72a1cc74f9f9f239938cbdc309c66dd87ceaf94 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 25 Oct 2011 17:19:52 -0700 Subject: [PATCH 056/365] Staging: hv: mousevsc: Get rid of unnecessary include files Get rid of unnecessary include files. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 21cd050b6b49..dd42411b1870 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -14,11 +14,8 @@ */ #include #include -#include #include -#include -#include -#include +#include #include #include #include From dba8e1ad957e19ab42c39808a502803dc5b2dee7 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Fri, 28 Oct 2011 15:11:26 -0700 Subject: [PATCH 057/365] Staging: hv: mousevsc: Address some style issues Deal with some style related issues. Also get rid of an unused macro. Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index dd42411b1870..7c7449bb5cf1 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -115,7 +115,6 @@ struct synthhid_input_report { #define INPUTVSC_SEND_RING_BUFFER_SIZE (10*PAGE_SIZE) #define INPUTVSC_RECV_RING_BUFFER_SIZE (10*PAGE_SIZE) -#define NBITS(x) (((x)/BITS_PER_LONG)+1) enum pipe_prot_msg_type { PIPE_MESSAGE_INVALID, @@ -146,6 +145,7 @@ struct mousevsc_prt_msg { struct mousevsc_dev { struct hv_device *device; bool init_complete; + bool connected; struct mousevsc_prt_msg protocol_req; struct mousevsc_prt_msg protocol_resp; /* Synchronize the request/response if needed */ @@ -156,7 +156,6 @@ struct mousevsc_dev { unsigned char *report_desc; u32 report_desc_size; struct hv_input_dev_info hid_dev_info; - bool connected; struct hid_device *hid_device; }; @@ -359,9 +358,9 @@ static void mousevsc_on_channel_callback(void *context) bufferlen = bytes_recvd; buffer = kmalloc(bytes_recvd, GFP_ATOMIC); - if (buffer == NULL) { + if (!buffer) return; - } + break; } } while (1); @@ -376,7 +375,6 @@ static int mousevsc_connect_to_vsp(struct hv_device *device) struct mousevsc_prt_msg *request; struct mousevsc_prt_msg *response; - request = &input_dev->protocol_req; memset(request, 0, sizeof(struct mousevsc_prt_msg)); @@ -388,7 +386,6 @@ static int mousevsc_connect_to_vsp(struct hv_device *device) request->request.header.size = sizeof(unsigned int); request->request.version_requested.version = SYNTHHID_INPUT_VERSION; - ret = vmbus_sendpacket(device->channel, request, sizeof(struct pipe_prt_msg) - sizeof(unsigned char) + @@ -396,11 +393,11 @@ static int mousevsc_connect_to_vsp(struct hv_device *device) (unsigned long)request, VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); - if (ret != 0) + if (ret) goto cleanup; t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ); - if (t == 0) { + if (!t) { ret = -ETIMEDOUT; goto cleanup; } @@ -415,7 +412,7 @@ static int mousevsc_connect_to_vsp(struct hv_device *device) } t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ); - if (t == 0) { + if (!t) { ret = -ETIMEDOUT; goto cleanup; } @@ -487,7 +484,6 @@ static int mousevsc_probe(struct hv_device *device, return ret; } - ret = mousevsc_connect_to_vsp(device); if (ret != 0) From 226383751ff3ce67a648653e8bfe0842f36bbf96 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Fri, 28 Oct 2011 15:11:27 -0700 Subject: [PATCH 058/365] Staging: hv: mousevsc: Add a check to prevent memory corruption Add a check to prevent memory corruption. Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 7c7449bb5cf1..c22f729155fc 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -274,6 +274,18 @@ static void mousevsc_on_receive(struct hv_device *device, switch (hid_msg->header.type) { case SYNTH_HID_PROTOCOL_RESPONSE: + /* + * While it will be impossible for us to protect against + * malicious/buggy hypervisor/host, add a check here to + * ensure we don't corrupt memory. + */ + if ((pipe_msg->size + sizeof(struct pipe_prt_msg) + - sizeof(unsigned char)) + > sizeof(struct mousevsc_prt_msg)) { + WARN_ON(1); + break; + } + memcpy(&input_dev->protocol_resp, pipe_msg, pipe_msg->size + sizeof(struct pipe_prt_msg) - sizeof(unsigned char)); From 1c7dac3269e8dc77a1b6dc08b8a7fd6731e13b7f Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Fri, 28 Oct 2011 15:11:28 -0700 Subject: [PATCH 059/365] Staging: hv: mousevsc: Use the KBUILD_MODNAME macro Use the KBUILD_MODNAME macro. Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index c22f729155fc..2c2e1b4e9b85 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -578,7 +578,7 @@ static const struct hv_vmbus_device_id id_table[] = { MODULE_DEVICE_TABLE(vmbus, id_table); static struct hv_driver mousevsc_drv = { - .name = "mousevsc", + .name = KBUILD_MODNAME, .id_table = id_table, .probe = mousevsc_probe, .remove = mousevsc_remove, From 4e03e697c5446146318cdb6344af0060541cbc1c Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 8 Nov 2011 09:01:40 -0800 Subject: [PATCH 060/365] Staging: hv: storvsc: Use mempools to allocate struct storvsc_cmd_request We intend to use the storage driver to manage the root device. To avoid deadlocks, use mempools to allocate struct storvsc_cmd_request. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index ae8c33e7849c..6a255e977219 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -42,6 +43,7 @@ #include +#define STORVSC_MIN_BUF_NR 64 #define STORVSC_RING_BUFFER_SIZE (20*PAGE_SIZE) static int storvsc_ringbuffer_size = STORVSC_RING_BUFFER_SIZE; @@ -287,6 +289,7 @@ struct storvsc_device { struct hv_host_device { struct hv_device *dev; struct kmem_cache *request_pool; + mempool_t *request_mempool; unsigned int port; unsigned char path; unsigned char target; @@ -974,8 +977,10 @@ static int storvsc_remove(struct hv_device *dev) storvsc_dev_remove(dev); if (host_dev->request_pool) { + mempool_destroy(host_dev->request_mempool); kmem_cache_destroy(host_dev->request_pool); host_dev->request_pool = NULL; + host_dev->request_mempool = NULL; } return 0; } @@ -1120,7 +1125,7 @@ static void storvsc_command_completion(struct hv_storvsc_request *request) scsi_done_fn(scmnd); - kmem_cache_free(host_dev->request_pool, cmd_request); + mempool_free(cmd_request, host_dev->request_mempool); } static bool storvsc_check_scsi_cmd(struct scsi_cmnd *scmnd) @@ -1176,12 +1181,13 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd, request_size = sizeof(struct storvsc_cmd_request); - cmd_request = kmem_cache_zalloc(host_dev->request_pool, + cmd_request = mempool_alloc(host_dev->request_mempool, GFP_ATOMIC); if (!cmd_request) { scmnd->scsi_done = NULL; return SCSI_MLQUEUE_DEVICE_BUSY; } + memset(cmd_request, 0, sizeof(struct storvsc_cmd_request)); /* Setup the cmd request */ cmd_request->bounce_sgl_count = 0; @@ -1235,8 +1241,8 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd, if (!cmd_request->bounce_sgl) { scmnd->scsi_done = NULL; scmnd->host_scribble = NULL; - kmem_cache_free(host_dev->request_pool, - cmd_request); + mempool_free(cmd_request, + host_dev->request_mempool); return SCSI_MLQUEUE_HOST_BUSY; } @@ -1278,7 +1284,7 @@ retry_request: destroy_bounce_buffer(cmd_request->bounce_sgl, cmd_request->bounce_sgl_count); - kmem_cache_free(host_dev->request_pool, cmd_request); + mempool_free(cmd_request, host_dev->request_mempool); scmnd->scsi_done = NULL; scmnd->host_scribble = NULL; @@ -1348,6 +1354,7 @@ static int storvsc_probe(struct hv_device *device, const struct hv_vmbus_device_id *dev_id) { int ret; + int number = STORVSC_MIN_BUF_NR; struct Scsi_Host *host; struct hv_host_device *host_dev; bool dev_is_ide = ((dev_id->driver_data == IDE_GUID) ? true : false); @@ -1376,8 +1383,19 @@ static int storvsc_probe(struct hv_device *device, return -ENOMEM; } + host_dev->request_mempool = mempool_create(number, mempool_alloc_slab, + mempool_free_slab, + host_dev->request_pool); + + if (!host_dev->request_mempool) { + kmem_cache_destroy(host_dev->request_pool); + scsi_host_put(host); + return -ENOMEM; + } + stor_device = kzalloc(sizeof(struct storvsc_device), GFP_KERNEL); if (!stor_device) { + mempool_destroy(host_dev->request_mempool); kmem_cache_destroy(host_dev->request_pool); scsi_host_put(host); return -ENOMEM; @@ -1392,6 +1410,7 @@ static int storvsc_probe(struct hv_device *device, stor_device->port_number = host->host_no; ret = storvsc_connect_to_vsp(device, storvsc_ringbuffer_size); if (ret) { + mempool_destroy(host_dev->request_mempool); kmem_cache_destroy(host_dev->request_pool); scsi_host_put(host); kfree(stor_device); @@ -1431,6 +1450,7 @@ static int storvsc_probe(struct hv_device *device, err_out: storvsc_dev_remove(device); + mempool_destroy(host_dev->request_mempool); kmem_cache_destroy(host_dev->request_pool); scsi_host_put(host); return -ENODEV; From 225ce6eab741d51d565f67ce9065c596c6535f25 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 8 Nov 2011 09:01:41 -0800 Subject: [PATCH 061/365] Staging: hv: storvsc: Cleanup error handling in the probe function Cleanup error handling in the probe function. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 42 ++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 6a255e977219..a72cc22062b5 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -1388,17 +1388,14 @@ static int storvsc_probe(struct hv_device *device, host_dev->request_pool); if (!host_dev->request_mempool) { - kmem_cache_destroy(host_dev->request_pool); - scsi_host_put(host); - return -ENOMEM; + ret = -ENOMEM; + goto err_out0; } stor_device = kzalloc(sizeof(struct storvsc_device), GFP_KERNEL); if (!stor_device) { - mempool_destroy(host_dev->request_mempool); - kmem_cache_destroy(host_dev->request_pool); - scsi_host_put(host); - return -ENOMEM; + ret = -ENOMEM; + goto err_out1; } stor_device->destroy = false; @@ -1409,13 +1406,8 @@ static int storvsc_probe(struct hv_device *device, stor_device->port_number = host->host_no; ret = storvsc_connect_to_vsp(device, storvsc_ringbuffer_size); - if (ret) { - mempool_destroy(host_dev->request_mempool); - kmem_cache_destroy(host_dev->request_pool); - scsi_host_put(host); - kfree(stor_device); - return ret; - } + if (ret) + goto err_out2; if (dev_is_ide) storvsc_get_ide_info(device, &target, &path); @@ -1435,7 +1427,7 @@ static int storvsc_probe(struct hv_device *device, /* Register the HBA and start the scsi bus scan */ ret = scsi_add_host(host, &device->device); if (ret != 0) - goto err_out; + goto err_out3; if (!dev_is_ide) { scsi_scan_host(host); @@ -1444,16 +1436,30 @@ static int storvsc_probe(struct hv_device *device, ret = scsi_add_device(host, 0, target, 0); if (ret) { scsi_remove_host(host); - goto err_out; + goto err_out3; } return 0; -err_out: +err_out3: + /* + * Once we have connected with the host, we would need to + * to invoke storvsc_dev_remove() to rollback this state and + * this call also frees up the stor_device; hence the jump around + * err_out2 label. + */ storvsc_dev_remove(device); + goto err_out1; + +err_out2: + kfree(stor_device); + +err_out1: mempool_destroy(host_dev->request_mempool); + +err_out0: kmem_cache_destroy(host_dev->request_pool); scsi_host_put(host); - return -ENODEV; + return ret; } /* The one and only one */ From 59e00e744d2413430ebaa09a5fdb61e9ad02a492 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 8 Nov 2011 09:01:42 -0800 Subject: [PATCH 062/365] Staging: hv: storvsc: Fixup the error when processing SET_WINDOW command Fixup the error when processing SET_WINDOW command. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index a72cc22062b5..e16c7a3a402d 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -1136,7 +1136,7 @@ static bool storvsc_check_scsi_cmd(struct scsi_cmnd *scmnd) switch (scsi_op) { /* smartd sends this command, which will offline the device */ case SET_WINDOW: - scmnd->result = DID_ERROR << 16; + scmnd->result = ILLEGAL_REQUEST << 16; allowed = false; break; default: From a00e8224c19fa5ba3007da00d850865cbefcaabd Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 8 Nov 2011 09:01:43 -0800 Subject: [PATCH 063/365] Staging: hv: storvsc: Fix error handling storvsc_host_reset() Fix error handling storvsc_host_reset(). I would like to thank Long Li for reporting this. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Reported-by: Long Li Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index e16c7a3a402d..a1452455e10a 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -1019,7 +1019,7 @@ static int storvsc_host_reset(struct hv_device *device) stor_device = get_out_stor_device(device); if (!stor_device) - return -ENODEV; + return FAILED; request = &stor_device->reset_request; vstor_packet = &request->vstor_packet; @@ -1036,13 +1036,11 @@ static int storvsc_host_reset(struct hv_device *device) VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); if (ret != 0) - goto cleanup; + return FAILED; t = wait_for_completion_timeout(&request->wait_event, 5*HZ); - if (t == 0) { - ret = -ETIMEDOUT; - goto cleanup; - } + if (t == 0) + return TIMEOUT_ERROR; /* @@ -1050,8 +1048,7 @@ static int storvsc_host_reset(struct hv_device *device) * should have been flushed out and return to us */ -cleanup: - return ret; + return SUCCESS; } @@ -1060,16 +1057,11 @@ cleanup: */ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd) { - int ret; struct hv_host_device *host_dev = (struct hv_host_device *)scmnd->device->host->hostdata; struct hv_device *dev = host_dev->dev; - ret = storvsc_host_reset(dev); - if (ret != 0) - return ret; - - return ret; + return storvsc_host_reset(dev); } From 7f33f30a67cebbdaa938e34c5144424d2f0ce9cc Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 8 Nov 2011 09:01:44 -0800 Subject: [PATCH 064/365] Staging: hv: storvsc: Use the accessor function shost_priv() Use the accessor function shost_priv(). Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index a1452455e10a..b21e85f8e0d0 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -968,8 +968,7 @@ static int storvsc_remove(struct hv_device *dev) { struct storvsc_device *stor_device = hv_get_drvdata(dev); struct Scsi_Host *host = stor_device->host; - struct hv_host_device *host_dev = - (struct hv_host_device *)host->hostdata; + struct hv_host_device *host_dev = shost_priv(host); scsi_remove_host(host); @@ -1057,8 +1056,7 @@ static int storvsc_host_reset(struct hv_device *device) */ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd) { - struct hv_host_device *host_dev = - (struct hv_host_device *)scmnd->device->host->hostdata; + struct hv_host_device *host_dev = shost_priv(scmnd->device->host); struct hv_device *dev = host_dev->dev; return storvsc_host_reset(dev); @@ -1073,8 +1071,7 @@ static void storvsc_command_completion(struct hv_storvsc_request *request) struct storvsc_cmd_request *cmd_request = (struct storvsc_cmd_request *)request->context; struct scsi_cmnd *scmnd = cmd_request->cmd; - struct hv_host_device *host_dev = - (struct hv_host_device *)scmnd->device->host->hostdata; + struct hv_host_device *host_dev = shost_priv(scmnd->device->host); void (*scsi_done_fn)(struct scsi_cmnd *); struct scsi_sense_hdr sense_hdr; struct vmscsi_request *vm_srb; @@ -1144,8 +1141,7 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd, void (*done)(struct scsi_cmnd *)) { int ret; - struct hv_host_device *host_dev = - (struct hv_host_device *)scmnd->device->host->hostdata; + struct hv_host_device *host_dev = shost_priv(scmnd->device->host); struct hv_device *dev = host_dev->dev; struct hv_storvsc_request *request; struct storvsc_cmd_request *cmd_request; @@ -1359,7 +1355,7 @@ static int storvsc_probe(struct hv_device *device, if (!host) return -ENOMEM; - host_dev = (struct hv_host_device *)host->hostdata; + host_dev = shost_priv(host); memset(host_dev, 0, sizeof(struct hv_host_device)); host_dev->port = host->host_no; From bab445e12b45153282fb7d39143516e11987deaa Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 8 Nov 2011 09:01:45 -0800 Subject: [PATCH 065/365] Staging: hv: storvsc: Use the unlocked version queuecommand Use the unlocked version queuecommand. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index b21e85f8e0d0..827bc68f6052 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -1137,11 +1137,10 @@ static bool storvsc_check_scsi_cmd(struct scsi_cmnd *scmnd) /* * storvsc_queuecommand - Initiate command processing */ -static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd, - void (*done)(struct scsi_cmnd *)) +static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) { int ret; - struct hv_host_device *host_dev = shost_priv(scmnd->device->host); + struct hv_host_device *host_dev = shost_priv(host); struct hv_device *dev = host_dev->dev; struct hv_storvsc_request *request; struct storvsc_cmd_request *cmd_request; @@ -1152,7 +1151,7 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd, struct vmscsi_request *vm_srb; if (storvsc_check_scsi_cmd(scmnd) == false) { - done(scmnd); + scmnd->scsi_done(scmnd); return 0; } @@ -1165,16 +1164,13 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd, goto retry_request; } - scmnd->scsi_done = done; - request_size = sizeof(struct storvsc_cmd_request); cmd_request = mempool_alloc(host_dev->request_mempool, GFP_ATOMIC); - if (!cmd_request) { - scmnd->scsi_done = NULL; + if (!cmd_request) return SCSI_MLQUEUE_DEVICE_BUSY; - } + memset(cmd_request, 0, sizeof(struct storvsc_cmd_request)); /* Setup the cmd request */ @@ -1227,7 +1223,6 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd, create_bounce_buffer(sgl, scsi_sg_count(scmnd), scsi_bufflen(scmnd)); if (!cmd_request->bounce_sgl) { - scmnd->scsi_done = NULL; scmnd->host_scribble = NULL; mempool_free(cmd_request, host_dev->request_mempool); @@ -1274,7 +1269,6 @@ retry_request: mempool_free(cmd_request, host_dev->request_mempool); - scmnd->scsi_done = NULL; scmnd->host_scribble = NULL; ret = SCSI_MLQUEUE_DEVICE_BUSY; @@ -1283,9 +1277,6 @@ retry_request: return ret; } -static DEF_SCSI_QCMD(storvsc_queuecommand) - - /* Scsi driver */ static struct scsi_host_template scsi_driver = { .module = THIS_MODULE, From fafb0efc303a916f9902cbadddef3ea125720c1b Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 8 Nov 2011 09:01:46 -0800 Subject: [PATCH 066/365] Staging: hv: storvsc: use the macro KBUILD_MODNAME Use the macro KBUILD_MODNAME. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 827bc68f6052..916f5d04c510 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -1444,7 +1444,7 @@ err_out0: /* The one and only one */ static struct hv_driver storvsc_drv = { - .name = "storvsc", + .name = KBUILD_MODNAME, .id_table = id_table, .probe = storvsc_probe, .remove = storvsc_remove, From a404c1ff5556fe29460c097a34d2abe10ddd6e0a Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 8 Nov 2011 09:01:47 -0800 Subject: [PATCH 067/365] Staging: hv: storvsc: Get rid of an unnecessary forward declaration Get rid of an unnecessary forward declaration. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 916f5d04c510..4cdb417fd0f9 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -236,8 +236,6 @@ struct vstor_packet { #define STORVSC_MAX_CHANNELS 1 #define STORVSC_MAX_CMD_LEN 16 -struct hv_storvsc_request; - /* Matches Windows-end */ enum storvsc_request_type { WRITE_TYPE, From 2b9525f511791758b394643b61754a9688e0707d Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 8 Nov 2011 09:01:48 -0800 Subject: [PATCH 068/365] Staging: hv: storvsc: Upgrade the vmstor protocol version In preparation for supporting hot add/remove of scsi devices, upgrade the vmstor protocol version. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 4cdb417fd0f9..9153641f7946 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -80,7 +80,7 @@ MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)"); /* V1 Beta 0.1 */ /* V1 RC < 2008/1/31 1.0 */ /* V1 RC > 2008/1/31 2.0 */ -#define VMSTOR_PROTOCOL_VERSION_CURRENT VMSTOR_PROTOCOL_VERSION(2, 0) +#define VMSTOR_PROTOCOL_VERSION_CURRENT VMSTOR_PROTOCOL_VERSION(4, 2) @@ -106,7 +106,8 @@ enum vstor_packet_operation { VSTOR_OPERATION_END_INITIALIZATION = 8, VSTOR_OPERATION_QUERY_PROTOCOL_VERSION = 9, VSTOR_OPERATION_QUERY_PROPERTIES = 10, - VSTOR_OPERATION_MAXIMUM = 10 + VSTOR_OPERATION_ENUMERATE_BUS = 11, + VSTOR_OPERATION_MAXIMUM = 11 }; /* From 126757998a50659f79a3f1ff23fccfc40ff1bf5c Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 8 Nov 2011 09:01:49 -0800 Subject: [PATCH 069/365] Staging: hv: storvsc: Support hot add of scsi disks Support hot add of scsi disks. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 38 ++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 9153641f7946..7c82d148f32e 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -304,6 +304,30 @@ struct storvsc_cmd_request { struct hv_storvsc_request request; }; +struct storvsc_scan_work { + struct work_struct work; + struct Scsi_Host *host; + uint lun; +}; + +static void storvsc_bus_scan(struct work_struct *work) +{ + struct storvsc_scan_work *wrk; + int id, order_id; + + wrk = container_of(work, struct storvsc_scan_work, work); + for (id = 0; id < wrk->host->max_id; ++id) { + if (wrk->host->reverse_ordering) + order_id = wrk->host->max_id - id - 1; + else + order_id = id; + + scsi_scan_target(&wrk->host->shost_gendev, 0, + order_id, SCAN_WILD_CARD, 1); + } + kfree(wrk); +} + static inline struct storvsc_device *get_out_stor_device( struct hv_device *device) { @@ -551,11 +575,25 @@ static void storvsc_on_receive(struct hv_device *device, struct vstor_packet *vstor_packet, struct hv_storvsc_request *request) { + struct storvsc_scan_work *work; + struct storvsc_device *stor_device; + switch (vstor_packet->operation) { case VSTOR_OPERATION_COMPLETE_IO: storvsc_on_io_completion(device, vstor_packet, request); break; + case VSTOR_OPERATION_REMOVE_DEVICE: + case VSTOR_OPERATION_ENUMERATE_BUS: + stor_device = get_in_stor_device(device); + work = kmalloc(sizeof(struct storvsc_scan_work), GFP_ATOMIC); + if (!work) + return; + + INIT_WORK(&work->work, storvsc_bus_scan); + work->host = stor_device->host; + schedule_work(&work->work); + break; default: break; From b401731985bfa7c02e4e5673a151b29ae7180fce Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 8 Nov 2011 09:01:50 -0800 Subject: [PATCH 070/365] Staging: hv: storvsc: Support hot-removing of scsi devices Support hot-removing of scsi devices. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/storvsc_drv.c | 45 ++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 7c82d148f32e..0245143dc2f9 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -328,6 +328,27 @@ static void storvsc_bus_scan(struct work_struct *work) kfree(wrk); } +static void storvsc_remove_lun(struct work_struct *work) +{ + struct storvsc_scan_work *wrk; + struct scsi_device *sdev; + + wrk = container_of(work, struct storvsc_scan_work, work); + if (!scsi_host_get(wrk->host)) + goto done; + + sdev = scsi_device_lookup(wrk->host, 0, 0, wrk->lun); + + if (sdev) { + scsi_remove_device(sdev); + scsi_device_put(sdev); + } + scsi_host_put(wrk->host); + +done: + kfree(wrk); +} + static inline struct storvsc_device *get_out_stor_device( struct hv_device *device) { @@ -1112,6 +1133,7 @@ static void storvsc_command_completion(struct hv_storvsc_request *request) void (*scsi_done_fn)(struct scsi_cmnd *); struct scsi_sense_hdr sense_hdr; struct vmscsi_request *vm_srb; + struct storvsc_scan_work *wrk; vm_srb = &request->vstor_packet.vm_srb; if (cmd_request->bounce_sgl_count) { @@ -1134,6 +1156,29 @@ static void storvsc_command_completion(struct hv_storvsc_request *request) else scmnd->result = vm_srb->scsi_status; + /* + * If the LUN is invalid; remove the device. + */ + if (vm_srb->srb_status == 0x20) { + struct storvsc_device *stor_dev; + struct hv_device *dev = host_dev->dev; + struct Scsi_Host *host; + + stor_dev = get_in_stor_device(dev); + host = stor_dev->host; + + wrk = kmalloc(sizeof(struct storvsc_scan_work), + GFP_ATOMIC); + if (!wrk) { + scmnd->result = DID_TARGET_FAILURE << 16; + } else { + wrk->host = host; + wrk->lun = vm_srb->lun; + INIT_WORK(&wrk->work, storvsc_remove_lun); + schedule_work(&wrk->work); + } + } + if (scmnd->result) { if (scsi_normalize_sense(scmnd->sense_buffer, SCSI_SENSE_BUFFERSIZE, &sense_hdr)) From 27b7923035f737a7e6384d0084e34706ea068040 Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Sat, 12 Nov 2011 13:21:49 +0100 Subject: [PATCH 071/365] staging: hv: Use kmemdup rather than duplicating its implementation Use kmemdup rather than duplicating its implementation The semantic patch that makes this change is available in scripts/coccinelle/api/memdup.cocci. Signed-off-by: Thomas Meyer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/hv_mouse.c | 4 +--- drivers/staging/hv/netvsc.c | 11 +++-------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index 2c2e1b4e9b85..a28c54983282 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -201,13 +201,11 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, desc = &device_info->hid_descriptor; WARN_ON(desc->bLength == 0); - input_device->hid_desc = kzalloc(desc->bLength, GFP_ATOMIC); + input_device->hid_desc = kmemdup(desc, desc->bLength, GFP_ATOMIC); if (!input_device->hid_desc) goto cleanup; - memcpy(input_device->hid_desc, desc, desc->bLength); - input_device->report_desc_size = desc->desc[0].wDescriptorLength; if (input_device->report_desc_size == 0) goto cleanup; diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index b902579c7fe6..28e69a6c74a1 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -230,19 +230,14 @@ static int netvsc_init_recv_buf(struct hv_device *device) net_device->recv_section_cnt = init_packet->msg. v1_msg.send_recv_buf_complete.num_sections; - net_device->recv_section = kmalloc(net_device->recv_section_cnt - * sizeof(struct nvsp_1_receive_buffer_section), GFP_KERNEL); + net_device->recv_section = kmemdup(init_packet->msg.v1_msg.send_recv_buf_complete.sections, + net_device->recv_section_cnt * sizeof(struct nvsp_1_receive_buffer_section), + GFP_KERNEL); if (net_device->recv_section == NULL) { ret = -EINVAL; goto cleanup; } - memcpy(net_device->recv_section, - init_packet->msg.v1_msg. - send_recv_buf_complete.sections, - net_device->recv_section_cnt * - sizeof(struct nvsp_1_receive_buffer_section)); - /* * For 1st release, there should only be 1 section that represents the * entire receive buffer From ed8e9bb7e082bea54aef18db497cb4297c2cf0fb Mon Sep 17 00:00:00 2001 From: "Diego F. Marfil" Date: Thu, 3 Nov 2011 12:25:35 -0300 Subject: [PATCH 072/365] Staging: bcm: hostmibs: C99 comments replaced Signed-off-by: Diego F. Marfil Reviewed-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/hostmibs.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/staging/bcm/hostmibs.c b/drivers/staging/bcm/hostmibs.c index c13ea5c9a2aa..c77e273126c7 100644 --- a/drivers/staging/bcm/hostmibs.c +++ b/drivers/staging/bcm/hostmibs.c @@ -1,4 +1,3 @@ - /* * File Name: hostmibs.c * @@ -8,6 +7,7 @@ * the driver to the Host MIBS structure and giving the same to Application. * */ + #include "headers.h" INT ProcessGetHostMibs(PMINI_ADAPTER Adapter, S_MIBS_HOST_STATS_MIBS *pstHostMibs) @@ -26,7 +26,7 @@ INT ProcessGetHostMibs(PMINI_ADAPTER Adapter, S_MIBS_HOST_STATS_MIBS *pstHostMi return STATUS_FAILURE; } - //Copy the classifier Table + /* Copy the classifier Table */ for(nClassifierIndex=0; nClassifierIndex < MAX_CLASSIFIERS; nClassifierIndex++) { @@ -36,7 +36,7 @@ INT ProcessGetHostMibs(PMINI_ADAPTER Adapter, S_MIBS_HOST_STATS_MIBS *pstHostMi sizeof(S_MIBS_CLASSIFIER_RULE)); } - //Copy the SF Table + /* Copy the SF Table */ for(nSfIndex=0; nSfIndex < NO_OF_QUEUES ; nSfIndex++) { if(Adapter->PackInfo[nSfIndex].bValid) @@ -45,11 +45,14 @@ INT ProcessGetHostMibs(PMINI_ADAPTER Adapter, S_MIBS_HOST_STATS_MIBS *pstHostMi } else { - //if index in not valid, don't process this for the PHS table. Go For the next entry. + /* If index in not valid, + * don't process this for the PHS table. + * Go For the next entry. + */ continue ; } - //Retrieve the SFID Entry Index for requested Service Flow + /* Retrieve the SFID Entry Index for requested Service Flow */ if(PHS_INVALID_TABLE_INDEX == GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable, Adapter->PackInfo[nSfIndex].usVCID_Value ,&pstServiceFlowEntry)) { @@ -82,7 +85,7 @@ INT ProcessGetHostMibs(PMINI_ADAPTER Adapter, S_MIBS_HOST_STATS_MIBS *pstHostMi } - //copy other Host Statistics parameters + /* Copy other Host Statistics parameters */ pstHostMibs->stHostInfo.GoodTransmits = Adapter->dev->stats.tx_packets; pstHostMibs->stHostInfo.GoodReceives = Adapter->dev->stats.rx_packets; pstHostMibs->stHostInfo.CurrNumFreeDesc = From 94abda9837d8b269e26bb8b992fc95a780fe6779 Mon Sep 17 00:00:00 2001 From: "Diego F. Marfil" Date: Thu, 3 Nov 2011 12:25:36 -0300 Subject: [PATCH 073/365] Staging: bcm: hostmibs: White spaces and indentation fixes. Signed-off-by: Diego F. Marfil Reviewed-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/hostmibs.c | 107 +++++++++++++++------------------ 1 file changed, 49 insertions(+), 58 deletions(-) diff --git a/drivers/staging/bcm/hostmibs.c b/drivers/staging/bcm/hostmibs.c index c77e273126c7..aee801ec88a7 100644 --- a/drivers/staging/bcm/hostmibs.c +++ b/drivers/staging/bcm/hostmibs.c @@ -5,77 +5,72 @@ * * Abstract: This file contains the routines to copy the statistics used by * the driver to the Host MIBS structure and giving the same to Application. - * */ #include "headers.h" -INT ProcessGetHostMibs(PMINI_ADAPTER Adapter, S_MIBS_HOST_STATS_MIBS *pstHostMibs) +INT ProcessGetHostMibs(PMINI_ADAPTER Adapter, S_MIBS_HOST_STATS_MIBS *pstHostMibs) { - S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL; - S_PHS_RULE *pstPhsRule = NULL; - S_CLASSIFIER_TABLE *pstClassifierTable = NULL; - S_CLASSIFIER_ENTRY *pstClassifierRule = NULL; - PPHS_DEVICE_EXTENSION pDeviceExtension = (PPHS_DEVICE_EXTENSION)&Adapter->stBCMPhsContext; + S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL; + S_PHS_RULE *pstPhsRule = NULL; + S_CLASSIFIER_TABLE *pstClassifierTable = NULL; + S_CLASSIFIER_ENTRY *pstClassifierRule = NULL; + PPHS_DEVICE_EXTENSION pDeviceExtension = (PPHS_DEVICE_EXTENSION) &Adapter->stBCMPhsContext; - UINT nClassifierIndex = 0, nPhsTableIndex = 0,nSfIndex = 0, uiIndex = 0; + UINT nClassifierIndex = 0, nPhsTableIndex = 0, nSfIndex = 0, uiIndex = 0; - if(pDeviceExtension == NULL) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, HOST_MIBS, DBG_LVL_ALL, "Invalid Device Extension\n"); + if (pDeviceExtension == NULL) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, HOST_MIBS, DBG_LVL_ALL, "Invalid Device Extension\n"); return STATUS_FAILURE; } /* Copy the classifier Table */ - for(nClassifierIndex=0; nClassifierIndex < MAX_CLASSIFIERS; - nClassifierIndex++) - { - if(Adapter->astClassifierTable[nClassifierIndex].bUsed == TRUE) - memcpy((PVOID)&pstHostMibs->astClassifierTable[nClassifierIndex], - (PVOID)&Adapter->astClassifierTable[nClassifierIndex], - sizeof(S_MIBS_CLASSIFIER_RULE)); + for (nClassifierIndex = 0; nClassifierIndex < MAX_CLASSIFIERS; nClassifierIndex++) { + if (Adapter->astClassifierTable[nClassifierIndex].bUsed == TRUE) + memcpy((PVOID) & pstHostMibs-> + astClassifierTable[nClassifierIndex], + (PVOID) & Adapter-> + astClassifierTable[nClassifierIndex], + sizeof(S_MIBS_CLASSIFIER_RULE)); } - /* Copy the SF Table */ - for(nSfIndex=0; nSfIndex < NO_OF_QUEUES ; nSfIndex++) - { - if(Adapter->PackInfo[nSfIndex].bValid) - { - memcpy((PVOID)&pstHostMibs->astSFtable[nSfIndex],(PVOID)&Adapter->PackInfo[nSfIndex],sizeof(S_MIBS_SERVICEFLOW_TABLE)); - } - else - { - /* If index in not valid, - * don't process this for the PHS table. - * Go For the next entry. - */ - continue ; - } + /* Copy the SF Table */ + for (nSfIndex = 0; nSfIndex < NO_OF_QUEUES; nSfIndex++) { + if (Adapter->PackInfo[nSfIndex].bValid) { + memcpy((PVOID) & pstHostMibs->astSFtable[nSfIndex], + (PVOID) & Adapter->PackInfo[nSfIndex], + sizeof(S_MIBS_SERVICEFLOW_TABLE)); + } else { + /* If index in not valid, + * don't process this for the PHS table. + * Go For the next entry. + */ + continue; + } /* Retrieve the SFID Entry Index for requested Service Flow */ - if(PHS_INVALID_TABLE_INDEX == GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable, - Adapter->PackInfo[nSfIndex].usVCID_Value ,&pstServiceFlowEntry)) - { + if (PHS_INVALID_TABLE_INDEX == + GetServiceFlowEntry(pDeviceExtension-> + pstServiceFlowPhsRulesTable, + Adapter->PackInfo[nSfIndex]. + usVCID_Value, &pstServiceFlowEntry)) - continue; - } + continue; pstClassifierTable = pstServiceFlowEntry->pstClassifierTable; - - for(uiIndex = 0; uiIndex < MAX_PHSRULE_PER_SF; uiIndex++) - { + for (uiIndex = 0; uiIndex < MAX_PHSRULE_PER_SF; uiIndex++) { pstClassifierRule = &pstClassifierTable->stActivePhsRulesList[uiIndex]; - if(pstClassifierRule->bUsed) - { - pstPhsRule = pstClassifierRule->pstPhsRule; + if (pstClassifierRule->bUsed) { + pstPhsRule = pstClassifierRule->pstPhsRule; - pstHostMibs->astPhsRulesTable[nPhsTableIndex].ulSFID = Adapter->PackInfo[nSfIndex].ulSFID; + pstHostMibs->astPhsRulesTable[nPhsTableIndex]. + ulSFID = Adapter->PackInfo[nSfIndex].ulSFID; - memcpy(&pstHostMibs->astPhsRulesTable[nPhsTableIndex].u8PHSI, - &pstPhsRule->u8PHSI, - sizeof(S_PHS_RULE)); + memcpy(&pstHostMibs-> + astPhsRulesTable[nPhsTableIndex].u8PHSI, + &pstPhsRule->u8PHSI, sizeof(S_PHS_RULE)); nPhsTableIndex++; } @@ -84,33 +79,29 @@ INT ProcessGetHostMibs(PMINI_ADAPTER Adapter, S_MIBS_HOST_STATS_MIBS *pstHostMi } - /* Copy other Host Statistics parameters */ pstHostMibs->stHostInfo.GoodTransmits = Adapter->dev->stats.tx_packets; pstHostMibs->stHostInfo.GoodReceives = Adapter->dev->stats.rx_packets; - pstHostMibs->stHostInfo.CurrNumFreeDesc = - atomic_read(&Adapter->CurrNumFreeTxDesc); + pstHostMibs->stHostInfo.CurrNumFreeDesc = atomic_read(&Adapter->CurrNumFreeTxDesc); pstHostMibs->stHostInfo.BEBucketSize = Adapter->BEBucketSize; pstHostMibs->stHostInfo.rtPSBucketSize = Adapter->rtPSBucketSize; pstHostMibs->stHostInfo.TimerActive = Adapter->TimerActive; pstHostMibs->stHostInfo.u32TotalDSD = Adapter->u32TotalDSD; - memcpy(pstHostMibs->stHostInfo.aTxPktSizeHist,Adapter->aTxPktSizeHist,sizeof(UINT32)*MIBS_MAX_HIST_ENTRIES); - memcpy(pstHostMibs->stHostInfo.aRxPktSizeHist,Adapter->aRxPktSizeHist,sizeof(UINT32)*MIBS_MAX_HIST_ENTRIES); + memcpy(pstHostMibs->stHostInfo.aTxPktSizeHist, Adapter->aTxPktSizeHist, sizeof(UINT32) * MIBS_MAX_HIST_ENTRIES); + memcpy(pstHostMibs->stHostInfo.aRxPktSizeHist, Adapter->aRxPktSizeHist, sizeof(UINT32) * MIBS_MAX_HIST_ENTRIES); return STATUS_SUCCESS; } - VOID GetDroppedAppCntrlPktMibs(S_MIBS_HOST_STATS_MIBS *pstHostMibs, const PPER_TARANG_DATA pTarang) { memcpy(&(pstHostMibs->stDroppedAppCntrlMsgs), - &(pTarang->stDroppedAppCntrlMsgs),sizeof(S_MIBS_DROPPED_APP_CNTRL_MESSAGES)); + &(pTarang->stDroppedAppCntrlMsgs), + sizeof(S_MIBS_DROPPED_APP_CNTRL_MESSAGES)); } - -VOID CopyMIBSExtendedSFParameters(PMINI_ADAPTER Adapter, - CServiceFlowParamSI *psfLocalSet, UINT uiSearchRuleIndex) +VOID CopyMIBSExtendedSFParameters(PMINI_ADAPTER Adapter, CServiceFlowParamSI *psfLocalSet, UINT uiSearchRuleIndex) { Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfSfid = psfLocalSet->u32SFID; Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsMaxSustainedRate = psfLocalSet->u32MaxSustainedTrafficRate; From 57bfa9d41741614cb945064521fc8904440313c7 Mon Sep 17 00:00:00 2001 From: "Diego F. Marfil" Date: Thu, 3 Nov 2011 12:25:37 -0300 Subject: [PATCH 074/365] Staging: bcm: hostmibs: Added temporary variable to shorten lines Signed-off-by: Diego F. Marfil Reviewed-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/hostmibs.c | 66 +++++++++++++++++----------------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/drivers/staging/bcm/hostmibs.c b/drivers/staging/bcm/hostmibs.c index aee801ec88a7..101c4e31249e 100644 --- a/drivers/staging/bcm/hostmibs.c +++ b/drivers/staging/bcm/hostmibs.c @@ -103,37 +103,39 @@ VOID GetDroppedAppCntrlPktMibs(S_MIBS_HOST_STATS_MIBS *pstHostMibs, const PPER_T VOID CopyMIBSExtendedSFParameters(PMINI_ADAPTER Adapter, CServiceFlowParamSI *psfLocalSet, UINT uiSearchRuleIndex) { - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfSfid = psfLocalSet->u32SFID; - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsMaxSustainedRate = psfLocalSet->u32MaxSustainedTrafficRate; - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsMaxTrafficBurst = psfLocalSet->u32MaxTrafficBurst; - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsMinReservedRate = psfLocalSet->u32MinReservedTrafficRate; - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsToleratedJitter = psfLocalSet->u32ToleratedJitter; - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsMaxLatency = psfLocalSet->u32MaximumLatency; - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsFixedVsVariableSduInd = psfLocalSet->u8FixedLengthVSVariableLengthSDUIndicator; - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsFixedVsVariableSduInd = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsFixedVsVariableSduInd); - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsSduSize = psfLocalSet->u8SDUSize; - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsSduSize = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsSduSize); - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsSfSchedulingType = psfLocalSet->u8ServiceFlowSchedulingType; - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsSfSchedulingType = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsSfSchedulingType); - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqEnable = psfLocalSet->u8ARQEnable; - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqEnable = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqEnable); - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqWindowSize = ntohs(psfLocalSet->u16ARQWindowSize); - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqWindowSize = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqWindowSize); - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqBlockLifetime = ntohs(psfLocalSet->u16ARQBlockLifeTime); - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqBlockLifetime = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqBlockLifetime); - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqSyncLossTimeout = ntohs(psfLocalSet->u16ARQSyncLossTimeOut); - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqSyncLossTimeout = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqSyncLossTimeout); - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqDeliverInOrder = psfLocalSet->u8ARQDeliverInOrder; - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqDeliverInOrder = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqDeliverInOrder); - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqRxPurgeTimeout = ntohs(psfLocalSet->u16ARQRxPurgeTimeOut); - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqRxPurgeTimeout = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqRxPurgeTimeout); - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqBlockSize = ntohs(psfLocalSet->u16ARQBlockSize); - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqBlockSize = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqBlockSize); - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsReqTxPolicy = psfLocalSet->u8RequesttransmissionPolicy; - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsReqTxPolicy = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsReqTxPolicy); - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnSfCsSpecification = psfLocalSet->u8CSSpecification; - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnSfCsSpecification = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnSfCsSpecification); - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsTargetSaid = ntohs(psfLocalSet->u16TargetSAID); - Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsTargetSaid = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsTargetSaid); + S_MIBS_EXTSERVICEFLOW_PARAMETERS *t = &Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable; + + t->wmanIfSfid = psfLocalSet->u32SFID; + t->wmanIfCmnCpsMaxSustainedRate = psfLocalSet->u32MaxSustainedTrafficRate; + t->wmanIfCmnCpsMaxTrafficBurst = psfLocalSet->u32MaxTrafficBurst; + t->wmanIfCmnCpsMinReservedRate = psfLocalSet->u32MinReservedTrafficRate; + t->wmanIfCmnCpsToleratedJitter = psfLocalSet->u32ToleratedJitter; + t->wmanIfCmnCpsMaxLatency = psfLocalSet->u32MaximumLatency; + t->wmanIfCmnCpsFixedVsVariableSduInd = psfLocalSet->u8FixedLengthVSVariableLengthSDUIndicator; + t->wmanIfCmnCpsFixedVsVariableSduInd = ntohl(t->wmanIfCmnCpsFixedVsVariableSduInd); + t->wmanIfCmnCpsSduSize = psfLocalSet->u8SDUSize; + t->wmanIfCmnCpsSduSize = ntohl(t->wmanIfCmnCpsSduSize); + t->wmanIfCmnCpsSfSchedulingType = psfLocalSet->u8ServiceFlowSchedulingType; + t->wmanIfCmnCpsSfSchedulingType = ntohl(t->wmanIfCmnCpsSfSchedulingType); + t->wmanIfCmnCpsArqEnable = psfLocalSet->u8ARQEnable; + t->wmanIfCmnCpsArqEnable = ntohl(t->wmanIfCmnCpsArqEnable); + t->wmanIfCmnCpsArqWindowSize = ntohs(psfLocalSet->u16ARQWindowSize); + t->wmanIfCmnCpsArqWindowSize = ntohl(t->wmanIfCmnCpsArqWindowSize); + t->wmanIfCmnCpsArqBlockLifetime = ntohs(psfLocalSet->u16ARQBlockLifeTime); + t->wmanIfCmnCpsArqBlockLifetime = ntohl(t->wmanIfCmnCpsArqBlockLifetime); + t->wmanIfCmnCpsArqSyncLossTimeout = ntohs(psfLocalSet->u16ARQSyncLossTimeOut); + t->wmanIfCmnCpsArqSyncLossTimeout = ntohl(t->wmanIfCmnCpsArqSyncLossTimeout); + t->wmanIfCmnCpsArqDeliverInOrder = psfLocalSet->u8ARQDeliverInOrder; + t->wmanIfCmnCpsArqDeliverInOrder = ntohl(t->wmanIfCmnCpsArqDeliverInOrder); + t->wmanIfCmnCpsArqRxPurgeTimeout = ntohs(psfLocalSet->u16ARQRxPurgeTimeOut); + t->wmanIfCmnCpsArqRxPurgeTimeout = ntohl(t->wmanIfCmnCpsArqRxPurgeTimeout); + t->wmanIfCmnCpsArqBlockSize = ntohs(psfLocalSet->u16ARQBlockSize); + t->wmanIfCmnCpsArqBlockSize = ntohl(t->wmanIfCmnCpsArqBlockSize); + t->wmanIfCmnCpsReqTxPolicy = psfLocalSet->u8RequesttransmissionPolicy; + t->wmanIfCmnCpsReqTxPolicy = ntohl(t->wmanIfCmnCpsReqTxPolicy); + t->wmanIfCmnSfCsSpecification = psfLocalSet->u8CSSpecification; + t->wmanIfCmnSfCsSpecification = ntohl(t->wmanIfCmnSfCsSpecification); + t->wmanIfCmnCpsTargetSaid = ntohs(psfLocalSet->u16TargetSAID); + t->wmanIfCmnCpsTargetSaid = ntohl(t->wmanIfCmnCpsTargetSaid); } From 41c7b7c0fa2f68afb1154e88597ff6b9b97334cf Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Sun, 6 Nov 2011 09:40:11 -0500 Subject: [PATCH 075/365] Staging: bcm: Fix information leak in ioctl: IOCTL_BCM_REGISTER_READ_PRIVATE, IOCTL_BCM_EEPROM_REGISTER_READ This patch fixes an information leak in ioctl IOCTL_BCM_REGISTER_READ_PRIVATE and IOCTL_BCM_EEPROM_REGISTER_READ when determining the number of bytes to copy to user space. Function, usb_control_msg, returns the correct number of bytes from the hardware. Instead of using this value, we were using a value derived from user space. In this case, this value could be more than the hardware allocated. Therefore, this patch copies the proper number of bytes from the hardware, and uses this value as the maximum number of bytes for user space. Signed-off-by: Kevin McKinney Reviewed-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Bcmchar.c | 49 +++++++++---- drivers/staging/bcm/InterfaceDld.c | 12 ++-- drivers/staging/bcm/InterfaceIdleMode.c | 33 +++++---- drivers/staging/bcm/InterfaceInit.c | 12 ++-- drivers/staging/bcm/InterfaceMisc.c | 24 +++---- drivers/staging/bcm/Misc.c | 32 ++++++--- drivers/staging/bcm/nvm.c | 95 ++++++++++++++----------- 7 files changed, 153 insertions(+), 104 deletions(-) diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c index 2fa658eb74dc..e110d0e68872 100644 --- a/drivers/staging/bcm/Bcmchar.c +++ b/drivers/staging/bcm/Bcmchar.c @@ -161,6 +161,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) INT Status = STATUS_FAILURE; int timeout = 0; IOCTL_BUFFER IoBuffer; + int bytes; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Parameters Passed to control IOCTL cmd=0x%X arg=0x%lX", cmd, arg); @@ -230,11 +231,14 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) if (!temp_buff) return -ENOMEM; - Status = rdmalt(Adapter, (UINT)sRdmBuffer.Register, + bytes = rdmalt(Adapter, (UINT)sRdmBuffer.Register, (PUINT)temp_buff, Bufflen); - if (Status == STATUS_SUCCESS) { - if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, IoBuffer.OutputLength)) + if (bytes > 0) { + Status = STATUS_SUCCESS; + if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, bytes)) Status = -EFAULT; + } else { + Status = bytes; } kfree(temp_buff); @@ -318,11 +322,15 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) } uiTempVar = sRdmBuffer.Register & EEPROM_REJECT_MASK; - Status = rdmaltWithLock(Adapter, (UINT)sRdmBuffer.Register, (PUINT)temp_buff, IoBuffer.OutputLength); + bytes = rdmaltWithLock(Adapter, (UINT)sRdmBuffer.Register, (PUINT)temp_buff, IoBuffer.OutputLength); - if (Status == STATUS_SUCCESS) - if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, IoBuffer.OutputLength)) + if (bytes > 0) { + Status = STATUS_SUCCESS; + if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, bytes)) Status = -EFAULT; + } else { + Status = bytes; + } kfree(temp_buff); break; @@ -437,12 +445,14 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) } } - Status = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(UINT)); - - if (STATUS_SUCCESS != Status) { + bytes = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(UINT)); + if (bytes < 0) { + Status = bytes; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "GPIO_MODE_REGISTER read failed"); break; + } else { + Status = STATUS_SUCCESS; } /* Set the gpio mode register to output */ @@ -519,12 +529,15 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) uiBit = gpio_info.uiGpioNumber; /* Set the gpio output register */ - Status = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER, + bytes = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER, (PUINT)ucRead, sizeof(UINT)); - if (Status != STATUS_SUCCESS) { + if (bytes < 0) { + Status = bytes; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "RDM Failed\n"); return Status; + } else { + Status = STATUS_SUCCESS; } } break; @@ -590,11 +603,14 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) } if (pgpio_multi_info[WIMAX_IDX].uiGPIOMask) { - Status = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER, (PUINT)ucResetValue, sizeof(UINT)); + bytes = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER, (PUINT)ucResetValue, sizeof(UINT)); - if (Status != STATUS_SUCCESS) { + if (bytes < 0) { + Status = bytes; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "RDM to GPIO_PIN_STATE_REGISTER Failed."); return Status; + } else { + Status = STATUS_SUCCESS; } pgpio_multi_info[WIMAX_IDX].uiGPIOValue = (*(UINT *)ucResetValue & @@ -629,11 +645,14 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) if (copy_from_user(&gpio_multi_mode, IoBuffer.InputBuffer, IoBuffer.InputLength)) return -EFAULT; - Status = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(UINT)); + bytes = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(UINT)); - if (STATUS_SUCCESS != Status) { + if (bytes < 0) { + Status = bytes; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read of GPIO_MODE_REGISTER failed"); return Status; + } else { + Status = STATUS_SUCCESS; } /* Validating the request */ diff --git a/drivers/staging/bcm/InterfaceDld.c b/drivers/staging/bcm/InterfaceDld.c index bcd86bbef2fd..65c352f35681 100644 --- a/drivers/staging/bcm/InterfaceDld.c +++ b/drivers/staging/bcm/InterfaceDld.c @@ -62,6 +62,7 @@ int InterfaceFileReadbackFromChip(PVOID arg, struct file *flp, unsigned int on_c static int fw_down; INT Status = STATUS_SUCCESS; PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)arg; + int bytes; buff = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_DMA); buff_readback = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB , GFP_DMA); @@ -94,8 +95,9 @@ int InterfaceFileReadbackFromChip(PVOID arg, struct file *flp, unsigned int on_c break; } - Status = InterfaceRDM(psIntfAdapter, on_chip_loc, buff_readback, len); - if (Status) { + bytes = InterfaceRDM(psIntfAdapter, on_chip_loc, buff_readback, len); + if (bytes < 0) { + Status = bytes; BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "RDM of len %d Failed! %d", len, reg); goto exit; } @@ -302,6 +304,7 @@ static INT buffRdbkVerify(PMINI_ADAPTER Adapter, PUCHAR mappedbuffer, UINT u32Fi UINT len = u32FirmwareLength; INT retval = STATUS_SUCCESS; PUCHAR readbackbuff = kzalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL); + int bytes; if (NULL == readbackbuff) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "MEMORY ALLOCATION FAILED"); @@ -310,9 +313,10 @@ static INT buffRdbkVerify(PMINI_ADAPTER Adapter, PUCHAR mappedbuffer, UINT u32Fi while (u32FirmwareLength && !retval) { len = MIN_VAL(u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB); - retval = rdm(Adapter, u32StartingAddress, readbackbuff, len); + bytes = rdm(Adapter, u32StartingAddress, readbackbuff, len); - if (retval) { + if (bytes < 0) { + retval = bytes; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "rdm failed with status %d", retval); break; } diff --git a/drivers/staging/bcm/InterfaceIdleMode.c b/drivers/staging/bcm/InterfaceIdleMode.c index 96fa4ead7930..faeb03e62c06 100644 --- a/drivers/staging/bcm/InterfaceIdleMode.c +++ b/drivers/staging/bcm/InterfaceIdleMode.c @@ -46,6 +46,7 @@ int InterfaceIdleModeRespond(PMINI_ADAPTER Adapter, unsigned int* puiBuffer) { int status = STATUS_SUCCESS; unsigned int uiRegRead = 0; + int bytes; BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"SubType of Message :0x%X", ntohl(*puiBuffer)); @@ -77,16 +78,16 @@ int InterfaceIdleModeRespond(PMINI_ADAPTER Adapter, unsigned int* puiBuffer) else if(Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE) { //clear on read Register - status = rdmalt(Adapter, DEVICE_INT_OUT_EP_REG0, &uiRegRead, sizeof(uiRegRead)); - if(status) - { + bytes = rdmalt(Adapter, DEVICE_INT_OUT_EP_REG0, &uiRegRead, sizeof(uiRegRead)); + if (bytes < 0) { + status = bytes; BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "rdm failed while clearing H/W Abort Reg0"); return status; } //clear on read Register - status = rdmalt (Adapter, DEVICE_INT_OUT_EP_REG1, &uiRegRead, sizeof(uiRegRead)); - if(status) - { + bytes = rdmalt(Adapter, DEVICE_INT_OUT_EP_REG1, &uiRegRead, sizeof(uiRegRead)); + if (bytes < 0) { + status = bytes; BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "rdm failed while clearing H/W Abort Reg1"); return status; } @@ -117,9 +118,9 @@ int InterfaceIdleModeRespond(PMINI_ADAPTER Adapter, unsigned int* puiBuffer) Adapter->chip_id== BCS220_3) { - status = rdmalt(Adapter, HPM_CONFIG_MSW, &uiRegRead, sizeof(uiRegRead)); - if(status) - { + bytes = rdmalt(Adapter, HPM_CONFIG_MSW, &uiRegRead, sizeof(uiRegRead)); + if (bytes < 0) { + status = bytes; BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "rdm failed while Reading HPM_CONFIG_LDO145 Reg 0\n"); return status; } @@ -266,6 +267,8 @@ void InterfaceHandleShutdownModeWakeup(PMINI_ADAPTER Adapter) { unsigned int uiRegVal = 0; INT Status = 0; + int bytes; + if(Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING) { // clear idlemode interrupt. @@ -282,16 +285,16 @@ void InterfaceHandleShutdownModeWakeup(PMINI_ADAPTER Adapter) { //clear Interrupt EP registers. - Status = rdmalt(Adapter,DEVICE_INT_OUT_EP_REG0, &uiRegVal, sizeof(uiRegVal)); - if(Status) - { + bytes = rdmalt(Adapter,DEVICE_INT_OUT_EP_REG0, &uiRegVal, sizeof(uiRegVal)); + if (bytes < 0) { + Status = bytes; BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"RDM of DEVICE_INT_OUT_EP_REG0 failed with Err :%d", Status); return; } - Status = rdmalt(Adapter,DEVICE_INT_OUT_EP_REG1, &uiRegVal, sizeof(uiRegVal)); - if(Status) - { + bytes = rdmalt(Adapter,DEVICE_INT_OUT_EP_REG1, &uiRegVal, sizeof(uiRegVal)); + if (bytes < 0) { + Status = bytes; BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"RDM of DEVICE_INT_OUT_EP_REG1 failed with Err :%d", Status); return; } diff --git a/drivers/staging/bcm/InterfaceInit.c b/drivers/staging/bcm/InterfaceInit.c index a09d35108f04..8e3c586a699c 100644 --- a/drivers/staging/bcm/InterfaceInit.c +++ b/drivers/staging/bcm/InterfaceInit.c @@ -68,7 +68,7 @@ static void InterfaceAdapterFree(PS_INTERFACE_ADAPTER psIntfAdapter) static void ConfigureEndPointTypesThroughEEPROM(PMINI_ADAPTER Adapter) { unsigned long ulReg = 0; - int ret; + int bytes; /* Program EP2 MAX_PKT_SIZE */ ulReg = ntohl(EP2_MPS_REG); @@ -94,8 +94,8 @@ static void ConfigureEndPointTypesThroughEEPROM(PMINI_ADAPTER Adapter) BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&ulReg, 0x140, 4, TRUE); /* Program TX EP as interrupt(Alternate Setting) */ - ret = rdmalt(Adapter, 0x0F0110F8, (u32 *)&ulReg, sizeof(u32)); - if (ret) { + bytes = rdmalt(Adapter, 0x0F0110F8, (u32 *)&ulReg, sizeof(u32)); + if (bytes < 0) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "reading of Tx EP failed\n"); return; @@ -430,6 +430,7 @@ static int InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter) int usedIntOutForBulkTransfer = 0 ; BOOLEAN bBcm16 = FALSE; UINT uiData = 0; + int bytes; /* Store the usb dev into interface adapter */ psIntfAdapter->udev = usb_get_dev(interface_to_usbdev(psIntfAdapter->interface)); @@ -438,9 +439,10 @@ static int InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter) psIntfAdapter->psAdapter->interface_rdm = BcmRDM; psIntfAdapter->psAdapter->interface_wrm = BcmWRM; - retval = rdmalt(psIntfAdapter->psAdapter, CHIP_ID_REG, + bytes = rdmalt(psIntfAdapter->psAdapter, CHIP_ID_REG, (u32 *)&(psIntfAdapter->psAdapter->chip_id), sizeof(u32)); - if (retval) { + if (bytes < 0) { + retval = bytes; BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "CHIP ID Read Failed\n"); return retval; } diff --git a/drivers/staging/bcm/InterfaceMisc.c b/drivers/staging/bcm/InterfaceMisc.c index 61f878b4f56c..2218faeaf8ac 100644 --- a/drivers/staging/bcm/InterfaceMisc.c +++ b/drivers/staging/bcm/InterfaceMisc.c @@ -5,7 +5,7 @@ INT InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter, PVOID buff, INT len) { - int retval = 0; + int bytes; USHORT usRetries = 0; if (psIntfAdapter == NULL) { @@ -30,7 +30,7 @@ INT InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter, psIntfAdapter->psAdapter->DeviceAccess = TRUE; do { - retval = usb_control_msg(psIntfAdapter->udev, + bytes = usb_control_msg(psIntfAdapter->udev, usb_rcvctrlpipe(psIntfAdapter->udev, 0), 0x02, 0xC2, @@ -41,22 +41,20 @@ INT InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter, 5000); usRetries++; - if (-ENODEV == retval) { + if (-ENODEV == bytes) { psIntfAdapter->psAdapter->device_removed = TRUE; break; } - } while ((retval < 0) && (usRetries < MAX_RDM_WRM_RETIRES)); + } while ((bytes < 0) && (usRetries < MAX_RDM_WRM_RETIRES)); - if (retval < 0) { - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM failed status :%d, retires :%d", retval, usRetries); - psIntfAdapter->psAdapter->DeviceAccess = FALSE; - return retval; - } else { - BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM sent %d", retval); - psIntfAdapter->psAdapter->DeviceAccess = FALSE; - return STATUS_SUCCESS; - } + if (bytes < 0) + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM failed status :%d, retires :%d", bytes, usRetries); + else + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM sent %d", bytes); + + psIntfAdapter->psAdapter->DeviceAccess = FALSE; + return bytes; } INT InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter, diff --git a/drivers/staging/bcm/Misc.c b/drivers/staging/bcm/Misc.c index e9f29d597518..c7725e141fd5 100644 --- a/drivers/staging/bcm/Misc.c +++ b/drivers/staging/bcm/Misc.c @@ -814,6 +814,7 @@ int reset_card_proc(PMINI_ADAPTER ps_adapter) PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); PS_INTERFACE_ADAPTER psIntfAdapter = NULL; unsigned int value = 0, uiResetValue = 0; + int bytes; psIntfAdapter = ((PS_INTERFACE_ADAPTER)(ps_adapter->pvInterfaceAdapter)); ps_adapter->bDDRInitDone = FALSE; @@ -848,8 +849,9 @@ int reset_card_proc(PMINI_ADAPTER ps_adapter) ps_adapter->chip_id == BCS250_BC || ps_adapter->chip_id == BCS220_3) { - retval = rdmalt(ps_adapter, HPM_CONFIG_LDO145, &value, sizeof(value)); - if (retval < 0) { + bytes = rdmalt(ps_adapter, HPM_CONFIG_LDO145, &value, sizeof(value)); + if (bytes < 0) { + retval = bytes; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "read failed with status :%d", retval); goto err_exit; } @@ -862,8 +864,9 @@ int reset_card_proc(PMINI_ADAPTER ps_adapter) } } } else { - retval = rdmalt(ps_adapter, 0x0f007018, &value, sizeof(value)); - if (retval < 0) { + bytes = rdmalt(ps_adapter, 0x0f007018, &value, sizeof(value)); + if (bytes < 0) { + retval = bytes; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "read failed with status :%d", retval); goto err_exit; } @@ -925,11 +928,16 @@ err_exit: int run_card_proc(PMINI_ADAPTER ps_adapter) { + int status = STATUS_SUCCESS; + int bytes; + unsigned int value = 0; { - if (rdmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &value, sizeof(value)) < 0) { + bytes = rdmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &value, sizeof(value)); + if (bytes < 0) { + status = bytes; BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "%s:%d\n", __func__, __LINE__); - return STATUS_FAILURE; + return status; } if (ps_adapter->bFlashBoot) @@ -942,7 +950,7 @@ int run_card_proc(PMINI_ADAPTER ps_adapter) return STATUS_FAILURE; } } - return STATUS_SUCCESS; + return status; } int InitCardAndDownloadFirmware(PMINI_ADAPTER ps_adapter) @@ -1215,6 +1223,7 @@ static unsigned char *ReadMacAddrEEPROM(PMINI_ADAPTER Adapter, ulong dwAddress) int status = 0, i = 0; unsigned int temp = 0; unsigned char *pucmacaddr = kmalloc(MAC_ADDRESS_SIZE, GFP_KERNEL); + int bytes; if (!pucmacaddr) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "No Buffers to Read the EEPROM Address\n"); @@ -1231,8 +1240,9 @@ static unsigned char *ReadMacAddrEEPROM(PMINI_ADAPTER Adapter, ulong dwAddress) } for (i = 0; i < MAC_ADDRESS_SIZE; i++) { - status = rdmalt(Adapter, EEPROM_READ_DATA_Q_REG, &temp, sizeof(temp)); - if (status != STATUS_SUCCESS) { + bytes = rdmalt(Adapter, EEPROM_READ_DATA_Q_REG, &temp, sizeof(temp)); + if (bytes < 0) { + status = bytes; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "rdm Failed..\n"); kfree(pucmacaddr); pucmacaddr = NULL; @@ -1574,11 +1584,13 @@ void update_per_sf_desc_cnts(PMINI_ADAPTER Adapter) { INT iIndex = 0; u32 uibuff[MAX_TARGET_DSX_BUFFERS]; + int bytes; if (!atomic_read(&Adapter->uiMBupdate)) return; - if (rdmaltWithLock(Adapter, TARGET_SFID_TXDESC_MAP_LOC, (PUINT)uibuff, sizeof(UINT) * MAX_TARGET_DSX_BUFFERS) < 0) { + bytes = rdmaltWithLock(Adapter, TARGET_SFID_TXDESC_MAP_LOC, (PUINT)uibuff, sizeof(UINT) * MAX_TARGET_DSX_BUFFERS); + if (bytes < 0) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "rdm failed\n"); return; } diff --git a/drivers/staging/bcm/nvm.c b/drivers/staging/bcm/nvm.c index 3de0daf5edb2..7d703cb3c5e0 100644 --- a/drivers/staging/bcm/nvm.c +++ b/drivers/staging/bcm/nvm.c @@ -78,7 +78,7 @@ static UCHAR ReadEEPROMStatusRegister( PMINI_ADAPTER Adapter ) { value=0; uiStatus = 0 ; - rdmalt( Adapter, EEPROM_SPI_Q_STATUS1_REG,&uiStatus, sizeof(uiStatus)); + rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus)); if(Adapter->device_removed == TRUE) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Modem has got removed hence exiting...."); @@ -93,7 +93,7 @@ static UCHAR ReadEEPROMStatusRegister( PMINI_ADAPTER Adapter ) wrmalt( Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); value =0; - rdmalt(Adapter, EEPROM_READ_DATAQ_REG,&value, sizeof(value)); + rdmalt(Adapter, EEPROM_READ_DATAQ_REG, &value, sizeof(value)); uiData = (UCHAR)value; break; @@ -102,8 +102,8 @@ static UCHAR ReadEEPROMStatusRegister( PMINI_ADAPTER Adapter ) dwRetries-- ; if ( dwRetries == 0 ) { - rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG,&value, sizeof(value)); - rdmalt(Adapter, EEPROM_SPI_Q_STATUS_REG,&value1, sizeof(value1)); + rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); + rdmalt(Adapter, EEPROM_SPI_Q_STATUS_REG, &value1, sizeof(value1)); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"0x3004 = %x 0x3008 = %x, retries = %d failed.\n",value,value1, MAX_EEPROM_RETRIES*RETRIES_PER_DELAY); return uiData; } @@ -158,7 +158,7 @@ INT ReadBeceemEEPROMBulk( PMINI_ADAPTER Adapter, { uiStatus = 0; - rdmalt( Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus)); + rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus)); if(Adapter->device_removed == TRUE) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Modem has got Removed.hence exiting from loop..."); @@ -202,8 +202,8 @@ INT ReadBeceemEEPROMBulk( PMINI_ADAPTER Adapter, { value=0; value1=0; - rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG,&value, sizeof(value)); - rdmalt(Adapter, EEPROM_SPI_Q_STATUS_REG,&value1, sizeof(value1)); + rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); + rdmalt(Adapter, EEPROM_SPI_Q_STATUS_REG, &value1, sizeof(value1)); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "dwNumWords %d 0x3004 = %x 0x3008 = %x retries = %d failed.\n", dwNumWords, value, value1, MAX_EEPROM_RETRIES*RETRIES_PER_DELAY); return STATUS_FAILURE; } @@ -217,22 +217,22 @@ INT ReadBeceemEEPROMBulk( PMINI_ADAPTER Adapter, pvalue = (PUCHAR)(pdwData + dwIndex); value =0; - rdmalt(Adapter, EEPROM_READ_DATAQ_REG,&value, sizeof(value)); + rdmalt(Adapter, EEPROM_READ_DATAQ_REG, &value, sizeof(value)); pvalue[0] = value; value = 0; - rdmalt(Adapter, EEPROM_READ_DATAQ_REG,&value, sizeof(value)); + rdmalt(Adapter, EEPROM_READ_DATAQ_REG, &value, sizeof(value)); pvalue[1] = value; value =0; - rdmalt(Adapter, EEPROM_READ_DATAQ_REG,&value, sizeof(value)); + rdmalt(Adapter, EEPROM_READ_DATAQ_REG, &value, sizeof(value)); pvalue[2] = value; value = 0; - rdmalt(Adapter, EEPROM_READ_DATAQ_REG,&value, sizeof(value)); + rdmalt(Adapter, EEPROM_READ_DATAQ_REG, &value, sizeof(value)); pvalue[3] = value; } @@ -445,6 +445,7 @@ static INT BeceemFlashBulkRead( UINT uiBytesToRead = uiNumBytes; INT Status = 0; UINT uiPartOffset = 0; + int bytes; if(Adapter->device_removed ) { @@ -469,9 +470,9 @@ static INT BeceemFlashBulkRead( uiBytesToRead = MAX_RW_SIZE - (uiOffset%MAX_RW_SIZE); uiBytesToRead = MIN(uiNumBytes,uiBytesToRead); - if(rdm(Adapter,uiPartOffset, (PCHAR)pBuffer+uiIndex,uiBytesToRead)) - { - Status = -1; + bytes = rdm(Adapter, uiPartOffset, (PCHAR)pBuffer+uiIndex, uiBytesToRead); + if (bytes < 0) { + Status = bytes; Adapter->SelectedChip = RESET_CHIP_SELECT; return Status; } @@ -488,9 +489,9 @@ static INT BeceemFlashBulkRead( uiBytesToRead = MIN(uiNumBytes,MAX_RW_SIZE); - if(rdm(Adapter,uiPartOffset, (PCHAR)pBuffer+uiIndex,uiBytesToRead)) - { - Status = -1; + bytes = rdm(Adapter, uiPartOffset, (PCHAR)pBuffer+uiIndex, uiBytesToRead); + if (bytes < 0) { + Status = bytes; break; } @@ -613,6 +614,7 @@ static INT FlashSectorErase(PMINI_ADAPTER Adapter, UINT iIndex = 0, iRetries = 0; UINT uiStatus = 0; UINT value; + int bytes; for(iIndex=0;iIndexdevice_removed == TRUE) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Modem got removed hence exiting from loop...."); @@ -2500,7 +2511,7 @@ static ULONG BcmReadFlashRDID(PMINI_ADAPTER Adapter) // Read SPI READQ REG. The output will be WWXXYYZZ. // The ID is 3Bytes long and is WWXXYY. ZZ needs to be Ignored. // - rdmalt(Adapter, FLASH_SPI_READQ_REG,(PUINT)&ulRDID, sizeof(ulRDID)); + rdmalt(Adapter, FLASH_SPI_READQ_REG, (PUINT)&ulRDID, sizeof(ulRDID)); return (ulRDID >>8); @@ -4735,8 +4746,8 @@ static INT BcmDoChipSelect(PMINI_ADAPTER Adapter, UINT offset) Adapter->SelectedChip = ChipNum ; //bit[13..12] will select the appropriate chip - rdmalt(Adapter,FLASH_CONFIG_REG, &FlashConfig, 4); - rdmalt(Adapter,FLASH_GPIO_CONFIG_REG, &GPIOConfig, 4); + rdmalt(Adapter, FLASH_CONFIG_REG, &FlashConfig, 4); + rdmalt(Adapter, FLASH_GPIO_CONFIG_REG, &GPIOConfig, 4); { switch(ChipNum) From 51935d2259a476162bbf5c35ff81f3a01057ed6f Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Tue, 8 Nov 2011 22:33:35 -0500 Subject: [PATCH 076/365] Staging: bcm: Clean up code in ioctl: IOCTL_BCM_EEPROM_REGISTER_READ This patch verifies two conditions before executing a kmalloc call. First, it checks to see that IoBuffer.OutputLength is not greater than an unsigned short. If so, an invalid value may be returned. The second change is a check to make sure IoBuffer.OutputLength is not equal to zero. Which simply keeps this code inline with the other ioctl, IOCTL_BCM_REGISTER_READ_PRIVATE. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Bcmchar.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c index e110d0e68872..7cffbddd5e9c 100644 --- a/drivers/staging/bcm/Bcmchar.c +++ b/drivers/staging/bcm/Bcmchar.c @@ -306,7 +306,11 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) if (copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) return -EFAULT; - /* FIXME: don't trust user supplied length */ + if (IoBuffer.OutputLength > USHRT_MAX || + IoBuffer.OutputLength == 0) { + return -EINVAL; + } + temp_buff = kmalloc(IoBuffer.OutputLength, GFP_KERNEL); if (!temp_buff) return STATUS_FAILURE; From 77121d52a4de5e06c0b37d7e2fb9f6060904ecca Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Tue, 22 Nov 2011 20:25:55 -0500 Subject: [PATCH 077/365] Staging: bcm: Remove unnecessary "do while" statement in, IOCTL_BCM_BUFFER_DOWNLOAD This patch removes a superfluous "do while" statement in IOCTL_BCM_BUFFER_DOWNLOAD. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Bcmchar.c | 95 +++++++++++++++++------------------ 1 file changed, 46 insertions(+), 49 deletions(-) diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c index 7cffbddd5e9c..1bf28c95ef85 100644 --- a/drivers/staging/bcm/Bcmchar.c +++ b/drivers/staging/bcm/Bcmchar.c @@ -792,59 +792,56 @@ cntrlEnd: case IOCTL_BCM_BUFFER_DOWNLOAD: { FIRMWARE_INFO *psFwInfo = NULL; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Starting the firmware download PID =0x%x!!!!\n", current->pid); - do { - if (!down_trylock(&Adapter->fw_download_sema)) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, - "Invalid way to download buffer. Use Start and then call this!!!\n"); - Status = -EINVAL; - break; - } - - /* Copy Ioctl Buffer structure */ - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) - return -EFAULT; + if (!down_trylock(&Adapter->fw_download_sema)) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, - "Length for FW DLD is : %lx\n", IoBuffer.InputLength); - - if (IoBuffer.InputLength > sizeof(FIRMWARE_INFO)) - return -EINVAL; - - psFwInfo = kmalloc(sizeof(*psFwInfo), GFP_KERNEL); - if (!psFwInfo) - return -ENOMEM; - - if (copy_from_user(psFwInfo, IoBuffer.InputBuffer, IoBuffer.InputLength)) - return -EFAULT; - - if (!psFwInfo->pvMappedFirmwareAddress || - (psFwInfo->u32FirmwareLength == 0)) { - - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Something else is wrong %lu\n", - psFwInfo->u32FirmwareLength); - Status = -EINVAL; - break; - } - - Status = bcm_ioctl_fw_download(Adapter, psFwInfo); - - if (Status != STATUS_SUCCESS) { - if (psFwInfo->u32StartingAddress == CONFIG_BEGIN_ADDR) - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL: Configuration File Upload Failed\n"); - else - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL: Firmware File Upload Failed\n"); - - /* up(&Adapter->fw_download_sema); */ - - if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) { - Adapter->DriverState = DRIVER_INIT; - Adapter->LEDInfo.bLedInitDone = FALSE; - wake_up(&Adapter->LEDInfo.notify_led_event); - } - } + "Invalid way to download buffer. Use Start and then call this!!!\n"); + Status = -EINVAL; break; + } - } while (0); + /* Copy Ioctl Buffer structure */ + if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + return -EFAULT; + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, + "Length for FW DLD is : %lx\n", IoBuffer.InputLength); + + if (IoBuffer.InputLength > sizeof(FIRMWARE_INFO)) + return -EINVAL; + + psFwInfo = kmalloc(sizeof(*psFwInfo), GFP_KERNEL); + if (!psFwInfo) + return -ENOMEM; + + if (copy_from_user(psFwInfo, IoBuffer.InputBuffer, IoBuffer.InputLength)) + return -EFAULT; + + if (!psFwInfo->pvMappedFirmwareAddress || + (psFwInfo->u32FirmwareLength == 0)) { + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Something else is wrong %lu\n", + psFwInfo->u32FirmwareLength); + Status = -EINVAL; + break; + } + + Status = bcm_ioctl_fw_download(Adapter, psFwInfo); + + if (Status != STATUS_SUCCESS) { + if (psFwInfo->u32StartingAddress == CONFIG_BEGIN_ADDR) + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL: Configuration File Upload Failed\n"); + else + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL: Firmware File Upload Failed\n"); + + /* up(&Adapter->fw_download_sema); */ + + if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) { + Adapter->DriverState = DRIVER_INIT; + Adapter->LEDInfo.bLedInitDone = FALSE; + wake_up(&Adapter->LEDInfo.notify_led_event); + } + } if (Status != STATUS_SUCCESS) up(&Adapter->fw_download_sema); From abe33fc0933f9221193fc047fbf93cf9db23c8f6 Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Tue, 22 Nov 2011 20:25:56 -0500 Subject: [PATCH 078/365] Staging: bcm: Fix semaphore locking bug in, IOCTL_BCM_BUFFER_DOWNLOAD In this ioctl, we are testing to see if the lock is held. If it is not held, that means this ioctl used incorrectly. Therefore, we do not want to take the lock ourselves here. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Bcmchar.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c index 1bf28c95ef85..5a3e7c846a3e 100644 --- a/drivers/staging/bcm/Bcmchar.c +++ b/drivers/staging/bcm/Bcmchar.c @@ -796,6 +796,7 @@ cntrlEnd: if (!down_trylock(&Adapter->fw_download_sema)) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Invalid way to download buffer. Use Start and then call this!!!\n"); + up(&Adapter->fw_download_sema); Status = -EINVAL; break; } From d9f26a6689a3e4ae643fca9c2acda3148b717e63 Mon Sep 17 00:00:00 2001 From: Kevin McKinney Date: Tue, 22 Nov 2011 20:25:57 -0500 Subject: [PATCH 079/365] Staging: bcm: Fix semaphore locking error when downloading firmware. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch releases semaphore locks when an error occurrs while attempting to download firmware for the bcm driver. When downloading firmware for this driver, a process is expected to call the following ioctl's in this order: (1)IOCTL_BCM_BUFFER_DOWNLOAD_START, (2)IOCTL_BCM_BUFFER_DOWNLOAD, and (3) IOCTL_BCM_BUFFER_DOWNLOAD_STOP. Semaphore, “Adapter->fw_download_sema” is expected to be acquired in the first ioctl, IOCTL_BCM_BUFFER_DOWNLOAD_START, and it should block until IOCTL_BCM_BUFFER_DOWNLOAD_STOP is called. In this case, if an error occurred before STOP finished, the semaphore "Adapter->fw_download_sema" was not being released. Signed-off-by: Kevin McKinney Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Bcmchar.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c index 5a3e7c846a3e..d0a0b10c5d4e 100644 --- a/drivers/staging/bcm/Bcmchar.c +++ b/drivers/staging/bcm/Bcmchar.c @@ -802,27 +802,36 @@ cntrlEnd: } /* Copy Ioctl Buffer structure */ - if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) + if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) { + up(&Adapter->fw_download_sema); return -EFAULT; + } BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Length for FW DLD is : %lx\n", IoBuffer.InputLength); - if (IoBuffer.InputLength > sizeof(FIRMWARE_INFO)) + if (IoBuffer.InputLength > sizeof(FIRMWARE_INFO)) { + up(&Adapter->fw_download_sema); return -EINVAL; + } psFwInfo = kmalloc(sizeof(*psFwInfo), GFP_KERNEL); - if (!psFwInfo) + if (!psFwInfo) { + up(&Adapter->fw_download_sema); return -ENOMEM; + } - if (copy_from_user(psFwInfo, IoBuffer.InputBuffer, IoBuffer.InputLength)) + if (copy_from_user(psFwInfo, IoBuffer.InputBuffer, IoBuffer.InputLength)) { + up(&Adapter->fw_download_sema); return -EFAULT; + } if (!psFwInfo->pvMappedFirmwareAddress || (psFwInfo->u32FirmwareLength == 0)) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Something else is wrong %lu\n", psFwInfo->u32FirmwareLength); + up(&Adapter->fw_download_sema); Status = -EINVAL; break; } From 7990b0d7ec449b10da383bab191eb487185aadce Mon Sep 17 00:00:00 2001 From: Marc Dietrich Date: Tue, 1 Nov 2011 21:37:04 +0100 Subject: [PATCH 080/365] staging: nvec: add device tree support This adds device tree support to the nvec driver. By using this method it is no longer necessary to specify platform data through a board file. Signed-off-by: Marc Dietrich Acked-by: Stephen Warren Cc: Julian Andres Klode Cc: Grant Likely Acked-by: Olof Johansson Signed-off-by: Greg Kroah-Hartman --- .../devicetree/bindings/nvec/nvec_nvidia.txt | 9 ++++++ drivers/staging/nvec/nvec.c | 30 +++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 Documentation/devicetree/bindings/nvec/nvec_nvidia.txt diff --git a/Documentation/devicetree/bindings/nvec/nvec_nvidia.txt b/Documentation/devicetree/bindings/nvec/nvec_nvidia.txt new file mode 100644 index 000000000000..5aeee53ff9f4 --- /dev/null +++ b/Documentation/devicetree/bindings/nvec/nvec_nvidia.txt @@ -0,0 +1,9 @@ +NVIDIA compliant embedded controller + +Required properties: +- compatible : should be "nvidia,nvec". +- reg : the iomem of the i2c slave controller +- interrupts : the interrupt line of the i2c slave controller +- clock-frequency : the frequency of the i2c bus +- gpios : the gpio used for ec request +- slave-addr: the i2c address of the slave controller diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c index e06b867d1e0c..fafdfa25e139 100644 --- a/drivers/staging/nvec/nvec.c +++ b/drivers/staging/nvec/nvec.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include #include @@ -727,8 +729,24 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, nvec); nvec->dev = &pdev->dev; - nvec->gpio = pdata->gpio; - nvec->i2c_addr = pdata->i2c_addr; + + if (pdata) { + nvec->gpio = pdata->gpio; + nvec->i2c_addr = pdata->i2c_addr; + } else if (nvec->dev->of_node) { + nvec->gpio = of_get_named_gpio(nvec->dev->of_node, "request-gpios", 0); + if (nvec->gpio < 0) { + dev_err(&pdev->dev, "no gpio specified"); + goto failed; + } + if (of_property_read_u32(nvec->dev->of_node, "slave-addr", &nvec->i2c_addr)) { + dev_err(&pdev->dev, "no i2c address specified"); + goto failed; + } + } else { + dev_err(&pdev->dev, "no platform data\n"); + goto failed; + } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { @@ -893,6 +911,13 @@ static int tegra_nvec_resume(struct platform_device *pdev) #define tegra_nvec_resume NULL #endif +/* Match table for of_platform binding */ +static const struct of_device_id nvidia_nvec_of_match[] __devinitconst = { + { .compatible = "nvidia,nvec", }, + {}, +}; +MODULE_DEVICE_TABLE(of, nvidia_nvec_of_match); + static struct platform_driver nvec_device_driver = { .probe = tegra_nvec_probe, .remove = __devexit_p(tegra_nvec_remove), @@ -901,6 +926,7 @@ static struct platform_driver nvec_device_driver = { .driver = { .name = "nvec", .owner = THIS_MODULE, + .of_match_table = nvidia_nvec_of_match, } }; From 7c19c1e80d348a5c79b65f9fc3d54bbbeea9cd0f Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 29 Oct 2011 01:58:13 +0200 Subject: [PATCH 081/365] drivers/staging/rtl8712/rtl871x_mlme.c: eliminate a null pointer dereference If ibss_wlan is NULL, it is not correct to memcpy into its field. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @r@ expression E, E1; identifier f; statement S1,S2,S3; @@ if (E == NULL) { ... when != if (E == NULL || ...) S1 else S2 when != E = E1 *E->f ... when any return ...; } else S3 // Signed-off-by: Julia Lawall Signed-off-by: Larry Finger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_mlme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c index ef8eb6c7ee41..4277d0304b7a 100644 --- a/drivers/staging/rtl8712/rtl871x_mlme.c +++ b/drivers/staging/rtl8712/rtl871x_mlme.c @@ -551,7 +551,7 @@ void r8712_survey_event_callback(struct _adapter *adapter, u8 *pbuf) ibss_wlan = r8712_find_network( &pmlmepriv->scanned_queue, pnetwork->MacAddress); - if (!ibss_wlan) { + if (ibss_wlan) { memcpy(ibss_wlan->network.IEs, pnetwork->IEs, 8); goto exit; From 6f03053b6810c7ca315afb30b31b63d9f5863faf Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Mon, 7 Nov 2011 00:21:26 +0100 Subject: [PATCH 082/365] rtl8192e: Don't copy huge struct by value (and make it const). rtllib_is_shortslot() takes one argument - a struct that's more than a kilobyte large. It should take a pointer instead of copying such a huge struct - and the argument might as well be declared 'const' now that we are at it, since it is not modified. This patch makes these changes. Signed-off-by: Jesper Juhl Acked-by: Larry Finger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib.h | 2 +- drivers/staging/rtl8192e/rtllib_softmac.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h index de25975ccee4..3a5212065715 100644 --- a/drivers/staging/rtl8192e/rtllib.h +++ b/drivers/staging/rtl8192e/rtllib.h @@ -2804,7 +2804,7 @@ extern int rtllib_wx_set_gen_ie(struct rtllib_device *ieee, u8 *ie, size_t len); /* rtllib_softmac.c */ extern short rtllib_is_54g(struct rtllib_network *net); -extern short rtllib_is_shortslot(struct rtllib_network net); +extern short rtllib_is_shortslot(const struct rtllib_network *net); extern int rtllib_rx_frame_softmac(struct rtllib_device *ieee, struct sk_buff *skb, struct rtllib_rx_stats *rx_stats, u16 type, diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c index b5086850f0de..fa774cf7fc78 100644 --- a/drivers/staging/rtl8192e/rtllib_softmac.c +++ b/drivers/staging/rtl8192e/rtllib_softmac.c @@ -28,9 +28,9 @@ short rtllib_is_54g(struct rtllib_network *net) return (net->rates_ex_len > 0) || (net->rates_len > 4); } -short rtllib_is_shortslot(struct rtllib_network net) +short rtllib_is_shortslot(const struct rtllib_network *net) { - return net.capability & WLAN_CAPABILITY_SHORT_SLOT_TIME; + return net->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME; } /* returns the total length needed for pleacing the RATE MFIE From 44b6eb263783bee7f619d6c5ae48a4306756a797 Mon Sep 17 00:00:00 2001 From: Stefan Lippers-Hollmann Date: Tue, 15 Nov 2011 11:24:49 +0100 Subject: [PATCH 083/365] rtl8192e: remove stale defines from ccflags-y Code paths using these defines have been removed long time ago, now remove stale references from injected ccflags-y. Signed-off-by: Stefan Lippers-Hollmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/Makefile | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/staging/rtl8192e/Makefile b/drivers/staging/rtl8192e/Makefile index a66a9ad33686..80c2c8360b4f 100644 --- a/drivers/staging/rtl8192e/Makefile +++ b/drivers/staging/rtl8192e/Makefile @@ -1,8 +1,5 @@ -ccflags-y += -DUSE_FW_SOURCE_IMG_FILE ccflags-y += -DCONFIG_PM_RTL -ccflags-y += -DCONFIG_PM ccflags-y += -DHAVE_NET_DEVICE_OPS -ccflags-y += -DENABLE_DOT11D r8192e_pci-objs := \ rtl_core.o \ From 71769d737a2887aa9608e89deaca4185e44a0bca Mon Sep 17 00:00:00 2001 From: Stefan Lippers-Hollmann Date: Tue, 15 Nov 2011 11:26:10 +0100 Subject: [PATCH 084/365] rtl8192e: use HAVE_NET_DEVICE_OPS unconditionally Mainline provides NET_DEVICE_OPS, remove alternate code paths and now obsolete defines from ccflags-y. Signed-off-by: Stefan Lippers-Hollmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/Makefile | 1 - drivers/staging/rtl8192e/rtl_core.c | 12 ------------ 2 files changed, 13 deletions(-) diff --git a/drivers/staging/rtl8192e/Makefile b/drivers/staging/rtl8192e/Makefile index 80c2c8360b4f..299131c256e6 100644 --- a/drivers/staging/rtl8192e/Makefile +++ b/drivers/staging/rtl8192e/Makefile @@ -1,5 +1,4 @@ ccflags-y += -DCONFIG_PM_RTL -ccflags-y += -DHAVE_NET_DEVICE_OPS r8192e_pci-objs := \ rtl_core.o \ diff --git a/drivers/staging/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl_core.c index 5ad96649f407..4868091c3a42 100644 --- a/drivers/staging/rtl8192e/rtl_core.c +++ b/drivers/staging/rtl8192e/rtl_core.c @@ -2839,7 +2839,6 @@ done: /**************************************************************************** ---------------------------- PCI_STUFF--------------------------- *****************************************************************************/ -#ifdef HAVE_NET_DEVICE_OPS static const struct net_device_ops rtl8192_netdev_ops = { .ndo_open = rtl8192_open, .ndo_stop = rtl8192_close, @@ -2851,7 +2850,6 @@ static const struct net_device_ops rtl8192_netdev_ops = { .ndo_change_mtu = eth_change_mtu, .ndo_start_xmit = rtllib_xmit, }; -#endif static int __devinit rtl8192_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) @@ -2938,17 +2936,7 @@ static int __devinit rtl8192_pci_probe(struct pci_dev *pdev, dev->irq = pdev->irq; priv->irq = 0; -#ifdef HAVE_NET_DEVICE_OPS dev->netdev_ops = &rtl8192_netdev_ops; -#else - dev->open = rtl8192_open; - dev->stop = rtl8192_close; - dev->tx_timeout = rtl8192_tx_timeout; - dev->do_ioctl = rtl8192_ioctl; - dev->set_multicast_list = r8192_set_multicast; - dev->set_mac_address = r8192_set_mac_adr; - dev->hard_start_xmit = rtllib_xmit; -#endif dev->wireless_handlers = (struct iw_handler_def *) &r8192_wx_handlers_def; From 61fcc0166f8f004b36ac2ec239e43cfda7a62278 Mon Sep 17 00:00:00 2001 From: Stefan Lippers-Hollmann Date: Tue, 15 Nov 2011 11:27:30 +0100 Subject: [PATCH 085/365] rtl8192e: drop alternate code paths for CONFIG_PM_RTL It has always been enabled unconditionally by ccflags-y. Signed-off-by: Stefan Lippers-Hollmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/Makefile | 2 -- drivers/staging/rtl8192e/rtl_core.c | 2 -- drivers/staging/rtl8192e/rtl_pm.c | 2 -- drivers/staging/rtl8192e/rtl_pm.h | 4 ---- 4 files changed, 10 deletions(-) diff --git a/drivers/staging/rtl8192e/Makefile b/drivers/staging/rtl8192e/Makefile index 299131c256e6..04714c4b8700 100644 --- a/drivers/staging/rtl8192e/Makefile +++ b/drivers/staging/rtl8192e/Makefile @@ -1,5 +1,3 @@ -ccflags-y += -DCONFIG_PM_RTL - r8192e_pci-objs := \ rtl_core.o \ rtl_eeprom.o \ diff --git a/drivers/staging/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl_core.c index 4868091c3a42..b7c6d6b47173 100644 --- a/drivers/staging/rtl8192e/rtl_core.c +++ b/drivers/staging/rtl8192e/rtl_core.c @@ -53,9 +53,7 @@ #include "rtl_wx.h" #include "rtl_dm.h" -#ifdef CONFIG_PM_RTL #include "rtl_pm.h" -#endif int hwwep = 1; static int channels = 0x3fff; diff --git a/drivers/staging/rtl8192e/rtl_pm.c b/drivers/staging/rtl8192e/rtl_pm.c index 92e2fde7f5f4..8e1a5d55dce8 100644 --- a/drivers/staging/rtl8192e/rtl_pm.c +++ b/drivers/staging/rtl8192e/rtl_pm.c @@ -17,7 +17,6 @@ * wlanfae ******************************************************************************/ -#ifdef CONFIG_PM_RTL #include "rtl_core.h" #include "r8192E_hw.h" #include "r8190P_rtl8256.h" @@ -133,4 +132,3 @@ int rtl8192E_enable_wake(struct pci_dev *dev, pm_message_t state, int enable) return -EAGAIN; } -#endif diff --git a/drivers/staging/rtl8192e/rtl_pm.h b/drivers/staging/rtl8192e/rtl_pm.h index 4d7f4067cc78..e5299fc3b34a 100644 --- a/drivers/staging/rtl8192e/rtl_pm.h +++ b/drivers/staging/rtl8192e/rtl_pm.h @@ -17,8 +17,6 @@ * wlanfae ******************************************************************************/ -#ifdef CONFIG_PM_RTL - #ifndef R8192E_PM_H #define R8192E_PM_H @@ -31,5 +29,3 @@ int rtl8192E_resume(struct pci_dev *dev); int rtl8192E_enable_wake(struct pci_dev *dev, pm_message_t state, int enable); #endif - -#endif From 929fa2a42e75e0c6ded89c450bd0f668e32190d7 Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Thu, 10 Nov 2011 19:04:19 +0100 Subject: [PATCH 086/365] staging: rtl8192e: Use kzalloc rather than kmalloc v2 Use kzalloc rather than kmalloc followed by memset with 0 This considers some simple cases that are common and easy to validate Note in particular that there are no ...s in the rule, so all of the matched code has to be contiguous The semantic patch that makes this change is available in scripts/coccinelle/api/alloc/kzalloc-simple.cocci. Signed-off-by: Thomas Meyer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_crypt.c | 6 ++---- drivers/staging/rtl8192e/rtllib_crypt_ccmp.c | 3 +-- drivers/staging/rtl8192e/rtllib_crypt_tkip.c | 3 +-- drivers/staging/rtl8192e/rtllib_crypt_wep.c | 3 +-- drivers/staging/rtl8192e/rtllib_softmac.c | 3 +-- drivers/staging/rtl8192e/rtllib_wx.c | 3 +-- 6 files changed, 7 insertions(+), 14 deletions(-) diff --git a/drivers/staging/rtl8192e/rtllib_crypt.c b/drivers/staging/rtl8192e/rtllib_crypt.c index acda37b81848..a33bf024c37e 100644 --- a/drivers/staging/rtl8192e/rtllib_crypt.c +++ b/drivers/staging/rtl8192e/rtllib_crypt.c @@ -104,11 +104,10 @@ int rtllib_register_crypto_ops(struct rtllib_crypto_ops *ops) if (hcrypt == NULL) return -1; - alg = kmalloc(sizeof(*alg), GFP_KERNEL); + alg = kzalloc(sizeof(*alg), GFP_KERNEL); if (alg == NULL) return -ENOMEM; - memset(alg, 0, sizeof(*alg)); alg->ops = ops; spin_lock_irqsave(&hcrypt->lock, flags); @@ -202,11 +201,10 @@ int __init rtllib_crypto_init(void) { int ret = -ENOMEM; - hcrypt = kmalloc(sizeof(*hcrypt), GFP_KERNEL); + hcrypt = kzalloc(sizeof(*hcrypt), GFP_KERNEL); if (!hcrypt) goto out; - memset(hcrypt, 0, sizeof(*hcrypt)); INIT_LIST_HEAD(&hcrypt->algs); spin_lock_init(&hcrypt->lock); diff --git a/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c b/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c index 6196b9aa3a09..63b75045aa6b 100644 --- a/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c +++ b/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c @@ -63,10 +63,9 @@ static void *rtllib_ccmp_init(int key_idx) { struct rtllib_ccmp_data *priv; - priv = kmalloc(sizeof(*priv), GFP_ATOMIC); + priv = kzalloc(sizeof(*priv), GFP_ATOMIC); if (priv == NULL) goto fail; - memset(priv, 0, sizeof(*priv)); priv->key_idx = key_idx; priv->tfm = (void *)crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); diff --git a/drivers/staging/rtl8192e/rtllib_crypt_tkip.c b/drivers/staging/rtl8192e/rtllib_crypt_tkip.c index 6a0c87886422..70d5001e6460 100644 --- a/drivers/staging/rtl8192e/rtllib_crypt_tkip.c +++ b/drivers/staging/rtl8192e/rtllib_crypt_tkip.c @@ -60,10 +60,9 @@ static void *rtllib_tkip_init(int key_idx) { struct rtllib_tkip_data *priv; - priv = kmalloc(sizeof(*priv), GFP_ATOMIC); + priv = kzalloc(sizeof(*priv), GFP_ATOMIC); if (priv == NULL) goto fail; - memset(priv, 0, sizeof(*priv)); priv->key_idx = key_idx; priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); diff --git a/drivers/staging/rtl8192e/rtllib_crypt_wep.c b/drivers/staging/rtl8192e/rtllib_crypt_wep.c index c59bf10fe780..1f1ffb8ea197 100644 --- a/drivers/staging/rtl8192e/rtllib_crypt_wep.c +++ b/drivers/staging/rtl8192e/rtllib_crypt_wep.c @@ -38,10 +38,9 @@ static void *prism2_wep_init(int keyidx) { struct prism2_wep_data *priv; - priv = kmalloc(sizeof(*priv), GFP_ATOMIC); + priv = kzalloc(sizeof(*priv), GFP_ATOMIC); if (priv == NULL) goto fail; - memset(priv, 0, sizeof(*priv)); priv->key_idx = keyidx; priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c index fa774cf7fc78..30c3bca1c368 100644 --- a/drivers/staging/rtl8192e/rtllib_softmac.c +++ b/drivers/staging/rtl8192e/rtllib_softmac.c @@ -3048,10 +3048,9 @@ void rtllib_softmac_init(struct rtllib_device *ieee) ieee->state = RTLLIB_NOLINK; for (i = 0; i < 5; i++) ieee->seq_ctrl[i] = 0; - ieee->pDot11dInfo = kmalloc(sizeof(struct rt_dot11d_info), GFP_ATOMIC); + ieee->pDot11dInfo = kzalloc(sizeof(struct rt_dot11d_info), GFP_ATOMIC); if (!ieee->pDot11dInfo) RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't alloc memory for DOT11D\n"); - memset(ieee->pDot11dInfo, 0, sizeof(struct rt_dot11d_info)); ieee->LinkDetectInfo.SlotIndex = 0; ieee->LinkDetectInfo.SlotNum = 2; ieee->LinkDetectInfo.NumRecvBcnInPeriod = 0; diff --git a/drivers/staging/rtl8192e/rtllib_wx.c b/drivers/staging/rtl8192e/rtllib_wx.c index 8cea4a60e1b3..a8fd2e1f4ada 100644 --- a/drivers/staging/rtl8192e/rtllib_wx.c +++ b/drivers/staging/rtl8192e/rtllib_wx.c @@ -368,11 +368,10 @@ int rtllib_wx_set_encode(struct rtllib_device *ieee, struct rtllib_crypt_data *new_crypt; /* take WEP into use */ - new_crypt = kmalloc(sizeof(struct rtllib_crypt_data), + new_crypt = kzalloc(sizeof(struct rtllib_crypt_data), GFP_KERNEL); if (new_crypt == NULL) return -ENOMEM; - memset(new_crypt, 0, sizeof(struct rtllib_crypt_data)); new_crypt->ops = rtllib_get_crypto_ops("WEP"); if (!new_crypt->ops) { request_module("rtllib_crypt_wep"); From d9317533c54836887d64bba973ae5c9c341b36a0 Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Tue, 8 Nov 2011 20:37:03 +0100 Subject: [PATCH 087/365] staging: rtl8192e: Use kmemdup rather than duplicating its implementation Use kmemdup rather than duplicating its implementation The semantic patch that makes this change is available in scripts/coccinelle/api/memdup.cocci. More information about semantic patching is available at http://coccinelle.lip6.fr/ Signed-off-by: Thomas Meyer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_softmac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c index 30c3bca1c368..a326880888f7 100644 --- a/drivers/staging/rtl8192e/rtllib_softmac.c +++ b/drivers/staging/rtl8192e/rtllib_softmac.c @@ -3206,11 +3206,11 @@ static int rtllib_wpa_set_wpa_ie(struct rtllib_device *ieee, return -EINVAL; if (param->u.wpa_ie.len) { - buf = kmalloc(param->u.wpa_ie.len, GFP_KERNEL); + buf = kmemdup(param->u.wpa_ie.data, param->u.wpa_ie.len, + GFP_KERNEL); if (buf == NULL) return -ENOMEM; - memcpy(buf, param->u.wpa_ie.data, param->u.wpa_ie.len); kfree(ieee->wpa_ie); ieee->wpa_ie = buf; ieee->wpa_ie_len = param->u.wpa_ie.len; From 23226977e9421434a2e7e384219477199ca5f0ec Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Tue, 8 Nov 2011 20:30:20 +0100 Subject: [PATCH 088/365] staging: rtl8192e: Use kmemdup rather than duplicating its implementation Use kmemdup rather than duplicating its implementation The semantic patch that makes this change is available in scripts/coccinelle/api/memdup.cocci. More information about semantic patching is available at http://coccinelle.lip6.fr/ Signed-off-by: Thomas Meyer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_wx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/staging/rtl8192e/rtllib_wx.c b/drivers/staging/rtl8192e/rtllib_wx.c index a8fd2e1f4ada..b4f00e54bd02 100644 --- a/drivers/staging/rtl8192e/rtllib_wx.c +++ b/drivers/staging/rtl8192e/rtllib_wx.c @@ -845,10 +845,9 @@ int rtllib_wx_set_gen_ie(struct rtllib_device *ieee, u8 *ie, size_t len) ieee->wps_ie_len = (len < MAX_WZC_IE_LEN) ? (len) : (MAX_WZC_IE_LEN); - buf = kmalloc(ieee->wps_ie_len, GFP_KERNEL); + buf = kmemdup(ie, ieee->wps_ie_len, GFP_KERNEL); if (buf == NULL) return -ENOMEM; - memcpy(buf, ie, ieee->wps_ie_len); ieee->wps_ie = buf; return 0; } @@ -859,10 +858,9 @@ int rtllib_wx_set_gen_ie(struct rtllib_device *ieee, u8 *ie, size_t len) if (len) { if (len != ie[1]+2) return -EINVAL; - buf = kmalloc(len, GFP_KERNEL); + buf = kmemdup(ie, len, GFP_KERNEL); if (buf == NULL) return -ENOMEM; - memcpy(buf, ie, len); kfree(ieee->wpa_ie); ieee->wpa_ie = buf; ieee->wpa_ie_len = len; From 9638b67ba25b4a008767fca3b6f52d24400a8d1d Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 29 Oct 2011 10:20:20 +0300 Subject: [PATCH 089/365] Staging: sep: potential buffer overflow in ioctl tail_size is determined by several variables that come from the user so we should verify that it's not too large. Signed-off-by: Dan Carpenter Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sep/sep_driver.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/sep/sep_driver.c b/drivers/staging/sep/sep_driver.c index 8ac3faea2d2f..e624e2874902 100644 --- a/drivers/staging/sep/sep_driver.c +++ b/drivers/staging/sep/sep_driver.c @@ -2120,6 +2120,8 @@ static int sep_prepare_input_output_dma_table_in_dcb(struct sep_device *sep, } } if (tail_size) { + if (tail_size > sizeof(dcb_table_ptr->tail_data)) + return -EINVAL; if (is_kva == true) { memcpy(dcb_table_ptr->tail_data, (void *)(app_in_address + data_in_size - From b91a9363bbdf71324c80bdf0baac09b94c02c52a Mon Sep 17 00:00:00 2001 From: Manohar Vanga Date: Wed, 2 Nov 2011 16:50:39 +0100 Subject: [PATCH 090/365] staging: vme: fix address cast warnings for 64 bit architectures Signed-off-by: Manohar Vanga Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vme/bridges/vme_ca91cx42.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.c b/drivers/staging/vme/bridges/vme_ca91cx42.c index 0e4feac138eb..f563a0082129 100644 --- a/drivers/staging/vme/bridges/vme_ca91cx42.c +++ b/drivers/staging/vme/bridges/vme_ca91cx42.c @@ -876,13 +876,13 @@ static ssize_t ca91cx42_master_read(struct vme_master_resource *image, * maximal configured data cycle is used and splits it * automatically for non-aligned addresses. */ - if ((int)addr & 0x1) { + if ((uintptr_t)addr & 0x1) { *(u8 *)buf = ioread8(addr); done += 1; if (done == count) goto out; } - if ((int)addr & 0x2) { + if ((uintptr_t)addr & 0x2) { if ((count - done) < 2) { *(u8 *)(buf + done) = ioread8(addr + done); done += 1; @@ -930,13 +930,13 @@ static ssize_t ca91cx42_master_write(struct vme_master_resource *image, /* Here we apply for the same strategy we do in master_read * function in order to assure D16 cycle when required. */ - if ((int)addr & 0x1) { + if ((uintptr_t)addr & 0x1) { iowrite8(*(u8 *)buf, addr); done += 1; if (done == count) goto out; } - if ((int)addr & 0x2) { + if ((uintptr_t)addr & 0x2) { if ((count - done) < 2) { iowrite8(*(u8 *)(buf + done), addr + done); done += 1; @@ -973,7 +973,8 @@ static unsigned int ca91cx42_master_rmw(struct vme_master_resource *image, unsigned int mask, unsigned int compare, unsigned int swap, loff_t offset) { - u32 pci_addr, result; + u32 result; + uintptr_t pci_addr; int i; struct ca91cx42_driver *bridge; struct device *dev; @@ -990,7 +991,7 @@ static unsigned int ca91cx42_master_rmw(struct vme_master_resource *image, /* Lock image */ spin_lock(&image->lock); - pci_addr = (u32)image->kern_base + offset; + pci_addr = (uintptr_t)image->kern_base + offset; /* Address must be 4-byte aligned */ if (pci_addr & 0x3) { From 3fe0a87f8fa98fb24ceb0231e326f3892e84e39b Mon Sep 17 00:00:00 2001 From: Martyn Welch Date: Thu, 3 Nov 2011 10:57:26 +0000 Subject: [PATCH 091/365] Staging: VME: Update TODO file Contents of TODO file has become more of a feature wish-list rather than issues which should stop the VME driver being merged into the mainline kernel. Update the TODO list with issues that need to be resolved before it can be migrated to mainline. Signed-off-by: Martyn Welch Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vme/TODO | 67 +--------------------------------------- 1 file changed, 1 insertion(+), 66 deletions(-) diff --git a/drivers/staging/vme/TODO b/drivers/staging/vme/TODO index 82c222b4a146..79f00333e7ef 100644 --- a/drivers/staging/vme/TODO +++ b/drivers/staging/vme/TODO @@ -1,70 +1,5 @@ TODO ==== -API -=== - -Master window broadcast select mask ------------------------------------ - -API currently provides no method to set or get Broadcast Select mask. Suggest -somthing like: - - int vme_master_bmsk_set (struct vme_resource *res, int mask); - int vme_master_bmsk_get (struct vme_resource *res, int *mask); - - -Interrupt Generation --------------------- - -Add optional timeout when waiting for an IACK. - - -CR/CSR Buffer -------------- - -The VME API provides no functions to access the buffer mapped into the CR/CSR -space. - - -Mailboxes ---------- - -Whilst not part of the VME specification, they are provided by a number of -chips. They are currently not supported at all by the API. - - -Core -==== - -- Improve generic sanity checks (Such as does an offset and size fit within a - window and parameter checking). - -Bridge Support -============== - -Tempe (tsi148) --------------- - -- 2eSST Broadcast mode. -- Mailboxes unsupported. -- Improve error detection. -- Control of prefetch size, threshold. -- Arbiter control -- Requestor control - -Universe II (ca91c142) ----------------------- - -- Mailboxes unsupported. -- Error Detection. -- Control of prefetch size, threshold. -- Arbiter control -- Requestor control -- Slot detection - -Universe I (ca91x042) ---------------------- - -Currently completely unsupported. +- Add one or more device drivers which use the VME framework. From c26f6112990b90977db429596ed0640d153b3a32 Mon Sep 17 00:00:00 2001 From: Manohar Vanga Date: Fri, 4 Nov 2011 11:12:29 +0100 Subject: [PATCH 092/365] staging: vme: fix comment in __vme_register_driver() Signed-off-by: Manohar Vanga Acked-by: Martyn Welch Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vme/vme.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/staging/vme/vme.c b/drivers/staging/vme/vme.c index b04b4688f705..3cbc69c65d78 100644 --- a/drivers/staging/vme/vme.c +++ b/drivers/staging/vme/vme.c @@ -1421,10 +1421,7 @@ static int __vme_register_driver(struct vme_driver *drv, unsigned int ndevs) * and if the bridge is removed, it will have to go through * vme_unregister_bridge() to do it (which calls remove() on * the bridge which in turn tries to acquire vme_buses_lock and - * will have to wait). The probe() called after device - * registration in __vme_register_driver below will also fail - * as the bridge is being removed (since the probe() calls - * vme_bridge_get()). + * will have to wait). */ err = __vme_register_driver_bus(drv, bridge, ndevs); if (err) From 5b93c2a2f1d560463cbcd6e3fca5366b75e99b4b Mon Sep 17 00:00:00 2001 From: Manohar Vanga Date: Fri, 4 Nov 2011 11:12:30 +0100 Subject: [PATCH 093/365] staging: vme: remove vme_add_bus() and vme_remove_bus() The functions vme_add_bus() and vme_remove_bus() were only being used in the vme_register_bridge() and vme_unregister_bridge() functions respectively. This patch gets rid of them and moves their code to vme_register_bridge() and vme_unregister_bridge(). Signed-off-by: Manohar Vanga Acked-by: Martyn Welch Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vme/vme.c | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/drivers/staging/vme/vme.c b/drivers/staging/vme/vme.c index 3cbc69c65d78..4c6dc69405cd 100644 --- a/drivers/staging/vme/vme.c +++ b/drivers/staging/vme/vme.c @@ -1307,7 +1307,12 @@ EXPORT_SYMBOL(vme_slot_get); /* - Bridge Registration --------------------------------------------------- */ -static int vme_add_bus(struct vme_bridge *bridge) +static void vme_dev_release(struct device *dev) +{ + kfree(dev_to_vme_dev(dev)); +} + +int vme_register_bridge(struct vme_bridge *bridge) { int i; int ret = -1; @@ -1327,8 +1332,9 @@ static int vme_add_bus(struct vme_bridge *bridge) return ret; } +EXPORT_SYMBOL(vme_register_bridge); -static void vme_remove_bus(struct vme_bridge *bridge) +void vme_unregister_bridge(struct vme_bridge *bridge) { struct vme_dev *vdev; struct vme_dev *tmp; @@ -1343,22 +1349,6 @@ static void vme_remove_bus(struct vme_bridge *bridge) list_del(&bridge->bus_list); mutex_unlock(&vme_buses_lock); } - -static void vme_dev_release(struct device *dev) -{ - kfree(dev_to_vme_dev(dev)); -} - -int vme_register_bridge(struct vme_bridge *bridge) -{ - return vme_add_bus(bridge); -} -EXPORT_SYMBOL(vme_register_bridge); - -void vme_unregister_bridge(struct vme_bridge *bridge) -{ - vme_remove_bus(bridge); -} EXPORT_SYMBOL(vme_unregister_bridge); /* - Driver Registration --------------------------------------------------- */ From 8cdc081913b61e4b1086b62e13f083085fd0d3fd Mon Sep 17 00:00:00 2001 From: Manohar Vanga Date: Fri, 4 Nov 2011 11:12:31 +0100 Subject: [PATCH 094/365] staging: vme: fix comment for struct vme_dev Signed-off-by: Manohar Vanga Acked-by: Martyn Welch Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vme/vme.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/vme/vme.h b/drivers/staging/vme/vme.h index e3828badca61..e62a3234ce25 100644 --- a/drivers/staging/vme/vme.h +++ b/drivers/staging/vme/vme.h @@ -97,7 +97,7 @@ extern struct bus_type vme_bus_type; /** * Structure representing a VME device - * @id: The ID of the device (currently the bus and slot number) + * @num: The device number * @bridge: Pointer to the bridge device this device is on * @dev: Internal device structure * @drv_list: List of devices (per driver) From 9dc367bc4c76cc4c6595e9fab6a5a02523b537c6 Mon Sep 17 00:00:00 2001 From: Martyn Welch Date: Tue, 8 Nov 2011 09:54:25 +0000 Subject: [PATCH 095/365] Driver for GE PIO2 VME Card This patch implements a driver for the GE PIO2 VME Parallel I/O Card. This card is a 6U VME Card, implementing 32 solid-state relay switched IO lines, in 4 groups of 8. Each bank of IO lines is built to function as input, output or both depending on the variant of the card. Signed-off-by: Martyn Welch Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vme/devices/Kconfig | 12 + drivers/staging/vme/devices/Makefile | 3 + drivers/staging/vme/devices/vme_pio2.h | 249 ++++++++++ drivers/staging/vme/devices/vme_pio2_cntr.c | 71 +++ drivers/staging/vme/devices/vme_pio2_core.c | 524 ++++++++++++++++++++ drivers/staging/vme/devices/vme_pio2_gpio.c | 227 +++++++++ 6 files changed, 1086 insertions(+) create mode 100644 drivers/staging/vme/devices/vme_pio2.h create mode 100644 drivers/staging/vme/devices/vme_pio2_cntr.c create mode 100644 drivers/staging/vme/devices/vme_pio2_core.c create mode 100644 drivers/staging/vme/devices/vme_pio2_gpio.c diff --git a/drivers/staging/vme/devices/Kconfig b/drivers/staging/vme/devices/Kconfig index ca5ba89e2d8c..8f5d286071d1 100644 --- a/drivers/staging/vme/devices/Kconfig +++ b/drivers/staging/vme/devices/Kconfig @@ -6,3 +6,15 @@ config VME_USER If you say Y here you want to be able to access a limited number of VME windows in a manner at least semi-compatible with the interface provided with the original driver at http://vmelinux.org/. + +config VME_PIO2 + tristate "GE PIO2 VME" + help + Say Y here to include support for the GE PIO2. The PIO2 is a 6U VME + slave card, implementing 32 solid-state relay switched IO lines, in + 4 groups of 8. Each bank of IO lines is built to function as input, + output or both depending on the variant of the card. + + To compile this driver as a module, choose M here. The module will + be called vme_pio2. If unsure, say N. + diff --git a/drivers/staging/vme/devices/Makefile b/drivers/staging/vme/devices/Makefile index 459742a75283..172512cb5dbf 100644 --- a/drivers/staging/vme/devices/Makefile +++ b/drivers/staging/vme/devices/Makefile @@ -3,3 +3,6 @@ # obj-$(CONFIG_VME_USER) += vme_user.o + +vme_pio2-objs := vme_pio2_cntr.o vme_pio2_gpio.o vme_pio2_core.o +obj-$(CONFIG_VME_PIO2) += vme_pio2.o diff --git a/drivers/staging/vme/devices/vme_pio2.h b/drivers/staging/vme/devices/vme_pio2.h new file mode 100644 index 000000000000..3c5931364535 --- /dev/null +++ b/drivers/staging/vme/devices/vme_pio2.h @@ -0,0 +1,249 @@ +#ifndef _VME_PIO2_H_ +#define _VME_PIO2_H_ + +#define PIO2_CARDS_MAX 32 + +#define PIO2_VARIANT_LENGTH 5 + +#define PIO2_NUM_CHANNELS 32 +#define PIO2_NUM_IRQS 11 +#define PIO2_NUM_CNTRS 6 + +#define PIO2_REGS_SIZE 0x40 + +#define PIO2_REGS_DATA0 0x0 +#define PIO2_REGS_DATA1 0x1 +#define PIO2_REGS_DATA2 0x2 +#define PIO2_REGS_DATA3 0x3 + +static const int PIO2_REGS_DATA[4] = { PIO2_REGS_DATA0, PIO2_REGS_DATA1, + PIO2_REGS_DATA2, PIO2_REGS_DATA3 }; + +#define PIO2_REGS_INT_STAT0 0x8 +#define PIO2_REGS_INT_STAT1 0x9 +#define PIO2_REGS_INT_STAT2 0xa +#define PIO2_REGS_INT_STAT3 0xb + +static const int PIO2_REGS_INT_STAT[4] = { PIO2_REGS_INT_STAT0, + PIO2_REGS_INT_STAT1, + PIO2_REGS_INT_STAT2, + PIO2_REGS_INT_STAT3 }; + +#define PIO2_REGS_INT_STAT_CNTR 0xc +#define PIO2_REGS_INT_MASK0 0x10 +#define PIO2_REGS_INT_MASK1 0x11 +#define PIO2_REGS_INT_MASK2 0x12 +#define PIO2_REGS_INT_MASK3 0x13 +#define PIO2_REGS_INT_MASK4 0x14 +#define PIO2_REGS_INT_MASK5 0x15 +#define PIO2_REGS_INT_MASK6 0x16 +#define PIO2_REGS_INT_MASK7 0x17 + +static const int PIO2_REGS_INT_MASK[8] = { PIO2_REGS_INT_MASK0, + PIO2_REGS_INT_MASK1, + PIO2_REGS_INT_MASK2, + PIO2_REGS_INT_MASK3, + PIO2_REGS_INT_MASK4, + PIO2_REGS_INT_MASK5, + PIO2_REGS_INT_MASK6, + PIO2_REGS_INT_MASK7 }; + + + +#define PIO2_REGS_CTRL 0x18 +#define PIO2_REGS_VME_VECTOR 0x19 +#define PIO2_REGS_CNTR0 0x20 +#define PIO2_REGS_CNTR1 0x22 +#define PIO2_REGS_CNTR2 0x24 +#define PIO2_REGS_CTRL_WRD0 0x26 +#define PIO2_REGS_CNTR3 0x28 +#define PIO2_REGS_CNTR4 0x2a +#define PIO2_REGS_CNTR5 0x2c +#define PIO2_REGS_CTRL_WRD1 0x2e + +#define PIO2_REGS_ID 0x30 + + +/* PIO2_REGS_DATAx (0x0 - 0x3) */ + +static const int PIO2_CHANNEL_BANK[32] = { 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3 }; + +#define PIO2_CHANNEL0_BIT (1 << 0) +#define PIO2_CHANNEL1_BIT (1 << 1) +#define PIO2_CHANNEL2_BIT (1 << 2) +#define PIO2_CHANNEL3_BIT (1 << 3) +#define PIO2_CHANNEL4_BIT (1 << 4) +#define PIO2_CHANNEL5_BIT (1 << 5) +#define PIO2_CHANNEL6_BIT (1 << 6) +#define PIO2_CHANNEL7_BIT (1 << 7) +#define PIO2_CHANNEL8_BIT (1 << 0) +#define PIO2_CHANNEL9_BIT (1 << 1) +#define PIO2_CHANNEL10_BIT (1 << 2) +#define PIO2_CHANNEL11_BIT (1 << 3) +#define PIO2_CHANNEL12_BIT (1 << 4) +#define PIO2_CHANNEL13_BIT (1 << 5) +#define PIO2_CHANNEL14_BIT (1 << 6) +#define PIO2_CHANNEL15_BIT (1 << 7) +#define PIO2_CHANNEL16_BIT (1 << 0) +#define PIO2_CHANNEL17_BIT (1 << 1) +#define PIO2_CHANNEL18_BIT (1 << 2) +#define PIO2_CHANNEL19_BIT (1 << 3) +#define PIO2_CHANNEL20_BIT (1 << 4) +#define PIO2_CHANNEL21_BIT (1 << 5) +#define PIO2_CHANNEL22_BIT (1 << 6) +#define PIO2_CHANNEL23_BIT (1 << 7) +#define PIO2_CHANNEL24_BIT (1 << 0) +#define PIO2_CHANNEL25_BIT (1 << 1) +#define PIO2_CHANNEL26_BIT (1 << 2) +#define PIO2_CHANNEL27_BIT (1 << 3) +#define PIO2_CHANNEL28_BIT (1 << 4) +#define PIO2_CHANNEL29_BIT (1 << 5) +#define PIO2_CHANNEL30_BIT (1 << 6) +#define PIO2_CHANNEL31_BIT (1 << 7) + +static const int PIO2_CHANNEL_BIT[32] = { PIO2_CHANNEL0_BIT, PIO2_CHANNEL1_BIT, + PIO2_CHANNEL2_BIT, PIO2_CHANNEL3_BIT, + PIO2_CHANNEL4_BIT, PIO2_CHANNEL5_BIT, + PIO2_CHANNEL6_BIT, PIO2_CHANNEL7_BIT, + PIO2_CHANNEL8_BIT, PIO2_CHANNEL9_BIT, + PIO2_CHANNEL10_BIT, PIO2_CHANNEL11_BIT, + PIO2_CHANNEL12_BIT, PIO2_CHANNEL13_BIT, + PIO2_CHANNEL14_BIT, PIO2_CHANNEL15_BIT, + PIO2_CHANNEL16_BIT, PIO2_CHANNEL17_BIT, + PIO2_CHANNEL18_BIT, PIO2_CHANNEL19_BIT, + PIO2_CHANNEL20_BIT, PIO2_CHANNEL21_BIT, + PIO2_CHANNEL22_BIT, PIO2_CHANNEL23_BIT, + PIO2_CHANNEL24_BIT, PIO2_CHANNEL25_BIT, + PIO2_CHANNEL26_BIT, PIO2_CHANNEL27_BIT, + PIO2_CHANNEL28_BIT, PIO2_CHANNEL29_BIT, + PIO2_CHANNEL30_BIT, PIO2_CHANNEL31_BIT + }; + +/* PIO2_REGS_INT_STAT_CNTR (0xc) */ +#define PIO2_COUNTER0 (1 << 0) +#define PIO2_COUNTER1 (1 << 1) +#define PIO2_COUNTER2 (1 << 2) +#define PIO2_COUNTER3 (1 << 3) +#define PIO2_COUNTER4 (1 << 4) +#define PIO2_COUNTER5 (1 << 5) + +static const int PIO2_COUNTER[6] = { PIO2_COUNTER0, PIO2_COUNTER1, + PIO2_COUNTER2, PIO2_COUNTER3, + PIO2_COUNTER4, PIO2_COUNTER5 }; + +/* PIO2_REGS_CTRL (0x18) */ +#define PIO2_VME_INT_MASK 0x7 +#define PIO2_LED (1 << 6) +#define PIO2_LOOP (1 << 7) + +/* PIO2_REGS_VME_VECTOR (0x19) */ +#define PIO2_VME_VECTOR_SPUR 0x0 +#define PIO2_VME_VECTOR_BANK0 0x1 +#define PIO2_VME_VECTOR_BANK1 0x2 +#define PIO2_VME_VECTOR_BANK2 0x3 +#define PIO2_VME_VECTOR_BANK3 0x4 +#define PIO2_VME_VECTOR_CNTR0 0x5 +#define PIO2_VME_VECTOR_CNTR1 0x6 +#define PIO2_VME_VECTOR_CNTR2 0x7 +#define PIO2_VME_VECTOR_CNTR3 0x8 +#define PIO2_VME_VECTOR_CNTR4 0x9 +#define PIO2_VME_VECTOR_CNTR5 0xa + +#define PIO2_VME_VECTOR_MASK 0xf0 + +static const int PIO2_VECTOR_BANK[4] = { PIO2_VME_VECTOR_BANK0, + PIO2_VME_VECTOR_BANK1, + PIO2_VME_VECTOR_BANK2, + PIO2_VME_VECTOR_BANK3 }; + +static const int PIO2_VECTOR_CNTR[6] = { PIO2_VME_VECTOR_CNTR0, + PIO2_VME_VECTOR_CNTR1, + PIO2_VME_VECTOR_CNTR2, + PIO2_VME_VECTOR_CNTR3, + PIO2_VME_VECTOR_CNTR4, + PIO2_VME_VECTOR_CNTR5 }; + +/* PIO2_REGS_CNTRx (0x20 - 0x24 & 0x28 - 0x2c) */ + +static const int PIO2_CNTR_DATA[6] = { PIO2_REGS_CNTR0, PIO2_REGS_CNTR1, + PIO2_REGS_CNTR2, PIO2_REGS_CNTR3, + PIO2_REGS_CNTR4, PIO2_REGS_CNTR5 }; + +/* PIO2_REGS_CTRL_WRDx (0x26 & 0x2e) */ + +static const int PIO2_CNTR_CTRL[6] = { PIO2_REGS_CTRL_WRD0, + PIO2_REGS_CTRL_WRD0, + PIO2_REGS_CTRL_WRD0, + PIO2_REGS_CTRL_WRD1, + PIO2_REGS_CTRL_WRD1, + PIO2_REGS_CTRL_WRD1 }; + +#define PIO2_CNTR_SC_DEV0 0 +#define PIO2_CNTR_SC_DEV1 (1 << 6) +#define PIO2_CNTR_SC_DEV2 (2 << 6) +#define PIO2_CNTR_SC_RDBACK (3 << 6) + +static const int PIO2_CNTR_SC_DEV[6] = { PIO2_CNTR_SC_DEV0, PIO2_CNTR_SC_DEV1, + PIO2_CNTR_SC_DEV2, PIO2_CNTR_SC_DEV0, + PIO2_CNTR_SC_DEV1, PIO2_CNTR_SC_DEV2 }; + +#define PIO2_CNTR_RW_LATCH 0 +#define PIO2_CNTR_RW_LSB (1 << 4) +#define PIO2_CNTR_RW_MSB (2 << 4) +#define PIO2_CNTR_RW_BOTH (3 << 4) + +#define PIO2_CNTR_MODE0 0 +#define PIO2_CNTR_MODE1 (1 << 1) +#define PIO2_CNTR_MODE2 (2 << 1) +#define PIO2_CNTR_MODE3 (3 << 1) +#define PIO2_CNTR_MODE4 (4 << 1) +#define PIO2_CNTR_MODE5 (5 << 1) + +#define PIO2_CNTR_BCD 1 + + + +enum pio2_bank_config { NOFIT, INPUT, OUTPUT, BOTH }; +enum pio2_int_config { NONE = 0, LOW2HIGH = 1, HIGH2LOW = 2, EITHER = 4 }; + +/* Bank configuration structure */ +struct pio2_io_bank { + enum pio2_bank_config config; + u8 value; + enum pio2_int_config irq[8]; +}; + +/* Counter configuration structure */ +struct pio2_cntr { + int mode; + int count; +}; + +struct pio2_card { + int id; + int bus; + long base; + int irq_vector; + int irq_level; + char variant[6]; + int led; + + struct vme_dev *vdev; + struct vme_resource *window; + + struct gpio_chip gc; + struct pio2_io_bank bank[4]; + + struct pio2_cntr cntr[6]; +}; + +int pio2_cntr_reset(struct pio2_card *); + +int pio2_gpio_reset(struct pio2_card *); +int __init pio2_gpio_init(struct pio2_card *); +void __exit pio2_gpio_exit(struct pio2_card *); + +#endif /* _VME_PIO2_H_ */ diff --git a/drivers/staging/vme/devices/vme_pio2_cntr.c b/drivers/staging/vme/devices/vme_pio2_cntr.c new file mode 100644 index 000000000000..08e0d59806ca --- /dev/null +++ b/drivers/staging/vme/devices/vme_pio2_cntr.c @@ -0,0 +1,71 @@ +/* + * GE PIO2 Counter Driver + * + * Author: Martyn Welch + * Copyright 2009 GE Intelligent Platforms Embedded Systems, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The PIO-2 has 6 counters, currently this code just disables the interrupts + * and leaves them alone. + * + */ + +#include +#include +#include + +#include "../vme.h" +#include "vme_pio2.h" + +static int pio2_cntr_irq_set(struct pio2_card *card, int id) +{ + int retval; + u8 data; + + data = PIO2_CNTR_SC_DEV[id] | PIO2_CNTR_RW_BOTH | card->cntr[id].mode; + retval = vme_master_write(card->window, &data, 1, PIO2_CNTR_CTRL[id]); + if (retval < 0) + return retval; + + data = card->cntr[id].count & 0xFF; + retval = vme_master_write(card->window, &data, 1, PIO2_CNTR_DATA[id]); + if (retval < 0) + return retval; + + data = (card->cntr[id].count >> 8) & 0xFF; + retval = vme_master_write(card->window, &data, 1, PIO2_CNTR_DATA[id]); + if (retval < 0) + return retval; + + return 0; +} + +int pio2_cntr_reset(struct pio2_card *card) +{ + int i, retval = 0; + u8 reg; + + /* Clear down all timers */ + for (i = 0; i < 6; i++) { + card->cntr[i].mode = PIO2_CNTR_MODE5; + card->cntr[i].count = 0; + retval = pio2_cntr_irq_set(card, i); + if (retval < 0) + return retval; + } + + /* Ensure all counter interrupts are cleared */ + do { + retval = vme_master_read(card->window, ®, 1, + PIO2_REGS_INT_STAT_CNTR); + if (retval < 0) + return retval; + } while (reg != 0); + + return retval; +} + diff --git a/drivers/staging/vme/devices/vme_pio2_core.c b/drivers/staging/vme/devices/vme_pio2_core.c new file mode 100644 index 000000000000..9fedc442a779 --- /dev/null +++ b/drivers/staging/vme/devices/vme_pio2_core.c @@ -0,0 +1,524 @@ +/* + * GE PIO2 6U VME I/O Driver + * + * Author: Martyn Welch + * Copyright 2009 GE Intelligent Platforms Embedded Systems, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../vme.h" +#include "vme_pio2.h" + + +static const char driver_name[] = "pio2"; + +static int bus[PIO2_CARDS_MAX]; +static int bus_num; +static long base[PIO2_CARDS_MAX]; +static int base_num; +static int vector[PIO2_CARDS_MAX]; +static int vector_num; +static int level[PIO2_CARDS_MAX]; +static int level_num; +static const char *variant[PIO2_CARDS_MAX]; +static int variant_num; + +static int loopback; + +static int pio2_match(struct vme_dev *); +static int __devinit pio2_probe(struct vme_dev *); +static int __devexit pio2_remove(struct vme_dev *); + +static int pio2_get_led(struct pio2_card *card) +{ + /* Can't read hardware, state saved in structure */ + return card->led; +} + +static int pio2_set_led(struct pio2_card *card, int state) +{ + u8 reg; + int retval; + + reg = card->irq_level; + + /* Register state inverse of led state */ + if (!state) + reg |= PIO2_LED; + + if (loopback) + reg |= PIO2_LOOP; + + retval = vme_master_write(card->window, ®, 1, PIO2_REGS_CTRL); + if (retval < 0) + return retval; + + card->led = state ? 1 : 0; + + return 0; +} + +static void pio2_int(int level, int vector, void *ptr) +{ + int vec, i, channel, retval; + u8 reg; + struct pio2_card *card = ptr; + + vec = vector & ~PIO2_VME_VECTOR_MASK; + + switch (vec) { + case 0: + dev_warn(&card->vdev->dev, "Spurious Interrupt\n"); + break; + case 1: + case 2: + case 3: + case 4: + /* Channels 0 to 7 */ + retval = vme_master_read(card->window, ®, 1, + PIO2_REGS_INT_STAT[vec - 1]); + if (retval < 0) { + dev_err(&card->vdev->dev, + "Unable to read IRQ status register\n"); + return; + } + for (i = 0; i < 8; i++) { + channel = ((vec - 1) * 8) + i; + if (reg & PIO2_CHANNEL_BIT[channel]) + dev_info(&card->vdev->dev, + "Interrupt on I/O channel %d\n", + channel); + } + break; + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + /* Counters are dealt with by their own handler */ + dev_err(&card->vdev->dev, + "Counter interrupt\n"); + break; + } +} + + +/* + * We return whether this has been successful - this is used in the probe to + * ensure we have a valid card. + */ +static int pio2_reset_card(struct pio2_card *card) +{ + int retval = 0; + u8 data = 0; + + /* Clear main register*/ + retval = vme_master_write(card->window, &data, 1, PIO2_REGS_CTRL); + if (retval < 0) + return retval; + + /* Clear VME vector */ + retval = vme_master_write(card->window, &data, 1, PIO2_REGS_VME_VECTOR); + if (retval < 0) + return retval; + + /* Reset GPIO */ + retval = pio2_gpio_reset(card); + if (retval < 0) + return retval; + + /* Reset counters */ + retval = pio2_cntr_reset(card); + if (retval < 0) + return retval; + + return 0; +} + +static struct vme_driver pio2_driver = { + .name = driver_name, + .match = pio2_match, + .probe = pio2_probe, + .remove = __devexit_p(pio2_remove), +}; + + +static int __init pio2_init(void) +{ + int retval = 0; + + if (bus_num == 0) { + printk(KERN_ERR "%s: No cards, skipping registration\n", + driver_name); + goto err_nocard; + } + + if (bus_num > PIO2_CARDS_MAX) { + printk(KERN_ERR + "%s: Driver only able to handle %d PIO2 Cards\n", + driver_name, PIO2_CARDS_MAX); + bus_num = PIO2_CARDS_MAX; + } + + /* Register the PIO2 driver */ + retval = vme_register_driver(&pio2_driver, bus_num); + if (retval != 0) + goto err_reg; + + return retval; + +err_reg: +err_nocard: + return retval; +} + +static int pio2_match(struct vme_dev *vdev) +{ + + if (vdev->num >= bus_num) { + dev_err(&vdev->dev, + "The enumeration of the VMEbus to which the board is connected must be specified"); + return 0; + } + + if (vdev->num >= base_num) { + dev_err(&vdev->dev, + "The VME address for the cards registers must be specified"); + return 0; + } + + if (vdev->num >= vector_num) { + dev_err(&vdev->dev, + "The IRQ vector used by the card must be specified"); + return 0; + } + + if (vdev->num >= level_num) { + dev_err(&vdev->dev, + "The IRQ level used by the card must be specified"); + return 0; + } + + if (vdev->num >= variant_num) { + dev_err(&vdev->dev, "The variant of the card must be specified"); + return 0; + } + + return 1; +} + +static int __devinit pio2_probe(struct vme_dev *vdev) +{ + struct pio2_card *card; + int retval; + int i; + u8 reg; + int vec; + + card = kzalloc(sizeof(struct pio2_card), GFP_KERNEL); + if (card == NULL) { + dev_err(&vdev->dev, "Unable to allocate card structure\n"); + retval = -ENOMEM; + goto err_struct; + } + + card->id = vdev->num; + card->bus = bus[card->id]; + card->base = base[card->id]; + card->irq_vector = vector[card->id]; + card->irq_level = level[card->id] & PIO2_VME_INT_MASK; + strncpy(card->variant, variant[card->id], PIO2_VARIANT_LENGTH); + card->vdev = vdev; + + for (i = 0; i < PIO2_VARIANT_LENGTH; i++) { + + if (isdigit(card->variant[i]) == 0) { + dev_err(&card->vdev->dev, "Variant invalid\n"); + retval = -EINVAL; + goto err_variant; + } + } + + /* + * Bottom 4 bits of VME interrupt vector used to determine source, + * provided vector should only use upper 4 bits. + */ + if (card->irq_vector & ~PIO2_VME_VECTOR_MASK) { + dev_err(&card->vdev->dev, + "Invalid VME IRQ Vector, vector must not use lower 4 bits\n"); + retval = -EINVAL; + goto err_vector; + } + + /* + * There is no way to determine the build variant or whether each bank + * is input, output or both at run time. The inputs are also inverted + * if configured as both. + * + * We pass in the board variant and use that to determine the + * configuration of the banks. + */ + for (i = 1; i < PIO2_VARIANT_LENGTH; i++) { + switch (card->variant[i]) { + case '0': + card->bank[i-1].config = NOFIT; + break; + case '1': + case '2': + case '3': + case '4': + card->bank[i-1].config = INPUT; + break; + case '5': + card->bank[i-1].config = OUTPUT; + break; + case '6': + case '7': + case '8': + case '9': + card->bank[i-1].config = BOTH; + break; + } + } + + /* Get a master window and position over regs */ + card->window = vme_master_request(vdev, VME_A24, VME_SCT, VME_D16); + if (card->window == NULL) { + dev_err(&card->vdev->dev, + "Unable to assign VME master resource\n"); + retval = -EIO; + goto err_window; + } + + retval = vme_master_set(card->window, 1, card->base, 0x10000, VME_A24, + (VME_SCT | VME_USER | VME_DATA), VME_D16); + if (retval) { + dev_err(&card->vdev->dev, + "Unable to configure VME master resource\n"); + goto err_set; + } + + /* + * There is also no obvious register which we can probe to determine + * whether the provided base is valid. If we can read the "ID Register" + * offset and the reset function doesn't error, assume we have a valid + * location. + */ + retval = vme_master_read(card->window, ®, 1, PIO2_REGS_ID); + if (retval < 0) { + dev_err(&card->vdev->dev, "Unable to read from device\n"); + goto err_read; + } + + dev_dbg(&card->vdev->dev, "ID Register:%x\n", reg); + + /* + * Ensure all the I/O is cleared. We can't read back the states, so + * this is the only method we have to ensure that the I/O is in a known + * state. + */ + retval = pio2_reset_card(card); + if (retval) { + dev_err(&card->vdev->dev, + "Failed to reset card, is location valid?"); + retval = -ENODEV; + goto err_reset; + } + + /* Configure VME Interrupts */ + reg = card->irq_level; + if (pio2_get_led(card)) + reg |= PIO2_LED; + if (loopback) + reg |= PIO2_LOOP; + retval = vme_master_write(card->window, ®, 1, PIO2_REGS_CTRL); + if (retval < 0) + return retval; + + /* Set VME vector */ + retval = vme_master_write(card->window, &card->irq_vector, 1, + PIO2_REGS_VME_VECTOR); + if (retval < 0) + return retval; + + /* Attach spurious interrupt handler. */ + vec = card->irq_vector | PIO2_VME_VECTOR_SPUR; + + retval = vme_irq_request(vdev, card->irq_level, vec, + &pio2_int, (void *)card); + if (retval < 0) { + dev_err(&card->vdev->dev, + "Unable to attach VME interrupt vector0x%x, level 0x%x\n", + vec, card->irq_level); + goto err_irq; + } + + /* Attach GPIO interrupt handlers. */ + for (i = 0; i < 4; i++) { + vec = card->irq_vector | PIO2_VECTOR_BANK[i]; + + retval = vme_irq_request(vdev, card->irq_level, vec, + &pio2_int, (void *)card); + if (retval < 0) { + dev_err(&card->vdev->dev, + "Unable to attach VME interrupt vector0x%x, level 0x%x\n", + vec, card->irq_level); + goto err_gpio_irq; + } + } + + /* Attach counter interrupt handlers. */ + for (i = 0; i < 6; i++) { + vec = card->irq_vector | PIO2_VECTOR_CNTR[i]; + + retval = vme_irq_request(vdev, card->irq_level, vec, + &pio2_int, (void *)card); + if (retval < 0) { + dev_err(&card->vdev->dev, + "Unable to attach VME interrupt vector0x%x, level 0x%x\n", + vec, card->irq_level); + goto err_cntr_irq; + } + } + + /* Register IO */ + retval = pio2_gpio_init(card); + if (retval < 0) { + dev_err(&card->vdev->dev, + "Unable to register with GPIO framework\n"); + goto err_gpio; + } + + /* Set LED - This also sets interrupt level */ + retval = pio2_set_led(card, 0); + if (retval < 0) { + dev_err(&card->vdev->dev, "Unable to set LED\n"); + goto err_led; + } + + dev_set_drvdata(&card->vdev->dev, card); + + dev_info(&card->vdev->dev, + "PIO2 (variant %s) configured at 0x%lx\n", card->variant, + card->base); + + return 0; + +err_led: + pio2_gpio_exit(card); +err_gpio: + i = 6; +err_cntr_irq: + while (i > 0) { + i--; + vec = card->irq_vector | PIO2_VECTOR_CNTR[i]; + vme_irq_free(vdev, card->irq_level, vec); + } + + i = 4; +err_gpio_irq: + while (i > 0) { + i--; + vec = card->irq_vector | PIO2_VECTOR_BANK[i]; + vme_irq_free(vdev, card->irq_level, vec); + } + + vec = (card->irq_vector & PIO2_VME_VECTOR_MASK) | PIO2_VME_VECTOR_SPUR; + vme_irq_free(vdev, card->irq_level, vec); +err_irq: + pio2_reset_card(card); +err_reset: +err_read: + vme_master_set(card->window, 0, 0, 0, VME_A16, 0, VME_D16); +err_set: + vme_master_free(card->window); +err_window: +err_vector: +err_variant: + kfree(card); +err_struct: + return retval; +} + +static int __devexit pio2_remove(struct vme_dev *vdev) +{ + int vec; + int i; + + struct pio2_card *card = dev_get_drvdata(&vdev->dev); + + pio2_gpio_exit(card); + + for (i = 0; i < 6; i++) { + vec = card->irq_vector | PIO2_VECTOR_CNTR[i]; + vme_irq_free(vdev, card->irq_level, vec); + } + + for (i = 0; i < 4; i++) { + vec = card->irq_vector | PIO2_VECTOR_BANK[i]; + vme_irq_free(vdev, card->irq_level, vec); + } + + vec = (card->irq_vector & PIO2_VME_VECTOR_MASK) | PIO2_VME_VECTOR_SPUR; + vme_irq_free(vdev, card->irq_level, vec); + + pio2_reset_card(card); + + vme_master_set(card->window, 0, 0, 0, VME_A16, 0, VME_D16); + + vme_master_free(card->window); + + kfree(card); + + return 0; +} + +static void __exit pio2_exit(void) +{ + vme_unregister_driver(&pio2_driver); +} + + +/* These are required for each board */ +MODULE_PARM_DESC(bus, "Enumeration of VMEbus to which the board is connected"); +module_param_array(bus, int, &bus_num, S_IRUGO); + +MODULE_PARM_DESC(base, "Base VME address for PIO2 Registers"); +module_param_array(base, long, &base_num, S_IRUGO); + +MODULE_PARM_DESC(vector, "VME IRQ Vector (Lower 4 bits masked)"); +module_param_array(vector, int, &vector_num, S_IRUGO); + +MODULE_PARM_DESC(level, "VME IRQ Level"); +module_param_array(level, int, &level_num, S_IRUGO); + +MODULE_PARM_DESC(variant, "Last 4 characters of PIO2 board variant"); +module_param_array(variant, charp, &variant_num, S_IRUGO); + +/* This is for debugging */ +MODULE_PARM_DESC(loopback, "Enable loopback mode on all cards"); +module_param(loopback, bool, S_IRUGO); + +MODULE_DESCRIPTION("GE PIO2 6U VME I/O Driver"); +MODULE_AUTHOR("Martyn Welch + * Copyright 2009 GE Intelligent Platforms Embedded Systems, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../vme.h" +#include "vme_pio2.h" + +static const char driver_name[] = "pio2_gpio"; + +static struct pio2_card *gpio_to_pio2_card(struct gpio_chip *chip) +{ + return container_of(chip, struct pio2_card, gc); +} + +static int pio2_gpio_get(struct gpio_chip *chip, unsigned int offset) +{ + u8 reg; + int retval; + struct pio2_card *card = gpio_to_pio2_card(chip); + + if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == OUTPUT) | + (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) { + + dev_err(&card->vdev->dev, "Channel not available as input\n"); + return 0; + } + + retval = vme_master_read(card->window, ®, 1, + PIO2_REGS_DATA[PIO2_CHANNEL_BANK[offset]]); + if (retval < 0) { + dev_err(&card->vdev->dev, "Unable to read from GPIO\n"); + return 0; + } + + /* + * Remember, input on channels configured as both input and output + * are inverted! + */ + if (reg & PIO2_CHANNEL_BIT[offset]) { + if (card->bank[PIO2_CHANNEL_BANK[offset]].config != BOTH) + return 0; + else + return 1; + } else { + if (card->bank[PIO2_CHANNEL_BANK[offset]].config != BOTH) + return 1; + else + return 0; + } +} + +static void pio2_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) +{ + u8 reg; + int retval; + struct pio2_card *card = gpio_to_pio2_card(chip); + + if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == INPUT) | + (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) { + + dev_err(&card->vdev->dev, "Channel not availabe as output\n"); + return; + } + + if (value) + reg = card->bank[PIO2_CHANNEL_BANK[offset]].value | + PIO2_CHANNEL_BIT[offset]; + else + reg = card->bank[PIO2_CHANNEL_BANK[offset]].value & + ~PIO2_CHANNEL_BIT[offset]; + + retval = vme_master_write(card->window, ®, 1, + PIO2_REGS_DATA[PIO2_CHANNEL_BANK[offset]]); + if (retval < 0) { + dev_err(&card->vdev->dev, "Unable to write to GPIO\n"); + return; + } + + card->bank[PIO2_CHANNEL_BANK[offset]].value = reg; +} + +/* Directionality configured at board build - send appropriate response */ +static int pio2_gpio_dir_in(struct gpio_chip *chip, unsigned offset) +{ + int data; + struct pio2_card *card = gpio_to_pio2_card(chip); + + if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == OUTPUT) | + (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) { + dev_err(&card->vdev->dev, + "Channel directionality not configurable at runtine\n"); + + data = -EINVAL; + } else { + data = 0; + } + + return data; +} + +/* Directionality configured at board build - send appropriate response */ +static int pio2_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value) +{ + int data; + struct pio2_card *card = gpio_to_pio2_card(chip); + + if ((card->bank[PIO2_CHANNEL_BANK[offset]].config == INPUT) | + (card->bank[PIO2_CHANNEL_BANK[offset]].config == NOFIT)) { + dev_err(&card->vdev->dev, + "Channel directionality not configurable at runtine\n"); + + data = -EINVAL; + } else { + data = 0; + } + + return data; +} + +/* + * We return whether this has been successful - this is used in the probe to + * ensure we have a valid card. + */ +int pio2_gpio_reset(struct pio2_card *card) +{ + int retval = 0; + int i, j; + + u8 data = 0; + + /* Zero output registers */ + for (i = 0; i < 4; i++) { + retval = vme_master_write(card->window, &data, 1, + PIO2_REGS_DATA[i]); + if (retval < 0) + return retval; + card->bank[i].value = 0; + } + + /* Set input interrupt masks */ + for (i = 0; i < 8; i++) { + retval = vme_master_write(card->window, &data, 1, + PIO2_REGS_INT_MASK[i]); + if (retval < 0) + return retval; + + for (j = 0; j < 8; j++) + card->bank[i].irq[j] = NONE; + } + + /* Ensure all I/O interrupts are cleared */ + for (i = 0; i < 4; i++) { + do { + retval = vme_master_read(card->window, &data, 1, + PIO2_REGS_INT_STAT[i]); + if (retval < 0) + return retval; + } while (data != 0); + } + + return 0; +} + +int __init pio2_gpio_init(struct pio2_card *card) +{ + int retval = 0; + char *label; + + label = kmalloc(PIO2_NUM_CHANNELS, GFP_KERNEL); + if (label == NULL) { + dev_err(&card->vdev->dev, "Unable to allocate GPIO label\n"); + return -ENOMEM; + } + + sprintf(label, "%s@%s", driver_name, dev_name(&card->vdev->dev)); + card->gc.label = label; + + card->gc.ngpio = PIO2_NUM_CHANNELS; + /* Dynamic allocation of base */ + card->gc.base = -1; + /* Setup pointers to chip functions */ + card->gc.direction_input = pio2_gpio_dir_in; + card->gc.direction_output = pio2_gpio_dir_out; + card->gc.get = pio2_gpio_get; + card->gc.set = pio2_gpio_set; + + /* This function adds a memory mapped GPIO chip */ + retval = gpiochip_add(&(card->gc)); + if (retval) { + dev_err(&card->vdev->dev, "Unable to register GPIO\n"); + kfree(card->gc.label); + } + + return retval; +}; + +void __exit pio2_gpio_exit(struct pio2_card *card) +{ + const char *label = card->gc.label; + + if (gpiochip_remove(&(card->gc))) + dev_err(&card->vdev->dev, "Failed to remove GPIO"); + + kfree(label); +} + From be7f39c5ecf51d1becb699563e9ac2447f7bcdcd Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 26 Nov 2011 17:28:56 -0800 Subject: [PATCH 096/365] Staging: delete spectra driver To quote Alan: Moorestown/Oaktrail has appeared only in the PC like form so the following bits of staging can be binned: drivers/staging/spectra so let's delete it. Cc: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/spectra/Kconfig | 41 - drivers/staging/spectra/Makefile | 11 - drivers/staging/spectra/README | 29 - drivers/staging/spectra/ffsdefs.h | 58 - drivers/staging/spectra/ffsport.c | 834 ---- drivers/staging/spectra/ffsport.h | 85 - drivers/staging/spectra/flash.c | 4305 --------------------- drivers/staging/spectra/flash.h | 198 - drivers/staging/spectra/lld.c | 339 -- drivers/staging/spectra/lld.h | 111 - drivers/staging/spectra/lld_cdma.c | 910 ----- drivers/staging/spectra/lld_cdma.h | 123 - drivers/staging/spectra/lld_emu.c | 776 ---- drivers/staging/spectra/lld_emu.h | 51 - drivers/staging/spectra/lld_mtd.c | 683 ---- drivers/staging/spectra/lld_mtd.h | 51 - drivers/staging/spectra/lld_nand.c | 2619 ------------- drivers/staging/spectra/lld_nand.h | 131 - drivers/staging/spectra/nand_regs.h | 619 --- drivers/staging/spectra/spectraswconfig.h | 82 - 22 files changed, 12059 deletions(-) delete mode 100644 drivers/staging/spectra/Kconfig delete mode 100644 drivers/staging/spectra/Makefile delete mode 100644 drivers/staging/spectra/README delete mode 100644 drivers/staging/spectra/ffsdefs.h delete mode 100644 drivers/staging/spectra/ffsport.c delete mode 100644 drivers/staging/spectra/ffsport.h delete mode 100644 drivers/staging/spectra/flash.c delete mode 100644 drivers/staging/spectra/flash.h delete mode 100644 drivers/staging/spectra/lld.c delete mode 100644 drivers/staging/spectra/lld.h delete mode 100644 drivers/staging/spectra/lld_cdma.c delete mode 100644 drivers/staging/spectra/lld_cdma.h delete mode 100644 drivers/staging/spectra/lld_emu.c delete mode 100644 drivers/staging/spectra/lld_emu.h delete mode 100644 drivers/staging/spectra/lld_mtd.c delete mode 100644 drivers/staging/spectra/lld_mtd.h delete mode 100644 drivers/staging/spectra/lld_nand.c delete mode 100644 drivers/staging/spectra/lld_nand.h delete mode 100644 drivers/staging/spectra/nand_regs.h delete mode 100644 drivers/staging/spectra/spectraswconfig.h diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 25cdff36a78a..0f1e5ca99448 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -72,8 +72,6 @@ source "drivers/staging/octeon/Kconfig" source "drivers/staging/serqt_usb2/Kconfig" -source "drivers/staging/spectra/Kconfig" - source "drivers/staging/quatech_usb2/Kconfig" source "drivers/staging/vt6655/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index a25f3f26c7ff..6f886bd9e782 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -21,7 +21,6 @@ obj-$(CONFIG_RTL8192E) += rtl8192e/ obj-$(CONFIG_R8712U) += rtl8712/ obj-$(CONFIG_RTS_PSTOR) += rts_pstor/ obj-$(CONFIG_RTS5139) += rts5139/ -obj-$(CONFIG_SPECTRA) += spectra/ obj-$(CONFIG_TRANZPORT) += frontier/ obj-$(CONFIG_POHMELFS) += pohmelfs/ obj-$(CONFIG_IDE_PHISON) += phison/ diff --git a/drivers/staging/spectra/Kconfig b/drivers/staging/spectra/Kconfig deleted file mode 100644 index 4fc206484830..000000000000 --- a/drivers/staging/spectra/Kconfig +++ /dev/null @@ -1,41 +0,0 @@ - -menuconfig SPECTRA - tristate "Denali Spectra Flash Translation Layer" - depends on BLOCK - depends on X86_MRST - default n - ---help--- - Enable the FTL pseudo-filesystem used with the NAND Flash - controller on Intel Moorestown Platform to pretend to be a disk. - -choice - prompt "Compile for" - depends on SPECTRA - default SPECTRA_MRST_HW - -config SPECTRA_MRST_HW - bool "Moorestown hardware mode" - help - Driver communicates with the Moorestown hardware's register interface. - in DMA mode. - -config SPECTRA_MTD - bool "Linux MTD mode" - depends on MTD - help - Driver communicates with the kernel MTD subsystem instead of its own - built-in hardware driver. - -config SPECTRA_EMU - bool "RAM emulator testing" - help - Driver emulates Flash on a RAM buffer and / or disk file. Useful to test the behavior of FTL layer. - -endchoice - -config SPECTRA_MRST_HW_DMA - bool - default n - depends on SPECTRA_MRST_HW - help - Use DMA for native hardware interface. diff --git a/drivers/staging/spectra/Makefile b/drivers/staging/spectra/Makefile deleted file mode 100644 index f777dfba05a5..000000000000 --- a/drivers/staging/spectra/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# -# Makefile of Intel Moorestown NAND controller driver -# - -obj-$(CONFIG_SPECTRA) += spectra.o -spectra-y := ffsport.o flash.o lld.o -spectra-$(CONFIG_SPECTRA_MRST_HW) += lld_nand.o -spectra-$(CONFIG_SPECTRA_MRST_HW_DMA) += lld_cdma.o -spectra-$(CONFIG_SPECTRA_EMU) += lld_emu.o -spectra-$(CONFIG_SPECTRA_MTD) += lld_mtd.o - diff --git a/drivers/staging/spectra/README b/drivers/staging/spectra/README deleted file mode 100644 index ecba559b899c..000000000000 --- a/drivers/staging/spectra/README +++ /dev/null @@ -1,29 +0,0 @@ -This is a driver for NAND controller of Intel Moorestown platform. - -This driver is a standalone linux block device driver, it acts as if it's a normal hard disk. -It includes three layer: - block layer interface - file ffsport.c - Flash Translation Layer (FTL) - file flash.c (implement the NAND flash Translation Layer, includs address mapping, garbage collection, wear-leveling and so on) - Low level layer - file lld_nand.c/lld_cdma.c/lld_emu.c (which implements actual controller hardware registers access) - -This driver can be build as modules or build-in. - -Dependency: -This driver has dependency on IA Firmware of Intel Moorestown platform. -It need the IA Firmware to create the block table for the first time. -And to validate this driver code without IA Firmware, you can change the -macro AUTO_FORMAT_FLASH from 0 to 1 in file spectraswconfig.h. Thus the -driver will erase the whole nand flash and create a new block table. - -TODO: - - Enable Command DMA feature support - - lower the memory footprint - - Remove most of the unnecessary global variables - - Change all the upcase variable / functions name to lowercase - - Some other misc bugs - -Please send patches to: - Greg Kroah-Hartman - -And Cc to: Gao Yunpeng - diff --git a/drivers/staging/spectra/ffsdefs.h b/drivers/staging/spectra/ffsdefs.h deleted file mode 100644 index a9e9cd233d2a..000000000000 --- a/drivers/staging/spectra/ffsdefs.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef _FFSDEFS_ -#define _FFSDEFS_ - -#define CLEAR 0 /*use this to clear a field instead of "fail"*/ -#define SET 1 /*use this to set a field instead of "pass"*/ -#define FAIL 1 /*failed flag*/ -#define PASS 0 /*success flag*/ -#define ERR -1 /*error flag*/ - -#define ERASE_CMD 10 -#define WRITE_MAIN_CMD 11 -#define READ_MAIN_CMD 12 -#define WRITE_SPARE_CMD 13 -#define READ_SPARE_CMD 14 -#define WRITE_MAIN_SPARE_CMD 15 -#define READ_MAIN_SPARE_CMD 16 -#define MEMCOPY_CMD 17 -#define DUMMY_CMD 99 - -#define EVENT_PASS 0x00 -#define EVENT_CORRECTABLE_DATA_ERROR_FIXED 0x01 -#define EVENT_UNCORRECTABLE_DATA_ERROR 0x02 -#define EVENT_TIME_OUT 0x03 -#define EVENT_PROGRAM_FAILURE 0x04 -#define EVENT_ERASE_FAILURE 0x05 -#define EVENT_MEMCOPY_FAILURE 0x06 -#define EVENT_FAIL 0x07 - -#define EVENT_NONE 0x22 -#define EVENT_DMA_CMD_COMP 0x77 -#define EVENT_ECC_TRANSACTION_DONE 0x88 -#define EVENT_DMA_CMD_FAIL 0x99 - -#define CMD_PASS 0 -#define CMD_FAIL 1 -#define CMD_ABORT 2 -#define CMD_NOT_DONE 3 - -#endif /* _FFSDEFS_ */ diff --git a/drivers/staging/spectra/ffsport.c b/drivers/staging/spectra/ffsport.c deleted file mode 100644 index 86d556d6cf98..000000000000 --- a/drivers/staging/spectra/ffsport.c +++ /dev/null @@ -1,834 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include "ffsport.h" -#include "flash.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/**** Helper functions used for Div, Remainder operation on u64 ****/ - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_Calc_Used_Bits -* Inputs: Power of 2 number -* Outputs: Number of Used Bits -* 0, if the argument is 0 -* Description: Calculate the number of bits used by a given power of 2 number -* Number can be up to 32 bit -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int GLOB_Calc_Used_Bits(u32 n) -{ - int tot_bits = 0; - - if (n >= 1 << 16) { - n >>= 16; - tot_bits += 16; - } - - if (n >= 1 << 8) { - n >>= 8; - tot_bits += 8; - } - - if (n >= 1 << 4) { - n >>= 4; - tot_bits += 4; - } - - if (n >= 1 << 2) { - n >>= 2; - tot_bits += 2; - } - - if (n >= 1 << 1) - tot_bits += 1; - - return ((n == 0) ? (0) : tot_bits); -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_u64_Div -* Inputs: Number of u64 -* A power of 2 number as Division -* Outputs: Quotient of the Divisor operation -* Description: It divides the address by divisor by using bit shift operation -* (essentially without explicitely using "/"). -* Divisor is a power of 2 number and Divided is of u64 -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u64 GLOB_u64_Div(u64 addr, u32 divisor) -{ - return (u64)(addr >> GLOB_Calc_Used_Bits(divisor)); -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_u64_Remainder -* Inputs: Number of u64 -* Divisor Type (1 -PageAddress, 2- BlockAddress) -* Outputs: Remainder of the Division operation -* Description: It calculates the remainder of a number (of u64) by -* divisor(power of 2 number ) by using bit shifting and multiply -* operation(essentially without explicitely using "/"). -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u64 GLOB_u64_Remainder(u64 addr, u32 divisor_type) -{ - u64 result = 0; - - if (divisor_type == 1) { /* Remainder -- Page */ - result = (addr >> DeviceInfo.nBitsInPageDataSize); - result = result * DeviceInfo.wPageDataSize; - } else if (divisor_type == 2) { /* Remainder -- Block */ - result = (addr >> DeviceInfo.nBitsInBlockDataSize); - result = result * DeviceInfo.wBlockDataSize; - } - - result = addr - result; - - return result; -} - -#define NUM_DEVICES 1 -#define PARTITIONS 8 - -#define GLOB_SBD_NAME "nd" -#define GLOB_SBD_IRQ_NUM (29) - -#define GLOB_SBD_IOCTL_GC (0x7701) -#define GLOB_SBD_IOCTL_WL (0x7702) -#define GLOB_SBD_IOCTL_FORMAT (0x7703) -#define GLOB_SBD_IOCTL_ERASE_FLASH (0x7704) -#define GLOB_SBD_IOCTL_FLUSH_CACHE (0x7705) -#define GLOB_SBD_IOCTL_COPY_BLK_TABLE (0x7706) -#define GLOB_SBD_IOCTL_COPY_WEAR_LEVELING_TABLE (0x7707) -#define GLOB_SBD_IOCTL_GET_NAND_INFO (0x7708) -#define GLOB_SBD_IOCTL_WRITE_DATA (0x7709) -#define GLOB_SBD_IOCTL_READ_DATA (0x770A) - -static int reserved_mb = 0; -module_param(reserved_mb, int, 0); -MODULE_PARM_DESC(reserved_mb, "Reserved space for OS image, in MiB (default 25 MiB)"); - -int nand_debug_level; -module_param(nand_debug_level, int, 0644); -MODULE_PARM_DESC(nand_debug_level, "debug level value: 1-3"); - -MODULE_LICENSE("GPL"); - -struct spectra_nand_dev { - struct pci_dev *dev; - u64 size; - u16 users; - spinlock_t qlock; - void __iomem *ioaddr; /* Mapped address */ - struct request_queue *queue; - struct task_struct *thread; - struct gendisk *gd; - u8 *tmp_buf; -}; - - -static int GLOB_SBD_majornum; - -static char *GLOB_version = GLOB_VERSION; - -static struct spectra_nand_dev nand_device[NUM_DEVICES]; - -static struct mutex spectra_lock; - -static int res_blks_os = 1; - -struct spectra_indentfy_dev_tag IdentifyDeviceData; - -static int force_flush_cache(void) -{ - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (ERR == GLOB_FTL_Flush_Cache()) { - printk(KERN_ERR "Fail to Flush FTL Cache!\n"); - return -EFAULT; - } -#if CMD_DMA - if (glob_ftl_execute_cmds()) - return -EIO; - else - return 0; -#endif - return 0; -} - -struct ioctl_rw_page_info { - u8 *data; - unsigned int page; -}; - -static int ioctl_read_page_data(unsigned long arg) -{ - u8 *buf; - struct ioctl_rw_page_info info; - int result = PASS; - - if (copy_from_user(&info, (void __user *)arg, sizeof(info))) - return -EFAULT; - - buf = kmalloc(IdentifyDeviceData.PageDataSize, GFP_ATOMIC); - if (!buf) { - printk(KERN_ERR "ioctl_read_page_data: " - "failed to allocate memory\n"); - return -ENOMEM; - } - - mutex_lock(&spectra_lock); - result = GLOB_FTL_Page_Read(buf, - (u64)info.page * IdentifyDeviceData.PageDataSize); - mutex_unlock(&spectra_lock); - - if (copy_to_user((void __user *)info.data, buf, - IdentifyDeviceData.PageDataSize)) { - printk(KERN_ERR "ioctl_read_page_data: " - "failed to copy user data\n"); - kfree(buf); - return -EFAULT; - } - - kfree(buf); - return result; -} - -static int ioctl_write_page_data(unsigned long arg) -{ - u8 *buf; - struct ioctl_rw_page_info info; - int result = PASS; - - if (copy_from_user(&info, (void __user *)arg, sizeof(info))) - return -EFAULT; - - buf = memdup_user((void __user *)info.data, - IdentifyDeviceData.PageDataSize); - if (IS_ERR(buf)) { - printk(KERN_ERR "ioctl_write_page_data: " - "failed to copy user data\n"); - return PTR_ERR(buf); - } - - mutex_lock(&spectra_lock); - result = GLOB_FTL_Page_Write(buf, - (u64)info.page * IdentifyDeviceData.PageDataSize); - mutex_unlock(&spectra_lock); - - kfree(buf); - return result; -} - -/* Return how many blocks should be reserved for bad block replacement */ -static int get_res_blk_num_bad_blk(void) -{ - return IdentifyDeviceData.wDataBlockNum / 10; -} - -/* Return how many blocks should be reserved for OS image */ -static int get_res_blk_num_os(void) -{ - u32 res_blks, blk_size; - - blk_size = IdentifyDeviceData.PageDataSize * - IdentifyDeviceData.PagesPerBlock; - - res_blks = (reserved_mb * 1024 * 1024) / blk_size; - - if ((res_blks < 1) || (res_blks >= IdentifyDeviceData.wDataBlockNum)) - res_blks = 1; /* Reserved 1 block for block table */ - - return res_blks; -} - -/* Transfer a full request. */ -static int do_transfer(struct spectra_nand_dev *tr, struct request *req) -{ - u64 start_addr, addr; - u32 logical_start_sect, hd_start_sect; - u32 nsect, hd_sects; - u32 rsect, tsect = 0; - char *buf; - u32 ratio = IdentifyDeviceData.PageDataSize >> 9; - - start_addr = (u64)(blk_rq_pos(req)) << 9; - /* Add a big enough offset to prevent the OS Image from - * being accessed or damaged by file system */ - start_addr += IdentifyDeviceData.PageDataSize * - IdentifyDeviceData.PagesPerBlock * - res_blks_os; - - if (req->cmd_type & REQ_FLUSH) { - if (force_flush_cache()) /* Fail to flush cache */ - return -EIO; - else - return 0; - } - - if (req->cmd_type != REQ_TYPE_FS) - return -EIO; - - if (blk_rq_pos(req) + blk_rq_cur_sectors(req) > get_capacity(tr->gd)) { - printk(KERN_ERR "Spectra error: request over the NAND " - "capacity!sector %d, current_nr_sectors %d, " - "while capacity is %d\n", - (int)blk_rq_pos(req), - blk_rq_cur_sectors(req), - (int)get_capacity(tr->gd)); - return -EIO; - } - - logical_start_sect = start_addr >> 9; - hd_start_sect = logical_start_sect / ratio; - rsect = logical_start_sect - hd_start_sect * ratio; - - addr = (u64)hd_start_sect * ratio * 512; - buf = req->buffer; - nsect = blk_rq_cur_sectors(req); - - if (rsect) - tsect = (ratio - rsect) < nsect ? (ratio - rsect) : nsect; - - switch (rq_data_dir(req)) { - case READ: - /* Read the first NAND page */ - if (rsect) { - if (GLOB_FTL_Page_Read(tr->tmp_buf, addr)) { - printk(KERN_ERR "Error in %s, Line %d\n", - __FILE__, __LINE__); - return -EIO; - } - memcpy(buf, tr->tmp_buf + (rsect << 9), tsect << 9); - addr += IdentifyDeviceData.PageDataSize; - buf += tsect << 9; - nsect -= tsect; - } - - /* Read the other NAND pages */ - for (hd_sects = nsect / ratio; hd_sects > 0; hd_sects--) { - if (GLOB_FTL_Page_Read(buf, addr)) { - printk(KERN_ERR "Error in %s, Line %d\n", - __FILE__, __LINE__); - return -EIO; - } - addr += IdentifyDeviceData.PageDataSize; - buf += IdentifyDeviceData.PageDataSize; - } - - /* Read the last NAND pages */ - if (nsect % ratio) { - if (GLOB_FTL_Page_Read(tr->tmp_buf, addr)) { - printk(KERN_ERR "Error in %s, Line %d\n", - __FILE__, __LINE__); - return -EIO; - } - memcpy(buf, tr->tmp_buf, (nsect % ratio) << 9); - } -#if CMD_DMA - if (glob_ftl_execute_cmds()) - return -EIO; - else - return 0; -#endif - return 0; - - case WRITE: - /* Write the first NAND page */ - if (rsect) { - if (GLOB_FTL_Page_Read(tr->tmp_buf, addr)) { - printk(KERN_ERR "Error in %s, Line %d\n", - __FILE__, __LINE__); - return -EIO; - } - memcpy(tr->tmp_buf + (rsect << 9), buf, tsect << 9); - if (GLOB_FTL_Page_Write(tr->tmp_buf, addr)) { - printk(KERN_ERR "Error in %s, Line %d\n", - __FILE__, __LINE__); - return -EIO; - } - addr += IdentifyDeviceData.PageDataSize; - buf += tsect << 9; - nsect -= tsect; - } - - /* Write the other NAND pages */ - for (hd_sects = nsect / ratio; hd_sects > 0; hd_sects--) { - if (GLOB_FTL_Page_Write(buf, addr)) { - printk(KERN_ERR "Error in %s, Line %d\n", - __FILE__, __LINE__); - return -EIO; - } - addr += IdentifyDeviceData.PageDataSize; - buf += IdentifyDeviceData.PageDataSize; - } - - /* Write the last NAND pages */ - if (nsect % ratio) { - if (GLOB_FTL_Page_Read(tr->tmp_buf, addr)) { - printk(KERN_ERR "Error in %s, Line %d\n", - __FILE__, __LINE__); - return -EIO; - } - memcpy(tr->tmp_buf, buf, (nsect % ratio) << 9); - if (GLOB_FTL_Page_Write(tr->tmp_buf, addr)) { - printk(KERN_ERR "Error in %s, Line %d\n", - __FILE__, __LINE__); - return -EIO; - } - } -#if CMD_DMA - if (glob_ftl_execute_cmds()) - return -EIO; - else - return 0; -#endif - return 0; - - default: - printk(KERN_NOTICE "Unknown request %u\n", rq_data_dir(req)); - return -EIO; - } -} - -/* This function is copied from drivers/mtd/mtd_blkdevs.c */ -static int spectra_trans_thread(void *arg) -{ - struct spectra_nand_dev *tr = arg; - struct request_queue *rq = tr->queue; - struct request *req = NULL; - - /* we might get involved when memory gets low, so use PF_MEMALLOC */ - current->flags |= PF_MEMALLOC; - - spin_lock_irq(rq->queue_lock); - while (!kthread_should_stop()) { - int res; - - if (!req) { - req = blk_fetch_request(rq); - if (!req) { - set_current_state(TASK_INTERRUPTIBLE); - spin_unlock_irq(rq->queue_lock); - schedule(); - spin_lock_irq(rq->queue_lock); - continue; - } - } - - spin_unlock_irq(rq->queue_lock); - - mutex_lock(&spectra_lock); - res = do_transfer(tr, req); - mutex_unlock(&spectra_lock); - - spin_lock_irq(rq->queue_lock); - - if (!__blk_end_request_cur(req, res)) - req = NULL; - } - - if (req) - __blk_end_request_all(req, -EIO); - - spin_unlock_irq(rq->queue_lock); - - return 0; -} - - -/* Request function that "handles clustering". */ -static void GLOB_SBD_request(struct request_queue *rq) -{ - struct spectra_nand_dev *pdev = rq->queuedata; - wake_up_process(pdev->thread); -} - -static int GLOB_SBD_open(struct block_device *bdev, fmode_t mode) - -{ - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - return 0; -} - -static int GLOB_SBD_release(struct gendisk *disk, fmode_t mode) -{ - int ret; - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - mutex_lock(&spectra_lock); - ret = force_flush_cache(); - mutex_unlock(&spectra_lock); - - return 0; -} - -static int GLOB_SBD_getgeo(struct block_device *bdev, struct hd_geometry *geo) -{ - geo->heads = 4; - geo->sectors = 16; - geo->cylinders = get_capacity(bdev->bd_disk) / (4 * 16); - - nand_dbg_print(NAND_DBG_DEBUG, - "heads: %d, sectors: %d, cylinders: %d\n", - geo->heads, geo->sectors, geo->cylinders); - - return 0; -} - -int GLOB_SBD_ioctl(struct block_device *bdev, fmode_t mode, - unsigned int cmd, unsigned long arg) -{ - int ret; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - switch (cmd) { - case GLOB_SBD_IOCTL_GC: - nand_dbg_print(NAND_DBG_DEBUG, - "Spectra IOCTL: Garbage Collection " - "being performed\n"); - if (PASS != GLOB_FTL_Garbage_Collection()) - return -EFAULT; - return 0; - - case GLOB_SBD_IOCTL_WL: - nand_dbg_print(NAND_DBG_DEBUG, - "Spectra IOCTL: Static Wear Leveling " - "being performed\n"); - if (PASS != GLOB_FTL_Wear_Leveling()) - return -EFAULT; - return 0; - - case GLOB_SBD_IOCTL_FORMAT: - nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: Flash format " - "being performed\n"); - if (PASS != GLOB_FTL_Flash_Format()) - return -EFAULT; - return 0; - - case GLOB_SBD_IOCTL_FLUSH_CACHE: - nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: Cache flush " - "being performed\n"); - mutex_lock(&spectra_lock); - ret = force_flush_cache(); - mutex_unlock(&spectra_lock); - return ret; - - case GLOB_SBD_IOCTL_COPY_BLK_TABLE: - nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: " - "Copy block table\n"); - if (copy_to_user((void __user *)arg, - get_blk_table_start_addr(), - get_blk_table_len())) - return -EFAULT; - return 0; - - case GLOB_SBD_IOCTL_COPY_WEAR_LEVELING_TABLE: - nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: " - "Copy wear leveling table\n"); - if (copy_to_user((void __user *)arg, - get_wear_leveling_table_start_addr(), - get_wear_leveling_table_len())) - return -EFAULT; - return 0; - - case GLOB_SBD_IOCTL_GET_NAND_INFO: - nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: " - "Get NAND info\n"); - if (copy_to_user((void __user *)arg, &IdentifyDeviceData, - sizeof(IdentifyDeviceData))) - return -EFAULT; - return 0; - - case GLOB_SBD_IOCTL_WRITE_DATA: - nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: " - "Write one page data\n"); - return ioctl_write_page_data(arg); - - case GLOB_SBD_IOCTL_READ_DATA: - nand_dbg_print(NAND_DBG_DEBUG, "Spectra IOCTL: " - "Read one page data\n"); - return ioctl_read_page_data(arg); - } - - return -ENOTTY; -} - -static DEFINE_MUTEX(ffsport_mutex); - -int GLOB_SBD_unlocked_ioctl(struct block_device *bdev, fmode_t mode, - unsigned int cmd, unsigned long arg) -{ - int ret; - - mutex_lock(&ffsport_mutex); - ret = GLOB_SBD_ioctl(bdev, mode, cmd, arg); - mutex_unlock(&ffsport_mutex); - - return ret; -} - -static struct block_device_operations GLOB_SBD_ops = { - .owner = THIS_MODULE, - .open = GLOB_SBD_open, - .release = GLOB_SBD_release, - .ioctl = GLOB_SBD_unlocked_ioctl, - .getgeo = GLOB_SBD_getgeo, -}; - -static int SBD_setup_device(struct spectra_nand_dev *dev, int which) -{ - int res_blks; - u32 sects; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - memset(dev, 0, sizeof(struct spectra_nand_dev)); - - nand_dbg_print(NAND_DBG_WARN, "Reserved %d blocks " - "for OS image, %d blocks for bad block replacement.\n", - get_res_blk_num_os(), - get_res_blk_num_bad_blk()); - - res_blks = get_res_blk_num_bad_blk() + get_res_blk_num_os(); - - dev->size = (u64)IdentifyDeviceData.PageDataSize * - IdentifyDeviceData.PagesPerBlock * - (IdentifyDeviceData.wDataBlockNum - res_blks); - - res_blks_os = get_res_blk_num_os(); - - spin_lock_init(&dev->qlock); - - dev->tmp_buf = kmalloc(IdentifyDeviceData.PageDataSize, GFP_ATOMIC); - if (!dev->tmp_buf) { - printk(KERN_ERR "Failed to kmalloc memory in %s Line %d, exit.\n", - __FILE__, __LINE__); - goto out_vfree; - } - - dev->queue = blk_init_queue(GLOB_SBD_request, &dev->qlock); - if (dev->queue == NULL) { - printk(KERN_ERR - "Spectra: Request queue could not be initialized." - " Aborting\n "); - goto out_vfree; - } - dev->queue->queuedata = dev; - - /* As Linux block layer doesn't support >4KB hardware sector, */ - /* Here we force report 512 byte hardware sector size to Kernel */ - blk_queue_logical_block_size(dev->queue, 512); - - blk_queue_flush(dev->queue, REQ_FLUSH); - - dev->thread = kthread_run(spectra_trans_thread, dev, "nand_thd"); - if (IS_ERR(dev->thread)) { - blk_cleanup_queue(dev->queue); - unregister_blkdev(GLOB_SBD_majornum, GLOB_SBD_NAME); - return PTR_ERR(dev->thread); - } - - dev->gd = alloc_disk(PARTITIONS); - if (!dev->gd) { - printk(KERN_ERR - "Spectra: Could not allocate disk. Aborting \n "); - goto out_vfree; - } - dev->gd->major = GLOB_SBD_majornum; - dev->gd->first_minor = which * PARTITIONS; - dev->gd->fops = &GLOB_SBD_ops; - dev->gd->queue = dev->queue; - dev->gd->private_data = dev; - snprintf(dev->gd->disk_name, 32, "%s%c", GLOB_SBD_NAME, which + 'a'); - - sects = dev->size >> 9; - nand_dbg_print(NAND_DBG_WARN, "Capacity sects: %d\n", sects); - set_capacity(dev->gd, sects); - - add_disk(dev->gd); - - return 0; -out_vfree: - return -ENOMEM; -} - -/* -static ssize_t show_nand_block_num(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", - (int)IdentifyDeviceData.wDataBlockNum); -} - -static ssize_t show_nand_pages_per_block(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", - (int)IdentifyDeviceData.PagesPerBlock); -} - -static ssize_t show_nand_page_size(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", - (int)IdentifyDeviceData.PageDataSize); -} - -static DEVICE_ATTR(nand_block_num, 0444, show_nand_block_num, NULL); -static DEVICE_ATTR(nand_pages_per_block, 0444, show_nand_pages_per_block, NULL); -static DEVICE_ATTR(nand_page_size, 0444, show_nand_page_size, NULL); - -static void create_sysfs_entry(struct device *dev) -{ - if (device_create_file(dev, &dev_attr_nand_block_num)) - printk(KERN_ERR "Spectra: " - "failed to create sysfs entry nand_block_num.\n"); - if (device_create_file(dev, &dev_attr_nand_pages_per_block)) - printk(KERN_ERR "Spectra: " - "failed to create sysfs entry nand_pages_per_block.\n"); - if (device_create_file(dev, &dev_attr_nand_page_size)) - printk(KERN_ERR "Spectra: " - "failed to create sysfs entry nand_page_size.\n"); -} -*/ - -static void register_spectra_ftl_async(void *unused, async_cookie_t cookie) -{ - int i; - - /* create_sysfs_entry(&dev->dev); */ - - if (PASS != GLOB_FTL_IdentifyDevice(&IdentifyDeviceData)) { - printk(KERN_ERR "Spectra: Unable to Read Flash Device. " - "Aborting\n"); - return; - } else { - nand_dbg_print(NAND_DBG_WARN, "In GLOB_SBD_init: " - "Num blocks=%d, pagesperblock=%d, " - "pagedatasize=%d, ECCBytesPerSector=%d\n", - (int)IdentifyDeviceData.NumBlocks, - (int)IdentifyDeviceData.PagesPerBlock, - (int)IdentifyDeviceData.PageDataSize, - (int)IdentifyDeviceData.wECCBytesPerSector); - } - - printk(KERN_ALERT "Spectra: searching block table, please wait ...\n"); - if (GLOB_FTL_Init() != PASS) { - printk(KERN_ERR "Spectra: Unable to Initialize FTL Layer. " - "Aborting\n"); - goto out_ftl_flash_register; - } - printk(KERN_ALERT "Spectra: block table has been found.\n"); - - GLOB_SBD_majornum = register_blkdev(0, GLOB_SBD_NAME); - if (GLOB_SBD_majornum <= 0) { - printk(KERN_ERR "Unable to get the major %d for Spectra", - GLOB_SBD_majornum); - goto out_ftl_flash_register; - } - - for (i = 0; i < NUM_DEVICES; i++) - if (SBD_setup_device(&nand_device[i], i) == -ENOMEM) - goto out_blk_register; - - nand_dbg_print(NAND_DBG_DEBUG, - "Spectra: module loaded with major number %d\n", - GLOB_SBD_majornum); - - return; - -out_blk_register: - unregister_blkdev(GLOB_SBD_majornum, GLOB_SBD_NAME); -out_ftl_flash_register: - GLOB_FTL_Cache_Release(); - printk(KERN_ERR "Spectra: Module load failed.\n"); -} - -int register_spectra_ftl() -{ - async_schedule(register_spectra_ftl_async, NULL); - return 0; -} -EXPORT_SYMBOL_GPL(register_spectra_ftl); - -static int GLOB_SBD_init(void) -{ - /* Set debug output level (0~3) here. 3 is most verbose */ - printk(KERN_ALERT "Spectra: %s\n", GLOB_version); - - mutex_init(&spectra_lock); - - if (PASS != GLOB_FTL_Flash_Init()) { - printk(KERN_ERR "Spectra: Unable to Initialize Flash Device. " - "Aborting\n"); - return -ENODEV; - } - return 0; -} - -static void __exit GLOB_SBD_exit(void) -{ - int i; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - for (i = 0; i < NUM_DEVICES; i++) { - struct spectra_nand_dev *dev = &nand_device[i]; - if (dev->gd) { - del_gendisk(dev->gd); - put_disk(dev->gd); - } - if (dev->queue) - blk_cleanup_queue(dev->queue); - kfree(dev->tmp_buf); - } - - unregister_blkdev(GLOB_SBD_majornum, GLOB_SBD_NAME); - - mutex_lock(&spectra_lock); - force_flush_cache(); - mutex_unlock(&spectra_lock); - - GLOB_FTL_Cache_Release(); - - GLOB_FTL_Flash_Release(); - - nand_dbg_print(NAND_DBG_DEBUG, - "Spectra FTL module (major number %d) unloaded.\n", - GLOB_SBD_majornum); -} - -module_init(GLOB_SBD_init); -module_exit(GLOB_SBD_exit); diff --git a/drivers/staging/spectra/ffsport.h b/drivers/staging/spectra/ffsport.h deleted file mode 100644 index 85c0750612f6..000000000000 --- a/drivers/staging/spectra/ffsport.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef _FFSPORT_ -#define _FFSPORT_ - -#include "ffsdefs.h" - -#if defined __GNUC__ -#define PACKED -#define PACKED_GNU __attribute__ ((packed)) -#define UNALIGNED -#endif - -#include -#include /* for strcpy(), stricmp(), etc */ -#include /* for kmalloc(), kfree() */ -#include -#include -#include -#include - -#include /* printk() */ -#include /* everything... */ -#include /* error codes */ -#include /* size_t */ -#include -#include -#include -#include -#include "flash.h" - -#define VERBOSE 1 - -#define NAND_DBG_WARN 1 -#define NAND_DBG_DEBUG 2 -#define NAND_DBG_TRACE 3 - -extern int nand_debug_level; - -#ifdef VERBOSE -#define nand_dbg_print(level, args...) \ - do { \ - if (level <= nand_debug_level) \ - printk(KERN_ALERT args); \ - } while (0) -#else -#define nand_dbg_print(level, args...) -#endif - -#ifdef SUPPORT_BIG_ENDIAN -#define INVERTUINT16(w) ((u16)(((u16)(w)) << 8) | \ - (u16)((u16)(w) >> 8)) - -#define INVERTUINT32(dw) (((u32)(dw) << 24) | \ - (((u32)(dw) << 8) & 0x00ff0000) | \ - (((u32)(dw) >> 8) & 0x0000ff00) | \ - ((u32)(dw) >> 24)) -#else -#define INVERTUINT16(w) w -#define INVERTUINT32(dw) dw -#endif - -extern int GLOB_Calc_Used_Bits(u32 n); -extern u64 GLOB_u64_Div(u64 addr, u32 divisor); -extern u64 GLOB_u64_Remainder(u64 addr, u32 divisor_type); -extern int register_spectra_ftl(void); - -#endif /* _FFSPORT_ */ diff --git a/drivers/staging/spectra/flash.c b/drivers/staging/spectra/flash.c deleted file mode 100644 index aead358e5c2a..000000000000 --- a/drivers/staging/spectra/flash.c +++ /dev/null @@ -1,4305 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include -#include - -#include "flash.h" -#include "ffsdefs.h" -#include "lld.h" -#include "lld_nand.h" -#if CMD_DMA -#include "lld_cdma.h" -#endif - -#define BLK_FROM_ADDR(addr) ((u32)(addr >> DeviceInfo.nBitsInBlockDataSize)) -#define PAGE_FROM_ADDR(addr, Block) ((u16)((addr - (u64)Block * \ - DeviceInfo.wBlockDataSize) >> DeviceInfo.nBitsInPageDataSize)) - -#define IS_SPARE_BLOCK(blk) (BAD_BLOCK != (pbt[blk] &\ - BAD_BLOCK) && SPARE_BLOCK == (pbt[blk] & SPARE_BLOCK)) - -#define IS_DATA_BLOCK(blk) (0 == (pbt[blk] & BAD_BLOCK)) - -#define IS_DISCARDED_BLOCK(blk) (BAD_BLOCK != (pbt[blk] &\ - BAD_BLOCK) && DISCARD_BLOCK == (pbt[blk] & DISCARD_BLOCK)) - -#define IS_BAD_BLOCK(blk) (BAD_BLOCK == (pbt[blk] & BAD_BLOCK)) - -#if DEBUG_BNDRY -void debug_boundary_lineno_error(int chnl, int limit, int no, - int lineno, char *filename) -{ - if (chnl >= limit) - printk(KERN_ERR "Boundary Check Fail value %d >= limit %d, " - "at %s:%d. Other info:%d. Aborting...\n", - chnl, limit, filename, lineno, no); -} -/* static int globalmemsize; */ -#endif - -static u16 FTL_Cache_If_Hit(u64 dwPageAddr); -static int FTL_Cache_Read(u64 dwPageAddr); -static void FTL_Cache_Read_Page(u8 *pData, u64 dwPageAddr, - u16 cache_blk); -static void FTL_Cache_Write_Page(u8 *pData, u64 dwPageAddr, - u8 cache_blk, u16 flag); -static int FTL_Cache_Write(void); -static void FTL_Calculate_LRU(void); -static u32 FTL_Get_Block_Index(u32 wBlockNum); - -static int FTL_Search_Block_Table_IN_Block(u32 BT_Block, - u8 BT_Tag, u16 *Page); -static int FTL_Read_Block_Table(void); -static int FTL_Write_Block_Table(int wForce); -static int FTL_Write_Block_Table_Data(void); -static int FTL_Check_Block_Table(int wOldTable); -static int FTL_Static_Wear_Leveling(void); -static u32 FTL_Replace_Block_Table(void); -static int FTL_Write_IN_Progress_Block_Table_Page(void); - -static u32 FTL_Get_Page_Num(u64 length); -static u64 FTL_Get_Physical_Block_Addr(u64 blk_addr); - -static u32 FTL_Replace_OneBlock(u32 wBlockNum, - u32 wReplaceNum); -static u32 FTL_Replace_LWBlock(u32 wBlockNum, - int *pGarbageCollect); -static u32 FTL_Replace_MWBlock(void); -static int FTL_Replace_Block(u64 blk_addr); -static int FTL_Adjust_Relative_Erase_Count(u32 Index_of_MAX); - -struct device_info_tag DeviceInfo; -struct flash_cache_tag Cache; -static struct spectra_l2_cache_info cache_l2; - -static u8 *cache_l2_page_buf; -static u8 *cache_l2_blk_buf; - -u8 *g_pBlockTable; -u8 *g_pWearCounter; -u16 *g_pReadCounter; -u32 *g_pBTBlocks; -static u16 g_wBlockTableOffset; -static u32 g_wBlockTableIndex; -static u8 g_cBlockTableStatus; - -static u8 *g_pTempBuf; -static u8 *flag_check_blk_table; -static u8 *tmp_buf_search_bt_in_block; -static u8 *spare_buf_search_bt_in_block; -static u8 *spare_buf_bt_search_bt_in_block; -static u8 *tmp_buf1_read_blk_table; -static u8 *tmp_buf2_read_blk_table; -static u8 *flags_static_wear_leveling; -static u8 *tmp_buf_write_blk_table_data; -static u8 *tmp_buf_read_disturbance; - -u8 *buf_read_page_main_spare; -u8 *buf_write_page_main_spare; -u8 *buf_read_page_spare; -u8 *buf_get_bad_block; - -#if (RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE && CMD_DMA) -struct flash_cache_delta_list_tag int_cache[MAX_CHANS + MAX_DESCS]; -struct flash_cache_tag cache_start_copy; -#endif - -int g_wNumFreeBlocks; -u8 g_SBDCmdIndex; - -static u8 *g_pIPF; -static u8 bt_flag = FIRST_BT_ID; -static u8 bt_block_changed; - -static u16 cache_block_to_write; -static u8 last_erased = FIRST_BT_ID; - -static u8 GC_Called; -static u8 BT_GC_Called; - -#if CMD_DMA -#define COPY_BACK_BUF_NUM 10 - -static u8 ftl_cmd_cnt; /* Init value is 0 */ -u8 *g_pBTDelta; -u8 *g_pBTDelta_Free; -u8 *g_pBTStartingCopy; -u8 *g_pWearCounterCopy; -u16 *g_pReadCounterCopy; -u8 *g_pBlockTableCopies; -u8 *g_pNextBlockTable; -static u8 *cp_back_buf_copies[COPY_BACK_BUF_NUM]; -static int cp_back_buf_idx; - -static u8 *g_temp_buf; - -#pragma pack(push, 1) -#pragma pack(1) -struct BTableChangesDelta { - u8 ftl_cmd_cnt; - u8 ValidFields; - u16 g_wBlockTableOffset; - u32 g_wBlockTableIndex; - u32 BT_Index; - u32 BT_Entry_Value; - u32 WC_Index; - u8 WC_Entry_Value; - u32 RC_Index; - u16 RC_Entry_Value; -}; - -#pragma pack(pop) - -struct BTableChangesDelta *p_BTableChangesDelta; -#endif - - -#define MARK_BLOCK_AS_BAD(blocknode) (blocknode |= BAD_BLOCK) -#define MARK_BLK_AS_DISCARD(blk) (blk = (blk & ~SPARE_BLOCK) | DISCARD_BLOCK) - -#define FTL_Get_LBAPBA_Table_Mem_Size_Bytes() (DeviceInfo.wDataBlockNum *\ - sizeof(u32)) -#define FTL_Get_WearCounter_Table_Mem_Size_Bytes() (DeviceInfo.wDataBlockNum *\ - sizeof(u8)) -#define FTL_Get_ReadCounter_Table_Mem_Size_Bytes() (DeviceInfo.wDataBlockNum *\ - sizeof(u16)) -#if SUPPORT_LARGE_BLOCKNUM -#define FTL_Get_LBAPBA_Table_Flash_Size_Bytes() (DeviceInfo.wDataBlockNum *\ - sizeof(u8) * 3) -#else -#define FTL_Get_LBAPBA_Table_Flash_Size_Bytes() (DeviceInfo.wDataBlockNum *\ - sizeof(u16)) -#endif -#define FTL_Get_WearCounter_Table_Flash_Size_Bytes \ - FTL_Get_WearCounter_Table_Mem_Size_Bytes -#define FTL_Get_ReadCounter_Table_Flash_Size_Bytes \ - FTL_Get_ReadCounter_Table_Mem_Size_Bytes - -static u32 FTL_Get_Block_Table_Flash_Size_Bytes(void) -{ - u32 byte_num; - - if (DeviceInfo.MLCDevice) { - byte_num = FTL_Get_LBAPBA_Table_Flash_Size_Bytes() + - DeviceInfo.wDataBlockNum * sizeof(u8) + - DeviceInfo.wDataBlockNum * sizeof(u16); - } else { - byte_num = FTL_Get_LBAPBA_Table_Flash_Size_Bytes() + - DeviceInfo.wDataBlockNum * sizeof(u8); - } - - byte_num += 4 * sizeof(u8); - - return byte_num; -} - -static u16 FTL_Get_Block_Table_Flash_Size_Pages(void) -{ - return (u16)FTL_Get_Page_Num(FTL_Get_Block_Table_Flash_Size_Bytes()); -} - -static int FTL_Copy_Block_Table_To_Flash(u8 *flashBuf, u32 sizeToTx, - u32 sizeTxed) -{ - u32 wBytesCopied, blk_tbl_size, wBytes; - u32 *pbt = (u32 *)g_pBlockTable; - - blk_tbl_size = FTL_Get_LBAPBA_Table_Flash_Size_Bytes(); - for (wBytes = 0; - (wBytes < sizeToTx) && ((wBytes + sizeTxed) < blk_tbl_size); - wBytes++) { -#if SUPPORT_LARGE_BLOCKNUM - flashBuf[wBytes] = (u8)(pbt[(wBytes + sizeTxed) / 3] - >> (((wBytes + sizeTxed) % 3) ? - ((((wBytes + sizeTxed) % 3) == 2) ? 0 : 8) : 16)) & 0xFF; -#else - flashBuf[wBytes] = (u8)(pbt[(wBytes + sizeTxed) / 2] - >> (((wBytes + sizeTxed) % 2) ? 0 : 8)) & 0xFF; -#endif - } - - sizeTxed = (sizeTxed > blk_tbl_size) ? (sizeTxed - blk_tbl_size) : 0; - blk_tbl_size = FTL_Get_WearCounter_Table_Flash_Size_Bytes(); - wBytesCopied = wBytes; - wBytes = ((blk_tbl_size - sizeTxed) > (sizeToTx - wBytesCopied)) ? - (sizeToTx - wBytesCopied) : (blk_tbl_size - sizeTxed); - memcpy(flashBuf + wBytesCopied, g_pWearCounter + sizeTxed, wBytes); - - sizeTxed = (sizeTxed > blk_tbl_size) ? (sizeTxed - blk_tbl_size) : 0; - - if (DeviceInfo.MLCDevice) { - blk_tbl_size = FTL_Get_ReadCounter_Table_Flash_Size_Bytes(); - wBytesCopied += wBytes; - for (wBytes = 0; ((wBytes + wBytesCopied) < sizeToTx) && - ((wBytes + sizeTxed) < blk_tbl_size); wBytes++) - flashBuf[wBytes + wBytesCopied] = - (g_pReadCounter[(wBytes + sizeTxed) / 2] >> - (((wBytes + sizeTxed) % 2) ? 0 : 8)) & 0xFF; - } - - return wBytesCopied + wBytes; -} - -static int FTL_Copy_Block_Table_From_Flash(u8 *flashBuf, - u32 sizeToTx, u32 sizeTxed) -{ - u32 wBytesCopied, blk_tbl_size, wBytes; - u32 *pbt = (u32 *)g_pBlockTable; - - blk_tbl_size = FTL_Get_LBAPBA_Table_Flash_Size_Bytes(); - for (wBytes = 0; (wBytes < sizeToTx) && - ((wBytes + sizeTxed) < blk_tbl_size); wBytes++) { -#if SUPPORT_LARGE_BLOCKNUM - if (!((wBytes + sizeTxed) % 3)) - pbt[(wBytes + sizeTxed) / 3] = 0; - pbt[(wBytes + sizeTxed) / 3] |= - (flashBuf[wBytes] << (((wBytes + sizeTxed) % 3) ? - ((((wBytes + sizeTxed) % 3) == 2) ? 0 : 8) : 16)); -#else - if (!((wBytes + sizeTxed) % 2)) - pbt[(wBytes + sizeTxed) / 2] = 0; - pbt[(wBytes + sizeTxed) / 2] |= - (flashBuf[wBytes] << (((wBytes + sizeTxed) % 2) ? - 0 : 8)); -#endif - } - - sizeTxed = (sizeTxed > blk_tbl_size) ? (sizeTxed - blk_tbl_size) : 0; - blk_tbl_size = FTL_Get_WearCounter_Table_Flash_Size_Bytes(); - wBytesCopied = wBytes; - wBytes = ((blk_tbl_size - sizeTxed) > (sizeToTx - wBytesCopied)) ? - (sizeToTx - wBytesCopied) : (blk_tbl_size - sizeTxed); - memcpy(g_pWearCounter + sizeTxed, flashBuf + wBytesCopied, wBytes); - sizeTxed = (sizeTxed > blk_tbl_size) ? (sizeTxed - blk_tbl_size) : 0; - - if (DeviceInfo.MLCDevice) { - wBytesCopied += wBytes; - blk_tbl_size = FTL_Get_ReadCounter_Table_Flash_Size_Bytes(); - for (wBytes = 0; ((wBytes + wBytesCopied) < sizeToTx) && - ((wBytes + sizeTxed) < blk_tbl_size); wBytes++) { - if (((wBytes + sizeTxed) % 2)) - g_pReadCounter[(wBytes + sizeTxed) / 2] = 0; - g_pReadCounter[(wBytes + sizeTxed) / 2] |= - (flashBuf[wBytes] << - (((wBytes + sizeTxed) % 2) ? 0 : 8)); - } - } - - return wBytesCopied+wBytes; -} - -static int FTL_Insert_Block_Table_Signature(u8 *buf, u8 tag) -{ - int i; - - for (i = 0; i < BTSIG_BYTES; i++) - buf[BTSIG_OFFSET + i] = - ((tag + (i * BTSIG_DELTA) - FIRST_BT_ID) % - (1 + LAST_BT_ID-FIRST_BT_ID)) + FIRST_BT_ID; - - return PASS; -} - -static int FTL_Extract_Block_Table_Tag(u8 *buf, u8 **tagarray) -{ - static u8 tag[BTSIG_BYTES >> 1]; - int i, j, k, tagi, tagtemp, status; - - *tagarray = (u8 *)tag; - tagi = 0; - - for (i = 0; i < (BTSIG_BYTES - 1); i++) { - for (j = i + 1; (j < BTSIG_BYTES) && - (tagi < (BTSIG_BYTES >> 1)); j++) { - tagtemp = buf[BTSIG_OFFSET + j] - - buf[BTSIG_OFFSET + i]; - if (tagtemp && !(tagtemp % BTSIG_DELTA)) { - tagtemp = (buf[BTSIG_OFFSET + i] + - (1 + LAST_BT_ID - FIRST_BT_ID) - - (i * BTSIG_DELTA)) % - (1 + LAST_BT_ID - FIRST_BT_ID); - status = FAIL; - for (k = 0; k < tagi; k++) { - if (tagtemp == tag[k]) - status = PASS; - } - - if (status == FAIL) { - tag[tagi++] = tagtemp; - i = (j == (i + 1)) ? i + 1 : i; - j = (j == (i + 1)) ? i + 1 : i; - } - } - } - } - - return tagi; -} - - -static int FTL_Execute_SPL_Recovery(void) -{ - u32 j, block, blks; - u32 *pbt = (u32 *)g_pBlockTable; - int ret; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - blks = DeviceInfo.wSpectraEndBlock - DeviceInfo.wSpectraStartBlock; - for (j = 0; j <= blks; j++) { - block = (pbt[j]); - if (((block & BAD_BLOCK) != BAD_BLOCK) && - ((block & SPARE_BLOCK) == SPARE_BLOCK)) { - ret = GLOB_LLD_Erase_Block(block & ~BAD_BLOCK); - if (FAIL == ret) { - nand_dbg_print(NAND_DBG_WARN, - "NAND Program fail in %s, Line %d, " - "Function: %s, new Bad Block %d " - "generated!\n", - __FILE__, __LINE__, __func__, - (int)(block & ~BAD_BLOCK)); - MARK_BLOCK_AS_BAD(pbt[j]); - } - } - } - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_FTL_IdentifyDevice -* Inputs: pointer to identify data structure -* Outputs: PASS / FAIL -* Description: the identify data structure is filled in with -* information for the block driver. -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int GLOB_FTL_IdentifyDevice(struct spectra_indentfy_dev_tag *dev_data) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - dev_data->NumBlocks = DeviceInfo.wTotalBlocks; - dev_data->PagesPerBlock = DeviceInfo.wPagesPerBlock; - dev_data->PageDataSize = DeviceInfo.wPageDataSize; - dev_data->wECCBytesPerSector = DeviceInfo.wECCBytesPerSector; - dev_data->wDataBlockNum = DeviceInfo.wDataBlockNum; - - return PASS; -} - -/* ..... */ -static int allocate_memory(void) -{ - u32 block_table_size, page_size, block_size, mem_size; - u32 total_bytes = 0; - int i; -#if CMD_DMA - int j; -#endif - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - page_size = DeviceInfo.wPageSize; - block_size = DeviceInfo.wPagesPerBlock * DeviceInfo.wPageDataSize; - - block_table_size = DeviceInfo.wDataBlockNum * - (sizeof(u32) + sizeof(u8) + sizeof(u16)); - block_table_size += (DeviceInfo.wPageDataSize - - (block_table_size % DeviceInfo.wPageDataSize)) % - DeviceInfo.wPageDataSize; - - /* Malloc memory for block tables */ - g_pBlockTable = kzalloc(block_table_size, GFP_ATOMIC); - if (!g_pBlockTable) - goto block_table_fail; - total_bytes += block_table_size; - - g_pWearCounter = (u8 *)(g_pBlockTable + - DeviceInfo.wDataBlockNum * sizeof(u32)); - - if (DeviceInfo.MLCDevice) - g_pReadCounter = (u16 *)(g_pBlockTable + - DeviceInfo.wDataBlockNum * - (sizeof(u32) + sizeof(u8))); - - /* Malloc memory and init for cache items */ - for (i = 0; i < CACHE_ITEM_NUM; i++) { - Cache.array[i].address = NAND_CACHE_INIT_ADDR; - Cache.array[i].use_cnt = 0; - Cache.array[i].changed = CLEAR; - Cache.array[i].buf = kzalloc(Cache.cache_item_size, - GFP_ATOMIC); - if (!Cache.array[i].buf) - goto cache_item_fail; - total_bytes += Cache.cache_item_size; - } - - /* Malloc memory for IPF */ - g_pIPF = kzalloc(page_size, GFP_ATOMIC); - if (!g_pIPF) - goto ipf_fail; - total_bytes += page_size; - - /* Malloc memory for data merging during Level2 Cache flush */ - cache_l2_page_buf = kmalloc(page_size, GFP_ATOMIC); - if (!cache_l2_page_buf) - goto cache_l2_page_buf_fail; - memset(cache_l2_page_buf, 0xff, page_size); - total_bytes += page_size; - - cache_l2_blk_buf = kmalloc(block_size, GFP_ATOMIC); - if (!cache_l2_blk_buf) - goto cache_l2_blk_buf_fail; - memset(cache_l2_blk_buf, 0xff, block_size); - total_bytes += block_size; - - /* Malloc memory for temp buffer */ - g_pTempBuf = kzalloc(Cache.cache_item_size, GFP_ATOMIC); - if (!g_pTempBuf) - goto Temp_buf_fail; - total_bytes += Cache.cache_item_size; - - /* Malloc memory for block table blocks */ - mem_size = (1 + LAST_BT_ID - FIRST_BT_ID) * sizeof(u32); - g_pBTBlocks = kmalloc(mem_size, GFP_ATOMIC); - if (!g_pBTBlocks) - goto bt_blocks_fail; - memset(g_pBTBlocks, 0xff, mem_size); - total_bytes += mem_size; - - /* Malloc memory for function FTL_Check_Block_Table */ - flag_check_blk_table = kmalloc(DeviceInfo.wDataBlockNum, GFP_ATOMIC); - if (!flag_check_blk_table) - goto flag_check_blk_table_fail; - total_bytes += DeviceInfo.wDataBlockNum; - - /* Malloc memory for function FTL_Search_Block_Table_IN_Block */ - tmp_buf_search_bt_in_block = kmalloc(page_size, GFP_ATOMIC); - if (!tmp_buf_search_bt_in_block) - goto tmp_buf_search_bt_in_block_fail; - memset(tmp_buf_search_bt_in_block, 0xff, page_size); - total_bytes += page_size; - - mem_size = DeviceInfo.wPageSize - DeviceInfo.wPageDataSize; - spare_buf_search_bt_in_block = kmalloc(mem_size, GFP_ATOMIC); - if (!spare_buf_search_bt_in_block) - goto spare_buf_search_bt_in_block_fail; - memset(spare_buf_search_bt_in_block, 0xff, mem_size); - total_bytes += mem_size; - - spare_buf_bt_search_bt_in_block = kmalloc(mem_size, GFP_ATOMIC); - if (!spare_buf_bt_search_bt_in_block) - goto spare_buf_bt_search_bt_in_block_fail; - memset(spare_buf_bt_search_bt_in_block, 0xff, mem_size); - total_bytes += mem_size; - - /* Malloc memory for function FTL_Read_Block_Table */ - tmp_buf1_read_blk_table = kmalloc(page_size, GFP_ATOMIC); - if (!tmp_buf1_read_blk_table) - goto tmp_buf1_read_blk_table_fail; - memset(tmp_buf1_read_blk_table, 0xff, page_size); - total_bytes += page_size; - - tmp_buf2_read_blk_table = kmalloc(page_size, GFP_ATOMIC); - if (!tmp_buf2_read_blk_table) - goto tmp_buf2_read_blk_table_fail; - memset(tmp_buf2_read_blk_table, 0xff, page_size); - total_bytes += page_size; - - /* Malloc memory for function FTL_Static_Wear_Leveling */ - flags_static_wear_leveling = kmalloc(DeviceInfo.wDataBlockNum, - GFP_ATOMIC); - if (!flags_static_wear_leveling) - goto flags_static_wear_leveling_fail; - total_bytes += DeviceInfo.wDataBlockNum; - - /* Malloc memory for function FTL_Write_Block_Table_Data */ - if (FTL_Get_Block_Table_Flash_Size_Pages() > 3) - mem_size = FTL_Get_Block_Table_Flash_Size_Bytes() - - 2 * DeviceInfo.wPageSize; - else - mem_size = DeviceInfo.wPageSize; - tmp_buf_write_blk_table_data = kmalloc(mem_size, GFP_ATOMIC); - if (!tmp_buf_write_blk_table_data) - goto tmp_buf_write_blk_table_data_fail; - memset(tmp_buf_write_blk_table_data, 0xff, mem_size); - total_bytes += mem_size; - - /* Malloc memory for function FTL_Read_Disturbance */ - tmp_buf_read_disturbance = kmalloc(block_size, GFP_ATOMIC); - if (!tmp_buf_read_disturbance) - goto tmp_buf_read_disturbance_fail; - memset(tmp_buf_read_disturbance, 0xff, block_size); - total_bytes += block_size; - - /* Alloc mem for function NAND_Read_Page_Main_Spare of lld_nand.c */ - buf_read_page_main_spare = kmalloc(DeviceInfo.wPageSize, GFP_ATOMIC); - if (!buf_read_page_main_spare) - goto buf_read_page_main_spare_fail; - total_bytes += DeviceInfo.wPageSize; - - /* Alloc mem for function NAND_Write_Page_Main_Spare of lld_nand.c */ - buf_write_page_main_spare = kmalloc(DeviceInfo.wPageSize, GFP_ATOMIC); - if (!buf_write_page_main_spare) - goto buf_write_page_main_spare_fail; - total_bytes += DeviceInfo.wPageSize; - - /* Alloc mem for function NAND_Read_Page_Spare of lld_nand.c */ - buf_read_page_spare = kmalloc(DeviceInfo.wPageSpareSize, GFP_ATOMIC); - if (!buf_read_page_spare) - goto buf_read_page_spare_fail; - memset(buf_read_page_spare, 0xff, DeviceInfo.wPageSpareSize); - total_bytes += DeviceInfo.wPageSpareSize; - - /* Alloc mem for function NAND_Get_Bad_Block of lld_nand.c */ - buf_get_bad_block = kmalloc(DeviceInfo.wPageSpareSize, GFP_ATOMIC); - if (!buf_get_bad_block) - goto buf_get_bad_block_fail; - memset(buf_get_bad_block, 0xff, DeviceInfo.wPageSpareSize); - total_bytes += DeviceInfo.wPageSpareSize; - -#if CMD_DMA - g_temp_buf = kmalloc(block_size, GFP_ATOMIC); - if (!g_temp_buf) - goto temp_buf_fail; - memset(g_temp_buf, 0xff, block_size); - total_bytes += block_size; - - /* Malloc memory for copy of block table used in CDMA mode */ - g_pBTStartingCopy = kzalloc(block_table_size, GFP_ATOMIC); - if (!g_pBTStartingCopy) - goto bt_starting_copy; - total_bytes += block_table_size; - - g_pWearCounterCopy = (u8 *)(g_pBTStartingCopy + - DeviceInfo.wDataBlockNum * sizeof(u32)); - - if (DeviceInfo.MLCDevice) - g_pReadCounterCopy = (u16 *)(g_pBTStartingCopy + - DeviceInfo.wDataBlockNum * - (sizeof(u32) + sizeof(u8))); - - /* Malloc memory for block table copies */ - mem_size = 5 * DeviceInfo.wDataBlockNum * sizeof(u32) + - 5 * DeviceInfo.wDataBlockNum * sizeof(u8); - if (DeviceInfo.MLCDevice) - mem_size += 5 * DeviceInfo.wDataBlockNum * sizeof(u16); - g_pBlockTableCopies = kzalloc(mem_size, GFP_ATOMIC); - if (!g_pBlockTableCopies) - goto blk_table_copies_fail; - total_bytes += mem_size; - g_pNextBlockTable = g_pBlockTableCopies; - - /* Malloc memory for Block Table Delta */ - mem_size = MAX_DESCS * sizeof(struct BTableChangesDelta); - g_pBTDelta = kzalloc(mem_size, GFP_ATOMIC); - if (!g_pBTDelta) - goto bt_delta_fail; - total_bytes += mem_size; - g_pBTDelta_Free = g_pBTDelta; - - /* Malloc memory for Copy Back Buffers */ - for (j = 0; j < COPY_BACK_BUF_NUM; j++) { - cp_back_buf_copies[j] = kzalloc(block_size, GFP_ATOMIC); - if (!cp_back_buf_copies[j]) - goto cp_back_buf_copies_fail; - total_bytes += block_size; - } - cp_back_buf_idx = 0; - - /* Malloc memory for pending commands list */ - mem_size = sizeof(struct pending_cmd) * MAX_DESCS; - info.pcmds = kzalloc(mem_size, GFP_KERNEL); - if (!info.pcmds) - goto pending_cmds_buf_fail; - total_bytes += mem_size; - - /* Malloc memory for CDMA descripter table */ - mem_size = sizeof(struct cdma_descriptor) * MAX_DESCS; - info.cdma_desc_buf = kzalloc(mem_size, GFP_KERNEL); - if (!info.cdma_desc_buf) - goto cdma_desc_buf_fail; - total_bytes += mem_size; - - /* Malloc memory for Memcpy descripter table */ - mem_size = sizeof(struct memcpy_descriptor) * MAX_DESCS; - info.memcp_desc_buf = kzalloc(mem_size, GFP_KERNEL); - if (!info.memcp_desc_buf) - goto memcp_desc_buf_fail; - total_bytes += mem_size; -#endif - - nand_dbg_print(NAND_DBG_WARN, - "Total memory allocated in FTL layer: %d\n", total_bytes); - - return PASS; - -#if CMD_DMA -memcp_desc_buf_fail: - kfree(info.cdma_desc_buf); -cdma_desc_buf_fail: - kfree(info.pcmds); -pending_cmds_buf_fail: -cp_back_buf_copies_fail: - j--; - for (; j >= 0; j--) - kfree(cp_back_buf_copies[j]); - kfree(g_pBTDelta); -bt_delta_fail: - kfree(g_pBlockTableCopies); -blk_table_copies_fail: - kfree(g_pBTStartingCopy); -bt_starting_copy: - kfree(g_temp_buf); -temp_buf_fail: - kfree(buf_get_bad_block); -#endif - -buf_get_bad_block_fail: - kfree(buf_read_page_spare); -buf_read_page_spare_fail: - kfree(buf_write_page_main_spare); -buf_write_page_main_spare_fail: - kfree(buf_read_page_main_spare); -buf_read_page_main_spare_fail: - kfree(tmp_buf_read_disturbance); -tmp_buf_read_disturbance_fail: - kfree(tmp_buf_write_blk_table_data); -tmp_buf_write_blk_table_data_fail: - kfree(flags_static_wear_leveling); -flags_static_wear_leveling_fail: - kfree(tmp_buf2_read_blk_table); -tmp_buf2_read_blk_table_fail: - kfree(tmp_buf1_read_blk_table); -tmp_buf1_read_blk_table_fail: - kfree(spare_buf_bt_search_bt_in_block); -spare_buf_bt_search_bt_in_block_fail: - kfree(spare_buf_search_bt_in_block); -spare_buf_search_bt_in_block_fail: - kfree(tmp_buf_search_bt_in_block); -tmp_buf_search_bt_in_block_fail: - kfree(flag_check_blk_table); -flag_check_blk_table_fail: - kfree(g_pBTBlocks); -bt_blocks_fail: - kfree(g_pTempBuf); -Temp_buf_fail: - kfree(cache_l2_blk_buf); -cache_l2_blk_buf_fail: - kfree(cache_l2_page_buf); -cache_l2_page_buf_fail: - kfree(g_pIPF); -ipf_fail: -cache_item_fail: - i--; - for (; i >= 0; i--) - kfree(Cache.array[i].buf); - kfree(g_pBlockTable); -block_table_fail: - printk(KERN_ERR "Failed to kmalloc memory in %s Line %d.\n", - __FILE__, __LINE__); - - return -ENOMEM; -} - -/* .... */ -static int free_memory(void) -{ - int i; - -#if CMD_DMA - kfree(info.memcp_desc_buf); - kfree(info.cdma_desc_buf); - kfree(info.pcmds); - for (i = COPY_BACK_BUF_NUM - 1; i >= 0; i--) - kfree(cp_back_buf_copies[i]); - kfree(g_pBTDelta); - kfree(g_pBlockTableCopies); - kfree(g_pBTStartingCopy); - kfree(g_temp_buf); - kfree(buf_get_bad_block); -#endif - kfree(buf_read_page_spare); - kfree(buf_write_page_main_spare); - kfree(buf_read_page_main_spare); - kfree(tmp_buf_read_disturbance); - kfree(tmp_buf_write_blk_table_data); - kfree(flags_static_wear_leveling); - kfree(tmp_buf2_read_blk_table); - kfree(tmp_buf1_read_blk_table); - kfree(spare_buf_bt_search_bt_in_block); - kfree(spare_buf_search_bt_in_block); - kfree(tmp_buf_search_bt_in_block); - kfree(flag_check_blk_table); - kfree(g_pBTBlocks); - kfree(g_pTempBuf); - kfree(g_pIPF); - for (i = CACHE_ITEM_NUM - 1; i >= 0; i--) - kfree(Cache.array[i].buf); - kfree(g_pBlockTable); - - return 0; -} - -static void dump_cache_l2_table(void) -{ - struct list_head *p; - struct spectra_l2_cache_list *pnd; - int n; - - n = 0; - list_for_each(p, &cache_l2.table.list) { - pnd = list_entry(p, struct spectra_l2_cache_list, list); - nand_dbg_print(NAND_DBG_WARN, "dump_cache_l2_table node: %d, logical_blk_num: %d\n", n, pnd->logical_blk_num); -/* - for (i = 0; i < DeviceInfo.wPagesPerBlock; i++) { - if (pnd->pages_array[i] != MAX_U32_VALUE) - nand_dbg_print(NAND_DBG_WARN, " pages_array[%d]: 0x%x\n", i, pnd->pages_array[i]); - } -*/ - n++; - } -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_FTL_Init -* Inputs: none -* Outputs: PASS=0 / FAIL=1 -* Description: allocates the memory for cache array, -* important data structures -* clears the cache array -* reads the block table from flash into array -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int GLOB_FTL_Init(void) -{ - int i; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - Cache.pages_per_item = 1; - Cache.cache_item_size = 1 * DeviceInfo.wPageDataSize; - - if (allocate_memory() != PASS) - return FAIL; - -#if CMD_DMA -#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE - memcpy((void *)&cache_start_copy, (void *)&Cache, - sizeof(struct flash_cache_tag)); - memset((void *)&int_cache, -1, - sizeof(struct flash_cache_delta_list_tag) * - (MAX_CHANS + MAX_DESCS)); -#endif - ftl_cmd_cnt = 0; -#endif - - if (FTL_Read_Block_Table() != PASS) - return FAIL; - - /* Init the Level2 Cache data structure */ - for (i = 0; i < BLK_NUM_FOR_L2_CACHE; i++) - cache_l2.blk_array[i] = MAX_U32_VALUE; - cache_l2.cur_blk_idx = 0; - cache_l2.cur_page_num = 0; - INIT_LIST_HEAD(&cache_l2.table.list); - cache_l2.table.logical_blk_num = MAX_U32_VALUE; - - dump_cache_l2_table(); - - return 0; -} - - -#if CMD_DMA -#if 0 -static void save_blk_table_changes(u16 idx) -{ - u8 ftl_cmd; - u32 *pbt = (u32 *)g_pBTStartingCopy; - -#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE - u16 id; - u8 cache_blks; - - id = idx - MAX_CHANS; - if (int_cache[id].item != -1) { - cache_blks = int_cache[id].item; - cache_start_copy.array[cache_blks].address = - int_cache[id].cache.address; - cache_start_copy.array[cache_blks].changed = - int_cache[id].cache.changed; - } -#endif - - ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; - - while (ftl_cmd <= PendingCMD[idx].Tag) { - if (p_BTableChangesDelta->ValidFields == 0x01) { - g_wBlockTableOffset = - p_BTableChangesDelta->g_wBlockTableOffset; - } else if (p_BTableChangesDelta->ValidFields == 0x0C) { - pbt[p_BTableChangesDelta->BT_Index] = - p_BTableChangesDelta->BT_Entry_Value; - debug_boundary_error((( - p_BTableChangesDelta->BT_Index)), - DeviceInfo.wDataBlockNum, 0); - } else if (p_BTableChangesDelta->ValidFields == 0x03) { - g_wBlockTableOffset = - p_BTableChangesDelta->g_wBlockTableOffset; - g_wBlockTableIndex = - p_BTableChangesDelta->g_wBlockTableIndex; - } else if (p_BTableChangesDelta->ValidFields == 0x30) { - g_pWearCounterCopy[p_BTableChangesDelta->WC_Index] = - p_BTableChangesDelta->WC_Entry_Value; - } else if ((DeviceInfo.MLCDevice) && - (p_BTableChangesDelta->ValidFields == 0xC0)) { - g_pReadCounterCopy[p_BTableChangesDelta->RC_Index] = - p_BTableChangesDelta->RC_Entry_Value; - nand_dbg_print(NAND_DBG_DEBUG, - "In event status setting read counter " - "GLOB_ftl_cmd_cnt %u Count %u Index %u\n", - ftl_cmd, - p_BTableChangesDelta->RC_Entry_Value, - (unsigned int)p_BTableChangesDelta->RC_Index); - } else { - nand_dbg_print(NAND_DBG_DEBUG, - "This should never occur \n"); - } - p_BTableChangesDelta += 1; - ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; - } -} - -static void discard_cmds(u16 n) -{ - u32 *pbt = (u32 *)g_pBTStartingCopy; - u8 ftl_cmd; - unsigned long k; -#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE - u8 cache_blks; - u16 id; -#endif - - if ((PendingCMD[n].CMD == WRITE_MAIN_CMD) || - (PendingCMD[n].CMD == WRITE_MAIN_SPARE_CMD)) { - for (k = 0; k < DeviceInfo.wDataBlockNum; k++) { - if (PendingCMD[n].Block == (pbt[k] & (~BAD_BLOCK))) - MARK_BLK_AS_DISCARD(pbt[k]); - } - } - - ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; - while (ftl_cmd <= PendingCMD[n].Tag) { - p_BTableChangesDelta += 1; - ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; - } - -#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE - id = n - MAX_CHANS; - - if (int_cache[id].item != -1) { - cache_blks = int_cache[id].item; - if (PendingCMD[n].CMD == MEMCOPY_CMD) { - if ((cache_start_copy.array[cache_blks].buf <= - PendingCMD[n].DataDestAddr) && - ((cache_start_copy.array[cache_blks].buf + - Cache.cache_item_size) > - PendingCMD[n].DataDestAddr)) { - cache_start_copy.array[cache_blks].address = - NAND_CACHE_INIT_ADDR; - cache_start_copy.array[cache_blks].use_cnt = - 0; - cache_start_copy.array[cache_blks].changed = - CLEAR; - } - } else { - cache_start_copy.array[cache_blks].address = - int_cache[id].cache.address; - cache_start_copy.array[cache_blks].changed = - int_cache[id].cache.changed; - } - } -#endif -} - -static void process_cmd_pass(int *first_failed_cmd, u16 idx) -{ - if (0 == *first_failed_cmd) - save_blk_table_changes(idx); - else - discard_cmds(idx); -} - -static void process_cmd_fail_abort(int *first_failed_cmd, - u16 idx, int event) -{ - u32 *pbt = (u32 *)g_pBTStartingCopy; - u8 ftl_cmd; - unsigned long i; - int erase_fail, program_fail; -#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE - u8 cache_blks; - u16 id; -#endif - - if (0 == *first_failed_cmd) - *first_failed_cmd = PendingCMD[idx].SBDCmdIndex; - - nand_dbg_print(NAND_DBG_DEBUG, "Uncorrectable error has occurred " - "while executing %u Command %u accesing Block %u\n", - (unsigned int)p_BTableChangesDelta->ftl_cmd_cnt, - PendingCMD[idx].CMD, - (unsigned int)PendingCMD[idx].Block); - - ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; - while (ftl_cmd <= PendingCMD[idx].Tag) { - p_BTableChangesDelta += 1; - ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; - } - -#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE - id = idx - MAX_CHANS; - - if (int_cache[id].item != -1) { - cache_blks = int_cache[id].item; - if ((PendingCMD[idx].CMD == WRITE_MAIN_CMD)) { - cache_start_copy.array[cache_blks].address = - int_cache[id].cache.address; - cache_start_copy.array[cache_blks].changed = SET; - } else if ((PendingCMD[idx].CMD == READ_MAIN_CMD)) { - cache_start_copy.array[cache_blks].address = - NAND_CACHE_INIT_ADDR; - cache_start_copy.array[cache_blks].use_cnt = 0; - cache_start_copy.array[cache_blks].changed = - CLEAR; - } else if (PendingCMD[idx].CMD == ERASE_CMD) { - /* ? */ - } else if (PendingCMD[idx].CMD == MEMCOPY_CMD) { - /* ? */ - } - } -#endif - - erase_fail = (event == EVENT_ERASE_FAILURE) && - (PendingCMD[idx].CMD == ERASE_CMD); - - program_fail = (event == EVENT_PROGRAM_FAILURE) && - ((PendingCMD[idx].CMD == WRITE_MAIN_CMD) || - (PendingCMD[idx].CMD == WRITE_MAIN_SPARE_CMD)); - - if (erase_fail || program_fail) { - for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { - if (PendingCMD[idx].Block == - (pbt[i] & (~BAD_BLOCK))) - MARK_BLOCK_AS_BAD(pbt[i]); - } - } -} - -static void process_cmd(int *first_failed_cmd, u16 idx, int event) -{ - u8 ftl_cmd; - int cmd_match = 0; - - if (p_BTableChangesDelta->ftl_cmd_cnt == PendingCMD[idx].Tag) - cmd_match = 1; - - if (PendingCMD[idx].Status == CMD_PASS) { - process_cmd_pass(first_failed_cmd, idx); - } else if ((PendingCMD[idx].Status == CMD_FAIL) || - (PendingCMD[idx].Status == CMD_ABORT)) { - process_cmd_fail_abort(first_failed_cmd, idx, event); - } else if ((PendingCMD[idx].Status == CMD_NOT_DONE) && - PendingCMD[idx].Tag) { - nand_dbg_print(NAND_DBG_DEBUG, - " Command no. %hu is not executed\n", - (unsigned int)PendingCMD[idx].Tag); - ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; - while (ftl_cmd <= PendingCMD[idx].Tag) { - p_BTableChangesDelta += 1; - ftl_cmd = p_BTableChangesDelta->ftl_cmd_cnt; - } - } -} -#endif - -static void process_cmd(int *first_failed_cmd, u16 idx, int event) -{ - printk(KERN_ERR "temporary workaround function. " - "Should not be called! \n"); -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_FTL_Event_Status -* Inputs: none -* Outputs: Event Code -* Description: It is called by SBD after hardware interrupt signalling -* completion of commands chain -* It does following things -* get event status from LLD -* analyze command chain status -* determine last command executed -* analyze results -* rebuild the block table in case of uncorrectable error -* return event code -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int GLOB_FTL_Event_Status(int *first_failed_cmd) -{ - int event_code = PASS; - u16 i_P; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - *first_failed_cmd = 0; - - event_code = GLOB_LLD_Event_Status(); - - switch (event_code) { - case EVENT_PASS: - nand_dbg_print(NAND_DBG_DEBUG, "Handling EVENT_PASS\n"); - break; - case EVENT_UNCORRECTABLE_DATA_ERROR: - nand_dbg_print(NAND_DBG_DEBUG, "Handling Uncorrectable ECC!\n"); - break; - case EVENT_PROGRAM_FAILURE: - case EVENT_ERASE_FAILURE: - nand_dbg_print(NAND_DBG_WARN, "Handling Ugly case. " - "Event code: 0x%x\n", event_code); - p_BTableChangesDelta = - (struct BTableChangesDelta *)g_pBTDelta; - for (i_P = MAX_CHANS; i_P < (ftl_cmd_cnt + MAX_CHANS); - i_P++) - process_cmd(first_failed_cmd, i_P, event_code); - memcpy(g_pBlockTable, g_pBTStartingCopy, - DeviceInfo.wDataBlockNum * sizeof(u32)); - memcpy(g_pWearCounter, g_pWearCounterCopy, - DeviceInfo.wDataBlockNum * sizeof(u8)); - if (DeviceInfo.MLCDevice) - memcpy(g_pReadCounter, g_pReadCounterCopy, - DeviceInfo.wDataBlockNum * sizeof(u16)); - -#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE - memcpy((void *)&Cache, (void *)&cache_start_copy, - sizeof(struct flash_cache_tag)); - memset((void *)&int_cache, -1, - sizeof(struct flash_cache_delta_list_tag) * - (MAX_DESCS + MAX_CHANS)); -#endif - break; - default: - nand_dbg_print(NAND_DBG_WARN, - "Handling unexpected event code - 0x%x\n", - event_code); - event_code = ERR; - break; - } - - memcpy(g_pBTStartingCopy, g_pBlockTable, - DeviceInfo.wDataBlockNum * sizeof(u32)); - memcpy(g_pWearCounterCopy, g_pWearCounter, - DeviceInfo.wDataBlockNum * sizeof(u8)); - if (DeviceInfo.MLCDevice) - memcpy(g_pReadCounterCopy, g_pReadCounter, - DeviceInfo.wDataBlockNum * sizeof(u16)); - - g_pBTDelta_Free = g_pBTDelta; - ftl_cmd_cnt = 0; - g_pNextBlockTable = g_pBlockTableCopies; - cp_back_buf_idx = 0; - -#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE - memcpy((void *)&cache_start_copy, (void *)&Cache, - sizeof(struct flash_cache_tag)); - memset((void *)&int_cache, -1, - sizeof(struct flash_cache_delta_list_tag) * - (MAX_DESCS + MAX_CHANS)); -#endif - - return event_code; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: glob_ftl_execute_cmds -* Inputs: none -* Outputs: none -* Description: pass thru to LLD -***************************************************************/ -u16 glob_ftl_execute_cmds(void) -{ - nand_dbg_print(NAND_DBG_TRACE, - "glob_ftl_execute_cmds: ftl_cmd_cnt %u\n", - (unsigned int)ftl_cmd_cnt); - g_SBDCmdIndex = 0; - return glob_lld_execute_cmds(); -} - -#endif - -#if !CMD_DMA -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_FTL_Read Immediate -* Inputs: pointer to data -* address of data -* Outputs: PASS / FAIL -* Description: Reads one page of data into RAM directly from flash without -* using or disturbing cache.It is assumed this function is called -* with CMD-DMA disabled. -*****************************************************************/ -int GLOB_FTL_Read_Immediate(u8 *read_data, u64 addr) -{ - int wResult = FAIL; - u32 Block; - u16 Page; - u32 phy_blk; - u32 *pbt = (u32 *)g_pBlockTable; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - Block = BLK_FROM_ADDR(addr); - Page = PAGE_FROM_ADDR(addr, Block); - - if (!IS_SPARE_BLOCK(Block)) - return FAIL; - - phy_blk = pbt[Block]; - wResult = GLOB_LLD_Read_Page_Main(read_data, phy_blk, Page, 1); - - if (DeviceInfo.MLCDevice) { - g_pReadCounter[phy_blk - DeviceInfo.wSpectraStartBlock]++; - if (g_pReadCounter[phy_blk - DeviceInfo.wSpectraStartBlock] - >= MAX_READ_COUNTER) - FTL_Read_Disturbance(phy_blk); - if (g_cBlockTableStatus != IN_PROGRESS_BLOCK_TABLE) { - g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; - FTL_Write_IN_Progress_Block_Table_Page(); - } - } - - return wResult; -} -#endif - -#ifdef SUPPORT_BIG_ENDIAN -/********************************************************************* -* Function: FTL_Invert_Block_Table -* Inputs: none -* Outputs: none -* Description: Re-format the block table in ram based on BIG_ENDIAN and -* LARGE_BLOCKNUM if necessary -**********************************************************************/ -static void FTL_Invert_Block_Table(void) -{ - u32 i; - u32 *pbt = (u32 *)g_pBlockTable; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - -#ifdef SUPPORT_LARGE_BLOCKNUM - for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { - pbt[i] = INVERTUINT32(pbt[i]); - g_pWearCounter[i] = INVERTUINT32(g_pWearCounter[i]); - } -#else - for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { - pbt[i] = INVERTUINT16(pbt[i]); - g_pWearCounter[i] = INVERTUINT16(g_pWearCounter[i]); - } -#endif -} -#endif - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_FTL_Flash_Init -* Inputs: none -* Outputs: PASS=0 / FAIL=0x01 (based on read ID) -* Description: The flash controller is initialized -* The flash device is reset -* Perform a flash READ ID command to confirm that a -* valid device is attached and active. -* The DeviceInfo structure gets filled in -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int GLOB_FTL_Flash_Init(void) -{ - int status = FAIL; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - g_SBDCmdIndex = 0; - - status = GLOB_LLD_Flash_Init(); - - return status; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Inputs: none -* Outputs: PASS=0 / FAIL=0x01 (based on read ID) -* Description: The flash controller is released -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int GLOB_FTL_Flash_Release(void) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - return GLOB_LLD_Flash_Release(); -} - - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_FTL_Cache_Release -* Inputs: none -* Outputs: none -* Description: release all allocated memory in GLOB_FTL_Init -* (allocated in GLOB_FTL_Init) -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -void GLOB_FTL_Cache_Release(void) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - free_memory(); -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Cache_If_Hit -* Inputs: Page Address -* Outputs: Block number/UNHIT BLOCK -* Description: Determines if the addressed page is in cache -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static u16 FTL_Cache_If_Hit(u64 page_addr) -{ - u16 item; - u64 addr; - int i; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - item = UNHIT_CACHE_ITEM; - for (i = 0; i < CACHE_ITEM_NUM; i++) { - addr = Cache.array[i].address; - if ((page_addr >= addr) && - (page_addr < (addr + Cache.cache_item_size))) { - item = i; - break; - } - } - - return item; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Calculate_LRU -* Inputs: None -* Outputs: None -* Description: Calculate the least recently block in a cache and record its -* index in LRU field. -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static void FTL_Calculate_LRU(void) -{ - u16 i, bCurrentLRU, bTempCount; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - bCurrentLRU = 0; - bTempCount = MAX_WORD_VALUE; - - for (i = 0; i < CACHE_ITEM_NUM; i++) { - if (Cache.array[i].use_cnt < bTempCount) { - bCurrentLRU = i; - bTempCount = Cache.array[i].use_cnt; - } - } - - Cache.LRU = bCurrentLRU; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Cache_Read_Page -* Inputs: pointer to read buffer, logical address and cache item number -* Outputs: None -* Description: Read the page from the cached block addressed by blocknumber -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static void FTL_Cache_Read_Page(u8 *data_buf, u64 logic_addr, u16 cache_item) -{ - u8 *start_addr; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - start_addr = Cache.array[cache_item].buf; - start_addr += (u32)(((logic_addr - Cache.array[cache_item].address) >> - DeviceInfo.nBitsInPageDataSize) * DeviceInfo.wPageDataSize); - -#if CMD_DMA - GLOB_LLD_MemCopy_CMD(data_buf, start_addr, - DeviceInfo.wPageDataSize, 0); - ftl_cmd_cnt++; -#else - memcpy(data_buf, start_addr, DeviceInfo.wPageDataSize); -#endif - - if (Cache.array[cache_item].use_cnt < MAX_WORD_VALUE) - Cache.array[cache_item].use_cnt++; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Cache_Read_All -* Inputs: pointer to read buffer,block address -* Outputs: PASS=0 / FAIL =1 -* Description: It reads pages in cache -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static int FTL_Cache_Read_All(u8 *pData, u64 phy_addr) -{ - int wResult = PASS; - u32 Block; - u32 lba; - u16 Page; - u16 PageCount; - u32 *pbt = (u32 *)g_pBlockTable; - u32 i; - - Block = BLK_FROM_ADDR(phy_addr); - Page = PAGE_FROM_ADDR(phy_addr, Block); - PageCount = Cache.pages_per_item; - - nand_dbg_print(NAND_DBG_DEBUG, - "%s, Line %d, Function: %s, Block: 0x%x\n", - __FILE__, __LINE__, __func__, Block); - - lba = 0xffffffff; - for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { - if ((pbt[i] & (~BAD_BLOCK)) == Block) { - lba = i; - if (IS_SPARE_BLOCK(i) || IS_BAD_BLOCK(i) || - IS_DISCARDED_BLOCK(i)) { - /* Add by yunpeng -2008.12.3 */ -#if CMD_DMA - GLOB_LLD_MemCopy_CMD(pData, g_temp_buf, - PageCount * DeviceInfo.wPageDataSize, 0); - ftl_cmd_cnt++; -#else - memset(pData, 0xFF, - PageCount * DeviceInfo.wPageDataSize); -#endif - return wResult; - } else { - continue; /* break ?? */ - } - } - } - - if (0xffffffff == lba) - printk(KERN_ERR "FTL_Cache_Read_All: Block is not found in BT\n"); - -#if CMD_DMA - wResult = GLOB_LLD_Read_Page_Main_cdma(pData, Block, Page, - PageCount, LLD_CMD_FLAG_MODE_CDMA); - if (DeviceInfo.MLCDevice) { - g_pReadCounter[Block - DeviceInfo.wSpectraStartBlock]++; - nand_dbg_print(NAND_DBG_DEBUG, - "Read Counter modified in ftl_cmd_cnt %u" - " Block %u Counter%u\n", - ftl_cmd_cnt, (unsigned int)Block, - g_pReadCounter[Block - - DeviceInfo.wSpectraStartBlock]); - - p_BTableChangesDelta = - (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; - p_BTableChangesDelta->RC_Index = - Block - DeviceInfo.wSpectraStartBlock; - p_BTableChangesDelta->RC_Entry_Value = - g_pReadCounter[Block - DeviceInfo.wSpectraStartBlock]; - p_BTableChangesDelta->ValidFields = 0xC0; - - ftl_cmd_cnt++; - - if (g_pReadCounter[Block - DeviceInfo.wSpectraStartBlock] >= - MAX_READ_COUNTER) - FTL_Read_Disturbance(Block); - if (g_cBlockTableStatus != IN_PROGRESS_BLOCK_TABLE) { - g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; - FTL_Write_IN_Progress_Block_Table_Page(); - } - } else { - ftl_cmd_cnt++; - } -#else - wResult = GLOB_LLD_Read_Page_Main(pData, Block, Page, PageCount); - if (wResult == FAIL) - return wResult; - - if (DeviceInfo.MLCDevice) { - g_pReadCounter[Block - DeviceInfo.wSpectraStartBlock]++; - if (g_pReadCounter[Block - DeviceInfo.wSpectraStartBlock] >= - MAX_READ_COUNTER) - FTL_Read_Disturbance(Block); - if (g_cBlockTableStatus != IN_PROGRESS_BLOCK_TABLE) { - g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; - FTL_Write_IN_Progress_Block_Table_Page(); - } - } -#endif - return wResult; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Cache_Write_All -* Inputs: pointer to cache in sys memory -* address of free block in flash -* Outputs: PASS=0 / FAIL=1 -* Description: writes all the pages of the block in cache to flash -* -* NOTE:need to make sure this works ok when cache is limited -* to a partial block. This is where copy-back would be -* activated. This would require knowing which pages in the -* cached block are clean/dirty.Right now we only know if -* the whole block is clean/dirty. -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static int FTL_Cache_Write_All(u8 *pData, u64 blk_addr) -{ - u16 wResult = PASS; - u32 Block; - u16 Page; - u16 PageCount; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - nand_dbg_print(NAND_DBG_DEBUG, "This block %d going to be written " - "on %d\n", cache_block_to_write, - (u32)(blk_addr >> DeviceInfo.nBitsInBlockDataSize)); - - Block = BLK_FROM_ADDR(blk_addr); - Page = PAGE_FROM_ADDR(blk_addr, Block); - PageCount = Cache.pages_per_item; - -#if CMD_DMA - if (FAIL == GLOB_LLD_Write_Page_Main_cdma(pData, - Block, Page, PageCount)) { - nand_dbg_print(NAND_DBG_WARN, - "NAND Program fail in %s, Line %d, " - "Function: %s, new Bad Block %d generated! " - "Need Bad Block replacing.\n", - __FILE__, __LINE__, __func__, Block); - wResult = FAIL; - } - ftl_cmd_cnt++; -#else - if (FAIL == GLOB_LLD_Write_Page_Main(pData, Block, Page, PageCount)) { - nand_dbg_print(NAND_DBG_WARN, "NAND Program fail in %s," - " Line %d, Function %s, new Bad Block %d generated!" - "Need Bad Block replacing.\n", - __FILE__, __LINE__, __func__, Block); - wResult = FAIL; - } -#endif - return wResult; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Copy_Block -* Inputs: source block address -* Destination block address -* Outputs: PASS=0 / FAIL=1 -* Description: used only for static wear leveling to move the block -* containing static data to new blocks(more worn) -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int FTL_Copy_Block(u64 old_blk_addr, u64 blk_addr) -{ - int i, r1, r2, wResult = PASS; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - for (i = 0; i < DeviceInfo.wPagesPerBlock; i += Cache.pages_per_item) { - r1 = FTL_Cache_Read_All(g_pTempBuf, old_blk_addr + - i * DeviceInfo.wPageDataSize); - r2 = FTL_Cache_Write_All(g_pTempBuf, blk_addr + - i * DeviceInfo.wPageDataSize); - if ((ERR == r1) || (FAIL == r2)) { - wResult = FAIL; - break; - } - } - - return wResult; -} - -/* Search the block table to find out the least wear block and then return it */ -static u32 find_least_worn_blk_for_l2_cache(void) -{ - int i; - u32 *pbt = (u32 *)g_pBlockTable; - u8 least_wear_cnt = MAX_BYTE_VALUE; - u32 least_wear_blk_idx = MAX_U32_VALUE; - u32 phy_idx; - - for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { - if (IS_SPARE_BLOCK(i)) { - phy_idx = (u32)((~BAD_BLOCK) & pbt[i]); - if (phy_idx > DeviceInfo.wSpectraEndBlock) - printk(KERN_ERR "find_least_worn_blk_for_l2_cache: " - "Too big phy block num (%d)\n", phy_idx); - if (g_pWearCounter[phy_idx -DeviceInfo.wSpectraStartBlock] < least_wear_cnt) { - least_wear_cnt = g_pWearCounter[phy_idx - DeviceInfo.wSpectraStartBlock]; - least_wear_blk_idx = i; - } - } - } - - nand_dbg_print(NAND_DBG_WARN, - "find_least_worn_blk_for_l2_cache: " - "find block %d with least worn counter (%d)\n", - least_wear_blk_idx, least_wear_cnt); - - return least_wear_blk_idx; -} - - - -/* Get blocks for Level2 Cache */ -static int get_l2_cache_blks(void) -{ - int n; - u32 blk; - u32 *pbt = (u32 *)g_pBlockTable; - - for (n = 0; n < BLK_NUM_FOR_L2_CACHE; n++) { - blk = find_least_worn_blk_for_l2_cache(); - if (blk >= DeviceInfo.wDataBlockNum) { - nand_dbg_print(NAND_DBG_WARN, - "find_least_worn_blk_for_l2_cache: " - "No enough free NAND blocks (n: %d) for L2 Cache!\n", n); - return FAIL; - } - /* Tag the free block as discard in block table */ - pbt[blk] = (pbt[blk] & (~BAD_BLOCK)) | DISCARD_BLOCK; - /* Add the free block to the L2 Cache block array */ - cache_l2.blk_array[n] = pbt[blk] & (~BAD_BLOCK); - } - - return PASS; -} - -static int erase_l2_cache_blocks(void) -{ - int i, ret = PASS; - u32 pblk, lblk = BAD_BLOCK; - u64 addr; - u32 *pbt = (u32 *)g_pBlockTable; - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - for (i = 0; i < BLK_NUM_FOR_L2_CACHE; i++) { - pblk = cache_l2.blk_array[i]; - - /* If the L2 cache block is invalid, then just skip it */ - if (MAX_U32_VALUE == pblk) - continue; - - BUG_ON(pblk > DeviceInfo.wSpectraEndBlock); - - addr = (u64)pblk << DeviceInfo.nBitsInBlockDataSize; - if (PASS == GLOB_FTL_Block_Erase(addr)) { - /* Get logical block number of the erased block */ - lblk = FTL_Get_Block_Index(pblk); - BUG_ON(BAD_BLOCK == lblk); - /* Tag it as free in the block table */ - pbt[lblk] &= (u32)(~DISCARD_BLOCK); - pbt[lblk] |= (u32)(SPARE_BLOCK); - } else { - MARK_BLOCK_AS_BAD(pbt[lblk]); - ret = ERR; - } - } - - return ret; -} - -/* - * Merge the valid data page in the L2 cache blocks into NAND. -*/ -static int flush_l2_cache(void) -{ - struct list_head *p; - struct spectra_l2_cache_list *pnd, *tmp_pnd; - u32 *pbt = (u32 *)g_pBlockTable; - u32 phy_blk, l2_blk; - u64 addr; - u16 l2_page; - int i, ret = PASS; - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (list_empty(&cache_l2.table.list)) /* No data to flush */ - return ret; - - //dump_cache_l2_table(); - - if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) { - g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; - FTL_Write_IN_Progress_Block_Table_Page(); - } - - list_for_each(p, &cache_l2.table.list) { - pnd = list_entry(p, struct spectra_l2_cache_list, list); - if (IS_SPARE_BLOCK(pnd->logical_blk_num) || - IS_BAD_BLOCK(pnd->logical_blk_num) || - IS_DISCARDED_BLOCK(pnd->logical_blk_num)) { - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d\n", __FILE__, __LINE__); - memset(cache_l2_blk_buf, 0xff, DeviceInfo.wPagesPerBlock * DeviceInfo.wPageDataSize); - } else { - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d\n", __FILE__, __LINE__); - phy_blk = pbt[pnd->logical_blk_num] & (~BAD_BLOCK); - ret = GLOB_LLD_Read_Page_Main(cache_l2_blk_buf, - phy_blk, 0, DeviceInfo.wPagesPerBlock); - if (ret == FAIL) { - printk(KERN_ERR "Read NAND page fail in %s, Line %d\n", __FILE__, __LINE__); - } - } - - for (i = 0; i < DeviceInfo.wPagesPerBlock; i++) { - if (pnd->pages_array[i] != MAX_U32_VALUE) { - l2_blk = cache_l2.blk_array[(pnd->pages_array[i] >> 16) & 0xffff]; - l2_page = pnd->pages_array[i] & 0xffff; - ret = GLOB_LLD_Read_Page_Main(cache_l2_page_buf, l2_blk, l2_page, 1); - if (ret == FAIL) { - printk(KERN_ERR "Read NAND page fail in %s, Line %d\n", __FILE__, __LINE__); - } - memcpy(cache_l2_blk_buf + i * DeviceInfo.wPageDataSize, cache_l2_page_buf, DeviceInfo.wPageDataSize); - } - } - - /* Find a free block and tag the original block as discarded */ - addr = (u64)pnd->logical_blk_num << DeviceInfo.nBitsInBlockDataSize; - ret = FTL_Replace_Block(addr); - if (ret == FAIL) { - printk(KERN_ERR "FTL_Replace_Block fail in %s, Line %d\n", __FILE__, __LINE__); - } - - /* Write back the updated data into NAND */ - phy_blk = pbt[pnd->logical_blk_num] & (~BAD_BLOCK); - if (FAIL == GLOB_LLD_Write_Page_Main(cache_l2_blk_buf, phy_blk, 0, DeviceInfo.wPagesPerBlock)) { - nand_dbg_print(NAND_DBG_WARN, - "Program NAND block %d fail in %s, Line %d\n", - phy_blk, __FILE__, __LINE__); - /* This may not be really a bad block. So just tag it as discarded. */ - /* Then it has a chance to be erased when garbage collection. */ - /* If it is really bad, then the erase will fail and it will be marked */ - /* as bad then. Otherwise it will be marked as free and can be used again */ - MARK_BLK_AS_DISCARD(pbt[pnd->logical_blk_num]); - /* Find another free block and write it again */ - FTL_Replace_Block(addr); - phy_blk = pbt[pnd->logical_blk_num] & (~BAD_BLOCK); - if (FAIL == GLOB_LLD_Write_Page_Main(cache_l2_blk_buf, phy_blk, 0, DeviceInfo.wPagesPerBlock)) { - printk(KERN_ERR "Failed to write back block %d when flush L2 cache." - "Some data will be lost!\n", phy_blk); - MARK_BLOCK_AS_BAD(pbt[pnd->logical_blk_num]); - } - } else { - /* tag the new free block as used block */ - pbt[pnd->logical_blk_num] &= (~SPARE_BLOCK); - } - } - - /* Destroy the L2 Cache table and free the memory of all nodes */ - list_for_each_entry_safe(pnd, tmp_pnd, &cache_l2.table.list, list) { - list_del(&pnd->list); - kfree(pnd); - } - - /* Erase discard L2 cache blocks */ - if (erase_l2_cache_blocks() != PASS) - nand_dbg_print(NAND_DBG_WARN, - " Erase L2 cache blocks error in %s, Line %d\n", - __FILE__, __LINE__); - - /* Init the Level2 Cache data structure */ - for (i = 0; i < BLK_NUM_FOR_L2_CACHE; i++) - cache_l2.blk_array[i] = MAX_U32_VALUE; - cache_l2.cur_blk_idx = 0; - cache_l2.cur_page_num = 0; - INIT_LIST_HEAD(&cache_l2.table.list); - cache_l2.table.logical_blk_num = MAX_U32_VALUE; - - return ret; -} - -/* - * Write back a changed victim cache item to the Level2 Cache - * and update the L2 Cache table to map the change. - * If the L2 Cache is full, then start to do the L2 Cache flush. -*/ -static int write_back_to_l2_cache(u8 *buf, u64 logical_addr) -{ - u32 logical_blk_num; - u16 logical_page_num; - struct list_head *p; - struct spectra_l2_cache_list *pnd, *pnd_new; - u32 node_size; - int i, found; - - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - /* - * If Level2 Cache table is empty, then it means either: - * 1. This is the first time that the function called after FTL_init - * or - * 2. The Level2 Cache has just been flushed - * - * So, 'steal' some free blocks from NAND for L2 Cache using - * by just mask them as discard in the block table - */ - if (list_empty(&cache_l2.table.list)) { - BUG_ON(cache_l2.cur_blk_idx != 0); - BUG_ON(cache_l2.cur_page_num!= 0); - BUG_ON(cache_l2.table.logical_blk_num != MAX_U32_VALUE); - if (FAIL == get_l2_cache_blks()) { - GLOB_FTL_Garbage_Collection(); - if (FAIL == get_l2_cache_blks()) { - printk(KERN_ALERT "Fail to get L2 cache blks!\n"); - return FAIL; - } - } - } - - logical_blk_num = BLK_FROM_ADDR(logical_addr); - logical_page_num = PAGE_FROM_ADDR(logical_addr, logical_blk_num); - BUG_ON(logical_blk_num == MAX_U32_VALUE); - - /* Write the cache item data into the current position of L2 Cache */ -#if CMD_DMA - /* - * TODO - */ -#else - if (FAIL == GLOB_LLD_Write_Page_Main(buf, - cache_l2.blk_array[cache_l2.cur_blk_idx], - cache_l2.cur_page_num, 1)) { - nand_dbg_print(NAND_DBG_WARN, "NAND Program fail in " - "%s, Line %d, new Bad Block %d generated!\n", - __FILE__, __LINE__, - cache_l2.blk_array[cache_l2.cur_blk_idx]); - - /* TODO: tag the current block as bad and try again */ - - return FAIL; - } -#endif - - /* - * Update the L2 Cache table. - * - * First seaching in the table to see whether the logical block - * has been mapped. If not, then kmalloc a new node for the - * logical block, fill data, and then insert it to the list. - * Otherwise, just update the mapped node directly. - */ - found = 0; - list_for_each(p, &cache_l2.table.list) { - pnd = list_entry(p, struct spectra_l2_cache_list, list); - if (pnd->logical_blk_num == logical_blk_num) { - pnd->pages_array[logical_page_num] = - (cache_l2.cur_blk_idx << 16) | - cache_l2.cur_page_num; - found = 1; - break; - } - } - if (!found) { /* Create new node for the logical block here */ - - /* The logical pages to physical pages map array is - * located at the end of struct spectra_l2_cache_list. - */ - node_size = sizeof(struct spectra_l2_cache_list) + - sizeof(u32) * DeviceInfo.wPagesPerBlock; - pnd_new = kmalloc(node_size, GFP_ATOMIC); - if (!pnd_new) { - printk(KERN_ERR "Failed to kmalloc in %s Line %d\n", - __FILE__, __LINE__); - /* - * TODO: Need to flush all the L2 cache into NAND ASAP - * since no memory available here - */ - } - pnd_new->logical_blk_num = logical_blk_num; - for (i = 0; i < DeviceInfo.wPagesPerBlock; i++) - pnd_new->pages_array[i] = MAX_U32_VALUE; - pnd_new->pages_array[logical_page_num] = - (cache_l2.cur_blk_idx << 16) | cache_l2.cur_page_num; - list_add(&pnd_new->list, &cache_l2.table.list); - } - - /* Increasing the current position pointer of the L2 Cache */ - cache_l2.cur_page_num++; - if (cache_l2.cur_page_num >= DeviceInfo.wPagesPerBlock) { - cache_l2.cur_blk_idx++; - if (cache_l2.cur_blk_idx >= BLK_NUM_FOR_L2_CACHE) { - /* The L2 Cache is full. Need to flush it now */ - nand_dbg_print(NAND_DBG_WARN, - "L2 Cache is full, will start to flush it\n"); - flush_l2_cache(); - } else { - cache_l2.cur_page_num = 0; - } - } - - return PASS; -} - -/* - * Search in the Level2 Cache table to find the cache item. - * If find, read the data from the NAND page of L2 Cache, - * Otherwise, return FAIL. - */ -static int search_l2_cache(u8 *buf, u64 logical_addr) -{ - u32 logical_blk_num; - u16 logical_page_num; - struct list_head *p; - struct spectra_l2_cache_list *pnd; - u32 tmp = MAX_U32_VALUE; - u32 phy_blk; - u16 phy_page; - int ret = FAIL; - - logical_blk_num = BLK_FROM_ADDR(logical_addr); - logical_page_num = PAGE_FROM_ADDR(logical_addr, logical_blk_num); - - list_for_each(p, &cache_l2.table.list) { - pnd = list_entry(p, struct spectra_l2_cache_list, list); - if (pnd->logical_blk_num == logical_blk_num) { - tmp = pnd->pages_array[logical_page_num]; - break; - } - } - - if (tmp != MAX_U32_VALUE) { /* Found valid map */ - phy_blk = cache_l2.blk_array[(tmp >> 16) & 0xFFFF]; - phy_page = tmp & 0xFFFF; -#if CMD_DMA - /* TODO */ -#else - ret = GLOB_LLD_Read_Page_Main(buf, phy_blk, phy_page, 1); -#endif - } - - return ret; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Cache_Write_Page -* Inputs: Pointer to buffer, page address, cache block number -* Outputs: PASS=0 / FAIL=1 -* Description: It writes the data in Cache Block -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static void FTL_Cache_Write_Page(u8 *pData, u64 page_addr, - u8 cache_blk, u16 flag) -{ - u8 *pDest; - u64 addr; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - addr = Cache.array[cache_blk].address; - pDest = Cache.array[cache_blk].buf; - - pDest += (unsigned long)(page_addr - addr); - Cache.array[cache_blk].changed = SET; -#if CMD_DMA -#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE - int_cache[ftl_cmd_cnt].item = cache_blk; - int_cache[ftl_cmd_cnt].cache.address = - Cache.array[cache_blk].address; - int_cache[ftl_cmd_cnt].cache.changed = - Cache.array[cache_blk].changed; -#endif - GLOB_LLD_MemCopy_CMD(pDest, pData, DeviceInfo.wPageDataSize, flag); - ftl_cmd_cnt++; -#else - memcpy(pDest, pData, DeviceInfo.wPageDataSize); -#endif - if (Cache.array[cache_blk].use_cnt < MAX_WORD_VALUE) - Cache.array[cache_blk].use_cnt++; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Cache_Write -* Inputs: none -* Outputs: PASS=0 / FAIL=1 -* Description: It writes least frequently used Cache block to flash if it -* has been changed -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static int FTL_Cache_Write(void) -{ - int i, bResult = PASS; - u16 bNO, least_count = 0xFFFF; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - FTL_Calculate_LRU(); - - bNO = Cache.LRU; - nand_dbg_print(NAND_DBG_DEBUG, "FTL_Cache_Write: " - "Least used cache block is %d\n", bNO); - - if (Cache.array[bNO].changed != SET) - return bResult; - - nand_dbg_print(NAND_DBG_DEBUG, "FTL_Cache_Write: Cache" - " Block %d containing logical block %d is dirty\n", - bNO, - (u32)(Cache.array[bNO].address >> - DeviceInfo.nBitsInBlockDataSize)); -#if CMD_DMA -#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE - int_cache[ftl_cmd_cnt].item = bNO; - int_cache[ftl_cmd_cnt].cache.address = - Cache.array[bNO].address; - int_cache[ftl_cmd_cnt].cache.changed = CLEAR; -#endif -#endif - bResult = write_back_to_l2_cache(Cache.array[bNO].buf, - Cache.array[bNO].address); - if (bResult != ERR) - Cache.array[bNO].changed = CLEAR; - - least_count = Cache.array[bNO].use_cnt; - - for (i = 0; i < CACHE_ITEM_NUM; i++) { - if (i == bNO) - continue; - if (Cache.array[i].use_cnt > 0) - Cache.array[i].use_cnt -= least_count; - } - - return bResult; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Cache_Read -* Inputs: Page address -* Outputs: PASS=0 / FAIL=1 -* Description: It reads the block from device in Cache Block -* Set the LRU count to 1 -* Mark the Cache Block as clean -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static int FTL_Cache_Read(u64 logical_addr) -{ - u64 item_addr, phy_addr; - u16 num; - int ret; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - num = Cache.LRU; /* The LRU cache item will be overwritten */ - - item_addr = (u64)GLOB_u64_Div(logical_addr, Cache.cache_item_size) * - Cache.cache_item_size; - Cache.array[num].address = item_addr; - Cache.array[num].use_cnt = 1; - Cache.array[num].changed = CLEAR; - -#if CMD_DMA -#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE - int_cache[ftl_cmd_cnt].item = num; - int_cache[ftl_cmd_cnt].cache.address = - Cache.array[num].address; - int_cache[ftl_cmd_cnt].cache.changed = - Cache.array[num].changed; -#endif -#endif - /* - * Search in L2 Cache. If hit, fill data into L1 Cache item buffer, - * Otherwise, read it from NAND - */ - ret = search_l2_cache(Cache.array[num].buf, logical_addr); - if (PASS == ret) /* Hit in L2 Cache */ - return ret; - - /* Compute the physical start address of NAND device according to */ - /* the logical start address of the cache item (LRU cache item) */ - phy_addr = FTL_Get_Physical_Block_Addr(item_addr) + - GLOB_u64_Remainder(item_addr, 2); - - return FTL_Cache_Read_All(Cache.array[num].buf, phy_addr); -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Check_Block_Table -* Inputs: ? -* Outputs: PASS=0 / FAIL=1 -* Description: It checks the correctness of each block table entry -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static int FTL_Check_Block_Table(int wOldTable) -{ - u32 i; - int wResult = PASS; - u32 blk_idx; - u32 *pbt = (u32 *)g_pBlockTable; - u8 *pFlag = flag_check_blk_table; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (NULL != pFlag) { - memset(pFlag, FAIL, DeviceInfo.wDataBlockNum); - for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { - blk_idx = (u32)(pbt[i] & (~BAD_BLOCK)); - - /* - * 20081006/KBV - Changed to pFlag[i] reference - * to avoid buffer overflow - */ - - /* - * 2008-10-20 Yunpeng Note: This change avoid - * buffer overflow, but changed function of - * the code, so it should be re-write later - */ - if ((blk_idx > DeviceInfo.wSpectraEndBlock) || - PASS == pFlag[i]) { - wResult = FAIL; - break; - } else { - pFlag[i] = PASS; - } - } - } - - return wResult; -} - - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Write_Block_Table -* Inputs: flasg -* Outputs: 0=Block Table was updated. No write done. 1=Block write needs to -* happen. -1 Error -* Description: It writes the block table -* Block table always mapped to LBA 0 which inturn mapped -* to any physical block -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static int FTL_Write_Block_Table(int wForce) -{ - u32 *pbt = (u32 *)g_pBlockTable; - int wSuccess = PASS; - u32 wTempBlockTableIndex; - u16 bt_pages, new_bt_offset; - u8 blockchangeoccured = 0; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - bt_pages = FTL_Get_Block_Table_Flash_Size_Pages(); - - if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) - return 0; - - if (PASS == wForce) { - g_wBlockTableOffset = - (u16)(DeviceInfo.wPagesPerBlock - bt_pages); -#if CMD_DMA - p_BTableChangesDelta = - (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - - p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; - p_BTableChangesDelta->g_wBlockTableOffset = - g_wBlockTableOffset; - p_BTableChangesDelta->ValidFields = 0x01; -#endif - } - - nand_dbg_print(NAND_DBG_DEBUG, - "Inside FTL_Write_Block_Table: block %d Page:%d\n", - g_wBlockTableIndex, g_wBlockTableOffset); - - do { - new_bt_offset = g_wBlockTableOffset + bt_pages + 1; - if ((0 == (new_bt_offset % DeviceInfo.wPagesPerBlock)) || - (new_bt_offset > DeviceInfo.wPagesPerBlock) || - (FAIL == wSuccess)) { - wTempBlockTableIndex = FTL_Replace_Block_Table(); - if (BAD_BLOCK == wTempBlockTableIndex) - return ERR; - if (!blockchangeoccured) { - bt_block_changed = 1; - blockchangeoccured = 1; - } - - g_wBlockTableIndex = wTempBlockTableIndex; - g_wBlockTableOffset = 0; - pbt[BLOCK_TABLE_INDEX] = g_wBlockTableIndex; -#if CMD_DMA - p_BTableChangesDelta = - (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - - p_BTableChangesDelta->ftl_cmd_cnt = - ftl_cmd_cnt; - p_BTableChangesDelta->g_wBlockTableOffset = - g_wBlockTableOffset; - p_BTableChangesDelta->g_wBlockTableIndex = - g_wBlockTableIndex; - p_BTableChangesDelta->ValidFields = 0x03; - - p_BTableChangesDelta = - (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += - sizeof(struct BTableChangesDelta); - - p_BTableChangesDelta->ftl_cmd_cnt = - ftl_cmd_cnt; - p_BTableChangesDelta->BT_Index = - BLOCK_TABLE_INDEX; - p_BTableChangesDelta->BT_Entry_Value = - pbt[BLOCK_TABLE_INDEX]; - p_BTableChangesDelta->ValidFields = 0x0C; -#endif - } - - wSuccess = FTL_Write_Block_Table_Data(); - if (FAIL == wSuccess) - MARK_BLOCK_AS_BAD(pbt[BLOCK_TABLE_INDEX]); - } while (FAIL == wSuccess); - - g_cBlockTableStatus = CURRENT_BLOCK_TABLE; - - return 1; -} - -static int force_format_nand(void) -{ - u32 i; - - /* Force erase the whole unprotected physical partiton of NAND */ - printk(KERN_ALERT "Start to force erase whole NAND device ...\n"); - printk(KERN_ALERT "From phyical block %d to %d\n", - DeviceInfo.wSpectraStartBlock, DeviceInfo.wSpectraEndBlock); - for (i = DeviceInfo.wSpectraStartBlock; i <= DeviceInfo.wSpectraEndBlock; i++) { - if (GLOB_LLD_Erase_Block(i)) - printk(KERN_ERR "Failed to force erase NAND block %d\n", i); - } - printk(KERN_ALERT "Force Erase ends. Please reboot the system ...\n"); - while(1); - - return PASS; -} - -int GLOB_FTL_Flash_Format(void) -{ - //return FTL_Format_Flash(1); - return force_format_nand(); - -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Search_Block_Table_IN_Block -* Inputs: Block Number -* Pointer to page -* Outputs: PASS / FAIL -* Page contatining the block table -* Description: It searches the block table in the block -* passed as an argument. -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static int FTL_Search_Block_Table_IN_Block(u32 BT_Block, - u8 BT_Tag, u16 *Page) -{ - u16 i, j, k; - u16 Result = PASS; - u16 Last_IPF = 0; - u8 BT_Found = 0; - u8 *tagarray; - u8 *tempbuf = tmp_buf_search_bt_in_block; - u8 *pSpareBuf = spare_buf_search_bt_in_block; - u8 *pSpareBufBTLastPage = spare_buf_bt_search_bt_in_block; - u8 bt_flag_last_page = 0xFF; - u8 search_in_previous_pages = 0; - u16 bt_pages; - - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - nand_dbg_print(NAND_DBG_DEBUG, - "Searching block table in %u block\n", - (unsigned int)BT_Block); - - bt_pages = FTL_Get_Block_Table_Flash_Size_Pages(); - - for (i = bt_pages; i < DeviceInfo.wPagesPerBlock; - i += (bt_pages + 1)) { - nand_dbg_print(NAND_DBG_DEBUG, - "Searching last IPF: %d\n", i); - Result = GLOB_LLD_Read_Page_Main_Polling(tempbuf, - BT_Block, i, 1); - - if (0 == memcmp(tempbuf, g_pIPF, DeviceInfo.wPageDataSize)) { - if ((i + bt_pages + 1) < DeviceInfo.wPagesPerBlock) { - continue; - } else { - search_in_previous_pages = 1; - Last_IPF = i; - } - } - - if (!search_in_previous_pages) { - if (i != bt_pages) { - i -= (bt_pages + 1); - Last_IPF = i; - } - } - - if (0 == Last_IPF) - break; - - if (!search_in_previous_pages) { - i = i + 1; - nand_dbg_print(NAND_DBG_DEBUG, - "Reading the spare area of Block %u Page %u", - (unsigned int)BT_Block, i); - Result = GLOB_LLD_Read_Page_Spare(pSpareBuf, - BT_Block, i, 1); - nand_dbg_print(NAND_DBG_DEBUG, - "Reading the spare area of Block %u Page %u", - (unsigned int)BT_Block, i + bt_pages - 1); - Result = GLOB_LLD_Read_Page_Spare(pSpareBufBTLastPage, - BT_Block, i + bt_pages - 1, 1); - - k = 0; - j = FTL_Extract_Block_Table_Tag(pSpareBuf, &tagarray); - if (j) { - for (; k < j; k++) { - if (tagarray[k] == BT_Tag) - break; - } - } - - if (k < j) - bt_flag = tagarray[k]; - else - Result = FAIL; - - if (Result == PASS) { - k = 0; - j = FTL_Extract_Block_Table_Tag( - pSpareBufBTLastPage, &tagarray); - if (j) { - for (; k < j; k++) { - if (tagarray[k] == BT_Tag) - break; - } - } - - if (k < j) - bt_flag_last_page = tagarray[k]; - else - Result = FAIL; - - if (Result == PASS) { - if (bt_flag == bt_flag_last_page) { - nand_dbg_print(NAND_DBG_DEBUG, - "Block table is found" - " in page after IPF " - "at block %d " - "page %d\n", - (int)BT_Block, i); - BT_Found = 1; - *Page = i; - g_cBlockTableStatus = - CURRENT_BLOCK_TABLE; - break; - } else { - Result = FAIL; - } - } - } - } - - if (search_in_previous_pages) - i = i - bt_pages; - else - i = i - (bt_pages + 1); - - Result = PASS; - - nand_dbg_print(NAND_DBG_DEBUG, - "Reading the spare area of Block %d Page %d", - (int)BT_Block, i); - - Result = GLOB_LLD_Read_Page_Spare(pSpareBuf, BT_Block, i, 1); - nand_dbg_print(NAND_DBG_DEBUG, - "Reading the spare area of Block %u Page %u", - (unsigned int)BT_Block, i + bt_pages - 1); - - Result = GLOB_LLD_Read_Page_Spare(pSpareBufBTLastPage, - BT_Block, i + bt_pages - 1, 1); - - k = 0; - j = FTL_Extract_Block_Table_Tag(pSpareBuf, &tagarray); - if (j) { - for (; k < j; k++) { - if (tagarray[k] == BT_Tag) - break; - } - } - - if (k < j) - bt_flag = tagarray[k]; - else - Result = FAIL; - - if (Result == PASS) { - k = 0; - j = FTL_Extract_Block_Table_Tag(pSpareBufBTLastPage, - &tagarray); - if (j) { - for (; k < j; k++) { - if (tagarray[k] == BT_Tag) - break; - } - } - - if (k < j) { - bt_flag_last_page = tagarray[k]; - } else { - Result = FAIL; - break; - } - - if (Result == PASS) { - if (bt_flag == bt_flag_last_page) { - nand_dbg_print(NAND_DBG_DEBUG, - "Block table is found " - "in page prior to IPF " - "at block %u page %d\n", - (unsigned int)BT_Block, i); - BT_Found = 1; - *Page = i; - g_cBlockTableStatus = - IN_PROGRESS_BLOCK_TABLE; - break; - } else { - Result = FAIL; - break; - } - } - } - } - - if (Result == FAIL) { - if ((Last_IPF > bt_pages) && (i < Last_IPF) && (!BT_Found)) { - BT_Found = 1; - *Page = i - (bt_pages + 1); - } - if ((Last_IPF == bt_pages) && (i < Last_IPF) && (!BT_Found)) - goto func_return; - } - - if (Last_IPF == 0) { - i = 0; - Result = PASS; - nand_dbg_print(NAND_DBG_DEBUG, "Reading the spare area of " - "Block %u Page %u", (unsigned int)BT_Block, i); - - Result = GLOB_LLD_Read_Page_Spare(pSpareBuf, BT_Block, i, 1); - nand_dbg_print(NAND_DBG_DEBUG, - "Reading the spare area of Block %u Page %u", - (unsigned int)BT_Block, i + bt_pages - 1); - Result = GLOB_LLD_Read_Page_Spare(pSpareBufBTLastPage, - BT_Block, i + bt_pages - 1, 1); - - k = 0; - j = FTL_Extract_Block_Table_Tag(pSpareBuf, &tagarray); - if (j) { - for (; k < j; k++) { - if (tagarray[k] == BT_Tag) - break; - } - } - - if (k < j) - bt_flag = tagarray[k]; - else - Result = FAIL; - - if (Result == PASS) { - k = 0; - j = FTL_Extract_Block_Table_Tag(pSpareBufBTLastPage, - &tagarray); - if (j) { - for (; k < j; k++) { - if (tagarray[k] == BT_Tag) - break; - } - } - - if (k < j) - bt_flag_last_page = tagarray[k]; - else - Result = FAIL; - - if (Result == PASS) { - if (bt_flag == bt_flag_last_page) { - nand_dbg_print(NAND_DBG_DEBUG, - "Block table is found " - "in page after IPF at " - "block %u page %u\n", - (unsigned int)BT_Block, - (unsigned int)i); - BT_Found = 1; - *Page = i; - g_cBlockTableStatus = - CURRENT_BLOCK_TABLE; - goto func_return; - } else { - Result = FAIL; - } - } - } - - if (Result == FAIL) - goto func_return; - } -func_return: - return Result; -} - -u8 *get_blk_table_start_addr(void) -{ - return g_pBlockTable; -} - -unsigned long get_blk_table_len(void) -{ - return DeviceInfo.wDataBlockNum * sizeof(u32); -} - -u8 *get_wear_leveling_table_start_addr(void) -{ - return g_pWearCounter; -} - -unsigned long get_wear_leveling_table_len(void) -{ - return DeviceInfo.wDataBlockNum * sizeof(u8); -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Read_Block_Table -* Inputs: none -* Outputs: PASS / FAIL -* Description: read the flash spare area and find a block containing the -* most recent block table(having largest block_table_counter). -* Find the last written Block table in this block. -* Check the correctness of Block Table -* If CDMA is enabled, this function is called in -* polling mode. -* We don't need to store changes in Block table in this -* function as it is called only at initialization -* -* Note: Currently this function is called at initialization -* before any read/erase/write command issued to flash so, -* there is no need to wait for CDMA list to complete as of now -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static int FTL_Read_Block_Table(void) -{ - u16 i = 0; - int k, j; - u8 *tempBuf, *tagarray; - int wResult = FAIL; - int status = FAIL; - u8 block_table_found = 0; - int search_result; - u32 Block; - u16 Page = 0; - u16 PageCount; - u16 bt_pages; - int wBytesCopied = 0, tempvar; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - tempBuf = tmp_buf1_read_blk_table; - bt_pages = FTL_Get_Block_Table_Flash_Size_Pages(); - - for (j = DeviceInfo.wSpectraStartBlock; - j <= (int)DeviceInfo.wSpectraEndBlock; - j++) { - status = GLOB_LLD_Read_Page_Spare(tempBuf, j, 0, 1); - k = 0; - i = FTL_Extract_Block_Table_Tag(tempBuf, &tagarray); - if (i) { - status = GLOB_LLD_Read_Page_Main_Polling(tempBuf, - j, 0, 1); - for (; k < i; k++) { - if (tagarray[k] == tempBuf[3]) - break; - } - } - - if (k < i) - k = tagarray[k]; - else - continue; - - nand_dbg_print(NAND_DBG_DEBUG, - "Block table is contained in Block %d %d\n", - (unsigned int)j, (unsigned int)k); - - if (g_pBTBlocks[k-FIRST_BT_ID] == BTBLOCK_INVAL) { - g_pBTBlocks[k-FIRST_BT_ID] = j; - block_table_found = 1; - } else { - printk(KERN_ERR "FTL_Read_Block_Table -" - "This should never happens. " - "Two block table have same counter %u!\n", k); - } - } - - if (block_table_found) { - if (g_pBTBlocks[FIRST_BT_ID - FIRST_BT_ID] != BTBLOCK_INVAL && - g_pBTBlocks[LAST_BT_ID - FIRST_BT_ID] != BTBLOCK_INVAL) { - j = LAST_BT_ID; - while ((j > FIRST_BT_ID) && - (g_pBTBlocks[j - FIRST_BT_ID] != BTBLOCK_INVAL)) - j--; - if (j == FIRST_BT_ID) { - j = LAST_BT_ID; - last_erased = LAST_BT_ID; - } else { - last_erased = (u8)j + 1; - while ((j > FIRST_BT_ID) && (BTBLOCK_INVAL == - g_pBTBlocks[j - FIRST_BT_ID])) - j--; - } - } else { - j = FIRST_BT_ID; - while (g_pBTBlocks[j - FIRST_BT_ID] == BTBLOCK_INVAL) - j++; - last_erased = (u8)j; - while ((j < LAST_BT_ID) && (BTBLOCK_INVAL != - g_pBTBlocks[j - FIRST_BT_ID])) - j++; - if (g_pBTBlocks[j-FIRST_BT_ID] == BTBLOCK_INVAL) - j--; - } - - if (last_erased > j) - j += (1 + LAST_BT_ID - FIRST_BT_ID); - - for (; (j >= last_erased) && (FAIL == wResult); j--) { - i = (j - FIRST_BT_ID) % - (1 + LAST_BT_ID - FIRST_BT_ID); - search_result = - FTL_Search_Block_Table_IN_Block(g_pBTBlocks[i], - i + FIRST_BT_ID, &Page); - if (g_cBlockTableStatus == IN_PROGRESS_BLOCK_TABLE) - block_table_found = 0; - - while ((search_result == PASS) && (FAIL == wResult)) { - nand_dbg_print(NAND_DBG_DEBUG, - "FTL_Read_Block_Table:" - "Block: %u Page: %u " - "contains block table\n", - (unsigned int)g_pBTBlocks[i], - (unsigned int)Page); - - tempBuf = tmp_buf2_read_blk_table; - - for (k = 0; k < bt_pages; k++) { - Block = g_pBTBlocks[i]; - PageCount = 1; - - status = - GLOB_LLD_Read_Page_Main_Polling( - tempBuf, Block, Page, PageCount); - - tempvar = k ? 0 : 4; - - wBytesCopied += - FTL_Copy_Block_Table_From_Flash( - tempBuf + tempvar, - DeviceInfo.wPageDataSize - tempvar, - wBytesCopied); - - Page++; - } - - wResult = FTL_Check_Block_Table(FAIL); - if (FAIL == wResult) { - block_table_found = 0; - if (Page > bt_pages) - Page -= ((bt_pages<<1) + 1); - else - search_result = FAIL; - } - } - } - } - - if (PASS == wResult) { - if (!block_table_found) - FTL_Execute_SPL_Recovery(); - - if (g_cBlockTableStatus == IN_PROGRESS_BLOCK_TABLE) - g_wBlockTableOffset = (u16)Page + 1; - else - g_wBlockTableOffset = (u16)Page - bt_pages; - - g_wBlockTableIndex = (u32)g_pBTBlocks[i]; - -#if CMD_DMA - if (DeviceInfo.MLCDevice) - memcpy(g_pBTStartingCopy, g_pBlockTable, - DeviceInfo.wDataBlockNum * sizeof(u32) - + DeviceInfo.wDataBlockNum * sizeof(u8) - + DeviceInfo.wDataBlockNum * sizeof(u16)); - else - memcpy(g_pBTStartingCopy, g_pBlockTable, - DeviceInfo.wDataBlockNum * sizeof(u32) - + DeviceInfo.wDataBlockNum * sizeof(u8)); -#endif - } - - if (FAIL == wResult) - printk(KERN_ERR "Yunpeng - " - "Can not find valid spectra block table!\n"); - -#if AUTO_FORMAT_FLASH - if (FAIL == wResult) { - nand_dbg_print(NAND_DBG_DEBUG, "doing auto-format\n"); - wResult = FTL_Format_Flash(0); - } -#endif - - return wResult; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Get_Page_Num -* Inputs: Size in bytes -* Outputs: Size in pages -* Description: It calculates the pages required for the length passed -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static u32 FTL_Get_Page_Num(u64 length) -{ - return (u32)((length >> DeviceInfo.nBitsInPageDataSize) + - (GLOB_u64_Remainder(length , 1) > 0 ? 1 : 0)); -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Get_Physical_Block_Addr -* Inputs: Block Address (byte format) -* Outputs: Physical address of the block. -* Description: It translates LBA to PBA by returning address stored -* at the LBA location in the block table -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static u64 FTL_Get_Physical_Block_Addr(u64 logical_addr) -{ - u32 *pbt; - u64 physical_addr; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - pbt = (u32 *)g_pBlockTable; - physical_addr = (u64) DeviceInfo.wBlockDataSize * - (pbt[BLK_FROM_ADDR(logical_addr)] & (~BAD_BLOCK)); - - return physical_addr; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Get_Block_Index -* Inputs: Physical Block no. -* Outputs: Logical block no. /BAD_BLOCK -* Description: It returns the logical block no. for the PBA passed -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static u32 FTL_Get_Block_Index(u32 wBlockNum) -{ - u32 *pbt = (u32 *)g_pBlockTable; - u32 i; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - for (i = 0; i < DeviceInfo.wDataBlockNum; i++) - if (wBlockNum == (pbt[i] & (~BAD_BLOCK))) - return i; - - return BAD_BLOCK; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_FTL_Wear_Leveling -* Inputs: none -* Outputs: PASS=0 -* Description: This is static wear leveling (done by explicit call) -* do complete static wear leveling -* do complete garbage collection -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int GLOB_FTL_Wear_Leveling(void) -{ - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - FTL_Static_Wear_Leveling(); - GLOB_FTL_Garbage_Collection(); - - return PASS; -} - -static void find_least_most_worn(u8 *chg, - u32 *least_idx, u8 *least_cnt, - u32 *most_idx, u8 *most_cnt) -{ - u32 *pbt = (u32 *)g_pBlockTable; - u32 idx; - u8 cnt; - int i; - - for (i = BLOCK_TABLE_INDEX + 1; i < DeviceInfo.wDataBlockNum; i++) { - if (IS_BAD_BLOCK(i) || PASS == chg[i]) - continue; - - idx = (u32) ((~BAD_BLOCK) & pbt[i]); - cnt = g_pWearCounter[idx - DeviceInfo.wSpectraStartBlock]; - - if (IS_SPARE_BLOCK(i)) { - if (cnt > *most_cnt) { - *most_cnt = cnt; - *most_idx = idx; - } - } - - if (IS_DATA_BLOCK(i)) { - if (cnt < *least_cnt) { - *least_cnt = cnt; - *least_idx = idx; - } - } - - if (PASS == chg[*most_idx] || PASS == chg[*least_idx]) { - debug_boundary_error(*most_idx, - DeviceInfo.wDataBlockNum, 0); - debug_boundary_error(*least_idx, - DeviceInfo.wDataBlockNum, 0); - continue; - } - } -} - -static int move_blks_for_wear_leveling(u8 *chg, - u32 *least_idx, u32 *rep_blk_num, int *result) -{ - u32 *pbt = (u32 *)g_pBlockTable; - u32 rep_blk; - int j, ret_cp_blk, ret_erase; - int ret = PASS; - - chg[*least_idx] = PASS; - debug_boundary_error(*least_idx, DeviceInfo.wDataBlockNum, 0); - - rep_blk = FTL_Replace_MWBlock(); - if (rep_blk != BAD_BLOCK) { - nand_dbg_print(NAND_DBG_DEBUG, - "More than two spare blocks exist so do it\n"); - nand_dbg_print(NAND_DBG_DEBUG, "Block Replaced is %d\n", - rep_blk); - - chg[rep_blk] = PASS; - - if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) { - g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; - FTL_Write_IN_Progress_Block_Table_Page(); - } - - for (j = 0; j < RETRY_TIMES; j++) { - ret_cp_blk = FTL_Copy_Block((u64)(*least_idx) * - DeviceInfo.wBlockDataSize, - (u64)rep_blk * DeviceInfo.wBlockDataSize); - if (FAIL == ret_cp_blk) { - ret_erase = GLOB_FTL_Block_Erase((u64)rep_blk - * DeviceInfo.wBlockDataSize); - if (FAIL == ret_erase) - MARK_BLOCK_AS_BAD(pbt[rep_blk]); - } else { - nand_dbg_print(NAND_DBG_DEBUG, - "FTL_Copy_Block == OK\n"); - break; - } - } - - if (j < RETRY_TIMES) { - u32 tmp; - u32 old_idx = FTL_Get_Block_Index(*least_idx); - u32 rep_idx = FTL_Get_Block_Index(rep_blk); - tmp = (u32)(DISCARD_BLOCK | pbt[old_idx]); - pbt[old_idx] = (u32)((~SPARE_BLOCK) & - pbt[rep_idx]); - pbt[rep_idx] = tmp; -#if CMD_DMA - p_BTableChangesDelta = (struct BTableChangesDelta *) - g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - p_BTableChangesDelta->ftl_cmd_cnt = - ftl_cmd_cnt; - p_BTableChangesDelta->BT_Index = old_idx; - p_BTableChangesDelta->BT_Entry_Value = pbt[old_idx]; - p_BTableChangesDelta->ValidFields = 0x0C; - - p_BTableChangesDelta = (struct BTableChangesDelta *) - g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - - p_BTableChangesDelta->ftl_cmd_cnt = - ftl_cmd_cnt; - p_BTableChangesDelta->BT_Index = rep_idx; - p_BTableChangesDelta->BT_Entry_Value = pbt[rep_idx]; - p_BTableChangesDelta->ValidFields = 0x0C; -#endif - } else { - pbt[FTL_Get_Block_Index(rep_blk)] |= BAD_BLOCK; -#if CMD_DMA - p_BTableChangesDelta = (struct BTableChangesDelta *) - g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - - p_BTableChangesDelta->ftl_cmd_cnt = - ftl_cmd_cnt; - p_BTableChangesDelta->BT_Index = - FTL_Get_Block_Index(rep_blk); - p_BTableChangesDelta->BT_Entry_Value = - pbt[FTL_Get_Block_Index(rep_blk)]; - p_BTableChangesDelta->ValidFields = 0x0C; -#endif - *result = FAIL; - ret = FAIL; - } - - if (((*rep_blk_num)++) > WEAR_LEVELING_BLOCK_NUM) - ret = FAIL; - } else { - printk(KERN_ERR "Less than 3 spare blocks exist so quit\n"); - ret = FAIL; - } - - return ret; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Static_Wear_Leveling -* Inputs: none -* Outputs: PASS=0 / FAIL=1 -* Description: This is static wear leveling (done by explicit call) -* search for most&least used -* if difference < GATE: -* update the block table with exhange -* mark block table in flash as IN_PROGRESS -* copy flash block -* the caller should handle GC clean up after calling this function -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int FTL_Static_Wear_Leveling(void) -{ - u8 most_worn_cnt; - u8 least_worn_cnt; - u32 most_worn_idx; - u32 least_worn_idx; - int result = PASS; - int go_on = PASS; - u32 replaced_blks = 0; - u8 *chang_flag = flags_static_wear_leveling; - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (!chang_flag) - return FAIL; - - memset(chang_flag, FAIL, DeviceInfo.wDataBlockNum); - while (go_on == PASS) { - nand_dbg_print(NAND_DBG_DEBUG, - "starting static wear leveling\n"); - most_worn_cnt = 0; - least_worn_cnt = 0xFF; - least_worn_idx = BLOCK_TABLE_INDEX; - most_worn_idx = BLOCK_TABLE_INDEX; - - find_least_most_worn(chang_flag, &least_worn_idx, - &least_worn_cnt, &most_worn_idx, &most_worn_cnt); - - nand_dbg_print(NAND_DBG_DEBUG, - "Used and least worn is block %u, whos count is %u\n", - (unsigned int)least_worn_idx, - (unsigned int)least_worn_cnt); - - nand_dbg_print(NAND_DBG_DEBUG, - "Free and most worn is block %u, whos count is %u\n", - (unsigned int)most_worn_idx, - (unsigned int)most_worn_cnt); - - if ((most_worn_cnt > least_worn_cnt) && - (most_worn_cnt - least_worn_cnt > WEAR_LEVELING_GATE)) - go_on = move_blks_for_wear_leveling(chang_flag, - &least_worn_idx, &replaced_blks, &result); - else - go_on = FAIL; - } - - return result; -} - -#if CMD_DMA -static int do_garbage_collection(u32 discard_cnt) -{ - u32 *pbt = (u32 *)g_pBlockTable; - u32 pba; - u8 bt_block_erased = 0; - int i, cnt, ret = FAIL; - u64 addr; - - i = 0; - while ((i < DeviceInfo.wDataBlockNum) && (discard_cnt > 0) && - ((ftl_cmd_cnt + 28) < 256)) { - if (((pbt[i] & BAD_BLOCK) != BAD_BLOCK) && - (pbt[i] & DISCARD_BLOCK)) { - if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) { - g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; - FTL_Write_IN_Progress_Block_Table_Page(); - } - - addr = FTL_Get_Physical_Block_Addr((u64)i * - DeviceInfo.wBlockDataSize); - pba = BLK_FROM_ADDR(addr); - - for (cnt = FIRST_BT_ID; cnt <= LAST_BT_ID; cnt++) { - if (pba == g_pBTBlocks[cnt - FIRST_BT_ID]) { - nand_dbg_print(NAND_DBG_DEBUG, - "GC will erase BT block %u\n", - (unsigned int)pba); - discard_cnt--; - i++; - bt_block_erased = 1; - break; - } - } - - if (bt_block_erased) { - bt_block_erased = 0; - continue; - } - - addr = FTL_Get_Physical_Block_Addr((u64)i * - DeviceInfo.wBlockDataSize); - - if (PASS == GLOB_FTL_Block_Erase(addr)) { - pbt[i] &= (u32)(~DISCARD_BLOCK); - pbt[i] |= (u32)(SPARE_BLOCK); - p_BTableChangesDelta = - (struct BTableChangesDelta *) - g_pBTDelta_Free; - g_pBTDelta_Free += - sizeof(struct BTableChangesDelta); - p_BTableChangesDelta->ftl_cmd_cnt = - ftl_cmd_cnt - 1; - p_BTableChangesDelta->BT_Index = i; - p_BTableChangesDelta->BT_Entry_Value = pbt[i]; - p_BTableChangesDelta->ValidFields = 0x0C; - discard_cnt--; - ret = PASS; - } else { - MARK_BLOCK_AS_BAD(pbt[i]); - } - } - - i++; - } - - return ret; -} - -#else -static int do_garbage_collection(u32 discard_cnt) -{ - u32 *pbt = (u32 *)g_pBlockTable; - u32 pba; - u8 bt_block_erased = 0; - int i, cnt, ret = FAIL; - u64 addr; - - i = 0; - while ((i < DeviceInfo.wDataBlockNum) && (discard_cnt > 0)) { - if (((pbt[i] & BAD_BLOCK) != BAD_BLOCK) && - (pbt[i] & DISCARD_BLOCK)) { - if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) { - g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; - FTL_Write_IN_Progress_Block_Table_Page(); - } - - addr = FTL_Get_Physical_Block_Addr((u64)i * - DeviceInfo.wBlockDataSize); - pba = BLK_FROM_ADDR(addr); - - for (cnt = FIRST_BT_ID; cnt <= LAST_BT_ID; cnt++) { - if (pba == g_pBTBlocks[cnt - FIRST_BT_ID]) { - nand_dbg_print(NAND_DBG_DEBUG, - "GC will erase BT block %d\n", - pba); - discard_cnt--; - i++; - bt_block_erased = 1; - break; - } - } - - if (bt_block_erased) { - bt_block_erased = 0; - continue; - } - - /* If the discard block is L2 cache block, then just skip it */ - for (cnt = 0; cnt < BLK_NUM_FOR_L2_CACHE; cnt++) { - if (cache_l2.blk_array[cnt] == pba) { - nand_dbg_print(NAND_DBG_DEBUG, - "GC will erase L2 cache blk %d\n", - pba); - break; - } - } - if (cnt < BLK_NUM_FOR_L2_CACHE) { /* Skip it */ - discard_cnt--; - i++; - continue; - } - - addr = FTL_Get_Physical_Block_Addr((u64)i * - DeviceInfo.wBlockDataSize); - - if (PASS == GLOB_FTL_Block_Erase(addr)) { - pbt[i] &= (u32)(~DISCARD_BLOCK); - pbt[i] |= (u32)(SPARE_BLOCK); - discard_cnt--; - ret = PASS; - } else { - MARK_BLOCK_AS_BAD(pbt[i]); - } - } - - i++; - } - - return ret; -} -#endif - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_FTL_Garbage_Collection -* Inputs: none -* Outputs: PASS / FAIL (returns the number of un-erased blocks -* Description: search the block table for all discarded blocks to erase -* for each discarded block: -* set the flash block to IN_PROGRESS -* erase the block -* update the block table -* write the block table to flash -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int GLOB_FTL_Garbage_Collection(void) -{ - u32 i; - u32 wDiscard = 0; - int wResult = FAIL; - u32 *pbt = (u32 *)g_pBlockTable; - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (GC_Called) { - printk(KERN_ALERT "GLOB_FTL_Garbage_Collection() " - "has been re-entered! Exit.\n"); - return PASS; - } - - GC_Called = 1; - - GLOB_FTL_BT_Garbage_Collection(); - - for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { - if (IS_DISCARDED_BLOCK(i)) - wDiscard++; - } - - if (wDiscard <= 0) { - GC_Called = 0; - return wResult; - } - - nand_dbg_print(NAND_DBG_DEBUG, - "Found %d discarded blocks\n", wDiscard); - - FTL_Write_Block_Table(FAIL); - - wResult = do_garbage_collection(wDiscard); - - FTL_Write_Block_Table(FAIL); - - GC_Called = 0; - - return wResult; -} - - -#if CMD_DMA -static int do_bt_garbage_collection(void) -{ - u32 pba, lba; - u32 *pbt = (u32 *)g_pBlockTable; - u32 *pBTBlocksNode = (u32 *)g_pBTBlocks; - u64 addr; - int i, ret = FAIL; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (BT_GC_Called) - return PASS; - - BT_GC_Called = 1; - - for (i = last_erased; (i <= LAST_BT_ID) && - (g_pBTBlocks[((i + 2) % (1 + LAST_BT_ID - FIRST_BT_ID)) + - FIRST_BT_ID - FIRST_BT_ID] != BTBLOCK_INVAL) && - ((ftl_cmd_cnt + 28)) < 256; i++) { - pba = pBTBlocksNode[i - FIRST_BT_ID]; - lba = FTL_Get_Block_Index(pba); - nand_dbg_print(NAND_DBG_DEBUG, - "do_bt_garbage_collection: pba %d, lba %d\n", - pba, lba); - nand_dbg_print(NAND_DBG_DEBUG, - "Block Table Entry: %d", pbt[lba]); - - if (((pbt[lba] & BAD_BLOCK) != BAD_BLOCK) && - (pbt[lba] & DISCARD_BLOCK)) { - nand_dbg_print(NAND_DBG_DEBUG, - "do_bt_garbage_collection_cdma: " - "Erasing Block tables present in block %d\n", - pba); - addr = FTL_Get_Physical_Block_Addr((u64)lba * - DeviceInfo.wBlockDataSize); - if (PASS == GLOB_FTL_Block_Erase(addr)) { - pbt[lba] &= (u32)(~DISCARD_BLOCK); - pbt[lba] |= (u32)(SPARE_BLOCK); - - p_BTableChangesDelta = - (struct BTableChangesDelta *) - g_pBTDelta_Free; - g_pBTDelta_Free += - sizeof(struct BTableChangesDelta); - - p_BTableChangesDelta->ftl_cmd_cnt = - ftl_cmd_cnt - 1; - p_BTableChangesDelta->BT_Index = lba; - p_BTableChangesDelta->BT_Entry_Value = - pbt[lba]; - - p_BTableChangesDelta->ValidFields = 0x0C; - - ret = PASS; - pBTBlocksNode[last_erased - FIRST_BT_ID] = - BTBLOCK_INVAL; - nand_dbg_print(NAND_DBG_DEBUG, - "resetting bt entry at index %d " - "value %d\n", i, - pBTBlocksNode[i - FIRST_BT_ID]); - if (last_erased == LAST_BT_ID) - last_erased = FIRST_BT_ID; - else - last_erased++; - } else { - MARK_BLOCK_AS_BAD(pbt[lba]); - } - } - } - - BT_GC_Called = 0; - - return ret; -} - -#else -static int do_bt_garbage_collection(void) -{ - u32 pba, lba; - u32 *pbt = (u32 *)g_pBlockTable; - u32 *pBTBlocksNode = (u32 *)g_pBTBlocks; - u64 addr; - int i, ret = FAIL; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (BT_GC_Called) - return PASS; - - BT_GC_Called = 1; - - for (i = last_erased; (i <= LAST_BT_ID) && - (g_pBTBlocks[((i + 2) % (1 + LAST_BT_ID - FIRST_BT_ID)) + - FIRST_BT_ID - FIRST_BT_ID] != BTBLOCK_INVAL); i++) { - pba = pBTBlocksNode[i - FIRST_BT_ID]; - lba = FTL_Get_Block_Index(pba); - nand_dbg_print(NAND_DBG_DEBUG, - "do_bt_garbage_collection_cdma: pba %d, lba %d\n", - pba, lba); - nand_dbg_print(NAND_DBG_DEBUG, - "Block Table Entry: %d", pbt[lba]); - - if (((pbt[lba] & BAD_BLOCK) != BAD_BLOCK) && - (pbt[lba] & DISCARD_BLOCK)) { - nand_dbg_print(NAND_DBG_DEBUG, - "do_bt_garbage_collection: " - "Erasing Block tables present in block %d\n", - pba); - addr = FTL_Get_Physical_Block_Addr((u64)lba * - DeviceInfo.wBlockDataSize); - if (PASS == GLOB_FTL_Block_Erase(addr)) { - pbt[lba] &= (u32)(~DISCARD_BLOCK); - pbt[lba] |= (u32)(SPARE_BLOCK); - ret = PASS; - pBTBlocksNode[last_erased - FIRST_BT_ID] = - BTBLOCK_INVAL; - nand_dbg_print(NAND_DBG_DEBUG, - "resetting bt entry at index %d " - "value %d\n", i, - pBTBlocksNode[i - FIRST_BT_ID]); - if (last_erased == LAST_BT_ID) - last_erased = FIRST_BT_ID; - else - last_erased++; - } else { - MARK_BLOCK_AS_BAD(pbt[lba]); - } - } - } - - BT_GC_Called = 0; - - return ret; -} - -#endif - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_FTL_BT_Garbage_Collection -* Inputs: none -* Outputs: PASS / FAIL (returns the number of un-erased blocks -* Description: Erases discarded blocks containing Block table -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int GLOB_FTL_BT_Garbage_Collection(void) -{ - return do_bt_garbage_collection(); -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Replace_OneBlock -* Inputs: Block number 1 -* Block number 2 -* Outputs: Replaced Block Number -* Description: Interchange block table entries at wBlockNum and wReplaceNum -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static u32 FTL_Replace_OneBlock(u32 blk, u32 rep_blk) -{ - u32 tmp_blk; - u32 replace_node = BAD_BLOCK; - u32 *pbt = (u32 *)g_pBlockTable; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (rep_blk != BAD_BLOCK) { - if (IS_BAD_BLOCK(blk)) - tmp_blk = pbt[blk]; - else - tmp_blk = DISCARD_BLOCK | (~SPARE_BLOCK & pbt[blk]); - - replace_node = (u32) ((~SPARE_BLOCK) & pbt[rep_blk]); - pbt[blk] = replace_node; - pbt[rep_blk] = tmp_blk; - -#if CMD_DMA - p_BTableChangesDelta = - (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - - p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; - p_BTableChangesDelta->BT_Index = blk; - p_BTableChangesDelta->BT_Entry_Value = pbt[blk]; - - p_BTableChangesDelta->ValidFields = 0x0C; - - p_BTableChangesDelta = - (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - - p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; - p_BTableChangesDelta->BT_Index = rep_blk; - p_BTableChangesDelta->BT_Entry_Value = pbt[rep_blk]; - p_BTableChangesDelta->ValidFields = 0x0C; -#endif - } - - return replace_node; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Write_Block_Table_Data -* Inputs: Block table size in pages -* Outputs: PASS=0 / FAIL=1 -* Description: Write block table data in flash -* If first page and last page -* Write data+BT flag -* else -* Write data -* BT flag is a counter. Its value is incremented for block table -* write in a new Block -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static int FTL_Write_Block_Table_Data(void) -{ - u64 dwBlockTableAddr, pTempAddr; - u32 Block; - u16 Page, PageCount; - u8 *tempBuf = tmp_buf_write_blk_table_data; - int wBytesCopied; - u16 bt_pages; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - dwBlockTableAddr = - (u64)((u64)g_wBlockTableIndex * DeviceInfo.wBlockDataSize + - (u64)g_wBlockTableOffset * DeviceInfo.wPageDataSize); - pTempAddr = dwBlockTableAddr; - - bt_pages = FTL_Get_Block_Table_Flash_Size_Pages(); - - nand_dbg_print(NAND_DBG_DEBUG, "FTL_Write_Block_Table_Data: " - "page= %d BlockTableIndex= %d " - "BlockTableOffset=%d\n", bt_pages, - g_wBlockTableIndex, g_wBlockTableOffset); - - Block = BLK_FROM_ADDR(pTempAddr); - Page = PAGE_FROM_ADDR(pTempAddr, Block); - PageCount = 1; - - if (bt_block_changed) { - if (bt_flag == LAST_BT_ID) { - bt_flag = FIRST_BT_ID; - g_pBTBlocks[bt_flag - FIRST_BT_ID] = Block; - } else if (bt_flag < LAST_BT_ID) { - bt_flag++; - g_pBTBlocks[bt_flag - FIRST_BT_ID] = Block; - } - - if ((bt_flag > (LAST_BT_ID-4)) && - g_pBTBlocks[FIRST_BT_ID - FIRST_BT_ID] != - BTBLOCK_INVAL) { - bt_block_changed = 0; - GLOB_FTL_BT_Garbage_Collection(); - } - - bt_block_changed = 0; - nand_dbg_print(NAND_DBG_DEBUG, - "Block Table Counter is %u Block %u\n", - bt_flag, (unsigned int)Block); - } - - memset(tempBuf, 0, 3); - tempBuf[3] = bt_flag; - wBytesCopied = FTL_Copy_Block_Table_To_Flash(tempBuf + 4, - DeviceInfo.wPageDataSize - 4, 0); - memset(&tempBuf[wBytesCopied + 4], 0xff, - DeviceInfo.wPageSize - (wBytesCopied + 4)); - FTL_Insert_Block_Table_Signature(&tempBuf[DeviceInfo.wPageDataSize], - bt_flag); - -#if CMD_DMA - memcpy(g_pNextBlockTable, tempBuf, - DeviceInfo.wPageSize * sizeof(u8)); - nand_dbg_print(NAND_DBG_DEBUG, "Writing First Page of Block Table " - "Block %u Page %u\n", (unsigned int)Block, Page); - if (FAIL == GLOB_LLD_Write_Page_Main_Spare_cdma(g_pNextBlockTable, - Block, Page, 1, - LLD_CMD_FLAG_MODE_CDMA | LLD_CMD_FLAG_ORDER_BEFORE_REST)) { - nand_dbg_print(NAND_DBG_WARN, "NAND Program fail in " - "%s, Line %d, Function: %s, " - "new Bad Block %d generated!\n", - __FILE__, __LINE__, __func__, Block); - goto func_return; - } - - ftl_cmd_cnt++; - g_pNextBlockTable += ((DeviceInfo.wPageSize * sizeof(u8))); -#else - if (FAIL == GLOB_LLD_Write_Page_Main_Spare(tempBuf, Block, Page, 1)) { - nand_dbg_print(NAND_DBG_WARN, - "NAND Program fail in %s, Line %d, Function: %s, " - "new Bad Block %d generated!\n", - __FILE__, __LINE__, __func__, Block); - goto func_return; - } -#endif - - if (bt_pages > 1) { - PageCount = bt_pages - 1; - if (PageCount > 1) { - wBytesCopied += FTL_Copy_Block_Table_To_Flash(tempBuf, - DeviceInfo.wPageDataSize * (PageCount - 1), - wBytesCopied); - -#if CMD_DMA - memcpy(g_pNextBlockTable, tempBuf, - (PageCount - 1) * DeviceInfo.wPageDataSize); - if (FAIL == GLOB_LLD_Write_Page_Main_cdma( - g_pNextBlockTable, Block, Page + 1, - PageCount - 1)) { - nand_dbg_print(NAND_DBG_WARN, - "NAND Program fail in %s, Line %d, " - "Function: %s, " - "new Bad Block %d generated!\n", - __FILE__, __LINE__, __func__, - (int)Block); - goto func_return; - } - - ftl_cmd_cnt++; - g_pNextBlockTable += (PageCount - 1) * - DeviceInfo.wPageDataSize * sizeof(u8); -#else - if (FAIL == GLOB_LLD_Write_Page_Main(tempBuf, - Block, Page + 1, PageCount - 1)) { - nand_dbg_print(NAND_DBG_WARN, - "NAND Program fail in %s, Line %d, " - "Function: %s, " - "new Bad Block %d generated!\n", - __FILE__, __LINE__, __func__, - (int)Block); - goto func_return; - } -#endif - } - - wBytesCopied = FTL_Copy_Block_Table_To_Flash(tempBuf, - DeviceInfo.wPageDataSize, wBytesCopied); - memset(&tempBuf[wBytesCopied], 0xff, - DeviceInfo.wPageSize-wBytesCopied); - FTL_Insert_Block_Table_Signature( - &tempBuf[DeviceInfo.wPageDataSize], bt_flag); -#if CMD_DMA - memcpy(g_pNextBlockTable, tempBuf, - DeviceInfo.wPageSize * sizeof(u8)); - nand_dbg_print(NAND_DBG_DEBUG, - "Writing the last Page of Block Table " - "Block %u Page %u\n", - (unsigned int)Block, Page + bt_pages - 1); - if (FAIL == GLOB_LLD_Write_Page_Main_Spare_cdma( - g_pNextBlockTable, Block, Page + bt_pages - 1, 1, - LLD_CMD_FLAG_MODE_CDMA | - LLD_CMD_FLAG_ORDER_BEFORE_REST)) { - nand_dbg_print(NAND_DBG_WARN, - "NAND Program fail in %s, Line %d, " - "Function: %s, new Bad Block %d generated!\n", - __FILE__, __LINE__, __func__, Block); - goto func_return; - } - ftl_cmd_cnt++; -#else - if (FAIL == GLOB_LLD_Write_Page_Main_Spare(tempBuf, - Block, Page+bt_pages - 1, 1)) { - nand_dbg_print(NAND_DBG_WARN, - "NAND Program fail in %s, Line %d, " - "Function: %s, " - "new Bad Block %d generated!\n", - __FILE__, __LINE__, __func__, Block); - goto func_return; - } -#endif - } - - nand_dbg_print(NAND_DBG_DEBUG, "FTL_Write_Block_Table_Data: done\n"); - -func_return: - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Replace_Block_Table -* Inputs: None -* Outputs: PASS=0 / FAIL=1 -* Description: Get a new block to write block table -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static u32 FTL_Replace_Block_Table(void) -{ - u32 blk; - int gc; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - blk = FTL_Replace_LWBlock(BLOCK_TABLE_INDEX, &gc); - - if ((BAD_BLOCK == blk) && (PASS == gc)) { - GLOB_FTL_Garbage_Collection(); - blk = FTL_Replace_LWBlock(BLOCK_TABLE_INDEX, &gc); - } - if (BAD_BLOCK == blk) - printk(KERN_ERR "%s, %s: There is no spare block. " - "It should never happen\n", - __FILE__, __func__); - - nand_dbg_print(NAND_DBG_DEBUG, "New Block table Block is %d\n", blk); - - return blk; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Replace_LWBlock -* Inputs: Block number -* Pointer to Garbage Collect flag -* Outputs: -* Description: Determine the least weared block by traversing -* block table -* Set Garbage collection to be called if number of spare -* block is less than Free Block Gate count -* Change Block table entry to map least worn block for current -* operation -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static u32 FTL_Replace_LWBlock(u32 wBlockNum, int *pGarbageCollect) -{ - u32 i; - u32 *pbt = (u32 *)g_pBlockTable; - u8 wLeastWornCounter = 0xFF; - u32 wLeastWornIndex = BAD_BLOCK; - u32 wSpareBlockNum = 0; - u32 wDiscardBlockNum = 0; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (IS_SPARE_BLOCK(wBlockNum)) { - *pGarbageCollect = FAIL; - pbt[wBlockNum] = (u32)(pbt[wBlockNum] & (~SPARE_BLOCK)); -#if CMD_DMA - p_BTableChangesDelta = - (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - p_BTableChangesDelta->ftl_cmd_cnt = - ftl_cmd_cnt; - p_BTableChangesDelta->BT_Index = (u32)(wBlockNum); - p_BTableChangesDelta->BT_Entry_Value = pbt[wBlockNum]; - p_BTableChangesDelta->ValidFields = 0x0C; -#endif - return pbt[wBlockNum]; - } - - for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { - if (IS_DISCARDED_BLOCK(i)) - wDiscardBlockNum++; - - if (IS_SPARE_BLOCK(i)) { - u32 wPhysicalIndex = (u32)((~BAD_BLOCK) & pbt[i]); - if (wPhysicalIndex > DeviceInfo.wSpectraEndBlock) - printk(KERN_ERR "FTL_Replace_LWBlock: " - "This should never occur!\n"); - if (g_pWearCounter[wPhysicalIndex - - DeviceInfo.wSpectraStartBlock] < - wLeastWornCounter) { - wLeastWornCounter = - g_pWearCounter[wPhysicalIndex - - DeviceInfo.wSpectraStartBlock]; - wLeastWornIndex = i; - } - wSpareBlockNum++; - } - } - - nand_dbg_print(NAND_DBG_WARN, - "FTL_Replace_LWBlock: Least Worn Counter %d\n", - (int)wLeastWornCounter); - - if ((wDiscardBlockNum >= NUM_FREE_BLOCKS_GATE) || - (wSpareBlockNum <= NUM_FREE_BLOCKS_GATE)) - *pGarbageCollect = PASS; - else - *pGarbageCollect = FAIL; - - nand_dbg_print(NAND_DBG_DEBUG, - "FTL_Replace_LWBlock: Discarded Blocks %u Spare" - " Blocks %u\n", - (unsigned int)wDiscardBlockNum, - (unsigned int)wSpareBlockNum); - - return FTL_Replace_OneBlock(wBlockNum, wLeastWornIndex); -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Replace_MWBlock -* Inputs: None -* Outputs: most worn spare block no./BAD_BLOCK -* Description: It finds most worn spare block. -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static u32 FTL_Replace_MWBlock(void) -{ - u32 i; - u32 *pbt = (u32 *)g_pBlockTable; - u8 wMostWornCounter = 0; - u32 wMostWornIndex = BAD_BLOCK; - u32 wSpareBlockNum = 0; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { - if (IS_SPARE_BLOCK(i)) { - u32 wPhysicalIndex = (u32)((~SPARE_BLOCK) & pbt[i]); - if (g_pWearCounter[wPhysicalIndex - - DeviceInfo.wSpectraStartBlock] > - wMostWornCounter) { - wMostWornCounter = - g_pWearCounter[wPhysicalIndex - - DeviceInfo.wSpectraStartBlock]; - wMostWornIndex = wPhysicalIndex; - } - wSpareBlockNum++; - } - } - - if (wSpareBlockNum <= 2) - return BAD_BLOCK; - - return wMostWornIndex; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Replace_Block -* Inputs: Block Address -* Outputs: PASS=0 / FAIL=1 -* Description: If block specified by blk_addr parameter is not free, -* replace it with the least worn block. -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static int FTL_Replace_Block(u64 blk_addr) -{ - u32 current_blk = BLK_FROM_ADDR(blk_addr); - u32 *pbt = (u32 *)g_pBlockTable; - int wResult = PASS; - int GarbageCollect = FAIL; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (IS_SPARE_BLOCK(current_blk)) { - pbt[current_blk] = (~SPARE_BLOCK) & pbt[current_blk]; -#if CMD_DMA - p_BTableChangesDelta = - (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - p_BTableChangesDelta->ftl_cmd_cnt = - ftl_cmd_cnt; - p_BTableChangesDelta->BT_Index = current_blk; - p_BTableChangesDelta->BT_Entry_Value = pbt[current_blk]; - p_BTableChangesDelta->ValidFields = 0x0C ; -#endif - return wResult; - } - - FTL_Replace_LWBlock(current_blk, &GarbageCollect); - - if (PASS == GarbageCollect) - wResult = GLOB_FTL_Garbage_Collection(); - - return wResult; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_FTL_Is_BadBlock -* Inputs: block number to test -* Outputs: PASS (block is BAD) / FAIL (block is not bad) -* Description: test if this block number is flagged as bad -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int GLOB_FTL_Is_BadBlock(u32 wBlockNum) -{ - u32 *pbt = (u32 *)g_pBlockTable; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (wBlockNum >= DeviceInfo.wSpectraStartBlock - && BAD_BLOCK == (pbt[wBlockNum] & BAD_BLOCK)) - return PASS; - else - return FAIL; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_FTL_Flush_Cache -* Inputs: none -* Outputs: PASS=0 / FAIL=1 -* Description: flush all the cache blocks to flash -* if a cache block is not dirty, don't do anything with it -* else, write the block and update the block table -* Note: This function should be called at shutdown/power down. -* to write important data into device -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int GLOB_FTL_Flush_Cache(void) -{ - int i, ret; - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - for (i = 0; i < CACHE_ITEM_NUM; i++) { - if (SET == Cache.array[i].changed) { -#if CMD_DMA -#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE - int_cache[ftl_cmd_cnt].item = i; - int_cache[ftl_cmd_cnt].cache.address = - Cache.array[i].address; - int_cache[ftl_cmd_cnt].cache.changed = CLEAR; -#endif -#endif - ret = write_back_to_l2_cache(Cache.array[i].buf, Cache.array[i].address); - if (PASS == ret) { - Cache.array[i].changed = CLEAR; - } else { - printk(KERN_ALERT "Failed when write back to L2 cache!\n"); - /* TODO - How to handle this? */ - } - } - } - - flush_l2_cache(); - - return FTL_Write_Block_Table(FAIL); -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_FTL_Page_Read -* Inputs: pointer to data -* logical address of data (u64 is LBA * Bytes/Page) -* Outputs: PASS=0 / FAIL=1 -* Description: reads a page of data into RAM from the cache -* if the data is not already in cache, read from flash to cache -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int GLOB_FTL_Page_Read(u8 *data, u64 logical_addr) -{ - u16 cache_item; - int res = PASS; - - nand_dbg_print(NAND_DBG_DEBUG, "GLOB_FTL_Page_Read - " - "page_addr: %llu\n", logical_addr); - - cache_item = FTL_Cache_If_Hit(logical_addr); - - if (UNHIT_CACHE_ITEM == cache_item) { - nand_dbg_print(NAND_DBG_DEBUG, - "GLOB_FTL_Page_Read: Cache not hit\n"); - res = FTL_Cache_Write(); - if (ERR == FTL_Cache_Read(logical_addr)) - res = ERR; - cache_item = Cache.LRU; - } - - FTL_Cache_Read_Page(data, logical_addr, cache_item); - - return res; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_FTL_Page_Write -* Inputs: pointer to data -* address of data (ADDRESSTYPE is LBA * Bytes/Page) -* Outputs: PASS=0 / FAIL=1 -* Description: writes a page of data from RAM to the cache -* if the data is not already in cache, write back the -* least recently used block and read the addressed block -* from flash to cache -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int GLOB_FTL_Page_Write(u8 *pData, u64 dwPageAddr) -{ - u16 cache_blk; - u32 *pbt = (u32 *)g_pBlockTable; - int wResult = PASS; - - nand_dbg_print(NAND_DBG_TRACE, "GLOB_FTL_Page_Write - " - "dwPageAddr: %llu\n", dwPageAddr); - - cache_blk = FTL_Cache_If_Hit(dwPageAddr); - - if (UNHIT_CACHE_ITEM == cache_blk) { - wResult = FTL_Cache_Write(); - if (IS_BAD_BLOCK(BLK_FROM_ADDR(dwPageAddr))) { - wResult = FTL_Replace_Block(dwPageAddr); - pbt[BLK_FROM_ADDR(dwPageAddr)] |= SPARE_BLOCK; - if (wResult == FAIL) - return FAIL; - } - if (ERR == FTL_Cache_Read(dwPageAddr)) - wResult = ERR; - cache_blk = Cache.LRU; - FTL_Cache_Write_Page(pData, dwPageAddr, cache_blk, 0); - } else { -#if CMD_DMA - FTL_Cache_Write_Page(pData, dwPageAddr, cache_blk, - LLD_CMD_FLAG_ORDER_BEFORE_REST); -#else - FTL_Cache_Write_Page(pData, dwPageAddr, cache_blk, 0); -#endif - } - - return wResult; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: GLOB_FTL_Block_Erase -* Inputs: address of block to erase (now in byte format, should change to -* block format) -* Outputs: PASS=0 / FAIL=1 -* Description: erases the specified block -* increments the erase count -* If erase count reaches its upper limit,call function to -* do the adjustment as per the relative erase count values -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int GLOB_FTL_Block_Erase(u64 blk_addr) -{ - int status; - u32 BlkIdx; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - BlkIdx = (u32)(blk_addr >> DeviceInfo.nBitsInBlockDataSize); - - if (BlkIdx < DeviceInfo.wSpectraStartBlock) { - printk(KERN_ERR "GLOB_FTL_Block_Erase: " - "This should never occur\n"); - return FAIL; - } - -#if CMD_DMA - status = GLOB_LLD_Erase_Block_cdma(BlkIdx, LLD_CMD_FLAG_MODE_CDMA); - if (status == FAIL) - nand_dbg_print(NAND_DBG_WARN, - "NAND Program fail in %s, Line %d, " - "Function: %s, new Bad Block %d generated!\n", - __FILE__, __LINE__, __func__, BlkIdx); -#else - status = GLOB_LLD_Erase_Block(BlkIdx); - if (status == FAIL) { - nand_dbg_print(NAND_DBG_WARN, - "NAND Program fail in %s, Line %d, " - "Function: %s, new Bad Block %d generated!\n", - __FILE__, __LINE__, __func__, BlkIdx); - return status; - } -#endif - - if (DeviceInfo.MLCDevice) { - g_pReadCounter[BlkIdx - DeviceInfo.wSpectraStartBlock] = 0; - if (g_cBlockTableStatus != IN_PROGRESS_BLOCK_TABLE) { - g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; - FTL_Write_IN_Progress_Block_Table_Page(); - } - } - - g_pWearCounter[BlkIdx - DeviceInfo.wSpectraStartBlock]++; - -#if CMD_DMA - p_BTableChangesDelta = - (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; - p_BTableChangesDelta->WC_Index = - BlkIdx - DeviceInfo.wSpectraStartBlock; - p_BTableChangesDelta->WC_Entry_Value = - g_pWearCounter[BlkIdx - DeviceInfo.wSpectraStartBlock]; - p_BTableChangesDelta->ValidFields = 0x30; - - if (DeviceInfo.MLCDevice) { - p_BTableChangesDelta = - (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - p_BTableChangesDelta->ftl_cmd_cnt = - ftl_cmd_cnt; - p_BTableChangesDelta->RC_Index = - BlkIdx - DeviceInfo.wSpectraStartBlock; - p_BTableChangesDelta->RC_Entry_Value = - g_pReadCounter[BlkIdx - - DeviceInfo.wSpectraStartBlock]; - p_BTableChangesDelta->ValidFields = 0xC0; - } - - ftl_cmd_cnt++; -#endif - - if (g_pWearCounter[BlkIdx - DeviceInfo.wSpectraStartBlock] == 0xFE) - FTL_Adjust_Relative_Erase_Count(BlkIdx); - - return status; -} - - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Adjust_Relative_Erase_Count -* Inputs: index to block that was just incremented and is at the max -* Outputs: PASS=0 / FAIL=1 -* Description: If any erase counts at MAX, adjusts erase count of every -* block by subtracting least worn -* counter from counter value of every entry in wear table -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static int FTL_Adjust_Relative_Erase_Count(u32 Index_of_MAX) -{ - u8 wLeastWornCounter = MAX_BYTE_VALUE; - u8 wWearCounter; - u32 i, wWearIndex; - u32 *pbt = (u32 *)g_pBlockTable; - int wResult = PASS; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - for (i = 0; i < DeviceInfo.wDataBlockNum; i++) { - if (IS_BAD_BLOCK(i)) - continue; - wWearIndex = (u32)(pbt[i] & (~BAD_BLOCK)); - - if ((wWearIndex - DeviceInfo.wSpectraStartBlock) < 0) - printk(KERN_ERR "FTL_Adjust_Relative_Erase_Count:" - "This should never occur\n"); - wWearCounter = g_pWearCounter[wWearIndex - - DeviceInfo.wSpectraStartBlock]; - if (wWearCounter < wLeastWornCounter) - wLeastWornCounter = wWearCounter; - } - - if (wLeastWornCounter == 0) { - nand_dbg_print(NAND_DBG_WARN, - "Adjusting Wear Levelling Counters: Special Case\n"); - g_pWearCounter[Index_of_MAX - - DeviceInfo.wSpectraStartBlock]--; -#if CMD_DMA - p_BTableChangesDelta = - (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; - p_BTableChangesDelta->WC_Index = - Index_of_MAX - DeviceInfo.wSpectraStartBlock; - p_BTableChangesDelta->WC_Entry_Value = - g_pWearCounter[Index_of_MAX - - DeviceInfo.wSpectraStartBlock]; - p_BTableChangesDelta->ValidFields = 0x30; -#endif - FTL_Static_Wear_Leveling(); - } else { - for (i = 0; i < DeviceInfo.wDataBlockNum; i++) - if (!IS_BAD_BLOCK(i)) { - wWearIndex = (u32)(pbt[i] & (~BAD_BLOCK)); - g_pWearCounter[wWearIndex - - DeviceInfo.wSpectraStartBlock] = - (u8)(g_pWearCounter - [wWearIndex - - DeviceInfo.wSpectraStartBlock] - - wLeastWornCounter); -#if CMD_DMA - p_BTableChangesDelta = - (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += - sizeof(struct BTableChangesDelta); - - p_BTableChangesDelta->ftl_cmd_cnt = - ftl_cmd_cnt; - p_BTableChangesDelta->WC_Index = wWearIndex - - DeviceInfo.wSpectraStartBlock; - p_BTableChangesDelta->WC_Entry_Value = - g_pWearCounter[wWearIndex - - DeviceInfo.wSpectraStartBlock]; - p_BTableChangesDelta->ValidFields = 0x30; -#endif - } - } - - return wResult; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Write_IN_Progress_Block_Table_Page -* Inputs: None -* Outputs: None -* Description: It writes in-progress flag page to the page next to -* block table -***********************************************************************/ -static int FTL_Write_IN_Progress_Block_Table_Page(void) -{ - int wResult = PASS; - u16 bt_pages; - u16 dwIPFPageAddr; -#if CMD_DMA -#else - u32 *pbt = (u32 *)g_pBlockTable; - u32 wTempBlockTableIndex; -#endif - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - bt_pages = FTL_Get_Block_Table_Flash_Size_Pages(); - - dwIPFPageAddr = g_wBlockTableOffset + bt_pages; - - nand_dbg_print(NAND_DBG_DEBUG, "Writing IPF at " - "Block %d Page %d\n", - g_wBlockTableIndex, dwIPFPageAddr); - -#if CMD_DMA - wResult = GLOB_LLD_Write_Page_Main_Spare_cdma(g_pIPF, - g_wBlockTableIndex, dwIPFPageAddr, 1, - LLD_CMD_FLAG_MODE_CDMA | LLD_CMD_FLAG_ORDER_BEFORE_REST); - if (wResult == FAIL) { - nand_dbg_print(NAND_DBG_WARN, - "NAND Program fail in %s, Line %d, " - "Function: %s, new Bad Block %d generated!\n", - __FILE__, __LINE__, __func__, - g_wBlockTableIndex); - } - g_wBlockTableOffset = dwIPFPageAddr + 1; - p_BTableChangesDelta = (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; - p_BTableChangesDelta->g_wBlockTableOffset = g_wBlockTableOffset; - p_BTableChangesDelta->ValidFields = 0x01; - ftl_cmd_cnt++; -#else - wResult = GLOB_LLD_Write_Page_Main_Spare(g_pIPF, - g_wBlockTableIndex, dwIPFPageAddr, 1); - if (wResult == FAIL) { - nand_dbg_print(NAND_DBG_WARN, - "NAND Program fail in %s, Line %d, " - "Function: %s, new Bad Block %d generated!\n", - __FILE__, __LINE__, __func__, - (int)g_wBlockTableIndex); - MARK_BLOCK_AS_BAD(pbt[BLOCK_TABLE_INDEX]); - wTempBlockTableIndex = FTL_Replace_Block_Table(); - bt_block_changed = 1; - if (BAD_BLOCK == wTempBlockTableIndex) - return ERR; - g_wBlockTableIndex = wTempBlockTableIndex; - g_wBlockTableOffset = 0; - /* Block table tag is '00'. Means it's used one */ - pbt[BLOCK_TABLE_INDEX] = g_wBlockTableIndex; - return FAIL; - } - g_wBlockTableOffset = dwIPFPageAddr + 1; -#endif - return wResult; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Read_Disturbance -* Inputs: block address -* Outputs: PASS=0 / FAIL=1 -* Description: used to handle read disturbance. Data in block that -* reaches its read limit is moved to new block -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int FTL_Read_Disturbance(u32 blk_addr) -{ - int wResult = FAIL; - u32 *pbt = (u32 *) g_pBlockTable; - u32 dwOldBlockAddr = blk_addr; - u32 wBlockNum; - u32 i; - u32 wLeastReadCounter = 0xFFFF; - u32 wLeastReadIndex = BAD_BLOCK; - u32 wSpareBlockNum = 0; - u32 wTempNode; - u32 wReplacedNode; - u8 *g_pTempBuf; - - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - -#if CMD_DMA - g_pTempBuf = cp_back_buf_copies[cp_back_buf_idx]; - cp_back_buf_idx++; - if (cp_back_buf_idx > COPY_BACK_BUF_NUM) { - printk(KERN_ERR "cp_back_buf_copies overflow! Exit." - "Maybe too many pending commands in your CDMA chain.\n"); - return FAIL; - } -#else - g_pTempBuf = tmp_buf_read_disturbance; -#endif - - wBlockNum = FTL_Get_Block_Index(blk_addr); - - do { - /* This is a bug.Here 'i' should be logical block number - * and start from 1 (0 is reserved for block table). - * Have fixed it. - Yunpeng 2008. 12. 19 - */ - for (i = 1; i < DeviceInfo.wDataBlockNum; i++) { - if (IS_SPARE_BLOCK(i)) { - u32 wPhysicalIndex = - (u32)((~SPARE_BLOCK) & pbt[i]); - if (g_pReadCounter[wPhysicalIndex - - DeviceInfo.wSpectraStartBlock] < - wLeastReadCounter) { - wLeastReadCounter = - g_pReadCounter[wPhysicalIndex - - DeviceInfo.wSpectraStartBlock]; - wLeastReadIndex = i; - } - wSpareBlockNum++; - } - } - - if (wSpareBlockNum <= NUM_FREE_BLOCKS_GATE) { - wResult = GLOB_FTL_Garbage_Collection(); - if (PASS == wResult) - continue; - else - break; - } else { - wTempNode = (u32)(DISCARD_BLOCK | pbt[wBlockNum]); - wReplacedNode = (u32)((~SPARE_BLOCK) & - pbt[wLeastReadIndex]); -#if CMD_DMA - pbt[wBlockNum] = wReplacedNode; - pbt[wLeastReadIndex] = wTempNode; - p_BTableChangesDelta = - (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - - p_BTableChangesDelta->ftl_cmd_cnt = - ftl_cmd_cnt; - p_BTableChangesDelta->BT_Index = wBlockNum; - p_BTableChangesDelta->BT_Entry_Value = pbt[wBlockNum]; - p_BTableChangesDelta->ValidFields = 0x0C; - - p_BTableChangesDelta = - (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - - p_BTableChangesDelta->ftl_cmd_cnt = - ftl_cmd_cnt; - p_BTableChangesDelta->BT_Index = wLeastReadIndex; - p_BTableChangesDelta->BT_Entry_Value = - pbt[wLeastReadIndex]; - p_BTableChangesDelta->ValidFields = 0x0C; - - wResult = GLOB_LLD_Read_Page_Main_cdma(g_pTempBuf, - dwOldBlockAddr, 0, DeviceInfo.wPagesPerBlock, - LLD_CMD_FLAG_MODE_CDMA); - if (wResult == FAIL) - return wResult; - - ftl_cmd_cnt++; - - if (wResult != FAIL) { - if (FAIL == GLOB_LLD_Write_Page_Main_cdma( - g_pTempBuf, pbt[wBlockNum], 0, - DeviceInfo.wPagesPerBlock)) { - nand_dbg_print(NAND_DBG_WARN, - "NAND Program fail in " - "%s, Line %d, Function: %s, " - "new Bad Block %d " - "generated!\n", - __FILE__, __LINE__, __func__, - (int)pbt[wBlockNum]); - wResult = FAIL; - MARK_BLOCK_AS_BAD(pbt[wBlockNum]); - } - ftl_cmd_cnt++; - } -#else - wResult = GLOB_LLD_Read_Page_Main(g_pTempBuf, - dwOldBlockAddr, 0, DeviceInfo.wPagesPerBlock); - if (wResult == FAIL) - return wResult; - - if (wResult != FAIL) { - /* This is a bug. At this time, pbt[wBlockNum] - is still the physical address of - discard block, and should not be write. - Have fixed it as below. - -- Yunpeng 2008.12.19 - */ - wResult = GLOB_LLD_Write_Page_Main(g_pTempBuf, - wReplacedNode, 0, - DeviceInfo.wPagesPerBlock); - if (wResult == FAIL) { - nand_dbg_print(NAND_DBG_WARN, - "NAND Program fail in " - "%s, Line %d, Function: %s, " - "new Bad Block %d " - "generated!\n", - __FILE__, __LINE__, __func__, - (int)wReplacedNode); - MARK_BLOCK_AS_BAD(wReplacedNode); - } else { - pbt[wBlockNum] = wReplacedNode; - pbt[wLeastReadIndex] = wTempNode; - } - } - - if ((wResult == PASS) && (g_cBlockTableStatus != - IN_PROGRESS_BLOCK_TABLE)) { - g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; - FTL_Write_IN_Progress_Block_Table_Page(); - } -#endif - } - } while (wResult != PASS) - ; - -#if CMD_DMA - /* ... */ -#endif - - return wResult; -} - diff --git a/drivers/staging/spectra/flash.h b/drivers/staging/spectra/flash.h deleted file mode 100644 index e59cf4ede551..000000000000 --- a/drivers/staging/spectra/flash.h +++ /dev/null @@ -1,198 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef _FLASH_INTERFACE_ -#define _FLASH_INTERFACE_ - -#include "ffsport.h" -#include "spectraswconfig.h" - -#define MAX_BYTE_VALUE 0xFF -#define MAX_WORD_VALUE 0xFFFF -#define MAX_U32_VALUE 0xFFFFFFFF - -#define MAX_BLOCKNODE_VALUE 0xFFFFFF -#define DISCARD_BLOCK 0x800000 -#define SPARE_BLOCK 0x400000 -#define BAD_BLOCK 0xC00000 - -#define UNHIT_CACHE_ITEM 0xFFFF - -#define NAND_CACHE_INIT_ADDR 0xffffffffffffffffULL - -#define IN_PROGRESS_BLOCK_TABLE 0x00 -#define CURRENT_BLOCK_TABLE 0x01 - -#define BTSIG_OFFSET (0) -#define BTSIG_BYTES (5) -#define BTSIG_DELTA (3) - -#define MAX_READ_COUNTER 0x2710 - -#define FIRST_BT_ID (1) -#define LAST_BT_ID (254) -#define BTBLOCK_INVAL (u32)(0xFFFFFFFF) - -struct device_info_tag { - u16 wDeviceMaker; - u16 wDeviceID; - u32 wDeviceType; - u32 wSpectraStartBlock; - u32 wSpectraEndBlock; - u32 wTotalBlocks; - u16 wPagesPerBlock; - u16 wPageSize; - u16 wPageDataSize; - u16 wPageSpareSize; - u16 wNumPageSpareFlag; - u16 wECCBytesPerSector; - u32 wBlockSize; - u32 wBlockDataSize; - u32 wDataBlockNum; - u8 bPlaneNum; - u16 wDeviceMainAreaSize; - u16 wDeviceSpareAreaSize; - u16 wDevicesConnected; - u16 wDeviceWidth; - u16 wHWRevision; - u16 wHWFeatures; - - u16 wONFIDevFeatures; - u16 wONFIOptCommands; - u16 wONFITimingMode; - u16 wONFIPgmCacheTimingMode; - - u16 MLCDevice; - u16 wSpareSkipBytes; - - u8 nBitsInPageNumber; - u8 nBitsInPageDataSize; - u8 nBitsInBlockDataSize; -}; - -extern struct device_info_tag DeviceInfo; - -/* Cache item format */ -struct flash_cache_item_tag { - u64 address; - u16 use_cnt; - u16 changed; - u8 *buf; -}; - -struct flash_cache_tag { - u32 cache_item_size; /* Size in bytes of each cache item */ - u16 pages_per_item; /* How many NAND pages in each cache item */ - u16 LRU; /* No. of the least recently used cache item */ - struct flash_cache_item_tag array[CACHE_ITEM_NUM]; -}; - -/* - *Data structure for each list node of the management table - * used for the Level 2 Cache. Each node maps one logical NAND block. - */ -struct spectra_l2_cache_list { - struct list_head list; - u32 logical_blk_num; /* Logical block number */ - u32 pages_array[]; /* Page map array of this logical block. - * Array index is the logical block number, - * and for every item of this arry: - * high 16 bit is index of the L2 cache block num, - * low 16 bit is the phy page num - * of the above L2 cache block. - * This array will be kmalloc during run time. - */ -}; - -struct spectra_l2_cache_info { - u32 blk_array[BLK_NUM_FOR_L2_CACHE]; - u16 cur_blk_idx; /* idx to the phy block number of current using */ - u16 cur_page_num; /* pages number of current using */ - struct spectra_l2_cache_list table; /* First node of the table */ -}; - -#define RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE 1 - -#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE -struct flash_cache_mod_item_tag { - u64 address; - u8 changed; -}; - -struct flash_cache_delta_list_tag { - u8 item; /* used cache item */ - struct flash_cache_mod_item_tag cache; -}; -#endif - -extern struct flash_cache_tag Cache; - -extern u8 *buf_read_page_main_spare; -extern u8 *buf_write_page_main_spare; -extern u8 *buf_read_page_spare; -extern u8 *buf_get_bad_block; -extern u8 *cdma_desc_buf; -extern u8 *memcp_desc_buf; - -/* struture used for IndentfyDevice function */ -struct spectra_indentfy_dev_tag { - u32 NumBlocks; - u16 PagesPerBlock; - u16 PageDataSize; - u16 wECCBytesPerSector; - u32 wDataBlockNum; -}; - -int GLOB_FTL_Flash_Init(void); -int GLOB_FTL_Flash_Release(void); -/*void GLOB_FTL_Erase_Flash(void);*/ -int GLOB_FTL_Block_Erase(u64 block_addr); -int GLOB_FTL_Is_BadBlock(u32 block_num); -int GLOB_FTL_IdentifyDevice(struct spectra_indentfy_dev_tag *dev_data); -int GLOB_FTL_Event_Status(int *); -u16 glob_ftl_execute_cmds(void); - -/*int FTL_Read_Disturbance(ADDRESSTYPE dwBlockAddr);*/ -int FTL_Read_Disturbance(u32 dwBlockAddr); - -/*Flash r/w based on cache*/ -int GLOB_FTL_Page_Read(u8 *read_data, u64 page_addr); -int GLOB_FTL_Page_Write(u8 *write_data, u64 page_addr); -int GLOB_FTL_Wear_Leveling(void); -int GLOB_FTL_Flash_Format(void); -int GLOB_FTL_Init(void); -int GLOB_FTL_Flush_Cache(void); -int GLOB_FTL_Garbage_Collection(void); -int GLOB_FTL_BT_Garbage_Collection(void); -void GLOB_FTL_Cache_Release(void); -u8 *get_blk_table_start_addr(void); -u8 *get_wear_leveling_table_start_addr(void); -unsigned long get_blk_table_len(void); -unsigned long get_wear_leveling_table_len(void); - -#if DEBUG_BNDRY -void debug_boundary_lineno_error(int chnl, int limit, int no, int lineno, - char *filename); -#define debug_boundary_error(chnl, limit, no) debug_boundary_lineno_error(chnl,\ - limit, no, __LINE__, __FILE__) -#else -#define debug_boundary_error(chnl, limit, no) ; -#endif - -#endif /*_FLASH_INTERFACE_*/ diff --git a/drivers/staging/spectra/lld.c b/drivers/staging/spectra/lld.c deleted file mode 100644 index 5c3b9762dc3e..000000000000 --- a/drivers/staging/spectra/lld.c +++ /dev/null @@ -1,339 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include "spectraswconfig.h" -#include "ffsport.h" -#include "ffsdefs.h" -#include "lld.h" -#include "lld_nand.h" - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -#if FLASH_EMU /* vector all the LLD calls to the LLD_EMU code */ -#include "lld_emu.h" -#include "lld_cdma.h" - -/* common functions: */ -u16 GLOB_LLD_Flash_Reset(void) -{ - return emu_Flash_Reset(); -} - -u16 GLOB_LLD_Read_Device_ID(void) -{ - return emu_Read_Device_ID(); -} - -int GLOB_LLD_Flash_Release(void) -{ - return emu_Flash_Release(); -} - -u16 GLOB_LLD_Flash_Init(void) -{ - return emu_Flash_Init(); -} - -u16 GLOB_LLD_Erase_Block(u32 block_add) -{ - return emu_Erase_Block(block_add); -} - -u16 GLOB_LLD_Write_Page_Main(u8 *write_data, u32 block, u16 Page, - u16 PageCount) -{ - return emu_Write_Page_Main(write_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Read_Page_Main(u8 *read_data, u32 block, u16 Page, - u16 PageCount) -{ - return emu_Read_Page_Main(read_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Read_Page_Main_Polling(u8 *read_data, - u32 block, u16 page, u16 page_count) -{ - return emu_Read_Page_Main(read_data, block, page, page_count); -} - -u16 GLOB_LLD_Write_Page_Main_Spare(u8 *write_data, u32 block, - u16 Page, u16 PageCount) -{ - return emu_Write_Page_Main_Spare(write_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Read_Page_Main_Spare(u8 *read_data, u32 block, - u16 Page, u16 PageCount) -{ - return emu_Read_Page_Main_Spare(read_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Write_Page_Spare(u8 *write_data, u32 block, u16 Page, - u16 PageCount) -{ - return emu_Write_Page_Spare(write_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Read_Page_Spare(u8 *read_data, u32 block, u16 Page, - u16 PageCount) -{ - return emu_Read_Page_Spare(read_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Get_Bad_Block(u32 block) -{ - return emu_Get_Bad_Block(block); -} - -#endif /* FLASH_EMU */ - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -#if FLASH_MTD /* vector all the LLD calls to the LLD_MTD code */ -#include "lld_mtd.h" -#include "lld_cdma.h" - -/* common functions: */ -u16 GLOB_LLD_Flash_Reset(void) -{ - return mtd_Flash_Reset(); -} - -u16 GLOB_LLD_Read_Device_ID(void) -{ - return mtd_Read_Device_ID(); -} - -int GLOB_LLD_Flash_Release(void) -{ - return mtd_Flash_Release(); -} - -u16 GLOB_LLD_Flash_Init(void) -{ - return mtd_Flash_Init(); -} - -u16 GLOB_LLD_Erase_Block(u32 block_add) -{ - return mtd_Erase_Block(block_add); -} - -u16 GLOB_LLD_Write_Page_Main(u8 *write_data, u32 block, u16 Page, - u16 PageCount) -{ - return mtd_Write_Page_Main(write_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Read_Page_Main(u8 *read_data, u32 block, u16 Page, - u16 PageCount) -{ - return mtd_Read_Page_Main(read_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Read_Page_Main_Polling(u8 *read_data, - u32 block, u16 page, u16 page_count) -{ - return mtd_Read_Page_Main(read_data, block, page, page_count); -} - -u16 GLOB_LLD_Write_Page_Main_Spare(u8 *write_data, u32 block, - u16 Page, u16 PageCount) -{ - return mtd_Write_Page_Main_Spare(write_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Read_Page_Main_Spare(u8 *read_data, u32 block, - u16 Page, u16 PageCount) -{ - return mtd_Read_Page_Main_Spare(read_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Write_Page_Spare(u8 *write_data, u32 block, u16 Page, - u16 PageCount) -{ - return mtd_Write_Page_Spare(write_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Read_Page_Spare(u8 *read_data, u32 block, u16 Page, - u16 PageCount) -{ - return mtd_Read_Page_Spare(read_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Get_Bad_Block(u32 block) -{ - return mtd_Get_Bad_Block(block); -} - -#endif /* FLASH_MTD */ - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -#if FLASH_NAND /* vector all the LLD calls to the NAND controller code */ -#include "lld_nand.h" -#include "lld_cdma.h" -#include "flash.h" - -/* common functions for LLD_NAND */ -void GLOB_LLD_ECC_Control(int enable) -{ - NAND_ECC_Ctrl(enable); -} - -/* common functions for LLD_NAND */ -u16 GLOB_LLD_Flash_Reset(void) -{ - return NAND_Flash_Reset(); -} - -u16 GLOB_LLD_Read_Device_ID(void) -{ - return NAND_Read_Device_ID(); -} - -u16 GLOB_LLD_UnlockArrayAll(void) -{ - return NAND_UnlockArrayAll(); -} - -u16 GLOB_LLD_Flash_Init(void) -{ - return NAND_Flash_Init(); -} - -int GLOB_LLD_Flash_Release(void) -{ - return nand_release_spectra(); -} - -u16 GLOB_LLD_Erase_Block(u32 block_add) -{ - return NAND_Erase_Block(block_add); -} - - -u16 GLOB_LLD_Write_Page_Main(u8 *write_data, u32 block, u16 Page, - u16 PageCount) -{ - return NAND_Write_Page_Main(write_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Read_Page_Main(u8 *read_data, u32 block, u16 page, - u16 page_count) -{ - if (page_count == 1) /* Using polling to improve read speed */ - return NAND_Read_Page_Main_Polling(read_data, block, page, 1); - else - return NAND_Read_Page_Main(read_data, block, page, page_count); -} - -u16 GLOB_LLD_Read_Page_Main_Polling(u8 *read_data, - u32 block, u16 page, u16 page_count) -{ - return NAND_Read_Page_Main_Polling(read_data, - block, page, page_count); -} - -u16 GLOB_LLD_Write_Page_Main_Spare(u8 *write_data, u32 block, - u16 Page, u16 PageCount) -{ - return NAND_Write_Page_Main_Spare(write_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Write_Page_Spare(u8 *write_data, u32 block, u16 Page, - u16 PageCount) -{ - return NAND_Write_Page_Spare(write_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Read_Page_Main_Spare(u8 *read_data, u32 block, - u16 page, u16 page_count) -{ - return NAND_Read_Page_Main_Spare(read_data, block, page, page_count); -} - -u16 GLOB_LLD_Read_Page_Spare(u8 *read_data, u32 block, u16 Page, - u16 PageCount) -{ - return NAND_Read_Page_Spare(read_data, block, Page, PageCount); -} - -u16 GLOB_LLD_Get_Bad_Block(u32 block) -{ - return NAND_Get_Bad_Block(block); -} - -#if CMD_DMA -u16 GLOB_LLD_Event_Status(void) -{ - return CDMA_Event_Status(); -} - -u16 glob_lld_execute_cmds(void) -{ - return CDMA_Execute_CMDs(); -} - -u16 GLOB_LLD_MemCopy_CMD(u8 *dest, u8 *src, - u32 ByteCount, u16 flag) -{ - /* Replace the hardware memcopy with software memcpy function */ - if (CDMA_Execute_CMDs()) - return FAIL; - memcpy(dest, src, ByteCount); - return PASS; - - /* return CDMA_MemCopy_CMD(dest, src, ByteCount, flag); */ -} - -u16 GLOB_LLD_Erase_Block_cdma(u32 block, u16 flags) -{ - return CDMA_Data_CMD(ERASE_CMD, 0, block, 0, 0, flags); -} - -u16 GLOB_LLD_Write_Page_Main_cdma(u8 *data, u32 block, u16 page, u16 count) -{ - return CDMA_Data_CMD(WRITE_MAIN_CMD, data, block, page, count, 0); -} - -u16 GLOB_LLD_Read_Page_Main_cdma(u8 *data, u32 block, u16 page, - u16 count, u16 flags) -{ - return CDMA_Data_CMD(READ_MAIN_CMD, data, block, page, count, flags); -} - -u16 GLOB_LLD_Write_Page_Main_Spare_cdma(u8 *data, u32 block, u16 page, - u16 count, u16 flags) -{ - return CDMA_Data_CMD(WRITE_MAIN_SPARE_CMD, - data, block, page, count, flags); -} - -u16 GLOB_LLD_Read_Page_Main_Spare_cdma(u8 *data, - u32 block, u16 page, u16 count) -{ - return CDMA_Data_CMD(READ_MAIN_SPARE_CMD, data, block, page, count, - LLD_CMD_FLAG_MODE_CDMA); -} - -#endif /* CMD_DMA */ -#endif /* FLASH_NAND */ - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ - -/* end of LLD.c */ diff --git a/drivers/staging/spectra/lld.h b/drivers/staging/spectra/lld.h deleted file mode 100644 index d3738e0e1fea..000000000000 --- a/drivers/staging/spectra/lld.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - - - -#ifndef _LLD_ -#define _LLD_ - -#include "ffsport.h" -#include "spectraswconfig.h" -#include "flash.h" - -#define GOOD_BLOCK 0 -#define DEFECTIVE_BLOCK 1 -#define READ_ERROR 2 - -#define CLK_X 5 -#define CLK_MULTI 4 - -/* Typedefs */ - -/* prototypes: API for LLD */ -/* Currently, Write_Page_Main - * MemCopy - * Read_Page_Main_Spare - * do not have flag because they were not implemented prior to this - * They are not being added to keep changes to a minimum for now. - * Currently, they are not required (only reqd for Wr_P_M_S.) - * Later on, these NEED to be changed. - */ - -extern void GLOB_LLD_ECC_Control(int enable); - -extern u16 GLOB_LLD_Flash_Reset(void); - -extern u16 GLOB_LLD_Read_Device_ID(void); - -extern u16 GLOB_LLD_UnlockArrayAll(void); - -extern u16 GLOB_LLD_Flash_Init(void); - -extern int GLOB_LLD_Flash_Release(void); - -extern u16 GLOB_LLD_Erase_Block(u32 block_add); - -extern u16 GLOB_LLD_Write_Page_Main(u8 *write_data, - u32 block, u16 Page, u16 PageCount); - -extern u16 GLOB_LLD_Read_Page_Main(u8 *read_data, - u32 block, u16 page, u16 page_count); - -extern u16 GLOB_LLD_Read_Page_Main_Polling(u8 *read_data, - u32 block, u16 page, u16 page_count); - -extern u16 GLOB_LLD_Write_Page_Main_Spare(u8 *write_data, - u32 block, u16 Page, u16 PageCount); - -extern u16 GLOB_LLD_Write_Page_Spare(u8 *write_data, - u32 block, u16 Page, u16 PageCount); - -extern u16 GLOB_LLD_Read_Page_Main_Spare(u8 *read_data, - u32 block, u16 page, u16 page_count); - -extern u16 GLOB_LLD_Read_Page_Spare(u8 *read_data, - u32 block, u16 Page, u16 PageCount); - -extern u16 GLOB_LLD_Get_Bad_Block(u32 block); - -extern u16 GLOB_LLD_Event_Status(void); - -extern u16 GLOB_LLD_MemCopy_CMD(u8 *dest, u8 *src, u32 ByteCount, u16 flag); - -extern u16 glob_lld_execute_cmds(void); - -extern u16 GLOB_LLD_Erase_Block_cdma(u32 block, u16 flags); - -extern u16 GLOB_LLD_Write_Page_Main_cdma(u8 *data, - u32 block, u16 page, u16 count); - -extern u16 GLOB_LLD_Read_Page_Main_cdma(u8 *data, - u32 block, u16 page, u16 count, u16 flags); - -extern u16 GLOB_LLD_Write_Page_Main_Spare_cdma(u8 *data, - u32 block, u16 page, u16 count, u16 flags); - -extern u16 GLOB_LLD_Read_Page_Main_Spare_cdma(u8 *data, - u32 block, u16 page, u16 count); - -#define LLD_CMD_FLAG_ORDER_BEFORE_REST (0x1) -#define LLD_CMD_FLAG_MODE_CDMA (0x8) - - -#endif /*_LLD_ */ - - diff --git a/drivers/staging/spectra/lld_cdma.c b/drivers/staging/spectra/lld_cdma.c deleted file mode 100644 index c6e76103d43c..000000000000 --- a/drivers/staging/spectra/lld_cdma.c +++ /dev/null @@ -1,910 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include -#include - -#include "spectraswconfig.h" -#include "lld.h" -#include "lld_nand.h" -#include "lld_cdma.h" -#include "lld_emu.h" -#include "flash.h" -#include "nand_regs.h" - -#define MAX_PENDING_CMDS 4 -#define MODE_02 (0x2 << 26) - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: CDMA_Data_Cmd -* Inputs: cmd code (aligned for hw) -* data: pointer to source or destination -* block: block address -* page: page address -* num: num pages to transfer -* Outputs: PASS -* Description: This function takes the parameters and puts them -* into the "pending commands" array. -* It does not parse or validate the parameters. -* The array index is same as the tag. -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 CDMA_Data_CMD(u8 cmd, u8 *data, u32 block, u16 page, u16 num, u16 flags) -{ - u8 bank; - - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (0 == cmd) - nand_dbg_print(NAND_DBG_DEBUG, - "%s, Line %d, Illegal cmd (0)\n", __FILE__, __LINE__); - - /* If a command of another bank comes, then first execute */ - /* pending commands of the current bank, then set the new */ - /* bank as current bank */ - bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); - if (bank != info.flash_bank) { - nand_dbg_print(NAND_DBG_WARN, - "Will access new bank. old bank: %d, new bank: %d\n", - info.flash_bank, bank); - if (CDMA_Execute_CMDs()) { - printk(KERN_ERR "CDMA_Execute_CMDs fail!\n"); - return FAIL; - } - info.flash_bank = bank; - } - - info.pcmds[info.pcmds_num].CMD = cmd; - info.pcmds[info.pcmds_num].DataAddr = data; - info.pcmds[info.pcmds_num].Block = block; - info.pcmds[info.pcmds_num].Page = page; - info.pcmds[info.pcmds_num].PageCount = num; - info.pcmds[info.pcmds_num].DataDestAddr = 0; - info.pcmds[info.pcmds_num].DataSrcAddr = 0; - info.pcmds[info.pcmds_num].MemCopyByteCnt = 0; - info.pcmds[info.pcmds_num].Flags = flags; - info.pcmds[info.pcmds_num].Status = 0xB0B; - - switch (cmd) { - case WRITE_MAIN_SPARE_CMD: - Conv_Main_Spare_Data_Log2Phy_Format(data, num); - break; - case WRITE_SPARE_CMD: - Conv_Spare_Data_Log2Phy_Format(data); - break; - default: - break; - } - - info.pcmds_num++; - - if (info.pcmds_num >= MAX_PENDING_CMDS) { - if (CDMA_Execute_CMDs()) { - printk(KERN_ERR "CDMA_Execute_CMDs fail!\n"); - return FAIL; - } - } - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: CDMA_MemCopy_CMD -* Inputs: dest: pointer to destination -* src: pointer to source -* count: num bytes to transfer -* Outputs: PASS -* Description: This function takes the parameters and puts them -* into the "pending commands" array. -* It does not parse or validate the parameters. -* The array index is same as the tag. -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 CDMA_MemCopy_CMD(u8 *dest, u8 *src, u32 byte_cnt, u16 flags) -{ - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - info.pcmds[info.pcmds_num].CMD = MEMCOPY_CMD; - info.pcmds[info.pcmds_num].DataAddr = 0; - info.pcmds[info.pcmds_num].Block = 0; - info.pcmds[info.pcmds_num].Page = 0; - info.pcmds[info.pcmds_num].PageCount = 0; - info.pcmds[info.pcmds_num].DataDestAddr = dest; - info.pcmds[info.pcmds_num].DataSrcAddr = src; - info.pcmds[info.pcmds_num].MemCopyByteCnt = byte_cnt; - info.pcmds[info.pcmds_num].Flags = flags; - info.pcmds[info.pcmds_num].Status = 0xB0B; - - info.pcmds_num++; - - if (info.pcmds_num >= MAX_PENDING_CMDS) { - if (CDMA_Execute_CMDs()) { - printk(KERN_ERR "CDMA_Execute_CMDs fail!\n"); - return FAIL; - } - } - - return PASS; -} - -#if 0 -/* Prints the PendingCMDs array */ -void print_pending_cmds(void) -{ - u16 i; - - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - for (i = 0; i < info.pcmds_num; i++) { - nand_dbg_print(NAND_DBG_DEBUG, "\ni: %d\n", i); - switch (info.pcmds[i].CMD) { - case ERASE_CMD: - nand_dbg_print(NAND_DBG_DEBUG, - "Erase Command (0x%x)\n", - info.pcmds[i].CMD); - break; - case WRITE_MAIN_CMD: - nand_dbg_print(NAND_DBG_DEBUG, - "Write Main Command (0x%x)\n", - info.pcmds[i].CMD); - break; - case WRITE_MAIN_SPARE_CMD: - nand_dbg_print(NAND_DBG_DEBUG, - "Write Main Spare Command (0x%x)\n", - info.pcmds[i].CMD); - break; - case READ_MAIN_SPARE_CMD: - nand_dbg_print(NAND_DBG_DEBUG, - "Read Main Spare Command (0x%x)\n", - info.pcmds[i].CMD); - break; - case READ_MAIN_CMD: - nand_dbg_print(NAND_DBG_DEBUG, - "Read Main Command (0x%x)\n", - info.pcmds[i].CMD); - break; - case MEMCOPY_CMD: - nand_dbg_print(NAND_DBG_DEBUG, - "Memcopy Command (0x%x)\n", - info.pcmds[i].CMD); - break; - case DUMMY_CMD: - nand_dbg_print(NAND_DBG_DEBUG, - "Dummy Command (0x%x)\n", - info.pcmds[i].CMD); - break; - default: - nand_dbg_print(NAND_DBG_DEBUG, - "Illegal Command (0x%x)\n", - info.pcmds[i].CMD); - break; - } - - nand_dbg_print(NAND_DBG_DEBUG, "DataAddr: 0x%x\n", - (u32)info.pcmds[i].DataAddr); - nand_dbg_print(NAND_DBG_DEBUG, "Block: %d\n", - info.pcmds[i].Block); - nand_dbg_print(NAND_DBG_DEBUG, "Page: %d\n", - info.pcmds[i].Page); - nand_dbg_print(NAND_DBG_DEBUG, "PageCount: %d\n", - info.pcmds[i].PageCount); - nand_dbg_print(NAND_DBG_DEBUG, "DataDestAddr: 0x%x\n", - (u32)info.pcmds[i].DataDestAddr); - nand_dbg_print(NAND_DBG_DEBUG, "DataSrcAddr: 0x%x\n", - (u32)info.pcmds[i].DataSrcAddr); - nand_dbg_print(NAND_DBG_DEBUG, "MemCopyByteCnt: %d\n", - info.pcmds[i].MemCopyByteCnt); - nand_dbg_print(NAND_DBG_DEBUG, "Flags: 0x%x\n", - info.pcmds[i].Flags); - nand_dbg_print(NAND_DBG_DEBUG, "Status: 0x%x\n", - info.pcmds[i].Status); - } -} - -/* Print the CDMA descriptors */ -void print_cdma_descriptors(void) -{ - struct cdma_descriptor *pc; - int i; - - pc = (struct cdma_descriptor *)info.cdma_desc_buf; - - nand_dbg_print(NAND_DBG_DEBUG, "\nWill dump cdma descriptors:\n"); - - for (i = 0; i < info.cdma_num; i++) { - nand_dbg_print(NAND_DBG_DEBUG, "\ni: %d\n", i); - nand_dbg_print(NAND_DBG_DEBUG, - "NxtPointerHi: 0x%x, NxtPointerLo: 0x%x\n", - pc[i].NxtPointerHi, pc[i].NxtPointerLo); - nand_dbg_print(NAND_DBG_DEBUG, - "FlashPointerHi: 0x%x, FlashPointerLo: 0x%x\n", - pc[i].FlashPointerHi, pc[i].FlashPointerLo); - nand_dbg_print(NAND_DBG_DEBUG, "CommandType: 0x%x\n", - pc[i].CommandType); - nand_dbg_print(NAND_DBG_DEBUG, - "MemAddrHi: 0x%x, MemAddrLo: 0x%x\n", - pc[i].MemAddrHi, pc[i].MemAddrLo); - nand_dbg_print(NAND_DBG_DEBUG, "CommandFlags: 0x%x\n", - pc[i].CommandFlags); - nand_dbg_print(NAND_DBG_DEBUG, "Channel: %d, Status: 0x%x\n", - pc[i].Channel, pc[i].Status); - nand_dbg_print(NAND_DBG_DEBUG, - "MemCopyPointerHi: 0x%x, MemCopyPointerLo: 0x%x\n", - pc[i].MemCopyPointerHi, pc[i].MemCopyPointerLo); - nand_dbg_print(NAND_DBG_DEBUG, - "Reserved12: 0x%x, Reserved13: 0x%x, " - "Reserved14: 0x%x, pcmd: %d\n", - pc[i].Reserved12, pc[i].Reserved13, - pc[i].Reserved14, pc[i].pcmd); - } -} - -/* Print the Memory copy descriptors */ -static void print_memcp_descriptors(void) -{ - struct memcpy_descriptor *pm; - int i; - - pm = (struct memcpy_descriptor *)info.memcp_desc_buf; - - nand_dbg_print(NAND_DBG_DEBUG, "\nWill dump mem_cpy descriptors:\n"); - - for (i = 0; i < info.cdma_num; i++) { - nand_dbg_print(NAND_DBG_DEBUG, "\ni: %d\n", i); - nand_dbg_print(NAND_DBG_DEBUG, - "NxtPointerHi: 0x%x, NxtPointerLo: 0x%x\n", - pm[i].NxtPointerHi, pm[i].NxtPointerLo); - nand_dbg_print(NAND_DBG_DEBUG, - "SrcAddrHi: 0x%x, SrcAddrLo: 0x%x\n", - pm[i].SrcAddrHi, pm[i].SrcAddrLo); - nand_dbg_print(NAND_DBG_DEBUG, - "DestAddrHi: 0x%x, DestAddrLo: 0x%x\n", - pm[i].DestAddrHi, pm[i].DestAddrLo); - nand_dbg_print(NAND_DBG_DEBUG, "XferSize: %d\n", - pm[i].XferSize); - nand_dbg_print(NAND_DBG_DEBUG, "MemCopyFlags: 0x%x\n", - pm[i].MemCopyFlags); - nand_dbg_print(NAND_DBG_DEBUG, "MemCopyStatus: %d\n", - pm[i].MemCopyStatus); - nand_dbg_print(NAND_DBG_DEBUG, "reserved9: 0x%x\n", - pm[i].reserved9); - nand_dbg_print(NAND_DBG_DEBUG, "reserved10: 0x%x\n", - pm[i].reserved10); - nand_dbg_print(NAND_DBG_DEBUG, "reserved11: 0x%x\n", - pm[i].reserved11); - nand_dbg_print(NAND_DBG_DEBUG, "reserved12: 0x%x\n", - pm[i].reserved12); - nand_dbg_print(NAND_DBG_DEBUG, "reserved13: 0x%x\n", - pm[i].reserved13); - nand_dbg_print(NAND_DBG_DEBUG, "reserved14: 0x%x\n", - pm[i].reserved14); - nand_dbg_print(NAND_DBG_DEBUG, "reserved15: 0x%x\n", - pm[i].reserved15); - } -} -#endif - -/* Reset cdma_descriptor chain to 0 */ -static void reset_cdma_desc(int i) -{ - struct cdma_descriptor *ptr; - - BUG_ON(i >= MAX_DESCS); - - ptr = (struct cdma_descriptor *)info.cdma_desc_buf; - - ptr[i].NxtPointerHi = 0; - ptr[i].NxtPointerLo = 0; - ptr[i].FlashPointerHi = 0; - ptr[i].FlashPointerLo = 0; - ptr[i].CommandType = 0; - ptr[i].MemAddrHi = 0; - ptr[i].MemAddrLo = 0; - ptr[i].CommandFlags = 0; - ptr[i].Channel = 0; - ptr[i].Status = 0; - ptr[i].MemCopyPointerHi = 0; - ptr[i].MemCopyPointerLo = 0; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: CDMA_UpdateEventStatus -* Inputs: none -* Outputs: none -* Description: This function update the event status of all the channels -* when an error condition is reported. -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -void CDMA_UpdateEventStatus(void) -{ - int i, j, active_chan; - struct cdma_descriptor *ptr; - - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - ptr = (struct cdma_descriptor *)info.cdma_desc_buf; - - for (j = 0; j < info.cdma_num; j++) { - /* Check for the descriptor with failure */ - if ((ptr[j].Status & CMD_DMA_DESC_FAIL)) - break; - - } - - /* All the previous cmd's status for this channel must be good */ - for (i = 0; i < j; i++) { - if (ptr[i].pcmd != 0xff) - info.pcmds[ptr[i].pcmd].Status = CMD_PASS; - } - - /* Abort the channel with type 0 reset command. It resets the */ - /* selected channel after the descriptor completes the flash */ - /* operation and status has been updated for the descriptor. */ - /* Memory Copy and Sync associated with this descriptor will */ - /* not be executed */ - active_chan = ioread32(FlashReg + CHNL_ACTIVE); - if ((active_chan & (1 << info.flash_bank)) == (1 << info.flash_bank)) { - iowrite32(MODE_02 | (0 << 4), FlashMem); /* Type 0 reset */ - iowrite32((0xF << 4) | info.flash_bank, FlashMem + 0x10); - } else { /* Should not reached here */ - printk(KERN_ERR "Error! Used bank is not set in" - " reg CHNL_ACTIVE\n"); - } -} - -static void cdma_trans(u16 chan) -{ - u32 addr; - - addr = info.cdma_desc; - - iowrite32(MODE_10 | (chan << 24), FlashMem); - iowrite32((1 << 7) | chan, FlashMem + 0x10); - - iowrite32(MODE_10 | (chan << 24) | ((0x0FFFF & (addr >> 16)) << 8), - FlashMem); - iowrite32((1 << 7) | (1 << 4) | 0, FlashMem + 0x10); - - iowrite32(MODE_10 | (chan << 24) | ((0x0FFFF & addr) << 8), FlashMem); - iowrite32((1 << 7) | (1 << 5) | 0, FlashMem + 0x10); - - iowrite32(MODE_10 | (chan << 24), FlashMem); - iowrite32((1 << 7) | (1 << 5) | (1 << 4) | 0, FlashMem + 0x10); -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: CDMA_Execute_CMDs (for use with CMD_DMA) -* Inputs: tag_count: the number of pending cmds to do -* Outputs: PASS/FAIL -* Description: Build the SDMA chain(s) by making one CMD-DMA descriptor -* for each pending command, start the CDMA engine, and return. -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 CDMA_Execute_CMDs(void) -{ - int i, ret; - u64 flash_add; - u32 ptr; - dma_addr_t map_addr, next_ptr; - u16 status = PASS; - u16 tmp_c; - struct cdma_descriptor *pc; - struct memcpy_descriptor *pm; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - /* No pending cmds to execute, just exit */ - if (0 == info.pcmds_num) { - nand_dbg_print(NAND_DBG_TRACE, - "No pending cmds to execute. Just exit.\n"); - return PASS; - } - - for (i = 0; i < MAX_DESCS; i++) - reset_cdma_desc(i); - - pc = (struct cdma_descriptor *)info.cdma_desc_buf; - pm = (struct memcpy_descriptor *)info.memcp_desc_buf; - - info.cdma_desc = virt_to_bus(info.cdma_desc_buf); - info.memcp_desc = virt_to_bus(info.memcp_desc_buf); - next_ptr = info.cdma_desc; - info.cdma_num = 0; - - for (i = 0; i < info.pcmds_num; i++) { - if (info.pcmds[i].Block >= DeviceInfo.wTotalBlocks) { - info.pcmds[i].Status = CMD_NOT_DONE; - continue; - } - - next_ptr += sizeof(struct cdma_descriptor); - pc[info.cdma_num].NxtPointerHi = next_ptr >> 16; - pc[info.cdma_num].NxtPointerLo = next_ptr & 0xffff; - - /* Use the Block offset within a bank */ - tmp_c = info.pcmds[i].Block / - (DeviceInfo.wTotalBlocks / totalUsedBanks); - flash_add = (u64)(info.pcmds[i].Block - tmp_c * - (DeviceInfo.wTotalBlocks / totalUsedBanks)) * - DeviceInfo.wBlockDataSize + - (u64)(info.pcmds[i].Page) * - DeviceInfo.wPageDataSize; - - ptr = MODE_10 | (info.flash_bank << 24) | - (u32)GLOB_u64_Div(flash_add, - DeviceInfo.wPageDataSize); - pc[info.cdma_num].FlashPointerHi = ptr >> 16; - pc[info.cdma_num].FlashPointerLo = ptr & 0xffff; - - if ((info.pcmds[i].CMD == WRITE_MAIN_SPARE_CMD) || - (info.pcmds[i].CMD == READ_MAIN_SPARE_CMD)) { - /* Descriptor to set Main+Spare Access Mode */ - pc[info.cdma_num].CommandType = 0x43; - pc[info.cdma_num].CommandFlags = - (0 << 10) | (1 << 9) | (0 << 8) | 0x40; - pc[info.cdma_num].MemAddrHi = 0; - pc[info.cdma_num].MemAddrLo = 0; - pc[info.cdma_num].Channel = 0; - pc[info.cdma_num].Status = 0; - pc[info.cdma_num].pcmd = i; - - info.cdma_num++; - BUG_ON(info.cdma_num >= MAX_DESCS); - - reset_cdma_desc(info.cdma_num); - next_ptr += sizeof(struct cdma_descriptor); - pc[info.cdma_num].NxtPointerHi = next_ptr >> 16; - pc[info.cdma_num].NxtPointerLo = next_ptr & 0xffff; - pc[info.cdma_num].FlashPointerHi = ptr >> 16; - pc[info.cdma_num].FlashPointerLo = ptr & 0xffff; - } - - switch (info.pcmds[i].CMD) { - case ERASE_CMD: - pc[info.cdma_num].CommandType = 1; - pc[info.cdma_num].CommandFlags = - (0 << 10) | (1 << 9) | (0 << 8) | 0x40; - pc[info.cdma_num].MemAddrHi = 0; - pc[info.cdma_num].MemAddrLo = 0; - break; - - case WRITE_MAIN_CMD: - pc[info.cdma_num].CommandType = - 0x2100 | info.pcmds[i].PageCount; - pc[info.cdma_num].CommandFlags = - (0 << 10) | (1 << 9) | (0 << 8) | 0x40; - map_addr = virt_to_bus(info.pcmds[i].DataAddr); - pc[info.cdma_num].MemAddrHi = map_addr >> 16; - pc[info.cdma_num].MemAddrLo = map_addr & 0xffff; - break; - - case READ_MAIN_CMD: - pc[info.cdma_num].CommandType = - 0x2000 | info.pcmds[i].PageCount; - pc[info.cdma_num].CommandFlags = - (0 << 10) | (1 << 9) | (0 << 8) | 0x40; - map_addr = virt_to_bus(info.pcmds[i].DataAddr); - pc[info.cdma_num].MemAddrHi = map_addr >> 16; - pc[info.cdma_num].MemAddrLo = map_addr & 0xffff; - break; - - case WRITE_MAIN_SPARE_CMD: - pc[info.cdma_num].CommandType = - 0x2100 | info.pcmds[i].PageCount; - pc[info.cdma_num].CommandFlags = - (0 << 10) | (1 << 9) | (0 << 8) | 0x40; - map_addr = virt_to_bus(info.pcmds[i].DataAddr); - pc[info.cdma_num].MemAddrHi = map_addr >> 16; - pc[info.cdma_num].MemAddrLo = map_addr & 0xffff; - break; - - case READ_MAIN_SPARE_CMD: - pc[info.cdma_num].CommandType = - 0x2000 | info.pcmds[i].PageCount; - pc[info.cdma_num].CommandFlags = - (0 << 10) | (1 << 9) | (0 << 8) | 0x40; - map_addr = virt_to_bus(info.pcmds[i].DataAddr); - pc[info.cdma_num].MemAddrHi = map_addr >> 16; - pc[info.cdma_num].MemAddrLo = map_addr & 0xffff; - break; - - case MEMCOPY_CMD: - pc[info.cdma_num].CommandType = 0xFFFF; /* NOP cmd */ - /* Set bit 11 to let the CDMA engine continue to */ - /* execute only after it has finished processing */ - /* the memcopy descriptor. */ - /* Also set bit 10 and bit 9 to 1 */ - pc[info.cdma_num].CommandFlags = 0x0E40; - map_addr = info.memcp_desc + info.cdma_num * - sizeof(struct memcpy_descriptor); - pc[info.cdma_num].MemCopyPointerHi = map_addr >> 16; - pc[info.cdma_num].MemCopyPointerLo = map_addr & 0xffff; - - pm[info.cdma_num].NxtPointerHi = 0; - pm[info.cdma_num].NxtPointerLo = 0; - - map_addr = virt_to_bus(info.pcmds[i].DataSrcAddr); - pm[info.cdma_num].SrcAddrHi = map_addr >> 16; - pm[info.cdma_num].SrcAddrLo = map_addr & 0xffff; - map_addr = virt_to_bus(info.pcmds[i].DataDestAddr); - pm[info.cdma_num].DestAddrHi = map_addr >> 16; - pm[info.cdma_num].DestAddrLo = map_addr & 0xffff; - - pm[info.cdma_num].XferSize = - info.pcmds[i].MemCopyByteCnt; - pm[info.cdma_num].MemCopyFlags = - (0 << 15 | 0 << 14 | 27 << 8 | 0x40); - pm[info.cdma_num].MemCopyStatus = 0; - break; - - case DUMMY_CMD: - default: - pc[info.cdma_num].CommandType = 0XFFFF; - pc[info.cdma_num].CommandFlags = - (0 << 10) | (1 << 9) | (0 << 8) | 0x40; - pc[info.cdma_num].MemAddrHi = 0; - pc[info.cdma_num].MemAddrLo = 0; - break; - } - - pc[info.cdma_num].Channel = 0; - pc[info.cdma_num].Status = 0; - pc[info.cdma_num].pcmd = i; - - info.cdma_num++; - BUG_ON(info.cdma_num >= MAX_DESCS); - - if ((info.pcmds[i].CMD == WRITE_MAIN_SPARE_CMD) || - (info.pcmds[i].CMD == READ_MAIN_SPARE_CMD)) { - /* Descriptor to set back Main Area Access Mode */ - reset_cdma_desc(info.cdma_num); - next_ptr += sizeof(struct cdma_descriptor); - pc[info.cdma_num].NxtPointerHi = next_ptr >> 16; - pc[info.cdma_num].NxtPointerLo = next_ptr & 0xffff; - - pc[info.cdma_num].FlashPointerHi = ptr >> 16; - pc[info.cdma_num].FlashPointerLo = ptr & 0xffff; - - pc[info.cdma_num].CommandType = 0x42; - pc[info.cdma_num].CommandFlags = - (0 << 10) | (1 << 9) | (0 << 8) | 0x40; - pc[info.cdma_num].MemAddrHi = 0; - pc[info.cdma_num].MemAddrLo = 0; - - pc[info.cdma_num].Channel = 0; - pc[info.cdma_num].Status = 0; - pc[info.cdma_num].pcmd = i; - - info.cdma_num++; - BUG_ON(info.cdma_num >= MAX_DESCS); - } - } - - /* Add a dummy descriptor at end of the CDMA chain */ - reset_cdma_desc(info.cdma_num); - ptr = MODE_10 | (info.flash_bank << 24); - pc[info.cdma_num].FlashPointerHi = ptr >> 16; - pc[info.cdma_num].FlashPointerLo = ptr & 0xffff; - pc[info.cdma_num].CommandType = 0xFFFF; /* NOP command */ - /* Set Command Flags for the last CDMA descriptor: */ - /* set Continue bit (bit 9) to 0 and Interrupt bit (bit 8) to 1 */ - pc[info.cdma_num].CommandFlags = - (0 << 10) | (0 << 9) | (1 << 8) | 0x40; - pc[info.cdma_num].pcmd = 0xff; /* Set it to an illegal value */ - info.cdma_num++; - BUG_ON(info.cdma_num >= MAX_DESCS); - - iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable Interrupt */ - - iowrite32(1, FlashReg + DMA_ENABLE); - /* Wait for DMA to be enabled before issuing the next command */ - while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - cdma_trans(info.flash_bank); - - ret = wait_for_completion_timeout(&info.complete, 50 * HZ); - if (!ret) - printk(KERN_ERR "Wait for completion timeout " - "in %s, Line %d\n", __FILE__, __LINE__); - status = info.ret; - - info.pcmds_num = 0; /* Clear the pending cmds number to 0 */ - - return status; -} - -int is_cdma_interrupt(void) -{ - u32 ints_b0, ints_b1, ints_b2, ints_b3, ints_cdma; - u32 int_en_mask; - u32 cdma_int_en_mask; - - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - /* Set the global Enable masks for only those interrupts - * that are supported */ - cdma_int_en_mask = (DMA_INTR__DESC_COMP_CHANNEL0 | - DMA_INTR__DESC_COMP_CHANNEL1 | - DMA_INTR__DESC_COMP_CHANNEL2 | - DMA_INTR__DESC_COMP_CHANNEL3 | - DMA_INTR__MEMCOPY_DESC_COMP); - - int_en_mask = (INTR_STATUS0__ECC_ERR | - INTR_STATUS0__PROGRAM_FAIL | - INTR_STATUS0__ERASE_FAIL); - - ints_b0 = ioread32(FlashReg + INTR_STATUS0) & int_en_mask; - ints_b1 = ioread32(FlashReg + INTR_STATUS1) & int_en_mask; - ints_b2 = ioread32(FlashReg + INTR_STATUS2) & int_en_mask; - ints_b3 = ioread32(FlashReg + INTR_STATUS3) & int_en_mask; - ints_cdma = ioread32(FlashReg + DMA_INTR) & cdma_int_en_mask; - - nand_dbg_print(NAND_DBG_WARN, "ints_bank0 to ints_bank3: " - "0x%x, 0x%x, 0x%x, 0x%x, ints_cdma: 0x%x\n", - ints_b0, ints_b1, ints_b2, ints_b3, ints_cdma); - - if (ints_b0 || ints_b1 || ints_b2 || ints_b3 || ints_cdma) { - return 1; - } else { - iowrite32(ints_b0, FlashReg + INTR_STATUS0); - iowrite32(ints_b1, FlashReg + INTR_STATUS1); - iowrite32(ints_b2, FlashReg + INTR_STATUS2); - iowrite32(ints_b3, FlashReg + INTR_STATUS3); - nand_dbg_print(NAND_DBG_DEBUG, - "Not a NAND controller interrupt! Ignore it.\n"); - return 0; - } -} - -static void update_event_status(void) -{ - int i; - struct cdma_descriptor *ptr; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - ptr = (struct cdma_descriptor *)info.cdma_desc_buf; - - for (i = 0; i < info.cdma_num; i++) { - if (ptr[i].pcmd != 0xff) - info.pcmds[ptr[i].pcmd].Status = CMD_PASS; - if ((ptr[i].CommandType == 0x41) || - (ptr[i].CommandType == 0x42) || - (ptr[i].CommandType == 0x43)) - continue; - - switch (info.pcmds[ptr[i].pcmd].CMD) { - case READ_MAIN_SPARE_CMD: - Conv_Main_Spare_Data_Phy2Log_Format( - info.pcmds[ptr[i].pcmd].DataAddr, - info.pcmds[ptr[i].pcmd].PageCount); - break; - case READ_SPARE_CMD: - Conv_Spare_Data_Phy2Log_Format( - info.pcmds[ptr[i].pcmd].DataAddr); - break; - } - } -} - -static u16 do_ecc_for_desc(u32 ch, u8 *buf, u16 page) -{ - u16 event = EVENT_NONE; - u16 err_byte; - u16 err_page = 0; - u8 err_sector; - u8 err_device; - u16 ecc_correction_info; - u16 err_address; - u32 eccSectorSize; - u8 *err_pos; - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected); - - do { - if (0 == ch) - err_page = ioread32(FlashReg + ERR_PAGE_ADDR0); - else if (1 == ch) - err_page = ioread32(FlashReg + ERR_PAGE_ADDR1); - else if (2 == ch) - err_page = ioread32(FlashReg + ERR_PAGE_ADDR2); - else if (3 == ch) - err_page = ioread32(FlashReg + ERR_PAGE_ADDR3); - - err_address = ioread32(FlashReg + ECC_ERROR_ADDRESS); - err_byte = err_address & ECC_ERROR_ADDRESS__OFFSET; - err_sector = ((err_address & - ECC_ERROR_ADDRESS__SECTOR_NR) >> 12); - - ecc_correction_info = ioread32(FlashReg + ERR_CORRECTION_INFO); - err_device = ((ecc_correction_info & - ERR_CORRECTION_INFO__DEVICE_NR) >> 8); - - if (ecc_correction_info & ERR_CORRECTION_INFO__ERROR_TYPE) { - event = EVENT_UNCORRECTABLE_DATA_ERROR; - } else { - event = EVENT_CORRECTABLE_DATA_ERROR_FIXED; - if (err_byte < ECC_SECTOR_SIZE) { - err_pos = buf + - (err_page - page) * - DeviceInfo.wPageDataSize + - err_sector * eccSectorSize + - err_byte * - DeviceInfo.wDevicesConnected + - err_device; - *err_pos ^= ecc_correction_info & - ERR_CORRECTION_INFO__BYTEMASK; - } - } - } while (!(ecc_correction_info & ERR_CORRECTION_INFO__LAST_ERR_INFO)); - - return event; -} - -static u16 process_ecc_int(u32 c, u16 *p_desc_num) -{ - struct cdma_descriptor *ptr; - u16 j; - int event = EVENT_PASS; - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (c != info.flash_bank) - printk(KERN_ERR "Error!info.flash_bank is %d, while c is %d\n", - info.flash_bank, c); - - ptr = (struct cdma_descriptor *)info.cdma_desc_buf; - - for (j = 0; j < info.cdma_num; j++) - if ((ptr[j].Status & CMD_DMA_DESC_COMP) != CMD_DMA_DESC_COMP) - break; - - *p_desc_num = j; /* Pass the descripter number found here */ - - if (j >= info.cdma_num) { - printk(KERN_ERR "Can not find the correct descriptor number " - "when ecc interrupt triggered!" - "info.cdma_num: %d, j: %d\n", info.cdma_num, j); - return EVENT_UNCORRECTABLE_DATA_ERROR; - } - - event = do_ecc_for_desc(c, info.pcmds[ptr[j].pcmd].DataAddr, - info.pcmds[ptr[j].pcmd].Page); - - if (EVENT_UNCORRECTABLE_DATA_ERROR == event) { - printk(KERN_ERR "Uncorrectable ECC error!" - "info.cdma_num: %d, j: %d, " - "pending cmd CMD: 0x%x, " - "Block: 0x%x, Page: 0x%x, PageCount: 0x%x\n", - info.cdma_num, j, - info.pcmds[ptr[j].pcmd].CMD, - info.pcmds[ptr[j].pcmd].Block, - info.pcmds[ptr[j].pcmd].Page, - info.pcmds[ptr[j].pcmd].PageCount); - - if (ptr[j].pcmd != 0xff) - info.pcmds[ptr[j].pcmd].Status = CMD_FAIL; - CDMA_UpdateEventStatus(); - } - - return event; -} - -static void process_prog_erase_fail_int(u16 desc_num) -{ - struct cdma_descriptor *ptr; - - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - ptr = (struct cdma_descriptor *)info.cdma_desc_buf; - - if (ptr[desc_num].pcmd != 0xFF) - info.pcmds[ptr[desc_num].pcmd].Status = CMD_FAIL; - - CDMA_UpdateEventStatus(); -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: CDMA_Event_Status (for use with CMD_DMA) -* Inputs: none -* Outputs: Event_Status code -* Description: This function is called after an interrupt has happened -* It reads the HW status register and ...tbd -* It returns the appropriate event status -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 CDMA_Event_Status(void) -{ - u32 ints_addr[4] = {INTR_STATUS0, INTR_STATUS1, - INTR_STATUS2, INTR_STATUS3}; - u32 dma_intr_bit[4] = {DMA_INTR__DESC_COMP_CHANNEL0, - DMA_INTR__DESC_COMP_CHANNEL1, - DMA_INTR__DESC_COMP_CHANNEL2, - DMA_INTR__DESC_COMP_CHANNEL3}; - u32 cdma_int_status, int_status; - u32 ecc_enable = 0; - u16 event = EVENT_PASS; - u16 cur_desc = 0; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - ecc_enable = ioread32(FlashReg + ECC_ENABLE); - - while (1) { - int_status = ioread32(FlashReg + ints_addr[info.flash_bank]); - if (ecc_enable && (int_status & INTR_STATUS0__ECC_ERR)) { - event = process_ecc_int(info.flash_bank, &cur_desc); - iowrite32(INTR_STATUS0__ECC_ERR, - FlashReg + ints_addr[info.flash_bank]); - if (EVENT_UNCORRECTABLE_DATA_ERROR == event) { - nand_dbg_print(NAND_DBG_WARN, - "ints_bank0 to ints_bank3: " - "0x%x, 0x%x, 0x%x, 0x%x, " - "ints_cdma: 0x%x\n", - ioread32(FlashReg + INTR_STATUS0), - ioread32(FlashReg + INTR_STATUS1), - ioread32(FlashReg + INTR_STATUS2), - ioread32(FlashReg + INTR_STATUS3), - ioread32(FlashReg + DMA_INTR)); - break; - } - } else if (int_status & INTR_STATUS0__PROGRAM_FAIL) { - printk(KERN_ERR "NAND program fail interrupt!\n"); - process_prog_erase_fail_int(cur_desc); - event = EVENT_PROGRAM_FAILURE; - break; - } else if (int_status & INTR_STATUS0__ERASE_FAIL) { - printk(KERN_ERR "NAND erase fail interrupt!\n"); - process_prog_erase_fail_int(cur_desc); - event = EVENT_ERASE_FAILURE; - break; - } else { - cdma_int_status = ioread32(FlashReg + DMA_INTR); - if (cdma_int_status & dma_intr_bit[info.flash_bank]) { - iowrite32(dma_intr_bit[info.flash_bank], - FlashReg + DMA_INTR); - update_event_status(); - event = EVENT_PASS; - break; - } - } - } - - int_status = ioread32(FlashReg + ints_addr[info.flash_bank]); - iowrite32(int_status, FlashReg + ints_addr[info.flash_bank]); - cdma_int_status = ioread32(FlashReg + DMA_INTR); - iowrite32(cdma_int_status, FlashReg + DMA_INTR); - - iowrite32(0, FlashReg + DMA_ENABLE); - while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - - return event; -} - - - diff --git a/drivers/staging/spectra/lld_cdma.h b/drivers/staging/spectra/lld_cdma.h deleted file mode 100644 index 854ea066f0c4..000000000000 --- a/drivers/staging/spectra/lld_cdma.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -/* header for LLD_CDMA.c module */ - -#ifndef _LLD_CDMA_ -#define _LLD_CDMA_ - -#include "flash.h" - -#define DEBUG_SYNC 1 - -/*/////////// CDMA specific MACRO definition */ -#define MAX_DESCS (255) -#define MAX_CHANS (4) -#define MAX_SYNC_POINTS (16) -#define MAX_DESC_PER_CHAN (MAX_DESCS * 3 + MAX_SYNC_POINTS + 2) - -#define CHANNEL_SYNC_MASK (0x000F) -#define CHANNEL_DMA_MASK (0x00F0) -#define CHANNEL_ID_MASK (0x0300) -#define CHANNEL_CONT_MASK (0x4000) -#define CHANNEL_INTR_MASK (0x8000) - -#define CHANNEL_SYNC_OFFSET (0) -#define CHANNEL_DMA_OFFSET (4) -#define CHANNEL_ID_OFFSET (8) -#define CHANNEL_CONT_OFFSET (14) -#define CHANNEL_INTR_OFFSET (15) - -u16 CDMA_Data_CMD(u8 cmd, u8 *data, u32 block, u16 page, u16 num, u16 flags); -u16 CDMA_MemCopy_CMD(u8 *dest, u8 *src, u32 byte_cnt, u16 flags); -u16 CDMA_Execute_CMDs(void); -void print_pending_cmds(void); -void print_cdma_descriptors(void); - -extern u8 g_SBDCmdIndex; -extern struct mrst_nand_info info; - - -/*/////////// prototypes: APIs for LLD_CDMA */ -int is_cdma_interrupt(void); -u16 CDMA_Event_Status(void); - -/* CMD-DMA Descriptor Struct. These are defined by the CMD_DMA HW */ -struct cdma_descriptor { - u32 NxtPointerHi; - u32 NxtPointerLo; - u32 FlashPointerHi; - u32 FlashPointerLo; - u32 CommandType; - u32 MemAddrHi; - u32 MemAddrLo; - u32 CommandFlags; - u32 Channel; - u32 Status; - u32 MemCopyPointerHi; - u32 MemCopyPointerLo; - u32 Reserved12; - u32 Reserved13; - u32 Reserved14; - u32 pcmd; /* pending cmd num related to this descriptor */ -}; - -/* This struct holds one MemCopy descriptor as defined by the HW */ -struct memcpy_descriptor { - u32 NxtPointerHi; - u32 NxtPointerLo; - u32 SrcAddrHi; - u32 SrcAddrLo; - u32 DestAddrHi; - u32 DestAddrLo; - u32 XferSize; - u32 MemCopyFlags; - u32 MemCopyStatus; - u32 reserved9; - u32 reserved10; - u32 reserved11; - u32 reserved12; - u32 reserved13; - u32 reserved14; - u32 reserved15; -}; - -/* Pending CMD table entries (includes MemCopy parameters */ -struct pending_cmd { - u8 CMD; - u8 *DataAddr; - u32 Block; - u16 Page; - u16 PageCount; - u8 *DataDestAddr; - u8 *DataSrcAddr; - u32 MemCopyByteCnt; - u16 Flags; - u16 Status; -}; - -#if DEBUG_SYNC -extern u32 debug_sync_cnt; -#endif - -/* Definitions for CMD DMA descriptor chain fields */ -#define CMD_DMA_DESC_COMP 0x8000 -#define CMD_DMA_DESC_FAIL 0x4000 - -#endif /*_LLD_CDMA_*/ diff --git a/drivers/staging/spectra/lld_emu.c b/drivers/staging/spectra/lld_emu.c deleted file mode 100644 index 095f2f0c2e5b..000000000000 --- a/drivers/staging/spectra/lld_emu.c +++ /dev/null @@ -1,776 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include -#include -#include "flash.h" -#include "ffsdefs.h" -#include "lld_emu.h" -#include "lld.h" -#if CMD_DMA -#include "lld_cdma.h" -#if FLASH_EMU -u32 totalUsedBanks; -u32 valid_banks[MAX_CHANS]; -#endif -#endif - -#define GLOB_LLD_PAGES 64 -#define GLOB_LLD_PAGE_SIZE (512+16) -#define GLOB_LLD_PAGE_DATA_SIZE 512 -#define GLOB_LLD_BLOCKS 2048 - -#if FLASH_EMU /* This is for entire module */ - -static u8 *flash_memory[GLOB_LLD_BLOCKS * GLOB_LLD_PAGES]; - -/* Read nand emu file and then fill it's content to flash_memory */ -int emu_load_file_to_mem(void) -{ - mm_segment_t fs; - struct file *nef_filp = NULL; - struct inode *inode = NULL; - loff_t nef_size = 0; - loff_t tmp_file_offset, file_offset; - ssize_t nread; - int i, rc = -EINVAL; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - fs = get_fs(); - set_fs(get_ds()); - - nef_filp = filp_open("/root/nand_emu_file", O_RDWR | O_LARGEFILE, 0); - if (IS_ERR(nef_filp)) { - printk(KERN_ERR "filp_open error: " - "Unable to open nand emu file!\n"); - return PTR_ERR(nef_filp); - } - - if (nef_filp->f_path.dentry) { - inode = nef_filp->f_path.dentry->d_inode; - } else { - printk(KERN_ERR "Can not get valid inode!\n"); - goto out; - } - - nef_size = i_size_read(inode->i_mapping->host); - if (nef_size <= 0) { - printk(KERN_ERR "Invalid nand emu file size: " - "0x%llx\n", nef_size); - goto out; - } else { - nand_dbg_print(NAND_DBG_DEBUG, "nand emu file size: %lld\n", - nef_size); - } - - file_offset = 0; - for (i = 0; i < GLOB_LLD_BLOCKS * GLOB_LLD_PAGES; i++) { - tmp_file_offset = file_offset; - nread = vfs_read(nef_filp, - (char __user *)flash_memory[i], - GLOB_LLD_PAGE_SIZE, &tmp_file_offset); - if (nread < GLOB_LLD_PAGE_SIZE) { - printk(KERN_ERR "%s, Line %d - " - "nand emu file partial read: " - "%d bytes\n", __FILE__, __LINE__, (int)nread); - goto out; - } - file_offset += GLOB_LLD_PAGE_SIZE; - } - rc = 0; - -out: - filp_close(nef_filp, current->files); - set_fs(fs); - return rc; -} - -/* Write contents of flash_memory to nand emu file */ -int emu_write_mem_to_file(void) -{ - mm_segment_t fs; - struct file *nef_filp = NULL; - struct inode *inode = NULL; - loff_t nef_size = 0; - loff_t tmp_file_offset, file_offset; - ssize_t nwritten; - int i, rc = -EINVAL; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - fs = get_fs(); - set_fs(get_ds()); - - nef_filp = filp_open("/root/nand_emu_file", O_RDWR | O_LARGEFILE, 0); - if (IS_ERR(nef_filp)) { - printk(KERN_ERR "filp_open error: " - "Unable to open nand emu file!\n"); - return PTR_ERR(nef_filp); - } - - if (nef_filp->f_path.dentry) { - inode = nef_filp->f_path.dentry->d_inode; - } else { - printk(KERN_ERR "Invalid " "nef_filp->f_path.dentry value!\n"); - goto out; - } - - nef_size = i_size_read(inode->i_mapping->host); - if (nef_size <= 0) { - printk(KERN_ERR "Invalid " - "nand emu file size: 0x%llx\n", nef_size); - goto out; - } else { - nand_dbg_print(NAND_DBG_DEBUG, "nand emu file size: " - "%lld\n", nef_size); - } - - file_offset = 0; - for (i = 0; i < GLOB_LLD_BLOCKS * GLOB_LLD_PAGES; i++) { - tmp_file_offset = file_offset; - nwritten = vfs_write(nef_filp, - (char __user *)flash_memory[i], - GLOB_LLD_PAGE_SIZE, &tmp_file_offset); - if (nwritten < GLOB_LLD_PAGE_SIZE) { - printk(KERN_ERR "%s, Line %d - " - "nand emu file partial write: " - "%d bytes\n", __FILE__, __LINE__, (int)nwritten); - goto out; - } - file_offset += GLOB_LLD_PAGE_SIZE; - } - rc = 0; - -out: - filp_close(nef_filp, current->files); - set_fs(fs); - return rc; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: emu_Flash_Init -* Inputs: none -* Outputs: PASS=0 (notice 0=ok here) -* Description: Creates & initializes the flash RAM array. -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 emu_Flash_Init(void) -{ - int i; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - flash_memory[0] = vmalloc(GLOB_LLD_PAGE_SIZE * GLOB_LLD_BLOCKS * - GLOB_LLD_PAGES * sizeof(u8)); - if (!flash_memory[0]) { - printk(KERN_ERR "Fail to allocate memory " - "for nand emulator!\n"); - return ERR; - } - - memset((char *)(flash_memory[0]), 0xFF, - GLOB_LLD_PAGE_SIZE * GLOB_LLD_BLOCKS * GLOB_LLD_PAGES * - sizeof(u8)); - - for (i = 1; i < GLOB_LLD_BLOCKS * GLOB_LLD_PAGES; i++) - flash_memory[i] = flash_memory[i - 1] + GLOB_LLD_PAGE_SIZE; - - emu_load_file_to_mem(); /* Load nand emu file to mem */ - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: emu_Flash_Release -* Inputs: none -* Outputs: PASS=0 (notice 0=ok here) -* Description: Releases the flash. -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int emu_Flash_Release(void) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - emu_write_mem_to_file(); /* Write back mem to nand emu file */ - - vfree(flash_memory[0]); - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: emu_Read_Device_ID -* Inputs: none -* Outputs: PASS=1 FAIL=0 -* Description: Reads the info from the controller registers. -* Sets up DeviceInfo structure with device parameters -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ - -u16 emu_Read_Device_ID(void) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - DeviceInfo.wDeviceMaker = 0; - DeviceInfo.wDeviceType = 8; - DeviceInfo.wSpectraStartBlock = 36; - DeviceInfo.wSpectraEndBlock = GLOB_LLD_BLOCKS - 1; - DeviceInfo.wTotalBlocks = GLOB_LLD_BLOCKS; - DeviceInfo.wPagesPerBlock = GLOB_LLD_PAGES; - DeviceInfo.wPageSize = GLOB_LLD_PAGE_SIZE; - DeviceInfo.wPageDataSize = GLOB_LLD_PAGE_DATA_SIZE; - DeviceInfo.wPageSpareSize = GLOB_LLD_PAGE_SIZE - - GLOB_LLD_PAGE_DATA_SIZE; - DeviceInfo.wBlockSize = DeviceInfo.wPageSize * GLOB_LLD_PAGES; - DeviceInfo.wBlockDataSize = DeviceInfo.wPageDataSize * GLOB_LLD_PAGES; - DeviceInfo.wDataBlockNum = (u32) (DeviceInfo.wSpectraEndBlock - - DeviceInfo.wSpectraStartBlock - + 1); - DeviceInfo.MLCDevice = 1; /* Emulate MLC device */ - DeviceInfo.nBitsInPageNumber = - (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPagesPerBlock); - DeviceInfo.nBitsInPageDataSize = - (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPageDataSize); - DeviceInfo.nBitsInBlockDataSize = - (u8)GLOB_Calc_Used_Bits(DeviceInfo.wBlockDataSize); - -#if CMD_DMA - totalUsedBanks = 4; - valid_banks[0] = 1; - valid_banks[1] = 1; - valid_banks[2] = 1; - valid_banks[3] = 1; -#endif - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: emu_Flash_Reset -* Inputs: none -* Outputs: PASS=0 (notice 0=ok here) -* Description: Reset the flash -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 emu_Flash_Reset(void) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: emu_Erase_Block -* Inputs: Address -* Outputs: PASS=0 (notice 0=ok here) -* Description: Erase a block -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 emu_Erase_Block(u32 block_add) -{ - int i; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (block_add >= DeviceInfo.wTotalBlocks) { - printk(KERN_ERR "emu_Erase_Block error! " - "Too big block address: %d\n", block_add); - return FAIL; - } - - nand_dbg_print(NAND_DBG_DEBUG, "Erasing block %d\n", - (int)block_add); - - for (i = block_add * GLOB_LLD_PAGES; - i < ((block_add + 1) * GLOB_LLD_PAGES); i++) { - if (flash_memory[i]) { - memset((u8 *)(flash_memory[i]), 0xFF, - DeviceInfo.wPageSize * sizeof(u8)); - } - } - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: emu_Write_Page_Main -* Inputs: Write buffer address pointer -* Block number -* Page number -* Number of pages to process -* Outputs: PASS=0 (notice 0=ok here) -* Description: Write the data in the buffer to main area of flash -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 emu_Write_Page_Main(u8 *write_data, u32 Block, - u16 Page, u16 PageCount) -{ - int i; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (Block >= DeviceInfo.wTotalBlocks) - return FAIL; - - if (Page + PageCount > DeviceInfo.wPagesPerBlock) - return FAIL; - - nand_dbg_print(NAND_DBG_DEBUG, "emu_Write_Page_Main: " - "lba %u Page %u PageCount %u\n", - (unsigned int)Block, - (unsigned int)Page, (unsigned int)PageCount); - - for (i = 0; i < PageCount; i++) { - if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) { - printk(KERN_ERR "Run out of memory\n"); - return FAIL; - } - memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page]), - write_data, DeviceInfo.wPageDataSize); - write_data += DeviceInfo.wPageDataSize; - Page++; - } - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: emu_Read_Page_Main -* Inputs: Read buffer address pointer -* Block number -* Page number -* Number of pages to process -* Outputs: PASS=0 (notice 0=ok here) -* Description: Read the data from the flash main area to the buffer -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 emu_Read_Page_Main(u8 *read_data, u32 Block, - u16 Page, u16 PageCount) -{ - int i; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (Block >= DeviceInfo.wTotalBlocks) - return FAIL; - - if (Page + PageCount > DeviceInfo.wPagesPerBlock) - return FAIL; - - nand_dbg_print(NAND_DBG_DEBUG, "emu_Read_Page_Main: " - "lba %u Page %u PageCount %u\n", - (unsigned int)Block, - (unsigned int)Page, (unsigned int)PageCount); - - for (i = 0; i < PageCount; i++) { - if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) { - memset(read_data, 0xFF, DeviceInfo.wPageDataSize); - } else { - memcpy(read_data, - (u8 *) (flash_memory[Block * GLOB_LLD_PAGES - + Page]), - DeviceInfo.wPageDataSize); - } - read_data += DeviceInfo.wPageDataSize; - Page++; - } - - return PASS; -} - -#ifndef ELDORA -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: emu_Read_Page_Main_Spare -* Inputs: Write Buffer -* Address -* Buffer size -* Outputs: PASS=0 (notice 0=ok here) -* Description: Read from flash main+spare area -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 emu_Read_Page_Main_Spare(u8 *read_data, u32 Block, - u16 Page, u16 PageCount) -{ - int i; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (Block >= DeviceInfo.wTotalBlocks) { - printk(KERN_ERR "Read Page Main+Spare " - "Error: Block Address too big\n"); - return FAIL; - } - - if (Page + PageCount > DeviceInfo.wPagesPerBlock) { - printk(KERN_ERR "Read Page Main+Spare " - "Error: Page number too big\n"); - return FAIL; - } - - nand_dbg_print(NAND_DBG_DEBUG, "Read Page Main + Spare - " - "No. of pages %u block %u start page %u\n", - (unsigned int)PageCount, - (unsigned int)Block, (unsigned int)Page); - - for (i = 0; i < PageCount; i++) { - if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) { - memset(read_data, 0xFF, DeviceInfo.wPageSize); - } else { - memcpy(read_data, (u8 *) (flash_memory[Block * - GLOB_LLD_PAGES - + Page]), - DeviceInfo.wPageSize); - } - - read_data += DeviceInfo.wPageSize; - Page++; - } - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: emu_Write_Page_Main_Spare -* Inputs: Write buffer -* address -* buffer length -* Outputs: PASS=0 (notice 0=ok here) -* Description: Write the buffer to main+spare area of flash -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 emu_Write_Page_Main_Spare(u8 *write_data, u32 Block, - u16 Page, u16 page_count) -{ - u16 i; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (Block >= DeviceInfo.wTotalBlocks) { - printk(KERN_ERR "Write Page Main + Spare " - "Error: Block Address too big\n"); - return FAIL; - } - - if (Page + page_count > DeviceInfo.wPagesPerBlock) { - printk(KERN_ERR "Write Page Main + Spare " - "Error: Page number too big\n"); - return FAIL; - } - - nand_dbg_print(NAND_DBG_DEBUG, "Write Page Main+Spare - " - "No. of pages %u block %u start page %u\n", - (unsigned int)page_count, - (unsigned int)Block, (unsigned int)Page); - - for (i = 0; i < page_count; i++) { - if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) { - printk(KERN_ERR "Run out of memory!\n"); - return FAIL; - } - memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page]), - write_data, DeviceInfo.wPageSize); - write_data += DeviceInfo.wPageSize; - Page++; - } - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: emu_Write_Page_Spare -* Inputs: Write buffer -* Address -* buffer size -* Outputs: PASS=0 (notice 0=ok here) -* Description: Write the buffer in the spare area -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 emu_Write_Page_Spare(u8 *write_data, u32 Block, - u16 Page, u16 PageCount) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (Block >= DeviceInfo.wTotalBlocks) { - printk(KERN_ERR "Read Page Spare Error: " - "Block Address too big\n"); - return FAIL; - } - - if (Page + PageCount > DeviceInfo.wPagesPerBlock) { - printk(KERN_ERR "Read Page Spare Error: " - "Page number too big\n"); - return FAIL; - } - - nand_dbg_print(NAND_DBG_DEBUG, "Write Page Spare- " - "block %u page %u\n", - (unsigned int)Block, (unsigned int)Page); - - if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) { - printk(KERN_ERR "Run out of memory!\n"); - return FAIL; - } - - memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page] + - DeviceInfo.wPageDataSize), write_data, - (DeviceInfo.wPageSize - DeviceInfo.wPageDataSize)); - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: emu_Read_Page_Spare -* Inputs: Write Buffer -* Address -* Buffer size -* Outputs: PASS=0 (notice 0=ok here) -* Description: Read data from the spare area -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 emu_Read_Page_Spare(u8 *write_data, u32 Block, - u16 Page, u16 PageCount) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (Block >= DeviceInfo.wTotalBlocks) { - printk(KERN_ERR "Read Page Spare " - "Error: Block Address too big\n"); - return FAIL; - } - - if (Page + PageCount > DeviceInfo.wPagesPerBlock) { - printk(KERN_ERR "Read Page Spare " - "Error: Page number too big\n"); - return FAIL; - } - - nand_dbg_print(NAND_DBG_DEBUG, "Read Page Spare- " - "block %u page %u\n", - (unsigned int)Block, (unsigned int)Page); - - if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) { - memset(write_data, 0xFF, - (DeviceInfo.wPageSize - DeviceInfo.wPageDataSize)); - } else { - memcpy(write_data, - (u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page] - + DeviceInfo.wPageDataSize), - (DeviceInfo.wPageSize - DeviceInfo.wPageDataSize)); - } - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: emu_Enable_Disable_Interrupts -* Inputs: enable or disable -* Outputs: none -* Description: NOP -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -void emu_Enable_Disable_Interrupts(u16 INT_ENABLE) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); -} - -u16 emu_Get_Bad_Block(u32 block) -{ - return 0; -} - -#if CMD_DMA -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Support for CDMA functions -************************************ -* emu_CDMA_Flash_Init -* CDMA_process_data command (use LLD_CDMA) -* CDMA_MemCopy_CMD (use LLD_CDMA) -* emu_CDMA_execute all commands -* emu_CDMA_Event_Status -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 emu_CDMA_Flash_Init(void) -{ - u16 i; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - for (i = 0; i < MAX_DESCS + MAX_CHANS; i++) { - PendingCMD[i].CMD = 0; - PendingCMD[i].Tag = 0; - PendingCMD[i].DataAddr = 0; - PendingCMD[i].Block = 0; - PendingCMD[i].Page = 0; - PendingCMD[i].PageCount = 0; - PendingCMD[i].DataDestAddr = 0; - PendingCMD[i].DataSrcAddr = 0; - PendingCMD[i].MemCopyByteCnt = 0; - PendingCMD[i].ChanSync[0] = 0; - PendingCMD[i].ChanSync[1] = 0; - PendingCMD[i].ChanSync[2] = 0; - PendingCMD[i].ChanSync[3] = 0; - PendingCMD[i].ChanSync[4] = 0; - PendingCMD[i].Status = 3; - } - - return PASS; -} - -static void emu_isr(int irq, void *dev_id) -{ - /* TODO: ... */ -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: CDMA_Execute_CMDs -* Inputs: tag_count: the number of pending cmds to do -* Outputs: PASS/FAIL -* Description: execute each command in the pending CMD array -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 emu_CDMA_Execute_CMDs(u16 tag_count) -{ - u16 i, j; - u8 CMD; /* cmd parameter */ - u8 *data; - u32 block; - u16 page; - u16 count; - u16 status = PASS; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - nand_dbg_print(NAND_DBG_TRACE, "At start of Execute CMDs: " - "Tag Count %u\n", tag_count); - - for (i = 0; i < totalUsedBanks; i++) { - PendingCMD[i].CMD = DUMMY_CMD; - PendingCMD[i].Tag = 0xFF; - PendingCMD[i].Block = - (DeviceInfo.wTotalBlocks / totalUsedBanks) * i; - - for (j = 0; j <= MAX_CHANS; j++) - PendingCMD[i].ChanSync[j] = 0; - } - - CDMA_Execute_CMDs(tag_count); - - print_pending_cmds(tag_count); - -#if DEBUG_SYNC - } - debug_sync_cnt++; -#endif - - for (i = MAX_CHANS; - i < tag_count + MAX_CHANS; i++) { - CMD = PendingCMD[i].CMD; - data = PendingCMD[i].DataAddr; - block = PendingCMD[i].Block; - page = PendingCMD[i].Page; - count = PendingCMD[i].PageCount; - - switch (CMD) { - case ERASE_CMD: - emu_Erase_Block(block); - PendingCMD[i].Status = PASS; - break; - case WRITE_MAIN_CMD: - emu_Write_Page_Main(data, block, page, count); - PendingCMD[i].Status = PASS; - break; - case WRITE_MAIN_SPARE_CMD: - emu_Write_Page_Main_Spare(data, block, page, count); - PendingCMD[i].Status = PASS; - break; - case READ_MAIN_CMD: - emu_Read_Page_Main(data, block, page, count); - PendingCMD[i].Status = PASS; - break; - case MEMCOPY_CMD: - memcpy(PendingCMD[i].DataDestAddr, - PendingCMD[i].DataSrcAddr, - PendingCMD[i].MemCopyByteCnt); - case DUMMY_CMD: - PendingCMD[i].Status = PASS; - break; - default: - PendingCMD[i].Status = FAIL; - break; - } - } - - /* - * Temperory adding code to reset PendingCMD array for basic testing. - * It should be done at the end of event status function. - */ - for (i = tag_count + MAX_CHANS; i < MAX_DESCS; i++) { - PendingCMD[i].CMD = 0; - PendingCMD[i].Tag = 0; - PendingCMD[i].DataAddr = 0; - PendingCMD[i].Block = 0; - PendingCMD[i].Page = 0; - PendingCMD[i].PageCount = 0; - PendingCMD[i].DataDestAddr = 0; - PendingCMD[i].DataSrcAddr = 0; - PendingCMD[i].MemCopyByteCnt = 0; - PendingCMD[i].ChanSync[0] = 0; - PendingCMD[i].ChanSync[1] = 0; - PendingCMD[i].ChanSync[2] = 0; - PendingCMD[i].ChanSync[3] = 0; - PendingCMD[i].ChanSync[4] = 0; - PendingCMD[i].Status = CMD_NOT_DONE; - } - - nand_dbg_print(NAND_DBG_TRACE, "At end of Execute CMDs.\n"); - - emu_isr(0, 0); /* This is a null isr now. Need fill it in future */ - - return status; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: emu_Event_Status -* Inputs: none -* Outputs: Event_Status code -* Description: This function can also be used to force errors -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 emu_CDMA_Event_Status(void) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - return EVENT_PASS; -} - -#endif /* CMD_DMA */ -#endif /* !ELDORA */ -#endif /* FLASH_EMU */ diff --git a/drivers/staging/spectra/lld_emu.h b/drivers/staging/spectra/lld_emu.h deleted file mode 100644 index 63f84c38d3c1..000000000000 --- a/drivers/staging/spectra/lld_emu.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef _LLD_EMU_ -#define _LLD_EMU_ - -#include "ffsport.h" -#include "ffsdefs.h" - -/* prototypes: emulator API functions */ -extern u16 emu_Flash_Reset(void); -extern u16 emu_Flash_Init(void); -extern int emu_Flash_Release(void); -extern u16 emu_Read_Device_ID(void); -extern u16 emu_Erase_Block(u32 block_addr); -extern u16 emu_Write_Page_Main(u8 *write_data, u32 Block, - u16 Page, u16 PageCount); -extern u16 emu_Read_Page_Main(u8 *read_data, u32 Block, u16 Page, - u16 PageCount); -extern u16 emu_Event_Status(void); -extern void emu_Enable_Disable_Interrupts(u16 INT_ENABLE); -extern u16 emu_Write_Page_Main_Spare(u8 *write_data, u32 Block, - u16 Page, u16 PageCount); -extern u16 emu_Write_Page_Spare(u8 *write_data, u32 Block, - u16 Page, u16 PageCount); -extern u16 emu_Read_Page_Main_Spare(u8 *read_data, u32 Block, - u16 Page, u16 PageCount); -extern u16 emu_Read_Page_Spare(u8 *read_data, u32 Block, u16 Page, - u16 PageCount); -extern u16 emu_Get_Bad_Block(u32 block); - -u16 emu_CDMA_Flash_Init(void); -u16 emu_CDMA_Execute_CMDs(u16 tag_count); -u16 emu_CDMA_Event_Status(void); -#endif /*_LLD_EMU_*/ diff --git a/drivers/staging/spectra/lld_mtd.c b/drivers/staging/spectra/lld_mtd.c deleted file mode 100644 index a9c309a167c2..000000000000 --- a/drivers/staging/spectra/lld_mtd.c +++ /dev/null @@ -1,683 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include -#include -#include -#include "flash.h" -#include "ffsdefs.h" -#include "lld_emu.h" -#include "lld.h" -#if CMD_DMA -#include "lld_cdma.h" -u32 totalUsedBanks; -u32 valid_banks[MAX_CHANS]; -#endif - -#define GLOB_LLD_PAGES 64 -#define GLOB_LLD_PAGE_SIZE (512+16) -#define GLOB_LLD_PAGE_DATA_SIZE 512 -#define GLOB_LLD_BLOCKS 2048 - -static struct mtd_info *spectra_mtd; -static int mtddev = -1; -module_param(mtddev, int, 0); - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: mtd_Flash_Init -* Inputs: none -* Outputs: PASS=0 (notice 0=ok here) -* Description: Creates & initializes the flash RAM array. -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 mtd_Flash_Init(void) -{ - if (mtddev == -1) { - printk(KERN_ERR "No MTD device specified. Give mtddev parameter\n"); - return FAIL; - } - - spectra_mtd = get_mtd_device(NULL, mtddev); - if (!spectra_mtd) { - printk(KERN_ERR "Failed to obtain MTD device #%d\n", mtddev); - return FAIL; - } - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: mtd_Flash_Release -* Inputs: none -* Outputs: PASS=0 (notice 0=ok here) -* Description: Releases the flash. -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -int mtd_Flash_Release(void) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - if (!spectra_mtd) - return PASS; - - put_mtd_device(spectra_mtd); - spectra_mtd = NULL; - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: mtd_Read_Device_ID -* Inputs: none -* Outputs: PASS=1 FAIL=0 -* Description: Reads the info from the controller registers. -* Sets up DeviceInfo structure with device parameters -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ - -u16 mtd_Read_Device_ID(void) -{ - uint64_t tmp; - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (!spectra_mtd) - return FAIL; - - DeviceInfo.wDeviceMaker = 0; - DeviceInfo.wDeviceType = 8; - DeviceInfo.wSpectraStartBlock = SPECTRA_START_BLOCK; - tmp = spectra_mtd->size; - do_div(tmp, spectra_mtd->erasesize); - DeviceInfo.wTotalBlocks = tmp; - DeviceInfo.wSpectraEndBlock = DeviceInfo.wTotalBlocks - 1; - DeviceInfo.wPagesPerBlock = spectra_mtd->erasesize / spectra_mtd->writesize; - DeviceInfo.wPageSize = spectra_mtd->writesize + spectra_mtd->oobsize; - DeviceInfo.wPageDataSize = spectra_mtd->writesize; - DeviceInfo.wPageSpareSize = spectra_mtd->oobsize; - DeviceInfo.wBlockSize = DeviceInfo.wPageSize * DeviceInfo.wPagesPerBlock; - DeviceInfo.wBlockDataSize = DeviceInfo.wPageDataSize * DeviceInfo.wPagesPerBlock; - DeviceInfo.wDataBlockNum = (u32) (DeviceInfo.wSpectraEndBlock - - DeviceInfo.wSpectraStartBlock - + 1); - DeviceInfo.MLCDevice = 0;//spectra_mtd->celltype & NAND_CI_CELLTYPE_MSK; - DeviceInfo.nBitsInPageNumber = - (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPagesPerBlock); - DeviceInfo.nBitsInPageDataSize = - (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPageDataSize); - DeviceInfo.nBitsInBlockDataSize = - (u8)GLOB_Calc_Used_Bits(DeviceInfo.wBlockDataSize); - -#if CMD_DMA - totalUsedBanks = 4; - valid_banks[0] = 1; - valid_banks[1] = 1; - valid_banks[2] = 1; - valid_banks[3] = 1; -#endif - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: mtd_Flash_Reset -* Inputs: none -* Outputs: PASS=0 (notice 0=ok here) -* Description: Reset the flash -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 mtd_Flash_Reset(void) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - return PASS; -} - -void erase_callback(struct erase_info *e) -{ - complete((void *)e->priv); -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: mtd_Erase_Block -* Inputs: Address -* Outputs: PASS=0 (notice 0=ok here) -* Description: Erase a block -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 mtd_Erase_Block(u32 block_add) -{ - struct erase_info erase; - DECLARE_COMPLETION_ONSTACK(comp); - int ret; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (block_add >= DeviceInfo.wTotalBlocks) { - printk(KERN_ERR "mtd_Erase_Block error! " - "Too big block address: %d\n", block_add); - return FAIL; - } - - nand_dbg_print(NAND_DBG_DEBUG, "Erasing block %d\n", - (int)block_add); - - erase.mtd = spectra_mtd; - erase.callback = erase_callback; - erase.addr = block_add * spectra_mtd->erasesize; - erase.len = spectra_mtd->erasesize; - erase.priv = (unsigned long)∁ - - ret = spectra_mtd->erase(spectra_mtd, &erase); - if (!ret) { - wait_for_completion(&comp); - if (erase.state != MTD_ERASE_DONE) - ret = -EIO; - } - if (ret) { - printk(KERN_WARNING "mtd_Erase_Block error! " - "erase of region [0x%llx, 0x%llx] failed\n", - erase.addr, erase.len); - return FAIL; - } - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: mtd_Write_Page_Main -* Inputs: Write buffer address pointer -* Block number -* Page number -* Number of pages to process -* Outputs: PASS=0 (notice 0=ok here) -* Description: Write the data in the buffer to main area of flash -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 mtd_Write_Page_Main(u8 *write_data, u32 Block, - u16 Page, u16 PageCount) -{ - size_t retlen; - int ret = 0; - - if (Block >= DeviceInfo.wTotalBlocks) - return FAIL; - - if (Page + PageCount > DeviceInfo.wPagesPerBlock) - return FAIL; - - nand_dbg_print(NAND_DBG_DEBUG, "mtd_Write_Page_Main: " - "lba %u Page %u PageCount %u\n", - (unsigned int)Block, - (unsigned int)Page, (unsigned int)PageCount); - - - while (PageCount) { - ret = spectra_mtd->write(spectra_mtd, - (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize), - DeviceInfo.wPageDataSize, &retlen, write_data); - if (ret) { - printk(KERN_ERR "%s failed %d\n", __func__, ret); - return FAIL; - } - write_data += DeviceInfo.wPageDataSize; - Page++; - PageCount--; - } - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: mtd_Read_Page_Main -* Inputs: Read buffer address pointer -* Block number -* Page number -* Number of pages to process -* Outputs: PASS=0 (notice 0=ok here) -* Description: Read the data from the flash main area to the buffer -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 mtd_Read_Page_Main(u8 *read_data, u32 Block, - u16 Page, u16 PageCount) -{ - size_t retlen; - int ret = 0; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (Block >= DeviceInfo.wTotalBlocks) - return FAIL; - - if (Page + PageCount > DeviceInfo.wPagesPerBlock) - return FAIL; - - nand_dbg_print(NAND_DBG_DEBUG, "mtd_Read_Page_Main: " - "lba %u Page %u PageCount %u\n", - (unsigned int)Block, - (unsigned int)Page, (unsigned int)PageCount); - - - while (PageCount) { - ret = spectra_mtd->read(spectra_mtd, - (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize), - DeviceInfo.wPageDataSize, &retlen, read_data); - if (ret) { - printk(KERN_ERR "%s failed %d\n", __func__, ret); - return FAIL; - } - read_data += DeviceInfo.wPageDataSize; - Page++; - PageCount--; - } - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - return PASS; -} - -#ifndef ELDORA -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: mtd_Read_Page_Main_Spare -* Inputs: Write Buffer -* Address -* Buffer size -* Outputs: PASS=0 (notice 0=ok here) -* Description: Read from flash main+spare area -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 mtd_Read_Page_Main_Spare(u8 *read_data, u32 Block, - u16 Page, u16 PageCount) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (Block >= DeviceInfo.wTotalBlocks) { - printk(KERN_ERR "Read Page Main+Spare " - "Error: Block Address too big\n"); - return FAIL; - } - - if (Page + PageCount > DeviceInfo.wPagesPerBlock) { - printk(KERN_ERR "Read Page Main+Spare " - "Error: Page number %d+%d too big in block %d\n", - Page, PageCount, Block); - return FAIL; - } - - nand_dbg_print(NAND_DBG_DEBUG, "Read Page Main + Spare - " - "No. of pages %u block %u start page %u\n", - (unsigned int)PageCount, - (unsigned int)Block, (unsigned int)Page); - - - while (PageCount) { - struct mtd_oob_ops ops; - int ret; - - ops.mode = MTD_OPS_AUTO_OOB; - ops.datbuf = read_data; - ops.len = DeviceInfo.wPageDataSize; - ops.oobbuf = read_data + DeviceInfo.wPageDataSize + BTSIG_OFFSET; - ops.ooblen = BTSIG_BYTES; - ops.ooboffs = 0; - - ret = spectra_mtd->read_oob(spectra_mtd, - (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize), - &ops); - if (ret) { - printk(KERN_ERR "%s failed %d\n", __func__, ret); - return FAIL; - } - read_data += DeviceInfo.wPageSize; - Page++; - PageCount--; - } - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: mtd_Write_Page_Main_Spare -* Inputs: Write buffer -* address -* buffer length -* Outputs: PASS=0 (notice 0=ok here) -* Description: Write the buffer to main+spare area of flash -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 mtd_Write_Page_Main_Spare(u8 *write_data, u32 Block, - u16 Page, u16 page_count) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (Block >= DeviceInfo.wTotalBlocks) { - printk(KERN_ERR "Write Page Main + Spare " - "Error: Block Address too big\n"); - return FAIL; - } - - if (Page + page_count > DeviceInfo.wPagesPerBlock) { - printk(KERN_ERR "Write Page Main + Spare " - "Error: Page number %d+%d too big in block %d\n", - Page, page_count, Block); - WARN_ON(1); - return FAIL; - } - - nand_dbg_print(NAND_DBG_DEBUG, "Write Page Main+Spare - " - "No. of pages %u block %u start page %u\n", - (unsigned int)page_count, - (unsigned int)Block, (unsigned int)Page); - - while (page_count) { - struct mtd_oob_ops ops; - int ret; - - ops.mode = MTD_OPS_AUTO_OOB; - ops.datbuf = write_data; - ops.len = DeviceInfo.wPageDataSize; - ops.oobbuf = write_data + DeviceInfo.wPageDataSize + BTSIG_OFFSET; - ops.ooblen = BTSIG_BYTES; - ops.ooboffs = 0; - - ret = spectra_mtd->write_oob(spectra_mtd, - (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize), - &ops); - if (ret) { - printk(KERN_ERR "%s failed %d\n", __func__, ret); - return FAIL; - } - write_data += DeviceInfo.wPageSize; - Page++; - page_count--; - } - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: mtd_Write_Page_Spare -* Inputs: Write buffer -* Address -* buffer size -* Outputs: PASS=0 (notice 0=ok here) -* Description: Write the buffer in the spare area -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 mtd_Write_Page_Spare(u8 *write_data, u32 Block, - u16 Page, u16 PageCount) -{ - WARN_ON(1); - return FAIL; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: mtd_Read_Page_Spare -* Inputs: Write Buffer -* Address -* Buffer size -* Outputs: PASS=0 (notice 0=ok here) -* Description: Read data from the spare area -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 mtd_Read_Page_Spare(u8 *read_data, u32 Block, - u16 Page, u16 PageCount) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (Block >= DeviceInfo.wTotalBlocks) { - printk(KERN_ERR "Read Page Spare " - "Error: Block Address too big\n"); - return FAIL; - } - - if (Page + PageCount > DeviceInfo.wPagesPerBlock) { - printk(KERN_ERR "Read Page Spare " - "Error: Page number too big\n"); - return FAIL; - } - - nand_dbg_print(NAND_DBG_DEBUG, "Read Page Spare- " - "block %u page %u (%u pages)\n", - (unsigned int)Block, (unsigned int)Page, PageCount); - - while (PageCount) { - struct mtd_oob_ops ops; - int ret; - - ops.mode = MTD_OPS_AUTO_OOB; - ops.datbuf = NULL; - ops.len = 0; - ops.oobbuf = read_data; - ops.ooblen = BTSIG_BYTES; - ops.ooboffs = 0; - - ret = spectra_mtd->read_oob(spectra_mtd, - (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize), - &ops); - if (ret) { - printk(KERN_ERR "%s failed %d\n", __func__, ret); - return FAIL; - } - - read_data += DeviceInfo.wPageSize; - Page++; - PageCount--; - } - - return PASS; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: mtd_Enable_Disable_Interrupts -* Inputs: enable or disable -* Outputs: none -* Description: NOP -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -void mtd_Enable_Disable_Interrupts(u16 INT_ENABLE) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); -} - -u16 mtd_Get_Bad_Block(u32 block) -{ - return 0; -} - -#if CMD_DMA -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Support for CDMA functions -************************************ -* mtd_CDMA_Flash_Init -* CDMA_process_data command (use LLD_CDMA) -* CDMA_MemCopy_CMD (use LLD_CDMA) -* mtd_CDMA_execute all commands -* mtd_CDMA_Event_Status -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 mtd_CDMA_Flash_Init(void) -{ - u16 i; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - for (i = 0; i < MAX_DESCS + MAX_CHANS; i++) { - PendingCMD[i].CMD = 0; - PendingCMD[i].Tag = 0; - PendingCMD[i].DataAddr = 0; - PendingCMD[i].Block = 0; - PendingCMD[i].Page = 0; - PendingCMD[i].PageCount = 0; - PendingCMD[i].DataDestAddr = 0; - PendingCMD[i].DataSrcAddr = 0; - PendingCMD[i].MemCopyByteCnt = 0; - PendingCMD[i].ChanSync[0] = 0; - PendingCMD[i].ChanSync[1] = 0; - PendingCMD[i].ChanSync[2] = 0; - PendingCMD[i].ChanSync[3] = 0; - PendingCMD[i].ChanSync[4] = 0; - PendingCMD[i].Status = 3; - } - - return PASS; -} - -static void mtd_isr(int irq, void *dev_id) -{ - /* TODO: ... */ -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: CDMA_Execute_CMDs -* Inputs: tag_count: the number of pending cmds to do -* Outputs: PASS/FAIL -* Description: execute each command in the pending CMD array -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 mtd_CDMA_Execute_CMDs(u16 tag_count) -{ - u16 i, j; - u8 CMD; /* cmd parameter */ - u8 *data; - u32 block; - u16 page; - u16 count; - u16 status = PASS; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - nand_dbg_print(NAND_DBG_TRACE, "At start of Execute CMDs: " - "Tag Count %u\n", tag_count); - - for (i = 0; i < totalUsedBanks; i++) { - PendingCMD[i].CMD = DUMMY_CMD; - PendingCMD[i].Tag = 0xFF; - PendingCMD[i].Block = - (DeviceInfo.wTotalBlocks / totalUsedBanks) * i; - - for (j = 0; j <= MAX_CHANS; j++) - PendingCMD[i].ChanSync[j] = 0; - } - - CDMA_Execute_CMDs(tag_count); - -#ifdef VERBOSE - print_pending_cmds(tag_count); -#endif -#if DEBUG_SYNC - } - debug_sync_cnt++; -#endif - - for (i = MAX_CHANS; - i < tag_count + MAX_CHANS; i++) { - CMD = PendingCMD[i].CMD; - data = PendingCMD[i].DataAddr; - block = PendingCMD[i].Block; - page = PendingCMD[i].Page; - count = PendingCMD[i].PageCount; - - switch (CMD) { - case ERASE_CMD: - mtd_Erase_Block(block); - PendingCMD[i].Status = PASS; - break; - case WRITE_MAIN_CMD: - mtd_Write_Page_Main(data, block, page, count); - PendingCMD[i].Status = PASS; - break; - case WRITE_MAIN_SPARE_CMD: - mtd_Write_Page_Main_Spare(data, block, page, count); - PendingCMD[i].Status = PASS; - break; - case READ_MAIN_CMD: - mtd_Read_Page_Main(data, block, page, count); - PendingCMD[i].Status = PASS; - break; - case MEMCOPY_CMD: - memcpy(PendingCMD[i].DataDestAddr, - PendingCMD[i].DataSrcAddr, - PendingCMD[i].MemCopyByteCnt); - case DUMMY_CMD: - PendingCMD[i].Status = PASS; - break; - default: - PendingCMD[i].Status = FAIL; - break; - } - } - - /* - * Temperory adding code to reset PendingCMD array for basic testing. - * It should be done at the end of event status function. - */ - for (i = tag_count + MAX_CHANS; i < MAX_DESCS; i++) { - PendingCMD[i].CMD = 0; - PendingCMD[i].Tag = 0; - PendingCMD[i].DataAddr = 0; - PendingCMD[i].Block = 0; - PendingCMD[i].Page = 0; - PendingCMD[i].PageCount = 0; - PendingCMD[i].DataDestAddr = 0; - PendingCMD[i].DataSrcAddr = 0; - PendingCMD[i].MemCopyByteCnt = 0; - PendingCMD[i].ChanSync[0] = 0; - PendingCMD[i].ChanSync[1] = 0; - PendingCMD[i].ChanSync[2] = 0; - PendingCMD[i].ChanSync[3] = 0; - PendingCMD[i].ChanSync[4] = 0; - PendingCMD[i].Status = CMD_NOT_DONE; - } - - nand_dbg_print(NAND_DBG_TRACE, "At end of Execute CMDs.\n"); - - mtd_isr(0, 0); /* This is a null isr now. Need fill it in future */ - - return status; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: mtd_Event_Status -* Inputs: none -* Outputs: Event_Status code -* Description: This function can also be used to force errors -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -u16 mtd_CDMA_Event_Status(void) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - return EVENT_PASS; -} - -#endif /* CMD_DMA */ -#endif /* !ELDORA */ diff --git a/drivers/staging/spectra/lld_mtd.h b/drivers/staging/spectra/lld_mtd.h deleted file mode 100644 index 4e81ee87b53d..000000000000 --- a/drivers/staging/spectra/lld_mtd.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef _LLD_MTD_ -#define _LLD_MTD_ - -#include "ffsport.h" -#include "ffsdefs.h" - -/* prototypes: MTD API functions */ -extern u16 mtd_Flash_Reset(void); -extern u16 mtd_Flash_Init(void); -extern int mtd_Flash_Release(void); -extern u16 mtd_Read_Device_ID(void); -extern u16 mtd_Erase_Block(u32 block_addr); -extern u16 mtd_Write_Page_Main(u8 *write_data, u32 Block, - u16 Page, u16 PageCount); -extern u16 mtd_Read_Page_Main(u8 *read_data, u32 Block, u16 Page, - u16 PageCount); -extern u16 mtd_Event_Status(void); -extern void mtd_Enable_Disable_Interrupts(u16 INT_ENABLE); -extern u16 mtd_Write_Page_Main_Spare(u8 *write_data, u32 Block, - u16 Page, u16 PageCount); -extern u16 mtd_Write_Page_Spare(u8 *write_data, u32 Block, - u16 Page, u16 PageCount); -extern u16 mtd_Read_Page_Main_Spare(u8 *read_data, u32 Block, - u16 Page, u16 PageCount); -extern u16 mtd_Read_Page_Spare(u8 *read_data, u32 Block, u16 Page, - u16 PageCount); -extern u16 mtd_Get_Bad_Block(u32 block); - -u16 mtd_CDMA_Flash_Init(void); -u16 mtd_CDMA_Execute_CMDs(u16 tag_count); -u16 mtd_CDMA_Event_Status(void); -#endif /*_LLD_MTD_*/ diff --git a/drivers/staging/spectra/lld_nand.c b/drivers/staging/spectra/lld_nand.c deleted file mode 100644 index 60a14ff26c7f..000000000000 --- a/drivers/staging/spectra/lld_nand.c +++ /dev/null @@ -1,2619 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include "lld.h" -#include "lld_nand.h" -#include "lld_cdma.h" - -#include "spectraswconfig.h" -#include "flash.h" -#include "ffsdefs.h" - -#include -#include -#include -#include - -#include "nand_regs.h" - -#define SPECTRA_NAND_NAME "nd" - -#define CEIL_DIV(X, Y) (((X)%(Y)) ? ((X)/(Y)+1) : ((X)/(Y))) -#define MAX_PAGES_PER_RW 128 - -#define INT_IDLE_STATE 0 -#define INT_READ_PAGE_MAIN 0x01 -#define INT_WRITE_PAGE_MAIN 0x02 -#define INT_PIPELINE_READ_AHEAD 0x04 -#define INT_PIPELINE_WRITE_AHEAD 0x08 -#define INT_MULTI_PLANE_READ 0x10 -#define INT_MULTI_PLANE_WRITE 0x11 - -static u32 enable_ecc; - -struct mrst_nand_info info; - -int totalUsedBanks; -u32 GLOB_valid_banks[LLD_MAX_FLASH_BANKS]; - -void __iomem *FlashReg; -void __iomem *FlashMem; - -u16 conf_parameters[] = { - 0x0000, - 0x0000, - 0x01F4, - 0x01F4, - 0x01F4, - 0x01F4, - 0x0000, - 0x0000, - 0x0001, - 0x0000, - 0x0000, - 0x0000, - 0x0000, - 0x0040, - 0x0001, - 0x000A, - 0x000A, - 0x000A, - 0x0000, - 0x0000, - 0x0005, - 0x0012, - 0x000C -}; - -u16 NAND_Get_Bad_Block(u32 block) -{ - u32 status = PASS; - u32 flag_bytes = 0; - u32 skip_bytes = DeviceInfo.wSpareSkipBytes; - u32 page, i; - u8 *pReadSpareBuf = buf_get_bad_block; - - if (enable_ecc) - flag_bytes = DeviceInfo.wNumPageSpareFlag; - - for (page = 0; page < 2; page++) { - status = NAND_Read_Page_Spare(pReadSpareBuf, block, page, 1); - if (status != PASS) - return READ_ERROR; - for (i = flag_bytes; i < (flag_bytes + skip_bytes); i++) - if (pReadSpareBuf[i] != 0xff) - return DEFECTIVE_BLOCK; - } - - for (page = 1; page < 3; page++) { - status = NAND_Read_Page_Spare(pReadSpareBuf, block, - DeviceInfo.wPagesPerBlock - page , 1); - if (status != PASS) - return READ_ERROR; - for (i = flag_bytes; i < (flag_bytes + skip_bytes); i++) - if (pReadSpareBuf[i] != 0xff) - return DEFECTIVE_BLOCK; - } - - return GOOD_BLOCK; -} - - -u16 NAND_Flash_Reset(void) -{ - u32 i; - u32 intr_status_rst_comp[4] = {INTR_STATUS0__RST_COMP, - INTR_STATUS1__RST_COMP, - INTR_STATUS2__RST_COMP, - INTR_STATUS3__RST_COMP}; - u32 intr_status_time_out[4] = {INTR_STATUS0__TIME_OUT, - INTR_STATUS1__TIME_OUT, - INTR_STATUS2__TIME_OUT, - INTR_STATUS3__TIME_OUT}; - u32 intr_status[4] = {INTR_STATUS0, INTR_STATUS1, - INTR_STATUS2, INTR_STATUS3}; - u32 device_reset_banks[4] = {DEVICE_RESET__BANK0, - DEVICE_RESET__BANK1, - DEVICE_RESET__BANK2, - DEVICE_RESET__BANK3}; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++) - iowrite32(intr_status_rst_comp[i] | intr_status_time_out[i], - FlashReg + intr_status[i]); - - for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++) { - iowrite32(device_reset_banks[i], FlashReg + DEVICE_RESET); - while (!(ioread32(FlashReg + intr_status[i]) & - (intr_status_rst_comp[i] | intr_status_time_out[i]))) - ; - if (ioread32(FlashReg + intr_status[i]) & - intr_status_time_out[i]) - nand_dbg_print(NAND_DBG_WARN, - "NAND Reset operation timed out on bank %d\n", i); - } - - for (i = 0; i < LLD_MAX_FLASH_BANKS; i++) - iowrite32(intr_status_rst_comp[i] | intr_status_time_out[i], - FlashReg + intr_status[i]); - - return PASS; -} - -static void NAND_ONFi_Timing_Mode(u16 mode) -{ - u16 Trea[6] = {40, 30, 25, 20, 20, 16}; - u16 Trp[6] = {50, 25, 17, 15, 12, 10}; - u16 Treh[6] = {30, 15, 15, 10, 10, 7}; - u16 Trc[6] = {100, 50, 35, 30, 25, 20}; - u16 Trhoh[6] = {0, 15, 15, 15, 15, 15}; - u16 Trloh[6] = {0, 0, 0, 0, 5, 5}; - u16 Tcea[6] = {100, 45, 30, 25, 25, 25}; - u16 Tadl[6] = {200, 100, 100, 100, 70, 70}; - u16 Trhw[6] = {200, 100, 100, 100, 100, 100}; - u16 Trhz[6] = {200, 100, 100, 100, 100, 100}; - u16 Twhr[6] = {120, 80, 80, 60, 60, 60}; - u16 Tcs[6] = {70, 35, 25, 25, 20, 15}; - - u16 TclsRising = 1; - u16 data_invalid_rhoh, data_invalid_rloh, data_invalid; - u16 dv_window = 0; - u16 en_lo, en_hi; - u16 acc_clks; - u16 addr_2_data, re_2_we, re_2_re, we_2_re, cs_cnt; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - en_lo = CEIL_DIV(Trp[mode], CLK_X); - en_hi = CEIL_DIV(Treh[mode], CLK_X); - -#if ONFI_BLOOM_TIME - if ((en_hi * CLK_X) < (Treh[mode] + 2)) - en_hi++; -#endif - - if ((en_lo + en_hi) * CLK_X < Trc[mode]) - en_lo += CEIL_DIV((Trc[mode] - (en_lo + en_hi) * CLK_X), CLK_X); - - if ((en_lo + en_hi) < CLK_MULTI) - en_lo += CLK_MULTI - en_lo - en_hi; - - while (dv_window < 8) { - data_invalid_rhoh = en_lo * CLK_X + Trhoh[mode]; - - data_invalid_rloh = (en_lo + en_hi) * CLK_X + Trloh[mode]; - - data_invalid = - data_invalid_rhoh < - data_invalid_rloh ? data_invalid_rhoh : data_invalid_rloh; - - dv_window = data_invalid - Trea[mode]; - - if (dv_window < 8) - en_lo++; - } - - acc_clks = CEIL_DIV(Trea[mode], CLK_X); - - while (((acc_clks * CLK_X) - Trea[mode]) < 3) - acc_clks++; - - if ((data_invalid - acc_clks * CLK_X) < 2) - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d: Warning!\n", - __FILE__, __LINE__); - - addr_2_data = CEIL_DIV(Tadl[mode], CLK_X); - re_2_we = CEIL_DIV(Trhw[mode], CLK_X); - re_2_re = CEIL_DIV(Trhz[mode], CLK_X); - we_2_re = CEIL_DIV(Twhr[mode], CLK_X); - cs_cnt = CEIL_DIV((Tcs[mode] - Trp[mode]), CLK_X); - if (!TclsRising) - cs_cnt = CEIL_DIV(Tcs[mode], CLK_X); - if (cs_cnt == 0) - cs_cnt = 1; - - if (Tcea[mode]) { - while (((cs_cnt * CLK_X) + Trea[mode]) < Tcea[mode]) - cs_cnt++; - } - -#if MODE5_WORKAROUND - if (mode == 5) - acc_clks = 5; -#endif - - /* Sighting 3462430: Temporary hack for MT29F128G08CJABAWP:B */ - if ((ioread32(FlashReg + MANUFACTURER_ID) == 0) && - (ioread32(FlashReg + DEVICE_ID) == 0x88)) - acc_clks = 6; - - iowrite32(acc_clks, FlashReg + ACC_CLKS); - iowrite32(re_2_we, FlashReg + RE_2_WE); - iowrite32(re_2_re, FlashReg + RE_2_RE); - iowrite32(we_2_re, FlashReg + WE_2_RE); - iowrite32(addr_2_data, FlashReg + ADDR_2_DATA); - iowrite32(en_lo, FlashReg + RDWR_EN_LO_CNT); - iowrite32(en_hi, FlashReg + RDWR_EN_HI_CNT); - iowrite32(cs_cnt, FlashReg + CS_SETUP_CNT); -} - -static void index_addr(u32 address, u32 data) -{ - iowrite32(address, FlashMem); - iowrite32(data, FlashMem + 0x10); -} - -static void index_addr_read_data(u32 address, u32 *pdata) -{ - iowrite32(address, FlashMem); - *pdata = ioread32(FlashMem + 0x10); -} - -static void set_ecc_config(void) -{ -#if SUPPORT_8BITECC - if ((ioread32(FlashReg + DEVICE_MAIN_AREA_SIZE) < 4096) || - (ioread32(FlashReg + DEVICE_SPARE_AREA_SIZE) <= 128)) - iowrite32(8, FlashReg + ECC_CORRECTION); -#endif - - if ((ioread32(FlashReg + ECC_CORRECTION) & ECC_CORRECTION__VALUE) - == 1) { - DeviceInfo.wECCBytesPerSector = 4; - DeviceInfo.wECCBytesPerSector *= DeviceInfo.wDevicesConnected; - DeviceInfo.wNumPageSpareFlag = - DeviceInfo.wPageSpareSize - - DeviceInfo.wPageDataSize / - (ECC_SECTOR_SIZE * DeviceInfo.wDevicesConnected) * - DeviceInfo.wECCBytesPerSector - - DeviceInfo.wSpareSkipBytes; - } else { - DeviceInfo.wECCBytesPerSector = - (ioread32(FlashReg + ECC_CORRECTION) & - ECC_CORRECTION__VALUE) * 13 / 8; - if ((DeviceInfo.wECCBytesPerSector) % 2 == 0) - DeviceInfo.wECCBytesPerSector += 2; - else - DeviceInfo.wECCBytesPerSector += 1; - - DeviceInfo.wECCBytesPerSector *= DeviceInfo.wDevicesConnected; - DeviceInfo.wNumPageSpareFlag = DeviceInfo.wPageSpareSize - - DeviceInfo.wPageDataSize / - (ECC_SECTOR_SIZE * DeviceInfo.wDevicesConnected) * - DeviceInfo.wECCBytesPerSector - - DeviceInfo.wSpareSkipBytes; - } -} - -static u16 get_onfi_nand_para(void) -{ - int i; - u16 blks_lun_l, blks_lun_h, n_of_luns; - u32 blockperlun, id; - - iowrite32(DEVICE_RESET__BANK0, FlashReg + DEVICE_RESET); - - while (!((ioread32(FlashReg + INTR_STATUS0) & - INTR_STATUS0__RST_COMP) | - (ioread32(FlashReg + INTR_STATUS0) & - INTR_STATUS0__TIME_OUT))) - ; - - if (ioread32(FlashReg + INTR_STATUS0) & INTR_STATUS0__RST_COMP) { - iowrite32(DEVICE_RESET__BANK1, FlashReg + DEVICE_RESET); - while (!((ioread32(FlashReg + INTR_STATUS1) & - INTR_STATUS1__RST_COMP) | - (ioread32(FlashReg + INTR_STATUS1) & - INTR_STATUS1__TIME_OUT))) - ; - - if (ioread32(FlashReg + INTR_STATUS1) & - INTR_STATUS1__RST_COMP) { - iowrite32(DEVICE_RESET__BANK2, - FlashReg + DEVICE_RESET); - while (!((ioread32(FlashReg + INTR_STATUS2) & - INTR_STATUS2__RST_COMP) | - (ioread32(FlashReg + INTR_STATUS2) & - INTR_STATUS2__TIME_OUT))) - ; - - if (ioread32(FlashReg + INTR_STATUS2) & - INTR_STATUS2__RST_COMP) { - iowrite32(DEVICE_RESET__BANK3, - FlashReg + DEVICE_RESET); - while (!((ioread32(FlashReg + INTR_STATUS3) & - INTR_STATUS3__RST_COMP) | - (ioread32(FlashReg + INTR_STATUS3) & - INTR_STATUS3__TIME_OUT))) - ; - } else { - printk(KERN_ERR "Getting a time out for bank 2!\n"); - } - } else { - printk(KERN_ERR "Getting a time out for bank 1!\n"); - } - } - - iowrite32(INTR_STATUS0__TIME_OUT, FlashReg + INTR_STATUS0); - iowrite32(INTR_STATUS1__TIME_OUT, FlashReg + INTR_STATUS1); - iowrite32(INTR_STATUS2__TIME_OUT, FlashReg + INTR_STATUS2); - iowrite32(INTR_STATUS3__TIME_OUT, FlashReg + INTR_STATUS3); - - DeviceInfo.wONFIDevFeatures = - ioread32(FlashReg + ONFI_DEVICE_FEATURES); - DeviceInfo.wONFIOptCommands = - ioread32(FlashReg + ONFI_OPTIONAL_COMMANDS); - DeviceInfo.wONFITimingMode = - ioread32(FlashReg + ONFI_TIMING_MODE); - DeviceInfo.wONFIPgmCacheTimingMode = - ioread32(FlashReg + ONFI_PGM_CACHE_TIMING_MODE); - - n_of_luns = ioread32(FlashReg + ONFI_DEVICE_NO_OF_LUNS) & - ONFI_DEVICE_NO_OF_LUNS__NO_OF_LUNS; - blks_lun_l = ioread32(FlashReg + ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_L); - blks_lun_h = ioread32(FlashReg + ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_U); - - blockperlun = (blks_lun_h << 16) | blks_lun_l; - - DeviceInfo.wTotalBlocks = n_of_luns * blockperlun; - - if (!(ioread32(FlashReg + ONFI_TIMING_MODE) & - ONFI_TIMING_MODE__VALUE)) - return FAIL; - - for (i = 5; i > 0; i--) { - if (ioread32(FlashReg + ONFI_TIMING_MODE) & (0x01 << i)) - break; - } - - NAND_ONFi_Timing_Mode(i); - - index_addr(MODE_11 | 0, 0x90); - index_addr(MODE_11 | 1, 0); - - for (i = 0; i < 3; i++) - index_addr_read_data(MODE_11 | 2, &id); - - nand_dbg_print(NAND_DBG_DEBUG, "3rd ID: 0x%x\n", id); - - DeviceInfo.MLCDevice = id & 0x0C; - - /* By now, all the ONFI devices we know support the page cache */ - /* rw feature. So here we enable the pipeline_rw_ahead feature */ - /* iowrite32(1, FlashReg + CACHE_WRITE_ENABLE); */ - /* iowrite32(1, FlashReg + CACHE_READ_ENABLE); */ - - return PASS; -} - -static void get_samsung_nand_para(void) -{ - u8 no_of_planes; - u32 blk_size; - u64 plane_size, capacity; - u32 id_bytes[5]; - int i; - - index_addr((u32)(MODE_11 | 0), 0x90); - index_addr((u32)(MODE_11 | 1), 0); - for (i = 0; i < 5; i++) - index_addr_read_data((u32)(MODE_11 | 2), &id_bytes[i]); - - nand_dbg_print(NAND_DBG_DEBUG, - "ID bytes: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", - id_bytes[0], id_bytes[1], id_bytes[2], - id_bytes[3], id_bytes[4]); - - if ((id_bytes[1] & 0xff) == 0xd3) { /* Samsung K9WAG08U1A */ - /* Set timing register values according to datasheet */ - iowrite32(5, FlashReg + ACC_CLKS); - iowrite32(20, FlashReg + RE_2_WE); - iowrite32(12, FlashReg + WE_2_RE); - iowrite32(14, FlashReg + ADDR_2_DATA); - iowrite32(3, FlashReg + RDWR_EN_LO_CNT); - iowrite32(2, FlashReg + RDWR_EN_HI_CNT); - iowrite32(2, FlashReg + CS_SETUP_CNT); - } - - no_of_planes = 1 << ((id_bytes[4] & 0x0c) >> 2); - plane_size = (u64)64 << ((id_bytes[4] & 0x70) >> 4); - blk_size = 64 << ((ioread32(FlashReg + DEVICE_PARAM_1) & 0x30) >> 4); - capacity = (u64)128 * plane_size * no_of_planes; - - DeviceInfo.wTotalBlocks = (u32)GLOB_u64_Div(capacity, blk_size); -} - -static void get_toshiba_nand_para(void) -{ - void __iomem *scratch_reg; - u32 tmp; - - /* Workaround to fix a controller bug which reports a wrong */ - /* spare area size for some kind of Toshiba NAND device */ - if ((ioread32(FlashReg + DEVICE_MAIN_AREA_SIZE) == 4096) && - (ioread32(FlashReg + DEVICE_SPARE_AREA_SIZE) == 64)) { - iowrite32(216, FlashReg + DEVICE_SPARE_AREA_SIZE); - tmp = ioread32(FlashReg + DEVICES_CONNECTED) * - ioread32(FlashReg + DEVICE_SPARE_AREA_SIZE); - iowrite32(tmp, FlashReg + LOGICAL_PAGE_SPARE_SIZE); -#if SUPPORT_15BITECC - iowrite32(15, FlashReg + ECC_CORRECTION); -#elif SUPPORT_8BITECC - iowrite32(8, FlashReg + ECC_CORRECTION); -#endif - } - - /* As Toshiba NAND can not provide it's block number, */ - /* so here we need user to provide the correct block */ - /* number in a scratch register before the Linux NAND */ - /* driver is loaded. If no valid value found in the scratch */ - /* register, then we use default block number value */ - scratch_reg = ioremap_nocache(SCRATCH_REG_ADDR, SCRATCH_REG_SIZE); - if (!scratch_reg) { - printk(KERN_ERR "Spectra: ioremap failed in %s, Line %d", - __FILE__, __LINE__); - DeviceInfo.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; - } else { - nand_dbg_print(NAND_DBG_WARN, - "Spectra: ioremap reg address: 0x%p\n", scratch_reg); - DeviceInfo.wTotalBlocks = 1 << ioread8(scratch_reg); - if (DeviceInfo.wTotalBlocks < 512) - DeviceInfo.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; - iounmap(scratch_reg); - } -} - -static void get_hynix_nand_para(void) -{ - void __iomem *scratch_reg; - u32 main_size, spare_size; - - switch (DeviceInfo.wDeviceID) { - case 0xD5: /* Hynix H27UAG8T2A, H27UBG8U5A or H27UCG8VFA */ - case 0xD7: /* Hynix H27UDG8VEM, H27UCG8UDM or H27UCG8V5A */ - iowrite32(128, FlashReg + PAGES_PER_BLOCK); - iowrite32(4096, FlashReg + DEVICE_MAIN_AREA_SIZE); - iowrite32(224, FlashReg + DEVICE_SPARE_AREA_SIZE); - main_size = 4096 * ioread32(FlashReg + DEVICES_CONNECTED); - spare_size = 224 * ioread32(FlashReg + DEVICES_CONNECTED); - iowrite32(main_size, FlashReg + LOGICAL_PAGE_DATA_SIZE); - iowrite32(spare_size, FlashReg + LOGICAL_PAGE_SPARE_SIZE); - iowrite32(0, FlashReg + DEVICE_WIDTH); -#if SUPPORT_15BITECC - iowrite32(15, FlashReg + ECC_CORRECTION); -#elif SUPPORT_8BITECC - iowrite32(8, FlashReg + ECC_CORRECTION); -#endif - DeviceInfo.MLCDevice = 1; - break; - default: - nand_dbg_print(NAND_DBG_WARN, - "Spectra: Unknown Hynix NAND (Device ID: 0x%x)." - "Will use default parameter values instead.\n", - DeviceInfo.wDeviceID); - } - - scratch_reg = ioremap_nocache(SCRATCH_REG_ADDR, SCRATCH_REG_SIZE); - if (!scratch_reg) { - printk(KERN_ERR "Spectra: ioremap failed in %s, Line %d", - __FILE__, __LINE__); - DeviceInfo.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; - } else { - nand_dbg_print(NAND_DBG_WARN, - "Spectra: ioremap reg address: 0x%p\n", scratch_reg); - DeviceInfo.wTotalBlocks = 1 << ioread8(scratch_reg); - if (DeviceInfo.wTotalBlocks < 512) - DeviceInfo.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; - iounmap(scratch_reg); - } -} - -static void find_valid_banks(void) -{ - u32 id[LLD_MAX_FLASH_BANKS]; - int i; - - totalUsedBanks = 0; - for (i = 0; i < LLD_MAX_FLASH_BANKS; i++) { - index_addr((u32)(MODE_11 | (i << 24) | 0), 0x90); - index_addr((u32)(MODE_11 | (i << 24) | 1), 0); - index_addr_read_data((u32)(MODE_11 | (i << 24) | 2), &id[i]); - - nand_dbg_print(NAND_DBG_DEBUG, - "Return 1st ID for bank[%d]: %x\n", i, id[i]); - - if (i == 0) { - if (id[i] & 0x0ff) - GLOB_valid_banks[i] = 1; - } else { - if ((id[i] & 0x0ff) == (id[0] & 0x0ff)) - GLOB_valid_banks[i] = 1; - } - - totalUsedBanks += GLOB_valid_banks[i]; - } - - nand_dbg_print(NAND_DBG_DEBUG, - "totalUsedBanks: %d\n", totalUsedBanks); -} - -static void detect_partition_feature(void) -{ - if (ioread32(FlashReg + FEATURES) & FEATURES__PARTITION) { - if ((ioread32(FlashReg + PERM_SRC_ID_1) & - PERM_SRC_ID_1__SRCID) == SPECTRA_PARTITION_ID) { - DeviceInfo.wSpectraStartBlock = - ((ioread32(FlashReg + MIN_MAX_BANK_1) & - MIN_MAX_BANK_1__MIN_VALUE) * - DeviceInfo.wTotalBlocks) - + - (ioread32(FlashReg + MIN_BLK_ADDR_1) & - MIN_BLK_ADDR_1__VALUE); - - DeviceInfo.wSpectraEndBlock = - (((ioread32(FlashReg + MIN_MAX_BANK_1) & - MIN_MAX_BANK_1__MAX_VALUE) >> 2) * - DeviceInfo.wTotalBlocks) - + - (ioread32(FlashReg + MAX_BLK_ADDR_1) & - MAX_BLK_ADDR_1__VALUE); - - DeviceInfo.wTotalBlocks *= totalUsedBanks; - - if (DeviceInfo.wSpectraEndBlock >= - DeviceInfo.wTotalBlocks) { - DeviceInfo.wSpectraEndBlock = - DeviceInfo.wTotalBlocks - 1; - } - - DeviceInfo.wDataBlockNum = - DeviceInfo.wSpectraEndBlock - - DeviceInfo.wSpectraStartBlock + 1; - } else { - DeviceInfo.wTotalBlocks *= totalUsedBanks; - DeviceInfo.wSpectraStartBlock = SPECTRA_START_BLOCK; - DeviceInfo.wSpectraEndBlock = - DeviceInfo.wTotalBlocks - 1; - DeviceInfo.wDataBlockNum = - DeviceInfo.wSpectraEndBlock - - DeviceInfo.wSpectraStartBlock + 1; - } - } else { - DeviceInfo.wTotalBlocks *= totalUsedBanks; - DeviceInfo.wSpectraStartBlock = SPECTRA_START_BLOCK; - DeviceInfo.wSpectraEndBlock = DeviceInfo.wTotalBlocks - 1; - DeviceInfo.wDataBlockNum = - DeviceInfo.wSpectraEndBlock - - DeviceInfo.wSpectraStartBlock + 1; - } -} - -static void dump_device_info(void) -{ - nand_dbg_print(NAND_DBG_DEBUG, "DeviceInfo:\n"); - nand_dbg_print(NAND_DBG_DEBUG, "DeviceMaker: 0x%x\n", - DeviceInfo.wDeviceMaker); - nand_dbg_print(NAND_DBG_DEBUG, "DeviceID: 0x%x\n", - DeviceInfo.wDeviceID); - nand_dbg_print(NAND_DBG_DEBUG, "DeviceType: 0x%x\n", - DeviceInfo.wDeviceType); - nand_dbg_print(NAND_DBG_DEBUG, "SpectraStartBlock: %d\n", - DeviceInfo.wSpectraStartBlock); - nand_dbg_print(NAND_DBG_DEBUG, "SpectraEndBlock: %d\n", - DeviceInfo.wSpectraEndBlock); - nand_dbg_print(NAND_DBG_DEBUG, "TotalBlocks: %d\n", - DeviceInfo.wTotalBlocks); - nand_dbg_print(NAND_DBG_DEBUG, "PagesPerBlock: %d\n", - DeviceInfo.wPagesPerBlock); - nand_dbg_print(NAND_DBG_DEBUG, "PageSize: %d\n", - DeviceInfo.wPageSize); - nand_dbg_print(NAND_DBG_DEBUG, "PageDataSize: %d\n", - DeviceInfo.wPageDataSize); - nand_dbg_print(NAND_DBG_DEBUG, "PageSpareSize: %d\n", - DeviceInfo.wPageSpareSize); - nand_dbg_print(NAND_DBG_DEBUG, "NumPageSpareFlag: %d\n", - DeviceInfo.wNumPageSpareFlag); - nand_dbg_print(NAND_DBG_DEBUG, "ECCBytesPerSector: %d\n", - DeviceInfo.wECCBytesPerSector); - nand_dbg_print(NAND_DBG_DEBUG, "BlockSize: %d\n", - DeviceInfo.wBlockSize); - nand_dbg_print(NAND_DBG_DEBUG, "BlockDataSize: %d\n", - DeviceInfo.wBlockDataSize); - nand_dbg_print(NAND_DBG_DEBUG, "DataBlockNum: %d\n", - DeviceInfo.wDataBlockNum); - nand_dbg_print(NAND_DBG_DEBUG, "PlaneNum: %d\n", - DeviceInfo.bPlaneNum); - nand_dbg_print(NAND_DBG_DEBUG, "DeviceMainAreaSize: %d\n", - DeviceInfo.wDeviceMainAreaSize); - nand_dbg_print(NAND_DBG_DEBUG, "DeviceSpareAreaSize: %d\n", - DeviceInfo.wDeviceSpareAreaSize); - nand_dbg_print(NAND_DBG_DEBUG, "DevicesConnected: %d\n", - DeviceInfo.wDevicesConnected); - nand_dbg_print(NAND_DBG_DEBUG, "DeviceWidth: %d\n", - DeviceInfo.wDeviceWidth); - nand_dbg_print(NAND_DBG_DEBUG, "HWRevision: 0x%x\n", - DeviceInfo.wHWRevision); - nand_dbg_print(NAND_DBG_DEBUG, "HWFeatures: 0x%x\n", - DeviceInfo.wHWFeatures); - nand_dbg_print(NAND_DBG_DEBUG, "ONFIDevFeatures: 0x%x\n", - DeviceInfo.wONFIDevFeatures); - nand_dbg_print(NAND_DBG_DEBUG, "ONFIOptCommands: 0x%x\n", - DeviceInfo.wONFIOptCommands); - nand_dbg_print(NAND_DBG_DEBUG, "ONFITimingMode: 0x%x\n", - DeviceInfo.wONFITimingMode); - nand_dbg_print(NAND_DBG_DEBUG, "ONFIPgmCacheTimingMode: 0x%x\n", - DeviceInfo.wONFIPgmCacheTimingMode); - nand_dbg_print(NAND_DBG_DEBUG, "MLCDevice: %s\n", - DeviceInfo.MLCDevice ? "Yes" : "No"); - nand_dbg_print(NAND_DBG_DEBUG, "SpareSkipBytes: %d\n", - DeviceInfo.wSpareSkipBytes); - nand_dbg_print(NAND_DBG_DEBUG, "BitsInPageNumber: %d\n", - DeviceInfo.nBitsInPageNumber); - nand_dbg_print(NAND_DBG_DEBUG, "BitsInPageDataSize: %d\n", - DeviceInfo.nBitsInPageDataSize); - nand_dbg_print(NAND_DBG_DEBUG, "BitsInBlockDataSize: %d\n", - DeviceInfo.nBitsInBlockDataSize); -} - -u16 NAND_Read_Device_ID(void) -{ - u16 status = PASS; - u8 no_of_planes; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - iowrite32(0x02, FlashReg + SPARE_AREA_SKIP_BYTES); - iowrite32(0xffff, FlashReg + SPARE_AREA_MARKER); - DeviceInfo.wDeviceMaker = ioread32(FlashReg + MANUFACTURER_ID); - DeviceInfo.wDeviceID = ioread32(FlashReg + DEVICE_ID); - DeviceInfo.MLCDevice = ioread32(FlashReg + DEVICE_PARAM_0) & 0x0c; - - if (ioread32(FlashReg + ONFI_DEVICE_NO_OF_LUNS) & - ONFI_DEVICE_NO_OF_LUNS__ONFI_DEVICE) { /* ONFI 1.0 NAND */ - if (FAIL == get_onfi_nand_para()) - return FAIL; - } else if (DeviceInfo.wDeviceMaker == 0xEC) { /* Samsung NAND */ - get_samsung_nand_para(); - } else if (DeviceInfo.wDeviceMaker == 0x98) { /* Toshiba NAND */ - get_toshiba_nand_para(); - } else if (DeviceInfo.wDeviceMaker == 0xAD) { /* Hynix NAND */ - get_hynix_nand_para(); - } else { - DeviceInfo.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; - } - - nand_dbg_print(NAND_DBG_DEBUG, "Dump timing register values:" - "acc_clks: %d, re_2_we: %d, we_2_re: %d," - "addr_2_data: %d, rdwr_en_lo_cnt: %d, " - "rdwr_en_hi_cnt: %d, cs_setup_cnt: %d\n", - ioread32(FlashReg + ACC_CLKS), - ioread32(FlashReg + RE_2_WE), - ioread32(FlashReg + WE_2_RE), - ioread32(FlashReg + ADDR_2_DATA), - ioread32(FlashReg + RDWR_EN_LO_CNT), - ioread32(FlashReg + RDWR_EN_HI_CNT), - ioread32(FlashReg + CS_SETUP_CNT)); - - DeviceInfo.wHWRevision = ioread32(FlashReg + REVISION); - DeviceInfo.wHWFeatures = ioread32(FlashReg + FEATURES); - - DeviceInfo.wDeviceMainAreaSize = - ioread32(FlashReg + DEVICE_MAIN_AREA_SIZE); - DeviceInfo.wDeviceSpareAreaSize = - ioread32(FlashReg + DEVICE_SPARE_AREA_SIZE); - - DeviceInfo.wPageDataSize = - ioread32(FlashReg + LOGICAL_PAGE_DATA_SIZE); - - /* Note: When using the Micon 4K NAND device, the controller will report - * Page Spare Size as 216 bytes. But Micron's Spec say it's 218 bytes. - * And if force set it to 218 bytes, the controller can not work - * correctly. So just let it be. But keep in mind that this bug may - * cause - * other problems in future. - Yunpeng 2008-10-10 - */ - DeviceInfo.wPageSpareSize = - ioread32(FlashReg + LOGICAL_PAGE_SPARE_SIZE); - - DeviceInfo.wPagesPerBlock = ioread32(FlashReg + PAGES_PER_BLOCK); - - DeviceInfo.wPageSize = - DeviceInfo.wPageDataSize + DeviceInfo.wPageSpareSize; - DeviceInfo.wBlockSize = - DeviceInfo.wPageSize * DeviceInfo.wPagesPerBlock; - DeviceInfo.wBlockDataSize = - DeviceInfo.wPagesPerBlock * DeviceInfo.wPageDataSize; - - DeviceInfo.wDeviceWidth = ioread32(FlashReg + DEVICE_WIDTH); - DeviceInfo.wDeviceType = - ((ioread32(FlashReg + DEVICE_WIDTH) > 0) ? 16 : 8); - - DeviceInfo.wDevicesConnected = ioread32(FlashReg + DEVICES_CONNECTED); - - DeviceInfo.wSpareSkipBytes = - ioread32(FlashReg + SPARE_AREA_SKIP_BYTES) * - DeviceInfo.wDevicesConnected; - - DeviceInfo.nBitsInPageNumber = - (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPagesPerBlock); - DeviceInfo.nBitsInPageDataSize = - (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPageDataSize); - DeviceInfo.nBitsInBlockDataSize = - (u8)GLOB_Calc_Used_Bits(DeviceInfo.wBlockDataSize); - - set_ecc_config(); - - no_of_planes = ioread32(FlashReg + NUMBER_OF_PLANES) & - NUMBER_OF_PLANES__VALUE; - - switch (no_of_planes) { - case 0: - case 1: - case 3: - case 7: - DeviceInfo.bPlaneNum = no_of_planes + 1; - break; - default: - status = FAIL; - break; - } - - find_valid_banks(); - - detect_partition_feature(); - - dump_device_info(); - - return status; -} - -u16 NAND_UnlockArrayAll(void) -{ - u64 start_addr, end_addr; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - start_addr = 0; - end_addr = ((u64)DeviceInfo.wBlockSize * - (DeviceInfo.wTotalBlocks - 1)) >> - DeviceInfo.nBitsInPageDataSize; - - index_addr((u32)(MODE_10 | (u32)start_addr), 0x10); - index_addr((u32)(MODE_10 | (u32)end_addr), 0x11); - - return PASS; -} - -void NAND_LLD_Enable_Disable_Interrupts(u16 INT_ENABLE) -{ - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (INT_ENABLE) - iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); - else - iowrite32(0, FlashReg + GLOBAL_INT_ENABLE); -} - -u16 NAND_Erase_Block(u32 block) -{ - u16 status = PASS; - u64 flash_add; - u16 flash_bank; - u32 intr_status = 0; - u32 intr_status_addresses[4] = {INTR_STATUS0, - INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) - * DeviceInfo.wBlockDataSize; - - flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); - - if (block >= DeviceInfo.wTotalBlocks) - status = FAIL; - - if (status == PASS) { - intr_status = intr_status_addresses[flash_bank]; - - iowrite32(INTR_STATUS0__ERASE_COMP | INTR_STATUS0__ERASE_FAIL, - FlashReg + intr_status); - - index_addr((u32)(MODE_10 | (flash_bank << 24) | - (flash_add >> DeviceInfo.nBitsInPageDataSize)), 1); - - while (!(ioread32(FlashReg + intr_status) & - (INTR_STATUS0__ERASE_COMP | INTR_STATUS0__ERASE_FAIL))) - ; - - if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__ERASE_FAIL) - status = FAIL; - - iowrite32(INTR_STATUS0__ERASE_COMP | INTR_STATUS0__ERASE_FAIL, - FlashReg + intr_status); - } - - return status; -} - -static u32 Boundary_Check_Block_Page(u32 block, u16 page, - u16 page_count) -{ - u32 status = PASS; - - if (block >= DeviceInfo.wTotalBlocks) - status = FAIL; - - if (page + page_count > DeviceInfo.wPagesPerBlock) - status = FAIL; - - return status; -} - -u16 NAND_Read_Page_Spare(u8 *read_data, u32 block, u16 page, - u16 page_count) -{ - u32 status = PASS; - u32 i; - u64 flash_add; - u32 PageSpareSize = DeviceInfo.wPageSpareSize; - u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag; - u32 flash_bank; - u32 intr_status = 0; - u32 intr_status_addresses[4] = {INTR_STATUS0, - INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; - u8 *page_spare = buf_read_page_spare; - - if (block >= DeviceInfo.wTotalBlocks) { - printk(KERN_ERR "block too big: %d\n", (int)block); - status = FAIL; - } - - if (page >= DeviceInfo.wPagesPerBlock) { - printk(KERN_ERR "page too big: %d\n", page); - status = FAIL; - } - - if (page_count > 1) { - printk(KERN_ERR "page count too big: %d\n", page_count); - status = FAIL; - } - - flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) - * DeviceInfo.wBlockDataSize + - (u64)page * DeviceInfo.wPageDataSize; - - flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); - - if (status == PASS) { - intr_status = intr_status_addresses[flash_bank]; - iowrite32(ioread32(FlashReg + intr_status), - FlashReg + intr_status); - - index_addr((u32)(MODE_10 | (flash_bank << 24) | - (flash_add >> DeviceInfo.nBitsInPageDataSize)), - 0x41); - index_addr((u32)(MODE_10 | (flash_bank << 24) | - (flash_add >> DeviceInfo.nBitsInPageDataSize)), - 0x2000 | page_count); - while (!(ioread32(FlashReg + intr_status) & - INTR_STATUS0__LOAD_COMP)) - ; - - iowrite32((u32)(MODE_01 | (flash_bank << 24) | - (flash_add >> DeviceInfo.nBitsInPageDataSize)), - FlashMem); - - for (i = 0; i < (PageSpareSize / 4); i++) - *((u32 *)page_spare + i) = - ioread32(FlashMem + 0x10); - - if (enable_ecc) { - for (i = 0; i < spareFlagBytes; i++) - read_data[i] = - page_spare[PageSpareSize - - spareFlagBytes + i]; - for (i = 0; i < (PageSpareSize - spareFlagBytes); i++) - read_data[spareFlagBytes + i] = - page_spare[i]; - } else { - for (i = 0; i < PageSpareSize; i++) - read_data[i] = page_spare[i]; - } - - index_addr((u32)(MODE_10 | (flash_bank << 24) | - (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42); - } - - return status; -} - -/* No use function. Should be removed later */ -u16 NAND_Write_Page_Spare(u8 *write_data, u32 block, u16 page, - u16 page_count) -{ - printk(KERN_ERR - "Error! This function (NAND_Write_Page_Spare) should never" - " be called!\n"); - return ERR; -} - -/* op value: 0 - DDMA read; 1 - DDMA write */ -static void ddma_trans(u8 *data, u64 flash_add, - u32 flash_bank, int op, u32 numPages) -{ - u32 data_addr; - - /* Map virtual address to bus address for DDMA */ - data_addr = virt_to_bus(data); - - index_addr((u32)(MODE_10 | (flash_bank << 24) | - (flash_add >> DeviceInfo.nBitsInPageDataSize)), - (u16)(2 << 12) | (op << 8) | numPages); - - index_addr((u32)(MODE_10 | (flash_bank << 24) | - ((u16)(0x0FFFF & (data_addr >> 16)) << 8)), - (u16)(2 << 12) | (2 << 8) | 0); - - index_addr((u32)(MODE_10 | (flash_bank << 24) | - ((u16)(0x0FFFF & data_addr) << 8)), - (u16)(2 << 12) | (3 << 8) | 0); - - index_addr((u32)(MODE_10 | (flash_bank << 24) | - (1 << 16) | (0x40 << 8)), - (u16)(2 << 12) | (4 << 8) | 0); -} - -/* If data in buf are all 0xff, then return 1; otherwise return 0 */ -static int check_all_1(u8 *buf) -{ - int i, j, cnt; - - for (i = 0; i < DeviceInfo.wPageDataSize; i++) { - if (buf[i] != 0xff) { - cnt = 0; - nand_dbg_print(NAND_DBG_WARN, - "the first non-0xff data byte is: %d\n", i); - for (j = i; j < DeviceInfo.wPageDataSize; j++) { - nand_dbg_print(NAND_DBG_WARN, "0x%x ", buf[j]); - cnt++; - if (cnt > 8) - break; - } - nand_dbg_print(NAND_DBG_WARN, "\n"); - return 0; - } - } - - return 1; -} - -static int do_ecc_new(unsigned long bank, u8 *buf, - u32 block, u16 page) -{ - int status = PASS; - u16 err_page = 0; - u16 err_byte; - u8 err_sect; - u8 err_dev; - u16 err_fix_info; - u16 err_addr; - u32 ecc_sect_size; - u8 *err_pos; - u32 err_page_addr[4] = {ERR_PAGE_ADDR0, - ERR_PAGE_ADDR1, ERR_PAGE_ADDR2, ERR_PAGE_ADDR3}; - - ecc_sect_size = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected); - - do { - err_page = ioread32(FlashReg + err_page_addr[bank]); - err_addr = ioread32(FlashReg + ECC_ERROR_ADDRESS); - err_byte = err_addr & ECC_ERROR_ADDRESS__OFFSET; - err_sect = ((err_addr & ECC_ERROR_ADDRESS__SECTOR_NR) >> 12); - err_fix_info = ioread32(FlashReg + ERR_CORRECTION_INFO); - err_dev = ((err_fix_info & ERR_CORRECTION_INFO__DEVICE_NR) - >> 8); - if (err_fix_info & ERR_CORRECTION_INFO__ERROR_TYPE) { - nand_dbg_print(NAND_DBG_WARN, - "%s, Line %d Uncorrectable ECC error " - "when read block %d page %d." - "PTN_INTR register: 0x%x " - "err_page: %d, err_sect: %d, err_byte: %d, " - "err_dev: %d, ecc_sect_size: %d, " - "err_fix_info: 0x%x\n", - __FILE__, __LINE__, block, page, - ioread32(FlashReg + PTN_INTR), - err_page, err_sect, err_byte, err_dev, - ecc_sect_size, (u32)err_fix_info); - - if (check_all_1(buf)) - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d" - "All 0xff!\n", - __FILE__, __LINE__); - else - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d" - "Not all 0xff!\n", - __FILE__, __LINE__); - status = FAIL; - } else { - nand_dbg_print(NAND_DBG_WARN, - "%s, Line %d Found ECC error " - "when read block %d page %d." - "err_page: %d, err_sect: %d, err_byte: %d, " - "err_dev: %d, ecc_sect_size: %d, " - "err_fix_info: 0x%x\n", - __FILE__, __LINE__, block, page, - err_page, err_sect, err_byte, err_dev, - ecc_sect_size, (u32)err_fix_info); - if (err_byte < ECC_SECTOR_SIZE) { - err_pos = buf + - (err_page - page) * - DeviceInfo.wPageDataSize + - err_sect * ecc_sect_size + - err_byte * - DeviceInfo.wDevicesConnected + - err_dev; - - *err_pos ^= err_fix_info & - ERR_CORRECTION_INFO__BYTEMASK; - } - } - } while (!(err_fix_info & ERR_CORRECTION_INFO__LAST_ERR_INFO)); - - return status; -} - -u16 NAND_Read_Page_Main_Polling(u8 *read_data, - u32 block, u16 page, u16 page_count) -{ - u32 status = PASS; - u64 flash_add; - u32 intr_status = 0; - u32 flash_bank; - u32 intr_status_addresses[4] = {INTR_STATUS0, - INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; - u8 *read_data_l; - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - status = Boundary_Check_Block_Page(block, page, page_count); - if (status != PASS) - return status; - - flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) - * DeviceInfo.wBlockDataSize + - (u64)page * DeviceInfo.wPageDataSize; - flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); - - iowrite32(0, FlashReg + TRANSFER_SPARE_REG); - - intr_status = intr_status_addresses[flash_bank]; - iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); - - if (page_count > 1) { - read_data_l = read_data; - while (page_count > MAX_PAGES_PER_RW) { - if (ioread32(FlashReg + MULTIPLANE_OPERATION)) - status = NAND_Multiplane_Read(read_data_l, - block, page, MAX_PAGES_PER_RW); - else - status = NAND_Pipeline_Read_Ahead_Polling( - read_data_l, block, page, - MAX_PAGES_PER_RW); - - if (status == FAIL) - return status; - - read_data_l += DeviceInfo.wPageDataSize * - MAX_PAGES_PER_RW; - page_count -= MAX_PAGES_PER_RW; - page += MAX_PAGES_PER_RW; - } - if (ioread32(FlashReg + MULTIPLANE_OPERATION)) - status = NAND_Multiplane_Read(read_data_l, - block, page, page_count); - else - status = NAND_Pipeline_Read_Ahead_Polling( - read_data_l, block, page, page_count); - - return status; - } - - iowrite32(1, FlashReg + DMA_ENABLE); - while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - - iowrite32(0, FlashReg + TRANSFER_SPARE_REG); - iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); - - ddma_trans(read_data, flash_add, flash_bank, 0, 1); - - if (enable_ecc) { - while (!(ioread32(FlashReg + intr_status) & - (INTR_STATUS0__ECC_TRANSACTION_DONE | - INTR_STATUS0__ECC_ERR))) - ; - - if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__ECC_ERR) { - iowrite32(INTR_STATUS0__ECC_ERR, - FlashReg + intr_status); - status = do_ecc_new(flash_bank, read_data, - block, page); - } - - if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__ECC_TRANSACTION_DONE & - INTR_STATUS0__ECC_ERR) - iowrite32(INTR_STATUS0__ECC_TRANSACTION_DONE | - INTR_STATUS0__ECC_ERR, - FlashReg + intr_status); - else if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__ECC_TRANSACTION_DONE) - iowrite32(INTR_STATUS0__ECC_TRANSACTION_DONE, - FlashReg + intr_status); - else if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__ECC_ERR) - iowrite32(INTR_STATUS0__ECC_ERR, - FlashReg + intr_status); - } else { - while (!(ioread32(FlashReg + intr_status) & - INTR_STATUS0__DMA_CMD_COMP)) - ; - iowrite32(INTR_STATUS0__DMA_CMD_COMP, FlashReg + intr_status); - } - - iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); - - iowrite32(0, FlashReg + DMA_ENABLE); - while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - - return status; -} - -u16 NAND_Pipeline_Read_Ahead_Polling(u8 *read_data, - u32 block, u16 page, u16 page_count) -{ - u32 status = PASS; - u32 NumPages = page_count; - u64 flash_add; - u32 flash_bank; - u32 intr_status = 0; - u32 intr_status_addresses[4] = {INTR_STATUS0, - INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; - u32 ecc_done_OR_dma_comp; - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - status = Boundary_Check_Block_Page(block, page, page_count); - - if (page_count < 2) - status = FAIL; - - flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) - *DeviceInfo.wBlockDataSize + - (u64)page * DeviceInfo.wPageDataSize; - - flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); - - if (status == PASS) { - intr_status = intr_status_addresses[flash_bank]; - iowrite32(ioread32(FlashReg + intr_status), - FlashReg + intr_status); - - iowrite32(1, FlashReg + DMA_ENABLE); - while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - - iowrite32(0, FlashReg + TRANSFER_SPARE_REG); - - index_addr((u32)(MODE_10 | (flash_bank << 24) | - (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42); - ddma_trans(read_data, flash_add, flash_bank, 0, NumPages); - - ecc_done_OR_dma_comp = 0; - while (1) { - if (enable_ecc) { - while (!ioread32(FlashReg + intr_status)) - ; - - if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__ECC_ERR) { - iowrite32(INTR_STATUS0__ECC_ERR, - FlashReg + intr_status); - status = do_ecc_new(flash_bank, - read_data, block, page); - } else if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__DMA_CMD_COMP) { - iowrite32(INTR_STATUS0__DMA_CMD_COMP, - FlashReg + intr_status); - - if (1 == ecc_done_OR_dma_comp) - break; - - ecc_done_OR_dma_comp = 1; - } else if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__ECC_TRANSACTION_DONE) { - iowrite32( - INTR_STATUS0__ECC_TRANSACTION_DONE, - FlashReg + intr_status); - - if (1 == ecc_done_OR_dma_comp) - break; - - ecc_done_OR_dma_comp = 1; - } - } else { - while (!(ioread32(FlashReg + intr_status) & - INTR_STATUS0__DMA_CMD_COMP)) - ; - - iowrite32(INTR_STATUS0__DMA_CMD_COMP, - FlashReg + intr_status); - break; - } - - iowrite32((~INTR_STATUS0__ECC_ERR) & - (~INTR_STATUS0__ECC_TRANSACTION_DONE) & - (~INTR_STATUS0__DMA_CMD_COMP), - FlashReg + intr_status); - - } - - iowrite32(ioread32(FlashReg + intr_status), - FlashReg + intr_status); - - iowrite32(0, FlashReg + DMA_ENABLE); - - while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - } - return status; -} - -u16 NAND_Read_Page_Main(u8 *read_data, u32 block, u16 page, - u16 page_count) -{ - u32 status = PASS; - u64 flash_add; - u32 intr_status = 0; - u32 flash_bank; - u32 intr_status_addresses[4] = {INTR_STATUS0, - INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; - int ret; - u8 *read_data_l; - - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - status = Boundary_Check_Block_Page(block, page, page_count); - if (status != PASS) - return status; - - flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) - * DeviceInfo.wBlockDataSize + - (u64)page * DeviceInfo.wPageDataSize; - flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); - - iowrite32(0, FlashReg + TRANSFER_SPARE_REG); - - intr_status = intr_status_addresses[flash_bank]; - iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); - - if (page_count > 1) { - read_data_l = read_data; - while (page_count > MAX_PAGES_PER_RW) { - if (ioread32(FlashReg + MULTIPLANE_OPERATION)) - status = NAND_Multiplane_Read(read_data_l, - block, page, MAX_PAGES_PER_RW); - else - status = NAND_Pipeline_Read_Ahead( - read_data_l, block, page, - MAX_PAGES_PER_RW); - - if (status == FAIL) - return status; - - read_data_l += DeviceInfo.wPageDataSize * - MAX_PAGES_PER_RW; - page_count -= MAX_PAGES_PER_RW; - page += MAX_PAGES_PER_RW; - } - if (ioread32(FlashReg + MULTIPLANE_OPERATION)) - status = NAND_Multiplane_Read(read_data_l, - block, page, page_count); - else - status = NAND_Pipeline_Read_Ahead( - read_data_l, block, page, page_count); - - return status; - } - - iowrite32(1, FlashReg + DMA_ENABLE); - while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - - iowrite32(0, FlashReg + TRANSFER_SPARE_REG); - iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); - - /* Fill the mrst_nand_info structure */ - info.state = INT_READ_PAGE_MAIN; - info.read_data = read_data; - info.flash_bank = flash_bank; - info.block = block; - info.page = page; - info.ret = PASS; - - ddma_trans(read_data, flash_add, flash_bank, 0, 1); - - iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable Interrupt */ - - ret = wait_for_completion_timeout(&info.complete, 10 * HZ); - if (!ret) { - printk(KERN_ERR "Wait for completion timeout " - "in %s, Line %d\n", __FILE__, __LINE__); - status = ERR; - } else { - status = info.ret; - } - - iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); - - iowrite32(0, FlashReg + DMA_ENABLE); - while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - - return status; -} - -void Conv_Spare_Data_Log2Phy_Format(u8 *data) -{ - int i; - const u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag; - const u32 PageSpareSize = DeviceInfo.wPageSpareSize; - - if (enable_ecc) { - for (i = spareFlagBytes - 1; i >= 0; i--) - data[PageSpareSize - spareFlagBytes + i] = data[i]; - } -} - -void Conv_Spare_Data_Phy2Log_Format(u8 *data) -{ - int i; - const u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag; - const u32 PageSpareSize = DeviceInfo.wPageSpareSize; - - if (enable_ecc) { - for (i = 0; i < spareFlagBytes; i++) - data[i] = data[PageSpareSize - spareFlagBytes + i]; - } -} - - -void Conv_Main_Spare_Data_Log2Phy_Format(u8 *data, u16 page_count) -{ - const u32 PageSize = DeviceInfo.wPageSize; - const u32 PageDataSize = DeviceInfo.wPageDataSize; - const u32 eccBytes = DeviceInfo.wECCBytesPerSector; - const u32 spareSkipBytes = DeviceInfo.wSpareSkipBytes; - const u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag; - u32 eccSectorSize; - u32 page_offset; - int i, j; - - eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected); - if (enable_ecc) { - while (page_count > 0) { - page_offset = (page_count - 1) * PageSize; - j = (DeviceInfo.wPageDataSize / eccSectorSize); - for (i = spareFlagBytes - 1; i >= 0; i--) - data[page_offset + - (eccSectorSize + eccBytes) * j + i] = - data[page_offset + PageDataSize + i]; - for (j--; j >= 1; j--) { - for (i = eccSectorSize - 1; i >= 0; i--) - data[page_offset + - (eccSectorSize + eccBytes) * j + i] = - data[page_offset + - eccSectorSize * j + i]; - } - for (i = (PageSize - spareSkipBytes) - 1; - i >= PageDataSize; i--) - data[page_offset + i + spareSkipBytes] = - data[page_offset + i]; - page_count--; - } - } -} - -void Conv_Main_Spare_Data_Phy2Log_Format(u8 *data, u16 page_count) -{ - const u32 PageSize = DeviceInfo.wPageSize; - const u32 PageDataSize = DeviceInfo.wPageDataSize; - const u32 eccBytes = DeviceInfo.wECCBytesPerSector; - const u32 spareSkipBytes = DeviceInfo.wSpareSkipBytes; - const u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag; - u32 eccSectorSize; - u32 page_offset; - int i, j; - - eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected); - if (enable_ecc) { - while (page_count > 0) { - page_offset = (page_count - 1) * PageSize; - for (i = PageDataSize; - i < PageSize - spareSkipBytes; - i++) - data[page_offset + i] = - data[page_offset + i + - spareSkipBytes]; - for (j = 1; - j < DeviceInfo.wPageDataSize / eccSectorSize; - j++) { - for (i = 0; i < eccSectorSize; i++) - data[page_offset + - eccSectorSize * j + i] = - data[page_offset + - (eccSectorSize + eccBytes) * j - + i]; - } - for (i = 0; i < spareFlagBytes; i++) - data[page_offset + PageDataSize + i] = - data[page_offset + - (eccSectorSize + eccBytes) * j + i]; - page_count--; - } - } -} - -/* Un-tested function */ -u16 NAND_Multiplane_Read(u8 *read_data, u32 block, u16 page, - u16 page_count) -{ - u32 status = PASS; - u32 NumPages = page_count; - u64 flash_add; - u32 flash_bank; - u32 intr_status = 0; - u32 intr_status_addresses[4] = {INTR_STATUS0, - INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; - u32 ecc_done_OR_dma_comp; - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - status = Boundary_Check_Block_Page(block, page, page_count); - - flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) - * DeviceInfo.wBlockDataSize + - (u64)page * DeviceInfo.wPageDataSize; - - flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); - - if (status == PASS) { - intr_status = intr_status_addresses[flash_bank]; - iowrite32(ioread32(FlashReg + intr_status), - FlashReg + intr_status); - - iowrite32(0, FlashReg + TRANSFER_SPARE_REG); - iowrite32(0x01, FlashReg + MULTIPLANE_OPERATION); - - iowrite32(1, FlashReg + DMA_ENABLE); - while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - index_addr((u32)(MODE_10 | (flash_bank << 24) | - (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42); - ddma_trans(read_data, flash_add, flash_bank, 0, NumPages); - - ecc_done_OR_dma_comp = 0; - while (1) { - if (enable_ecc) { - while (!ioread32(FlashReg + intr_status)) - ; - - if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__ECC_ERR) { - iowrite32(INTR_STATUS0__ECC_ERR, - FlashReg + intr_status); - status = do_ecc_new(flash_bank, - read_data, block, page); - } else if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__DMA_CMD_COMP) { - iowrite32(INTR_STATUS0__DMA_CMD_COMP, - FlashReg + intr_status); - - if (1 == ecc_done_OR_dma_comp) - break; - - ecc_done_OR_dma_comp = 1; - } else if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__ECC_TRANSACTION_DONE) { - iowrite32( - INTR_STATUS0__ECC_TRANSACTION_DONE, - FlashReg + intr_status); - - if (1 == ecc_done_OR_dma_comp) - break; - - ecc_done_OR_dma_comp = 1; - } - } else { - while (!(ioread32(FlashReg + intr_status) & - INTR_STATUS0__DMA_CMD_COMP)) - ; - iowrite32(INTR_STATUS0__DMA_CMD_COMP, - FlashReg + intr_status); - break; - } - - iowrite32((~INTR_STATUS0__ECC_ERR) & - (~INTR_STATUS0__ECC_TRANSACTION_DONE) & - (~INTR_STATUS0__DMA_CMD_COMP), - FlashReg + intr_status); - - } - - iowrite32(ioread32(FlashReg + intr_status), - FlashReg + intr_status); - - iowrite32(0, FlashReg + DMA_ENABLE); - - while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - - iowrite32(0, FlashReg + MULTIPLANE_OPERATION); - } - - return status; -} - -u16 NAND_Pipeline_Read_Ahead(u8 *read_data, u32 block, - u16 page, u16 page_count) -{ - u32 status = PASS; - u32 NumPages = page_count; - u64 flash_add; - u32 flash_bank; - u32 intr_status = 0; - u32 intr_status_addresses[4] = {INTR_STATUS0, - INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; - int ret; - - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - status = Boundary_Check_Block_Page(block, page, page_count); - - if (page_count < 2) - status = FAIL; - - if (status != PASS) - return status; - - flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) - *DeviceInfo.wBlockDataSize + - (u64)page * DeviceInfo.wPageDataSize; - - flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); - - intr_status = intr_status_addresses[flash_bank]; - iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); - - iowrite32(1, FlashReg + DMA_ENABLE); - while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - - iowrite32(0, FlashReg + TRANSFER_SPARE_REG); - - /* Fill the mrst_nand_info structure */ - info.state = INT_PIPELINE_READ_AHEAD; - info.read_data = read_data; - info.flash_bank = flash_bank; - info.block = block; - info.page = page; - info.ret = PASS; - - index_addr((u32)(MODE_10 | (flash_bank << 24) | - (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42); - - ddma_trans(read_data, flash_add, flash_bank, 0, NumPages); - - iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable Interrupt */ - - ret = wait_for_completion_timeout(&info.complete, 10 * HZ); - if (!ret) { - printk(KERN_ERR "Wait for completion timeout " - "in %s, Line %d\n", __FILE__, __LINE__); - status = ERR; - } else { - status = info.ret; - } - - iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); - - iowrite32(0, FlashReg + DMA_ENABLE); - - while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - - return status; -} - - -u16 NAND_Write_Page_Main(u8 *write_data, u32 block, u16 page, - u16 page_count) -{ - u32 status = PASS; - u64 flash_add; - u32 intr_status = 0; - u32 flash_bank; - u32 intr_status_addresses[4] = {INTR_STATUS0, - INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; - int ret; - u8 *write_data_l; - - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - status = Boundary_Check_Block_Page(block, page, page_count); - if (status != PASS) - return status; - - flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) - * DeviceInfo.wBlockDataSize + - (u64)page * DeviceInfo.wPageDataSize; - - flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); - - intr_status = intr_status_addresses[flash_bank]; - - iowrite32(0, FlashReg + TRANSFER_SPARE_REG); - - iowrite32(INTR_STATUS0__PROGRAM_COMP | - INTR_STATUS0__PROGRAM_FAIL, FlashReg + intr_status); - - if (page_count > 1) { - write_data_l = write_data; - while (page_count > MAX_PAGES_PER_RW) { - if (ioread32(FlashReg + MULTIPLANE_OPERATION)) - status = NAND_Multiplane_Write(write_data_l, - block, page, MAX_PAGES_PER_RW); - else - status = NAND_Pipeline_Write_Ahead( - write_data_l, block, page, - MAX_PAGES_PER_RW); - if (status == FAIL) - return status; - - write_data_l += DeviceInfo.wPageDataSize * - MAX_PAGES_PER_RW; - page_count -= MAX_PAGES_PER_RW; - page += MAX_PAGES_PER_RW; - } - if (ioread32(FlashReg + MULTIPLANE_OPERATION)) - status = NAND_Multiplane_Write(write_data_l, - block, page, page_count); - else - status = NAND_Pipeline_Write_Ahead(write_data_l, - block, page, page_count); - - return status; - } - - iowrite32(1, FlashReg + DMA_ENABLE); - while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - - iowrite32(0, FlashReg + TRANSFER_SPARE_REG); - - iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); - - /* Fill the mrst_nand_info structure */ - info.state = INT_WRITE_PAGE_MAIN; - info.write_data = write_data; - info.flash_bank = flash_bank; - info.block = block; - info.page = page; - info.ret = PASS; - - ddma_trans(write_data, flash_add, flash_bank, 1, 1); - - iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable interrupt */ - - ret = wait_for_completion_timeout(&info.complete, 10 * HZ); - if (!ret) { - printk(KERN_ERR "Wait for completion timeout " - "in %s, Line %d\n", __FILE__, __LINE__); - status = ERR; - } else { - status = info.ret; - } - - iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); - - iowrite32(0, FlashReg + DMA_ENABLE); - while (ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG) - ; - - return status; -} - -void NAND_ECC_Ctrl(int enable) -{ - if (enable) { - nand_dbg_print(NAND_DBG_WARN, - "Will enable ECC in %s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - iowrite32(1, FlashReg + ECC_ENABLE); - enable_ecc = 1; - } else { - nand_dbg_print(NAND_DBG_WARN, - "Will disable ECC in %s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - iowrite32(0, FlashReg + ECC_ENABLE); - enable_ecc = 0; - } -} - -u16 NAND_Write_Page_Main_Spare(u8 *write_data, u32 block, - u16 page, u16 page_count) -{ - u32 status = PASS; - u32 i, j, page_num = 0; - u32 PageSize = DeviceInfo.wPageSize; - u32 PageDataSize = DeviceInfo.wPageDataSize; - u32 eccBytes = DeviceInfo.wECCBytesPerSector; - u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag; - u32 spareSkipBytes = DeviceInfo.wSpareSkipBytes; - u64 flash_add; - u32 eccSectorSize; - u32 flash_bank; - u32 intr_status = 0; - u32 intr_status_addresses[4] = {INTR_STATUS0, - INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; - u8 *page_main_spare = buf_write_page_main_spare; - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected); - - status = Boundary_Check_Block_Page(block, page, page_count); - - flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); - - if (status == PASS) { - intr_status = intr_status_addresses[flash_bank]; - - iowrite32(1, FlashReg + TRANSFER_SPARE_REG); - - while ((status != FAIL) && (page_count > 0)) { - flash_add = (u64)(block % - (DeviceInfo.wTotalBlocks / totalUsedBanks)) * - DeviceInfo.wBlockDataSize + - (u64)page * DeviceInfo.wPageDataSize; - - iowrite32(ioread32(FlashReg + intr_status), - FlashReg + intr_status); - - iowrite32((u32)(MODE_01 | (flash_bank << 24) | - (flash_add >> - DeviceInfo.nBitsInPageDataSize)), - FlashMem); - - if (enable_ecc) { - for (j = 0; - j < - DeviceInfo.wPageDataSize / eccSectorSize; - j++) { - for (i = 0; i < eccSectorSize; i++) - page_main_spare[(eccSectorSize + - eccBytes) * j + - i] = - write_data[eccSectorSize * - j + i]; - - for (i = 0; i < eccBytes; i++) - page_main_spare[(eccSectorSize + - eccBytes) * j + - eccSectorSize + - i] = - write_data[PageDataSize + - spareFlagBytes + - eccBytes * j + - i]; - } - - for (i = 0; i < spareFlagBytes; i++) - page_main_spare[(eccSectorSize + - eccBytes) * j + i] = - write_data[PageDataSize + i]; - - for (i = PageSize - 1; i >= PageDataSize + - spareSkipBytes; i--) - page_main_spare[i] = page_main_spare[i - - spareSkipBytes]; - - for (i = PageDataSize; i < PageDataSize + - spareSkipBytes; i++) - page_main_spare[i] = 0xff; - - for (i = 0; i < PageSize / 4; i++) - iowrite32( - *((u32 *)page_main_spare + i), - FlashMem + 0x10); - } else { - - for (i = 0; i < PageSize / 4; i++) - iowrite32(*((u32 *)write_data + i), - FlashMem + 0x10); - } - - while (!(ioread32(FlashReg + intr_status) & - (INTR_STATUS0__PROGRAM_COMP | - INTR_STATUS0__PROGRAM_FAIL))) - ; - - if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__PROGRAM_FAIL) - status = FAIL; - - iowrite32(ioread32(FlashReg + intr_status), - FlashReg + intr_status); - - page_num++; - page_count--; - write_data += PageSize; - } - - iowrite32(0, FlashReg + TRANSFER_SPARE_REG); - } - - return status; -} - -u16 NAND_Read_Page_Main_Spare(u8 *read_data, u32 block, u16 page, - u16 page_count) -{ - u32 status = PASS; - u32 i, j; - u64 flash_add = 0; - u32 PageSize = DeviceInfo.wPageSize; - u32 PageDataSize = DeviceInfo.wPageDataSize; - u32 PageSpareSize = DeviceInfo.wPageSpareSize; - u32 eccBytes = DeviceInfo.wECCBytesPerSector; - u32 spareFlagBytes = DeviceInfo.wNumPageSpareFlag; - u32 spareSkipBytes = DeviceInfo.wSpareSkipBytes; - u32 eccSectorSize; - u32 flash_bank; - u32 intr_status = 0; - u8 *read_data_l = read_data; - u32 intr_status_addresses[4] = {INTR_STATUS0, - INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; - u8 *page_main_spare = buf_read_page_main_spare; - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - eccSectorSize = ECC_SECTOR_SIZE * (DeviceInfo.wDevicesConnected); - - status = Boundary_Check_Block_Page(block, page, page_count); - - flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); - - if (status == PASS) { - intr_status = intr_status_addresses[flash_bank]; - - iowrite32(1, FlashReg + TRANSFER_SPARE_REG); - - iowrite32(ioread32(FlashReg + intr_status), - FlashReg + intr_status); - - while ((status != FAIL) && (page_count > 0)) { - flash_add = (u64)(block % - (DeviceInfo.wTotalBlocks / totalUsedBanks)) - * DeviceInfo.wBlockDataSize + - (u64)page * DeviceInfo.wPageDataSize; - - index_addr((u32)(MODE_10 | (flash_bank << 24) | - (flash_add >> DeviceInfo.nBitsInPageDataSize)), - 0x43); - index_addr((u32)(MODE_10 | (flash_bank << 24) | - (flash_add >> DeviceInfo.nBitsInPageDataSize)), - 0x2000 | page_count); - - while (!(ioread32(FlashReg + intr_status) & - INTR_STATUS0__LOAD_COMP)) - ; - - iowrite32((u32)(MODE_01 | (flash_bank << 24) | - (flash_add >> - DeviceInfo.nBitsInPageDataSize)), - FlashMem); - - for (i = 0; i < PageSize / 4; i++) - *(((u32 *)page_main_spare) + i) = - ioread32(FlashMem + 0x10); - - if (enable_ecc) { - for (i = PageDataSize; i < PageSize - - spareSkipBytes; i++) - page_main_spare[i] = page_main_spare[i + - spareSkipBytes]; - - for (j = 0; - j < DeviceInfo.wPageDataSize / eccSectorSize; - j++) { - - for (i = 0; i < eccSectorSize; i++) - read_data_l[eccSectorSize * j + - i] = - page_main_spare[ - (eccSectorSize + - eccBytes) * j + i]; - - for (i = 0; i < eccBytes; i++) - read_data_l[PageDataSize + - spareFlagBytes + - eccBytes * j + i] = - page_main_spare[ - (eccSectorSize + - eccBytes) * j + - eccSectorSize + i]; - } - - for (i = 0; i < spareFlagBytes; i++) - read_data_l[PageDataSize + i] = - page_main_spare[(eccSectorSize + - eccBytes) * j + i]; - } else { - for (i = 0; i < (PageDataSize + PageSpareSize); - i++) - read_data_l[i] = page_main_spare[i]; - - } - - if (enable_ecc) { - while (!(ioread32(FlashReg + intr_status) & - (INTR_STATUS0__ECC_TRANSACTION_DONE | - INTR_STATUS0__ECC_ERR))) - ; - - if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__ECC_ERR) { - iowrite32(INTR_STATUS0__ECC_ERR, - FlashReg + intr_status); - status = do_ecc_new(flash_bank, - read_data, block, page); - } - - if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__ECC_TRANSACTION_DONE & - INTR_STATUS0__ECC_ERR) { - iowrite32(INTR_STATUS0__ECC_ERR | - INTR_STATUS0__ECC_TRANSACTION_DONE, - FlashReg + intr_status); - } else if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__ECC_TRANSACTION_DONE) { - iowrite32( - INTR_STATUS0__ECC_TRANSACTION_DONE, - FlashReg + intr_status); - } else if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__ECC_ERR) { - iowrite32(INTR_STATUS0__ECC_ERR, - FlashReg + intr_status); - } - } - - page++; - page_count--; - read_data_l += PageSize; - } - } - - iowrite32(0, FlashReg + TRANSFER_SPARE_REG); - - index_addr((u32)(MODE_10 | (flash_bank << 24) | - (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42); - - return status; -} - -u16 NAND_Pipeline_Write_Ahead(u8 *write_data, u32 block, - u16 page, u16 page_count) -{ - u16 status = PASS; - u32 NumPages = page_count; - u64 flash_add; - u32 flash_bank; - u32 intr_status = 0; - u32 intr_status_addresses[4] = {INTR_STATUS0, - INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; - int ret; - - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - status = Boundary_Check_Block_Page(block, page, page_count); - - if (page_count < 2) - status = FAIL; - - if (status != PASS) - return status; - - flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) - * DeviceInfo.wBlockDataSize + - (u64)page * DeviceInfo.wPageDataSize; - - flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); - - intr_status = intr_status_addresses[flash_bank]; - iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); - - iowrite32(1, FlashReg + DMA_ENABLE); - while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - - iowrite32(0, FlashReg + TRANSFER_SPARE_REG); - - /* Fill the mrst_nand_info structure */ - info.state = INT_PIPELINE_WRITE_AHEAD; - info.write_data = write_data; - info.flash_bank = flash_bank; - info.block = block; - info.page = page; - info.ret = PASS; - - index_addr((u32)(MODE_10 | (flash_bank << 24) | - (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42); - - ddma_trans(write_data, flash_add, flash_bank, 1, NumPages); - - iowrite32(1, FlashReg + GLOBAL_INT_ENABLE); /* Enable interrupt */ - - ret = wait_for_completion_timeout(&info.complete, 10 * HZ); - if (!ret) { - printk(KERN_ERR "Wait for completion timeout " - "in %s, Line %d\n", __FILE__, __LINE__); - status = ERR; - } else { - status = info.ret; - } - - iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); - - iowrite32(0, FlashReg + DMA_ENABLE); - while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - - return status; -} - -/* Un-tested function */ -u16 NAND_Multiplane_Write(u8 *write_data, u32 block, u16 page, - u16 page_count) -{ - u16 status = PASS; - u32 NumPages = page_count; - u64 flash_add; - u32 flash_bank; - u32 intr_status = 0; - u32 intr_status_addresses[4] = {INTR_STATUS0, - INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; - u16 status2 = PASS; - u32 t; - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - status = Boundary_Check_Block_Page(block, page, page_count); - if (status != PASS) - return status; - - flash_add = (u64)(block % (DeviceInfo.wTotalBlocks / totalUsedBanks)) - * DeviceInfo.wBlockDataSize + - (u64)page * DeviceInfo.wPageDataSize; - - flash_bank = block / (DeviceInfo.wTotalBlocks / totalUsedBanks); - - intr_status = intr_status_addresses[flash_bank]; - iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); - - iowrite32(0, FlashReg + TRANSFER_SPARE_REG); - iowrite32(0x01, FlashReg + MULTIPLANE_OPERATION); - - iowrite32(1, FlashReg + DMA_ENABLE); - while (!(ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - - iowrite32(0, FlashReg + TRANSFER_SPARE_REG); - - index_addr((u32)(MODE_10 | (flash_bank << 24) | - (flash_add >> DeviceInfo.nBitsInPageDataSize)), 0x42); - - ddma_trans(write_data, flash_add, flash_bank, 1, NumPages); - - while (1) { - while (!ioread32(FlashReg + intr_status)) - ; - - if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__DMA_CMD_COMP) { - iowrite32(INTR_STATUS0__DMA_CMD_COMP, - FlashReg + intr_status); - status = PASS; - if (status2 == FAIL) - status = FAIL; - break; - } else if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__PROGRAM_FAIL) { - status2 = FAIL; - status = FAIL; - t = ioread32(FlashReg + intr_status) & - INTR_STATUS0__PROGRAM_FAIL; - iowrite32(t, FlashReg + intr_status); - } else { - iowrite32((~INTR_STATUS0__PROGRAM_FAIL) & - (~INTR_STATUS0__DMA_CMD_COMP), - FlashReg + intr_status); - } - } - - iowrite32(ioread32(FlashReg + intr_status), FlashReg + intr_status); - - iowrite32(0, FlashReg + DMA_ENABLE); - - while ((ioread32(FlashReg + DMA_ENABLE) & DMA_ENABLE__FLAG)) - ; - - iowrite32(0, FlashReg + MULTIPLANE_OPERATION); - - return status; -} - - -#if CMD_DMA -static irqreturn_t cdma_isr(int irq, void *dev_id) -{ - struct mrst_nand_info *dev = dev_id; - int first_failed_cmd; - - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (!is_cdma_interrupt()) - return IRQ_NONE; - - /* Disable controller interrupts */ - iowrite32(0, FlashReg + GLOBAL_INT_ENABLE); - GLOB_FTL_Event_Status(&first_failed_cmd); - complete(&dev->complete); - - return IRQ_HANDLED; -} -#else -static void handle_nand_int_read(struct mrst_nand_info *dev) -{ - u32 intr_status_addresses[4] = {INTR_STATUS0, - INTR_STATUS1, INTR_STATUS2, INTR_STATUS3}; - u32 intr_status; - u32 ecc_done_OR_dma_comp = 0; - - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - dev->ret = PASS; - intr_status = intr_status_addresses[dev->flash_bank]; - - while (1) { - if (enable_ecc) { - if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__ECC_ERR) { - iowrite32(INTR_STATUS0__ECC_ERR, - FlashReg + intr_status); - dev->ret = do_ecc_new(dev->flash_bank, - dev->read_data, - dev->block, dev->page); - } else if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__DMA_CMD_COMP) { - iowrite32(INTR_STATUS0__DMA_CMD_COMP, - FlashReg + intr_status); - if (1 == ecc_done_OR_dma_comp) - break; - ecc_done_OR_dma_comp = 1; - } else if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__ECC_TRANSACTION_DONE) { - iowrite32(INTR_STATUS0__ECC_TRANSACTION_DONE, - FlashReg + intr_status); - if (1 == ecc_done_OR_dma_comp) - break; - ecc_done_OR_dma_comp = 1; - } - } else { - if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__DMA_CMD_COMP) { - iowrite32(INTR_STATUS0__DMA_CMD_COMP, - FlashReg + intr_status); - break; - } else { - printk(KERN_ERR "Illegal INTS " - "(offset addr 0x%x) value: 0x%x\n", - intr_status, - ioread32(FlashReg + intr_status)); - } - } - - iowrite32((~INTR_STATUS0__ECC_ERR) & - (~INTR_STATUS0__ECC_TRANSACTION_DONE) & - (~INTR_STATUS0__DMA_CMD_COMP), - FlashReg + intr_status); - } -} - -static void handle_nand_int_write(struct mrst_nand_info *dev) -{ - u32 intr_status; - u32 intr[4] = {INTR_STATUS0, INTR_STATUS1, - INTR_STATUS2, INTR_STATUS3}; - int status = PASS; - - nand_dbg_print(NAND_DBG_DEBUG, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - dev->ret = PASS; - intr_status = intr[dev->flash_bank]; - - while (1) { - while (!ioread32(FlashReg + intr_status)) - ; - - if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__DMA_CMD_COMP) { - iowrite32(INTR_STATUS0__DMA_CMD_COMP, - FlashReg + intr_status); - if (FAIL == status) - dev->ret = FAIL; - break; - } else if (ioread32(FlashReg + intr_status) & - INTR_STATUS0__PROGRAM_FAIL) { - status = FAIL; - iowrite32(INTR_STATUS0__PROGRAM_FAIL, - FlashReg + intr_status); - } else { - iowrite32((~INTR_STATUS0__PROGRAM_FAIL) & - (~INTR_STATUS0__DMA_CMD_COMP), - FlashReg + intr_status); - } - } -} - -static irqreturn_t ddma_isr(int irq, void *dev_id) -{ - struct mrst_nand_info *dev = dev_id; - u32 int_mask, ints0, ints1, ints2, ints3, ints_offset; - u32 intr[4] = {INTR_STATUS0, INTR_STATUS1, - INTR_STATUS2, INTR_STATUS3}; - - int_mask = INTR_STATUS0__DMA_CMD_COMP | - INTR_STATUS0__ECC_TRANSACTION_DONE | - INTR_STATUS0__ECC_ERR | - INTR_STATUS0__PROGRAM_FAIL | - INTR_STATUS0__ERASE_FAIL; - - ints0 = ioread32(FlashReg + INTR_STATUS0); - ints1 = ioread32(FlashReg + INTR_STATUS1); - ints2 = ioread32(FlashReg + INTR_STATUS2); - ints3 = ioread32(FlashReg + INTR_STATUS3); - - ints_offset = intr[dev->flash_bank]; - - nand_dbg_print(NAND_DBG_DEBUG, - "INTR0: 0x%x, INTR1: 0x%x, INTR2: 0x%x, INTR3: 0x%x, " - "DMA_INTR: 0x%x, " - "dev->state: 0x%x, dev->flash_bank: %d\n", - ints0, ints1, ints2, ints3, - ioread32(FlashReg + DMA_INTR), - dev->state, dev->flash_bank); - - if (!(ioread32(FlashReg + ints_offset) & int_mask)) { - iowrite32(ints0, FlashReg + INTR_STATUS0); - iowrite32(ints1, FlashReg + INTR_STATUS1); - iowrite32(ints2, FlashReg + INTR_STATUS2); - iowrite32(ints3, FlashReg + INTR_STATUS3); - nand_dbg_print(NAND_DBG_WARN, - "ddma_isr: Invalid interrupt for NAND controller. " - "Ignore it\n"); - return IRQ_NONE; - } - - switch (dev->state) { - case INT_READ_PAGE_MAIN: - case INT_PIPELINE_READ_AHEAD: - /* Disable controller interrupts */ - iowrite32(0, FlashReg + GLOBAL_INT_ENABLE); - handle_nand_int_read(dev); - break; - case INT_WRITE_PAGE_MAIN: - case INT_PIPELINE_WRITE_AHEAD: - iowrite32(0, FlashReg + GLOBAL_INT_ENABLE); - handle_nand_int_write(dev); - break; - default: - printk(KERN_ERR "ddma_isr - Illegal state: 0x%x\n", - dev->state); - return IRQ_NONE; - } - - dev->state = INT_IDLE_STATE; - complete(&dev->complete); - return IRQ_HANDLED; -} -#endif - -static const struct pci_device_id nand_pci_ids[] = { - { - .vendor = 0x8086, - .device = 0x0809, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { /* end: all zeroes */ } -}; - -static int nand_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - int ret = -ENODEV; - unsigned long csr_base; - unsigned long csr_len; - struct mrst_nand_info *pndev = &info; - u32 int_mask; - - ret = pci_enable_device(dev); - if (ret) { - printk(KERN_ERR "Spectra: pci_enable_device failed.\n"); - return ret; - } - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - FlashReg = ioremap_nocache(GLOB_HWCTL_REG_BASE, - GLOB_HWCTL_REG_SIZE); - if (!FlashReg) { - printk(KERN_ERR "Spectra: ioremap_nocache failed!"); - goto failed_disable; - } - nand_dbg_print(NAND_DBG_WARN, - "Spectra: Remapped reg base address: " - "0x%p, len: %d\n", - FlashReg, GLOB_HWCTL_REG_SIZE); - - FlashMem = ioremap_nocache(GLOB_HWCTL_MEM_BASE, - GLOB_HWCTL_MEM_SIZE); - if (!FlashMem) { - printk(KERN_ERR "Spectra: ioremap_nocache failed!"); - iounmap(FlashReg); - goto failed_disable; - } - nand_dbg_print(NAND_DBG_WARN, - "Spectra: Remapped flash base address: " - "0x%p, len: %d\n", - (void *)FlashMem, GLOB_HWCTL_MEM_SIZE); - - nand_dbg_print(NAND_DBG_DEBUG, "Dump timing register values:" - "acc_clks: %d, re_2_we: %d, we_2_re: %d," - "addr_2_data: %d, rdwr_en_lo_cnt: %d, " - "rdwr_en_hi_cnt: %d, cs_setup_cnt: %d\n", - ioread32(FlashReg + ACC_CLKS), - ioread32(FlashReg + RE_2_WE), - ioread32(FlashReg + WE_2_RE), - ioread32(FlashReg + ADDR_2_DATA), - ioread32(FlashReg + RDWR_EN_LO_CNT), - ioread32(FlashReg + RDWR_EN_HI_CNT), - ioread32(FlashReg + CS_SETUP_CNT)); - - NAND_Flash_Reset(); - - iowrite32(0, FlashReg + GLOBAL_INT_ENABLE); - -#if CMD_DMA - info.pcmds_num = 0; - info.flash_bank = 0; - info.cdma_num = 0; - int_mask = (DMA_INTR__DESC_COMP_CHANNEL0 | - DMA_INTR__DESC_COMP_CHANNEL1 | - DMA_INTR__DESC_COMP_CHANNEL2 | - DMA_INTR__DESC_COMP_CHANNEL3 | - DMA_INTR__MEMCOPY_DESC_COMP); - iowrite32(int_mask, FlashReg + DMA_INTR_EN); - iowrite32(0xFFFF, FlashReg + DMA_INTR); - - int_mask = (INTR_STATUS0__ECC_ERR | - INTR_STATUS0__PROGRAM_FAIL | - INTR_STATUS0__ERASE_FAIL); -#else - int_mask = INTR_STATUS0__DMA_CMD_COMP | - INTR_STATUS0__ECC_TRANSACTION_DONE | - INTR_STATUS0__ECC_ERR | - INTR_STATUS0__PROGRAM_FAIL | - INTR_STATUS0__ERASE_FAIL; -#endif - iowrite32(int_mask, FlashReg + INTR_EN0); - iowrite32(int_mask, FlashReg + INTR_EN1); - iowrite32(int_mask, FlashReg + INTR_EN2); - iowrite32(int_mask, FlashReg + INTR_EN3); - - /* Clear all status bits */ - iowrite32(0xFFFF, FlashReg + INTR_STATUS0); - iowrite32(0xFFFF, FlashReg + INTR_STATUS1); - iowrite32(0xFFFF, FlashReg + INTR_STATUS2); - iowrite32(0xFFFF, FlashReg + INTR_STATUS3); - - iowrite32(0x0F, FlashReg + RB_PIN_ENABLED); - iowrite32(CHIP_EN_DONT_CARE__FLAG, FlashReg + CHIP_ENABLE_DONT_CARE); - - /* Should set value for these registers when init */ - iowrite32(0, FlashReg + TWO_ROW_ADDR_CYCLES); - iowrite32(1, FlashReg + ECC_ENABLE); - enable_ecc = 1; - - pci_set_master(dev); - pndev->dev = dev; - - csr_base = pci_resource_start(dev, 0); - if (!csr_base) { - printk(KERN_ERR "Spectra: pci_resource_start failed!\n"); - ret = -ENODEV; - goto failed_req_csr; - } - - csr_len = pci_resource_len(dev, 0); - if (!csr_len) { - printk(KERN_ERR "Spectra: pci_resource_len failed!\n"); - ret = -ENODEV; - goto failed_req_csr; - } - - ret = pci_request_regions(dev, SPECTRA_NAND_NAME); - if (ret) { - printk(KERN_ERR "Spectra: Unable to request " - "memory region\n"); - goto failed_req_csr; - } - - pndev->ioaddr = ioremap_nocache(csr_base, csr_len); - if (!pndev->ioaddr) { - printk(KERN_ERR "Spectra: Unable to remap memory region\n"); - ret = -ENOMEM; - goto failed_remap_csr; - } - nand_dbg_print(NAND_DBG_DEBUG, "Spectra: CSR 0x%08lx -> 0x%p (0x%lx)\n", - csr_base, pndev->ioaddr, csr_len); - - init_completion(&pndev->complete); - nand_dbg_print(NAND_DBG_DEBUG, "Spectra: IRQ %d\n", dev->irq); - -#if CMD_DMA - if (request_irq(dev->irq, cdma_isr, IRQF_SHARED, - SPECTRA_NAND_NAME, &info)) { - printk(KERN_ERR "Spectra: Unable to allocate IRQ\n"); - ret = -ENODEV; - iounmap(pndev->ioaddr); - goto failed_remap_csr; - } -#else - if (request_irq(dev->irq, ddma_isr, IRQF_SHARED, - SPECTRA_NAND_NAME, &info)) { - printk(KERN_ERR "Spectra: Unable to allocate IRQ\n"); - ret = -ENODEV; - iounmap(pndev->ioaddr); - goto failed_remap_csr; - } -#endif - - pci_set_drvdata(dev, pndev); - - ret = GLOB_LLD_Read_Device_ID(); - if (ret) { - iounmap(pndev->ioaddr); - goto failed_remap_csr; - } - - ret = register_spectra_ftl(); - if (ret) { - iounmap(pndev->ioaddr); - goto failed_remap_csr; - } - - return 0; - -failed_remap_csr: - pci_release_regions(dev); -failed_req_csr: - iounmap(FlashMem); - iounmap(FlashReg); -failed_disable: - pci_disable_device(dev); - - return ret; -} - -static void nand_pci_remove(struct pci_dev *dev) -{ - struct mrst_nand_info *pndev = pci_get_drvdata(dev); - - nand_dbg_print(NAND_DBG_WARN, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - -#if CMD_DMA - free_irq(dev->irq, pndev); -#endif - iounmap(pndev->ioaddr); - pci_release_regions(dev); - pci_disable_device(dev); -} - -MODULE_DEVICE_TABLE(pci, nand_pci_ids); - -static struct pci_driver nand_pci_driver = { - .name = SPECTRA_NAND_NAME, - .id_table = nand_pci_ids, - .probe = nand_pci_probe, - .remove = nand_pci_remove, -}; - -int NAND_Flash_Init(void) -{ - int retval; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - retval = pci_register_driver(&nand_pci_driver); - if (retval) - return -ENOMEM; - - return PASS; -} - -/* Free memory */ -int nand_release_spectra(void) -{ - pci_unregister_driver(&nand_pci_driver); - iounmap(FlashMem); - iounmap(FlashReg); - - return 0; -} - - - diff --git a/drivers/staging/spectra/lld_nand.h b/drivers/staging/spectra/lld_nand.h deleted file mode 100644 index d08388287da8..000000000000 --- a/drivers/staging/spectra/lld_nand.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef _LLD_NAND_ -#define _LLD_NAND_ - -#ifdef ELDORA -#include "defs.h" -#else -#include "flash.h" -#include "ffsport.h" -#endif - -#define MODE_00 0x00000000 -#define MODE_01 0x04000000 -#define MODE_10 0x08000000 -#define MODE_11 0x0C000000 - - -#define DATA_TRANSFER_MODE 0 -#define PROTECTION_PER_BLOCK 1 -#define LOAD_WAIT_COUNT 2 -#define PROGRAM_WAIT_COUNT 3 -#define ERASE_WAIT_COUNT 4 -#define INT_MONITOR_CYCLE_COUNT 5 -#define READ_BUSY_PIN_ENABLED 6 -#define MULTIPLANE_OPERATION_SUPPORT 7 -#define PRE_FETCH_MODE 8 -#define CE_DONT_CARE_SUPPORT 9 -#define COPYBACK_SUPPORT 10 -#define CACHE_WRITE_SUPPORT 11 -#define CACHE_READ_SUPPORT 12 -#define NUM_PAGES_IN_BLOCK 13 -#define ECC_ENABLE_SELECT 14 -#define WRITE_ENABLE_2_READ_ENABLE 15 -#define ADDRESS_2_DATA 16 -#define READ_ENABLE_2_WRITE_ENABLE 17 -#define TWO_ROW_ADDRESS_CYCLES 18 -#define MULTIPLANE_ADDRESS_RESTRICT 19 -#define ACC_CLOCKS 20 -#define READ_WRITE_ENABLE_LOW_COUNT 21 -#define READ_WRITE_ENABLE_HIGH_COUNT 22 - -#define ECC_SECTOR_SIZE 512 -#define LLD_MAX_FLASH_BANKS 4 - -struct mrst_nand_info { - struct pci_dev *dev; - u32 state; - u32 flash_bank; - u8 *read_data; - u8 *write_data; - u32 block; - u16 page; - u32 use_dma; - void __iomem *ioaddr; /* Mapped io reg base address */ - int ret; - u32 pcmds_num; - struct pending_cmd *pcmds; - int cdma_num; /* CDMA descriptor number in this chan */ - u8 *cdma_desc_buf; /* CDMA descriptor table */ - u8 *memcp_desc_buf; /* Memory copy descriptor table */ - dma_addr_t cdma_desc; /* Mapped CDMA descriptor table */ - dma_addr_t memcp_desc; /* Mapped memory copy descriptor table */ - struct completion complete; -}; - -int NAND_Flash_Init(void); -int nand_release_spectra(void); -u16 NAND_Flash_Reset(void); -u16 NAND_Read_Device_ID(void); -u16 NAND_Erase_Block(u32 flash_add); -u16 NAND_Write_Page_Main(u8 *write_data, u32 block, u16 page, - u16 page_count); -u16 NAND_Read_Page_Main(u8 *read_data, u32 block, u16 page, - u16 page_count); -u16 NAND_UnlockArrayAll(void); -u16 NAND_Write_Page_Main_Spare(u8 *write_data, u32 block, - u16 page, u16 page_count); -u16 NAND_Write_Page_Spare(u8 *read_data, u32 block, u16 page, - u16 page_count); -u16 NAND_Read_Page_Main_Spare(u8 *read_data, u32 block, u16 page, - u16 page_count); -u16 NAND_Read_Page_Spare(u8 *read_data, u32 block, u16 page, - u16 page_count); -void NAND_LLD_Enable_Disable_Interrupts(u16 INT_ENABLE); -u16 NAND_Get_Bad_Block(u32 block); -u16 NAND_Pipeline_Read_Ahead(u8 *read_data, u32 block, u16 page, - u16 page_count); -u16 NAND_Pipeline_Write_Ahead(u8 *write_data, u32 block, - u16 page, u16 page_count); -u16 NAND_Multiplane_Read(u8 *read_data, u32 block, u16 page, - u16 page_count); -u16 NAND_Multiplane_Write(u8 *write_data, u32 block, u16 page, - u16 page_count); -void NAND_ECC_Ctrl(int enable); -u16 NAND_Read_Page_Main_Polling(u8 *read_data, - u32 block, u16 page, u16 page_count); -u16 NAND_Pipeline_Read_Ahead_Polling(u8 *read_data, - u32 block, u16 page, u16 page_count); -void Conv_Spare_Data_Log2Phy_Format(u8 *data); -void Conv_Spare_Data_Phy2Log_Format(u8 *data); -void Conv_Main_Spare_Data_Log2Phy_Format(u8 *data, u16 page_count); -void Conv_Main_Spare_Data_Phy2Log_Format(u8 *data, u16 page_count); - -extern void __iomem *FlashReg; -extern void __iomem *FlashMem; - -extern int totalUsedBanks; -extern u32 GLOB_valid_banks[LLD_MAX_FLASH_BANKS]; - -#endif /*_LLD_NAND_*/ - - - diff --git a/drivers/staging/spectra/nand_regs.h b/drivers/staging/spectra/nand_regs.h deleted file mode 100644 index e192e4ae8c1e..000000000000 --- a/drivers/staging/spectra/nand_regs.h +++ /dev/null @@ -1,619 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#define DEVICE_RESET 0x0 -#define DEVICE_RESET__BANK0 0x0001 -#define DEVICE_RESET__BANK1 0x0002 -#define DEVICE_RESET__BANK2 0x0004 -#define DEVICE_RESET__BANK3 0x0008 - -#define TRANSFER_SPARE_REG 0x10 -#define TRANSFER_SPARE_REG__FLAG 0x0001 - -#define LOAD_WAIT_CNT 0x20 -#define LOAD_WAIT_CNT__VALUE 0xffff - -#define PROGRAM_WAIT_CNT 0x30 -#define PROGRAM_WAIT_CNT__VALUE 0xffff - -#define ERASE_WAIT_CNT 0x40 -#define ERASE_WAIT_CNT__VALUE 0xffff - -#define INT_MON_CYCCNT 0x50 -#define INT_MON_CYCCNT__VALUE 0xffff - -#define RB_PIN_ENABLED 0x60 -#define RB_PIN_ENABLED__BANK0 0x0001 -#define RB_PIN_ENABLED__BANK1 0x0002 -#define RB_PIN_ENABLED__BANK2 0x0004 -#define RB_PIN_ENABLED__BANK3 0x0008 - -#define MULTIPLANE_OPERATION 0x70 -#define MULTIPLANE_OPERATION__FLAG 0x0001 - -#define MULTIPLANE_READ_ENABLE 0x80 -#define MULTIPLANE_READ_ENABLE__FLAG 0x0001 - -#define COPYBACK_DISABLE 0x90 -#define COPYBACK_DISABLE__FLAG 0x0001 - -#define CACHE_WRITE_ENABLE 0xa0 -#define CACHE_WRITE_ENABLE__FLAG 0x0001 - -#define CACHE_READ_ENABLE 0xb0 -#define CACHE_READ_ENABLE__FLAG 0x0001 - -#define PREFETCH_MODE 0xc0 -#define PREFETCH_MODE__PREFETCH_EN 0x0001 -#define PREFETCH_MODE__PREFETCH_BURST_LENGTH 0xfff0 - -#define CHIP_ENABLE_DONT_CARE 0xd0 -#define CHIP_EN_DONT_CARE__FLAG 0x01 - -#define ECC_ENABLE 0xe0 -#define ECC_ENABLE__FLAG 0x0001 - -#define GLOBAL_INT_ENABLE 0xf0 -#define GLOBAL_INT_EN_FLAG 0x01 - -#define WE_2_RE 0x100 -#define WE_2_RE__VALUE 0x003f - -#define ADDR_2_DATA 0x110 -#define ADDR_2_DATA__VALUE 0x003f - -#define RE_2_WE 0x120 -#define RE_2_WE__VALUE 0x003f - -#define ACC_CLKS 0x130 -#define ACC_CLKS__VALUE 0x000f - -#define NUMBER_OF_PLANES 0x140 -#define NUMBER_OF_PLANES__VALUE 0x0007 - -#define PAGES_PER_BLOCK 0x150 -#define PAGES_PER_BLOCK__VALUE 0xffff - -#define DEVICE_WIDTH 0x160 -#define DEVICE_WIDTH__VALUE 0x0003 - -#define DEVICE_MAIN_AREA_SIZE 0x170 -#define DEVICE_MAIN_AREA_SIZE__VALUE 0xffff - -#define DEVICE_SPARE_AREA_SIZE 0x180 -#define DEVICE_SPARE_AREA_SIZE__VALUE 0xffff - -#define TWO_ROW_ADDR_CYCLES 0x190 -#define TWO_ROW_ADDR_CYCLES__FLAG 0x0001 - -#define MULTIPLANE_ADDR_RESTRICT 0x1a0 -#define MULTIPLANE_ADDR_RESTRICT__FLAG 0x0001 - -#define ECC_CORRECTION 0x1b0 -#define ECC_CORRECTION__VALUE 0x001f - -#define READ_MODE 0x1c0 -#define READ_MODE__VALUE 0x000f - -#define WRITE_MODE 0x1d0 -#define WRITE_MODE__VALUE 0x000f - -#define COPYBACK_MODE 0x1e0 -#define COPYBACK_MODE__VALUE 0x000f - -#define RDWR_EN_LO_CNT 0x1f0 -#define RDWR_EN_LO_CNT__VALUE 0x001f - -#define RDWR_EN_HI_CNT 0x200 -#define RDWR_EN_HI_CNT__VALUE 0x001f - -#define MAX_RD_DELAY 0x210 -#define MAX_RD_DELAY__VALUE 0x000f - -#define CS_SETUP_CNT 0x220 -#define CS_SETUP_CNT__VALUE 0x001f - -#define SPARE_AREA_SKIP_BYTES 0x230 -#define SPARE_AREA_SKIP_BYTES__VALUE 0x003f - -#define SPARE_AREA_MARKER 0x240 -#define SPARE_AREA_MARKER__VALUE 0xffff - -#define DEVICES_CONNECTED 0x250 -#define DEVICES_CONNECTED__VALUE 0x0007 - -#define DIE_MASK 0x260 -#define DIE_MASK__VALUE 0x00ff - -#define FIRST_BLOCK_OF_NEXT_PLANE 0x270 -#define FIRST_BLOCK_OF_NEXT_PLANE__VALUE 0xffff - -#define WRITE_PROTECT 0x280 -#define WRITE_PROTECT__FLAG 0x0001 - -#define RE_2_RE 0x290 -#define RE_2_RE__VALUE 0x003f - -#define MANUFACTURER_ID 0x300 -#define MANUFACTURER_ID__VALUE 0x00ff - -#define DEVICE_ID 0x310 -#define DEVICE_ID__VALUE 0x00ff - -#define DEVICE_PARAM_0 0x320 -#define DEVICE_PARAM_0__VALUE 0x00ff - -#define DEVICE_PARAM_1 0x330 -#define DEVICE_PARAM_1__VALUE 0x00ff - -#define DEVICE_PARAM_2 0x340 -#define DEVICE_PARAM_2__VALUE 0x00ff - -#define LOGICAL_PAGE_DATA_SIZE 0x350 -#define LOGICAL_PAGE_DATA_SIZE__VALUE 0xffff - -#define LOGICAL_PAGE_SPARE_SIZE 0x360 -#define LOGICAL_PAGE_SPARE_SIZE__VALUE 0xffff - -#define REVISION 0x370 -#define REVISION__VALUE 0xffff - -#define ONFI_DEVICE_FEATURES 0x380 -#define ONFI_DEVICE_FEATURES__VALUE 0x003f - -#define ONFI_OPTIONAL_COMMANDS 0x390 -#define ONFI_OPTIONAL_COMMANDS__VALUE 0x003f - -#define ONFI_TIMING_MODE 0x3a0 -#define ONFI_TIMING_MODE__VALUE 0x003f - -#define ONFI_PGM_CACHE_TIMING_MODE 0x3b0 -#define ONFI_PGM_CACHE_TIMING_MODE__VALUE 0x003f - -#define ONFI_DEVICE_NO_OF_LUNS 0x3c0 -#define ONFI_DEVICE_NO_OF_LUNS__NO_OF_LUNS 0x00ff -#define ONFI_DEVICE_NO_OF_LUNS__ONFI_DEVICE 0x0100 - -#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_L 0x3d0 -#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_L__VALUE 0xffff - -#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_U 0x3e0 -#define ONFI_DEVICE_NO_OF_BLOCKS_PER_LUN_U__VALUE 0xffff - -#define FEATURES 0x3f0 -#define FEATURES__N_BANKS 0x0003 -#define FEATURES__ECC_MAX_ERR 0x003c -#define FEATURES__DMA 0x0040 -#define FEATURES__CMD_DMA 0x0080 -#define FEATURES__PARTITION 0x0100 -#define FEATURES__XDMA_SIDEBAND 0x0200 -#define FEATURES__GPREG 0x0400 -#define FEATURES__INDEX_ADDR 0x0800 - -#define TRANSFER_MODE 0x400 -#define TRANSFER_MODE__VALUE 0x0003 - -#define INTR_STATUS0 0x410 -#define INTR_STATUS0__ECC_TRANSACTION_DONE 0x0001 -#define INTR_STATUS0__ECC_ERR 0x0002 -#define INTR_STATUS0__DMA_CMD_COMP 0x0004 -#define INTR_STATUS0__TIME_OUT 0x0008 -#define INTR_STATUS0__PROGRAM_FAIL 0x0010 -#define INTR_STATUS0__ERASE_FAIL 0x0020 -#define INTR_STATUS0__LOAD_COMP 0x0040 -#define INTR_STATUS0__PROGRAM_COMP 0x0080 -#define INTR_STATUS0__ERASE_COMP 0x0100 -#define INTR_STATUS0__PIPE_CPYBCK_CMD_COMP 0x0200 -#define INTR_STATUS0__LOCKED_BLK 0x0400 -#define INTR_STATUS0__UNSUP_CMD 0x0800 -#define INTR_STATUS0__INT_ACT 0x1000 -#define INTR_STATUS0__RST_COMP 0x2000 -#define INTR_STATUS0__PIPE_CMD_ERR 0x4000 -#define INTR_STATUS0__PAGE_XFER_INC 0x8000 - -#define INTR_EN0 0x420 -#define INTR_EN0__ECC_TRANSACTION_DONE 0x0001 -#define INTR_EN0__ECC_ERR 0x0002 -#define INTR_EN0__DMA_CMD_COMP 0x0004 -#define INTR_EN0__TIME_OUT 0x0008 -#define INTR_EN0__PROGRAM_FAIL 0x0010 -#define INTR_EN0__ERASE_FAIL 0x0020 -#define INTR_EN0__LOAD_COMP 0x0040 -#define INTR_EN0__PROGRAM_COMP 0x0080 -#define INTR_EN0__ERASE_COMP 0x0100 -#define INTR_EN0__PIPE_CPYBCK_CMD_COMP 0x0200 -#define INTR_EN0__LOCKED_BLK 0x0400 -#define INTR_EN0__UNSUP_CMD 0x0800 -#define INTR_EN0__INT_ACT 0x1000 -#define INTR_EN0__RST_COMP 0x2000 -#define INTR_EN0__PIPE_CMD_ERR 0x4000 -#define INTR_EN0__PAGE_XFER_INC 0x8000 - -#define PAGE_CNT0 0x430 -#define PAGE_CNT0__VALUE 0x00ff - -#define ERR_PAGE_ADDR0 0x440 -#define ERR_PAGE_ADDR0__VALUE 0xffff - -#define ERR_BLOCK_ADDR0 0x450 -#define ERR_BLOCK_ADDR0__VALUE 0xffff - -#define INTR_STATUS1 0x460 -#define INTR_STATUS1__ECC_TRANSACTION_DONE 0x0001 -#define INTR_STATUS1__ECC_ERR 0x0002 -#define INTR_STATUS1__DMA_CMD_COMP 0x0004 -#define INTR_STATUS1__TIME_OUT 0x0008 -#define INTR_STATUS1__PROGRAM_FAIL 0x0010 -#define INTR_STATUS1__ERASE_FAIL 0x0020 -#define INTR_STATUS1__LOAD_COMP 0x0040 -#define INTR_STATUS1__PROGRAM_COMP 0x0080 -#define INTR_STATUS1__ERASE_COMP 0x0100 -#define INTR_STATUS1__PIPE_CPYBCK_CMD_COMP 0x0200 -#define INTR_STATUS1__LOCKED_BLK 0x0400 -#define INTR_STATUS1__UNSUP_CMD 0x0800 -#define INTR_STATUS1__INT_ACT 0x1000 -#define INTR_STATUS1__RST_COMP 0x2000 -#define INTR_STATUS1__PIPE_CMD_ERR 0x4000 -#define INTR_STATUS1__PAGE_XFER_INC 0x8000 - -#define INTR_EN1 0x470 -#define INTR_EN1__ECC_TRANSACTION_DONE 0x0001 -#define INTR_EN1__ECC_ERR 0x0002 -#define INTR_EN1__DMA_CMD_COMP 0x0004 -#define INTR_EN1__TIME_OUT 0x0008 -#define INTR_EN1__PROGRAM_FAIL 0x0010 -#define INTR_EN1__ERASE_FAIL 0x0020 -#define INTR_EN1__LOAD_COMP 0x0040 -#define INTR_EN1__PROGRAM_COMP 0x0080 -#define INTR_EN1__ERASE_COMP 0x0100 -#define INTR_EN1__PIPE_CPYBCK_CMD_COMP 0x0200 -#define INTR_EN1__LOCKED_BLK 0x0400 -#define INTR_EN1__UNSUP_CMD 0x0800 -#define INTR_EN1__INT_ACT 0x1000 -#define INTR_EN1__RST_COMP 0x2000 -#define INTR_EN1__PIPE_CMD_ERR 0x4000 -#define INTR_EN1__PAGE_XFER_INC 0x8000 - -#define PAGE_CNT1 0x480 -#define PAGE_CNT1__VALUE 0x00ff - -#define ERR_PAGE_ADDR1 0x490 -#define ERR_PAGE_ADDR1__VALUE 0xffff - -#define ERR_BLOCK_ADDR1 0x4a0 -#define ERR_BLOCK_ADDR1__VALUE 0xffff - -#define INTR_STATUS2 0x4b0 -#define INTR_STATUS2__ECC_TRANSACTION_DONE 0x0001 -#define INTR_STATUS2__ECC_ERR 0x0002 -#define INTR_STATUS2__DMA_CMD_COMP 0x0004 -#define INTR_STATUS2__TIME_OUT 0x0008 -#define INTR_STATUS2__PROGRAM_FAIL 0x0010 -#define INTR_STATUS2__ERASE_FAIL 0x0020 -#define INTR_STATUS2__LOAD_COMP 0x0040 -#define INTR_STATUS2__PROGRAM_COMP 0x0080 -#define INTR_STATUS2__ERASE_COMP 0x0100 -#define INTR_STATUS2__PIPE_CPYBCK_CMD_COMP 0x0200 -#define INTR_STATUS2__LOCKED_BLK 0x0400 -#define INTR_STATUS2__UNSUP_CMD 0x0800 -#define INTR_STATUS2__INT_ACT 0x1000 -#define INTR_STATUS2__RST_COMP 0x2000 -#define INTR_STATUS2__PIPE_CMD_ERR 0x4000 -#define INTR_STATUS2__PAGE_XFER_INC 0x8000 - -#define INTR_EN2 0x4c0 -#define INTR_EN2__ECC_TRANSACTION_DONE 0x0001 -#define INTR_EN2__ECC_ERR 0x0002 -#define INTR_EN2__DMA_CMD_COMP 0x0004 -#define INTR_EN2__TIME_OUT 0x0008 -#define INTR_EN2__PROGRAM_FAIL 0x0010 -#define INTR_EN2__ERASE_FAIL 0x0020 -#define INTR_EN2__LOAD_COMP 0x0040 -#define INTR_EN2__PROGRAM_COMP 0x0080 -#define INTR_EN2__ERASE_COMP 0x0100 -#define INTR_EN2__PIPE_CPYBCK_CMD_COMP 0x0200 -#define INTR_EN2__LOCKED_BLK 0x0400 -#define INTR_EN2__UNSUP_CMD 0x0800 -#define INTR_EN2__INT_ACT 0x1000 -#define INTR_EN2__RST_COMP 0x2000 -#define INTR_EN2__PIPE_CMD_ERR 0x4000 -#define INTR_EN2__PAGE_XFER_INC 0x8000 - -#define PAGE_CNT2 0x4d0 -#define PAGE_CNT2__VALUE 0x00ff - -#define ERR_PAGE_ADDR2 0x4e0 -#define ERR_PAGE_ADDR2__VALUE 0xffff - -#define ERR_BLOCK_ADDR2 0x4f0 -#define ERR_BLOCK_ADDR2__VALUE 0xffff - -#define INTR_STATUS3 0x500 -#define INTR_STATUS3__ECC_TRANSACTION_DONE 0x0001 -#define INTR_STATUS3__ECC_ERR 0x0002 -#define INTR_STATUS3__DMA_CMD_COMP 0x0004 -#define INTR_STATUS3__TIME_OUT 0x0008 -#define INTR_STATUS3__PROGRAM_FAIL 0x0010 -#define INTR_STATUS3__ERASE_FAIL 0x0020 -#define INTR_STATUS3__LOAD_COMP 0x0040 -#define INTR_STATUS3__PROGRAM_COMP 0x0080 -#define INTR_STATUS3__ERASE_COMP 0x0100 -#define INTR_STATUS3__PIPE_CPYBCK_CMD_COMP 0x0200 -#define INTR_STATUS3__LOCKED_BLK 0x0400 -#define INTR_STATUS3__UNSUP_CMD 0x0800 -#define INTR_STATUS3__INT_ACT 0x1000 -#define INTR_STATUS3__RST_COMP 0x2000 -#define INTR_STATUS3__PIPE_CMD_ERR 0x4000 -#define INTR_STATUS3__PAGE_XFER_INC 0x8000 - -#define INTR_EN3 0x510 -#define INTR_EN3__ECC_TRANSACTION_DONE 0x0001 -#define INTR_EN3__ECC_ERR 0x0002 -#define INTR_EN3__DMA_CMD_COMP 0x0004 -#define INTR_EN3__TIME_OUT 0x0008 -#define INTR_EN3__PROGRAM_FAIL 0x0010 -#define INTR_EN3__ERASE_FAIL 0x0020 -#define INTR_EN3__LOAD_COMP 0x0040 -#define INTR_EN3__PROGRAM_COMP 0x0080 -#define INTR_EN3__ERASE_COMP 0x0100 -#define INTR_EN3__PIPE_CPYBCK_CMD_COMP 0x0200 -#define INTR_EN3__LOCKED_BLK 0x0400 -#define INTR_EN3__UNSUP_CMD 0x0800 -#define INTR_EN3__INT_ACT 0x1000 -#define INTR_EN3__RST_COMP 0x2000 -#define INTR_EN3__PIPE_CMD_ERR 0x4000 -#define INTR_EN3__PAGE_XFER_INC 0x8000 - -#define PAGE_CNT3 0x520 -#define PAGE_CNT3__VALUE 0x00ff - -#define ERR_PAGE_ADDR3 0x530 -#define ERR_PAGE_ADDR3__VALUE 0xffff - -#define ERR_BLOCK_ADDR3 0x540 -#define ERR_BLOCK_ADDR3__VALUE 0xffff - -#define DATA_INTR 0x550 -#define DATA_INTR__WRITE_SPACE_AV 0x0001 -#define DATA_INTR__READ_DATA_AV 0x0002 - -#define DATA_INTR_EN 0x560 -#define DATA_INTR_EN__WRITE_SPACE_AV 0x0001 -#define DATA_INTR_EN__READ_DATA_AV 0x0002 - -#define GPREG_0 0x570 -#define GPREG_0__VALUE 0xffff - -#define GPREG_1 0x580 -#define GPREG_1__VALUE 0xffff - -#define GPREG_2 0x590 -#define GPREG_2__VALUE 0xffff - -#define GPREG_3 0x5a0 -#define GPREG_3__VALUE 0xffff - -#define ECC_THRESHOLD 0x600 -#define ECC_THRESHOLD__VALUE 0x03ff - -#define ECC_ERROR_BLOCK_ADDRESS 0x610 -#define ECC_ERROR_BLOCK_ADDRESS__VALUE 0xffff - -#define ECC_ERROR_PAGE_ADDRESS 0x620 -#define ECC_ERROR_PAGE_ADDRESS__VALUE 0x0fff -#define ECC_ERROR_PAGE_ADDRESS__BANK 0xf000 - -#define ECC_ERROR_ADDRESS 0x630 -#define ECC_ERROR_ADDRESS__OFFSET 0x0fff -#define ECC_ERROR_ADDRESS__SECTOR_NR 0xf000 - -#define ERR_CORRECTION_INFO 0x640 -#define ERR_CORRECTION_INFO__BYTEMASK 0x00ff -#define ERR_CORRECTION_INFO__DEVICE_NR 0x0f00 -#define ERR_CORRECTION_INFO__ERROR_TYPE 0x4000 -#define ERR_CORRECTION_INFO__LAST_ERR_INFO 0x8000 - -#define DMA_ENABLE 0x700 -#define DMA_ENABLE__FLAG 0x0001 - -#define IGNORE_ECC_DONE 0x710 -#define IGNORE_ECC_DONE__FLAG 0x0001 - -#define DMA_INTR 0x720 -#define DMA_INTR__TARGET_ERROR 0x0001 -#define DMA_INTR__DESC_COMP_CHANNEL0 0x0002 -#define DMA_INTR__DESC_COMP_CHANNEL1 0x0004 -#define DMA_INTR__DESC_COMP_CHANNEL2 0x0008 -#define DMA_INTR__DESC_COMP_CHANNEL3 0x0010 -#define DMA_INTR__MEMCOPY_DESC_COMP 0x0020 - -#define DMA_INTR_EN 0x730 -#define DMA_INTR_EN__TARGET_ERROR 0x0001 -#define DMA_INTR_EN__DESC_COMP_CHANNEL0 0x0002 -#define DMA_INTR_EN__DESC_COMP_CHANNEL1 0x0004 -#define DMA_INTR_EN__DESC_COMP_CHANNEL2 0x0008 -#define DMA_INTR_EN__DESC_COMP_CHANNEL3 0x0010 -#define DMA_INTR_EN__MEMCOPY_DESC_COMP 0x0020 - -#define TARGET_ERR_ADDR_LO 0x740 -#define TARGET_ERR_ADDR_LO__VALUE 0xffff - -#define TARGET_ERR_ADDR_HI 0x750 -#define TARGET_ERR_ADDR_HI__VALUE 0xffff - -#define CHNL_ACTIVE 0x760 -#define CHNL_ACTIVE__CHANNEL0 0x0001 -#define CHNL_ACTIVE__CHANNEL1 0x0002 -#define CHNL_ACTIVE__CHANNEL2 0x0004 -#define CHNL_ACTIVE__CHANNEL3 0x0008 - -#define ACTIVE_SRC_ID 0x800 -#define ACTIVE_SRC_ID__VALUE 0x00ff - -#define PTN_INTR 0x810 -#define PTN_INTR__CONFIG_ERROR 0x0001 -#define PTN_INTR__ACCESS_ERROR_BANK0 0x0002 -#define PTN_INTR__ACCESS_ERROR_BANK1 0x0004 -#define PTN_INTR__ACCESS_ERROR_BANK2 0x0008 -#define PTN_INTR__ACCESS_ERROR_BANK3 0x0010 -#define PTN_INTR__REG_ACCESS_ERROR 0x0020 - -#define PTN_INTR_EN 0x820 -#define PTN_INTR_EN__CONFIG_ERROR 0x0001 -#define PTN_INTR_EN__ACCESS_ERROR_BANK0 0x0002 -#define PTN_INTR_EN__ACCESS_ERROR_BANK1 0x0004 -#define PTN_INTR_EN__ACCESS_ERROR_BANK2 0x0008 -#define PTN_INTR_EN__ACCESS_ERROR_BANK3 0x0010 -#define PTN_INTR_EN__REG_ACCESS_ERROR 0x0020 - -#define PERM_SRC_ID_0 0x830 -#define PERM_SRC_ID_0__SRCID 0x00ff -#define PERM_SRC_ID_0__DIRECT_ACCESS_ACTIVE 0x0800 -#define PERM_SRC_ID_0__WRITE_ACTIVE 0x2000 -#define PERM_SRC_ID_0__READ_ACTIVE 0x4000 -#define PERM_SRC_ID_0__PARTITION_VALID 0x8000 - -#define MIN_BLK_ADDR_0 0x840 -#define MIN_BLK_ADDR_0__VALUE 0xffff - -#define MAX_BLK_ADDR_0 0x850 -#define MAX_BLK_ADDR_0__VALUE 0xffff - -#define MIN_MAX_BANK_0 0x860 -#define MIN_MAX_BANK_0__MIN_VALUE 0x0003 -#define MIN_MAX_BANK_0__MAX_VALUE 0x000c - -#define PERM_SRC_ID_1 0x870 -#define PERM_SRC_ID_1__SRCID 0x00ff -#define PERM_SRC_ID_1__DIRECT_ACCESS_ACTIVE 0x0800 -#define PERM_SRC_ID_1__WRITE_ACTIVE 0x2000 -#define PERM_SRC_ID_1__READ_ACTIVE 0x4000 -#define PERM_SRC_ID_1__PARTITION_VALID 0x8000 - -#define MIN_BLK_ADDR_1 0x880 -#define MIN_BLK_ADDR_1__VALUE 0xffff - -#define MAX_BLK_ADDR_1 0x890 -#define MAX_BLK_ADDR_1__VALUE 0xffff - -#define MIN_MAX_BANK_1 0x8a0 -#define MIN_MAX_BANK_1__MIN_VALUE 0x0003 -#define MIN_MAX_BANK_1__MAX_VALUE 0x000c - -#define PERM_SRC_ID_2 0x8b0 -#define PERM_SRC_ID_2__SRCID 0x00ff -#define PERM_SRC_ID_2__DIRECT_ACCESS_ACTIVE 0x0800 -#define PERM_SRC_ID_2__WRITE_ACTIVE 0x2000 -#define PERM_SRC_ID_2__READ_ACTIVE 0x4000 -#define PERM_SRC_ID_2__PARTITION_VALID 0x8000 - -#define MIN_BLK_ADDR_2 0x8c0 -#define MIN_BLK_ADDR_2__VALUE 0xffff - -#define MAX_BLK_ADDR_2 0x8d0 -#define MAX_BLK_ADDR_2__VALUE 0xffff - -#define MIN_MAX_BANK_2 0x8e0 -#define MIN_MAX_BANK_2__MIN_VALUE 0x0003 -#define MIN_MAX_BANK_2__MAX_VALUE 0x000c - -#define PERM_SRC_ID_3 0x8f0 -#define PERM_SRC_ID_3__SRCID 0x00ff -#define PERM_SRC_ID_3__DIRECT_ACCESS_ACTIVE 0x0800 -#define PERM_SRC_ID_3__WRITE_ACTIVE 0x2000 -#define PERM_SRC_ID_3__READ_ACTIVE 0x4000 -#define PERM_SRC_ID_3__PARTITION_VALID 0x8000 - -#define MIN_BLK_ADDR_3 0x900 -#define MIN_BLK_ADDR_3__VALUE 0xffff - -#define MAX_BLK_ADDR_3 0x910 -#define MAX_BLK_ADDR_3__VALUE 0xffff - -#define MIN_MAX_BANK_3 0x920 -#define MIN_MAX_BANK_3__MIN_VALUE 0x0003 -#define MIN_MAX_BANK_3__MAX_VALUE 0x000c - -#define PERM_SRC_ID_4 0x930 -#define PERM_SRC_ID_4__SRCID 0x00ff -#define PERM_SRC_ID_4__DIRECT_ACCESS_ACTIVE 0x0800 -#define PERM_SRC_ID_4__WRITE_ACTIVE 0x2000 -#define PERM_SRC_ID_4__READ_ACTIVE 0x4000 -#define PERM_SRC_ID_4__PARTITION_VALID 0x8000 - -#define MIN_BLK_ADDR_4 0x940 -#define MIN_BLK_ADDR_4__VALUE 0xffff - -#define MAX_BLK_ADDR_4 0x950 -#define MAX_BLK_ADDR_4__VALUE 0xffff - -#define MIN_MAX_BANK_4 0x960 -#define MIN_MAX_BANK_4__MIN_VALUE 0x0003 -#define MIN_MAX_BANK_4__MAX_VALUE 0x000c - -#define PERM_SRC_ID_5 0x970 -#define PERM_SRC_ID_5__SRCID 0x00ff -#define PERM_SRC_ID_5__DIRECT_ACCESS_ACTIVE 0x0800 -#define PERM_SRC_ID_5__WRITE_ACTIVE 0x2000 -#define PERM_SRC_ID_5__READ_ACTIVE 0x4000 -#define PERM_SRC_ID_5__PARTITION_VALID 0x8000 - -#define MIN_BLK_ADDR_5 0x980 -#define MIN_BLK_ADDR_5__VALUE 0xffff - -#define MAX_BLK_ADDR_5 0x990 -#define MAX_BLK_ADDR_5__VALUE 0xffff - -#define MIN_MAX_BANK_5 0x9a0 -#define MIN_MAX_BANK_5__MIN_VALUE 0x0003 -#define MIN_MAX_BANK_5__MAX_VALUE 0x000c - -#define PERM_SRC_ID_6 0x9b0 -#define PERM_SRC_ID_6__SRCID 0x00ff -#define PERM_SRC_ID_6__DIRECT_ACCESS_ACTIVE 0x0800 -#define PERM_SRC_ID_6__WRITE_ACTIVE 0x2000 -#define PERM_SRC_ID_6__READ_ACTIVE 0x4000 -#define PERM_SRC_ID_6__PARTITION_VALID 0x8000 - -#define MIN_BLK_ADDR_6 0x9c0 -#define MIN_BLK_ADDR_6__VALUE 0xffff - -#define MAX_BLK_ADDR_6 0x9d0 -#define MAX_BLK_ADDR_6__VALUE 0xffff - -#define MIN_MAX_BANK_6 0x9e0 -#define MIN_MAX_BANK_6__MIN_VALUE 0x0003 -#define MIN_MAX_BANK_6__MAX_VALUE 0x000c - -#define PERM_SRC_ID_7 0x9f0 -#define PERM_SRC_ID_7__SRCID 0x00ff -#define PERM_SRC_ID_7__DIRECT_ACCESS_ACTIVE 0x0800 -#define PERM_SRC_ID_7__WRITE_ACTIVE 0x2000 -#define PERM_SRC_ID_7__READ_ACTIVE 0x4000 -#define PERM_SRC_ID_7__PARTITION_VALID 0x8000 - -#define MIN_BLK_ADDR_7 0xa00 -#define MIN_BLK_ADDR_7__VALUE 0xffff - -#define MAX_BLK_ADDR_7 0xa10 -#define MAX_BLK_ADDR_7__VALUE 0xffff - -#define MIN_MAX_BANK_7 0xa20 -#define MIN_MAX_BANK_7__MIN_VALUE 0x0003 -#define MIN_MAX_BANK_7__MAX_VALUE 0x000c diff --git a/drivers/staging/spectra/spectraswconfig.h b/drivers/staging/spectra/spectraswconfig.h deleted file mode 100644 index 17259469e955..000000000000 --- a/drivers/staging/spectra/spectraswconfig.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * NAND Flash Controller Device Driver - * Copyright (c) 2009, Intel Corporation and its suppliers. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef _SPECTRASWCONFIG_ -#define _SPECTRASWCONFIG_ - -/* NAND driver version */ -#define GLOB_VERSION "driver version 20100311" - - -/***** Common Parameters *****/ -#define RETRY_TIMES 3 - -#define READ_BADBLOCK_INFO 1 -#define READBACK_VERIFY 0 -#define AUTO_FORMAT_FLASH 0 - -/***** Cache Parameters *****/ -#define CACHE_ITEM_NUM 128 -#define BLK_NUM_FOR_L2_CACHE 16 - -/***** Block Table Parameters *****/ -#define BLOCK_TABLE_INDEX 0 - -/***** Wear Leveling Parameters *****/ -#define WEAR_LEVELING_GATE 0x10 -#define WEAR_LEVELING_BLOCK_NUM 10 - -#define DEBUG_BNDRY 0 - -/***** Product Feature Support *****/ -#define FLASH_EMU defined(CONFIG_SPECTRA_EMU) -#define FLASH_NAND defined(CONFIG_SPECTRA_MRST_HW) -#define FLASH_MTD defined(CONFIG_SPECTRA_MTD) -#define CMD_DMA defined(CONFIG_SPECTRA_MRST_HW_DMA) - -#define SPECTRA_PARTITION_ID 0 - -/* Enable this macro if the number of flash blocks is larger than 16K. */ -#define SUPPORT_LARGE_BLOCKNUM 1 - -/**** Block Table and Reserved Block Parameters *****/ -#define SPECTRA_START_BLOCK 3 -//#define NUM_FREE_BLOCKS_GATE 30 -#define NUM_FREE_BLOCKS_GATE 60 - -/**** Hardware Parameters ****/ -#define GLOB_HWCTL_REG_BASE 0xFFA40000 -#define GLOB_HWCTL_REG_SIZE 4096 - -#define GLOB_HWCTL_MEM_BASE 0xFFA48000 -#define GLOB_HWCTL_MEM_SIZE 4096 - -/* KBV - Updated to LNW scratch register address */ -#define SCRATCH_REG_ADDR 0xFF108018 -#define SCRATCH_REG_SIZE 64 - -#define GLOB_HWCTL_DEFAULT_BLKS 2048 - -#define SUPPORT_15BITECC 1 -#define SUPPORT_8BITECC 1 - -#define ONFI_BLOOM_TIME 0 -#define MODE5_WORKAROUND 1 - -#endif /*_SPECTRASWCONFIG_*/ From cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Sat, 12 Nov 2011 12:09:40 -0600 Subject: [PATCH 097/365] staging: add omapdrm DRM/KMS driver for TI OMAP platforms A DRM display driver for TI OMAP platform. Similar to omapfb (fbdev) and omap_vout (v4l2 display) drivers in the past, this driver uses the DSS2 driver to access the display hardware, including support for HDMI, DVI, and various types of LCD panels. And it implements GEM support for buffer allocation (for KMS as well as offscreen buffers used by the xf86-video-omap userspace xorg driver). The driver maps CRTCs to overlays, encoders to overlay-managers, and connectors to dssdev's. Note that this arrangement might change slightly when support for drm_plane overlays is added. For GEM support, non-scanout buffers are using the shmem backed pages provided by GEM core (In drm_gem_object_init()). In the case of scanout buffers, which need to be physically contiguous, those are allocated with CMA and use drm_gem_private_object_init(). See userspace xorg driver: git://github.com/robclark/xf86-video-omap.git Refer to this link for CMA (Continuous Memory Allocator): http://lkml.org/lkml/2011/8/19/302 Links to previous versions of the patch: v1: http://lwn.net/Articles/458137/ v2: http://patches.linaro.org/4156/ v3: http://patches.linaro.org/4688/ v4: http://patches.linaro.org/4791/ History: v5: move headers from include/drm at Greg KH's request, minor rebasing on 3.2-rc1, pull in private copies of drm_gem_{get,put}_pages() because "drm/gem: add functions to get/put pages" patch is not merged yet v4: bit of rework of encoder/connector _dpms() code, modeset_init() rework to not use nested functions, update TODO.txt v3: minor cleanups, improved error handling for dev_load(), some minor API changes that will be needed later for tiled buffer support v2: replace omap_vram with CMA for scanout buffer allocation, remove unneeded functions, use dma_addr_t for physical addresses, error handling cleanup, refactor attach/detach pages into common drm functions, split non-userspace-facing API into omap_priv.h, remove plugin API v1: original Signed-off-by: Rob Clark Acked-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 2 + drivers/staging/Makefile | 1 + drivers/staging/omapdrm/Kconfig | 25 + drivers/staging/omapdrm/Makefile | 12 + drivers/staging/omapdrm/TODO | 32 + drivers/staging/omapdrm/omap_connector.c | 371 ++++++++++ drivers/staging/omapdrm/omap_crtc.c | 327 +++++++++ drivers/staging/omapdrm/omap_drm.h | 123 ++++ drivers/staging/omapdrm/omap_drv.c | 810 +++++++++++++++++++++ drivers/staging/omapdrm/omap_drv.h | 124 ++++ drivers/staging/omapdrm/omap_encoder.c | 172 +++++ drivers/staging/omapdrm/omap_fb.c | 261 +++++++ drivers/staging/omapdrm/omap_fbdev.c | 304 ++++++++ drivers/staging/omapdrm/omap_gem.c | 774 ++++++++++++++++++++ drivers/staging/omapdrm/omap_gem_helpers.c | 114 +++ drivers/staging/omapdrm/omap_priv.h | 42 ++ drivers/video/omap2/omapfb/Kconfig | 2 +- 17 files changed, 3495 insertions(+), 1 deletion(-) create mode 100644 drivers/staging/omapdrm/Kconfig create mode 100644 drivers/staging/omapdrm/Makefile create mode 100644 drivers/staging/omapdrm/TODO create mode 100644 drivers/staging/omapdrm/omap_connector.c create mode 100644 drivers/staging/omapdrm/omap_crtc.c create mode 100644 drivers/staging/omapdrm/omap_drm.h create mode 100644 drivers/staging/omapdrm/omap_drv.c create mode 100644 drivers/staging/omapdrm/omap_drv.h create mode 100644 drivers/staging/omapdrm/omap_encoder.c create mode 100644 drivers/staging/omapdrm/omap_fb.c create mode 100644 drivers/staging/omapdrm/omap_fbdev.c create mode 100644 drivers/staging/omapdrm/omap_gem.c create mode 100644 drivers/staging/omapdrm/omap_gem_helpers.c create mode 100644 drivers/staging/omapdrm/omap_priv.h diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 0f1e5ca99448..985937a9f3a6 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -130,4 +130,6 @@ source "drivers/staging/nvec/Kconfig" source "drivers/staging/media/Kconfig" +source "drivers/staging/omapdrm/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 6f886bd9e782..ba3fb8d7bf64 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -56,3 +56,4 @@ obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += ste_rmi4/ obj-$(CONFIG_DRM_PSB) += gma500/ obj-$(CONFIG_INTEL_MEI) += mei/ obj-$(CONFIG_MFD_NVEC) += nvec/ +obj-$(CONFIG_DRM_OMAP) += omapdrm/ diff --git a/drivers/staging/omapdrm/Kconfig b/drivers/staging/omapdrm/Kconfig new file mode 100644 index 000000000000..81a7cba4a0c5 --- /dev/null +++ b/drivers/staging/omapdrm/Kconfig @@ -0,0 +1,25 @@ + +config DRM_OMAP + tristate "OMAP DRM" + depends on DRM && !CONFIG_FB_OMAP2 + depends on ARCH_OMAP2PLUS + select DRM_KMS_HELPER + select OMAP2_DSS + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + select FB_SYS_FOPS + default n + help + DRM display driver for OMAP2/3/4 based boards. + +config DRM_OMAP_NUM_CRTCS + int "Number of CRTCs" + range 1 10 + default 1 if ARCH_OMAP2 || ARCH_OMAP3 + default 2 if ARCH_OMAP4 + depends on DRM_OMAP + help + Select the number of video overlays which can be used as framebuffers. + The remaining overlays are reserved for video. + diff --git a/drivers/staging/omapdrm/Makefile b/drivers/staging/omapdrm/Makefile new file mode 100644 index 000000000000..4aa9a2f34d4a --- /dev/null +++ b/drivers/staging/omapdrm/Makefile @@ -0,0 +1,12 @@ +# +# Makefile for the drm device driver. This driver provides support for the +# Direct Rendering Infrastructure (DRI) +# + +ccflags-y := -Iinclude/drm -Werror +omapdrm-y := omap_drv.o omap_crtc.o omap_encoder.o omap_connector.o omap_fb.o omap_fbdev.o omap_gem.o + +# temporary: +omapdrm-y += omap_gem_helpers.o + +obj-$(CONFIG_DRM_OMAP) += omapdrm.o diff --git a/drivers/staging/omapdrm/TODO b/drivers/staging/omapdrm/TODO new file mode 100644 index 000000000000..17781c954a83 --- /dev/null +++ b/drivers/staging/omapdrm/TODO @@ -0,0 +1,32 @@ +TODO +. check error handling/cleanup paths +. add drm_plane / overlay support +. add video decode/encode support (via syslink3 + codec-engine) +. still some rough edges with flipping.. event back to userspace should + really come after VSYNC interrupt +. where should we do eviction (detatch_pages())? We aren't necessarily + accessing the pages via a GART, so maybe we need some other threshold + to put a cap on the # of pages that can be pin'd. (It is mostly only + of interest in case you have a swap partition/file.. which a lot of + these devices do not.. but it doesn't hurt for the driver to do the + right thing anyways.) + . Use mm_shrinker to trigger unpinning pages. Need to figure out how + to handle next issue first (I think?) + . Note TTM already has some mm_shrinker stuff.. maybe an argument to + move to TTM? Or maybe something that could be factored out in common? +. GEM/shmem backed pages can have existing mappings (kernel linear map, + etc..), which isn't really ideal. +. Revisit GEM sync object infrastructure.. TTM has some framework for this + already. Possibly this could be refactored out and made more common? + There should be some way to do this with less wheel-reinvention. +. Review DSS vs KMS mismatches. The omap_dss_device is sort of part encoder, + part connector. Which results in a bit of duct tape to fwd calls from + encoder to connector. Possibly this could be done a bit better. + +Userspace: +. git://github.com/robclark/xf86-video-omap.git + +Currently tested on +. OMAP3530 beagleboard +. OMAP4430 pandaboard +. OMAP4460 pandaboard diff --git a/drivers/staging/omapdrm/omap_connector.c b/drivers/staging/omapdrm/omap_connector.c new file mode 100644 index 000000000000..5e2856c0e0bb --- /dev/null +++ b/drivers/staging/omapdrm/omap_connector.c @@ -0,0 +1,371 @@ +/* + * drivers/staging/omapdrm/omap_connector.c + * + * Copyright (C) 2011 Texas Instruments + * Author: Rob Clark + * + * 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. + * + * 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, see . + */ + +#include "omap_drv.h" + +#include "drm_crtc.h" +#include "drm_crtc_helper.h" + +/* + * connector funcs + */ + +#define to_omap_connector(x) container_of(x, struct omap_connector, base) + +struct omap_connector { + struct drm_connector base; + struct omap_dss_device *dssdev; +}; + +static inline void copy_timings_omap_to_drm(struct drm_display_mode *mode, + struct omap_video_timings *timings) +{ + mode->clock = timings->pixel_clock; + + mode->hdisplay = timings->x_res; + mode->hsync_start = mode->hdisplay + timings->hfp; + mode->hsync_end = mode->hsync_start + timings->hsw; + mode->htotal = mode->hsync_end + timings->hbp; + + mode->vdisplay = timings->y_res; + mode->vsync_start = mode->vdisplay + timings->vfp; + mode->vsync_end = mode->vsync_start + timings->vsw; + mode->vtotal = mode->vsync_end + timings->vbp; + + /* note: whether or not it is interlaced, +/- h/vsync, etc, + * which should be set in the mode flags, is not exposed in + * the omap_video_timings struct.. but hdmi driver tracks + * those separately so all we have to have to set the mode + * is the way to recover these timings values, and the + * omap_dss_driver would do the rest. + */ +} + +static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings, + struct drm_display_mode *mode) +{ + timings->pixel_clock = mode->clock; + + timings->x_res = mode->hdisplay; + timings->hfp = mode->hsync_start - mode->hdisplay; + timings->hsw = mode->hsync_end - mode->hsync_start; + timings->hbp = mode->htotal - mode->hsync_end; + + timings->y_res = mode->vdisplay; + timings->vfp = mode->vsync_start - mode->vdisplay; + timings->vsw = mode->vsync_end - mode->vsync_start; + timings->vbp = mode->vtotal - mode->vsync_end; +} + +static void omap_connector_dpms(struct drm_connector *connector, int mode) +{ + struct omap_connector *omap_connector = to_omap_connector(connector); + struct omap_dss_device *dssdev = omap_connector->dssdev; + int old_dpms; + + DBG("%s: %d", dssdev->name, mode); + + old_dpms = connector->dpms; + + /* from off to on, do from crtc to connector */ + if (mode < old_dpms) + drm_helper_connector_dpms(connector, mode); + + if (mode == DRM_MODE_DPMS_ON) { + /* store resume info for suspended displays */ + switch (dssdev->state) { + case OMAP_DSS_DISPLAY_SUSPENDED: + dssdev->activate_after_resume = true; + break; + case OMAP_DSS_DISPLAY_DISABLED: { + int ret = dssdev->driver->enable(dssdev); + if (ret) { + DBG("%s: failed to enable: %d", + dssdev->name, ret); + dssdev->driver->disable(dssdev); + } + break; + } + default: + break; + } + } else { + /* TODO */ + } + + /* from on to off, do from connector to crtc */ + if (mode > old_dpms) + drm_helper_connector_dpms(connector, mode); +} + +enum drm_connector_status omap_connector_detect( + struct drm_connector *connector, bool force) +{ + struct omap_connector *omap_connector = to_omap_connector(connector); + struct omap_dss_device *dssdev = omap_connector->dssdev; + struct omap_dss_driver *dssdrv = dssdev->driver; + enum drm_connector_status ret; + + if (dssdrv->detect) { + if (dssdrv->detect(dssdev)) { + ret = connector_status_connected; + } else { + ret = connector_status_disconnected; + } + } else { + ret = connector_status_unknown; + } + + VERB("%s: %d (force=%d)", omap_connector->dssdev->name, ret, force); + + return ret; +} + +static void omap_connector_destroy(struct drm_connector *connector) +{ + struct omap_connector *omap_connector = to_omap_connector(connector); + struct omap_dss_device *dssdev = omap_connector->dssdev; + + dssdev->driver->disable(dssdev); + + DBG("%s", omap_connector->dssdev->name); + drm_sysfs_connector_remove(connector); + drm_connector_cleanup(connector); + kfree(omap_connector); + + omap_dss_put_device(dssdev); +} + +#define MAX_EDID 512 + +static int omap_connector_get_modes(struct drm_connector *connector) +{ + struct omap_connector *omap_connector = to_omap_connector(connector); + struct omap_dss_device *dssdev = omap_connector->dssdev; + struct omap_dss_driver *dssdrv = dssdev->driver; + struct drm_device *dev = connector->dev; + int n = 0; + + DBG("%s", omap_connector->dssdev->name); + + /* if display exposes EDID, then we parse that in the normal way to + * build table of supported modes.. otherwise (ie. fixed resolution + * LCD panels) we just return a single mode corresponding to the + * currently configured timings: + */ + if (dssdrv->read_edid) { + void *edid = kzalloc(MAX_EDID, GFP_KERNEL); + + if ((dssdrv->read_edid(dssdev, edid, MAX_EDID) > 0) && + drm_edid_is_valid(edid)) { + drm_mode_connector_update_edid_property( + connector, edid); + n = drm_add_edid_modes(connector, edid); + kfree(connector->display_info.raw_edid); + connector->display_info.raw_edid = edid; + } else { + drm_mode_connector_update_edid_property( + connector, NULL); + connector->display_info.raw_edid = NULL; + kfree(edid); + } + } else { + struct drm_display_mode *mode = drm_mode_create(dev); + struct omap_video_timings timings; + + dssdrv->get_timings(dssdev, &timings); + + copy_timings_omap_to_drm(mode, &timings); + + mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; + drm_mode_set_name(mode); + drm_mode_probed_add(connector, mode); + + n = 1; + } + + return n; +} + +static int omap_connector_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + struct omap_connector *omap_connector = to_omap_connector(connector); + struct omap_dss_device *dssdev = omap_connector->dssdev; + struct omap_dss_driver *dssdrv = dssdev->driver; + struct omap_video_timings timings = {0}; + struct drm_device *dev = connector->dev; + struct drm_display_mode *new_mode; + int ret = MODE_BAD; + + copy_timings_drm_to_omap(&timings, mode); + mode->vrefresh = drm_mode_vrefresh(mode); + + if (!dssdrv->check_timings(dssdev, &timings)) { + /* check if vrefresh is still valid */ + new_mode = drm_mode_duplicate(dev, mode); + new_mode->clock = timings.pixel_clock; + new_mode->vrefresh = 0; + if (mode->vrefresh == drm_mode_vrefresh(new_mode)) + ret = MODE_OK; + drm_mode_destroy(dev, new_mode); + } + + DBG("connector: mode %s: " + "%d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x", + (ret == MODE_OK) ? "valid" : "invalid", + mode->base.id, mode->name, mode->vrefresh, mode->clock, + mode->hdisplay, mode->hsync_start, + mode->hsync_end, mode->htotal, + mode->vdisplay, mode->vsync_start, + mode->vsync_end, mode->vtotal, mode->type, mode->flags); + + return ret; +} + +struct drm_encoder *omap_connector_attached_encoder( + struct drm_connector *connector) +{ + int i; + struct omap_connector *omap_connector = to_omap_connector(connector); + + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { + struct drm_mode_object *obj; + + if (connector->encoder_ids[i] == 0) + break; + + obj = drm_mode_object_find(connector->dev, + connector->encoder_ids[i], + DRM_MODE_OBJECT_ENCODER); + + if (obj) { + struct drm_encoder *encoder = obj_to_encoder(obj); + struct omap_overlay_manager *mgr = + omap_encoder_get_manager(encoder); + DBG("%s: found %s", omap_connector->dssdev->name, + mgr->name); + return encoder; + } + } + + DBG("%s: no encoder", omap_connector->dssdev->name); + + return NULL; +} + +static const struct drm_connector_funcs omap_connector_funcs = { + .dpms = omap_connector_dpms, + .detect = omap_connector_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = omap_connector_destroy, +}; + +static const struct drm_connector_helper_funcs omap_connector_helper_funcs = { + .get_modes = omap_connector_get_modes, + .mode_valid = omap_connector_mode_valid, + .best_encoder = omap_connector_attached_encoder, +}; + +/* called from encoder when mode is set, to propagate settings to the dssdev */ +void omap_connector_mode_set(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + struct drm_device *dev = connector->dev; + struct omap_connector *omap_connector = to_omap_connector(connector); + struct omap_dss_device *dssdev = omap_connector->dssdev; + struct omap_dss_driver *dssdrv = dssdev->driver; + struct omap_video_timings timings; + + copy_timings_drm_to_omap(&timings, mode); + + DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x", + omap_connector->dssdev->name, + mode->base.id, mode->name, mode->vrefresh, mode->clock, + mode->hdisplay, mode->hsync_start, + mode->hsync_end, mode->htotal, + mode->vdisplay, mode->vsync_start, + mode->vsync_end, mode->vtotal, mode->type, mode->flags); + + if (dssdrv->check_timings(dssdev, &timings)) { + dev_err(dev->dev, "could not set timings\n"); + return; + } + + dssdrv->set_timings(dssdev, &timings); +} + +/* flush an area of the framebuffer (in case of manual update display that + * is not automatically flushed) + */ +void omap_connector_flush(struct drm_connector *connector, + int x, int y, int w, int h) +{ + struct omap_connector *omap_connector = to_omap_connector(connector); + + /* TODO: enable when supported in dss */ + VERB("%s: %d,%d, %dx%d", omap_connector->dssdev->name, x, y, w, h); +} + +/* initialize connector */ +struct drm_connector *omap_connector_init(struct drm_device *dev, + int connector_type, struct omap_dss_device *dssdev) +{ + struct drm_connector *connector = NULL; + struct omap_connector *omap_connector; + + DBG("%s", dssdev->name); + + omap_dss_get_device(dssdev); + + omap_connector = kzalloc(sizeof(struct omap_connector), GFP_KERNEL); + if (!omap_connector) { + dev_err(dev->dev, "could not allocate connector\n"); + goto fail; + } + + omap_connector->dssdev = dssdev; + connector = &omap_connector->base; + + drm_connector_init(dev, connector, &omap_connector_funcs, + connector_type); + drm_connector_helper_add(connector, &omap_connector_helper_funcs); + +#if 0 /* enable when dss2 supports hotplug */ + if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_HPD) + connector->polled = 0; + else +#endif + connector->polled = DRM_CONNECTOR_POLL_CONNECT | + DRM_CONNECTOR_POLL_DISCONNECT; + + connector->interlace_allowed = 1; + connector->doublescan_allowed = 0; + + drm_sysfs_connector_add(connector); + + return connector; + +fail: + if (connector) { + omap_connector_destroy(connector); + } + + return NULL; +} diff --git a/drivers/staging/omapdrm/omap_crtc.c b/drivers/staging/omapdrm/omap_crtc.c new file mode 100644 index 000000000000..fd09bcfab858 --- /dev/null +++ b/drivers/staging/omapdrm/omap_crtc.c @@ -0,0 +1,327 @@ +/* + * drivers/staging/omapdrm/omap_crtc.c + * + * Copyright (C) 2011 Texas Instruments + * Author: Rob Clark + * + * 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. + * + * 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, see . + */ + +#include "omap_drv.h" + +#include "drm_mode.h" +#include "drm_crtc.h" +#include "drm_crtc_helper.h" + +#define to_omap_crtc(x) container_of(x, struct omap_crtc, base) + +struct omap_crtc { + struct drm_crtc base; + struct omap_overlay *ovl; + struct omap_overlay_info info; + int id; + + /* if there is a pending flip, this will be non-null: */ + struct drm_pending_vblank_event *event; +}; + +/* push changes down to dss2 */ +static int commit(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + struct omap_overlay *ovl = omap_crtc->ovl; + struct omap_overlay_info *info = &omap_crtc->info; + int ret; + + DBG("%s", omap_crtc->ovl->name); + DBG("%dx%d -> %dx%d (%d)", info->width, info->height, info->out_width, + info->out_height, info->screen_width); + DBG("%d,%d %08x", info->pos_x, info->pos_y, info->paddr); + + /* NOTE: do we want to do this at all here, or just wait + * for dpms(ON) since other CRTC's may not have their mode + * set yet, so fb dimensions may still change.. + */ + ret = ovl->set_overlay_info(ovl, info); + if (ret) { + dev_err(dev->dev, "could not set overlay info\n"); + return ret; + } + + /* our encoder doesn't necessarily get a commit() after this, in + * particular in the dpms() and mode_set_base() cases, so force the + * manager to update: + * + * could this be in the encoder somehow? + */ + if (ovl->manager) { + ret = ovl->manager->apply(ovl->manager); + if (ret) { + dev_err(dev->dev, "could not apply settings\n"); + return ret; + } + } + + if (info->enabled) { + omap_framebuffer_flush(crtc->fb, crtc->x, crtc->y, + crtc->fb->width, crtc->fb->height); + } + + return 0; +} + +/* update parameters that are dependent on the framebuffer dimensions and + * position within the fb that this crtc scans out from. This is called + * when framebuffer dimensions or x,y base may have changed, either due + * to our mode, or a change in another crtc that is scanning out of the + * same fb. + */ +static void update_scanout(struct drm_crtc *crtc) +{ + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + dma_addr_t paddr; + unsigned int screen_width; + + omap_framebuffer_get_buffer(crtc->fb, crtc->x, crtc->y, + NULL, &paddr, &screen_width); + + DBG("%s: %d,%d: %08x (%d)", omap_crtc->ovl->name, + crtc->x, crtc->y, (u32)paddr, screen_width); + + omap_crtc->info.paddr = paddr; + omap_crtc->info.screen_width = screen_width; +} + +static void omap_crtc_gamma_set(struct drm_crtc *crtc, + u16 *red, u16 *green, u16 *blue, uint32_t start, uint32_t size) +{ + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + DBG("%s", omap_crtc->ovl->name); +} + +static void omap_crtc_destroy(struct drm_crtc *crtc) +{ + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + DBG("%s", omap_crtc->ovl->name); + drm_crtc_cleanup(crtc); + kfree(omap_crtc); +} + +static void omap_crtc_dpms(struct drm_crtc *crtc, int mode) +{ + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + + DBG("%s: %d", omap_crtc->ovl->name, mode); + + if (mode == DRM_MODE_DPMS_ON) { + update_scanout(crtc); + omap_crtc->info.enabled = true; + } else { + omap_crtc->info.enabled = false; + } + + WARN_ON(commit(crtc)); +} + +static bool omap_crtc_mode_fixup(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + DBG("%s", omap_crtc->ovl->name); + return true; +} + +static int omap_crtc_mode_set(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode, + int x, int y, + struct drm_framebuffer *old_fb) +{ + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + + DBG("%s: %d,%d: %dx%d", omap_crtc->ovl->name, x, y, + mode->hdisplay, mode->vdisplay); + + /* just use adjusted mode */ + mode = adjusted_mode; + + omap_crtc->info.width = mode->hdisplay; + omap_crtc->info.height = mode->vdisplay; + omap_crtc->info.out_width = mode->hdisplay; + omap_crtc->info.out_height = mode->vdisplay; + omap_crtc->info.color_mode = OMAP_DSS_COLOR_RGB24U; + omap_crtc->info.rotation_type = OMAP_DSS_ROT_DMA; + omap_crtc->info.rotation = OMAP_DSS_ROT_0; + omap_crtc->info.global_alpha = 0xff; + omap_crtc->info.mirror = 0; + omap_crtc->info.mirror = 0; + omap_crtc->info.pos_x = 0; + omap_crtc->info.pos_y = 0; +#if 0 /* re-enable when these are available in DSS2 driver */ + omap_crtc->info.zorder = 3; /* GUI in the front, video behind */ + omap_crtc->info.min_x_decim = 1; + omap_crtc->info.max_x_decim = 1; + omap_crtc->info.min_y_decim = 1; + omap_crtc->info.max_y_decim = 1; +#endif + + update_scanout(crtc); + + return 0; +} + +static void omap_crtc_prepare(struct drm_crtc *crtc) +{ + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + struct omap_overlay *ovl = omap_crtc->ovl; + + DBG("%s", omap_crtc->ovl->name); + + ovl->get_overlay_info(ovl, &omap_crtc->info); + + omap_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); +} + +static void omap_crtc_commit(struct drm_crtc *crtc) +{ + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + DBG("%s", omap_crtc->ovl->name); + omap_crtc_dpms(crtc, DRM_MODE_DPMS_ON); +} + +static int omap_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, + struct drm_framebuffer *old_fb) +{ + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + + DBG("%s %d,%d: fb=%p", omap_crtc->ovl->name, x, y, old_fb); + + update_scanout(crtc); + + return commit(crtc); +} + +static void omap_crtc_load_lut(struct drm_crtc *crtc) +{ + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + DBG("%s", omap_crtc->ovl->name); +} + +static void page_flip_cb(void *arg) +{ + struct drm_crtc *crtc = arg; + struct drm_device *dev = crtc->dev; + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + struct drm_pending_vblank_event *event = omap_crtc->event; + struct timeval now; + unsigned long flags; + + WARN_ON(!event); + + omap_crtc->event = NULL; + + update_scanout(crtc); + WARN_ON(commit(crtc)); + + /* wakeup userspace */ + /* TODO: this should happen *after* flip in vsync IRQ handler */ + if (event) { + spin_lock_irqsave(&dev->event_lock, flags); + event->event.sequence = drm_vblank_count_and_time( + dev, omap_crtc->id, &now); + event->event.tv_sec = now.tv_sec; + event->event.tv_usec = now.tv_usec; + list_add_tail(&event->base.link, + &event->base.file_priv->event_list); + wake_up_interruptible(&event->base.file_priv->event_wait); + spin_unlock_irqrestore(&dev->event_lock, flags); + } +} + +static int omap_crtc_page_flip_locked(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event) +{ + struct drm_device *dev = crtc->dev; + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + + DBG("%d -> %d", crtc->fb ? crtc->fb->base.id : -1, fb->base.id); + + if (omap_crtc->event) { + dev_err(dev->dev, "already a pending flip\n"); + return -EINVAL; + } + + crtc->fb = fb; + omap_crtc->event = event; + + omap_gem_op_async(omap_framebuffer_bo(fb), OMAP_GEM_READ, + page_flip_cb, crtc); + + return 0; +} + +static const struct drm_crtc_funcs omap_crtc_funcs = { + .gamma_set = omap_crtc_gamma_set, + .set_config = drm_crtc_helper_set_config, + .destroy = omap_crtc_destroy, + .page_flip = omap_crtc_page_flip_locked, +}; + +static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = { + .dpms = omap_crtc_dpms, + .mode_fixup = omap_crtc_mode_fixup, + .mode_set = omap_crtc_mode_set, + .prepare = omap_crtc_prepare, + .commit = omap_crtc_commit, + .mode_set_base = omap_crtc_mode_set_base, + .load_lut = omap_crtc_load_lut, +}; + +struct omap_overlay *omap_crtc_get_overlay(struct drm_crtc *crtc) +{ + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + return omap_crtc->ovl; +} + +/* initialize crtc */ +struct drm_crtc *omap_crtc_init(struct drm_device *dev, + struct omap_overlay *ovl, int id) +{ + struct drm_crtc *crtc = NULL; + struct omap_crtc *omap_crtc = kzalloc(sizeof(*omap_crtc), GFP_KERNEL); + + DBG("%s", ovl->name); + + if (!omap_crtc) { + dev_err(dev->dev, "could not allocate CRTC\n"); + goto fail; + } + + omap_crtc->ovl = ovl; + omap_crtc->id = id; + crtc = &omap_crtc->base; + drm_crtc_init(dev, crtc, &omap_crtc_funcs); + drm_crtc_helper_add(crtc, &omap_crtc_helper_funcs); + + return crtc; + +fail: + if (crtc) { + drm_crtc_cleanup(crtc); + kfree(omap_crtc); + } + return NULL; +} diff --git a/drivers/staging/omapdrm/omap_drm.h b/drivers/staging/omapdrm/omap_drm.h new file mode 100644 index 000000000000..40167dd97589 --- /dev/null +++ b/drivers/staging/omapdrm/omap_drm.h @@ -0,0 +1,123 @@ +/* + * include/drm/omap_drm.h + * + * Copyright (C) 2011 Texas Instruments + * Author: Rob Clark + * + * 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. + * + * 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, see . + */ + +#ifndef __OMAP_DRM_H__ +#define __OMAP_DRM_H__ + +#include "drm.h" + +/* Please note that modifications to all structs defined here are + * subject to backwards-compatibility constraints. + */ + +#define OMAP_PARAM_CHIPSET_ID 1 /* ie. 0x3430, 0x4430, etc */ + +struct drm_omap_param { + uint64_t param; /* in */ + uint64_t value; /* in (set_param), out (get_param) */ +}; + +#define OMAP_BO_SCANOUT 0x00000001 /* scanout capable (phys contiguous) */ +#define OMAP_BO_CACHE_MASK 0x00000006 /* cache type mask, see cache modes */ +#define OMAP_BO_TILED_MASK 0x00000f00 /* tiled mapping mask, see tiled modes */ + +/* cache modes */ +#define OMAP_BO_CACHED 0x00000000 /* default */ +#define OMAP_BO_WC 0x00000002 /* write-combine */ +#define OMAP_BO_UNCACHED 0x00000004 /* strongly-ordered (uncached) */ + +/* tiled modes */ +#define OMAP_BO_TILED_8 0x00000100 +#define OMAP_BO_TILED_16 0x00000200 +#define OMAP_BO_TILED_32 0x00000300 +#define OMAP_BO_TILED (OMAP_BO_TILED_8 | OMAP_BO_TILED_16 | OMAP_BO_TILED_32) + +union omap_gem_size { + uint32_t bytes; /* (for non-tiled formats) */ + struct { + uint16_t width; + uint16_t height; + } tiled; /* (for tiled formats) */ +}; + +struct drm_omap_gem_new { + union omap_gem_size size; /* in */ + uint32_t flags; /* in */ + uint32_t handle; /* out */ + uint32_t __pad; +}; + +/* mask of operations: */ +enum omap_gem_op { + OMAP_GEM_READ = 0x01, + OMAP_GEM_WRITE = 0x02, +}; + +struct drm_omap_gem_cpu_prep { + uint32_t handle; /* buffer handle (in) */ + uint32_t op; /* mask of omap_gem_op (in) */ +}; + +struct drm_omap_gem_cpu_fini { + uint32_t handle; /* buffer handle (in) */ + uint32_t op; /* mask of omap_gem_op (in) */ + /* TODO maybe here we pass down info about what regions are touched + * by sw so we can be clever about cache ops? For now a placeholder, + * set to zero and we just do full buffer flush.. + */ + uint32_t nregions; + uint32_t __pad; +}; + +struct drm_omap_gem_info { + uint32_t handle; /* buffer handle (in) */ + uint32_t pad; + uint64_t offset; /* mmap offset (out) */ + /* note: in case of tiled buffers, the user virtual size can be + * different from the physical size (ie. how many pages are needed + * to back the object) which is returned in DRM_IOCTL_GEM_OPEN.. + * This size here is the one that should be used if you want to + * mmap() the buffer: + */ + uint32_t size; /* virtual size for mmap'ing (out) */ + uint32_t __pad; +}; + +#define DRM_OMAP_GET_PARAM 0x00 +#define DRM_OMAP_SET_PARAM 0x01 +/* placeholder for plugin-api +#define DRM_OMAP_GET_BASE 0x02 +*/ +#define DRM_OMAP_GEM_NEW 0x03 +#define DRM_OMAP_GEM_CPU_PREP 0x04 +#define DRM_OMAP_GEM_CPU_FINI 0x05 +#define DRM_OMAP_GEM_INFO 0x06 +#define DRM_OMAP_NUM_IOCTLS 0x07 + +#define DRM_IOCTL_OMAP_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_OMAP_GET_PARAM, struct drm_omap_param) +#define DRM_IOCTL_OMAP_SET_PARAM DRM_IOW (DRM_COMMAND_BASE + DRM_OMAP_SET_PARAM, struct drm_omap_param) +/* placeholder for plugin-api +#define DRM_IOCTL_OMAP_GET_BASE DRM_IOWR(DRM_COMMAND_BASE + DRM_OMAP_GET_BASE, struct drm_omap_get_base) +*/ +#define DRM_IOCTL_OMAP_GEM_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_OMAP_GEM_NEW, struct drm_omap_gem_new) +#define DRM_IOCTL_OMAP_GEM_CPU_PREP DRM_IOW (DRM_COMMAND_BASE + DRM_OMAP_GEM_CPU_PREP, struct drm_omap_gem_cpu_prep) +#define DRM_IOCTL_OMAP_GEM_CPU_FINI DRM_IOW (DRM_COMMAND_BASE + DRM_OMAP_GEM_CPU_FINI, struct drm_omap_gem_cpu_fini) +#define DRM_IOCTL_OMAP_GEM_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_OMAP_GEM_INFO, struct drm_omap_gem_info) + +#endif /* __OMAP_DRM_H__ */ diff --git a/drivers/staging/omapdrm/omap_drv.c b/drivers/staging/omapdrm/omap_drv.c new file mode 100644 index 000000000000..cee005043dbd --- /dev/null +++ b/drivers/staging/omapdrm/omap_drv.c @@ -0,0 +1,810 @@ +/* + * drivers/staging/omapdrm/omap_drv.c + * + * Copyright (C) 2011 Texas Instruments + * Author: Rob Clark + * + * 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. + * + * 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, see . + */ + +#include "omap_drv.h" + +#include "drm_crtc_helper.h" +#include "drm_fb_helper.h" + +#define DRIVER_NAME MODULE_NAME +#define DRIVER_DESC "OMAP DRM" +#define DRIVER_DATE "20110917" +#define DRIVER_MAJOR 1 +#define DRIVER_MINOR 0 +#define DRIVER_PATCHLEVEL 0 + +struct drm_device *drm_device; + +static int num_crtc = CONFIG_DRM_OMAP_NUM_CRTCS; + +MODULE_PARM_DESC(num_crtc, "Number of overlays to use as CRTCs"); +module_param(num_crtc, int, 0600); + +/* + * mode config funcs + */ + +/* Notes about mapping DSS and DRM entities: + * CRTC: overlay + * encoder: manager.. with some extension to allow one primary CRTC + * and zero or more video CRTC's to be mapped to one encoder? + * connector: dssdev.. manager can be attached/detached from different + * devices + */ + +static void omap_fb_output_poll_changed(struct drm_device *dev) +{ + struct omap_drm_private *priv = dev->dev_private; + DBG("dev=%p", dev); + if (priv->fbdev) { + drm_fb_helper_hotplug_event(priv->fbdev); + } +} + +static struct drm_mode_config_funcs omap_mode_config_funcs = { + .fb_create = omap_framebuffer_create, + .output_poll_changed = omap_fb_output_poll_changed, +}; + +static int get_connector_type(struct omap_dss_device *dssdev) +{ + switch (dssdev->type) { + case OMAP_DISPLAY_TYPE_HDMI: + return DRM_MODE_CONNECTOR_HDMIA; + case OMAP_DISPLAY_TYPE_DPI: + if (!strcmp(dssdev->name, "dvi")) + return DRM_MODE_CONNECTOR_DVID; + /* fallthrough */ + default: + return DRM_MODE_CONNECTOR_Unknown; + } +} + +#if 0 /* enable when dss2 supports hotplug */ +static int omap_drm_notifier(struct notifier_block *nb, + unsigned long evt, void *arg) +{ + switch (evt) { + case OMAP_DSS_SIZE_CHANGE: + case OMAP_DSS_HOTPLUG_CONNECT: + case OMAP_DSS_HOTPLUG_DISCONNECT: { + struct drm_device *dev = drm_device; + DBG("hotplug event: evt=%d, dev=%p", evt, dev); + if (dev) { + drm_sysfs_hotplug_event(dev); + } + return NOTIFY_OK; + } + default: /* don't care about other events for now */ + return NOTIFY_DONE; + } +} +#endif + +static void dump_video_chains(void) +{ + int i; + + DBG("dumping video chains: "); + for (i = 0; i < omap_dss_get_num_overlays(); i++) { + struct omap_overlay *ovl = omap_dss_get_overlay(i); + struct omap_overlay_manager *mgr = ovl->manager; + struct omap_dss_device *dssdev = mgr ? mgr->device : NULL; + if (dssdev) { + DBG("%d: %s -> %s -> %s", i, ovl->name, mgr->name, + dssdev->name); + } else if (mgr) { + DBG("%d: %s -> %s", i, ovl->name, mgr->name); + } else { + DBG("%d: %s", i, ovl->name); + } + } +} + +/* create encoders for each manager */ +static int create_encoder(struct drm_device *dev, + struct omap_overlay_manager *mgr) +{ + struct omap_drm_private *priv = dev->dev_private; + struct drm_encoder *encoder = omap_encoder_init(dev, mgr); + + if (!encoder) { + dev_err(dev->dev, "could not create encoder: %s\n", + mgr->name); + return -ENOMEM; + } + + BUG_ON(priv->num_encoders >= ARRAY_SIZE(priv->encoders)); + + priv->encoders[priv->num_encoders++] = encoder; + + return 0; +} + +/* create connectors for each display device */ +static int create_connector(struct drm_device *dev, + struct omap_dss_device *dssdev) +{ + struct omap_drm_private *priv = dev->dev_private; + static struct notifier_block *notifier; + struct drm_connector *connector; + int j; + + if (!dssdev->driver) { + dev_warn(dev->dev, "%s has no driver.. skipping it\n", + dssdev->name); + return 0; + } + + if (!(dssdev->driver->get_timings || + dssdev->driver->read_edid)) { + dev_warn(dev->dev, "%s driver does not support " + "get_timings or read_edid.. skipping it!\n", + dssdev->name); + return 0; + } + + connector = omap_connector_init(dev, + get_connector_type(dssdev), dssdev); + + if (!connector) { + dev_err(dev->dev, "could not create connector: %s\n", + dssdev->name); + return -ENOMEM; + } + + BUG_ON(priv->num_connectors >= ARRAY_SIZE(priv->connectors)); + + priv->connectors[priv->num_connectors++] = connector; + +#if 0 /* enable when dss2 supports hotplug */ + notifier = kzalloc(sizeof(struct notifier_block), GFP_KERNEL); + notifier->notifier_call = omap_drm_notifier; + omap_dss_add_notify(dssdev, notifier); +#else + notifier = NULL; +#endif + + for (j = 0; j < priv->num_encoders; j++) { + struct omap_overlay_manager *mgr = + omap_encoder_get_manager(priv->encoders[j]); + if (mgr->device == dssdev) { + drm_mode_connector_attach_encoder(connector, + priv->encoders[j]); + } + } + + return 0; +} + +/* create up to max_overlays CRTCs mapping to overlays.. by default, + * connect the overlays to different managers/encoders, giving priority + * to encoders connected to connectors with a detected connection + */ +static int create_crtc(struct drm_device *dev, struct omap_overlay *ovl, + int *j, unsigned int connected_connectors) +{ + struct omap_drm_private *priv = dev->dev_private; + struct omap_overlay_manager *mgr = NULL; + struct drm_crtc *crtc; + + if (ovl->manager) { + DBG("disconnecting %s from %s", ovl->name, + ovl->manager->name); + ovl->unset_manager(ovl); + } + + /* find next best connector, ones with detected connection first + */ + while (*j < priv->num_connectors && !mgr) { + if (connected_connectors & (1 << *j)) { + struct drm_encoder *encoder = + omap_connector_attached_encoder( + priv->connectors[*j]); + if (encoder) { + mgr = omap_encoder_get_manager(encoder); + } + } + (*j)++; + } + + /* if we couldn't find another connected connector, lets start + * looking at the unconnected connectors: + * + * note: it might not be immediately apparent, but thanks to + * the !mgr check in both this loop and the one above, the only + * way to enter this loop is with *j == priv->num_connectors, + * so idx can never go negative. + */ + while (*j < 2 * priv->num_connectors && !mgr) { + int idx = *j - priv->num_connectors; + if (!(connected_connectors & (1 << idx))) { + struct drm_encoder *encoder = + omap_connector_attached_encoder( + priv->connectors[idx]); + if (encoder) { + mgr = omap_encoder_get_manager(encoder); + } + } + (*j)++; + } + + if (mgr) { + DBG("connecting %s to %s", ovl->name, mgr->name); + ovl->set_manager(ovl, mgr); + } + + crtc = omap_crtc_init(dev, ovl, priv->num_crtcs); + + if (!crtc) { + dev_err(dev->dev, "could not create CRTC: %s\n", + ovl->name); + return -ENOMEM; + } + + BUG_ON(priv->num_crtcs >= ARRAY_SIZE(priv->crtcs)); + + priv->crtcs[priv->num_crtcs++] = crtc; + + return 0; +} + +static int match_dev_name(struct omap_dss_device *dssdev, void *data) +{ + return !strcmp(dssdev->name, data); +} + +static unsigned int detect_connectors(struct drm_device *dev) +{ + struct omap_drm_private *priv = dev->dev_private; + unsigned int connected_connectors = 0; + int i; + + for (i = 0; i < priv->num_connectors; i++) { + struct drm_connector *connector = priv->connectors[i]; + if (omap_connector_detect(connector, true) == + connector_status_connected) { + connected_connectors |= (1 << i); + } + } + + return connected_connectors; +} + +static int omap_modeset_init(struct drm_device *dev) +{ + const struct omap_drm_platform_data *pdata = dev->dev->platform_data; + struct omap_drm_private *priv = dev->dev_private; + struct omap_dss_device *dssdev = NULL; + int i, j; + unsigned int connected_connectors = 0; + + drm_mode_config_init(dev); + + if (pdata) { + /* if platform data is provided by the board file, use it to + * control which overlays, managers, and devices we own. + */ + for (i = 0; i < pdata->mgr_cnt; i++) { + struct omap_overlay_manager *mgr = + omap_dss_get_overlay_manager(pdata->mgr_ids[i]); + create_encoder(dev, mgr); + } + + for (i = 0; i < pdata->dev_cnt; i++) { + struct omap_dss_device *dssdev = + omap_dss_find_device( + (void *)pdata->dev_names[i], match_dev_name); + if (!dssdev) { + dev_warn(dev->dev, "no such dssdev: %s\n", + pdata->dev_names[i]); + continue; + } + create_connector(dev, dssdev); + } + + connected_connectors = detect_connectors(dev); + + j = 0; + for (i = 0; i < pdata->ovl_cnt; i++) { + struct omap_overlay *ovl = + omap_dss_get_overlay(pdata->ovl_ids[i]); + create_crtc(dev, ovl, &j, connected_connectors); + } + } else { + /* otherwise just grab up to CONFIG_DRM_OMAP_NUM_CRTCS and try + * to make educated guesses about everything else + */ + int max_overlays = min(omap_dss_get_num_overlays(), num_crtc); + + for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) { + create_encoder(dev, omap_dss_get_overlay_manager(i)); + } + + for_each_dss_dev(dssdev) { + create_connector(dev, dssdev); + } + + connected_connectors = detect_connectors(dev); + + j = 0; + for (i = 0; i < max_overlays; i++) { + create_crtc(dev, omap_dss_get_overlay(i), + &j, connected_connectors); + } + } + + /* for now keep the mapping of CRTCs and encoders static.. */ + for (i = 0; i < priv->num_encoders; i++) { + struct drm_encoder *encoder = priv->encoders[i]; + struct omap_overlay_manager *mgr = + omap_encoder_get_manager(encoder); + + encoder->possible_crtcs = 0; + + for (j = 0; j < priv->num_crtcs; j++) { + struct omap_overlay *ovl = + omap_crtc_get_overlay(priv->crtcs[j]); + if (ovl->manager == mgr) { + encoder->possible_crtcs |= (1 << j); + } + } + + DBG("%s: possible_crtcs=%08x", mgr->name, + encoder->possible_crtcs); + } + + dump_video_chains(); + + dev->mode_config.min_width = 256; + dev->mode_config.min_height = 256; + + /* note: eventually will need some cpu_is_omapXYZ() type stuff here + * to fill in these limits properly on different OMAP generations.. + */ + dev->mode_config.max_width = 2048; + dev->mode_config.max_height = 2048; + + dev->mode_config.funcs = &omap_mode_config_funcs; + + return 0; +} + +static void omap_modeset_free(struct drm_device *dev) +{ + drm_mode_config_cleanup(dev); +} + +/* + * drm ioctl funcs + */ + + +static int ioctl_get_param(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_omap_param *args = data; + + DBG("%p: param=%llu", dev, args->param); + + switch (args->param) { + case OMAP_PARAM_CHIPSET_ID: + args->value = GET_OMAP_TYPE; + break; + default: + DBG("unknown parameter %lld", args->param); + return -EINVAL; + } + + return 0; +} + +static int ioctl_set_param(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_omap_param *args = data; + + switch (args->param) { + default: + DBG("unknown parameter %lld", args->param); + return -EINVAL; + } + + return 0; +} + +static int ioctl_gem_new(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_omap_gem_new *args = data; + DBG("%p:%p: size=0x%08x, flags=%08x", dev, file_priv, + args->size.bytes, args->flags); + return omap_gem_new_handle(dev, file_priv, args->size, + args->flags, &args->handle); +} + +static int ioctl_gem_cpu_prep(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_omap_gem_cpu_prep *args = data; + struct drm_gem_object *obj; + int ret; + + VERB("%p:%p: handle=%d, op=%x", dev, file_priv, args->handle, args->op); + + obj = drm_gem_object_lookup(dev, file_priv, args->handle); + if (!obj) { + return -ENOENT; + } + + ret = omap_gem_op_sync(obj, args->op); + + if (!ret) { + ret = omap_gem_op_start(obj, args->op); + } + + drm_gem_object_unreference_unlocked(obj); + + return ret; +} + +static int ioctl_gem_cpu_fini(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_omap_gem_cpu_fini *args = data; + struct drm_gem_object *obj; + int ret; + + VERB("%p:%p: handle=%d", dev, file_priv, args->handle); + + obj = drm_gem_object_lookup(dev, file_priv, args->handle); + if (!obj) { + return -ENOENT; + } + + /* XXX flushy, flushy */ + ret = 0; + + if (!ret) { + ret = omap_gem_op_finish(obj, args->op); + } + + drm_gem_object_unreference_unlocked(obj); + + return ret; +} + +static int ioctl_gem_info(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_omap_gem_info *args = data; + struct drm_gem_object *obj; + int ret = 0; + + DBG("%p:%p: handle=%d", dev, file_priv, args->handle); + + obj = drm_gem_object_lookup(dev, file_priv, args->handle); + if (!obj) { + return -ENOENT; + } + + args->size = obj->size; /* for now */ + args->offset = omap_gem_mmap_offset(obj); + + drm_gem_object_unreference_unlocked(obj); + + return ret; +} + +struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] = { + DRM_IOCTL_DEF_DRV(OMAP_GET_PARAM, ioctl_get_param, DRM_UNLOCKED|DRM_AUTH), + DRM_IOCTL_DEF_DRV(OMAP_SET_PARAM, ioctl_set_param, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(OMAP_GEM_NEW, ioctl_gem_new, DRM_UNLOCKED|DRM_AUTH), + DRM_IOCTL_DEF_DRV(OMAP_GEM_CPU_PREP, ioctl_gem_cpu_prep, DRM_UNLOCKED|DRM_AUTH), + DRM_IOCTL_DEF_DRV(OMAP_GEM_CPU_FINI, ioctl_gem_cpu_fini, DRM_UNLOCKED|DRM_AUTH), + DRM_IOCTL_DEF_DRV(OMAP_GEM_INFO, ioctl_gem_info, DRM_UNLOCKED|DRM_AUTH), +}; + +/* + * drm driver funcs + */ + +/** + * load - setup chip and create an initial config + * @dev: DRM device + * @flags: startup flags + * + * The driver load routine has to do several things: + * - initialize the memory manager + * - allocate initial config memory + * - setup the DRM framebuffer with the allocated memory + */ +static int dev_load(struct drm_device *dev, unsigned long flags) +{ + struct omap_drm_private *priv; + int ret; + + DBG("load: dev=%p", dev); + + drm_device = dev; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) { + dev_err(dev->dev, "could not allocate priv\n"); + return -ENOMEM; + } + + dev->dev_private = priv; + + ret = omap_modeset_init(dev); + if (ret) { + dev_err(dev->dev, "omap_modeset_init failed: ret=%d\n", ret); + dev->dev_private = NULL; + kfree(priv); + return ret; + } + + priv->fbdev = omap_fbdev_init(dev); + if (!priv->fbdev) { + dev_warn(dev->dev, "omap_fbdev_init failed\n"); + /* well, limp along without an fbdev.. maybe X11 will work? */ + } + + drm_kms_helper_poll_init(dev); + + ret = drm_vblank_init(dev, priv->num_crtcs); + if (ret) { + dev_warn(dev->dev, "could not init vblank\n"); + } + + return 0; +} + +static int dev_unload(struct drm_device *dev) +{ + DBG("unload: dev=%p", dev); + + drm_vblank_cleanup(dev); + drm_kms_helper_poll_fini(dev); + + omap_fbdev_free(dev); + + omap_modeset_free(dev); + + kfree(dev->dev_private); + dev->dev_private = NULL; + + return 0; +} + +static int dev_open(struct drm_device *dev, struct drm_file *file) +{ + file->driver_priv = NULL; + + DBG("open: dev=%p, file=%p", dev, file); + + return 0; +} + +static int dev_firstopen(struct drm_device *dev) +{ + DBG("firstopen: dev=%p", dev); + return 0; +} + +/** + * lastclose - clean up after all DRM clients have exited + * @dev: DRM device + * + * Take care of cleaning up after all DRM clients have exited. In the + * mode setting case, we want to restore the kernel's initial mode (just + * in case the last client left us in a bad state). + */ +static void dev_lastclose(struct drm_device *dev) +{ + /* we don't support vga-switcheroo.. so just make sure the fbdev + * mode is active + */ + struct omap_drm_private *priv = dev->dev_private; + int ret; + + DBG("lastclose: dev=%p", dev); + + ret = drm_fb_helper_restore_fbdev_mode(priv->fbdev); + if (ret) + DBG("failed to restore crtc mode"); +} + +static void dev_preclose(struct drm_device *dev, struct drm_file *file) +{ + DBG("preclose: dev=%p", dev); +} + +static void dev_postclose(struct drm_device *dev, struct drm_file *file) +{ + DBG("postclose: dev=%p, file=%p", dev, file); +} + +/** + * enable_vblank - enable vblank interrupt events + * @dev: DRM device + * @crtc: which irq to enable + * + * Enable vblank interrupts for @crtc. If the device doesn't have + * a hardware vblank counter, this routine should be a no-op, since + * interrupts will have to stay on to keep the count accurate. + * + * RETURNS + * Zero on success, appropriate errno if the given @crtc's vblank + * interrupt cannot be enabled. + */ +static int dev_enable_vblank(struct drm_device *dev, int crtc) +{ + DBG("enable_vblank: dev=%p, crtc=%d", dev, crtc); + return 0; +} + +/** + * disable_vblank - disable vblank interrupt events + * @dev: DRM device + * @crtc: which irq to enable + * + * Disable vblank interrupts for @crtc. If the device doesn't have + * a hardware vblank counter, this routine should be a no-op, since + * interrupts will have to stay on to keep the count accurate. + */ +static void dev_disable_vblank(struct drm_device *dev, int crtc) +{ + DBG("disable_vblank: dev=%p, crtc=%d", dev, crtc); +} + +static irqreturn_t dev_irq_handler(DRM_IRQ_ARGS) +{ + return IRQ_HANDLED; +} + +static void dev_irq_preinstall(struct drm_device *dev) +{ + DBG("irq_preinstall: dev=%p", dev); +} + +static int dev_irq_postinstall(struct drm_device *dev) +{ + DBG("irq_postinstall: dev=%p", dev); + return 0; +} + +static void dev_irq_uninstall(struct drm_device *dev) +{ + DBG("irq_uninstall: dev=%p", dev); +} + +static struct vm_operations_struct omap_gem_vm_ops = { + .fault = omap_gem_fault, + .open = drm_gem_vm_open, + .close = drm_gem_vm_close, +}; + +static struct drm_driver omap_drm_driver = { + .driver_features = + DRIVER_HAVE_IRQ | DRIVER_MODESET | DRIVER_GEM, + .load = dev_load, + .unload = dev_unload, + .open = dev_open, + .firstopen = dev_firstopen, + .lastclose = dev_lastclose, + .preclose = dev_preclose, + .postclose = dev_postclose, + .get_vblank_counter = drm_vblank_count, + .enable_vblank = dev_enable_vblank, + .disable_vblank = dev_disable_vblank, + .irq_preinstall = dev_irq_preinstall, + .irq_postinstall = dev_irq_postinstall, + .irq_uninstall = dev_irq_uninstall, + .irq_handler = dev_irq_handler, + .reclaim_buffers = drm_core_reclaim_buffers, + .gem_init_object = omap_gem_init_object, + .gem_free_object = omap_gem_free_object, + .gem_vm_ops = &omap_gem_vm_ops, + .dumb_create = omap_gem_dumb_create, + .dumb_map_offset = omap_gem_dumb_map_offset, + .dumb_destroy = omap_gem_dumb_destroy, + .ioctls = ioctls, + .num_ioctls = DRM_OMAP_NUM_IOCTLS, + .fops = { + .owner = THIS_MODULE, + .open = drm_open, + .unlocked_ioctl = drm_ioctl, + .release = drm_release, + .mmap = omap_gem_mmap, + .poll = drm_poll, + .fasync = drm_fasync, + .read = drm_read, + .llseek = noop_llseek, + }, + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = DRIVER_DATE, + .major = DRIVER_MAJOR, + .minor = DRIVER_MINOR, + .patchlevel = DRIVER_PATCHLEVEL, +}; + +static int pdev_suspend(struct platform_device *pDevice, pm_message_t state) +{ + DBG(""); + return 0; +} + +static int pdev_resume(struct platform_device *device) +{ + DBG(""); + return 0; +} + +static void pdev_shutdown(struct platform_device *device) +{ + DBG(""); +} + +static int pdev_probe(struct platform_device *device) +{ + DBG("%s", device->name); + return drm_platform_init(&omap_drm_driver, device); +} + +static int pdev_remove(struct platform_device *device) +{ + DBG(""); + drm_platform_exit(&omap_drm_driver, device); + return 0; +} + +struct platform_driver pdev = { + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + }, + .probe = pdev_probe, + .remove = pdev_remove, + .suspend = pdev_suspend, + .resume = pdev_resume, + .shutdown = pdev_shutdown, +}; + +static int __init omap_drm_init(void) +{ + DBG("init"); + return platform_driver_register(&pdev); +} + +static void __exit omap_drm_fini(void) +{ + DBG("fini"); + platform_driver_unregister(&pdev); +} + +/* need late_initcall() so we load after dss_driver's are loaded */ +late_initcall(omap_drm_init); +module_exit(omap_drm_fini); + +MODULE_AUTHOR("Rob Clark "); +MODULE_DESCRIPTION("OMAP DRM Display Driver"); +MODULE_ALIAS("platform:" DRIVER_NAME); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/omapdrm/omap_drv.h b/drivers/staging/omapdrm/omap_drv.h new file mode 100644 index 000000000000..c8f2752a4f18 --- /dev/null +++ b/drivers/staging/omapdrm/omap_drv.h @@ -0,0 +1,124 @@ +/* + * drivers/staging/omapdrm/omap_drv.h + * + * Copyright (C) 2011 Texas Instruments + * Author: Rob Clark + * + * 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. + * + * 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, see . + */ + +#ifndef __OMAP_DRV_H__ +#define __OMAP_DRV_H__ + +#include