xref: /haiku/src/add-ons/kernel/busses/mmc/sdhci.h (revision 7371ccbe44abb58f0c9ee51089864bdd82f39a18)
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  *		Ron Ben Aroya, sed4906birdie@gmail.com
8  */
9 #ifndef _SDHCI_H
10 #define _SDHCI_H
11 
12 
13 #include <device_manager.h>
14 #include <KernelExport.h>
15 
16 
17 #define SDHCI_PCI_SLOT_INFO 							0x40
18 #define SDHCI_PCI_SLOTS(x) 								((((x) >> 4) & 0x7) + 1)
19 #define SDHCI_PCI_SLOT_INFO_FIRST_BASE_INDEX(x)			((x) & 0x7)
20 
21 // Ricoh specific PCI registers
22 // Ricoh devices start in a vendor-specific mode but can be switched
23 // to standard sdhci using these PCI registers
24 #define SDHCI_PCI_RICOH_MODE_KEY						0xf9
25 #define SDHCI_PCI_RICOH_MODE							0x150
26 #define SDHCI_PCI_RICOH_MODE_SD20						0x10
27 
28 #define SDHCI_BUS_TYPE_NAME 							"bus/sdhci/v1"
29 
30 
31 class SdhciBus {
32 	public:
33 							SdhciBus(struct registers* registers, uint8_t irq, bool poll);
34 							~SdhciBus();
35 
36 		void				EnableInterrupts(uint32_t mask);
37 		void				DisableInterrupts();
38 		status_t			ExecuteCommand(uint8_t command, uint32_t argument,
39 								uint32_t* response);
40 		int32				HandleInterrupt();
41 		status_t			InitCheck();
42 		void				Reset();
43 		void				SetClock(int kilohertz);
44 		status_t			DoIO(uint8_t command, IOOperation* operation,
45 								bool offsetAsSectors);
46 		void				SetScanSemaphore(sem_id sem);
47 		void				SetBusWidth(int width);
48 
49 	private:
50 		bool				PowerOn();
51 		void				RecoverError();
52 		static status_t			_WorkerThread(void*);
53 
54 	private:
55 		struct registers*	fRegisters;
56 		uint32_t			fCommandResult;
57 		uint8_t				fIrq;
58 		sem_id				fSemaphore;
59 		sem_id				fScanSemaphore;
60 		status_t			fStatus;
61 		thread_id			fWorkerThread;
62 };
63 
64 
65 class SdhciDevice {
66 	public:
67 		device_node* fNode;
68 		uint8_t fRicohOriginalMode;
69 };
70 
71 class TransferMode {
72 	public:
Bits()73 		uint16_t Bits() { return fBits; }
74 
75 		// TODO response interrupt
76 		// TODO response check
77 
78 		static const uint8_t kR1 = 0 << 6;
79 		static const uint8_t kR5 = 1 << 6;
80 
81 		static const uint8_t kMulti = 1 << 5;
82 		static const uint8_t kSingle = 0 << 5;
83 
84 		static const uint8_t kRead = 1 << 4;
85 		static const uint8_t kWrite = 0 << 4;
86 
87 		static const uint8_t kAutoCmdDisabled = 0 << 2;
88 		static const uint8_t kAutoCmd12Enable = 1 << 2;
89 		static const uint8_t kAutoCmd23Enable = 2 << 2;
90 		static const uint8_t kAutoCmdAutoSelect
91 			= kAutoCmd23Enable | kAutoCmd12Enable;
92 
93 		static const uint8_t kBlockCountEnable = 1 << 1;
94 
95 		static const uint8_t kDmaEnable = 1;
96 		static const uint8_t kNoDmaOrNoData = 0;
97 
98 	private:
99 		volatile uint16_t fBits;
100 } __attribute__((packed));
101 
102 
103 class Command {
104 	public:
Bits()105 		uint16_t Bits() { return fBits; }
106 
SendCommand(uint8_t command,uint8_t type)107 		void SendCommand(uint8_t command, uint8_t type)
108 		{
109 			fBits = (command << 8) | type;
110 		}
111 
112 		static const uint8_t kDataPresent = 0x20;
113 		static const uint8_t kCheckIndex = 0x10;
114 		static const uint8_t kCRCEnable = 0x8;
115 		static const uint8_t kSubCommand = 0x4;
116 		static const uint8_t kReplySizeMask = 0x3;
117 		static const uint8_t k32BitResponse = 0x2;
118 		static const uint8_t k128BitResponse = 0x1;
119 		static const uint8_t k32BitResponseCheckBusy = 0x3;
120 
121 		// For simplicity pre-define the standard response types from the SD
122 		// card specification
123 		static const uint8_t kNoReplyType = 0;
124 		static const uint8_t kR1Type = kCheckIndex | kCRCEnable
125 			| k32BitResponse;
126 		static const uint8_t kR1bType = (kCheckIndex | kCRCEnable
127 			| k32BitResponseCheckBusy) & (~ kDataPresent);
128  		static const uint8_t kR2Type = kCRCEnable | k128BitResponse;
129 		static const uint8_t kR3Type = k32BitResponse;
130 		static const uint8_t kR6Type = kCheckIndex | k32BitResponse;
131 		static const uint8_t kR7Type = kCheckIndex | kCRCEnable
132 			| k32BitResponse;
133 
134 	private:
135 		volatile uint16_t fBits;
136 } __attribute__((packed));
137 
138 
139 class PresentState {
140 	public:
Bits()141 		uint32_t Bits() { return fBits; }
142 
IsCardInserted()143 		bool IsCardInserted() { return fBits & (1 << 16); }
CommandInhibit()144 		bool CommandInhibit() { return fBits & (1 << 0); }
DataInhibit()145 		bool DataInhibit() { return fBits & (1 << 1); }
146 
147 	private:
148 		volatile uint32_t fBits;
149 } __attribute__((packed));
150 
151 
152 class PowerControl {
153 	public:
Bits()154 		uint8_t Bits() { return fBits; }
155 
SetVoltage(int voltage)156 		void SetVoltage(int voltage) {
157 			fBits |= voltage | kBusPowerOn;
158 		}
PowerOff()159 		void PowerOff() { fBits &= ~kBusPowerOn; }
160 
161 		static const uint8_t k3v3 = 7 << 1;
162 		static const uint8_t k3v0 = 6 << 1;
163 		static const uint8_t k1v8 = 5 << 1;
164 	private:
165 		volatile uint8_t fBits;
166 
167 		static const uint8_t kBusPowerOn = 1;
168 } __attribute__((packed));
169 
170 
171 class ClockControl
172 {
173 	public:
Bits()174 		uint16_t Bits() { return fBits; }
175 
SetDivider(uint16_t divider)176 		uint16_t SetDivider(uint16_t divider) {
177 			if (divider == 1)
178 				divider = 0;
179 			else
180 				divider /= 2;
181 			uint16_t bits = fBits & ~0xffc0;
182 			bits |= divider << 8;
183 			bits |= (divider >> 8) & 0xc0;
184 			fBits = bits;
185 
186 			return divider == 0 ? 1 : divider * 2;
187 		}
188 
EnableInternal()189 		void EnableInternal() { fBits |= 1 << 0; }
InternalStable()190 		bool InternalStable() { return fBits & (1 << 1); }
EnableSD()191 		void EnableSD() { fBits |= 1 << 2; }
DisableSD()192 		void DisableSD() { fBits &= ~(1 << 2); }
EnablePLL()193 		void EnablePLL() { fBits |= 1 << 3; }
194 	private:
195 		volatile  uint16_t fBits;
196 } __attribute__((packed));
197 
198 
199 class SoftwareReset {
200 	public:
Bits()201 		uint8_t Bits() { return fBits; }
202 
ResetAll()203 		bool ResetAll() {
204 			fBits = 1;
205 			int i = 0;
206 			// wait up to 100ms
207 			while ((fBits & 1) != 0 && i++ < 10)
208 				snooze(10000);
209 			return i < 10;
210 		}
211 
ResetCommandLine()212 		void ResetCommandLine() {
213 			fBits |= 2;
214 			while(fBits & 2);
215 		}
216 
217 	private:
218 		volatile uint8_t fBits;
219 } __attribute__((packed));
220 
221 
222 // #pragma mark Interrupt registers
223 #define SDHCI_INT_CMD_CMP			0x00000001	// command complete enable
224 #define SDHCI_INT_TRANS_CMP			0x00000002	// transfer complete enable
225 #define SDHCI_INT_BUF_READ_READY	0x00000020  // buffer read ready enable
226 #define SDHCI_INT_CARD_INS 			0x00000040	// card insertion enable
227 #define SDHCI_INT_CARD_REM 			0x00000080	// card removal enable
228 #define SDHCI_INT_ERROR         	0x00008000	// error
229 #define SDHCI_INT_TIMEOUT			0x00010000	// Timeout error
230 #define SDHCI_INT_CRC				0x00020000	// CRC error
231 #define SDHCI_INT_END_BIT			0x00040000	// end bit error
232 #define SDHCI_INT_INDEX 			0x00080000	// index error
233 #define SDHCI_INT_BUS_POWER			0x00800000	// power fail
234 
235 #define	 SDHCI_INT_CMD_ERROR_MASK	(SDHCI_INT_TIMEOUT | \
236 		SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX)
237 
238 #define SDHCI_INT_CMD_MASK 	(SDHCI_INT_CMD_CMP | SDHCI_INT_CMD_ERROR_MASK)
239 
240 // #pragma mark -
241 class Capabilities
242 {
243 	public:
Bits()244 		uint64_t Bits() { return fBits; }
245 
SupportedVoltages()246 		uint8_t SupportedVoltages() { return (fBits >> 24) & 7; }
BaseClockFrequency()247 		uint8_t BaseClockFrequency() { return (fBits >> 8) & 0xFF; }
248 
249 		static const uint8_t k3v3 = 1;
250 		static const uint8_t k3v0 = 2;
251 		static const uint8_t k1v8 = 4;
252 
253 	private:
254 		uint64_t fBits;
255 } __attribute__((packed));
256 
257 
258 class HostControllerVersion {
259 	public:
260 		const uint8_t specVersion;
261 		const uint8_t vendorVersion;
262 } __attribute__((packed));
263 
264 
265 class HostControl {
266 	public:
SetDMAMode(uint8_t dmaMode)267 		void SetDMAMode(uint8_t dmaMode)
268 		{
269 			value = (value & ~kDmaMask) | dmaMode;
270 		}
271 
SetDataTransferWidth(uint8_t width)272 		void SetDataTransferWidth(uint8_t width)
273 		{
274 			value = (value & ~kDataTransferWidthMask) | width;
275 		}
276 
277 		static const uint8_t kDmaMask = 3 << 3;
278 		static const uint8_t kSdma = 0 << 3;
279 		static const uint8_t kAdma32 = 2 << 3;
280 		static const uint8_t kAdma64 = 3 << 3;
281 
282 		// It's convenient to think of this as a single "bit width" setting,
283 		// but the bits for 4-bit and 8-bit modes were introduced at different
284 		// times and are not next to each other in the register.
285 		static const uint8_t kDataTransfer1Bit = 0;
286 		static const uint8_t kDataTransfer4Bit = 1 << 1;
287 		static const uint8_t kDataTransfer8Bit = 1 << 5;
288 
289 		static const uint8_t kDataTransferWidthMask
290 			= kDataTransfer4Bit | kDataTransfer8Bit;
291 	private:
292 		volatile uint8_t value;
293 } __attribute__((packed));
294 
295 
296 class BlockSize {
297 	public:
ConfigureTransfer(uint16_t transferBlockSize,uint16_t dmaBoundary)298 		void ConfigureTransfer(uint16_t transferBlockSize,
299 			uint16_t dmaBoundary)
300 		{
301 			value = transferBlockSize | dmaBoundary << 12;
302 		}
303 
304 		static const uint16_t kDmaBoundary4K = 0;
305 		static const uint16_t kDmaBoundary8K = 1;
306 		static const uint16_t kDmaBoundary16K = 2;
307 		static const uint16_t kDmaBoundary32K = 3;
308 		static const uint16_t kDmaBoundary64K = 4;
309 		static const uint16_t kDmaBoundary128K = 5;
310 		static const uint16_t kDmaBoundary256K = 6;
311 		static const uint16_t kDmaBoundary512K = 7;
312 
313 	private:
314 		volatile uint16_t value;
315 } __attribute__((packed));
316 
317 
318 // #pragma mark -
319 struct registers {
320 	// SD command generation
321 	volatile uint32_t system_address;
322 	BlockSize block_size;
323 	volatile uint16_t block_count;
324 	volatile uint32_t argument;
325 	volatile uint16_t transfer_mode;
326 	Command command;
327 
328 	// Response
329 	volatile uint32_t response[4];
330 
331 	// Buffer Data Port
332 	volatile uint32_t buffer_data_port;
333 
334 	// Host control 1
335 	PresentState		present_state;
336 	HostControl			host_control;
337 	PowerControl		power_control;
338 	volatile uint8_t	block_gap_control;
339 	volatile uint8_t	wakeup_control;
340 	ClockControl		clock_control;
341 	volatile uint8_t	timeout_control;
342 	SoftwareReset		software_reset;
343 
344 	// Interrupt control
345 	volatile uint32_t interrupt_status;
346 	volatile uint32_t interrupt_status_enable;
347 	volatile uint32_t interrupt_signal_enable;
348 	volatile uint16_t auto_cmd12_error_status;
349 
350 	// Host control 2
351 	volatile uint16_t host_control_2;
352 
353 	// Capabilities
354 	Capabilities capabilities;
355 	volatile uint64_t max_current_capabilities;
356 
357 	// Force event
358 	volatile uint16_t force_event_acmd_status;
359 	volatile uint16_t force_event_error_status;
360 
361 	// ADMA2
362 	volatile uint8_t adma_error_status;
363 	volatile uint8_t padding[3];
364 	volatile uint64_t adma_system_address;
365 
366 	// Preset values
367 	volatile uint64_t preset_value[2];
368 	volatile uint32_t padding1 :32;
369 	volatile uint16_t uhs2_preset_value;
370 	volatile uint16_t padding2 :16;
371 
372 	// ADMA3
373 	volatile uint64_t adma3_id_address;
374 
375 	// UHS-II
376 	volatile uint16_t uhs2_block_size;
377 	volatile uint16_t padding3 :16;
378 	volatile uint32_t uhs2_block_count;
379 	volatile uint8_t uhs2_command_packet[20];
380 	volatile uint16_t uhs2_transfer_mode;
381 	volatile uint16_t uhs2_command;
382 	volatile uint8_t uhs2_response[20];
383 	volatile uint8_t uhs2_msg_select;
384 	volatile uint8_t padding4[3];
385 	volatile uint32_t uhs2_msg;
386 	volatile uint16_t uhs2_device_interrupt_status;
387 	volatile uint8_t uhs2_device_select;
388 	volatile uint8_t uhs2_device_int_code;
389 	volatile uint16_t uhs2_software_reset;
390 	volatile uint16_t uhs2_timer_control;
391 	volatile uint32_t uhs2_error_interrupt_status;
392 	volatile uint32_t uhs2_error_interrupt_status_enable;
393 	volatile uint32_t uhs2_error_interrupt_signal_enable;
394 	volatile uint8_t padding5[16];
395 
396 	// Pointers
397 	volatile uint16_t uhs2_settings_pointer;
398 	volatile uint16_t uhs2_host_capabilities_pointer;
399 	volatile uint16_t uhs2_test_pointer;
400 	volatile uint16_t embedded_control_pointer;
401 	volatile uint16_t vendor_specific_pointer;
402 	volatile uint16_t reserved_specific_pointer;
403 	volatile uint8_t padding6[16];
404 
405 	// Common area
406 	volatile uint16_t slot_interrupt_status;
407 	HostControllerVersion host_controller_version;
408 } __attribute__((packed));
409 
410 typedef void* sdhci_mmc_bus;
411 
412 struct sdhci_crs {
413 	uint8	irq;
414 //	uint8	irq_triggering;
415 //	uint8	irq_polarity;
416 //	uint8	irq_shareable;
417 
418 	uint32	addr_bas;
419 	uint32	addr_len;
420 };
421 
422 extern float supports_device_acpi(device_node* parent);
423 extern float supports_device_pci(device_node* parent);
424 
425 extern status_t register_child_devices_acpi(void* cookie);
426 extern status_t register_child_devices_pci(void* cookie);
427 
428 extern status_t init_device_pci(device_node* node, SdhciDevice* context);
429 extern void uninit_device_pci(SdhciDevice* context, device_node* pciParent);
430 
431 extern status_t init_bus_acpi(device_node* node, void** bus_cookie);
432 extern status_t init_bus_pci(device_node* node, void** bus_cookie);
433 
434 extern void uninit_bus(void* bus_cookie);
435 extern void bus_removed(void* bus_cookie);
436 
437 status_t set_clock(void* controller, uint32_t kilohertz);
438 status_t execute_command(void* controller, uint8_t command,
439 	uint32_t argument, uint32_t* response);
440 status_t do_io(void* controller, uint8_t command,
441 	IOOperation* operation, bool offsetAsSectors);
442 void set_scan_semaphore(void* controller, sem_id sem);
443 void set_bus_width(void* controller, int width);
444 
445 extern mmc_bus_interface gSDHCIACPIDeviceModule;
446 extern mmc_bus_interface gSDHCIPCIDeviceModule;
447 
448 extern device_manager_info* gDeviceManager;
449 
450 #endif /*_SDHCI_H*/
451