blob: 1f508d5cda6510ecb2d1e5c7fdce34d8659d5bb5 [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>
Pali Rohárd73afb22020-10-26 23:45:11 +010025#include <dm.h>
Simon Glass5e6201b2019-08-01 09:46:51 -060026#include <env.h>
Simon Glass97589732020-05-10 11:40:02 -060027#include <init.h>
Pali Rohár248ef0a2012-10-29 07:54:01 +000028#include <watchdog.h>
29#include <malloc.h>
30#include <twl4030.h>
31#include <i2c.h>
32#include <video_fb.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060033#include <asm/global_data.h>
Pali Rohár248ef0a2012-10-29 07:54:01 +000034#include <asm/io.h>
35#include <asm/setup.h>
36#include <asm/bitops.h>
37#include <asm/mach-types.h>
Pali Rohárd73afb22020-10-26 23:45:11 +010038#include <asm/omap_i2c.h>
Pali Rohár248ef0a2012-10-29 07:54:01 +000039#include <asm/arch/mux.h>
40#include <asm/arch/sys_proto.h>
41#include <asm/arch/mmc_host_def.h>
42
43#include "rx51.h"
44#include "tag_omap.h"
45
46DECLARE_GLOBAL_DATA_PTR;
47
48GraphicDevice gdev;
49
50const omap3_sysinfo sysinfo = {
51 DDR_STACKED,
52 "Nokia RX-51",
53 "OneNAND"
54};
55
56/* This structure contains default omap tags needed for booting Maemo 5 */
57static struct tag_omap omap[] = {
58 OMAP_TAG_UART_CONFIG(0x04),
59 OMAP_TAG_SERIAL_CONSOLE_CONFIG(0x03, 0x01C200),
60 OMAP_TAG_LCD_CONFIG("acx565akm", "internal", 90, 0x18),
61 OMAP_TAG_GPIO_SWITCH_CONFIG("cam_focus", 0x44, 0x1, 0x2, 0x0),
62 OMAP_TAG_GPIO_SWITCH_CONFIG("cam_launch", 0x45, 0x1, 0x2, 0x0),
63 OMAP_TAG_GPIO_SWITCH_CONFIG("cam_shutter", 0x6e, 0x1, 0x0, 0x0),
64 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_apeslpx", 0x46, 0x2, 0x2, 0x0),
65 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_bsi", 0x9d, 0x2, 0x2, 0x0),
66 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_en", 0x4a, 0x2, 0x2, 0x0),
67 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_rst", 0x4b, 0x6, 0x2, 0x0),
68 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_rst_rq", 0x49, 0x6, 0x2, 0x0),
69 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_wddis", 0x0d, 0x2, 0x2, 0x0),
70 OMAP_TAG_GPIO_SWITCH_CONFIG("headphone", 0xb1, 0x1, 0x1, 0x0),
71 OMAP_TAG_GPIO_SWITCH_CONFIG("kb_lock", 0x71, 0x1, 0x0, 0x0),
72 OMAP_TAG_GPIO_SWITCH_CONFIG("proximity", 0x59, 0x0, 0x0, 0x0),
73 OMAP_TAG_GPIO_SWITCH_CONFIG("sleep_ind", 0xa2, 0x2, 0x2, 0x0),
74 OMAP_TAG_GPIO_SWITCH_CONFIG("slide", GPIO_SLIDE, 0x0, 0x0, 0x0),
75 OMAP_TAG_WLAN_CX3110X_CONFIG(0x25, 0xff, 87, 42, -1),
Pali Rohár7ce37522020-04-01 00:35:13 +020076 OMAP_TAG_PARTITION_CONFIG("bootloader", 128 * 1024, 0x00000000, 0x00000003),
77 OMAP_TAG_PARTITION_CONFIG("config", 384 * 1024, 0x00020000, 0x00000000),
78 OMAP_TAG_PARTITION_CONFIG("log", 256 * 1024, 0x00080000, 0x00000000),
79 OMAP_TAG_PARTITION_CONFIG("kernel", 2 * 1024*1024, 0x000c0000, 0x00000000),
80 OMAP_TAG_PARTITION_CONFIG("initfs", 2 * 1024*1024, 0x002c0000, 0x00000000),
81 OMAP_TAG_PARTITION_CONFIG("rootfs", 257280 * 1024, 0x004c0000, 0x00000000),
Pali Rohár248ef0a2012-10-29 07:54:01 +000082 OMAP_TAG_BOOT_REASON_CONFIG("pwr_key"),
83 OMAP_TAG_VERSION_STR_CONFIG("product", "RX-51"),
84 OMAP_TAG_VERSION_STR_CONFIG("hw-build", "2101"),
85 OMAP_TAG_VERSION_STR_CONFIG("nolo", "1.4.14"),
86 OMAP_TAG_VERSION_STR_CONFIG("boot-mode", "normal"),
87 { }
88};
89
90static char *boot_reason_ptr;
91static char *hw_build_ptr;
92static char *nolo_version_ptr;
93static char *boot_mode_ptr;
Pali Rohár02f45842020-04-01 00:35:14 +020094static int serial_was_console_enabled;
Pali Rohár248ef0a2012-10-29 07:54:01 +000095
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;
Pali Rohár02f45842020-04-01 00:35:14 +0200151 case OMAP_TAG_UART:
Pali Roháre01ae762020-06-01 00:29:10 +0200152 if (t->u.uart.enabled_uarts)
Pali Rohár02f45842020-04-01 00:35:14 +0200153 serial_was_console_enabled = 1;
154 break;
155 case OMAP_TAG_SERIAL_CONSOLE:
156 serial_was_console_enabled = 1;
157 break;
Pali Rohár248ef0a2012-10-29 07:54:01 +0000158 default:
159 break;
160 }
161 t = tag_omap_next(t);
162 }
163}
164
165/*
166 * Routine: reuse_atags
167 * Description: Reuse atags from previous bootloader.
168 * Reuse only only HW build, boot reason, boot mode and nolo
169 */
170static void reuse_atags(void)
171{
172 struct tag *t = (struct tag *)gd->bd->bi_boot_params;
173
174 /* First tag must be ATAG_CORE */
175 if (t->hdr.tag != ATAG_CORE)
176 return;
177
178 if (!boot_reason_ptr || !hw_build_ptr)
179 return;
180
181 /* Last tag must be ATAG_NONE */
182 while (t->hdr.tag != ATAG_NONE) {
183 switch (t->hdr.tag) {
184 case ATAG_REVISION:
185 memset(hw_build_ptr, 0, 12);
186 sprintf(hw_build_ptr, "%x", t->u.revision.rev);
187 break;
188 case ATAG_BOARD:
189 reuse_omap_atags((struct tag_omap *)&t->u);
190 break;
191 default:
192 break;
193 }
194 t = tag_next(t);
195 }
196}
197
198/*
199 * Routine: board_init
200 * Description: Early hardware init.
201 */
202int board_init(void)
203{
Ivaylo Dimitrovbe2ff862020-10-31 17:32:49 +0100204#if defined(CONFIG_CMD_ONENAND)
205 const u32 gpmc_regs_onenandrx51[GPMC_MAX_REG] = {
206 ONENAND_GPMC_CONFIG1_RX51,
207 ONENAND_GPMC_CONFIG2_RX51,
208 ONENAND_GPMC_CONFIG3_RX51,
209 ONENAND_GPMC_CONFIG4_RX51,
210 ONENAND_GPMC_CONFIG5_RX51,
211 ONENAND_GPMC_CONFIG6_RX51,
212 0
213 };
214#endif
Pali Rohár248ef0a2012-10-29 07:54:01 +0000215 /* in SRAM or SDRAM, finish GPMC */
216 gpmc_init();
Ivaylo Dimitrovbe2ff862020-10-31 17:32:49 +0100217#if defined(CONFIG_CMD_ONENAND)
218 enable_gpmc_cs_config(gpmc_regs_onenandrx51, &gpmc_cfg->cs[0],
219 CONFIG_SYS_ONENAND_BASE, GPMC_SIZE_256M);
220#endif
Pali Rohár6327bac2020-10-31 17:32:46 +0100221 /* Enable the clks & power */
222 per_clocks_enable();
Pali Rohár248ef0a2012-10-29 07:54:01 +0000223 /* boot param addr */
224 gd->bd->bi_boot_params = OMAP34XX_SDRC_CS0 + 0x100;
225 return 0;
226}
227
228/*
229 * Routine: get_board_revision
230 * Description: Return board revision.
231 */
232u32 get_board_rev(void)
233{
234 return simple_strtol(hw_build_ptr, NULL, 16);
235}
236
237/*
238 * Routine: setup_board_tags
239 * Description: Append board specific boot tags.
240 */
241void setup_board_tags(struct tag **in_params)
242{
243 int setup_console_atag;
244 char *setup_boot_reason_atag;
245 char *setup_boot_mode_atag;
246 char *str;
247 int i;
248 int size;
249 int total_size;
250 struct tag *params;
251 struct tag_omap *t;
252
253 params = (struct tag *)gd->bd->bi_boot_params;
254
255 params->u.core.flags = 0x0;
256 params->u.core.pagesize = 0x1000;
257 params->u.core.rootdev = 0x0;
258
259 /* append omap atag only if env setup_omap_atag is set to 1 */
Simon Glass64b723f2017-08-03 12:22:12 -0600260 str = env_get("setup_omap_atag");
Pali Rohár248ef0a2012-10-29 07:54:01 +0000261 if (!str || str[0] != '1')
262 return;
263
Simon Glass64b723f2017-08-03 12:22:12 -0600264 str = env_get("setup_console_atag");
Pali Rohár02f45842020-04-01 00:35:14 +0200265 if (str && str[0]) {
266 if (str[0] == '1')
267 setup_console_atag = 1;
268 else
269 setup_console_atag = 0;
270 } else {
271 if (serial_was_console_enabled)
272 setup_console_atag = 1;
273 else
274 setup_console_atag = 0;
275 }
Pali Rohár248ef0a2012-10-29 07:54:01 +0000276
Simon Glass64b723f2017-08-03 12:22:12 -0600277 setup_boot_reason_atag = env_get("setup_boot_reason_atag");
278 setup_boot_mode_atag = env_get("setup_boot_mode_atag");
Pali Rohár248ef0a2012-10-29 07:54:01 +0000279
280 params = *in_params;
281 t = (struct tag_omap *)&params->u;
282 total_size = sizeof(struct tag_header);
283
284 for (i = 0; omap[i].hdr.tag; i++) {
285
286 /* skip serial console tag */
287 if (!setup_console_atag &&
288 omap[i].hdr.tag == OMAP_TAG_SERIAL_CONSOLE)
289 continue;
290
291 size = omap[i].hdr.size + sizeof(struct tag_omap_header);
292 memcpy(t, &omap[i], size);
293
294 /* set uart tag to 0 - disable serial console */
295 if (!setup_console_atag && omap[i].hdr.tag == OMAP_TAG_UART)
296 t->u.uart.enabled_uarts = 0;
297
298 /* change boot reason */
299 if (setup_boot_reason_atag &&
300 omap[i].hdr.tag == OMAP_TAG_BOOT_REASON) {
301 memset(t->u.boot_reason.reason_str, 0, 12);
302 strcpy(t->u.boot_reason.reason_str,
303 setup_boot_reason_atag);
304 }
305
306 /* change boot mode */
307 if (setup_boot_mode_atag &&
308 omap[i].hdr.tag == OMAP_TAG_VERSION_STR &&
309 strcmp(omap[i].u.version.component, "boot-mode") == 0) {
310 memset(t->u.version.version, 0, 12);
311 strcpy(t->u.version.version, setup_boot_mode_atag);
312 }
313
314 total_size += size;
315 t = tag_omap_next(t);
316
317 }
318
319 params->hdr.tag = ATAG_BOARD;
320 params->hdr.size = total_size >> 2;
321 params = tag_next(params);
322
323 *in_params = params;
324}
325
326/*
327 * Routine: video_hw_init
328 * Description: Set up the GraphicDevice depending on sys_boot.
329 */
330void *video_hw_init(void)
331{
332 /* fill in Graphic Device */
333 gdev.frameAdrs = 0x8f9c0000;
334 gdev.winSizeX = 800;
335 gdev.winSizeY = 480;
336 gdev.gdfBytesPP = 2;
337 gdev.gdfIndex = GDF_16BIT_565RGB;
338 memset((void *)gdev.frameAdrs, 0, 0xbb800);
339 return (void *) &gdev;
340}
341
342/*
343 * Routine: twl4030_regulator_set_mode
344 * Description: Set twl4030 regulator mode over i2c powerbus.
345 */
346static void twl4030_regulator_set_mode(u8 id, u8 mode)
347{
348 u16 msg = MSG_SINGULAR(DEV_GRP_P1, id, mode);
Nishanth Menond26a1062013-03-26 05:20:49 +0000349 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
350 TWL4030_PM_MASTER_PB_WORD_MSB, msg >> 8);
351 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
352 TWL4030_PM_MASTER_PB_WORD_LSB, msg & 0xff);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000353}
354
355static void omap3_emu_romcode_call(u32 service_id, u32 *parameters)
356{
357 u32 i, num_params = *parameters;
358 u32 *sram_scratch_space = (u32 *)OMAP3_PUBLIC_SRAM_SCRATCH_AREA;
359
360 /*
361 * copy the parameters to an un-cached area to avoid coherency
362 * issues
363 */
364 for (i = 0; i < num_params; i++) {
365 __raw_writel(*parameters, sram_scratch_space);
366 parameters++;
367 sram_scratch_space++;
368 }
369
370 /* Now make the PPA call */
371 do_omap3_emu_romcode_call(service_id, OMAP3_PUBLIC_SRAM_SCRATCH_AREA);
372}
373
Nishanth Menon53fee1e2015-03-09 17:12:09 -0500374void omap3_set_aux_cr_secure(u32 acr)
375{
376 struct emu_hal_params_rx51 emu_romcode_params = { 0, };
377
378 emu_romcode_params.num_params = 2;
379 emu_romcode_params.param1 = acr;
380
381 omap3_emu_romcode_call(OMAP3_EMU_HAL_API_WRITE_ACR,
382 (u32 *)&emu_romcode_params);
383}
384
Pali Rohár248ef0a2012-10-29 07:54:01 +0000385/*
386 * Routine: omap3_update_aux_cr_secure_rx51
387 * Description: Modify the contents Auxiliary Control Register.
388 * Parameters:
389 * set_bits - bits to set in ACR
390 * clr_bits - bits to clear in ACR
391 */
392static void omap3_update_aux_cr_secure_rx51(u32 set_bits, u32 clear_bits)
393{
Pali Rohár248ef0a2012-10-29 07:54:01 +0000394 u32 acr;
395
396 /* Read ACR */
397 asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r" (acr));
398 acr &= ~clear_bits;
399 acr |= set_bits;
Nishanth Menon53fee1e2015-03-09 17:12:09 -0500400 omap3_set_aux_cr_secure(acr);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000401}
402
403/*
404 * Routine: misc_init_r
405 * Description: Configure board specific parts.
406 */
407int misc_init_r(void)
408{
Pali Rohárd73afb22020-10-26 23:45:11 +0100409 struct udevice *dev;
Pali Rohár248ef0a2012-10-29 07:54:01 +0000410 char buf[12];
411 u8 state;
412
Pali Rohár977229b2020-10-31 17:32:47 +0100413 /* disable lp5523 led */
Pali Rohárd73afb22020-10-26 23:45:11 +0100414 if (i2c_get_chip_for_busnum(1, 0x32, 1, &dev) == 0)
Pali Rohár977229b2020-10-31 17:32:47 +0100415 dm_i2c_reg_write(dev, 0x00, 0x00);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000416
417 /* initialize twl4030 power managment */
418 twl4030_power_init();
Pali Rohárcc58d292021-01-16 01:04:54 +0100419 twl4030_power_mmc_init(0);
420 twl4030_power_mmc_init(1);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000421
422 /* set VSIM to 1.8V */
423 twl4030_pmrecv_vsel_cfg(TWL4030_PM_RECEIVER_VSIM_DEDICATED,
424 TWL4030_PM_RECEIVER_VSIM_VSEL_18,
425 TWL4030_PM_RECEIVER_VSIM_DEV_GRP,
426 TWL4030_PM_RECEIVER_DEV_GRP_P1);
427
428 /* store I2C access state */
Nishanth Menon5d9d6f72013-03-26 05:20:50 +0000429 twl4030_i2c_read_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
430 &state);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000431
432 /* enable I2C access to powerbus (needed for twl4030 regulator) */
Nishanth Menond26a1062013-03-26 05:20:49 +0000433 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
434 0x02);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000435
436 /* set VAUX3, VSIM and VMMC1 state to active - enable eMMC memory */
437 twl4030_regulator_set_mode(RES_VAUX3, RES_STATE_ACTIVE);
438 twl4030_regulator_set_mode(RES_VSIM, RES_STATE_ACTIVE);
439 twl4030_regulator_set_mode(RES_VMMC1, RES_STATE_ACTIVE);
440
441 /* restore I2C access state */
Nishanth Menond26a1062013-03-26 05:20:49 +0000442 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
443 state);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000444
445 /* set env variable attkernaddr for relocated kernel */
446 sprintf(buf, "%#x", KERNEL_ADDRESS);
Simon Glass6a38e412017-08-03 12:22:09 -0600447 env_set("attkernaddr", buf);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000448
449 /* initialize omap tags */
450 init_omap_tags();
451
452 /* reuse atags from previous bootloader */
453 reuse_atags();
454
Paul Kocialkowski6bc318e2015-08-27 19:37:13 +0200455 omap_die_id_display();
Pali Rohár248ef0a2012-10-29 07:54:01 +0000456 print_cpuinfo();
457
458 /*
459 * Cortex-A8(r1p0..r1p2) errata 430973 workaround
460 * Set IBE bit in Auxiliary Control Register
Pali Rohár415b8042015-01-08 10:11:40 +0100461 *
462 * Call this routine only on real secure device
463 * Qemu does not implement secure PPA and crash
Pali Rohár248ef0a2012-10-29 07:54:01 +0000464 */
Pali Rohár415b8042015-01-08 10:11:40 +0100465 if (get_device_type() == HS_DEVICE)
466 omap3_update_aux_cr_secure_rx51(1 << 6, 0);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000467
468 return 0;
469}
470
471/*
472 * Routine: set_muxconf_regs
473 * Description: Setting up the configuration Mux registers specific to the
474 * hardware. Many pins need to be moved from protect to primary
475 * mode.
476 */
477void set_muxconf_regs(void)
478{
479 MUX_RX51();
480}
481
482static unsigned long int twl_wd_time; /* last time of watchdog reset */
483static unsigned long int twl_i2c_lock;
484
485/*
486 * Routine: hw_watchdog_reset
487 * Description: Reset timeout of twl4030 watchdog.
488 */
489void hw_watchdog_reset(void)
490{
491 u8 timeout = 0;
492
493 /* do not reset watchdog too often - max every 4s */
494 if (get_timer(twl_wd_time) < 4 * CONFIG_SYS_HZ)
495 return;
496
497 /* localy lock twl4030 i2c bus */
498 if (test_and_set_bit(0, &twl_i2c_lock))
499 return;
500
501 /* read actual watchdog timeout */
Nishanth Menon5d9d6f72013-03-26 05:20:50 +0000502 twl4030_i2c_read_u8(TWL4030_CHIP_PM_RECEIVER,
503 TWL4030_PM_RECEIVER_WATCHDOG_CFG, &timeout);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000504
505 /* timeout 0 means watchdog is disabled */
506 /* reset watchdog timeout to 31s (maximum) */
507 if (timeout != 0)
Nishanth Menond26a1062013-03-26 05:20:49 +0000508 twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER,
509 TWL4030_PM_RECEIVER_WATCHDOG_CFG, 31);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000510
511 /* store last watchdog reset time */
512 twl_wd_time = get_timer(0);
513
514 /* localy unlock twl4030 i2c bus */
515 test_and_clear_bit(0, &twl_i2c_lock);
516}
517
518/*
519 * TWL4030 keypad handler for cfb_console
520 */
521
522static const char keymap[] = {
523 /* normal */
524 'q', 'o', 'p', ',', '\b', 0, 'a', 's',
525 'w', 'd', 'f', 'g', 'h', 'j', 'k', 'l',
526 'e', '.', 0, '\r', 0, 'z', 'x', 'c',
527 'r', 'v', 'b', 'n', 'm', ' ', ' ', 0,
528 't', 0, 0, 0, 0, 0, 0, 0,
529 'y', 0, 0, 0, 0, 0, 0, 0,
530 'u', 0, 0, 0, 0, 0, 0, 0,
531 'i', 5, 6, 0, 0, 0, 0, 0,
532 /* fn */
533 '1', '9', '0', '=', '\b', 0, '*', '+',
534 '2', '#', '-', '_', '(', ')', '&', '!',
535 '3', '?', '^', '\r', 0, 156, '$', 238,
536 '4', '/', '\\', '"', '\'', '@', 0, '<',
537 '5', '|', '>', 0, 0, 0, 0, 0,
538 '6', 0, 0, 0, 0, 0, 0, 0,
539 '7', 0, 0, 0, 0, 0, 0, 0,
540 '8', 16, 17, 0, 0, 0, 0, 0,
541};
542
543static u8 keys[8];
544static u8 old_keys[8] = {0, 0, 0, 0, 0, 0, 0, 0};
545#define KEYBUF_SIZE 32
546static u8 keybuf[KEYBUF_SIZE];
547static u8 keybuf_head;
548static u8 keybuf_tail;
549
550/*
551 * Routine: rx51_kp_init
552 * Description: Initialize HW keyboard.
553 */
554int rx51_kp_init(void)
555{
556 int ret = 0;
557 u8 ctrl;
Nishanth Menon5d9d6f72013-03-26 05:20:50 +0000558 ret = twl4030_i2c_read_u8(TWL4030_CHIP_KEYPAD,
559 TWL4030_KEYPAD_KEYP_CTRL_REG, &ctrl);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000560
561 if (ret)
562 return ret;
563
564 /* turn on keyboard and use hardware scanning */
565 ctrl |= TWL4030_KEYPAD_CTRL_KBD_ON;
566 ctrl |= TWL4030_KEYPAD_CTRL_SOFT_NRST;
567 ctrl |= TWL4030_KEYPAD_CTRL_SOFTMODEN;
Nishanth Menond26a1062013-03-26 05:20:49 +0000568 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
569 TWL4030_KEYPAD_KEYP_CTRL_REG, ctrl);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000570 /* enable key event status */
Nishanth Menond26a1062013-03-26 05:20:49 +0000571 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
572 TWL4030_KEYPAD_KEYP_IMR1, 0xfe);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000573 /* enable interrupt generation on rising and falling */
574 /* this is a workaround for qemu twl4030 emulation */
Nishanth Menond26a1062013-03-26 05:20:49 +0000575 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
576 TWL4030_KEYPAD_KEYP_EDR, 0x57);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000577 /* enable ISR clear on read */
Nishanth Menond26a1062013-03-26 05:20:49 +0000578 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
579 TWL4030_KEYPAD_KEYP_SIH_CTRL, 0x05);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000580 return 0;
581}
582
583static void rx51_kp_fill(u8 k, u8 mods)
584{
585 /* check if some cursor key without meta fn key was pressed */
586 if (!(mods & 2) && (k == 18 || k == 31 || k == 33 || k == 34)) {
587 keybuf[keybuf_tail++] = '\e';
588 keybuf_tail %= KEYBUF_SIZE;
589 keybuf[keybuf_tail++] = '[';
590 keybuf_tail %= KEYBUF_SIZE;
591 if (k == 18) /* up */
592 keybuf[keybuf_tail++] = 'A';
593 else if (k == 31) /* left */
594 keybuf[keybuf_tail++] = 'D';
595 else if (k == 33) /* down */
596 keybuf[keybuf_tail++] = 'B';
597 else if (k == 34) /* right */
598 keybuf[keybuf_tail++] = 'C';
599 keybuf_tail %= KEYBUF_SIZE;
600 return;
601 }
602
603 if (mods & 2) { /* fn meta key was pressed */
604 k = keymap[k+64];
605 } else {
606 k = keymap[k];
607 if (mods & 1) { /* ctrl key was pressed */
608 if (k >= 'a' && k <= 'z')
609 k -= 'a' - 1;
610 }
611 if (mods & 4) { /* shift key was pressed */
612 if (k >= 'a' && k <= 'z')
613 k += 'A' - 'a';
614 else if (k == '.')
615 k = ':';
616 else if (k == ',')
617 k = ';';
618 }
619 }
620 keybuf[keybuf_tail++] = k;
621 keybuf_tail %= KEYBUF_SIZE;
622}
623
624/*
625 * Routine: rx51_kp_tstc
626 * Description: Test if key was pressed (from buffer).
627 */
Simon Glass0d1e1f72014-07-23 06:54:59 -0600628int rx51_kp_tstc(struct stdio_dev *sdev)
Pali Rohár248ef0a2012-10-29 07:54:01 +0000629{
630 u8 c, r, dk, i;
631 u8 intr;
632 u8 mods;
633
634 /* localy lock twl4030 i2c bus */
635 if (test_and_set_bit(0, &twl_i2c_lock))
636 return 0;
637
638 /* twl4030 remembers up to 2 events */
639 for (i = 0; i < 2; i++) {
640
641 /* check interrupt register for events */
Nishanth Menon5d9d6f72013-03-26 05:20:50 +0000642 twl4030_i2c_read_u8(TWL4030_CHIP_KEYPAD,
643 TWL4030_KEYPAD_KEYP_ISR1 + (2 * i), &intr);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000644
645 /* no event */
646 if (!(intr&1))
647 continue;
648
649 /* read the key state */
Pali Rohárd73afb22020-10-26 23:45:11 +0100650 twl4030_i2c_read(TWL4030_CHIP_KEYPAD,
651 TWL4030_KEYPAD_FULL_CODE_7_0, keys, 8);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000652
653 /* cut out modifier keys from the keystate */
654 mods = keys[4] >> 4;
655 keys[4] &= 0x0f;
656
657 for (c = 0; c < 8; c++) {
658
659 /* get newly pressed keys only */
660 dk = ((keys[c] ^ old_keys[c])&keys[c]);
661 old_keys[c] = keys[c];
662
663 /* fill the keybuf */
664 for (r = 0; r < 8; r++) {
665 if (dk&1)
666 rx51_kp_fill((c*8)+r, mods);
667 dk = dk >> 1;
668 }
669
670 }
671
672 }
673
674 /* localy unlock twl4030 i2c bus */
675 test_and_clear_bit(0, &twl_i2c_lock);
676
677 return (KEYBUF_SIZE + keybuf_tail - keybuf_head)%KEYBUF_SIZE;
678}
679
680/*
681 * Routine: rx51_kp_getc
682 * Description: Get last pressed key (from buffer).
683 */
Simon Glass0d1e1f72014-07-23 06:54:59 -0600684int rx51_kp_getc(struct stdio_dev *sdev)
Pali Rohár248ef0a2012-10-29 07:54:01 +0000685{
686 keybuf_head %= KEYBUF_SIZE;
Simon Glass0d1e1f72014-07-23 06:54:59 -0600687 while (!rx51_kp_tstc(sdev))
Pali Rohár248ef0a2012-10-29 07:54:01 +0000688 WATCHDOG_RESET();
689 return keybuf[keybuf_head++];
690}
691
Pali Rohárcc58d292021-01-16 01:04:54 +0100692static const struct mmc_config rx51_mmc_cfg = {
693 .host_caps = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS,
694 .f_min = 400000,
695 .f_max = 52000000,
696 .b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT,
697 .voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195,
698};
Paul Kocialkowski69559892014-11-08 20:55:47 +0100699
Pali Rohárcc58d292021-01-16 01:04:54 +0100700static const struct omap_hsmmc_plat rx51_mmc[] = {
701 { rx51_mmc_cfg, (struct hsmmc *)OMAP_HSMMC1_BASE },
702 { rx51_mmc_cfg, (struct hsmmc *)OMAP_HSMMC2_BASE },
703};
704
705U_BOOT_DRVINFOS(rx51_mmc) = {
706 { "omap_hsmmc", &rx51_mmc[0] },
707 { "omap_hsmmc", &rx51_mmc[1] },
708};
Pali Rohárd73afb22020-10-26 23:45:11 +0100709
Simon Glassb75b15b2020-12-03 16:55:23 -0700710static const struct omap_i2c_plat rx51_i2c[] = {
Pali Rohárde39c112020-11-21 23:30:11 +0100711 { I2C_BASE1, 100000, OMAP_I2C_REV_V1 },
Pali Rohárd73afb22020-10-26 23:45:11 +0100712 { I2C_BASE2, 100000, OMAP_I2C_REV_V1 },
Pali Rohárde39c112020-11-21 23:30:11 +0100713 { I2C_BASE3, 100000, OMAP_I2C_REV_V1 },
Pali Rohárd73afb22020-10-26 23:45:11 +0100714};
715
Simon Glass1d8364a2020-12-28 20:34:54 -0700716U_BOOT_DRVINFOS(rx51_i2c) = {
Pali Rohárd73afb22020-10-26 23:45:11 +0100717 { "i2c_omap", &rx51_i2c[0] },
718 { "i2c_omap", &rx51_i2c[1] },
719 { "i2c_omap", &rx51_i2c[2] },
720};