一、概述

mfd是Multifunction device的简称,即多功能设备,是许多有共性的设备的集合,mfd由核心层(core)以及其下的“子设备”组成。从下文将会看到,mfd只是将设备注册到platform总线——因此,其子设备属于platform设备。它并没有对涉及到的设备或驱动做实质性改变。但是,因为某些设备的共性,所以可以在mfd中提供共同的函数给其下子设备进行调用。

本文提到的hisi_fmc驱动就是如此:

下面就分析mfd设备注册过程,并结合1个实例讲解。

内核配置(make menuconfig)信息如下:

在里面可以选中自己需要的器件;

.config文件中配置CONFIG_MFD_CORE=y

二、mfd设备添加

mfd核心代码位于drivers/mfd/mfd-core.c文件中。对外提供添加设备和删除设备的接口:mfd_add_devices、mfd_remove_devices。设备添加函数原型如下:

int mfd_add_devices(struct device *parent, int id,
const struct mfd_cell *cells, int n_devs,
struct resource *mem_base,
int irq_base, struct irq_domain *domain)
  • id:即设备ID号。它指示着设备的个数。一般可以设置为-1。即表示系统有且仅有一个这样的设备。如果有多个foo设备,则需要使用id来区别。

在/sys/bus/platform/devices目录下会产生foo.0,foo.1等设备。详情可以看platform设备添加函数过程。

  • cells:即mfd_cell结构体数组,n_devs为其数组大小,即设备数量。

  • mem_base:资源resource结构体。如果没有,可置为NULL。

描述mfd设备单元称为“cell”,mfd_cell定义如下:

/*
* This struct describes the MFD part ("cell").
* After registration the copy of this structure will become the platform data
* of the resulting platform_device
*/
struct mfd_cell {
const char *name;
int id; /* 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 Tree compatible string
* See: Documentation/devicetree/usage-model.txt Chapter 2.2 for details
*/
const char *of_compatible; /*
* These resources can be specified relative to the parent device.
* For accessing hardware you should use resources from the platform dev
*/
int num_resources;
const struct resource *resources; /* don't check for resource conflicts */
bool ignore_resource_conflicts; /*
* Disable runtime PM callbacks for this subdevice - see
* pm_runtime_no_callbacks().
*/
bool pm_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;
int num_parent_supplies;
};

部分常见的成员介绍如下:

  • name:设备平台。
  • platform_data:平台私有数据指针,数据大小使用pdata_size表示。
  • resources:资源结构体,资源数量使用num_resources表示。
  • ignore_resource_conflicts:为true表示不检查资源冲突。
  • of_compatible:设备树匹配compatible的字符串(具体参考Documentation/devicetree/usage-model.txt Chapter 2.2)这个根据我的理解,是用于platform device的,只是写在了mfd设备上;

至此,mfd设备的添加就完成了,最终调用驱动的probe函数。从这个过程中知道,mfd实质上就是封装一个接口,将一些可以归纳到一起的platform设备注册到platform总线上。它就是一个收纳盒子。里面的设备该是怎样处理就怎样处理。

三、mfd实例

下面介绍hisi_fmc驱动的实例:


static int hisi_fmc_probe(struct platform_device *pdev)
{
struct hisi_fmc *fmc;
struct resource *res;
struct device *dev = &pdev->dev;
int ret; pr_err("hisi_fmc_probe successfully!\n");
fmc = devm_kzalloc(dev, sizeof(*fmc), GFP_KERNEL);
if (!fmc)
return -ENOMEM; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "control");
fmc->regbase = devm_ioremap_resource(dev, res);
if (IS_ERR(fmc->regbase))
return PTR_ERR(fmc->regbase); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "memory");
fmc->iobase = devm_ioremap_resource(dev, res);
if (IS_ERR(fmc->iobase))
return PTR_ERR(fmc->iobase); fmc->clk = devm_clk_get(dev, NULL);
if (IS_ERR(fmc->clk))
return PTR_ERR(fmc->clk); if (of_property_read_u32(dev->of_node, "max-dma-size", &fmc->dma_len)) {
dev_err(dev, "Please set the suitable max-dma-size value !!!\n");
return -ENOMEM;
} ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
if (ret) {
dev_warn(dev, "Unable to set dma mask\n");
return ret;
} fmc->buffer = dmam_alloc_coherent(dev, fmc->dma_len,
&fmc->dma_buffer, GFP_KERNEL);
if (IS_ERR(fmc->buffer))
return PTR_ERR(fmc->buffer); mutex_init(&fmc->lock); platform_set_drvdata(pdev, fmc); ret = mfd_add_devices(dev, 0, hisi_fmc_devs,
ARRAY_SIZE(hisi_fmc_devs), NULL, 0, NULL);
if (ret) {
dev_err(dev, "add mfd devices failed: %d\n", ret);
return ret;
} return 0;
}
  1. 读取fmc的reg_base、io_base;
  2. 获取最大的max-dma-size
  3. 添加mfd设备
