blob: a282fe68a610f498ff37937cffa6281ab17081d2 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Pali Roháred407be2012-10-29 07:54:01 +00002/*
3 * (C) Copyright 2012
4 * Ивайло Димитров <freemangordon@abv.bg>
5 *
6 * (C) Copyright 2011-2012
Pali Rohár53086652020-04-01 00:35:08 +02007 * Pali Rohár <pali@kernel.org>
Pali Roháred407be2012-10-29 07:54:01 +00008 *
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>
Pali Roháred407be2012-10-29 07:54:01 +000022 */
23
24#include <common.h>
Simon Glass9fb625c2019-08-01 09:46:51 -060025#include <env.h>
Pali Roháred407be2012-10-29 07:54:01 +000026#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),
Pali Rohárf5cfdbf2020-04-01 00:35:13 +020072 OMAP_TAG_PARTITION_CONFIG("bootloader", 128 * 1024, 0x00000000, 0x00000003),
73 OMAP_TAG_PARTITION_CONFIG("config", 384 * 1024, 0x00020000, 0x00000000),
74 OMAP_TAG_PARTITION_CONFIG("log", 256 * 1024, 0x00080000, 0x00000000),
75 OMAP_TAG_PARTITION_CONFIG("kernel", 2 * 1024*1024, 0x000c0000, 0x00000000),
76 OMAP_TAG_PARTITION_CONFIG("initfs", 2 * 1024*1024, 0x002c0000, 0x00000000),
77 OMAP_TAG_PARTITION_CONFIG("rootfs", 257280 * 1024, 0x004c0000, 0x00000000),
Pali Roháred407be2012-10-29 07:54:01 +000078 OMAP_TAG_BOOT_REASON_CONFIG("pwr_key"),
79 OMAP_TAG_VERSION_STR_CONFIG("product", "RX-51"),
80 OMAP_TAG_VERSION_STR_CONFIG("hw-build", "2101"),
81 OMAP_TAG_VERSION_STR_CONFIG("nolo", "1.4.14"),
82 OMAP_TAG_VERSION_STR_CONFIG("boot-mode", "normal"),
83 { }
84};
85
86static char *boot_reason_ptr;
87static char *hw_build_ptr;
88static char *nolo_version_ptr;
89static char *boot_mode_ptr;
Pali Rohárb5f7cf52020-04-01 00:35:14 +020090static int serial_was_console_enabled;
Pali Roháred407be2012-10-29 07:54:01 +000091
92/*
93 * Routine: init_omap_tags
94 * Description: Initialize pointers to values in tag_omap
95 */
96static void init_omap_tags(void)
97{
98 char *component;
99 char *version;
100 int i = 0;
101 while (omap[i].hdr.tag) {
102 switch (omap[i].hdr.tag) {
103 case OMAP_TAG_BOOT_REASON:
104 boot_reason_ptr = omap[i].u.boot_reason.reason_str;
105 break;
106 case OMAP_TAG_VERSION_STR:
107 component = omap[i].u.version.component;
108 version = omap[i].u.version.version;
109 if (strcmp(component, "hw-build") == 0)
110 hw_build_ptr = version;
111 else if (strcmp(component, "nolo") == 0)
112 nolo_version_ptr = version;
113 else if (strcmp(component, "boot-mode") == 0)
114 boot_mode_ptr = version;
115 break;
116 default:
117 break;
118 }
119 i++;
120 }
121}
122
123static void reuse_omap_atags(struct tag_omap *t)
124{
125 char *component;
126 char *version;
127 while (t->hdr.tag) {
128 switch (t->hdr.tag) {
129 case OMAP_TAG_BOOT_REASON:
130 memset(boot_reason_ptr, 0, 12);
131 strcpy(boot_reason_ptr, t->u.boot_reason.reason_str);
132 break;
133 case OMAP_TAG_VERSION_STR:
134 component = t->u.version.component;
135 version = t->u.version.version;
136 if (strcmp(component, "hw-build") == 0) {
137 memset(hw_build_ptr, 0, 12);
138 strcpy(hw_build_ptr, version);
139 } else if (strcmp(component, "nolo") == 0) {
140 memset(nolo_version_ptr, 0, 12);
141 strcpy(nolo_version_ptr, version);
142 } else if (strcmp(component, "boot-mode") == 0) {
143 memset(boot_mode_ptr, 0, 12);
144 strcpy(boot_mode_ptr, version);
145 }
146 break;
Pali Rohárb5f7cf52020-04-01 00:35:14 +0200147 case OMAP_TAG_UART:
148 if (!t->u.uart.enabled_uarts)
149 serial_was_console_enabled = 1;
150 break;
151 case OMAP_TAG_SERIAL_CONSOLE:
152 serial_was_console_enabled = 1;
153 break;
Pali Roháred407be2012-10-29 07:54:01 +0000154 default:
155 break;
156 }
157 t = tag_omap_next(t);
158 }
159}
160
161/*
162 * Routine: reuse_atags
163 * Description: Reuse atags from previous bootloader.
164 * Reuse only only HW build, boot reason, boot mode and nolo
165 */
166static void reuse_atags(void)
167{
168 struct tag *t = (struct tag *)gd->bd->bi_boot_params;
169
170 /* First tag must be ATAG_CORE */
171 if (t->hdr.tag != ATAG_CORE)
172 return;
173
174 if (!boot_reason_ptr || !hw_build_ptr)
175 return;
176
177 /* Last tag must be ATAG_NONE */
178 while (t->hdr.tag != ATAG_NONE) {
179 switch (t->hdr.tag) {
180 case ATAG_REVISION:
181 memset(hw_build_ptr, 0, 12);
182 sprintf(hw_build_ptr, "%x", t->u.revision.rev);
183 break;
184 case ATAG_BOARD:
185 reuse_omap_atags((struct tag_omap *)&t->u);
186 break;
187 default:
188 break;
189 }
190 t = tag_next(t);
191 }
192}
193
194/*
195 * Routine: board_init
196 * Description: Early hardware init.
197 */
198int board_init(void)
199{
200 /* in SRAM or SDRAM, finish GPMC */
201 gpmc_init();
202 /* boot param addr */
203 gd->bd->bi_boot_params = OMAP34XX_SDRC_CS0 + 0x100;
204 return 0;
205}
206
207/*
208 * Routine: get_board_revision
209 * Description: Return board revision.
210 */
211u32 get_board_rev(void)
212{
213 return simple_strtol(hw_build_ptr, NULL, 16);
214}
215
216/*
217 * Routine: setup_board_tags
218 * Description: Append board specific boot tags.
219 */
220void setup_board_tags(struct tag **in_params)
221{
222 int setup_console_atag;
223 char *setup_boot_reason_atag;
224 char *setup_boot_mode_atag;
225 char *str;
226 int i;
227 int size;
228 int total_size;
229 struct tag *params;
230 struct tag_omap *t;
231
232 params = (struct tag *)gd->bd->bi_boot_params;
233
234 params->u.core.flags = 0x0;
235 params->u.core.pagesize = 0x1000;
236 params->u.core.rootdev = 0x0;
237
238 /* append omap atag only if env setup_omap_atag is set to 1 */
Simon Glass00caae62017-08-03 12:22:12 -0600239 str = env_get("setup_omap_atag");
Pali Roháred407be2012-10-29 07:54:01 +0000240 if (!str || str[0] != '1')
241 return;
242
Simon Glass00caae62017-08-03 12:22:12 -0600243 str = env_get("setup_console_atag");
Pali Rohárb5f7cf52020-04-01 00:35:14 +0200244 if (str && str[0]) {
245 if (str[0] == '1')
246 setup_console_atag = 1;
247 else
248 setup_console_atag = 0;
249 } else {
250 if (serial_was_console_enabled)
251 setup_console_atag = 1;
252 else
253 setup_console_atag = 0;
254 }
Pali Roháred407be2012-10-29 07:54:01 +0000255
Simon Glass00caae62017-08-03 12:22:12 -0600256 setup_boot_reason_atag = env_get("setup_boot_reason_atag");
257 setup_boot_mode_atag = env_get("setup_boot_mode_atag");
Pali Roháred407be2012-10-29 07:54:01 +0000258
259 params = *in_params;
260 t = (struct tag_omap *)&params->u;
261 total_size = sizeof(struct tag_header);
262
263 for (i = 0; omap[i].hdr.tag; i++) {
264
265 /* skip serial console tag */
266 if (!setup_console_atag &&
267 omap[i].hdr.tag == OMAP_TAG_SERIAL_CONSOLE)
268 continue;
269
270 size = omap[i].hdr.size + sizeof(struct tag_omap_header);
271 memcpy(t, &omap[i], size);
272
273 /* set uart tag to 0 - disable serial console */
274 if (!setup_console_atag && omap[i].hdr.tag == OMAP_TAG_UART)
275 t->u.uart.enabled_uarts = 0;
276
277 /* change boot reason */
278 if (setup_boot_reason_atag &&
279 omap[i].hdr.tag == OMAP_TAG_BOOT_REASON) {
280 memset(t->u.boot_reason.reason_str, 0, 12);
281 strcpy(t->u.boot_reason.reason_str,
282 setup_boot_reason_atag);
283 }
284
285 /* change boot mode */
286 if (setup_boot_mode_atag &&
287 omap[i].hdr.tag == OMAP_TAG_VERSION_STR &&
288 strcmp(omap[i].u.version.component, "boot-mode") == 0) {
289 memset(t->u.version.version, 0, 12);
290 strcpy(t->u.version.version, setup_boot_mode_atag);
291 }
292
293 total_size += size;
294 t = tag_omap_next(t);
295
296 }
297
298 params->hdr.tag = ATAG_BOARD;
299 params->hdr.size = total_size >> 2;
300 params = tag_next(params);
301
302 *in_params = params;
303}
304
305/*
306 * Routine: video_hw_init
307 * Description: Set up the GraphicDevice depending on sys_boot.
308 */
309void *video_hw_init(void)
310{
311 /* fill in Graphic Device */
312 gdev.frameAdrs = 0x8f9c0000;
313 gdev.winSizeX = 800;
314 gdev.winSizeY = 480;
315 gdev.gdfBytesPP = 2;
316 gdev.gdfIndex = GDF_16BIT_565RGB;
317 memset((void *)gdev.frameAdrs, 0, 0xbb800);
318 return (void *) &gdev;
319}
320
321/*
322 * Routine: twl4030_regulator_set_mode
323 * Description: Set twl4030 regulator mode over i2c powerbus.
324 */
325static void twl4030_regulator_set_mode(u8 id, u8 mode)
326{
327 u16 msg = MSG_SINGULAR(DEV_GRP_P1, id, mode);
Nishanth Menon0208aaf2013-03-26 05:20:49 +0000328 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
329 TWL4030_PM_MASTER_PB_WORD_MSB, msg >> 8);
330 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
331 TWL4030_PM_MASTER_PB_WORD_LSB, msg & 0xff);
Pali Roháred407be2012-10-29 07:54:01 +0000332}
333
334static void omap3_emu_romcode_call(u32 service_id, u32 *parameters)
335{
336 u32 i, num_params = *parameters;
337 u32 *sram_scratch_space = (u32 *)OMAP3_PUBLIC_SRAM_SCRATCH_AREA;
338
339 /*
340 * copy the parameters to an un-cached area to avoid coherency
341 * issues
342 */
343 for (i = 0; i < num_params; i++) {
344 __raw_writel(*parameters, sram_scratch_space);
345 parameters++;
346 sram_scratch_space++;
347 }
348
349 /* Now make the PPA call */
350 do_omap3_emu_romcode_call(service_id, OMAP3_PUBLIC_SRAM_SCRATCH_AREA);
351}
352
Nishanth Menoncdef0b32015-03-09 17:12:09 -0500353void omap3_set_aux_cr_secure(u32 acr)
354{
355 struct emu_hal_params_rx51 emu_romcode_params = { 0, };
356
357 emu_romcode_params.num_params = 2;
358 emu_romcode_params.param1 = acr;
359
360 omap3_emu_romcode_call(OMAP3_EMU_HAL_API_WRITE_ACR,
361 (u32 *)&emu_romcode_params);
362}
363
Pali Roháred407be2012-10-29 07:54:01 +0000364/*
365 * Routine: omap3_update_aux_cr_secure_rx51
366 * Description: Modify the contents Auxiliary Control Register.
367 * Parameters:
368 * set_bits - bits to set in ACR
369 * clr_bits - bits to clear in ACR
370 */
371static void omap3_update_aux_cr_secure_rx51(u32 set_bits, u32 clear_bits)
372{
Pali Roháred407be2012-10-29 07:54:01 +0000373 u32 acr;
374
375 /* Read ACR */
376 asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r" (acr));
377 acr &= ~clear_bits;
378 acr |= set_bits;
Nishanth Menoncdef0b32015-03-09 17:12:09 -0500379 omap3_set_aux_cr_secure(acr);
Pali Roháred407be2012-10-29 07:54:01 +0000380}
381
382/*
383 * Routine: misc_init_r
384 * Description: Configure board specific parts.
385 */
386int misc_init_r(void)
387{
388 char buf[12];
389 u8 state;
390
391 /* reset lp5523 led */
392 i2c_set_bus_num(1);
393 state = 0xff;
394 i2c_write(0x32, 0x3d, 1, &state, 1);
395 i2c_set_bus_num(0);
396
397 /* initialize twl4030 power managment */
398 twl4030_power_init();
399
400 /* set VSIM to 1.8V */
401 twl4030_pmrecv_vsel_cfg(TWL4030_PM_RECEIVER_VSIM_DEDICATED,
402 TWL4030_PM_RECEIVER_VSIM_VSEL_18,
403 TWL4030_PM_RECEIVER_VSIM_DEV_GRP,
404 TWL4030_PM_RECEIVER_DEV_GRP_P1);
405
406 /* store I2C access state */
Nishanth Menonb29c2f02013-03-26 05:20:50 +0000407 twl4030_i2c_read_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
408 &state);
Pali Roháred407be2012-10-29 07:54:01 +0000409
410 /* enable I2C access to powerbus (needed for twl4030 regulator) */
Nishanth Menon0208aaf2013-03-26 05:20:49 +0000411 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
412 0x02);
Pali Roháred407be2012-10-29 07:54:01 +0000413
414 /* set VAUX3, VSIM and VMMC1 state to active - enable eMMC memory */
415 twl4030_regulator_set_mode(RES_VAUX3, RES_STATE_ACTIVE);
416 twl4030_regulator_set_mode(RES_VSIM, RES_STATE_ACTIVE);
417 twl4030_regulator_set_mode(RES_VMMC1, RES_STATE_ACTIVE);
418
419 /* restore I2C access state */
Nishanth Menon0208aaf2013-03-26 05:20:49 +0000420 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
421 state);
Pali Roháred407be2012-10-29 07:54:01 +0000422
423 /* set env variable attkernaddr for relocated kernel */
424 sprintf(buf, "%#x", KERNEL_ADDRESS);
Simon Glass382bee52017-08-03 12:22:09 -0600425 env_set("attkernaddr", buf);
Pali Roháred407be2012-10-29 07:54:01 +0000426
427 /* initialize omap tags */
428 init_omap_tags();
429
430 /* reuse atags from previous bootloader */
431 reuse_atags();
432
Paul Kocialkowski679f82c2015-08-27 19:37:13 +0200433 omap_die_id_display();
Pali Roháred407be2012-10-29 07:54:01 +0000434 print_cpuinfo();
435
436 /*
437 * Cortex-A8(r1p0..r1p2) errata 430973 workaround
438 * Set IBE bit in Auxiliary Control Register
Pali Rohár8cda4132015-01-08 10:11:40 +0100439 *
440 * Call this routine only on real secure device
441 * Qemu does not implement secure PPA and crash
Pali Roháred407be2012-10-29 07:54:01 +0000442 */
Pali Rohár8cda4132015-01-08 10:11:40 +0100443 if (get_device_type() == HS_DEVICE)
444 omap3_update_aux_cr_secure_rx51(1 << 6, 0);
Pali Roháred407be2012-10-29 07:54:01 +0000445
446 return 0;
447}
448
449/*
450 * Routine: set_muxconf_regs
451 * Description: Setting up the configuration Mux registers specific to the
452 * hardware. Many pins need to be moved from protect to primary
453 * mode.
454 */
455void set_muxconf_regs(void)
456{
457 MUX_RX51();
458}
459
460static unsigned long int twl_wd_time; /* last time of watchdog reset */
461static unsigned long int twl_i2c_lock;
462
463/*
464 * Routine: hw_watchdog_reset
465 * Description: Reset timeout of twl4030 watchdog.
466 */
467void hw_watchdog_reset(void)
468{
469 u8 timeout = 0;
470
471 /* do not reset watchdog too often - max every 4s */
472 if (get_timer(twl_wd_time) < 4 * CONFIG_SYS_HZ)
473 return;
474
475 /* localy lock twl4030 i2c bus */
476 if (test_and_set_bit(0, &twl_i2c_lock))
477 return;
478
479 /* read actual watchdog timeout */
Nishanth Menonb29c2f02013-03-26 05:20:50 +0000480 twl4030_i2c_read_u8(TWL4030_CHIP_PM_RECEIVER,
481 TWL4030_PM_RECEIVER_WATCHDOG_CFG, &timeout);
Pali Roháred407be2012-10-29 07:54:01 +0000482
483 /* timeout 0 means watchdog is disabled */
484 /* reset watchdog timeout to 31s (maximum) */
485 if (timeout != 0)
Nishanth Menon0208aaf2013-03-26 05:20:49 +0000486 twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER,
487 TWL4030_PM_RECEIVER_WATCHDOG_CFG, 31);
Pali Roháred407be2012-10-29 07:54:01 +0000488
489 /* store last watchdog reset time */
490 twl_wd_time = get_timer(0);
491
492 /* localy unlock twl4030 i2c bus */
493 test_and_clear_bit(0, &twl_i2c_lock);
494}
495
496/*
497 * TWL4030 keypad handler for cfb_console
498 */
499
500static const char keymap[] = {
501 /* normal */
502 'q', 'o', 'p', ',', '\b', 0, 'a', 's',
503 'w', 'd', 'f', 'g', 'h', 'j', 'k', 'l',
504 'e', '.', 0, '\r', 0, 'z', 'x', 'c',
505 'r', 'v', 'b', 'n', 'm', ' ', ' ', 0,
506 't', 0, 0, 0, 0, 0, 0, 0,
507 'y', 0, 0, 0, 0, 0, 0, 0,
508 'u', 0, 0, 0, 0, 0, 0, 0,
509 'i', 5, 6, 0, 0, 0, 0, 0,
510 /* fn */
511 '1', '9', '0', '=', '\b', 0, '*', '+',
512 '2', '#', '-', '_', '(', ')', '&', '!',
513 '3', '?', '^', '\r', 0, 156, '$', 238,
514 '4', '/', '\\', '"', '\'', '@', 0, '<',
515 '5', '|', '>', 0, 0, 0, 0, 0,
516 '6', 0, 0, 0, 0, 0, 0, 0,
517 '7', 0, 0, 0, 0, 0, 0, 0,
518 '8', 16, 17, 0, 0, 0, 0, 0,
519};
520
521static u8 keys[8];
522static u8 old_keys[8] = {0, 0, 0, 0, 0, 0, 0, 0};
523#define KEYBUF_SIZE 32
524static u8 keybuf[KEYBUF_SIZE];
525static u8 keybuf_head;
526static u8 keybuf_tail;
527
528/*
529 * Routine: rx51_kp_init
530 * Description: Initialize HW keyboard.
531 */
532int rx51_kp_init(void)
533{
534 int ret = 0;
535 u8 ctrl;
Nishanth Menonb29c2f02013-03-26 05:20:50 +0000536 ret = twl4030_i2c_read_u8(TWL4030_CHIP_KEYPAD,
537 TWL4030_KEYPAD_KEYP_CTRL_REG, &ctrl);
Pali Roháred407be2012-10-29 07:54:01 +0000538
539 if (ret)
540 return ret;
541
542 /* turn on keyboard and use hardware scanning */
543 ctrl |= TWL4030_KEYPAD_CTRL_KBD_ON;
544 ctrl |= TWL4030_KEYPAD_CTRL_SOFT_NRST;
545 ctrl |= TWL4030_KEYPAD_CTRL_SOFTMODEN;
Nishanth Menon0208aaf2013-03-26 05:20:49 +0000546 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
547 TWL4030_KEYPAD_KEYP_CTRL_REG, ctrl);
Pali Roháred407be2012-10-29 07:54:01 +0000548 /* enable key event status */
Nishanth Menon0208aaf2013-03-26 05:20:49 +0000549 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
550 TWL4030_KEYPAD_KEYP_IMR1, 0xfe);
Pali Roháred407be2012-10-29 07:54:01 +0000551 /* enable interrupt generation on rising and falling */
552 /* this is a workaround for qemu twl4030 emulation */
Nishanth Menon0208aaf2013-03-26 05:20:49 +0000553 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
554 TWL4030_KEYPAD_KEYP_EDR, 0x57);
Pali Roháred407be2012-10-29 07:54:01 +0000555 /* enable ISR clear on read */
Nishanth Menon0208aaf2013-03-26 05:20:49 +0000556 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
557 TWL4030_KEYPAD_KEYP_SIH_CTRL, 0x05);
Pali Roháred407be2012-10-29 07:54:01 +0000558 return 0;
559}
560
561static void rx51_kp_fill(u8 k, u8 mods)
562{
563 /* check if some cursor key without meta fn key was pressed */
564 if (!(mods & 2) && (k == 18 || k == 31 || k == 33 || k == 34)) {
565 keybuf[keybuf_tail++] = '\e';
566 keybuf_tail %= KEYBUF_SIZE;
567 keybuf[keybuf_tail++] = '[';
568 keybuf_tail %= KEYBUF_SIZE;
569 if (k == 18) /* up */
570 keybuf[keybuf_tail++] = 'A';
571 else if (k == 31) /* left */
572 keybuf[keybuf_tail++] = 'D';
573 else if (k == 33) /* down */
574 keybuf[keybuf_tail++] = 'B';
575 else if (k == 34) /* right */
576 keybuf[keybuf_tail++] = 'C';
577 keybuf_tail %= KEYBUF_SIZE;
578 return;
579 }
580
581 if (mods & 2) { /* fn meta key was pressed */
582 k = keymap[k+64];
583 } else {
584 k = keymap[k];
585 if (mods & 1) { /* ctrl key was pressed */
586 if (k >= 'a' && k <= 'z')
587 k -= 'a' - 1;
588 }
589 if (mods & 4) { /* shift key was pressed */
590 if (k >= 'a' && k <= 'z')
591 k += 'A' - 'a';
592 else if (k == '.')
593 k = ':';
594 else if (k == ',')
595 k = ';';
596 }
597 }
598 keybuf[keybuf_tail++] = k;
599 keybuf_tail %= KEYBUF_SIZE;
600}
601
602/*
603 * Routine: rx51_kp_tstc
604 * Description: Test if key was pressed (from buffer).
605 */
Simon Glass709ea542014-07-23 06:54:59 -0600606int rx51_kp_tstc(struct stdio_dev *sdev)
Pali Roháred407be2012-10-29 07:54:01 +0000607{
608 u8 c, r, dk, i;
609 u8 intr;
610 u8 mods;
611
612 /* localy lock twl4030 i2c bus */
613 if (test_and_set_bit(0, &twl_i2c_lock))
614 return 0;
615
616 /* twl4030 remembers up to 2 events */
617 for (i = 0; i < 2; i++) {
618
619 /* check interrupt register for events */
Nishanth Menonb29c2f02013-03-26 05:20:50 +0000620 twl4030_i2c_read_u8(TWL4030_CHIP_KEYPAD,
621 TWL4030_KEYPAD_KEYP_ISR1 + (2 * i), &intr);
Pali Roháred407be2012-10-29 07:54:01 +0000622
623 /* no event */
624 if (!(intr&1))
625 continue;
626
627 /* read the key state */
628 i2c_read(TWL4030_CHIP_KEYPAD,
629 TWL4030_KEYPAD_FULL_CODE_7_0, 1, keys, 8);
630
631 /* cut out modifier keys from the keystate */
632 mods = keys[4] >> 4;
633 keys[4] &= 0x0f;
634
635 for (c = 0; c < 8; c++) {
636
637 /* get newly pressed keys only */
638 dk = ((keys[c] ^ old_keys[c])&keys[c]);
639 old_keys[c] = keys[c];
640
641 /* fill the keybuf */
642 for (r = 0; r < 8; r++) {
643 if (dk&1)
644 rx51_kp_fill((c*8)+r, mods);
645 dk = dk >> 1;
646 }
647
648 }
649
650 }
651
652 /* localy unlock twl4030 i2c bus */
653 test_and_clear_bit(0, &twl_i2c_lock);
654
655 return (KEYBUF_SIZE + keybuf_tail - keybuf_head)%KEYBUF_SIZE;
656}
657
658/*
659 * Routine: rx51_kp_getc
660 * Description: Get last pressed key (from buffer).
661 */
Simon Glass709ea542014-07-23 06:54:59 -0600662int rx51_kp_getc(struct stdio_dev *sdev)
Pali Roháred407be2012-10-29 07:54:01 +0000663{
664 keybuf_head %= KEYBUF_SIZE;
Simon Glass709ea542014-07-23 06:54:59 -0600665 while (!rx51_kp_tstc(sdev))
Pali Roháred407be2012-10-29 07:54:01 +0000666 WATCHDOG_RESET();
667 return keybuf[keybuf_head++];
668}
669
670/*
671 * Routine: board_mmc_init
672 * Description: Initialize mmc devices.
673 */
674int board_mmc_init(bd_t *bis)
675{
Nikita Kiryanove3913f52012-12-03 02:19:47 +0000676 omap_mmc_init(0, 0, 0, -1, -1);
677 omap_mmc_init(1, 0, 0, -1, -1);
Pali Roháred407be2012-10-29 07:54:01 +0000678 return 0;
679}
Paul Kocialkowskiaac54502014-11-08 20:55:47 +0100680
681void board_mmc_power_init(void)
682{
683 twl4030_power_mmc_init(0);
684 twl4030_power_mmc_init(1);
685}