X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=hw%2Fomap_dma.c;h=0c878b6ef2571a5a9c11acdaf22f53ce84b165e7;hb=35569cea79fd3f5ccb5b23ca024c7d3aa4d24e75;hp=ba980df5e17d71ecaced7f8bb290495427c97a01;hpb=d406647966365b4ea505ef290825b257c678e764;p=mirror_qemu.git diff --git a/hw/omap_dma.c b/hw/omap_dma.c index ba980df5e1..0c878b6ef2 100644 --- a/hw/omap_dma.c +++ b/hw/omap_dma.c @@ -14,13 +14,11 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . */ #include "qemu-common.h" -#include "qemu-timer.h" +#include "qemu/timer.h" #include "omap.h" #include "irq.h" #include "soc_dma.h" @@ -33,7 +31,7 @@ struct omap_dma_channel_s { int endian_lock[2]; int translate[2]; enum omap_dma_port port[2]; - target_phys_addr_t addr[2]; + hwaddr addr[2]; omap_dma_addressing_t mode[2]; uint32_t elements; uint16_t frames; @@ -80,7 +78,7 @@ struct omap_dma_channel_s { struct omap_dma_channel_s *sibling; struct omap_dma_reg_set_s { - target_phys_addr_t src, dest; + hwaddr src, dest; int frame; int element; int pck_element; @@ -104,9 +102,9 @@ struct omap_dma_channel_s { struct omap_dma_s { struct soc_dma_s *dma; + MemoryRegion iomem; struct omap_mpu_state_s *mpu; - target_phys_addr_t base; omap_clk clk; qemu_irq irq[4]; void (*intr_update)(struct omap_dma_s *s); @@ -594,84 +592,88 @@ static void omap_dma_transfer_setup(struct soc_dma_ch_s *dma) if (dma->update) { #endif - /* If the channel is element synchronized, deactivate it */ - if (min_elems == elements[omap_dma_intr_element_sync]) - omap_dma_deactivate_channel(s, ch); + /* If the channel is element synchronized, deactivate it */ + if (min_elems == elements[omap_dma_intr_element_sync]) + omap_dma_deactivate_channel(s, ch); - /* If it is the last frame, set the LAST_FRAME interrupt */ - if (min_elems == elements[omap_dma_intr_last_frame]) - ch->status |= LAST_FRAME_INTR; + /* If it is the last frame, set the LAST_FRAME interrupt */ + if (min_elems == elements[omap_dma_intr_last_frame]) + ch->status |= LAST_FRAME_INTR; - /* If exactly half of the frame was reached, set the HALF_FRAME - interrupt */ - if (min_elems == elements[omap_dma_intr_half_frame]) - ch->status |= HALF_FRAME_INTR; + /* If exactly half of the frame was reached, set the HALF_FRAME + interrupt */ + if (min_elems == elements[omap_dma_intr_half_frame]) + ch->status |= HALF_FRAME_INTR; - /* If a full packet has been transferred, set the END_PKT interrupt */ - if (min_elems == elements[omap_dma_intr_packet]) - ch->status |= END_PKT_INTR; + /* If a full packet has been transferred, set the END_PKT interrupt */ + if (min_elems == elements[omap_dma_intr_packet]) + ch->status |= END_PKT_INTR; - /* If the channel is packet-synchronized, deactivate it */ - if (min_elems == elements[omap_dma_intr_packet_sync]) - omap_dma_deactivate_channel(s, ch); + /* If the channel is packet-synchronized, deactivate it */ + if (min_elems == elements[omap_dma_intr_packet_sync]) + omap_dma_deactivate_channel(s, ch); - /* If the channel is frame synchronized, deactivate it */ - if (min_elems == elements[omap_dma_intr_frame_sync]) - omap_dma_deactivate_channel(s, ch); + /* If the channel is frame synchronized, deactivate it */ + if (min_elems == elements[omap_dma_intr_frame_sync]) + omap_dma_deactivate_channel(s, ch); - /* Set the END_FRAME interrupt */ - if (min_elems == elements[omap_dma_intr_frame]) - ch->status |= END_FRAME_INTR; + /* Set the END_FRAME interrupt */ + if (min_elems == elements[omap_dma_intr_frame]) + ch->status |= END_FRAME_INTR; - if (min_elems == elements[omap_dma_intr_block]) { - /* End of Block */ - /* Disable the channel */ + if (min_elems == elements[omap_dma_intr_block]) { + /* End of Block */ + /* Disable the channel */ - if (ch->omap_3_1_compatible_disable) { - omap_dma_disable_channel(s, ch); - if (ch->link_enabled) - omap_dma_enable_channel(s, &s->ch[ch->link_next_ch]); - } else { - if (!ch->auto_init) + if (ch->omap_3_1_compatible_disable) { omap_dma_disable_channel(s, ch); - else if (ch->repeat || ch->end_prog) - omap_dma_channel_load(ch); - else { - ch->waiting_end_prog = 1; - omap_dma_deactivate_channel(s, ch); + if (ch->link_enabled) + omap_dma_enable_channel(s, &s->ch[ch->link_next_ch]); + } else { + if (!ch->auto_init) + omap_dma_disable_channel(s, ch); + else if (ch->repeat || ch->end_prog) + omap_dma_channel_load(ch); + else { + ch->waiting_end_prog = 1; + omap_dma_deactivate_channel(s, ch); + } } - } - if (ch->interrupts & END_BLOCK_INTR) - ch->status |= END_BLOCK_INTR; - } + if (ch->interrupts & END_BLOCK_INTR) + ch->status |= END_BLOCK_INTR; + } - /* Update packet number */ - if (ch->fs && ch->bs) { - a->pck_element += min_elems; - a->pck_element %= a->pck_elements; - } + /* Update packet number */ + if (ch->fs && ch->bs) { + a->pck_element += min_elems; + a->pck_element %= a->pck_elements; + } - /* TODO: check if we really need to update anything here or perhaps we - * can skip part of this. */ + /* TODO: check if we really need to update anything here or perhaps we + * can skip part of this. */ #ifndef MULTI_REQ - if (dma->update) { + if (dma->update) { #endif - a->element += min_elems; + a->element += min_elems; - frames = a->element / a->elements; - a->element = a->element % a->elements; - a->frame += frames; - a->src += min_elems * a->elem_delta[0] + frames * a->frame_delta[0]; - a->dest += min_elems * a->elem_delta[1] + frames * a->frame_delta[1]; + frames = a->element / a->elements; + a->element = a->element % a->elements; + a->frame += frames; + a->src += min_elems * a->elem_delta[0] + frames * a->frame_delta[0]; + a->dest += min_elems * a->elem_delta[1] + frames * a->frame_delta[1]; - /* If the channel is async, update cpc */ - if (!ch->sync && frames) - ch->cpc = a->dest & 0xffff; + /* If the channel is async, update cpc */ + if (!ch->sync && frames) + ch->cpc = a->dest & 0xffff; - /* TODO: if the destination port is IMIF or EMIFF, set the dirty - * bits on it. */ + /* TODO: if the destination port is IMIF or EMIFF, set the dirty + * bits on it. */ +#ifndef MULTI_REQ + } +#else } +#endif omap_dma_interrupts_update(s); } @@ -912,7 +914,7 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s, break; case 0x06: /* SYS_DMA_CSR_CH0 */ - OMAP_RO_REG((target_phys_addr_t) reg); + OMAP_RO_REG((hwaddr) reg); break; case 0x08: /* SYS_DMA_CSSA_L_CH0 */ @@ -952,7 +954,7 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s, break; case 0x18: /* SYS_DMA_CPC_CH0 or DMA_CSAC */ - OMAP_RO_REG((target_phys_addr_t) reg); + OMAP_RO_REG((hwaddr) reg); break; case 0x1c: /* DMA_CDEI */ @@ -1444,23 +1446,28 @@ static int omap_dma_sys_read(struct omap_dma_s *s, int offset, return 0; } -static uint32_t omap_dma_read(void *opaque, target_phys_addr_t addr) +static uint64_t omap_dma_read(void *opaque, hwaddr addr, + unsigned size) { struct omap_dma_s *s = (struct omap_dma_s *) opaque; - int reg, ch, offset = addr - s->base; + int reg, ch; uint16_t ret; - switch (offset) { + if (size != 2) { + return omap_badwidth_read16(opaque, addr); + } + + switch (addr) { case 0x300 ... 0x3fe: if (s->model <= omap_dma_3_1 || !s->omap_3_1_mapping_disabled) { - if (omap_dma_3_1_lcd_read(&s->lcd_ch, offset, &ret)) + if (omap_dma_3_1_lcd_read(&s->lcd_ch, addr, &ret)) break; return ret; } /* Fall through. */ case 0x000 ... 0x2fe: - reg = offset & 0x3f; - ch = (offset >> 6) & 0x0f; + reg = addr & 0x3f; + ch = (addr >> 6) & 0x0f; if (omap_dma_ch_reg_read(s, &s->ch[ch], reg, &ret)) break; return ret; @@ -1470,13 +1477,13 @@ static uint32_t omap_dma_read(void *opaque, target_phys_addr_t addr) break; /* Fall through. */ case 0x400: - if (omap_dma_sys_read(s, offset, &ret)) + if (omap_dma_sys_read(s, addr, &ret)) break; return ret; case 0xb00 ... 0xbfe: if (s->model == omap_dma_3_2 && s->omap_3_1_mapping_disabled) { - if (omap_dma_3_2_lcd_read(&s->lcd_ch, offset, &ret)) + if (omap_dma_3_2_lcd_read(&s->lcd_ch, addr, &ret)) break; return ret; } @@ -1487,23 +1494,27 @@ static uint32_t omap_dma_read(void *opaque, target_phys_addr_t addr) return 0; } -static void omap_dma_write(void *opaque, target_phys_addr_t addr, - uint32_t value) +static void omap_dma_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) { struct omap_dma_s *s = (struct omap_dma_s *) opaque; - int reg, ch, offset = addr - s->base; + int reg, ch; - switch (offset) { + if (size != 2) { + return omap_badwidth_write16(opaque, addr, value); + } + + switch (addr) { case 0x300 ... 0x3fe: if (s->model <= omap_dma_3_1 || !s->omap_3_1_mapping_disabled) { - if (omap_dma_3_1_lcd_write(&s->lcd_ch, offset, value)) + if (omap_dma_3_1_lcd_write(&s->lcd_ch, addr, value)) break; return; } /* Fall through. */ case 0x000 ... 0x2fe: - reg = offset & 0x3f; - ch = (offset >> 6) & 0x0f; + reg = addr & 0x3f; + ch = (addr >> 6) & 0x0f; if (omap_dma_ch_reg_write(s, &s->ch[ch], reg, value)) break; return; @@ -1513,13 +1524,13 @@ static void omap_dma_write(void *opaque, target_phys_addr_t addr, break; case 0x400: /* Fall through. */ - if (omap_dma_sys_write(s, offset, value)) + if (omap_dma_sys_write(s, addr, value)) break; return; case 0xb00 ... 0xbfe: if (s->model == omap_dma_3_2 && s->omap_3_1_mapping_disabled) { - if (omap_dma_3_2_lcd_write(&s->lcd_ch, offset, value)) + if (omap_dma_3_2_lcd_write(&s->lcd_ch, addr, value)) break; return; } @@ -1529,16 +1540,10 @@ static void omap_dma_write(void *opaque, target_phys_addr_t addr, OMAP_BAD_REG(addr); } -static CPUReadMemoryFunc *omap_dma_readfn[] = { - omap_badwidth_read16, - omap_dma_read, - omap_badwidth_read16, -}; - -static CPUWriteMemoryFunc *omap_dma_writefn[] = { - omap_badwidth_write16, - omap_dma_write, - omap_badwidth_write16, +static const MemoryRegionOps omap_dma_ops = { + .read = omap_dma_read, + .write = omap_dma_write, + .endianness = DEVICE_NATIVE_ENDIAN, }; static void omap_dma_request(void *opaque, int drq, int req) @@ -1613,13 +1618,14 @@ static void omap_dma_setcaps(struct omap_dma_s *s) } } -struct soc_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs, +struct soc_dma_s *omap_dma_init(hwaddr base, qemu_irq *irqs, + MemoryRegion *sysmem, qemu_irq lcd_irq, struct omap_mpu_state_s *mpu, omap_clk clk, enum omap_dma_model model) { - int iomemtype, num_irqs, memsize, i; + int num_irqs, memsize, i; struct omap_dma_s *s = (struct omap_dma_s *) - qemu_mallocz(sizeof(struct omap_dma_s)); + g_malloc0(sizeof(struct omap_dma_s)); if (model <= omap_dma_3_1) { num_irqs = 6; @@ -1628,7 +1634,6 @@ struct soc_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs, num_irqs = 16; memsize = 0xc00; } - s->base = base; s->model = model; s->mpu = mpu; s->clk = clk; @@ -1658,9 +1663,8 @@ struct soc_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs, omap_dma_reset(s->dma); omap_dma_clk_update(s, 0, 1); - iomemtype = cpu_register_io_memory(0, omap_dma_readfn, - omap_dma_writefn, s); - cpu_register_physical_memory(s->base, memsize, iomemtype); + memory_region_init_io(&s->iomem, &omap_dma_ops, s, "omap.dma", memsize); + memory_region_add_subregion(sysmem, base, &s->iomem); mpu->drq = s->dma->drq; @@ -1688,31 +1692,42 @@ static void omap_dma_interrupts_4_update(struct omap_dma_s *s) qemu_irq_raise(s->irq[3]); } -static uint32_t omap_dma4_read(void *opaque, target_phys_addr_t addr) +static uint64_t omap_dma4_read(void *opaque, hwaddr addr, + unsigned size) { struct omap_dma_s *s = (struct omap_dma_s *) opaque; - int irqn = 0, chnum, offset = addr - s->base; + int irqn = 0, chnum; struct omap_dma_channel_s *ch; - switch (offset) { + if (size == 1) { + return omap_badwidth_read16(opaque, addr); + } + + switch (addr) { case 0x00: /* DMA4_REVISION */ return 0x40; case 0x14: /* DMA4_IRQSTATUS_L3 */ irqn ++; + /* fall through */ case 0x10: /* DMA4_IRQSTATUS_L2 */ irqn ++; + /* fall through */ case 0x0c: /* DMA4_IRQSTATUS_L1 */ irqn ++; + /* fall through */ case 0x08: /* DMA4_IRQSTATUS_L0 */ return s->irqstat[irqn]; case 0x24: /* DMA4_IRQENABLE_L3 */ irqn ++; + /* fall through */ case 0x20: /* DMA4_IRQENABLE_L2 */ irqn ++; + /* fall through */ case 0x1c: /* DMA4_IRQENABLE_L1 */ irqn ++; + /* fall through */ case 0x18: /* DMA4_IRQENABLE_L0 */ return s->irqen[irqn]; @@ -1735,10 +1750,10 @@ static uint32_t omap_dma4_read(void *opaque, target_phys_addr_t addr) return s->gcr; case 0x80 ... 0xfff: - offset -= 0x80; - chnum = offset / 0x60; + addr -= 0x80; + chnum = addr / 0x60; ch = s->ch + chnum; - offset -= chnum * 0x60; + addr -= chnum * 0x60; break; default: @@ -1747,7 +1762,7 @@ static uint32_t omap_dma4_read(void *opaque, target_phys_addr_t addr) } /* Per-channel registers */ - switch (offset) { + switch (addr) { case 0x00: /* DMA4_CCR */ return (ch->buf_disable << 25) | (ch->src_sync << 24) | @@ -1833,20 +1848,27 @@ static uint32_t omap_dma4_read(void *opaque, target_phys_addr_t addr) } } -static void omap_dma4_write(void *opaque, target_phys_addr_t addr, - uint32_t value) +static void omap_dma4_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) { struct omap_dma_s *s = (struct omap_dma_s *) opaque; - int chnum, irqn = 0, offset = addr - s->base; + int chnum, irqn = 0; struct omap_dma_channel_s *ch; - switch (offset) { + if (size == 1) { + return omap_badwidth_write16(opaque, addr, value); + } + + switch (addr) { case 0x14: /* DMA4_IRQSTATUS_L3 */ irqn ++; + /* fall through */ case 0x10: /* DMA4_IRQSTATUS_L2 */ irqn ++; + /* fall through */ case 0x0c: /* DMA4_IRQSTATUS_L1 */ irqn ++; + /* fall through */ case 0x08: /* DMA4_IRQSTATUS_L0 */ s->irqstat[irqn] &= ~value; if (!s->irqstat[irqn]) @@ -1855,10 +1877,13 @@ static void omap_dma4_write(void *opaque, target_phys_addr_t addr, case 0x24: /* DMA4_IRQENABLE_L3 */ irqn ++; + /* fall through */ case 0x20: /* DMA4_IRQENABLE_L2 */ irqn ++; + /* fall through */ case 0x1c: /* DMA4_IRQENABLE_L1 */ irqn ++; + /* fall through */ case 0x18: /* DMA4_IRQENABLE_L0 */ s->irqen[irqn] = value; return; @@ -1878,10 +1903,10 @@ static void omap_dma4_write(void *opaque, target_phys_addr_t addr, return; case 0x80 ... 0xfff: - offset -= 0x80; - chnum = offset / 0x60; + addr -= 0x80; + chnum = addr / 0x60; ch = s->ch + chnum; - offset -= chnum * 0x60; + addr -= chnum * 0x60; break; case 0x00: /* DMA4_REVISION */ @@ -1899,7 +1924,7 @@ static void omap_dma4_write(void *opaque, target_phys_addr_t addr, } /* Per-channel registers */ - switch (offset) { + switch (addr) { case 0x00: /* DMA4_CCR */ ch->buf_disable = (value >> 25) & 1; ch->src_sync = (value >> 24) & 1; /* XXX For CamDMA must be 1 */ @@ -1975,12 +2000,12 @@ static void omap_dma4_write(void *opaque, target_phys_addr_t addr, break; case 0x1c: /* DMA4_CSSA */ - ch->addr[0] = (target_phys_addr_t) (uint32_t) value; + ch->addr[0] = (hwaddr) (uint32_t) value; ch->set_update = 1; break; case 0x20: /* DMA4_CDSA */ - ch->addr[1] = (target_phys_addr_t) (uint32_t) value; + ch->addr[1] = (hwaddr) (uint32_t) value; ch->set_update = 1; break; @@ -2021,27 +2046,21 @@ static void omap_dma4_write(void *opaque, target_phys_addr_t addr, } } -static CPUReadMemoryFunc *omap_dma4_readfn[] = { - omap_badwidth_read16, - omap_dma4_read, - omap_dma4_read, +static const MemoryRegionOps omap_dma4_ops = { + .read = omap_dma4_read, + .write = omap_dma4_write, + .endianness = DEVICE_NATIVE_ENDIAN, }; -static CPUWriteMemoryFunc *omap_dma4_writefn[] = { - omap_badwidth_write16, - omap_dma4_write, - omap_dma4_write, -}; - -struct soc_dma_s *omap_dma4_init(target_phys_addr_t base, qemu_irq *irqs, +struct soc_dma_s *omap_dma4_init(hwaddr base, qemu_irq *irqs, + MemoryRegion *sysmem, struct omap_mpu_state_s *mpu, int fifo, int chans, omap_clk iclk, omap_clk fclk) { - int iomemtype, i; + int i; struct omap_dma_s *s = (struct omap_dma_s *) - qemu_mallocz(sizeof(struct omap_dma_s)); + g_malloc0(sizeof(struct omap_dma_s)); - s->base = base; s->model = omap_dma_4; s->chans = chans; s->mpu = mpu; @@ -2066,9 +2085,8 @@ struct soc_dma_s *omap_dma4_init(target_phys_addr_t base, qemu_irq *irqs, omap_dma_reset(s->dma); omap_dma_clk_update(s, 0, !!s->dma->freq); - iomemtype = cpu_register_io_memory(0, omap_dma4_readfn, - omap_dma4_writefn, s); - cpu_register_physical_memory(s->base, 0x1000, iomemtype); + memory_region_init_io(&s->iomem, &omap_dma4_ops, s, "omap.dma4", 0x1000); + memory_region_add_subregion(sysmem, base, &s->iomem); mpu->drq = s->dma->drq;