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
staging
olpc_dcon
olpc_dcon_xo_1.c
Go to the documentation of this file.
1
/*
2
* Mainly by David Woodhouse, somewhat modified by Jordan Crouse
3
*
4
* Copyright © 2006-2007 Red Hat, Inc.
5
* Copyright © 2006-2007 Advanced Micro Devices, Inc.
6
* Copyright © 2009 VIA Technology, Inc.
7
* Copyright (c) 2010 Andres Salomon <
[email protected]
>
8
*
9
* This program is free software. You can redistribute it and/or
10
* modify it under the terms of version 2 of the GNU General Public
11
* License as published by the Free Software Foundation.
12
*/
13
14
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
15
16
#include <
linux/cs5535.h
>
17
#include <
linux/gpio.h
>
18
#include <
linux/delay.h
>
19
#include <
asm/olpc.h
>
20
21
#include "
olpc_dcon.h
"
22
23
static
int
dcon_init_xo_1(
struct
dcon_priv
*dcon)
24
{
25
unsigned
char
lob;
26
27
if
(
gpio_request
(
OLPC_GPIO_DCON_STAT0
,
"OLPC-DCON"
)) {
28
pr_err
(
"failed to request STAT0 GPIO\n"
);
29
return
-
EIO
;
30
}
31
if
(
gpio_request
(
OLPC_GPIO_DCON_STAT1
,
"OLPC-DCON"
)) {
32
pr_err
(
"failed to request STAT1 GPIO\n"
);
33
goto
err_gp_stat1;
34
}
35
if
(
gpio_request
(
OLPC_GPIO_DCON_IRQ
,
"OLPC-DCON"
)) {
36
pr_err
(
"failed to request IRQ GPIO\n"
);
37
goto
err_gp_irq;
38
}
39
if
(
gpio_request
(
OLPC_GPIO_DCON_LOAD
,
"OLPC-DCON"
)) {
40
pr_err
(
"failed to request LOAD GPIO\n"
);
41
goto
err_gp_load;
42
}
43
if
(
gpio_request
(
OLPC_GPIO_DCON_BLANK
,
"OLPC-DCON"
)) {
44
pr_err
(
"failed to request BLANK GPIO\n"
);
45
goto
err_gp_blank;
46
}
47
48
/* Turn off the event enable for GPIO7 just to be safe */
49
cs5535_gpio_clear
(
OLPC_GPIO_DCON_IRQ
,
GPIO_EVENTS_ENABLE
);
50
51
/*
52
* Determine the current state by reading the GPIO bit; earlier
53
* stages of the boot process have established the state.
54
*
55
* Note that we read GPIO_OUPUT_VAL rather than GPIO_READ_BACK here;
56
* this is because OFW will disable input for the pin and set a value..
57
* READ_BACK will only contain a valid value if input is enabled and
58
* then a value is set. So, future readings of the pin can use
59
* READ_BACK, but the first one cannot. Awesome, huh?
60
*/
61
dcon->
curr_src
=
cs5535_gpio_isset
(
OLPC_GPIO_DCON_LOAD
,
GPIO_OUTPUT_VAL
)
62
?
DCON_SOURCE_CPU
63
:
DCON_SOURCE_DCON
;
64
dcon->
pending_src
= dcon->
curr_src
;
65
66
/* Set the directions for the GPIO pins */
67
gpio_direction_input
(
OLPC_GPIO_DCON_STAT0
);
68
gpio_direction_input
(
OLPC_GPIO_DCON_STAT1
);
69
gpio_direction_input
(
OLPC_GPIO_DCON_IRQ
);
70
gpio_direction_input
(
OLPC_GPIO_DCON_BLANK
);
71
gpio_direction_output
(
OLPC_GPIO_DCON_LOAD
,
72
dcon->
curr_src
==
DCON_SOURCE_CPU
);
73
74
/* Set up the interrupt mappings */
75
76
/* Set the IRQ to pair 2 */
77
cs5535_gpio_setup_event
(
OLPC_GPIO_DCON_IRQ
, 2, 0);
78
79
/* Enable group 2 to trigger the DCON interrupt */
80
cs5535_gpio_set_irq
(2,
DCON_IRQ
);
81
82
/* Select edge level for interrupt (in PIC) */
83
lob =
inb
(0x4d0);
84
lob &= ~(1 <<
DCON_IRQ
);
85
outb
(lob, 0x4d0);
86
87
/* Register the interrupt handler */
88
if
(
request_irq
(
DCON_IRQ
, &
dcon_interrupt
, 0,
"DCON"
, dcon)) {
89
pr_err
(
"failed to request DCON's irq\n"
);
90
goto
err_req_irq;
91
}
92
93
/* Clear INV_EN for GPIO7 (DCONIRQ) */
94
cs5535_gpio_clear
(
OLPC_GPIO_DCON_IRQ
,
GPIO_INPUT_INVERT
);
95
96
/* Enable filter for GPIO12 (DCONBLANK) */
97
cs5535_gpio_set
(
OLPC_GPIO_DCON_BLANK
,
GPIO_INPUT_FILTER
);
98
99
/* Disable filter for GPIO7 */
100
cs5535_gpio_clear
(
OLPC_GPIO_DCON_IRQ
,
GPIO_INPUT_FILTER
);
101
102
/* Disable event counter for GPIO7 (DCONIRQ) and GPIO12 (DCONBLANK) */
103
cs5535_gpio_clear
(
OLPC_GPIO_DCON_IRQ
,
GPIO_INPUT_EVENT_COUNT
);
104
cs5535_gpio_clear
(
OLPC_GPIO_DCON_BLANK
,
GPIO_INPUT_EVENT_COUNT
);
105
106
/* Add GPIO12 to the Filter Event Pair #7 */
107
cs5535_gpio_set
(
OLPC_GPIO_DCON_BLANK
,
GPIO_FE7_SEL
);
108
109
/* Turn off negative Edge Enable for GPIO12 */
110
cs5535_gpio_clear
(
OLPC_GPIO_DCON_BLANK
,
GPIO_NEGATIVE_EDGE_EN
);
111
112
/* Enable negative Edge Enable for GPIO7 */
113
cs5535_gpio_set
(
OLPC_GPIO_DCON_IRQ
,
GPIO_NEGATIVE_EDGE_EN
);
114
115
/* Zero the filter amount for Filter Event Pair #7 */
116
cs5535_gpio_set
(0,
GPIO_FLTR7_AMOUNT
);
117
118
/* Clear the negative edge status for GPIO7 and GPIO12 */
119
cs5535_gpio_set
(
OLPC_GPIO_DCON_IRQ
,
GPIO_NEGATIVE_EDGE_STS
);
120
cs5535_gpio_set
(
OLPC_GPIO_DCON_BLANK
,
GPIO_NEGATIVE_EDGE_STS
);
121
122
/* FIXME: Clear the positive status as well, just to be sure */
123
cs5535_gpio_set
(
OLPC_GPIO_DCON_IRQ
,
GPIO_POSITIVE_EDGE_STS
);
124
cs5535_gpio_set
(
OLPC_GPIO_DCON_BLANK
,
GPIO_POSITIVE_EDGE_STS
);
125
126
/* Enable events for GPIO7 (DCONIRQ) and GPIO12 (DCONBLANK) */
127
cs5535_gpio_set
(
OLPC_GPIO_DCON_IRQ
,
GPIO_EVENTS_ENABLE
);
128
cs5535_gpio_set
(
OLPC_GPIO_DCON_BLANK
,
GPIO_EVENTS_ENABLE
);
129
130
return
0;
131
132
err_req_irq:
133
gpio_free
(
OLPC_GPIO_DCON_BLANK
);
134
err_gp_blank:
135
gpio_free
(
OLPC_GPIO_DCON_LOAD
);
136
err_gp_load:
137
gpio_free
(
OLPC_GPIO_DCON_IRQ
);
138
err_gp_irq:
139
gpio_free
(
OLPC_GPIO_DCON_STAT1
);
140
err_gp_stat1:
141
gpio_free
(
OLPC_GPIO_DCON_STAT0
);
142
return
-
EIO
;
143
}
144
145
static
void
dcon_wiggle_xo_1(
void
)
146
{
147
int
x
;
148
149
/*
150
* According to HiMax, when powering the DCON up we should hold
151
* SMB_DATA high for 8 SMB_CLK cycles. This will force the DCON
152
* state machine to reset to a (sane) initial state. Mitch Bradley
153
* did some testing and discovered that holding for 16 SMB_CLK cycles
154
* worked a lot more reliably, so that's what we do here.
155
*
156
* According to the cs5536 spec, to set GPIO14 to SMB_CLK we must
157
* simultaneously set AUX1 IN/OUT to GPIO14; ditto for SMB_DATA and
158
* GPIO15.
159
*/
160
cs5535_gpio_set
(
OLPC_GPIO_SMB_CLK
,
GPIO_OUTPUT_VAL
);
161
cs5535_gpio_set
(
OLPC_GPIO_SMB_DATA
,
GPIO_OUTPUT_VAL
);
162
cs5535_gpio_set
(
OLPC_GPIO_SMB_CLK
,
GPIO_OUTPUT_ENABLE
);
163
cs5535_gpio_set
(
OLPC_GPIO_SMB_DATA
,
GPIO_OUTPUT_ENABLE
);
164
cs5535_gpio_clear
(
OLPC_GPIO_SMB_CLK
,
GPIO_OUTPUT_AUX1
);
165
cs5535_gpio_clear
(
OLPC_GPIO_SMB_DATA
,
GPIO_OUTPUT_AUX1
);
166
cs5535_gpio_clear
(
OLPC_GPIO_SMB_CLK
,
GPIO_OUTPUT_AUX2
);
167
cs5535_gpio_clear
(
OLPC_GPIO_SMB_DATA
,
GPIO_OUTPUT_AUX2
);
168
cs5535_gpio_clear
(
OLPC_GPIO_SMB_CLK
,
GPIO_INPUT_AUX1
);
169
cs5535_gpio_clear
(
OLPC_GPIO_SMB_DATA
,
GPIO_INPUT_AUX1
);
170
171
for
(x = 0; x < 16; x++) {
172
udelay
(5);
173
cs5535_gpio_clear
(
OLPC_GPIO_SMB_CLK
,
GPIO_OUTPUT_VAL
);
174
udelay
(5);
175
cs5535_gpio_set
(
OLPC_GPIO_SMB_CLK
,
GPIO_OUTPUT_VAL
);
176
}
177
udelay
(5);
178
cs5535_gpio_set
(
OLPC_GPIO_SMB_CLK
,
GPIO_OUTPUT_AUX1
);
179
cs5535_gpio_set
(
OLPC_GPIO_SMB_DATA
,
GPIO_OUTPUT_AUX1
);
180
cs5535_gpio_set
(
OLPC_GPIO_SMB_CLK
,
GPIO_INPUT_AUX1
);
181
cs5535_gpio_set
(
OLPC_GPIO_SMB_DATA
,
GPIO_INPUT_AUX1
);
182
}
183
184
static
void
dcon_set_dconload_1(
int
val
)
185
{
186
gpio_set_value
(
OLPC_GPIO_DCON_LOAD
, val);
187
}
188
189
static
int
dcon_read_status_xo_1(
u8
*
status
)
190
{
191
*status =
gpio_get_value
(
OLPC_GPIO_DCON_STAT0
);
192
*status |=
gpio_get_value
(
OLPC_GPIO_DCON_STAT1
) << 1;
193
194
/* Clear the negative edge status for GPIO7 */
195
cs5535_gpio_set
(
OLPC_GPIO_DCON_IRQ
,
GPIO_NEGATIVE_EDGE_STS
);
196
197
return
0;
198
}
199
200
struct
dcon_platform_data
dcon_pdata_xo_1
= {
201
.init = dcon_init_xo_1,
202
.bus_stabilize_wiggle = dcon_wiggle_xo_1,
203
.set_dconload = dcon_set_dconload_1,
204
.read_status = dcon_read_status_xo_1,
205
};
Generated on Thu Jan 10 2013 14:29:51 for Linux Kernel by
1.8.2