xref: /haiku/src/add-ons/kernel/bus_managers/i2c/I2CBus.cpp (revision 4b918abdb02a26a770d898594eaaccc6f1726e9b)
1 /*
2  * Copyright 2020, Jérôme Duval, jerome.duval@gmail.com.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "I2CPrivate.h"
8 
9 
10 I2CBus::I2CBus(device_node *node, uint8 id)
11 	:
12 	fNode(node),
13 	fID(id),
14 	fController(NULL),
15 	fCookie(NULL)
16 {
17 	CALLED();
18 	device_node *parent = gDeviceManager->get_parent_node(node);
19 	status_t status = gDeviceManager->get_driver(parent,
20 		(driver_module_info **)&fController, &fCookie);
21 	gDeviceManager->put_node(parent);
22 
23 	if (status != B_OK)
24 		return;
25 
26 	fController->set_i2c_bus(fCookie, this);
27 
28 }
29 
30 
31 I2CBus::~I2CBus()
32 {
33 }
34 
35 
36 status_t
37 I2CBus::InitCheck()
38 {
39 	return B_OK;
40 }
41 
42 
43 status_t
44 I2CBus::ExecCommand(i2c_op op, i2c_addr slaveAddress, const void *cmdBuffer,
45 	size_t cmdLength, void* dataBuffer, size_t dataLength)
46 {
47 	CALLED();
48 	return fController->exec_command(fCookie, op, slaveAddress, cmdBuffer, cmdLength,
49 		dataBuffer, dataLength);
50 }
51 
52 
53 status_t
54 I2CBus::RegisterDevice(i2c_addr slaveAddress, char* hid, char** cid,
55 	acpi_handle acpiHandle)
56 {
57 	CALLED();
58 
59 	device_attr attrs[] = {
60 		// connection
61 		{ I2C_DEVICE_SLAVE_ADDR_ITEM, B_UINT16_TYPE, { ui16: slaveAddress }},
62 
63 		// description of peripheral drivers
64 		{ B_DEVICE_BUS, B_STRING_TYPE, { string: "i2c" }},
65 
66 		{ B_DEVICE_FLAGS, B_UINT32_TYPE, { ui32: B_FIND_MULTIPLE_CHILDREN }},
67 
68 		{ ACPI_DEVICE_HID_ITEM, B_STRING_TYPE, { string: hid }},
69 
70 		{ ACPI_DEVICE_CID_ITEM, B_STRING_TYPE, { string: cid[0] }},
71 
72 		{ ACPI_DEVICE_HANDLE_ITEM, B_UINT64_TYPE, { ui64: (addr_t)acpiHandle }},
73 
74 		{ NULL }
75 	};
76 
77 	return gDeviceManager->register_node(fNode, I2C_DEVICE_MODULE_NAME, attrs,
78 		NULL, NULL);
79 }
80 
81 
82 status_t
83 I2CBus::Scan()
84 {
85 	CALLED();
86 	if (fController->scan_bus != NULL)
87 		fController->scan_bus(fCookie);
88 	return B_OK;
89 }
90 
91 
92 status_t
93 I2CBus::AcquireBus()
94 {
95 	CALLED();
96 	if (fController->acquire_bus != NULL)
97 		return fController->acquire_bus(fCookie);
98 	return B_OK;
99 }
100 
101 
102 void
103 I2CBus::ReleaseBus()
104 {
105 	CALLED();
106 	if (fController->release_bus != NULL)
107 		fController->release_bus(fCookie);
108 }
109 
110 
111 static status_t
112 i2c_init_bus(device_node *node, void **_bus)
113 {
114 	CALLED();
115 	uint8 pathID;
116 	if (gDeviceManager->get_attr_uint8(node, I2C_BUS_PATH_ID_ITEM, &pathID,
117 		false) != B_OK) {
118 		return B_ERROR;
119 	}
120 
121 	I2CBus *bus = new(std::nothrow) I2CBus(node, pathID);
122 	if (bus == NULL)
123 		return B_NO_MEMORY;
124 
125 	status_t result = bus->InitCheck();
126 	if (result != B_OK) {
127 		ERROR("failed to set up i2c bus object\n");
128 		return result;
129 	}
130 
131 	*_bus = bus;
132 
133 	char name[128];
134 	snprintf(name, sizeof(name), "bus/i2c/%d/bus_raw", pathID);
135 
136 	return gDeviceManager->publish_device(node, name, I2C_BUS_RAW_MODULE_NAME);
137 }
138 
139 
140 static void
141 i2c_uninit_bus(void *_bus)
142 {
143 	CALLED();
144 	I2CBus *bus = (I2CBus *)_bus;
145 	delete bus;
146 }
147 
148 
149 static status_t
150 i2c_scan_bus(void *_bus)
151 {
152 	I2CBus *bus = (I2CBus *)_bus;
153 	return bus->Scan();
154 }
155 
156 
157 status_t
158 i2c_bus_exec_command(void* _bus, i2c_op op, i2c_addr slaveAddress,
159 		const void *cmdBuffer, size_t cmdLength, void* dataBuffer,
160 		size_t dataLength)
161 {
162 	CALLED();
163 	I2CBus* bus = (I2CBus*)_bus;
164 	return bus->ExecCommand(op, slaveAddress, cmdBuffer, cmdLength,
165 		dataBuffer, dataLength);
166 }
167 
168 
169 static status_t
170 i2c_bus_acquire_bus(void* _bus)
171 {
172 	CALLED();
173 	I2CBus* bus = (I2CBus*)_bus;
174 	return bus->AcquireBus();
175 }
176 
177 
178 static void
179 i2c_bus_release_bus(void* _bus)
180 {
181 	CALLED();
182 	I2CBus* bus = (I2CBus*)_bus;
183 	return bus->ReleaseBus();
184 }
185 
186 
187 static status_t
188 std_ops(int32 op, ...)
189 {
190 	switch (op) {
191 		case B_MODULE_INIT:
192 		case B_MODULE_UNINIT:
193 			return B_OK;
194 
195 		default:
196 			break;
197 	}
198 
199 	return B_ERROR;
200 }
201 
202 
203 i2c_bus_interface gI2CBusModule = {
204 	{
205 		{
206 			I2C_BUS_MODULE_NAME,
207 			0,
208 			std_ops
209 		},
210 
211 		NULL, // supported devices
212 		NULL, // register node
213 		i2c_init_bus,
214 		i2c_uninit_bus,
215 		i2c_scan_bus, // register child devices
216 		NULL, // rescan
217 	},
218 
219 	i2c_bus_exec_command,
220 	i2c_bus_acquire_bus,
221 	i2c_bus_release_bus,
222 };
223 
224