summaryrefslogtreecommitdiffstats
path: root/drivers/mci/sdhci.h
blob: 2df73e3bece048cce05a95821be62721f034b956 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __MCI_SDHCI_H
#define __MCI_SDHCI_H

#include <pbl.h>
#include <dma.h>
#include <linux/iopoll.h>

#define SDHCI_DMA_ADDRESS					0x00
#define SDHCI_BLOCK_SIZE__BLOCK_COUNT				0x04
#define SDHCI_BLOCK_SIZE					0x04
#define  SDHCI_DMA_BOUNDARY_512K		SDHCI_DMA_BOUNDARY(7)
#define  SDHCI_DMA_BOUNDARY_256K		SDHCI_DMA_BOUNDARY(6)
#define  SDHCI_DMA_BOUNDARY_128K		SDHCI_DMA_BOUNDARY(5)
#define  SDHCI_DMA_BOUNDARY_64K			SDHCI_DMA_BOUNDARY(4)
#define  SDHCI_DMA_BOUNDARY_32K			SDHCI_DMA_BOUNDARY(3)
#define  SDHCI_DMA_BOUNDARY_16K			SDHCI_DMA_BOUNDARY(2)
#define  SDHCI_DMA_BOUNDARY_8K			SDHCI_DMA_BOUNDARY(1)
#define  SDHCI_DMA_BOUNDARY_4K			SDHCI_DMA_BOUNDARY(0)
#define  SDHCI_DMA_BOUNDARY(x)			(((x) & 0x7) << 12)
#define  SDHCI_TRANSFER_BLOCK_SIZE(x)		((x) & 0xfff)
#define SDHCI_BLOCK_COUNT					0x06
#define SDHCI_ARGUMENT						0x08
#define SDHCI_TRANSFER_MODE__COMMAND				0x0c
#define SDHCI_TRANSFER_MODE					0x0c
#define  SDHCI_MULTIPLE_BLOCKS			BIT(5)
#define  SDHCI_DATA_TO_HOST			BIT(4)
#define  SDHCI_BLOCK_COUNT_EN			BIT(1)
#define  SDHCI_DMA_EN				BIT(0)
#define SDHCI_COMMAND						0x0e
#define  SDHCI_CMD_INDEX(c)			(((c) & 0x3f) << 8)
#define  SDHCI_COMMAND_CMDTYP_SUSPEND		(1 << 6)
#define  SDHCI_COMMAND_CMDTYP_RESUME		(2 << 6)
#define  SDHCI_COMMAND_CMDTYP_ABORT		(3 << 6)
#define  SDHCI_DATA_PRESENT			BIT(5)
#define  SDHCI_CMD_INDEX_CHECK_EN		BIT(4)
#define  SDHCI_CMD_CRC_CHECK_EN			BIT(3)
#define  SDHCI_RESP_TYPE_48_BUSY		3
#define  SDHCI_RESP_TYPE_48			2
#define  SDHCI_RESP_TYPE_136			1
#define  SDHCI_RESP_NONE			0
#define SDHCI_RESPONSE_0					0x10
#define SDHCI_RESPONSE_1					0x14
#define SDHCI_RESPONSE_2					0x18
#define SDHCI_RESPONSE_3					0x1c
#define SDHCI_BUFFER						0x20
#define SDHCI_PRESENT_STATE					0x24
#define  SDHCI_WRITE_PROTECT			BIT(19)
#define  SDHCI_CARD_DETECT			BIT(18)
#define  SDHCI_CARD_PRESENT			BIT(16)
#define  SDHCI_BUFFER_READ_ENABLE		BIT(11)
#define  SDHCI_BUFFER_WRITE_ENABLE		BIT(10)
#define  SDHCI_DATA_LINE_ACTIVE			BIT(2)
#define  SDHCI_CMD_INHIBIT_DATA			BIT(1)
#define  SDHCI_CMD_INHIBIT_CMD			BIT(0)
#define SDHCI_PRESENT_STATE1					0x26
#define SDHCI_HOST_CONTROL__POWER_CONTROL__BLOCK_GAP_CONTROL	0x28
#define SDHCI_HOST_CONTROL					0x28
#define  SDHCI_CTRL_LED         BIT(0)
#define  SDHCI_CTRL_4BITBUS     BIT(1)
#define  SDHCI_CTRL_HISPD       BIT(2)
#define  SDHCI_CTRL_DMA_MASK    0x18
#define   SDHCI_CTRL_SDMA       0x00
#define   SDHCI_CTRL_ADMA1      0x08
#define   SDHCI_CTRL_ADMA32     0x10
#define   SDHCI_CTRL_ADMA64     0x18
#define   SDHCI_CTRL_ADMA3      0x18
#define  SDHCI_CTRL_8BITBUS     BIT(5)
#define  SDHCI_CTRL_CDTEST_INS  BIT(6)
#define  SDHCI_CTRL_CDTEST_EN   BIT(7)
#define SDHCI_POWER_CONTROL					0x29
#define  SDHCI_POWER_ON				0x01
#define  SDHCI_POWER_180			0x0A
#define  SDHCI_POWER_300			0x0C
#define  SDHCI_POWER_330			0x0E
#define  SDHCI_BUS_VOLTAGE_330			SDHCI_BUS_VOLTAGE(7)
#define  SDHCI_BUS_VOLTAGE(v)			((v) << 1)
#define  SDHCI_BUS_POWER_EN			BIT(0)
#define SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET	0x2c
#define SDHCI_CLOCK_CONTROL					0x2C
#define  SDHCI_DIVIDER_SHIFT			8
#define  SDHCI_DIVIDER_HI_SHIFT			6
#define  SDHCI_DIV_MASK				0xFF
#define  SDHCI_DIV_HI_MASK			0x300
#define  SDHCI_DIV_MASK_LEN			8
#define  SDHCI_FREQ_SEL(x)                     (((x) & 0xff) << 8)
#define  SDHCI_DIV_HI_MASK			0x300
#define  SDHCI_PROG_CLOCK_MODE			BIT(5)
#define  SDHCI_CLOCK_CARD_EN			BIT(2)
#define  SDHCI_CLOCK_PLL_EN			BIT(3)
#define  SDHCI_CLOCK_INT_STABLE			BIT(1)
#define  SDHCI_CLOCK_INT_EN     		BIT(0)
#define SDHCI_TIMEOUT_CONTROL					0x2e
#define SDHCI_SOFTWARE_RESET					0x2f
#define  SDHCI_RESET_ALL			BIT(0)
#define  SDHCI_RESET_CMD			BIT(1)
#define  SDHCI_RESET_DATA			BIT(2)
#define SDHCI_INT_STATUS					0x30
#define SDHCI_INT_NORMAL_STATUS					0x30
#define  SDHCI_INT_DATA_END_BIT			BIT(22)
#define  SDHCI_INT_DATA_CRC			BIT(21)
#define  SDHCI_INT_DATA_TIMEOUT			BIT(20)
#define  SDHCI_INT_INDEX			BIT(19)
#define  SDHCI_INT_END_BIT			BIT(18)
#define  SDHCI_INT_CRC				BIT(17)
#define  SDHCI_INT_TIMEOUT			BIT(16)
#define  SDHCI_INT_ERROR			BIT(15)
#define  SDHCI_INT_CARD_INT			BIT(8)
#define  SDHCI_INT_CARD_INSERT			BIT(6)
#define  SDHCI_INT_DATA_AVAIL			BIT(5)
#define  SDHCI_INT_SPACE_AVAIL			BIT(4)
#define  SDHCI_INT_DMA				BIT(3)
#define  SDHCI_INT_XFER_COMPLETE		BIT(1)
#define  SDHCI_INT_CMD_COMPLETE			BIT(0)
#define SDHCI_INT_ERROR_STATUS					0x32
#define SDHCI_INT_ENABLE					0x34
#define SDHCI_INT_ERROR_ENABLE					0x36
#define SDHCI_SIGNAL_ENABLE					0x38
#define SDHCI_ACMD12_ERR__HOST_CONTROL2				0x3C
#define SDHCI_CAPABILITIES					0x40
#define  SDHCI_TIMEOUT_CLK_MASK			GENMASK(5, 0)
#define  SDHCI_TIMEOUT_CLK_UNIT			0x00000080
#define  SDHCI_CLOCK_BASE_MASK			GENMASK(13, 8)
#define  SDHCI_CLOCK_V3_BASE_MASK		GENMASK(15, 8)
#define  SDHCI_MAX_BLOCK_MASK			0x00030000
#define  SDHCI_MAX_BLOCK_SHIFT			16
#define  SDHCI_CAN_DO_8BIT			0x00040000
#define  SDHCI_CAN_DO_ADMA2			0x00080000
#define  SDHCI_CAN_DO_ADMA1			0x00100000
#define  SDHCI_CAN_DO_HISPD			0x00200000
#define  SDHCI_CAN_DO_SDMA			0x00400000
#define  SDHCI_CAN_DO_SUSPEND			0x00800000
#define  SDHCI_CAN_VDD_330			0x01000000
#define  SDHCI_CAN_VDD_300			0x02000000
#define  SDHCI_CAN_VDD_180			0x04000000
#define  SDHCI_CAN_64BIT_V4			0x08000000
#define  SDHCI_CAN_64BIT			0x10000000

