/*
 * Copyright (C) 2002,2003 Broadcom Corporation
 *
 * 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.
 */

/* 
 * The Bus Watcher monitors internal bus transactions and maintains
 * counts of transactions with error status, logging details and
 * causing one of several interrupts.  This driver provides a handler
 * for those interrupts which aggregates the counts (to avoid
 * saturating the 8-bit counters) and provides a presence in
 * /proc/bus_watcher if PROC_FS is on.
 */

#include <linux/config.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
#include <asm/system.h>
#include <asm/io.h>

#include <asm/sibyte/sb1250.h>
#include <asm/sibyte/sb1250_regs.h>
#include <asm/sibyte/sb1250_int.h>
#include <asm/sibyte/sb1250_scd.h>


struct bw_stats_struct {
	uint64_t status;
	uint32_t l2_err;
	uint32_t memio_err;
	int status_printed;
	unsigned long l2_cor_d;
	unsigned long l2_bad_d;
	unsigned long l2_cor_t;
	unsigned long l2_bad_t;
	unsigned long mem_cor_d;
	unsigned long mem_bad_d;
	unsigned long bus_error;
} bw_stats;


static void print_summary(uint32_t status, uint32_t l2_err,
			  uint32_t memio_err)
{
	printk("Bus watcher error counters: %08x %08x\n", l2_err, memio_err);
	printk("\nLast recorded signature:\n");
	printk("Request %02x from %d, answered by %d with Dcode %d\n",
	       (unsigned int)(G_SCD_BERR_TID(status) & 0x3f),
	       (int)(G_SCD_BERR_TID(status) >> 6),
	       (int)G_SCD_BERR_RID(status),
	       (int)G_SCD_BERR_DCODE(status));
}

/*
 * check_bus_watcher is exported for use in situations where we want
 * to see the most recent status of the bus watcher, which might have
 * already been destructively read out of the registers.
 *
 * notes: this is currently used by the cache error handler
 *        should provide locking against the interrupt handler
 */
void check_bus_watcher(void)
{
	u32 status, l2_err, memio_err;

#ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
	/* Destructive read, clears register and interrupt */
	status = csr_in32(IOADDR(A_SCD_BUS_ERR_STATUS));
#else
	/* Use non-destructive register */
	status = csr_in32(IOADDR(A_SCD_BUS_ERR_STATUS_DEBUG));
#endif
	if (!(status & 0x7fffffff)) {
		printk("Using last values reaped by bus watcher driver\n");
		status = bw_stats.status;
		l2_err = bw_stats.l2_err;
		memio_err = bw_stats.memio_err;
	} else {
		l2_err = csr_in32(IOADDR(A_BUS_L2_ERRORS));
		memio_err = csr_in32(IOADDR(A_BUS_MEM_IO_ERRORS));
	}
	if (status & ~(1UL << 31))
		print_summary(status, l2_err, memio_err);
	else
		printk("Bus watcher indicates no error\n");
}

static int bw_print_buffer(char *page, struct bw_stats_struct *stats)
{
	int len;

	len = sprintf(page, "SiByte Bus Watcher statistics\n");
	len += sprintf(page+len, "-----------------------------\n");
	len += sprintf(page+len, "L2-d-cor %8ld\nL2-d-bad %8ld\n",
		       stats->l2_cor_d, stats->l2_bad_d);
	len += sprintf(page+len, "L2-t-cor %8ld\nL2-t-bad %8ld\n",
		       stats->l2_cor_t, stats->l2_bad_t);
	len += sprintf(page+len, "MC-d-cor %8ld\nMC-d-bad %8ld\n",
		       stats->mem_cor_d, stats->mem_bad_d);
	len += sprintf(page+len, "IO-err   %8ld\n", stats->bus_error);
	len += sprintf(page+len, "\nLast recorded signature:\n");
	len += sprintf(page+len, "Request %02x from %d, answered by %d with Dcode %d\n",
		       (unsigned int)(G_SCD_BERR_TID(stats->status) & 0x3f),
		       (int)(G_SCD_BERR_TID(stats->status) >> 6),
		       (int)G_SCD_BERR_RID(stats->status),
		       (int)G_SCD_BERR_DCODE(stats->status));
	/* XXXKW indicate multiple errors between printings, or stats
           collection (or both)? */
	if (stats->status & M_SCD_BERR_MULTERRS)
		len += sprintf(page+len, "Multiple errors observed since last check.\n");
	if (stats->status_printed) {
		len += sprintf(page+len, "(no change since last printing)\n");
	} else {
		stats->status_printed = 1;
	}

	return len;
}

#ifdef CONFIG_PROC_FS

/* For simplicity, I want to assume a single read is required each
   time */
