[PATCH] CRIS update: drivers
Mikael Starvik [Wed, 27 Jul 2005 18:44:34 +0000 (11:44 -0700)]
Updates to device drivers.

* Use I/O and DMA allocators.
* Use wait_event_interruptible instead of interrutiple_sleep_on.
* Added spinlocks SMP.
* Changed restore_flags to local_irq_restore etc.
* Updated IDE driver include to fit 2.6.12.

Signed-off-by: Mikael Starvik <starvik@axis.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

arch/cris/arch-v10/drivers/axisflashmap.c
arch/cris/arch-v10/drivers/ds1302.c
arch/cris/arch-v10/drivers/eeprom.c
arch/cris/arch-v10/drivers/gpio.c
arch/cris/arch-v10/drivers/i2c.c
arch/cris/arch-v10/drivers/pcf8563.c
arch/cris/arch-v10/kernel/Makefile
arch/cris/arch-v10/kernel/fasttimer.c
include/asm-cris/arch-v10/ide.h [new file with mode: 0644]
include/asm-cris/ide.h [new file with mode: 0644]

index fb7d485..11ab383 100644 (file)
@@ -11,6 +11,9 @@
  * partition split defined below.
  *
  * $Log: axisflashmap.c,v $
+ * Revision 1.11  2004/11/15 10:27:14  starvik
+ * Corrected typo (Thanks to Milton Miller <miltonm@bga.com>).
+ *
  * Revision 1.10  2004/08/16 12:37:22  starvik
  * Merge of Linux 2.6.8
  *
 #elif CONFIG_ETRAX_FLASH_BUSWIDTH==2
 #define flash_data __u16
 #elif CONFIG_ETRAX_FLASH_BUSWIDTH==4
-#define flash_data __u16
+#define flash_data __u32
 #endif
 
 /* From head.S */
index fba530f..10795f6 100644 (file)
@@ -7,6 +7,15 @@
 *! Functions exported: ds1302_readreg, ds1302_writereg, ds1302_init
 *!
 *! $Log: ds1302.c,v $
+*! Revision 1.18  2005/01/24 09:11:26  mikaelam
+*! Minor changes to get DS1302 RTC chip driver to work
+*!
+*! Revision 1.17  2005/01/05 06:11:22  starvik
+*! No need to do local_irq_disable after local_irq_save.
+*!
+*! Revision 1.16  2004/12/13 12:21:52  starvik
+*! Added I/O and DMA allocators from Linux 2.4
+*!
 *! Revision 1.14  2004/08/24 06:48:43  starvik
 *! Whitespace cleanup
 *!
 *!
 *! ---------------------------------------------------------------------------
 *!
-*! (C) Copyright 1999, 2000, 2001  Axis Communications AB, LUND, SWEDEN
+*! (C) Copyright 1999, 2000, 2001, 2002, 2003, 2004  Axis Communications AB, LUND, SWEDEN
 *!
-*! $Id: ds1302.c,v 1.14 2004/08/24 06:48:43 starvik Exp $
+*! $Id: ds1302.c,v 1.18 2005/01/24 09:11:26 mikaelam Exp $
 *!
 *!***************************************************************************/
 
 #include <asm/arch/svinto.h>
 #include <asm/io.h>
 #include <asm/rtc.h>
+#include <asm/arch/io_interface_mux.h>
 
 #define RTC_MAJOR_NR 121 /* local major, change later */
 
@@ -320,7 +330,6 @@ get_rtc_time(struct rtc_time *rtc_tm)
        unsigned long flags;
 
        local_irq_save(flags);
-       local_irq_disable();
 
        rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS);
        rtc_tm->tm_min = CMOS_READ(RTC_MINUTES);
@@ -358,7 +367,7 @@ static int
 rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
          unsigned long arg) 
 {
-        unsigned long flags;
+       unsigned long flags;
 
        switch(cmd) {
                case RTC_RD_TIME:       /* read the time/date from RTC  */
@@ -382,7 +391,7 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                                return -EPERM;
 
                        if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time)))
-                               return -EFAULT;         
+                               return -EFAULT;
 
                        yrs = rtc_tm.tm_year + 1900;
                        mon = rtc_tm.tm_mon + 1;   /* tm_mon starts at zero */
@@ -419,7 +428,6 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                        BIN_TO_BCD(yrs);
 
                        local_irq_save(flags);
-                       local_irq_disable();
                        CMOS_WRITE(yrs, RTC_YEAR);
                        CMOS_WRITE(mon, RTC_MONTH);
                        CMOS_WRITE(day, RTC_DAY_OF_MONTH);
@@ -438,7 +446,7 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 
                case RTC_SET_CHARGE: /* set the RTC TRICKLE CHARGE register */
                {
-                       int tcs_val;                        
+                       int tcs_val;
 
                        if (!capable(CAP_SYS_TIME))
                                return -EPERM;
@@ -492,8 +500,8 @@ print_rtc_status(void)
 /* The various file operations we support. */
 
 static struct file_operations rtc_fops = {
-        .owner          = THIS_MODULE,
-        .ioctl          = rtc_ioctl,   
+       .owner =        THIS_MODULE,
+       .ioctl =        rtc_ioctl,
 }; 
 
 /* Probe for the chip by writing something to its RAM and try reading it back. */
@@ -532,7 +540,7 @@ ds1302_probe(void)
                       "PB",
 #endif
                       CONFIG_ETRAX_DS1302_RSTBIT);
