add flash/nor/{tcl.c,imp.h} from flash/flash.c
[fw/openocd] / src / flash / nor / tcl.c
1 /***************************************************************************
2  *   Copyright (C) 2005 by Dominic Rath <Dominic.Rath@gmx.de>              *
3  *   Copyright (C) 2007,2008 Ã˜yvind Harboe <oyvind.harboe@zylin.com>       *
4  *   Copyright (C) 2008 by Spencer Oliver <spen@spen-soft.co.uk>           *
5  *   Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net>             *
6  *                                                                         *
7  *   This program is free software; you can redistribute it and/or modify  *
8  *   it under the terms of the GNU General Public License as published by  *
9  *   the Free Software Foundation; either version 2 of the License, or     *
10  *   (at your option) any later version.                                   *
11  *                                                                         *
12  *   This program is distributed in the hope that it will be useful,       *
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
15  *   GNU General Public License for more details.                          *
16  *                                                                         *
17  *   You should have received a copy of the GNU General Public License     *
18  *   along with this program; if not, write to the                         *
19  *   Free Software Foundation, Inc.,                                       *
20  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
21  ***************************************************************************/
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 #include "imp.h"
26
27 COMMAND_HANDLER(handle_flash_bank_command)
28 {
29         if (CMD_ARGC < 7)
30         {
31                 LOG_ERROR("usage: flash bank <name> <driver> "
32                                 "<base> <size> <chip_width> <bus_width>");
33                 return ERROR_COMMAND_SYNTAX_ERROR;
34         }
35         // save bank name and advance arguments for compatibility
36         const char *bank_name = *CMD_ARGV++;
37         CMD_ARGC--;
38
39         struct target *target;
40         if ((target = get_target(CMD_ARGV[5])) == NULL)
41         {
42                 LOG_ERROR("target '%s' not defined", CMD_ARGV[5]);
43                 return ERROR_FAIL;
44         }
45
46         const char *driver_name = CMD_ARGV[0];
47         for (unsigned i = 0; flash_drivers[i]; i++)
48         {
49                 if (strcmp(driver_name, flash_drivers[i]->name) != 0)
50                         continue;
51
52                 /* register flash specific commands */
53                 if (NULL != flash_drivers[i]->commands)
54                 {
55                         int retval = register_commands(CMD_CTX, NULL,
56                                         flash_drivers[i]->commands);
57                         if (ERROR_OK != retval)
58                         {
59                                 LOG_ERROR("couldn't register '%s' commands",
60                                                 driver_name);
61                                 return ERROR_FAIL;
62                         }
63                 }
64
65                 struct flash_bank *p, *c;
66                 c = malloc(sizeof(struct flash_bank));
67                 c->name = strdup(bank_name);
68                 c->target = target;
69                 c->driver = flash_drivers[i];
70                 c->driver_priv = NULL;
71                 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], c->base);
72                 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], c->size);
73                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], c->chip_width);
74                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[4], c->bus_width);
75                 c->num_sectors = 0;
76                 c->sectors = NULL;
77                 c->next = NULL;
78
79                 int retval;
80                 retval = CALL_COMMAND_HANDLER(flash_drivers[i]->flash_bank_command, c);
81                 if (ERROR_OK != retval)
82                 {
83                         LOG_ERROR("'%s' driver rejected flash bank at 0x%8.8" PRIx32,
84                                         driver_name, c->base);
85                         free(c);
86                         return retval;
87                 }
88
89                 /* put flash bank in linked list */
90                 if (flash_banks)
91                 {
92                         int     bank_num = 0;
93                         /* find last flash bank */
94                         for (p = flash_banks; p && p->next; p = p->next) bank_num++;
95                         if (p)
96                                 p->next = c;
97                         c->bank_number = bank_num + 1;
98                 }
99                 else
100                 {
101                         flash_banks = c;
102                         c->bank_number = 0;
103                 }
104
105                 return ERROR_OK;
106         }
107
108         /* no matching flash driver found */
109         LOG_ERROR("flash driver '%s' not found", driver_name);
110         return ERROR_FAIL;
111 }
112
113
114 static int jim_flash_banks(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
115 {
116         struct flash_bank *p;
117
118         if (argc != 1) {
119                 Jim_WrongNumArgs(interp, 1, argv, "no arguments to flash_banks command");
120                 return JIM_ERR;
121         }
122
123         Jim_Obj *list = Jim_NewListObj(interp, NULL, 0);
124         for (p = flash_banks; p; p = p->next)
125         {
126                 Jim_Obj *elem = Jim_NewListObj(interp, NULL, 0);
127
128                 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "name", -1));
129                 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, p->driver->name, -1));
130                 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "base", -1));
131                 Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->base));
132                 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "size", -1));
133                 Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->size));
134                 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "bus_width", -1));
135                 Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->bus_width));
136                 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "chip_width", -1));
137                 Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->chip_width));
138
139                 Jim_ListAppendElement(interp, list, elem);
140         }
141
142         Jim_SetResult(interp, list);
143
144         return JIM_OK;
145 }
146
147
148 COMMAND_HANDLER(handle_flash_init_command)
149 {
150         if (CMD_ARGC != 0)
151                 return ERROR_COMMAND_SYNTAX_ERROR;
152
153         static bool flash_initialized = false;
154         if (flash_initialized)
155         {
156                 LOG_INFO("'flash init' has already been called");
157                 return ERROR_OK;
158         }
159         flash_initialized = true;
160
161         LOG_DEBUG("Initializing flash devices...");
162         return flash_init_drivers(CMD_CTX);
163 }
164
165 static const struct command_registration flash_config_command_handlers[] = {
166         {
167                 .name = "bank",
168                 .handler = &handle_flash_bank_command,
169                 .mode = COMMAND_CONFIG,
170                 .usage = "<name> <driver> <base> <size> "
171                         "<chip_width> <bus_width> <target> "
172                         "[driver_options ...]",
173                 .help = "Define a new bank with the given name, "
174                         "using the specified NOR flash driver.",
175         },
176         {
177                 .name = "init",
178                 .mode = COMMAND_CONFIG,
179                 .handler = &handle_flash_init_command,
180                 .help = "initialize flash devices",
181         },
182         {
183                 .name = "banks",
184                 .mode = COMMAND_ANY,
185                 .jim_handler = &jim_flash_banks,
186                 .help = "return information about the flash banks",
187         },
188         COMMAND_REGISTRATION_DONE
189 };
190 static const struct command_registration flash_command_handlers[] = {
191         {
192                 .name = "flash",
193                 .mode = COMMAND_ANY,
194                 .help = "NOR flash command group",
195                 .chain = flash_config_command_handlers,
196         },
197         COMMAND_REGISTRATION_DONE
198 };
199
200 int flash_register_commands(struct command_context *cmd_ctx)
201 {
202         return register_commands(cmd_ctx, NULL, flash_command_handlers);
203 }