作者
QQ群:852283276
微信:arm80x86
微信公众号:青儿创客基地
B站:主页 https://space.bilibili.com/208826118
参考
sysfs使用
pex8724 I2C驱动,首先声明函数和结构体,
/* sysfs interface */
static ssize_t
pex8724_sysfs_show_cmd(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct pex8724_data *pex8724 = i2c_get_clientdata(to_i2c_client(dev));
return sprintf(buf, "0x%08x\n", pex8724->cmd);
}
static ssize_t
pex8724_sysfs_store_cmd(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
u32 cmd = 0;
struct pex8724_data *pex8724 = i2c_get_clientdata(to_i2c_client(dev));
if (buf[0] == '0' && (buf[1] == 'x' || buf[1] == 'X')) {
if (sscanf(buf, "%x", &cmd) != 1)
return -EINVAL;
} else {
if (sscanf(buf, "%u", &cmd) != 1)
return -EINVAL;
}
pex8724->cmd = cmd;
return count;
}
static DEVICE_ATTR(cmd, S_IRUGO | S_IWUSR, pex8724_sysfs_show_cmd,
pex8724_sysfs_store_cmd);
static ssize_t
pex8724_sysfs_show_reg(struct device *dev,
struct device_attribute *attr, char *buf)
{
u32 val;
int ret;
struct i2c_client *client = to_i2c_client(dev);
struct pex8724_data *pex8724 = i2c_get_clientdata(client);
ret = pex8724_i2c_read_regs(to_i2c_client(dev), pex8724->cmd, &val);
if (ret < 0)
return ret;
return sprintf(buf, "0x%08x\n", val);
}
static ssize_t
pex8724_sysfs_store_reg(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
u32 val;
int ret;
struct i2c_client *client = to_i2c_client(dev);
struct pex8724_data *pex8724 = i2c_get_clientdata(client);
if (buf[0] == '0' && (buf[1] == 'x' || buf[1] == 'X')) {
if (sscanf(buf, "%x", &val) != 1)
return -EINVAL;
} else {
if (sscanf(buf, "%d", &val) != 1)
return -EINVAL;
}
ret = pex8724_i2c_set_regs(to_i2c_client(dev), pex8724->cmd, val);
if (ret < 0)
return -EIO;
return count;
}
static DEVICE_ATTR(reg, S_IRUGO | S_IWUSR, pex8724_sysfs_show_reg,
pex8724_sysfs_store_reg);
static struct attribute *pex8724_attrs[] = {
&dev_attr_cmd.attr,
&dev_attr_reg.attr,
NULL
};
static const struct attribute_group pex8724_sysfs_files = {
.attrs = pex8724_attrs,
};
在probe中注册,
rc = sysfs_create_group(&client->dev.kobj, &pex8724_sysfs_files);
if (rc)
return rc;
访问,读取芯片ID,
root@zynqmp:~# i2cdetect -l
i2c-1 i2c xiic-i2c I2C adapter
i2c-0 i2c Cadence I2C at ff020000 I2C adapter
root@zynqmp:~#
root@zynqmp:~#
root@zynqmp:~# i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- 38 -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
root@zynqmp:~# cat /sys/bus/i2c/devices/1-0038/cmd
0x00000000
root@zynqmp:~# echo 0x04003C00 > /sys/bus/i2c/devices/1-0038/cmd
root@zynqmp:~# cat /sys/bus/i2c/devices/1-0038/cmd
0x04003c00
root@zynqmp:~# cat /sys/bus/i2c/devices/1-0038/reg
0x872410b5
很多时候,需要批量构造sys接口,类似于数组的形式,
#define nvme_show_str_function(field) \
static ssize_t field##_show(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
struct nvme_ctrl *ctrl = dev_get_drvdata(dev); \
return sprintf(buf, "%.*s\n", (int)sizeof(ctrl->field), ctrl->field); \
} \
static DEVICE_ATTR(field, S_IRUGO, field##_show, NULL);
#define nvme_show_int_function(field) \
static ssize_t field##_show(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
struct nvme_ctrl *ctrl = dev_get_drvdata(dev); \
return sprintf(buf, "%d\n", ctrl->field); \
} \
static DEVICE_ATTR(field, S_IRUGO, field##_show, NULL);
nvme_show_str_function(model);
nvme_show_str_function(serial);
nvme_show_str_function(firmware_rev);
nvme_show_int_function(cntlid);
debugfs使用
查看gpio使用状态,
root@zynqmp_vcu:~# mkdir debugfs
root@zynqmp_vcu:~# mount -t debugfs debugfs ./debugfs/
root@zynqmp_vcu:~#
root@zynqmp_vcu:~# cd debugfs/
root@zynqmp_vcu:~/debugfs# ls
asoc clk dma_buf gpio mali pinctrl ras split_huge_pages
bdi debug_enabled dri hid memblock pm_genpd regmap suspend_stats
block device_component extfrag iio mtd pm_qos regulator wakeup_sources
clear_warn_once devices_deferred fault_around_bytes ion opp pmbus sleep_time xlnx-bridge
root@zynqmp_vcu:~/debugfs# cat gpio
gpiochip0: GPIOs 338-511, parent: platform/ff0a0000.gpio, zynqmp_gpio:
gpio-401 ( |reset ) out hi
gpio-416 ( |reset ) out hi
gpio-417 ( |reset ) out hi
gpio-418 ( |reset ) out hi
gpio-419 ( |reset ) out hi
gpio-420 ( |reset ) out hi
gpio-421 ( |reset ) out hi
gpio-422 ( |reset ) out hi
gpio-424 ( |reset ) out hi
gpio-425 ( |reset ) out hi
proc使用
从proc文件系统查看设备树节点信息,
root@t2080rdb:~# ls /proc/device-tree/
#address-cells buffer-pool@10/ buffer-pool@8/ cpus/ localbus@ffe124000/ pcie@ffe270000/ soc@ffe000000/
#size-cells buffer-pool@11/ buffer-pool@9/ dcsr@f00000000/ memory/ qman-portals@ff6000000/
aliases/ buffer-pool@12/ chosen/ fsl,dpaa/ model rapidio@ffe0c0000/
bman-portals@ff4000000/ buffer-pool@7/ compatible interrupt-parent name reserved-memory/