summaryrefslogtreecommitdiffstats
path: root/arch/arm/boards/phytec-som-am335x/lowlevel.c
blob: 267f30b638cc52545660ae1a0f9e0c1f9fcb177f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
// SPDX-License-Identifier: GPL-2.0-or-later
// SPDX-FileCopyrightText: 2015 Wadim Egorov, PHYTEC Messtechnik GmbH

#include <common.h>
#include <linux/sizes.h>
#include <io.h>
#include <init.h>
#include <asm/barebox-arm-head.h>
#include <asm/barebox-arm.h>
#include <mach/omap/am33xx-silicon.h>
#include <mach/omap/am33xx-clock.h>
#include <mach/omap/generic.h>
#include <mach/omap/sdrc.h>
#include <mach/omap/sys_info.h>
#include <mach/omap/syslib.h>
#include <mach/omap/am33xx-mux.h>
#include <mach/omap/am33xx-generic.h>
#include <debug_ll.h>
#include <mach/omap/debug_ll.h>

#include "ram-timings.h"

#define DDR_IOCTRL	0x18B

static const struct am33xx_cmd_control physom_cmd = {
	.slave_ratio0	= 0x80,
	.dll_lock_diff0	= 0x0,
	.invert_clkout0	= 0x0,
	.slave_ratio1	= 0x80,
	.dll_lock_diff1	= 0x0,
	.invert_clkout1	= 0x0,
	.slave_ratio2	= 0x80,
	.dll_lock_diff2	= 0x0,
	.invert_clkout2	= 0x0,
};

/* Module family for the unified MLO
 *
 * NONE:        Unified MLO is not supported
 * PHYCORE_R2:  Unified MLO for PCM-060, PCM-062
 */
enum {
	NONE,
	PHYCORE_R2,
};

/* @brief Supplies default ram timings for all ram sizes
 *
 * Returns generic ram timings for module families to find the correct
 * ram size.
 *
 * @return struct am335x_sdram_timings* or NULL
 */

static noinline struct am335x_sdram_timings* get_minimal_timings(
							int module_family)
{
	struct am335x_sdram_timings *timing;

	switch (module_family) {
	case PHYCORE_R2:
		timing = &physom_timings[PHYCORE_R2_MT41K512M16HA125IT_1024MB];
		break;
	default:
		timing = NULL;
	}

	return timing;
}

/* @brief Converts ramsizes to ram timings for phyCORE-R2 modules
 *
 * Returns ram timings for a given ram size or NULL, if this size is
 * not supported.
 *
 * @return struct am335x_sdram_timings* or NULL
 */

static noinline struct am335x_sdram_timings* convert_phycore_r2_timings(
								u32 ramsize)
{
	struct am335x_sdram_timings *timing;

	switch (ramsize) {
	case SZ_256M:
		timing = &physom_timings[PHYCORE_R2_MT41K128M16JT_256MB];
		break;
	case SZ_512M:
		timing = &physom_timings[PHYCORE_R2_MT41K256M16TW107IT_512MB];
		break;
	case SZ_1G:
		timing = &physom_timings[PHYCORE_R2_MT41K512M16HA125IT_1024MB];
		break;
	default:
		timing = NULL;
	}

	return timing;
}

/* @brief Converts a module family and ram size to ram timings
 *
 * Returns ram timings for a given ram size and module family or NULL,
 * if the ram size or module family is not supported.
 *
 * @return struct am335x_sdram_timings* or NULL
 */

static noinline struct am335x_sdram_timings* get_timings_by_size(
						int module_family, u32 ramsize)
{
	struct am335x_sdram_timings *timing;

	switch (module_family) {
	case PHYCORE_R2:
		timing = convert_phycore_r2_timings(ramsize);
		break;
	default:
		timing = NULL;
	}

	return timing;
}

/**
 * @brief The basic entry point for board initialization.
 *
 * This is called as part of machine init (after arch init).
 * This is again called with stack in SRAM, so not too many
 * constructs possible here.
 *
 * @return void
 */
static noinline void physom_board_init(void *fdt, int sdram, int module_family)
{
	struct am335x_sdram_timings *timing = NULL;
	u32 ramsize;

	omap_watchdog_disable(IOMEM(AM33XX_WDT_BASE));

	am33xx_pll_init(MPUPLL_M_600, DDRPLL_M_400);

	if (module_family == NONE) {
		timing = &physom_timings[sdram];
	} else {
		/* Load generic DDR3 ram timings to find the ram size */
		timing = get_minimal_timings(module_family);
		if (!timing)
			hang();
		am335x_sdram_init(DDR_IOCTRL, &physom_cmd,
				&timing->regs,
				&timing->data);

		/* Find the ram size and set up the correct ram timings */
		ramsize = get_ram_size((long *) 0x80000000, SZ_1G);
		timing = get_timings_by_size(module_family, ramsize);
		if (!timing)
			hang();
	}

	am335x_sdram_init(DDR_IOCTRL, &physom_cmd,
			&timing->regs,
			&timing->data);

	am33xx_uart_soft_reset((void *)AM33XX_UART0_BASE);
	am33xx_enable_uart0_pin_mux();
	omap_debug_ll_init();
	putc_ll('>');

	am335x_barebox_entry(fdt);
}

