diff options
author | Uwe Kleine-König <u.kleine-koenig@pengutronix.de> | 2010-06-30 12:16:24 +0200 |
---|---|---|
committer | Uwe Kleine-König <u.kleine-koenig@pengutronix.de> | 2010-07-26 14:27:25 +0200 |
commit | 2dcf78c0eeae3bd07082821557014f25f02ca2e9 (patch) | |
tree | 8ca5c4c7f35c9a9ab07fcd9732124c905e609aa1 /drivers/mfd/ab8500-spi.c | |
parent | 6b6322676add0fa2713d0ec89a28390fd4d907f5 (diff) | |
parent | 5109a4597f7e758b8d20694392d0361a0b4c43b1 (diff) |
Merge branch 'imx/for-2.6.36' of git://git.pengutronix.de/git/ukl/linux-2.6 into HEAD
There are some more conflicts than detected by git, namely support for
the newly added cpuimx machines needed to be converted to dynamic device
registration.
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Conflicts:
arch/arm/mach-imx/Makefile
arch/arm/mach-imx/devices.c
arch/arm/mach-imx/devices.h
arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
arch/arm/mach-mx2/Kconfig
arch/arm/mach-mx25/Makefile
arch/arm/mach-mx25/devices.c
arch/arm/plat-mxc/include/mach/mx25.h
arch/arm/plat-mxc/include/mach/mxc_nand.h
Diffstat (limited to 'drivers/mfd/ab8500-spi.c')
-rw-r--r-- | drivers/mfd/ab8500-spi.c | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/drivers/mfd/ab8500-spi.c b/drivers/mfd/ab8500-spi.c new file mode 100644 index 000000000000..b81d4f768ef6 --- /dev/null +++ b/drivers/mfd/ab8500-spi.c @@ -0,0 +1,133 @@ +/* + * 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) + ret = ab8500->rx_buf[0]; + + return ret; +} + +static int __devinit ab8500_spi_probe(struct spi_device *spi) +{ + struct ab8500 *ab8500; + int 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"); |