1/*
2 * Copyright 2018-2019 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#ifndef _SDHCI_PCI_H
9#define _SDHCI_PCI_H
10
11
12#include <device_manager.h>
13#include <KernelExport.h>
14
15
16#define SDHCI_PCI_SLOT_INFO 							0x40
17#define SDHCI_PCI_SLOTS(x) 								((( x >> 4) & 7))
18#define SDHCI_PCI_SLOT_INFO_FIRST_BASE_INDEX(x)			(( x ) & 7)
19
20#define SDHCI_DEVICE_TYPE_ITEM 							"sdhci/type"
21#define SDHCI_BUS_TYPE_NAME 							"bus/sdhci/v1"
22
23
24class Command {
25	public:
26		uint16_t Bits() { return fBits; }
27
28		void SendCommand(uint8_t command, uint8_t type)
29		{
30			fBits = (command << 8) | type;
31		}
32
33		static const uint8_t kNoReplyType = 0;
34		static const uint8_t kR1Type = 0x1C;
35		static const uint8_t kR2Type = 0x09;
36		static const uint8_t kR3Type = 0x02;
37		static const uint8_t kR6Type = 0x1C;
38		static const uint8_t kR7Type = 0x3C;
39
40	private:
41		volatile uint16_t fBits;
42} __attribute__((packed));
43#define SDHCI_RESPONSE_R1                               2
44#define SDHCI_CMD_CRC_EN                                1 << 3
45#define SDHCI_CMD_INDEX_EN                              1 << 4
46
47
48class PresentState {
49	public:
50		uint32_t Bits() { return fBits; }
51
52		bool IsCardInserted() { return fBits & (1 << 16); }
53		bool CommandInhibit() { return fBits & (1 << 0); }
54
55	private:
56		volatile uint32_t fBits;
57} __attribute__((packed));
58
59
60class PowerControl {
61	public:
62		uint8_t Bits() { return fBits; }
63
64		void SetVoltage(int voltage) {
65			fBits |= voltage | kBusPowerOn;
66		}
67		void PowerOff() { fBits &= ~kBusPowerOn; }
68
69		static const uint8_t k3v3 = 7 << 1;
70		static const uint8_t k3v0 = 6 << 1;
71		static const uint8_t k1v8 = 5 << 1;
72	private:
73		volatile uint8_t fBits;
74
75		static const uint8_t kBusPowerOn = 1;
76} __attribute__((packed));
77
78
79class ClockControl
80{
81	public:
82		uint16_t Bits() { return fBits; }
83
84		uint16_t SetDivider(uint16_t divider) {
85			if (divider == 1)
86				divider = 0;
87			else
88				divider /= 2;
89			uint16_t bits = fBits & ~0xffc0;
90			bits |= divider << 8;
91			bits |= (divider >> 8) & 0xc0;
92			fBits = bits;
93
94			return divider == 0 ? 1 : divider * 2;
95		}
96
97		void EnableInternal() { fBits |= 1 << 0; }
98		bool InternalStable() { return fBits & (1 << 1); }
99		void EnableSD() { fBits |= 1 << 2; }
100		void DisableSD() { fBits &= ~(1 << 2); }
101		void EnablePLL() { fBits |= 1 << 3; }
102	private:
103		volatile  uint16_t fBits;
104} __attribute__((packed));
105
106
107class SoftwareReset {
108	public:
109		uint8_t Bits() { return fBits; }
110
111		void ResetAll() {
112			fBits |= 1;
113			while(fBits & 1);
114		}
115
116		void ResetCommandLine() {
117			fBits |= 2;
118			while(fBits & 2);
119		}
120
121	private:
122		volatile uint8_t fBits;
123} __attribute__((packed));
124
125
126/* Interrupt registers */
127#define SDHCI_INT_CMD_CMP		0x00000001 		// command complete enable
128#define SDHCI_INT_TRANS_CMP		0x00000002		// transfer complete enable
129#define SDHCI_INT_CARD_INS 		0x00000040 		// card insertion enable
130#define SDHCI_INT_CARD_REM 		0x00000080 		// card removal enable
131#define SDHCI_INT_ERROR         0x00008000      // error
132#define SDHCI_INT_TIMEOUT		0x00010000 		// Timeout error
133#define SDHCI_INT_CRC			0x00020000 		// CRC error
134#define SDHCI_INT_END_BIT		0x00040000 		// end bit error
135#define SDHCI_INT_INDEX 		0x00080000		// index error
136#define SDHCI_INT_BUS_POWER		0x00800000 		// power fail
137
138#define	 SDHCI_INT_CMD_ERROR_MASK	(SDHCI_INT_TIMEOUT | \
139		SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX)
140
141#define SDHCI_INT_CMD_MASK 	(SDHCI_INT_CMD_CMP | SDHCI_INT_CMD_ERROR_MASK)
142
143
144class Capabilities
145{
146	public:
147		uint64_t Bits() { return fBits; }
148
149		uint8_t SupportedVoltages() { return (fBits >> 24) & 7; }
150		uint8_t BaseClockFrequency() { return (fBits >> 8) & 0xFF; }
151
152		static const uint8_t k3v3 = 1;
153		static const uint8_t k3v0 = 2;
154		static const uint8_t k1v8 = 4;
155
156	private:
157		const uint64_t fBits;
158} __attribute__((packed));
159
160
161class HostControllerVersion {
162	public:
163		const uint8_t specVersion;
164		const uint8_t vendorVersion;
165} __attribute__((packed));
166
167
168struct registers {
169	// SD command generation
170	volatile uint32_t system_address;
171	volatile uint16_t block_size;
172	volatile uint16_t block_count;
173	volatile uint32_t argument;
174	volatile uint16_t transfer_mode;
175	Command command;
176
177	// Response
178	volatile uint32_t response[4];
179
180	// Buffer Data Port
181	volatile uint32_t buffer_data_port;
182
183	// Host control 1
184	PresentState present_state;
185	volatile uint8_t host_control;
186	PowerControl power_control;
187	volatile uint8_t block_gap_control;
188	volatile uint8_t wakeup_control;
189	ClockControl clock_control;
190	volatile uint8_t timeout_control;
191	SoftwareReset software_reset;
192
193	// Interrupt control
194	volatile uint32_t interrupt_status;
195	volatile uint32_t interrupt_status_enable;
196	volatile uint32_t interrupt_signal_enable;
197	volatile uint16_t auto_cmd12_error_status;
198
199	// Host control 2
200	volatile uint16_t host_control_2;
201
202	// Capabilities
203	Capabilities capabilities;
204	volatile uint64_t max_current_capabilities;
205
206	// Force event
207	volatile uint16_t force_event_acmd_status;
208	volatile uint16_t force_event_error_status;
209
210	// ADMA2
211	volatile uint8_t adma_error_status;
212	volatile uint8_t padding[3];
213	volatile uint64_t adma_system_address;
214
215	// Preset values
216	volatile uint64_t preset_value[2];
217	volatile uint32_t :32;
218	volatile uint16_t uhs2_preset_value;
219	volatile uint16_t :16;
220
221	// ADMA3
222	volatile uint64_t adma3_id_address;
223
224	// UHS-II
225	volatile uint16_t uhs2_block_size;
226	volatile uint16_t :16;
227	volatile uint32_t uhs2_block_count;
228	volatile uint8_t uhs2_command_packet[20];
229	volatile uint16_t uhs2_transfer_mode;
230	volatile uint16_t uhs2_command;
231	volatile uint8_t uhs2_response[20];
232	volatile uint8_t uhs2_msg_select;
233	volatile uint8_t padding2[3];
234	volatile uint32_t uhs2_msg;
235	volatile uint16_t uhs2_device_interrupt_status;
236	volatile uint8_t uhs2_device_select;
237	volatile uint8_t uhs2_device_int_code;
238	volatile uint16_t uhs2_software_reset;
239	volatile uint16_t uhs2_timer_control;
240	volatile uint32_t uhs2_error_interrupt_status;
241	volatile uint32_t uhs2_error_interrupt_status_enable;
242	volatile uint32_t uhs2_error_interrupt_signal_enable;
243	volatile uint8_t padding3[16];
244
245	// Pointers
246	volatile uint16_t uhs2_settings_pointer;
247	volatile uint16_t uhs2_host_capabilities_pointer;
248	volatile uint16_t uhs2_test_pointer;
249	volatile uint16_t embedded_control_pointer;
250	volatile uint16_t vendor_specific_pointer;
251	volatile uint16_t reserved_specific_pointer;
252	volatile uint8_t padding4[16];
253
254	// Common area
255	volatile uint16_t slot_interrupt_status;
256	HostControllerVersion host_controller_version;
257} __attribute__((packed));
258
259typedef void* sdhci_mmc_bus;
260
261
262
263#endif /*_SDHCI_PCI_H*/
264