#define SDHCI_CAPABILITIES_1			0x44
#define  SDHCI_SUPPORT_SDR50			0x00000001
#define  SDHCI_SUPPORT_SDR104			0x00000002
#define  SDHCI_SUPPORT_DDR50			0x00000004
#define  SDHCI_DRIVER_TYPE_A			0x00000010
#define  SDHCI_DRIVER_TYPE_C			0x00000020
#define  SDHCI_DRIVER_TYPE_D			0x00000040
#define  SDHCI_RETUNING_TIMER_COUNT_MASK	GENMASK(11, 8)
#define  SDHCI_USE_SDR50_TUNING			0x00002000
#define  SDHCI_RETUNING_MODE_MASK		GENMASK(15, 14)
#define  SDHCI_CLOCK_MUL_MASK			GENMASK(23, 16)
#define  SDHCI_CAN_DO_ADMA3			0x08000000
#define  SDHCI_SUPPORT_HS400			0x80000000 /* Non-standard */

#define SDHCI_PRESET_FOR_SDR12	0x66
#define SDHCI_PRESET_FOR_SDR25	0x68
#define SDHCI_PRESET_FOR_SDR50	0x6A
#define SDHCI_PRESET_FOR_SDR104	0x6C
#define SDHCI_PRESET_FOR_DDR50	0x6E
#define SDHCI_PRESET_FOR_HS400	0x74 /* Non-standard */
#define SDHCI_PRESET_CLKGEN_SEL		BIT(10)
#define SDHCI_PRESET_SDCLK_FREQ_MASK	GENMASK(9, 0)

