blob: 057b6e900a0ad4a4b9f4cabfec972d03fc7498fe [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/*
2 * (C) Copyright 2003
3 * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net
4 *
5 * See file CREDITS for list of people who contributed to this
6 * project.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 */
23
24
25#include <common.h>
26#include "zx_mmc.h"
27#include "type.h"
28#include <asm/io.h>
29#include <image.h>
30#include <linux/byteorder/generic.h>
31
32
33u32 mmc_rca;
34static u32 ocr_avail = 0;
35static u32 block_addr = 0;
36
37#define MMC_BLOCK_SIZE 512
38
39static u32 emmc_cmd(u32 cmd, u32 arg,
40 void *resp, u32 flags)
41{
42 u32 *response = resp;
43 u32 i,response_words = 0;
44 u32 status,err_status = ZXMCI_STS_RE | ZXMCI_STS_RCRC | ZXMCI_STS_RTO;
45 u32 cmdreg;
46
47 /*Clear all raw interrupt status*/
48 REG32(SYS_EMMC_REGS_BASE+ZXMCI_RINTSTS) = 0xffffffff;
49
50 cmdreg = cmd & ZXMCI_CMD_INDEX_MASK;
51 cmdreg |= flags | ZXMCI_CMD_START;
52
53 cmdreg |= (0x1 << 29);
54
55 if(flags & ZXMCI_CMD_RSPLEN)
56 {
57 response_words = 4;
58 }
59 else if(flags & ZXMCI_CMD_RSPEXP)
60 {
61 response_words = 1;
62 }
63
64 REG32(SYS_EMMC_REGS_BASE+ZXMCI_CMDARG) = arg;
65 REG32(SYS_EMMC_REGS_BASE+ZXMCI_CMD) = cmdreg;
66
67/*check command done*/
68 do {
69 status = REG32(SYS_EMMC_REGS_BASE+ZXMCI_RINTSTS);
70
71 } while (!(status & ZXMCI_STS_CD));
72/*check error*/
73 if(status & err_status)
74 {
75 printf("send cmd error\n");
76 return 1;
77 }
78
79 for(i = 0;i < response_words;i++)
80 {
81 response[i] = REG32(SYS_EMMC_REGS_BASE+ZXMCI_RESP0 + i*4);
82 }
83
84 return 0;
85}
86
87s32 zx_mmc_read(u32 src, u8 * dst, u32 size)
88{
89 u32 ret, i = 0,j = 0;
90 u32 resp;
91 u32 data;
92 u32 wordcount;
93 u32 *p = (u32 *)dst;
94 u32 status;
95 u32 start_addr;
96 u32 fifo_cnt;
97
98 if (size == 0)
99 return -1;
100
101 while((REG32(SYS_EMMC_REGS_BASE+ZXMCI_STATUS) & ZXMCI_STA_DATBUSY) != 0)
102 {
103 i++;
104 mmcdelay((80));
105 if(i>200)
106 break;
107 }
108
109
110 start_addr = src;
111
112
113 data = REG32(SYS_EMMC_REGS_BASE+ZXMCI_CTRL);
114 data |=(1<<1) ;
115 REG32(SYS_EMMC_REGS_BASE+ZXMCI_CTRL) = data;
116
117 i = 0;
118 do
119 {
120 i++;
121 mmcdelay((80));
122 if(i>100)
123 {
124 printf("fifo reset failure");
125 break;
126 }
127 }while(REG32(SYS_EMMC_REGS_BASE+ZXMCI_CTRL) & 2);
128
129
130 REG32(SYS_EMMC_REGS_BASE+ZXMCI_BYTCNT) = size;
131 REG32(SYS_EMMC_REGS_BASE+ZXMCI_BLKSIZ) = MMC_DEFAULT_BLKLEN;
132
133 if (size > MMC_DEFAULT_BLKLEN)
134 {
135 ret = emmc_cmd(MMC_CMD_READ_MULTIPLE_BLOCK,start_addr, &resp,(R1 | CF_DATA));
136 if (ret)
137 {
138 return -MMC_CMD_READ_MULTIPLE_BLOCK;
139 }
140 }
141 else
142 {
143 ret = emmc_cmd(MMC_CMD_READ_SINGLE_BLOCK,start_addr, &resp,(R1 | CF_DATA));
144 if (ret)
145 {
146 return -MMC_CMD_READ_SINGLE_BLOCK;
147 }
148 }
149
150 wordcount = 0;
151 do {
152
153 status = REG32(SYS_EMMC_REGS_BASE+ZXMCI_STATUS);
154 fifo_cnt =(status >> 17) & 0x1fff;
155 for(j = 0;j < fifo_cnt;j++)
156 {
157 data = REG32(SYS_EMMC_REGS_BASE+ZXMCI_FIFO);
158 *p++ = data;
159 wordcount++;
160 }
161
162 } while(wordcount < (size/4));
163
164 return 0;
165
166}
167
168static u32 mmc_bread(u32 dev_num, u32 blknr, u32 blkcnt, void *dst)
169{
170 u32 src = 0;
171 s32 ret;
172
173 if (block_addr == 0)
174 {
175 src = blknr * MMC_BLOCK_SIZE;
176 }
177 else
178 {
179 src = blknr;
180 }
181
182 ret = zx_mmc_read(src, (u8 *) dst, blkcnt * MMC_BLOCK_SIZE);
183 if (ret < 0)
184 {
185 printf("mmc read error\n");
186 return 1;
187 }
188
189 return blkcnt;
190}
191
192
193 void mmcdelay(unsigned long us)
194 {
195 volatile int i = 0; /* approximate */
196 for(i=0;i<5000;i++)
197 {
198 ;
199 }
200 }
201
202int mmc_read( u32 src, u32 length, void *dst)
203{
204 u32 blkcnt = 0;
205 u32 start_blk = 0;
206 int ret = 0;
207
208 if(length%MMC_DEFAULT_BLKLEN)
209 blkcnt = (length/MMC_DEFAULT_BLKLEN)+1;
210 else
211 blkcnt = (length/MMC_DEFAULT_BLKLEN);
212
213 start_blk = src/MMC_DEFAULT_BLKLEN;
214 block_addr = 1;
215
216 printf("entry mmc_bread\n");
217 ret = mmc_bread(0, start_blk, blkcnt, (void *)dst);
218
219 if(ret == blkcnt )
220 return 0;
221 else
222 return -1;
223
224}
225
226uint32_t page_align(uint32_t offset)
227{
228 uint32_t page_size = 2048;
229 if( offset & (page_size - 1) )
230 {
231 offset &= (~(page_size - 1));
232 offset += page_size;
233 }
234 return offset;
235}
236
237/*******************************************************************************
238 * Function: nand_init
239 * Description: mmc init
240 * Parameters:
241 * Input:
242 *
243 * Output:
244 *
245 * Returns:
246 *
247 *
248 * Others:
249 ********************************************************************************/
250int32_t mmc_init (void)
251{
252 return 0;
253
254}
255
256