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