xref: /haiku/src/add-ons/kernel/busses/i2c/ocores/ocores_i2c.h (revision 85d9d60045d56e6a004b0bae5067a401573ea6d4)
1 /*
2  * Copyright 2022, Haiku, Inc.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #ifndef _OCORES_I2C_H_
8 #define _OCORES_I2C_H_
9 
10 #include <i2c.h>
11 #include <ByteOrder.h>
12 #include <assert.h>
13 
14 #include <AutoDeleterOS.h>
15 #include <lock.h>
16 
17 
18 #define CHECK_RET(err) {status_t _err = (err); if (_err < B_OK) return _err;}
19 
20 #define OCORES_I2C_DRIVER_MODULE_NAME "busses/i2c/ocores_i2c/driver_v1"
21 
22 
23 static_assert(B_HOST_IS_LENDIAN);
24 
25 union OcoresI2cRegsAddress7 {
26 	struct {
27 		uint8 read: 1;
28 		uint8 address: 7;
29 	};
30 	uint8 val;
31 };
32 
33 union OcoresI2cRegsControl {
34 	struct {
35 		uint8 unused1: 6;
36 		uint8 intEnabled: 1;
37 		uint8 enabled: 1;
38 	};
39 	uint8 val;
40 };
41 
42 union OcoresI2cRegsCommand {
43 	struct {
44 		uint8 intAck: 1;
45 		uint8 unused1: 2;
46 		uint8 nack: 1;
47 		uint8 write: 1;
48 		uint8 read: 1;
49 		uint8 stop: 1;
50 		uint8 start: 1;
51 	};
52 	uint8 val;
53 };
54 
55 union OcoresI2cRegsStatus {
56 	struct {
57 		uint8 interrupt: 1;
58 		uint8 transferInProgress: 1;
59 		uint8 reserved1: 3;
60 		uint8 arbitrationLost: 1;
61 		uint8 busy: 1;
62 		uint8 nackReceived: 1;
63 	};
64 	uint8 val;
65 };
66 
67 struct OcoresI2cRegs {
68 	uint8 preLo;
69 	uint8 align1[3];
70 	uint8 preHi;
71 	uint8 align2[3];
72 	OcoresI2cRegsControl control;
73 	uint8 align3[3];
74 	uint8 data;
75 	uint8 align4[3];
76 	union {
77 		OcoresI2cRegsCommand command;
78 		OcoresI2cRegsStatus status;
79 	};
80 	uint8 align5[3];
81 };
82 
83 
84 class OcoresI2c {
85 public:
86 	static float SupportsDevice(device_node* parent);
87 	static status_t RegisterDevice(device_node* parent);
88 	static status_t InitDriver(device_node* node, OcoresI2c*& outDriver);
89 	void UninitDriver();
90 
91 	void SetI2cBus(i2c_bus bus);
92 	status_t ExecCommand(i2c_op op,
93 		i2c_addr slaveAddress, const uint8 *cmdBuffer, size_t cmdLength,
94 		uint8* dataBuffer, size_t dataLength);
95 	status_t AcquireBus();
96 	void ReleaseBus();
97 
98 private:
99 	inline status_t InitDriverInt(device_node* node);
100 	static int32 InterruptReceived(void* arg);
101 	inline int32 InterruptReceivedInt();
102 
103 	status_t WaitCompletion();
104 	status_t WriteByte(OcoresI2cRegsCommand cmd, uint8 val);
105 	status_t ReadByte(OcoresI2cRegsCommand cmd, uint8& val);
106 	status_t WriteAddress(i2c_addr address, bool isRead);
107 
108 private:
109 	struct mutex fLock = MUTEX_INITIALIZER("Opencores i2c");
110 
111 	AreaDeleter fRegsArea;
112 	volatile OcoresI2cRegs* fRegs{};
113 	long fIrqVector = -1;
114 
115 	device_node* fNode{};
116 	i2c_bus fBus{};
117 };
118 
119 
120 extern device_manager_info* gDeviceManager;
121 extern i2c_for_controller_interface* gI2c;
122 extern i2c_sim_interface gOcoresI2cDriver;
123 
124 #endif	// _OCORES_I2C_H_
125