[i2c] [I2C] Emulation SMBus block read on I2C. Adaptation for the Freescale MPC.
Derer, Renaud
Renaud.Derer at barco.com
Fri Mar 2 16:53:58 CET 2007
This patche was tested succesfully on a MPC8347E platform with an SMBus
battery as device under test. The goal of this improvement was to be
able to read string like the battery manufacturer name, Chemistery of
the battery...
### PATCH BEGINS HERE
Subject: i2c: Emulate SMBus block read over I2C on the MPC I2C interface
Date: 02 March 2007
This patch was applied succesfully on a MPC8347 platform to read SMBus
strings
in a battery with I2CDump (Manufacturer name, Chemistery, Battery
commercial name...)
The testing setup was:
- The 2.6.20 official kernel patched into 2.6.20.1.
- Patch from Jean Delvare to enable SMBus emulation
http://khali.linux-fr.org/devel/linux-2.6/jdelvare-i2c/i2c-add-smbus-blo
ck-read-emulation.patch (02/19/2007)
ChangeLog and new features:
- "mpc_read" and "mpc_write" work now directly on the *msg structure
and not on local copies
Choice done to avoid passing additionnal parameters because they
already are in the msg structure
- [mpc_read] Add detection of the I2C_M_RECV_LEN that announce a
read length in the first read
- [mpc_read] Add special read that update the lenght of the read in
block read case
- [mpc_functionality] Add I2C_FUNC_SMBUS_READ_BLOCK_DATA and
I2C_FUNC_SMBUS_BLOCK_PROC_CALL capacities
Signed-off-by: Renaud DERER <renaud.derer at barco.com>
diff -upr linux-2.6.20.1-orig/drivers/i2c/busses/i2c-mpc.c
linux-2.6.20.1-dev/drivers/i2c/busses/i2c-mpc.c
--- linux-2.6.20.1-orig/drivers/i2c/busses/i2c-mpc.c 2007-02-04
19:44:54.000000000 +0100
+++ linux-2.6.20.1-dev/drivers/i2c/busses/i2c-mpc.c 2007-03-01
17:37:43.000000000 +0100
-static int mpc_write(struct mpc_i2c *i2c, int target,
- const u8 * data, int length, int restart)
+static int mpc_write(struct mpc_i2c *i2c, struct i2c_msg *msg, int
restart)
{
int i;
unsigned timeout = i2c->adap.timeout;
@@ -169,14 +168,14 @@ static int mpc_write(struct mpc_i2c *i2c
/* Start as master */
writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags);
/* Write target byte */
- writeb((target << 1), i2c->base + MPC_I2C_DR);
+ writeb((msg->addr << 1), i2c->base + MPC_I2C_DR);
if (i2c_wait(i2c, timeout, 1) < 0)
return -1;
- for (i = 0; i < length; i++) {
+ for (i = 0; i < msg->len; i++) {
/* Write data byte */
- writeb(data[i], i2c->base + MPC_I2C_DR);
+ writeb(msg->buf[i], i2c->base + MPC_I2C_DR);
if (i2c_wait(i2c, timeout, 1) < 0)
return -1;
@@ -185,8 +184,7 @@ static int mpc_write(struct mpc_i2c *i2c
return 0;
}
-static int mpc_read(struct mpc_i2c *i2c, int target,
- u8 * data, int length, int restart)
+static int mpc_read(struct mpc_i2c *i2c, struct i2c_msg *msg, int
restart)
{
unsigned timeout = i2c->adap.timeout;
int i;
@@ -198,34 +196,55 @@ static int mpc_read(struct mpc_i2c *i2c,
/* Switch to read - restart */
writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags);
/* Write target address byte - this time with the read flag set
*/
- writeb((target << 1) | 1, i2c->base + MPC_I2C_DR);
+ writeb((msg->addr << 1) | 1, i2c->base + MPC_I2C_DR);
if (i2c_wait(i2c, timeout, 1) < 0)
return -1;
- if (length) {
- if (length == 1)
- writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA |
CCR_TXAK);
- else
+ if (msg->len) {
+ if (msg->len == 1) {
+ if (msg->flags & I2C_M_RECV_LEN) {
+ writeccr(i2c, CCR_MIEN | CCR_MEN |
CCR_MSTA);
+ msg->len = 32;
+ }
+ else {
+ writeccr(i2c, CCR_MIEN | CCR_MEN |
CCR_MSTA | CCR_TXAK);
+ }
+ }
+ else {
writeccr(i3c, CCR_MIEN | CCR_MEN | CCR_MSTA);
+ }
/* Dummy read */
readb(i2c->base + MPC_I2C_DR);
}
- for (i = 0; i < length; i++) {
- if (i2c_wait(i2c, timeout, 0) < 0)
+ for (i = 0; i < msg->len; i++) {
+ if (i2c_wait(i2c, timeout, 0) < 0) {
return -1;
+ }
/* Generate txack on next to last byte */
- if (i == length - 2)
+ if (i == msg->len - 2) {
writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA |
CCR_TXAK);
+ }
/* Generate stop on last byte */
- if (i == length - 1)
+ if (i == msg->len - 1) {
writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_TXAK);
- data[i] = readb(i2c->base + MPC_I2C_DR);
+ }
+
+ msg->buf[i] = readb(i2c->base + MPC_I2C_DR);
+
+ /* Change lengh of block in case of I2C_M_RECV_LEN
transaction */
+ if ((msg->flags & I2C_M_RECV_LEN) && (i == 0)) {
+ /* Force length to 32 if the value read in the
ByteCount field is more than 32 */
+ if (msg->buf[i] > 32) {
+ msg->buf[i] = 32;
+ }
+ msg->len = msg->buf[i] + 1;
+ }
}
- return length;
+ return msg->len;
}
static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int
num)
@@ -258,10 +277,10 @@ static int mpc_xfer(struct i2c_adapter *
pmsg->len, pmsg->addr, i + 1, num);
if (pmsg->flags & I2C_M_RD)
ret =
- mpc_read(i2c, pmsg->addr, pmsg->buf,
pmsg->len, i);
+ mpc_read(i2c, pmsg, i);
else
ret =
- mpc_write(i2c, pmsg->addr, pmsg->buf,
pmsg->len, i);
+ mpc_write(i2c, pmsg, i);
}
mpc_i2c_stop(i2c);
return (ret < 0) ? ret : num;
@@ -269,7 +288,9 @@ static int mpc_xfer(struct i2c_adapter *
static u32 mpc_functionality(struct i2c_adapter *adap)
{
- return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
+ I2C_FUNC_SMBUS_READ_BLOCK_DATA |
+ I2C_FUNC_SMBUS_BLOCK_PROC_CALL;
}
static const struct i2c_algorithm mpc_algo = {
### PATCH ENDS HERE
As result for the battery we have the following on I2CDUMP output
/home/rend # ./i2cdump.bin
Error: No i2c-bus specified!
Syntax: i2cdump [-y] I2CBUS ADDRESS [MODE] [BANK [BANKREG]]
i2cdump -V
MODE is one of:
b (byte, default)
w (word)
W (word on even register addresses)
s (SMBus block)
i (I2C block)
c (consecutive byte)
Append 'p' to 'b', 'w', 's' or 'c' for PEC checking
I2CBUS is an integer
ADDRESS is an integer 0x00 - 0x7f
BANK and BANKREG are for byte and word accesses (default bank 0, reg
0x4e)
BANK is the command for smbusblock accesses (default 0)
Installed I2C busses:
i2c-1 i2c MPC adapter
i2c-0 i2c MPC adapter
/home/rend # ./i2cdump.bin 1 11 s 32
WARNING! This program can confuse your I2C bus, cause data loss and
worse!
I will probe file /dev/i2c/1, address 0xb, mode smbus block
Using command 0x20.
Continue? [Y/n] y
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: 49 4e 53 50 49 52 45 44 45 XX XX XX XX XX XX XX INSPIREDEXXXXXXX
10: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX
/home/rend # ./i2cdump.bin 1 11 s 33
WARNING! This program can confuse your I2C bus, cause data loss and
worse!
I will probe file /dev/i2c/1, address 0xb, mode smbus block
Using command 0x21.
Continue? [Y/n] y
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: 4e 43 32 30 34 30 48 44 20 XX XX XX XX XX XX XX NC2040HD XXXXXXX
10: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX
/home/rend # ./i2cdump.bin 1 11 s 34
WARNING! This program can confuse your I2C bus, cause data loss and
worse!
I will probe file /dev/i2c/1, address 0xb, mode smbus block
Using command 0x22.
Continue? [Y/n] y
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: 4c 49 4f 4e XX XX XX XX XX XX XX XX XX XX XX XX LIONXXXXXXXXXXXX
10: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XXXXXXXXXXXXXXXX
Renaud DERER
Development engineer electronics
BARCO - Medical Imaging Systems
President Kennedypark 35 - B-8500 KORTRIJK - BELGIUM
Tel. +32 56 233 177
Fax +32 56 233 457
http://www.barco.com/medical/
mailto:renaud.derer at barco.com
DISCLAIMER:
Unless indicated otherwise, the information contained in this message is privileged and confidential, and is intended only for the use of the addressee(s) named above and others who have been specifically authorized to receive it. If you are not the intended recipient, you are hereby notified that any dissemination, distribution or copying of this message and/or attachments is strictly prohibited. The company accepts no liability for any damage caused by any virus transmitted by this email. Furthermore, the company does not warrant a proper and complete transmission of this information, nor does it accept liability for any delays. If you have received this message in error, please contact the sender and delete the message. Thank you.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.lm-sensors.org/pipermail/i2c/attachments/20070302/6caf3e8e/attachment-0001.html
More information about the i2c
mailing list