arch/arm/am67: Add a RAT sliding window for 36-bit DDR access.

J722S maps DDR above the first 2 GB at 0x8_8000_0000, out of reach of the
32-bit R5F, while a 64-bit Linux peer posts virtio buffers there.

Dedicates RAT region 0 as a 16 MB window at 0xFE000000.  am67_rat_map() re-aims
it and returns a pointer plus the bytes left before the edge, so callers can
split copies that straddle it.

The window is Non-cacheable, since it retargets at runtime and cached lines
would alias across physical blocks.  A mapping is valid only until the next
call; the sole user, vhost-net, is serialised on the netdev work thread.

Assisted-by: Claude Code:claude-fable-5
Signed-off-by: Ulaş Sertan Kemeç <sertan.usk@gmail.com>
This commit is contained in:
Ulaş Sertan Kemeç 2026-08-04 11:38:19 +03:00 • committed by Xiang Xiao
parent a2edd99159
commit cd4fe549ee
5 changed files with 184 additions and 2 deletions

View file

@ -20,8 +20,14 @@
#
# ##############################################################################
set(SRCS am67_boot.c am67_irq.c am67_mpuinit.c am67_pinmux.c am67_serial.c
am67_timer.c)
set(SRCS
am67_boot.c
am67_irq.c
am67_mpuinit.c
am67_pinmux.c
am67_rat.c
am67_serial.c
am67_timer.c)
if(CONFIG_RPTUN)
list(APPEND SRCS am67_rptun.c)

View file

@ -48,3 +48,4 @@ endif
ifeq ($(CONFIG_RPTUN),y)
CHIP_CSRCS += am67_rptun.c
endif
CHIP_CSRCS += am67_rat.c

View file

@ -31,6 +31,7 @@
#include <sys/param.h>
#include "am67_mpuinit.h"
#include "am67_rat.h"
#include "mpu.h"
/****************************************************************************
@ -85,5 +86,11 @@ void am67_mpu_init(void)
am67_ipc_shm_region(AM67_IPC_SHM0_START_ADDR, AM67_IPC_SHM0_SIZE);
am67_ipc_shm_region(AM67_IPC_SHM1_START_ADDR, AM67_IPC_SHM1_SIZE);
/* RAT sliding window (am67_rat.c): retargeted at runtime onto arbitrary
* 36-bit physical blocks, so it must never be cached.
*/
am67_ipc_shm_region(AM67_RAT_WIN_BASE, AM67_RAT_WIN_SIZE);
mpu_control(true);
}

View file

@ -0,0 +1,114 @@
/****************************************************************************
* arch/arm/src/am67/am67_rat.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
/* Region Address Translator (RAT) sliding window.
*
* The Cortex-R5F is a 32-bit master on a 36-bit SoC: DDR beyond the first
* 2 GB lives at 0x8_8000_0000 and cannot be addressed by the core
* directly. The R5FSS integrates a per-core RAT (config space at
* 0x2ffe_0000, 4 regions) that remaps a 32-bit input window onto any
* 36-bit output address (TRM 7.2.2.6 / 7.3.2.6.4).
*
* This driver dedicates one region as a 16 MB sliding window: callers ask
* for a pointer to an arbitrary 36-bit physical address and the window is
* re-aimed at the containing 16 MB block. The window range is mapped
* Non-cacheable in the MPU (am67_mpuinit.c), so accesses through it are
* also coherent with the A53 without cache maintenance.
*
* The single window is a shared resource: the returned pointer is only
* valid until the next am67_rat_map() call, and callers must be
* serialized (the sole current user is the vhost-net driver, whose
* transmit/receive both run on the netdev work thread).
*/
#include <nuttx/config.h>
#include <stdint.h>
#include <stddef.h>
#include <arch/barriers.h>
#include "arm_internal.h"
#include "am67_rat.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define AM67_RAT_BASE (0x2ffe0000ul)
#define AM67_RAT_CTRL(n) (AM67_RAT_BASE + 0x20 + 0x10 * (n))
#define AM67_RAT_ADDR(n) (AM67_RAT_BASE + 0x24 + 0x10 * (n))
#define AM67_RAT_TRANS_L(n) (AM67_RAT_BASE + 0x28 + 0x10 * (n))
#define AM67_RAT_TRANS_U(n) (AM67_RAT_BASE + 0x2c + 0x10 * (n))
#define AM67_RAT_CTRL_EN (1ul << 31)
#define AM67_RAT_REGION (0) /* RAT region index used for the window */
#define AM67_RAT_WIN_LOG2 (24) /* 16 MB window */
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: am67_rat_map
*
* Description:
* Return a CPU pointer to the given 36-bit physical address by sliding
* the RAT window over its 16 MB block. If avail is non-NULL it
* receives the number of contiguous bytes reachable from the returned
* pointer before the window ends (callers accessing more must map
* again at the advanced address).
*
* The pointer is valid only until the next call. Not reentrant.
*
****************************************************************************/
FAR void *am67_rat_map(uint64_t pa, FAR size_t *avail)
{
static uint64_t cur_block = UINT64_MAX;
uint64_t block = pa & ~((uint64_t)AM67_RAT_WIN_SIZE - 1);
uint32_t offset = (uint32_t)(pa & (AM67_RAT_WIN_SIZE - 1));
if (block != cur_block)
{
putreg32(0, AM67_RAT_CTRL(AM67_RAT_REGION));
putreg32(AM67_RAT_WIN_BASE, AM67_RAT_ADDR(AM67_RAT_REGION));
putreg32((uint32_t)block, AM67_RAT_TRANS_L(AM67_RAT_REGION));
putreg32((uint32_t)(block >> 32), AM67_RAT_TRANS_U(AM67_RAT_REGION));
putreg32(AM67_RAT_CTRL_EN | AM67_RAT_WIN_LOG2,
AM67_RAT_CTRL(AM67_RAT_REGION));
UP_DSB();
cur_block = block;
}
if (avail != NULL)
{
*avail = AM67_RAT_WIN_SIZE - offset;
}
return (FAR void *)(AM67_RAT_WIN_BASE + offset);
}

View file

@ -0,0 +1,54 @@
/****************************************************************************
* arch/arm/src/am67/am67_rat.h
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __ARCH_ARM_SRC_AM67_AM67_RAT_H
#define __ARCH_ARM_SRC_AM67_AM67_RAT_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <stddef.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* 32-bit address range claimed by the RAT sliding window. Must be mapped
* Non-cacheable in the MPU (am67_mpuinit.c) and must not overlap anything
* the firmware needs to address directly (NuttX RAM/IPC live in
* 0xa2000000-0xa3000000).
*/
#define AM67_RAT_WIN_BASE (0xfe000000ul)
#define AM67_RAT_WIN_SIZE (0x01000000ul) /* 16 MB */
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
FAR void *am67_rat_map(uint64_t pa, FAR size_t *avail);
#endif /* __ARCH_ARM_SRC_AM67_AM67_RAT_H */