-
Notifications
You must be signed in to change notification settings - Fork 6.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
drivers: Add external address translation module and TI RAT support #60028
Merged
carlescufi
merged 1 commit into
zephyrproject-rtos:main
from
KarthikL1729:external_address_translation
Jul 11, 2023
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,143 @@ | ||
/* | ||
* Copyright (c) 2023 Texas Instruments Incorporated | ||
* Copyright (c) 2023 L Lakshmanan | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
/** | ||
* @file | ||
* @brief Driver handling Region based Address Translation (RAT) | ||
* related functions | ||
* | ||
* RAT is a module that is used by certain Texas Instruments SoCs | ||
* to allow some cores with a 32 bit address space to access | ||
* the full 48 bit SoC address space. This is required for the | ||
* core to be able to use peripherals. | ||
* | ||
* The driver uses the sys_mm_drv_page_phys_get() API to access | ||
* the address space. | ||
*/ | ||
|
||
#include <zephyr/drivers/mm/rat.h> | ||
#include <zephyr/drivers/mm/system_mm.h> | ||
#include <zephyr/sys/__assert.h> | ||
|
||
static struct address_trans_params translate_config; | ||
|
||
/** | ||
* @brief Set registers for the address regions being used | ||
* | ||
* @param addr_translate_config Pointer to config struct for the RAT module | ||
* @param region_num Number of regions being initialised | ||
* @param enable Region status | ||
*/ | ||
|
||
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)((BIT64_MASK(size))))); | ||
system_addrH = (uint32_t)((system_addr >> 32) & 0xFFFF); | ||
local_addr = local_addr & ~((uint32_t)(BIT64_MASK(size))); | ||
|
||
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(RAT_CTRL_W(enable, size), 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); | ||
} | ||
} | ||
|
||
/** | ||
* @brief Initialise RAT module | ||
* | ||
* @param region_config Pointer to config struct for the regions | ||
* @param rat_base_addr Base address for the RAT module | ||
* @param translate_regions Number of regions being initialised | ||
*/ | ||
|
||
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; | ||
|
||
size_mask = | ||
((uint32_t)((BIT64_MASK(translate_config.region_config[regionId].size)))); | ||
|
||
start_addr = translate_config.region_config[regionId].system_addr; | ||
|
||
end_addr = start_addr + size_mask; | ||
|
||
if (pa >= start_addr && pa <= end_addr) { | ||
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,87 @@ | ||
/* | ||
* 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)) | ||
#define RAT_CTRL_W(enable, size) (((enable & 0x1) << 31u) | (size & 0x3F)) | ||
|
||
/** | ||
* @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 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,10 +33,14 @@ | |
* If we have PCIE enabled, this does mean that non-PCIE drivers may waste | ||
* a bit of RAM, but systems with PCI express are not RAM constrained. | ||
*/ | ||
#if defined(CONFIG_MMU) || defined(CONFIG_PCIE) | ||
#if defined(CONFIG_MMU) || defined(CONFIG_PCIE) || defined(CONFIG_EXTERNAL_ADDRESS_TRANSLATION) | ||
#define DEVICE_MMIO_IS_IN_RAM | ||
#endif | ||
|
||
#if defined(CONFIG_EXTERNAL_ADDRESS_TRANSLATION) | ||
#include <zephyr/drivers/mm/system_mm.h> | ||
#endif | ||
|
||
#ifndef _ASMLANGUAGE | ||
#include <stdint.h> | ||
#include <stddef.h> | ||
|
@@ -101,8 +105,11 @@ static inline void device_map(mm_reg_t *virt_addr, uintptr_t phys_addr, | |
#else | ||
ARG_UNUSED(size); | ||
ARG_UNUSED(flags); | ||
|
||
#ifdef CONFIG_EXTERNAL_ADDRESS_TRANSLATION | ||
sys_mm_drv_page_phys_get((void *) phys_addr, virt_addr); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have no objection to this since this is the only use case for now? Just raise my concern for the future as this is a system API:
Fortunately, we could think about it later. MMU and RAT existing simultaneously seem like a 2 stage translation which is definitely a tricky thing. |
||
#else | ||
*virt_addr = phys_addr; | ||
#endif /* CONFIG_EXTERNAL_ADDRESS_TRANSLATION */ | ||
#endif /* CONFIG_MMU */ | ||
} | ||
#else | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this file
select KERNEL_VM_SUPPORT
should be moved out ofmenuconfig
now?