blob: 99ca36fbbea13292983d97d97cda17cfb1f94da8 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Pali Roháred407be2012-10-29 07:54:01 +00002/*
3 * (C) Copyright 2012
4 * Ивайло Димитров <freemangordon@abv.bg>
5 *
6 * (C) Copyright 2011-2012
Pali Rohár53086652020-04-01 00:35:08 +02007 * Pali Rohár <pali@kernel.org>
Pali Roháred407be2012-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áred407be2012-10-29 07:54:01 +000022 */
23
24#include <common.h>
Pali Rohár8d8c1812020-10-26 23:45:11 +010025#include <dm.h>
Simon Glass9fb625c2019-08-01 09:46:51 -060026#include <env.h>
Simon Glass691d7192020-05-10 11:40:02 -060027#include <init.h>
Pali Roháred407be2012-10-29 07:54:01 +000028#include <watchdog.h>
Pali Roháre61a4ff2021-03-09 21:19:15 +010029#include <wdt.h>
Pali Roháred407be2012-10-29 07:54:01 +000030#include <malloc.h>
31#include <twl4030.h>
32#include <i2c.h>
33#include <video_fb.h>
Simon Glass401d1c42020-10-30 21:38:53 -060034#include <asm/global_data.h>
Pali Roháred407be2012-10-29 07:54:01 +000035#include <asm/io.h>
36#include <asm/setup.h>
37#include <asm/bitops.h>
38#include <asm/mach-types.h>
Pali Rohár8d8c1812020-10-26 23:45:11 +010039#include <asm/omap_i2c.h>
Pali Roháred407be2012-10-29 07:54:01 +000040#include <asm/arch/mux.h>
41#include <asm/arch/sys_proto.h>
42#include <asm/arch/mmc_host_def.h>
43
Pali Roháred407be2012-10-29 07:54:01 +000044#include "tag_omap.h"
45
Pali Rohár69b78cb2021-02-07 14:50:15 +010046/* Needed for ROM SMC call */
47struct emu_hal_params_rx51 {
48 u32 num_params;
49 u32 param1;
50 u32 param2;
51 u32 param3;
52 u32 param4;
53};
54
55#define ONENAND_GPMC_CONFIG1_RX51 0xfb001202
56#define ONENAND_GPMC_CONFIG2_RX51 0x00111100
57#define ONENAND_GPMC_CONFIG3_RX51 0x00020200
58#define ONENAND_GPMC_CONFIG4_RX51 0x11001102
59#define ONENAND_GPMC_CONFIG5_RX51 0x03101616
60#define ONENAND_GPMC_CONFIG6_RX51 0x90060000
61
Pali Roháred407be2012-10-29 07:54:01 +000062DECLARE_GLOBAL_DATA_PTR;
63
64GraphicDevice gdev;
65
66const omap3_sysinfo sysinfo = {
67 DDR_STACKED,
68 "Nokia RX-51",
69 "OneNAND"
70};
71
72/* This structure contains default omap tags needed for booting Maemo 5 */
73static struct tag_omap omap[] = {
74 OMAP_TAG_UART_CONFIG(0x04),
75 OMAP_TAG_SERIAL_CONSOLE_CONFIG(0x03, 0x01C200),
76 OMAP_TAG_LCD_CONFIG("acx565akm", "internal", 90, 0x18),
77 OMAP_TAG_GPIO_SWITCH_CONFIG("cam_focus", 0x44, 0x1, 0x2, 0x0),
78 OMAP_TAG_GPIO_SWITCH_CONFIG("cam_launch", 0x45, 0x1, 0x2, 0x0),
79 OMAP_TAG_GPIO_SWITCH_CONFIG("cam_shutter", 0x6e, 0x1, 0x0, 0x0),
80 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_apeslpx", 0x46, 0x2, 0x2, 0x0),
81 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_bsi", 0x9d, 0x2, 0x2, 0x0),
82 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_en", 0x4a, 0x2, 0x2, 0x0),
83 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_rst", 0x4b, 0x6, 0x2, 0x0),
84 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_rst_rq", 0x49, 0x6, 0x2, 0x0),
85 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_wddis", 0x0d, 0x2, 0x2, 0x0),
86 OMAP_TAG_GPIO_SWITCH_CONFIG("headphone", 0xb1, 0x1, 0x1, 0x0),
87 OMAP_TAG_GPIO_SWITCH_CONFIG("kb_lock", 0x71, 0x1, 0x0, 0x0),
88 OMAP_TAG_GPIO_SWITCH_CONFIG("proximity", 0x59, 0x0, 0x0, 0x0),
89 OMAP_TAG_GPIO_SWITCH_CONFIG("sleep_ind", 0xa2, 0x2, 0x2, 0x0),
90 OMAP_TAG_GPIO_SWITCH_CONFIG("slide", GPIO_SLIDE, 0x0, 0x0, 0x0),
91 OMAP_TAG_WLAN_CX3110X_CONFIG(0x25, 0xff, 87, 42, -1),
Pali Rohárf5cfdbf2020-04-01 00:35:13 +020092 OMAP_TAG_PARTITION_CONFIG("bootloader", 128 * 1024, 0x00000000, 0x00000003),
93 OMAP_TAG_PARTITION_CONFIG("config", 384 * 1024, 0x00020000, 0x00000000),
94 OMAP_TAG_PARTITION_CONFIG("log", 256 * 1024, 0x00080000, 0x00000000),
95 OMAP_TAG_PARTITION_CONFIG("kernel", 2 * 1024*1024, 0x000c0000, 0x00000000),
96 OMAP_TAG_PARTITION_CONFIG("initfs", 2 * 1024*1024, 0x002c0000, 0x00000000),
97 OMAP_TAG_PARTITION_CONFIG("rootfs", 257280 * 1024, 0x004c0000, 0x00000000),
Pali Roháred407be2012-10-29 07:54:01 +000098 OMAP_TAG_BOOT_REASON_CONFIG("pwr_key"),
99 OMAP_TAG_VERSION_STR_CONFIG("product", "RX-51"),
100 OMAP_TAG_VERSION_STR_CONFIG("hw-build", "2101"),
101 OMAP_TAG_VERSION_STR_CONFIG("nolo", "1.4.14"),
102 OMAP_TAG_VERSION_STR_CONFIG("boot-mode", "normal"),
103 { }
104};
105
106static char *boot_reason_ptr;
107static char *hw_build_ptr;
108static char *nolo_version_ptr;
109static char *boot_mode_ptr;
Pali Rohárb5f7cf52020-04-01 00:35:14 +0200110static int serial_was_console_enabled;
Pali Roháred407be2012-10-29 07:54:01 +0000111
112/*
113 * Routine: init_omap_tags
114 * Description: Initialize pointers to values in tag_omap
115 */
116static void init_omap_tags(void)
117{
118 char *component;
119 char *version;
120 int i = 0;
121 while (omap[i].hdr.tag) {
122 switch (omap[i].hdr.tag) {
123 case OMAP_TAG_BOOT_REASON:
124 boot_reason_ptr = omap[i].u.boot_reason.reason_str;
125 break;
126 case OMAP_TAG_VERSION_STR:
127 component = omap[i].u.version.component;
128 version = omap[i].u.version.version;
129 if (strcmp(component, "hw-build") == 0)
130 hw_build_ptr = version;
131 else if (strcmp(component, "nolo") == 0)
132 nolo_version_ptr = version;
133 else if (strcmp(component, "boot-mode") == 0)
134 boot_mode_ptr = version;
135 break;
136 default:
137 break;
138 }
139 i++;
140 }
141}
142
143static void reuse_omap_atags(struct tag_omap *t)
144{
145 char *component;
146 char *version;
147 while (t->hdr.tag) {
148 switch (t->hdr.tag) {
149 case OMAP_TAG_BOOT_REASON:
150 memset(boot_reason_ptr, 0, 12);
151 strcpy(boot_reason_ptr, t->u.boot_reason.reason_str);
152 break;
153 case OMAP_TAG_VERSION_STR:
154 component = t->u.version.component;
155 version = t->u.version.version;
156 if (strcmp(component, "hw-build") == 0) {
157 memset(hw_build_ptr, 0, 12);
158 strcpy(hw_build_ptr, version);
159 } else if (strcmp(component, "nolo") == 0) {
160 memset(nolo_version_ptr, 0, 12);
161 strcpy(nolo_version_ptr, version);
162 } else if (strcmp(component, "boot-mode") == 0) {
163 memset(boot_mode_ptr, 0, 12);
164 strcpy(boot_mode_ptr, version);
165 }
166 break;
Pali Rohárb5f7cf52020-04-01 00:35:14 +0200167 case OMAP_TAG_UART:
Pali Rohár94e837b2020-06-01 00:29:10 +0200168 if (t->u.uart.enabled_uarts)
Pali Rohárb5f7cf52020-04-01 00:35:14 +0200169 serial_was_console_enabled = 1;
170 break;
171 case OMAP_TAG_SERIAL_CONSOLE:
172 serial_was_console_enabled = 1;
173 break;
Pali Roháred407be2012-10-29 07:54:01 +0000174 default:
175 break;
176 }
177 t = tag_omap_next(t);
178 }
179}
180
181/*
182 * Routine: reuse_atags
183 * Description: Reuse atags from previous bootloader.
184 * Reuse only only HW build, boot reason, boot mode and nolo
185 */
186static void reuse_atags(void)
187{
188 struct tag *t = (struct tag *)gd->bd->bi_boot_params;
189
190 /* First tag must be ATAG_CORE */
191 if (t->hdr.tag != ATAG_CORE)
192 return;
193
194 if (!boot_reason_ptr || !hw_build_ptr)
195 return;
196
197 /* Last tag must be ATAG_NONE */
198 while (t->hdr.tag != ATAG_NONE) {
199 switch (t->hdr.tag) {
200 case ATAG_REVISION:
201 memset(hw_build_ptr, 0, 12);
202 sprintf(hw_build_ptr, "%x", t->u.revision.rev);
203 break;
204 case ATAG_BOARD:
205 reuse_omap_atags((struct tag_omap *)&t->u);
206 break;
207 default:
208 break;
209 }
210 t = tag_next(t);
211 }
212}
213
214/*
215 * Routine: board_init
216 * Description: Early hardware init.
217 */
218int board_init(void)
219{
Ivaylo Dimitrov71c27db2020-10-31 17:32:49 +0100220#if defined(CONFIG_CMD_ONENAND)
221 const u32 gpmc_regs_onenandrx51[GPMC_MAX_REG] = {
222 ONENAND_GPMC_CONFIG1_RX51,
223 ONENAND_GPMC_CONFIG2_RX51,
224 ONENAND_GPMC_CONFIG3_RX51,
225 ONENAND_GPMC_CONFIG4_RX51,
226 ONENAND_GPMC_CONFIG5_RX51,
227 ONENAND_GPMC_CONFIG6_RX51,
228 0
229 };
230#endif
Pali Roháred407be2012-10-29 07:54:01 +0000231 /* in SRAM or SDRAM, finish GPMC */
232 gpmc_init();
Ivaylo Dimitrov71c27db2020-10-31 17:32:49 +0100233#if defined(CONFIG_CMD_ONENAND)
234 enable_gpmc_cs_config(gpmc_regs_onenandrx51, &gpmc_cfg->cs[0],
235 CONFIG_SYS_ONENAND_BASE, GPMC_SIZE_256M);
236#endif
Pali Rohár94f69f42020-10-31 17:32:46 +0100237 /* Enable the clks & power */
238 per_clocks_enable();
Pali Roháred407be2012-10-29 07:54:01 +0000239 /* boot param addr */
240 gd->bd->bi_boot_params = OMAP34XX_SDRC_CS0 + 0x100;
241 return 0;
242}
243
Tom Rini97744622021-08-30 09:16:30 -0400244#ifdef CONFIG_REVISION_TAG
Pali Roháred407be2012-10-29 07:54:01 +0000245/*
246 * Routine: get_board_revision
247 * Description: Return board revision.
248 */
249u32 get_board_rev(void)
250{
251 return simple_strtol(hw_build_ptr, NULL, 16);
252}
Tom Rini97744622021-08-30 09:16:30 -0400253#endif
Pali Roháred407be2012-10-29 07:54:01 +0000254
255/*
256 * Routine: setup_board_tags
257 * Description: Append board specific boot tags.
258 */
259void setup_board_tags(struct tag **in_params)
260{
261 int setup_console_atag;
262 char *setup_boot_reason_atag;
263 char *setup_boot_mode_atag;
264 char *str;
265 int i;
266 int size;
267 int total_size;
268 struct tag *params;
269 struct tag_omap *t;
270
271 params = (struct tag *)gd->bd->bi_boot_params;
272
273 params->u.core.flags = 0x0;
274 params->u.core.pagesize = 0x1000;
275 params->u.core.rootdev = 0x0;
276
277 /* append omap atag only if env setup_omap_atag is set to 1 */
Simon Glass00caae62017-08-03 12:22:12 -0600278 str = env_get("setup_omap_atag");
Pali Roháred407be2012-10-29 07:54:01 +0000279 if (!str || str[0] != '1')
280 return;
281
Simon Glass00caae62017-08-03 12:22:12 -0600282 str = env_get("setup_console_atag");
Pali Rohárb5f7cf52020-04-01 00:35:14 +0200283 if (str && str[0]) {
284 if (str[0] == '1')
285 setup_console_atag = 1;
286 else
287 setup_console_atag = 0;
288 } else {
289 if (serial_was_console_enabled)
290 setup_console_atag = 1;
291 else
292 setup_console_atag = 0;
293 }
Pali Roháred407be2012-10-29 07:54:01 +0000294
Simon Glass00caae62017-08-03 12:22:12 -0600295 setup_boot_reason_atag = env_get("setup_boot_reason_atag");
296 setup_boot_mode_atag = env_get("setup_boot_mode_atag");
Pali Roháred407be2012-10-29 07:54:01 +0000297
298 params = *in_params;
299 t = (struct tag_omap *)&params->u;
300 total_size = sizeof(struct tag_header);
301
302 for (i = 0; omap[i].hdr.tag; i++) {
303
304 /* skip serial console tag */
305 if (!setup_console_atag &&
306 omap[i].hdr.tag == OMAP_TAG_SERIAL_CONSOLE)
307 continue;
308
309 size = omap[i].hdr.size + sizeof(struct tag_omap_header);
310 memcpy(t, &omap[i], size);
311
312 /* set uart tag to 0 - disable serial console */
313 if (!setup_console_atag && omap[i].hdr.tag == OMAP_TAG_UART)
314 t->u.uart.enabled_uarts = 0;
315
316 /* change boot reason */
317 if (setup_boot_reason_atag &&
318 omap[i].hdr.tag == OMAP_TAG_BOOT_REASON) {
319 memset(t->u.boot_reason.reason_str, 0, 12);
320 strcpy(t->u.boot_reason.reason_str,
321 setup_boot_reason_atag);
322 }
323
324 /* change boot mode */
325 if (setup_boot_mode_atag &&
326 omap[i].hdr.tag == OMAP_TAG_VERSION_STR &&
327 strcmp(omap[i].u.version.component, "boot-mode") == 0) {
328 memset(t->u.version.version, 0, 12);
329 strcpy(t->u.version.version, setup_boot_mode_atag);
330 }
331
332 total_size += size;
333 t = tag_omap_next(t);
334
335 }
336
337 params->hdr.tag = ATAG_BOARD;
338 params->hdr.size = total_size >> 2;
339 params = tag_next(params);
340
341 *in_params = params;
342}
343
344/*
345 * Routine: video_hw_init
346 * Description: Set up the GraphicDevice depending on sys_boot.
347 */
348void *video_hw_init(void)
349{
350 /* fill in Graphic Device */
351 gdev.frameAdrs = 0x8f9c0000;
352 gdev.winSizeX = 800;
353 gdev.winSizeY = 480;
354 gdev.gdfBytesPP = 2;
355 gdev.gdfIndex = GDF_16BIT_565RGB;
356 memset((void *)gdev.frameAdrs, 0, 0xbb800);
357 return (void *) &gdev;
358}
359
360/*
361 * Routine: twl4030_regulator_set_mode
362 * Description: Set twl4030 regulator mode over i2c powerbus.
363 */
364static void twl4030_regulator_set_mode(u8 id, u8 mode)
365{
366 u16 msg = MSG_SINGULAR(DEV_GRP_P1, id, mode);
Nishanth Menon0208aaf2013-03-26 05:20:49 +0000367 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
368 TWL4030_PM_MASTER_PB_WORD_MSB, msg >> 8);
369 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
370 TWL4030_PM_MASTER_PB_WORD_LSB, msg & 0xff);
Pali Roháred407be2012-10-29 07:54:01 +0000371}
372
373static void omap3_emu_romcode_call(u32 service_id, u32 *parameters)
374{
375 u32 i, num_params = *parameters;
376 u32 *sram_scratch_space = (u32 *)OMAP3_PUBLIC_SRAM_SCRATCH_AREA;
377
378 /*
379 * copy the parameters to an un-cached area to avoid coherency
380 * issues
381 */
382 for (i = 0; i < num_params; i++) {
383 __raw_writel(*parameters, sram_scratch_space);
384 parameters++;
385 sram_scratch_space++;
386 }
387
388 /* Now make the PPA call */
389 do_omap3_emu_romcode_call(service_id, OMAP3_PUBLIC_SRAM_SCRATCH_AREA);
390}
391
Nishanth Menoncdef0b32015-03-09 17:12:09 -0500392void omap3_set_aux_cr_secure(u32 acr)
393{
394 struct emu_hal_params_rx51 emu_romcode_params = { 0, };
395
396 emu_romcode_params.num_params = 2;
397 emu_romcode_params.param1 = acr;
398
399 omap3_emu_romcode_call(OMAP3_EMU_HAL_API_WRITE_ACR,
400 (u32 *)&emu_romcode_params);
401}
402
Pali Roháred407be2012-10-29 07:54:01 +0000403/*
404 * Routine: omap3_update_aux_cr_secure_rx51
405 * Description: Modify the contents Auxiliary Control Register.
406 * Parameters:
407 * set_bits - bits to set in ACR
408 * clr_bits - bits to clear in ACR
409 */
410static void omap3_update_aux_cr_secure_rx51(u32 set_bits, u32 clear_bits)
411{
Pali Roháred407be2012-10-29 07:54:01 +0000412 u32 acr;
413
414 /* Read ACR */
415 asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r" (acr));
416 acr &= ~clear_bits;
417 acr |= set_bits;
Nishanth Menoncdef0b32015-03-09 17:12:09 -0500418 omap3_set_aux_cr_secure(acr);
Pali Roháred407be2012-10-29 07:54:01 +0000419}
420
421/*
422 * Routine: misc_init_r
423 * Description: Configure board specific parts.
424 */
425int misc_init_r(void)
426{
Pali Rohár8d8c1812020-10-26 23:45:11 +0100427 struct udevice *dev;
Pali Roháred407be2012-10-29 07:54:01 +0000428 char buf[12];
429 u8 state;
430
Pali Rohárb95ffd32020-10-31 17:32:47 +0100431 /* disable lp5523 led */
Pali Rohár8d8c1812020-10-26 23:45:11 +0100432 if (i2c_get_chip_for_busnum(1, 0x32, 1, &dev) == 0)
Pali Rohárb95ffd32020-10-31 17:32:47 +0100433 dm_i2c_reg_write(dev, 0x00, 0x00);
Pali Roháred407be2012-10-29 07:54:01 +0000434
435 /* initialize twl4030 power managment */
436 twl4030_power_init();
Pali Rohár64fd2d22021-01-16 01:04:54 +0100437 twl4030_power_mmc_init(0);
438 twl4030_power_mmc_init(1);
Pali Roháred407be2012-10-29 07:54:01 +0000439
440 /* set VSIM to 1.8V */
441 twl4030_pmrecv_vsel_cfg(TWL4030_PM_RECEIVER_VSIM_DEDICATED,
442 TWL4030_PM_RECEIVER_VSIM_VSEL_18,
443 TWL4030_PM_RECEIVER_VSIM_DEV_GRP,
444 TWL4030_PM_RECEIVER_DEV_GRP_P1);
445
446 /* store I2C access state */
Nishanth Menonb29c2f02013-03-26 05:20:50 +0000447 twl4030_i2c_read_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
448 &state);
Pali Roháred407be2012-10-29 07:54:01 +0000449
450 /* enable I2C access to powerbus (needed for twl4030 regulator) */
Nishanth Menon0208aaf2013-03-26 05:20:49 +0000451 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
452 0x02);
Pali Roháred407be2012-10-29 07:54:01 +0000453
454 /* set VAUX3, VSIM and VMMC1 state to active - enable eMMC memory */
455 twl4030_regulator_set_mode(RES_VAUX3, RES_STATE_ACTIVE);
456 twl4030_regulator_set_mode(RES_VSIM, RES_STATE_ACTIVE);
457 twl4030_regulator_set_mode(RES_VMMC1, RES_STATE_ACTIVE);
458
459 /* restore I2C access state */
Nishanth Menon0208aaf2013-03-26 05:20:49 +0000460 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
461 state);
Pali Roháred407be2012-10-29 07:54:01 +0000462
463 /* set env variable attkernaddr for relocated kernel */
464 sprintf(buf, "%#x", KERNEL_ADDRESS);
Simon Glass382bee52017-08-03 12:22:09 -0600465 env_set("attkernaddr", buf);
Pali Roháred407be2012-10-29 07:54:01 +0000466
467 /* initialize omap tags */
468 init_omap_tags();
469
470 /* reuse atags from previous bootloader */
471 reuse_atags();
472
Paul Kocialkowski679f82c2015-08-27 19:37:13 +0200473 omap_die_id_display();
Pali Roháred407be2012-10-29 07:54:01 +0000474 print_cpuinfo();
475
476 /*
477 * Cortex-A8(r1p0..r1p2) errata 430973 workaround
478 * Set IBE bit in Auxiliary Control Register
Pali Rohár8cda4132015-01-08 10:11:40 +0100479 *
480 * Call this routine only on real secure device
481 * Qemu does not implement secure PPA and crash
Pali Roháred407be2012-10-29 07:54:01 +0000482 */
Pali Rohár8cda4132015-01-08 10:11:40 +0100483 if (get_device_type() == HS_DEVICE)
484 omap3_update_aux_cr_secure_rx51(1 << 6, 0);
Pali Roháred407be2012-10-29 07:54:01 +0000485
486 return 0;
487}
488
Pali Roháred407be2012-10-29 07:54:01 +0000489static unsigned long int twl_wd_time; /* last time of watchdog reset */
490static unsigned long int twl_i2c_lock;
491
492/*
Pali Roháre61a4ff2021-03-09 21:19:15 +0100493 * Routine: rx51_watchdog_reset
Pali Roháred407be2012-10-29 07:54:01 +0000494 * Description: Reset timeout of twl4030 watchdog.
495 */
Pali Roháre61a4ff2021-03-09 21:19:15 +0100496static int rx51_watchdog_reset(struct udevice *dev)
Pali Roháred407be2012-10-29 07:54:01 +0000497{
498 u8 timeout = 0;
499
500 /* do not reset watchdog too often - max every 4s */
501 if (get_timer(twl_wd_time) < 4 * CONFIG_SYS_HZ)
Pali Roháre61a4ff2021-03-09 21:19:15 +0100502 return 0;
Pali Roháred407be2012-10-29 07:54:01 +0000503
504 /* localy lock twl4030 i2c bus */
505 if (test_and_set_bit(0, &twl_i2c_lock))
Pali Roháre61a4ff2021-03-09 21:19:15 +0100506 return 0;
Pali Roháred407be2012-10-29 07:54:01 +0000507
508 /* read actual watchdog timeout */
Nishanth Menonb29c2f02013-03-26 05:20:50 +0000509 twl4030_i2c_read_u8(TWL4030_CHIP_PM_RECEIVER,
510 TWL4030_PM_RECEIVER_WATCHDOG_CFG, &timeout);
Pali Roháred407be2012-10-29 07:54:01 +0000511
512 /* timeout 0 means watchdog is disabled */
513 /* reset watchdog timeout to 31s (maximum) */
514 if (timeout != 0)
Nishanth Menon0208aaf2013-03-26 05:20:49 +0000515 twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER,
516 TWL4030_PM_RECEIVER_WATCHDOG_CFG, 31);
Pali Roháred407be2012-10-29 07:54:01 +0000517
518 /* store last watchdog reset time */
519 twl_wd_time = get_timer(0);
520
521 /* localy unlock twl4030 i2c bus */
522 test_and_clear_bit(0, &twl_i2c_lock);
Pali Roháre61a4ff2021-03-09 21:19:15 +0100523
524 return 0;
Pali Roháred407be2012-10-29 07:54:01 +0000525}
526
Pali Roháre61a4ff2021-03-09 21:19:15 +0100527static int rx51_watchdog_start(struct udevice *dev, u64 timeout_ms, ulong flags)
528{
529 return 0;
530}
531
532static int rx51_watchdog_probe(struct udevice *dev)
533{
534 return 0;
535}
536
537static const struct wdt_ops rx51_watchdog_ops = {
538 .start = rx51_watchdog_start,
539 .reset = rx51_watchdog_reset,
540};
541
542U_BOOT_DRIVER(rx51_watchdog) = {
543 .name = "rx51_watchdog",
544 .id = UCLASS_WDT,
545 .ops = &rx51_watchdog_ops,
546 .probe = rx51_watchdog_probe,
547};
548
Pali Roháred407be2012-10-29 07:54:01 +0000549/*
550 * TWL4030 keypad handler for cfb_console
551 */
552
553static const char keymap[] = {
554 /* normal */
555 'q', 'o', 'p', ',', '\b', 0, 'a', 's',
556 'w', 'd', 'f', 'g', 'h', 'j', 'k', 'l',
557 'e', '.', 0, '\r', 0, 'z', 'x', 'c',
558 'r', 'v', 'b', 'n', 'm', ' ', ' ', 0,
559 't', 0, 0, 0, 0, 0, 0, 0,
560 'y', 0, 0, 0, 0, 0, 0, 0,
561 'u', 0, 0, 0, 0, 0, 0, 0,
562 'i', 5, 6, 0, 0, 0, 0, 0,
563 /* fn */
564 '1', '9', '0', '=', '\b', 0, '*', '+',
565 '2', '#', '-', '_', '(', ')', '&', '!',
566 '3', '?', '^', '\r', 0, 156, '$', 238,
567 '4', '/', '\\', '"', '\'', '@', 0, '<',
568 '5', '|', '>', 0, 0, 0, 0, 0,
569 '6', 0, 0, 0, 0, 0, 0, 0,
570 '7', 0, 0, 0, 0, 0, 0, 0,
571 '8', 16, 17, 0, 0, 0, 0, 0,
572};
573
574static u8 keys[8];
575static u8 old_keys[8] = {0, 0, 0, 0, 0, 0, 0, 0};
576#define KEYBUF_SIZE 32
577static u8 keybuf[KEYBUF_SIZE];
578static u8 keybuf_head;
579static u8 keybuf_tail;
580
581/*
582 * Routine: rx51_kp_init
583 * Description: Initialize HW keyboard.
584 */
585int rx51_kp_init(void)
586{
587 int ret = 0;
588 u8 ctrl;
Nishanth Menonb29c2f02013-03-26 05:20:50 +0000589 ret = twl4030_i2c_read_u8(TWL4030_CHIP_KEYPAD,
590 TWL4030_KEYPAD_KEYP_CTRL_REG, &ctrl);
Pali Roháred407be2012-10-29 07:54:01 +0000591
592 if (ret)
593 return ret;
594
595 /* turn on keyboard and use hardware scanning */
596 ctrl |= TWL4030_KEYPAD_CTRL_KBD_ON;
597 ctrl |= TWL4030_KEYPAD_CTRL_SOFT_NRST;
598 ctrl |= TWL4030_KEYPAD_CTRL_SOFTMODEN;
Nishanth Menon0208aaf2013-03-26 05:20:49 +0000599 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
600 TWL4030_KEYPAD_KEYP_CTRL_REG, ctrl);
Pali Roháred407be2012-10-29 07:54:01 +0000601 /* enable key event status */
Nishanth Menon0208aaf2013-03-26 05:20:49 +0000602 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
603 TWL4030_KEYPAD_KEYP_IMR1, 0xfe);
Pali Roháred407be2012-10-29 07:54:01 +0000604 /* enable interrupt generation on rising and falling */
605 /* this is a workaround for qemu twl4030 emulation */
Nishanth Menon0208aaf2013-03-26 05:20:49 +0000606 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
607 TWL4030_KEYPAD_KEYP_EDR, 0x57);
Pali Roháred407be2012-10-29 07:54:01 +0000608 /* enable ISR clear on read */
Nishanth Menon0208aaf2013-03-26 05:20:49 +0000609 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
610 TWL4030_KEYPAD_KEYP_SIH_CTRL, 0x05);
Pali Roháred407be2012-10-29 07:54:01 +0000611 return 0;
612}
613
614static void rx51_kp_fill(u8 k, u8 mods)
615{
616 /* check if some cursor key without meta fn key was pressed */
617 if (!(mods & 2) && (k == 18 || k == 31 || k == 33 || k == 34)) {
618 keybuf[keybuf_tail++] = '\e';
619 keybuf_tail %= KEYBUF_SIZE;
620 keybuf[keybuf_tail++] = '[';
621 keybuf_tail %= KEYBUF_SIZE;
622 if (k == 18) /* up */
623 keybuf[keybuf_tail++] = 'A';
624 else if (k == 31) /* left */
625 keybuf[keybuf_tail++] = 'D';
626 else if (k == 33) /* down */
627 keybuf[keybuf_tail++] = 'B';
628 else if (k == 34) /* right */
629 keybuf[keybuf_tail++] = 'C';
630 keybuf_tail %= KEYBUF_SIZE;
631 return;
632 }
633
634 if (mods & 2) { /* fn meta key was pressed */
635 k = keymap[k+64];
636 } else {
637 k = keymap[k];
638 if (mods & 1) { /* ctrl key was pressed */
639 if (k >= 'a' && k <= 'z')
640 k -= 'a' - 1;
641 }
642 if (mods & 4) { /* shift key was pressed */
643 if (k >= 'a' && k <= 'z')
644 k += 'A' - 'a';
645 else if (k == '.')
646 k = ':';
647 else if (k == ',')
648 k = ';';
649 }
650 }
651 keybuf[keybuf_tail++] = k;
652 keybuf_tail %= KEYBUF_SIZE;
653}
654
655/*
656 * Routine: rx51_kp_tstc
657 * Description: Test if key was pressed (from buffer).
658 */
Simon Glass709ea542014-07-23 06:54:59 -0600659int rx51_kp_tstc(struct stdio_dev *sdev)
Pali Roháred407be2012-10-29 07:54:01 +0000660{
661 u8 c, r, dk, i;
662 u8 intr;
663 u8 mods;
664
665 /* localy lock twl4030 i2c bus */
666 if (test_and_set_bit(0, &twl_i2c_lock))
667 return 0;
668
669 /* twl4030 remembers up to 2 events */
670 for (i = 0; i < 2; i++) {
671
672 /* check interrupt register for events */
Nishanth Menonb29c2f02013-03-26 05:20:50 +0000673 twl4030_i2c_read_u8(TWL4030_CHIP_KEYPAD,
674 TWL4030_KEYPAD_KEYP_ISR1 + (2 * i), &intr);
Pali Roháred407be2012-10-29 07:54:01 +0000675
676 /* no event */
677 if (!(intr&1))
678 continue;
679
680 /* read the key state */
Pali Rohár8d8c1812020-10-26 23:45:11 +0100681 twl4030_i2c_read(TWL4030_CHIP_KEYPAD,
682 TWL4030_KEYPAD_FULL_CODE_7_0, keys, 8);
Pali Roháred407be2012-10-29 07:54:01 +0000683
684 /* cut out modifier keys from the keystate */
685 mods = keys[4] >> 4;
686 keys[4] &= 0x0f;
687
688 for (c = 0; c < 8; c++) {
689
690 /* get newly pressed keys only */
691 dk = ((keys[c] ^ old_keys[c])&keys[c]);
692 old_keys[c] = keys[c];
693
694 /* fill the keybuf */
695 for (r = 0; r < 8; r++) {
696 if (dk&1)
697 rx51_kp_fill((c*8)+r, mods);
698 dk = dk >> 1;
699 }
700
701 }
702
703 }
704
705 /* localy unlock twl4030 i2c bus */
706 test_and_clear_bit(0, &twl_i2c_lock);
707
708 return (KEYBUF_SIZE + keybuf_tail - keybuf_head)%KEYBUF_SIZE;
709}
710
711/*
712 * Routine: rx51_kp_getc
713 * Description: Get last pressed key (from buffer).
714 */
Simon Glass709ea542014-07-23 06:54:59 -0600715int rx51_kp_getc(struct stdio_dev *sdev)
Pali Roháred407be2012-10-29 07:54:01 +0000716{
717 keybuf_head %= KEYBUF_SIZE;
Simon Glass709ea542014-07-23 06:54:59 -0600718 while (!rx51_kp_tstc(sdev))
Pali Roháred407be2012-10-29 07:54:01 +0000719 WATCHDOG_RESET();
720 return keybuf[keybuf_head++];
721}
722
Pali Rohár64fd2d22021-01-16 01:04:54 +0100723static const struct mmc_config rx51_mmc_cfg = {
724 .host_caps = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS,
725 .f_min = 400000,
726 .f_max = 52000000,
727 .b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT,
728 .voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195,
729};
Paul Kocialkowskiaac54502014-11-08 20:55:47 +0100730
Pali Rohár64fd2d22021-01-16 01:04:54 +0100731static const struct omap_hsmmc_plat rx51_mmc[] = {
732 { rx51_mmc_cfg, (struct hsmmc *)OMAP_HSMMC1_BASE },
733 { rx51_mmc_cfg, (struct hsmmc *)OMAP_HSMMC2_BASE },
734};
735
736U_BOOT_DRVINFOS(rx51_mmc) = {
737 { "omap_hsmmc", &rx51_mmc[0] },
738 { "omap_hsmmc", &rx51_mmc[1] },
739};
Pali Rohár8d8c1812020-10-26 23:45:11 +0100740
Simon Glass8a8d24b2020-12-03 16:55:23 -0700741static const struct omap_i2c_plat rx51_i2c[] = {
Pali Rohára8ef64e2020-11-21 23:30:11 +0100742 { I2C_BASE1, 100000, OMAP_I2C_REV_V1 },
Pali Rohár8d8c1812020-10-26 23:45:11 +0100743 { I2C_BASE2, 100000, OMAP_I2C_REV_V1 },
Pali Rohára8ef64e2020-11-21 23:30:11 +0100744 { I2C_BASE3, 100000, OMAP_I2C_REV_V1 },
Pali Rohár8d8c1812020-10-26 23:45:11 +0100745};
746
Simon Glass20e442a2020-12-28 20:34:54 -0700747U_BOOT_DRVINFOS(rx51_i2c) = {
Pali Rohár8d8c1812020-10-26 23:45:11 +0100748 { "i2c_omap", &rx51_i2c[0] },
749 { "i2c_omap", &rx51_i2c[1] },
750 { "i2c_omap", &rx51_i2c[2] },
751};
Pali Roháre61a4ff2021-03-09 21:19:15 +0100752
753U_BOOT_DRVINFOS(rx51_watchdog) = {
754 { "rx51_watchdog" },
755};