Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions components/drivers/include/drivers/pci_endpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ struct rt_pci_ep_msix_tbl
};

struct rt_pci_ep_ops;
struct rt_pci_ep_mem;

struct rt_pci_ep
{
Expand All @@ -84,6 +85,9 @@ struct rt_pci_ep
const struct rt_device *rc_dev;
const struct rt_pci_ep_ops *ops;

rt_size_t mems_nr;
struct rt_pci_ep_mem *mems;

rt_uint8_t max_functions;
RT_BITMAP_DECLARE(functions_map, 8);
rt_list_t epf_nodes;
Expand All @@ -92,6 +96,16 @@ struct rt_pci_ep
void *priv;
};

struct rt_pci_ep_mem
{
rt_ubase_t cpu_addr;
rt_size_t size;
rt_size_t page_size;

rt_bitmap_t *map;
rt_size_t bits;
};

struct rt_pci_epf
{
rt_list_t list;
Expand Down Expand Up @@ -170,6 +184,16 @@ rt_err_t rt_pci_ep_stop(struct rt_pci_ep *ep);
rt_err_t rt_pci_ep_register(struct rt_pci_ep *ep);
rt_err_t rt_pci_ep_unregister(struct rt_pci_ep *ep);

rt_err_t rt_pci_ep_mem_array_init(struct rt_pci_ep *ep,
struct rt_pci_ep_mem *mems, rt_size_t mems_nr);
rt_err_t rt_pci_ep_mem_init(struct rt_pci_ep *ep,
rt_ubase_t cpu_addr, rt_size_t size, rt_size_t page_size);

void *rt_pci_ep_mem_alloc(struct rt_pci_ep *ep,
rt_ubase_t *out_cpu_addr, rt_size_t size);
void rt_pci_ep_mem_free(struct rt_pci_ep *ep,
void *vaddr, rt_ubase_t cpu_addr, rt_size_t size);

rt_err_t rt_pci_ep_add_epf(struct rt_pci_ep *ep, struct rt_pci_epf *epf);
rt_err_t rt_pci_ep_remove_epf(struct rt_pci_ep *ep, struct rt_pci_epf *epf);

Expand Down
2 changes: 1 addition & 1 deletion components/drivers/pci/endpoint/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ if not GetDepend(['RT_PCI_ENDPOINT']):
cwd = GetCurrentDir()
CPPPATH = [cwd + '/../../include']

src = ['endpoint.c']
src = ['endpoint.c', 'mem.c']

group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)

Expand Down
205 changes: 205 additions & 0 deletions components/drivers/pci/endpoint/mem.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-08-25 GuEe-GUI first version
*/

#include <drivers/pci_endpoint.h>

#define DBG_TAG "pci.ep.mem"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>

rt_err_t rt_pci_ep_mem_array_init(struct rt_pci_ep *ep,
struct rt_pci_ep_mem *mems, rt_size_t mems_nr)
{
rt_size_t idx;
rt_err_t err = RT_EOK;

if (!ep || !mems)
{
return -RT_EINVAL;
}

rt_mutex_take(&ep->lock, RT_WAITING_FOREVER);

ep->mems_nr = mems_nr;
ep->mems = rt_calloc(mems_nr, sizeof(*ep->mems));

if (!ep->mems)
{
return -RT_ENOMEM;
}

for (idx = 0; idx < mems_nr; ++idx)
{
struct rt_pci_ep_mem *mem = &ep->mems[idx];

mem->cpu_addr = mems->cpu_addr;
mem->size = mems->size;
mem->page_size = mems->page_size;
mem->bits = mems->size / mems->page_size;
mem->map = rt_calloc(RT_BITMAP_LEN(mem->bits), sizeof(*mem->map));

if (!mem->map)
{
err = -RT_ENOMEM;
goto _out_lock;
}
}

_out_lock:
if (err)
{
while (idx --> 0)
{
rt_free(ep->mems[idx].map);
}
rt_free(ep->mems);

ep->mems_nr = 0;
ep->mems = RT_NULL;
}

rt_mutex_release(&ep->lock);

return err;
}

rt_err_t rt_pci_ep_mem_init(struct rt_pci_ep *ep,
rt_ubase_t cpu_addr, rt_size_t size, rt_size_t page_size)
{
struct rt_pci_ep_mem mem;

if (!ep)
{
return -RT_EINVAL;
}

mem.cpu_addr = cpu_addr;
mem.size = size;
mem.page_size = page_size;

return rt_pci_ep_mem_array_init(ep, &mem, 1);
}

