Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
extcon
extcon-gpio.c
Go to the documentation of this file.
1
/*
2
* drivers/extcon/extcon_gpio.c
3
*
4
* Single-state GPIO extcon driver based on extcon class
5
*
6
* Copyright (C) 2008 Google, Inc.
7
* Author: Mike Lockwood <
[email protected]
>
8
*
9
* Modified by MyungJoo Ham <
[email protected]
> to support extcon
10
* (originally switch class is supported)
11
*
12
* This software is licensed under the terms of the GNU General Public
13
* License version 2, as published by the Free Software Foundation, and
14
* may be copied, distributed, and modified under those terms.
15
*
16
* This program is distributed in the hope that it will be useful,
17
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
* GNU General Public License for more details.
20
*
21
*/
22
23
#include <linux/module.h>
24
#include <linux/kernel.h>
25
#include <
linux/init.h
>
26
#include <
linux/interrupt.h
>
27
#include <
linux/platform_device.h
>
28
#include <linux/slab.h>
29
#include <
linux/workqueue.h
>
30
#include <
linux/gpio.h
>
31
#include <
linux/extcon.h
>
32
#include <
linux/extcon/extcon_gpio.h
>
33
34
struct
gpio_extcon_data
{
35
struct
extcon_dev
edev
;
36
unsigned
gpio
;
37
const
char
*
state_on
;
38
const
char
*
state_off
;
39
int
irq
;
40
struct
delayed_work
work
;
41
unsigned
long
debounce_jiffies
;
42
};
43
44
static
void
gpio_extcon_work(
struct
work_struct
*
work
)
45
{
46
int
state
;
47
struct
gpio_extcon_data
*
data
=
48
container_of
(to_delayed_work(work),
struct
gpio_extcon_data
,
49
work);
50
51
state =
gpio_get_value
(data->
gpio
);
52
extcon_set_state
(&data->
edev
, state);
53
}
54
55
static
irqreturn_t
gpio_irq_handler(
int
irq
,
void
*
dev_id
)
56
{
57
struct
gpio_extcon_data
*extcon_data =
dev_id
;
58
59
schedule_delayed_work
(&extcon_data->
work
,
60
extcon_data->
debounce_jiffies
);
61
return
IRQ_HANDLED
;
62
}
63
64
static
ssize_t
extcon_gpio_print_state(
struct
extcon_dev
*
edev
,
char
*
buf
)
65
{
66
struct
gpio_extcon_data
*extcon_data =
67
container_of
(edev,
struct
gpio_extcon_data
, edev);
68
const
char
*
state
;
69
if
(extcon_get_state(edev))
70
state = extcon_data->
state_on
;
71
else
72
state = extcon_data->
state_off
;
73
74
if
(state)
75
return
sprintf
(buf,
"%s\n"
, state);
76
return
-
EINVAL
;
77
}
78
79
static
int
__devinit
gpio_extcon_probe(
struct
platform_device
*pdev)
80
{
81
struct
gpio_extcon_platform_data
*
pdata
= pdev->
dev
.platform_data;
82
struct
gpio_extcon_data
*extcon_data;
83
int
ret
= 0;
84
85
if
(!pdata)
86
return
-
EBUSY
;
87
if
(!pdata->
irq_flags
) {
88
dev_err
(&pdev->
dev
,
"IRQ flag is not specified.\n"
);
89
return
-
EINVAL
;
90
}
91
92
extcon_data =
devm_kzalloc
(&pdev->
dev
,
sizeof
(
struct
gpio_extcon_data
),
93
GFP_KERNEL
);
94
if
(!extcon_data)
95
return
-
ENOMEM
;
96
97
extcon_data->
edev
.name = pdata->
name
;
98
extcon_data->
gpio
= pdata->
gpio
;
99
extcon_data->
state_on
= pdata->
state_on
;
100
extcon_data->
state_off
= pdata->
state_off
;
101
if
(pdata->
state_on
&& pdata->
state_off
)
102
extcon_data->
edev
.print_state = extcon_gpio_print_state;
103
extcon_data->
debounce_jiffies
=
msecs_to_jiffies
(pdata->
debounce
);
104
105
ret =
extcon_dev_register
(&extcon_data->
edev
, &pdev->
dev
);
106
if
(ret < 0)
107
return
ret
;
108
109
ret =
devm_gpio_request_one
(&pdev->
dev
, extcon_data->
gpio
,
GPIOF_DIR_IN
,
110
pdev->
name
);
111
if
(ret < 0)
112
goto
err
;
113
114
INIT_DELAYED_WORK
(&extcon_data->
work
, gpio_extcon_work);
115
116
extcon_data->
irq
=
gpio_to_irq
(extcon_data->
gpio
);
117
if
(extcon_data->
irq
< 0) {
118
ret = extcon_data->
irq
;
119
goto
err
;
120
}
121
122
ret =
request_any_context_irq
(extcon_data->
irq
, gpio_irq_handler,
123
pdata->
irq_flags
, pdev->
name
,
124
extcon_data);
125
if
(ret < 0)
126
goto
err
;
127
128
platform_set_drvdata(pdev, extcon_data);
129
/* Perform initial detection */
130
gpio_extcon_work(&extcon_data->
work
.work);
131
132
return
0;
133
134
err
:
135
extcon_dev_unregister
(&extcon_data->
edev
);
136
137
return
ret
;
138
}
139
140
static
int
__devexit
gpio_extcon_remove(
struct
platform_device
*pdev)
141
{
142
struct
gpio_extcon_data
*extcon_data = platform_get_drvdata(pdev);
143
144
cancel_delayed_work_sync
(&extcon_data->
work
);
145
free_irq
(extcon_data->
irq
, extcon_data);
146
extcon_dev_unregister
(&extcon_data->
edev
);
147
148
return
0;
149
}
150
151
static
struct
platform_driver
gpio_extcon_driver = {
152
.probe = gpio_extcon_probe,
153
.remove =
__devexit_p
(gpio_extcon_remove),
154
.driver = {
155
.name =
"extcon-gpio"
,
156
.owner =
THIS_MODULE
,
157
},
158
};
159
160
module_platform_driver
(gpio_extcon_driver);
161
162
MODULE_AUTHOR
(
"Mike Lockwood <
[email protected]
>"
);
163
MODULE_DESCRIPTION
(
"GPIO extcon driver"
);
164
MODULE_LICENSE
(
"GPL"
);
Generated on Thu Jan 10 2013 13:30:11 for Linux Kernel by
1.8.2