?? rf_io.c
字號(hào):
/*************************************************************************** rf_io.c - IO-functions for the rf ------------------- begin : 2002 authors : Linus Gasser emails : linus.gasser@epfl.ch ***************************************************************************//*************************************************************************** Changes ------- date - name - description 02-10-01 - ineiti - create 02-12-11 - ineiti - changed the name from daq_io.c, adjusted daq to rf **************************************************************************//*************************************************************************** * * * 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. * * * ***************************************************************************//** * The hardware-interface for the rf-cards */#include "debugging.h"#include "channel_rf.h"#include "rf_io.h"#include "rf_dev.h"#include "memory.h"#define DBG_LVL 0void setup_regs( device_t *dev_rf ) { unsigned int baseptr, ioptr; unsigned int rx_pci_address; unsigned int tx_pci_address; unsigned int mbox_pci_address; baseptr = dev_rf->data_base; ioptr = dev_rf->addr[1]; PR_DBG( 2, "baseptr: %x, ioptr: %x\n", baseptr, ioptr ); rx_pci_address = (unsigned int) virt_to_bus(dev_rf->rx_buffer); tx_pci_address = (unsigned int) virt_to_bus(dev_rf->tx_buffer); mbox_pci_address = (unsigned int) virt_to_bus(dev_rf->mboxes); PR_DBG( 2, "rx: %p-%p\n", dev_rf->rx_buffer, dev_rf->rx_buffer + dev_rf->blocks_in_frame * DAQ_DMA_BLOCK_SIZE_BYTES ); PR_DBG( 2, "tx: %p-%p\n", dev_rf->tx_buffer, dev_rf->tx_buffer + dev_rf->blocks_in_frame * DAQ_DMA_BLOCK_SIZE_BYTES ); // Program DMA0 mode reg 80h // 0000000000000000000 0 0 1 0 1 1 0 0000 11 = 0x583 // width 32 bits // 0 wait state // BTERM enable (burst forever) // Burst enable outl(0x00000183,ioptr + DMA0_MODE_REG); // Program DMA0 descriptor pointer register 90h // 0000000000000000000000000000 1 0 0 0 = 0x8 // Direction: Local to PCI outl(0x00000008,ioptr + DMA0_DESC_REG); // Program DMA LOCAL DMA address // Top of ADC Buffer outl(ADC_BUFFER,ioptr + DMA0_LOCAL_START); // Program DMA Block Size outl(ADC_LOCAL_SIZE, ioptr + DMA0_BYTE_COUNT); // Program DMA FIFO Thresholds (to be tuned) outl(0x00000770, ioptr + DMA_THRESHOLD); // Program Direct Master Range register // Needed for write to mailbox outl(DMA_RANGE, ioptr + DIR_MAST_RANGE); // Program Local Base Address for Direct Master write // Needed for write to mailbox outl(MBOX_LOCAL_MAP, ioptr + DIR_MAST_ADD); // Program Remap for Direct Master write // Map 1 Mbyte area on local bus + enable Direct Master Memory Access outl(((unsigned int) 0x00000001) | (mbox_pci_address & 0xFFF00000), ioptr + DIR_MAST_REMAP); // Program DMA1 mode reg 94h // 0000000000000000000 0 0 0 0 1 1 0 0000 11 = 0x183 // width 32 bits // 0 wait states // BTERM enable (burst forever) // Burst enable outl(0x00000183,ioptr+DMA1_MODE_REG); // Program DMA1 descriptor pointer register A4h // 0000000000000000000000000000 0 0 0 0 = 0x0 // Direction: Local to PCI outl(0x00000000,ioptr+DMA1_DESC_REG); // Program DMA LOCAL DMA address // Top of ADC Buffer outl(DAC_BUFFER,ioptr + DMA1_LOCAL_START); // Program DMA Block Size outl(DAC_LOCAL_SIZE, ioptr + DMA1_BYTE_COUNT); // Program Direct Master Range register // Needed for write to mailbox outl(DMA_RANGE, ioptr + DIR_MAST_RANGE); // Program Local Base Address for Direct Master write // Needed for write to mailbox outl(MBOX_LOCAL_MAP, ioptr + DIR_MAST_ADD); // Program Remap for Direct Master write // Map 1 Mbyte area on local bus + enable Direct Master Memory Access outl(((unsigned int) 0x00000001) | (mbox_pci_address & 0xFFF00000), ioptr + DIR_MAST_REMAP); // Write PCI address of top of DMA buffer to FPGA rf_writel(rx_pci_address, baseptr + PCI_BASE_REG_RD); // Write PCI address of bottom of DMA buffer rf_writel(rx_pci_address + dev_rf->blocks_in_frame * DAQ_DMA_BLOCK_SIZE_BYTES, baseptr + PCI_LIMIT_REG_RD); // Write Local Bus address of PCI Mailbox rf_writel(MBOX_LOCAL_MAP | (mbox_pci_address & 0x000FFFFF), baseptr+PCI_MBOX_REG_RD); // Write PCI address of top of DMA buffer to FPGA rf_writel(tx_pci_address , baseptr + PCI_BASE_REG_WR); //0 // Write PCI address of bottom of DMA buffer rf_writel(tx_pci_address + dev_rf->blocks_in_frame * DAQ_DMA_BLOCK_SIZE_BYTES, baseptr + PCI_LIMIT_REG_WR); // Write Local Bus address of PCI Mailbox rf_writel(MBOX_LOCAL_MAP | ((mbox_pci_address + 4)& 0x000FFFFF), baseptr + PCI_MBOX_REG_WR);}/** * @short Sets the gains * * This is a special function that is only available with the rf-antenna. * It should be packed in the general interface, but for the moment (dec02) * no certainity exists on how to set a certain gain in dbm. * * There are four gain-controllers on the RF-board. All four can * be set at the same time through this function. * * @param nbr_daq The index of the DAQ [0..MAX_ANTENNAS - 1] * @param tx_pa The transmission power-amplifier gain * @param tx_med The transmission DAC-gain * @param tx_if The transmission intermediate-frequency gain * @param rx_if The reception intermediate-frequency gain * @return 0 for success or -1 for error */int swr_rf_set_gains( device_t *dev_rf, int tx_pa, int tx_med, int tx_if, int rx_if ) { dev_rf->tx_pa_gain = tx_pa; dev_rf->tx_med_gain = tx_med; dev_rf->tx_if_gain = tx_if; dev_rf->rx_if_gain = rx_if; writegain( dev_rf, TX_PA_GAIN, dev_rf->tx_pa_gain ); writegain( dev_rf, TX_MED_GAIN, dev_rf->tx_med_gain ); writegain( dev_rf, TX_IF_GAIN, dev_rf->tx_if_gain ); writegain( dev_rf, RX_IF_GAIN, dev_rf->rx_if_gain ); PR_DBG( 3, "Wrote gains... if:%i\n", dev_rf->rx_if_gain ); return 0;}/** * @short Reads the gains * * @return 0 for success or -1 for error */int swr_rf_get_gains( device_t *dev_rf, int *tx_pa, int *tx_med, int *tx_if, int *rx_if ) { *tx_pa = dev_rf->tx_pa_gain; *tx_med = dev_rf->tx_med_gain; *tx_if = dev_rf->tx_if_gain; *rx_if = dev_rf->rx_if_gain; return 0;}// sets particular qdac channel to some levelvoid writegain ( device_t *dev_rf, int channel, int level ) { unsigned int baseptr=dev_rf->data_base; unsigned int qdacword, intlevel; const unsigned long // system control wakeup, offset coding // Vdd/2 for A, B, C, D : qdacctrl[5] = { 0x0060, 0x4010, 0x4410, 0x4810, 0x4C10 }, qdacdata[4] = {0x2000, 0x2400, 0x2800, 0x2C00}; intlevel = min(0x3ff,level); qdacword = qdacdata[channel-1] | intlevel; // write the control and data word rf_writel(qdacctrl[0], baseptr + ODAC); rtl_delay(10000); rf_writel(qdacctrl[channel], baseptr + ODAC); rtl_delay(10000); rf_writel(qdacword, baseptr + ODAC); rtl_delay(10000);}#define LDAC (1<<13) // Load DAC A#define PDB (1<<12) // Power down DAC Bvoid write_sdac( device_t *dev_rf, int level ) { unsigned int baseptr=dev_rf->data_base; unsigned int qdacword, intlevel; intlevel = min(0xff,level); qdacword = LDAC | PDB | intlevel; // write the control and data word rf_writel(qdacword, baseptr + SDAC);}void setmode( device_t *dev_rf, unsigned int mode ) { unsigned int baseptr=dev_rf->data_base; unsigned int oldval,newval; PR_DBG( 4, "Setting mode to %d\n",mode); mode&=0xf; oldval = rf_readl(baseptr + ODAC) & 0xff; newval = (mode<<12)|oldval; rf_writel(newval, baseptr + ODAC);}#define Fosc 16e6 // Reference frequency#define Xmax 32767#define RF_CP_WORD ((1<<1) | 1) // Charge Pump = 200 uA, +ve VCO polarity#define V2_EN 0 // Voltage doubled#define DLL_MODE 1 // Fast#define RF_CNTL_WORD 1 // Normal Operation, Powered up, 32/33void write_lo( device_t *dev_rf, unsigned int freq ) { unsigned int baseptr=dev_rf->data_base; int PBA,F,R,RF_N,RF_R; DEBDIV( freq, "rf_printf::write_lo div0\n" ); R = (int)(((double)Xmax * Fosc)/ (double)freq); PBA = (int)(((double)freq * R) / (double)Fosc); F = ((int)(((((double)freq * R )*16))/Fosc))%16; RF_R = (R<<2) | 2 | (RF_CP_WORD<<17) | (V2_EN<<22) | (DLL_MODE<<23); RF_N = (RF_CNTL_WORD << 21) | (PBA<<6) | (F<<2) | 3; rf_writel((1<<23) | (1<<22),baseptr + FSYN); // OSC = 1, Frac = 16 PR_DBG( 4, "IF_R = %x\n",(1<<23) | (1<<22)); rtl_delay((long)3000); rf_writel(RF_R,baseptr + FSYN); PR_DBG( 4, "RF_R = %x\n",RF_R); rtl_delay((long)3000); rf_writel(RF_N,baseptr + FSYN); PR_DBG( 4, "RF_N = %x\n",RF_N); rtl_delay((long) 3000);}int dump_config( device_t *dev_rf, unsigned char bus, unsigned char func ) { int res; int i; unsigned int mask; unsigned char b; unsigned short w; unsigned int dw; struct pci_dev *pdev; unsigned int addr[] = { PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2, PCI_BASE_ADDRESS_3, PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5 }; res = pcibios_read_config_word(bus, func, PCI_VENDOR_ID, &w); PR_DBG( 4, "vendor: 0x%04X\n", (int)w); res = pcibios_read_config_word(bus, func, PCI_DEVICE_ID, &w); PR_DBG( 4, "device: 0x%04X\n", (int)w); res = pcibios_read_config_word(bus, func, PCI_COMMAND, &w); PR_DBG( 4, "command: 0x%04X\n", (int)w); res = pcibios_read_config_word(bus, func, PCI_STATUS, &w); PR_DBG( 4, "status: 0x%04X\n", (int)w); res = pcibios_read_config_dword(bus, func, PCI_CLASS_REVISION, &dw); PR_DBG( 4, "Class & revision: 0x%08X\n", (int)dw); res = pcibios_read_config_byte(bus, func, PCI_REVISION_ID, &b); PR_DBG( 4, "revision: %d\n", (int)b); res = pcibios_read_config_byte(bus, func, PCI_CACHE_LINE_SIZE, &b); PR_DBG( 4, "cache line size: %d\n", (int)b); res = pcibios_read_config_byte(bus, func, PCI_LATENCY_TIMER, &b); PR_DBG( 4, "latency timer: %d\n", (int)b); res = pcibios_read_config_byte(bus, func, PCI_HEADER_TYPE, &b); PR_DBG( 4, "header type: %d\n", (int)b); res = pcibios_read_config_byte(bus, func, PCI_BIST, &b); PR_DBG( 4, "burst ist: %d\n", (int)b); for(i = 0; i <= 5; ++i) { res = pcibios_read_config_dword(bus, func, addr[i], &dw); res = pcibios_write_config_dword(bus, func, addr[i], ~0); res = pcibios_read_config_dword(bus, func, addr[i], &mask); res = pcibios_write_config_dword(bus, func, addr[i], dw); if(dw != 0) { PR_DBG( 4, "----------------\n"); if(dw & PCI_BASE_ADDRESS_SPACE_IO) { PR_DBG( 4, "I/O\n"); dev_rf->addr[i] = dw & PCI_BASE_ADDRESS_IO_MASK; dw ^= PCI_BASE_ADDRESS_SPACE_IO; /* Clean the last bit */ mask ^= PCI_BASE_ADDRESS_SPACE_IO; /* Clean the last bit */ } else { PR_DBG( 4, "memory\n"); dev_rf->addr[i] = dw & PCI_BASE_ADDRESS_MEM_MASK; switch(dw & PCI_BASE_ADDRESS_MEM_TYPE_MASK) { case PCI_BASE_ADDRESS_MEM_TYPE_32: PR_DBG( 4, "32 bits address\n"); break; case PCI_BASE_ADDRESS_MEM_TYPE_1M: PR_DBG( 4, "below 1M address\n"); break; case PCI_BASE_ADDRESS_MEM_TYPE_64: PR_DBG( 4, "64 bits address\n"); break; default: PR_DBG( 4, "ERROR: unkown address type\n"); break; } if(dw & PCI_BASE_ADDRESS_MEM_PREFETCH) { PR_DBG( 4, "prefetchable\n"); } else { PR_DBG( 4, "not prefetchable\n"); } } PR_DBG( 4, "Base address %d: 0x%08x\n", i, dev_rf->addr[i]); PR_DBG( 4, "size: 0x%08X\n", (unsigned int)~mask + 1); } } PR_DBG( 4, "----------------\n"); pdev = pci_find_slot(bus, func); dev_rf->irq = pdev->irq; return 0;}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -