xref: /haiku/src/add-ons/kernel/busses/mmc/sdhci_pci.cpp (revision 7457ccb4b2f4786525d3b7bda42598487d57ab7d)
1 /*
2  * Copyright 2018 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 SDHCI_PCI_CONTROLLER_TYPE_NAME "sdhci pci controller"
35 
36 #define SLOTS_COUNT				"device/slots_count"
37 #define SLOT_NUMBER				"device/slot"
38 #define BAR_INDEX				"device/bar"
39 
40 typedef struct {
41 	pci_device_module_info* pci;
42 	pci_device* device;
43 	addr_t base_addr;
44 	uint8 irq;
45 	sdhci_mmc_bus mmc_bus;
46 	area_id regs_area;
47 	device_node* node;
48 	pci_info info;
49 	struct registers* _regs;
50 
51 } sdhci_pci_mmc_bus_info;
52 
53 
54 device_manager_info* gDeviceManager;
55 device_module_info* gSDHCIDeviceController;
56 static pci_x86_module_info* sPCIx86Module;
57 
58 
59 static void
60 sdhci_register_dump(uint8_t slot, struct registers* regs)
61 {
62 	TRACE("Register values for slot: %d\n", slot);
63 	TRACE("system_address: %d\n", regs->system_address);
64 	TRACE("block_size: %d\n", regs->block_size);
65 	TRACE("block_count: %d\n", regs->block_count);
66 	TRACE("argument: %d\n", regs->argument);
67 	TRACE("transfer_mode: %d\n", regs->transfer_mode);
68 	TRACE("command: %d\n", regs->command);
69 	TRACE("response0: %d\n", regs->response0);
70 	TRACE("response2: %d\n", regs->response2);
71 	TRACE("response4: %d\n", regs->response4);
72 	TRACE("response6: %d\n", regs->response6);
73 	TRACE("buffer_data_port: %d\n", regs->buffer_data_port);
74 	TRACE("present_state: %d\n", regs->present_state);
75 	TRACE("power_control: %d\n", regs->power_control);
76 	TRACE("host_control: %d\n", regs->host_control);
77 	TRACE("wakeup_control: %d\n", regs->wakeup_control);
78 	TRACE("block_gap_control: %d\n", regs->block_gap_control);
79 	TRACE("clock_control: %d\n", regs->clock_control);
80 	TRACE("software_reset: %d\n", regs->software_reset);
81 	TRACE("timeout_control: %d\n", regs->timeout_control);
82 	TRACE("interrupt_status: %d\n", regs->interrupt_status);
83 	TRACE("interrupt_status_enable: %d\n", regs->interrupt_status_enable);
84 	TRACE("interrupt_signal_enable: %d\n", regs->interrupt_signal_enable);
85 	TRACE("auto_cmd12_error_status: %d\n", regs->auto_cmd12_error_status);
86 	TRACE("capabilities: %d\n", regs->capabilities);
87 	TRACE("capabilities_rsvd: %d\n", regs->capabilities_rsvd);
88 	TRACE("max_current_capabilities: %d\n",
89 		regs->max_current_capabilities);
90 	TRACE("max_current_capabilities_rsvd: %d\n",
91 		regs->max_current_capabilities_rsvd);
92 	TRACE("slot_interrupt_status: %d\n", regs->slot_interrupt_status);
93 	TRACE("host_control_version %d\n", regs->host_control_version);
94 }
95 
96 
97 static void
98 sdhci_reset(struct registers* regs)
99 {
100 	// if card is not present then no point of reseting the registers
101 	if (!(regs->present_state & SDHCI_CARD_DETECT))
102 		return;
103 
104 	// enabling software reset all
105 	regs->software_reset |= SDHCI_SOFTWARE_RESET_ALL;
106 
107 	// waiting for clock and power to get off
108 	while (regs->clock_control != 0 && regs->power_control != 0);
109 }
110 
111 
112 static void
113 sdhci_set_clock(struct registers* regs, uint16_t base_clock_div)
114 {
115 	uint32_t clock_control = regs->clock_control;
116 	int base_clock = SDHCI_BASE_CLOCK_FREQ(regs->capabilities);
117 
118 	TRACE("SDCLK frequency: %dMHz\n", base_clock);
119 
120 	// clearing previous frequency
121 	clock_control &= SDHCI_CLR_FREQ_SEL;
122 	clock_control |= base_clock_div;
123 
124 	// enabling internal clock
125 	clock_control |= SDHCI_INTERNAL_CLOCK_ENABLE;
126 	regs->clock_control = clock_control;
127 
128 	// waiting till internal clock gets stable
129 	while (!(regs->clock_control & SDHCI_INTERNAL_CLOCK_STABLE));
130 
131 	regs->clock_control |= SDHCI_SD_CLOCK_ENABLE; // enabling the SD clock
132 }
133 
134 
135 static void
136 sdhci_stop_clock(struct registers* regs)
137 {
138 	regs->clock_control &= SDHCI_SD_CLOCK_DISABLE;
139 }
140 
141 
142 static void
143 sdhci_set_power(struct registers* _regs)
144 {
145 	uint16_t command = _regs->command;
146 
147 	if (SDHCI_VOLTAGE_SUPPORTED(_regs->capabilities))
148 		if (SDHCI_VOLTAGE_SUPPORTED_33(_regs->capabilities))
149 			_regs->power_control |= SDHCI_VOLTAGE_SUPPORT_33;
150 		else if (SDHCI_VOLTAGE_SUPPORTED_30(_regs->capabilities))
151 			_regs->power_control |= SDHCI_VOLTAGE_SUPPORT_30;
152 		else
153 			_regs->power_control |= SDHCI_VOLTAGE_SUPPORT_18;
154 	else
155 		TRACE("No voltage is supported\n");
156 
157 	if (SDHCI_CARD_INSERTED(_regs->present_state) == 0) {
158 		TRACE("Card not inserted\n");
159 		return;
160 	}
161 
162 	_regs->power_control |= SDHCI_BUS_POWER_ON;
163 	TRACE("Executed CMD0\n");
164 
165 	command = SDHCI_RESPONSE_R1 | SDHCI_CMD_CRC_EN
166 		| SDHCI_CMD_INDEX_EN | SDHCI_CMD_0;
167 	_regs->command |= command;
168 
169 	DELAY(1000);
170 }
171 
172 
173 static status_t
174 init_bus(device_node* node, void** bus_cookie)
175 {
176 	CALLED();
177 	status_t status = B_OK;
178 	area_id	regs_area;
179 	volatile uint32_t* regs;
180 	uint8_t bar, slot;
181 
182 	sdhci_pci_mmc_bus_info* bus = new(std::nothrow) sdhci_pci_mmc_bus_info;
183 	if (bus == NULL)
184 		return B_NO_MEMORY;
185 
186 	pci_info* pciInfo = &bus->info;
187 	pci_device_module_info* pci;
188 	pci_device* device;
189 
190 	device_node* parent = gDeviceManager->get_parent_node(node);
191 	device_node* pciParent = gDeviceManager->get_parent_node(parent);
192 	gDeviceManager->get_driver(pciParent, (driver_module_info**)&pci,
193 	        (void**)&device);
194 	gDeviceManager->put_node(pciParent);
195 	gDeviceManager->put_node(parent);
196 
197 	if (get_module(B_PCI_X86_MODULE_NAME, (module_info**)&sPCIx86Module)
198 	    != B_OK) {
199 	    sPCIx86Module = NULL;
200 		TRACE("PCIx86Module not loaded\n");
201 	}
202 
203 	int msiCount = sPCIx86Module->get_msi_count(pciInfo->bus,
204 		pciInfo->device, pciInfo->function);
205 
206 	TRACE("interrupts count: %d\n",msiCount);
207 
208 	if (gDeviceManager->get_attr_uint8(node, SLOT_NUMBER, &slot, false) < B_OK
209 		|| gDeviceManager->get_attr_uint8(node, BAR_INDEX, &bar, false) < B_OK)
210 		return -1;
211 
212 	bus->node = node;
213 	bus->pci = pci;
214 	bus->device = device;
215 
216 	pci->get_pci_info(device, pciInfo);
217 
218 	// legacy interrupt
219 	bus->base_addr = pciInfo->u.h0.base_registers[bar];
220 
221 	// enable bus master and io
222 	uint16 pcicmd = pci->read_pci_config(device, PCI_command, 2);
223 	pcicmd &= ~(PCI_command_int_disable | PCI_command_io);
224 	pcicmd |= PCI_command_master | PCI_command_memory;
225 	pci->write_pci_config(device, PCI_command, 2, pcicmd);
226 
227 	TRACE("init_bus() %p node %p pci %p device %p\n", bus, node,
228 		bus->pci, bus->device);
229 
230 	// mapping the registers by MMUIO method
231 	int bar_size = pciInfo->u.h0.base_register_sizes[bar];
232 
233 	regs_area = map_physical_memory("sdhc_regs_map",
234 		pciInfo->u.h0.base_registers[bar],
235 		pciInfo->u.h0.base_register_sizes[bar], B_ANY_KERNEL_BLOCK_ADDRESS,
236 		B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)&regs);
237 
238 	if (regs_area < B_OK) {
239 		TRACE("mapping failed");
240 		return B_BAD_VALUE;
241 	}
242 
243 	bus->regs_area = regs_area;
244 	struct registers* _regs = (struct registers*)regs;
245 	bus->_regs = _regs;
246 	sdhci_reset(_regs);
247 	bus->irq = pciInfo->u.h0.interrupt_line;
248 
249 	TRACE("irq interrupt line: %d\n",bus->irq);
250 
251 	if (bus->irq == 0 || bus->irq == 0xff) {
252 		TRACE("PCI IRQ not assigned\n");
253 		if (sPCIx86Module != NULL) {
254 			put_module(B_PCI_X86_MODULE_NAME);
255 			sPCIx86Module = NULL;
256 		}
257 		delete bus;
258 		return B_ERROR;
259 	}
260 
261 	status = install_io_interrupt_handler(bus->irq,
262 		sdhci_generic_interrupt, bus, 0);
263 
264 	if (status != B_OK) {
265 		TRACE("can't install interrupt handler\n");
266 		return status;
267 	}
268 	TRACE("interrupt handler installed\n");
269 
270 	_regs->interrupt_status_enable = SDHCI_INT_CMD_CMP
271 		| SDHCI_INT_TRANS_CMP | SDHCI_INT_CARD_INS | SDHCI_INT_CARD_REM
272 		| SDHCI_INT_TIMEOUT | SDHCI_INT_CRC | SDHCI_INT_INDEX
273 		| SDHCI_INT_BUS_POWER | SDHCI_INT_END_BIT;
274 	_regs->interrupt_signal_enable =  SDHCI_INT_CMD_CMP
275 		| SDHCI_INT_TRANS_CMP | SDHCI_INT_CARD_INS | SDHCI_INT_CARD_REM
276 		| SDHCI_INT_TIMEOUT | SDHCI_INT_CRC | SDHCI_INT_INDEX
277 		| SDHCI_INT_BUS_POWER | SDHCI_INT_END_BIT;
278 
279 	sdhci_register_dump(slot, _regs);
280 	sdhci_set_clock(_regs, SDHCI_BASE_CLOCK_DIV_128);
281 	sdhci_set_power(_regs);
282 	sdhci_register_dump(slot, _regs);
283 
284 	*bus_cookie = bus;
285 	return status;
286 }
287 
288 
289 void
290 sdhci_error_interrupt_recovery(struct registers* _regs)
291 {
292 	_regs->interrupt_signal_enable &= ~(SDHCI_INT_CMD_CMP
293 		| SDHCI_INT_TRANS_CMP | SDHCI_INT_CARD_INS | SDHCI_INT_CARD_REM);
294 
295 	if (_regs->interrupt_status & 7) {
296 		_regs->software_reset |= 1 << 1;
297 		while (_regs->command);
298 	}
299 
300 	int16_t erorr_status = _regs->interrupt_status;
301 	_regs->interrupt_status &= ~(erorr_status);
302 }
303 
304 
305 int32
306 sdhci_generic_interrupt(void* data)
307 {
308 	TRACE("interrupt function called\n");
309 	sdhci_pci_mmc_bus_info* bus = (sdhci_pci_mmc_bus_info*)data;
310 
311 	uint16_t intmask, card_present;
312 
313 	intmask = bus->_regs->slot_interrupt_status;
314 
315 	if (intmask == 0 || intmask == 0xffffffff) {
316 		TRACE("invalid command interrupt\n");
317 
318 		return B_UNHANDLED_INTERRUPT;
319 	}
320 
321 	// handling card presence interrupt
322 	if (intmask & (SDHCI_INT_CARD_INS | SDHCI_INT_CARD_REM)) {
323 		card_present = ((intmask & SDHCI_INT_CARD_INS) != 0);
324 		bus->_regs->interrupt_status_enable &= ~(SDHCI_INT_CARD_INS
325 			| SDHCI_INT_CARD_REM);
326 		bus->_regs->interrupt_signal_enable &= ~(SDHCI_INT_CARD_INS
327 			| SDHCI_INT_CARD_REM);
328 
329 		bus->_regs->interrupt_status_enable |= card_present
330 		 	? SDHCI_INT_CARD_REM : SDHCI_INT_CARD_INS;
331 		bus->_regs->interrupt_signal_enable |= card_present
332 			? SDHCI_INT_CARD_REM : SDHCI_INT_CARD_INS;
333 
334 		bus->_regs->interrupt_status |= (intmask &
335 			(SDHCI_INT_CARD_INS | SDHCI_INT_CARD_REM));
336 		TRACE("Card presence interrupt handled\n");
337 
338 		return B_HANDLED_INTERRUPT;
339 	}
340 
341 	// handling command interrupt
342 	if (intmask & SDHCI_INT_CMD_MASK) {
343 		TRACE("interrupt status error: %d\n", bus->_regs->interrupt_status);
344 		bus->_regs->interrupt_status |= (intmask & SDHCI_INT_CMD_MASK);
345 		TRACE("Command interrupt handled\n");
346 
347 		return B_HANDLED_INTERRUPT;
348 	}
349 
350 	// handling bus power interrupt
351 	if (intmask & SDHCI_INT_BUS_POWER) {
352 		bus->_regs->interrupt_status |= SDHCI_INT_BUS_POWER;
353 		TRACE("card is consuming too much power\n");
354 
355 		return B_HANDLED_INTERRUPT;
356 	}
357 
358 	intmask &= ~(SDHCI_INT_BUS_POWER | SDHCI_INT_CARD_INS
359 		|SDHCI_INT_CARD_REM | SDHCI_INT_CMD_MASK);
360 
361 }
362 
363 
364 static void
365 uninit_bus(void* bus_cookie)
366 {
367 	sdhci_pci_mmc_bus_info* bus = (sdhci_pci_mmc_bus_info*)bus_cookie;
368 	delete bus;
369 }
370 
371 
372 static void
373 bus_removed(void* bus_cookie)
374 {
375 	return;
376 }
377 
378 
379 static status_t
380 register_child_devices(void* cookie)
381 {
382 	CALLED();
383 	device_node* node = (device_node*)cookie;
384 	device_node* parent = gDeviceManager->get_parent_node(node);
385 	pci_device_module_info* pci;
386 	pci_device* device;
387 	uint8 slots_count, bar, slotsInfo;
388 
389 	gDeviceManager->get_driver(parent, (driver_module_info**)&pci,
390 		(void**)&device);
391 	uint16 pciSubDeviceId = pci->read_pci_config(device, PCI_subsystem_id, 2);
392 	slotsInfo = pci->read_pci_config(device, SDHCI_PCI_SLOT_INFO, 1);
393 	bar = SDHCI_PCI_SLOT_INFO_FIRST_BASE_INDEX(slotsInfo);
394 	slots_count = SDHCI_PCI_SLOTS(slotsInfo);
395 
396 	char prettyName[25];
397 
398 	if (slots_count > 6 || bar > 5) {
399 		TRACE("Invalid slots count: %d or BAR count: %d \n", slots_count, bar);
400 		return B_BAD_VALUE;
401 	}
402 
403 	for (uint8_t slot = 0; slot <= slots_count; slot++) {
404 
405 		bar = bar + slot;
406 		sprintf(prettyName, "SDHC bus %" B_PRIu16 " slot %"
407 			B_PRIu8, pciSubDeviceId, slot);
408 		device_attr attrs[] = {
409 			// properties of this controller for SDHCI bus manager
410 			{ B_DEVICE_PRETTY_NAME, B_STRING_TYPE,
411 				{ string: prettyName }},
412 			{ B_DEVICE_FIXED_CHILD, B_STRING_TYPE,
413 				{string: SDHCI_BUS_CONTROLLER_MODULE_NAME}},
414 			{SDHCI_DEVICE_TYPE_ITEM, B_UINT16_TYPE,
415 				{ ui16: pciSubDeviceId}},
416 			{B_DEVICE_BUS, B_STRING_TYPE,{string: "mmc"}},
417 			{SLOT_NUMBER, B_UINT8_TYPE,
418 				{ ui8: slot}},
419 			{BAR_INDEX, B_UINT8_TYPE,
420 				{ ui8: bar}},
421 			{ NULL }
422 		};
423 		if (gDeviceManager->register_node(node, SDHCI_PCI_MMC_BUS_MODULE_NAME,
424 				attrs, NULL, &node) != B_OK)
425 			return B_BAD_VALUE;
426 	}
427 	return B_OK;
428 }
429 
430 
431 static status_t
432 init_device(device_node* node, void** device_cookie)
433 {
434 	CALLED();
435 	*device_cookie = node;
436 	return B_OK;
437 }
438 
439 
440 static status_t
441 register_device(device_node* parent)
442 {
443 	device_attr attrs[] = {
444 		{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "SDHC PCI controller"}},
445 		{}
446 	};
447 
448 	return gDeviceManager->register_node(parent, SDHCI_PCI_DEVICE_MODULE_NAME,
449 		attrs, NULL, NULL);
450 }
451 
452 
453 static float
454 supports_device(device_node* parent)
455 {
456 	CALLED();
457 	const char* bus;
458 	uint16 type, subType;
459 	uint8 pciSubDeviceId;
460 
461 	// make sure parent is a PCI SDHCI device node
462 	if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false)
463 		!= B_OK || gDeviceManager->get_attr_uint16(parent, B_DEVICE_SUB_TYPE,
464 		&subType, false) < B_OK || gDeviceManager->get_attr_uint16(parent,
465 		B_DEVICE_TYPE, &type, false) < B_OK)
466 		return -1;
467 
468 	if (strcmp(bus, "pci") != 0)
469 		return 0.0f;
470 
471 	if (type == PCI_base_peripheral) {
472 		if (subType != PCI_sd_host)
473 			return 0.0f;
474 
475 		pci_device_module_info* pci;
476 		pci_device* device;
477 		gDeviceManager->get_driver(parent, (driver_module_info**)&pci,
478 			(void**)&device);
479 		pciSubDeviceId = pci->read_pci_config(device, PCI_revision, 1);
480 		TRACE("SDHCI Device found! Subtype: 0x%04x, type: 0x%04x\n",
481 			subType, type);
482 		return 0.8f;
483 	}
484 
485 	return 0.0f;
486 }
487 
488 
489 module_dependency module_dependencies[] = {
490 	{ SDHCI_BUS_CONTROLLER_MODULE_NAME, (module_info**)&gSDHCIDeviceController},
491 	{ B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager },
492 	{}
493 };
494 
495 
496 static sdhci_mmc_bus_interface gSDHCIPCIDeviceModule = {
497 	{
498 		{
499 			SDHCI_PCI_MMC_BUS_MODULE_NAME,
500 			0,
501 			NULL
502 		},
503 		NULL,	// supports device
504 		NULL,	// register device
505 		init_bus,
506 		uninit_bus,
507 		NULL,	// register child devices
508 		NULL,	// rescan
509 		bus_removed,
510 	}
511 };
512 
513 
514 static driver_module_info sSDHCIDevice = {
515 	{
516 		SDHCI_PCI_DEVICE_MODULE_NAME,
517 		0,
518 		NULL
519 	},
520 	supports_device,
521 	register_device,
522 	init_device,
523 	NULL,	// uninit
524 	register_child_devices,
525 	NULL,	// rescan
526 	NULL,	// device removed
527 };
528 
529 
530 module_info* modules[] = {
531 	(module_info* )&sSDHCIDevice,
532 	(module_info* )&gSDHCIPCIDeviceModule,
533 	NULL
534 };
535