qemu/hw/ppc/ppc4xx_devs.c
<<
>>
Prefs
   1/*
   2 * QEMU PowerPC 4xx embedded processors shared devices emulation
   3 *
   4 * Copyright (c) 2007 Jocelyn Mayer
   5 *
   6 * Permission is hereby granted, free of charge, to any person obtaining a copy
   7 * of this software and associated documentation files (the "Software"), to deal
   8 * in the Software without restriction, including without limitation the rights
   9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 * copies of the Software, and to permit persons to whom the Software is
  11 * furnished to do so, subject to the following conditions:
  12 *
  13 * The above copyright notice and this permission notice shall be included in
  14 * all copies or substantial portions of the Software.
  15 *
  16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 * THE SOFTWARE.
  23 */
  24#include "qemu/osdep.h"
  25#include "qemu/units.h"
  26#include "cpu.h"
  27#include "hw/hw.h"
  28#include "hw/ppc/ppc.h"
  29#include "hw/ppc/ppc4xx.h"
  30#include "hw/boards.h"
  31#include "qemu/log.h"
  32#include "exec/address-spaces.h"
  33#include "qemu/error-report.h"
  34
  35#define DEBUG_UIC
  36
  37
  38#ifdef DEBUG_UIC
  39#  define LOG_UIC(...) qemu_log_mask(CPU_LOG_INT, ## __VA_ARGS__)
  40#else
  41#  define LOG_UIC(...) do { } while (0)
  42#endif
  43
  44static void ppc4xx_reset(void *opaque)
  45{
  46    PowerPCCPU *cpu = opaque;
  47
  48    cpu_reset(CPU(cpu));
  49}
  50
  51/*****************************************************************************/
  52/* Generic PowerPC 4xx processor instantiation */
  53PowerPCCPU *ppc4xx_init(const char *cpu_type,
  54                        clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
  55                        uint32_t sysclk)
  56{
  57    PowerPCCPU *cpu;
  58    CPUPPCState *env;
  59
  60    /* init CPUs */
  61    cpu = POWERPC_CPU(cpu_create(cpu_type));
  62    env = &cpu->env;
  63
  64    cpu_clk->cb = NULL; /* We don't care about CPU clock frequency changes */
  65    cpu_clk->opaque = env;
  66    /* Set time-base frequency to sysclk */
  67    tb_clk->cb = ppc_40x_timers_init(env, sysclk, PPC_INTERRUPT_PIT);
  68    tb_clk->opaque = env;
  69    ppc_dcr_init(env, NULL, NULL);
  70    /* Register qemu callbacks */
  71    qemu_register_reset(ppc4xx_reset, cpu);
  72
  73    return cpu;
  74}
  75
  76/*****************************************************************************/
  77/* "Universal" Interrupt controller */
  78enum {
  79    DCR_UICSR  = 0x000,
  80    DCR_UICSRS = 0x001,
  81    DCR_UICER  = 0x002,
  82    DCR_UICCR  = 0x003,
  83    DCR_UICPR  = 0x004,
  84    DCR_UICTR  = 0x005,
  85    DCR_UICMSR = 0x006,
  86    DCR_UICVR  = 0x007,
  87    DCR_UICVCR = 0x008,
  88    DCR_UICMAX = 0x009,
  89};
  90
  91#define UIC_MAX_IRQ 32
  92typedef struct ppcuic_t ppcuic_t;
  93struct ppcuic_t {
  94    uint32_t dcr_base;
  95    int use_vectors;
  96    uint32_t level;  /* Remembers the state of level-triggered interrupts. */
  97    uint32_t uicsr;  /* Status register */
  98    uint32_t uicer;  /* Enable register */
  99    uint32_t uiccr;  /* Critical register */
 100    uint32_t uicpr;  /* Polarity register */
 101    uint32_t uictr;  /* Triggering register */
 102    uint32_t uicvcr; /* Vector configuration register */
 103    uint32_t uicvr;
 104    qemu_irq *irqs;
 105};
 106
 107static void ppcuic_trigger_irq (ppcuic_t *uic)
 108{
 109    uint32_t ir, cr;
 110    int start, end, inc, i;
 111
 112    /* Trigger interrupt if any is pending */
 113    ir = uic->uicsr & uic->uicer & (~uic->uiccr);
 114    cr = uic->uicsr & uic->uicer & uic->uiccr;
 115    LOG_UIC("%s: uicsr %08" PRIx32 " uicer %08" PRIx32
 116                " uiccr %08" PRIx32 "\n"
 117                "   %08" PRIx32 " ir %08" PRIx32 " cr %08" PRIx32 "\n",
 118                __func__, uic->uicsr, uic->uicer, uic->uiccr,
 119                uic->uicsr & uic->uicer, ir, cr);
 120    if (ir != 0x0000000) {
 121        LOG_UIC("Raise UIC interrupt\n");
 122        qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_INT]);
 123    } else {
 124        LOG_UIC("Lower UIC interrupt\n");
 125        qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_INT]);
 126    }
 127    /* Trigger critical interrupt if any is pending and update vector */
 128    if (cr != 0x0000000) {
 129        qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_CINT]);
 130        if (uic->use_vectors) {
 131            /* Compute critical IRQ vector */
 132            if (uic->uicvcr & 1) {
 133                start = 31;
 134                end = 0;
 135                inc = -1;
 136            } else {
 137                start = 0;
 138                end = 31;
 139                inc = 1;
 140            }
 141            uic->uicvr = uic->uicvcr & 0xFFFFFFFC;
 142            for (i = start; i <= end; i += inc) {
 143                if (cr & (1 << i)) {
 144                    uic->uicvr += (i - start) * 512 * inc;
 145                    break;
 146                }
 147            }
 148        }
 149        LOG_UIC("Raise UIC critical interrupt - "
 150                    "vector %08" PRIx32 "\n", uic->uicvr);
 151    } else {
 152        LOG_UIC("Lower UIC critical interrupt\n");
 153        qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_CINT]);
 154        uic->uicvr = 0x00000000;
 155    }
 156}
 157
 158static void ppcuic_set_irq (void *opaque, int irq_num, int level)
 159{
 160    ppcuic_t *uic;
 161    uint32_t mask, sr;
 162
 163    uic = opaque;
 164    mask = 1U << (31-irq_num);
 165    LOG_UIC("%s: irq %d level %d uicsr %08" PRIx32
 166                " mask %08" PRIx32 " => %08" PRIx32 " %08" PRIx32 "\n",
 167                __func__, irq_num, level,
 168                uic->uicsr, mask, uic->uicsr & mask, level << irq_num);
 169    if (irq_num < 0 || irq_num > 31)
 170        return;
 171    sr = uic->uicsr;
 172
 173    /* Update status register */
 174    if (uic->uictr & mask) {
 175        /* Edge sensitive interrupt */
 176        if (level == 1)
 177            uic->uicsr |= mask;
 178    } else {
 179        /* Level sensitive interrupt */
 180        if (level == 1) {
 181            uic->uicsr |= mask;
 182            uic->level |= mask;
 183        } else {
 184            uic->uicsr &= ~mask;
 185            uic->level &= ~mask;
 186        }
 187    }
 188    LOG_UIC("%s: irq %d level %d sr %" PRIx32 " => "
 189                "%08" PRIx32 "\n", __func__, irq_num, level, uic->uicsr, sr);
 190    if (sr != uic->uicsr)
 191        ppcuic_trigger_irq(uic);
 192}
 193
 194static uint32_t dcr_read_uic (void *opaque, int dcrn)
 195{
 196    ppcuic_t *uic;
 197    uint32_t ret;
 198
 199    uic = opaque;
 200    dcrn -= uic->dcr_base;
 201    switch (dcrn) {
 202    case DCR_UICSR:
 203    case DCR_UICSRS:
 204        ret = uic->uicsr;
 205        break;
 206    case DCR_UICER:
 207        ret = uic->uicer;
 208        break;
 209    case DCR_UICCR:
 210        ret = uic->uiccr;
 211        break;
 212    case DCR_UICPR:
 213        ret = uic->uicpr;
 214        break;
 215    case DCR_UICTR:
 216        ret = uic->uictr;
 217        break;
 218    case DCR_UICMSR:
 219        ret = uic->uicsr & uic->uicer;
 220        break;
 221    case DCR_UICVR:
 222        if (!uic->use_vectors)
 223            goto no_read;
 224        ret = uic->uicvr;
 225        break;
 226    case DCR_UICVCR:
 227        if (!uic->use_vectors)
 228            goto no_read;
 229        ret = uic->uicvcr;
 230        break;
 231    default:
 232    no_read:
 233        ret = 0x00000000;
 234        break;
 235    }
 236
 237    return ret;
 238}
 239
 240static void dcr_write_uic (void *opaque, int dcrn, uint32_t val)
 241{
 242    ppcuic_t *uic;
 243
 244    uic = opaque;
 245    dcrn -= uic->dcr_base;
 246    LOG_UIC("%s: dcr %d val 0x%x\n", __func__, dcrn, val);
 247    switch (dcrn) {
 248    case DCR_UICSR:
 249        uic->uicsr &= ~val;
 250        uic->uicsr |= uic->level;
 251        ppcuic_trigger_irq(uic);
 252        break;
 253    case DCR_UICSRS:
 254        uic->uicsr |= val;
 255        ppcuic_trigger_irq(uic);
 256        break;
 257    case DCR_UICER:
 258        uic->uicer = val;
 259        ppcuic_trigger_irq(uic);
 260        break;
 261    case DCR_UICCR:
 262        uic->uiccr = val;
 263        ppcuic_trigger_irq(uic);
 264        break;
 265    case DCR_UICPR:
 266        uic->uicpr = val;
 267        break;
 268    case DCR_UICTR:
 269        uic->uictr = val;
 270        ppcuic_trigger_irq(uic);
 271        break;
 272    case DCR_UICMSR:
 273        break;
 274    case DCR_UICVR:
 275        break;
 276    case DCR_UICVCR:
 277        uic->uicvcr = val & 0xFFFFFFFD;
 278        ppcuic_trigger_irq(uic);
 279        break;
 280    }
 281}
 282
 283static void ppcuic_reset (void *opaque)
 284{
 285    ppcuic_t *uic;
 286
 287    uic = opaque;
 288    uic->uiccr = 0x00000000;
 289    uic->uicer = 0x00000000;
 290    uic->uicpr = 0x00000000;
 291    uic->uicsr = 0x00000000;
 292    uic->uictr = 0x00000000;
 293    if (uic->use_vectors) {
 294        uic->uicvcr = 0x00000000;
 295        uic->uicvr = 0x0000000;
 296    }
 297}
 298
 299qemu_irq *ppcuic_init (CPUPPCState *env, qemu_irq *irqs,
 300                       uint32_t dcr_base, int has_ssr, int has_vr)
 301{
 302    ppcuic_t *uic;
 303    int i;
 304
 305    uic = g_malloc0(sizeof(ppcuic_t));
 306    uic->dcr_base = dcr_base;
 307    uic->irqs = irqs;
 308    if (has_vr)
 309        uic->use_vectors = 1;
 310    for (i = 0; i < DCR_UICMAX; i++) {
 311        ppc_dcr_register(env, dcr_base + i, uic,
 312                         &dcr_read_uic, &dcr_write_uic);
 313    }
 314    qemu_register_reset(ppcuic_reset, uic);
 315
 316    return qemu_allocate_irqs(&ppcuic_set_irq, uic, UIC_MAX_IRQ);
 317}
 318
 319/*****************************************************************************/
 320/* SDRAM controller */
 321typedef struct ppc4xx_sdram_t ppc4xx_sdram_t;
 322struct ppc4xx_sdram_t {
 323    uint32_t addr;
 324    int nbanks;
 325    MemoryRegion containers[4]; /* used for clipping */
 326    MemoryRegion *ram_memories;
 327    hwaddr ram_bases[4];
 328    hwaddr ram_sizes[4];
 329    uint32_t besr0;
 330    uint32_t besr1;
 331    uint32_t bear;
 332    uint32_t cfg;
 333    uint32_t status;
 334    uint32_t rtr;
 335    uint32_t pmit;
 336    uint32_t bcr[4];
 337    uint32_t tr;
 338    uint32_t ecccfg;
 339    uint32_t eccesr;
 340    qemu_irq irq;
 341};
 342
 343enum {
 344    SDRAM0_CFGADDR = 0x010,
 345    SDRAM0_CFGDATA = 0x011,
 346};
 347
 348/* XXX: TOFIX: some patches have made this code become inconsistent:
 349 *      there are type inconsistencies, mixing hwaddr, target_ulong
 350 *      and uint32_t
 351 */
 352static uint32_t sdram_bcr (hwaddr ram_base,
 353                           hwaddr ram_size)
 354{
 355    uint32_t bcr;
 356
 357    switch (ram_size) {
 358    case 4 * MiB:
 359        bcr = 0x00000000;
 360        break;
 361    case 8 * MiB:
 362        bcr = 0x00020000;
 363        break;
 364    case 16 * MiB:
 365        bcr = 0x00040000;
 366        break;
 367    case 32 * MiB:
 368        bcr = 0x00060000;
 369        break;
 370    case 64 * MiB:
 371        bcr = 0x00080000;
 372        break;
 373    case 128 * MiB:
 374        bcr = 0x000A0000;
 375        break;
 376    case 256 * MiB:
 377        bcr = 0x000C0000;
 378        break;
 379    default:
 380        printf("%s: invalid RAM size " TARGET_FMT_plx "\n", __func__,
 381               ram_size);
 382        return 0x00000000;
 383    }
 384    bcr |= ram_base & 0xFF800000;
 385    bcr |= 1;
 386
 387    return bcr;
 388}
 389
 390static inline hwaddr sdram_base(uint32_t bcr)
 391{
 392    return bcr & 0xFF800000;
 393}
 394
 395static target_ulong sdram_size (uint32_t bcr)
 396{
 397    target_ulong size;
 398    int sh;
 399
 400    sh = (bcr >> 17) & 0x7;
 401    if (sh == 7)
 402        size = -1;
 403    else
 404        size = (4 * MiB) << sh;
 405
 406    return size;
 407}
 408
 409static void sdram_set_bcr(ppc4xx_sdram_t *sdram,
 410                          uint32_t *bcrp, uint32_t bcr, int enabled)
 411{
 412    unsigned n = bcrp - sdram->bcr;
 413
 414    if (*bcrp & 0x00000001) {
 415        /* Unmap RAM */
 416#ifdef DEBUG_SDRAM
 417        printf("%s: unmap RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
 418               __func__, sdram_base(*bcrp), sdram_size(*bcrp));
 419#endif
 420        memory_region_del_subregion(get_system_memory(),
 421                                    &sdram->containers[n]);
 422        memory_region_del_subregion(&sdram->containers[n],
 423                                    &sdram->ram_memories[n]);
 424        object_unparent(OBJECT(&sdram->containers[n]));
 425    }
 426    *bcrp = bcr & 0xFFDEE001;
 427    if (enabled && (bcr & 0x00000001)) {
 428#ifdef DEBUG_SDRAM
 429        printf("%s: Map RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
 430               __func__, sdram_base(bcr), sdram_size(bcr));
 431#endif
 432        memory_region_init(&sdram->containers[n], NULL, "sdram-containers",
 433                           sdram_size(bcr));
 434        memory_region_add_subregion(&sdram->containers[n], 0,
 435                                    &sdram->ram_memories[n]);
 436        memory_region_add_subregion(get_system_memory(),
 437                                    sdram_base(bcr),
 438                                    &sdram->containers[n]);
 439    }
 440}
 441
 442static void sdram_map_bcr (ppc4xx_sdram_t *sdram)
 443{
 444    int i;
 445
 446    for (i = 0; i < sdram->nbanks; i++) {
 447        if (sdram->ram_sizes[i] != 0) {
 448            sdram_set_bcr(sdram,
 449                          &sdram->bcr[i],
 450                          sdram_bcr(sdram->ram_bases[i], sdram->ram_sizes[i]),
 451                          1);
 452        } else {
 453            sdram_set_bcr(sdram, &sdram->bcr[i], 0x00000000, 0);
 454        }
 455    }
 456}
 457
 458static void sdram_unmap_bcr (ppc4xx_sdram_t *sdram)
 459{
 460    int i;
 461
 462    for (i = 0; i < sdram->nbanks; i++) {
 463#ifdef DEBUG_SDRAM
 464        printf("%s: Unmap RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
 465               __func__, sdram_base(sdram->bcr[i]), sdram_size(sdram->bcr[i]));
 466#endif
 467        memory_region_del_subregion(get_system_memory(),
 468                                    &sdram->ram_memories[i]);
 469    }
 470}
 471
 472static uint32_t dcr_read_sdram (void *opaque, int dcrn)
 473{
 474    ppc4xx_sdram_t *sdram;
 475    uint32_t ret;
 476
 477    sdram = opaque;
 478    switch (dcrn) {
 479    case SDRAM0_CFGADDR:
 480        ret = sdram->addr;
 481        break;
 482    case SDRAM0_CFGDATA:
 483        switch (sdram->addr) {
 484        case 0x00: /* SDRAM_BESR0 */
 485            ret = sdram->besr0;
 486            break;
 487        case 0x08: /* SDRAM_BESR1 */
 488            ret = sdram->besr1;
 489            break;
 490        case 0x10: /* SDRAM_BEAR */
 491            ret = sdram->bear;
 492            break;
 493        case 0x20: /* SDRAM_CFG */
 494            ret = sdram->cfg;
 495            break;
 496        case 0x24: /* SDRAM_STATUS */
 497            ret = sdram->status;
 498            break;
 499        case 0x30: /* SDRAM_RTR */
 500            ret = sdram->rtr;
 501            break;
 502        case 0x34: /* SDRAM_PMIT */
 503            ret = sdram->pmit;
 504            break;
 505        case 0x40: /* SDRAM_B0CR */
 506            ret = sdram->bcr[0];
 507            break;
 508        case 0x44: /* SDRAM_B1CR */
 509            ret = sdram->bcr[1];
 510            break;
 511        case 0x48: /* SDRAM_B2CR */
 512            ret = sdram->bcr[2];
 513            break;
 514        case 0x4C: /* SDRAM_B3CR */
 515            ret = sdram->bcr[3];
 516            break;
 517        case 0x80: /* SDRAM_TR */
 518            ret = -1; /* ? */
 519            break;
 520        case 0x94: /* SDRAM_ECCCFG */
 521            ret = sdram->ecccfg;
 522            break;
 523        case 0x98: /* SDRAM_ECCESR */
 524            ret = sdram->eccesr;
 525            break;
 526        default: /* Error */
 527            ret = -1;
 528            break;
 529        }
 530        break;
 531    default:
 532        /* Avoid gcc warning */
 533        ret = 0x00000000;
 534        break;
 535    }
 536
 537    return ret;
 538}
 539
 540static void dcr_write_sdram (void *opaque, int dcrn, uint32_t val)
 541{
 542    ppc4xx_sdram_t *sdram;
 543
 544    sdram = opaque;
 545    switch (dcrn) {
 546    case SDRAM0_CFGADDR:
 547        sdram->addr = val;
 548        break;
 549    case SDRAM0_CFGDATA:
 550        switch (sdram->addr) {
 551        case 0x00: /* SDRAM_BESR0 */
 552            sdram->besr0 &= ~val;
 553            break;
 554        case 0x08: /* SDRAM_BESR1 */
 555            sdram->besr1 &= ~val;
 556            break;
 557        case 0x10: /* SDRAM_BEAR */
 558            sdram->bear = val;
 559            break;
 560        case 0x20: /* SDRAM_CFG */
 561            val &= 0xFFE00000;
 562            if (!(sdram->cfg & 0x80000000) && (val & 0x80000000)) {
 563#ifdef DEBUG_SDRAM
 564                printf("%s: enable SDRAM controller\n", __func__);
 565#endif
 566                /* validate all RAM mappings */
 567                sdram_map_bcr(sdram);
 568                sdram->status &= ~0x80000000;
 569            } else if ((sdram->cfg & 0x80000000) && !(val & 0x80000000)) {
 570#ifdef DEBUG_SDRAM
 571                printf("%s: disable SDRAM controller\n", __func__);
 572#endif
 573                /* invalidate all RAM mappings */
 574                sdram_unmap_bcr(sdram);
 575                sdram->status |= 0x80000000;
 576            }
 577            if (!(sdram->cfg & 0x40000000) && (val & 0x40000000))
 578                sdram->status |= 0x40000000;
 579            else if ((sdram->cfg & 0x40000000) && !(val & 0x40000000))
 580                sdram->status &= ~0x40000000;
 581            sdram->cfg = val;
 582            break;
 583        case 0x24: /* SDRAM_STATUS */
 584            /* Read-only register */
 585            break;
 586        case 0x30: /* SDRAM_RTR */
 587            sdram->rtr = val & 0x3FF80000;
 588            break;
 589        case 0x34: /* SDRAM_PMIT */
 590            sdram->pmit = (val & 0xF8000000) | 0x07C00000;
 591            break;
 592        case 0x40: /* SDRAM_B0CR */
 593            sdram_set_bcr(sdram, &sdram->bcr[0], val, sdram->cfg & 0x80000000);
 594            break;
 595        case 0x44: /* SDRAM_B1CR */
 596            sdram_set_bcr(sdram, &sdram->bcr[1], val, sdram->cfg & 0x80000000);
 597            break;
 598        case 0x48: /* SDRAM_B2CR */
 599            sdram_set_bcr(sdram, &sdram->bcr[2], val, sdram->cfg & 0x80000000);
 600            break;
 601        case 0x4C: /* SDRAM_B3CR */
 602            sdram_set_bcr(sdram, &sdram->bcr[3], val, sdram->cfg & 0x80000000);
 603            break;
 604        case 0x80: /* SDRAM_TR */
 605            sdram->tr = val & 0x018FC01F;
 606            break;
 607        case 0x94: /* SDRAM_ECCCFG */
 608            sdram->ecccfg = val & 0x00F00000;
 609            break;
 610        case 0x98: /* SDRAM_ECCESR */
 611            val &= 0xFFF0F000;
 612            if (sdram->eccesr == 0 && val != 0)
 613                qemu_irq_raise(sdram->irq);
 614            else if (sdram->eccesr != 0 && val == 0)
 615                qemu_irq_lower(sdram->irq);
 616            sdram->eccesr = val;
 617            break;
 618        default: /* Error */
 619            break;
 620        }
 621        break;
 622    }
 623}
 624
 625static void sdram_reset (void *opaque)
 626{
 627    ppc4xx_sdram_t *sdram;
 628
 629    sdram = opaque;
 630    sdram->addr = 0x00000000;
 631    sdram->bear = 0x00000000;
 632    sdram->besr0 = 0x00000000; /* No error */
 633    sdram->besr1 = 0x00000000; /* No error */
 634    sdram->cfg = 0x00000000;
 635    sdram->ecccfg = 0x00000000; /* No ECC */
 636    sdram->eccesr = 0x00000000; /* No error */
 637    sdram->pmit = 0x07C00000;
 638    sdram->rtr = 0x05F00000;
 639    sdram->tr = 0x00854009;
 640    /* We pre-initialize RAM banks */
 641    sdram->status = 0x00000000;
 642    sdram->cfg = 0x00800000;
 643}
 644
 645void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks,
 646                        MemoryRegion *ram_memories,
 647                        hwaddr *ram_bases,
 648                        hwaddr *ram_sizes,
 649                        int do_init)
 650{
 651    ppc4xx_sdram_t *sdram;
 652
 653    sdram = g_malloc0(sizeof(ppc4xx_sdram_t));
 654    sdram->irq = irq;
 655    sdram->nbanks = nbanks;
 656    sdram->ram_memories = ram_memories;
 657    memset(sdram->ram_bases, 0, 4 * sizeof(hwaddr));
 658    memcpy(sdram->ram_bases, ram_bases,
 659           nbanks * sizeof(hwaddr));
 660    memset(sdram->ram_sizes, 0, 4 * sizeof(hwaddr));
 661    memcpy(sdram->ram_sizes, ram_sizes,
 662           nbanks * sizeof(hwaddr));
 663    qemu_register_reset(&sdram_reset, sdram);
 664    ppc_dcr_register(env, SDRAM0_CFGADDR,
 665                     sdram, &dcr_read_sdram, &dcr_write_sdram);
 666    ppc_dcr_register(env, SDRAM0_CFGDATA,
 667                     sdram, &dcr_read_sdram, &dcr_write_sdram);
 668    if (do_init)
 669        sdram_map_bcr(sdram);
 670}
 671
 672/* Fill in consecutive SDRAM banks with 'ram_size' bytes of memory.
 673 *
 674 * sdram_bank_sizes[] must be 0-terminated.
 675 *
 676 * The 4xx SDRAM controller supports a small number of banks, and each bank
 677 * must be one of a small set of sizes. The number of banks and the supported
 678 * sizes varies by SoC. */
 679ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
 680                               MemoryRegion ram_memories[],
 681                               hwaddr ram_bases[],
 682                               hwaddr ram_sizes[],
 683                               const unsigned int sdram_bank_sizes[])
 684{
 685    MemoryRegion *ram = g_malloc0(sizeof(*ram));
 686    ram_addr_t size_left = ram_size;
 687    ram_addr_t base = 0;
 688    unsigned int bank_size;
 689    int i;
 690    int j;
 691
 692    for (i = 0; i < nr_banks; i++) {
 693        for (j = 0; sdram_bank_sizes[j] != 0; j++) {
 694            bank_size = sdram_bank_sizes[j];
 695            if (bank_size <= size_left) {
 696                size_left -= bank_size;
 697            }
 698        }
 699        if (!size_left) {
 700            /* No need to use the remaining banks. */
 701            break;
 702        }
 703    }
 704
 705    ram_size -= size_left;
 706    if (size_left) {
 707        error_report("Truncating memory to %" PRId64 " MiB to fit SDRAM"
 708                     " controller limits", ram_size / MiB);
 709    }
 710
 711    memory_region_allocate_system_memory(ram, NULL, "ppc4xx.sdram", ram_size);
 712
 713    size_left = ram_size;
 714    for (i = 0; i < nr_banks && size_left; i++) {
 715        for (j = 0; sdram_bank_sizes[j] != 0; j++) {
 716            bank_size = sdram_bank_sizes[j];
 717
 718            if (bank_size <= size_left) {
 719                char name[32];
 720                snprintf(name, sizeof(name), "ppc4xx.sdram%d", i);
 721                memory_region_init_alias(&ram_memories[i], NULL, name, ram,
 722                                         base, bank_size);
 723                ram_bases[i] = base;
 724                ram_sizes[i] = bank_size;
 725                base += bank_size;
 726                size_left -= bank_size;
 727                break;
 728            }
 729        }
 730    }
 731
 732    return ram_size;
 733}
 734
 735/*****************************************************************************/
 736/* MAL */
 737
 738enum {
 739    MAL0_CFG      = 0x180,
 740    MAL0_ESR      = 0x181,
 741    MAL0_IER      = 0x182,
 742    MAL0_TXCASR   = 0x184,
 743    MAL0_TXCARR   = 0x185,
 744    MAL0_TXEOBISR = 0x186,
 745    MAL0_TXDEIR   = 0x187,
 746    MAL0_RXCASR   = 0x190,
 747    MAL0_RXCARR   = 0x191,
 748    MAL0_RXEOBISR = 0x192,
 749    MAL0_RXDEIR   = 0x193,
 750    MAL0_TXCTP0R  = 0x1A0,
 751    MAL0_RXCTP0R  = 0x1C0,
 752    MAL0_RCBS0    = 0x1E0,
 753    MAL0_RCBS1    = 0x1E1,
 754};
 755
 756typedef struct ppc4xx_mal_t ppc4xx_mal_t;
 757struct ppc4xx_mal_t {
 758    qemu_irq irqs[4];
 759    uint32_t cfg;
 760    uint32_t esr;
 761    uint32_t ier;
 762    uint32_t txcasr;
 763    uint32_t txcarr;
 764    uint32_t txeobisr;
 765    uint32_t txdeir;
 766    uint32_t rxcasr;
 767    uint32_t rxcarr;
 768    uint32_t rxeobisr;
 769    uint32_t rxdeir;
 770    uint32_t *txctpr;
 771    uint32_t *rxctpr;
 772    uint32_t *rcbs;
 773    uint8_t  txcnum;
 774    uint8_t  rxcnum;
 775};
 776
 777static void ppc4xx_mal_reset(void *opaque)
 778{
 779    ppc4xx_mal_t *mal;
 780
 781    mal = opaque;
 782    mal->cfg = 0x0007C000;
 783    mal->esr = 0x00000000;
 784    mal->ier = 0x00000000;
 785    mal->rxcasr = 0x00000000;
 786    mal->rxdeir = 0x00000000;
 787    mal->rxeobisr = 0x00000000;
 788    mal->txcasr = 0x00000000;
 789    mal->txdeir = 0x00000000;
 790    mal->txeobisr = 0x00000000;
 791}
 792
 793static uint32_t dcr_read_mal(void *opaque, int dcrn)
 794{
 795    ppc4xx_mal_t *mal;
 796    uint32_t ret;
 797
 798    mal = opaque;
 799    switch (dcrn) {
 800    case MAL0_CFG:
 801        ret = mal->cfg;
 802        break;
 803    case MAL0_ESR:
 804        ret = mal->esr;
 805        break;
 806    case MAL0_IER:
 807        ret = mal->ier;
 808        break;
 809    case MAL0_TXCASR:
 810        ret = mal->txcasr;
 811        break;
 812    case MAL0_TXCARR:
 813        ret = mal->txcarr;
 814        break;
 815    case MAL0_TXEOBISR:
 816        ret = mal->txeobisr;
 817        break;
 818    case MAL0_TXDEIR:
 819        ret = mal->txdeir;
 820        break;
 821    case MAL0_RXCASR:
 822        ret = mal->rxcasr;
 823        break;
 824    case MAL0_RXCARR:
 825        ret = mal->rxcarr;
 826        break;
 827    case MAL0_RXEOBISR:
 828        ret = mal->rxeobisr;
 829        break;
 830    case MAL0_RXDEIR:
 831        ret = mal->rxdeir;
 832        break;
 833    default:
 834        ret = 0;
 835        break;
 836    }
 837    if (dcrn >= MAL0_TXCTP0R && dcrn < MAL0_TXCTP0R + mal->txcnum) {
 838        ret = mal->txctpr[dcrn - MAL0_TXCTP0R];
 839    }
 840    if (dcrn >= MAL0_RXCTP0R && dcrn < MAL0_RXCTP0R + mal->rxcnum) {
 841        ret = mal->rxctpr[dcrn - MAL0_RXCTP0R];
 842    }
 843    if (dcrn >= MAL0_RCBS0 && dcrn < MAL0_RCBS0 + mal->rxcnum) {
 844        ret = mal->rcbs[dcrn - MAL0_RCBS0];
 845    }
 846
 847    return ret;
 848}
 849
 850static void dcr_write_mal(void *opaque, int dcrn, uint32_t val)
 851{
 852    ppc4xx_mal_t *mal;
 853
 854    mal = opaque;
 855    switch (dcrn) {
 856    case MAL0_CFG:
 857        if (val & 0x80000000) {
 858            ppc4xx_mal_reset(mal);
 859        }
 860        mal->cfg = val & 0x00FFC087;
 861        break;
 862    case MAL0_ESR:
 863        /* Read/clear */
 864        mal->esr &= ~val;
 865        break;
 866    case MAL0_IER:
 867        mal->ier = val & 0x0000001F;
 868        break;
 869    case MAL0_TXCASR:
 870        mal->txcasr = val & 0xF0000000;
 871        break;
 872    case MAL0_TXCARR:
 873        mal->txcarr = val & 0xF0000000;
 874        break;
 875    case MAL0_TXEOBISR:
 876        /* Read/clear */
 877        mal->txeobisr &= ~val;
 878        break;
 879    case MAL0_TXDEIR:
 880        /* Read/clear */
 881        mal->txdeir &= ~val;
 882        break;
 883    case MAL0_RXCASR:
 884        mal->rxcasr = val & 0xC0000000;
 885        break;
 886    case MAL0_RXCARR:
 887        mal->rxcarr = val & 0xC0000000;
 888        break;
 889    case MAL0_RXEOBISR:
 890        /* Read/clear */
 891        mal->rxeobisr &= ~val;
 892        break;
 893    case MAL0_RXDEIR:
 894        /* Read/clear */
 895        mal->rxdeir &= ~val;
 896        break;
 897    }
 898    if (dcrn >= MAL0_TXCTP0R && dcrn < MAL0_TXCTP0R + mal->txcnum) {
 899        mal->txctpr[dcrn - MAL0_TXCTP0R] = val;
 900    }
 901    if (dcrn >= MAL0_RXCTP0R && dcrn < MAL0_RXCTP0R + mal->rxcnum) {
 902        mal->rxctpr[dcrn - MAL0_RXCTP0R] = val;
 903    }
 904    if (dcrn >= MAL0_RCBS0 && dcrn < MAL0_RCBS0 + mal->rxcnum) {
 905        mal->rcbs[dcrn - MAL0_RCBS0] = val & 0x000000FF;
 906    }
 907}
 908
 909void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, uint8_t rxcnum,
 910                     qemu_irq irqs[4])
 911{
 912    ppc4xx_mal_t *mal;
 913    int i;
 914
 915    assert(txcnum <= 32 && rxcnum <= 32);
 916    mal = g_malloc0(sizeof(*mal));
 917    mal->txcnum = txcnum;
 918    mal->rxcnum = rxcnum;
 919    mal->txctpr = g_new0(uint32_t, txcnum);
 920    mal->rxctpr = g_new0(uint32_t, rxcnum);
 921    mal->rcbs = g_new0(uint32_t, rxcnum);
 922    for (i = 0; i < 4; i++) {
 923        mal->irqs[i] = irqs[i];
 924    }
 925    qemu_register_reset(&ppc4xx_mal_reset, mal);
 926    ppc_dcr_register(env, MAL0_CFG,
 927                     mal, &dcr_read_mal, &dcr_write_mal);
 928    ppc_dcr_register(env, MAL0_ESR,
 929                     mal, &dcr_read_mal, &dcr_write_mal);
 930    ppc_dcr_register(env, MAL0_IER,
 931                     mal, &dcr_read_mal, &dcr_write_mal);
 932    ppc_dcr_register(env, MAL0_TXCASR,
 933                     mal, &dcr_read_mal, &dcr_write_mal);
 934    ppc_dcr_register(env, MAL0_TXCARR,
 935                     mal, &dcr_read_mal, &dcr_write_mal);
 936    ppc_dcr_register(env, MAL0_TXEOBISR,
 937                     mal, &dcr_read_mal, &dcr_write_mal);
 938    ppc_dcr_register(env, MAL0_TXDEIR,
 939                     mal, &dcr_read_mal, &dcr_write_mal);
 940    ppc_dcr_register(env, MAL0_RXCASR,
 941                     mal, &dcr_read_mal, &dcr_write_mal);
 942    ppc_dcr_register(env, MAL0_RXCARR,
 943                     mal, &dcr_read_mal, &dcr_write_mal);
 944    ppc_dcr_register(env, MAL0_RXEOBISR,
 945                     mal, &dcr_read_mal, &dcr_write_mal);
 946    ppc_dcr_register(env, MAL0_RXDEIR,
 947                     mal, &dcr_read_mal, &dcr_write_mal);
 948    for (i = 0; i < txcnum; i++) {
 949        ppc_dcr_register(env, MAL0_TXCTP0R + i,
 950                         mal, &dcr_read_mal, &dcr_write_mal);
 951    }
 952    for (i = 0; i < rxcnum; i++) {
 953        ppc_dcr_register(env, MAL0_RXCTP0R + i,
 954                         mal, &dcr_read_mal, &dcr_write_mal);
 955    }
 956    for (i = 0; i < rxcnum; i++) {
 957        ppc_dcr_register(env, MAL0_RCBS0 + i,
 958                         mal, &dcr_read_mal, &dcr_write_mal);
 959    }
 960}
 961