/*
 * simple driver to access what Should be the MBX device
 * on the iMX31 from LogicPD, should work on any IMX31 with the MBX chip!
 * last seen working on kernel 2.6.19.2 with out of tree patching to make imx31 work
 * freescale + community patches
 * we should get 0x1010200 from reading @ MBX_REG_BASE+MBX_REVISION 
 * Filename: reg.c
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <linux/platform_device.h>

#define MX3MBX_NAME		"mx3_mbx_regs"

/* this rev is good for the iMX31 Litekit setup from LogicPD */
#define MBX_REVISION		0x0F10

/* 
	put this somewhere in your platform code
#define MBX_REG_BASE		0xC0000000
#define MBX_REG_RANGE		0x00004000

static struct resource mxc_reg_resources[] = {
        {
        .start = MBX_REG_BASE,
        .end = MBX_REG_BASE + MBX_REG_RANGE - 1,
        .flags = IORESOURCE_MEM },
};

static struct platform_device mxc_reg_device = {
        .name           = "mx3_mbx_regs",
        .id             = 0,
        .num_resources  = ARRAY_SIZE(mxc_reg_resources),
        .resource       = mxc_reg_resources,

        .dev = {
                .coherent_dma_mask = 0xFFFFFFFF,
        },
};
	be sure to register it:
		platform_device_register(&mxc_reg_device);
*/

struct mx3reg_data {
        void __iomem	*	reg_base;
        struct device	*	dev;
};

static u32 mx3reg_read_reg(struct mx3reg_data *mx3reg, unsigned long reg)
{
//        return __raw_readl(mx3reg->reg_base + reg);
//        return readl_relaxed(mx3reg->reg_base + reg);
        return readl(mx3reg->reg_base + reg);
}

static int reg_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct resource *mbx_reg;
	struct mx3reg_data *mx3reg;

	u32 regread;
	int ret;

	mbx_reg = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!mbx_reg) {
		printk(KERN_CRIT "Failed to locate resources..\n");
		return -EINVAL;
	}

	mx3reg = kzalloc(sizeof(*mx3reg), GFP_KERNEL);

	if(!mx3reg)
		return -ENOMEM;

	mx3reg->reg_base = ioremap(mbx_reg->start, resource_size(mbx_reg));
	if (!mx3reg->reg_base) {
		ret = -ENOMEM;
		goto eremap;
        }

	mx3reg->dev = dev;
        platform_set_drvdata(pdev, mx3reg);

	printk(KERN_CRIT "reg_probe(%s)\n", MX3MBX_NAME);
	printk(KERN_CRIT "Address: from 0x%08X to 0x%08lX\n",
		 mbx_reg->start, (unsigned long)mx3reg->reg_base);

	regread = mx3reg_read_reg(mx3reg, MBX_REVISION);
	printk(KERN_CRIT "MBX_REVISION: 0x%.8X\n", regread);

	return 0;

eremap:
	kfree(mx3reg);
        dev_err(dev, "mx3reg: failed to register registers!\n");

	return ret;
}

static int reg_remove(struct platform_device *dev)
{
        struct mx3reg_data *mx3reg = platform_get_drvdata(dev);

	printk(KERN_CRIT "reg_remove\n");

        iounmap(mx3reg->reg_base);
        kfree(mx3reg);

	return 0;
}

static struct platform_driver reg_driver = {
	.driver = {
		.name = MX3MBX_NAME,
	},
	.probe = reg_probe,
	.remove = reg_remove,
};

static int __init reg_init(void)
{
	int ret;

	ret = platform_driver_register(&reg_driver);
	return ret;
}

static void __exit reg_exit(void)
{
	platform_driver_unregister(&reg_driver);
}

module_init(reg_init);
module_exit(reg_exit);

MODULE_AUTHOR("Chris");
MODULE_DESCRIPTION("MX3 MBX Reg Access Driver");
MODULE_ALIAS("platform:" MX3MBX_NAME);
MODULE_LICENSE("GPL");