栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

SC20 Android 7.1 ACC(GPIO)状态检测内核修改

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SC20 Android 7.1 ACC(GPIO)状态检测内核修改

功能: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状态变化会上报状态,系统根据状态进行对应操作

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/945938.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号