qemu/hw/omap1.c
<<
>>
Prefs
   1/*
   2 * TI OMAP processors emulation.
   3 *
   4 * Copyright (C) 2006-2008 Andrzej Zaborowski  <balrog@zabor.org>
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License as
   8 * published by the Free Software Foundation; either version 2 or
   9 * (at your option) version 3 of the License.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License along
  17 * with this program; if not, see <http://www.gnu.org/licenses/>.
  18 */
  19#include "hw.h"
  20#include "arm-misc.h"
  21#include "omap.h"
  22#include "sysemu.h"
  23#include "qemu-timer.h"
  24#include "qemu-char.h"
  25#include "soc_dma.h"
  26/* We use pc-style serial ports.  */
  27#include "pc.h"
  28#include "blockdev.h"
  29#include "range.h"
  30
  31/* Should signal the TCMI/GPMC */
  32uint32_t omap_badwidth_read8(void *opaque, target_phys_addr_t addr)
  33{
  34    uint8_t ret;
  35
  36    OMAP_8B_REG(addr);
  37    cpu_physical_memory_read(addr, (void *) &ret, 1);
  38    return ret;
  39}
  40
  41void omap_badwidth_write8(void *opaque, target_phys_addr_t addr,
  42                uint32_t value)
  43{
  44    uint8_t val8 = value;
  45
  46    OMAP_8B_REG(addr);
  47    cpu_physical_memory_write(addr, (void *) &val8, 1);
  48}
  49
  50uint32_t omap_badwidth_read16(void *opaque, target_phys_addr_t addr)
  51{
  52    uint16_t ret;
  53
  54    OMAP_16B_REG(addr);
  55    cpu_physical_memory_read(addr, (void *) &ret, 2);
  56    return ret;
  57}
  58
  59void omap_badwidth_write16(void *opaque, target_phys_addr_t addr,
  60                uint32_t value)
  61{
  62    uint16_t val16 = value;
  63
  64    OMAP_16B_REG(addr);
  65    cpu_physical_memory_write(addr, (void *) &val16, 2);
  66}
  67
  68uint32_t omap_badwidth_read32(void *opaque, target_phys_addr_t addr)
  69{
  70    uint32_t ret;
  71
  72    OMAP_32B_REG(addr);
  73    cpu_physical_memory_read(addr, (void *) &ret, 4);
  74    return ret;
  75}
  76
  77void omap_badwidth_write32(void *opaque, target_phys_addr_t addr,
  78                uint32_t value)
  79{
  80    OMAP_32B_REG(addr);
  81    cpu_physical_memory_write(addr, (void *) &value, 4);
  82}
  83
  84/* MPU OS timers */
  85struct omap_mpu_timer_s {
  86    qemu_irq irq;
  87    omap_clk clk;
  88    uint32_t val;
  89    int64_t time;
  90    QEMUTimer *timer;
  91    QEMUBH *tick;
  92    int64_t rate;
  93    int it_ena;
  94
  95    int enable;
  96    int ptv;
  97    int ar;
  98    int st;
  99    uint32_t reset_val;
 100};
 101
 102static inline uint32_t omap_timer_read(struct omap_mpu_timer_s *timer)
 103{
 104    uint64_t distance = qemu_get_clock(vm_clock) - timer->time;
 105
 106    if (timer->st && timer->enable && timer->rate)
 107        return timer->val - muldiv64(distance >> (timer->ptv + 1),
 108                                     timer->rate, get_ticks_per_sec());
 109    else
 110        return timer->val;
 111}
 112
 113static inline void omap_timer_sync(struct omap_mpu_timer_s *timer)
 114{
 115    timer->val = omap_timer_read(timer);
 116    timer->time = qemu_get_clock(vm_clock);
 117}
 118
 119static inline void omap_timer_update(struct omap_mpu_timer_s *timer)
 120{
 121    int64_t expires;
 122
 123    if (timer->enable && timer->st && timer->rate) {
 124        timer->val = timer->reset_val;  /* Should skip this on clk enable */
 125        expires = muldiv64((uint64_t) timer->val << (timer->ptv + 1),
 126                           get_ticks_per_sec(), timer->rate);
 127
 128        /* If timer expiry would be sooner than in about 1 ms and
 129         * auto-reload isn't set, then fire immediately.  This is a hack
 130         * to make systems like PalmOS run in acceptable time.  PalmOS
 131         * sets the interval to a very low value and polls the status bit
 132         * in a busy loop when it wants to sleep just a couple of CPU
 133         * ticks.  */
 134        if (expires > (get_ticks_per_sec() >> 10) || timer->ar)
 135            qemu_mod_timer(timer->timer, timer->time + expires);
 136        else
 137            qemu_bh_schedule(timer->tick);
 138    } else
 139        qemu_del_timer(timer->timer);
 140}
 141
 142static void omap_timer_fire(void *opaque)
 143{
 144    struct omap_mpu_timer_s *timer = opaque;
 145
 146    if (!timer->ar) {
 147        timer->val = 0;
 148        timer->st = 0;
 149    }
 150
 151    if (timer->it_ena)
 152        /* Edge-triggered irq */
 153        qemu_irq_pulse(timer->irq);
 154}
 155
 156static void omap_timer_tick(void *opaque)
 157{
 158    struct omap_mpu_timer_s *timer = (struct omap_mpu_timer_s *) opaque;
 159
 160    omap_timer_sync(timer);
 161    omap_timer_fire(timer);
 162    omap_timer_update(timer);
 163}
 164
 165static void omap_timer_clk_update(void *opaque, int line, int on)
 166{
 167    struct omap_mpu_timer_s *timer = (struct omap_mpu_timer_s *) opaque;
 168
 169    omap_timer_sync(timer);
 170    timer->rate = on ? omap_clk_getrate(timer->clk) : 0;
 171    omap_timer_update(timer);
 172}
 173
 174static void omap_timer_clk_setup(struct omap_mpu_timer_s *timer)
 175{
 176    omap_clk_adduser(timer->clk,
 177                    qemu_allocate_irqs(omap_timer_clk_update, timer, 1)[0]);
 178    timer->rate = omap_clk_getrate(timer->clk);
 179}
 180
 181static uint32_t omap_mpu_timer_read(void *opaque, target_phys_addr_t addr)
 182{
 183    struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) opaque;
 184
 185    switch (addr) {
 186    case 0x00:  /* CNTL_TIMER */
 187        return (s->enable << 5) | (s->ptv << 2) | (s->ar << 1) | s->st;
 188
 189    case 0x04:  /* LOAD_TIM */
 190        break;
 191
 192    case 0x08:  /* READ_TIM */
 193        return omap_timer_read(s);
 194    }
 195
 196    OMAP_BAD_REG(addr);
 197    return 0;
 198}
 199
 200static void omap_mpu_timer_write(void *opaque, target_phys_addr_t addr,
 201                uint32_t value)
 202{
 203    struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) opaque;
 204
 205    switch (addr) {
 206    case 0x00:  /* CNTL_TIMER */
 207        omap_timer_sync(s);
 208        s->enable = (value >> 5) & 1;
 209        s->ptv = (value >> 2) & 7;
 210        s->ar = (value >> 1) & 1;
 211        s->st = value & 1;
 212        omap_timer_update(s);
 213        return;
 214
 215    case 0x04:  /* LOAD_TIM */
 216        s->reset_val = value;
 217        return;
 218
 219    case 0x08:  /* READ_TIM */
 220        OMAP_RO_REG(addr);
 221        break;
 222
 223    default:
 224        OMAP_BAD_REG(addr);
 225    }
 226}
 227
 228static CPUReadMemoryFunc * const omap_mpu_timer_readfn[] = {
 229    omap_badwidth_read32,
 230    omap_badwidth_read32,
 231    omap_mpu_timer_read,
 232};
 233
 234static CPUWriteMemoryFunc * const omap_mpu_timer_writefn[] = {
 235    omap_badwidth_write32,
 236    omap_badwidth_write32,
 237    omap_mpu_timer_write,
 238};
 239
 240static void omap_mpu_timer_reset(struct omap_mpu_timer_s *s)
 241{
 242    qemu_del_timer(s->timer);
 243    s->enable = 0;
 244    s->reset_val = 31337;
 245    s->val = 0;
 246    s->ptv = 0;
 247    s->ar = 0;
 248    s->st = 0;
 249    s->it_ena = 1;
 250}
 251
 252static struct omap_mpu_timer_s *omap_mpu_timer_init(target_phys_addr_t base,
 253                qemu_irq irq, omap_clk clk)
 254{
 255    int iomemtype;
 256    struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *)
 257            qemu_mallocz(sizeof(struct omap_mpu_timer_s));
 258
 259    s->irq = irq;
 260    s->clk = clk;
 261    s->timer = qemu_new_timer(vm_clock, omap_timer_tick, s);
 262    s->tick = qemu_bh_new(omap_timer_fire, s);
 263    omap_mpu_timer_reset(s);
 264    omap_timer_clk_setup(s);
 265
 266    iomemtype = cpu_register_io_memory(omap_mpu_timer_readfn,
 267                    omap_mpu_timer_writefn, s, DEVICE_NATIVE_ENDIAN);
 268    cpu_register_physical_memory(base, 0x100, iomemtype);
 269
 270    return s;
 271}
 272
 273/* Watchdog timer */
 274struct omap_watchdog_timer_s {
 275    struct omap_mpu_timer_s timer;
 276    uint8_t last_wr;
 277    int mode;
 278    int free;
 279    int reset;
 280};
 281
 282static uint32_t omap_wd_timer_read(void *opaque, target_phys_addr_t addr)
 283{
 284    struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) opaque;
 285
 286    switch (addr) {
 287    case 0x00:  /* CNTL_TIMER */
 288        return (s->timer.ptv << 9) | (s->timer.ar << 8) |
 289                (s->timer.st << 7) | (s->free << 1);
 290
 291    case 0x04:  /* READ_TIMER */
 292        return omap_timer_read(&s->timer);
 293
 294    case 0x08:  /* TIMER_MODE */
 295        return s->mode << 15;
 296    }
 297
 298    OMAP_BAD_REG(addr);
 299    return 0;
 300}
 301
 302static void omap_wd_timer_write(void *opaque, target_phys_addr_t addr,
 303                uint32_t value)
 304{
 305    struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) opaque;
 306
 307    switch (addr) {
 308    case 0x00:  /* CNTL_TIMER */
 309        omap_timer_sync(&s->timer);
 310        s->timer.ptv = (value >> 9) & 7;
 311        s->timer.ar = (value >> 8) & 1;
 312        s->timer.st = (value >> 7) & 1;
 313        s->free = (value >> 1) & 1;
 314        omap_timer_update(&s->timer);
 315        break;
 316
 317    case 0x04:  /* LOAD_TIMER */
 318        s->timer.reset_val = value & 0xffff;
 319        break;
 320
 321    case 0x08:  /* TIMER_MODE */
 322        if (!s->mode && ((value >> 15) & 1))
 323            omap_clk_get(s->timer.clk);
 324        s->mode |= (value >> 15) & 1;
 325        if (s->last_wr == 0xf5) {
 326            if ((value & 0xff) == 0xa0) {
 327                if (s->mode) {
 328                    s->mode = 0;
 329                    omap_clk_put(s->timer.clk);
 330                }
 331            } else {
 332                /* XXX: on T|E hardware somehow this has no effect,
 333                 * on Zire 71 it works as specified.  */
 334                s->reset = 1;
 335                qemu_system_reset_request();
 336            }
 337        }
 338        s->last_wr = value & 0xff;
 339        break;
 340
 341    default:
 342        OMAP_BAD_REG(addr);
 343    }
 344}
 345
 346static CPUReadMemoryFunc * const omap_wd_timer_readfn[] = {
 347    omap_badwidth_read16,
 348    omap_wd_timer_read,
 349    omap_badwidth_read16,
 350};
 351
 352static CPUWriteMemoryFunc * const omap_wd_timer_writefn[] = {
 353    omap_badwidth_write16,
 354    omap_wd_timer_write,
 355    omap_badwidth_write16,
 356};
 357
 358static void omap_wd_timer_reset(struct omap_watchdog_timer_s *s)
 359{
 360    qemu_del_timer(s->timer.timer);
 361    if (!s->mode)
 362        omap_clk_get(s->timer.clk);
 363    s->mode = 1;
 364    s->free = 1;
 365    s->reset = 0;
 366    s->timer.enable = 1;
 367    s->timer.it_ena = 1;
 368    s->timer.reset_val = 0xffff;
 369    s->timer.val = 0;
 370    s->timer.st = 0;
 371    s->timer.ptv = 0;
 372    s->timer.ar = 0;
 373    omap_timer_update(&s->timer);
 374}
 375
 376static struct omap_watchdog_timer_s *omap_wd_timer_init(target_phys_addr_t base,
 377                qemu_irq irq, omap_clk clk)
 378{
 379    int iomemtype;
 380    struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *)
 381            qemu_mallocz(sizeof(struct omap_watchdog_timer_s));
 382
 383    s->timer.irq = irq;
 384    s->timer.clk = clk;
 385    s->timer.timer = qemu_new_timer(vm_clock, omap_timer_tick, &s->timer);
 386    omap_wd_timer_reset(s);
 387    omap_timer_clk_setup(&s->timer);
 388
 389    iomemtype = cpu_register_io_memory(omap_wd_timer_readfn,
 390                    omap_wd_timer_writefn, s, DEVICE_NATIVE_ENDIAN);
 391    cpu_register_physical_memory(base, 0x100, iomemtype);
 392
 393    return s;
 394}
 395
 396/* 32-kHz timer */
 397struct omap_32khz_timer_s {
 398    struct omap_mpu_timer_s timer;
 399};
 400
 401static uint32_t omap_os_timer_read(void *opaque, target_phys_addr_t addr)
 402{
 403    struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *) opaque;
 404    int offset = addr & OMAP_MPUI_REG_MASK;
 405
 406    switch (offset) {
 407    case 0x00:  /* TVR */
 408        return s->timer.reset_val;
 409
 410    case 0x04:  /* TCR */
 411        return omap_timer_read(&s->timer);
 412
 413    case 0x08:  /* CR */
 414        return (s->timer.ar << 3) | (s->timer.it_ena << 2) | s->timer.st;
 415
 416    default:
 417        break;
 418    }
 419    OMAP_BAD_REG(addr);
 420    return 0;
 421}
 422
 423static void omap_os_timer_write(void *opaque, target_phys_addr_t addr,
 424                uint32_t value)
 425{
 426    struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *) opaque;
 427    int offset = addr & OMAP_MPUI_REG_MASK;
 428
 429    switch (offset) {
 430    case 0x00:  /* TVR */
 431        s->timer.reset_val = value & 0x00ffffff;
 432        break;
 433
 434    case 0x04:  /* TCR */
 435        OMAP_RO_REG(addr);
 436        break;
 437
 438    case 0x08:  /* CR */
 439        s->timer.ar = (value >> 3) & 1;
 440        s->timer.it_ena = (value >> 2) & 1;
 441        if (s->timer.st != (value & 1) || (value & 2)) {
 442            omap_timer_sync(&s->timer);
 443            s->timer.enable = value & 1;
 444            s->timer.st = value & 1;
 445            omap_timer_update(&s->timer);
 446        }
 447        break;
 448
 449    default:
 450        OMAP_BAD_REG(addr);
 451    }
 452}
 453
 454static CPUReadMemoryFunc * const omap_os_timer_readfn[] = {
 455    omap_badwidth_read32,
 456    omap_badwidth_read32,
 457    omap_os_timer_read,
 458};
 459
 460static CPUWriteMemoryFunc * const omap_os_timer_writefn[] = {
 461    omap_badwidth_write32,
 462    omap_badwidth_write32,
 463    omap_os_timer_write,
 464};
 465
 466static void omap_os_timer_reset(struct omap_32khz_timer_s *s)
 467{
 468    qemu_del_timer(s->timer.timer);
 469    s->timer.enable = 0;
 470    s->timer.it_ena = 0;
 471    s->timer.reset_val = 0x00ffffff;
 472    s->timer.val = 0;
 473    s->timer.st = 0;
 474    s->timer.ptv = 0;
 475    s->timer.ar = 1;
 476}
 477
 478static struct omap_32khz_timer_s *omap_os_timer_init(target_phys_addr_t base,
 479                qemu_irq irq, omap_clk clk)
 480{
 481    int iomemtype;
 482    struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *)
 483            qemu_mallocz(sizeof(struct omap_32khz_timer_s));
 484
 485    s->timer.irq = irq;
 486    s->timer.clk = clk;
 487    s->timer.timer = qemu_new_timer(vm_clock, omap_timer_tick, &s->timer);
 488    omap_os_timer_reset(s);
 489    omap_timer_clk_setup(&s->timer);
 490
 491    iomemtype = cpu_register_io_memory(omap_os_timer_readfn,
 492                    omap_os_timer_writefn, s, DEVICE_NATIVE_ENDIAN);
 493    cpu_register_physical_memory(base, 0x800, iomemtype);
 494
 495    return s;
 496}
 497
 498/* Ultra Low-Power Device Module */
 499static uint32_t omap_ulpd_pm_read(void *opaque, target_phys_addr_t addr)
 500{
 501    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
 502    uint16_t ret;
 503
 504    switch (addr) {
 505    case 0x14:  /* IT_STATUS */
 506        ret = s->ulpd_pm_regs[addr >> 2];
 507        s->ulpd_pm_regs[addr >> 2] = 0;
 508        qemu_irq_lower(s->irq[1][OMAP_INT_GAUGE_32K]);
 509        return ret;
 510
 511    case 0x18:  /* Reserved */
 512    case 0x1c:  /* Reserved */
 513    case 0x20:  /* Reserved */
 514    case 0x28:  /* Reserved */
 515    case 0x2c:  /* Reserved */
 516        OMAP_BAD_REG(addr);
 517    case 0x00:  /* COUNTER_32_LSB */
 518    case 0x04:  /* COUNTER_32_MSB */
 519    case 0x08:  /* COUNTER_HIGH_FREQ_LSB */
 520    case 0x0c:  /* COUNTER_HIGH_FREQ_MSB */
 521    case 0x10:  /* GAUGING_CTRL */
 522    case 0x24:  /* SETUP_ANALOG_CELL3_ULPD1 */
 523    case 0x30:  /* CLOCK_CTRL */
 524    case 0x34:  /* SOFT_REQ */
 525    case 0x38:  /* COUNTER_32_FIQ */
 526    case 0x3c:  /* DPLL_CTRL */
 527    case 0x40:  /* STATUS_REQ */
 528        /* XXX: check clk::usecount state for every clock */
 529    case 0x48:  /* LOCL_TIME */
 530    case 0x4c:  /* APLL_CTRL */
 531    case 0x50:  /* POWER_CTRL */
 532        return s->ulpd_pm_regs[addr >> 2];
 533    }
 534
 535    OMAP_BAD_REG(addr);
 536    return 0;
 537}
 538
 539static inline void omap_ulpd_clk_update(struct omap_mpu_state_s *s,
 540                uint16_t diff, uint16_t value)
 541{
 542    if (diff & (1 << 4))                                /* USB_MCLK_EN */
 543        omap_clk_onoff(omap_findclk(s, "usb_clk0"), (value >> 4) & 1);
 544    if (diff & (1 << 5))                                /* DIS_USB_PVCI_CLK */
 545        omap_clk_onoff(omap_findclk(s, "usb_w2fc_ck"), (~value >> 5) & 1);
 546}
 547
 548static inline void omap_ulpd_req_update(struct omap_mpu_state_s *s,
 549                uint16_t diff, uint16_t value)
 550{
 551    if (diff & (1 << 0))                                /* SOFT_DPLL_REQ */
 552        omap_clk_canidle(omap_findclk(s, "dpll4"), (~value >> 0) & 1);
 553    if (diff & (1 << 1))                                /* SOFT_COM_REQ */
 554        omap_clk_canidle(omap_findclk(s, "com_mclk_out"), (~value >> 1) & 1);
 555    if (diff & (1 << 2))                                /* SOFT_SDW_REQ */
 556        omap_clk_canidle(omap_findclk(s, "bt_mclk_out"), (~value >> 2) & 1);
 557    if (diff & (1 << 3))                                /* SOFT_USB_REQ */
 558        omap_clk_canidle(omap_findclk(s, "usb_clk0"), (~value >> 3) & 1);
 559}
 560
 561static void omap_ulpd_pm_write(void *opaque, target_phys_addr_t addr,
 562                uint32_t value)
 563{
 564    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
 565    int64_t now, ticks;
 566    int div, mult;
 567    static const int bypass_div[4] = { 1, 2, 4, 4 };
 568    uint16_t diff;
 569
 570    switch (addr) {
 571    case 0x00:  /* COUNTER_32_LSB */
 572    case 0x04:  /* COUNTER_32_MSB */
 573    case 0x08:  /* COUNTER_HIGH_FREQ_LSB */
 574    case 0x0c:  /* COUNTER_HIGH_FREQ_MSB */
 575    case 0x14:  /* IT_STATUS */
 576    case 0x40:  /* STATUS_REQ */
 577        OMAP_RO_REG(addr);
 578        break;
 579
 580    case 0x10:  /* GAUGING_CTRL */
 581        /* Bits 0 and 1 seem to be confused in the OMAP 310 TRM */
 582        if ((s->ulpd_pm_regs[addr >> 2] ^ value) & 1) {
 583            now = qemu_get_clock(vm_clock);
 584
 585            if (value & 1)
 586                s->ulpd_gauge_start = now;
 587            else {
 588                now -= s->ulpd_gauge_start;
 589
 590                /* 32-kHz ticks */
 591                ticks = muldiv64(now, 32768, get_ticks_per_sec());
 592                s->ulpd_pm_regs[0x00 >> 2] = (ticks >>  0) & 0xffff;
 593                s->ulpd_pm_regs[0x04 >> 2] = (ticks >> 16) & 0xffff;
 594                if (ticks >> 32)        /* OVERFLOW_32K */
 595                    s->ulpd_pm_regs[0x14 >> 2] |= 1 << 2;
 596
 597                /* High frequency ticks */
 598                ticks = muldiv64(now, 12000000, get_ticks_per_sec());
 599                s->ulpd_pm_regs[0x08 >> 2] = (ticks >>  0) & 0xffff;
 600                s->ulpd_pm_regs[0x0c >> 2] = (ticks >> 16) & 0xffff;
 601                if (ticks >> 32)        /* OVERFLOW_HI_FREQ */
 602                    s->ulpd_pm_regs[0x14 >> 2] |= 1 << 1;
 603
 604                s->ulpd_pm_regs[0x14 >> 2] |= 1 << 0;   /* IT_GAUGING */
 605                qemu_irq_raise(s->irq[1][OMAP_INT_GAUGE_32K]);
 606            }
 607        }
 608        s->ulpd_pm_regs[addr >> 2] = value;
 609        break;
 610
 611    case 0x18:  /* Reserved */
 612    case 0x1c:  /* Reserved */
 613    case 0x20:  /* Reserved */
 614    case 0x28:  /* Reserved */
 615    case 0x2c:  /* Reserved */
 616        OMAP_BAD_REG(addr);
 617    case 0x24:  /* SETUP_ANALOG_CELL3_ULPD1 */
 618    case 0x38:  /* COUNTER_32_FIQ */
 619    case 0x48:  /* LOCL_TIME */
 620    case 0x50:  /* POWER_CTRL */
 621        s->ulpd_pm_regs[addr >> 2] = value;
 622        break;
 623
 624    case 0x30:  /* CLOCK_CTRL */
 625        diff = s->ulpd_pm_regs[addr >> 2] ^ value;
 626        s->ulpd_pm_regs[addr >> 2] = value & 0x3f;
 627        omap_ulpd_clk_update(s, diff, value);
 628        break;
 629
 630    case 0x34:  /* SOFT_REQ */
 631        diff = s->ulpd_pm_regs[addr >> 2] ^ value;
 632        s->ulpd_pm_regs[addr >> 2] = value & 0x1f;
 633        omap_ulpd_req_update(s, diff, value);
 634        break;
 635
 636    case 0x3c:  /* DPLL_CTRL */
 637        /* XXX: OMAP310 TRM claims bit 3 is PLL_ENABLE, and bit 4 is
 638         * omitted altogether, probably a typo.  */
 639        /* This register has identical semantics with DPLL(1:3) control
 640         * registers, see omap_dpll_write() */
 641        diff = s->ulpd_pm_regs[addr >> 2] & value;
 642        s->ulpd_pm_regs[addr >> 2] = value & 0x2fff;
 643        if (diff & (0x3ff << 2)) {
 644            if (value & (1 << 4)) {                     /* PLL_ENABLE */
 645                div = ((value >> 5) & 3) + 1;           /* PLL_DIV */
 646                mult = MIN((value >> 7) & 0x1f, 1);     /* PLL_MULT */
 647            } else {
 648                div = bypass_div[((value >> 2) & 3)];   /* BYPASS_DIV */
 649                mult = 1;
 650            }
 651            omap_clk_setrate(omap_findclk(s, "dpll4"), div, mult);
 652        }
 653
 654        /* Enter the desired mode.  */
 655        s->ulpd_pm_regs[addr >> 2] =
 656                (s->ulpd_pm_regs[addr >> 2] & 0xfffe) |
 657                ((s->ulpd_pm_regs[addr >> 2] >> 4) & 1);
 658
 659        /* Act as if the lock is restored.  */
 660        s->ulpd_pm_regs[addr >> 2] |= 2;
 661        break;
 662
 663    case 0x4c:  /* APLL_CTRL */
 664        diff = s->ulpd_pm_regs[addr >> 2] & value;
 665        s->ulpd_pm_regs[addr >> 2] = value & 0xf;
 666        if (diff & (1 << 0))                            /* APLL_NDPLL_SWITCH */
 667            omap_clk_reparent(omap_findclk(s, "ck_48m"), omap_findclk(s,
 668                                    (value & (1 << 0)) ? "apll" : "dpll4"));
 669        break;
 670
 671    default:
 672        OMAP_BAD_REG(addr);
 673    }
 674}
 675
 676static CPUReadMemoryFunc * const omap_ulpd_pm_readfn[] = {
 677    omap_badwidth_read16,
 678    omap_ulpd_pm_read,
 679    omap_badwidth_read16,
 680};
 681
 682static CPUWriteMemoryFunc * const omap_ulpd_pm_writefn[] = {
 683    omap_badwidth_write16,
 684    omap_ulpd_pm_write,
 685    omap_badwidth_write16,
 686};
 687
 688static void omap_ulpd_pm_reset(struct omap_mpu_state_s *mpu)
 689{
 690    mpu->ulpd_pm_regs[0x00 >> 2] = 0x0001;
 691    mpu->ulpd_pm_regs[0x04 >> 2] = 0x0000;
 692    mpu->ulpd_pm_regs[0x08 >> 2] = 0x0001;
 693    mpu->ulpd_pm_regs[0x0c >> 2] = 0x0000;
 694    mpu->ulpd_pm_regs[0x10 >> 2] = 0x0000;
 695    mpu->ulpd_pm_regs[0x18 >> 2] = 0x01;
 696    mpu->ulpd_pm_regs[0x1c >> 2] = 0x01;
 697    mpu->ulpd_pm_regs[0x20 >> 2] = 0x01;
 698    mpu->ulpd_pm_regs[0x24 >> 2] = 0x03ff;
 699    mpu->ulpd_pm_regs[0x28 >> 2] = 0x01;
 700    mpu->ulpd_pm_regs[0x2c >> 2] = 0x01;
 701    omap_ulpd_clk_update(mpu, mpu->ulpd_pm_regs[0x30 >> 2], 0x0000);
 702    mpu->ulpd_pm_regs[0x30 >> 2] = 0x0000;
 703    omap_ulpd_req_update(mpu, mpu->ulpd_pm_regs[0x34 >> 2], 0x0000);
 704    mpu->ulpd_pm_regs[0x34 >> 2] = 0x0000;
 705    mpu->ulpd_pm_regs[0x38 >> 2] = 0x0001;
 706    mpu->ulpd_pm_regs[0x3c >> 2] = 0x2211;
 707    mpu->ulpd_pm_regs[0x40 >> 2] = 0x0000; /* FIXME: dump a real STATUS_REQ */
 708    mpu->ulpd_pm_regs[0x48 >> 2] = 0x960;
 709    mpu->ulpd_pm_regs[0x4c >> 2] = 0x08;
 710    mpu->ulpd_pm_regs[0x50 >> 2] = 0x08;
 711    omap_clk_setrate(omap_findclk(mpu, "dpll4"), 1, 4);
 712    omap_clk_reparent(omap_findclk(mpu, "ck_48m"), omap_findclk(mpu, "dpll4"));
 713}
 714
 715static void omap_ulpd_pm_init(target_phys_addr_t base,
 716                struct omap_mpu_state_s *mpu)
 717{
 718    int iomemtype = cpu_register_io_memory(omap_ulpd_pm_readfn,
 719                    omap_ulpd_pm_writefn, mpu, DEVICE_NATIVE_ENDIAN);
 720
 721    cpu_register_physical_memory(base, 0x800, iomemtype);
 722    omap_ulpd_pm_reset(mpu);
 723}
 724
 725/* OMAP Pin Configuration */
 726static uint32_t omap_pin_cfg_read(void *opaque, target_phys_addr_t addr)
 727{
 728    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
 729
 730    switch (addr) {
 731    case 0x00:  /* FUNC_MUX_CTRL_0 */
 732    case 0x04:  /* FUNC_MUX_CTRL_1 */
 733    case 0x08:  /* FUNC_MUX_CTRL_2 */
 734        return s->func_mux_ctrl[addr >> 2];
 735
 736    case 0x0c:  /* COMP_MODE_CTRL_0 */
 737        return s->comp_mode_ctrl[0];
 738
 739    case 0x10:  /* FUNC_MUX_CTRL_3 */
 740    case 0x14:  /* FUNC_MUX_CTRL_4 */
 741    case 0x18:  /* FUNC_MUX_CTRL_5 */
 742    case 0x1c:  /* FUNC_MUX_CTRL_6 */
 743    case 0x20:  /* FUNC_MUX_CTRL_7 */
 744    case 0x24:  /* FUNC_MUX_CTRL_8 */
 745    case 0x28:  /* FUNC_MUX_CTRL_9 */
 746    case 0x2c:  /* FUNC_MUX_CTRL_A */
 747    case 0x30:  /* FUNC_MUX_CTRL_B */
 748    case 0x34:  /* FUNC_MUX_CTRL_C */
 749    case 0x38:  /* FUNC_MUX_CTRL_D */
 750        return s->func_mux_ctrl[(addr >> 2) - 1];
 751
 752    case 0x40:  /* PULL_DWN_CTRL_0 */
 753    case 0x44:  /* PULL_DWN_CTRL_1 */
 754    case 0x48:  /* PULL_DWN_CTRL_2 */
 755    case 0x4c:  /* PULL_DWN_CTRL_3 */
 756        return s->pull_dwn_ctrl[(addr & 0xf) >> 2];
 757
 758    case 0x50:  /* GATE_INH_CTRL_0 */
 759        return s->gate_inh_ctrl[0];
 760
 761    case 0x60:  /* VOLTAGE_CTRL_0 */
 762        return s->voltage_ctrl[0];
 763
 764    case 0x70:  /* TEST_DBG_CTRL_0 */
 765        return s->test_dbg_ctrl[0];
 766
 767    case 0x80:  /* MOD_CONF_CTRL_0 */
 768        return s->mod_conf_ctrl[0];
 769    }
 770
 771    OMAP_BAD_REG(addr);
 772    return 0;
 773}
 774
 775static inline void omap_pin_funcmux0_update(struct omap_mpu_state_s *s,
 776                uint32_t diff, uint32_t value)
 777{
 778    if (s->compat1509) {
 779        if (diff & (1 << 9))                    /* BLUETOOTH */
 780            omap_clk_onoff(omap_findclk(s, "bt_mclk_out"),
 781                            (~value >> 9) & 1);
 782        if (diff & (1 << 7))                    /* USB.CLKO */
 783            omap_clk_onoff(omap_findclk(s, "usb.clko"),
 784                            (value >> 7) & 1);
 785    }
 786}
 787
 788static inline void omap_pin_funcmux1_update(struct omap_mpu_state_s *s,
 789                uint32_t diff, uint32_t value)
 790{
 791    if (s->compat1509) {
 792        if (diff & (1 << 31))                   /* MCBSP3_CLK_HIZ_DI */
 793            omap_clk_onoff(omap_findclk(s, "mcbsp3.clkx"),
 794                            (value >> 31) & 1);
 795        if (diff & (1 << 1))                    /* CLK32K */
 796            omap_clk_onoff(omap_findclk(s, "clk32k_out"),
 797                            (~value >> 1) & 1);
 798    }
 799}
 800
 801static inline void omap_pin_modconf1_update(struct omap_mpu_state_s *s,
 802                uint32_t diff, uint32_t value)
 803{
 804    if (diff & (1 << 31))                       /* CONF_MOD_UART3_CLK_MODE_R */
 805         omap_clk_reparent(omap_findclk(s, "uart3_ck"),
 806                         omap_findclk(s, ((value >> 31) & 1) ?
 807                                 "ck_48m" : "armper_ck"));
 808    if (diff & (1 << 30))                       /* CONF_MOD_UART2_CLK_MODE_R */
 809         omap_clk_reparent(omap_findclk(s, "uart2_ck"),
 810                         omap_findclk(s, ((value >> 30) & 1) ?
 811                                 "ck_48m" : "armper_ck"));
 812    if (diff & (1 << 29))                       /* CONF_MOD_UART1_CLK_MODE_R */
 813         omap_clk_reparent(omap_findclk(s, "uart1_ck"),
 814                         omap_findclk(s, ((value >> 29) & 1) ?
 815                                 "ck_48m" : "armper_ck"));
 816    if (diff & (1 << 23))                       /* CONF_MOD_MMC_SD_CLK_REQ_R */
 817         omap_clk_reparent(omap_findclk(s, "mmc_ck"),
 818                         omap_findclk(s, ((value >> 23) & 1) ?
 819                                 "ck_48m" : "armper_ck"));
 820    if (diff & (1 << 12))                       /* CONF_MOD_COM_MCLK_12_48_S */
 821         omap_clk_reparent(omap_findclk(s, "com_mclk_out"),
 822                         omap_findclk(s, ((value >> 12) & 1) ?
 823                                 "ck_48m" : "armper_ck"));
 824    if (diff & (1 << 9))                        /* CONF_MOD_USB_HOST_HHC_UHO */
 825         omap_clk_onoff(omap_findclk(s, "usb_hhc_ck"), (value >> 9) & 1);
 826}
 827
 828static void omap_pin_cfg_write(void *opaque, target_phys_addr_t addr,
 829                uint32_t value)
 830{
 831    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
 832    uint32_t diff;
 833
 834    switch (addr) {
 835    case 0x00:  /* FUNC_MUX_CTRL_0 */
 836        diff = s->func_mux_ctrl[addr >> 2] ^ value;
 837        s->func_mux_ctrl[addr >> 2] = value;
 838        omap_pin_funcmux0_update(s, diff, value);
 839        return;
 840
 841    case 0x04:  /* FUNC_MUX_CTRL_1 */
 842        diff = s->func_mux_ctrl[addr >> 2] ^ value;
 843        s->func_mux_ctrl[addr >> 2] = value;
 844        omap_pin_funcmux1_update(s, diff, value);
 845        return;
 846
 847    case 0x08:  /* FUNC_MUX_CTRL_2 */
 848        s->func_mux_ctrl[addr >> 2] = value;
 849        return;
 850
 851    case 0x0c:  /* COMP_MODE_CTRL_0 */
 852        s->comp_mode_ctrl[0] = value;
 853        s->compat1509 = (value != 0x0000eaef);
 854        omap_pin_funcmux0_update(s, ~0, s->func_mux_ctrl[0]);
 855        omap_pin_funcmux1_update(s, ~0, s->func_mux_ctrl[1]);
 856        return;
 857
 858    case 0x10:  /* FUNC_MUX_CTRL_3 */
 859    case 0x14:  /* FUNC_MUX_CTRL_4 */
 860    case 0x18:  /* FUNC_MUX_CTRL_5 */
 861    case 0x1c:  /* FUNC_MUX_CTRL_6 */
 862    case 0x20:  /* FUNC_MUX_CTRL_7 */
 863    case 0x24:  /* FUNC_MUX_CTRL_8 */
 864    case 0x28:  /* FUNC_MUX_CTRL_9 */
 865    case 0x2c:  /* FUNC_MUX_CTRL_A */
 866    case 0x30:  /* FUNC_MUX_CTRL_B */
 867    case 0x34:  /* FUNC_MUX_CTRL_C */
 868    case 0x38:  /* FUNC_MUX_CTRL_D */
 869        s->func_mux_ctrl[(addr >> 2) - 1] = value;
 870        return;
 871
 872    case 0x40:  /* PULL_DWN_CTRL_0 */
 873    case 0x44:  /* PULL_DWN_CTRL_1 */
 874    case 0x48:  /* PULL_DWN_CTRL_2 */
 875    case 0x4c:  /* PULL_DWN_CTRL_3 */
 876        s->pull_dwn_ctrl[(addr & 0xf) >> 2] = value;
 877        return;
 878
 879    case 0x50:  /* GATE_INH_CTRL_0 */
 880        s->gate_inh_ctrl[0] = value;
 881        return;
 882
 883    case 0x60:  /* VOLTAGE_CTRL_0 */
 884        s->voltage_ctrl[0] = value;
 885        return;
 886
 887    case 0x70:  /* TEST_DBG_CTRL_0 */
 888        s->test_dbg_ctrl[0] = value;
 889        return;
 890
 891    case 0x80:  /* MOD_CONF_CTRL_0 */
 892        diff = s->mod_conf_ctrl[0] ^ value;
 893        s->mod_conf_ctrl[0] = value;
 894        omap_pin_modconf1_update(s, diff, value);
 895        return;
 896
 897    default:
 898        OMAP_BAD_REG(addr);
 899    }
 900}
 901
 902static CPUReadMemoryFunc * const omap_pin_cfg_readfn[] = {
 903    omap_badwidth_read32,
 904    omap_badwidth_read32,
 905    omap_pin_cfg_read,
 906};
 907
 908static CPUWriteMemoryFunc * const omap_pin_cfg_writefn[] = {
 909    omap_badwidth_write32,
 910    omap_badwidth_write32,
 911    omap_pin_cfg_write,
 912};
 913
 914static void omap_pin_cfg_reset(struct omap_mpu_state_s *mpu)
 915{
 916    /* Start in Compatibility Mode.  */
 917    mpu->compat1509 = 1;
 918    omap_pin_funcmux0_update(mpu, mpu->func_mux_ctrl[0], 0);
 919    omap_pin_funcmux1_update(mpu, mpu->func_mux_ctrl[1], 0);
 920    omap_pin_modconf1_update(mpu, mpu->mod_conf_ctrl[0], 0);
 921    memset(mpu->func_mux_ctrl, 0, sizeof(mpu->func_mux_ctrl));
 922    memset(mpu->comp_mode_ctrl, 0, sizeof(mpu->comp_mode_ctrl));
 923    memset(mpu->pull_dwn_ctrl, 0, sizeof(mpu->pull_dwn_ctrl));
 924    memset(mpu->gate_inh_ctrl, 0, sizeof(mpu->gate_inh_ctrl));
 925    memset(mpu->voltage_ctrl, 0, sizeof(mpu->voltage_ctrl));
 926    memset(mpu->test_dbg_ctrl, 0, sizeof(mpu->test_dbg_ctrl));
 927    memset(mpu->mod_conf_ctrl, 0, sizeof(mpu->mod_conf_ctrl));
 928}
 929
 930static void omap_pin_cfg_init(target_phys_addr_t base,
 931                struct omap_mpu_state_s *mpu)
 932{
 933    int iomemtype = cpu_register_io_memory(omap_pin_cfg_readfn,
 934                    omap_pin_cfg_writefn, mpu, DEVICE_NATIVE_ENDIAN);
 935
 936    cpu_register_physical_memory(base, 0x800, iomemtype);
 937    omap_pin_cfg_reset(mpu);
 938}
 939
 940/* Device Identification, Die Identification */
 941static uint32_t omap_id_read(void *opaque, target_phys_addr_t addr)
 942{
 943    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
 944
 945    switch (addr) {
 946    case 0xfffe1800:    /* DIE_ID_LSB */
 947        return 0xc9581f0e;
 948    case 0xfffe1804:    /* DIE_ID_MSB */
 949        return 0xa8858bfa;
 950
 951    case 0xfffe2000:    /* PRODUCT_ID_LSB */
 952        return 0x00aaaafc;
 953    case 0xfffe2004:    /* PRODUCT_ID_MSB */
 954        return 0xcafeb574;
 955
 956    case 0xfffed400:    /* JTAG_ID_LSB */
 957        switch (s->mpu_model) {
 958        case omap310:
 959            return 0x03310315;
 960        case omap1510:
 961            return 0x03310115;
 962        default:
 963            hw_error("%s: bad mpu model\n", __FUNCTION__);
 964        }
 965        break;
 966
 967    case 0xfffed404:    /* JTAG_ID_MSB */
 968        switch (s->mpu_model) {
 969        case omap310:
 970            return 0xfb57402f;
 971        case omap1510:
 972            return 0xfb47002f;
 973        default:
 974            hw_error("%s: bad mpu model\n", __FUNCTION__);
 975        }
 976        break;
 977    }
 978
 979    OMAP_BAD_REG(addr);
 980    return 0;
 981}
 982
 983static void omap_id_write(void *opaque, target_phys_addr_t addr,
 984                uint32_t value)
 985{
 986    OMAP_BAD_REG(addr);
 987}
 988
 989static CPUReadMemoryFunc * const omap_id_readfn[] = {
 990    omap_badwidth_read32,
 991    omap_badwidth_read32,
 992    omap_id_read,
 993};
 994
 995static CPUWriteMemoryFunc * const omap_id_writefn[] = {
 996    omap_badwidth_write32,
 997    omap_badwidth_write32,
 998    omap_id_write,
 999};
