use broken-out patches for the coldfire to make it easier to follow differences again...
[openwrt/svn-archive/archive.git] / target / linux / coldfire / patches / 032-m5445x_edma_update.patch
diff --git a/target/linux/coldfire/patches/032-m5445x_edma_update.patch b/target/linux/coldfire/patches/032-m5445x_edma_update.patch
new file mode 100644 (file)
index 0000000..17f2bec
--- /dev/null
@@ -0,0 +1,553 @@
+From 7b5b08d99d5362e9c36fd7d42d6c06c2a848266c Mon Sep 17 00:00:00 2001
+From: Kurt Mahan <kmahan@freescale.com>
+Date: Sun, 9 Dec 2007 02:21:19 -0700
+Subject: [PATCH] Update EDMA.
+
+LTIBName: m5445x-edma-update
+Signed-off-by: Kurt Mahan <kmahan@freescale.com>
+---
+ drivers/spi/coldfire_edma.c      |  261 +++++++++++++++++++++++---------------
+ include/asm-m68k/coldfire_edma.h |    9 +-
+ include/asm-m68k/mcf5445x_edma.h |   28 +++-
+ 3 files changed, 188 insertions(+), 110 deletions(-)
+
+--- a/drivers/spi/coldfire_edma.c
++++ b/drivers/spi/coldfire_edma.c
+@@ -20,76 +20,91 @@
+ #include <linux/cdev.h>
+ #include <linux/seq_file.h>
+ #include <linux/proc_fs.h>
++#ifdef CONFIG_M54455
+ #include <asm/mcf5445x_edma.h>
+ #include <asm/mcf5445x_intc.h>
++#endif /* CONFIG_M54455 */
+ #include <asm/coldfire_edma.h>
+-
+-/* callback handler data for each TCD */
++/*
++ * Callback handler data for each TCD
++ */
+ struct edma_isr_record {
+-      edma_irq_handler irq_handler;       /* interrupt handler */
+-      edma_error_handler error_handler;       /* error interrupt handler */
+-      void* dev;                                                      /* device used for the channel */
+-      int  allocated;                                         /* busy flag */
+-      spinlock_t *lock;                                       /* spin lock (if needs to be locked in interrupt) */
+-      const char* device_id;                          /* device id string, used in proc file system */
++      edma_irq_handler irq_handler;     /* interrupt handler */
++      edma_error_handler error_handler; /* error interrupt handler */
++      void *arg;                        /* argument to pass back */
++      int allocated;                    /* busy flag */
++      spinlock_t *lock;                 /* spin lock (optional) */
++      const char *device_id;            /* dev id string, used in procfs */
+ };
+-/* device structure */
++/*
++ * Device structure
++ */
+ struct coldfire_edma_dev {
+-      struct cdev cdev;                       /* character device */
+-      struct edma_isr_record dma_interrupt_handlers[EDMA_CHANNELS]; /* channel handlers */
++      struct cdev cdev;                 /* character device */
++      struct edma_isr_record dma_interrupt_handlers[EDMA_CHANNELS];
+ };
+ /* allocated major device number */
+ static int coldfire_dma_major;
++
+ /* device driver structure */
+-static struct coldfire_edma_dev* devp = NULL;
++static struct coldfire_edma_dev *devp = NULL;
+ /* device driver file operations */
+ struct file_operations coldfire_edma_fops = {
+       .owner = THIS_MODULE,
+ };
+-/* eDMA channel interrupt handler */
++/**
++ * dmaisr - eDMA channel interrupt handler
++ * @irq: interrupt number
++ * @dev_id: argument
++ */
+ static int dmaisr(int irq, void *dev_id)
+ {
+       int channel = irq - EDMA_INT_CONTROLLER_BASE - EDMA_INT_CHANNEL_BASE;
+       int result = IRQ_HANDLED;
+-      if (devp!=NULL && devp->dma_interrupt_handlers[channel].lock) {
+-              spin_lock(devp->dma_interrupt_handlers[channel].lock);
+-      }
++      if ((devp != NULL) &&
++          (devp->dma_interrupt_handlers[channel].irq_handler)) {
++              /* call user irq handler */
++              if (devp->dma_interrupt_handlers[channel].lock)
++                      spin_lock(devp->dma_interrupt_handlers[channel].lock);
++
++              result = devp->dma_interrupt_handlers[channel].irq_handler(
++                      channel, devp->dma_interrupt_handlers[channel].arg);
+-      if (devp!=NULL && devp->dma_interrupt_handlers[channel].irq_handler) {
+-              result = devp->dma_interrupt_handlers[channel].irq_handler(channel,
+-                                                      devp->dma_interrupt_handlers[channel].dev);
++              if (devp->dma_interrupt_handlers[channel].lock)
++                      spin_unlock(devp->dma_interrupt_handlers[channel].lock);
+       } else {
++              /* no irq handler so just ack it */
+               confirm_edma_interrupt_handled(channel);
+-              printk(EDMA_DRIVER_NAME ": No handler for DMA channel %d\n", channel);
+-      }
+-
+-      if (devp!=NULL && devp->dma_interrupt_handlers[channel].lock) {
+-              spin_unlock(devp->dma_interrupt_handlers[channel].lock);
++              printk(EDMA_DRIVER_NAME ": No handler for DMA channel %d\n",
++                     channel);
+       }
+       return result;
+ }
+-/* eDMA error interrupt handler */
++/**
++ * dma_error_isr - eDMA error interrupt handler
++ * @irq: interrupt number
++ * @dev_id: argument
++ */
+ static int dma_error_isr(int irq, void* dev_id)
+ {
+       u16 err;
+       int i;
+       err = MCF_EDMA_ERR;
+-      for (i=0;i<EDMA_CHANNELS;i++) {
++      for (i=0; i<EDMA_CHANNELS; i++) {
+               if (err & (1<<i)) {
+-                      if (devp!=NULL && devp->dma_interrupt_handlers[i].error_handler) {
+-                              devp->dma_interrupt_handlers[i].error_handler(i, devp->dma_interrupt_handlers[i].dev);
+-                      } else {
++                      if (devp!=NULL && devp->dma_interrupt_handlers[i].error_handler)
++                              devp->dma_interrupt_handlers[i].error_handler(i, devp->dma_interrupt_handlers[i].arg);
++                      else
+                               printk(KERN_WARNING EDMA_DRIVER_NAME ": DMA error on channel %d\n", i);
+-                      }
+               }
+       }
+@@ -97,11 +112,26 @@ static int dma_error_isr(int irq, void* 
+       return IRQ_HANDLED;
+ }
+-/* sets channel parameters */
++/**
++ * set_edma_params - Set transfer control descriptor (TCD)
++ * @channel: channel number
++ * @source: source address
++ * @dest: destination address
++ * @attr: attributes
++ * @soff: source offset
++ * @nbytes: number of bytes to be transfered in minor loop
++ * @slast: last source address adjustment
++ * @citer: major loop count
++ * @biter: beginning minor loop count
++ * @doff: destination offset
++ * @dlast_sga: last destination address adjustment
++ * @major_int: generate interrupt after each major loop
++ * @disable_req: disable DMA request after major loop
++ */
+ void set_edma_params(int channel, u32 source, u32 dest,
+-                                       u32 attr, u32 soff, u32 nbytes, u32 slast,
+-                                       u32 citer, u32 biter, u32 doff, u32 dlast_sga,
+-                                       int major_int, int disable_req)
++      u32 attr, u32 soff, u32 nbytes, u32 slast,
++      u32 citer, u32 biter, u32 doff, u32 dlast_sga,
++      int major_int, int disable_req)
+ {
+       if (channel<0 || channel>EDMA_CHANNELS)
+@@ -117,45 +147,56 @@ void set_edma_params(int channel, u32 so
+       MCF_EDMA_TCD_BITER(channel)=MCF_EDMA_TCD_BITER_BITER(biter);
+       MCF_EDMA_TCD_DOFF(channel) = MCF_EDMA_TCD_DOFF_DOFF(doff);
+       MCF_EDMA_TCD_DLAST_SGA(channel) = MCF_EDMA_TCD_DLAST_SGA_DLAST_SGA(dlast_sga);
++
+       /* interrupt at the end of major loop */
+-      if (major_int) {
++      if (major_int)
+               MCF_EDMA_TCD_CSR(channel) |= MCF_EDMA_TCD_CSR_INT_MAJOR;
+-      } else {
++      else
+               MCF_EDMA_TCD_CSR(channel) &= ~MCF_EDMA_TCD_CSR_INT_MAJOR;
+-      }
++
+       /* disable request at the end of major loop of transfer or not*/
+-      if (disable_req) {
++      if (disable_req)
+               MCF_EDMA_TCD_CSR(channel) |= MCF_EDMA_TCD_CSR_D_REQ;
+-      } else {
++      else
+               MCF_EDMA_TCD_CSR(channel) &= ~MCF_EDMA_TCD_CSR_D_REQ;
+-      }
+-
+ }
+ EXPORT_SYMBOL(set_edma_params);
+-/* init eDMA controller */
++/**
++ * init_edma - Initialize the eDMA controller
++ */
+ void init_edma(void)
+ {
+       MCF_EDMA_CR = 0;
+ }
+ EXPORT_SYMBOL(init_edma);
+-/* request eDMA channel */
++/**
++ * request_edma_channel - Request an eDMA channel
++ * @channel: channel number
++ * @handler: dma handler
++ * @error_handler: dma error handler
++ * @arg: argument to pass back
++ * @lock: optional spinlock to hold over interrupt
++ * @device_id: device id
++ *
++ * Returns 0 if success or a negative value if failure
++ */
+ int request_edma_channel(int channel,
+-                                              edma_irq_handler handler,
+-                                              edma_error_handler error_handler,
+-                                              void* dev,
+-                                              spinlock_t *lock,
+-                                              const char* device_id )
++      edma_irq_handler handler,
++      edma_error_handler error_handler,
++      void *arg,
++      spinlock_t *lock,
++      const char *device_id )
+ {
+       if (devp!=NULL && channel>=0 && channel<=EDMA_CHANNELS) {
+-              if (devp->dma_interrupt_handlers[channel].allocated) {
++              if (devp->dma_interrupt_handlers[channel].allocated)
+                       return -EBUSY;
+-              }
++
+               devp->dma_interrupt_handlers[channel].allocated = 1;
+               devp->dma_interrupt_handlers[channel].irq_handler = handler;
+               devp->dma_interrupt_handlers[channel].error_handler = error_handler;
+-              devp->dma_interrupt_handlers[channel].dev = dev;
++              devp->dma_interrupt_handlers[channel].arg = arg;
+               devp->dma_interrupt_handlers[channel].lock = lock;
+               devp->dma_interrupt_handlers[channel].device_id = device_id;
+               return 0;
+@@ -164,16 +205,22 @@ int request_edma_channel(int channel,
+ }
+ EXPORT_SYMBOL(request_edma_channel);
+-/* free eDMA channel */
+-int free_edma_channel(int channel, void* dev)
++/**
++ * free_edma_channel - Free the edma channel
++ * @channel: channel number
++ * @arg: argument created with
++ *
++ * Returns 0 if success or a negative value if failure
++ */
++int free_edma_channel(int channel, void *arg)
+ {
+       if (devp!=NULL && channel>=0 && channel<=EDMA_CHANNELS) {
+               if (devp->dma_interrupt_handlers[channel].allocated) {
+-                      if (devp->dma_interrupt_handlers[channel].dev != dev) {
++                      if (devp->dma_interrupt_handlers[channel].arg != arg)
+                               return -EBUSY;
+-                      }
++
+                       devp->dma_interrupt_handlers[channel].allocated = 0;
+-                      devp->dma_interrupt_handlers[channel].dev = NULL;
++                      devp->dma_interrupt_handlers[channel].arg = NULL;
+                       devp->dma_interrupt_handlers[channel].irq_handler = NULL;
+                       devp->dma_interrupt_handlers[channel].error_handler = NULL;
+                       devp->dma_interrupt_handlers[channel].lock = NULL;
+@@ -184,7 +231,9 @@ int free_edma_channel(int channel, void*
+ }
+ EXPORT_SYMBOL(free_edma_channel);
+-/* clean-up device driver allocated resources */
++/**
++ * coldfire_edma_cleanup - cleanup driver allocated resources
++ */
+ static void coldfire_edma_cleanup(void)
+ {
+       dev_t devno;
+@@ -192,13 +241,10 @@ static void coldfire_edma_cleanup(void)
+       /* free interrupts/memory */
+       if (devp) {
+-              for (i=0;i<EDMA_CHANNELS;i++)
+-              {
+-                      MCF_INTC0_SIMR = EDMA_INT_CHANNEL_BASE+i;
+-                      free_irq(EDMA_INT_CHANNEL_BASE+EDMA_INT_CONTROLLER_BASE+i,      devp);
+-              }
+-              MCF_INTC0_SIMR = EDMA_INT_CHANNEL_BASE+EDMA_CHANNELS;
+-              free_irq(EDMA_INT_CHANNEL_BASE+EDMA_INT_CONTROLLER_BASE+EDMA_CHANNELS, devp);
++              for (i=0; i<EDMA_CHANNELS; i++)
++                      free_irq(EDMA_INT_BASE+i, devp);
++
++              free_irq(EDMA_INT_BASE+EDMA_INT_ERR, devp);
+               cdev_del(&devp->cdev);
+               kfree(devp);
+       }
+@@ -209,30 +255,42 @@ static void coldfire_edma_cleanup(void)
+ }
+ #ifdef CONFIG_PROC_FS
+-/* proc file system support */
++/*
++ * proc file system support
++ */
+ #define FREE_CHANNEL "free"
+ #define DEVICE_UNKNOWN "device unknown"
++/**
++ * proc_edma_show - print out proc info
++ * @m: seq_file
++ * @v:
++ */
+ static int proc_edma_show(struct seq_file *m, void *v)
+ {
+       int i;
+-      if (devp==NULL) return 0;
++      if (devp == NULL)
++              return 0;
+       for (i = 0 ; i < EDMA_CHANNELS ; i++) {
+               if (devp->dma_interrupt_handlers[i].allocated) {
+                       if (devp->dma_interrupt_handlers[i].device_id)
+-                      seq_printf(m, "%2d: %s\n", i, devp->dma_interrupt_handlers[i].device_id);
++                              seq_printf(m, "%2d: %s\n", i, devp->dma_interrupt_handlers[i].device_id);
+                       else
+                               seq_printf(m, "%2d: %s\n", i, DEVICE_UNKNOWN);
+-              } else {
++              } else
+                       seq_printf(m, "%2d: %s\n", i, FREE_CHANNEL);
+-              }
+       }
+       return 0;
+ }
++/**
++ * proc_edma_open - open the proc file
++ * @inode: inode ptr
++ * @file: file ptr
++ */
+ static int proc_edma_open(struct inode *inode, struct file *file)
+ {
+       return single_open(file, proc_edma_show, NULL);
+@@ -245,6 +303,9 @@ static const struct file_operations proc
+       .release        = single_release,
+ };
++/**
++ * proc_edma_init - initialize proc filesystem
++ */
+ static int __init proc_edma_init(void)
+ {
+       struct proc_dir_entry *e;
+@@ -258,7 +319,9 @@ static int __init proc_edma_init(void)
+ #endif
+-/* initializes device driver */
++/**
++ * coldfire_edma_init - eDMA module init
++ */
+ static int __init coldfire_edma_init(void)
+ {
+       dev_t dev;
+@@ -267,8 +330,9 @@ static int __init coldfire_edma_init(voi
+       /* allocate free major number */
+       result = alloc_chrdev_region(&dev, DMA_DEV_MINOR, 1, EDMA_DRIVER_NAME);
+-      if (result<0) {
+-              printk(KERN_WARNING EDMA_DRIVER_NAME": can't get major %d\n", result);
++      if (result < 0) {
++              printk(KERN_WARNING EDMA_DRIVER_NAME": can't get major %d\n",
++                     result);
+               return result;
+       }
+       coldfire_dma_major = MAJOR(dev);
+@@ -280,71 +344,68 @@ static int __init coldfire_edma_init(voi
+               goto fail;
+       }
+-      /* init handlers (no handlers for beggining) */
+-      for (i=0;i<EDMA_CHANNELS;i++) {
++      /* init handlers (no handlers for beginning) */
++      for (i = 0; i < EDMA_CHANNELS; i++) {
+               devp->dma_interrupt_handlers[i].irq_handler = NULL;
+               devp->dma_interrupt_handlers[i].error_handler = NULL;
+-              devp->dma_interrupt_handlers[i].dev = NULL;
++              devp->dma_interrupt_handlers[i].arg = NULL;
+               devp->dma_interrupt_handlers[i].allocated = 0;
+               devp->dma_interrupt_handlers[i].lock = NULL;
+               devp->dma_interrupt_handlers[i].device_id = NULL;
+       }
+-    /* register char device */
++      /* register char device */
+       cdev_init(&devp->cdev, &coldfire_edma_fops);
+       devp->cdev.owner = THIS_MODULE;
+       devp->cdev.ops = &coldfire_edma_fops;
+       result = cdev_add(&devp->cdev, dev, 1);
+       if (result) {
+-              printk(KERN_NOTICE EDMA_DRIVER_NAME": Error %d adding coldfire-dma device\n", result);
++              printk(KERN_NOTICE EDMA_DRIVER_NAME
++                     ": Error %d adding coldfire-dma device\n", result);
+               result = -ENODEV;
+               goto fail;
+       }
+       /* request/enable irq for each eDMA channel */
+-      for (i=0;i<EDMA_CHANNELS;i++)
+-      {
+-              result = request_irq(EDMA_INT_CHANNEL_BASE+EDMA_INT_CONTROLLER_BASE+i,
+-                      dmaisr, SA_INTERRUPT, EDMA_DRIVER_NAME, devp);
++      for (i = 0; i < EDMA_CHANNELS;i++) {
++              result = request_irq(EDMA_INT_BASE + i,
++                                   dmaisr, IRQF_DISABLED,
++                                   EDMA_DRIVER_NAME, devp);
+               if (result) {
+-                      printk(KERN_WARNING EDMA_DRIVER_NAME": Cannot request irq %d\n",
+-                              EDMA_INT_CHANNEL_BASE+EDMA_INT_CONTROLLER_BASE+i);
++                      printk(KERN_WARNING EDMA_DRIVER_NAME
++                             ": Cannot request irq %d\n",
++                             (EDMA_INT_BASE + EDMA_INT_ERR+i));
+                       result = -EBUSY;
+                       goto fail;
+               }
+-
+-              MCF_INTC0_ICR(EDMA_INT_CHANNEL_BASE+i) = EDMA_IRQ_LEVEL;
+-              MCF_INTC0_CIMR = EDMA_INT_CHANNEL_BASE+i;
+-
+       }
+-    /* request error interrupt */
+-      result = request_irq(EDMA_INT_CHANNEL_BASE + EDMA_INT_CONTROLLER_BASE + EDMA_CHANNELS,
+-                              dma_error_isr, SA_INTERRUPT, EDMA_DRIVER_NAME, devp);
++      /* request error interrupt */
++      result = request_irq(EDMA_INT_BASE + EDMA_INT_ERR,
++                           dma_error_isr, IRQF_DISABLED,
++                           EDMA_DRIVER_NAME, devp);
+       if (result) {
+-              printk(KERN_WARNING EDMA_DRIVER_NAME": Cannot request irq %d\n",
+-                              EDMA_INT_CHANNEL_BASE+EDMA_INT_CONTROLLER_BASE+EDMA_CHANNELS);
++              printk(KERN_WARNING EDMA_DRIVER_NAME
++                     ": Cannot request irq %d\n",
++                     (EDMA_INT_BASE + EDMA_INT_ERR));
+               result = -EBUSY;
+               goto fail;
+       }
+-      /* enable error interrupt in interrupt controller */
+-      MCF_INTC0_ICR(EDMA_INT_CHANNEL_BASE+EDMA_CHANNELS) = EDMA_IRQ_LEVEL;
+-      MCF_INTC0_CIMR = EDMA_INT_CHANNEL_BASE+EDMA_CHANNELS;
+-
+ #ifdef CONFIG_PROC_FS
+       proc_edma_init();
+ #endif
+       printk(EDMA_DRIVER_NAME ": initialized successfully\n");
+-
+       return 0;
+ fail:
+       coldfire_edma_cleanup();
+       return result;
+-
+ }
++/**
++ * coldfire_edma_exit - eDMA module exit
++ */
+ static void __exit coldfire_edma_exit(void)
+ {
+       coldfire_edma_cleanup();
+@@ -354,5 +415,5 @@ module_init(coldfire_edma_init);
+ module_exit(coldfire_edma_exit);
+ MODULE_LICENSE("GPL");
+-MODULE_AUTHOR("Yaroslav Vinogradov, Freescale Inc.");
+-MODULE_DESCRIPTION("eDMA library for Coldfire 5445x");
++MODULE_AUTHOR("Freescale Semiconductor, Inc.");
++MODULE_DESCRIPTION("eDMA library for Coldfire M5445x");
+--- a/include/asm-m68k/coldfire_edma.h
++++ b/include/asm-m68k/coldfire_edma.h
+@@ -20,11 +20,14 @@
+ #define EDMA_DRIVER_NAME "ColdFire-eDMA"
+ #define DMA_DEV_MINOR 1
++#ifdef CONFIG_M54455
+ #define EDMA_INT_CHANNEL_BASE                 8
+ #define EDMA_INT_CONTROLLER_BASE      64
++#define EDMA_INT_BASE                 (EDMA_INT_CHANNEL_BASE + \
++                                       EDMA_INT_CONTROLLER_BASE)
+ #define EDMA_CHANNELS                 16
+- 
+-#define EDMA_IRQ_LEVEL                        5
++#define EDMA_INT_ERR                  16      /* edma error interrupt */
++#endif /* CONFIG_M54455 */
+  
+ typedef irqreturn_t (*edma_irq_handler)(int, void *);
+ typedef void (*edma_error_handler)(int, void *);
+@@ -38,7 +41,7 @@ typedef void (*edma_error_handler)(int, 
+  *   nbytes  - number of bytes to be transfered in minor loop
+  *   slast   - last source address adjustment
+  *   citer   - major loop count
+- *   biter   - beggining minor loop count
++ *   biter   - begining minor loop count
+  *   doff    - destination offset
+  *   dlast_sga - last destination address adjustment
+  *   major_int - generate interrupt after each major loop
+--- a/include/asm-m68k/mcf5445x_edma.h
++++ b/include/asm-m68k/mcf5445x_edma.h
+@@ -11,11 +11,27 @@
+ #ifndef __MCF5445X_EDMA_H__
+ #define __MCF5445X_EDMA_H__
+-/*********************************************************************
+-*
+-* Enhanced DMA (EDMA)
+-*
+-*********************************************************************/
++/*
++ * Enhanced DMA (EDMA)
++ */
++
++/* Channels */
++#define MCF_EDMA_CHAN_DREQ0   0       /* External DMA request 0 */
++#define MCF_EDMA_CHAN_DREQ1   1       /* External DMA request 1 */
++#define MCF_EDMA_CHAN_UART0_RX        2       /* UART0 Receive */
++#define MCF_EDMA_CHAN_UART0_TX        3       /* UART0 Transmit */
++#define MCF_EDMA_CHAN_UART1_RX        4       /* UART1 Receive */
++#define MCF_EDMA_CHAN_UART1_TX        5       /* UART1 Transmit */
++#define MCF_EDMA_CHAN_UART2_RX        6       /* UART2 Receive */
++#define MCF_EDMA_CHAN_UART2_TX        7       /* UART2 Transmit */
++#define MCF_EDMA_CHAN_TIMER0  8       /* Timer 0 / SSI0 Rx */
++#define MCF_EDMA_CHAN_TIMER1  9       /* Timer 1 / SSI1 Rx */
++#define MCF_EDMA_CHAN_TIMER2  10      /* Timer 2 / SSI0 Tx */
++#define MCF_EDMA_CHAN_TIMER3  11      /* Timer 3 / SSI1 Tx */
++#define MCF_EDMA_CHAN_DSPI_RX 12      /* DSPI Receive */
++#define MCF_EDMA_CHAN_DSPI_TX 13      /* DSPI Transmit */
++#define MCF_EDMA_CHAN_ATA_RX  14      /* ATA Receive */
++#define MCF_EDMA_CHAN_ATA_TX  15      /* ATA Transmit */
+ /* Register read/write macros */
+ #define MCF_EDMA_CR                     MCF_REG32(0xFC044000)
+@@ -1453,6 +1469,4 @@
+ #define MCF_EDMA_TCD15_CSR_LINKCH(x)    (((x)&0x003F)<<8)
+ #define MCF_EDMA_TCD15_CSR_BWC(x)       (((x)&0x0003)<<14)
+-/********************************************************************/
+-
+ #endif /* __MCF5445X_EDMA_H__ */