Linux驱动——mmc card热插拔检测机制(十)

Linux驱动——mmc card热插拔检测机制(十)

备注:
  1. Kernel版本:5.4
  2. 使用工具:Source Insight 4.0
  3. 参考博客:
[sd card] mmc硬件总线扫描流程(以sd card为例)

前言

  扫描mmc硬件总线,也就是检测mmc硬件总线上是否有挂载card。更加通俗的,就是卡槽上是否有插入card。
  检测机制有如下两种:

  • 中断检测
  • 轮询检测

卡检测时机

  mmc core在如下情况下会去扫描mmc硬件总线:

    1. 启动host时,调用_mmc_detect_change,唤醒host->detect;
    1. cd-gpio中断检测到card状态发送变化,调用mmc_detect_change,唤醒host->detect;
    1. host要求轮询sd card插入状态的情况下,所进行的轮询操作;

启动host时,检测

  当启动一个host的时候,并不知道当前是否有card插入,此时需要调用mmc_detect_change来假设card插入状态发生了变化,并且进行第一次扫描mmc硬件总线。

mmc_add_host——>mmc_start_host——>_mmc_detect_change

核心代码如下:

void mmc_start_host(struct mmc_host *host)
{
    ......
	//申请 cd_gpio
	mmc_gpiod_request_cd_irq(host);

	/* 到这里host已经可以工作了,可以开始进行后续的card操作了 */
	_mmc_detect_change(host, 0, false); // 调用mmc_detect_change检测card变化
}

中断检测

  底层硬件发现card插入状态发生变化而调用mmc_detect_change的时候(sd card插入状态监控)。
  当底层硬件发现card插入状态发生变化,例如sd card的插入或者拔出可以触发某个GPIO产生中断。
  此时,可以在中断处理中调用mmc_detect_change来进行扫描mmc硬件总线,并且根据总线上的card状态变化进行处理。
这种情况的主要目的是为了实现sd card的热插拔。

static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id)
{
	/* Schedule a card detection after a debounce timeout */
	struct mmc_host *host = dev_id;
	struct mmc_gpio *ctx = host->slot.handler_priv;

	host->trigger_card_event = true;
    
    // 调用mmc_detect_change对card的插入状态变化进行处理 
    // 注意,这里ctx->cd_debounce_delay_ms=200,延时了200ms是用来进行消抖
	mmc_detect_change(host, msecs_to_jiffies(ctx->cd_debounce_delay_ms));

	return IRQ_HANDLED;
}

轮询检测

  host要求轮询sd card插入状态的情况下,所进行的轮询操作(sd card插入状态监控)。

  一般来说,在host无法根据硬件来及时获取card插入状态发生变化的情况下,会要求mmc_core每隔一段时间(一般是HZ,一秒)扫描一次mmc硬件总线。

  在这种情况下,mmc_host的MMC_CAP_NEEDS_POLL属性会被设置。
  这种情况的主要目的也是为了实现sd card的热插拔。

void mmc_rescan(struct work_struct *work)
{
	struct mmc_host *host =
		container_of(work, struct mmc_host, detect.work);
	int i;
    
    ......
    
 out:
	// 当host设置了MMC_CAP_NEEDS_POLL属性时,需要每隔HZ的时间轮询检测host的卡槽状态,
	// 调度了host->detect工作,对应就是mmc_rescan
        // INIT_DELAYED_WORK(&host->detect, mmc_rescan) 
       // 这样,通过mmc_schedule_delayed_work(&host->detect, HZ)就会每隔HZ时间就会执行一次mmc_rescan
	if (host->caps & MMC_CAP_NEEDS_POLL)
		mmc_schedule_delayed_work(&host->detect, HZ);
}

如何扫描mmc硬件总线

从上述,我们知道了可以通过调用mmc_detect_change和执行host->detect工作来发起mmc硬件总线的扫描。而mmc_detect_change最终也是执行mmc_host->detect工作来发起mmc硬件总线扫描的。

detect task的创建

struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
{
    ......
	// 初始化detect工作为mmc_rescan,
	// 后续调度host->detect来检测是否有card插入时,
	// 就会调用到mmc_rescan
	INIT_DELAYED_WORK(&host->detect, mmc_rescan);
    ......
 }   

detect task的唤醒

mmc_detect_change:

void mmc_detect_change(struct mmc_host *host, unsigned long delay)
{
	_mmc_detect_change(host, delay, true);
}
EXPORT_SYMBOL(mmc_detect_change);

_mmc_detect_change:

void _mmc_detect_change(struct mmc_host *host, unsigned long delay, bool cd_irq)
{
	/*
	 * If the device is configured as wakeup, we prevent a new sleep for
	 * 5 s to give provision for user space to consume the event.
	 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值