xref: /openbmc/u-boot/include/dwmmc.h (revision 407b5b95)
1  /* SPDX-License-Identifier: GPL-2.0+ */
2  /*
3   * (C) Copyright 2012 SAMSUNG Electronics
4   * Jaehoon Chung <jh80.chung@samsung.com>
5   */
6  
7  #ifndef __DWMMC_HW_H
8  #define __DWMMC_HW_H
9  
10  #include <asm/io.h>
11  #include <mmc.h>
12  
13  #define DWMCI_CTRL		0x000
14  #define	DWMCI_PWREN		0x004
15  #define DWMCI_CLKDIV		0x008
16  #define DWMCI_CLKSRC		0x00C
17  #define DWMCI_CLKENA		0x010
18  #define DWMCI_TMOUT		0x014
19  #define DWMCI_CTYPE		0x018
20  #define DWMCI_BLKSIZ		0x01C
21  #define DWMCI_BYTCNT		0x020
22  #define DWMCI_INTMASK		0x024
23  #define DWMCI_CMDARG		0x028
24  #define DWMCI_CMD		0x02C
25  #define DWMCI_RESP0		0x030
26  #define DWMCI_RESP1		0x034
27  #define DWMCI_RESP2		0x038
28  #define DWMCI_RESP3		0x03C
29  #define DWMCI_MINTSTS		0x040
30  #define DWMCI_RINTSTS		0x044
31  #define DWMCI_STATUS		0x048
32  #define DWMCI_FIFOTH		0x04C
33  #define DWMCI_CDETECT		0x050
34  #define DWMCI_WRTPRT		0x054
35  #define DWMCI_GPIO		0x058
36  #define DWMCI_TCMCNT		0x05C
37  #define DWMCI_TBBCNT		0x060
38  #define DWMCI_DEBNCE		0x064
39  #define DWMCI_USRID		0x068
40  #define DWMCI_VERID		0x06C
41  #define DWMCI_HCON		0x070
42  #define DWMCI_UHS_REG		0x074
43  #define DWMCI_BMOD		0x080
44  #define DWMCI_PLDMND		0x084
45  #define DWMCI_DBADDR		0x088
46  #define DWMCI_IDSTS		0x08C
47  #define DWMCI_IDINTEN		0x090
48  #define DWMCI_DSCADDR		0x094
49  #define DWMCI_BUFADDR		0x098
50  #define DWMCI_DATA		0x200
51  
52  /* Interrupt Mask register */
53  #define DWMCI_INTMSK_ALL	0xffffffff
54  #define DWMCI_INTMSK_RE		(1 << 1)
55  #define DWMCI_INTMSK_CDONE	(1 << 2)
56  #define DWMCI_INTMSK_DTO	(1 << 3)
57  #define DWMCI_INTMSK_TXDR	(1 << 4)
58  #define DWMCI_INTMSK_RXDR	(1 << 5)
59  #define DWMCI_INTMSK_RCRC	(1 << 6)
60  #define DWMCI_INTMSK_DCRC	(1 << 7)
61  #define DWMCI_INTMSK_RTO	(1 << 8)
62  #define DWMCI_INTMSK_DRTO	(1 << 9)
63  #define DWMCI_INTMSK_HTO	(1 << 10)
64  #define DWMCI_INTMSK_FRUN	(1 << 11)
65  #define DWMCI_INTMSK_HLE	(1 << 12)
66  #define DWMCI_INTMSK_SBE	(1 << 13)
67  #define DWMCI_INTMSK_ACD	(1 << 14)
68  #define DWMCI_INTMSK_EBE	(1 << 15)
69  
70  /* Raw interrupt Regsiter */
71  #define DWMCI_DATA_ERR	(DWMCI_INTMSK_EBE | DWMCI_INTMSK_SBE | DWMCI_INTMSK_HLE |\
72  			DWMCI_INTMSK_FRUN | DWMCI_INTMSK_EBE | DWMCI_INTMSK_DCRC)
73  #define DWMCI_DATA_TOUT	(DWMCI_INTMSK_HTO | DWMCI_INTMSK_DRTO)
74  /* CTRL register */
75  #define DWMCI_CTRL_RESET	(1 << 0)
76  #define DWMCI_CTRL_FIFO_RESET	(1 << 1)
77  #define DWMCI_CTRL_DMA_RESET	(1 << 2)
78  #define DWMCI_DMA_EN		(1 << 5)
79  #define DWMCI_CTRL_SEND_AS_CCSD	(1 << 10)
80  #define DWMCI_IDMAC_EN		(1 << 25)
81  #define DWMCI_RESET_ALL		(DWMCI_CTRL_RESET | DWMCI_CTRL_FIFO_RESET |\
82  				DWMCI_CTRL_DMA_RESET)
83  
84  /* CMD register */
85  #define DWMCI_CMD_RESP_EXP	(1 << 6)
86  #define DWMCI_CMD_RESP_LENGTH	(1 << 7)
87  #define DWMCI_CMD_CHECK_CRC	(1 << 8)
88  #define DWMCI_CMD_DATA_EXP	(1 << 9)
89  #define DWMCI_CMD_RW		(1 << 10)
90  #define DWMCI_CMD_SEND_STOP	(1 << 12)
91  #define DWMCI_CMD_ABORT_STOP	(1 << 14)
92  #define DWMCI_CMD_PRV_DAT_WAIT	(1 << 13)
93  #define DWMCI_CMD_UPD_CLK	(1 << 21)
94  #define DWMCI_CMD_USE_HOLD_REG	(1 << 29)
95  #define DWMCI_CMD_START		(1 << 31)
96  
97  /* CLKENA register */
98  #define DWMCI_CLKEN_ENABLE	(1 << 0)
99  #define DWMCI_CLKEN_LOW_PWR	(1 << 16)
100  
101  /* Card-type registe */
102  #define DWMCI_CTYPE_1BIT	0
103  #define DWMCI_CTYPE_4BIT	(1 << 0)
104  #define DWMCI_CTYPE_8BIT	(1 << 16)
105  
106  /* Status Register */
107  #define DWMCI_FIFO_EMPTY	(1 << 2)
108  #define DWMCI_FIFO_FULL		(1 << 3)
109  #define DWMCI_BUSY		(1 << 9)
110  #define DWMCI_FIFO_MASK		0x1fff
111  #define DWMCI_FIFO_SHIFT	17
112  
113  /* FIFOTH Register */
114  #define MSIZE(x)		((x) << 28)
115  #define RX_WMARK(x)		((x) << 16)
116  #define TX_WMARK(x)		(x)
117  #define RX_WMARK_SHIFT		16
118  #define RX_WMARK_MASK		(0xfff << RX_WMARK_SHIFT)
119  
120  #define DWMCI_IDMAC_OWN		(1 << 31)
121  #define DWMCI_IDMAC_CH		(1 << 4)
122  #define DWMCI_IDMAC_FS		(1 << 3)
123  #define DWMCI_IDMAC_LD		(1 << 2)
124  
125  /*  Bus Mode Register */
126  #define DWMCI_BMOD_IDMAC_RESET	(1 << 0)
127  #define DWMCI_BMOD_IDMAC_FB	(1 << 1)
128  #define DWMCI_BMOD_IDMAC_EN	(1 << 7)
129  
130  /* UHS register */
131  #define DWMCI_DDR_MODE	(1 << 16)
132  
133  /* Internal IDMAC interrupt defines */
134  #define DWMCI_IDINTEN_RI		BIT(1)
135  #define DWMCI_IDINTEN_TI		BIT(0)
136  
137  #define DWMCI_IDINTEN_MASK	(DWMCI_IDINTEN_TI | \
138  				 DWMCI_IDINTEN_RI)
139  
140  /* quirks */
141  #define DWMCI_QUIRK_DISABLE_SMU		(1 << 0)
142  
143  /**
144   * struct dwmci_host - Information about a designware MMC host
145   *
146   * @name:	Device name
147   * @ioaddr:	Base I/O address of controller
148   * @quirks:	Quick flags - see DWMCI_QUIRK_...
149   * @caps:	Capabilities - see MMC_MODE_...
150   * @bus_hz:	Bus speed in Hz, if @get_mmc_clk() is NULL
151   * @div:	Arbitrary clock divider value for use by controller
152   * @dev_index:	Arbitrary device index for use by controller
153   * @dev_id:	Arbitrary device ID for use by controller
154   * @buswidth:	Bus width in bits (8 or 4)
155   * @fifoth_val:	Value for FIFOTH register (or 0 to leave unset)
156   * @mmc:	Pointer to generic MMC structure for this device
157   * @priv:	Private pointer for use by controller
158   */
159  struct dwmci_host {
160  	const char *name;
161  	void *ioaddr;
162  	unsigned int quirks;
163  	unsigned int caps;
164  	unsigned int version;
165  	unsigned int clock;
166  	unsigned int bus_hz;
167  	unsigned int div;
168  	int dev_index;
169  	int dev_id;
170  	int buswidth;
171  	u32 fifoth_val;
172  	struct mmc *mmc;
173  	void *priv;
174  
175  	void (*clksel)(struct dwmci_host *host);
176  	void (*board_init)(struct dwmci_host *host);
177  
178  	/**
179  	 * Get / set a particular MMC clock frequency
180  	 *
181  	 * This is used to request the current clock frequency of the clock
182  	 * that drives the DWMMC peripheral. The caller will then use this
183  	 * information to work out the divider it needs to achieve the
184  	 * required MMC bus clock frequency. If you want to handle the
185  	 * clock external to DWMMC, use @freq to select the frequency and
186  	 * return that value too. Then DWMMC will put itself in bypass mode.
187  	 *
188  	 * @host:	DWMMC host
189  	 * @freq:	Frequency the host is trying to achieve
190  	 */
191  	unsigned int (*get_mmc_clk)(struct dwmci_host *host, uint freq);
192  #ifndef CONFIG_BLK
193  	struct mmc_config cfg;
194  #endif
195  
196  	/* use fifo mode to read and write data */
197  	bool fifo_mode;
198  };
199  
200  struct dwmci_idmac {
201  	u32 flags;
202  	u32 cnt;
203  	u32 addr;
204  	u32 next_addr;
205  } __aligned(ARCH_DMA_MINALIGN);
206  
207  static inline void dwmci_writel(struct dwmci_host *host, int reg, u32 val)
208  {
209  	writel(val, host->ioaddr + reg);
210  }
211  
212  static inline void dwmci_writew(struct dwmci_host *host, int reg, u16 val)
213  {
214  	writew(val, host->ioaddr + reg);
215  }
216  
217  static inline void dwmci_writeb(struct dwmci_host *host, int reg, u8 val)
218  {
219  	writeb(val, host->ioaddr + reg);
220  }
221  static inline u32 dwmci_readl(struct dwmci_host *host, int reg)
222  {
223  	return readl(host->ioaddr + reg);
224  }
225  
226  static inline u16 dwmci_readw(struct dwmci_host *host, int reg)
227  {
228  	return readw(host->ioaddr + reg);
229  }
230  
231  static inline u8 dwmci_readb(struct dwmci_host *host, int reg)
232  {
233  	return readb(host->ioaddr + reg);
234  }
235  
236  #ifdef CONFIG_BLK
237  /**
238   * dwmci_setup_cfg() - Set up the configuration for DWMMC
239   *
240   * This is used to set up a DWMMC device when you are using CONFIG_BLK.
241   *
242   * This should be called from your MMC driver's probe() method once you have
243   * the information required.
244   *
245   * Generally your driver will have a platform data structure which holds both
246   * the configuration (struct mmc_config) and the MMC device info (struct mmc).
247   * For example:
248   *
249   * struct rockchip_mmc_plat {
250   *	struct mmc_config cfg;
251   *	struct mmc mmc;
252   * };
253   *
254   * ...
255   *
256   * Inside U_BOOT_DRIVER():
257   *	.platdata_auto_alloc_size = sizeof(struct rockchip_mmc_plat),
258   *
259   * To access platform data:
260   *	struct rockchip_mmc_plat *plat = dev_get_platdata(dev);
261   *
262   * See rockchip_dw_mmc.c for an example.
263   *
264   * @cfg:	Configuration structure to fill in (generally &plat->mmc)
265   * @host:	DWMMC host
266   * @max_clk:	Maximum supported clock speed in HZ (e.g. 150000000)
267   * @min_clk:	Minimum supported clock speed in HZ (e.g. 400000)
268   */
269  void dwmci_setup_cfg(struct mmc_config *cfg, struct dwmci_host *host,
270  		u32 max_clk, u32 min_clk);
271  
272  /**
273   * dwmci_bind() - Set up a new MMC block device
274   *
275   * This is used to set up a DWMMC block device when you are using CONFIG_BLK.
276   * It should be called from your driver's bind() method.
277   *
278   * See rockchip_dw_mmc.c for an example.
279   *
280   * @dev:	Device to set up
281   * @mmc:	Pointer to mmc structure (normally &plat->mmc)
282   * @cfg:	Empty configuration structure (generally &plat->cfg). This is
283   *		normally all zeroes at this point. The only purpose of passing
284   *		this in is to set mmc->cfg to it.
285   * @return 0 if OK, -ve if the block device could not be created
286   */
287  int dwmci_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg);
288  
289  #else
290  /**
291   * add_dwmci() - Add a new DWMMC interface
292   *
293   * This is used when you are not using CONFIG_BLK. Convert your driver over!
294   *
295   * @host:	DWMMC host structure
296   * @max_clk:	Maximum supported clock speed in HZ (e.g. 150000000)
297   * @min_clk:	Minimum supported clock speed in HZ (e.g. 400000)
298   * @return 0 if OK, -ve on error
299   */
300  int add_dwmci(struct dwmci_host *host, u32 max_clk, u32 min_clk);
301  #endif /* !CONFIG_BLK */
302  
303  #ifdef CONFIG_DM_MMC
304  /* Export the operations to drivers */
305  int dwmci_probe(struct udevice *dev);
306  extern const struct dm_mmc_ops dm_dwmci_ops;
307  #endif
308  
309  #endif	/* __DWMMC_HW_H */
310