/*
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) 2001-2006 Silicon Graphics, Inc. All rights reserved.
 */

#include <linux/types.h>
#include <asm/sn/sn_sal.h>
#include <asm/sn/pcibr_provider.h>
#include <asm/sn/pcibus_provider_defs.h>
#include <asm/sn/pcidev.h>

int pcibr_invalidate_ate;	/* by default don't invalidate ATE on free */

/*
 * mark_ate: Mark the ate as either free or inuse.
 */
static void mark_ate(struct ate_resource *ate_resource, int start, int number,
		     u64 value)
{
	u64 *ate = ate_resource->ate;
	int index;
	int length = 0;

	for (index = start; length < number; index++, length++)
		ate[index] = value;
}

/*
 * find_free_ate:  Find the first free ate index starting from the given
 *		   index for the desired consecutive count.
 */
static int find_free_ate(struct ate_resource *ate_resource, int start,
			 int count)
{
	u64 *ate = ate_resource->ate;
	int index;
	int start_free;

	for (index = start; index < ate_resource->num_ate;) {
		if (!ate[index]) {
			int i;
			int free;
			free = 0;
			start_free = index;	/* Found start free ate */
			for (i = start_free; i < ate_resource->num_ate; i++) {
				if (!ate[i]) {	/* This is free */
					if (++free == count)
						return start_free;
				} else {
					index = i + 1;
					break;
				}
			}
			if (i >= ate_resource->num_ate)
				return -1;
		} else
			index++;	/* Try next ate */
	}

	return -1;
}

/*
 * free_ate_resource:  Free the requested number of ATEs.
 */
static inline void free_ate_resource(struct ate_resource *ate_resource,
				     int start)
{
	mark_ate(ate_resource, start, ate_resource->ate[start], 0);
	if ((ate_resource->lowest_free_index > start) ||
	    (ate_resource->lowest_free_index < 0))
		ate_resource->lowest_free_index = start;
}

/*
 * alloc_ate_resource:  Allocate the requested number of ATEs.
 */
static inline int alloc_ate_resource(struct ate_resource *ate_resource,
				     int ate_needed)
{
	int start_index;

	/*
	 * Check for ate exhaustion.
	 */
	if (ate_resource->lowest_free_index < 0)
		return -1;

	/*
	 * Find the required number of free consecutive ates.
	 */
	start_index =
	    find_free_ate(ate_resource, ate_resource->lowest_free_index,
			  ate_needed);
	if (start_index >= 0)
		mark_ate(ate_resource, start_index, ate_needed, ate_needed);

	ate_resource->lowest_free_index =
	    find_free_ate(ate_resource, ate_resource->lowest_free_index, 1);

	return start_index;
}

/*
 * Allocate "count" contiguous Bridge Address Translation Entries
 * on the specified bridge to be used for PCI to XTALK mappings.
 * Indices in rm map range from 1..num_entries.  Indices returned
 * to caller range from 0..num_entries-1.
 *
 * Return the start index on success, -1 on failure.
 */
int pcibr_ate_alloc(struct pcibus_info *pcibus_info, int count)
{
	int status;
	unsigned long flags;

	spin_lock_irqsave(&pcibus_info->pbi_lock, flags);
	status = alloc_ate_resource(&pcibus_info->pbi_int_ate_resource, count);
	spin_unlock_irqrestore(&pcibus_info->pbi_lock, flags);

	return status;
}

/*
 * Setup an Address Translation Entry as specified.  Use either the Bridge
 * internal maps or the external map RAM, as appropriate.
 */
static inline u64 __iomem *pcibr_ate_addr(struct pcibus_info *pcibus_info,
				       int ate_index)
{
	if (ate_index < pcibus_info->pbi_int_ate_size) {
		return pcireg_int_ate_addr(pcibus_info, ate_index);
	}
	panic("pcibr_ate_addr: invalid ate_index 0x%x", ate_index);
}

/*
 * Update the ate.
 */
void inline
ate_write(struct pcibus_info *pcibus_info, int ate_index, int count,
	  volatile u64 ate)
{
	while (count-- > 0) {
		if (ate_index < pcibus_info->pbi_int_ate_size) {
			pcireg_int_ate_set(pcibus_info, ate_index, ate);
		} else {
			panic("ate_write: invalid ate_index 0x%x", ate_index);
		}
		ate_index++;
		ate += IOPGSIZE;
	}

	pcireg_tflush_get(pcibus_info);	/* wait until Bridge PIO complete */
}

void pcibr_ate_free(struct pcibus_info *pcibus_info, int index)
{

	volatile u64 ate;
	int count;
	unsigned long flags;

	if (pcibr_invalidate_ate) {
		/* For debugging purposes, clear the valid bit in the ATE */
		ate = *pcibr_ate_addr(pcibus_info, index);
		count = pcibus_info->pbi_int_ate_resource.ate[index];
		ate_write(pcibus_info, index, count, (ate & ~PCI32_ATE_V));
	}

	spin_lock_irqsave(&pcibus_info->pbi_lock, flags);
	free_ate_resource(&pcibus_info->pbi_int_ate_resource, index);
	spin_unlock_irqrestore(&pcibus_info->pbi_lock, flags);
}
