blob: 1c0922f2405a5b94ee8eab69a250bbdc2c4db4ca [file] [log] [blame]
Gary Jennejohn6bd24472007-01-24 12:16:56 +01001/*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License as
4 * published by the Free Software Foundation; either version 2 of
5 * the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
15 * MA 02111-1307 USA
16 */
17
18#include <config.h>
19#include <common.h>
20#include <mmc.h>
21#include <asm/errno.h>
22#include <asm/arch/hardware.h>
23#include <part.h>
24#include <fat.h>
25#include "mmc_hw.h"
26#include "spi.h"
27
28#ifdef CONFIG_MMC
29
30#undef MMC_DEBUG
31
32static block_dev_desc_t mmc_dev;
33
34/* these are filled out by a call to mmc_hw_get_parameters */
35static int hw_size; /* in kbytes */
36static int hw_nr_sects;
37static int hw_sect_size; /* in bytes */
38
39block_dev_desc_t * mmc_get_dev(int dev)
40{
41 return (block_dev_desc_t *)(&mmc_dev);
42}
43
Wolfgang Denkf8db84f2007-01-30 00:50:40 +010044unsigned long mmc_block_read(int dev,
45 unsigned long start,
Gary Jennejohn6bd24472007-01-24 12:16:56 +010046 lbaint_t blkcnt,
47 unsigned long *buffer)
48{
49 unsigned long rc = 0;
50 unsigned char *p = (unsigned char *)buffer;
51 unsigned long i;
52 unsigned long addr = start;
53
54#ifdef MMC_DEBUG
Wolfgang Denkf8db84f2007-01-30 00:50:40 +010055 printf("mmc_block_read: start=%lu, blkcnt=%lu\n", start,
Gary Jennejohn6bd24472007-01-24 12:16:56 +010056 (unsigned long)blkcnt);
57#endif
58
59 for(i = 0; i < (unsigned long)blkcnt; i++) {
60#ifdef MMC_DEBUG
61 printf("mmc_read_sector: addr=%lu, buffer=%p\n", addr, p);
62#endif
63 (void)mmc_read_sector(addr, p);
64 rc++;
65 addr++;
66 p += hw_sect_size;
Wolfgang Denkf8db84f2007-01-30 00:50:40 +010067 }
Gary Jennejohn6bd24472007-01-24 12:16:56 +010068
69 return rc;
70}
71
72/*-----------------------------------------------------------------------------
73 * Read hardware paramterers (sector size, size, number of sectors)
74 */
75static int mmc_hw_get_parameters(void)
76{
77 unsigned char csddata[16];
78 unsigned int sizemult;
79 unsigned int size;
80
81 mmc_read_csd(csddata);
82 hw_sect_size = 1<<(csddata[5] & 0x0f);
83 size = ((csddata[6]&0x03)<<10)+(csddata[7]<<2)+(csddata[8]&0xc0);
84 sizemult = ((csddata[10] & 0x80)>>7)+((csddata[9] & 0x03)<<1);
85 hw_nr_sects = (size+1)*(1<<(sizemult+2));
86 hw_size = hw_nr_sects*hw_sect_size/1024;
87
88#ifdef MMC_DEBUG
89 printf("mmc_hw_get_parameters: hw_sect_size=%d, hw_nr_sects=%d, "
90 "hw_size=%d\n", hw_sect_size, hw_nr_sects, hw_size);
91#endif
92
93 return 0;
94}
95
96int mmc_init(int verbose)
97{
98 int ret = -ENODEV;
99
100 if (verbose)
101 printf("mmc_init\n");
102
103 spi_init();
104 mmc_hw_init();
105
106 mmc_hw_get_parameters();
107
108 mmc_dev.if_type = IF_TYPE_MMC;
109 mmc_dev.part_type = PART_TYPE_DOS;
110 mmc_dev.dev = 0;
111 mmc_dev.lun = 0;
112 mmc_dev.type = 0;
113 mmc_dev.blksz = hw_sect_size;
114 mmc_dev.lba = hw_nr_sects;
115 sprintf((char*)mmc_dev.vendor, "Unknown vendor");
116 sprintf((char*)mmc_dev.product, "Unknown product");
117 sprintf((char*)mmc_dev.revision, "N/A");
118 mmc_dev.removable = 0; /* should be true??? */
119 mmc_dev.block_read = mmc_block_read;
120
121 fat_register_device(&mmc_dev, 1);
122
123 ret = 0;
124
125 return ret;
126}
127
128int mmc_write(uchar * src, ulong dst, int size)
129{
130#ifdef MMC_DEBUG
131 printf("mmc_write: src=%p, dst=%lu, size=%u\n", src, dst, size);
132#endif
133 /* Since mmc2info always returns 0 this function will never be called */
134 return 0;
135}
136
137int mmc_read(ulong src, uchar * dst, int size)
138{
139#ifdef MMC_DEBUG
140 printf("mmc_read: src=%lu, dst=%p, size=%u\n", src, dst, size);
141#endif
142 /* Since mmc2info always returns 0 this function will never be called */
143 return 0;
144}
145
146int mmc2info(ulong addr)
147{
148 /* This function is used by cmd_cp to determine if source or destination
149 address resides on MMC-card or not. We do not support copy to and from
150 MMC-card so we always return 0. */
151 return 0;
152}
153
154#endif /* CONFIG_MMC */