#define SDHCI_HOST_VERSION	0xFE
#define  SDHCI_VENDOR_VER_MASK	0xFF00
#define  SDHCI_VENDOR_VER_SHIFT	8
#define  SDHCI_SPEC_VER_MASK	0x00FF
#define  SDHCI_SPEC_VER_SHIFT	0
#define   SDHCI_SPEC_100	0
#define   SDHCI_SPEC_200	1
#define   SDHCI_SPEC_300	2
#define   SDHCI_SPEC_400	3
#define   SDHCI_SPEC_410	4
#define   SDHCI_SPEC_420	5

#define  SDHCI_CLOCK_MUL_SHIFT	16

#define SDHCI_MMC_BOOT						0xC4

#define SDHCI_MAX_DIV_SPEC_200	256
#define SDHCI_MAX_DIV_SPEC_300	2046

struct sdhci {
	u32 (*read32)(struct sdhci *host, int reg);
	u16 (*read16)(struct sdhci *host, int reg);
	u8 (*read8)(struct sdhci *host, int reg);
	void (*write32)(struct sdhci *host, int reg, u32 val);
	void (*write16)(struct sdhci *host, int reg, u16 val);
	void (*write8)(struct sdhci *host, int reg, u8 val);

	void __iomem *base;

	int max_clk; /* Max possible freq (Hz) */
	int clk_mul; /* Clock Muliplier value */

