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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
|
/* u-boot driver for the GTA04 LEDs and Buttons
*
* Copyright (C) 2010 by Golden Delicious Computers GmbH&Co. KG
* Author: H. Nikolaus Schaller <hns@goldelico.com>
* All rights reserved.
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
*/
#include <common.h>
#include <asm/errno.h>
#include <asm/io.h>
#include <asm/arch/mux.h>
#include <asm/arch/sys_proto.h>
#include <asm/arch/gpio.h>
#include <asm/mach-types.h>
#include <i2c.h>
#include <twl4030.h>
#include "status.h"
#if defined(CONFIG_OMAP3_GTA04)
// no need to probe for LED controller (compiler should optimize unnecessary code)
#define hasTCA6507 (1==1)
#else
static int hasTCA6507=0;
#endif
#define TWL4030_I2C_BUS (1-1) // I2C1
#define TCA6507_BUS (2-1) // I2C2
#define TCA6507_ADDRESS 0x45
/* register numbers */
#define TCA6507_SELECT0 0
#define TCA6507_SELECT1 1
#define TCA6507_SELECT2 2
#define TCA6507_FADE_ON_TIME 3
#define TCA6507_FULLY_ON_TIME 4
#define TCA6507_FADR_OFF_TIME 5
#define TCA6507_FIRST_FULLY_OFF_TIME 6
#define TCA6507_SECOND_FULLY_OFF_TIME 7
#define TCA6507_MAXIMUM_INTENSITY 8
#define TCA6507_ONE_SHOT_MASTER_INTENSITY 9
#define TCA6507_INITIALIZATION 10
#define TCA6507_AUTO_INCREMENT 16
// we can't include "beagle.h"
/* BeagleBoard revisions */
extern int get_board_revision(void);
#define REVISION_AXBX 0x7
#define REVISION_CX 0x6
#define REVISION_C4 0x5
#define REVISION_XM 0x0
static int isXM = 0;
#if defined(CONFIG_OMAP3_GTA04)
#define GPIO_AUX 7 // AUX/User button
#define GPIO_POWER -1 // N/A on GTA04 (access through TPS65950)
#define GPIO_GPSEXT 144 // external GPS antenna is plugged in
#define GPIO_PENIRQ 160 // TSC must be set up to provide PENIRQ
#elif defined(CONFIG_OMAP3_BEAGLE_HYBRID)
#define GPIO_AUX 136 // AUX/User button
#define GPIO_POWER 137 // POWER button
#define GPIO_GPSEXT 138 // external GPS antenna is plugged in
#define GPIO_PENIRQ 157 // TSC must be set up to provide PENIRQ
#elif defined(CONFIG_OMAP3_BEAGLE_EXPANDER)
#define GPIO_AUX 136 // AUX/User button
#define GPIO_POWER 137 // POWER button
#define GPIO_GPSEXT 138 // external GPS antenna is plugged in
#define GPIO_PENIRQ 157 // TSC must be set up to provide PENIRQ
#else
#error unknown config
#endif
#define GPIO_LED_AUX_RED (isXM?88:70) // AUX
#define GPIO_LED_AUX_GREEN (isXM?89:71) // AUX
#define GPIO_LED_POWER_RED 78 // Power
#define GPIO_LED_POWER_GREEN 79 // Power
#define GPIO_LED_VIBRA (isXM?2:88) // Vibracall motor
#define GPIO_LED_UNUSED (isXM?3:89) // unused
void status_set_status(int value)
{
if(!hasTCA6507) {
omap_set_gpio_dataout(GPIO_LED_AUX_RED, (value&(1 << 0)));
omap_set_gpio_dataout(GPIO_LED_AUX_GREEN, (value&(1 << 1)));
omap_set_gpio_dataout(GPIO_LED_POWER_RED, (value&(1 << 3)));
omap_set_gpio_dataout(GPIO_LED_POWER_GREEN, (value&(1 << 4)));
omap_set_gpio_dataout(GPIO_LED_VIBRA, (value&(1 << 6)));
omap_set_gpio_dataout(GPIO_LED_UNUSED, (value&(1 << 7)));
}
else {
value &= 0x3f; // 6 LEDs only - 7th is reserved to reset the WLAN/BT chip
i2c_set_bus_num(TCA6507_BUS); // write I2C2
// we could write a autoincrement address and all 3 bytes in a single message
// we could set the TCA to do smooth transitions
i2c_reg_write(TCA6507_ADDRESS, TCA6507_SELECT0, 0);
i2c_reg_write(TCA6507_ADDRESS, TCA6507_SELECT1, 0);
i2c_reg_write(TCA6507_ADDRESS, TCA6507_SELECT2, value); // 1 = on
}
}
int status_get_buttons(void)
{ // convert button state into led state
#if defined(CONFIG_OMAP3_GTA04)
u8 val;
i2c_set_bus_num(TWL4030_I2C_BUS); // read I2C1
twl4030_i2c_read_u8(TWL4030_CHIP_PM_MASTER, &val, TWL4030_PM_MASTER_STS_HW_CONDITIONS); // read state of power button (bit 0) from TPS65950
return ((omap_get_gpio_datain(GPIO_AUX)) << 0) |
((omap_get_gpio_datain(GPIO_GPSEXT)) << 1) |
(((val&0x01) != 0) << 3) |
((omap_get_gpio_datain(GPIO_PENIRQ)) << 4);
#elif defined(CONFIG_OMAP3_BEAGLE_EXPANDER)
return
((omap_get_gpio_datain(GPIO_AUX)) << 0) |
((0) << 1) |
((!omap_get_gpio_datain(GPIO_POWER)) << 3) |
((omap_get_gpio_datain(GPIO_PENIRQ)) << 4);
#else
return
((!omap_get_gpio_datain(GPIO_AUX)) << 0) |
((omap_get_gpio_datain(GPIO_GPSEXT)) << 1) |
((!omap_get_gpio_datain(GPIO_POWER)) << 3) |
((omap_get_gpio_datain(GPIO_PENIRQ)) << 4);
#endif
}
int status_init(void)
{
isXM = (get_board_revision() == REVISION_XM);
#if !defined(CONFIG_OMAP3_GTA04)
if(i2c_set_bus_num(TCA6507_BUS))
{
printf ("could not select I2C2\n");
return 1;
}
hasTCA6507 = !i2c_probe(TCA6507_ADDRESS);
#endif
if(!hasTCA6507) {
if(isXM) { // XM has scrambled dss assignment with respect to default ball name
MUX_VAL(CP(DSS_DATA18), (IEN | PTD | EN | M4)); /*GPIO */
MUX_VAL(CP(DSS_DATA19), (IEN | PTD | EN | M4)); /*GPIO */
MUX_VAL(CP(DSS_DATA8), (IEN | PTD | EN | M4)); /*GPIO */
MUX_VAL(CP(DSS_DATA9), (IEN | PTD | EN | M4)); /*GPIO */
MUX_VAL(CP(SYS_BOOT0), (IEN | PTD | EN | M4)); /*GPIO */
MUX_VAL(CP(SYS_BOOT1), (IEN | PTD | EN | M4)); /*GPIO */
}
else {
MUX_VAL(CP(DSS_DATA0), (IEN | PTD | EN | M4)); /*GPIO */
MUX_VAL(CP(DSS_DATA1), (IEN | PTD | EN | M4)); /*GPIO */
MUX_VAL(CP(DSS_DATA8), (IEN | PTD | EN | M4)); /*GPIO */
MUX_VAL(CP(DSS_DATA9), (IEN | PTD | EN | M4)); /*GPIO */
MUX_VAL(CP(DSS_DATA16), (IEN | PTD | EN | M4)); /*GPIO */
MUX_VAL(CP(DSS_DATA17), (IEN | PTD | EN | M4)); /*GPIO */
}
omap_request_gpio(GPIO_LED_AUX_GREEN);
omap_request_gpio(GPIO_LED_AUX_RED);
omap_request_gpio(GPIO_LED_POWER_GREEN);
omap_request_gpio(GPIO_LED_POWER_RED);
omap_request_gpio(GPIO_LED_VIBRA);
omap_request_gpio(GPIO_LED_UNUSED);
omap_request_gpio(GPIO_POWER);
}
else {
// initialize I2C controller
}
omap_request_gpio(GPIO_AUX);
omap_request_gpio(GPIO_GPSEXT);
omap_request_gpio(GPIO_PENIRQ);
if(!hasTCA6507) {
omap_set_gpio_direction(GPIO_LED_AUX_GREEN, 0); // output
omap_set_gpio_direction(GPIO_LED_AUX_RED, 0); // output
omap_set_gpio_direction(GPIO_LED_POWER_GREEN, 0); // output
omap_set_gpio_direction(GPIO_LED_POWER_RED, 0); // output
omap_set_gpio_direction(GPIO_LED_VIBRA, 0); // output
omap_set_gpio_direction(GPIO_LED_UNUSED, 0); // output
omap_set_gpio_direction(GPIO_POWER, 1); // input
}
omap_set_gpio_direction(GPIO_AUX, 1); // input
#ifndef CONFIG_OMAP3_GTA04
omap_set_gpio_direction(GPIO_POWER, 1); // input
#endif
omap_set_gpio_direction(GPIO_GPSEXT, 1); // input
// when sould we do omap_free_gpio(GPIO_LED_AUX_GREEN); ?
printf("did init LED driver for %s\n", hasTCA6507?"TCA6507":"GPIOs");
return 0;
}
int status_set_flash (int mode)
{ // 0: off, 1: torch, 2: flash
if(i2c_set_bus_num(TCA6507_BUS))
{
printf ("could not select I2C2\n");
return 1;
}
// initialize if needed
// set flash controller mode
return 0;
}
int status_set_vibra (int value)
{ // 0: off otherwise msb controls left/right (2's complement)
unsigned char byte;
if(i2c_set_bus_num(TWL4030_I2C_BUS))
{
printf ("could not select I2C1\n");
return 1;
}
// program Audio controller (see document SWCU050D)
byte = 0x00; // LEDAON=LEDBON=0
i2c_write(0x4A, 0xEE, 1, &byte, 1); // LEDEN
byte = value != 0 ? 0x03 : 0x00; // 8 kHz, Codec on (if value != 0), Option 1:RX and TX stereo audio path
i2c_write(0x49, 0x01, 1, &byte, 1); // CODEC_MODE
byte = 0x16; // APLL_EN enabled, 26 MHz
i2c_write(0x49, 0x3a, 1, &byte, 1); // APLL_CTL
byte = 0x04; // use PWM
i2c_write(0x4B, 0x60, 1, &byte, 1); // VIBRATOR_CFG
byte = value > 0?0x01:0x03; // use VIBRADIR, local driver, enable
i2c_write(0x49, 0x45, 1, &byte, 1); // VIBRATOR_CFG
byte = 256-(value>=0?value:-value); // PWM turnon value
if(byte == 0) byte = 0x01; // 0x00 is forbidden!
i2c_write(0x49, 0x46, 1, &byte, 1); // VIBRA_SEL
// do we have to set some Audio PLL frequency (number 6 & 7?)
/*
To use the vibrator H-bridge:
1. Disable LEDA: Set the LEDEN[0]LEDAON bit to logic 0.
2. Disable LEDB: Set the LEDEN[1]LEDBON bit to logic 0.
3. Turn on the codec:
Set the CODEC_MODE[1] CODECPDZ bit to 1.
The H-bridge vibrator can get its operation from the following sources:
• An audio channel can provide the stimulus.
• A PWM in the audio subchip can generate the signal.
If an audio channel provides the motivating force for the vibrator (for example: the audio right 1 channel):
1. Set the VIBR_CTL[4]VIBRA_SEL bit to 1.
2. Set the VIBR_CTL[5]VIBRA_DIR_SEL bit to 1.
3. Set the VIBR_CTL[3:2]VIBRA_AUDIO_SEL bit field to 0x1 (audio right 1 channel).
4. Select the use of the SIGN bit to determine the output phase to VIBRA_P and VIBRA_M.
5. Set the VIBRA_CTL[0]VIBRA_EN bit to 1 (power to the H-bridge is driven by audiodata).
Notes:
• If audio data drives the vibrator H-bridge, set the VIBRA_SET register to 0xFF.
• The direction of the vibrator H-bridge controlled by the VIBRA_DIR bit can be changed
on the fly.
6. Set the audio PLL input frequency: The APLL_CTL APLL_INFREQ bitfield=0x6.
7. Enable the audio PLL: The APLL_CTL APLL_ENbit=1.
Note: Do not enable LEDA/B and the H-vibrator simultaneously.
*/
return 0;
}
|