aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/i2c-slave.c
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
commitfcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch)
treea57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/i2c/i2c-slave.c
parent8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff)
Added missing tegra files.HEADmaster
Diffstat (limited to 'drivers/i2c/i2c-slave.c')
-rw-r--r--drivers/i2c/i2c-slave.c281
1 files changed, 281 insertions, 0 deletions
diff --git a/drivers/i2c/i2c-slave.c b/drivers/i2c/i2c-slave.c
new file mode 100644
index 00000000000..280a860cd2e
--- /dev/null
+++ b/drivers/i2c/i2c-slave.c
@@ -0,0 +1,281 @@
1/*
2 * i2c-slave.c - a device driver for the iic-slave bus interface.
3 *
4 * Copyright (c) 2009-2011, NVIDIA Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <linux/slab.h>
24#include <linux/i2c.h>
25#include <linux/i2c-slave.h>
26struct i2c_slave_priv {
27 struct i2c_adapter master_adap;
28 struct i2c_slave_adapter *slave_adap;
29 struct i2c_algorithm master_algo;
30};
31
32/**
33 * i2c_slave_send - Sends data to master. When master issues a read cycle, the
34 * data is sent by the slave.
35 * This function copies the client data into the slave tx buffer and return to
36 * client. This is not a blocking call. Data will be sent to master later once
37 * slave got the master-ready cycle transfer.
38 * if there is no sufficient space to write the client buffer, it will return
39 * error. it will not write partial data.
40 * @client: Handle to i2c-slave client.
41 * @buf: Data that will be written to the master
42 * @count: How many bytes to write.
43 *
44 * Returns negative errno, or else the number of bytes written.
45 */
46int i2c_slave_send(struct i2c_client *client, const char *buf, int count)
47{
48 struct i2c_adapter *adap = client->adapter;
49 struct i2c_slave_priv *priv = adap->algo_data;
50
51 if (!(adap->algo->functionality(adap) & I2C_FUNC_I2C_SLAVE_SUPPORT))
52 BUG();
53
54 if (priv->slave_adap->slv_algo->slave_send)
55 return priv->slave_adap->slv_algo->slave_send(priv->slave_adap,
56 buf, count);
57 return -ENODEV;
58}
59EXPORT_SYMBOL(i2c_slave_send);
60
61/**
62 * i2c_slave_get_tx_status - Get amount of data available in tx buffer. If there
63 * is still data in tx buffer then wait for given time to transfer complete
64 * for a give timeout.
65 * @client: Handle to i2c-slave client.
66 * @timeout_ms: Time to wait for transfer to complete.
67 *
68 * Returns negative errno, or else the number of bytes remaining in tx buffer.
69 */
70int i2c_slave_get_tx_status(struct i2c_client *client, int timeout_ms)
71{
72 struct i2c_adapter *adap = client->adapter;
73 struct i2c_slave_priv *priv = adap->algo_data;
74
75 if (!(adap->algo->functionality(adap) & I2C_FUNC_I2C_SLAVE_SUPPORT))
76 BUG();
77
78 if (priv->slave_adap->slv_algo->slave_get_tx_status)
79 return priv->slave_adap->slv_algo->slave_get_tx_status(
80 priv->slave_adap, timeout_ms);
81 return -ENODEV;
82}
83EXPORT_SYMBOL(i2c_slave_get_tx_status);
84
85/**
86 * i2c_slave_recv - Receive data from master. The data receive from master is
87 * stored on slave rx buffer. When this api will be called, the data will be
88 * copied from the slave rx buffer to client buffer. If requested amount (count)
89 * of data is not available then it will wait for either min_count to be receive
90 * or timeout whatever first.
91 *
92 * if timeout_ms = 0, then wait for min_count data to be read.
93 * if timoue_ms non zero then wait for the data till timeout happen.
94 * @client: Handle to i2c-slave client.
95 * @buf: Data that will be read from the master
96 * @count: How many bytes to read.
97 * @min_count: Block till read min_count of data.
98 * @timeout_ms: Time to wait for read to be complete.
99 *
100 * Returns negative errno, or else the number of bytes read.
101 */
102int i2c_slave_recv(struct i2c_client *client, char *buf, int count,
103 int min_count, int timeout_ms)
104{
105 struct i2c_adapter *adap = client->adapter;
106 struct i2c_slave_priv *priv = adap->algo_data;
107
108 if (!(adap->algo->functionality(adap) & I2C_FUNC_I2C_SLAVE_SUPPORT))
109 BUG();
110
111 if (priv->slave_adap->slv_algo->slave_recv)
112 return priv->slave_adap->slv_algo->slave_recv(priv->slave_adap,
113 buf, count, min_count, timeout_ms);
114
115 return -ENODEV;
116}
117EXPORT_SYMBOL(i2c_slave_recv);
118
119/**
120 * i2c_slave_start - Start the i2c slave to receive/transmit data.
121 * After this i2c controller starts responding master.
122 * The dummy-char will send to master if there is no data to send on slave tx
123 * buffer.
124 * @client: Handle to i2c-slave client.
125 * @dummy_char: Data which will be send to master if there is no data to be send
126 * in slave tx buffer.
127 *
128 * Returns negative errno, or else 0 for success.
129 */
130int i2c_slave_start(struct i2c_client *client, unsigned char dummy_char)
131{
132 struct i2c_adapter *adap = client->adapter;
133 struct i2c_slave_priv *priv = adap->algo_data;
134 int slave_add;
135 int is_10bit_addr;
136
137 if (!(adap->algo->functionality(adap) & I2C_FUNC_I2C_SLAVE_SUPPORT))
138 BUG();
139 slave_add = client->addr;
140 is_10bit_addr = (client->flags & I2C_CLIENT_TEN) ? 1 : 0;
141 if (priv->slave_adap->slv_algo->slave_start)
142 return priv->slave_adap->slv_algo->slave_start(priv->slave_adap,
143 slave_add, is_10bit_addr, dummy_char);
144 return -ENODEV;
145}
146EXPORT_SYMBOL(i2c_slave_start);
147
148/**
149 * i2c_slave_stop - Stop slave to receive/transmit data.
150 * After this i2c controller stops responding master.
151 * @client: Handle to i2c-slave client.
152 * @is_buffer_clear: Reset the tx and rx slave buffer or not.
153 */
154void i2c_slave_stop(struct i2c_client *client, int is_buffer_clear)
155{
156 struct i2c_adapter *adap = client->adapter;
157 struct i2c_slave_priv *priv = adap->algo_data;
158
159 if (!(adap->algo->functionality(adap) & I2C_FUNC_I2C_SLAVE_SUPPORT))
160 BUG();
161
162 if (priv->slave_adap->slv_algo->slave_stop)
163 return priv->slave_adap->slv_algo->slave_stop(priv->slave_adap,
164 is_buffer_clear);
165}
166EXPORT_SYMBOL(i2c_slave_stop);
167
168/**
169 * i2c_slave_flush_buffer - Flush the receive and transmit buffer.
170 * @client: Handle to i2c-slave client.
171 * @is_flush_tx_buffer: Reset the tx slave buffer or not.
172 * @is_flush_rx_buffer: Reset the rx slave buffer or not.
173 *
174 * Returns negative errno, or else 0 for success.
175 */
176int i2c_slave_flush_buffer(struct i2c_client *client,
177 int is_flush_tx_buffer, int is_flush_rx_buffer)
178{
179 struct i2c_adapter *adap = client->adapter;
180 struct i2c_slave_priv *priv = adap->algo_data;
181
182 if (!(adap->algo->functionality(adap) & I2C_FUNC_I2C_SLAVE_SUPPORT))
183 BUG();
184
185 if (priv->slave_adap->slv_algo->slave_flush_buffer)
186 return priv->slave_adap->slv_algo->slave_flush_buffer(
187 priv->slave_adap, is_flush_tx_buffer,
188 is_flush_rx_buffer);
189
190 return -ENODEV;
191}
192EXPORT_SYMBOL(i2c_slave_flush_buffer);
193
194/**
195 * i2c_slave_get_nack_cycle - Get the number of master read cycle on which
196 * dummy char sent. This is the way to find that how much cycle slave sent the
197 * NACK packet.
198 *
199 * @client: Handle to i2c-slave client.
200 * @is_cout_reset: Reset the nack count or not.
201 *
202 * Returns negative errno, or else 0 for success.
203 */
204int i2c_slave_get_nack_cycle(struct i2c_client *client,
205 int is_cout_reset)
206{
207 struct i2c_adapter *adap = client->adapter;
208 struct i2c_slave_priv *priv = adap->algo_data;
209
210 if (!(adap->algo->functionality(adap) & I2C_FUNC_I2C_SLAVE_SUPPORT))
211 BUG();
212
213 if (priv->slave_adap->slv_algo->slave_get_nack_cycle)
214 return priv->slave_adap->slv_algo->slave_get_nack_cycle(
215 priv->slave_adap, is_cout_reset);
216
217 return -ENODEV;
218}
219EXPORT_SYMBOL(i2c_slave_get_nack_cycle);
220
221static u32 i2c_slave_func(struct i2c_adapter *adap)
222{
223 return I2C_FUNC_I2C_SLAVE_SUPPORT;
224}
225
226int i2c_add_slave_adapter(struct i2c_slave_adapter *slv_adap, bool force_nr)
227{
228 struct i2c_slave_priv *priv;
229 int ret;
230
231 priv = kzalloc(sizeof(struct i2c_slave_priv), GFP_KERNEL);
232 if (!priv)
233 return -ENOMEM;
234
235 /* Set up private adapter data */
236 priv->slave_adap = slv_adap;
237 slv_adap->parent_data = priv;
238
239 priv->master_algo.functionality = i2c_slave_func;
240
241 /* Now fill out new adapter structure */
242 snprintf(priv->master_adap.name, sizeof(priv->master_adap.name),
243 "i2c-%d-slave", slv_adap->nr);
244 priv->master_adap.owner = THIS_MODULE;
245 priv->master_adap.class = slv_adap->class;
246 priv->master_adap.algo = &priv->master_algo;
247 priv->master_adap.algo_data = priv;
248 priv->master_adap.dev.parent = slv_adap->parent_dev;
249
250 if (force_nr) {
251 priv->master_adap.nr = slv_adap->nr;
252 ret = i2c_add_numbered_adapter(&priv->master_adap);
253 } else {
254 ret = i2c_add_adapter(&priv->master_adap);
255 }
256 if (ret < 0) {
257 dev_err(slv_adap->parent_dev,
258 "failed to add slave-adapter (error=%d)\n", ret);
259 kfree(priv);
260 return ret;
261 }
262 slv_adap->dev = &priv->master_adap.dev;
263 dev_info(slv_adap->parent_dev, "Added slave i2c bus %d\n",
264 i2c_adapter_id(&priv->master_adap));
265
266 return 0;
267}
268EXPORT_SYMBOL_GPL(i2c_add_slave_adapter);
269
270int i2c_del_slave_adapter(struct i2c_slave_adapter *slv_adap)
271{
272 struct i2c_slave_priv *priv = slv_adap->parent_data;
273 int ret;
274
275 ret = i2c_del_adapter(&priv->master_adap);
276 if (ret < 0)
277 return ret;
278 kfree(priv);
279 return 0;
280}
281EXPORT_SYMBOL_GPL(i2c_del_slave_adapter);