blob: a52691509da454b093c20eaba14c4450a67a04d4 [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>
Pali Rohár126038a2021-03-09 21:19:15 +010029#include <wdt.h>
Pali Rohár248ef0a2012-10-29 07:54:01 +000030#include <malloc.h>
31#include <twl4030.h>
32#include <i2c.h>
33#include <video_fb.h>
Pali Rohár54a30142022-02-03 19:38:50 +010034#include <keyboard.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060035#include <asm/global_data.h>
Pali Rohár248ef0a2012-10-29 07:54:01 +000036#include <asm/io.h>
37#include <asm/setup.h>
38#include <asm/bitops.h>
39#include <asm/mach-types.h>
Pali Rohárd73afb22020-10-26 23:45:11 +010040#include <asm/omap_i2c.h>
Pali Rohár248ef0a2012-10-29 07:54:01 +000041#include <asm/arch/mux.h>
42#include <asm/arch/sys_proto.h>
43#include <asm/arch/mmc_host_def.h>
44
Pali Rohár248ef0a2012-10-29 07:54:01 +000045#include "tag_omap.h"
46
Pali Rohár9157a8c2021-02-07 14:50:15 +010047/* Needed for ROM SMC call */
48struct emu_hal_params_rx51 {
49 u32 num_params;
50 u32 param1;
51 u32 param2;
52 u32 param3;
53 u32 param4;
54};
55
56#define ONENAND_GPMC_CONFIG1_RX51 0xfb001202
57#define ONENAND_GPMC_CONFIG2_RX51 0x00111100
58#define ONENAND_GPMC_CONFIG3_RX51 0x00020200
59#define ONENAND_GPMC_CONFIG4_RX51 0x11001102
60#define ONENAND_GPMC_CONFIG5_RX51 0x03101616
61#define ONENAND_GPMC_CONFIG6_RX51 0x90060000
62
Pali Rohár248ef0a2012-10-29 07:54:01 +000063DECLARE_GLOBAL_DATA_PTR;
64
65GraphicDevice gdev;
66
67const omap3_sysinfo sysinfo = {
68 DDR_STACKED,
69 "Nokia RX-51",
70 "OneNAND"
71};
72
73/* This structure contains default omap tags needed for booting Maemo 5 */
74static struct tag_omap omap[] = {
75 OMAP_TAG_UART_CONFIG(0x04),
76 OMAP_TAG_SERIAL_CONSOLE_CONFIG(0x03, 0x01C200),
77 OMAP_TAG_LCD_CONFIG("acx565akm", "internal", 90, 0x18),
78 OMAP_TAG_GPIO_SWITCH_CONFIG("cam_focus", 0x44, 0x1, 0x2, 0x0),
79 OMAP_TAG_GPIO_SWITCH_CONFIG("cam_launch", 0x45, 0x1, 0x2, 0x0),
80 OMAP_TAG_GPIO_SWITCH_CONFIG("cam_shutter", 0x6e, 0x1, 0x0, 0x0),
81 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_apeslpx", 0x46, 0x2, 0x2, 0x0),
82 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_bsi", 0x9d, 0x2, 0x2, 0x0),
83 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_en", 0x4a, 0x2, 0x2, 0x0),
84 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_rst", 0x4b, 0x6, 0x2, 0x0),
85 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_rst_rq", 0x49, 0x6, 0x2, 0x0),
86 OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_wddis", 0x0d, 0x2, 0x2, 0x0),
87 OMAP_TAG_GPIO_SWITCH_CONFIG("headphone", 0xb1, 0x1, 0x1, 0x0),
88 OMAP_TAG_GPIO_SWITCH_CONFIG("kb_lock", 0x71, 0x1, 0x0, 0x0),
89 OMAP_TAG_GPIO_SWITCH_CONFIG("proximity", 0x59, 0x0, 0x0, 0x0),
90 OMAP_TAG_GPIO_SWITCH_CONFIG("sleep_ind", 0xa2, 0x2, 0x2, 0x0),
91 OMAP_TAG_GPIO_SWITCH_CONFIG("slide", GPIO_SLIDE, 0x0, 0x0, 0x0),
92 OMAP_TAG_WLAN_CX3110X_CONFIG(0x25, 0xff, 87, 42, -1),
Pali Rohár7ce37522020-04-01 00:35:13 +020093 OMAP_TAG_PARTITION_CONFIG("bootloader", 128 * 1024, 0x00000000, 0x00000003),
94 OMAP_TAG_PARTITION_CONFIG("config", 384 * 1024, 0x00020000, 0x00000000),
95 OMAP_TAG_PARTITION_CONFIG("log", 256 * 1024, 0x00080000, 0x00000000),
96 OMAP_TAG_PARTITION_CONFIG("kernel", 2 * 1024*1024, 0x000c0000, 0x00000000),
97 OMAP_TAG_PARTITION_CONFIG("initfs", 2 * 1024*1024, 0x002c0000, 0x00000000),
98 OMAP_TAG_PARTITION_CONFIG("rootfs", 257280 * 1024, 0x004c0000, 0x00000000),
Pali Rohár248ef0a2012-10-29 07:54:01 +000099 OMAP_TAG_BOOT_REASON_CONFIG("pwr_key"),
100 OMAP_TAG_VERSION_STR_CONFIG("product", "RX-51"),
101 OMAP_TAG_VERSION_STR_CONFIG("hw-build", "2101"),
102 OMAP_TAG_VERSION_STR_CONFIG("nolo", "1.4.14"),
103 OMAP_TAG_VERSION_STR_CONFIG("boot-mode", "normal"),
104 { }
105};
106
107static char *boot_reason_ptr;
108static char *hw_build_ptr;
109static char *nolo_version_ptr;
110static char *boot_mode_ptr;
Pali Rohár02f45842020-04-01 00:35:14 +0200111static int serial_was_console_enabled;
Pali Rohár248ef0a2012-10-29 07:54:01 +0000112
113/*
114 * Routine: init_omap_tags
115 * Description: Initialize pointers to values in tag_omap
116 */
117static void init_omap_tags(void)
118{
119 char *component;
120 char *version;
121 int i = 0;
122 while (omap[i].hdr.tag) {
123 switch (omap[i].hdr.tag) {
124 case OMAP_TAG_BOOT_REASON:
125 boot_reason_ptr = omap[i].u.boot_reason.reason_str;
126 break;
127 case OMAP_TAG_VERSION_STR:
128 component = omap[i].u.version.component;
129 version = omap[i].u.version.version;
130 if (strcmp(component, "hw-build") == 0)
131 hw_build_ptr = version;
132 else if (strcmp(component, "nolo") == 0)
133 nolo_version_ptr = version;
134 else if (strcmp(component, "boot-mode") == 0)
135 boot_mode_ptr = version;
136 break;
137 default:
138 break;
139 }
140 i++;
141 }
142}
143
144static void reuse_omap_atags(struct tag_omap *t)
145{
146 char *component;
147 char *version;
148 while (t->hdr.tag) {
149 switch (t->hdr.tag) {
150 case OMAP_TAG_BOOT_REASON:
151 memset(boot_reason_ptr, 0, 12);
152 strcpy(boot_reason_ptr, t->u.boot_reason.reason_str);
153 break;
154 case OMAP_TAG_VERSION_STR:
155 component = t->u.version.component;
156 version = t->u.version.version;
157 if (strcmp(component, "hw-build") == 0) {
158 memset(hw_build_ptr, 0, 12);
159 strcpy(hw_build_ptr, version);
160 } else if (strcmp(component, "nolo") == 0) {
161 memset(nolo_version_ptr, 0, 12);
162 strcpy(nolo_version_ptr, version);
163 } else if (strcmp(component, "boot-mode") == 0) {
164 memset(boot_mode_ptr, 0, 12);
165 strcpy(boot_mode_ptr, version);
166 }
167 break;
Pali Rohár02f45842020-04-01 00:35:14 +0200168 case OMAP_TAG_UART:
Pali Roháre01ae762020-06-01 00:29:10 +0200169 if (t->u.uart.enabled_uarts)
Pali Rohár02f45842020-04-01 00:35:14 +0200170 serial_was_console_enabled = 1;
171 break;
172 case OMAP_TAG_SERIAL_CONSOLE:
173 serial_was_console_enabled = 1;
174 break;
Pali Rohár248ef0a2012-10-29 07:54:01 +0000175 default:
176 break;
177 }
178 t = tag_omap_next(t);
179 }
180}
181
182/*
183 * Routine: reuse_atags
184 * Description: Reuse atags from previous bootloader.
185 * Reuse only only HW build, boot reason, boot mode and nolo
186 */
187static void reuse_atags(void)
188{
189 struct tag *t = (struct tag *)gd->bd->bi_boot_params;
190
191 /* First tag must be ATAG_CORE */
192 if (t->hdr.tag != ATAG_CORE)
193 return;
194
195 if (!boot_reason_ptr || !hw_build_ptr)
196 return;
197
198 /* Last tag must be ATAG_NONE */
199 while (t->hdr.tag != ATAG_NONE) {
200 switch (t->hdr.tag) {
201 case ATAG_REVISION:
202 memset(hw_build_ptr, 0, 12);
203 sprintf(hw_build_ptr, "%x", t->u.revision.rev);
204 break;
205 case ATAG_BOARD:
206 reuse_omap_atags((struct tag_omap *)&t->u);
207 break;
208 default:
209 break;
210 }
211 t = tag_next(t);
212 }
213}
214
215/*
216 * Routine: board_init
217 * Description: Early hardware init.
218 */
219int board_init(void)
220{
Ivaylo Dimitrovbe2ff862020-10-31 17:32:49 +0100221#if defined(CONFIG_CMD_ONENAND)
222 const u32 gpmc_regs_onenandrx51[GPMC_MAX_REG] = {
223 ONENAND_GPMC_CONFIG1_RX51,
224 ONENAND_GPMC_CONFIG2_RX51,
225 ONENAND_GPMC_CONFIG3_RX51,
226 ONENAND_GPMC_CONFIG4_RX51,
227 ONENAND_GPMC_CONFIG5_RX51,
228 ONENAND_GPMC_CONFIG6_RX51,
229 0
230 };
231#endif
Pali Rohár248ef0a2012-10-29 07:54:01 +0000232 /* in SRAM or SDRAM, finish GPMC */
233 gpmc_init();
Ivaylo Dimitrovbe2ff862020-10-31 17:32:49 +0100234#if defined(CONFIG_CMD_ONENAND)
235 enable_gpmc_cs_config(gpmc_regs_onenandrx51, &gpmc_cfg->cs[0],
236 CONFIG_SYS_ONENAND_BASE, GPMC_SIZE_256M);
237#endif
Pali Rohár6327bac2020-10-31 17:32:46 +0100238 /* Enable the clks & power */
239 per_clocks_enable();
Pali Rohár248ef0a2012-10-29 07:54:01 +0000240 /* boot param addr */
241 gd->bd->bi_boot_params = OMAP34XX_SDRC_CS0 + 0x100;
242 return 0;
243}
244
Tom Rini4cc38852021-08-30 09:16:30 -0400245#ifdef CONFIG_REVISION_TAG
Pali Rohár248ef0a2012-10-29 07:54:01 +0000246/*
247 * Routine: get_board_revision
248 * Description: Return board revision.
249 */
250u32 get_board_rev(void)
251{
252 return simple_strtol(hw_build_ptr, NULL, 16);
253}
Tom Rini4cc38852021-08-30 09:16:30 -0400254#endif
Pali Rohár248ef0a2012-10-29 07:54:01 +0000255
256/*
257 * Routine: setup_board_tags
258 * Description: Append board specific boot tags.
259 */
260void setup_board_tags(struct tag **in_params)
261{
262 int setup_console_atag;
263 char *setup_boot_reason_atag;
264 char *setup_boot_mode_atag;
265 char *str;
266 int i;
267 int size;
268 int total_size;
269 struct tag *params;
270 struct tag_omap *t;
271
272 params = (struct tag *)gd->bd->bi_boot_params;
273
274 params->u.core.flags = 0x0;
275 params->u.core.pagesize = 0x1000;
276 params->u.core.rootdev = 0x0;
277
278 /* append omap atag only if env setup_omap_atag is set to 1 */
Simon Glass64b723f2017-08-03 12:22:12 -0600279 str = env_get("setup_omap_atag");
Pali Rohár248ef0a2012-10-29 07:54:01 +0000280 if (!str || str[0] != '1')
281 return;
282
Simon Glass64b723f2017-08-03 12:22:12 -0600283 str = env_get("setup_console_atag");
Pali Rohár02f45842020-04-01 00:35:14 +0200284 if (str && str[0]) {
285 if (str[0] == '1')
286 setup_console_atag = 1;
287 else
288 setup_console_atag = 0;
289 } else {
290 if (serial_was_console_enabled)
291 setup_console_atag = 1;
292 else
293 setup_console_atag = 0;
294 }
Pali Rohár248ef0a2012-10-29 07:54:01 +0000295
Simon Glass64b723f2017-08-03 12:22:12 -0600296 setup_boot_reason_atag = env_get("setup_boot_reason_atag");
297 setup_boot_mode_atag = env_get("setup_boot_mode_atag");
Pali Rohár248ef0a2012-10-29 07:54:01 +0000298
299 params = *in_params;
300 t = (struct tag_omap *)&params->u;
301 total_size = sizeof(struct tag_header);
302
303 for (i = 0; omap[i].hdr.tag; i++) {
304
305 /* skip serial console tag */
306 if (!setup_console_atag &&
307 omap[i].hdr.tag == OMAP_TAG_SERIAL_CONSOLE)
308 continue;
309
310 size = omap[i].hdr.size + sizeof(struct tag_omap_header);
311 memcpy(t, &omap[i], size);
312
313 /* set uart tag to 0 - disable serial console */
314 if (!setup_console_atag && omap[i].hdr.tag == OMAP_TAG_UART)
315 t->u.uart.enabled_uarts = 0;
316
317 /* change boot reason */
318 if (setup_boot_reason_atag &&
319 omap[i].hdr.tag == OMAP_TAG_BOOT_REASON) {
320 memset(t->u.boot_reason.reason_str, 0, 12);
321 strcpy(t->u.boot_reason.reason_str,
322 setup_boot_reason_atag);
323 }
324
325 /* change boot mode */
326 if (setup_boot_mode_atag &&
327 omap[i].hdr.tag == OMAP_TAG_VERSION_STR &&
328 strcmp(omap[i].u.version.component, "boot-mode") == 0) {
329 memset(t->u.version.version, 0, 12);
330 strcpy(t->u.version.version, setup_boot_mode_atag);
331 }
332
333 total_size += size;
334 t = tag_omap_next(t);
335
336 }
337
338 params->hdr.tag = ATAG_BOARD;
339 params->hdr.size = total_size >> 2;
340 params = tag_next(params);
341
342 *in_params = params;
343}
344
345/*
346 * Routine: video_hw_init
347 * Description: Set up the GraphicDevice depending on sys_boot.
348 */
349void *video_hw_init(void)
350{
351 /* fill in Graphic Device */
352 gdev.frameAdrs = 0x8f9c0000;
353 gdev.winSizeX = 800;
354 gdev.winSizeY = 480;
355 gdev.gdfBytesPP = 2;
356 gdev.gdfIndex = GDF_16BIT_565RGB;
357 memset((void *)gdev.frameAdrs, 0, 0xbb800);
358 return (void *) &gdev;
359}
360
361/*
362 * Routine: twl4030_regulator_set_mode
363 * Description: Set twl4030 regulator mode over i2c powerbus.
364 */
365static void twl4030_regulator_set_mode(u8 id, u8 mode)
366{
367 u16 msg = MSG_SINGULAR(DEV_GRP_P1, id, mode);
Nishanth Menond26a1062013-03-26 05:20:49 +0000368 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
369 TWL4030_PM_MASTER_PB_WORD_MSB, msg >> 8);
370 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
371 TWL4030_PM_MASTER_PB_WORD_LSB, msg & 0xff);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000372}
373
374static void omap3_emu_romcode_call(u32 service_id, u32 *parameters)
375{
376 u32 i, num_params = *parameters;
377 u32 *sram_scratch_space = (u32 *)OMAP3_PUBLIC_SRAM_SCRATCH_AREA;
378
379 /*
380 * copy the parameters to an un-cached area to avoid coherency
381 * issues
382 */
383 for (i = 0; i < num_params; i++) {
384 __raw_writel(*parameters, sram_scratch_space);
385 parameters++;
386 sram_scratch_space++;
387 }
388
389 /* Now make the PPA call */
390 do_omap3_emu_romcode_call(service_id, OMAP3_PUBLIC_SRAM_SCRATCH_AREA);
391}
392
Nishanth Menon53fee1e2015-03-09 17:12:09 -0500393void omap3_set_aux_cr_secure(u32 acr)
394{
395 struct emu_hal_params_rx51 emu_romcode_params = { 0, };
396
397 emu_romcode_params.num_params = 2;
398 emu_romcode_params.param1 = acr;
399
400 omap3_emu_romcode_call(OMAP3_EMU_HAL_API_WRITE_ACR,
401 (u32 *)&emu_romcode_params);
402}
403
Pali Rohár248ef0a2012-10-29 07:54:01 +0000404/*
405 * Routine: omap3_update_aux_cr_secure_rx51
406 * Description: Modify the contents Auxiliary Control Register.
407 * Parameters:
408 * set_bits - bits to set in ACR
409 * clr_bits - bits to clear in ACR
410 */
411static void omap3_update_aux_cr_secure_rx51(u32 set_bits, u32 clear_bits)
412{
Pali Rohár248ef0a2012-10-29 07:54:01 +0000413 u32 acr;
414
415 /* Read ACR */
416 asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r" (acr));
417 acr &= ~clear_bits;
418 acr |= set_bits;
Nishanth Menon53fee1e2015-03-09 17:12:09 -0500419 omap3_set_aux_cr_secure(acr);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000420}
421
422/*
423 * Routine: misc_init_r
424 * Description: Configure board specific parts.
425 */
426int misc_init_r(void)
427{
Pali Rohárd73afb22020-10-26 23:45:11 +0100428 struct udevice *dev;
Pali Rohár248ef0a2012-10-29 07:54:01 +0000429 char buf[12];
430 u8 state;
431
Pali Rohár977229b2020-10-31 17:32:47 +0100432 /* disable lp5523 led */
Pali Rohárd73afb22020-10-26 23:45:11 +0100433 if (i2c_get_chip_for_busnum(1, 0x32, 1, &dev) == 0)
Pali Rohár977229b2020-10-31 17:32:47 +0100434 dm_i2c_reg_write(dev, 0x00, 0x00);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000435
436 /* initialize twl4030 power managment */
437 twl4030_power_init();
Pali Rohárcc58d292021-01-16 01:04:54 +0100438 twl4030_power_mmc_init(0);
439 twl4030_power_mmc_init(1);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000440
441 /* set VSIM to 1.8V */
442 twl4030_pmrecv_vsel_cfg(TWL4030_PM_RECEIVER_VSIM_DEDICATED,
443 TWL4030_PM_RECEIVER_VSIM_VSEL_18,
444 TWL4030_PM_RECEIVER_VSIM_DEV_GRP,
445 TWL4030_PM_RECEIVER_DEV_GRP_P1);
446
447 /* store I2C access state */
Nishanth Menon5d9d6f72013-03-26 05:20:50 +0000448 twl4030_i2c_read_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
449 &state);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000450
451 /* enable I2C access to powerbus (needed for twl4030 regulator) */
Nishanth Menond26a1062013-03-26 05:20:49 +0000452 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
453 0x02);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000454
455 /* set VAUX3, VSIM and VMMC1 state to active - enable eMMC memory */
456 twl4030_regulator_set_mode(RES_VAUX3, RES_STATE_ACTIVE);
457 twl4030_regulator_set_mode(RES_VSIM, RES_STATE_ACTIVE);
458 twl4030_regulator_set_mode(RES_VMMC1, RES_STATE_ACTIVE);
459
460 /* restore I2C access state */
Nishanth Menond26a1062013-03-26 05:20:49 +0000461 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
462 state);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000463
464 /* set env variable attkernaddr for relocated kernel */
465 sprintf(buf, "%#x", KERNEL_ADDRESS);
Simon Glass6a38e412017-08-03 12:22:09 -0600466 env_set("attkernaddr", buf);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000467
468 /* initialize omap tags */
469 init_omap_tags();
470
471 /* reuse atags from previous bootloader */
472 reuse_atags();
473
Paul Kocialkowski6bc318e2015-08-27 19:37:13 +0200474 omap_die_id_display();
Pali Rohár248ef0a2012-10-29 07:54:01 +0000475 print_cpuinfo();
476
477 /*
478 * Cortex-A8(r1p0..r1p2) errata 430973 workaround
479 * Set IBE bit in Auxiliary Control Register
Pali Rohár415b8042015-01-08 10:11:40 +0100480 *
481 * Call this routine only on real secure device
482 * Qemu does not implement secure PPA and crash
Pali Rohár248ef0a2012-10-29 07:54:01 +0000483 */
Pali Rohár415b8042015-01-08 10:11:40 +0100484 if (get_device_type() == HS_DEVICE)
485 omap3_update_aux_cr_secure_rx51(1 << 6, 0);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000486
487 return 0;
488}
489
Pali Rohár248ef0a2012-10-29 07:54:01 +0000490static unsigned long int twl_wd_time; /* last time of watchdog reset */
491static unsigned long int twl_i2c_lock;
492
493/*
Pali Rohár126038a2021-03-09 21:19:15 +0100494 * Routine: rx51_watchdog_reset
Pali Rohár248ef0a2012-10-29 07:54:01 +0000495 * Description: Reset timeout of twl4030 watchdog.
496 */
Pali Rohár126038a2021-03-09 21:19:15 +0100497static int rx51_watchdog_reset(struct udevice *dev)
Pali Rohár248ef0a2012-10-29 07:54:01 +0000498{
499 u8 timeout = 0;
500
501 /* do not reset watchdog too often - max every 4s */
502 if (get_timer(twl_wd_time) < 4 * CONFIG_SYS_HZ)
Pali Rohár126038a2021-03-09 21:19:15 +0100503 return 0;
Pali Rohár248ef0a2012-10-29 07:54:01 +0000504
505 /* localy lock twl4030 i2c bus */
506 if (test_and_set_bit(0, &twl_i2c_lock))
Pali Rohár126038a2021-03-09 21:19:15 +0100507 return 0;
Pali Rohár248ef0a2012-10-29 07:54:01 +0000508
509 /* read actual watchdog timeout */
Nishanth Menon5d9d6f72013-03-26 05:20:50 +0000510 twl4030_i2c_read_u8(TWL4030_CHIP_PM_RECEIVER,
511 TWL4030_PM_RECEIVER_WATCHDOG_CFG, &timeout);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000512
513 /* timeout 0 means watchdog is disabled */
514 /* reset watchdog timeout to 31s (maximum) */
515 if (timeout != 0)
Nishanth Menond26a1062013-03-26 05:20:49 +0000516 twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER,
517 TWL4030_PM_RECEIVER_WATCHDOG_CFG, 31);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000518
519 /* store last watchdog reset time */
520 twl_wd_time = get_timer(0);
521
522 /* localy unlock twl4030 i2c bus */
523 test_and_clear_bit(0, &twl_i2c_lock);
Pali Rohár126038a2021-03-09 21:19:15 +0100524
525 return 0;
526}
527
528static int rx51_watchdog_start(struct udevice *dev, u64 timeout_ms, ulong flags)
529{
530 return 0;
Pali Rohár248ef0a2012-10-29 07:54:01 +0000531}
532
Pali Rohár126038a2021-03-09 21:19:15 +0100533static int rx51_watchdog_probe(struct udevice *dev)
534{
535 return 0;
536}
537
538static const struct wdt_ops rx51_watchdog_ops = {
539 .start = rx51_watchdog_start,
540 .reset = rx51_watchdog_reset,
541};
542
543U_BOOT_DRIVER(rx51_watchdog) = {
544 .name = "rx51_watchdog",
545 .id = UCLASS_WDT,
546 .ops = &rx51_watchdog_ops,
547 .probe = rx51_watchdog_probe,
548};
549
Pali Rohár248ef0a2012-10-29 07:54:01 +0000550/*
551 * TWL4030 keypad handler for cfb_console
552 */
553
554static const char keymap[] = {
555 /* normal */
556 'q', 'o', 'p', ',', '\b', 0, 'a', 's',
557 'w', 'd', 'f', 'g', 'h', 'j', 'k', 'l',
558 'e', '.', 0, '\r', 0, 'z', 'x', 'c',
559 'r', 'v', 'b', 'n', 'm', ' ', ' ', 0,
560 't', 0, 0, 0, 0, 0, 0, 0,
561 'y', 0, 0, 0, 0, 0, 0, 0,
562 'u', 0, 0, 0, 0, 0, 0, 0,
563 'i', 5, 6, 0, 0, 0, 0, 0,
564 /* fn */
565 '1', '9', '0', '=', '\b', 0, '*', '+',
566 '2', '#', '-', '_', '(', ')', '&', '!',
567 '3', '?', '^', '\r', 0, 156, '$', 238,
568 '4', '/', '\\', '"', '\'', '@', 0, '<',
569 '5', '|', '>', 0, 0, 0, 0, 0,
570 '6', 0, 0, 0, 0, 0, 0, 0,
571 '7', 0, 0, 0, 0, 0, 0, 0,
572 '8', 16, 17, 0, 0, 0, 0, 0,
573};
574
575static u8 keys[8];
576static u8 old_keys[8] = {0, 0, 0, 0, 0, 0, 0, 0};
577#define KEYBUF_SIZE 32
578static u8 keybuf[KEYBUF_SIZE];
579static u8 keybuf_head;
580static u8 keybuf_tail;
581
582/*
Pali Rohár54a30142022-02-03 19:38:50 +0100583 * Routine: rx51_kp_start
Pali Rohár248ef0a2012-10-29 07:54:01 +0000584 * Description: Initialize HW keyboard.
585 */
Pali Rohár54a30142022-02-03 19:38:50 +0100586static int rx51_kp_start(struct udevice *dev)
Pali Rohár248ef0a2012-10-29 07:54:01 +0000587{
588 int ret = 0;
589 u8 ctrl;
Nishanth Menon5d9d6f72013-03-26 05:20:50 +0000590 ret = twl4030_i2c_read_u8(TWL4030_CHIP_KEYPAD,
591 TWL4030_KEYPAD_KEYP_CTRL_REG, &ctrl);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000592
593 if (ret)
594 return ret;
595
596 /* turn on keyboard and use hardware scanning */
597 ctrl |= TWL4030_KEYPAD_CTRL_KBD_ON;
598 ctrl |= TWL4030_KEYPAD_CTRL_SOFT_NRST;
599 ctrl |= TWL4030_KEYPAD_CTRL_SOFTMODEN;
Nishanth Menond26a1062013-03-26 05:20:49 +0000600 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
601 TWL4030_KEYPAD_KEYP_CTRL_REG, ctrl);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000602 /* enable key event status */
Nishanth Menond26a1062013-03-26 05:20:49 +0000603 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
604 TWL4030_KEYPAD_KEYP_IMR1, 0xfe);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000605 /* enable interrupt generation on rising and falling */
606 /* this is a workaround for qemu twl4030 emulation */
Nishanth Menond26a1062013-03-26 05:20:49 +0000607 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
608 TWL4030_KEYPAD_KEYP_EDR, 0x57);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000609 /* enable ISR clear on read */
Nishanth Menond26a1062013-03-26 05:20:49 +0000610 ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
611 TWL4030_KEYPAD_KEYP_SIH_CTRL, 0x05);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000612 return 0;
613}
614
615static void rx51_kp_fill(u8 k, u8 mods)
616{
617 /* check if some cursor key without meta fn key was pressed */
618 if (!(mods & 2) && (k == 18 || k == 31 || k == 33 || k == 34)) {
619 keybuf[keybuf_tail++] = '\e';
620 keybuf_tail %= KEYBUF_SIZE;
621 keybuf[keybuf_tail++] = '[';
622 keybuf_tail %= KEYBUF_SIZE;
623 if (k == 18) /* up */
624 keybuf[keybuf_tail++] = 'A';
625 else if (k == 31) /* left */
626 keybuf[keybuf_tail++] = 'D';
627 else if (k == 33) /* down */
628 keybuf[keybuf_tail++] = 'B';
629 else if (k == 34) /* right */
630 keybuf[keybuf_tail++] = 'C';
631 keybuf_tail %= KEYBUF_SIZE;
632 return;
633 }
634
635 if (mods & 2) { /* fn meta key was pressed */
636 k = keymap[k+64];
637 } else {
638 k = keymap[k];
639 if (mods & 1) { /* ctrl key was pressed */
640 if (k >= 'a' && k <= 'z')
641 k -= 'a' - 1;
642 }
643 if (mods & 4) { /* shift key was pressed */
644 if (k >= 'a' && k <= 'z')
645 k += 'A' - 'a';
646 else if (k == '.')
647 k = ':';
648 else if (k == ',')
649 k = ';';
650 }
651 }
652 keybuf[keybuf_tail++] = k;
653 keybuf_tail %= KEYBUF_SIZE;
654}
655
656/*
657 * Routine: rx51_kp_tstc
658 * Description: Test if key was pressed (from buffer).
659 */
Pali Rohár54a30142022-02-03 19:38:50 +0100660static int rx51_kp_tstc(struct udevice *dev)
Pali Rohár248ef0a2012-10-29 07:54:01 +0000661{
662 u8 c, r, dk, i;
663 u8 intr;
664 u8 mods;
665
666 /* localy lock twl4030 i2c bus */
667 if (test_and_set_bit(0, &twl_i2c_lock))
668 return 0;
669
670 /* twl4030 remembers up to 2 events */
671 for (i = 0; i < 2; i++) {
672
673 /* check interrupt register for events */
Nishanth Menon5d9d6f72013-03-26 05:20:50 +0000674 twl4030_i2c_read_u8(TWL4030_CHIP_KEYPAD,
675 TWL4030_KEYPAD_KEYP_ISR1 + (2 * i), &intr);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000676
677 /* no event */
678 if (!(intr&1))
679 continue;
680
681 /* read the key state */
Pali Rohárd73afb22020-10-26 23:45:11 +0100682 twl4030_i2c_read(TWL4030_CHIP_KEYPAD,
683 TWL4030_KEYPAD_FULL_CODE_7_0, keys, 8);
Pali Rohár248ef0a2012-10-29 07:54:01 +0000684
685 /* cut out modifier keys from the keystate */
686 mods = keys[4] >> 4;
687 keys[4] &= 0x0f;
688
689 for (c = 0; c < 8; c++) {
690
691 /* get newly pressed keys only */
692 dk = ((keys[c] ^ old_keys[c])&keys[c]);
693 old_keys[c] = keys[c];
694
695 /* fill the keybuf */
696 for (r = 0; r < 8; r++) {
697 if (dk&1)
698 rx51_kp_fill((c*8)+r, mods);
699 dk = dk >> 1;
700 }
701
702 }
703
704 }
705
706 /* localy unlock twl4030 i2c bus */
707 test_and_clear_bit(0, &twl_i2c_lock);
708
709 return (KEYBUF_SIZE + keybuf_tail - keybuf_head)%KEYBUF_SIZE;
710}
711
712/*
713 * Routine: rx51_kp_getc
714 * Description: Get last pressed key (from buffer).
715 */
Pali Rohár54a30142022-02-03 19:38:50 +0100716static int rx51_kp_getc(struct udevice *dev)
Pali Rohár248ef0a2012-10-29 07:54:01 +0000717{
718 keybuf_head %= KEYBUF_SIZE;
Pali Rohár54a30142022-02-03 19:38:50 +0100719 while (!rx51_kp_tstc(dev))
Pali Rohár248ef0a2012-10-29 07:54:01 +0000720 WATCHDOG_RESET();
721 return keybuf[keybuf_head++];
722}
723
Pali Rohár54a30142022-02-03 19:38:50 +0100724static int rx51_kp_probe(struct udevice *dev)
725{
726 struct keyboard_priv *uc_priv = dev_get_uclass_priv(dev);
727 struct stdio_dev *sdev = &uc_priv->sdev;
728
729 strcpy(sdev->name, "keyboard");
730 return input_stdio_register(sdev);
731}
732
733static const struct keyboard_ops rx51_kp_ops = {
734 .start = rx51_kp_start,
735 .tstc = rx51_kp_tstc,
736 .getc = rx51_kp_getc,
737};
738
739U_BOOT_DRIVER(rx51_kp) = {
740 .name = "rx51_kp",
741 .id = UCLASS_KEYBOARD,
742 .probe = rx51_kp_probe,
743 .ops = &rx51_kp_ops,
744};
745
Pali Rohárcc58d292021-01-16 01:04:54 +0100746static const struct mmc_config rx51_mmc_cfg = {
747 .host_caps = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS,
748 .f_min = 400000,
749 .f_max = 52000000,
750 .b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT,
751 .voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195,
752};
Paul Kocialkowski69559892014-11-08 20:55:47 +0100753
Pali Rohárcc58d292021-01-16 01:04:54 +0100754static const struct omap_hsmmc_plat rx51_mmc[] = {
755 { rx51_mmc_cfg, (struct hsmmc *)OMAP_HSMMC1_BASE },
756 { rx51_mmc_cfg, (struct hsmmc *)OMAP_HSMMC2_BASE },
757};
758
759U_BOOT_DRVINFOS(rx51_mmc) = {
760 { "omap_hsmmc", &rx51_mmc[0] },
761 { "omap_hsmmc", &rx51_mmc[1] },
762};
Pali Rohárd73afb22020-10-26 23:45:11 +0100763
Simon Glassb75b15b2020-12-03 16:55:23 -0700764static const struct omap_i2c_plat rx51_i2c[] = {
Pali Rohárde39c112020-11-21 23:30:11 +0100765 { I2C_BASE1, 100000, OMAP_I2C_REV_V1 },
Pali Rohárd73afb22020-10-26 23:45:11 +0100766 { I2C_BASE2, 100000, OMAP_I2C_REV_V1 },
Pali Rohárde39c112020-11-21 23:30:11 +0100767 { I2C_BASE3, 100000, OMAP_I2C_REV_V1 },
Pali Rohárd73afb22020-10-26 23:45:11 +0100768};
769
Simon Glass1d8364a2020-12-28 20:34:54 -0700770U_BOOT_DRVINFOS(rx51_i2c) = {
Pali Rohárd73afb22020-10-26 23:45:11 +0100771 { "i2c_omap", &rx51_i2c[0] },
772 { "i2c_omap", &rx51_i2c[1] },
773 { "i2c_omap", &rx51_i2c[2] },
774};
Pali Rohár126038a2021-03-09 21:19:15 +0100775
776U_BOOT_DRVINFOS(rx51_watchdog) = {
777 { "rx51_watchdog" },
778};
Pali Rohár54a30142022-02-03 19:38:50 +0100779
780U_BOOT_DRVINFOS(rx51_kp) = {
781 { "rx51_kp" },
782};