功能:ACC在车载是一个常用的功能,它是使用GPIO口来检测ACC的状态,根据ACC状态做对应的功能,常用功能是ACC上电开机,ACC下电息屏或者关机功能。
1.添加内核驱动
kernel/drivers/misc/gpio-acc.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define INVALID_GPIO -1
struct acc_priv {
struct input_dev *input_dev;
struct gpio_priv *pdata;
unsigned int acc_status:1;
int cur_acc_status;
unsigned int irq[2];
unsigned int irq_type[2];
struct delayed_work h_delayed_work[2];
struct switch_dev sdev;
};
static struct acc_priv *acc_info;
struct gpio_priv {
unsigned int sysclk;
struct clk *mclk;
struct snd_pcm_hw_constraint_list *sysclk_constraints;
struct iio_channel *chan;
int acc_wakeup;
int acc_det_gpio;
bool acc_det_level;
};
static struct gpio_priv *gpio_private;
static irqreturn_t acc_det_irq_handler(int irq, void *dev_id)
{
struct gpio_priv *gpio = gpio_private;
if (gpio_get_value(gpio->acc_det_gpio) == 0) {
acc_info->cur_acc_status = 1;
switch_set_state(&acc_info->sdev, acc_info->cur_acc_status);
}else {
acc_info->cur_acc_status = 0;
switch_set_state(&acc_info->sdev, acc_info->cur_acc_status);
}
printk("acc_info->cur_acc_status = %dn",acc_info->cur_acc_status);
return IRQ_HANDLED;
}
static ssize_t acc_print_name(struct switch_dev *sdev, char *buf)
{
return sprintf(buf, "accn");
}
static int rk_acc_probe(struct platform_device *pdev,struct gpio_priv *gpio)
{
int ret;
struct acc_priv *acc;
acc = kzalloc(sizeof(struct acc_priv), GFP_KERNEL);
if (acc == NULL) {
dev_err(&pdev->dev, "failed to allocate driver datan");
return -ENOMEM;
}
acc_info = acc;
acc->sdev.name = "car-acc";
acc->sdev.print_name = acc_print_name;
ret = switch_dev_register(&acc->sdev);
if (ret < 0){
goto failed_free;
}
return 0;
failed_free:
dev_err(&pdev->dev, "failed to headset proben");
kfree(acc);
return ret;
}
static int gpio_det_probe(struct platform_device *pdev)
{
struct gpio_priv *gpio;
int ret = -1;
int acc_irq = 0;
enum of_gpio_flags flags;
gpio = devm_kzalloc(&pdev->dev, sizeof(struct gpio_priv), GFP_KERNEL);
if (gpio == NULL)
return -ENOMEM;
memset(gpio,0,sizeof(struct gpio_priv));
gpio_private = gpio;
gpio->acc_det_gpio = of_get_named_gpio_flags(pdev->dev.of_node, "gpios", 0, &flags);
if (gpio->acc_det_gpio < 0) {
dev_info(&pdev->dev, "Can not read property hp_det_gpion");
gpio->acc_det_gpio = INVALID_GPIO;
} else {
gpio->acc_det_level = (flags & OF_GPIO_ACTIVE_LOW) ? 0 : 1;
ret = devm_gpio_request_one(&pdev->dev, gpio->acc_det_gpio, GPIOF_IN, NULL);
if (ret != 0) {
dev_err(&pdev->dev, "Failed to request acc_det_gpion");
return ret;
}
acc_irq = gpio_to_irq(gpio->acc_det_gpio);
enable_irq_wake(acc_irq);
if (acc_irq) {
ret = devm_request_threaded_irq(&pdev->dev, acc_irq, NULL, acc_det_irq_handler,
IRQ_TYPE_EDGE_BOTH |IRQF_ONESHOT,"GPIO", NULL);
if (ret < 0) {
dev_err(&pdev->dev, "request_irq failed: %dn", ret);
return ret;
}
}
}
ret = rk_acc_probe(pdev,gpio);
if(ret < 0)
{
goto err;
}
if (gpio_get_value(gpio->acc_det_gpio) == 0) {
acc_info->cur_acc_status = 1;
switch_set_state(&acc_info->sdev, acc_info->cur_acc_status);
}else {
acc_info->cur_acc_status = 0;
switch_set_state(&acc_info->sdev, acc_info->cur_acc_status);
}
printk("acc_info->cur_acc_status = %dn",acc_info->cur_acc_status);
return ret;
err:
kfree(gpio);
return ret;
}
static int gpio_det_remove(struct platform_device *dev)
{
return 0;
}
static void gpio_det_shutdown(struct platform_device *dev)
{
}
#if defined(CONFIG_OF)
static const struct of_device_id gpio_det_of_match[] = {
{ .compatible = "gpio-detection", },
{},
};
#endif
static struct platform_driver gpio_det_driver = {
.driver = {
.name = "gpio-detection",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(gpio_det_of_match),
},
.probe = gpio_det_probe,
.remove = gpio_det_remove,
.shutdown = gpio_det_shutdown,
};
static int __init gpio_det_init(void)
{
return platform_driver_register(&gpio_det_driver);
}
fs_initcall_sync(gpio_det_init);
static void __exit gpio_det_exit(void)
{
platform_driver_unregister(&gpio_det_driver);
}
module_exit(gpio_det_exit);
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:gpio-detection");
MODULE_AUTHOR("ROCKCHIP");
2.kernel/drivers/misc/Makefile
obj-y += gpio-acc.o
3.kernel/arch/arm/boot/dts/qcom/msm8909-mtp.dtsi
gpio_acc {
compatible = "gpio-detection";
status = "okay";
gpios = <&msm_gpio 98 0>;
};
内核编译后ACC状态变化会上报状态,系统根据状态进行对应操作



