diff options
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/busses/i2c-tegra-hv-common.c | 508 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-tegra-hv-common.h | 152 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-tegra-hv.c | 324 |
3 files changed, 984 insertions, 0 deletions
diff --git a/drivers/i2c/busses/i2c-tegra-hv-common.c b/drivers/i2c/busses/i2c-tegra-hv-common.c new file mode 100644 index 000000000..db3d2e65e --- /dev/null +++ b/drivers/i2c/busses/i2c-tegra-hv-common.c | |||
@@ -0,0 +1,508 @@ | |||
1 | /* | ||
2 | * IVC based Library for I2C services. | ||
3 | * | ||
4 | * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/resource.h> | ||
18 | #include <linux/of.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/wait.h> | ||
21 | #include <linux/tegra-ivc.h> | ||
22 | #include <linux/spinlock.h> | ||
23 | #include <linux/hardirq.h> | ||
24 | #include <linux/list.h> | ||
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/skbuff.h> | ||
27 | |||
28 | #include "i2c-tegra-hv-common.h" | ||
29 | |||
30 | static int _hv_i2c_ivc_send(struct tegra_hv_i2c_comm_chan *comm_chan, | ||
31 | struct i2c_ivc_msg *msg, int size) | ||
32 | { | ||
33 | struct tegra_hv_i2c_comm_dev *comm_dev = comm_chan->hv_comm_dev; | ||
34 | unsigned long flags = 0; | ||
35 | int ret = 0; | ||
36 | |||
37 | if (!comm_chan->ivck || !msg || !size) | ||
38 | return -EINVAL; | ||
39 | |||
40 | spin_lock_irqsave(&comm_dev->ivck_tx_lock, flags); | ||
41 | |||
42 | if (!tegra_hv_ivc_can_write(comm_chan->ivck)) { | ||
43 | ret = -EBUSY; | ||
44 | goto fail; | ||
45 | } | ||
46 | |||
47 | ret = tegra_hv_ivc_write(comm_chan->ivck, msg, size); | ||
48 | if (ret != size) { | ||
49 | ret = -EIO; | ||
50 | goto fail; | ||
51 | } | ||
52 | |||
53 | fail: | ||
54 | spin_unlock_irqrestore(&comm_dev->ivck_tx_lock, flags); | ||
55 | return ret; | ||
56 | } | ||
57 | |||
58 | static inline int _hv_i2c_get_data_ptr_offset(enum i2c_ivc_msg_t type) | ||
59 | { | ||
60 | switch (type) { | ||
61 | case I2C_READ_RESPONSE: | ||
62 | case I2C_WRITE_RESPONSE: | ||
63 | return I2C_IVC_COMMON_HEADER_LEN | ||
64 | + sizeof(struct i2c_ivc_msg_tx_rx_hdr); | ||
65 | case I2C_GET_MAX_PAYLOAD_RESPONSE: | ||
66 | return I2C_IVC_COMMON_HEADER_LEN; | ||
67 | default: | ||
68 | WARN(1, "Unsupported message type\n"); | ||
69 | } | ||
70 | return -1; | ||
71 | } | ||
72 | |||
73 | static void _hv_i2c_comm_chan_cleanup(struct tegra_hv_i2c_comm_chan *comm_chan) | ||
74 | { | ||
75 | unsigned long flags; | ||
76 | |||
77 | spin_lock_irqsave(&comm_chan->lock, flags); | ||
78 | /* Free this channel up for further use */ | ||
79 | comm_chan->rcvd_data = NULL; | ||
80 | comm_chan->data_len = 0; | ||
81 | comm_chan->rcvd_err = NULL; | ||
82 | comm_chan->rx_state = I2C_RX_INIT; | ||
83 | spin_unlock_irqrestore(&comm_chan->lock, flags); | ||
84 | } | ||
85 | |||
86 | static void _hv_i2c_prep_msg_generic(int comm_chan_id, int cont_id, | ||
87 | struct i2c_ivc_msg *msg) | ||
88 | { | ||
89 | i2c_ivc_start_marker(msg) = 0xf005ba11; | ||
90 | i2c_ivc_chan_id(msg) = comm_chan_id; | ||
91 | i2c_ivc_controller_instance(msg) = cont_id + 1; | ||
92 | i2c_ivc_msg_type(msg) = 0; | ||
93 | i2c_ivc_error_field(msg) = 0; | ||
94 | i2c_ivc_end_marker(msg) = 0x11ab500f; | ||
95 | } | ||
96 | |||
97 | static int _hv_i2c_send_msg(struct device *dev, | ||
98 | struct tegra_hv_i2c_comm_chan *comm_chan, | ||
99 | struct i2c_ivc_msg *msg, uint8_t *buf, int *err, | ||
100 | size_t data_len, size_t total_len) | ||
101 | { | ||
102 | unsigned long flags; | ||
103 | int rv; | ||
104 | |||
105 | spin_lock_irqsave(&comm_chan->lock, flags); | ||
106 | |||
107 | if (comm_chan->rx_state != I2C_RX_INIT) { | ||
108 | dev_err(dev, "can only handle 1 frame per adapter at a time\n"); | ||
109 | rv = -EBUSY; | ||
110 | goto fail; | ||
111 | } | ||
112 | |||
113 | if (i2c_ivc_msg_type(msg) == I2C_CLEANUP) | ||
114 | comm_chan->rx_state = I2C_RX_PENDING_CLEANUP; | ||
115 | else | ||
116 | comm_chan->rx_state = I2C_RX_PENDING; | ||
117 | |||
118 | comm_chan->rcvd_data = buf; | ||
119 | comm_chan->data_len = data_len; | ||
120 | comm_chan->rcvd_err = err; | ||
121 | rv = _hv_i2c_ivc_send(comm_chan, msg, total_len); | ||
122 | if (rv < 0) { | ||
123 | dev_err(dev, "ivc_send failed err %d\n", rv); | ||
124 | goto fail; /* Redundant but safe */ | ||
125 | } | ||
126 | fail: | ||
127 | spin_unlock_irqrestore(&comm_chan->lock, flags); | ||
128 | return rv; | ||
129 | } | ||
130 | |||
131 | int hv_i2c_comm_chan_cleanup(struct tegra_hv_i2c_comm_chan *comm_chan, | ||
132 | int cont_id) | ||
133 | { | ||
134 | /* Using skbs for fast allocation and deallocation */ | ||
135 | struct sk_buff *tx_msg_skb = NULL; | ||
136 | struct i2c_ivc_msg *tx_msg = NULL; | ||
137 | int rv; | ||
138 | struct device *dev = comm_chan->dev; | ||
139 | |||
140 | _hv_i2c_comm_chan_cleanup(comm_chan); | ||
141 | |||
142 | tx_msg_skb = alloc_skb(I2C_IVC_COMMON_HEADER_LEN, GFP_KERNEL); | ||
143 | if (!tx_msg_skb) { | ||
144 | dev_err(dev, "could not allocate memory\n"); | ||
145 | return -ENOMEM; | ||
146 | } | ||
147 | |||
148 | tx_msg = (struct i2c_ivc_msg *)skb_put(tx_msg_skb, | ||
149 | I2C_IVC_COMMON_HEADER_LEN); | ||
150 | _hv_i2c_prep_msg_generic(comm_chan->id, cont_id, tx_msg); | ||
151 | |||
152 | i2c_ivc_msg_type(tx_msg) = I2C_CLEANUP; | ||
153 | rv = _hv_i2c_send_msg(dev, comm_chan, tx_msg, NULL, NULL, 0, | ||
154 | I2C_IVC_COMMON_HEADER_LEN); | ||
155 | kfree_skb(tx_msg_skb); | ||
156 | return rv; | ||
157 | } | ||
158 | |||
159 | /* | ||
160 | * hv_i2c_transfer | ||
161 | * Send a message to the i2c server, caller is expected to wait for response | ||
162 | * and handle possible timeout | ||
163 | */ | ||
164 | int hv_i2c_transfer(struct tegra_hv_i2c_comm_chan *comm_chan, int cont_id, | ||
165 | int addr, int read, uint8_t *buf, size_t len, int *err, | ||
166 | int seq_no, bool more_msgs) | ||
167 | { | ||
168 | /* Using skbs for fast allocation and deallocation */ | ||
169 | struct sk_buff *tx_msg_skb = NULL; | ||
170 | struct i2c_ivc_msg *tx_msg = NULL; | ||
171 | int rv; | ||
172 | int msg_len = I2C_IVC_COMMON_HEADER_LEN | ||
173 | + sizeof(struct i2c_ivc_msg_tx_rx_hdr) + len - 1; | ||
174 | struct device *dev = comm_chan->dev; | ||
175 | |||
176 | tx_msg_skb = alloc_skb(msg_len, GFP_KERNEL); | ||
177 | if (!tx_msg_skb) { | ||
178 | dev_err(dev, "could not allocate memory\n"); | ||
179 | return -ENOMEM; | ||
180 | } | ||
181 | |||
182 | tx_msg = (struct i2c_ivc_msg *)skb_put(tx_msg_skb, msg_len); | ||
183 | _hv_i2c_prep_msg_generic(comm_chan->id, cont_id, tx_msg); | ||
184 | |||
185 | if (read) | ||
186 | i2c_ivc_msg_type(tx_msg) = I2C_READ; | ||
187 | else { | ||
188 | i2c_ivc_msg_type(tx_msg) = I2C_WRITE; | ||
189 | memcpy(&i2c_ivc_message_buffer(tx_msg), &(buf[1]), len-1); | ||
190 | len = len - 1; | ||
191 | } | ||
192 | |||
193 | i2c_ivc_message_seq_nr(tx_msg) = seq_no; | ||
194 | i2c_ivc_message_slave_addr(tx_msg) = addr; | ||
195 | i2c_ivc_message_slave_reg(tx_msg) = buf[0]; | ||
196 | i2c_ivc_message_buf_len(tx_msg) = len; | ||
197 | if (more_msgs) | ||
198 | i2c_ivc_message_flags(tx_msg) = HV_I2C_FLAGS_REPEAT_START; | ||
199 | else | ||
200 | i2c_ivc_message_flags(tx_msg) = 0; | ||
201 | |||
202 | rv = _hv_i2c_send_msg(dev, comm_chan, tx_msg, buf, err, len, msg_len); | ||
203 | kfree_skb(tx_msg_skb); | ||
204 | return rv; | ||
205 | } | ||
206 | |||
207 | int hv_i2c_get_max_payload(struct tegra_hv_i2c_comm_chan *comm_chan, | ||
208 | int cont_id, uint32_t *max_payload, int *err) | ||
209 | { | ||
210 | /* Using skbs for fast allocation and deallocation */ | ||
211 | struct sk_buff *tx_msg_skb = NULL; | ||
212 | struct i2c_ivc_msg *tx_msg = NULL; | ||
213 | int rv; | ||
214 | int msg_len = I2C_IVC_COMMON_HEADER_LEN + sizeof(*max_payload); | ||
215 | struct device *dev = comm_chan->dev; | ||
216 | |||
217 | tx_msg_skb = alloc_skb(msg_len, GFP_KERNEL); | ||
218 | if (!tx_msg_skb) { | ||
219 | dev_err(dev, "could not allocate memory\n"); | ||
220 | return -ENOMEM; | ||
221 | } | ||
222 | |||
223 | tx_msg = (struct i2c_ivc_msg *)skb_put(tx_msg_skb, msg_len); | ||
224 | _hv_i2c_prep_msg_generic(comm_chan->id, cont_id, tx_msg); | ||
225 | |||
226 | i2c_ivc_msg_type(tx_msg) = I2C_GET_MAX_PAYLOAD; | ||
227 | i2c_ivc_max_payload_field(tx_msg) = 0; | ||
228 | rv = _hv_i2c_send_msg(dev, comm_chan, tx_msg, (uint8_t *)max_payload, | ||
229 | err, sizeof(*max_payload), msg_len); | ||
230 | kfree_skb(tx_msg_skb); | ||
231 | return rv; | ||
232 | } | ||
233 | |||
234 | static void *_hv_i2c_comm_chan_alloc(i2c_isr_handler handler, void *data, | ||
235 | struct device *dev, struct tegra_hv_i2c_comm_dev *comm_dev) | ||
236 | { | ||
237 | struct tegra_hv_i2c_comm_chan *comm_chan = NULL; | ||
238 | unsigned long flags; | ||
239 | void *err = NULL; | ||
240 | int chan_id; | ||
241 | |||
242 | comm_chan = devm_kzalloc(dev, sizeof(*comm_chan), | ||
243 | GFP_KERNEL); | ||
244 | if (!comm_chan) { | ||
245 | err = ERR_PTR(-ENOMEM); | ||
246 | goto out; | ||
247 | } | ||
248 | |||
249 | comm_chan->dev = dev; | ||
250 | comm_chan->rx_state = I2C_RX_INIT; | ||
251 | comm_chan->hv_comm_dev = comm_dev; | ||
252 | spin_lock_init(&comm_chan->lock); | ||
253 | comm_chan->handler = handler; | ||
254 | comm_chan->data = data; | ||
255 | comm_chan->ivck = comm_dev->ivck; | ||
256 | |||
257 | spin_lock_irqsave(&comm_dev->lock, flags); | ||
258 | /* Find a free channel number */ | ||
259 | for (chan_id = 0; chan_id < MAX_COMM_CHANS; chan_id++) { | ||
260 | if (comm_dev->hv_comm_chan[chan_id] == NULL) | ||
261 | break; | ||
262 | } | ||
263 | |||
264 | if (chan_id >= MAX_COMM_CHANS) { | ||
265 | /* No free channel available */ | ||
266 | err = ERR_PTR(-ENOMEM); | ||
267 | goto fail_cleanup; | ||
268 | } | ||
269 | comm_chan->id = chan_id; | ||
270 | |||
271 | comm_dev->hv_comm_chan[comm_chan->id] = comm_chan; | ||
272 | spin_unlock_irqrestore(&comm_dev->lock, flags); | ||
273 | return comm_chan; | ||
274 | fail_cleanup: | ||
275 | spin_unlock_irqrestore(&comm_dev->lock, flags); | ||
276 | devm_kfree(dev, comm_chan); | ||
277 | out: | ||
278 | return err; | ||
279 | } | ||
280 | |||
281 | void hv_i2c_comm_chan_free(struct tegra_hv_i2c_comm_chan *comm_chan) | ||
282 | { | ||
283 | unsigned long flags; | ||
284 | struct tegra_hv_i2c_comm_dev *comm_dev = comm_chan->hv_comm_dev; | ||
285 | struct device *dev = comm_chan->dev; | ||
286 | |||
287 | spin_lock_irqsave(&comm_dev->lock, flags); | ||
288 | comm_dev->hv_comm_chan[comm_chan->id] = NULL; | ||
289 | spin_unlock_irqrestore(&comm_dev->lock, flags); | ||
290 | |||
291 | devm_kfree(dev, comm_chan); | ||
292 | |||
293 | } | ||
294 | |||
295 | static irqreturn_t hv_i2c_isr(int irq, void *dev_id) | ||
296 | { | ||
297 | struct tegra_hv_i2c_comm_dev *comm_dev = | ||
298 | (struct tegra_hv_i2c_comm_dev *)dev_id; | ||
299 | |||
300 | queue_work(system_wq, &comm_dev->work); | ||
301 | |||
302 | return IRQ_HANDLED; | ||
303 | } | ||
304 | |||
305 | static void hv_i2c_work(struct work_struct *work) | ||
306 | { | ||
307 | /* In theory it is possible that the comm_chan referred to in the | ||
308 | * received message might not have been allocated yet on this side | ||
309 | * (although that is unlikely given that the server responds to | ||
310 | * messages from the client only) | ||
311 | */ | ||
312 | struct tegra_hv_i2c_comm_dev *comm_dev = | ||
313 | container_of(work, struct tegra_hv_i2c_comm_dev, work); | ||
314 | struct tegra_hv_ivc_cookie *ivck = comm_dev->ivck; | ||
315 | struct i2c_ivc_msg_common rx_msg_hdr; | ||
316 | struct i2c_ivc_msg *fake_rx_msg = (struct i2c_ivc_msg *)&rx_msg_hdr; | ||
317 | /* fake in the sense that this ptr does not represent the whole message, | ||
318 | * DO NOT use it to access anything except common header fields | ||
319 | */ | ||
320 | struct tegra_hv_i2c_comm_chan *comm_chan = NULL; | ||
321 | int comm_chan_id; | ||
322 | u32 len = 0; | ||
323 | |||
324 | for (; tegra_hv_ivc_can_read(ivck); tegra_hv_ivc_read_advance(ivck)) { | ||
325 | /* Message available | ||
326 | * Initialize local variables to safe values | ||
327 | */ | ||
328 | comm_chan = NULL; | ||
329 | comm_chan_id = -1; | ||
330 | len = 0; | ||
331 | memset(&rx_msg_hdr, 0, I2C_IVC_COMMON_HEADER_LEN); | ||
332 | |||
333 | len = tegra_hv_ivc_read_peek(ivck, &rx_msg_hdr, 0, | ||
334 | I2C_IVC_COMMON_HEADER_LEN); | ||
335 | if (len != I2C_IVC_COMMON_HEADER_LEN) { | ||
336 | pr_err("%s: IVC read failure (msg size error)\n", | ||
337 | __func__); | ||
338 | continue; | ||
339 | } | ||
340 | |||
341 | if ((i2c_ivc_start_marker(fake_rx_msg) != 0xf005ba11) || | ||
342 | (i2c_ivc_end_marker(fake_rx_msg) != 0x11ab500f)) { | ||
343 | pr_err("%s: IVC read failure (invalid markers)\n", | ||
344 | __func__); | ||
345 | continue; | ||
346 | } | ||
347 | |||
348 | comm_chan_id = i2c_ivc_chan_id(fake_rx_msg); | ||
349 | |||
350 | if (!((comm_chan_id >= 0) && (comm_chan_id < MAX_COMM_CHANS))) { | ||
351 | pr_err("%s: IVC read failure (invalid comm chan id)\n", | ||
352 | __func__); | ||
353 | continue; | ||
354 | } | ||
355 | |||
356 | comm_chan = comm_dev->hv_comm_chan[comm_chan_id]; | ||
357 | if (!comm_chan || comm_chan->id != comm_chan_id) { | ||
358 | pr_err("%s: Invalid channel from server %d\n", __func__, | ||
359 | comm_chan_id); | ||
360 | continue; | ||
361 | } | ||
362 | |||
363 | if (comm_chan->rx_state == I2C_RX_INIT) { | ||
364 | dev_err(comm_chan->dev, | ||
365 | "Spurious message from server (channel %d)\n", | ||
366 | comm_chan_id); | ||
367 | WARN_ON(comm_chan->rcvd_data != NULL); | ||
368 | WARN_ON(comm_chan->data_len != 0); | ||
369 | WARN_ON(comm_chan->rcvd_err != NULL); | ||
370 | continue; | ||
371 | } | ||
372 | |||
373 | if (comm_chan->rx_state == I2C_RX_PENDING) { | ||
374 | /* Copy the message to consumer*/ | ||
375 | tegra_hv_ivc_read_peek(ivck, comm_chan->rcvd_data, | ||
376 | _hv_i2c_get_data_ptr_offset( | ||
377 | i2c_ivc_msg_type(fake_rx_msg)), | ||
378 | comm_chan->data_len); | ||
379 | *comm_chan->rcvd_err = i2c_ivc_error_field(fake_rx_msg); | ||
380 | _hv_i2c_comm_chan_cleanup(comm_chan); | ||
381 | comm_chan->handler(comm_chan->data); | ||
382 | } else if (comm_chan->rx_state == I2C_RX_PENDING_CLEANUP) { | ||
383 | /* We might get some stale responses in this scenario, | ||
384 | * ignore those | ||
385 | */ | ||
386 | if (i2c_ivc_msg_type(fake_rx_msg) | ||
387 | == I2C_CLEANUP_RESPONSE) { | ||
388 | _hv_i2c_comm_chan_cleanup(comm_chan); | ||
389 | comm_chan->handler(comm_chan->data); | ||
390 | } else { | ||
391 | dev_err(comm_chan->dev, | ||
392 | "Stale response from server (channel %d)\n", | ||
393 | comm_chan_id); | ||
394 | } | ||
395 | } else { | ||
396 | WARN(1, "Bad channel state\n"); | ||
397 | } | ||
398 | } | ||
399 | |||
400 | return; | ||
401 | } | ||
402 | |||
403 | struct tegra_hv_i2c_comm_dev *_hv_i2c_get_comm_dev(struct device *dev, | ||
404 | struct device_node *hv_dn, uint32_t ivc_queue) | ||
405 | { | ||
406 | static HLIST_HEAD(ivc_comm_devs); | ||
407 | static DEFINE_SPINLOCK(ivc_comm_devs_lock); | ||
408 | unsigned long flags = 0; | ||
409 | struct tegra_hv_i2c_comm_dev *comm_dev = NULL; | ||
410 | struct tegra_hv_ivc_cookie *ivck = NULL; | ||
411 | int err; | ||
412 | |||
413 | spin_lock_irqsave(&ivc_comm_devs_lock, flags); | ||
414 | |||
415 | hlist_for_each_entry(comm_dev, &ivc_comm_devs, list) { | ||
416 | if (comm_dev->queue_id == ivc_queue) | ||
417 | goto end; | ||
418 | } | ||
419 | |||
420 | /* could not find a previously created comm_dev for this ivc | ||
421 | * queue, create one. | ||
422 | */ | ||
423 | |||
424 | ivck = tegra_hv_ivc_reserve(hv_dn, ivc_queue, NULL); | ||
425 | if (IS_ERR_OR_NULL(ivck)) { | ||
426 | dev_err(dev, "Failed to reserve ivc queue %d\n", | ||
427 | ivc_queue); | ||
428 | comm_dev = ERR_PTR(-EINVAL); | ||
429 | goto end; | ||
430 | } | ||
431 | |||
432 | comm_dev = devm_kzalloc(dev, sizeof(*comm_dev), | ||
433 | GFP_KERNEL); | ||
434 | if (!comm_dev) { | ||
435 | /* Unreserve the queue here because other controllers | ||
436 | * will probably try to reserve it again until one | ||
437 | * succeeds or all of them fail | ||
438 | */ | ||
439 | tegra_hv_ivc_unreserve(ivck); | ||
440 | comm_dev = ERR_PTR(-ENOMEM); | ||
441 | goto end; | ||
442 | } | ||
443 | |||
444 | comm_dev->ivck = ivck; | ||
445 | comm_dev->queue_id = ivc_queue; | ||
446 | |||
447 | spin_lock_init(&comm_dev->ivck_tx_lock); | ||
448 | spin_lock_init(&comm_dev->lock); | ||
449 | |||
450 | INIT_HLIST_NODE(&comm_dev->list); | ||
451 | hlist_add_head(&comm_dev->list, &ivc_comm_devs); | ||
452 | |||
453 | /* Our comm_dev is ready, so enable irq here. But channels are | ||
454 | * not yet allocated, we need to take care of that in the | ||
455 | * handler | ||
456 | */ | ||
457 | err = request_threaded_irq(ivck->irq, hv_i2c_isr, NULL, 0, | ||
458 | dev_name(dev), comm_dev); | ||
459 | if (err) { | ||
460 | hlist_del(&comm_dev->list); | ||
461 | devm_kfree(dev, comm_dev); | ||
462 | tegra_hv_ivc_unreserve(ivck); | ||
463 | comm_dev = ERR_PTR(-ENOMEM); | ||
464 | goto end; | ||
465 | } | ||
466 | |||
467 | INIT_WORK(&comm_dev->work, hv_i2c_work); | ||
468 | |||
469 | end: | ||
470 | spin_unlock_irqrestore(&ivc_comm_devs_lock, flags); | ||
471 | return comm_dev; | ||
472 | } | ||
473 | |||
474 | void *hv_i2c_comm_init(struct device *dev, i2c_isr_handler handler, | ||
475 | void *data) | ||
476 | { | ||
477 | int err; | ||
478 | uint32_t ivc_queue; | ||
479 | struct device_node *dn, *hv_dn; | ||
480 | struct tegra_hv_i2c_comm_dev *comm_dev = NULL; | ||
481 | |||
482 | dn = dev->of_node; | ||
483 | if (dn == NULL) { | ||
484 | dev_err(dev, "No OF data\n"); | ||
485 | return ERR_PTR(-EINVAL); | ||
486 | } | ||
487 | |||
488 | hv_dn = of_parse_phandle(dn, "ivc_queue", 0); | ||
489 | if (hv_dn == NULL) { | ||
490 | dev_err(dev, "Failed to parse phandle of ivc prop\n"); | ||
491 | return ERR_PTR(-EINVAL); | ||
492 | } | ||
493 | |||
494 | err = of_property_read_u32_index(dn, "ivc_queue", 1, | ||
495 | &ivc_queue); | ||
496 | if (err != 0) { | ||
497 | dev_err(dev, "Failed to read IVC property ID\n"); | ||
498 | of_node_put(hv_dn); | ||
499 | return ERR_PTR(-EINVAL); | ||
500 | } | ||
501 | |||
502 | comm_dev = _hv_i2c_get_comm_dev(dev, hv_dn, ivc_queue); | ||
503 | |||
504 | if (IS_ERR_OR_NULL(comm_dev)) | ||
505 | return comm_dev; | ||
506 | |||
507 | return _hv_i2c_comm_chan_alloc(handler, data, dev, comm_dev); | ||
508 | } | ||
diff --git a/drivers/i2c/busses/i2c-tegra-hv-common.h b/drivers/i2c/busses/i2c-tegra-hv-common.h new file mode 100644 index 000000000..b41f822c1 --- /dev/null +++ b/drivers/i2c/busses/i2c-tegra-hv-common.h | |||
@@ -0,0 +1,152 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | */ | ||
13 | |||
14 | #ifndef __I2C_LIB_HV_H__ | ||
15 | #define __I2C_LIB_HV_H__ | ||
16 | |||
17 | #ifdef CONFIG_TEGRA_HV_MANAGER | ||
18 | #include <linux/device.h> | ||
19 | #include <linux/spinlock.h> | ||
20 | #include <linux/tegra-ivc.h> | ||
21 | #include <linux/list.h> | ||
22 | #include <linux/workqueue.h> | ||
23 | |||
24 | typedef void (*i2c_isr_handler)(void *context); | ||
25 | |||
26 | struct tegra_hv_i2c_comm_chan; | ||
27 | |||
28 | int hv_i2c_transfer(struct tegra_hv_i2c_comm_chan *comm_chan, int cont_id, | ||
29 | int addr, int read, uint8_t *buf, size_t len, int *err, | ||
30 | int seq_no, bool more_msgs); | ||
31 | int hv_i2c_get_max_payload(struct tegra_hv_i2c_comm_chan *comm_chan, | ||
32 | int cont_id, uint32_t *max_payload, int *err); | ||
33 | int hv_i2c_comm_chan_cleanup(struct tegra_hv_i2c_comm_chan *comm_chan, | ||
34 | int cont_id); | ||
35 | void hv_i2c_comm_chan_free(struct tegra_hv_i2c_comm_chan *comm_chan); | ||
36 | void *hv_i2c_comm_init(struct device *dev, i2c_isr_handler handler, | ||
37 | void *data); | ||
38 | |||
39 | #define MAX_COMM_CHANS 7 | ||
40 | #define COMM_CHAN_UNASSIGNED MAX_COMM_CHANS | ||
41 | |||
42 | enum i2c_ivc_msg_t { | ||
43 | I2C_READ, | ||
44 | I2C_READ_RESPONSE, | ||
45 | I2C_WRITE, | ||
46 | I2C_WRITE_RESPONSE, | ||
47 | I2C_GET_MAX_PAYLOAD, | ||
48 | I2C_GET_MAX_PAYLOAD_RESPONSE, | ||
49 | I2C_CLEANUP, | ||
50 | I2C_CLEANUP_RESPONSE, | ||
51 | I2C_INVALID, | ||
52 | }; | ||
53 | |||
54 | enum i2c_rx_state_t { | ||
55 | I2C_RX_INIT, | ||
56 | I2C_RX_PENDING, | ||
57 | I2C_RX_PENDING_CLEANUP, | ||
58 | }; | ||
59 | |||
60 | #define HV_I2C_FLAGS_REPEAT_START (1<<0) | ||
61 | |||
62 | struct i2c_ivc_msg_common { | ||
63 | uint32_t s_marker; | ||
64 | uint32_t msg_type; | ||
65 | int32_t comm_chan_id; | ||
66 | uint32_t controller_instance; | ||
67 | uint32_t err; | ||
68 | uint32_t e_marker; | ||
69 | }; | ||
70 | |||
71 | struct i2c_ivc_msg_tx_rx_hdr { | ||
72 | int32_t seq_no; | ||
73 | uint32_t slave_address; | ||
74 | uint32_t slave_reg; | ||
75 | uint32_t buf_len; | ||
76 | uint32_t flags; | ||
77 | }; | ||
78 | |||
79 | struct i2c_ivc_msg_tx_rx { | ||
80 | struct i2c_ivc_msg_tx_rx_hdr fixed; | ||
81 | uint8_t buffer[4096]; | ||
82 | }; | ||
83 | |||
84 | struct i2c_ivc_msg_max_payload { | ||
85 | uint32_t max_payload; | ||
86 | }; | ||
87 | |||
88 | struct i2c_ivc_msg { | ||
89 | struct i2c_ivc_msg_common hdr; | ||
90 | union { | ||
91 | struct i2c_ivc_msg_tx_rx m; | ||
92 | struct i2c_ivc_msg_max_payload p; | ||
93 | } body; | ||
94 | }; | ||
95 | |||
96 | #define I2C_IVC_COMMON_HEADER_LEN sizeof(struct i2c_ivc_msg_common) | ||
97 | |||
98 | #define i2c_ivc_start_marker(_msg_ptr) (_msg_ptr->hdr.s_marker) | ||
99 | #define i2c_ivc_end_marker(_msg_ptr) (_msg_ptr->hdr.e_marker) | ||
100 | #define i2c_ivc_chan_id(_msg_ptr) (_msg_ptr->hdr.comm_chan_id) | ||
101 | #define i2c_ivc_controller_instance(_msg_ptr) \ | ||
102 | (_msg_ptr->hdr.controller_instance) | ||
103 | #define i2c_ivc_msg_type(_msg_ptr) (_msg_ptr->hdr.msg_type) | ||
104 | #define i2c_ivc_error_field(_msg_ptr) (_msg_ptr->hdr.err) | ||
105 | |||
106 | #define i2c_ivc_message_seq_nr(_msg_ptr) \ | ||
107 | (_msg_ptr->body.m.fixed.seq_no) | ||
108 | #define i2c_ivc_message_slave_addr(_msg_ptr) \ | ||
109 | (_msg_ptr->body.m.fixed.slave_address) | ||
110 | #define i2c_ivc_message_slave_reg(_msg_ptr) \ | ||
111 | (_msg_ptr->body.m.fixed.slave_reg) | ||
112 | #define i2c_ivc_message_buf_len(_msg_ptr) \ | ||
113 | (_msg_ptr->body.m.fixed.buf_len) | ||
114 | #define i2c_ivc_message_flags(_msg_ptr) (_msg_ptr->body.m.fixed.flags) | ||
115 | #define i2c_ivc_message_buffer(_msg_ptr) \ | ||
116 | (_msg_ptr->body.m.buffer[0]) | ||
117 | |||
118 | #define i2c_ivc_max_payload_field(_msg_ptr) \ | ||
119 | (_msg_ptr->body.p.max_payload) | ||
120 | |||
121 | struct tegra_hv_i2c_comm_dev; | ||
122 | |||
123 | /* channel is virtual abstraction over a single ivc queue | ||
124 | * each channel holds messages that are independent of other channels | ||
125 | * we allocate one channel per i2c adapter as these can operate in parallel | ||
126 | */ | ||
127 | struct tegra_hv_i2c_comm_chan { | ||
128 | struct tegra_hv_ivc_cookie *ivck; | ||
129 | struct device *dev; | ||
130 | int id; | ||
131 | i2c_isr_handler handler; | ||
132 | void *data; | ||
133 | void *rcvd_data; | ||
134 | size_t data_len; | ||
135 | int *rcvd_err; | ||
136 | enum i2c_rx_state_t rx_state; | ||
137 | struct tegra_hv_i2c_comm_dev *hv_comm_dev; | ||
138 | spinlock_t lock; | ||
139 | }; | ||
140 | |||
141 | |||
142 | struct tegra_hv_i2c_comm_dev { | ||
143 | uint32_t queue_id; | ||
144 | struct tegra_hv_ivc_cookie *ivck; | ||
145 | spinlock_t ivck_tx_lock; | ||
146 | spinlock_t lock; | ||
147 | struct hlist_node list; | ||
148 | struct work_struct work; | ||
149 | struct tegra_hv_i2c_comm_chan *hv_comm_chan[MAX_COMM_CHANS]; | ||
150 | }; | ||
151 | #endif | ||
152 | #endif | ||
diff --git a/drivers/i2c/busses/i2c-tegra-hv.c b/drivers/i2c/busses/i2c-tegra-hv.c new file mode 100644 index 000000000..c4de07c42 --- /dev/null +++ b/drivers/i2c/busses/i2c-tegra-hv.c | |||
@@ -0,0 +1,324 @@ | |||
1 | /* | ||
2 | * drivers/i2c/busses/i2c-tegra-hv.c | ||
3 | * | ||
4 | * Copyright (C) 2015 NVIDIA Corporation. All rights reserved. | ||
5 | * Author: Arnab Basu <abasu@nvidia.com> | ||
6 | * | ||
7 | * This software is licensed under the terms of the GNU General Public | ||
8 | * License version 2, as published by the Free Software Foundation, and | ||
9 | * may be copied, distributed, and modified under those terms. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/i2c-tegra-hv.h> | ||
22 | #include <linux/of_device.h> | ||
23 | #include <linux/of_i2c.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/spinlock.h> | ||
26 | #include <linux/completion.h> | ||
27 | #include <linux/device.h> | ||
28 | #include <linux/jiffies.h> | ||
29 | |||
30 | #include "i2c-tegra-hv-common.h" | ||
31 | |||
32 | #include <asm/unaligned.h> | ||
33 | |||
34 | #define TEGRA_I2C_TIMEOUT (msecs_to_jiffies(1000)) | ||
35 | #define TEGRA_I2C_RETRIES 3 | ||
36 | |||
37 | #define I2C_NO_ERROR 0 | ||
38 | |||
39 | /** | ||
40 | * struct tegra_hv_i2c_dev - per device i2c context | ||
41 | * @dev: device reference | ||
42 | * @adapter: core i2c layer adapter information | ||
43 | * @cont_id: i2c controller id | ||
44 | * @comm_chan: context for the logical channel over which this | ||
45 | * device communicates with the i2c server | ||
46 | * @msg_complete: transfer completion notifier | ||
47 | * @max_payload_size: maximum packet size supported | ||
48 | * by this i2c device | ||
49 | * @completion_timeout: time to wait for reply from server | ||
50 | */ | ||
51 | struct tegra_hv_i2c_dev { | ||
52 | struct device *dev; | ||
53 | struct i2c_adapter adapter; | ||
54 | int cont_id; | ||
55 | void *comm_chan; | ||
56 | struct completion msg_complete; | ||
57 | u32 max_payload_size; | ||
58 | u32 completion_timeout; | ||
59 | }; | ||
60 | |||
61 | static void tegra_hv_i2c_isr(void *dev_id) | ||
62 | { | ||
63 | struct tegra_hv_i2c_dev *i2c_dev = dev_id; | ||
64 | complete(&i2c_dev->msg_complete); | ||
65 | } | ||
66 | |||
67 | static int tegra_hv_i2c_xfer_msg(struct tegra_hv_i2c_dev *i2c_dev, | ||
68 | struct i2c_msg *msg, int sno, bool more_msgs) | ||
69 | { | ||
70 | int ret; | ||
71 | int msg_err; | ||
72 | int msg_read; | ||
73 | int rv; | ||
74 | |||
75 | if (msg->len == 0) | ||
76 | return -EINVAL; | ||
77 | |||
78 | if (msg->len > i2c_dev->max_payload_size) | ||
79 | return -E2BIG; | ||
80 | |||
81 | msg_err = I2C_NO_ERROR; | ||
82 | msg_read = (msg->flags & I2C_M_RD); | ||
83 | INIT_COMPLETION(i2c_dev->msg_complete); | ||
84 | |||
85 | ret = hv_i2c_transfer(i2c_dev->comm_chan, i2c_dev->cont_id, msg->addr, | ||
86 | msg_read, msg->buf, msg->len, &msg_err, sno, more_msgs); | ||
87 | if (ret < 0) { | ||
88 | dev_err(i2c_dev->dev, "unable to send message (%d)\n", ret); | ||
89 | return ret; | ||
90 | } | ||
91 | |||
92 | ret = wait_for_completion_timeout(&i2c_dev->msg_complete, | ||
93 | i2c_dev->completion_timeout); | ||
94 | |||
95 | if (ret == 0) { | ||
96 | dev_err(i2c_dev->dev, | ||
97 | "i2c transfer timed out, addr 0x%04x, data 0x%02x\n", | ||
98 | msg->addr, msg->buf[0]); | ||
99 | rv = -EBUSY; | ||
100 | goto error; | ||
101 | } | ||
102 | |||
103 | dev_dbg(i2c_dev->dev, "transfer complete: %d %d %d\n", | ||
104 | ret, completion_done(&i2c_dev->msg_complete), msg_err); | ||
105 | |||
106 | if (likely(msg_err == I2C_NO_ERROR)) | ||
107 | return 0; | ||
108 | |||
109 | dev_dbg(i2c_dev->dev, "received error code %d\n", msg_err); | ||
110 | rv = -EIO; | ||
111 | error: | ||
112 | INIT_COMPLETION(i2c_dev->msg_complete); | ||
113 | ret = hv_i2c_comm_chan_cleanup(i2c_dev->comm_chan, i2c_dev->cont_id); | ||
114 | |||
115 | if (ret < 0) { | ||
116 | dev_err(i2c_dev->dev, "Failed to send cleanup message\n"); | ||
117 | BUG(); | ||
118 | } | ||
119 | |||
120 | ret = wait_for_completion_timeout(&i2c_dev->msg_complete, | ||
121 | i2c_dev->completion_timeout * 2); | ||
122 | if (ret == 0) { | ||
123 | dev_err(i2c_dev->dev, "Cleanup failed after timeout\n"); | ||
124 | BUG(); | ||
125 | } | ||
126 | return rv; | ||
127 | } | ||
128 | |||
129 | static int tegra_hv_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], | ||
130 | int num) | ||
131 | { | ||
132 | struct tegra_hv_i2c_dev *i2c_dev = i2c_get_adapdata(adap); | ||
133 | int i; | ||
134 | int ret = 0; | ||
135 | |||
136 | for (i = 0; i < num; i++) { | ||
137 | ret = tegra_hv_i2c_xfer_msg(i2c_dev, &msgs[i], i, | ||
138 | (i < (num - 1))); | ||
139 | if (ret) | ||
140 | break; | ||
141 | } | ||
142 | |||
143 | return ret ? ret : i; | ||
144 | } | ||
145 | |||
146 | static u32 tegra_hv_i2c_func(struct i2c_adapter *adap) | ||
147 | { | ||
148 | u32 ret = I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; | ||
149 | |||
150 | return ret; | ||
151 | } | ||
152 | |||
153 | static const struct i2c_algorithm tegra_hv_i2c_algo = { | ||
154 | .master_xfer = tegra_hv_i2c_xfer, | ||
155 | .functionality = tegra_hv_i2c_func, | ||
156 | }; | ||
157 | |||
158 | static struct tegra_hv_i2c_platform_data *parse_i2c_tegra_dt( | ||
159 | struct platform_device *pdev) | ||
160 | { | ||
161 | struct tegra_hv_i2c_platform_data *pdata; | ||
162 | |||
163 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
164 | if (!pdata) | ||
165 | return ERR_PTR(-ENOMEM); | ||
166 | |||
167 | return pdata; | ||
168 | } | ||
169 | |||
170 | /* Match table for of_platform binding */ | ||
171 | static const struct of_device_id tegra_hv_i2c_of_match[] = { | ||
172 | { .compatible = "nvidia,tegra124-i2c-hv", .data = NULL}, | ||
173 | {}, | ||
174 | }; | ||
175 | MODULE_DEVICE_TABLE(of, tegra_hv_i2c_of_match); | ||
176 | |||
177 | static int tegra_hv_i2c_probe(struct platform_device *pdev) | ||
178 | { | ||
179 | struct tegra_hv_i2c_dev *i2c_dev; | ||
180 | struct tegra_hv_i2c_platform_data *pdata = pdev->dev.platform_data; | ||
181 | int ret = 0; | ||
182 | const struct of_device_id *match; | ||
183 | int bus_num = -1; | ||
184 | void *chan; | ||
185 | int err; | ||
186 | |||
187 | if (pdev->dev.of_node) { | ||
188 | match = of_match_device(of_match_ptr(tegra_hv_i2c_of_match), | ||
189 | &pdev->dev); | ||
190 | if (!match) { | ||
191 | dev_err(&pdev->dev, "Device Not matching\n"); | ||
192 | return -ENODEV; | ||
193 | } | ||
194 | if (!pdata) | ||
195 | pdata = parse_i2c_tegra_dt(pdev); | ||
196 | } else { | ||
197 | WARN(1, "Only device tree based init is supported\n"); | ||
198 | return -EINVAL; | ||
199 | } | ||
200 | |||
201 | i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL); | ||
202 | if (!i2c_dev) { | ||
203 | dev_err(&pdev->dev, "Could not allocate struct tegra_hv_i2c_dev"); | ||
204 | return -ENOMEM; | ||
205 | } | ||
206 | |||
207 | chan = hv_i2c_comm_init(&pdev->dev, tegra_hv_i2c_isr, i2c_dev); | ||
208 | if (IS_ERR(chan)) | ||
209 | return PTR_ERR(chan); | ||
210 | |||
211 | i2c_dev->dev = &pdev->dev; | ||
212 | i2c_dev->comm_chan = chan; | ||
213 | |||
214 | platform_set_drvdata(pdev, i2c_dev); | ||
215 | |||
216 | i2c_set_adapdata(&i2c_dev->adapter, i2c_dev); | ||
217 | i2c_dev->adapter.owner = THIS_MODULE; | ||
218 | i2c_dev->adapter.class = I2C_CLASS_HWMON; | ||
219 | strlcpy(i2c_dev->adapter.name, "Tegra I2C HV adapter", | ||
220 | sizeof(i2c_dev->adapter.name)); | ||
221 | i2c_dev->adapter.algo = &tegra_hv_i2c_algo; | ||
222 | i2c_dev->adapter.dev.parent = &pdev->dev; | ||
223 | i2c_dev->adapter.nr = bus_num; | ||
224 | i2c_dev->adapter.dev.of_node = pdev->dev.of_node; | ||
225 | |||
226 | if (pdata->retries) | ||
227 | i2c_dev->adapter.retries = pdata->retries; | ||
228 | else | ||
229 | i2c_dev->adapter.retries = TEGRA_I2C_RETRIES; | ||
230 | |||
231 | if (pdata->timeout) | ||
232 | i2c_dev->adapter.timeout = pdata->timeout; | ||
233 | |||
234 | if (i2c_dev->adapter.timeout) | ||
235 | i2c_dev->completion_timeout = i2c_dev->adapter.timeout; | ||
236 | else | ||
237 | i2c_dev->completion_timeout = TEGRA_I2C_TIMEOUT; | ||
238 | |||
239 | ret = i2c_add_numbered_adapter(&i2c_dev->adapter); | ||
240 | if (ret) { | ||
241 | dev_err(&pdev->dev, "Failed to add I2C adapter\n"); | ||
242 | return ret; | ||
243 | } | ||
244 | i2c_dev->cont_id = i2c_dev->adapter.nr; | ||
245 | init_completion(&i2c_dev->msg_complete); | ||
246 | INIT_COMPLETION(i2c_dev->msg_complete); | ||
247 | |||
248 | ret = hv_i2c_get_max_payload(i2c_dev->comm_chan, i2c_dev->cont_id, | ||
249 | &(i2c_dev->max_payload_size), &err); | ||
250 | if (ret < 0) { | ||
251 | dev_warn(&pdev->dev, "Could not get max payload, defaulting to 4096\n"); | ||
252 | i2c_dev->max_payload_size = 4096; | ||
253 | } else { | ||
254 | ret = wait_for_completion_timeout(&i2c_dev->msg_complete, | ||
255 | i2c_dev->completion_timeout); | ||
256 | if (ret == 0) { | ||
257 | dev_warn(&pdev->dev, "Timed out getting max payload, defaulting to 4096\n"); | ||
258 | i2c_dev->max_payload_size = 4096; | ||
259 | } else if (err != I2C_NO_ERROR) { | ||
260 | dev_warn(&pdev->dev, "Error getting max payload, defaulting to 4096\n"); | ||
261 | i2c_dev->max_payload_size = 4096; | ||
262 | } | ||
263 | } | ||
264 | |||
265 | of_i2c_register_devices(&i2c_dev->adapter); | ||
266 | |||
267 | return 0; | ||
268 | } | ||
269 | |||
270 | static int tegra_hv_i2c_remove(struct platform_device *pdev) | ||
271 | { | ||
272 | struct tegra_hv_i2c_dev *i2c_dev = platform_get_drvdata(pdev); | ||
273 | |||
274 | hv_i2c_comm_chan_free(i2c_dev->comm_chan); | ||
275 | i2c_dev->comm_chan = NULL; | ||
276 | i2c_del_adapter(&i2c_dev->adapter); | ||
277 | return 0; | ||
278 | } | ||
279 | |||
280 | static void tegra_hv_i2c_shutdown(struct platform_device *pdev) | ||
281 | { | ||
282 | struct tegra_hv_i2c_dev *i2c_dev = platform_get_drvdata(pdev); | ||
283 | |||
284 | dev_info(i2c_dev->dev, "Bus is shutdown down..\n"); | ||
285 | i2c_shutdown_adapter(&i2c_dev->adapter); | ||
286 | } | ||
287 | |||
288 | static struct platform_device_id tegra_hv_i2c_devtype[] = { | ||
289 | { | ||
290 | .name = "tegra12-hv-i2c", | ||
291 | .driver_data = 0, | ||
292 | }, | ||
293 | |||
294 | }; | ||
295 | |||
296 | static struct platform_driver tegra_hv_i2c_driver = { | ||
297 | .probe = tegra_hv_i2c_probe, | ||
298 | .remove = tegra_hv_i2c_remove, | ||
299 | .late_shutdown = tegra_hv_i2c_shutdown, | ||
300 | .id_table = tegra_hv_i2c_devtype, | ||
301 | .driver = { | ||
302 | .name = "tegra-hv-i2c", | ||
303 | .owner = THIS_MODULE, | ||
304 | .of_match_table = of_match_ptr(tegra_hv_i2c_of_match), | ||
305 | .pm = NULL, | ||
306 | }, | ||
307 | }; | ||
308 | |||
309 | static int __init tegra_hv_i2c_init_driver(void) | ||
310 | { | ||
311 | return platform_driver_register(&tegra_hv_i2c_driver); | ||
312 | } | ||
313 | |||
314 | static void __exit tegra_hv_i2c_exit_driver(void) | ||
315 | { | ||
316 | platform_driver_unregister(&tegra_hv_i2c_driver); | ||
317 | } | ||
318 | |||
319 | subsys_initcall(tegra_hv_i2c_init_driver); | ||
320 | module_exit(tegra_hv_i2c_exit_driver); | ||
321 | |||
322 | MODULE_DESCRIPTION("nVidia Tegra Hypervisor I2C Bus Controller driver"); | ||
323 | MODULE_AUTHOR("Arnab Basu"); | ||
324 | MODULE_LICENSE("GPL v2"); | ||