/*
 * On-chip DMA controller framework.
 *
 * Copyright (C) 2008 Nokia Corporation
 * Written by Andrzej Zaborowski <andrew@openedhand.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 or
 * (at your option) version 3 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * 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.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

struct soc_dma_s;
struct soc_dma_ch_s;
typedef void (*soc_dma_io_t)(void *opaque, uint8_t *buf, int len);
typedef void (*soc_dma_transfer_t)(struct soc_dma_ch_s *ch);

enum soc_dma_port_type {
    soc_dma_port_mem,
    soc_dma_port_fifo,
    soc_dma_port_other,
};

enum soc_dma_access_type {
    soc_dma_access_const,
    soc_dma_access_linear,
    soc_dma_access_other,
};

struct soc_dma_ch_s {
    /* Private */
    struct soc_dma_s *dma;
    int num;
    QEMUTimer *timer;

    /* Set by soc_dma.c */
    int enable;
    int update;

    /* This should be set by dma->setup_fn().  */
    int bytes;
    /* Initialised by the DMA module, call soc_dma_ch_update after writing.  */
    enum soc_dma_access_type type[2];
    target_phys_addr_t vaddr[2];	/* Updated by .transfer_fn().  */
    /* Private */
    void *paddr[2];
    soc_dma_io_t io_fn[2];
    void *io_opaque[2];

    int running;
    soc_dma_transfer_t transfer_fn;

    /* Set and used by the DMA module.  */
    void *opaque;
};

struct soc_dma_s {
    /* Following fields are set by the SoC DMA module and can be used
     * by anybody.  */
    uint64_t drqbmp;	/* Is zeroed by soc_dma_reset() */
    qemu_irq *drq;
    void *opaque;
    int64_t freq;
    soc_dma_transfer_t transfer_fn;
    soc_dma_transfer_t setup_fn;
    /* Set by soc_dma_init() for use by the DMA module.  */
    struct soc_dma_ch_s *ch;
};

/* Call to activate or stop a DMA channel.  */
void soc_dma_set_request(struct soc_dma_ch_s *ch, int level);
/* Call after every write to one of the following fields and before
 * calling soc_dma_set_request(ch, 1):
 *   ch->type[0...1],
 *   ch->vaddr[0...1],
 *   ch->paddr[0...1],
 * or after a soc_dma_port_add_fifo() or soc_dma_port_add_mem().  */
void soc_dma_ch_update(struct soc_dma_ch_s *ch);

/* The SoC should call this when the DMA module is being reset.  */
void soc_dma_reset(struct soc_dma_s *s);
struct soc_dma_s *soc_dma_init(int n);

void soc_dma_port_add_fifo(struct soc_dma_s *dma, target_phys_addr_t virt_base,
                soc_dma_io_t fn, void *opaque, int out);
void soc_dma_port_add_mem(struct soc_dma_s *dma, uint8_t *phys_base,
                target_phys_addr_t virt_base, size_t size);

static inline void soc_dma_port_add_fifo_in(struct soc_dma_s *dma,
                target_phys_addr_t virt_base, soc_dma_io_t fn, void *opaque)
{
    return soc_dma_port_add_fifo(dma, virt_base, fn, opaque, 0);
}

static inline void soc_dma_port_add_fifo_out(struct soc_dma_s *dma,
                target_phys_addr_t virt_base, soc_dma_io_t fn, void *opaque)
{
    return soc_dma_port_add_fifo(dma, virt_base, fn, opaque, 1);
}

static inline void soc_dma_port_add_mem_ram(struct soc_dma_s *dma,
                ram_addr_t offset, target_phys_addr_t virt_base, size_t size)
{
    return soc_dma_port_add_mem(dma, qemu_get_ram_ptr(offset), virt_base, size);
}
