summaryrefslogtreecommitdiff
path: root/arch/arm/mach-socfpga/misc_arria10.c
blob: a75cbc4ce6c59ac0a891d5a2fb9384a0250dd4f7 (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
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2016-2017 Intel Corporation
 */

#include <altera.h>
#include <common.h>
#include <errno.h>
#include <fdtdec.h>
#include <miiphy.h>
#include <netdev.h>
#include <ns16550.h>
#include <watchdog.h>
#include <asm/arch/misc.h>
#include <asm/arch/pinmux.h>
#include <asm/arch/reset_manager.h>
#include <asm/arch/reset_manager_arria10.h>
#include <asm/arch/sdram_arria10.h>
#include <asm/arch/system_manager.h>
#include <asm/arch/nic301.h>
#include <asm/io.h>
#include <asm/pl310.h>

#define PINMUX_UART0_TX_SHARED_IO_OFFSET_Q1_3	0x08
#define PINMUX_UART0_TX_SHARED_IO_OFFSET_Q2_11	0x58
#define PINMUX_UART0_TX_SHARED_IO_OFFSET_Q3_3	0x68
#define PINMUX_UART1_TX_SHARED_IO_OFFSET_Q1_7	0x18
#define PINMUX_UART1_TX_SHARED_IO_OFFSET_Q3_7	0x78
#define PINMUX_UART1_TX_SHARED_IO_OFFSET_Q4_3	0x98

#if defined(CONFIG_SPL_BUILD)
static struct pl310_regs *const pl310 =
	(struct pl310_regs *)CONFIG_SYS_PL310_BASE;
static const struct socfpga_noc_fw_ocram *noc_fw_ocram_base =
	(void *)SOCFPGA_SDR_FIREWALL_OCRAM_ADDRESS;
#endif

static struct socfpga_system_manager *sysmgr_regs =
	(struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS;

/*
 * DesignWare Ethernet initialization
 */
#ifdef CONFIG_ETH_DESIGNWARE
static void arria10_dwmac_reset(const u8 of_reset_id, const u8 phymode)
{
	u32 reset;

	if (of_reset_id == EMAC0_RESET) {
		reset = SOCFPGA_RESET(EMAC0);
	} else if (of_reset_id == EMAC1_RESET) {
		reset = SOCFPGA_RESET(EMAC1);
	} else if (of_reset_id == EMAC2_RESET) {
		reset = SOCFPGA_RESET(EMAC2);
	} else {
		printf("GMAC: Invalid reset ID (%i)!\n", of_reset_id);
		return;
	}

	clrsetbits_le32(&sysmgr_regs->emac[of_reset_id - EMAC0_RESET],
			SYSMGR_EMACGRP_CTRL_PHYSEL_MASK,
			phymode);

	/* Release the EMAC controller from reset */
	socfpga_per_reset(reset, 0);
}

static int socfpga_eth_reset(void)
{
	/* Put all GMACs into RESET state. */
	socfpga_per_reset(SOCFPGA_RESET(EMAC0), 1);
	socfpga_per_reset(SOCFPGA_RESET(EMAC1), 1);
	socfpga_per_reset(SOCFPGA_RESET(EMAC2), 1);
	return socfpga_eth_reset_common(arria10_dwmac_reset);
};
#else
static int socfpga_eth_reset(void)
{
	return 0;
};
#endif

#if defined(CONFIG_SPL_BUILD)
/*
+ * This function initializes security policies to be consistent across
+ * all logic units in the Arria 10.
+ *
+ * The idea is to set all security policies to be normal, nonsecure
+ * for all units.
+ */
static void initialize_security_policies(void)
{
	/* Put OCRAM in non-secure */
	writel(0x003f0000, &noc_fw_ocram_base->region0);
	writel(0x1, &noc_fw_ocram_base->enable);
}

int arch_early_init_r(void)
{
	initialize_security_policies();

	/* Configure the L2 controller to make SDRAM start at 0 */
	writel(0x1, &pl310->pl310_addr_filter_start);

	/* assert reset to all except L4WD0 and L4TIMER0 */
	socfpga_per_reset_all();

	return 0;
}
#else
int arch_early_init_r(void)
{
	return 0;
}
#endif

/*
 * This function looking the 1st encounter UART peripheral,
 * and then return its offset of the dedicated/shared IO pin
 * mux. offset value (zero and above).
 */
static int find_peripheral_uart(const void *blob,
	int child, const char *node_name)
{
	int len;
	fdt_addr_t base_addr = 0;
	fdt_size_t size;
	const u32 *cell;
	u32 value, offset = 0;

	base_addr = fdtdec_get_addr_size(blob, child, "reg", &size);
	if (base_addr != FDT_ADDR_T_NONE) {
		cell = fdt_getprop(blob, child, "pinctrl-single,pins",
			&len);
		if (cell != NULL) {
			for (; len > 0; len -= (2 * sizeof(u32))) {
				offset = fdt32_to_cpu(*cell++);
				value = fdt32_to_cpu(*cell++);
				/* Found UART peripheral. */
				if (value == PINMUX_UART)
					return offset;
			}
		}
	}
	return -EINVAL;
}

/*
 * This function looks up the 1st encounter UART peripheral,
 * and then return its offset of the dedicated/shared IO pin
 * mux. UART peripheral is found if the offset is not in negative
 * value.
 */
static int is_peripheral_uart_true(const void *blob,
	int node, const char *child_name)
{
	int child, len;
	const char *node_name;

	child = fdt_first_subnode(blob, node);

	if (child < 0)
		return -EINVAL;

	node_name = fdt_get_name(blob, child, &len);

	while (node_name) {
		if (!strcmp(child_name, node_name))
			return find_peripheral_uart(blob, child, node_name);

		child = fdt_next_subnode(blob, child);
		if (child < 0)
			break;

		node_name = fdt_get_name(blob, child, &len);
	}

	return -1;
}

/*
 * This function looking the 1st encounter UART dedicated IO peripheral,
 * and then return based address of the 1st encounter UART dedicated
 * IO peripheral.
 */
unsigned int dedicated_uart_com_port(const void *blob)
{
	int node;

	node = fdtdec_next_compatible(blob, 0,
		 COMPAT_ALTERA_SOCFPGA_PINCTRL_SINGLE);
	if (node < 0)
		return 0;

	if (is_peripheral_uart_true(blob, node, "dedicated") >= 0)
		return SOCFPGA_UART1_ADDRESS;

	return 0;
}

/*
 * This function looking the 1st encounter UART shared IO peripheral, and then
 * return based address of the 1st encounter UART shared IO peripheral.
 */
unsigned int shared_uart_com_port(const void *blob)
{
	int node, ret;

	node = fdtdec_next_compatible(blob, 0,
		 COMPAT_ALTERA_SOCFPGA_PINCTRL_SINGLE);
	if (node < 0)
		return 0;

	ret = is_peripheral_uart_true(blob, node, "shared");

	if (ret == PINMUX_UART0_TX_SHARED_IO_OFFSET_Q1_3 ||
	    ret == PINMUX_UART0_TX_SHARED_IO_OFFSET_Q2_11 ||
	    ret == PINMUX_UART0_TX_SHARED_IO_OFFSET_Q3_3)
		return SOCFPGA_UART0_ADDRESS;
	else if (ret == PINMUX_UART1_TX_SHARED_IO_OFFSET_Q1_7 ||
		ret == PINMUX_UART1_TX_SHARED_IO_OFFSET_Q3_7 ||
		ret == PINMUX_UART1_TX_SHARED_IO_OFFSET_Q4_3)
		return SOCFPGA_UART1_ADDRESS;

	return 0;
}

/*
 * This function looking the 1st encounter UART peripheral, and then return
 * base address of the 1st encounter UART peripheral.
 */
unsigned int uart_com_port(const void *blob)
{
	unsigned int ret;

	ret = dedicated_uart_com_port(blob);

	if (ret)
		return ret;

	return shared_uart_com_port(blob);
}

/*
 * Print CPU information
 */
#if defined(CONFIG_DISPLAY_CPUINFO)
int print_cpuinfo(void)
{
	const u32 bsel =
		SYSMGR_GET_BOOTINFO_BSEL(readl(&sysmgr_regs->bootinfo));

	puts("CPU:   Altera SoCFPGA Arria 10\n");

	printf("BOOT:  %s\n", bsel_str[bsel].name);
	return 0;
}
#endif

#ifdef CONFIG_ARCH_MISC_INIT
int arch_misc_init(void)
{
	return socfpga_eth_reset();
}
#endif

void do_bridge_reset(int enable)
{
	if (enable)
		socfpga_reset_deassert_bridges_handoff();
	else
		socfpga_bridges_reset();
}