Commit | Line | Data |
---|---|---|
36e52873 MO |
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; | |
36ab08ee | 35 | u32 tx_buf; |
36e52873 MO |
36 | |
37 | tx_buf = spi_data; | |
36e52873 MO |
38 | |
39 | xfer.tx_buf = &tx_buf; | |
40 | xfer.rx_buf = NULL; | |
41 | xfer.len = sizeof(unsigned long); | |
42 | xfer.bits_per_word = 24; | |
43 | ||
44 | spi_message_init(&msg); | |
45 | spi_message_add_tail(&xfer, &msg); | |
46 | ||
47 | ret = spi_sync(spi, &msg); | |
48 | return ret; | |
49 | } | |
50 | ||
51 | static int tps65912_spi_read(struct tps65912 *tps65912, u8 addr, | |
52 | int bytes, void *dest) | |
53 | { | |
54 | struct spi_device *spi = tps65912->control_data; | |
55 | /* bit 23 is the read/write bit */ | |
56 | unsigned long spi_data = 0 << 23 | addr << 15; | |
57 | struct spi_transfer xfer; | |
58 | struct spi_message msg; | |
59 | int ret; | |
60 | u8 *data = (u8 *) dest; | |
61 | u32 tx_buf, rx_buf; | |
62 | ||
63 | tx_buf = spi_data; | |
64 | rx_buf = 0; | |
65 | ||
66 | xfer.tx_buf = &tx_buf; | |
67 | xfer.rx_buf = &rx_buf; | |
68 | xfer.len = sizeof(unsigned long); | |
69 | xfer.bits_per_word = 24; | |
70 | ||
71 | spi_message_init(&msg); | |
72 | spi_message_add_tail(&xfer, &msg); | |
73 | ||
74 | if (spi == NULL) | |
75 | return 0; | |
76 | ||
77 | ret = spi_sync(spi, &msg); | |
78 | if (ret == 0) | |
79 | *data = (u8) (rx_buf & 0xFF); | |
80 | return ret; | |
81 | } | |
82 | ||
f791be49 | 83 | static int tps65912_spi_probe(struct spi_device *spi) |
36e52873 MO |
84 | { |
85 | struct tps65912 *tps65912; | |
86 | ||
b3fff177 LJ |
87 | tps65912 = devm_kzalloc(&spi->dev, |
88 | sizeof(struct tps65912), GFP_KERNEL); | |
36e52873 MO |
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 | ||
4740f73f | 102 | static int tps65912_spi_remove(struct spi_device *spi) |
36e52873 MO |
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", | |
36e52873 MO |
114 | }, |
115 | .probe = tps65912_spi_probe, | |
84449216 | 116 | .remove = tps65912_spi_remove, |
36e52873 MO |
117 | }; |
118 | ||
119 | static int __init tps65912_spi_init(void) | |
120 | { | |
121 | int ret; | |
122 | ||
123 | ret = spi_register_driver(&tps65912_spi_driver); | |
124 | if (ret != 0) | |
125 | pr_err("Failed to register TPS65912 SPI driver: %d\n", ret); | |
126 | ||
127 | return 0; | |
128 | } | |
129 | /* init early so consumer devices can complete system boot */ | |
130 | subsys_initcall(tps65912_spi_init); | |
131 | ||
132 | static void __exit tps65912_spi_exit(void) | |
133 | { | |
134 | spi_unregister_driver(&tps65912_spi_driver); | |
135 | } | |
136 | module_exit(tps65912_spi_exit); | |
137 | ||
138 | MODULE_AUTHOR("Margarita Olaya <magi@slimlogic.co.uk>"); | |
139 | MODULE_DESCRIPTION("SPI support for TPS65912 chip family mfd"); | |
140 | MODULE_LICENSE("GPL"); |