static rt_ubase_t bitmap_region_alloc(struct rt_pci_ep_mem *mem, rt_size_t size)
{
rt_size_t bit, next_bit, end_bit, max_bits;

size /= mem->page_size;
max_bits = mem->bits - size;

rt_bitmap_for_each_clear_bit(mem->map, bit, max_bits)
{
end_bit = bit + size;

for (next_bit = bit + 1; next_bit < end_bit; ++next_bit)
{
if (rt_bitmap_test_bit(mem->map, next_bit))
{
bit = next_bit;
goto _next;
}
}

if (next_bit == end_bit)
{
while (next_bit --> bit)
{
rt_bitmap_set_bit(mem->map, next_bit);
}

return mem->cpu_addr + bit * mem->page_size;
}
_next:
}

return ~0ULL;
}

static void bitmap_region_free(struct rt_pci_ep_mem *mem,
rt_ubase_t cpu_addr, rt_size_t size)
{
rt_size_t bit = (cpu_addr - mem->cpu_addr) / mem->page_size, end_bit;

size /= mem->page_size;
end_bit = bit + size;

for (; bit < end_bit; ++bit)
{
rt_bitmap_clear_bit(mem->map, bit);
}
}

void *rt_pci_ep_mem_alloc(struct rt_pci_ep *ep,
rt_ubase_t *out_cpu_addr, rt_size_t size)
{
void *vaddr = RT_NULL;

if (!ep || !out_cpu_addr)
{
return vaddr;
}

rt_mutex_take(&ep->lock, RT_WAITING_FOREVER);

for (rt_size_t idx = 0; idx < ep->mems_nr; ++idx)
{
rt_ubase_t cpu_addr;
struct rt_pci_ep_mem *mem = &ep->mems[idx];

cpu_addr = bitmap_region_alloc(mem, size);

if (cpu_addr != ~0ULL)
{
vaddr = rt_ioremap((void *)cpu_addr, size);

if (!vaddr)
{
bitmap_region_free(mem, cpu_addr, size);

/* Try next memory */
continue;
}

*out_cpu_addr = cpu_addr;
break;
}
}

rt_mutex_release(&ep->lock);

return vaddr;
}

void rt_pci_ep_mem_free(struct rt_pci_ep *ep,
void *vaddr, rt_ubase_t cpu_addr, rt_size_t size)
{
if (!ep || !vaddr || !size)
{
return;
}

rt_mutex_take(&ep->lock, RT_WAITING_FOREVER);

for (rt_size_t idx = 0; idx < ep->mems_nr; ++idx)
{
struct rt_pci_ep_mem *mem = &ep->mems[idx];

if (mem->cpu_addr > cpu_addr &&
mem->cpu_addr + mem->size >= cpu_addr + size)
{
rt_iounmap(mem);
bitmap_region_free(mem, cpu_addr, size);

break;
}
}

rt_mutex_release(&ep->lock);
}
2 changes: 2 additions & 0 deletions components/drivers/pci/host/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ config RT_PCI_HOST_GENERIC
depends on RT_PCI_ECAM
select RT_PCI_HOST_COMMON
default y

rsource "dw/Kconfig"
13 changes: 13 additions & 0 deletions components/drivers/pci/host/dw/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
config RT_PCI_DW
bool "DesignWare-based PCIe"
depends on RT_MFD_SYSCON
depends on RT_USING_DMA
default n

config RT_PCI_DW_HOST
bool
depends on RT_PCI_DW

config RT_PCI_DW_EP
bool
depends on RT_PCI_DW
21 changes: 21 additions & 0 deletions components/drivers/pci/host/dw/SConscript
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from building import *

group = []

if not GetDepend(['RT_PCI_DW']):
Return('group')

cwd = GetCurrentDir()
CPPPATH = [cwd + '/../../../include']

src = ['pcie-dw.c', 'pcie-dw_platfrom.c']

if GetDepend(['RT_PCI_DW_HOST']):
src += ['pcie-dw_host.c']

if GetDepend(['RT_PCI_DW_EP']):
src += ['pcie-dw_ep.c']

group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)

Return('group')
Loading