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_ACPI_MMC_BUS_MODULE_NAME "busses/mmc/sdhci/acpi/device/v1"
39 #define SDHCI_PCI_MMC_BUS_MODULE_NAME "busses/mmc/sdhci/pci/device/v1"
40
41 #define SLOT_NUMBER "device/slot"
42 #define BAR_INDEX "device/bar"
43
44 device_manager_info* gDeviceManager;
45 device_module_info* gMMCBusController;
46
47 static int32
sdhci_generic_interrupt(void * data)48 sdhci_generic_interrupt(void* data)
49 {
50 SdhciBus* bus = (SdhciBus*)data;
51 return bus->HandleInterrupt();
52 }
53
54
SdhciBus(struct registers * registers,uint8_t irq,bool poll)55 SdhciBus::SdhciBus(struct registers* registers, uint8_t irq, bool poll)
56 :
57 fRegisters(registers),
58 fIrq(irq),
59 fSemaphore(0)
60 {
61 if (irq == 0 || irq == 0xff) {
62 ERROR("IRQ not assigned\n");
63 fStatus = B_BAD_DATA;
64 return;
65 }
66
67 fSemaphore = create_sem(0, "SDHCI interrupts");
68
69 DisableInterrupts();
70
71 fStatus = install_io_interrupt_handler(fIrq,
72 sdhci_generic_interrupt, this, 0);
73
74 if (fStatus != B_OK) {
75 ERROR("can't install interrupt handler\n");
76 return;
77 }
78
79 // First of all, we have to make sure we are in a sane state. The easiest
80 // way is to reset everything.
81 Reset();
82
83 // Turn on the power supply to the card, if there is a card inserted
84 if (PowerOn()) {
85 // Then we configure the clock to the frequency needed for
86 // initialization
87 SetClock(400);
88 }
89
90 // Finally, configure some useful interrupts
91 EnableInterrupts(SDHCI_INT_CMD_CMP | SDHCI_INT_CARD_REM
92 | SDHCI_INT_TRANS_CMP);
93
94 // We want to see the error bits in the status register, but not have an
95 // interrupt trigger on them (we get a "command complete" interrupt on
96 // errors already)
97 fRegisters->interrupt_status_enable |= SDHCI_INT_ERROR
98 | SDHCI_INT_TIMEOUT | SDHCI_INT_CRC | SDHCI_INT_INDEX
99 | SDHCI_INT_BUS_POWER | SDHCI_INT_END_BIT;
100
101 if (poll) {
102 // Spawn a polling thread, as the interrupts won't currently work on ACPI.
103 fWorkerThread = spawn_kernel_thread(_WorkerThread, "SD bus poller",
104 B_NORMAL_PRIORITY, this);
105 resume_thread(fWorkerThread);
106 }
107 }
108
109
~SdhciBus()110 SdhciBus::~SdhciBus()
111 {
112 DisableInterrupts();
113
114 if (fSemaphore != 0)
115 delete_sem(fSemaphore);
116
117 if (fIrq != 0)
118 remove_io_interrupt_handler(fIrq, sdhci_generic_interrupt, this);
119
120 area_id regs_area = area_for(fRegisters);
121 delete_area(regs_area);
122
123 fStatus = B_SHUTTING_DOWN;
124
125 status_t result;
126 if (fWorkerThread != 0)
127 wait_for_thread(fWorkerThread, &result);
128 }
129
130
131 void
EnableInterrupts(uint32_t mask)132 SdhciBus::EnableInterrupts(uint32_t mask)
133 {
134 fRegisters->interrupt_status_enable |= mask;
135 fRegisters->interrupt_signal_enable |= mask;
136 }
137
138
139 void
DisableInterrupts()140 SdhciBus::DisableInterrupts()
141 {
142 fRegisters->interrupt_status_enable = 0;
143 fRegisters->interrupt_signal_enable = 0;
144 }
145
146
147 // #pragma mark -
148 /*
149 PartA2, SD Host Controller Simplified Specification, Version 4.20
150 §3.7.1.1 The sequence to issue an SD Command
151 */
152 status_t
ExecuteCommand(uint8_t command,uint32_t argument,uint32_t * response)153 SdhciBus::ExecuteCommand(uint8_t command, uint32_t argument, uint32_t* response)
154 {
155 TRACE("ExecuteCommand(%d, %x)\n", command, argument);
156
157 // First of all clear the result
158 fCommandResult = 0;
159
160 // Check if it's possible to send a command right now.
161 // It is not possible to send a command as long as the command line is busy.
162 // The spec says we should wait, but we can't do that on kernel side, since
163 // it leaves no chance for the upper layers to handle the problem. So we
164 // just say we're busy and the caller can retry later.
165 // Note that this should normally never happen: the command line is busy
166 // only during command execution, and we don't leave this function with ac
167 // command running.
168 if (fRegisters->present_state.CommandInhibit()) {
169 panic("Command execution impossible, command inhibit\n");
170 return B_BUSY;
171 }
172 if (fRegisters->present_state.DataInhibit()) {
173 panic("Command execution unwise, data inhibit\n");
174 return B_BUSY;
175 }
176
177 uint32_t replyType;
178
179 switch (command) {
180 case SD_GO_IDLE_STATE:
181 replyType = Command::kNoReplyType;
182 break;
183 case SD_ALL_SEND_CID:
184 case SD_SEND_CSD:
185 replyType = Command::kR2Type;
186 break;
187 case SD_SEND_RELATIVE_ADDR:
188 replyType = Command::kR6Type;
189 break;
190 case SD_SELECT_DESELECT_CARD:
191 case SD_ERASE:
192 replyType = Command::kR1bType;
193 break;
194 case SD_SEND_IF_COND:
195 replyType = Command::kR7Type;
196 break;
197 case SD_READ_SINGLE_BLOCK:
198 case SD_READ_MULTIPLE_BLOCKS:
199 case SD_WRITE_SINGLE_BLOCK:
200 case SD_WRITE_MULTIPLE_BLOCKS:
201 replyType = Command::kR1Type | Command::kDataPresent;
202 break;
203 case SD_APP_CMD:
204 case SD_ERASE_WR_BLK_START:
205 case SD_ERASE_WR_BLK_END:
206 case SD_SET_BUS_WIDTH: // SD Application command
207 replyType = Command::kR1Type;
208 break;
209 case SD_SEND_OP_COND: // SD Application command
210 replyType = Command::kR3Type;
211 break;
212 default:
213 ERROR("Unknown command %x\n", command);
214 return B_BAD_DATA;
215 }
216
217 // Check if DATA line is available (if needed)
218 if ((replyType & Command::k32BitResponseCheckBusy) != 0
219 && command != SD_STOP_TRANSMISSION && command != SD_IO_ABORT) {
220 if (fRegisters->present_state.DataInhibit()) {
221 ERROR("Execution aborted, data inhibit\n");
222 return B_BUSY;
223 }
224 }
225
226 if (fRegisters->present_state.CommandInhibit())
227 panic("Command line busy at start of execute command\n");
228
229 if (replyType == Command::kR1bType)
230 fRegisters->transfer_mode = 0;
231
232 fRegisters->argument = argument;
233 fRegisters->command.SendCommand(command, replyType);
234
235 // Wait for command response to be available ("command complete" interrupt)
236 TRACE("Wait for command complete...");
237 do {
238 //fCommandResult = fRegisters->interrupt_status;
239 acquire_sem(fSemaphore);
240 TRACE("command complete sem acquired, status: %x\n", fCommandResult);
241 TRACE("real status = %x command line busy: %d\n",
242 fRegisters->interrupt_status,
243 fRegisters->present_state.CommandInhibit());
244 } while (fCommandResult == 0);
245
246 TRACE("Command response available\n");
247
248 if (fCommandResult & SDHCI_INT_ERROR) {
249 fRegisters->interrupt_status |= fCommandResult;
250 if (fCommandResult & SDHCI_INT_TIMEOUT) {
251 ERROR("Command execution timed out\n");
252 if (fRegisters->present_state.CommandInhibit()) {
253 TRACE("Command line is still busy, clearing it\n");
254 // Clear the stall
255 fRegisters->software_reset.ResetCommandLine();
256 }
257 return B_TIMED_OUT;
258 }
259 if (fCommandResult & SDHCI_INT_CRC) {
260 ERROR("CRC error\n");
261 return B_BAD_VALUE;
262 }
263 ERROR("Command execution failed %x\n", fCommandResult);
264 // TODO look at errors in interrupt_status register for more details
265 // and return a more appropriate error code
266 return B_ERROR;
267 }
268
269 if (fRegisters->present_state.CommandInhibit()) {
270 TRACE("Command execution failed, card stalled\n");
271 // Clear the stall
272 fRegisters->software_reset.ResetCommandLine();
273 return B_ERROR;
274 }
275
276 switch (replyType & Command::kReplySizeMask) {
277 case Command::k32BitResponse:
278 *response = fRegisters->response[0];
279 break;
280 case Command::k128BitResponse:
281 response[0] = fRegisters->response[0];
282 response[1] = fRegisters->response[1];
283 response[2] = fRegisters->response[2];
284 response[3] = fRegisters->response[3];
285 break;
286
287 default:
288 // No response
289 break;
290 }
291
292 if (replyType == Command::kR1bType
293 && (fCommandResult & SDHCI_INT_TRANS_CMP) == 0) {
294 // R1b commands may use the data line so we must wait for the
295 // "transfer complete" interrupt here.
296 TRACE("Waiting for data line...\n");
297 do {
298 acquire_sem(fSemaphore);
299 } while (fRegisters->present_state.DataInhibit());
300 TRACE("Dataline is released.\n");
301 }
302
303 ERROR("Command execution %d complete\n", command);
304 return B_OK;
305 }
306
307
308 status_t
InitCheck()309 SdhciBus::InitCheck()
310 {
311 return fStatus;
312 }
313
314
315 void
Reset()316 SdhciBus::Reset()
317 {
318 if (!fRegisters->software_reset.ResetAll())
319 ERROR("SdhciBus::Reset: SoftwareReset timeout\n");
320 }
321
322
323 void
SetClock(int kilohertz)324 SdhciBus::SetClock(int kilohertz)
325 {
326 int base_clock = fRegisters->capabilities.BaseClockFrequency();
327 // Try to get as close to 400kHz as possible, but not faster
328 int divider = base_clock * 1000 / kilohertz;
329
330 if (fRegisters->host_controller_version.specVersion <= 1) {
331 // Old controller only support power of two dividers up to 256,
332 // round to next power of two up to 256
333 if (divider > 256)
334 divider = 256;
335
336 divider--;
337 divider |= divider >> 1;
338 divider |= divider >> 2;
339 divider |= divider >> 4;
340 divider++;
341 }
342
343 divider = fRegisters->clock_control.SetDivider(divider);
344
345 // Log the value after possible rounding by SetDivider (only even values
346 // are allowed).
347 TRACE("SDCLK frequency: %dMHz / %d = %dkHz\n", base_clock, divider,
348 base_clock * 1000 / divider);
349
350 // We have set the divider, now we can enable the internal clock.
351 fRegisters->clock_control.EnableInternal();
352
353 // wait until internal clock is stabilized
354 while (!(fRegisters->clock_control.InternalStable()));
355
356 fRegisters->clock_control.EnablePLL();
357 while (!(fRegisters->clock_control.InternalStable()));
358
359 // Finally, route the clock to the SD card
360 fRegisters->clock_control.EnableSD();
361 }
362
363
364 status_t
DoIO(uint8_t command,IOOperation * operation,bool offsetAsSectors)365 SdhciBus::DoIO(uint8_t command, IOOperation* operation, bool offsetAsSectors)
366 {
367 bool isWrite = operation->IsWrite();
368
369 static const uint32 kBlockSize = 512;
370 off_t offset = operation->Offset();
371 generic_size_t length = operation->Length();
372
373 TRACE("%s %" B_PRIu64 " bytes at %" B_PRIdOFF "\n",
374 isWrite ? "Write" : "Read", length, offset);
375
376 // Check that the IO scheduler did its job in following our DMA restrictions
377 // We can start a read only at a sector boundary
378 ASSERT(offset % kBlockSize == 0);
379 // We can only read complete sectors
380 ASSERT(length % kBlockSize == 0);
381
382 const generic_io_vec* vecs = operation->Vecs();
383 generic_size_t vecOffset = 0;
384
385 // FIXME can this be moved to the init function instead?
386 //
387 // For simplicity we use a transfer size equal to the sector size. We could
388 // go up to 2K here if the length to read in each individual vec is a
389 // multiple of 2K, but we have no easy way to know this (we would need to
390 // iterate through the IOOperation vecs and check the size of each of them).
391 // We could also do smaller transfers, but it is not possible to start a
392 // transfer anywhere else than the start of a sector, so it's a lot simpler
393 // to always work in complete sectors. We set the B_DMA_ALIGNMENT device
394 // node property accordingly, making sure that we don't get asked to do
395 // transfers that are not aligned with sectors.
396 //
397 // Additionnally, set SDMA buffer boundary aligment to 512K. This is the
398 // largest possible size. We also set the B_DMA_BOUNDARY property on the
399 // published device node, so that the DMA resource manager knows that it
400 // must respect this boundary. As a result, we will never be asked to
401 // do a transfer that crosses this boundary, and we don't need to handle
402 // the DMA boundary interrupt (the transfer will be split in two at an
403 // upper layer).
404 fRegisters->block_size.ConfigureTransfer(kBlockSize,
405 BlockSize::kDmaBoundary512K);
406 status_t result = B_OK;
407
408 while (length > 0) {
409 size_t toCopy = std::min((generic_size_t)length,
410 vecs->length - vecOffset);
411
412 // If the current vec is empty, we can move to the next
413 if (toCopy == 0) {
414 vecs++;
415 vecOffset = 0;
416 continue;
417 }
418
419 // With SDMA we can only transfer multiples of 1 sector
420 ASSERT(toCopy % kBlockSize == 0);
421
422 fRegisters->system_address = vecs->base + vecOffset;
423 // fRegisters->adma_system_address = fDmaMemory;
424
425 fRegisters->block_count = toCopy / kBlockSize;
426
427 uint16 direction;
428 if (isWrite)
429 direction = TransferMode::kWrite;
430 else
431 direction = TransferMode::kRead;
432 fRegisters->transfer_mode = TransferMode::kMulti | direction
433 | TransferMode::kAutoCmd12Enable
434 | TransferMode::kBlockCountEnable | TransferMode::kDmaEnable;
435
436 uint32_t response;
437 result = ExecuteCommand(command,
438 offset / (offsetAsSectors ? kBlockSize : 1), &response);
439 if (result != B_OK)
440 break;
441
442 // Wait for DMA transfer to complete
443 // In theory we could go on and send other commands as long as they
444 // don't need the DAT lines, but it's overcomplicating things.
445 TRACE("Wait for transfer complete...");
446 //while ((fRegisters->interrupt_status & SDHCI_INT_TRANS_CMP) == 0);
447 acquire_sem(fSemaphore);
448 TRACE("transfer complete OK.\n");
449
450 length -= toCopy;
451 vecOffset += toCopy;
452 offset += toCopy;
453 }
454
455 return result;
456 }
457
458
459 void
SetScanSemaphore(sem_id sem)460 SdhciBus::SetScanSemaphore(sem_id sem)
461 {
462 fScanSemaphore = sem;
463
464 // If there is already a card in, start a scan immediately
465 if (fRegisters->present_state.IsCardInserted())
466 release_sem(fScanSemaphore);
467
468 // We can now enable the card insertion interrupt for next time a card
469 // is inserted
470 EnableInterrupts(SDHCI_INT_CARD_INS);
471 }
472
473
474 void
SetBusWidth(int width)475 SdhciBus::SetBusWidth(int width)
476 {
477 uint8_t widthBits;
478 switch(width) {
479 case 1:
480 widthBits = HostControl::kDataTransfer1Bit;
481 break;
482 case 4:
483 widthBits = HostControl::kDataTransfer4Bit;
484 break;
485 case 8:
486 widthBits = HostControl::kDataTransfer8Bit;
487 break;
488 default:
489 panic("Incorrect bitwidth value");
490 return;
491 }
492 fRegisters->host_control.SetDataTransferWidth(widthBits);
493 }
494
495
496 bool
PowerOn()497 SdhciBus::PowerOn()
498 {
499 if (!fRegisters->present_state.IsCardInserted()) {
500 TRACE("Card not inserted, not powering on for now\n");
501 return false;
502 }
503
504 uint8_t supportedVoltages = fRegisters->capabilities.SupportedVoltages();
505 if ((supportedVoltages & Capabilities::k3v3) != 0)
506 fRegisters->power_control.SetVoltage(PowerControl::k3v3);
507 else if ((supportedVoltages & Capabilities::k3v0) != 0)
508 fRegisters->power_control.SetVoltage(PowerControl::k3v0);
509 else if ((supportedVoltages & Capabilities::k1v8) != 0)
510 fRegisters->power_control.SetVoltage(PowerControl::k1v8);
511 else {
512 fRegisters->power_control.PowerOff();
513 ERROR("No voltage is supported\n");
514 return false;
515 }
516
517 return true;
518 }
519
520
521 void
RecoverError()522 SdhciBus::RecoverError()
523 {
524 fRegisters->interrupt_signal_enable &= ~(SDHCI_INT_CMD_CMP
525 | SDHCI_INT_TRANS_CMP | SDHCI_INT_CARD_INS | SDHCI_INT_CARD_REM);
526
527 if (fRegisters->interrupt_status & 7)
528 fRegisters->software_reset.ResetCommandLine();
529
530 int16_t error_status = fRegisters->interrupt_status;
531 fRegisters->interrupt_status &= ~(error_status);
532 }
533
534
535 int32
HandleInterrupt()536 SdhciBus::HandleInterrupt()
537 {
538 #if 0
539 // We could use the slot register to quickly see for which slot the
540 // interrupt is. But since we have an interrupt handler call for each slot
541 // anyway, it's just as simple to let each of them scan its own interrupt
542 // status register.
543 if ( !(fRegisters->slot_interrupt_status & (1 << fSlot)) ) {
544 TRACE("interrupt not for me.\n");
545 return B_UNHANDLED_INTERRUPT;
546 }
547 #endif
548
549 uint32_t intmask = fRegisters->interrupt_status;
550
551 // Shortcut: exit early if there is no interrupt or if the register is
552 // clearly invalid.
553 if ((intmask == 0) || (intmask == 0xffffffff)) {
554 return B_UNHANDLED_INTERRUPT;
555 }
556
557 TRACE("interrupt function called %x\n", intmask);
558
559 // handling card presence interrupts
560 if ((intmask & SDHCI_INT_CARD_REM) != 0) {
561 // We can get spurious interrupts as the card is inserted or removed,
562 // so check the actual state before acting
563 if (!fRegisters->present_state.IsCardInserted())
564 fRegisters->power_control.PowerOff();
565 else
566 TRACE("Card removed interrupt, but card is inserted\n");
567
568 fRegisters->interrupt_status |= SDHCI_INT_CARD_REM;
569 TRACE("Card removal interrupt handled\n");
570 }
571
572 if ((intmask & SDHCI_INT_CARD_INS) != 0) {
573 // We can get spurious interrupts as the card is inserted or removed,
574 // so check the actual state before acting
575 if (fRegisters->present_state.IsCardInserted()) {
576 if (PowerOn())
577 SetClock(400);
578 release_sem_etc(fScanSemaphore, 1, B_DO_NOT_RESCHEDULE);
579 } else
580 TRACE("Card insertion interrupt, but card is removed\n");
581
582 fRegisters->interrupt_status |= SDHCI_INT_CARD_INS;
583 TRACE("Card presence interrupt handled\n");
584 }
585
586 // handling command interrupt
587 if (intmask & SDHCI_INT_CMD_MASK) {
588 fCommandResult = intmask;
589 // Save the status before clearing so the thread can handle it
590 fRegisters->interrupt_status |= (intmask & SDHCI_INT_CMD_MASK);
591
592 // Notify the thread
593 release_sem_etc(fSemaphore, 1, B_DO_NOT_RESCHEDULE);
594 TRACE("Command complete interrupt handled\n");
595 }
596
597 if (intmask & SDHCI_INT_TRANS_CMP) {
598 fCommandResult = intmask;
599 fRegisters->interrupt_status |= SDHCI_INT_TRANS_CMP;
600 release_sem_etc(fSemaphore, 1, B_DO_NOT_RESCHEDULE);
601 TRACE("Transfer complete interrupt handled\n");
602 }
603
604 // handling bus power interrupt
605 if (intmask & SDHCI_INT_BUS_POWER) {
606 fRegisters->interrupt_status |= SDHCI_INT_BUS_POWER;
607 TRACE("card is consuming too much power\n");
608 }
609
610 // Check that all interrupts have been cleared (we check all the ones we
611 // enabled, so that should always be the case)
612 intmask = fRegisters->interrupt_status;
613 if (intmask != 0) {
614 ERROR("Remaining interrupts at end of handler: %x\n", intmask);
615 }
616
617 return B_HANDLED_INTERRUPT;
618 }
619
620 status_t
_WorkerThread(void * cookie)621 SdhciBus::_WorkerThread(void* cookie) {
622 SdhciBus* bus = (SdhciBus*)cookie;
623 while (bus->fStatus != B_SHUTTING_DOWN) {
624 uint32_t intmask = bus->fRegisters->interrupt_status;
625 if (intmask & SDHCI_INT_CMD_CMP) {
626 bus->fCommandResult = intmask;
627 bus->fRegisters->interrupt_status |= (intmask & SDHCI_INT_CMD_MASK);
628 release_sem(bus->fSemaphore);
629 }
630 if (intmask & SDHCI_INT_TRANS_CMP) {
631 bus->fCommandResult = intmask;
632 bus->fRegisters->interrupt_status |= SDHCI_INT_TRANS_CMP;
633 release_sem(bus->fSemaphore);
634 }
635 snooze(100);
636 }
637 TRACE("poller thread terminating");
638 return B_OK;
639 }
640
641 // #pragma mark -
642
643 void
uninit_bus(void * bus_cookie)644 uninit_bus(void* bus_cookie)
645 {
646 SdhciBus* bus = (SdhciBus*)bus_cookie;
647 delete bus;
648
649 // FIXME do we need to put() the PCI module here?
650 }
651
652
653 void
bus_removed(void * bus_cookie)654 bus_removed(void* bus_cookie)
655 {
656 return;
657 }
658
659 static status_t
register_child_devices(void * cookie)660 register_child_devices(void* cookie)
661 {
662 CALLED();
663 SdhciDevice* context = (SdhciDevice*)cookie;
664 status_t status = B_OK;
665 const char* bus;
666 device_node* parent = gDeviceManager->get_parent_node(context->fNode);
667 status = gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false);
668 if (status != B_OK) {
669 TRACE("Could not find required attribute device/bus\n");
670 return status;
671 }
672
673 if (strcmp(bus, "pci") == 0)
674 status = register_child_devices_pci(cookie);
675 else if (strcmp(bus, "acpi") == 0)
676 status = register_child_devices_acpi(cookie);
677 else
678 status = B_BAD_VALUE;
679
680 return status;
681 }
682
683 static status_t
init_device(device_node * node,void ** device_cookie)684 init_device(device_node* node, void** device_cookie)
685 {
686 CALLED();
687
688 SdhciDevice* context = new(std::nothrow)SdhciDevice;
689 if (context == NULL)
690 return B_NO_MEMORY;
691 context->fNode = node;
692 *device_cookie = context;
693
694 status_t status = B_OK;
695 const char* bus;
696 device_node* parent = gDeviceManager->get_parent_node(node);
697 status = gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false);
698 if (status != B_OK) {
699 TRACE("Could not find required attribute device/bus\n");
700 return status;
701 }
702
703 if (strcmp(bus, "pci") == 0)
704 return init_device_pci(node, context);
705
706 return B_OK;
707 }
708
709 static void
uninit_device(void * device_cookie)710 uninit_device(void* device_cookie)
711 {
712 SdhciDevice* context = (SdhciDevice*)device_cookie;
713 device_node* parent = gDeviceManager->get_parent_node(context->fNode);
714
715 const char* bus;
716 if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false) != B_OK) {
717 TRACE("Could not find required attribute device/bus\n");
718 }
719
720 if (strcmp(bus, "pci") == 0)
721 uninit_device_pci(context, parent);
722
723 gDeviceManager->put_node(parent);
724
725 delete context;
726 }
727
728
729 static status_t
register_device(device_node * parent)730 register_device(device_node* parent)
731 {
732 device_attr attrs[] = {
733 {B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {.string = "SD Host Controller"}},
734 {}
735 };
736
737 return gDeviceManager->register_node(parent, SDHCI_DEVICE_MODULE_NAME,
738 attrs, NULL, NULL);
739 }
740
741 static float
supports_device(device_node * parent)742 supports_device(device_node* parent)
743 {
744 const char* bus;
745
746 // make sure parent is either an ACPI or PCI SDHCI device node
747 if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false)
748 != B_OK) {
749 TRACE("Could not find required attribute device/bus\n");
750 return -1;
751 }
752
753 if (strcmp(bus, "pci") == 0)
754 return supports_device_pci(parent);
755 else if (strcmp(bus, "acpi") == 0)
756 return supports_device_acpi(parent);
757
758 return 0.0f;
759 }
760
761
762 module_dependency module_dependencies[] = {
763 { MMC_BUS_MODULE_NAME, (module_info**)&gMMCBusController},
764 { B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager },
765 {}
766 };
767
768 status_t
set_clock(void * controller,uint32_t kilohertz)769 set_clock(void* controller, uint32_t kilohertz)
770 {
771 SdhciBus* bus = (SdhciBus*)controller;
772 bus->SetClock(kilohertz);
773 return B_OK;
774 }
775
776
777 status_t
execute_command(void * controller,uint8_t command,uint32_t argument,uint32_t * response)778 execute_command(void* controller, uint8_t command, uint32_t argument,
779 uint32_t* response)
780 {
781 SdhciBus* bus = (SdhciBus*)controller;
782 return bus->ExecuteCommand(command, argument, response);
783 }
784
785
786 status_t
do_io(void * controller,uint8_t command,IOOperation * operation,bool offsetAsSectors)787 do_io(void* controller, uint8_t command, IOOperation* operation,
788 bool offsetAsSectors)
789 {
790 SdhciBus* bus = (SdhciBus*)controller;
791 return bus->DoIO(command, operation, offsetAsSectors);
792 }
793
794
795 void
set_scan_semaphore(void * controller,sem_id sem)796 set_scan_semaphore(void* controller, sem_id sem)
797 {
798 SdhciBus* bus = (SdhciBus*)controller;
799 return bus->SetScanSemaphore(sem);
800 }
801
802
803 void
set_bus_width(void * controller,int width)804 set_bus_width(void* controller, int width)
805 {
806 SdhciBus* bus = (SdhciBus*)controller;
807 return bus->SetBusWidth(width);
808 }
809
810 // Root device that binds to the ACPI or PCI bus. It will register an mmc_bus_interface
811 // node for each SD slot in the device.
812 static driver_module_info sSDHCIDevice = {
813 {
814 SDHCI_DEVICE_MODULE_NAME,
815 0,
816 NULL
817 },
818 supports_device,
819 register_device,
820 init_device,
821 uninit_device,
822 register_child_devices,
823 NULL, // rescan
824 NULL, // device removed
825 };
826
827
828 module_info* modules[] = {
829 (module_info* )&sSDHCIDevice,
830 (module_info* )&gSDHCIPCIDeviceModule,
831 (module_info* )&gSDHCIACPIDeviceModule,
832 NULL
833 };
834