1 /*
2 * Freescale mpc8313 compatible bus driver via BSR
3 * Copyright (C) 2011 Miklós Márton
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18 * 02111-1307, USA.
19 *
20 * Written by Miklós Márton <martonmiklosqdev@gmail.com>, 2011.
21 */
22
23 #include <sysdep.h>
24
25 #include <stdlib.h>
26 #include <stdint.h>
27 #include <string.h>
28
29 #include <urjtag/part.h>
30 #include <urjtag/chain.h>
31 #include <urjtag/bus.h>
32 #include <urjtag/bssignal.h>
33
34 #include "buses.h"
35 #include "generic_bus.h"
36
37 #define BUS_WIDTH 16
38 #define A_WIDTH 26
39
40 typedef struct
41 {
42 uint32_t last_adr;
43
44 urj_part_signal_t *la[A_WIDTH];
45 urj_part_signal_t *lad[BUS_WIDTH];
46 urj_part_signal_t *ncs;
47 urj_part_signal_t *nwe;
48 urj_part_signal_t *nfoe;
49 urj_part_signal_t *nwp;
50 int lbc_num_d;
51 char revbits;
52 } bus_params_t;
53
54 #define LAST_ADR ((bus_params_t *) bus->params)->last_adr
55
56 #define LA ((bus_params_t *) bus->params)->la
57 #define LAD ((bus_params_t *) bus->params)->lad
58 #define nCS ((bus_params_t *) bus->params)->ncs
59 #define nWE ((bus_params_t *) bus->params)->nwe
60 #define nFOE ((bus_params_t *) bus->params)->nfoe
61 #define nWP ((bus_params_t *) bus->params)->nwp
62 #define REVBITS ((bus_params_t *) bus->params)->revbits
63
64 /**
65 * bus->driver->(*new_bus)
66 *
67 */
68 static urj_bus_t *
mpc8313_bus_new(urj_chain_t * chain,const urj_bus_driver_t * driver,const urj_param_t * cmd_params[])69 mpc8313_bus_new (urj_chain_t *chain, const urj_bus_driver_t *driver,
70 const urj_param_t *cmd_params[])
71 {
72 urj_bus_t *bus;
73 bus_params_t *bp;
74 urj_part_t *part;
75 char buff[10];
76 int i;
77 int failed = 0;
78 const char *nwppin = NULL, *noepin = NULL, *ncspin = NULL, *nwepin = NULL;
79
80 bus = urj_bus_generic_new (chain, driver, sizeof (bus_params_t));
81 REVBITS = 0;
82
83 for (i = 0; cmd_params[i] != NULL; i++)
84 {
85 switch (cmd_params[i]->key)
86 {
87
88 case URJ_BUS_PARAM_KEY_HELP:
89 urj_log (URJ_LOG_LEVEL_NORMAL,
90 _("Usage: initbus mpc8313 [NOE=NOE] [NWE=NWE] [NCS=NCS]\n\n"
91 " NOE signal name to control output enable pin (LGPL2 for e.g.)\n"
92 " NWE signal name to control write enable pin (default - LWE_B0)\n"
93 " NCS signal name for the bus Chip select (default - LCS_B0)\n"
94 " REVBITS reverse bits in data bus (default - no)\n"
95 " NWP signal name to control write protection pin if it neccessary (for e.g. TSEC2_RXD3)\n"));
96 return NULL;
97 case URJ_BUS_PARAM_KEY_NWP:
98 nwppin = cmd_params[i]->value.string;
99 break;
100 case URJ_BUS_PARAM_KEY_NCS:
101 ncspin = cmd_params[i]->value.string;
102 break;
103 case URJ_BUS_PARAM_KEY_NOE:
104 noepin = cmd_params[i]->value.string;
105 break;
106 case URJ_BUS_PARAM_KEY_NWE:
107 nwepin = cmd_params[i]->value.string;
108 break;
109 case URJ_BUS_PARAM_KEY_REVBITS:
110 REVBITS = 1;
111 break;
112 default:
113 urj_error_set (URJ_ERROR_SYNTAX, "unrecognised bus parameter '%s'",
114 urj_param_string(&urj_bus_param_list, cmd_params[i]));
115 return NULL;
116 }
117 }
118
119 if (bus == NULL)
120 return NULL;
121
122 bp = bus->params;
123 bp->lbc_num_d = 16;
124
125 part = bus->part;
126
127 urj_part_set_instruction (part, "SAMPLE/PRELOAD");
128 urj_tap_chain_shift_instructions (chain);
129 urj_tap_chain_shift_data_registers (chain, 0);
130 urj_part_set_instruction (part, "EXTEST");
131 urj_tap_chain_shift_instructions (chain);
132 urj_tap_chain_shift_data_registers (chain, 1);
133
134 for (i = 0; i < A_WIDTH; i++)
135 {
136 sprintf (buff, "LA%d", i);
137 failed |= urj_bus_generic_attach_sig (part, &(LA[i]), buff);
138 }
139
140 for (i = 0; i < BUS_WIDTH; i++)
141 {
142 sprintf (buff, "LAD%d", i);
143 failed |= urj_bus_generic_attach_sig (part, &(LAD[i]), buff);
144 }
145
146 if (nwppin != NULL)
147 {
148 failed |= urj_bus_generic_attach_sig (part, &(nWP), nwppin);
149 urj_part_set_signal_high (part, nWP);
150 }
151
152 if (noepin == NULL)
153 failed = 255;
154 else
155 failed |= urj_bus_generic_attach_sig (part, &(nFOE), noepin);
156
157 if (nwepin == NULL)
158 failed |= urj_bus_generic_attach_sig (part, &(nWE), "LWE_B0");
159 else
160 failed |= urj_bus_generic_attach_sig (part, &(nWE), nwepin);
161
162 if (ncspin == NULL)
163 failed |= urj_bus_generic_attach_sig (part, &(nCS), "LCS_B0");
164 else
165 failed |= urj_bus_generic_attach_sig (part, &(nCS), ncspin);
166
167 if (failed)
168 {
169 urj_bus_generic_free (bus);
170 return NULL;
171 }
172
173 return bus;
174 }
175
176 /**
177 * bus->driver->(*printinfo)
178 *
179 */
180 static void
mpc8313_bus_printinfo(urj_log_level_t ll,urj_bus_t * bus)181 mpc8313_bus_printinfo (urj_log_level_t ll, urj_bus_t *bus)
182 {
183 int i;
184
185 for (i = 0; i < bus->chain->parts->len; i++)
186 if (bus->part == bus->chain->parts->parts[i])
187 break;
188 urj_log (ll, _("Freescale MPC8313 compatible bus driver via BSR (JTAG part No. %d)\n"),
189 i);
190 }
191
192 /**
193 * bus->driver->(*area)
194 *
195 */
196 static int
mpc8313_bus_area(urj_bus_t * bus,uint32_t adr,urj_bus_area_t * area)197 mpc8313_bus_area (urj_bus_t *bus, uint32_t adr, urj_bus_area_t *area)
198 {
199 bus_params_t *bp = bus->params;
200
201 area->description = N_("Local Bus Controller");
202 area->start = UINT32_C (0x00000000);
203 area->length = UINT64_C (0x40000000);
204 area->width = bp->lbc_num_d;
205
206 return URJ_STATUS_OK;
207 }
208
209 static void
setup_address(urj_bus_t * bus,uint32_t a)210 setup_address (urj_bus_t *bus, uint32_t a)
211 {
212 int i;
213 urj_part_t *p = bus->part;
214
215 for (i = 0; i < A_WIDTH ; i++)
216 urj_part_set_signal (p, LA[A_WIDTH - 1 - i], 1, (a >> i) & 1);
217 }
218
219 static void
set_data_in(urj_bus_t * bus,uint32_t adr)220 set_data_in (urj_bus_t *bus, uint32_t adr)
221 {
222 bus_params_t *bp = bus->params;
223 urj_part_t *p = bus->part;
224 urj_bus_area_t area;
225 int i;
226
227 mpc8313_bus_area (bus, adr, &area);
228 if (area.width > bp->lbc_num_d)
229 return;
230
231 for (i = 0; i < area.width; i++)
232 urj_part_set_signal_input (p, LAD[i]);
233
234 }
235
236 static void
setup_data(urj_bus_t * bus,uint32_t adr,uint32_t d)237 setup_data (urj_bus_t *bus, uint32_t adr, uint32_t d)
238 {
239 int i;
240 urj_part_t *p = bus->part;
241
242 for (i = 0; i < BUS_WIDTH; i++)
243 urj_part_set_signal (p, LAD[i], 1,
244 (d >> ((REVBITS == 1) ? BUS_WIDTH - 1 - i : i)) &
245 1);
246 }
247
248 static uint32_t
get_data(urj_bus_t * bus,uint32_t adr)249 get_data (urj_bus_t *bus, uint32_t adr)
250 {
251 bus_params_t *bp = bus->params;
252 urj_part_t *p = bus->part;
253 urj_bus_area_t area;
254 uint32_t d = 0;
255 int i;
256
257 mpc8313_bus_area (bus, adr, &area);
258
259 for (i = 0; i <= bp->lbc_num_d; i++)
260 d |= (uint32_t) (urj_part_get_signal (p, LAD[i]) <<
261 (REVBITS ? BUS_WIDTH - 1 - i : i));
262
263 return d;
264 }
265
266 /**
267 * bus->driver->(*read_start)
268 *
269 */
270 static int
mpc8313_bus_read_start(urj_bus_t * bus,uint32_t adr)271 mpc8313_bus_read_start (urj_bus_t *bus, uint32_t adr)
272 {
273 urj_part_t *p = bus->part;
274
275 LAST_ADR = adr;
276
277 /* see Figure 6-45 in [1] */
278 urj_part_set_signal_low (p, nCS);
279 urj_part_set_signal_high (p, nWE);
280 urj_part_set_signal_low (p, nFOE);
281
282 setup_address (bus, adr);
283 set_data_in (bus, adr);
284
285 urj_tap_chain_shift_data_registers (bus->chain, 0);
286
287 return URJ_STATUS_OK;
288 }
289
290 /**
291 * bus->driver->(*read_next)
292 *
293 */
294 static uint32_t
mpc8313_bus_read_next(urj_bus_t * bus,uint32_t adr)295 mpc8313_bus_read_next (urj_bus_t *bus, uint32_t adr)
296 {
297 uint32_t d;
298
299 setup_address (bus, adr);
300 urj_tap_chain_shift_data_registers (bus->chain, 1);
301
302 d = get_data (bus, LAST_ADR);
303 LAST_ADR = adr;
304 return d;
305 }
306
307 /**
308 * bus->driver->(*read_end)
309 *
310 */
311 static uint32_t
mpc8313_bus_read_end(urj_bus_t * bus)312 mpc8313_bus_read_end (urj_bus_t *bus)
313 {
314 urj_part_t *p = bus->part;
315
316 urj_part_set_signal_high (p, nCS);
317 urj_part_set_signal_high (p, nFOE);
318
319 urj_tap_chain_shift_data_registers (bus->chain, 1);
320
321 return get_data (bus, LAST_ADR);
322 }
323
324 /**
325 * bus->driver->(*write)
326 *
327 */
328 static void
mpc8313_bus_write(urj_bus_t * bus,uint32_t adr,uint32_t data)329 mpc8313_bus_write (urj_bus_t *bus, uint32_t adr, uint32_t data)
330 {
331 urj_part_t *p = bus->part;
332
333 LAST_ADR = adr;
334
335
336 /* see Figure 6-47 in [1] */
337 urj_part_set_signal_low (p, nCS);
338 urj_part_set_signal_high (p, nWE);
339 urj_part_set_signal_high (p, nFOE);
340
341 if (nWP != NULL)
342 urj_part_set_signal_low (p, nWP);
343
344 setup_address (bus, adr);
345
346 setup_data (bus, adr, data);
347
348 urj_tap_chain_shift_data_registers (bus->chain, 0);
349
350 urj_part_set_signal_low (p, nWE);
351 urj_tap_chain_shift_data_registers (bus->chain, 0);
352 urj_part_set_signal_high (p, nWE);
353 urj_part_set_signal_high (p, nCS);
354 urj_tap_chain_shift_data_registers (bus->chain, 0);
355 }
356
357 const urj_bus_driver_t urj_bus_mpc8313_bus = {
358 "mpc8313",
359 N_("Motorola MPC8313 compatible bus driver via BSR"),
360 mpc8313_bus_new,
361 urj_bus_generic_free,
362 mpc8313_bus_printinfo,
363 urj_bus_generic_prepare_extest,
364 mpc8313_bus_area,
365 mpc8313_bus_read_start,
366 mpc8313_bus_read_next,
367 mpc8313_bus_read_end,
368 urj_bus_generic_read,
369 urj_bus_generic_write_start,
370 mpc8313_bus_write,
371 urj_bus_generic_no_init,
372 urj_bus_generic_no_enable,
373 urj_bus_generic_no_disable,
374 URJ_BUS_TYPE_PARALLEL,
375 };
376