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