blob: 76f6ede38c62d8b9811c717b59762b5d584fb49c [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Pali Rohár248ef0a2012-10-29 07:54:01 +00002/*
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>
Pali Rohár248ef0a2012-10-29 07:54:01 +000022 */
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 */
Simon Glass64b723f2017-08-03 12:22:12 -0600236 str = env_get("setup_omap_atag");
Pali Rohár248ef0a2012-10-29 07:54:01 +0000237 if (!str || str[0] != '1')
238 return;
239
Simon Glass64b723f2017-08-03 12:22:12 -0600240 str = env_get("setup_console_atag");
Pali Rohár248ef0a2012-10-29 07:54:01 +0000241 if (str && str[0] == '1')
242 setup_console_atag = 1;
243 else
244 setup_console_atag = 0;
245
Simon Glass64b723f2017-08-03 12:22:12 -0600246 setup_boot_reason_atag = env_get("setup_boot_reason_atag");
247 setup_boot_mode_atag = env_get("setup_boot_mode_atag");
Pali Rohár248ef0a2012-10-29 07:54:01 +0000248
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);
Nishanth Menond26a1062013-03-26 05:20:49 +0000318 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);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000322}
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
Nishanth Menon53fee1e2015-03-09 17:12:09 -0500343void 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
Pali Rohár248ef0a2012-10-29 07:54:01 +0000354/*
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{
Pali Rohár248ef0a2012-10-29 07:54:01 +0000363 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;
Nishanth Menon53fee1e2015-03-09 17:12:09 -0500369 omap3_set_aux_cr_secure(acr);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000370}
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 */
Nishanth Menon5d9d6f72013-03-26 05:20:50 +0000397 twl4030_i2c_read_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
398 &state);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000399
400 /* enable I2C access to powerbus (needed for twl4030 regulator) */
Nishanth Menond26a1062013-03-26 05:20:49 +0000401 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
402 0x02);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000403
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 */
Nishanth Menond26a1062013-03-26 05:20:49 +0000410 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
411 state);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000412
413 /* set env variable attkernaddr for relocated kernel */
414 sprintf(buf, "%#x", KERNEL_ADDRESS);
Simon Glass6a38e412017-08-03 12:22:09 -0600415 env_set("attkernaddr", buf);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000416
417 /* initialize omap tags */
418 init_omap_tags();
419
420 /* reuse atags from previous bootloader */
421 reuse_atags();
422
Paul Kocialkowski6bc318e2015-08-27 19:37:13 +0200423 omap_die_id_display();
Pali Rohár248ef0a2012-10-29 07:54:01 +0000424 print_cpuinfo();
425
426 /*
427 * Cortex-A8(r1p0..r1p2) errata 430973 workaround
428 * Set IBE bit in Auxiliary Control Register
Pali Rohár415b8042015-01-08 10:11:40 +0100429 *
430 * Call this routine only on real secure device
431 * Qemu does not implement secure PPA and crash
Pali Rohár248ef0a2012-10-29 07:54:01 +0000432 */
Pali Rohár415b8042015-01-08 10:11:40 +0100433 if (get_device_type() == HS_DEVICE)
434 omap3_update_aux_cr_secure_rx51(1 << 6, 0);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000435
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 */
Nishanth Menon5d9d6f72013-03-26 05:20:50 +0000470 twl4030_i2c_read_u8(TWL4030_CHIP_PM_RECEIVER,
471 TWL4030_PM_RECEIVER_WATCHDOG_CFG, &timeout);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000472
473 /* timeout 0 means watchdog is disabled */
474 /* reset watchdog timeout to 31s (maximum) */
475 if (timeout != 0)
Nishanth Menond26a1062013-03-26 05:20:49 +0000476 twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER,
477 TWL4030_PM_RECEIVER_WATCHDOG_CFG, 31);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000478
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;
Nishanth Menon5d9d6f72013-03-26 05:20:50 +0000526 ret = twl4030_i2c_read_u8(TWL4030_CHIP_KEYPAD,
527 TWL4030_KEYPAD_KEYP_CTRL_REG, &ctrl);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000528
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;
Nishanth Menond26a1062013-03-26 05:20:49 +0000536 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
537 TWL4030_KEYPAD_KEYP_CTRL_REG, ctrl);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000538 /* enable key event status */
Nishanth Menond26a1062013-03-26 05:20:49 +0000539 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
540 TWL4030_KEYPAD_KEYP_IMR1, 0xfe);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000541 /* enable interrupt generation on rising and falling */
542 /* this is a workaround for qemu twl4030 emulation */
Nishanth Menond26a1062013-03-26 05:20:49 +0000543 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
544 TWL4030_KEYPAD_KEYP_EDR, 0x57);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000545 /* enable ISR clear on read */
Nishanth Menond26a1062013-03-26 05:20:49 +0000546 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
547 TWL4030_KEYPAD_KEYP_SIH_CTRL, 0x05);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000548 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 */
Simon Glass0d1e1f72014-07-23 06:54:59 -0600596int rx51_kp_tstc(struct stdio_dev *sdev)
Pali Rohár248ef0a2012-10-29 07:54:01 +0000597{
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 */
Nishanth Menon5d9d6f72013-03-26 05:20:50 +0000610 twl4030_i2c_read_u8(TWL4030_CHIP_KEYPAD,
611 TWL4030_KEYPAD_KEYP_ISR1 + (2 * i), &intr);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000612
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 */
Simon Glass0d1e1f72014-07-23 06:54:59 -0600652int rx51_kp_getc(struct stdio_dev *sdev)
Pali Rohár248ef0a2012-10-29 07:54:01 +0000653{
654 keybuf_head %= KEYBUF_SIZE;
Simon Glass0d1e1f72014-07-23 06:54:59 -0600655 while (!rx51_kp_tstc(sdev))
Pali Rohár248ef0a2012-10-29 07:54:01 +0000656 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{
Nikita Kiryanov4be9dbc2012-12-03 02:19:47 +0000666 omap_mmc_init(0, 0, 0, -1, -1);
667 omap_mmc_init(1, 0, 0, -1, -1);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000668 return 0;
669}
Paul Kocialkowski69559892014-11-08 20:55:47 +0100670
671void board_mmc_power_init(void)
672{
673 twl4030_power_mmc_init(0);
674 twl4030_power_mmc_init(1);
675}