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 7, 2023
1 parent f3cafe7 commit ccca323
Show file tree
Hide file tree
Showing 5 changed files with 239 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)
18 changes: 18 additions & 0 deletions drivers/mm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,22 @@ 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 if necessary"
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
118 changes: 118 additions & 0 deletions drivers/mm/mm_drv_ti_rat.c
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;
}
92 changes: 92 additions & 0 deletions include/zephyr/drivers/mm/rat.h
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_ */
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_MM_DRV)
#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 ccca323

Please sign in to comment.