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