linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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


  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).