From Michael Bruck
[fw/openocd] / src / pld / virtex2.c
1 /***************************************************************************\r
2  *   Copyright (C) 2006 by Dominic Rath                                    *\r
3  *   Dominic.Rath@gmx.de                                                   *\r
4  *                                                                         *\r
5  *   This program is free software; you can redistribute it and/or modify  *\r
6  *   it under the terms of the GNU General Public License as published by  *\r
7  *   the Free Software Foundation; either version 2 of the License, or     *\r
8  *   (at your option) any later version.                                   *\r
9  *                                                                         *\r
10  *   This program is distributed in the hope that it will be useful,       *\r
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *\r
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *\r
13  *   GNU General Public License for more details.                          *\r
14  *                                                                         *\r
15  *   You should have received a copy of the GNU General Public License     *\r
16  *   along with this program; if not, write to the                         *\r
17  *   Free Software Foundation, Inc.,                                       *\r
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *\r
19  ***************************************************************************/\r
20 #ifdef HAVE_CONFIG_H\r
21 #include "config.h"\r
22 #endif\r
23 \r
24 #include "virtex2.h"\r
25 \r
26 #include "pld.h"\r
27 #include "xilinx_bit.h"\r
28 #include "command.h"\r
29 #include "log.h"\r
30 #include "jtag.h"\r
31 \r
32 #include <stdlib.h>\r
33 \r
34 int virtex2_register_commands(struct command_context_s *cmd_ctx);\r
35 int virtex2_pld_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct pld_device_s *pld_device);\r
36 int virtex2_load(struct pld_device_s *pld_device, char *filename);\r
37 \r
38 pld_driver_t virtex2_pld =\r
39 {\r
40         .name = "virtex2",\r
41         .register_commands = virtex2_register_commands,\r
42         .pld_device_command = virtex2_pld_device_command,\r
43         .load = virtex2_load,\r
44 };\r
45 \r
46 int virtex2_set_instr(int chain_pos, u32 new_instr)\r
47 {\r
48         jtag_device_t *device = jtag_get_device(chain_pos);\r
49         \r
50         if (buf_get_u32(device->cur_instr, 0, device->ir_length) != new_instr)\r
51         {\r
52                 scan_field_t field;\r
53         \r
54                 field.device = chain_pos;\r
55                 field.num_bits = device->ir_length;\r
56                 field.out_value = calloc(CEIL(field.num_bits, 8), 1);\r
57                 buf_set_u32(field.out_value, 0, field.num_bits, new_instr);\r
58                 field.out_mask = NULL;\r
59                 field.in_value = NULL;\r
60                 field.in_check_value = NULL;\r
61                 field.in_check_mask = NULL;\r
62                 field.in_handler = NULL;\r
63                 field.in_handler_priv = NULL;\r
64                 \r
65                 jtag_add_ir_scan(1, &field, TAP_RTI);\r
66                 \r
67                 free(field.out_value);\r
68         }\r
69         \r
70         return ERROR_OK;\r
71 }\r
72 \r
73 int virtex2_send_32(struct pld_device_s *pld_device, int num_words, u32 *words)\r
74 {\r
75         virtex2_pld_device_t *virtex2_info = pld_device->driver_priv;\r
76         scan_field_t scan_field;\r
77         u8 *values;\r
78         int i;\r
79         \r
80         values = malloc(num_words * 4);\r
81 \r
82         scan_field.device = virtex2_info->chain_pos;\r
83         scan_field.num_bits = num_words * 32;\r
84         scan_field.out_value = values;\r
85         scan_field.out_mask = NULL;\r
86         scan_field.in_value = NULL;\r
87         scan_field.in_check_value = NULL;\r
88         scan_field.in_check_mask = NULL;\r
89         scan_field.in_handler = NULL;\r
90         scan_field.in_handler_priv = NULL;\r
91         \r
92         for (i = 0; i < num_words; i++)\r
93                 buf_set_u32(values + 4 * i, 0, 32, flip_u32(*words++, 32));\r
94         \r
95         virtex2_set_instr(virtex2_info->chain_pos, 0x5); /* CFG_IN */\r
96         \r
97         jtag_add_dr_scan(1, &scan_field, TAP_PD);\r
98         \r
99         free(values);\r
100         \r
101         return ERROR_OK;\r
102 }\r
103 \r
104 int virtex2_jtag_buf_to_u32(u8 *in_buf, void *priv, struct scan_field_s *field)\r
105 {\r
106         u32 *dest = priv;\r
107         *dest = flip_u32(le_to_h_u32(in_buf), 32);\r
108         return ERROR_OK;\r
109 }\r
110 \r
111 int virtex2_receive_32(struct pld_device_s *pld_device, int num_words, u32 *words)\r
112 {\r
113         virtex2_pld_device_t *virtex2_info = pld_device->driver_priv;\r
114         scan_field_t scan_field;\r
115         \r
116         scan_field.device = virtex2_info->chain_pos;\r
117         scan_field.num_bits = 32;\r
118         scan_field.out_value = NULL;\r
119         scan_field.out_mask = NULL;\r
120         scan_field.in_value = NULL;\r
121         scan_field.in_check_value = NULL;\r
122         scan_field.in_check_mask = NULL;\r
123         scan_field.in_handler = virtex2_jtag_buf_to_u32;\r
124         \r
125         virtex2_set_instr(virtex2_info->chain_pos, 0x4); /* CFG_OUT */\r
126         \r
127         while (num_words--)\r
128         {\r
129                 scan_field.in_handler_priv = words++;\r
130                 jtag_add_dr_scan(1, &scan_field, TAP_PD);\r
131         }\r
132         \r
133         return ERROR_OK;\r
134 }\r
135 \r
136 int virtex2_read_stat(struct pld_device_s *pld_device, u32 *status)\r
137 {\r
138         u32 data[5];\r
139         \r
140         jtag_add_statemove(TAP_TLR);\r
141         \r
142         data[0] = 0xaa995566; /* synch word */\r
143         data[1] = 0x2800E001; /* Type 1, read, address 7, 1 word */\r
144         data[2] = 0x20000000; /* NOOP (Type 1, read, address 0, 0 words */\r
145         data[3] = 0x20000000; /* NOOP */\r
146         data[4] = 0x20000000; /* NOOP */\r
147         virtex2_send_32(pld_device, 5, data);\r
148         \r
149         virtex2_receive_32(pld_device, 1, status);\r
150         \r
151         jtag_execute_queue();\r
152         \r
153         DEBUG("status: 0x%8.8x", *status);\r
154         \r
155         return ERROR_OK;\r
156 }\r
157 \r
158 int virtex2_load(struct pld_device_s *pld_device, char *filename)\r
159 {\r
160         virtex2_pld_device_t *virtex2_info = pld_device->driver_priv;\r
161         xilinx_bit_file_t bit_file;\r
162         int retval;\r
163         int i;\r
164 \r
165         scan_field_t field;\r
166 \r
167         field.device = virtex2_info->chain_pos;\r
168         field.out_mask = NULL;\r
169         field.in_value = NULL;\r
170         field.in_check_value = NULL;\r
171         field.in_check_mask = NULL;\r
172         field.in_handler = NULL;\r
173         field.in_handler_priv = NULL;\r
174         \r
175         if ((retval = xilinx_read_bit_file(&bit_file, filename)) != ERROR_OK)\r
176                 return retval;\r
177         \r
178         jtag_add_end_state(TAP_RTI);\r
179         virtex2_set_instr(virtex2_info->chain_pos, 0xb); /* JPROG_B */\r
180         jtag_execute_queue();\r
181         jtag_add_sleep(1000);\r
182         \r
183         virtex2_set_instr(virtex2_info->chain_pos, 0x5); /* CFG_IN */\r
184         jtag_execute_queue();\r
185         \r
186         for (i = 0; i < bit_file.length; i++)\r
187                 bit_file.data[i] = flip_u32(bit_file.data[i], 8);\r
188         \r
189         field.num_bits = bit_file.length * 8;\r
190         field.out_value = bit_file.data;\r
191 \r
192         jtag_add_dr_scan(1, &field, TAP_PD);\r
193         jtag_execute_queue();\r
194         \r
195         jtag_add_statemove(TAP_TLR);\r
196         \r
197         jtag_add_end_state(TAP_RTI);\r
198         virtex2_set_instr(virtex2_info->chain_pos, 0xc); /* JSTART */\r
199         jtag_add_runtest(13, TAP_RTI);\r
200         virtex2_set_instr(virtex2_info->chain_pos, 0x3f); /* BYPASS */\r
201         virtex2_set_instr(virtex2_info->chain_pos, 0x3f); /* BYPASS */\r
202         virtex2_set_instr(virtex2_info->chain_pos, 0xc); /* JSTART */\r
203         jtag_add_runtest(13, TAP_RTI);\r
204         virtex2_set_instr(virtex2_info->chain_pos, 0x3f); /* BYPASS */\r
205         jtag_execute_queue();\r
206 \r
207         return ERROR_OK;\r
208 }\r
209 \r
210 int virtex2_handle_read_stat_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
211 {\r
212         pld_device_t *device;\r
213         virtex2_pld_device_t *virtex2_info;\r
214         u32 status;\r
215         \r
216         if (argc < 1)\r
217         {\r
218                 command_print(cmd_ctx, "usage: virtex2 read_stat <num>");\r
219                 return ERROR_OK;\r
220         }\r
221         \r
222         device = get_pld_device_by_num(strtoul(args[0], NULL, 0));\r
223         if (!device)\r
224         {\r
225                 command_print(cmd_ctx, "pld device '#%s' is out of bounds", args[0]);\r
226                 return ERROR_OK;\r
227         }\r
228 \r
229         virtex2_info = device->driver_priv;\r
230         \r
231         virtex2_read_stat(device, &status);\r
232         \r
233         command_print(cmd_ctx, "virtex2 status register: 0x%8.8x", status);\r
234         \r
235         return ERROR_OK;\r
236 }\r
237 \r
238 int virtex2_register_commands(struct command_context_s *cmd_ctx)\r
239 {\r
240         command_t *virtex2_cmd = register_command(cmd_ctx, NULL, "virtex2", NULL, COMMAND_ANY, "virtex2 specific commands");\r
241 \r
242         register_command(cmd_ctx, virtex2_cmd, "read_stat", virtex2_handle_read_stat_command, COMMAND_EXEC,\r
243                                          "read Virtex-II status register");\r
244 \r
245         return ERROR_OK;\r
246 }\r
247 \r
248 int virtex2_pld_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct pld_device_s *pld_device)\r
249 {\r
250         virtex2_pld_device_t *virtex2_info;\r
251         \r
252         if (argc < 2)\r
253         {\r
254                 WARNING("incomplete pld device 'virtex2' configuration");\r
255                 return ERROR_PLD_DEVICE_INVALID;\r
256         }\r
257         \r
258         virtex2_info = malloc(sizeof(virtex2_pld_device_t));\r
259         pld_device->driver_priv = virtex2_info;\r
260         \r
261         virtex2_info->chain_pos = strtoul(args[1], NULL, 0);\r
262         \r
263         return ERROR_OK;\r
264 }\r