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
init_bus_pci(device_node * node,void ** bus_cookie)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
register_child_devices_pci(void * cookie)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
init_device_pci(device_node * node,SdhciDevice * context)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
uninit_device_pci(SdhciDevice * context,device_node * pciParent)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
supports_device_pci(device_node * parent)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 };
323