I2C 関連
とりあえず、kernel の DEBUG メッセージより。ついでに、Sound 周りも…。
I2C周りの情報源
kernel ソースの Documentation/i2c/ 以下に拡張子は無いがテキストファイルがある。
kernel/Documentation/i2c/
のだが…、私は未だ読んでない。。。これからです…。
I2Cに繋がっているものは??
後述している kernel の DEBUG 関連を有効にした後、dmesg より、I2C関連を抜粋した。
I2C adapter driver [MSM I2C adapter-PRI] forgot to specify physical device
i2c-adapter i2c-0: adapter [MSM I2C adapter-PRI] registered
i2c-adapter i2c-0: client [SH_touchpanel] registered with bus id 0-0015
i2c-adapter i2c-0: client [akm8973] registered with bus id 0-001c
i2c-adapter i2c-0: client [SH_SMB380] registered with bus id 0-0038
i2c-adapter i2c-0: client [SH_qwerty_key] registered with bus id 0-0044
i2c-adapter i2c-0: client [tps65023] registered with bus id 0-0048
I2C adapter driver [MSM I2C adapter-AUX] forgot to specify physical device
i2c-adapter i2c-1: adapter [MSM I2C adapter-AUX] registered
と言う事らしい。(メッセージが出てくるのは個別ドライバあるモノだと思われる。…、たぶん)
リンク先は有ってるかどうかは不明。
I2C と Sound の DEBUG を有効にする。
実機から、config.gz を取得して、PCで展開。
それを、.conf にリネームして
$ make ARCH=arm CROSS_COMPILE=../../froyo_orig/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi- menuconfig
CROSS_COMPILE=のディレクトリは環境依存なので適宜変更の事。
Device Drivers --->
を選択、
I2C support --->
を選択、以下を有効にする。
[*] I2C Core debugging messages
[*] I2C Algorithm debugging messages
[*] I2C Bus debugging messages
[*] I2C Chip debugging messages
<Exit> で一つ戻って、
Sound card support --->
を選択
Advanced Linux Sound Architecture --->
を選択、以下を有効にする。
[*] Debug
[*] More verbose debug
[*] Enable PCM ring buffer overrun/underrun debugging
[*] Enable PCM ring buffer overrun/underrun debugging
<Exit> で戻って、
Save an Alternate Configuration File
.config
に保存して、<Exit>
I2C周りのDEBUGをさらに詳しく出力させる。
改変したファイル
drivers/i2c/i2c-dev.c
- i2cdev_read と i2cdev_write で buf の内容を1バイトずつ16進数で表示させている。
- 初期はbuf=で改行していたが、全行に buf[%d]= とつけるように変更した。
$ diff -ubB i2c-dev.c.orig i2c-dev.c
--- i2c-dev.c.orig 2011-02-09 01:19:18.614087449 +0900
+++ i2c-dev.c 2011-02-10 02:50:08.953117738 +0900
@@ -25,7 +25,7 @@
only fair to recognize him as co-author -- Frodo */
/* The I2C_RDWR ioctl code is written by Kolja Waschk <waschk@telos.de> */
-
+#define DEBUG 1
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
@@ -138,7 +138,9 @@
{
char *tmp;
int ret;
-
+#ifdef DEBUG
+ int i;
+#endif
struct i2c_client *client = (struct i2c_client *)file->private_data;
if (count > 8192)
@@ -154,6 +156,13 @@
ret = i2c_master_recv(client,tmp,count);
if (ret >= 0)
ret = copy_to_user(buf,tmp,count)?-EFAULT:ret;
+
+#ifdef DEBUG
+ for(i=0;i<(int)count;i++) {
+ pr_debug("i2c-dev:buf[%d]=0x%02X\n",i,(unsigned int)tmp[i]&0xff);
+ }
+#endif
+
kfree(tmp);
return ret;
}
@@ -163,6 +172,9 @@
{
int ret;
char *tmp;
+#ifdef DEBUG
+ int i;
+#endif
struct i2c_client *client = (struct i2c_client *)file->private_data;
if (count > 8192)
@@ -180,6 +192,13 @@
iminor(file->f_path.dentry->d_inode), count);
ret = i2c_master_send(client,tmp,count);
+
+#ifdef DEBUG
+ for(i=0;i<(int)count;i++) {
+ pr_debug("i2c-dev:buf[%d]=0x%02X\n",i,(unsigned int)tmp[i]&0xff);
+ }
+#endif
+
kfree(tmp);
return ret;
}
kernel/drivers/i2c/busses/i2c-msm.c
- ログがすごい量になったので、個別ドライバが判明しているアドレスの DEBUG 情報を出力させないようにした。
- grep -i i2c dmesg.txt 等と出来るように、ヘッダを追加している。
$ diff -ubB i2c-msm.c.orig i2c-msm.c
--- i2c-msm.c.orig 2011-02-10 01:40:32.314943342 +0900
+++ i2c-msm.c 2011-02-10 01:39:22.513606231 +0900
@@ -39,7 +39,7 @@
#include <mach/sharp_smem.h>
#endif /* FEATURE_SHLOCAL_SHI2C */
-#define DEBUG 0
+//#define DEBUG 0
#ifdef FEATURE_SHLOCAL_SHI2C
@@ -143,7 +143,7 @@
static void
dump_status(uint32_t status)
{
- printk("STATUS (0x%.8x): ", status);
+ printk("i2c-msm: STATUS (0x%.8x): ", status);
if (status & I2C_STATUS_BUS_MASTER)
printk("MST ");
if (status & I2C_STATUS_BUS_ACTIVE)
@@ -270,7 +277,13 @@
int err = 0;
#if DEBUG
+ if( dev->msg->addr != 0x15 &&
+ dev->msg->addr != 0x1c &&
+ dev->msg->addr != 0x38 &&
+ dev->msg->addr != 0x44 &&
+ dev->msg->addr != 0x48 ) {
dump_status(status);
+ }
#endif
spin_lock(&dev->lock);
kernel/drivers/i2c/i2c-core.c
$ diff -ubB i2c-core.c.orig i2c-core.c
--- i2c-core.c.orig 2011-02-10 01:53:07.143133972 +0900
+++ i2c-core.c 2011-02-10 01:21:50.693613883 +0900
@@ -1036,11 +1036,17 @@
if (adap->algo->master_xfer) {
#ifdef DEBUG
for (ret = 0; ret < num; ret++) {
+ if( msgs[ret].addr != 0x15 &&
+ msgs[ret].addr != 0x1c &&
+ msgs[ret].addr != 0x38 &&
+ msgs[ret].addr != 0x44 &&
+ msgs[ret].addr != 0x48 ) {
dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, "
"len=%d%s\n", ret, (msgs[ret].flags & I2C_M_RD)
? 'R' : 'W', msgs[ret].addr, msgs[ret].len,
(msgs[ret].flags & I2C_M_RECV_LEN) ? "+" : "");
}
+ }
#endif
if (in_atomic() || irqs_disabled()) {
kernel を makeする
$ make ARCH=arm CROSS_COMPILE=../../froyo_orig/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi-
エラーが出たので、
drivers/i2c/busses/i2c-msm.c:42:1: error: "DEBUG" redefined
drivers/i2c/chips/akm8973.c:54:1: error: "DEBUG" redefined
drivers/i2c/chips/smb380.c:28:1: error: "DEBUG" redefined
上記3つのファイル内の #define DEBUG をコメントアウトした。
boot.img化、ubi化、実機へ転送、リブート。
I2C周りのDEBUG情報の見方
dmesg でDEBUGメッセージを確認すると
<7>[ 9.810313] i2c-adapter i2c-0: ioctl, cmd=0x704, arg=0x00
<7>[ 9.810326] i2c-adapter i2c-0: ioctl, cmd=0x703, arg=0x62
<7>[ 10.267413] i2c-adapter i2c-0: ioctl, cmd=0x703, arg=0x5b
のようにでてくる。cmd の 0x703 、 0x704は
kernelヘッダの
linux/i2c-dev.h
において、
#define I2C_SLAVE 0x0703 /* Use this slave address */
#define I2C_TENBIT 0x0704 /* 0 for 7 bit addrs, != 0 for 10 bit */
のように定義されている。
また、argは、下記のようなコードを書けば出てくる。(と思う。まだ試していない^^;)
#include <linux/i2c-dev.h> //#include <linux/i2c.h>
(省略)
int fd,addr;
fd = open("/dev/i2c-0", O_RDWR);
int addr = 0x62; /* I2C address */
ioctl(fd, I2C_SLAVE, addr);
(省略)
I2C周りのDEBUG情報の見方(その2)
dmesg で DEBUG 情報を見てみると、下記のような STATUS が出てきた。(ログ出力を抑制したため現在は出ない。)
<7>[ 1.010060] i2c-adapter i2c-0: master_xfer[0] W, addr=0x1c, len=1
<7>[ 1.010073] i2c-adapter i2c-0: master_xfer[1] R, addr=0x1c, len=1
<4>[ 1.010120] STATUS (0x00006700): MST ACT
<4>[ 1.010166] STATUS (0x00006b00): MST ACT
<4>[ 1.010213] STATUS (0x00007b01): MST ACT WR_FULL
<4>[ 1.010240] STATUS (0x00006302): MST ACT RD_FULL
全く見方が分からないので、出力箇所を調べてみた。
最初の、master_xfer~の
i2c-adapter i2c-0: master_xfer[0] W, addr=0x1c, len=1
部分は、
kernel/drivers/i2c/i2c-core.c
1037行~1044行付近
#ifdef DEBUG
for (ret = 0; ret < num; ret++) {
dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, "
"len=%d%s\n", ret, (msgs[ret].flags & I2C_M_RD)
? 'R' : 'W', msgs[ret].addr, msgs[ret].len,
(msgs[ret].flags & I2C_M_RECV_LEN) ? "+" : "");
}
#endif
で出力されている。
次に、
STATUS (0x00007b01): MST ACT WR_FULL
等の部分だが、MST ACT WR_FULL は I2C 素人の私は何の事かさっぱり分からない。
出力該当部分を探したところ、
kernel/drivers/i2c/busses/i2c-msm.c
142行~167行付近
#if DEBUG
static void
dump_status(uint32_t status)
{
printk("i2c-msm: STATUS (0x%.8x): ", status);
if (status & I2C_STATUS_BUS_MASTER)
printk("MST ");
if (status & I2C_STATUS_BUS_ACTIVE)
printk("ACT ");
if (status & I2C_STATUS_INVALID_WRITE)
printk("INV_WR ");
if (status & I2C_STATUS_ARB_LOST)
printk("ARB_LST ");
if (status & I2C_STATUS_PACKET_NACKED)
printk("NAK ");
if (status & I2C_STATUS_BUS_ERROR)
printk("BUS_ERR ");
if (status & I2C_STATUS_RD_BUFFER_FULL)
printk("RD_FULL ");
if (status & I2C_STATUS_WR_BUFFER_FULL)
printk("WR_FULL ");
if (status & I2C_STATUS_FAILED)
printk("FAIL 0x%x", (status & I2C_STATUS_FAILED));
printk("\n");
}
#endif
となっていた。(上記の改変を含む)
.config の
CONFIG_LOG_BUF_SHIFT=17
を増やすと良いのだろうか?
現状では128KBのリングバッファになっているようだ。
話を戻すと、STATUSの数値とその各項目は上記の箇所で出力されていた。
具体的な定義は同一ファイル内において、下記のように定義されているようだ。
enum {
I2C_WRITE_DATA = 0x00,
I2C_CLK_CTL = 0x04,
I2C_STATUS = 0x08,
I2C_READ_DATA = 0x0c,
I2C_INTERFACE_SELECT = 0x10,
I2C_WRITE_DATA_DATA_BYTE = 0xff,
I2C_WRITE_DATA_ADDR_BYTE = 1U << 8,
I2C_WRITE_DATA_LAST_BYTE = 1U << 9,
I2C_CLK_CTL_FS_DIVIDER_VALUE = 0xff,
I2C_CLK_CTL_HS_DIVIDER_VALUE = 7U << 8,
I2C_STATUS_WR_BUFFER_FULL = 1U << 0,
I2C_STATUS_RD_BUFFER_FULL = 1U << 1,
I2C_STATUS_BUS_ERROR = 1U << 2,
I2C_STATUS_PACKET_NACKED = 1U << 3,
I2C_STATUS_ARB_LOST = 1U << 4,
I2C_STATUS_INVALID_WRITE = 1U << 5,
I2C_STATUS_FAILED = 3U << 6,
I2C_STATUS_BUS_ACTIVE = 1U << 8,
I2C_STATUS_BUS_MASTER = 1U << 9,
I2C_STATUS_ERROR_MASK = 0xfc,
I2C_INTERFACE_SELECT_INTF_SELECT = 1U << 0,
I2C_INTERFACE_SELECT_SCL = 1U << 8,
I2C_INTERFACE_SELECT_SDA = 1U << 9,
I2C_STATUS_RX_DATA_STATE = 3U << 11,
I2C_STATUS_LOW_CLK_STATE = 3U << 13,
};
ん~、DUMP出来てない値があるような気がする。。。
間違いが多く含まれているかもしれません、何かお気づきの点が有りましたら、Twitterか下記まで。
コメント
(2011/02/10 1:58 Audio関連よりI2C関連部分を分離変更)
最終更新:2011年03月07日 23:19