1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #ifndef I3C_CORE_H
10 #define I3C_CORE_H
11 
12 #include "i3c_if.h"
13 #include "hdf_base.h"
14 #include "hdf_dlist.h"
15 #include "osal_spinlock.h"
16 #include "platform_core.h"
17 
18 #ifdef __cplusplus
19 #if __cplusplus
20 extern "C" {
21 #endif
22 #endif /* __cplusplus */
23 
24 #define I3C_CNTLR_MAX   20
25 #define I3C_ADDR_MAX             127
26 #define I3C_IBI_MAX              10
27 #define ADDRS_STATUS_BITS        2
28 #define BITS_PER_UINT16          16
29 #define ADDRS_PER_UINT16         8
30 
31 #define ADDR_STATUS_BIT0_MASK    0x1
32 #define ADDR_STATUS_BIT1_MASK    0x2
33 #define ADDR_STATUS_MASK         0x3
34 
35 
36 #define I3C_RESERVED_ADDR_7H00    0x00
37 #define I3C_RESERVED_ADDR_7H01    0x01
38 #define I3C_RESERVED_ADDR_7H02    0x02
39 #define I3C_RESERVED_ADDR_7H3E    0x3e
40 #define I3C_RESERVED_ADDR_7H5E    0x5e
41 #define I3C_RESERVED_ADDR_7H6E    0x6e
42 #define I3C_RESERVED_ADDR_7H76    0x76
43 #define I3C_RESERVED_ADDR_7H78    0x78
44 #define I3C_RESERVED_ADDR_7H79    0x79
45 #define I3C_RESERVED_ADDR_7H7A    0x7a
46 #define I3C_RESERVED_ADDR_7H7B    0x7b
47 #define I3C_RESERVED_ADDR_7H7C    0x7c
48 #define I3C_RESERVED_ADDR_7H7D    0x7d
49 #define I3C_RESERVED_ADDR_7H7E    0x7e
50 #define I3C_RESERVED_ADDR_7H7F    0x7f
51 
52 #define I3C_HOT_JOIN_ADDR   I3C_RESERVED_ADDR_7H02
53 #define I3C_BROADCAST_ADDR  I3C_RESERVED_ADDR_7H7E
54 
55 struct I3cCntlr;
56 struct I3cMethod;
57 struct I3cLockMethod;
58 struct I3cDevice;
59 struct I3cVendor;
60 
61 enum I3cDeviceType {
62     /** I2C device */
63     I3C_CNTLR_I2C_DEVICE = 0,
64     /** legacy I2C device */
65     I3C_CNTLR_I2C_LEGACY_DEVICE,
66     /** I3C device */
67     I3C_CNTLR_I3C_DEVICE,
68 };
69 
70 struct I3cCntlr {
71     OsalSpinlock lock;
72     void *owner;
73     int16_t busId;
74     struct I3cConfig config;
75     uint16_t addrSlot[(I3C_ADDR_MAX + 1) / ADDRS_PER_UINT16];
76     struct I3cIbiInfo *ibiSlot[I3C_IBI_MAX];
77     const struct I3cMethod *ops;
78     const struct I3cLockMethod *lockOps;
79     void *priv;
80 };
81 
82 /* vendor information of I3C device */
83 struct I3cVendor {
84     uint32_t vendorMipiId;
85     uint32_t vendorVersionId;
86     uint32_t vendorProductId;
87 };
88 
89 /* In-bind Interrupt information */
90 struct I3cIbiInfo {
91     I3cIbiFunc ibiFunc;
92     uint32_t payload;
93     uint8_t *data;
94 };
95 
96 struct I3cDevice {
97     struct DListHead list;
98     struct I3cCntlr *cntlr;
99     uint16_t bcr;
100     uint16_t dcr;
101     uint64_t pid;
102     uint16_t addr;
103     enum I3cDeviceType type;
104     uint16_t dynaAddr;
105     uint16_t supportIbi;
106     struct I3cIbiInfo *ibi;
107     struct I3cVendor vendor;
108     void *devPriv;
109 };
110 
111 struct I3cMethod {
112     /**
113      * @brief Send a CCC(Common Command Code), which is implemented by a specific vendor driver.
114      *
115      * @param cntlr Indicates the I3C controller device.
116      * @param ccc Indicates the {@link I3cCccCmd}(Common Command Code) structure.
117      *
118      * @return Returns <b>0</b> on success; Returns a negative value otherwise.
119      * @since 1.0
120      */
121     int32_t (*sendCccCmd)(struct I3cCntlr *cntlr, struct I3cCccCmd *ccc);
122 
123     /**
124      * @brief Execute one or more I3C messages in I3C mode, which is implemented by a specific vendor driver.
125      *
126      * @param cntlr Indicates the I3C controller device.
127      * @param msgs Indicates the {@link I3cMsg} message array.
128      * @param count Indicates the length of the message array.
129      *
130      * @return Returns the number of transferred message structures on success; Returns a negative value otherwise.
131      *
132      * @see I3cMsg
133      * @since 1.0
134      */
135     int32_t (*Transfer)(struct I3cCntlr *cntlr, struct I3cMsg *msgs, int16_t count);
136 
137     /**
138      * @brief Execute one or more I3C messages in I2C mode, which is implemented by a specific vendor driver.
139      *
140      * @param cntlr Indicates the I3C controller device.
141      * @param msgs Indicates the {@link I3cMsg} message array.
142      * @param count Indicates the length of the message array.
143      *
144      * @return Returns the number of transferred message structures on success; Returns a negative value otherwise.
145      *
146      * @see I3cMsg
147      * @since 1.0
148      */
149     int32_t (*i2cTransfer)(struct I3cCntlr *cntlr, struct I3cMsg *msgs, int16_t count);
150 
151     /**
152      * @brief Set configurations of an I3C controller.
153      *
154      * @param cntlr Indicates the I3C controller to set.
155      * @param config Indicates the pointer of configuration structure.
156      *
157      * @return Returns <b>0</b> on success; Returns a negative value otherwise.
158      * @since 1.0
159      */
160     int32_t (*setConfig)(struct I3cCntlr *cntlr, struct I3cConfig *config);
161 
162     /**
163      * @brief Get configurations of an I3C controller.
164      *
165      * @param cntlr Indicates the I3C controller to get configurations.
166      * @param config Indicates the pointer of configuration structure.
167      *
168      * @return Returns <b>0</b> on success; Returns a negative value otherwise.
169      * @since 1.0
170      */
171     int32_t (*getConfig)(struct I3cCntlr *cntlr, struct I3cConfig *config);
172 
173     /**
174      * @brief Requeset an IBI(in-bind interrupt) for an I3C device which is supported.
175      *
176      * @param device Indicates the I3C device.
177      *
178      * @return Returns <b>0</b> on success; Returns a negative value otherwise.
179      * @since 1.0
180      */
181     int32_t (*requestIbi)(struct I3cDevice *dev);
182 
183     /**
184      * @brief Free an IBI(in-bind interrupt).
185      *
186      * @param device Indicates the I3C device.
187      *
188      * @return Returns <b>0</b> on success; Returns a negative value otherwise.
189      * @since 1.0
190      */
191     void (*freeIbi)(struct I3cDevice *dev);
192 };
193 
194 struct I3cLockMethod {
195     /**
196      * @brief Get exclusive access to an I3C controller.
197      *
198      * @param cntlr Indicates the I3C controller to access.
199      *
200      * @return Returns <b>0</b> on success; Returns a negative value otherwise.
201      * @since 1.0
202      */
203     int32_t (*lock)(struct I3cCntlr *cntlr);
204     /**
205      * @brief Release exclusive access to an I3C controller.
206      *
207      * @param cntlr Indicates the I3C controller to release.
208      *
209      * @since 1.0
210      */
211     void (*unlock)(struct I3cCntlr *cntlr);
212 };
213 
214 enum I3C_ERROR_CODE {
215     I3C_ERROR_UNKNOWN = 0,
216     I3C_ERROR_M0,
217     I3C_ERROR_M1,
218     I3C_ERROR_M2,
219     I3C_ERROR_S0,
220     I3C_ERROR_S1,
221     I3C_ERROR_S2,
222     I3C_ERROR_S3,
223     I3C_ERROR_S4,
224     I3C_ERROR_S5,
225     I3C_ERROR_S6,
226 };
227 
228 enum I3cAddrStatus {
229     I3C_ADDR_FREE = 0,
230     I3C_ADDR_RESERVED,
231     I3C_ADDR_I2C_DEVICE,
232     I3C_ADDR_I3C_DEVICE,
233 };
234 
235 enum I3cDeviceSupportIbi {
236     I3C_DEVICE_NOT_SUPPORT_IBI = 0,
237     I3C_DEVICE_SUPPORT_IBI,
238 };
239 
240 /**
241  * @brief Set the config of a I3C controller.
242  *
243  * @param cntlr Indicates the I3C controller device.
244  * @param config Indicates the pointer of the configuration structure.
245  *
246  * @return Returns <b>0</b> on success; Returns a negative value otherwise.
247  * @since 1.0
248  */
249 int32_t I3cCntlrSetConfig(struct I3cCntlr *cntlr, struct I3cConfig *config);
250 
251 /**
252  * @brief Get the config of a I3C controller.
253  *
254  * @param cntlr Indicates the I3C controller device.
255  * @param config Indicates the pointer of the configuration structure.
256  *
257  * @return Returns <b>0</b> on success; Returns a negative value otherwise.
258  * @since 1.0
259  */
260 int32_t I3cCntlrGetConfig(struct I3cCntlr *cntlr, struct I3cConfig *config);
261 
262 /**
263  * @brief Requeset an IBI(in-bind interrupt) for an I3C device which is supported.
264  *
265  * @param cntlr Indicates the I3C controller device.
266  * @param addr Indicates the address of device to requeset IBI(In-Band Interrupt).
267  * @param func Indicates the call back function of the IBI.
268  * @param payload Indicates the length of payload data, in bytes.
269  *
270  * @return Returns <b>0</b> on success; Returns a negative value otherwise.
271  * @since 1.0
272  */
273 int32_t I3cCntlrRequestIbi(struct I3cCntlr *cntlr, uint16_t addr, I3cIbiFunc func, uint32_t payload);
274 
275 /**
276  * @brief Free the IBI(in-bind interrupt) which is Requeseted by {@link I3cCntlrRequestIbi}.
277  *
278  * @param cntlr Indicates the I3C controller device.
279  * @param addr Indicates the address of device to requeset IBI(In-Band Interrupt).
280  *
281  * @return Returns <b>0</b> on success; Returns a negative value otherwise.
282  * @since 1.0
283  */
284 int32_t I3cCntlrFreeIbi(struct I3cCntlr *cntlr, uint16_t addr);
285 
286 /**
287  * @brief Send a CCC (Common Command Code) to an I3C device which is supported.
288  *
289  * @param cntlr Indicates the I3C controller device.
290  * @param ccc The pointer of CCC (Common Command Code) structure to send.
291  *
292  * @return Returns <b>0</b> on success; Returns a negative value otherwise.
293  * @since 1.0
294  */
295 int32_t I3cCntlrSendCccCmd(struct I3cCntlr *cntlr, struct I3cCccCmd *ccc);
296 
297 /**
298  * @brief Execute one or more I3C messages in I2C mode.
299  *
300  * @param cntlr Indicates the I3C controller device.
301  * @param msgs Indicates the {@link I3cMsg} message array.
302  * @param count Indicates the length of the message array.
303  *
304  * @return Returns the number of transferred message structures on success; Returns a negative value otherwise.
305  *
306  * @see I3cMsg
307  * @since 1.0
308  */
309 int32_t I3cCntlrI2cTransfer(struct I3cCntlr *cntlr, struct I3cMsg *msgs, int16_t count);
310 
311 /**
312  * @brief Execute one or more I3C messages in I3C mode.
313  *
314  * @param cntlr Indicates the I3C controller device.
315  * @param msgs Indicates the {@link I3cMsg} message array.
316  * @param count Indicates the length of the message array.
317  *
318  * @return Returns the number of transferred message structures on success; Returns a negative value otherwise.
319  *
320  * @see I3cMsg
321  * @since 1.0
322  */
323 int32_t I3cCntlrTransfer(struct I3cCntlr *cntlr, struct I3cMsg *msgs, int16_t count);
324 
325 /**
326  * @brief Add an I3C device or an I2C device to device list.
327  *
328  * @param device Indicates the I3C device or I2C device.
329  *
330  * @return Returns <b>0</b> on success; Returns a negative value otherwise.
331  * @since 1.0
332  */
333 int32_t I3cDeviceAdd(struct I3cDevice *device);
334 
335 /**
336  * @brief Remove an I3C device or an I2C device from device list.
337  *
338  * @param device Indicates the I3C device or I2C device.
339  *
340  * @return Returns <b>0</b> on success; Returns a negative value otherwise.
341  * @since 1.0
342  */
343 void I3cDeviceRemove(struct I3cDevice *device);
344 
345 /**
346  * @brief Find and return an I3C controller by number, with ref count.
347  *
348  * @param number Indicates the I3C controller to get.
349  *
350  * @return Returns an I3C controller object on success; Returns <b>NULL</b> otherwise.
351  *
352  * @since 1.0
353  */
354 struct I3cCntlr *I3cCntlrGet(int16_t number);
355 
356 /**
357  * @brief Release an I3C controller obtained by {@link I3cCntlrGet}.
358  *
359  * @param number Indicates the I3C controller to get.
360  *
361  * @since 1.0
362  */
363 void I3cCntlrPut(struct I3cCntlr *cntlr);
364 
365 /**
366  * @brief Add an I3C controller to controller list.
367  *
368  * @param cntlr Indicates the I3C controller device.
369  *
370  * @return Returns <b>0</b> on success; Returns a negative value otherwise.
371  * @since 1.0
372  */
373 int32_t I3cCntlrAdd(struct I3cCntlr *cntlr);
374 
375 /**
376  * @brief Remove an I3C controller from controller list.
377  *
378  * @param cntlr Indicates the I3C controller device.
379  *
380  * @return Returns <b>0</b> on success; Returns a negative value otherwise.
381  * @since 1.0
382  */
383 void I3cCntlrRemove(struct I3cCntlr *cntlr);
384 
385 /**
386  * @brief Get an I3C device by addr.
387  *
388  * @param cntlr Indicates the I3C controller device.
389  * @param addr Indicates the address of the device which you would like to get.
390  *
391  * @return Returns <b>0</b> on success; Returns a negative value otherwise.
392  * @since 1.0
393  */
394 struct I3cDevice *I3cGetDeviceByAddr(const struct I3cCntlr *cntlr, uint16_t addr);
395 
396 /**
397  * @brief IBI(In-bind Interrupt) callback function.
398  *
399  * @param device Indicates the device that generated the IBI.
400  *
401  * @return Returns an I3C device object on success; Returns <b>NULL</b> otherwise.
402  *
403  * @since 1.0
404  */
405 int32_t I3cCntlrIbiCallback(struct I3cDevice *device);
406 
407 enum I3cIoCmd {
408     I3C_IO_I2C_TRANSFER = 0,
409     I3C_IO_PRIV_TRANSFER,
410     I3C_IO_OPEN,
411     I3C_IO_CLOSE,
412     I3C_IO_GET_CONFIG,
413     I3C_IO_SET_CONFIG,
414     I3C_IO_REQUEST_IBI,
415     I3C_IO_FREE_IBI,
416 };
417 
418 int I3cCheckReservedAddr(uint16_t addr);
419 
420 #ifdef __cplusplus
421 #if __cplusplus
422 }
423 #endif
424 #endif /* __cplusplus */
425 
426 #endif /* I3C_CORE_H */
427