📄 ics_564.c
字号:
TIME_PAST; PR_DBG( 4, "Putting block[%x] (data%i[%i/%i]) at %x -> %6i\n", board->block_size, ch, ch_inv, block_offset, last_time, past_time ); } ics564_setup_datapath( board, 1 << ch_inv, 1 ); PR_DBG( 4, "Starting DMA with adress: %p[%x]\n", board->params[ch]->addr_tx, block_offset * board->block_size * sizeof( u32 ) ); ics564_start_dma( board, ch_inv, board->params[ ch ]->addr_tx + block_offset * board->block_size * sizeof( u32 ), board->block_size * sizeof( u32 ) ); PR_DBG( 4, "DMA kicked off\n" ); board->block_count++;}int kick_loop;struct thread kick_thread;pthread_mutex_t kick_mut;// = PTHREAD_MUTEX_INITIALIZER;pthread_cond_t kick_cond;// = PTHREAD_COND_INITIALIZER;#define KICK_WAKEUP \ pthread_mutex_lock( &kick_mut ); \ pthread_cond_signal( &kick_cond ); \ pthread_mutex_unlock( &kick_mut ); \void *kick_it( void *arg ){ struct ics_dev *board = &board_tx; struct sched_param p; p.sched_priority = 1; pthread_setschedparam( pthread_self(), SCHED_FIFO, &p ); kick_loop = 1; while ( kick_loop ){ PR_DBG( 1, "Suspending myself\n" ); pthread_mutex_lock( &kick_mut ); pthread_cond_wait( &kick_cond, &kick_mut ); pthread_mutex_unlock( &kick_mut ); PR_DBG( 1, "Waking up\n" ); rtl_udelay( 20 ); if ( kick_loop ){ ics564_dma_next_block( board ); } } return 0;}u64 last_time_get;unsigned int ics564_interrupt( unsigned int irq, struct pt_regs *r ){ u64 intRegister, tmp, i, now = gethrtime(); u32 dacRegister, irq_mask; struct ics_dev *board = &board_tx; int ics564_dac_trig = 0; /* Read the Interrupt status Register */ intRegister = READ_QL5064_U64(board,IRQ_STAT); PR_DBG( 3, "INTR: 0x%16.16llx, count=%lli, time: %lli\n", intRegister, board->block_count, ( now - last_time_get ) / 1000 ); last_time_get = now; /* Now Acknowledge the interrupt on the device */ WRITE_QL5064_U64(board,IRQ_STAT,intRegister); /* wait bus to stabilize (QL user manual - ISR 3.11.2.0) */ tmp = READ_QL5064_U64(board, WAIT); /* Check if the interrupt was caused by our device */ if( !(intRegister & ( QL_5064_INT_STAT_XMT0 | QL_5064_INT_STAT_RCV0 | QL_5064_INT_STAT_CHN | QL_5064_INT_STAT_USR ) ) ) { PR_DBG( 1, "Not enabled interrupt!?!\n" ); return 0; } if ( board->flags & ICS564_NO_INT ){ PR_DBG( 1, "Interrupt cancelled\n" ); ics564_clear_imr( board, ics564_dac_trig ); return 0; } if ( intRegister & QL_5064_INT_STAT_USR ){ //AE interrupts dacRegister = READ_ICS564_U32( board, IRQ_STAT ); irq_mask = READ_ICS564_U32( board, IRQ_MASK ); PR_DBG( 2, "AE Intr: %x\n", dacRegister ); if ( board->flags & ICS564_RUN ){ ics564_clear_imr( board, ics564_dac_trig ); if ( ( dacRegister & irq_mask ) & ( 0x10 << ics564_dac_trig ) ){ TIME_PAST; if ( past_time < 10 ){ PR_DBG( 1, "Past-time too small: %i!\ndac: %8x, int: %8llx\n", past_time, dacRegister, intRegister ); } if ( ( board->block_count % 1000 ) < TIME_SHOW ){ PR_DBG( 1, "Block %8lli, IRQ-mask %x at %x -> %6i\n", board->block_count, irq_mask, last_time, past_time ); } ics564_dma_next_block( board ); } } else { PR_DBG( 1, "AE interrupt while not running\n" ); } } PR_DBG( 4,"Block_count = %i \n", board->block_count ); if ( intRegister & QL_5064_INT_STAT_RCV0 ){ //End of DMA transfer PR_DBG( 2, "DMA acknowledged\n" ); if ( board->flags & ICS564_RUN ){ if( board->block_count < board->number_channels * DMA_PRELOAD ){ ics564_dma_next_block( board ); //pthread_wakeup_np( kick_thread.thread ); } else if ( board->block_count == board->number_channels * DMA_PRELOAD ){ PR_DBG( 1, "Triggering at %x\n", (u32)( gethrtime() / 1000 ) ); for ( i=0; i<4; i++ ){ ics564_clear_imr( board, i ); } ics564_set_imr( board, ics564_dac_trig ); ics564_clear_imr( board, ics564_dac_trig ); ics564_set_imr( board, ics564_dac_trig ); ics564_trigger( board ); PR_DBG( 1, "Conversion Triggered \n" ); } else { // DMA_PRELOAD is finished, and either we have to continue // filling up the other channels, or we have to re-enable the // dac-interrupt if ( ( board->block_count % 1000 ) < TIME_SHOW ){ TIME_PAST; PR_DBG( 1, "DMA for block %8lli at %x -> %6i\n", board->block_count, last_time, past_time ); } if ( board->block_count % board->number_channels ){ ics564_dma_next_block( board ); } else { ics564_set_imr( board, ics564_dac_trig ); ics564_clear_imr( board, ics564_dac_trig ); ics564_set_imr( board, ics564_dac_trig ); } } } else { PR_DBG( 1, "DMA int while not running\n" ); } } rtl_hard_enable_irq( board->irq ); return 0;}void ics564_reset( struct ics_dev *board ){ /* Reset QL5064 */ WRITE_QL5064_U64(board, RESET, 1); rtl_udelay(1000); WRITE_QL5064_U64(board, CONTROL, 1 ); /* Reset QL5064 Dma Interrupt */ WRITE_QL5064_U64( board, IRQ_MASK, ( QL_5064_INT_STAT_XMT0 | QL_5064_INT_STAT_RCV0 | QL_5064_INT_STAT_CHN | QL_5064_INT_STAT_USR) ); rtl_udelay(1000); WRITE_QL5064_U64( board, FIFO, 0x800200020001BLL ); rtl_udelay(1000); WRITE_ICS564_U32(board, IRQ_MASK, 0x0); rtl_udelay(1000); PR_DBG( 2,"QL_MASK(0x%2.2x)=0x%16.16llx\n", QL_5064_IRQ_MASK, READ_QL5064_U64(board, IRQ_MASK ) ); PR_DBG( 2,"QL_FIFO(0x%2.2x)=0x%16.16llx\n", QL_5064_FIFO, READ_QL5064_U64(board, FIFO) ); // Reset the DACs WRITE_ICS564_U32( board, DAC_RESET, 0xf ); rtl_udelay( 10000 ); WRITE_ICS564_U32( board, DAC_RESET, 0x0 ); rtl_udelay( 10000 ); board->block_count = 0; if ( board->irq ){ rtl_hard_enable_irq( board->irq ); }}void ics564_setup( struct ics_dev *board ){ int ch_nbr, trigger, clock; u64 profile, base; profile = ics564_dac_config_profile( ICS564_CARRIER( CARRIER_MHZ ), 0, 0, 0x10, 0xff ); // first parameter is pll-multiplier, 1 for 100MHz-clock // and 4 for 50MHz clock. 2 is an invalid multiplier! base = ics564_dac_config_base( 1, 1, 0, 1, 0, 0, 0, 0, 0 ); for ( ch_nbr=0; ch_nbr<4; ch_nbr++ ){ // Setting up DAC 1-4 ics564_dac_set_base( board, ch_nbr, base ); // Write profile 0 and 1 for eventual frequency-update ics564_dac_set_profile( board, ch_nbr, 0, profile ); ics564_dac_set_profile( board, ch_nbr, 1, profile ); } ics564_fifo_setup( board, FIFO_SIZE_64K ); // clock == 0 -> internal clock // clock == 1 -> external clock // same for trigger if ( board->flags & ICS564_TEST ){ // In test mode, set everything to internal mode trigger = 0; clock = 0; } else { trigger = !( board->flags & ICS564_TRIGGER_INT ); clock = 1; } ics564_setup_control( board, DAC_MODE_CONTINOUS, DAC_MODE_CONTINOUS, DAC_MODE_CONTINOUS, DAC_MODE_CONTINOUS, 1, trigger, clock ); rtl_udelay( 10000 ); ics564_set_buffer_size( board, 65535 ); // Configuration of the RF boards freq synthetiser Si4136-BT // Main configuration of the RF freq synth: 0x40 in register 0 for ( ch_nbr=0; ch_nbr<4; ch_nbr++ ){ ics564_send_serial( board, ICS_564_SYNTH_W_SIZE, (0x000000 << 4)+0x0, ICS_564_SYNTH_CHIP,0,ch_nbr); // Phase detector gain of the RF freq synth:0x0 in register 1 ics564_send_serial( board, ICS_564_SYNTH_W_SIZE, (0x000000 << 4)+0x1, ICS_564_SYNTH_CHIP,0,ch_nbr); // Power config of the RF freq synth:0x1 in register 2 ics564_send_serial( board, ICS_564_SYNTH_W_SIZE, (0x000001 << 4)+0x2, ICS_564_SYNTH_CHIP,0,ch_nbr); rf_set_synth( board, 0, 2400, 0, ch_nbr ); // RF1_R ref frequency divider, R=15=0x0f in register 0x6 ics564_send_serial( board, ICS_564_SYNTH_W_SIZE, ( RF_SYNCH_R << 4)+0x6, ICS_564_SYNTH_CHIP,0,ch_nbr); //Configuration of the RF board RX and TX attenuators: full att ics564_send_serial( board, ICS_564_ATT_W_SIZE, 0xffffff, ICS_564_ATT_CHIP,0,ch_nbr); rtl_udelay( 10000 ); }}int ics564_stop(struct ics_dev *board){ PR_DBG( 1, "Stopping ICS564\n" ); board->flags &= ~ICS564_RUN; board->flags |= ICS564_NO_INT; ics564_cancel_dma( board ); board->flags &= ~ICS564_STARTED; PR_DBG( 1, "Finished 564\n" ); return 0;}int ics564_init(){ if ( ics_get_board( &board_tx, ICS_SUB_DEV_564, ics564_interrupt ) == 0 ){ PR_DBG( 0, "Couldn't find ICS 564 board!\n" ); return -1; } PR_DBG( 0, "Found ICS 564 DAC board\n" ); ics564_reset( &board_tx ); ics564_setup( &board_tx ); board_tx.number_channels = 0; board_tx.blocks_per_frame = 0; board_tx.block_size = DAQ_DMA_BLOCK_SIZE_QI_SAMPLES * BOARD_BLOCK_SIZE; board_tx.flags = ICS564_INITIALIZED; return 0;}int ics564_free(struct ics_dev *board){ int j; PR_DBG( 1, "Freeing ICS564\n" ); if(board->flags & ICS564_INITIALIZED) { PR_DBG( 1, "Stopping se board\n" ); ics564_stop(board); if(board->irq >= 0) { PR_DBG( 1, "Freeing the IRQ\n" ); rtl_free_irq(board->irq); } for(j=0; j < 3; j++) { iounmap(board->iobase[j]); } } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -