From: David Brownell Date: Tue, 26 Jul 2005 08:10:40 +0000 (-0700) Subject: [PATCH] ARM: OMAP: I2C cleanups X-Git-Tag: v2.6.13-omap1~62 X-Git-Url: http://pilppa.com/gitweb/?a=commitdiff_plain;h=ff0d5f8bd361d07b78a1eabab2922734dc8ce656;p=linux-2.6-omap-h63xx.git [PATCH] ARM: OMAP: I2C cleanups I2C driver cleanups, shrinking object code by a bit over 1KB: * cleanup debug-only code - remove the scan code ... doesn't work, among other things - default debug (and scan) code to "off"; - reduce (ab)use of driver-specific printk wrappers; * comments: - correct and/or cleanup; - remove internal changelog (that's for GIT, BK, CVS, etc); * move all MODULE_* stuff to conventional locations; * fix some of the whitespace problems Plus small bugfixes: * reserve physical memory addresses instead of virtual i/o ones; * define the adapter as supporting "I2C_CLASS_HWMON" * don't clobber driver state if reservation fails * check directly for I2C rev1 instead of omap1510 CPU; * using the right driver name in several places. * startup message info is no longer content-free Plus start on the "sparse" fixes. Signed-off-by: David Brownell Signed-off-by: Tony Lindgren --- diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 0ebfac452c7..82a2014cf13 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -1,16 +1,13 @@ /* * linux/drivers/i2c/i2c-omap.c * - * TI OMAP I2C unified algorith+adapter driver (inspired by i2c-ibm_iic.c and i2c-omap1510.c) + * TI OMAP I2C master mode driver * * Copyright (C) 2003 MontaVista Software, Inc. - * * Copyright (C) 2004 Texas Instruments. * * ---------------------------------------------------------------------------- - * This file was highly leveraged from i2c-elektor.c, which was created - * by Simon G. Vogl and Hans Berglund: - * + * This file was highly leveraged from i2c-elektor.c: * * Copyright 1995-97 Simon G. Vogl * 1998-99 Hans Berglund @@ -31,28 +28,6 @@ * 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. - * ---------------------------------------------------------------------------- - Modifications: - ver. 1.1: Nov 2003, MontaVista Software - - added DPM support - ver. 1.2: Feb 2004, Texas Instruments - - Ported to 2.6 kernel (Feb 2004) - - Added support for I2C_M_IGNORE_NAK option. - ver. 1.3: Mar 2004, Juha Yrjölä - - Cleaned up - ver. 1.4: Aug 2004, Thiago Radicchi DCC-UFMG / iNdT - - Updated omap_i2c_isr to remove messages of too much work in one IRQ, - by reading the interrupt vector, as specified on ref [1] - ver. 1.5: Oct 2004, Tuukka Tikkanen - - Changed clock handling - * - * REFERENCES: - * - * 1. OMAP5910 Dual-Core Processor Inter-Integrated Circuit (I2C) - * Controller Reference Guide - * Document number: spru681 - * Date: October 2003 - * http://www-s.ti.com/sc/psheets/spru681/spru681.pdf */ #include @@ -78,13 +53,19 @@ #include #include "i2c-omap.h" -/* ----- global defines ----------------------------------------------- */ -#define MODULE_NAME "OMAP I2C" -#define OMAP_I2C_TIMEOUT (1*HZ) /* timeout waiting for an I2C transaction */ +#undef I2C_OMAP_DEBUG + + +/* ----- debug defines ----------------------------------------------- */ -#define I2C_OMAP_DEBUG #ifdef I2C_OMAP_DEBUG static int i2c_debug = 0; + +module_param(i2c_debug, int, 0); +MODULE_PARM_DESC(i2c_debug, + "debug level - 0 off; 1 normal; 2,3 more verbose; " + "9 omap-protocol"); + #define DEB0(format, arg...) printk(KERN_DEBUG MODULE_NAME " DEBUG: " format "\n", ## arg ) #define DEB1(format, arg...) \ if (i2c_debug>=1) { \ @@ -111,10 +92,13 @@ static int i2c_debug = 0; #define DEB9(fmt, args...) #endif +/* ----- global defines ----------------------------------------------- */ +static const char driver_name[] = "i2c_omap"; + +#define MODULE_NAME "OMAP I2C" +#define OMAP_I2C_TIMEOUT (1*HZ) /* timeout waiting for an I2C transaction */ + #define err(format, arg...) printk(KERN_ERR MODULE_NAME " ERROR: " format "\n", ## arg ) -#define info(format, arg...) printk(KERN_INFO MODULE_NAME ": " format "\n", ## arg ) -#define warn(format, arg...) printk(KERN_WARNING MODULE_NAME " WARNING: " format "\n", ## arg ) -#define emerg(format, arg...) printk(KERN_EMERG MODULE_NAME " EMERGENCY: " format "\n", ## arg ) #ifdef CONFIG_ARCH_OMAP1510 #define omap_i2c_rev1() (readw(OMAP_I2C_REV) < 0x20) @@ -122,12 +106,18 @@ static int i2c_debug = 0; #define omap_i2c_rev1() 0 #endif -#define DEFAULT_OWN 1 /*default own I2C address */ +#define DEFAULT_OWN 1 /* default own I2C address */ #define MAX_MESSAGES 65536 /* max number of messages */ static int clock = 100; /* Default: Fast Mode = 400 KHz, Standard Mode = 100 KHz */ +module_param(clock, int, 0); +MODULE_PARM_DESC(clock, + "Set I2C clock in KHz: 100 (Standard Mode) or 400 (Fast Mode)"); + static int own; -static int i2c_scan; /* have a look at what's hanging 'round */ +module_param(own, int, 0); +MODULE_PARM_DESC(own, "Address of OMAP i2c master (0 for default == 1)"); + static struct omap_i2c_dev { int cmd_complete, cmd_err; @@ -136,23 +126,23 @@ static struct omap_i2c_dev { size_t buf_len; } omap_i2c_dev; +/* FIXME pass "sparse": convert {read,write}w() with iomapped addresses + * to omap_{read,write}w() with physical addresses. + */ -static int omap_i2c_reset(void) +static void omap_i2c_reset(void) { unsigned long timeout; u16 psc; struct clk *armxor_ck; unsigned long armxor_rate; - if(!cpu_is_omap1510()) { - + if (!omap_i2c_rev1()) writew(OMAP_I2C_SYSC_SRST, OMAP_I2C_SYSC); /*soft reset */ - } - else { + else writew(OMAP_I2C_CON_RST, OMAP_I2C_CON); /* reset */ - } - armxor_ck = clk_get(0, "armxor_ck"); + armxor_ck = clk_get(NULL, "armxor_ck"); if (IS_ERR(armxor_ck)) { printk(KERN_WARNING "i2c: Could not obtain armxor_ck rate.\n"); armxor_rate = 12000000; @@ -187,19 +177,16 @@ static int omap_i2c_reset(void) /* Take the I2C module out of reset: */ writew(OMAP_I2C_CON_EN, OMAP_I2C_CON); - if(!cpu_is_omap1510()){ + if (!omap_i2c_rev1()){ timeout = jiffies + OMAP_I2C_TIMEOUT; while (!(readw(OMAP_I2C_SYSS) & OMAP_I2C_SYSS_RDONE)) { if (time_after(jiffies, timeout)) { err("timeout waiting for I2C reset complete"); - return -EFAULT; + break; } - schedule_timeout(1); + msleep(1); } } - - return 0; - } /* @@ -213,7 +200,7 @@ omap_i2c_wait_for_bb(char allow_sleep) timeout = jiffies + OMAP_I2C_TIMEOUT; while (readw(OMAP_I2C_STAT) & OMAP_I2C_STAT_BB) { if (time_after(jiffies, timeout)) { - warn("timeout waiting for bus ready"); + printk(KERN_WARNING "timeout waiting for bus ready\n"); return -ETIMEDOUT; } if (allow_sleep) @@ -229,8 +216,8 @@ omap_i2c_wait_for_bb(char allow_sleep) static int omap_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) { - struct omap_i2c_dev *dev = i2c_get_adapdata(adap); - u8 zero_byte = 0; + struct omap_i2c_dev *dev = i2c_get_adapdata(adap); + u8 zero_byte = 0; int r; u16 w; @@ -283,12 +270,12 @@ omap_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) if (msg->flags & I2C_M_IGNORE_NAK) return msg->len; if (stop) - writew(readw(OMAP_I2C_CON) | OMAP_I2C_CON_STP, OMAP_I2C_CON); + writew(readw(OMAP_I2C_CON) | OMAP_I2C_CON_STP, + OMAP_I2C_CON); return -EREMOTEIO; } - if (dev->cmd_err & OMAP_I2C_STAT_AL || - dev->cmd_err & OMAP_I2C_STAT_ROVR || - dev->cmd_err & OMAP_I2C_STAT_XUDF) { + if ((OMAP_I2C_STAT_AL | OMAP_I2C_STAT_ROVR | OMAP_I2C_STAT_XUDF) + & dev->cmd_err) { omap_i2c_reset(); return -EIO; } @@ -296,8 +283,8 @@ omap_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) } /* - * Prepare controller for a transaction and call omap_i2c_rxbytes - * to do the work. + * Prepare controller for a transaction and call omap_i2c_xfer_msg + * to do the work during IRQ processing. */ static int omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) @@ -315,6 +302,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) if (msgs[i].buf == NULL) return -EINVAL; +// REVISIT: initialize and use adap->retries + if ((r = omap_i2c_wait_for_bb(1)) < 0) return r; @@ -338,49 +327,6 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) return r; } -/* - * Sanity check for the adapter hardware - check the reaction of - * the bus lines only if it seems to be idle. - * - * Scan the I2C bus for valid 7 bit addresses - * (ie things that ACK on 1byte read) - * if i2c_debug is off we print everything on one line. - * if i2c_debug is on we do a newline per print so we don't - * clash too much with printf's in the other functions. - * TODO: check for 10-bit mode and never run as a slave. - */ -static int -omap_i2c_scan_bus(struct i2c_adapter *adap) -{ - int found = 0; - int i; - struct i2c_msg msg; - char data[1]; - - info("scanning for active I2C devices on the bus..."); - - for (i = 1; i < 0x7f; i++) { - if (readw(OMAP_I2C_OA) == i) - continue; - - msg.addr = i; - msg.buf = data; - msg.len = 0; - msg.flags = I2C_M_RD; - - if (omap_i2c_xfer(adap, &msg, 1) == 0) { - info("I2C device 0x%02x found", i); - found++; - } - } - - if (!found) - info("found nothing"); - - return found; -} - - static u32 omap_i2c_func(struct i2c_adapter *adap) { @@ -407,7 +353,7 @@ omap_i2c_isr(int this_irq, void *dev_id, struct pt_regs *regs) while ((stat = readw(OMAP_I2C_STAT)) & bits) { if (count++ == 100) { - warn("Too much work in one IRQ"); + printk(KERN_WARNING "Too much work in one IRQ\n"); break; } @@ -460,11 +406,11 @@ omap_i2c_isr(int this_irq, void *dev_id, struct pt_regs *regs) continue; } if (stat & OMAP_I2C_STAT_ROVR) { - warn("Receive overrun"); + pr_debug("Receive overrun\n"); dev->cmd_err |= OMAP_I2C_STAT_ROVR; } if (stat & OMAP_I2C_STAT_XUDF) { - warn("Transmit overflow"); + pr_debug("Transmit overflow\n"); dev->cmd_err |= OMAP_I2C_STAT_XUDF; } if (stat & OMAP_I2C_STAT_NACK) { @@ -473,7 +419,7 @@ omap_i2c_isr(int this_irq, void *dev_id, struct pt_regs *regs) writew(OMAP_I2C_CON_STP, OMAP_I2C_CON); } if (stat & OMAP_I2C_STAT_AL) { - warn("Arbitration lost"); + pr_debug("Arbitration lost\n"); dev->cmd_err |= OMAP_I2C_STAT_AL; omap_i2c_complete_cmd(dev); } @@ -495,24 +441,17 @@ static void omap_i2c_device_release(struct device *dev) } static struct i2c_algorithm omap_i2c_algo = { - .name = "OMAP I2C algorithm", - .id = I2C_ALGO_EXP, - .master_xfer = omap_i2c_xfer, - .smbus_xfer = NULL, - .slave_send = NULL, - .slave_recv = NULL, - .algo_control = NULL, - .functionality = omap_i2c_func, + .name = "OMAP I2C algorithm", + .id = I2C_ALGO_EXP, + .master_xfer = omap_i2c_xfer, + .functionality = omap_i2c_func, }; static struct i2c_adapter omap_i2c_adap = { - .owner = THIS_MODULE, - .name = "OMAP I2C adapter", - .id = I2C_ALGO_EXP, /* REVISIT: register for id */ - .algo = &omap_i2c_algo, - .algo_data = NULL, - .client_register = NULL, - .client_unregister = NULL, + .owner = THIS_MODULE, + .class = I2C_CLASS_HWMON, + .name = "OMAP I2C adapter", + .algo = &omap_i2c_algo, }; static struct device_driver omap_i2c_driver = { @@ -535,8 +474,12 @@ omap_i2c_init(void) { int r; - info("Driver ver. 1.3"); - DEB0("%s %s", __TIME__, __DATE__); + r = (int) request_mem_region(io_v2p(OMAP_I2C_BASE), OMAP_I2C_IOSIZE, + driver_name); + if (!r) { + pr_debug("%s: I2C region already claimed\n", driver_name); + return -EBUSY; + } if (clock > 200) clock = 400; /*Fast mode */ @@ -546,27 +489,24 @@ omap_i2c_init(void) if (own < 1 || own > 0x7f) own = DEFAULT_OWN; - memset(&omap_i2c_dev, 0, sizeof(omap_i2c_dev)); + memset(&omap_i2c_dev, 0, sizeof(omap_i2c_dev)); init_waitqueue_head(&omap_i2c_dev.cmd_wait); - r = (int) request_region(OMAP_I2C_BASE, OMAP_I2C_IOSIZE, MODULE_NAME); - if (!r) { - err("I2C is already in use"); - return -ENODEV; - } - - r = request_irq(INT_I2C, omap_i2c_isr, 0, MODULE_NAME, &omap_i2c_dev); + r = request_irq(INT_I2C, omap_i2c_isr, 0, driver_name, &omap_i2c_dev); if (r) { - err("failed to request I2C IRQ"); - goto do_release_region; + pr_debug("%s: failure requesting irq\n", driver_name); + goto do_release_region; } + r = readw(OMAP_I2C_REV) & 0xff; + pr_info("%s: rev%d.%d at %d KHz\n", driver_name, + r >> 4, r & 0xf, clock); + i2c_set_adapdata(&omap_i2c_adap, &omap_i2c_dev); r = i2c_add_adapter(&omap_i2c_adap); if (r) { - err("failed to add adapter"); - goto do_free_irq; - return r; + pr_debug("%s: failure adding adapter\n", driver_name); + goto do_free_irq; } /* configure I/O pin multiplexing */ @@ -576,8 +516,6 @@ omap_i2c_init(void) omap_i2c_reset(); - if (i2c_scan) - omap_i2c_scan_bus(&omap_i2c_adap); if(driver_register(&omap_i2c_driver) != 0) printk(KERN_ERR "Driver register failed for omap_i2c\n"); if(platform_device_register(&omap_i2c_device) != 0) { @@ -588,9 +526,9 @@ omap_i2c_init(void) return 0; do_free_irq: - free_irq(INT_I2C, &omap_i2c_dev); + free_irq(INT_I2C, &omap_i2c_dev); do_release_region: - release_region(OMAP_I2C_BASE, OMAP_I2C_IOSIZE); + release_region(io_v2p(OMAP_I2C_BASE), OMAP_I2C_IOSIZE); return r; } @@ -601,31 +539,15 @@ omap_i2c_exit(void) i2c_del_adapter(&omap_i2c_adap); writew(0, OMAP_I2C_CON); free_irq(INT_I2C, &omap_i2c_dev); - release_region(OMAP_I2C_BASE, OMAP_I2C_IOSIZE); + release_region(io_v2p(OMAP_I2C_BASE), OMAP_I2C_IOSIZE); driver_unregister(&omap_i2c_driver); platform_device_unregister(&omap_i2c_device); } -MODULE_AUTHOR("MontaVista Software, Inc."); -MODULE_DESCRIPTION("TI OMAP I2C bus adapter"); -MODULE_LICENSE("GPL"); - -module_param(clock, int, 0); -MODULE_PARM_DESC(clock, - "Set I2C clock in KHz: 100 (Standard Mode) or 400 (Fast Mode)"); - -module_param(own, int, 0); - -module_param(i2c_scan, int, 0); -MODULE_PARM_DESC(i2c_scan, "Scan for active I2C clients on the bus"); - -#ifdef I2C_OMAP_DEBUG -module_param(i2c_debug, int, 0); -MODULE_PARM_DESC(i2c_debug, - "debug level - 0 off; 1 normal; 2,3 more verbose; " - "9 omap-protocol"); -#endif - /* i2c may be needed to bring up other drivers */ subsys_initcall(omap_i2c_init); module_exit(omap_i2c_exit); + +MODULE_AUTHOR("MontaVista Software, Inc. (and others)"); +MODULE_DESCRIPTION("TI OMAP I2C bus adapter"); +MODULE_LICENSE("GPL");