/*
 * arch/ppc/kernel/ibm440gx_common.c
 *
 * PPC440GX system library
 *
 * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
 * Copyright (c) 2003, 2004 Zultys Technologies
 *
 * 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.
 *
 */
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <asm/ibm44x.h>
#include <asm/mmu.h>
#include <asm/processor.h>
#include <syslib/ibm440gx_common.h>

/*
 * Calculate 440GX clocks
 */
static inline u32 __fix_zero(u32 v, u32 def){
	return v ? v : def;
}

void __init ibm440gx_get_clocks(struct ibm44x_clocks* p, unsigned int sys_clk,
	unsigned int ser_clk)
{
	u32 pllc  = CPR_READ(DCRN_CPR_PLLC);
	u32 plld  = CPR_READ(DCRN_CPR_PLLD);
	u32 uart0 = SDR_READ(DCRN_SDR_UART0);
	u32 uart1 = SDR_READ(DCRN_SDR_UART1);
#ifdef CONFIG_440EP
	u32 uart2 = SDR_READ(DCRN_SDR_UART2);
	u32 uart3 = SDR_READ(DCRN_SDR_UART3);
#endif

	/* Dividers */
	u32 fbdv   = __fix_zero((plld >> 24) & 0x1f, 32);
	u32 fwdva  = __fix_zero((plld >> 16) & 0xf, 16);
	u32 fwdvb  = __fix_zero((plld >> 8) & 7, 8);
	u32 lfbdv  = __fix_zero(plld & 0x3f, 64);
	u32 pradv0 = __fix_zero((CPR_READ(DCRN_CPR_PRIMAD) >> 24) & 7, 8);
	u32 prbdv0 = __fix_zero((CPR_READ(DCRN_CPR_PRIMBD) >> 24) & 7, 8);
	u32 opbdv0 = __fix_zero((CPR_READ(DCRN_CPR_OPBD) >> 24) & 3, 4);
	u32 perdv0 = __fix_zero((CPR_READ(DCRN_CPR_PERD) >> 24) & 3, 4);

	/* Input clocks for primary dividers */
	u32 clk_a, clk_b;

	if (pllc & 0x40000000){
		u32 m;

		/* Feedback path */
		switch ((pllc >> 24) & 7){
		case 0:
			/* PLLOUTx */
			m = ((pllc & 0x20000000) ? fwdvb : fwdva) * lfbdv;
			break;
		case 1:
			/* CPU */
			m = fwdva * pradv0;
			break;
		case 5:
			/* PERClk */
			m = fwdvb * prbdv0 * opbdv0 * perdv0;
			break;
		default:
			printk(KERN_EMERG "invalid PLL feedback source\n");
			goto bypass;
		}
		m *= fbdv;
		p->vco = sys_clk * m;
		clk_a = p->vco / fwdva;
		clk_b = p->vco / fwdvb;
	}
	else {
bypass:
		/* Bypass system PLL */
		p->vco = 0;
		clk_a = clk_b = sys_clk;
	}

	p->cpu = clk_a / pradv0;
	p->plb = clk_b / prbdv0;
	p->opb = p->plb / opbdv0;
	p->ebc = p->opb / perdv0;

	/* UARTs clock */
	if (uart0 & 0x00800000)
		p->uart0 = ser_clk;
	else
		p->uart0 = p->plb / __fix_zero(uart0 & 0xff, 256);

	if (uart1 & 0x00800000)
		p->uart1 = ser_clk;
	else
		p->uart1 = p->plb / __fix_zero(uart1 & 0xff, 256);
#ifdef CONFIG_440EP
	if (uart2 & 0x00800000)
		p->uart2 = ser_clk;
	else
		p->uart2 = p->plb / __fix_zero(uart2 & 0xff, 256);

	if (uart3 & 0x00800000)
		p->uart3 = ser_clk;
	else
		p->uart3 = p->plb / __fix_zero(uart3 & 0xff, 256);
#endif
}

/* Issue L2C diagnostic command */
static inline u32 l2c_diag(u32 addr)
{
	mtdcr(DCRN_L2C0_ADDR, addr);
	mtdcr(DCRN_L2C0_CMD, L2C_CMD_DIAG);
	while (!(mfdcr(DCRN_L2C0_SR) & L2C_SR_CC)) ;
	return mfdcr(DCRN_L2C0_DATA);
}

static irqreturn_t l2c_error_handler(int irq, void* dev, struct pt_regs* regs)
{
	u32 sr = mfdcr(DCRN_L2C0_SR);
	if (sr & L2C_SR_CPE){
		/* Read cache trapped address */
		u32 addr = l2c_diag(0x42000000);
		printk(KERN_EMERG "L2C: Cache Parity Error, addr[16:26] = 0x%08x\n", addr);
	}
	if (sr & L2C_SR_TPE){
		/* Read tag trapped address */
		u32 addr = l2c_diag(0x82000000) >> 16;
		printk(KERN_EMERG "L2C: Tag Parity Error, addr[16:26] = 0x%08x\n", addr);
	}

	/* Clear parity errors */
	if (sr & (L2C_SR_CPE | L2C_SR_TPE)){
		mtdcr(DCRN_L2C0_ADDR, 0);
		mtdcr(DCRN_L2C0_CMD, L2C_CMD_CCP | L2C_CMD_CTE);
	} else
		printk(KERN_EMERG "L2C: LRU error\n");

	return IRQ_HANDLED;
}

/* Enable L2 cache */
void __init ibm440gx_l2c_enable(void){
	u32 r;
	unsigned long flags;

	/* Install error handler */
	if (request_irq(87, l2c_error_handler, SA_INTERRUPT, "L2C", 0) < 0){
		printk(KERN_ERR "Cannot install L2C error handler, cache is not enabled\n");
		return;
	}

	local_irq_save(flags);
	asm volatile ("sync" ::: "memory");

	/* Disable SRAM */
	mtdcr(DCRN_SRAM0_DPC,   mfdcr(DCRN_SRAM0_DPC)   & ~SRAM_DPC_ENABLE);
	mtdcr(DCRN_SRAM0_SB0CR, mfdcr(DCRN_SRAM0_SB0CR) & ~SRAM_SBCR_BU_MASK);
	mtdcr(DCRN_SRAM0_SB1CR, mfdcr(DCRN_SRAM0_SB1CR) & ~SRAM_SBCR_BU_MASK);
	mtdcr(DCRN_SRAM0_SB2CR, mfdcr(DCRN_SRAM0_SB2CR) & ~SRAM_SBCR_BU_MASK);
	mtdcr(DCRN_SRAM0_SB3CR, mfdcr(DCRN_SRAM0_SB3CR) & ~SRAM_SBCR_BU_MASK);

	/* Enable L2_MODE without ICU/DCU */
	r = mfdcr(DCRN_L2C0_CFG) & ~(L2C_CFG_ICU | L2C_CFG_DCU | L2C_CFG_SS_MASK);
	r |= L2C_CFG_L2M | L2C_CFG_SS_256;
	mtdcr(DCRN_L2C0_CFG, r);

	mtdcr(DCRN_L2C0_ADDR, 0);

	/* Hardware Clear Command */
	mtdcr(DCRN_L2C0_CMD, L2C_CMD_HCC);
	while (!(mfdcr(DCRN_L2C0_SR) & L2C_SR_CC)) ;

	/* Clear Cache Parity and Tag Errors */
	mtdcr(DCRN_L2C0_CMD, L2C_CMD_CCP | L2C_CMD_CTE);

	/* Enable 64G snoop region starting at 0 */
	r = mfdcr(DCRN_L2C0_SNP0) & ~(L2C_SNP_BA_MASK | L2C_SNP_SSR_MASK);
	r |= L2C_SNP_SSR_32G | L2C_SNP_ESR;
	mtdcr(DCRN_L2C0_SNP0, r);

	r = mfdcr(DCRN_L2C0_SNP1) & ~(L2C_SNP_BA_MASK | L2C_SNP_SSR_MASK);
	r |= 0x80000000 | L2C_SNP_SSR_32G | L2C_SNP_ESR;
	mtdcr(DCRN_L2C0_SNP1, r);

	asm volatile ("sync" ::: "memory");

	/* Enable ICU/DCU ports */
	r = mfdcr(DCRN_L2C0_CFG);
	r &= ~(L2C_CFG_DCW_MASK | L2C_CFG_PMUX_MASK | L2C_CFG_PMIM | L2C_CFG_TPEI
		| L2C_CFG_CPEI | L2C_CFG_NAM | L2C_CFG_NBRM);
	r |= L2C_CFG_ICU | L2C_CFG_DCU | L2C_CFG_TPC | L2C_CFG_CPC | L2C_CFG_FRAN
		| L2C_CFG_CPIM | L2C_CFG_TPIM | L2C_CFG_LIM | L2C_CFG_SMCM;
	mtdcr(DCRN_L2C0_CFG, r);

	asm volatile ("sync; isync" ::: "memory");
	local_irq_restore(flags);
}

