xref: /haiku/src/add-ons/kernel/busses/mmc/sdhci_pci.cpp (revision 5ac9b506412b11afb993bb52d161efe7666958a5)
1 /*
2  * Copyright 2018-2019 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  */
8 #include <new>
9 #include <stdio.h>
10 #include <string.h>
11 
12 #include <bus/PCI.h>
13 #include <PCI_x86.h>
14 
15 #include <KernelExport.h>
16 
17 #include "sdhci_pci.h"
18 
19 
20 #define TRACE_SDHCI
21 #ifdef TRACE_SDHCI
22 #	define TRACE(x...) dprintf("\33[33msdhci_pci:\33[0m " x)
23 #else
24 #	define TRACE(x...) ;
25 #endif
26 #define TRACE_ALWAYS(x...)	dprintf("\33[33msdhci_pci:\33[0m " x)
27 #define ERROR(x...)			dprintf("\33[33msdhci_pci:\33[0m " x)
28 #define CALLED(x...)		TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
29 
30 
31 #define SDHCI_PCI_DEVICE_MODULE_NAME "busses/mmc/sdhci_pci/driver_v1"
32 #define SDHCI_PCI_MMC_BUS_MODULE_NAME "busses/mmc/sdhci_pci/device/v1"
33 
34 #define SLOTS_COUNT				"device/slots_count"
35 #define SLOT_NUMBER				"device/slot"
36 #define BAR_INDEX				"device/bar"
37 
38 typedef struct {
39 	struct registers* fRegisters;
40 	uint8_t fIrq;
41 } sdhci_pci_mmc_bus_info;
42 
43 
44 device_manager_info* gDeviceManager;
45 device_module_info* gSDHCIDeviceController;
46 static pci_x86_module_info* sPCIx86Module;
47 
48 
49 static void
50 sdhci_register_dump(uint8_t slot, struct registers* regs)
51 {
52 #ifdef TRACE_SDHCI
53 	TRACE("Register values for slot %d:\n", slot);
54 	TRACE("system_address: %d\n", regs->system_address);
55 	TRACE("%d blocks of size %d\n", regs->block_count, regs->block_size);
56 	TRACE("argument: %d\n", regs->argument);
57 	TRACE("transfer_mode: %d\n", regs->transfer_mode);
58 	TRACE("command: %d\n", regs->command.Bits());
59 	TRACE("response:");
60 	for (int i = 0; i < 8; i++)
61 		dprintf(" %d", regs->response[i]);
62 	dprintf("\n");
63 	TRACE("buffer_data_port: %d\n", regs->buffer_data_port);
64 	TRACE("present_state: %x\n", regs->present_state.Bits());
65 	TRACE("power_control: %d\n", regs->power_control.Bits());
66 	TRACE("host_control: %d\n", regs->host_control);
67 	TRACE("wakeup_control: %d\n", regs->wakeup_control);
68 	TRACE("block_gap_control: %d\n", regs->block_gap_control);
69 	TRACE("clock_control: %x\n", regs->clock_control.Bits());
70 	TRACE("software_reset: %d\n", regs->software_reset.Bits());
71 	TRACE("timeout_control: %d\n", regs->timeout_control);
72 	TRACE("interrupt_status: %x enable: %x signal: %x\n",
73 		regs->interrupt_status, regs->interrupt_status_enable,
74 		regs->interrupt_signal_enable);
75 	TRACE("auto_cmd12_error_status: %d\n", regs->auto_cmd12_error_status);
76 	TRACE("capabilities: %lld\n", regs->capabilities.Bits());
77 	TRACE("max_current_capabilities: %lld\n",
78 		regs->max_current_capabilities);
79 	TRACE("slot_interrupt_status: %d\n", regs->slot_interrupt_status);
80 	TRACE("host_controller_version spec %x vendor %x\n",
81 		regs->host_controller_version.specVersion,
82 		regs->host_controller_version.vendorVersion);
83 #endif
84 }
85 
86 
87 static void
88 sdhci_reset(struct registers* regs)
89 {
90 	// if card is not present then no point of reseting the registers
91 	if (!regs->present_state.IsCardInserted())
92 		return;
93 
94 	// enabling software reset all
95 	regs->software_reset.ResetAll();
96 }
97 
98 
99 static void
100 sdhci_set_clock(struct registers* regs)
101 {
102 	int base_clock = regs->capabilities.BaseClockFrequency();
103 	// Try to get as close to 400kHz as possible, but not faster
104 	int divider = base_clock * 1000 / 400;
105 
106 	if (regs->host_controller_version.specVersion <= 1) {
107 		// Old controller only support power of two dividers up to 256,
108 		// round to next power of two up to 256
109 		if (divider > 256)
110 			divider = 256;
111 
112 		divider--;
113 		divider |= divider >> 1;
114 		divider |= divider >> 2;
115 		divider |= divider >> 4;
116 		divider++;
117 	}
118 
119 	divider = regs->clock_control.SetDivider(divider);
120 
121 	// Log the value after possible rounding by SetDivider (only even values
122 	// are allowed).
123 	TRACE("SDCLK frequency: %dMHz / %d = %dkHz\n", base_clock, divider,
124 		base_clock * 1000 / divider);
125 
126 	// We have set the divider, now we can enable the internal clock.
127 	regs->clock_control.EnableInternal();
128 
129 	// wait until internal clock is stabilized
130 	while (!(regs->clock_control.InternalStable()));
131 
132 	regs->clock_control.EnablePLL();
133 	while (!(regs->clock_control.InternalStable()));
134 
135 	// Finally, route the clock to the SD card
136 	regs->clock_control.EnableSD();
137 }
138 
139 
140 static void
141 sdhci_stop_clock(struct registers* regs)
142 {
143 	regs->clock_control.DisableSD();
144 }
145 
146 
147 static void
148 sdhci_set_power(struct registers* _regs)
149 {
150 	uint8_t supportedVoltages = _regs->capabilities.SupportedVoltages();
151 	if ((supportedVoltages & Capabilities::k3v3) != 0)
152 		_regs->power_control.SetVoltage(PowerControl::k3v3);
153 	else if ((supportedVoltages & Capabilities::k3v0) != 0)
154 		_regs->power_control.SetVoltage(PowerControl::k3v0);
155 	else if ((supportedVoltages & Capabilities::k1v8) != 0)
156 		_regs->power_control.SetVoltage(PowerControl::k1v8);
157 	else {
158 		_regs->power_control.PowerOff();
159 		ERROR("No voltage is supported\n");
160 		return;
161 	}
162 
163 	if (!_regs->present_state.IsCardInserted()) {
164 		TRACE("Card not inserted\n");
165 		return;
166 	}
167 
168 	TRACE("Execute CMD0\n");
169 	_regs->command.SendCommand(0, false);
170 
171 	DELAY(1000);
172 }
173 
174 
175 static status_t
176 init_bus(device_node* node, void** bus_cookie)
177 {
178 	CALLED();
179 	status_t status = B_OK;
180 	area_id	regs_area;
181 	volatile uint32_t* regs;
182 	uint8_t bar, slot;
183 
184 	sdhci_pci_mmc_bus_info* bus = new(std::nothrow) sdhci_pci_mmc_bus_info;
185 	if (bus == NULL)
186 		return B_NO_MEMORY;
187 
188 	pci_device_module_info* pci;
189 	pci_device* device;
190 
191 	device_node* parent = gDeviceManager->get_parent_node(node);
192 	device_node* pciParent = gDeviceManager->get_parent_node(parent);
193 	gDeviceManager->get_driver(pciParent, (driver_module_info**)&pci,
194 	        (void**)&device);
195 	gDeviceManager->put_node(pciParent);
196 	gDeviceManager->put_node(parent);
197 
198 	if (get_module(B_PCI_X86_MODULE_NAME, (module_info**)&sPCIx86Module)
199 	    != B_OK) {
200 	    sPCIx86Module = NULL;
201 		TRACE("PCIx86Module not loaded\n");
202 	}
203 
204 	if (gDeviceManager->get_attr_uint8(node, SLOT_NUMBER, &slot, false) < B_OK
205 		|| gDeviceManager->get_attr_uint8(node, BAR_INDEX, &bar, false) < B_OK)
206 		return -1;
207 
208 	TRACE("Register SD bus at slot %d, using bar %d\n", slot + 1, bar);
209 
210 	pci_info pciInfo;
211 	pci->get_pci_info(device, &pciInfo);
212 	int msiCount = sPCIx86Module->get_msi_count(pciInfo.bus,
213 		pciInfo.device, pciInfo.function);
214 	TRACE("interrupts count: %d\n",msiCount);
215 
216 	// enable bus master and io
217 	uint16 pcicmd = pci->read_pci_config(device, PCI_command, 2);
218 	pcicmd &= ~(PCI_command_int_disable | PCI_command_io);
219 	pcicmd |= PCI_command_master | PCI_command_memory;
220 	pci->write_pci_config(device, PCI_command, 2, pcicmd);
221 
222 	TRACE("init_bus() %p node %p pci %p device %p\n", bus, node,
223 		pci, device);
224 
225 	// mapping the registers by MMUIO method
226 	int bar_size = pciInfo->u.h0.base_register_sizes[bar];
227 
228 	regs_area = map_physical_memory("sdhc_regs_map",
229 		pciInfo.u.h0.base_registers[bar],
230 		pciInfo.u.h0.base_register_sizes[bar], B_ANY_KERNEL_BLOCK_ADDRESS,
231 		B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)&regs);
232 
233 	if (regs_area < B_OK) {
234 		TRACE("mapping failed");
235 		return B_BAD_VALUE;
236 	}
237 
238 	struct registers* _regs = (struct registers*)regs;
239 	bus->fRegisters = _regs;
240 	sdhci_reset(_regs);
241 
242 	// the interrupt is shared between all busses in an SDHC controller, but
243 	// they each register an handler. Not a problem, we will just test the
244 	// interrupt registers for all busses one after the other and find no
245 	// interrupts on the idle busses.
246 	bus->fIrq = pciInfo.u.h0.interrupt_line;
247 
248 	TRACE("irq interrupt line: %d\n", bus->fIrq);
249 
250 	if (bus->fIrq == 0 || bus->fIrq == 0xff) {
251 		TRACE("PCI IRQ not assigned\n");
252 		if (sPCIx86Module != NULL) {
253 			put_module(B_PCI_X86_MODULE_NAME);
254 			sPCIx86Module = NULL;
255 		}
256 		delete_area(regs_area);
257 		delete bus;
258 		return B_ERROR;
259 	}
260 
261 	status = install_io_interrupt_handler(bus->fIrq,
262 		sdhci_generic_interrupt, bus, 0);
263 
264 	if (status != B_OK) {
265 		TRACE("can't install interrupt handler\n");
266 		if (sPCIx86Module != NULL) {
267 			put_module(B_PCI_X86_MODULE_NAME);
268 			sPCIx86Module = NULL;
269 		}
270 		delete_area(regs_area);
271 		delete bus;
272 		return status;
273 	}
274 	TRACE("interrupt handler installed\n");
275 
276 	_regs->interrupt_status_enable = SDHCI_INT_CMD_CMP
277 		| SDHCI_INT_TRANS_CMP | SDHCI_INT_CARD_INS | SDHCI_INT_CARD_REM
278 		| SDHCI_INT_TIMEOUT | SDHCI_INT_CRC | SDHCI_INT_INDEX
279 		| SDHCI_INT_BUS_POWER | SDHCI_INT_END_BIT;
280 	_regs->interrupt_signal_enable =  SDHCI_INT_CMD_CMP
281 		| SDHCI_INT_TRANS_CMP | SDHCI_INT_CARD_INS | SDHCI_INT_CARD_REM
282 		| SDHCI_INT_TIMEOUT | SDHCI_INT_CRC | SDHCI_INT_INDEX
283 		| SDHCI_INT_BUS_POWER | SDHCI_INT_END_BIT;
284 
285 	sdhci_register_dump(slot, _regs);
286 	sdhci_set_clock(_regs);
287 	sdhci_set_power(_regs);
288 
289 	*bus_cookie = bus;
290 	return status;
291 }
292 
293 
294 static void
295 uninit_bus(void* bus_cookie)
296 {
297 	sdhci_pci_mmc_bus_info* bus = (sdhci_pci_mmc_bus_info*)bus_cookie;
298 
299 	bus->fRegisters->interrupt_signal_enable = 0;
300 	bus->fRegisters->interrupt_status_enable = 0;
301 
302 	remove_io_interrupt_handler(bus->fIrq, sdhci_generic_interrupt, bus);
303 
304 	area_id regs_area = area_for(bus->fRegisters);
305 	delete_area(regs_area);
306 
307 	// FIXME do we need to put() the PCI module here?
308 
309 	delete bus;
310 }
311 
312 
313 void
314 sdhci_error_interrupt_recovery(struct registers* _regs)
315 {
316 	_regs->interrupt_signal_enable &= ~(SDHCI_INT_CMD_CMP
317 		| SDHCI_INT_TRANS_CMP | SDHCI_INT_CARD_INS | SDHCI_INT_CARD_REM);
318 
319 	if (_regs->interrupt_status & 7)
320 		_regs->software_reset.ResetTransaction();
321 
322 	int16_t erorr_status = _regs->interrupt_status;
323 	_regs->interrupt_status &= ~(erorr_status);
324 }
325 
326 
327 int32
328 sdhci_generic_interrupt(void* data)
329 {
330 	sdhci_pci_mmc_bus_info* bus = (sdhci_pci_mmc_bus_info*)data;
331 	uint32_t intmask = bus->fRegisters->slot_interrupt_status;
332 
333 	if ((intmask == 0) || (intmask == 0xffffffff)) {
334 		return B_UNHANDLED_INTERRUPT;
335 	}
336 
337 	TRACE("interrupt function called\n");
338 
339 	// handling card presence interrupt
340 	if (intmask & (SDHCI_INT_CARD_INS | SDHCI_INT_CARD_REM)) {
341 		uint32_t card_present = ((intmask & SDHCI_INT_CARD_INS) != 0);
342 		bus->fRegisters->interrupt_status_enable &= ~(SDHCI_INT_CARD_INS
343 			| SDHCI_INT_CARD_REM);
344 		bus->fRegisters->interrupt_signal_enable &= ~(SDHCI_INT_CARD_INS
345 			| SDHCI_INT_CARD_REM);
346 
347 		bus->fRegisters->interrupt_status_enable |= card_present
348 		 	? SDHCI_INT_CARD_REM : SDHCI_INT_CARD_INS;
349 		bus->fRegisters->interrupt_signal_enable |= card_present
350 			? SDHCI_INT_CARD_REM : SDHCI_INT_CARD_INS;
351 
352 		bus->fRegisters->interrupt_status |= (intmask &
353 			(SDHCI_INT_CARD_INS | SDHCI_INT_CARD_REM));
354 		TRACE("Card presence interrupt handled\n");
355 
356 		return B_HANDLED_INTERRUPT;
357 	}
358 
359 	// handling command interrupt
360 	if (intmask & SDHCI_INT_CMD_MASK) {
361 		bus->fRegisters->interrupt_status |= (intmask & SDHCI_INT_CMD_MASK);
362 		// TODO do something with the interrupt
363 		TRACE("Command interrupt handled\n");
364 
365 		return B_HANDLED_INTERRUPT;
366 	}
367 
368 	// handling bus power interrupt
369 	if (intmask & SDHCI_INT_BUS_POWER) {
370 		bus->fRegisters->interrupt_status |= SDHCI_INT_BUS_POWER;
371 		TRACE("card is consuming too much power\n");
372 
373 		return B_HANDLED_INTERRUPT;
374 	}
375 
376 	intmask = bus->fRegisters->slot_interrupt_status;
377 	if (intmask != 0) {
378 		ERROR("Remaining interrupts at end of handler: %x\n", intmask);
379 		intmask &= ~(SDHCI_INT_BUS_POWER | SDHCI_INT_CARD_INS
380 			| SDHCI_INT_CARD_REM | SDHCI_INT_CMD_MASK);
381 	}
382 
383 	return B_UNHANDLED_INTERRUPT;
384 }
385 
386 
387 static void
388 bus_removed(void* bus_cookie)
389 {
390 	return;
391 }
392 
393 
394 static status_t
395 register_child_devices(void* cookie)
396 {
397 	CALLED();
398 	device_node* node = (device_node*)cookie;
399 	device_node* parent = gDeviceManager->get_parent_node(node);
400 	pci_device_module_info* pci;
401 	pci_device* device;
402 	uint8 slots_count, bar, slotsInfo;
403 
404 	gDeviceManager->get_driver(parent, (driver_module_info**)&pci,
405 		(void**)&device);
406 	uint16 pciSubDeviceId = pci->read_pci_config(device, PCI_subsystem_id, 2);
407 	slotsInfo = pci->read_pci_config(device, SDHCI_PCI_SLOT_INFO, 1);
408 	bar = SDHCI_PCI_SLOT_INFO_FIRST_BASE_INDEX(slotsInfo);
409 	slots_count = SDHCI_PCI_SLOTS(slotsInfo);
410 
411 	char prettyName[25];
412 
413 	if (slots_count > 6 || bar > 5) {
414 		TRACE("Invalid slots count: %d or BAR count: %d \n", slots_count, bar);
415 		return B_BAD_VALUE;
416 	}
417 
418 	for (uint8_t slot = 0; slot <= slots_count; slot++) {
419 
420 		bar = bar + slot;
421 		sprintf(prettyName, "SDHC bus %" B_PRIu16 " slot %"
422 			B_PRIu8, pciSubDeviceId, slot);
423 		device_attr attrs[] = {
424 			// properties of this controller for SDHCI bus manager
425 			{ B_DEVICE_PRETTY_NAME, B_STRING_TYPE,
426 				{ string: prettyName }},
427 			{ B_DEVICE_FIXED_CHILD, B_STRING_TYPE,
428 				{string: SDHCI_BUS_CONTROLLER_MODULE_NAME}},
429 			{SDHCI_DEVICE_TYPE_ITEM, B_UINT16_TYPE,
430 				{ ui16: pciSubDeviceId}},
431 			{B_DEVICE_BUS, B_STRING_TYPE,{string: "mmc"}},
432 			{SLOT_NUMBER, B_UINT8_TYPE,
433 				{ ui8: slot}},
434 			{BAR_INDEX, B_UINT8_TYPE,
435 				{ ui8: bar}},
436 			{ NULL }
437 		};
438 		if (gDeviceManager->register_node(node, SDHCI_PCI_MMC_BUS_MODULE_NAME,
439 				attrs, NULL, &node) != B_OK)
440 			return B_BAD_VALUE;
441 	}
442 	return B_OK;
443 }
444 
445 
446 static status_t
447 init_device(device_node* node, void** device_cookie)
448 {
449 	CALLED();
450 	*device_cookie = node;
451 	return B_OK;
452 }
453 
454 
455 static status_t
456 register_device(device_node* parent)
457 {
458 	device_attr attrs[] = {
459 		{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "SD Host Controller"}},
460 		{}
461 	};
462 
463 	return gDeviceManager->register_node(parent, SDHCI_PCI_DEVICE_MODULE_NAME,
464 		attrs, NULL, NULL);
465 }
466 
467 
468 static float
469 supports_device(device_node* parent)
470 {
471 	CALLED();
472 	const char* bus;
473 	uint16 type, subType;
474 	uint8 pciSubDeviceId;
475 
476 	// make sure parent is a PCI SDHCI device node
477 	if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false)
478 		!= B_OK || gDeviceManager->get_attr_uint16(parent, B_DEVICE_SUB_TYPE,
479 		&subType, false) < B_OK || gDeviceManager->get_attr_uint16(parent,
480 		B_DEVICE_TYPE, &type, false) < B_OK)
481 		return -1;
482 
483 	if (strcmp(bus, "pci") != 0)
484 		return 0.0f;
485 
486 	if (type == PCI_base_peripheral) {
487 		if (subType != PCI_sd_host)
488 			return 0.0f;
489 
490 		pci_device_module_info* pci;
491 		pci_device* device;
492 		gDeviceManager->get_driver(parent, (driver_module_info**)&pci,
493 			(void**)&device);
494 		pciSubDeviceId = pci->read_pci_config(device, PCI_revision, 1);
495 		TRACE("SDHCI Device found! Subtype: 0x%04x, type: 0x%04x\n",
496 			subType, type);
497 		return 0.8f;
498 	}
499 
500 	return 0.0f;
501 }
502 
503 
504 module_dependency module_dependencies[] = {
505 	{ SDHCI_BUS_CONTROLLER_MODULE_NAME, (module_info**)&gSDHCIDeviceController},
506 	{ B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager },
507 	{}
508 };
509 
510 
511 static sdhci_mmc_bus_interface gSDHCIPCIDeviceModule = {
512 	{
513 		{
514 			SDHCI_PCI_MMC_BUS_MODULE_NAME,
515 			0,
516 			NULL
517 		},
518 		NULL,	// supports device
519 		NULL,	// register device
520 		init_bus,
521 		uninit_bus,
522 		NULL,	// register child devices
523 		NULL,	// rescan
524 		bus_removed,
525 	}
526 };
527 
528 
529 static driver_module_info sSDHCIDevice = {
530 	{
531 		SDHCI_PCI_DEVICE_MODULE_NAME,
532 		0,
533 		NULL
534 	},
535 	supports_device,
536 	register_device,
537 	init_device,
538 	NULL,	// uninit
539 	register_child_devices,
540 	NULL,	// rescan
541 	NULL,	// device removed
542 };
543 
544 
545 module_info* modules[] = {
546 	(module_info* )&sSDHCIDevice,
547 	(module_info* )&gSDHCIPCIDeviceModule,
548 	NULL
549 };
550