diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-31 14:31:44 -1000 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-31 14:31:44 -1000 |
commit | 3da3f872aa175f59e20766ed30aaea67fd4fa7d1 (patch) | |
tree | a44697edf5eebd02b6f159a7ab824a45730134b4 /drivers/mfd/tps65912-spi.c | |
parent | 968e75fc13b6d582f42ce44172e13ba58157e11f (diff) | |
parent | e178ccb33569da17dc897a08a3865441b813bdfb (diff) |
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6
* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6: (46 commits)
mfd: Fix mismatch in twl4030 mutex lock-unlock
mfd: twl6030-pwm.c needs MODULE_LICENSE
mfd: Fix the omap-usb-host clock API usage on usbhs_disable()
mfd: Acknowledge WM8994 IRQs before reporting
mfd: Acknowlege all WM831x IRQs before we handle them
mfd: Avoid two assignments if failures happen in tps65910_i2c_probe
regulator: Storing tps65912 error codes in u8
mfd: Don't leak init_data in tps65910_i2c_probe
regulator: aat2870: Add AAT2870 regulator driver
backlight: Add AAT2870 backlight driver
mfd: Add AAT2870 mfd driver
mfd: Remove dead code from max8997-irq
mfd: Move TPS55910 Kconfig option
mfd: Fix missing stmpe kerneldoc
mfd: Fix off-by-one value range checking for tps65912_i2c_write
mfd: Add devices for WM831x clocking module
mfd: Remove comp{1,2}_threshold sysfs entries in tps65911_comparator_remove
mfd: Don't ask about the TPS65912 core driver in Kconfig
mfd: Fix off by one in WM831x IRQ code
mfd: Add tps65921 support from twl-core
...
Diffstat (limited to 'drivers/mfd/tps65912-spi.c')
-rw-r--r-- | drivers/mfd/tps65912-spi.c | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/drivers/mfd/tps65912-spi.c b/drivers/mfd/tps65912-spi.c new file mode 100644 index 00000000000..6d71e0d2574 --- /dev/null +++ b/drivers/mfd/tps65912-spi.c @@ -0,0 +1,142 @@ +/* + * tps65912-spi.c -- SPI access for TI TPS65912x PMIC + * + * Copyright 2011 Texas Instruments Inc. + * + * Author: Margarita Olaya Cabrera <magi@slimlogic.co.uk> + * + * 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. + * + * This driver is based on wm8350 implementation. + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/gpio.h> +#include <linux/spi/spi.h> +#include <linux/mfd/core.h> +#include <linux/mfd/tps65912.h> + +static int tps65912_spi_write(struct tps65912 *tps65912, u8 addr, + int bytes, void *src) +{ + struct spi_device *spi = tps65912->control_data; + u8 *data = (u8 *) src; + int ret; + /* bit 23 is the read/write bit */ + unsigned long spi_data = 1 << 23 | addr << 15 | *data; + struct spi_transfer xfer; + struct spi_message msg; + u32 tx_buf, rx_buf; + + tx_buf = spi_data; + rx_buf = 0; + + xfer.tx_buf = &tx_buf; + xfer.rx_buf = NULL; + xfer.len = sizeof(unsigned long); + xfer.bits_per_word = 24; + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + + ret = spi_sync(spi, &msg); + return ret; +} + +static int tps65912_spi_read(struct tps65912 *tps65912, u8 addr, + int bytes, void *dest) +{ + struct spi_device *spi = tps65912->control_data; + /* bit 23 is the read/write bit */ + unsigned long spi_data = 0 << 23 | addr << 15; + struct spi_transfer xfer; + struct spi_message msg; + int ret; + u8 *data = (u8 *) dest; + u32 tx_buf, rx_buf; + + tx_buf = spi_data; + rx_buf = 0; + + xfer.tx_buf = &tx_buf; + xfer.rx_buf = &rx_buf; + xfer.len = sizeof(unsigned long); + xfer.bits_per_word = 24; + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + + if (spi == NULL) + return 0; + + ret = spi_sync(spi, &msg); + if (ret == 0) + *data = (u8) (rx_buf & 0xFF); + return ret; +} + +static int __devinit tps65912_spi_probe(struct spi_device *spi) +{ + struct tps65912 *tps65912; + + tps65912 = kzalloc(sizeof(struct tps65912), GFP_KERNEL); + if (tps65912 == NULL) + return -ENOMEM; + + tps65912->dev = &spi->dev; + tps65912->control_data = spi; + tps65912->read = tps65912_spi_read; + tps65912->write = tps65912_spi_write; + + spi_set_drvdata(spi, tps65912); + + return tps65912_device_init(tps65912); +} + +static int __devexit tps65912_spi_remove(struct spi_device *spi) +{ + struct tps65912 *tps65912 = spi_get_drvdata(spi); + + tps65912_device_exit(tps65912); + + return 0; +} + +static struct spi_driver tps65912_spi_driver = { + .driver = { + .name = "tps65912", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = tps65912_spi_probe, + .remove = __devexit_p(tps65912_spi_remove), +}; + +static int __init tps65912_spi_init(void) +{ + int ret; + + ret = spi_register_driver(&tps65912_spi_driver); + if (ret != 0) + pr_err("Failed to register TPS65912 SPI driver: %d\n", ret); + + return 0; +} +/* init early so consumer devices can complete system boot */ +subsys_initcall(tps65912_spi_init); + +static void __exit tps65912_spi_exit(void) +{ + spi_unregister_driver(&tps65912_spi_driver); +} +module_exit(tps65912_spi_exit); + +MODULE_AUTHOR("Margarita Olaya <magi@slimlogic.co.uk>"); +MODULE_DESCRIPTION("SPI support for TPS65912 chip family mfd"); +MODULE_LICENSE("GPL"); |