static noinline void physom_board_entry(unsigned long bootinfo, int sdram,
					void *fdt, int module_family)
{
	am33xx_save_bootinfo((void *)bootinfo);

	arm_cpu_lowlevel_init();

	/*
	 * Setup C environment, the board init code uses global variables.
	 * Stackpointer has already been initialized by the ROM code.
	 */
	relocate_to_current_adr();
	setup_c();
	physom_board_init(fdt, sdram, module_family);
}

#define PHYTEC_ENTRY_UNIFIED_MLO(name, fdt_name, module_family)		\
	ENTRY_FUNCTION(name, bootinfo, r1, r2)				\
	{								\
		extern char __dtb_z_##fdt_name##_start[];		\
		void *fdt = __dtb_z_##fdt_name##_start +		\
			get_runtime_offset();				\
		physom_board_entry(bootinfo, 0, fdt, module_family);	\
	}

#define PHYTEC_ENTRY_MLO(name, fdt_name, sdram)				\
	ENTRY_FUNCTION(name, bootinfo, r1, r2)				\
	{								\
		extern char __dtb_z_##fdt_name##_start[];		\
		void *fdt = __dtb_z_##fdt_name##_start +		\
			get_runtime_offset();				\
		physom_board_entry(bootinfo, sdram, fdt, NONE);		\
	}

#define PHYTEC_ENTRY(name, fdt_name)					\
	ENTRY_FUNCTION(name, r0, r1, r2)				\
	{								\
		extern char __dtb_z_##fdt_name##_start[];		\
		void *fdt = __dtb_z_##fdt_name##_start +		\
			get_runtime_offset();				\
		am335x_barebox_entry(fdt);				\
	}

/* phycore-som */
PHYTEC_ENTRY_MLO(start_am33xx_phytec_phycore_sram_128mb, am335x_phytec_phycore_som_mlo, PHYCORE_MT41J64M1615IT_128MB);
PHYTEC_ENTRY_MLO(start_am33xx_phytec_phycore_sram_256mb, am335x_phytec_phycore_som_mlo, PHYCORE_MT41J128M16125IT_256MB);
PHYTEC_ENTRY_MLO(start_am33xx_phytec_phycore_sram_512mb, am335x_phytec_phycore_som_mlo, PHYCORE_MT41J256M16HA15EIT_512MB);
PHYTEC_ENTRY_MLO(start_am33xx_phytec_phycore_sram_2x512mb, am335x_phytec_phycore_som_mlo, PHYCORE_MT41J512M8125IT_2x512MB);
PHYTEC_ENTRY_MLO(start_am33xx_phytec_phycore_r2_sram_1024mb, am335x_phytec_phycore_som_mlo, PHYCORE_R2_MT41K512M16HA125IT_1024MB);
PHYTEC_ENTRY_UNIFIED_MLO(start_am33xx_phytec_phycore_r2_sram, am335x_phytec_phycore_som_mlo, PHYCORE_R2);
PHYTEC_ENTRY(start_am33xx_phytec_phycore_nand_sdram, am335x_phytec_phycore_som_nand);
PHYTEC_ENTRY(start_am33xx_phytec_phycore_emmc_sdram, am335x_phytec_phycore_som_emmc);
PHYTEC_ENTRY(start_am33xx_phytec_phycore_nand_no_spi_sdram, am335x_phytec_phycore_som_nand_no_spi);
PHYTEC_ENTRY(start_am33xx_phytec_phycore_nand_no_eeprom_sdram, am335x_phytec_phycore_som_nand_no_eeprom);
PHYTEC_ENTRY(start_am33xx_phytec_phycore_nand_no_spi_no_eeprom_sdram, am335x_phytec_phycore_som_nand_no_spi_no_eeprom);

/* phyflex-som */
PHYTEC_ENTRY_MLO(start_am33xx_phytec_phyflex_sram_256mb, am335x_phytec_phyflex_som_mlo, PHYFLEX_MT41K128M16JT_256MB);
PHYTEC_ENTRY_MLO(start_am33xx_phytec_phyflex_sram_512mb, am335x_phytec_phyflex_som_mlo, PHYFLEX_MT41K256M16HA_512MB);
PHYTEC_ENTRY(start_am33xx_phytec_phyflex_sdram, am335x_phytec_phyflex_som);
PHYTEC_ENTRY(start_am33xx_phytec_phyflex_no_spi_sdram, am335x_phytec_phyflex_som_no_spi);
PHYTEC_ENTRY(start_am33xx_phytec_phyflex_no_eeprom_sdram, am335x_phytec_phyflex_som_no_eeprom);
PHYTEC_ENTRY(start_am33xx_phytec_phyflex_no_spi_no_eeprom_sdram, am335x_phytec_phyflex_som_no_spi_no_eeprom);

/* phycard-som */
PHYTEC_ENTRY_MLO(start_am33xx_phytec_phycard_sram_256mb, am335x_phytec_phycard_som_mlo, PHYCARD_NT5CB128M16BP_256MB);
PHYTEC_ENTRY(start_am33xx_phytec_phycard_sdram, am335x_phytec_phycard_som);