]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/karo/common/mmc.c
Merge branch 'tx48-devel' into uboot-merge
[karo-tx-uboot.git] / board / karo / common / mmc.c
1 /*
2  * (C) Copyright 2014 Lothar Waßmann <LW@KARO-electronics.de>
3  *
4  * See file CREDITS for list of people who contributed to this
5  * project.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * version 2 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16 */
17
18 #include <common.h>
19 #include <errno.h>
20 #include <libfdt.h>
21 #include <fdt_support.h>
22 //#include <nand.h>
23 #include <mmc.h>
24 #include <mxcfb.h>
25 #include <linux/list.h>
26 #include <linux/fb.h>
27 #include <jffs2/load_kernel.h>
28 #include <malloc.h>
29
30 #include "karo.h"
31
32 #define CONFIG_MMC_BOOT_DEV 0
33
34 DECLARE_GLOBAL_DATA_PTR;
35
36 static void __maybe_unused memdmp(void *addr, size_t len)
37 {
38         size_t i;
39
40         for (i = 0; i < len; i+= 16) {
41                 size_t j;
42                 u32 *wp = addr + i;
43
44                 debug("%p: ", addr + i);
45                 for (j = 0; j < 4; j++) {
46                         debug(" %08x", wp[j]);
47                 }
48                 debug("\n");
49         }
50 }
51
52 #define MAX_SEARCH_PARTITIONS 16
53
54 static int find_efi_partition(const char *ifname, int devno, const char *part_str,
55                              block_dev_desc_t **dev_desc,
56                              disk_partition_t *info)
57 {
58         int ret = -1;
59         char *dup_str = NULL;
60         int p;
61         int part;
62         block_dev_desc_t *dd;
63
64 printf("Searching for partition '%s'\n", part_str);
65
66         dd = get_dev(ifname, devno);
67         if (!dd || dd->type == DEV_TYPE_UNKNOWN) {
68                 printf("** Bad device %s %d **\n", ifname, devno);
69                 return -1;
70         }
71         init_part(dd);
72
73         /*
74          * No partition table on device,
75          * or user requested partition 0 (entire device).
76          */
77         if (dd->part_type == PART_TYPE_UNKNOWN) {
78                 printf("** No partition table - %s %d **\n", ifname,
79                         devno);
80                 goto cleanup;
81         }
82
83         part = 0;
84         for (p = 1; p <= MAX_SEARCH_PARTITIONS; p++) {
85                 ret = get_partition_info(dd, p, info);
86                 if (ret)
87                         continue;
88
89                 if (strcmp((char *)info->name, part_str) == 0) {
90                         part = p;
91                         dd->log2blksz = LOG2(dd->blksz);
92                         break;
93                 }
94         }
95         if (!part) {
96                 printf("** No valid partitions found **\n");
97                 ret = -1;
98                 goto cleanup;
99         }
100
101         ret = part;
102         *dev_desc = dd;
103
104 cleanup:
105         free(dup_str);
106         return ret;
107 }
108
109 int karo_load_mmc_part(const char *part, void *addr, size_t len)
110 {
111         int ret;
112         struct mmc *mmc;
113         disk_partition_t part_info;
114         int devno = CONFIG_MMC_BOOT_DEV;
115         uint blk_start, blk_cnt;
116
117         mmc = find_mmc_device(devno);
118         if (!mmc) {
119                 printf("Failed to find mmc%u\n", devno);
120                 return -ENODEV;
121         }
122
123         mmc_init(mmc);
124
125 //      mmc_boot_part_access(mmc, 1, part_num, part_num);
126 #if 1
127         block_dev_desc_t *mmc_dev;
128
129         ret = find_efi_partition("mmc", devno, part, &mmc_dev, &part_info);
130         if (ret < 0) {
131                 printf("eMMC partition '%s' not found: %d\n", part, ret);
132                 goto out;
133         }
134         mmc_switch_part(devno, ret);
135
136         blk_start = 0;
137         blk_cnt = DIV_ROUND_UP(len, part_info.blksz);
138
139         printf("Using mmc%d blksz %lu blks %lu\n", devno,
140                 mmc_dev->blksz, mmc_dev->lba);
141 #endif
142         debug("Found partition '%s': offset=%08x size=%08lx\n",
143                 part, blk_start, part_info.size);
144         if (part_info.size < blk_cnt) {
145                 printf("Warning: partition '%s' smaller than requested size: %u; truncating data to %lu blocks\n",
146                         part, len, part_info.size * mmc->read_bl_len);
147                 blk_cnt = part_info.size;
148         }
149
150         debug("Reading %u blks from MMC partition '%s' offset %u to %p\n",
151                 blk_cnt, part, blk_start, addr);
152         ret = mmc->block_dev.block_read(devno, blk_start, blk_cnt, addr);
153         if (ret == 0) {
154                 printf("Failed to read MMC partition %s\n", part);
155                 goto out;
156         }
157         debug("Read %u byte from partition '%s' @ offset %08x\n",
158                 ret * mmc->read_bl_len, part, blk_start);
159         memdmp(addr, 512);
160         ret = 0;
161 out:
162 //      mmc_boot_part_access(mmc, 1, part_num, 0);
163         mmc_switch_part(devno, 0);
164         return ret;
165 }