/*
 *	Copyright (c) 2001 Maciej W. Rozycki
 *
 *	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.
 *
 *	$Id: ms02-nv.c,v 1.8 2005/01/05 18:05:12 dwmw2 Exp $
 */

#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mtd/mtd.h>
#include <linux/slab.h>
#include <linux/types.h>

#include <asm/addrspace.h>
#include <asm/bootinfo.h>
#include <asm/dec/ioasic_addrs.h>
#include <asm/dec/kn02.h>
#include <asm/dec/kn03.h>
#include <asm/io.h>
#include <asm/paccess.h>

#include "ms02-nv.h"


static char version[] __initdata =
	"ms02-nv.c: v.1.0.0  13 Aug 2001  Maciej W. Rozycki.\n";

MODULE_AUTHOR("Maciej W. Rozycki <macro@linux-mips.org>");
MODULE_DESCRIPTION("DEC MS02-NV NVRAM module driver");
MODULE_LICENSE("GPL");


/*
 * Addresses we probe for an MS02-NV at.  Modules may be located
 * at any 8MiB boundary within a 0MiB up to 112MiB range or at any 32MiB
 * boundary within a 0MiB up to 448MiB range.  We don't support a module
 * at 0MiB, though.
 */
static ulong ms02nv_addrs[] __initdata = {
	0x07000000, 0x06800000, 0x06000000, 0x05800000, 0x05000000,
	0x04800000, 0x04000000, 0x03800000, 0x03000000, 0x02800000,
	0x02000000, 0x01800000, 0x01000000, 0x00800000
};

static const char ms02nv_name[] = "DEC MS02-NV NVRAM";
static const char ms02nv_res_diag_ram[] = "Diagnostic RAM";
static const char ms02nv_res_user_ram[] = "General-purpose RAM";
static const char ms02nv_res_csr[] = "Control and status register";

static struct mtd_info *root_ms02nv_mtd;


static int ms02nv_read(struct mtd_info *mtd, loff_t from,
			size_t len, size_t *retlen, u_char *buf)
{
	struct ms02nv_private *mp = mtd->priv;

	if (from + len > mtd->size)
		return -EINVAL;

	memcpy(buf, mp->uaddr + from, len);
	*retlen = len;

	return 0;
}

static int ms02nv_write(struct mtd_info *mtd, loff_t to,
			size_t len, size_t *retlen, const u_char *buf)
{
	struct ms02nv_private *mp = mtd->priv;

	if (to + len > mtd->size)
		return -EINVAL;

	memcpy(mp->uaddr + to, buf, len);
	*retlen = len;

	return 0;
}


static inline uint ms02nv_probe_one(ulong addr)
{
	ms02nv_uint *ms02nv_diagp;
	ms02nv_uint *ms02nv_magicp;
	uint ms02nv_diag;
	uint ms02nv_magic;
	size_t size;

	int err;

	/*
	 * The firmware writes MS02NV_ID at MS02NV_MAGIC and also
	 * a diagnostic status at MS02NV_DIAG.
	 */
	ms02nv_diagp = (ms02nv_uint *)(KSEG1ADDR(addr + MS02NV_DIAG));
	ms02nv_magicp = (ms02nv_uint *)(KSEG1ADDR(addr + MS02NV_MAGIC));
	err = get_dbe(ms02nv_magic, ms02nv_magicp);
	if (err)
		return 0;
	if (ms02nv_magic != MS02NV_ID)
		return 0;

	ms02nv_diag = *ms02nv_diagp;
	size = (ms02nv_diag & MS02NV_DIAG_SIZE_MASK) << MS02NV_DIAG_SIZE_SHIFT;
	if (size > MS02NV_CSR)
		size = MS02NV_CSR;

	return size;
}

