Skip to content

Commit 3e313c3

Browse files
Alex Elderdavem330
authored andcommitted
net: ipa: define IMEM memory region for IPA
Define a region of IMEM memory available for use by IPA in the platform configuration data. Initialize it from ipa_mem_init(). The memory must be mapped for access through an SMMU. Signed-off-by: Alex Elder <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 3128aae commit 3e313c3

File tree

5 files changed

+98
-1
lines changed

5 files changed

+98
-1
lines changed

drivers/net/ipa/ipa.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ struct ipa_interrupt;
4747
* @mem_offset: Offset from @mem_virt used for access to IPA memory
4848
* @mem_size: Total size (bytes) of memory at @mem_virt
4949
* @mem: Array of IPA-local memory region descriptors
50+
* @imem_iova: I/O virtual address of IPA region in IMEM
51+
* @imem_size; Size of IMEM region
5052
* @zero_addr: DMA address of preallocated zero-filled memory
5153
* @zero_virt: Virtual address of preallocated zero-filled memory
5254
* @zero_size: Size (bytes) of preallocated zero-filled memory
@@ -88,6 +90,9 @@ struct ipa {
8890
u32 mem_size;
8991
const struct ipa_mem *mem;
9092

93+
unsigned long imem_iova;
94+
size_t imem_size;
95+
9196
dma_addr_t zero_addr;
9297
void *zero_virt;
9398
size_t zero_size;

drivers/net/ipa/ipa_data-sc7180.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,8 @@ static const struct ipa_mem ipa_mem_local_data[] = {
299299
static struct ipa_mem_data ipa_mem_data = {
300300
.local_count = ARRAY_SIZE(ipa_mem_local_data),
301301
.local = ipa_mem_local_data,
302+
.imem_addr = 0x146a8000,
303+
.imem_size = 0x00002000,
302304
};
303305

304306
/* Configuration data for the SC7180 SoC. */

drivers/net/ipa/ipa_data-sdm845.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,8 @@ static const struct ipa_mem ipa_mem_local_data[] = {
321321
static struct ipa_mem_data ipa_mem_data = {
322322
.local_count = ARRAY_SIZE(ipa_mem_local_data),
323323
.local = ipa_mem_local_data,
324+
.imem_addr = 0x146bd000,
325+
.imem_size = 0x00002000,
324326
};
325327

326328
/* Configuration data for the SDM845 SoC. */

drivers/net/ipa/ipa_data.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,13 +245,17 @@ struct ipa_resource_data {
245245
};
246246

247247
/**
248-
* struct ipa_mem - IPA-local memory region description
248+
* struct ipa_mem - description of IPA memory regions
249249
* @local_count: number of regions defined in the local[] array
250250
* @local: array of IPA-local memory region descriptors
251+
* @imem_addr: physical address of IPA region within IMEM
252+
* @imem_size: size in bytes of IPA IMEM region
251253
*/
252254
struct ipa_mem_data {
253255
u32 local_count;
254256
const struct ipa_mem *local;
257+
u32 imem_addr;
258+
u32 imem_size;
255259
};
256260

257261
/**

drivers/net/ipa/ipa_mem.c

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <linux/bitfield.h>
99
#include <linux/bug.h>
1010
#include <linux/dma-mapping.h>
11+
#include <linux/iommu.h>
1112
#include <linux/io.h>
1213

1314
#include "ipa.h"
@@ -266,6 +267,79 @@ int ipa_mem_zero_modem(struct ipa *ipa)
266267
return 0;
267268
}
268269

270+
/**
271+
* ipa_imem_init() - Initialize IMEM memory used by the IPA
272+
* @ipa: IPA pointer
273+
* @addr: Physical address of the IPA region in IMEM
274+
* @size: Size (bytes) of the IPA region in IMEM
275+
*
276+
* IMEM is a block of shared memory separate from system DRAM, and
277+
* a portion of this memory is available for the IPA to use. The
278+
* modem accesses this memory directly, but the IPA accesses it
279+
* via the IOMMU, using the AP's credentials.
280+
*
281+
* If this region exists (size > 0) we map it for read/write access
282+
* through the IOMMU using the IPA device.
283+
*
284+
* Note: @addr and @size are not guaranteed to be page-aligned.
285+
*/
286+
static int ipa_imem_init(struct ipa *ipa, unsigned long addr, size_t size)
287+
{
288+
struct device *dev = &ipa->pdev->dev;
289+
struct iommu_domain *domain;
290+
unsigned long iova;
291+
phys_addr_t phys;
292+
int ret;
293+
294+
if (!size)
295+
return 0; /* IMEM memory not used */
296+
297+
domain = iommu_get_domain_for_dev(dev);
298+
if (!domain) {
299+
dev_err(dev, "no IOMMU domain found for IMEM\n");
300+
return -EINVAL;
301+
}
302+
303+
/* Align the address down and the size up to page boundaries */
304+
phys = addr & PAGE_MASK;
305+
size = PAGE_ALIGN(size + addr - phys);
306+
iova = phys; /* We just want a direct mapping */
307+
308+
ret = iommu_map(domain, iova, phys, size, IOMMU_READ | IOMMU_WRITE);
309+
if (ret)
310+
return ret;
311+
312+
ipa->imem_iova = iova;
313+
ipa->imem_size = size;
314+
315+
return 0;
316+
}
317+
318+
static void ipa_imem_exit(struct ipa *ipa)
319+
{
320+
struct iommu_domain *domain;
321+
struct device *dev;
322+
323+
if (!ipa->imem_size)
324+
return;
325+
326+
dev = &ipa->pdev->dev;
327+
domain = iommu_get_domain_for_dev(dev);
328+
if (domain) {
329+
size_t size;
330+
331+
size = iommu_unmap(domain, ipa->imem_iova, ipa->imem_size);
332+
if (size != ipa->imem_size)
333+
dev_warn(dev, "unmapped %zu IMEM bytes, expected %lu\n",
334+
size, ipa->imem_size);
335+
} else {
336+
dev_err(dev, "couldn't get IPA IOMMU domain for IMEM\n");
337+
}
338+
339+
ipa->imem_size = 0;
340+
ipa->imem_iova = 0;
341+
}
342+
269343
/* Perform memory region-related initialization */
270344
int ipa_mem_init(struct ipa *ipa, const struct ipa_mem_data *mem_data)
271345
{
@@ -305,11 +379,21 @@ int ipa_mem_init(struct ipa *ipa, const struct ipa_mem_data *mem_data)
305379
/* The ipa->mem[] array is indexed by enum ipa_mem_id values */
306380
ipa->mem = mem_data->local;
307381

382+
ret = ipa_imem_init(ipa, mem_data->imem_addr, mem_data->imem_size);
383+
if (ret)
384+
goto err_unmap;
385+
308386
return 0;
387+
388+
err_unmap:
389+
memunmap(ipa->mem_virt);
390+
391+
return ret;
309392
}
310393

311394
/* Inverse of ipa_mem_init() */
312395
void ipa_mem_exit(struct ipa *ipa)
313396
{
397+
ipa_imem_exit(ipa);
314398
memunmap(ipa->mem_virt);
315399
}

0 commit comments

Comments
 (0)