env: Move env_set() to env.h
[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 <env.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
42 DECLARE_GLOBAL_DATA_PTR;
43
44 GraphicDevice gdev;
45
46 const 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 */
53 static 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
92 static char *boot_reason_ptr;
93 static char *hw_build_ptr;
94 static char *nolo_version_ptr;
95 static char *boot_mode_ptr;
96
97 /*
98  * Routine: init_omap_tags
99  * Description: Initialize pointers to values in tag_omap
100  */
101 static 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
128 static 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  */
164 static 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  */
196 int 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  */
209 u32 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  */
218 void 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 = env_get("setup_omap_atag");
238         if (!str || str[0] != '1')
239                 return;
240
241         str = env_get("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 = env_get("setup_boot_reason_atag");
248         setup_boot_mode_atag = env_get("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  */
300 void *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  */
316 static void twl4030_regulator_set_mode(u8 id, u8 mode)
317 {
318         u16 msg = MSG_SINGULAR(DEV_GRP_P1, id, mode);
319         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);
323 }
324
325 static 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 void omap3_set_aux_cr_secure(u32 acr)
345 {
346         struct emu_hal_params_rx51 emu_romcode_params = { 0, };
347
348         emu_romcode_params.num_params = 2;
349         emu_romcode_params.param1 = acr;
350
351         omap3_emu_romcode_call(OMAP3_EMU_HAL_API_WRITE_ACR,
352                                (u32 *)&emu_romcode_params);
353 }
354
355 /*
356  * Routine: omap3_update_aux_cr_secure_rx51
357  * Description: Modify the contents Auxiliary Control Register.
358  * Parameters:
359  *   set_bits - bits to set in ACR
360  *   clr_bits - bits to clear in ACR
361  */
362 static void omap3_update_aux_cr_secure_rx51(u32 set_bits, u32 clear_bits)
363 {
364         u32 acr;
365
366         /* Read ACR */
367         asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r" (acr));
368         acr &= ~clear_bits;
369         acr |= set_bits;
370         omap3_set_aux_cr_secure(acr);
371 }
372
373 /*
374  * Routine: misc_init_r
375  * Description: Configure board specific parts.
376  */
377 int misc_init_r(void)
378 {
379         char buf[12];
380         u8 state;
381
382         /* reset lp5523 led */
383         i2c_set_bus_num(1);
384         state = 0xff;
385         i2c_write(0x32, 0x3d, 1, &state, 1);
386         i2c_set_bus_num(0);
387
388         /* initialize twl4030 power managment */
389         twl4030_power_init();
390
391         /* set VSIM to 1.8V */
392         twl4030_pmrecv_vsel_cfg(TWL4030_PM_RECEIVER_VSIM_DEDICATED,
393                                 TWL4030_PM_RECEIVER_VSIM_VSEL_18,
394                                 TWL4030_PM_RECEIVER_VSIM_DEV_GRP,
395                                 TWL4030_PM_RECEIVER_DEV_GRP_P1);
396
397         /* store I2C access state */
398         twl4030_i2c_read_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
399                             &state);
400
401         /* enable I2C access to powerbus (needed for twl4030 regulator) */
402         twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
403                              0x02);
404
405         /* set VAUX3, VSIM and VMMC1 state to active - enable eMMC memory */
406         twl4030_regulator_set_mode(RES_VAUX3, RES_STATE_ACTIVE);
407         twl4030_regulator_set_mode(RES_VSIM, RES_STATE_ACTIVE);
408         twl4030_regulator_set_mode(RES_VMMC1, RES_STATE_ACTIVE);
409
410         /* restore I2C access state */
411         twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
412                              state);
413
414         /* set env variable attkernaddr for relocated kernel */
415         sprintf(buf, "%#x", KERNEL_ADDRESS);
416         env_set("attkernaddr", buf);
417
418         /* initialize omap tags */
419         init_omap_tags();
420
421         /* reuse atags from previous bootloader */
422         reuse_atags();
423
424         omap_die_id_display();
425         print_cpuinfo();
426
427         /*
428          * Cortex-A8(r1p0..r1p2) errata 430973 workaround
429          * Set IBE bit in Auxiliary Control Register
430          *
431          * Call this routine only on real secure device
432          * Qemu does not implement secure PPA and crash
433          */
434         if (get_device_type() == HS_DEVICE)
435                 omap3_update_aux_cr_secure_rx51(1 << 6, 0);
436
437         return 0;
438 }
439
440 /*
441  * Routine: set_muxconf_regs
442  * Description: Setting up the configuration Mux registers specific to the
443  *              hardware. Many pins need to be moved from protect to primary
444  *              mode.
445  */
446 void set_muxconf_regs(void)
447 {
448         MUX_RX51();
449 }
450
451 static unsigned long int twl_wd_time; /* last time of watchdog reset */
452 static unsigned long int twl_i2c_lock;
453
454 /*
455  * Routine: hw_watchdog_reset
456  * Description: Reset timeout of twl4030 watchdog.
457  */
458 void hw_watchdog_reset(void)
459 {
460         u8 timeout = 0;
461
462         /* do not reset watchdog too often - max every 4s */
463         if (get_timer(twl_wd_time) < 4 * CONFIG_SYS_HZ)
464                 return;
465
466         /* localy lock twl4030 i2c bus */
467         if (test_and_set_bit(0, &twl_i2c_lock))
468                 return;
469
470         /* read actual watchdog timeout */
471         twl4030_i2c_read_u8(TWL4030_CHIP_PM_RECEIVER,
472                             TWL4030_PM_RECEIVER_WATCHDOG_CFG, &timeout);
473
474         /* timeout 0 means watchdog is disabled */
475         /* reset watchdog timeout to 31s (maximum) */
476         if (timeout != 0)
477                 twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER,
478                                      TWL4030_PM_RECEIVER_WATCHDOG_CFG, 31);
479
480         /* store last watchdog reset time */
481         twl_wd_time = get_timer(0);
482
483         /* localy unlock twl4030 i2c bus */
484         test_and_clear_bit(0, &twl_i2c_lock);
485 }
486
487 /*
488  * TWL4030 keypad handler for cfb_console
489  */
490
491 static const char keymap[] = {
492         /* normal */
493         'q',  'o',  'p',  ',', '\b',    0,  'a',  's',
494         'w',  'd',  'f',  'g',  'h',  'j',  'k',  'l',
495         'e',  '.',    0,  '\r',   0,  'z',  'x',  'c',
496         'r',  'v',  'b',  'n',  'm',  ' ',  ' ',    0,
497         't',    0,    0,    0,    0,    0,    0,    0,
498         'y',    0,    0,    0,    0,    0,    0,    0,
499         'u',    0,    0,    0,    0,    0,    0,    0,
500         'i',    5,    6,    0,    0,    0,    0,    0,
501         /* fn */
502         '1',  '9',  '0',  '=', '\b',    0,  '*',  '+',
503         '2',  '#',  '-',  '_',  '(',  ')',  '&',  '!',
504         '3',  '?',  '^', '\r',    0,  156,  '$',  238,
505         '4',  '/', '\\',  '"', '\'',  '@',    0,  '<',
506         '5',  '|',  '>',    0,    0,    0,    0,    0,
507         '6',    0,    0,    0,    0,    0,    0,    0,
508         '7',    0,    0,    0,    0,    0,    0,    0,
509         '8',   16,   17,    0,    0,    0,    0,    0,
510 };
511
512 static u8 keys[8];
513 static u8 old_keys[8] = {0, 0, 0, 0, 0, 0, 0, 0};
514 #define KEYBUF_SIZE 32
515 static u8 keybuf[KEYBUF_SIZE];
516 static u8 keybuf_head;
517 static u8 keybuf_tail;
518
519 /*
520  * Routine: rx51_kp_init
521  * Description: Initialize HW keyboard.
522  */
523 int rx51_kp_init(void)
524 {
525         int ret = 0;
526         u8 ctrl;
527         ret = twl4030_i2c_read_u8(TWL4030_CHIP_KEYPAD,
528                                   TWL4030_KEYPAD_KEYP_CTRL_REG, &ctrl);
529
530         if (ret)
531                 return ret;
532
533         /* turn on keyboard and use hardware scanning */
534         ctrl |= TWL4030_KEYPAD_CTRL_KBD_ON;
535         ctrl |= TWL4030_KEYPAD_CTRL_SOFT_NRST;
536         ctrl |= TWL4030_KEYPAD_CTRL_SOFTMODEN;
537         ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
538                                     TWL4030_KEYPAD_KEYP_CTRL_REG, ctrl);
539         /* enable key event status */
540         ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
541                                     TWL4030_KEYPAD_KEYP_IMR1, 0xfe);
542         /* enable interrupt generation on rising and falling */
543         /* this is a workaround for qemu twl4030 emulation */
544         ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
545                                     TWL4030_KEYPAD_KEYP_EDR, 0x57);
546         /* enable ISR clear on read */
547         ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
548                                     TWL4030_KEYPAD_KEYP_SIH_CTRL, 0x05);
549         return 0;
550 }
551
552 static void rx51_kp_fill(u8 k, u8 mods)
553 {
554         /* check if some cursor key without meta fn key was pressed */
555         if (!(mods & 2) && (k == 18 || k == 31 || k == 33 || k == 34)) {
556                 keybuf[keybuf_tail++] = '\e';
557                 keybuf_tail %= KEYBUF_SIZE;
558                 keybuf[keybuf_tail++] = '[';
559                 keybuf_tail %= KEYBUF_SIZE;
560                 if (k == 18) /* up */
561                         keybuf[keybuf_tail++] = 'A';
562                 else if (k == 31) /* left */
563                         keybuf[keybuf_tail++] = 'D';
564                 else if (k == 33) /* down */
565                         keybuf[keybuf_tail++] = 'B';
566                 else if (k == 34) /* right */
567                         keybuf[keybuf_tail++] = 'C';
568                 keybuf_tail %= KEYBUF_SIZE;
569                 return;
570         }
571
572         if (mods & 2) { /* fn meta key was pressed */
573                 k = keymap[k+64];
574         } else {
575                 k = keymap[k];
576                 if (mods & 1) { /* ctrl key was pressed */
577                         if (k >= 'a' && k <= 'z')
578                                 k -= 'a' - 1;
579                 }
580                 if (mods & 4) { /* shift key was pressed */
581                         if (k >= 'a' && k <= 'z')
582                                 k += 'A' - 'a';
583                         else if (k == '.')
584                                 k = ':';
585                         else if (k == ',')
586                                 k = ';';
587                 }
588         }
589         keybuf[keybuf_tail++] = k;
590         keybuf_tail %= KEYBUF_SIZE;
591 }
592
593 /*
594  * Routine: rx51_kp_tstc
595  * Description: Test if key was pressed (from buffer).
596  */
597 int rx51_kp_tstc(struct stdio_dev *sdev)
598 {
599         u8 c, r, dk, i;
600         u8 intr;
601         u8 mods;
602
603         /* localy lock twl4030 i2c bus */
604         if (test_and_set_bit(0, &twl_i2c_lock))
605                 return 0;
606
607         /* twl4030 remembers up to 2 events */
608         for (i = 0; i < 2; i++) {
609
610                 /* check interrupt register for events */
611                 twl4030_i2c_read_u8(TWL4030_CHIP_KEYPAD,
612                                     TWL4030_KEYPAD_KEYP_ISR1 + (2 * i), &intr);
613
614                 /* no event */
615                 if (!(intr&1))
616                         continue;
617
618                 /* read the key state */
619                 i2c_read(TWL4030_CHIP_KEYPAD,
620                         TWL4030_KEYPAD_FULL_CODE_7_0, 1, keys, 8);
621
622                 /* cut out modifier keys from the keystate */
623                 mods = keys[4] >> 4;
624                 keys[4] &= 0x0f;
625
626                 for (c = 0; c < 8; c++) {
627
628                         /* get newly pressed keys only */
629                         dk = ((keys[c] ^ old_keys[c])&keys[c]);
630                         old_keys[c] = keys[c];
631
632                         /* fill the keybuf */
633                         for (r = 0; r < 8; r++) {
634                                 if (dk&1)
635                                         rx51_kp_fill((c*8)+r, mods);
636                                 dk = dk >> 1;
637                         }
638
639                 }
640
641         }
642
643         /* localy unlock twl4030 i2c bus */
644         test_and_clear_bit(0, &twl_i2c_lock);
645
646         return (KEYBUF_SIZE + keybuf_tail - keybuf_head)%KEYBUF_SIZE;
647 }
648
649 /*
650  * Routine: rx51_kp_getc
651  * Description: Get last pressed key (from buffer).
652  */
653 int rx51_kp_getc(struct stdio_dev *sdev)
654 {
655         keybuf_head %= KEYBUF_SIZE;
656         while (!rx51_kp_tstc(sdev))
657                 WATCHDOG_RESET();
658         return keybuf[keybuf_head++];
659 }
660
661 /*
662  * Routine: board_mmc_init
663  * Description: Initialize mmc devices.
664  */
665 int board_mmc_init(bd_t *bis)
666 {
667         omap_mmc_init(0, 0, 0, -1, -1);
668         omap_mmc_init(1, 0, 0, -1, -1);
669         return 0;
670 }
671
672 void board_mmc_power_init(void)
673 {
674         twl4030_power_mmc_init(0);
675         twl4030_power_mmc_init(1);
676 }