-                print_rtc_status();
+                      print_rtc_status();
                retval = 1;
        } else {
                stop();
@@ -548,7 +556,9 @@ ds1302_probe(void)
 int __init
 ds1302_init(void) 
 {
+#ifdef CONFIG_ETRAX_I2C
        i2c_init();
+#endif
 
        if (!ds1302_probe()) {
 #ifdef CONFIG_ETRAX_DS1302_RST_ON_GENERIC_PORT
@@ -558,25 +568,42 @@ ds1302_init(void)
                 *
                 * Make sure that R_GEN_CONFIG is setup correct.
                 */
-               genconfig_shadow = ((genconfig_shadow &
-                                    ~IO_MASK(R_GEN_CONFIG, ata)) | 
-                                  (IO_STATE(R_GEN_CONFIG, ata, select)));    
-               *R_GEN_CONFIG = genconfig_shadow;
+               /* Allocating the ATA interface will grab almost all
+                * pins in I/O groups a, b, c and d.  A consequence of
+                * allocating the ATA interface is that the fixed
+                * interfaces shared RAM, parallel port 0, parallel
+                * port 1, parallel port W, SCSI-8 port 0, SCSI-8 port
+                * 1, SCSI-W, serial port 2, serial port 3,
+                * synchronous serial port 3 and USB port 2 and almost
+                * all GPIO pins on port g cannot be used.
+                */
+               if (cris_request_io_interface(if_ata, "ds1302/ATA")) {
+                       printk(KERN_WARNING "ds1302: Failed to get IO interface\n");
+                       return -1;
+               }
+
 #elif CONFIG_ETRAX_DS1302_RSTBIT == 0
-               
-               /* Set the direction of this bit to out. */             
-               genconfig_shadow = ((genconfig_shadow &
-                                    ~IO_MASK(R_GEN_CONFIG, g0dir)) | 
-                                  (IO_STATE(R_GEN_CONFIG, g0dir, out)));    
-               *R_GEN_CONFIG = genconfig_shadow;
+               if (cris_io_interface_allocate_pins(if_gpio_grp_a,
+                                                   'g',
+                                                   CONFIG_ETRAX_DS1302_RSTBIT,
+                                                   CONFIG_ETRAX_DS1302_RSTBIT)) {
+                       printk(KERN_WARNING "ds1302: Failed to get IO interface\n");
+                       return -1;
+               }
+
+               /* Set the direction of this bit to out. */
+               genconfig_shadow = ((genconfig_shadow &
+                                    ~IO_MASK(R_GEN_CONFIG, g0dir)) |
+                                  (IO_STATE(R_GEN_CONFIG, g0dir, out)));
+               *R_GEN_CONFIG = genconfig_shadow;
 #endif
                if (!ds1302_probe()) {
                        printk(KERN_WARNING "%s: RTC not found.\n", ds1302_name);
-                       return -1;
+                       return -1;
                }
 #else
                printk(KERN_WARNING "%s: RTC not found.\n", ds1302_name);
-               return -1;
+               return -1;
 #endif
        }
        /* Initialise trickle charger */
index 316ca15..512f16d 100644 (file)
 *!                                  in the spin-lock.
 *!
 *!  $Log: eeprom.c,v $
+*!  Revision 1.12  2005/06/19 17:06:46  starvik
+*!  Merge of Linux 2.6.12.
+*!
+*!  Revision 1.11  2005/01/26 07:14:46  starvik
+*!  Applied diff from kernel janitors (Nish Aravamudan).
+*!
 *!  Revision 1.10  2003/09/11 07:29:48  starvik
 *!  Merge of Linux 2.6.0-test5
 *!
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/wait.h>
 #include <asm/uaccess.h>
 #include "i2c.h"
 
@@ -526,15 +533,10 @@ static ssize_t eeprom_read(struct file * file, char * buf, size_t count, loff_t
     return -EFAULT;
   }
   
-  while(eeprom.busy)
-  {
-    interruptible_sleep_on(&eeprom.wait_q);
+  wait_event_interruptible(eeprom.wait_q, !eeprom.busy);
+  if (signal_pending(current))
+    return -EINTR;
 
-    /* bail out if we get interrupted */
-    if (signal_pending(current))
-      return -EINTR;
-    
-  }
   eeprom.busy++;
 
   page = (unsigned char) (p >> 8);
@@ -604,13 +606,10 @@ static ssize_t eeprom_write(struct file * file, const char * buf, size_t count,
     return -EFAULT;
   }
 
-  while(eeprom.busy)
-  {
-    interruptible_sleep_on(&eeprom.wait_q);
-    /* bail out if we get interrupted */
-    if (signal_pending(current))
-      return -EINTR;
-  }
+  wait_event_interruptible(eeprom.wait_q, !eeprom.busy);
+  /* bail out if we get interrupted */
+  if (signal_pending(current))
+    return -EINTR;
   eeprom.busy++;
   for(i = 0; (i < EEPROM_RETRIES) && (restart > 0); i++)
   {
index c095de8..09963fe 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: gpio.c,v 1.12 2004/08/24 07:19:59 starvik Exp $
+/* $Id: gpio.c,v 1.17 2005/06/19 17:06:46 starvik Exp $
  *
  * Etrax general port I/O device
  *
@@ -9,6 +9,18 @@
  *             Johan Adolfsson  (read/set directions, write, port G)
  *
  * $Log: gpio.c,v $
+ * Revision 1.17  2005/06/19 17:06:46  starvik
+ * Merge of Linux 2.6.12.
+ *
+ * Revision 1.16  2005/03/07 13:02:29  starvik
+ * Protect driver global states with spinlock
+ *
+ * Revision 1.15  2005/01/05 06:08:55  starvik
+ * No need to do local_irq_disable after local_irq_save.
+ *
+ * Revision 1.14  2004/12/13 12:21:52  starvik
+ * Added I/O and DMA allocators from Linux 2.4
+ *
  * Revision 1.12  2004/08/24 07:19:59  starvik
  * Whitespace cleanup
  *
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/irq.h>
+#include <asm/arch/io_interface_mux.h>
 
 #define GPIO_MAJOR 120  /* experimental MAJOR number */
 
@@ -194,6 +207,8 @@ static struct gpio_private *alarmlist = 0;
 static int gpio_some_alarms = 0; /* Set if someone uses alarm */
 static unsigned long gpio_pa_irq_enabled_mask = 0;
 
+static DEFINE_SPINLOCK(gpio_lock); /* Protect directions etc */
+
 /* Port A and B use 8 bit access, but Port G is 32 bit */
 #define NUM_PORTS (GPIO_MINOR_B+1)
 
@@ -241,6 +256,9 @@ static volatile unsigned char *dir_shadow[NUM_PORTS] = {
        &port_pb_dir_shadow 
 };
 
+/* All bits in port g that can change dir. */
+static const unsigned long int changeable_dir_g_mask = 0x01FFFF01;
+
 /* Port G is 32 bit, handle it special, some bits are both inputs 
    and outputs at the same time, only some of the bits can change direction
    and some of them in groups of 8 bit. */
@@ -260,6 +278,7 @@ gpio_poll(struct file *file,
        unsigned int mask = 0;
        struct gpio_private *priv = (struct gpio_private *)file->private_data;
        unsigned long data;
+       spin_lock(&gpio_lock);
        poll_wait(file, &priv->alarm_wq, wait);
        if (priv->minor == GPIO_MINOR_A) {
                unsigned long flags;
@@ -270,10 +289,10 @@ gpio_poll(struct file *file,
                 */
                tmp = ~data & priv->highalarm & 0xFF;
                tmp = (tmp << R_IRQ_MASK1_SET__pa0__BITNR);
-               save_flags(flags); cli();
+               local_irq_save(flags);
                gpio_pa_irq_enabled_mask |= tmp;
                *R_IRQ_MASK1_SET = tmp;
-               restore_flags(flags);
+               local_irq_restore(flags);
 
        } else if (priv->minor == GPIO_MINOR_B)
                data = *R_PORT_PB_DATA;
@@ -286,8 +305,11 @@ gpio_poll(struct file *file,
            (~data & priv->lowalarm)) {
                mask = POLLIN|POLLRDNORM;
        }
+
+       spin_unlock(&gpio_lock);
        
        DP(printk("gpio_poll ready: mask 0x%08X\n", mask));
+
        return mask;
 }
 
@@ -296,6 +318,7 @@ int etrax_gpio_wake_up_check(void)
        struct gpio_private *priv = alarmlist;
        unsigned long data = 0;
         int ret = 0;
+       spin_lock(&gpio_lock);
        while (priv) {
                if (USE_PORTS(priv)) {
                        data = *priv->port;
@@ -310,6 +333,7 @@ int etrax_gpio_wake_up_check(void)
                }
                priv = priv->next;
        }
+       spin_unlock(&gpio_lock);
         return ret;
 }
 
@@ -327,6 +351,7 @@ static irqreturn_t
 gpio_pa_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
        unsigned long tmp;
+       spin_lock(&gpio_lock);
        /* Find what PA interrupts are active */
        tmp = (*R_IRQ_READ1);
 
@@ -337,6 +362,8 @@ gpio_pa_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        *R_IRQ_MASK1_CLR = tmp;
        gpio_pa_irq_enabled_mask &= ~tmp;
 
+       spin_unlock(&gpio_lock);
+
        if (gpio_some_alarms) {
                return IRQ_RETVAL(etrax_gpio_wake_up_check());
        }
@@ -350,6 +377,9 @@ static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
        struct gpio_private *priv = (struct gpio_private *)file->private_data;
        unsigned char data, clk_mask, data_mask, write_msb;
        unsigned long flags;
+
+       spin_lock(&gpio_lock);
+
        ssize_t retval = count;
        if (priv->minor !=GPIO_MINOR_A && priv->minor != GPIO_MINOR_B) {
                return -EFAULT;
@@ -372,7 +402,7 @@ static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
                data = *buf++;
                if (priv->write_msb) {
                        for (i = 7; i >= 0;i--) {
-                               local_irq_save(flags); local_irq_disable();
+                               local_irq_save(flags);
                                *priv->port = *priv->shadow &= ~clk_mask;
                                if (data & 1<<i)
                                        *priv->port = *priv->shadow |= data_mask;
@@ -384,7 +414,7 @@ static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
                        }
                } else {
                        for (i = 0; i <= 7;i++) {
-                               local_irq_save(flags); local_irq_disable();
+                               local_irq_save(flags);
                                *priv->port = *priv->shadow &= ~clk_mask;
                                if (data & 1<<i)
                                        *priv->port = *priv->shadow |= data_mask;
@@ -396,6 +426,7 @@ static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
                        }
                }
        }
+       spin_unlock(&gpio_lock);
        return retval;
 }
 
@@ -452,9 +483,14 @@ gpio_open(struct inode *inode, struct file *filp)
 static int
 gpio_release(struct inode *inode, struct file *filp)
 {
-       struct gpio_private *p = alarmlist;
-       struct gpio_private *todel = (struct gpio_private *)filp->private_data;
-       
+       struct gpio_private *p;
+       struct gpio_private *todel;
+
+       spin_lock(&gpio_lock);
+
+        p = alarmlist;
+        todel = (struct gpio_private *)filp->private_data;
+
        /* unlink from alarmlist and free the private structure */
 
        if (p == todel) {
@@ -476,7 +512,7 @@ gpio_release(struct inode *inode, struct file *filp)
                p = p->next;
        }
        gpio_some_alarms = 0;
-               
+       spin_unlock(&gpio_lock);
        return 0;
 }
 
@@ -491,14 +527,14 @@ unsigned long inline setget_input(struct gpio_private *priv, unsigned long arg)
         */
        unsigned long flags;
        if (USE_PORTS(priv)) {
-               local_irq_save(flags); local_irq_disable();
+               local_irq_save(flags);
                *priv->dir = *priv->dir_shadow &= 
                ~((unsigned char)arg & priv->changeable_dir);
                local_irq_restore(flags);
                return ~(*priv->dir_shadow) & 0xFF; /* Only 8 bits */
        } else if (priv->minor == GPIO_MINOR_G) {
                /* We must fiddle with R_GEN_CONFIG to change dir */
-               save_flags(flags); cli();
+               local_irq_save(flags);
                if (((arg & dir_g_in_bits) != arg) && 
                    (arg & changeable_dir_g)) {
                        arg &= changeable_dir_g;
@@ -533,7 +569,7 @@ unsigned long inline setget_input(struct gpio_private *priv, unsigned long arg)
                        /* Must be a >120 ns delay before writing this again */
                                
                }
-               restore_flags(flags);
+               local_irq_restore(flags);
                return dir_g_in_bits;
        }
        return 0;
@@ -543,14 +579,14 @@ unsigned long inline setget_output(struct gpio_private *priv, unsigned long arg)
 {
        unsigned long flags;
        if (USE_PORTS(priv)) {
-               local_irq_save(flags); local_irq_disable();
+               local_irq_save(flags);
                *priv->dir = *priv->dir_shadow |= 
                  ((unsigned char)arg & priv->changeable_dir);
                local_irq_restore(flags);
                return *priv->dir_shadow;
        } else if (priv->minor == GPIO_MINOR_G) {
                /* We must fiddle with R_GEN_CONFIG to change dir */                    
-               save_flags(flags); cli();
+               local_irq_save(flags);
                if (((arg & dir_g_out_bits) != arg) &&
                    (arg & changeable_dir_g)) {
                        /* Set bits in genconfig to set to output */
@@ -583,7 +619,7 @@ unsigned long inline setget_output(struct gpio_private *priv, unsigned long arg)
                        *R_GEN_CONFIG = genconfig_shadow;
                        /* Must be a >120 ns delay before writing this again */
                }
-               restore_flags(flags);
+               local_irq_restore(flags);
                return dir_g_out_bits & 0x7FFFFFFF;
        }
        return 0;
@@ -598,22 +634,26 @@ gpio_ioctl(struct inode *inode, struct file *file,
 {
        unsigned long flags;
        unsigned long val;
+        int ret = 0;
+
        struct gpio_private *priv = (struct gpio_private *)file->private_data;
        if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE) {
                return -EINVAL;
        }
 
+       spin_lock(&gpio_lock);
+
        switch (_IOC_NR(cmd)) {
        case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */
                // read the port
                if (USE_PORTS(priv)) {
-                       return *priv->port;
+                       ret =  *priv->port;
                } else if (priv->minor == GPIO_MINOR_G) {
-                       return (*R_PORT_G_DATA) & 0x7FFFFFFF;
+                       ret =  (*R_PORT_G_DATA) & 0x7FFFFFFF;
                }
                break;
        case IO_SETBITS:
-               local_irq_save(flags); local_irq_disable();
+               local_irq_save(flags);
                // set changeable bits with a 1 in arg
                if (USE_PORTS(priv)) {
                        *priv->port = *priv->shadow |= 
@@ -624,7 +664,7 @@ gpio_ioctl(struct inode *inode, struct file *file,
                local_irq_restore(flags);
                break;
        case IO_CLRBITS:
-               local_irq_save(flags); local_irq_disable();
+               local_irq_save(flags);
                // clear changeable bits with a 1 in arg
                if (USE_PORTS(priv)) {
                        *priv->port = *priv->shadow &= 
@@ -666,33 +706,34 @@ gpio_ioctl(struct inode *inode, struct file *file,
        case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */
                /* Read direction 0=input 1=output */
                if (USE_PORTS(priv)) {
-                       return *priv->dir_shadow;
+                       ret = *priv->dir_shadow;
                } else if (priv->minor == GPIO_MINOR_G) {
                        /* Note: Some bits are both in and out,
                         * Those that are dual is set here as well.
                         */
-                       return (dir_g_shadow | dir_g_out_bits) & 0x7FFFFFFF;
+                       ret = (dir_g_shadow | dir_g_out_bits) & 0x7FFFFFFF;
                }
+               break;
        case IO_SETINPUT: /* Use IO_SETGET_INPUT instead! */
                /* Set direction 0=unchanged 1=input, 
                 * return mask with 1=input 
                 */
-               return setget_input(priv, arg) & 0x7FFFFFFF;
+               ret = setget_input(priv, arg) & 0x7FFFFFFF;
                break;
        case IO_SETOUTPUT: /* Use IO_SETGET_OUTPUT instead! */
                /* Set direction 0=unchanged 1=output, 
                 * return mask with 1=output 
                 */
-               return setget_output(priv, arg) & 0x7FFFFFFF;
-
+               ret =  setget_output(priv, arg) & 0x7FFFFFFF;
+               break;
        case IO_SHUTDOWN:
                SOFT_SHUTDOWN();
                break;
        case IO_GET_PWR_BT:
 #if defined (CONFIG_ETRAX_SOFT_SHUTDOWN)
-               return (*R_PORT_G_DATA & ( 1 << CONFIG_ETRAX_POWERBUTTON_BIT));
+               ret = (*R_PORT_G_DATA & ( 1 << CONFIG_ETRAX_POWERBUTTON_BIT));
 #else
-               return 0;
+               ret = 0;
 #endif
                break;
        case IO_CFG_WRITE_MODE:
@@ -709,7 +750,7 @@ gpio_ioctl(struct inode *inode, struct file *file,
                {
                        priv->clk_mask = 0;
                        priv->data_mask = 0;
-                       return -EPERM;
+                       ret = -EPERM;
                }
                break;
        case IO_READ_INBITS: 
@@ -720,8 +761,7 @@ gpio_ioctl(struct inode *inode, struct file *file,
                        val = *R_PORT_G_DATA;
                }
                if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
-                       return -EFAULT;
-               return 0;
+                       ret = -EFAULT;
                break;
        case IO_READ_OUTBITS:
                 /* *arg is result of reading the output shadow */
@@ -731,36 +771,43 @@ gpio_ioctl(struct inode *inode, struct file *file,
                        val = port_g_data_shadow;
                }
                if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
-                       return -EFAULT;
+                       ret = -EFAULT;
                break;
        case IO_SETGET_INPUT: 
                /* bits set in *arg is set to input,
                 * *arg updated with current input pins.
                 */
                if (copy_from_user(&val, (unsigned long*)arg, sizeof(val)))
-                       return -EFAULT;
+               {
+                       ret = -EFAULT;
+                       break;
+               }
                val = setget_input(priv, val);
                if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
-                       return -EFAULT;
+                       ret = -EFAULT;
                break;
        case IO_SETGET_OUTPUT:
                /* bits set in *arg is set to output,
                 * *arg updated with current output pins.
                 */
                if (copy_from_user(&val, (unsigned long*)arg, sizeof(val)))
-                       return -EFAULT;
+               {
+                       ret = -EFAULT;
+                       break;
+               }
                val = setget_output(priv, val);
                if (copy_to_user((unsigned long*)arg, &val, sizeof(val)))
-                       return -EFAULT;
+                       ret = -EFAULT;
                break;
        default:
                if (priv->minor == GPIO_MINOR_LEDS)
-                       return gpio_leds_ioctl(cmd, arg);
+                       ret = gpio_leds_ioctl(cmd, arg);
                else
-                       return -EINVAL;
+                       ret = -EINVAL;
        } /* switch */
-       
-       return 0;
+
+       spin_unlock(&gpio_lock);
+       return ret;
 }
 
 static int
@@ -802,60 +849,20 @@ struct file_operations gpio_fops = {
 };
 
 
-static void __init gpio_init_port_g(void)
+void ioif_watcher(const unsigned int gpio_in_available,
+                 const unsigned int gpio_out_available,
+                 const unsigned char pa_available,
+                 const unsigned char pb_available)
 {
-#define GROUPA (0x0000FF3F)
-#define GROUPB (1<<6 | 1<<7)
-#define GROUPC (1<<30 | 1<<31)
-#define GROUPD (0x3FFF0000)
-#define GROUPD_LOW (0x00FF0000)
-       unsigned long used_in_bits = 0;
-       unsigned long used_out_bits = 0;
-       if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, scsi0, select)){
-               used_in_bits  |= GROUPA | GROUPB | 0 | 0;
-               used_out_bits |= GROUPA | GROUPB | 0 | 0;
-       }
-       if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, ata, select)) {
-               used_in_bits  |= GROUPA | GROUPB | GROUPC | (GROUPD & ~(1<<25|1<<26));
-               used_out_bits |= GROUPA | GROUPB | GROUPC | GROUPD;
-       }
+       unsigned long int flags;
+       D(printk("gpio.c: ioif_watcher called\n"));
+       D(printk("gpio.c: G in: 0x%08x G out: 0x%08x PA: 0x%02x PB: 0x%02x\n",
+                gpio_in_available, gpio_out_available, pa_available, pb_available));
 
-       if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, par0, select)) {
-               used_in_bits  |= (GROUPA & ~(1<<0)) | 0 | 0 | 0;
-               used_out_bits |= (GROUPA & ~(1<<0)) | 0 | 0 | 0;
-       }
-       if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, ser2, select)) {
-               used_in_bits  |= 0 | GROUPB | 0 | 0;
-               used_out_bits |= 0 | GROUPB | 0 | 0;
-       }
-       /* mio same as shared RAM ? */
-       if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, mio, select)) {
-               used_in_bits  |= (GROUPA & ~(1<<0)) | 0 |0 |GROUPD_LOW;
-               used_out_bits |= (GROUPA & ~(1<<0|1<<1|1<<2)) | 0 |0 |GROUPD_LOW;
-       }
-       if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, scsi1, select)) {
-               used_in_bits  |= 0 | 0 | GROUPC | GROUPD;
-               used_out_bits |= 0 | 0 | GROUPC | GROUPD;
-       }
-       if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, scsi0w, select)) {
-               used_in_bits  |= GROUPA | GROUPB | 0 | (GROUPD_LOW | 1<<24);
-               used_out_bits |= GROUPA | GROUPB | 0 | (GROUPD_LOW | 1<<24 | 1<<25|1<<26);
-       }
+       spin_lock_irqsave(&gpio_lock, flags);
 
