| 
									
										
										
										
											2011-06-09 14:50:00 -05:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * 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; | 
					
						
							| 
									
										
										
										
											2014-07-18 17:30:17 +05:30
										 |  |  | 	u32 tx_buf; | 
					
						
							| 
									
										
										
										
											2011-06-09 14:50:00 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	tx_buf = spi_data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-19 13:23:04 -05:00
										 |  |  | static int tps65912_spi_probe(struct spi_device *spi) | 
					
						
							| 
									
										
										
										
											2011-06-09 14:50:00 -05:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct tps65912 *tps65912; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-23 16:25:02 +01:00
										 |  |  | 	tps65912 = devm_kzalloc(&spi->dev, | 
					
						
							|  |  |  | 				sizeof(struct tps65912), GFP_KERNEL); | 
					
						
							| 
									
										
										
										
											2011-06-09 14:50:00 -05:00
										 |  |  | 	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); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-19 13:26:01 -05:00
										 |  |  | static int tps65912_spi_remove(struct spi_device *spi) | 
					
						
							| 
									
										
										
										
											2011-06-09 14:50:00 -05:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct tps65912 *tps65912 = spi_get_drvdata(spi); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tps65912_device_exit(tps65912); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct spi_driver tps65912_spi_driver = { | 
					
						
							|  |  |  | 	.driver = { | 
					
						
							|  |  |  | 		.name = "tps65912", | 
					
						
							|  |  |  | 		.owner = THIS_MODULE, | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	.probe	= tps65912_spi_probe, | 
					
						
							| 
									
										
										
										
											2012-11-19 13:20:24 -05:00
										 |  |  | 	.remove = tps65912_spi_remove, | 
					
						
							| 
									
										
										
										
											2011-06-09 14:50:00 -05:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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"); |