1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (C) 2010
3*4882a593Smuzhiyun * Rob Emanuele <rob@emanuele.us>
4*4882a593Smuzhiyun * Reinhard Meyer, EMK Elektronik <reinhard.meyer@emk-elektronik.de>
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Original Driver:
7*4882a593Smuzhiyun * Copyright (C) 2004-2006 Atmel Corporation
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
10*4882a593Smuzhiyun */
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <common.h>
13*4882a593Smuzhiyun #include <clk.h>
14*4882a593Smuzhiyun #include <dm.h>
15*4882a593Smuzhiyun #include <mmc.h>
16*4882a593Smuzhiyun #include <part.h>
17*4882a593Smuzhiyun #include <malloc.h>
18*4882a593Smuzhiyun #include <asm/io.h>
19*4882a593Smuzhiyun #include <linux/errno.h>
20*4882a593Smuzhiyun #include <asm/byteorder.h>
21*4882a593Smuzhiyun #include <asm/arch/clk.h>
22*4882a593Smuzhiyun #include <asm/arch/hardware.h>
23*4882a593Smuzhiyun #include "atmel_mci.h"
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun #ifndef CONFIG_SYS_MMC_CLK_OD
28*4882a593Smuzhiyun # define CONFIG_SYS_MMC_CLK_OD 150000
29*4882a593Smuzhiyun #endif
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun #define MMC_DEFAULT_BLKLEN 512
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun #if defined(CONFIG_ATMEL_MCI_PORTB)
34*4882a593Smuzhiyun # define MCI_BUS 1
35*4882a593Smuzhiyun #else
36*4882a593Smuzhiyun # define MCI_BUS 0
37*4882a593Smuzhiyun #endif
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun #ifdef CONFIG_DM_MMC
40*4882a593Smuzhiyun struct atmel_mci_plat {
41*4882a593Smuzhiyun struct mmc mmc;
42*4882a593Smuzhiyun struct mmc_config cfg;
43*4882a593Smuzhiyun struct atmel_mci *mci;
44*4882a593Smuzhiyun };
45*4882a593Smuzhiyun #endif
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun struct atmel_mci_priv {
48*4882a593Smuzhiyun #ifndef CONFIG_DM_MMC
49*4882a593Smuzhiyun struct mmc_config cfg;
50*4882a593Smuzhiyun struct atmel_mci *mci;
51*4882a593Smuzhiyun #endif
52*4882a593Smuzhiyun unsigned int initialized:1;
53*4882a593Smuzhiyun unsigned int curr_clk;
54*4882a593Smuzhiyun #ifdef CONFIG_DM_MMC
55*4882a593Smuzhiyun ulong bus_clk_rate;
56*4882a593Smuzhiyun #endif
57*4882a593Smuzhiyun };
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun /* Read Atmel MCI IP version */
atmel_mci_get_version(struct atmel_mci * mci)60*4882a593Smuzhiyun static unsigned int atmel_mci_get_version(struct atmel_mci *mci)
61*4882a593Smuzhiyun {
62*4882a593Smuzhiyun return readl(&mci->version) & 0x00000fff;
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun /*
66*4882a593Smuzhiyun * Print command and status:
67*4882a593Smuzhiyun *
68*4882a593Smuzhiyun * - always when DEBUG is defined
69*4882a593Smuzhiyun * - on command errors
70*4882a593Smuzhiyun */
dump_cmd(u32 cmdr,u32 arg,u32 status,const char * msg)71*4882a593Smuzhiyun static void dump_cmd(u32 cmdr, u32 arg, u32 status, const char* msg)
72*4882a593Smuzhiyun {
73*4882a593Smuzhiyun debug("gen_atmel_mci: CMDR %08x (%2u) ARGR %08x (SR: %08x) %s\n",
74*4882a593Smuzhiyun cmdr, cmdr & 0x3F, arg, status, msg);
75*4882a593Smuzhiyun }
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun /* Setup for MCI Clock and Block Size */
78*4882a593Smuzhiyun #ifdef CONFIG_DM_MMC
mci_set_mode(struct udevice * dev,u32 hz,u32 blklen)79*4882a593Smuzhiyun static void mci_set_mode(struct udevice *dev, u32 hz, u32 blklen)
80*4882a593Smuzhiyun {
81*4882a593Smuzhiyun struct atmel_mci_plat *plat = dev_get_platdata(dev);
82*4882a593Smuzhiyun struct atmel_mci_priv *priv = dev_get_priv(dev);
83*4882a593Smuzhiyun struct mmc *mmc = &plat->mmc;
84*4882a593Smuzhiyun u32 bus_hz = priv->bus_clk_rate;
85*4882a593Smuzhiyun atmel_mci_t *mci = plat->mci;
86*4882a593Smuzhiyun #else
87*4882a593Smuzhiyun static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun struct atmel_mci_priv *priv = mmc->priv;
90*4882a593Smuzhiyun u32 bus_hz = get_mci_clk_rate();
91*4882a593Smuzhiyun atmel_mci_t *mci = priv->mci;
92*4882a593Smuzhiyun #endif
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun u32 clkdiv = 255;
95*4882a593Smuzhiyun unsigned int version = atmel_mci_get_version(mci);
96*4882a593Smuzhiyun u32 clkodd = 0;
97*4882a593Smuzhiyun u32 mr;
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun debug("mci: bus_hz is %u, setting clock %u Hz, block size %u\n",
100*4882a593Smuzhiyun bus_hz, hz, blklen);
101*4882a593Smuzhiyun if (hz > 0) {
102*4882a593Smuzhiyun if (version >= 0x500) {
103*4882a593Smuzhiyun clkdiv = DIV_ROUND_UP(bus_hz, hz) - 2;
104*4882a593Smuzhiyun if (clkdiv > 511)
105*4882a593Smuzhiyun clkdiv = 511;
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun clkodd = clkdiv & 1;
108*4882a593Smuzhiyun clkdiv >>= 1;
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun debug("mci: setting clock %u Hz, block size %u\n",
111*4882a593Smuzhiyun bus_hz / (clkdiv * 2 + clkodd + 2), blklen);
112*4882a593Smuzhiyun } else {
113*4882a593Smuzhiyun /* find clkdiv yielding a rate <= than requested */
114*4882a593Smuzhiyun for (clkdiv = 0; clkdiv < 255; clkdiv++) {
115*4882a593Smuzhiyun if ((bus_hz / (clkdiv + 1) / 2) <= hz)
116*4882a593Smuzhiyun break;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun debug("mci: setting clock %u Hz, block size %u\n",
119*4882a593Smuzhiyun (bus_hz / (clkdiv + 1)) / 2, blklen);
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun if (version >= 0x500)
124*4882a593Smuzhiyun priv->curr_clk = bus_hz / (clkdiv * 2 + clkodd + 2);
125*4882a593Smuzhiyun else
126*4882a593Smuzhiyun priv->curr_clk = (bus_hz / (clkdiv + 1)) / 2;
127*4882a593Smuzhiyun blklen &= 0xfffc;
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun mr = MMCI_BF(CLKDIV, clkdiv);
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun /* MCI IP version >= 0x200 has R/WPROOF */
132*4882a593Smuzhiyun if (version >= 0x200)
133*4882a593Smuzhiyun mr |= MMCI_BIT(RDPROOF) | MMCI_BIT(WRPROOF);
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun /*
136*4882a593Smuzhiyun * MCI IP version >= 0x500 use bit 16 as clkodd.
137*4882a593Smuzhiyun * MCI IP version < 0x500 use upper 16 bits for blklen.
138*4882a593Smuzhiyun */
139*4882a593Smuzhiyun if (version >= 0x500)
140*4882a593Smuzhiyun mr |= MMCI_BF(CLKODD, clkodd);
141*4882a593Smuzhiyun else
142*4882a593Smuzhiyun mr |= MMCI_BF(BLKLEN, blklen);
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun writel(mr, &mci->mr);
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun /* MCI IP version >= 0x200 has blkr */
147*4882a593Smuzhiyun if (version >= 0x200)
148*4882a593Smuzhiyun writel(MMCI_BF(BLKLEN, blklen), &mci->blkr);
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun if (mmc->card_caps & mmc->cfg->host_caps & MMC_MODE_HS)
151*4882a593Smuzhiyun writel(MMCI_BIT(HSMODE), &mci->cfg);
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun priv->initialized = 1;
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun /* Return the CMDR with flags for a given command and data packet */
157*4882a593Smuzhiyun static u32 mci_encode_cmd(
158*4882a593Smuzhiyun struct mmc_cmd *cmd, struct mmc_data *data, u32* error_flags)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun u32 cmdr = 0;
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun /* Default Flags for Errors */
163*4882a593Smuzhiyun *error_flags |= (MMCI_BIT(DTOE) | MMCI_BIT(RDIRE) | MMCI_BIT(RENDE) |
164*4882a593Smuzhiyun MMCI_BIT(RINDE) | MMCI_BIT(RTOE));
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun /* Default Flags for the Command */
167*4882a593Smuzhiyun cmdr |= MMCI_BIT(MAXLAT);
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun if (data) {
170*4882a593Smuzhiyun cmdr |= MMCI_BF(TRCMD, 1);
171*4882a593Smuzhiyun if (data->blocks > 1)
172*4882a593Smuzhiyun cmdr |= MMCI_BF(TRTYP, 1);
173*4882a593Smuzhiyun if (data->flags & MMC_DATA_READ)
174*4882a593Smuzhiyun cmdr |= MMCI_BIT(TRDIR);
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun if (cmd->resp_type & MMC_RSP_CRC)
178*4882a593Smuzhiyun *error_flags |= MMCI_BIT(RCRCE);
179*4882a593Smuzhiyun if (cmd->resp_type & MMC_RSP_136)
180*4882a593Smuzhiyun cmdr |= MMCI_BF(RSPTYP, 2);
181*4882a593Smuzhiyun else if (cmd->resp_type & MMC_RSP_BUSY)
182*4882a593Smuzhiyun cmdr |= MMCI_BF(RSPTYP, 3);
183*4882a593Smuzhiyun else if (cmd->resp_type & MMC_RSP_PRESENT)
184*4882a593Smuzhiyun cmdr |= MMCI_BF(RSPTYP, 1);
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun return cmdr | MMCI_BF(CMDNB, cmd->cmdidx);
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun /* Entered into function pointer in mci_send_cmd */
190*4882a593Smuzhiyun static u32 mci_data_read(atmel_mci_t *mci, u32* data, u32 error_flags)
191*4882a593Smuzhiyun {
192*4882a593Smuzhiyun u32 status;
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun do {
195*4882a593Smuzhiyun status = readl(&mci->sr);
196*4882a593Smuzhiyun if (status & (error_flags | MMCI_BIT(OVRE)))
197*4882a593Smuzhiyun goto io_fail;
198*4882a593Smuzhiyun } while (!(status & MMCI_BIT(RXRDY)));
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun if (status & MMCI_BIT(RXRDY)) {
201*4882a593Smuzhiyun *data = readl(&mci->rdr);
202*4882a593Smuzhiyun status = 0;
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun io_fail:
205*4882a593Smuzhiyun return status;
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun /* Entered into function pointer in mci_send_cmd */
209*4882a593Smuzhiyun static u32 mci_data_write(atmel_mci_t *mci, u32* data, u32 error_flags)
210*4882a593Smuzhiyun {
211*4882a593Smuzhiyun u32 status;
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun do {
214*4882a593Smuzhiyun status = readl(&mci->sr);
215*4882a593Smuzhiyun if (status & (error_flags | MMCI_BIT(UNRE)))
216*4882a593Smuzhiyun goto io_fail;
217*4882a593Smuzhiyun } while (!(status & MMCI_BIT(TXRDY)));
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun if (status & MMCI_BIT(TXRDY)) {
220*4882a593Smuzhiyun writel(*data, &mci->tdr);
221*4882a593Smuzhiyun status = 0;
222*4882a593Smuzhiyun }
223*4882a593Smuzhiyun io_fail:
224*4882a593Smuzhiyun return status;
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun /*
228*4882a593Smuzhiyun * Entered into mmc structure during driver init
229*4882a593Smuzhiyun *
230*4882a593Smuzhiyun * Sends a command out on the bus and deals with the block data.
231*4882a593Smuzhiyun * Takes the mmc pointer, a command pointer, and an optional data pointer.
232*4882a593Smuzhiyun */
233*4882a593Smuzhiyun #ifdef CONFIG_DM_MMC
234*4882a593Smuzhiyun static int atmel_mci_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
235*4882a593Smuzhiyun struct mmc_data *data)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun struct atmel_mci_plat *plat = dev_get_platdata(dev);
238*4882a593Smuzhiyun struct atmel_mci_priv *priv = dev_get_priv(dev);
239*4882a593Smuzhiyun struct mmc *mmc = mmc_get_mmc_dev(dev);
240*4882a593Smuzhiyun atmel_mci_t *mci = plat->mci;
241*4882a593Smuzhiyun #else
242*4882a593Smuzhiyun static int
243*4882a593Smuzhiyun mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
244*4882a593Smuzhiyun {
245*4882a593Smuzhiyun struct atmel_mci_priv *priv = mmc->priv;
246*4882a593Smuzhiyun atmel_mci_t *mci = priv->mci;
247*4882a593Smuzhiyun #endif
248*4882a593Smuzhiyun u32 cmdr;
249*4882a593Smuzhiyun u32 error_flags = 0;
250*4882a593Smuzhiyun u32 status;
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun if (!priv->initialized) {
253*4882a593Smuzhiyun puts ("MCI not initialized!\n");
254*4882a593Smuzhiyun return -ECOMM;
255*4882a593Smuzhiyun }
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun /* Figure out the transfer arguments */
258*4882a593Smuzhiyun cmdr = mci_encode_cmd(cmd, data, &error_flags);
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun /* For multi blocks read/write, set the block register */
261*4882a593Smuzhiyun if ((cmd->cmdidx == MMC_CMD_READ_MULTIPLE_BLOCK)
262*4882a593Smuzhiyun || (cmd->cmdidx == MMC_CMD_WRITE_MULTIPLE_BLOCK))
263*4882a593Smuzhiyun writel(data->blocks | MMCI_BF(BLKLEN, mmc->read_bl_len),
264*4882a593Smuzhiyun &mci->blkr);
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun /* Send the command */
267*4882a593Smuzhiyun writel(cmd->cmdarg, &mci->argr);
268*4882a593Smuzhiyun writel(cmdr, &mci->cmdr);
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun #ifdef DEBUG
271*4882a593Smuzhiyun dump_cmd(cmdr, cmd->cmdarg, 0, "DEBUG");
272*4882a593Smuzhiyun #endif
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun /* Wait for the command to complete */
275*4882a593Smuzhiyun while (!((status = readl(&mci->sr)) & MMCI_BIT(CMDRDY)));
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun if ((status & error_flags) & MMCI_BIT(RTOE)) {
278*4882a593Smuzhiyun dump_cmd(cmdr, cmd->cmdarg, status, "Command Time Out");
279*4882a593Smuzhiyun return -ETIMEDOUT;
280*4882a593Smuzhiyun } else if (status & error_flags) {
281*4882a593Smuzhiyun dump_cmd(cmdr, cmd->cmdarg, status, "Command Failed");
282*4882a593Smuzhiyun return -ECOMM;
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun /* Copy the response to the response buffer */
286*4882a593Smuzhiyun if (cmd->resp_type & MMC_RSP_136) {
287*4882a593Smuzhiyun cmd->response[0] = readl(&mci->rspr);
288*4882a593Smuzhiyun cmd->response[1] = readl(&mci->rspr1);
289*4882a593Smuzhiyun cmd->response[2] = readl(&mci->rspr2);
290*4882a593Smuzhiyun cmd->response[3] = readl(&mci->rspr3);
291*4882a593Smuzhiyun } else
292*4882a593Smuzhiyun cmd->response[0] = readl(&mci->rspr);
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun /* transfer all of the blocks */
295*4882a593Smuzhiyun if (data) {
296*4882a593Smuzhiyun u32 word_count, block_count;
297*4882a593Smuzhiyun u32* ioptr;
298*4882a593Smuzhiyun u32 sys_blocksize, dummy, i;
299*4882a593Smuzhiyun u32 (*mci_data_op)
300*4882a593Smuzhiyun (atmel_mci_t *mci, u32* data, u32 error_flags);
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun if (data->flags & MMC_DATA_READ) {
303*4882a593Smuzhiyun mci_data_op = mci_data_read;
304*4882a593Smuzhiyun sys_blocksize = mmc->read_bl_len;
305*4882a593Smuzhiyun ioptr = (u32*)data->dest;
306*4882a593Smuzhiyun } else {
307*4882a593Smuzhiyun mci_data_op = mci_data_write;
308*4882a593Smuzhiyun sys_blocksize = mmc->write_bl_len;
309*4882a593Smuzhiyun ioptr = (u32*)data->src;
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun status = 0;
313*4882a593Smuzhiyun for (block_count = 0;
314*4882a593Smuzhiyun block_count < data->blocks && !status;
315*4882a593Smuzhiyun block_count++) {
316*4882a593Smuzhiyun word_count = 0;
317*4882a593Smuzhiyun do {
318*4882a593Smuzhiyun status = mci_data_op(mci, ioptr, error_flags);
319*4882a593Smuzhiyun word_count++;
320*4882a593Smuzhiyun ioptr++;
321*4882a593Smuzhiyun } while (!status && word_count < (data->blocksize/4));
322*4882a593Smuzhiyun #ifdef DEBUG
323*4882a593Smuzhiyun if (data->flags & MMC_DATA_READ)
324*4882a593Smuzhiyun {
325*4882a593Smuzhiyun u32 cnt = word_count * 4;
326*4882a593Smuzhiyun printf("Read Data:\n");
327*4882a593Smuzhiyun print_buffer(0, data->dest + cnt * block_count,
328*4882a593Smuzhiyun 1, cnt, 0);
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun #endif
331*4882a593Smuzhiyun #ifdef DEBUG
332*4882a593Smuzhiyun if (!status && word_count < (sys_blocksize / 4))
333*4882a593Smuzhiyun printf("filling rest of block...\n");
334*4882a593Smuzhiyun #endif
335*4882a593Smuzhiyun /* fill the rest of a full block */
336*4882a593Smuzhiyun while (!status && word_count < (sys_blocksize / 4)) {
337*4882a593Smuzhiyun status = mci_data_op(mci, &dummy,
338*4882a593Smuzhiyun error_flags);
339*4882a593Smuzhiyun word_count++;
340*4882a593Smuzhiyun }
341*4882a593Smuzhiyun if (status) {
342*4882a593Smuzhiyun dump_cmd(cmdr, cmd->cmdarg, status,
343*4882a593Smuzhiyun "Data Transfer Failed");
344*4882a593Smuzhiyun return -ECOMM;
345*4882a593Smuzhiyun }
346*4882a593Smuzhiyun }
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun /* Wait for Transfer End */
349*4882a593Smuzhiyun i = 0;
350*4882a593Smuzhiyun do {
351*4882a593Smuzhiyun status = readl(&mci->sr);
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun if (status & error_flags) {
354*4882a593Smuzhiyun dump_cmd(cmdr, cmd->cmdarg, status,
355*4882a593Smuzhiyun "DTIP Wait Failed");
356*4882a593Smuzhiyun return -ECOMM;
357*4882a593Smuzhiyun }
358*4882a593Smuzhiyun i++;
359*4882a593Smuzhiyun } while ((status & MMCI_BIT(DTIP)) && i < 10000);
360*4882a593Smuzhiyun if (status & MMCI_BIT(DTIP)) {
361*4882a593Smuzhiyun dump_cmd(cmdr, cmd->cmdarg, status,
362*4882a593Smuzhiyun "XFER DTIP never unset, ignoring");
363*4882a593Smuzhiyun }
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun /*
367*4882a593Smuzhiyun * After the switch command, wait for 8 clocks before the next
368*4882a593Smuzhiyun * command
369*4882a593Smuzhiyun */
370*4882a593Smuzhiyun if (cmd->cmdidx == MMC_CMD_SWITCH)
371*4882a593Smuzhiyun udelay(8*1000000 / priv->curr_clk); /* 8 clk in us */
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun return 0;
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun
376*4882a593Smuzhiyun #ifdef CONFIG_DM_MMC
377*4882a593Smuzhiyun static int atmel_mci_set_ios(struct udevice *dev)
378*4882a593Smuzhiyun {
379*4882a593Smuzhiyun struct atmel_mci_plat *plat = dev_get_platdata(dev);
380*4882a593Smuzhiyun struct mmc *mmc = mmc_get_mmc_dev(dev);
381*4882a593Smuzhiyun atmel_mci_t *mci = plat->mci;
382*4882a593Smuzhiyun #else
383*4882a593Smuzhiyun /* Entered into mmc structure during driver init */
384*4882a593Smuzhiyun static int mci_set_ios(struct mmc *mmc)
385*4882a593Smuzhiyun {
386*4882a593Smuzhiyun struct atmel_mci_priv *priv = mmc->priv;
387*4882a593Smuzhiyun atmel_mci_t *mci = priv->mci;
388*4882a593Smuzhiyun #endif
389*4882a593Smuzhiyun int bus_width = mmc->bus_width;
390*4882a593Smuzhiyun unsigned int version = atmel_mci_get_version(mci);
391*4882a593Smuzhiyun int busw;
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun /* Set the clock speed */
394*4882a593Smuzhiyun #ifdef CONFIG_DM_MMC
395*4882a593Smuzhiyun mci_set_mode(dev, mmc->clock, MMC_DEFAULT_BLKLEN);
396*4882a593Smuzhiyun #else
397*4882a593Smuzhiyun mci_set_mode(mmc, mmc->clock, MMC_DEFAULT_BLKLEN);
398*4882a593Smuzhiyun #endif
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun /*
401*4882a593Smuzhiyun * set the bus width and select slot for this interface
402*4882a593Smuzhiyun * there is no capability for multiple slots on the same interface yet
403*4882a593Smuzhiyun */
404*4882a593Smuzhiyun if ((version & 0xf00) >= 0x300) {
405*4882a593Smuzhiyun switch (bus_width) {
406*4882a593Smuzhiyun case 8:
407*4882a593Smuzhiyun busw = 3;
408*4882a593Smuzhiyun break;
409*4882a593Smuzhiyun case 4:
410*4882a593Smuzhiyun busw = 2;
411*4882a593Smuzhiyun break;
412*4882a593Smuzhiyun default:
413*4882a593Smuzhiyun busw = 0;
414*4882a593Smuzhiyun break;
415*4882a593Smuzhiyun }
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun writel(busw << 6 | MMCI_BF(SCDSEL, MCI_BUS), &mci->sdcr);
418*4882a593Smuzhiyun } else {
419*4882a593Smuzhiyun busw = (bus_width == 4) ? 1 : 0;
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun writel(busw << 7 | MMCI_BF(SCDSEL, MCI_BUS), &mci->sdcr);
422*4882a593Smuzhiyun }
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun return 0;
425*4882a593Smuzhiyun }
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun #ifdef CONFIG_DM_MMC
428*4882a593Smuzhiyun static int atmel_mci_hw_init(struct udevice *dev)
429*4882a593Smuzhiyun {
430*4882a593Smuzhiyun struct atmel_mci_plat *plat = dev_get_platdata(dev);
431*4882a593Smuzhiyun atmel_mci_t *mci = plat->mci;
432*4882a593Smuzhiyun #else
433*4882a593Smuzhiyun /* Entered into mmc structure during driver init */
434*4882a593Smuzhiyun static int mci_init(struct mmc *mmc)
435*4882a593Smuzhiyun {
436*4882a593Smuzhiyun struct atmel_mci_priv *priv = mmc->priv;
437*4882a593Smuzhiyun atmel_mci_t *mci = priv->mci;
438*4882a593Smuzhiyun #endif
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun /* Initialize controller */
441*4882a593Smuzhiyun writel(MMCI_BIT(SWRST), &mci->cr); /* soft reset */
442*4882a593Smuzhiyun writel(MMCI_BIT(PWSDIS), &mci->cr); /* disable power save */
443*4882a593Smuzhiyun writel(MMCI_BIT(MCIEN), &mci->cr); /* enable mci */
444*4882a593Smuzhiyun writel(MMCI_BF(SCDSEL, MCI_BUS), &mci->sdcr); /* select port */
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun /* This delay can be optimized, but stick with max value */
447*4882a593Smuzhiyun writel(0x7f, &mci->dtor);
448*4882a593Smuzhiyun /* Disable Interrupts */
449*4882a593Smuzhiyun writel(~0UL, &mci->idr);
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun /* Set default clocks and blocklen */
452*4882a593Smuzhiyun #ifdef CONFIG_DM_MMC
453*4882a593Smuzhiyun mci_set_mode(dev, CONFIG_SYS_MMC_CLK_OD, MMC_DEFAULT_BLKLEN);
454*4882a593Smuzhiyun #else
455*4882a593Smuzhiyun mci_set_mode(mmc, CONFIG_SYS_MMC_CLK_OD, MMC_DEFAULT_BLKLEN);
456*4882a593Smuzhiyun #endif
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun return 0;
459*4882a593Smuzhiyun }
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun #ifndef CONFIG_DM_MMC
462*4882a593Smuzhiyun static const struct mmc_ops atmel_mci_ops = {
463*4882a593Smuzhiyun .send_cmd = mci_send_cmd,
464*4882a593Smuzhiyun .set_ios = mci_set_ios,
465*4882a593Smuzhiyun .init = mci_init,
466*4882a593Smuzhiyun };
467*4882a593Smuzhiyun
468*4882a593Smuzhiyun /*
469*4882a593Smuzhiyun * This is the only exported function
470*4882a593Smuzhiyun *
471*4882a593Smuzhiyun * Call it with the MCI register base address
472*4882a593Smuzhiyun */
473*4882a593Smuzhiyun int atmel_mci_init(void *regs)
474*4882a593Smuzhiyun {
475*4882a593Smuzhiyun struct mmc *mmc;
476*4882a593Smuzhiyun struct mmc_config *cfg;
477*4882a593Smuzhiyun struct atmel_mci_priv *priv;
478*4882a593Smuzhiyun unsigned int version;
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun priv = calloc(1, sizeof(*priv));
481*4882a593Smuzhiyun if (!priv)
482*4882a593Smuzhiyun return -ENOMEM;
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun cfg = &priv->cfg;
485*4882a593Smuzhiyun
486*4882a593Smuzhiyun cfg->name = "mci";
487*4882a593Smuzhiyun cfg->ops = &atmel_mci_ops;
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun priv->mci = (struct atmel_mci *)regs;
490*4882a593Smuzhiyun priv->initialized = 0;
491*4882a593Smuzhiyun
492*4882a593Smuzhiyun /* need to be able to pass these in on a board by board basis */
493*4882a593Smuzhiyun cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
494*4882a593Smuzhiyun version = atmel_mci_get_version(priv->mci);
495*4882a593Smuzhiyun if ((version & 0xf00) >= 0x300) {
496*4882a593Smuzhiyun cfg->host_caps = MMC_MODE_8BIT;
497*4882a593Smuzhiyun cfg->host_caps |= MMC_MODE_HS | MMC_MODE_HS_52MHz;
498*4882a593Smuzhiyun }
499*4882a593Smuzhiyun
500*4882a593Smuzhiyun cfg->host_caps |= MMC_MODE_4BIT;
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun /*
503*4882a593Smuzhiyun * min and max frequencies determined by
504*4882a593Smuzhiyun * max and min of clock divider
505*4882a593Smuzhiyun */
506*4882a593Smuzhiyun cfg->f_min = get_mci_clk_rate() / (2*256);
507*4882a593Smuzhiyun cfg->f_max = get_mci_clk_rate() / (2*1);
508*4882a593Smuzhiyun
509*4882a593Smuzhiyun cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun mmc = mmc_create(cfg, priv);
512*4882a593Smuzhiyun
513*4882a593Smuzhiyun if (mmc == NULL) {
514*4882a593Smuzhiyun free(priv);
515*4882a593Smuzhiyun return -ENODEV;
516*4882a593Smuzhiyun }
517*4882a593Smuzhiyun /* NOTE: possibly leaking the priv structure */
518*4882a593Smuzhiyun
519*4882a593Smuzhiyun return 0;
520*4882a593Smuzhiyun }
521*4882a593Smuzhiyun #endif
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun #ifdef CONFIG_DM_MMC
524*4882a593Smuzhiyun static const struct dm_mmc_ops atmel_mci_mmc_ops = {
525*4882a593Smuzhiyun .send_cmd = atmel_mci_send_cmd,
526*4882a593Smuzhiyun .set_ios = atmel_mci_set_ios,
527*4882a593Smuzhiyun };
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun static void atmel_mci_setup_cfg(struct udevice *dev)
530*4882a593Smuzhiyun {
531*4882a593Smuzhiyun struct atmel_mci_plat *plat = dev_get_platdata(dev);
532*4882a593Smuzhiyun struct atmel_mci_priv *priv = dev_get_priv(dev);
533*4882a593Smuzhiyun struct mmc_config *cfg;
534*4882a593Smuzhiyun u32 version;
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun cfg = &plat->cfg;
537*4882a593Smuzhiyun cfg->name = "Atmel mci";
538*4882a593Smuzhiyun cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun /*
541*4882a593Smuzhiyun * If the version is above 3.0, the capabilities of the 8-bit
542*4882a593Smuzhiyun * bus width and high speed are supported.
543*4882a593Smuzhiyun */
544*4882a593Smuzhiyun version = atmel_mci_get_version(plat->mci);
545*4882a593Smuzhiyun if ((version & 0xf00) >= 0x300) {
546*4882a593Smuzhiyun cfg->host_caps = MMC_MODE_8BIT |
547*4882a593Smuzhiyun MMC_MODE_HS | MMC_MODE_HS_52MHz;
548*4882a593Smuzhiyun }
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun cfg->host_caps |= MMC_MODE_4BIT;
551*4882a593Smuzhiyun cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
552*4882a593Smuzhiyun cfg->f_min = priv->bus_clk_rate / (2 * 256);
553*4882a593Smuzhiyun cfg->f_max = priv->bus_clk_rate / 2;
554*4882a593Smuzhiyun }
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun static int atmel_mci_enable_clk(struct udevice *dev)
557*4882a593Smuzhiyun {
558*4882a593Smuzhiyun struct atmel_mci_priv *priv = dev_get_priv(dev);
559*4882a593Smuzhiyun struct clk clk;
560*4882a593Smuzhiyun ulong clk_rate;
561*4882a593Smuzhiyun int ret = 0;
562*4882a593Smuzhiyun
563*4882a593Smuzhiyun ret = clk_get_by_index(dev, 0, &clk);
564*4882a593Smuzhiyun if (ret) {
565*4882a593Smuzhiyun ret = -EINVAL;
566*4882a593Smuzhiyun goto failed;
567*4882a593Smuzhiyun }
568*4882a593Smuzhiyun
569*4882a593Smuzhiyun ret = clk_enable(&clk);
570*4882a593Smuzhiyun if (ret)
571*4882a593Smuzhiyun goto failed;
572*4882a593Smuzhiyun
573*4882a593Smuzhiyun clk_rate = clk_get_rate(&clk);
574*4882a593Smuzhiyun if (!clk_rate) {
575*4882a593Smuzhiyun ret = -EINVAL;
576*4882a593Smuzhiyun goto failed;
577*4882a593Smuzhiyun }
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun priv->bus_clk_rate = clk_rate;
580*4882a593Smuzhiyun
581*4882a593Smuzhiyun failed:
582*4882a593Smuzhiyun clk_free(&clk);
583*4882a593Smuzhiyun
584*4882a593Smuzhiyun return ret;
585*4882a593Smuzhiyun }
586*4882a593Smuzhiyun
587*4882a593Smuzhiyun static int atmel_mci_probe(struct udevice *dev)
588*4882a593Smuzhiyun {
589*4882a593Smuzhiyun struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
590*4882a593Smuzhiyun struct atmel_mci_plat *plat = dev_get_platdata(dev);
591*4882a593Smuzhiyun struct mmc *mmc;
592*4882a593Smuzhiyun int ret;
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun ret = atmel_mci_enable_clk(dev);
595*4882a593Smuzhiyun if (ret)
596*4882a593Smuzhiyun return ret;
597*4882a593Smuzhiyun
598*4882a593Smuzhiyun plat->mci = (struct atmel_mci *)devfdt_get_addr_ptr(dev);
599*4882a593Smuzhiyun
600*4882a593Smuzhiyun atmel_mci_setup_cfg(dev);
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun mmc = &plat->mmc;
603*4882a593Smuzhiyun mmc->cfg = &plat->cfg;
604*4882a593Smuzhiyun mmc->dev = dev;
605*4882a593Smuzhiyun upriv->mmc = mmc;
606*4882a593Smuzhiyun
607*4882a593Smuzhiyun atmel_mci_hw_init(dev);
608*4882a593Smuzhiyun
609*4882a593Smuzhiyun return 0;
610*4882a593Smuzhiyun }
611*4882a593Smuzhiyun
612*4882a593Smuzhiyun static int atmel_mci_bind(struct udevice *dev)
613*4882a593Smuzhiyun {
614*4882a593Smuzhiyun struct atmel_mci_plat *plat = dev_get_platdata(dev);
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun return mmc_bind(dev, &plat->mmc, &plat->cfg);
617*4882a593Smuzhiyun }
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun static const struct udevice_id atmel_mci_ids[] = {
620*4882a593Smuzhiyun { .compatible = "atmel,hsmci" },
621*4882a593Smuzhiyun { }
622*4882a593Smuzhiyun };
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun U_BOOT_DRIVER(atmel_mci) = {
625*4882a593Smuzhiyun .name = "atmel-mci",
626*4882a593Smuzhiyun .id = UCLASS_MMC,
627*4882a593Smuzhiyun .of_match = atmel_mci_ids,
628*4882a593Smuzhiyun .bind = atmel_mci_bind,
629*4882a593Smuzhiyun .probe = atmel_mci_probe,
630*4882a593Smuzhiyun .platdata_auto_alloc_size = sizeof(struct atmel_mci_plat),
631*4882a593Smuzhiyun .priv_auto_alloc_size = sizeof(struct atmel_mci_priv),
632*4882a593Smuzhiyun .ops = &atmel_mci_mmc_ops,
633*4882a593Smuzhiyun };
634*4882a593Smuzhiyun #endif
635