summaryrefslogtreecommitdiff
path: root/arch/mips/mach-pic32/cpu.c
blob: f2ee911df4d183059eec5d6103c07870370a3b39 (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
/*
 * Copyright (C) 2015
 * Purna Chandra Mandal <purna.mandal@microchip.com>
 *
 * SPDX-License-Identifier:	GPL-2.0+
 *
 */
#include <common.h>
#include <clk.h>
#include <dm.h>
#include <mach/pic32.h>
#include <mach/ddr.h>
#include <dt-bindings/clock/microchip,clock.h>

/* Flash prefetch */
#define PRECON          0x00

/* Flash ECCCON */
#define ECC_MASK	0x03
#define ECC_SHIFT	4

#define CLK_MHZ(x)	((x) / 1000000)

DECLARE_GLOBAL_DATA_PTR;

static ulong clk_get_cpu_rate(void)
{
	int ret;
	struct udevice *dev;

	ret = uclass_get_device(UCLASS_CLK, 0, &dev);
	if (ret) {
		panic("uclass-clk: device not found\n");
		return 0;
	}

	return clk_get_rate(dev);
}

/* initialize prefetch module related to cpu_clk */
static void prefetch_init(void)
{
	struct pic32_reg_atomic *regs;
	const void __iomem *base;
	int v, nr_waits;
	ulong rate;

	/* cpu frequency in MHZ */
	rate = clk_get_cpu_rate() / 1000000;

	/* get flash ECC type */
	base = pic32_get_syscfg_base();
	v = (readl(base + CFGCON) >> ECC_SHIFT) & ECC_MASK;

	if (v < 2) {
		if (rate < 66)
			nr_waits = 0;
		else if (rate < 133)
			nr_waits = 1;
		else
			nr_waits = 2;
	} else {
		if (rate <= 83)
			nr_waits = 0;
		else if (rate <= 166)
			nr_waits = 1;
		else
			nr_waits = 2;
	}

	regs = ioremap(PREFETCH_BASE + PRECON, sizeof(*regs));
	writel(nr_waits, &regs->raw);

	/* Enable prefetch for all */
	writel(0x30, &regs->set);
	iounmap(regs);
}

/* arch specific CPU init after DM */
int arch_cpu_init_dm(void)
{
	/* flash prefetch */
	prefetch_init();
	return 0;
}

/* Un-gate DDR2 modules (gated by default) */
static void ddr2_pmd_ungate(void)
{
	void __iomem *regs;

	regs = pic32_get_syscfg_base();
	writel(0, regs + PMD7);
}

/* initialize the DDR2 Controller and DDR2 PHY */
phys_size_t initdram(int board_type)
{
	ddr2_pmd_ungate();
	ddr2_phy_init();
	ddr2_ctrl_init();
	return ddr2_calculate_size();
}

int misc_init_r(void)
{
	set_io_port_base(0);
	return 0;
}

#ifdef CONFIG_DISPLAY_BOARDINFO
const char *get_core_name(void)
{
	u32 proc_id;
	const char *str;

	proc_id = read_c0_prid();
	switch (proc_id) {
	case 0x19e28:
		str = "PIC32MZ[DA]";
		break;
	default:
		str = "UNKNOWN";
	}

	return str;
}
#endif
#ifdef CONFIG_CMD_CLK
int soc_clk_dump(void)
{
	int i, ret;
	struct udevice *dev;

	ret = uclass_get_device(UCLASS_CLK, 0, &dev);
	if (ret) {
		printf("clk-uclass not found\n");
		return ret;
	}

	printf("PLL Speed: %lu MHz\n",
	       CLK_MHZ(clk_get_periph_rate(dev, PLLCLK)));
	printf("CPU Speed: %lu MHz\n", CLK_MHZ(clk_get_rate(dev)));
	printf("MPLL Speed: %lu MHz\n",
	       CLK_MHZ(clk_get_periph_rate(dev, MPLL)));

	for (i = PB1CLK; i <= PB7CLK; i++)
		printf("PB%d Clock Speed: %lu MHz\n", i - PB1CLK + 1,
		       CLK_MHZ(clk_get_periph_rate(dev, i)));

	for (i = REF1CLK; i <= REF5CLK; i++)
		printf("REFO%d Clock Speed: %lu MHz\n", i - REF1CLK + 1,
		       CLK_MHZ(clk_get_periph_rate(dev, i)));
	return 0;
}
#endif