From: Jesper Nilsson <jesper.nilsson@axis.com>
To: Andrew Morton <akpm@linux-foundation.org>,
Mikael Starvik <mikael.starvik@axis.com>,
Jesper Nilsson <jesper.nilsson@axis.com>,
linux-kernel@vger.kernel.org
Subject: [PATCH 21/47] New version of CRISv32 I2C driver.
Date: Fri, 30 Nov 2007 15:54:01 +0100 [thread overview]
Message-ID: <1756cef44b33372567336fe3f7ec3f7896e67644.1196848533.git.jesper.nilsson@axis.com> (raw)
In-Reply-To: <ca13018bb45763422de40e6109171637091a312e.1196848533.git.jesper.nilsson@axis.com>
- Add i2c_write and i2c_read as functions.
- Use spinlocks for critical regions.
- Add config item to set I2C data and clock port.
- Put unneeded testcode inside #if 0.
- Remove CVS id tag.
Signed-off-by: Jesper Nilsson <jesper.nilsson@axis.com>
---
arch/cris/arch-v32/drivers/i2c.c | 199 +++++++++++++++++++++++++++++++++++---
arch/cris/arch-v32/drivers/i2c.h | 2 +
2 files changed, 187 insertions(+), 14 deletions(-)
diff --git a/arch/cris/arch-v32/drivers/i2c.c b/arch/cris/arch-v32/drivers/i2c.c
index f1edd2e..4eda323 100644
--- a/arch/cris/arch-v32/drivers/i2c.c
+++ b/arch/cris/arch-v32/drivers/i2c.c
@@ -19,10 +19,10 @@
*!
*! ---------------------------------------------------------------------------
*!
-*! (C) Copyright 1999-2002 Axis Communications AB, LUND, SWEDEN
+*! (C) Copyright 1999-2007 Axis Communications AB, LUND, SWEDEN
*!
*!***************************************************************************/
-/* $Id: i2c.c,v 1.2 2005/05/09 15:29:49 starvik Exp $ */
+
/****************** INCLUDE FILES SECTION ***********************************/
#include <linux/module.h>
@@ -79,6 +79,8 @@ static const char i2c_name[] = "i2c";
#define i2c_delay(usecs) udelay(usecs)
+static DEFINE_SPINLOCK(i2c_lock); /* Protect directions etc */
+
/****************** VARIABLE SECTION ************************************/
static struct crisv32_iopin cris_i2c_clk;
@@ -252,6 +254,7 @@ i2c_getack(void)
* generate ACK clock pulse
*/
i2c_clk(I2C_CLOCK_HIGH);
+#if 0
/*
* Use PORT PB instead of I2C
* for input. (I2C not working)
@@ -264,6 +267,8 @@ i2c_getack(void)
i2c_data(1);
i2c_disable();
i2c_dir_in();
+#endif
+
/*
* now wait for ack
*/
@@ -271,11 +276,11 @@ i2c_getack(void)
/*
* check for ack
*/
- if(i2c_getbit())
+ if (i2c_getbit())
ack = 0;
i2c_delay(CLOCK_HIGH_TIME/2);
- if(!ack){
- if(!i2c_getbit()) /* receiver pulled SDA low */
+ if (!ack) {
+ if (!i2c_getbit()) /* receiver pulld SDA low */
ack = 1;
i2c_delay(CLOCK_HIGH_TIME/2);
}
@@ -285,6 +290,7 @@ i2c_getack(void)
* before we enable our output. If we keep data high
* and enable output, we would generate a stop condition.
*/
+#if 0
i2c_data(I2C_DATA_LOW);
/*
@@ -292,6 +298,7 @@ i2c_getack(void)
*/
i2c_enable();
i2c_dir_out();
+#endif
i2c_clk(I2C_CLOCK_LOW);
i2c_delay(CLOCK_HIGH_TIME/4);
/*
@@ -375,6 +382,137 @@ i2c_sendnack(void)
/*#---------------------------------------------------------------------------
*#
+*# FUNCTION NAME: i2c_write
+*#
+*# DESCRIPTION : Writes a value to an I2C device
+*#
+*#--------------------------------------------------------------------------*/
+int
+i2c_write(unsigned char theSlave, void *data, size_t nbytes)
+{
+ int error, cntr = 3;
+ unsigned char bytes_wrote = 0;
+ unsigned char value;
+ unsigned long flags;
+
+ spin_lock(&i2c_lock);
+
+ do {
+ error = 0;
+ /*
+ * we don't like to be interrupted
+ */
+ local_irq_save(flags);
+
+ i2c_start();
+ /*
+ * send slave address
+ */
+ i2c_outbyte((theSlave & 0xfe));
+ /*
+ * wait for ack
+ */
+ if (!i2c_getack())
+ error = 1;
+ /*
+ * send data
+ */
+ for (bytes_wrote = 0; bytes_wrote < nbytes; bytes_wrote++) {
+ memcpy(&value, data + bytes_wrote, sizeof value);
+ i2c_outbyte(value);
+ /*
+ * now it's time to wait for ack
+ */
+ if (!i2c_getack())
+ error |= 4;
+ }
+ /*
+ * end byte stream
+ */
+ i2c_stop();
+ /*
+ * enable interrupt again
+ */
+ local_irq_restore(flags);
+
+ } while (error && cntr--);
+
+ i2c_delay(CLOCK_LOW_TIME);
+
+ spin_unlock(&i2c_lock);
+
+ return -error;
+}
+
+/*#---------------------------------------------------------------------------
+*#
+*# FUNCTION NAME: i2c_read
+*#
+*# DESCRIPTION : Reads a value from an I2C device
+*#
+*#--------------------------------------------------------------------------*/
+int
+i2c_read(unsigned char theSlave, void *data, size_t nbytes)
+{
+ unsigned char b = 0;
+ unsigned char bytes_read = 0;
+ int error, cntr = 3;
+ unsigned long flags;
+
+ spin_lock(&i2c_lock);
+
+ do {
+ error = 0;
+ memset(data, 0, nbytes);
+ /*
+ * we don't like to be interrupted
+ */
+ local_irq_save(flags);
+ /*
+ * generate start condition
+ */
+ i2c_start();
+ /*
+ * send slave address
+ */
+ i2c_outbyte((theSlave | 0x01));
+ /*
+ * wait for ack
+ */
+ if (!i2c_getack())
+ error = 1;
+ /*
+ * fetch data
+ */
+ for (bytes_read = 0; bytes_read < nbytes; bytes_read++) {
+ b = i2c_inbyte();
+ memcpy(data + bytes_read, &b, sizeof b);
+
+ if (bytes_read < (nbytes - 1))
+ i2c_sendack();
+ }
+ /*
+ * last received byte needs to be nacked
+ * instead of acked
+ */
+ i2c_sendnack();
+ /*
+ * end sequence
+ */
+ i2c_stop();
+ /*
+ * enable interrupt again
+ */
+ local_irq_restore(flags);
+ } while (error && cntr--);
+
+ spin_unlock(&i2c_lock);
+
+ return -error;
+}
+
+/*#---------------------------------------------------------------------------
+*#
*# FUNCTION NAME: i2c_writereg
*#
*# DESCRIPTION : Writes a value to an I2C device
@@ -387,6 +525,8 @@ i2c_writereg(unsigned char theSlave, unsigned char theReg,
int error, cntr = 3;
unsigned long flags;
+ spin_lock(&i2c_lock);
+
do {
error = 0;
/*
@@ -431,11 +571,12 @@ i2c_writereg(unsigned char theSlave, unsigned char theReg,
* enable interrupt again
*/
local_irq_restore(flags);
-
} while(error && cntr--);
i2c_delay(CLOCK_LOW_TIME);
+ spin_unlock(&i2c_lock);
+
return -error;
}
@@ -453,6 +594,8 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg)
int error, cntr = 3;
unsigned long flags;
+ spin_lock(&i2c_lock);
+
do {
error = 0;
/*
@@ -482,7 +625,7 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg)
* now it's time to wait for ack
*/
if(!i2c_getack())
- error = 1;
+ error |= 2;
/*
* repeat start condition
*/
@@ -496,7 +639,7 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg)
* wait for ack
*/
if(!i2c_getack())
- error = 1;
+ error |= 4;
/*
* fetch register
*/
@@ -517,6 +660,8 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg)
} while(error && cntr--);
+ spin_unlock(&i2c_lock);
+
return b;
}
@@ -583,12 +728,37 @@ static const struct file_operations i2c_fops = {
int __init
i2c_init(void)
{
- int res;
+ static int res;
+ static int first = 1;
- /* Setup and enable the Port B I2C interface */
+ if (!first)
+ return res;
+
+ first = 0;
+
+ /* Setup and enable the DATA and CLK pins */
+
+ res = crisv32_io_get_name(&cris_i2c_data,
+ CONFIG_ETRAX_V32_I2C_DATA_PORT);
+ if (res < 0)
+ return res;
+
+ res = crisv32_io_get_name(&cris_i2c_clk, CONFIG_ETRAX_V32_I2C_CLK_PORT);
+ crisv32_io_set_dir(&cris_i2c_clk, crisv32_io_dir_out);
+
+ return res;
+}
- crisv32_io_get_name(&cris_i2c_data, CONFIG_ETRAX_I2C_DATA_PORT);
- crisv32_io_get_name(&cris_i2c_clk, CONFIG_ETRAX_I2C_CLK_PORT);
+
+int __init
+i2c_register(void)
+{
+
+ int res;
+
+ res = i2c_init();
+ if (res < 0)
+ return res;
/* register char device */
@@ -598,13 +768,14 @@ i2c_init(void)
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-2007 Axis Communications AB\n");
return 0;
}
/* this makes sure that i2c_init is called during boot */
-module_init(i2c_init);
+module_init(i2c_register);
/****************** END OF FILE i2c.c ********************************/
diff --git a/arch/cris/arch-v32/drivers/i2c.h b/arch/cris/arch-v32/drivers/i2c.h
index bfe1a13..c073cf4 100644
--- a/arch/cris/arch-v32/drivers/i2c.h
+++ b/arch/cris/arch-v32/drivers/i2c.h
@@ -3,6 +3,8 @@
/* High level I2C actions */
int __init i2c_init(void);
+int i2c_write(unsigned char theSlave, void *data, size_t nbytes);
+int i2c_read(unsigned char theSlave, void *data, size_t nbytes);
int i2c_writereg(unsigned char theSlave, unsigned char theReg, unsigned char theValue);
unsigned char i2c_readreg(unsigned char theSlave, unsigned char theReg);
--
1.5.3.6.970.gd25430
next prev parent reply other threads:[~2007-12-06 12:48 UTC|newest]
Thread overview: 64+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-11-29 16:02 [PATCH 00/47] CRIS patches for CRISv32 EtraxFS and ARTPEC-3 Jesper Nilsson
2007-11-29 16:02 ` [PATCH 01/47] Rearrange Kconfigs for CRIS v10 and v32 to allow compilation without warnings Jesper Nilsson
2007-11-29 16:03 ` [PATCH 02/47] Add new driver files for Artpec-3 Jesper Nilsson
2007-12-12 11:09 ` Andrew Morton
2007-11-29 16:05 ` [PATCH 03/47] Add new driver files for Etrax-FS Jesper Nilsson
2007-11-29 16:11 ` [PATCH 04/47] Add new machine dependent files for Etrax-FS and Artpec-3 Jesper Nilsson
2007-11-29 16:23 ` [PATCH 06/47] Add serial driver for CRISv32 Jesper Nilsson
2007-12-12 11:14 ` Andrew Morton
2007-11-29 16:24 ` [PATCH 07/47] Add L2 cache initialization code Jesper Nilsson
2007-11-29 16:26 ` [PATCH 08/47] Add SECOND_WORD_SYNC, used in CRISv32 version of sync_serial Jesper Nilsson
2007-11-29 16:30 ` [PATCH 09/47] Update CRISv32 synchronous serial driver Jesper Nilsson
2007-11-29 16:58 ` [PATCH 10/47] Merge axisflashmap.h with Axis internal changes Jesper Nilsson
2007-11-29 17:11 ` [PATCH 11/47] Minor fixes to CRISv32 irq defines Jesper Nilsson
2007-11-29 17:19 ` [PATCH 12/47] Remove unnecessary CVS log from cris/mm/init.c Jesper Nilsson
2007-11-30 9:11 ` [PATCH 13/47] Add prototypes for cache flushing on CRISv32 Jesper Nilsson
2007-11-30 9:12 ` [PATCH 14/47] Add headers for CRISv32 chips EtraxFS and Artpec-3 Jesper Nilsson
2007-11-30 12:59 ` [PATCH 15/47] Minor fixes to mm/fault.c for CRIS Jesper Nilsson
2007-12-12 11:17 ` Andrew Morton
2007-12-12 13:36 ` Jesper Nilsson
2007-11-30 13:11 ` [PATCH 16/47] Minor CRIS generic kernel/traps.c changes Jesper Nilsson
2007-11-30 13:14 ` [PATCH 17/47] Add handling of PTRACE_DETATCH for CRISv32. Whitespace and formatting changes to avoid checkpatch errors Jesper Nilsson
2007-11-30 14:40 ` [PATCH 18/47] Remove define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY from CRIS Jesper Nilsson
2007-11-30 14:44 ` [PATCH 19/47] Update CRISv32 entry.S to working order Jesper Nilsson
2007-11-30 14:47 ` [PATCH 20/47] Fixup CRISv32 kernel Makefile Jesper Nilsson
2007-11-30 14:54 ` Jesper Nilsson [this message]
2007-12-12 11:19 ` [PATCH 21/47] New version of CRISv32 I2C driver Andrew Morton
2007-11-30 15:01 ` [PATCH 22/47] Update and improve axisflashmap for CRISv32 Jesper Nilsson
2007-11-30 15:07 ` [PATCH 23/47] Update CRIS main Kbuild makefile Jesper Nilsson
2007-11-30 15:08 ` [PATCH 24/47] Update CRISv10 boot " Jesper Nilsson
2007-11-30 15:10 ` [PATCH 25/47] Update CRISv10 boot compressed " Jesper Nilsson
2007-11-30 15:11 ` [PATCH 26/47] Update CRISv10 rescue " Jesper Nilsson
2007-11-30 15:13 ` [PATCH 27/47] Update CRISv10 rescue head.s Jesper Nilsson
2007-12-06 13:58 ` David Miller
2007-12-07 0:46 ` Jesper Nilsson
2007-11-30 15:17 ` [PATCH 28/47] Update and improve CRISv10 axisflashmap.c Jesper Nilsson
2007-11-30 15:22 ` [PATCH 29/47] Update CRISv32 traps.c Jesper Nilsson
2007-12-12 11:21 ` Andrew Morton
2007-11-30 15:24 ` [PATCH 30/47] Update CRISv32 boot Kbuild makefile Jesper Nilsson
2007-11-30 15:25 ` [PATCH 31/47] Update CRISv32 boot compressed " Jesper Nilsson
2007-11-30 15:28 ` [PATCH 32/47] Update CRISv32 boot rescue " Jesper Nilsson
2007-11-30 15:30 ` [PATCH 33/47] Remove CRISv32 common gpio and nandflash, add mach-fs and mach-a3 as subdirs Jesper Nilsson
2007-11-30 15:40 ` [PATCH 34/47] Update CRISv32 compressed head.S Jesper Nilsson
2007-11-30 16:16 ` [PATCH 35/47] Update CRISv32 boot/compressed/misc.c Jesper Nilsson
2007-11-30 16:20 ` [PATCH 36/47] Update CRISv32 boot/rescue/head.S code Jesper Nilsson
2007-11-30 16:26 ` [PATCH 37/47] Update CRISv32 debugport Jesper Nilsson
2007-11-30 16:28 ` [PATCH 38/47] Include path fix for CRISv32 timex.h Jesper Nilsson
2007-11-30 16:46 ` [PATCH 39/47] Update and improve CRISv32 fasttimer.c Jesper Nilsson
2007-12-12 11:23 ` Andrew Morton
2007-11-30 16:54 ` [PATCH 40/47] Update CRISv32 kernel/head.S Jesper Nilsson
2007-11-30 17:09 ` [PATCH 41/47] Update and simplify CRISv32 kernel/irq.c Jesper Nilsson
2007-12-03 9:54 ` [PATCH 42/47] Minor updates to CRISv32 kernel/process.c Jesper Nilsson
2007-12-12 11:24 ` Andrew Morton
2007-12-03 10:12 ` [PATCH 43/47] Update and improve CRISv32 kernel/traps.c Jesper Nilsson
2007-12-03 10:16 ` [PATCH 44/47] Minor fixes for CRISv32 io.h Jesper Nilsson
2007-12-12 11:29 ` Andrew Morton
2007-12-12 17:04 ` Jesper Nilsson
2007-12-03 10:37 ` [PATCH 45/47] New default config for CRISv10 Jesper Nilsson
2007-12-04 16:25 ` [PATCH 46/47] Update and improve CRISv32 kernel/time.c Jesper Nilsson
2007-12-12 11:33 ` Andrew Morton
2007-12-04 16:40 ` [PATCH 47/47] Add new defconfigs for Artpec-3 and EtraxFS, both CRISv32 Jesper Nilsson
2007-12-12 10:52 ` [PATCH 00/47] CRIS patches for CRISv32 EtraxFS and ARTPEC-3 Andrew Morton
2007-12-12 13:28 ` Jesper Nilsson
2007-12-12 13:28 ` Adrian Bunk
2007-12-12 13:46 ` Jesper Nilsson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1756cef44b33372567336fe3f7ec3f7896e67644.1196848533.git.jesper.nilsson@axis.com \
--to=jesper.nilsson@axis.com \
--cc=akpm@linux-foundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mikael.starvik@axis.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).