static int __init ms02nv_init_one(ulong addr)
{
	struct mtd_info *mtd;
	struct ms02nv_private *mp;
	struct resource *mod_res;
	struct resource *diag_res;
	struct resource *user_res;
	struct resource *csr_res;
	ulong fixaddr;
	size_t size, fixsize;

	static int version_printed;

	int ret = -ENODEV;

	/* The module decodes 8MiB of address space. */
	mod_res = kmalloc(sizeof(*mod_res), GFP_KERNEL);
	if (!mod_res)
		return -ENOMEM;

	memset(mod_res, 0, sizeof(*mod_res));
	mod_res->name = ms02nv_name;
	mod_res->start = addr;
	mod_res->end = addr + MS02NV_SLOT_SIZE - 1;
	mod_res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
	if (request_resource(&iomem_resource, mod_res) < 0)
		goto err_out_mod_res;

	size = ms02nv_probe_one(addr);
	if (!size)
		goto err_out_mod_res_rel;

	if (!version_printed) {
		printk(KERN_INFO "%s", version);
		version_printed = 1;
	}

	ret = -ENOMEM;
	mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
	if (!mtd)
		goto err_out_mod_res_rel;
	memset(mtd, 0, sizeof(*mtd));
	mp = kmalloc(sizeof(*mp), GFP_KERNEL);
	if (!mp)
		goto err_out_mtd;
	memset(mp, 0, sizeof(*mp));

	mtd->priv = mp;
	mp->resource.module = mod_res;

	/* Firmware's diagnostic NVRAM area. */
	diag_res = kmalloc(sizeof(*diag_res), GFP_KERNEL);
	if (!diag_res)
		goto err_out_mp;

	memset(diag_res, 0, sizeof(*diag_res));
	diag_res->name = ms02nv_res_diag_ram;
	diag_res->start = addr;
	diag_res->end = addr + MS02NV_RAM - 1;
	diag_res->flags = IORESOURCE_BUSY;
	request_resource(mod_res, diag_res);

	mp->resource.diag_ram = diag_res;

	/* User-available general-purpose NVRAM area. */
	user_res = kmalloc(sizeof(*user_res), GFP_KERNEL);
	if (!user_res)
		goto err_out_diag_res;

	memset(user_res, 0, sizeof(*user_res));
	user_res->name = ms02nv_res_user_ram;
	user_res->start = addr + MS02NV_RAM;
	user_res->end = addr + size - 1;
	user_res->flags = IORESOURCE_BUSY;
	request_resource(mod_res, user_res);

	mp->resource.user_ram = user_res;

	/* Control and status register. */
	csr_res = kmalloc(sizeof(*csr_res), GFP_KERNEL);
	if (!csr_res)
		goto err_out_user_res;

	memset(csr_res, 0, sizeof(*csr_res));
	csr_res->name = ms02nv_res_csr;
	csr_res->start = addr + MS02NV_CSR;
	csr_res->end = addr + MS02NV_CSR + 3;
	csr_res->flags = IORESOURCE_BUSY;
	request_resource(mod_res, csr_res);

	mp->resource.csr = csr_res;

	mp->addr = phys_to_virt(addr);
	mp->size = size;

	/*
	 * Hide the firmware's diagnostic area.  It may get destroyed
	 * upon a reboot.  Take paging into account for mapping support.
	 */
	fixaddr = (addr + MS02NV_RAM + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
	fixsize = (size - (fixaddr - addr)) & ~(PAGE_SIZE - 1);
	mp->uaddr = phys_to_virt(fixaddr);

	mtd->type = MTD_RAM;
	mtd->flags = MTD_CAP_RAM | MTD_XIP;
	mtd->size = fixsize;
	mtd->name = (char *)ms02nv_name;
	mtd->owner = THIS_MODULE;
	mtd->read = ms02nv_read;
	mtd->write = ms02nv_write;

	ret = -EIO;
	if (add_mtd_device(mtd)) {
		printk(KERN_ERR
			"ms02-nv: Unable to register MTD device, aborting!\n");
		goto err_out_csr_res;
	}

	printk(KERN_INFO "mtd%d: %s at 0x%08lx, size %uMiB.\n",
		mtd->index, ms02nv_name, addr, size >> 20);

	mp->next = root_ms02nv_mtd;
	root_ms02nv_mtd = mtd;

	return 0;


err_out_csr_res:
	release_resource(csr_res);
	kfree(csr_res);
err_out_user_res:
	release_resource(user_res);
	kfree(user_res);
err_out_diag_res:
	release_resource(diag_res);
	kfree(diag_res);
err_out_mp:
	kfree(mp);
err_out_mtd:
	kfree(mtd);
err_out_mod_res_rel:
	release_resource(mod_res);
err_out_mod_res:
	kfree(mod_res);
	return ret;
}

static void __exit ms02nv_remove_one(void)
{
	struct mtd_info *mtd = root_ms02nv_mtd;
	struct ms02nv_private *mp = mtd->priv;

	root_ms02nv_mtd = mp->next;

	del_mtd_device(mtd);

	release_resource(mp->resource.csr);
	kfree(mp->resource.csr);
	release_resource(mp->resource.user_ram);
	kfree(mp->resource.user_ram);
	release_resource(mp->resource.diag_ram);
	kfree(mp->resource.diag_ram);
	release_resource(mp->resource.module);
	kfree(mp->resource.module);
	kfree(mp);
	kfree(mtd);
}


static int __init ms02nv_init(void)
{
	volatile u32 *csr;
	uint stride = 0;
	int count = 0;
	int i;

	switch (mips_machtype) {
	case MACH_DS5000_200:
		csr = (volatile u32 *)KN02_CSR_BASE;
		if (*csr & KN02_CSR_BNK32M)
			stride = 2;
		break;
	case MACH_DS5000_2X0:
	case MACH_DS5900:
		csr = (volatile u32 *)KN03_MCR_BASE;
		if (*csr & KN03_MCR_BNK32M)
			stride = 2;
		break;
	default:
		return -ENODEV;
		break;
	}

	for (i = 0; i < (sizeof(ms02nv_addrs) / sizeof(*ms02nv_addrs)); i++)
		if (!ms02nv_init_one(ms02nv_addrs[i] << stride))
			count++;

	return (count > 0) ? 0 : -ENODEV;
}

static void __exit ms02nv_cleanup(void)
{
	while (root_ms02nv_mtd)
		ms02nv_remove_one();
}


module_init(ms02nv_init);
module_exit(ms02nv_cleanup);
