blob: 61eef113a940c306bf319220c117f1830e24a1ac [file] [log] [blame]
/*
* Copyright (C) 2012-2014 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*
* A copy of the licence is included with the program, and can also be obtained from Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __MALI_DMA_H__
#define __MALI_DMA_H__
#include "mali_osk.h"
#include "mali_osk_mali.h"
#include "mali_hw_core.h"
#define MALI_DMA_CMD_BUF_SIZE 1024
typedef struct mali_dma_cmd_buf {
u32 *virt_addr; /**< CPU address of command buffer */
u32 phys_addr; /**< Physical address of command buffer */
u32 size; /**< Number of prepared words in command buffer */
} mali_dma_cmd_buf;
/** @brief Create a new DMA unit
*
* This is called from entry point of the driver in order to create and
* intialize the DMA resource
*
* @param resource it will be a pointer to a DMA resource
* @return DMA object on success, NULL on failure
*/
struct mali_dma_core *mali_dma_create(_mali_osk_resource_t *resource);
/** @brief Delete DMA unit
*
* This is called on entry point of driver if the driver initialization fails
* after initialization of the DMA unit. It is also called on the exit of the
* driver to delete the DMA resource
*
* @param dma Pointer to DMA unit object
*/
void mali_dma_delete(struct mali_dma_core *dma);
/** @brief Retrieves the MALI DMA core object (if there is)
*
* @return The Mali DMA object otherwise NULL
*/
struct mali_dma_core *mali_dma_get_global_dma_core(void);
/**
* @brief Run a command buffer on the DMA unit
*
* @param dma Pointer to the DMA unit to use
* @param buf Pointer to the command buffer to use
* @return _MALI_OSK_ERR_OK if the buffer was started successfully,
* _MALI_OSK_ERR_BUSY if the DMA unit is busy.
*/
_mali_osk_errcode_t mali_dma_start(struct mali_dma_core *dma, mali_dma_cmd_buf *buf);
/**
* @brief Create a DMA command
*
* @param core Mali core
* @param reg offset to register of core
* @param n number of registers to write
*/
MALI_STATIC_INLINE u32 mali_dma_command_write(struct mali_hw_core *core, u32 reg, u32 n)
{
u32 core_offset = core->phys_offset;
MALI_DEBUG_ASSERT(reg < 0x2000);
MALI_DEBUG_ASSERT(n < 0x800);
MALI_DEBUG_ASSERT(core_offset < 0x30000);
MALI_DEBUG_ASSERT(0 == ((core_offset + reg) & ~0x7FFFF));
return (n << 20) | (core_offset + reg);
}
/**
* @brief Add a array write to DMA command buffer
*
* @param buf DMA command buffer to fill in
* @param core Core to do DMA to
* @param reg Register on core to start writing to
* @param data Pointer to data to write
* @param count Number of 4 byte words to write
*/
MALI_STATIC_INLINE void mali_dma_write_array(mali_dma_cmd_buf *buf, struct mali_hw_core *core,
u32 reg, u32 *data, u32 count)
{
MALI_DEBUG_ASSERT((buf->size + 1 + count) < MALI_DMA_CMD_BUF_SIZE / 4);
buf->virt_addr[buf->size++] = mali_dma_command_write(core, reg, count);
_mali_osk_memcpy(buf->virt_addr + buf->size, data, count * sizeof(*buf->virt_addr));
buf->size += count;
}
/**
* @brief Add a conditional array write to DMA command buffer
*
* @param buf DMA command buffer to fill in
* @param core Core to do DMA to
* @param reg Register on core to start writing to
* @param data Pointer to data to write
* @param count Number of 4 byte words to write
* @param ref Pointer to referance data that can be skipped if equal
*/
MALI_STATIC_INLINE void mali_dma_write_array_conditional(mali_dma_cmd_buf *buf, struct mali_hw_core *core,
u32 reg, u32 *data, u32 count, const u32 *ref)
{
/* Do conditional array writes are not yet implemented, fallback to a
* normal array write. */
mali_dma_write_array(buf, core, reg, data, count);
}
/**
* @brief Add a conditional register write to the DMA command buffer
*
* If the data matches the reference the command will be skipped.
*
* @param buf DMA command buffer to fill in
* @param core Core to do DMA to
* @param reg Register on core to start writing to
* @param data Pointer to data to write
* @param ref Pointer to referance data that can be skipped if equal
*/
MALI_STATIC_INLINE void mali_dma_write_conditional(mali_dma_cmd_buf *buf, struct mali_hw_core *core,
u32 reg, u32 data, const u32 ref)
{
/* Skip write if reference value is equal to data. */
if (data == ref) return;
buf->virt_addr[buf->size++] = mali_dma_command_write(core, reg, 1);
buf->virt_addr[buf->size++] = data;
MALI_DEBUG_ASSERT(buf->size < MALI_DMA_CMD_BUF_SIZE / 4);
}
/**
* @brief Add a register write to the DMA command buffer
*
* @param buf DMA command buffer to fill in
* @param core Core to do DMA to
* @param reg Register on core to start writing to
* @param data Pointer to data to write
*/
MALI_STATIC_INLINE void mali_dma_write(mali_dma_cmd_buf *buf, struct mali_hw_core *core,
u32 reg, u32 data)
{
buf->virt_addr[buf->size++] = mali_dma_command_write(core, reg, 1);
buf->virt_addr[buf->size++] = data;
MALI_DEBUG_ASSERT(buf->size < MALI_DMA_CMD_BUF_SIZE / 4);
}
/**
* @brief Prepare DMA command buffer for use
*
* This function allocates the DMA buffer itself.
*
* @param buf The mali_dma_cmd_buf to prepare
* @return _MALI_OSK_ERR_OK if the \a buf is ready to use
*/
_mali_osk_errcode_t mali_dma_get_cmd_buf(mali_dma_cmd_buf *buf);
/**
* @brief Check if a DMA command buffer is ready for use
*
* @param buf The mali_dma_cmd_buf to check
* @return MALI_TRUE if buffer is usable, MALI_FALSE otherwise
*/
MALI_STATIC_INLINE mali_bool mali_dma_cmd_buf_is_valid(mali_dma_cmd_buf *buf)
{
return NULL != buf->virt_addr;
}
/**
* @brief Return a DMA command buffer
*
* @param buf Pointer to DMA command buffer to return
*/
void mali_dma_put_cmd_buf(mali_dma_cmd_buf *buf);
#endif /* __MALI_DMA_H__ */