summaryrefslogtreecommitdiff
path: root/arch/arm/mach-zynq/cpu.c
blob: 69b818f24b890c00b3cf6f800d3e08b71425ec19 (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
// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
 * Copyright (C) 2012 Xilinx, Inc. All rights reserved.
 */
#include <common.h>
#include <cpu_func.h>
#include <init.h>
#include <zynqpl.h>
#include <asm/cache.h>
#include <asm/io.h>
#include <asm/arch/clk.h>
#include <asm/arch/hardware.h>
#include <asm/arch/ps7_init_gpl.h>
#include <asm/arch/sys_proto.h>

#define ZYNQ_SILICON_VER_MASK	0xF0000000
#define ZYNQ_SILICON_VER_SHIFT	28

#if CONFIG_IS_ENABLED(FPGA)
xilinx_desc fpga = {
	.family = xilinx_zynq,
	.iface = devcfg,
	.operations = &zynq_op,
};
#endif

static const struct {
	u8 idcode;
#if defined(CONFIG_FPGA)
	u32 fpga_size;
#endif
	char *devicename;
} zynq_fpga_descs[] = {
	ZYNQ_DESC(7Z007S),
	ZYNQ_DESC(7Z010),
	ZYNQ_DESC(7Z012S),
	ZYNQ_DESC(7Z014S),
	ZYNQ_DESC(7Z015),
	ZYNQ_DESC(7Z020),
	ZYNQ_DESC(7Z030),
	ZYNQ_DESC(7Z035),
	ZYNQ_DESC(7Z045),
	ZYNQ_DESC(7Z100),
	{ /* Sentinel */ },
};

int arch_cpu_init(void)
{
	zynq_slcr_unlock();
#ifndef CONFIG_SPL_BUILD
	/* Device config APB, unlock the PCAP */
	writel(0x757BDF0D, &devcfg_base->unlock);
	writel(0xFFFFFFFF, &devcfg_base->rom_shadow);

#if (CONFIG_SYS_SDRAM_BASE == 0)
	/* remap DDR to zero, FILTERSTART */
	writel(0, &scu_base->filter_start);

	/* OCM_CFG, Mask out the ROM, map ram into upper addresses */
	writel(0x1F, &slcr_base->ocm_cfg);
	/* FPGA_RST_CTRL, clear resets on AXI fabric ports */
	writel(0x0, &slcr_base->fpga_rst_ctrl);
	/* Set urgent bits with register */
	writel(0x0, &slcr_base->ddr_urgent_sel);
	/* Urgent write, ports S2/S3 */
	writel(0xC, &slcr_base->ddr_urgent);
#endif
#endif
	zynq_slcr_lock();

	return 0;
}

unsigned int zynq_get_silicon_version(void)
{
	return (readl(&devcfg_base->mctrl) & ZYNQ_SILICON_VER_MASK)
						>> ZYNQ_SILICON_VER_SHIFT;
}

void reset_cpu(void)
{
	zynq_slcr_cpu_reset();
	while (1)
		;
}

#if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
void enable_caches(void)
{
	/* Enable D-cache. I-cache is already enabled in start.S */
	dcache_enable();
}
#endif

static int __maybe_unused cpu_desc_id(void)
{
	u32 idcode;
	u8 i;

	idcode = zynq_slcr_get_idcode();
	for (i = 0; zynq_fpga_descs[i].idcode; i++) {
		if (zynq_fpga_descs[i].idcode == idcode)
			return i;
	}

	return -ENODEV;
}

#if defined(CONFIG_ARCH_EARLY_INIT_R)
int arch_early_init_r(void)
{
#if CONFIG_IS_ENABLED(FPGA)
	int cpu_id = cpu_desc_id();

	if (cpu_id < 0)
		return 0;

	fpga.size = zynq_fpga_descs[cpu_id].fpga_size;
	fpga.name = zynq_fpga_descs[cpu_id].devicename;
	fpga_init();
	fpga_add(fpga_xilinx, &fpga);
#endif
	return 0;
}
#endif

#ifdef CONFIG_DISPLAY_CPUINFO
int print_cpuinfo(void)
{
	u32 version;
	int cpu_id = cpu_desc_id();

	if (cpu_id < 0)
		return 0;

	version = zynq_get_silicon_version() << 1;
	if (version > (PCW_SILICON_VERSION_3 << 1))
		version += 1;

	printf("CPU:   Zynq %s\n", zynq_fpga_descs[cpu_id].devicename);
	printf("Silicon: v%d.%d\n", version >> 1, version & 1);
	return 0;
}
#endif