xref: /qemu/hw/ppc/ppc4xx_sdram.c (revision 54a3527e427b7df33ffcea3ad0ab56f7a0a61dd9)
12a48dd7cSBALATON Zoltan /*
2fa446fc5SBALATON Zoltan  * QEMU PowerPC 4xx embedded processors SDRAM controller emulation
3fa446fc5SBALATON Zoltan  *
4fa446fc5SBALATON Zoltan  * DDR SDRAM controller:
5fa446fc5SBALATON Zoltan  * Copyright (c) 2007 Jocelyn Mayer
6fa446fc5SBALATON Zoltan  *
7fa446fc5SBALATON Zoltan  * Permission is hereby granted, free of charge, to any person obtaining a copy
8fa446fc5SBALATON Zoltan  * of this software and associated documentation files (the "Software"), to deal
9fa446fc5SBALATON Zoltan  * in the Software without restriction, including without limitation the rights
10fa446fc5SBALATON Zoltan  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11fa446fc5SBALATON Zoltan  * copies of the Software, and to permit persons to whom the Software is
12fa446fc5SBALATON Zoltan  * furnished to do so, subject to the following conditions:
13fa446fc5SBALATON Zoltan  *
14fa446fc5SBALATON Zoltan  * The above copyright notice and this permission notice shall be included in
15fa446fc5SBALATON Zoltan  * all copies or substantial portions of the Software.
16fa446fc5SBALATON Zoltan  *
17fa446fc5SBALATON Zoltan  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18fa446fc5SBALATON Zoltan  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19fa446fc5SBALATON Zoltan  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20fa446fc5SBALATON Zoltan  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21fa446fc5SBALATON Zoltan  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22fa446fc5SBALATON Zoltan  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23fa446fc5SBALATON Zoltan  * THE SOFTWARE.
24fa446fc5SBALATON Zoltan  *
252a48dd7cSBALATON Zoltan  * DDR2 SDRAM controller:
262a48dd7cSBALATON Zoltan  * Copyright (c) 2012 François Revol
272a48dd7cSBALATON Zoltan  * Copyright (c) 2016-2019 BALATON Zoltan
282a48dd7cSBALATON Zoltan  *
292a48dd7cSBALATON Zoltan  * This work is licensed under the GNU GPL license version 2 or later.
302a48dd7cSBALATON Zoltan  */
312a48dd7cSBALATON Zoltan 
322a48dd7cSBALATON Zoltan #include "qemu/osdep.h"
332a48dd7cSBALATON Zoltan #include "qemu/units.h"
342a48dd7cSBALATON Zoltan #include "qapi/error.h"
35fa446fc5SBALATON Zoltan #include "qemu/log.h"
362a48dd7cSBALATON Zoltan #include "exec/address-spaces.h" /* get_system_memory() */
372a48dd7cSBALATON Zoltan #include "hw/irq.h"
382a48dd7cSBALATON Zoltan #include "hw/qdev-properties.h"
392a48dd7cSBALATON Zoltan #include "hw/ppc/ppc4xx.h"
402a48dd7cSBALATON Zoltan #include "trace.h"
412a48dd7cSBALATON Zoltan 
422a48dd7cSBALATON Zoltan /*****************************************************************************/
432a48dd7cSBALATON Zoltan /* Shared functions */
442a48dd7cSBALATON Zoltan 
45080741abSBALATON Zoltan /*
46080741abSBALATON Zoltan  * Split RAM between SDRAM banks.
47080741abSBALATON Zoltan  *
48080741abSBALATON Zoltan  * sdram_bank_sizes[] must be in descending order, that is sizes[i] > sizes[i+1]
49080741abSBALATON Zoltan  * and must be 0-terminated.
50080741abSBALATON Zoltan  *
51080741abSBALATON Zoltan  * The 4xx SDRAM controller supports a small number of banks, and each bank
52080741abSBALATON Zoltan  * must be one of a small set of sizes. The number of banks and the supported
53080741abSBALATON Zoltan  * sizes varies by SoC.
54080741abSBALATON Zoltan  */
55080741abSBALATON Zoltan static void ppc4xx_sdram_banks(MemoryRegion *ram, int nr_banks,
56080741abSBALATON Zoltan                                Ppc4xxSdramBank ram_banks[],
57080741abSBALATON Zoltan                                const ram_addr_t sdram_bank_sizes[])
58080741abSBALATON Zoltan {
59080741abSBALATON Zoltan     ram_addr_t size_left = memory_region_size(ram);
60080741abSBALATON Zoltan     ram_addr_t base = 0;
61080741abSBALATON Zoltan     ram_addr_t bank_size;
62080741abSBALATON Zoltan     int i;
63080741abSBALATON Zoltan     int j;
64080741abSBALATON Zoltan 
65080741abSBALATON Zoltan     for (i = 0; i < nr_banks; i++) {
66080741abSBALATON Zoltan         for (j = 0; sdram_bank_sizes[j] != 0; j++) {
67080741abSBALATON Zoltan             bank_size = sdram_bank_sizes[j];
68080741abSBALATON Zoltan             if (bank_size <= size_left) {
69080741abSBALATON Zoltan                 char name[32];
70080741abSBALATON Zoltan 
71080741abSBALATON Zoltan                 ram_banks[i].base = base;
72080741abSBALATON Zoltan                 ram_banks[i].size = bank_size;
73080741abSBALATON Zoltan                 base += bank_size;
74080741abSBALATON Zoltan                 size_left -= bank_size;
75080741abSBALATON Zoltan                 snprintf(name, sizeof(name), "ppc4xx.sdram%d", i);
76080741abSBALATON Zoltan                 memory_region_init_alias(&ram_banks[i].ram, NULL, name, ram,
77080741abSBALATON Zoltan                                          ram_banks[i].base, ram_banks[i].size);
78080741abSBALATON Zoltan                 break;
79080741abSBALATON Zoltan             }
80080741abSBALATON Zoltan         }
81080741abSBALATON Zoltan         if (!size_left) {
82080741abSBALATON Zoltan             /* No need to use the remaining banks. */
83080741abSBALATON Zoltan             break;
84080741abSBALATON Zoltan         }
85080741abSBALATON Zoltan     }
86080741abSBALATON Zoltan 
87080741abSBALATON Zoltan     if (size_left) {
88080741abSBALATON Zoltan         ram_addr_t used_size = memory_region_size(ram) - size_left;
89080741abSBALATON Zoltan         GString *s = g_string_new(NULL);
90080741abSBALATON Zoltan 
91080741abSBALATON Zoltan         for (i = 0; sdram_bank_sizes[i]; i++) {
92080741abSBALATON Zoltan             g_string_append_printf(s, "%" PRIi64 "%s",
93080741abSBALATON Zoltan                                    sdram_bank_sizes[i] / MiB,
94080741abSBALATON Zoltan                                    sdram_bank_sizes[i + 1] ? ", " : "");
95080741abSBALATON Zoltan         }
96080741abSBALATON Zoltan         error_report("at most %d bank%s of %s MiB each supported",
97080741abSBALATON Zoltan                      nr_banks, nr_banks == 1 ? "" : "s", s->str);
98080741abSBALATON Zoltan         error_printf("Possible valid RAM size: %" PRIi64 " MiB\n",
99080741abSBALATON Zoltan             used_size ? used_size / MiB : sdram_bank_sizes[i - 1] / MiB);
100080741abSBALATON Zoltan 
101080741abSBALATON Zoltan         g_string_free(s, true);
102080741abSBALATON Zoltan         exit(EXIT_FAILURE);
103080741abSBALATON Zoltan     }
104080741abSBALATON Zoltan }
105080741abSBALATON Zoltan 
1062a48dd7cSBALATON Zoltan static void sdram_bank_map(Ppc4xxSdramBank *bank)
1072a48dd7cSBALATON Zoltan {
108424a660cSBALATON Zoltan     trace_ppc4xx_sdram_map(bank->base, bank->size);
1092a48dd7cSBALATON Zoltan     memory_region_init(&bank->container, NULL, "sdram-container", bank->size);
1102a48dd7cSBALATON Zoltan     memory_region_add_subregion(&bank->container, 0, &bank->ram);
1112a48dd7cSBALATON Zoltan     memory_region_add_subregion(get_system_memory(), bank->base,
1122a48dd7cSBALATON Zoltan                                 &bank->container);
1132a48dd7cSBALATON Zoltan }
1142a48dd7cSBALATON Zoltan 
1152a48dd7cSBALATON Zoltan static void sdram_bank_unmap(Ppc4xxSdramBank *bank)
1162a48dd7cSBALATON Zoltan {
117424a660cSBALATON Zoltan     trace_ppc4xx_sdram_unmap(bank->base, bank->size);
1182a48dd7cSBALATON Zoltan     memory_region_del_subregion(get_system_memory(), &bank->container);
1192a48dd7cSBALATON Zoltan     memory_region_del_subregion(&bank->container, &bank->ram);
1202a48dd7cSBALATON Zoltan     object_unparent(OBJECT(&bank->container));
1212a48dd7cSBALATON Zoltan }
1222a48dd7cSBALATON Zoltan 
123424a660cSBALATON Zoltan static void sdram_bank_set_bcr(Ppc4xxSdramBank *bank, uint32_t bcr,
124424a660cSBALATON Zoltan                                hwaddr base, hwaddr size, int enabled)
125424a660cSBALATON Zoltan {
126424a660cSBALATON Zoltan     if (memory_region_is_mapped(&bank->container)) {
127424a660cSBALATON Zoltan         sdram_bank_unmap(bank);
128424a660cSBALATON Zoltan     }
129424a660cSBALATON Zoltan     bank->bcr = bcr;
130424a660cSBALATON Zoltan     bank->base = base;
131424a660cSBALATON Zoltan     bank->size = size;
132424a660cSBALATON Zoltan     if (enabled && (bcr & 1)) {
133424a660cSBALATON Zoltan         sdram_bank_map(bank);
134424a660cSBALATON Zoltan     }
135424a660cSBALATON Zoltan }
136424a660cSBALATON Zoltan 
1372a48dd7cSBALATON Zoltan enum {
1382a48dd7cSBALATON Zoltan     SDRAM0_CFGADDR = 0x010,
1392a48dd7cSBALATON Zoltan     SDRAM0_CFGDATA = 0x011,
1402a48dd7cSBALATON Zoltan };
1412a48dd7cSBALATON Zoltan 
1422a48dd7cSBALATON Zoltan /*****************************************************************************/
143fa446fc5SBALATON Zoltan /* DDR SDRAM controller */
144*54a3527eSBALATON Zoltan #define SDRAM_DDR_BCR_MASK 0xFFDEE001
145*54a3527eSBALATON Zoltan 
146fa446fc5SBALATON Zoltan static uint32_t sdram_ddr_bcr(hwaddr ram_base, hwaddr ram_size)
147fa446fc5SBALATON Zoltan {
148fa446fc5SBALATON Zoltan     uint32_t bcr;
149fa446fc5SBALATON Zoltan 
150fa446fc5SBALATON Zoltan     switch (ram_size) {
151fa446fc5SBALATON Zoltan     case 4 * MiB:
152fa446fc5SBALATON Zoltan         bcr = 0;
153fa446fc5SBALATON Zoltan         break;
154fa446fc5SBALATON Zoltan     case 8 * MiB:
155fa446fc5SBALATON Zoltan         bcr = 0x20000;
156fa446fc5SBALATON Zoltan         break;
157fa446fc5SBALATON Zoltan     case 16 * MiB:
158fa446fc5SBALATON Zoltan         bcr = 0x40000;
159fa446fc5SBALATON Zoltan         break;
160fa446fc5SBALATON Zoltan     case 32 * MiB:
161fa446fc5SBALATON Zoltan         bcr = 0x60000;
162fa446fc5SBALATON Zoltan         break;
163fa446fc5SBALATON Zoltan     case 64 * MiB:
164fa446fc5SBALATON Zoltan         bcr = 0x80000;
165fa446fc5SBALATON Zoltan         break;
166fa446fc5SBALATON Zoltan     case 128 * MiB:
167fa446fc5SBALATON Zoltan         bcr = 0xA0000;
168fa446fc5SBALATON Zoltan         break;
169fa446fc5SBALATON Zoltan     case 256 * MiB:
170fa446fc5SBALATON Zoltan         bcr = 0xC0000;
171fa446fc5SBALATON Zoltan         break;
172fa446fc5SBALATON Zoltan     default:
173fa446fc5SBALATON Zoltan         qemu_log_mask(LOG_GUEST_ERROR,
174fa446fc5SBALATON Zoltan                       "%s: invalid RAM size 0x%" HWADDR_PRIx "\n", __func__,
175fa446fc5SBALATON Zoltan                       ram_size);
176fa446fc5SBALATON Zoltan         return 0;
177fa446fc5SBALATON Zoltan     }
178fa446fc5SBALATON Zoltan     bcr |= ram_base & 0xFF800000;
179fa446fc5SBALATON Zoltan     bcr |= 1;
180fa446fc5SBALATON Zoltan 
181fa446fc5SBALATON Zoltan     return bcr;
182fa446fc5SBALATON Zoltan }
183fa446fc5SBALATON Zoltan 
184fa446fc5SBALATON Zoltan static inline hwaddr sdram_ddr_base(uint32_t bcr)
185fa446fc5SBALATON Zoltan {
186fa446fc5SBALATON Zoltan     return bcr & 0xFF800000;
187fa446fc5SBALATON Zoltan }
188fa446fc5SBALATON Zoltan 
189c8c6d68aSBALATON Zoltan static hwaddr sdram_ddr_size(uint32_t bcr)
190fa446fc5SBALATON Zoltan {
191c8c6d68aSBALATON Zoltan     hwaddr size;
192fa446fc5SBALATON Zoltan     int sh;
193fa446fc5SBALATON Zoltan 
194fa446fc5SBALATON Zoltan     sh = (bcr >> 17) & 0x7;
195fa446fc5SBALATON Zoltan     if (sh == 7) {
196fa446fc5SBALATON Zoltan         size = -1;
197fa446fc5SBALATON Zoltan     } else {
198fa446fc5SBALATON Zoltan         size = (4 * MiB) << sh;
199fa446fc5SBALATON Zoltan     }
200fa446fc5SBALATON Zoltan 
201fa446fc5SBALATON Zoltan     return size;
202fa446fc5SBALATON Zoltan }
203fa446fc5SBALATON Zoltan 
204fa446fc5SBALATON Zoltan static uint32_t sdram_ddr_dcr_read(void *opaque, int dcrn)
205fa446fc5SBALATON Zoltan {
20661cfe0dfSBALATON Zoltan     Ppc4xxSdramDdrState *s = opaque;
207fa446fc5SBALATON Zoltan     uint32_t ret;
208fa446fc5SBALATON Zoltan 
209fa446fc5SBALATON Zoltan     switch (dcrn) {
210fa446fc5SBALATON Zoltan     case SDRAM0_CFGADDR:
21161cfe0dfSBALATON Zoltan         ret = s->addr;
212fa446fc5SBALATON Zoltan         break;
213fa446fc5SBALATON Zoltan     case SDRAM0_CFGDATA:
21461cfe0dfSBALATON Zoltan         switch (s->addr) {
215fa446fc5SBALATON Zoltan         case 0x00: /* SDRAM_BESR0 */
21661cfe0dfSBALATON Zoltan             ret = s->besr0;
217fa446fc5SBALATON Zoltan             break;
218fa446fc5SBALATON Zoltan         case 0x08: /* SDRAM_BESR1 */
21961cfe0dfSBALATON Zoltan             ret = s->besr1;
220fa446fc5SBALATON Zoltan             break;
221fa446fc5SBALATON Zoltan         case 0x10: /* SDRAM_BEAR */
22261cfe0dfSBALATON Zoltan             ret = s->bear;
223fa446fc5SBALATON Zoltan             break;
224fa446fc5SBALATON Zoltan         case 0x20: /* SDRAM_CFG */
22561cfe0dfSBALATON Zoltan             ret = s->cfg;
226fa446fc5SBALATON Zoltan             break;
227fa446fc5SBALATON Zoltan         case 0x24: /* SDRAM_STATUS */
22861cfe0dfSBALATON Zoltan             ret = s->status;
229fa446fc5SBALATON Zoltan             break;
230fa446fc5SBALATON Zoltan         case 0x30: /* SDRAM_RTR */
23161cfe0dfSBALATON Zoltan             ret = s->rtr;
232fa446fc5SBALATON Zoltan             break;
233fa446fc5SBALATON Zoltan         case 0x34: /* SDRAM_PMIT */
23461cfe0dfSBALATON Zoltan             ret = s->pmit;
235fa446fc5SBALATON Zoltan             break;
236fa446fc5SBALATON Zoltan         case 0x40: /* SDRAM_B0CR */
23761cfe0dfSBALATON Zoltan             ret = s->bank[0].bcr;
238fa446fc5SBALATON Zoltan             break;
239fa446fc5SBALATON Zoltan         case 0x44: /* SDRAM_B1CR */
24061cfe0dfSBALATON Zoltan             ret = s->bank[1].bcr;
241fa446fc5SBALATON Zoltan             break;
242fa446fc5SBALATON Zoltan         case 0x48: /* SDRAM_B2CR */
24361cfe0dfSBALATON Zoltan             ret = s->bank[2].bcr;
244fa446fc5SBALATON Zoltan             break;
245fa446fc5SBALATON Zoltan         case 0x4C: /* SDRAM_B3CR */
24661cfe0dfSBALATON Zoltan             ret = s->bank[3].bcr;
247fa446fc5SBALATON Zoltan             break;
248fa446fc5SBALATON Zoltan         case 0x80: /* SDRAM_TR */
249fa446fc5SBALATON Zoltan             ret = -1; /* ? */
250fa446fc5SBALATON Zoltan             break;
251fa446fc5SBALATON Zoltan         case 0x94: /* SDRAM_ECCCFG */
25261cfe0dfSBALATON Zoltan             ret = s->ecccfg;
253fa446fc5SBALATON Zoltan             break;
254fa446fc5SBALATON Zoltan         case 0x98: /* SDRAM_ECCESR */
25561cfe0dfSBALATON Zoltan             ret = s->eccesr;
256fa446fc5SBALATON Zoltan             break;
257fa446fc5SBALATON Zoltan         default: /* Error */
258fa446fc5SBALATON Zoltan             ret = -1;
259fa446fc5SBALATON Zoltan             break;
260fa446fc5SBALATON Zoltan         }
261fa446fc5SBALATON Zoltan         break;
262fa446fc5SBALATON Zoltan     default:
263fa446fc5SBALATON Zoltan         /* Avoid gcc warning */
264fa446fc5SBALATON Zoltan         ret = 0;
265fa446fc5SBALATON Zoltan         break;
266fa446fc5SBALATON Zoltan     }
267fa446fc5SBALATON Zoltan 
268fa446fc5SBALATON Zoltan     return ret;
269fa446fc5SBALATON Zoltan }
270fa446fc5SBALATON Zoltan 
271fa446fc5SBALATON Zoltan static void sdram_ddr_dcr_write(void *opaque, int dcrn, uint32_t val)
272fa446fc5SBALATON Zoltan {
27361cfe0dfSBALATON Zoltan     Ppc4xxSdramDdrState *s = opaque;
274*54a3527eSBALATON Zoltan     int i;
275fa446fc5SBALATON Zoltan 
276fa446fc5SBALATON Zoltan     switch (dcrn) {
277fa446fc5SBALATON Zoltan     case SDRAM0_CFGADDR:
27861cfe0dfSBALATON Zoltan         s->addr = val;
279fa446fc5SBALATON Zoltan         break;
280fa446fc5SBALATON Zoltan     case SDRAM0_CFGDATA:
28161cfe0dfSBALATON Zoltan         switch (s->addr) {
282fa446fc5SBALATON Zoltan         case 0x00: /* SDRAM_BESR0 */
28361cfe0dfSBALATON Zoltan             s->besr0 &= ~val;
284fa446fc5SBALATON Zoltan             break;
285fa446fc5SBALATON Zoltan         case 0x08: /* SDRAM_BESR1 */
28661cfe0dfSBALATON Zoltan             s->besr1 &= ~val;
287fa446fc5SBALATON Zoltan             break;
288fa446fc5SBALATON Zoltan         case 0x10: /* SDRAM_BEAR */
28961cfe0dfSBALATON Zoltan             s->bear = val;
290fa446fc5SBALATON Zoltan             break;
291fa446fc5SBALATON Zoltan         case 0x20: /* SDRAM_CFG */
292fa446fc5SBALATON Zoltan             val &= 0xFFE00000;
29361cfe0dfSBALATON Zoltan             if (!(s->cfg & 0x80000000) && (val & 0x80000000)) {
294fa446fc5SBALATON Zoltan                 trace_ppc4xx_sdram_enable("enable");
295fa446fc5SBALATON Zoltan                 /* validate all RAM mappings */
296*54a3527eSBALATON Zoltan                 for (i = 0; i < s->nbanks; i++) {
297*54a3527eSBALATON Zoltan                     if (s->bank[i].size) {
298*54a3527eSBALATON Zoltan                         sdram_bank_set_bcr(&s->bank[i], s->bank[i].bcr,
299*54a3527eSBALATON Zoltan                                            s->bank[i].base, s->bank[i].size,
300*54a3527eSBALATON Zoltan                                            1);
301*54a3527eSBALATON Zoltan                     }
302*54a3527eSBALATON Zoltan                 }
30361cfe0dfSBALATON Zoltan                 s->status &= ~0x80000000;
30461cfe0dfSBALATON Zoltan             } else if ((s->cfg & 0x80000000) && !(val & 0x80000000)) {
305fa446fc5SBALATON Zoltan                 trace_ppc4xx_sdram_enable("disable");
306fa446fc5SBALATON Zoltan                 /* invalidate all RAM mappings */
307*54a3527eSBALATON Zoltan                 for (i = 0; i < s->nbanks; i++) {
308*54a3527eSBALATON Zoltan                     if (s->bank[i].size) {
309*54a3527eSBALATON Zoltan                         sdram_bank_set_bcr(&s->bank[i], s->bank[i].bcr,
310*54a3527eSBALATON Zoltan                                            s->bank[i].base, s->bank[i].size,
311*54a3527eSBALATON Zoltan                                            0);
312*54a3527eSBALATON Zoltan                     }
313*54a3527eSBALATON Zoltan                 }
31461cfe0dfSBALATON Zoltan                 s->status |= 0x80000000;
315fa446fc5SBALATON Zoltan             }
31661cfe0dfSBALATON Zoltan             if (!(s->cfg & 0x40000000) && (val & 0x40000000)) {
31761cfe0dfSBALATON Zoltan                 s->status |= 0x40000000;
31861cfe0dfSBALATON Zoltan             } else if ((s->cfg & 0x40000000) && !(val & 0x40000000)) {
31961cfe0dfSBALATON Zoltan                 s->status &= ~0x40000000;
320fa446fc5SBALATON Zoltan             }
32161cfe0dfSBALATON Zoltan             s->cfg = val;
322fa446fc5SBALATON Zoltan             break;
323fa446fc5SBALATON Zoltan         case 0x24: /* SDRAM_STATUS */
324fa446fc5SBALATON Zoltan             /* Read-only register */
325fa446fc5SBALATON Zoltan             break;
326fa446fc5SBALATON Zoltan         case 0x30: /* SDRAM_RTR */
32761cfe0dfSBALATON Zoltan             s->rtr = val & 0x3FF80000;
328fa446fc5SBALATON Zoltan             break;
329fa446fc5SBALATON Zoltan         case 0x34: /* SDRAM_PMIT */
33061cfe0dfSBALATON Zoltan             s->pmit = (val & 0xF8000000) | 0x07C00000;
331fa446fc5SBALATON Zoltan             break;
332fa446fc5SBALATON Zoltan         case 0x40: /* SDRAM_B0CR */
333fa446fc5SBALATON Zoltan         case 0x44: /* SDRAM_B1CR */
334fa446fc5SBALATON Zoltan         case 0x48: /* SDRAM_B2CR */
335fa446fc5SBALATON Zoltan         case 0x4C: /* SDRAM_B3CR */
336*54a3527eSBALATON Zoltan             i = (s->addr - 0x40) / 4;
337*54a3527eSBALATON Zoltan             val &= SDRAM_DDR_BCR_MASK;
338*54a3527eSBALATON Zoltan             if (s->bank[i].size) {
339*54a3527eSBALATON Zoltan                 sdram_bank_set_bcr(&s->bank[i], val,
340*54a3527eSBALATON Zoltan                                    sdram_ddr_base(val), sdram_ddr_size(val),
341*54a3527eSBALATON Zoltan                                    s->cfg & 0x80000000);
342*54a3527eSBALATON Zoltan             }
343fa446fc5SBALATON Zoltan             break;
344fa446fc5SBALATON Zoltan         case 0x80: /* SDRAM_TR */
34561cfe0dfSBALATON Zoltan             s->tr = val & 0x018FC01F;
346fa446fc5SBALATON Zoltan             break;
347fa446fc5SBALATON Zoltan         case 0x94: /* SDRAM_ECCCFG */
34861cfe0dfSBALATON Zoltan             s->ecccfg = val & 0x00F00000;
349fa446fc5SBALATON Zoltan             break;
350fa446fc5SBALATON Zoltan         case 0x98: /* SDRAM_ECCESR */
351fa446fc5SBALATON Zoltan             val &= 0xFFF0F000;
35261cfe0dfSBALATON Zoltan             if (s->eccesr == 0 && val != 0) {
35361cfe0dfSBALATON Zoltan                 qemu_irq_raise(s->irq);
35461cfe0dfSBALATON Zoltan             } else if (s->eccesr != 0 && val == 0) {
35561cfe0dfSBALATON Zoltan                 qemu_irq_lower(s->irq);
356fa446fc5SBALATON Zoltan             }
35761cfe0dfSBALATON Zoltan             s->eccesr = val;
358fa446fc5SBALATON Zoltan             break;
359fa446fc5SBALATON Zoltan         default: /* Error */
360fa446fc5SBALATON Zoltan             break;
361fa446fc5SBALATON Zoltan         }
362fa446fc5SBALATON Zoltan         break;
363fa446fc5SBALATON Zoltan     }
364fa446fc5SBALATON Zoltan }
365fa446fc5SBALATON Zoltan 
366fa446fc5SBALATON Zoltan static void ppc4xx_sdram_ddr_reset(DeviceState *dev)
367fa446fc5SBALATON Zoltan {
36861cfe0dfSBALATON Zoltan     Ppc4xxSdramDdrState *s = PPC4xx_SDRAM_DDR(dev);
369fa446fc5SBALATON Zoltan 
37061cfe0dfSBALATON Zoltan     s->addr = 0;
37161cfe0dfSBALATON Zoltan     s->bear = 0;
37261cfe0dfSBALATON Zoltan     s->besr0 = 0; /* No error */
37361cfe0dfSBALATON Zoltan     s->besr1 = 0; /* No error */
37461cfe0dfSBALATON Zoltan     s->cfg = 0;
37561cfe0dfSBALATON Zoltan     s->ecccfg = 0; /* No ECC */
37661cfe0dfSBALATON Zoltan     s->eccesr = 0; /* No error */
37761cfe0dfSBALATON Zoltan     s->pmit = 0x07C00000;
37861cfe0dfSBALATON Zoltan     s->rtr = 0x05F00000;
37961cfe0dfSBALATON Zoltan     s->tr = 0x00854009;
380fa446fc5SBALATON Zoltan     /* We pre-initialize RAM banks */
38161cfe0dfSBALATON Zoltan     s->status = 0;
38261cfe0dfSBALATON Zoltan     s->cfg = 0x00800000;
383fa446fc5SBALATON Zoltan }
384fa446fc5SBALATON Zoltan 
385fa446fc5SBALATON Zoltan static void ppc4xx_sdram_ddr_realize(DeviceState *dev, Error **errp)
386fa446fc5SBALATON Zoltan {
387fa446fc5SBALATON Zoltan     Ppc4xxSdramDdrState *s = PPC4xx_SDRAM_DDR(dev);
388fa446fc5SBALATON Zoltan     Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev);
389fa446fc5SBALATON Zoltan     const ram_addr_t valid_bank_sizes[] = {
390fa446fc5SBALATON Zoltan         256 * MiB, 128 * MiB, 64 * MiB, 32 * MiB, 16 * MiB, 8 * MiB, 4 * MiB, 0
391fa446fc5SBALATON Zoltan     };
392*54a3527eSBALATON Zoltan     int i;
393fa446fc5SBALATON Zoltan 
394fa446fc5SBALATON Zoltan     if (s->nbanks < 1 || s->nbanks > 4) {
395fa446fc5SBALATON Zoltan         error_setg(errp, "Invalid number of RAM banks");
396fa446fc5SBALATON Zoltan         return;
397fa446fc5SBALATON Zoltan     }
398fa446fc5SBALATON Zoltan     if (!s->dram_mr) {
399fa446fc5SBALATON Zoltan         error_setg(errp, "Missing dram memory region");
400fa446fc5SBALATON Zoltan         return;
401fa446fc5SBALATON Zoltan     }
402fa446fc5SBALATON Zoltan     ppc4xx_sdram_banks(s->dram_mr, s->nbanks, s->bank, valid_bank_sizes);
403*54a3527eSBALATON Zoltan     for (i = 0; i < s->nbanks; i++) {
404*54a3527eSBALATON Zoltan         if (s->bank[i].size) {
405*54a3527eSBALATON Zoltan             s->bank[i].bcr = sdram_ddr_bcr(s->bank[i].base, s->bank[i].size);
406*54a3527eSBALATON Zoltan             sdram_bank_set_bcr(&s->bank[i], s->bank[i].bcr,
407*54a3527eSBALATON Zoltan                                s->bank[i].base, s->bank[i].size, 0);
408*54a3527eSBALATON Zoltan         } else {
409*54a3527eSBALATON Zoltan             sdram_bank_set_bcr(&s->bank[i], 0, 0, 0, 0);
410*54a3527eSBALATON Zoltan         }
411*54a3527eSBALATON Zoltan         trace_ppc4xx_sdram_init(sdram_ddr_base(s->bank[i].bcr),
412*54a3527eSBALATON Zoltan                                 sdram_ddr_size(s->bank[i].bcr),
413*54a3527eSBALATON Zoltan                                 s->bank[i].bcr);
414*54a3527eSBALATON Zoltan     }
415fa446fc5SBALATON Zoltan 
416fa446fc5SBALATON Zoltan     sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
417fa446fc5SBALATON Zoltan 
418fa446fc5SBALATON Zoltan     ppc4xx_dcr_register(dcr, SDRAM0_CFGADDR,
419fa446fc5SBALATON Zoltan                         s, &sdram_ddr_dcr_read, &sdram_ddr_dcr_write);
420fa446fc5SBALATON Zoltan     ppc4xx_dcr_register(dcr, SDRAM0_CFGDATA,
421fa446fc5SBALATON Zoltan                         s, &sdram_ddr_dcr_read, &sdram_ddr_dcr_write);
422fa446fc5SBALATON Zoltan }
423fa446fc5SBALATON Zoltan 
424fa446fc5SBALATON Zoltan static Property ppc4xx_sdram_ddr_props[] = {
425fa446fc5SBALATON Zoltan     DEFINE_PROP_LINK("dram", Ppc4xxSdramDdrState, dram_mr, TYPE_MEMORY_REGION,
426fa446fc5SBALATON Zoltan                      MemoryRegion *),
427fa446fc5SBALATON Zoltan     DEFINE_PROP_UINT32("nbanks", Ppc4xxSdramDdrState, nbanks, 4),
428fa446fc5SBALATON Zoltan     DEFINE_PROP_END_OF_LIST(),
429fa446fc5SBALATON Zoltan };
430fa446fc5SBALATON Zoltan 
431fa446fc5SBALATON Zoltan static void ppc4xx_sdram_ddr_class_init(ObjectClass *oc, void *data)
432fa446fc5SBALATON Zoltan {
433fa446fc5SBALATON Zoltan     DeviceClass *dc = DEVICE_CLASS(oc);
434fa446fc5SBALATON Zoltan 
435fa446fc5SBALATON Zoltan     dc->realize = ppc4xx_sdram_ddr_realize;
436fa446fc5SBALATON Zoltan     dc->reset = ppc4xx_sdram_ddr_reset;
437fa446fc5SBALATON Zoltan     /* Reason: only works as function of a ppc4xx SoC */
438fa446fc5SBALATON Zoltan     dc->user_creatable = false;
439fa446fc5SBALATON Zoltan     device_class_set_props(dc, ppc4xx_sdram_ddr_props);
440fa446fc5SBALATON Zoltan }
441fa446fc5SBALATON Zoltan 
442fa446fc5SBALATON Zoltan void ppc4xx_sdram_ddr_enable(Ppc4xxSdramDdrState *s)
443fa446fc5SBALATON Zoltan {
444fa446fc5SBALATON Zoltan     sdram_ddr_dcr_write(s, SDRAM0_CFGADDR, 0x20);
445fa446fc5SBALATON Zoltan     sdram_ddr_dcr_write(s, SDRAM0_CFGDATA, 0x80000000);
446fa446fc5SBALATON Zoltan }
447fa446fc5SBALATON Zoltan 
448fa446fc5SBALATON Zoltan /*****************************************************************************/
4492a48dd7cSBALATON Zoltan /* DDR2 SDRAM controller */
450424a660cSBALATON Zoltan #define SDRAM_DDR2_BCR_MASK 0xffe0ffc1
451424a660cSBALATON Zoltan 
4522a48dd7cSBALATON Zoltan enum {
4532a48dd7cSBALATON Zoltan     SDRAM_R0BAS = 0x40,
4542a48dd7cSBALATON Zoltan     SDRAM_R1BAS,
4552a48dd7cSBALATON Zoltan     SDRAM_R2BAS,
4562a48dd7cSBALATON Zoltan     SDRAM_R3BAS,
4572a48dd7cSBALATON Zoltan     SDRAM_CONF1HB = 0x45,
4582a48dd7cSBALATON Zoltan     SDRAM_PLBADDULL = 0x4a,
4592a48dd7cSBALATON Zoltan     SDRAM_CONF1LL = 0x4b,
4602a48dd7cSBALATON Zoltan     SDRAM_CONFPATHB = 0x4f,
4612a48dd7cSBALATON Zoltan     SDRAM_PLBADDUHB = 0x50,
4622a48dd7cSBALATON Zoltan };
4632a48dd7cSBALATON Zoltan 
4642a48dd7cSBALATON Zoltan static uint32_t sdram_ddr2_bcr(hwaddr ram_base, hwaddr ram_size)
4652a48dd7cSBALATON Zoltan {
4662a48dd7cSBALATON Zoltan     uint32_t bcr;
4672a48dd7cSBALATON Zoltan 
4682a48dd7cSBALATON Zoltan     switch (ram_size) {
4692a48dd7cSBALATON Zoltan     case 8 * MiB:
4702a48dd7cSBALATON Zoltan         bcr = 0xffc0;
4712a48dd7cSBALATON Zoltan         break;
4722a48dd7cSBALATON Zoltan     case 16 * MiB:
4732a48dd7cSBALATON Zoltan         bcr = 0xff80;
4742a48dd7cSBALATON Zoltan         break;
4752a48dd7cSBALATON Zoltan     case 32 * MiB:
4762a48dd7cSBALATON Zoltan         bcr = 0xff00;
4772a48dd7cSBALATON Zoltan         break;
4782a48dd7cSBALATON Zoltan     case 64 * MiB:
4792a48dd7cSBALATON Zoltan         bcr = 0xfe00;
4802a48dd7cSBALATON Zoltan         break;
4812a48dd7cSBALATON Zoltan     case 128 * MiB:
4822a48dd7cSBALATON Zoltan         bcr = 0xfc00;
4832a48dd7cSBALATON Zoltan         break;
4842a48dd7cSBALATON Zoltan     case 256 * MiB:
4852a48dd7cSBALATON Zoltan         bcr = 0xf800;
4862a48dd7cSBALATON Zoltan         break;
4872a48dd7cSBALATON Zoltan     case 512 * MiB:
4882a48dd7cSBALATON Zoltan         bcr = 0xf000;
4892a48dd7cSBALATON Zoltan         break;
4902a48dd7cSBALATON Zoltan     case 1 * GiB:
4912a48dd7cSBALATON Zoltan         bcr = 0xe000;
4922a48dd7cSBALATON Zoltan         break;
4932a48dd7cSBALATON Zoltan     case 2 * GiB:
4942a48dd7cSBALATON Zoltan         bcr = 0xc000;
4952a48dd7cSBALATON Zoltan         break;
4962a48dd7cSBALATON Zoltan     case 4 * GiB:
4972a48dd7cSBALATON Zoltan         bcr = 0x8000;
4982a48dd7cSBALATON Zoltan         break;
4992a48dd7cSBALATON Zoltan     default:
5002a48dd7cSBALATON Zoltan         error_report("invalid RAM size " TARGET_FMT_plx, ram_size);
5012a48dd7cSBALATON Zoltan         return 0;
5022a48dd7cSBALATON Zoltan     }
5032a48dd7cSBALATON Zoltan     bcr |= ram_base >> 2 & 0xffe00000;
5042a48dd7cSBALATON Zoltan     bcr |= 1;
5052a48dd7cSBALATON Zoltan 
5062a48dd7cSBALATON Zoltan     return bcr;
5072a48dd7cSBALATON Zoltan }
5082a48dd7cSBALATON Zoltan 
5092a48dd7cSBALATON Zoltan static inline hwaddr sdram_ddr2_base(uint32_t bcr)
5102a48dd7cSBALATON Zoltan {
5112a48dd7cSBALATON Zoltan     return (bcr & 0xffe00000) << 2;
5122a48dd7cSBALATON Zoltan }
5132a48dd7cSBALATON Zoltan 
514c8c6d68aSBALATON Zoltan static hwaddr sdram_ddr2_size(uint32_t bcr)
5152a48dd7cSBALATON Zoltan {
516c8c6d68aSBALATON Zoltan     hwaddr size;
5172a48dd7cSBALATON Zoltan     int sh;
5182a48dd7cSBALATON Zoltan 
5192a48dd7cSBALATON Zoltan     sh = 1024 - ((bcr >> 6) & 0x3ff);
5202a48dd7cSBALATON Zoltan     size = 8 * MiB * sh;
5212a48dd7cSBALATON Zoltan 
5222a48dd7cSBALATON Zoltan     return size;
5232a48dd7cSBALATON Zoltan }
5242a48dd7cSBALATON Zoltan 
5252a48dd7cSBALATON Zoltan static uint32_t sdram_ddr2_dcr_read(void *opaque, int dcrn)
5262a48dd7cSBALATON Zoltan {
52761cfe0dfSBALATON Zoltan     Ppc4xxSdramDdr2State *s = opaque;
5282a48dd7cSBALATON Zoltan     uint32_t ret = 0;
5292a48dd7cSBALATON Zoltan 
5302a48dd7cSBALATON Zoltan     switch (dcrn) {
5312a48dd7cSBALATON Zoltan     case SDRAM_R0BAS:
5322a48dd7cSBALATON Zoltan     case SDRAM_R1BAS:
5332a48dd7cSBALATON Zoltan     case SDRAM_R2BAS:
5342a48dd7cSBALATON Zoltan     case SDRAM_R3BAS:
53561cfe0dfSBALATON Zoltan         if (s->bank[dcrn - SDRAM_R0BAS].size) {
53661cfe0dfSBALATON Zoltan             ret = sdram_ddr2_bcr(s->bank[dcrn - SDRAM_R0BAS].base,
53761cfe0dfSBALATON Zoltan                                  s->bank[dcrn - SDRAM_R0BAS].size);
5382a48dd7cSBALATON Zoltan         }
5392a48dd7cSBALATON Zoltan         break;
5402a48dd7cSBALATON Zoltan     case SDRAM_CONF1HB:
5412a48dd7cSBALATON Zoltan     case SDRAM_CONF1LL:
5422a48dd7cSBALATON Zoltan     case SDRAM_CONFPATHB:
5432a48dd7cSBALATON Zoltan     case SDRAM_PLBADDULL:
5442a48dd7cSBALATON Zoltan     case SDRAM_PLBADDUHB:
5452a48dd7cSBALATON Zoltan         break;
5462a48dd7cSBALATON Zoltan     case SDRAM0_CFGADDR:
54761cfe0dfSBALATON Zoltan         ret = s->addr;
5482a48dd7cSBALATON Zoltan         break;
5492a48dd7cSBALATON Zoltan     case SDRAM0_CFGDATA:
55061cfe0dfSBALATON Zoltan         switch (s->addr) {
5512a48dd7cSBALATON Zoltan         case 0x14: /* SDRAM_MCSTAT (405EX) */
5522a48dd7cSBALATON Zoltan         case 0x1F:
5532a48dd7cSBALATON Zoltan             ret = 0x80000000;
5542a48dd7cSBALATON Zoltan             break;
5552a48dd7cSBALATON Zoltan         case 0x21: /* SDRAM_MCOPT2 */
55661cfe0dfSBALATON Zoltan             ret = s->mcopt2;
5572a48dd7cSBALATON Zoltan             break;
5582a48dd7cSBALATON Zoltan         case 0x40: /* SDRAM_MB0CF */
5592a48dd7cSBALATON Zoltan             ret = 0x00008001;
5602a48dd7cSBALATON Zoltan             break;
5612a48dd7cSBALATON Zoltan         case 0x7A: /* SDRAM_DLCR */
5622a48dd7cSBALATON Zoltan             ret = 0x02000000;
5632a48dd7cSBALATON Zoltan             break;
5642a48dd7cSBALATON Zoltan         case 0xE1: /* SDR0_DDR0 */
5652a48dd7cSBALATON Zoltan             ret = SDR0_DDR0_DDRM_ENCODE(1) | SDR0_DDR0_DDRM_DDR1;
5662a48dd7cSBALATON Zoltan             break;
5672a48dd7cSBALATON Zoltan         default:
5682a48dd7cSBALATON Zoltan             break;
5692a48dd7cSBALATON Zoltan         }
5702a48dd7cSBALATON Zoltan         break;
5712a48dd7cSBALATON Zoltan     default:
5722a48dd7cSBALATON Zoltan         break;
5732a48dd7cSBALATON Zoltan     }
5742a48dd7cSBALATON Zoltan 
5752a48dd7cSBALATON Zoltan     return ret;
5762a48dd7cSBALATON Zoltan }
5772a48dd7cSBALATON Zoltan 
5782a48dd7cSBALATON Zoltan #define SDRAM_DDR2_MCOPT2_DCEN BIT(27)
5792a48dd7cSBALATON Zoltan 
5802a48dd7cSBALATON Zoltan static void sdram_ddr2_dcr_write(void *opaque, int dcrn, uint32_t val)
5812a48dd7cSBALATON Zoltan {
58261cfe0dfSBALATON Zoltan     Ppc4xxSdramDdr2State *s = opaque;
583424a660cSBALATON Zoltan     int i;
5842a48dd7cSBALATON Zoltan 
5852a48dd7cSBALATON Zoltan     switch (dcrn) {
5862a48dd7cSBALATON Zoltan     case SDRAM_R0BAS:
5872a48dd7cSBALATON Zoltan     case SDRAM_R1BAS:
5882a48dd7cSBALATON Zoltan     case SDRAM_R2BAS:
5892a48dd7cSBALATON Zoltan     case SDRAM_R3BAS:
5902a48dd7cSBALATON Zoltan     case SDRAM_CONF1HB:
5912a48dd7cSBALATON Zoltan     case SDRAM_CONF1LL:
5922a48dd7cSBALATON Zoltan     case SDRAM_CONFPATHB:
5932a48dd7cSBALATON Zoltan     case SDRAM_PLBADDULL:
5942a48dd7cSBALATON Zoltan     case SDRAM_PLBADDUHB:
5952a48dd7cSBALATON Zoltan         break;
5962a48dd7cSBALATON Zoltan     case SDRAM0_CFGADDR:
59761cfe0dfSBALATON Zoltan         s->addr = val;
5982a48dd7cSBALATON Zoltan         break;
5992a48dd7cSBALATON Zoltan     case SDRAM0_CFGDATA:
60061cfe0dfSBALATON Zoltan         switch (s->addr) {
6012a48dd7cSBALATON Zoltan         case 0x00: /* B0CR */
6022a48dd7cSBALATON Zoltan             break;
6032a48dd7cSBALATON Zoltan         case 0x21: /* SDRAM_MCOPT2 */
60461cfe0dfSBALATON Zoltan             if (!(s->mcopt2 & SDRAM_DDR2_MCOPT2_DCEN) &&
6052a48dd7cSBALATON Zoltan                 (val & SDRAM_DDR2_MCOPT2_DCEN)) {
6062a48dd7cSBALATON Zoltan                 trace_ppc4xx_sdram_enable("enable");
6072a48dd7cSBALATON Zoltan                 /* validate all RAM mappings */
608424a660cSBALATON Zoltan                 for (i = 0; i < s->nbanks; i++) {
609424a660cSBALATON Zoltan                     if (s->bank[i].size) {
610424a660cSBALATON Zoltan                         sdram_bank_set_bcr(&s->bank[i], s->bank[i].bcr,
611424a660cSBALATON Zoltan                                            s->bank[i].base, s->bank[i].size,
612424a660cSBALATON Zoltan                                            1);
613424a660cSBALATON Zoltan                     }
614424a660cSBALATON Zoltan                 }
61561cfe0dfSBALATON Zoltan                 s->mcopt2 |= SDRAM_DDR2_MCOPT2_DCEN;
61661cfe0dfSBALATON Zoltan             } else if ((s->mcopt2 & SDRAM_DDR2_MCOPT2_DCEN) &&
6172a48dd7cSBALATON Zoltan                        !(val & SDRAM_DDR2_MCOPT2_DCEN)) {
6182a48dd7cSBALATON Zoltan                 trace_ppc4xx_sdram_enable("disable");
6192a48dd7cSBALATON Zoltan                 /* invalidate all RAM mappings */
620424a660cSBALATON Zoltan                 for (i = 0; i < s->nbanks; i++) {
621424a660cSBALATON Zoltan                     if (s->bank[i].size) {
622424a660cSBALATON Zoltan                         sdram_bank_set_bcr(&s->bank[i], s->bank[i].bcr,
623424a660cSBALATON Zoltan                                            s->bank[i].base, s->bank[i].size,
624424a660cSBALATON Zoltan                                            0);
625424a660cSBALATON Zoltan                     }
626424a660cSBALATON Zoltan                 }
62761cfe0dfSBALATON Zoltan                 s->mcopt2 &= ~SDRAM_DDR2_MCOPT2_DCEN;
6282a48dd7cSBALATON Zoltan             }
6292a48dd7cSBALATON Zoltan             break;
6302a48dd7cSBALATON Zoltan         default:
6312a48dd7cSBALATON Zoltan             break;
6322a48dd7cSBALATON Zoltan         }
6332a48dd7cSBALATON Zoltan         break;
6342a48dd7cSBALATON Zoltan     default:
6352a48dd7cSBALATON Zoltan         break;
6362a48dd7cSBALATON Zoltan     }
6372a48dd7cSBALATON Zoltan }
6382a48dd7cSBALATON Zoltan 
6392a48dd7cSBALATON Zoltan static void ppc4xx_sdram_ddr2_reset(DeviceState *dev)
6402a48dd7cSBALATON Zoltan {
64161cfe0dfSBALATON Zoltan     Ppc4xxSdramDdr2State *s = PPC4xx_SDRAM_DDR2(dev);
6422a48dd7cSBALATON Zoltan 
64361cfe0dfSBALATON Zoltan     s->addr = 0;
64461cfe0dfSBALATON Zoltan     s->mcopt2 = 0;
6452a48dd7cSBALATON Zoltan }
6462a48dd7cSBALATON Zoltan 
6472a48dd7cSBALATON Zoltan static void ppc4xx_sdram_ddr2_realize(DeviceState *dev, Error **errp)
6482a48dd7cSBALATON Zoltan {
6492a48dd7cSBALATON Zoltan     Ppc4xxSdramDdr2State *s = PPC4xx_SDRAM_DDR2(dev);
6502a48dd7cSBALATON Zoltan     Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev);
6512a48dd7cSBALATON Zoltan     /*
6522a48dd7cSBALATON Zoltan      * SoC also has 4 GiB but that causes problem with 32 bit
6532a48dd7cSBALATON Zoltan      * builds (4*GiB overflows the 32 bit ram_addr_t).
6542a48dd7cSBALATON Zoltan      */
6552a48dd7cSBALATON Zoltan     const ram_addr_t valid_bank_sizes[] = {
6562a48dd7cSBALATON Zoltan         2 * GiB, 1 * GiB, 512 * MiB, 256 * MiB, 128 * MiB,
6572a48dd7cSBALATON Zoltan         64 * MiB, 32 * MiB, 16 * MiB, 8 * MiB, 0
6582a48dd7cSBALATON Zoltan     };
659424a660cSBALATON Zoltan     int i;
6602a48dd7cSBALATON Zoltan 
6612a48dd7cSBALATON Zoltan     if (s->nbanks < 1 || s->nbanks > 4) {
6622a48dd7cSBALATON Zoltan         error_setg(errp, "Invalid number of RAM banks");
6632a48dd7cSBALATON Zoltan         return;
6642a48dd7cSBALATON Zoltan     }
6652a48dd7cSBALATON Zoltan     if (!s->dram_mr) {
6662a48dd7cSBALATON Zoltan         error_setg(errp, "Missing dram memory region");
6672a48dd7cSBALATON Zoltan         return;
6682a48dd7cSBALATON Zoltan     }
6692a48dd7cSBALATON Zoltan     ppc4xx_sdram_banks(s->dram_mr, s->nbanks, s->bank, valid_bank_sizes);
670424a660cSBALATON Zoltan     for (i = 0; i < s->nbanks; i++) {
671424a660cSBALATON Zoltan         if (s->bank[i].size) {
672424a660cSBALATON Zoltan             s->bank[i].bcr = sdram_ddr2_bcr(s->bank[i].base, s->bank[i].size);
673424a660cSBALATON Zoltan             s->bank[i].bcr &= SDRAM_DDR2_BCR_MASK;
674424a660cSBALATON Zoltan             sdram_bank_set_bcr(&s->bank[i], s->bank[i].bcr,
675424a660cSBALATON Zoltan                                s->bank[i].base, s->bank[i].size, 0);
676424a660cSBALATON Zoltan         } else {
677424a660cSBALATON Zoltan             sdram_bank_set_bcr(&s->bank[i], 0, 0, 0, 0);
678424a660cSBALATON Zoltan         }
679424a660cSBALATON Zoltan         trace_ppc4xx_sdram_init(sdram_ddr2_base(s->bank[i].bcr),
680424a660cSBALATON Zoltan                                 sdram_ddr2_size(s->bank[i].bcr),
681424a660cSBALATON Zoltan                                 s->bank[i].bcr);
682424a660cSBALATON Zoltan     }
6832a48dd7cSBALATON Zoltan 
6842a48dd7cSBALATON Zoltan     ppc4xx_dcr_register(dcr, SDRAM0_CFGADDR,
6852a48dd7cSBALATON Zoltan                         s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write);
6862a48dd7cSBALATON Zoltan     ppc4xx_dcr_register(dcr, SDRAM0_CFGDATA,
6872a48dd7cSBALATON Zoltan                         s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write);
6882a48dd7cSBALATON Zoltan 
6892a48dd7cSBALATON Zoltan     ppc4xx_dcr_register(dcr, SDRAM_R0BAS,
6902a48dd7cSBALATON Zoltan                         s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write);
6912a48dd7cSBALATON Zoltan     ppc4xx_dcr_register(dcr, SDRAM_R1BAS,
6922a48dd7cSBALATON Zoltan                         s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write);
6932a48dd7cSBALATON Zoltan     ppc4xx_dcr_register(dcr, SDRAM_R2BAS,
6942a48dd7cSBALATON Zoltan                         s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write);
6952a48dd7cSBALATON Zoltan     ppc4xx_dcr_register(dcr, SDRAM_R3BAS,
6962a48dd7cSBALATON Zoltan                         s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write);
6972a48dd7cSBALATON Zoltan     ppc4xx_dcr_register(dcr, SDRAM_CONF1HB,
6982a48dd7cSBALATON Zoltan                         s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write);
6992a48dd7cSBALATON Zoltan     ppc4xx_dcr_register(dcr, SDRAM_PLBADDULL,
7002a48dd7cSBALATON Zoltan                         s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write);
7012a48dd7cSBALATON Zoltan     ppc4xx_dcr_register(dcr, SDRAM_CONF1LL,
7022a48dd7cSBALATON Zoltan                         s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write);
7032a48dd7cSBALATON Zoltan     ppc4xx_dcr_register(dcr, SDRAM_CONFPATHB,
7042a48dd7cSBALATON Zoltan                         s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write);
7052a48dd7cSBALATON Zoltan     ppc4xx_dcr_register(dcr, SDRAM_PLBADDUHB,
7062a48dd7cSBALATON Zoltan                         s, &sdram_ddr2_dcr_read, &sdram_ddr2_dcr_write);
7072a48dd7cSBALATON Zoltan }
7082a48dd7cSBALATON Zoltan 
7092a48dd7cSBALATON Zoltan static Property ppc4xx_sdram_ddr2_props[] = {
7102a48dd7cSBALATON Zoltan     DEFINE_PROP_LINK("dram", Ppc4xxSdramDdr2State, dram_mr, TYPE_MEMORY_REGION,
7112a48dd7cSBALATON Zoltan                      MemoryRegion *),
7122a48dd7cSBALATON Zoltan     DEFINE_PROP_UINT32("nbanks", Ppc4xxSdramDdr2State, nbanks, 4),
7132a48dd7cSBALATON Zoltan     DEFINE_PROP_END_OF_LIST(),
7142a48dd7cSBALATON Zoltan };
7152a48dd7cSBALATON Zoltan 
7162a48dd7cSBALATON Zoltan static void ppc4xx_sdram_ddr2_class_init(ObjectClass *oc, void *data)
7172a48dd7cSBALATON Zoltan {
7182a48dd7cSBALATON Zoltan     DeviceClass *dc = DEVICE_CLASS(oc);
7192a48dd7cSBALATON Zoltan 
7202a48dd7cSBALATON Zoltan     dc->realize = ppc4xx_sdram_ddr2_realize;
7212a48dd7cSBALATON Zoltan     dc->reset = ppc4xx_sdram_ddr2_reset;
7222a48dd7cSBALATON Zoltan     /* Reason: only works as function of a ppc4xx SoC */
7232a48dd7cSBALATON Zoltan     dc->user_creatable = false;
7242a48dd7cSBALATON Zoltan     device_class_set_props(dc, ppc4xx_sdram_ddr2_props);
7252a48dd7cSBALATON Zoltan }
7262a48dd7cSBALATON Zoltan 
7272a48dd7cSBALATON Zoltan void ppc4xx_sdram_ddr2_enable(Ppc4xxSdramDdr2State *s)
7282a48dd7cSBALATON Zoltan {
7292a48dd7cSBALATON Zoltan     sdram_ddr2_dcr_write(s, SDRAM0_CFGADDR, 0x21);
7302a48dd7cSBALATON Zoltan     sdram_ddr2_dcr_write(s, SDRAM0_CFGDATA, 0x08000000);
7312a48dd7cSBALATON Zoltan }
7322a48dd7cSBALATON Zoltan 
7332a48dd7cSBALATON Zoltan static const TypeInfo ppc4xx_sdram_types[] = {
7342a48dd7cSBALATON Zoltan     {
735fa446fc5SBALATON Zoltan         .name           = TYPE_PPC4xx_SDRAM_DDR,
736fa446fc5SBALATON Zoltan         .parent         = TYPE_PPC4xx_DCR_DEVICE,
737fa446fc5SBALATON Zoltan         .instance_size  = sizeof(Ppc4xxSdramDdrState),
738fa446fc5SBALATON Zoltan         .class_init     = ppc4xx_sdram_ddr_class_init,
739fa446fc5SBALATON Zoltan     }, {
7402a48dd7cSBALATON Zoltan         .name           = TYPE_PPC4xx_SDRAM_DDR2,
7412a48dd7cSBALATON Zoltan         .parent         = TYPE_PPC4xx_DCR_DEVICE,
7422a48dd7cSBALATON Zoltan         .instance_size  = sizeof(Ppc4xxSdramDdr2State),
7432a48dd7cSBALATON Zoltan         .class_init     = ppc4xx_sdram_ddr2_class_init,
7442a48dd7cSBALATON Zoltan     }
7452a48dd7cSBALATON Zoltan };
7462a48dd7cSBALATON Zoltan 
7472a48dd7cSBALATON Zoltan DEFINE_TYPES(ppc4xx_sdram_types)
748