xref: /haiku/src/add-ons/kernel/busses/mmc/sdhci_pci.cpp (revision dd2a1e350b303b855a50fd64e6cb55618be1ae6a)
1 /*
2  * Copyright 2018-2024 Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		B Krishnan Iyer, krishnaniyer97@gmail.com
7  *		Adrien Destugues, pulkomandy@pulkomandy.tk
8  *		Ron Ben Aroya, sed4906birdie@gmail.com
9  */
10 #include <algorithm>
11 #include <new>
12 #include <stdio.h>
13 #include <string.h>
14 
15 #include <bus/PCI.h>
16 #include <ACPI.h>
17 #include "acpi.h"
18 
19 #include <KernelExport.h>
20 
21 #include "IOSchedulerSimple.h"
22 #include "mmc.h"
23 #include "sdhci.h"
24 
25 
26 #define TRACE_SDHCI
27 #ifdef TRACE_SDHCI
28 #	define TRACE(x...) dprintf("\33[33msdhci:\33[0m " x)
29 #else
30 #	define TRACE(x...) ;
31 #endif
32 #define TRACE_ALWAYS(x...)	dprintf("\33[33msdhci:\33[0m " x)
33 #define ERROR(x...)			dprintf("\33[33msdhci:\33[0m " x)
34 #define CALLED(x...)		TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
35 
36 
37 #define SDHCI_DEVICE_MODULE_NAME "busses/mmc/sdhci/driver_v1"
38 #define SDHCI_PCI_MMC_BUS_MODULE_NAME "busses/mmc/sdhci/pci/device/v1"
39 
40 #define SLOT_NUMBER				"device/slot"
41 #define BAR_INDEX				"device/bar"
42 
43 status_t
44 init_bus_pci(device_node* node, void** bus_cookie)
45 {
46 	CALLED();
47 
48 	// Get the PCI driver and device
49 	pci_device_module_info* pci;
50 	pci_device* device;
51 
52 	device_node* parent = gDeviceManager->get_parent_node(node);
53 	device_node* pciParent = gDeviceManager->get_parent_node(parent);
54 	gDeviceManager->get_driver(pciParent, (driver_module_info**)&pci,
55 	        (void**)&device);
56 	gDeviceManager->put_node(pciParent);
57 	gDeviceManager->put_node(parent);
58 
59 	uint8_t bar, slot;
60 	if (gDeviceManager->get_attr_uint8(node, SLOT_NUMBER, &slot, false) < B_OK
61 		|| gDeviceManager->get_attr_uint8(node, BAR_INDEX, &bar, false) < B_OK)
62 		return B_BAD_TYPE;
63 
64 	// Ignore invalid bars
65 	TRACE("Register SD bus at slot %d, using bar %d\n", slot + 1, bar);
66 
67 	pci_info pciInfo;
68 	pci->get_pci_info(device, &pciInfo);
69 
70 	for (; bar < 6 && slot > 0; bar++, slot--) {
71 		if ((pciInfo.u.h0.base_register_flags[bar] & PCI_address_type)
72 			== PCI_address_type_64) {
73 			bar++;
74 		}
75 	}
76 
77 	phys_addr_t physicalAddress = pciInfo.u.h0.base_registers[bar];
78 	uint64 barSize = pciInfo.u.h0.base_register_sizes[bar];
79 	if ((pciInfo.u.h0.base_register_flags[bar] & PCI_address_type)
80 			== PCI_address_type_64) {
81 		physicalAddress |= (uint64)pciInfo.u.h0.base_registers[bar + 1] << 32;
82 		barSize |= (uint64)pciInfo.u.h0.base_register_sizes[bar + 1] << 32;
83 	}
84 
85 	if (physicalAddress == 0 || barSize == 0) {
86 		ERROR("No registers to map\n");
87 		return B_IO_ERROR;
88 	}
89 
90 	// enable bus master and io
91 	uint16 pcicmd = pci->read_pci_config(device, PCI_command, 2);
92 	pcicmd &= ~(PCI_command_int_disable | PCI_command_io);
93 	pcicmd |= PCI_command_master | PCI_command_memory;
94 	pci->write_pci_config(device, PCI_command, 2, pcicmd);
95 
96 	// map the slot registers
97 	area_id	regs_area;
98 	struct registers* _regs;
99 	regs_area = map_physical_memory("sdhc_regs_map",
100 		physicalAddress, barSize, B_ANY_KERNEL_BLOCK_ADDRESS,
101 		B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)&_regs);
102 
103 	if (regs_area < B_OK) {
104 		ERROR("Could not map registers\n");
105 		return B_BAD_VALUE;
106 	}
107 
108 	// the interrupt is shared between all busses in an SDHC controller, but
109 	// they each register an handler. Not a problem, we will just test the
110 	// interrupt registers for all busses one after the other and find no
111 	// interrupts on the idle busses.
112 	uint8_t irq = pciInfo.u.h0.interrupt_line;
113 	TRACE("irq interrupt line: %d\n", irq);
114 
115 	SdhciBus* bus = new(std::nothrow) SdhciBus(_regs, irq, false);
116 
117 	status_t status = B_NO_MEMORY;
118 	if (bus != NULL)
119 		status = bus->InitCheck();
120 
121 	if (status != B_OK) {
122 		if (bus != NULL)
123 			delete bus;
124 		else
125 			delete_area(regs_area);
126 		return status;
127 	}
128 
129 	// Store the created object as a cookie, allowing users of the bus to
130 	// locate it.
131 	*bus_cookie = bus;
132 
133 	return status;
134 }
135 
136 status_t
137 register_child_devices_pci(void* cookie)
138 {
139 	CALLED();
140 	SdhciDevice* context = (SdhciDevice*)cookie;
141 	device_node* parent = gDeviceManager->get_parent_node(context->fNode);
142 	pci_device_module_info* pci;
143 	pci_device* device;
144 
145 	gDeviceManager->get_driver(parent, (driver_module_info**)&pci,
146 		(void**)&device);
147 	uint8 slotsInfo = pci->read_pci_config(device, SDHCI_PCI_SLOT_INFO, 1);
148 	uint8 bar = SDHCI_PCI_SLOT_INFO_FIRST_BASE_INDEX(slotsInfo);
149 	uint8 slotsCount = SDHCI_PCI_SLOTS(slotsInfo);
150 
151 	TRACE("register_child_devices: %u, %u\n", bar, slotsCount);
152 
153 	char prettyName[25];
154 
155 	if (slotsCount > 6 || bar > 5) {
156 		ERROR("Invalid slots count: %d or BAR count: %d \n", slotsCount, bar);
157 		return B_BAD_VALUE;
158 	}
159 
160 	for (uint8_t slot = 0; slot < slotsCount; slot++) {
161 		sprintf(prettyName, "SDHC bus %" B_PRIu8, slot);
162 		device_attr attrs[] = {
163 			// properties of this controller for mmc bus manager
164 			{ B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { .string = prettyName } },
165 			{ B_DEVICE_FIXED_CHILD, B_STRING_TYPE,
166 				{.string = MMC_BUS_MODULE_NAME} },
167 			{ B_DEVICE_BUS, B_STRING_TYPE, {.string = "mmc"} },
168 
169 			// DMA properties
170 			// The high alignment is to force access only to complete sectors
171 			// These constraints could be removed by using ADMA which allows
172 			// use of the full 64bit address space and can do scatter-gather.
173 			{ B_DMA_ALIGNMENT, B_UINT32_TYPE, { .ui32 = 511 }},
174 			{ B_DMA_HIGH_ADDRESS, B_UINT64_TYPE, { .ui64 = 0x100000000LL }},
175 			{ B_DMA_BOUNDARY, B_UINT32_TYPE, { .ui32 = (1 << 19) - 1 }},
176 			{ B_DMA_MAX_SEGMENT_COUNT, B_UINT32_TYPE, { .ui32 = 1 }},
177 			{ B_DMA_MAX_SEGMENT_BLOCKS, B_UINT32_TYPE, { .ui32 = (1 << 10) - 1 }},
178 
179 			// private data to identify device
180 			{ SLOT_NUMBER, B_UINT8_TYPE, { .ui8 = slot} },
181 			{ BAR_INDEX, B_UINT8_TYPE, { .ui8 = bar} },
182 			{ NULL }
183 		};
184 		device_node* node;
185 		if (gDeviceManager->register_node(context->fNode,
186 				SDHCI_PCI_MMC_BUS_MODULE_NAME, attrs, NULL,
187 				&node) != B_OK)
188 			return B_BAD_VALUE;
189 	}
190 	return B_OK;
191 }
192 
193 status_t
194 init_device_pci(device_node* node, SdhciDevice* context)
195 {
196 	// Get the PCI driver and device
197 	pci_device_module_info* pci;
198 	pci_device* device;
199 	uint16 vendorId, deviceId;
200 
201 	device_node* pciParent = gDeviceManager->get_parent_node(context->fNode);
202 	gDeviceManager->get_driver(pciParent, (driver_module_info**)&pci,
203 	        (void**)&device);
204 	gDeviceManager->put_node(pciParent);
205 
206 	if (gDeviceManager->get_attr_uint16(node, B_DEVICE_VENDOR_ID,
207 			&vendorId, true) != B_OK
208 		|| gDeviceManager->get_attr_uint16(node, B_DEVICE_ID, &deviceId,
209 			true) != B_OK) {
210 		panic("No vendor or device id attribute\n");
211 		return B_OK; // Let's hope it didn't need the quirk?
212 	}
213 
214 	if (vendorId == 0x1180 && deviceId == 0xe823) {
215 		// Switch the device to SD2.0 mode
216 		// This should change its device id to 0xe822 if succesful.
217 		// The device then remains in SD2.0 mode even after reboot.
218 		pci->write_pci_config(device, SDHCI_PCI_RICOH_MODE_KEY, 1, 0xfc);
219 		context->fRicohOriginalMode = pci->read_pci_config(device,
220 			SDHCI_PCI_RICOH_MODE, 1);
221 		pci->write_pci_config(device, SDHCI_PCI_RICOH_MODE, 1,
222 			SDHCI_PCI_RICOH_MODE_SD20);
223 		pci->write_pci_config(device, SDHCI_PCI_RICOH_MODE_KEY, 1, 0);
224 
225 		deviceId = pci->read_pci_config(device, 2, 2);
226 		TRACE("Device ID after Ricoh quirk: %x\n", deviceId);
227 	}
228 
229 	return B_OK;
230 }
231 
232 void
233 uninit_device_pci(SdhciDevice* context, device_node* pciParent)
234 {
235 	// Get the PCI driver and device
236 	pci_device_module_info* pci;
237 	pci_device* device;
238 	uint16 vendorId, deviceId;
239 
240 	gDeviceManager->get_driver(pciParent, (driver_module_info**)&pci,
241 	        (void**)&device);
242 
243 	if (gDeviceManager->get_attr_uint16(context->fNode, B_DEVICE_VENDOR_ID,
244 			&vendorId, true) != B_OK
245 		|| gDeviceManager->get_attr_uint16(context->fNode, B_DEVICE_ID,
246 			&deviceId, false) != B_OK) {
247 		ERROR("No vendor or device id attribute\n");
248 	} else if (vendorId == 0x1180 && deviceId == 0xe823) {
249 		pci->write_pci_config(device, SDHCI_PCI_RICOH_MODE_KEY, 1, 0xfc);
250 		pci->write_pci_config(device, SDHCI_PCI_RICOH_MODE, 1,
251 			context->fRicohOriginalMode);
252 		pci->write_pci_config(device, SDHCI_PCI_RICOH_MODE_KEY, 1, 0);
253 	}
254 }
255 
256 float
257 supports_device_pci(device_node* parent)
258 {
259 	uint16 type, subType;
260 	uint16 vendorId, deviceId;
261 
262 	if (gDeviceManager->get_attr_uint16(parent, B_DEVICE_VENDOR_ID, &vendorId,
263 			false) != B_OK
264 		|| gDeviceManager->get_attr_uint16(parent, B_DEVICE_ID, &deviceId,
265 			false) != B_OK) {
266 		TRACE("No vendor or device id attribute\n");
267 		return 0.0f;
268 	}
269 
270 	TRACE("supports_device(vid:%04x pid:%04x)\n", vendorId, deviceId);
271 
272 	if (gDeviceManager->get_attr_uint16(parent, B_DEVICE_SUB_TYPE, &subType,
273 			false) < B_OK
274 		|| gDeviceManager->get_attr_uint16(parent, B_DEVICE_TYPE, &type,
275 			false) < B_OK) {
276 		TRACE("Could not find type/subtype attributes\n");
277 		return -1;
278 	}
279 
280 	if (type == PCI_base_peripheral) {
281 		if (subType != PCI_sd_host) {
282 			// Also accept some compliant devices that do not advertise
283 			// themselves as such.
284 			if (vendorId != 0x1180
285 				|| (deviceId != 0xe823 && deviceId != 0xe822)) {
286 				TRACE("Not the right subclass, and not a Ricoh device\n");
287 				return 0.0f;
288 			}
289 		}
290 
291 		pci_device_module_info* pci;
292 		pci_device* device;
293 		gDeviceManager->get_driver(parent, (driver_module_info**)&pci,
294 			(void**)&device);
295 		TRACE("SDHCI Device found! Subtype: 0x%04x, type: 0x%04x\n",
296 			subType, type);
297 
298 		return 0.8f;
299 	}
300 
301 	return 0.0f;
302 }
303 
304 // Device node registered for each SD slot. It implements the MMC operations so
305 // the bus manager can use it to communicate with SD cards.
306 mmc_bus_interface gSDHCIPCIDeviceModule = {
307 	.info = {
308 		.info = {
309 			.name = SDHCI_PCI_MMC_BUS_MODULE_NAME,
310 		},
311 
312 		.init_driver = init_bus_pci,
313 		.uninit_driver = uninit_bus,
314 		.device_removed = bus_removed,
315 	},
316 
317 	.set_clock = set_clock,
318 	.execute_command = execute_command,
319 	.do_io = do_io,
320 	.set_scan_semaphore = set_scan_semaphore,
321 	.set_bus_width = set_bus_width,
322 };