diff options
Diffstat (limited to 'drivers/mfd/tps65912-spi.c')
| -rw-r--r-- | drivers/mfd/tps65912-spi.c | 89 |
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 = ℞ + 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, |