static int bw_read_proc(char *page, char **start, off_t off,
			int count, int *eof, void *data)
{
	int len;

	if (off == 0) {
		len = bw_print_buffer(page, data);
		*start = page;
	} else {
		len = 0;
		*eof = 1;
	}
	return len;
}

static void create_proc_decoder(struct bw_stats_struct *stats)
{
	struct proc_dir_entry *ent;
	
	ent = create_proc_read_entry("bus_watcher", S_IWUSR | S_IRUGO, NULL,
				     bw_read_proc, stats);
	if (!ent) {
		printk(KERN_INFO "Unable to initialize bus_watcher /proc entry\n");
		return;
	}
}

#endif /* CONFIG_PROC_FS */

/*
 * sibyte_bw_int - handle bus watcher interrupts and accumulate counts
 *
 * notes: possible re-entry due to multiple sources
 *        should check/indicate saturation
 */
static irqreturn_t sibyte_bw_int(int irq, void *data, struct pt_regs *regs)
{
	struct bw_stats_struct *stats = data;
	unsigned long cntr;
#ifdef CONFIG_SIBYTE_BW_TRACE
	int i;
#endif
#ifndef CONFIG_PROC_FS
	char bw_buf[1024];
#endif

#ifdef CONFIG_SIBYTE_BW_TRACE
	csr_out32(M_SCD_TRACE_CFG_FREEZE, IOADDR(A_SCD_TRACE_CFG));
	csr_out32(M_SCD_TRACE_CFG_START_READ, IOADDR(A_SCD_TRACE_CFG));

	for (i=0; i<256*6; i++)
		printk("%016llx\n",
		       (unsigned long long)bus_readq(IOADDR(A_SCD_TRACE_READ)));

	csr_out32(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG));
	csr_out32(M_SCD_TRACE_CFG_START, IOADDR(A_SCD_TRACE_CFG));
#endif

	/* Destructive read, clears register and interrupt */
	stats->status = csr_in32(IOADDR(A_SCD_BUS_ERR_STATUS));
	stats->status_printed = 0;

	stats->l2_err = cntr = csr_in32(IOADDR(A_BUS_L2_ERRORS));
	stats->l2_cor_d += G_SCD_L2ECC_CORR_D(cntr);
	stats->l2_bad_d += G_SCD_L2ECC_BAD_D(cntr);
	stats->l2_cor_t += G_SCD_L2ECC_CORR_T(cntr);
	stats->l2_bad_t += G_SCD_L2ECC_BAD_T(cntr);
	csr_out32(0, IOADDR(A_BUS_L2_ERRORS));

	stats->memio_err = cntr = csr_in32(IOADDR(A_BUS_MEM_IO_ERRORS));
	stats->mem_cor_d += G_SCD_MEM_ECC_CORR(cntr);
	stats->mem_bad_d += G_SCD_MEM_ECC_BAD(cntr);
	stats->bus_error += G_SCD_MEM_BUSERR(cntr);
	csr_out32(0, IOADDR(A_BUS_MEM_IO_ERRORS));

#ifndef CONFIG_PROC_FS
	bw_print_buffer(bw_buf, stats);
	printk(bw_buf);
#endif

	return IRQ_HANDLED;
}

int __init sibyte_bus_watcher(void)
{
	memset(&bw_stats, 0, sizeof(struct bw_stats_struct));
	bw_stats.status_printed = 1;

	if (request_irq(K_INT_BAD_ECC, sibyte_bw_int, 0, "Bus watcher", &bw_stats)) {
		printk("Failed to register bus watcher BAD_ECC irq\n");
		return -1;
	}
	if (request_irq(K_INT_COR_ECC, sibyte_bw_int, 0, "Bus watcher", &bw_stats)) {
		free_irq(K_INT_BAD_ECC, &bw_stats);
		printk("Failed to register bus watcher COR_ECC irq\n");
		return -1;
	}
	if (request_irq(K_INT_IO_BUS, sibyte_bw_int, 0, "Bus watcher", &bw_stats)) {
		free_irq(K_INT_BAD_ECC, &bw_stats);
		free_irq(K_INT_COR_ECC, &bw_stats);
		printk("Failed to register bus watcher IO_BUS irq\n");
		return -1;
	}

#ifdef CONFIG_PROC_FS
	create_proc_decoder(&bw_stats);
#endif

#ifdef CONFIG_SIBYTE_BW_TRACE
	csr_out32((M_SCD_TRSEQ_ASAMPLE | M_SCD_TRSEQ_DSAMPLE |
		   K_SCD_TRSEQ_TRIGGER_ALL),
		  IOADDR(A_SCD_TRACE_SEQUENCE_0));
	csr_out32(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG));
	csr_out32(M_SCD_TRACE_CFG_START, IOADDR(A_SCD_TRACE_CFG));
#endif

	return 0;
}

__initcall(sibyte_bus_watcher);
