1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2ed407be5SPali Rohár /*
3ed407be5SPali Rohár * (C) Copyright 2012
4ed407be5SPali Rohár * Ивайло Димитров <freemangordon@abv.bg>
5ed407be5SPali Rohár *
6ed407be5SPali Rohár * (C) Copyright 2011-2012
7ed407be5SPali Rohár * Pali Rohár <pali.rohar@gmail.com>
8ed407be5SPali Rohár *
9ed407be5SPali Rohár * (C) Copyright 2010
10ed407be5SPali Rohár * Alistair Buxton <a.j.buxton@gmail.com>
11ed407be5SPali Rohár *
12ed407be5SPali Rohár * Derived from Beagle Board and 3430 SDP code:
13ed407be5SPali Rohár * (C) Copyright 2004-2008
14ed407be5SPali Rohár * Texas Instruments, <www.ti.com>
15ed407be5SPali Rohár *
16ed407be5SPali Rohár * Author :
17ed407be5SPali Rohár * Sunil Kumar <sunilsaini05@gmail.com>
18ed407be5SPali Rohár * Shashi Ranjan <shashiranjanmca05@gmail.com>
19ed407be5SPali Rohár *
20ed407be5SPali Rohár * Richard Woodruff <r-woodruff2@ti.com>
21ed407be5SPali Rohár * Syed Mohammed Khasim <khasim@ti.com>
22ed407be5SPali Rohár */
23ed407be5SPali Rohár
24ed407be5SPali Rohár #include <common.h>
25ed407be5SPali Rohár #include <watchdog.h>
26ed407be5SPali Rohár #include <malloc.h>
27ed407be5SPali Rohár #include <twl4030.h>
28ed407be5SPali Rohár #include <i2c.h>
29ed407be5SPali Rohár #include <video_fb.h>
30ed407be5SPali Rohár #include <asm/io.h>
31ed407be5SPali Rohár #include <asm/setup.h>
32ed407be5SPali Rohár #include <asm/bitops.h>
33ed407be5SPali Rohár #include <asm/mach-types.h>
34ed407be5SPali Rohár #include <asm/arch/mux.h>
35ed407be5SPali Rohár #include <asm/arch/sys_proto.h>
36ed407be5SPali Rohár #include <asm/arch/mmc_host_def.h>
37ed407be5SPali Rohár
38ed407be5SPali Rohár #include "rx51.h"
39ed407be5SPali Rohár #include "tag_omap.h"
40ed407be5SPali Rohár
41ed407be5SPali Rohár DECLARE_GLOBAL_DATA_PTR;
42ed407be5SPali Rohár
43ed407be5SPali Rohár GraphicDevice gdev;
44ed407be5SPali Rohár
45ed407be5SPali Rohár const omap3_sysinfo sysinfo = {
46ed407be5SPali Rohár DDR_STACKED,
47ed407be5SPali Rohár "Nokia RX-51",
48ed407be5SPali Rohár "OneNAND"
49ed407be5SPali Rohár };
50ed407be5SPali Rohár
51ed407be5SPali Rohár /* This structure contains default omap tags needed for booting Maemo 5 */
52ed407be5SPali Rohár static struct tag_omap omap[] = {
53ed407be5SPali Rohár OMAP_TAG_UART_CONFIG(0x04),
54ed407be5SPali Rohár OMAP_TAG_SERIAL_CONSOLE_CONFIG(0x03, 0x01C200),
55ed407be5SPali Rohár OMAP_TAG_LCD_CONFIG("acx565akm", "internal", 90, 0x18),
56ed407be5SPali Rohár OMAP_TAG_GPIO_SWITCH_CONFIG("cam_focus", 0x44, 0x1, 0x2, 0x0),
57ed407be5SPali Rohár OMAP_TAG_GPIO_SWITCH_CONFIG("cam_launch", 0x45, 0x1, 0x2, 0x0),
58ed407be5SPali Rohár OMAP_TAG_GPIO_SWITCH_CONFIG("cam_shutter", 0x6e, 0x1, 0x0, 0x0),
59ed407be5SPali Rohár OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_apeslpx", 0x46, 0x2, 0x2, 0x0),
60ed407be5SPali Rohár OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_bsi", 0x9d, 0x2, 0x2, 0x0),
61ed407be5SPali Rohár OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_en", 0x4a, 0x2, 0x2, 0x0),
62ed407be5SPali Rohár OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_rst", 0x4b, 0x6, 0x2, 0x0),
63ed407be5SPali Rohár OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_rst_rq", 0x49, 0x6, 0x2, 0x0),
64ed407be5SPali Rohár OMAP_TAG_GPIO_SWITCH_CONFIG("cmt_wddis", 0x0d, 0x2, 0x2, 0x0),
65ed407be5SPali Rohár OMAP_TAG_GPIO_SWITCH_CONFIG("headphone", 0xb1, 0x1, 0x1, 0x0),
66ed407be5SPali Rohár OMAP_TAG_GPIO_SWITCH_CONFIG("kb_lock", 0x71, 0x1, 0x0, 0x0),
67ed407be5SPali Rohár OMAP_TAG_GPIO_SWITCH_CONFIG("proximity", 0x59, 0x0, 0x0, 0x0),
68ed407be5SPali Rohár OMAP_TAG_GPIO_SWITCH_CONFIG("sleep_ind", 0xa2, 0x2, 0x2, 0x0),
69ed407be5SPali Rohár OMAP_TAG_GPIO_SWITCH_CONFIG("slide", GPIO_SLIDE, 0x0, 0x0, 0x0),
70ed407be5SPali Rohár OMAP_TAG_WLAN_CX3110X_CONFIG(0x25, 0xff, 87, 42, -1),
71ed407be5SPali Rohár OMAP_TAG_PARTITION_CONFIG(PART1_NAME, PART1_SIZE * PART1_MULL,
72ed407be5SPali Rohár PART1_OFFS, PART1_MASK),
73ed407be5SPali Rohár OMAP_TAG_PARTITION_CONFIG(PART2_NAME, PART2_SIZE * PART2_MULL,
74ed407be5SPali Rohár PART2_OFFS, PART2_MASK),
75ed407be5SPali Rohár OMAP_TAG_PARTITION_CONFIG(PART3_NAME, PART3_SIZE * PART3_MULL,
76ed407be5SPali Rohár PART3_OFFS, PART3_MASK),
77ed407be5SPali Rohár OMAP_TAG_PARTITION_CONFIG(PART4_NAME, PART4_SIZE * PART4_MULL,
78ed407be5SPali Rohár PART4_OFFS, PART4_MASK),
79ed407be5SPali Rohár OMAP_TAG_PARTITION_CONFIG(PART5_NAME, PART5_SIZE * PART5_MULL,
80ed407be5SPali Rohár PART5_OFFS, PART5_MASK),
81ed407be5SPali Rohár OMAP_TAG_PARTITION_CONFIG(PART6_NAME, PART6_SIZE * PART6_MULL,
82ed407be5SPali Rohár PART6_OFFS, PART6_MASK),
83ed407be5SPali Rohár OMAP_TAG_BOOT_REASON_CONFIG("pwr_key"),
84ed407be5SPali Rohár OMAP_TAG_VERSION_STR_CONFIG("product", "RX-51"),
85ed407be5SPali Rohár OMAP_TAG_VERSION_STR_CONFIG("hw-build", "2101"),
86ed407be5SPali Rohár OMAP_TAG_VERSION_STR_CONFIG("nolo", "1.4.14"),
87ed407be5SPali Rohár OMAP_TAG_VERSION_STR_CONFIG("boot-mode", "normal"),
88ed407be5SPali Rohár { }
89ed407be5SPali Rohár };
90ed407be5SPali Rohár
91ed407be5SPali Rohár static char *boot_reason_ptr;
92ed407be5SPali Rohár static char *hw_build_ptr;
93ed407be5SPali Rohár static char *nolo_version_ptr;
94ed407be5SPali Rohár static char *boot_mode_ptr;
95ed407be5SPali Rohár
96ed407be5SPali Rohár /*
97ed407be5SPali Rohár * Routine: init_omap_tags
98ed407be5SPali Rohár * Description: Initialize pointers to values in tag_omap
99ed407be5SPali Rohár */
init_omap_tags(void)100ed407be5SPali Rohár static void init_omap_tags(void)
101ed407be5SPali Rohár {
102ed407be5SPali Rohár char *component;
103ed407be5SPali Rohár char *version;
104ed407be5SPali Rohár int i = 0;
105ed407be5SPali Rohár while (omap[i].hdr.tag) {
106ed407be5SPali Rohár switch (omap[i].hdr.tag) {
107ed407be5SPali Rohár case OMAP_TAG_BOOT_REASON:
108ed407be5SPali Rohár boot_reason_ptr = omap[i].u.boot_reason.reason_str;
109ed407be5SPali Rohár break;
110ed407be5SPali Rohár case OMAP_TAG_VERSION_STR:
111ed407be5SPali Rohár component = omap[i].u.version.component;
112ed407be5SPali Rohár version = omap[i].u.version.version;
113ed407be5SPali Rohár if (strcmp(component, "hw-build") == 0)
114ed407be5SPali Rohár hw_build_ptr = version;
115ed407be5SPali Rohár else if (strcmp(component, "nolo") == 0)
116ed407be5SPali Rohár nolo_version_ptr = version;
117ed407be5SPali Rohár else if (strcmp(component, "boot-mode") == 0)
118ed407be5SPali Rohár boot_mode_ptr = version;
119ed407be5SPali Rohár break;
120ed407be5SPali Rohár default:
121ed407be5SPali Rohár break;
122ed407be5SPali Rohár }
123ed407be5SPali Rohár i++;
124ed407be5SPali Rohár }
125ed407be5SPali Rohár }
126ed407be5SPali Rohár
reuse_omap_atags(struct tag_omap * t)127ed407be5SPali Rohár static void reuse_omap_atags(struct tag_omap *t)
128ed407be5SPali Rohár {
129ed407be5SPali Rohár char *component;
130ed407be5SPali Rohár char *version;
131ed407be5SPali Rohár while (t->hdr.tag) {
132ed407be5SPali Rohár switch (t->hdr.tag) {
133ed407be5SPali Rohár case OMAP_TAG_BOOT_REASON:
134ed407be5SPali Rohár memset(boot_reason_ptr, 0, 12);
135ed407be5SPali Rohár strcpy(boot_reason_ptr, t->u.boot_reason.reason_str);
136ed407be5SPali Rohár break;
137ed407be5SPali Rohár case OMAP_TAG_VERSION_STR:
138ed407be5SPali Rohár component = t->u.version.component;
139ed407be5SPali Rohár version = t->u.version.version;
140ed407be5SPali Rohár if (strcmp(component, "hw-build") == 0) {
141ed407be5SPali Rohár memset(hw_build_ptr, 0, 12);
142ed407be5SPali Rohár strcpy(hw_build_ptr, version);
143ed407be5SPali Rohár } else if (strcmp(component, "nolo") == 0) {
144ed407be5SPali Rohár memset(nolo_version_ptr, 0, 12);
145ed407be5SPali Rohár strcpy(nolo_version_ptr, version);
146ed407be5SPali Rohár } else if (strcmp(component, "boot-mode") == 0) {
147ed407be5SPali Rohár memset(boot_mode_ptr, 0, 12);
148ed407be5SPali Rohár strcpy(boot_mode_ptr, version);
149ed407be5SPali Rohár }
150ed407be5SPali Rohár break;
151ed407be5SPali Rohár default:
152ed407be5SPali Rohár break;
153ed407be5SPali Rohár }
154ed407be5SPali Rohár t = tag_omap_next(t);
155ed407be5SPali Rohár }
156ed407be5SPali Rohár }
157ed407be5SPali Rohár
158ed407be5SPali Rohár /*
159ed407be5SPali Rohár * Routine: reuse_atags
160ed407be5SPali Rohár * Description: Reuse atags from previous bootloader.
161ed407be5SPali Rohár * Reuse only only HW build, boot reason, boot mode and nolo
162ed407be5SPali Rohár */
reuse_atags(void)163ed407be5SPali Rohár static void reuse_atags(void)
164ed407be5SPali Rohár {
165ed407be5SPali Rohár struct tag *t = (struct tag *)gd->bd->bi_boot_params;
166ed407be5SPali Rohár
167ed407be5SPali Rohár /* First tag must be ATAG_CORE */
168ed407be5SPali Rohár if (t->hdr.tag != ATAG_CORE)
169ed407be5SPali Rohár return;
170ed407be5SPali Rohár
171ed407be5SPali Rohár if (!boot_reason_ptr || !hw_build_ptr)
172ed407be5SPali Rohár return;
173ed407be5SPali Rohár
174ed407be5SPali Rohár /* Last tag must be ATAG_NONE */
175ed407be5SPali Rohár while (t->hdr.tag != ATAG_NONE) {
176ed407be5SPali Rohár switch (t->hdr.tag) {
177ed407be5SPali Rohár case ATAG_REVISION:
178ed407be5SPali Rohár memset(hw_build_ptr, 0, 12);
179ed407be5SPali Rohár sprintf(hw_build_ptr, "%x", t->u.revision.rev);
180ed407be5SPali Rohár break;
181ed407be5SPali Rohár case ATAG_BOARD:
182ed407be5SPali Rohár reuse_omap_atags((struct tag_omap *)&t->u);
183ed407be5SPali Rohár break;
184ed407be5SPali Rohár default:
185ed407be5SPali Rohár break;
186ed407be5SPali Rohár }
187ed407be5SPali Rohár t = tag_next(t);
188ed407be5SPali Rohár }
189ed407be5SPali Rohár }
190ed407be5SPali Rohár
191ed407be5SPali Rohár /*
192ed407be5SPali Rohár * Routine: board_init
193ed407be5SPali Rohár * Description: Early hardware init.
194ed407be5SPali Rohár */
board_init(void)195ed407be5SPali Rohár int board_init(void)
196ed407be5SPali Rohár {
197ed407be5SPali Rohár /* in SRAM or SDRAM, finish GPMC */
198ed407be5SPali Rohár gpmc_init();
199ed407be5SPali Rohár /* boot param addr */
200ed407be5SPali Rohár gd->bd->bi_boot_params = OMAP34XX_SDRC_CS0 + 0x100;
201ed407be5SPali Rohár return 0;
202ed407be5SPali Rohár }
203ed407be5SPali Rohár
204ed407be5SPali Rohár /*
205ed407be5SPali Rohár * Routine: get_board_revision
206ed407be5SPali Rohár * Description: Return board revision.
207ed407be5SPali Rohár */
get_board_rev(void)208ed407be5SPali Rohár u32 get_board_rev(void)
209ed407be5SPali Rohár {
210ed407be5SPali Rohár return simple_strtol(hw_build_ptr, NULL, 16);
211ed407be5SPali Rohár }
212ed407be5SPali Rohár
213ed407be5SPali Rohár /*
214ed407be5SPali Rohár * Routine: setup_board_tags
215ed407be5SPali Rohár * Description: Append board specific boot tags.
216ed407be5SPali Rohár */
setup_board_tags(struct tag ** in_params)217ed407be5SPali Rohár void setup_board_tags(struct tag **in_params)
218ed407be5SPali Rohár {
219ed407be5SPali Rohár int setup_console_atag;
220ed407be5SPali Rohár char *setup_boot_reason_atag;
221ed407be5SPali Rohár char *setup_boot_mode_atag;
222ed407be5SPali Rohár char *str;
223ed407be5SPali Rohár int i;
224ed407be5SPali Rohár int size;
225ed407be5SPali Rohár int total_size;
226ed407be5SPali Rohár struct tag *params;
227ed407be5SPali Rohár struct tag_omap *t;
228ed407be5SPali Rohár
229ed407be5SPali Rohár params = (struct tag *)gd->bd->bi_boot_params;
230ed407be5SPali Rohár
231ed407be5SPali Rohár params->u.core.flags = 0x0;
232ed407be5SPali Rohár params->u.core.pagesize = 0x1000;
233ed407be5SPali Rohár params->u.core.rootdev = 0x0;
234ed407be5SPali Rohár
235ed407be5SPali Rohár /* append omap atag only if env setup_omap_atag is set to 1 */
23600caae6dSSimon Glass str = env_get("setup_omap_atag");
237ed407be5SPali Rohár if (!str || str[0] != '1')
238ed407be5SPali Rohár return;
239ed407be5SPali Rohár
24000caae6dSSimon Glass str = env_get("setup_console_atag");
241ed407be5SPali Rohár if (str && str[0] == '1')
242ed407be5SPali Rohár setup_console_atag = 1;
243ed407be5SPali Rohár else
244ed407be5SPali Rohár setup_console_atag = 0;
245ed407be5SPali Rohár
24600caae6dSSimon Glass setup_boot_reason_atag = env_get("setup_boot_reason_atag");
24700caae6dSSimon Glass setup_boot_mode_atag = env_get("setup_boot_mode_atag");
248ed407be5SPali Rohár
249ed407be5SPali Rohár params = *in_params;
250ed407be5SPali Rohár t = (struct tag_omap *)¶ms->u;
251ed407be5SPali Rohár total_size = sizeof(struct tag_header);
252ed407be5SPali Rohár
253ed407be5SPali Rohár for (i = 0; omap[i].hdr.tag; i++) {
254ed407be5SPali Rohár
255ed407be5SPali Rohár /* skip serial console tag */
256ed407be5SPali Rohár if (!setup_console_atag &&
257ed407be5SPali Rohár omap[i].hdr.tag == OMAP_TAG_SERIAL_CONSOLE)
258ed407be5SPali Rohár continue;
259ed407be5SPali Rohár
260ed407be5SPali Rohár size = omap[i].hdr.size + sizeof(struct tag_omap_header);
261ed407be5SPali Rohár memcpy(t, &omap[i], size);
262ed407be5SPali Rohár
263ed407be5SPali Rohár /* set uart tag to 0 - disable serial console */
264ed407be5SPali Rohár if (!setup_console_atag && omap[i].hdr.tag == OMAP_TAG_UART)
265ed407be5SPali Rohár t->u.uart.enabled_uarts = 0;
266ed407be5SPali Rohár
267ed407be5SPali Rohár /* change boot reason */
268ed407be5SPali Rohár if (setup_boot_reason_atag &&
269ed407be5SPali Rohár omap[i].hdr.tag == OMAP_TAG_BOOT_REASON) {
270ed407be5SPali Rohár memset(t->u.boot_reason.reason_str, 0, 12);
271ed407be5SPali Rohár strcpy(t->u.boot_reason.reason_str,
272ed407be5SPali Rohár setup_boot_reason_atag);
273ed407be5SPali Rohár }
274ed407be5SPali Rohár
275ed407be5SPali Rohár /* change boot mode */
276ed407be5SPali Rohár if (setup_boot_mode_atag &&
277ed407be5SPali Rohár omap[i].hdr.tag == OMAP_TAG_VERSION_STR &&
278ed407be5SPali Rohár strcmp(omap[i].u.version.component, "boot-mode") == 0) {
279ed407be5SPali Rohár memset(t->u.version.version, 0, 12);
280ed407be5SPali Rohár strcpy(t->u.version.version, setup_boot_mode_atag);
281ed407be5SPali Rohár }
282ed407be5SPali Rohár
283ed407be5SPali Rohár total_size += size;
284ed407be5SPali Rohár t = tag_omap_next(t);
285ed407be5SPali Rohár
286ed407be5SPali Rohár }
287ed407be5SPali Rohár
288ed407be5SPali Rohár params->hdr.tag = ATAG_BOARD;
289ed407be5SPali Rohár params->hdr.size = total_size >> 2;
290ed407be5SPali Rohár params = tag_next(params);
291ed407be5SPali Rohár
292ed407be5SPali Rohár *in_params = params;
293ed407be5SPali Rohár }
294ed407be5SPali Rohár
295ed407be5SPali Rohár /*
296ed407be5SPali Rohár * Routine: video_hw_init
297ed407be5SPali Rohár * Description: Set up the GraphicDevice depending on sys_boot.
298ed407be5SPali Rohár */
video_hw_init(void)299ed407be5SPali Rohár void *video_hw_init(void)
300ed407be5SPali Rohár {
301ed407be5SPali Rohár /* fill in Graphic Device */
302ed407be5SPali Rohár gdev.frameAdrs = 0x8f9c0000;
303ed407be5SPali Rohár gdev.winSizeX = 800;
304ed407be5SPali Rohár gdev.winSizeY = 480;
305ed407be5SPali Rohár gdev.gdfBytesPP = 2;
306ed407be5SPali Rohár gdev.gdfIndex = GDF_16BIT_565RGB;
307ed407be5SPali Rohár memset((void *)gdev.frameAdrs, 0, 0xbb800);
308ed407be5SPali Rohár return (void *) &gdev;
309ed407be5SPali Rohár }
310ed407be5SPali Rohár
311ed407be5SPali Rohár /*
312ed407be5SPali Rohár * Routine: twl4030_regulator_set_mode
313ed407be5SPali Rohár * Description: Set twl4030 regulator mode over i2c powerbus.
314ed407be5SPali Rohár */
twl4030_regulator_set_mode(u8 id,u8 mode)315ed407be5SPali Rohár static void twl4030_regulator_set_mode(u8 id, u8 mode)
316ed407be5SPali Rohár {
317ed407be5SPali Rohár u16 msg = MSG_SINGULAR(DEV_GRP_P1, id, mode);
3180208aaf6SNishanth Menon twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
3190208aaf6SNishanth Menon TWL4030_PM_MASTER_PB_WORD_MSB, msg >> 8);
3200208aaf6SNishanth Menon twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
3210208aaf6SNishanth Menon TWL4030_PM_MASTER_PB_WORD_LSB, msg & 0xff);
322ed407be5SPali Rohár }
323ed407be5SPali Rohár
omap3_emu_romcode_call(u32 service_id,u32 * parameters)324ed407be5SPali Rohár static void omap3_emu_romcode_call(u32 service_id, u32 *parameters)
325ed407be5SPali Rohár {
326ed407be5SPali Rohár u32 i, num_params = *parameters;
327ed407be5SPali Rohár u32 *sram_scratch_space = (u32 *)OMAP3_PUBLIC_SRAM_SCRATCH_AREA;
328ed407be5SPali Rohár
329ed407be5SPali Rohár /*
330ed407be5SPali Rohár * copy the parameters to an un-cached area to avoid coherency
331ed407be5SPali Rohár * issues
332ed407be5SPali Rohár */
333ed407be5SPali Rohár for (i = 0; i < num_params; i++) {
334ed407be5SPali Rohár __raw_writel(*parameters, sram_scratch_space);
335ed407be5SPali Rohár parameters++;
336ed407be5SPali Rohár sram_scratch_space++;
337ed407be5SPali Rohár }
338ed407be5SPali Rohár
339ed407be5SPali Rohár /* Now make the PPA call */
340ed407be5SPali Rohár do_omap3_emu_romcode_call(service_id, OMAP3_PUBLIC_SRAM_SCRATCH_AREA);
341ed407be5SPali Rohár }
342ed407be5SPali Rohár
omap3_set_aux_cr_secure(u32 acr)343cdef0b3fSNishanth Menon void omap3_set_aux_cr_secure(u32 acr)
344cdef0b3fSNishanth Menon {
345cdef0b3fSNishanth Menon struct emu_hal_params_rx51 emu_romcode_params = { 0, };
346cdef0b3fSNishanth Menon
347cdef0b3fSNishanth Menon emu_romcode_params.num_params = 2;
348cdef0b3fSNishanth Menon emu_romcode_params.param1 = acr;
349cdef0b3fSNishanth Menon
350cdef0b3fSNishanth Menon omap3_emu_romcode_call(OMAP3_EMU_HAL_API_WRITE_ACR,
351cdef0b3fSNishanth Menon (u32 *)&emu_romcode_params);
352cdef0b3fSNishanth Menon }
353cdef0b3fSNishanth Menon
354ed407be5SPali Rohár /*
355ed407be5SPali Rohár * Routine: omap3_update_aux_cr_secure_rx51
356ed407be5SPali Rohár * Description: Modify the contents Auxiliary Control Register.
357ed407be5SPali Rohár * Parameters:
358ed407be5SPali Rohár * set_bits - bits to set in ACR
359ed407be5SPali Rohár * clr_bits - bits to clear in ACR
360ed407be5SPali Rohár */
omap3_update_aux_cr_secure_rx51(u32 set_bits,u32 clear_bits)361ed407be5SPali Rohár static void omap3_update_aux_cr_secure_rx51(u32 set_bits, u32 clear_bits)
362ed407be5SPali Rohár {
363ed407be5SPali Rohár u32 acr;
364ed407be5SPali Rohár
365ed407be5SPali Rohár /* Read ACR */
366ed407be5SPali Rohár asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r" (acr));
367ed407be5SPali Rohár acr &= ~clear_bits;
368ed407be5SPali Rohár acr |= set_bits;
369cdef0b3fSNishanth Menon omap3_set_aux_cr_secure(acr);
370ed407be5SPali Rohár }
371ed407be5SPali Rohár
372ed407be5SPali Rohár /*
373ed407be5SPali Rohár * Routine: misc_init_r
374ed407be5SPali Rohár * Description: Configure board specific parts.
375ed407be5SPali Rohár */
misc_init_r(void)376ed407be5SPali Rohár int misc_init_r(void)
377ed407be5SPali Rohár {
378ed407be5SPali Rohár char buf[12];
379ed407be5SPali Rohár u8 state;
380ed407be5SPali Rohár
381ed407be5SPali Rohár /* reset lp5523 led */
382ed407be5SPali Rohár i2c_set_bus_num(1);
383ed407be5SPali Rohár state = 0xff;
384ed407be5SPali Rohár i2c_write(0x32, 0x3d, 1, &state, 1);
385ed407be5SPali Rohár i2c_set_bus_num(0);
386ed407be5SPali Rohár
387ed407be5SPali Rohár /* initialize twl4030 power managment */
388ed407be5SPali Rohár twl4030_power_init();
389ed407be5SPali Rohár
390ed407be5SPali Rohár /* set VSIM to 1.8V */
391ed407be5SPali Rohár twl4030_pmrecv_vsel_cfg(TWL4030_PM_RECEIVER_VSIM_DEDICATED,
392ed407be5SPali Rohár TWL4030_PM_RECEIVER_VSIM_VSEL_18,
393ed407be5SPali Rohár TWL4030_PM_RECEIVER_VSIM_DEV_GRP,
394ed407be5SPali Rohár TWL4030_PM_RECEIVER_DEV_GRP_P1);
395ed407be5SPali Rohár
396ed407be5SPali Rohár /* store I2C access state */
397b29c2f0cSNishanth Menon twl4030_i2c_read_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
398b29c2f0cSNishanth Menon &state);
399ed407be5SPali Rohár
400ed407be5SPali Rohár /* enable I2C access to powerbus (needed for twl4030 regulator) */
4010208aaf6SNishanth Menon twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
4020208aaf6SNishanth Menon 0x02);
403ed407be5SPali Rohár
404ed407be5SPali Rohár /* set VAUX3, VSIM and VMMC1 state to active - enable eMMC memory */
405ed407be5SPali Rohár twl4030_regulator_set_mode(RES_VAUX3, RES_STATE_ACTIVE);
406ed407be5SPali Rohár twl4030_regulator_set_mode(RES_VSIM, RES_STATE_ACTIVE);
407ed407be5SPali Rohár twl4030_regulator_set_mode(RES_VMMC1, RES_STATE_ACTIVE);
408ed407be5SPali Rohár
409ed407be5SPali Rohár /* restore I2C access state */
4100208aaf6SNishanth Menon twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, TWL4030_PM_MASTER_PB_CFG,
4110208aaf6SNishanth Menon state);
412ed407be5SPali Rohár
413ed407be5SPali Rohár /* set env variable attkernaddr for relocated kernel */
414ed407be5SPali Rohár sprintf(buf, "%#x", KERNEL_ADDRESS);
415382bee57SSimon Glass env_set("attkernaddr", buf);
416ed407be5SPali Rohár
417ed407be5SPali Rohár /* initialize omap tags */
418ed407be5SPali Rohár init_omap_tags();
419ed407be5SPali Rohár
420ed407be5SPali Rohár /* reuse atags from previous bootloader */
421ed407be5SPali Rohár reuse_atags();
422ed407be5SPali Rohár
423679f82c3SPaul Kocialkowski omap_die_id_display();
424ed407be5SPali Rohár print_cpuinfo();
425ed407be5SPali Rohár
426ed407be5SPali Rohár /*
427ed407be5SPali Rohár * Cortex-A8(r1p0..r1p2) errata 430973 workaround
428ed407be5SPali Rohár * Set IBE bit in Auxiliary Control Register
4298cda413bSPali Rohár *
4308cda413bSPali Rohár * Call this routine only on real secure device
4318cda413bSPali Rohár * Qemu does not implement secure PPA and crash
432ed407be5SPali Rohár */
4338cda413bSPali Rohár if (get_device_type() == HS_DEVICE)
434ed407be5SPali Rohár omap3_update_aux_cr_secure_rx51(1 << 6, 0);
435ed407be5SPali Rohár
436ed407be5SPali Rohár return 0;
437ed407be5SPali Rohár }
438ed407be5SPali Rohár
439ed407be5SPali Rohár /*
440ed407be5SPali Rohár * Routine: set_muxconf_regs
441ed407be5SPali Rohár * Description: Setting up the configuration Mux registers specific to the
442ed407be5SPali Rohár * hardware. Many pins need to be moved from protect to primary
443ed407be5SPali Rohár * mode.
444ed407be5SPali Rohár */
set_muxconf_regs(void)445ed407be5SPali Rohár void set_muxconf_regs(void)
446ed407be5SPali Rohár {
447ed407be5SPali Rohár MUX_RX51();
448ed407be5SPali Rohár }
449ed407be5SPali Rohár
450ed407be5SPali Rohár static unsigned long int twl_wd_time; /* last time of watchdog reset */
451ed407be5SPali Rohár static unsigned long int twl_i2c_lock;
452ed407be5SPali Rohár
453ed407be5SPali Rohár /*
454ed407be5SPali Rohár * Routine: hw_watchdog_reset
455ed407be5SPali Rohár * Description: Reset timeout of twl4030 watchdog.
456ed407be5SPali Rohár */
hw_watchdog_reset(void)457ed407be5SPali Rohár void hw_watchdog_reset(void)
458ed407be5SPali Rohár {
459ed407be5SPali Rohár u8 timeout = 0;
460ed407be5SPali Rohár
461ed407be5SPali Rohár /* do not reset watchdog too often - max every 4s */
462ed407be5SPali Rohár if (get_timer(twl_wd_time) < 4 * CONFIG_SYS_HZ)
463ed407be5SPali Rohár return;
464ed407be5SPali Rohár
465ed407be5SPali Rohár /* localy lock twl4030 i2c bus */
466ed407be5SPali Rohár if (test_and_set_bit(0, &twl_i2c_lock))
467ed407be5SPali Rohár return;
468ed407be5SPali Rohár
469ed407be5SPali Rohár /* read actual watchdog timeout */
470b29c2f0cSNishanth Menon twl4030_i2c_read_u8(TWL4030_CHIP_PM_RECEIVER,
471b29c2f0cSNishanth Menon TWL4030_PM_RECEIVER_WATCHDOG_CFG, &timeout);
472ed407be5SPali Rohár
473ed407be5SPali Rohár /* timeout 0 means watchdog is disabled */
474ed407be5SPali Rohár /* reset watchdog timeout to 31s (maximum) */
475ed407be5SPali Rohár if (timeout != 0)
4760208aaf6SNishanth Menon twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER,
4770208aaf6SNishanth Menon TWL4030_PM_RECEIVER_WATCHDOG_CFG, 31);
478ed407be5SPali Rohár
479ed407be5SPali Rohár /* store last watchdog reset time */
480ed407be5SPali Rohár twl_wd_time = get_timer(0);
481ed407be5SPali Rohár
482ed407be5SPali Rohár /* localy unlock twl4030 i2c bus */
483ed407be5SPali Rohár test_and_clear_bit(0, &twl_i2c_lock);
484ed407be5SPali Rohár }
485ed407be5SPali Rohár
486ed407be5SPali Rohár /*
487ed407be5SPali Rohár * TWL4030 keypad handler for cfb_console
488ed407be5SPali Rohár */
489ed407be5SPali Rohár
490ed407be5SPali Rohár static const char keymap[] = {
491ed407be5SPali Rohár /* normal */
492ed407be5SPali Rohár 'q', 'o', 'p', ',', '\b', 0, 'a', 's',
493ed407be5SPali Rohár 'w', 'd', 'f', 'g', 'h', 'j', 'k', 'l',
494ed407be5SPali Rohár 'e', '.', 0, '\r', 0, 'z', 'x', 'c',
495ed407be5SPali Rohár 'r', 'v', 'b', 'n', 'm', ' ', ' ', 0,
496ed407be5SPali Rohár 't', 0, 0, 0, 0, 0, 0, 0,
497ed407be5SPali Rohár 'y', 0, 0, 0, 0, 0, 0, 0,
498ed407be5SPali Rohár 'u', 0, 0, 0, 0, 0, 0, 0,
499ed407be5SPali Rohár 'i', 5, 6, 0, 0, 0, 0, 0,
500ed407be5SPali Rohár /* fn */
501ed407be5SPali Rohár '1', '9', '0', '=', '\b', 0, '*', '+',
502ed407be5SPali Rohár '2', '#', '-', '_', '(', ')', '&', '!',
503ed407be5SPali Rohár '3', '?', '^', '\r', 0, 156, '$', 238,
504ed407be5SPali Rohár '4', '/', '\\', '"', '\'', '@', 0, '<',
505ed407be5SPali Rohár '5', '|', '>', 0, 0, 0, 0, 0,
506ed407be5SPali Rohár '6', 0, 0, 0, 0, 0, 0, 0,
507ed407be5SPali Rohár '7', 0, 0, 0, 0, 0, 0, 0,
508ed407be5SPali Rohár '8', 16, 17, 0, 0, 0, 0, 0,
509ed407be5SPali Rohár };
510ed407be5SPali Rohár
511ed407be5SPali Rohár static u8 keys[8];
512ed407be5SPali Rohár static u8 old_keys[8] = {0, 0, 0, 0, 0, 0, 0, 0};
513ed407be5SPali Rohár #define KEYBUF_SIZE 32
514ed407be5SPali Rohár static u8 keybuf[KEYBUF_SIZE];
515ed407be5SPali Rohár static u8 keybuf_head;
516ed407be5SPali Rohár static u8 keybuf_tail;
517ed407be5SPali Rohár
518ed407be5SPali Rohár /*
519ed407be5SPali Rohár * Routine: rx51_kp_init
520ed407be5SPali Rohár * Description: Initialize HW keyboard.
521ed407be5SPali Rohár */
rx51_kp_init(void)522ed407be5SPali Rohár int rx51_kp_init(void)
523ed407be5SPali Rohár {
524ed407be5SPali Rohár int ret = 0;
525ed407be5SPali Rohár u8 ctrl;
526b29c2f0cSNishanth Menon ret = twl4030_i2c_read_u8(TWL4030_CHIP_KEYPAD,
527b29c2f0cSNishanth Menon TWL4030_KEYPAD_KEYP_CTRL_REG, &ctrl);
528ed407be5SPali Rohár
529ed407be5SPali Rohár if (ret)
530ed407be5SPali Rohár return ret;
531ed407be5SPali Rohár
532ed407be5SPali Rohár /* turn on keyboard and use hardware scanning */
533ed407be5SPali Rohár ctrl |= TWL4030_KEYPAD_CTRL_KBD_ON;
534ed407be5SPali Rohár ctrl |= TWL4030_KEYPAD_CTRL_SOFT_NRST;
535ed407be5SPali Rohár ctrl |= TWL4030_KEYPAD_CTRL_SOFTMODEN;
5360208aaf6SNishanth Menon ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
5370208aaf6SNishanth Menon TWL4030_KEYPAD_KEYP_CTRL_REG, ctrl);
538ed407be5SPali Rohár /* enable key event status */
5390208aaf6SNishanth Menon ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
5400208aaf6SNishanth Menon TWL4030_KEYPAD_KEYP_IMR1, 0xfe);
541ed407be5SPali Rohár /* enable interrupt generation on rising and falling */
542ed407be5SPali Rohár /* this is a workaround for qemu twl4030 emulation */
5430208aaf6SNishanth Menon ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
5440208aaf6SNishanth Menon TWL4030_KEYPAD_KEYP_EDR, 0x57);
545ed407be5SPali Rohár /* enable ISR clear on read */
5460208aaf6SNishanth Menon ret |= twl4030_i2c_write_u8(TWL4030_CHIP_KEYPAD,
5470208aaf6SNishanth Menon TWL4030_KEYPAD_KEYP_SIH_CTRL, 0x05);
548ed407be5SPali Rohár return 0;
549ed407be5SPali Rohár }
550ed407be5SPali Rohár
rx51_kp_fill(u8 k,u8 mods)551ed407be5SPali Rohár static void rx51_kp_fill(u8 k, u8 mods)
552ed407be5SPali Rohár {
553ed407be5SPali Rohár /* check if some cursor key without meta fn key was pressed */
554ed407be5SPali Rohár if (!(mods & 2) && (k == 18 || k == 31 || k == 33 || k == 34)) {
555ed407be5SPali Rohár keybuf[keybuf_tail++] = '\e';
556ed407be5SPali Rohár keybuf_tail %= KEYBUF_SIZE;
557ed407be5SPali Rohár keybuf[keybuf_tail++] = '[';
558ed407be5SPali Rohár keybuf_tail %= KEYBUF_SIZE;
559ed407be5SPali Rohár if (k == 18) /* up */
560ed407be5SPali Rohár keybuf[keybuf_tail++] = 'A';
561ed407be5SPali Rohár else if (k == 31) /* left */
562ed407be5SPali Rohár keybuf[keybuf_tail++] = 'D';
563ed407be5SPali Rohár else if (k == 33) /* down */
564ed407be5SPali Rohár keybuf[keybuf_tail++] = 'B';
565ed407be5SPali Rohár else if (k == 34) /* right */
566ed407be5SPali Rohár keybuf[keybuf_tail++] = 'C';
567ed407be5SPali Rohár keybuf_tail %= KEYBUF_SIZE;
568ed407be5SPali Rohár return;
569ed407be5SPali Rohár }
570ed407be5SPali Rohár
571ed407be5SPali Rohár if (mods & 2) { /* fn meta key was pressed */
572ed407be5SPali Rohár k = keymap[k+64];
573ed407be5SPali Rohár } else {
574ed407be5SPali Rohár k = keymap[k];
575ed407be5SPali Rohár if (mods & 1) { /* ctrl key was pressed */
576ed407be5SPali Rohár if (k >= 'a' && k <= 'z')
577ed407be5SPali Rohár k -= 'a' - 1;
578ed407be5SPali Rohár }
579ed407be5SPali Rohár if (mods & 4) { /* shift key was pressed */
580ed407be5SPali Rohár if (k >= 'a' && k <= 'z')
581ed407be5SPali Rohár k += 'A' - 'a';
582ed407be5SPali Rohár else if (k == '.')
583ed407be5SPali Rohár k = ':';
584ed407be5SPali Rohár else if (k == ',')
585ed407be5SPali Rohár k = ';';
586ed407be5SPali Rohár }
587ed407be5SPali Rohár }
588ed407be5SPali Rohár keybuf[keybuf_tail++] = k;
589ed407be5SPali Rohár keybuf_tail %= KEYBUF_SIZE;
590ed407be5SPali Rohár }
591ed407be5SPali Rohár
592ed407be5SPali Rohár /*
593ed407be5SPali Rohár * Routine: rx51_kp_tstc
594ed407be5SPali Rohár * Description: Test if key was pressed (from buffer).
595ed407be5SPali Rohár */
rx51_kp_tstc(struct stdio_dev * sdev)596709ea543SSimon Glass int rx51_kp_tstc(struct stdio_dev *sdev)
597ed407be5SPali Rohár {
598ed407be5SPali Rohár u8 c, r, dk, i;
599ed407be5SPali Rohár u8 intr;
600ed407be5SPali Rohár u8 mods;
601ed407be5SPali Rohár
602ed407be5SPali Rohár /* localy lock twl4030 i2c bus */
603ed407be5SPali Rohár if (test_and_set_bit(0, &twl_i2c_lock))
604ed407be5SPali Rohár return 0;
605ed407be5SPali Rohár
606ed407be5SPali Rohár /* twl4030 remembers up to 2 events */
607ed407be5SPali Rohár for (i = 0; i < 2; i++) {
608ed407be5SPali Rohár
609ed407be5SPali Rohár /* check interrupt register for events */
610b29c2f0cSNishanth Menon twl4030_i2c_read_u8(TWL4030_CHIP_KEYPAD,
611b29c2f0cSNishanth Menon TWL4030_KEYPAD_KEYP_ISR1 + (2 * i), &intr);
612ed407be5SPali Rohár
613ed407be5SPali Rohár /* no event */
614ed407be5SPali Rohár if (!(intr&1))
615ed407be5SPali Rohár continue;
616ed407be5SPali Rohár
617ed407be5SPali Rohár /* read the key state */
618ed407be5SPali Rohár i2c_read(TWL4030_CHIP_KEYPAD,
619ed407be5SPali Rohár TWL4030_KEYPAD_FULL_CODE_7_0, 1, keys, 8);
620ed407be5SPali Rohár
621ed407be5SPali Rohár /* cut out modifier keys from the keystate */
622ed407be5SPali Rohár mods = keys[4] >> 4;
623ed407be5SPali Rohár keys[4] &= 0x0f;
624ed407be5SPali Rohár
625ed407be5SPali Rohár for (c = 0; c < 8; c++) {
626ed407be5SPali Rohár
627ed407be5SPali Rohár /* get newly pressed keys only */
628ed407be5SPali Rohár dk = ((keys[c] ^ old_keys[c])&keys[c]);
629ed407be5SPali Rohár old_keys[c] = keys[c];
630ed407be5SPali Rohár
631ed407be5SPali Rohár /* fill the keybuf */
632ed407be5SPali Rohár for (r = 0; r < 8; r++) {
633ed407be5SPali Rohár if (dk&1)
634ed407be5SPali Rohár rx51_kp_fill((c*8)+r, mods);
635ed407be5SPali Rohár dk = dk >> 1;
636ed407be5SPali Rohár }
637ed407be5SPali Rohár
638ed407be5SPali Rohár }
639ed407be5SPali Rohár
640ed407be5SPali Rohár }
641ed407be5SPali Rohár
642ed407be5SPali Rohár /* localy unlock twl4030 i2c bus */
643ed407be5SPali Rohár test_and_clear_bit(0, &twl_i2c_lock);
644ed407be5SPali Rohár
645ed407be5SPali Rohár return (KEYBUF_SIZE + keybuf_tail - keybuf_head)%KEYBUF_SIZE;
646ed407be5SPali Rohár }
647ed407be5SPali Rohár
648ed407be5SPali Rohár /*
649ed407be5SPali Rohár * Routine: rx51_kp_getc
650ed407be5SPali Rohár * Description: Get last pressed key (from buffer).
651ed407be5SPali Rohár */
rx51_kp_getc(struct stdio_dev * sdev)652709ea543SSimon Glass int rx51_kp_getc(struct stdio_dev *sdev)
653ed407be5SPali Rohár {
654ed407be5SPali Rohár keybuf_head %= KEYBUF_SIZE;
655709ea543SSimon Glass while (!rx51_kp_tstc(sdev))
656ed407be5SPali Rohár WATCHDOG_RESET();
657ed407be5SPali Rohár return keybuf[keybuf_head++];
658ed407be5SPali Rohár }
659ed407be5SPali Rohár
660ed407be5SPali Rohár /*
661ed407be5SPali Rohár * Routine: board_mmc_init
662ed407be5SPali Rohár * Description: Initialize mmc devices.
663ed407be5SPali Rohár */
board_mmc_init(bd_t * bis)664ed407be5SPali Rohár int board_mmc_init(bd_t *bis)
665ed407be5SPali Rohár {
666e3913f56SNikita Kiryanov omap_mmc_init(0, 0, 0, -1, -1);
667e3913f56SNikita Kiryanov omap_mmc_init(1, 0, 0, -1, -1);
668ed407be5SPali Rohár return 0;
669ed407be5SPali Rohár }
670aac5450eSPaul Kocialkowski
board_mmc_power_init(void)671aac5450eSPaul Kocialkowski void board_mmc_power_init(void)
672aac5450eSPaul Kocialkowski {
673aac5450eSPaul Kocialkowski twl4030_power_mmc_init(0);
674aac5450eSPaul Kocialkowski twl4030_power_mmc_init(1);
675aac5450eSPaul Kocialkowski }
676