summaryrefslogtreecommitdiff
path: root/drivers/mmc/arm_pl180_mmci.h
blob: 9df4b75470f8dc7d41b3d29c122e36eedf78db28 (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
/*
 * ARM PrimeCell MultiMedia Card Interface - PL180
 *
 * Copyright (C) ST-Ericsson SA 2010
 *
 * Author: Ulf Hansson <ulf.hansson@stericsson.com>
 * Author: Martin Lundholm <martin.xa.lundholm@stericsson.com>
 * Ported to drivers/mmc/ by: Matt Waddel <matt.waddel@linaro.org>
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#ifndef __ARM_PL180_MMCI_H__
#define __ARM_PL180_MMCI_H__

/* need definition of struct mmc_config */
#include <mmc.h>

#define COMMAND_REG_DELAY	300
#define DATA_REG_DELAY		1000
#define CLK_CHANGE_DELAY	2000

#define INIT_PWR		0xBF /* Power on, full power, not open drain */
#define ARM_MCLK		(100*1000*1000)

/* SDI Power Control register bits */
#define SDI_PWR_PWRCTRL_MASK	0x00000003
#define SDI_PWR_PWRCTRL_ON	0x00000003
#define SDI_PWR_PWRCTRL_OFF	0x00000000
#define SDI_PWR_DAT2DIREN	0x00000004
#define SDI_PWR_CMDDIREN	0x00000008
#define SDI_PWR_DAT0DIREN	0x00000010
#define SDI_PWR_DAT31DIREN	0x00000020
#define SDI_PWR_OPD		0x00000040
#define SDI_PWR_FBCLKEN		0x00000080
#define SDI_PWR_DAT74DIREN	0x00000100
#define SDI_PWR_RSTEN		0x00000200

#define VOLTAGE_WINDOW_MMC	0x00FF8080
#define VOLTAGE_WINDOW_SD	0x80010000

/* SDI clock control register bits */
#define SDI_CLKCR_CLKDIV_MASK	0x000000FF
#define SDI_CLKCR_CLKEN		0x00000100
#define SDI_CLKCR_PWRSAV	0x00000200
#define SDI_CLKCR_BYPASS	0x00000400
#define SDI_CLKCR_WIDBUS_MASK	0x00001800
#define SDI_CLKCR_WIDBUS_1	0x00000000
#define SDI_CLKCR_WIDBUS_4	0x00000800
/* V2 only */
#define SDI_CLKCR_WIDBUS_8	0x00001000
#define SDI_CLKCR_NEDGE		0x00002000
#define SDI_CLKCR_HWFC_EN	0x00004000

#define SDI_CLKCR_CLKDIV_INIT_V1 0x000000C6 /* MCLK/(2*(0xC6+1)) => 505KHz */
#define SDI_CLKCR_CLKDIV_INIT_V2 0x000000FD

/* SDI command register bits */
#define SDI_CMD_CMDINDEX_MASK	0x000000FF
#define SDI_CMD_WAITRESP	0x00000040
#define SDI_CMD_LONGRESP	0x00000080
#define SDI_CMD_WAITINT		0x00000100
#define SDI_CMD_WAITPEND	0x00000200
#define SDI_CMD_CPSMEN		0x00000400
#define SDI_CMD_SDIOSUSPEND	0x00000800
#define SDI_CMD_ENDCMDCOMPL	0x00001000
#define SDI_CMD_NIEN		0x00002000
#define SDI_CMD_CE_ATACMD	0x00004000
#define SDI_CMD_CBOOTMODEEN	0x00008000

#define SDI_DTIMER_DEFAULT	0xFFFF0000

/* SDI Status register bits */
#define SDI_STA_CCRCFAIL	0x00000001
#define SDI_STA_DCRCFAIL	0x00000002
#define SDI_STA_CTIMEOUT	0x00000004
#define SDI_STA_DTIMEOUT	0x00000008
#define SDI_STA_TXUNDERR	0x00000010
#define SDI_STA_RXOVERR		0x00000020
#define SDI_STA_CMDREND		0x00000040
#define SDI_STA_CMDSENT		0x00000080
#define SDI_STA_DATAEND		0x00000100
#define SDI_STA_STBITERR	0x00000200
#define SDI_STA_DBCKEND		0x00000400
#define SDI_STA_CMDACT		0x00000800
#define SDI_STA_TXACT		0x00001000
#define SDI_STA_RXACT		0x00002000
#define SDI_STA_TXFIFOBW	0x00004000
#define SDI_STA_RXFIFOBR	0x00008000
#define SDI_STA_TXFIFOF		0x00010000
#define SDI_STA_RXFIFOF		0x00020000
#define SDI_STA_TXFIFOE		0x00040000
#define SDI_STA_RXFIFOE		0x00080000
#define SDI_STA_TXDAVL		0x00100000
#define SDI_STA_RXDAVL		0x00200000
#define SDI_STA_SDIOIT		0x00400000
#define SDI_STA_CEATAEND	0x00800000
#define SDI_STA_CARDBUSY	0x01000000
#define SDI_STA_BOOTMODE	0x02000000
#define SDI_STA_BOOTACKERR	0x04000000
#define SDI_STA_BOOTACKTIMEOUT	0x08000000
#define SDI_STA_RSTNEND		0x10000000

/* SDI Interrupt Clear register bits */
#define SDI_ICR_MASK		0x1DC007FF
#define SDI_ICR_CCRCFAILC	0x00000001
#define SDI_ICR_DCRCFAILC	0x00000002
#define SDI_ICR_CTIMEOUTC	0x00000004
#define SDI_ICR_DTIMEOUTC	0x00000008
#define SDI_ICR_TXUNDERRC	0x00000010
#define SDI_ICR_RXOVERRC	0x00000020
#define SDI_ICR_CMDRENDC	0x00000040
#define SDI_ICR_CMDSENTC	0x00000080
#define SDI_ICR_DATAENDC	0x00000100
#define SDI_ICR_STBITERRC	0x00000200
#define SDI_ICR_DBCKENDC	0x00000400
#define SDI_ICR_SDIOITC		0x00400000
#define SDI_ICR_CEATAENDC	0x00800000
#define SDI_ICR_BUSYENDC	0x01000000
#define SDI_ICR_BOOTACKERRC	0x04000000
#define SDI_ICR_BOOTACKTIMEOUTC	0x08000000
#define SDI_ICR_RSTNENDC	0x10000000

#define SDI_MASK0_MASK		0x1FFFFFFF

/* SDI Data control register bits */
#define SDI_DCTRL_DTEN		0x00000001
#define SDI_DCTRL_DTDIR_IN	0x00000002
#define SDI_DCTRL_DTMODE_STREAM	0x00000004
#define SDI_DCTRL_DMAEN		0x00000008
#define SDI_DCTRL_DBLKSIZE_MASK	0x000000F0
#define SDI_DCTRL_RWSTART	0x00000100
#define SDI_DCTRL_RWSTOP	0x00000200
#define SDI_DCTRL_RWMOD		0x00000200
#define SDI_DCTRL_SDIOEN	0x00000800
#define SDI_DCTRL_DMAREQCTL	0x00001000
#define SDI_DCTRL_DBOOTMODEEN	0x00002000
#define SDI_DCTRL_BUSYMODE	0x00004000
#define SDI_DCTRL_DDR_MODE	0x00008000
#define SDI_DCTRL_DBLOCKSIZE_V2_MASK   0x7fff0000
#define SDI_DCTRL_DBLOCKSIZE_V2_SHIFT  16

#define SDI_FIFO_BURST_SIZE	8

#define VERSION1	false
#define VERSION2	true

struct sdi_registers {
	u32 power;		/* 0x00*/
	u32 clock;		/* 0x04*/
	u32 argument;		/* 0x08*/
	u32 command;		/* 0x0c*/
	u32 respcommand;	/* 0x10*/
	u32 response0;		/* 0x14*/
	u32 response1;		/* 0x18*/
	u32 response2;		/* 0x1c*/
	u32 response3;		/* 0x20*/
	u32 datatimer;		/* 0x24*/
	u32 datalength;		/* 0x28*/
	u32 datactrl;		/* 0x2c*/
	u32 datacount;		/* 0x30*/
	u32 status;		/* 0x34*/
	u32 status_clear;	/* 0x38*/
	u32 mask0;		/* 0x3c*/
	u32 mask1;		/* 0x40*/
	u32 card_select;	/* 0x44*/
	u32 fifo_count;		/* 0x48*/
	u32 padding1[(0x80-0x4C)>>2];
	u32 fifo;		/* 0x80*/
	u32 padding2[(0xFE0-0x84)>>2];
	u32 periph_id0;		/* 0xFE0 mmc Peripheral Identifcation Register*/
	u32 periph_id1;		/* 0xFE4*/
	u32 periph_id2;		/* 0xFE8*/
	u32 periph_id3;		/* 0xFEC*/
	u32 pcell_id0;		/* 0xFF0*/
	u32 pcell_id1;		/* 0xFF4*/
	u32 pcell_id2;		/* 0xFF8*/
	u32 pcell_id3;		/* 0xFFC*/
};

struct pl180_mmc_host {
	struct sdi_registers *base;
	char name[32];
	unsigned int b_max;
	unsigned int voltages;
	unsigned int caps;
	unsigned int clock_in;
	unsigned int clock_min;
	unsigned int clock_max;
	unsigned int clkdiv_init;
	unsigned int pwr_init;
	int version2;
	struct mmc_config cfg;
#ifdef CONFIG_DM_MMC
	struct gpio_desc cd_gpio;
	bool cd_inverted;
#endif
};

int arm_pl180_mmci_init(struct pl180_mmc_host *host, struct mmc **mmc);

#endif