linux 驱动 include .h 路径 control,linux内核中的MFD子系统

分析用的内核版本为5.1.3

1.MFD全称

Multi-function Device,多功能设备

2. 为何会出现MFD子系统

由于出现了一类具有多种功能的外围设备或cpu内部集成的硬件模块

3. 有哪些多功能设备呢?

3.1 PMIC,电源管理芯片

da9063: 调节器,led控制器,看门狗,实时时钟控制器,温度传感器,震动马达驱动,长按关机功能(ON key)

max77843: 调节器,充电器,燃油量表,触觉反馈,led控制器,micro USB接口控制器

wm831x: 调节器,时钟,实时时钟控制器,看门狗,触摸控制器,温度传感器,背光控制器,状态led控制器,GPIO,长按关机功能(ON key),ADC

其它: 甚至具有codec功能

3.2 atmel-hlcdc: 显示控制器和背光pwm

3.3 Diolan DLN2: USB转I2C,SPI和GPIO控制器

3.4 Realtek PCI-E读卡器: SD/MMC和记忆棒读取器

4. MFD子系统解决的主要问题

在不同的内核子系统中注册这些驱动。特别是外部外围设备仅仅由一个结构体struct device(或是指定的i2c_client或spi_device)呈现

5. MFD子系统的优点有哪些?

5.1 允许在多个子系统中注册相同的设备

5.2 MFD驱动必须能否复用总线(主要是关于锁的处理)和处理中断请求

5.3 处理时钟

5.4 需要配置IP

5.5 允许驱动重用,多个多功能设备能重用其它子系统中的驱动

6. MFD提供的API

intmfd_add_devices(structdevice*parent,intid,const structmfd_cell*cells,intn_devs,structresource*mem_base,intirq_base,structirq_domain*irq_domain);

extern void mfd_remove_devices(struct device *parent);

这些接口定义在include/linux/mfd/core.h中,在drivers/mfd/mtd-core.c中被实现

7. MFD提供的结构体

structmfd_cell {const char *name;intid;/*refcounting for multiple drivers to use a single cell*/atomic_t*usage_count;int (*enable)(struct platform_device *dev);int (*disable)(struct platform_device *dev);int (*suspend)(struct platform_device *dev);int (*resume)(struct platform_device *dev);/*platform data passed to the sub devices drivers*/

void *platform_data;

size_t pdata_size;/*device properties passed to the sub devices drivers*/

struct property_entry *properties;/** Device Tree compatible string

* See: Documentation/devicetree/usage-model.txt Chapter 2.2 for details*/

const char *of_compatible;/*Matches ACPI*/

const struct mfd_cell_acpi_match *acpi_match;/** These resources can be specified relative to the parent device.

* For accessing hardware you should use resources from the platform dev*/

intnum_resources;const struct resource *resources;/*don't check for resource conflicts*/

boolignore_resource_conflicts;/** Disable runtime PM callbacks for this subdevice - see

* pm_runtime_no_callbacks().*/

boolpm_runtime_no_callbacks;/*A list of regulator supplies that should be mapped to the MFD

* device rather than the child device when requested*/

const char * const *parent_supplies;intnum_parent_supplies;

};

8. 示例分析

8.1 分析tps6507x的多功能驱动

8.1.1 涉及的文件

drivers/mfd/tps6507x.c

include/linux/mfd/tps6507x.h

drivers/regulator/tps6507x-regulator.c

drivers/input/touchscreen/tps6507x-ts.c

8.1.2 涉及的结构体

static const struct mfd_cell tps6507x_devs[] ={

{

.name= "tps6507x-pmic",

},

{

.name= "tps6507x-ts",

},

};

从以上结构体可以得出,tps6507x系列芯片提供两种功能: 电源管理功能(regulator)+触摸屏功能(touchscreen)

static struct i2c_driver tps6507x_i2c_driver ={

.driver={

.name= "tps6507x",

.of_match_table=of_match_ptr(tps6507x_of_match),

},

.probe=tps6507x_i2c_probe,

.id_table=tps6507x_i2c_id,

};

这个结构体为tps6507x提供探测函数tps6507x_i2c_probe

structtps6507x_dev {struct device *dev;struct i2c_client *i2c_client;int (*read_dev)(struct tps6507x_dev *tps6507x, char reg, intsize,void *dest);int (*write_dev)(struct tps6507x_dev *tps6507x, char reg, intsize,void *src);/*Client devices*/

struct tps6507x_pmic *pmic;

};

tps6507x 的读写接口就是放在这个结构体中,这也就是所谓的共性

8.1.3 对tps6507x进行初始化

subsys_initcall(tps6507x_i2c_init);

调用路径如下:

tps6507x_i2c_init->i2c_add_driver

8.1.4 探测函数tps6507x_i2c_probe做了些什么?

注册tps6507x的读写函数: tps6507x_i2c_read_device和tps6507x_i2c_write_device到结构体struct tps6507x_dev中

