#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: bus_space.c,v 1.14 2023/12/20 15:29:05 thorpej Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <uvm/uvm_extern.h>
#include <machine/bus.h>
void
mipsco_bus_space_init(bus_space_tag_t bst, const char *name, paddr_t paddr, vaddr_t vaddr, bus_addr_t start, bus_size_t size)
{
bst->bs_name = name;
bst->bs_spare = NULL;
bst->bs_start = start;
bst->bs_size = size;
bst->bs_pbase = paddr;
bst->bs_vbase = vaddr;
bst->bs_compose_handle = mipsco_bus_space_compose_handle;
bst->bs_dispose_handle = mipsco_bus_space_dispose_handle;
bst->bs_paddr = mipsco_bus_space_paddr;
bst->bs_map = mipsco_bus_space_map;
bst->bs_unmap = mipsco_bus_space_unmap;
bst->bs_subregion = mipsco_bus_space_subregion;
bst->bs_mmap = mipsco_bus_space_mmap;
bst->bs_alloc = mipsco_bus_space_alloc;
bst->bs_free = mipsco_bus_space_free;
bst->bs_aux = NULL;
bst->bs_bswap = 0;
mipsco_bus_space_set_aligned_stride(bst, 0);
}
void
mipsco_bus_space_set_aligned_stride(bus_space_tag_t bst, unsigned int shift)
{
bst->bs_stride = shift;
if (shift == 2) {
bst->bs_offset_1 = 3;
bst->bs_offset_2 = 2;
} else {
bst->bs_offset_1 = 0;
bst->bs_offset_2 = 0;
}
bst->bs_offset_4 = 0;
bst->bs_offset_8 = 0;
}
int
mipsco_bus_space_compose_handle(bus_space_tag_t bst, bus_addr_t addr, bus_size_t size, int flags, bus_space_handle_t *bshp)
{
bus_space_handle_t bsh = bst->bs_vbase +
((addr - bst->bs_start) << bst->bs_stride);
if ((flags & BUS_SPACE_MAP_CACHEABLE) == 0) {
*bshp = bsh;
return (0);
}
if (bsh < MIPS_KSEG1_START)
panic("mipsco_bus_space_compose_handle: bad address 0x%x", bsh);
if (bsh < MIPS_KSEG2_START) {
*bshp = MIPS_PHYS_TO_KSEG0(MIPS_KSEG1_TO_PHYS(bsh));
return (0);
}
#ifdef DIAGNOSTIC
printf("mipsco_bus_space_compose_handle: ignore cacheable 0x%x\n", bsh);
#endif
*bshp = bsh;
return (0);
}
int
mipsco_bus_space_dispose_handle(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t size)
{
return (0);
}
int
mipsco_bus_space_paddr(bus_space_tag_t bst, bus_space_handle_t bsh, paddr_t *pap)
{
if (bsh < MIPS_KSEG0_START)
panic("mipsco_bus_space_paddr(%p): bad address", (void *)bsh);
else if (bsh < MIPS_KSEG1_START)
*pap = MIPS_KSEG0_TO_PHYS(bsh);
else if (bsh < MIPS_KSEG2_START)
*pap = MIPS_KSEG1_TO_PHYS(bsh);
else {
*pap = bst->bs_pbase + (bsh - bst->bs_vbase);
}
return (0);
}
int
mipsco_bus_space_map(bus_space_tag_t bst, bus_addr_t addr, bus_size_t size, int flags, bus_space_handle_t *bshp)
{
if (addr < bst->bs_start || addr + size > bst->bs_start + bst->bs_size)
return (EINVAL);
return (bus_space_compose_handle(bst, addr, size, flags, bshp));
}
void
mipsco_bus_space_unmap(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t size)
{
bus_space_dispose_handle(bst, bsh, size);
}
int
mipsco_bus_space_subregion(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp)
{
*nbshp = bsh + (offset << bst->bs_stride);
return (0);
}
paddr_t
mipsco_bus_space_mmap(bus_space_tag_t bst, bus_addr_t addr, off_t off, int prot, int flags)
{
if (addr < bst->bs_start ||
(addr + off) >= (bst->bs_start + bst->bs_size))
return (-1);
return (mips_btop(bst->bs_pbase + (addr - bst->bs_start) + off));
}
int
mipsco_bus_space_alloc(bus_space_tag_t bst, bus_addr_t start, bus_addr_t end, bus_size_t size, bus_size_t align, bus_size_t boundary, int flags, bus_addr_t *addrp, bus_space_handle_t *bshp)
{
panic("bus_space_alloc() not implemented");
}