1 /*-
2  * Copyright (c) 2021 Beckhoff Automation GmbH & Co. KG
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  *
25  */
26 
27 #ifndef _LINUX_I2C_H_
28 #define	_LINUX_I2C_H_
29 
30 #include <sys/types.h>
31 #include <sys/errno.h>
32 #include <sys/systm.h>
33 
34 #include <linux/device.h>
35 
36 #define	I2C_MAX_ADAPTER_NAME_LENGTH	32
37 
38 #define	I2C_M_RD	0x0001
39 #define	I2C_M_NOSTART	0x0002
40 #define	I2C_M_STOP	0x0004
41 
42 /* No need for us */
43 #define	I2C_FUNC_I2C			0
44 #define	I2C_FUNC_SMBUS_EMUL		0
45 #define	I2C_FUNC_SMBUS_READ_BLOCK_DATA	0
46 #define	I2C_FUNC_SMBUS_BLOCK_PROC_CALL	0
47 #define	I2C_FUNC_10BIT_ADDR		0
48 
49 #define	I2C_CLASS_DDC	0x8
50 #define	I2C_CLASS_SPD	0x80
51 
52 struct i2c_adapter {
53 	struct module *owner;
54 	unsigned int class;
55 
56 	char name[I2C_MAX_ADAPTER_NAME_LENGTH];
57 	struct device dev;
58 
59 	const struct i2c_lock_operations *lock_ops;
60 	const struct i2c_algorithm *algo;
61 	void *algo_data;
62 
63 	int retries;
64 	void *data;
65 };
66 
67 struct i2c_msg {
68 	uint16_t addr;
69 	uint16_t flags;
70 	uint16_t len;
71 	uint8_t *buf;
72 };
73 
74 struct i2c_algorithm {
75 	int (*master_xfer)(struct i2c_adapter *, struct i2c_msg *, int);
76 	uint32_t (*functionality)(struct i2c_adapter *);
77 };
78 
79 struct i2c_lock_operations {
80 	void (*lock_bus)(struct i2c_adapter *, unsigned int);
81 	int (*trylock_bus)(struct i2c_adapter *, unsigned int);
82 	void (*unlock_bus)(struct i2c_adapter *, unsigned int);
83 };
84 
85 int lkpi_i2c_add_adapter(struct i2c_adapter *adapter);
86 int lkpi_i2c_del_adapter(struct i2c_adapter *adapter);
87 
88 int lkpi_i2cbb_transfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int nmsgs);
89 
90 #define	i2c_add_adapter(adapter)	lkpi_i2c_add_adapter(adapter)
91 #define	i2c_del_adapter(adapter)	lkpi_i2c_del_adapter(adapter)
92 
93 #define	i2c_get_adapter(x)	NULL
94 #define	i2c_put_adapter(x)
95 
96 static inline int
97 do_i2c_transfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int nmsgs)
98 {
99 	int ret, retries;
100 
101 	retries = adapter->retries == 0 ? 1 : adapter->retries;
102 	for (; retries != 0; retries--) {
103 		if (adapter->algo != NULL && adapter->algo->master_xfer != NULL)
104 			ret = adapter->algo->master_xfer(adapter, msgs, nmsgs);
105 		else
106 			ret = lkpi_i2cbb_transfer(adapter, msgs, nmsgs);
107 		if (ret != -EAGAIN)
108 			break;
109 	}
110 
111 	return (ret);
112 }
113 
114 static inline int
115 i2c_transfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int nmsgs)
116 {
117 	int ret;
118 
119 	if (adapter->algo == NULL && adapter->algo_data == NULL)
120 		return (-EOPNOTSUPP);
121 
122 	if (adapter->lock_ops)
123 		adapter->lock_ops->lock_bus(adapter, 0);
124 
125 	ret = do_i2c_transfer(adapter, msgs, nmsgs);
126 
127 	if (adapter->lock_ops)
128 		adapter->lock_ops->unlock_bus(adapter, 0);
129 
130 	return (ret);
131 }
132 
133 /* Unlocked version of i2c_transfer */
134 static inline int
135 __i2c_transfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int nmsgs)
136 {
137 	return (do_i2c_transfer(adapter, msgs, nmsgs));
138 }
139 
140 static inline void
141 i2c_set_adapdata(struct i2c_adapter *adapter, void *data)
142 {
143 	adapter->data = data;
144 }
145 
146 static inline void *
147 i2c_get_adapdata(struct i2c_adapter *adapter)
148 {
149 	return (adapter->data);
150 }
151 
152 #endif	/* _LINUX_I2C_H_ */
153