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
23static_assert(B_HOST_IS_LENDIAN);
24
25union OcoresI2cRegsAddress7 {
26	struct {
27		uint8 read: 1;
28		uint8 address: 7;
29	};
30	uint8 val;
31};
32
33union OcoresI2cRegsControl {
34	struct {
35		uint8 unused1: 6;
36		uint8 intEnabled: 1;
37		uint8 enabled: 1;
38	};
39	uint8 val;
40};
41
42union 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
55union 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
67struct 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
84class OcoresI2c {
85public:
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
98private:
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
108private:
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
120extern device_manager_info* gDeviceManager;
121extern i2c_for_controller_interface* gI2c;
122extern i2c_sim_interface gOcoresI2cDriver;
123
124#endif	// _OCORES_I2C_H_
125