blob: 7bd5fbd715207628e7f39e6bc83c36aa657e14fd [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
Pali Rohár248ef0a2012-10-29 07:54:01 +000043#include "tag_omap.h"
44
Pali Rohár9157a8c2021-02-07 14:50:15 +010045/* Needed for ROM SMC call */
46struct emu_hal_params_rx51 {
47 u32 num_params;
48 u32 param1;
49 u32 param2;
50 u32 param3;
51 u32 param4;
52};
53
54#define ONENAND_GPMC_CONFIG1_RX51 0xfb001202
55#define ONENAND_GPMC_CONFIG2_RX51 0x00111100
56#define ONENAND_GPMC_CONFIG3_RX51 0x00020200
57#define ONENAND_GPMC_CONFIG4_RX51 0x11001102
58#define ONENAND_GPMC_CONFIG5_RX51 0x03101616
59#define ONENAND_GPMC_CONFIG6_RX51 0x90060000
60
Pali Rohár248ef0a2012-10-29 07:54:01 +000061DECLARE_GLOBAL_DATA_PTR;
62
63GraphicDevice gdev;
64
65const omap3_sysinfo sysinfo = {
66 DDR_STACKED,
67 "Nokia RX-51",
68 "OneNAND"
69};
70
71/* This structure contains default omap tags needed for booting Maemo 5 */
72static struct tag_omap omap[] = {
73 OMAP_TAG_UART_CONFIG(0x04),
74 OMAP_TAG_SERIAL_CONSOLE_CONFIG(0x03, 0x01C200),
75 OMAP_TAG_LCD_CONFIG("acx565akm", "internal", 90, 0x18),
76 OMAP_TAG_GPIO_SWITCH_CONFIG("cam_focus", 0x44, 0x1, 0x2, 0x0),
77 OMAP_TAG_GPIO_SWITCH_CONFIG("cam_launch", 0x45, 0x1, 0x2, 0x0),
78 OMAP_TAG_GPIO_SWITCH_CONFIG("cam_shutter", 0x6e, 0x1, 0x0, 0x0),
79 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_apeslpx", 0x46, 0x2, 0x2, 0x0),
80 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_bsi", 0x9d, 0x2, 0x2, 0x0),
81 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_en", 0x4a, 0x2, 0x2, 0x0),
82 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_rst", 0x4b, 0x6, 0x2, 0x0),
83 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_rst_rq", 0x49, 0x6, 0x2, 0x0),
84 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_wddis", 0x0d, 0x2, 0x2, 0x0),
85 OMAP_TAG_GPIO_SWITCH_CONFIG("headphone", 0xb1, 0x1, 0x1, 0x0),
86 OMAP_TAG_GPIO_SWITCH_CONFIG("kb_lock", 0x71, 0x1, 0x0, 0x0),
87 OMAP_TAG_GPIO_SWITCH_CONFIG("proximity", 0x59, 0x0, 0x0, 0x0),
88 OMAP_TAG_GPIO_SWITCH_CONFIG("sleep_ind", 0xa2, 0x2, 0x2, 0x0),
89 OMAP_TAG_GPIO_SWITCH_CONFIG("slide", GPIO_SLIDE, 0x0, 0x0, 0x0),
90 OMAP_TAG_WLAN_CX3110X_CONFIG(0x25, 0xff, 87, 42, -1),
Pali Rohár7ce37522020-04-01 00:35:13 +020091 OMAP_TAG_PARTITION_CONFIG("bootloader", 128 * 1024, 0x00000000, 0x00000003),
92 OMAP_TAG_PARTITION_CONFIG("config", 384 * 1024, 0x00020000, 0x00000000),
93 OMAP_TAG_PARTITION_CONFIG("log", 256 * 1024, 0x00080000, 0x00000000),
94 OMAP_TAG_PARTITION_CONFIG("kernel", 2 * 1024*1024, 0x000c0000, 0x00000000),
95 OMAP_TAG_PARTITION_CONFIG("initfs", 2 * 1024*1024, 0x002c0000, 0x00000000),
96 OMAP_TAG_PARTITION_CONFIG("rootfs", 257280 * 1024, 0x004c0000, 0x00000000),
Pali Rohár248ef0a2012-10-29 07:54:01 +000097 OMAP_TAG_BOOT_REASON_CONFIG("pwr_key"),
98 OMAP_TAG_VERSION_STR_CONFIG("product", "RX-51"),
99 OMAP_TAG_VERSION_STR_CONFIG("hw-build", "2101"),
100 OMAP_TAG_VERSION_STR_CONFIG("nolo", "1.4.14"),
101 OMAP_TAG_VERSION_STR_CONFIG("boot-mode", "normal"),
102 { }
103};
104
105static char *boot_reason_ptr;
106static char *hw_build_ptr;
107static char *nolo_version_ptr;
108static char *boot_mode_ptr;
Pali Rohár02f45842020-04-01 00:35:14 +0200109static int serial_was_console_enabled;
Pali Rohár248ef0a2012-10-29 07:54:01 +0000110
111/*
112 * Routine: init_omap_tags
113 * Description: Initialize pointers to values in tag_omap
114 */
115static void init_omap_tags(void)
116{
117 char *component;
118 char *version;
119 int i = 0;
120 while (omap[i].hdr.tag) {
121 switch (omap[i].hdr.tag) {
122 case OMAP_TAG_BOOT_REASON:
123 boot_reason_ptr = omap[i].u.boot_reason.reason_str;
124 break;
125 case OMAP_TAG_VERSION_STR:
126 component = omap[i].u.version.component;
127 version = omap[i].u.version.version;
128 if (strcmp(component, "hw-build") == 0)
129 hw_build_ptr = version;
130 else if (strcmp(component, "nolo") == 0)
131 nolo_version_ptr = version;
132 else if (strcmp(component, "boot-mode") == 0)
133 boot_mode_ptr = version;
134 break;
135 default:
136 break;
137 }
138 i++;
139 }
140}
141
142static void reuse_omap_atags(struct tag_omap *t)
143{
144 char *component;
145 char *version;
146 while (t->hdr.tag) {
147 switch (t->hdr.tag) {
148 case OMAP_TAG_BOOT_REASON:
149 memset(boot_reason_ptr, 0, 12);
150 strcpy(boot_reason_ptr, t->u.boot_reason.reason_str);
151 break;
152 case OMAP_TAG_VERSION_STR:
153 component = t->u.version.component;
154 version = t->u.version.version;
155 if (strcmp(component, "hw-build") == 0) {
156 memset(hw_build_ptr, 0, 12);
157 strcpy(hw_build_ptr, version);
158 } else if (strcmp(component, "nolo") == 0) {
159 memset(nolo_version_ptr, 0, 12);
160 strcpy(nolo_version_ptr, version);
161 } else if (strcmp(component, "boot-mode") == 0) {
162 memset(boot_mode_ptr, 0, 12);
163 strcpy(boot_mode_ptr, version);
164 }
165 break;
Pali Rohár02f45842020-04-01 00:35:14 +0200166 case OMAP_TAG_UART:
Pali Roháre01ae762020-06-01 00:29:10 +0200167 if (t->u.uart.enabled_uarts)
Pali Rohár02f45842020-04-01 00:35:14 +0200168 serial_was_console_enabled = 1;
169 break;
170 case OMAP_TAG_SERIAL_CONSOLE:
171 serial_was_console_enabled = 1;
172 break;
Pali Rohár248ef0a2012-10-29 07:54:01 +0000173 default:
174 break;
175 }
176 t = tag_omap_next(t);
177 }
178}
179
180/*
181 * Routine: reuse_atags
182 * Description: Reuse atags from previous bootloader.
183 * Reuse only only HW build, boot reason, boot mode and nolo
184 */
185static void reuse_atags(void)
186{
187 struct tag *t = (struct tag *)gd->bd->bi_boot_params;
188
189 /* First tag must be ATAG_CORE */
190 if (t->hdr.tag != ATAG_CORE)
191 return;
192
193 if (!boot_reason_ptr || !hw_build_ptr)
194 return;
195
196 /* Last tag must be ATAG_NONE */
197 while (t->hdr.tag != ATAG_NONE) {
198 switch (t->hdr.tag) {
199 case ATAG_REVISION:
200 memset(hw_build_ptr, 0, 12);
201 sprintf(hw_build_ptr, "%x", t->u.revision.rev);
202 break;
203 case ATAG_BOARD:
204 reuse_omap_atags((struct tag_omap *)&t->u);
205 break;
206 default:
207 break;
208 }
209 t = tag_next(t);
210 }
211}
212
213/*
214 * Routine: board_init
215 * Description: Early hardware init.
216 */
217int board_init(void)
218{
Ivaylo Dimitrovbe2ff862020-10-31 17:32:49 +0100219#if defined(CONFIG_CMD_ONENAND)
220 const u32 gpmc_regs_onenandrx51[GPMC_MAX_REG] = {
221 ONENAND_GPMC_CONFIG1_RX51,
222 ONENAND_GPMC_CONFIG2_RX51,
223 ONENAND_GPMC_CONFIG3_RX51,
224 ONENAND_GPMC_CONFIG4_RX51,
225 ONENAND_GPMC_CONFIG5_RX51,
226 ONENAND_GPMC_CONFIG6_RX51,
227 0
228 };
229#endif
Pali Rohár248ef0a2012-10-29 07:54:01 +0000230 /* in SRAM or SDRAM, finish GPMC */
231 gpmc_init();
Ivaylo Dimitrovbe2ff862020-10-31 17:32:49 +0100232#if defined(CONFIG_CMD_ONENAND)
233 enable_gpmc_cs_config(gpmc_regs_onenandrx51, &gpmc_cfg->cs[0],
234 CONFIG_SYS_ONENAND_BASE, GPMC_SIZE_256M);
235#endif
Pali Rohár6327bac2020-10-31 17:32:46 +0100236 /* Enable the clks & power */
237 per_clocks_enable();
Pali Rohár248ef0a2012-10-29 07:54:01 +0000238 /* boot param addr */
239 gd->bd->bi_boot_params = OMAP34XX_SDRC_CS0 + 0x100;
240 return 0;
241}
242
243/*
244 * Routine: get_board_revision
245 * Description: Return board revision.
246 */
247u32 get_board_rev(void)
248{
249 return simple_strtol(hw_build_ptr, NULL, 16);
250}
251
252/*
253 * Routine: setup_board_tags
254 * Description: Append board specific boot tags.
255 */
256void setup_board_tags(struct tag **in_params)
257{
258 int setup_console_atag;
259 char *setup_boot_reason_atag;
260 char *setup_boot_mode_atag;
261 char *str;
262 int i;
263 int size;
264 int total_size;
265 struct tag *params;
266 struct tag_omap *t;
267
268 params = (struct tag *)gd->bd->bi_boot_params;
269
270 params->u.core.flags = 0x0;
271 params->u.core.pagesize = 0x1000;
272 params->u.core.rootdev = 0x0;
273
274 /* append omap atag only if env setup_omap_atag is set to 1 */
Simon Glass64b723f2017-08-03 12:22:12 -0600275 str = env_get("setup_omap_atag");
Pali Rohár248ef0a2012-10-29 07:54:01 +0000276 if (!str || str[0] != '1')
277 return;
278
Simon Glass64b723f2017-08-03 12:22:12 -0600279 str = env_get("setup_console_atag");
Pali Rohár02f45842020-04-01 00:35:14 +0200280 if (str && str[0]) {
281 if (str[0] == '1')
282 setup_console_atag = 1;
283 else
284 setup_console_atag = 0;
285 } else {
286 if (serial_was_console_enabled)
287 setup_console_atag = 1;
288 else
289 setup_console_atag = 0;
290 }
Pali Rohár248ef0a2012-10-29 07:54:01 +0000291
Simon Glass64b723f2017-08-03 12:22:12 -0600292 setup_boot_reason_atag = env_get("setup_boot_reason_atag");
293 setup_boot_mode_atag = env_get("setup_boot_mode_atag");
Pali Rohár248ef0a2012-10-29 07:54:01 +0000294
295 params = *in_params;
296 t = (struct tag_omap *)&params->u;
297 total_size = sizeof(struct tag_header);
298
299 for (i = 0; omap[i].hdr.tag; i++) {
300
301 /* skip serial console tag */
302 if (!setup_console_atag &&
303 omap[i].hdr.tag == OMAP_TAG_SERIAL_CONSOLE)
304 continue;
305
306 size = omap[i].hdr.size + sizeof(struct tag_omap_header);
307 memcpy(t, &omap[i], size);
308
309 /* set uart tag to 0 - disable serial console */
310 if (!setup_console_atag && omap[i].hdr.tag == OMAP_TAG_UART)
311 t->u.uart.enabled_uarts = 0;
312
313 /* change boot reason */
314 if (setup_boot_reason_atag &&
315 omap[i].hdr.tag == OMAP_TAG_BOOT_REASON) {
316 memset(t->u.boot_reason.reason_str, 0, 12);
317 strcpy(t->u.boot_reason.reason_str,
318 setup_boot_reason_atag);
319 }
320
321 /* change boot mode */
322 if (setup_boot_mode_atag &&
323 omap[i].hdr.tag == OMAP_TAG_VERSION_STR &&
324 strcmp(omap[i].u.version.component, "boot-mode") == 0) {
325 memset(t->u.version.version, 0, 12);
326 strcpy(t->u.version.version, setup_boot_mode_atag);
327 }
328
329 total_size += size;
330 t = tag_omap_next(t);
331
332 }
333
334 params->hdr.tag = ATAG_BOARD;
335 params->hdr.size = total_size >> 2;
336 params = tag_next(params);
337
338 *in_params = params;
339}
340
341/*
342 * Routine: video_hw_init
343 * Description: Set up the GraphicDevice depending on sys_boot.
344 */
345void *video_hw_init(void)
346{
347 /* fill in Graphic Device */
348 gdev.frameAdrs = 0x8f9c0000;
349 gdev.winSizeX = 800;
350 gdev.winSizeY = 480;
351 gdev.gdfBytesPP = 2;
352 gdev.gdfIndex = GDF_16BIT_565RGB;
353 memset((void *)gdev.frameAdrs, 0, 0xbb800);
354 return (void *) &gdev;
355}
356
357/*
358 * Routine: twl4030_regulator_set_mode
359 * Description: Set twl4030 regulator mode over i2c powerbus.
360 */
361static void twl4030_regulator_set_mode(u8 id, u8 mode)
362{
363 u16 msg = MSG_SINGULAR(DEV_GRP_P1, id, mode);
Nishanth Menond26a1062013-03-26 05:20:49 +0000364 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
365 TWL4030_PM_MASTER_PB_WORD_MSB, msg >> 8);
366 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
367 TWL4030_PM_MASTER_PB_WORD_LSB, msg & 0xff);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000368}
369
370static void omap3_emu_romcode_call(u32 service_id, u32 *parameters)
371{
372 u32 i, num_params = *parameters;
373 u32 *sram_scratch_space = (u32 *)OMAP3_PUBLIC_SRAM_SCRATCH_AREA;
374
375 /*
376 * copy the parameters to an un-cached area to avoid coherency
377 * issues
378 */
379 for (i = 0; i < num_params; i++) {
380 __raw_writel(*parameters, sram_scratch_space);
381 parameters++;
382 sram_scratch_space++;
383 }
384
385 /* Now make the PPA call */
386 do_omap3_emu_romcode_call(service_id, OMAP3_PUBLIC_SRAM_SCRATCH_AREA);
387}
388
Nishanth Menon53fee1e2015-03-09 17:12:09 -0500389void omap3_set_aux_cr_secure(u32 acr)
390{
391 struct emu_hal_params_rx51 emu_romcode_params = { 0, };
392
393 emu_romcode_params.num_params = 2;
394 emu_romcode_params.param1 = acr;
395
396 omap3_emu_romcode_call(OMAP3_EMU_HAL_API_WRITE_ACR,
397 (u32 *)&emu_romcode_params);
398}
399
Pali Rohár248ef0a2012-10-29 07:54:01 +0000400/*
401 * Routine: omap3_update_aux_cr_secure_rx51
402 * Description: Modify the contents Auxiliary Control Register.
403 * Parameters:
404 * set_bits - bits to set in ACR
405 * clr_bits - bits to clear in ACR
406 */
407static void omap3_update_aux_cr_secure_rx51(u32 set_bits, u32 clear_bits)
408{
Pali Rohár248ef0a2012-10-29 07:54:01 +0000409 u32 acr;
410
411 /* Read ACR */
412 asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r" (acr));
413 acr &= ~clear_bits;
414 acr |= set_bits;
Nishanth Menon53fee1e2015-03-09 17:12:09 -0500415 omap3_set_aux_cr_secure(acr);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000416}
417
418/*
419 * Routine: misc_init_r
420 * Description: Configure board specific parts.
421 */
422int misc_init_r(void)
423{
Pali Rohárd73afb22020-10-26 23:45:11 +0100424 struct udevice *dev;
Pali Rohár248ef0a2012-10-29 07:54:01 +0000425 char buf[12];
426 u8 state;
427
Pali Rohár977229b2020-10-31 17:32:47 +0100428 /* disable lp5523 led */
Pali Rohárd73afb22020-10-26 23:45:11 +0100429 if (i2c_get_chip_for_busnum(1, 0x32, 1, &dev) == 0)
Pali Rohár977229b2020-10-31 17:32:47 +0100430 dm_i2c_reg_write(dev, 0x00, 0x00);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000431
432 /* initialize twl4030 power managment */
433 twl4030_power_init();
Pali Rohárcc58d292021-01-16 01:04:54 +0100434 twl4030_power_mmc_init(0);
435 twl4030_power_mmc_init(1);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000436
437 /* set VSIM to 1.8V */
438 twl4030_pmrecv_vsel_cfg(TWL4030_PM_RECEIVER_VSIM_DEDICATED,
439 TWL4030_PM_RECEIVER_VSIM_VSEL_18,
440 TWL4030_PM_RECEIVER_VSIM_DEV_GRP,
441 TWL4030_PM_RECEIVER_DEV_GRP_P1);
442
443 /* store I2C access state */
Nishanth Menon5d9d6f72013-03-26 05:20:50 +0000444 twl4030_i2c_read_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
445 &state);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000446
447 /* enable I2C access to powerbus (needed for twl4030 regulator) */
Nishanth Menond26a1062013-03-26 05:20:49 +0000448 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
449 0x02);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000450
451 /* set VAUX3, VSIM and VMMC1 state to active - enable eMMC memory */
452 twl4030_regulator_set_mode(RES_VAUX3, RES_STATE_ACTIVE);
453 twl4030_regulator_set_mode(RES_VSIM, RES_STATE_ACTIVE);
454 twl4030_regulator_set_mode(RES_VMMC1, RES_STATE_ACTIVE);
455
456 /* restore I2C access state */
Nishanth Menond26a1062013-03-26 05:20:49 +0000457 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
458 state);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000459
460 /* set env variable attkernaddr for relocated kernel */
461 sprintf(buf, "%#x", KERNEL_ADDRESS);
Simon Glass6a38e412017-08-03 12:22:09 -0600462 env_set("attkernaddr", buf);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000463
464 /* initialize omap tags */
465 init_omap_tags();
466
467 /* reuse atags from previous bootloader */
468 reuse_atags();
469
Paul Kocialkowski6bc318e2015-08-27 19:37:13 +0200470 omap_die_id_display();
Pali Rohár248ef0a2012-10-29 07:54:01 +0000471 print_cpuinfo();
472
473 /*
474 * Cortex-A8(r1p0..r1p2) errata 430973 workaround
475 * Set IBE bit in Auxiliary Control Register
Pali Rohár415b8042015-01-08 10:11:40 +0100476 *
477 * Call this routine only on real secure device
478 * Qemu does not implement secure PPA and crash
Pali Rohár248ef0a2012-10-29 07:54:01 +0000479 */
Pali Rohár415b8042015-01-08 10:11:40 +0100480 if (get_device_type() == HS_DEVICE)
481 omap3_update_aux_cr_secure_rx51(1 << 6, 0);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000482
483 return 0;
484}
485
Pali Rohár248ef0a2012-10-29 07:54:01 +0000486static unsigned long int twl_wd_time; /* last time of watchdog reset */
487static unsigned long int twl_i2c_lock;
488
489/*
490 * Routine: hw_watchdog_reset
491 * Description: Reset timeout of twl4030 watchdog.
492 */
493void hw_watchdog_reset(void)
494{
495 u8 timeout = 0;
496
497 /* do not reset watchdog too often - max every 4s */
498 if (get_timer(twl_wd_time) < 4 * CONFIG_SYS_HZ)
499 return;
500
501 /* localy lock twl4030 i2c bus */
502 if (test_and_set_bit(0, &twl_i2c_lock))
503 return;
504
505 /* read actual watchdog timeout */
Nishanth Menon5d9d6f72013-03-26 05:20:50 +0000506 twl4030_i2c_read_u8(TWL4030_CHIP_PM_RECEIVER,
507 TWL4030_PM_RECEIVER_WATCHDOG_CFG, &timeout);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000508
509 /* timeout 0 means watchdog is disabled */
510 /* reset watchdog timeout to 31s (maximum) */
511 if (timeout != 0)
Nishanth Menond26a1062013-03-26 05:20:49 +0000512 twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER,
513 TWL4030_PM_RECEIVER_WATCHDOG_CFG, 31);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000514
515 /* store last watchdog reset time */
516 twl_wd_time = get_timer(0);
517
518 /* localy unlock twl4030 i2c bus */
519 test_and_clear_bit(0, &twl_i2c_lock);
520}
521
522/*
523 * TWL4030 keypad handler for cfb_console
524 */
525
526static const char keymap[] = {
527 /* normal */
528 'q', 'o', 'p', ',', '\b', 0, 'a', 's',
529 'w', 'd', 'f', 'g', 'h', 'j', 'k', 'l',
530 'e', '.', 0, '\r', 0, 'z', 'x', 'c',
531 'r', 'v', 'b', 'n', 'm', ' ', ' ', 0,
532 't', 0, 0, 0, 0, 0, 0, 0,
533 'y', 0, 0, 0, 0, 0, 0, 0,
534 'u', 0, 0, 0, 0, 0, 0, 0,
535 'i', 5, 6, 0, 0, 0, 0, 0,
536 /* fn */
537 '1', '9', '0', '=', '\b', 0, '*', '+',
538 '2', '#', '-', '_', '(', ')', '&', '!',
539 '3', '?', '^', '\r', 0, 156, '$', 238,
540 '4', '/', '\\', '"', '\'', '@', 0, '<',
541 '5', '|', '>', 0, 0, 0, 0, 0,
542 '6', 0, 0, 0, 0, 0, 0, 0,
543 '7', 0, 0, 0, 0, 0, 0, 0,
544 '8', 16, 17, 0, 0, 0, 0, 0,
545};
546
547static u8 keys[8];
548static u8 old_keys[8] = {0, 0, 0, 0, 0, 0, 0, 0};
549#define KEYBUF_SIZE 32
550static u8 keybuf[KEYBUF_SIZE];
551static u8 keybuf_head;
552static u8 keybuf_tail;
553
554/*
555 * Routine: rx51_kp_init
556 * Description: Initialize HW keyboard.
557 */
558int rx51_kp_init(void)
559{
560 int ret = 0;
561 u8 ctrl;
Nishanth Menon5d9d6f72013-03-26 05:20:50 +0000562 ret = twl4030_i2c_read_u8(TWL4030_CHIP_KEYPAD,
563 TWL4030_KEYPAD_KEYP_CTRL_REG, &ctrl);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000564
565 if (ret)
566 return ret;
567
568 /* turn on keyboard and use hardware scanning */
569 ctrl |= TWL4030_KEYPAD_CTRL_KBD_ON;
570 ctrl |= TWL4030_KEYPAD_CTRL_SOFT_NRST;
571 ctrl |= TWL4030_KEYPAD_CTRL_SOFTMODEN;
Nishanth Menond26a1062013-03-26 05:20:49 +0000572 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
573 TWL4030_KEYPAD_KEYP_CTRL_REG, ctrl);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000574 /* enable key event status */
Nishanth Menond26a1062013-03-26 05:20:49 +0000575 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
576 TWL4030_KEYPAD_KEYP_IMR1, 0xfe);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000577 /* enable interrupt generation on rising and falling */
578 /* this is a workaround for qemu twl4030 emulation */
Nishanth Menond26a1062013-03-26 05:20:49 +0000579 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
580 TWL4030_KEYPAD_KEYP_EDR, 0x57);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000581 /* enable ISR clear on read */
Nishanth Menond26a1062013-03-26 05:20:49 +0000582 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
583 TWL4030_KEYPAD_KEYP_SIH_CTRL, 0x05);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000584 return 0;
585}
586
587static void rx51_kp_fill(u8 k, u8 mods)
588{
589 /* check if some cursor key without meta fn key was pressed */
590 if (!(mods & 2) && (k == 18 || k == 31 || k == 33 || k == 34)) {
591 keybuf[keybuf_tail++] = '\e';
592 keybuf_tail %= KEYBUF_SIZE;
593 keybuf[keybuf_tail++] = '[';
594 keybuf_tail %= KEYBUF_SIZE;
595 if (k == 18) /* up */
596 keybuf[keybuf_tail++] = 'A';
597 else if (k == 31) /* left */
598 keybuf[keybuf_tail++] = 'D';
599 else if (k == 33) /* down */
600 keybuf[keybuf_tail++] = 'B';
601 else if (k == 34) /* right */
602 keybuf[keybuf_tail++] = 'C';
603 keybuf_tail %= KEYBUF_SIZE;
604 return;
605 }
606
607 if (mods & 2) { /* fn meta key was pressed */
608 k = keymap[k+64];
609 } else {
610 k = keymap[k];
611 if (mods & 1) { /* ctrl key was pressed */
612 if (k >= 'a' && k <= 'z')
613 k -= 'a' - 1;
614 }
615 if (mods & 4) { /* shift key was pressed */
616 if (k >= 'a' && k <= 'z')
617 k += 'A' - 'a';
618 else if (k == '.')
619 k = ':';
620 else if (k == ',')
621 k = ';';
622 }
623 }
624 keybuf[keybuf_tail++] = k;
625 keybuf_tail %= KEYBUF_SIZE;
626}
627
628/*
629 * Routine: rx51_kp_tstc
630 * Description: Test if key was pressed (from buffer).
631 */
Simon Glass0d1e1f72014-07-23 06:54:59 -0600632int rx51_kp_tstc(struct stdio_dev *sdev)
Pali Rohár248ef0a2012-10-29 07:54:01 +0000633{
634 u8 c, r, dk, i;
635 u8 intr;
636 u8 mods;
637
638 /* localy lock twl4030 i2c bus */
639 if (test_and_set_bit(0, &twl_i2c_lock))
640 return 0;
641
642 /* twl4030 remembers up to 2 events */
643 for (i = 0; i < 2; i++) {
644
645 /* check interrupt register for events */
Nishanth Menon5d9d6f72013-03-26 05:20:50 +0000646 twl4030_i2c_read_u8(TWL4030_CHIP_KEYPAD,
647 TWL4030_KEYPAD_KEYP_ISR1 + (2 * i), &intr);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000648
649 /* no event */
650 if (!(intr&1))
651 continue;
652
653 /* read the key state */
Pali Rohárd73afb22020-10-26 23:45:11 +0100654 twl4030_i2c_read(TWL4030_CHIP_KEYPAD,
655 TWL4030_KEYPAD_FULL_CODE_7_0, keys, 8);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000656
657 /* cut out modifier keys from the keystate */
658 mods = keys[4] >> 4;
659 keys[4] &= 0x0f;
660
661 for (c = 0; c < 8; c++) {
662
663 /* get newly pressed keys only */
664 dk = ((keys[c] ^ old_keys[c])&keys[c]);
665 old_keys[c] = keys[c];
666
667 /* fill the keybuf */
668 for (r = 0; r < 8; r++) {
669 if (dk&1)
670 rx51_kp_fill((c*8)+r, mods);
671 dk = dk >> 1;
672 }
673
674 }
675
676 }
677
678 /* localy unlock twl4030 i2c bus */
679 test_and_clear_bit(0, &twl_i2c_lock);
680
681 return (KEYBUF_SIZE + keybuf_tail - keybuf_head)%KEYBUF_SIZE;
682}
683
684/*
685 * Routine: rx51_kp_getc
686 * Description: Get last pressed key (from buffer).
687 */
Simon Glass0d1e1f72014-07-23 06:54:59 -0600688int rx51_kp_getc(struct stdio_dev *sdev)
Pali Rohár248ef0a2012-10-29 07:54:01 +0000689{
690 keybuf_head %= KEYBUF_SIZE;
Simon Glass0d1e1f72014-07-23 06:54:59 -0600691 while (!rx51_kp_tstc(sdev))
Pali Rohár248ef0a2012-10-29 07:54:01 +0000692 WATCHDOG_RESET();
693 return keybuf[keybuf_head++];
694}
695
Pali Rohárcc58d292021-01-16 01:04:54 +0100696static const struct mmc_config rx51_mmc_cfg = {
697 .host_caps = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS,
698 .f_min = 400000,
699 .f_max = 52000000,
700 .b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT,
701 .voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195,
702};
Paul Kocialkowski69559892014-11-08 20:55:47 +0100703
Pali Rohárcc58d292021-01-16 01:04:54 +0100704static const struct omap_hsmmc_plat rx51_mmc[] = {
705 { rx51_mmc_cfg, (struct hsmmc *)OMAP_HSMMC1_BASE },
706 { rx51_mmc_cfg, (struct hsmmc *)OMAP_HSMMC2_BASE },
707};
708
709U_BOOT_DRVINFOS(rx51_mmc) = {
710 { "omap_hsmmc", &rx51_mmc[0] },
711 { "omap_hsmmc", &rx51_mmc[1] },
712};
Pali Rohárd73afb22020-10-26 23:45:11 +0100713
Simon Glassb75b15b2020-12-03 16:55:23 -0700714static const struct omap_i2c_plat rx51_i2c[] = {
Pali Rohárde39c112020-11-21 23:30:11 +0100715 { I2C_BASE1, 100000, OMAP_I2C_REV_V1 },
Pali Rohárd73afb22020-10-26 23:45:11 +0100716 { I2C_BASE2, 100000, OMAP_I2C_REV_V1 },
Pali Rohárde39c112020-11-21 23:30:11 +0100717 { I2C_BASE3, 100000, OMAP_I2C_REV_V1 },
Pali Rohárd73afb22020-10-26 23:45:11 +0100718};
719
Simon Glass1d8364a2020-12-28 20:34:54 -0700720U_BOOT_DRVINFOS(rx51_i2c) = {
Pali Rohárd73afb22020-10-26 23:45:11 +0100721 { "i2c_omap", &rx51_i2c[0] },
722 { "i2c_omap", &rx51_i2c[1] },
723 { "i2c_omap", &rx51_i2c[2] },
724};