-       if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, par1, select)) {
-               used_in_bits  |= 0 | 0 | 0 | (GROUPD & ~(1<<24));
-               used_out_bits |= 0 | 0 | 0 | (GROUPD & ~(1<<24));
-       }
-       if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, ser3, select)) {
-               used_in_bits  |= 0 | 0 | GROUPC | 0;
-               used_out_bits |= 0 | 0 | GROUPC | 0;
-       }
-       /* mio same as shared RAM-W? */
-       if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, mio_w, select)) {
-               used_in_bits  |= (GROUPA & ~(1<<0)) | 0 | 0 |GROUPD_LOW;
-               used_out_bits |= (GROUPA & ~(1<<0|1<<1|1<<2)) | 0 | 0 |GROUPD_LOW;
-       }
-       /* TODO: USB p2, parw, sync ser3? */
+       dir_g_in_bits = gpio_in_available;
+       dir_g_out_bits = gpio_out_available;
 
        /* Initialise the dir_g_shadow etc. depending on genconfig */
        /* 0=input 1=output */
@@ -868,10 +875,7 @@ static void __init gpio_init_port_g(void)
        if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g24dir, out))
                dir_g_shadow |= (1 << 24);
 
-       dir_g_in_bits = ~used_in_bits;
-       dir_g_out_bits = ~used_out_bits;
-
-       changeable_dir_g = 0x01FFFF01; /* all that can change dir */
+       changeable_dir_g = changeable_dir_g_mask;
        changeable_dir_g &= dir_g_out_bits;
        changeable_dir_g &= dir_g_in_bits;
        /* Correct the bits that can change direction */ 
@@ -880,6 +884,7 @@ static void __init gpio_init_port_g(void)
        dir_g_in_bits &= ~changeable_dir_g;
        dir_g_in_bits |= (~dir_g_shadow & changeable_dir_g);
 
+       spin_unlock_irqrestore(&gpio_lock, flags);
 
        printk(KERN_INFO "GPIO port G: in_bits: 0x%08lX out_bits: 0x%08lX val: %08lX\n",
               dir_g_in_bits, dir_g_out_bits, (unsigned long)*R_PORT_G_DATA);
@@ -896,6 +901,7 @@ gpio_init(void)
 #if defined (CONFIG_ETRAX_CSP0_LEDS)
        int i;
 #endif
+        printk("gpio init\n");
 
        /* do the formalities */
 
@@ -919,8 +925,13 @@ gpio_init(void)
 #endif
 
 #endif
-       gpio_init_port_g();
-       printk(KERN_INFO "ETRAX 100LX GPIO driver v2.5, (c) 2001, 2002 Axis Communications AB\n");
+       /* The I/O interface allocation watcher will be called when
+        * registering it. */
+       if (cris_io_interface_register_watcher(ioif_watcher)){
+               printk(KERN_WARNING "gpio_init: Failed to install IO if allocator watcher\n");
+       }
+
+       printk(KERN_INFO "ETRAX 100LX GPIO driver v2.5, (c) 2001, 2002, 2003, 2004 Axis Communications AB\n");
        /* We call etrax_gpio_wake_up_check() from timer interrupt and
         * from cpu_idle() in kernel/process.c
         * The check in cpu_idle() reduces latency from ~15 ms to ~6 ms
index 8bbe233..b38267d 100644 (file)
 *!                                 don't use PB_I2C if DS1302 uses same bits,
 *!                                 use PB.
 *! $Log: i2c.c,v $
+*! Revision 1.13  2005/03/07 13:13:07  starvik
+*! Added spinlocks to protect states etc
+*!
+*! Revision 1.12  2005/01/05 06:11:22  starvik
+*! No need to do local_irq_disable after local_irq_save.
+*!
+*! Revision 1.11  2004/12/13 12:21:52  starvik
+*! Added I/O and DMA allocators from Linux 2.4
+*!
 *! Revision 1.9  2004/08/24 06:49:14  starvik
 *! Whitespace cleanup
 *!
@@ -75,7 +84,7 @@
 *! (C) Copyright 1999-2002 Axis Communications AB, LUND, SWEDEN
 *!
 *!***************************************************************************/
-/* $Id: i2c.c,v 1.9 2004/08/24 06:49:14 starvik Exp $ */
+/* $Id: i2c.c,v 1.13 2005/03/07 13:13:07 starvik Exp $ */
 
 /****************** INCLUDE FILES SECTION ***********************************/
 
 #include <asm/arch/svinto.h>
 #include <asm/io.h>
 #include <asm/delay.h>
+#include <asm/arch/io_interface_mux.h>
 
 #include "i2c.h"
 
@@ -184,6 +194,7 @@ static const char i2c_name[] = "i2c";
 
 #define i2c_delay(usecs) udelay(usecs)
 
+static DEFINE_SPINLOCK(i2c_lock); /* Protect directions etc */
 
 /****************** FUNCTION DEFINITION SECTION *************************/
 
@@ -488,13 +499,14 @@ i2c_writereg(unsigned char theSlave, unsigned char theReg,
        int error, cntr = 3;
        unsigned long flags;
 
+       spin_lock(&i2c_lock);
+
        do {
                error = 0;
                /*
                 * we don't like to be interrupted
                 */
                local_irq_save(flags);
-               local_irq_disable();
 
                i2c_start();
                /*
@@ -538,6 +550,8 @@ i2c_writereg(unsigned char theSlave, unsigned char theReg,
 
        i2c_delay(CLOCK_LOW_TIME);
 
+       spin_unlock(&i2c_lock);
+
        return -error;
 }
 
@@ -555,13 +569,14 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg)
        int error, cntr = 3;
        unsigned long flags;
 
+       spin_lock(&i2c_lock);
+
        do {
                error = 0;
                /*
                 * we don't like to be interrupted
                 */
                local_irq_save(flags);
-               local_irq_disable();
                /*
                 * generate start condition
                 */
@@ -620,6 +635,8 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg)
                
        } while(error && cntr--);
 
+       spin_unlock(&i2c_lock);
+
        return b;
 }
 
@@ -686,15 +703,26 @@ static struct file_operations i2c_fops = {
 int __init
 i2c_init(void)
 {
+       static int res = 0;
+       static int first = 1;
+
+       if (!first) {
+               return res;
+       }
+
        /* Setup and enable the Port B I2C interface */
 
 #ifndef CONFIG_ETRAX_I2C_USES_PB_NOT_PB_I2C
+       if ((res = cris_request_io_interface(if_i2c, "I2C"))) {
+               printk(KERN_CRIT "i2c_init: Failed to get IO interface\n");
+               return res;
+       }
+
        *R_PORT_PB_I2C = port_pb_i2c_shadow |= 
                IO_STATE(R_PORT_PB_I2C, i2c_en,  on) |
                IO_FIELD(R_PORT_PB_I2C, i2c_d,   1)  |
                IO_FIELD(R_PORT_PB_I2C, i2c_clk, 1)  |
                IO_STATE(R_PORT_PB_I2C, i2c_oe_, enable);
-#endif
 
        port_pb_dir_shadow &= ~IO_MASK(R_PORT_PB_DIR, dir0);
        port_pb_dir_shadow &= ~IO_MASK(R_PORT_PB_DIR, dir1);
@@ -702,8 +730,26 @@ i2c_init(void)
        *R_PORT_PB_DIR = (port_pb_dir_shadow |=
                          IO_STATE(R_PORT_PB_DIR, dir0, input)  |
                          IO_STATE(R_PORT_PB_DIR, dir1, output));
+#else
+        if ((res = cris_io_interface_allocate_pins(if_i2c,
+                                                  'b',
+                                                   CONFIG_ETRAX_I2C_DATA_PORT,
+                                                  CONFIG_ETRAX_I2C_DATA_PORT))) {
+               printk(KERN_WARNING "i2c_init: Failed to get IO pin for I2C data port\n");
+               return res;
+       } else if ((res = cris_io_interface_allocate_pins(if_i2c,
+                                                         'b',
+                                                         CONFIG_ETRAX_I2C_CLK_PORT,
+                                                         CONFIG_ETRAX_I2C_CLK_PORT))) {
+               cris_io_interface_free_pins(if_i2c,
+                                           'b',
+                                           CONFIG_ETRAX_I2C_DATA_PORT,
+                                           CONFIG_ETRAX_I2C_DATA_PORT);
+               printk(KERN_WARNING "i2c_init: Failed to get IO pin for I2C clk port\n");
+       }
+#endif
 
-       return 0;
+       return res;
 }
 
 static int __init
@@ -711,14 +757,16 @@ i2c_register(void)
 {
        int res;
 
-       i2c_init();
+       res = i2c_init();
+       if (res < 0)
+               return res;
        res = register_chrdev(I2C_MAJOR, i2c_name, &i2c_fops);
        if(res < 0) {
                printk(KERN_ERR "i2c: couldn't get a major number.\n");
                return res;
        }
 
-       printk(KERN_INFO "I2C driver v2.2, (c) 1999-2001 Axis Communications AB\n");
+       printk(KERN_INFO "I2C driver v2.2, (c) 1999-2004 Axis Communications AB\n");
        
        return 0;
 }
index b3dfdf7..201f4c9 100644 (file)
@@ -15,7 +15,7 @@
  *
  * Author: Tobias Anderberg <tobiasa@axis.com>.
  *
- * $Id: pcf8563.c,v 1.8 2004/08/24 06:42:51 starvik Exp $
+ * $Id: pcf8563.c,v 1.11 2005/03/07 13:13:07 starvik Exp $
  */
 
 #include <linux/config.h>
@@ -40,7 +40,7 @@
 #define PCF8563_MAJOR 121              /* Local major number. */
 #define DEVICE_NAME "rtc"              /* Name which is registered in /proc/devices. */
 #define PCF8563_NAME "PCF8563"
-#define DRIVER_VERSION "$Revision: 1.8 $"
+#define DRIVER_VERSION "$Revision: 1.11 $"
 
 /* I2C bus slave registers. */
 #define RTC_I2C_READ           0xa3
@@ -49,6 +49,8 @@
 /* Two simple wrapper macros, saves a few keystrokes. */
 #define rtc_read(x) i2c_readreg(RTC_I2C_READ, x)
 #define rtc_write(x,y) i2c_writereg(RTC_I2C_WRITE, x, y)
+
+static DEFINE_SPINLOCK(rtc_lock); /* Protect state etc */
        
 static const unsigned char days_in_month[] =
        { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
@@ -125,9 +127,12 @@ get_rtc_time(struct rtc_time *tm)
 int __init
 pcf8563_init(void)
 {
-       unsigned char ret;
+       int ret;
 
-       i2c_init();
+       if ((ret = i2c_init())) {
+               printk(KERN_CRIT "pcf8563_init: failed to init i2c\n");
+               return ret;
+       }
 
        /*
         * First of all we need to reset the chip. This is done by
@@ -200,12 +205,15 @@ pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned
                        {
                                struct rtc_time tm;
 
+                               spin_lock(&rtc_lock);
                                get_rtc_time(&tm);
 
                                if (copy_to_user((struct rtc_time *) arg, &tm, sizeof(struct rtc_time))) {
+                                       spin_unlock(&rtc_lock);
                                        return -EFAULT;
                                }
 
+                               spin_unlock(&rtc_lock);
                                return 0;
                        }
                        break;
@@ -250,6 +258,8 @@ pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned
                                BIN_TO_BCD(tm.tm_min);
                                BIN_TO_BCD(tm.tm_sec);
                                tm.tm_mon |= century;
+
+                               spin_lock(&rtc_lock);
                                
                                rtc_write(RTC_YEAR, tm.tm_year);
                                rtc_write(RTC_MONTH, tm.tm_mon);
@@ -258,6 +268,8 @@ pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned
                                rtc_write(RTC_MINUTES, tm.tm_min);
                                rtc_write(RTC_SECONDS, tm.tm_sec);
 
+                               spin_unlock(&rtc_lock);
+
                                return 0;
 #endif /* !CONFIG_ETRAX_RTC_READONLY */
                        }
index 5276160..dcfec41 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.5 2004/06/02 08:24:38 starvik Exp $
+# $Id: Makefile,v 1.6 2004/12/13 12:21:51 starvik Exp $
 #
 # Makefile for the linux kernel.
 #
@@ -7,7 +7,8 @@ extra-y := head.o
 
 
 obj-y   := entry.o traps.o shadows.o debugport.o irq.o \
-          process.o setup.o signal.o traps.o time.o ptrace.o
+          process.o setup.o signal.o traps.o time.o ptrace.o \
+          dma.o io_interface_mux.o
 
 obj-$(CONFIG_ETRAX_KGDB) += kgdb.o
 obj-$(CONFIG_ETRAX_FAST_TIMER) += fasttimer.o
index 4717f7a..094ff45 100644 (file)
@@ -1,10 +1,20 @@
-/* $Id: fasttimer.c,v 1.6 2004/05/14 10:18:39 starvik Exp $
+/* $Id: fasttimer.c,v 1.9 2005/03/04 08:16:16 starvik Exp $
  * linux/arch/cris/kernel/fasttimer.c
  *
  * Fast timers for ETRAX100/ETRAX100LX
  * This may be useful in other OS than Linux so use 2 space indentation...
  *
  * $Log: fasttimer.c,v $
+ * Revision 1.9  2005/03/04 08:16:16  starvik
+ * Merge of Linux 2.6.11.
+ *
+ * Revision 1.8  2005/01/05 06:09:29  starvik
+ * cli()/sti() will be obsolete in 2.6.11.
+ *
+ * Revision 1.7  2005/01/03 13:35:46  starvik
+ * Removed obsolete stuff.
+ * Mark fast timer IRQ as not shared.
+ *
  * Revision 1.6  2004/05/14 10:18:39  starvik
  * Export fast_timer_list
  *
@@ -148,8 +158,7 @@ static int debug_log_cnt_wrapped = 0;
 #define DEBUG_LOG(string, value) \
 { \
   unsigned long log_flags; \
-  save_flags(log_flags); \
-  cli(); \
+  local_irq_save(log_flags); \
   debug_log_string[debug_log_cnt] = (string); \
   debug_log_value[debug_log_cnt] = (unsigned long)(value); \
   if (++debug_log_cnt >= DEBUG_LOG_MAX) \
@@ -157,7 +166,7 @@ static int debug_log_cnt_wrapped = 0;
     debug_log_cnt = debug_log_cnt % DEBUG_LOG_MAX; \
     debug_log_cnt_wrapped = 1; \
   } \
-  restore_flags(log_flags); \
+  local_irq_restore(log_flags); \
 }
 #else
 #define DEBUG_LOG(string, value)
@@ -320,8 +329,7 @@ void start_one_shot_timer(struct fast_timer *t,
 
   D1(printk("sft %s %d us\n", name, delay_us));
 
-  save_flags(flags);
-  cli();
+  local_irq_save(flags);
 
   do_gettimeofday_fast(&t->tv_set);
   tmp = fast_timer_list;
@@ -395,7 +403,7 @@ void start_one_shot_timer(struct fast_timer *t,
 
   D2(printk("start_one_shot_timer: %d us done\n", delay_us));
 
-  restore_flags(flags);
+  local_irq_restore(flags);
 } /* start_one_shot_timer */
 
 static inline int fast_timer_pending (const struct fast_timer * t)
@@ -425,11 +433,10 @@ int del_fast_timer(struct fast_timer * t)
   unsigned long flags;
   int ret;
   
-  save_flags(flags);
-  cli();
+  local_irq_save(flags);
   ret = detach_fast_timer(t);
   t->next = t->prev = NULL;
-  restore_flags(flags);
+  local_irq_restore(flags);
   return ret;
 } /* del_fast_timer */
 
@@ -444,8 +451,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
   struct fast_timer *t;
   unsigned long flags;
 
-  save_flags(flags);
-  cli();
+  local_irq_save(flags);
 
   /* Clear timer1 irq */
   *R_IRQ_MASK0_CLR = IO_STATE(R_IRQ_MASK0_CLR, timer1, clr);
@@ -462,7 +468,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
   fast_timer_running = 0;
   fast_timer_ints++;
 
-  restore_flags(flags);
+  local_irq_restore(flags);
 
   t = fast_timer_list;
   while (t)
@@ -482,8 +488,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
       fast_timers_expired++;
 
       /* Remove this timer before call, since it may reuse the timer */
-      save_flags(flags);
-      cli();
+      local_irq_save(flags);
       if (t->prev)
       {
         t->prev->next = t->next;
@@ -498,7 +503,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
       }
       t->prev = NULL;
       t->next = NULL;
-      restore_flags(flags);
+      local_irq_restore(flags);
 
       if (t->function != NULL)
       {
@@ -515,8 +520,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
       D1(printk(".\n"));
     }
 
-    save_flags(flags);
-    cli();
+    local_irq_save(flags);
     if ((t = fast_timer_list) != NULL)
     {
       /* Start next timer.. */
@@ -535,7 +539,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
 #endif
           start_timer1(us);
         }
-        restore_flags(flags);
+        local_irq_restore(flags);
         break;
       }
       else
@@ -546,7 +550,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
         D1(printk("e! %d\n", us));
       }
     }
-    restore_flags(flags);
+    local_irq_restore(flags);
   }
 
   if (!t)
@@ -748,13 +752,12 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
 #endif
 
     used += sprintf(bigbuf + used, "Active timers:\n");
-    save_flags(flags);
-    cli();
+    local_irq_save(flags);
     t = fast_timer_list;
     while (t != NULL && (used+100 < BIG_BUF_SIZE))
     {
       nextt = t->next;
-      restore_flags(flags);
+      local_irq_restore(flags);
       used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
                       "d: %6li us data: 0x%08lX"
 /*                      " func: 0x%08lX" */
@@ -768,14 +771,14 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
                       t->data
 /*                      , t->function */
                       );
-      cli();
+      local_irq_disable();
       if (t->next != nextt)
       {
         printk(KERN_WARNING "timer removed!\n");
       }
       t = nextt;
     }
-    restore_flags(flags);
+    local_irq_restore(flags);
   }
 
   if (used - offset < len)
@@ -963,7 +966,7 @@ void fast_timer_init(void)
    if ((fasttimer_proc_entry = create_proc_entry( "fasttimer", 0, 0 )))
      fasttimer_proc_entry->read_proc = proc_fasttimer_read;
 #endif /* PROC_FS */
-    if(request_irq(TIMER1_IRQ_NBR, timer1_handler, SA_SHIRQ,
+    if(request_irq(TIMER1_IRQ_NBR, timer1_handler, 0,
                    "fast timer int", NULL))
     {
       printk("err: timer1 irq\n");
diff --git a/include/asm-cris/arch-v10/ide.h b/include/asm-cris/arch-v10/ide.h
new file mode 100644 (file)
index 0000000..8cf2d7c
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ *  linux/include/asm-cris/ide.h
+ *
+ *  Copyright (C) 2000, 2001, 2002  Axis Communications AB
+ *
+ *  Authors:    Bjorn Wesen
+ *
+ */
+
+/*
+ *  This file contains the ETRAX 100LX specific IDE code.
+ */
+
+#ifndef __ASMCRIS_IDE_H
+#define __ASMCRIS_IDE_H
+
+#ifdef __KERNEL__
+
+#include <asm/arch/svinto.h>
+#include <asm/io.h>
+#include <asm-generic/ide_iops.h>
+
+
+/* ETRAX 100 can support 4 IDE busses on the same pins (serialized) */
+
+#define MAX_HWIFS      4
+
+extern __inline__ int ide_default_irq(unsigned long base)
+{
+       /* all IDE busses share the same IRQ, number 4.
+        * this has the side-effect that ide-probe.c will cluster our 4 interfaces
+        * together in a hwgroup, and will serialize accesses. this is good, because
+        * we can't access more than one interface at the same time on ETRAX100.
+        */
+       return 4;
+}
+
+extern __inline__ unsigned long ide_default_io_base(int index)
+{
+       /* we have no real I/O base address per interface, since all go through the
+        * same register. but in a bitfield in that register, we have the i/f number.
+        * so we can use the io_base to remember that bitfield.
+        */
+       static const unsigned long io_bases[MAX_HWIFS] = {
+               IO_FIELD(R_ATA_CTRL_DATA, sel, 0),
+               IO_FIELD(R_ATA_CTRL_DATA, sel, 1),
+               IO_FIELD(R_ATA_CTRL_DATA, sel, 2),
+               IO_FIELD(R_ATA_CTRL_DATA, sel, 3)
+       };
+       return io_bases[index];
+}
+
+/* this is called once for each interface, to setup the port addresses. data_port is the result
+ * of the ide_default_io_base call above. ctrl_port will be 0, but that is don't care for us.
+ */
+
+extern __inline__ void ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port, unsigned long ctrl_port, int *irq)
+{
+       int i;
+
+       /* fill in ports for ATA addresses 0 to 7 */
+
+       for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+               hw->io_ports[i] = data_port |
+                       IO_FIELD(R_ATA_CTRL_DATA, addr, i) |
+                       IO_STATE(R_ATA_CTRL_DATA, cs0, active);
+       }
+
+       /* the IDE control register is at ATA address 6, with CS1 active instead of CS0 */
+
+       hw->io_ports[IDE_CONTROL_OFFSET] = data_port |
+                       IO_FIELD(R_ATA_CTRL_DATA, addr, 6) |
+                       IO_STATE(R_ATA_CTRL_DATA, cs1, active);
+
+       /* whats this for ? */
+
+       hw->io_ports[IDE_IRQ_OFFSET] = 0;
+}
+
+extern __inline__ void ide_init_default_hwifs(void)
+{
+       hw_regs_t hw;
+       int index;
+
+       for(index = 0; index < MAX_HWIFS; index++) {
+               ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
+               hw.irq = ide_default_irq(ide_default_io_base(index));
+               ide_register_hw(&hw, NULL);
+       }
+}
+
+/* some configuration options we don't need */
+
+#undef SUPPORT_VLB_SYNC
+#define SUPPORT_VLB_SYNC 0
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASMCRIS_IDE_H */
diff --git a/include/asm-cris/ide.h b/include/asm-cris/ide.h
new file mode 100644 (file)
index 0000000..a894f66
--- /dev/null
@@ -0,0 +1 @@
+#include <asm/arch/ide.h>