1 // SPDX-License-Identifier: GPL-2.0
3 * PCI Endpoint *Controller* Address Space Management
5 * Copyright (C) 2017 Texas Instruments
6 * Author: Kishon Vijay Abraham I <kishon@ti.com>
10 #include <linux/module.h>
11 #include <linux/slab.h>
13 #include <linux/pci-epc.h>
16 * pci_epc_mem_get_order() - determine the allocation order of a memory size
17 * @mem: address space of the endpoint controller
18 * @size: the size for which to get the order
20 * Reimplement get_order() for mem->page_size since the generic get_order
21 * always gets order with a constant PAGE_SIZE.
23 static int pci_epc_mem_get_order(struct pci_epc_mem
*mem
, size_t size
)
26 unsigned int page_shift
= ilog2(mem
->page_size
);
30 #if BITS_PER_LONG == 32
39 * __pci_epc_mem_init() - initialize the pci_epc_mem structure
40 * @epc: the EPC device that invoked pci_epc_mem_init
41 * @phys_base: the physical address of the base
42 * @size: the size of the address space
43 * @page_size: size of each page
45 * Invoke to initialize the pci_epc_mem structure used by the
46 * endpoint functions to allocate mapped PCI address.
48 int __pci_epc_mem_init(struct pci_epc
*epc
, phys_addr_t phys_base
, size_t size
,
52 struct pci_epc_mem
*mem
;
53 unsigned long *bitmap
;
54 unsigned int page_shift
;
58 if (page_size
< PAGE_SIZE
)
59 page_size
= PAGE_SIZE
;
61 page_shift
= ilog2(page_size
);
62 pages
= size
>> page_shift
;
63 bitmap_size
= BITS_TO_LONGS(pages
) * sizeof(long);
65 mem
= kzalloc(sizeof(*mem
), GFP_KERNEL
);
71 bitmap
= kzalloc(bitmap_size
, GFP_KERNEL
);
78 mem
->phys_base
= phys_base
;
79 mem
->page_size
= page_size
;
93 EXPORT_SYMBOL_GPL(__pci_epc_mem_init
);
96 * pci_epc_mem_exit() - cleanup the pci_epc_mem structure
97 * @epc: the EPC device that invoked pci_epc_mem_exit
99 * Invoke to cleanup the pci_epc_mem structure allocated in
100 * pci_epc_mem_init().
102 void pci_epc_mem_exit(struct pci_epc
*epc
)
104 struct pci_epc_mem
*mem
= epc
->mem
;
110 EXPORT_SYMBOL_GPL(pci_epc_mem_exit
);
113 * pci_epc_mem_alloc_addr() - allocate memory address from EPC addr space
114 * @epc: the EPC device on which memory has to be allocated
115 * @phys_addr: populate the allocated physical address here
116 * @size: the size of the address space that has to be allocated
118 * Invoke to allocate memory address from the EPC address space. This
119 * is usually done to map the remote RC address into the local system.
121 void __iomem
*pci_epc_mem_alloc_addr(struct pci_epc
*epc
,
122 phys_addr_t
*phys_addr
, size_t size
)
125 void __iomem
*virt_addr
;
126 struct pci_epc_mem
*mem
= epc
->mem
;
127 unsigned int page_shift
= ilog2(mem
->page_size
);
130 size
= ALIGN(size
, mem
->page_size
);
131 order
= pci_epc_mem_get_order(mem
, size
);
133 pageno
= bitmap_find_free_region(mem
->bitmap
, mem
->pages
, order
);
137 *phys_addr
= mem
->phys_base
+ ((phys_addr_t
)pageno
<< page_shift
);
138 virt_addr
= ioremap(*phys_addr
, size
);
140 bitmap_release_region(mem
->bitmap
, pageno
, order
);
144 EXPORT_SYMBOL_GPL(pci_epc_mem_alloc_addr
);
147 * pci_epc_mem_free_addr() - free the allocated memory address
148 * @epc: the EPC device on which memory was allocated
149 * @phys_addr: the allocated physical address
150 * @virt_addr: virtual address of the allocated mem space
151 * @size: the size of the allocated address space
153 * Invoke to free the memory allocated using pci_epc_mem_alloc_addr.
155 void pci_epc_mem_free_addr(struct pci_epc
*epc
, phys_addr_t phys_addr
,
156 void __iomem
*virt_addr
, size_t size
)
159 struct pci_epc_mem
*mem
= epc
->mem
;
160 unsigned int page_shift
= ilog2(mem
->page_size
);
164 pageno
= (phys_addr
- mem
->phys_base
) >> page_shift
;
165 size
= ALIGN(size
, mem
->page_size
);
166 order
= pci_epc_mem_get_order(mem
, size
);
167 bitmap_release_region(mem
->bitmap
, pageno
, order
);
169 EXPORT_SYMBOL_GPL(pci_epc_mem_free_addr
);
171 MODULE_DESCRIPTION("PCI EPC Address Space Management");
172 MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
173 MODULE_LICENSE("GPL v2");