/*
 * (C) Copyright 2010
 * Texas Instruments, <www.ti.com>
 * Aneesh V <aneesh@ti.com>
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */
#include <linux/types.h>
#include <asm/io.h>
#include <asm/armv7.h>
#include <asm/pl310.h>
#include <config.h>

struct pl310_regs *const pl310 = (struct pl310_regs *)CONFIG_SYS_PL310_BASE;

static void pl310_cache_sync(void)
{
	writel(0, &pl310->pl310_cache_sync);
}

static void pl310_background_op_all_ways(u32 *op_reg)
{
	u32 assoc_16, associativity, way_mask;

	assoc_16 = readl(&pl310->pl310_aux_ctrl) &
			PL310_AUX_CTRL_ASSOCIATIVITY_MASK;
	if (assoc_16)
		associativity = 16;
	else
		associativity = 8;

	way_mask = (1 << associativity) - 1;
	/* Invalidate all ways */
	writel(way_mask, op_reg);
	/* Wait for all ways to be invalidated */
	while (readl(op_reg) && way_mask)
		;
	pl310_cache_sync();
}

void v7_outer_cache_inval_all(void)
{
	pl310_background_op_all_ways(&pl310->pl310_inv_way);
}

void v7_outer_cache_flush_all(void)
{
	pl310_background_op_all_ways(&pl310->pl310_clean_inv_way);
}

/* Flush(clean invalidate) memory from start to stop-1 */
void v7_outer_cache_flush_range(u32 start, u32 stop)
{
	/* PL310 currently supports only 32 bytes cache line */
	u32 pa, line_size = 32;

	/*
	 * Align to the beginning of cache-line - this ensures that
	 * the first 5 bits are 0 as required by PL310 TRM
	 */
	start &= ~(line_size - 1);

	for (pa = start; pa < stop; pa = pa + line_size)
		writel(pa, &pl310->pl310_clean_inv_line_pa);

	pl310_cache_sync();
}

/* invalidate memory from start to stop-1 */
void v7_outer_cache_inval_range(u32 start, u32 stop)
{
	/* PL310 currently supports only 32 bytes cache line */
	u32 pa, line_size = 32;

	/*
	 * If start address is not aligned to cache-line flush the first
	 * line to prevent affecting somebody else's buffer
	 */
	if (start & (line_size - 1)) {
		v7_outer_cache_flush_range(start, start + 1);
		/* move to next cache line */
		start = (start + line_size - 1) & ~(line_size - 1);
	}

	/*
	 * If stop address is not aligned to cache-line flush the last
	 * line to prevent affecting somebody else's buffer
	 */
	if (stop & (line_size - 1)) {
		v7_outer_cache_flush_range(stop, stop + 1);
		/* align to the beginning of this cache line */
		stop &= ~(line_size - 1);
	}

	for (pa = start; pa < stop; pa = pa + line_size)
		writel(pa, &pl310->pl310_inv_line_pa);

	pl310_cache_sync();
}
