?? pxa2xx.c
字號:
{ struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) opaque; addr -= s->base; switch (addr) { case ICR: return s->control; case ISR: return s->status | (i2c_bus_busy(s->bus) << 2); case ISAR: return s->slave.address; case IDBR: return s->data; case IBMR: if (s->status & (1 << 2)) s->ibmr ^= 3; /* Fake SCL and SDA pin changes */ else s->ibmr = 0; return s->ibmr; default: printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr); break; } return 0;}static void pxa2xx_i2c_write(void *opaque, target_phys_addr_t addr, uint32_t value){ struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) opaque; int ack; addr -= s->base; switch (addr) { case ICR: s->control = value & 0xfff7; if ((value & (1 << 3)) && (value & (1 << 6))) { /* TB and IUE */ /* TODO: slave mode */ if (value & (1 << 0)) { /* START condition */ if (s->data & 1) s->status |= 1 << 0; /* set RWM */ else s->status &= ~(1 << 0); /* clear RWM */ ack = !i2c_start_transfer(s->bus, s->data >> 1, s->data & 1); } else { if (s->status & (1 << 0)) { /* RWM */ s->data = i2c_recv(s->bus); if (value & (1 << 2)) /* ACKNAK */ i2c_nack(s->bus); ack = 1; } else ack = !i2c_send(s->bus, s->data); } if (value & (1 << 1)) /* STOP condition */ i2c_end_transfer(s->bus); if (ack) { if (value & (1 << 0)) /* START condition */ s->status |= 1 << 6; /* set ITE */ else if (s->status & (1 << 0)) /* RWM */ s->status |= 1 << 7; /* set IRF */ else s->status |= 1 << 6; /* set ITE */ s->status &= ~(1 << 1); /* clear ACKNAK */ } else { s->status |= 1 << 6; /* set ITE */ s->status |= 1 << 10; /* set BED */ s->status |= 1 << 1; /* set ACKNAK */ } } if (!(value & (1 << 3)) && (value & (1 << 6))) /* !TB and IUE */ if (value & (1 << 4)) /* MA */ i2c_end_transfer(s->bus); pxa2xx_i2c_update(s); break; case ISR: s->status &= ~(value & 0x07f0); pxa2xx_i2c_update(s); break; case ISAR: i2c_set_slave_address(&s->slave, value & 0x7f); break; case IDBR: s->data = value & 0xff; break; default: printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr); }}static CPUReadMemoryFunc *pxa2xx_i2c_readfn[] = { pxa2xx_i2c_read, pxa2xx_i2c_read, pxa2xx_i2c_read,};static CPUWriteMemoryFunc *pxa2xx_i2c_writefn[] = { pxa2xx_i2c_write, pxa2xx_i2c_write, pxa2xx_i2c_write,};static void pxa2xx_i2c_save(QEMUFile *f, void *opaque){ struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) opaque; qemu_put_be16s(f, &s->control); qemu_put_be16s(f, &s->status); qemu_put_8s(f, &s->ibmr); qemu_put_8s(f, &s->data); i2c_bus_save(f, s->bus); i2c_slave_save(f, &s->slave);}static int pxa2xx_i2c_load(QEMUFile *f, void *opaque, int version_id){ struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) opaque; qemu_get_be16s(f, &s->control); qemu_get_be16s(f, &s->status); qemu_get_8s(f, &s->ibmr); qemu_get_8s(f, &s->data); i2c_bus_load(f, s->bus); i2c_slave_load(f, &s->slave); return 0;}struct pxa2xx_i2c_s *pxa2xx_i2c_init(target_phys_addr_t base, qemu_irq irq, uint32_t page_size){ int iomemtype; struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) i2c_slave_init(i2c_init_bus(), 0, sizeof(struct pxa2xx_i2c_s)); s->base = base; s->irq = irq; s->slave.event = pxa2xx_i2c_event; s->slave.recv = pxa2xx_i2c_rx; s->slave.send = pxa2xx_i2c_tx; s->bus = i2c_init_bus(); iomemtype = cpu_register_io_memory(0, pxa2xx_i2c_readfn, pxa2xx_i2c_writefn, s); cpu_register_physical_memory(s->base & ~page_size, page_size, iomemtype); register_savevm("pxa2xx_i2c", base, 0, pxa2xx_i2c_save, pxa2xx_i2c_load, s); return s;}i2c_bus *pxa2xx_i2c_bus(struct pxa2xx_i2c_s *s){ return s->bus;}/* PXA Inter-IC Sound Controller */static void pxa2xx_i2s_reset(struct pxa2xx_i2s_s *i2s){ i2s->rx_len = 0; i2s->tx_len = 0; i2s->fifo_len = 0; i2s->clk = 0x1a; i2s->control[0] = 0x00; i2s->control[1] = 0x00; i2s->status = 0x00; i2s->mask = 0x00;}#define SACR_TFTH(val) ((val >> 8) & 0xf)#define SACR_RFTH(val) ((val >> 12) & 0xf)#define SACR_DREC(val) (val & (1 << 3))#define SACR_DPRL(val) (val & (1 << 4))static inline void pxa2xx_i2s_update(struct pxa2xx_i2s_s *i2s){ int rfs, tfs; rfs = SACR_RFTH(i2s->control[0]) < i2s->rx_len && !SACR_DREC(i2s->control[1]); tfs = (i2s->tx_len || i2s->fifo_len < SACR_TFTH(i2s->control[0])) && i2s->enable && !SACR_DPRL(i2s->control[1]); pxa2xx_dma_request(i2s->dma, PXA2XX_RX_RQ_I2S, rfs); pxa2xx_dma_request(i2s->dma, PXA2XX_TX_RQ_I2S, tfs); i2s->status &= 0xe0; if (i2s->fifo_len < 16 || !i2s->enable) i2s->status |= 1 << 0; /* TNF */ if (i2s->rx_len) i2s->status |= 1 << 1; /* RNE */ if (i2s->enable) i2s->status |= 1 << 2; /* BSY */ if (tfs) i2s->status |= 1 << 3; /* TFS */ if (rfs) i2s->status |= 1 << 4; /* RFS */ if (!(i2s->tx_len && i2s->enable)) i2s->status |= i2s->fifo_len << 8; /* TFL */ i2s->status |= MAX(i2s->rx_len, 0xf) << 12; /* RFL */ qemu_set_irq(i2s->irq, i2s->status & i2s->mask);}#define SACR0 0x00 /* Serial Audio Global Control register */#define SACR1 0x04 /* Serial Audio I2S/MSB-Justified Control register */#define SASR0 0x0c /* Serial Audio Interface and FIFO Status register */#define SAIMR 0x14 /* Serial Audio Interrupt Mask register */#define SAICR 0x18 /* Serial Audio Interrupt Clear register */#define SADIV 0x60 /* Serial Audio Clock Divider register */#define SADR 0x80 /* Serial Audio Data register */static uint32_t pxa2xx_i2s_read(void *opaque, target_phys_addr_t addr){ struct pxa2xx_i2s_s *s = (struct pxa2xx_i2s_s *) opaque; addr -= s->base; switch (addr) { case SACR0: return s->control[0]; case SACR1: return s->control[1]; case SASR0: return s->status; case SAIMR: return s->mask; case SAICR: return 0; case SADIV: return s->clk; case SADR: if (s->rx_len > 0) { s->rx_len --; pxa2xx_i2s_update(s); return s->codec_in(s->opaque); } return 0; default: printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr); break; } return 0;}static void pxa2xx_i2s_write(void *opaque, target_phys_addr_t addr, uint32_t value){ struct pxa2xx_i2s_s *s = (struct pxa2xx_i2s_s *) opaque; uint32_t *sample; addr -= s->base; switch (addr) { case SACR0: if (value & (1 << 3)) /* RST */ pxa2xx_i2s_reset(s); s->control[0] = value & 0xff3d; if (!s->enable && (value & 1) && s->tx_len) { /* ENB */ for (sample = s->fifo; s->fifo_len > 0; s->fifo_len --, sample ++) s->codec_out(s->opaque, *sample); s->status &= ~(1 << 7); /* I2SOFF */ } if (value & (1 << 4)) /* EFWR */ printf("%s: Attempt to use special function\n", __FUNCTION__); s->enable = ((value ^ 4) & 5) == 5; /* ENB && !RST*/ pxa2xx_i2s_update(s); break; case SACR1: s->control[1] = value & 0x0039; if (value & (1 << 5)) /* ENLBF */ printf("%s: Attempt to use loopback function\n", __FUNCTION__); if (value & (1 << 4)) /* DPRL */ s->fifo_len = 0; pxa2xx_i2s_update(s); break; case SAIMR: s->mask = value & 0x0078; pxa2xx_i2s_update(s); break; case SAICR: s->status &= ~(value & (3 << 5)); pxa2xx_i2s_update(s); break; case SADIV: s->clk = value & 0x007f; break; case SADR: if (s->tx_len && s->enable) { s->tx_len --; pxa2xx_i2s_update(s); s->codec_out(s->opaque, value); } else if (s->fifo_len < 16) { s->fifo[s->fifo_len ++] = value; pxa2xx_i2s_update(s); } break; default: printf("%s: Bad register " REG_FMT "\n", __FUNCTION__, addr); }}static CPUReadMemoryFunc *pxa2xx_i2s_readfn[] = { pxa2xx_i2s_read, pxa2xx_i2s_read, pxa2xx_i2s_read,};static CPUWriteMemoryFunc *pxa2xx_i2s_writefn[] = { pxa2xx_i2s_write, pxa2xx_i2s_write, pxa2xx_i2s_write,};static void pxa2xx_i2s_save(QEMUFile *f, void *opaque){ struct pxa2xx_i2s_s *s = (struct pxa2xx_i2s_s *) opaque; qemu_put_be32s(f, &s->control[0]); qemu_put_be32s(f, &s->control[1]); qemu_put_be32s(f, &s->status); qemu_put_be32s(f, &s->mask); qemu_put_be32s(f, &s->clk); qemu_put_be32(f, s->enable); qemu_put_be32(f, s->rx_len); qemu_put_be32(f, s->tx_len); qemu_put_be32(f, s->fifo_len);}static int pxa2xx_i2s_load(QEMUFile *f, void *opaque, int version_id){ struct pxa2xx_i2s_s *s = (struct pxa2xx_i2s_s *) opaque; qemu_get_be32s(f, &s->control[0]); qemu_get_be32s(f, &s->control[1]); qemu_get_be32s(f, &s->status); qemu_get_be32s(f, &s->mask); qemu_get_be32s(f, &s->clk); s->enable = qemu_get_be32(f); s->rx_len = qemu_get_be32(f); s->tx_len = qemu_get_be32(f); s->fifo_len = qemu_get_be32(f); return 0;}static void pxa2xx_i2s_data_req(void *opaque, int tx, int rx){ struct pxa2xx_i2s_s *s = (struct pxa2xx_i2s_s *) opaque; uint32_t *sample; /* Signal FIFO errors */ if (s->enable && s->tx_len) s->status |= 1 << 5; /* TUR */ if (s->enable && s->rx_len) s->status |= 1 << 6; /* ROR */ /* Should be tx - MIN(tx, s->fifo_len) but we don't really need to * handle the cases where it makes a difference. */ s->tx_len = tx - s->fifo_len; s->rx_len = rx; /* Note that is s->codec_out wasn't set, we wouldn't get called. */ if (s->enable) for (sample = s->fifo; s->fifo_len; s->fifo_len --, sample ++) s->codec_out(s->opaque, *sample); pxa2xx_i2s_update(s);}static struct pxa2xx_i2s_s *pxa2xx_i2s_init(target_phys_addr_t base, qemu_irq irq, struct pxa2xx_dma_state_s *dma){ int iomemtype; struct pxa2xx_i2s_s *s = (struct pxa2xx_i2s_s *) qemu_mallocz(sizeof(struct pxa2xx_i2s_s)); s->base = base; s->irq = irq; s->dma = dma; s->data_req = pxa2xx_i2s_data_req; pxa2xx_i2s_reset(s); iomemtype = cpu_register_io_memory(0, pxa2xx_i2s_readfn, pxa2xx_i2s_writefn, s); cpu_register_physical_memory(s->base & 0xfff00000, 0x100000, iomemtype); register_savevm("pxa2xx_i2s", base, 0, pxa2xx_i2s_save, pxa2xx_i2s_load, s); return s;}/* PXA Fast Infra-red Communications Port */struct pxa2xx_fir_s { target_phys_addr_t base; qemu_irq irq; struct pxa2xx_dma_state_s *dma; int enable; CharDriverState *chr; uint8_t control[3]; uint8_t status[2]; int rx_len; int rx_start; uint8_t rx_fifo[64];};static void pxa2xx_fir_reset(struct pxa2xx_fir_s *s){ s->control[0] = 0x00; s->control[1] = 0x00; s->control[2] = 0x00; s->status[0] = 0x00; s->status[1] = 0x00; s->enable = 0;}static inline void pxa2xx_fir_update(struct pxa2xx_fir_s *s){ static const int tresh[4] = { 8, 16, 32, 0 }; int intr = 0; if ((s->control[0] & (1 << 4)) && /* RXE */ s->rx_len >= tresh[s->control[2] & 3]) /* TRIG */ s->status[0] |= 1 << 4; /* RFS */ else s->status[0] &= ~(1 << 4); /* RFS */ if (s->control[0] & (1 << 3)) /* TXE */ s->status[0] |= 1 << 3; /* TFS */ else s->status[0] &= ~(1 << 3); /* TFS */ if (s->rx_len) s->status[1] |= 1 << 2; /* RNE */ else s->status[1] &= ~(1 << 2); /* RNE */ if (s->control[0] & (1 << 4)) /* RXE */ s->status[1] |= 1 << 0; /* RSY */ else s->status[1] &= ~(1 << 0); /* RSY */ intr |= (s->control[0] & (1 << 5)) && /* RIE */ (s->status[0] & (1 << 4)); /* RFS */ intr |= (s->control[0] & (1 << 6)) && /* TIE */ (s->status[0] & (1 << 3)); /* TFS */ intr |= (s->control[2] & (1 << 4)) && /* TRAIL */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -