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