2 * $Id: scif.c,v 1.7 2005-12-26 03:54:55 nkeynes Exp $
3 * SCIF (Serial Communication Interface with FIFO) implementation - part of the
4 * SH4 standard on-chip peripheral set. The SCIF is hooked up to the DCs
7 * Copyright (c) 2005 Nathan Keynes.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
29 void SCIF_set_break(void);
31 /************************* External serial interface ************************/
34 * Note: serial_* operations are called from outside the SH4, and as such are
35 * named relative to the external serial device. SCIF_* operations are only
36 * called internally to the SH4 and so are named relative to the CPU.
40 * Storage space for inbound/outbound data blocks. It's a little more
41 * convenient for serial consumers to be able to deal with block-sized pieces
42 * rather than a byte at a time, even if it makes all this look rather
45 * Currently there's no limit on the number of blocks that can be queued up.
47 typedef struct serial_data_block {
50 struct serial_data_block *next;
52 } *serial_data_block_t;
54 serial_data_block_t serial_recvq_head = NULL, serial_recvq_tail = NULL;
55 serial_device_t serial_device = NULL;
57 void serial_attach_device( serial_device_t dev )
59 if( serial_device != NULL )
60 serial_detach_device();
65 void serial_detach_device( void )
71 * Add a block of data to the serial receive queue. The data will be received
72 * by the CPU at the appropriate baud rate.
74 void serial_transmit_data( char *data, int length ) {
77 serial_data_block_t block =
78 g_malloc( sizeof( struct serial_data_block ) + length );
79 block->length = length;
82 memcpy( block->data, data, length );
84 if( serial_recvq_head == NULL ) {
85 serial_recvq_head = serial_recvq_tail = block;
87 serial_recvq_tail->next = block;
88 serial_recvq_tail = block;
93 * Dequeue a byte from the serial input queue
95 static int serial_transmit_dequeue( ) {
96 if( serial_recvq_head != NULL ) {
97 uint8_t val = serial_recvq_head->data[serial_recvq_head->offset++];
98 if( serial_recvq_head->offset >= serial_recvq_head->length ) {
99 serial_data_block_t next = serial_recvq_head->next;
100 g_free( serial_recvq_head );
101 serial_recvq_head = next;
103 serial_recvq_tail = NULL;
105 return (int)(unsigned int)val;
111 void serial_transmit_break() {
115 /********************************* SCIF *************************************/
117 #define FIFO_LENGTH 16
118 #define FIFO_ARR_LENGTH (FIFO_LENGTH+1)
120 /* Serial control register flags */
121 #define SCSCR2_TIE 0x80
122 #define SCSCR2_RIE 0x40
123 #define SCSCR2_TE 0x20
124 #define SCSCR2_RE 0x10
125 #define SCSCR2_REIE 0x08
126 #define SCSCR2_CKE 0x02
128 #define IS_TRANSMIT_IRQ_ENABLED() (MMIO_READ(SCIF,SCSCR2) & SCSCR2_TIE)
129 #define IS_RECEIVE_IRQ_ENABLED() (MMIO_READ(SCIF,SCSCR2) & SCSCR2_RIE)
130 #define IS_RECEIVE_ERROR_IRQ_ENABLED() (MMIO_READ(SCIF,SCSCR2) & (SCSCR2_RIE|SCSCR2_REIE))
131 /* Receive is enabled if the RE bit is set in SCSCR2, and the ORER bit is cleared in SCLSR2 */
132 #define IS_RECEIVE_ENABLED() ( (MMIO_READ(SCIF,SCSCR2) & SCSCR2_RE) && (MMIO_READ(SCIF,SCLSR2) & SCLSR2_ORER == 0) )
133 /* Transmit is enabled if the TE bit is set in SCSCR2 */
134 #define IS_TRANSMIT_ENABLED() (MMIO_READ(SCIF,SCSCR2) & SCSCR2_TE)
135 #define IS_LOOPBACK_ENABLED() (MMIO_READ(SCIF,SCFCR2) & SCFCR2_LOOP)
137 /* Serial status register flags */
138 #define SCFSR2_ER 0x80
139 #define SCFSR2_TEND 0x40
140 #define SCFSR2_TDFE 0x20
141 #define SCFSR2_BRK 0x10
142 #define SCFSR2_RDF 0x02
143 #define SCFSR2_DR 0x01
145 /* FIFO control register flags */
146 #define SCFCR2_MCE 0x08
147 #define SCFCR2_TFRST 0x04
148 #define SCFCR2_RFRST 0x02
149 #define SCFCR2_LOOP 0x01
151 /* Line Status Register */
152 #define SCLSR2_ORER 0x01
158 uint8_t data[FIFO_ARR_LENGTH];
161 int SCIF_recvq_triggers[4] = {1, 4, 8, 14};
162 struct SCIF_fifo SCIF_recvq = {0,0,1};
164 int SCIF_sendq_triggers[4] = {8, 4, 2, 1};
165 struct SCIF_fifo SCIF_sendq = {0,0,8};
168 * Flag to indicate if data was received (ie added to the receive queue)
169 * during the last SCIF clock tick. Used to determine when to set the DR
172 gboolean SCIF_rcvd_last_tick = FALSE;
174 uint32_t SCIF_tick_period = 0;
175 uint32_t SCIF_tick_remainder = 0;
177 void SCIF_save_state( FILE *f )
179 fwrite( &SCIF_recvq, sizeof(SCIF_recvq), 1, f );
180 fwrite( &SCIF_sendq, sizeof(SCIF_sendq), 1, f );
181 fwrite( &SCIF_rcvd_last_tick, sizeof(gboolean), 1, f );
185 int SCIF_load_state( FILE *f )
187 fread( &SCIF_recvq, sizeof(SCIF_recvq), 1, f );
188 fread( &SCIF_sendq, sizeof(SCIF_sendq), 1, f );
189 fread( &SCIF_rcvd_last_tick, sizeof(gboolean), 1, f );
193 static inline uint8_t SCIF_recvq_size( )
195 int val = SCIF_recvq.tail - SCIF_recvq.head;
197 val = FIFO_ARR_LENGTH - SCIF_recvq.head + SCIF_recvq.tail;
202 int SCIF_recvq_dequeue( gboolean clearFlags )
205 uint32_t tmp, length;
206 if( SCIF_recvq.head == SCIF_recvq.tail )
207 return -1; /* No data */
208 result = SCIF_recvq.data[SCIF_recvq.head++];
209 if( SCIF_recvq.head > FIFO_LENGTH )
212 /* Update data count register */
213 tmp = MMIO_READ( SCIF, SCFDR2 ) & 0xF0;
214 length = SCIF_recvq_size();
215 MMIO_WRITE( SCIF, SCFDR2, tmp | length );
217 /* Clear flags (if requested ) */
218 if( clearFlags && length < SCIF_recvq.trigger ) {
222 tmp = MMIO_READ( SCIF, SCFSR2 ) & (~tmp);
223 MMIO_WRITE( SCIF, SCFSR2, tmp );
224 /* If both flags are cleared, clear the interrupt as well */
225 if( (tmp & (SCFSR2_DR|SCFSR2_RDF)) == 0 && IS_RECEIVE_IRQ_ENABLED() )
226 intc_clear_interrupt( INT_SCIF_RXI );
229 return (int)(unsigned int)result;
232 gboolean SCIF_recvq_enqueue( uint8_t value )
234 uint32_t tmp, length;
235 int newpos = SCIF_recvq.tail + 1;
236 if( newpos > FIFO_LENGTH )
238 if( newpos == SCIF_recvq.head ) {
239 /* FIFO full - set ORER and discard the value */
240 MMIO_WRITE( SCIF, SCLSR2, SCLSR2_ORER );
241 if( IS_RECEIVE_ERROR_IRQ_ENABLED() )
242 intc_raise_interrupt( INT_SCIF_ERI );
245 SCIF_recvq.data[SCIF_recvq.tail] = value;
247 /* Update data count register */
248 tmp = MMIO_READ( SCIF, SCFDR2 ) & 0xF0;
249 length = SCIF_recvq_size();
250 MMIO_WRITE( SCIF, SCFDR2, tmp | length );
252 /* Update status register */
253 tmp = MMIO_READ( SCIF, SCFSR2 );
254 if( length >= SCIF_recvq.trigger ) {
256 if( IS_RECEIVE_IRQ_ENABLED() )
257 intc_raise_interrupt( INT_SCIF_RXI );
259 MMIO_WRITE( SCIF, SCFSR2, tmp );
265 * Reset the receive FIFO to its initial state. Manual is unclear as to
266 * whether this also clears flags/interrupts, but we're assuming here that
267 * it does until proven otherwise.
269 void SCIF_recvq_clear( void )
271 SCIF_recvq.head = SCIF_recvq.tail = 0;
272 MMIO_WRITE( SCIF, SCFDR2, MMIO_READ( SCIF, SCFDR2 ) & 0xF0 );
273 MMIO_WRITE( SCIF, SCFSR2, MMIO_READ( SCIF, SCFSR2 ) & ~(SCFSR2_DR|SCFSR2_RDF) );
274 if( IS_RECEIVE_IRQ_ENABLED() )
275 intc_clear_interrupt( INT_SCIF_RXI );
278 static inline uint8_t SCIF_sendq_size( )
280 int val = SCIF_sendq.tail - SCIF_sendq.head;
282 val = FIFO_ARR_LENGTH - SCIF_sendq.head + SCIF_sendq.tail;
288 * Dequeue one byte from the SCIF transmit queue (ie transmit the byte),
289 * updating all status flags as required.
290 * @return The byte dequeued, or -1 if the queue is empty.
292 int SCIF_sendq_dequeue( )
295 uint32_t tmp, length;
296 if( SCIF_sendq.head == SCIF_sendq.tail )
297 return -1; /* No data */
299 /* Update queue head pointer */
300 result = SCIF_sendq.data[SCIF_sendq.head++];
301 if( SCIF_sendq.head > FIFO_LENGTH )
304 /* Update data count register */
305 tmp = MMIO_READ( SCIF, SCFDR2 ) & 0x0F;
306 length = SCIF_sendq_size();
307 MMIO_WRITE( SCIF, SCFDR2, tmp | (length << 8) );
309 /* Update status register */
310 if( length <= SCIF_sendq.trigger ) {
311 tmp = MMIO_READ( SCIF, SCFSR2 ) | SCFSR2_TDFE;
313 tmp |= SCFSR2_TEND; /* Transmission ended - no data waiting */
314 if( IS_TRANSMIT_IRQ_ENABLED() )
315 intc_raise_interrupt( INT_SCIF_TXI );
316 MMIO_WRITE( SCIF, SCFSR2, tmp );
318 return (int)(unsigned int)result;
322 * Enqueue a single byte in the SCIF transmit queue. If the queue is full,
323 * the value will be discarded.
324 * @param value to be queued.
325 * @param clearFlags TRUE if the TEND/TDFE flags should be cleared
326 * if the queue exceeds the trigger level. (According to the manual,
327 * DMAC writes will clear the flag, whereas regular SH4 writes do NOT
328 * automatically clear it. Go figure).
329 * @return gboolean TRUE if the value was queued, FALSE if the queue was
332 gboolean SCIF_sendq_enqueue( uint8_t value, gboolean clearFlags )
334 uint32_t tmp, length;
335 int newpos = SCIF_sendq.tail + 1;
336 if( newpos > FIFO_LENGTH )
338 if( newpos == SCIF_sendq.head ) {
339 /* FIFO full - discard */
342 SCIF_sendq.data[SCIF_sendq.tail] = value;
343 SCIF_sendq.tail = newpos;
345 /* Update data count register */
346 tmp = MMIO_READ( SCIF, SCFDR2 ) & 0x0F;
347 length = SCIF_sendq_size();
348 MMIO_WRITE( SCIF, SCFDR2, tmp | (length << 8) );
350 /* Update flags if requested */
353 if( length > SCIF_sendq.trigger ) {
355 if( IS_TRANSMIT_IRQ_ENABLED() )
356 intc_clear_interrupt( INT_SCIF_TXI );
358 tmp = MMIO_READ( SCIF, SCFSR2 ) & (~tmp);
359 MMIO_WRITE( SCIF, SCFSR2, tmp );
364 void SCIF_sendq_clear( void )
366 SCIF_sendq.head = SCIF_sendq.tail = 0;
367 MMIO_WRITE( SCIF, SCFDR2, MMIO_READ( SCIF, SCFDR2 ) & 0x0F );
368 MMIO_WRITE( SCIF, SCFSR2, MMIO_READ( SCIF, SCFSR2 ) | SCFSR2_TEND | SCFSR2_TDFE );
369 if( IS_TRANSMIT_IRQ_ENABLED() ) {
370 intc_raise_interrupt( INT_SCIF_TXI );
375 * Update the SCFSR2 status register with the given mask (ie clear any values
376 * that are set to 0 in the mask. According to a strict reading of the doco
377 * though, the bits will only actually clear if the flag state is no longer
378 * true, so we need to recheck everything...
380 void SCIF_update_status( uint32_t mask )
382 uint32_t value = MMIO_READ( SCIF, SCFSR2 );
383 uint32_t result = value & mask;
384 uint32_t sendq_size = SCIF_sendq_size();
385 uint32_t recvq_size = SCIF_recvq_size();
387 if( sendq_size != 0 )
388 result |= SCFSR2_TEND;
390 if( sendq_size <= SCIF_sendq.trigger )
391 result |= SCFSR2_TDFE;
392 else if( result & SCFSR2_TDFE == 0 && IS_TRANSMIT_IRQ_ENABLED() )
393 intc_clear_interrupt( INT_SCIF_TXI );
395 if( recvq_size >= SCIF_recvq.trigger )
396 result |= SCFSR2_RDF;
397 if( (value & SCFSR2_DR) != 0 && (result & SCFSR2_DR) == 0 &&
400 if( (result & (SCFSR2_DR|SCFSR2_RDF)) == 0 && IS_RECEIVE_IRQ_ENABLED() )
401 intc_clear_interrupt( INT_SCIF_RXI );
403 if( IS_RECEIVE_ERROR_IRQ_ENABLED() ) {
404 if( (result & SCFSR2_BRK) == 0 )
405 intc_clear_interrupt( INT_SCIF_BRI );
406 if( (result & SCFSR2_ER) == 0 &&
407 (MMIO_READ( SCIF, SCLSR2 ) & SCLSR2_ORER) == 0 )
408 intc_clear_interrupt( INT_SCIF_ERI );
413 * Set the break detected flag
415 void SCIF_set_break( void )
417 MMIO_WRITE( SCIF, SCFSR2, MMIO_READ( SCIF, SCFSR2 ) | SCFSR2_BRK );
418 if( IS_RECEIVE_ERROR_IRQ_ENABLED() )
419 intc_raise_interrupt( INT_SCIF_BRI );
422 const static int SCIF_CLOCK_MULTIPLIER[4] = {1, 4, 16, 64};
425 * Calculate the current line speed.
427 void SCIF_update_line_speed( void )
429 /* If CKE1 is set, use the external clock as a base */
430 if( MMIO_READ( SCIF, SCSCR2 ) & SCSCR2_CKE ) {
435 /* Otherwise, SH4 peripheral clock divided by n */
436 int mult = SCIF_CLOCK_MULTIPLIER[MMIO_READ( SCIF, SCSMR2 ) & 0x03];
438 /* Then process the bitrate register */
439 int bbr = MMIO_READ( SCIF, SCBRR2 ) & 0xFF;
441 int baudrate = sh4_peripheral_freq / (32 * mult * (bbr+1) );
443 if( serial_device != NULL && serial_device->set_line_speed != NULL )
444 serial_device->set_line_speed( baudrate );
446 SCIF_tick_period = sh4_peripheral_period * (32 * mult * (bbr+1));
449 clock_set_tick_rate( CLOCK_SCIF, baudrate / 10 );
454 int32_t mmio_region_SCIF_read( uint32_t reg )
457 case SCFRDR2: /* Receive data */
458 return SCIF_recvq_dequeue(FALSE);
460 return MMIO_READ( SCIF, reg );
464 void mmio_region_SCIF_write( uint32_t reg, uint32_t val )
468 case SCSMR2: /* Serial mode register */
469 /* Bit 6 => 0 = 8-bit, 1 = 7-bit
470 * Bit 5 => 0 = Parity disabled, 1 = parity enabled
471 * Bit 4 => 0 = Even parity, 1 = Odd parity
472 * Bit 3 => 0 = 1 stop bit, 1 = 2 stop bits
473 * Bits 0-1 => Clock select 00 = P, 01 = P/4, 10 = P/16, 11 = P/64
476 if( serial_device != NULL ) {
477 serial_device->set_line_params( val );
479 tmp = MMIO_READ( SCIF, SCSMR2 );
480 if( tmp & 0x03 != val & 0x03 ) {
482 SCIF_update_line_speed( );
484 /* Save for later read-back */
485 MMIO_WRITE( SCIF, SCSMR2, val );
487 case SCBRR2: /* Bit rate register */
488 MMIO_WRITE( SCIF, SCBRR2, val );
489 SCIF_update_line_speed( );
491 case SCSCR2: /* Serial control register */
492 /* Bit 7 => Transmit-FIFO-data-empty interrupt enabled
493 * Bit 6 => Receive-data-full interrupt enabled
494 * Bit 5 => Transmit enable
495 * Bit 4 => Receive enable
496 * Bit 3 => Receive-error/break interrupt enabled
497 * Bit 1 => Clock enable
500 /* Clear any interrupts that just became disabled */
501 if( val & SCSCR2_TIE == 0 )
502 intc_clear_interrupt( INT_SCIF_TXI );
503 if( val & SCSCR2_RIE == 0 )
504 intc_clear_interrupt( INT_SCIF_RXI );
505 if( val & (SCSCR2_RIE|SCSCR2_REIE) == 0 ) {
506 intc_clear_interrupt( INT_SCIF_ERI );
507 intc_clear_interrupt( INT_SCIF_BRI );
510 MMIO_WRITE( SCIF, reg, val );
512 case SCFTDR2: /* Transmit FIFO data register */
513 SCIF_sendq_enqueue( val, FALSE );
515 case SCFSR2: /* Serial status register */
516 /* Bits 12-15 Parity error count
517 * Bits 8-11 Framing erro count
518 * Bit 7 - Receive error
519 * Bit 6 - Transmit end
520 * Bit 5 - Transmit FIFO data empty
521 * Bit 4 - Break detect
522 * Bit 3 - Framing error
523 * Bit 2 - Parity error
524 * Bit 1 - Receive FIFO data full
525 * Bit 0 - Receive data ready
527 /* Clear off any flags/interrupts that are being set to 0 */
528 SCIF_update_status( val );
530 case SCFCR2: /* FIFO control register */
532 SCIF_recvq.trigger = SCIF_recvq_triggers[val >> 6];
533 SCIF_sendq.trigger = SCIF_sendq_triggers[(val >> 4) & 0x03];
534 if( val & SCFCR2_TFRST ) {
537 if( val & SCFCR2_RFRST ) {
541 MMIO_WRITE( SCIF, reg, val );
543 case SCSPTR2: /* Serial Port Register */
544 MMIO_WRITE( SCIF, reg, val );
545 /* NOT IMPLEMENTED */
546 WARN( "SCSPTR2 not implemented: Write %08X", val );
549 val = val & SCLSR2_ORER;
551 MMIO_WRITE( SCIF, SCLSR2, val );
552 if( (MMIO_READ( SCIF, SCFSR2 ) & SCFSR2_ER) == 0 &&
553 IS_RECEIVE_ERROR_IRQ_ENABLED() )
554 intc_clear_interrupt( INT_SCIF_ERI );
562 * Actions for a single tick of the serial clock, defined as the transmission
563 * time of a single frame.
565 * If transmit queue is non-empty:
566 * Transmit one byte and remove from queue
567 * If input receive source is non-empty:
568 * Transfer one byte to the receive queue (if queue is full, byte is lost)
569 * If recvq is non-empty, less than the trigger level, and no data has been
570 * received in the last 2 ticks (including this one), set the DR flag and
571 * IRQ if appropriate.
573 void SCIF_clock_tick( void )
575 gboolean rcvd = FALSE;
577 if( IS_LOOPBACK_ENABLED() ) {
578 if( IS_TRANSMIT_ENABLED() ) {
579 int val = SCIF_sendq_dequeue();
580 if( val != -1 && IS_RECEIVE_ENABLED() ) {
581 SCIF_recvq_enqueue( val );
586 if( IS_TRANSMIT_ENABLED() ) {
587 int val = SCIF_sendq_dequeue();
588 if( val != -1 && serial_device != NULL &&
589 serial_device->receive_data != NULL ) {
590 serial_device->receive_data( val );
594 if( IS_RECEIVE_ENABLED() ) {
595 int val = serial_transmit_dequeue();
597 SCIF_recvq_enqueue( val );
603 /* Check if we need to set the DR flag */
604 if( !rcvd && !SCIF_rcvd_last_tick &&
605 SCIF_recvq.head != SCIF_recvq.tail &&
606 SCIF_recvq_size() < SCIF_recvq.trigger ) {
607 uint32_t tmp = MMIO_READ( SCIF, SCFSR2 );
608 if( tmp & SCFSR2_DR == 0 ) {
609 MMIO_WRITE( SCIF, SCFSR2, tmp | SCFSR2_DR );
610 if( IS_RECEIVE_IRQ_ENABLED() )
611 intc_raise_interrupt( INT_SCIF_RXI );
614 SCIF_rcvd_last_tick = rcvd;
617 void SCIF_reset( void )
621 SCIF_update_line_speed();
624 void SCIF_run_slice( uint32_t nanosecs )
626 SCIF_tick_remainder += nanosecs;
627 while( SCIF_tick_remainder >= SCIF_tick_period ) {
628 SCIF_tick_remainder -= SCIF_tick_period;
.