?? pxa2xx.c
字號(hào):
int64_t rt = qemu_get_clock(rt_clock); s->last_rcnr += ((rt - s->last_hz) << 15) / (1000 * ((s->rttr & 0xffff) + 1)); s->last_rdcr += ((rt - s->last_hz) << 15) / (1000 * ((s->rttr & 0xffff) + 1)); s->last_hz = rt;}static void pxa2xx_rtc_swupdate(struct pxa2xx_state_s *s){ int64_t rt = qemu_get_clock(rt_clock); if (s->rtsr & (1 << 12)) s->last_swcr += (rt - s->last_sw) / 10; s->last_sw = rt;}static void pxa2xx_rtc_piupdate(struct pxa2xx_state_s *s){ int64_t rt = qemu_get_clock(rt_clock); if (s->rtsr & (1 << 15)) s->last_swcr += rt - s->last_pi; s->last_pi = rt;}static inline void pxa2xx_rtc_alarm_update(struct pxa2xx_state_s *s, uint32_t rtsr){ if ((rtsr & (1 << 2)) && !(rtsr & (1 << 0))) qemu_mod_timer(s->rtc_hz, s->last_hz + (((s->rtar - s->last_rcnr) * 1000 * ((s->rttr & 0xffff) + 1)) >> 15)); else qemu_del_timer(s->rtc_hz); if ((rtsr & (1 << 5)) && !(rtsr & (1 << 4))) qemu_mod_timer(s->rtc_rdal1, s->last_hz + (((s->rdar1 - s->last_rdcr) * 1000 * ((s->rttr & 0xffff) + 1)) >> 15)); /* TODO: fixup */ else qemu_del_timer(s->rtc_rdal1); if ((rtsr & (1 << 7)) && !(rtsr & (1 << 6))) qemu_mod_timer(s->rtc_rdal2, s->last_hz + (((s->rdar2 - s->last_rdcr) * 1000 * ((s->rttr & 0xffff) + 1)) >> 15)); /* TODO: fixup */ else qemu_del_timer(s->rtc_rdal2); if ((rtsr & 0x1200) == 0x1200 && !(rtsr & (1 << 8))) qemu_mod_timer(s->rtc_swal1, s->last_sw + (s->swar1 - s->last_swcr) * 10); /* TODO: fixup */ else qemu_del_timer(s->rtc_swal1); if ((rtsr & 0x1800) == 0x1800 && !(rtsr & (1 << 10))) qemu_mod_timer(s->rtc_swal2, s->last_sw + (s->swar2 - s->last_swcr) * 10); /* TODO: fixup */ else qemu_del_timer(s->rtc_swal2); if ((rtsr & 0xc000) == 0xc000 && !(rtsr & (1 << 13))) qemu_mod_timer(s->rtc_pi, s->last_pi + (s->piar & 0xffff) - s->last_rtcpicr); else qemu_del_timer(s->rtc_pi);}static inline void pxa2xx_rtc_hz_tick(void *opaque){ struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque; s->rtsr |= (1 << 0); pxa2xx_rtc_alarm_update(s, s->rtsr); pxa2xx_rtc_int_update(s);}static inline void pxa2xx_rtc_rdal1_tick(void *opaque){ struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque; s->rtsr |= (1 << 4); pxa2xx_rtc_alarm_update(s, s->rtsr); pxa2xx_rtc_int_update(s);}static inline void pxa2xx_rtc_rdal2_tick(void *opaque){ struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque; s->rtsr |= (1 << 6); pxa2xx_rtc_alarm_update(s, s->rtsr); pxa2xx_rtc_int_update(s);}static inline void pxa2xx_rtc_swal1_tick(void *opaque){ struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque; s->rtsr |= (1 << 8); pxa2xx_rtc_alarm_update(s, s->rtsr); pxa2xx_rtc_int_update(s);}static inline void pxa2xx_rtc_swal2_tick(void *opaque){ struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque; s->rtsr |= (1 << 10); pxa2xx_rtc_alarm_update(s, s->rtsr); pxa2xx_rtc_int_update(s);}static inline void pxa2xx_rtc_pi_tick(void *opaque){ struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque; s->rtsr |= (1 << 13); pxa2xx_rtc_piupdate(s); s->last_rtcpicr = 0; pxa2xx_rtc_alarm_update(s, s->rtsr); pxa2xx_rtc_int_update(s);}static uint32_t pxa2xx_rtc_read(void *opaque, target_phys_addr_t addr){ struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque; addr -= s->rtc_base; switch (addr) { case RTTR: return s->rttr; case RTSR: return s->rtsr; case RTAR: return s->rtar; case RDAR1: return s->rdar1; case RDAR2: return s->rdar2; case RYAR1: return s->ryar1; case RYAR2: return s->ryar2; case SWAR1: return s->swar1; case SWAR2: return s->swar2; case PIAR: return s->piar; case RCNR: return s->last_rcnr + ((qemu_get_clock(rt_clock) - s->last_hz) << 15) / (1000 * ((s->rttr & 0xffff) + 1)); case RDCR: return s->last_rdcr + ((qemu_get_clock(rt_clock) - s->last_hz) << 15) / (1000 * ((s->rttr & 0xffff) + 1)); case RYCR: return s->last_rycr; case SWCR: if (s->rtsr & (1 << 12)) return s->last_swcr + (qemu_get_clock(rt_clock) - s->last_sw) / 10; else return s->last_swcr; default: printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr); break; } return 0;}static void pxa2xx_rtc_write(void *opaque, target_phys_addr_t addr, uint32_t value){ struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque; addr -= s->rtc_base; switch (addr) { case RTTR: if (!(s->rttr & (1 << 31))) { pxa2xx_rtc_hzupdate(s); s->rttr = value; pxa2xx_rtc_alarm_update(s, s->rtsr); } break; case RTSR: if ((s->rtsr ^ value) & (1 << 15)) pxa2xx_rtc_piupdate(s); if ((s->rtsr ^ value) & (1 << 12)) pxa2xx_rtc_swupdate(s); if (((s->rtsr ^ value) & 0x4aac) | (value & ~0xdaac)) pxa2xx_rtc_alarm_update(s, value); s->rtsr = (value & 0xdaac) | (s->rtsr & ~(value & ~0xdaac)); pxa2xx_rtc_int_update(s); break; case RTAR: s->rtar = value; pxa2xx_rtc_alarm_update(s, s->rtsr); break; case RDAR1: s->rdar1 = value; pxa2xx_rtc_alarm_update(s, s->rtsr); break; case RDAR2: s->rdar2 = value; pxa2xx_rtc_alarm_update(s, s->rtsr); break; case RYAR1: s->ryar1 = value; pxa2xx_rtc_alarm_update(s, s->rtsr); break; case RYAR2: s->ryar2 = value; pxa2xx_rtc_alarm_update(s, s->rtsr); break; case SWAR1: pxa2xx_rtc_swupdate(s); s->swar1 = value; s->last_swcr = 0; pxa2xx_rtc_alarm_update(s, s->rtsr); break; case SWAR2: s->swar2 = value; pxa2xx_rtc_alarm_update(s, s->rtsr); break; case PIAR: s->piar = value; pxa2xx_rtc_alarm_update(s, s->rtsr); break; case RCNR: pxa2xx_rtc_hzupdate(s); s->last_rcnr = value; pxa2xx_rtc_alarm_update(s, s->rtsr); break; case RDCR: pxa2xx_rtc_hzupdate(s); s->last_rdcr = value; pxa2xx_rtc_alarm_update(s, s->rtsr); break; case RYCR: s->last_rycr = value; break; case SWCR: pxa2xx_rtc_swupdate(s); s->last_swcr = value; pxa2xx_rtc_alarm_update(s, s->rtsr); break; case RTCPICR: pxa2xx_rtc_piupdate(s); s->last_rtcpicr = value & 0xffff; pxa2xx_rtc_alarm_update(s, s->rtsr); break; default: printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr); }}static CPUReadMemoryFunc *pxa2xx_rtc_readfn[] = { pxa2xx_rtc_read, pxa2xx_rtc_read, pxa2xx_rtc_read,};static CPUWriteMemoryFunc *pxa2xx_rtc_writefn[] = { pxa2xx_rtc_write, pxa2xx_rtc_write, pxa2xx_rtc_write,};static void pxa2xx_rtc_init(struct pxa2xx_state_s *s){ struct tm *tm; time_t ti; int wom; s->rttr = 0x7fff; s->rtsr = 0; time(&ti); if (rtc_utc) tm = gmtime(&ti); else tm = localtime(&ti); wom = ((tm->tm_mday - 1) / 7) + 1; s->last_rcnr = (uint32_t) ti; s->last_rdcr = (wom << 20) | ((tm->tm_wday + 1) << 17) | (tm->tm_hour << 12) | (tm->tm_min << 6) | tm->tm_sec; s->last_rycr = ((tm->tm_year + 1900) << 9) | ((tm->tm_mon + 1) << 5) | tm->tm_mday; s->last_swcr = (tm->tm_hour << 19) | (tm->tm_min << 13) | (tm->tm_sec << 7); s->last_rtcpicr = 0; s->last_hz = s->last_sw = s->last_pi = qemu_get_clock(rt_clock); s->rtc_hz = qemu_new_timer(rt_clock, pxa2xx_rtc_hz_tick, s); s->rtc_rdal1 = qemu_new_timer(rt_clock, pxa2xx_rtc_rdal1_tick, s); s->rtc_rdal2 = qemu_new_timer(rt_clock, pxa2xx_rtc_rdal2_tick, s); s->rtc_swal1 = qemu_new_timer(rt_clock, pxa2xx_rtc_swal1_tick, s); s->rtc_swal2 = qemu_new_timer(rt_clock, pxa2xx_rtc_swal2_tick, s); s->rtc_pi = qemu_new_timer(rt_clock, pxa2xx_rtc_pi_tick, s);}static void pxa2xx_rtc_save(QEMUFile *f, void *opaque){ struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque; pxa2xx_rtc_hzupdate(s); pxa2xx_rtc_piupdate(s); pxa2xx_rtc_swupdate(s); qemu_put_be32s(f, &s->rttr); qemu_put_be32s(f, &s->rtsr); qemu_put_be32s(f, &s->rtar); qemu_put_be32s(f, &s->rdar1); qemu_put_be32s(f, &s->rdar2); qemu_put_be32s(f, &s->ryar1); qemu_put_be32s(f, &s->ryar2); qemu_put_be32s(f, &s->swar1); qemu_put_be32s(f, &s->swar2); qemu_put_be32s(f, &s->piar); qemu_put_be32s(f, &s->last_rcnr); qemu_put_be32s(f, &s->last_rdcr); qemu_put_be32s(f, &s->last_rycr); qemu_put_be32s(f, &s->last_swcr); qemu_put_be32s(f, &s->last_rtcpicr); qemu_put_be64s(f, &s->last_hz); qemu_put_be64s(f, &s->last_sw); qemu_put_be64s(f, &s->last_pi);}static int pxa2xx_rtc_load(QEMUFile *f, void *opaque, int version_id){ struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque; qemu_get_be32s(f, &s->rttr); qemu_get_be32s(f, &s->rtsr); qemu_get_be32s(f, &s->rtar); qemu_get_be32s(f, &s->rdar1); qemu_get_be32s(f, &s->rdar2); qemu_get_be32s(f, &s->ryar1); qemu_get_be32s(f, &s->ryar2); qemu_get_be32s(f, &s->swar1); qemu_get_be32s(f, &s->swar2); qemu_get_be32s(f, &s->piar); qemu_get_be32s(f, &s->last_rcnr); qemu_get_be32s(f, &s->last_rdcr); qemu_get_be32s(f, &s->last_rycr); qemu_get_be32s(f, &s->last_swcr); qemu_get_be32s(f, &s->last_rtcpicr); qemu_get_be64s(f, &s->last_hz); qemu_get_be64s(f, &s->last_sw); qemu_get_be64s(f, &s->last_pi); pxa2xx_rtc_alarm_update(s, s->rtsr); return 0;}/* I2C Interface */struct pxa2xx_i2c_s { i2c_slave slave; i2c_bus *bus; target_phys_addr_t base; qemu_irq irq; uint16_t control; uint16_t status; uint8_t ibmr; uint8_t data;};#define IBMR 0x80 /* I2C Bus Monitor register */#define IDBR 0x88 /* I2C Data Buffer register */#define ICR 0x90 /* I2C Control register */#define ISR 0x98 /* I2C Status register */#define ISAR 0xa0 /* I2C Slave Address register */static void pxa2xx_i2c_update(struct pxa2xx_i2c_s *s){ uint16_t level = 0; level |= s->status & s->control & (1 << 10); /* BED */ level |= (s->status & (1 << 7)) && (s->control & (1 << 9)); /* IRF */ level |= (s->status & (1 << 6)) && (s->control & (1 << 8)); /* ITE */ level |= s->status & (1 << 9); /* SAD */ qemu_set_irq(s->irq, !!level);}/* These are only stubs now. */static void pxa2xx_i2c_event(i2c_slave *i2c, enum i2c_event event){ struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) i2c; switch (event) { case I2C_START_SEND: s->status |= (1 << 9); /* set SAD */ s->status &= ~(1 << 0); /* clear RWM */ break; case I2C_START_RECV: s->status |= (1 << 9); /* set SAD */ s->status |= 1 << 0; /* set RWM */ break; case I2C_FINISH: s->status |= (1 << 4); /* set SSD */ break; case I2C_NACK: s->status |= 1 << 1; /* set ACKNAK */ break; } pxa2xx_i2c_update(s);}static int pxa2xx_i2c_rx(i2c_slave *i2c){ struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) i2c; if ((s->control & (1 << 14)) || !(s->control & (1 << 6))) return 0; if (s->status & (1 << 0)) { /* RWM */ s->status |= 1 << 6; /* set ITE */ } pxa2xx_i2c_update(s); return s->data;}static int pxa2xx_i2c_tx(i2c_slave *i2c, uint8_t data){ struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) i2c; if ((s->control & (1 << 14)) || !(s->control & (1 << 6))) return 1; if (!(s->status & (1 << 0))) { /* RWM */ s->status |= 1 << 7; /* set IRF */ s->data = data; } pxa2xx_i2c_update(s); return 1;}static uint32_t pxa2xx_i2c_read(void *opaque, target_phys_addr_t addr)
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -