diff options
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 000000000000..6d71e0d25744 --- /dev/null +++ b/drivers/mfd/tps65912-spi.c | |||
@@ -0,0 +1,142 @@ | |||
1 | /* | ||
2 | * tps65912-spi.c -- SPI access for TI TPS65912x PMIC | ||
3 | * | ||
4 | * Copyright 2011 Texas Instruments Inc. | ||
5 | * | ||
6 | * Author: Margarita Olaya Cabrera <magi@slimlogic.co.uk> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | * This driver is based on wm8350 implementation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/moduleparam.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/gpio.h> | ||
21 | #include <linux/spi/spi.h> | ||
22 | #include <linux/mfd/core.h> | ||
23 | #include <linux/mfd/tps65912.h> | ||
24 | |||
25 | static int tps65912_spi_write(struct tps65912 *tps65912, u8 addr, | ||
26 | int bytes, void *src) | ||
27 | { | ||
28 | struct spi_device *spi = tps65912->control_data; | ||
29 | u8 *data = (u8 *) src; | ||
30 | int ret; | ||
31 | /* bit 23 is the read/write bit */ | ||
32 | unsigned long spi_data = 1 << 23 | addr << 15 | *data; | ||
33 | struct spi_transfer xfer; | ||
34 | struct spi_message msg; | ||
35 | u32 tx_buf, rx_buf; | ||
36 | |||
37 | tx_buf = spi_data; | ||
38 | rx_buf = 0; | ||
39 | |||
40 | xfer.tx_buf = &tx_buf; | ||
41 | xfer.rx_buf = NULL; | ||
42 | xfer.len = sizeof(unsigned long); | ||
43 | xfer.bits_per_word = 24; | ||
44 | |||
45 | spi_message_init(&msg); | ||
46 | spi_message_add_tail(&xfer, &msg); | ||
47 | |||
48 | ret = spi_sync(spi, &msg); | ||
49 | return ret; | ||
50 | } | ||
51 | |||
52 | static int tps65912_spi_read(struct tps65912 *tps65912, u8 addr, | ||
53 | int bytes, void *dest) | ||
54 | { | ||
55 | struct spi_device *spi = tps65912->control_data; | ||
56 | /* bit 23 is the read/write bit */ | ||
57 | unsigned long spi_data = 0 << 23 | addr << 15; | ||
58 | struct spi_transfer xfer; | ||
59 | struct spi_message msg; | ||
60 | int ret; | ||
61 | u8 *data = (u8 *) dest; | ||
62 | u32 tx_buf, rx_buf; | ||
63 | |||
64 | tx_buf = spi_data; | ||
65 | rx_buf = 0; | ||
66 | |||
67 | xfer.tx_buf = &tx_buf; | ||
68 | xfer.rx_buf = &rx_buf; | ||
69 | xfer.len = sizeof(unsigned long); | ||
70 | xfer.bits_per_word = 24; | ||
71 | |||
72 | spi_message_init(&msg); | ||
73 | spi_message_add_tail(&xfer, &msg); | ||
74 | |||
75 | if (spi == NULL) | ||
76 | return 0; | ||
77 | |||
78 | ret = spi_sync(spi, &msg); | ||
79 | if (ret == 0) | ||
80 | *data = (u8) (rx_buf & 0xFF); | ||
81 | return ret; | ||
82 | } | ||
83 | |||
84 | static int __devinit tps65912_spi_probe(struct spi_device *spi) | ||
85 | { | ||
86 | struct tps65912 *tps65912; | ||
87 | |||
88 | tps65912 = kzalloc(sizeof(struct tps65912), GFP_KERNEL); | ||
89 | if (tps65912 == NULL) | ||
90 | return -ENOMEM; | ||
91 | |||
92 | tps65912->dev = &spi->dev; | ||
93 | tps65912->control_data = spi; | ||
94 | tps65912->read = tps65912_spi_read; | ||
95 | tps65912->write = tps65912_spi_write; | ||
96 | |||
97 | spi_set_drvdata(spi, tps65912); | ||
98 | |||
99 | return tps65912_device_init(tps65912); | ||
100 | } | ||
101 | |||
102 | static int __devexit tps65912_spi_remove(struct spi_device *spi) | ||
103 | { | ||
104 | struct tps65912 *tps65912 = spi_get_drvdata(spi); | ||
105 | |||
106 | tps65912_device_exit(tps65912); | ||
107 | |||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | static struct spi_driver tps65912_spi_driver = { | ||
112 | .driver = { | ||
113 | .name = "tps65912", | ||
114 | .bus = &spi_bus_type, | ||
115 | .owner = THIS_MODULE, | ||
116 | }, | ||
117 | .probe = tps65912_spi_probe, | ||
118 | .remove = __devexit_p(tps65912_spi_remove), | ||
119 | }; | ||
120 | |||
121 | static int __init tps65912_spi_init(void) | ||
122 | { | ||
123 | int ret; | ||
124 | |||
125 | ret = spi_register_driver(&tps65912_spi_driver); | ||
126 | if (ret != 0) | ||
127 | pr_err("Failed to register TPS65912 SPI driver: %d\n", ret); | ||
128 | |||
129 | return 0; | ||
130 | } | ||
131 | /* init early so consumer devices can complete system boot */ | ||
132 | subsys_initcall(tps65912_spi_init); | ||
133 | |||
134 | static void __exit tps65912_spi_exit(void) | ||
135 | { | ||
136 | spi_unregister_driver(&tps65912_spi_driver); | ||
137 | } | ||
138 | module_exit(tps65912_spi_exit); | ||
139 | |||
140 | MODULE_AUTHOR("Margarita Olaya <magi@slimlogic.co.uk>"); | ||
141 | MODULE_DESCRIPTION("SPI support for TPS65912 chip family mfd"); | ||
142 | MODULE_LICENSE("GPL"); | ||