Skip to content

Commit

Permalink
drivers: mm: Add support for TI RAT module using system_mm API
Browse files Browse the repository at this point in the history
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
KarthikL1729 committed Jul 10, 2023
1 parent f3cafe7 commit 90e654d
Show file tree
Hide file tree
Showing 5 changed files with 260 additions and 2 deletions.
2 changes: 2 additions & 0 deletions drivers/mm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@ zephyr_sources_ifdef(
mm_drv_intel_adsp_regions.c
mm_drv_intel_adsp_mtl_tlb.c
)

zephyr_sources_ifdef(CONFIG_MM_TI_RAT mm_drv_ti_rat.c)
19 changes: 19 additions & 0 deletions drivers/mm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,23 @@ config MM_DRV_INTEL_ADSP_TLB
Driver for the translation lookup buffer on
Intel Audio DSP hardware.

config EXTERNAL_ADDRESS_TRANSLATION
bool "Support for external address translation modules"
depends on !MMU
help
This config is intended to support an external address
translation module if required for an SoC. Uses the
sys_mm_drv_page_phys_get() function from the system_mm API.

if EXTERNAL_ADDRESS_TRANSLATION

config MM_TI_RAT
bool "Texas Instruments RAT module"
depends on EXTERNAL_ADDRESS_TRANSLATION
help
Enables Region based address translation support
functions specific to TI SoCs.

endif # EXTERNAL_ADDRESS_TRANSLATION

endif # MM_DRV
143 changes: 143 additions & 0 deletions drivers/mm/mm_drv_ti_rat.c
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;
}
87 changes: 87 additions & 0 deletions include/zephyr/drivers/mm/rat.h
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_ */
11 changes: 9 additions & 2 deletions include/zephyr/sys/device_mmio.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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);
#else
*virt_addr = phys_addr;
#endif /* CONFIG_EXTERNAL_ADDRESS_TRANSLATION */
#endif /* CONFIG_MMU */
}
#else
Expand Down

0 comments on commit 90e654d

Please sign in to comment.