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