1000
1001static void omap_id_init(struct omap_mpu_state_s *mpu)
1002{
1003    int iomemtype = cpu_register_io_memory(omap_id_readfn,
1004                    omap_id_writefn, mpu, DEVICE_NATIVE_ENDIAN);
1005    cpu_register_physical_memory_offset(0xfffe1800, 0x800, iomemtype, 0xfffe1800);
1006    cpu_register_physical_memory_offset(0xfffed400, 0x100, iomemtype, 0xfffed400);
1007    if (!cpu_is_omap15xx(mpu))
1008        cpu_register_physical_memory_offset(0xfffe2000, 0x800, iomemtype, 0xfffe2000);
1009}
1010
1011/* MPUI Control (Dummy) */
1012static uint32_t omap_mpui_read(void *opaque, target_phys_addr_t addr)
1013{
1014    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
1015
1016    switch (addr) {
1017    case 0x00:  /* CTRL */
1018        return s->mpui_ctrl;
1019    case 0x04:  /* DEBUG_ADDR */
1020        return 0x01ffffff;
1021    case 0x08:  /* DEBUG_DATA */
1022        return 0xffffffff;
1023    case 0x0c:  /* DEBUG_FLAG */
1024        return 0x00000800;
1025    case 0x10:  /* STATUS */
1026        return 0x00000000;
1027
1028    /* Not in OMAP310 */
1029    case 0x14:  /* DSP_STATUS */
1030    case 0x18:  /* DSP_BOOT_CONFIG */
1031        return 0x00000000;
1032    case 0x1c:  /* DSP_MPUI_CONFIG */
1033        return 0x0000ffff;
1034    }
1035
1036    OMAP_BAD_REG(addr);
1037    return 0;
1038}
1039
1040static void omap_mpui_write(void *opaque, target_phys_addr_t addr,
1041                uint32_t value)
1042{
1043    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
1044
1045    switch (addr) {
1046    case 0x00:  /* CTRL */
1047        s->mpui_ctrl = value & 0x007fffff;
1048        break;
1049
1050    case 0x04:  /* DEBUG_ADDR */
1051    case 0x08:  /* DEBUG_DATA */
1052    case 0x0c:  /* DEBUG_FLAG */
1053    case 0x10:  /* STATUS */
1054    /* Not in OMAP310 */
1055    case 0x14:  /* DSP_STATUS */
1056        OMAP_RO_REG(addr);
1057    case 0x18:  /* DSP_BOOT_CONFIG */
1058    case 0x1c:  /* DSP_MPUI_CONFIG */
1059        break;
1060
1061    default:
1062        OMAP_BAD_REG(addr);
1063    }
1064}
1065
1066static CPUReadMemoryFunc * const omap_mpui_readfn[] = {
1067    omap_badwidth_read32,
1068    omap_badwidth_read32,
1069    omap_mpui_read,
1070};
1071
1072static CPUWriteMemoryFunc * const omap_mpui_writefn[] = {
1073    omap_badwidth_write32,
1074    omap_badwidth_write32,
1075    omap_mpui_write,
1076};
1077
1078static void omap_mpui_reset(struct omap_mpu_state_s *s)
1079{
1080    s->mpui_ctrl = 0x0003ff1b;
1081}
1082
1083static void omap_mpui_init(target_phys_addr_t base,
1084                struct omap_mpu_state_s *mpu)
1085{
1086    int iomemtype = cpu_register_io_memory(omap_mpui_readfn,
1087                    omap_mpui_writefn, mpu, DEVICE_NATIVE_ENDIAN);
1088
1089    cpu_register_physical_memory(base, 0x100, iomemtype);
1090
1091    omap_mpui_reset(mpu);
1092}
1093
1094/* TIPB Bridges */
1095struct omap_tipb_bridge_s {
1096    qemu_irq abort;
1097
1098    int width_intr;
1099    uint16_t control;
1100    uint16_t alloc;
1101    uint16_t buffer;
1102    uint16_t enh_control;
1103};
1104
1105static uint32_t omap_tipb_bridge_read(void *opaque, target_phys_addr_t addr)
1106{
1107    struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *) opaque;
1108
1109    switch (addr) {
1110    case 0x00:  /* TIPB_CNTL */
1111        return s->control;
1112    case 0x04:  /* TIPB_BUS_ALLOC */
1113        return s->alloc;
1114    case 0x08:  /* MPU_TIPB_CNTL */
1115        return s->buffer;
1116    case 0x0c:  /* ENHANCED_TIPB_CNTL */
1117        return s->enh_control;
1118    case 0x10:  /* ADDRESS_DBG */
1119    case 0x14:  /* DATA_DEBUG_LOW */
1120    case 0x18:  /* DATA_DEBUG_HIGH */
1121        return 0xffff;
1122    case 0x1c:  /* DEBUG_CNTR_SIG */
1123        return 0x00f8;
1124    }
1125
1126    OMAP_BAD_REG(addr);
1127    return 0;
1128}
1129
1130static void omap_tipb_bridge_write(void *opaque, target_phys_addr_t addr,
1131                uint32_t value)
1132{
1133    struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *) opaque;
1134
1135    switch (addr) {
1136    case 0x00:  /* TIPB_CNTL */
1137        s->control = value & 0xffff;
1138        break;
1139
1140    case 0x04:  /* TIPB_BUS_ALLOC */
1141        s->alloc = value & 0x003f;
1142        break;
1143
1144    case 0x08:  /* MPU_TIPB_CNTL */
1145        s->buffer = value & 0x0003;
1146        break;
1147
1148    case 0x0c:  /* ENHANCED_TIPB_CNTL */
1149        s->width_intr = !(value & 2);
1150        s->enh_control = value & 0x000f;
1151        break;
1152
1153    case 0x10:  /* ADDRESS_DBG */
1154    case 0x14:  /* DATA_DEBUG_LOW */
1155    case 0x18:  /* DATA_DEBUG_HIGH */
1156    case 0x1c:  /* DEBUG_CNTR_SIG */
1157        OMAP_RO_REG(addr);
1158        break;
1159
1160    default:
1161        OMAP_BAD_REG(addr);
1162    }
1163}
1164
1165static CPUReadMemoryFunc * const omap_tipb_bridge_readfn[] = {
1166    omap_badwidth_read16,
1167    omap_tipb_bridge_read,
1168    omap_tipb_bridge_read,
1169};
1170
1171static CPUWriteMemoryFunc * const omap_tipb_bridge_writefn[] = {
1172    omap_badwidth_write16,
1173    omap_tipb_bridge_write,
1174    omap_tipb_bridge_write,
1175};
1176
1177static void omap_tipb_bridge_reset(struct omap_tipb_bridge_s *s)
1178{
1179    s->control = 0xffff;
1180    s->alloc = 0x0009;
1181    s->buffer = 0x0000;
1182    s->enh_control = 0x000f;
1183}
1184
1185static struct omap_tipb_bridge_s *omap_tipb_bridge_init(target_phys_addr_t base,
1186                qemu_irq abort_irq, omap_clk clk)
1187{
1188    int iomemtype;
1189    struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *)
1190            qemu_mallocz(sizeof(struct omap_tipb_bridge_s));
1191
1192    s->abort = abort_irq;
1193    omap_tipb_bridge_reset(s);
1194
1195    iomemtype = cpu_register_io_memory(omap_tipb_bridge_readfn,
1196                    omap_tipb_bridge_writefn, s, DEVICE_NATIVE_ENDIAN);
1197    cpu_register_physical_memory(base, 0x100, iomemtype);
1198
1199    return s;
1200}
1201
1202/* Dummy Traffic Controller's Memory Interface */
1203static uint32_t omap_tcmi_read(void *opaque, target_phys_addr_t addr)
1204{
1205    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
1206    uint32_t ret;
1207
1208    switch (addr) {
1209    case 0x00:  /* IMIF_PRIO */
1210    case 0x04:  /* EMIFS_PRIO */
1211    case 0x08:  /* EMIFF_PRIO */
1212    case 0x0c:  /* EMIFS_CONFIG */
1213    case 0x10:  /* EMIFS_CS0_CONFIG */
1214    case 0x14:  /* EMIFS_CS1_CONFIG */
1215    case 0x18:  /* EMIFS_CS2_CONFIG */
1216    case 0x1c:  /* EMIFS_CS3_CONFIG */
1217    case 0x24:  /* EMIFF_MRS */
1218    case 0x28:  /* TIMEOUT1 */
1219    case 0x2c:  /* TIMEOUT2 */
1220    case 0x30:  /* TIMEOUT3 */
1221    case 0x3c:  /* EMIFF_SDRAM_CONFIG_2 */
1222    case 0x40:  /* EMIFS_CFG_DYN_WAIT */
1223        return s->tcmi_regs[addr >> 2];
1224
1225    case 0x20:  /* EMIFF_SDRAM_CONFIG */
1226        ret = s->tcmi_regs[addr >> 2];
1227        s->tcmi_regs[addr >> 2] &= ~1; /* XXX: Clear SLRF on SDRAM access */
1228        /* XXX: We can try using the VGA_DIRTY flag for this */
1229        return ret;
1230    }
1231
1232    OMAP_BAD_REG(addr);
1233    return 0;
1234}
1235
1236static void omap_tcmi_write(void *opaque, target_phys_addr_t addr,
1237                uint32_t value)
1238{
1239    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
1240
1241    switch (addr) {
1242    case 0x00:  /* IMIF_PRIO */
1243    case 0x04:  /* EMIFS_PRIO */
1244    case 0x08:  /* EMIFF_PRIO */
1245    case 0x10:  /* EMIFS_CS0_CONFIG */
1246    case 0x14:  /* EMIFS_CS1_CONFIG */
1247    case 0x18:  /* EMIFS_CS2_CONFIG */
1248    case 0x1c:  /* EMIFS_CS3_CONFIG */
1249    case 0x20:  /* EMIFF_SDRAM_CONFIG */
1250    case 0x24:  /* EMIFF_MRS */
1251    case 0x28:  /* TIMEOUT1 */
1252    case 0x2c:  /* TIMEOUT2 */
1253    case 0x30:  /* TIMEOUT3 */
1254    case 0x3c:  /* EMIFF_SDRAM_CONFIG_2 */
1255    case 0x40:  /* EMIFS_CFG_DYN_WAIT */
1256        s->tcmi_regs[addr >> 2] = value;
1257        break;
1258    case 0x0c:  /* EMIFS_CONFIG */
1259        s->tcmi_regs[addr >> 2] = (value & 0xf) | (1 << 4);
1260        break;
1261
1262    default:
1263        OMAP_BAD_REG(addr);
1264    }
1265}
1266
1267static CPUReadMemoryFunc * const omap_tcmi_readfn[] = {
1268    omap_badwidth_read32,
1269    omap_badwidth_read32,
1270    omap_tcmi_read,
1271};
1272
1273static CPUWriteMemoryFunc * const omap_tcmi_writefn[] = {
1274    omap_badwidth_write32,
1275    omap_badwidth_write32,
1276    omap_tcmi_write,
1277};
1278
1279static void omap_tcmi_reset(struct omap_mpu_state_s *mpu)
1280{
1281    mpu->tcmi_regs[0x00 >> 2] = 0x00000000;
1282    mpu->tcmi_regs[0x04 >> 2] = 0x00000000;
1283    mpu->tcmi_regs[0x08 >> 2] = 0x00000000;
1284    mpu->tcmi_regs[0x0c >> 2] = 0x00000010;
1285    mpu->tcmi_regs[0x10 >> 2] = 0x0010fffb;
1286    mpu->tcmi_regs[0x14 >> 2] = 0x0010fffb;
1287    mpu->tcmi_regs[0x18 >> 2] = 0x0010fffb;
1288    mpu->tcmi_regs[0x1c >> 2] = 0x0010fffb;
1289    mpu->tcmi_regs[0x20 >> 2] = 0x00618800;
1290    mpu->tcmi_regs[0x24 >> 2] = 0x00000037;
1291    mpu->tcmi_regs[0x28 >> 2] = 0x00000000;
1292    mpu->tcmi_regs[0x2c >> 2] = 0x00000000;
1293    mpu->tcmi_regs[0x30 >> 2] = 0x00000000;
1294    mpu->tcmi_regs[0x3c >> 2] = 0x00000003;
1295    mpu->tcmi_regs[0x40 >> 2] = 0x00000000;
1296}
1297
1298static void omap_tcmi_init(target_phys_addr_t base,
1299                struct omap_mpu_state_s *mpu)
1300{
1301    int iomemtype = cpu_register_io_memory(omap_tcmi_readfn,
1302                    omap_tcmi_writefn, mpu, DEVICE_NATIVE_ENDIAN);
1303
1304    cpu_register_physical_memory(base, 0x100, iomemtype);
1305    omap_tcmi_reset(mpu);
1306}
1307
1308/* Digital phase-locked loops control */
1309static uint32_t omap_dpll_read(void *opaque, target_phys_addr_t addr)
1310{
1311    struct dpll_ctl_s *s = (struct dpll_ctl_s *) opaque;
1312
1313    if (addr == 0x00)   /* CTL_REG */
1314        return s->mode;
1315
1316    OMAP_BAD_REG(addr);
1317    return 0;
1318}
1319
1320static void omap_dpll_write(void *opaque, target_phys_addr_t addr,
1321                uint32_t value)
1322{
1323    struct dpll_ctl_s *s = (struct dpll_ctl_s *) opaque;
1324    uint16_t diff;
1325    static const int bypass_div[4] = { 1, 2, 4, 4 };
1326    int div, mult;
1327
1328    if (addr == 0x00) { /* CTL_REG */
1329        /* See omap_ulpd_pm_write() too */
1330        diff = s->mode & value;
1331        s->mode = value & 0x2fff;
1332        if (diff & (0x3ff << 2)) {
1333            if (value & (1 << 4)) {                     /* PLL_ENABLE */
1334                div = ((value >> 5) & 3) + 1;           /* PLL_DIV */
1335                mult = MIN((value >> 7) & 0x1f, 1);     /* PLL_MULT */
1336            } else {
1337                div = bypass_div[((value >> 2) & 3)];   /* BYPASS_DIV */
1338                mult = 1;
1339            }
1340            omap_clk_setrate(s->dpll, div, mult);
1341        }
1342
1343        /* Enter the desired mode.  */
1344        s->mode = (s->mode & 0xfffe) | ((s->mode >> 4) & 1);
1345
1346        /* Act as if the lock is restored.  */
1347        s->mode |= 2;
1348    } else {
1349        OMAP_BAD_REG(addr);
1350    }
1351}
1352
1353static CPUReadMemoryFunc * const omap_dpll_readfn[] = {
1354    omap_badwidth_read16,
1355    omap_dpll_read,
1356    omap_badwidth_read16,
1357};
1358
1359static CPUWriteMemoryFunc * const omap_dpll_writefn[] = {
1360    omap_badwidth_write16,
1361    omap_dpll_write,
1362    omap_badwidth_write16,
1363};
1364
1365static void omap_dpll_reset(struct dpll_ctl_s *s)
1366{
1367    s->mode = 0x2002;
1368    omap_clk_setrate(s->dpll, 1, 1);
1369}
1370
1371static void omap_dpll_init(struct dpll_ctl_s *s, target_phys_addr_t base,
1372                omap_clk clk)
1373{
1374    int iomemtype = cpu_register_io_memory(omap_dpll_readfn,
1375                    omap_dpll_writefn, s, DEVICE_NATIVE_ENDIAN);
1376
1377    s->dpll = clk;
1378    omap_dpll_reset(s);
1379
1380    cpu_register_physical_memory(base, 0x100, iomemtype);
1381}
1382
1383/* MPU Clock/Reset/Power Mode Control */
1384static uint32_t omap_clkm_read(void *opaque, target_phys_addr_t addr)
1385{
1386    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
1387
1388    switch (addr) {
1389    case 0x00:  /* ARM_CKCTL */
1390        return s->clkm.arm_ckctl;
1391
1392    case 0x04:  /* ARM_IDLECT1 */
1393        return s->clkm.arm_idlect1;
1394
1395    case 0x08:  /* ARM_IDLECT2 */
1396        return s->clkm.arm_idlect2;
1397
1398    case 0x0c:  /* ARM_EWUPCT */
1399        return s->clkm.arm_ewupct;
1400
1401    case 0x10:  /* ARM_RSTCT1 */
1402        return s->clkm.arm_rstct1;
1403
1404    case 0x14:  /* ARM_RSTCT2 */
1405        return s->clkm.arm_rstct2;
1406
1407    case 0x18:  /* ARM_SYSST */
1408        return (s->clkm.clocking_scheme << 11) | s->clkm.cold_start;
1409
1410    case 0x1c:  /* ARM_CKOUT1 */
1411        return s->clkm.arm_ckout1;
1412
1413    case 0x20:  /* ARM_CKOUT2 */
1414        break;
1415    }
1416
1417    OMAP_BAD_REG(addr);
1418    return 0;
1419}
1420
1421static inline void omap_clkm_ckctl_update(struct omap_mpu_state_s *s,
1422                uint16_t diff, uint16_t value)
1423{
1424    omap_clk clk;
1425
1426    if (diff & (1 << 14)) {                             /* ARM_INTHCK_SEL */
1427        if (value & (1 << 14))
1428            /* Reserved */;
1429        else {
1430            clk = omap_findclk(s, "arminth_ck");
1431            omap_clk_reparent(clk, omap_findclk(s, "tc_ck"));
1432        }
1433    }
1434    if (diff & (1 << 12)) {                             /* ARM_TIMXO */
1435        clk = omap_findclk(s, "armtim_ck");
1436        if (value & (1 << 12))
1437            omap_clk_reparent(clk, omap_findclk(s, "clkin"));
1438        else
1439            omap_clk_reparent(clk, omap_findclk(s, "ck_gen1"));
1440    }
1441    /* XXX: en_dspck */
1442    if (diff & (3 << 10)) {                             /* DSPMMUDIV */
1443        clk = omap_findclk(s, "dspmmu_ck");
1444        omap_clk_setrate(clk, 1 << ((value >> 10) & 3), 1);
1445    }
1446    if (diff & (3 << 8)) {                              /* TCDIV */
1447        clk = omap_findclk(s, "tc_ck");
1448        omap_clk_setrate(clk, 1 << ((value >> 8) & 3), 1);
1449    }
1450    if (diff & (3 << 6)) {                              /* DSPDIV */
1451        clk = omap_findclk(s, "dsp_ck");
1452        omap_clk_setrate(clk, 1 << ((value >> 6) & 3), 1);
1453    }
1454    if (diff & (3 << 4)) {                              /* ARMDIV */
1455        clk = omap_findclk(s, "arm_ck");
1456        omap_clk_setrate(clk, 1 << ((value >> 4) & 3), 1);
1457    }
1458    if (diff & (3 << 2)) {                              /* LCDDIV */
1459        clk = omap_findclk(s, "lcd_ck");
1460        omap_clk_setrate(clk, 1 << ((value >> 2) & 3), 1);
1461    }
1462    if (diff & (3 << 0)) {                              /* PERDIV */
1463        clk = omap_findclk(s, "armper_ck");
1464        omap_clk_setrate(clk, 1 << ((value >> 0) & 3), 1);
1465    }
1466}
1467
1468static inline void omap_clkm_idlect1_update(struct omap_mpu_state_s *s,
1469                uint16_t diff, uint16_t value)
1470{
1471    omap_clk clk;
1472
1473    if (value & (1 << 11))                              /* SETARM_IDLE */
1474        cpu_interrupt(s->env, CPU_INTERRUPT_HALT);
1475    if (!(value & (1 << 10)))                           /* WKUP_MODE */
1476        qemu_system_shutdown_request(); /* XXX: disable wakeup from IRQ */
1477
1478#define SET_CANIDLE(clock, bit)                         \
1479    if (diff & (1 << bit)) {                            \
1480        clk = omap_findclk(s, clock);                   \
1481        omap_clk_canidle(clk, (value >> bit) & 1);      \
1482    }
1483    SET_CANIDLE("mpuwd_ck", 0)                          /* IDLWDT_ARM */
1484    SET_CANIDLE("armxor_ck", 1)                         /* IDLXORP_ARM */
1485    SET_CANIDLE("mpuper_ck", 2)                         /* IDLPER_ARM */
1486    SET_CANIDLE("lcd_ck", 3)                            /* IDLLCD_ARM */
1487    SET_CANIDLE("lb_ck", 4)                             /* IDLLB_ARM */
1488    SET_CANIDLE("hsab_ck", 5)                           /* IDLHSAB_ARM */
1489    SET_CANIDLE("tipb_ck", 6)                           /* IDLIF_ARM */
1490    SET_CANIDLE("dma_ck", 6)                            /* IDLIF_ARM */
1491    SET_CANIDLE("tc_ck", 6)                             /* IDLIF_ARM */
1492    SET_CANIDLE("dpll1", 7)                             /* IDLDPLL_ARM */
1493    SET_CANIDLE("dpll2", 7)                             /* IDLDPLL_ARM */
1494    SET_CANIDLE("dpll3", 7)                             /* IDLDPLL_ARM */
1495    SET_CANIDLE("mpui_ck", 8)                           /* IDLAPI_ARM */
1496    SET_CANIDLE("armtim_ck", 9)                         /* IDLTIM_ARM */
1497}
1498
1499static inline void omap_clkm_idlect2_update(struct omap_mpu_state_s *s,
1500                uint16_t diff, uint16_t value)
1501{
1502    omap_clk clk;
1503
1504#define SET_ONOFF(clock, bit)                           \
1505    if (diff & (1 << bit)) {                            \
1506        clk = omap_findclk(s, clock);                   \
1507        omap_clk_onoff(clk, (value >> bit) & 1);        \
1508    }
1509    SET_ONOFF("mpuwd_ck", 0)                            /* EN_WDTCK */
1510    SET_ONOFF("armxor_ck", 1)                           /* EN_XORPCK */
1511    SET_ONOFF("mpuper_ck", 2)                           /* EN_PERCK */
1512    SET_ONOFF("lcd_ck", 3)                              /* EN_LCDCK */
1513    SET_ONOFF("lb_ck", 4)                               /* EN_LBCK */
1514    SET_ONOFF("hsab_ck", 5)                             /* EN_HSABCK */
1515    SET_ONOFF("mpui_ck", 6)                             /* EN_APICK */
1516    SET_ONOFF("armtim_ck", 7)                           /* EN_TIMCK */
1517    SET_CANIDLE("dma_ck", 8)                            /* DMACK_REQ */
1518    SET_ONOFF("arm_gpio_ck", 9)                         /* EN_GPIOCK */
1519    SET_ONOFF("lbfree_ck", 10)                          /* EN_LBFREECK */
1520}
1521
1522static inline void omap_clkm_ckout1_update(struct omap_mpu_state_s *s,
1523                uint16_t diff, uint16_t value)
1524{
1525    omap_clk clk;
1526
1527    if (diff & (3 << 4)) {                              /* TCLKOUT */
1528        clk = omap_findclk(s, "tclk_out");
1529        switch ((value >> 4) & 3) {
1530        case 1:
1531            omap_clk_reparent(clk, omap_findclk(s, "ck_gen3"));
1532            omap_clk_onoff(clk, 1);
1533            break;
1534        case 2:
1535            omap_clk_reparent(clk, omap_findclk(s, "tc_ck"));
1536            omap_clk_onoff(clk, 1);
1537            break;
1538        default:
1539            omap_clk_onoff(clk, 0);
1540        }
1541    }
1542    if (diff & (3 << 2)) {                              /* DCLKOUT */
1543        clk = omap_findclk(s, "dclk_out");
1544        switch ((value >> 2) & 3) {
1545        case 0:
1546            omap_clk_reparent(clk, omap_findclk(s, "dspmmu_ck"));
1547            break;
1548        case 1:
1549            omap_clk_reparent(clk, omap_findclk(s, "ck_gen2"));
1550            break;
1551        case 2:
1552            omap_clk_reparent(clk, omap_findclk(s, "dsp_ck"));
1553            break;
1554        case 3:
1555            omap_clk_reparent(clk, omap_findclk(s, "ck_ref14"));
1556            break;
1557        }
1558    }
1559    if (diff & (3 << 0)) {                              /* ACLKOUT */
1560        clk = omap_findclk(s, "aclk_out");
1561        switch ((value >> 0) & 3) {
1562        case 1:
1563            omap_clk_reparent(clk, omap_findclk(s, "ck_gen1"));
1564            omap_clk_onoff(clk, 1);
1565            break;
1566        case 2:
1567            omap_clk_reparent(clk, omap_findclk(s, "arm_ck"));
1568            omap_clk_onoff(clk, 1);
1569            break;
1570        case 3:
1571            omap_clk_reparent(clk, omap_findclk(s, "ck_ref14"));
1572            omap_clk_onoff(clk, 1);
1573            break;
1574        default:
1575            omap_clk_onoff(clk, 0);
1576        }
1577    }
1578}
1579
1580static void omap_clkm_write(void *opaque, target_phys_addr_t addr,
1581                uint32_t value)
1582{
1583    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
1584    uint16_t diff;
1585    omap_clk clk;
1586    static const char *clkschemename[8] = {
1587        "fully synchronous", "fully asynchronous", "synchronous scalable",
1588        "mix mode 1", "mix mode 2", "bypass mode", "mix mode 3", "mix mode 4",
1589    };
1590
1591    switch (addr) {
1592    case 0x00:  /* ARM_CKCTL */
1593        diff = s->clkm.arm_ckctl ^ value;
1594        s->clkm.arm_ckctl = value & 0x7fff;
1595        omap_clkm_ckctl_update(s, diff, value);
1596        return;
1597
1598    case 0x04:  /* ARM_IDLECT1 */
1599        diff = s->clkm.arm_idlect1 ^ value;
1600        s->clkm.arm_idlect1 = value & 0x0fff;
1601        omap_clkm_idlect1_update(s, diff, value);
1602        return;
1603
1604    case 0x08:  /* ARM_IDLECT2 */
1605        diff = s->clkm.arm_idlect2 ^ value;
1606        s->clkm.arm_idlect2 = value & 0x07ff;
1607        omap_clkm_idlect2_update(s, diff, value);
1608        return;
1609
1610    case 0x0c:  /* ARM_EWUPCT */
1611        s->clkm.arm_ewupct = value & 0x003f;
1612        return;
1613
1614    case 0x10:  /* ARM_RSTCT1 */
1615        diff = s->clkm.arm_rstct1 ^ value;
1616        s->clkm.arm_rstct1 = value & 0x0007;
1617        if (value & 9) {
1618            qemu_system_reset_request();
1619            s->clkm.cold_start = 0xa;
1620        }
1621        if (diff & ~value & 4) {                                /* DSP_RST */
1622            omap_mpui_reset(s);
1623            omap_tipb_bridge_reset(s->private_tipb);
1624            omap_tipb_bridge_reset(s->public_tipb);
1625        }
1626        if (diff & 2) {                                         /* DSP_EN */
1627            clk = omap_findclk(s, "dsp_ck");
1628            omap_clk_canidle(clk, (~value >> 1) & 1);
1629        }
1630        return;
1631
1632    case 0x14:  /* ARM_RSTCT2 */
1633        s->clkm.arm_rstct2 = value & 0x0001;
1634        return;
1635
1636    case 0x18:  /* ARM_SYSST */
1637        if ((s->clkm.clocking_scheme ^ (value >> 11)) & 7) {
1638            s->clkm.clocking_scheme = (value >> 11) & 7;
1639            printf("%s: clocking scheme set to %s\n", __FUNCTION__,
1640                            clkschemename[s->clkm.clocking_scheme]);
1641        }
1642        s->clkm.cold_start &= value & 0x3f;
1643        return;
1644
1645    case 0x1c:  /* ARM_CKOUT1 */
1646        diff = s->clkm.arm_ckout1 ^ value;
1647        s->clkm.arm_ckout1 = value & 0x003f;
1648        omap_clkm_ckout1_update(s, diff, value);
1649        return;
1650
1651    case 0x20:  /* ARM_CKOUT2 */
1652    default:
1653        OMAP_BAD_REG(addr);
1654    }
1655}
1656
1657static CPUReadMemoryFunc * const omap_clkm_readfn[] = {
1658    omap_badwidth_read16,
1659    omap_clkm_read,
1660    omap_badwidth_read16,
1661};
1662
1663static CPUWriteMemoryFunc * const omap_clkm_writefn[] = {
1664    omap_badwidth_write16,
1665    omap_clkm_write,
1666    omap_badwidth_write16,
1667};
1668
1669static uint32_t omap_clkdsp_read(void *opaque, target_phys_addr_t addr)
1670{
1671    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
1672
1673    switch (addr) {
1674    case 0x04:  /* DSP_IDLECT1 */
1675        return s->clkm.dsp_idlect1;
1676
1677    case 0x08:  /* DSP_IDLECT2 */
1678        return s->clkm.dsp_idlect2;
1679
1680    case 0x14:  /* DSP_RSTCT2 */
1681        return s->clkm.dsp_rstct2;
1682
1683    case 0x18:  /* DSP_SYSST */
1684        return (s->clkm.clocking_scheme << 11) | s->clkm.cold_start |
1685                (s->env->halted << 6);  /* Quite useless... */
1686    }
1687
1688    OMAP_BAD_REG(addr);
1689    return 0;
1690}
1691
1692static inline void omap_clkdsp_idlect1_update(struct omap_mpu_state_s *s,
1693                uint16_t diff, uint16_t value)
1694{
1695    omap_clk clk;
1696
1697    SET_CANIDLE("dspxor_ck", 1);                        /* IDLXORP_DSP */
1698}
1699
1700static inline void omap_clkdsp_idlect2_update(struct omap_mpu_state_s *s,
1701                uint16_t diff, uint16_t value)
1702{
1703    omap_clk clk;
1704
1705    SET_ONOFF("dspxor_ck", 1);                          /* EN_XORPCK */
1706}
1707
1708static void omap_clkdsp_write(void *opaque, target_phys_addr_t addr,
1709                uint32_t value)
1710{
1711    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
1712    uint16_t diff;
1713
1714    switch (addr) {
1715    case 0x04:  /* DSP_IDLECT1 */
1716        diff = s->clkm.dsp_idlect1 ^ value;
1717        s->clkm.dsp_idlect1 = value & 0x01f7;
1718        omap_clkdsp_idlect1_update(s, diff, value);
1719        break;
1720
1721    case 0x08:  /* DSP_IDLECT2 */
1722        s->clkm.dsp_idlect2 = value & 0x0037;
1723        diff = s->clkm.dsp_idlect1 ^ value;
1724        omap_clkdsp_idlect2_update(s, diff, value);
1725        break;
1726
1727    case 0x14:  /* DSP_RSTCT2 */
1728        s->clkm.dsp_rstct2 = value & 0x0001;
1729        break;
1730
1731    case 0x18:  /* DSP_SYSST */
1732        s->clkm.cold_start &= value & 0x3f;
1733        break;
1734
1735    default:
1736        OMAP_BAD_REG(addr);
1737    }
1738}
1739
1740static CPUReadMemoryFunc * const omap_clkdsp_readfn[] = {
1741    omap_badwidth_read16,
1742    omap_clkdsp_read,
1743    omap_badwidth_read16,
1744};
1745
1746static CPUWriteMemoryFunc * const omap_clkdsp_writefn[] = {
1747    omap_badwidth_write16,
1748    omap_clkdsp_write,
1749    omap_badwidth_write16,
1750};
1751
1752static void omap_clkm_reset(struct omap_mpu_state_s *s)
1753{
1754    if (s->wdt && s->wdt->reset)
1755        s->clkm.cold_start = 0x6;
1756    s->clkm.clocking_scheme = 0;
1757    omap_clkm_ckctl_update(s, ~0, 0x3000);
1758    s->clkm.arm_ckctl = 0x3000;
1759    omap_clkm_idlect1_update(s, s->clkm.arm_idlect1 ^ 0x0400, 0x0400);
1760    s->clkm.arm_idlect1 = 0x0400;
1761    omap_clkm_idlect2_update(s, s->clkm.arm_idlect2 ^ 0x0100, 0x0100);
1762    s->clkm.arm_idlect2 = 0x0100;
1763    s->clkm.arm_ewupct = 0x003f;
1764    s->clkm.arm_rstct1 = 0x0000;
1765    s->clkm.arm_rstct2 = 0x0000;
1766    s->clkm.arm_ckout1 = 0x0015;
1767    s->clkm.dpll1_mode = 0x2002;
1768    omap_clkdsp_idlect1_update(s, s->clkm.dsp_idlect1 ^ 0x0040, 0x0040);
1769    s->clkm.dsp_idlect1 = 0x0040;
1770    omap_clkdsp_idlect2_update(s, ~0, 0x0000);
1771    s->clkm.dsp_idlect2 = 0x0000;
1772    s->clkm.dsp_rstct2 = 0x0000;
1773}
1774
1775static void omap_clkm_init(target_phys_addr_t mpu_base,
1776                target_phys_addr_t dsp_base, struct omap_mpu_state_s *s)
1777{
1778    int iomemtype[2] = {
1779        cpu_register_io_memory(omap_clkm_readfn, omap_clkm_writefn, s,
1780                               DEVICE_NATIVE_ENDIAN),
1781        cpu_register_io_memory(omap_clkdsp_readfn, omap_clkdsp_writefn, s,
1782                               DEVICE_NATIVE_ENDIAN),
1783    };
1784
1785    s->clkm.arm_idlect1 = 0x03ff;
1786    s->clkm.arm_idlect2 = 0x0100;
1787    s->clkm.dsp_idlect1 = 0x0002;
1788    omap_clkm_reset(s);
1789    s->clkm.cold_start = 0x3a;
1790
1791    cpu_register_physical_memory(mpu_base, 0x100, iomemtype[0]);
1792    cpu_register_physical_memory(dsp_base, 0x1000, iomemtype[1]);
1793}
1794
1795/* MPU I/O */
1796struct omap_mpuio_s {
1797    qemu_irq irq;
1798    qemu_irq kbd_irq;
1799    qemu_irq *in;
1800    qemu_irq handler[16];
1801    qemu_irq wakeup;
1802
1803    uint16_t inputs;
1804    uint16_t outputs;
1805    uint16_t dir;
1806    uint16_t edge;
1807    uint16_t mask;
1808    uint16_t ints;
1809
1810    uint16_t debounce;
1811    uint16_t latch;
1812    uint8_t event;
1813
1814    uint8_t buttons[5];
1815    uint8_t row_latch;
1816    uint8_t cols;
1817    int kbd_mask;
1818    int clk;
1819};
1820
1821static void omap_mpuio_set(void *opaque, int line, int level)
1822{
1823    struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
1824    uint16_t prev = s->inputs;
1825
1826    if (level)
1827        s->inputs |= 1 << line;
1828    else
1829        s->inputs &= ~(1 << line);
1830
1831    if (((1 << line) & s->dir & ~s->mask) && s->clk) {
1832        if ((s->edge & s->inputs & ~prev) | (~s->edge & ~s->inputs & prev)) {
1833            s->ints |= 1 << line;
1834            qemu_irq_raise(s->irq);
1835            /* TODO: wakeup */
1836        }
1837        if ((s->event & (1 << 0)) &&            /* SET_GPIO_EVENT_MODE */
1838                (s->event >> 1) == line)        /* PIN_SELECT */
1839            s->latch = s->inputs;
1840    }
1841}
1842
1843static void omap_mpuio_kbd_update(struct omap_mpuio_s *s)
1844{
1845    int i;
1846    uint8_t *row, rows = 0, cols = ~s->cols;
1847
1848    for (row = s->buttons + 4, i = 1 << 4; i; row --, i >>= 1)
1849        if (*row & cols)
1850            rows |= i;
1851
1852    qemu_set_irq(s->kbd_irq, rows && !s->kbd_mask && s->clk);
1853    s->row_latch = ~rows;
1854}
1855
1856static uint32_t omap_mpuio_read(void *opaque, target_phys_addr_t addr)
1857{
1858    struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
1859    int offset = addr & OMAP_MPUI_REG_MASK;
1860    uint16_t ret;
1861
1862    switch (offset) {
1863    case 0x00:  /* INPUT_LATCH */
1864        return s->inputs;
1865
1866    case 0x04:  /* OUTPUT_REG */
1867        return s->outputs;
1868
1869    case 0x08:  /* IO_CNTL */
1870        return s->dir;
1871
1872    case 0x10:  /* KBR_LATCH */
1873        return s->row_latch;
1874
1875    case 0x14:  /* KBC_REG */
1876        return s->cols;
1877
1878    case 0x18:  /* GPIO_EVENT_MODE_REG */
1879        return s->event;
1880
1881    case 0x1c:  /* GPIO_INT_EDGE_REG */
1882        return s->edge;
1883
1884    case 0x20:  /* KBD_INT */
1885        return (~s->row_latch & 0x1f) && !s->kbd_mask;
1886
1887    case 0x24:  /* GPIO_INT */
1888        ret = s->ints;
1889        s->ints &= s->mask;
1890        if (ret)
1891            qemu_irq_lower(s->irq);
1892        return ret;
1893
1894    case 0x28:  /* KBD_MASKIT */
1895        return s->kbd_mask;
1896
1897    case 0x2c:  /* GPIO_MASKIT */
1898        return s->mask;
1899
1900    case 0x30:  /* GPIO_DEBOUNCING_REG */
1901        return s->debounce;
1902
1903    case 0x34:  /* GPIO_LATCH_REG */
1904        return s->latch;
1905    }
1906
1907    OMAP_BAD_REG(addr);
1908    return 0;
1909}
1910
1911static void omap_mpuio_write(void *opaque, target_phys_addr_t addr,
1912                uint32_t value)
1913{
1914    struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
1915    int offset = addr & OMAP_MPUI_REG_MASK;
1916    uint16_t diff;
1917    int ln;
1918
1919    switch (offset) {
1920    case 0x04:  /* OUTPUT_REG */
1921        diff = (s->outputs ^ value) & ~s->dir;
1922        s->outputs = value;
1923        while ((ln = ffs(diff))) {
1924            ln --;
1925            if (s->handler[ln])
1926                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
1927            diff &= ~(1 << ln);
1928        }
1929        break;
1930
1931    case 0x08:  /* IO_CNTL */
1932        diff = s->outputs & (s->dir ^ value);
1933        s->dir = value;
1934
1935        value = s->outputs & ~s->dir;
1936        while ((ln = ffs(diff))) {
1937            ln --;
1938            if (s->handler[ln])
1939                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
1940            diff &= ~(1 << ln);
1941        }
1942        break;
1943
1944    case 0x14:  /* KBC_REG */
1945        s->cols = value;
1946        omap_mpuio_kbd_update(s);
1947        break;
1948
1949    case 0x18:  /* GPIO_EVENT_MODE_REG */
1950        s->event = value & 0x1f;
1951        break;
1952
1953    case 0x1c:  /* GPIO_INT_EDGE_REG */
1954        s->edge = value;
1955        break;
1956
1957    case 0x28:  /* KBD_MASKIT */
1958        s->kbd_mask = value & 1;
1959        omap_mpuio_kbd_update(s);
1960        break;
1961
1962    case 0x2c:  /* GPIO_MASKIT */
1963        s->mask = value;
1964        break;
1965
1966    case 0x30:  /* GPIO_DEBOUNCING_REG */
1967        s->debounce = value & 0x1ff;
1968        break;
1969
1970    case 0x00:  /* INPUT_LATCH */
1971    case 0x10:  /* KBR_LATCH */
1972    case 0x20:  /* KBD_INT */
1973    case 0x24:  /* GPIO_INT */
1974    case 0x34:  /* GPIO_LATCH_REG */
1975        OMAP_RO_REG(addr);
1976        return;
1977
1978    default:
1979        OMAP_BAD_REG(addr);
1980        return;
1981    }
1982}
1983
1984static CPUReadMemoryFunc * const omap_mpuio_readfn[] = {
1985    omap_badwidth_read16,
1986    omap_mpuio_read,
1987    omap_badwidth_read16,
1988};
1989
1990static CPUWriteMemoryFunc * const omap_mpuio_writefn[] = {
1991    omap_badwidth_write16,
1992    omap_mpuio_write,
1993    omap_badwidth_write16,
1994};
1995
1996static void omap_mpuio_reset(struct omap_mpuio_s *s)
1997{
1998    s->inputs = 0;
1999    s->outputs = 0;
2000    s->dir = ~0;
2001    s->event = 0;
2002    s->edge = 0;
2003    s->kbd_mask = 0;
2004    s->mask = 0;
2005    s->debounce = 0;
2006    s->latch = 0;
2007    s->ints = 0;
2008    s->row_latch = 0x1f;
2009    s->clk = 1;
2010}
2011
2012static void omap_mpuio_onoff(void *opaque, int line, int on)
2013{
2014    struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
2015
2016    s->clk = on;
2017    if (on)
2018        omap_mpuio_kbd_update(s);
2019}
2020
2021struct omap_mpuio_s *omap_mpuio_init(target_phys_addr_t base,
2022                qemu_irq kbd_int, qemu_irq gpio_int, qemu_irq wakeup,
2023                omap_clk clk)
2024{
2025    int iomemtype;
2026    struct omap_mpuio_s *s = (struct omap_mpuio_s *)
2027            qemu_mallocz(sizeof(struct omap_mpuio_s));
2028
2029    s->irq = gpio_int;
2030    s->kbd_irq = kbd_int;
2031    s->wakeup = wakeup;
2032    s->in = qemu_allocate_irqs(omap_mpuio_set, s, 16);
2033    omap_mpuio_reset(s);
2034
2035    iomemtype = cpu_register_io_memory(omap_mpuio_readfn,
2036                    omap_mpuio_writefn, s, DEVICE_NATIVE_ENDIAN);
2037    cpu_register_physical_memory(base, 0x800, iomemtype);
2038
2039    omap_clk_adduser(clk, qemu_allocate_irqs(omap_mpuio_onoff, s, 1)[0]);
2040
2041    return s;
2042}
2043
2044qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s)
2045{
2046    return s->in;
2047}
2048
2049void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler)
2050{
2051    if (line >= 16 || line < 0)
2052        hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
2053    s->handler[line] = handler;
2054}
2055
2056void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down)
2057{
2058    if (row >= 5 || row < 0)
2059        hw_error("%s: No key %i-%i\n", __FUNCTION__, col, row);
2060
2061    if (down)
2062        s->buttons[row] |= 1 << col;
2063    else
2064        s->buttons[row] &= ~(1 << col);
2065
2066    omap_mpuio_kbd_update(s);
2067}
2068
2069/* MicroWire Interface */
2070struct omap_uwire_s {
2071    qemu_irq txirq;
2072    qemu_irq rxirq;
2073    qemu_irq txdrq;
2074
2075    uint16_t txbuf;
2076    uint16_t rxbuf;
2077    uint16_t control;
2078    uint16_t setup[5];
2079
2080    uWireSlave *chip[4];
2081};
2082
2083static void omap_uwire_transfer_start(struct omap_uwire_s *s)
2084{
2085    int chipselect = (s->control >> 10) & 3;            /* INDEX */
2086    uWireSlave *slave = s->chip[chipselect];
2087
2088    if ((s->control >> 5) & 0x1f) {                     /* NB_BITS_WR */
2089        if (s->control & (1 << 12))                     /* CS_CMD */
2090            if (slave && slave->send)
2091                slave->send(slave->opaque,
2092                                s->txbuf >> (16 - ((s->control >> 5) & 0x1f)));
2093        s->control &= ~(1 << 14);                       /* CSRB */
2094        /* TODO: depending on s->setup[4] bits [1:0] assert an IRQ or
2095         * a DRQ.  When is the level IRQ supposed to be reset?  */
2096    }
2097
2098    if ((s->control >> 0) & 0x1f) {                     /* NB_BITS_RD */
2099        if (s->control & (1 << 12))                     /* CS_CMD */
2100            if (slave && slave->receive)
2101                s->rxbuf = slave->receive(slave->opaque);
2102        s->control |= 1 << 15;                          /* RDRB */
2103        /* TODO: depending on s->setup[4] bits [1:0] assert an IRQ or
2104         * a DRQ.  When is the level IRQ supposed to be reset?  */
2105    }
2106}
2107
2108static uint32_t omap_uwire_read(void *opaque, target_phys_addr_t addr)
2109{
2110    struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
2111    int offset = addr & OMAP_MPUI_REG_MASK;
2112
2113    switch (offset) {
2114    case 0x00:  /* RDR */
2115        s->control &= ~(1 << 15);                       /* RDRB */
2116        return s->rxbuf;
2117
2118    case 0x04:  /* CSR */
2119        return s->control;
2120
2121    case 0x08:  /* SR1 */
2122        return s->setup[0];
2123    case 0x0c:  /* SR2 */
2124        return s->setup[1];
2125    case 0x10:  /* SR3 */
2126        return s->setup[2];
2127    case 0x14:  /* SR4 */
2128        return s->setup[3];
2129    case 0x18:  /* SR5 */
2130        return s->setup[4];
2131    }
2132
2133    OMAP_BAD_REG(addr);
2134    return 0;
2135}
2136
2137static void omap_uwire_write(void *opaque, target_phys_addr_t addr,
2138                uint32_t value)
2139{
2140    struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
2141    int offset = addr & OMAP_MPUI_REG_MASK;
2142
2143    switch (offset) {
2144    case 0x00:  /* TDR */
2145        s->txbuf = value;                               /* TD */
2146        if ((s->setup[4] & (1 << 2)) &&                 /* AUTO_TX_EN */
2147                        ((s->setup[4] & (1 << 3)) ||    /* CS_TOGGLE_TX_EN */
2148                         (s->control & (1 << 12)))) {   /* CS_CMD */
2149            s->control |= 1 << 14;                      /* CSRB */
2150            omap_uwire_transfer_start(s);
2151        }
2152        break;
2153
2154    case 0x04:  /* CSR */
2155        s->control = value & 0x1fff;
2156        if (value & (1 << 13))                          /* START */
2157            omap_uwire_transfer_start(s);
2158        break;
2159
2160    case 0x08:  /* SR1 */
2161        s->setup[0] = value & 0x003f;
2162        break;
2163
2164    case 0x0c:  /* SR2 */
2165        s->setup[1] = value & 0x0fc0;
2166        break;
2167
2168    case 0x10:  /* SR3 */
2169        s->setup[2] = value & 0x0003;
2170        break;
2171
2172    case 0x14:  /* SR4 */
2173        s->setup[3] = value & 0x0001;
2174        break;
2175
2176    case 0x18:  /* SR5 */
2177        s->setup[4] = value & 0x000f;
2178        break;
2179
2180    default:
2181        OMAP_BAD_REG(addr);
2182        return;
2183    }
2184}
2185
2186static CPUReadMemoryFunc * const omap_uwire_readfn[] = {
2187    omap_badwidth_read16,
2188    omap_uwire_read,
2189    omap_badwidth_read16,
2190};
2191
2192static CPUWriteMemoryFunc * const omap_uwire_writefn[] = {
2193    omap_badwidth_write16,
2194    omap_uwire_write,
2195    omap_badwidth_write16,
2196};
2197
2198static void omap_uwire_reset(struct omap_uwire_s *s)
2199{
2200    s->control = 0;
2201    s->setup[0] = 0;
2202    s->setup[1] = 0;
2203    s->setup[2] = 0;
2204    s->setup[3] = 0;
2205    s->setup[4] = 0;
2206}
2207
2208struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base,
2209                qemu_irq *irq, qemu_irq dma, omap_clk clk)
2210{
2211    int iomemtype;
2212    struct omap_uwire_s *s = (struct omap_uwire_s *)
2213            qemu_mallocz(sizeof(struct omap_uwire_s));
2214
2215    s->txirq = irq[0];
2216    s->rxirq = irq[1];
2217    s->txdrq = dma;
2218    omap_uwire_reset(s);
2219
2220    iomemtype = cpu_register_io_memory(omap_uwire_readfn,
2221                    omap_uwire_writefn, s, DEVICE_NATIVE_ENDIAN);
2222    cpu_register_physical_memory(base, 0x800, iomemtype);
2223
2224    return s;
2225}
2226
2227void omap_uwire_attach(struct omap_uwire_s *s,
2228                uWireSlave *slave, int chipselect)
2229{
2230    if (chipselect < 0 || chipselect > 3) {
2231        fprintf(stderr, "%s: Bad chipselect %i\n", __FUNCTION__, chipselect);
2232        exit(-1);
2233    }
2234
2235    s->chip[chipselect] = slave;
2236}
2237
2238/* Pseudonoise Pulse-Width Light Modulator */
2239static void omap_pwl_update(struct omap_mpu_state_s *s)
2240{
2241    int output = (s->pwl.clk && s->pwl.enable) ? s->pwl.level : 0;
2242
2243    if (output != s->pwl.output) {
2244        s->pwl.output = output;
2245        printf("%s: Backlight now at %i/256\n", __FUNCTION__, output);
2246    }
2247}
2248
2249static uint32_t omap_pwl_read(void *opaque, target_phys_addr_t addr)
2250{
2251    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
2252    int offset = addr & OMAP_MPUI_REG_MASK;
2253
2254    switch (offset) {
2255    case 0x00:  /* PWL_LEVEL */
2256        return s->pwl.level;
2257    case 0x04:  /* PWL_CTRL */
2258        return s->pwl.enable;
2259    }
2260    OMAP_BAD_REG(addr);
2261    return 0;
2262}
2263
2264static void omap_pwl_write(void *opaque, target_phys_addr_t addr,
2265                uint32_t value)
2266{
2267    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
2268    int offset = addr & OMAP_MPUI_REG_MASK;
2269
2270    switch (offset) {
2271    case 0x00:  /* PWL_LEVEL */
2272        s->pwl.level = value;
2273        omap_pwl_update(s);
2274        break;
2275    case 0x04:  /* PWL_CTRL */
2276        s->pwl.enable = value & 1;
2277        omap_pwl_update(s);
2278        break;
2279    default:
2280        OMAP_BAD_REG(addr);
2281        return;
2282    }
2283}
2284
2285static CPUReadMemoryFunc * const omap_pwl_readfn[] = {
2286    omap_pwl_read,
2287    omap_badwidth_read8,
2288    omap_badwidth_read8,
2289};
2290
2291static CPUWriteMemoryFunc * const omap_pwl_writefn[] = {
2292    omap_pwl_write,
2293    omap_badwidth_write8,
2294    omap_badwidth_write8,
2295};
2296
2297static void omap_pwl_reset(struct omap_mpu_state_s *s)
2298{
2299    s->pwl.output = 0;
2300    s->pwl.level = 0;
2301    s->pwl.enable = 0;
2302    s->pwl.clk = 1;
2303    omap_pwl_update(s);
2304}
2305
2306static void omap_pwl_clk_update(void *opaque, int line, int on)
2307{
2308    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
2309
2310    s->pwl.clk = on;
2311    omap_pwl_update(s);
2312}
2313
2314static void omap_pwl_init(target_phys_addr_t base, struct omap_mpu_state_s *s,
2315                omap_clk clk)
2316{
2317    int iomemtype;
2318
2319    omap_pwl_reset(s);
2320
2321    iomemtype = cpu_register_io_memory(omap_pwl_readfn,
2322                    omap_pwl_writefn, s, DEVICE_NATIVE_ENDIAN);
2323    cpu_register_physical_memory(base, 0x800, iomemtype);
2324
2325    omap_clk_adduser(clk, qemu_allocate_irqs(omap_pwl_clk_update, s, 1)[0]);
2326}
2327
2328/* Pulse-Width Tone module */
2329static uint32_t omap_pwt_read(void *opaque, target_phys_addr_t addr)
2330{
2331    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
2332    int offset = addr & OMAP_MPUI_REG_MASK;
2333
2334    switch (offset) {
2335    case 0x00:  /* FRC */
2336        return s->pwt.frc;
2337    case 0x04:  /* VCR */
2338        return s->pwt.vrc;
2339    case 0x08:  /* GCR */
2340        return s->pwt.gcr;
2341    }
2342    OMAP_BAD_REG(addr);
2343    return 0;
2344}
2345
2346static void omap_pwt_write(void *opaque, target_phys_addr_t addr,
2347                uint32_t value)
2348{
2349    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
2350    int offset = addr & OMAP_MPUI_REG_MASK;
2351
2352    switch (offset) {
2353    case 0x00:  /* FRC */
2354        s->pwt.frc = value & 0x3f;
2355        break;
2356    case 0x04:  /* VRC */
2357        if ((value ^ s->pwt.vrc) & 1) {
2358            if (value & 1)
2359                printf("%s: %iHz buzz on\n", __FUNCTION__, (int)
2360                                /* 1.5 MHz from a 12-MHz or 13-MHz PWT_CLK */
2361                                ((omap_clk_getrate(s->pwt.clk) >> 3) /
2362                                 /* Pre-multiplexer divider */
2363                                 ((s->pwt.gcr & 2) ? 1 : 154) /
2364                                 /* Octave multiplexer */
2365                                 (2 << (value & 3)) *
2366                                 /* 101/107 divider */
2367                                 ((value & (1 << 2)) ? 101 : 107) *
2368                                 /*  49/55 divider */
2369                                 ((value & (1 << 3)) ?  49 : 55) *
2370                                 /*  50/63 divider */
2371                                 ((value & (1 << 4)) ?  50 : 63) *
2372                                 /*  80/127 divider */
2373                                 ((value & (1 << 5)) ?  80 : 127) /
2374                                 (107 * 55 * 63 * 127)));
2375            else
2376                printf("%s: silence!\n", __FUNCTION__);
2377        }
2378        s->pwt.vrc = value & 0x7f;
2379        break;
2380    case 0x08:  /* GCR */
2381        s->pwt.gcr = value & 3;
2382        break;
2383    default:
2384        OMAP_BAD_REG(addr);
2385        return;
2386    }
2387}
2388
2389static CPUReadMemoryFunc * const omap_pwt_readfn[] = {
2390    omap_pwt_read,
2391    omap_badwidth_read8,
2392    omap_badwidth_read8,
2393};
2394
2395static CPUWriteMemoryFunc * const omap_pwt_writefn[] = {
2396    omap_pwt_write,
2397    omap_badwidth_write8,
2398    omap_badwidth_write8,
2399};
2400
2401static void omap_pwt_reset(struct omap_mpu_state_s *s)
2402{
2403    s->pwt.frc = 0;
2404    s->pwt.vrc = 0;
2405    s->pwt.gcr = 0;
2406}
2407
2408static void omap_pwt_init(target_phys_addr_t base, struct omap_mpu_state_s *s,
2409                omap_clk clk)
2410{
2411    int iomemtype;
2412
2413    s->pwt.clk = clk;
2414    omap_pwt_reset(s);
2415
2416    iomemtype = cpu_register_io_memory(omap_pwt_readfn,
2417                    omap_pwt_writefn, s, DEVICE_NATIVE_ENDIAN);
2418    cpu_register_physical_memory(base, 0x800, iomemtype);
2419}
2420
2421/* Real-time Clock module */
2422struct omap_rtc_s {
2423    qemu_irq irq;
2424    qemu_irq alarm;
2425    QEMUTimer *clk;
2426
2427    uint8_t interrupts;
2428    uint8_t status;
2429    int16_t comp_reg;
2430    int running;
2431    int pm_am;
2432    int auto_comp;
2433    int round;
2434    struct tm alarm_tm;
2435    time_t alarm_ti;
2436
2437    struct tm current_tm;
2438    time_t ti;
2439    uint64_t tick;
2440};
2441
2442static void omap_rtc_interrupts_update(struct omap_rtc_s *s)
2443{
2444    /* s->alarm is level-triggered */
2445    qemu_set_irq(s->alarm, (s->status >> 6) & 1);
2446}
2447
2448static void omap_rtc_alarm_update(struct omap_rtc_s *s)
2449{
2450    s->alarm_ti = mktimegm(&s->alarm_tm);
2451    if (s->alarm_ti == -1)
2452        printf("%s: conversion failed\n", __FUNCTION__);
2453}
2454
2455static uint32_t omap_rtc_read(void *opaque, target_phys_addr_t addr)
2456{
2457    struct omap_rtc_s *s = (struct omap_rtc_s *) opaque;
2458    int offset = addr & OMAP_MPUI_REG_MASK;
2459    uint8_t i;
2460
2461    switch (offset) {
2462    case 0x00:  /* SECONDS_REG */
2463        return to_bcd(s->current_tm.tm_sec);
2464
2465    case 0x04:  /* MINUTES_REG */
2466        return to_bcd(s->current_tm.tm_min);
2467
2468    case 0x08:  /* HOURS_REG */
2469        if (s->pm_am)
2470            return ((s->current_tm.tm_hour > 11) << 7) |
2471                    to_bcd(((s->current_tm.tm_hour - 1) % 12) + 1);
2472        else
2473            return to_bcd(s->current_tm.tm_hour);
2474
2475    case 0x0c:  /* DAYS_REG */
2476        return to_bcd(s->current_tm.tm_mday);
2477
2478    case 0x10:  /* MONTHS_REG */
2479        return to_bcd(s->current_tm.tm_mon + 1);
2480
2481    case 0x14:  /* YEARS_REG */
2482        return to_bcd(s->current_tm.tm_year % 100);
2483
2484    case 0x18:  /* WEEK_REG */
2485        return s->current_tm.tm_wday;
2486
2487    case 0x20:  /* ALARM_SECONDS_REG */
2488        return to_bcd(s->alarm_tm.tm_sec);
2489
2490    case 0x24:  /* ALARM_MINUTES_REG */
2491        return to_bcd(s->alarm_tm.tm_min);
2492
2493    case 0x28:  /* ALARM_HOURS_REG */
2494        if (s->pm_am)
2495            return ((s->alarm_tm.tm_hour > 11) << 7) |
2496                    to_bcd(((s->alarm_tm.tm_hour - 1) % 12) + 1);
2497        else
2498            return to_bcd(s->alarm_tm.tm_hour);
2499
2500    case 0x2c:  /* ALARM_DAYS_REG */
2501        return to_bcd(s->alarm_tm.tm_mday);
2502
2503    case 0x30:  /* ALARM_MONTHS_REG */
2504        return to_bcd(s->alarm_tm.tm_mon + 1);
2505
2506    case 0x34:  /* ALARM_YEARS_REG */
2507        return to_bcd(s->alarm_tm.tm_year % 100);
2508
2509    case 0x40:  /* RTC_CTRL_REG */
2510        return (s->pm_am << 3) | (s->auto_comp << 2) |
2511                (s->round << 1) | s->running;
2512
2513    case 0x44:  /* RTC_STATUS_REG */
2514        i = s->status;
2515        s->status &= ~0x3d;
2516        return i;
2517
2518    case 0x48:  /* RTC_INTERRUPTS_REG */
2519        return s->interrupts;
2520
2521    case 0x4c:  /* RTC_COMP_LSB_REG */
2522        return ((uint16_t) s->comp_reg) & 0xff;
2523
2524    case 0x50:  /* RTC_COMP_MSB_REG */
2525        return ((uint16_t) s->comp_reg) >> 8;
2526    }
2527
2528    OMAP_BAD_REG(addr);
2529    return 0;
2530}
2531
2532static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
2533                uint32_t value)
2534{
2535    struct omap_rtc_s *s = (struct omap_rtc_s *) opaque;
2536    int offset = addr & OMAP_MPUI_REG_MASK;
2537    struct tm new_tm;
2538    time_t ti[2];
2539
2540    switch (offset) {
2541    case 0x00:  /* SECONDS_REG */
2542#ifdef ALMDEBUG
2543        printf("RTC SEC_REG <-- %02x\n", value);
2544#endif
2545        s->ti -= s->current_tm.tm_sec;
2546        s->ti += from_bcd(value);
2547        return;
2548
2549    case 0x04:  /* MINUTES_REG */
2550#ifdef ALMDEBUG
2551        printf("RTC MIN_REG <-- %02x\n", value);
2552#endif
2553        s->ti -= s->current_tm.tm_min * 60;
2554        s->ti += from_bcd(value) * 60;
2555        return;
2556
2557    case 0x08:  /* HOURS_REG */
2558#ifdef ALMDEBUG
2559        printf("RTC HRS_REG <-- %02x\n", value);
2560#endif
2561        s->ti -= s->current_tm.tm_hour * 3600;
2562        if (s->pm_am) {
2563            s->ti += (from_bcd(value & 0x3f) & 12) * 3600;
2564            s->ti += ((value >> 7) & 1) * 43200;
2565        } else
2566            s->ti += from_bcd(value & 0x3f) * 3600;
2567        return;
2568
2569    case 0x0c:  /* DAYS_REG */
2570#ifdef ALMDEBUG
2571        printf("RTC DAY_REG <-- %02x\n", value);
2572#endif
2573        s->ti -= s->current_tm.tm_mday * 86400;
2574        s->ti += from_bcd(value) * 86400;
2575        return;
2576
2577    case 0x10:  /* MONTHS_REG */
2578#ifdef ALMDEBUG
2579        printf("RTC MTH_REG <-- %02x\n", value);
2580#endif
2581        memcpy(&new_tm, &s->current_tm, sizeof(new_tm));
2582        new_tm.tm_mon = from_bcd(value);
2583        ti[0] = mktimegm(&s->current_tm);
2584        ti[1] = mktimegm(&new_tm);
2585
2586        if (ti[0] != -1 && ti[1] != -1) {
2587            s->ti -= ti[0];
2588            s->ti += ti[1];
2589        } else {
2590            /* A less accurate version */
2591            s->ti -= s->current_tm.tm_mon * 2592000;
2592            s->ti += from_bcd(value) * 2592000;
2593        }
2594        return;
2595
2596    case 0x14:  /* YEARS_REG */
2597#ifdef ALMDEBUG
2598        printf("RTC YRS_REG <-- %02x\n", value);
2599#endif
2600        memcpy(&new_tm, &s->current_tm, sizeof(new_tm));
2601        new_tm.tm_year += from_bcd(value) - (new_tm.tm_year % 100);
2602        ti[0] = mktimegm(&s->current_tm);
2603        ti[1] = mktimegm(&new_tm);
2604
2605        if (ti[0] != -1 && ti[1] != -1) {
2606            s->ti -= ti[0];
2607            s->ti += ti[1];
2608        } else {
2609            /* A less accurate version */
2610            s->ti -= (s->current_tm.tm_year % 100) * 31536000;
2611            s->ti += from_bcd(value) * 31536000;
2612        }
2613        return;
2614
2615    case 0x18:  /* WEEK_REG */
2616        return; /* Ignored */
2617
2618    case 0x20:  /* ALARM_SECONDS_REG */
2619#ifdef ALMDEBUG
2620        printf("ALM SEC_REG <-- %02x\n", value);
2621#endif
2622        s->alarm_tm.tm_sec = from_bcd(value);
2623        omap_rtc_alarm_update(s);
2624        return;
2625
2626    case 0x24:  /* ALARM_MINUTES_REG */
2627#ifdef ALMDEBUG
2628        printf("ALM MIN_REG <-- %02x\n", value);
2629#endif
2630        s->alarm_tm.tm_min = from_bcd(value);
2631        omap_rtc_alarm_update(s);
2632        return;
2633
2634    case 0x28:  /* ALARM_HOURS_REG */
2635#ifdef ALMDEBUG
2636        printf("ALM HRS_REG <-- %02x\n", value);
2637#endif
2638        if (s->pm_am)
2639            s->alarm_tm.tm_hour =
2640                    ((from_bcd(value & 0x3f)) % 12) +
2641                    ((value >> 7) & 1) * 12;
2642        else
2643            s->alarm_tm.tm_hour = from_bcd(value);
2644        omap_rtc_alarm_update(s);
2645        return;
2646
2647    case 0x2c:  /* ALARM_DAYS_REG */
2648#ifdef ALMDEBUG
2649        printf("ALM DAY_REG <-- %02x\n", value);
2650#endif
2651        s->alarm_tm.tm_mday = from_bcd(value);
2652        omap_rtc_alarm_update(s);
2653        return;
2654
2655    case 0x30:  /* ALARM_MONTHS_REG */
2656#ifdef ALMDEBUG
2657        printf("ALM MON_REG <-- %02x\n", value);
2658#endif
2659        s->alarm_tm.tm_mon = from_bcd(value);
2660        omap_rtc_alarm_update(s);
2661        return;
2662
2663    case 0x34:  /* ALARM_YEARS_REG */
2664#ifdef ALMDEBUG
2665        printf("ALM YRS_REG <-- %02x\n", value);
2666#endif
2667        s->alarm_tm.tm_year = from_bcd(value);
2668        omap_rtc_alarm_update(s);
2669        return;
2670
2671    case 0x40:  /* RTC_CTRL_REG */
2672#ifdef ALMDEBUG
2673        printf("RTC CONTROL <-- %02x\n", value);
2674#endif
2675        s->pm_am = (value >> 3) & 1;
2676        s->auto_comp = (value >> 2) & 1;
2677        s->round = (value >> 1) & 1;
2678        s->running = value & 1;
2679        s->status &= 0xfd;
2680        s->status |= s->running << 1;
2681        return;
2682
2683    case 0x44:  /* RTC_STATUS_REG */
2684#ifdef ALMDEBUG
2685        printf("RTC STATUSL <-- %02x\n", value);
2686#endif
2687        s->status &= ~((value & 0xc0) ^ 0x80);
2688        omap_rtc_interrupts_update(s);
2689        return;
2690
2691    case 0x48:  /* RTC_INTERRUPTS_REG */
2692#ifdef ALMDEBUG
2693        printf("RTC INTRS <-- %02x\n", value);
2694#endif
2695        s->interrupts = value;
2696        return;
2697
2698    case 0x4c:  /* RTC_COMP_LSB_REG */
2699#ifdef ALMDEBUG
2700        printf("RTC COMPLSB <-- %02x\n", value);
2701#endif
2702        s->comp_reg &= 0xff00;
2703        s->comp_reg |= 0x00ff & value;
2704        return;
2705
2706    case 0x50:  /* RTC_COMP_MSB_REG */
2707#ifdef ALMDEBUG
2708        printf("RTC COMPMSB <-- %02x\n", value);
2709#endif
2710        s->comp_reg &= 0x00ff;
2711        s->comp_reg |= 0xff00 & (value << 8);
2712        return;
2713
2714    default:
2715        OMAP_BAD_REG(addr);
2716        return;
2717    }
2718}
2719
2720static CPUReadMemoryFunc * const omap_rtc_readfn[] = {
2721    omap_rtc_read,
2722    omap_badwidth_read8,
2723    omap_badwidth_read8,
2724};
2725
2726static CPUWriteMemoryFunc * const omap_rtc_writefn[] = {
2727    omap_rtc_write,
2728    omap_badwidth_write8,
2729    omap_badwidth_write8,
2730};
2731
2732static void omap_rtc_tick(void *opaque)
2733{
2734    struct omap_rtc_s *s = opaque;
2735
2736    if (s->round) {
2737        /* Round to nearest full minute.  */
2738        if (s->current_tm.tm_sec < 30)
2739            s->ti -= s->current_tm.tm_sec;
2740        else
2741            s->ti += 60 - s->current_tm.tm_sec;
2742
2743        s->round = 0;
2744    }
2745
2746    memcpy(&s->current_tm, localtime(&s->ti), sizeof(s->current_tm));
2747
2748    if ((s->interrupts & 0x08) && s->ti == s->alarm_ti) {
2749        s->status |= 0x40;
2750        omap_rtc_interrupts_update(s);
2751    }
2752
2753    if (s->interrupts & 0x04)
2754        switch (s->interrupts & 3) {
2755        case 0:
2756            s->status |= 0x04;
2757            qemu_irq_pulse(s->irq);
2758            break;
2759        case 1:
2760            if (s->current_tm.tm_sec)
2761                break;
2762            s->status |= 0x08;
2763            qemu_irq_pulse(s->irq);
2764            break;
2765        case 2:
2766            if (s->current_tm.tm_sec || s->current_tm.tm_min)
2767                break;
2768            s->status |= 0x10;
2769            qemu_irq_pulse(s->irq);
2770            break;
2771        case 3:
2772            if (s->current_tm.tm_sec ||
2773                            s->current_tm.tm_min || s->current_tm.tm_hour)
2774                break;
2775            s->status |= 0x20;
2776            qemu_irq_pulse(s->irq);
2777            break;
2778        }
2779
2780    /* Move on */
2781    if (s->running)
2782        s->ti ++;
2783    s->tick += 1000;
2784
2785    /*
2786     * Every full hour add a rough approximation of the compensation
2787     * register to the 32kHz Timer (which drives the RTC) value. 
2788     */
2789    if (s->auto_comp && !s->current_tm.tm_sec && !s->current_tm.tm_min)
2790        s->tick += s->comp_reg * 1000 / 32768;
2791
2792    qemu_mod_timer(s->clk, s->tick);
2793}
2794
2795static void omap_rtc_reset(struct omap_rtc_s *s)
2796{
2797    struct tm tm;
2798
2799    s->interrupts = 0;
2800    s->comp_reg = 0;
2801    s->running = 0;
2802    s->pm_am = 0;
2803    s->auto_comp = 0;
2804    s->round = 0;
2805    s->tick = qemu_get_clock(rt_clock);
2806    memset(&s->alarm_tm, 0, sizeof(s->alarm_tm));
2807    s->alarm_tm.tm_mday = 0x01;
2808    s->status = 1 << 7;
2809    qemu_get_timedate(&tm, 0);
2810    s->ti = mktimegm(&tm);
2811
2812    omap_rtc_alarm_update(s);
2813    omap_rtc_tick(s);
2814}
2815
2816static struct omap_rtc_s *omap_rtc_init(target_phys_addr_t base,
2817                qemu_irq *irq, omap_clk clk)
2818{
2819    int iomemtype;
2820    struct omap_rtc_s *s = (struct omap_rtc_s *)
2821            qemu_mallocz(sizeof(struct omap_rtc_s));
2822
2823    s->irq = irq[0];
2824    s->alarm = irq[1];
2825    s->clk = qemu_new_timer(rt_clock, omap_rtc_tick, s);
2826
2827    omap_rtc_reset(s);
2828
2829    iomemtype = cpu_register_io_memory(omap_rtc_readfn,
2830                    omap_rtc_writefn, s, DEVICE_NATIVE_ENDIAN);
2831    cpu_register_physical_memory(base, 0x800, iomemtype);
2832
2833    return s;
2834}
2835
2836/* Multi-channel Buffered Serial Port interfaces */
2837struct omap_mcbsp_s {
2838    qemu_irq txirq;
2839    qemu_irq rxirq;
2840    qemu_irq txdrq;
2841    qemu_irq rxdrq;
2842
2843    uint16_t spcr[2];
2844    uint16_t rcr[2];
2845    uint16_t xcr[2];
2846    uint16_t srgr[2];
2847    uint16_t mcr[2];
2848    uint16_t pcr;
2849    uint16_t rcer[8];
2850    uint16_t xcer[8];
2851    int tx_rate;
2852    int rx_rate;
2853    int tx_req;
2854    int rx_req;
2855
2856    I2SCodec *codec;
2857    QEMUTimer *source_timer;
2858    QEMUTimer *sink_timer;
2859};
2860
2861static void omap_mcbsp_intr_update(struct omap_mcbsp_s *s)
2862{
2863    int irq;
2864
2865    switch ((s->spcr[0] >> 4) & 3) {                    /* RINTM */
2866    case 0:
2867        irq = (s->spcr[0] >> 1) & 1;                    /* RRDY */
2868        break;
2869    case 3:
2870        irq = (s->spcr[0] >> 3) & 1;                    /* RSYNCERR */
2871        break;
2872    default:
2873        irq = 0;
2874        break;
2875    }
2876
2877    if (irq)
2878        qemu_irq_pulse(s->rxirq);
2879
2880    switch ((s->spcr[1] >> 4) & 3) {                    /* XINTM */
2881    case 0:
2882        irq = (s->spcr[1] >> 1) & 1;                    /* XRDY */
2883        break;
2884    case 3:
2885        irq = (s->spcr[1] >> 3) & 1;                    /* XSYNCERR */
2886        break;
2887    default:
2888        irq = 0;
2889        break;
2890    }
2891
2892    if (irq)
2893        qemu_irq_pulse(s->txirq);
2894}
2895
2896static void omap_mcbsp_rx_newdata(struct omap_mcbsp_s *s)
2897{
2898    if ((s->spcr[0] >> 1) & 1)                          /* RRDY */
2899        s->spcr[0] |= 1 << 2;                           /* RFULL */
2900    s->spcr[0] |= 1 << 1;                               /* RRDY */
2901    qemu_irq_raise(s->rxdrq);
2902    omap_mcbsp_intr_update(s);
2903}
2904
2905static void omap_mcbsp_source_tick(void *opaque)
2906{
2907    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
2908    static const int bps[8] = { 0, 1, 1, 2, 2, 2, -255, -255 };
2909
2910    if (!s->rx_rate)
2911        return;
2912    if (s->rx_req)
2913        printf("%s: Rx FIFO overrun\n", __FUNCTION__);
2914
2915    s->rx_req = s->rx_rate << bps[(s->rcr[0] >> 5) & 7];
2916
2917    omap_mcbsp_rx_newdata(s);
2918    qemu_mod_timer(s->source_timer, qemu_get_clock(vm_clock) +
2919                   get_ticks_per_sec());
2920}
2921
2922static void omap_mcbsp_rx_start(struct omap_mcbsp_s *s)
2923{
2924    if (!s->codec || !s->codec->rts)
2925        omap_mcbsp_source_tick(s);
2926    else if (s->codec->in.len) {
2927        s->rx_req = s->codec->in.len;
2928        omap_mcbsp_rx_newdata(s);
2929    }
2930}
2931
2932static void omap_mcbsp_rx_stop(struct omap_mcbsp_s *s)
2933{
2934    qemu_del_timer(s->source_timer);
2935}
2936
2937static void omap_mcbsp_rx_done(struct omap_mcbsp_s *s)
2938{
2939    s->spcr[0] &= ~(1 << 1);                            /* RRDY */
2940    qemu_irq_lower(s->rxdrq);
2941    omap_mcbsp_intr_update(s);
2942}
2943
2944static void omap_mcbsp_tx_newdata(struct omap_mcbsp_s *s)
2945{
2946    s->spcr[1] |= 1 << 1;                               /* XRDY */
2947    qemu_irq_raise(s->txdrq);
2948    omap_mcbsp_intr_update(s);
2949}
2950
2951static void omap_mcbsp_sink_tick(void *opaque)
2952{
2953    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
2954    static const int bps[8] = { 0, 1, 1, 2, 2, 2, -255, -255 };
2955
2956    if (!s->tx_rate)
2957        return;
2958    if (s->tx_req)
2959        printf("%s: Tx FIFO underrun\n", __FUNCTION__);
2960
2961    s->tx_req = s->tx_rate << bps[(s->xcr[0] >> 5) & 7];
2962
2963    omap_mcbsp_tx_newdata(s);
2964    qemu_mod_timer(s->sink_timer, qemu_get_clock(vm_clock) +
2965                   get_ticks_per_sec());
2966}
2967
2968static void omap_mcbsp_tx_start(struct omap_mcbsp_s *s)
2969{
2970    if (!s->codec || !s->codec->cts)
2971        omap_mcbsp_sink_tick(s);
2972    else if (s->codec->out.size) {
2973        s->tx_req = s->codec->out.size;
2974        omap_mcbsp_tx_newdata(s);
2975    }
2976}
2977
2978static void omap_mcbsp_tx_done(struct omap_mcbsp_s *s)
2979{
2980    s->spcr[1] &= ~(1 << 1);                            /* XRDY */
2981    qemu_irq_lower(s->txdrq);
2982    omap_mcbsp_intr_update(s);
2983    if (s->codec && s->codec->cts)
2984        s->codec->tx_swallow(s->codec->opaque);
2985}
2986
2987static void omap_mcbsp_tx_stop(struct omap_mcbsp_s *s)
2988{
2989    s->tx_req = 0;
2990    omap_mcbsp_tx_done(s);
2991    qemu_del_timer(s->sink_timer);
2992}
2993
2994static void omap_mcbsp_req_update(struct omap_mcbsp_s *s)
2995{
2996    int prev_rx_rate, prev_tx_rate;
2997    int rx_rate = 0, tx_rate = 0;
2998    int cpu_rate = 1500000;     /* XXX */
2999
3000    /* TODO: check CLKSTP bit */
3001    if (s->spcr[1] & (1 << 6)) {                        /* GRST */
3002        if (s->spcr[0] & (1 << 0)) {                    /* RRST */
3003            if ((s->srgr[1] & (1 << 13)) &&             /* CLKSM */
3004                            (s->pcr & (1 << 8))) {      /* CLKRM */
3005                if (~s->pcr & (1 << 7))                 /* SCLKME */
3006                    rx_rate = cpu_rate /
3007                            ((s->srgr[0] & 0xff) + 1);  /* CLKGDV */
3008            } else
3009                if (s->codec)
3010                    rx_rate = s->codec->rx_rate;
3011        }
3012
3013        if (s->spcr[1] & (1 << 0)) {                    /* XRST */
3014            if ((s->srgr[1] & (1 << 13)) &&             /* CLKSM */
3015                            (s->pcr & (1 << 9))) {      /* CLKXM */
3016                if (~s->pcr & (1 << 7))                 /* SCLKME */
3017                    tx_rate = cpu_rate /
3018                            ((s->srgr[0] & 0xff) + 1);  /* CLKGDV */
3019            } else
3020                if (s->codec)
3021                    tx_rate = s->codec->tx_rate;
3022        }
3023    }
3024    prev_tx_rate = s->tx_rate;
3025    prev_rx_rate = s->rx_rate;
3026    s->tx_rate = tx_rate;
3027    s->rx_rate = rx_rate;
3028
3029    if (s->codec)
3030        s->codec->set_rate(s->codec->opaque, rx_rate, tx_rate);
3031
3032    if (!prev_tx_rate && tx_rate)
3033        omap_mcbsp_tx_start(s);
3034    else if (s->tx_rate && !tx_rate)
3035        omap_mcbsp_tx_stop(s);
3036
3037    if (!prev_rx_rate && rx_rate)
3038        omap_mcbsp_rx_start(s);
3039    else if (prev_tx_rate && !tx_rate)
3040        omap_mcbsp_rx_stop(s);
3041}
3042
3043static uint32_t omap_mcbsp_read(void *opaque, target_phys_addr_t addr)
3044{
3045    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
3046    int offset = addr & OMAP_MPUI_REG_MASK;
3047    uint16_t ret;
3048
3049    switch (offset) {
3050    case 0x00:  /* DRR2 */
3051        if (((s->rcr[0] >> 5) & 7) < 3)                 /* RWDLEN1 */
3052            return 0x0000;
3053        /* Fall through.  */
3054    case 0x02:  /* DRR1 */
3055        if (s->rx_req < 2) {
3056            printf("%s: Rx FIFO underrun\n", __FUNCTION__);
3057            omap_mcbsp_rx_done(s);
3058        } else {
3059            s->tx_req -= 2;
3060            if (s->codec && s->codec->in.len >= 2) {
3061                ret = s->codec->in.fifo[s->codec->in.start ++] << 8;
3062                ret |= s->codec->in.fifo[s->codec->in.start ++];
3063                s->codec->in.len -= 2;
3064            } else
3065                ret = 0x0000;
3066            if (!s->tx_req)
3067                omap_mcbsp_rx_done(s);
3068            return ret;
3069        }
3070        return 0x0000;
3071
3072    case 0x04:  /* DXR2 */
3073    case 0x06:  /* DXR1 */
3074        return 0x0000;
3075
3076    case 0x08:  /* SPCR2 */
3077        return s->spcr[1];
3078    case 0x0a:  /* SPCR1 */
3079        return s->spcr[0];
3080    case 0x0c:  /* RCR2 */
3081        return s->rcr[1];
3082    case 0x0e:  /* RCR1 */
3083        return s->rcr[0];
3084    case 0x10:  /* XCR2 */
3085        return s->xcr[1];
3086    case 0x12:  /* XCR1 */
3087        return s->xcr[0];
3088    case 0x14:  /* SRGR2 */
3089        return s->srgr[1];
3090    case 0x16:  /* SRGR1 */
3091        return s->srgr[0];
3092    case 0x18:  /* MCR2 */
3093        return s->mcr[1];
3094    case 0x1a:  /* MCR1 */
3095        return s->mcr[0];
3096    case 0x1c:  /* RCERA */
3097        return s->rcer[0];
3098    case 0x1e:  /* RCERB */
3099        return s->rcer[1];
3100    case 0x20:  /* XCERA */
3101        return s->xcer[0];
3102    case 0x22:  /* XCERB */
3103        return s->xcer[1];
3104    case 0x24:  /* PCR0 */
3105        return s->pcr;
3106    case 0x26:  /* RCERC */
3107        return s->rcer[2];
3108    case 0x28:  /* RCERD */
3109        return s->rcer[3];
3110    case 0x2a:  /* XCERC */
3111        return s->xcer[2];
3112    case 0x2c:  /* XCERD */
3113        return s->xcer[3];
3114    case 0x2e:  /* RCERE */
3115        return s->rcer[4];
3116    case 0x30:  /* RCERF */
3117        return s->rcer[5];
3118    case 0x32:  /* XCERE */
3119        return s->xcer[4];
3120    case 0x34:  /* XCERF */
3121        return s->xcer[5];
3122    case 0x36:  /* RCERG */
3123        return s->rcer[6];
3124    case 0x38:  /* RCERH */
3125        return s->rcer[7];
3126    case 0x3a:  /* XCERG */
3127        return s->xcer[6];
3128    case 0x3c:  /* XCERH */
3129        return s->xcer[7];
3130    }
3131
3132    OMAP_BAD_REG(addr);
3133    return 0;
3134}
3135
3136static void omap_mcbsp_writeh(void *opaque, target_phys_addr_t addr,
3137                uint32_t value)
3138{
3139    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
3140    int offset = addr & OMAP_MPUI_REG_MASK;
3141
3142    switch (offset) {
3143    case 0x00:  /* DRR2 */
3144    case 0x02:  /* DRR1 */
3145        OMAP_RO_REG(addr);
3146        return;
3147
3148    case 0x04:  /* DXR2 */
3149        if (((s->xcr[0] >> 5) & 7) < 3)                 /* XWDLEN1 */
3150            return;
3151        /* Fall through.  */
3152    case 0x06:  /* DXR1 */
3153        if (s->tx_req > 1) {
3154            s->tx_req -= 2;
3155            if (s->codec && s->codec->cts) {
3156                s->codec->out.fifo[s->codec->out.len ++] = (value >> 8) & 0xff;
3157                s->codec->out.fifo[s->codec->out.len ++] = (value >> 0) & 0xff;
3158            }
3159            if (s->tx_req < 2)
3160                omap_mcbsp_tx_done(s);
3161        } else
3162            printf("%s: Tx FIFO overrun\n", __FUNCTION__);
3163        return;
3164
3165    case 0x08:  /* SPCR2 */
3166        s->spcr[1] &= 0x0002;
3167        s->spcr[1] |= 0x03f9 & value;
3168        s->spcr[1] |= 0x0004 & (value << 2);            /* XEMPTY := XRST */
3169        if (~value & 1)                                 /* XRST */
3170            s->spcr[1] &= ~6;
3171        omap_mcbsp_req_update(s);
3172        return;
3173    case 0x0a:  /* SPCR1 */
3174        s->spcr[0] &= 0x0006;
3175        s->spcr[0] |= 0xf8f9 & value;
3176        if (value & (1 << 15))                          /* DLB */
3177            printf("%s: Digital Loopback mode enable attempt\n", __FUNCTION__);
3178        if (~value & 1) {                               /* RRST */
3179            s->spcr[0] &= ~6;
3180            s->rx_req = 0;
3181            omap_mcbsp_rx_done(s);
3182        }
3183        omap_mcbsp_req_update(s);
3184        return;
3185
3186    case 0x0c:  /* RCR2 */
3187        s->rcr[1] = value & 0xffff;
3188        return;
3189    case 0x0e:  /* RCR1 */
3190        s->rcr[0] = value & 0x7fe0;
3191        return;
3192    case 0x10:  /* XCR2 */
3193        s->xcr[1] = value & 0xffff;
3194        return;
3195    case 0x12:  /* XCR1 */
3196        s->xcr[0] = value & 0x7fe0;
3197        return;
3198    case 0x14:  /* SRGR2 */
3199        s->srgr[1] = value & 0xffff;
3200        omap_mcbsp_req_update(s);
3201        return;
3202    case 0x16:  /* SRGR1 */
3203        s->srgr[0] = value & 0xffff;
3204        omap_mcbsp_req_update(s);
3205        return;
3206    case 0x18:  /* MCR2 */
3207        s->mcr[1] = value & 0x03e3;
3208        if (value & 3)                                  /* XMCM */
3209            printf("%s: Tx channel selection mode enable attempt\n",
3210                            __FUNCTION__);
3211        return;
3212    case 0x1a:  /* MCR1 */
3213        s->mcr[0] = value & 0x03e1;
3214        if (value & 1)                                  /* RMCM */
3215            printf("%s: Rx channel selection mode enable attempt\n",
3216                            __FUNCTION__);
3217        return;
3218    case 0x1c:  /* RCERA */
3219        s->rcer[0] = value & 0xffff;
3220        return;
3221    case 0x1e:  /* RCERB */
3222        s->rcer[1] = value & 0xffff;
3223        return;
3224    case 0x20:  /* XCERA */
3225        s->xcer[0] = value & 0xffff;
3226        return;
3227    case 0x22:  /* XCERB */
3228        s->xcer[1] = value & 0xffff;
3229        return;
3230    case 0x24:  /* PCR0 */
3231        s->pcr = value & 0x7faf;
3232        return;
3233    case 0x26:  /* RCERC */
3234        s->rcer[2] = value & 0xffff;
3235        return;
3236    case 0x28:  /* RCERD */
3237        s->rcer[3] = value & 0xffff;
3238        return;
3239    case 0x2a:  /* XCERC */
3240        s->xcer[2] = value & 0xffff;
3241        return;
3242    case 0x2c:  /* XCERD */
3243        s->xcer[3] = value & 0xffff;
3244        return;
3245    case 0x2e:  /* RCERE */
3246        s->rcer[4] = value & 0xffff;
3247        return;
3248    case 0x30:  /* RCERF */
3249        s->rcer[5] = value & 0xffff;
3250        return;
3251    case 0x32:  /* XCERE */
3252        s->xcer[4] = value & 0xffff;
3253        return;
3254    case 0x34:  /* XCERF */
3255        s->xcer[5] = value & 0xffff;
3256        return;
3257    case 0x36:  /* RCERG */
3258        s->rcer[6] = value & 0xffff;
3259        return;
3260    case 0x38:  /* RCERH */
3261        s->rcer[7] = value & 0xffff;
3262        return;
3263    case 0x3a:  /* XCERG */
3264        s->xcer[6] = value & 0xffff;
3265        return;
3266    case 0x3c:  /* XCERH */
3267        s->xcer[7] = value & 0xffff;
3268        return;
3269    }
3270
3271    OMAP_BAD_REG(addr);
3272}
3273
3274static void omap_mcbsp_writew(void *opaque, target_phys_addr_t addr,
3275                uint32_t value)
3276{
3277    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
3278    int offset = addr & OMAP_MPUI_REG_MASK;
3279
3280    if (offset == 0x04) {                               /* DXR */
3281        if (((s->xcr[0] >> 5) & 7) < 3)                 /* XWDLEN1 */
3282            return;
3283        if (s->tx_req > 3) {
3284            s->tx_req -= 4;
3285            if (s->codec && s->codec->cts) {
3286                s->codec->out.fifo[s->codec->out.len ++] =
3287                        (value >> 24) & 0xff;
3288                s->codec->out.fifo[s->codec->out.len ++] =
3289                        (value >> 16) & 0xff;
3290                s->codec->out.fifo[s->codec->out.len ++] =
3291                        (value >> 8) & 0xff;
3292                s->codec->out.fifo[s->codec->out.len ++] =
3293                        (value >> 0) & 0xff;
3294            }
3295            if (s->tx_req < 4)
3296                omap_mcbsp_tx_done(s);
3297        } else
3298            printf("%s: Tx FIFO overrun\n", __FUNCTION__);
3299        return;
3300    }
3301
3302    omap_badwidth_write16(opaque, addr, value);
3303}
3304
3305static CPUReadMemoryFunc * const omap_mcbsp_readfn[] = {
3306    omap_badwidth_read16,
3307    omap_mcbsp_read,
3308    omap_badwidth_read16,
3309};
3310
3311static CPUWriteMemoryFunc * const omap_mcbsp_writefn[] = {
3312    omap_badwidth_write16,
3313    omap_mcbsp_writeh,
3314    omap_mcbsp_writew,
3315};
3316
3317static void omap_mcbsp_reset(struct omap_mcbsp_s *s)
3318{
3319    memset(&s->spcr, 0, sizeof(s->spcr));
3320    memset(&s->rcr, 0, sizeof(s->rcr));
3321    memset(&s->xcr, 0, sizeof(s->xcr));
3322    s->srgr[0] = 0x0001;
3323    s->srgr[1] = 0x2000;
3324    memset(&s->mcr, 0, sizeof(s->mcr));
3325    memset(&s->pcr, 0, sizeof(s->pcr));
3326    memset(&s->rcer, 0, sizeof(s->rcer));
3327    memset(&s->xcer, 0, sizeof(s->xcer));
3328    s->tx_req = 0;
3329    s->rx_req = 0;
3330    s->tx_rate = 0;
3331    s->rx_rate = 0;
3332    qemu_del_timer(s->source_timer);
3333    qemu_del_timer(s->sink_timer);
3334}
3335
3336struct omap_mcbsp_s *omap_mcbsp_init(target_phys_addr_t base,
3337                qemu_irq *irq, qemu_irq *dma, omap_clk clk)
3338{
3339    int iomemtype;
3340    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *)
3341            qemu_mallocz(sizeof(struct omap_mcbsp_s));
3342
3343    s->txirq = irq[0];
3344    s->rxirq = irq[1];
3345    s->txdrq = dma[0];
3346    s->rxdrq = dma[1];
3347    s->sink_timer = qemu_new_timer(vm_clock, omap_mcbsp_sink_tick, s);
3348    s->source_timer = qemu_new_timer(vm_clock, omap_mcbsp_source_tick, s);
3349    omap_mcbsp_reset(s);
3350
3351    iomemtype = cpu_register_io_memory(omap_mcbsp_readfn,
3352                    omap_mcbsp_writefn, s, DEVICE_NATIVE_ENDIAN);
3353    cpu_register_physical_memory(base, 0x800, iomemtype);
3354
3355    return s;
3356}
3357
3358static void omap_mcbsp_i2s_swallow(void *opaque, int line, int level)
3359{
3360    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
3361
3362    if (s->rx_rate) {
3363        s->rx_req = s->codec->in.len;
3364        omap_mcbsp_rx_newdata(s);
3365    }
3366}
3367
3368static void omap_mcbsp_i2s_start(void *opaque, int line, int level)
3369{
3370    struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
3371
3372    if (s->tx_rate) {
3373        s->tx_req = s->codec->out.size;
3374        omap_mcbsp_tx_newdata(s);
3375    }
3376}
3377
3378void omap_mcbsp_i2s_attach(struct omap_mcbsp_s *s, I2SCodec *slave)
3379{
3380    s->codec = slave;
3381    slave->rx_swallow = qemu_allocate_irqs(omap_mcbsp_i2s_swallow, s, 1)[0];
3382    slave->tx_start = qemu_allocate_irqs(omap_mcbsp_i2s_start, s, 1)[0];
3383}
3384
3385/* LED Pulse Generators */
3386struct omap_lpg_s {
3387    QEMUTimer *tm;
3388
3389    uint8_t control;
3390    uint8_t power;
3391    int64_t on;
3392    int64_t period;
3393    int clk;
3394    int cycle;
3395};
3396
3397static void omap_lpg_tick(void *opaque)
3398{
3399    struct omap_lpg_s *s = opaque;
3400
3401    if (s->cycle)
3402        qemu_mod_timer(s->tm, qemu_get_clock(rt_clock) + s->period - s->on);
3403    else
3404        qemu_mod_timer(s->tm, qemu_get_clock(rt_clock) + s->on);
3405
3406    s->cycle = !s->cycle;
3407    printf("%s: LED is %s\n", __FUNCTION__, s->cycle ? "on" : "off");
3408}
3409
3410static void omap_lpg_update(struct omap_lpg_s *s)
3411{
3412    int64_t on, period = 1, ticks = 1000;
3413    static const int per[8] = { 1, 2, 4, 8, 12, 16, 20, 24 };
3414
3415    if (~s->control & (1 << 6))                                 /* LPGRES */
3416        on = 0;
3417    else if (s->control & (1 << 7))                             /* PERM_ON */
3418        on = period;
3419    else {
3420        period = muldiv64(ticks, per[s->control & 7],           /* PERCTRL */
3421                        256 / 32);
3422        on = (s->clk && s->power) ? muldiv64(ticks,
3423                        per[(s->control >> 3) & 7], 256) : 0;   /* ONCTRL */
3424    }
3425
3426    qemu_del_timer(s->tm);
3427    if (on == period && s->on < s->period)
3428        printf("%s: LED is on\n", __FUNCTION__);
3429    else if (on == 0 && s->on)
3430        printf("%s: LED is off\n", __FUNCTION__);
3431    else if (on && (on != s->on || period != s->period)) {
3432        s->cycle = 0;
3433        s->on = on;
3434        s->period = period;
3435        omap_lpg_tick(s);
3436        return;
3437    }
3438
3439    s->on = on;
3440    s->period = period;
3441}
3442
3443static void omap_lpg_reset(struct omap_lpg_s *s)
3444{
3445    s->control = 0x00;
3446    s->power = 0x00;
3447    s->clk = 1;
3448    omap_lpg_update(s);
3449}
3450
3451static uint32_t omap_lpg_read(void *opaque, target_phys_addr_t addr)
3452{
3453    struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
3454    int offset = addr & OMAP_MPUI_REG_MASK;
3455
3456    switch (offset) {
3457    case 0x00:  /* LCR */
3458        return s->control;
3459
3460    case 0x04:  /* PMR */
3461        return s->power;
3462    }
3463
3464    OMAP_BAD_REG(addr);
3465    return 0;
3466}
3467
3468static void omap_lpg_write(void *opaque, target_phys_addr_t addr,
3469                uint32_t value)
3470{
3471    struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
3472    int offset = addr & OMAP_MPUI_REG_MASK;
3473
3474    switch (offset) {
3475    case 0x00:  /* LCR */
3476        if (~value & (1 << 6))                                  /* LPGRES */
3477            omap_lpg_reset(s);
3478        s->control = value & 0xff;
3479        omap_lpg_update(s);
3480        return;
3481
3482    case 0x04:  /* PMR */
3483        s->power = value & 0x01;
3484        omap_lpg_update(s);
3485        return;
3486
3487    default:
3488        OMAP_BAD_REG(addr);
3489        return;
3490    }
3491}
3492
3493static CPUReadMemoryFunc * const omap_lpg_readfn[] = {
3494    omap_lpg_read,
3495    omap_badwidth_read8,
3496    omap_badwidth_read8,
3497};
3498
3499static CPUWriteMemoryFunc * const omap_lpg_writefn[] = {
3500    omap_lpg_write,
3501    omap_badwidth_write8,
3502    omap_badwidth_write8,
3503};
3504
3505static void omap_lpg_clk_update(void *opaque, int line, int on)
3506{
3507    struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
3508
3509    s->clk = on;
3510    omap_lpg_update(s);
3511}
3512
3513static struct omap_lpg_s *omap_lpg_init(target_phys_addr_t base, omap_clk clk)
3514{
3515    int iomemtype;
3516    struct omap_lpg_s *s = (struct omap_lpg_s *)
3517            qemu_mallocz(sizeof(struct omap_lpg_s));
3518
3519    s->tm = qemu_new_timer(rt_clock, omap_lpg_tick, s);
3520
3521    omap_lpg_reset(s);
3522
3523    iomemtype = cpu_register_io_memory(omap_lpg_readfn,
3524                    omap_lpg_writefn, s, DEVICE_NATIVE_ENDIAN);
3525    cpu_register_physical_memory(base, 0x800, iomemtype);
3526
3527    omap_clk_adduser(clk, qemu_allocate_irqs(omap_lpg_clk_update, s, 1)[0]);
3528
3529    return s;
3530}
3531
3532/* MPUI Peripheral Bridge configuration */
3533static uint32_t omap_mpui_io_read(void *opaque, target_phys_addr_t addr)
3534{
3535    if (addr == OMAP_MPUI_BASE) /* CMR */
3536        return 0xfe4d;
3537
3538    OMAP_BAD_REG(addr);
3539    return 0;
3540}
3541
3542static CPUReadMemoryFunc * const omap_mpui_io_readfn[] = {
3543    omap_badwidth_read16,
3544    omap_mpui_io_read,
3545    omap_badwidth_read16,
3546};
3547
3548static CPUWriteMemoryFunc * const omap_mpui_io_writefn[] = {
3549    omap_badwidth_write16,
3550    omap_badwidth_write16,
3551    omap_badwidth_write16,
3552};
3553
3554static void omap_setup_mpui_io(struct omap_mpu_state_s *mpu)
3555{
3556    int iomemtype = cpu_register_io_memory(omap_mpui_io_readfn,
3557                    omap_mpui_io_writefn, mpu, DEVICE_NATIVE_ENDIAN);
3558    cpu_register_physical_memory(OMAP_MPUI_BASE, 0x7fff, iomemtype);
3559}
3560
3561/* General chip reset */
3562static void omap1_mpu_reset(void *opaque)
3563{
3564    struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
3565
3566    omap_inth_reset(mpu->ih[0]);
3567    omap_inth_reset(mpu->ih[1]);
3568    omap_dma_reset(mpu->dma);
3569    omap_mpu_timer_reset(mpu->timer[0]);
3570    omap_mpu_timer_reset(mpu->timer[1]);
3571    omap_mpu_timer_reset(mpu->timer[2]);
3572    omap_wd_timer_reset(mpu->wdt);
3573    omap_os_timer_reset(mpu->os_timer);
3574    omap_lcdc_reset(mpu->lcd);
3575    omap_ulpd_pm_reset(mpu);
3576    omap_pin_cfg_reset(mpu);
3577    omap_mpui_reset(mpu);
3578    omap_tipb_bridge_reset(mpu->private_tipb);
3579    omap_tipb_bridge_reset(mpu->public_tipb);
3580    omap_dpll_reset(&mpu->dpll[0]);
3581    omap_dpll_reset(&mpu->dpll[1]);
3582    omap_dpll_reset(&mpu->dpll[2]);
3583    omap_uart_reset(mpu->uart[0]);
3584    omap_uart_reset(mpu->uart[1]);
3585    omap_uart_reset(mpu->uart[2]);
3586    omap_mmc_reset(mpu->mmc);
3587    omap_mpuio_reset(mpu->mpuio);
3588    omap_gpio_reset(mpu->gpio);
3589    omap_uwire_reset(mpu->microwire);
3590    omap_pwl_reset(mpu);
3591    omap_pwt_reset(mpu);
3592    omap_i2c_reset(mpu->i2c[0]);
3593    omap_rtc_reset(mpu->rtc);
3594    omap_mcbsp_reset(mpu->mcbsp1);
3595    omap_mcbsp_reset(mpu->mcbsp2);
3596    omap_mcbsp_reset(mpu->mcbsp3);
3597    omap_lpg_reset(mpu->led[0]);
3598    omap_lpg_reset(mpu->led[1]);
3599    omap_clkm_reset(mpu);
3600    cpu_reset(mpu->env);
3601}
3602
3603static const struct omap_map_s {
3604    target_phys_addr_t phys_dsp;
3605    target_phys_addr_t phys_mpu;
3606    uint32_t size;
3607    const char *name;
3608} omap15xx_dsp_mm[] = {
3609    /* Strobe 0 */
3610    { 0xe1010000, 0xfffb0000, 0x800, "UART1 BT" },              /* CS0 */
3611    { 0xe1010800, 0xfffb0800, 0x800, "UART2 COM" },             /* CS1 */
3612    { 0xe1011800, 0xfffb1800, 0x800, "McBSP1 audio" },          /* CS3 */
3613    { 0xe1012000, 0xfffb2000, 0x800, "MCSI2 communication" },   /* CS4 */
3614    { 0xe1012800, 0xfffb2800, 0x800, "MCSI1 BT u-Law" },        /* CS5 */
3615    { 0xe1013000, 0xfffb3000, 0x800, "uWire" },                 /* CS6 */
3616    { 0xe1013800, 0xfffb3800, 0x800, "I^2C" },                  /* CS7 */
3617    { 0xe1014000, 0xfffb4000, 0x800, "USB W2FC" },              /* CS8 */
3618    { 0xe1014800, 0xfffb4800, 0x800, "RTC" },                   /* CS9 */
3619    { 0xe1015000, 0xfffb5000, 0x800, "MPUIO" },                 /* CS10 */
3620    { 0xe1015800, 0xfffb5800, 0x800, "PWL" },                   /* CS11 */
3621    { 0xe1016000, 0xfffb6000, 0x800, "PWT" },                   /* CS12 */
3622    { 0xe1017000, 0xfffb7000, 0x800, "McBSP3" },                /* CS14 */
3623    { 0xe1017800, 0xfffb7800, 0x800, "MMC" },                   /* CS15 */
3624    { 0xe1019000, 0xfffb9000, 0x800, "32-kHz timer" },          /* CS18 */
3625    { 0xe1019800, 0xfffb9800, 0x800, "UART3" },                 /* CS19 */
3626    { 0xe101c800, 0xfffbc800, 0x800, "TIPB switches" },         /* CS25 */
3627    /* Strobe 1 */
3628    { 0xe101e000, 0xfffce000, 0x800, "GPIOs" },                 /* CS28 */
3629
3630    { 0 }
3631};
3632
3633static void omap_setup_dsp_mapping(const struct omap_map_s *map)
3634{
3635    int io;
3636
3637    for (; map->phys_dsp; map ++) {
3638        io = cpu_get_physical_page_desc(map->phys_mpu);
3639
3640        cpu_register_physical_memory(map->phys_dsp, map->size, io);
3641    }
3642}
3643
3644void omap_mpu_wakeup(void *opaque, int irq, int req)
3645{
3646    struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
3647
3648    if (mpu->env->halted)
3649        cpu_interrupt(mpu->env, CPU_INTERRUPT_EXITTB);
3650}
3651
3652static const struct dma_irq_map omap1_dma_irq_map[] = {
3653    { 0, OMAP_INT_DMA_CH0_6 },
3654    { 0, OMAP_INT_DMA_CH1_7 },
3655    { 0, OMAP_INT_DMA_CH2_8 },
3656    { 0, OMAP_INT_DMA_CH3 },
3657    { 0, OMAP_INT_DMA_CH4 },
3658    { 0, OMAP_INT_DMA_CH5 },
3659    { 1, OMAP_INT_1610_DMA_CH6 },
3660    { 1, OMAP_INT_1610_DMA_CH7 },
3661    { 1, OMAP_INT_1610_DMA_CH8 },
3662    { 1, OMAP_INT_1610_DMA_CH9 },
3663    { 1, OMAP_INT_1610_DMA_CH10 },
3664    { 1, OMAP_INT_1610_DMA_CH11 },
3665    { 1, OMAP_INT_1610_DMA_CH12 },
3666    { 1, OMAP_INT_1610_DMA_CH13 },
3667    { 1, OMAP_INT_1610_DMA_CH14 },
3668    { 1, OMAP_INT_1610_DMA_CH15 }
3669};
3670
3671/* DMA ports for OMAP1 */
3672static int omap_validate_emiff_addr(struct omap_mpu_state_s *s,
3673                target_phys_addr_t addr)
3674{
3675    return range_covers_byte(OMAP_EMIFF_BASE, s->sdram_size, addr);
3676}
3677
3678static int omap_validate_emifs_addr(struct omap_mpu_state_s *s,
3679                target_phys_addr_t addr)
3680{
3681    return range_covers_byte(OMAP_EMIFS_BASE, OMAP_EMIFF_BASE - OMAP_EMIFS_BASE,
3682                             addr);
3683}
3684
3685static int omap_validate_imif_addr(struct omap_mpu_state_s *s,
3686                target_phys_addr_t addr)
3687{
3688    return range_covers_byte(OMAP_IMIF_BASE, s->sram_size, addr);
3689}
3690
3691static int omap_validate_tipb_addr(struct omap_mpu_state_s *s,
3692                target_phys_addr_t addr)
3693{
3694    return range_covers_byte(0xfffb0000, 0xffff0000 - 0xfffb0000, addr);
3695}
3696
3697static int omap_validate_local_addr(struct omap_mpu_state_s *s,
3698                target_phys_addr_t addr)
3699{
3700    return range_covers_byte(OMAP_LOCALBUS_BASE, 0x1000000, addr);
3701}
3702
3703static int omap_validate_tipb_mpui_addr(struct omap_mpu_state_s *s,
3704                target_phys_addr_t addr)
3705{
3706    return range_covers_byte(0xe1010000, 0xe1020004 - 0xe1010000, addr);
3707}
3708
3709struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
3710                const char *core)
3711{
3712    int i;
3713    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
3714            qemu_mallocz(sizeof(struct omap_mpu_state_s));
3715    ram_addr_t imif_base, emiff_base;
3716    qemu_irq *cpu_irq;
3717    qemu_irq dma_irqs[6];
3718    DriveInfo *dinfo;
3719
3720    if (!core)
3721        core = "ti925t";
3722
3723    /* Core */
3724    s->mpu_model = omap310;
3725    s->env = cpu_init(core);
3726    if (!s->env) {
3727        fprintf(stderr, "Unable to find CPU definition\n");
3728        exit(1);
3729    }
3730    s->sdram_size = sdram_size;
3731    s->sram_size = OMAP15XX_SRAM_SIZE;
3732
3733    s->wakeup = qemu_allocate_irqs(omap_mpu_wakeup, s, 1)[0];
3734
3735    /* Clocks */
3736    omap_clk_init(s);
3737
3738    /* Memory-mapped stuff */
3739    cpu_register_physical_memory(OMAP_EMIFF_BASE, s->sdram_size,
3740                    (emiff_base = qemu_ram_alloc(NULL, "omap1.dram",
3741                                                 s->sdram_size)) | IO_MEM_RAM);
3742    cpu_register_physical_memory(OMAP_IMIF_BASE, s->sram_size,
3743                    (imif_base = qemu_ram_alloc(NULL, "omap1.sram",
3744                                                s->sram_size)) | IO_MEM_RAM);
3745
3746    omap_clkm_init(0xfffece00, 0xe1008000, s);
3747
3748    cpu_irq = arm_pic_init_cpu(s->env);
3749    s->ih[0] = omap_inth_init(0xfffecb00, 0x100, 1, &s->irq[0],
3750                    cpu_irq[ARM_PIC_CPU_IRQ], cpu_irq[ARM_PIC_CPU_FIQ],
3751                    omap_findclk(s, "arminth_ck"));
3752    s->ih[1] = omap_inth_init(0xfffe0000, 0x800, 1, &s->irq[1],
3753                    omap_inth_get_pin(s->ih[0], OMAP_INT_15XX_IH2_IRQ),
3754                    NULL, omap_findclk(s, "arminth_ck"));
3755
3756    for (i = 0; i < 6; i ++)
3757        dma_irqs[i] =
3758                s->irq[omap1_dma_irq_map[i].ih][omap1_dma_irq_map[i].intr];
3759    s->dma = omap_dma_init(0xfffed800, dma_irqs, s->irq[0][OMAP_INT_DMA_LCD],
3760                           s, omap_findclk(s, "dma_ck"), omap_dma_3_1);
3761
3762    s->port[emiff    ].addr_valid = omap_validate_emiff_addr;
3763    s->port[emifs    ].addr_valid = omap_validate_emifs_addr;
3764    s->port[imif     ].addr_valid = omap_validate_imif_addr;
3765    s->port[tipb     ].addr_valid = omap_validate_tipb_addr;
3766    s->port[local    ].addr_valid = omap_validate_local_addr;
3767    s->port[tipb_mpui].addr_valid = omap_validate_tipb_mpui_addr;
3768
3769    /* Register SDRAM and SRAM DMA ports for fast transfers.  */
3770    soc_dma_port_add_mem_ram(s->dma,
3771                    emiff_base, OMAP_EMIFF_BASE, s->sdram_size);
3772    soc_dma_port_add_mem_ram(s->dma,
3773                    imif_base, OMAP_IMIF_BASE, s->sram_size);
3774
3775    s->timer[0] = omap_mpu_timer_init(0xfffec500,
3776                    s->irq[0][OMAP_INT_TIMER1],
3777                    omap_findclk(s, "mputim_ck"));
3778    s->timer[1] = omap_mpu_timer_init(0xfffec600,
3779                    s->irq[0][OMAP_INT_TIMER2],
3780                    omap_findclk(s, "mputim_ck"));
3781    s->timer[2] = omap_mpu_timer_init(0xfffec700,
3782                    s->irq[0][OMAP_INT_TIMER3],
3783                    omap_findclk(s, "mputim_ck"));
3784
3785    s->wdt = omap_wd_timer_init(0xfffec800,
3786                    s->irq[0][OMAP_INT_WD_TIMER],
3787                    omap_findclk(s, "armwdt_ck"));
3788
3789    s->os_timer = omap_os_timer_init(0xfffb9000,
3790                    s->irq[1][OMAP_INT_OS_TIMER],
3791                    omap_findclk(s, "clk32-kHz"));
3792
3793    s->lcd = omap_lcdc_init(0xfffec000, s->irq[0][OMAP_INT_LCD_CTRL],
3794                    omap_dma_get_lcdch(s->dma), imif_base, emiff_base,
3795                    omap_findclk(s, "lcd_ck"));
3796
3797    omap_ulpd_pm_init(0xfffe0800, s);
3798    omap_pin_cfg_init(0xfffe1000, s);
3799    omap_id_init(s);
3800
3801    omap_mpui_init(0xfffec900, s);
3802
3803    s->private_tipb = omap_tipb_bridge_init(0xfffeca00,
3804                    s->irq[0][OMAP_INT_BRIDGE_PRIV],
3805                    omap_findclk(s, "tipb_ck"));
3806    s->public_tipb = omap_tipb_bridge_init(0xfffed300,
3807                    s->irq[0][OMAP_INT_BRIDGE_PUB],
3808                    omap_findclk(s, "tipb_ck"));
3809
3810    omap_tcmi_init(0xfffecc00, s);
3811
3812    s->uart[0] = omap_uart_init(0xfffb0000, s->irq[1][OMAP_INT_UART1],
3813                    omap_findclk(s, "uart1_ck"),
3814                    omap_findclk(s, "uart1_ck"),
3815                    s->drq[OMAP_DMA_UART1_TX], s->drq[OMAP_DMA_UART1_RX],
3816                    "uart1",
3817                    serial_hds[0]);
3818    s->uart[1] = omap_uart_init(0xfffb0800, s->irq[1][OMAP_INT_UART2],
3819                    omap_findclk(s, "uart2_ck"),
3820                    omap_findclk(s, "uart2_ck"),
3821                    s->drq[OMAP_DMA_UART2_TX], s->drq[OMAP_DMA_UART2_RX],
3822                    "uart2",
3823                    serial_hds[0] ? serial_hds[1] : NULL);
3824    s->uart[2] = omap_uart_init(0xfffb9800, s->irq[0][OMAP_INT_UART3],
3825                    omap_findclk(s, "uart3_ck"),
3826                    omap_findclk(s, "uart3_ck"),
3827                    s->drq[OMAP_DMA_UART3_TX], s->drq[OMAP_DMA_UART3_RX],
3828                    "uart3",
3829                    serial_hds[0] && serial_hds[1] ? serial_hds[2] : NULL);
3830
3831    omap_dpll_init(&s->dpll[0], 0xfffecf00, omap_findclk(s, "dpll1"));
3832    omap_dpll_init(&s->dpll[1], 0xfffed000, omap_findclk(s, "dpll2"));
3833    omap_dpll_init(&s->dpll[2], 0xfffed100, omap_findclk(s, "dpll3"));
3834
3835    dinfo = drive_get(IF_SD, 0, 0);
3836    if (!dinfo) {
3837        fprintf(stderr, "qemu: missing SecureDigital device\n");
3838        exit(1);
3839    }
3840    s->mmc = omap_mmc_init(0xfffb7800, dinfo->bdrv,
3841                    s->irq[1][OMAP_INT_OQN], &s->drq[OMAP_DMA_MMC_TX],
3842                    omap_findclk(s, "mmc_ck"));
3843
3844    s->mpuio = omap_mpuio_init(0xfffb5000,
3845                    s->irq[1][OMAP_INT_KEYBOARD], s->irq[1][OMAP_INT_MPUIO],
3846                    s->wakeup, omap_findclk(s, "clk32-kHz"));
3847
3848    s->gpio = omap_gpio_init(0xfffce000, s->irq[0][OMAP_INT_GPIO_BANK1],
3849                    omap_findclk(s, "arm_gpio_ck"));
3850
3851    s->microwire = omap_uwire_init(0xfffb3000, &s->irq[1][OMAP_INT_uWireTX],
3852                    s->drq[OMAP_DMA_UWIRE_TX], omap_findclk(s, "mpuper_ck"));
3853
3854    omap_pwl_init(0xfffb5800, s, omap_findclk(s, "armxor_ck"));
3855    omap_pwt_init(0xfffb6000, s, omap_findclk(s, "armxor_ck"));
3856
3857    s->i2c[0] = omap_i2c_init(0xfffb3800, s->irq[1][OMAP_INT_I2C],
3858                    &s->drq[OMAP_DMA_I2C_RX], omap_findclk(s, "mpuper_ck"));
3859
3860    s->rtc = omap_rtc_init(0xfffb4800, &s->irq[1][OMAP_INT_RTC_TIMER],
3861                    omap_findclk(s, "clk32-kHz"));
3862
3863    s->mcbsp1 = omap_mcbsp_init(0xfffb1800, &s->irq[1][OMAP_INT_McBSP1TX],
3864                    &s->drq[OMAP_DMA_MCBSP1_TX], omap_findclk(s, "dspxor_ck"));
3865    s->mcbsp2 = omap_mcbsp_init(0xfffb1000, &s->irq[0][OMAP_INT_310_McBSP2_TX],
3866                    &s->drq[OMAP_DMA_MCBSP2_TX], omap_findclk(s, "mpuper_ck"));
3867    s->mcbsp3 = omap_mcbsp_init(0xfffb7000, &s->irq[1][OMAP_INT_McBSP3TX],
3868                    &s->drq[OMAP_DMA_MCBSP3_TX], omap_findclk(s, "dspxor_ck"));
3869
3870    s->led[0] = omap_lpg_init(0xfffbd000, omap_findclk(s, "clk32-kHz"));
3871    s->led[1] = omap_lpg_init(0xfffbd800, omap_findclk(s, "clk32-kHz"));
3872
3873    /* Register mappings not currenlty implemented:
3874     * MCSI2 Comm       fffb2000 - fffb27ff (not mapped on OMAP310)
3875     * MCSI1 Bluetooth  fffb2800 - fffb2fff (not mapped on OMAP310)
3876     * USB W2FC         fffb4000 - fffb47ff
3877     * Camera Interface fffb6800 - fffb6fff
3878     * USB Host         fffba000 - fffba7ff
3879     * FAC              fffba800 - fffbafff
3880     * HDQ/1-Wire       fffbc000 - fffbc7ff
3881     * TIPB switches    fffbc800 - fffbcfff
3882     * Mailbox          fffcf000 - fffcf7ff
3883     * Local bus IF     fffec100 - fffec1ff
3884     * Local bus MMU    fffec200 - fffec2ff
3885     * DSP MMU          fffed200 - fffed2ff
3886     */
3887
3888    omap_setup_dsp_mapping(omap15xx_dsp_mm);
3889    omap_setup_mpui_io(s);
3890
3891    qemu_register_reset(omap1_mpu_reset, s);
3892
3893    return s;
3894}
3895