1 i2c-tools
1.1 i2c-tools
i2cdetect
i2cdump
i2cget
i2cset

https://github.com/Hashcode/i2c-tools

i2cset -f -y I2C_BUS 7bit_i2c_addr reg val
i2cget -f -y I2C_BUS 7bit_i2c_addr reg
i2cdump -f -y I2C_BUS 7bit_i2c_addr

1.2 i2cscan
/sys/class/i2c-adapter
/sys/bus/i2c/drivers

2 i2c-gpio
#include <linux/i2c-gpio.h>
#include <linux/platform_device.h>

static struct i2c_gpio_platform_data i2c1_gpio_adapter_data = {
    .sda_pin = 10,
    .scl_pin = 11,
    .udelay = 5, /* 100KHz */
    .timeout = 100,
    .sda_is_open_drain = 1,
    .scl_is_open_drain = 1,
};

static struct platform_device i2c1_gpio = {
    .name = "i2c-gpio",
    .id = 1, /* i2c-1, 0-based index */
    .dev = {
        .platform_data = &i2c1_gpio_adapter_data,
    },
};

3 APL A39X0 Gen9 I2C
3.1 PCI BDF - I2C mapping
/sys/devices/pci0000:00/0000:00:17.3/i2c_designware.7
find /sys -name *designware*
i2cscan
pcitool -w 00:17.3=4,1,0
usleep 100000
pcitool -w 00:17.3=4,1,6

3.2 不修改ACPI添加I2C设备
使用传统的i2c_register_board_info()

How to instantiate I2C devices
https://www.kernel.org/doc/html/latest/i2c/instantiating-devices.html

3.3 I2C bus recovery infrastructure
DesignWare DW_apb_i2c Databook

SCL hang:dw i2c出问题时,控制器的SCL会被一直拉低,无法恢复,只有重启
SDA hang:外设拉低了SDA,需要GPIO模式做恢复

3.4 I2C设备hotplug
struct i2c_virtualhub {};

3.5 I2C和SMBus区别
I2C偏重速度,而SMBus偏重可靠性和成本。I2C速度从10KHz起步(理论上可以更低至0),最高5MHz;而SMBus最低10KHz,最高100KHz。也就是说在10KHz到100KHz上,两者才通用,这就排除了中速和高速设备。I2C不强制Slave对地址请求发送回应(ACK),而SMBus要求必须ACK。与此对应,SMBus对NACK的要求也严格于I2C。这是因为SMBus面向电脑中很多可拆卸设备,必须确定该设备是否存在,避免误操作。SMBus还加入了WatchDog,在SMBCLK拉低后,不得超过35ms(这就是10KHz的最低频率的由来),否则Slave应该Reset。而I2C并没有该限制。这让SMBus避免了复杂的错误恢复电路。SMBus还提供了单独的SMBSUS来用于Slave向Master报警。

3.6 不通过dt添加pinctrl_map
1)
每个GPIO bank有一个结构体struct pinctrl_desc来描述。
pctrl->soc->pins[offset].drv_data

2)不通过dt添加pinctrl_map
#include <linux/pinctrl/machine.h>
#include <linux/pinctrl/pinconf-generic.h>

static unsigned long i2c7_grp_configs[] = {
    PIN_CONFIG_BIAS_DISABLE,
    PIN_CONFIG_DRIVE_OPEN_DRAIN,
};

// pinctrl_map是映射consumer driver
// 到pinctrl driver的一个结构体
// consumer dev_name = "0000:00:17.3",
// 通过dev_name(dev)获得
// ctrl_dev_name,对应的pin controller设备名,
// cat /d/pinctrl/pinctrl-devices

static const struct pinctrl_map demo_pinctrl_map[] __initdata = {
    // 配置成I2C控制器
    PIN_MAP_MUX_GROUP("0000:00:17.3",
        PINCTRL_STATE_DEFAULT,
        "INT3452:02",
        "i2c7_grp",
        "i2c7"),
    // PIN_MAP_CONFIGS_GROUP("0000:00:17.3",
    //    PINCTRL_STATE_DEFAULT,
    //    "INT3452:02",
    //    "i2c7_grp",
    //    i2c7_grp_configs),
    // PIN_MAP_CONFIGS_PIN
};

ret = pinctrl_register_mappings(
        demo_pinctrl_map,
        ARRAY_SIZE(demo_pinctrl_map));
if (ret) {
    // TODO: error message
}

3)使用
struct pinctrl *pinctrl;
pinctrl = devm_pinctrl_get_select(
        &pdev->dev,
        PINCTRL_STATE_DEFAULT);
if (IS_ERR(pinctrl)) {
    // TODO
}

3.7 PCI I2C reset
pci_enable_device(): Command register offset, 0x04 - 0x05
enable PCI: 0x4 = 6
disable PCI: 0x4 = 0
PCI dwc i2c controller will show timeout in dmesg when PCI config space command register 0x4 = 0. Set 0x4 = 6, then call i2c_dw_init() to re-initialize dwc.

PCI PM Capability
PCI PM的Capability ID为0x01,找到这个ID开始的8个字节。
8个字节中索引4的字节bit[1:0]表示电源的状态,0表示D0,3表示D3。bit3表示是否支持soft reset,0表示支持。
8个字节中索引5的字节bit0表示PME Enable,bit7表示PME Status。
PCI PM寄存器地址的获取,参考文章Linux PCI和PCIe总线 s5.2。
pci_pm_reset(struct pci_dev *dev,
int probe)

4 file name by filp
kernel中vma->vm_pgoff等于mmap()函数最后一个参数offset >> PAGE_SHIFT
filp->f_path.dentry->d_iname

5 Abbreviations
gpiod:GPIO Descriptor Consumer Interface,还有一种是deprecated integer-based GPIO interface
I3C:Improved Inter Integrated Circuit
lm_sensors:Linux-monitoring sensors
PSoC:Programmable PSoC,PSoC中的CPLD是收购的MicroSystems

Logo

更多推荐