huangcm
2025-09-01 53d8e046ac1bf2ebe94f671983e3d3be059df91a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*
 * drivers/input/sensor/sunxi_gpadc_test.c
 *
 * Copyright (C) 2016 Allwinner.
 * fuzhaoke <fuzhaoke@allwinnertech.com>
 *
 * SUNXI GPADC test file
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 */
 
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/timer.h>
#include <linux/irq.h>
#include <linux/of_irq.h>
#include "sunxi_gpadc.h"
 
struct sunxi_gpadc *sunxi_gpadc_handler;
 
extern void sunxi_gpadc_sample_rate_set(void __iomem *reg_base, u32 clk_in, u32 round_clk);
extern void sunxi_gpadc_ctrl_set(void __iomem *reg_base, u32 ctrl_para);
extern u32 sunxi_gpadc_ch_select(void __iomem *reg_base, enum gp_channel_id id);
extern u32 sunxi_gpadc_ch_deselect(void __iomem *reg_base, enum gp_channel_id id);
extern u32 sunxi_gpadc_mode_select(void __iomem *reg_base, enum gp_select_mode mode);
extern u32 sunxi_gpadc_ch_cmp(void __iomem *reg_base, enum gp_channel_id id, u32 low_uv, u32 hig_uv);
extern u32 sunxi_gpadc_cmp_select(void __iomem *reg_base, enum gp_channel_id id);
extern void sunxi_gpadc_en(void __iomem *reg_base, bool onoff);
extern u32 sunxi_gpadc_int_cfg(void __iomem *reg_base);
extern void sunxi_gpadc_int_set(void __iomem *reg_base, u32 int_para);
extern void sunxi_gpadc_int_clr(void __iomem *reg_base, u32 int_para);
extern u32 sunxi_gpadc_read_ints(void __iomem *reg_base);
extern void sunxi_gpadc_clr_ints(void __iomem *reg_base, u32 int_para);
extern u32 sunxi_gpadc_read_data(void __iomem *reg_base, enum gp_channel_id id);
extern struct sunxi_gpadc *sunxi_gpadc_get_handler(void);
 
 
static irqreturn_t sunxi_gpadc_interrupt(int irqno, void *dev_id)
{
   struct sunxi_gpadc *sunxi_gpadc_handler = (struct sunxi_gpadc *)dev_id;
   u32  reg_val = 0;
 
   reg_val = sunxi_gpadc_read_ints(sunxi_gpadc_handler->reg_base);
   reg_val &= sunxi_gpadc_int_cfg(sunxi_gpadc_handler->reg_base);
 
   if (reg_val & GP_CH0_LOW_IRQ_PEND)
       printk("channel 0 low pend\n");
 
   if (reg_val & GP_CH1_LOW_IRQ_PEND)
       printk("channel 1 low pend\n");
 
   if (reg_val & GP_CH0_DATA_IRQ_PEND)
       printk("val_ch0 = %d mv\n", sunxi_gpadc_read_data(sunxi_gpadc_handler->reg_base, GP_CH_0)*561);
 
   if (reg_val & GP_CH1_DATA_IRQ_PEND)
       printk("val_ch1 = %d mv\n", sunxi_gpadc_read_data(sunxi_gpadc_handler->reg_base, GP_CH_1)*561);
 
   if (reg_val & GP_CH0_HIG_IRQ_PEND)
       printk("channel 0 hight pend\n");
 
   if (reg_val & GP_CH1_HIG_IRQ_PEND)
       printk("channel 1 hight pend\n");
 
   sunxi_gpadc_clr_ints(sunxi_gpadc_handler->reg_base, reg_val);
 
   return IRQ_HANDLED;
}
 
 
static int __init gp_test_init(void)
{
   int try_time = 50;
   int val;
 
   printk("gp_test_init\n");
 
   sunxi_gpadc_handler = sunxi_gpadc_get_handler();
   if (NULL == sunxi_gpadc_handler) {
       pr_err("sunxi_gpadc_handler is null !\n");
       return -EINVAL;
   }
 
   sunxi_gpadc_sample_rate_set(sunxi_gpadc_handler->reg_base, OSC_24MHZ, 50000);
   sunxi_gpadc_int_clr(sunxi_gpadc_handler->reg_base, ~0);
 
   sunxi_gpadc_mode_select(sunxi_gpadc_handler->reg_base, GP_CONTINUOUS_MODE);
   sunxi_gpadc_ch_select(sunxi_gpadc_handler, GP_CH_0);
 
#if 0
   /* config for channle 1, enable low voltage interrupt */
   sunxi_gpadc_ch_select(sunxi_gpadc_handler, GP_CH_1);
   sunxi_gpadc_ch_cmp(sunxi_gpadc_handler->reg_base, GP_CH_1, 1500000, VOL_RANGE);
   sunxi_gpadc_cmp_select(sunxi_gpadc_handler, GP_CH_1);
   if (request_irq(sunxi_gpadc_handler->irq_num, sunxi_gpadc_interrupt,
        IRQF_TRIGGER_NONE, "sunxi-gpadc", sunxi_gpadc_handler)) {
       pr_err("sunxi_gpadc request irq failure\n");
       return -1;
   }
   sunxi_gpadc_int_set(sunxi_gpadc_handler->reg_base, GP_CH1_LOW_IRQ_EN);
#endif
 
   /* enable GPADC */
   sunxi_gpadc_en(sunxi_gpadc_handler, true);
 
   /* get the data of channel 0 */
   while (try_time--) {
       val = sunxi_gpadc_read_data(sunxi_gpadc_handler->reg_base, GP_CH_0);
       printk("val = 0x%03x ,  vol=%d mv\n", val, val*561);
       mdelay(100);
   }
 
   return 0;
}
 
static void __exit gp_test_exit(void)
{
   printk("gp_test_exit\n");
#if 0
   free_irq(sunxi_gpadc_handler->irq_num, sunxi_gpadc_handler);
#endif
   sunxi_gpadc_en(sunxi_gpadc_handler, false);
}
 
module_init(gp_test_init);
module_exit(gp_test_exit);
 
 
MODULE_AUTHOR("Fuzhaoke");
MODULE_DESCRIPTION("sunxi-gpadc driver test");
MODULE_LICENSE("GPL");