📄 ics_564.c
字号:
/*************************************************************************** ics_564.c - ICS-564 driver ------------------- begin : 2003 authors : Linus Gasser emails : linus.gasser@epfl.ch ***************************************************************************//*************************************************************************** Changes ------- date - name - description 03-09-16 - ineiti - create **************************************************************************//*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/#include "system.h"#include "ics_564.h"#include "ics_564_test.h"#include "ql_5064.h"#include <linux/pci.h>#include "debugging.h"#include <math.h>#include "std.h"#include "rtl_time.h"#include "rf_ics.h"#define DBG_LVL 0u16 old_regout;void ics564_dac_write( struct ics_dev *board, u8 dac, u8 addr, u8 data ){ u32 val; dac &= 3; addr &= 0x1f; val = (u32)data + ( (u32)addr << 8 ) + ( (u32)dac << 13 ); PR_DBG( 4,"Setting dac(%hi) at %hi to %hx\n", dac, addr, data ); WRITE_ICS564_U32(board, DAC_INSTR, val); rtl_udelay(1000);}u8 ics564_dac_read( struct ics_dev *board, u8 dac, u8 addr ){ u32 val; u32 data; dac &= 3; addr &= 0x1f; val = ( (u32)addr << 8 ) + ( (u32)dac << 13 ) + DAC_INSTRUCTION_RW; WRITE_ICS564_U32(board, DAC_INSTR, val); rtl_udelay(1000); data = READ_ICS564_U32( board, DAC_INSTR ); PR_DBG( 4,"Reading dac(%i) at %i: %x\n", dac, addr, data ); return (u8)data;}void ics564_freq( struct ics_dev *board, int dac, u32 freq ){ int i; for ( i=2; i<=5; i++ ){ ics564_dac_write( board, dac, i, freq & 0xff ); freq >>= 8; } WRITE_ICS564_U32( board, DAC_CONFIG, 0x10000 ); WRITE_ICS564_U32( board, DAC_CONFIG, 0x11000 ); WRITE_ICS564_U32( board, DAC_CONFIG, 0x01000 ); WRITE_ICS564_U32( board, DAC_CONFIG, 0x00000 );}/** * updates the frequency and goes into the 'other' profile */void ics564_freq_quad( struct ics_dev *board, int dac, int profile, u32 freq ){ int i; u32 dac_config = READ_ICS564_U32( board, DAC_CONFIG ); profile = max( profile, 0 ); profile = min( profile, 3 ); for ( i=2; i<=5; i++ ){ ics564_dac_write( board, dac, i + profile * 6, freq & 0xff ); freq >>= 8; } dac_config &= ~( 3 << ( dac * 2 ) ); dac_config |= profile << ( dac * 2 ); WRITE_ICS564_U32( board, DAC_CONFIG, dac_config ); PR_DBG( 4, "Wrote %x to dac %i and profile %i\n", dac_config, dac, profile );}void ics564_set_imr( struct ics_dev *board, u8 dac ){ u32 old, mask; old = READ_ICS564_U32( board, IRQ_MASK ); mask = ( (1<<(u32)dac) << 4 ); WRITE_ICS564_U32( board, IRQ_MASK, old | mask ); // rtl_udelay( 1000 );}void ics564_clear_imr( struct ics_dev *board, u8 dac ){ u32 old, mask; old = READ_ICS564_U32( board, IRQ_MASK ); mask = ( (1<<(u32)dac) << 4 ); WRITE_ICS564_U32( board, IRQ_MASK, old & ~mask ); // rtl_udelay( 1000 );}void ics564_dac_set_base( struct ics_dev *board, int dac, u16 config ){ ics564_dac_write( board, dac, 0, config & 0xff ); ics564_dac_write( board, dac, 1, config >> 8 ); PR_DBG( 1, "Setting dac %i to %2x/%2x\n", dac, config & 0xff, config >> 8 );}u16 ics564_dac_config_base( u16 refclk, u16 pll_lock, u16 lsb_first, u16 sdio, u16 mode, u16 auto_power, u16 sleep, u16 bypass_inv_sinc, u16 cic_clear ){// u16 temp; // Set all parameters to good values refclk = min( refclk, (u16)0x14 ); if ( refclk < 4 ) refclk = 1; mode = min( (u16)2, mode ); #if 1 return refclk + ( !!pll_lock << 5 ) + ( !!lsb_first << 6 ) + ( !! sdio << 7 )+ ( mode << 8 ) + ( !!auto_power << 10 ) + ( !! sleep << 11 ) + ( !!bypass_inv_sinc << 14 ) + ( !!cic_clear << 15 );#else return temp; temp = refclk + ( !!pll_lock << 5 ) + ( !!lsb_first << 6 ) + ( !! sdio << 7 ); temp += ( mode << 8 ) + ( !!auto_power << 10 ) + ( !! sleep << 11 ); temp += ( !!bypass_inv_sinc << 14 ) + ( !!cic_clear << 15 ); return temp;#endif}void ics564_dac_set_profile( struct ics_dev *board, int dac, int profile, u64 config ){ int i; profile = min( profile, 3 ); profile = max( profile, 0 ); PR_DBG( 1, "Setting dac %i/%i to %8.8x-%4.4x\n", dac, profile, (u32)( config & 0xffffffff ), (u32)( config >> 32 ) ); for ( i = 0; i < 6; i++ ){ ics564_dac_write( board, dac, i + profile * 6 + 2, config & 0xff ); config >>= 8; }}u64 ics564_dac_config_profile( u64 frequency, u64 bypass_inv_cic, u64 inv_spect, u64 cic_interp, u64 scaling ){ cic_interp = min( cic_interp, (u64)0x3f ); cic_interp = max( cic_interp, (u64)1 ); return frequency + ( (u64)!!bypass_inv_cic << 32 ) + ( (u64)!!inv_spect << 33 ) + ( (u64)cic_interp << 34 ) + ( (u64)scaling << 40 );}void ics564_fifo_setup( struct ics_dev *board, int size ){ u32 x; int ld, sel; ld = size / 4; sel = size & 3; // Set LD-flags ( + PCI LD flag ) x = ld * ( 0x1f << 5 ); // Set select-flags x += sel * ( 0x55 << 10 ); PR_DBG( 1, "FIFO-setup: %x\n", x ); WRITE_ICS564_U32( board, FIFO, x ); WRITE_ICS564_U32( board, FIFO, x + ( 1 << 3 ) ); WRITE_ICS564_U32( board, FIFO, x ); }void ics564_setup_control( struct ics_dev *board, u32 m1, u32 m2, u32 m3, u32 m4, u32 enable, u32 ext_trig, u32 ext_clock ){ u32 val; val = m1 + (m2<<2) + (m3<<4) + (m4<<6) + (!!enable << 15 ); val += (!!ext_trig << 8) + (!!ext_clock << 17); WRITE_ICS564_U32( board, CONTROL, val ); rtl_udelay( 10000 ); /* #define ics564_dac_setup_control(board,d1,d2,d3,d4,enable) WRITE_ICS564_U32( board,\ CONTROL, (u32)DAC_MODE_##d1 + ((u32)DAC_MODE_##d2<<2) + ((u32)DAC_MODE_##d3<<4) + \ ((u32)DAC_MODE_##d4<<6) + (!!((u32)enable) << 15 ) ) */}void ics564_load( struct ics_dev *board, u32 dacs ){ u32 fifo; // Mask all four dacs dacs &= 0xf; fifo = READ_ICS564_U32( board, FIFO ); fifo &= ~( 0xf << 5 ); PR_DBG( 1, "Loading fifos: %x, dacs: %x\n", fifo, dacs ); WRITE_ICS564_U32( board, FIFO, fifo ); // Enable triggering rtl_udelay( 10000 ); WRITE_ICS564_U32( board, LOAD, dacs ); rtl_udelay( 10000 ); // Enable PCI for sure dacs += 0x10; // And enable writing to the fifos fifo |= dacs << 5; WRITE_ICS564_U32( board, FIFO, fifo ); PR_DBG( 4, "Finished\n" );}void ics564_setup_datapath( struct ics_dev *board, u32 dacs, u32 enable ){ // WRITE_ICS564_U32( board, USER_CONTROL, ( dacs & 0xf ) << 1 ); WRITE_ICS564_U32( board, USER_CONTROL, ( ( dacs & 0xf ) << 1 ) + !!enable );}void ics564_start_dma( struct ics_dev *board, u64 dac, void *from, u64 count ){ WRITE_QL5064_U64( board, TOICS_PCI_ADDR, virt_to_bus( from ) ); WRITE_QL5064_U64( board, TOICS_COUNT, count ); WRITE_QL5064_U64( board, LOC_RCV0_CNT_ADDR, ( count << 32 ) + 0x80000 * 0 ); WRITE_QL5064_U64( board, DMA_CONTROL, DMA_START_TOICS );}void ics564_cancel_dma( struct ics_dev *board ){ WRITE_QL5064_U8( board, LOC_DMA_CANCEL, 1 );}void ics564_send_serial( struct ics_dev *board,u8 w_size, u32 word, u8 chip, u16 tx, u16 adr){ int i; u16 reg_out; // 8bits: ADR1,ADR2,SYN_CE,SYN_Data,SYN_Clk,ATT_CE,ATT_Data,ATT_Clk int shift=0; u32 orig_word=word; u8 dir=0; /* reg_out = 0; WRITE_ICS564_U16( board, USER_IO, reg_out); usleep( 10 ); */ switch( chip ){ case ICS_564_ATT_CHIP: shift=0; dir=0; //clock'in LSB first break; case ICS_564_SYNTH_CHIP: shift=3; dir=1; //clock'in MSB first break; } tx=tx<<8; // an extra nine'th bit for the rx/tx commutation adr=adr<<6; reg_out = 4; WRITE_ICS564_U16( board, USER_IO, adr + tx + ( reg_out << shift )); usleep( 10 ); reg_out = 5; WRITE_ICS564_U16( board, USER_IO, adr + tx + ( reg_out << shift )); usleep( 10 ); for ( i=0; i<w_size; i++ ){ word=orig_word>>(dir*(w_size-i-1)+(1-dir)*i); reg_out = ( 0 << 2 )+( ( word & 0x1 ) << 1 ) + 0; PR_DBG( 4, "%2i: reg_out is %x\n", i, reg_out ); WRITE_ICS564_U16( board, USER_IO, adr + tx + ( reg_out << shift )); usleep( 10 ); reg_out = ( 0 << 2 ) + ( ( word & 0x1 ) << 1 ) + 1; WRITE_ICS564_U16( board, USER_IO, adr + tx + ( reg_out << shift )); usleep( 10 ); } reg_out = 4; WRITE_ICS564_U16( board, USER_IO, adr + tx + ( reg_out << shift )); usleep( 10 ); reg_out = 4; WRITE_ICS564_U16( board, USER_IO, adr + tx + ( reg_out << shift )); usleep( 10 ); }u32 last_time, old_time, past_time;#define TIME_PAST old_time = last_time; last_time = gethrtime() / 1000; \ past_time = last_time - old_time#define DMA_PRELOAD 9#define TIME_SHOW ((DMA_PRELOAD + 10)*board->number_channels)void ics564_dma_next_block( struct ics_dev *board ){ int block_offset, ch, bc, ch_inv; bc = board->block_count; ch = bc % board->number_channels; // ch_inv = ( ch + 2 ) % 4; ch_inv = ch; block_offset = bc / board->number_channels; block_offset %= board->blocks_per_frame; if ( ( bc % 1000 ) < TIME_SHOW ){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -