diff options
author | Mikael Starvik <mikael.starvik@axis.com> | 2005-07-27 11:44:34 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-07-27 16:25:59 -0700 |
commit | 7e9204265b4ec6680fad9abc7a78b94087983916 (patch) | |
tree | 50ff709f7d37193bb56599a4e1646509d8e353ff /arch/cris/arch-v10/drivers/i2c.c | |
parent | 059163cabc01a15b9e2cf10e5de5b6dc06e0da1f (diff) |
[PATCH] CRIS update: drivers
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>
Diffstat (limited to 'arch/cris/arch-v10/drivers/i2c.c')
-rw-r--r-- | arch/cris/arch-v10/drivers/i2c.c | 62 |
1 files changed, 55 insertions, 7 deletions
diff --git a/arch/cris/arch-v10/drivers/i2c.c b/arch/cris/arch-v10/drivers/i2c.c index 8bbe233ba7b..b38267d60d3 100644 --- a/arch/cris/arch-v10/drivers/i2c.c +++ b/arch/cris/arch-v10/drivers/i2c.c @@ -12,6 +12,15 @@ *! 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 ***********************************/ @@ -95,6 +104,7 @@ #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; } |