125b6a6f1Skrish_iyer/*
23aef22f7SAdrien Destugues * Copyright 2018-2019 Haiku, Inc. All rights reserved.
325b6a6f1Skrish_iyer * Distributed under the terms of the MIT License.
425b6a6f1Skrish_iyer *
525b6a6f1Skrish_iyer * Authors:
625b6a6f1Skrish_iyer *		B Krishnan Iyer, krishnaniyer97@gmail.com
725b6a6f1Skrish_iyer */
825b6a6f1Skrish_iyer#ifndef _SDHCI_PCI_H
925b6a6f1Skrish_iyer#define _SDHCI_PCI_H
1025b6a6f1Skrish_iyer
1125b6a6f1Skrish_iyer
1225b6a6f1Skrish_iyer#include <device_manager.h>
1325b6a6f1Skrish_iyer#include <KernelExport.h>
1425b6a6f1Skrish_iyer
1525b6a6f1Skrish_iyer
1625b6a6f1Skrish_iyer#define SDHCI_PCI_SLOT_INFO 							0x40
1725b6a6f1Skrish_iyer#define SDHCI_PCI_SLOTS(x) 								((( x >> 4) & 7))
1825b6a6f1Skrish_iyer#define SDHCI_PCI_SLOT_INFO_FIRST_BASE_INDEX(x)			(( x ) & 7)
1925b6a6f1Skrish_iyer
2025b6a6f1Skrish_iyer#define SDHCI_DEVICE_TYPE_ITEM 							"sdhci/type"
2125b6a6f1Skrish_iyer#define SDHCI_BUS_TYPE_NAME 							"bus/sdhci/v1"
2225b6a6f1Skrish_iyer
23cdc4a175SAdrien Destugues
24cdc4a175SAdrien Destuguesclass Command {
25cdc4a175SAdrien Destugues	public:
26cdc4a175SAdrien Destugues		uint16_t Bits() { return fBits; }
27cdc4a175SAdrien Destugues
28ff76d2dfSAdrien Destugues		void SendCommand(uint8_t command, uint8_t type)
29cdc4a175SAdrien Destugues		{
30ff76d2dfSAdrien Destugues			fBits = (command << 8) | type;
31cdc4a175SAdrien Destugues		}
32cdc4a175SAdrien Destugues
33ff76d2dfSAdrien Destugues		static const uint8_t kNoReplyType = 0;
34ff76d2dfSAdrien Destugues		static const uint8_t kR1Type = 0x1C;
35ff76d2dfSAdrien Destugues		static const uint8_t kR2Type = 0x09;
36ff76d2dfSAdrien Destugues		static const uint8_t kR3Type = 0x02;
37ff76d2dfSAdrien Destugues		static const uint8_t kR6Type = 0x1C;
38ff76d2dfSAdrien Destugues		static const uint8_t kR7Type = 0x3C;
39ff76d2dfSAdrien Destugues
40cdc4a175SAdrien Destugues	private:
41cdc4a175SAdrien Destugues		volatile uint16_t fBits;
42cdc4a175SAdrien Destugues} __attribute__((packed));
4325b6a6f1Skrish_iyer#define SDHCI_RESPONSE_R1                               2
4425b6a6f1Skrish_iyer#define SDHCI_CMD_CRC_EN                                1 << 3
4525b6a6f1Skrish_iyer#define SDHCI_CMD_INDEX_EN                              1 << 4
46cdc4a175SAdrien Destugues
47cdc4a175SAdrien Destugues
48cdc4a175SAdrien Destuguesclass PresentState {
49cdc4a175SAdrien Destugues	public:
50cdc4a175SAdrien Destugues		uint32_t Bits() { return fBits; }
51cdc4a175SAdrien Destugues
52cdc4a175SAdrien Destugues		bool IsCardInserted() { return fBits & (1 << 16); }
53ff76d2dfSAdrien Destugues		bool CommandInhibit() { return fBits & (1 << 0); }
54cdc4a175SAdrien Destugues
55cdc4a175SAdrien Destugues	private:
56cdc4a175SAdrien Destugues		volatile uint32_t fBits;
57cdc4a175SAdrien Destugues} __attribute__((packed));
58cdc4a175SAdrien Destugues
59cdc4a175SAdrien Destugues
60cdc4a175SAdrien Destuguesclass PowerControl {
61cdc4a175SAdrien Destugues	public:
62cdc4a175SAdrien Destugues		uint8_t Bits() { return fBits; }
63cdc4a175SAdrien Destugues
64cdc4a175SAdrien Destugues		void SetVoltage(int voltage) {
65cdc4a175SAdrien Destugues			fBits |= voltage | kBusPowerOn;
66cdc4a175SAdrien Destugues		}
67cdc4a175SAdrien Destugues		void PowerOff() { fBits &= ~kBusPowerOn; }
68cdc4a175SAdrien Destugues
69cdc4a175SAdrien Destugues		static const uint8_t k3v3 = 7 << 1;
70cdc4a175SAdrien Destugues		static const uint8_t k3v0 = 6 << 1;
71cdc4a175SAdrien Destugues		static const uint8_t k1v8 = 5 << 1;
72cdc4a175SAdrien Destugues	private:
73cdc4a175SAdrien Destugues		volatile uint8_t fBits;
74cdc4a175SAdrien Destugues
75cdc4a175SAdrien Destugues		static const uint8_t kBusPowerOn = 1;
76cdc4a175SAdrien Destugues} __attribute__((packed));
77cdc4a175SAdrien Destugues
78cdc4a175SAdrien Destugues
79cdc4a175SAdrien Destuguesclass ClockControl
80cdc4a175SAdrien Destugues{
81cdc4a175SAdrien Destugues	public:
82cdc4a175SAdrien Destugues		uint16_t Bits() { return fBits; }
83cdc4a175SAdrien Destugues
84cdc4a175SAdrien Destugues		uint16_t SetDivider(uint16_t divider) {
85cdc4a175SAdrien Destugues			if (divider == 1)
86cdc4a175SAdrien Destugues				divider = 0;
87cdc4a175SAdrien Destugues			else
88cdc4a175SAdrien Destugues				divider /= 2;
89cdc4a175SAdrien Destugues			uint16_t bits = fBits & ~0xffc0;
90cdc4a175SAdrien Destugues			bits |= divider << 8;
91cdc4a175SAdrien Destugues			bits |= (divider >> 8) & 0xc0;
92cdc4a175SAdrien Destugues			fBits = bits;
93cdc4a175SAdrien Destugues
94cdc4a175SAdrien Destugues			return divider == 0 ? 1 : divider * 2;
95cdc4a175SAdrien Destugues		}
96cdc4a175SAdrien Destugues
97cdc4a175SAdrien Destugues		void EnableInternal() { fBits |= 1 << 0; }
98cdc4a175SAdrien Destugues		bool InternalStable() { return fBits & (1 << 1); }
99cdc4a175SAdrien Destugues		void EnableSD() { fBits |= 1 << 2; }
100cdc4a175SAdrien Destugues		void DisableSD() { fBits &= ~(1 << 2); }
101cdc4a175SAdrien Destugues		void EnablePLL() { fBits |= 1 << 3; }
102cdc4a175SAdrien Destugues	private:
103cdc4a175SAdrien Destugues		volatile  uint16_t fBits;
104cdc4a175SAdrien Destugues} __attribute__((packed));
105cdc4a175SAdrien Destugues
106cdc4a175SAdrien Destugues
107cdc4a175SAdrien Destuguesclass SoftwareReset {
108cdc4a175SAdrien Destugues	public:
109cdc4a175SAdrien Destugues		uint8_t Bits() { return fBits; }
110cdc4a175SAdrien Destugues
111cdc4a175SAdrien Destugues		void ResetAll() {
112cdc4a175SAdrien Destugues			fBits |= 1;
113cdc4a175SAdrien Destugues			while(fBits & 1);
114cdc4a175SAdrien Destugues		}
115cdc4a175SAdrien Destugues
116518af33fSAdrien Destugues		void ResetCommandLine() {
117cdc4a175SAdrien Destugues			fBits |= 2;
118cdc4a175SAdrien Destugues			while(fBits & 2);
119cdc4a175SAdrien Destugues		}
120cdc4a175SAdrien Destugues
121cdc4a175SAdrien Destugues	private:
122cdc4a175SAdrien Destugues		volatile uint8_t fBits;
123cdc4a175SAdrien Destugues} __attribute__((packed));
124cdc4a175SAdrien Destugues
125cdc4a175SAdrien Destugues
12625b6a6f1Skrish_iyer/* Interrupt registers */
12725b6a6f1Skrish_iyer#define SDHCI_INT_CMD_CMP		0x00000001 		// command complete enable
12825b6a6f1Skrish_iyer#define SDHCI_INT_TRANS_CMP		0x00000002		// transfer complete enable
12925b6a6f1Skrish_iyer#define SDHCI_INT_CARD_INS 		0x00000040 		// card insertion enable
13025b6a6f1Skrish_iyer#define SDHCI_INT_CARD_REM 		0x00000080 		// card removal enable
131518af33fSAdrien Destugues#define SDHCI_INT_ERROR         0x00008000      // error
13225b6a6f1Skrish_iyer#define SDHCI_INT_TIMEOUT		0x00010000 		// Timeout error
13325b6a6f1Skrish_iyer#define SDHCI_INT_CRC			0x00020000 		// CRC error
13425b6a6f1Skrish_iyer#define SDHCI_INT_END_BIT		0x00040000 		// end bit error
13525b6a6f1Skrish_iyer#define SDHCI_INT_INDEX 		0x00080000		// index error
13625b6a6f1Skrish_iyer#define SDHCI_INT_BUS_POWER		0x00800000 		// power fail
13725b6a6f1Skrish_iyer
13825b6a6f1Skrish_iyer#define	 SDHCI_INT_CMD_ERROR_MASK	(SDHCI_INT_TIMEOUT | \
13925b6a6f1Skrish_iyer		SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX)
14025b6a6f1Skrish_iyer
14125b6a6f1Skrish_iyer#define SDHCI_INT_CMD_MASK 	(SDHCI_INT_CMD_CMP | SDHCI_INT_CMD_ERROR_MASK)
14225b6a6f1Skrish_iyer
14325b6a6f1Skrish_iyer
144cdc4a175SAdrien Destuguesclass Capabilities
145cdc4a175SAdrien Destugues{
146cdc4a175SAdrien Destugues	public:
147cdc4a175SAdrien Destugues		uint64_t Bits() { return fBits; }
148cdc4a175SAdrien Destugues
149cdc4a175SAdrien Destugues		uint8_t SupportedVoltages() { return (fBits >> 24) & 7; }
150cdc4a175SAdrien Destugues		uint8_t BaseClockFrequency() { return (fBits >> 8) & 0xFF; }
151cdc4a175SAdrien Destugues
152cdc4a175SAdrien Destugues		static const uint8_t k3v3 = 1;
153cdc4a175SAdrien Destugues		static const uint8_t k3v0 = 2;
154cdc4a175SAdrien Destugues		static const uint8_t k1v8 = 4;
155cdc4a175SAdrien Destugues
156cdc4a175SAdrien Destugues	private:
157cdc4a175SAdrien Destugues		const uint64_t fBits;
158cdc4a175SAdrien Destugues} __attribute__((packed));
159cdc4a175SAdrien Destugues
160cdc4a175SAdrien Destugues
161cdc4a175SAdrien Destuguesclass HostControllerVersion {
162cdc4a175SAdrien Destugues	public:
163cdc4a175SAdrien Destugues		const uint8_t specVersion;
164cdc4a175SAdrien Destugues		const uint8_t vendorVersion;
165cdc4a175SAdrien Destugues} __attribute__((packed));
166cdc4a175SAdrien Destugues
167cdc4a175SAdrien Destugues
16825b6a6f1Skrish_iyerstruct registers {
169cdc4a175SAdrien Destugues	// SD command generation
17025b6a6f1Skrish_iyer	volatile uint32_t system_address;
17125b6a6f1Skrish_iyer	volatile uint16_t block_size;
17225b6a6f1Skrish_iyer	volatile uint16_t block_count;
17325b6a6f1Skrish_iyer	volatile uint32_t argument;
17425b6a6f1Skrish_iyer	volatile uint16_t transfer_mode;
175cdc4a175SAdrien Destugues	Command command;
176cdc4a175SAdrien Destugues
177cdc4a175SAdrien Destugues	// Response
178ff76d2dfSAdrien Destugues	volatile uint32_t response[4];
179cdc4a175SAdrien Destugues
180cdc4a175SAdrien Destugues	// Buffer Data Port
18125b6a6f1Skrish_iyer	volatile uint32_t buffer_data_port;
182cdc4a175SAdrien Destugues
183cdc4a175SAdrien Destugues	// Host control 1
184cdc4a175SAdrien Destugues	PresentState present_state;
18525b6a6f1Skrish_iyer	volatile uint8_t host_control;
186cdc4a175SAdrien Destugues	PowerControl power_control;
18725b6a6f1Skrish_iyer	volatile uint8_t block_gap_control;
18825b6a6f1Skrish_iyer	volatile uint8_t wakeup_control;
189cdc4a175SAdrien Destugues	ClockControl clock_control;
19025b6a6f1Skrish_iyer	volatile uint8_t timeout_control;
191cdc4a175SAdrien Destugues	SoftwareReset software_reset;
192cdc4a175SAdrien Destugues
193cdc4a175SAdrien Destugues	// Interrupt control
19425b6a6f1Skrish_iyer	volatile uint32_t interrupt_status;
19525b6a6f1Skrish_iyer	volatile uint32_t interrupt_status_enable;
19625b6a6f1Skrish_iyer	volatile uint32_t interrupt_signal_enable;
19725b6a6f1Skrish_iyer	volatile uint16_t auto_cmd12_error_status;
198cdc4a175SAdrien Destugues
199cdc4a175SAdrien Destugues	// Host control 2
200f3755303SAdrien Destugues	volatile uint16_t host_control_2;
201cdc4a175SAdrien Destugues
202cdc4a175SAdrien Destugues	// Capabilities
203cdc4a175SAdrien Destugues	Capabilities capabilities;
204f3755303SAdrien Destugues	volatile uint64_t max_current_capabilities;
205cdc4a175SAdrien Destugues
206cdc4a175SAdrien Destugues	// Force event
207f3755303SAdrien Destugues	volatile uint16_t force_event_acmd_status;
208f3755303SAdrien Destugues	volatile uint16_t force_event_error_status;
209cdc4a175SAdrien Destugues
210cdc4a175SAdrien Destugues	// ADMA2
211f3755303SAdrien Destugues	volatile uint8_t adma_error_status;
212f3755303SAdrien Destugues	volatile uint8_t padding[3];
213f3755303SAdrien Destugues	volatile uint64_t adma_system_address;
214cdc4a175SAdrien Destugues
215cdc4a175SAdrien Destugues	// Preset values
216f3755303SAdrien Destugues	volatile uint64_t preset_value[2];
217f3755303SAdrien Destugues	volatile uint32_t :32;
218f3755303SAdrien Destugues	volatile uint16_t uhs2_preset_value;
219f3755303SAdrien Destugues	volatile uint16_t :16;
220cdc4a175SAdrien Destugues
221cdc4a175SAdrien Destugues	// ADMA3
222f3755303SAdrien Destugues	volatile uint64_t adma3_id_address;
223cdc4a175SAdrien Destugues
224cdc4a175SAdrien Destugues	// UHS-II
225f3755303SAdrien Destugues	volatile uint16_t uhs2_block_size;
226f3755303SAdrien Destugues	volatile uint16_t :16;
227f3755303SAdrien Destugues	volatile uint32_t uhs2_block_count;
228f3755303SAdrien Destugues	volatile uint8_t uhs2_command_packet[20];
229f3755303SAdrien Destugues	volatile uint16_t uhs2_transfer_mode;
230f3755303SAdrien Destugues	volatile uint16_t uhs2_command;
231f3755303SAdrien Destugues	volatile uint8_t uhs2_response[20];
232f3755303SAdrien Destugues	volatile uint8_t uhs2_msg_select;
233f3755303SAdrien Destugues	volatile uint8_t padding2[3];
234f3755303SAdrien Destugues	volatile uint32_t uhs2_msg;
235f3755303SAdrien Destugues	volatile uint16_t uhs2_device_interrupt_status;
236f3755303SAdrien Destugues	volatile uint8_t uhs2_device_select;
237f3755303SAdrien Destugues	volatile uint8_t uhs2_device_int_code;
238f3755303SAdrien Destugues	volatile uint16_t uhs2_software_reset;
239f3755303SAdrien Destugues	volatile uint16_t uhs2_timer_control;
240f3755303SAdrien Destugues	volatile uint32_t uhs2_error_interrupt_status;
241f3755303SAdrien Destugues	volatile uint32_t uhs2_error_interrupt_status_enable;
242f3755303SAdrien Destugues	volatile uint32_t uhs2_error_interrupt_signal_enable;
243f3755303SAdrien Destugues	volatile uint8_t padding3[16];
244cdc4a175SAdrien Destugues
245cdc4a175SAdrien Destugues	// Pointers
246f3755303SAdrien Destugues	volatile uint16_t uhs2_settings_pointer;
247f3755303SAdrien Destugues	volatile uint16_t uhs2_host_capabilities_pointer;
248f3755303SAdrien Destugues	volatile uint16_t uhs2_test_pointer;
249f3755303SAdrien Destugues	volatile uint16_t embedded_control_pointer;
250f3755303SAdrien Destugues	volatile uint16_t vendor_specific_pointer;
251f3755303SAdrien Destugues	volatile uint16_t reserved_specific_pointer;
252f3755303SAdrien Destugues	volatile uint8_t padding4[16];
253cdc4a175SAdrien Destugues
254cdc4a175SAdrien Destugues	// Common area
25525b6a6f1Skrish_iyer	volatile uint16_t slot_interrupt_status;
256cdc4a175SAdrien Destugues	HostControllerVersion host_controller_version;
25725b6a6f1Skrish_iyer} __attribute__((packed));
25825b6a6f1Skrish_iyer
25925b6a6f1Skrish_iyertypedef void* sdhci_mmc_bus;
26025b6a6f1Skrish_iyer
26125b6a6f1Skrish_iyer
26225b6a6f1Skrish_iyer
26325b6a6f1Skrish_iyer#endif /*_SDHCI_PCI_H*/
264