/*
 * Common code for the boards based on Freescale MPC52xx embedded CPU.
 *
 * 
 * Maintainer : Sylvain Munaut <tnt@246tNt.com>
 *
 * Support for other bootloaders than UBoot by Dale Farnsworth 
 * <dfarnsworth@mvista.com>
 * 
 * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
 * Copyright (C) 2003 Montavista Software, Inc
 * 
 * This file is licensed under the terms of the GNU General Public License
 * version 2. This program is licensed "as is" without any warranty of any
 * kind, whether express or implied.
 */


#include <asm/io.h>
#include <asm/time.h>
#include <asm/mpc52xx.h>
#include <asm/mpc52xx_psc.h>
#include <asm/pgtable.h>
#include <asm/ppcboot.h>

#include <syslib/mpc52xx_pci.h>

extern bd_t __res;

static int core_mult[] = {		/* CPU Frequency multiplier, taken    */
	0,  0,  0,  10, 20, 20, 25, 45,	/* from the datasheet used to compute */
	30, 55, 40, 50, 0,  60, 35, 0,	/* CPU frequency from XLB freq and    */
	30, 25, 65, 10, 70, 20, 75, 45,	/* external jumper config             */
	0,  55, 40, 50, 80, 60, 35, 0
};

void
mpc52xx_restart(char *cmd)
{
	struct mpc52xx_gpt __iomem *gpt0 = MPC52xx_VA(MPC52xx_GPTx_OFFSET(0));

	local_irq_disable();

	/* Turn on the watchdog and wait for it to expire. It effectively
	  does a reset */
	out_be32(&gpt0->count, 0x000000ff);
	out_be32(&gpt0->mode, 0x00009004);

	while (1);
}

void
mpc52xx_halt(void)
{
	local_irq_disable();

	while (1);
}

void
mpc52xx_power_off(void)
{
	/* By default we don't have any way of shut down.
	   If a specific board wants to, it can set the power down
	   code to any hardware implementation dependent code */
	mpc52xx_halt();
}


void __init
mpc52xx_set_bat(void)
{
	/* Set BAT 2 to map the 0xf0000000 area */
	/* This mapping is used during mpc52xx_progress,
	 * mpc52xx_find_end_of_memory, and UARTs/GPIO access for debug
	 */
	mb();
	mtspr(SPRN_DBAT2U, 0xf0001ffe);
	mtspr(SPRN_DBAT2L, 0xf000002a);
	mb();
}

void __init
mpc52xx_map_io(void)
{
	/* Here we map the MBAR and the whole upper zone. MBAR is only
	   64k but we can't map only 64k with BATs. Map the whole
	   0xf0000000 range is ok and helps eventual lpb devices placed there */
	io_block_mapping(
		MPC52xx_MBAR_VIRT, MPC52xx_MBAR, 0x10000000, _PAGE_IO);
}


#ifdef CONFIG_SERIAL_TEXT_DEBUG
#ifndef MPC52xx_PF_CONSOLE_PORT
#error "mpc52xx PSC for console not selected"
#endif

static void
mpc52xx_psc_putc(struct mpc52xx_psc __iomem *psc, unsigned char c)
{
	while (!(in_be16(&psc->mpc52xx_psc_status) &
	         MPC52xx_PSC_SR_TXRDY));
	out_8(&psc->mpc52xx_psc_buffer_8, c);
}

void
mpc52xx_progress(char *s, unsigned short hex)
{
	char c;
	struct mpc52xx_psc __iomem *psc;

	psc = MPC52xx_VA(MPC52xx_PSCx_OFFSET(MPC52xx_PF_CONSOLE_PORT));

	while ((c = *s++) != 0) {
		if (c == '\n')
			mpc52xx_psc_putc(psc, '\r');
		mpc52xx_psc_putc(psc, c);
	}

	mpc52xx_psc_putc(psc, '\r');
	mpc52xx_psc_putc(psc, '\n');
}

#endif  /* CONFIG_SERIAL_TEXT_DEBUG */


unsigned long __init
mpc52xx_find_end_of_memory(void)
{
	u32 ramsize = __res.bi_memsize;

	/*
	 * if bootloader passed a memsize, just use it
	 * else get size from sdram config registers
	 */
	if (ramsize == 0) {
		struct mpc52xx_mmap_ctl __iomem *mmap_ctl;
		u32 sdram_config_0, sdram_config_1;

		/* Temp BAT2 mapping active when this is called ! */
		mmap_ctl = MPC52xx_VA(MPC52xx_MMAP_CTL_OFFSET);

		sdram_config_0 = in_be32(&mmap_ctl->sdram0);
		sdram_config_1 = in_be32(&mmap_ctl->sdram1);

		if ((sdram_config_0 & 0x1f) >= 0x13)
			ramsize = 1 << ((sdram_config_0 & 0xf) + 17);

		if (((sdram_config_1 & 0x1f) >= 0x13) &&
				((sdram_config_1 & 0xfff00000) == ramsize))
			ramsize += 1 << ((sdram_config_1 & 0xf) + 17);
	}

	return ramsize;
}

