1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
/*
* Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
#ifndef __I2C_LIB_HV_H__
#define __I2C_LIB_HV_H__
#ifdef CONFIG_TEGRA_HV_MANAGER
#include <linux/device.h>
#include <linux/spinlock.h>
#include <linux/tegra-ivc.h>
#include <linux/list.h>
#include <linux/workqueue.h>
typedef void (*i2c_isr_handler)(void *context);
struct tegra_hv_i2c_comm_chan;
int hv_i2c_transfer(struct tegra_hv_i2c_comm_chan *comm_chan, int cont_id,
int addr, int read, uint8_t *buf, size_t len, int *err,
int seq_no, bool more_msgs);
int hv_i2c_get_max_payload(struct tegra_hv_i2c_comm_chan *comm_chan,
int cont_id, uint32_t *max_payload, int *err);
int hv_i2c_comm_chan_cleanup(struct tegra_hv_i2c_comm_chan *comm_chan,
int cont_id);
void hv_i2c_comm_chan_free(struct tegra_hv_i2c_comm_chan *comm_chan);
void *hv_i2c_comm_init(struct device *dev, i2c_isr_handler handler,
void *data);
#define MAX_COMM_CHANS 7
#define COMM_CHAN_UNASSIGNED MAX_COMM_CHANS
enum i2c_ivc_msg_t {
I2C_READ,
I2C_READ_RESPONSE,
I2C_WRITE,
I2C_WRITE_RESPONSE,
I2C_GET_MAX_PAYLOAD,
I2C_GET_MAX_PAYLOAD_RESPONSE,
I2C_CLEANUP,
I2C_CLEANUP_RESPONSE,
I2C_INVALID,
};
enum i2c_rx_state_t {
I2C_RX_INIT,
I2C_RX_PENDING,
I2C_RX_PENDING_CLEANUP,
};
#define HV_I2C_FLAGS_REPEAT_START (1<<0)
struct i2c_ivc_msg_common {
uint32_t s_marker;
uint32_t msg_type;
int32_t comm_chan_id;
uint32_t controller_instance;
uint32_t err;
uint32_t e_marker;
};
struct i2c_ivc_msg_tx_rx_hdr {
int32_t seq_no;
uint32_t slave_address;
uint32_t slave_reg;
uint32_t buf_len;
uint32_t flags;
};
struct i2c_ivc_msg_tx_rx {
struct i2c_ivc_msg_tx_rx_hdr fixed;
uint8_t buffer[4096];
};
struct i2c_ivc_msg_max_payload {
uint32_t max_payload;
};
struct i2c_ivc_msg {
struct i2c_ivc_msg_common hdr;
union {
struct i2c_ivc_msg_tx_rx m;
struct i2c_ivc_msg_max_payload p;
} body;
};
#define I2C_IVC_COMMON_HEADER_LEN sizeof(struct i2c_ivc_msg_common)
#define i2c_ivc_start_marker(_msg_ptr) (_msg_ptr->hdr.s_marker)
#define i2c_ivc_end_marker(_msg_ptr) (_msg_ptr->hdr.e_marker)
#define i2c_ivc_chan_id(_msg_ptr) (_msg_ptr->hdr.comm_chan_id)
#define i2c_ivc_controller_instance(_msg_ptr) \
(_msg_ptr->hdr.controller_instance)
#define i2c_ivc_msg_type(_msg_ptr) (_msg_ptr->hdr.msg_type)
#define i2c_ivc_error_field(_msg_ptr) (_msg_ptr->hdr.err)
#define i2c_ivc_message_seq_nr(_msg_ptr) \
(_msg_ptr->body.m.fixed.seq_no)
#define i2c_ivc_message_slave_addr(_msg_ptr) \
(_msg_ptr->body.m.fixed.slave_address)
#define i2c_ivc_message_slave_reg(_msg_ptr) \
(_msg_ptr->body.m.fixed.slave_reg)
#define i2c_ivc_message_buf_len(_msg_ptr) \
(_msg_ptr->body.m.fixed.buf_len)
#define i2c_ivc_message_flags(_msg_ptr) (_msg_ptr->body.m.fixed.flags)
#define i2c_ivc_message_buffer(_msg_ptr) \
(_msg_ptr->body.m.buffer[0])
#define i2c_ivc_max_payload_field(_msg_ptr) \
(_msg_ptr->body.p.max_payload)
struct tegra_hv_i2c_comm_dev;
/* channel is virtual abstraction over a single ivc queue
* each channel holds messages that are independent of other channels
* we allocate one channel per i2c adapter as these can operate in parallel
*/
struct tegra_hv_i2c_comm_chan {
struct tegra_hv_ivc_cookie *ivck;
struct device *dev;
int id;
i2c_isr_handler handler;
void *data;
void *rcvd_data;
size_t data_len;
int *rcvd_err;
enum i2c_rx_state_t rx_state;
struct tegra_hv_i2c_comm_dev *hv_comm_dev;
spinlock_t lock;
};
struct tegra_hv_i2c_comm_dev {
uint32_t queue_id;
struct tegra_hv_ivc_cookie *ivck;
spinlock_t ivck_tx_lock;
spinlock_t lock;
struct hlist_node list;
struct work_struct work;
struct tegra_hv_i2c_comm_chan *hv_comm_chan[MAX_COMM_CHANS];
};
#endif
#endif
|