项目场景:MTK6833平台按键上报
提示:只记录学习笔记,仅供参考
一、问题描述
问题:在调试的过程中发现MTK的上电log很容易被冲掉,所以加了delay_work做调试
延时代码:
#include <linux/workqueue.h>
static struct workqueue_struct *test_wq;
static struct delayed_work test_work;
static void test_power_delay_work_func(struct work_struct *work)
{
// 延迟执行的代码逻辑
printk(KERN_INFO "YSJDelayed work start\n");
}
//在需要延时的函数中添加
test_wq = alloc_ordered_workqueue("%s",
WQ_MEM_RECLAIM |
WQ_FREEZABLE,
"test-wq");
INIT_DELAYED_WORK(&test_work, test_power_delay_work_func);
queue_delayed_work(test_wq, &test_work,
msecs_to_jiffies(10000));
原因分析:
延时进入函数时间,可以打印需要的调试信息排查问题
例如:用dmesg | grep xx,来查看printk打印信息,同时要打开debug学会使用dev打印。
二、键值上报和中断函数:
配置好dts和dws之后,在驱动函数解析引脚的中断和中断函数的键值上报,下面是驱动文件:
#include <linux/of.h>
#include <linux/input.h>
#include <linux/slab.h>
#include <linux/interrupt.h> //for DECLARE_TASKLET compile
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h> //add by zhuguanglei
#include <linux/platform_device.h>
#include <linux/yft_include/yft_project_all_config.h>
#include <linux/delay.h>
#ifdef __YFT_CUSTOMKEY_F3_SUPPORT__
#if __YFT_CUSTOMKEY_F3_SUPPORT__
#if 0 //def __YFT_CUSTOMKEY_CHANGE__
#undef KEY_F3
#define KEY_F3 KEY_HIRAGANA
#endif
#define CUSTOMKEY_F3_GPIO_NAME "customkey_f3_gpio"
#define CUSTOMKEY_F3_NUM KEY_F3
static int yft_customkey_f3_irqnum;
static struct class *custom_key3_class;
static unsigned int yft_customkey_f3_gpio_num;
static unsigned int handle_3v3_gpio_num;
static unsigned int handle_1v8_gpio_num;
//static unsigned int yft_customkey_state_pin;
//static struct pinctrl *yft_customkey_pinctrl1;
//static struct pinctrl_state *yft_customkey_pins_eint_int;
//static struct pinctrl_state *pins_default;
static void kpd_customkey_f3_handler(unsigned long data);
static DECLARE_TASKLET(kpd_customkey_f3_tasklet,kpd_customkey_f3_handler,0);
extern void customkey_handler(bool pressed, int key_value); //In kpd.c achieve add by zhuguanglei
//extern int yft_parse_dts(struct device_node *node, const char *gpio_name, bool gpio_mode);
#if 0
static unsigned int yft_parse_dts1(struct device_node *node, const char *gpio_name, bool gpio_mode)
{
unsigned int gpio_num = 0;
// struct gpio_desc *desc;
// int ret = 0;
if (node)
{
if (of_property_read_u32_index(node, gpio_name, 1, &gpio_num)) {
pr_err("f3 read_irq_registration fail~~~\n");
}
// gpio_num = of_get_named_gpio(node, gpio_name, 0);
if (gpio_num < 0)
{
printk("%s: f3 of_get_named_gpio fail. \n", __func__);
return -1;
}
else //获取GPIO成功
{
printk("%s: f3 of_get_named_gpio GPIO is %d.\n", __func__, gpio_num);
}
}
else
{
printk("%s: f3 get gpio num fail. \n", __func__);
}
return gpio_num;
}
#endif
static int yft_parse_dts(struct device_node *node, const char *gpio_name, bool gpio_mode)
{
int gpio_num = 0;
struct gpio_desc *desc;
int ret = 0;
unsigned int debounce11;
if (node)
{
gpio_num = of_get_named_gpio(node, gpio_name, 0);
if (gpio_num < 0)
{
printk("%s: of_get_named_gpio fail. \n", __func__);
return -1;
}
else //获取GPIO成功
{
printk("%s: of_get_named_gpio GPIO is %d.\n", __func__, gpio_num);
desc = gpio_to_desc(gpio_num);
if (!desc)
{
printk("%s: gpio_desc is null.\n", __func__);
return -1;
}
else //获取描述成功
printk("%s: gpio_desc is not null.\n", __func__);
if (gpio_is_valid(gpio_num))
printk("%s: gpio number %d is valid. \n", __func__ ,gpio_num);
ret = gpio_request(gpio_num, gpio_name);
if (ret)
{
printk("%s: gpio_request fail. \n", __func__);
return -1;
}
else //gpio_request 成功
{
if (!gpio_mode) //中断模式
{
ret = gpio_direction_input(gpio_num);
if (ret)
{
printk("%s: gpio_direction_input fail. \n", __func__);
return -1;
}
of_property_read_u32_index(node, "debounce", 1, &debounce11);
gpio_set_debounce(gpio_num,debounce11*1000);
printk("zcy add for gpio_num = (%d) debug debounce = (%d)\n",gpio_num,debounce11);
}
else //GPIO 模式
{
ret = gpio_direction_output(gpio_num, 0);
if (ret)
{
printk("%s: gpio_direction_output failed. \n", __func__);
return -1;
}
gpio_set_value(gpio_num, 0);
printk("%s: gpio_get_value =%d. \n", __func__, gpio_get_value(gpio_num));
}
return gpio_num; //返回GPIO num
}
}
}
else
{
printk("%s: get gpio num fail. \n", __func__);
return -1;
}
}
static void kpd_customkey_f3_handler(unsigned long data)
{
bool pressed;
int customkey_f3_state = 0;
printk("%s: f3 enter. \n", __func__);
customkey_f3_state = gpio_get_value(yft_customkey_f3_gpio_num);//__gpio_get_value(yft_customkey_f3_gpio_num);
if(customkey_f3_state < 0)
return;
printk("%s: f3_num = (%d) customkey_f3_state = (%d) gpio_get_value end. \n", __func__,yft_customkey_f3_gpio_num,customkey_f3_state);
pressed = !customkey_f3_state;
customkey_handler(pressed, CUSTOMKEY_F3_NUM);
printk("%s: %s HW keycode(%u) using EINT =%d.\n", __func__, pressed ? "pressed" : "released", CUSTOMKEY_F3_NUM, customkey_f3_state);
if (pressed)
{
printk("%s: key %s. \n", __func__, pressed ? "pressed" : "released");
irq_set_irq_type(yft_customkey_f3_irqnum, IRQF_TRIGGER_RISING);
}
else
{
printk("%s: key %s. \n", __func__, pressed ? "pressed" : "released");
irq_set_irq_type(yft_customkey_f3_irqnum, IRQF_TRIGGER_FALLING);
}
enable_irq(yft_customkey_f3_irqnum);
}
static irqreturn_t yft_customkey_f3_isr(int irqnum, void *data)
{
printk("%s: enter.\n", __func__);
disable_irq_nosync(yft_customkey_f3_irqnum);
tasklet_schedule(&kpd_customkey_f3_tasklet);
return IRQ_HANDLED;
}
static ssize_t key3_ctrl_show(struct class *class, struct class_attribute *attr, char *buf)
{
int handle_1v8_state = 0;
int handle_3v3_state = 0;
handle_1v8_state = gpio_get_value(handle_1v8_gpio_num);
handle_3v3_state = gpio_get_value(handle_3v3_gpio_num);
printk("%s: handle_1v8_state=%d; handle_3v3_state=%d. \n", __func__, handle_1v8_state, handle_3v3_state);
return sprintf(buf, "pin27=%d; pin28=%d\n",handle_3v3_state, handle_1v8_state);
}
static ssize_t key3_ctrl_store(struct class *class, struct class_attribute *attr, const char *buf, size_t count)
{
if ((buf[0] == '1') )
{
printk("echo on\n",__func__);
gpio_direction_output(handle_1v8_gpio_num, 1);
gpio_direction_output(handle_3v3_gpio_num, 1);
}
else if ((buf[0] == '0') )
{
printk("echo off\n",__func__);
gpio_direction_output(handle_3v3_gpio_num, 0);
gpio_direction_output(handle_1v8_gpio_num, 0);
}else{
printk("echo fail\n",__func__);
}
return count;
}
static struct class_attribute class_attr_custom_key3[] = {
__ATTR(key3_ctrl, 0664, key3_ctrl_show, key3_ctrl_store),
__ATTR_NULL
};
/*
初始化, 获取dts中相关的配置信息
pdev 由 yft_intercom_plat_probe 传进来
*/
int yft_customkey_f3_init(struct platform_device *pdev)
{
int retval;
int i = 0;
//int err = -EIO;
struct device_node *node;
printk("+++++++++++ %s: begin +++++++++++\n",__func__);
/*get the node*/
node = of_find_compatible_node(NULL, NULL, "mediatek,yft_customkey3");
if (node) {
printk("%s: node = (%d) not null.\n", __func__,node);
yft_customkey_f3_irqnum = irq_of_parse_and_map(node, 0);
printk("%s: f3 yft_customkey_f3_irqnum = %d\n", __func__, yft_customkey_f3_irqnum);
}
else {
printk("%s: f3 cannot get the node: 'mediatek,yft_customkey'.\n", __func__);
return -ENODEV;
}
handle_1v8_gpio_num = yft_parse_dts(node, "handle_1v8_gpio", true);
if(handle_1v8_gpio_num < 0){
printk("%s: yft_parse_dts get gpio fail.\n", __func__);
return -ENODEV;
} else {
printk("handle_1v8_gpio = %d. \n", handle_1v8_gpio_num);
}
handle_3v3_gpio_num = yft_parse_dts(node, "handle_3v3_gpio", true);
if(handle_3v3_gpio_num < 0) {
printk("%s: yft_parse_dts get gpio fail.\n", __func__);
return -ENODEV;
} else {
printk("handle_3v3_gpio = %d. \n", handle_3v3_gpio_num);
}
//call key_parse_dts_and_get_pin_status to get gpio num
yft_customkey_f3_gpio_num = yft_parse_dts(node, CUSTOMKEY_F3_GPIO_NAME, false);
if(yft_customkey_f3_gpio_num < 0)
{ //获取GPIO num 失败
printk("%s: yft_parse_dts get gpio fail.\n", __func__);
return -ENODEV;
}
else
{ //打印出GPIO num的值
printk("%s = %d. \n",CUSTOMKEY_F3_GPIO_NAME, yft_customkey_f3_gpio_num);
}
/*irq register*/
retval = request_irq(yft_customkey_f3_irqnum, yft_customkey_f3_isr, IRQF_TRIGGER_FALLING, "customkeyf3", NULL);
if (retval != 0) {
printk("%s: request_irq fail, ret %d, irqnum %d.\n", __func__, retval, yft_customkey_f3_irqnum);
return retval;
}
enable_irq(yft_customkey_f3_irqnum);
enable_irq_wake(yft_customkey_f3_irqnum);
custom_key3_class = class_create(THIS_MODULE, "custom_key3");
if (IS_ERR(custom_key3_class)) {
retval = PTR_ERR(custom_key3_class);
printk("%s: create class, err = %d\n",__func__, retval);
return retval;
}
for (i = 0; class_attr_custom_key3[i].attr.name; i++) {
retval = class_create_file(custom_key3_class, &class_attr_custom_key3[i]);
if (retval) {
printk("%s: Fail class_create_file\n", __func__);
return retval;
}
}
printk("+++++++++++ yft_customkey_f3_init end +++++++++++");
return retval;
}
#endif
#endif