summaryrefslogtreecommitdiff
path: root/drivers/mfd/tps65912-spi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd/tps65912-spi.c')
-rw-r--r--drivers/mfd/tps65912-spi.c89
1 files changed, 61 insertions, 28 deletions
diff --git a/drivers/mfd/tps65912-spi.c b/drivers/mfd/tps65912-spi.c
index b45f460d299..8aef1f0dad0 100644
--- a/drivers/mfd/tps65912-spi.c
+++ b/drivers/mfd/tps65912-spi.c
@@ -21,32 +21,32 @@
#include <linux/spi/spi.h>
#include <linux/mfd/core.h>
#include <linux/mfd/tps65912.h>
+#include <linux/of_device.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;
+ u32 tx = 1 << 23 | addr << 15 | *(u8 *)src;
struct spi_transfer xfer;
struct spi_message msg;
- u32 tx_buf, rx_buf;
- tx_buf = spi_data;
- rx_buf = 0;
+ if ((spi == NULL) || (bytes == 0))
+ return -ENODATA;
- xfer.tx_buf = &tx_buf;
- xfer.rx_buf = NULL;
- xfer.len = sizeof(unsigned long);
- xfer.bits_per_word = 24;
+ if (bytes > 1)
+ dev_err(tps65912->dev, "too many bytes to write %d\n", bytes);
+ memset(&xfer, 0, sizeof(xfer));
+ /* Do not setup the bits per transfer or the speed, as this causes the
+ driver to re-initialize, which wastes time. */
+ xfer.tx_buf = &tx;
+ xfer.len = sizeof(tx);
+ xfer.bits_per_word = 24;
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
-
- ret = spi_sync(spi, &msg);
- return ret;
+ return spi_sync(spi, &msg);
}
static int tps65912_spi_read(struct tps65912 *tps65912, u8 addr,
@@ -54,33 +54,41 @@ static int tps65912_spi_read(struct tps65912 *tps65912, u8 addr,
{
struct spi_device *spi = tps65912->control_data;
/* bit 23 is the read/write bit */
- unsigned long spi_data = 0 << 23 | addr << 15;
+ u32 tx = 0 << 23 | addr << 15;
struct spi_transfer xfer;
struct spi_message msg;
+ u32 rx;
int ret;
- u8 *data = (u8 *) dest;
- u32 tx_buf, rx_buf;
- tx_buf = spi_data;
- rx_buf = 0;
+ if ((spi == NULL) || (bytes == 0))
+ return -ENODATA;
- xfer.tx_buf = &tx_buf;
- xfer.rx_buf = &rx_buf;
- xfer.len = sizeof(unsigned long);
- xfer.bits_per_word = 24;
+ if (bytes > 1)
+ dev_err(tps65912->dev, "too many bytes to read %d\n", bytes);
+ memset(&xfer, 0, sizeof(xfer));
+ /* Do not setup the bits per transfer or the speed, as this causes the
+ driver to re-initialize, which wastes time. */
+ xfer.tx_buf = &tx;
+ xfer.rx_buf = &rx;
+ xfer.len = sizeof(tx);
+ 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);
+ if (!ret)
+ *(u8 *)dest = (u8)rx & 0xff;
return ret;
}
+#ifdef CONFIG_OF
+static struct of_device_id tps65912_of_match[] = {
+ { .compatible = "ti,tps65912" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, tps65912_of_match);
+#endif
+
static int tps65912_spi_probe(struct spi_device *spi)
{
struct tps65912 *tps65912;
@@ -94,6 +102,8 @@ static int tps65912_spi_probe(struct spi_device *spi)
tps65912->read = tps65912_spi_read;
tps65912->write = tps65912_spi_write;
+ mutex_init(&tps65912->pm_lock);
+
spi_set_drvdata(spi, tps65912);
return tps65912_device_init(tps65912);
@@ -108,10 +118,33 @@ static int tps65912_spi_remove(struct spi_device *spi)
return 0;
}
+int tps65912_spi_suspend_late(struct device *dev)
+{
+ struct tps65912 *tps65912 = dev_get_drvdata(dev);
+ if (tps65912)
+ mutex_lock(&tps65912->pm_lock);
+ return 0;
+}
+int tps65912_spi_resume_early(struct device *dev)
+{
+ struct tps65912 *tps65912 = dev_get_drvdata(dev);
+ if (tps65912)
+ mutex_unlock(&tps65912->pm_lock);
+ return 0;
+}
+
+static struct dev_pm_ops tps65912_pm_ops = {
+ .suspend_late = tps65912_spi_suspend_late,
+ .resume_early = tps65912_spi_resume_early,
+};
+
static struct spi_driver tps65912_spi_driver = {
.driver = {
.name = "tps65912",
+ .pm = &tps65912_pm_ops,
+ .bus = &spi_bus_type,
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(tps65912_of_match),
},
.probe = tps65912_spi_probe,
.remove = tps65912_spi_remove,