/*
 * Copyright (c) 2006-2008 Simtec Electronics
 *	http://armlinux.simtec.co.uk/
 *	Ben Dooks <ben@simtec.co.uk>
 *
 * S3C2412/S3C2443 (PL093 based) IO timing support
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
*/

#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/cpufreq.h>
#include <linux/seq_file.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/slab.h>

#include <linux/amba/pl093.h>

#include <asm/mach/arch.h>
#include <asm/mach/map.h>

#include <plat/cpu.h>
#include <plat/cpu-freq-core.h>
#include <plat/clock.h>

#include "s3c2412.h"

#define print_ns(x) ((x) / 10), ((x) % 10)

/**
 * s3c2412_print_timing - print timing infromation via printk.
 * @pfx: The prefix to print each line with.
 * @iot: The IO timing information
 */
static void s3c2412_print_timing(const char *pfx, struct s3c_iotimings *iot)
{
	struct s3c2412_iobank_timing *bt;
	unsigned int bank;

	for (bank = 0; bank < MAX_BANKS; bank++) {
		bt = iot->bank[bank].io_2412;
		if (!bt)
			continue;

		printk(KERN_DEBUG "%s: %d: idcy=%d.%d wstrd=%d.%d wstwr=%d,%d"
		       "wstoen=%d.%d wstwen=%d.%d wstbrd=%d.%d\n", pfx, bank,
		       print_ns(bt->idcy),
		       print_ns(bt->wstrd),
		       print_ns(bt->wstwr),
		       print_ns(bt->wstoen),
		       print_ns(bt->wstwen),
		       print_ns(bt->wstbrd));
	}
}

/**
 * to_div - turn a cycle length into a divisor setting.
 * @cyc_tns: The cycle time in 10ths of nanoseconds.
 * @clk_tns: The clock period in 10ths of nanoseconds.
 */
static inline unsigned int to_div(unsigned int cyc_tns, unsigned int clk_tns)
{
	return cyc_tns ? DIV_ROUND_UP(cyc_tns, clk_tns) : 0;
}

/**
 * calc_timing - calculate timing divisor value and check in range.
 * @hwtm: The hardware timing in 10ths of nanoseconds.
 * @clk_tns: The clock period in 10ths of nanoseconds.
 * @err: Pointer to err variable to update in event of failure.
 */
static unsigned int calc_timing(unsigned int hwtm, unsigned int clk_tns,
				unsigned int *err)
{
	unsigned int ret = to_div(hwtm, clk_tns);

	if (ret > 0xf)
		*err = -EINVAL;

	return ret;
}

/**
 * s3c2412_calc_bank - calculate the bank divisor settings.
 * @cfg: The current frequency configuration.
 * @bt: The bank timing.
 */
static int s3c2412_calc_bank(struct s3c_cpufreq_config *cfg,
			     struct s3c2412_iobank_timing *bt)
{
	unsigned int hclk = cfg->freq.hclk_tns;
	int err = 0;

	bt->smbidcyr = calc_timing(bt->idcy, hclk, &err);
	bt->smbwstrd = calc_timing(bt->wstrd, hclk, &err);
	bt->smbwstwr = calc_timing(bt->wstwr, hclk, &err);
	bt->smbwstoen = calc_timing(bt->wstoen, hclk, &err);
	bt->smbwstwen = calc_timing(bt->wstwen, hclk, &err);
	bt->smbwstbrd = calc_timing(bt->wstbrd, hclk, &err);

	return err;
}

/**
 * s3c2412_iotiming_debugfs - debugfs show io bank timing information
 * @seq: The seq_file to write output to using seq_printf().
 * @cfg: The current configuration.
 * @iob: The IO bank information to decode.
*/
void s3c2412_iotiming_debugfs(struct seq_file *seq,
			      struct s3c_cpufreq_config *cfg,
			      union s3c_iobank *iob)
{
	struct s3c2412_iobank_timing *bt = iob->io_2412;

	seq_printf(seq,
		   "\tRead: idcy=%d.%d wstrd=%d.%d wstwr=%d,%d"
		   "wstoen=%d.%d wstwen=%d.%d wstbrd=%d.%d\n",
		   print_ns(bt->idcy),
		   print_ns(bt->wstrd),
		   print_ns(bt->wstwr),
		   print_ns(bt->wstoen),
		   print_ns(bt->wstwen),
		   print_ns(bt->wstbrd));
}

/**
 * s3c2412_iotiming_calc - calculate all the bank divisor settings.
 * @cfg: The current frequency configuration.
 * @iot: The bank timing information.
 *
 * Calculate the timing information for all the banks that are
 * configured as IO, using s3c2412_calc_bank().
 */
int s3c2412_iotiming_calc(struct s3c_cpufreq_config *cfg,
			  struct s3c_iotimings *iot)
{
	struct s3c2412_iobank_timing *bt;
	int bank;
	int ret;

