uboot/board/nokia/rx51/rx51.c
<<
>>
Prefs
   1/*
   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 *
  22 * SPDX-License-Identifier:     GPL-2.0+
  23 */
  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);
 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
 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
 344void 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 */
 362static 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 */
 377int 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        setenv("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 */
 446void set_muxconf_regs(void)
 447{
 448        MUX_RX51();
 449}
 450
 451static unsigned long int twl_wd_time; /* last time of watchdog reset */
 452static unsigned long int twl_i2c_lock;
 453
 454/*
 455 * Routine: hw_watchdog_reset
 456 * Description: Reset timeout of twl4030 watchdog.
 457 */
 458void 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
 491static 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
 512static u8 keys[8];
 513static u8 old_keys[8] = {0, 0, 0, 0, 0, 0, 0, 0};
 514#define KEYBUF_SIZE 32
 515static u8 keybuf[KEYBUF_SIZE];
 516static u8 keybuf_head;
 517static u8 keybuf_tail;
 518
 519/*
 520 * Routine: rx51_kp_init
 521 * Description: Initialize HW keyboard.
 522 */
 523int 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
 552static 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 */
 597int 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 */
 653int 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 */
 665int 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
 672void board_mmc_power_init(void)
 673{
 674        twl4030_power_mmc_init(0);
 675        twl4030_power_mmc_init(1);
 676}
 677