/*
 * This file is part of the coreboot project.
 *
 * Copyright 2013 Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <config.h>
#include <stdlib.h>
#include <stdint.h>

#include <cbmem.h>
#include <console/console.h>

#include <arch/cache.h>
#include <arch/io.h>

static void *const ttb_buff = (void *)CONFIG_TTB_BUFFER;

void mmu_disable_range(unsigned long start_mb, unsigned long size_mb)
{
	unsigned int i;
	uint32_t *ttb_entry = ttb_buff;
	printk(BIOS_DEBUG, "Disabling: 0x%08lx:0x%08lx\n",
			start_mb*MiB, start_mb*MiB + size_mb*MiB - 1);

	for (i = start_mb; i < start_mb + size_mb; i++)
		writel(0, &ttb_entry[i]);

	for (i = start_mb; i < start_mb + size_mb; i++) {
		dccmvac((uintptr_t)&ttb_entry[i]);
		tlbimvaa(i*MiB);
	}
}

void mmu_config_range(unsigned long start_mb, unsigned long size_mb,
		enum dcache_policy policy)
{
	unsigned int i;
	uint32_t attr;
	uint32_t *ttb_entry = ttb_buff;
	const char *str = NULL;

	/*
	 * Section entry bits:
	 * 31:20 - section base address
	 *    18 - 0 to indicate normal section (versus supersection)
	 *    17 - nG, 0 to indicate page is global
	 *    16 - S, 0 for non-shareable (?)
	 *    15 - APX, 0 for full access
	 * 14:12 - TEX, 0b000 for outer and inner write-back
	 * 11:10 - AP, 0b11 for full access
	 *     9 - P, ? (FIXME: not described or possibly obsolete?)
	 *  8: 5 - Domain
	 *     4 - XN, 1 to set execute-never (and also avoid prefetches)
	 *     3 - C, 1 for cacheable
	 *     2 - B, 1 for bufferable
	 *  1: 0 - 0b10 to indicate section entry
	 */

	switch(policy) {
	case DCACHE_OFF:
		/* XN set to avoid prefetches to uncached/unbuffered regions */
		attr = (0x3 << 10) | (1 << 4) | 0x2;
		str = "off";
		break;
	case DCACHE_WRITEBACK:
		attr =  (0x3 << 10) | (1 << 3) | (1 << 2) | 0x2;
		str = "writeback";
		break;
	case DCACHE_WRITETHROUGH:
		attr =  (0x3 << 10) | (1 << 3) | 0x2;
		str = "writethrough";
		break;
	default:
		printk(BIOS_ERR, "unknown dcache policy: %02x\n", policy);
		return;
	}

	printk(BIOS_DEBUG, "Setting dcache policy: 0x%08lx:0x%08lx [%s]\n",
			start_mb << 20, ((start_mb + size_mb) << 20) - 1, str);

	/* Write out page table entries. */
	for (i = start_mb; i < start_mb + size_mb; i++)
		writel((i << 20) | attr, &ttb_entry[i]);

	/* Flush the page table entries, and old translations from the TLB. */
	for (i = start_mb; i < start_mb + size_mb; i++) {
		dccmvac((uintptr_t)&ttb_entry[i]);
		tlbimvaa(i*MiB);
	}
}

void mmu_init(void)
{
	/*
	 * For coreboot's purposes, we will create a simple L1 page table
	 * in RAM with 1MB section translation entries over the 4GB address
	 * space.
	 * (ref: section 10.2 and example 15-4 in Cortex-A series
	 * programmer's guide)
         */
	printk(BIOS_DEBUG, "Translation table is @ %p\n", ttb_buff);

	/*
	 * Disable TTBR1 by setting TTBCR.N to 0b000, which means the TTBR0
	 * table size is 16KB and has indices VA[31:20].
	 *
	 * ref: Arch Ref. Manual for ARMv7-A, B3.5.4,
	 */
	write_ttbcr(read_ttbcr() & ~0x3);

	/*
	 * Translation table base 0 address is in bits 31:14-N, where N is given
	 * by bits 2:0 in TTBCR (which we set to 0). All lower bits in this
	 * register should be zero for coreboot.
	 */
	write_ttbr0((uintptr_t)ttb_buff);

	/* disable domain-level checking of permissions */
	write_dacr(~0);
}
