blob: 08fcaf21b3c6302a0ab425ee1537fee1537287ab [file] [log] [blame]
Pali Rohár248ef0a2012-10-29 07:54:01 +00001/*
2 * (C) Copyright 2012
3 * Ивайло Димитров <freemangordon@abv.bg>
4 *
5 * (C) Copyright 2011-2012
6 * Pali Rohár <pali.rohar@gmail.com>
7 *
8 * (C) Copyright 2010
9 * Alistair Buxton <a.j.buxton@gmail.com>
10 *
11 * Derived from Beagle Board and 3430 SDP code:
12 * (C) Copyright 2004-2008
13 * Texas Instruments, <www.ti.com>
14 *
15 * Author :
16 * Sunil Kumar <sunilsaini05@gmail.com>
17 * Shashi Ranjan <shashiranjanmca05@gmail.com>
18 *
19 * Richard Woodruff <r-woodruff2@ti.com>
20 * Syed Mohammed Khasim <khasim@ti.com>
21 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +020022 * SPDX-License-Identifier: GPL-2.0+
Pali Rohár248ef0a2012-10-29 07:54:01 +000023 */
24
25#include <common.h>
26#include <watchdog.h>
27#include <malloc.h>
28#include <twl4030.h>
29#include <i2c.h>
30#include <video_fb.h>
31#include <asm/io.h>
32#include <asm/setup.h>
33#include <asm/bitops.h>
34#include <asm/mach-types.h>
35#include <asm/arch/mux.h>
36#include <asm/arch/sys_proto.h>
37#include <asm/arch/mmc_host_def.h>
38
39#include "rx51.h"
40#include "tag_omap.h"
41
42DECLARE_GLOBAL_DATA_PTR;
43
44GraphicDevice gdev;
45
46const omap3_sysinfo sysinfo = {
47 DDR_STACKED,
48 "Nokia RX-51",
49 "OneNAND"
50};
51
52/* This structure contains default omap tags needed for booting Maemo 5 */
53static struct tag_omap omap[] = {
54 OMAP_TAG_UART_CONFIG(0x04),
55 OMAP_TAG_SERIAL_CONSOLE_CONFIG(0x03, 0x01C200),
56 OMAP_TAG_LCD_CONFIG("acx565akm", "internal", 90, 0x18),
57 OMAP_TAG_GPIO_SWITCH_CONFIG("cam_focus", 0x44, 0x1, 0x2, 0x0),
58 OMAP_TAG_GPIO_SWITCH_CONFIG("cam_launch", 0x45, 0x1, 0x2, 0x0),
59 OMAP_TAG_GPIO_SWITCH_CONFIG("cam_shutter", 0x6e, 0x1, 0x0, 0x0),
60 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_apeslpx", 0x46, 0x2, 0x2, 0x0),
61 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_bsi", 0x9d, 0x2, 0x2, 0x0),
62 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_en", 0x4a, 0x2, 0x2, 0x0),
63 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_rst", 0x4b, 0x6, 0x2, 0x0),
64 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_rst_rq", 0x49, 0x6, 0x2, 0x0),
65 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_wddis", 0x0d, 0x2, 0x2, 0x0),
66 OMAP_TAG_GPIO_SWITCH_CONFIG("headphone", 0xb1, 0x1, 0x1, 0x0),
67 OMAP_TAG_GPIO_SWITCH_CONFIG("kb_lock", 0x71, 0x1, 0x0, 0x0),
68 OMAP_TAG_GPIO_SWITCH_CONFIG("proximity", 0x59, 0x0, 0x0, 0x0),
69 OMAP_TAG_GPIO_SWITCH_CONFIG("sleep_ind", 0xa2, 0x2, 0x2, 0x0),
70 OMAP_TAG_GPIO_SWITCH_CONFIG("slide", GPIO_SLIDE, 0x0, 0x0, 0x0),
71 OMAP_TAG_WLAN_CX3110X_CONFIG(0x25, 0xff, 87, 42, -1),
72 OMAP_TAG_PARTITION_CONFIG(PART1_NAME, PART1_SIZE * PART1_MULL,
73 PART1_OFFS, PART1_MASK),
74 OMAP_TAG_PARTITION_CONFIG(PART2_NAME, PART2_SIZE * PART2_MULL,
75 PART2_OFFS, PART2_MASK),
76 OMAP_TAG_PARTITION_CONFIG(PART3_NAME, PART3_SIZE * PART3_MULL,
77 PART3_OFFS, PART3_MASK),
78 OMAP_TAG_PARTITION_CONFIG(PART4_NAME, PART4_SIZE * PART4_MULL,
79 PART4_OFFS, PART4_MASK),
80 OMAP_TAG_PARTITION_CONFIG(PART5_NAME, PART5_SIZE * PART5_MULL,
81 PART5_OFFS, PART5_MASK),
82 OMAP_TAG_PARTITION_CONFIG(PART6_NAME, PART6_SIZE * PART6_MULL,
83 PART6_OFFS, PART6_MASK),
84 OMAP_TAG_BOOT_REASON_CONFIG("pwr_key"),
85 OMAP_TAG_VERSION_STR_CONFIG("product", "RX-51"),
86 OMAP_TAG_VERSION_STR_CONFIG("hw-build", "2101"),
87 OMAP_TAG_VERSION_STR_CONFIG("nolo", "1.4.14"),
88 OMAP_TAG_VERSION_STR_CONFIG("boot-mode", "normal"),
89 { }
90};
91
92static char *boot_reason_ptr;
93static char *hw_build_ptr;
94static char *nolo_version_ptr;
95static char *boot_mode_ptr;
96
97/*
98 * Routine: init_omap_tags
99 * Description: Initialize pointers to values in tag_omap
100 */
101static void init_omap_tags(void)
102{
103 char *component;
104 char *version;
105 int i = 0;
106 while (omap[i].hdr.tag) {
107 switch (omap[i].hdr.tag) {
108 case OMAP_TAG_BOOT_REASON:
109 boot_reason_ptr = omap[i].u.boot_reason.reason_str;
110 break;
111 case OMAP_TAG_VERSION_STR:
112 component = omap[i].u.version.component;
113 version = omap[i].u.version.version;
114 if (strcmp(component, "hw-build") == 0)
115 hw_build_ptr = version;
116 else if (strcmp(component, "nolo") == 0)
117 nolo_version_ptr = version;
118 else if (strcmp(component, "boot-mode") == 0)
119 boot_mode_ptr = version;
120 break;
121 default:
122 break;
123 }
124 i++;
125 }
126}
127
128static void reuse_omap_atags(struct tag_omap *t)
129{
130 char *component;
131 char *version;
132 while (t->hdr.tag) {
133 switch (t->hdr.tag) {
134 case OMAP_TAG_BOOT_REASON:
135 memset(boot_reason_ptr, 0, 12);
136 strcpy(boot_reason_ptr, t->u.boot_reason.reason_str);
137 break;
138 case OMAP_TAG_VERSION_STR:
139 component = t->u.version.component;
140 version = t->u.version.version;
141 if (strcmp(component, "hw-build") == 0) {
142 memset(hw_build_ptr, 0, 12);
143 strcpy(hw_build_ptr, version);
144 } else if (strcmp(component, "nolo") == 0) {
145 memset(nolo_version_ptr, 0, 12);
146 strcpy(nolo_version_ptr, version);
147 } else if (strcmp(component, "boot-mode") == 0) {
148 memset(boot_mode_ptr, 0, 12);
149 strcpy(boot_mode_ptr, version);
150 }
151 break;
152 default:
153 break;
154 }
155 t = tag_omap_next(t);
156 }
157}
158
159/*
160 * Routine: reuse_atags
161 * Description: Reuse atags from previous bootloader.
162 * Reuse only only HW build, boot reason, boot mode and nolo
163 */
164static void reuse_atags(void)
165{
166 struct tag *t = (struct tag *)gd->bd->bi_boot_params;
167
168 /* First tag must be ATAG_CORE */
169 if (t->hdr.tag != ATAG_CORE)
170 return;
171
172 if (!boot_reason_ptr || !hw_build_ptr)
173 return;
174
175 /* Last tag must be ATAG_NONE */
176 while (t->hdr.tag != ATAG_NONE) {
177 switch (t->hdr.tag) {
178 case ATAG_REVISION:
179 memset(hw_build_ptr, 0, 12);
180 sprintf(hw_build_ptr, "%x", t->u.revision.rev);
181 break;
182 case ATAG_BOARD:
183 reuse_omap_atags((struct tag_omap *)&t->u);
184 break;
185 default:
186 break;
187 }
188 t = tag_next(t);
189 }
190}
191
192/*
193 * Routine: board_init
194 * Description: Early hardware init.
195 */
196int board_init(void)
197{
198 /* in SRAM or SDRAM, finish GPMC */
199 gpmc_init();
200 /* boot param addr */
201 gd->bd->bi_boot_params = OMAP34XX_SDRC_CS0 + 0x100;
202 return 0;
203}
204
205/*
206 * Routine: get_board_revision
207 * Description: Return board revision.
208 */
209u32 get_board_rev(void)
210{
211 return simple_strtol(hw_build_ptr, NULL, 16);
212}
213
214/*
215 * Routine: setup_board_tags
216 * Description: Append board specific boot tags.
217 */
218void setup_board_tags(struct tag **in_params)
219{
220 int setup_console_atag;
221 char *setup_boot_reason_atag;
222 char *setup_boot_mode_atag;
223 char *str;
224 int i;
225 int size;
226 int total_size;
227 struct tag *params;
228 struct tag_omap *t;
229
230 params = (struct tag *)gd->bd->bi_boot_params;
231
232 params->u.core.flags = 0x0;
233 params->u.core.pagesize = 0x1000;
234 params->u.core.rootdev = 0x0;
235
236 /* append omap atag only if env setup_omap_atag is set to 1 */
237 str = getenv("setup_omap_atag");
238 if (!str || str[0] != '1')
239 return;
240
241 str = getenv("setup_console_atag");
242 if (str && str[0] == '1')
243 setup_console_atag = 1;
244 else
245 setup_console_atag = 0;
246
247 setup_boot_reason_atag = getenv("setup_boot_reason_atag");
248 setup_boot_mode_atag = getenv("setup_boot_mode_atag");
249
250 params = *in_params;
251 t = (struct tag_omap *)&params->u;
252 total_size = sizeof(struct tag_header);
253
254 for (i = 0; omap[i].hdr.tag; i++) {
255
256 /* skip serial console tag */
257 if (!setup_console_atag &&
258 omap[i].hdr.tag == OMAP_TAG_SERIAL_CONSOLE)
259 continue;
260
261 size = omap[i].hdr.size + sizeof(struct tag_omap_header);
262 memcpy(t, &omap[i], size);
263
264 /* set uart tag to 0 - disable serial console */
265 if (!setup_console_atag && omap[i].hdr.tag == OMAP_TAG_UART)
266 t->u.uart.enabled_uarts = 0;
267
268 /* change boot reason */
269 if (setup_boot_reason_atag &&
270 omap[i].hdr.tag == OMAP_TAG_BOOT_REASON) {
271 memset(t->u.boot_reason.reason_str, 0, 12);
272 strcpy(t->u.boot_reason.reason_str,
273 setup_boot_reason_atag);
274 }
275
276 /* change boot mode */
277 if (setup_boot_mode_atag &&
278 omap[i].hdr.tag == OMAP_TAG_VERSION_STR &&
279 strcmp(omap[i].u.version.component, "boot-mode") == 0) {
280 memset(t->u.version.version, 0, 12);
281 strcpy(t->u.version.version, setup_boot_mode_atag);
282 }
283
284 total_size += size;
285 t = tag_omap_next(t);
286
287 }
288
289 params->hdr.tag = ATAG_BOARD;
290 params->hdr.size = total_size >> 2;
291 params = tag_next(params);
292
293 *in_params = params;
294}
295
296/*
297 * Routine: video_hw_init
298 * Description: Set up the GraphicDevice depending on sys_boot.
299 */
300void *video_hw_init(void)
301{
302 /* fill in Graphic Device */
303 gdev.frameAdrs = 0x8f9c0000;
304 gdev.winSizeX = 800;
305 gdev.winSizeY = 480;
306 gdev.gdfBytesPP = 2;
307 gdev.gdfIndex = GDF_16BIT_565RGB;
308 memset((void *)gdev.frameAdrs, 0, 0xbb800);
309 return (void *) &gdev;
310}
311
312/*
313 * Routine: twl4030_regulator_set_mode
314 * Description: Set twl4030 regulator mode over i2c powerbus.
315 */
316static void twl4030_regulator_set_mode(u8 id, u8 mode)
317{
318 u16 msg = MSG_SINGULAR(DEV_GRP_P1, id, mode);
Nishanth Menond26a1062013-03-26 05:20:49 +0000319 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
320 TWL4030_PM_MASTER_PB_WORD_MSB, msg >> 8);
321 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
322 TWL4030_PM_MASTER_PB_WORD_LSB, msg & 0xff);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000323}
324
325static void omap3_emu_romcode_call(u32 service_id, u32 *parameters)
326{
327 u32 i, num_params = *parameters;
328 u32 *sram_scratch_space = (u32 *)OMAP3_PUBLIC_SRAM_SCRATCH_AREA;
329
330 /*
331 * copy the parameters to an un-cached area to avoid coherency
332 * issues
333 */
334 for (i = 0; i < num_params; i++) {
335 __raw_writel(*parameters, sram_scratch_space);
336 parameters++;
337 sram_scratch_space++;
338 }
339
340 /* Now make the PPA call */
341 do_omap3_emu_romcode_call(service_id, OMAP3_PUBLIC_SRAM_SCRATCH_AREA);
342}
343
344/*
345 * Routine: omap3_update_aux_cr_secure_rx51
346 * Description: Modify the contents Auxiliary Control Register.
347 * Parameters:
348 * set_bits - bits to set in ACR
349 * clr_bits - bits to clear in ACR
350 */
351static void omap3_update_aux_cr_secure_rx51(u32 set_bits, u32 clear_bits)
352{
353 struct emu_hal_params_rx51 emu_romcode_params = { 0, };
354 u32 acr;
355
356 /* Read ACR */
357 asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r" (acr));
358 acr &= ~clear_bits;
359 acr |= set_bits;
360
361 emu_romcode_params.num_params = 2;
362 emu_romcode_params.param1 = acr;
363
364 omap3_emu_romcode_call(OMAP3_EMU_HAL_API_WRITE_ACR,
365 (u32 *)&emu_romcode_params);
366}
367
368/*
369 * Routine: misc_init_r
370 * Description: Configure board specific parts.
371 */
372int misc_init_r(void)
373{
374 char buf[12];
375 u8 state;
376
377 /* reset lp5523 led */
378 i2c_set_bus_num(1);
379 state = 0xff;
380 i2c_write(0x32, 0x3d, 1, &state, 1);
381 i2c_set_bus_num(0);
382
383 /* initialize twl4030 power managment */
384 twl4030_power_init();
385
386 /* set VSIM to 1.8V */
387 twl4030_pmrecv_vsel_cfg(TWL4030_PM_RECEIVER_VSIM_DEDICATED,
388 TWL4030_PM_RECEIVER_VSIM_VSEL_18,
389 TWL4030_PM_RECEIVER_VSIM_DEV_GRP,
390 TWL4030_PM_RECEIVER_DEV_GRP_P1);
391
392 /* store I2C access state */
Nishanth Menon5d9d6f72013-03-26 05:20:50 +0000393 twl4030_i2c_read_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
394 &state);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000395
396 /* enable I2C access to powerbus (needed for twl4030 regulator) */
Nishanth Menond26a1062013-03-26 05:20:49 +0000397 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
398 0x02);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000399
400 /* set VAUX3, VSIM and VMMC1 state to active - enable eMMC memory */
401 twl4030_regulator_set_mode(RES_VAUX3, RES_STATE_ACTIVE);
402 twl4030_regulator_set_mode(RES_VSIM, RES_STATE_ACTIVE);
403 twl4030_regulator_set_mode(RES_VMMC1, RES_STATE_ACTIVE);
404
405 /* restore I2C access state */
Nishanth Menond26a1062013-03-26 05:20:49 +0000406 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
407 state);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000408
409 /* set env variable attkernaddr for relocated kernel */
410 sprintf(buf, "%#x", KERNEL_ADDRESS);
411 setenv("attkernaddr", buf);
412
413 /* initialize omap tags */
414 init_omap_tags();
415
416 /* reuse atags from previous bootloader */
417 reuse_atags();
418
419 dieid_num_r();
420 print_cpuinfo();
421
422 /*
423 * Cortex-A8(r1p0..r1p2) errata 430973 workaround
424 * Set IBE bit in Auxiliary Control Register
Pali Rohár415b8042015-01-08 10:11:40 +0100425 *
426 * Call this routine only on real secure device
427 * Qemu does not implement secure PPA and crash
Pali Rohár248ef0a2012-10-29 07:54:01 +0000428 */
Pali Rohár415b8042015-01-08 10:11:40 +0100429 if (get_device_type() == HS_DEVICE)
430 omap3_update_aux_cr_secure_rx51(1 << 6, 0);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000431
432 return 0;
433}
434
435/*
436 * Routine: set_muxconf_regs
437 * Description: Setting up the configuration Mux registers specific to the
438 * hardware. Many pins need to be moved from protect to primary
439 * mode.
440 */
441void set_muxconf_regs(void)
442{
443 MUX_RX51();
444}
445
446static unsigned long int twl_wd_time; /* last time of watchdog reset */
447static unsigned long int twl_i2c_lock;
448
449/*
450 * Routine: hw_watchdog_reset
451 * Description: Reset timeout of twl4030 watchdog.
452 */
453void hw_watchdog_reset(void)
454{
455 u8 timeout = 0;
456
457 /* do not reset watchdog too often - max every 4s */
458 if (get_timer(twl_wd_time) < 4 * CONFIG_SYS_HZ)
459 return;
460
461 /* localy lock twl4030 i2c bus */
462 if (test_and_set_bit(0, &twl_i2c_lock))
463 return;
464
465 /* read actual watchdog timeout */
Nishanth Menon5d9d6f72013-03-26 05:20:50 +0000466 twl4030_i2c_read_u8(TWL4030_CHIP_PM_RECEIVER,
467 TWL4030_PM_RECEIVER_WATCHDOG_CFG, &timeout);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000468
469 /* timeout 0 means watchdog is disabled */
470 /* reset watchdog timeout to 31s (maximum) */
471 if (timeout != 0)
Nishanth Menond26a1062013-03-26 05:20:49 +0000472 twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER,
473 TWL4030_PM_RECEIVER_WATCHDOG_CFG, 31);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000474
475 /* store last watchdog reset time */
476 twl_wd_time = get_timer(0);
477
478 /* localy unlock twl4030 i2c bus */
479 test_and_clear_bit(0, &twl_i2c_lock);
480}
481
482/*
483 * TWL4030 keypad handler for cfb_console
484 */
485
486static const char keymap[] = {
487 /* normal */
488 'q', 'o', 'p', ',', '\b', 0, 'a', 's',
489 'w', 'd', 'f', 'g', 'h', 'j', 'k', 'l',
490 'e', '.', 0, '\r', 0, 'z', 'x', 'c',
491 'r', 'v', 'b', 'n', 'm', ' ', ' ', 0,
492 't', 0, 0, 0, 0, 0, 0, 0,
493 'y', 0, 0, 0, 0, 0, 0, 0,
494 'u', 0, 0, 0, 0, 0, 0, 0,
495 'i', 5, 6, 0, 0, 0, 0, 0,
496 /* fn */
497 '1', '9', '0', '=', '\b', 0, '*', '+',
498 '2', '#', '-', '_', '(', ')', '&', '!',
499 '3', '?', '^', '\r', 0, 156, '$', 238,
500 '4', '/', '\\', '"', '\'', '@', 0, '<',
501 '5', '|', '>', 0, 0, 0, 0, 0,
502 '6', 0, 0, 0, 0, 0, 0, 0,
503 '7', 0, 0, 0, 0, 0, 0, 0,
504 '8', 16, 17, 0, 0, 0, 0, 0,
505};
506
507static u8 keys[8];
508static u8 old_keys[8] = {0, 0, 0, 0, 0, 0, 0, 0};
509#define KEYBUF_SIZE 32
510static u8 keybuf[KEYBUF_SIZE];
511static u8 keybuf_head;
512static u8 keybuf_tail;
513
514/*
515 * Routine: rx51_kp_init
516 * Description: Initialize HW keyboard.
517 */
518int rx51_kp_init(void)
519{
520 int ret = 0;
521 u8 ctrl;
Nishanth Menon5d9d6f72013-03-26 05:20:50 +0000522 ret = twl4030_i2c_read_u8(TWL4030_CHIP_KEYPAD,
523 TWL4030_KEYPAD_KEYP_CTRL_REG, &ctrl);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000524
525 if (ret)
526 return ret;
527
528 /* turn on keyboard and use hardware scanning */
529 ctrl |= TWL4030_KEYPAD_CTRL_KBD_ON;
530 ctrl |= TWL4030_KEYPAD_CTRL_SOFT_NRST;
531 ctrl |= TWL4030_KEYPAD_CTRL_SOFTMODEN;
Nishanth Menond26a1062013-03-26 05:20:49 +0000532 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
533 TWL4030_KEYPAD_KEYP_CTRL_REG, ctrl);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000534 /* enable key event status */
Nishanth Menond26a1062013-03-26 05:20:49 +0000535 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
536 TWL4030_KEYPAD_KEYP_IMR1, 0xfe);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000537 /* enable interrupt generation on rising and falling */
538 /* this is a workaround for qemu twl4030 emulation */
Nishanth Menond26a1062013-03-26 05:20:49 +0000539 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
540 TWL4030_KEYPAD_KEYP_EDR, 0x57);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000541 /* enable ISR clear on read */
Nishanth Menond26a1062013-03-26 05:20:49 +0000542 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
543 TWL4030_KEYPAD_KEYP_SIH_CTRL, 0x05);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000544 return 0;
545}
546
547static void rx51_kp_fill(u8 k, u8 mods)
548{
549 /* check if some cursor key without meta fn key was pressed */
550 if (!(mods & 2) && (k == 18 || k == 31 || k == 33 || k == 34)) {
551 keybuf[keybuf_tail++] = '\e';
552 keybuf_tail %= KEYBUF_SIZE;
553 keybuf[keybuf_tail++] = '[';
554 keybuf_tail %= KEYBUF_SIZE;
555 if (k == 18) /* up */
556 keybuf[keybuf_tail++] = 'A';
557 else if (k == 31) /* left */
558 keybuf[keybuf_tail++] = 'D';
559 else if (k == 33) /* down */
560 keybuf[keybuf_tail++] = 'B';
561 else if (k == 34) /* right */
562 keybuf[keybuf_tail++] = 'C';
563 keybuf_tail %= KEYBUF_SIZE;
564 return;
565 }
566
567 if (mods & 2) { /* fn meta key was pressed */
568 k = keymap[k+64];
569 } else {
570 k = keymap[k];
571 if (mods & 1) { /* ctrl key was pressed */
572 if (k >= 'a' && k <= 'z')
573 k -= 'a' - 1;
574 }
575 if (mods & 4) { /* shift key was pressed */
576 if (k >= 'a' && k <= 'z')
577 k += 'A' - 'a';
578 else if (k == '.')
579 k = ':';
580 else if (k == ',')
581 k = ';';
582 }
583 }
584 keybuf[keybuf_tail++] = k;
585 keybuf_tail %= KEYBUF_SIZE;
586}
587
588/*
589 * Routine: rx51_kp_tstc
590 * Description: Test if key was pressed (from buffer).
591 */
Simon Glass0d1e1f72014-07-23 06:54:59 -0600592int rx51_kp_tstc(struct stdio_dev *sdev)
Pali Rohár248ef0a2012-10-29 07:54:01 +0000593{
594 u8 c, r, dk, i;
595 u8 intr;
596 u8 mods;
597
598 /* localy lock twl4030 i2c bus */
599 if (test_and_set_bit(0, &twl_i2c_lock))
600 return 0;
601
602 /* twl4030 remembers up to 2 events */
603 for (i = 0; i < 2; i++) {
604
605 /* check interrupt register for events */
Nishanth Menon5d9d6f72013-03-26 05:20:50 +0000606 twl4030_i2c_read_u8(TWL4030_CHIP_KEYPAD,
607 TWL4030_KEYPAD_KEYP_ISR1 + (2 * i), &intr);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000608
609 /* no event */
610 if (!(intr&1))
611 continue;
612
613 /* read the key state */
614 i2c_read(TWL4030_CHIP_KEYPAD,
615 TWL4030_KEYPAD_FULL_CODE_7_0, 1, keys, 8);
616
617 /* cut out modifier keys from the keystate */
618 mods = keys[4] >> 4;
619 keys[4] &= 0x0f;
620
621 for (c = 0; c < 8; c++) {
622
623 /* get newly pressed keys only */
624 dk = ((keys[c] ^ old_keys[c])&keys[c]);
625 old_keys[c] = keys[c];
626
627 /* fill the keybuf */
628 for (r = 0; r < 8; r++) {
629 if (dk&1)
630 rx51_kp_fill((c*8)+r, mods);
631 dk = dk >> 1;
632 }
633
634 }
635
636 }
637
638 /* localy unlock twl4030 i2c bus */
639 test_and_clear_bit(0, &twl_i2c_lock);
640
641 return (KEYBUF_SIZE + keybuf_tail - keybuf_head)%KEYBUF_SIZE;
642}
643
644/*
645 * Routine: rx51_kp_getc
646 * Description: Get last pressed key (from buffer).
647 */
Simon Glass0d1e1f72014-07-23 06:54:59 -0600648int rx51_kp_getc(struct stdio_dev *sdev)
Pali Rohár248ef0a2012-10-29 07:54:01 +0000649{
650 keybuf_head %= KEYBUF_SIZE;
Simon Glass0d1e1f72014-07-23 06:54:59 -0600651 while (!rx51_kp_tstc(sdev))
Pali Rohár248ef0a2012-10-29 07:54:01 +0000652 WATCHDOG_RESET();
653 return keybuf[keybuf_head++];
654}
655
656/*
657 * Routine: board_mmc_init
658 * Description: Initialize mmc devices.
659 */
660int board_mmc_init(bd_t *bis)
661{
Nikita Kiryanov4be9dbc2012-12-03 02:19:47 +0000662 omap_mmc_init(0, 0, 0, -1, -1);
663 omap_mmc_init(1, 0, 0, -1, -1);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000664 return 0;
665}
Paul Kocialkowski69559892014-11-08 20:55:47 +0100666
667void board_mmc_power_init(void)
668{
669 twl4030_power_mmc_init(0);
670 twl4030_power_mmc_init(1);
671}