1 /*
2 * Freescale MPC837X compatible bus driver via BSR
3 * Copyright (C) 2010 Andrzej Jalowiecki
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 *
21 * Documentation:
22 * [1] Freescale, "Freescale MPC837x Users Guide"
23 * Order Number: MPC8379UG
24 *
25 */
26
27 #include "sysdep.h"
28
29 #include <stdlib.h>
30 #include <stdint.h>
31 #include <string.h>
32
33 #include <urjtag/chain.h>
34 #include <urjtag/part.h>
35 #include <urjtag/bus.h>
36 #include <urjtag/bssignal.h>
37
38 #include "buses.h"
39 #include "generic_bus.h"
40
41 #define LBC_NUM_LCS 4
42 #define LBC_NUM_LWE 4
43 #define LBC_NUM_LAD 32
44
45 typedef struct {
46 uint32_t last_adr;
47 urj_part_signal_t *nlcs[LBC_NUM_LCS];
48 urj_part_signal_t *lad[LBC_NUM_LAD];
49 urj_part_signal_t *la[LBC_NUM_LAD];
50 urj_part_signal_t *nlwe[LBC_NUM_LWE];
51 urj_part_signal_t *nloe;
52 urj_part_signal_t *ale;
53 urj_part_signal_t *lbctl;
54 int lbc_muxed;
55 int lbc_num_ad;
56 int lbc_num_d;
57 } bus_params_t;
58
59 #define LAST_ADR ((bus_params_t *) bus->params)->last_adr /* Last used address */
60 #define nCS ((bus_params_t *) bus->params)->nlcs /* Chipselect# */
61 #define nWE ((bus_params_t *) bus->params)->nlwe /* Write enable# */
62 #define nOE ((bus_params_t *) bus->params)->nloe /* Output enable# */
63 #define ALE ((bus_params_t *) bus->params)->ale /* Addres strobe */
64 #define BCTL ((bus_params_t *) bus->params)->lbctl /* Write /Read# */
65
66 #define LAD ((bus_params_t *) bus->params)->lad /* Addres/Data Bus Mux */
67 #define LA ((bus_params_t *) bus->params)->la /* Addres Bus nonMux */
68
69 /**
70 * bus->driver->(*new_bus)
71 *
72 */
73 static urj_bus_t *
mpc837x_bus_new(urj_chain_t * chain,const urj_bus_driver_t * driver,const urj_param_t * cmd_params[])74 mpc837x_bus_new (urj_chain_t *chain, const urj_bus_driver_t *driver,
75 const urj_param_t *cmd_params[])
76 {
77 urj_bus_t *bus;
78 bus_params_t *bp;
79 urj_part_t *part;
80 char buff[10];
81 int i;
82 int failed = 0;
83
84 bus = urj_bus_generic_new (chain, driver, sizeof (bus_params_t));
85 if (bus == NULL)
86 return NULL;
87
88 part = bus->part;
89 bp = bus->params;
90
91 /* default values */
92 bp->lbc_muxed = 0;
93 bp->lbc_num_d = 8;
94 bp->lbc_num_ad = 25;
95
96 for (i = 0; cmd_params[i] != NULL; i++)
97 {
98 switch (cmd_params[i]->key)
99 {
100 case URJ_BUS_PARAM_KEY_HELP:
101 urj_bus_generic_free (bus);
102 urj_log (URJ_LOG_LEVEL_NORMAL,
103 _("Usage: initbus mpc837x [mux] [width=WIDTH]\n"
104 " MUX multiplexed data bus (default no)\n"
105 " WIDTH data bus width - 8, 16, 32 (default 8)\n"));
106 return NULL;
107 case URJ_BUS_PARAM_KEY_MUX:
108 bp->lbc_muxed = 1;
109 break;
110 case URJ_BUS_PARAM_KEY_WIDTH:
111 switch (cmd_params[i]->value.lu)
112 {
113 case 8:
114 bp->lbc_num_d = 8;
115 break;
116 case 16:
117 bp->lbc_num_d = 16;
118 break;
119 case 32:
120 bp->lbc_num_d = 32;
121 break;
122 default:
123 urj_error_set (URJ_ERROR_UNSUPPORTED,
124 _(" Only 8, 16, 32 bus width are suported\n"));
125 }
126 break;
127 default:
128 urj_bus_generic_free (bus);
129 urj_error_set (URJ_ERROR_SYNTAX, "unrecognised bus parameter '%s'",
130 urj_param_string (&urj_bus_param_list, cmd_params[i]));
131 return NULL;
132 }
133 }
134
135 if (!bp->lbc_muxed && (bp->lbc_num_d > 16))
136 {
137 urj_bus_generic_free (bus);
138 urj_error_set (URJ_ERROR_UNSUPPORTED,
139 _(" Only 8 and 16 non multiplexed bus width are suported\n"));
140 return NULL;
141 }
142
143 if (bp->lbc_muxed)
144 bp->lbc_num_ad = 32;
145
146 /* Get the signals */
147 if (bp->lbc_muxed)
148 {
149 failed |= urj_bus_generic_attach_sig (part, &(ALE), "LALE");
150 for (i = 0; i < LBC_NUM_LAD; i++)
151 {
152 sprintf (buff, "LAD%d", i);
153 failed |= urj_bus_generic_attach_sig (part, &(LAD[i]), buff);
154 }
155 }
156 else
157 {
158 failed |= urj_bus_generic_attach_sig (part, &(LA[7]), "LDP2");
159 failed |= urj_bus_generic_attach_sig (part, &(LA[8]), "LDP3");
160 failed |= urj_bus_generic_attach_sig (part, &(LA[9]), "LGPL5");
161 failed |= urj_bus_generic_attach_sig (part, &(LA[10]), "LALE");
162 for (i = 11; i < 27; i++)
163 {
164 sprintf (buff, "LAD%d", i + 5);
165 failed |= urj_bus_generic_attach_sig (part, &(LA[i]), buff);
166 }
167 }
168
169 for (i = 27; i < LBC_NUM_LAD; i++)
170 {
171 sprintf (buff, "LA%d", i);
172 failed |= urj_bus_generic_attach_sig (part, &(LA[i]), buff);
173 }
174
175 for (i = 0; i < LBC_NUM_LCS; i++)
176 {
177 sprintf (buff, "LCS_B%d", i);
178 failed |= urj_bus_generic_attach_sig (part, &(nCS[i]), buff);
179 }
180
181 for (i = 0; i < LBC_NUM_LWE; i++)
182 {
183 sprintf (buff, "LWE_B%d", i);
184 failed |= urj_bus_generic_attach_sig (part, &(nWE[i]), buff);
185 }
186
187 failed |= urj_bus_generic_attach_sig (part, &(nOE), "LGPL2");
188 failed |= urj_bus_generic_attach_sig (part, &(BCTL), "LBCTL");
189
190 if (failed)
191 {
192 urj_bus_generic_free (bus);
193 return NULL;
194 }
195
196 urj_log (URJ_LOG_LEVEL_NORMAL,
197 "%sMUXed %db address, %db data bus\n",
198 ((bp->lbc_muxed) ? "" : "Non-"),
199 bp->lbc_num_ad, bp->lbc_num_d);
200
201 return bus;
202 }
203
204 /**
205 * bus->driver->(*printinfo)
206 *
207 */
208 static void
mpc837x_bus_printinfo(urj_log_level_t ll,urj_bus_t * bus)209 mpc837x_bus_printinfo (urj_log_level_t ll, urj_bus_t *bus)
210 {
211 int i;
212
213 for (i = 0; i < bus->chain->parts->len; i++)
214 if (bus->part == bus->chain->parts->parts[i])
215 break;
216 urj_log (ll, _("Freescale MPC837X compatible bus driver via BSR (JTAG part No. %d)\n"), i);
217 }
218
219 /**
220 * bus->driver->(*area)
221 *
222 */
223 static int
mpc837x_bus_area(urj_bus_t * bus,uint32_t adr,urj_bus_area_t * area)224 mpc837x_bus_area (urj_bus_t *bus, uint32_t adr, urj_bus_area_t *area)
225 {
226 bus_params_t *bp = bus->params;
227
228 area->description = N_("Local Bus Controller");
229 area->start = UINT32_C(0x00000000);
230 area->length = UINT64_C(0x100000000);
231 area->width = bp->lbc_num_d;
232 return URJ_STATUS_OK;
233 }
234
235 static void
setup_address(urj_bus_t * bus,uint32_t a)236 setup_address (urj_bus_t *bus, uint32_t a)
237 {
238 bus_params_t *bp = bus->params;
239 urj_part_t *p = bus->part;
240 int i;
241
242 if (bp->lbc_muxed)
243 {
244 for (i = 0; i < bp->lbc_num_ad; i++)
245 urj_part_set_signal (p, LAD[LBC_NUM_LAD - i - 1], 1, (a >> i) & 1);
246
247 for (i = 0; i < 5; i++)
248 urj_part_set_signal (p, LA[LBC_NUM_LAD - i - 1], 1, (a >> i) & 1);
249 }
250 else
251 {
252 for (i = 0; i < bp->lbc_num_ad; i++)
253 urj_part_set_signal (p, LA[LBC_NUM_LAD - i - 1], 1, (a >> i) & 1);
254 }
255 }
256
257 static void
set_data_in(urj_bus_t * bus,uint32_t adr)258 set_data_in (urj_bus_t *bus, uint32_t adr)
259 {
260 bus_params_t *bp = bus->params;
261 urj_part_t *p = bus->part;
262 urj_bus_area_t area;
263 int i;
264
265 mpc837x_bus_area (bus, adr, &area);
266 if (area.width > bp->lbc_num_d)
267 return;
268
269 for (i = 0; i < area.width; i++)
270 urj_part_set_signal_input (p, LAD[bp->lbc_num_d - i - 1]);
271 }
272
273 static void
setup_data(urj_bus_t * bus,uint32_t adr,uint32_t d)274 setup_data (urj_bus_t *bus, uint32_t adr, uint32_t d)
275 {
276 bus_params_t *bp = bus->params;
277 urj_part_t *p = bus->part;
278 urj_bus_area_t area;
279 int i;
280
281 mpc837x_bus_area (bus, adr, &area);
282 if (area.width > bp->lbc_num_d)
283 return;
284
285 for (i = 0; i < area.width; i++)
286 urj_part_set_signal (p, LAD[bp->lbc_num_d - i - 1], 1, (d >> i) & 1);
287 }
288
289 static uint32_t
get_data(urj_bus_t * bus,uint32_t adr)290 get_data (urj_bus_t *bus, uint32_t adr)
291 {
292 bus_params_t *bp = bus->params;
293 urj_part_t *p = bus->part;
294 urj_bus_area_t area;
295 uint32_t d = 0;
296 int i;
297
298 mpc837x_bus_area (bus, adr, &area);
299 if (area.width > bp->lbc_num_d)
300 return 0;
301
302 for (i = 0; i < area.width; i++)
303 d |= (urj_part_get_signal (p, LAD[bp->lbc_num_d - i - 1]) << i);
304 return d;
305 }
306
307 /**
308 * bus->driver->(*read_start)
309 *
310 */
311 static int
mpc837x_bus_read_start(urj_bus_t * bus,uint32_t adr)312 mpc837x_bus_read_start (urj_bus_t *bus, uint32_t adr)
313 {
314 bus_params_t *bp = bus->params;
315 urj_chain_t *chain = bus->chain;
316 urj_part_t *p = bus->part;
317 uint8_t cs;
318 int i;
319
320 LAST_ADR = adr;
321 cs = 0;
322
323 for (i = 0; i < LBC_NUM_LCS; i++)
324 urj_part_set_signal (p, nCS[i], 1, !(cs == i));
325
326 for (i = 0; i < LBC_NUM_LWE; i++)
327 urj_part_set_signal_high (p, nWE[i]);
328
329 setup_address (bus, adr);
330
331 if (bp->lbc_muxed)
332 {
333 urj_part_set_signal_high (p, BCTL); /* Address Out */
334 urj_part_set_signal_high (p, ALE);
335 urj_part_set_signal_high (p, nOE);
336 urj_tap_chain_shift_data_registers (chain, 0);
337 urj_part_set_signal_low (p, BCTL); /* Data In */
338 urj_part_set_signal_low (p, ALE);
339 urj_part_set_signal_low (p, nOE);
340 }
341 else
342 {
343 urj_part_set_signal_low (p, BCTL); /* Data In */
344 urj_part_set_signal_low (p, nOE);
345 set_data_in (bus, adr);
346 }
347
348 urj_tap_chain_shift_data_registers (chain, 0);
349
350 return URJ_STATUS_OK;
351 }
352
353 /**
354 * bus->driver->(*read_next)
355 *
356 */
357 static uint32_t
mpc837x_bus_read_next(urj_bus_t * bus,uint32_t adr)358 mpc837x_bus_read_next (urj_bus_t *bus, uint32_t adr)
359 {
360 bus_params_t *bp = bus->params;
361 urj_chain_t *chain = bus->chain;
362 urj_part_t *p = bus->part;
363 uint32_t d;
364
365 if (bp->lbc_muxed)
366 {
367 set_data_in (bus, adr);
368 urj_tap_chain_shift_data_registers (chain, 0);
369
370 urj_tap_chain_shift_data_registers (chain, 1);
371 d = get_data (bus, LAST_ADR);
372
373 setup_address (bus, adr);
374 LAST_ADR = adr;
375
376 urj_part_set_signal_high (p, BCTL); /* Address Out */
377 urj_part_set_signal_high (p, ALE);
378 urj_part_set_signal_high (p, nOE);
379 urj_tap_chain_shift_data_registers (chain, 0);
380
381 urj_part_set_signal_low (p, BCTL); /* Data In */
382 urj_part_set_signal_low (p, ALE);
383 urj_part_set_signal_low (p, nOE);
384 urj_tap_chain_shift_data_registers (chain, 0);
385 }
386 else
387 {
388 setup_address (bus, adr); /* Data In */
389 urj_tap_chain_shift_data_registers (chain, 1);
390 d = get_data (bus, LAST_ADR);
391 }
392
393 LAST_ADR = adr;
394 return d;
395 }
396
397 /**
398 * bus->driver->(*read_end)
399 *
400 */
401 static uint32_t
mpc837x_bus_read_end(urj_bus_t * bus)402 mpc837x_bus_read_end (urj_bus_t *bus)
403 {
404 bus_params_t *bp = bus->params;
405 urj_chain_t *chain = bus->chain;
406 urj_part_t *p = bus->part;
407 int i;
408
409 if (bp->lbc_muxed)
410 {
411 set_data_in (bus, LAST_ADR);
412 urj_tap_chain_shift_data_registers (chain, 0);
413 urj_part_set_signal_high (p, ALE);
414 }
415
416 for (i = 0; i < LBC_NUM_LCS; i++)
417 urj_part_set_signal_high (p, nCS[i]);
418
419 urj_part_set_signal_high (p, BCTL);
420 urj_part_set_signal_high (p, nOE);
421
422 urj_tap_chain_shift_data_registers (chain, 1);
423
424 return get_data (bus, LAST_ADR);
425 }
426
427 /**
428 * bus->driver->(*write)
429 *
430 */
431 static void
mpc837x_bus_write(urj_bus_t * bus,uint32_t adr,uint32_t data)432 mpc837x_bus_write (urj_bus_t *bus, uint32_t adr, uint32_t data)
433 {
434 bus_params_t *bp = bus->params;
435 urj_chain_t *chain = bus->chain;
436 urj_part_t *p = bus->part;
437 urj_bus_area_t area;
438 uint8_t cs;
439 int i;
440
441 mpc837x_bus_area (bus, adr, &area);
442 if (area.width > bp->lbc_num_d)
443 return;
444
445 cs = 0;
446 urj_part_set_signal_high (p, BCTL);
447 urj_part_set_signal_high (p, nOE);
448
449 for (i = 0; i < LBC_NUM_LWE; i++)
450 urj_part_set_signal_high (p, nWE[i]);
451
452 if (bp->lbc_muxed)
453 {
454 setup_address (bus, adr);
455 urj_part_set_signal_high (p, ALE);
456 urj_tap_chain_shift_data_registers (chain, 0);
457 urj_part_set_signal_low (p, ALE);
458 urj_tap_chain_shift_data_registers (chain, 0);
459 }
460 else
461 setup_address (bus, adr);
462
463 for (i = 0; i < LBC_NUM_LCS; i++)
464 urj_part_set_signal (p, nCS[i], 1, !(cs == i));
465
466 setup_data (bus, adr, data);
467
468 urj_tap_chain_shift_data_registers (chain, 0);
469
470 switch (area.width)
471 {
472 case 32:
473 urj_part_set_signal_low (p, nWE[3]);
474 urj_part_set_signal_low (p, nWE[2]);
475 case 16:
476 urj_part_set_signal_low (p, nWE[1]);
477 case 8:
478 urj_part_set_signal_low (p, nWE[0]);
479 default:
480 break;
481 }
482
483 urj_tap_chain_shift_data_registers (chain, 0);
484
485 for (i = 0; i < LBC_NUM_LWE; i++)
486 urj_part_set_signal_high (p, nWE[i]);
487
488 urj_tap_chain_shift_data_registers (chain, 0);
489 }
490
491 const urj_bus_driver_t urj_bus_mpc837x_bus = {
492 "mpc837x",
493 N_("Freescale MPC837x compatible bus driver via BSR, parameter: [mux] [width]"),
494 mpc837x_bus_new,
495 urj_bus_generic_free,
496 mpc837x_bus_printinfo,
497 urj_bus_generic_prepare_extest,
498 mpc837x_bus_area,
499 mpc837x_bus_read_start,
500 mpc837x_bus_read_next,
501 mpc837x_bus_read_end,
502 urj_bus_generic_read,
503 urj_bus_generic_write_start,
504 mpc837x_bus_write,
505 urj_bus_generic_no_init,
506 urj_bus_generic_no_enable,
507 urj_bus_generic_no_disable,
508 URJ_BUS_TYPE_PARALLEL,
509 };
510