212d53a4c6dc326802d39950668abd24844fa008
[fw/openocd] / src / flash / nor / virtual.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 /***************************************************************************
4  *   Copyright (C) 2010 by Spencer Oliver                                  *
5  *   spen@spen-soft.co.uk                                                  *
6  ***************************************************************************/
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
12 #include "imp.h"
13
14 static struct flash_bank *virtual_get_master_bank(struct flash_bank *bank)
15 {
16         struct flash_bank *master_bank;
17
18         master_bank = get_flash_bank_by_name_noprobe(bank->driver_priv);
19         if (!master_bank)
20                 LOG_ERROR("master flash bank '%s' does not exist", (char *)bank->driver_priv);
21
22         return master_bank;
23 }
24
25 static void virtual_update_bank_info(struct flash_bank *bank)
26 {
27         struct flash_bank *master_bank = virtual_get_master_bank(bank);
28
29         if (!master_bank)
30                 return;
31
32         /* update the info we do not have */
33         bank->size = master_bank->size;
34         bank->chip_width = master_bank->chip_width;
35         bank->bus_width = master_bank->bus_width;
36         bank->erased_value = master_bank->erased_value;
37         bank->default_padded_value = master_bank->default_padded_value;
38         bank->write_start_alignment = master_bank->write_start_alignment;
39         bank->write_end_alignment = master_bank->write_end_alignment;
40         bank->minimal_write_gap = master_bank->minimal_write_gap;
41         bank->num_sectors = master_bank->num_sectors;
42         bank->sectors = master_bank->sectors;
43         bank->num_prot_blocks = master_bank->num_prot_blocks;
44         bank->prot_blocks = master_bank->prot_blocks;
45 }
46
47 FLASH_BANK_COMMAND_HANDLER(virtual_flash_bank_command)
48 {
49         if (CMD_ARGC < 7)
50                 return ERROR_COMMAND_SYNTAX_ERROR;
51
52         /* get the master flash bank */
53         const char *bank_name = CMD_ARGV[6];
54         struct flash_bank *master_bank = get_flash_bank_by_name_noprobe(bank_name);
55
56         if (!master_bank) {
57                 LOG_ERROR("master flash bank '%s' does not exist", bank_name);
58                 return ERROR_FLASH_OPERATION_FAILED;
59         }
60
61         /* save master bank name - use this to get settings later */
62         bank->driver_priv = strdup(bank_name);
63
64         return ERROR_OK;
65 }
66
67 static int virtual_protect(struct flash_bank *bank, int set, unsigned int first,
68                 unsigned int last)
69 {
70         struct flash_bank *master_bank = virtual_get_master_bank(bank);
71
72         if (!master_bank)
73                 return ERROR_FLASH_OPERATION_FAILED;
74
75         return flash_driver_protect(master_bank, set, first, last);
76 }
77
78 static int virtual_protect_check(struct flash_bank *bank)
79 {
80         struct flash_bank *master_bank = virtual_get_master_bank(bank);
81
82         if (!master_bank)
83                 return ERROR_FLASH_OPERATION_FAILED;
84
85         if (!master_bank->driver->protect_check)
86                 return ERROR_FLASH_OPER_UNSUPPORTED;
87
88         /* call master handler */
89         return master_bank->driver->protect_check(master_bank);
90 }
91
92 static int virtual_erase(struct flash_bank *bank, unsigned int first,
93                 unsigned int last)
94 {
95         struct flash_bank *master_bank = virtual_get_master_bank(bank);
96         int retval;
97
98         if (!master_bank)
99                 return ERROR_FLASH_OPERATION_FAILED;
100
101         /* call master handler */
102         retval = master_bank->driver->erase(master_bank, first, last);
103         if (retval != ERROR_OK)
104                 return retval;
105
106         return ERROR_OK;
107 }
108
109 static int virtual_write(struct flash_bank *bank, const uint8_t *buffer,
110                 uint32_t offset, uint32_t count)
111 {
112         struct flash_bank *master_bank = virtual_get_master_bank(bank);
113         int retval;
114
115         if (!master_bank)
116                 return ERROR_FLASH_OPERATION_FAILED;
117
118         /* call master handler */
119         retval = master_bank->driver->write(master_bank, buffer, offset, count);
120         if (retval != ERROR_OK)
121                 return retval;
122
123         return ERROR_OK;
124 }
125
126 static int virtual_probe(struct flash_bank *bank)
127 {
128         struct flash_bank *master_bank = virtual_get_master_bank(bank);
129         int retval;
130
131         if (!master_bank)
132                 return ERROR_FLASH_OPERATION_FAILED;
133
134         /* call master handler */
135         retval = master_bank->driver->probe(master_bank);
136         if (retval != ERROR_OK)
137                 return retval;
138
139         /* update the info we do not have */
140         virtual_update_bank_info(bank);
141
142         return ERROR_OK;
143 }
144
145 static int virtual_auto_probe(struct flash_bank *bank)
146 {
147         struct flash_bank *master_bank = virtual_get_master_bank(bank);
148         int retval;
149
150         if (!master_bank)
151                 return ERROR_FLASH_OPERATION_FAILED;
152
153         /* call master handler */
154         retval = master_bank->driver->auto_probe(master_bank);
155         if (retval != ERROR_OK)
156                 return retval;
157
158         /* update the info we do not have */
159         virtual_update_bank_info(bank);
160
161         return ERROR_OK;
162 }
163
164 static int virtual_info(struct flash_bank *bank, struct command_invocation *cmd)
165 {
166         struct flash_bank *master_bank = virtual_get_master_bank(bank);
167
168         if (!master_bank)
169                 return ERROR_FLASH_OPERATION_FAILED;
170
171         command_print_sameline(cmd, "%s driver for flash bank %s at " TARGET_ADDR_FMT,
172                         bank->driver->name, master_bank->name, master_bank->base);
173
174         return ERROR_OK;
175 }
176
177 static int virtual_blank_check(struct flash_bank *bank)
178 {
179         struct flash_bank *master_bank = virtual_get_master_bank(bank);
180         int retval;
181
182         if (!master_bank)
183                 return ERROR_FLASH_OPERATION_FAILED;
184
185         /* call master handler */
186         retval = master_bank->driver->erase_check(master_bank);
187         if (retval != ERROR_OK)
188                 return retval;
189
190         return ERROR_OK;
191 }
192
193 static int virtual_flash_read(struct flash_bank *bank,
194                 uint8_t *buffer, uint32_t offset, uint32_t count)
195 {
196         struct flash_bank *master_bank = virtual_get_master_bank(bank);
197         int retval;
198
199         if (!master_bank)
200                 return ERROR_FLASH_OPERATION_FAILED;
201
202         /* call master handler */
203         retval = master_bank->driver->read(master_bank, buffer, offset, count);
204         if (retval != ERROR_OK)
205                 return retval;
206
207         return ERROR_OK;
208 }
209
210 const struct flash_driver virtual_flash = {
211         .name = "virtual",
212         .flash_bank_command = virtual_flash_bank_command,
213         .erase = virtual_erase,
214         .protect = virtual_protect,
215         .write = virtual_write,
216         .read = virtual_flash_read,
217         .probe = virtual_probe,
218         .auto_probe = virtual_auto_probe,
219         .erase_check = virtual_blank_check,
220         .protect_check = virtual_protect_check,
221         .info = virtual_info,
222         .free_driver_priv = default_flash_free_driver_priv,
223 };