Linux Audio

Check our new training course

Embedded Linux Audio

Check our new training course
with Creative Commons CC-BY-SA
lecture materials

Bootlin logo

Elixir Cross Referencer

Loading...
/*
 * Copyright (c) 2018, Pinecone Inc. and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <metal/cache.h>
#include <metal/io.h>
#include <nuttx/arch.h>

static uint64_t metal_io_read_(struct metal_io_region *io,
			       unsigned long offset,
			       memory_order order,
			       int width)
{
	uint64_t value = 0;

	metal_io_block_read(io, offset, &value, width);
	return value;
}

static void metal_io_write_(struct metal_io_region *io,
			    unsigned long offset,
			    uint64_t value,
			    memory_order order,
			    int width)
{
	metal_io_block_write(io, offset, &value, width);
}

static int metal_io_block_read_(struct metal_io_region *io,
				unsigned long offset,
				void *restrict dst,
				memory_order order,
				int len)
{
	void *va = metal_io_virt(io, offset);

	metal_cache_invalidate(va, len);
	memcpy(dst, va, len);

	return len;
}

static int metal_io_block_write_(struct metal_io_region *io,
				 unsigned long offset,
				 const void *restrict src,
				 memory_order order,
				 int len)
{
	void *va = metal_io_virt(io, offset);

	memcpy(va, src, len);
	metal_cache_flush(va, len);

	return len;
}

static void metal_io_block_set_(struct metal_io_region *io,
				unsigned long offset,
				unsigned char value,
				memory_order order,
				int len)
{
	void *va = metal_io_virt(io, offset);

	memset(va, value, len);
	metal_cache_flush(va, len);
}

static void metal_io_close_(struct metal_io_region *io)
{
}

static metal_phys_addr_t metal_io_offset_to_phys_(struct metal_io_region *io,
						  unsigned long offset)
{
	return up_addrenv_va_to_pa((char *)io->virt + offset);
}

static unsigned long metal_io_phys_to_offset_(struct metal_io_region *io,
					      metal_phys_addr_t phys)
{
	return (char *)up_addrenv_pa_to_va(phys) - (char *)io->virt;
}

static metal_phys_addr_t metal_io_phys_start_ = 0;

static struct metal_io_region metal_io_region_ = {
	.virt = NULL,
	.physmap = &metal_io_phys_start_,
	.size = (size_t)-1,
	.page_shift = sizeof(metal_phys_addr_t) * CHAR_BIT,
	.page_mask = (metal_phys_addr_t)-1,
	.mem_flags = 0,
	.ops = {
		.read = metal_io_read_,
		.write = metal_io_write_,
		.block_read = metal_io_block_read_,
		.block_write = metal_io_block_write_,
		.block_set = metal_io_block_set_,
		.close = metal_io_close_,
		.offset_to_phys = metal_io_offset_to_phys_,
		.phys_to_offset = metal_io_phys_to_offset_,
	},
};

struct metal_io_ops *metal_io_get_ops(void)
{
	return &metal_io_region_.ops;
}

struct metal_io_region *metal_io_get_region(void)
{
	return &metal_io_region_;
}