/* Disable L2 cache */
void __init ibm440gx_l2c_disable(void){
	u32 r;
	unsigned long flags;

	local_irq_save(flags);
	asm volatile ("sync" ::: "memory");

	/* Disable L2C mode */
	r = mfdcr(DCRN_L2C0_CFG) & ~(L2C_CFG_L2M | L2C_CFG_ICU | L2C_CFG_DCU);
	mtdcr(DCRN_L2C0_CFG, r);

	/* Enable SRAM */
	mtdcr(DCRN_SRAM0_DPC, mfdcr(DCRN_SRAM0_DPC) | SRAM_DPC_ENABLE);
	mtdcr(DCRN_SRAM0_SB0CR,
	      SRAM_SBCR_BAS0 | SRAM_SBCR_BS_64KB | SRAM_SBCR_BU_RW);
	mtdcr(DCRN_SRAM0_SB1CR,
	      SRAM_SBCR_BAS1 | SRAM_SBCR_BS_64KB | SRAM_SBCR_BU_RW);
	mtdcr(DCRN_SRAM0_SB2CR,
	      SRAM_SBCR_BAS2 | SRAM_SBCR_BS_64KB | SRAM_SBCR_BU_RW);
	mtdcr(DCRN_SRAM0_SB3CR,
	      SRAM_SBCR_BAS3 | SRAM_SBCR_BS_64KB | SRAM_SBCR_BU_RW);

	asm volatile ("sync; isync" ::: "memory");
	local_irq_restore(flags);
}

void __init ibm440gx_l2c_setup(struct ibm44x_clocks* p)
{
	/* Disable L2C on rev.A, rev.B and 800MHz version of rev.C,
	   enable it on all other revisions
	 */
	if (strcmp(cur_cpu_spec[0]->cpu_name, "440GX Rev. A") == 0 ||
			strcmp(cur_cpu_spec[0]->cpu_name, "440GX Rev. B") == 0
			|| (strcmp(cur_cpu_spec[0]->cpu_name, "440GX Rev. C")
				== 0 && p->cpu > 667000000))
		ibm440gx_l2c_disable();
	else
		ibm440gx_l2c_enable();
}

int __init ibm440gx_get_eth_grp(void)
{
	return (SDR_READ(DCRN_SDR_PFC1) & DCRN_SDR_PFC1_EPS) >> DCRN_SDR_PFC1_EPS_SHIFT;
}

void __init ibm440gx_set_eth_grp(int group)
{
	SDR_WRITE(DCRN_SDR_PFC1, (SDR_READ(DCRN_SDR_PFC1) & ~DCRN_SDR_PFC1_EPS) | (group << DCRN_SDR_PFC1_EPS_SHIFT));
}

void __init ibm440gx_tah_enable(void)
{
	/* Enable TAH0 and TAH1 */
	SDR_WRITE(DCRN_SDR_MFR,SDR_READ(DCRN_SDR_MFR) &
			~DCRN_SDR_MFR_TAH0);
	SDR_WRITE(DCRN_SDR_MFR,SDR_READ(DCRN_SDR_MFR) &
			~DCRN_SDR_MFR_TAH1);
}

int ibm440gx_show_cpuinfo(struct seq_file *m){

	u32 l2c_cfg = mfdcr(DCRN_L2C0_CFG);
	const char* s;
	if (l2c_cfg & L2C_CFG_L2M){
	    switch (l2c_cfg & (L2C_CFG_ICU | L2C_CFG_DCU)){
		case L2C_CFG_ICU: s = "I-Cache only";    break;
		case L2C_CFG_DCU: s = "D-Cache only";    break;
		default:	  s = "I-Cache/D-Cache"; break;
	    }
	}
	else
	    s = "disabled";

	seq_printf(m, "L2-Cache\t: %s (0x%08x 0x%08x)\n", s,
	    l2c_cfg, mfdcr(DCRN_L2C0_SR));

	return 0;
}

