1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  JTAG console device			File: dev_jtag.c
5    *
6    *  This file supports a serial-port-style console over the
7    *  BCM12500's JTAG port.
8    *
9    *  Author:  Mitch Lichtenberg
10    *           Kip Walker
11    *
12    *********************************************************************
13    *
14    *  Copyright 2000,2001,2002,2003
15    *  Broadcom Corporation. All rights reserved.
16    *
17    *  This software is furnished under license and may be used and
18    *  copied only in accordance with the following terms and
19    *  conditions.  Subject to these conditions, you may download,
20    *  copy, install, use, modify and distribute modified or unmodified
21    *  copies of this software in source and/or binary form.  No title
22    *  or ownership is transferred hereby.
23    *
24    *  1) Any source code used, modified or distributed must reproduce
25    *     and retain this copyright notice and list of conditions
26    *     as they appear in the source file.
27    *
28    *  2) No right is granted to use any trade name, trademark, or
29    *     logo of Broadcom Corporation.  The "Broadcom Corporation"
30    *     name may not be used to endorse or promote products derived
31    *     from this software without the prior written permission of
32    *     Broadcom Corporation.
33    *
34    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
35    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
36    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
37    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
38    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
39    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
40    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
41    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
42    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
44    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
45    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
46    *     THE POSSIBILITY OF SUCH DAMAGE.
47    ********************************************************************* */
48
49
50#include "cfe.h"
51#include "sbmips.h"
52#include "sb1250_defs.h"
53
54/* XXX How can I share these definitions with console clients? */
55#define JTAG_CONS_CONTROL  0x00
56#define JTAG_CONS_INPUT    0x20
57#define JTAG_CONS_OUTPUT   0x40
58#define JTAG_CONS_MAGICNUM 0x50FABEEF12349873LL
59
60#define jtag_input_len(data)    (((data) >> 56) & 0xFF)
61
62/*  *********************************************************************
63    *  Prototypes
64    ********************************************************************* */
65
66static void jtag_probe(cfe_driver_t *drv,
67			      unsigned long probe_a, unsigned long probe_b,
68			      void *probe_ptr);
69
70
71static int jtag_open(cfe_devctx_t *ctx);
72static int jtag_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
73static int jtag_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
74static int jtag_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
75static int jtag_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
76static int jtag_close(cfe_devctx_t *ctx);
77
78/*  *********************************************************************
79    *  Device dispatch table
80    ********************************************************************* */
81
82const static cfe_devdisp_t jtag_dispatch = {
83    jtag_open,
84    jtag_read,
85    jtag_inpstat,
86    jtag_write,
87    jtag_ioctl,
88    jtag_close,
89    NULL,
90    NULL
91};
92
93/*  *********************************************************************
94    *  Device descriptor
95    ********************************************************************* */
96
97const cfe_driver_t jtagconsole = {
98    "JTAG serial console",
99    "jtag",
100    CFE_DEV_SERIAL,
101    &jtag_dispatch,
102    jtag_probe
103};
104
105/*  *********************************************************************
106    *  Local constants and structures
107    ********************************************************************* */
108
109
110typedef struct jtag_s {
111    unsigned long jtag_input;
112    unsigned long jtag_output;
113    unsigned long jtag_control;
114    uint64_t input_buf;
115    int waiting_input;
116} jtag_t;
117
118
119/*  *********************************************************************
120    *  jtag_probe(drv,probe_a,probe_b,probe_ptr)
121    *
122    *  Device "Probe" routine.  This routine creates the soft
123    *  context for the device and calls the attach routine.
124    *
125    *  Input parameters:
126    *  	   drv - driver structure
127    *  	   probe_a,probe_b,probe_ptr - probe args
128    *
129    *  Return value:
130    *  	   nothing
131    ********************************************************************* */
132
133
134static void jtag_probe(cfe_driver_t *drv,
135			  unsigned long probe_a,
136			  unsigned long probe_b,
137			  void *probe_ptr)
138{
139    jtag_t *softc;
140    char descr[80];
141
142    /*
143     * probe_a is the physical base address within JTAG space of the
144     * communications area.
145     */
146
147    softc = (jtag_t *) KMALLOC(sizeof(jtag_t),0);
148    if (softc) {
149	softc->jtag_input = probe_a + JTAG_CONS_INPUT;
150	softc->jtag_output = probe_a + JTAG_CONS_OUTPUT;
151	softc->jtag_control = probe_a + JTAG_CONS_CONTROL;
152        softc->waiting_input = 0;
153	xsprintf(descr,"%s at 0x%X",drv->drv_description,probe_a);
154	cfe_attach(drv,softc,NULL,descr);
155    }
156}
157
158
159
160/*  *********************************************************************
161    *  jtag_open(ctx)
162    *
163    *  Open the device
164    *
165    *  Input parameters:
166    *  	   ctx - device context
167    *
168    *  Return value:
169    *  	   0 if ok, else error code
170    ********************************************************************* */
171static int jtag_open(cfe_devctx_t *ctx)
172{
173    jtag_t *softc = ctx->dev_softc;
174    int64_t timer;
175    uint64_t magic;
176
177    TIMER_SET(timer, 120*CFE_HZ);
178    do {
179      POLL();
180      magic = SBREADCSR(softc->jtag_control);
181    } while ((magic == 0) && !TIMER_EXPIRED(timer));
182
183    if (magic != JTAG_CONS_MAGICNUM) {
184      return -1;
185    }
186
187    return 0;
188}
189
190/*  *********************************************************************
191    *  jtag_grab_dword(softc)
192    *
193    *  Get the next dword (if any) from the JTAG client.  (Local helper
194    *  function - not part of the device dispatch table).
195    *
196    *  Input parameters:
197    *  	   softc - jtag structure
198    ********************************************************************* */
199static void jtag_grab_dword(jtag_t *softc)
200{
201    uint64_t inbuf;
202
203    inbuf = SBREADCSR(softc->jtag_input);
204    softc->waiting_input = jtag_input_len(inbuf);
205    softc->input_buf = inbuf << 8;
206}
207
208/*  *********************************************************************
209    *  jtag_read(ctx,buffer)
210    *
211    *  Read data from the device
212    *
213    *  Input parameters:
214    *  	   ctx - device context
215    *  	   buffer - I/O buffer descriptor
216    *
217    *  Return value:
218    *  	   0 if successful, or <0 if error
219    ********************************************************************* */
220static int jtag_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
221{
222    jtag_t *softc = ctx->dev_softc;
223    hsaddr_t bptr;
224    int blen;
225    uint8_t b;
226
227    bptr = buffer->buf_ptr;
228    blen = buffer->buf_length;
229
230    /* If the caller always inpstats first, we don't need to do this!  */
231    if (softc->waiting_input == 0) {
232        jtag_grab_dword(softc);
233    }
234
235    while ((blen > 0) && (softc->waiting_input)) {
236        int bytes = blen > softc->waiting_input ? softc->waiting_input : blen;
237        int i;
238
239        /* Take min(waiting,blen) from input_buf */
240        for (i=0; i<bytes; i++) {
241	    b = (softc->input_buf >> 56) & 0xFF;
242	    hs_write8(bptr,b);
243	    bptr++;
244            softc->input_buf <<= 8;
245        }
246
247        softc->waiting_input -= bytes;
248        blen -= bytes;
249
250        if (softc->waiting_input == 0) {
251            /* Look for more */
252            jtag_grab_dword(softc);
253        }
254    }
255
256    buffer->buf_retlen = buffer->buf_length - blen;
257
258    return 0;
259}
260
261/*  *********************************************************************
262    *  jtag_inpstat(ctx,inpstat)
263    *
264    *  Determine if read data is available
265    *
266    *  Input parameters:
267    *  	   ctx - device context
268    *  	   inpstat - input status structure
269    *
270    *  Return value:
271    *  	   0
272    ********************************************************************* */
273
274static int jtag_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat)
275{
276    jtag_t *softc = ctx->dev_softc;
277
278    if (softc->waiting_input == 0) {
279        jtag_grab_dword(softc);
280    }
281
282    inpstat->inp_status = softc->waiting_input ? 1 : 0;
283
284    return 0;
285}
286
287/*  *********************************************************************
288    *  jtag_write(ctx,buffer)
289    *
290    *  Write data to the device
291    *
292    *  Input parameters:
293    *  	   ctx - device context
294    *  	   buffer - I/O buffer descriptor
295    *
296    *  Return value:
297    *  	   0 if successful, or <0 if error
298    ********************************************************************* */
299static int jtag_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
300{
301    jtag_t *softc = ctx->dev_softc;
302    hsaddr_t bptr;
303    uint8_t b;
304    int blen, bytes, i;
305    uint64_t data;
306
307    bptr = buffer->buf_ptr;
308    blen = buffer->buf_length;
309
310    while (blen > 0) {
311        bytes = (blen > 7) ? 7 : blen;
312        data = bytes;
313        for (i=0; i<bytes; i++) {
314            data <<= 8;
315	    b = hs_read8(bptr);
316	    bptr++;
317            data |= b;
318
319        }
320        if (bytes < 7)
321            data <<= 8 * (7-bytes);
322        blen -= bytes;
323        SBWRITECSR(softc->jtag_output, data);
324    }
325
326    buffer->buf_retlen = buffer->buf_length - blen; /* always 0 */
327    return 0;                   /* XXX blen? */
328}
329
330/*  *********************************************************************
331    *  jtag_ioctl(ctx,buffer)
332    *
333    *  Do I/O control operations
334    *
335    *  Input parameters:
336    *  	   ctx - device context
337    *  	   buffer - I/O control args
338    *
339    *  Return value:
340    *  	   0 if ok
341    *  	   else error code
342    ********************************************************************* */
343
344static int jtag_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
345{
346    return -1;
347}
348
349/*  *********************************************************************
350    *  jtag_close(ctx)
351    *
352    *  Close the device.
353    *
354    *  Input parameters:
355    *  	   ctx - device context
356    *
357    *  Return value:
358    *  	   0
359    ********************************************************************* */
360
361static int jtag_close(cfe_devctx_t *ctx)
362{
363    return 0;
364}
365
366
367