blob: 84739ae129e74135b706905e8070980bab8f6b95 [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>
33#include <asm/io.h>
34#include <asm/setup.h>
35#include <asm/bitops.h>
36#include <asm/mach-types.h>
Pali Rohárd73afb22020-10-26 23:45:11 +010037#include <asm/omap_i2c.h>
Pali Rohár248ef0a2012-10-29 07:54:01 +000038#include <asm/arch/mux.h>
39#include <asm/arch/sys_proto.h>
40#include <asm/arch/mmc_host_def.h>
41
42#include "rx51.h"
43#include "tag_omap.h"
44
45DECLARE_GLOBAL_DATA_PTR;
46
47GraphicDevice gdev;
48
49const omap3_sysinfo sysinfo = {
50 DDR_STACKED,
51 "Nokia RX-51",
52 "OneNAND"
53};
54
55/* This structure contains default omap tags needed for booting Maemo 5 */
56static struct tag_omap omap[] = {
57 OMAP_TAG_UART_CONFIG(0x04),
58 OMAP_TAG_SERIAL_CONSOLE_CONFIG(0x03, 0x01C200),
59 OMAP_TAG_LCD_CONFIG("acx565akm", "internal", 90, 0x18),
60 OMAP_TAG_GPIO_SWITCH_CONFIG("cam_focus", 0x44, 0x1, 0x2, 0x0),
61 OMAP_TAG_GPIO_SWITCH_CONFIG("cam_launch", 0x45, 0x1, 0x2, 0x0),
62 OMAP_TAG_GPIO_SWITCH_CONFIG("cam_shutter", 0x6e, 0x1, 0x0, 0x0),
63 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_apeslpx", 0x46, 0x2, 0x2, 0x0),
64 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_bsi", 0x9d, 0x2, 0x2, 0x0),
65 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_en", 0x4a, 0x2, 0x2, 0x0),
66 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_rst", 0x4b, 0x6, 0x2, 0x0),
67 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_rst_rq", 0x49, 0x6, 0x2, 0x0),
68 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_wddis", 0x0d, 0x2, 0x2, 0x0),
69 OMAP_TAG_GPIO_SWITCH_CONFIG("headphone", 0xb1, 0x1, 0x1, 0x0),
70 OMAP_TAG_GPIO_SWITCH_CONFIG("kb_lock", 0x71, 0x1, 0x0, 0x0),
71 OMAP_TAG_GPIO_SWITCH_CONFIG("proximity", 0x59, 0x0, 0x0, 0x0),
72 OMAP_TAG_GPIO_SWITCH_CONFIG("sleep_ind", 0xa2, 0x2, 0x2, 0x0),
73 OMAP_TAG_GPIO_SWITCH_CONFIG("slide", GPIO_SLIDE, 0x0, 0x0, 0x0),
74 OMAP_TAG_WLAN_CX3110X_CONFIG(0x25, 0xff, 87, 42, -1),
Pali Rohár7ce37522020-04-01 00:35:13 +020075 OMAP_TAG_PARTITION_CONFIG("bootloader", 128 * 1024, 0x00000000, 0x00000003),
76 OMAP_TAG_PARTITION_CONFIG("config", 384 * 1024, 0x00020000, 0x00000000),
77 OMAP_TAG_PARTITION_CONFIG("log", 256 * 1024, 0x00080000, 0x00000000),
78 OMAP_TAG_PARTITION_CONFIG("kernel", 2 * 1024*1024, 0x000c0000, 0x00000000),
79 OMAP_TAG_PARTITION_CONFIG("initfs", 2 * 1024*1024, 0x002c0000, 0x00000000),
80 OMAP_TAG_PARTITION_CONFIG("rootfs", 257280 * 1024, 0x004c0000, 0x00000000),
Pali Rohár248ef0a2012-10-29 07:54:01 +000081 OMAP_TAG_BOOT_REASON_CONFIG("pwr_key"),
82 OMAP_TAG_VERSION_STR_CONFIG("product", "RX-51"),
83 OMAP_TAG_VERSION_STR_CONFIG("hw-build", "2101"),
84 OMAP_TAG_VERSION_STR_CONFIG("nolo", "1.4.14"),
85 OMAP_TAG_VERSION_STR_CONFIG("boot-mode", "normal"),
86 { }
87};
88
89static char *boot_reason_ptr;
90static char *hw_build_ptr;
91static char *nolo_version_ptr;
92static char *boot_mode_ptr;
Pali Rohár02f45842020-04-01 00:35:14 +020093static int serial_was_console_enabled;
Pali Rohár248ef0a2012-10-29 07:54:01 +000094
95/*
96 * Routine: init_omap_tags
97 * Description: Initialize pointers to values in tag_omap
98 */
99static void init_omap_tags(void)
100{
101 char *component;
102 char *version;
103 int i = 0;
104 while (omap[i].hdr.tag) {
105 switch (omap[i].hdr.tag) {
106 case OMAP_TAG_BOOT_REASON:
107 boot_reason_ptr = omap[i].u.boot_reason.reason_str;
108 break;
109 case OMAP_TAG_VERSION_STR:
110 component = omap[i].u.version.component;
111 version = omap[i].u.version.version;
112 if (strcmp(component, "hw-build") == 0)
113 hw_build_ptr = version;
114 else if (strcmp(component, "nolo") == 0)
115 nolo_version_ptr = version;
116 else if (strcmp(component, "boot-mode") == 0)
117 boot_mode_ptr = version;
118 break;
119 default:
120 break;
121 }
122 i++;
123 }
124}
125
126static void reuse_omap_atags(struct tag_omap *t)
127{
128 char *component;
129 char *version;
130 while (t->hdr.tag) {
131 switch (t->hdr.tag) {
132 case OMAP_TAG_BOOT_REASON:
133 memset(boot_reason_ptr, 0, 12);
134 strcpy(boot_reason_ptr, t->u.boot_reason.reason_str);
135 break;
136 case OMAP_TAG_VERSION_STR:
137 component = t->u.version.component;
138 version = t->u.version.version;
139 if (strcmp(component, "hw-build") == 0) {
140 memset(hw_build_ptr, 0, 12);
141 strcpy(hw_build_ptr, version);
142 } else if (strcmp(component, "nolo") == 0) {
143 memset(nolo_version_ptr, 0, 12);
144 strcpy(nolo_version_ptr, version);
145 } else if (strcmp(component, "boot-mode") == 0) {
146 memset(boot_mode_ptr, 0, 12);
147 strcpy(boot_mode_ptr, version);
148 }
149 break;
Pali Rohár02f45842020-04-01 00:35:14 +0200150 case OMAP_TAG_UART:
Pali Roháre01ae762020-06-01 00:29:10 +0200151 if (t->u.uart.enabled_uarts)
Pali Rohár02f45842020-04-01 00:35:14 +0200152 serial_was_console_enabled = 1;
153 break;
154 case OMAP_TAG_SERIAL_CONSOLE:
155 serial_was_console_enabled = 1;
156 break;
Pali Rohár248ef0a2012-10-29 07:54:01 +0000157 default:
158 break;
159 }
160 t = tag_omap_next(t);
161 }
162}
163
164/*
165 * Routine: reuse_atags
166 * Description: Reuse atags from previous bootloader.
167 * Reuse only only HW build, boot reason, boot mode and nolo
168 */
169static void reuse_atags(void)
170{
171 struct tag *t = (struct tag *)gd->bd->bi_boot_params;
172
173 /* First tag must be ATAG_CORE */
174 if (t->hdr.tag != ATAG_CORE)
175 return;
176
177 if (!boot_reason_ptr || !hw_build_ptr)
178 return;
179
180 /* Last tag must be ATAG_NONE */
181 while (t->hdr.tag != ATAG_NONE) {
182 switch (t->hdr.tag) {
183 case ATAG_REVISION:
184 memset(hw_build_ptr, 0, 12);
185 sprintf(hw_build_ptr, "%x", t->u.revision.rev);
186 break;
187 case ATAG_BOARD:
188 reuse_omap_atags((struct tag_omap *)&t->u);
189 break;
190 default:
191 break;
192 }
193 t = tag_next(t);
194 }
195}
196
197/*
198 * Routine: board_init
199 * Description: Early hardware init.
200 */
201int board_init(void)
202{
Ivaylo Dimitrovbe2ff862020-10-31 17:32:49 +0100203#if defined(CONFIG_CMD_ONENAND)
204 const u32 gpmc_regs_onenandrx51[GPMC_MAX_REG] = {
205 ONENAND_GPMC_CONFIG1_RX51,
206 ONENAND_GPMC_CONFIG2_RX51,
207 ONENAND_GPMC_CONFIG3_RX51,
208 ONENAND_GPMC_CONFIG4_RX51,
209 ONENAND_GPMC_CONFIG5_RX51,
210 ONENAND_GPMC_CONFIG6_RX51,
211 0
212 };
213#endif
Pali Rohár248ef0a2012-10-29 07:54:01 +0000214 /* in SRAM or SDRAM, finish GPMC */
215 gpmc_init();
Ivaylo Dimitrovbe2ff862020-10-31 17:32:49 +0100216#if defined(CONFIG_CMD_ONENAND)
217 enable_gpmc_cs_config(gpmc_regs_onenandrx51, &gpmc_cfg->cs[0],
218 CONFIG_SYS_ONENAND_BASE, GPMC_SIZE_256M);
219#endif
Pali Rohár6327bac2020-10-31 17:32:46 +0100220 /* Enable the clks & power */
221 per_clocks_enable();
Pali Rohár248ef0a2012-10-29 07:54:01 +0000222 /* boot param addr */
223 gd->bd->bi_boot_params = OMAP34XX_SDRC_CS0 + 0x100;
224 return 0;
225}
226
227/*
228 * Routine: get_board_revision
229 * Description: Return board revision.
230 */
231u32 get_board_rev(void)
232{
233 return simple_strtol(hw_build_ptr, NULL, 16);
234}
235
236/*
237 * Routine: setup_board_tags
238 * Description: Append board specific boot tags.
239 */
240void setup_board_tags(struct tag **in_params)
241{
242 int setup_console_atag;
243 char *setup_boot_reason_atag;
244 char *setup_boot_mode_atag;
245 char *str;
246 int i;
247 int size;
248 int total_size;
249 struct tag *params;
250 struct tag_omap *t;
251
252 params = (struct tag *)gd->bd->bi_boot_params;
253
254 params->u.core.flags = 0x0;
255 params->u.core.pagesize = 0x1000;
256 params->u.core.rootdev = 0x0;
257
258 /* append omap atag only if env setup_omap_atag is set to 1 */
Simon Glass64b723f2017-08-03 12:22:12 -0600259 str = env_get("setup_omap_atag");
Pali Rohár248ef0a2012-10-29 07:54:01 +0000260 if (!str || str[0] != '1')
261 return;
262
Simon Glass64b723f2017-08-03 12:22:12 -0600263 str = env_get("setup_console_atag");
Pali Rohár02f45842020-04-01 00:35:14 +0200264 if (str && str[0]) {
265 if (str[0] == '1')
266 setup_console_atag = 1;
267 else
268 setup_console_atag = 0;
269 } else {
270 if (serial_was_console_enabled)
271 setup_console_atag = 1;
272 else
273 setup_console_atag = 0;
274 }
Pali Rohár248ef0a2012-10-29 07:54:01 +0000275
Simon Glass64b723f2017-08-03 12:22:12 -0600276 setup_boot_reason_atag = env_get("setup_boot_reason_atag");
277 setup_boot_mode_atag = env_get("setup_boot_mode_atag");
Pali Rohár248ef0a2012-10-29 07:54:01 +0000278
279 params = *in_params;
280 t = (struct tag_omap *)&params->u;
281 total_size = sizeof(struct tag_header);
282
283 for (i = 0; omap[i].hdr.tag; i++) {
284
285 /* skip serial console tag */
286 if (!setup_console_atag &&
287 omap[i].hdr.tag == OMAP_TAG_SERIAL_CONSOLE)
288 continue;
289
290 size = omap[i].hdr.size + sizeof(struct tag_omap_header);
291 memcpy(t, &omap[i], size);
292
293 /* set uart tag to 0 - disable serial console */
294 if (!setup_console_atag && omap[i].hdr.tag == OMAP_TAG_UART)
295 t->u.uart.enabled_uarts = 0;
296
297 /* change boot reason */
298 if (setup_boot_reason_atag &&
299 omap[i].hdr.tag == OMAP_TAG_BOOT_REASON) {
300 memset(t->u.boot_reason.reason_str, 0, 12);
301 strcpy(t->u.boot_reason.reason_str,
302 setup_boot_reason_atag);
303 }
304
305 /* change boot mode */
306 if (setup_boot_mode_atag &&
307 omap[i].hdr.tag == OMAP_TAG_VERSION_STR &&
308 strcmp(omap[i].u.version.component, "boot-mode") == 0) {
309 memset(t->u.version.version, 0, 12);
310 strcpy(t->u.version.version, setup_boot_mode_atag);
311 }
312
313 total_size += size;
314 t = tag_omap_next(t);
315
316 }
317
318 params->hdr.tag = ATAG_BOARD;
319 params->hdr.size = total_size >> 2;
320 params = tag_next(params);
321
322 *in_params = params;
323}
324
325/*
326 * Routine: video_hw_init
327 * Description: Set up the GraphicDevice depending on sys_boot.
328 */
329void *video_hw_init(void)
330{
331 /* fill in Graphic Device */
332 gdev.frameAdrs = 0x8f9c0000;
333 gdev.winSizeX = 800;
334 gdev.winSizeY = 480;
335 gdev.gdfBytesPP = 2;
336 gdev.gdfIndex = GDF_16BIT_565RGB;
337 memset((void *)gdev.frameAdrs, 0, 0xbb800);
338 return (void *) &gdev;
339}
340
341/*
342 * Routine: twl4030_regulator_set_mode
343 * Description: Set twl4030 regulator mode over i2c powerbus.
344 */
345static void twl4030_regulator_set_mode(u8 id, u8 mode)
346{
347 u16 msg = MSG_SINGULAR(DEV_GRP_P1, id, mode);
Nishanth Menond26a1062013-03-26 05:20:49 +0000348 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
349 TWL4030_PM_MASTER_PB_WORD_MSB, msg >> 8);
350 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
351 TWL4030_PM_MASTER_PB_WORD_LSB, msg & 0xff);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000352}
353
354static void omap3_emu_romcode_call(u32 service_id, u32 *parameters)
355{
356 u32 i, num_params = *parameters;
357 u32 *sram_scratch_space = (u32 *)OMAP3_PUBLIC_SRAM_SCRATCH_AREA;
358
359 /*
360 * copy the parameters to an un-cached area to avoid coherency
361 * issues
362 */
363 for (i = 0; i < num_params; i++) {
364 __raw_writel(*parameters, sram_scratch_space);
365 parameters++;
366 sram_scratch_space++;
367 }
368
369 /* Now make the PPA call */
370 do_omap3_emu_romcode_call(service_id, OMAP3_PUBLIC_SRAM_SCRATCH_AREA);
371}
372
Nishanth Menon53fee1e2015-03-09 17:12:09 -0500373void omap3_set_aux_cr_secure(u32 acr)
374{
375 struct emu_hal_params_rx51 emu_romcode_params = { 0, };
376
377 emu_romcode_params.num_params = 2;
378 emu_romcode_params.param1 = acr;
379
380 omap3_emu_romcode_call(OMAP3_EMU_HAL_API_WRITE_ACR,
381 (u32 *)&emu_romcode_params);
382}
383
Pali Rohár248ef0a2012-10-29 07:54:01 +0000384/*
385 * Routine: omap3_update_aux_cr_secure_rx51
386 * Description: Modify the contents Auxiliary Control Register.
387 * Parameters:
388 * set_bits - bits to set in ACR
389 * clr_bits - bits to clear in ACR
390 */
391static void omap3_update_aux_cr_secure_rx51(u32 set_bits, u32 clear_bits)
392{
Pali Rohár248ef0a2012-10-29 07:54:01 +0000393 u32 acr;
394
395 /* Read ACR */
396 asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r" (acr));
397 acr &= ~clear_bits;
398 acr |= set_bits;
Nishanth Menon53fee1e2015-03-09 17:12:09 -0500399 omap3_set_aux_cr_secure(acr);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000400}
401
402/*
403 * Routine: misc_init_r
404 * Description: Configure board specific parts.
405 */
406int misc_init_r(void)
407{
Pali Rohárd73afb22020-10-26 23:45:11 +0100408 struct udevice *dev;
Pali Rohár248ef0a2012-10-29 07:54:01 +0000409 char buf[12];
410 u8 state;
411
Pali Rohár977229b2020-10-31 17:32:47 +0100412 /* disable lp5523 led */
Pali Rohárd73afb22020-10-26 23:45:11 +0100413 if (i2c_get_chip_for_busnum(1, 0x32, 1, &dev) == 0)
Pali Rohár977229b2020-10-31 17:32:47 +0100414 dm_i2c_reg_write(dev, 0x00, 0x00);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000415
416 /* initialize twl4030 power managment */
417 twl4030_power_init();
Pali Rohárcc58d292021-01-16 01:04:54 +0100418 twl4030_power_mmc_init(0);
419 twl4030_power_mmc_init(1);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000420
421 /* set VSIM to 1.8V */
422 twl4030_pmrecv_vsel_cfg(TWL4030_PM_RECEIVER_VSIM_DEDICATED,
423 TWL4030_PM_RECEIVER_VSIM_VSEL_18,
424 TWL4030_PM_RECEIVER_VSIM_DEV_GRP,
425 TWL4030_PM_RECEIVER_DEV_GRP_P1);
426
427 /* store I2C access state */
Nishanth Menon5d9d6f72013-03-26 05:20:50 +0000428 twl4030_i2c_read_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
429 &state);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000430
431 /* enable I2C access to powerbus (needed for twl4030 regulator) */
Nishanth Menond26a1062013-03-26 05:20:49 +0000432 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
433 0x02);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000434
435 /* set VAUX3, VSIM and VMMC1 state to active - enable eMMC memory */
436 twl4030_regulator_set_mode(RES_VAUX3, RES_STATE_ACTIVE);
437 twl4030_regulator_set_mode(RES_VSIM, RES_STATE_ACTIVE);
438 twl4030_regulator_set_mode(RES_VMMC1, RES_STATE_ACTIVE);
439
440 /* restore I2C access state */
Nishanth Menond26a1062013-03-26 05:20:49 +0000441 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
442 state);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000443
444 /* set env variable attkernaddr for relocated kernel */
445 sprintf(buf, "%#x", KERNEL_ADDRESS);
Simon Glass6a38e412017-08-03 12:22:09 -0600446 env_set("attkernaddr", buf);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000447
448 /* initialize omap tags */
449 init_omap_tags();
450
451 /* reuse atags from previous bootloader */
452 reuse_atags();
453
Paul Kocialkowski6bc318e2015-08-27 19:37:13 +0200454 omap_die_id_display();
Pali Rohár248ef0a2012-10-29 07:54:01 +0000455 print_cpuinfo();
456
457 /*
458 * Cortex-A8(r1p0..r1p2) errata 430973 workaround
459 * Set IBE bit in Auxiliary Control Register
Pali Rohár415b8042015-01-08 10:11:40 +0100460 *
461 * Call this routine only on real secure device
462 * Qemu does not implement secure PPA and crash
Pali Rohár248ef0a2012-10-29 07:54:01 +0000463 */
Pali Rohár415b8042015-01-08 10:11:40 +0100464 if (get_device_type() == HS_DEVICE)
465 omap3_update_aux_cr_secure_rx51(1 << 6, 0);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000466
467 return 0;
468}
469
470/*
471 * Routine: set_muxconf_regs
472 * Description: Setting up the configuration Mux registers specific to the
473 * hardware. Many pins need to be moved from protect to primary
474 * mode.
475 */
476void set_muxconf_regs(void)
477{
478 MUX_RX51();
479}
480
481static unsigned long int twl_wd_time; /* last time of watchdog reset */
482static unsigned long int twl_i2c_lock;
483
484/*
485 * Routine: hw_watchdog_reset
486 * Description: Reset timeout of twl4030 watchdog.
487 */
488void hw_watchdog_reset(void)
489{
490 u8 timeout = 0;
491
492 /* do not reset watchdog too often - max every 4s */
493 if (get_timer(twl_wd_time) < 4 * CONFIG_SYS_HZ)
494 return;
495
496 /* localy lock twl4030 i2c bus */
497 if (test_and_set_bit(0, &twl_i2c_lock))
498 return;
499
500 /* read actual watchdog timeout */
Nishanth Menon5d9d6f72013-03-26 05:20:50 +0000501 twl4030_i2c_read_u8(TWL4030_CHIP_PM_RECEIVER,
502 TWL4030_PM_RECEIVER_WATCHDOG_CFG, &timeout);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000503
504 /* timeout 0 means watchdog is disabled */
505 /* reset watchdog timeout to 31s (maximum) */
506 if (timeout != 0)
Nishanth Menond26a1062013-03-26 05:20:49 +0000507 twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER,
508 TWL4030_PM_RECEIVER_WATCHDOG_CFG, 31);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000509
510 /* store last watchdog reset time */
511 twl_wd_time = get_timer(0);
512
513 /* localy unlock twl4030 i2c bus */
514 test_and_clear_bit(0, &twl_i2c_lock);
515}
516
517/*
518 * TWL4030 keypad handler for cfb_console
519 */
520
521static const char keymap[] = {
522 /* normal */
523 'q', 'o', 'p', ',', '\b', 0, 'a', 's',
524 'w', 'd', 'f', 'g', 'h', 'j', 'k', 'l',
525 'e', '.', 0, '\r', 0, 'z', 'x', 'c',
526 'r', 'v', 'b', 'n', 'm', ' ', ' ', 0,
527 't', 0, 0, 0, 0, 0, 0, 0,
528 'y', 0, 0, 0, 0, 0, 0, 0,
529 'u', 0, 0, 0, 0, 0, 0, 0,
530 'i', 5, 6, 0, 0, 0, 0, 0,
531 /* fn */
532 '1', '9', '0', '=', '\b', 0, '*', '+',
533 '2', '#', '-', '_', '(', ')', '&', '!',
534 '3', '?', '^', '\r', 0, 156, '$', 238,
535 '4', '/', '\\', '"', '\'', '@', 0, '<',
536 '5', '|', '>', 0, 0, 0, 0, 0,
537 '6', 0, 0, 0, 0, 0, 0, 0,
538 '7', 0, 0, 0, 0, 0, 0, 0,
539 '8', 16, 17, 0, 0, 0, 0, 0,
540};
541
542static u8 keys[8];
543static u8 old_keys[8] = {0, 0, 0, 0, 0, 0, 0, 0};
544#define KEYBUF_SIZE 32
545static u8 keybuf[KEYBUF_SIZE];
546static u8 keybuf_head;
547static u8 keybuf_tail;
548
549/*
550 * Routine: rx51_kp_init
551 * Description: Initialize HW keyboard.
552 */
553int rx51_kp_init(void)
554{
555 int ret = 0;
556 u8 ctrl;
Nishanth Menon5d9d6f72013-03-26 05:20:50 +0000557 ret = twl4030_i2c_read_u8(TWL4030_CHIP_KEYPAD,
558 TWL4030_KEYPAD_KEYP_CTRL_REG, &ctrl);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000559
560 if (ret)
561 return ret;
562
563 /* turn on keyboard and use hardware scanning */
564 ctrl |= TWL4030_KEYPAD_CTRL_KBD_ON;
565 ctrl |= TWL4030_KEYPAD_CTRL_SOFT_NRST;
566 ctrl |= TWL4030_KEYPAD_CTRL_SOFTMODEN;
Nishanth Menond26a1062013-03-26 05:20:49 +0000567 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
568 TWL4030_KEYPAD_KEYP_CTRL_REG, ctrl);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000569 /* enable key event status */
Nishanth Menond26a1062013-03-26 05:20:49 +0000570 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
571 TWL4030_KEYPAD_KEYP_IMR1, 0xfe);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000572 /* enable interrupt generation on rising and falling */
573 /* this is a workaround for qemu twl4030 emulation */
Nishanth Menond26a1062013-03-26 05:20:49 +0000574 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
575 TWL4030_KEYPAD_KEYP_EDR, 0x57);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000576 /* enable ISR clear on read */
Nishanth Menond26a1062013-03-26 05:20:49 +0000577 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
578 TWL4030_KEYPAD_KEYP_SIH_CTRL, 0x05);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000579 return 0;
580}
581
582static void rx51_kp_fill(u8 k, u8 mods)
583{
584 /* check if some cursor key without meta fn key was pressed */
585 if (!(mods & 2) && (k == 18 || k == 31 || k == 33 || k == 34)) {
586 keybuf[keybuf_tail++] = '\e';
587 keybuf_tail %= KEYBUF_SIZE;
588 keybuf[keybuf_tail++] = '[';
589 keybuf_tail %= KEYBUF_SIZE;
590 if (k == 18) /* up */
591 keybuf[keybuf_tail++] = 'A';
592 else if (k == 31) /* left */
593 keybuf[keybuf_tail++] = 'D';
594 else if (k == 33) /* down */
595 keybuf[keybuf_tail++] = 'B';
596 else if (k == 34) /* right */
597 keybuf[keybuf_tail++] = 'C';
598 keybuf_tail %= KEYBUF_SIZE;
599 return;
600 }
601
602 if (mods & 2) { /* fn meta key was pressed */
603 k = keymap[k+64];
604 } else {
605 k = keymap[k];
606 if (mods & 1) { /* ctrl key was pressed */
607 if (k >= 'a' && k <= 'z')
608 k -= 'a' - 1;
609 }
610 if (mods & 4) { /* shift key was pressed */
611 if (k >= 'a' && k <= 'z')
612 k += 'A' - 'a';
613 else if (k == '.')
614 k = ':';
615 else if (k == ',')
616 k = ';';
617 }
618 }
619 keybuf[keybuf_tail++] = k;
620 keybuf_tail %= KEYBUF_SIZE;
621}
622
623/*
624 * Routine: rx51_kp_tstc
625 * Description: Test if key was pressed (from buffer).
626 */
Simon Glass0d1e1f72014-07-23 06:54:59 -0600627int rx51_kp_tstc(struct stdio_dev *sdev)
Pali Rohár248ef0a2012-10-29 07:54:01 +0000628{
629 u8 c, r, dk, i;
630 u8 intr;
631 u8 mods;
632
633 /* localy lock twl4030 i2c bus */
634 if (test_and_set_bit(0, &twl_i2c_lock))
635 return 0;
636
637 /* twl4030 remembers up to 2 events */
638 for (i = 0; i < 2; i++) {
639
640 /* check interrupt register for events */
Nishanth Menon5d9d6f72013-03-26 05:20:50 +0000641 twl4030_i2c_read_u8(TWL4030_CHIP_KEYPAD,
642 TWL4030_KEYPAD_KEYP_ISR1 + (2 * i), &intr);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000643
644 /* no event */
645 if (!(intr&1))
646 continue;
647
648 /* read the key state */
Pali Rohárd73afb22020-10-26 23:45:11 +0100649 twl4030_i2c_read(TWL4030_CHIP_KEYPAD,
650 TWL4030_KEYPAD_FULL_CODE_7_0, keys, 8);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000651
652 /* cut out modifier keys from the keystate */
653 mods = keys[4] >> 4;
654 keys[4] &= 0x0f;
655
656 for (c = 0; c < 8; c++) {
657
658 /* get newly pressed keys only */
659 dk = ((keys[c] ^ old_keys[c])&keys[c]);
660 old_keys[c] = keys[c];
661
662 /* fill the keybuf */
663 for (r = 0; r < 8; r++) {
664 if (dk&1)
665 rx51_kp_fill((c*8)+r, mods);
666 dk = dk >> 1;
667 }
668
669 }
670
671 }
672
673 /* localy unlock twl4030 i2c bus */
674 test_and_clear_bit(0, &twl_i2c_lock);
675
676 return (KEYBUF_SIZE + keybuf_tail - keybuf_head)%KEYBUF_SIZE;
677}
678
679/*
680 * Routine: rx51_kp_getc
681 * Description: Get last pressed key (from buffer).
682 */
Simon Glass0d1e1f72014-07-23 06:54:59 -0600683int rx51_kp_getc(struct stdio_dev *sdev)
Pali Rohár248ef0a2012-10-29 07:54:01 +0000684{
685 keybuf_head %= KEYBUF_SIZE;
Simon Glass0d1e1f72014-07-23 06:54:59 -0600686 while (!rx51_kp_tstc(sdev))
Pali Rohár248ef0a2012-10-29 07:54:01 +0000687 WATCHDOG_RESET();
688 return keybuf[keybuf_head++];
689}
690
Pali Rohárcc58d292021-01-16 01:04:54 +0100691static const struct mmc_config rx51_mmc_cfg = {
692 .host_caps = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS,
693 .f_min = 400000,
694 .f_max = 52000000,
695 .b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT,
696 .voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195,
697};
Paul Kocialkowski69559892014-11-08 20:55:47 +0100698
Pali Rohárcc58d292021-01-16 01:04:54 +0100699static const struct omap_hsmmc_plat rx51_mmc[] = {
700 { rx51_mmc_cfg, (struct hsmmc *)OMAP_HSMMC1_BASE },
701 { rx51_mmc_cfg, (struct hsmmc *)OMAP_HSMMC2_BASE },
702};
703
704U_BOOT_DRVINFOS(rx51_mmc) = {
705 { "omap_hsmmc", &rx51_mmc[0] },
706 { "omap_hsmmc", &rx51_mmc[1] },
707};
Pali Rohárd73afb22020-10-26 23:45:11 +0100708
Simon Glassb75b15b2020-12-03 16:55:23 -0700709static const struct omap_i2c_plat rx51_i2c[] = {
Pali Rohárde39c112020-11-21 23:30:11 +0100710 { I2C_BASE1, 100000, OMAP_I2C_REV_V1 },
Pali Rohárd73afb22020-10-26 23:45:11 +0100711 { I2C_BASE2, 100000, OMAP_I2C_REV_V1 },
Pali Rohárde39c112020-11-21 23:30:11 +0100712 { I2C_BASE3, 100000, OMAP_I2C_REV_V1 },
Pali Rohárd73afb22020-10-26 23:45:11 +0100713};
714
Simon Glass1d8364a2020-12-28 20:34:54 -0700715U_BOOT_DRVINFOS(rx51_i2c) = {
Pali Rohárd73afb22020-10-26 23:45:11 +0100716 { "i2c_omap", &rx51_i2c[0] },
717 { "i2c_omap", &rx51_i2c[1] },
718 { "i2c_omap", &rx51_i2c[2] },
719};