-
Notifications
You must be signed in to change notification settings - Fork 6.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
drivers: mm: Add support for TI RAT module using system_mm API
Added Region based Address Translation (RAT) module driver. Required by a few Texas Instruments SoCs to fucntion. Uses sys_mm_drv_page_phys_get() API with device_map() for address translation. Signed-off-by: L Lakshmanan <l-lakshmanan@ti.com>
- Loading branch information
1 parent
f3cafe7
commit ccca323
Showing
5 changed files
with
239 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
/* | ||
* Copyright (c) 2023 Texas Instruments Incorporated | ||
* Copyright (c) 2023 L Lakshmanan | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <zephyr/drivers/mm/rat.h> | ||
#include <zephyr/drivers/mm/system_mm.h> | ||
#include <zephyr/sys/__assert.h> | ||
|
||
struct address_trans_params translate_config; | ||
|
||
static void address_trans_set_region(struct address_trans_params addr_translate_config, | ||
uint16_t region_num, uint32_t enable) | ||
{ | ||
uint32_t rat_base_addr = addr_translate_config.rat_base_addr; | ||
uint64_t system_addr = addr_translate_config.region_config[region_num].system_addr; | ||
uint32_t local_addr = addr_translate_config.region_config[region_num].local_addr; | ||
uint32_t size = addr_translate_config.region_config[region_num].size; | ||
uint32_t system_addrL, system_addrH; | ||
|
||
if (size > address_trans_region_size_4G) { | ||
size = address_trans_region_size_4G; | ||
} | ||
system_addrL = (uint32_t)(system_addr & ~((uint32_t)(((uint64_t)1 << size) - 1))); | ||
system_addrH = (uint32_t)((system_addr >> 32) & 0xFFFF); | ||
local_addr = local_addr & ~((uint32_t)(((uint64_t)1 << size) - 1)); | ||
|
||
sys_write32(0, RAT_CTRL(rat_base_addr, region_num)); | ||
sys_write32(local_addr, RAT_BASE(rat_base_addr, region_num)); | ||
sys_write32(system_addrL, RAT_TRANS_L(rat_base_addr, region_num)); | ||
sys_write32(system_addrH, RAT_TRANS_H(rat_base_addr, region_num)); | ||
sys_write32(((enable & 0x1) << 31u) | (size & 0x3F), RAT_CTRL(rat_base_addr, region_num)); | ||
} | ||
|
||
static void address_trans_init(struct address_trans_params *params) | ||
{ | ||
uint32_t i; | ||
|
||
if (params != NULL) { | ||
translate_config = *params; | ||
} | ||
|
||
__ASSERT(translate_config.num_regions < ADDR_TRANSLATE_MAX_REGIONS, | ||
"Exceeding maximum number of regions"); | ||
|
||
for (i = 0; i < translate_config.num_regions; i++) { | ||
__ASSERT(translate_config.rat_base_addr != 0, "RAT base address cannot be 0"); | ||
__ASSERT(translate_config.region_config != NULL, | ||
"RAT region config cannot be NULL"); | ||
|
||
/* enable regions setup by user */ | ||
address_trans_set_region(translate_config, i, 1); | ||
} | ||
} | ||
|
||
void sys_mm_drv_ti_rat_init(void *region_config, uint64_t rat_base_addr, uint8_t translate_regions) | ||
{ | ||
translate_config.num_regions = translate_regions; | ||
translate_config.rat_base_addr = rat_base_addr; | ||
translate_config.region_config = (struct address_trans_region_config *)region_config; | ||
|
||
address_trans_init(&translate_config); | ||
} | ||
|
||
int sys_mm_drv_page_phys_get(void *virt, uintptr_t *phys) | ||
{ | ||
if (virt == NULL) { | ||
return -EINVAL; | ||
} | ||
uint64_t pa = ((uint64_t) (virt)); | ||
uintptr_t *va = phys; | ||
|
||
uint32_t found, regionId; | ||
|
||
__ASSERT(translate_config.num_regions < address_trans_MAX_REGIONS, | ||
"Exceeding maximum number of regions"); | ||
|
||
found = 0; | ||
|
||
for (regionId = 0; regionId < translate_config.num_regions; regionId++) { | ||
uint64_t start_addr, end_addr; | ||
uint32_t size_mask; | ||
|
||
/* we assume translate_config.region_config[] address and size is aligned */ | ||
size_mask = | ||
((uint32_t)(((uint64_t)1 << translate_config.region_config[regionId].size) - | ||
1)); | ||
|
||
start_addr = translate_config.region_config[regionId].system_addr; | ||
|
||
/* calculate end address */ | ||
end_addr = start_addr + size_mask; | ||
|
||
/* see if input address falls in this region */ | ||
if (pa >= start_addr && pa <= end_addr) { | ||
/* yes, input address falls in this region, break from loop */ | ||
found = 1; | ||
break; | ||
} | ||
} | ||
if (found) { | ||
/* translate input address to output address */ | ||
uint32_t offset = | ||
pa - translate_config.region_config[regionId].system_addr; | ||
|
||
*va = (void *)(translate_config.region_config[regionId].local_addr + offset); | ||
} else { | ||
/* no mapping found, set output = input with 32b truncation */ | ||
*va = (void *)pa; | ||
} | ||
|
||
if (va == NULL) { | ||
return -EFAULT; | ||
} | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
/* | ||
* Copyright (c) 2023 Texas Instruments Incorporated | ||
* Copyright (c) 2023 L Lakshmanan | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#ifndef ZEPHYR_INCLUDE_RAT_H_ | ||
#define ZEPHYR_INCLUDE_RAT_H_ | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
#include <stdint.h> | ||
|
||
#define ADDR_TRANSLATE_MAX_REGIONS (16u) | ||
#define RAT_CTRL(base_addr, i) (volatile uint32_t *)(base_addr + 0x20 + 0x10 * (i)) | ||
#define RAT_BASE(base_addr, i) (volatile uint32_t *)(base_addr + 0x24 + 0x10 * (i)) | ||
#define RAT_TRANS_L(base_addr, i) (volatile uint32_t *)(base_addr + 0x28 + 0x10 * (i)) | ||
#define RAT_TRANS_H(base_addr, i) (volatile uint32_t *)(base_addr + 0x2C + 0x10 * (i)) | ||
|
||
/** | ||
* \brief Enum's to represent different possible region size for the address translate module | ||
*/ | ||
enum address_trans_region_size { | ||
address_trans_region_size_1 = 0x0, | ||
address_trans_region_size_2, | ||
address_trans_region_size_4, | ||
address_trans_region_size_8, | ||
address_trans_region_size_16, | ||
address_trans_region_size_32, | ||
address_trans_region_size_64, | ||
address_trans_region_size_128, | ||
address_trans_region_size_256, | ||
address_trans_region_size_512, | ||
address_trans_region_size_1K, | ||
address_trans_region_size_2K, | ||
address_trans_region_size_4K, | ||
address_trans_region_size_8K, | ||
address_trans_region_size_16K, | ||
address_trans_region_size_32K, | ||
address_trans_region_size_64K, | ||
address_trans_region_size_128K, | ||
address_trans_region_size_256K, | ||
address_trans_region_size_512K, | ||
address_trans_region_size_1M, | ||
address_trans_region_size_2M, | ||
address_trans_region_size_4M, | ||
address_trans_region_size_8M, | ||
address_trans_region_size_16M, | ||
address_trans_region_size_32M, | ||
address_trans_region_size_64M, | ||
address_trans_region_size_128M, | ||
address_trans_region_size_256M, | ||
address_trans_region_size_512M, | ||
address_trans_region_size_1G, | ||
address_trans_region_size_2G, | ||
address_trans_region_size_4G | ||
}; | ||
|
||
/** | ||
* \brief Region config structure | ||
*/ | ||
struct address_trans_region_config { | ||
|
||
uint64_t system_addr; | ||
uint32_t local_addr; | ||
uint32_t size; | ||
|
||
}; | ||
|
||
/** | ||
* \brief Parameters for \ref address_trans_init | ||
*/ | ||
struct address_trans_params { | ||
|
||
uint32_t num_regions; | ||
uint32_t rat_base_addr; | ||
struct address_trans_region_config *region_config; | ||
|
||
}; | ||
|
||
void sys_mm_drv_ti_rat_init(void *region_config, uint64_t rat_base_addr, uint8_t translate_regions); | ||
|
||
/** @} */ | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif /* ZEPHYR_INCLUDE_RAT_H_ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters