arm: mx6: cm-fx6: add splash screen support
[platform/kernel/u-boot.git] / board / compulab / common / splash.c
1 /*
2  * (C) Copyright 2014 CompuLab, Ltd. <www.compulab.co.il>
3  *
4  * Authors: Igor Grinberg <grinberg@compulab.co.il>
5  *
6  * SPDX-License-Identifier:     GPL-2.0+
7  */
8
9 #include <common.h>
10 #include <nand.h>
11 #include <errno.h>
12 #include <spi_flash.h>
13 #include <spi.h>
14 #include <bmp_layout.h>
15 #include "common.h"
16
17 DECLARE_GLOBAL_DATA_PTR;
18
19 #ifdef CONFIG_SPI_FLASH
20 static struct spi_flash *sf;
21 static int splash_sf_read(u32 bmp_load_addr, int offset, size_t read_size)
22 {
23         if (!sf) {
24                 sf = spi_flash_probe(CONFIG_SF_DEFAULT_BUS,
25                                      CONFIG_SF_DEFAULT_CS,
26                                      CONFIG_SF_DEFAULT_SPEED,
27                                      CONFIG_SF_DEFAULT_MODE);
28                 if (!sf)
29                         return -ENODEV;
30         }
31
32         return spi_flash_read(sf, offset, read_size, (void *)bmp_load_addr);
33 }
34 #else
35 static int splash_sf_read(u32 bmp_load_addr, int offset, size_t read_size)
36 {
37         debug("%s: sf support not available\n", __func__);
38         return -ENOSYS;
39 }
40 #endif
41
42 #ifdef CONFIG_CMD_NAND
43 static int splash_nand_read(u32 bmp_load_addr, int offset, size_t read_size)
44 {
45         return nand_read_skip_bad(&nand_info[nand_curr_device], offset,
46                                   &read_size, NULL,
47                                   nand_info[nand_curr_device].size,
48                                   (u_char *)bmp_load_addr);
49 }
50 #else
51 static int splash_nand_read(u32 bmp_load_addr, int offset, size_t read_size)
52 {
53         debug("%s: nand support not available\n", __func__);
54         return -ENOSYS;
55 }
56 #endif
57
58 static int splash_storage_read(struct splash_location *location,
59                                u32 bmp_load_addr, size_t read_size)
60 {
61         u32 offset;
62
63         if (!location)
64                 return -EINVAL;
65
66         offset = location->offset;
67         switch (location->storage) {
68         case SPLASH_STORAGE_NAND:
69                 return splash_nand_read(bmp_load_addr, offset, read_size);
70         case SPLASH_STORAGE_SF:
71                 return splash_sf_read(bmp_load_addr, offset, read_size);
72         default:
73                 printf("Unknown splash location\n");
74         }
75
76         return -EINVAL;
77 }
78
79 static int splash_load_raw(struct splash_location *location, u32 bmp_load_addr)
80 {
81         struct bmp_header *bmp_hdr;
82         int res;
83         size_t bmp_size, bmp_header_size = sizeof(struct bmp_header);
84
85         if (bmp_load_addr + bmp_header_size >= gd->start_addr_sp)
86                 goto splash_address_too_high;
87
88         res = splash_storage_read(location, bmp_load_addr, bmp_header_size);
89         if (res < 0)
90                 return res;
91
92         bmp_hdr = (struct bmp_header *)bmp_load_addr;
93         bmp_size = le32_to_cpu(bmp_hdr->file_size);
94
95         if (bmp_load_addr + bmp_size >= gd->start_addr_sp)
96                 goto splash_address_too_high;
97
98         return splash_storage_read(location, bmp_load_addr, bmp_size);
99
100 splash_address_too_high:
101         printf("Error: splashimage address too high. Data overwrites U-Boot "
102                 "and/or placed beyond DRAM boundaries.\n");
103
104         return -EFAULT;
105 }
106
107 /**
108  * select_splash_location - return the splash location based on board support
109  *                          and env variable "splashsource".
110  *
111  * @locations:          An array of supported splash locations.
112  * @size:               Size of splash_locations array.
113  *
114  * @return: If a null set of splash locations is given, or
115  *          splashsource env variable is set to unsupported value
116  *                      return NULL.
117  *          If splashsource env variable is not defined
118  *                      return the first entry in splash_locations as default.
119  *          If splashsource env variable contains a supported value
120  *                      return the location selected by splashsource.
121  */
122 static struct splash_location *select_splash_location(
123                             struct splash_location *locations, uint size)
124 {
125         int i;
126         char *env_splashsource;
127
128         if (!locations || size == 0)
129                 return NULL;
130
131         env_splashsource = getenv("splashsource");
132         if (env_splashsource == NULL)
133                 return &locations[0];
134
135         for (i = 0; i < size; i++) {
136                 if (!strcmp(locations[i].name, env_splashsource))
137                         return &locations[i];
138         }
139
140         printf("splashsource env variable set to unsupported value\n");
141         return NULL;
142 }
143
144 int cl_splash_screen_prepare(struct splash_location *locations, uint size)
145 {
146         struct splash_location *splash_location;
147         char *env_splashimage_value;
148         u32 bmp_load_addr;
149
150         env_splashimage_value = getenv("splashimage");
151         if (env_splashimage_value == NULL)
152                 return -ENOENT;
153
154         bmp_load_addr = simple_strtoul(env_splashimage_value, 0, 16);
155         if (bmp_load_addr == 0) {
156                 printf("Error: bad splashimage address specified\n");
157                 return -EFAULT;
158         }
159
160         splash_location = select_splash_location(locations, size);
161         if (!splash_location)
162                 return -EINVAL;
163
164         return splash_load_raw(splash_location, bmp_load_addr);
165 }