8.1.5 tps6507x的两种功能实现在哪里呢?

drivers/regulator/tps6507x-regulator.c,这里面实现电源管理功能(电压调节器驱动)

drivers/input/touchscreen/tps6507x-ts.c,这里面实现触摸屏功能

8.1.6 tps6507x电压调节器驱动

8.1.6.1 调用路径

subsys_initcall(tps6507x_pmic_init);

tps6507x_pmic_init->platform_driver_register

8.1.6.2 探测函数tps6507x_pmic_probe干了些什么?

获取共用的结构体struct tps6507x_dev

再注册相关的结构体以便提供pmic的相关操作接口,如下:

static struct regulator_ops tps6507x_pmic_ops ={

.is_enabled=tps6507x_pmic_is_enabled, 检查tps6507x的pmic功能是否已经使能了

.enable=tps6507x_pmic_enable, 使能tps6507x的pmic功能

.disable=tps6507x_pmic_disable, 禁用tsp6507x的pmic功能

.get_voltage_sel=tps6507x_pmic_get_voltage_sel, 获取电压值

.set_voltage_sel=tps6507x_pmic_set_voltage_sel, 设置电压值

.list_voltage=regulator_list_voltage_table, 列出电压表

.map_voltage=regulator_map_voltage_ascend,

};

8.1.7 tps6507x触摸屏驱动

8.1.7.1 驱动在哪里?

drivers/input/touchscreen/tps6507x-ts.c

8.1.7.2 分析probe函数都做了些什么?

获取公用的结构体struct tps6507x_dev

填充结构体struct tps6507x_ts,关键是注册了函数tps6507x_ts_poll

8.2 分析da9063相关驱动

8.2.1 mfd驱动

8.2.1.1 相关源码

drivers/mfd/da9063-i2c.c

8.2.1.2 分析探测函数da9063_i2c_probe的调用路径

da9063_i2c_probe->da9063_device_init

8.2.1.3 da9063_device_init做了些什么?

读取da9063的芯片ID,检查是否匹配

读取da9063的variant ID,不同的variant ID表示不同的封装

通过接口devm_mfd_add_devices添加具体的结构体struct mfd_cell数组,这个数组里包含了多个驱动相关的信息,如名字,资源等

8.2.1.4 结构体数组da906_common_devs

static const struct mfd_cell da9063_common_devs[] ={

{

.name=DA9063_DRVNAME_REGULATORS,

.num_resources=ARRAY_SIZE(da9063_regulators_resources),

.resources=da9063_regulators_resources,

},

{

.name=DA9063_DRVNAME_LEDS,

},

{

.name=DA9063_DRVNAME_WATCHDOG,

.of_compatible= "dlg,da9063-watchdog",

},

{

.name=DA9063_DRVNAME_HWMON,

.num_resources=ARRAY_SIZE(da9063_hwmon_resources),

.resources=da9063_hwmon_resources,

},

{

.name=DA9063_DRVNAME_ONKEY,

.num_resources=ARRAY_SIZE(da9063_onkey_resources),

.resources=da9063_onkey_resources,

.of_compatible= "dlg,da9063-onkey",

},

{

.name=DA9063_DRVNAME_VIBRATION,

},

};

这个结构体数组中就包含了调节器,led控制器,看门狗,硬件监测(电压监测,温度监测),长按关键功能(onkey),震动等驱动名称,也就是da9063会关联(具有)这些功能,da9063有两种硬件版本,一种为DA9063,另一种为DA9063L,这两种硬件的差异在于DA9063具有实时时钟功能,而后者没有此功能

8.2.1.5 结构体数组da9063_devs

/*Only present on DA9063 , not on DA9063L*/

static const struct mfd_cell da9063_devs[] ={

{

.name=DA9063_DRVNAME_RTC,

.num_resources=ARRAY_SIZE(da9063_rtc_resources),

.resources=da9063_rtc_resources,

.of_compatible= "dlg,da9063-rtc",

},

};

8.2.1.6 da9063_common_devs和da9063_devs中的这些具体的驱动实现在哪里?

drivers/regulator/da9063-regulator.c (调节器驱动)

(没有找到da9063的led控制器驱动)

drivers/watchdog/da9063_wdt.c (看门狗驱动)

(没有找到da9063的硬件监测驱动)

drivers/input/misc/da9063_onkey.c (onkey驱动)

(没有找到da9063的震动功能驱动)

drivers/rtc/rtc-da9063.c (实时时钟驱动)

8.2.1.7 重要的结构体struct da9063

structda9063 {/*Device*/

struct device *dev;enumda9063_type type;

unsignedcharvariant_code;

unsignedintflags;/*Control interface*/

struct regmap *regmap;/*Interrupts*/

intchip_irq;

unsignedintirq_base;struct regmap_irq_chip_data *regmap_irq;

};

参考资料:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值