Commit a7749acc authored by Varun Wadekar's avatar Varun Wadekar
Browse files

Tegra: memctrl_v2: fixup sequence to resize video memory



The previous sequence used by the driver to program the new memory
aperture settings and clear the non-overlapping memory was faulty.
The sequence locked the non-overlapping regions twice, leading to
faults when trying to clear it.

This patch modifies the sequence to follow these steps:

* move the previous memory region to a new firewall register
* program the new memory aperture settings
* clean the non-overlapping memory

This patch also maps the non-overlapping memory as Device memory to
follow guidance from the arch. team.
Signed-off-by: default avatarVarun Wadekar <vwadekar@nvidia.com>
Change-Id: I7cf6e05b2dd372103dc7229e37b1b3fc269a57ae
parent 9935047b
...@@ -280,56 +280,32 @@ static void tegra_clear_videomem(uintptr_t non_overlap_area_start, ...@@ -280,56 +280,32 @@ static void tegra_clear_videomem(uintptr_t non_overlap_area_start,
{ {
int ret; int ret;
INFO("Cleaning previous Video Memory Carveout\n");
/* /*
* Map the NS memory first, clean it and then unmap it. * Map the NS memory first, clean it and then unmap it.
*/ */
ret = mmap_add_dynamic_region(non_overlap_area_start, /* PA */ ret = mmap_add_dynamic_region(non_overlap_area_start, /* PA */
non_overlap_area_start, /* VA */ non_overlap_area_start, /* VA */
non_overlap_area_size, /* size */ non_overlap_area_size, /* size */
MT_NS | MT_RW | MT_EXECUTE_NEVER | MT_DEVICE | MT_RW | MT_NS); /* attrs */
MT_NON_CACHEABLE); /* attrs */
assert(ret == 0); assert(ret == 0);
zero_normalmem((void *)non_overlap_area_start, non_overlap_area_size); zeromem((void *)non_overlap_area_start, non_overlap_area_size);
flush_dcache_range(non_overlap_area_start, non_overlap_area_size); flush_dcache_range(non_overlap_area_start, non_overlap_area_size);
(void)mmap_remove_dynamic_region(non_overlap_area_start, ret = mmap_remove_dynamic_region(non_overlap_area_start,
non_overlap_area_size); non_overlap_area_size);
assert(ret == 0);
} }
/* static void tegra_clear_videomem_nonoverlap(uintptr_t phys_base,
* Program the Video Memory carveout region unsigned long size_in_bytes)
*
* phys_base = physical base of aperture
* size_in_bytes = size of aperture in bytes
*/
void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes)
{ {
uintptr_t vmem_end_old = video_mem_base + (video_mem_size_mb << 20); uintptr_t vmem_end_old = video_mem_base + (video_mem_size_mb << 20);
uintptr_t vmem_end_new = phys_base + size_in_bytes; uintptr_t vmem_end_new = phys_base + size_in_bytes;
unsigned long long non_overlap_area_size; unsigned long long non_overlap_area_size;
/*
* Setup the Memory controller to restrict CPU accesses to the Video
* Memory region
*/
INFO("Configuring Video Memory Carveout\n");
/*
* Configure Memory Controller directly for the first time.
*/
if (video_mem_base == 0U)
goto done;
/*
* Lock the non overlapping memory being cleared so that other masters
* do not accidently write to it. The memory would be unlocked once
* the non overlapping region is cleared and the new memory
* settings take effect.
*/
tegra_lock_videomem_nonoverlap(video_mem_base,
video_mem_size_mb << 20);
/* /*
* Clear the old regions now being exposed. The following cases * Clear the old regions now being exposed. The following cases
* can occur - * can occur -
...@@ -338,8 +314,6 @@ void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes) ...@@ -338,8 +314,6 @@ void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes)
* 2. clear old sub-region below new base * 2. clear old sub-region below new base
* 3. clear old sub-region above new end * 3. clear old sub-region above new end
*/ */
INFO("Cleaning previous Video Memory Carveout\n");
if ((phys_base > vmem_end_old) || (video_mem_base > vmem_end_new)) { if ((phys_base > vmem_end_old) || (video_mem_base > vmem_end_new)) {
tegra_clear_videomem(video_mem_base, tegra_clear_videomem(video_mem_base,
video_mem_size_mb << 20U); video_mem_size_mb << 20U);
...@@ -353,26 +327,55 @@ void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes) ...@@ -353,26 +327,55 @@ void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes)
tegra_clear_videomem(vmem_end_new, non_overlap_area_size); tegra_clear_videomem(vmem_end_new, non_overlap_area_size);
} }
} }
}
/*
* Program the Video Memory carveout region
*
* phys_base = physical base of aperture
* size_in_bytes = size of aperture in bytes
*/
void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes)
{
/*
* Setup the Memory controller to restrict CPU accesses to the Video
* Memory region
*/
INFO("Configuring Video Memory Carveout\n");
if (video_mem_base != 0U) {
/*
* Lock the non overlapping memory being cleared so that
* other masters do not accidently write to it. The memory
* would be unlocked once the non overlapping region is
* cleared and the new memory settings take effect.
*/
tegra_lock_videomem_nonoverlap(video_mem_base,
video_mem_size_mb << 20);
}
done:
/* program the Videomem aperture */ /* program the Videomem aperture */
tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO, (uint32_t)phys_base); tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO, (uint32_t)phys_base);
tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI, tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI,
(uint32_t)(phys_base >> 32)); (uint32_t)(phys_base >> 32));
tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, size_in_bytes >> 20); tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, size_in_bytes >> 20);
/* unlock the previous locked nonoverlapping aperture */
tegra_unlock_videomem_nonoverlap();
/* store new values */
video_mem_base = phys_base;
video_mem_size_mb = size_in_bytes >> 20;
/* /*
* MCE propagates the VideoMem configuration values across the * MCE propagates the VideoMem configuration values across the
* CCPLEX. * CCPLEX.
*/ */
mce_update_gsc_videomem(); (void)mce_update_gsc_videomem();
/* Clear the non-overlapping memory */
if (video_mem_base != 0U) {
tegra_clear_videomem_nonoverlap(phys_base, size_in_bytes);
tegra_unlock_videomem_nonoverlap();
}
/* store new values */
video_mem_base = phys_base;
video_mem_size_mb = (uint64_t)size_in_bytes >> 20;
} }
/* /*
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment