1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  PromICE console device			File: dev_promice.c
5    *
6    *  This device driver supports Grammar Engine's PromICE AI2
7    *  serial communications options.  With this console, you can
8    *  communicate with the firmware using only uncached reads in the
9    *  boot ROM space.  See Grammar Engine's PromICE manuals
10    *  for more information at http://www.gei.com
11    *
12    *  Author:  Mitch Lichtenberg
13    *
14    *********************************************************************
15    *
16    *  Copyright 2000,2001,2002,2003
17    *  Broadcom Corporation. All rights reserved.
18    *
19    *  This software is furnished under license and may be used and
20    *  copied only in accordance with the following terms and
21    *  conditions.  Subject to these conditions, you may download,
22    *  copy, install, use, modify and distribute modified or unmodified
23    *  copies of this software in source and/or binary form.  No title
24    *  or ownership is transferred hereby.
25    *
26    *  1) Any source code used, modified or distributed must reproduce
27    *     and retain this copyright notice and list of conditions
28    *     as they appear in the source file.
29    *
30    *  2) No right is granted to use any trade name, trademark, or
31    *     logo of Broadcom Corporation.  The "Broadcom Corporation"
32    *     name may not be used to endorse or promote products derived
33    *     from this software without the prior written permission of
34    *     Broadcom Corporation.
35    *
36    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
37    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
38    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
39    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
40    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
41    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
42    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
43    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
44    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
45    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
46    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
47    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
48    *     THE POSSIBILITY OF SUCH DAMAGE.
49    ********************************************************************* */
50
51
52/*
53 * Example PromICE initialization file:
54 *
55 * -----------------------
56 * output=com1
57 * pponly=lpt1
58 * rom=27040
59 * word=8
60 * file=cfe.srec
61 * ailoc 7FC00,9600
62 * -----------------------
63 *
64 * The offset specified in the 'ailoc' line must be the location where you
65 * will configure the AI2 serial port.  In this example, the ROM is assumed
66 * to be 512KB, and the AI2 serial port is at 511KB, or offset 0x7FC00.
67 * This area is filled with 0xCC to detect AI2's initialization sequence
68 * properly (see the PromICE manual).  You should connect your
69 * PromICE's serial port up to the PC and run a terminal emulator on it.
70 * The parallel port will be used for downloading data to the PromICE.
71 *
72 * If you have not connected the write line to the PromICE, then you must
73 * supply the AINODIRT_FLG bit in probe_b to turn off direct mode.
74 */
75
76
77#include "cfe.h"
78
79/*#define _AIDIRT_*/
80
81#define AINODIRT_FLG	0x100
82#define WORDSIZE_MASK	0x0FF
83
84/*  *********************************************************************
85    *  Prototypes
86    ********************************************************************* */
87
88static void promice_probe(cfe_driver_t *drv,
89			      unsigned long probe_a, unsigned long probe_b,
90			      void *probe_ptr);
91
92
93static int promice_open(cfe_devctx_t *ctx);
94static int promice_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
95static int promice_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
96static int promice_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
97static int promice_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
98static int promice_close(cfe_devctx_t *ctx);
99
100/*  *********************************************************************
101    *  Device dispatch table
102    ********************************************************************* */
103
104const static cfe_devdisp_t promice_dispatch = {
105    promice_open,
106    promice_read,
107    promice_inpstat,
108    promice_write,
109    promice_ioctl,
110    promice_close,
111    NULL,
112    NULL
113};
114
115/*  *********************************************************************
116    *  Device descriptor
117    ********************************************************************* */
118
119const cfe_driver_t promice_uart = {
120    "PromICE AI2 Serial Port",
121    "promice",
122    CFE_DEV_SERIAL,
123    &promice_dispatch,
124    promice_probe
125};
126
127/*  *********************************************************************
128    *  Local constants and structures
129    ********************************************************************* */
130
131/*
132 * If your PromICE is connected to a 32-bit host (emulating four
133 * flash ROMs) and the SB1250 is set to boot from that host, define
134 * the PROMICE_32BITS symbol to make sure the AI2 interface is
135 * configured correctly.
136 */
137
138/*#define PROMICE_32BITS*/
139
140#ifdef PROMICE_32BITS
141#define WORDSIZE	4
142#define WORDTYPE	uint32_t
143#else
144#define WORDSIZE	1
145#define WORDTYPE	uint8_t
146#endif
147
148
149#define ZERO_OFFSET	(0)
150#define ONE_OFFSET	(1)
151#define DATA_OFFSET	(2)
152#define STATUS_OFFSET	(3)
153
154#define TDA 0x01 	/* Target data available */
155#define HDA 0x02 	/* Host data available */
156#define OVR 0x04 	/* Host data overflow */
157
158typedef struct promice_s {
159    unsigned long ai2_addr;
160    unsigned int ai2_wordsize;
161    unsigned int ai2_aidirt;
162    volatile WORDTYPE *zero;
163    volatile WORDTYPE *one;
164    volatile WORDTYPE *data;
165    volatile WORDTYPE *status;
166} promice_t;
167
168
169/*  *********************************************************************
170    *  promice_probe(drv,probe_a,probe_b,probe_ptr)
171    *
172    *  Device "Probe" routine.  This routine creates the soft
173    *  context for the device and calls the attach routine.
174    *
175    *  Input parameters:
176    *  	   drv - driver structure
177    *  	   probe_a,probe_b,probe_ptr - probe args
178    *
179    *  Return value:
180    *  	   nothing
181    ********************************************************************* */
182
183
184static void promice_probe(cfe_driver_t *drv,
185			  unsigned long probe_a,
186			  unsigned long probe_b,
187			  void *probe_ptr)
188{
189    promice_t *softc;
190    char descr[80];
191
192    /*
193     * probe_a is the address in the ROM of the AI2 interface
194     * on the PromICE.
195     * probe_b is the word size (1,2,4)  (bottom 8 bits)
196     * probe_b also has the AINODIRT flag (bit #8)
197     *    (if set, we will NOT use direct mode)
198     */
199
200    softc = (promice_t *) KMALLOC(sizeof(promice_t),0);
201    if (softc) {
202	softc->ai2_addr = probe_a;
203	if (probe_b & WORDSIZE_MASK) softc->ai2_wordsize = probe_b;
204	else softc->ai2_wordsize = WORDSIZE;
205
206	if (probe_b & AINODIRT_FLG) softc->ai2_aidirt = FALSE;
207	else softc->ai2_aidirt = TRUE;
208
209	xsprintf(descr,"%s at 0x%X",drv->drv_description,probe_a);
210	cfe_attach(drv,softc,NULL,descr);
211	}
212}
213
214
215
216/*  *********************************************************************
217    *  promice_open(ctx)
218    *
219    *  Open the device
220    *
221    *  Input parameters:
222    *  	   ctx - device context
223    *
224    *  Return value:
225    *  	   0 if ok, else error code
226    ********************************************************************* */
227static int promice_open(cfe_devctx_t *ctx)
228{
229    promice_t *softc = ctx->dev_softc;
230    uint8_t dummy;
231
232    softc->zero   = (volatile WORDTYPE *)
233	UNCADDR(softc->ai2_addr + (ZERO_OFFSET*softc->ai2_wordsize));
234    softc->one    = (volatile WORDTYPE *)
235	UNCADDR(softc->ai2_addr + (ONE_OFFSET*softc->ai2_wordsize));
236    softc->data   = (volatile WORDTYPE *)
237	UNCADDR(softc->ai2_addr + (DATA_OFFSET*softc->ai2_wordsize));
238    softc->status = (volatile WORDTYPE *)
239	UNCADDR(softc->ai2_addr + (STATUS_OFFSET*softc->ai2_wordsize));
240
241    /*
242     * Wait for bit 3 to clear so we know the interface is ready.
243     */
244
245    while (*(softc->status) == 0xCC) ; 	/* NULL LOOP */
246
247    /*
248     * a dummy read is required to clear out the interface.
249     */
250
251    dummy = *(softc->data);
252
253    return 0;
254}
255
256/*  *********************************************************************
257    *  promice_read(ctx,buffer)
258    *
259    *  Read data from the device
260    *
261    *  Input parameters:
262    *  	   ctx - device context
263    *  	   buffer - I/O buffer descriptor
264    *
265    *  Return value:
266    *  	   number of bytes transferred, or <0 if error
267    ********************************************************************* */
268static int promice_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
269{
270    promice_t *softc = ctx->dev_softc;
271    hsaddr_t bptr;
272    uint8_t b;
273    int blen;
274
275    bptr = buffer->buf_ptr;
276    blen = buffer->buf_length;
277
278    while ((blen > 0) && (*(softc->status) & HDA)) {
279	b = *(softc->data);
280	hs_write8(bptr,b);
281	bptr++ ;
282	blen--;
283	}
284
285    buffer->buf_retlen = buffer->buf_length - blen;
286    return 0;
287}
288
289/*  *********************************************************************
290    *  promice_inpstat(ctx,inpstat)
291    *
292    *  Determine if read data is available
293    *
294    *  Input parameters:
295    *  	   ctx - device context
296    *  	   inpstat - input status structure
297    *
298    *  Return value:
299    *  	   0
300    ********************************************************************* */
301
302static int promice_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat)
303{
304    promice_t *softc = ctx->dev_softc;
305
306    inpstat->inp_status = (*(softc->status) & HDA) ? 1 : 0;
307
308    return 0;
309}
310
311/*  *********************************************************************
312    *  promice_write(ctx,buffer)
313    *
314    *  Write data to the device
315    *
316    *  Input parameters:
317    *  	   ctx - device context
318    *  	   buffer - I/O buffer descriptor
319    *
320    *  Return value:
321    *  	   number of bytes transferred, or <0 if error
322    ********************************************************************* */
323static int promice_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
324{
325    promice_t *softc = ctx->dev_softc;
326    hsaddr_t bptr;
327    int blen;
328    uint8_t data;
329    uint8_t dummy;
330    int count;
331
332    bptr = buffer->buf_ptr;
333    blen = buffer->buf_length;
334
335
336    /*
337     * The AI2 interface requires you to transmit characters
338     * one bit at a time.  First a '1' start bit,
339     * then 8 data bits (lsb first) then another '1' stop bit.
340     *
341     * Just reference the right memory location to transmit a bit.
342     */
343
344    while ((blen > 0) && !(*(softc->status) & TDA)) {
345
346	if (softc->ai2_aidirt) {
347	    data = hs_read8(bptr);
348	    bptr++;
349	    *(softc->zero) = data;
350	    }
351	else {
352	    dummy = *(softc->one);		/* send start bit */
353
354	    data = hs_read8(bptr);
355	    bptr++;
356
357	    for (count = 0; count < 8; count++) {
358		if (data & 1) dummy = *(softc->one);
359		else dummy = *(softc->zero);
360		data >>= 1; 		/* shift in next bit */
361		}
362
363	    dummy = *(softc->one);		/* send stop bit */
364	    }
365
366	blen--;
367	}
368
369    buffer->buf_retlen = buffer->buf_length - blen;
370    return 0;
371}
372
373/*  *********************************************************************
374    *  promice_ioctl(ctx,buffer)
375    *
376    *  Do I/O control operations
377    *
378    *  Input parameters:
379    *  	   ctx - device context
380    *  	   buffer - I/O control args
381    *
382    *  Return value:
383    *  	   0 if ok
384    *  	   else error code
385    ********************************************************************* */
386
387static int promice_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
388{
389    return -1;
390}
391
392/*  *********************************************************************
393    *  promice_close(ctx)
394    *
395    *  Close the device.
396    *
397    *  Input parameters:
398    *  	   ctx - device context
399    *
400    *  Return value:
401    *  	   0
402    ********************************************************************* */
403
404static int promice_close(cfe_devctx_t *ctx)
405{
406    return 0;
407}
408
409
410