2 * (C) Copyright 2014 Lothar Waßmann <LW@KARO-electronics.de>
4 * See file CREDITS for list of people who contributed to this
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.
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.
22 #include <fdt_support.h>
28 #include <linux/err.h>
29 #include <jffs2/load_kernel.h>
33 DECLARE_GLOBAL_DATA_PTR;
35 #define MAX_SEARCH_PARTITIONS 16
37 static int find_partitions(const char *ifname, int devno, const char *partname,
38 struct blk_desc **dev_desc, disk_partition_t *info)
41 char dev_part_str[16];
44 dd = blk_get_devnum_by_typename(ifname, devno);
45 if (!dd || dd->type == DEV_TYPE_UNKNOWN) {
46 printf("** Bad device %s %d **\n", ifname, devno);
52 * No partition table on device,
53 * or user requested partition 0 (entire device).
55 if (dd->part_type == PART_TYPE_UNKNOWN) {
56 printf("** No partition table on device %s %d **\n",
61 printf("part type: %08x\n", dd->part_type);
62 for (p = 1; p <= MAX_SEARCH_PARTITIONS; p++) {
66 ret = part_get_info(dd, p, info);
68 ret = strncmp((char *)info->name, partname,
71 ret = fat_register_device(dd, p);
77 snprintf(dev_part_str, sizeof(dev_part_str), "%d:%d",
79 ret = fs_set_blk_dev(ifname, dev_part_str, FS_TYPE_ANY);
81 dd->log2blksz = LOG2(dd->blksz);
86 printf("** No valid partition on device %s %d **\n",
91 static int karo_mmc_find_part(struct mmc *mmc, const char *part,
92 const char *filename, int devno,
93 disk_partition_t *part_info)
96 struct blk_desc *mmc_dev;
98 #if defined(CONFIG_SYS_DTB_OFFSET) && defined(CONFIG_SYS_MMC_ENV_PART)
99 if (strcmp(part, "dtb") == 0) {
100 const int partnum = CONFIG_SYS_MMC_ENV_PART;
102 part_info->blksz = mmc->read_bl_len;
103 part_info->start = CONFIG_SYS_DTB_OFFSET / part_info->blksz;
104 part_info->size = CONFIG_SYS_DTB_PART_SIZE / part_info->blksz;
105 printf("Using virtual partition %s(%d) ["LBAF".."LBAF"]\n",
106 part, partnum, part_info->start,
107 part_info->start + part_info->size - 1);
111 ret = find_partitions("mmc", devno, part, &mmc_dev, part_info);
113 printf("No (e)MMC partition found: %d\n", ret);
119 int karo_mmc_load_part(const char *part_file, void *addr, size_t len)
123 char *partname = strdup(part_file);
125 disk_partition_t part_info;
126 int devno = mmc_get_env_dev();
132 mmc = find_mmc_device(devno);
134 printf("Failed to find mmc%u\n", devno);
139 printf("Failed to init MMC device %d\n", devno);
143 filename = strchr(partname, ':');
151 blk_cnt = DIV_ROUND_UP(len, mmc->read_bl_len);
153 ret = karo_mmc_find_part(mmc, partname, filename, devno, &part_info);
157 if (partname == filename) {
159 struct blk_desc *desc = mmc_get_blk_desc(mmc);
160 int hwpart = desc->hwpart;
163 if (part_info.start + blk_cnt < part_info.start) {
164 printf("%s: given length 0x%08zx exceeds size of partition\n",
169 if (partnum != hwpart) {
170 ret = blk_select_hwpart_devnum(IF_TYPE_MMC, devno,
175 desc = mmc_get_blk_desc(mmc);
177 if (part_info.start + blk_cnt > desc->lba)
178 blk_cnt = desc->lba - part_info.start;
180 debug("Reading 0x"LBAF" blks from MMC partition %d offset 0x"LBAF" to %p\n",
181 blk_cnt, partnum, part_info.start, addr);
183 retval = blk_dread(desc, part_info.start, blk_cnt, addr);
184 if (partnum != hwpart)
185 blk_select_hwpart_devnum(IF_TYPE_MMC, devno, hwpart);
186 if (IS_ERR_VALUE(retval) || retval == 0) {
187 printf("Failed to read file %s from MMC partition %s\n",
189 ret = retval ?: -EIO;
192 debug("Read %lu (%zu) byte from partition '%s' @ offset 0x"LBAF"\n",
193 retval * mmc->read_bl_len, len, filename, part_info.start);
197 debug("Trying to read (%zu) byte from file '%s' in mmc partition '%s'\n",
198 len, filename, partname);
199 ret = fs_read(filename, (ulong)addr, 0, len, &len_read);
201 printf("Failed to read %zu byte from '%s' in mmc partition '%s'; err: %d\n",
202 len, filename, partname, ret);
205 debug("Read %llu bytes from %s\n", len_read, filename);