summaryrefslogtreecommitdiffstats
path: root/u-boot/board/goldelico/gta04/status.c
blob: 659061f5fff0b6be7819a0bc113e9097b7618626 (plain)
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
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
/* 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)

#define GPIO_AUX		7		// AUX/User button
#define GPIO_AUX_ACTIVE	1
#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
#define GPIO_KEYIRQ		176		// FIXME: was 63, 10 on GTA04A2 and A3

// FIXME: other expander variants?

#elif defined(CONFIG_OMAP3_BEAGLE)

static int hasTCA6507=0;

#define GPIO_AUX_ACTIVE	1
#define GPIO_KEYIRQ		-1

#if defined(CONFIG_GOLDELICO_EXPANDER_B1)

#define GPIO_AUX		136		// AUX/User button on expansion board
#define GPIO_POWER		137		// POWER button
#define GPIO_GPSEXT		144		// external GPS antenna is plugged in
#define GPIO_PENIRQ		157		// TSC must be set up to provide PENIRQ

#elif defined(CONFIG_GOLDELICO_EXPANDER_B2)

#define GPIO_AUX		136		// AUX/User button on expansion board
#define GPIO_POWER		137		// POWER button
#define GPIO_GPSEXT		144		// external GPS antenna is plugged in
#define GPIO_PENIRQ		157		// TSC must be set up to provide PENIRQ
#undef GPIO_KEYIRQ
#define GPIO_KEYIRQ		138		// TRF79x0

#elif defined(CONFIG_GOLDELICO_EXPANDER_B4)

#define GPIO_AUX		7		// AUX/User button sits on main board
#define GPIO_POWER		-1		// POWER button
#define GPIO_GPSEXT		144		// external GPS antenna is plugged in
#define GPIO_PENIRQ		157		// TSC must be set up to provide PENIRQ
#undef GPIO_KEYIRQ
#define GPIO_KEYIRQ		138		// PPS interrupt

#endif

#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;

// FIXME some BB Expanders have neither TCA6507 nor LEDs
// we could use the GPIO 149 and 150 LEDs

#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

static int status;

void status_set_status(int value)
{
	status=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
#if defined(CONFIG_GOLDELICO_EXPANDER_B2)
		value |= (value >> 3) & 0x03;	// map power LEDs to AUX LEDs (we only have 2)
#endif
		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 (for mirror)
	int status=0;
	if(GPIO_AUX >= 0)
		status |= ((omap_get_gpio_datain(GPIO_AUX) == GPIO_AUX_ACTIVE) << 0);
	if(GPIO_GPSEXT >= 0)
		status |= ((omap_get_gpio_datain(GPIO_GPSEXT)) << 1);
	if(GPIO_POWER >= 0)
		status |= ((!omap_get_gpio_datain(GPIO_POWER)) << 3);
	else
		{
		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
		status |= (val&0x01) != 0;
		}
	if(GPIO_PENIRQ >= 0)
		status |= ((!omap_get_gpio_datain(GPIO_PENIRQ)) << 4);
	if(GPIO_KEYIRQ >= 0)
		status |= ((omap_get_gpio_datain(GPIO_KEYIRQ)) << 5);
	return status;

#if OLD
#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_GOLDELICO_EXPANDER_B2)
	return
		((omap_get_gpio_datain(GPIO_AUX)) << 0) |
		((0) << 1) |
	((GPIO_POWER>=0?(!omap_get_gpio_datain(GPIO_POWER)):0) << 3) |
		((omap_get_gpio_datain(GPIO_PENIRQ)) << 4);
#else
	return
		((!omap_get_gpio_datain(GPIO_AUX)) << 0) |
		((omap_get_gpio_datain(GPIO_GPSEXT)) << 1) |
	((GPIO_POWER>=0?(!omap_get_gpio_datain(GPIO_POWER)):0) << 3) |
		((omap_get_gpio_datain(GPIO_PENIRQ)) << 4);
#endif
#endif
}

int status_init(void)
{
	isXM = (get_board_revision() == REVISION_XM);
	i2c_set_bus_num(TWL4030_I2C_BUS);
	if(isXM) {
		/* Set VAUX1 to 3.3V for GTA04E display board */
		twl4030_pmrecv_vsel_cfg(TWL4030_PM_RECEIVER_VAUX1_DEDICATED,
								/*TWL4030_PM_RECEIVER_VAUX1_VSEL_33*/ 0x07,
								TWL4030_PM_RECEIVER_VAUX1_DEV_GRP,
								TWL4030_PM_RECEIVER_DEV_GRP_P1);
		udelay(5000);
	}
#if !defined(CONFIG_OMAP3_GTA04)	// we assume that a GTA04 always has a TCA6507
	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 names
			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);
		if(GPIO_POWER >= 0)
			omap_request_gpio(GPIO_POWER);
	}
	else {
		// initialize I2C controller
	}
	
	if(GPIO_AUX >= 0)
		omap_request_gpio(GPIO_AUX);
	if(GPIO_POWER >= 0)
		omap_request_gpio(GPIO_POWER);
	if(GPIO_GPSEXT >= 0)
		omap_request_gpio(GPIO_GPSEXT);
	if(GPIO_PENIRQ >= 0)
		omap_request_gpio(GPIO_PENIRQ);
	if(GPIO_KEYIRQ >= 0)
		omap_request_gpio(GPIO_KEYIRQ);
	
	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
		}
	
	if(GPIO_AUX >= 0)
		omap_set_gpio_direction(GPIO_AUX, 1);		// input
	if(GPIO_POWER >= 0)
		omap_set_gpio_direction(GPIO_POWER, 1);		// input
	if(GPIO_GPSEXT >= 0)
		omap_set_gpio_direction(GPIO_GPSEXT, 1);	// input
	if(GPIO_PENIRQ >= 0)
		omap_set_gpio_direction(GPIO_PENIRQ, 1);	// input
	if(GPIO_KEYIRQ >= 0)
		omap_set_gpio_direction(GPIO_KEYIRQ, 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;	
}