AC充电适配器插入检测(GPIO中断)

原文网址(转载请注明出处):

链接:http://t.csdnimg.cn/fka6z

源码基于:Android Q

1.介绍

设备使用的是7.4V 的电池,但是展锐调好的电池曲线没有7.4V 的,所以需要我们自己调试,大概流程就是自己写一个电池百分比与电池电压的数组,通过读取电池电压来匹配我们的电池百分比。

但是在调试过程中发现,当插入适配器瞬间,电压会突然增大很多,所以需要将这突然增加的电压减掉,否则会导致电池百分比突然增大然后再降低的现象,所以有如下两种方式:

检测适配器插入后减去相应的电压
每次检测电压时,与上一次的电压作比较,如果差别过大则表示我们插入了适配器,再减去相应的电压值即可

2.原理

通过看硬件原理图,可以发现当我们插入适配器时,GPIO90 口会被拉低,所以如果要检测适配器是否插入,可以监测GPIO90 口的中断信息。
在这里插入图片描述

3.中断实现

3.1.配置PINMAP

由于GPIO90 口没有外部上,所以需要在内部配置GPIO90 口默认为上拉状态

bsp/bootloader/u-boot15/board/spreadtrum/sl8541e_1h10wifi5g_32b/pinmap-sl8541e.c

-{REG_PIN_SPI0_CSN,                      BITS_PIN_AF(0)},
-{REG_MISC_PIN_SPI0_CSN,                 BITS_PIN_DS(1)|BIT_PIN_NULL|BIT_PIN_NUL|BIT_PIN_SLP_AP|BIT_PIN_SLP_NUL|BIT_PIN_SLP_OE},//FTID_SPI_CSSPI?FingerPrintID
+{REG_PIN_SPI0_CSN,                      BITS_PIN_AF(3)},
+{REG_MISC_PIN_SPI0_CSN,                 BITS_PIN_DS(1)|BIT_PIN_NULL|BIT_PIN_WPU|BIT_PIN_SLP_AP|BIT_PIN_SLP_WPU|BIT_PIN_SLP_IE},//FTID_SPI_CSSPI?FingerPrintID

3.2.配置GPIO90口

sl8541e-1h10wifi5g_32b-overlay.dts
&pmic_fgu {
	monitored-battery = <&bat>;
	sprd,calib-resistance-real = <10000>;
	sprd,calib-resistance-spec = <20000>;
	io-channels =  <&pmic_adc 0>, <&pmic_adc 3>, <&pmic_adc 14>, <&pmic_adc 4>;
	io-channel-names = "adc-batt-id", "bat-temp", "charge-vol", "chg-temp";
+   power-gpio = <&ap_gpio 90 GPIO_ACTIVE_LOW>;
};

3.3.将GPIO90 口配置为上拉和下拉中断

bsp/kernel/kernel4.14/drivers/power/supply/sc27xx_fuel_gauge.c

struct sc27xx_fgu_data {
	...
	struct gpio_desc *gpiod;
+	struct gpio_desc *gpiop; // 在结构体中添加gpiop, 用来保存gpio90 口
	struct iio_channel *channel;
	...
}
// gpio90口的中断方法,当发生中断的时候会调用到这个方法
+static irqreturn_t sc27xx_fgu_power_detection(int irq, void *dev_id)
+{
+       struct sc27xx_fgu_data *data = dev_id;
+       int state;
+       mutex_lock(&data->lock);
+       state = gpiod_get_value_cansleep(data->gpiop); // 读取gpio90 口的值,用来判断是上拉发生的中断还是下拉发生的中断
+       if (state < 0) {
+               dev_err(data->dev, "failed to get gpio state\n");
+               mutex_unlock(&data->lock);
+               return IRQ_RETVAL(state);
+       }
+       SPRD_FGU_DEBUG("%s xlf irq_power 2 state = %d \n", __func__, state);
+       dev_err(data->dev, "xlf get gpio state = %d \n", state);
+
+       mutex_unlock(&data->lock);
+       return IRQ_HANDLED;
+}

static int sc27xx_fgu_probe(struct platform_device *pdev)
{
	...
	const struct sc27xx_fgu_variant_data *pdata;
-   int ret, irq;
+	int ret, irq, irq_power;
	struct device_node *battery_np = NULL;
	...
	data->chg_temp_cha = devm_iio_channel_get(&pdev->dev, "chg-temp");
	if (IS_ERR(data->chg_temp_cha)) {
		dev_err(&pdev->dev, "failed to get IIO channel chg-temp\n");
		return PTR_ERR(data->chg_temp_cha);
	}

+	// 获取在dtsi中配置的power-gpio 参数
+	data->gpiop = devm_gpiod_get(&pdev->dev, "power", GPIOD_IN);
+	if (IS_ERR(data->gpiop)) {
+		dev_err(&pdev->dev, "failed to get power detection GPIO\n");
+		return PTR_ERR(data->gpiop);
+	}

	data->gpiod = devm_gpiod_get(&pdev->dev, "bat-detect", GPIOD_IN);
	...

	if (ret) {
		dev_err(data->dev, "failed to request fgu IRQ\n");
		return ret;
	}

+	// 将gpio90 口配置为中断模式
+	irq_power = gpiod_to_irq(data->gpiop);
+	if (irq_power < 0) {
+		dev_err(&pdev->dev, "failed to translate GPIO to IRQ\n");
+		return irq_power;
+	}
+
+	// 设置gpio 的中断方式(上拉和下拉时发生中断),配置中断时调用的方法(sc27xx_fgu_power_detection)
+	ret = devm_request_threaded_irq(&pdev->dev, irq_power, NULL,
+					sc27xx_fgu_power_detection,
+					IRQF_ONESHOT | IRQF_TRIGGER_RISING |
+					IRQF_TRIGGER_FALLING,
+					"power-gpio", data);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to request IRQ\n");
+		return ret;
+	}

	irq = gpiod_to_irq(data->gpiod);
	...
}

4.测试

连上串口,通过串口输出log。
插入电源适配器。
拔出电源适配器。
查看串口log是否有“state =” 相关的log。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lion_heart001

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值