* [PATCH] EMMA2RH I2C driver
[not found] <20070308145948.GA4235@linux-mips.org>
@ 2007-03-13 17:59 ` dmitry pervushin
2007-03-14 17:52 ` Ralf Baechle
0 siblings, 1 reply; 4+ messages in thread
From: dmitry pervushin @ 2007-03-13 17:59 UTC (permalink / raw)
To: Ralf Baechle; +Cc: linux-mips
Below is patch to support I2C controller on NEC EMMA2RH board
Signed-off: dmitry pervushin <dpervushin@ru.mvista.com>
drivers/i2c/algos/Kconfig | 5
drivers/i2c/algos/Makefile | 1
drivers/i2c/algos/i2c-algo-emma2rh.c | 426 +++++++++++++++++++++++++++++++++++
drivers/i2c/algos/i2c-algo-emma2rh.h | 105 ++++++++
drivers/i2c/busses/Kconfig | 7
drivers/i2c/busses/Makefile | 1
drivers/i2c/busses/i2c-emma2rh.c | 253 ++++++++++++++++++++
7 files changed, 798 insertions(+)
Index: linux-2.6.20/drivers/i2c/algos/Kconfig
===================================================================
--- linux-2.6.20.orig/drivers/i2c/algos/Kconfig
+++ linux-2.6.20/drivers/i2c/algos/Kconfig
@@ -49,5 +49,10 @@ config I2C_ALGO_SGI
Supports the SGI interfaces like the ones found on SGI Indy VINO
or SGI O2 MACE.
+config I2C_ALGO_EMMA2RH
+ tristate "I2C EMMA2RH interfaces"
+ depends on I2C && MARKEINS
+ help
+ NEC EMMA2RH I2C Algorithm
endmenu
Index: linux-2.6.20/drivers/i2c/algos/Makefile
===================================================================
--- linux-2.6.20.orig/drivers/i2c/algos/Makefile
+++ linux-2.6.20/drivers/i2c/algos/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_I2C_ALGOBIT) += i2c-algo-bi
obj-$(CONFIG_I2C_ALGOPCF) += i2c-algo-pcf.o
obj-$(CONFIG_I2C_ALGOPCA) += i2c-algo-pca.o
obj-$(CONFIG_I2C_ALGO_SGI) += i2c-algo-sgi.o
+obj-$(CONFIG_I2C_ALGO_EMMA2RH) += i2c-algo-emma2rh.o
ifeq ($(CONFIG_I2C_DEBUG_ALGO),y)
EXTRA_CFLAGS += -DDEBUG
Index: linux-2.6.20/drivers/i2c/algos/i2c-algo-emma2rh.c
===================================================================
--- /dev/null
+++ linux-2.6.20/drivers/i2c/algos/i2c-algo-emma2rh.c
@@ -0,0 +1,426 @@
+/*
+ -------------------------------------------------------------------------
+ i2c-algo-emma2rh.c i2c driver algorithms for NEC EMMA2RH I2C adapters
+ -------------------------------------------------------------------------
+
+ Copyright (C) NEC Electronics Corporation 2005-2006
+
+ Changes made to support the I2C peripheral on the NEC EMMA2RH
+
+ -------------------------------------------------------------------------
+ This file was highly leveraged from i2c-algo-pcf.c, which was created
+ by Simon G. Vogl and Hans Berglund:
+
+ Copyright (C) 1995-1997 Simon G. Vogl
+ 1998-2000 Hans Berglund
+
+ With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
+ Frodo Looijaard <frodol@dds.nl> ,and also from Martin Bailey
+ <mbailey@littlefeet-inc.com>
+
+ Partially rewriten by Oleg I. Vdovikin <vdovikin@jscc.ru> to handle multiple
+ messages, proper stop/repstart signaling during receive,
+ added detect code
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ -------------------------------------------------------------------------
+*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c-algo-emma2rh.h>
+
+#include <asm/emma2rh/emma2rh.h>
+
+#ifdef DEBUG
+#define i2c_emma2rh_debug(level,op) do { if (i2c_debug>=(level)) { op; } } while (0)
+static int i2c_debug;
+module_param(i2c_debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(i2c_debug,
+ "debug level - 0 off; 1 normal; 2,3 more verbose; 9 i2c-protocol");
+#else
+#define i2c_emma2rh_debug(level,op) /* nothing */
+#endif
+
+#define DEB(x) i2c_emma2rh_debug(1, x)
+#define DEB2(x) i2c_emma2rh_debug(2, x)
+#define DEB3(x) i2c_emma2rh_debug(3, x)
+#define DEBPROTO(x) i2c_emma2rh_debug(9,x)
+
+#define EMMA2RH_I2C_RETRIES 3
+#define EMMA2RH_I2C_TIMEOUT 100
+
+/* --- setting states on the bus with the right timing: --------------- */
+#define set_emma(adap, ctl, val) adap->setemma(adap->data, ctl, val)
+#define get_emma(adap, ctl) adap->getemma(adap->data, ctl)
+#define get_own(adap) adap->getown(adap->data)
+#define get_clock(adap) adap->getclock(adap->data)
+
+/* --- other auxiliary functions -------------------------------------- */
+
+static void i2c_start(struct i2c_algo_emma_data *adap)
+{
+ DEBPROTO(printk("S "));
+ set_emma(adap, I2C_EMMA_CNT, I2C_EMMA_START);
+}
+
+static void i2c_repstart(struct i2c_algo_emma_data *adap)
+{
+ DEBPROTO(printk(" Sr "));
+ set_emma(adap, I2C_EMMA_CNT, I2C_EMMA_REPSTART);
+}
+
+static void i2c_stop(struct i2c_algo_emma_data *adap)
+{
+ DEBPROTO(printk("P\n"));
+ set_emma(adap, I2C_EMMA_CNT, I2C_EMMA_STOP);
+}
+
+static inline void emma_sleep(unsigned long timeout)
+{
+ schedule_timeout(timeout * HZ);
+}
+
+static int wait_for_pin(struct i2c_algo_emma_data *adap, int *status)
+{
+ adap->waitforpin(adap->data);
+ *status = get_emma(adap, I2C_EMMA_STA);
+ return 0;
+}
+
+static int emma_init(struct i2c_algo_emma_data *adap)
+{
+ unsigned char temp;
+
+ /* serial interface off */
+ set_emma(adap, I2C_EMMA_CNT, 0);
+
+ /* load clock register CS */
+ set_emma(adap, I2C_EMMA_CSEL, get_clock(adap));
+ udelay(20); /* wait awhile */
+ /* check it's realy written, the only 4 lowest bits does matter */
+ if (((temp = get_emma(adap, I2C_EMMA_CSEL)) & 0x8f) != get_clock(adap)) {
+ DEB2(printk
+ (KERN_ERR
+ "%s: EMMA detection failed -- can't set I2C_EMMA_CSEL (0x%02x).\n",
+ __FUNCTION__, temp));
+ return -ENXIO;
+ }
+
+ /* initialize interrupt mask */
+ set_emma(adap, I2C_EMMA_INT, 0);
+ set_emma(adap, I2C_EMMA_INTM, INTE0);
+
+ /* Enable serial interface */
+ set_emma(adap, I2C_EMMA_CNT, IICE);
+
+ /* generate a STOP condition, first of all */
+ i2c_stop(adap);
+
+ return 0;
+}
+
+static int emma_exit(struct i2c_algo_emma_data *adap)
+{
+ set_emma(adap, I2C_EMMA_INTM, 0);
+}
+
+/* --- Utility functions ---------------------------------------------- */
+
+static inline int try_address(struct i2c_algo_emma_data *adap,
+ unsigned char addr, int retries)
+{
+ int i, status, ret = -1;
+
+ for (i = 0; i < retries; i++) {
+ i2c_start(adap);
+ set_emma(adap, I2C_EMMA_SHR, addr);
+ if (wait_for_pin(adap, &status) >= 0)
+ if (status & ACKD) {
+ i2c_stop(adap);
+ ret = 1;
+ break; /* success! */
+ }
+ i2c_stop(adap);
+ udelay(adap->udelay);
+ }
+ DEB2(if (i)
+ printk(KERN_DEBUG "%s: needed %d retries for %d\n", __FUNCTION__, i, addr)) ;
+ return ret;
+}
+
+static int emma_sendbytes(struct i2c_adapter *i2c_adap, const char *buf,
+ int count, int last)
+{
+ struct i2c_algo_emma_data *adap = i2c_adap->algo_data;
+ int wrcount, status, timeout;
+
+ set_emma(adap, I2C_EMMA_CNT, IICE | WTIM);
+ for (wrcount = 0; wrcount < count; wrcount++) {
+ set_emma(adap, I2C_EMMA_INT, 0);
+ set_emma(adap, I2C_EMMA_SHR, buf[wrcount] & SR);
+ timeout = wait_for_pin(adap, &status);
+ if (timeout) {
+ i2c_stop(adap);
+ printk(KERN_ERR "%s i2c_write: "
+ "error - timeout.\n", i2c_adap->name);
+ return -EREMOTEIO; /* got a better one ?? */
+ }
+ if (!(status & ACKD)) {
+ i2c_stop(adap);
+ printk(KERN_ERR "%s i2c_write: "
+ "error - no ack.\n", i2c_adap->name);
+ return -EREMOTEIO; /* got a better one ?? */
+ }
+ }
+
+ if (last)
+ i2c_stop(adap);
+ else
+ i2c_repstart(adap);
+
+ return (wrcount);
+}
+
+static int emma_readbytes(struct i2c_adapter *i2c_adap, char *buf,
+ int count, int last)
+{
+ struct i2c_algo_emma_data *adap = i2c_adap->algo_data;
+ int rdcount, status, timeout;
+
+ for (rdcount = 0; rdcount < count; rdcount++) {
+
+ /* we will suffer from unexpected interrupts if we
+ * use 8-clock-wait.
+ */
+
+ set_emma(adap, I2C_EMMA_INT, 0);
+ if (rdcount == count - 1)
+ /* last byte */
+ set_emma(adap, I2C_EMMA_CNT, IICE | WREL | WTIM);
+ else
+ set_emma(adap, I2C_EMMA_CNT, IICE | WREL | WTIM | ACKE);
+
+ timeout = wait_for_pin(adap, &status);
+ if (timeout) {
+ i2c_stop(adap);
+ printk(KERN_ERR
+ "i2c-algo-emma.o: emma_readbytes timed out.\n");
+ return (-1);
+ }
+ if (!(status & ACKD) && (rdcount != count - 1)) {
+ i2c_stop(adap);
+ printk(KERN_ERR
+ "i2c-algo-emma.o: i2c_read: i2c_inb, No ack.\n");
+ return (-1);
+ }
+ buf[rdcount] = get_emma(adap, I2C_EMMA_SHR);
+ }
+
+ if (last)
+ i2c_stop(adap);
+ else
+ i2c_repstart(adap);
+
+ return (rdcount);
+}
+
+static inline int emma_doAddress(struct i2c_algo_emma_data *adap,
+ struct i2c_msg *msg, int retries)
+{
+ unsigned short flags = msg->flags;
+ unsigned int addr;
+ int ret;
+
+ set_emma(adap, I2C_EMMA_INT, 0);
+
+ if (flags & I2C_M_TEN) {
+ /* a ten bit address */
+ addr = 0xf0 | ((msg->addr >> 7) & 0x03);
+ DEB2(printk(KERN_DEBUG "addr0: %d\n", addr));
+
+ /* try extended address code... */
+ ret = try_address(adap, addr, retries);
+ if (ret != 1) {
+ printk(KERN_ERR "died at extended address code.\n");
+ return -EREMOTEIO;
+ }
+ /* the remaining 8 bit address */
+ /* ...TBD */
+ printk(KERN_ERR"10 bit addresses are not supported in this driver.\n");
+ return -EREMOTEIO;
+ } else { /* normal 7bit address */
+ addr = (msg->addr << 1);
+ if (flags & I2C_M_RD)
+ addr |= 1;
+ if (flags & I2C_M_REV_DIR_ADDR)
+ addr ^= 1;
+ set_emma(adap, I2C_EMMA_SHR, addr);
+ }
+ return 0;
+}
+
+static int emma_xfer(struct i2c_adapter *i2c_adap,
+ struct i2c_msg msgs[], int num)
+{
+ struct i2c_algo_emma_data *adap = i2c_adap->algo_data;
+ struct i2c_msg *pmsg;
+ int i;
+ int ret = 0, timeout, status;
+
+ for (i = 0; ret >= 0 && i < num; i++) {
+ pmsg = &msgs[i];
+
+ DEB2(printk
+ (KERN_DEBUG
+ "Doing %s %d bytes to 0x%02x - %d of %d messages\n",
+ pmsg->flags & I2C_M_RD ? "read" : "write", pmsg->len,
+ pmsg->addr, i + 1, num));
+
+ /* Send START */
+ if (i == 0)
+ i2c_start(adap);
+
+ ret = emma_doAddress(adap, pmsg, i2c_adap->retries);
+
+ /* Wait for PIN (pending interrupt NOT) */
+ timeout = wait_for_pin(adap, &status);
+ if (timeout) {
+ i2c_stop(adap);
+ DEB2(printk(KERN_ERR "Timeout waiting "
+ "for PIN(1) in emma_xfer\n"));
+ return (-EREMOTEIO);
+ }
+
+ /* Check LRB (last rcvd bit - slave ack) */
+ if (!(status & ACKD)) {
+ i2c_stop(adap);
+ DEB2(printk
+ (KERN_ERR
+ "No LRB(1) in emma_xfer\n"));
+ return (-EREMOTEIO);
+ }
+
+ DEB3(printk
+ (KERN_DEBUG
+ "i2c-algo-emma.o: Msg %d, addr=0x%x, flags=0x%x, len=%d\n",
+ i, msgs[i].addr, msgs[i].flags, msgs[i].len));
+
+ if (pmsg->flags & I2C_M_RD)
+ /* read bytes into buffer */
+ ret = emma_readbytes(i2c_adap, pmsg->buf, pmsg->len,
+ (i + 1 == num));
+ else /* Write */
+ ret = emma_sendbytes(i2c_adap, pmsg->buf, pmsg->len,
+ (i + 1 == num));
+
+ DEB2( printk( KERN_DEBUG "transferred %d bytes of %d -- %s\n",
+ ret, pmsg->len, ret != pmsg->len ? "FAIL" : "succeeded"));
+ }
+
+ return (i);
+}
+
+static int algo_control(struct i2c_adapter *adapter,
+ unsigned int cmd, unsigned long arg)
+{
+ return 0;
+}
+
+static u32 emma_func(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING;
+}
+
+/* --- exported algorithm data ---------------------------------------- */
+
+static struct i2c_algorithm emma_algo = {
+ .master_xfer = emma_xfer,
+ .smbus_xfer = NULL,
+ .algo_control = algo_control, /* ioctl */
+ .functionality = emma_func, /* functionality */
+};
+
+/*
+ * registering functions to load algorithms at routine
+ */
+int i2c_emma_add_bus(struct i2c_adapter *adap)
+{
+ int i;
+ struct i2c_algo_emma_data *emma_adap = adap->algo_data;
+
+ DEB2(printk
+ (KERN_DEBUG "hw routines for %s registered.\n",
+ adap->name));
+
+ /* register new adapter to i2c module... */
+ adap->algo = &emma_algo;
+
+ adap->timeout = EMMA2RH_I2C_TIMEOUT; /* default values, should */
+ adap->retries = EMMA2RH_I2C_RETRIES; /* be replaced by defines */
+
+ if ((i = emma_init(emma_adap)))
+ return i;
+
+ i2c_add_adapter(adap);
+
+ return 0;
+}
+
+int i2c_emma_del_bus(struct i2c_adapter *adap)
+{
+ int res;
+ struct i2c_algo_emma_data *emma_adap = adap->algo_data;
+
+ emma_exit(emma_adap);
+
+ if ((res = i2c_del_adapter(adap)) < 0)
+ return res;
+ DEB2(printk(KERN_DEBUG "adapter unregistered: %s\n",
+ adap->name));
+
+ return 0;
+}
+
+int __init i2c_algo_emma_init(void)
+{
+ return 0;
+}
+
+void i2c_algo_emma_exit(void)
+{
+ return;
+}
+
+EXPORT_SYMBOL_GPL(i2c_emma_add_bus);
+EXPORT_SYMBOL_GPL(i2c_emma_del_bus);
+
+MODULE_AUTHOR("NEC Electronics Corporation <www.necel.com>");
+MODULE_DESCRIPTION("NEC EMMA2RH I2C-Bus algorithm");
+MODULE_LICENSE("GPL");
+
+module_init(i2c_algo_emma_init);
+module_exit(i2c_algo_emma_exit);
Index: linux-2.6.20/drivers/i2c/algos/i2c-algo-emma2rh.h
===================================================================
--- /dev/null
+++ linux-2.6.20/drivers/i2c/algos/i2c-algo-emma2rh.h
@@ -0,0 +1,105 @@
+/* -------------------------------------------------------------------- */
+/* i2c-algo-emma2rh.h: NEC EMMA2RH global defines */
+/* -------------------------------------------------------------------- */
+/*
+ Copyright (C) NEC Electronics Corporation 2005-2006
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/
+/* -------------------------------------------------------------------- */
+
+#ifndef I2C_EMMA2RH_H
+#define I2C_EMMA2RH_H
+
+/*---------------------------------------------------------------------------*/
+/* CNT - Control register (00H R/W) */
+/*---------------------------------------------------------------------------*/
+#define SPT 0x00000001
+#define STT 0x00000002
+#define ACKE 0x00000004
+#define WTIM 0x00000008
+#define SPIE 0x00000010
+#define WREL 0x00000020
+#define LREL 0x00000040
+#define IICE 0x00000080
+#define CNT_RESERVED 0x000000ff /* reserved bit 0 */
+
+#define I2C_EMMA_START (IICE | STT)
+#define I2C_EMMA_STOP (IICE | SPT)
+#define I2C_EMMA_REPSTART I2C_EMMA_START
+
+/*---------------------------------------------------------------------------*/
+/* STA - Status register (10H Read) */
+/*---------------------------------------------------------------------------*/
+#define MSTS 0x00000080
+#define ALD 0x00000040
+#define EXC 0x00000020
+#define COI 0x00000010
+#define TRC 0x00000008
+#define ACKD 0x00000004
+#define STD 0x00000002
+#define SPD 0x00000001
+
+/*---------------------------------------------------------------------------*/
+/* CSEL - Clock select register (20H R/W) */
+/*---------------------------------------------------------------------------*/
+#define FCL 0x00000080
+#define ND50 0x00000040
+#define CLD 0x00000020
+#define DAD 0x00000010
+#define SMC 0x00000008
+#define DFC 0x00000004
+#define CL 0x00000003
+#define CSEL_RESERVED 0x000000ff /* reserved bit 0 */
+
+#define FAST397 0x0000008b
+#define FAST297 0x0000008a
+#define FAST347 0x0000000b
+#define FAST260 0x0000000a
+#define FAST130 0x00000008
+#define STANDARD108 0x00000083
+#define STANDARD83 0x00000082
+#define STANDARD95 0x00000003
+#define STANDARD73 0x00000002
+#define STANDARD36 0x00000001
+#define STANDARD71 0x00000000
+
+/*---------------------------------------------------------------------------*/
+/* SVA - Slave address register (30H R/W) */
+/*---------------------------------------------------------------------------*/
+#define SVA 0x000000fe
+
+/*---------------------------------------------------------------------------*/
+/* SHR - Shift register (40H R/W) */
+/*---------------------------------------------------------------------------*/
+#define SR 0x000000ff
+
+/*---------------------------------------------------------------------------*/
+/* INT - Interrupt register (50H R/W) */
+/* INTM - Interrupt mask register (60H R/W) */
+/*---------------------------------------------------------------------------*/
+#define INTE0 0x00000001
+
+/***********************************************************************
+ * I2C registers
+ ***********************************************************************
+ */
+#define I2C_EMMA_CNT 0x00
+#define I2C_EMMA_STA 0x10
+#define I2C_EMMA_CSEL 0x20
+#define I2C_EMMA_SVA 0x30
+#define I2C_EMMA_SHR 0x40
+#define I2C_EMMA_INT 0x50
+#define I2C_EMMA_INTM 0x60
+#endif /* I2C_EMMA2RH_H */
Index: linux-2.6.20/drivers/i2c/busses/Kconfig
===================================================================
--- linux-2.6.20.orig/drivers/i2c/busses/Kconfig
+++ linux-2.6.20/drivers/i2c/busses/Kconfig
@@ -573,4 +573,11 @@ config I2C_PNX
This driver can also be built as a module. If so, the module
will be called i2c-pnx.
+config I2C_EMMA2RH
+ tristate "EMMA2RH I2C adapter"
+ depends on I2C && MARKEINS
+ select I2C_ALGO_EMMA2RH
+ help
+ Support for NEC EMMA2RH I2C Adapter
+
endmenu
Index: linux-2.6.20/drivers/i2c/busses/Makefile
===================================================================
--- linux-2.6.20.orig/drivers/i2c/busses/Makefile
+++ linux-2.6.20/drivers/i2c/busses/Makefile
@@ -47,6 +47,7 @@ obj-$(CONFIG_I2C_VIAPRO) += i2c-viapro.o
obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o
obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o
+obj-$(CONFIG_I2C_EMMA2RH) += i2c-emma2rh.o
ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
EXTRA_CFLAGS += -DDEBUG
Index: linux-2.6.20/drivers/i2c/busses/i2c-emma2rh.c
===================================================================
--- /dev/null
+++ linux-2.6.20/drivers/i2c/busses/i2c-emma2rh.c
@@ -0,0 +1,253 @@
+/*
+ -------------------------------------------------------------------------
+ i2c-emma2rh.c i2c-hw access for the I2C peripheral on the NEC EMMA2RH
+ -------------------------------------------------------------------------
+
+ Copyright (C) NEC Electronics Corporation 2005-2006
+
+ Changes made to support the I2C peripheral on the NEC EMMA2RH
+
+ -------------------------------------------------------------------------
+ This file was highly leveraged from i2c-elektor.c, which was created
+ by Simon G. Vogl and Hans Berglund:
+
+ Copyright (C) 1995-97 Simon G. Vogl
+ 1998-99 Hans Berglund
+
+ With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
+ Frodo Looijaard <frodol@dds.nl>
+
+ Partialy rewriten by Oleg I. Vdovikin for mmapped support of
+ for Alpha Processor Inc. UP-2000(+) boards
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ -------------------------------------------------------------------------
+*/
+
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/i2c-algo-emma2rh.h>
+#include <linux/platform_device.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+#include <asm/emma2rh/emma2rh.h>
+
+#define I2C_EMMA2RH "emma2rh-iic"
+static int i2c_debug = 0;
+
+/* ----- global defines ----------------------------------------------- */
+#define DEB(x) if (i2c_debug>=1) x
+#define DEB2(x) if (i2c_debug>=2) x
+#define DEB3(x) if (i2c_debug>=3) x
+#define DEBE(x) x /* error messages */
+
+struct i2c_drvdata {
+ struct i2c_algo_emma_data alg;
+ struct i2c_adapter adap;
+ spinlock_t lock;
+ atomic_t pending;
+ u32 base;
+ int irq;
+ int clock;
+ int own;
+ wait_queue_head_t wait;
+};
+
+/* ----- local functions ---------------------------------------------- */
+static void i2c_emma_setbyte(void *data, int ctl, int val)
+{
+ int address = ((struct i2c_drvdata *)data)->base + ctl;
+
+ DEB3(printk
+ (KERN_DEBUG "i2c_emma_setbyte: Write 0x%08x 0x%08x\n", address,
+ val));
+ __raw_writel(val, (void *)address);
+}
+
+static int i2c_emma_getbyte(void *data, int ctl)
+{
+ int address = ((struct i2c_drvdata *)data)->base + ctl;
+ int val = __raw_readl((void *)address);
+
+ DEB3(printk
+ (KERN_DEBUG "i2c_emma_getbyte: Read 0x%08x 0x%08x\n", address,
+ val));
+ return (val);
+}
+
+static int i2c_emma_getown(void *data)
+{
+ return (((struct i2c_drvdata *)data)->own);
+}
+
+static int i2c_emma_getclock(void *data)
+{
+ return (((struct i2c_drvdata *)data)->clock);
+}
+
+
+
+static int i2c_emma_reg(struct i2c_client *client)
+{
+ return 0;
+}
+
+static int i2c_emma_unreg(struct i2c_client *client)
+{
+ return 0;
+}
+
+
+static irqreturn_t i2c_emma_handler(int this_irq, void *dev_id)
+{
+ struct i2c_drvdata *dd = dev_id;
+
+ DEB2(printk("i2c_emma_handler: status = 0x%08x\n",
+ __raw_readl((void *)(dd->base + I2C_EMMA_INT))));
+ /* clear interrupt */
+ __raw_writel(0, (void *)(dd->base + I2C_EMMA_INT));
+
+ atomic_set(&dd->pending, 1);
+ wake_up(&dd->wait);
+ return IRQ_HANDLED;
+}
+
+static void i2c_emma_waitforpin(void *data)
+{
+ int timeout = 2;
+ struct i2c_drvdata *dd = data;
+
+ if (dd->irq >=0) {
+ timeout = wait_event_timeout(dd->wait,
+ atomic_read(&dd->pending),
+ timeout * HZ);
+ atomic_set(&dd->pending,0);
+ } else
+ udelay(100);
+}
+
+static int __devinit i2c_emma_probe(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct i2c_drvdata *dd;
+ int err = 0;
+ struct resource *r;
+
+ dd = kzalloc (sizeof *dd, GFP_KERNEL);
+ if (dd == NULL) {
+ err = -ENOMEM;
+ goto out;
+ }
+ dd->alg.data = dd;
+ dd->alg.setemma = i2c_emma_setbyte;
+ dd->alg.getemma = i2c_emma_getbyte;
+ dd->alg.getown = i2c_emma_getown;
+ dd->alg.getclock = i2c_emma_getclock;
+ dd->alg.waitforpin = i2c_emma_waitforpin;
+ dd->alg.udelay = 80;
+ dd->alg.mdelay = 80;
+ dd->alg.timeout = 200;
+
+ strcpy(dd->adap.name, dev->bus_id);
+ dd->adap.id = 0x00;
+ dd->adap.algo = NULL;
+ dd->adap.algo_data = &dd->alg;
+ dd->adap.client_register = i2c_emma_reg;
+ dd->adap.client_unregister = i2c_emma_unreg;
+
+ spin_lock_init(&dd->lock);
+
+ atomic_set(&dd->pending,0);
+ init_waitqueue_head(&dd->wait);
+
+ dev_set_drvdata(dev, dd);
+
+ r = platform_get_resource(pdev, 0, 0);
+ /* get resource of type '0' with #0 */
+
+ if (!r) {
+ printk("Cannot get resource\n");
+ err = -ENODEV;
+ goto out_free;
+ }
+ dd->base = r->start;
+
+ dd->irq = platform_get_irq(pdev,0);
+ dd->clock = FAST397;
+ dd->own = 0x40 + pdev->id * 4;
+
+ err = request_irq(dd->irq, i2c_emma_handler, 0, dev->bus_id, dd);
+ if (err < 0)
+ goto out_free;
+
+ if ((err = i2c_emma_add_bus(&dd->adap)) < 0)
+ goto out_irq;
+
+ return 0;
+out_irq:
+ free_irq(dd->irq, dev->bus_id);
+out_free:
+ kfree(dd);
+out:
+ return err;
+}
+
+static int __devexit i2c_emma_remove (struct device *dev)
+{
+ struct i2c_drvdata* dd = dev_get_drvdata(dev);
+
+ if (dd) {
+ disable_irq(dd->irq);
+ free_irq(dd->irq, dev->bus_id);
+ i2c_emma_del_bus(&dd->adap);
+ kfree(dd);
+ }
+ return 0;
+}
+
+static struct device_driver i2c_emma_driver = {
+ .bus = &platform_bus_type,
+ .name = I2C_EMMA2RH,
+ .probe = i2c_emma_probe,
+ .remove = i2c_emma_remove,
+};
+
+static int __init i2c_emma_init(void)
+{
+ return driver_register(&i2c_emma_driver);
+}
+
+static void __exit i2c_emma_exit(void)
+{
+ driver_unregister(&i2c_emma_driver);
+}
+
+MODULE_AUTHOR("NEC Electronics Corporation <www.necel.com>");
+MODULE_DESCRIPTION("I2C-Bus adapter routines for EMMA2RH I2C bus adapter");
+MODULE_LICENSE("GPL");
+
+module_param(i2c_debug, int, S_IRUGO | S_IWUSR);
+module_init(i2c_emma_init);
+module_exit(i2c_emma_exit);
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] EMMA2RH I2C driver
2007-03-13 17:59 ` dmitry pervushin
@ 2007-03-14 17:52 ` Ralf Baechle
0 siblings, 0 replies; 4+ messages in thread
From: Ralf Baechle @ 2007-03-14 17:52 UTC (permalink / raw)
To: dmitry pervushin; +Cc: linux-mips
On Tue, Mar 13, 2007 at 08:59:51PM +0300, dmitry pervushin wrote:
> Below is patch to support I2C controller on NEC EMMA2RH board
I've dropped this one into the queue tree. Markus Gothe has already
reported a bunch of issues so I'll leave polishing to him.
Ralf
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] EMMA2RH I2C driver
@ 2007-04-12 8:43 Markus Gothe
2007-04-12 14:49 ` Sergei Shtylyov
0 siblings, 1 reply; 4+ messages in thread
From: Markus Gothe @ 2007-04-12 8:43 UTC (permalink / raw)
To: linux-mips
[-- Attachment #1: Type: text/plain, Size: 850 bytes --]
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
As Ralf pointed out in march I've been polishing the IIC-driver for
EMMA2RH.
I've shaped up the I2C-driver to be a platform-device-driver and added
accurately memory-mapping/unmapping and irq-request/free.
There was a datastructure missing which was pretty straight forward to
figure out how to rebuild (i.e. i2c_algo_emma_data).
The patch (for the patch) is attached.
//Markus
- --
_______________________________________
Mr Markus Gothe
Software Engineer
Phone: +46 (0)13 21 81 20 (ext. 1046)
Fax: +46 (0)13 21 21 15
Mobile: +46 (0)73 718 72 80
Diskettgatan 11, SE-583 35 Linköping, Sweden
www.27m.com
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
iD8DBQFGHfEc6I0XmJx2NrwRCMZ8AJ0QgruqOX2y+MxF/+RbpTbSciUsGwCfcH7M
efI4rmnlkfxNezQbOWENjRY=
=rJPp
-----END PGP SIGNATURE-----
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: i2c-emma2rh.patch --]
[-- Type: text/x-patch; name="i2c-emma2rh.patch", Size: 9115 bytes --]
--- drivers/i2c/algos/i2c-algo-emma2rh.c.orig 2007-03-15 13:32:35.000000000 +0100
+++ drivers/i2c/algos/i2c-algo-emma2rh.c 2007-04-12 10:08:58.000000000 +0200
@@ -14,7 +14,7 @@
Copyright (C) 1995-1997 Simon G. Vogl
1998-2000 Hans Berglund
- With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
+ With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
Frodo Looijaard <frodol@dds.nl> ,and also from Martin Bailey
<mbailey@littlefeet-inc.com>
@@ -51,13 +51,11 @@
#include <linux/interrupt.h>
#include <linux/i2c.h>
-#include <linux/i2c-algo-emma2rh.h>
-
-#include <asm/emma2rh/emma2rh.h>
+#include "i2c-algo-emma2rh.h"
#ifdef DEBUG
#define i2c_emma2rh_debug(level,op) do { if (i2c_debug>=(level)) { op; } } while (0)
-static int i2c_debug;
+static int i2c_debug = 9;
module_param(i2c_debug, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(i2c_debug,
"debug level - 0 off; 1 normal; 2,3 more verbose; 9 i2c-protocol");
@@ -73,13 +71,15 @@
#define EMMA2RH_I2C_RETRIES 3
#define EMMA2RH_I2C_TIMEOUT 100
-/* --- setting states on the bus with the right timing: --------------- */
+/* --- setting states on the bus with the right timing: ---------------
+*/
#define set_emma(adap, ctl, val) adap->setemma(adap->data, ctl, val)
#define get_emma(adap, ctl) adap->getemma(adap->data, ctl)
#define get_own(adap) adap->getown(adap->data)
#define get_clock(adap) adap->getclock(adap->data)
-/* --- other auxiliary functions -------------------------------------- */
+/* --- other auxiliary functions --------------------------------------
+*/
static void i2c_start(struct i2c_algo_emma_data *adap)
{
@@ -168,7 +168,8 @@
udelay(adap->udelay);
}
DEB2(if (i)
- printk(KERN_DEBUG "%s: needed %d retries for %d\n", __FUNCTION__, i, addr)) ;
+ printk(KERN_DEBUG "%s: needed %d retries for %d\n", __FUNCTION__,
+i, addr)) ;
return ret;
}
@@ -352,7 +353,7 @@
static u32 emma_func(struct i2c_adapter *adap)
{
- return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING;
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING;
}
/* --- exported algorithm data ---------------------------------------- */
--- drivers/i2c/algos/i2c-algo-emma2rh.h.orig 2007-03-15 13:32:50.000000000 +0100
+++ drivers/i2c/algos/i2c-algo-emma2rh.h 2007-04-12 10:08:18.000000000 +0200
@@ -17,7 +17,8 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/
-/* -------------------------------------------------------------------- */
+/* --------------------------------------------------------------------
+*/
#ifndef I2C_EMMA2RH_H
#define I2C_EMMA2RH_H
@@ -102,4 +103,19 @@
#define I2C_EMMA_SHR 0x40
#define I2C_EMMA_INT 0x50
#define I2C_EMMA_INTM 0x60
+
+struct i2c_algo_emma_data {
+ void *data; /* private data for lolevel routines */
+ void (*setemma) (void *data, int ctl, int val);
+ int (*getemma) (void *data, int ctl);
+ int (*getown) (void *data);
+ int (*getclock) (void *data);
+ void (*waitforpin) (void *data);
+
+ /* local settings */
+ int udelay;
+ int timeout;
+
+};
+
#endif /* I2C_EMMA2RH_H */
--- drivers/i2c/busses/i2c-emma2rh.c.orig 2007-03-15 13:33:45.000000000 +0100
+++ drivers/i2c/busses/i2c-emma2rh.c 2007-04-12 10:06:48.000000000 +0200
@@ -14,7 +14,7 @@
Copyright (C) 1995-97 Simon G. Vogl
1998-99 Hans Berglund
- With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
+ With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
Frodo Looijaard <frodol@dds.nl>
Partialy rewriten by Oleg I. Vdovikin for mmapped support of
@@ -47,17 +47,17 @@
#include <linux/device.h>
#include <linux/i2c.h>
#include <linux/i2c-id.h>
-#include <linux/i2c-algo-emma2rh.h>
#include <linux/platform_device.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/atomic.h>
-#include <asm/emma2rh/emma2rh.h>
-#define I2C_EMMA2RH "emma2rh-iic"
+#include "../algos/i2c-algo-emma2rh.h"
+
static int i2c_debug = 0;
-/* ----- global defines ----------------------------------------------- */
+/* ----- global defines -----------------------------------------------
+*/
#define DEB(x) if (i2c_debug>=1) x
#define DEB2(x) if (i2c_debug>=2) x
#define DEB3(x) if (i2c_debug>=3) x
@@ -75,7 +75,8 @@
wait_queue_head_t wait;
};
-/* ----- local functions ----------------------------------------------*/
+/* ----- local functions ----------------------------------------------
+*/
static void i2c_emma_setbyte(void *data, int ctl, int val)
{
int address = ((struct i2c_drvdata *)data)->base + ctl;
@@ -148,9 +149,8 @@
udelay(100);
}
-static int __devinit i2c_emma_probe(struct device *dev)
+static int __devinit i2c_emma_probe(struct platform_device *pdev)
{
- struct platform_device *pdev = to_platform_device(dev);
struct i2c_drvdata *dd;
int err = 0;
struct resource *r;
@@ -167,81 +167,108 @@
dd->alg.getclock = i2c_emma_getclock;
dd->alg.waitforpin = i2c_emma_waitforpin;
dd->alg.udelay = 80;
- dd->alg.mdelay = 80;
dd->alg.timeout = 200;
- strcpy(dd->adap.name, dev->bus_id);
+ strcpy(dd->adap.name, pdev->name);
dd->adap.id = 0x00;
dd->adap.algo = NULL;
dd->adap.algo_data = &dd->alg;
dd->adap.client_register = i2c_emma_reg;
dd->adap.client_unregister = i2c_emma_unreg;
- spin_lock_init(&dd->lock);
-
- atomic_set(&dd->pending,0);
- init_waitqueue_head(&dd->wait);
-
- dev_set_drvdata(dev, dd);
-
- r = platform_get_resource(pdev, 0, 0);
- /* get resource of type '0' with #0 */
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);/* get resource of type '0' with #0 */
+
if (!r) {
printk("Cannot get resource\n");
err = -ENODEV;
goto out_free;
- }
- dd->base = r->start;
-
+ }
+
+ if (!request_mem_region(r->start, r->end - r->start + 1, pdev->name)) {
+ printk("Memory region busy\n");
+ err = -EBUSY;
+ goto out_mem_region;
+ }
+
+ dd->base = ioremap_nocache(r->start, r->end - r->start);
+ if (!dd->base) {
+ printk("Unable to map registers\n");
+ err = -EIO;
+ goto out_ioremap;
+ }
+
dd->irq = platform_get_irq(pdev,0);
dd->clock = FAST397;
dd->own = 0x40 + pdev->id * 4;
- err = request_irq(dd->irq, i2c_emma_handler, 0, dev->bus_id, dd);
+ err = request_irq(dd->irq, i2c_emma_handler, 0, pdev->name, dd);
if (err < 0)
goto out_free;
+
+ spin_lock_init(&dd->lock);
+ atomic_set(&dd->pending,0);
+ init_waitqueue_head(&dd->wait);
+
+ platform_set_drvdata(pdev, dd);
+
if ((err = i2c_emma_add_bus(&dd->adap)) < 0)
goto out_irq;
return 0;
+
out_irq:
- free_irq(dd->irq, dev->bus_id);
+ free_irq(dd->irq, dd);
+out_ioremap:
+ iounmap(dd->base);
+out_mem_region:
+ release_mem_region(r->start, r->end - r->start + 1);
out_free:
- kfree(dd);
+ kfree(dd);
out:
- return err;
+ return err;
}
-static int __devexit i2c_emma_remove (struct device *dev)
+static int __devexit i2c_emma_remove (struct platform_device *pdev)
{
- struct i2c_drvdata* dd = dev_get_drvdata(dev);
-
- if (dd) {
- disable_irq(dd->irq);
- free_irq(dd->irq, dev->bus_id);
- i2c_emma_del_bus(&dd->adap);
- kfree(dd);
- }
- return 0;
-}
-
-static struct device_driver i2c_emma_driver = {
- .bus = &platform_bus_type,
- .name = I2C_EMMA2RH,
- .probe = i2c_emma_probe,
- .remove = i2c_emma_remove,
+ struct i2c_drvdata* dd = platform_get_drvdata(pdev);
+ struct resource *r;
+
+ i2c_emma_del_bus(&dd->adap);
+ platform_set_drvdata(pdev, NULL);
+ r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if(r)
+ free_irq(r->start, dd);
+
+ iounmap(dd->base);
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if(r)
+ release_mem_region(r->start, r->end - r->start + 1);
+ kfree(dd);
+
+ return 0;
+}
+
+static struct platform_driver i2c_emma_driver = {
+ .probe = i2c_emma_probe,
+ .remove = __devexit_p(i2c_emma_remove),
+ .driver = {
+ .owner = THIS_MODULE,
+ .bus = &platform_bus_type,
+ .name = "emma2rh-iic",
+ }
};
static int __init i2c_emma_init(void)
{
- return driver_register(&i2c_emma_driver);
+ return platform_driver_register(&i2c_emma_driver);
}
static void __exit i2c_emma_exit(void)
{
- driver_unregister(&i2c_emma_driver);
+ platform_driver_unregister(&i2c_emma_driver);
}
MODULE_AUTHOR("NEC Electronics Corporation <www.necel.com>");
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] EMMA2RH I2C driver
2007-04-12 8:43 [PATCH] EMMA2RH I2C driver Markus Gothe
@ 2007-04-12 14:49 ` Sergei Shtylyov
0 siblings, 0 replies; 4+ messages in thread
From: Sergei Shtylyov @ 2007-04-12 14:49 UTC (permalink / raw)
To: Markus Gothe; +Cc: linux-mips
Markus Gothe wrote:
> As Ralf pointed out in march I've been polishing the IIC-driver for
> EMMA2RH.
> I've shaped up the I2C-driver to be a platform-device-driver and added
> accurately memory-mapping/unmapping and irq-request/free.
> There was a datastructure missing which was pretty straight forward to
> figure out how to rebuild (i.e. i2c_algo_emma_data).
Below are a few comments...
> --- drivers/i2c/algos/i2c-algo-emma2rh.c.orig 2007-03-15 13:32:35.000000000 +0100
> +++ drivers/i2c/algos/i2c-algo-emma2rh.c 2007-04-12 10:08:58.000000000 +0200
[...]
> @@ -73,13 +71,15 @@
> #define EMMA2RH_I2C_RETRIES 3
> #define EMMA2RH_I2C_TIMEOUT 100
>
> -/* --- setting states on the bus with the right timing: --------------- */
> +/* --- setting states on the bus with the right timing: ---------------
> +*/
> #define set_emma(adap, ctl, val) adap->setemma(adap->data, ctl, val)
> #define get_emma(adap, ctl) adap->getemma(adap->data, ctl)
> #define get_own(adap) adap->getown(adap->data)
> #define get_clock(adap) adap->getclock(adap->data)
>
> -/* --- other auxiliary functions -------------------------------------- */
> +/* --- other auxiliary functions --------------------------------------
> +*/
>
> static void i2c_start(struct i2c_algo_emma_data *adap)
> {
> @@ -168,7 +168,8 @@
> udelay(adap->udelay);
> }
> DEB2(if (i)
> - printk(KERN_DEBUG "%s: needed %d retries for %d\n", __FUNCTION__, i, addr)) ;
> + printk(KERN_DEBUG "%s: needed %d retries for %d\n", __FUNCTION__,
> +i, addr)) ;
Please don't "uglify" the code. If you intend to carry it to the new line indent properlu (by starting it under paren).
> --- drivers/i2c/algos/i2c-algo-emma2rh.h.orig 2007-03-15 13:32:50.000000000 +0100
> +++ drivers/i2c/algos/i2c-algo-emma2rh.h 2007-04-12 10:08:18.000000000 +0200
> @@ -17,7 +17,8 @@
> You should have received a copy of the GNU General Public License
> along with this program; if not, write to the Free Software
> Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/
> -/* -------------------------------------------------------------------- */
> +/* --------------------------------------------------------------------
> +*/
No need to make the comment more ugly too.
> #ifndef I2C_EMMA2RH_H
> #define I2C_EMMA2RH_H
> @@ -102,4 +103,19 @@
> #define I2C_EMMA_SHR 0x40
> #define I2C_EMMA_INT 0x50
> #define I2C_EMMA_INTM 0x60
> +
> +struct i2c_algo_emma_data {
> + void *data; /* private data for lolevel routines */
> + void (*setemma) (void *data, int ctl, int val);
> + int (*getemma) (void *data, int ctl);
> + int (*getown) (void *data);
> + int (*getclock) (void *data);
> + void (*waitforpin) (void *data);
> +
> + /* local settings */
> + int udelay;
> + int timeout;
> +
> +};
> +
> #endif /* I2C_EMMA2RH_H */
> --- drivers/i2c/busses/i2c-emma2rh.c.orig 2007-03-15 13:33:45.000000000 +0100
> +++ drivers/i2c/busses/i2c-emma2rh.c 2007-04-12 10:06:48.000000000 +0200
> @@ -14,7 +14,7 @@
> Copyright (C) 1995-97 Simon G. Vogl
> 1998-99 Hans Berglund
>
> - With some changes from KyУЖsti MУЄlkki <kmalkki@cc.hut.fi> and even
> + With some changes from Kyіsti Mфlkki <kmalkki@cc.hut.fi> and even
> Frodo Looijaard <frodol@dds.nl>
I'm not sure what that change is.
> @@ -167,81 +167,108 @@
> dd->alg.getclock = i2c_emma_getclock;
> dd->alg.waitforpin = i2c_emma_waitforpin;
> dd->alg.udelay = 80;
> - dd->alg.mdelay = 80;
> dd->alg.timeout = 200;
>
> - strcpy(dd->adap.name, dev->bus_id);
> + strcpy(dd->adap.name, pdev->name);
> dd->adap.id = 0x00;
> dd->adap.algo = NULL;
> dd->adap.algo_data = &dd->alg;
> dd->adap.client_register = i2c_emma_reg;
> dd->adap.client_unregister = i2c_emma_unreg;
>
> - spin_lock_init(&dd->lock);
> -
> - atomic_set(&dd->pending,0);
> - init_waitqueue_head(&dd->wait);
> -
> - dev_set_drvdata(dev, dd);
> -
> - r = platform_get_resource(pdev, 0, 0);
> - /* get resource of type '0' with #0 */
>
> + r = platform_get_resource(pdev, IORESOURCE_MEM, 0);/* get resource of type '0' with #0 */
> +
Put at least one space between ; and comment, and no trailing whitespace, please.
> if (!r) {
> printk("Cannot get resource\n");
> err = -ENODEV;
> goto out_free;
> - }
> - dd->base = r->start;
> -
> + }
> +
> + if (!request_mem_region(r->start, r->end - r->start + 1, pdev->name)) {
> + printk("Memory region busy\n");
> + err = -EBUSY;
> + goto out_mem_region;
You've already failed to request region, why then free it?
> + }
> +
> + dd->base = ioremap_nocache(r->start, r->end - r->start);
> + if (!dd->base) {
> + printk("Unable to map registers\n");
> + err = -EIO;
> + goto out_ioremap;
You've already failed to ioremap() it, why call iounmap()?
> + }
> +
> dd->irq = platform_get_irq(pdev,0);
> dd->clock = FAST397;
> dd->own = 0x40 + pdev->id * 4;
>
> - err = request_irq(dd->irq, i2c_emma_handler, 0, dev->bus_id, dd);
> + err = request_irq(dd->irq, i2c_emma_handler, 0, pdev->name, dd);
> if (err < 0)
> goto out_free;
And you've forgetten to call iounmap() and release_mem_region() in this case...
> +
> + spin_lock_init(&dd->lock);
>
> + atomic_set(&dd->pending,0);
> + init_waitqueue_head(&dd->wait);
> +
> + platform_set_drvdata(pdev, dd);
> +
> if ((err = i2c_emma_add_bus(&dd->adap)) < 0)
> goto out_irq;
>
> return 0;
> +
> out_irq:
> - free_irq(dd->irq, dev->bus_id);
> + free_irq(dd->irq, dd);
> +out_ioremap:
> + iounmap(dd->base);
> +out_mem_region:
> + release_mem_region(r->start, r->end - r->start + 1);
> out_free:
> - kfree(dd);
> + kfree(dd);
> out:
> - return err;
> + return err;
> }
The cleanup code needs fixing, as you can see...
WBR, Sergei
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2007-04-12 14:49 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-04-12 8:43 [PATCH] EMMA2RH I2C driver Markus Gothe
2007-04-12 14:49 ` Sergei Shtylyov
[not found] <20070308145948.GA4235@linux-mips.org>
2007-03-13 17:59 ` dmitry pervushin
2007-03-14 17:52 ` Ralf Baechle
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox