uboot/board/nokia/rx51/rx51.c
<<
>>
Prefs
   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
  41DECLARE_GLOBAL_DATA_PTR;
  42
  43GraphicDevice gdev;
  44
  45const 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 */
  52static 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
  91static char *boot_reason_ptr;
  92static char *hw_build_ptr;
  93static char *nolo_version_ptr;
  94static char *boot_mode_ptr;
  95
  96/*
  97 * Routine: init_omap_tags
  98 * Description: Initialize pointers to values in tag_omap
  99 */
 100static 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
 127static 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 */
 163static 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 */
 195int 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 */
 208u32 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 */
 217void 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 */
 299void *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 */
 315static 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
 324static 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
 343void 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 */
 361static 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 */
 376int 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 */
 445void set_muxconf_regs(void)
 446{
 447        MUX_RX51();
 448}
 449
 450static unsigned long int twl_wd_time; /* last time of watchdog reset */
 451static unsigned long int twl_i2c_lock;
 452
 453/*
 454 * Routine: hw_watchdog_reset
 455 * Description: Reset timeout of twl4030 watchdog.
 456 */
 457void 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
 490static 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
 511static u8 keys[8];
 512static u8 old_keys[8] = {0, 0, 0, 0, 0, 0, 0, 0};
 513#define KEYBUF_SIZE 32
 514static u8 keybuf[KEYBUF_SIZE];
 515static u8 keybuf_head;
 516static u8 keybuf_tail;
 517
 518/*
 519 * Routine: rx51_kp_init
 520 * Description: Initialize HW keyboard.
 521 */
 522int 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
 551static 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 */
 596int 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 */
 652int 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 */
 664int 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
 671void board_mmc_power_init(void)
 672{
 673        twl4030_power_mmc_init(0);
 674        twl4030_power_mmc_init(1);
 675}
 676