* 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 <http://www.gnu.org/licenses/>.
*/
#include "qemu-common.h"
-#include "qemu-timer.h"
+#include "qemu/timer.h"
#include "omap.h"
#include "irq.h"
#include "soc_dma.h"
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;
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;
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);
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. */
+#ifndef MULTI_REQ
+ }
+#else
}
+#endif
omap_dma_interrupts_update(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 */
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 */
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;
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;
}
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;
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;
}
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)
}
}
-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;
num_irqs = 16;
memsize = 0xc00;
}
- s->base = base;
s->model = model;
s->mpu = mpu;
s->clk = clk;
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;
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;
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:
}
/* Per-channel registers */
- switch (offset) {
+ switch (addr) {
case 0x00: /* DMA4_CCR */
return (ch->buf_disable << 25) |
(ch->src_sync << 24) |
}
}
-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 ++;
case 0x10: /* DMA4_IRQSTATUS_L2 */
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 */
}
/* 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 */
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;
}
}
-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;
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;