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
gpio
gpio-janz-ttl.c
Go to the documentation of this file.
1
/*
2
* Janz MODULbus VMOD-TTL GPIO Driver
3
*
4
* Copyright (c) 2010 Ira W. Snyder <
[email protected]
>
5
*
6
* This program is free software; you can redistribute it and/or modify it
7
* under the terms of the GNU General Public License as published by the
8
* Free Software Foundation; either version 2 of the License, or (at your
9
* option) any later version.
10
*/
11
12
#include <linux/kernel.h>
13
#include <linux/module.h>
14
#include <
linux/init.h
>
15
#include <
linux/interrupt.h
>
16
#include <
linux/delay.h
>
17
#include <
linux/platform_device.h
>
18
#include <
linux/io.h
>
19
#include <
linux/gpio.h
>
20
#include <linux/slab.h>
21
22
#include <
linux/mfd/janz.h
>
23
24
#define DRV_NAME "janz-ttl"
25
26
#define PORTA_DIRECTION 0x23
27
#define PORTB_DIRECTION 0x2B
28
#define PORTC_DIRECTION 0x06
29
#define PORTA_IOCTL 0x24
30
#define PORTB_IOCTL 0x2C
31
#define PORTC_IOCTL 0x07
32
33
#define MASTER_INT_CTL 0x00
34
#define MASTER_CONF_CTL 0x01
35
36
#define CONF_PAE (1 << 2)
37
#define CONF_PBE (1 << 7)
38
#define CONF_PCE (1 << 4)
39
40
struct
ttl_control_regs
{
41
__be16
portc
;
42
__be16
portb
;
43
__be16
porta
;
44
__be16
control
;
45
};
46
47
struct
ttl_module
{
48
struct
gpio_chip
gpio
;
49
50
/* base address of registers */
51
struct
ttl_control_regs
__iomem
*
regs
;
52
53
u8
portc_shadow
;
54
u8
portb_shadow
;
55
u8
porta_shadow
;
56
57
spinlock_t
lock
;
58
};
59
60
static
int
ttl_get_value(
struct
gpio_chip *
gpio
,
unsigned
offset
)
61
{
62
struct
ttl_module
*
mod
=
dev_get_drvdata
(gpio->dev);
63
u8
*
shadow
;
64
int
ret
;
65
66
if
(offset < 8) {
67
shadow = &mod->
porta_shadow
;
68
}
else
if
(offset < 16) {
69
shadow = &mod->
portb_shadow
;
70
offset -= 8;
71
}
else
{
72
shadow = &mod->
portc_shadow
;
73
offset -= 16;
74
}
75
76
spin_lock(&mod->
lock
);
77
ret = *shadow & (1 <<
offset
);
78
spin_unlock(&mod->
lock
);
79
return
ret
;
80
}
81
82
static
void
ttl_set_value(
struct
gpio_chip *gpio,
unsigned
offset,
int
value
)
83
{
84
struct
ttl_module
*mod =
dev_get_drvdata
(gpio->dev);
85
void
__iomem
*
port
;
86
u8
*
shadow
;
87
88
if
(offset < 8) {
89
port = &mod->
regs
->porta;
90
shadow = &mod->
porta_shadow
;
91
}
else
if
(offset < 16) {
92
port = &mod->
regs
->portb;
93
shadow = &mod->
portb_shadow
;
94
offset -= 8;
95
}
else
{
96
port = &mod->
regs
->portc;
97
shadow = &mod->
portc_shadow
;
98
offset -= 16;
99
}
100
101
spin_lock(&mod->
lock
);
102
if
(value)
103
*shadow |= (1 <<
offset
);
104
else
105
*shadow &= ~(1 <<
offset
);
106
107
iowrite16be
(*shadow, port);
108
spin_unlock(&mod->
lock
);
109
}
110
111
static
void
__devinit
ttl_write_reg(
struct
ttl_module
*mod,
u8
reg
,
u16
val
)
112
{
113
iowrite16be
(reg, &mod->
regs
->control);
114
iowrite16be
(val, &mod->
regs
->control);
115
}
116
117
static
void
__devinit
ttl_setup_device(
struct
ttl_module
*mod)
118
{
119
/* reset the device to a known state */
120
iowrite16be
(0x0000, &mod->
regs
->control);
121
iowrite16be
(0x0001, &mod->
regs
->control);
122
iowrite16be
(0x0000, &mod->
regs
->control);
123
124
/* put all ports in open-drain mode */
125
ttl_write_reg(mod,
PORTA_IOCTL
, 0x00ff);
126
ttl_write_reg(mod,
PORTB_IOCTL
, 0x00ff);
127
ttl_write_reg(mod,
PORTC_IOCTL
, 0x000f);
128
129
/* set all ports as outputs */
130
ttl_write_reg(mod,
PORTA_DIRECTION
, 0x0000);
131
ttl_write_reg(mod,
PORTB_DIRECTION
, 0x0000);
132
ttl_write_reg(mod,
PORTC_DIRECTION
, 0x0000);
133
134
/* set all ports to drive zeroes */
135
iowrite16be
(0x0000, &mod->
regs
->porta);
136
iowrite16be
(0x0000, &mod->
regs
->portb);
137
iowrite16be
(0x0000, &mod->
regs
->portc);
138
139
/* enable all ports */
140
ttl_write_reg(mod,
MASTER_CONF_CTL
,
CONF_PAE
|
CONF_PBE
|
CONF_PCE
);
141
}
142
143
static
int
__devinit
ttl_probe(
struct
platform_device
*pdev)
144
{
145
struct
janz_platform_data
*
pdata
;
146
struct
device
*
dev
= &pdev->
dev
;
147
struct
ttl_module
*
mod
;
148
struct
gpio_chip *
gpio
;
149
struct
resource
*
res
;
150
int
ret
;
151
152
pdata = pdev->
dev
.platform_data;
153
if
(!pdata) {
154
dev_err
(dev,
"no platform data\n"
);
155
ret = -
ENXIO
;
156
goto
out_return;
157
}
158
159
mod = kzalloc(
sizeof
(*mod),
GFP_KERNEL
);
160
if
(!mod) {
161
dev_err
(dev,
"unable to allocate private data\n"
);
162
ret = -
ENOMEM
;
163
goto
out_return;
164
}
165
166
platform_set_drvdata(pdev, mod);
167
spin_lock_init
(&mod->
lock
);
168
169
/* get access to the MODULbus registers for this module */
170
res =
platform_get_resource
(pdev,
IORESOURCE_MEM
, 0);
171
if
(!res) {
172
dev_err
(dev,
"MODULbus registers not found\n"
);
173
ret = -
ENODEV
;
174
goto
out_free_mod;
175
}
176
177
mod->
regs
=
ioremap
(res->
start
, resource_size(res));
178
if
(!mod->
regs
) {
179
dev_err
(dev,
"MODULbus registers not ioremap\n"
);
180
ret = -
ENOMEM
;
181
goto
out_free_mod;
182
}
183
184
ttl_setup_device(mod);
185
186
/* Initialize the GPIO data structures */
187
gpio = &mod->
gpio
;
188
gpio->dev = &pdev->
dev
;
189
gpio->label = pdev->
name
;
190
gpio->get = ttl_get_value;
191
gpio->set = ttl_set_value;
192
gpio->owner =
THIS_MODULE
;
193
194
/* request dynamic allocation */
195
gpio->base = -1;
196
gpio->ngpio = 20;
197
198
ret =
gpiochip_add
(gpio);
199
if
(ret) {
200
dev_err
(dev,
"unable to add GPIO chip\n"
);
201
goto
out_iounmap_regs;
202
}
203
204
return
0;
205
206
out_iounmap_regs:
207
iounmap
(mod->
regs
);
208
out_free_mod:
209
kfree
(mod);
210
out_return:
211
return
ret
;
212
}
213
214
static
int
__devexit
ttl_remove(
struct
platform_device
*pdev)
215
{
216
struct
ttl_module
*mod = platform_get_drvdata(pdev);
217
struct
device
*dev = &pdev->
dev
;
218
int
ret
;
219
220
ret =
gpiochip_remove
(&mod->
gpio
);
221
if
(ret) {
222
dev_err
(dev,
"unable to remove GPIO chip\n"
);
223
return
ret
;
224
}
225
226
iounmap
(mod->
regs
);
227
kfree
(mod);
228
return
0;
229
}
230
231
static
struct
platform_driver
ttl_driver = {
232
.driver = {
233
.name =
DRV_NAME
,
234
.owner =
THIS_MODULE
,
235
},
236
.probe = ttl_probe,
237
.remove =
__devexit_p
(ttl_remove),
238
};
239
240
module_platform_driver
(ttl_driver);
241
242
MODULE_AUTHOR
(
"Ira W. Snyder <
[email protected]
>"
);
243
MODULE_DESCRIPTION
(
"Janz MODULbus VMOD-TTL Driver"
);
244
MODULE_LICENSE
(
"GPL"
);
245
MODULE_ALIAS
(
"platform:janz-ttl"
);
Generated on Thu Jan 10 2013 13:30:40 for Linux Kernel by
1.8.2