void __init
mpc52xx_calibrate_decr(void)
{
	int current_time, previous_time;
	int tbl_start, tbl_end;
	unsigned int xlbfreq, cpufreq, ipbfreq, pcifreq, divisor;

	xlbfreq = __res.bi_busfreq;
	/* if bootloader didn't pass bus frequencies, calculate them */
	if (xlbfreq == 0) {
		/* Get RTC & Clock manager modules */
		struct mpc52xx_rtc __iomem *rtc;
		struct mpc52xx_cdm __iomem *cdm;

		rtc = ioremap(MPC52xx_PA(MPC52xx_RTC_OFFSET), MPC52xx_RTC_SIZE);
		cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);

		if ((rtc==NULL) || (cdm==NULL))
			panic("Can't ioremap RTC/CDM while computing bus freq");

		/* Count bus clock during 1/64 sec */
		out_be32(&rtc->dividers, 0x8f1f0000);	/* Set RTC 64x faster */
		previous_time = in_be32(&rtc->time);
		while ((current_time = in_be32(&rtc->time)) == previous_time) ;
		tbl_start = get_tbl();
		previous_time = current_time;
		while ((current_time = in_be32(&rtc->time)) == previous_time) ;
		tbl_end = get_tbl();
		out_be32(&rtc->dividers, 0xffff0000);	/* Restore RTC */

		/* Compute all frequency from that & CDM settings */
		xlbfreq = (tbl_end - tbl_start) << 8;
		cpufreq = (xlbfreq * core_mult[in_be32(&cdm->rstcfg)&0x1f])/10;
		ipbfreq = (in_8(&cdm->ipb_clk_sel) & 1) ?
					xlbfreq / 2 : xlbfreq;
		switch (in_8(&cdm->pci_clk_sel) & 3) {
		case 0:
			pcifreq = ipbfreq;
			break;
		case 1:
			pcifreq = ipbfreq / 2;
			break;
		default:
			pcifreq = xlbfreq / 4;
			break;
		}
		__res.bi_busfreq = xlbfreq;
		__res.bi_intfreq = cpufreq;
		__res.bi_ipbfreq = ipbfreq;
		__res.bi_pcifreq = pcifreq;

		/* Release mapping */
		iounmap(rtc);
		iounmap(cdm);
	}

	divisor = 4;

	tb_ticks_per_jiffy = xlbfreq / HZ / divisor;
	tb_to_us = mulhwu_scale_factor(xlbfreq / divisor, 1000000);
}


void __init
mpc52xx_setup_cpu(void)
{
	struct mpc52xx_cdm  __iomem *cdm;
	struct mpc52xx_xlb  __iomem *xlb;

	/* Map zones */
	cdm  = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);
	xlb  = ioremap(MPC52xx_PA(MPC52xx_XLB_OFFSET), MPC52xx_XLB_SIZE);

	if (!cdm || !xlb) {
		printk(KERN_ERR __FILE__ ": "
			"Error while mapping CDM/XLB during "
			"mpc52xx_setup_cpu\n");
		goto unmap_regs;
	}

	/* Use internal 48 Mhz */
	out_8(&cdm->ext_48mhz_en, 0x00);
	out_8(&cdm->fd_enable, 0x01);
	if (in_be32(&cdm->rstcfg) & 0x40)	/* Assumes 33Mhz clock */
		out_be16(&cdm->fd_counters, 0x0001);
	else
		out_be16(&cdm->fd_counters, 0x5555);

	/* Configure the XLB Arbiter priorities */
	out_be32(&xlb->master_pri_enable, 0xff);
	out_be32(&xlb->master_priority, 0x11111111);

	/* Enable ram snooping for 1GB window */
	out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_SNOOP);
	out_be32(&xlb->snoop_window, MPC52xx_PCI_TARGET_MEM | 0x1d);

	/* Disable XLB pipelining */
	/* (cfr errate 292. We could do this only just before ATA PIO
	    transaction and re-enable it after ...) */
	out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_PLDIS);

	/* Unmap reg zone */
unmap_regs:
	if (cdm)  iounmap(cdm);
	if (xlb)  iounmap(xlb);
}


int mpc52xx_match_psc_function(int psc_idx, const char *func)
{
	struct mpc52xx_psc_func *cf = mpc52xx_psc_functions;

	while ((cf->id != -1) && (cf->func != NULL)) {
		if ((cf->id == psc_idx) && !strcmp(cf->func,func))
			return 1;
		cf++;
	}

	return 0;
}
