2010年5月8日 星期六

從 gpio & I2C 硬體線路對應到檔案讀寫

0. 硬體電路的 schema
找到電路圖上的 gpio, i2c 線路圖上的 block 是接到 datasheet 上哪一個 slot

1. datasheet 中的 gpio chapter
針對 gpio controller 的 register 值依照 in/out, pull up/down, data 值設定

2. board initial entry point,比如 Samsung s3c6410
~linux/arch/arm/mach-s3c64xx/mach-smdk6410.c
MACHINE_START macro 定義 board information
可以看到註冊的 .init_machine 進入點 function 是 smdk6410_machine_init

Qualcomm 的 arm board initial 檔案則是在
~linux/arch/arm/mach-msm/board-msm7x27.c
定義了 QCT MSM7x2x (7225)
~linux/arch/arm/mach-msm/board-msm7x30.c
定義了 QCT MSM7x30
~linux/arch/arm/mach-msm/board-qsd8x50.c
定義了 QCT QSD8X50 (8250)

3. i2c
關於 i2c 參考 Documentation/i2c/instantiating-devices,可以看到 mach-smdk6410.c 定義兩個 i2c slot 0, 1 為 struct i2c_board_info,裡面定義這個 bus 上接的 i2c slave device(s) 名稱與 slave address 資訊,透過 S3C_EINT 對應到外部中斷 12,然後在 smdk6410_machine_init():

i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));
i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));

註冊兩個 i2c bus,0 跟 1。接下來 i2c device 的具體化由 i2c core 完成。

kernel driver 可以在 ~linux/drivers/i2c 目錄找到,可以使用 i2c-dev,直接 sudo modprobe -a i2c-dev,就可以在 /dev/i2c-0 存取 i2c bus。

參考 ~linux/Documentation/i2c/dev-interface 可以針對 /dev/i2c-0[1] 的 device file 使用 user space driver 的 ioctl 控制 i2c 設定與傳輸。

最簡單的動作是 ioctl(file, I2C_SLAVE, addr),就直接對 file read(), write() 就可以讀寫 i2c device 資料。

4. gpio
關於取得需要使用的 gpio 方式如下:

gpio_request(S3C64XX_GPN(5), "LCD power");
gpio_request(S3C64XX_GPF(13), "LCD power");
gpio_request(S3C64XX_GPF(15), "LCD power");

這是指取用 GPN pin 5 跟 GPF pin 13, pin 15 操作 LCD power

~linux/Documentation/gpio.txt 可以用 /sys/class/gpio/ 底下針對 gpiochip (controller) 或是 gpioXX (pin) 進行 user driver 的控制 in/out, high/low, trigger mode /sys/class/gpio/gpiochip0/ 中的 label 可以對應到 datasheet 的 controller 名稱,參考 arch/arm/mach-s3c64xx/include/mach/gpio.h 可以找到 S3C64XX_GPA, S3C64XX_GPB 等 gpio controller

S3C64XX_GPIO_A_NR (8) 定義 Bank A 有 8 根 gpio 腳位,依此類推對於 /sys/class/gpio/gpioXX/value read/write 就可以讀取 gpio 腳位high/low 或設定 high/low