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