	unsigned int version; /* SDHCI spec. version */

	enum mci_timing timing;
	bool preset_enabled; /* Preset is enabled */

	unsigned int quirks;
#define SDHCI_QUIRK_MISSING_CAPS		BIT(27)
	unsigned int quirks2;
#define SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN	BIT(15)
	u32 caps;	/* CAPABILITY_0 */
	u32 caps1;	/* CAPABILITY_1 */
	bool read_caps;	/* Capability flags have been read */
	u32 sdma_boundary;

	struct mci_host	*mci;
};

static inline u32 sdhci_read32(struct sdhci *host, int reg)
{
	if (host->read32)
		return host->read32(host, reg);
	else
		return readl(host->base + reg);
}

static inline u32 sdhci_read16(struct sdhci *host, int reg)
{
	if (host->read16)
		return host->read16(host, reg);
	else
		return readw(host->base + reg);
}

static inline u32 sdhci_read8(struct sdhci *host, int reg)
{
	if (host->read8)
		return host->read8(host, reg);
	else
		return readb(host->base + reg);
}

static inline void sdhci_write32(struct sdhci *host, int reg, u32 val)
{
	if (host->write32)
		host->write32(host, reg, val);
	else
		writel(val, host->base + reg);
}

static inline void sdhci_write16(struct sdhci *host, int reg, u32 val)
{
	if (host->write16)
		host->write16(host, reg, val);
	else
		writew(val, host->base + reg);
}

static inline void sdhci_write8(struct sdhci *host, int reg, u32 val)
{
	if (host->write8)
		host->write8(host, reg, val);
	else
		writeb(val, host->base + reg);
}

#define SDHCI_NO_DMA DMA_ERROR_CODE
void sdhci_read_response(struct sdhci *host, struct mci_cmd *cmd);
void sdhci_set_cmd_xfer_mode(struct sdhci *host, struct mci_cmd *cmd,
			     struct mci_data *data, bool dma, u32 *command,
			     u32 *xfer);
void sdhci_setup_data_pio(struct sdhci *sdhci, struct mci_data *data);
void sdhci_setup_data_dma(struct sdhci *sdhci, struct mci_data *data, dma_addr_t *dma);
int sdhci_transfer_data(struct sdhci *sdhci, struct mci_data *data, dma_addr_t dma);
int sdhci_transfer_data_pio(struct sdhci *sdhci, struct mci_data *data);
int sdhci_transfer_data_dma(struct sdhci *sdhci, struct mci_data *data,
			    dma_addr_t dma);
int sdhci_reset(struct sdhci *sdhci, u8 mask);
u16 sdhci_calc_clk(struct sdhci *host, unsigned int clock,
		   unsigned int *actual_clock, unsigned int input_clock);
void sdhci_set_clock(struct sdhci *host, unsigned int clock, unsigned int input_clock);
void sdhci_enable_clk(struct sdhci *host, u16 clk);
int sdhci_setup_host(struct sdhci *host);
void __sdhci_read_caps(struct sdhci *host, const u16 *ver,
			const u32 *caps, const u32 *caps1);
static inline void sdhci_read_caps(struct sdhci *host)
{
	__sdhci_read_caps(host, NULL, NULL, NULL);
}
void sdhci_set_bus_width(struct sdhci *host, int width);

#define sdhci_read8_poll_timeout(sdhci, reg, val, cond, timeout_us) \
	read_poll_timeout(sdhci_read8, val, cond, timeout_us, sdhci, reg)

#define sdhci_read16_poll_timeout(sdhci, reg, val, cond, timeout_us) \
	read_poll_timeout(sdhci_read16, val, cond, timeout_us, sdhci, reg)

#define sdhci_read32_poll_timeout(sdhci, reg, val, cond, timeout_us) \
	read_poll_timeout(sdhci_read32, val, cond, timeout_us, sdhci, reg)

#endif /* __MCI_SDHCI_H */