]> git.karo-electronics.de Git - karo-tx-uboot.git/blob - board/karo/common/nand.c
karo: tx6: add support for TX6-V2 (eMMC)
[karo-tx-uboot.git] / board / karo / common / nand.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 <mxcfb.h>
24 #include <linux/list.h>
25 #include <linux/fb.h>
26 #include <jffs2/load_kernel.h>
27 #include <malloc.h>
28
29 #include "karo.h"
30
31 #ifdef CONFIG_MAX_DTB_SIZE
32 #define MAX_DTB_SIZE    CONFIG_MAX_DTB_SIZE
33 #else
34 #define MAX_DTB_SIZE    SZ_64K
35 #endif
36
37 DECLARE_GLOBAL_DATA_PTR;
38
39 int karo_load_nand_part(const char *part, void *addr, size_t len)
40 {
41         int ret;
42         struct mtd_device *dev;
43         struct part_info *part_info;
44         u8 part_num;
45         size_t actual;
46
47         debug("Initializing mtd_parts\n");
48         ret = mtdparts_init();
49         if (ret)
50                 return ret;
51
52         debug("Trying to find NAND partition '%s'\n", part);
53         ret = find_dev_and_part(part, &dev, &part_num, &part_info);
54         if (ret) {
55                 printf("Failed to find flash partition '%s': %d\n",
56                         part, ret);
57
58                 return ret;
59         }
60         debug("Found partition '%s': offset=%08x size=%08x\n",
61                 part, part_info->offset, part_info->size);
62         if (part_info->size < len) {
63                 printf("Warning: partition '%s' smaller than requested size: %u; truncating data to %u byte\n",
64                         part, len, part_info->size);
65                 len = part_info->size;
66         }
67         debug("Reading NAND partition '%s' to %p\n", part, addr);
68         ret = nand_read_skip_bad(&nand_info[0], part_info->offset, &len,
69                                 &actual, len, addr);
70         if (ret) {
71                 printf("Failed to load partition '%s' to %p\n", part, addr);
72                 return ret;
73         }
74         if (actual < len)
75                 printf("Read only %u of %u bytes due to bad blocks\n",
76                         actual, len);
77
78         debug("Read %u byte from partition '%s' @ offset %08x\n",
79                 len, part, part_info->offset);
80         return 0;
81 }
82
83 #ifdef CONFIG_SPLASH_SCREEN_
84 static int erase_flash(loff_t offs, size_t len)
85 {
86         nand_erase_options_t nand_erase_options;
87
88         memset(&nand_erase_options, 0, sizeof(nand_erase_options));
89         nand_erase_options.length = len;
90         nand_erase_options.offset = offs;
91
92         return nand_erase_opts(&nand_info[0], &nand_erase_options);
93 }
94
95 int do_fbdump(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
96 {
97         int ret;
98         size_t fbsize = calc_fbsize();
99         const char *part = "logo";
100         struct mtd_device *dev;
101         struct part_info *part_info;
102         u8 part_num;
103         u_char *addr = (u_char *)gd->fb_base;
104         size_t actual;
105
106         if (argc > 2)
107                 return CMD_RET_USAGE;
108
109         if (argc == 2)
110                 part = argv[1];
111
112         if (!addr) {
113                 printf("fb address unknown\n");
114                 return CMD_RET_FAILURE;
115         }
116
117         debug("Initializing mtd_parts\n");
118         ret = mtdparts_init();
119         if (ret)
120                 return ret;
121
122         debug("Trying to find NAND partition '%s'\n", part);
123         ret = find_dev_and_part(part, &dev, &part_num,
124                                 &part_info);
125         if (ret) {
126                 printf("Failed to find flash partition '%s': %d\n",
127                         part, ret);
128
129                 return ret;
130         }
131         debug("Found partition '%s': offset=%08x size=%08x\n",
132                 part, part_info->offset, part_info->size);
133         if (part_info->size < fbsize) {
134                 printf("Error: partition '%s' smaller than frame buffer size: %u\n",
135                         part, fbsize);
136                 return CMD_RET_FAILURE;
137         }
138         debug("Writing framebuffer %p to NAND partition '%s'\n",
139                 addr, part);
140
141         ret = erase_flash(part_info->offset, fbsize);
142         if (ret) {
143                 printf("Failed to erase partition '%s'\n", part);
144                 return CMD_RET_FAILURE;
145         }
146
147         ret = nand_write_skip_bad(&nand_info[0], part_info->offset,
148                                 &fbsize, &actual, part_info->size,
149                                 addr, WITH_DROP_FFS);
150         if (ret) {
151                 printf("Failed to write partition '%s'\n", part);
152                 return ret;
153         }
154         if (actual < fbsize)
155                 printf("Wrote only %u of %u bytes due to bad blocks\n",
156                         actual, fbsize);
157
158         debug("Wrote %u byte from %p to partition '%s' @ offset %08x\n",
159                 fbsize, addr, part, part_info->offset);
160
161         return CMD_RET_SUCCESS;
162 }
163
164 U_BOOT_CMD(fbdump, 2, 0, do_fbdump, "dump framebuffer contents to flash",
165         "[partition name]\n"
166         "       default partition name: 'logo'\n");
167 #endif