	for (bank = 0; bank < MAX_BANKS; bank++) {
		bt = iot->bank[bank].io_2412;
		if (!bt)
			continue;

		ret = s3c2412_calc_bank(cfg, bt);
		if (ret) {
			printk(KERN_ERR "%s: cannot calculate bank %d io\n",
			       __func__, bank);
			goto err;
		}
	}

	return 0;
 err:
	return ret;
}

/**
 * s3c2412_iotiming_set - set the timing information
 * @cfg: The current frequency configuration.
 * @iot: The bank timing information.
 *
 * Set the IO bank information from the details calculated earlier from
 * calling s3c2412_iotiming_calc().
 */
void s3c2412_iotiming_set(struct s3c_cpufreq_config *cfg,
			  struct s3c_iotimings *iot)
{
	struct s3c2412_iobank_timing *bt;
	void __iomem *regs;
	int bank;

	/* set the io timings from the specifier */

	for (bank = 0; bank < MAX_BANKS; bank++) {
		bt = iot->bank[bank].io_2412;
		if (!bt)
			continue;

		regs = S3C2412_SSMC_BANK(bank);

		__raw_writel(bt->smbidcyr, regs + SMBIDCYR);
		__raw_writel(bt->smbwstrd, regs + SMBWSTRDR);
		__raw_writel(bt->smbwstwr, regs + SMBWSTWRR);
		__raw_writel(bt->smbwstoen, regs + SMBWSTOENR);
		__raw_writel(bt->smbwstwen, regs + SMBWSTWENR);
		__raw_writel(bt->smbwstbrd, regs + SMBWSTBRDR);
	}
}

static inline unsigned int s3c2412_decode_timing(unsigned int clock, u32 reg)
{
	return (reg & 0xf) * clock;
}

static void s3c2412_iotiming_getbank(struct s3c_cpufreq_config *cfg,
				     struct s3c2412_iobank_timing *bt,
				     unsigned int bank)
{
	unsigned long clk = cfg->freq.hclk_tns;  /* ssmc clock??? */
	void __iomem *regs = S3C2412_SSMC_BANK(bank);

	bt->idcy = s3c2412_decode_timing(clk, __raw_readl(regs + SMBIDCYR));
	bt->wstrd = s3c2412_decode_timing(clk, __raw_readl(regs + SMBWSTRDR));
	bt->wstoen = s3c2412_decode_timing(clk, __raw_readl(regs + SMBWSTOENR));
	bt->wstwen = s3c2412_decode_timing(clk, __raw_readl(regs + SMBWSTWENR));
	bt->wstbrd = s3c2412_decode_timing(clk, __raw_readl(regs + SMBWSTBRDR));
}

/**
 * bank_is_io - return true if bank is (possibly) IO.
 * @bank: The bank number.
 * @bankcfg: The value of S3C2412_EBI_BANKCFG.
 */
static inline bool bank_is_io(unsigned int bank, u32 bankcfg)
{
	if (bank < 2)
		return true;

	return !(bankcfg & (1 << bank));
}

int s3c2412_iotiming_get(struct s3c_cpufreq_config *cfg,
			 struct s3c_iotimings *timings)
{
	struct s3c2412_iobank_timing *bt;
	u32 bankcfg = __raw_readl(S3C2412_EBI_BANKCFG);
	unsigned int bank;

	/* look through all banks to see what is currently set. */

	for (bank = 0; bank < MAX_BANKS; bank++) {
		if (!bank_is_io(bank, bankcfg))
			continue;

		bt = kzalloc(sizeof(struct s3c2412_iobank_timing), GFP_KERNEL);
		if (!bt) {
			printk(KERN_ERR "%s: no memory for bank\n", __func__);
			return -ENOMEM;
		}

		timings->bank[bank].io_2412 = bt;
		s3c2412_iotiming_getbank(cfg, bt, bank);
	}

	s3c2412_print_timing("get", timings);
	return 0;
}

/* this is in here as it is so small, it doesn't currently warrant a file
 * to itself. We expect that any s3c24xx needing this is going to also
 * need the iotiming support.
 */
void s3c2412_cpufreq_setrefresh(struct s3c_cpufreq_config *cfg)
{
	struct s3c_cpufreq_board *board = cfg->board;
	u32 refresh;

	WARN_ON(board == NULL);

	/* Reduce both the refresh time (in ns) and the frequency (in MHz)
	 * down to ensure that we do not overflow 32 bit numbers.
	 *
	 * This should work for HCLK up to 133MHz and refresh period up
	 * to 30usec.
	 */

	refresh = (cfg->freq.hclk / 100) * (board->refresh / 10);
	refresh = DIV_ROUND_UP(refresh, (1000 * 1000)); /* apply scale  */
	refresh &= ((1 << 16) - 1);

	s3c_freq_dbg("%s: refresh value %u\n", __func__, (unsigned int)refresh);

	__raw_writel(refresh, S3C2412_REFRESH);
}