ret = mfd_add_devices(dev, 0, hisi_fmc_devs,
ARRAY_SIZE(hisi_fmc_devs), NULL, 0, NULL);

多功能设备mfd驱动的更多相关文章

  1. i2c总线,设备,驱动之间的关系

    ------ 总线上先添加好所有具体驱动,i2c.c遍历i2c_boardinfo链表,依次建立i2c_client, 并对每一个i2c_client与所有这个线上的驱动匹配,匹配上,就调用这个驱动的 ...

  2. linux设备驱动归纳总结(九):1.platform总线的设备和驱动【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-111745.html linux设备驱动归纳总结(九):1.platform总线的设备和驱动 xxxx ...

  3. linux设备驱动归纳总结(八):1.总线、设备和驱动【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-109733.html linux设备驱动归纳总结(八):1.总线.设备和驱动 xxxxxxxxxxxx ...

  4. Linux下实现流水灯等功能的LED驱动代码及测试实例

    驱动代码: #include <linux/errno.h> #include <linux/kernel.h> #include <linux/module.h> ...

  5. platform总线,设备,驱动的注册

    linux设备驱动归纳总结(九):1.platform总线的设备和驱动 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...

  6. SPI设备的驱动

    主要包括两个SPI设备步骤:register_chrdevspi_register_driver关键点1:spi_board_info可以去已经运行的板子下面找例子:/sys/bus/spi/driv ...

  7. I2C总线、设备、驱动

    I2C总线.设备.驱动 框架 I2C驱动框架可分为3个部分,分别是:I2C核心层.I2C总线驱动层(适配器层)以及I2C设备驱动层: I2C核心层 提供了统一的I2C操作函数,主要有两套函数smbus ...

  8. 【Linux开发】linux设备驱动归纳总结(九):1.platform总线的设备和驱动

    linux设备驱动归纳总结(九):1.platform总线的设备和驱动 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...

  9. 【Linux开发】linux设备驱动归纳总结(八):1.总线、设备和驱动

    linux设备驱动归纳总结(八):1.总线.设备和驱动 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...

随机推荐

  1. Java 标准 I/O 介绍

    一.Java标准I/O知识体系图: 二.I/O是什么 I/O 是Input/Output(输入.输出)的简称,输入流可以理解为向内存输入,输出流是从内存输出. 三.Java I/O 用途与对应的流一览 ...

  2. PAT1116: Come on! Let's C

    1116. Come on! Let's C (20) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue &quo ...

  3. ARP攻击之Kali Linux局域网断网攻击

    特别声明: 我们学习研究网络安全技术的目的应是为了维护网络世界的安全,保护自己和他人的私有信息不被非法窃取和传播.请您遵守您所在地的法律,请勿利用本文所介绍的相关技术做背离道德或者违反法律的事情. S ...

  4. Spring Batch 专题

    如今微服务架构讨论的如火如荼.但在企业架构里除了大量的OLTP交易外,还存在海量的批处理交易.在诸如银行的金融机构中,每天有3-4万笔的批处理作业需要处理.针对OLTP,业界有大量的开源框架.优秀的架 ...

  5. mysql可视化工具下载地址2017.6.27

    https://www.baidu.com/s?tn=90117497_hao_pg&usm=1&wd=navicat+for+mysql&ie=utf-8&rsv_r ...

  6. 从零开始学Web之HTML(二)标签、超链接、特殊符号、列表、音乐、滚动、head等

    大家好,这里是 Daotin 从零开始学 Web 系列教程.此文首发于「 Daotin的梦呓 」,欢迎大家订阅关注.在这里我会从 Web 前端零基础开始,一步步学习 Web 相关的知识点,期间也会分享 ...

  7. Java 中的纤程库 – Quasar

    来源:鸟窝, colobu.com/2016/07/14/Java-Fiber-Quasar/ 如有好文章投稿,请点击 → 这里了解详情 最近遇到的一个问题大概是微服务架构中经常会遇到的一个问题: 服 ...

  8. 聊聊Socket、TCP/IP、HTTP、FTP及网络编程

    1 这些都是什么 既然是网络传输,涉及几个系统之间的交互,那么首先要考虑的是如何准确的定位到网络上的一台或几台主机,另一个是如何进行可靠高效的数据传输.这里就要使用到TCP/IP协议. 1.1 TCP ...

  9. matplotlib解决中文乱码

    调试以前写的matplotlib相关脚本,中文呈方块样:重新解决一遍,感觉比以前的理解更进一步,故而记下一笔: 1. 首先要为matplotlib添加中文字体库: 系统字体库在/usr/share/f ...

  10. UWP中实现大爆炸效果(一)

    自从老罗搞出大爆炸之后,各家安卓都内置了类似功能.UWP怎么能落下呢,在这里我们就一起撸一个简单的大爆炸实现. 闲话不说,先上效果: 因为代码太多,所以我打算写成一个系列,下面是第一篇的正文: 首先, ...