blob: 60a2e3619c2cc41f9e80b52db4528a51f3fb3f7b [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
Pali Rohár10a953d2020-04-01 00:35:08 +02007 * Pali Rohár <pali@kernel.org>
Pali Rohár248ef0a2012-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ár248ef0a2012-10-29 07:54:01 +000022 */
23
24#include <common.h>
Simon Glass5e6201b2019-08-01 09:46:51 -060025#include <env.h>
Simon Glass97589732020-05-10 11:40:02 -060026#include <init.h>
Pali Rohár248ef0a2012-10-29 07:54:01 +000027#include <watchdog.h>
28#include <malloc.h>
29#include <twl4030.h>
30#include <i2c.h>
31#include <video_fb.h>
32#include <asm/io.h>
33#include <asm/setup.h>
34#include <asm/bitops.h>
35#include <asm/mach-types.h>
36#include <asm/arch/mux.h>
37#include <asm/arch/sys_proto.h>
38#include <asm/arch/mmc_host_def.h>
39
40#include "rx51.h"
41#include "tag_omap.h"
42
43DECLARE_GLOBAL_DATA_PTR;
44
45GraphicDevice gdev;
46
47const omap3_sysinfo sysinfo = {
48 DDR_STACKED,
49 "Nokia RX-51",
50 "OneNAND"
51};
52
53/* This structure contains default omap tags needed for booting Maemo 5 */
54static struct tag_omap omap[] = {
55 OMAP_TAG_UART_CONFIG(0x04),
56 OMAP_TAG_SERIAL_CONSOLE_CONFIG(0x03, 0x01C200),
57 OMAP_TAG_LCD_CONFIG("acx565akm", "internal", 90, 0x18),
58 OMAP_TAG_GPIO_SWITCH_CONFIG("cam_focus", 0x44, 0x1, 0x2, 0x0),
59 OMAP_TAG_GPIO_SWITCH_CONFIG("cam_launch", 0x45, 0x1, 0x2, 0x0),
60 OMAP_TAG_GPIO_SWITCH_CONFIG("cam_shutter", 0x6e, 0x1, 0x0, 0x0),
61 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_apeslpx", 0x46, 0x2, 0x2, 0x0),
62 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_bsi", 0x9d, 0x2, 0x2, 0x0),
63 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_en", 0x4a, 0x2, 0x2, 0x0),
64 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_rst", 0x4b, 0x6, 0x2, 0x0),
65 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_rst_rq", 0x49, 0x6, 0x2, 0x0),
66 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_wddis", 0x0d, 0x2, 0x2, 0x0),
67 OMAP_TAG_GPIO_SWITCH_CONFIG("headphone", 0xb1, 0x1, 0x1, 0x0),
68 OMAP_TAG_GPIO_SWITCH_CONFIG("kb_lock", 0x71, 0x1, 0x0, 0x0),
69 OMAP_TAG_GPIO_SWITCH_CONFIG("proximity", 0x59, 0x0, 0x0, 0x0),
70 OMAP_TAG_GPIO_SWITCH_CONFIG("sleep_ind", 0xa2, 0x2, 0x2, 0x0),
71 OMAP_TAG_GPIO_SWITCH_CONFIG("slide", GPIO_SLIDE, 0x0, 0x0, 0x0),
72 OMAP_TAG_WLAN_CX3110X_CONFIG(0x25, 0xff, 87, 42, -1),
Pali Rohár7ce37522020-04-01 00:35:13 +020073 OMAP_TAG_PARTITION_CONFIG("bootloader", 128 * 1024, 0x00000000, 0x00000003),
74 OMAP_TAG_PARTITION_CONFIG("config", 384 * 1024, 0x00020000, 0x00000000),
75 OMAP_TAG_PARTITION_CONFIG("log", 256 * 1024, 0x00080000, 0x00000000),
76 OMAP_TAG_PARTITION_CONFIG("kernel", 2 * 1024*1024, 0x000c0000, 0x00000000),
77 OMAP_TAG_PARTITION_CONFIG("initfs", 2 * 1024*1024, 0x002c0000, 0x00000000),
78 OMAP_TAG_PARTITION_CONFIG("rootfs", 257280 * 1024, 0x004c0000, 0x00000000),
Pali Rohár248ef0a2012-10-29 07:54:01 +000079 OMAP_TAG_BOOT_REASON_CONFIG("pwr_key"),
80 OMAP_TAG_VERSION_STR_CONFIG("product", "RX-51"),
81 OMAP_TAG_VERSION_STR_CONFIG("hw-build", "2101"),
82 OMAP_TAG_VERSION_STR_CONFIG("nolo", "1.4.14"),
83 OMAP_TAG_VERSION_STR_CONFIG("boot-mode", "normal"),
84 { }
85};
86
87static char *boot_reason_ptr;
88static char *hw_build_ptr;
89static char *nolo_version_ptr;
90static char *boot_mode_ptr;
Pali Rohár02f45842020-04-01 00:35:14 +020091static int serial_was_console_enabled;
Pali Rohár248ef0a2012-10-29 07:54:01 +000092
93/*
94 * Routine: init_omap_tags
95 * Description: Initialize pointers to values in tag_omap
96 */
97static void init_omap_tags(void)
98{
99 char *component;
100 char *version;
101 int i = 0;
102 while (omap[i].hdr.tag) {
103 switch (omap[i].hdr.tag) {
104 case OMAP_TAG_BOOT_REASON:
105 boot_reason_ptr = omap[i].u.boot_reason.reason_str;
106 break;
107 case OMAP_TAG_VERSION_STR:
108 component = omap[i].u.version.component;
109 version = omap[i].u.version.version;
110 if (strcmp(component, "hw-build") == 0)
111 hw_build_ptr = version;
112 else if (strcmp(component, "nolo") == 0)
113 nolo_version_ptr = version;
114 else if (strcmp(component, "boot-mode") == 0)
115 boot_mode_ptr = version;
116 break;
117 default:
118 break;
119 }
120 i++;
121 }
122}
123
124static void reuse_omap_atags(struct tag_omap *t)
125{
126 char *component;
127 char *version;
128 while (t->hdr.tag) {
129 switch (t->hdr.tag) {
130 case OMAP_TAG_BOOT_REASON:
131 memset(boot_reason_ptr, 0, 12);
132 strcpy(boot_reason_ptr, t->u.boot_reason.reason_str);
133 break;
134 case OMAP_TAG_VERSION_STR:
135 component = t->u.version.component;
136 version = t->u.version.version;
137 if (strcmp(component, "hw-build") == 0) {
138 memset(hw_build_ptr, 0, 12);
139 strcpy(hw_build_ptr, version);
140 } else if (strcmp(component, "nolo") == 0) {
141 memset(nolo_version_ptr, 0, 12);
142 strcpy(nolo_version_ptr, version);
143 } else if (strcmp(component, "boot-mode") == 0) {
144 memset(boot_mode_ptr, 0, 12);
145 strcpy(boot_mode_ptr, version);
146 }
147 break;
Pali Rohár02f45842020-04-01 00:35:14 +0200148 case OMAP_TAG_UART:
149 if (!t->u.uart.enabled_uarts)
150 serial_was_console_enabled = 1;
151 break;
152 case OMAP_TAG_SERIAL_CONSOLE:
153 serial_was_console_enabled = 1;
154 break;
Pali Rohár248ef0a2012-10-29 07:54:01 +0000155 default:
156 break;
157 }
158 t = tag_omap_next(t);
159 }
160}
161
162/*
163 * Routine: reuse_atags
164 * Description: Reuse atags from previous bootloader.
165 * Reuse only only HW build, boot reason, boot mode and nolo
166 */
167static void reuse_atags(void)
168{
169 struct tag *t = (struct tag *)gd->bd->bi_boot_params;
170
171 /* First tag must be ATAG_CORE */
172 if (t->hdr.tag != ATAG_CORE)
173 return;
174
175 if (!boot_reason_ptr || !hw_build_ptr)
176 return;
177
178 /* Last tag must be ATAG_NONE */
179 while (t->hdr.tag != ATAG_NONE) {
180 switch (t->hdr.tag) {
181 case ATAG_REVISION:
182 memset(hw_build_ptr, 0, 12);
183 sprintf(hw_build_ptr, "%x", t->u.revision.rev);
184 break;
185 case ATAG_BOARD:
186 reuse_omap_atags((struct tag_omap *)&t->u);
187 break;
188 default:
189 break;
190 }
191 t = tag_next(t);
192 }
193}
194
195/*
196 * Routine: board_init
197 * Description: Early hardware init.
198 */
199int board_init(void)
200{
201 /* in SRAM or SDRAM, finish GPMC */
202 gpmc_init();
203 /* boot param addr */
204 gd->bd->bi_boot_params = OMAP34XX_SDRC_CS0 + 0x100;
205 return 0;
206}
207
208/*
209 * Routine: get_board_revision
210 * Description: Return board revision.
211 */
212u32 get_board_rev(void)
213{
214 return simple_strtol(hw_build_ptr, NULL, 16);
215}
216
217/*
218 * Routine: setup_board_tags
219 * Description: Append board specific boot tags.
220 */
221void setup_board_tags(struct tag **in_params)
222{
223 int setup_console_atag;
224 char *setup_boot_reason_atag;
225 char *setup_boot_mode_atag;
226 char *str;
227 int i;
228 int size;
229 int total_size;
230 struct tag *params;
231 struct tag_omap *t;
232
233 params = (struct tag *)gd->bd->bi_boot_params;
234
235 params->u.core.flags = 0x0;
236 params->u.core.pagesize = 0x1000;
237 params->u.core.rootdev = 0x0;
238
239 /* append omap atag only if env setup_omap_atag is set to 1 */
Simon Glass64b723f2017-08-03 12:22:12 -0600240 str = env_get("setup_omap_atag");
Pali Rohár248ef0a2012-10-29 07:54:01 +0000241 if (!str || str[0] != '1')
242 return;
243
Simon Glass64b723f2017-08-03 12:22:12 -0600244 str = env_get("setup_console_atag");
Pali Rohár02f45842020-04-01 00:35:14 +0200245 if (str && str[0]) {
246 if (str[0] == '1')
247 setup_console_atag = 1;
248 else
249 setup_console_atag = 0;
250 } else {
251 if (serial_was_console_enabled)
252 setup_console_atag = 1;
253 else
254 setup_console_atag = 0;
255 }
Pali Rohár248ef0a2012-10-29 07:54:01 +0000256
Simon Glass64b723f2017-08-03 12:22:12 -0600257 setup_boot_reason_atag = env_get("setup_boot_reason_atag");
258 setup_boot_mode_atag = env_get("setup_boot_mode_atag");
Pali Rohár248ef0a2012-10-29 07:54:01 +0000259
260 params = *in_params;
261 t = (struct tag_omap *)&params->u;
262 total_size = sizeof(struct tag_header);
263
264 for (i = 0; omap[i].hdr.tag; i++) {
265
266 /* skip serial console tag */
267 if (!setup_console_atag &&
268 omap[i].hdr.tag == OMAP_TAG_SERIAL_CONSOLE)
269 continue;
270
271 size = omap[i].hdr.size + sizeof(struct tag_omap_header);
272 memcpy(t, &omap[i], size);
273
274 /* set uart tag to 0 - disable serial console */
275 if (!setup_console_atag && omap[i].hdr.tag == OMAP_TAG_UART)
276 t->u.uart.enabled_uarts = 0;
277
278 /* change boot reason */
279 if (setup_boot_reason_atag &&
280 omap[i].hdr.tag == OMAP_TAG_BOOT_REASON) {
281 memset(t->u.boot_reason.reason_str, 0, 12);
282 strcpy(t->u.boot_reason.reason_str,
283 setup_boot_reason_atag);
284 }
285
286 /* change boot mode */
287 if (setup_boot_mode_atag &&
288 omap[i].hdr.tag == OMAP_TAG_VERSION_STR &&
289 strcmp(omap[i].u.version.component, "boot-mode") == 0) {
290 memset(t->u.version.version, 0, 12);
291 strcpy(t->u.version.version, setup_boot_mode_atag);
292 }
293
294 total_size += size;
295 t = tag_omap_next(t);
296
297 }
298
299 params->hdr.tag = ATAG_BOARD;
300 params->hdr.size = total_size >> 2;
301 params = tag_next(params);
302
303 *in_params = params;
304}
305
306/*
307 * Routine: video_hw_init
308 * Description: Set up the GraphicDevice depending on sys_boot.
309 */
310void *video_hw_init(void)
311{
312 /* fill in Graphic Device */
313 gdev.frameAdrs = 0x8f9c0000;
314 gdev.winSizeX = 800;
315 gdev.winSizeY = 480;
316 gdev.gdfBytesPP = 2;
317 gdev.gdfIndex = GDF_16BIT_565RGB;
318 memset((void *)gdev.frameAdrs, 0, 0xbb800);
319 return (void *) &gdev;
320}
321
322/*
323 * Routine: twl4030_regulator_set_mode
324 * Description: Set twl4030 regulator mode over i2c powerbus.
325 */
326static void twl4030_regulator_set_mode(u8 id, u8 mode)
327{
328 u16 msg = MSG_SINGULAR(DEV_GRP_P1, id, mode);
Nishanth Menond26a1062013-03-26 05:20:49 +0000329 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
330 TWL4030_PM_MASTER_PB_WORD_MSB, msg >> 8);
331 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
332 TWL4030_PM_MASTER_PB_WORD_LSB, msg & 0xff);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000333}
334
335static void omap3_emu_romcode_call(u32 service_id, u32 *parameters)
336{
337 u32 i, num_params = *parameters;
338 u32 *sram_scratch_space = (u32 *)OMAP3_PUBLIC_SRAM_SCRATCH_AREA;
339
340 /*
341 * copy the parameters to an un-cached area to avoid coherency
342 * issues
343 */
344 for (i = 0; i < num_params; i++) {
345 __raw_writel(*parameters, sram_scratch_space);
346 parameters++;
347 sram_scratch_space++;
348 }
349
350 /* Now make the PPA call */
351 do_omap3_emu_romcode_call(service_id, OMAP3_PUBLIC_SRAM_SCRATCH_AREA);
352}
353
Nishanth Menon53fee1e2015-03-09 17:12:09 -0500354void omap3_set_aux_cr_secure(u32 acr)
355{
356 struct emu_hal_params_rx51 emu_romcode_params = { 0, };
357
358 emu_romcode_params.num_params = 2;
359 emu_romcode_params.param1 = acr;
360
361 omap3_emu_romcode_call(OMAP3_EMU_HAL_API_WRITE_ACR,
362 (u32 *)&emu_romcode_params);
363}
364
Pali Rohár248ef0a2012-10-29 07:54:01 +0000365/*
366 * Routine: omap3_update_aux_cr_secure_rx51
367 * Description: Modify the contents Auxiliary Control Register.
368 * Parameters:
369 * set_bits - bits to set in ACR
370 * clr_bits - bits to clear in ACR
371 */
372static void omap3_update_aux_cr_secure_rx51(u32 set_bits, u32 clear_bits)
373{
Pali Rohár248ef0a2012-10-29 07:54:01 +0000374 u32 acr;
375
376 /* Read ACR */
377 asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r" (acr));
378 acr &= ~clear_bits;
379 acr |= set_bits;
Nishanth Menon53fee1e2015-03-09 17:12:09 -0500380 omap3_set_aux_cr_secure(acr);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000381}
382
383/*
384 * Routine: misc_init_r
385 * Description: Configure board specific parts.
386 */
387int misc_init_r(void)
388{
389 char buf[12];
390 u8 state;
391
392 /* reset lp5523 led */
393 i2c_set_bus_num(1);
394 state = 0xff;
395 i2c_write(0x32, 0x3d, 1, &state, 1);
396 i2c_set_bus_num(0);
397
398 /* initialize twl4030 power managment */
399 twl4030_power_init();
400
401 /* set VSIM to 1.8V */
402 twl4030_pmrecv_vsel_cfg(TWL4030_PM_RECEIVER_VSIM_DEDICATED,
403 TWL4030_PM_RECEIVER_VSIM_VSEL_18,
404 TWL4030_PM_RECEIVER_VSIM_DEV_GRP,
405 TWL4030_PM_RECEIVER_DEV_GRP_P1);
406
407 /* store I2C access state */
Nishanth Menon5d9d6f72013-03-26 05:20:50 +0000408 twl4030_i2c_read_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
409 &state);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000410
411 /* enable I2C access to powerbus (needed for twl4030 regulator) */
Nishanth Menond26a1062013-03-26 05:20:49 +0000412 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
413 0x02);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000414
415 /* set VAUX3, VSIM and VMMC1 state to active - enable eMMC memory */
416 twl4030_regulator_set_mode(RES_VAUX3, RES_STATE_ACTIVE);
417 twl4030_regulator_set_mode(RES_VSIM, RES_STATE_ACTIVE);
418 twl4030_regulator_set_mode(RES_VMMC1, RES_STATE_ACTIVE);
419
420 /* restore I2C access state */
Nishanth Menond26a1062013-03-26 05:20:49 +0000421 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
422 state);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000423
424 /* set env variable attkernaddr for relocated kernel */
425 sprintf(buf, "%#x", KERNEL_ADDRESS);
Simon Glass6a38e412017-08-03 12:22:09 -0600426 env_set("attkernaddr", buf);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000427
428 /* initialize omap tags */
429 init_omap_tags();
430
431 /* reuse atags from previous bootloader */
432 reuse_atags();
433
Paul Kocialkowski6bc318e2015-08-27 19:37:13 +0200434 omap_die_id_display();
Pali Rohár248ef0a2012-10-29 07:54:01 +0000435 print_cpuinfo();
436
437 /*
438 * Cortex-A8(r1p0..r1p2) errata 430973 workaround
439 * Set IBE bit in Auxiliary Control Register
Pali Rohár415b8042015-01-08 10:11:40 +0100440 *
441 * Call this routine only on real secure device
442 * Qemu does not implement secure PPA and crash
Pali Rohár248ef0a2012-10-29 07:54:01 +0000443 */
Pali Rohár415b8042015-01-08 10:11:40 +0100444 if (get_device_type() == HS_DEVICE)
445 omap3_update_aux_cr_secure_rx51(1 << 6, 0);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000446
447 return 0;
448}
449
450/*
451 * Routine: set_muxconf_regs
452 * Description: Setting up the configuration Mux registers specific to the
453 * hardware. Many pins need to be moved from protect to primary
454 * mode.
455 */
456void set_muxconf_regs(void)
457{
458 MUX_RX51();
459}
460
461static unsigned long int twl_wd_time; /* last time of watchdog reset */
462static unsigned long int twl_i2c_lock;
463
464/*
465 * Routine: hw_watchdog_reset
466 * Description: Reset timeout of twl4030 watchdog.
467 */
468void hw_watchdog_reset(void)
469{
470 u8 timeout = 0;
471
472 /* do not reset watchdog too often - max every 4s */
473 if (get_timer(twl_wd_time) < 4 * CONFIG_SYS_HZ)
474 return;
475
476 /* localy lock twl4030 i2c bus */
477 if (test_and_set_bit(0, &twl_i2c_lock))
478 return;
479
480 /* read actual watchdog timeout */
Nishanth Menon5d9d6f72013-03-26 05:20:50 +0000481 twl4030_i2c_read_u8(TWL4030_CHIP_PM_RECEIVER,
482 TWL4030_PM_RECEIVER_WATCHDOG_CFG, &timeout);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000483
484 /* timeout 0 means watchdog is disabled */
485 /* reset watchdog timeout to 31s (maximum) */
486 if (timeout != 0)
Nishanth Menond26a1062013-03-26 05:20:49 +0000487 twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER,
488 TWL4030_PM_RECEIVER_WATCHDOG_CFG, 31);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000489
490 /* store last watchdog reset time */
491 twl_wd_time = get_timer(0);
492
493 /* localy unlock twl4030 i2c bus */
494 test_and_clear_bit(0, &twl_i2c_lock);
495}
496
497/*
498 * TWL4030 keypad handler for cfb_console
499 */
500
501static const char keymap[] = {
502 /* normal */
503 'q', 'o', 'p', ',', '\b', 0, 'a', 's',
504 'w', 'd', 'f', 'g', 'h', 'j', 'k', 'l',
505 'e', '.', 0, '\r', 0, 'z', 'x', 'c',
506 'r', 'v', 'b', 'n', 'm', ' ', ' ', 0,
507 't', 0, 0, 0, 0, 0, 0, 0,
508 'y', 0, 0, 0, 0, 0, 0, 0,
509 'u', 0, 0, 0, 0, 0, 0, 0,
510 'i', 5, 6, 0, 0, 0, 0, 0,
511 /* fn */
512 '1', '9', '0', '=', '\b', 0, '*', '+',
513 '2', '#', '-', '_', '(', ')', '&', '!',
514 '3', '?', '^', '\r', 0, 156, '$', 238,
515 '4', '/', '\\', '"', '\'', '@', 0, '<',
516 '5', '|', '>', 0, 0, 0, 0, 0,
517 '6', 0, 0, 0, 0, 0, 0, 0,
518 '7', 0, 0, 0, 0, 0, 0, 0,
519 '8', 16, 17, 0, 0, 0, 0, 0,
520};
521
522static u8 keys[8];
523static u8 old_keys[8] = {0, 0, 0, 0, 0, 0, 0, 0};
524#define KEYBUF_SIZE 32
525static u8 keybuf[KEYBUF_SIZE];
526static u8 keybuf_head;
527static u8 keybuf_tail;
528
529/*
530 * Routine: rx51_kp_init
531 * Description: Initialize HW keyboard.
532 */
533int rx51_kp_init(void)
534{
535 int ret = 0;
536 u8 ctrl;
Nishanth Menon5d9d6f72013-03-26 05:20:50 +0000537 ret = twl4030_i2c_read_u8(TWL4030_CHIP_KEYPAD,
538 TWL4030_KEYPAD_KEYP_CTRL_REG, &ctrl);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000539
540 if (ret)
541 return ret;
542
543 /* turn on keyboard and use hardware scanning */
544 ctrl |= TWL4030_KEYPAD_CTRL_KBD_ON;
545 ctrl |= TWL4030_KEYPAD_CTRL_SOFT_NRST;
546 ctrl |= TWL4030_KEYPAD_CTRL_SOFTMODEN;
Nishanth Menond26a1062013-03-26 05:20:49 +0000547 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
548 TWL4030_KEYPAD_KEYP_CTRL_REG, ctrl);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000549 /* enable key event status */
Nishanth Menond26a1062013-03-26 05:20:49 +0000550 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
551 TWL4030_KEYPAD_KEYP_IMR1, 0xfe);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000552 /* enable interrupt generation on rising and falling */
553 /* this is a workaround for qemu twl4030 emulation */
Nishanth Menond26a1062013-03-26 05:20:49 +0000554 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
555 TWL4030_KEYPAD_KEYP_EDR, 0x57);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000556 /* enable ISR clear on read */
Nishanth Menond26a1062013-03-26 05:20:49 +0000557 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
558 TWL4030_KEYPAD_KEYP_SIH_CTRL, 0x05);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000559 return 0;
560}
561
562static void rx51_kp_fill(u8 k, u8 mods)
563{
564 /* check if some cursor key without meta fn key was pressed */
565 if (!(mods & 2) && (k == 18 || k == 31 || k == 33 || k == 34)) {
566 keybuf[keybuf_tail++] = '\e';
567 keybuf_tail %= KEYBUF_SIZE;
568 keybuf[keybuf_tail++] = '[';
569 keybuf_tail %= KEYBUF_SIZE;
570 if (k == 18) /* up */
571 keybuf[keybuf_tail++] = 'A';
572 else if (k == 31) /* left */
573 keybuf[keybuf_tail++] = 'D';
574 else if (k == 33) /* down */
575 keybuf[keybuf_tail++] = 'B';
576 else if (k == 34) /* right */
577 keybuf[keybuf_tail++] = 'C';
578 keybuf_tail %= KEYBUF_SIZE;
579 return;
580 }
581
582 if (mods & 2) { /* fn meta key was pressed */
583 k = keymap[k+64];
584 } else {
585 k = keymap[k];
586 if (mods & 1) { /* ctrl key was pressed */
587 if (k >= 'a' && k <= 'z')
588 k -= 'a' - 1;
589 }
590 if (mods & 4) { /* shift key was pressed */
591 if (k >= 'a' && k <= 'z')
592 k += 'A' - 'a';
593 else if (k == '.')
594 k = ':';
595 else if (k == ',')
596 k = ';';
597 }
598 }
599 keybuf[keybuf_tail++] = k;
600 keybuf_tail %= KEYBUF_SIZE;
601}
602
603/*
604 * Routine: rx51_kp_tstc
605 * Description: Test if key was pressed (from buffer).
606 */
Simon Glass0d1e1f72014-07-23 06:54:59 -0600607int rx51_kp_tstc(struct stdio_dev *sdev)
Pali Rohár248ef0a2012-10-29 07:54:01 +0000608{
609 u8 c, r, dk, i;
610 u8 intr;
611 u8 mods;
612
613 /* localy lock twl4030 i2c bus */
614 if (test_and_set_bit(0, &twl_i2c_lock))
615 return 0;
616
617 /* twl4030 remembers up to 2 events */
618 for (i = 0; i < 2; i++) {
619
620 /* check interrupt register for events */
Nishanth Menon5d9d6f72013-03-26 05:20:50 +0000621 twl4030_i2c_read_u8(TWL4030_CHIP_KEYPAD,
622 TWL4030_KEYPAD_KEYP_ISR1 + (2 * i), &intr);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000623
624 /* no event */
625 if (!(intr&1))
626 continue;
627
628 /* read the key state */
629 i2c_read(TWL4030_CHIP_KEYPAD,
630 TWL4030_KEYPAD_FULL_CODE_7_0, 1, keys, 8);
631
632 /* cut out modifier keys from the keystate */
633 mods = keys[4] >> 4;
634 keys[4] &= 0x0f;
635
636 for (c = 0; c < 8; c++) {
637
638 /* get newly pressed keys only */
639 dk = ((keys[c] ^ old_keys[c])&keys[c]);
640 old_keys[c] = keys[c];
641
642 /* fill the keybuf */
643 for (r = 0; r < 8; r++) {
644 if (dk&1)
645 rx51_kp_fill((c*8)+r, mods);
646 dk = dk >> 1;
647 }
648
649 }
650
651 }
652
653 /* localy unlock twl4030 i2c bus */
654 test_and_clear_bit(0, &twl_i2c_lock);
655
656 return (KEYBUF_SIZE + keybuf_tail - keybuf_head)%KEYBUF_SIZE;
657}
658
659/*
660 * Routine: rx51_kp_getc
661 * Description: Get last pressed key (from buffer).
662 */
Simon Glass0d1e1f72014-07-23 06:54:59 -0600663int rx51_kp_getc(struct stdio_dev *sdev)
Pali Rohár248ef0a2012-10-29 07:54:01 +0000664{
665 keybuf_head %= KEYBUF_SIZE;
Simon Glass0d1e1f72014-07-23 06:54:59 -0600666 while (!rx51_kp_tstc(sdev))
Pali Rohár248ef0a2012-10-29 07:54:01 +0000667 WATCHDOG_RESET();
668 return keybuf[keybuf_head++];
669}
670
671/*
672 * Routine: board_mmc_init
673 * Description: Initialize mmc devices.
674 */
675int board_mmc_init(bd_t *bis)
676{
Nikita Kiryanov4be9dbc2012-12-03 02:19:47 +0000677 omap_mmc_init(0, 0, 0, -1, -1);
678 omap_mmc_init(1, 0, 0, -1, -1);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000679 return 0;
680}
Paul Kocialkowski69559892014-11-08 20:55:47 +0100681
682void board_mmc_power_init(void)
683{
684 twl4030_power_mmc_init(0);
685 twl4030_power_mmc_init(1);
686}