/*
 * Copyright (C) ST-Ericsson SA 2010
 *
 * License Terms: GNU General Public License v2
 * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
 */

#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/mfd/ab8500.h>

/*
 * This funtion writes to any AB8500 registers using
 * SPI protocol &  before it writes it packs the data
 * in the below 24 bit frame format
 *
 *	 *|------------------------------------|
 *	 *| 23|22...18|17.......10|9|8|7......0|
 *	 *| r/w  bank       adr          data  |
 *	 * ------------------------------------
 *
 * This function shouldn't be called from interrupt
 * context
 */
static int ab8500_spi_write(struct ab8500 *ab8500, u16 addr, u8 data)
{
	struct spi_device *spi = container_of(ab8500->dev, struct spi_device,
					      dev);
	unsigned long spi_data = addr << 10 | data;
	struct spi_transfer xfer;
	struct spi_message msg;

	ab8500->tx_buf[0] = spi_data;
	ab8500->rx_buf[0] = 0;

	xfer.tx_buf	= ab8500->tx_buf;
	xfer.rx_buf	= NULL;
	xfer.len	= sizeof(unsigned long);

	spi_message_init(&msg);
	spi_message_add_tail(&xfer, &msg);

	return spi_sync(spi, &msg);
}

static int ab8500_spi_read(struct ab8500 *ab8500, u16 addr)
{
	struct spi_device *spi = container_of(ab8500->dev, struct spi_device,
					      dev);
	unsigned long spi_data = 1 << 23 | addr << 10;
	struct spi_transfer xfer;
	struct spi_message msg;
	int ret;

	ab8500->tx_buf[0] = spi_data;
	ab8500->rx_buf[0] = 0;

	xfer.tx_buf	= ab8500->tx_buf;
	xfer.rx_buf	= ab8500->rx_buf;
	xfer.len	= sizeof(unsigned long);

	spi_message_init(&msg);
	spi_message_add_tail(&xfer, &msg);

	ret = spi_sync(spi, &msg);
	if (!ret)
		/*
		 * Only the 8 lowermost bytes are
		 * defined with value, the rest may
		 * vary depending on chip/board noise.
		 */
		ret = ab8500->rx_buf[0] & 0xFFU;

	return ret;
}

static int __devinit ab8500_spi_probe(struct spi_device *spi)
{
	struct ab8500 *ab8500;
	int ret;

	spi->bits_per_word = 24;
	ret = spi_setup(spi);
	if (ret < 0)
		return ret;

	ab8500 = kzalloc(sizeof *ab8500, GFP_KERNEL);
	if (!ab8500)
		return -ENOMEM;

	ab8500->dev = &spi->dev;
	ab8500->irq = spi->irq;

	ab8500->read = ab8500_spi_read;
	ab8500->write = ab8500_spi_write;

	spi_set_drvdata(spi, ab8500);

	ret = ab8500_init(ab8500);
	if (ret)
		kfree(ab8500);

	return ret;
}

static int __devexit ab8500_spi_remove(struct spi_device *spi)
{
	struct ab8500 *ab8500 = spi_get_drvdata(spi);

	ab8500_exit(ab8500);
	kfree(ab8500);

	return 0;
}

static struct spi_driver ab8500_spi_driver = {
	.driver = {
		.name = "ab8500",
		.owner = THIS_MODULE,
	},
	.probe	= ab8500_spi_probe,
	.remove	= __devexit_p(ab8500_spi_remove)
};

static int __init ab8500_spi_init(void)
{
	return spi_register_driver(&ab8500_spi_driver);
}
subsys_initcall(ab8500_spi_init);

static void __exit ab8500_spi_exit(void)
{
	spi_unregister_driver(&ab8500_spi_driver);
}
module_exit(ab8500_spi_exit);

MODULE_AUTHOR("Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com");
MODULE_DESCRIPTION("AB8500 SPI");
MODULE_LICENSE("GPL v2");
