]>
Commit | Line | Data |
---|---|---|
5894ca00 | 1 | /* |
f6e7f07c | 2 | * Copyright (C) 2011-2015 Masahiro Yamada <yamada.masahiro@socionext.com> |
5894ca00 MY |
3 | * |
4 | * SPDX-License-Identifier: GPL-2.0+ | |
5 | */ | |
6 | ||
7 | #include <common.h> | |
323d1f9d | 8 | #include <linux/err.h> |
f6e7f07c | 9 | #include <linux/io.h> |
323d1f9d MY |
10 | #include <linux/sizes.h> |
11 | #include <mach/init.h> | |
a86ac954 MY |
12 | #include <mach/umc-regs.h> |
13 | #include <mach/ddrphy-regs.h> | |
5894ca00 | 14 | |
ee94ee34 | 15 | static void umc_start_ssif(void __iomem *ssif_base) |
5894ca00 MY |
16 | { |
17 | writel(0x00000001, ssif_base + 0x0000b004); | |
18 | writel(0xffffffff, ssif_base + 0x0000c004); | |
19 | writel(0x07ffffff, ssif_base + 0x0000c008); | |
20 | writel(0x00000001, ssif_base + 0x0000b000); | |
21 | writel(0x00000001, ssif_base + 0x0000c000); | |
22 | ||
23 | writel(0x03010100, ssif_base + UMC_HDMCHSEL); | |
24 | writel(0x03010101, ssif_base + UMC_MDMCHSEL); | |
25 | writel(0x03010100, ssif_base + UMC_DVCCHSEL); | |
26 | writel(0x03010100, ssif_base + UMC_DMDCHSEL); | |
27 | ||
28 | writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_FETCH); | |
29 | writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMQUE0); | |
30 | writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMWC0); | |
31 | writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMRC0); | |
32 | writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMQUE1); | |
33 | writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMWC1); | |
34 | writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_COMRC1); | |
35 | writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_WC); | |
36 | writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_RC); | |
37 | writel(0x00000000, ssif_base + UMC_CLKEN_SSIF_DST); | |
38 | writel(0x00000000, ssif_base + 0x0000c044); /* DCGIV_SSIF_REG */ | |
39 | ||
40 | writel(0x00000001, ssif_base + UMC_CPURST); | |
41 | writel(0x00000001, ssif_base + UMC_IDSRST); | |
42 | writel(0x00000001, ssif_base + UMC_IXMRST); | |
43 | writel(0x00000001, ssif_base + UMC_HDMRST); | |
44 | writel(0x00000001, ssif_base + UMC_MDMRST); | |
45 | writel(0x00000001, ssif_base + UMC_HDDRST); | |
46 | writel(0x00000001, ssif_base + UMC_MDDRST); | |
47 | writel(0x00000001, ssif_base + UMC_SIORST); | |
48 | writel(0x00000001, ssif_base + UMC_GIORST); | |
49 | writel(0x00000001, ssif_base + UMC_HD2RST); | |
50 | writel(0x00000001, ssif_base + UMC_VIORST); | |
51 | writel(0x00000001, ssif_base + UMC_DVCRST); | |
52 | writel(0x00000001, ssif_base + UMC_RGLRST); | |
53 | writel(0x00000001, ssif_base + UMC_VPERST); | |
54 | writel(0x00000001, ssif_base + UMC_AIORST); | |
55 | writel(0x00000001, ssif_base + UMC_DMDRST); | |
56 | } | |
57 | ||
ec79c798 MY |
58 | static void umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, |
59 | int size, int freq) | |
5894ca00 MY |
60 | { |
61 | writel(0x66bb0f17, dramcont + UMC_CMDCTLA); | |
62 | writel(0x18c6aa44, dramcont + UMC_CMDCTLB); | |
63 | writel(0x5101387f, dramcont + UMC_INITCTLA); | |
64 | writel(0x43030d3f, dramcont + UMC_INITCTLB); | |
65 | writel(0x00ff00ff, dramcont + UMC_INITCTLC); | |
66 | writel(0x00000d71, dramcont + UMC_DRMMR0); | |
67 | writel(0x00000006, dramcont + UMC_DRMMR1); | |
68 | writel(0x00000298, dramcont + UMC_DRMMR2); | |
69 | writel(0x00000000, dramcont + UMC_DRMMR3); | |
70 | writel(0x003f0617, dramcont + UMC_SPCCTLA); | |
71 | writel(0x00ff0008, dramcont + UMC_SPCCTLB); | |
72 | writel(0x000c00ae, dramcont + UMC_RDATACTL_D0); | |
73 | writel(0x000c00ae, dramcont + UMC_RDATACTL_D1); | |
74 | writel(0x04060802, dramcont + UMC_WDATACTL_D0); | |
75 | writel(0x04060802, dramcont + UMC_WDATACTL_D1); | |
76 | writel(0x04a02000, dramcont + UMC_DATASET); | |
77 | writel(0x00000000, ca_base + 0x2300); | |
78 | writel(0x00400020, dramcont + UMC_DCCGCTL); | |
79 | writel(0x0000000f, dramcont + 0x7000); | |
80 | writel(0x0000000f, dramcont + 0x8000); | |
81 | writel(0x000000c3, dramcont + 0x8004); | |
82 | writel(0x00000071, dramcont + 0x8008); | |
83 | writel(0x00000004, dramcont + UMC_FLOWCTLG); | |
84 | writel(0x00000000, dramcont + 0x0060); | |
85 | writel(0x80000201, ca_base + 0xc20); | |
86 | writel(0x0801e01e, dramcont + UMC_FLOWCTLA); | |
87 | writel(0x00200000, dramcont + UMC_FLOWCTLB); | |
88 | writel(0x00004444, dramcont + UMC_FLOWCTLC); | |
89 | writel(0x200a0a00, dramcont + UMC_SPCSETB); | |
90 | writel(0x00010000, dramcont + UMC_SPCSETD); | |
91 | writel(0x80000020, dramcont + UMC_DFICUPDCTLA); | |
92 | } | |
93 | ||
ee94ee34 | 94 | static int umc_init_sub(int freq, int size_ch0, int size_ch1) |
5894ca00 MY |
95 | { |
96 | void __iomem *ssif_base = (void __iomem *)UMC_SSIF_BASE; | |
97 | void __iomem *ca_base0 = (void __iomem *)UMC_CA_BASE(0); | |
98 | void __iomem *ca_base1 = (void __iomem *)UMC_CA_BASE(1); | |
99 | void __iomem *dramcont0 = (void __iomem *)UMC_DRAMCONT_BASE(0); | |
100 | void __iomem *dramcont1 = (void __iomem *)UMC_DRAMCONT_BASE(1); | |
b614e16c MY |
101 | void __iomem *phy0_0 = (void __iomem *)DDRPHY_BASE(0, 0); |
102 | void __iomem *phy0_1 = (void __iomem *)DDRPHY_BASE(0, 1); | |
103 | void __iomem *phy1_0 = (void __iomem *)DDRPHY_BASE(1, 0); | |
104 | void __iomem *phy1_1 = (void __iomem *)DDRPHY_BASE(1, 1); | |
5894ca00 MY |
105 | |
106 | umc_dram_init_start(dramcont0); | |
107 | umc_dram_init_start(dramcont1); | |
108 | umc_dram_init_poll(dramcont0); | |
109 | umc_dram_init_poll(dramcont1); | |
110 | ||
111 | writel(0x00000101, dramcont0 + UMC_DIOCTLA); | |
112 | ||
323d1f9d | 113 | ph1_pro4_ddrphy_init(phy0_0, freq, size_ch0); |
b614e16c MY |
114 | |
115 | ddrphy_prepare_training(phy0_0, 0); | |
116 | ddrphy_training(phy0_0); | |
117 | ||
5894ca00 MY |
118 | writel(0x00000103, dramcont0 + UMC_DIOCTLA); |
119 | ||
323d1f9d | 120 | ph1_pro4_ddrphy_init(phy0_1, freq, size_ch0); |
b614e16c MY |
121 | |
122 | ddrphy_prepare_training(phy0_1, 1); | |
123 | ddrphy_training(phy0_1); | |
124 | ||
5894ca00 MY |
125 | writel(0x00000101, dramcont1 + UMC_DIOCTLA); |
126 | ||
323d1f9d | 127 | ph1_pro4_ddrphy_init(phy1_0, freq, size_ch1); |
b614e16c MY |
128 | |
129 | ddrphy_prepare_training(phy1_0, 0); | |
130 | ddrphy_training(phy1_0); | |
131 | ||
5894ca00 MY |
132 | writel(0x00000103, dramcont1 + UMC_DIOCTLA); |
133 | ||
323d1f9d | 134 | ph1_pro4_ddrphy_init(phy1_1, freq, size_ch1); |
b614e16c MY |
135 | |
136 | ddrphy_prepare_training(phy1_1, 1); | |
137 | ddrphy_training(phy1_1); | |
138 | ||
5894ca00 MY |
139 | umc_dramcont_init(dramcont0, ca_base0, size_ch0, freq); |
140 | umc_dramcont_init(dramcont1, ca_base1, size_ch1, freq); | |
141 | ||
142 | umc_start_ssif(ssif_base); | |
143 | ||
144 | return 0; | |
145 | } | |
146 | ||
323d1f9d | 147 | int ph1_pro4_umc_init(const struct uniphier_board_data *bd) |
5894ca00 | 148 | { |
323d1f9d MY |
149 | if (((bd->dram_ch0_size == SZ_512M && bd->dram_ch0_width == 32) || |
150 | (bd->dram_ch0_size == SZ_256M && bd->dram_ch0_width == 16)) && | |
151 | ((bd->dram_ch1_size == SZ_512M && bd->dram_ch1_width == 32) || | |
152 | (bd->dram_ch1_size == SZ_256M && bd->dram_ch1_width == 16)) && | |
153 | bd->dram_freq == 1600) { | |
154 | return umc_init_sub(bd->dram_freq, | |
155 | bd->dram_ch0_size / SZ_128M, | |
156 | bd->dram_ch1_size / SZ_128M); | |
157 | } else { | |
158 | pr_err("Unsupported DDR configuration\n"); | |
159 | return -EINVAL; | |
160 | } | |
5894ca00 | 161 | } |