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
31class 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
65class SdhciDevice {
66	public:
67		device_node* fNode;
68		uint8_t fRicohOriginalMode;
69};
70
71class TransferMode {
72	public:
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
103class Command {
104	public:
105		uint16_t Bits() { return fBits; }
106
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
139class PresentState {
140	public:
141		uint32_t Bits() { return fBits; }
142
143		bool IsCardInserted() { return fBits & (1 << 16); }
144		bool CommandInhibit() { return fBits & (1 << 0); }
145		bool DataInhibit() { return fBits & (1 << 1); }
146
147	private:
148		volatile uint32_t fBits;
149} __attribute__((packed));
150
151
152class PowerControl {
153	public:
154		uint8_t Bits() { return fBits; }
155
156		void SetVoltage(int voltage) {
157			fBits |= voltage | kBusPowerOn;
158		}
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
171class ClockControl
172{
173	public:
174		uint16_t Bits() { return fBits; }
175
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
189		void EnableInternal() { fBits |= 1 << 0; }
190		bool InternalStable() { return fBits & (1 << 1); }
191		void EnableSD() { fBits |= 1 << 2; }
192		void DisableSD() { fBits &= ~(1 << 2); }
193		void EnablePLL() { fBits |= 1 << 3; }
194	private:
195		volatile  uint16_t fBits;
196} __attribute__((packed));
197
198
199class SoftwareReset {
200	public:
201		uint8_t Bits() { return fBits; }
202
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
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 -
241class Capabilities
242{
243	public:
244		uint64_t Bits() { return fBits; }
245
246		uint8_t SupportedVoltages() { return (fBits >> 24) & 7; }
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
258class HostControllerVersion {
259	public:
260		const uint8_t specVersion;
261		const uint8_t vendorVersion;
262} __attribute__((packed));
263
264
265class HostControl {
266	public:
267		void SetDMAMode(uint8_t dmaMode)
268		{
269			value = (value & ~kDmaMask) | dmaMode;
270		}
271
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
296class BlockSize {
297	public:
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 -
319struct 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 :32;
369	volatile uint16_t uhs2_preset_value;
370	volatile uint16_t :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 :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 padding2[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 padding3[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 padding4[16];
404
405	// Common area
406	volatile uint16_t slot_interrupt_status;
407	HostControllerVersion host_controller_version;
408} __attribute__((packed));
409
410typedef void* sdhci_mmc_bus;
411
412struct 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
422extern float supports_device_acpi(device_node* parent);
423extern float supports_device_pci(device_node* parent);
424
425extern status_t register_child_devices_acpi(void* cookie);
426extern status_t register_child_devices_pci(void* cookie);
427
428extern status_t init_device_pci(device_node* node, SdhciDevice* context);
429extern void uninit_device_pci(SdhciDevice* context, device_node* pciParent);
430
431extern status_t init_bus_acpi(device_node* node, void** bus_cookie);
432extern status_t init_bus_pci(device_node* node, void** bus_cookie);
433
434extern void uninit_bus(void* bus_cookie);
435extern void bus_removed(void* bus_cookie);
436
437status_t set_clock(void* controller, uint32_t kilohertz);
438status_t execute_command(void* controller, uint8_t command,
439	uint32_t argument, uint32_t* response);
440status_t do_io(void* controller, uint8_t command,
441	IOOperation* operation, bool offsetAsSectors);
442void set_scan_semaphore(void* controller, sem_id sem);
443void set_bus_width(void* controller, int width);
444
445extern mmc_bus_interface gSDHCIACPIDeviceModule;
446extern mmc_bus_interface gSDHCIPCIDeviceModule;
447
448extern device_manager_info* gDeviceManager;
449
450#endif /*_SDHCI_H*/
451